diff --git a/.changelog/18329.txt b/.changelog/18329.txt new file mode 100644 index 000000000000..ab3671de86bf --- /dev/null +++ b/.changelog/18329.txt @@ -0,0 +1,4 @@ +```release-note:improvement +cli: Adds cli support for checking TCP connection for ports. If -ports flag is not given, it will check for +default ports of consul listed here - https://developer.hashicorp.com/consul/docs/install/ports +``` \ No newline at end of file diff --git a/.changelog/19499.txt b/.changelog/19499.txt new file mode 100644 index 000000000000..83849637d413 --- /dev/null +++ b/.changelog/19499.txt @@ -0,0 +1,3 @@ +```release-note:feature +acl: add policy bindtype to binding rules. +``` \ No newline at end of file diff --git a/.changelog/19586.txt b/.changelog/19586.txt new file mode 100644 index 000000000000..2c58b38b5578 --- /dev/null +++ b/.changelog/19586.txt @@ -0,0 +1,3 @@ +```release-note:bug +ui: fix being able to view peered services from non-default namnespaces +``` diff --git a/.changelog/19594.txt b/.changelog/19594.txt new file mode 100644 index 000000000000..9348b98bf504 --- /dev/null +++ b/.changelog/19594.txt @@ -0,0 +1,3 @@ +```release-note:improvement +ui: move nspace and partitions requests into their selector menus +``` diff --git a/.changelog/19647.txt b/.changelog/19647.txt new file mode 100644 index 000000000000..33b91ef01cbd --- /dev/null +++ b/.changelog/19647.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: Add `CaseInsensitive` flag to service-routers that allows paths and path prefixes to ignore URL upper and lower casing. +``` diff --git a/.changelog/19663.txt b/.changelog/19663.txt new file mode 100644 index 000000000000..d3b338dfdf25 --- /dev/null +++ b/.changelog/19663.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: Default `stats_flush_interval` to 60 seconds when using the Consul Telemetry Collector, unless custom stats sink are present or an explicit flush interval is configured. +``` \ No newline at end of file diff --git a/.changelog/19666.txt b/.changelog/19666.txt new file mode 100644 index 000000000000..c3880be4d10a --- /dev/null +++ b/.changelog/19666.txt @@ -0,0 +1,3 @@ +```release-note:improvement +api: Add support for listing ACL tokens by service name when using templated policies. +``` \ No newline at end of file diff --git a/.changelog/19679.txt b/.changelog/19679.txt new file mode 100644 index 000000000000..42f681be29d7 --- /dev/null +++ b/.changelog/19679.txt @@ -0,0 +1,3 @@ +```release-note:bug +CLI: fix a panic when deleting a non existing policy by name. +``` diff --git a/.changelog/19682.txt b/.changelog/19682.txt new file mode 100644 index 000000000000..cfcee3e9b1c0 --- /dev/null +++ b/.changelog/19682.txt @@ -0,0 +1,3 @@ +```release-note:improvement +cloud: push additional server TLS metadata to HCP +``` diff --git a/.changelog/19705.txt b/.changelog/19705.txt new file mode 100644 index 000000000000..7b9100d81616 --- /dev/null +++ b/.changelog/19705.txt @@ -0,0 +1,3 @@ +```release-note:security +Update `github.com/golang-jwt/jwt/v4` to v4.5.0 to address [PRISMA-2022-0270](https://github.com/golang-jwt/jwt/issues/258). +``` diff --git a/.changelog/19721.txt b/.changelog/19721.txt new file mode 100644 index 000000000000..5a6b4bbd377e --- /dev/null +++ b/.changelog/19721.txt @@ -0,0 +1,6 @@ +```release-note:improvement +metrics: modify consul.client.rpc metric to exclude internal retries for consistency with consul.client.rpc.exceeded and consul.client.rpc.failed +``` +```release-note:improvement +metrics: increment consul.client.rpc.failed if RPC fails because no servers are accessible +``` diff --git a/.changelog/19728.txt b/.changelog/19728.txt new file mode 100644 index 000000000000..53c61bc5e0e8 --- /dev/null +++ b/.changelog/19728.txt @@ -0,0 +1,3 @@ +```release-note:improvement +acl: add api-gateway templated policy +``` \ No newline at end of file diff --git a/.changelog/19735.txt b/.changelog/19735.txt new file mode 100644 index 000000000000..b7a712ced6e9 --- /dev/null +++ b/.changelog/19735.txt @@ -0,0 +1,3 @@ +```release-note:improvement +acl: add templated policy descriptions +``` \ No newline at end of file diff --git a/.changelog/19795.txt b/.changelog/19795.txt new file mode 100644 index 000000000000..cb35a077b313 --- /dev/null +++ b/.changelog/19795.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +wan-federation: use a hash to diff config entries when replicating in the secondary DC to avoid unnecessary writes.. +``` diff --git a/.changelog/19821.txt b/.changelog/19821.txt new file mode 100644 index 000000000000..ee88046faa06 --- /dev/null +++ b/.changelog/19821.txt @@ -0,0 +1,3 @@ +```release-note:feature +cli: Adds new subcommand `peering exported-services` to list services exported to a peer . Refer to the [CLI docs](https://developer.hashicorp.com/consul/commands/peering) for more information. +``` diff --git a/.changelog/19827.txt b/.changelog/19827.txt new file mode 100644 index 000000000000..6a3d9a7ec827 --- /dev/null +++ b/.changelog/19827.txt @@ -0,0 +1,3 @@ +```release-note:feature +acl: Adds nomad client templated policy +``` diff --git a/.changelog/19829.txt b/.changelog/19829.txt new file mode 100644 index 000000000000..6c8c924b54c9 --- /dev/null +++ b/.changelog/19829.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +mesh: parse the proxy-defaults protocol when write the config-entry to avoid parsing it when compiling the discovery chain. +``` diff --git a/.changelog/19840.txt b/.changelog/19840.txt new file mode 100644 index 000000000000..f63948096e60 --- /dev/null +++ b/.changelog/19840.txt @@ -0,0 +1,7 @@ +```release-note:security +Upgrade to use Go 1.20.12. This resolves CVEs +[CVE-2023-45283](https://nvd.nist.gov/vuln/detail/CVE-2023-45283): (`path/filepath`) recognize \??\ as a Root Local Device path prefix (Windows) +[CVE-2023-45284](https://nvd.nist.gov/vuln/detail/CVE-2023-45285): recognize device names with trailing spaces and superscripts (Windows) +[CVE-2023-39326](https://nvd.nist.gov/vuln/detail/CVE-2023-39326): (`net/http`) limit chunked data overhead +[CVE-2023-45285](https://nvd.nist.gov/vuln/detail/CVE-2023-45285): (`cmd/go`) go get may unexpectedly fallback to insecure git +``` \ No newline at end of file diff --git a/.changelog/19860.txt b/.changelog/19860.txt new file mode 100644 index 000000000000..e4edb69d8b75 --- /dev/null +++ b/.changelog/19860.txt @@ -0,0 +1,3 @@ +```release-note:bug +connect: Solves an issue where two upstream services with the same name in different namespaces were not getting routed to correctly by API Gateways. +``` diff --git a/.changelog/19866.txt b/.changelog/19866.txt new file mode 100644 index 000000000000..b1fd94f8cb2c --- /dev/null +++ b/.changelog/19866.txt @@ -0,0 +1,3 @@ +```release-note:bug +xds: ensure child resources are re-sent to Envoy when the parent is updated even if the child already has pending updates. +``` diff --git a/.changelog/19871.txt b/.changelog/19871.txt new file mode 100644 index 000000000000..f05f7aa51e6b --- /dev/null +++ b/.changelog/19871.txt @@ -0,0 +1,3 @@ +```release-note:bug +xds: Add configurable `xds_fetch_timeout_ms` option to proxy registrations that allows users to prevent endpoints from dropping when they have proxies with a large number of upstreams. +``` diff --git a/.changelog/19879.txt b/.changelog/19879.txt new file mode 100644 index 000000000000..12e7e2d75f8f --- /dev/null +++ b/.changelog/19879.txt @@ -0,0 +1,3 @@ +```release-note:security +mesh: update supported envoy version 1.28.0 in addition to 1.25.11, 1.26.6, 1.27.2, 1.28.0 to address [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) +``` \ No newline at end of file diff --git a/.changelog/19881.txt b/.changelog/19881.txt new file mode 100644 index 000000000000..0164661749ae --- /dev/null +++ b/.changelog/19881.txt @@ -0,0 +1,3 @@ +```release-note:bug +xds: Make TCP external service registered with terminating gateway reachable from peered cluster +``` diff --git a/.changelog/19907.txt b/.changelog/19907.txt new file mode 100644 index 000000000000..905794114fbf --- /dev/null +++ b/.changelog/19907.txt @@ -0,0 +1,3 @@ +```release-note:bug +ui: stop manually reconciling services if peering is enabled +``` diff --git a/.changelog/19912.txt b/.changelog/19912.txt new file mode 100644 index 000000000000..5ce329dab08a --- /dev/null +++ b/.changelog/19912.txt @@ -0,0 +1,3 @@ +```release-note:bug +ui: update token list on Role details page to show only linked tokens +``` \ No newline at end of file diff --git a/.changelog/19940.txt b/.changelog/19940.txt new file mode 100644 index 000000000000..b83ba176e6dc --- /dev/null +++ b/.changelog/19940.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: Replace usage of deprecated Envoy fields `envoy.config.cluster.v3.Cluster.http2_protocol_options` and `envoy.config.bootstrap.v3.Admin.access_log_path`. +``` \ No newline at end of file diff --git a/.changelog/19943.txt b/.changelog/19943.txt new file mode 100644 index 000000000000..fff1b52d6c10 --- /dev/null +++ b/.changelog/19943.txt @@ -0,0 +1,3 @@ +```release-note:deprecation +cli: Deprecate the `-admin-access-log-path` flag from `consul connect envoy` command in favor of: `-admin-access-log-config`. +``` diff --git a/.changelog/19954.txt b/.changelog/19954.txt new file mode 100644 index 000000000000..a465088a827e --- /dev/null +++ b/.changelog/19954.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: Remove usage of deprecated Envoy field `match_subject_alt_names` in favor of `match_typed_subject_alt_names`. +``` \ No newline at end of file diff --git a/.changelog/19992.txt b/.changelog/19992.txt new file mode 100644 index 000000000000..58c26440f74e --- /dev/null +++ b/.changelog/19992.txt @@ -0,0 +1,3 @@ +```release-note:breaking-change +config-entries: Allow disabling request and idle timeouts with negative values in service router and service resolver config entries. +``` diff --git a/.changelog/20010.txt b/.changelog/20010.txt new file mode 100644 index 000000000000..1ae89d88b70b --- /dev/null +++ b/.changelog/20010.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: Replace usage of deprecated Envoy field `envoy.config.cluster.v3.Cluster.http_protocol_options`. +``` \ No newline at end of file diff --git a/.changelog/20011.txt b/.changelog/20011.txt new file mode 100644 index 000000000000..12a70a84f2f7 --- /dev/null +++ b/.changelog/20011.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: Replace usage of deprecated Envoy field `envoy.config.router.v3.WeightedCluster.total_weight`. +``` \ No newline at end of file diff --git a/.changelog/20012.txt b/.changelog/20012.txt new file mode 100644 index 000000000000..cf1b26b09217 --- /dev/null +++ b/.changelog/20012.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: Replace usage of deprecated Envoy field `envoy.extensions.filters.http.lua.v3.Lua.inline_code`. +``` diff --git a/.changelog/20013.txt b/.changelog/20013.txt new file mode 100644 index 000000000000..d9c8349f97fe --- /dev/null +++ b/.changelog/20013.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: Replace usage of deprecated Envoy fields `envoy.config.route.v3.HeaderMatcher.safe_regex_match` and `envoy.type.matcher.v3.RegexMatcher.google_re2`. +``` \ No newline at end of file diff --git a/.changelog/20014.txt b/.changelog/20014.txt new file mode 100644 index 000000000000..032356f98968 --- /dev/null +++ b/.changelog/20014.txt @@ -0,0 +1,3 @@ +```release-note:security +Upgrade OpenShift container images to use `ubi9-minimal:9.3` as the base image. +``` diff --git a/.changelog/20015.txt b/.changelog/20015.txt new file mode 100644 index 000000000000..7ca2b7b04363 --- /dev/null +++ b/.changelog/20015.txt @@ -0,0 +1,3 @@ +```release-note:improvement +api: add a new api(/v1/exported-services) to list all the exported service and their consumers. +``` \ No newline at end of file diff --git a/.changelog/20023.txt b/.changelog/20023.txt new file mode 100644 index 000000000000..812573bf97e3 --- /dev/null +++ b/.changelog/20023.txt @@ -0,0 +1,3 @@ +```release-note:security +Update `golang.org/x/crypto` to v0.17.0 to address [CVE-2023-48795](https://nvd.nist.gov/vuln/detail/CVE-2023-48795). +``` diff --git a/.changelog/20062.txt b/.changelog/20062.txt new file mode 100644 index 000000000000..81568f397f5d --- /dev/null +++ b/.changelog/20062.txt @@ -0,0 +1,3 @@ +```release-note:improvement +Upgrade to use Go 1.21.6. +``` diff --git a/.changelog/20078.txt b/.changelog/20078.txt new file mode 100644 index 000000000000..00fd03f48602 --- /dev/null +++ b/.changelog/20078.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: Replace usage of deprecated Envoy field `envoy.config.core.v3.HeaderValueOption.append`. +``` diff --git a/.changelog/20111.txt b/.changelog/20111.txt new file mode 100644 index 000000000000..ae1c31ac5b99 --- /dev/null +++ b/.changelog/20111.txt @@ -0,0 +1,3 @@ +```release-note:bug +UI: fix autofocus on search box when page refreshes on typing in it due to url change. +``` diff --git a/.changelog/20112.txt b/.changelog/20112.txt new file mode 100644 index 000000000000..99a2a2ecd02b --- /dev/null +++ b/.changelog/20112.txt @@ -0,0 +1,3 @@ +```release-note:security +Update RSA key generation to use a key size of at least 2048 bits. +``` diff --git a/.changelog/20168.txt b/.changelog/20168.txt new file mode 100644 index 000000000000..354991e324e0 --- /dev/null +++ b/.changelog/20168.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +ProxyCfg: avoid setting a watch on `Internal.ServiceDump` when mesh gateway is not used. +``` + +```release-note:enhancement +ProxyCfg: only return the nodes list when querying the `Internal.ServiceDump` watch from proxycfg +``` diff --git a/.changelog/20220.txt b/.changelog/20220.txt new file mode 100644 index 000000000000..aca1a8096195 --- /dev/null +++ b/.changelog/20220.txt @@ -0,0 +1,3 @@ +```release-note:improvement +cloud: unconditionally add Access-Control-Expose-Headers HTTP header +``` diff --git a/.changelog/20299.txt b/.changelog/20299.txt new file mode 100644 index 000000000000..b1c1538e674b --- /dev/null +++ b/.changelog/20299.txt @@ -0,0 +1,3 @@ +```release-note:feature +v2: prevent use of the v2 experiments in secondary datacenters for now +``` diff --git a/.changelog/20308.txt b/.changelog/20308.txt new file mode 100644 index 000000000000..3dade6fb0dbd --- /dev/null +++ b/.changelog/20308.txt @@ -0,0 +1,3 @@ +```release-note:improvement +docs: add Link API documentation +``` diff --git a/.changelog/20312.txt b/.changelog/20312.txt new file mode 100644 index 000000000000..f42c4f17becd --- /dev/null +++ b/.changelog/20312.txt @@ -0,0 +1,6 @@ +```release-note:feature +cloud: Adds new API/CLI to initiate and manage linking a Consul cluster to HCP Consul Central +``` +```release-note:breaking-change +telemetry: Adds fix to always use the value of `telemetry.disable_hostname` when determining whether to prefix gauge-type metrics with the hostname of the Consul agent. Previously, if only the default metric sink was enabled, this configuration was ignored and always treated as `true`, even though its default value is `false`. +``` \ No newline at end of file diff --git a/.changelog/20331.txt b/.changelog/20331.txt new file mode 100644 index 000000000000..245e0eda693a --- /dev/null +++ b/.changelog/20331.txt @@ -0,0 +1,3 @@ +```release-note:feature +cli: Adds new command `exported-services` to list all services exported and their consumers. Refer to the [CLI docs](https://developer.hashicorp.com/consul/commands/exported-services) for more information. +``` diff --git a/.changelog/20345.txt b/.changelog/20345.txt new file mode 100644 index 000000000000..b2fcc5271f0f --- /dev/null +++ b/.changelog/20345.txt @@ -0,0 +1,3 @@ +```release-note:bug + audit-logs: **(Enterprise Only)** Fixes non ASCII characters in audit logs because of gzip. +``` diff --git a/.changelog/20352.txt b/.changelog/20352.txt new file mode 100644 index 000000000000..d9faed27af67 --- /dev/null +++ b/.changelog/20352.txt @@ -0,0 +1,3 @@ +```release-note:bug +logging: add /api prefix to v2 resource endpoint logs +``` \ No newline at end of file diff --git a/.changelog/20353.txt b/.changelog/20353.txt new file mode 100644 index 000000000000..d1d8f4ebc207 --- /dev/null +++ b/.changelog/20353.txt @@ -0,0 +1,3 @@ +```release-note:feature +ui: adds V2CatalogEnabled to config that is passed to the ui +``` diff --git a/.changelog/20359.txt b/.changelog/20359.txt new file mode 100644 index 000000000000..c010b32ef579 --- /dev/null +++ b/.changelog/20359.txt @@ -0,0 +1,3 @@ +```release-note:feature +ui: Adds a redirect and warning message around unavailable UI with V2 enabled +``` diff --git a/.changelog/20406.txt b/.changelog/20406.txt new file mode 100644 index 000000000000..168456a599d6 --- /dev/null +++ b/.changelog/20406.txt @@ -0,0 +1,3 @@ +```release-note:bug +mesh: Fix bug where envoy extensions could not be configured with "permissive" mTLS mode. Note that envoy extensions currently do not apply to non-mTLS traffic in permissive mode. +``` diff --git a/.changelog/20417.txt b/.changelog/20417.txt new file mode 100644 index 000000000000..c55353348aa9 --- /dev/null +++ b/.changelog/20417.txt @@ -0,0 +1,3 @@ +```release-note:bug +connect: Fix regression with SAN matching on terminating gateways [GH-20360](https://github.com/hashicorp/consul/issues/20360) +``` diff --git a/.changelog/20439.txt b/.changelog/20439.txt new file mode 100644 index 000000000000..1dd027d3d10b --- /dev/null +++ b/.changelog/20439.txt @@ -0,0 +1,3 @@ +```release-note:bug +docs: Consul DNS Forwarding configuration for OpenShift update for [Resolve Consul DNS Requests in Kubernetes](https://developer.hashicorp.com/consul/docs/k8s/dns) +``` diff --git a/.changelog/20481.txt b/.changelog/20481.txt new file mode 100644 index 000000000000..5c2772648ca4 --- /dev/null +++ b/.changelog/20481.txt @@ -0,0 +1,3 @@ +```release-note:bug +connect: Fix issue where re-persisting existing proxy-defaults using `http` protocol fails with a protocol-mismatch error. +``` diff --git a/.changelog/20511.txt b/.changelog/20511.txt new file mode 100644 index 000000000000..ba368bc07b42 --- /dev/null +++ b/.changelog/20511.txt @@ -0,0 +1,3 @@ +```release-note:bug +connect: Remove code coupling where the xDS capacity controller could negatively affect raft autopilot performance. +``` diff --git a/.changelog/20514.txt b/.changelog/20514.txt new file mode 100644 index 000000000000..45eedfd82c2a --- /dev/null +++ b/.changelog/20514.txt @@ -0,0 +1,3 @@ +```release-note:bug +hcp: fix error logs when failing to push metrics +``` diff --git a/.changelog/20544.txt b/.changelog/20544.txt new file mode 100644 index 000000000000..bfe3cbd6ff9d --- /dev/null +++ b/.changelog/20544.txt @@ -0,0 +1,3 @@ +```release-note:feature +agent: Introduces a new agent config default_intention_policy to decouple the default intention behavior from ACLs +``` diff --git a/.changelog/20545.txt b/.changelog/20545.txt new file mode 100644 index 000000000000..fc6d2802db16 --- /dev/null +++ b/.changelog/20545.txt @@ -0,0 +1,3 @@ +```release-note:improvement +Upgrade to use Go 1.21.7. +``` \ No newline at end of file diff --git a/.changelog/20589.txt b/.changelog/20589.txt new file mode 100644 index 000000000000..533dc4cc4c39 --- /dev/null +++ b/.changelog/20589.txt @@ -0,0 +1,3 @@ +```release-note:security +mesh: Update Envoy versions to 1.28.1, 1.27.3, and 1.26.7 to address [CVE-2024-23324](https://github.com/envoyproxy/envoy/security/advisories/GHSA-gq3v-vvhj-96j6), [CVE-2024-23325](https://github.com/envoyproxy/envoy/security/advisories/GHSA-5m7c-mrwr-pm26), [CVE-2024-23322](https://github.com/envoyproxy/envoy/security/advisories/GHSA-6p83-mfmh-qv38), [CVE-2024-23323](https://github.com/envoyproxy/envoy/security/advisories/GHSA-x278-4w4x-r7ch), [CVE-2024-23327](https://github.com/envoyproxy/envoy/security/advisories/GHSA-4h5x-x9vh-m29j), and [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) +``` diff --git a/.changelog/20642.txt b/.changelog/20642.txt new file mode 100644 index 000000000000..0f224654cbd8 --- /dev/null +++ b/.changelog/20642.txt @@ -0,0 +1,7 @@ +```release-note:bug +server: Ensure internal streams are properly terminated on snapshot restore. +``` + +```release-note:bug +server: Ensure controllers are automatically restarted on internal stream errors. +``` diff --git a/.changelog/20643.txt b/.changelog/20643.txt new file mode 100644 index 000000000000..5c16c8784d44 --- /dev/null +++ b/.changelog/20643.txt @@ -0,0 +1,7 @@ +```release-note:feature +dns: adds experimental support for a refactored DNS server that is v1 and v2 Catalog compatible. +Use `v2dns` in the `experiments` agent config to enable. +It will automatically be enabled when using the `resource-apis` (Catalog v2) experiment. +The new DNS implementation will be the default in Consul 1.19. +See the [Consul 1.18.x Release Notes](https://developer.hashicorp.com/consul/docs/release-notes/consul/v1_18_x) for deprecated DNS features. +``` diff --git a/.changelog/20669.txt b/.changelog/20669.txt new file mode 100644 index 000000000000..8202d5e304ca --- /dev/null +++ b/.changelog/20669.txt @@ -0,0 +1,3 @@ +```release-note:improvement +partitions: **(Enterprise only)** Allow disabling of Gossip per Partition +``` diff --git a/.changelog/20672.txt b/.changelog/20672.txt new file mode 100644 index 000000000000..e7c00817b9e9 --- /dev/null +++ b/.changelog/20672.txt @@ -0,0 +1,3 @@ +```release-note: improvement +xds: Improved the performance of xDS server side load balancing. Its slightly improved in Consul CE with drastic CPU usage reductions in Consul Enterprise. +``` diff --git a/.changelog/20674.txt b/.changelog/20674.txt new file mode 100644 index 000000000000..233391aa9b19 --- /dev/null +++ b/.changelog/20674.txt @@ -0,0 +1,7 @@ +```release-note:breaking-change +telemetry: State store usage metrics with a double `consul` element in the metric name have been removed. Please use the same metric without the second `consul` instead. As an example instead of `consul.consul.state.config_entries` use `consul.state.config_entries` +``` + +```release-note: improvement +telemetry: Improved the performance usage metrics emission by not outputting redundant metrics. +``` diff --git a/.changelog/20679.txt b/.changelog/20679.txt new file mode 100644 index 000000000000..0efb6b276336 --- /dev/null +++ b/.changelog/20679.txt @@ -0,0 +1,3 @@ +```release-note:bug +dns: SERVFAIL when resolving not found PTR records. +``` \ No newline at end of file diff --git a/.changelog/20715.txt b/.changelog/20715.txt new file mode 100644 index 000000000000..19938678aac9 --- /dev/null +++ b/.changelog/20715.txt @@ -0,0 +1,6 @@ +```release-note:feature +dns: queries now default to a refactored DNS server that is v1 and v2 Catalog compatible. +Use `v1dns` in the `experiments` agent config to disable. +The legacy server will be removed in a future release of Consul. +See the [Consul 1.19.x Release Notes](https://developer.hashicorp.com/consul/docs/release-notes/consul/v1_19_x) for removed DNS features. +``` diff --git a/.changelog/20801.txt b/.changelog/20801.txt new file mode 100644 index 000000000000..947e9f65a65c --- /dev/null +++ b/.changelog/20801.txt @@ -0,0 +1,3 @@ +```release-note:security +Update `google.golang.org/protobuf` to v1.33.0 to address [CVE-2024-24786](https://nvd.nist.gov/vuln/detail/CVE-2024-24786). +``` diff --git a/.changelog/20802.txt b/.changelog/20802.txt new file mode 100644 index 000000000000..16a8267b5ff6 --- /dev/null +++ b/.changelog/20802.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: Add ability to disable Auto Host Header Rewrite on Terminating Gateway at the service level +``` \ No newline at end of file diff --git a/.changelog/20812.txt b/.changelog/20812.txt new file mode 100644 index 000000000000..6e4fb371b8c4 --- /dev/null +++ b/.changelog/20812.txt @@ -0,0 +1,14 @@ +```release-note:security +Upgrade to use Go `1.21.8`. This resolves CVEs +[CVE-2024-24783](https://nvd.nist.gov/vuln/detail/CVE-2024-24783) (`crypto/x509`). +[CVE-2023-45290](https://nvd.nist.gov/vuln/detail/CVE-2023-45290) (`net/http`). +[CVE-2023-45289](https://nvd.nist.gov/vuln/detail/CVE-2023-45289) (`net/http`, `net/http/cookiejar`). +[CVE-2024-24785](https://nvd.nist.gov/vuln/detail/CVE-2024-24785) (`html/template`). +[CVE-2024-24784](https://nvd.nist.gov/vuln/detail/CVE-2024-24784) (`net/mail`). +``` + +```release-note:security +Update the Consul Build Go base image to `alpine3.19`. This resolves CVEs +[CVE-2023-52425](https://nvd.nist.gov/vuln/detail/CVE-2023-52425) +[CVE-2023-52426⁠](https://nvd.nist.gov/vuln/detail/CVE-2023-52426) +``` diff --git a/.changelog/20824.txt b/.changelog/20824.txt new file mode 100644 index 000000000000..c067616dbec7 --- /dev/null +++ b/.changelog/20824.txt @@ -0,0 +1,3 @@ +```release-note:improvement +snapshot: Add `consul snapshot decode` CLI command to output a JSON object stream of all the snapshots data. +``` \ No newline at end of file diff --git a/.changelog/20866.txt b/.changelog/20866.txt new file mode 100644 index 000000000000..20c41f02bc0f --- /dev/null +++ b/.changelog/20866.txt @@ -0,0 +1,7 @@ +```release-note:improvement +api: Randomize the returned server list for the WatchServers gRPC endpoint. +``` + +```release-note:bug +connect: Fix potential goroutine leak in xDS stream handling. +``` diff --git a/.changelog/20867.txt b/.changelog/20867.txt new file mode 100644 index 000000000000..3a39126c8a04 --- /dev/null +++ b/.changelog/20867.txt @@ -0,0 +1,3 @@ +```release-note:bug +connect: Fix xDS deadlock that could result in proxies being unable to start. +``` diff --git a/.changelog/20868.txt b/.changelog/20868.txt new file mode 100644 index 000000000000..172cd12f243f --- /dev/null +++ b/.changelog/20868.txt @@ -0,0 +1,3 @@ +```release-note:bug +connect: Fix issue where Consul-dataplane xDS sessions would not utilize the streaming backend for wan-federated queries. +``` diff --git a/.changelog/20873.txt b/.changelog/20873.txt new file mode 100644 index 000000000000..31067e28c8b3 --- /dev/null +++ b/.changelog/20873.txt @@ -0,0 +1,3 @@ +```release-note:feature +gateways: api-gateway can leverage listener TLS certificates available on the gateway's local filesystem by specifying the public certificate and private key path in the new file-system-certificate configuration entry +``` diff --git a/.changelog/20876.txt b/.changelog/20876.txt new file mode 100644 index 000000000000..70a2ad468e44 --- /dev/null +++ b/.changelog/20876.txt @@ -0,0 +1,3 @@ +```release-note:bug +streaming: Handle ACL errors consistently when blocking query timeout is reached. +``` diff --git a/.changelog/20897.txt b/.changelog/20897.txt new file mode 100644 index 000000000000..f685f2240028 --- /dev/null +++ b/.changelog/20897.txt @@ -0,0 +1,3 @@ +```release-note:security + Bump Dockerfile base image to `alpine:3.19`. + ``` diff --git a/.changelog/20899.txt b/.changelog/20899.txt new file mode 100644 index 000000000000..3823a7514b50 --- /dev/null +++ b/.changelog/20899.txt @@ -0,0 +1,4 @@ +```release-note:improvement +dns: DNS-over-grpc when using `consul-dataplane` now accepts partition, namespace, token as metadata to default those query parameters. +`consul-dataplane` v1.5+ will send this information automatically. +``` diff --git a/.changelog/20910.txt b/.changelog/20910.txt new file mode 100644 index 000000000000..2ec948ee6cb6 --- /dev/null +++ b/.changelog/20910.txt @@ -0,0 +1,4 @@ +```release-note:security +Update `vault/api` to v1.12.2 to address [CVE-2024-28180](https://nvd.nist.gov/vuln/detail/CVE-2024-28180) +(removes indirect dependency on impacted `go-jose.v2`) +``` diff --git a/.changelog/20926.txt b/.changelog/20926.txt new file mode 100644 index 000000000000..9778a1a71eb4 --- /dev/null +++ b/.changelog/20926.txt @@ -0,0 +1,3 @@ +```release-note:bug +error running consul server in 1.18.0: failed to configure SCADA provider user's home directory path: $HOME is not defined +``` \ No newline at end of file diff --git a/.changelog/20945.txt b/.changelog/20945.txt new file mode 100644 index 000000000000..a0a0602156fa --- /dev/null +++ b/.changelog/20945.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +gateways: service defaults configuration entries can now be used to set default upstream limits for mesh-gateways +``` \ No newline at end of file diff --git a/.changelog/20956.txt b/.changelog/20956.txt new file mode 100644 index 000000000000..b142c84e8299 --- /dev/null +++ b/.changelog/20956.txt @@ -0,0 +1,14 @@ +```release-note:security +Upgrade to use Go `1.21.9`. This resolves CVE +[CVE-2023-45288](https://nvd.nist.gov/vuln/detail/CVE-2023-45288) (`http2`). +``` + +```release-note:security +Upgrade to support Envoy `1.26.8, 1.27.4, and 1.28.2`. This resolves CVE +[CVE-2024-27919](https://nvd.nist.gov/vuln/detail/CVE-2024-27919) (`http2`). +``` + +```release-note:security +Upgrade to use golang.org/x/net `v0.24.0`. This resolves CVE +[CVE-2023-45288](https://nvd.nist.gov/vuln/detail/CVE-2023-45288) (`x/net`). +``` diff --git a/.changelog/20973.txt b/.changelog/20973.txt new file mode 100644 index 000000000000..3241c937924d --- /dev/null +++ b/.changelog/20973.txt @@ -0,0 +1,3 @@ +```release-note:improvement +Upgrade `github.com/envoyproxy/go-control-plane` to 0.12.0. +``` \ No newline at end of file diff --git a/.changelog/20977.txt b/.changelog/20977.txt new file mode 100644 index 000000000000..06cfb68c0fd3 --- /dev/null +++ b/.changelog/20977.txt @@ -0,0 +1,3 @@ +```release-note:bug +server: fix Ent snapshot restore on CE when CE downgrade is enabled +``` diff --git a/.changelog/21017.txt b/.changelog/21017.txt new file mode 100644 index 000000000000..0091047f7f36 --- /dev/null +++ b/.changelog/21017.txt @@ -0,0 +1,9 @@ +```release-note:security +Upgrade to support Envoy `1.27.5 and 1.28.3`. This resolves CVE +[CVE-2024-32475](https://nvd.nist.gov/vuln/detail/CVE-2024-32475) (`auto_sni`). +``` + +```release-note:security +Upgrade to support k8s.io/apimachinery `v0.18.7 or higher`. This resolves CVE +[CVE-2020-8559](https://nvd.nist.gov/vuln/detail/CVE-2020-8559). +``` diff --git a/.changelog/21074.txt b/.changelog/21074.txt new file mode 100644 index 000000000000..9b2bd21f42fb --- /dev/null +++ b/.changelog/21074.txt @@ -0,0 +1,5 @@ +```release-note:security +Upgrade Go to use 1.21.10. This addresses CVEs +[CVE-2024-24787](https://nvd.nist.gov/vuln/detail/CVE-2024-24787) and +[CVE-2024-24788](https://nvd.nist.gov/vuln/detail/CVE-2024-24788) +``` diff --git a/.changelog/21113.txt b/.changelog/21113.txt new file mode 100644 index 000000000000..e1e153f0acb1 --- /dev/null +++ b/.changelog/21113.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +upgrade go version to v1.22.3. +``` diff --git a/.changelog/21142.txt b/.changelog/21142.txt new file mode 100644 index 000000000000..6119fb26740b --- /dev/null +++ b/.changelog/21142.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +mesh: update supported envoy version 1.29.4 in addition to 1.28.3, 1.27.5, 1.26.8. +``` \ No newline at end of file diff --git a/.changelog/21230.txt b/.changelog/21230.txt new file mode 100644 index 000000000000..5a57333afa9d --- /dev/null +++ b/.changelog/21230.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +dns: new version was not supporting partition or namespace being set to 'default' in CE version. +``` \ No newline at end of file diff --git a/.changelog/21251.txt b/.changelog/21251.txt new file mode 100644 index 000000000000..ff4ef7cf2388 --- /dev/null +++ b/.changelog/21251.txt @@ -0,0 +1,3 @@ +```release-note:bug +core: Fix multiple incorrect type conversion for potential overflows +``` diff --git a/.changelog/21265.txt b/.changelog/21265.txt new file mode 100644 index 000000000000..fdf600e70c98 --- /dev/null +++ b/.changelog/21265.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +upgrade go version to v1.22.4. +``` diff --git a/.changelog/21277.txt b/.changelog/21277.txt new file mode 100644 index 000000000000..a14a5aab2042 --- /dev/null +++ b/.changelog/21277.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +mesh: update supported envoy version 1.29.5 in addition to 1.28.4, 1.27.6. +``` \ No newline at end of file diff --git a/.changelog/21339.txt b/.changelog/21339.txt new file mode 100644 index 000000000000..8e8379ada035 --- /dev/null +++ b/.changelog/21339.txt @@ -0,0 +1,3 @@ +```release-note:bug +core: Fix panic runtime error on AliasCheck +``` diff --git a/.changelog/21342.txt b/.changelog/21342.txt new file mode 100644 index 000000000000..d2850bc4fd30 --- /dev/null +++ b/.changelog/21342.txt @@ -0,0 +1,3 @@ +```release-note:security +agent: removed reflected cross-site scripting vulnerability +``` \ No newline at end of file diff --git a/.changelog/21361.txt b/.changelog/21361.txt new file mode 100644 index 000000000000..5cfa906bcd2f --- /dev/null +++ b/.changelog/21361.txt @@ -0,0 +1,8 @@ +```release-note:bug +dns: Fix a regression where DNS tags using the standard lookup syntax, `tag.name.service.consul`, were being disregarded. +``` + +```release-note:bug +dns: Fix a regression where DNS SRV questions were returning duplicate hostnames instead of encoded IPs. +This affected Nomad integrations with Consul. +``` \ No newline at end of file diff --git a/.changelog/21378.txt b/.changelog/21378.txt new file mode 100644 index 000000000000..c9fd8820dcb4 --- /dev/null +++ b/.changelog/21378.txt @@ -0,0 +1,3 @@ +```release-note:security +ui: Pin and namespace sub-module dependencies related to the Consul UI +``` diff --git a/.changelog/21381.txt b/.changelog/21381.txt new file mode 100644 index 000000000000..e69989f03292 --- /dev/null +++ b/.changelog/21381.txt @@ -0,0 +1,4 @@ +```release-note:bug +dns: Fixes a spam log message "Failed to parse TTL for prepared query..." +that was always being logged on each prepared query evaluation. +``` \ No newline at end of file diff --git a/.changelog/21382.txt b/.changelog/21382.txt new file mode 100644 index 000000000000..dc59445371a2 --- /dev/null +++ b/.changelog/21382.txt @@ -0,0 +1,3 @@ +```release-note:bug +terminating-gateway: **(Enterprise Only)** Fixed issue where enterprise metadata applied to linked services was the terminating-gateways enterprise metadata and not the linked services enterprise metadata. +``` diff --git a/.changelog/21384.txt b/.changelog/21384.txt new file mode 100644 index 000000000000..c5ba2347e535 --- /dev/null +++ b/.changelog/21384.txt @@ -0,0 +1,3 @@ +```release-note:security +Upgrade go-retryablehttp to address [CVE-2024-6104](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-6104) +``` \ No newline at end of file diff --git a/.changelog/21507.txt b/.changelog/21507.txt new file mode 100644 index 000000000000..e06736fdbce5 --- /dev/null +++ b/.changelog/21507.txt @@ -0,0 +1,3 @@ +```release-note:security +Upgrade go version to 1.22.5 to address [CVE-2024-24791](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-24791) +``` \ No newline at end of file diff --git a/.changelog/21519.txt b/.changelog/21519.txt new file mode 100644 index 000000000000..2913443b1c4d --- /dev/null +++ b/.changelog/21519.txt @@ -0,0 +1,3 @@ +```release-note:bug +txn: Fix a bug where mismatched Consul server versions could result in undetected data loss for when using newer Transaction verbs. +``` diff --git a/.changelog/21524.txt b/.changelog/21524.txt new file mode 100644 index 000000000000..5f064e5c946e --- /dev/null +++ b/.changelog/21524.txt @@ -0,0 +1,3 @@ +```release-note:security +Upgrade envoy module dependencies to version 1.27.7, 1.28.5 and 1.29.7 or higher to resolve [CVE-2024-39305](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-39305) +``` diff --git a/.changelog/21587.txt b/.changelog/21587.txt new file mode 100644 index 000000000000..f83db38c9500 --- /dev/null +++ b/.changelog/21587.txt @@ -0,0 +1,3 @@ +```release-note:improvement +Use Envoy's default for a route's validate_clusters option, which is false. This fixes a case where non-existent clusters could cause a route to no longer route to any of its backends, including existing ones. +``` diff --git a/.changelog/21588.txt b/.changelog/21588.txt new file mode 100644 index 000000000000..073901f88bd3 --- /dev/null +++ b/.changelog/21588.txt @@ -0,0 +1,3 @@ +```release-note:security +ui: Upgrade modules with d3-color as a dependency to address denial of service issue in d3-color < 3.1.0 +``` \ No newline at end of file diff --git a/.changelog/21592.txt b/.changelog/21592.txt new file mode 100644 index 000000000000..a8a69f0d9b94 --- /dev/null +++ b/.changelog/21592.txt @@ -0,0 +1,3 @@ +```release-note:feature +server: remove v2 tenancy, catalog, and mesh experiments +``` diff --git a/.changelog/21604.txt b/.changelog/21604.txt new file mode 100644 index 000000000000..f5441403434b --- /dev/null +++ b/.changelog/21604.txt @@ -0,0 +1,3 @@ +```release-note:bug +api-gateway: **(Enterprise only)** ensure clusters are properly created for JWT providers with a remote URI for the JWKS endpoint +``` diff --git a/.changelog/21616.txt b/.changelog/21616.txt new file mode 100644 index 000000000000..f26b47c711d8 --- /dev/null +++ b/.changelog/21616.txt @@ -0,0 +1,3 @@ +```release-note: improvement +connect: Add Envoy 1.31 and 1.30 to support matrix +``` diff --git a/.changelog/21655.txt b/.changelog/21655.txt new file mode 100644 index 000000000000..3ef13bdf88fa --- /dev/null +++ b/.changelog/21655.txt @@ -0,0 +1,3 @@ +```release-note:improvement +xds: configures Envoy to load balance over all instances of an external service configured with hostnames when "envoy_dns_discovery_type" is set to "STRICT_DNS" +``` diff --git a/.changelog/21684.txt b/.changelog/21684.txt new file mode 100644 index 000000000000..3702737cb09a --- /dev/null +++ b/.changelog/21684.txt @@ -0,0 +1,6 @@ +```release-note:security +Upgrade to support aws/aws-sdk-go `v1.55.5 or higher`. This resolves CVEs +[CVE-2020-8911](https://nvd.nist.gov/vuln/detail/cve-2020-8911) and +[CVE-2020-8912](https://nvd.nist.gov/vuln/detail/cve-2020-8912). +``` + diff --git a/.changelog/21703.txt b/.changelog/21703.txt new file mode 100644 index 000000000000..41d226e4898e --- /dev/null +++ b/.changelog/21703.txt @@ -0,0 +1,3 @@ +```release-note:bug +jwt-provider: change dns lookup family from the default of AUTO which would prefer ipv6 to ALL if LOGICAL_DNS is used or PREFER_IPV4 if STRICT_DNS is used to gracefully handle transitions to ipv6. +``` diff --git a/.changelog/21704.txt b/.changelog/21704.txt new file mode 100644 index 000000000000..4e42741ebb39 --- /dev/null +++ b/.changelog/21704.txt @@ -0,0 +1,3 @@ +```release-note:security +Explicitly set 'Content-Type' header to mitigate XSS vulnerability. +``` \ No newline at end of file diff --git a/.changelog/21705.txt b/.changelog/21705.txt new file mode 100644 index 000000000000..e6ab5ba8118a --- /dev/null +++ b/.changelog/21705.txt @@ -0,0 +1,4 @@ +```release-note:security +Upgrade Go to use 1.22.7. This addresses CVE +[CVE-2024-34155](https://nvd.nist.gov/vuln/detail/CVE-2024-34155) +``` \ No newline at end of file diff --git a/.changelog/21710.txt b/.changelog/21710.txt new file mode 100644 index 000000000000..d557407635c1 --- /dev/null +++ b/.changelog/21710.txt @@ -0,0 +1,3 @@ +```release-note:security +ui: Pin a newer resolution of Braces +``` diff --git a/.changelog/21711.txt b/.changelog/21711.txt new file mode 100644 index 000000000000..b3ab185a2a3f --- /dev/null +++ b/.changelog/21711.txt @@ -0,0 +1,3 @@ +```release-note:security +Implement HTML sanitization for user-generated content to prevent XSS attacks in the UI. +``` diff --git a/.changelog/21715.txt b/.changelog/21715.txt new file mode 100644 index 000000000000..1b9402193232 --- /dev/null +++ b/.changelog/21715.txt @@ -0,0 +1,3 @@ +```release-note:security +ui: Pin a newer resolution of Codemirror +``` diff --git a/.changelog/21717.txt b/.changelog/21717.txt new file mode 100644 index 000000000000..2b51e643020d --- /dev/null +++ b/.changelog/21717.txt @@ -0,0 +1,3 @@ +```release-note:security +ui: Pin a newer resolution of Markdown-it +``` diff --git a/.changelog/21726.txt b/.changelog/21726.txt new file mode 100644 index 000000000000..20251e740cbe --- /dev/null +++ b/.changelog/21726.txt @@ -0,0 +1,3 @@ +```release-note:security +UI: Remove codemirror linting due to package dependency +``` diff --git a/.changelog/21729.txt b/.changelog/21729.txt new file mode 100644 index 000000000000..ce334fdfe901 --- /dev/null +++ b/.changelog/21729.txt @@ -0,0 +1,4 @@ +```release-notes:security +Bump Dockerfile base image to `alpine:3.20`. +This resolves CVE-2024-7264 and CVE-2024-8096 (curl). +``` diff --git a/.changelog/21735.txt b/.changelog/21735.txt new file mode 100644 index 000000000000..223b84b4803c --- /dev/null +++ b/.changelog/21735.txt @@ -0,0 +1,3 @@ +```release-note:security +ui: Pin a newer resolution of ansi-html +``` diff --git a/.changelog/21750.txt b/.changelog/21750.txt new file mode 100644 index 000000000000..c30c08179b4b --- /dev/null +++ b/.changelog/21750.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +security: upgrade ubi base image to 9.4 +``` diff --git a/.changelog/21780.txt b/.changelog/21780.txt new file mode 100644 index 000000000000..72550e549a42 --- /dev/null +++ b/.changelog/21780.txt @@ -0,0 +1,3 @@ +```release-note:improvement +api: remove dependency on proto-public, protobuf, and grpc +``` diff --git a/.changelog/21806.txt b/.changelog/21806.txt new file mode 100644 index 000000000000..0f47c49bd9bf --- /dev/null +++ b/.changelog/21806.txt @@ -0,0 +1,3 @@ +```release-note:feature +grafana: added the dashboards service-to-service dashboard, service dashboard, and consul dataplane dashboard +``` diff --git a/.changelog/21816.txt b/.changelog/21816.txt new file mode 100644 index 000000000000..40bc844beee9 --- /dev/null +++ b/.changelog/21816.txt @@ -0,0 +1,9 @@ +```release-note:security +mesh: Add `http.incoming.requestNormalization` to Mesh configuration entry to support inbound service traffic request normalization. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005) and [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). +``` +```release-note:security +mesh: Add `contains` and `ignoreCase` to L7 Intentions HTTP header matching criteria to support configuration resilient to variable casing and multiple values. This resolves [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). +``` +```release-note:breaking-change +mesh: Enable Envoy `HttpConnectionManager.normalize_path` by default on inbound traffic to mesh proxies. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005). +``` diff --git a/.changelog/_20721.txt b/.changelog/_20721.txt new file mode 100644 index 000000000000..e8f45bd280d6 --- /dev/null +++ b/.changelog/_20721.txt @@ -0,0 +1,3 @@ +```release-note:bug +ingress-gateway: **(Enterprise Only)** Fix a bug where on update, Ingress Gateways lost all upstreams for listeners with wildcard services in a different namespace. +``` \ No newline at end of file diff --git a/.changelog/_7773.txt b/.changelog/_7773.txt new file mode 100644 index 000000000000..6f5b340f56c3 --- /dev/null +++ b/.changelog/_7773.txt @@ -0,0 +1,3 @@ +```release-note:bug +prepared-query: (Enterprise-only) Fix issue where sameness-group failover targets to peers would attempt to query data from the default partition, rather than the sameness-group's partition always. +``` diff --git a/.changelog/_9142.txt b/.changelog/_9142.txt new file mode 100644 index 000000000000..9a10a8a0cab5 --- /dev/null +++ b/.changelog/_9142.txt @@ -0,0 +1,3 @@ +```release-note: improvement +telemetry: Add `telemetry.disable_per_tenancy_usage_metrics` in agent configuration to disable setting tenancy labels on usage metrics. This significantly decreases CPU utilization in clusters with many admin partitions or namespaces. +``` diff --git a/.copywrite.hcl b/.copywrite.hcl index 243a0a730722..1df5f1dce9d9 100644 --- a/.copywrite.hcl +++ b/.copywrite.hcl @@ -2,7 +2,7 @@ schema_version = 1 project { license = "BUSL-1.1" - copyright_year = 2023 + copyright_year = 2024 # (OPTIONAL) A list of globs that should not have copyright/license headers. # Supports doublestar glob patterns for more flexibility in defining which diff --git a/.fossa.yml b/.fossa.yml new file mode 100644 index 000000000000..0a70affa4bda --- /dev/null +++ b/.fossa.yml @@ -0,0 +1 @@ +version: 3 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index c6c09d402a92..8d5dd6dc4ba9 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -156,13 +156,16 @@ When you're ready to submit a pull request: 5. If there's any reason Consul users might need to know about this change, [add a changelog entry](../docs/contributing/add-a-changelog-entry.md). 6. Add labels to your pull request. A table of commonly use labels is below. - If you have any questions about which to apply, feel free to call it out in the PR or comments. - | Label | When to Use | - | --- | --- | - | `pr/no-changelog` | This PR does not have an intended changelog entry | + If you have any questions about which to apply, feel free to call it out in the PR or comments. Other labels may automatically be added by GitHub Actions CI. + + | Label | When to Use | + |----------------------| --- | + | `pr/no-changelog` | This PR does not have an intended changelog entry | + | `pr/no-backport` | This PR does not have an intended backport target | | `pr/no-metrics-test` | This PR does not require any testing for metrics | - | `backport/1.12.x` | Backport the changes in this PR to the targeted release branch. Consult the [Consul Release Notes](https://www.consul.io/docs/release-notes) page to view active releases. Website documentation merged to the latest release branch is deployed immediately | - Other labels may automatically be added by the Github Action CI. + | `backport/1.12.x` | Backport the changes in this PR to the targeted release branch. Consult the [Consul Release Notes](https://www.consul.io/docs/release-notes) page and [`versions.hcl`](/.release/versions.hcl) to view active releases. Website documentation merged to the latest release branch is deployed immediately. See [backport policy](#backport-policy) for more information. | + | `backport/all` | If contributing a bug fix or other change applicable to all branches, use `backport/all` to target all active branches automatically. See [backport policy](#backport-policy) for more information. | + 7. After you submit, the Consul maintainers team needs time to carefully review your contribution and ensure it is production-ready, considering factors such as: security, backwards-compatibility, potential regressions, etc. @@ -174,6 +177,10 @@ When you're ready to submit a pull request: Assuming the tests pass, the PR will be merged automatically. If the tests fail, it is you responsibility to resolve the issues with backports and request another reviewer. +### Backport Policy + +Consul is maintained as a Community Edition (CE) and an Enterprise product. Bug fixes and patches may be backported to the current major release in CE. In Enterprise, bug fixes and patches may be backported to all maintained releases: the N-2 releases and the 2 latest Long-Term Support (LTS) releases. For more information, refer to Consul’s [LTS documentation](https://developer.hashicorp.com/consul/docs/enterprise/long-term-support). + #### Checklists Some common changes that many PRs require are documented through checklists as diff --git a/.github/pr-labeler.yml b/.github/pr-labeler.yml index fd39f2ccab42..10db39816de9 100644 --- a/.github/pr-labeler.yml +++ b/.github/pr-labeler.yml @@ -2,45 +2,75 @@ # SPDX-License-Identifier: BUSL-1.1 pr/dependencies: - - vendor/**/* - - go.* + - changed-files: + - any-glob-to-any-file: + - vendor/**/* + - go.* theme/acls: - - acl/**/* + - changed-files: + - any-glob-to-any-file: + - acl/**/* theme/agent-cache: - - agent/cache/**/* + - changed-files: + - any-glob-to-any-file: + - agent/cache/**/* theme/api: - - api/**/* + - changed-files: + - any-glob-to-any-file: + - api/**/* theme/catalog: - - agent/catalog/**/* + - changed-files: + - any-glob-to-any-file: + - agent/catalog/**/* theme/certificates: - - tlsutil/**/* + - changed-files: + - any-glob-to-any-file: + - tlsutil/**/* theme/cli: - - command/**/* + - changed-files: + - any-glob-to-any-file: + - command/**/* theme/config: - - agent/config/**/* + - changed-files: + - any-glob-to-any-file: + - agent/config/**/* theme/connect: - - connect/**/* - - agent/connect/**/* + - changed-files: + - any-glob-to-any-file: + - connect/**/* + - agent/connect/**/* # theme/consul-nomad: theme/consul-terraform-sync: - - website/content/docs/nia/**/* - - website/content/docs/integrate/nia* + - changed-files: + - any-glob-to-any-file: + - website/content/docs/nia/**/* + - website/content/docs/integrate/nia* # theme/consul-vault: theme/contributing: - - .github/**/* + - changed-files: + - any-glob-to-any-file: + - .github/**/* theme/dns: - - dns/**/* + - changed-files: + - any-glob-to-any-file: + - dns/**/* theme/envoy/xds: - - agent/xds/**/* + - changed-files: + - any-glob-to-any-file: + - agent/xds/**/* # theme/federation-usability: theme/health-checks: - - agent/health* - - api/health* + - changed-files: + - any-glob-to-any-file: + - agent/health* + - api/health* # theme/ingress-gw: # theme/internal-cleanup: theme/internals: - - lib/**/* - - types/**/* + - changed-files: + - any-glob-to-any-file: + - lib/**/* + - types/**/* # theme/kubernetes: # theme/mesh-gw: # theme/operator-usability: @@ -48,19 +78,31 @@ theme/internals: # theme/service-metadata: # theme/streaming: theme/telemetry: - - logging/**/* + - changed-files: + - any-glob-to-any-file: + - logging/**/* # theme/terminating-gw: theme/testing: - - ./*test*/**/* + - changed-files: + - any-glob-to-any-file: + - ./*test*/**/* theme/tls: - - tlsutil/**/* + - changed-files: + - any-glob-to-any-file: + - tlsutil/**/* theme/ui: - - ui/**/* + - changed-files: + - any-glob-to-any-file: + - ui/**/* # theme/windows: # thinking: # type/bug: type/ci: - - .github/workflows/* + - changed-files: + - any-glob-to-any-file: + - .github/workflows/* # type/crash: type/docs: - - website/**/* + - changed-files: + - any-glob-to-any-file: + - website/**/* diff --git a/.github/scripts/filter_changed_files_go_test.sh b/.github/scripts/filter_changed_files_go_test.sh deleted file mode 100755 index bdd0e3f77f4e..000000000000 --- a/.github/scripts/filter_changed_files_go_test.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - -set -euo pipefail - -# Get the list of changed files -# Using `git merge-base` ensures that we're always comparing against the correct branch point. -#For example, given the commits: -# -# A---B---C---D---W---X---Y---Z # origin/main -# \---E---F # feature/branch -# -# ... `git merge-base origin/$SKIP_CHECK_BRANCH HEAD` would return commit `D` -# `...HEAD` specifies from the common ancestor to the latest commit on the current branch (HEAD).. -files_to_check=$(git diff --name-only "$(git merge-base origin/$SKIP_CHECK_BRANCH HEAD~)"...HEAD) - -# Define the directories to check -skipped_directories=("docs/" "ui/" "website/" "grafana/") - -# Loop through the changed files and find directories/files outside the skipped ones -for file_to_check in "${files_to_check[@]}"; do - file_is_skipped=false - for dir in "${skipped_directories[@]}"; do - if [[ "$file_to_check" == "$dir"* ]] || [[ "$file_to_check" == *.md && "$dir" == *"/" ]]; then - file_is_skipped=true - break - fi - done - if [ "$file_is_skipped" != "true" ]; then - echo -e $file_to_check - SKIP_CI=false - echo "Changes detected in non-documentation files - skip-ci: $SKIP_CI" - echo "skip-ci=$SKIP_CI" >> "$GITHUB_OUTPUT" - exit 0 ## if file is outside of the skipped_directory exit script - fi -done - -echo -e "$files_to_check" -SKIP_CI=true -echo "Changes detected in only documentation files - skip-ci: $SKIP_CI" -echo "skip-ci=$SKIP_CI" >> "$GITHUB_OUTPUT" \ No newline at end of file diff --git a/.github/scripts/goldenfile_checker.sh b/.github/scripts/goldenfile_checker.sh new file mode 100755 index 000000000000..0bdcfa35d0e4 --- /dev/null +++ b/.github/scripts/goldenfile_checker.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +set -euo pipefail + +# check if there is a diff in the xds testdata directory after running `make envoy-regen` +echo "regenerating xds files" +make envoy-regen + +echo "calculating changed files" +changed_xds_files=$(git --no-pager diff --name-only HEAD "$(git merge-base HEAD "origin/$GITHUB_BRANCH_REF")" | egrep "agent/xds/testdata/.*" || true) +# If we do not find a file in .changelog/, we fail the check +if [ -z "$changed_xds_files" ]; then + # pass status check if no changes were found for xds files + echo "Found no changes to xds golden files" + exit 0 +else + echo "Found diffs with xds golden files run 'make envoy-regen' to update them and check that output is expected" + exit 0 +fi diff --git a/.github/scripts/license_checker.sh b/.github/scripts/license_checker.sh deleted file mode 100755 index e001832f1d49..000000000000 --- a/.github/scripts/license_checker.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - -if [[ ${GITHUB_BASE_REF} == release/1.14.* ]] || [[ ${GITHUB_BASE_REF} == release/1.15.* ]] || [[ ${GITHUB_BASE_REF} == release/1.16.* ]]; then - busl_files=$(grep -r 'SPDX-License-Identifier: BUSL' . --exclude-dir .github) - - if [ -n "$busl_files" ]; then - echo "Found BUSL occurrences in the PR branch! (See NET-5258 for details)" - echo -n "$busl_files" - exit 1 - else - echo "Did not find any occurrences of BUSL in the PR branch" - exit 0 - fi - echo "The variable starts with release/1.14, release/1.15, or release/1.17." -else - echo "Skipping BUSL check since ${GITHUB_BASE_REF} not one of release/1.14.*, release/1.15.*, or release/1.16.*." - exit 0 -fi \ No newline at end of file diff --git a/.github/scripts/notify_slack.sh b/.github/scripts/notify_slack.sh deleted file mode 100755 index 8df3f3f64876..000000000000 --- a/.github/scripts/notify_slack.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: BUSL-1.1 - -set -uo pipefail - -# This script is used in GitHub Actions pipelines to notify Slack of a job failure. - -if [[ $GITHUB_REF_NAME == "main" ]]; then - GITHUB_ENDPOINT="https://github.com/${GITHUB_REPOSITORY}/commit/${GITHUB_SHA}" - GITHUB_ACTIONS_ENDPOINT="https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" - COMMIT_MESSAGE=$(git log -1 --pretty=%B | head -n1) - SHORT_REF=$(git rev-parse --short "${GITHUB_SHA}") - curl -X POST -H 'Content-type: application/json' \ - --data \ - "{ \ - \"attachments\": [ \ - { \ - \"fallback\": \"GitHub Actions workflow failed!\", \ - \"text\": \"❌ Failed: \`${GITHUB_ACTOR}\`'s <${GITHUB_ACTIONS_ENDPOINT}|${GITHUB_JOB}> job failed for commit <${GITHUB_ENDPOINT}|${SHORT_REF}> on \`${GITHUB_REF_NAME}\`!\n\n- <${COMMIT_MESSAGE}\", \ - \"footer\": \"${GITHUB_REPOSITORY}\", \ - \"ts\": \"$(date +%s)\", \ - \"color\": \"danger\" \ - } \ - ] \ - }" "${FEED_CONSUL_GH_URL}" -else - echo "Not posting slack failure notifications for non-main branch" -fi diff --git a/.github/scripts/set_test_package_matrix.sh b/.github/scripts/set_test_package_matrix.sh index 3f8a389297f4..73ef72001933 100755 --- a/.github/scripts/set_test_package_matrix.sh +++ b/.github/scripts/set_test_package_matrix.sh @@ -5,7 +5,15 @@ set -euo pipefail export RUNNER_COUNT=$1 +if ((RUNNER_COUNT < 2 )) +then + echo ERROR: RUNNER_COUNT must be greater than 1. Otherwise use the non-split unit test cod in .github/workflows/reusable-unit.yml. + exit 1 # terminate and indicate error +else + EFFECTIVE_RUNNER_COUNT=$((RUNNER_COUNT-1)) +fi + # set matrix var to list of unique packages containing tests -matrix="$(go list -json="ImportPath,TestGoFiles" ./... | jq --compact-output '. | select(.TestGoFiles != null) | .ImportPath' | shuf | jq --slurp --compact-output '.' | jq --argjson runnercount $RUNNER_COUNT -cM '[_nwise(length / $runnercount | floor)]'))" +matrix="$(go list -json="ImportPath,TestGoFiles" ./... | jq --compact-output '. | select(.TestGoFiles != null) | select(.ImportPath != "github.com/hashicorp/consul/agent") | .ImportPath' | shuf | jq --slurp --compact-output '.' | jq --argjson runnercount $EFFECTIVE_RUNNER_COUNT -cM '[_nwise(length / $runnercount | ceil)]' | jq --compact-output '. += [["github.com/hashicorp/consul/agent"]]'))" echo "matrix=${matrix}" >> "${GITHUB_OUTPUT}" diff --git a/.github/scripts/verify_artifact.sh b/.github/scripts/verify_artifact.sh index 3aa9e0848dfb..cb94726571a2 100755 --- a/.github/scripts/verify_artifact.sh +++ b/.github/scripts/verify_artifact.sh @@ -102,7 +102,8 @@ function verify_rpm { ${docker_image} \ /scripts/verify_rpm.sh \ "/workdir/${artifact_path}" \ - "${expect_version}" + "${expect_version}" \ + "${docker_image}" } # Arguments: diff --git a/.github/scripts/verify_rpm.sh b/.github/scripts/verify_rpm.sh index 96cd658eef3d..844f6a86bdd3 100755 --- a/.github/scripts/verify_rpm.sh +++ b/.github/scripts/verify_rpm.sh @@ -10,6 +10,10 @@ set -euo pipefail # report why it failed. This is meant to be run as part of the build workflow to verify the built # .rpm meets some basic criteria for validity. +# Notably, CentOS 7 is EOL, so we need to point to the vault for updates. It's not clear what alternative +# we may use in the future that supports linux/386 as the platform was dropped in CentOS 8+9. The docker_image +# is passed in as the third argument so that the script can determine if it needs to point to the vault for updates. + # set this so we can locate and execute the verify_bin.sh script for verifying version output SCRIPT_DIR="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" @@ -20,6 +24,7 @@ function usage { function main { local rpm_path="${1:-}" local expect_version="${2:-}" + local docker_image="${3:-}" local got_version if [[ -z "${rpm_path}" ]]; then @@ -34,6 +39,12 @@ function main { exit 1 fi + if [[ -z "${docker_image}" ]]; then + echo "ERROR: docker image argument is required" + usage + exit 1 + fi + # expand globs for path names, if this fails, the script will exit rpm_path=$(echo ${rpm_path}) @@ -43,6 +54,12 @@ function main { exit 1 fi + # CentOS 7 is EOL, so we need to point to the vault for updates + if [[ "$docker_image" == *centos:7 ]]; then + sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* + sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* + fi + yum -y clean all yum -y update yum -y install which openssl diff --git a/.github/workflows/backport-assistant.yml b/.github/workflows/backport-assistant.yml index 17462f811261..c58049f4441a 100644 --- a/.github/workflows/backport-assistant.yml +++ b/.github/workflows/backport-assistant.yml @@ -1,43 +1,57 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -# This action creates downstream PRs for PRs with backport labels defined. -# See docs here: https://github.com/hashicorp/backport-assistant - -name: Backport Assistant Runner - -on: - pull_request_target: - types: - - closed - - labeled - branches: - - main - - 'release/*.*.x' - -jobs: - backport: - if: github.event.pull_request.merged - runs-on: ubuntu-latest - container: hashicorpdev/backport-assistant:0.3.4 - steps: - - name: Run Backport Assistant for release branches - run: | - backport-assistant backport -merge-method=squash -gh-automerge - env: - BACKPORT_LABEL_REGEXP: "backport/(?P\\d+\\.\\d+)" - BACKPORT_TARGET_TEMPLATE: "release/{{.target}}.x" - GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - handle-failure: - needs: - - backport - if: always() && needs.backport.result == 'failure' - runs-on: ubuntu-latest - steps: - - name: Comment on PR - run: | - github_message="Backport failed @${{ github.event.sender.login }}. Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - curl -s -H "Authorization: token ${{ secrets.PR_COMMENT_TOKEN }}" \ - -X POST \ - -d "{ \"body\": \"${github_message}\"}" \ - "https://api.github.com/repos/${GITHUB_REPOSITORY}/issues/${{ github.event.pull_request.number }}/comments" +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +## This action creates downstream PRs for PRs with backport labels defined. +## See docs here: https://github.com/hashicorp/backport-assistant +# +#name: Backport Assistant Runner +# +#on: +# pull_request_target: +# types: +# - closed +# - labeled +# branches: +# - main +# - 'release/*.*.x' +# +#jobs: +# backport: +# if: github.event.pull_request.merged +# runs-on: ubuntu-latest +# container: hashicorpdev/backport-assistant:0.4.4 +# steps: +# - name: Run Backport Assistant for release branches +# run: | +# backport-assistant backport -merge-method=squash +# env: +# BACKPORT_LABEL_REGEXP: "backport/(?P\\d+\\.\\d+)" +# BACKPORT_TARGET_TEMPLATE: "release/{{.target}}.x" +# GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN_WORKFLOW }} +# ENABLE_VERSION_MANIFESTS: true +# backport-ent: +# if: github.event.pull_request.merged && contains(join(github.event.pull_request.labels.*.name), 'backport/ent') +# runs-on: ubuntu-latest +# steps: +# - name: Trigger backport for Enterprise +# uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3.0.0 +# with: +# token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# repository: hashicorp/consul-enterprise +# event-type: ent-backport +# client-payload: ${{ toJson(github.event) }} +# handle-failure: +# needs: +# - backport +# - backport-ent +# if: always() && (needs.backport.result == 'failure' || needs.backport-ent.result == 'failure') +# runs-on: ubuntu-latest +# steps: +# - name: Comment on PR +# run: | +# github_message="Backport failed @${{ github.event.sender.login }}. Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" +# curl -s -H "Authorization: token ${{ secrets.PR_COMMENT_TOKEN }}" \ +# -X POST \ +# -d "{ \"body\": \"${github_message}\"}" \ +# "https://api.github.com/repos/${GITHUB_REPOSITORY}/issues/${{ github.event.pull_request.number }}/comments" +# diff --git a/.github/workflows/backport-checker.yml b/.github/workflows/backport-checker.yml index 0e7cb0396ae5..edb9b92df39a 100644 --- a/.github/workflows/backport-checker.yml +++ b/.github/workflows/backport-checker.yml @@ -1,35 +1,35 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -# This workflow checks that there is either a 'pr/no-backport' label applied to a PR -# or there is a backport/* label indicating a backport has been set - -name: Backport Checker - -on: - pull_request: - types: [opened, synchronize, labeled] - # Runs on PRs to main and all release branches - branches: - - main - - release/* - -jobs: - # checks that a backport label is present for a PR - backport-check: - # If there's a `pr/no-backport` label we ignore this check. Also, we ignore PRs created by the bot assigned to `backport-assistant` - if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/no-backport') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" - runs-on: ubuntu-latest - - steps: - - name: Check for Backport Label - run: | - labels="${{join(github.event.pull_request.labels.*.name, ', ') }}" - if [[ "$labels" =~ .*"backport/".* ]]; then - echo "Found backport label!" - exit 0 - fi - # Fail status check when no backport label was found on the PR - echo "Did not find a backport label matching the pattern 'backport/*' and the 'pr/no-backport' label was not applied. Reference - https://github.com/hashicorp/consul/pull/16567" - exit 1 - +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +## This workflow checks that there is either a 'pr/no-backport' label applied to a PR +## or there is a backport/* label indicating a backport has been set +# +#name: Backport Checker +# +#on: +# pull_request: +# types: [opened, synchronize, labeled] +# # Runs on PRs to main and all release branches +# branches: +# - main +# - release/* +# +#jobs: +# # checks that a backport label is present for a PR +# backport-check: +# # If there's a `pr/no-backport` label we ignore this check. Also, we ignore PRs created by the bot assigned to `backport-assistant` +# if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/no-backport') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" +# runs-on: ubuntu-latest +# +# steps: +# - name: Check for Backport Label +# run: | +# labels="${{join(github.event.pull_request.labels.*.name, ', ') }}" +# if [[ "$labels" =~ .*"backport/".* ]]; then +# echo "Found backport label!" +# exit 0 +# fi +# # Fail status check when no backport label was found on the PR +# echo "Did not find a backport label matching the pattern 'backport/*' and the 'pr/no-backport' label was not applied. Reference - https://github.com/hashicorp/consul/pull/16567" +# exit 1 +# diff --git a/.github/workflows/bot-auto-approve.yaml b/.github/workflows/bot-auto-approve.yaml index 911fc27f4696..d6ca7811e0b2 100644 --- a/.github/workflows/bot-auto-approve.yaml +++ b/.github/workflows/bot-auto-approve.yaml @@ -1,16 +1,16 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Bot Auto Approve - -on: pull_request_target - -jobs: - auto-approve: - runs-on: ubuntu-latest - if: github.actor == 'hc-github-team-consul-core' - steps: - - uses: hmarr/auto-approve-action@44888193675f29a83e04faf4002fa8c0b537b1e4 # v3.2.1 - with: - review-message: "Auto approved Consul Bot automated PR" - github-token: ${{ secrets.MERGE_APPROVE_TOKEN }} +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Bot Auto Approve +# +#on: pull_request_target +# +#jobs: +# auto-approve: +# runs-on: ubuntu-latest +# if: github.actor == 'hc-github-team-consul-core' +# steps: +# - uses: hmarr/auto-approve-action@f0939ea97e9205ef24d872e76833fa908a770363 # v4.0.0 +# with: +# review-message: "Auto approved Consul Bot automated PR" +# github-token: ${{ secrets.MERGE_APPROVE_TOKEN }} diff --git a/.github/workflows/broken-link-check.yml b/.github/workflows/broken-link-check.yml index 2a8d77c5880f..9b12d0f0fd6c 100644 --- a/.github/workflows/broken-link-check.yml +++ b/.github/workflows/broken-link-check.yml @@ -1,33 +1,33 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Broken Link Check - -on: - workflow_dispatch: - schedule: - - cron: "0 0 * * 1" - -jobs: - linkChecker: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - - name: Run lychee link checker - id: lychee - uses: lycheeverse/lychee-action@ec3ed119d4f44ad2673a7232460dc7dff59d2421 # v1.8.0 - with: - args: ./website/content/docs/ --base https://developer.hashicorp.com/ --exclude-all-private --exclude '\.(svg|gif|jpg|png)' --exclude 'manage\.auth0\.com' --accept 403 --max-concurrency=24 --no-progress --verbose - # Fail GitHub action when broken links are found? - fail: false - env: - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} - - - name: Create GitHub Issue From lychee output file - if: env.lychee_exit_code != 0 - uses: peter-evans/create-issue-from-file@433e51abf769039ee20ba1293a088ca19d573b7f # v4.0.1 - with: - title: Link Checker Report - content-filepath: ./lychee/out.md - labels: report, automated issue \ No newline at end of file +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Broken Link Check +# +#on: +# workflow_dispatch: +# schedule: +# - cron: "0 0 1 * *" +# +#jobs: +# linkChecker: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# - name: Run lychee link checker +# id: lychee +# uses: lycheeverse/lychee-action@2b973e86fc7b1f6b36a93795fe2c9c6ae1118621 # v1.10.0 +# with: +# args: ./website/content/docs/ --base https://developer.hashicorp.com/ --exclude-all-private --exclude '\.(svg|gif|jpg|png)' --exclude 'manage\.auth0\.com' --accept 403 --max-concurrency=24 --no-progress --verbose +# # Fail GitHub action when broken links are found? +# fail: false +# env: +# GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} +# +# - name: Create GitHub Issue From lychee output file +# if: env.lychee_exit_code != 0 +# uses: peter-evans/create-issue-from-file@24452a72d85239eacf1468b0f1982a9f3fec4c94 # v5.0.0 +# with: +# title: Link Checker Report +# content-filepath: ./lychee/out.md +# labels: report, automated issue diff --git a/.github/workflows/build-artifacts.yml b/.github/workflows/build-artifacts.yml index 2977a73b6eb0..9df0f75777e0 100644 --- a/.github/workflows/build-artifacts.yml +++ b/.github/workflows/build-artifacts.yml @@ -1,134 +1,139 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -# This workflow builds a dev binary and distributes a Docker image on every push to the main branch. -name: build-artifacts - -on: - push: - branches: - - main - -permissions: - contents: read - -env: - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - -jobs: - setup: - name: Setup - runs-on: ubuntu-latest - outputs: - compute-small: ${{ steps.setup-outputs.outputs.compute-small }} - compute-medium: ${{ steps.setup-outputs.outputs.compute-medium }} - compute-large: ${{ steps.setup-outputs.outputs.compute-large }} - compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - id: setup-outputs - name: Setup outputs - run: ./.github/scripts/get_runner_classes.sh - - dev-build-push: - needs: setup - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - steps: - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/dockerhub username | DOCKERHUB_USERNAME; - kv/data/github/${{ github.repository }}/dockerhub token | DOCKERHUB_TOKEN; - - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - # NOTE: ENT specific step as we need to set elevated GitHub permissions. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - - run: go env - - - name: Build dev binary - run: make dev - - - name: Set env vars - run: | - echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - echo "GITHUB_BUILD_URL=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_ENV - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 - - # NOTE: conditional specific logic as we store secrets in Vault in ENT and use GHA secrets in CE. - - name: Login to Docker Hub - uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0 - with: - username: ${{ endsWith(github.repository, '-enterprise') && steps.secrets.outputs.DOCKERHUB_USERNAME || secrets.DOCKERHUB_USERNAME }} - password: ${{ endsWith(github.repository, '-enterprise') && steps.secrets.outputs.DOCKERHUB_TOKEN || secrets.DOCKERHUB_TOKEN }} - - - name: Docker build and push - uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825 # v4.1.1 - with: - context: ./bin - file: ./build-support/docker/Consul-Dev.dockerfile - labels: COMMIT_SHA=${{ github.sha }},GITHUB_BUILD_URL=${{ env.GITHUB_BUILD_URL }} - push: true - # This is required or else the image is not pullable. - # See https://github.com/docker/build-push-action/issues/820 for further - # details. - # TODO - investigate further and see if we can find a solution where we - # we don't have to know to set this. - provenance: false - tags: | - hashicorpdev/${{ github.event.repository.name }}:${{ env.SHORT_SHA }} - hashicorpdev/${{ github.event.repository.name }}:latest - - # This is job is required for branch protection as a required gihub check - # because GitHub actions show up as checks at the job level and not the - # workflow level. This is currently a feature request: - # https://github.com/orgs/community/discussions/12395 - # - # This job must: - # - be placed after the fanout of a workflow so that everything fans back in - # to this job. - # - "need" any job that is part of the fan out / fan in - # - implement the if logic because we have conditional jobs - # (go-test-enteprise) that this job needs and this would potentially get - # skipped if a previous job got skipped. So we use the if clause to make - # sure it does not get skipped. - - build-artifacts-success: - needs: - - setup - - dev-build-push - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - if: ${{ always() }} - steps: - - name: evaluate upstream job results - run: | - # exit 1 if failure or cancelled result for any upstream job - if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then - printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" - exit 1 - fi +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +## This workflow builds a dev binary and distributes a Docker image on every push to the main branch. +#name: build-artifacts +# +#on: +# push: +# branches: +# - main +# +#permissions: +# contents: read +# +#env: +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +#jobs: +# setup: +# name: Setup +# runs-on: ubuntu-latest +# outputs: +# compute-small: ${{ steps.setup-outputs.outputs.compute-small }} +# compute-medium: ${{ steps.setup-outputs.outputs.compute-medium }} +# compute-large: ${{ steps.setup-outputs.outputs.compute-large }} +# compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# - id: setup-outputs +# name: Setup outputs +# run: ./.github/scripts/get_runner_classes.sh +# +# get-go-version: +# uses: ./.github/workflows/reusable-get-go-version.yml +# +# dev-build-push: +# needs: +# - setup +# - get-go-version +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# steps: +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/dockerhub username | DOCKERHUB_USERNAME; +# kv/data/github/${{ github.repository }}/dockerhub token | DOCKERHUB_TOKEN; +# +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# # NOTE: ENT specific step as we need to set elevated GitHub permissions. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# +# - run: go env +# +# - name: Build dev binary +# run: make dev +# +# - name: Set env vars +# run: | +# echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV +# echo "GITHUB_BUILD_URL=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_ENV +# +# - name: Set up Docker Buildx +# uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 +# +# # NOTE: conditional specific logic as we store secrets in Vault in ENT and use GHA secrets in CE. +# - name: Login to Docker Hub +# uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 +# with: +# username: ${{ endsWith(github.repository, '-enterprise') && steps.secrets.outputs.DOCKERHUB_USERNAME || secrets.DOCKERHUB_USERNAME }} +# password: ${{ endsWith(github.repository, '-enterprise') && steps.secrets.outputs.DOCKERHUB_TOKEN || secrets.DOCKERHUB_TOKEN }} +# +# - name: Docker build and push +# uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 +# with: +# context: ./bin +# file: ./build-support/docker/Consul-Dev.dockerfile +# labels: COMMIT_SHA=${{ github.sha }},GITHUB_BUILD_URL=${{ env.GITHUB_BUILD_URL }} +# push: true +# # This is required or else the image is not pullable. +# # See https://github.com/docker/build-push-action/issues/820 for further +# # details. +# # TODO - investigate further and see if we can find a solution where we +# # we don't have to know to set this. +# provenance: false +# tags: | +# hashicorpdev/${{ github.event.repository.name }}:${{ env.SHORT_SHA }} +# hashicorpdev/${{ github.event.repository.name }}:latest +# +# # This is job is required for branch protection as a required gihub check +# # because GitHub actions show up as checks at the job level and not the +# # workflow level. This is currently a feature request: +# # https://github.com/orgs/community/discussions/12395 +# # +# # This job must: +# # - be placed after the fanout of a workflow so that everything fans back in +# # to this job. +# # - "need" any job that is part of the fan out / fan in +# # - implement the if logic because we have conditional jobs +# # (go-test-enteprise) that this job needs and this would potentially get +# # skipped if a previous job got skipped. So we use the if clause to make +# # sure it does not get skipped. +# +# build-artifacts-success: +# needs: +# - setup +# - dev-build-push +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# if: ${{ always() }} +# steps: +# - name: evaluate upstream job results +# run: | +# # exit 1 if failure or cancelled result for any upstream job +# if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then +# printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" +# exit 1 +# fi diff --git a/.github/workflows/build-distros.yml b/.github/workflows/build-distros.yml index 4d8799a5643d..262f8d61024b 100644 --- a/.github/workflows/build-distros.yml +++ b/.github/workflows/build-distros.yml @@ -1,174 +1,183 @@ -# NOTE: this workflow builds Consul binaries on multiple architectures for PRs. -# It is aimed at checking new commits don't introduce any breaking build changes. -name: build-distros - -on: - pull_request: - push: - branches: - # Push events on the main branch - - main - - release/** - -permissions: - contents: read - -env: - GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} - cancel-in-progress: true - -jobs: - setup: - name: Setup - runs-on: ubuntu-latest - outputs: - compute-small: ${{ steps.setup-outputs.outputs.compute-small }} - compute-medium: ${{ steps.setup-outputs.outputs.compute-medium }} - compute-large: ${{ steps.setup-outputs.outputs.compute-large }} - compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - id: setup-outputs - name: Setup outputs - run: ./.github/scripts/get_runner_classes.sh - - check-go-mod: - needs: - - setup - uses: ./.github/workflows/reusable-check-go-mod.yml - with: - runs-on: ${{ needs.setup.outputs.compute-medium }} - repository-name: ${{ github.repository }} - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - build-386: - needs: - - setup - - check-go-mod - env: - XC_OS: "freebsd linux windows" - runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - name: Build - run: | - for os in $XC_OS; do - GOOS="$os" GOARCH=386 CGO_ENABLED=0 go build -tags "${{ env.GOTAGS }}" - done - - build-amd64: - needs: - - setup - - check-go-mod - env: - XC_OS: "darwin freebsd linux solaris windows" - runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - name: Build - run: | - for os in $XC_OS; do - GOOS="$os" GOARCH=amd64 CGO_ENABLED=0 go build -tags "${{ env.GOTAGS }}" - done - - build-arm: - needs: - - setup - - check-go-mod - runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} - env: - CGO_ENABLED: 1 - GOOS: linux - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: | - sudo apt-get update --allow-releaseinfo-change-suite --allow-releaseinfo-change-version && sudo apt-get install -y gcc-arm-linux-gnueabi gcc-arm-linux-gnueabihf gcc-aarch64-linux-gnu - - - run: CC=arm-linux-gnueabi-gcc GOARCH=arm GOARM=5 go build -tags "${{ env.GOTAGS }}" - - run: CC=arm-linux-gnueabihf-gcc GOARCH=arm GOARM=6 go build -tags "${{ env.GOTAGS }}" - - run: CC=aarch64-linux-gnu-gcc GOARCH=arm64 go build -tags "${{ env.GOTAGS }}" - - - build-s390x: - if: ${{ endsWith(github.repository, '-enterprise') }} - needs: - - setup - - check-go-mod - runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - name: Build - run: GOOS=linux GOARCH=s390x CGO_ENABLED=0 go build -tags "${{ env.GOTAGS }}" - - # This is job is required for branch protection as a required gihub check - # because GitHub actions show up as checks at the job level and not the - # workflow level. This is currently a feature request: - # https://github.com/orgs/community/discussions/12395 - # - # This job must: - # - be placed after the fanout of a workflow so that everything fans back in - # to this job. - # - "need" any job that is part of the fan out / fan in - # - implement the if logic because we have conditional jobs - # (go-test-enteprise) that this job needs and this would potentially get - # skipped if a previous job got skipped. So we use the if clause to make - # sure it does not get skipped. - build-distros-success: - needs: - - setup - - check-go-mod - - build-386 - - build-amd64 - - build-arm - - build-s390x - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - if: ${{ always() }} - steps: - - name: evaluate upstream job results - run: | - # exit 1 if failure or cancelled result for any upstream job - if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then - printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" - exit 1 - fi +## NOTE: this workflow builds Consul binaries on multiple architectures for PRs. +## It is aimed at checking new commits don't introduce any breaking build changes. +#name: build-distros +# +#on: +# pull_request: +# push: +# branches: +# # Push events on the main branch +# - main +# - release/** +# +#permissions: +# contents: read +# +#env: +# GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +#concurrency: +# group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} +# cancel-in-progress: true +# +#jobs: +# setup: +# name: Setup +# runs-on: ubuntu-latest +# outputs: +# compute-small: ${{ steps.setup-outputs.outputs.compute-small }} +# compute-medium: ${{ steps.setup-outputs.outputs.compute-medium }} +# compute-large: ${{ steps.setup-outputs.outputs.compute-large }} +# compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# - id: setup-outputs +# name: Setup outputs +# run: ./.github/scripts/get_runner_classes.sh +# +# get-go-version: +# uses: ./.github/workflows/reusable-get-go-version.yml +# +# check-go-mod: +# needs: +# - setup +# - get-go-version +# uses: ./.github/workflows/reusable-check-go-mod.yml +# with: +# runs-on: ${{ needs.setup.outputs.compute-medium }} +# repository-name: ${{ github.repository }} +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# build-386: +# needs: +# - setup +# - get-go-version +# - check-go-mod +# env: +# XC_OS: "freebsd linux windows" +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - name: Build +# run: | +# for os in $XC_OS; do +# GOOS="$os" GOARCH=386 CGO_ENABLED=0 go build -tags "${{ env.GOTAGS }}" +# done +# +# build-amd64: +# needs: +# - setup +# - get-go-version +# - check-go-mod +# env: +# XC_OS: "darwin freebsd linux solaris windows" +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - name: Build +# run: | +# for os in $XC_OS; do +# GOOS="$os" GOARCH=amd64 CGO_ENABLED=0 go build -tags "${{ env.GOTAGS }}" +# done +# +# build-arm: +# needs: +# - setup +# - get-go-version +# - check-go-mod +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} +# env: +# CGO_ENABLED: 1 +# GOOS: linux +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# +# +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: | +# sudo apt-get update --allow-releaseinfo-change-suite --allow-releaseinfo-change-version && sudo apt-get install -y gcc-arm-linux-gnueabi gcc-arm-linux-gnueabihf gcc-aarch64-linux-gnu +# +# - run: CC=arm-linux-gnueabi-gcc GOARCH=arm GOARM=5 go build -tags "${{ env.GOTAGS }}" +# - run: CC=arm-linux-gnueabihf-gcc GOARCH=arm GOARM=6 go build -tags "${{ env.GOTAGS }}" +# - run: CC=aarch64-linux-gnu-gcc GOARCH=arm64 go build -tags "${{ env.GOTAGS }}" +# +# +# build-s390x: +# if: ${{ endsWith(github.repository, '-enterprise') }} +# needs: +# - setup +# - get-go-version +# - check-go-mod +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - name: Build +# run: GOOS=linux GOARCH=s390x CGO_ENABLED=0 go build -tags "${{ env.GOTAGS }}" +# +# # This is job is required for branch protection as a required gihub check +# # because GitHub actions show up as checks at the job level and not the +# # workflow level. This is currently a feature request: +# # https://github.com/orgs/community/discussions/12395 +# # +# # This job must: +# # - be placed after the fanout of a workflow so that everything fans back in +# # to this job. +# # - "need" any job that is part of the fan out / fan in +# # - implement the if logic because we have conditional jobs +# # (go-test-enteprise) that this job needs and this would potentially get +# # skipped if a previous job got skipped. So we use the if clause to make +# # sure it does not get skipped. +# build-distros-success: +# needs: +# - setup +# - check-go-mod +# - build-386 +# - build-amd64 +# - build-arm +# - build-s390x +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# if: ${{ always() }} +# steps: +# - name: evaluate upstream job results +# run: | +# # exit 1 if failure or cancelled result for any upstream job +# if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then +# printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" +# exit 1 +# fi diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cc2e2437a050..b3313e216d85 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,526 +1,453 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: build - -on: - push: - # Sequence of patterns matched against refs/heads - branches: - # Push events on the main branch - - main - - release/** - -env: - PKG_NAME: consul - # TODO(spatel): CE refactor - METADATA: oss - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - -jobs: - set-product-version: - runs-on: ubuntu-latest - outputs: - product-version: ${{ steps.set-product-version.outputs.product-version }} - base-product-version: ${{ steps.set-product-version.outputs.base-product-version }} - product-date: ${{ steps.get-product-version.outputs.product-date }} - pre-version: ${{ steps.set-product-version.outputs.prerelease-product-version }} - shared-ldflags: ${{ steps.shared-ldflags.outputs.shared-ldflags }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # action-set-product-version implicitly sets fields like 'product-version' using version/VERSION - # https://github.com/hashicorp/actions-set-product-version - - name: set product version - id: set-product-version - uses: hashicorp/actions-set-product-version@v1 - - name: get product version - id: get-product-version - run: | - CONSUL_DATE=$(build-support/scripts/build-date.sh) - echo "product-date=${CONSUL_DATE}" >> "$GITHUB_OUTPUT" - - - name: Set shared -ldflags - id: shared-ldflags - run: | - T="github.com/hashicorp/consul/version" - echo "shared-ldflags=-X ${T}.GitCommit=${GITHUB_SHA::8} \ - -X ${T}.GitDescribe=${{ steps.set-product-version.outputs.product-version }} \ - -X ${T}.BuildDate=${{ steps.get-product-version.outputs.product-date }} \ - " >> "$GITHUB_OUTPUT" - validate-outputs: - needs: set-product-version - runs-on: ubuntu-latest - steps: - - name: Validate Outputs - run: | - echo "Product Version: ${{ needs.set-product-version.outputs.product-version }}" - echo "Base Product Version: ${{ needs.set-product-version.outputs.base-product-version }}" - echo "Product Metadata: ${{ env.METADATA }}" - echo "Product Date: ${{ needs.set-product-version.outputs.product-date }}" - echo "Prerelease Version: ${{ needs.set-product-version.outputs.pre-version }}" - echo "Ldflags: ${{ needs.set-product-version.outputs.shared-ldflags }}" - - generate-metadata-file: - needs: set-product-version - runs-on: ubuntu-latest - outputs: - filepath: ${{ steps.generate-metadata-file.outputs.filepath }} - steps: - - name: 'Checkout directory' - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Generate metadata file - id: generate-metadata-file - uses: hashicorp/actions-generate-metadata@v1 - with: - version: ${{ needs.set-product-version.outputs.product-version }} - product: ${{ env.PKG_NAME }} - - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: metadata.json - path: ${{ steps.generate-metadata-file.outputs.filepath }} - - build: - needs: set-product-version - runs-on: ubuntu-latest - strategy: - matrix: - include: - - {go: "1.20.10", goos: "linux", goarch: "386"} - - {go: "1.20.10", goos: "linux", goarch: "amd64"} - - {go: "1.20.10", goos: "linux", goarch: "arm"} - - {go: "1.20.10", goos: "linux", goarch: "arm64"} - - {go: "1.20.10", goos: "freebsd", goarch: "386"} - - {go: "1.20.10", goos: "freebsd", goarch: "amd64"} - - {go: "1.20.10", goos: "windows", goarch: "386"} - - {go: "1.20.10", goos: "windows", goarch: "amd64"} - - {go: "1.20.10", goos: "solaris", goarch: "amd64"} - fail-fast: true - - name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - - name: Setup with node and yarn - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: '18' - cache: 'yarn' - cache-dependency-path: 'ui/yarn.lock' - - - name: Build UI - run: | - CONSUL_VERSION=${{ needs.set-product-version.outputs.product-version }} - CONSUL_DATE=${{ needs.set-product-version.outputs.product-date }} - CONSUL_BINARY_TYPE=${CONSUL_BINARY_TYPE} - CONSUL_COPYRIGHT_YEAR=$(git show -s --format=%cd --date=format:%Y HEAD) - echo "consul_version is ${CONSUL_VERSION}" - echo "consul_date is ${CONSUL_DATE}" - echo "consul binary type is ${CONSUL_BINARY_TYPE}" - echo "consul copyright year is ${CONSUL_COPYRIGHT_YEAR}" - cd ui && make && cd .. - rm -rf agent/uiserver/dist - mv ui/packages/consul-ui/dist agent/uiserver/ - - name: Go Build - env: - PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }} - PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.pre-version }} - CGO_ENABLED: "0" - GOLDFLAGS: "${{needs.set-product-version.outputs.shared-ldflags}}" - uses: hashicorp/actions-go-build@v0.1.7 - with: - product_name: ${{ env.PKG_NAME }} - product_version: ${{ needs.set-product-version.outputs.product-version }} - go_version: ${{ matrix.go }} - os: ${{ matrix.goos }} - arch: ${{ matrix.goarch }} - reproducible: report - instructions: |- - go build -ldflags="$GOLDFLAGS" -o "$BIN_PATH" -trimpath -buildvcs=false - - - name: Package - if: ${{ matrix.goos == 'linux' }} - uses: hashicorp/actions-packaging-linux@v1 - with: - name: ${{ github.event.repository.name }} - description: "Consul is a distributed, highly available, and data center aware solution to connect and configure applications across dynamic, distributed infrastructure. " - arch: ${{ matrix.goarch }} - version: ${{ needs.set-product-version.outputs.product-version }} - maintainer: "HashiCorp" - homepage: "https://github.com/hashicorp/consul" - license: "MPL-2.0" - binary: "dist/${{ env.PKG_NAME }}" - deb_depends: "openssl" - rpm_depends: "openssl" - config_dir: ".release/linux/package" - preinstall: ".release/linux/preinstall" - postinstall: ".release/linux/postinstall" - preremove: ".release/linux/preremove" - postremove: ".release/linux/postremove" - - - name: Set Package Names - if: ${{ matrix.goos == 'linux' }} - run: | - echo "RPM_PACKAGE=$(basename out/*.rpm)" >> $GITHUB_ENV - echo "DEB_PACKAGE=$(basename out/*.deb)" >> $GITHUB_ENV - - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - if: ${{ matrix.goos == 'linux' }} - with: - name: ${{ env.RPM_PACKAGE }} - path: out/${{ env.RPM_PACKAGE }} - - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - if: ${{ matrix.goos == 'linux' }} - with: - name: ${{ env.DEB_PACKAGE }} - path: out/${{ env.DEB_PACKAGE }} - - build-s390x: - needs: set-product-version - if: ${{ endsWith(github.repository, '-enterprise') }} - runs-on: ubuntu-latest - strategy: - matrix: - include: - - {go: "1.20.10", goos: "linux", goarch: "s390x"} - fail-fast: true - - name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - - name: Setup with node and yarn - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: '18' - cache: 'yarn' - cache-dependency-path: 'ui/yarn.lock' - - - name: Build UI - run: | - CONSUL_VERSION=${{ needs.set-product-version.outputs.product-version }} - CONSUL_DATE=${{ needs.set-product-version.outputs.product-date }} - CONSUL_BINARY_TYPE=${CONSUL_BINARY_TYPE} - CONSUL_COPYRIGHT_YEAR=$(git show -s --format=%cd --date=format:%Y HEAD) - echo "consul_version is ${CONSUL_VERSION}" - echo "consul_date is ${CONSUL_DATE}" - echo "consul binary type is ${CONSUL_BINARY_TYPE}" - echo "consul copyright year is ${CONSUL_COPYRIGHT_YEAR}" - cd ui && make && cd .. - rm -rf agent/uiserver/dist - mv ui/packages/consul-ui/dist agent/uiserver/ - - name: Go Build - env: - PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }} - PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.pre-version }} - CGO_ENABLED: "0" - GOLDFLAGS: "${{needs.set-product-version.outputs.shared-ldflags}}" - uses: hashicorp/actions-go-build@v0.1.7 - with: - product_name: ${{ env.PKG_NAME }} - product_version: ${{ needs.set-product-version.outputs.product-version }} - go_version: ${{ matrix.go }} - os: ${{ matrix.goos }} - arch: ${{ matrix.goarch }} - reproducible: report - instructions: |- - go build -ldflags="$GOLDFLAGS" -o "$BIN_PATH" -trimpath -buildvcs=false - - build-darwin: - needs: set-product-version - runs-on: macos-latest - strategy: - matrix: - goos: [ darwin ] - goarch: [ "amd64", "arm64" ] - go: [ "1.20.10" ] - fail-fast: true - - name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - - name: Setup with node and yarn - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: '18' - cache: 'yarn' - cache-dependency-path: 'ui/yarn.lock' - - - name: Build UI - run: | - CONSUL_VERSION=${{ needs.set-product-version.outputs.product-version }} - CONSUL_BINARY_TYPE=${CONSUL_BINARY_TYPE} - CONSUL_COPYRIGHT_YEAR=$(git show -s --format=%cd --date=format:%Y HEAD) - echo "consul_version is ${CONSUL_VERSION}" - echo "consul binary type is ${CONSUL_BINARY_TYPE}" - echo "consul copyright year is ${CONSUL_COPYRIGHT_YEAR}" - cd ui && make && cd .. - rm -rf agent/uiserver/dist - mv ui/packages/consul-ui/dist agent/uiserver/ - - name: Go Build - env: - PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }} - PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.pre-version }} - CGO_ENABLED: "0" - GOLDFLAGS: "${{needs.set-product-version.outputs.shared-ldflags}}" - uses: hashicorp/actions-go-build@v0.1.7 - with: - product_name: ${{ env.PKG_NAME }} - product_version: ${{ needs.set-product-version.outputs.product-version }} - go_version: ${{ matrix.go }} - os: ${{ matrix.goos }} - arch: ${{ matrix.goarch }} - reproducible: report - instructions: |- - go build -ldflags="$GOLDFLAGS" -tags netcgo -o "$BIN_PATH" -trimpath -buildvcs=false - - build-docker: - name: Docker ${{ matrix.arch }} build - needs: - - set-product-version - - build - runs-on: ubuntu-latest - strategy: - matrix: - include: - - { arch: "386" } - - { arch: "arm" } - - { arch: "amd64" } - - { arch: "arm64" } - env: - repo: ${{github.event.repository.name}} - version: ${{needs.set-product-version.outputs.product-version}} - - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - # Strip everything but MAJOR.MINOR from the version string and add a `-dev` suffix - # This naming convention will be used ONLY for per-commit dev images - - name: Set docker dev tag - run: | - echo "full_dev_tag=${{ env.version }}" - echo "full_dev_tag=${{ env.version }}" >> $GITHUB_ENV - echo "minor_dev_tag=$(echo ${{ env.version }}| sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+(-[0-9a-zA-Z\+\.]+)?$/\1\2/')" - echo "minor_dev_tag=$(echo ${{ env.version }}| sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+(-[0-9a-zA-Z\+\.]+)?$/\1\2/')" >> $GITHUB_ENV - - - name: Docker Build (Action) - uses: hashicorp/actions-docker-build@v1 - with: - version: ${{env.version}} - target: default - arch: ${{matrix.arch}} - tags: | - docker.io/hashicorp/${{env.repo}}:${{env.version}} - public.ecr.aws/hashicorp/${{env.repo}}:${{env.version}} - dev_tags: | - docker.io/hashicorppreview/${{ env.repo }}:${{ env.full_dev_tag }} - docker.io/hashicorppreview/${{ env.repo }}:${{ env.full_dev_tag }}-${{ github.sha }} - docker.io/hashicorppreview/${{ env.repo }}:${{ env.minor_dev_tag }} - docker.io/hashicorppreview/${{ env.repo }}:${{ env.minor_dev_tag }}-${{ github.sha }} - smoke_test: .github/scripts/verify_docker.sh v${{ env.version }} - - build-docker-ubi-redhat: - name: Docker Build UBI Image for RedHat Registry - needs: - - set-product-version - - build - runs-on: ubuntu-latest - env: - repo: ${{github.event.repository.name}} - version: ${{needs.set-product-version.outputs.product-version}} - - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - uses: hashicorp/actions-docker-build@v1 - with: - version: ${{env.version}} - target: ubi - arch: amd64 - redhat_tag: quay.io/redhat-isv-containers/60f9fdbec3a80eac643abedf:${{env.version}}-ubi - smoke_test: .github/scripts/verify_docker.sh v${{ env.version }} - - build-docker-ubi-dockerhub: - name: Docker Build UBI Image for DockerHub - needs: - - set-product-version - - build - runs-on: ubuntu-latest - env: - repo: ${{github.event.repository.name}} - version: ${{needs.set-product-version.outputs.product-version}} - - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - # Strip everything but MAJOR.MINOR from the version string and add a `-dev` suffix - # This naming convention will be used ONLY for per-commit dev images - - name: Set docker dev tag - run: | - echo "full_dev_tag=${{ env.version }}" - echo "full_dev_tag=${{ env.version }}" >> $GITHUB_ENV - echo "minor_dev_tag=$(echo ${{ env.version }}| sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+(-[0-9a-zA-Z\+\.]+)?$/\1\2/')" - echo "minor_dev_tag=$(echo ${{ env.version }}| sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+(-[0-9a-zA-Z\+\.]+)?$/\1\2/')" >> $GITHUB_ENV - - - uses: hashicorp/actions-docker-build@v1 - with: - version: ${{env.version}} - target: ubi - arch: amd64 - tags: | - docker.io/hashicorp/${{env.repo}}:${{env.version}}-ubi - public.ecr.aws/hashicorp/${{env.repo}}:${{env.version}}-ubi - dev_tags: | - docker.io/hashicorppreview/${{ env.repo }}:${{ env.full_dev_tag }}-ubi - docker.io/hashicorppreview/${{ env.repo }}:${{ env.full_dev_tag }}-ubi-${{ github.sha }} - docker.io/hashicorppreview/${{ env.repo }}:${{ env.minor_dev_tag }}-ubi - docker.io/hashicorppreview/${{ env.repo }}:${{ env.minor_dev_tag }}-ubi-${{ github.sha }} - smoke_test: .github/scripts/verify_docker.sh v${{ env.version }} - - verify-linux: - needs: - - set-product-version - - build - runs-on: ubuntu-latest - strategy: - matrix: - include: - - { arch: "386" } - - { arch: "arm" } - - { arch: "amd64" } - - { arch: "arm64" } - fail-fast: true - env: - version: ${{ needs.set-product-version.outputs.product-version }} - zip_name: consul_${{ needs.set-product-version.outputs.product-version }}_linux_${{ matrix.arch }}.zip - - name: Verify ${{ matrix.arch }} linux binary - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - if: ${{ endsWith(github.repository, '-enterprise') || matrix.arch != 's390x' }} - - - name: Download ${{ matrix.arch }} zip - if: ${{ endsWith(github.repository, '-enterprise') || matrix.arch != 's390x' }} - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: ${{ env.zip_name }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0 - if: ${{ matrix.arch == 'arm' || matrix.arch == 'arm64' }} - with: - # this should be a comma-separated string as opposed to an array - platforms: arm,arm64 - - - name: Run verification for ${{ matrix.arch }} binary - if: ${{ endsWith(github.repository, '-enterprise') || matrix.arch != 's390x' }} - run: .github/scripts/verify_artifact.sh ${{ env.zip_name }} v${{ env.version }} - - verify-darwin: - needs: - - set-product-version - - build-darwin - runs-on: macos-latest - strategy: - fail-fast: true - env: - version: ${{needs.set-product-version.outputs.product-version}} - zip_name: consul_${{ needs.set-product-version.outputs.product-version }}_darwin_amd64.zip - - name: Verify amd64 darwin binary - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - - name: Download amd64 darwin zip - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: ${{ env.zip_name }} - - - name: Unzip amd64 darwin zip - run: unzip ${{ env.zip_name }} - - - name: Run verification for amd64 darwin binary - run: .github/scripts/verify_bin.sh ./consul v${{ env.version }} - - verify-linux-packages-deb: - needs: - - build - - set-product-version - runs-on: ubuntu-latest - strategy: - matrix: - include: - - { arch: "i386" } - - { arch: "armhf" } - - { arch: "amd64" } - - { arch: "arm64" } - # fail-fast: true - env: - version: ${{ needs.set-product-version.outputs.product-version }} - - name: Verify ${{ matrix.arch }} debian package - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - - name: Set package version - run: | - echo "pkg_version=$(echo ${{ needs.set-product-version.outputs.product-version }} | sed 's/\-/~/g')" >> $GITHUB_ENV - - - name: Set package name - run: | - echo "pkg_name=consul_${{ env.pkg_version }}-1_${{ matrix.arch }}.deb" >> $GITHUB_ENV - - - name: Download workflow artifacts - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: ${{ env.pkg_name }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0 - with: - platforms: all - - - name: Verify ${{ matrix.arch }} debian package - run: ./.github/scripts/verify_artifact.sh ${{ env.pkg_name }} v${{ env.version }} - - verify-linux-packages-rpm: - needs: - - build - - set-product-version - runs-on: ubuntu-latest - strategy: - matrix: - include: - - { arch: "i386" } - - { arch: "x86_64" } - # TODO(eculver): re-enable when there is a smaller verification container available - # - { arch: "armv7hl" } - # - { arch: "aarch64" } - env: - version: ${{ needs.set-product-version.outputs.product-version }} - - name: Verify ${{ matrix.arch }} rpm - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - - name: Set package version - run: | - echo "pkg_version=$(echo ${{ needs.set-product-version.outputs.product-version }} | sed 's/\-/~/g')" >> $GITHUB_ENV - - - name: Set package name - run: | - echo "pkg_name=consul-${{ env.pkg_version }}-1.${{ matrix.arch }}.rpm" >> $GITHUB_ENV - - - name: Download workflow artifacts - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: ${{ env.pkg_name }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0 - with: - platforms: all - - - name: Verify ${{ matrix.arch }} rpm - run: ./.github/scripts/verify_artifact.sh ${{ env.pkg_name }} v${{ env.version }} +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: build +# +#on: +# push: +# # Sequence of patterns matched against refs/heads +# branches: +# # Push events on the main branch +# - main +# - release/** +# +#env: +# PKG_NAME: consul +# # TODO(spatel): CE refactor +# METADATA: oss +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +#jobs: +# get-go-version: +# uses: ./.github/workflows/reusable-get-go-version.yml +# +# set-product-version: +# runs-on: ubuntu-latest +# outputs: +# product-version: ${{ steps.set-product-version.outputs.product-version }} +# base-product-version: ${{ steps.set-product-version.outputs.base-product-version }} +# product-date: ${{ steps.get-product-version.outputs.product-date }} +# pre-version: ${{ steps.set-product-version.outputs.prerelease-product-version }} +# shared-ldflags: ${{ steps.shared-ldflags.outputs.shared-ldflags }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # action-set-product-version implicitly sets fields like 'product-version' using version/VERSION +# # https://github.com/hashicorp/actions-set-product-version +# - name: set product version +# id: set-product-version +# uses: hashicorp/actions-set-product-version@v2 +# - name: get product version +# id: get-product-version +# run: | +# CONSUL_DATE=$(build-support/scripts/build-date.sh) +# echo "product-date=${CONSUL_DATE}" >> "$GITHUB_OUTPUT" +# +# - name: Set shared -ldflags +# id: shared-ldflags +# run: | +# T="github.com/hashicorp/consul/version" +# echo "shared-ldflags=-X ${T}.GitCommit=${GITHUB_SHA::8} \ +# -X ${T}.GitDescribe=${{ steps.set-product-version.outputs.product-version }} \ +# -X ${T}.BuildDate=${{ steps.get-product-version.outputs.product-date }} \ +# " >> "$GITHUB_OUTPUT" +# validate-outputs: +# needs: set-product-version +# runs-on: ubuntu-latest +# steps: +# - name: Validate Outputs +# run: | +# echo "Product Version: ${{ needs.set-product-version.outputs.product-version }}" +# echo "Base Product Version: ${{ needs.set-product-version.outputs.base-product-version }}" +# echo "Product Metadata: ${{ env.METADATA }}" +# echo "Product Date: ${{ needs.set-product-version.outputs.product-date }}" +# echo "Prerelease Version: ${{ needs.set-product-version.outputs.pre-version }}" +# echo "Ldflags: ${{ needs.set-product-version.outputs.shared-ldflags }}" +# +# generate-metadata-file: +# needs: set-product-version +# runs-on: ubuntu-latest +# outputs: +# filepath: ${{ steps.generate-metadata-file.outputs.filepath }} +# steps: +# - name: 'Checkout directory' +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# - name: Generate metadata file +# id: generate-metadata-file +# uses: hashicorp/actions-generate-metadata@v1 +# with: +# version: ${{ needs.set-product-version.outputs.product-version }} +# product: ${{ env.PKG_NAME }} +# +# - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: metadata.json +# path: ${{ steps.generate-metadata-file.outputs.filepath }} +# +# build: +# needs: +# - set-product-version +# - get-go-version +# runs-on: ubuntu-latest +# strategy: +# matrix: +# include: +# - {goos: "linux", goarch: "386"} +# - {goos: "linux", goarch: "amd64"} +# - {goos: "linux", goarch: "arm"} +# - {goos: "linux", goarch: "arm64"} +# - {goos: "darwin", goarch: "amd64"} +# - {goos: "darwin", goarch: "arm64"} +# - {goos: "freebsd", goarch: "386"} +# - {goos: "freebsd", goarch: "amd64"} +# - {goos: "windows", goarch: "386"} +# - {goos: "windows", goarch: "amd64"} +# - {goos: "solaris", goarch: "amd64"} +# fail-fast: true +# +# name: Go ${{ needs.get-go-version.outputs.go-version }} ${{ matrix.goos }} ${{ matrix.goarch }} build +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# - name: Setup with node and yarn +# uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: '18' +# cache: 'yarn' +# cache-dependency-path: 'ui/yarn.lock' +# +# - name: Build UI +# run: | +# CONSUL_VERSION=${{ needs.set-product-version.outputs.product-version }} +# CONSUL_DATE=${{ needs.set-product-version.outputs.product-date }} +# CONSUL_BINARY_TYPE=${CONSUL_BINARY_TYPE} +# CONSUL_COPYRIGHT_YEAR=$(git show -s --format=%cd --date=format:%Y HEAD) +# echo "consul_version is ${CONSUL_VERSION}" +# echo "consul_date is ${CONSUL_DATE}" +# echo "consul binary type is ${CONSUL_BINARY_TYPE}" +# echo "consul copyright year is ${CONSUL_COPYRIGHT_YEAR}" +# cd ui && make && cd .. +# rm -rf agent/uiserver/dist +# mv ui/packages/consul-ui/dist agent/uiserver/ +# - name: Go Build +# env: +# PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }} +# PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.pre-version }} +# CGO_ENABLED: "0" +# GOLDFLAGS: "${{needs.set-product-version.outputs.shared-ldflags}}" +# uses: hashicorp/actions-go-build@make-clean-flag-optional +# with: +# product_name: ${{ env.PKG_NAME }} +# product_version: ${{ needs.set-product-version.outputs.product-version }} +# go_version: ${{ needs.get-go-version.outputs.go-version }} +# os: ${{ matrix.goos }} +# arch: ${{ matrix.goarch }} +# reproducible: nope +# clean: false +# instructions: |- +# cp LICENSE $TARGET_DIR/LICENSE.txt +# go build -ldflags="$GOLDFLAGS" -o "$BIN_PATH" -trimpath -buildvcs=false +# +# - name: Copy license file +# if: ${{ !endsWith(github.repository, '-enterprise') }} +# env: +# LICENSE_DIR: ".release/linux/package/usr/share/doc/${{ env.PKG_NAME }}" +# run: | +# mkdir -p "$LICENSE_DIR" +# cp LICENSE "$LICENSE_DIR/LICENSE.txt" +# +# - name: Package +# if: ${{ matrix.goos == 'linux' }} +# uses: hashicorp/actions-packaging-linux@v1 +# with: +# name: ${{ github.event.repository.name }} +# description: "Consul is a distributed, highly available, and data center aware solution to connect and configure applications across dynamic, distributed infrastructure. " +# arch: ${{ matrix.goarch }} +# version: ${{ needs.set-product-version.outputs.product-version }} +# maintainer: "HashiCorp" +# homepage: "https://github.com/hashicorp/consul" +# license: "BSL-1.1" +# binary: "dist/${{ env.PKG_NAME }}" +# deb_depends: "openssl" +# rpm_depends: "openssl" +# config_dir: ".release/linux/package" +# preinstall: ".release/linux/preinstall" +# postinstall: ".release/linux/postinstall" +# preremove: ".release/linux/preremove" +# postremove: ".release/linux/postremove" +# +# - name: Set Package Names +# if: ${{ matrix.goos == 'linux' }} +# run: | +# echo "RPM_PACKAGE=$(basename out/*.rpm)" >> $GITHUB_ENV +# echo "DEB_PACKAGE=$(basename out/*.deb)" >> $GITHUB_ENV +# +# - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# if: ${{ matrix.goos == 'linux' }} +# with: +# name: ${{ env.RPM_PACKAGE }} +# path: out/${{ env.RPM_PACKAGE }} +# +# - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# if: ${{ matrix.goos == 'linux' }} +# with: +# name: ${{ env.DEB_PACKAGE }} +# path: out/${{ env.DEB_PACKAGE }} +# +# build-s390x: +# needs: +# - set-product-version +# - get-go-version +# if: ${{ endsWith(github.repository, '-enterprise') }} +# runs-on: ubuntu-latest +# strategy: +# matrix: +# include: +# - {goos: "linux", goarch: "s390x"} +# fail-fast: true +# +# name: Go ${{ needs.get-go-version.outputs.go-version }} ${{ matrix.goos }} ${{ matrix.goarch }} build +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# - name: Setup with node and yarn +# uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: '18' +# cache: 'yarn' +# cache-dependency-path: 'ui/yarn.lock' +# +# - name: Build UI +# run: | +# CONSUL_VERSION=${{ needs.set-product-version.outputs.product-version }} +# CONSUL_DATE=${{ needs.set-product-version.outputs.product-date }} +# CONSUL_BINARY_TYPE=${CONSUL_BINARY_TYPE} +# CONSUL_COPYRIGHT_YEAR=$(git show -s --format=%cd --date=format:%Y HEAD) +# echo "consul_version is ${CONSUL_VERSION}" +# echo "consul_date is ${CONSUL_DATE}" +# echo "consul binary type is ${CONSUL_BINARY_TYPE}" +# echo "consul copyright year is ${CONSUL_COPYRIGHT_YEAR}" +# cd ui && make && cd .. +# rm -rf agent/uiserver/dist +# mv ui/packages/consul-ui/dist agent/uiserver/ +# - name: Go Build +# env: +# PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }} +# PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.pre-version }} +# CGO_ENABLED: "0" +# GOLDFLAGS: "${{needs.set-product-version.outputs.shared-ldflags}}" +# uses: hashicorp/actions-go-build@make-clean-flag-optional +# with: +# product_name: ${{ env.PKG_NAME }} +# product_version: ${{ needs.set-product-version.outputs.product-version }} +# go_version: ${{ needs.get-go-version.outputs.go-version }} +# os: ${{ matrix.goos }} +# arch: ${{ matrix.goarch }} +# reproducible: nope +# clean: false +# instructions: |- +# cp LICENSE $TARGET_DIR/LICENSE.txt +# go build -ldflags="$GOLDFLAGS" -o "$BIN_PATH" -trimpath -buildvcs=false +# +# build-docker: +# name: Docker ${{ matrix.arch }} build +# needs: +# - set-product-version +# - build +# runs-on: ubuntu-latest +# strategy: +# matrix: +# include: +# - { arch: "386" } +# - { arch: "arm" } +# - { arch: "amd64" } +# - { arch: "arm64" } +# env: +# repo: ${{github.event.repository.name}} +# version: ${{needs.set-product-version.outputs.product-version}} +# +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# # Strip everything but MAJOR.MINOR from the version string and add a `-dev` suffix +# # This naming convention will be used ONLY for per-commit dev images +# - name: Set docker dev tag +# run: | +# echo "full_dev_tag=${{ env.version }}" +# echo "full_dev_tag=${{ env.version }}" >> $GITHUB_ENV +# echo "minor_dev_tag=$(echo ${{ env.version }}| sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+(-[0-9a-zA-Z\+\.]+)?$/\1\2/')" +# echo "minor_dev_tag=$(echo ${{ env.version }}| sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+(-[0-9a-zA-Z\+\.]+)?$/\1\2/')" >> $GITHUB_ENV +# +# - name: Docker Build (Action) +# uses: hashicorp/actions-docker-build@v2 +# with: +# version: ${{env.version}} +# target: default +# arch: ${{matrix.arch}} +# tags: | +# docker.io/hashicorp/${{env.repo}}:${{env.version}} +# public.ecr.aws/hashicorp/${{env.repo}}:${{env.version}} +# dev_tags: | +# docker.io/hashicorppreview/${{ env.repo }}:${{ env.full_dev_tag }} +# docker.io/hashicorppreview/${{ env.repo }}:${{ env.full_dev_tag }}-${{ github.sha }} +# docker.io/hashicorppreview/${{ env.repo }}:${{ env.minor_dev_tag }} +# docker.io/hashicorppreview/${{ env.repo }}:${{ env.minor_dev_tag }}-${{ github.sha }} +# smoke_test: .github/scripts/verify_docker.sh v${{ env.version }} +# +# build-docker-ubi-dockerhub: +# name: Docker Build UBI Images +# needs: +# - set-product-version +# - build +# runs-on: ubuntu-latest +# env: +# repo: ${{github.event.repository.name}} +# version: ${{needs.set-product-version.outputs.product-version}} +# +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# # Strip everything but MAJOR.MINOR from the version string and add a `-dev` suffix +# # This naming convention will be used ONLY for per-commit dev images +# - name: Set docker dev tag +# run: | +# echo "full_dev_tag=${{ env.version }}" +# echo "full_dev_tag=${{ env.version }}" >> $GITHUB_ENV +# echo "minor_dev_tag=$(echo ${{ env.version }}| sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+(-[0-9a-zA-Z\+\.]+)?$/\1\2/')" +# echo "minor_dev_tag=$(echo ${{ env.version }}| sed -E 's/([0-9]+\.[0-9]+)\.[0-9]+(-[0-9a-zA-Z\+\.]+)?$/\1\2/')" >> $GITHUB_ENV +# +# - uses: hashicorp/actions-docker-build@v2 +# with: +# version: ${{env.version}} +# target: ubi +# arch: amd64 +# tags: | +# docker.io/hashicorp/${{env.repo}}:${{env.version}}-ubi +# public.ecr.aws/hashicorp/${{env.repo}}:${{env.version}}-ubi +# dev_tags: | +# docker.io/hashicorppreview/${{ env.repo }}:${{ env.full_dev_tag }}-ubi +# docker.io/hashicorppreview/${{ env.repo }}:${{ env.full_dev_tag }}-ubi-${{ github.sha }} +# docker.io/hashicorppreview/${{ env.repo }}:${{ env.minor_dev_tag }}-ubi +# docker.io/hashicorppreview/${{ env.repo }}:${{ env.minor_dev_tag }}-ubi-${{ github.sha }} +# smoke_test: .github/scripts/verify_docker.sh v${{ env.version }} +# redhat_tag: quay.io/redhat-isv-containers/60f9fdbec3a80eac643abedf:${{env.version}}-ubi +# +# verify-linux: +# needs: +# - set-product-version +# - build +# runs-on: ubuntu-latest +# strategy: +# matrix: +# include: +# - { arch: "386" } +# - { arch: "arm" } +# - { arch: "amd64" } +# - { arch: "arm64" } +# fail-fast: true +# env: +# version: ${{ needs.set-product-version.outputs.product-version }} +# zip_name: consul_${{ needs.set-product-version.outputs.product-version }}_linux_${{ matrix.arch }}.zip +# +# name: Verify ${{ matrix.arch }} linux binary +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# if: ${{ endsWith(github.repository, '-enterprise') || matrix.arch != 's390x' }} +# +# - name: Download ${{ matrix.arch }} zip +# if: ${{ endsWith(github.repository, '-enterprise') || matrix.arch != 's390x' }} +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: ${{ env.zip_name }} +# +# - name: Set up QEMU +# uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 +# if: ${{ matrix.arch == 'arm' || matrix.arch == 'arm64' }} +# with: +# # this should be a comma-separated string as opposed to an array +# platforms: arm,arm64 +# +# - name: Run verification for ${{ matrix.arch }} binary +# if: ${{ endsWith(github.repository, '-enterprise') || matrix.arch != 's390x' }} +# run: .github/scripts/verify_artifact.sh ${{ env.zip_name }} v${{ env.version }} +# +# verify-linux-packages-deb: +# needs: +# - build +# - set-product-version +# runs-on: ubuntu-latest +# strategy: +# matrix: +# include: +# - { arch: "i386" } +# - { arch: "armhf" } +# - { arch: "amd64" } +# - { arch: "arm64" } +# # fail-fast: true +# env: +# version: ${{ needs.set-product-version.outputs.product-version }} +# +# name: Verify ${{ matrix.arch }} debian package +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# - name: Set package version +# run: | +# echo "pkg_version=$(echo ${{ needs.set-product-version.outputs.product-version }} | sed 's/\-/~/g')" >> $GITHUB_ENV +# +# - name: Set package name +# run: | +# echo "pkg_name=consul_${{ env.pkg_version }}-1_${{ matrix.arch }}.deb" >> $GITHUB_ENV +# +# - name: Download workflow artifacts +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: ${{ env.pkg_name }} +# +# - name: Set up QEMU +# uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 +# with: +# platforms: all +# +# - name: Verify ${{ matrix.arch }} debian package +# run: ./.github/scripts/verify_artifact.sh ${{ env.pkg_name }} v${{ env.version }} +# +# verify-linux-packages-rpm: +# needs: +# - build +# - set-product-version +# runs-on: ubuntu-latest +# strategy: +# matrix: +# include: +# - { arch: "i386" } +# - { arch: "x86_64" } +# # TODO(eculver): re-enable when there is a smaller verification container available +# # - { arch: "armv7hl" } +# # - { arch: "aarch64" } +# env: +# version: ${{ needs.set-product-version.outputs.product-version }} +# +# name: Verify ${{ matrix.arch }} rpm +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# - name: Set package version +# run: | +# echo "pkg_version=$(echo ${{ needs.set-product-version.outputs.product-version }} | sed 's/\-/~/g')" >> $GITHUB_ENV +# +# - name: Set package name +# run: | +# echo "pkg_name=consul-${{ env.pkg_version }}-1.${{ matrix.arch }}.rpm" >> $GITHUB_ENV +# +# - name: Download workflow artifacts +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: ${{ env.pkg_name }} +# +# - name: Set up QEMU +# uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 +# with: +# platforms: all +# +# - name: Verify ${{ matrix.arch }} rpm +# run: ./.github/scripts/verify_artifact.sh ${{ env.pkg_name }} v${{ env.version }} diff --git a/.github/workflows/ce-merge-trigger.yml b/.github/workflows/ce-merge-trigger.yml index 30a6b5fd90df..49fb2156e8cc 100644 --- a/.github/workflows/ce-merge-trigger.yml +++ b/.github/workflows/ce-merge-trigger.yml @@ -1,30 +1,35 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Trigger Community Edition to Enterprise Merge -on: - pull_request_target: - types: - - closed - branches: - - main - - release/** - -jobs: - trigger-ce-merge: - # run this only on merge events in CE repo - if: ${{ github.event.pull_request.merged && github.repository == 'hashicorp/consul' }} - runs-on: ubuntu-latest - steps: - - name: Trigger Merge - env: - GIT_REF: ${{ github.ref_name }} - GIT_SHA: ${{ github.sha }} - GH_PAT: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - GIT_ACTOR: ${{ github.actor }} - # TODO(spatel): CE refactor - run: | - curl -H "Authorization: token $GH_PAT" \ - -H 'Accept: application/json' \ - -d "{\"event_type\": \"oss-merge\", \"client_payload\": {\"git-ref\": \"${GIT_REF}\", \"git-sha\": \"${GIT_SHA}\", \"git-actor\": \"${GIT_ACTOR}\" }}" \ - "https://api.github.com/repos/hashicorp/consul-enterprise/dispatches" +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Trigger Community Edition to Enterprise Merge +#on: +# pull_request_target: +# types: +# - closed +# branches: +# - main +# - release/** +# - '!release/1.18**' +# - '!release/1.17**' +# - '!release/1.16**' +# - '!release/1.15**' +# +# +#jobs: +# trigger-ce-merge: +# # run this only on merge events in CE repo +# if: ${{ github.event.pull_request.merged && github.repository == 'hashicorp/consul' }} +# runs-on: ubuntu-latest +# steps: +# - name: Trigger Merge +# env: +# GIT_REF: ${{ github.ref_name }} +# GIT_SHA: ${{ github.sha }} +# GH_PAT: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# GIT_ACTOR: ${{ github.actor }} +# # TODO(spatel): CE refactor +# run: | +# curl -H "Authorization: token $GH_PAT" \ +# -H 'Accept: application/json' \ +# -d "{\"event_type\": \"oss-merge\", \"client_payload\": {\"git-ref\": \"${GIT_REF}\", \"git-sha\": \"${GIT_SHA}\", \"git-actor\": \"${GIT_ACTOR}\" }}" \ +# "https://api.github.com/repos/hashicorp/consul-enterprise/dispatches" diff --git a/.github/workflows/changelog-checker.yml b/.github/workflows/changelog-checker.yml index 62b906eda3e6..d7ba05c73163 100644 --- a/.github/workflows/changelog-checker.yml +++ b/.github/workflows/changelog-checker.yml @@ -1,34 +1,34 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -# This workflow checks that there is either a 'pr/no-changelog' label applied to a PR -# or there is a .changelog/.txt file associated with a PR for a changelog entry - -name: Changelog Checker - -on: - pull_request: - types: [opened, synchronize, labeled] - # Runs on PRs to main and all release branches - branches: - - main - - release/* - -jobs: - # checks that a .changelog entry is present for a PR - changelog-check: - # If there a `pr/no-changelog` label we ignore this check. Also, we ignore PRs created by the bot assigned to `backport-assistant` - if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/no-changelog') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 # by default the checkout action doesn't checkout all branches - - name: Check for changelog entry in diff - run: ./.github/scripts/changelog_checker.sh - env: - GITHUB_BASE_REF: ${{ github.event.pull_request.base.ref }} - GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} - PR_NUMBER: ${{ github.event.pull_request.number }} +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +## This workflow checks that there is either a 'pr/no-changelog' label applied to a PR +## or there is a .changelog/.txt file associated with a PR for a changelog entry +# +#name: Changelog Checker +# +#on: +# pull_request: +# types: [opened, synchronize, labeled] +# # Runs on PRs to main and all release branches +# branches: +# - main +# - release/* +# +#jobs: +# # checks that a .changelog entry is present for a PR +# changelog-check: +# # If there a `pr/no-changelog` label we ignore this check. Also, we ignore PRs created by the bot assigned to `backport-assistant` +# if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/no-changelog') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" +# runs-on: ubuntu-latest +# +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ github.event.pull_request.head.sha }} +# fetch-depth: 0 # by default the checkout action doesn't checkout all branches +# - name: Check for changelog entry in diff +# run: ./.github/scripts/changelog_checker.sh +# env: +# GITHUB_BASE_REF: ${{ github.event.pull_request.base.ref }} +# GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} +# PR_NUMBER: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/embedded-asset-checker.yml b/.github/workflows/embedded-asset-checker.yml index 38879945e209..0f639cdfe5c2 100644 --- a/.github/workflows/embedded-asset-checker.yml +++ b/.github/workflows/embedded-asset-checker.yml @@ -1,40 +1,40 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -# This workflow detects if there is a diff in the `agent/uiserver/dist` directory -# which is used by Consul to serve its embedded UI. -# `agent/uiserver/dist` should not be manually updated. - -name: Embedded Asset Checker - -on: - pull_request: - types: [opened, synchronize, labeled, unlabeled, reopened] - # Runs on PRs to main and all release branches - branches: - - main - - release/* - -jobs: - dist-check: - if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/update-ui-assets') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 # by default the checkout action doesn't checkout all branches - - name: Check for agent/uiserver/dist dir change in diff - run: | - dist_files=$(git --no-pager diff --name-only HEAD "$(git merge-base HEAD "origin/${{ github.event.pull_request.base.ref }}")" -- agent/uiserver/dist) - if [[ -z "${dist_files}" ]]; then - exit 0 - fi - - echo "Found diffs in dir agent/uiserver/dist" - github_message="This PR has diffs in \`agent/uiserver/dist\`. If the changes are intentional, add the label \`pr/update-ui-assets\`. Otherwise, revert changes to \`agent/uiserver/dist\`." - curl -s -H "Authorization: token ${{ secrets.PR_COMMENT_TOKEN }}" \ - -X POST \ - -d "{ \"body\": \"${github_message}\"}" \ - "https://api.github.com/repos/${GITHUB_REPOSITORY}/issues/${{ github.event.pull_request.number }}/comments" - exit 1 +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +## This workflow detects if there is a diff in the `agent/uiserver/dist` directory +## which is used by Consul to serve its embedded UI. +## `agent/uiserver/dist` should not be manually updated. +# +#name: Embedded Asset Checker +# +#on: +# pull_request: +# types: [opened, synchronize, labeled, unlabeled, reopened] +# # Runs on PRs to main and all release branches +# branches: +# - main +# - release/* +# +#jobs: +# dist-check: +# if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/update-ui-assets') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ github.event.pull_request.head.sha }} +# fetch-depth: 0 # by default the checkout action doesn't checkout all branches +# - name: Check for agent/uiserver/dist dir change in diff +# run: | +# dist_files=$(git --no-pager diff --name-only HEAD "$(git merge-base HEAD "origin/${{ github.event.pull_request.base.ref }}")" -- agent/uiserver/dist) +# if [[ -z "${dist_files}" ]]; then +# exit 0 +# fi +# +# echo "Found diffs in dir agent/uiserver/dist" +# github_message="This PR has diffs in \`agent/uiserver/dist\`. If the changes are intentional, add the label \`pr/update-ui-assets\`. Otherwise, revert changes to \`agent/uiserver/dist\`." +# curl -s -H "Authorization: token ${{ secrets.PR_COMMENT_TOKEN }}" \ +# -X POST \ +# -d "{ \"body\": \"${github_message}\"}" \ +# "https://api.github.com/repos/${GITHUB_REPOSITORY}/issues/${{ github.event.pull_request.number }}/comments" +# exit 1 diff --git a/.github/workflows/fossa-scan.yaml b/.github/workflows/fossa-scan.yaml new file mode 100644 index 000000000000..50bb00e6260e --- /dev/null +++ b/.github/workflows/fossa-scan.yaml @@ -0,0 +1,26 @@ +name: FOSSA Scan +on: + pull_request: + +permissions: + repository-projects: read + contents: write + id-token: write + packages: write + actions: write + +jobs: + fossa_scan: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Install FOSSA CLI + run: | + curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install-latest.sh | bash ; + export FOSSA_API_KEY=${{ secrets.FOSSA_API_KEY }}; + fossa analyze --experimental-force-first-party-scans --debug --branch test-consul-v1-20-1 --unpack-archives diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 550fddd5d15f..203515b3c5d3 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -1,142 +1,182 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: frontend - -on: - push: - paths: - - ui/** - -permissions: - contents: read - -jobs: - setup: - name: Setup - runs-on: ubuntu-latest - outputs: - compute-small: ${{ steps.setup-outputs.outputs.compute-small }} - compute-medium: ${{ steps.setup-outputs.outputs.compute-medium }} - compute-large: ${{ steps.setup-outputs.outputs.compute-large }} - compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - id: setup-outputs - name: Setup outputs - run: ./.github/scripts/get_runner_classes.sh - - workspace-tests: - needs: setup - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - defaults: - run: - working-directory: ui - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: '18' - - - name: Install Yarn - run: corepack enable - - # Install dependencies. - - name: install yarn packages - working-directory: ui - run: make deps - - - run: make test-workspace - - node-tests: - needs: setup - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: '18' - - - name: Install Yarn - run: corepack enable - - # Install dependencies. - - name: install yarn packages - working-directory: ui - run: make deps - - - run: make test-node - working-directory: ui/packages/consul-ui - - ember-build-test: - needs: setup - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} - strategy: - matrix: - partition: [1, 2, 3, 4] - env: - EMBER_TEST_REPORT: test-results/report-ce.xml # outputs test report for CI test summary - EMBER_TEST_PARALLEL: true # enables test parallelization with ember-exam - CONSUL_NSPACES_ENABLED: ${{ endsWith(github.repository, '-enterprise') && 1 || 0 }} # NOTE: this should be 1 in ENT. - JOBS: 2 # limit parallelism for broccoli-babel-transpiler - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: '18' - - - name: Install Yarn - run: corepack enable - - - name: Install Chrome - uses: browser-actions/setup-chrome@c485fa3bab6be59dce18dbc18ef6ab7cbc8ff5f1 # v1.2.0 - - - name: Install dependencies - working-directory: ui - run: make deps - - - name: Build CI - working-directory: ui/packages/consul-ui - run: make build-ci - - - name: Ember exam - working-directory: ui/packages/consul-ui - run: node_modules/.bin/ember exam --split=4 --partition=${{ matrix.partition }} --path dist --silent -r xunit - - - name: Test Coverage CI - working-directory: ui/packages/consul-ui - run: make test-coverage-ci - - # This is job is required for branch protection as a required gihub check - # because GitHub actions show up as checks at the job level and not the - # workflow level. This is currently a feature request: - # https://github.com/orgs/community/discussions/12395 - # - # This job must: - # - be placed after the fanout of a workflow so that everything fans back in - # to this job. - # - "need" any job that is part of the fan out / fan in - # - implement the if logic because we have conditional jobs - # (go-test-enteprise) that this job needs and this would potentially get - # skipped if a previous job got skipped. So we use the if clause to make - # sure it does not get skipped. - - frontend-success: - needs: - - setup - - workspace-tests - - node-tests - - ember-build-test - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - if: ${{ always() }} - steps: - - name: evaluate upstream job results - run: | - # exit 1 if failure or cancelled result for any upstream job - if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then - printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" - exit 1 - fi +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: frontend +# +#on: +# push: +# paths: +# - ui/** +# +#permissions: +# contents: read +# +#jobs: +# setup: +# name: Setup +# runs-on: ubuntu-latest +# outputs: +# compute-small: ${{ steps.setup-outputs.outputs.compute-small }} +# compute-medium: ${{ steps.setup-outputs.outputs.compute-medium }} +# compute-large: ${{ steps.setup-outputs.outputs.compute-large }} +# compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# - id: setup-outputs +# name: Setup outputs +# run: ./.github/scripts/get_runner_classes.sh +# +# workspace-tests: +# needs: setup +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# defaults: +# run: +# working-directory: ui +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: '18' +# +# - name: Install Yarn +# run: corepack enable +# +# # Install dependencies. +# - name: install yarn packages +# working-directory: ui +# run: make deps +# +# - run: make test-workspace +# +# node-tests: +# needs: setup +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: '18' +# +# - name: Install Yarn +# run: corepack enable +# +# # Install dependencies. +# - name: install yarn packages +# working-directory: ui +# run: make deps +# +# - run: make test-node +# working-directory: ui/packages/consul-ui +# +# ember-build-test: +# needs: setup +# if: ${{ !endsWith(github.repository, '-enterprise') }} +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} +# strategy: +# matrix: +# partition: [1, 2, 3, 4] +# env: +# EMBER_TEST_REPORT: test-results/report-ce.xml # outputs test report for CI test summary +# EMBER_TEST_PARALLEL: true # enables test parallelization with ember-exam +# CONSUL_NSPACES_ENABLED: 0 # NOTE: this should be 1 in ENT. +# JOBS: 2 # limit parallelism for broccoli-babel-transpiler +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: '18' +# +# - name: Install Yarn +# run: corepack enable +# +# - name: Install Chrome +# uses: browser-actions/setup-chrome@82b9ce628cc5595478a9ebadc480958a36457dc2 # v1.6.0 +# +# - name: Install dependencies +# working-directory: ui +# run: make deps +# +# - name: Build CI +# working-directory: ui/packages/consul-ui +# run: make build-ci +# +# - name: Ember exam +# working-directory: ui/packages/consul-ui +# run: node_modules/.bin/ember exam --split=4 --partition=${{ matrix.partition }} --path dist --silent -r xunit +# +# - name: Test Coverage CI +# working-directory: ui/packages/consul-ui +# run: make test-coverage-ci +# +# ember-build-test-ent: +# needs: setup +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} +# strategy: +# matrix: +# partition: [1, 2, 3, 4] +# env: +# EMBER_TEST_REPORT: test-results/report-ce.xml # outputs test report for CI test summary +# EMBER_TEST_PARALLEL: true # enables test parallelization with ember-exam +# CONSUL_NSPACES_ENABLED: 1 # NOTE: this should be 1 in ENT. +# JOBS: 2 # limit parallelism for broccoli-babel-transpiler +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: '18' +# +# - name: Install Yarn +# run: corepack enable +# +# - name: Install Chrome +# uses: browser-actions/setup-chrome@82b9ce628cc5595478a9ebadc480958a36457dc2 # v1.6.0 +# +# - name: Install dependencies +# working-directory: ui +# run: make deps +# +# - name: Build CI +# working-directory: ui/packages/consul-ui +# run: make build-ci +# +# - name: Ember exam +# working-directory: ui/packages/consul-ui +# run: node_modules/.bin/ember exam --split=4 --partition=${{ matrix.partition }} --path dist --silent -r xunit +# +# - name: Test Coverage CI +# working-directory: ui/packages/consul-ui +# run: make test-coverage-ci +# # This is job is required for branch protection as a required gihub check +# # because GitHub actions show up as checks at the job level and not the +# # workflow level. This is currently a feature request: +# # https://github.com/orgs/community/discussions/12395 +# # +# # This job must: +# # - be placed after the fanout of a workflow so that everything fans back in +# # to this job. +# # - "need" any job that is part of the fan out / fan in +# # - implement the if logic because we have conditional jobs +# # (go-test-enteprise) that this job needs and this would potentially get +# # skipped if a previous job got skipped. So we use the if clause to make +# # sure it does not get skipped. +# +# frontend-success: +# needs: +# - setup +# - workspace-tests +# - node-tests +# - ember-build-test +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# if: ${{ always() }} +# steps: +# - name: evaluate upstream job results +# run: | +# # exit 1 if failure or cancelled result for any upstream job +# if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then +# printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" +# exit 1 +# fi diff --git a/.github/workflows/go-tests.yml b/.github/workflows/go-tests.yml index 20452515740f..525fc4427736 100644 --- a/.github/workflows/go-tests.yml +++ b/.github/workflows/go-tests.yml @@ -1,518 +1,598 @@ -name: go-tests - -on: - pull_request: - branches-ignore: - - stable-website - - 'docs/**' - - 'ui/**' - - 'mktg-**' # Digital Team Terraform-generated branches' prefix - - 'backport/docs/**' - - 'backport/ui/**' - - 'backport/mktg-**' - push: - branches: - # Push events on the main branch - - main - - release/** - -permissions: - contents: read - -env: - TEST_RESULTS: /tmp/test-results - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - SKIP_CHECK_BRANCH: ${{ github.head_ref || github.ref_name }} - -# concurrency -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} - cancel-in-progress: true - -jobs: - conditional-skip: - runs-on: ubuntu-latest - name: Get files changed and conditionally skip CI - outputs: - skip-ci: ${{ steps.read-files.outputs.skip-ci }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - fetch-depth: 0 - - name: Get changed files - id: read-files - run: ./.github/scripts/filter_changed_files_go_test.sh - - setup: - needs: [conditional-skip] - name: Setup - if: needs.conditional-skip.outputs.skip-ci != 'true' - runs-on: ubuntu-latest - outputs: - compute-small: ${{ steps.setup-outputs.outputs.compute-small }} - compute-medium: ${{ steps.setup-outputs.outputs.compute-medium }} - compute-large: ${{ steps.setup-outputs.outputs.compute-large }} - compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - id: setup-outputs - name: Setup outputs - run: ./.github/scripts/get_runner_classes.sh - - check-go-mod: - needs: - - setup - uses: ./.github/workflows/reusable-check-go-mod.yml - with: - runs-on: ${{ needs.setup.outputs.compute-small }} - repository-name: ${{ github.repository }} - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - check-generated-protobuf: - needs: - - setup - runs-on: ${{ fromJSON(needs.setup.outputs.compute-medium) }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: make proto-tools - name: Install protobuf - - run: make proto-format - name: "Protobuf Format" - - run: make --always-make proto - - run: | - if ! git diff --exit-code; then - echo "Generated code was not updated correctly" - exit 1 - fi - - run: make proto-lint - name: "Protobuf Lint" - - name: Notify Slack - if: ${{ failure() }} - run: .github/scripts/notify_slack.sh - check-codegen: - needs: - - setup - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: make --always-make codegen - - run: | - if ! git diff --exit-code; then - echo "Generated code was not updated correctly" - exit 1 - fi - - name: Notify Slack - if: ${{ failure() }} - run: .github/scripts/notify_slack.sh - - lint-enums: - needs: - - setup - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: go install github.com/reillywatson/enumcover/cmd/enumcover@master && enumcover ./... - - name: Notify Slack - if: ${{ failure() }} - run: .github/scripts/notify_slack.sh - - lint-container-test-deps: - needs: - - setup - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: make lint-container-test-deps - - name: Notify Slack - if: ${{ failure() }} - run: .github/scripts/notify_slack.sh - - lint-consul-retry: - needs: - - setup - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: go install github.com/hashicorp/lint-consul-retry@master && lint-consul-retry - - name: Notify Slack - if: ${{ failure() }} - run: .github/scripts/notify_slack.sh - - lint: - needs: - - setup - uses: ./.github/workflows/reusable-lint.yml - with: - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - lint-32bit: - needs: - - setup - uses: ./.github/workflows/reusable-lint.yml - with: - go-arch: "386" - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - # create a development build - dev-build: - needs: - - setup - uses: ./.github/workflows/reusable-dev-build.yml - with: - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - # dev-build-s390x: - # if: ${{ endsWith(github.repository, '-enterprise') }} - # needs: - # - setup - # uses: ./.github/workflows/reusable-dev-build.yml - # with: - # uploaded-binary-name: 'consul-bin-s390x' - # runs-on: ${{ needs.setup.outputs.compute-large }} - # go-arch: "s390x" - # repository-name: ${{ github.repository }} - # secrets: - # elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - # dev-build-arm64: - # # only run on enterprise because GHA does not have arm64 runners in CE - # if: ${{ endsWith(github.repository, '-enterprise') }} - # needs: - # - setup - # uses: ./.github/workflows/reusable-dev-build.yml - # with: - # uploaded-binary-name: 'consul-bin-arm64' - # runs-on: ${{ needs.setup.outputs.compute-large }} - # go-arch: "arm64" - # repository-name: ${{ github.repository }} - # secrets: - # elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - # go-test-arm64: - # # only run on enterprise because GHA does not have arm64 runners in CE - # if: ${{ endsWith(github.repository, '-enterprise') }} - # needs: - # - setup - # - dev-build-arm64 - # uses: ./.github/workflows/reusable-unit-split.yml - # with: - # directory: . - # uploaded-binary-name: 'consul-bin-arm64' - # runner-count: 12 - # runs-on: "['self-hosted', 'ondemand', 'os=macos-arm', 'arm64']" - # go-test-flags: 'if ! [[ "$GITHUB_REF_NAME" =~ ^main$|^release/ ]]; then export GO_TEST_FLAGS="-short"; fi' - # repository-name: ${{ github.repository }} - # secrets: - # elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - # consul-license: ${{secrets.CONSUL_LICENSE}} - # datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" - - go-test-ce: - needs: - - setup - - dev-build - uses: ./.github/workflows/reusable-unit-split.yml - with: - directory: . - runner-count: 12 - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - go-tags: "" - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - consul-license: ${{secrets.CONSUL_LICENSE}} - datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" - - go-test-enterprise: - if: ${{ endsWith(github.repository, '-enterprise') }} - needs: - - setup - - dev-build - uses: ./.github/workflows/reusable-unit-split.yml - with: - directory: . - runner-count: 12 - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - consul-license: ${{secrets.CONSUL_LICENSE}} - datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" - - go-test-race: - needs: - - setup - - dev-build - uses: ./.github/workflows/reusable-unit.yml - with: - directory: . - go-test-flags: 'GO_TEST_FLAGS="-race -gcflags=all=-d=checkptr=0"' - package-names-command: "go list ./... | grep -E -v '^github.com/hashicorp/consul/agent(/consul|/local|/routine-leak-checker)?$' | grep -E -v '^github.com/hashicorp/consul(/command|/connect|/snapshot)'" - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - consul-license: ${{secrets.CONSUL_LICENSE}} - datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" - - go-test-32bit: - needs: - - setup - - dev-build - uses: ./.github/workflows/reusable-unit.yml - with: - directory: . - go-arch: "386" - go-test-flags: 'export GO_TEST_FLAGS="-short"' - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - consul-license: ${{secrets.CONSUL_LICENSE}} - datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" - - # go-test-s390x: - # if: ${{ endsWith(github.repository, '-enterprise') }} - # needs: - # - setup - # - dev-build-s390x - # uses: ./.github/workflows/reusable-unit.yml - # with: - # uploaded-binary-name: 'consul-bin-s390x' - # directory: . - # go-test-flags: 'export GO_TEST_FLAGS="-short"' - # runs-on: ${{ needs.setup.outputs.compute-large }} - # repository-name: ${{ github.repository }} - # go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" - # permissions: - # id-token: write # NOTE: this permission is explicitly required for Vault auth. - # contents: read - # secrets: - # elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - # consul-license: ${{secrets.CONSUL_LICENSE}} - # datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" - - go-test-envoyextensions: - needs: - - setup - - dev-build - uses: ./.github/workflows/reusable-unit.yml - with: - directory: envoyextensions - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - consul-license: ${{secrets.CONSUL_LICENSE}} - datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" - - go-test-troubleshoot: - needs: - - setup - - dev-build - uses: ./.github/workflows/reusable-unit.yml - with: - directory: troubleshoot - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - consul-license: ${{secrets.CONSUL_LICENSE}} - datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" - - go-test-api-1-19: - needs: - - setup - - dev-build - uses: ./.github/workflows/reusable-unit.yml - with: - directory: api - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" - go-version: "1.19" - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - consul-license: ${{secrets.CONSUL_LICENSE}} - datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" - - go-test-api-1-20: - needs: - - setup - - dev-build - uses: ./.github/workflows/reusable-unit.yml - with: - directory: api - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" - go-version: "1.20" - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - consul-license: ${{secrets.CONSUL_LICENSE}} - datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" - - go-test-sdk-1-19: - needs: - - setup - - dev-build - uses: ./.github/workflows/reusable-unit.yml - with: - directory: sdk - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" - go-version: "1.19" - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - consul-license: ${{secrets.CONSUL_LICENSE}} - datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" - - go-test-sdk-1-20: - needs: - - setup - - dev-build - uses: ./.github/workflows/reusable-unit.yml - with: - directory: sdk - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" - go-version: "1.20" - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - consul-license: ${{secrets.CONSUL_LICENSE}} - datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" - - noop: - runs-on: ubuntu-latest - steps: - - run: "echo ok" - - # This is job is required for branch protection as a required gihub check - # because GitHub actions show up as checks at the job level and not the - # workflow level. This is currently a feature request: - # https://github.com/orgs/community/discussions/12395 - # - # This job must: - # - be placed after the fanout of a workflow so that everything fans back in - # to this job. - # - "need" any job that is part of the fan out / fan in - # - implement the if logic because we have conditional jobs - # (go-test-enteprise) that this job needs and this would potentially get - # skipped if a previous job got skipped. So we use the if clause to make - # sure it does not get skipped. - - go-tests-success: - needs: - - conditional-skip - - setup - - check-codegen - - check-generated-protobuf - - check-go-mod - - lint-consul-retry - - lint-container-test-deps - - lint-enums - - lint - - lint-32bit - # - go-test-arm64 - - go-test-enterprise - - go-test-ce - - go-test-race - - go-test-envoyextensions - - go-test-troubleshoot - - go-test-api-1-19 - - go-test-api-1-20 - - go-test-sdk-1-19 - - go-test-sdk-1-20 - - go-test-32bit - # - go-test-s390x - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - if: always() && needs.conditional-skip.outputs.skip-ci != 'true' - steps: - - name: evaluate upstream job results - run: | - # exit 1 if failure or cancelled result for any upstream job - if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then - printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" - exit 1 - fi +#name: go-tests +# +#on: +# pull_request: +# branches-ignore: +# - stable-website +# - 'docs/**' +# - 'ui/**' +# - 'mktg-**' # Digital Team Terraform-generated branches' prefix +# - 'backport/docs/**' +# - 'backport/ui/**' +# - 'backport/mktg-**' +# push: +# branches: +# # Push events on the main branch +# - main +# - release/** +# +#permissions: +# contents: read +# +#env: +# TEST_RESULTS: /tmp/test-results +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +## concurrency +#concurrency: +# group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} +# cancel-in-progress: true +# +#jobs: +# conditional-skip: +# uses: ./.github/workflows/reusable-conditional-skip.yml +# +# setup: +# needs: [conditional-skip] +# name: Setup +# if: needs.conditional-skip.outputs.skip-ci != 'true' +# runs-on: ubuntu-latest +# outputs: +# compute-small: ${{ steps.setup-outputs.outputs.compute-small }} +# compute-medium: ${{ steps.setup-outputs.outputs.compute-medium }} +# compute-large: ${{ steps.setup-outputs.outputs.compute-large }} +# compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# - id: setup-outputs +# name: Setup outputs +# run: ./.github/scripts/get_runner_classes.sh +# +# get-go-version: +# uses: ./.github/workflows/reusable-get-go-version.yml +# +# check-go-mod: +# needs: +# - setup +# - get-go-version +# uses: ./.github/workflows/reusable-check-go-mod.yml +# with: +# runs-on: ${{ needs.setup.outputs.compute-small }} +# repository-name: ${{ github.repository }} +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# check-generated-protobuf: +# needs: +# - setup +# - get-go-version +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-medium) }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: make proto-tools +# name: Install protobuf +# - run: make proto-format +# name: "Protobuf Format" +# - run: make --always-make proto +# - run: | +# if ! git diff --exit-code; then +# echo "Generated code was not updated correctly" +# exit 1 +# fi +# - run: make proto-lint +# name: "Protobuf Lint" +# check-codegen: +# needs: +# - setup +# - get-go-version +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: make --always-make codegen +# - run: | +# if ! git diff --exit-code; then +# echo "Generated code was not updated correctly" +# exit 1 +# fi +# +# lint-enums: +# needs: +# - setup +# - get-go-version +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go install github.com/reillywatson/enumcover/cmd/enumcover@master && enumcover ./... +# +# lint-container-test-deps: +# needs: +# - setup +# - get-go-version +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: make lint-container-test-deps +# +# lint-consul-retry: +# needs: +# - setup +# - get-go-version +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: make lint-consul-retry +# +# lint: +# needs: +# - setup +# - get-go-version +# uses: ./.github/workflows/reusable-lint.yml +# with: +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# lint-32bit: +# needs: +# - setup +# - get-go-version +# uses: ./.github/workflows/reusable-lint.yml +# with: +# go-arch: "386" +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# # create a development build +# dev-build: +# needs: +# - setup +# - get-go-version +# uses: ./.github/workflows/reusable-dev-build.yml +# with: +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# # dev-build-s390x: +# # if: ${{ endsWith(github.repository, '-enterprise') }} +# # needs: +# # - setup +# # - get-go-version +# # uses: ./.github/workflows/reusable-dev-build.yml +# # with: +# # uploaded-binary-name: 'consul-bin-s390x' +# # runs-on: ${{ needs.setup.outputs.compute-large }} +# # go-arch: "s390x" +# # go-version: ${{ needs.get-go-version.outputs.go-version }} +# # repository-name: ${{ github.repository }} +# # secrets: +# # elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# # dev-build-arm64: +# # # only run on enterprise because GHA does not have arm64 runners in CE +# # if: ${{ endsWith(github.repository, '-enterprise') }} +# # needs: +# # - setup +# # - get-go-version +# # uses: ./.github/workflows/reusable-dev-build.yml +# # with: +# # uploaded-binary-name: 'consul-bin-arm64' +# # runs-on: ${{ needs.setup.outputs.compute-large }} +# # go-arch: "arm64" +# # go-version: ${{ needs.get-go-version.outputs.go-version }} +# # repository-name: ${{ github.repository }} +# # secrets: +# # elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# # go-test-arm64: +# # # only run on enterprise because GHA does not have arm64 runners in CE +# # if: ${{ endsWith(github.repository, '-enterprise') }} +# # needs: +# # - setup +# # - get-go-version +# # - dev-build-arm64 +# # uses: ./.github/workflows/reusable-unit-split.yml +# # with: +# # directory: . +# # uploaded-binary-name: 'consul-bin-arm64' +# # runner-count: 12 +# # runs-on: "['self-hosted', 'ondemand', 'os=macos-arm', 'arm64']" +# # go-test-flags: "${{ (github.ref_name != 'main' && !startsWith(github.ref_name, 'release/')) && '-short' || '' }}" +# # go-version: ${{ needs.get-go-version.outputs.go-version }} +# # repository-name: ${{ github.repository }} +# # secrets: +# # elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# # consul-license: ${{secrets.CONSUL_LICENSE}} +# # datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# go-test-ce: +# needs: +# - setup +# - get-go-version +# - dev-build +# uses: ./.github/workflows/reusable-unit-split.yml +# with: +# directory: . +# runner-count: 6 +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-tags: "" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# consul-license: ${{secrets.CONSUL_LICENSE}} +# datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# go-test-enterprise: +# if: ${{ endsWith(github.repository, '-enterprise') }} +# needs: +# - setup +# - get-go-version +# - dev-build +# uses: ./.github/workflows/reusable-unit-split.yml +# with: +# directory: . +# runner-count: 6 +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consuldev' || '' }}" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# consul-license: ${{secrets.CONSUL_LICENSE}} +# datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# go-test-race: +# needs: +# - setup +# - get-go-version +# - dev-build +# uses: ./.github/workflows/reusable-unit.yml +# with: +# directory: . +# go-test-flags: "-race -gcflags=all=-d=checkptr=0" +# package-names-command: "go list ./... | grep -E -v '^github.com/hashicorp/consul/agent(/consul|/local|/routine-leak-checker)?$' | grep -E -v '^github.com/hashicorp/consul(/command|/connect|/snapshot)'" +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consuldev' || '' }}" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# consul-license: ${{secrets.CONSUL_LICENSE}} +# datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# go-test-32bit: +# needs: +# - setup +# - get-go-version +# - dev-build +# uses: ./.github/workflows/reusable-unit.yml +# with: +# directory: . +# go-arch: "386" +# go-test-flags: "-short" +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consuldev' || '' }}" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# consul-license: ${{secrets.CONSUL_LICENSE}} +# datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# # go-test-s390x: +# # if: ${{ endsWith(github.repository, '-enterprise') }} +# # needs: +# # - setup +# # - get-go-version +# # - dev-build-s390x +# # uses: ./.github/workflows/reusable-unit.yml +# # with: +# # uploaded-binary-name: 'consul-bin-s390x' +# # directory: . +# # go-test-flags: -short" +# # runs-on: ${{ needs.setup.outputs.compute-large }} +# # repository-name: ${{ github.repository }} +# # go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consuldev' || '' }}" +# # go-version: ${{ needs.get-go-version.outputs.go-version }} +# # permissions: +# # id-token: write # NOTE: this permission is explicitly required for Vault auth. +# # contents: read +# # secrets: +# # elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# # consul-license: ${{secrets.CONSUL_LICENSE}} +# # datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# go-test-envoyextensions: +# needs: +# - setup +# - get-go-version +# - dev-build +# uses: ./.github/workflows/reusable-unit.yml +# with: +# directory: envoyextensions +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consuldev' || '' }}" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# consul-license: ${{secrets.CONSUL_LICENSE}} +# datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# go-test-troubleshoot: +# needs: +# - setup +# - get-go-version +# - dev-build +# uses: ./.github/workflows/reusable-unit.yml +# with: +# directory: troubleshoot +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consuldev' || '' }}" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# consul-license: ${{secrets.CONSUL_LICENSE}} +# datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# go-test-api-backwards-compatibility: +# name: go-test-api-${{ needs.get-go-version.outputs.go-version-previous }} +# needs: +# - setup +# - get-go-version +# - dev-build +# uses: ./.github/workflows/reusable-unit.yml +# with: +# directory: api +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consuldev' || '' }}" +# go-version: ${{ needs.get-go-version.outputs.go-version-previous }} +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# consul-license: ${{secrets.CONSUL_LICENSE}} +# datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# go-test-api: +# needs: +# - setup +# - get-go-version +# - dev-build +# uses: ./.github/workflows/reusable-unit.yml +# with: +# directory: api +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consuldev' || '' }}" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# consul-license: ${{secrets.CONSUL_LICENSE}} +# datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# go-test-sdk-backwards-compatibility: +# name: go-test-sdk-${{ needs.get-go-version.outputs.go-version-previous }} +# needs: +# - setup +# - get-go-version +# - dev-build +# uses: ./.github/workflows/reusable-unit.yml +# with: +# directory: sdk +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consuldev' || '' }}" +# go-version: ${{ needs.get-go-version.outputs.go-version-previous }} +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# consul-license: ${{secrets.CONSUL_LICENSE}} +# datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# go-test-sdk: +# needs: +# - setup +# - get-go-version +# - dev-build +# uses: ./.github/workflows/reusable-unit.yml +# with: +# directory: sdk +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consuldev' || '' }}" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# consul-license: ${{secrets.CONSUL_LICENSE}} +# datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# go-test-testing-deployer: +# needs: +# - setup +# - get-go-version +# - dev-build +# uses: ./.github/workflows/reusable-unit.yml +# with: +# directory: testing/deployer +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# go-tags: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consuldev' || '' }}" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# consul-license: ${{secrets.CONSUL_LICENSE}} +# datadog-api-key: "${{ !endsWith(github.repository, '-enterprise') && secrets.DATADOG_API_KEY || '' }}" +# +# noop: +# runs-on: ubuntu-latest +# steps: +# - run: "echo ok" +# +# # This is job is required for branch protection as a required gihub check +# # because GitHub actions show up as checks at the job level and not the +# # workflow level. This is currently a feature request: +# # https://github.com/orgs/community/discussions/12395 +# # +# # This job must: +# # - be placed after the fanout of a workflow so that everything fans back in +# # to this job. +# # - "need" any job that is part of the fan out / fan in +# # - implement the if logic because we have conditional jobs +# # (go-test-enteprise) that this job needs and this would potentially get +# # skipped if a previous job got skipped. So we use the if clause to make +# # sure it does not get skipped. +# +# go-tests-success: +# needs: +# - conditional-skip +# - setup +# - check-codegen +# - check-generated-protobuf +# - check-go-mod +# - lint-consul-retry +# - lint-container-test-deps +# - lint-enums +# - lint +# - lint-32bit +# # - go-test-arm64 +# - go-test-enterprise +# - go-test-ce +# - go-test-race +# - go-test-envoyextensions +# - go-test-troubleshoot +# - go-test-api-backwards-compatibility +# - go-test-api +# - go-test-sdk-backwards-compatibility +# - go-test-sdk +# - go-test-32bit +# - go-test-testing-deployer +# # - go-test-s390x +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# if: always() && needs.conditional-skip.outputs.skip-ci != 'true' +# steps: +# - name: evaluate upstream job results +# run: | +# # exit 1 if failure or cancelled result for any upstream job +# # this ensures that we fail the PR check regardless of cancellation, rather than skip-passing it +# # see https://docs.github.com/en/actions/using-jobs/using-conditions-to-control-job-execution#overview +# if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then +# printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" +# exit 1 +# fi +# - name: Set failure Slack commit message summary +# # failure() ensures this runs even if the test eval step exits 1 +# if: failure() +# env: +# # Capturing in an env var makes this safe against GHA shell injection via commit message. +# # See https://securitylab.github.com/research/github-actions-untrusted-input/ +# COMMIT_MESSAGE_FULL: ${{ github.event.head_commit.message }} +# run: | +# # if failure (not cancelled), notify Slack +# if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure)\"'; then +# printf "Tests failed, notifying Slack" +# echo "FAILED_TESTS=true" >> $GITHUB_ENV +# +# # 'echo ... | head -n 1' does not work reliably, so use bash-ism to get first line. +# COMMIT_MESSAGE_SUMMARY=${COMMIT_MESSAGE_FULL%%$'\n'*} +# +# # Send multi-line env var to GITHUB_ENV. +# # github.event.head_commit.message and github.ref_name both rely on this event occurring on a push / merge +# echo "SLACK_MESSAGE_RAW<> $GITHUB_ENV +# echo "❌ ${{ github.workflow }} workflow failed: +# +# - Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} +# - Branch: ${{ github.ref_name }} +# - Message: ${COMMIT_MESSAGE_SUMMARY} +# - Author: ${{ github.event.sender.login }}" >> $GITHUB_ENV +# echo "EOF" >> $GITHUB_ENV +# fi +# - name: Notify Slack +# # failure() ensures this runs even if the test eval step exits 1 +# # FAILED_TESTS must also be checked to avoid running this step on cancellation due to the summary check above +# if: ${{ failure() && env.FAILED_TESTS == 'true' && (github.ref_name == 'main' || startsWith(github.ref_name, 'release/')) }} +# id: slack +# uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 +# with: +# # Escape entire message string to ensure valid JSON. If invalid, the notification will fail silently in CI. +# payload: | +# { +# "message": ${{ toJSON(env.SLACK_MESSAGE_RAW) }} +# } +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_PROTECTED_BRANCH_TEST_SLACK_WEBHOOK }} diff --git a/.github/workflows/goldenfile-checker.yml b/.github/workflows/goldenfile-checker.yml new file mode 100644 index 000000000000..154b48fa9740 --- /dev/null +++ b/.github/workflows/goldenfile-checker.yml @@ -0,0 +1,43 @@ +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +## This workflow checks that are no changes necessary to golden files for xds +## tests ensuring they are up to date +# +#name: Golden File Checker +# +#on: +# pull_request: +# types: [opened, synchronize, labeled] +# # Runs on PRs to main and all release branches +# branches: +# - main +# - release/* +# +#jobs: +# get-go-version: +# uses: ./.github/workflows/reusable-get-go-version.yml +# # checks that there is no diff between the existing golden files +# goldenfile-check: +# runs-on: ubuntu-latest +# needs: +# - get-go-version +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ github.event.pull_request.head.sha }} +# fetch-depth: 0 # by default the checkout action doesn't checkout all branches +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - name: Download Modules +# run: go mod download +# - name: Check for golden file xds tests in diff +# run: ./.github/scripts/goldenfile_checker.sh +# env: +# GITHUB_BRANCH_REF: ${{ github.event.pull_request.head.ref }} +# CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} diff --git a/.github/workflows/issue-comment-created.yml b/.github/workflows/issue-comment-created.yml index 42483d92b164..ad13a1e4fe52 100644 --- a/.github/workflows/issue-comment-created.yml +++ b/.github/workflows/issue-comment-created.yml @@ -1,18 +1,18 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Issue Comment Created - -on: - issue_comment: - types: [created] - -jobs: - triage: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 # v1.3.0 - with: - labels: | - waiting-reply +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Issue Comment Created +# +#on: +# issue_comment: +# types: [created] +# +#jobs: +# triage: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# - uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 # v1.3.0 +# with: +# labels: | +# waiting-reply diff --git a/.github/workflows/jira-issues.yaml b/.github/workflows/jira-issues.yaml index c136dfd69a78..5f76e567ad9a 100644 --- a/.github/workflows/jira-issues.yaml +++ b/.github/workflows/jira-issues.yaml @@ -1,104 +1,103 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -on: - issues: - types: [opened, closed, deleted, reopened] - issue_comment: - types: [created] - workflow_dispatch: - -name: Jira Community Issue Sync - -jobs: - sync: - runs-on: ubuntu-latest - name: Jira Community Issue sync - steps: - - name: Login - uses: atlassian/gajira-login@ca13f8850ea309cf44a6e4e0c49d9aa48ac3ca4c # v3 - env: - JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} - JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} - JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} - - - name: Set ticket type - id: set-ticket-type - run: | - echo "TYPE=GH Issue" >> $GITHUB_OUTPUT - - - name: Set ticket labels - if: github.event.action == 'opened' - id: set-ticket-labels - run: | - LABELS="[" - if [[ "${{ contains(github.event.issue.labels.*.name, 'type/bug') }}" == "true" ]]; then LABELS+="\"type/bug\", "; fi - if [[ "${{ contains(github.event.issue.labels.*.name, 'type/enhancement') }}" == "true" ]]; then LABELS+="\"type/enhancement\", "; fi - if [[ "${{ contains(github.event.issue.labels.*.name, 'type/docs') }}" == "true" ]]; then LABELS+="\"type/docs\", "; fi - if [[ ${#LABELS} != 1 ]]; then LABELS=${LABELS::-2}"]"; else LABELS+="]"; fi - echo "LABELS=${LABELS}" >> $GITHUB_OUTPUT - - - name: Create ticket if an issue is filed, or if PR not by a team member is opened - if: github.event.action == 'opened' - uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1 - with: - project: NET - issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" - summary: "${{ github.event.repository.name }} [${{ steps.set-ticket-type.outputs.TYPE }} #${{ github.event.issue.number }}]: ${{ github.event.issue.title }}" - description: "${{ github.event.issue.body || github.event.pull_request.body }}\n\n_Created in GitHub by ${{ github.actor }}._" - # customfield_10089 is "Issue Link", customfield_10371 is "Source" (use JIRA API to retrieve) - extraFields: '{ "customfield_10089": "${{ github.event.issue.html_url || github.event.pull_request.html_url }}", - "customfield_10371": { "value": "GitHub" }, - "customfield_10535": [{ "value": "Service Mesh" }], - "components": [{ "name": "${{ github.event.repository.name }}" }], - "labels": ${{ steps.set-ticket-labels.outputs.LABELS }} }' - env: - JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} - JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} - JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} - - # Education Jira - - name: Create ticket in Education board an issue is filed, or if PR not by a team member is opened - if: github.event.action == 'opened' && contains(github.event.issue.labels.*.name, 'type/docs') - uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1 - with: - project: CE - issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" - summary: "${{ github.event.repository.name }} [${{ steps.set-ticket-type.outputs.TYPE }} #${{ github.event.issue.number }}]: ${{ github.event.issue.title }}" - description: "GitHub URL: ${{ github.event.issue.html_url || github.event.pull_request.html_url }}\n\n${{ github.event.issue.body || github.event.pull_request.body }}\n\n_Created in GitHub by ${{ github.actor }}._" - # customfield_10089 is "Issue Link", customfield_10371 is "Source" (use JIRA API to retrieve) - extraFields: '{ "components": [{ "name": "${{ github.event.repository.name }}" }] }' - - env: - JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} - JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} - JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} - - - name: Search - if: github.event.action != 'opened' - id: search - uses: tomhjp/gh-action-jira-search@04700b457f317c3e341ce90da5a3ff4ce058f2fa # v0.2.2 - with: - # cf[10089] is Issue Link (use JIRA API to retrieve) - jql: 'issuetype = "${{ steps.set-ticket-type.outputs.TYPE }}" and cf[10089] = "${{ github.event.issue.html_url || github.event.pull_request.html_url }}"' - - - name: Sync comment - if: github.event.action == 'created' && steps.search.outputs.issue - uses: tomhjp/gh-action-jira-comment@6eb6b9ead70221916b6badd118c24535ed220bd9 # v0.2.0 - with: - issue: ${{ steps.search.outputs.issue }} - comment: "${{ github.actor }} ${{ github.event.review.state || 'commented' }}:\n\n${{ github.event.comment.body || github.event.review.body }}\n\n${{ github.event.comment.html_url || github.event.review.html_url }}" - - - name: Close ticket - if: ( github.event.action == 'closed' || github.event.action == 'deleted' ) && steps.search.outputs.issue - uses: atlassian/gajira-transition@4749176faf14633954d72af7a44d7f2af01cc92b # v3 - with: - issue: ${{ steps.search.outputs.issue }} - transition: "Closed" - - - name: Reopen ticket - if: github.event.action == 'reopened' && steps.search.outputs.issue - uses: atlassian/gajira-transition@4749176faf14633954d72af7a44d7f2af01cc92b # v3 - with: - issue: ${{ steps.search.outputs.issue }} - transition: "To Do" +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#on: +# issues: +# types: [opened, closed, deleted, reopened] +# issue_comment: +# types: [created] +# workflow_dispatch: +# +#name: Jira Community Issue Sync +# +#jobs: +# sync: +# runs-on: ubuntu-latest +# name: Jira Community Issue sync +# steps: +# - name: Login +# uses: atlassian/gajira-login@45fd029b9f1d6d8926c6f04175aa80c0e42c9026 # v3.0.1 +# env: +# JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} +# JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} +# JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} +# +# - name: Set ticket type +# id: set-ticket-type +# run: | +# echo "TYPE=GH Issue" >> $GITHUB_OUTPUT +# +# - name: Set ticket labels +# if: github.event.action == 'opened' +# id: set-ticket-labels +# run: | +# LABELS="[" +# if [[ "${{ contains(github.event.issue.labels.*.name, 'type/bug') }}" == "true" ]]; then LABELS+="\"type/bug\", "; fi +# if [[ "${{ contains(github.event.issue.labels.*.name, 'type/enhancement') }}" == "true" ]]; then LABELS+="\"type/enhancement\", "; fi +# if [[ "${{ contains(github.event.issue.labels.*.name, 'type/docs') }}" == "true" ]]; then LABELS+="\"type/docs\", "; fi +# if [[ ${#LABELS} != 1 ]]; then LABELS=${LABELS::-2}"]"; else LABELS+="]"; fi +# echo "LABELS=${LABELS}" >> $GITHUB_OUTPUT +# +# - name: Create ticket if an issue is filed, or if PR not by a team member is opened +# if: github.event.action == 'opened' +# uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1 +# with: +# project: NET +# issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" +# summary: "${{ github.event.repository.name }} [${{ steps.set-ticket-type.outputs.TYPE }} #${{ github.event.issue.number }}]: ${{ github.event.issue.title }}" +# description: "${{ github.event.issue.body || github.event.pull_request.body }}\n\n_Created in GitHub by ${{ github.actor }}._" +# # customfield_10089 is "Issue Link", customfield_10371 is "Source" (use JIRA API to retrieve) +# extraFields: '{ "customfield_10089": "${{ github.event.issue.html_url || github.event.pull_request.html_url }}", +# "customfield_10371": { "value": "GitHub" }, +# "components": [{ "name": "${{ github.event.repository.name }}" }], +# "labels": ${{ steps.set-ticket-labels.outputs.LABELS }} }' +# env: +# JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} +# JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} +# JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} +# +# # Education Jira +# - name: Create ticket in Education board an issue is filed, or if PR not by a team member is opened +# if: github.event.action == 'opened' && contains(github.event.issue.labels.*.name, 'type/docs') +# uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1 +# with: +# project: CE +# issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" +# summary: "${{ github.event.repository.name }} [${{ steps.set-ticket-type.outputs.TYPE }} #${{ github.event.issue.number }}]: ${{ github.event.issue.title }}" +# description: "GitHub URL: ${{ github.event.issue.html_url || github.event.pull_request.html_url }}\n\n${{ github.event.issue.body || github.event.pull_request.body }}\n\n_Created in GitHub by ${{ github.actor }}._" +# # customfield_10089 is "Issue Link", customfield_10371 is "Source" (use JIRA API to retrieve) +# extraFields: '{ "components": [{ "name": "${{ github.event.repository.name }}" }] }' +# +# env: +# JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} +# JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} +# JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} +# +# - name: Search +# if: github.event.action != 'opened' +# id: search +# uses: tomhjp/gh-action-jira-search@04700b457f317c3e341ce90da5a3ff4ce058f2fa # v0.2.2 +# with: +# # cf[10089] is Issue Link (use JIRA API to retrieve) +# jql: 'issuetype = "${{ steps.set-ticket-type.outputs.TYPE }}" and cf[10089] = "${{ github.event.issue.html_url || github.event.pull_request.html_url }}"' +# +# - name: Sync comment +# if: github.event.action == 'created' && steps.search.outputs.issue +# uses: tomhjp/gh-action-jira-comment@6eb6b9ead70221916b6badd118c24535ed220bd9 # v0.2.0 +# with: +# issue: ${{ steps.search.outputs.issue }} +# comment: "${{ github.actor }} ${{ github.event.review.state || 'commented' }}:\n\n${{ github.event.comment.body || github.event.review.body }}\n\n${{ github.event.comment.html_url || github.event.review.html_url }}" +# +# - name: Close ticket +# if: ( github.event.action == 'closed' || github.event.action == 'deleted' ) && steps.search.outputs.issue +# uses: atlassian/gajira-transition@38fc9cd61b03d6a53dd35fcccda172fe04b36de3 # v3.0.1 +# with: +# issue: ${{ steps.search.outputs.issue }} +# transition: "Closed" +# +# - name: Reopen ticket +# if: github.event.action == 'reopened' && steps.search.outputs.issue +# uses: atlassian/gajira-transition@38fc9cd61b03d6a53dd35fcccda172fe04b36de3 # v3.0.1 +# with: +# issue: ${{ steps.search.outputs.issue }} +# transition: "To Do" diff --git a/.github/workflows/jira-pr.yaml b/.github/workflows/jira-pr.yaml index a40bb0ae0f82..75ecca9ea161 100644 --- a/.github/workflows/jira-pr.yaml +++ b/.github/workflows/jira-pr.yaml @@ -1,118 +1,117 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -on: - pull_request_target: - types: [opened, closed, reopened] - workflow_dispatch: - -name: Jira Community PR Sync - -jobs: - sync: - runs-on: ubuntu-latest - name: Jira sync - steps: - - name: Login - uses: atlassian/gajira-login@ca13f8850ea309cf44a6e4e0c49d9aa48ac3ca4c # v3 - env: - JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} - JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} - JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} - - - name: Set ticket type - id: set-ticket-type - run: | - echo "TYPE=GH Issue" >> $GITHUB_OUTPUT - - - name: Set ticket labels - if: github.event.action == 'opened' - id: set-ticket-labels - run: | - LABELS="[" - if [[ "${{ contains(github.event.issue.labels.*.name, 'type/bug') }}" == "true" ]]; then LABELS+="\"type/bug\", "; fi - if [[ "${{ contains(github.event.issue.labels.*.name, 'type/enhancement') }}" == "true" ]]; then LABELS+="\"type/enhancement\", "; fi - if [[ ${#LABELS} != 1 ]]; then LABELS=${LABELS::-2}"]"; else LABELS+="]"; fi - echo "LABELS=${LABELS}" >> $GITHUB_OUTPUT - - - name: Check if team member - if: github.event.action == 'opened' - id: is-team-member - run: | - TEAM=consul - ROLE="$(gh api orgs/hashicorp/teams/${TEAM}/memberships/${{ github.actor }} | jq -r '.role | select(.!=null)')" - if [[ -n ${ROLE} ]]; then - echo "Actor ${{ github.actor }} is a ${TEAM} team member" - echo "MESSAGE=true" >> $GITHUB_OUTPUT - elif [[ "${{ contains(github.actor, 'hc-github-team-consul-core') }}" == "true" ]]; then - echo "Actor ${{ github.actor }} is a ${TEAM} team member" - echo "MESSAGE=true" >> $GITHUB_OUTPUT - elif [[ "${{ contains(github.actor, 'dependabot') }}" == "true" ]]; then - echo "Actor ${{ github.actor }} is a ${TEAM} team member" - echo "MESSAGE=true" >> $GITHUB_OUTPUT - else - echo "Actor ${{ github.actor }} is NOT a ${TEAM} team member" - echo "MESSAGE=false" >> $GITHUB_OUTPUT - fi - env: - GITHUB_TOKEN: ${{ secrets.JIRA_SYNC_GITHUB_TOKEN }} - - - name: Create ticket if an issue is filed, or if PR not by a team member is opened - if: ( github.event.action == 'opened' && steps.is-team-member.outputs.MESSAGE == 'false' ) - uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1 - with: - project: NET - issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" - summary: "${{ github.event.repository.name }} [${{ steps.set-ticket-type.outputs.TYPE }} #${{ github.event.pull_request.number }}]: ${{ github.event.pull_request.title }}" - description: "${{ github.event.issue.body || github.event.pull_request.body }}\n\n_Created in GitHub by ${{ github.actor }}._" - # customfield_10089 is "Issue Link", customfield_10371 is "Source" (use JIRA API to retrieve) - extraFields: '{ "customfield_10089": "${{ github.event.pull_request.html_url }}", - "customfield_10371": { "value": "GitHub" }, - "customfield_10535": [{ "value": "Service Mesh" }], - "components": [{ "name": "${{ github.event.repository.name }}" }], - "labels": ${{ steps.set-ticket-labels.outputs.LABELS }} }' - env: - JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} - JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} - JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} - - # Education Jira - - name: Create ticket in Education board an issue is filed, or if PR not by a team member is opened - if: github.event.action == 'opened' && steps.is-team-member.outputs.MESSAGE == 'false' && contains(github.event.issue.labels.*.name, 'type/docs') - uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1 - with: - project: CE - issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" - summary: "${{ github.event.repository.name }} [${{ steps.set-ticket-type.outputs.TYPE }} #${{ github.event.pull_request.number }}]: ${{ github.event.pull_request.title }}" - description: "GitHub URL: ${{ github.event.issue.html_url || github.event.pull_request.html_url }}\n\n${{ github.event.issue.body || github.event.pull_request.body }}\n\n_Created in GitHub by ${{ github.actor }}._" - # customfield_10089 is "Issue Link", customfield_10371 is "Source" (use JIRA API to retrieve) - extraFields: '{ "components": [{ "name": "${{ github.event.repository.name }}" }] }' - - - name: Search - if: github.event.action != 'opened' - id: search - uses: tomhjp/gh-action-jira-search@04700b457f317c3e341ce90da5a3ff4ce058f2fa # v0.2.2 - with: - # cf[10089] is Issue Link (use JIRA API to retrieve) - jql: 'issuetype = "${{ steps.set-ticket-type.outputs.TYPE }}" and cf[10089] = "${{ github.event.issue.html_url || github.event.pull_request.html_url }}"' - - - name: Sync comment - if: github.event.action == 'created' && steps.search.outputs.issue - uses: tomhjp/gh-action-jira-comment@6eb6b9ead70221916b6badd118c24535ed220bd9 # v0.2.0 - with: - issue: ${{ steps.search.outputs.issue }} - comment: "${{ github.actor }} ${{ github.event.review.state || 'commented' }}:\n\n${{ github.event.comment.body || github.event.review.body }}\n\n${{ github.event.comment.html_url || github.event.review.html_url }}" - - - name: Close ticket - if: ( github.event.action == 'closed' || github.event.action == 'deleted' ) && steps.search.outputs.issue - uses: atlassian/gajira-transition@4749176faf14633954d72af7a44d7f2af01cc92b # v3 - with: - issue: ${{ steps.search.outputs.issue }} - transition: "Closed" - - - name: Reopen ticket - if: github.event.action == 'reopened' && steps.search.outputs.issue - uses: atlassian/gajira-transition@4749176faf14633954d72af7a44d7f2af01cc92b # v3 - with: - issue: ${{ steps.search.outputs.issue }} - transition: "To Do" +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#on: +# pull_request_target: +# types: [opened, closed, reopened] +# workflow_dispatch: +# +#name: Jira Community PR Sync +# +#jobs: +# sync: +# runs-on: ubuntu-latest +# name: Jira sync +# steps: +# - name: Login +# uses: atlassian/gajira-login@45fd029b9f1d6d8926c6f04175aa80c0e42c9026 # v3.0.1 +# env: +# JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} +# JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} +# JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} +# +# - name: Set ticket type +# id: set-ticket-type +# run: | +# echo "TYPE=GH Issue" >> $GITHUB_OUTPUT +# +# - name: Set ticket labels +# if: github.event.action == 'opened' +# id: set-ticket-labels +# run: | +# LABELS="[" +# if [[ "${{ contains(github.event.issue.labels.*.name, 'type/bug') }}" == "true" ]]; then LABELS+="\"type/bug\", "; fi +# if [[ "${{ contains(github.event.issue.labels.*.name, 'type/enhancement') }}" == "true" ]]; then LABELS+="\"type/enhancement\", "; fi +# if [[ ${#LABELS} != 1 ]]; then LABELS=${LABELS::-2}"]"; else LABELS+="]"; fi +# echo "LABELS=${LABELS}" >> $GITHUB_OUTPUT +# +# - name: Check if team member +# if: github.event.action == 'opened' +# id: is-team-member +# run: | +# TEAM=consul +# ROLE="$(gh api orgs/hashicorp/teams/${TEAM}/memberships/${{ github.actor }} | jq -r '.role | select(.!=null)')" +# if [[ -n ${ROLE} ]]; then +# echo "Actor ${{ github.actor }} is a ${TEAM} team member" +# echo "MESSAGE=true" >> $GITHUB_OUTPUT +# elif [[ "${{ contains(github.actor, 'hc-github-team-consul-core') }}" == "true" ]]; then +# echo "Actor ${{ github.actor }} is a ${TEAM} team member" +# echo "MESSAGE=true" >> $GITHUB_OUTPUT +# elif [[ "${{ contains(github.actor, 'dependabot') }}" == "true" ]]; then +# echo "Actor ${{ github.actor }} is a ${TEAM} team member" +# echo "MESSAGE=true" >> $GITHUB_OUTPUT +# else +# echo "Actor ${{ github.actor }} is NOT a ${TEAM} team member" +# echo "MESSAGE=false" >> $GITHUB_OUTPUT +# fi +# env: +# GITHUB_TOKEN: ${{ secrets.JIRA_SYNC_GITHUB_TOKEN }} +# +# - name: Create ticket if an issue is filed, or if PR not by a team member is opened +# if: ( github.event.action == 'opened' && steps.is-team-member.outputs.MESSAGE == 'false' ) +# uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1 +# with: +# project: NET +# issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" +# summary: "${{ github.event.repository.name }} [${{ steps.set-ticket-type.outputs.TYPE }} #${{ github.event.pull_request.number }}]: ${{ github.event.pull_request.title }}" +# description: "${{ github.event.issue.body || github.event.pull_request.body }}\n\n_Created in GitHub by ${{ github.actor }}._" +# # customfield_10089 is "Issue Link", customfield_10371 is "Source" (use JIRA API to retrieve) +# extraFields: '{ "customfield_10089": "${{ github.event.pull_request.html_url }}", +# "customfield_10371": { "value": "GitHub" }, +# "components": [{ "name": "${{ github.event.repository.name }}" }], +# "labels": ${{ steps.set-ticket-labels.outputs.LABELS }} }' +# env: +# JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} +# JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} +# JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} +# +# # Education Jira +# - name: Create ticket in Education board an issue is filed, or if PR not by a team member is opened +# if: github.event.action == 'opened' && steps.is-team-member.outputs.MESSAGE == 'false' && contains(github.event.issue.labels.*.name, 'type/docs') +# uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1 +# with: +# project: CE +# issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" +# summary: "${{ github.event.repository.name }} [${{ steps.set-ticket-type.outputs.TYPE }} #${{ github.event.pull_request.number }}]: ${{ github.event.pull_request.title }}" +# description: "GitHub URL: ${{ github.event.issue.html_url || github.event.pull_request.html_url }}\n\n${{ github.event.issue.body || github.event.pull_request.body }}\n\n_Created in GitHub by ${{ github.actor }}._" +# # customfield_10089 is "Issue Link", customfield_10371 is "Source" (use JIRA API to retrieve) +# extraFields: '{ "components": [{ "name": "${{ github.event.repository.name }}" }] }' +# +# - name: Search +# if: github.event.action != 'opened' +# id: search +# uses: tomhjp/gh-action-jira-search@04700b457f317c3e341ce90da5a3ff4ce058f2fa # v0.2.2 +# with: +# # cf[10089] is Issue Link (use JIRA API to retrieve) +# jql: 'issuetype = "${{ steps.set-ticket-type.outputs.TYPE }}" and cf[10089] = "${{ github.event.issue.html_url || github.event.pull_request.html_url }}"' +# +# - name: Sync comment +# if: github.event.action == 'created' && steps.search.outputs.issue +# uses: tomhjp/gh-action-jira-comment@6eb6b9ead70221916b6badd118c24535ed220bd9 # v0.2.0 +# with: +# issue: ${{ steps.search.outputs.issue }} +# comment: "${{ github.actor }} ${{ github.event.review.state || 'commented' }}:\n\n${{ github.event.comment.body || github.event.review.body }}\n\n${{ github.event.comment.html_url || github.event.review.html_url }}" +# +# - name: Close ticket +# if: ( github.event.action == 'closed' || github.event.action == 'deleted' ) && steps.search.outputs.issue +# uses: atlassian/gajira-transition@38fc9cd61b03d6a53dd35fcccda172fe04b36de3 # v3.0.1 +# with: +# issue: ${{ steps.search.outputs.issue }} +# transition: "Closed" +# +# - name: Reopen ticket +# if: github.event.action == 'reopened' && steps.search.outputs.issue +# uses: atlassian/gajira-transition@38fc9cd61b03d6a53dd35fcccda172fe04b36de3 # v3.0.1 +# with: +# issue: ${{ steps.search.outputs.issue }} +# transition: "To Do" diff --git a/.github/workflows/license-checker.yml b/.github/workflows/license-checker.yml deleted file mode 100644 index 93ac36e75dbd..000000000000 --- a/.github/workflows/license-checker.yml +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -# This workflow checks that the BUSL license is not mentioned anywhere in -# a PR targeting a release that should maintain the MPL-2.0 license. -name: License Checker - -on: - pull_request: - # Logic to only apply check 1.1[4,5,6].x branches is in license_checker.sh - types: [opened, synchronize] - -jobs: - # checks that the diff does not contain any reference to - # the BUSL license and thus retains the MPL-2.0 license - license-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 # by default the checkout action doesn't checkout all branches - - name: Check for BUSL text in diff - run: ./.github/scripts/license_checker.sh diff --git a/.github/workflows/nightly-test-1.14.x.yaml b/.github/workflows/nightly-test-1.14.x.yaml deleted file mode 100644 index 11fb011d1357..000000000000 --- a/.github/workflows/nightly-test-1.14.x.yaml +++ /dev/null @@ -1,234 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Nightly Frontend Test 1.14.x -on: - schedule: - - cron: '0 4 * * *' - workflow_dispatch: {} - -env: - EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition - BRANCH: "release/1.14.x" - BRANCH_NAME: "release-1.14.x" # Used for naming artifacts - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - -jobs: - frontend-test-workspace-node: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Workspace Tests - id: workspace-test - working-directory: ./ui - run: make test-workspace - - - name: Node Tests - id: node-test - working-directory: ./ui/packages/consul-ui - run: make test-node - - frontend-build-ce: - runs-on: ubuntu-latest - env: - JOBS: 2 - CONSUL_NSPACES_ENABLED: 0 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Ember Build CE - id: build-ce - working-directory: ./ui/packages/consul-ui - run: make build-ci - - - name: Upload CE Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: frontend-ce-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - if-no-files-found: error - - frontend-test-ce: - runs-on: ubuntu-latest - needs: [frontend-build-ce] - strategy: - matrix: - partition: [ 1, 2, 3, 4 ] - env: - CONSUL_NSPACES_ENABLED: 0 - EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary - EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download CE Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ce-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Ember Test CE - id: cache - working-directory: ./ui/packages/consul-ui - run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit - - frontend-build-ent: - runs-on: ubuntu-latest - env: - JOBS: 2 - CONSUL_NSPACES_ENABLED: 1 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Ember Build ENT - id: build-ce - working-directory: ./ui/packages/consul-ui - run: make build-ci - - - name: Upload ENT Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - if-no-files-found: error - - frontend-test-ent: - runs-on: ubuntu-latest - needs: [frontend-build-ent] - strategy: - matrix: - partition: [ 1, 2, 3, 4 ] - env: - CONSUL_NSPACES_ENABLED: 1 - EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary - EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Ember Test ENT - id: cache - working-directory: ./ui/packages/consul-ui - run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit - - frontend-test-coverage-ent: - runs-on: ubuntu-latest - needs: [frontend-build-ent] - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Run ENT Code Coverage - working-directory: ./ui/packages/consul-ui - run: make test-coverage-ci - - slack-failure-notification: - runs-on: ubuntu-latest - needs: [frontend-test-ce, frontend-test-ent] - if: ${{ failure() }} - steps: - - name: Slack Notification - id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 - with: - payload: | - { - "message": "One or more nightly UI tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_UI_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-1.15.x.yaml b/.github/workflows/nightly-test-1.15.x.yaml index a98eb73070b3..8fb7edcfaa8e 100644 --- a/.github/workflows/nightly-test-1.15.x.yaml +++ b/.github/workflows/nightly-test-1.15.x.yaml @@ -1,234 +1,243 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Nightly Frontend Test 1.15.x -on: - schedule: - - cron: '0 4 * * *' - workflow_dispatch: {} - -env: - EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition - BRANCH: "release/1.15.x" - BRANCH_NAME: "release-1.15.x" # Used for naming artifacts - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - -jobs: - frontend-test-workspace-node: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Workspace Tests - id: workspace-test - working-directory: ./ui - run: make test-workspace - - - name: Node Tests - id: node-test - working-directory: ./ui/packages/consul-ui - run: make test-node - - frontend-build-ce: - runs-on: ubuntu-latest - env: - JOBS: 2 - CONSUL_NSPACES_ENABLED: 0 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Ember Build CE - id: build-ce - working-directory: ./ui/packages/consul-ui - run: make build-ci - - - name: Upload CE Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: frontend-ce-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - if-no-files-found: error - - frontend-test-ce: - runs-on: ubuntu-latest - needs: [frontend-build-ce] - strategy: - matrix: - partition: [ 1, 2, 3, 4 ] - env: - CONSUL_NSPACES_ENABLED: 0 - EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary - EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download CE Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ce-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Ember Test CE - id: cache - working-directory: ./ui/packages/consul-ui - run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit - - frontend-build-ent: - runs-on: ubuntu-latest - env: - JOBS: 2 - CONSUL_NSPACES_ENABLED: 1 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Ember Build ENT - id: build-ce - working-directory: ./ui/packages/consul-ui - run: make build-ci - - - name: Upload ENT Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - if-no-files-found: error - - frontend-test-ent: - runs-on: ubuntu-latest - needs: [frontend-build-ent] - strategy: - matrix: - partition: [ 1, 2, 3, 4 ] - env: - CONSUL_NSPACES_ENABLED: 1 - EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary - EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Ember Test ENT - id: cache - working-directory: ./ui/packages/consul-ui - run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit - - frontend-test-coverage-ent: - runs-on: ubuntu-latest - needs: [frontend-build-ent] - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Run ENT Code Coverage - working-directory: ./ui/packages/consul-ui - run: make test-coverage-ci - - slack-failure-notification: - runs-on: ubuntu-latest - needs: [frontend-test-ce, frontend-test-ent] - if: ${{ failure() }} - steps: - - name: Slack Notification - id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 - with: - payload: | - { - "message": "One or more nightly UI tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_UI_SLACK_WEBHOOK }} +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Nightly Frontend Test 1.15.x +#on: +# schedule: +# - cron: '0 4 * * *' +# workflow_dispatch: {} +# +#env: +# EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition +# BRANCH: "release/1.15.x" +# BRANCH_NAME: "release-1.15.x" # Used for naming artifacts +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +#jobs: +# check-ent: +# runs-on: ubuntu-latest +# if: ${{ endsWith(github.repository, '-enterprise') }} +# steps: +# - run: echo "Building Enterprise" +# +# frontend-test-workspace-node: +# runs-on: ubuntu-latest +# needs: [check-ent] +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 14 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Workspace Tests +# id: workspace-test +# working-directory: ./ui +# run: make test-workspace +# +# - name: Node Tests +# id: node-test +# working-directory: ./ui/packages/consul-ui +# run: make test-node +# +# frontend-build-ce: +# runs-on: ubuntu-latest +# needs: [check-ent] +# env: +# JOBS: 2 +# CONSUL_NSPACES_ENABLED: 0 +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 14 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Ember Build CE +# id: build-ce +# working-directory: ./ui/packages/consul-ui +# run: make build-ci +# +# - name: Upload CE Frontend +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: frontend-ce-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# if-no-files-found: error +# +# frontend-test-ce: +# runs-on: ubuntu-latest +# needs: [frontend-build-ce] +# strategy: +# matrix: +# partition: [ 1, 2, 3, 4 ] +# env: +# CONSUL_NSPACES_ENABLED: 0 +# EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary +# EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 14 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download CE Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ce-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Ember Test CE +# id: cache +# working-directory: ./ui/packages/consul-ui +# run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit +# +# frontend-build-ent: +# runs-on: ubuntu-latest +# needs: [check-ent] +# env: +# JOBS: 2 +# CONSUL_NSPACES_ENABLED: 1 +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 14 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Ember Build ENT +# id: build-ce +# working-directory: ./ui/packages/consul-ui +# run: make build-ci +# +# - name: Upload ENT Frontend +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# if-no-files-found: error +# +# frontend-test-ent: +# runs-on: ubuntu-latest +# needs: [frontend-build-ent] +# strategy: +# matrix: +# partition: [ 1, 2, 3, 4 ] +# env: +# CONSUL_NSPACES_ENABLED: 1 +# EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary +# EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 14 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download ENT Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Ember Test ENT +# id: cache +# working-directory: ./ui/packages/consul-ui +# run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit +# +# frontend-test-coverage-ent: +# runs-on: ubuntu-latest +# needs: [frontend-build-ent] +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 14 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download ENT Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Run ENT Code Coverage +# working-directory: ./ui/packages/consul-ui +# run: make test-coverage-ci +# +# slack-failure-notification: +# runs-on: ubuntu-latest +# needs: [frontend-test-ce, frontend-test-ent] +# if: ${{ failure() }} +# steps: +# - name: Slack Notification +# id: slack +# uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 +# with: +# payload: | +# { +# "message": "One or more nightly UI tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" +# } +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_UI_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-1.16.x.yaml b/.github/workflows/nightly-test-1.16.x.yaml deleted file mode 100644 index b441eca5d0f5..000000000000 --- a/.github/workflows/nightly-test-1.16.x.yaml +++ /dev/null @@ -1,234 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Nightly Frontend Test 1.16.x -on: - schedule: - - cron: '0 4 * * *' - workflow_dispatch: {} - -env: - EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition - BRANCH: "release/1.16.x" - BRANCH_NAME: "release-1.16.x" # Used for naming artifacts - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - -jobs: - frontend-test-workspace-node: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Workspace Tests - id: workspace-test - working-directory: ./ui - run: make test-workspace - - - name: Node Tests - id: node-test - working-directory: ./ui/packages/consul-ui - run: make test-node - - frontend-build-ce: - runs-on: ubuntu-latest - env: - JOBS: 2 - CONSUL_NSPACES_ENABLED: 0 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Ember Build CE - id: build-ce - working-directory: ./ui/packages/consul-ui - run: make build-ci - - - name: Upload CE Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: frontend-ce-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - if-no-files-found: error - - frontend-test-ce: - runs-on: ubuntu-latest - needs: [frontend-build-ce] - strategy: - matrix: - partition: [ 1, 2, 3, 4 ] - env: - CONSUL_NSPACES_ENABLED: 0 - EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary - EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download CE Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ce-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Ember Test CE - id: cache - working-directory: ./ui/packages/consul-ui - run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit - - frontend-build-ent: - runs-on: ubuntu-latest - env: - JOBS: 2 - CONSUL_NSPACES_ENABLED: 1 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Ember Build ENT - id: build-ce - working-directory: ./ui/packages/consul-ui - run: make build-ci - - - name: Upload ENT Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - if-no-files-found: error - - frontend-test-ent: - runs-on: ubuntu-latest - needs: [frontend-build-ent] - strategy: - matrix: - partition: [ 1, 2, 3, 4 ] - env: - CONSUL_NSPACES_ENABLED: 1 - EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary - EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Ember Test ENT - id: cache - working-directory: ./ui/packages/consul-ui - run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit - - frontend-test-coverage-ent: - runs-on: ubuntu-latest - needs: [frontend-build-ent] - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 14 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Run ENT Code Coverage - working-directory: ./ui/packages/consul-ui - run: make test-coverage-ci - - slack-failure-notification: - runs-on: ubuntu-latest - needs: [frontend-test-ce, frontend-test-ent] - if: ${{ failure() }} - steps: - - name: Slack Notification - id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 - with: - payload: | - { - "message": "One or more nightly UI tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_UI_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-1.17.x.yaml b/.github/workflows/nightly-test-1.17.x.yaml deleted file mode 100644 index 9a063001e402..000000000000 --- a/.github/workflows/nightly-test-1.17.x.yaml +++ /dev/null @@ -1,234 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Nightly Frontend Test 1.17.x -on: - schedule: - - cron: '0 4 * * *' - workflow_dispatch: {} - -env: - EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition - BRANCH: "release/1.17.x" - BRANCH_NAME: "release-1.17.x" # Used for naming artifacts - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - -jobs: - frontend-test-workspace-node: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 18 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Workspace Tests - id: workspace-test - working-directory: ./ui - run: make test-workspace - - - name: Node Tests - id: node-test - working-directory: ./ui/packages/consul-ui - run: make test-node - - frontend-build-ce: - runs-on: ubuntu-latest - env: - JOBS: 2 - CONSUL_NSPACES_ENABLED: 0 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 18 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Ember Build CE - id: build-ce - working-directory: ./ui/packages/consul-ui - run: make build-ci - - - name: Upload CE Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: frontend-ce-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - if-no-files-found: error - - frontend-test-ce: - runs-on: ubuntu-latest - needs: [frontend-build-ce] - strategy: - matrix: - partition: [ 1, 2, 3, 4 ] - env: - CONSUL_NSPACES_ENABLED: 0 - EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary - EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 18 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download CE Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ce-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Ember Test CE - id: cache - working-directory: ./ui/packages/consul-ui - run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit - - frontend-build-ent: - runs-on: ubuntu-latest - env: - JOBS: 2 - CONSUL_NSPACES_ENABLED: 1 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 18 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Ember Build ENT - id: build-ce - working-directory: ./ui/packages/consul-ui - run: make build-ci - - - name: Upload ENT Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - if-no-files-found: error - - frontend-test-ent: - runs-on: ubuntu-latest - needs: [frontend-build-ent] - strategy: - matrix: - partition: [ 1, 2, 3, 4 ] - env: - CONSUL_NSPACES_ENABLED: 1 - EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary - EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 18 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Ember Test ENT - id: cache - working-directory: ./ui/packages/consul-ui - run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit - - frontend-test-coverage-ent: - runs-on: ubuntu-latest - needs: [frontend-build-ent] - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 18 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Run ENT Code Coverage - working-directory: ./ui/packages/consul-ui - run: make test-coverage-ci - - slack-failure-notification: - runs-on: ubuntu-latest - needs: [frontend-test-ce, frontend-test-ent] - if: ${{ failure() }} - steps: - - name: Slack Notification - id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 - with: - payload: | - { - "message": "One or more nightly UI tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_UI_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-1.18.x.yaml b/.github/workflows/nightly-test-1.18.x.yaml new file mode 100644 index 000000000000..6d2ad7cf81c8 --- /dev/null +++ b/.github/workflows/nightly-test-1.18.x.yaml @@ -0,0 +1,243 @@ +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Nightly Frontend Test 1.18.x +#on: +# schedule: +# - cron: '0 4 * * *' +# workflow_dispatch: {} +# +#env: +# EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition +# BRANCH: "release/1.18.x" +# BRANCH_NAME: "release-1.18.x" # Used for naming artifacts +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +#jobs: +# check-ent: +# runs-on: ubuntu-latest +# if: ${{ endsWith(github.repository, '-enterprise') }} +# steps: +# - run: echo "Building Enterprise" +# +# frontend-test-workspace-node: +# runs-on: ubuntu-latest +# needs: [check-ent] +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Workspace Tests +# id: workspace-test +# working-directory: ./ui +# run: make test-workspace +# +# - name: Node Tests +# id: node-test +# working-directory: ./ui/packages/consul-ui +# run: make test-node +# +# frontend-build-ce: +# runs-on: ubuntu-latest +# needs: [check-ent] +# env: +# JOBS: 2 +# CONSUL_NSPACES_ENABLED: 0 +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Ember Build CE +# id: build-ce +# working-directory: ./ui/packages/consul-ui +# run: make build-ci +# +# - name: Upload CE Frontend +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: frontend-ce-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# if-no-files-found: error +# +# frontend-test-ce: +# runs-on: ubuntu-latest +# needs: [frontend-build-ce] +# strategy: +# matrix: +# partition: [ 1, 2, 3, 4 ] +# env: +# CONSUL_NSPACES_ENABLED: 0 +# EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary +# EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download CE Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ce-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Ember Test CE +# id: cache +# working-directory: ./ui/packages/consul-ui +# run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit +# +# frontend-build-ent: +# runs-on: ubuntu-latest +# needs: [check-ent] +# env: +# JOBS: 2 +# CONSUL_NSPACES_ENABLED: 1 +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Ember Build ENT +# id: build-ce +# working-directory: ./ui/packages/consul-ui +# run: make build-ci +# +# - name: Upload ENT Frontend +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# if-no-files-found: error +# +# frontend-test-ent: +# runs-on: ubuntu-latest +# needs: [frontend-build-ent] +# strategy: +# matrix: +# partition: [ 1, 2, 3, 4 ] +# env: +# CONSUL_NSPACES_ENABLED: 1 +# EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary +# EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download ENT Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Ember Test ENT +# id: cache +# working-directory: ./ui/packages/consul-ui +# run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit +# +# frontend-test-coverage-ent: +# runs-on: ubuntu-latest +# needs: [frontend-build-ent] +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download ENT Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Run ENT Code Coverage +# working-directory: ./ui/packages/consul-ui +# run: make test-coverage-ci +# +# slack-failure-notification: +# runs-on: ubuntu-latest +# needs: [frontend-test-ce, frontend-test-ent] +# if: ${{ failure() }} +# steps: +# - name: Slack Notification +# id: slack +# uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 +# with: +# payload: | +# { +# "message": "One or more nightly UI tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" +# } +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_UI_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-1.19.x.yaml b/.github/workflows/nightly-test-1.19.x.yaml new file mode 100644 index 000000000000..7441cbf1f850 --- /dev/null +++ b/.github/workflows/nightly-test-1.19.x.yaml @@ -0,0 +1,243 @@ +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Nightly Frontend Test 1.19.x +#on: +# schedule: +# - cron: '0 4 * * *' +# workflow_dispatch: {} +# +#env: +# EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition +# BRANCH: "release/1.19.x" +# BRANCH_NAME: "release-1.19.x" # Used for naming artifacts +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +#jobs: +# check-ent: +# runs-on: ubuntu-latest +# if: ${{ endsWith(github.repository, '-enterprise') }} +# steps: +# - run: echo "Building Enterprise" +# +# frontend-test-workspace-node: +# runs-on: ubuntu-latest +# needs: [ check-ent ] +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Workspace Tests +# id: workspace-test +# working-directory: ./ui +# run: make test-workspace +# +# - name: Node Tests +# id: node-test +# working-directory: ./ui/packages/consul-ui +# run: make test-node +# +# frontend-build-ce: +# runs-on: ubuntu-latest +# needs: [ check-ent ] +# env: +# JOBS: 2 +# CONSUL_NSPACES_ENABLED: 0 +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Ember Build CE +# id: build-ce +# working-directory: ./ui/packages/consul-ui +# run: make build-ci +# +# - name: Upload CE Frontend +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: frontend-ce-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# if-no-files-found: error +# +# frontend-test-ce: +# runs-on: ubuntu-latest +# needs: [frontend-build-ce] +# strategy: +# matrix: +# partition: [ 1, 2, 3, 4 ] +# env: +# CONSUL_NSPACES_ENABLED: 0 +# EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary +# EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download CE Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ce-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Ember Test CE +# id: cache +# working-directory: ./ui/packages/consul-ui +# run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit +# +# frontend-build-ent: +# runs-on: ubuntu-latest +# needs: [ check-ent ] +# env: +# JOBS: 2 +# CONSUL_NSPACES_ENABLED: 1 +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Ember Build ENT +# id: build-ce +# working-directory: ./ui/packages/consul-ui +# run: make build-ci +# +# - name: Upload ENT Frontend +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# if-no-files-found: error +# +# frontend-test-ent: +# runs-on: ubuntu-latest +# needs: [frontend-build-ent] +# strategy: +# matrix: +# partition: [ 1, 2, 3, 4 ] +# env: +# CONSUL_NSPACES_ENABLED: 1 +# EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary +# EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download ENT Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Ember Test ENT +# id: cache +# working-directory: ./ui/packages/consul-ui +# run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit +# +# frontend-test-coverage-ent: +# runs-on: ubuntu-latest +# needs: [frontend-build-ent] +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download ENT Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Run ENT Code Coverage +# working-directory: ./ui/packages/consul-ui +# run: make test-coverage-ci +# +# slack-failure-notification: +# runs-on: ubuntu-latest +# needs: [frontend-test-ce, frontend-test-ent] +# if: ${{ failure() }} +# steps: +# - name: Slack Notification +# id: slack +# uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 +# with: +# payload: | +# { +# "message": "One or more nightly UI tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" +# } +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_UI_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-1.20.x.yaml b/.github/workflows/nightly-test-1.20.x.yaml new file mode 100644 index 000000000000..f4a6cd6047dc --- /dev/null +++ b/.github/workflows/nightly-test-1.20.x.yaml @@ -0,0 +1,243 @@ +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Nightly Frontend Test 1.20.x +#on: +# schedule: +# - cron: '0 4 * * *' +# workflow_dispatch: {} +# +#env: +# EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition +# BRANCH: "release/1.20.x" +# BRANCH_NAME: "release-1.20.x" # Used for naming artifacts +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +#jobs: +# check-ent: +# runs-on: ubuntu-latest +# if: ${{ endsWith(github.repository, '-enterprise') }} +# steps: +# - run: echo "Building Enterprise" +# +# frontend-test-workspace-node: +# runs-on: ubuntu-latest +# needs: [ check-ent ] +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Workspace Tests +# id: workspace-test +# working-directory: ./ui +# run: make test-workspace +# +# - name: Node Tests +# id: node-test +# working-directory: ./ui/packages/consul-ui +# run: make test-node +# +# frontend-build-ce: +# runs-on: ubuntu-latest +# needs: [ check-ent ] +# env: +# JOBS: 2 +# CONSUL_NSPACES_ENABLED: 0 +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Ember Build CE +# id: build-ce +# working-directory: ./ui/packages/consul-ui +# run: make build-ci +# +# - name: Upload CE Frontend +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: frontend-ce-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# if-no-files-found: error +# +# frontend-test-ce: +# runs-on: ubuntu-latest +# needs: [frontend-build-ce] +# strategy: +# matrix: +# partition: [ 1, 2, 3, 4 ] +# env: +# CONSUL_NSPACES_ENABLED: 0 +# EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary +# EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download CE Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ce-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Ember Test CE +# id: cache +# working-directory: ./ui/packages/consul-ui +# run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit +# +# frontend-build-ent: +# runs-on: ubuntu-latest +# needs: [ check-ent ] +# env: +# JOBS: 2 +# CONSUL_NSPACES_ENABLED: 1 +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Ember Build ENT +# id: build-ce +# working-directory: ./ui/packages/consul-ui +# run: make build-ci +# +# - name: Upload ENT Frontend +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# if-no-files-found: error +# +# frontend-test-ent: +# runs-on: ubuntu-latest +# needs: [frontend-build-ent] +# strategy: +# matrix: +# partition: [ 1, 2, 3, 4 ] +# env: +# CONSUL_NSPACES_ENABLED: 1 +# EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary +# EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download ENT Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Ember Test ENT +# id: cache +# working-directory: ./ui/packages/consul-ui +# run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit +# +# frontend-test-coverage-ent: +# runs-on: ubuntu-latest +# needs: [frontend-build-ent] +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download ENT Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Run ENT Code Coverage +# working-directory: ./ui/packages/consul-ui +# run: make test-coverage-ci +# +# slack-failure-notification: +# runs-on: ubuntu-latest +# needs: [frontend-test-ce, frontend-test-ent] +# if: ${{ failure() }} +# steps: +# - name: Slack Notification +# id: slack +# uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 +# with: +# payload: | +# { +# "message": "One or more nightly UI tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" +# } +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_UI_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-integ-peering_commontopo.yml b/.github/workflows/nightly-test-integ-peering_commontopo.yml new file mode 100644 index 000000000000..0f637a0146b8 --- /dev/null +++ b/.github/workflows/nightly-test-integ-peering_commontopo.yml @@ -0,0 +1,175 @@ +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Nightly test integrations - peering_common_topo +# +#on: +# schedule: +# # Run nightly at 12AM UTC/8PM EST/5PM PST +# - cron: '0 0 * * *' +# workflow_dispatch: {} +# +#env: +# TEST_RESULTS_DIR: /tmp/test-results +# CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} +# GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} +# GOTESTSUM_VERSION: "1.10.1" +# CONSUL_BINARY_UPLOAD_NAME: consul-bin +# # strip the hashicorp/ off the front of github.repository for consul +# CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +#jobs: +# setup: +# runs-on: ubuntu-latest +# name: Setup +# outputs: +# compute-small: ${{ steps.runners.outputs.compute-small }} +# compute-medium: ${{ steps.runners.outputs.compute-medium }} +# compute-large: ${{ steps.runners.outputs.compute-large }} +# compute-xl: ${{ steps.runners.outputs.compute-xl }} +# enterprise: ${{ steps.runners.outputs.enterprise }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ inputs.branch }} +# - id: runners +# run: .github/scripts/get_runner_classes.sh +# +# get-go-version: +# uses: ./.github/workflows/reusable-get-go-version.yml +# with: +# ref: ${{ inputs.branch }} +# +# get-envoy-versions: +# uses: ./.github/workflows/reusable-get-envoy-versions.yml +# with: +# ref: ${{ inputs.branch }} +# +# tests: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl ) }} +# needs: +# - setup +# - get-go-version +# - get-envoy-versions +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# test-case: +# - TestSuitesOnSharedTopo +# # these are not part of sharedTopoSuites +# - TestAC5PreparedQueryFailover +# - TestAC6Failovers +# - TestNET5029Failovers +# - TestRotateGW +# - TestAC7_2RotateLeader +# name: '${{matrix.test-case}}' +# +# env: +# ENVOY_VERSION: ${{ needs.get-envoy-versions.outputs.max-envoy-version }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go env +# - name: Build +# run: | +# make dev +# mv bin/consul consul +# - name: restore mode+x +# run: chmod +x consul +# - name: Build consul:local image +# run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . +# - name: Peering commonTopo Integration Tests +# run: | +# export NOLOGBUFFER=1 +# mkdir -p "${{ env.TEST_RESULTS_DIR }}" +# cd ./test-integ/peering_commontopo +# docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --raw-command \ +# --format=standard-verbose \ +# --debug \ +# --packages="./..." \ +# -- \ +# go test \ +# -tags "${{ env.GOTAGS }}" \ +# -run '^${{ matrix.test-case }}$' \ +# -timeout=60m \ +# -parallel=1 \ +# -json . \ +# --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --target-version local \ +# --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --latest-version latest +# env: +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# # tput complains if this isn't set to something. +# TERM: ansi +# +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: upload test results +# if: ${{ !cancelled() }} +# continue-on-error: true +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: | +# # TODO: we should probably version this and check a shasum or something? or run a container? +# which datadog-ci > /dev/null 2>&1 || { +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# } +# datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# +# success: +# needs: +# - setup +# - tests +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# if: ${{ always() }} +# steps: +# - name: evaluate upstream job results +# run: | +# # exit 1 if failure or cancelled result for any upstream job +# if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then +# printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" +# exit 1 +# fi +# - name: Notify Slack +# if: ${{ failure() }} +# id: slack +# uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 +# with: +# payload: | +# { +# "message": "One or more nightly peering_commontopo integration tests have failed. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" +# } +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_NIGHTLY_INTEG_TEST_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-integrations-1.15.x.yml b/.github/workflows/nightly-test-integrations-1.15.x.yml index c570a541abd1..155c00d56bbe 100644 --- a/.github/workflows/nightly-test-integrations-1.15.x.yml +++ b/.github/workflows/nightly-test-integrations-1.15.x.yml @@ -1,320 +1,372 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Nightly test-integrations 1.15.x - -on: - schedule: - # Run nightly at 1AM UTC/9PM EST/6PM PST - - cron: '* 1 * * *' - workflow_dispatch: {} - -env: - TEST_RESULTS_DIR: /tmp/test-results - TEST_RESULTS_ARTIFACT_NAME: test-results - CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} - GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} - GOTESTSUM_VERSION: "1.10.1" - CONSUL_BINARY_UPLOAD_NAME: consul-bin - # strip the hashicorp/ off the front of github.repository for consul - CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - BRANCH: "release/1.15.x" - BRANCH_NAME: "release-1.15.x" # Used for naming artifacts - -jobs: - setup: - runs-on: ubuntu-latest - name: Setup - outputs: - compute-small: ${{ steps.runners.outputs.compute-small }} - compute-medium: ${{ steps.runners.outputs.compute-medium }} - compute-large: ${{ steps.runners.outputs.compute-large }} - compute-xl: ${{ steps.runners.outputs.compute-xl }} - enterprise: ${{ steps.runners.outputs.enterprise }} - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - id: runners - run: .github/scripts/get_runner_classes.sh - - dev-build: - needs: [setup] - uses: ./.github/workflows/reusable-dev-build.yml - with: - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - uploaded-binary-name: 'consul-bin' - branch-name: "release/1.15.x" - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - generate-envoy-job-matrices: - needs: [setup] - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - name: Generate Envoy Job Matrices - outputs: - envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - name: Generate Envoy Job Matrix - id: set-matrix - env: - # this is further going to multiplied in envoy-integration tests by the - # other dimensions in the matrix. Currently TOTAL_RUNNERS would be - # multiplied by 8 based on these values: - # envoy-version: ["1.22.11", "1.23.12", "1.24.12", "1.25.11"] - # xds-target: ["server", "client"] - TOTAL_RUNNERS: 4 - JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' - run: | - NUM_RUNNERS=$TOTAL_RUNNERS - NUM_DIRS=$(find ./test/integration/connect/envoy -mindepth 1 -maxdepth 1 -type d | wc -l) - - if [ "$NUM_DIRS" -lt "$NUM_RUNNERS" ]; then - echo "TOTAL_RUNNERS is larger than the number of tests/packages to split." - NUM_RUNNERS=$((NUM_DIRS-1)) - fi - # fix issue where test splitting calculation generates 1 more split than TOTAL_RUNNERS. - NUM_RUNNERS=$((NUM_RUNNERS-1)) - { - echo -n "envoy-matrix=" - find ./test/integration/connect/envoy -maxdepth 1 -type d -print0 \ - | xargs -0 -n 1 basename \ - | jq --raw-input --argjson runnercount "$NUM_RUNNERS" "$JQ_SLICER" \ - | jq --compact-output 'map(join("|"))' - } >> "$GITHUB_OUTPUT" - - envoy-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - needs: - - setup - - generate-envoy-job-matrices - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - envoy-version: ["1.22.11", "1.23.12", "1.24.12", "1.25.11"] - xds-target: ["server", "client"] - test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} - env: - ENVOY_VERSION: ${{ matrix.envoy-version }} - XDS_TARGET: ${{ matrix.xds-target }} - AWS_LAMBDA_REGION: us-west-2 - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: ./bin - - name: restore mode+x - run: chmod +x ./bin/consul - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 - - name: Docker build - run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin - - name: Envoy Integration Tests - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running $(sed 's,|, ,g' <<< "${{ matrix.test-cases }}" |wc -w) subtests" - # shellcheck disable=SC2001 - sed 's,|,\n,g' <<< "${{ matrix.test-cases }}" - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --debug \ - --rerun-fails \ - --rerun-fails-report=/tmp/gotestsum-rerun-fails \ - --jsonfile /tmp/jsonfile/go-test.log \ - --packages=./test/integration/connect/envoy \ - -- -timeout=30m -tags integration -run="TestEnvoy/(${{ matrix.test-cases }})" - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - upgrade-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - needs: - - setup - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - consul-version: ["1.14", "1.15"] - env: - CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} - ENVOY_VERSION: "1.24.6" - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: go env - - # Get go binary from workspace - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: . - - name: restore mode+x - run: chmod +x consul - - name: Build consul:local image - run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . - - name: Configure GH workaround for ipv6 loopback - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - cat /etc/hosts && echo "-----------" - sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6-localhost ip6-loopback/g' /etc/hosts - cat /etc/hosts - - name: Upgrade Integration Tests - run: | - mkdir -p "${{ env.TEST_RESULTS_DIR }}" - cd ./test/integration/consul-container/test/upgrade - docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --raw-command \ - --format=short-verbose \ - --debug \ - --rerun-fails=2 \ - --packages="./..." \ - -- \ - go test \ - -p=4 \ - -tags "${{ env.GOTAGS }}" \ - -timeout=30m \ - -json \ - ./... \ - --follow-log=false \ - --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --target-version local \ - --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --latest-version "${{ env.CONSUL_LATEST_VERSION }}" - ls -lrt - env: - # this is needed because of incompatibility between RYUK container and GHA - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - # tput complains if this isn't set to something. - TERM: ansi - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - test-integrations-success: - needs: - - setup - - dev-build - - generate-envoy-job-matrices - - envoy-integration-test - - upgrade-integration-test - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - if: ${{ always() }} - steps: - - name: evaluate upstream job results - run: | - # exit 1 if failure or cancelled result for any upstream job - if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then - printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" - exit 1 - fi - - name: Notify Slack - if: ${{ failure() }} - id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 - with: - payload: | - { - "message": "One or more nightly integration tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_NIGHTLY_INTEG_TEST_SLACK_WEBHOOK }} +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Nightly test-integrations 1.15.x +# +#on: +# schedule: +# # Run nightly at 1AM UTC/9PM EST/6PM PST +# - cron: '0 1 * * *' +# workflow_dispatch: {} +# +#env: +# TEST_RESULTS_DIR: /tmp/test-results +# TEST_RESULTS_ARTIFACT_NAME: test-results +# CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} +# GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} +# GOTESTSUM_VERSION: "1.11.0" +# CONSUL_BINARY_UPLOAD_NAME: consul-bin +# # strip the hashicorp/ off the front of github.repository for consul +# CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# BRANCH: "release/1.15.x" +# BRANCH_NAME: "release-1.15.x" # Used for naming artifacts +# +#jobs: +# check-ent: +# runs-on: ubuntu-latest +# if: ${{ endsWith(github.repository, '-enterprise') }} +# steps: +# - run: echo "Building Enterprise" +# +# setup: +# runs-on: ubuntu-latest +# needs: [check-ent] +# name: Setup +# outputs: +# compute-small: ${{ steps.runners.outputs.compute-small }} +# compute-medium: ${{ steps.runners.outputs.compute-medium }} +# compute-large: ${{ steps.runners.outputs.compute-large }} +# compute-xl: ${{ steps.runners.outputs.compute-xl }} +# enterprise: ${{ steps.runners.outputs.enterprise }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# - id: runners +# run: .github/scripts/get_runner_classes.sh +# +# get-go-version: +# needs: [check-ent] +# uses: ./.github/workflows/reusable-get-go-version.yml +# with: +# ref: release/1.15.x +# +# get-envoy-versions: +# needs: [check-ent] +# uses: ./.github/workflows/reusable-get-envoy-versions.yml +# with: +# ref: release/1.15.x +# +# dev-build: +# needs: +# - setup +# - get-go-version +# uses: ./.github/workflows/reusable-dev-build.yml +# with: +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# uploaded-binary-name: 'consul-bin' +# branch-name: "release/1.15.x" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# generate-envoy-job-matrices: +# needs: [setup] +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# name: Generate Envoy Job Matrices +# outputs: +# envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# - name: Generate Envoy Job Matrix +# id: set-matrix +# env: +# # TEST_SPLITS sets the number of test case splits to use in the matrix. This will be +# # further multiplied in envoy-integration tests by the other dimensions in the matrix +# # to determine the total number of runners used. +# TEST_SPLITS: 4 +# JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' +# run: | +# NUM_DIRS=$(find ./test/integration/connect/envoy -mindepth 1 -maxdepth 1 -type d | wc -l) +# +# if [ "$NUM_DIRS" -lt "$TEST_SPLITS" ]; then +# echo "TEST_SPLITS is larger than the number of tests/packages to split." +# TEST_SPLITS=$((NUM_DIRS-1)) +# fi +# # fix issue where test splitting calculation generates 1 more split than TEST_SPLITS. +# TEST_SPLITS=$((TEST_SPLITS-1)) +# { +# echo -n "envoy-matrix=" +# find ./test/integration/connect/envoy -maxdepth 1 -type d -print0 \ +# | xargs -0 -n 1 basename \ +# | jq --raw-input --argjson runnercount "$TEST_SPLITS" "$JQ_SLICER" \ +# | jq --compact-output 'map(join("|"))' +# } >> "$GITHUB_OUTPUT" +# +# envoy-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# needs: +# - setup +# - get-go-version +# - get-envoy-versions +# - generate-envoy-job-matrices +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# envoy-version: ${{ fromJSON(needs.get-envoy-versions.outputs.envoy-versions-json) }} +# xds-target: ["server", "client"] +# test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} +# env: +# ENVOY_VERSION: ${{ matrix.envoy-version }} +# XDS_TARGET: ${{ matrix.xds-target }} +# AWS_LAMBDA_REGION: us-west-2 +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# +# - name: fetch binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: ./bin +# - name: restore mode+x +# run: chmod +x ./bin/consul +# +# - name: Set up Docker Buildx +# uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 +# +# - name: Docker build +# run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin +# +# - name: Envoy Integration Tests +# id: envoy-integration-tests +# env: +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# LAMBDA_TESTS_ENABLED: "true" +# # tput complains if this isn't set to something. +# TERM: ansi +# run: | +# # shellcheck disable=SC2001 +# echo "Running $(sed 's,|, ,g' <<< "${{ matrix.test-cases }}" |wc -w) subtests" +# # shellcheck disable=SC2001 +# sed 's,|,\n,g' <<< "${{ matrix.test-cases }}" +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --debug \ +# --rerun-fails \ +# --rerun-fails-report=/tmp/gotestsum-rerun-fails \ +# --jsonfile /tmp/jsonfile/go-test.log \ +# --packages=./test/integration/connect/envoy \ +# -- -timeout=30m -tags integration -run="TestEnvoy/(${{ matrix.test-cases }})" +# +# # See https://github.com/orgs/community/discussions/8945#discussioncomment-9897011 +# # and overall topic discussion for why this is necessary. +# - name: Generate artifact ID +# id: generate-artifact-id +# if: ${{ failure() && steps.envoy-integration-tests.conclusion == 'failure' }} +# run: | +# ARTIFACT_ID=$(uuidgen) +# echo "Artifact ID: $ARTIFACT_ID (search this in job summary for download link)" +# echo "artifact_id=$ARTIFACT_ID" >> "$GITHUB_ENV" +# +# - name: Upload failure logs +# if: ${{ failure() && steps.envoy-integration-tests.conclusion == 'failure' }} +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: envoy-${{ matrix.envoy-version }}-logs-${{ env.artifact_id }} +# path: test/integration/connect/envoy/workdir/logs/ +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# upgrade-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# needs: +# - setup +# - get-go-version +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# consul-version: ["1.14", "1.15"] +# env: +# CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} +# # ENVOY_VERSION should be the latest version supported by _all_ Consul versions in the +# # matrix.consul-version, since we are testing upgrade from an older Consul version. +# # In practice, this should be the highest Envoy version supported by the lowest non-LTS +# # Consul version in the matrix (LTS versions receive additional Envoy version support). +# # +# # This value should be kept current in new nightly test workflows, and updated any time +# # a new major Envoy release is added to the set supported by Consul versions in +# # matrix.consul-version (i.e. whenever the highest common Envoy version across active +# # Consul versions changes). The minor Envoy version does not necessarily need to be +# # kept current for the purpose of these tests, but the major (1.N) version should be. +# ENVOY_VERSION: "1.24.12" +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go env +# +# # Get go binary from workspace +# - name: fetch binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: . +# - name: restore mode+x +# run: chmod +x consul +# - name: Build consul:local image +# run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . +# - name: Configure GH workaround for ipv6 loopback +# if: ${{ !endsWith(github.repository, '-enterprise') }} +# run: | +# cat /etc/hosts && echo "-----------" +# sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6-localhost ip6-loopback/g' /etc/hosts +# cat /etc/hosts +# - name: Upgrade Integration Tests +# run: | +# mkdir -p "${{ env.TEST_RESULTS_DIR }}" +# cd ./test/integration/consul-container/test/upgrade +# docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --raw-command \ +# --format=github-actions \ +# --rerun-fails \ +# --packages="./..." \ +# -- \ +# go test \ +# -p=4 \ +# -tags "${{ env.GOTAGS }}" \ +# -timeout=30m \ +# -json \ +# ./... \ +# --follow-log=false \ +# --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --target-version local \ +# --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --latest-version "${{ env.CONSUL_LATEST_VERSION }}" +# ls -lrt +# env: +# # this is needed because of incompatibility between RYUK container and GHA +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# # tput complains if this isn't set to something. +# TERM: ansi +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# test-integrations-success: +# needs: +# - setup +# - dev-build +# - generate-envoy-job-matrices +# - envoy-integration-test +# - upgrade-integration-test +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# if: ${{ always() && endsWith(github.repository, '-enterprise') }} +# steps: +# - name: evaluate upstream job results +# run: | +# # exit 1 if failure or cancelled result for any upstream job +# if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then +# printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" +# exit 1 +# fi +# - name: Notify Slack +# if: ${{ failure() }} +# id: slack +# uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 +# with: +# payload: | +# { +# "message": "One or more nightly integration tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" +# } +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_NIGHTLY_INTEG_TEST_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-integrations-1.16.x.yml b/.github/workflows/nightly-test-integrations-1.16.x.yml deleted file mode 100644 index d9a771c3fe13..000000000000 --- a/.github/workflows/nightly-test-integrations-1.16.x.yml +++ /dev/null @@ -1,342 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Nightly test-integrations 1.16.x - -on: - schedule: - # Run nightly at 1AM UTC/9PM EST/6PM PST - - cron: '* 1 * * *' - workflow_dispatch: {} - -env: - TEST_RESULTS_DIR: /tmp/test-results - TEST_RESULTS_ARTIFACT_NAME: test-results - CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} - GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} - GOTESTSUM_VERSION: "1.10.1" - CONSUL_BINARY_UPLOAD_NAME: consul-bin - # strip the hashicorp/ off the front of github.repository for consul - CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - BRANCH: "release/1.16.x" - BRANCH_NAME: "release-1.16.x" # Used for naming artifacts - -jobs: - setup: - runs-on: ubuntu-latest - name: Setup - outputs: - compute-small: ${{ steps.runners.outputs.compute-small }} - compute-medium: ${{ steps.runners.outputs.compute-medium }} - compute-large: ${{ steps.runners.outputs.compute-large }} - compute-xl: ${{ steps.runners.outputs.compute-xl }} - enterprise: ${{ steps.runners.outputs.enterprise }} - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - id: runners - run: .github/scripts/get_runner_classes.sh - - dev-build: - needs: [setup] - uses: ./.github/workflows/reusable-dev-build.yml - with: - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - uploaded-binary-name: 'consul-bin' - branch-name: "release/1.16.x" - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - generate-envoy-job-matrices: - needs: [setup] - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - name: Generate Envoy Job Matrices - outputs: - envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - name: Generate Envoy Job Matrix - id: set-matrix - env: - # this is further going to multiplied in envoy-integration tests by the - # other dimensions in the matrix. Currently TOTAL_RUNNERS would be - # multiplied by 8 based on these values: - # envoy-version: ["1.23.12", "1.24.12", "1.25.11", "1.26.6"] - # xds-target: ["server", "client"] - TOTAL_RUNNERS: 4 - JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' - run: | - NUM_RUNNERS=$TOTAL_RUNNERS - NUM_DIRS=$(find ./test/integration/connect/envoy -mindepth 1 -maxdepth 1 -type d | wc -l) - - if [ "$NUM_DIRS" -lt "$NUM_RUNNERS" ]; then - echo "TOTAL_RUNNERS is larger than the number of tests/packages to split." - NUM_RUNNERS=$((NUM_DIRS-1)) - fi - # fix issue where test splitting calculation generates 1 more split than TOTAL_RUNNERS. - NUM_RUNNERS=$((NUM_RUNNERS-1)) - { - echo -n "envoy-matrix=" - find ./test/integration/connect/envoy -maxdepth 1 -type d -print0 \ - | xargs -0 -n 1 basename \ - | jq --raw-input --argjson runnercount "$NUM_RUNNERS" "$JQ_SLICER" \ - | jq --compact-output 'map(join("|"))' - } >> "$GITHUB_OUTPUT" - - envoy-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - needs: - - setup - - generate-envoy-job-matrices - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - envoy-version: ["1.23.12", "1.24.12", "1.25.11", "1.26.6"] - xds-target: ["server", "client"] - test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} - env: - ENVOY_VERSION: ${{ matrix.envoy-version }} - XDS_TARGET: ${{ matrix.xds-target }} - AWS_LAMBDA_REGION: us-west-2 - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: ./bin - - name: restore mode+x - run: chmod +x ./bin/consul - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 - - - name: Docker build - run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin - - - name: Envoy Integration Tests - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running $(sed 's,|, ,g' <<< "${{ matrix.test-cases }}" |wc -w) subtests" - # shellcheck disable=SC2001 - sed 's,|,\n,g' <<< "${{ matrix.test-cases }}" - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --debug \ - --rerun-fails \ - --rerun-fails-report=/tmp/gotestsum-rerun-fails \ - --jsonfile /tmp/jsonfile/go-test.log \ - --packages=./test/integration/connect/envoy \ - -- -timeout=30m -tags integration -run="TestEnvoy/(${{ matrix.test-cases }})" - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - upgrade-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - needs: - - setup - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - consul-version: ["1.14", "1.15", "1.16"] - env: - CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} - ENVOY_VERSION: "1.24.6" - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: go env - - # Get go binary from workspace - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: . - - name: restore mode+x - run: chmod +x consul - - name: Build consul:local image - run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . - - name: Build consul-envoy:latest-version image - id: buildConsulEnvoyLatestImage - run: | - if ${{ endsWith(github.repository, '-enterprise') }} == 'true' - then - docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }}-ent --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - else - docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }} --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - fi - - name: Build consul-envoy:target-version image - id: buildConsulEnvoyTargetImage - continue-on-error: true - run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - - name: Retry Build consul-envoy:target-version image - if: steps.buildConsulEnvoyTargetImage.outcome == 'failure' - run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - - name: Build sds image - run: docker build -t consul-sds-server ./test/integration/connect/envoy/test-sds-server/ - - name: Configure GH workaround for ipv6 loopback - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - cat /etc/hosts && echo "-----------" - sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6-localhost ip6-loopback/g' /etc/hosts - cat /etc/hosts - - name: Upgrade Integration Tests - run: | - mkdir -p "${{ env.TEST_RESULTS_DIR }}" - cd ./test/integration/consul-container/test/upgrade - docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --raw-command \ - --format=short-verbose \ - --debug \ - --rerun-fails=2 \ - --packages="./..." \ - -- \ - go test \ - -p=4 \ - -tags "${{ env.GOTAGS }}" \ - -timeout=30m \ - -json \ - ./... \ - --follow-log=false \ - --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --target-version local \ - --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --latest-version "${{ env.CONSUL_LATEST_VERSION }}" - ls -lrt - env: - # this is needed because of incompatibility between RYUK container and GHA - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - # tput complains if this isn't set to something. - TERM: ansi - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - - test-integrations-success: - needs: - - setup - - dev-build - - generate-envoy-job-matrices - - envoy-integration-test - - upgrade-integration-test - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - if: ${{ always() }} - steps: - - name: evaluate upstream job results - run: | - # exit 1 if failure or cancelled result for any upstream job - if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then - printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" - exit 1 - fi - - name: Notify Slack - if: ${{ failure() }} - id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 - with: - payload: | - { - "message": "One or more nightly integration tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_NIGHTLY_INTEG_TEST_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-integrations-1.17.x.yml b/.github/workflows/nightly-test-integrations-1.17.x.yml deleted file mode 100644 index 660a28374b78..000000000000 --- a/.github/workflows/nightly-test-integrations-1.17.x.yml +++ /dev/null @@ -1,342 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Nightly test-integrations 1.17.x - -on: - schedule: - # Run nightly at 1AM UTC/9PM EST/6PM PST - - cron: '* 1 * * *' - workflow_dispatch: {} - -env: - TEST_RESULTS_DIR: /tmp/test-results - TEST_RESULTS_ARTIFACT_NAME: test-results - CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} - GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} - GOTESTSUM_VERSION: "1.10.1" - CONSUL_BINARY_UPLOAD_NAME: consul-bin - # strip the hashicorp/ off the front of github.repository for consul - CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - BRANCH: "release/1.17.x" - BRANCH_NAME: "release-1.17.x" # Used for naming artifacts - -jobs: - setup: - runs-on: ubuntu-latest - name: Setup - outputs: - compute-small: ${{ steps.runners.outputs.compute-small }} - compute-medium: ${{ steps.runners.outputs.compute-medium }} - compute-large: ${{ steps.runners.outputs.compute-large }} - compute-xl: ${{ steps.runners.outputs.compute-xl }} - enterprise: ${{ steps.runners.outputs.enterprise }} - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - id: runners - run: .github/scripts/get_runner_classes.sh - - dev-build: - needs: [setup] - uses: ./.github/workflows/reusable-dev-build.yml - with: - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - uploaded-binary-name: 'consul-bin' - branch-name: "release/1.17.x" - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - generate-envoy-job-matrices: - needs: [setup] - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - name: Generate Envoy Job Matrices - outputs: - envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - name: Generate Envoy Job Matrix - id: set-matrix - env: - # this is further going to multiplied in envoy-integration tests by the - # other dimensions in the matrix. Currently TOTAL_RUNNERS would be - # multiplied by 8 based on these values: - # envoy-version: ["1.24.12", "1.25.11", "1.26.6", "1.27.2"] - # xds-target: ["server", "client"] - TOTAL_RUNNERS: 4 - JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' - run: | - NUM_RUNNERS=$TOTAL_RUNNERS - NUM_DIRS=$(find ./test/integration/connect/envoy -mindepth 1 -maxdepth 1 -type d | wc -l) - - if [ "$NUM_DIRS" -lt "$NUM_RUNNERS" ]; then - echo "TOTAL_RUNNERS is larger than the number of tests/packages to split." - NUM_RUNNERS=$((NUM_DIRS-1)) - fi - # fix issue where test splitting calculation generates 1 more split than TOTAL_RUNNERS. - NUM_RUNNERS=$((NUM_RUNNERS-1)) - { - echo -n "envoy-matrix=" - find ./test/integration/connect/envoy -maxdepth 1 -type d -print0 \ - | xargs -0 -n 1 basename \ - | jq --raw-input --argjson runnercount "$NUM_RUNNERS" "$JQ_SLICER" \ - | jq --compact-output 'map(join("|"))' - } >> "$GITHUB_OUTPUT" - - envoy-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - needs: - - setup - - generate-envoy-job-matrices - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - envoy-version: ["1.24.12", "1.25.11", "1.26.6", "1.27.2"] - xds-target: ["server", "client"] - test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} - env: - ENVOY_VERSION: ${{ matrix.envoy-version }} - XDS_TARGET: ${{ matrix.xds-target }} - AWS_LAMBDA_REGION: us-west-2 - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: ./bin - - name: restore mode+x - run: chmod +x ./bin/consul - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 - - - name: Docker build - run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin - - - name: Envoy Integration Tests - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running $(sed 's,|, ,g' <<< "${{ matrix.test-cases }}" |wc -w) subtests" - # shellcheck disable=SC2001 - sed 's,|,\n,g' <<< "${{ matrix.test-cases }}" - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --debug \ - --rerun-fails \ - --rerun-fails-report=/tmp/gotestsum-rerun-fails \ - --jsonfile /tmp/jsonfile/go-test.log \ - --packages=./test/integration/connect/envoy \ - -- -timeout=30m -tags integration -run="TestEnvoy/(${{ matrix.test-cases }})" - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - upgrade-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - needs: - - setup - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - consul-version: ["1.15", "1.16", "1.17"] - env: - CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} - ENVOY_VERSION: "1.24.6" - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: go env - - # Get go binary from workspace - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: . - - name: restore mode+x - run: chmod +x consul - - name: Build consul:local image - run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . - - name: Build consul-envoy:latest-version image - id: buildConsulEnvoyLatestImage - run: | - if ${{ endsWith(github.repository, '-enterprise') }} == 'true' - then - docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }}-ent --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - else - docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }} --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - fi - - name: Build consul-envoy:target-version image - id: buildConsulEnvoyTargetImage - continue-on-error: true - run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - - name: Retry Build consul-envoy:target-version image - if: steps.buildConsulEnvoyTargetImage.outcome == 'failure' - run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - - name: Build sds image - run: docker build -t consul-sds-server ./test/integration/connect/envoy/test-sds-server/ - - name: Configure GH workaround for ipv6 loopback - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - cat /etc/hosts && echo "-----------" - sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6-localhost ip6-loopback/g' /etc/hosts - cat /etc/hosts - - name: Upgrade Integration Tests - run: | - mkdir -p "${{ env.TEST_RESULTS_DIR }}" - cd ./test/integration/consul-container/test/upgrade - docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --raw-command \ - --format=short-verbose \ - --debug \ - --rerun-fails=2 \ - --packages="./..." \ - -- \ - go test \ - -p=4 \ - -tags "${{ env.GOTAGS }}" \ - -timeout=30m \ - -json \ - ./... \ - --follow-log=false \ - --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --target-version local \ - --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --latest-version "${{ env.CONSUL_LATEST_VERSION }}" - ls -lrt - env: - # this is needed because of incompatibility between RYUK container and GHA - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - # tput complains if this isn't set to something. - TERM: ansi - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - - test-integrations-success: - needs: - - setup - - dev-build - - generate-envoy-job-matrices - - envoy-integration-test - - upgrade-integration-test - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - if: ${{ always() }} - steps: - - name: evaluate upstream job results - run: | - # exit 1 if failure or cancelled result for any upstream job - if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then - printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" - exit 1 - fi - - name: Notify Slack - if: ${{ failure() }} - id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 - with: - payload: | - { - "message": "One or more nightly integration tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_NIGHTLY_INTEG_TEST_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-integrations-1.18.x.yml b/.github/workflows/nightly-test-integrations-1.18.x.yml new file mode 100644 index 000000000000..77af4b9df0cf --- /dev/null +++ b/.github/workflows/nightly-test-integrations-1.18.x.yml @@ -0,0 +1,482 @@ +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Nightly test-integrations 1.18.x +# +#on: +# schedule: +# # Run nightly at 1AM UTC/9PM EST/6PM PST +# - cron: '0 1 * * *' +# workflow_dispatch: {} +# +#env: +# TEST_RESULTS_DIR: /tmp/test-results +# TEST_RESULTS_ARTIFACT_NAME: test-results +# CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} +# GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} +# GOTESTSUM_VERSION: "1.11.0" +# CONSUL_BINARY_UPLOAD_NAME: consul-bin +# # strip the hashicorp/ off the front of github.repository for consul +# CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# BRANCH: "release/1.18.x" +# BRANCH_NAME: "release-1.18.x" # Used for naming artifacts +# +#jobs: +# check-ent: +# runs-on: ubuntu-latest +# if: ${{ endsWith(github.repository, '-enterprise') }} +# steps: +# - run: echo "Building Enterprise" +# +# setup: +# runs-on: ubuntu-latest +# needs: [check-ent] +# name: Setup +# outputs: +# compute-small: ${{ steps.runners.outputs.compute-small }} +# compute-medium: ${{ steps.runners.outputs.compute-medium }} +# compute-large: ${{ steps.runners.outputs.compute-large }} +# compute-xl: ${{ steps.runners.outputs.compute-xl }} +# enterprise: ${{ steps.runners.outputs.enterprise }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# - id: runners +# run: .github/scripts/get_runner_classes.sh +# +# get-go-version: +# needs: [check-ent] +# uses: ./.github/workflows/reusable-get-go-version.yml +# with: +# ref: release/1.18.x +# +# get-envoy-versions: +# needs: [check-ent] +# uses: ./.github/workflows/reusable-get-envoy-versions.yml +# with: +# ref: release/1.18.x +# +# dev-build: +# needs: +# - setup +# - get-go-version +# uses: ./.github/workflows/reusable-dev-build.yml +# with: +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# uploaded-binary-name: 'consul-bin' +# branch-name: "release/1.18.x" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# generate-envoy-job-matrices: +# needs: [setup] +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# name: Generate Envoy Job Matrices +# outputs: +# envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# - name: Generate Envoy Job Matrix +# id: set-matrix +# env: +# # TEST_SPLITS sets the number of test case splits to use in the matrix. This will be +# # further multiplied in envoy-integration tests by the other dimensions in the matrix +# # to determine the total number of runners used. +# TEST_SPLITS: 4 +# JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' +# run: | +# NUM_DIRS=$(find ./test/integration/connect/envoy -mindepth 1 -maxdepth 1 -type d | wc -l) +# +# if [ "$NUM_DIRS" -lt "$TEST_SPLITS" ]; then +# echo "TEST_SPLITS is larger than the number of tests/packages to split." +# TEST_SPLITS=$((NUM_DIRS-1)) +# fi +# # fix issue where test splitting calculation generates 1 more split than TEST_SPLITS. +# TEST_SPLITS=$((TEST_SPLITS-1)) +# { +# echo -n "envoy-matrix=" +# find ./test/integration/connect/envoy -maxdepth 1 -type d -print0 \ +# | xargs -0 -n 1 basename \ +# | jq --raw-input --argjson runnercount "$TEST_SPLITS" "$JQ_SLICER" \ +# | jq --compact-output 'map(join("|"))' +# } >> "$GITHUB_OUTPUT" +# +# envoy-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# needs: +# - setup +# - get-go-version +# - get-envoy-versions +# - generate-envoy-job-matrices +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# envoy-version: ${{ fromJSON(needs.get-envoy-versions.outputs.envoy-versions-json) }} +# xds-target: ["server", "client"] +# test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} +# env: +# ENVOY_VERSION: ${{ matrix.envoy-version }} +# XDS_TARGET: ${{ matrix.xds-target }} +# AWS_LAMBDA_REGION: us-west-2 +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# +# - name: fetch binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: ./bin +# - name: restore mode+x +# run: chmod +x ./bin/consul +# +# - name: Set up Docker Buildx +# uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 +# +# - name: Docker build +# run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin +# +# - name: Envoy Integration Tests +# id: envoy-integration-tests +# env: +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# LAMBDA_TESTS_ENABLED: "true" +# # tput complains if this isn't set to something. +# TERM: ansi +# run: | +# # shellcheck disable=SC2001 +# echo "Running $(sed 's,|, ,g' <<< "${{ matrix.test-cases }}" |wc -w) subtests" +# # shellcheck disable=SC2001 +# sed 's,|,\n,g' <<< "${{ matrix.test-cases }}" +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --debug \ +# --rerun-fails \ +# --rerun-fails-report=/tmp/gotestsum-rerun-fails \ +# --jsonfile /tmp/jsonfile/go-test.log \ +# --packages=./test/integration/connect/envoy \ +# -- -timeout=30m -tags integration -run="TestEnvoy/(${{ matrix.test-cases }})" +# +# # See https://github.com/orgs/community/discussions/8945#discussioncomment-9897011 +# # and overall topic discussion for why this is necessary. +# - name: Generate artifact ID +# id: generate-artifact-id +# if: ${{ failure() && steps.envoy-integration-tests.conclusion == 'failure' }} +# run: | +# ARTIFACT_ID=$(uuidgen) +# echo "Artifact ID: $ARTIFACT_ID (search this in job summary for download link)" +# echo "artifact_id=$ARTIFACT_ID" >> "$GITHUB_ENV" +# +# - name: Upload failure logs +# if: ${{ failure() && steps.envoy-integration-tests.conclusion == 'failure' }} +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: envoy-${{ matrix.envoy-version }}-logs-${{ env.artifact_id }} +# path: test/integration/connect/envoy/workdir/logs/ +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# upgrade-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# needs: +# - setup +# - get-go-version +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# consul-version: ["1.15", "1.16", "1.17", "1.18"] +# env: +# CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} +# # ENVOY_VERSION should be the latest version supported by _all_ Consul versions in the +# # matrix.consul-version, since we are testing upgrade from an older Consul version. +# # In practice, this should be the highest Envoy version supported by the lowest non-LTS +# # Consul version in the matrix (LTS versions receive additional Envoy version support). +# # +# # This value should be kept current in new nightly test workflows, and updated any time +# # a new major Envoy release is added to the set supported by Consul versions in +# # matrix.consul-version (i.e. whenever the highest common Envoy version across active +# # Consul versions changes). The minor Envoy version does not necessarily need to be +# # kept current for the purpose of these tests, but the major (1.N) version should be. +# ENVOY_VERSION: 1.27.6 +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go env +# +# # Get go binary from workspace +# - name: fetch binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: . +# - name: restore mode+x +# run: chmod +x consul +# - name: Build consul:local image +# run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . +# - name: Build consul-envoy:latest-version image +# id: buildConsulEnvoyLatestImage +# run: | +# if ${{ endsWith(github.repository, '-enterprise') }} == 'true' +# then +# docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }}-ent --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# else +# docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }} --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# fi +# - name: Build consul-envoy:target-version image +# id: buildConsulEnvoyTargetImage +# continue-on-error: true +# run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# - name: Retry Build consul-envoy:target-version image +# if: steps.buildConsulEnvoyTargetImage.outcome == 'failure' +# run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# - name: Build sds image +# run: docker build -t consul-sds-server ./test/integration/connect/envoy/test-sds-server/ +# - name: Configure GH workaround for ipv6 loopback +# if: ${{ !endsWith(github.repository, '-enterprise') }} +# run: | +# cat /etc/hosts && echo "-----------" +# sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6-localhost ip6-loopback/g' /etc/hosts +# cat /etc/hosts +# - name: Upgrade Integration Tests +# run: | +# mkdir -p "${{ env.TEST_RESULTS_DIR }}" +# cd ./test/integration/consul-container/test/upgrade +# docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --raw-command \ +# --format=github-actions \ +# --rerun-fails \ +# --packages="./..." \ +# -- \ +# go test \ +# -p=4 \ +# -tags "${{ env.GOTAGS }}" \ +# -timeout=30m \ +# -json \ +# ./... \ +# --follow-log=false \ +# --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --target-version local \ +# --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --latest-version "${{ env.CONSUL_LATEST_VERSION }}" +# ls -lrt +# env: +# # this is needed because of incompatibility between RYUK container and GHA +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# # tput complains if this isn't set to something. +# TERM: ansi +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# upgrade-integration-test-deployer: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} +# needs: +# - setup +# - get-go-version +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# consul-version: [ "1.15", "1.16", "1.17"] +# env: +# CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go env +# - name: Build image +# run: make test-deployer-setup +# - name: Upgrade Integration Tests +# run: | +# mkdir -p "${{ env.TEST_RESULTS_DIR }}" +# export NOLOGBUFFER=1 +# cd ./test-integ/upgrade +# docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --raw-command \ +# --format=standard-verbose \ +# --debug \ +# --packages="./..." \ +# -- \ +# go test \ +# -tags "${{ env.GOTAGS }}" \ +# -timeout=60m \ +# -parallel=2 \ +# -json \ +# ./... \ +# --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --target-version local \ +# --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --latest-version "${{ env.CONSUL_LATEST_VERSION }}" +# env: +# # this is needed because of incompatibility between RYUK container and GHA +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# # tput complains if this isn't set to something. +# TERM: ansi +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# test-integrations-success: +# needs: +# - setup +# - dev-build +# - generate-envoy-job-matrices +# - envoy-integration-test +# - upgrade-integration-test +# - upgrade-integration-test-deployer +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# if: ${{ always() && endsWith(github.repository, '-enterprise') }} +# steps: +# - name: evaluate upstream job results +# run: | +# # exit 1 if failure or cancelled result for any upstream job +# if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then +# printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" +# exit 1 +# fi +# - name: Notify Slack +# if: ${{ failure() }} +# id: slack +# uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 +# with: +# payload: | +# { +# "message": "One or more nightly integration tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" +# } +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_NIGHTLY_INTEG_TEST_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-integrations-1.19.x.yml b/.github/workflows/nightly-test-integrations-1.19.x.yml new file mode 100644 index 000000000000..2301329bc29e --- /dev/null +++ b/.github/workflows/nightly-test-integrations-1.19.x.yml @@ -0,0 +1,474 @@ +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Nightly test-integrations 1.19.x +# +#on: +# schedule: +# # Run nightly at 1AM UTC/9PM EST/6PM PST +# - cron: '0 1 * * *' +# workflow_dispatch: {} +# +#env: +# TEST_RESULTS_DIR: /tmp/test-results +# TEST_RESULTS_ARTIFACT_NAME: test-results +# CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} +# GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} +# GOTESTSUM_VERSION: "1.11.0" +# CONSUL_BINARY_UPLOAD_NAME: consul-bin +# # strip the hashicorp/ off the front of github.repository for consul +# CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# BRANCH: "release/1.19.x" +# BRANCH_NAME: "release-1.19.x" # Used for naming artifacts +# +#jobs: +# setup: +# runs-on: ubuntu-latest +# name: Setup +# outputs: +# compute-small: ${{ steps.runners.outputs.compute-small }} +# compute-medium: ${{ steps.runners.outputs.compute-medium }} +# compute-large: ${{ steps.runners.outputs.compute-large }} +# compute-xl: ${{ steps.runners.outputs.compute-xl }} +# enterprise: ${{ steps.runners.outputs.enterprise }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# - id: runners +# run: .github/scripts/get_runner_classes.sh +# +# get-go-version: +# uses: ./.github/workflows/reusable-get-go-version.yml +# with: +# ref: release/1.19.x +# +# get-envoy-versions: +# uses: ./.github/workflows/reusable-get-envoy-versions.yml +# with: +# ref: release/1.19.x +# +# dev-build: +# needs: +# - setup +# - get-go-version +# uses: ./.github/workflows/reusable-dev-build.yml +# with: +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# uploaded-binary-name: 'consul-bin' +# branch-name: "release/1.19.x" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# generate-envoy-job-matrices: +# needs: [setup] +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# name: Generate Envoy Job Matrices +# outputs: +# envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# - name: Generate Envoy Job Matrix +# id: set-matrix +# env: +# # TEST_SPLITS sets the number of test case splits to use in the matrix. This will be +# # further multiplied in envoy-integration tests by the other dimensions in the matrix +# # to determine the total number of runners used. +# TEST_SPLITS: 4 +# JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' +# run: | +# NUM_DIRS=$(find ./test/integration/connect/envoy -mindepth 1 -maxdepth 1 -type d | wc -l) +# +# if [ "$NUM_DIRS" -lt "$TEST_SPLITS" ]; then +# echo "TEST_SPLITS is larger than the number of tests/packages to split." +# TEST_SPLITS=$((NUM_DIRS-1)) +# fi +# # fix issue where test splitting calculation generates 1 more split than TEST_SPLITS. +# TEST_SPLITS=$((TEST_SPLITS-1)) +# { +# echo -n "envoy-matrix=" +# find ./test/integration/connect/envoy -maxdepth 1 -type d -print0 \ +# | xargs -0 -n 1 basename \ +# | jq --raw-input --argjson runnercount "$TEST_SPLITS" "$JQ_SLICER" \ +# | jq --compact-output 'map(join("|"))' +# } >> "$GITHUB_OUTPUT" +# +# envoy-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# needs: +# - setup +# - get-go-version +# - get-envoy-versions +# - generate-envoy-job-matrices +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# envoy-version: ${{ fromJSON(needs.get-envoy-versions.outputs.envoy-versions-json) }} +# xds-target: ["server", "client"] +# test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} +# env: +# ENVOY_VERSION: ${{ matrix.envoy-version }} +# XDS_TARGET: ${{ matrix.xds-target }} +# AWS_LAMBDA_REGION: us-west-2 +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# +# - name: fetch binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: ./bin +# - name: restore mode+x +# run: chmod +x ./bin/consul +# +# - name: Set up Docker Buildx +# uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 +# +# - name: Docker build +# run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin +# +# - name: Envoy Integration Tests +# id: envoy-integration-tests +# env: +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# LAMBDA_TESTS_ENABLED: "true" +# # tput complains if this isn't set to something. +# TERM: ansi +# run: | +# # shellcheck disable=SC2001 +# echo "Running $(sed 's,|, ,g' <<< "${{ matrix.test-cases }}" |wc -w) subtests" +# # shellcheck disable=SC2001 +# sed 's,|,\n,g' <<< "${{ matrix.test-cases }}" +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --debug \ +# --rerun-fails \ +# --rerun-fails-report=/tmp/gotestsum-rerun-fails \ +# --jsonfile /tmp/jsonfile/go-test.log \ +# --packages=./test/integration/connect/envoy \ +# -- -timeout=30m -tags integration -run="TestEnvoy/(${{ matrix.test-cases }})" +# +# # See https://github.com/orgs/community/discussions/8945#discussioncomment-9897011 +# # and overall topic discussion for why this is necessary. +# - name: Generate artifact ID +# id: generate-artifact-id +# if: ${{ failure() && steps.envoy-integration-tests.conclusion == 'failure' }} +# run: | +# ARTIFACT_ID=$(uuidgen) +# echo "Artifact ID: $ARTIFACT_ID (search this in job summary for download link)" +# echo "artifact_id=$ARTIFACT_ID" >> "$GITHUB_ENV" +# +# - name: Upload failure logs +# if: ${{ failure() && steps.envoy-integration-tests.conclusion == 'failure' }} +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: envoy-${{ matrix.envoy-version }}-logs-${{ env.artifact_id }} +# path: test/integration/connect/envoy/workdir/logs/ +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# upgrade-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# needs: +# - setup +# - get-go-version +# - get-envoy-versions +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# consul-version: ["1.15", "1.17", "1.18", "1.19"] +# env: +# CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} +# # ENVOY_VERSION should be the latest version supported by _all_ Consul versions in the +# # matrix.consul-version, since we are testing upgrade from an older Consul version. +# # In practice, this should be the highest Envoy version supported by the lowest non-LTS +# # Consul version in the matrix (LTS versions receive additional Envoy version support). +# # +# # This value should be kept current in new nightly test workflows, and updated any time +# # a new major Envoy release is added to the set supported by Consul versions in +# # matrix.consul-version (i.e. whenever the highest common Envoy version across active +# # Consul versions changes). The minor Envoy version does not necessarily need to be +# # kept current for the purpose of these tests, but the major (1.N) version should be. +# ENVOY_VERSION: 1.27.6 +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go env +# +# # Get go binary from workspace +# - name: fetch binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: . +# - name: restore mode+x +# run: chmod +x consul +# - name: Build consul:local image +# run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . +# - name: Build consul-envoy:latest-version image +# id: buildConsulEnvoyLatestImage +# run: | +# if ${{ endsWith(github.repository, '-enterprise') }} == 'true' +# then +# docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }}-ent --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# else +# docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }} --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# fi +# - name: Build consul-envoy:target-version image +# id: buildConsulEnvoyTargetImage +# continue-on-error: true +# run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# - name: Retry Build consul-envoy:target-version image +# if: steps.buildConsulEnvoyTargetImage.outcome == 'failure' +# run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# - name: Build sds image +# run: docker build -t consul-sds-server ./test/integration/connect/envoy/test-sds-server/ +# - name: Configure GH workaround for ipv6 loopback +# if: ${{ !endsWith(github.repository, '-enterprise') }} +# run: | +# cat /etc/hosts && echo "-----------" +# sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6-localhost ip6-loopback/g' /etc/hosts +# cat /etc/hosts +# - name: Upgrade Integration Tests +# run: | +# mkdir -p "${{ env.TEST_RESULTS_DIR }}" +# cd ./test/integration/consul-container/test/upgrade +# docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --raw-command \ +# --format=github-actions \ +# --rerun-fails \ +# --packages="./..." \ +# -- \ +# go test \ +# -p=4 \ +# -tags "${{ env.GOTAGS }}" \ +# -timeout=30m \ +# -json \ +# ./... \ +# --follow-log=false \ +# --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --target-version local \ +# --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --latest-version "${{ env.CONSUL_LATEST_VERSION }}" +# ls -lrt +# env: +# # this is needed because of incompatibility between RYUK container and GHA +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# # tput complains if this isn't set to something. +# TERM: ansi +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# upgrade-integration-test-deployer: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} +# needs: +# - setup +# - get-go-version +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# consul-version: ["1.15", "1.17", "1.18"] +# env: +# CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go env +# - name: Build image +# run: make test-deployer-setup +# - name: Upgrade Integration Tests +# run: | +# mkdir -p "${{ env.TEST_RESULTS_DIR }}" +# export NOLOGBUFFER=1 +# cd ./test-integ/upgrade +# docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --raw-command \ +# --format=standard-verbose \ +# --debug \ +# --packages="./..." \ +# -- \ +# go test \ +# -tags "${{ env.GOTAGS }}" \ +# -timeout=60m \ +# -parallel=2 \ +# -json \ +# ./... \ +# --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --target-version local \ +# --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --latest-version "${{ env.CONSUL_LATEST_VERSION }}" +# env: +# # this is needed because of incompatibility between RYUK container and GHA +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# # tput complains if this isn't set to something. +# TERM: ansi +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# test-integrations-success: +# needs: +# - setup +# - dev-build +# - generate-envoy-job-matrices +# - envoy-integration-test +# - upgrade-integration-test +# - upgrade-integration-test-deployer +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# if: ${{ always() }} +# steps: +# - name: evaluate upstream job results +# run: | +# # exit 1 if failure or cancelled result for any upstream job +# if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then +# printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" +# exit 1 +# fi +# - name: Notify Slack +# if: ${{ failure() }} +# id: slack +# uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 +# with: +# payload: | +# { +# "message": "One or more nightly integration tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" +# } +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_NIGHTLY_INTEG_TEST_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-integrations-1.20.x.yml b/.github/workflows/nightly-test-integrations-1.20.x.yml new file mode 100644 index 000000000000..bf068b634eca --- /dev/null +++ b/.github/workflows/nightly-test-integrations-1.20.x.yml @@ -0,0 +1,474 @@ +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Nightly test-integrations 1.20.x +# +#on: +# schedule: +# # Run nightly at 1AM UTC/9PM EST/6PM PST +# - cron: '0 1 * * *' +# workflow_dispatch: {} +# +#env: +# TEST_RESULTS_DIR: /tmp/test-results +# TEST_RESULTS_ARTIFACT_NAME: test-results +# CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} +# GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} +# GOTESTSUM_VERSION: "1.11.0" +# CONSUL_BINARY_UPLOAD_NAME: consul-bin +# # strip the hashicorp/ off the front of github.repository for consul +# CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# BRANCH: "release/1.20.x" +# BRANCH_NAME: "release-1.20.x" # Used for naming artifacts +# +#jobs: +# setup: +# runs-on: ubuntu-latest +# name: Setup +# outputs: +# compute-small: ${{ steps.runners.outputs.compute-small }} +# compute-medium: ${{ steps.runners.outputs.compute-medium }} +# compute-large: ${{ steps.runners.outputs.compute-large }} +# compute-xl: ${{ steps.runners.outputs.compute-xl }} +# enterprise: ${{ steps.runners.outputs.enterprise }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# - id: runners +# run: .github/scripts/get_runner_classes.sh +# +# get-go-version: +# uses: ./.github/workflows/reusable-get-go-version.yml +# with: +# ref: release/1.20.x +# +# get-envoy-versions: +# uses: ./.github/workflows/reusable-get-envoy-versions.yml +# with: +# ref: release/1.20.x +# +# dev-build: +# needs: +# - setup +# - get-go-version +# uses: ./.github/workflows/reusable-dev-build.yml +# with: +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# uploaded-binary-name: 'consul-bin' +# branch-name: "release/1.20.x" +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# generate-envoy-job-matrices: +# needs: [setup] +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# name: Generate Envoy Job Matrices +# outputs: +# envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# - name: Generate Envoy Job Matrix +# id: set-matrix +# env: +# # TEST_SPLITS sets the number of test case splits to use in the matrix. This will be +# # further multiplied in envoy-integration tests by the other dimensions in the matrix +# # to determine the total number of runners used. +# TEST_SPLITS: 4 +# JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' +# run: | +# NUM_DIRS=$(find ./test/integration/connect/envoy -mindepth 1 -maxdepth 1 -type d | wc -l) +# +# if [ "$NUM_DIRS" -lt "$TEST_SPLITS" ]; then +# echo "TEST_SPLITS is larger than the number of tests/packages to split." +# TEST_SPLITS=$((NUM_DIRS-1)) +# fi +# # fix issue where test splitting calculation generates 1 more split than TEST_SPLITS. +# TEST_SPLITS=$((TEST_SPLITS-1)) +# { +# echo -n "envoy-matrix=" +# find ./test/integration/connect/envoy -maxdepth 1 -type d -print0 \ +# | xargs -0 -n 1 basename \ +# | jq --raw-input --argjson runnercount "$TEST_SPLITS" "$JQ_SLICER" \ +# | jq --compact-output 'map(join("|"))' +# } >> "$GITHUB_OUTPUT" +# +# envoy-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# needs: +# - setup +# - get-go-version +# - get-envoy-versions +# - generate-envoy-job-matrices +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# envoy-version: ${{ fromJSON(needs.get-envoy-versions.outputs.envoy-versions-json) }} +# xds-target: ["server", "client"] +# test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} +# env: +# ENVOY_VERSION: ${{ matrix.envoy-version }} +# XDS_TARGET: ${{ matrix.xds-target }} +# AWS_LAMBDA_REGION: us-west-2 +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# +# - name: fetch binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: ./bin +# - name: restore mode+x +# run: chmod +x ./bin/consul +# +# - name: Set up Docker Buildx +# uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 +# +# - name: Docker build +# run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin +# +# - name: Envoy Integration Tests +# id: envoy-integration-tests +# env: +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# LAMBDA_TESTS_ENABLED: "true" +# # tput complains if this isn't set to something. +# TERM: ansi +# run: | +# # shellcheck disable=SC2001 +# echo "Running $(sed 's,|, ,g' <<< "${{ matrix.test-cases }}" |wc -w) subtests" +# # shellcheck disable=SC2001 +# sed 's,|,\n,g' <<< "${{ matrix.test-cases }}" +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --debug \ +# --rerun-fails \ +# --rerun-fails-report=/tmp/gotestsum-rerun-fails \ +# --jsonfile /tmp/jsonfile/go-test.log \ +# --packages=./test/integration/connect/envoy \ +# -- -timeout=30m -tags integration -run="TestEnvoy/(${{ matrix.test-cases }})" +# +# # See https://github.com/orgs/community/discussions/8945#discussioncomment-9897011 +# # and overall topic discussion for why this is necessary. +# - name: Generate artifact ID +# id: generate-artifact-id +# if: ${{ failure() && steps.envoy-integration-tests.conclusion == 'failure' }} +# run: | +# ARTIFACT_ID=$(uuidgen) +# echo "Artifact ID: $ARTIFACT_ID (search this in job summary for download link)" +# echo "artifact_id=$ARTIFACT_ID" >> "$GITHUB_ENV" +# +# - name: Upload failure logs +# if: ${{ failure() && steps.envoy-integration-tests.conclusion == 'failure' }} +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: envoy-${{ matrix.envoy-version }}-logs-${{ env.artifact_id }} +# path: test/integration/connect/envoy/workdir/logs/ +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# upgrade-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# needs: +# - setup +# - get-go-version +# - get-envoy-versions +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# consul-version: ["1.15", "1.18", "1.19"] +# env: +# CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} +# # ENVOY_VERSION should be the latest version supported by _all_ Consul versions in the +# # matrix.consul-version, since we are testing upgrade from an older Consul version. +# # In practice, this should be the highest Envoy version supported by the lowest non-LTS +# # Consul version in the matrix (LTS versions receive additional Envoy version support). +# # +# # This value should be kept current in new nightly test workflows, and updated any time +# # a new major Envoy release is added to the set supported by Consul versions in +# # matrix.consul-version (i.e. whenever the highest common Envoy version across active +# # Consul versions changes). The minor Envoy version does not necessarily need to be +# # kept current for the purpose of these tests, but the major (1.N) version should be. +# ENVOY_VERSION: 1.28.7 +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go env +# +# # Get go binary from workspace +# - name: fetch binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: . +# - name: restore mode+x +# run: chmod +x consul +# - name: Build consul:local image +# run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . +# - name: Build consul-envoy:latest-version image +# id: buildConsulEnvoyLatestImage +# run: | +# if ${{ endsWith(github.repository, '-enterprise') }} == 'true' +# then +# docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }}-ent --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# else +# docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }} --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# fi +# - name: Build consul-envoy:target-version image +# id: buildConsulEnvoyTargetImage +# continue-on-error: true +# run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# - name: Retry Build consul-envoy:target-version image +# if: steps.buildConsulEnvoyTargetImage.outcome == 'failure' +# run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# - name: Build sds image +# run: docker build -t consul-sds-server ./test/integration/connect/envoy/test-sds-server/ +# - name: Configure GH workaround for ipv6 loopback +# if: ${{ !endsWith(github.repository, '-enterprise') }} +# run: | +# cat /etc/hosts && echo "-----------" +# sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6-localhost ip6-loopback/g' /etc/hosts +# cat /etc/hosts +# - name: Upgrade Integration Tests +# run: | +# mkdir -p "${{ env.TEST_RESULTS_DIR }}" +# cd ./test/integration/consul-container/test/upgrade +# docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --raw-command \ +# --format=github-actions \ +# --rerun-fails \ +# --packages="./..." \ +# -- \ +# go test \ +# -p=4 \ +# -tags "${{ env.GOTAGS }}" \ +# -timeout=30m \ +# -json \ +# ./... \ +# --follow-log=false \ +# --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --target-version local \ +# --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --latest-version "${{ env.CONSUL_LATEST_VERSION }}" +# ls -lrt +# env: +# # this is needed because of incompatibility between RYUK container and GHA +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# # tput complains if this isn't set to something. +# TERM: ansi +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# upgrade-integration-test-deployer: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} +# needs: +# - setup +# - get-go-version +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# consul-version: ["1.15", "1.18", "1.19"] +# env: +# CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go env +# - name: Build image +# run: make test-deployer-setup +# - name: Upgrade Integration Tests +# run: | +# mkdir -p "${{ env.TEST_RESULTS_DIR }}" +# export NOLOGBUFFER=1 +# cd ./test-integ/upgrade +# docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --raw-command \ +# --format=standard-verbose \ +# --debug \ +# --packages="./..." \ +# -- \ +# go test \ +# -tags "${{ env.GOTAGS }}" \ +# -timeout=60m \ +# -parallel=2 \ +# -json \ +# ./... \ +# --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --target-version local \ +# --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --latest-version "${{ env.CONSUL_LATEST_VERSION }}" +# env: +# # this is needed because of incompatibility between RYUK container and GHA +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# # tput complains if this isn't set to something. +# TERM: ansi +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# test-integrations-success: +# needs: +# - setup +# - dev-build +# - generate-envoy-job-matrices +# - envoy-integration-test +# - upgrade-integration-test +# - upgrade-integration-test-deployer +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# if: ${{ always() }} +# steps: +# - name: evaluate upstream job results +# run: | +# # exit 1 if failure or cancelled result for any upstream job +# if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then +# printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" +# exit 1 +# fi +# - name: Notify Slack +# if: ${{ failure() }} +# id: slack +# uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 +# with: +# payload: | +# { +# "message": "One or more nightly integration tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" +# } +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_NIGHTLY_INTEG_TEST_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-integrations.yml b/.github/workflows/nightly-test-integrations.yml index bab962f23eaa..e68666ba4293 100644 --- a/.github/workflows/nightly-test-integrations.yml +++ b/.github/workflows/nightly-test-integrations.yml @@ -1,433 +1,448 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Nightly test-integrations - -on: - schedule: - # Run nightly at 12AM UTC/8PM EST/5PM PST - - cron: '* 0 * * *' - workflow_dispatch: {} - -env: - TEST_RESULTS_DIR: /tmp/test-results - TEST_RESULTS_ARTIFACT_NAME: test-results - CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} - GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} - GOTESTSUM_VERSION: "1.10.1" - CONSUL_BINARY_UPLOAD_NAME: consul-bin - # strip the hashicorp/ off the front of github.repository for consul - CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - -jobs: - setup: - runs-on: ubuntu-latest - name: Setup - outputs: - compute-small: ${{ steps.runners.outputs.compute-small }} - compute-medium: ${{ steps.runners.outputs.compute-medium }} - compute-large: ${{ steps.runners.outputs.compute-large }} - compute-xl: ${{ steps.runners.outputs.compute-xl }} - enterprise: ${{ steps.runners.outputs.enterprise }} - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ inputs.branch }} - - id: runners - run: .github/scripts/get_runner_classes.sh - - dev-build: - needs: [setup] - uses: ./.github/workflows/reusable-dev-build.yml - with: - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - uploaded-binary-name: 'consul-bin' - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - generate-envoy-job-matrices: - needs: [setup] - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - name: Generate Envoy Job Matrices - outputs: - envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ inputs.branch }} - - name: Generate Envoy Job Matrix - id: set-matrix - env: - # this is further going to multiplied in envoy-integration tests by the - # other dimensions in the matrix. Currently TOTAL_RUNNERS would be - # multiplied by 8 based on these values: - # envoy-version: ["1.24.12", "1.25.11", "1.26.6", "1.27.2"] - # xds-target: ["server", "client"] - TOTAL_RUNNERS: 4 - JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' - run: | - NUM_RUNNERS=$TOTAL_RUNNERS - NUM_DIRS=$(find ./test/integration/connect/envoy -mindepth 1 -maxdepth 1 -type d | wc -l) - - if [ "$NUM_DIRS" -lt "$NUM_RUNNERS" ]; then - echo "TOTAL_RUNNERS is larger than the number of tests/packages to split." - NUM_RUNNERS=$((NUM_DIRS-1)) - fi - # fix issue where test splitting calculation generates 1 more split than TOTAL_RUNNERS. - NUM_RUNNERS=$((NUM_RUNNERS-1)) - { - echo -n "envoy-matrix=" - find ./test/integration/connect/envoy -maxdepth 1 -type d -print0 \ - | xargs -0 -n 1 basename \ - | jq --raw-input --argjson runnercount "$NUM_RUNNERS" "$JQ_SLICER" \ - | jq --compact-output 'map(join("|"))' - } >> "$GITHUB_OUTPUT" - - envoy-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} - needs: - - setup - - generate-envoy-job-matrices - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - envoy-version: ["1.24.12", "1.25.11", "1.26.6", "1.27.2"] - xds-target: ["server", "client"] - test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} - env: - ENVOY_VERSION: ${{ matrix.envoy-version }} - XDS_TARGET: ${{ matrix.xds-target }} - AWS_LAMBDA_REGION: us-west-2 - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ inputs.branch }} - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: ./bin - - name: restore mode+x - run: chmod +x ./bin/consul - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 - - - name: Docker build - run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin - - - name: Envoy Integration Tests - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running $(sed 's,|, ,g' <<< "${{ matrix.test-cases }}" |wc -w) subtests" - # shellcheck disable=SC2001 - sed 's,|,\n,g' <<< "${{ matrix.test-cases }}" - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --debug \ - --rerun-fails \ - --rerun-fails-report=/tmp/gotestsum-rerun-fails \ - --jsonfile /tmp/jsonfile/go-test.log \ - --packages=./test/integration/connect/envoy \ - -- -timeout=30m -tags integration -run="TestEnvoy/(${{ matrix.test-cases }})" - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - upgrade-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} - needs: - - setup - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - consul-version: [ "1.16", "1.17"] - env: - CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} - ENVOY_VERSION: "1.25.4" - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ inputs.branch }} - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: go env - - # Get go binary from workspace - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: . - - name: restore mode+x - run: chmod +x consul - - name: Build consul:local image - run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . - - name: Build consul-envoy:latest-version image - id: buildConsulEnvoyLatestImage - run: | - if ${{ endsWith(github.repository, '-enterprise') }} == 'true' - then - docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }}-ent --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - else - docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }} --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - fi - - name: Build consul-envoy:target-version image - id: buildConsulEnvoyTargetImage - continue-on-error: true - run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - - name: Retry Build consul-envoy:target-version image - if: steps.buildConsulEnvoyTargetImage.outcome == 'failure' - run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - - name: Build sds image - run: docker build -t consul-sds-server ./test/integration/connect/envoy/test-sds-server/ - - name: Configure GH workaround for ipv6 loopback - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - cat /etc/hosts && echo "-----------" - sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6-localhost ip6-loopback/g' /etc/hosts - cat /etc/hosts - - name: Upgrade Integration Tests - run: | - mkdir -p "${{ env.TEST_RESULTS_DIR }}" - cd ./test/integration/consul-container/test/upgrade - docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --raw-command \ - --format=short-verbose \ - --debug \ - --rerun-fails=2 \ - --packages="./..." \ - -- \ - go test \ - -p=4 \ - -tags "${{ env.GOTAGS }}" \ - -timeout=30m \ - -json \ - ./... \ - --follow-log=false \ - --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --target-version local \ - --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --latest-version "${{ env.CONSUL_LATEST_VERSION }}" - ls -lrt - env: - # this is needed because of incompatibility between RYUK container and GHA - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - # tput complains if this isn't set to something. - TERM: ansi - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - - peering_commontopo-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} - needs: - - setup - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - env: - ENVOY_VERSION: "1.24.6" - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: go env - - # Get go binary from workspace - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: . - - name: restore mode+x - run: chmod +x consul - - name: Build consul:local image - run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . - - name: Peering commonTopo Integration Tests - run: | - mkdir -p "${{ env.TEST_RESULTS_DIR }}" - cd ./test-integ/peering_commontopo - docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --raw-command \ - --format=short-verbose \ - --debug \ - --packages="./..." \ - -- \ - go test \ - -tags "${{ env.GOTAGS }}" \ - -timeout=30m \ - -json . \ - --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --target-version local \ - --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --latest-version latest - ls -lrt - env: - # this is needed because of incompatibility between RYUK container and GHA - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - # tput complains if this isn't set to something. - TERM: ansi - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - - test-integrations-success: - needs: - - setup - - dev-build - - generate-envoy-job-matrices - - envoy-integration-test - - upgrade-integration-test - - peering_commontopo-integration-test - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - if: ${{ always() }} - steps: - - name: evaluate upstream job results - run: | - # exit 1 if failure or cancelled result for any upstream job - if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then - printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" - exit 1 - fi - - name: Notify Slack - if: ${{ failure() }} - id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 - with: - payload: | - { - "message": "One or more nightly integration tests have failed. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_NIGHTLY_INTEG_TEST_SLACK_WEBHOOK }} +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Nightly test-integrations +# +#on: +# schedule: +# # Run nightly at 12AM UTC/8PM EST/5PM PST +# - cron: '0 0 * * *' +# workflow_dispatch: {} +# +#env: +# TEST_RESULTS_DIR: /tmp/test-results +# TEST_RESULTS_ARTIFACT_NAME: test-results +# CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} +# GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} +# GOTESTSUM_VERSION: "1.11.0" +# CONSUL_BINARY_UPLOAD_NAME: consul-bin +# # strip the hashicorp/ off the front of github.repository for consul +# CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +#jobs: +# setup: +# runs-on: ubuntu-latest +# name: Setup +# outputs: +# compute-small: ${{ steps.runners.outputs.compute-small }} +# compute-medium: ${{ steps.runners.outputs.compute-medium }} +# compute-large: ${{ steps.runners.outputs.compute-large }} +# compute-xl: ${{ steps.runners.outputs.compute-xl }} +# enterprise: ${{ steps.runners.outputs.enterprise }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ inputs.branch }} +# - id: runners +# run: .github/scripts/get_runner_classes.sh +# +# get-go-version: +# uses: ./.github/workflows/reusable-get-go-version.yml +# +# get-envoy-versions: +# uses: ./.github/workflows/reusable-get-envoy-versions.yml +# +# dev-build: +# needs: +# - setup +# - get-go-version +# uses: ./.github/workflows/reusable-dev-build.yml +# with: +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# uploaded-binary-name: 'consul-bin' +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# generate-envoy-job-matrices: +# needs: +# - setup +# - get-envoy-versions +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# name: Generate Envoy Job Matrices +# outputs: +# envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ inputs.branch }} +# - name: Generate Envoy Job Matrix +# id: set-matrix +# env: +# # TEST_SPLITS sets the number of test case splits to use in the matrix. This will be +# # further multiplied in envoy-integration tests by the other dimensions in the matrix +# # to determine the total number of runners used. +# TEST_SPLITS: 4 +# JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' +# run: | +# NUM_DIRS=$(find ./test/integration/connect/envoy -mindepth 1 -maxdepth 1 -type d | wc -l) +# +# if [ "$NUM_DIRS" -lt "$TEST_SPLITS" ]; then +# echo "TEST_SPLITS is larger than the number of tests/packages to split." +# TEST_SPLITS=$((NUM_DIRS-1)) +# fi +# # fix issue where test splitting calculation generates 1 more split than TEST_SPLITS. +# TEST_SPLITS=$((TEST_SPLITS-1)) +# { +# echo -n "envoy-matrix=" +# find ./test/integration/connect/envoy -maxdepth 1 -type d -print0 \ +# | xargs -0 -n 1 basename \ +# | jq --raw-input --argjson runnercount "$TEST_SPLITS" "$JQ_SLICER" \ +# | jq --compact-output 'map(join("|"))' +# } >> "$GITHUB_OUTPUT" +# +# envoy-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} +# needs: +# - setup +# - get-go-version +# - get-envoy-versions +# - generate-envoy-job-matrices +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# envoy-version: ${{ fromJSON(needs.get-envoy-versions.outputs.envoy-versions-json) }} +# xds-target: ["server", "client"] +# test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} +# env: +# ENVOY_VERSION: ${{ matrix.envoy-version }} +# XDS_TARGET: ${{ matrix.xds-target }} +# AWS_LAMBDA_REGION: us-west-2 +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ inputs.branch }} +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# +# - name: fetch binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: ./bin +# - name: restore mode+x +# run: chmod +x ./bin/consul +# +# - name: Set up Docker Buildx +# uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 +# +# - name: Docker build +# run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin +# +# - name: Envoy Integration Tests +# env: +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# LAMBDA_TESTS_ENABLED: "true" +# # tput complains if this isn't set to something. +# TERM: ansi +# run: | +# # shellcheck disable=SC2001 +# echo "Running $(sed 's,|, ,g' <<< "${{ matrix.test-cases }}" |wc -w) subtests" +# # shellcheck disable=SC2001 +# sed 's,|,\n,g' <<< "${{ matrix.test-cases }}" +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --debug \ +# --rerun-fails \ +# --rerun-fails-report=/tmp/gotestsum-rerun-fails \ +# --jsonfile /tmp/jsonfile/go-test.log \ +# --packages=./test/integration/connect/envoy \ +# -- -timeout=30m -tags integration -run="TestEnvoy/(${{ matrix.test-cases }})" +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# upgrade-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} +# needs: +# - setup +# - get-go-version +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# consul-version: ["1.17", "1.18", "1.19"] +# env: +# CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} +# # ENVOY_VERSION should be the latest version supported by _all_ Consul versions in the +# # matrix.consul-version, since we are testing upgrade from an older Consul version. +# # In practice, this should be the highest Envoy version supported by the lowest non-LTS +# # Consul version in the matrix (LTS versions receive additional Envoy version support). +# # +# # This value should be kept current in new nightly test workflows, and updated any time +# # a new major Envoy release is added to the set supported by Consul versions in +# # matrix.consul-version (i.e. whenever the highest common Envoy version across active +# # Consul versions changes). The minor Envoy version does not necessarily need to be +# # kept current for the purpose of these tests, but the major (1.N) version should be. +# ENVOY_VERSION: 1.27.6 +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ inputs.branch }} +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go env +# +# # Get go binary from workspace +# - name: fetch binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: . +# - name: restore mode+x +# run: chmod +x consul +# - name: Build consul:local image +# run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . +# - name: Build consul-envoy:latest-version image +# id: buildConsulEnvoyLatestImage +# run: | +# if ${{ endsWith(github.repository, '-enterprise') }} == 'true' +# then +# docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }}-ent --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# else +# docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }}:${{ env.CONSUL_LATEST_VERSION }} --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# fi +# - name: Build consul-envoy:target-version image +# id: buildConsulEnvoyTargetImage +# continue-on-error: true +# run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# - name: Retry Build consul-envoy:target-version image +# if: steps.buildConsulEnvoyTargetImage.outcome == 'failure' +# run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# - name: Build sds image +# run: docker build -t consul-sds-server ./test/integration/connect/envoy/test-sds-server/ +# - name: Configure GH workaround for ipv6 loopback +# if: ${{ !endsWith(github.repository, '-enterprise') }} +# run: | +# cat /etc/hosts && echo "-----------" +# sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6-localhost ip6-loopback/g' /etc/hosts +# cat /etc/hosts +# - name: Upgrade Integration Tests +# run: | +# mkdir -p "${{ env.TEST_RESULTS_DIR }}" +# cd ./test/integration/consul-container/test/upgrade +# docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --raw-command \ +# --format=github-actions \ +# --rerun-fails \ +# --packages="./..." \ +# -- \ +# go test \ +# -p=4 \ +# -tags "${{ env.GOTAGS }}" \ +# -timeout=30m \ +# -json \ +# ./... \ +# --follow-log=false \ +# --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --target-version local \ +# --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --latest-version "${{ env.CONSUL_LATEST_VERSION }}" +# ls -lrt +# env: +# # this is needed because of incompatibility between RYUK container and GHA +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# # tput complains if this isn't set to something. +# TERM: ansi +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# upgrade-integration-test-deployer: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} +# needs: +# - setup +# - get-go-version +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# consul-version: [ "1.17", "1.18"] +# env: +# CONSUL_LATEST_VERSION: ${{ matrix.consul-version }} +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ inputs.branch }} +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go env +# - name: Build image +# run: make test-deployer-setup +# - name: Upgrade Integration Tests +# run: | +# mkdir -p "${{ env.TEST_RESULTS_DIR }}" +# #export NOLOGBUFFER=1 +# cd ./test-integ/upgrade +# docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --raw-command \ +# --format=github-actions \ +# --packages="./..." \ +# -- \ +# go test \ +# -tags "${{ env.GOTAGS }}" \ +# -timeout=20m \ +# -parallel=2 \ +# -json \ +# ./... \ +# --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --target-version local \ +# --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --latest-version "${{ env.CONSUL_LATEST_VERSION }}" +# env: +# # this is needed because of incompatibility between RYUK container and GHA +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# # tput complains if this isn't set to something. +# TERM: ansi +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# test-integrations-success: +# needs: +# - setup +# - dev-build +# - generate-envoy-job-matrices +# - envoy-integration-test +# - upgrade-integration-test +# - upgrade-integration-test-deployer +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# if: ${{ always() }} +# steps: +# - name: evaluate upstream job results +# run: | +# # exit 1 if failure or cancelled result for any upstream job +# if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then +# printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" +# exit 1 +# fi +# - name: Notify Slack +# if: ${{ failure() }} +# id: slack +# uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 +# with: +# payload: | +# { +# "message": "One or more nightly integration tests have failed. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" +# } +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_NIGHTLY_INTEG_TEST_SLACK_WEBHOOK }} diff --git a/.github/workflows/nightly-test-main.yaml b/.github/workflows/nightly-test-main.yaml index a089121cc8c6..82f3f907f58c 100644 --- a/.github/workflows/nightly-test-main.yaml +++ b/.github/workflows/nightly-test-main.yaml @@ -1,234 +1,234 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Nightly Frontend Test Main -on: - schedule: - - cron: '0 4 * * *' - workflow_dispatch: {} - -env: - EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition - BRANCH: "main" - BRANCH_NAME: "main" # Used for naming artifacts - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - -jobs: - frontend-test-workspace-node: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 18 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Workspace Tests - id: workspace-test - working-directory: ./ui - run: make test-workspace - - - name: Node Tests - id: node-test - working-directory: ./ui/packages/consul-ui - run: make test-node - - frontend-build-ce: - runs-on: ubuntu-latest - env: - JOBS: 2 - CONSUL_NSPACES_ENABLED: 0 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 18 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Ember Build CE - id: build-ce - working-directory: ./ui/packages/consul-ui - run: make build-ci - - - name: Upload CE Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: frontend-ce-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - if-no-files-found: error - - frontend-test-ce: - runs-on: ubuntu-latest - needs: [frontend-build-ce] - strategy: - matrix: - partition: [ 1, 2, 3, 4 ] - env: - CONSUL_NSPACES_ENABLED: 0 - EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary - EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 18 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download CE Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ce-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Ember Test CE - id: cache - working-directory: ./ui/packages/consul-ui - run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit - - frontend-build-ent: - runs-on: ubuntu-latest - env: - JOBS: 2 - CONSUL_NSPACES_ENABLED: 1 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 18 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Ember Build ENT - id: build-ce - working-directory: ./ui/packages/consul-ui - run: make build-ci - - - name: Upload ENT Frontend - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - if-no-files-found: error - - frontend-test-ent: - runs-on: ubuntu-latest - needs: [frontend-build-ent] - strategy: - matrix: - partition: [ 1, 2, 3, 4 ] - env: - CONSUL_NSPACES_ENABLED: 1 - EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary - EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 18 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Ember Test ENT - id: cache - working-directory: ./ui/packages/consul-ui - run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit - - frontend-test-coverage-ent: - runs-on: ubuntu-latest - needs: [frontend-build-ent] - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ env.BRANCH }} - - # Not necessary to use yarn, but enables caching - - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 - with: - node-version: 18 - cache: 'yarn' - cache-dependency-path: ./ui/yarn.lock - - - name: Install - id: install - working-directory: ./ui - run: make deps - - - name: Download ENT Frontend - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: frontend-ent-${{ env.BRANCH_NAME }} - path: ./ui/packages/consul-ui/dist - - - name: Run ENT Code Coverage - working-directory: ./ui/packages/consul-ui - run: make test-coverage-ci - - slack-failure-notification: - runs-on: ubuntu-latest - needs: [frontend-test-ce, frontend-test-ent] - if: ${{ failure() }} - steps: - - name: Slack Notification - id: slack - uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0 - with: - payload: | - { - "message": "One or more nightly UI tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_UI_SLACK_WEBHOOK }} +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: Nightly Frontend Test Main +#on: +# schedule: +# - cron: '0 4 * * *' +# workflow_dispatch: {} +# +#env: +# EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition +# BRANCH: "main" +# BRANCH_NAME: "main" # Used for naming artifacts +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +#jobs: +# frontend-test-workspace-node: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Workspace Tests +# id: workspace-test +# working-directory: ./ui +# run: make test-workspace +# +# - name: Node Tests +# id: node-test +# working-directory: ./ui/packages/consul-ui +# run: make test-node +# +# frontend-build-ce: +# runs-on: ubuntu-latest +# env: +# JOBS: 2 +# CONSUL_NSPACES_ENABLED: 0 +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Ember Build CE +# id: build-ce +# working-directory: ./ui/packages/consul-ui +# run: make build-ci +# +# - name: Upload CE Frontend +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: frontend-ce-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# if-no-files-found: error +# +# frontend-test-ce: +# runs-on: ubuntu-latest +# needs: [frontend-build-ce] +# strategy: +# matrix: +# partition: [ 1, 2, 3, 4 ] +# env: +# CONSUL_NSPACES_ENABLED: 0 +# EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary +# EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download CE Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ce-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Ember Test CE +# id: cache +# working-directory: ./ui/packages/consul-ui +# run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit +# +# frontend-build-ent: +# runs-on: ubuntu-latest +# env: +# JOBS: 2 +# CONSUL_NSPACES_ENABLED: 1 +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Ember Build ENT +# id: build-ce +# working-directory: ./ui/packages/consul-ui +# run: make build-ci +# +# - name: Upload ENT Frontend +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# if-no-files-found: error +# +# frontend-test-ent: +# runs-on: ubuntu-latest +# needs: [frontend-build-ent] +# strategy: +# matrix: +# partition: [ 1, 2, 3, 4 ] +# env: +# CONSUL_NSPACES_ENABLED: 1 +# EMBER_TEST_REPORT: test-results/report-ce.xml #outputs test report for CI test summary +# EMBER_TEST_PARALLEL: true #enables test parallelization with ember-exam +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download ENT Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Ember Test ENT +# id: cache +# working-directory: ./ui/packages/consul-ui +# run: node_modules/.bin/ember exam --split=$EMBER_PARTITION_TOTAL --partition=${{ matrix.partition }} --path dist --silent -r xunit +# +# frontend-test-coverage-ent: +# runs-on: ubuntu-latest +# needs: [frontend-build-ent] +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ env.BRANCH }} +# +# # Not necessary to use yarn, but enables caching +# - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 +# with: +# node-version: 18 +# cache: 'yarn' +# cache-dependency-path: ./ui/yarn.lock +# +# - name: Install +# id: install +# working-directory: ./ui +# run: make deps +# +# - name: Download ENT Frontend +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: frontend-ent-${{ env.BRANCH_NAME }} +# path: ./ui/packages/consul-ui/dist +# +# - name: Run ENT Code Coverage +# working-directory: ./ui/packages/consul-ui +# run: make test-coverage-ci +# +# slack-failure-notification: +# runs-on: ubuntu-latest +# needs: [frontend-test-ce, frontend-test-ent] +# if: ${{ failure() }} +# steps: +# - name: Slack Notification +# id: slack +# uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 +# with: +# payload: | +# { +# "message": "One or more nightly UI tests have failed on branch ${{ env.BRANCH }} for Consul. ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" +# } +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.CONSUL_UI_SLACK_WEBHOOK }} diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index 0d6b71c9f061..c6c9715b31d2 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -1,17 +1,19 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: "Pull Request Labeler" -on: - pull_request_target: - types: [opened] - -jobs: - triage: - runs-on: ubuntu-latest - steps: - - uses: actions/labeler@0967ca812e7fdc8f5f71402a1b486d5bd061fe20 # v4.2.0 - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" - configuration-path: .github/pr-labeler.yml - sync-labels: false +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: "Pull Request Labeler" +#on: +# pull_request_target: +# types: [opened] +# +#jobs: +# triage: +# runs-on: ubuntu-latest +# steps: +# - name: 'Checkout repo' +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0 +# with: +# repo-token: "${{ secrets.GITHUB_TOKEN }}" +# configuration-path: .github/pr-labeler.yml +# sync-labels: false diff --git a/.github/workflows/pr-metrics-test-checker.yml b/.github/workflows/pr-metrics-test-checker.yml index d0bdac04f7e3..eabd6a9ab1f9 100644 --- a/.github/workflows/pr-metrics-test-checker.yml +++ b/.github/workflows/pr-metrics-test-checker.yml @@ -1,28 +1,28 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: "Check for metrics tests" -on: - pull_request: - types: [ opened, synchronize, labeled ] - # Runs on PRs to main - branches: - - main - -jobs: - metrics_test_check: - if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/no-metrics-test') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: "checkout repo" - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 # by default the checkout action doesn't checkout all branches - - name: "Check for metrics modifications" - run: ./.github/scripts/metrics_checker.sh - # as of now, cannot use github vars in "external" scripts; ref: https://github.community/t/using-github-action-environment-variables-in-shell-script/18330 - env: - PR_TITLE: ${{ github.event.pull_request.title }} - PR_BODY: ${{ github.event.pull_request.body }} - shell: bash +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: "Check for metrics tests" +#on: +# pull_request: +# types: [ opened, synchronize, labeled ] +# # Runs on PRs to main +# branches: +# - main +# +#jobs: +# metrics_test_check: +# if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/no-metrics-test') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# name: "checkout repo" +# with: +# ref: ${{ github.event.pull_request.head.sha }} +# fetch-depth: 0 # by default the checkout action doesn't checkout all branches +# - name: "Check for metrics modifications" +# run: ./.github/scripts/metrics_checker.sh +# # as of now, cannot use github vars in "external" scripts; ref: https://github.community/t/using-github-action-environment-variables-in-shell-script/18330 +# env: +# PR_TITLE: ${{ github.event.pull_request.title }} +# PR_BODY: ${{ github.event.pull_request.body }} +# shell: bash diff --git a/.github/workflows/reusable-check-go-mod.yml b/.github/workflows/reusable-check-go-mod.yml index 7fffb616879e..bbbeee034fa5 100644 --- a/.github/workflows/reusable-check-go-mod.yml +++ b/.github/workflows/reusable-check-go-mod.yml @@ -1,38 +1,39 @@ -name: check-go-mod - -on: - workflow_call: - inputs: - runs-on: - description: An expression indicating which kind of runners to use. - required: true - type: string - repository-name: - required: true - type: string - secrets: - elevated-github-token: - required: true -jobs: - check-go-mod: - runs-on: ${{ fromJSON(inputs.runs-on) }} - - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(inputs.repository-name, '-enterprise') }} - run: git config --global url."https://${{ secrets.elevated-github-token }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: go mod tidy - - run: | - if [[ -n $(git status -s) ]]; then - echo "Git directory has changes" - git status -s - exit 1 - fi - - name: Notify Slack - if: ${{ failure() }} - run: .github/scripts/notify_slack.sh +#name: check-go-mod +# +#on: +# workflow_call: +# inputs: +# runs-on: +# description: An expression indicating which kind of runners to use. +# required: true +# type: string +# repository-name: +# required: true +# type: string +# go-version: +# required: true +# type: string +# secrets: +# elevated-github-token: +# required: true +#jobs: +# check-go-mod: +# runs-on: ${{ fromJSON(inputs.runs-on) }} +# +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(inputs.repository-name, '-enterprise') }} +# run: git config --global url."https://${{ secrets.elevated-github-token }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ inputs.go-version }} +# # Run on all go.mod (include submodules). +# - run: make go-mod-tidy +# - run: | +# if [[ -n $(git status -s) ]]; then +# echo "Git directory has changes" +# git status -s +# exit 1 +# fi diff --git a/.github/workflows/reusable-conditional-skip.yml b/.github/workflows/reusable-conditional-skip.yml new file mode 100644 index 000000000000..80e440ffbe3a --- /dev/null +++ b/.github/workflows/reusable-conditional-skip.yml @@ -0,0 +1,69 @@ +#name: conditional-skip +# +#on: +# workflow_call: +# outputs: +# skip-ci: +# description: "Whether we should skip build and test jobs" +# value: ${{ jobs.check-skip.outputs.skip-ci }} +# +#jobs: +# check-skip: +# runs-on: ubuntu-latest +# name: Check whether to skip build and tests +# outputs: +# skip-ci: ${{ steps.maybe-skip-ci.outputs.skip-ci }} +# steps: +# # We only allow use of conditional skip in two scenarios: +# # 1. PRs +# # 2. Pushes (merges) to protected branches (`main`, `release/**`) +# # +# # The second scenario is the only place we can be sure that checking just the +# # latest change on the branch is sufficient. In PRs, we need to check _all_ commits. +# # The ability to do this is ultimately determined by the triggers of the calling +# # workflow, since `base_ref` (the target branch of a PR) is only available in +# # `pull_request` events, not `push`. +# - name: Error if conditional check is not allowed +# if: ${{ !github.base_ref && !github.ref_protected }} +# run: | +# echo "Conditional skip requires a PR event with 'base_ref' or 'push' to a protected branch." +# echo "github.base_ref: ${{ github.base_ref }}" +# echo "github.ref_protected: ${{ github.ref_protected }}" +# echo "github.ref_name: ${{ github.ref_name }}" +# echo "Check the triggers of the calling workflow to ensure that these requirements are met." +# exit 1 +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# fetch-depth: 0 +# - name: Check for skippable file changes +# id: changed-files +# uses: tj-actions/changed-files@e9772d140489982e0e3704fea5ee93d536f1e275 # v45.0.1 +# with: +# # This is a multi-line YAML string with one match pattern per line. +# # Do not use quotes around values, as it's not supported. +# # See https://github.com/tj-actions/changed-files/blob/main/README.md#inputs-%EF%B8%8F +# # for usage, options, and more details on match syntax. +# files: | +# .github/workflows/reusable-conditional-skip.yml +# **.md +# docs/** +# ui/** +# website/** +# grafana/** +# .changelog/** +# - name: Print changed files +# env: +# SKIPPABLE_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} +# NON_SKIPPABLE_FILES: ${{ steps.changed-files.outputs.other_changed_files }} +# run: | +# echo "Skippable changed files:" +# for file in ${SKIPPABLE_CHANGED_FILES}; do echo " $file"; done +# echo +# echo "Non-skippable files:" +# for file in ${NON_SKIPPABLE_FILES}; do echo " $file"; done +# - name: Skip tests and build if only skippable files changed +# id: maybe-skip-ci +# if: ${{ steps.changed-files.outputs.only_changed == 'true' }} +# run: | +# echo "Skipping tests and build because only skippable files changed" +# echo "skip-ci=true" >> $GITHUB_OUTPUT \ No newline at end of file diff --git a/.github/workflows/reusable-dev-build-windows.yml b/.github/workflows/reusable-dev-build-windows.yml index 01247c477878..c7ea2ce751c4 100644 --- a/.github/workflows/reusable-dev-build-windows.yml +++ b/.github/workflows/reusable-dev-build-windows.yml @@ -1,47 +1,47 @@ -name: reusable-dev-build-windows - -on: - workflow_call: - inputs: - uploaded-binary-name: - required: false - type: string - default: "consul.exe" - runs-on: - description: An expression indicating which kind of runners to use. - required: true - type: string - repository-name: - required: true - type: string - go-arch: - required: false - type: string - default: "" - secrets: - elevated-github-token: - required: true -jobs: - build: - runs-on: 'windows-2019' - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(inputs.repository-name, '-enterprise') }} - run: git config --global url."https://${{ secrets.elevated-github-token }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - name: Build - env: - GOARCH: ${{ inputs.goarch }} - run: go build . - # save dev build to pass to downstream jobs - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: ${{inputs.uploaded-binary-name}} - path: consul.exe - - name: Notify Slack - if: ${{ failure() }} - run: .github/scripts/notify_slack.sh +#name: reusable-dev-build-windows +# +#on: +# workflow_call: +# inputs: +# uploaded-binary-name: +# required: false +# type: string +# default: "consul.exe" +# runs-on: +# description: An expression indicating which kind of runners to use. +# required: true +# type: string +# repository-name: +# required: true +# type: string +# go-arch: +# required: false +# type: string +# default: "" +# go-version: +# required: true +# type: string +# secrets: +# elevated-github-token: +# required: true +#jobs: +# build: +# runs-on: 'windows-2019' +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(inputs.repository-name, '-enterprise') }} +# run: git config --global url."https://${{ secrets.elevated-github-token }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ inputs.go-version }} +# - name: Build +# env: +# GOARCH: ${{ inputs.goarch }} +# run: go build . +# # save dev build to pass to downstream jobs +# - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: ${{inputs.uploaded-binary-name}} +# path: consul.exe diff --git a/.github/workflows/reusable-dev-build.yml b/.github/workflows/reusable-dev-build.yml index 99bcb96592c3..248607043bfb 100644 --- a/.github/workflows/reusable-dev-build.yml +++ b/.github/workflows/reusable-dev-build.yml @@ -1,59 +1,59 @@ -name: reusable-dev-build - -on: - workflow_call: - inputs: - uploaded-binary-name: - required: false - type: string - default: "consul-bin" - runs-on: - description: An expression indicating which kind of runners to use. - required: true - type: string - repository-name: - required: true - type: string - branch-name: - required: false - type: string - default: "" - go-arch: - required: false - type: string - default: "" - secrets: - elevated-github-token: - required: true -jobs: - build: - runs-on: ${{ fromJSON(inputs.runs-on) }} - steps: - # NOTE: This is used for nightly job of building release branch. - - name: Checkout branch ${{ inputs.branch-name }} - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ inputs.branch-name }} - if: inputs.branch-name != '' - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - if: inputs.branch-name == '' - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(inputs.repository-name, '-enterprise') }} - run: git config --global url."https://${{ secrets.elevated-github-token }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - name: Build - env: - GOARCH: ${{ inputs.goarch }} - run: make dev - # save dev build to pass to downstream jobs - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: ${{inputs.uploaded-binary-name}} - path: ./bin/consul - - name: Notify Slack - if: ${{ failure() }} - run: .github/scripts/notify_slack.sh +#name: reusable-dev-build +# +#on: +# workflow_call: +# inputs: +# uploaded-binary-name: +# required: false +# type: string +# default: "consul-bin" +# runs-on: +# description: An expression indicating which kind of runners to use. +# required: true +# type: string +# repository-name: +# required: true +# type: string +# branch-name: +# required: false +# type: string +# default: "" +# go-arch: +# required: false +# type: string +# default: "" +# go-version: +# required: true +# type: string +# secrets: +# elevated-github-token: +# required: true +#jobs: +# build: +# runs-on: ${{ fromJSON(inputs.runs-on) }} +# steps: +# # NOTE: This is used for nightly job of building release branch. +# - name: Checkout branch ${{ inputs.branch-name }} +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ inputs.branch-name }} +# if: inputs.branch-name != '' +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# if: inputs.branch-name == '' +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(inputs.repository-name, '-enterprise') }} +# run: git config --global url."https://${{ secrets.elevated-github-token }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ inputs.go-version }} +# - name: Build +# env: +# GOARCH: ${{ inputs.goarch }} +# run: make dev +# # save dev build to pass to downstream jobs +# - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: ${{inputs.uploaded-binary-name}} +# path: ./bin/consul diff --git a/.github/workflows/reusable-get-envoy-versions.yml b/.github/workflows/reusable-get-envoy-versions.yml new file mode 100644 index 000000000000..aafdc6330c51 --- /dev/null +++ b/.github/workflows/reusable-get-envoy-versions.yml @@ -0,0 +1,71 @@ +#name: get-envoy-versions +# +## Reads the canonical ENVOY_VERSIONS file for either the current branch or a specified version of Consul, +## and returns both the max and all supported Envoy versions. +# +#on: +# workflow_call: +# inputs: +# ref: +# description: | +# The Consul ref/branch (e.g. release/1.18.x) for which to determine supported Envoy versions. +# If not provided, the default actions/checkout value (current ref) is used. +# type: string +# outputs: +# max-envoy-version: +# description: The max supported Envoy version for the specified Consul version +# value: ${{ jobs.get-envoy-versions.outputs.max-envoy-version }} +# envoy-versions: +# description: | +# All supported Envoy versions for the specified Consul version (formatted as multiline string with one version +# per line, in descending order) +# value: ${{ jobs.get-envoy-versions.outputs.envoy-versions }} +# envoy-versions-json: +# description: | +# All supported Envoy versions for the specified Consul version (formatted as JSON array) +# value: ${{ jobs.get-envoy-versions.outputs.envoy-versions-json }} +# +#jobs: +# get-envoy-versions: +# name: "Determine supported Envoy versions" +# runs-on: ubuntu-latest +# outputs: +# max-envoy-version: ${{ steps.get-envoy-versions.outputs.max-envoy-version }} +# envoy-versions: ${{ steps.get-envoy-versions.outputs.envoy-versions }} +# envoy-versions-json: ${{ steps.get-envoy-versions.outputs.envoy-versions-json }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# # If not set, will default to current branch. +# ref: ${{ inputs.ref }} +# - name: Determine Envoy versions +# id: get-envoy-versions +# # Note that this script assumes that the ENVOY_VERSIONS file is in the envoyextensions/xdscommon directory. +# # If in the future this file moves between branches, we could introduce a workflow input for the path that +# # defaults to the new value, and manually configure the old value as needed. +# run: | +# MAX_ENVOY_VERSION=$(cat envoyextensions/xdscommon/ENVOY_VERSIONS | grep '^[[:digit:]]' | sort -nr | head -n 1) +# ENVOY_VERSIONS=$(cat envoyextensions/xdscommon/ENVOY_VERSIONS | grep '^[[:digit:]]' | sort -nr) +# ENVOY_VERSIONS_JSON=$(echo -n '[' && echo "${ENVOY_VERSIONS}" | awk '{printf "\"%s\",", $0}' | sed 's/,$//' && echo -n ']') +# +# # Loop through each line of ENVOY_VERSIONS and compare it to the regex +# while IFS= read -r version; do +# if ! [[ $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then +# echo 'Invalid version in ENVOY_VERSIONS: '$version' does not match the pattern ^[0-9]+\.[0-9]+\.[0-9]+$' +# exit 1 +# fi +# done <<< "$ENVOY_VERSIONS" +# if ! [[ $MAX_ENVOY_VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then +# echo 'Invalid MAX_ENVOY_VERSION: '$MAX_ENVOY_VERSION' does not match the pattern ^[0-9]+\.[0-9]+\.[0-9]+$' +# exit 1 +# fi +# +# echo "Supported Envoy versions:" +# echo "${ENVOY_VERSIONS}" +# echo "envoy-versions<> $GITHUB_OUTPUT +# echo "${ENVOY_VERSIONS}" >> $GITHUB_OUTPUT +# echo "EOF" >> $GITHUB_OUTPUT +# echo "Supported Envoy versions JSON: ${ENVOY_VERSIONS_JSON}" +# echo "envoy-versions-json=${ENVOY_VERSIONS_JSON}" >> $GITHUB_OUTPUT +# echo "Max supported Envoy version: ${MAX_ENVOY_VERSION}" +# echo "max-envoy-version=${MAX_ENVOY_VERSION}" >> $GITHUB_OUTPUT diff --git a/.github/workflows/reusable-get-go-version.yml b/.github/workflows/reusable-get-go-version.yml new file mode 100644 index 000000000000..c185fbf8626b --- /dev/null +++ b/.github/workflows/reusable-get-go-version.yml @@ -0,0 +1,51 @@ +#name: get-go-version +# +#on: +# workflow_call: +# inputs: +# ref: +# description: | +# The Consul ref/branch (e.g. release/1.18.x) for which to determine the Go version. +# If not provided, the default actions/checkout value (current ref) is used. +# type: string +# outputs: +# go-version: +# description: "The Go version detected by this workflow" +# value: ${{ jobs.get-go-version.outputs.go-version }} +# go-version-previous: +# description: "The Go version (MAJOR.MINOR) prior to the current one, used for backwards compatibility testing" +# value: ${{ jobs.get-go-version.outputs.go-version-previous }} +# +#jobs: +# get-go-version: +# name: "Determine Go toolchain version" +# runs-on: ubuntu-latest +# outputs: +# go-version: ${{ steps.get-go-version.outputs.go-version }} +# go-version-previous: ${{ steps.get-go-version.outputs.go-version-previous }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# # If not set, will default to current branch. +# ref: ${{ inputs.ref }} +# - name: Determine Go version +# id: get-go-version +# # We use .go-version as our source of truth for current Go +# # version, because "goenv" can react to it automatically. +# # +# # In the future, we can transition from .go-version and goenv to +# # Go 1.21 `toolchain` directives by updating this workflow rather +# # than individually setting `go-version-file` in each `setup-go` +# # job (as of 2024-01-03, `setup-go` does not support `toolchain`). +# # +# # When changing the method of Go version detection, also update +# # GOLANG_VERSION detection in the root Makefile; this is used for +# # setting the Dockerfile Go version. +# run: | +# GO_VERSION=$(head -n 1 .go-version) +# echo "Building with Go ${GO_VERSION}" +# echo "go-version=${GO_VERSION}" >> $GITHUB_OUTPUT +# GO_MINOR_VERSION=${GO_VERSION%.*} +# GO_VERSION_PREVIOUS="${GO_MINOR_VERSION%.*}.$((${GO_MINOR_VERSION#*.}-1))" +# echo "Previous version ${GO_VERSION_PREVIOUS}" +# echo "go-version-previous=${GO_VERSION_PREVIOUS}" >> $GITHUB_OUTPUT diff --git a/.github/workflows/reusable-lint.yml b/.github/workflows/reusable-lint.yml index 902ff1867144..a006ad7cdc8b 100644 --- a/.github/workflows/reusable-lint.yml +++ b/.github/workflows/reusable-lint.yml @@ -1,60 +1,62 @@ -name: reusable-lint - -on: - workflow_call: - inputs: - go-arch: - required: false - type: string - default: "" - runs-on: - description: An expression indicating which kind of runners to use. - required: true - type: string - repository-name: - required: true - type: string - secrets: - elevated-github-token: - required: true -env: - GOTAGS: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consulprem consuldev' || '' }}" - GOARCH: ${{inputs.go-arch}} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - -jobs: - lint: - runs-on: ${{ fromJSON(inputs.runs-on) }} - strategy: - matrix: - directory: - - "" - - "api" - - "sdk" - - "envoyextensions" - - "troubleshoot" - - "test/integration/consul-container" - - "test-integ" - - "testing/deployer" - fail-fast: true - name: lint ${{ matrix.directory }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(inputs.repository-name, '-enterprise') }} - run: git config --global url."https://${{ secrets.elevated-github-token }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: go env - - name: lint-${{ matrix.directory }} - uses: golangci/golangci-lint-action@639cd343e1d3b897ff35927a75193d57cfcba299 # v3.6.0 - with: - working-directory: ${{ matrix.directory }} - version: v1.51.1 - args: --build-tags="${{ env.GOTAGS }}" -v - skip-cache: true - - name: Notify Slack - if: ${{ failure() }} - run: .github/scripts/notify_slack.sh +#name: reusable-lint +# +#on: +# workflow_call: +# inputs: +# go-arch: +# required: false +# type: string +# default: "" +# go-version: +# required: true +# type: string +# runs-on: +# description: An expression indicating which kind of runners to use. +# required: true +# type: string +# repository-name: +# required: true +# type: string +# secrets: +# elevated-github-token: +# required: true +#env: +# GOTAGS: "${{ github.event.repository.name == 'consul-enterprise' && 'consulent consuldev' || '' }}" +# GOARCH: ${{inputs.go-arch}} +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +#jobs: +# lint: +# runs-on: ${{ fromJSON(inputs.runs-on) }} +# strategy: +# matrix: +# directory: +# - "" +# - "api" +# - "sdk" +# - "envoyextensions" +# - "troubleshoot" +# - "test/integration/consul-container" +# - "test-integ" +# - "testing/deployer" +# fail-fast: true +# name: lint ${{ matrix.directory }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(inputs.repository-name, '-enterprise') }} +# run: git config --global url."https://${{ secrets.elevated-github-token }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ inputs.go-version }} +# - run: go env +# - name: Set golangci-lint version +# run: echo "GOLANGCI_LINT_VERSION=$(make --no-print-directory print-GOLANGCI_LINT_VERSION)" >> $GITHUB_ENV +# - name: lint-${{ matrix.directory }} +# uses: golangci/golangci-lint-action@82d40c283aeb1f2b6595839195e95c2d6a49081b # v5.0.0 +# with: +# working-directory: ${{ matrix.directory }} +# version: ${{ env.GOLANGCI_LINT_VERSION }} +# args: --build-tags="${{ env.GOTAGS }}" -v +# skip-cache: true diff --git a/.github/workflows/reusable-unit-split.yml b/.github/workflows/reusable-unit-split.yml index 3d959d168bed..5aa8cc736699 100644 --- a/.github/workflows/reusable-unit-split.yml +++ b/.github/workflows/reusable-unit-split.yml @@ -1,180 +1,188 @@ -name: reusable-unit-split - -on: - workflow_call: - inputs: - directory: - required: true - type: string - runs-on: - description: An expression indicating which kind of runners to use. - required: true - type: string - go-arch: - required: false - type: string - default: "" - uploaded-binary-name: - required: false - type: string - default: "consul-bin" - args: - required: false - type: string - default: "" - runner-count: - required: false - type: number - default: 1 - go-test-flags: - required: false - type: string - default: "" - repository-name: - required: true - type: string - go-tags: - required: false - type: string - default: "" - secrets: - elevated-github-token: - required: true - consul-license: - required: true - datadog-api-key: - required: true -env: - TEST_RESULTS: /tmp/test-results - GOTESTSUM_VERSION: "1.10.1" - GOARCH: ${{inputs.go-arch}} - TOTAL_RUNNERS: ${{inputs.runner-count}} - CONSUL_LICENSE: ${{secrets.consul-license}} - GOTAGS: ${{ inputs.go-tags}} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - DATADOG_API_KEY: ${{secrets.datadog-api-key}} - -jobs: - set-test-package-matrix: - runs-on: ubuntu-latest - outputs: - package-matrix: ${{ steps.set-matrix.outputs.matrix }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - id: set-matrix - run: ./.github/scripts/set_test_package_matrix.sh ${{env.TOTAL_RUNNERS}} - - go-test: - runs-on: ${{ fromJSON(inputs.runs-on) }} - name: "go-test" - needs: - - set-test-package-matrix - strategy: - fail-fast: false - matrix: - package: ${{ fromJson(needs.set-test-package-matrix.outputs.package-matrix) }} - steps: - - name: ulimit - run: | - echo "Soft limits" - ulimit -Sa - echo "Hard limits" - ulimit -Ha - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(inputs.repository-name, '-enterprise') }} - run: git config --global url."https://${{ secrets.elevated-github-token }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - cache: true - - run: mkdir -p ${{env.TEST_RESULTS}} - - name: go mod download - working-directory: ${{inputs.directory}} - run: go mod download - - name: Download consul - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: ${{inputs.uploaded-binary-name}} - path: ${{inputs.directory}} - - name: Display downloaded file - run: ls -ld consul - working-directory: ${{inputs.directory}} - - run: echo "$GITHUB_WORKSPACE/${{inputs.directory}}" >> $GITHUB_PATH - - name: Make sure consul is executable - run: chmod +x $GITHUB_WORKSPACE/${{inputs.directory}}/consul - - run: go env - - name: Run tests - working-directory: ${{inputs.directory}} - run: | - # separate the list - PACKAGE_NAMES="${{ join(matrix.package, ' ') }}" - # PACKAGE_NAMES="${{ matrix.package }}" - - ${{inputs.go-test-flags}} - - # some tests expect this umask, and arm images have a different default - umask 0022 - - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --format=short-verbose \ - --jsonfile /tmp/jsonfile/go-test.log \ - --debug \ - --rerun-fails=3 \ - --rerun-fails-max-failures=40 \ - --rerun-fails-report=/tmp/gotestsum-rerun-fails \ - --packages="$PACKAGE_NAMES" \ - --junitfile ${{env.TEST_RESULTS}}/gotestsum-report.xml -- \ - -tags="${{env.GOTAGS}}" \ - -cover -coverprofile=coverage.txt \ - -timeout=30m - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: ${{ env.DATADOG_API_KEY}} - env: - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" ${{env.TEST_RESULTS}}/gotestsum-report.xml - - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: test-results - path: ${{env.TEST_RESULTS}} - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: jsonfile - path: /tmp/jsonfile - - name: "Re-run fails report" - run: | - .github/scripts/rerun_fails_report.sh /tmp/gotestsum-rerun-fails - - name: Notify Slack - if: ${{ failure() }} - run: .github/scripts/notify_slack.sh +#name: reusable-unit-split +# +#on: +# workflow_call: +# inputs: +# directory: +# required: true +# type: string +# runs-on: +# description: An expression indicating which kind of runners to use. +# required: true +# type: string +# go-arch: +# required: false +# type: string +# default: "" +# uploaded-binary-name: +# required: false +# type: string +# default: "consul-bin" +# args: +# required: false +# type: string +# default: "" +# runner-count: +# required: false +# type: number +# default: 1 +# go-test-flags: +# required: false +# type: string +# default: "" +# repository-name: +# required: true +# type: string +# go-tags: +# required: false +# type: string +# default: "" +# go-version: +# required: true +# type: string +# secrets: +# elevated-github-token: +# required: true +# consul-license: +# required: true +# datadog-api-key: +# required: true +#env: +# TEST_RESULTS: /tmp/test-results +# GOTESTSUM_VERSION: "1.11.0" +# GOARCH: ${{inputs.go-arch}} +# TOTAL_RUNNERS: ${{inputs.runner-count}} +# CONSUL_LICENSE: ${{secrets.consul-license}} +# GOTAGS: ${{ inputs.go-tags}} +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# DATADOG_API_KEY: ${{secrets.datadog-api-key}} +# +#jobs: +# set-test-package-matrix: +# runs-on: ubuntu-latest +# outputs: +# package-matrix: ${{ steps.set-matrix.outputs.matrix }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ inputs.go-version }} +# - id: set-matrix +# run: ./.github/scripts/set_test_package_matrix.sh ${{env.TOTAL_RUNNERS}} +# +# go-test: +# runs-on: ${{ fromJSON(inputs.runs-on) }} +# name: "go-test" +# needs: +# - set-test-package-matrix +# strategy: +# fail-fast: false +# matrix: +# package: ${{ fromJson(needs.set-test-package-matrix.outputs.package-matrix) }} +# steps: +# - name: ulimit +# run: | +# echo "Soft limits" +# ulimit -Sa +# echo "Hard limits" +# ulimit -Ha +# # upload-artifact requires a unique ID per run. These steps will be repeated with the matrix run, and other unit tests +# # will also overlap with the names here. We use a random string rather than trying to do trickery +# # with the package matrix. +# - id: generate-matrix-id +# run: | +# MATRIX_RUN_ID=$(head /dev/urandom | tr -dc A-Z | head -c8) +# echo "The matrix run ID is $MATRIX_RUN_ID" +# echo "matrix-run-id=$MATRIX_RUN_ID" >> "$GITHUB_OUTPUT" +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(inputs.repository-name, '-enterprise') }} +# run: git config --global url."https://${{ secrets.elevated-github-token }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ inputs.go-version }} +# - run: mkdir -p ${{env.TEST_RESULTS}} +# - name: go mod download +# working-directory: ${{inputs.directory}} +# run: go mod download +# - name: Download consul +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: ${{inputs.uploaded-binary-name}} +# path: ${{inputs.directory}} +# - name: Display downloaded file +# run: ls -ld consul +# working-directory: ${{inputs.directory}} +# - run: echo "$GITHUB_WORKSPACE/${{inputs.directory}}" >> $GITHUB_PATH +# - name: Make sure consul is executable +# run: chmod +x $GITHUB_WORKSPACE/${{inputs.directory}}/consul +# - run: go env +# - name: Run tests +# working-directory: ${{inputs.directory}} +# run: | +# # separate the list +# PACKAGE_NAMES="${{ join(matrix.package, ' ') }}" +# # PACKAGE_NAMES="${{ matrix.package }}" +# +# # some tests expect this umask, and arm images have a different default +# umask 0022 +# +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --format=github-actions \ +# --format-hide-empty-pkg \ +# --jsonfile /tmp/jsonfile/go-test.log \ +# --rerun-fails \ +# --rerun-fails-report=/tmp/gotestsum-rerun-fails \ +# --packages="$PACKAGE_NAMES" \ +# --junitfile ${{env.TEST_RESULTS}}/gotestsum-report.xml -- \ +# -tags="${{env.GOTAGS}}" \ +# ${{inputs.go-test-flags}} \ +# -cover -coverprofile=coverage.txt \ +# -timeout=30m +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && env.DATADOG_API_KEY}} +# env: +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" ${{env.TEST_RESULTS}}/gotestsum-report.xml +# +# - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# if: ${{ !cancelled() }} +# with: +# name: ${{ steps.generate-matrix-id.outputs.matrix-run-id }}-test-results +# path: ${{env.TEST_RESULTS}} +# - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# if: ${{ !cancelled() }} +# with: +# name: ${{ steps.generate-matrix-id.outputs.matrix-run-id }}-jsonfile +# path: /tmp/jsonfile +# - name: "Re-run fails report" +# if: ${{ !cancelled() }} +# run: | +# .github/scripts/rerun_fails_report.sh /tmp/gotestsum-rerun-fails diff --git a/.github/workflows/reusable-unit.yml b/.github/workflows/reusable-unit.yml index 3b50bfa7e388..f9094bd38422 100644 --- a/.github/workflows/reusable-unit.yml +++ b/.github/workflows/reusable-unit.yml @@ -1,159 +1,153 @@ -name: reusable-unit - -on: - workflow_call: - inputs: - directory: - required: true - type: string - runs-on: - description: An expression indicating which kind of runners to use. - required: true - type: string - go-arch: - required: false - type: string - default: "" - uploaded-binary-name: - required: false - type: string - default: "consul-bin" - package-names-command: - required: false - type: string - default: 'go list -tags "$GOTAGS" ./...' - go-test-flags: - required: false - type: string - default: "" - repository-name: - required: true - type: string - go-tags: - required: false - type: string - default: "" - go-version: - required: false - type: string - default: "" - secrets: - elevated-github-token: - required: true - consul-license: - required: true - datadog-api-key: - required: true -env: - TEST_RESULTS: /tmp/test-results - GOTESTSUM_VERSION: "1.10.1" - GOARCH: ${{inputs.go-arch}} - CONSUL_LICENSE: ${{secrets.consul-license}} - GOTAGS: ${{ inputs.go-tags}} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - DATADOG_API_KEY: ${{secrets.datadog-api-key}} - -jobs: - go-test: - runs-on: ${{ fromJSON(inputs.runs-on) }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(inputs.repository-name, '-enterprise') }} - run: git config --global url."https://${{ secrets.elevated-github-token }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - if: ${{ inputs.go-version != '' }} - with: - go-version: ${{ inputs.go-version }} - cache: true - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - if: ${{ inputs.go-version == '' }} - with: - go-version-file: 'go.mod' - cache: true - - run: mkdir -p ${{env.TEST_RESULTS}} - - name: go mod download - working-directory: ${{inputs.directory}} - run: go mod download - - name: Download consul - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: ${{inputs.uploaded-binary-name}} - path: ${{inputs.directory}} - - name: Display downloaded file - run: ls -ld consul - working-directory: ${{inputs.directory}} - - run: echo "$GITHUB_WORKSPACE/${{inputs.directory}}" >> $GITHUB_PATH - - name: Make sure consul is executable - run: chmod +x $GITHUB_WORKSPACE/${{inputs.directory}}/consul - - run: go env - - name: Run tests - working-directory: ${{inputs.directory}} - run: | - PACKAGE_NAMES=$(${{inputs.package-names-command}}) - - # some tests expect this umask, and arm images have a different default - umask 0022 - - ${{inputs.go-test-flags}} - - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --format=short-verbose \ - --jsonfile /tmp/jsonfile/go-test.log \ - --debug \ - --rerun-fails=3 \ - --rerun-fails-max-failures=40 \ - --rerun-fails-report=/tmp/gotestsum-rerun-fails \ - --packages="$PACKAGE_NAMES" \ - --junitfile ${{env.TEST_RESULTS}}/gotestsum-report.xml -- \ - -tags="${{env.GOTAGS}}" \ - ${GO_TEST_FLAGS-} \ - -cover -coverprofile=coverage.txt \ - -timeout=30m - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: ${{ env.DATADOG_API_KEY}} - env: - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" ${{env.TEST_RESULTS}}/gotestsum-report.xml - - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: test-results - path: ${{env.TEST_RESULTS}} - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - name: jsonfile - path: /tmp/jsonfile - - name: "Re-run fails report" - run: | - .github/scripts/rerun_fails_report.sh /tmp/gotestsum-rerun-fails - - name: Notify Slack - if: ${{ failure() }} - run: .github/scripts/notify_slack.sh +#name: reusable-unit +# +#on: +# workflow_call: +# inputs: +# directory: +# required: true +# type: string +# runs-on: +# description: An expression indicating which kind of runners to use. +# required: true +# type: string +# go-arch: +# required: false +# type: string +# default: "" +# uploaded-binary-name: +# required: false +# type: string +# default: "consul-bin" +# package-names-command: +# required: false +# type: string +# default: 'go list -tags "$GOTAGS" ./...' +# go-test-flags: +# required: false +# type: string +# default: "" +# repository-name: +# required: true +# type: string +# go-tags: +# required: false +# type: string +# default: "" +# go-version: +# required: true +# type: string +# secrets: +# elevated-github-token: +# required: true +# consul-license: +# required: true +# datadog-api-key: +# required: true +#env: +# TEST_RESULTS: /tmp/test-results +# GOTESTSUM_VERSION: "1.11.0" +# GOARCH: ${{inputs.go-arch}} +# CONSUL_LICENSE: ${{secrets.consul-license}} +# GOTAGS: ${{ inputs.go-tags}} +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# DATADOG_API_KEY: ${{secrets.datadog-api-key}} +# +#jobs: +# go-test: +# runs-on: ${{ fromJSON(inputs.runs-on) }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(inputs.repository-name, '-enterprise') }} +# run: git config --global url."https://${{ secrets.elevated-github-token }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ inputs.go-version }} +# - run: mkdir -p ${{env.TEST_RESULTS}} +# - name: go mod download +# working-directory: ${{inputs.directory}} +# run: go mod download +# - name: Download consul +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: ${{inputs.uploaded-binary-name}} +# path: ${{inputs.directory}} +# - name: Display downloaded file +# run: ls -ld consul +# working-directory: ${{inputs.directory}} +# - run: echo "$GITHUB_WORKSPACE/${{inputs.directory}}" >> $GITHUB_PATH +# - name: Make sure consul is executable +# run: chmod +x $GITHUB_WORKSPACE/${{inputs.directory}}/consul +# - run: go env +# - name: Run tests +# working-directory: ${{inputs.directory}} +# run: | +# PACKAGE_NAMES=$(${{inputs.package-names-command}}) +# +# # some tests expect this umask, and arm images have a different default +# umask 0022 +# +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --format=github-actions \ +# --jsonfile /tmp/jsonfile/go-test.log \ +# --rerun-fails \ +# --rerun-fails-report=/tmp/gotestsum-rerun-fails \ +# --packages="$PACKAGE_NAMES" \ +# --junitfile ${{env.TEST_RESULTS}}/gotestsum-report.xml -- \ +# -tags="${{env.GOTAGS}}" \ +# ${{inputs.go-test-flags}} \ +# -cover -coverprofile=coverage.txt \ +# -timeout=30m +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && env.DATADOG_API_KEY}} +# env: +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" ${{env.TEST_RESULTS}}/gotestsum-report.xml +# # upload-artifact requires a unique ID per run. These steps will overlap with other users of the reusable workflow. +# # We use a random string rather than trying to pass in some identifying information. +# - id: generate-run-id +# run: | +# RUN_ID=$(head /dev/urandom | tr -dc A-Z | head -c8) +# echo "The run ID is $RUN_ID" +# echo "run-id=$RUN_ID" >> "$GITHUB_OUTPUT" +# - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# if: ${{ !cancelled() }} +# with: +# name: ${{ steps.generate-run-id.outputs.run-id }}-test-results +# path: ${{env.TEST_RESULTS}} +# - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# if: ${{ !cancelled() }} +# with: +# name: ${{ steps.generate-run-id.outputs.run-id }}-jsonfile +# path: /tmp/jsonfile +# - name: "Re-run fails report" +# if: ${{ !cancelled() }} +# run: | +# .github/scripts/rerun_fails_report.sh /tmp/gotestsum-rerun-fails diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml new file mode 100644 index 000000000000..e7fb3d08ea7b --- /dev/null +++ b/.github/workflows/security-scan.yml @@ -0,0 +1,85 @@ +## This job runs a non-blocking informational security scan on the repository. +## For release-blocking security scans, see .release/security-scan.hcl. +#name: Security Scan +# +#on: +# push: +# branches: +# - main +# - release/** +# pull_request: +# branches: +# - main +# - release/** +# # paths-ignore only works for non-required checks. +# # Jobs that are required for merge must use reusable-conditional-skip.yml. +# paths-ignore: +# - 'docs/**' +# - 'grafana/**' +# - '.changelog/**' +# +## cancel existing runs of the same workflow on the same ref +#concurrency: +# group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} +# cancel-in-progress: true +# +#jobs: +# setup: +# name: Setup +# runs-on: ubuntu-latest +# outputs: +# compute-small: ${{ steps.setup-outputs.outputs.compute-small }} +# compute-medium: ${{ steps.setup-outputs.outputs.compute-medium }} +# compute-large: ${{ steps.setup-outputs.outputs.compute-large }} +# compute-xl: ${{ steps.setup-outputs.outputs.compute-xl }} +# steps: +# - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 +# - id: setup-outputs +# name: Setup outputs +# run: ./.github/scripts/get_runner_classes.sh +# +# get-go-version: +# uses: ./.github/workflows/reusable-get-go-version.yml +# +# scan: +# needs: +# - setup +# - get-go-version +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} +# # The first check ensures this doesn't run on community-contributed PRs, who +# # won't have the permissions to run this job. +# if: ${{ (github.repository != 'hashicorp/consul' || (github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name)) +# && (github.actor != 'dependabot[bot]') && (github.actor != 'hc-github-team-consul-core') }} +# +# steps: +# - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 +# +# - name: Set up Go +# uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# +# - name: Clone Security Scanner repo +# uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 +# with: +# repository: hashicorp/security-scanner +# token: ${{ secrets.PRODSEC_SCANNER_READ_ONLY }} +# path: security-scanner +# ref: main +# +# - name: Scan +# id: scan +# uses: ./security-scanner +# with: +# repository: "$PWD" +# # See scan.hcl at repository root for config. +# +# - name: SARIF Output +# shell: bash +# run: | +# cat results.sarif | jq +# +# - name: Upload SARIF file +# uses: github/codeql-action/upload-sarif@8fd294e26a0e458834582b0fe4988d79966c7c0a # codeql-bundle-v2.18.4 +# with: +# sarif_file: results.sarif diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index ff07a961a4e4..13da65404406 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,31 +1,31 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: stale -on: - schedule: - - cron: 0 1 * * * - workflow_dispatch: {} -jobs: - stale: - runs-on: ubuntu-latest - permissions: - pull-requests: write - steps: - - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0 - with: - days-before-stale: -1 - days-before-close: -1 - days-before-pr-stale: 60 - days-before-pr-close: 30 - stale-pr-message: This pull request has been automatically flagged - for inactivity because it has not been acted upon in the last 60 - days. It will be closed if no new activity occurs in the next - 30 days. Please feel free to re-open to resurrect the change if - you feel this has happened by mistake. Thank you for your - contributions. - close-pr-message: Closing due to inactivity. If you feel this was a - mistake or you wish to re-open at any time in the future, please - leave a comment and it will be re-surfaced for the maintainers to review. - stale-pr-label: meta/stale - exempt-pr-labels: meta/staleproof +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: stale +#on: +# schedule: +# - cron: 0 1 * * * +# workflow_dispatch: {} +#jobs: +# stale: +# runs-on: ubuntu-latest +# permissions: +# pull-requests: write +# steps: +# - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 +# with: +# days-before-stale: -1 +# days-before-close: -1 +# days-before-pr-stale: 60 +# days-before-pr-close: 30 +# stale-pr-message: This pull request has been automatically flagged +# for inactivity because it has not been acted upon in the last 60 +# days. It will be closed if no new activity occurs in the next +# 30 days. Please feel free to re-open to resurrect the change if +# you feel this has happened by mistake. Thank you for your +# contributions. +# close-pr-message: Closing due to inactivity. If you feel this was a +# mistake or you wish to re-open at any time in the future, please +# leave a comment and it will be re-surfaced for the maintainers to review. +# stale-pr-label: meta/stale +# exempt-pr-labels: meta/staleproof diff --git a/.github/workflows/test-integrations-windows.yml b/.github/workflows/test-integrations-windows.yml deleted file mode 100644 index 16f7b26fdc67..000000000000 --- a/.github/workflows/test-integrations-windows.yml +++ /dev/null @@ -1,1211 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: test-integrations-windows - -on: - workflow_dispatch: - -env: - TEST_RESULTS_DIR: /tmp/test-results - TEST_RESULTS_ARTIFACT_NAME: test-results - CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} - GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} - GOTESTSUM_VERSION: "1.9.0" - CONSUL_BINARY_UPLOAD_NAME: consul.exe - # strip the hashicorp/ off the front of github.repository for consul - CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'consul' }} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - -jobs: - setup: - runs-on: ubuntu-latest - name: Setup - outputs: - compute-small: ${{ steps.runners.outputs.compute-small }} - compute-medium: ${{ steps.runners.outputs.compute-medium }} - compute-large: ${{ steps.runners.outputs.compute-large }} - compute-xl: ${{ steps.runners.outputs.compute-xl }} - enterprise: ${{ steps.runners.outputs.enterprise }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - id: runners - run: .github/scripts/get_runner_classes_windows.sh - - dev-build: - uses: ./.github/workflows/reusable-dev-build-windows.yml - with: - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - uploaded-binary-name: 'consul.exe' - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - # NOTE: Jobs needs to be added here manually. Jobs when run together on windows fails intermittently. - # So they are run independently of each other. - envoy-integration-test: - needs: - - setup - - dev-build - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - envoy-version: [ "1.27.2" ] - xds-target: [ "server", "client" ] - env: - ENVOY_VERSION: ${{ matrix.envoy-version }} - XDS_TARGET: ${{ matrix.xds-target }} - AWS_LAMBDA_REGION: us-west-2 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - - name: Fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: ${{ github.workspace }} - - - name: Create dist folder and copy binary - run: | - mkdir dist - cp ${{ github.workspace }}\consul.exe dist\ - - - name: Restore mode+x - run: icacls ${{ github.workspace }}\consul.exe /grant:rx Everyone:RX - - - name: Setup TcpDump Docker Image - shell: bash - run: | - cd test/integration/connect/envoy - curl -sSL "https://asheshvidyut-bucket.s3.ap-southeast-2.amazonaws.com/tcpdump.exe" -o tcpdump.exe - docker build -t envoy-tcpdump -f Dockerfile-tcpdump-windows . - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 - - - name: Docker build consul - run: docker build -t windows/consul -f Dockerfile-windows . - - - name: Docker build consul local - shell: bash - run: cd build-support/windows && ./build-consul-local-images.sh - - - name: Docker build consul dev - shell: bash - run: cd build-support/windows && ./build-consul-dev-image.sh - - # https://hashicorp.atlassian.net/browse/NET-4973 - # ^ Ticket to figure out why grouping test case is failing on Windows Machine - -# - name: Envoy Integration Tests for windows case-api-gateway-http-hostnames -# shell: bash -# if: always() -# env: -# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml -# GOTESTSUM_FORMAT: standard-verbose -# COMPOSE_INTERACTIVE_NO_CLI: 1 -# LAMBDA_TESTS_ENABLED: "true" -# # tput complains if this isn't set to something. -# TERM: ansi -# run: | -# # shellcheck disable=SC2001 -# echo "Running Integration Test case-api-gateway-http-hostnames" -# # shellcheck disable=SC2001 -# go test -v -timeout=45m -tags integration \ -# ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-http-hostnames" -win=true - - - name: Envoy Integration Tests for windows case-api-gateway-http-simple - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-api-gateway-http-simple" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-http-simple" -win=true - - - name: Envoy Integration Tests for windows case-api-gateway-http-splitter-targets - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-api-gateway-http-splitter-targets" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-http-splitter-targets" -win=true - - - name: Envoy Integration Tests for windows case-api-gateway-http-tls-overlapping-hosts - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-api-gateway-http-tls-overlapping-hosts" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-http-tls-overlapping-hosts" -win=true - - - name: Envoy Integration Tests for windows case-api-gateway-tcp-conflicted - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-api-gateway-tcp-conflicted" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-tcp-conflicted" -win=true - - - name: Envoy Integration Tests for windows case-api-gateway-tcp-simple - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-api-gateway-tcp-simple" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-tcp-simple" -win=true - - - name: Envoy Integration Tests for windows case-api-gateway-tcp-tls-overlapping-hosts - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-api-gateway-tcp-tls-overlapping-hosts" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-api-gateway-tcp-tls-overlapping-hosts" -win=true - - - name: Envoy Integration Tests for windows case-badauthz - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-badauthz" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-badauthz" -win=true - - - name: Envoy Integration Tests for windows case-basic - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-basic" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-basic" -win=true - - - name: Envoy Integration Tests for windows case-centralconf - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-centralconf" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-centralconf" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-cluster-peering-failover - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-resolver-cluster-peering-failover" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-cluster-peering-failover" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-dc-failover-gateways-none - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-resolver-dc-failover-gateways-none" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-dc-failover-gateways-none" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-dc-failover-gateways-remote - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-resolver-dc-failover-gateways-remote" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-dc-failover-gateways-remote" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-defaultsubset - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-resolver-defaultsubset" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-defaultsubset" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-features - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-resolver-features" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-features" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-subset-onlypassing - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-resolver-subset-onlypassing" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-subset-onlypassing" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-subset-redirect - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-resolver-subset-redirect" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-subset-redirect" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-svc-failover - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-resolver-svc-failover" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-svc-failover" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-svc-redirect-http - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-resolver-svc-redirect-http" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-svc-redirect-http" -win=true - - - name: Envoy Integration Tests for windows case-cfg-resolver-svc-redirect-tcp - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-resolver-svc-redirect-tcp" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-resolver-svc-redirect-tcp" -win=true - - - name: Envoy Integration Tests for windows case-cfg-router-features - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-router-features" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-router-features" -win=true - - - name: Envoy Integration Tests for windows case-cfg-splitter-cluster-peering - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-splitter-cluster-peering" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-splitter-cluster-peering" -win=true - - - name: Envoy Integration Tests for windows case-cfg-splitter-features - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-splitter-features" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-splitter-features" -win=true - - - name: Envoy Integration Tests for windows case-cfg-splitter-peering-ingress-gateways - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cfg-splitter-peering-ingress-gateways" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cfg-splitter-peering-ingress-gateways" -win=true - - # This test runs fine on windows machine but fails on CI - # Task to be picked later on - https://hashicorp.atlassian.net/browse/NET-4972 - # - name: Envoy Integration Tests for windows case-consul-exec - # if: always() - # shell: bash - # env: - # GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - # GOTESTSUM_FORMAT: standard-verbose - # COMPOSE_INTERACTIVE_NO_CLI: 1 - # LAMBDA_TESTS_ENABLED: "true" - # # tput complains if this isn't set to something. - # TERM: ansi - # run: | - # #shellcheck disable=SC2001 - # echo "Running Integration Test case-consul-exec" - # # shellcheck disable=SC2001 - # go test -v -timeout=45m -tags integration \ - # ./test/integration/connect/envoy -run="TestEnvoy/case-consul-exec" -win=true - - - name: Envoy Integration Tests for windows case-cross-peer-control-plane-mgw - if: always() - shell: bash - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cross-peer-control-plane-mgw" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cross-peer-control-plane-mgw" -win=true - - - name: Envoy Integration Tests for windows case-cross-peers - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cross-peers" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cross-peers" -win=true - - - name: Envoy Integration Tests for windows case-cross-peers-http - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cross-peers-http" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cross-peers-http" -win=true - - - name: Envoy Integration Tests for windows case-cross-peers-http-router - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cross-peers-http-router" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cross-peers-http-router" -win=true - - - name: Envoy Integration Tests for windows case-cross-peers-resolver-redirect-tcp - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-cross-peers-resolver-redirect-tcp" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-cross-peers-resolver-redirect-tcp" -win=true - - - name: Envoy Integration Tests for windows case-dogstatsd-udp - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-dogstatsd-udp" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-dogstatsd-udp" -win=true - - - name: Envoy Integration Tests for windows case-envoyext-ratelimit - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-envoyext-ratelimit" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-envoyext-ratelimit" -win=true - - - name: Envoy Integration Tests for windows case-expose-checks - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-expose-checks" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-expose-checks" -win=true - - - name: Envoy Integration Tests for windows case-gateway-without-services - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-gateway-without-services" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-gateway-without-services" -win=true - - - name: Envoy Integration Tests for windows case-gateways-local - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-gateways-local" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-gateways-local" -win=true - - - name: Envoy Integration Tests for windows case-gateways-remote - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-gateways-remote" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-gateways-remote" -win=true - - - name: Envoy Integration Tests for windows case-grpc - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-grpc" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-grpc" -win=true - - - name: Envoy Integration Tests for windows case-http - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-http" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-http" -win=true - - - name: Envoy Integration Tests for windows case-http-badauthz - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-http-badauthz" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-http-badauthz" -win=true - - - name: Envoy Integration Tests for windows case-ingress-gateway-grpc - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-ingress-gateway-grpc" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-grpc" -win=true - - - name: Envoy Integration Tests for windows case-ingress-gateway-http - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-ingress-gateway-http" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-http" -win=true - - - name: Envoy Integration Tests for windows case-ingress-gateway-multiple-services - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-ingress-gateway-multiple-services" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-multiple-services" -win=true - - - name: Envoy Integration Tests for windows case-ingress-gateway-peering-failover - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-ingress-gateway-peering-failover" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-peering-failover" -win=true - - - name: Envoy Integration Tests for windows case-ingress-gateway-simple - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-ingress-gateway-simple" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-simple" -win=true - - - name: Envoy Integration Tests for windows case-ingress-mesh-gateways-resolver - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-ingress-mesh-gateways-resolver" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-mesh-gateways-resolver" -win=true - - - name: Envoy Integration Tests for windows case-l7-intentions - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-l7-intentions" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-l7-intentions" -win=true - - - name: Envoy Integration Tests for windows case-multidc-rsa-ca - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-multidc-rsa-ca" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-multidc-rsa-ca" -win=true - - - name: Envoy Integration Tests for windows case-prometheus - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-prometheus" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-prometheus" -win=true - - - name: Envoy Integration Tests for windows case-property-override - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-property-override" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-property-override" -win=true - - - name: Envoy Integration Tests for windows case-stats-proxy - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-stats-proxy" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-stats-proxy" -win=true - - - name: Envoy Integration Tests for windows case-statsd-udp - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-statsd-udp" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-statsd-udp" -win=true - - - name: Envoy Integration Tests for windows case-terminating-gateway-hostnames - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-terminating-gateway-hostnames" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-terminating-gateway-hostnames" -win=true - - - name: Envoy Integration Tests for windows case-terminating-gateway-simple - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-terminating-gateway-simple" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-terminating-gateway-simple" -win=true - - - name: Envoy Integration Tests for windows case-terminating-gateway-without-services - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-terminating-gateway-without-services" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-terminating-gateway-without-services" -win=true - - - name: Envoy Integration Tests for windows case-upstream-config - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-upstream-config" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-upstream-config" -win=true - - - name: Envoy Integration Tests for windows case-wanfed-gw - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-wanfed-gw" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-wanfed-gw" -win=true - - - name: Envoy Integration Tests for windows case-ingress-gateway-sds - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-ingress-gateway-sds" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-sds" -win=true - - - name: Envoy Integration Tests for windows case-lua - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-lua" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-lua" -win=true - - - name: Envoy Integration Tests for windows case-terminating-gateway-subsets - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-terminating-gateway-subsets" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-terminating-gateway-subsets" -win=true - - # Skipping this because - https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/wasm_filter - # - name: Envoy Integration Tests for windows case-wasm - # shell: bash - # env: - # GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - # GOTESTSUM_FORMAT: standard-verbose - # COMPOSE_INTERACTIVE_NO_CLI: 1 - # LAMBDA_TESTS_ENABLED: "true" - # # tput complains if this isn't set to something. - # TERM: ansi - # run: | - # # shellcheck disable=SC2001 - # echo "Running Integration Test case-wasm" - # # shellcheck disable=SC2001 - # go test -v -timeout=45m -tags integration \ - # ./test/integration/connect/envoy -run="TestEnvoy/case-wasm" -win=true - - # Skipping because of - cacert is not available in curl windows - # https://www.phillipsj.net/posts/windows-curl-and-self-signed-certs/ - # - name: Envoy Integration Tests for windows case-ingress-gateway-tls - # shell: bash - # if: always() - # env: - # GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - # GOTESTSUM_FORMAT: standard-verbose - # COMPOSE_INTERACTIVE_NO_CLI: 1 - # LAMBDA_TESTS_ENABLED: "true" - # # tput complains if this isn't set to something. - # TERM: ansi - # run: | - # # shellcheck disable=SC2001 - # echo "Running Integration Test case-ingress-gateway-tls" - # # shellcheck disable=SC2001 - # go test -v -timeout=45m -tags integration \ - # ./test/integration/connect/envoy -run="TestEnvoy/case-ingress-gateway-tls" -win=true - - - name: Envoy Integration Tests for windows case-mesh-to-lambda - shell: bash - if: always() - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running Integration Test case-mesh-to-lambda" - # shellcheck disable=SC2001 - go test -v -timeout=45m -tags integration \ - ./test/integration/connect/envoy -run="TestEnvoy/case-mesh-to-lambda" -win=true - - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: Prepare datadog-ci - shell: bash - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/download/v2.17.2/datadog-ci_win-x64.exe" --output "C:/datadog-ci" - icacls C:/datadog-ci /grant:rx Everyone:RX - - - name: Upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: C:/datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - test-integrations-success: - needs: - - envoy-integration-test - runs-on: 'ubuntu-latest' - if: ${{ always() }} - steps: - - name: evaluate upstream job results - run: | - # exit 1 if failure or cancelled result for any upstream job - if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then - printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" - exit 1 - fi diff --git a/.github/workflows/test-integrations.yml b/.github/workflows/test-integrations.yml index 6816d9ef34a2..02ca7c187203 100644 --- a/.github/workflows/test-integrations.yml +++ b/.github/workflows/test-integrations.yml @@ -1,593 +1,622 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: test-integrations - -on: - pull_request: - branches-ignore: - - stable-website - - 'docs/**' - - 'ui/**' - - 'mktg-**' # Digital Team Terraform-generated branch prefix - - 'backport/docs/**' - - 'backport/ui/**' - - 'backport/mktg-**' - -env: - TEST_RESULTS_DIR: /tmp/test-results - TEST_RESULTS_ARTIFACT_NAME: test-results - CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} - GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} - GOTESTSUM_VERSION: "1.10.1" - CONSUL_BINARY_UPLOAD_NAME: consul-bin - # strip the hashicorp/ off the front of github.repository for consul - CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} - GOPRIVATE: github.com/hashicorp # Required for enterprise deps - SKIP_CHECK_BRANCH: ${{ github.head_ref || github.ref_name }} - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} - cancel-in-progress: true - -jobs: - conditional-skip: - runs-on: ubuntu-latest - name: Get files changed and conditionally skip CI - outputs: - skip-ci: ${{ steps.read-files.outputs.skip-ci }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - fetch-depth: 0 - - name: Get changed files - id: read-files - run: ./.github/scripts/filter_changed_files_go_test.sh - - setup: - needs: [conditional-skip] - runs-on: ubuntu-latest - name: Setup - if: needs.conditional-skip.outputs.skip-ci != 'true' - outputs: - compute-small: ${{ steps.runners.outputs.compute-small }} - compute-medium: ${{ steps.runners.outputs.compute-medium }} - compute-large: ${{ steps.runners.outputs.compute-large }} - compute-xl: ${{ steps.runners.outputs.compute-xl }} - enterprise: ${{ steps.runners.outputs.enterprise }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - id: runners - run: .github/scripts/get_runner_classes.sh - - dev-build: - needs: [setup] - uses: ./.github/workflows/reusable-dev-build.yml - with: - runs-on: ${{ needs.setup.outputs.compute-large }} - repository-name: ${{ github.repository }} - uploaded-binary-name: 'consul-bin' - secrets: - elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} - - nomad-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - needs: - - setup - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - matrix: - nomad-version: ['v1.6.2', 'v1.5.9', 'v1.4.13'] - steps: - - name: Checkout Nomad - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - repository: hashicorp/nomad - ref: ${{ matrix.nomad-version }} - - - name: Install Go - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - - name: Fetch Consul binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: ./bin - - name: Restore Consul permissions - run: | - chmod +x ./bin/consul - echo "$(pwd)/bin" >> $GITHUB_PATH - - - name: Make Nomad dev build - run: make pkg/linux_amd64/nomad - - - name: Run integration tests - run: | - go install gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} && \ - gotestsum \ - --format=short-verbose \ - --rerun-fails \ - --rerun-fails-report=/tmp/gotestsum-rerun-fails \ - --packages="./command/agent/consul" \ - --junitfile $TEST_RESULTS_DIR/results.xml -- \ - -run TestConsul - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - vault-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - needs: - - setup - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - matrix: - vault-version: ["1.15.0", "1.14.4", "1.13.8", "1.12.11"] - env: - VAULT_BINARY_VERSION: ${{ matrix.vault-version }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - - name: Install Vault - run: | - wget -q -O /tmp/vault.zip "https://releases.hashicorp.com/vault/${{ env.VAULT_BINARY_VERSION }}/vault_${{ env.VAULT_BINARY_VERSION }}_linux_amd64.zip" - unzip -d /tmp /tmp/vault.zip - echo "/tmp" >> $GITHUB_PATH - - - name: Run Connect CA Provider Tests - run: | - mkdir -p "${{ env.TEST_RESULTS_DIR }}" - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --format=short-verbose \ - --junitfile "${{ env.TEST_RESULTS_DIR }}/gotestsum-report.xml" \ - -- -tags "${{ env.GOTAGS }}" -cover -coverprofile=coverage.txt ./agent/connect/ca - # Run leader tests that require Vault - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --format=short-verbose \ - --junitfile "${{ env.TEST_RESULTS_DIR }}/gotestsum-report-leader.xml" \ - -- -tags "${{ env.GOTAGS }}" -cover -coverprofile=coverage-leader.txt -run Vault ./agent/consul - # Run agent tests that require Vault - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --format=short-verbose \ - --junitfile "${{ env.TEST_RESULTS_DIR }}/gotestsum-report-agent.xml" \ - -- -tags "${{ env.GOTAGS }}" -cover -coverprofile=coverage-agent.txt -run Vault ./agent - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" "${{ env.TEST_RESULTS_DIR }}/gotestsum-report.xml" - - - name: upload leader coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" "${{ env.TEST_RESULTS_DIR }}/gotestsum-report-leader.xml" - - - name: upload agent coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" "${{ env.TEST_RESULTS_DIR }}/gotestsum-report-agent.xml" - - generate-envoy-job-matrices: - needs: [setup] - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - name: Generate Envoy Job Matrices - outputs: - envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Generate Envoy Job Matrix - id: set-matrix - env: - # this is further going to multiplied in envoy-integration tests by the - # other dimensions in the matrix. Currently TOTAL_RUNNERS would be - # multiplied by 2 based on these values: - # envoy-version: ["1.27.2"] - # xds-target: ["server", "client"] - TOTAL_RUNNERS: 4 - JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' - run: | - NUM_RUNNERS=$TOTAL_RUNNERS - NUM_DIRS=$(find ./test/integration/connect/envoy -mindepth 1 -maxdepth 1 -type d | wc -l) - - if [ "$NUM_DIRS" -lt "$NUM_RUNNERS" ]; then - echo "TOTAL_RUNNERS is larger than the number of tests/packages to split." - NUM_RUNNERS=$((NUM_DIRS-1)) - fi - # fix issue where test splitting calculation generates 1 more split than TOTAL_RUNNERS. - NUM_RUNNERS=$((NUM_RUNNERS-1)) - { - echo -n "envoy-matrix=" - find ./test/integration/connect/envoy -maxdepth 1 -type d -print0 \ - | xargs -0 -n 1 basename \ - | jq --raw-input --argjson runnercount "$NUM_RUNNERS" "$JQ_SLICER" \ - | jq --compact-output 'map(join("|"))' - } >> "$GITHUB_OUTPUT" - - envoy-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} - needs: - - setup - - generate-envoy-job-matrices - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - matrix: - envoy-version: ["1.27.2"] - xds-target: ["server", "client"] - test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} - env: - ENVOY_VERSION: ${{ matrix.envoy-version }} - XDS_TARGET: ${{ matrix.xds-target }} - AWS_LAMBDA_REGION: us-west-2 - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: ./bin - - name: restore mode+x - run: chmod +x ./bin/consul - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0 - - - name: Docker build - run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin - - - name: Envoy Integration Tests - env: - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - LAMBDA_TESTS_ENABLED: "true" - # tput complains if this isn't set to something. - TERM: ansi - run: | - # shellcheck disable=SC2001 - echo "Running $(sed 's,|, ,g' <<< "${{ matrix.test-cases }}" |wc -w) subtests" - # shellcheck disable=SC2001 - sed 's,|,\n,g' <<< "${{ matrix.test-cases }}" - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --debug \ - --rerun-fails \ - --rerun-fails-report=/tmp/gotestsum-rerun-fails \ - --jsonfile /tmp/jsonfile/go-test.log \ - --packages=./test/integration/connect/envoy \ - -- -timeout=30m -tags integration -run="TestEnvoy/(${{ matrix.test-cases }})" - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - compatibility-integration-test: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} # NOTE: do not change without tuning the -p and -parallel flags in go test. - needs: - - setup - - dev-build - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - env: - ENVOY_VERSION: "1.25.4" - CONSUL_DATAPLANE_IMAGE: "docker.io/hashicorppreview/consul-dataplane:1.3-dev-ubi" - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: go env - - name: docker env - run: | - docker version - docker info - - name: fetch binary - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' - path: . - - name: restore mode+x - run: chmod +x consul - # Build the consul:local image from the already built binary - - name: Build consul:local image - run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . - - name: Build consul-envoy:target-version image - id: buildConsulEnvoyImage - continue-on-error: true - run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - - name: Retry Build consul-envoy:target-version image - if: steps.buildConsulEnvoyImage.outcome == 'failure' - run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets - - name: Build consul-dataplane:local image - run: docker build -t consul-dataplane:local --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg CONSUL_DATAPLANE_IMAGE=${{ env.CONSUL_DATAPLANE_IMAGE }} -f ./test/integration/consul-container/assets/Dockerfile-consul-dataplane ./test/integration/consul-container/assets - - name: Configure GH workaround for ipv6 loopback - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - cat /etc/hosts && echo "-----------" - sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6-localhost ip6-loopback/g' /etc/hosts - cat /etc/hosts - - name: Compatibility Integration Tests - run: | - mkdir -p "/tmp/test-results" - cd ./test/integration/consul-container - docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --raw-command \ - --format=pkgname-and-test-fails \ - --debug \ - --rerun-fails=3 \ - -- \ - go test \ - -p=6 \ - -parallel=4 \ - -tags "${{ env.GOTAGS }}" \ - -timeout=30m \ - -json \ - `go list -tags "${{ env.GOTAGS }}" ./... | grep -v upgrade | grep -v peering_commontopo` \ - --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --target-version local \ - --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --latest-version latest - ls -lrt - env: - # this is needed because of incompatibility between RYUK container and GHA - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - # tput complains if this isn't set to something. - TERM: ansi - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - integration-test-with-deployer: - runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} - needs: - - setup - permissions: - id-token: write # NOTE: this permission is explicitly required for Vault auth. - contents: read - strategy: - fail-fast: false - env: - DEPLOYER_CONSUL_DATAPLANE_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-dataplane:1.3-dev" - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. - - name: Setup Git - if: ${{ endsWith(github.repository, '-enterprise') }} - run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" - - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 - with: - go-version-file: 'go.mod' - - run: go env - - name: Build image - run: make test-compat-integ-setup - - name: Integration Tests - run: | - mkdir -p "${{ env.TEST_RESULTS_DIR }}" - export NOLOGBUFFER=1 - cd ./test-integ - go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ - --raw-command \ - --format=standard-verbose \ - --debug \ - -- \ - go test \ - -tags "${{ env.GOTAGS }}" \ - -timeout=20m \ - -parallel=2 \ - -json \ - `go list -tags "${{ env.GOTAGS }}" ./... | grep -v peering_commontopo` \ - --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --target-version local \ - --latest-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ - --latest-version latest - env: - # this is needed because of incompatibility between RYUK container and GHA - GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml - GOTESTSUM_FORMAT: standard-verbose - COMPOSE_INTERACTIVE_NO_CLI: 1 - # tput complains if this isn't set to something. - TERM: ansi - # NOTE: ENT specific step as we store secrets in Vault. - - name: Authenticate to Vault - if: ${{ endsWith(github.repository, '-enterprise') }} - id: vault-auth - run: vault-auth - - # NOTE: ENT specific step as we store secrets in Vault. - - name: Fetch Secrets - if: ${{ endsWith(github.repository, '-enterprise') }} - id: secrets - uses: hashicorp/vault-action@v2.5.0 - with: - url: ${{ steps.vault-auth.outputs.addr }} - caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} - token: ${{ steps.vault-auth.outputs.token }} - secrets: | - kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; - - - name: prepare datadog-ci - if: ${{ !endsWith(github.repository, '-enterprise') }} - run: | - curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" - chmod +x /usr/local/bin/datadog-ci - - - name: upload coverage - # do not run on forks - if: github.event.pull_request.head.repo.full_name == github.repository - env: - DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" - DD_ENV: ci - run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml - - test-integrations-success: - needs: - - conditional-skip - - setup - - dev-build - - nomad-integration-test - - vault-integration-test - - generate-envoy-job-matrices - - envoy-integration-test - - compatibility-integration-test - - integration-test-with-deployer - runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} - if: always() && needs.conditional-skip.outputs.skip-ci != 'true' - steps: - - name: evaluate upstream job results - run: | - # exit 1 if failure or cancelled result for any upstream job - if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then - printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" - exit 1 - fi +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +#name: test-integrations +# +#on: +# pull_request: +# branches-ignore: +# - stable-website +# - 'docs/**' +# - 'ui/**' +# - 'mktg-**' # Digital Team Terraform-generated branch prefix +# - 'backport/docs/**' +# - 'backport/ui/**' +# - 'backport/mktg-**' +# push: +# branches: +# # Push events on the main branch +# - main +# - release/** +# +#env: +# TEST_RESULTS_DIR: /tmp/test-results +# TEST_RESULTS_ARTIFACT_NAME: test-results +# CONSUL_LICENSE: ${{ secrets.CONSUL_LICENSE }} +# GOTAGS: ${{ endsWith(github.repository, '-enterprise') && 'consulent' || '' }} +# GOTESTSUM_VERSION: "1.11.0" +# CONSUL_BINARY_UPLOAD_NAME: consul-bin +# # strip the hashicorp/ off the front of github.repository for consul +# CONSUL_LATEST_IMAGE_NAME: ${{ endsWith(github.repository, '-enterprise') && github.repository || 'hashicorp/consul' }} +# GOPRIVATE: github.com/hashicorp # Required for enterprise deps +# +#concurrency: +# group: "${{ github.workflow }}-${{ github.head_ref || github.ref }}" +# cancel-in-progress: true +# +#jobs: +# conditional-skip: +# uses: ./.github/workflows/reusable-conditional-skip.yml +# +# setup: +# needs: [conditional-skip] +# runs-on: ubuntu-latest +# name: Setup +# if: needs.conditional-skip.outputs.skip-ci != 'true' +# outputs: +# compute-small: ${{ steps.runners.outputs.compute-small }} +# compute-medium: ${{ steps.runners.outputs.compute-medium }} +# compute-large: ${{ steps.runners.outputs.compute-large }} +# compute-xl: ${{ steps.runners.outputs.compute-xl }} +# enterprise: ${{ steps.runners.outputs.enterprise }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# - id: runners +# run: .github/scripts/get_runner_classes.sh +# +# get-go-version: +# uses: ./.github/workflows/reusable-get-go-version.yml +# +# get-envoy-versions: +# uses: ./.github/workflows/reusable-get-envoy-versions.yml +# +# dev-build: +# needs: +# - setup +# - get-go-version +# uses: ./.github/workflows/reusable-dev-build.yml +# with: +# runs-on: ${{ needs.setup.outputs.compute-large }} +# repository-name: ${{ github.repository }} +# uploaded-binary-name: 'consul-bin' +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# secrets: +# elevated-github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} +# +# nomad-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# needs: +# - setup +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# matrix: +# nomad-version: ['v1.7.7', 'v1.6.10', 'v1.5.17'] +# steps: +# - name: Checkout Nomad +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# repository: hashicorp/nomad +# ref: ${{ matrix.nomad-version }} +# +# - name: Install Go +# uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# # Do not explicitly set Go version here, as it should depend on what Nomad declares. +# go-version-file: 'go.mod' +# +# - name: Fetch Consul binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: ./bin +# - name: Restore Consul permissions +# run: | +# chmod +x ./bin/consul +# echo "$(pwd)/bin" >> $GITHUB_PATH +# +# - name: Make Nomad dev build +# run: | +# make pkg/linux_amd64/nomad +# echo "$(pwd)/pkg/linux_amd64" >> $GITHUB_PATH +# +# - name: Run integration tests +# run: | +# go install gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} && \ +# gotestsum \ +# --format=github-actions \ +# --rerun-fails \ +# --rerun-fails-report=/tmp/gotestsum-rerun-fails \ +# --packages="./command/agent/consul" \ +# --junitfile $TEST_RESULTS_DIR/results.xml -- \ +# -run TestConsul +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# vault-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# needs: +# - setup +# - get-go-version +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# matrix: +# vault-version: ["1.16.2", "1.15.6", "1.14.10"] +# env: +# VAULT_BINARY_VERSION: ${{ matrix.vault-version }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# # We use the current Consul Go version here since Vault is installed as a binary +# # and tests are run from the Consul repo. +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# +# - name: Install Vault +# run: | +# wget -q -O /tmp/vault.zip "https://releases.hashicorp.com/vault/${{ env.VAULT_BINARY_VERSION }}/vault_${{ env.VAULT_BINARY_VERSION }}_linux_amd64.zip" +# unzip -d /tmp /tmp/vault.zip +# echo "/tmp" >> $GITHUB_PATH +# +# - name: Run Connect CA Provider Tests +# run: | +# mkdir -p "${{ env.TEST_RESULTS_DIR }}" +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --format=github-actions \ +# --junitfile "${{ env.TEST_RESULTS_DIR }}/gotestsum-report.xml" \ +# -- -tags "${{ env.GOTAGS }}" -cover -coverprofile=coverage.txt ./agent/connect/ca +# # Run leader tests that require Vault +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --format=github-actions \ +# --junitfile "${{ env.TEST_RESULTS_DIR }}/gotestsum-report-leader.xml" \ +# -- -tags "${{ env.GOTAGS }}" -cover -coverprofile=coverage-leader.txt -run Vault ./agent/consul +# # Run agent tests that require Vault +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --format=github-actions \ +# --junitfile "${{ env.TEST_RESULTS_DIR }}/gotestsum-report-agent.xml" \ +# -- -tags "${{ env.GOTAGS }}" -cover -coverprofile=coverage-agent.txt -run Vault ./agent +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" "${{ env.TEST_RESULTS_DIR }}/gotestsum-report.xml" +# +# - name: upload leader coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" "${{ env.TEST_RESULTS_DIR }}/gotestsum-report-leader.xml" +# +# - name: upload agent coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" "${{ env.TEST_RESULTS_DIR }}/gotestsum-report-agent.xml" +# +# generate-envoy-job-matrices: +# needs: [setup] +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# name: Generate Envoy Job Matrices +# outputs: +# envoy-matrix: ${{ steps.set-matrix.outputs.envoy-matrix }} +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# - name: Generate Envoy Job Matrix +# id: set-matrix +# env: +# # TEST_SPLITS sets the number of test case splits to use in the matrix. This will be +# # further multiplied in envoy-integration tests by the other dimensions in the matrix +# # to determine the total number of runners used. +# TEST_SPLITS: 4 +# JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' +# run: | +# NUM_DIRS=$(find ./test/integration/connect/envoy -mindepth 1 -maxdepth 1 -type d | wc -l) +# +# if [ "$NUM_DIRS" -lt "$TEST_SPLITS" ]; then +# echo "TEST_SPLITS is larger than the number of tests/packages to split." +# TEST_SPLITS=$((NUM_DIRS-1)) +# fi +# # fix issue where test splitting calculation generates 1 more split than TEST_SPLITS. +# TEST_SPLITS=$((TEST_SPLITS-1)) +# { +# echo -n "envoy-matrix=" +# find ./test/integration/connect/envoy -maxdepth 1 -type d -print0 \ +# | xargs -0 -n 1 basename \ +# | jq --raw-input --argjson runnercount "$TEST_SPLITS" "$JQ_SLICER" \ +# | jq --compact-output 'map(join("|"))' +# } >> "$GITHUB_OUTPUT" +# +# envoy-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large) }} +# needs: +# - setup +# - get-go-version +# - get-envoy-versions +# - generate-envoy-job-matrices +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# matrix: +# xds-target: ["server", "client"] +# test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} +# env: +# ENVOY_VERSION: ${{ needs.get-envoy-versions.outputs.max-envoy-version }} +# XDS_TARGET: ${{ matrix.xds-target }} +# AWS_LAMBDA_REGION: us-west-2 +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# +# - name: fetch binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: ./bin +# - name: restore mode+x +# run: chmod +x ./bin/consul +# +# - name: Set up Docker Buildx +# uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 +# +# - name: Docker build +# run: docker build -t consul:local -f ./build-support/docker/Consul-Dev.dockerfile ./bin +# +# - name: Envoy Integration Tests +# id: envoy-integration-tests +# env: +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# LAMBDA_TESTS_ENABLED: "true" +# # tput complains if this isn't set to something. +# TERM: ansi +# run: | +# # shellcheck disable=SC2001 +# echo "Running $(sed 's,|, ,g' <<< "${{ matrix.test-cases }}" |wc -w) subtests" +# # shellcheck disable=SC2001 +# sed 's,|,\n,g' <<< "${{ matrix.test-cases }}" +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --debug \ +# --rerun-fails \ +# --rerun-fails-report=/tmp/gotestsum-rerun-fails \ +# --jsonfile /tmp/jsonfile/go-test.log \ +# --packages=./test/integration/connect/envoy \ +# -- -timeout=30m -tags integration -run="TestEnvoy/(${{ matrix.test-cases }})" +# +# # See https://github.com/orgs/community/discussions/8945#discussioncomment-9897011 +# # and overall topic discussion for why this is necessary. +# - name: Generate artifact ID +# id: generate-artifact-id +# if: ${{ failure() && steps.envoy-integration-tests.conclusion == 'failure' }} +# run: | +# ARTIFACT_ID=$(uuidgen) +# echo "Artifact ID: $ARTIFACT_ID (search this in job summary for download link)" +# echo "artifact_id=$ARTIFACT_ID" >> "$GITHUB_ENV" +# +# - name: Upload failure logs +# if: ${{ failure() && steps.envoy-integration-tests.conclusion == 'failure' }} +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 +# with: +# name: envoy-${{ matrix.envoy-version }}-logs-${{ env.artifact_id }} +# path: test/integration/connect/envoy/workdir/logs/ +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# compatibility-integration-test: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-xl) }} # NOTE: do not change without tuning the -p and -parallel flags in go test. +# needs: +# - setup +# - get-go-version +# - get-envoy-versions +# - dev-build +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# env: +# ENVOY_VERSION: ${{ needs.get-envoy-versions.outputs.max-envoy-version }} +# #TODO don't harcode this image name +# CONSUL_DATAPLANE_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-dataplane:1.6-dev-ubi" +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go env +# - name: docker env +# run: | +# docker version +# docker info +# - name: fetch binary +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 +# with: +# name: '${{ env.CONSUL_BINARY_UPLOAD_NAME }}' +# path: . +# - name: restore mode+x +# run: chmod +x consul +# # Build the consul:local image from the already built binary +# - name: Build consul:local image +# run: docker build -t ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local -f ./build-support/docker/Consul-Dev.dockerfile . +# - name: Build consul-envoy:target-version image +# id: buildConsulEnvoyImage +# continue-on-error: true +# run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# - name: Retry Build consul-envoy:target-version image +# if: steps.buildConsulEnvoyImage.outcome == 'failure' +# run: docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg ENVOY_VERSION=${{ env.ENVOY_VERSION }} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets +# - name: Build consul-dataplane:local image +# run: docker build -t consul-dataplane:local --build-arg CONSUL_IMAGE=${{ env.CONSUL_LATEST_IMAGE_NAME }}:local --build-arg CONSUL_DATAPLANE_IMAGE=${{ env.CONSUL_DATAPLANE_IMAGE }} -f ./test/integration/consul-container/assets/Dockerfile-consul-dataplane ./test/integration/consul-container/assets +# - name: Configure GH workaround for ipv6 loopback +# if: ${{ !endsWith(github.repository, '-enterprise') }} +# run: | +# cat /etc/hosts && echo "-----------" +# sudo sed -i 's/::1 *localhost ip6-localhost ip6-loopback/::1 ip6-localhost ip6-loopback/g' /etc/hosts +# cat /etc/hosts +# - name: Compatibility Integration Tests +# run: | +# mkdir -p "/tmp/test-results" +# cd ./test/integration/consul-container +# docker run --rm ${{ env.CONSUL_LATEST_IMAGE_NAME }}:local consul version +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --raw-command \ +# --format=github-actions \ +# --rerun-fails \ +# -- \ +# go test \ +# -p=6 \ +# -parallel=4 \ +# -tags "${{ env.GOTAGS }}" \ +# -timeout=30m \ +# -json \ +# `go list -tags "${{ env.GOTAGS }}" ./... | grep -v upgrade | grep -v peering_commontopo` \ +# --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --target-version local \ +# --latest-image docker.mirror.hashicorp.services/${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --latest-version latest +# ls -lrt +# env: +# # this is needed because of incompatibility between RYUK container and GHA +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# # tput complains if this isn't set to something. +# TERM: ansi +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# integration-test-with-deployer: +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-large ) }} +# needs: +# - setup +# - get-go-version +# permissions: +# id-token: write # NOTE: this permission is explicitly required for Vault auth. +# contents: read +# strategy: +# fail-fast: false +# env: +# # TODO @sarah.alsmiller Don't hardcode this version value +# DEPLOYER_CONSUL_DATAPLANE_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-dataplane:1.6-dev" +# steps: +# - name: Checkout code +# uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# # NOTE: This step is specifically needed for ENT. It allows us to access the required private HashiCorp repos. +# - name: Setup Git +# if: ${{ endsWith(github.repository, '-enterprise') }} +# run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com" +# - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 +# with: +# go-version: ${{ needs.get-go-version.outputs.go-version }} +# - run: go env +# - name: Build image +# run: make test-deployer-setup +# - name: Integration Tests +# run: | +# mkdir -p "${{ env.TEST_RESULTS_DIR }}" +# #export NOLOGBUFFER=1 +# cd ./test-integ +# go run gotest.tools/gotestsum@v${{env.GOTESTSUM_VERSION}} \ +# --raw-command \ +# --format=github-actions \ +# -- \ +# go test \ +# -tags "${{ env.GOTAGS }}" \ +# -timeout=20m \ +# -parallel=2 \ +# -failfast \ +# -json \ +# `go list -tags "${{ env.GOTAGS }}" ./... | grep -v peering_commontopo | grep -v upgrade ` \ +# --target-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --target-version local \ +# --latest-image ${{ env.CONSUL_LATEST_IMAGE_NAME }} \ +# --latest-version latest +# env: +# # this is needed because of incompatibility between RYUK container and GHA +# GOTESTSUM_JUNITFILE: ${{ env.TEST_RESULTS_DIR }}/results.xml +# GOTESTSUM_FORMAT: standard-verbose +# COMPOSE_INTERACTIVE_NO_CLI: 1 +# # tput complains if this isn't set to something. +# TERM: ansi +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Authenticate to Vault +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: vault-auth +# run: vault-auth +# +# # NOTE: ENT specific step as we store secrets in Vault. +# - name: Fetch Secrets +# if: ${{ !cancelled() && endsWith(github.repository, '-enterprise') }} +# id: secrets +# uses: hashicorp/vault-action@v3 +# with: +# url: ${{ steps.vault-auth.outputs.addr }} +# caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }} +# token: ${{ steps.vault-auth.outputs.token }} +# secrets: | +# kv/data/github/${{ github.repository }}/datadog apikey | DATADOG_API_KEY; +# +# - name: prepare datadog-ci +# if: ${{ !cancelled() && !endsWith(github.repository, '-enterprise') }} +# run: | +# curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" +# chmod +x /usr/local/bin/datadog-ci +# +# - name: upload coverage +# # do not run on forks +# if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} +# env: +# DATADOG_API_KEY: "${{ endsWith(github.repository, '-enterprise') && env.DATADOG_API_KEY || secrets.DATADOG_API_KEY }}" +# DD_ENV: ci +# run: datadog-ci junit upload --service "$GITHUB_REPOSITORY" $TEST_RESULTS_DIR/results.xml +# +# test-integrations-success: +# needs: +# - conditional-skip +# - setup +# - dev-build +# - nomad-integration-test +# - vault-integration-test +# - generate-envoy-job-matrices +# - envoy-integration-test +# - compatibility-integration-test +# - integration-test-with-deployer +# runs-on: ${{ fromJSON(needs.setup.outputs.compute-small) }} +# if: always() && needs.conditional-skip.outputs.skip-ci != 'true' +# steps: +# - name: evaluate upstream job results +# run: | +# # exit 1 if failure or cancelled result for any upstream job +# if printf '${{ toJSON(needs) }}' | grep -E -i '\"result\": \"(failure|cancelled)\"'; then +# printf "Tests failed or workflow cancelled:\n\n${{ toJSON(needs) }}" +# exit 1 +# fi diff --git a/.github/workflows/verify-ci.yml b/.github/workflows/verify-ci.yml index 4bd4536add1a..f20be36fe74a 100644 --- a/.github/workflows/verify-ci.yml +++ b/.github/workflows/verify-ci.yml @@ -1,23 +1,23 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -# verify-ci is a no-op workflow that must run on every PR. It is used in a -# branch protection rule to detect when CI workflows are not running. -name: verify-ci - -permissions: - contents: read - -on: - pull_request: - push: - branches: - # Push events on the main branch - - main - - release/** - -jobs: - verify-ci-success: - runs-on: ubuntu-latest - steps: - - run: echo "verify-ci succeeded" +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +## verify-ci is a no-op workflow that must run on every PR. It is used in a +## branch protection rule to detect when CI workflows are not running. +#name: verify-ci +# +#permissions: +# contents: read +# +#on: +# pull_request: +# push: +# branches: +# # Push events on the main branch +# - main +# - release/** +# +#jobs: +# verify-ci-success: +# runs-on: ubuntu-latest +# steps: +# - run: echo "verify-ci succeeded" diff --git a/.github/workflows/verify-envoy-version.yml b/.github/workflows/verify-envoy-version.yml index dafa9db6f22a..236233cf0f4d 100644 --- a/.github/workflows/verify-envoy-version.yml +++ b/.github/workflows/verify-envoy-version.yml @@ -1,31 +1,31 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -# This action ensures that Envoy is up to date on main and release branches. -# This workflow is only triggered on the main and release branches and will -# only perform a version check when a new release branch is created -# Contact Consul team for any questions - -name: Verify Envoy Version - -on: - push: - branches: - - main - - release/** - -env: - SKIP_VERIFY_ENVOY_VERSION: ${{ vars.SKIP_VERIFY_ENVOY_VERSION }} - -jobs: - verify-envoy-version: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 # by default the checkout action doesn't checkout all branches - - name: Run Envoy Version Verification for main and release branches - run: ./.github/scripts/verify_envoy_version.sh - env: - GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }} \ No newline at end of file +## Copyright (c) HashiCorp, Inc. +## SPDX-License-Identifier: MPL-2.0 +# +## This action ensures that Envoy is up to date on main and release branches. +## This workflow is only triggered on the main and release branches and will +## only perform a version check when a new release branch is created +## Contact Consul team for any questions +# +#name: Verify Envoy Version +# +#on: +# push: +# branches: +# - main +# - release/** +# +#env: +# SKIP_VERIFY_ENVOY_VERSION: ${{ vars.SKIP_VERIFY_ENVOY_VERSION }} +# +#jobs: +# verify-envoy-version: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 +# with: +# ref: ${{ github.event.pull_request.head.sha }} +# fetch-depth: 0 # by default the checkout action doesn't checkout all branches +# - name: Run Envoy Version Verification for main and release branches +# run: ./.github/scripts/verify_envoy_version.sh +# env: +# GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 793354db02d5..b03ff327c411 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ Thumbs.db __debug_bin coverage.out *.tmp +.zed # MacOS .DS_Store @@ -70,3 +71,4 @@ terraform.rc /go.work /go.work.sum .docker +.cache diff --git a/.go-version b/.go-version new file mode 100644 index 000000000000..5d287e490a76 --- /dev/null +++ b/.go-version @@ -0,0 +1 @@ +1.22.7 \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml index 0d426b34cd02..e530ce70bdf1 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -31,7 +31,7 @@ issues: # Allow usage of deprecated values. - linters: [ staticcheck ] text: 'SA1019:' - path: "(agent/grpc-external)" + path: "(agent/grpc-external|agent/grpc-internal)" # An argument that always receives the same value is often not a problem. - linters: [unparam] @@ -75,7 +75,9 @@ linters-settings: simplify: true forbidigo: # Forbid the following identifiers (list of regexp). + # Format includes custom message based on https://github.com/ashanbrown/forbidigo/pull/11 forbid: + - '\bhtml\/template\b(# Use text/template instead)?' - '\bioutil\b(# Use io and os packages instead of ioutil)?' - '\brequire\.New\b(# Use package-level functions with explicit TestingT)?' - '\bassert\.New\b(# Use package-level functions with explicit TestingT)?' @@ -98,18 +100,14 @@ linters-settings: - google.golang.org/protobuf depguard: - list-type: denylist - include-go-root: true - # A list of packages for the list type specified. - # Default: [] - packages: - - net/rpc - # A list of packages for the list type specified. - # Specify an error message to output when a denied package is used. - # Default: [] - packages-with-error-message: - - net/rpc: "only use forked copy in github.com/hashicorp/consul-net-rpc/net/rpc" - - github.com/golang/protobuf: "only use google.golang.org/protobuf" + rules: + main: + listMode: lax + deny: + - pkg: net/rpc + desc: "only use forked copy in github.com/hashicorp/consul-net-rpc/net/rpc" + - pkg: github.com/golang/protobuf + desc: "only use google.golang.org/protobuf" run: timeout: 10m diff --git a/.grpcmocks.yaml b/.grpcmocks.yaml new file mode 100644 index 000000000000..97949b9ff2cf --- /dev/null +++ b/.grpcmocks.yaml @@ -0,0 +1,21 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +with-expecter: true +recursive: true +include-regex: ".*" +exclude-regex: "(serverStream|Is(Inmem|Cloning).*Client)" +# We don't want the mocks within proto-public to prevent forcing a dependency +# of the testify library on the modules usage. The mocks are only for +# internal testing purposes. Other consumers can generated the mocks into +# their own code base. +dir: "grpcmocks/{{.InterfaceDirRelative}}" +outpkg: "mock{{.PackageName}}" +mockname: "{{.InterfaceName}}" +packages: + github.com/hashicorp/consul/proto-public/pbacl: + github.com/hashicorp/consul/proto-public/pbconnectca: + github.com/hashicorp/consul/proto-public/pbdataplane: + github.com/hashicorp/consul/proto-public/pbserverdiscovery: + github.com/hashicorp/consul/proto-public/pbresource: + github.com/hashicorp/consul/proto-public/pbdns: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000000..ec68f1133db8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,54 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +# +# Opt-in to running pre-commit hooks by running `make tools`. +# +# Guidelines for adding new pre-commit hooks +# ==================================================================== +# A hook SHOULD be blazingly fast (<2s) to impose minimal latency on +# developer workflows (e.g. golangci-lint takes > 8s) +# +# A hook SHOULD attempt to fix errors, not just identify them. +# +# A hook SHOULD address common errors in files that tend to change +# frequently. While surfacing esoteric issues is nice, hooks that have a +# wider impact are preferred. +# +repos: +- repo: https://github.com/tekwizely/pre-commit-golang + rev: v1.0.0-rc.1 + hooks: + # Formats go imports into deterministic sections. + # `pre-commit run gci` to run in isolation. + - id: my-cmd + name: Format go imports + alias: gci + # skip all generated go files + exclude: | + (?x)( + ^proto-public/| + ^proto/| + ^agent/xds/z_xds_packages\.go$| + ^testing/deployer/topology/default_versions\.go$| + \.deepcopy\.go$| + \.gen\.go$| + \.pb\.go$| + \.pb\.binary\.go$| + generated_funcs\.go$| + _generated_test\.go$| + mock_.+\.go$ + ) + args: + - "gci" + - "write" + - "--section" + - "standard" + - "--section" + - "default" + - "--section" + - "prefix(github.com/hashicorp/)" + - "--section" + - "prefix(github.com/hashicorp/consul/)" diff --git a/.release/security-scan.hcl b/.release/security-scan.hcl index 0dd5116c6ece..3e9506d79580 100644 --- a/.release/security-scan.hcl +++ b/.release/security-scan.hcl @@ -1,17 +1,94 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: BUSL-1.1 +# These scan results are run as part of CRT workflows. + +# Un-triaged results will block release. See `security-scanner` docs for more +# information on how to add `triage` config to unblock releases for specific results. +# In most cases, we should not need to disable the entire scanner to unblock a release. + +# To run manually, install scanner and then from the repository root run +# `SECURITY_SCANNER_CONFIG_FILE=.release/security-scan.hcl scan ...` +# To scan a local container, add `local_daemon = true` to the `container` block below. +# See `security-scanner` docs or run with `--help` for scan target syntax. + container { dependencies = true - alpine_secdb = false - secrets = false + alpine_secdb = true + + secrets { + matchers { + // Use most of default list, minus Vault (`hashicorp`), which has experienced false positives. + // See https://github.com/hashicorp/security-scanner/blob/v0.0.2/pkg/scanner/secrets.go#L130C2-L130C2 + known = [ + // "hashicorp", + "aws", + "google", + "slack", + "github", + "azure", + "npm", + ] + } + } + + # Triage items that are _safe_ to ignore here. Note that this list should be + # periodically cleaned up to remove items that are no longer found by the scanner. + triage { + suppress { + # N.b. `vulnerabilites` is the correct spelling for this tool. + vulnerabilites = [ + "CVE-2024-8096", # curl@8.9.1-r2, + "CVE-2024-9143", # openssl@3.3.2-r0, + ] + paths = [ + "internal/tools/proto-gen-rpc-glue/e2e/consul/*", + "test/integration/connect/envoy/test-sds-server/*", + "test/integration/consul-container/*", + "testing/deployer/*", + "test-integ/*", + ] + } + } } binary { - secrets = false - go_modules = false + go_modules = true osv = true - # TODO(spatel): CE refactor - oss_index = true - nvd = true + go_stdlib = true + # We can't enable npm for binary targets today because we don't yet embed the relevant file + # (yarn.lock) in the Consul binary. This is something we may investigate in the future. + + secrets { + matchers { + // Use most of default list, minus Vault (`hashicorp`), which has experienced false positives. + // See https://github.com/hashicorp/security-scanner/blob/v0.0.2/pkg/scanner/secrets.go#L130C2-L130C2 + known = [ + // "hashicorp", + "aws", + "google", + "slack", + "github", + "azure", + "npm", + ] + } + } + + # Triage items that are _safe_ to ignore here. Note that this list should be + # periodically cleaned up to remove items that are no longer found by the scanner. + triage { + suppress { + # N.b. `vulnerabilites` is the correct spelling for this tool. + vulnerabilites = [ + ] + paths = [ + "internal/tools/proto-gen-rpc-glue/e2e/consul/*", + "test/integration/connect/envoy/test-sds-server/*", + "test/integration/consul-container/*", + "testing/deployer/*", + "test-integ/*", + ] + } + } } diff --git a/.release/versions.hcl b/.release/versions.hcl new file mode 100644 index 000000000000..253430f3ccc1 --- /dev/null +++ b/.release/versions.hcl @@ -0,0 +1,19 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +# This manifest file describes active releases and is consumed by the backport tooling. +# It is only consumed from the default branch, so backporting changes to this file is not necessary. + +schema = 1 +active_versions { + version "1.20" { + ce_active = true + } + version "1.19" {} + version "1.18" { + lts = true + } + version "1.15" { + lts = true + } +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bbe1143e7f7..1956081e1ac2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,788 @@ +## 1.20.1 (October 29, 2024) +BREAKING CHANGES: + +* mesh: Enable Envoy `HttpConnectionManager.normalize_path` by default on inbound traffic to mesh proxies. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005). [[GH-21816](https://github.com/hashicorp/consul/issues/21816)] + +SECURITY: + +* mesh: Add `contains` and `ignoreCase` to L7 Intentions HTTP header matching criteria to support configuration resilient to variable casing and multiple values. This resolves [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). [[GH-21816](https://github.com/hashicorp/consul/issues/21816)] +* mesh: Add `http.incoming.requestNormalization` to Mesh configuration entry to support inbound service traffic request normalization. This resolves [CVE-2024-10005](https://nvd.nist.gov/vuln/detail/CVE-2024-10005) and [CVE-2024-10006](https://nvd.nist.gov/vuln/detail/CVE-2024-10006). [[GH-21816](https://github.com/hashicorp/consul/issues/21816)] + +IMPROVEMENTS: + +* api: remove dependency on proto-public, protobuf, and grpc [[GH-21780](https://github.com/hashicorp/consul/issues/21780)] +* snapshot agent: **(Enterprise only)** Implement Service Principal Auth for snapshot agent on azure. +* xds: configures Envoy to load balance over all instances of an external service configured with hostnames when "envoy_dns_discovery_type" is set to "STRICT_DNS" [[GH-21655](https://github.com/hashicorp/consul/issues/21655)] + +## 1.20.0 (October 14, 2024) + +SECURITY: + +* Explicitly set 'Content-Type' header to mitigate XSS vulnerability. [[GH-21704](https://github.com/hashicorp/consul/issues/21704)] +* Implement HTML sanitization for user-generated content to prevent XSS attacks in the UI. [[GH-21711](https://github.com/hashicorp/consul/issues/21711)] +* UI: Remove codemirror linting due to package dependency [[GH-21726](https://github.com/hashicorp/consul/issues/21726)] +* Upgrade Go to use 1.22.7. This addresses CVE +[CVE-2024-34155](https://nvd.nist.gov/vuln/detail/CVE-2024-34155) [[GH-21705](https://github.com/hashicorp/consul/issues/21705)] +* Upgrade to support aws/aws-sdk-go `v1.55.5 or higher`. This resolves CVEs +[CVE-2020-8911](https://nvd.nist.gov/vuln/detail/cve-2020-8911) and +[CVE-2020-8912](https://nvd.nist.gov/vuln/detail/cve-2020-8912). [[GH-21684](https://github.com/hashicorp/consul/issues/21684)] +* ui: Pin a newer resolution of Braces [[GH-21710](https://github.com/hashicorp/consul/issues/21710)] +* ui: Pin a newer resolution of Codemirror [[GH-21715](https://github.com/hashicorp/consul/issues/21715)] +* ui: Pin a newer resolution of Markdown-it [[GH-21717](https://github.com/hashicorp/consul/issues/21717)] +* ui: Pin a newer resolution of ansi-html [[GH-21735](https://github.com/hashicorp/consul/issues/21735)] + +FEATURES: + +* grafana: added the dashboards service-to-service dashboard, service dashboard, and consul dataplane dashboard [[GH-21806](https://github.com/hashicorp/consul/issues/21806)] +* server: remove v2 tenancy, catalog, and mesh experiments [[GH-21592](https://github.com/hashicorp/consul/issues/21592)] + +IMPROVEMENTS: + +* security: upgrade ubi base image to 9.4 [[GH-21750](https://github.com/hashicorp/consul/issues/21750)] +* connect: Add Envoy 1.31 and 1.30 to support matrix [[GH-21616](https://github.com/hashicorp/consul/issues/21616)] + +BUG FIXES: + +* jwt-provider: change dns lookup family from the default of AUTO which would prefer ipv6 to ALL if LOGICAL_DNS is used or PREFER_IPV4 if STRICT_DNS is used to gracefully handle transitions to ipv6. [[GH-21703](https://github.com/hashicorp/consul/issues/21703)] + +## 1.20.0-rc1 (September 19, 2024) + +SECURITY: + +* Explicitly set 'Content-Type' header to mitigate XSS vulnerability. [[GH-21704](https://github.com/hashicorp/consul/issues/21704)] +* Implement HTML sanitization for user-generated content to prevent XSS attacks in the UI. [[GH-21711](https://github.com/hashicorp/consul/issues/21711)] +* UI: Remove codemirror linting due to package dependency [[GH-21726](https://github.com/hashicorp/consul/issues/21726)] +* Upgrade Go to use 1.22.7. This addresses CVE +[CVE-2024-34155](https://nvd.nist.gov/vuln/detail/CVE-2024-34155) [[GH-21705](https://github.com/hashicorp/consul/issues/21705)] +* Upgrade to support aws/aws-sdk-go `v1.55.5 or higher`. This resolves CVEs +[CVE-2020-8911](https://nvd.nist.gov/vuln/detail/cve-2020-8911) and +[CVE-2020-8912](https://nvd.nist.gov/vuln/detail/cve-2020-8912). [[GH-21684](https://github.com/hashicorp/consul/issues/21684)] +* ui: Pin a newer resolution of Braces [[GH-21710](https://github.com/hashicorp/consul/issues/21710)] +* ui: Pin a newer resolution of Codemirror [[GH-21715](https://github.com/hashicorp/consul/issues/21715)] +* ui: Pin a newer resolution of Markdown-it [[GH-21717](https://github.com/hashicorp/consul/issues/21717)] +* ui: Pin a newer resolution of ansi-html [[GH-21735](https://github.com/hashicorp/consul/issues/21735)] + +FEATURES: + +* server: remove v2 tenancy, catalog, and mesh experiments [[GH-21592](https://github.com/hashicorp/consul/issues/21592)] + +IMPROVEMENTS: + +* security: upgrade ubi base image to 9.4 [[GH-21750](https://github.com/hashicorp/consul/issues/21750)] +* connect: Add Envoy 1.31 and 1.30 to support matrix [[GH-21616](https://github.com/hashicorp/consul/issues/21616)] + +BUG FIXES: + +* jwt-provider: change dns lookup family from the default of AUTO which would prefer ipv6 to ALL if LOGICAL_DNS is used or PREFER_IPV4 if STRICT_DNS is used to gracefully handle transitions to ipv6. [[GH-21703](https://github.com/hashicorp/consul/issues/21703)] + +## 1.19.2 (August 26, 2024) + +SECURITY: + +* ui: Upgrade modules with d3-color as a dependency to address denial of service issue in d3-color < 3.1.0 [[GH-21588](https://github.com/hashicorp/consul/issues/21588)] + +IMPROVEMENTS: + +* Use Envoy's default for a route's validate_clusters option, which is false. This fixes a case where non-existent clusters could cause a route to no longer route to any of its backends, including existing ones. [[GH-21587](https://github.com/hashicorp/consul/issues/21587)] + +BUG FIXES: + +* api-gateway: **(Enterprise only)** ensure clusters are properly created for JWT providers with a remote URI for the JWKS endpoint [[GH-21604](https://github.com/hashicorp/consul/issues/21604)] + +## 1.18.4 Enterprise (August 26, 2024) + +Enterprise LTS: Consul Enterprise 1.18 is a Long-Term Support (LTS) release. + +SECURITY: +* ui: Upgrade modules with d3-color as a dependency to address denial of service issue in d3-color < 3.1.0 + +IMPROVEMENTS: + +* Use Envoy's default for a route's validate_clusters option, which is false. This fixes a case where non-existent clusters could cause a route to no longer route to any of its backends, including existing ones. [[GH-21587](https://github.com/hashicorp/consul/issues/21587)] + +## 1.17.7 Enterprise (August 26, 2024) + +SECURITY: +* ui: Upgrade modules with d3-color as a dependency to address denial of service issue in d3-color < 3.1.0 + +IMPROVEMENTS: + +* Use Envoy's default for a route's validate_clusters option, which is false. This fixes a case where non-existent clusters could cause a route to no longer route to any of its backends, including existing ones. [[GH-21587](https://github.com/hashicorp/consul/issues/21587)] + +## 1.15.14 Enterprise (August 26, 2024) + +Enterprise LTS: Consul Enterprise 1.15 is a Long-Term Support (LTS) release. + +SECURITY: + +* ui: Upgrade modules with d3-color as a dependency to address denial of service issue in d3-color < 3.1.0 [[GH-21588](https://github.com/hashicorp/consul/issues/21588)] + +IMPROVEMENTS: + +* Use Envoy's default for a route's validate_clusters option, which is false. This fixes a case where non-existent clusters could cause a route to no longer route to any of its backends, including existing ones. [[GH-21587](https://github.com/hashicorp/consul/issues/21587)] + +## 1.19.1 (July 11, 2024) + +SECURITY: + +* Upgrade envoy module dependencies to version 1.27.7, 1.28.5 and 1.29.7 or higher to resolve [CVE-2024-39305](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-39305) [[GH-21524](https://github.com/hashicorp/consul/issues/21524)] +* Upgrade go version to 1.22.5 to address [CVE-2024-24791](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-24791) [[GH-21507](https://github.com/hashicorp/consul/issues/21507)] +* Upgrade go-retryablehttp to address [CVE-2024-6104](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-6104) [[GH-21384](https://github.com/hashicorp/consul/issues/21384)] +* agent: removed reflected cross-site scripting vulnerability [[GH-21342](https://github.com/hashicorp/consul/issues/21342)] +* ui: Pin and namespace sub-module dependencies related to the Consul UI [[GH-21378](https://github.com/hashicorp/consul/issues/21378)] + +IMPROVEMENTS: + +* mesh: update supported envoy version 1.29.5 in addition to 1.28.4, 1.27.6. [[GH-21277](https://github.com/hashicorp/consul/issues/21277)] + +BUG FIXES: + +* core: Fix multiple incorrect type conversion for potential overflows [[GH-21251](https://github.com/hashicorp/consul/issues/21251)] +* core: Fix panic runtime error on AliasCheck [[GH-21339](https://github.com/hashicorp/consul/issues/21339)] +* dns: Fix a regression where DNS SRV questions were returning duplicate hostnames instead of encoded IPs. + This affected Nomad integrations with Consul. [[GH-21361](https://github.com/hashicorp/consul/issues/21361)] +* dns: Fix a regression where DNS tags using the standard lookup syntax, `tag.name.service.consul`, were being disregarded. [[GH-21361](https://github.com/hashicorp/consul/issues/21361)] +* dns: Fixes a spam log message "Failed to parse TTL for prepared query..." + that was always being logged on each prepared query evaluation. [[GH-21381](https://github.com/hashicorp/consul/issues/21381)] +* terminating-gateway: **(Enterprise Only)** Fixed issue where enterprise metadata applied to linked services was the terminating-gateways enterprise metadata and not the linked services enterprise metadata. [[GH-21382](https://github.com/hashicorp/consul/issues/21382)] +* txn: Fix a bug where mismatched Consul server versions could result in undetected data loss for when using newer Transaction verbs. [[GH-21519](https://github.com/hashicorp/consul/issues/21519)] + +## 1.18.3 Enterprise (July 11, 2024) + +**Enterprise LTS**: Consul Enterprise 1.18 is a Long-Term Support (LTS) release. + +SECURITY: + +* Upgrade envoy module dependencies to version 1.27.7, 1.28.5 and 1.29.7 or higher to resolve [CVE-2024-39305](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-39305) [[GH-21524](https://github.com/hashicorp/consul/issues/21524)] +* Upgrade go version to 1.22.5 to address [CVE-2024-24791](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-24791) [[GH-21507](https://github.com/hashicorp/consul/issues/21507)] +* Upgrade go-retryablehttp to address [CVE-2024-6104](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-6104) [[GH-21384](https://github.com/hashicorp/consul/issues/21384)] +* agent: removed reflected cross-site scripting vulnerability [[GH-21342](https://github.com/hashicorp/consul/issues/21342)] +* ui: Pin and namespace sub-module dependencies related to the Consul UI [[GH-21378](https://github.com/hashicorp/consul/issues/21378)] + +IMPROVEMENTS: + +* mesh: update supported envoy version 1.29.4 +* mesh: update supported envoy version 1.29.5 in addition to 1.28.4, 1.27.6. [[GH-21277](https://github.com/hashicorp/consul/issues/21277)] +* upgrade go version to v1.22.3. [[GH-21113](https://github.com/hashicorp/consul/issues/21113)] +* upgrade go version to v1.22.4. [[GH-21265](https://github.com/hashicorp/consul/issues/21265)] + +BUG FIXES: + +* core: Fix multiple incorrect type conversion for potential overflows [[GH-21251](https://github.com/hashicorp/consul/issues/21251)] +* core: Fix panic runtime error on AliasCheck [[GH-21339](https://github.com/hashicorp/consul/issues/21339)] +* dns: Fix a regression where DNS SRV questions were returning duplicate hostnames instead of encoded IPs. + This affected Nomad integrations with Consul. [[GH-21361](https://github.com/hashicorp/consul/issues/21361)] +* dns: Fix a regression where DNS tags using the standard lookup syntax, `tag.name.service.consul`, were being disregarded. [[GH-21361](https://github.com/hashicorp/consul/issues/21361)] +* dns: Fixes a spam log message "Failed to parse TTL for prepared query..." + that was always being logged on each prepared query evaluation. [[GH-21381](https://github.com/hashicorp/consul/issues/21381)] +* terminating-gateway: **(Enterprise Only)** Fixed issue where enterprise metadata applied to linked services was the terminating-gateways enterprise metadata and not the linked services enterprise metadata. [[GH-21382](https://github.com/hashicorp/consul/issues/21382)] +* txn: Fix a bug where mismatched Consul server versions could result in undetected data loss for when using newer Transaction verbs. [[GH-21519](https://github.com/hashicorp/consul/issues/21519)] +* v2dns: Fix a regression where DNS SRV questions were returning duplicate hostnames instead of encoded IPs. + This affected Nomad integrations with Consul. [[GH-21361](https://github.com/hashicorp/consul/issues/21361)] +* v2dns: Fix a regression where DNS tags using the standard lookup syntax, `tag.name.service.consul`, were being disregarded. [[GH-21361](https://github.com/hashicorp/consul/issues/21361)] + +## 1.17.6 Enterprise (July 11, 2024) + +SECURITY: + +* Upgrade envoy module dependencies to version 1.27.7, 1.28.5 and 1.29.7 or higher to resolve [CVE-2024-39305](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-39305) [[GH-21524](https://github.com/hashicorp/consul/issues/21524)] +* Upgrade go version to 1.22.5 to address [CVE-2024-24791](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-24791) [[GH-21507](https://github.com/hashicorp/consul/issues/21507)] +* Upgrade go-retryablehttp to address [CVE-2024-6104](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-6104) [[GH-21384](https://github.com/hashicorp/consul/issues/21384)] +* agent: removed reflected cross-site scripting vulnerability [[GH-21342](https://github.com/hashicorp/consul/issues/21342)] +* ui: Pin and namespace sub-module dependencies related to the Consul UI [[GH-21378](https://github.com/hashicorp/consul/issues/21378)] + +IMPROVEMENTS: + +* upgrade go version to v1.22.3. [[GH-21113](https://github.com/hashicorp/consul/issues/21113)] +* upgrade go version to v1.22.4. [[GH-21265](https://github.com/hashicorp/consul/issues/21265)] + +BUG FIXES: + +* core: Fix panic runtime error on AliasCheck [[GH-21339](https://github.com/hashicorp/consul/issues/21339)] +* terminating-gateway: **(Enterprise Only)** Fixed issue where enterprise metadata applied to linked services was the terminating-gateways enterprise metadata and not the linked services enterprise metadata. [[GH-21382](https://github.com/hashicorp/consul/issues/21382)] +* txn: Fix a bug where mismatched Consul server versions could result in undetected data loss for when using newer Transaction verbs. [[GH-21519](https://github.com/hashicorp/consul/issues/21519)] + +## 1.15.13 Enterprise (July 11, 2024) + +**Enterprise LTS**: Consul Enterprise 1.15 is a Long-Term Support (LTS) release. + +SECURITY: + +* Upgrade envoy module dependencies to version 1.27.7, 1.28.5 and 1.29.7 or higher to resolve [CVE-2024-39305](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-39305) [[GH-21524](https://github.com/hashicorp/consul/issues/21524)] +* Upgrade go version to 1.22.5 to address [CVE-2024-24791](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-24791) [[GH-21507](https://github.com/hashicorp/consul/issues/21507)] +* Upgrade go-retryablehttp to address [CVE-2024-6104](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-6104) [[GH-21384](https://github.com/hashicorp/consul/issues/21384)] +* agent: removed reflected cross-site scripting vulnerability [[GH-21342](https://github.com/hashicorp/consul/issues/21342)] +* ui: Pin and namespace sub-module dependencies related to the Consul UI [[GH-21378](https://github.com/hashicorp/consul/issues/21378)] + +IMPROVEMENTS: + +* mesh: update supported envoy version 1.29.4 +* upgrade go version to v1.22.3. [[GH-21113](https://github.com/hashicorp/consul/issues/21113)] +* upgrade go version to v1.22.4. [[GH-21265](https://github.com/hashicorp/consul/issues/21265)] + +BUG FIXES: + +* core: Fix panic runtime error on AliasCheck [[GH-21339](https://github.com/hashicorp/consul/issues/21339)] +* terminating-gateway: **(Enterprise Only)** Fixed issue where enterprise metadata applied to linked services was the terminating-gateways enterprise metadata and not the linked services enterprise metadata. [[GH-21382](https://github.com/hashicorp/consul/issues/21382)] +* txn: Fix a bug where mismatched Consul server versions could result in undetected data loss for when using newer Transaction verbs. [[GH-21519](https://github.com/hashicorp/consul/issues/21519)] + +## 1.19.0 (June 12, 2024) + +BREAKING CHANGES: + +* telemetry: State store usage metrics with a double `consul` element in the metric name have been removed. Please use the same metric without the second `consul` instead. As an example instead of `consul.consul.state.config_entries` use `consul.state.config_entries` [[GH-20674](https://github.com/hashicorp/consul/issues/20674)] + +SECURITY: + +* Upgrade to support Envoy `1.27.5 and 1.28.3`. This resolves CVE +[CVE-2024-32475](https://nvd.nist.gov/vuln/detail/CVE-2024-32475) (`auto_sni`). [[GH-21017](https://github.com/hashicorp/consul/issues/21017)] +* Upgrade to support k8s.io/apimachinery `v0.18.7 or higher`. This resolves CVE +[CVE-2020-8559](https://nvd.nist.gov/vuln/detail/CVE-2020-8559). [[GH-21017](https://github.com/hashicorp/consul/issues/21017)] + +FEATURES: + +* dns: queries now default to a refactored DNS server that is v1 and v2 Catalog compatible. +Use `v1dns` in the `experiments` agent config to disable. +The legacy server will be removed in a future release of Consul. +See the [Consul 1.19.x Release Notes](https://developer.hashicorp.com/consul/docs/release-notes/consul/v1_19_x) for removed DNS features. [[GH-20715](https://github.com/hashicorp/consul/issues/20715)] +* gateways: api-gateway can leverage listener TLS certificates available on the gateway's local filesystem by specifying the public certificate and private key path in the new file-system-certificate configuration entry [[GH-20873](https://github.com/hashicorp/consul/issues/20873)] + +IMPROVEMENTS: + +* dns: new version was not supporting partition or namespace being set to 'default' in CE version. [[GH-21230](https://github.com/hashicorp/consul/issues/21230)] +* mesh: update supported envoy version 1.29.4 in addition to 1.28.3, 1.27.5, 1.26.8. [[GH-21142](https://github.com/hashicorp/consul/issues/21142)] +* upgrade go version to v1.22.4. [[GH-21265](https://github.com/hashicorp/consul/issues/21265)] +* Upgrade `github.com/envoyproxy/go-control-plane` to 0.12.0. [[GH-20973](https://github.com/hashicorp/consul/issues/20973)] +* dns: DNS-over-grpc when using `consul-dataplane` now accepts partition, namespace, token as metadata to default those query parameters. +`consul-dataplane` v1.5+ will send this information automatically. [[GH-20899](https://github.com/hashicorp/consul/issues/20899)] +* snapshot: Add `consul snapshot decode` CLI command to output a JSON object stream of all the snapshots data. [[GH-20824](https://github.com/hashicorp/consul/issues/20824)] +* telemetry: Add `telemetry.disable_per_tenancy_usage_metrics` in agent configuration to disable setting tenancy labels on usage metrics. This significantly decreases CPU utilization in clusters with many admin partitions or namespaces. +* telemetry: Improved the performance usage metrics emission by not outputting redundant metrics. [[GH-20674](https://github.com/hashicorp/consul/issues/20674)] + +DEPRECATIONS: + +* snapshot agent: **(Enterprise only)** Top level single snapshot destinations `local_storage`, `aws_storage`, `azure_blob_storage`, and `google_storage` in snapshot agent configuration files are now deprecated. Use the `backup_destinations` config object instead. + +BUG FIXES: + +* docs: Consul DNS Forwarding configuration for OpenShift update for [Resolve Consul DNS Requests in Kubernetes](https://developer.hashicorp.com/consul/docs/k8s/dns) [[GH-20439](https://github.com/hashicorp/consul/issues/20439)] +* hcp: fix error logs when failing to push metrics [[GH-20514](https://github.com/hashicorp/consul/issues/20514)] +* streaming: Handle ACL errors consistently when blocking query timeout is reached. [[GH-20876](https://github.com/hashicorp/consul/issues/20876)] + +## 1.18.2 (May 14, 2024) + +**Enterprise LTS**: Consul Enterprise 1.18 is a Long-Term Support (LTS) release. + +SECURITY: + +* Bump Dockerfile base image to `alpine:3.19`. [[GH-20897](https://github.com/hashicorp/consul/issues/20897)] +* Update `vault/api` to v1.12.2 to address [CVE-2024-28180](https://nvd.nist.gov/vuln/detail/CVE-2024-28180) + (removes indirect dependency on impacted `go-jose.v2`) [[GH-20910](https://github.com/hashicorp/consul/issues/20910)] +* Upgrade Go to use 1.21.10. This addresses CVEs + [CVE-2024-24787](https://nvd.nist.gov/vuln/detail/CVE-2024-24787) and + [CVE-2024-24788](https://nvd.nist.gov/vuln/detail/CVE-2024-24788) [[GH-21074](https://github.com/hashicorp/consul/issues/21074)] +* Upgrade to support Envoy `1.26.8, 1.27.4, 1.27.5, 1.28.2 and 1.28.3`. This resolves CVEs + [CVE-2024-27919](https://nvd.nist.gov/vuln/detail/CVE-2024-27919) (`http2`). [[GH-20956](https://github.com/hashicorp/consul/issues/20956)] and [CVE-2024-32475](https://nvd.nist.gov/vuln/detail/CVE-2024-32475) (`auto_sni`). [[GH-21030](https://github.com/hashicorp/consul/issues/21030)] +* Upgrade to support k8s.io/apimachinery `v0.18.7 or higher`. This resolves CVE + [CVE-2020-8559](https://nvd.nist.gov/vuln/detail/CVE-2020-8559). [[GH-21034](https://github.com/hashicorp/consul/issues/21034)] +* Upgrade to use Go `1.21.9`. This resolves CVE + [CVE-2023-45288](https://nvd.nist.gov/vuln/detail/CVE-2023-45288) (`http2`). [[GH-20956](https://github.com/hashicorp/consul/issues/20956)] +* Upgrade to use golang.org/x/net `v0.24.0`. This resolves CVE + [CVE-2023-45288](https://nvd.nist.gov/vuln/detail/CVE-2023-45288) (`x/net`). [[GH-20956](https://github.com/hashicorp/consul/issues/20956)] + +IMPROVEMENTS: + +* gateways: service defaults configuration entries can now be used to set default upstream limits for mesh-gateways [[GH-20945](https://github.com/hashicorp/consul/issues/20945)] +* connect: Add ability to disable Auto Host Header Rewrite on Terminating Gateway at the service level [[GH-20802](https://github.com/hashicorp/consul/issues/20802)] + +BUG FIXES: + +* dns: fix a bug with sameness group queries in DNS where responses did not respect [`DefaultForFailover`](/consul/docs/connect/config-entries/sameness-group#defaultforfailover). + DNS requests against sameness groups without this field set will now error as intended. +* error running consul server in 1.18.0: failed to configure SCADA provider user's home directory path: $HOME is not defined [[GH-20926](https://github.com/hashicorp/consul/issues/20926)] +* server: fix Ent snapshot restore on CE when CE downgrade is enabled [[GH-20977](https://github.com/hashicorp/consul/issues/20977)] +* xds: Make TCP external service registered with terminating gateway reachable from peered cluster [[GH-19881](https://github.com/hashicorp/consul/issues/19881)] + +## 1.17.5 Enterprise (May 14, 2024) + +SECURITY: + +* Bump Dockerfile base image to `alpine:3.19`. [[GH-20897](https://github.com/hashicorp/consul/issues/20897)] +* Update `vault/api` to v1.12.2 to address [CVE-2024-28180](https://nvd.nist.gov/vuln/detail/CVE-2024-28180) + (removes indirect dependency on impacted `go-jose.v2`) [[GH-20910](https://github.com/hashicorp/consul/issues/20910)] +* Upgrade Go to use 1.21.10. This addresses CVEs + [CVE-2024-24787](https://nvd.nist.gov/vuln/detail/CVE-2024-24787) and + [CVE-2024-24788](https://nvd.nist.gov/vuln/detail/CVE-2024-24788) [[GH-21074](https://github.com/hashicorp/consul/issues/21074)] +* Upgrade to support Envoy `1.26.8, 1.27.4, 1.27.5, 1.28.2 and 1.28.3`. This resolves CVEs + [CVE-2024-27919](https://nvd.nist.gov/vuln/detail/CVE-2024-27919) (`http2`). [[GH-20956](https://github.com/hashicorp/consul/issues/20956)] and [CVE-2024-32475](https://nvd.nist.gov/vuln/detail/CVE-2024-32475) (`auto_sni`). [[GH-21030](https://github.com/hashicorp/consul/issues/21030)] +* Upgrade to support k8s.io/apimachinery `v0.18.7 or higher`. This resolves CVE + [CVE-2020-8559](https://nvd.nist.gov/vuln/detail/CVE-2020-8559). [[GH-21033](https://github.com/hashicorp/consul/issues/21033)] +* Upgrade to use Go `1.21.9`. This resolves CVE + [CVE-2023-45288](https://nvd.nist.gov/vuln/detail/CVE-2023-45288) (`http2`). [[GH-20956](https://github.com/hashicorp/consul/issues/20956)] +* Upgrade to use golang.org/x/net `v0.24.0`. This resolves CVE + [CVE-2023-45288](https://nvd.nist.gov/vuln/detail/CVE-2023-45288) (`x/net`). [[GH-20956](https://github.com/hashicorp/consul/issues/20956)] +* security: Remove `coredns/coredns` dependency to address [CVE-2024-0874](https://nvd.nist.gov/vuln/detail/CVE-2024-0874) [[GH-9243](https://github.com/hashicorp/consul/issues/9243)] + +BUG FIXES: + +* dns: fix a bug with sameness group queries in DNS where responses did not respect [`DefaultForFailover`](/consul/docs/connect/config-entries/sameness-group#defaultforfailover). + DNS requests against sameness groups without this field set will now error as intended. +* xds: Make TCP external service registered with terminating gateway reachable from peered cluster [[GH-19881](https://github.com/hashicorp/consul/issues/19881)] + +## 1.16.8 Enterprise (May 14, 2024) + +SECURITY: + +* Bump Dockerfile base image to `alpine:3.19`. [[GH-20897](https://github.com/hashicorp/consul/issues/20897)] +* Update `vault/api` to v1.12.2 to address [CVE-2024-28180](https://nvd.nist.gov/vuln/detail/CVE-2024-28180) + (removes indirect dependency on impacted `go-jose.v2`) [[GH-20910](https://github.com/hashicorp/consul/issues/20910)] +* Upgrade Go to use 1.21.10. This addresses CVEs + [CVE-2024-24787](https://nvd.nist.gov/vuln/detail/CVE-2024-24787) and + [CVE-2024-24788](https://nvd.nist.gov/vuln/detail/CVE-2024-24788) [[GH-21074](https://github.com/hashicorp/consul/issues/21074)] +* Upgrade to support Envoy `1.26.8, 1.27.4, 1.27.5, 1.28.2 and 1.28.3`. This resolves CVEs + [CVE-2024-27919](https://nvd.nist.gov/vuln/detail/CVE-2024-27919) (`http2`). [[GH-20956](https://github.com/hashicorp/consul/issues/20956)] and [CVE-2024-32475](https://nvd.nist.gov/vuln/detail/CVE-2024-32475) (`auto_sni`). [[GH-21030](https://github.com/hashicorp/consul/issues/21030)] +* Upgrade to support k8s.io/apimachinery `v0.18.7 or higher`. This resolves CVE + [CVE-2020-8559](https://nvd.nist.gov/vuln/detail/CVE-2020-8559). [[GH-21032](https://github.com/hashicorp/consul/issues/21032)] +* Upgrade to use Go `1.21.9`. This resolves CVE + [CVE-2023-45288](https://nvd.nist.gov/vuln/detail/CVE-2023-45288) (`http2`). [[GH-20956](https://github.com/hashicorp/consul/issues/20956)] +* Upgrade to use golang.org/x/net `v0.24.0`. This resolves CVE + [CVE-2023-45288](https://nvd.nist.gov/vuln/detail/CVE-2023-45288) (`x/net`). [[GH-20956](https://github.com/hashicorp/consul/issues/20956)] +* security: Remove `coredns/coredns` dependency to address [CVE-2024-0874](https://nvd.nist.gov/vuln/detail/CVE-2024-0874) [[GH-9244](https://github.com/hashicorp/consul/issues/9244)] + +BUG FIXES: + +* dns: fix a bug with sameness group queries in DNS where responses did not respect [`DefaultForFailover`](/consul/docs/connect/config-entries/sameness-group#defaultforfailover). + DNS requests against sameness groups without this field set will now error as intended. +* xds: Make TCP external service registered with terminating gateway reachable from peered cluster [[GH-19881](https://github.com/hashicorp/consul/issues/19881)] + +## 1.15.12 Enterprise (May 14, 2024) + +**Enterprise LTS**: Consul Enterprise 1.15 is a Long-Term Support (LTS) release. + +SECURITY: + +* Bump Dockerfile base image to `alpine:3.19`. [[GH-20897](https://github.com/hashicorp/consul/issues/20897)] +* Update `vault/api` to v1.12.2 to address [CVE-2024-28180](https://nvd.nist.gov/vuln/detail/CVE-2024-28180) + (removes indirect dependency on impacted `go-jose.v2`) [[GH-20910](https://github.com/hashicorp/consul/issues/20910)] +* Upgrade Go to use 1.21.10. This addresses CVEs + [CVE-2024-24787](https://nvd.nist.gov/vuln/detail/CVE-2024-24787) and + [CVE-2024-24788](https://nvd.nist.gov/vuln/detail/CVE-2024-24788) [[GH-21074](https://github.com/hashicorp/consul/issues/21074)] +* Upgrade to support Envoy `1.26.8, 1.27.4, 1.27.5, 1.28.2 and 1.28.3`. This resolves CVEs + [CVE-2024-27919](https://nvd.nist.gov/vuln/detail/CVE-2024-27919) (`http2`). [[GH-20956](https://github.com/hashicorp/consul/issues/20956)] and [CVE-2024-32475](https://nvd.nist.gov/vuln/detail/CVE-2024-32475) (`auto_sni`). [[GH-21030](https://github.com/hashicorp/consul/issues/21030)] +* Upgrade to support k8s.io/apimachinery `v0.18.7 or higher`. This resolves CVE + [CVE-2020-8559](https://nvd.nist.gov/vuln/detail/CVE-2020-8559). [[GH-21030](https://github.com/hashicorp/consul/issues/21030)] +* Upgrade to use Go `1.21.9`. This resolves CVE + [CVE-2023-45288](https://nvd.nist.gov/vuln/detail/CVE-2023-45288) (`http2`). [[GH-20956](https://github.com/hashicorp/consul/issues/20956)] +* Upgrade to use golang.org/x/net `v0.24.0`. This resolves CVE + [CVE-2023-45288](https://nvd.nist.gov/vuln/detail/CVE-2023-45288) (`x/net`). [[GH-20956](https://github.com/hashicorp/consul/issues/20956)] +* security: Remove `coredns/coredns` dependency to address [CVE-2024-0874](https://nvd.nist.gov/vuln/detail/CVE-2024-0874) [[GH-9245](https://github.com/hashicorp/consul/issues/9245)] + +BUG FIXES: + +* xds: Make TCP external service registered with terminating gateway reachable from peered cluster [[GH-19881](https://github.com/hashicorp/consul/issues/19881)] + +## 1.18.1 (March 26, 2024) + +Enterprise LTS: Consul Enterprise 1.18 is a Long-Term Support (LTS) release. + +BREAKING CHANGES: + +* ui: Adds a "Link to HCP Consul Central" modal with integration to side-nav and link to HCP banner. There will be an option to disable the Link to HCP banner from the UI in a follow-up release. [[GH-20474](https://github.com/hashicorp/consul/issues/20474)] + +SECURITY: + +* Update `google.golang.org/protobuf` to v1.33.0 to address [CVE-2024-24786](https://nvd.nist.gov/vuln/detail/CVE-2024-24786). [[GH-20801](https://github.com/hashicorp/consul/issues/20801)] +* Update the Consul Build Go base image to `alpine3.19`. This resolves CVEs + [CVE-2023-52425](https://nvd.nist.gov/vuln/detail/CVE-2023-52425) + [CVE-2023-52426](https://nvd.nist.gov/vuln/detail/CVE-2023-52426) [[GH-20812](https://github.com/hashicorp/consul/issues/20812)] +* Upgrade to use Go `1.21.8`. This resolves CVEs + [CVE-2024-24783](https://nvd.nist.gov/vuln/detail/CVE-2024-24783) (`crypto/x509`). + [CVE-2023-45290](https://nvd.nist.gov/vuln/detail/CVE-2023-45290) (`net/http`). + [CVE-2023-45289](https://nvd.nist.gov/vuln/detail/CVE-2023-45289) (`net/http`, `net/http/cookiejar`). + [CVE-2024-24785](https://nvd.nist.gov/vuln/detail/CVE-2024-24785) (`html/template`). + [CVE-2024-24784](https://nvd.nist.gov/vuln/detail/CVE-2024-24784) (`net/mail`). [[GH-20812](https://github.com/hashicorp/consul/issues/20812)] + +IMPROVEMENTS: + +* api: Randomize the returned server list for the WatchServers gRPC endpoint. [[GH-20866](https://github.com/hashicorp/consul/issues/20866)] +* partitions: **(Enterprise only)** Allow disabling of Gossip per Partition [[GH-20669](https://github.com/hashicorp/consul/issues/20669)] +* snapshot agent: **(Enterprise only)** Add support for multiple snapshot destinations using the `backup_destinations` config file object. +* xds: Improved the performance of xDS server side load balancing. Its slightly improved in Consul CE with drastic CPU usage reductions in Consul Enterprise. [[GH-20672](https://github.com/hashicorp/consul/issues/20672)] + +BUG FIXES: + +* audit-logs: **(Enterprise Only)** Fixes non ASCII characters in audit logs because of gzip. [[GH-20345](https://github.com/hashicorp/consul/issues/20345)] +* connect: Fix issue where Consul-dataplane xDS sessions would not utilize the streaming backend for wan-federated queries. [[GH-20868](https://github.com/hashicorp/consul/issues/20868)] +* connect: Fix potential goroutine leak in xDS stream handling. [[GH-20866](https://github.com/hashicorp/consul/issues/20866)] +* connect: Fix xDS deadlock that could result in proxies being unable to start. [[GH-20867](https://github.com/hashicorp/consul/issues/20867)] +* ingress-gateway: **(Enterprise Only)** Fix a bug where on update, Ingress Gateways lost all upstreams for listeners with wildcard services in a different namespace. + +## 1.17.4 Enterprise (March 26, 2024) + +SECURITY: + +* Update `google.golang.org/protobuf` to v1.33.0 to address [CVE-2024-24786](https://nvd.nist.gov/vuln/detail/CVE-2024-24786). [[GH-20801](https://github.com/hashicorp/consul/issues/20801)] +* Update the Consul Build Go base image to `alpine3.19`. This resolves CVEs + [CVE-2023-52425](https://nvd.nist.gov/vuln/detail/CVE-2023-52425) + [CVE-2023-52426](https://nvd.nist.gov/vuln/detail/CVE-2023-52426) [[GH-20812](https://github.com/hashicorp/consul/issues/20812)] +* Upgrade to use Go `1.21.8`. This resolves CVEs + [CVE-2024-24783](https://nvd.nist.gov/vuln/detail/CVE-2024-24783) (`crypto/x509`). + [CVE-2023-45290](https://nvd.nist.gov/vuln/detail/CVE-2023-45290) (`net/http`). + [CVE-2023-45289](https://nvd.nist.gov/vuln/detail/CVE-2023-45289) (`net/http`, `net/http/cookiejar`). + [CVE-2024-24785](https://nvd.nist.gov/vuln/detail/CVE-2024-24785) (`html/template`). + [CVE-2024-24784](https://nvd.nist.gov/vuln/detail/CVE-2024-24784) (`net/mail`). [[GH-20812](https://github.com/hashicorp/consul/issues/20812)] + +IMPROVEMENTS: + +* api: Randomize the returned server list for the WatchServers gRPC endpoint. [[GH-20866](https://github.com/hashicorp/consul/issues/20866)] +* snapshot agent: **(Enterprise only)** Add support for multiple snapshot destinations using the `backup_destinations` config file object. + +BUG FIXES: + +* connect: Fix issue where Consul-dataplane xDS sessions would not utilize the streaming backend for wan-federated queries. [[GH-20868](https://github.com/hashicorp/consul/issues/20868)] +* connect: Fix potential goroutine leak in xDS stream handling. [[GH-20866](https://github.com/hashicorp/consul/issues/20866)] +* connect: Fix xDS deadlock that could result in proxies being unable to start. [[GH-20867](https://github.com/hashicorp/consul/issues/20867)] +* dns: SERVFAIL when resolving not found PTR records. [[GH-20679](https://github.com/hashicorp/consul/issues/20679)] +* ingress-gateway: **(Enterprise Only)** Fix a bug where on update, Ingress Gateways lost all upstreams for listeners with wildcard services in a different namespace. +* snapshot-agent: **(Enterprise only)** Fix a bug with static AWS credentials where one of the key id or secret key is provided via config file and the other is provided via an environment variable. + +## 1.16.7 Enterprise (March 26, 2024) + +SECURITY: + +* Update `google.golang.org/protobuf` to v1.33.0 to address [CVE-2024-24786](https://nvd.nist.gov/vuln/detail/CVE-2024-24786). [[GH-20801](https://github.com/hashicorp/consul/issues/20801)] +* Update the Consul Build Go base image to `alpine3.19`. This resolves CVEs + [CVE-2023-52425](https://nvd.nist.gov/vuln/detail/CVE-2023-52425) + [CVE-2023-52426](https://nvd.nist.gov/vuln/detail/CVE-2023-52426) [[GH-20812](https://github.com/hashicorp/consul/issues/20812)] +* Upgrade to use Go `1.21.8`. This resolves CVEs + [CVE-2024-24783](https://nvd.nist.gov/vuln/detail/CVE-2024-24783) (`crypto/x509`). + [CVE-2023-45290](https://nvd.nist.gov/vuln/detail/CVE-2023-45290) (`net/http`). + [CVE-2023-45289](https://nvd.nist.gov/vuln/detail/CVE-2023-45289) (`net/http`, `net/http/cookiejar`). + [CVE-2024-24785](https://nvd.nist.gov/vuln/detail/CVE-2024-24785) (`html/template`). + [CVE-2024-24784](https://nvd.nist.gov/vuln/detail/CVE-2024-24784) (`net/mail`). [[GH-20812](https://github.com/hashicorp/consul/issues/20812)] + +IMPROVEMENTS: + +* api: Randomize the returned server list for the WatchServers gRPC endpoint. [[GH-20866](https://github.com/hashicorp/consul/issues/20866)] +* snapshot agent: **(Enterprise only)** Add support for multiple snapshot destinations using the `backup_destinations` config file object. + +BUG FIXES: + +* connect: Fix issue where Consul-dataplane xDS sessions would not utilize the streaming backend for wan-federated queries. [[GH-20868](https://github.com/hashicorp/consul/issues/20868)] +* connect: Fix potential goroutine leak in xDS stream handling. [[GH-20866](https://github.com/hashicorp/consul/issues/20866)] +* connect: Fix xDS deadlock that could result in proxies being unable to start. [[GH-20867](https://github.com/hashicorp/consul/issues/20867)] +* ingress-gateway: **(Enterprise Only)** Fix a bug where on update, Ingress Gateways lost all upstreams for listeners with wildcard services in a different namespace. +* snapshot-agent: **(Enterprise only)** Fix a bug with static AWS credentials where one of the key id or secret key is provided via config file and the other is provided via an environment variable. + +## 1.15.11 Enterprise (March 26, 2024) + +**Enterprise LTS**: Consul Enterprise 1.15 is a Long-Term Support (LTS) release. + +SECURITY: + +* Update `google.golang.org/protobuf` to v1.33.0 to address [CVE-2024-24786](https://nvd.nist.gov/vuln/detail/CVE-2024-24786). [[GH-20801](https://github.com/hashicorp/consul/issues/20801)] + +IMPROVEMENTS: + +* api: Randomize the returned server list for the WatchServers gRPC endpoint. [[GH-20866](https://github.com/hashicorp/consul/issues/20866)] + +BUG FIXES: + +* connect: Fix issue where Consul-dataplane xDS sessions would not utilize the streaming backend for wan-federated queries. [[GH-20868](https://github.com/hashicorp/consul/issues/20868)] +* connect: Fix potential goroutine leak in xDS stream handling. [[GH-20866](https://github.com/hashicorp/consul/issues/20866)] +* connect: Fix xDS deadlock that could result in proxies being unable to start. [[GH-20867](https://github.com/hashicorp/consul/issues/20867)] +* ingress-gateway: **(Enterprise Only)** Fix a bug where on update, Ingress Gateways lost all upstreams for listeners with wildcard services in a different namespace. +* snapshot-agent: **(Enterprise only)** Fix a bug with static AWS credentials where one of the key id or secret key is provided via config file and the other is provided via an environment variable. + +## 1.18.0 (February 27, 2024) + +BREAKING CHANGES: + +* config-entries: Allow disabling request and idle timeouts with negative values in service router and service resolver config entries. [[GH-19992](https://github.com/hashicorp/consul/issues/19992)] +* telemetry: Adds fix to always use the value of `telemetry.disable_hostname` when determining whether to prefix gauge-type metrics with the hostname of the Consul agent. Previously, if only the default metric sink was enabled, this configuration was ignored and always treated as `true`, even though its default value is `false`. [[GH-20312](https://github.com/hashicorp/consul/issues/20312)] + +SECURITY: + +* Update `golang.org/x/crypto` to v0.17.0 to address [CVE-2023-48795](https://nvd.nist.gov/vuln/detail/CVE-2023-48795). [[GH-20023](https://github.com/hashicorp/consul/issues/20023)] +* connect: Update supported envoy versions to 1.24.12, 1.25.11, 1.26.6, 1.27.2 to address [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) [[GH-19306](https://github.com/hashicorp/consul/issues/19306)] +* mesh: Update Envoy versions to 1.28.1, 1.27.3, and 1.26.7 to address [CVE-2024-23324](https://github.com/envoyproxy/envoy/security/advisories/GHSA-gq3v-vvhj-96j6), [CVE-2024-23325](https://github.com/envoyproxy/envoy/security/advisories/GHSA-5m7c-mrwr-pm26), [CVE-2024-23322](https://github.com/envoyproxy/envoy/security/advisories/GHSA-6p83-mfmh-qv38), [CVE-2024-23323](https://github.com/envoyproxy/envoy/security/advisories/GHSA-x278-4w4x-r7ch), [CVE-2024-23327](https://github.com/envoyproxy/envoy/security/advisories/GHSA-4h5x-x9vh-m29j), [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76), [GH-20589](https://github.com/hashicorp/consul/issues/20589)], [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76), and [[GH-19879](https://github.com/hashicorp/consul/issues/19879)] + +FEATURES: + +* acl: add policy bindtype to binding rules. [[GH-19499](https://github.com/hashicorp/consul/issues/19499)] +* agent: Introduces a new agent config default_intention_policy to decouple the default intention behavior from ACLs [[GH-20544](https://github.com/hashicorp/consul/issues/20544)] +* agent: **(Enterprise Only)** Add fault injection filter support for Consul Service Mesh +* cloud: Adds new API/CLI to initiate and manage linking a Consul cluster to HCP Consul Central [[GH-20312](https://github.com/hashicorp/consul/issues/20312)] +* dns: adds experimental support for a refactored DNS server that is v1 and v2 Catalog compatible. + Use `v2dns` in the `experiments` agent config to enable. + It will automatically be enabled when using the `resource-apis` (Catalog v2) experiment. + The new DNS implementation will be the default in Consul 1.19. + See the [Consul 1.18.x Release Notes](https://developer.hashicorp.com/consul/docs/release-notes/consul/v1_18_x) for deprecated DNS features. [[GH-20643](https://github.com/hashicorp/consul/issues/20643)] +* ui: Added a banner to let users link their clusters to HCP [[GH-20275](https://github.com/hashicorp/consul/issues/20275)] +* ui: Adds a redirect and warning message around unavailable UI with V2 enabled [[GH-20359](https://github.com/hashicorp/consul/issues/20359)] +* ui: adds V2CatalogEnabled to config that is passed to the ui [[GH-20353](https://github.com/hashicorp/consul/issues/20353)] +* v2: prevent use of the v2 experiments in secondary datacenters for now [[GH-20299](https://github.com/hashicorp/consul/issues/20299)] + +IMPROVEMENTS: + +* cloud: unconditionally add Access-Control-Expose-Headers HTTP header [[GH-20220](https://github.com/hashicorp/consul/issues/20220)] +* connect: Replace usage of deprecated Envoy field `envoy.config.core.v3.HeaderValueOption.append`. [[GH-20078](https://github.com/hashicorp/consul/issues/20078)] +* connect: Replace usage of deprecated Envoy fields `envoy.config.route.v3.HeaderMatcher.safe_regex_match` and `envoy.type.matcher.v3.RegexMatcher.google_re2`. [[GH-20013](https://github.com/hashicorp/consul/issues/20013)] +* docs: add Link API documentation [[GH-20308](https://github.com/hashicorp/consul/issues/20308)] +* resource: lowercase names enforced for v2 resources only. [[GH-19218](https://github.com/hashicorp/consul/issues/19218)] + +BUG FIXES: + +* dns: SERVFAIL when resolving not found PTR records. [[GH-20679](https://github.com/hashicorp/consul/issues/20679)] +* raft: Fix panic during downgrade from enterprise to oss. [[GH-19311](https://github.com/hashicorp/consul/issues/19311)] +* server: Ensure controllers are automatically restarted on internal stream errors. [[GH-20642](https://github.com/hashicorp/consul/issues/20642)] +* server: Ensure internal streams are properly terminated on snapshot restore. [[GH-20642](https://github.com/hashicorp/consul/issues/20642)] +* snapshot-agent: **(Enterprise only)** Fix a bug with static AWS credentials where one of the key id or secret key is provided via config file and the other is provided via an environment variable. + + +## 1.17.3 (February 13, 2024) + +SECURITY: + +* mesh: Update Envoy versions to 1.27.3 and 1.26.7 to address [CVE-2024-23324](https://github.com/envoyproxy/envoy/security/advisories/GHSA-gq3v-vvhj-96j6), [CVE-2024-23325](https://github.com/envoyproxy/envoy/security/advisories/GHSA-5m7c-mrwr-pm26), [CVE-2024-23322](https://github.com/envoyproxy/envoy/security/advisories/GHSA-6p83-mfmh-qv38), [CVE-2024-23323](https://github.com/envoyproxy/envoy/security/advisories/GHSA-x278-4w4x-r7ch), [CVE-2024-23327](https://github.com/envoyproxy/envoy/security/advisories/GHSA-4h5x-x9vh-m29j), and [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) [[GH-20587](https://github.com/hashicorp/consul/issues/20587)] + +FEATURES: + +* cli: Adds new command `exported-services` to list all services exported and their consumers. Refer to the [CLI docs](https://developer.hashicorp.com/consul/commands/exported-services) for more information. [[GH-20331](https://github.com/hashicorp/consul/issues/20331)] + +IMPROVEMENTS: + +* ProxyCfg: avoid setting a watch on `Internal.ServiceDump` when mesh gateway is not used. [[GH-20168](https://github.com/hashicorp/consul/issues/20168)] +* ProxyCfg: only return the nodes list when querying the `Internal.ServiceDump` watch from proxycfg [[GH-20168](https://github.com/hashicorp/consul/issues/20168)] +* Upgrade to use Go 1.21.7. [[GH-20545](https://github.com/hashicorp/consul/issues/20545)] +* api: add a new api(/v1/exported-services) to list all the exported service and their consumers. [[GH-20015](https://github.com/hashicorp/consul/issues/20015)] +* connect: Add `CaseInsensitive` flag to service-routers that allows paths and path prefixes to ignore URL upper and lower casing. [[GH-19647](https://github.com/hashicorp/consul/issues/19647)] + +BUG FIXES: + +* audit-logs: **(Enterprise Only)** Fixes non ASCII characters in audit logs because of gzip. [[GH-20345](https://github.com/hashicorp/consul/issues/20345)] +* connect: Fix issue where re-persisting existing proxy-defaults using `http` protocol fails with a protocol-mismatch error. [[GH-20481](https://github.com/hashicorp/consul/issues/20481)] +* connect: Fix regression with SAN matching on terminating gateways [GH-20360](https://github.com/hashicorp/consul/issues/20360) [[GH-20417](https://github.com/hashicorp/consul/issues/20417)] +* connect: Remove code coupling where the xDS capacity controller could negatively affect raft autopilot performance. [[GH-20511](https://github.com/hashicorp/consul/issues/20511)] +* logging: add /api prefix to v2 resource endpoint logs [[GH-20352](https://github.com/hashicorp/consul/issues/20352)] +* mesh: Fix bug where envoy extensions could not be configured with "permissive" mTLS mode. Note that envoy extensions currently do not apply to non-mTLS traffic in permissive mode. [[GH-20406](https://github.com/hashicorp/consul/issues/20406)] + +## 1.16.6 (February 13, 2024) + +SECURITY: + +* mesh: Update Envoy version to 1.26.7 to address [CVE-2024-23324](https://github.com/envoyproxy/envoy/security/advisories/GHSA-gq3v-vvhj-96j6), [CVE-2024-23325](https://github.com/envoyproxy/envoy/security/advisories/GHSA-5m7c-mrwr-pm26), [CVE-2024-23322](https://github.com/envoyproxy/envoy/security/advisories/GHSA-6p83-mfmh-qv38), [CVE-2024-23323](https://github.com/envoyproxy/envoy/security/advisories/GHSA-x278-4w4x-r7ch), [CVE-2024-23327](https://github.com/envoyproxy/envoy/security/advisories/GHSA-4h5x-x9vh-m29j), and [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) [[GH-20586](https://github.com/hashicorp/consul/issues/20586)] + +IMPROVEMENTS: + +* ProxyCfg: avoid setting a watch on `Internal.ServiceDump` when mesh gateway is not used. [[GH-20168](https://github.com/hashicorp/consul/issues/20168)] +* ProxyCfg: only return the nodes list when querying the `Internal.ServiceDump` watch from proxycfg [[GH-20168](https://github.com/hashicorp/consul/issues/20168)] +* Upgrade to use Go 1.21.7. [[GH-20545](https://github.com/hashicorp/consul/issues/20545)] + +BUG FIXES: + +* audit-logs: **(Enterprise Only)** Fixes non ASCII characters in audit logs because of gzip. [[GH-20345](https://github.com/hashicorp/consul/issues/20345)] +* connect: Fix issue where re-persisting existing proxy-defaults using `http` protocol fails with a protocol-mismatch error. [[GH-20481](https://github.com/hashicorp/consul/issues/20481)] +* connect: Fix regression with SAN matching on terminating gateways [GH-20360](https://github.com/hashicorp/consul/issues/20360) [[GH-20417](https://github.com/hashicorp/consul/issues/20417)] +* connect: Remove code coupling where the xDS capacity controller could negatively affect raft autopilot performance. [[GH-20511](https://github.com/hashicorp/consul/issues/20511)] +* mesh: Fix bug where envoy extensions could not be configured with "permissive" mTLS mode. Note that envoy extensions currently do not apply to non-mTLS traffic in permissive mode. [[GH-20406](https://github.com/hashicorp/consul/issues/20406)] + +## 1.15.10 (February 13, 2024) + +SECURITY: + +* mesh: Update Envoy versions to 1.28.1, 1.27.3, and 1.26.7 to address [CVE-2024-23324](https://github.com/envoyproxy/envoy/security/advisories/GHSA-gq3v-vvhj-96j6), [CVE-2024-23325](https://github.com/envoyproxy/envoy/security/advisories/GHSA-5m7c-mrwr-pm26), [CVE-2024-23322](https://github.com/envoyproxy/envoy/security/advisories/GHSA-6p83-mfmh-qv38), [CVE-2024-23323](https://github.com/envoyproxy/envoy/security/advisories/GHSA-x278-4w4x-r7ch), [CVE-2024-23327](https://github.com/envoyproxy/envoy/security/advisories/GHSA-4h5x-x9vh-m29j), and [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) [[GH-20590](https://github.com/hashicorp/consul/issues/20590)] + +IMPROVEMENTS: + +* ProxyCfg: avoid setting a watch on `Internal.ServiceDump` when mesh gateway is not used. [[GH-20168](https://github.com/hashicorp/consul/issues/20168)] +* ProxyCfg: only return the nodes list when querying the `Internal.ServiceDump` watch from proxycfg [[GH-20168](https://github.com/hashicorp/consul/issues/20168)] +* Upgrade to use Go 1.21.7. [[GH-20545](https://github.com/hashicorp/consul/issues/20545)] +* mesh: update supported envoy version 1.28.0 in addition to 1.27.2, 1.26.6 to support LTS release [[GH-20323](https://github.com/hashicorp/consul/issues/20323)] + +BUG FIXES: + +* audit-logs: **(Enterprise Only)** Fixes non ASCII characters in audit logs because of gzip. [[GH-20345](https://github.com/hashicorp/consul/issues/20345)] +* connect: Fix issue where re-persisting existing proxy-defaults using `http` protocol fails with a protocol-mismatch error. [[GH-20481](https://github.com/hashicorp/consul/issues/20481)] +* connect: Remove code coupling where the xDS capacity controller could negatively affect raft autopilot performance. [[GH-20511](https://github.com/hashicorp/consul/issues/20511)] + +## 1.17.2 (January 23, 2024) + +KNOWN ISSUES: + +* connect: Consul versions 1.17.2 and 1.16.5 perform excessively strict TLS SAN verification on terminating gateways, which prevents connections outside of the mesh to upstream services. Terminating gateway users are advised to avoid deploying these Consul versions. A fix will be present in a future release of Consul 1.17.3 and 1.16.6. [[GH-20360](https://github.com/hashicorp/consul/issues/20360)] + +SECURITY: + +* Upgrade OpenShift container images to use `ubi9-minimal:9.3` as the base image. [[GH-20014](https://github.com/hashicorp/consul/issues/20014)] + +IMPROVEMENTS: + +* connect: Remove usage of deprecated Envoy field `match_subject_alt_names` in favor of `match_typed_subject_alt_names`. [[GH-19954](https://github.com/hashicorp/consul/issues/19954)] +* connect: replace usage of deprecated Envoy field `envoy.config.router.v3.WeightedCluster.total_weight`. [[GH-20011](https://github.com/hashicorp/consul/issues/20011)] +* xds: Replace usage of deprecated Envoy field `envoy.config.cluster.v3.Cluster.http_protocol_options` [[GH-20010](https://github.com/hashicorp/consul/issues/20010)] +* xds: remove usages of deprecated Envoy fields: `envoy.config.cluster.v3.Cluster.http2_protocol_options`, `envoy.config.bootstrap.v3.Admin.access_log_path` [[GH-19940](https://github.com/hashicorp/consul/issues/19940)] +* xds: replace usage of deprecated Envoy field `envoy.extensions.filters.http.lua.v3.Lua.inline_code` [[GH-20012](https://github.com/hashicorp/consul/issues/20012)] + +DEPRECATIONS: + +* cli: Deprecate the `-admin-access-log-path` flag from `consul connect envoy` command in favor of: `-admin-access-log-config`. [[GH-19943](https://github.com/hashicorp/consul/issues/19943)] + +BUG FIXES: + +* prepared-query: (Enterprise-only) Fix issue where sameness-group failover targets to peers would attempt to query data from the default partition, rather than the sameness-group's partition always. +* ui: update token list on Role details page to show only linked tokens [[GH-19912](https://github.com/hashicorp/consul/issues/19912)] + +## 1.16.5 (January 23, 2024) + +KNOWN ISSUES: + +* connect: Consul versions 1.17.2 and 1.16.5 perform excessively strict TLS SAN verification on terminating gateways, which prevents connections outside of the mesh to upstream services. Terminating gateway users are advised to avoid deploying these Consul versions. A fix will be present in a future release of Consul 1.17.3 and 1.16.6 [[GH-20360](https://github.com/hashicorp/consul/issues/20360)]. + +SECURITY: + +* Update RSA key generation to use a key size of at least 2048 bits. [[GH-20112](https://github.com/hashicorp/consul/issues/20112)] +* Upgrade OpenShift container images to use `ubi9-minimal:9.3` as the base image. [[GH-20014](https://github.com/hashicorp/consul/issues/20014)] + +IMPROVEMENTS: + +* Upgrade to use Go 1.21.6. [[GH-20062](https://github.com/hashicorp/consul/issues/20062)] +* connect: Remove usage of deprecated Envoy field `match_subject_alt_names` in favor of `match_typed_subject_alt_names`. [[GH-19954](https://github.com/hashicorp/consul/issues/19954)] +* connect: replace usage of deprecated Envoy field `envoy.config.router.v3.WeightedCluster.total_weight`. [[GH-20011](https://github.com/hashicorp/consul/issues/20011)] +* xds: Replace usage of deprecated Envoy field `envoy.config.cluster.v3.Cluster.http_protocol_options` [[GH-20010](https://github.com/hashicorp/consul/issues/20010)] +* xds: remove usages of deprecated Envoy fields: `envoy.config.cluster.v3.Cluster.http2_protocol_options`, `envoy.config.bootstrap.v3.Admin.access_log_path` [[GH-19940](https://github.com/hashicorp/consul/issues/19940)] +* xds: replace usage of deprecated Envoy field `envoy.extensions.filters.http.lua.v3.Lua.inline_code` [[GH-20012](https://github.com/hashicorp/consul/issues/20012)] + +BUG FIXES: + +* prepared-query: (Enterprise-only) Fix issue where sameness-group failover targets to peers would attempt to query data from the default partition, rather than the sameness-group's partition always. +* ui: update token list on Role details page to show only linked tokens [[GH-19912](https://github.com/hashicorp/consul/issues/19912)] + +## 1.15.9 (January 23, 2024) + +SECURITY: + +* Update RSA key generation to use a key size of at least 2048 bits. [[GH-20112](https://github.com/hashicorp/consul/issues/20112)] +* Upgrade OpenShift container images to use `ubi9-minimal:9.3` as the base image. [[GH-20014](https://github.com/hashicorp/consul/issues/20014)] + +IMPROVEMENTS: + +* Upgrade to use Go 1.21.6. [[GH-20062](https://github.com/hashicorp/consul/issues/20062)] + +BUG FIXES: + +* ui: update token list on Role details page to show only linked tokens [[GH-19912](https://github.com/hashicorp/consul/issues/19912)] + +## 1.17.1 (December 12, 2023) + +SECURITY: + +* Update `github.com/golang-jwt/jwt/v4` to v4.5.0 to address [PRISMA-2022-0270](https://github.com/golang-jwt/jwt/issues/258). [[GH-19705](https://github.com/hashicorp/consul/issues/19705)] +* Upgrade to use Go 1.20.12. This resolves CVEs + [CVE-2023-45283](https://nvd.nist.gov/vuln/detail/CVE-2023-45283): (`path/filepath`) recognize \??\ as a Root Local Device path prefix (Windows) + [CVE-2023-45284](https://nvd.nist.gov/vuln/detail/CVE-2023-45285): recognize device names with trailing spaces and superscripts (Windows) + [CVE-2023-39326](https://nvd.nist.gov/vuln/detail/CVE-2023-39326): (`net/http`) limit chunked data overhead + [CVE-2023-45285](https://nvd.nist.gov/vuln/detail/CVE-2023-45285): (`cmd/go`) go get may unexpectedly fallback to insecure git [[GH-19840](https://github.com/hashicorp/consul/issues/19840)] +* connect: update supported envoy versions to 1.24.12, 1.25.11, 1.26.6, 1.27.2 to address [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) [[GH-19274](https://github.com/hashicorp/consul/issues/19274)] + +FEATURES: + +* acl: Adds nomad client templated policy [[GH-19827](https://github.com/hashicorp/consul/issues/19827)] +* cli: Adds new subcommand `peering exported-services` to list services exported to a peer . Refer to the [CLI docs](https://developer.hashicorp.com/consul/commands/peering) for more information. [[GH-19821](https://github.com/hashicorp/consul/issues/19821)] + +IMPROVEMENTS: + +* mesh: parse the proxy-defaults protocol when write the config-entry to avoid parsing it when compiling the discovery chain. [[GH-19829](https://github.com/hashicorp/consul/issues/19829)] +* wan-federation: use a hash to diff config entries when replicating in the secondary DC to avoid unnecessary writes.. [[GH-19795](https://github.com/hashicorp/consul/issues/19795)] +* Replaces UI Side Nav with Helios Design System Side Nav. Adds dc/partition/namespace searching in Side Nav. [[GH-19342](https://github.com/hashicorp/consul/issues/19342)] +* acl: add api-gateway templated policy [[GH-19728](https://github.com/hashicorp/consul/issues/19728)] +* acl: add templated policy descriptions [[GH-19735](https://github.com/hashicorp/consul/issues/19735)] +* api: Add support for listing ACL tokens by service name when using templated policies. [[GH-19666](https://github.com/hashicorp/consul/issues/19666)] +* cli: stop simultaneous usage of -templated-policy and -templated-policy-file when creating a role or token. [[GH-19389](https://github.com/hashicorp/consul/issues/19389)] +* cloud: push additional server TLS metadata to HCP [[GH-19682](https://github.com/hashicorp/consul/issues/19682)] +* connect: Default `stats_flush_interval` to 60 seconds when using the Consul Telemetry Collector, unless custom stats sink are present or an explicit flush interval is configured. [[GH-19663](https://github.com/hashicorp/consul/issues/19663)] +* metrics: increment consul.client.rpc.failed if RPC fails because no servers are accessible [[GH-19721](https://github.com/hashicorp/consul/issues/19721)] +* metrics: modify consul.client.rpc metric to exclude internal retries for consistency with consul.client.rpc.exceeded and consul.client.rpc.failed [[GH-19721](https://github.com/hashicorp/consul/issues/19721)] +* ui: move nspace and partitions requests into their selector menus [[GH-19594](https://github.com/hashicorp/consul/issues/19594)] + +BUG FIXES: + +* CLI: fix a panic when deleting a non existing policy by name. [[GH-19679](https://github.com/hashicorp/consul/issues/19679)] +* Mesh Gateways: Fix a bug where replicated and peered mesh gateways with hostname-based WAN addresses fail to initialize. [[GH-19268](https://github.com/hashicorp/consul/issues/19268)] +* ca: Fix bug with Vault CA provider where renewing a retracted token would cause retries in a tight loop, degrading performance. [[GH-19285](https://github.com/hashicorp/consul/issues/19285)] +* ca: Fix bug with Vault CA provider where token renewal goroutines could leak if CA failed to initialize. [[GH-19285](https://github.com/hashicorp/consul/issues/19285)] +* connect: Solves an issue where two upstream services with the same name in different namespaces were not getting routed to correctly by API Gateways. [[GH-19860](https://github.com/hashicorp/consul/issues/19860)] +* federation: **(Enterprise Only)** Fixed an issue where namespace reconciliation could result into the secondary having dangling instances of namespaces marked for deletion +* ui: clear peer on home logo link [[GH-19549](https://github.com/hashicorp/consul/issues/19549)] +* ui: fix being able to view peered services from non-default namnespaces [[GH-19586](https://github.com/hashicorp/consul/issues/19586)] +* ui: stop manually reconciling services if peering is enabled [[GH-19907](https://github.com/hashicorp/consul/issues/19907)] +* wan-federation: Fix a bug where servers wan-federated through mesh-gateways could crash due to overlapping LAN IP addresses. [[GH-19503](https://github.com/hashicorp/consul/issues/19503)] +* xds: Add configurable `xds_fetch_timeout_ms` option to proxy registrations that allows users to prevent endpoints from dropping when they have proxies with a large number of upstreams. [[GH-19871](https://github.com/hashicorp/consul/issues/19871)] +* xds: ensure child resources are re-sent to Envoy when the parent is updated even if the child already has pending updates. [[GH-19866](https://github.com/hashicorp/consul/issues/19866)] + +## 1.16.4 (December 12, 2023) + +SECURITY: + +* Update `github.com/golang-jwt/jwt/v4` to v4.5.0 to address [PRISMA-2022-0270](https://github.com/golang-jwt/jwt/issues/258). [[GH-19705](https://github.com/hashicorp/consul/issues/19705)] +* Upgrade to use Go 1.20.12. This resolves CVEs + [CVE-2023-45283](https://nvd.nist.gov/vuln/detail/CVE-2023-45283): (`path/filepath`) recognize \??\ as a Root Local Device path prefix (Windows) + [CVE-2023-45284](https://nvd.nist.gov/vuln/detail/CVE-2023-45285): recognize device names with trailing spaces and superscripts (Windows) + [CVE-2023-39326](https://nvd.nist.gov/vuln/detail/CVE-2023-39326): (`net/http`) limit chunked data overhead + [CVE-2023-45285](https://nvd.nist.gov/vuln/detail/CVE-2023-45285): (`cmd/go`) go get may unexpectedly fallback to insecure git [[GH-19840](https://github.com/hashicorp/consul/issues/19840)] + +IMPROVEMENTS: + +* mesh: parse the proxy-defaults protocol when write the config-entry to avoid parsing it when compiling the discovery chain. [[GH-19829](https://github.com/hashicorp/consul/issues/19829)] +* wan-federation: use a hash to diff config entries when replicating in the secondary DC to avoid unnecessary writes.. [[GH-19795](https://github.com/hashicorp/consul/issues/19795)] +* cli: Adds cli support for checking TCP connection for ports. If -ports flag is not given, it will check for + default ports of consul listed here - https://developer.hashicorp.com/consul/docs/install/ports [[GH-18329](https://github.com/hashicorp/consul/issues/18329)] +* cloud: push additional server TLS metadata to HCP [[GH-19682](https://github.com/hashicorp/consul/issues/19682)] +* connect: Default `stats_flush_interval` to 60 seconds when using the Consul Telemetry Collector, unless custom stats sink are present or an explicit flush interval is configured. [[GH-19663](https://github.com/hashicorp/consul/issues/19663)] +* metrics: increment consul.client.rpc.failed if RPC fails because no servers are accessible [[GH-19721](https://github.com/hashicorp/consul/issues/19721)] +* metrics: modify consul.client.rpc metric to exclude internal retries for consistency with consul.client.rpc.exceeded and consul.client.rpc.failed [[GH-19721](https://github.com/hashicorp/consul/issues/19721)] + +BUG FIXES: + +* CLI: fix a panic when deleting a non existing policy by name. [[GH-19679](https://github.com/hashicorp/consul/issues/19679)] +* connect: Solves an issue where two upstream services with the same name in different namespaces were not getting routed to correctly by API Gateways. [[GH-19860](https://github.com/hashicorp/consul/issues/19860)] +* federation: **(Enterprise Only)** Fixed an issue where namespace reconciliation could result into the secondary having dangling instances of namespaces marked for deletion +* ui: only show hcp link if url is present [[GH-19443](https://github.com/hashicorp/consul/issues/19443)] +* wan-federation: Fix a bug where servers wan-federated through mesh-gateways could crash due to overlapping LAN IP addresses. [[GH-19503](https://github.com/hashicorp/consul/issues/19503)] +* xds: Add configurable `xds_fetch_timeout_ms` option to proxy registrations that allows users to prevent endpoints from dropping when they have proxies with a large number of upstreams. [[GH-19871](https://github.com/hashicorp/consul/issues/19871)] +* xds: ensure child resources are re-sent to Envoy when the parent is updated even if the child already has pending updates. [[GH-19866](https://github.com/hashicorp/consul/issues/19866)] + +## 1.15.8 (December 12, 2023) + +SECURITY: + +* Update `github.com/golang-jwt/jwt/v4` to v4.5.0 to address [PRISMA-2022-0270](https://github.com/golang-jwt/jwt/issues/258). [[GH-19705](https://github.com/hashicorp/consul/issues/19705)] +* Upgrade to use Go 1.20.12. This resolves CVEs + [CVE-2023-45283](https://nvd.nist.gov/vuln/detail/CVE-2023-45283): (`path/filepath`) recognize \??\ as a Root Local Device path prefix (Windows) + [CVE-2023-45284](https://nvd.nist.gov/vuln/detail/CVE-2023-45285): recognize device names with trailing spaces and superscripts (Windows) + [CVE-2023-39326](https://nvd.nist.gov/vuln/detail/CVE-2023-39326): (`net/http`) limit chunked data overhead + [CVE-2023-45285](https://nvd.nist.gov/vuln/detail/CVE-2023-45285): (`cmd/go`) go get may unexpectedly fallback to insecure git [[GH-19840](https://github.com/hashicorp/consul/issues/19840)] + +IMPROVEMENTS: + +* mesh: parse the proxy-defaults protocol when write the config-entry to avoid parsing it when compiling the discovery chain. [[GH-19829](https://github.com/hashicorp/consul/issues/19829)] +* wan-federation: use a hash to diff config entries when replicating in the secondary DC to avoid unnecessary writes.. [[GH-19795](https://github.com/hashicorp/consul/issues/19795)] +* cli: Adds cli support for checking TCP connection for ports. If -ports flag is not given, it will check for + default ports of consul listed here - https://developer.hashicorp.com/consul/docs/install/ports [[GH-18329](https://github.com/hashicorp/consul/issues/18329)] +* connect: Default `stats_flush_interval` to 60 seconds when using the Consul Telemetry Collector, unless custom stats sink are present or an explicit flush interval is configured. [[GH-19663](https://github.com/hashicorp/consul/issues/19663)] +* metrics: increment consul.client.rpc.failed if RPC fails because no servers are accessible [[GH-19721](https://github.com/hashicorp/consul/issues/19721)] +* metrics: modify consul.client.rpc metric to exclude internal retries for consistency with consul.client.rpc.exceeded and consul.client.rpc.failed [[GH-19721](https://github.com/hashicorp/consul/issues/19721)] + +BUG FIXES: + +* CLI: fix a panic when deleting a non existing policy by name. [[GH-19679](https://github.com/hashicorp/consul/issues/19679)] +* connect: Solves an issue where two upstream services with the same name in different namespaces were not getting routed to correctly by API Gateways. [[GH-19860](https://github.com/hashicorp/consul/issues/19860)] +* federation: **(Enterprise Only)** Fixed an issue where namespace reconciliation could result into the secondary having dangling instances of namespaces marked for deletion +* ui: only show back-to-hcp link when url is present [[GH-19444](https://github.com/hashicorp/consul/issues/19444)] +* wan-federation: Fix a bug where servers wan-federated through mesh-gateways could crash due to overlapping LAN IP addresses. [[GH-19503](https://github.com/hashicorp/consul/issues/19503)] +* xds: Add configurable `xds_fetch_timeout_ms` option to proxy registrations that allows users to prevent endpoints from dropping when they have proxies with a large number of upstreams. [[GH-19871](https://github.com/hashicorp/consul/issues/19871)] +* xds: ensure child resources are re-sent to Envoy when the parent is updated even if the child already has pending updates. [[GH-19866](https://github.com/hashicorp/consul/issues/19866)] + ## 1.17.0 (October 31, 2023) BREAKING CHANGES: @@ -5,6 +790,10 @@ BREAKING CHANGES: * api: RaftLeaderTransfer now requires an id string. An empty string can be specified to keep the old behavior. [[GH-17107](https://github.com/hashicorp/consul/issues/17107)] * audit-logging: **(Enterprise only)** allowing timestamp based filename only on rotation. initially the filename will be just file.json [[GH-18668](https://github.com/hashicorp/consul/issues/18668)] +DEPRECATIONS: + +* cli: Deprecate the `-admin-access-log-path` flag from `consul connect envoy` command in favor of: `-admin-access-log-config`. [[GH-15946](https://github.com/hashicorp/consul/issues/15946)] + SECURITY: * Update `golang.org/x/net` to v0.17.0 to address [CVE-2023-39325](https://nvd.nist.gov/vuln/detail/CVE-2023-39325) @@ -88,6 +877,81 @@ BUG FIXES: * telemetry: emit consul version metric on a regular interval. [[GH-6876](https://github.com/hashicorp/consul/issues/6876)] * tlsutil: Default setting of ServerName field in outgoing TLS configuration for checks now handled by crypto/tls. [[GH-17481](https://github.com/hashicorp/consul/issues/17481)] +## 1.16.3 (October 31, 2023) + +SECURITY: + +* Update `golang.org/x/net` to v0.17.0 to address [CVE-2023-39325](https://nvd.nist.gov/vuln/detail/CVE-2023-39325) +/ [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487)(`x/net/http2`). [[GH-19225](https://github.com/hashicorp/consul/issues/19225)] +* Upgrade Go to 1.20.10. +This resolves vulnerability [CVE-2023-39325](https://nvd.nist.gov/vuln/detail/CVE-2023-39325) +/ [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487)(`net/http`). [[GH-19225](https://github.com/hashicorp/consul/issues/19225)] +* Upgrade `google.golang.org/grpc` to 1.56.3. +This resolves vulnerability [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487). [[GH-19414](https://github.com/hashicorp/consul/issues/19414)] +* connect: update supported envoy versions to 1.24.12, 1.25.11, 1.26.6 to address [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) [[GH-19273](https://github.com/hashicorp/consul/issues/19273)] + +BUG FIXES: + +* Mesh Gateways: Fix a bug where replicated and peered mesh gateways with hostname-based WAN addresses fail to initialize. [[GH-19268](https://github.com/hashicorp/consul/issues/19268)] +* api-gateway: fix matching for different hostnames on the same listener [[GH-19120](https://github.com/hashicorp/consul/issues/19120)] +* api: add custom marshal/unmarshal for ServiceResolverConfigEntry.RequestTimeout so config entries that set this field can be read using the API. [[GH-19031](https://github.com/hashicorp/consul/issues/19031)] +* ca: Fix bug with Vault CA provider where renewing a retracted token would cause retries in a tight loop, degrading performance. [[GH-19285](https://github.com/hashicorp/consul/issues/19285)] +* ca: Fix bug with Vault CA provider where token renewal goroutines could leak if CA failed to initialize. [[GH-19285](https://github.com/hashicorp/consul/issues/19285)] +* ca: ensure Vault CA provider respects Vault Enterprise namespace configuration. [[GH-19095](https://github.com/hashicorp/consul/issues/19095)] +* catalog api: fixes a bug with catalog api where filter query parameter was not working correctly for the `/v1/catalog/services` endpoint [[GH-18322](https://github.com/hashicorp/consul/issues/18322)] +* connect: Fix bug where uncleanly closed xDS connections would influence connection balancing for too long and prevent envoy instances from starting. Two new configuration fields +`performance.grpc_keepalive_timeout` and `performance.grpc_keepalive_interval` now exist to allow for configuration on how often these dead connections will be cleaned up. [[GH-19339](https://github.com/hashicorp/consul/issues/19339)] +* dns: **(Enterprise only)** Fix bug where sameness group queries did not correctly inherit the agent's partition. +* gateways: Fix a bug where a service in a peered datacenter could not access an external node service through a terminating gateway [[GH-18959](https://github.com/hashicorp/consul/issues/18959)] +* server: **(Enterprise Only)** Fixed an issue where snake case keys were rejected when configuring the control-plane-request-limit config entry + +## 1.15.7 (October 31, 2023) + +SECURITY: + +* Update `golang.org/x/net` to v0.17.0 to address [CVE-2023-39325](https://nvd.nist.gov/vuln/detail/CVE-2023-39325) +/ [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487)(`x/net/http2`). [[GH-19225](https://github.com/hashicorp/consul/issues/19225)] +* Upgrade Go to 1.20.10. +This resolves vulnerability [CVE-2023-39325](https://nvd.nist.gov/vuln/detail/CVE-2023-39325) +/ [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487)(`net/http`). [[GH-19225](https://github.com/hashicorp/consul/issues/19225)] +* Upgrade `google.golang.org/grpc` to 1.56.3. +This resolves vulnerability [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487). [[GH-19414](https://github.com/hashicorp/consul/issues/19414)] +* connect: update supported envoy versions to 1.24.12, 1.25.11 to address [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) [[GH-19272](https://github.com/hashicorp/consul/issues/19272)] + +BUG FIXES: + +* Mesh Gateways: Fix a bug where replicated and peered mesh gateways with hostname-based WAN addresses fail to initialize. [[GH-19268](https://github.com/hashicorp/consul/issues/19268)] +* api: add custom marshal/unmarshal for ServiceResolverConfigEntry.RequestTimeout so config entries that set this field can be read using the API. [[GH-19031](https://github.com/hashicorp/consul/issues/19031)] +* ca: Fix bug with Vault CA provider where renewing a retracted token would cause retries in a tight loop, degrading performance. [[GH-19285](https://github.com/hashicorp/consul/issues/19285)] +* ca: Fix bug with Vault CA provider where token renewal goroutines could leak if CA failed to initialize. [[GH-19285](https://github.com/hashicorp/consul/issues/19285)] +* ca: ensure Vault CA provider respects Vault Enterprise namespace configuration. [[GH-19095](https://github.com/hashicorp/consul/issues/19095)] +* catalog api: fixes a bug with catalog api where filter query parameter was not working correctly for the `/v1/catalog/services` endpoint [[GH-18322](https://github.com/hashicorp/consul/issues/18322)] +* connect: Fix bug where uncleanly closed xDS connections would influence connection balancing for too long and prevent envoy instances from starting. Two new configuration fields +`performance.grpc_keepalive_timeout` and `performance.grpc_keepalive_interval` now exist to allow for configuration on how often these dead connections will be cleaned up. [[GH-19339](https://github.com/hashicorp/consul/issues/19339)] +* gateways: Fix a bug where a service in a peered datacenter could not access an external node service through a terminating gateway [[GH-18959](https://github.com/hashicorp/consul/issues/18959)] + +## 1.14.11 (October 31, 2023) + +SECURITY: + +* Update `golang.org/x/net` to v0.17.0 to address [CVE-2023-39325](https://nvd.nist.gov/vuln/detail/CVE-2023-39325) +/ [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487)(`x/net/http2`). [[GH-19225](https://github.com/hashicorp/consul/issues/19225)] +* Upgrade Go to 1.20.10. +This resolves vulnerability [CVE-2023-39325](https://nvd.nist.gov/vuln/detail/CVE-2023-39325) +/ [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487)(`net/http`). [[GH-19225](https://github.com/hashicorp/consul/issues/19225)] +* Upgrade `google.golang.org/grpc` to 1.56.3. +This resolves vulnerability [CVE-2023-44487](https://nvd.nist.gov/vuln/detail/CVE-2023-44487). [[GH-19414](https://github.com/hashicorp/consul/issues/19414)] +* connect: update supported envoy versions to 1.24.12 to address [CVE-2023-44487](https://github.com/envoyproxy/envoy/security/advisories/GHSA-jhv4-f7mr-xx76) [[GH-19271](https://github.com/hashicorp/consul/issues/19271)] + +BUG FIXES: + +* Mesh Gateways: Fix a bug where replicated and peered mesh gateways with hostname-based WAN addresses fail to initialize. [[GH-19268](https://github.com/hashicorp/consul/issues/19268)] +* api: add custom marshal/unmarshal for ServiceResolverConfigEntry.RequestTimeout so config entries that set this field can be read using the API. [[GH-19031](https://github.com/hashicorp/consul/issues/19031)] +* ca: ensure Vault CA provider respects Vault Enterprise namespace configuration. [[GH-19095](https://github.com/hashicorp/consul/issues/19095)] +* catalog api: fixes a bug with catalog api where filter query parameter was not working correctly for the `/v1/catalog/services` endpoint [[GH-18322](https://github.com/hashicorp/consul/issues/18322)] +* connect: Fix bug where uncleanly closed xDS connections would influence connection balancing for too long and prevent envoy instances from starting. Two new configuration fields +`performance.grpc_keepalive_timeout` and `performance.grpc_keepalive_interval` now exist to allow for configuration on how often these dead connections will be cleaned up. [[GH-19339](https://github.com/hashicorp/consul/issues/19339)] + ## 1.17.0-rc1 (October 11, 2023) BREAKING CHANGES: @@ -1584,6 +2448,24 @@ NOTES: * ci: change action to pull v1 instead of main [[GH-12846](https://github.com/hashicorp/consul/issues/12846)] +## 1.11.6 (May 25, 2022) + +IMPROVEMENTS: + +* sentinel: **(Enterprise Only)** Sentinel now uses SHA256 to generate policy ids + +BUG FIXES: + +* Fix a bug when configuring an `add_headers` directive named `Host` the header is not set for `v1/internal/ui/metrics-proxy/` endpoint. [[GH-13071](https://github.com/hashicorp/consul/issues/13071)] +* areas: **(Enterprise Only)** Fixes a bug when using Yamux pool ( for servers version 1.7.3 and later), the entire pool was locked while connecting to a remote location, which could potentially take a long time. [[GH-1368](https://github.com/hashicorp/consul/issues/1368)] +* ca: fix a bug that caused a non blocking leaf cert query after a blocking leaf cert query to block [[GH-12820](https://github.com/hashicorp/consul/issues/12820)] +* health: ensure /v1/health/service/:service endpoint returns the most recent results when a filter is used with streaming #12640 [[GH-12640](https://github.com/hashicorp/consul/issues/12640)] +* snapshot-agent: **(Enterprise only)** Fix a bug where providing the ACL token to the snapshot agent via a CLI or ENV variable without a license configured results in an error during license auto-retrieval. + +NOTES: + +* ci: change action to pull v1 instead of main [[GH-12846](https://github.com/hashicorp/consul/issues/12846)] + ## 1.12.0 (April 20, 2022) BREAKING CHANGES: @@ -1668,24 +2550,6 @@ NOTES: * Forked net/rpc to add middleware support: https://github.com/hashicorp/consul-net-rpc/ . [[GH-12311](https://github.com/hashicorp/consul/issues/12311)] * dependency: Upgrade to use Go 1.18.1 [[GH-12808](https://github.com/hashicorp/consul/issues/12808)] -## 1.11.6 (May 25, 2022) - -IMPROVEMENTS: - -* sentinel: **(Enterprise Only)** Sentinel now uses SHA256 to generate policy ids - -BUG FIXES: - -* Fix a bug when configuring an `add_headers` directive named `Host` the header is not set for `v1/internal/ui/metrics-proxy/` endpoint. [[GH-13071](https://github.com/hashicorp/consul/issues/13071)] -* areas: **(Enterprise Only)** Fixes a bug when using Yamux pool ( for servers version 1.7.3 and later), the entire pool was locked while connecting to a remote location, which could potentially take a long time. [[GH-1368](https://github.com/hashicorp/consul/issues/1368)] -* ca: fix a bug that caused a non blocking leaf cert query after a blocking leaf cert query to block [[GH-12820](https://github.com/hashicorp/consul/issues/12820)] -* health: ensure /v1/health/service/:service endpoint returns the most recent results when a filter is used with streaming #12640 [[GH-12640](https://github.com/hashicorp/consul/issues/12640)] -* snapshot-agent: **(Enterprise only)** Fix a bug where providing the ACL token to the snapshot agent via a CLI or ENV variable without a license configured results in an error during license auto-retrieval. - -NOTES: - -* ci: change action to pull v1 instead of main [[GH-12846](https://github.com/hashicorp/consul/issues/12846)] - ## 1.11.5 (April 13, 2022) SECURITY: diff --git a/Dockerfile b/Dockerfile index 1926c521299a..dc617c5e0492 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ # Official docker image that includes binaries from releases.hashicorp.com. This # downloads the release from releases.hashicorp.com and therefore requires that # the release is published before building the Docker image. -FROM docker.mirror.hashicorp.services/alpine:3.18 as official +FROM docker.mirror.hashicorp.services/alpine:3.20 as official # This is the release of Consul to pull in. ARG VERSION @@ -112,7 +112,7 @@ CMD ["agent", "-dev", "-client", "0.0.0.0"] # Production docker image that uses CI built binaries. # Remember, this image cannot be built locally. -FROM docker.mirror.hashicorp.services/alpine:3.18 as default +FROM docker.mirror.hashicorp.services/alpine:3.20 as default ARG PRODUCT_VERSION ARG BIN_NAME @@ -123,7 +123,7 @@ ENV BIN_NAME=$BIN_NAME ENV PRODUCT_VERSION=$PRODUCT_VERSION ARG PRODUCT_REVISION -ARG PRODUCT_NAME=$BIN_NAME +ENV PRODUCT_NAME=$BIN_NAME # TARGETOS and TARGETARCH are set automatically when --platform is provided. ARG TARGETOS TARGETARCH @@ -136,8 +136,10 @@ LABEL org.opencontainers.image.authors="Consul Team " \ org.opencontainers.image.vendor="HashiCorp" \ org.opencontainers.image.title="consul" \ org.opencontainers.image.description="Consul is a datacenter runtime that provides service discovery, configuration, and orchestration." \ + org.opencontainers.image.licenses="BSL-1.1" \ version=${PRODUCT_VERSION} +COPY LICENSE /usr/share/doc/$PRODUCT_NAME/LICENSE.txt # Set up certificates and base tools. # libc6-compat is needed to symlink the shared libraries for ARM builds RUN apk add -v --no-cache \ @@ -201,9 +203,8 @@ CMD ["agent", "-dev", "-client", "0.0.0.0"] # Red Hat UBI-based image # This target is used to build a Consul image for use on OpenShift. -FROM registry.access.redhat.com/ubi9-minimal:9.2 as ubi +FROM registry.access.redhat.com/ubi9-minimal:9.4 as ubi -ARG PRODUCT_NAME ARG PRODUCT_VERSION ARG PRODUCT_REVISION ARG BIN_NAME @@ -212,8 +213,7 @@ ARG BIN_NAME # and the version to download. Example: PRODUCT_NAME=consul PRODUCT_VERSION=1.2.3. ENV BIN_NAME=$BIN_NAME ENV PRODUCT_VERSION=$PRODUCT_VERSION - -ARG PRODUCT_NAME=$BIN_NAME +ENV PRODUCT_NAME=$BIN_NAME # TARGETOS and TARGETARCH are set automatically when --platform is provided. ARG TARGETOS TARGETARCH @@ -226,14 +226,16 @@ LABEL org.opencontainers.image.authors="Consul Team " \ org.opencontainers.image.vendor="HashiCorp" \ org.opencontainers.image.title="consul" \ org.opencontainers.image.description="Consul is a datacenter runtime that provides service discovery, configuration, and orchestration." \ + org.opencontainers.image.licenses="BSL-1.1" \ version=${PRODUCT_VERSION} +COPY LICENSE /usr/share/doc/$PRODUCT_NAME/LICENSE.txt # Copy license for Red Hat certification. COPY LICENSE /licenses/mozilla.txt # Set up certificates and base tools. # dumb-init is downloaded directly from GitHub because there's no RPM package. -# Its shasum is hardcoded. If you upgrade the dumb-init verion you'll need to +# Its shasum is hardcoded. If you upgrade the dumb-init version you'll need to # also update the shasum. RUN set -eux && \ microdnf install -y ca-certificates shadow-utils gnupg libcap openssl iputils jq iptables wget unzip tar && \ diff --git a/LICENSE b/LICENSE index 1f38fcdd11e2..e20f24315366 100644 --- a/LICENSE +++ b/LICENSE @@ -1,14 +1,45 @@ License text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved. -“Business Source License” is a trademark of MariaDB Corporation Ab. +"Business Source License" is a trademark of MariaDB Corporation Ab. Parameters Licensor: HashiCorp, Inc. -Licensed Work: Consul 1.17.0. The Licensed Work is (c) 2023 HashiCorp, Inc. -Additional Use Grant: You may make production use of the Licensed Work, - provided such use does not include offering the Licensed Work - to third parties on a hosted or embedded basis which is - competitive with HashiCorp's products. +Licensed Work: Consul Version 1.17.0 or later. The Licensed Work is (c) 2024 + HashiCorp, Inc. +Additional Use Grant: You may make production use of the Licensed Work, provided + Your use does not include offering the Licensed Work to third + parties on a hosted or embedded basis in order to compete with + HashiCorp's paid version(s) of the Licensed Work. For purposes + of this license: + + A "competitive offering" is a Product that is offered to third + parties on a paid basis, including through paid support + arrangements, that significantly overlaps with the capabilities + of HashiCorp's paid version(s) of the Licensed Work. If Your + Product is not a competitive offering when You first make it + generally available, it will not become a competitive offering + later due to HashiCorp releasing a new version of the Licensed + Work with additional capabilities. In addition, Products that + are not provided on a paid basis are not competitive. + + "Product" means software that is offered to end users to manage + in their own environments or offered as a service on a hosted + basis. + + "Embedded" means including the source code or executable code + from the Licensed Work in a competitive offering. "Embedded" + also means packaging the competitive offering in such a way + that the Licensed Work must be accessed or downloaded for the + competitive offering to operate. + + Hosting or using the Licensed Work(s) for internal purposes + within an organization is not considered a competitive + offering. HashiCorp considers your organization to include all + of your affiliates under common control. + + For binding interpretive guidance on using HashiCorp products + under the Business Source License, please visit our FAQ. + (https://www.hashicorp.com/license-faq) Change Date: Four years from the date the Licensed Work is published. Change License: MPL 2.0 @@ -55,7 +86,7 @@ Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License). TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON -AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. diff --git a/Makefile b/Makefile index a7c275511c51..b8b72d5de198 100644 --- a/Makefile +++ b/Makefile @@ -10,16 +10,19 @@ GO_MODULES := $(shell find . -name go.mod -exec dirname {} \; | grep -v "proto-g # These version variables can either be a valid string for "go install @" # or the string @DEV to imply use what is currently installed locally. ### -GOLANGCI_LINT_VERSION='v1.51.1' -MOCKERY_VERSION='v2.20.0' +GOLANGCI_LINT_VERSION='v1.55.2' +MOCKERY_VERSION='v2.41.0' BUF_VERSION='v1.26.0' -PROTOC_GEN_GO_GRPC_VERSION="v1.2.0" -MOG_VERSION='v0.4.1' +PROTOC_GEN_GO_GRPC_VERSION='v1.2.0' +MOG_VERSION='v0.4.2' PROTOC_GO_INJECT_TAG_VERSION='v1.3.0' -PROTOC_GEN_GO_BINARY_VERSION="v0.1.0" -DEEP_COPY_VERSION='bc3f5aa5735d8a54961580a3a24422c308c831c2' +PROTOC_GEN_GO_BINARY_VERSION='v0.1.0' +DEEP_COPY_VERSION='e112476c0181d3d69067bac191f9b6bcda2ce812' COPYWRITE_TOOL_VERSION='v0.16.4' +LINT_CONSUL_RETRY_VERSION='v1.4.0' +# Go imports formatter +GCI_VERSION='v0.11.2' MOCKED_PB_DIRS= pbdns @@ -65,8 +68,13 @@ GO_BUILD_TAG?=consul-build-go UI_BUILD_TAG?=consul-build-ui BUILD_CONTAINER_NAME?=consul-builder CONSUL_IMAGE_VERSION?=latest -ENVOY_VERSION?='1.25.4' -CONSUL_DATAPLANE_IMAGE := $(or $(CONSUL_DATAPLANE_IMAGE),"docker.io/hashicorppreview/consul-dataplane:1.3-dev-ubi") +# When changing the method of Go version detection, also update +# version detection in CI workflows (reusable-get-go-version.yml). +GOLANG_VERSION?=$(shell head -n 1 .go-version) +# Takes the highest version from the ENVOY_VERSIONS file. +ENVOY_VERSION?=$(shell cat envoyextensions/xdscommon/ENVOY_VERSIONS | grep '^[[:digit:]]' | sort -nr | head -n 1) +CONSUL_DATAPLANE_IMAGE := $(or $(CONSUL_DATAPLANE_IMAGE),"docker.io/hashicorppreview/consul-dataplane:1.6-dev-ubi") +DEPLOYER_CONSUL_DATAPLANE_IMAGE := $(or $(DEPLOYER_CONSUL_DATAPLANE_IMAGE), "docker.io/hashicorppreview/consul-dataplane:1.6-dev") CONSUL_VERSION?=$(shell cat version/VERSION) @@ -232,6 +240,19 @@ go-mod-tidy/%: @echo "--> Running go mod tidy ($*)" @cd $* && go mod tidy +.PHONY: go-mod-get +go-mod-get: $(foreach mod,$(GO_MODULES),go-mod-get/$(mod)) ## Run go get and go mod tidy in every module for the given dependency + +.PHONY: go-mod-get/% +go-mod-get/%: +ifndef DEP_VERSION + $(error DEP_VERSION is undefined: set this to @, e.g. github.com/hashicorp/go-hclog@v1.5.0) +endif + @echo "--> Running go get ${DEP_VERSION} ($*)" + @cd $* && go get $(DEP_VERSION) + @echo "--> Running go mod tidy ($*)" + @cd $* && go mod tidy + ##@ Checks .PHONY: fmt @@ -254,6 +275,15 @@ lint/%: @echo "--> Running enumcover ($*)" @cd $* && GOWORK=off enumcover ./... +.PHONY: lint-consul-retry +lint-consul-retry: $(foreach mod,$(GO_MODULES),lint-consul-retry/$(mod)) + +.PHONY: lint-consul-retry/% +lint-consul-retry/%: lint-tools + @echo "--> Running lint-consul-retry ($*)" + @cd $* && GOWORK=off lint-consul-retry + + # check that the test-container module only imports allowlisted packages # from the root consul module. Generally we don't want to allow these imports. # In a few specific instances though it is okay to import test definitions and @@ -264,7 +294,6 @@ lint-container-test-deps: ## Check that the test-container module only imports a @cd test/integration/consul-container && \ $(CURDIR)/build-support/scripts/check-allowed-imports.sh \ github.com/hashicorp/consul \ - "internal/catalog/catalogtest" \ "internal/resource/resourcetest" ##@ Testing @@ -339,20 +368,67 @@ other-consul: ## Checking for other consul instances # NOTE: Always uses amd64 images, even when running on M1 macs, to match CI/CD environment. # You can also specify the envoy version (example: 1.27.0) setting the environment variable: ENVOY_VERSION=1.27.0 .PHONY: test-envoy-integ -test-envoy-integ: $(ENVOY_INTEG_DEPS) ## Run integration tests. +test-envoy-integ: $(ENVOY_INTEG_DEPS) ## Run envoy integration tests. @go test -v -timeout=30m -tags integration $(GO_TEST_FLAGS) ./test/integration/connect/envoy # NOTE: Use DOCKER_BUILDKIT=0, if docker build fails to resolve consul:local base image .PHONY: test-compat-integ-setup -test-compat-integ-setup: dev-docker - @docker tag consul-dev:latest $(CONSUL_COMPAT_TEST_IMAGE):local - @docker run --rm -t $(CONSUL_COMPAT_TEST_IMAGE):local consul version +test-compat-integ-setup: test-deployer-setup @# 'consul-envoy:target-version' is needed by compatibility integ test @docker build -t consul-envoy:target-version --build-arg CONSUL_IMAGE=$(CONSUL_COMPAT_TEST_IMAGE):local --build-arg ENVOY_VERSION=${ENVOY_VERSION} -f ./test/integration/consul-container/assets/Dockerfile-consul-envoy ./test/integration/consul-container/assets @docker build -t consul-dataplane:local --build-arg CONSUL_IMAGE=$(CONSUL_COMPAT_TEST_IMAGE):local --build-arg CONSUL_DATAPLANE_IMAGE=${CONSUL_DATAPLANE_IMAGE} -f ./test/integration/consul-container/assets/Dockerfile-consul-dataplane ./test/integration/consul-container/assets +# NOTE: Use DOCKER_BUILDKIT=0, if docker build fails to resolve consul:local base image +.PHONY: test-deployer-setup +test-deployer-setup: dev-docker + @docker tag consul-dev:latest $(CONSUL_COMPAT_TEST_IMAGE):local + @docker run --rm -t $(CONSUL_COMPAT_TEST_IMAGE):local consul version + +.PHONY: test-deployer +test-deployer: test-deployer-setup ## Run deployer-based integration tests (skipping peering_commontopo). + @cd ./test-integ && \ + NOLOGBUFFER=1 \ + TEST_LOG_LEVEL=debug \ + DEPLOYER_CONSUL_DATAPLANE_IMAGE=$(DEPLOYER_CONSUL_DATAPLANE_IMAGE) \ + gotestsum \ + --raw-command \ + --format=standard-verbose \ + --debug \ + -- \ + go test \ + -tags "$(GOTAGS)" \ + -timeout=20m \ + -json \ + $(shell sh -c "cd test-integ ; go list -tags \"$(GOTAGS)\" ./... | grep -v peering_commontopo") \ + --target-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --target-version local \ + --latest-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --latest-version latest + +.PHONY: test-deployer-peering +test-deployer-peering: test-deployer-setup ## Run deployer-based integration tests (just peering_commontopo). + @cd ./test-integ/peering_commontopo && \ + NOLOGBUFFER=1 \ + TEST_LOG_LEVEL=debug \ + DEPLOYER_CONSUL_DATAPLANE_IMAGE=$(DEPLOYER_CONSUL_DATAPLANE_IMAGE) \ + gotestsum \ + --raw-command \ + --format=standard-verbose \ + --debug \ + -- \ + go test \ + -tags "$(GOTAGS)" \ + -timeout=20m \ + -json \ + . \ + --target-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --target-version local \ + --latest-image $(CONSUL_COMPAT_TEST_IMAGE) \ + --latest-version latest + + .PHONY: test-compat-integ -test-compat-integ: test-compat-integ-setup ## Test compat integ +test-compat-integ: test-compat-integ-setup ## Run consul-container based integration tests. ifeq ("$(GOTESTSUM_PATH)","") @cd ./test/integration/consul-container && \ go test \ @@ -470,8 +546,8 @@ docker-images: go-build-image ui-build-image .PHONY: go-build-image go-build-image: ## Building Golang build container - @echo "Building Golang build container" - @docker build $(NOCACHE) $(QUIET) -t $(GO_BUILD_TAG) - < build-support/docker/Build-Go.dockerfile + @echo "Building Golang $(GOLANG_VERSION) build container" + @docker build $(NOCACHE) $(QUIET) -t $(GO_BUILD_TAG) --build-arg GOLANG_VERSION=$(GOLANG_VERSION) - < build-support/docker/Build-Go.dockerfile .PHONY: consul-docker consul-docker: go-build-image ## Builds consul in a docker container and then dumps executable into ./pkg/bin/... @@ -502,11 +578,8 @@ proto-gen: proto-tools ## Regenerates all Go files from protobuf definitions .PHONY: proto-mocks proto-mocks: ## Proto mocks - for dir in $(MOCKED_PB_DIRS) ; do \ - cd proto-public && \ - rm -f $$dir/mock*.go && \ - mockery --dir $$dir --inpackage --all --recursive --log-level trace ; \ - done + @rm -rf grpcmocks/* + @mockery --config .grpcmocks.yaml .PHONY: proto-format proto-format: proto-tools ## Proto format @@ -546,6 +619,14 @@ envoy-regen: ## Regenerating envoy golden files @find "command/connect/envoy/testdata" -name '*.golden' -delete @go test -tags '$(GOTAGS)' ./command/connect/envoy -update + +##@ Changelog + +.PHONY: gen-changelog +gen-changelog: ## Generate changelog entry for the current branch based on the currently open PR for that branch + @$(SHELL) $(CURDIR)/build-support/scripts/gen-changelog.sh + + ##@ Help # The help target prints out all targets with their descriptions organized @@ -561,3 +642,4 @@ envoy-regen: ## Regenerating envoy golden files .PHONY: help help: ## Display this help. @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + diff --git a/acl/MockAuthorizer.go b/acl/MockAuthorizer.go index 9941f81e3f05..7e41db074f5c 100644 --- a/acl/MockAuthorizer.go +++ b/acl/MockAuthorizer.go @@ -59,31 +59,6 @@ func (m *MockAuthorizer) EventWrite(segment string, ctx *AuthorizerContext) Enfo return ret.Get(0).(EnforcementDecision) } -// IdentityRead checks for permission to read a given workload identity. -func (m *MockAuthorizer) IdentityRead(segment string, ctx *AuthorizerContext) EnforcementDecision { - ret := m.Called(segment, ctx) - return ret.Get(0).(EnforcementDecision) -} - -// IdentityReadAll checks for permission to read all workload identities. -func (m *MockAuthorizer) IdentityReadAll(ctx *AuthorizerContext) EnforcementDecision { - ret := m.Called(ctx) - return ret.Get(0).(EnforcementDecision) -} - -// IdentityWrite checks for permission to create or update a given -// workload identity. -func (m *MockAuthorizer) IdentityWrite(segment string, ctx *AuthorizerContext) EnforcementDecision { - ret := m.Called(segment, ctx) - return ret.Get(0).(EnforcementDecision) -} - -// IdentityWriteAny checks for write permission on any workload identity. -func (m *MockAuthorizer) IdentityWriteAny(ctx *AuthorizerContext) EnforcementDecision { - ret := m.Called(ctx) - return ret.Get(0).(EnforcementDecision) -} - // IntentionDefaultAllow determines the default authorized behavior // when no intentions match a Connect request. func (m *MockAuthorizer) IntentionDefaultAllow(ctx *AuthorizerContext) EnforcementDecision { @@ -225,7 +200,7 @@ func (m *MockAuthorizer) ServiceReadAll(ctx *AuthorizerContext) EnforcementDecis } func (m *MockAuthorizer) ServiceReadPrefix(prefix string, ctx *AuthorizerContext) EnforcementDecision { - ret := m.Called(ctx) + ret := m.Called(prefix, ctx) return ret.Get(0).(EnforcementDecision) } diff --git a/acl/acl_ce.go b/acl/acl_ce.go index 7d2b8513b832..0d207ad4211a 100644 --- a/acl/acl_ce.go +++ b/acl/acl_ce.go @@ -8,12 +8,25 @@ package acl const ( WildcardPartitionName = "" DefaultPartitionName = "" -) + // NonEmptyDefaultPartitionName is the name of the default partition that is + // not empty. An example of this being supplied is when a partition is specified + // in the request for DNS by consul-dataplane. This has been added to support + // DNS v1.5, which needs to be compatible with the original DNS subsystem which + // supports partition being "default" or empty. Otherwise, use DefaultPartitionName. + NonEmptyDefaultPartitionName = "default" + + // DefaultNamespaceName is used to mimic the behavior in consul/structs/intention.go, + // where we define IntentionDefaultNamespace as 'default' and so we use the same here. + // This is a little bit strange; one might want it to be "" like DefaultPartitionName. + DefaultNamespaceName = "default" -// Reviewer Note: This is a little bit strange; one might want it to be "" like partition name -// However in consul/structs/intention.go we define IntentionDefaultNamespace as 'default' and so -// we use the same here -const DefaultNamespaceName = "default" + // EmptyNamespaceName is the name of the default partition that is an empty string. + // An example of this being supplied is when a namespace is specifiedDNS v1. + // EmptyNamespaceName has been added to support DNS v1.5, which needs to be + // compatible with the original DNS subsystem which supports partition being "default" or empty. + // Otherwise, use DefaultNamespaceName. + EmptyNamespaceName = "" +) type EnterpriseConfig struct { // no fields in CE diff --git a/acl/acl_test.go b/acl/acl_test.go index 28542024e956..3f4c882b0e41 100644 --- a/acl/acl_test.go +++ b/acl/acl_test.go @@ -40,22 +40,6 @@ func checkAllowEventWrite(t *testing.T, authz Authorizer, prefix string, entCtx require.Equal(t, Allow, authz.EventWrite(prefix, entCtx)) } -func checkAllowIdentityRead(t *testing.T, authz Authorizer, prefix string, entCtx *AuthorizerContext) { - require.Equal(t, Allow, authz.IdentityRead(prefix, entCtx)) -} - -func checkAllowIdentityReadAll(t *testing.T, authz Authorizer, _ string, entCtx *AuthorizerContext) { - require.Equal(t, Allow, authz.IdentityReadAll(entCtx)) -} - -func checkAllowIdentityWrite(t *testing.T, authz Authorizer, prefix string, entCtx *AuthorizerContext) { - require.Equal(t, Allow, authz.IdentityWrite(prefix, entCtx)) -} - -func checkAllowIdentityWriteAny(t *testing.T, authz Authorizer, _ string, entCtx *AuthorizerContext) { - require.Equal(t, Allow, authz.IdentityWriteAny(entCtx)) -} - func checkAllowIntentionDefaultAllow(t *testing.T, authz Authorizer, prefix string, entCtx *AuthorizerContext) { require.Equal(t, Allow, authz.IntentionDefaultAllow(entCtx)) } @@ -196,22 +180,6 @@ func checkDenyEventWrite(t *testing.T, authz Authorizer, prefix string, entCtx * require.Equal(t, Deny, authz.EventWrite(prefix, entCtx)) } -func checkDenyIdentityRead(t *testing.T, authz Authorizer, prefix string, entCtx *AuthorizerContext) { - require.Equal(t, Deny, authz.IdentityRead(prefix, entCtx)) -} - -func checkDenyIdentityReadAll(t *testing.T, authz Authorizer, _ string, entCtx *AuthorizerContext) { - require.Equal(t, Deny, authz.IdentityReadAll(entCtx)) -} - -func checkDenyIdentityWrite(t *testing.T, authz Authorizer, prefix string, entCtx *AuthorizerContext) { - require.Equal(t, Deny, authz.IdentityWrite(prefix, entCtx)) -} - -func checkDenyIdentityWriteAny(t *testing.T, authz Authorizer, _ string, entCtx *AuthorizerContext) { - require.Equal(t, Deny, authz.IdentityWriteAny(entCtx)) -} - func checkDenyIntentionDefaultAllow(t *testing.T, authz Authorizer, prefix string, entCtx *AuthorizerContext) { require.Equal(t, Deny, authz.IntentionDefaultAllow(entCtx)) } @@ -360,22 +328,6 @@ func checkDefaultEventWrite(t *testing.T, authz Authorizer, prefix string, entCt require.Equal(t, Default, authz.EventWrite(prefix, entCtx)) } -func checkDefaultIdentityRead(t *testing.T, authz Authorizer, prefix string, entCtx *AuthorizerContext) { - require.Equal(t, Default, authz.IdentityRead(prefix, entCtx)) -} - -func checkDefaultIdentityReadAll(t *testing.T, authz Authorizer, _ string, entCtx *AuthorizerContext) { - require.Equal(t, Default, authz.IdentityReadAll(entCtx)) -} - -func checkDefaultIdentityWrite(t *testing.T, authz Authorizer, prefix string, entCtx *AuthorizerContext) { - require.Equal(t, Default, authz.IdentityWrite(prefix, entCtx)) -} - -func checkDefaultIdentityWriteAny(t *testing.T, authz Authorizer, _ string, entCtx *AuthorizerContext) { - require.Equal(t, Default, authz.IdentityWriteAny(entCtx)) -} - func checkDefaultIntentionDefaultAllow(t *testing.T, authz Authorizer, prefix string, entCtx *AuthorizerContext) { require.Equal(t, Default, authz.IntentionDefaultAllow(entCtx)) } @@ -516,10 +468,6 @@ func TestACL(t *testing.T) { {name: "DenyIntentionDefaultAllow", check: checkDenyIntentionDefaultAllow}, {name: "DenyIntentionRead", check: checkDenyIntentionRead}, {name: "DenyIntentionWrite", check: checkDenyIntentionWrite}, - {name: "DenyIdentityRead", check: checkDenyIdentityRead}, - {name: "DenyIdentityReadAll", check: checkDenyIdentityReadAll}, - {name: "DenyIdentityWrite", check: checkDenyIdentityWrite}, - {name: "DenyIdentityWriteAny", check: checkDenyIdentityWriteAny}, {name: "DenyKeyRead", check: checkDenyKeyRead}, {name: "DenyKeyringRead", check: checkDenyKeyringRead}, {name: "DenyKeyringWrite", check: checkDenyKeyringWrite}, @@ -554,10 +502,6 @@ func TestACL(t *testing.T) { {name: "AllowAgentWrite", check: checkAllowAgentWrite}, {name: "AllowEventRead", check: checkAllowEventRead}, {name: "AllowEventWrite", check: checkAllowEventWrite}, - {name: "AllowIdentityRead", check: checkAllowIdentityRead}, - {name: "AllowIdentityReadAll", check: checkAllowIdentityReadAll}, - {name: "AllowIdentityWrite", check: checkAllowIdentityWrite}, - {name: "AllowIdentityWriteAny", check: checkAllowIdentityWriteAny}, {name: "AllowIntentionDefaultAllow", check: checkAllowIntentionDefaultAllow}, {name: "AllowIntentionRead", check: checkAllowIntentionRead}, {name: "AllowIntentionWrite", check: checkAllowIntentionWrite}, @@ -597,10 +541,6 @@ func TestACL(t *testing.T) { {name: "AllowAgentWrite", check: checkAllowAgentWrite}, {name: "AllowEventRead", check: checkAllowEventRead}, {name: "AllowEventWrite", check: checkAllowEventWrite}, - {name: "AllowIdentityRead", check: checkAllowIdentityRead}, - {name: "AllowIdentityReadAll", check: checkAllowIdentityReadAll}, - {name: "AllowIdentityWrite", check: checkAllowIdentityWrite}, - {name: "AllowIdentityWriteAny", check: checkAllowIdentityWriteAny}, {name: "AllowIntentionDefaultAllow", check: checkAllowIntentionDefaultAllow}, {name: "AllowIntentionRead", check: checkAllowIntentionRead}, {name: "AllowIntentionWrite", check: checkAllowIntentionWrite}, @@ -1000,134 +940,6 @@ func TestACL(t *testing.T) { {name: "ChildOverrideWriteAllowed", prefix: "override", check: checkAllowAgentWrite}, }, }, - { - name: "IdentityDefaultAllowPolicyDeny", - defaultPolicy: AllowAll(), - policyStack: []*Policy{ - { - PolicyRules: PolicyRules{ - Identities: []*IdentityRule{ - { - Name: "foo", - Policy: PolicyDeny, - }, - }, - IdentityPrefixes: []*IdentityRule{ - { - Name: "prefix", - Policy: PolicyDeny, - }, - }, - }, - }, - }, - checks: []aclCheck{ - {name: "IdentityFooReadDenied", prefix: "foo", check: checkDenyIdentityRead}, - {name: "IdentityFooWriteDenied", prefix: "foo", check: checkDenyIdentityWrite}, - {name: "IdentityPrefixReadDenied", prefix: "prefix", check: checkDenyIdentityRead}, - {name: "IdentityPrefixWriteDenied", prefix: "prefix", check: checkDenyIdentityWrite}, - {name: "IdentityBarReadAllowed", prefix: "fail", check: checkAllowIdentityRead}, - {name: "IdentityBarWriteAllowed", prefix: "fail", check: checkAllowIdentityWrite}, - }, - }, - { - name: "IdentityDefaultDenyPolicyAllow", - defaultPolicy: DenyAll(), - policyStack: []*Policy{ - { - PolicyRules: PolicyRules{ - Identities: []*IdentityRule{ - { - Name: "foo", - Policy: PolicyWrite, - }, - }, - IdentityPrefixes: []*IdentityRule{ - { - Name: "prefix", - Policy: PolicyRead, - }, - }, - }, - }, - }, - checks: []aclCheck{ - {name: "IdentityFooReadAllowed", prefix: "foo", check: checkAllowIdentityRead}, - {name: "IdentityFooWriteAllowed", prefix: "foo", check: checkAllowIdentityWrite}, - {name: "IdentityPrefixReadAllowed", prefix: "prefix", check: checkAllowIdentityRead}, - {name: "IdentityPrefixWriteDenied", prefix: "prefix", check: checkDenyIdentityWrite}, - {name: "IdentityBarReadDenied", prefix: "fail", check: checkDenyIdentityRead}, - {name: "IdentityBarWriteDenied", prefix: "fail", check: checkDenyIdentityWrite}, - }, - }, - { - name: "IdentityDefaultDenyPolicyComplex", - defaultPolicy: DenyAll(), - policyStack: []*Policy{ - { - PolicyRules: PolicyRules{ - Identities: []*IdentityRule{ - { - Name: "football", - Policy: PolicyRead, - }, - { - Name: "prefix-forbidden", - Policy: PolicyDeny, - Intentions: PolicyDeny, - }, - }, - IdentityPrefixes: []*IdentityRule{ - { - Name: "foo", - Policy: PolicyWrite, - Intentions: PolicyWrite, - }, - { - Name: "prefix", - Policy: PolicyRead, - Intentions: PolicyWrite, - }, - }, - }, - }, - { - PolicyRules: PolicyRules{ - Identities: []*IdentityRule{ - { - Name: "foozball", - Policy: PolicyWrite, - Intentions: PolicyRead, - }, - }, - }, - }, - }, - checks: []aclCheck{ - {name: "IdentityReadAllowed", prefix: "foo", check: checkAllowIdentityRead}, - {name: "IdentityWriteAllowed", prefix: "foo", check: checkAllowIdentityWrite}, - {name: "TrafficPermissionsReadAllowed", prefix: "foo", check: checkAllowTrafficPermissionsRead}, - {name: "TrafficPermissionsWriteAllowed", prefix: "foo", check: checkAllowTrafficPermissionsWrite}, - {name: "IdentityReadAllowed", prefix: "football", check: checkAllowIdentityRead}, - {name: "IdentityWriteDenied", prefix: "football", check: checkDenyIdentityWrite}, - {name: "TrafficPermissionsReadAllowed", prefix: "football", check: checkAllowTrafficPermissionsRead}, - // This might be surprising but omitting intention rule gives at most intention:read - // if we have identity:write perms. This matches services as well. - {name: "TrafficPermissionsWriteDenied", prefix: "football", check: checkDenyTrafficPermissionsWrite}, - {name: "IdentityReadAllowed", prefix: "prefix", check: checkAllowIdentityRead}, - {name: "IdentityWriteDenied", prefix: "prefix", check: checkDenyIdentityWrite}, - {name: "TrafficPermissionsReadAllowed", prefix: "prefix", check: checkAllowTrafficPermissionsRead}, - {name: "TrafficPermissionsWriteDenied", prefix: "prefix", check: checkAllowTrafficPermissionsWrite}, - {name: "IdentityReadDenied", prefix: "prefix-forbidden", check: checkDenyIdentityRead}, - {name: "IdentityWriteDenied", prefix: "prefix-forbidden", check: checkDenyIdentityWrite}, - {name: "TrafficPermissionsReadDenied", prefix: "prefix-forbidden", check: checkDenyTrafficPermissionsRead}, - {name: "TrafficPermissionsWriteDenied", prefix: "prefix-forbidden", check: checkDenyTrafficPermissionsWrite}, - {name: "IdentityReadAllowed", prefix: "foozball", check: checkAllowIdentityRead}, - {name: "IdentityWriteAllowed", prefix: "foozball", check: checkAllowIdentityWrite}, - {name: "TrafficPermissionsReadAllowed", prefix: "foozball", check: checkAllowTrafficPermissionsRead}, - {name: "TrafficPermissionsWriteDenied", prefix: "foozball", check: checkDenyTrafficPermissionsWrite}, - }, - }, { name: "KeyringDefaultAllowPolicyDeny", defaultPolicy: AllowAll(), diff --git a/acl/authorizer.go b/acl/authorizer.go index 9e5bacc25e86..937d861129dc 100644 --- a/acl/authorizer.go +++ b/acl/authorizer.go @@ -43,7 +43,6 @@ const ( ResourceACL Resource = "acl" ResourceAgent Resource = "agent" ResourceEvent Resource = "event" - ResourceIdentity Resource = "identity" ResourceIntention Resource = "intention" ResourceKey Resource = "key" ResourceKeyring Resource = "keyring" @@ -78,21 +77,12 @@ type Authorizer interface { // EventWrite determines if a specific event may be fired. EventWrite(string, *AuthorizerContext) EnforcementDecision - // IdentityRead checks for permission to read a given workload identity. - IdentityRead(string, *AuthorizerContext) EnforcementDecision - - // IdentityReadAll checks for permission to read all workload identities. - IdentityReadAll(*AuthorizerContext) EnforcementDecision - - // IdentityWrite checks for permission to create or update a given - // workload identity. - IdentityWrite(string, *AuthorizerContext) EnforcementDecision - - // IdentityWriteAny checks for write permission on any workload identity. - IdentityWriteAny(*AuthorizerContext) EnforcementDecision - // IntentionDefaultAllow determines the default authorized behavior // when no intentions match a Connect request. + // + // Deprecated: Use DefaultIntentionPolicy under agent configuration. + // Moving forwards, intentions will not inherit default allow behavior + // from the ACL system. IntentionDefaultAllow(*AuthorizerContext) EnforcementDecision // IntentionRead determines if a specific intention can be read. @@ -263,51 +253,6 @@ func (a AllowAuthorizer) EventWriteAllowed(name string, ctx *AuthorizerContext) return nil } -// IdentityReadAllowed checks for permission to read a given workload identity, -func (a AllowAuthorizer) IdentityReadAllowed(name string, ctx *AuthorizerContext) error { - if a.Authorizer.IdentityRead(name, ctx) != Allow { - return PermissionDeniedByACL(a, ctx, ResourceIdentity, AccessRead, name) - } - return nil -} - -// IdentityReadAllAllowed checks for permission to read all workload identities. -func (a AllowAuthorizer) IdentityReadAllAllowed(ctx *AuthorizerContext) error { - if a.Authorizer.IdentityReadAll(ctx) != Allow { - // This is only used to gate certain UI functions right now (e.g metrics) - return PermissionDeniedByACL(a, ctx, ResourceIdentity, AccessRead, "all identities") // read - } - return nil -} - -// IdentityWriteAllowed checks for permission to create or update a given -// workload identity. -func (a AllowAuthorizer) IdentityWriteAllowed(name string, ctx *AuthorizerContext) error { - if a.Authorizer.IdentityWrite(name, ctx) != Allow { - return PermissionDeniedByACL(a, ctx, ResourceIdentity, AccessWrite, name) - } - return nil -} - -// IdentityWriteAnyAllowed checks for write permission on any workload identity -func (a AllowAuthorizer) IdentityWriteAnyAllowed(ctx *AuthorizerContext) error { - if a.Authorizer.IdentityWriteAny(ctx) != Allow { - return PermissionDeniedByACL(a, ctx, ResourceIdentity, AccessWrite, "any identity") - } - return nil -} - -// IntentionDefaultAllowAllowed determines the default authorized behavior -// when no intentions match a Connect request. -func (a AllowAuthorizer) IntentionDefaultAllowAllowed(ctx *AuthorizerContext) error { - if a.Authorizer.IntentionDefaultAllow(ctx) != Allow { - // This is a bit nuanced, in that this isn't set by a rule, but inherited globally - // TODO(acl-error-enhancements) revisit when we have full accessor info - return PermissionDeniedError{Cause: "Denied by intention default"} - } - return nil -} - // IntentionReadAllowed determines if a specific intention can be read. func (a AllowAuthorizer) IntentionReadAllowed(name string, ctx *AuthorizerContext) error { if a.Authorizer.IntentionRead(name, ctx) != Allow { @@ -586,13 +531,6 @@ func Enforce(authz Authorizer, rsc Resource, segment string, access string, ctx case "write": return authz.EventWrite(segment, ctx), nil } - case ResourceIdentity: - switch lowerAccess { - case "read": - return authz.IdentityRead(segment, ctx), nil - case "write": - return authz.IdentityWrite(segment, ctx), nil - } case ResourceIntention: switch lowerAccess { case "read": diff --git a/acl/authorizer_test.go b/acl/authorizer_test.go index d538a04ad715..09cba85fa6b5 100644 --- a/acl/authorizer_test.go +++ b/acl/authorizer_test.go @@ -188,34 +188,6 @@ func TestACL_Enforce(t *testing.T) { ret: Deny, err: "Invalid access level", }, - { - method: "IdentityRead", - resource: ResourceIdentity, - segment: "foo", - access: "read", - ret: Deny, - }, - { - method: "IdentityRead", - resource: ResourceIdentity, - segment: "foo", - access: "read", - ret: Allow, - }, - { - method: "IdentityWrite", - resource: ResourceIdentity, - segment: "foo", - access: "write", - ret: Deny, - }, - { - method: "IdentityWrite", - resource: ResourceIdentity, - segment: "foo", - access: "write", - ret: Allow, - }, { method: "IntentionRead", resource: ResourceIntention, diff --git a/acl/chained_authorizer.go b/acl/chained_authorizer.go index 76e973d2e9ed..15016e984928 100644 --- a/acl/chained_authorizer.go +++ b/acl/chained_authorizer.go @@ -80,39 +80,11 @@ func (c *ChainedAuthorizer) EventWrite(name string, entCtx *AuthorizerContext) E }) } -// IdentityRead checks for permission to read a given workload identity. -func (c *ChainedAuthorizer) IdentityRead(name string, entCtx *AuthorizerContext) EnforcementDecision { - return c.executeChain(func(authz Authorizer) EnforcementDecision { - return authz.IdentityRead(name, entCtx) - }) -} - -// IdentityReadAll checks for permission to read all workload identities. -func (c *ChainedAuthorizer) IdentityReadAll(entCtx *AuthorizerContext) EnforcementDecision { - return c.executeChain(func(authz Authorizer) EnforcementDecision { - return authz.IdentityReadAll(entCtx) - }) -} - -// IdentityWrite checks for permission to create or update a given -// workload identity. -func (c *ChainedAuthorizer) IdentityWrite(name string, entCtx *AuthorizerContext) EnforcementDecision { - return c.executeChain(func(authz Authorizer) EnforcementDecision { - return authz.IdentityWrite(name, entCtx) - }) -} - -// IdentityWriteAny checks for write permission on any workload identity. -func (c *ChainedAuthorizer) IdentityWriteAny(entCtx *AuthorizerContext) EnforcementDecision { - return c.executeChain(func(authz Authorizer) EnforcementDecision { - return authz.IdentityWriteAny(entCtx) - }) -} - // IntentionDefaultAllow determines the default authorized behavior // when no intentions match a Connect request. func (c *ChainedAuthorizer) IntentionDefaultAllow(entCtx *AuthorizerContext) EnforcementDecision { return c.executeChain(func(authz Authorizer) EnforcementDecision { + //nolint:staticcheck return authz.IntentionDefaultAllow(entCtx) }) } diff --git a/acl/policy.go b/acl/policy.go index 0c88a9041b28..86c9e83cfc58 100644 --- a/acl/policy.go +++ b/acl/policy.go @@ -59,8 +59,6 @@ type PolicyRules struct { ACL string `hcl:"acl,expand"` Agents []*AgentRule `hcl:"agent,expand"` AgentPrefixes []*AgentRule `hcl:"agent_prefix,expand"` - Identities []*IdentityRule `hcl:"identity,expand"` - IdentityPrefixes []*IdentityRule `hcl:"identity_prefix,expand"` Keys []*KeyRule `hcl:"key,expand"` KeyPrefixes []*KeyRule `hcl:"key_prefix,expand"` Nodes []*NodeRule `hcl:"node,expand"` @@ -77,6 +75,11 @@ type PolicyRules struct { Operator string `hcl:"operator"` Mesh string `hcl:"mesh"` Peering string `hcl:"peering"` + + // Deprecated: exists just to track the former field for decoding + Identities []*IdentityRule `hcl:"identity,expand"` + // Deprecated: exists just to track the former field for decoding + IdentityPrefixes []*IdentityRule `hcl:"identity_prefix,expand"` } // Policy is used to represent the policy specified by an ACL configuration. @@ -93,6 +96,8 @@ type AgentRule struct { } // IdentityRule represents a policy for a workload identity +// +// Deprecated: exists just to track the former field for decoding type IdentityRule struct { Name string `hcl:",key"` Policy string @@ -183,29 +188,9 @@ func (pr *PolicyRules) Validate(conf *Config) error { } } - // Validate the identity policies - for _, id := range pr.Identities { - if !isPolicyValid(id.Policy, false) { - return fmt.Errorf("Invalid identity policy: %#v", id) - } - if id.Intentions != "" && !isPolicyValid(id.Intentions, false) { - return fmt.Errorf("Invalid identity intentions policy: %#v", id) - } - if err := id.EnterpriseRule.Validate(id.Policy, conf); err != nil { - return fmt.Errorf("Invalid identity enterprise policy: %#v, got error: %v", id, err) - } - } - for _, id := range pr.IdentityPrefixes { - if !isPolicyValid(id.Policy, false) { - return fmt.Errorf("Invalid identity_prefix policy: %#v", id) - } - if id.Intentions != "" && !isPolicyValid(id.Intentions, false) { - return fmt.Errorf("Invalid identity_prefix intentions policy: %#v", id) - } - if err := id.EnterpriseRule.Validate(id.Policy, conf); err != nil { - return fmt.Errorf("Invalid identity_prefix enterprise policy: %#v, got error: %v", id, err) - } - } + // Identity rules are deprecated, zero them out. + pr.Identities = nil + pr.IdentityPrefixes = nil // Validate the key policy for _, kp := range pr.Keys { diff --git a/acl/policy_authorizer.go b/acl/policy_authorizer.go index 11d19609efde..16ffa743f95e 100644 --- a/acl/policy_authorizer.go +++ b/acl/policy_authorizer.go @@ -14,9 +14,6 @@ type policyAuthorizer struct { // agentRules contain the exact-match agent policies agentRules *radix.Tree - // identityRules contains the identity exact-match policies - identityRules *radix.Tree - // intentionRules contains the service intention exact-match policies intentionRules *radix.Tree @@ -186,48 +183,6 @@ func (p *policyAuthorizer) loadRules(policy *PolicyRules) error { } } - // Load the identity policy (exact matches) - for _, id := range policy.Identities { - if err := insertPolicyIntoRadix(id.Name, id.Policy, &id.EnterpriseRule, p.identityRules, false); err != nil { - return err - } - - intention := id.Intentions - if intention == "" { - switch id.Policy { - case PolicyRead, PolicyWrite: - intention = PolicyRead - default: - intention = PolicyDeny - } - } - - if err := insertPolicyIntoRadix(id.Name, intention, &id.EnterpriseRule, p.trafficPermissionsRules, false); err != nil { - return err - } - } - - // Load the identity policy (prefix matches) - for _, id := range policy.IdentityPrefixes { - if err := insertPolicyIntoRadix(id.Name, id.Policy, &id.EnterpriseRule, p.identityRules, true); err != nil { - return err - } - - intention := id.Intentions - if intention == "" { - switch id.Policy { - case PolicyRead, PolicyWrite: - intention = PolicyRead - default: - intention = PolicyDeny - } - } - - if err := insertPolicyIntoRadix(id.Name, intention, &id.EnterpriseRule, p.trafficPermissionsRules, true); err != nil { - return err - } - } - // Load the key policy (exact matches) for _, kp := range policy.Keys { if err := insertPolicyIntoRadix(kp.Prefix, kp.Policy, &kp.EnterpriseRule, p.keyRules, false); err != nil { @@ -397,7 +352,6 @@ func newPolicyAuthorizer(policies []*Policy, ent *Config) (*policyAuthorizer, er func newPolicyAuthorizerFromRules(rules *PolicyRules, ent *Config) (*policyAuthorizer, error) { p := &policyAuthorizer{ agentRules: radix.New(), - identityRules: radix.New(), intentionRules: radix.New(), trafficPermissionsRules: radix.New(), keyRules: radix.New(), @@ -578,33 +532,6 @@ func (p *policyAuthorizer) EventWrite(name string, _ *AuthorizerContext) Enforce return Default } -// IdentityRead checks for permission to read a given workload identity. -func (p *policyAuthorizer) IdentityRead(name string, _ *AuthorizerContext) EnforcementDecision { - if rule, ok := getPolicy(name, p.identityRules); ok { - return enforce(rule.access, AccessRead) - } - return Default -} - -// IdentityReadAll checks for permission to read all workload identities. -func (p *policyAuthorizer) IdentityReadAll(_ *AuthorizerContext) EnforcementDecision { - return p.allAllowed(p.identityRules, AccessRead) -} - -// IdentityWrite checks for permission to create or update a given -// workload identity. -func (p *policyAuthorizer) IdentityWrite(name string, _ *AuthorizerContext) EnforcementDecision { - if rule, ok := getPolicy(name, p.identityRules); ok { - return enforce(rule.access, AccessWrite) - } - return Default -} - -// IdentityWriteAny checks for write permission on any workload identity. -func (p *policyAuthorizer) IdentityWriteAny(_ *AuthorizerContext) EnforcementDecision { - return p.anyAllowed(p.identityRules, AccessWrite) -} - // IntentionDefaultAllow returns whether the default behavior when there are // no matching intentions is to allow or deny. func (p *policyAuthorizer) IntentionDefaultAllow(_ *AuthorizerContext) EnforcementDecision { diff --git a/acl/policy_authorizer_test.go b/acl/policy_authorizer_test.go index 96272d8b12f4..a2f9b929f10f 100644 --- a/acl/policy_authorizer_test.go +++ b/acl/policy_authorizer_test.go @@ -41,9 +41,6 @@ func TestPolicyAuthorizer(t *testing.T) { {name: "DefaultAgentWrite", prefix: "foo", check: checkDefaultAgentWrite}, {name: "DefaultEventRead", prefix: "foo", check: checkDefaultEventRead}, {name: "DefaultEventWrite", prefix: "foo", check: checkDefaultEventWrite}, - {name: "DefaultIdentityRead", prefix: "foo", check: checkDefaultIdentityRead}, - {name: "DefaultIdentityWrite", prefix: "foo", check: checkDefaultIdentityWrite}, - {name: "DefaultIdentityWriteAny", prefix: "", check: checkDefaultIdentityWriteAny}, {name: "DefaultIntentionDefaultAllow", prefix: "foo", check: checkDefaultIntentionDefaultAllow}, {name: "DefaultIntentionRead", prefix: "foo", check: checkDefaultIntentionRead}, {name: "DefaultIntentionWrite", prefix: "foo", check: checkDefaultIntentionWrite}, @@ -190,29 +187,6 @@ func TestPolicyAuthorizer(t *testing.T) { Policy: PolicyRead, }, }, - Identities: []*IdentityRule{ - { - Name: "foo", - Policy: PolicyWrite, - Intentions: PolicyWrite, - }, - { - Name: "football", - Policy: PolicyDeny, - }, - }, - IdentityPrefixes: []*IdentityRule{ - { - Name: "foot", - Policy: PolicyRead, - Intentions: PolicyRead, - }, - { - Name: "fo", - Policy: PolicyRead, - Intentions: PolicyRead, - }, - }, Keys: []*KeyRule{ { Prefix: "foo", @@ -400,22 +374,6 @@ func TestPolicyAuthorizer(t *testing.T) { {name: "ServiceWriteAnyAllowed", prefix: "", check: checkAllowServiceWriteAny}, {name: "ServiceReadWithinPrefixDenied", prefix: "foot", check: checkDenyServiceReadPrefix}, - {name: "IdentityReadPrefixAllowed", prefix: "fo", check: checkAllowIdentityRead}, - {name: "IdentityWritePrefixDenied", prefix: "fo", check: checkDenyIdentityWrite}, - {name: "IdentityReadPrefixAllowed", prefix: "for", check: checkAllowIdentityRead}, - {name: "IdentityWritePrefixDenied", prefix: "for", check: checkDenyIdentityWrite}, - {name: "IdentityReadAllowed", prefix: "foo", check: checkAllowIdentityRead}, - {name: "IdentityWriteAllowed", prefix: "foo", check: checkAllowIdentityWrite}, - {name: "IdentityReadPrefixAllowed", prefix: "foot", check: checkAllowIdentityRead}, - {name: "IdentityWritePrefixDenied", prefix: "foot", check: checkDenyIdentityWrite}, - {name: "IdentityReadPrefixAllowed", prefix: "foot2", check: checkAllowIdentityRead}, - {name: "IdentityWritePrefixDenied", prefix: "foot2", check: checkDenyIdentityWrite}, - {name: "IdentityReadPrefixAllowed", prefix: "food", check: checkAllowIdentityRead}, - {name: "IdentityWritePrefixDenied", prefix: "food", check: checkDenyIdentityWrite}, - {name: "IdentityReadDenied", prefix: "football", check: checkDenyIdentityRead}, - {name: "IdentityWriteDenied", prefix: "football", check: checkDenyIdentityWrite}, - {name: "IdentityWriteAnyAllowed", prefix: "", check: checkAllowIdentityWriteAny}, - {name: "IntentionReadPrefixAllowed", prefix: "fo", check: checkAllowIntentionRead}, {name: "IntentionWritePrefixDenied", prefix: "fo", check: checkDenyIntentionWrite}, {name: "IntentionReadPrefixAllowed", prefix: "for", check: checkAllowIntentionRead}, diff --git a/acl/policy_test.go b/acl/policy_test.go index 599c8c977e1b..2ce0b32892fb 100644 --- a/acl/policy_test.go +++ b/acl/policy_test.go @@ -42,12 +42,6 @@ func TestPolicySourceParse(t *testing.T) { event "bar" { policy = "deny" } - identity_prefix "" { - policy = "write" - } - identity "foo" { - policy = "read" - } key_prefix "" { policy = "read" } @@ -123,16 +117,6 @@ func TestPolicySourceParse(t *testing.T) { "policy": "deny" } }, - "identity_prefix": { - "": { - "policy": "write" - } - }, - "identity": { - "foo": { - "policy": "read" - } - }, "key_prefix": { "": { "policy": "read" @@ -233,18 +217,6 @@ func TestPolicySourceParse(t *testing.T) { Policy: PolicyDeny, }, }, - IdentityPrefixes: []*IdentityRule{ - { - Name: "", - Policy: PolicyWrite, - }, - }, - Identities: []*IdentityRule{ - { - Name: "foo", - Policy: PolicyRead, - }, - }, Keyring: PolicyDeny, KeyPrefixes: []*KeyRule{ { @@ -331,39 +303,6 @@ func TestPolicySourceParse(t *testing.T) { }, }}, }, - { - Name: "Identity No Intentions", - Rules: `identity "foo" { policy = "write" }`, - RulesJSON: `{ "identity": { "foo": { "policy": "write" }}}`, - Expected: &Policy{PolicyRules: PolicyRules{ - Identities: []*IdentityRule{ - { - Name: "foo", - Policy: "write", - }, - }, - }}, - }, - { - Name: "Identity Intentions", - Rules: `identity "foo" { policy = "write" intentions = "read" }`, - RulesJSON: `{ "identity": { "foo": { "policy": "write", "intentions": "read" }}}`, - Expected: &Policy{PolicyRules: PolicyRules{ - Identities: []*IdentityRule{ - { - Name: "foo", - Policy: "write", - Intentions: "read", - }, - }, - }}, - }, - { - Name: "Identity Intention: invalid value", - Rules: `identity "foo" { policy = "write" intentions = "foo" }`, - RulesJSON: `{ "identity": { "foo": { "policy": "write", "intentions": "foo" }}}`, - Err: "Invalid identity intentions policy", - }, { Name: "Service No Intentions", Rules: `service "foo" { policy = "write" }`, @@ -415,18 +354,6 @@ func TestPolicySourceParse(t *testing.T) { RulesJSON: `{ "agent_prefix": { "foo": { "policy": "nope" }}}`, Err: "Invalid agent_prefix policy", }, - { - Name: "Bad Policy - Identity", - Rules: `identity "foo" { policy = "nope" }`, - RulesJSON: `{ "identity": { "foo": { "policy": "nope" }}}`, - Err: "Invalid identity policy", - }, - { - Name: "Bad Policy - Identity Prefix", - Rules: `identity_prefix "foo" { policy = "nope" }`, - RulesJSON: `{ "identity_prefix": { "foo": { "policy": "nope" }}}`, - Err: "Invalid identity_prefix policy", - }, { Name: "Bad Policy - Key", Rules: `key "foo" { policy = "nope" }`, @@ -758,109 +685,6 @@ func TestMergePolicies(t *testing.T) { }, }}, }, - { - name: "Identities", - input: []*Policy{ - {PolicyRules: PolicyRules{ - Identities: []*IdentityRule{ - { - Name: "foo", - Policy: PolicyWrite, - Intentions: PolicyWrite, - }, - { - Name: "bar", - Policy: PolicyRead, - Intentions: PolicyRead, - }, - { - Name: "baz", - Policy: PolicyWrite, - Intentions: PolicyWrite, - }, - }, - IdentityPrefixes: []*IdentityRule{ - { - Name: "000", - Policy: PolicyWrite, - Intentions: PolicyWrite, - }, - { - Name: "111", - Policy: PolicyRead, - Intentions: PolicyRead, - }, - { - Name: "222", - Policy: PolicyWrite, - Intentions: PolicyWrite, - }, - }, - }}, - {PolicyRules: PolicyRules{ - Identities: []*IdentityRule{ - { - Name: "foo", - Policy: PolicyRead, - Intentions: PolicyRead, - }, - { - Name: "baz", - Policy: PolicyDeny, - Intentions: PolicyDeny, - }, - }, - IdentityPrefixes: []*IdentityRule{ - { - Name: "000", - Policy: PolicyRead, - Intentions: PolicyRead, - }, - { - Name: "222", - Policy: PolicyDeny, - Intentions: PolicyDeny, - }, - }, - }}, - }, - expected: &Policy{PolicyRules: PolicyRules{ - Identities: []*IdentityRule{ - { - Name: "foo", - Policy: PolicyWrite, - Intentions: PolicyWrite, - }, - { - Name: "bar", - Policy: PolicyRead, - Intentions: PolicyRead, - }, - { - Name: "baz", - Policy: PolicyDeny, - Intentions: PolicyDeny, - }, - }, - IdentityPrefixes: []*IdentityRule{ - { - Name: "000", - Policy: PolicyWrite, - Intentions: PolicyWrite, - }, - { - Name: "111", - Policy: PolicyRead, - Intentions: PolicyRead, - }, - { - Name: "222", - Policy: PolicyDeny, - Intentions: PolicyDeny, - }, - }, - }}, - }, { name: "Node", input: []*Policy{ diff --git a/acl/validation.go b/acl/validation.go index c0017effa15d..652a76e87930 100644 --- a/acl/validation.go +++ b/acl/validation.go @@ -68,6 +68,10 @@ func IsValidRoleName(name string) bool { return validRoleName.MatchString(name) } +func IsValidPolicyName(name string) bool { + return ValidatePolicyName(name) == nil +} + // IsValidRoleName returns true if the provided name can be used as an // ACLAuthMethod Name. func IsValidAuthMethodName(name string) bool { diff --git a/agent/acl_endpoint.go b/agent/acl_endpoint.go index fb94862800eb..ac773c59b443 100644 --- a/agent/acl_endpoint.go +++ b/agent/acl_endpoint.go @@ -1166,6 +1166,7 @@ func (s *HTTPHandlers) ACLTemplatedPoliciesList(resp http.ResponseWriter, req *h TemplateName: tmpBase.TemplateName, Schema: tmpBase.Schema, Template: tmpBase.Template, + Description: tmpBase.Description, } } @@ -1211,6 +1212,7 @@ func (s *HTTPHandlers) ACLTemplatedPolicyRead(resp http.ResponseWriter, req *htt TemplateName: baseTemplate.TemplateName, Schema: baseTemplate.Schema, Template: baseTemplate.Template, + Description: baseTemplate.Description, }, nil } diff --git a/agent/acl_endpoint_test.go b/agent/acl_endpoint_test.go index 7ce090204d82..7b484e092b5b 100644 --- a/agent/acl_endpoint_test.go +++ b/agent/acl_endpoint_test.go @@ -14,9 +14,10 @@ import ( "testing" "time" - "github.com/hashicorp/go-uuid" + "github.com/go-jose/go-jose/v3/jwt" "github.com/stretchr/testify/require" - "gopkg.in/square/go-jose.v2/jwt" + + "github.com/hashicorp/go-uuid" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/authmethod/testauth" @@ -1361,6 +1362,39 @@ func TestACL_HTTP(t *testing.T) { require.Len(t, token.ServiceIdentities, 1) require.Equal(t, "sn1", token.ServiceIdentities[0].ServiceName) }) + + t.Run("List by ServiceName based on templated policies", func(t *testing.T) { + tokenInput := &structs.ACLToken{ + Description: "token for templated policies service", + TemplatedPolicies: []*structs.ACLTemplatedPolicy{ + { + TemplateName: "builtin/service", + TemplateVariables: &structs.ACLTemplatedPolicyVariables{ + Name: "service1", + }, + }, + }, + } + + req, _ := http.NewRequest("PUT", "/v1/acl/token", jsonBody(tokenInput)) + req.Header.Add("X-Consul-Token", "root") + resp := httptest.NewRecorder() + _, err := a.srv.ACLTokenCreate(resp, req) + require.NoError(t, err) + + req, _ = http.NewRequest("GET", "/v1/acl/tokens?servicename=service1", nil) + req.Header.Add("X-Consul-Token", "root") + resp = httptest.NewRecorder() + raw, err := a.srv.ACLTokenList(resp, req) + require.NoError(t, err) + tokens, ok := raw.(structs.ACLTokenListStubs) + require.True(t, ok) + require.Len(t, tokens, 1) + token := tokens[0] + require.Equal(t, "token for templated policies service", token.Description) + require.Len(t, token.TemplatedPolicies, 1) + require.Equal(t, "service1", token.TemplatedPolicies[0].TemplateVariables.Name) + }) }) t.Run("ACLTemplatedPolicy", func(t *testing.T) { @@ -1374,12 +1408,13 @@ func TestACL_HTTP(t *testing.T) { var list map[string]api.ACLTemplatedPolicyResponse require.NoError(t, json.NewDecoder(resp.Body).Decode(&list)) - require.Len(t, list, 5) + require.Len(t, list, 6) require.Equal(t, api.ACLTemplatedPolicyResponse{ TemplateName: api.ACLTemplatedPolicyServiceName, Schema: structs.ACLTemplatedPolicyServiceSchema, Template: structs.ACLTemplatedPolicyService, + Description: structs.ACLTemplatedPolicyServiceDescription, }, list[api.ACLTemplatedPolicyServiceName]) }) t.Run("Read", func(t *testing.T) { @@ -1402,6 +1437,7 @@ func TestACL_HTTP(t *testing.T) { var templatedPolicy api.ACLTemplatedPolicyResponse require.NoError(t, json.NewDecoder(resp.Body).Decode(&templatedPolicy)) require.Equal(t, structs.ACLTemplatedPolicyNoRequiredVariablesSchema, templatedPolicy.Schema) + require.Equal(t, structs.ACLTemplatedPolicyDNSDescription, templatedPolicy.Description) require.Equal(t, api.ACLTemplatedPolicyDNSName, templatedPolicy.TemplateName) require.Equal(t, structs.ACLTemplatedPolicyDNS, templatedPolicy.Template) }) @@ -2182,7 +2218,7 @@ func TestACL_Authorize(t *testing.T) { } t.Parallel() - a1 := NewTestAgent(t, TestACLConfigWithParams(nil)) + a1 := NewTestAgent(t, TestACLConfigWithParams(nil), TestAgentOpts{DisableACLBootstrapCheck: true}) defer a1.Shutdown() testrpc.WaitForTestAgent(t, a1.RPC, "dc1", testrpc.WithToken(TestDefaultInitialManagementToken)) @@ -2190,7 +2226,7 @@ func TestACL_Authorize(t *testing.T) { policyReq := structs.ACLPolicySetRequest{ Policy: structs.ACLPolicy{ Name: "test", - Rules: `acl = "read" operator = "write" identity_prefix "" { policy = "read"} service_prefix "" { policy = "read"} node_prefix "" { policy= "write" } key_prefix "/foo" { policy = "write" } `, + Rules: `acl = "read" operator = "write" service_prefix "" { policy = "read"} node_prefix "" { policy= "write" } key_prefix "/foo" { policy = "write" } `, }, Datacenter: "dc1", WriteRequest: structs.WriteRequest{Token: TestDefaultInitialManagementToken}, @@ -2218,7 +2254,7 @@ func TestACL_Authorize(t *testing.T) { secondaryParams.ReplicationToken = secondaryParams.InitialManagementToken secondaryParams.EnableTokenReplication = true - a2 := NewTestAgent(t, `datacenter = "dc2" `+TestACLConfigWithParams(secondaryParams)) + a2 := NewTestAgent(t, `datacenter = "dc2" `+TestACLConfigWithParams(secondaryParams), TestAgentOpts{DisableACLBootstrapCheck: true}) defer a2.Shutdown() addr := fmt.Sprintf("127.0.0.1:%d", a1.Config.SerfPortWAN) @@ -2276,16 +2312,6 @@ func TestACL_Authorize(t *testing.T) { Segment: "foo", Access: "write", }, - { - Resource: "identity", - Segment: "foo", - Access: "read", - }, - { - Resource: "identity", - Segment: "foo", - Access: "write", - }, { Resource: "intention", Segment: "foo", @@ -2436,16 +2462,6 @@ func TestACL_Authorize(t *testing.T) { Segment: "foo", Access: "write", }, - { - Resource: "identity", - Segment: "foo", - Access: "read", - }, - { - Resource: "identity", - Segment: "foo", - Access: "write", - }, { Resource: "intention", Segment: "foo", @@ -2552,8 +2568,6 @@ func TestACL_Authorize(t *testing.T) { false, // agent:write false, // event:read false, // event:write - true, // identity:read - false, // identity:write true, // intentions:read false, // intention:write false, // key:read diff --git a/agent/acl_test.go b/agent/acl_test.go index 0958db8db6fb..8c5eace1f116 100644 --- a/agent/acl_test.go +++ b/agent/acl_test.go @@ -11,6 +11,8 @@ import ( "time" "github.com/armon/go-metrics" + "github.com/stretchr/testify/require" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/serf/serf" @@ -21,12 +23,11 @@ import ( "github.com/hashicorp/consul/agent/local" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/types" - - "github.com/stretchr/testify/require" ) type authzResolver func(string) (structs.ACLIdentity, acl.Authorizer, error) @@ -128,7 +129,7 @@ func (a *TestACLAgent) ResolveTokenAndDefaultMeta(secretID string, entMeta *acl. } // All of these are stubs to satisfy the interface -func (a *TestACLAgent) GetLANCoordinate() (lib.CoordinateSet, error) { +func (a *TestACLAgent) GetLANCoordinate() (librtt.CoordinateSet, error) { return nil, fmt.Errorf("Unimplemented") } func (a *TestACLAgent) Leave() error { diff --git a/agent/ae/ae.go b/agent/ae/ae.go index f8b9a331d100..94db2a7cf036 100644 --- a/agent/ae/ae.go +++ b/agent/ae/ae.go @@ -152,14 +152,6 @@ const ( retryFullSyncState fsmState = "retryFullSync" ) -// HardDisableSync is like PauseSync but is one-way. It causes other -// Pause/Resume/Start operations to be completely ignored. -func (s *StateSyncer) HardDisableSync() { - s.pauseLock.Lock() - s.hardDisabled = true - s.pauseLock.Unlock() -} - // Run is the long running method to perform state synchronization // between local and remote servers. func (s *StateSyncer) Run() { diff --git a/agent/agent.go b/agent/agent.go index dca7bf948739..a509ea2b3445 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -24,6 +24,12 @@ import ( "github.com/armon/go-metrics" "github.com/armon/go-metrics/prometheus" + "github.com/rboyer/safeio" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" + "google.golang.org/grpc" + "google.golang.org/grpc/keepalive" + "github.com/hashicorp/go-connlimit" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-memdb" @@ -31,10 +37,6 @@ import ( "github.com/hashicorp/hcp-scada-provider/capability" "github.com/hashicorp/raft" "github.com/hashicorp/serf/serf" - "golang.org/x/net/http2" - "golang.org/x/net/http2/h2c" - "google.golang.org/grpc" - "google.golang.org/grpc/keepalive" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl/resolver" @@ -46,7 +48,6 @@ import ( "github.com/hashicorp/consul/agent/consul" rpcRate "github.com/hashicorp/consul/agent/consul/rate" "github.com/hashicorp/consul/agent/consul/servercert" - "github.com/hashicorp/consul/agent/dns" external "github.com/hashicorp/consul/agent/grpc-external" grpcDNS "github.com/hashicorp/consul/agent/grpc-external/services/dns" middleware "github.com/hashicorp/consul/agent/grpc-middleware" @@ -66,7 +67,8 @@ import ( "github.com/hashicorp/consul/agent/xds" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api/watch" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" + libdns "github.com/hashicorp/consul/internal/dnsutil" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/file" @@ -74,6 +76,7 @@ import ( "github.com/hashicorp/consul/lib/routine" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/pbconfigentry" "github.com/hashicorp/consul/proto/private/pboperator" "github.com/hashicorp/consul/proto/private/pbpeering" "github.com/hashicorp/consul/tlsutil" @@ -184,7 +187,7 @@ type delegate interface { // are ancillary members of. // // NOTE: This assumes coordinates are enabled, so check that before calling. - GetLANCoordinate() (lib.CoordinateSet, error) + GetLANCoordinate() (librtt.CoordinateSet, error) // JoinLAN is used to have Consul join the inner-DC pool The target address // should be another node inside the DC listening on the Serf LAN address @@ -216,6 +219,14 @@ type notifier interface { Notify(string) error } +// dnsServer abstracts the implementations of the DNS server. +type dnsServer interface { + GetAddr() string + ListenAndServe(string, string, func()) error + ReloadConfig(*config.RuntimeConfig) error + Shutdown() +} + // Agent is the long running process that is run on every machine. // It exposes an RPC interface that is used by the CLI to control the // agent. The agent runs the query interfaces like HTTP, DNS, and RPC. @@ -229,6 +240,9 @@ type Agent struct { // config is the agent configuration. config *config.RuntimeConfig + displayOnlyConfigCopy *config.RuntimeConfig + displayOnlyConfigCopyLock sync.Mutex + // Used for writing our logs logger hclog.InterceptLogger @@ -335,7 +349,7 @@ type Agent struct { endpointsLock sync.RWMutex // dnsServer provides the DNS API - dnsServers []*DNSServer + dnsServers []dnsServer // apiServers listening for connections. If any of these server goroutines // fail, the agent will be shutdown. @@ -396,10 +410,11 @@ type Agent struct { // they can update their internal state. configReloaders []ConfigReloader - // TODO: pass directly to HTTPHandlers and DNSServer once those are passed + // TODO: pass directly to HTTPHandlers and dnsServer once those are passed // into Agent, which will allow us to remove this field. - rpcClientHealth *health.Client - rpcClientConfigEntry *configentry.Client + rpcClientHealth *health.Client + rpcClientConfigEntry *configentry.Client + grpcClientConfigEntry pbconfigentry.ConfigEntryServiceClient rpcClientPeering pbpeering.PeeringServiceClient @@ -502,6 +517,7 @@ func New(bd BaseDeps) (*Agent, error) { a.rpcClientPeering = pbpeering.NewPeeringServiceClient(conn) a.rpcClientOperator = pboperator.NewOperatorServiceClient(conn) + a.grpcClientConfigEntry = pbconfigentry.NewConfigEntryServiceClient(conn) a.serviceManager = NewServiceManager(&a) a.rpcClientConfigEntry = &configentry.Client{ @@ -622,9 +638,6 @@ func (a *Agent) Start(ctx context.Context) error { // create the state synchronization manager which performs // regular and on-demand state synchronizations (anti-entropy). a.sync = ae.NewStateSyncer(a.State, c.AEInterval, a.shutdownCh, a.logger) - if a.baseDeps.UseV2Resources() { - a.sync.HardDisableSync() - } err = validateFIPSConfig(a.config) if err != nil { @@ -656,10 +669,6 @@ func (a *Agent) Start(ctx context.Context) error { return fmt.Errorf("failed to start Consul enterprise component: %v", err) } - // proxyTracker will be used in the creation of the XDS server and also - // in the registration of the v2 xds controller - var proxyTracker *proxytracker.ProxyTracker - // Setup either the client or the server. var consulServer *consul.Server if c.ServerMode { @@ -696,15 +705,10 @@ func (a *Agent) Start(ctx context.Context) error { Time: a.config.GRPCKeepaliveInterval, Timeout: a.config.GRPCKeepaliveTimeout, }, + nil, ) - if a.baseDeps.UseV2Resources() { - proxyTracker = proxytracker.NewProxyTracker(proxytracker.ProxyTrackerConfig{ - Logger: a.logger.Named("proxy-tracker"), - SessionLimiter: a.baseDeps.XDSStreamLimiter, - }) - } - consulServer, err = consul.NewServer(consulCfg, a.baseDeps.Deps, a.externalGRPCServer, incomingRPCLimiter, serverLogger, proxyTracker) + consulServer, err = consul.NewServer(consulCfg, a.baseDeps.Deps, a.externalGRPCServer, incomingRPCLimiter, serverLogger) if err != nil { return fmt.Errorf("Failed to start Consul server: %v", err) } @@ -728,6 +732,11 @@ func (a *Agent) Start(ctx context.Context) error { } } } else { + // the conn is used to connect to the consul server agent + conn, err := a.baseDeps.GRPCConnPool.ClientConn(a.baseDeps.RuntimeConfig.Datacenter) + if err != nil { + return err + } a.externalGRPCServer = external.NewServer( a.logger.Named("grpc.external"), metrics.Default(), @@ -737,6 +746,7 @@ func (a *Agent) Start(ctx context.Context) error { Time: a.config.GRPCKeepaliveInterval, Timeout: a.config.GRPCKeepaliveTimeout, }, + conn, ) client, err := consul.NewClient(consulCfg, a.baseDeps.Deps) @@ -780,6 +790,15 @@ func (a *Agent) Start(ctx context.Context) error { return fmt.Errorf("unexpected ACL default policy value of %q", a.config.ACLResolverSettings.ACLDefaultPolicy) } + // If DefaultIntentionPolicy is defined, it should override + // the values inherited from ACLDefaultPolicy. + switch a.config.DefaultIntentionPolicy { + case "allow": + intentionDefaultAllow = true + case "deny": + intentionDefaultAllow = false + } + go a.baseDeps.ViewStore.Run(&lib.StopChannelContext{StopCh: a.shutdownCh}) // Start the proxy config manager. @@ -791,6 +810,7 @@ func (a *Agent) Start(ctx context.Context) error { Segment: a.config.SegmentName, Node: a.config.NodeName, NodePartition: a.config.PartitionOrEmpty(), + DisableNode: true, // Disable for agentless so that streaming RPCs can be used. }, DNSConfig: proxycfg.DNSConfig{ Domain: a.config.DNSDomain, @@ -857,7 +877,7 @@ func (a *Agent) Start(ctx context.Context) error { } // Start grpc and grpc_tls servers. - if err := a.listenAndServeGRPC(proxyTracker, consulServer); err != nil { + if err := a.listenAndServeGRPC(consulServer); err != nil { return err } @@ -895,17 +915,6 @@ func (a *Agent) Start(ctx context.Context) error { }() } - if a.scadaProvider != nil { - a.scadaProvider.UpdateMeta(map[string]string{ - "consul_server_id": string(a.config.NodeID), - }) - - if err = a.scadaProvider.Start(); err != nil { - a.baseDeps.Logger.Error("scada provider failed to start, some HashiCorp Cloud Platform functionality has been disabled", - "error", err, "resource_id", a.config.Cloud.ResourceID) - } - } - return nil } @@ -929,28 +938,20 @@ func (a *Agent) configureXDSServer(proxyWatcher xds.ProxyWatcher, server *consul // TODO(agentless): rather than asserting the concrete type of delegate, we // should add a method to the Delegate interface to build a ConfigSource. if server != nil { - switch proxyWatcher.(type) { - case *proxytracker.ProxyTracker: - go func() { - <-a.shutdownCh - proxyWatcher.(*proxytracker.ProxyTracker).Shutdown() - }() - default: - catalogCfg := catalogproxycfg.NewConfigSource(catalogproxycfg.Config{ - NodeName: a.config.NodeName, - LocalState: a.State, - LocalConfigSource: proxyWatcher, - Manager: a.proxyConfig, - GetStore: func() catalogproxycfg.Store { return server.FSM().State() }, - Logger: a.proxyConfig.Logger.Named("server-catalog"), - SessionLimiter: a.baseDeps.XDSStreamLimiter, - }) - go func() { - <-a.shutdownCh - catalogCfg.Shutdown() - }() - proxyWatcher = catalogCfg - } + catalogCfg := catalogproxycfg.NewConfigSource(catalogproxycfg.Config{ + NodeName: a.config.NodeName, + LocalState: a.State, + LocalConfigSource: proxyWatcher, + Manager: a.proxyConfig, + GetStore: func() catalogproxycfg.Store { return server.FSM().State() }, + Logger: a.proxyConfig.Logger.Named("server-catalog"), + SessionLimiter: a.baseDeps.XDSStreamLimiter, + }) + go func() { + <-a.shutdownCh + catalogCfg.Shutdown() + }() + proxyWatcher = catalogCfg } a.xdsServer = xds.NewServer( a.config.NodeName, @@ -964,16 +965,11 @@ func (a *Agent) configureXDSServer(proxyWatcher xds.ProxyWatcher, server *consul a.xdsServer.Register(a.externalGRPCServer) } -func (a *Agent) listenAndServeGRPC(proxyTracker *proxytracker.ProxyTracker, server *consul.Server) error { +func (a *Agent) listenAndServeGRPC(server *consul.Server) error { if len(a.config.GRPCAddrs) < 1 && len(a.config.GRPCTLSAddrs) < 1 { return nil } - var proxyWatcher xds.ProxyWatcher - if a.baseDeps.UseV2Resources() { - proxyWatcher = proxyTracker - } else { - proxyWatcher = localproxycfg.NewConfigSource(a.proxyConfig) - } + var proxyWatcher xds.ProxyWatcher = localproxycfg.NewConfigSource(a.proxyConfig) a.configureXDSServer(proxyWatcher, server) @@ -1196,7 +1192,7 @@ func (a *Agent) listenHTTP() ([]apiServer, error) { } httpAddrs := a.config.HTTPAddrs - if a.config.IsCloudEnabled() { + if a.config.IsCloudEnabled() && a.scadaProvider != nil { httpAddrs = append(httpAddrs, scada.CAPCoreAPI) } @@ -1597,7 +1593,7 @@ func newConsulConfig(runtimeCfg *config.RuntimeConfig, logger hclog.Logger) (*co cfg.RequestLimitsWriteRate = runtimeCfg.RequestLimitsWriteRate cfg.Locality = runtimeCfg.StructLocality() - cfg.Cloud.ManagementToken = runtimeCfg.Cloud.ManagementToken + cfg.Cloud = runtimeCfg.Cloud cfg.Reporting.License.Enabled = runtimeCfg.Reporting.License.Enabled @@ -1813,14 +1809,7 @@ func (a *Agent) ShutdownEndpoints() { ctx := context.TODO() for _, srv := range a.dnsServers { - if srv.Server != nil { - a.logger.Info("Stopping server", - "protocol", "DNS", - "address", srv.Server.Addr, - "network", srv.Server.Net, - ) - srv.Shutdown() - } + srv.Shutdown() } a.dnsServers = nil @@ -2032,7 +2021,7 @@ func (a *Agent) SyncPausedCh() <-chan struct{} { // GetLANCoordinate returns the coordinates of this node in the local pools // (assumes coordinates are enabled, so check that before calling). -func (a *Agent) GetLANCoordinate() (lib.CoordinateSet, error) { +func (a *Agent) GetLANCoordinate() (librtt.CoordinateSet, error) { return a.delegate.GetLANCoordinate() } @@ -2655,13 +2644,13 @@ func (a *Agent) validateService(service *structs.NodeService, chkTypes []*struct } // Warn if the service name is incompatible with DNS - if dns.InvalidNameRe.MatchString(service.Service) { + if libdns.InvalidNameRe.MatchString(service.Service) { a.logger.Warn("Service name will not be discoverable "+ "via DNS due to invalid characters. Valid characters include "+ "all alpha-numerics and dashes.", "service", service.Service, ) - } else if len(service.Service) > dns.MaxLabelLength { + } else if len(service.Service) > libdns.MaxLabelLength { a.logger.Warn("Service name will not be discoverable "+ "via DNS due to it being too long. Valid lengths are between "+ "1 and 63 bytes.", @@ -2671,13 +2660,13 @@ func (a *Agent) validateService(service *structs.NodeService, chkTypes []*struct // Warn if any tags are incompatible with DNS for _, tag := range service.Tags { - if dns.InvalidNameRe.MatchString(tag) { + if libdns.InvalidNameRe.MatchString(tag) { a.logger.Debug("Service tag will not be discoverable "+ "via DNS due to invalid characters. Valid characters include "+ "all alpha-numerics and dashes.", "tag", tag, ) - } else if len(tag) > dns.MaxLabelLength { + } else if len(tag) > libdns.MaxLabelLength { a.logger.Debug("Service tag will not be discoverable "+ "via DNS due to it being too long. Valid lengths are between "+ "1 and 63 bytes.", @@ -4352,11 +4341,22 @@ func (a *Agent) reloadConfigInternal(newCfg *config.RuntimeConfig) error { a.config.EnableDebug = newCfg.EnableDebug // update Agent config with new config - a.config = newCfg.DeepCopy() + a.displayOnlyConfigCopyLock.Lock() + a.displayOnlyConfigCopy = newCfg.DeepCopy() + a.displayOnlyConfigCopyLock.Unlock() return nil } +func (a *Agent) getRuntimeConfigForDisplay() *config.RuntimeConfig { + a.displayOnlyConfigCopyLock.Lock() + defer a.displayOnlyConfigCopyLock.Unlock() + if a.displayOnlyConfigCopy != nil { + return a.displayOnlyConfigCopy.DeepCopy() + } + return a.config +} + // LocalBlockingQuery performs a blocking query in a generic way against // local agent state that has no RPC or raft to back it. It uses `hash` parameter // instead of an `index`. @@ -4626,8 +4626,8 @@ func (a *Agent) proxyDataSources(server *consul.Server) proxycfg.DataSources { sources.Health = proxycfgglue.ServerHealthBlocking(deps, proxycfgglue.ClientHealth(a.rpcClientHealth)) sources.HTTPChecks = proxycfgglue.ServerHTTPChecks(deps, a.config.NodeName, proxycfgglue.CacheHTTPChecks(a.cache), a.State) sources.Intentions = proxycfgglue.ServerIntentions(deps) - sources.IntentionUpstreams = proxycfgglue.ServerIntentionUpstreams(deps) - sources.IntentionUpstreamsDestination = proxycfgglue.ServerIntentionUpstreamsDestination(deps) + sources.IntentionUpstreams = proxycfgglue.ServerIntentionUpstreams(deps, a.config.DefaultIntentionPolicy) + sources.IntentionUpstreamsDestination = proxycfgglue.ServerIntentionUpstreamsDestination(deps, a.config.DefaultIntentionPolicy) sources.InternalServiceDump = proxycfgglue.ServerInternalServiceDump(deps, proxycfgglue.CacheInternalServiceDump(a.cache)) sources.PeeringList = proxycfgglue.ServerPeeringList(deps) sources.PeeredUpstreams = proxycfgglue.ServerPeeredUpstreams(deps) @@ -4668,6 +4668,14 @@ func (a *Agent) persistServerMetadata() { continue } + // Use safeio.File to ensure the file is written to disk atomically + if sf, ok := f.(*safeio.File); ok { + if err := sf.Commit(); err != nil { + sf.Close() + a.logger.Error("failed to commit server metadata", "error", err) + continue + } + } f.Close() case <-a.shutdownCh: return @@ -4753,3 +4761,13 @@ func defaultIfEmpty(val, defaultVal string) string { } return defaultVal } + +func (a *Agent) getTokenFunc() func() string { + return func() string { + if a.tokens.DNSToken() != "" { + return a.tokens.DNSToken() + } else { + return a.tokens.UserToken() + } + } +} diff --git a/agent/agent_endpoint.go b/agent/agent_endpoint.go index 1048a2e65623..996212c97e70 100644 --- a/agent/agent_endpoint.go +++ b/agent/agent_endpoint.go @@ -11,14 +11,15 @@ import ( "strings" "time" + "github.com/mitchellh/hashstructure" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/hashicorp/go-bexpr" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-memdb" "github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/serf" - "github.com/mitchellh/hashstructure" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/hashicorp/consul/acl" cachetype "github.com/hashicorp/consul/agent/cache-types" @@ -30,8 +31,8 @@ import ( token_store "github.com/hashicorp/consul/agent/token" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/envoyextensions/xdscommon" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/ipaddr" - "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/logging/monitor" "github.com/hashicorp/consul/types" @@ -81,7 +82,7 @@ func (s *HTTPHandlers) AgentSelf(resp http.ResponseWriter, req *http.Request) (i return nil, err } - var cs lib.CoordinateSet + var cs librtt.CoordinateSet if !s.agent.config.DisableCoordinates { var err error if cs, err = s.agent.GetLANCoordinate(); err != nil { @@ -89,6 +90,8 @@ func (s *HTTPHandlers) AgentSelf(resp http.ResponseWriter, req *http.Request) (i } } + displayConfig := s.agent.getRuntimeConfigForDisplay() + var xds *XDSSelf if s.agent.xdsServer != nil { xds = &XDSSelf{ @@ -96,15 +99,15 @@ func (s *HTTPHandlers) AgentSelf(resp http.ResponseWriter, req *http.Request) (i "envoy": xdscommon.EnvoyVersions, }, // Prefer the TLS port. See comment on the XDSSelf struct for details. - Port: s.agent.config.GRPCTLSPort, + Port: displayConfig.GRPCTLSPort, Ports: GRPCPorts{ - Plaintext: s.agent.config.GRPCPort, - TLS: s.agent.config.GRPCTLSPort, + Plaintext: displayConfig.GRPCPort, + TLS: displayConfig.GRPCTLSPort, }, } // Fallback to standard port if TLS is not enabled. - if s.agent.config.GRPCTLSPort <= 0 { - xds.Port = s.agent.config.GRPCPort + if displayConfig.GRPCTLSPort <= 0 { + xds.Port = displayConfig.GRPCPort } } @@ -119,22 +122,22 @@ func (s *HTTPHandlers) AgentSelf(resp http.ResponseWriter, req *http.Request) (i Version string BuildDate string }{ - Datacenter: s.agent.config.Datacenter, - PrimaryDatacenter: s.agent.config.PrimaryDatacenter, - NodeName: s.agent.config.NodeName, - NodeID: string(s.agent.config.NodeID), - Partition: s.agent.config.PartitionOrEmpty(), - Revision: s.agent.config.Revision, - Server: s.agent.config.ServerMode, + Datacenter: displayConfig.Datacenter, + PrimaryDatacenter: displayConfig.PrimaryDatacenter, + NodeName: displayConfig.NodeName, + NodeID: string(displayConfig.NodeID), + Partition: displayConfig.PartitionOrEmpty(), + Revision: displayConfig.Revision, + Server: displayConfig.ServerMode, // We expect the ent version to be part of the reported version string, and that's now part of the metadata, not the actual version. - Version: s.agent.config.VersionWithMetadata(), - BuildDate: s.agent.config.BuildDate.Format(time.RFC3339), + Version: displayConfig.VersionWithMetadata(), + BuildDate: displayConfig.BuildDate.Format(time.RFC3339), } return Self{ Config: config, - DebugConfig: s.agent.config.Sanitized(), - Coord: cs[s.agent.config.SegmentName], + DebugConfig: displayConfig.Sanitized(), + Coord: cs[displayConfig.SegmentName], Member: s.agent.AgentLocalMember(), Stats: s.agent.Stats(), Meta: s.agent.State.Metadata(), @@ -1757,8 +1760,12 @@ func (s *HTTPHandlers) AgentConnectAuthorize(resp http.ResponseWriter, req *http // This is an L7 intention, so DENY. authorized = false } + } else if s.agent.config.DefaultIntentionPolicy != "" { + reason = "Default intention policy" + authorized = s.agent.config.DefaultIntentionPolicy == structs.IntentionDefaultPolicyAllow } else { reason = "Default behavior configured by ACLs" + //nolint:staticcheck authorized = authz.IntentionDefaultAllow(nil) == acl.Allow } diff --git a/agent/agent_endpoint_test.go b/agent/agent_endpoint_test.go index ab9a44ff9877..69551d7c3646 100644 --- a/agent/agent_endpoint_test.go +++ b/agent/agent_endpoint_test.go @@ -21,14 +21,15 @@ import ( "time" "github.com/armon/go-metrics" - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-uuid" - "github.com/hashicorp/serf/serf" "github.com/mitchellh/hashstructure" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/time/rate" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/serf/serf" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/agent/config" @@ -79,46 +80,6 @@ func createACLTokenWithAgentReadPolicy(t *testing.T, srv *HTTPHandlers) string { return svcToken.SecretID } -func TestAgentEndpointsFailInV2(t *testing.T) { - t.Parallel() - - a := NewTestAgent(t, `experiments = ["resource-apis"]`) - - checkRequest := func(method, url string) { - t.Run(method+" "+url, func(t *testing.T) { - assertV1CatalogEndpointDoesNotWorkWithV2(t, a, method, url, `{}`) - }) - } - - t.Run("agent-self-with-params", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/agent/self?dc=dc1", nil) - require.NoError(t, err) - - resp := httptest.NewRecorder() - a.srv.h.ServeHTTP(resp, req) - require.Equal(t, http.StatusOK, resp.Code) - - _, err = io.ReadAll(resp.Body) - require.NoError(t, err) - }) - - checkRequest("PUT", "/v1/agent/maintenance") - checkRequest("GET", "/v1/agent/services") - checkRequest("GET", "/v1/agent/service/web") - checkRequest("GET", "/v1/agent/checks") - checkRequest("GET", "/v1/agent/health/service/id/web") - checkRequest("GET", "/v1/agent/health/service/name/web") - checkRequest("PUT", "/v1/agent/check/register") - checkRequest("PUT", "/v1/agent/check/deregister/web") - checkRequest("PUT", "/v1/agent/check/pass/web") - checkRequest("PUT", "/v1/agent/check/warn/web") - checkRequest("PUT", "/v1/agent/check/fail/web") - checkRequest("PUT", "/v1/agent/check/update/web") - checkRequest("PUT", "/v1/agent/service/register") - checkRequest("PUT", "/v1/agent/service/deregister/web") - checkRequest("PUT", "/v1/agent/service/maintenance/web") -} - func TestAgent_Services(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") @@ -1660,6 +1621,7 @@ func newDefaultBaseDeps(t *testing.T) BaseDeps { } func TestHTTPHandlers_AgentMetricsStream_ACLDeny(t *testing.T) { + t.Skip("this test panics without a license manager in enterprise") bd := newDefaultBaseDeps(t) bd.Tokens = new(tokenStore.Store) sink := metrics.NewInmemSink(30*time.Millisecond, time.Second) @@ -1691,6 +1653,7 @@ func TestHTTPHandlers_AgentMetricsStream_ACLDeny(t *testing.T) { } func TestHTTPHandlers_AgentMetricsStream(t *testing.T) { + t.Skip("this test panics without a license manager in enterprise") bd := newDefaultBaseDeps(t) bd.Tokens = new(tokenStore.Store) sink := metrics.NewInmemSink(20*time.Millisecond, time.Second) @@ -1877,7 +1840,7 @@ func TestAgent_ReloadDoesNotTriggerWatch(t *testing.T) { require.NoError(t, a.updateTTLCheck(checkID, api.HealthPassing, "testing-agent-reload-001")) checkStr := func(r *retry.R, evaluator func(string) error) { - t.Helper() + r.Helper() contentsStr := "" // Wait for watch to be populated for i := 1; i < 7; i++ { @@ -1890,14 +1853,14 @@ func TestAgent_ReloadDoesNotTriggerWatch(t *testing.T) { break } time.Sleep(time.Duration(i) * time.Second) - testutil.Logger(t).Info("Watch not yet populated, retrying") + testutil.Logger(r).Info("Watch not yet populated, retrying") } if err := evaluator(contentsStr); err != nil { r.Errorf("ERROR: Test failing: %s", err) } } ensureNothingCritical := func(r *retry.R, mustContain string) { - t.Helper() + r.Helper() eval := func(contentsStr string) error { if strings.Contains(contentsStr, "critical") { return fmt.Errorf("MUST NOT contain critical:= %s", contentsStr) @@ -1915,7 +1878,7 @@ func TestAgent_ReloadDoesNotTriggerWatch(t *testing.T) { } retry.RunWith(retriesWithDelay(), t, func(r *retry.R) { - testutil.Logger(t).Info("Consul is now ready") + testutil.Logger(r).Info("Consul is now ready") // it should contain the output checkStr(r, func(contentStr string) error { if contentStr == "[]" { @@ -4340,7 +4303,7 @@ func testDefaultSidecar(svc string, port int, fns ...func(*structs.NodeService)) } // testCreateToken creates a Policy for the provided rules and a Token linked to that Policy. -func testCreateToken(t *testing.T, a *TestAgent, rules string) string { +func testCreateToken(t testutil.TestingTB, a *TestAgent, rules string) string { policyName, err := uuid.GenerateUUID() // we just need a unique name for the test and UUIDs are definitely unique require.NoError(t, err) @@ -4369,7 +4332,7 @@ func testCreateToken(t *testing.T, a *TestAgent, rules string) string { return aclResp.SecretID } -func testCreatePolicy(t *testing.T, a *TestAgent, name, rules string) string { +func testCreatePolicy(t testutil.TestingTB, a *TestAgent, name, rules string) string { args := map[string]interface{}{ "Name": name, "Rules": rules, @@ -8015,76 +7978,104 @@ func TestAgentConnectAuthorize_serviceWrite(t *testing.T) { assert.Equal(t, http.StatusForbidden, resp.Code) } -// Test when no intentions match w/ a default deny policy -func TestAgentConnectAuthorize_defaultDeny(t *testing.T) { +func TestAgentConnectAuthorize_DefaultIntentionPolicy(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } t.Parallel() - a := NewTestAgent(t, TestACLConfig()) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - args := &structs.ConnectAuthorizeRequest{ - Target: "foo", - ClientCertURI: connect.TestSpiffeIDService(t, "web").URI().String(), - } - req, _ := http.NewRequest("POST", "/v1/agent/connect/authorize", jsonReader(args)) - req.Header.Add("X-Consul-Token", "root") - resp := httptest.NewRecorder() - a.srv.h.ServeHTTP(resp, req) - assert.Equal(t, 200, resp.Code) - - dec := json.NewDecoder(resp.Body) - obj := &connectAuthorizeResp{} - require.NoError(t, dec.Decode(obj)) - assert.False(t, obj.Authorized) - assert.Contains(t, obj.Reason, "Default behavior") -} - -// Test when no intentions match w/ a default allow policy -func TestAgentConnectAuthorize_defaultAllow(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() + agentConfig := `primary_datacenter = "dc1" +default_intention_policy = "%s" +` + aclBlock := `acl { + enabled = true + default_policy = "%s" + tokens { + initial_management = "root" + agent = "root" + agent_recovery = "towel" + } +} +` + + type testcase struct { + aclsEnabled bool + defaultACL string + defaultIxn string + expectAuthz bool + expectReason string + } + tcs := map[string]testcase{ + "no ACLs, default intention allow": { + aclsEnabled: false, + defaultIxn: "allow", + expectAuthz: true, + expectReason: "Default intention policy", + }, + "no ACLs, default intention deny": { + aclsEnabled: false, + defaultIxn: "deny", + expectAuthz: false, + expectReason: "Default intention policy", + }, + "ACL deny, no intention policy": { + aclsEnabled: true, + defaultACL: "deny", + expectAuthz: false, + expectReason: "Default behavior configured by ACLs", + }, + "ACL allow, no intention policy": { + aclsEnabled: true, + defaultACL: "allow", + expectAuthz: true, + expectReason: "Default behavior configured by ACLs", + }, + "ACL deny, default intentions allow": { + aclsEnabled: true, + defaultACL: "deny", + defaultIxn: "allow", + expectAuthz: true, + expectReason: "Default intention policy", + }, + "ACL allow, default intentions deny": { + aclsEnabled: true, + defaultACL: "allow", + defaultIxn: "deny", + expectAuthz: false, + expectReason: "Default intention policy", + }, + } + for name, tc := range tcs { + tc := tc + t.Run(name, func(t *testing.T) { + t.Parallel() - dc1 := "dc1" - a := NewTestAgent(t, ` - primary_datacenter = "`+dc1+`" + conf := fmt.Sprintf(agentConfig, tc.defaultIxn) + if tc.aclsEnabled { + conf += fmt.Sprintf(aclBlock, tc.defaultACL) + } + a := NewTestAgent(t, conf) - acl { - enabled = true - default_policy = "allow" + testrpc.WaitForLeader(t, a.RPC, "dc1") - tokens { - initial_management = "root" - agent = "root" - agent_recovery = "towel" + args := &structs.ConnectAuthorizeRequest{ + Target: "foo", + ClientCertURI: connect.TestSpiffeIDService(t, "web").URI().String(), } - } - `) - defer a.Shutdown() - testrpc.WaitForTestAgent(t, a.RPC, dc1) + req, _ := http.NewRequest("POST", "/v1/agent/connect/authorize", jsonReader(args)) + req.Header.Add("X-Consul-Token", "root") + resp := httptest.NewRecorder() + a.srv.h.ServeHTTP(resp, req) + assert.Equal(t, 200, resp.Code) - args := &structs.ConnectAuthorizeRequest{ - Target: "foo", - ClientCertURI: connect.TestSpiffeIDService(t, "web").URI().String(), + dec := json.NewDecoder(resp.Body) + obj := &connectAuthorizeResp{} + require.NoError(t, dec.Decode(obj)) + assert.Equal(t, tc.expectAuthz, obj.Authorized) + assert.Contains(t, obj.Reason, tc.expectReason) + }) } - req, _ := http.NewRequest("POST", "/v1/agent/connect/authorize", jsonReader(args)) - req.Header.Add("X-Consul-Token", "root") - resp := httptest.NewRecorder() - a.srv.h.ServeHTTP(resp, req) - assert.Equal(t, 200, resp.Code) - - dec := json.NewDecoder(resp.Body) - obj := &connectAuthorizeResp{} - require.NoError(t, dec.Decode(obj)) - assert.True(t, obj.Authorized) - assert.Contains(t, obj.Reason, "Default behavior") } func TestAgent_Host(t *testing.T) { diff --git a/agent/agent_test.go b/agent/agent_test.go index 0b17190dd611..316adeb3ddf1 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -29,21 +29,21 @@ import ( "testing" "time" + "github.com/go-jose/go-jose/v3/jwt" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/tcpproxy" - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/hcp-scada-provider/capability" - "github.com/hashicorp/serf/coordinate" - "github.com/hashicorp/serf/serf" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" "golang.org/x/time/rate" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/protojson" - "gopkg.in/square/go-jose.v2/jwt" + + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/hcp-scada-provider/capability" + "github.com/hashicorp/serf/coordinate" + "github.com/hashicorp/serf/serf" "github.com/hashicorp/consul/agent/cache" cachetype "github.com/hashicorp/consul/agent/cache-types" @@ -58,9 +58,9 @@ import ( "github.com/hashicorp/consul/agent/token" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/internal/go-sso/oidcauth/oidcauthtest" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/ipaddr" - "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/proto/private/pbautoconf" "github.com/hashicorp/consul/sdk/freeport" "github.com/hashicorp/consul/sdk/testutil" @@ -90,7 +90,7 @@ func requireServiceMissing(t *testing.T, a *TestAgent, id string) { require.Nil(t, getService(a, id), "have service %q (expected missing)", id) } -func requireCheckExists(t *testing.T, a *TestAgent, id types.CheckID) *structs.HealthCheck { +func requireCheckExists(t testutil.TestingTB, a *TestAgent, id types.CheckID) *structs.HealthCheck { t.Helper() chk := getCheck(a, id) require.NotNil(t, chk, "missing check %q", id) @@ -853,7 +853,7 @@ func TestAgent_CheckAliasRPC(t *testing.T) { assert.NoError(t, err) retry.Run(t, func(r *retry.R) { - t.Helper() + r.Helper() var args structs.NodeSpecificRequest args.Datacenter = "dc1" args.Node = "node1" @@ -1888,7 +1888,7 @@ func TestAgent_RestoreServiceWithAliasCheck(t *testing.T) { // We do this so that the agent logs and the informational messages from // the test itself are interwoven properly. - logf := func(t *testing.T, a *TestAgent, format string, args ...interface{}) { + logf := func(a *TestAgent, format string, args ...interface{}) { a.logger.Info("testharness: " + fmt.Sprintf(format, args...)) } @@ -1947,12 +1947,12 @@ func TestAgent_RestoreServiceWithAliasCheck(t *testing.T) { retryUntilCheckState := func(t *testing.T, a *TestAgent, checkID string, expectedStatus string) { t.Helper() retry.Run(t, func(r *retry.R) { - chk := requireCheckExists(t, a, types.CheckID(checkID)) + chk := requireCheckExists(r, a, types.CheckID(checkID)) if chk.Status != expectedStatus { - logf(t, a, "check=%q expected status %q but got %q", checkID, expectedStatus, chk.Status) + logf(a, "check=%q expected status %q but got %q", checkID, expectedStatus, chk.Status) r.Fatalf("check=%q expected status %q but got %q", checkID, expectedStatus, chk.Status) } - logf(t, a, "check %q has reached desired status %q", checkID, expectedStatus) + logf(a, "check %q has reached desired status %q", checkID, expectedStatus) }) } @@ -1963,7 +1963,7 @@ func TestAgent_RestoreServiceWithAliasCheck(t *testing.T) { retryUntilCheckState(t, a, "service:ping", api.HealthPassing) retryUntilCheckState(t, a, "service:ping-sidecar-proxy", api.HealthPassing) - logf(t, a, "==== POWERING DOWN ORIGINAL ====") + logf(a, "==== POWERING DOWN ORIGINAL ====") require.NoError(t, a.Shutdown()) @@ -1985,7 +1985,7 @@ node_name = "` + a.Config.NodeName + `" // reregister during standup; we use an adjustable timing to try and force a race sleepDur := time.Duration(idx+1) * 500 * time.Millisecond time.Sleep(sleepDur) - logf(t, a2, "re-registering checks and services after a delay of %v", sleepDur) + logf(a2, "re-registering checks and services after a delay of %v", sleepDur) for i := 0; i < 20; i++ { // RACE RACE RACE! registerServicesAndChecks(t, a2) time.Sleep(50 * time.Millisecond) @@ -1995,7 +1995,7 @@ node_name = "` + a.Config.NodeName + `" retryUntilCheckState(t, a2, "service:ping", api.HealthPassing) - logf(t, a2, "giving the alias check a chance to notice...") + logf(a2, "giving the alias check a chance to notice...") time.Sleep(5 * time.Second) retryUntilCheckState(t, a2, "service:ping-sidecar-proxy", api.HealthPassing) @@ -3954,7 +3954,7 @@ func TestAgent_GetCoordinate(t *testing.T) { coords, err := a.GetLANCoordinate() require.NoError(t, err) - expected := lib.CoordinateSet{ + expected := librtt.CoordinateSet{ "": &coordinate.Coordinate{ Error: 1.5, Height: 1e-05, @@ -6338,21 +6338,13 @@ func TestAgent_scadaProvider(t *testing.T) { require.NoError(t, err) defer require.NoError(t, l.Close()) - pvd.EXPECT().UpdateMeta(mock.Anything).Once() - pvd.EXPECT().Start().Return(nil).Once() pvd.EXPECT().Listen(scada.CAPCoreAPI.Capability()).Return(l, nil).Once() pvd.EXPECT().Stop().Return(nil).Once() - pvd.EXPECT().SessionStatus().Return("test") a := TestAgent{ + HCL: `cloud = { resource_id = "test-resource-id" client_id = "test-client-id" client_secret = "test-client-secret" }`, OverrideDeps: func(deps *BaseDeps) { deps.HCP.Provider = pvd }, - Overrides: ` -cloud { - resource_id = "organization/0b9de9a3-8403-4ca6-aba8-fca752f42100/project/0b9de9a3-8403-4ca6-aba8-fca752f42100/consul.cluster/0b9de9a3-8403-4ca6-aba8-fca752f42100" - client_id = "test" - client_secret = "test" -}`, } defer a.Shutdown() require.NoError(t, a.Start(t)) diff --git a/agent/auto-config/auto_encrypt_test.go b/agent/auto-config/auto_encrypt_test.go index 10a7c8da4688..d0768080248c 100644 --- a/agent/auto-config/auto_encrypt_test.go +++ b/agent/auto-config/auto_encrypt_test.go @@ -7,6 +7,7 @@ import ( "context" "crypto/x509" "crypto/x509/pkix" + "encoding/pem" "fmt" "net" "net/url" @@ -107,6 +108,45 @@ func TestAutoEncrypt_generateCSR(t *testing.T) { } } +func TestAutoEncrypt_generateCSR_RSA(t *testing.T) { + testCases := []struct { + name string + keySize int + expectedKeySize int + }{ + { + name: "DefaultKeySize", + keySize: 0, + expectedKeySize: 4096, + }, + { + name: "KeySize2048", + keySize: 2048, + expectedKeySize: 2048, + }, + } + + for _, tcase := range testCases { + t.Run(tcase.name, func(t *testing.T) { + ac := AutoConfig{config: &config.RuntimeConfig{ + ConnectCAConfig: map[string]interface{}{ + "PrivateKeyType": "rsa", + "PrivateKeyBits": tcase.keySize, + }, + }} + + // Generate a private RSA key. + _, key, err := ac.generateCSR() + require.NoError(t, err) + + // Parse the private key and check it's length. + pemBlock, _ := pem.Decode([]byte(key)) + priv, _ := x509.ParsePKCS1PrivateKey(pemBlock.Bytes) + require.Equal(t, tcase.expectedKeySize, priv.N.BitLen()) + }) + } +} + func TestAutoEncrypt_hosts(t *testing.T) { type testCase struct { serverProvider ServerProvider diff --git a/agent/auto-config/tls.go b/agent/auto-config/tls.go index 8142a1eeb809..dd2d6f9e25e1 100644 --- a/agent/auto-config/tls.go +++ b/agent/auto-config/tls.go @@ -241,7 +241,12 @@ func (ac *AutoConfig) generateCSR() (csr string, key string, err error) { conf.PrivateKeyType = connect.DefaultPrivateKeyType } if conf.PrivateKeyBits == 0 { - conf.PrivateKeyBits = connect.DefaultPrivateKeyBits + // If using an RSA key, a key size of at least 2048 bits is recommended; 4096 bits is better. + if conf.PrivateKeyType == connect.PrivateKeyTypeRSA { + conf.PrivateKeyBits = connect.DefaultPrivateKeyBitsRSA + } else { + conf.PrivateKeyBits = connect.DefaultPrivateKeyBits + } } // Create a new private key diff --git a/agent/blockingquery/blockingquery.go b/agent/blockingquery/blockingquery.go index 3e073a1ffab2..32f170cc1ce8 100644 --- a/agent/blockingquery/blockingquery.go +++ b/agent/blockingquery/blockingquery.go @@ -28,6 +28,8 @@ type QueryFn func(memdb.WatchSet, *state.Store) error // RequestOptions are options used by Server.blockingQuery to modify the // behaviour of the query operation, or to populate response metadata. +// +//go:generate mockery --name RequestOptions --inpackage type RequestOptions interface { GetToken() string GetMinQueryIndex() uint64 @@ -37,6 +39,8 @@ type RequestOptions interface { // ResponseMeta is an interface used to populate the response struct // with metadata about the query and the state of the server. +// +//go:generate mockery --name ResponseMeta --inpackage type ResponseMeta interface { SetLastContact(time.Duration) SetKnownLeader(bool) @@ -47,6 +51,8 @@ type ResponseMeta interface { // FSMServer is interface into the stateful components of a Consul server, such // as memdb or raft leadership. +// +//go:generate mockery --name FSMServer --inpackage type FSMServer interface { ConsistentRead() error DecrementBlockingQueries() uint64 diff --git a/agent/blockingquery/blockingquery_test.go b/agent/blockingquery/blockingquery_test.go index 5861ed399164..494cc41b42ad 100644 --- a/agent/blockingquery/blockingquery_test.go +++ b/agent/blockingquery/blockingquery_test.go @@ -3,5 +3,338 @@ package blockingquery -// TODO: move tests from the consul package, rpc_test.go, TestServer_blockingQuery -// here using mock for FSMServer w/ structs.QueryOptions and structs.QueryOptions +import ( + "fmt" + "github.com/hashicorp/consul/agent/consul/state" + "github.com/hashicorp/go-memdb" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func TestServer_blockingQuery(t *testing.T) { + t.Parallel() + getFSM := func(t *testing.T, additionalCfgFunc func(mockFSM *MockFSMServer)) *MockFSMServer { + fsm := NewMockFSMServer(t) + testCh := make(chan struct{}) + tombstoneGC, err := state.NewTombstoneGC(time.Second, time.Second) + require.NoError(t, err) + store := state.NewStateStore(tombstoneGC) + fsm.On("GetShutdownChannel").Return(testCh) + fsm.On("GetState").Return(store) + fsm.On("SetQueryMeta", mock.Anything, mock.Anything).Return(nil) + if additionalCfgFunc != nil { + additionalCfgFunc(fsm) + } + return fsm + } + + getOpts := func(t *testing.T, additionalCfgFunc func(options *MockRequestOptions)) *MockRequestOptions { + requestOpts := NewMockRequestOptions(t) + requestOpts.On("GetRequireConsistent").Return(false) + requestOpts.On("GetToken").Return("fake-token") + if additionalCfgFunc != nil { + additionalCfgFunc(requestOpts) + } + return requestOpts + } + + getMeta := func(t *testing.T, additionalCfgFunc func(mockMeta *MockResponseMeta)) *MockResponseMeta { + meta := NewMockResponseMeta(t) + if additionalCfgFunc != nil { + additionalCfgFunc(meta) + } + return meta + } + + // Perform a non-blocking query. Note that it's significant that the meta has + // a zero index in response - the implied opts.MinQueryIndex is also zero but + // this should not block still. + t.Run("non-blocking query", func(t *testing.T) { + var calls int + fn := func(_ memdb.WatchSet, _ *state.Store) error { + calls++ + return nil + } + err := Query(getFSM(t, nil), getOpts(t, func(mockOpts *MockRequestOptions) { + mockOpts.On("GetMinQueryIndex").Return(uint64(0)) + }), getMeta(t, nil), fn) + require.NoError(t, err) + require.Equal(t, 1, calls) + }) + + // Perform a blocking query that gets woken up and loops around once. + t.Run("blocking query - single loop", func(t *testing.T) { + opts := getOpts(t, func(options *MockRequestOptions) { + options.On("GetMinQueryIndex").Return(uint64(1)) + options.On("GetMaxQueryTime").Return(1*time.Second, nil) + }) + + meta := getMeta(t, func(mockMeta *MockResponseMeta) { + mockMeta.On("GetIndex").Return(uint64(1)) + }) + + fsm := getFSM(t, func(mockFSM *MockFSMServer) { + mockFSM.On("RPCQueryTimeout", mock.Anything).Return(1 * time.Second) + mockFSM.On("IncrementBlockingQueries").Return(uint64(1)) + mockFSM.On("DecrementBlockingQueries").Return(uint64(1)) + }) + + var calls int + fn := func(ws memdb.WatchSet, _ *state.Store) error { + if calls == 0 { + meta.On("GetIndex").Return(uint64(3)) + + fakeCh := make(chan struct{}) + close(fakeCh) + ws.Add(fakeCh) + } else { + meta.On("GetIndex").Return(uint64(4)) + } + calls++ + return nil + } + err := Query(fsm, opts, meta, fn) + require.NoError(t, err) + require.Equal(t, 2, calls) + }) + + // Perform a blocking query that returns a zero index from blocking func (e.g. + // no state yet). This should still return an empty response immediately, but + // with index of 1 and then block on the next attempt. In one sense zero index + // is not really a valid response from a state method that is not an error but + // in practice a lot of state store operations do return it unless they + // explicitly special checks to turn 0 into 1. Often this is not caught or + // covered by tests but eventually when hit in the wild causes blocking + // clients to busy loop and burn CPU. This test ensure that blockingQuery + // systematically does the right thing to prevent future bugs like that. + t.Run("blocking query with 0 modifyIndex from state func", func(t *testing.T) { + opts := getOpts(t, func(options *MockRequestOptions) { + options.On("GetMinQueryIndex").Return(uint64(0)) + }) + + meta := getMeta(t, func(mockMeta *MockResponseMeta) { + mockMeta.On("GetIndex").Return(uint64(1)) + }) + + fsm := getFSM(t, func(mockFSM *MockFSMServer) { + mockFSM.On("RPCQueryTimeout", mock.Anything).Return(1 * time.Second) + mockFSM.On("IncrementBlockingQueries").Return(uint64(1)) + mockFSM.On("DecrementBlockingQueries").Return(uint64(1)) + }) + var calls int + fn := func(ws memdb.WatchSet, _ *state.Store) error { + if opts.GetMinQueryIndex() > 0 { + // If client requested blocking, block forever. This is simulating + // waiting for the watched resource to be initialized/written to giving + // it a non-zero index. Note the timeout on the query options is relied + // on to stop the test taking forever. + fakeCh := make(chan struct{}) + ws.Add(fakeCh) + } + meta.On("GetIndex").Return(uint64(0)) + calls++ + return nil + } + err := Query(fsm, opts, meta, fn) + require.NoError(t, err) + require.Equal(t, 1, calls) + require.Equal(t, uint64(1), meta.GetIndex(), + "expect fake index of 1 to force client to block on next update") + + // Simulate client making next request + opts = getOpts(t, func(options *MockRequestOptions) { + options.On("GetMinQueryIndex").Return(uint64(1)) + options.On("GetMaxQueryTime").Return(20*time.Millisecond, nil) + }) + + // This time we should block even though the func returns index 0 still + t0 := time.Now() + require.NoError(t, Query(fsm, opts, meta, fn)) + t1 := time.Now() + require.Equal(t, 2, calls) + require.Equal(t, uint64(1), meta.GetIndex(), + "expect fake index of 1 to force client to block on next update") + require.True(t, t1.Sub(t0) > 20*time.Millisecond, + "should have actually blocked waiting for timeout") + + }) + + // Perform a query that blocks and gets interrupted when the state store + // is abandoned. + t.Run("blocking query interrupted by abandonCh", func(t *testing.T) { + opts := getOpts(t, func(options *MockRequestOptions) { + options.On("GetMinQueryIndex").Return(uint64(3)) + options.On("GetMaxQueryTime").Return(20*time.Millisecond, nil) + }) + + meta := getMeta(t, func(mockMeta *MockResponseMeta) { + mockMeta.On("GetIndex").Return(uint64(1)) + }) + + fsm := getFSM(t, func(mockFSM *MockFSMServer) { + mockFSM.On("RPCQueryTimeout", mock.Anything).Return(1 * time.Second) + mockFSM.On("IncrementBlockingQueries").Return(uint64(1)) + mockFSM.On("DecrementBlockingQueries").Return(uint64(1)) + }) + + var calls int + fn := func(_ memdb.WatchSet, _ *state.Store) error { + if calls == 0 { + meta.On("GetIndex").Return(uint64(1)) + + fsm.GetState().Abandon() + } + calls++ + return nil + } + err := Query(fsm, opts, meta, fn) + require.NoError(t, err) + require.Equal(t, 1, calls) + }) + + t.Run("non-blocking query for item that does not exist", func(t *testing.T) { + opts := getOpts(t, func(options *MockRequestOptions) { + options.On("GetMinQueryIndex").Return(uint64(3)) + options.On("GetMaxQueryTime").Return(20*time.Millisecond, nil) + }) + + meta := getMeta(t, func(mockMeta *MockResponseMeta) { + mockMeta.On("GetIndex").Return(uint64(1)) + }) + + fsm := getFSM(t, func(mockFSM *MockFSMServer) { + mockFSM.On("RPCQueryTimeout", mock.Anything).Return(1 * time.Second) + mockFSM.On("IncrementBlockingQueries").Return(uint64(1)) + mockFSM.On("DecrementBlockingQueries").Return(uint64(1)) + }) + calls := 0 + fn := func(_ memdb.WatchSet, _ *state.Store) error { + calls++ + return ErrNotFound + } + + err := Query(fsm, opts, meta, fn) + require.NoError(t, err) + require.Equal(t, 1, calls) + }) + + t.Run("blocking query for item that does not exist", func(t *testing.T) { + opts := getOpts(t, func(options *MockRequestOptions) { + options.On("GetMinQueryIndex").Return(uint64(3)) + options.On("GetMaxQueryTime").Return(100*time.Millisecond, nil) + }) + + meta := getMeta(t, func(mockMeta *MockResponseMeta) { + mockMeta.On("GetIndex").Return(uint64(1)) + }) + + fsm := getFSM(t, func(mockFSM *MockFSMServer) { + mockFSM.On("RPCQueryTimeout", mock.Anything).Return(1 * time.Second) + mockFSM.On("IncrementBlockingQueries").Return(uint64(1)) + mockFSM.On("DecrementBlockingQueries").Return(uint64(1)) + }) + calls := 0 + fn := func(ws memdb.WatchSet, _ *state.Store) error { + calls++ + if calls == 1 { + meta.On("GetIndex").Return(uint64(3)) + + ch := make(chan struct{}) + close(ch) + ws.Add(ch) + return ErrNotFound + } + meta.On("GetIndex").Return(uint64(5)) + return ErrNotFound + } + + err := Query(fsm, opts, meta, fn) + require.NoError(t, err) + require.Equal(t, 2, calls) + }) + + t.Run("blocking query for item that existed and is removed", func(t *testing.T) { + opts := getOpts(t, func(options *MockRequestOptions) { + options.On("GetMinQueryIndex").Return(uint64(3)) + // this query taks 1.002 sceonds locally so setting the timeout to 2 seconds + options.On("GetMaxQueryTime").Return(2*time.Second, nil) + }) + + meta := getMeta(t, func(mockMeta *MockResponseMeta) { + mockMeta.On("GetIndex").Return(uint64(3)) + }) + + fsm := getFSM(t, func(mockFSM *MockFSMServer) { + mockFSM.On("RPCQueryTimeout", mock.Anything).Return(1 * time.Second) + mockFSM.On("IncrementBlockingQueries").Return(uint64(1)) + mockFSM.On("DecrementBlockingQueries").Return(uint64(1)) + }) + calls := 0 + fn := func(ws memdb.WatchSet, _ *state.Store) error { + calls++ + if calls == 1 { + + ch := make(chan struct{}) + close(ch) + ws.Add(ch) + return nil + } + meta = getMeta(t, func(mockMeta *MockResponseMeta) { + meta.On("GetIndex").Return(uint64(5)) + }) + return ErrNotFound + } + + start := time.Now() + require.NoError(t, Query(fsm, opts, meta, fn)) + queryDuration := time.Since(start) + maxQueryDuration, err := opts.GetMaxQueryTime() + require.NoError(t, err) + require.True(t, queryDuration < maxQueryDuration, fmt.Sprintf("query timed out - queryDuration: %v, maxQueryDuration: %v", queryDuration, maxQueryDuration)) + require.NoError(t, err) + require.Equal(t, 2, calls) + }) + + t.Run("blocking query for non-existent item that is created", func(t *testing.T) { + opts := getOpts(t, func(options *MockRequestOptions) { + options.On("GetMinQueryIndex").Return(uint64(3)) + // this query taks 1.002 sceonds locally so setting the timeout to 2 seconds + options.On("GetMaxQueryTime").Return(2*time.Second, nil) + }) + + meta := getMeta(t, func(mockMeta *MockResponseMeta) { + mockMeta.On("GetIndex").Return(uint64(3)) + }) + + fsm := getFSM(t, func(mockFSM *MockFSMServer) { + mockFSM.On("RPCQueryTimeout", mock.Anything).Return(1 * time.Second) + mockFSM.On("IncrementBlockingQueries").Return(uint64(1)) + mockFSM.On("DecrementBlockingQueries").Return(uint64(1)) + }) + calls := 0 + fn := func(ws memdb.WatchSet, _ *state.Store) error { + calls++ + if calls == 1 { + ch := make(chan struct{}) + close(ch) + ws.Add(ch) + return ErrNotFound + } + meta = getMeta(t, func(mockMeta *MockResponseMeta) { + meta.On("GetIndex").Return(uint64(5)) + }) + return nil + } + + start := time.Now() + require.NoError(t, Query(fsm, opts, meta, fn)) + queryDuration := time.Since(start) + maxQueryDuration, err := opts.GetMaxQueryTime() + require.NoError(t, err) + require.True(t, queryDuration < maxQueryDuration, fmt.Sprintf("query timed out - queryDuration: %v, maxQueryDuration: %v", queryDuration, maxQueryDuration)) + require.NoError(t, err) + require.Equal(t, 2, calls) + }) +} diff --git a/agent/blockingquery/mock_FSMServer.go b/agent/blockingquery/mock_FSMServer.go new file mode 100644 index 000000000000..1e62f391b8dd --- /dev/null +++ b/agent/blockingquery/mock_FSMServer.go @@ -0,0 +1,122 @@ +// Code generated by mockery v2.32.4. DO NOT EDIT. + +package blockingquery + +import ( + time "time" + + state "github.com/hashicorp/consul/agent/consul/state" + mock "github.com/stretchr/testify/mock" +) + +// MockFSMServer is an autogenerated mock type for the FSMServer type +type MockFSMServer struct { + mock.Mock +} + +// ConsistentRead provides a mock function with given fields: +func (_m *MockFSMServer) ConsistentRead() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DecrementBlockingQueries provides a mock function with given fields: +func (_m *MockFSMServer) DecrementBlockingQueries() uint64 { + ret := _m.Called() + + var r0 uint64 + if rf, ok := ret.Get(0).(func() uint64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(uint64) + } + + return r0 +} + +// GetShutdownChannel provides a mock function with given fields: +func (_m *MockFSMServer) GetShutdownChannel() chan struct{} { + ret := _m.Called() + + var r0 chan struct{} + if rf, ok := ret.Get(0).(func() chan struct{}); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(chan struct{}) + } + } + + return r0 +} + +// GetState provides a mock function with given fields: +func (_m *MockFSMServer) GetState() *state.Store { + ret := _m.Called() + + var r0 *state.Store + if rf, ok := ret.Get(0).(func() *state.Store); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.Store) + } + } + + return r0 +} + +// IncrementBlockingQueries provides a mock function with given fields: +func (_m *MockFSMServer) IncrementBlockingQueries() uint64 { + ret := _m.Called() + + var r0 uint64 + if rf, ok := ret.Get(0).(func() uint64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(uint64) + } + + return r0 +} + +// RPCQueryTimeout provides a mock function with given fields: _a0 +func (_m *MockFSMServer) RPCQueryTimeout(_a0 time.Duration) time.Duration { + ret := _m.Called(_a0) + + var r0 time.Duration + if rf, ok := ret.Get(0).(func(time.Duration) time.Duration); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(time.Duration) + } + + return r0 +} + +// SetQueryMeta provides a mock function with given fields: _a0, _a1 +func (_m *MockFSMServer) SetQueryMeta(_a0 ResponseMeta, _a1 string) { + _m.Called(_a0, _a1) +} + +// NewMockFSMServer creates a new instance of MockFSMServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockFSMServer(t interface { + mock.TestingT + Cleanup(func()) +}) *MockFSMServer { + mock := &MockFSMServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/agent/blockingquery/mock_RequestOptions.go b/agent/blockingquery/mock_RequestOptions.go new file mode 100644 index 000000000000..7e57c86b36de --- /dev/null +++ b/agent/blockingquery/mock_RequestOptions.go @@ -0,0 +1,94 @@ +// Code generated by mockery v2.32.4. DO NOT EDIT. + +package blockingquery + +import ( + time "time" + + mock "github.com/stretchr/testify/mock" +) + +// MockRequestOptions is an autogenerated mock type for the RequestOptions type +type MockRequestOptions struct { + mock.Mock +} + +// GetMaxQueryTime provides a mock function with given fields: +func (_m *MockRequestOptions) GetMaxQueryTime() (time.Duration, error) { + ret := _m.Called() + + var r0 time.Duration + var r1 error + if rf, ok := ret.Get(0).(func() (time.Duration, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() time.Duration); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(time.Duration) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetMinQueryIndex provides a mock function with given fields: +func (_m *MockRequestOptions) GetMinQueryIndex() uint64 { + ret := _m.Called() + + var r0 uint64 + if rf, ok := ret.Get(0).(func() uint64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(uint64) + } + + return r0 +} + +// GetRequireConsistent provides a mock function with given fields: +func (_m *MockRequestOptions) GetRequireConsistent() bool { + ret := _m.Called() + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// GetToken provides a mock function with given fields: +func (_m *MockRequestOptions) GetToken() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// NewMockRequestOptions creates a new instance of MockRequestOptions. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockRequestOptions(t interface { + mock.TestingT + Cleanup(func()) +}) *MockRequestOptions { + mock := &MockRequestOptions{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/agent/blockingquery/mock_ResponseMeta.go b/agent/blockingquery/mock_ResponseMeta.go new file mode 100644 index 000000000000..c038b4bcd5a4 --- /dev/null +++ b/agent/blockingquery/mock_ResponseMeta.go @@ -0,0 +1,62 @@ +// Code generated by mockery v2.32.4. DO NOT EDIT. + +package blockingquery + +import ( + time "time" + + mock "github.com/stretchr/testify/mock" +) + +// MockResponseMeta is an autogenerated mock type for the ResponseMeta type +type MockResponseMeta struct { + mock.Mock +} + +// GetIndex provides a mock function with given fields: +func (_m *MockResponseMeta) GetIndex() uint64 { + ret := _m.Called() + + var r0 uint64 + if rf, ok := ret.Get(0).(func() uint64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(uint64) + } + + return r0 +} + +// SetIndex provides a mock function with given fields: _a0 +func (_m *MockResponseMeta) SetIndex(_a0 uint64) { + _m.Called(_a0) +} + +// SetKnownLeader provides a mock function with given fields: _a0 +func (_m *MockResponseMeta) SetKnownLeader(_a0 bool) { + _m.Called(_a0) +} + +// SetLastContact provides a mock function with given fields: _a0 +func (_m *MockResponseMeta) SetLastContact(_a0 time.Duration) { + _m.Called(_a0) +} + +// SetResultsFilteredByACLs provides a mock function with given fields: _a0 +func (_m *MockResponseMeta) SetResultsFilteredByACLs(_a0 bool) { + _m.Called(_a0) +} + +// NewMockResponseMeta creates a new instance of MockResponseMeta. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockResponseMeta(t interface { + mock.TestingT + Cleanup(func()) +}) *MockResponseMeta { + mock := &MockResponseMeta{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/agent/catalog_endpoint.go b/agent/catalog_endpoint.go index 1dac61befa47..8af4654b90f2 100644 --- a/agent/catalog_endpoint.go +++ b/agent/catalog_endpoint.go @@ -13,6 +13,7 @@ import ( cachetype "github.com/hashicorp/consul/agent/cache-types" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/internal/dnsutil" ) var CatalogCounters = []prometheus.CounterDefinition{ @@ -257,7 +258,7 @@ RETRY_ONCE: } out.ConsistencyLevel = args.QueryOptions.ConsistencyLevel() - s.agent.TranslateAddresses(args.Datacenter, out.Nodes, TranslateAddressAcceptAny) + s.agent.TranslateAddresses(args.Datacenter, out.Nodes, dnsutil.TranslateAddressAcceptAny) // Use empty list instead of nil if out.Nodes == nil { @@ -403,7 +404,7 @@ func (s *HTTPHandlers) catalogServiceNodes(resp http.ResponseWriter, req *http.R } out.ConsistencyLevel = args.QueryOptions.ConsistencyLevel() - s.agent.TranslateAddresses(args.Datacenter, out.ServiceNodes, TranslateAddressAcceptAny) + s.agent.TranslateAddresses(args.Datacenter, out.ServiceNodes, dnsutil.TranslateAddressAcceptAny) // Use empty list instead of nil if out.ServiceNodes == nil { @@ -457,7 +458,7 @@ RETRY_ONCE: } out.ConsistencyLevel = args.QueryOptions.ConsistencyLevel() if out.NodeServices != nil { - s.agent.TranslateAddresses(args.Datacenter, out.NodeServices, TranslateAddressAcceptAny) + s.agent.TranslateAddresses(args.Datacenter, out.NodeServices, dnsutil.TranslateAddressAcceptAny) } // TODO: The NodeServices object in IndexedNodeServices is a pointer to @@ -521,7 +522,7 @@ RETRY_ONCE: goto RETRY_ONCE } out.ConsistencyLevel = args.QueryOptions.ConsistencyLevel() - s.agent.TranslateAddresses(args.Datacenter, &out.NodeServices, TranslateAddressAcceptAny) + s.agent.TranslateAddresses(args.Datacenter, &out.NodeServices, dnsutil.TranslateAddressAcceptAny) // Use empty list instead of nil for _, s := range out.NodeServices.Services { diff --git a/agent/catalog_endpoint_test.go b/agent/catalog_endpoint_test.go index 19d520220427..c06efc748cb6 100644 --- a/agent/catalog_endpoint_test.go +++ b/agent/catalog_endpoint_test.go @@ -6,18 +6,17 @@ package agent import ( "context" "fmt" - "io" "net/http" "net/http/httptest" "net/url" - "strings" "testing" "time" - "github.com/hashicorp/serf/coordinate" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/hashicorp/serf/coordinate" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" @@ -25,47 +24,10 @@ import ( "github.com/hashicorp/consul/testrpc" ) -func TestCatalogEndpointsFailInV2(t *testing.T) { - t.Parallel() - - a := NewTestAgent(t, `experiments = ["resource-apis"]`) - - checkRequest := func(method, url string) { - t.Run(method+" "+url, func(t *testing.T) { - assertV1CatalogEndpointDoesNotWorkWithV2(t, a, method, url, "{}") - }) - } - - checkRequest("PUT", "/v1/catalog/register") - checkRequest("GET", "/v1/catalog/connect/") - checkRequest("PUT", "/v1/catalog/deregister") - checkRequest("GET", "/v1/catalog/datacenters") - checkRequest("GET", "/v1/catalog/nodes") - checkRequest("GET", "/v1/catalog/services") - checkRequest("GET", "/v1/catalog/service/") - checkRequest("GET", "/v1/catalog/node/") - checkRequest("GET", "/v1/catalog/node-services/") - checkRequest("GET", "/v1/catalog/gateway-services/") -} - -func assertV1CatalogEndpointDoesNotWorkWithV2(t *testing.T, a *TestAgent, method, url string, requestBody string) { - var body io.Reader - switch method { - case http.MethodPost, http.MethodPut: - body = strings.NewReader(requestBody + "\n") - } - - req, err := http.NewRequest(method, url, body) - require.NoError(t, err) - - resp := httptest.NewRecorder() - a.srv.h.ServeHTTP(resp, req) - require.Equal(t, http.StatusBadRequest, resp.Code) - - got, err := io.ReadAll(resp.Body) - require.NoError(t, err) - - require.Contains(t, string(got), structs.ErrUsingV2CatalogExperiment.Error()) +func addQueryParam(req *http.Request, param, value string) { + q := req.URL.Query() + q.Add(param, value) + req.URL.RawQuery = q.Encode() } func TestCatalogRegister_PeeringRegistration(t *testing.T) { @@ -1167,7 +1129,7 @@ func TestCatalogServiceNodes_DistanceSort(t *testing.T) { r.Fatalf("err: %v", err) } - assertIndex(t, resp) + assertIndex(r, resp) nodes = obj.(structs.ServiceNodes) if len(nodes) != 2 { r.Fatalf("bad: %v", obj) @@ -1938,11 +1900,12 @@ func TestCatalog_GatewayServices_Terminating(t *testing.T) { SNI: "my-domain", }, { - Name: "*", - CAFile: "ca.crt", - CertFile: "client.crt", - KeyFile: "client.key", - SNI: "my-alt-domain", + Name: "*", + CAFile: "ca.crt", + CertFile: "client.crt", + KeyFile: "client.key", + SNI: "my-alt-domain", + DisableAutoHostRewrite: true, }, }, }, @@ -1965,23 +1928,25 @@ func TestCatalog_GatewayServices_Terminating(t *testing.T) { expect := structs.GatewayServices{ { - Service: structs.NewServiceName("api", nil), - Gateway: structs.NewServiceName("terminating", nil), - GatewayKind: structs.ServiceKindTerminatingGateway, - CAFile: "api/ca.crt", - CertFile: "api/client.crt", - KeyFile: "api/client.key", - SNI: "my-domain", + Service: structs.NewServiceName("api", nil), + Gateway: structs.NewServiceName("terminating", nil), + GatewayKind: structs.ServiceKindTerminatingGateway, + CAFile: "api/ca.crt", + CertFile: "api/client.crt", + KeyFile: "api/client.key", + SNI: "my-domain", + AutoHostRewrite: true, }, { - Service: structs.NewServiceName("redis", nil), - Gateway: structs.NewServiceName("terminating", nil), - GatewayKind: structs.ServiceKindTerminatingGateway, - CAFile: "ca.crt", - CertFile: "client.crt", - KeyFile: "client.key", - SNI: "my-alt-domain", - FromWildcard: true, + Service: structs.NewServiceName("redis", nil), + Gateway: structs.NewServiceName("terminating", nil), + GatewayKind: structs.ServiceKindTerminatingGateway, + CAFile: "ca.crt", + CertFile: "client.crt", + KeyFile: "client.key", + SNI: "my-alt-domain", + FromWildcard: true, + AutoHostRewrite: false, }, } diff --git a/agent/checks/alias.go b/agent/checks/alias.go index f75c05b9580b..200176364e91 100644 --- a/agent/checks/alias.go +++ b/agent/checks/alias.go @@ -144,6 +144,9 @@ func (c *CheckAlias) runLocal(stopCh chan struct{}) { type CheckIfServiceIDExists func(*structs.ServiceID) bool func (c *CheckAlias) checkServiceExistsOnRemoteServer(serviceID *structs.ServiceID) (bool, error) { + if serviceID == nil { + return false, fmt.Errorf("serviceID cannot be nil") + } args := c.RPCReq args.Node = c.Node args.AllowStale = true @@ -161,6 +164,12 @@ RETRY_CALL: } return false, err } + + // Do not proceed for nil returned services. + if out.NodeServices == nil { + return false, fmt.Errorf("no services found on node") + } + for _, srv := range out.NodeServices.Services { if serviceID.Matches(srv.CompoundServiceID()) { return true, nil diff --git a/agent/config/builder.go b/agent/config/builder.go index 852337d08cfb..f8d0df7b5c93 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -4,6 +4,7 @@ package config import ( + "crypto/tls" "encoding/base64" "encoding/json" "errors" @@ -21,12 +22,13 @@ import ( "time" "github.com/armon/go-metrics/prometheus" + "golang.org/x/time/rate" + "github.com/hashicorp/go-bexpr" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-multierror" "github.com/hashicorp/go-sockaddr/template" "github.com/hashicorp/memberlist" - "golang.org/x/time/rate" "github.com/hashicorp/consul/agent/cache" "github.com/hashicorp/consul/agent/checks" @@ -34,11 +36,11 @@ import ( "github.com/hashicorp/consul/agent/consul" "github.com/hashicorp/consul/agent/consul/authmethod/ssoauth" consulrate "github.com/hashicorp/consul/agent/consul/rate" - "github.com/hashicorp/consul/agent/dns" hcpconfig "github.com/hashicorp/consul/agent/hcp/config" "github.com/hashicorp/consul/agent/rpc/middleware" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/token" + "github.com/hashicorp/consul/internal/dnsutil" "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/stringslice" @@ -316,8 +318,10 @@ func formatFromFileExtension(name string) string { type byName []os.FileInfo -func (a byName) Len() int { return len(a) } -func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byName) Len() int { return len(a) } + +func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + func (a byName) Less(i, j int) bool { return a[i].Name() < a[j].Name() } // build constructs the runtime configuration from the config sources @@ -771,6 +775,7 @@ func (b *builder) build() (rt RuntimeConfig, err error) { if err != nil { return RuntimeConfig{}, fmt.Errorf("config_entries.bootstrap[%d]: %s", i, err) } + // Ensure Normalize is called before Validate for accurate validation if err := entry.Normalize(); err != nil { return RuntimeConfig{}, fmt.Errorf("config_entries.bootstrap[%d]: %s", i, err) } @@ -944,6 +949,7 @@ func (b *builder) build() (rt RuntimeConfig, err error) { CirconusSubmissionInterval: stringVal(c.Telemetry.CirconusSubmissionInterval), CirconusSubmissionURL: stringVal(c.Telemetry.CirconusSubmissionURL), DisableHostname: boolVal(c.Telemetry.DisableHostname), + DisablePerTenancyUsageMetrics: boolVal(c.Telemetry.DisablePerTenancyUsageMetrics), DogstatsdAddr: stringVal(c.Telemetry.DogstatsdAddr), DogstatsdTags: c.Telemetry.DogstatsdTags, RetryFailedConfiguration: boolVal(c.Telemetry.RetryFailedConfiguration), @@ -998,6 +1004,7 @@ func (b *builder) build() (rt RuntimeConfig, err error) { DataDir: dataDir, Datacenter: datacenter, DefaultQueryTime: b.durationVal("default_query_time", c.DefaultQueryTime), + DefaultIntentionPolicy: stringVal(c.DefaultIntentionPolicy), DevMode: boolVal(b.opts.DevMode), DisableAnonymousSignature: boolVal(c.DisableAnonymousSignature), DisableCoordinates: boolVal(c.DisableCoordinates), @@ -1110,7 +1117,7 @@ func (b *builder) build() (rt RuntimeConfig, err error) { LocalProxyConfigResyncInterval: 30 * time.Second, } - // host metrics are enabled by default if consul is configured with HashiCorp Cloud Platform integration + // host metrics are enabled if consul is configured with HashiCorp Cloud Platform integration rt.Telemetry.EnableHostMetrics = boolValWithDefault(c.Telemetry.EnableHostMetrics, rt.IsCloudEnabled()) rt.TLS, err = b.buildTLSConfig(rt, c.TLS) @@ -1137,15 +1144,6 @@ func (b *builder) build() (rt RuntimeConfig, err error) { return RuntimeConfig{}, fmt.Errorf("cache.entry_fetch_rate must be strictly positive, was: %v", rt.Cache.EntryFetchRate) } - // TODO(CC-6389): Remove once resource-apis is no longer considered experimental and is supported by HCP - if stringslice.Contains(rt.Experiments, consul.CatalogResourceExperimentName) && rt.IsCloudEnabled() { - // Allow override of this check for development/testing purposes. Should not be used in production - override, err := strconv.ParseBool(os.Getenv("CONSUL_OVERRIDE_HCP_RESOURCE_APIS_CHECK")) - if err != nil || !override { - return RuntimeConfig{}, fmt.Errorf("`experiments` cannot include 'resource-apis' when HCP `cloud` configuration is set") - } - } - if rt.UIConfig.MetricsProvider == "prometheus" { // Handle defaulting for the built-in version of prometheus. if len(rt.UIConfig.MetricsProxy.PathAllowlist) == 0 { @@ -1288,7 +1286,7 @@ func (b *builder) validate(rt RuntimeConfig) error { switch { case rt.NodeName == "": return fmt.Errorf("node_name cannot be empty") - case dns.InvalidNameRe.MatchString(rt.NodeName): + case dnsutil.InvalidNameRe.MatchString(rt.NodeName): b.warn("Node name %q will not be discoverable "+ "via DNS due to invalid characters. Valid characters include "+ "all alpha-numerics and dashes.", rt.NodeName) @@ -1296,7 +1294,7 @@ func (b *builder) validate(rt RuntimeConfig) error { // todo(kyhavlov): Add stronger validation here for node names. b.warn("Found invalid characters in node name %q - whitespace and quotes "+ "(', \", `) cannot be used with auto-config.", rt.NodeName) - case len(rt.NodeName) > dns.MaxLabelLength: + case len(rt.NodeName) > dnsutil.MaxLabelLength: b.warn("Node name %q will not be discoverable "+ "via DNS due to it being too long. Valid lengths are between "+ "1 and 63 bytes.", rt.NodeName) @@ -1828,14 +1826,14 @@ func (b *builder) meshGatewayConfVal(mgConf *MeshGatewayConfig) structs.MeshGate return cfg } -func (b *builder) dnsRecursorStrategyVal(v string) dns.RecursorStrategy { - var out dns.RecursorStrategy +func (b *builder) dnsRecursorStrategyVal(v string) structs.RecursorStrategy { + var out structs.RecursorStrategy - switch dns.RecursorStrategy(v) { - case dns.RecursorStrategyRandom: - out = dns.RecursorStrategyRandom - case dns.RecursorStrategySequential, "": - out = dns.RecursorStrategySequential + switch structs.RecursorStrategy(v) { + case structs.RecursorStrategyRandom: + out = structs.RecursorStrategyRandom + case structs.RecursorStrategySequential, "": + out = structs.RecursorStrategySequential default: b.err = multierror.Append(b.err, fmt.Errorf("dns_config.recursor_strategy: invalid strategy: %q", v)) } @@ -2570,9 +2568,37 @@ func validateAutoConfigAuthorizer(rt RuntimeConfig) error { } func (b *builder) cloudConfigVal(v Config) hcpconfig.CloudConfig { + // Load the same environment variables expected by hcp-sdk-go + envHostname, ok := os.LookupEnv("HCP_API_ADDRESS") + if !ok { + if legacyEnvHostname, ok := os.LookupEnv("HCP_API_HOST"); ok { + // Remove only https scheme prefixes from the deprecated environment + // variable for specifying the API host. Mirrors the same behavior as + // hcp-sdk-go. + if strings.HasPrefix(strings.ToLower(legacyEnvHostname), "https://") { + legacyEnvHostname = legacyEnvHostname[8:] + } + envHostname = legacyEnvHostname + } + } + + var envTLSConfig *tls.Config + if os.Getenv("HCP_AUTH_TLS") == "insecure" || + os.Getenv("HCP_SCADA_TLS") == "insecure" || + os.Getenv("HCP_API_TLS") == "insecure" { + envTLSConfig = &tls.Config{InsecureSkipVerify: true} + } + val := hcpconfig.CloudConfig{ - ResourceID: os.Getenv("HCP_RESOURCE_ID"), + ResourceID: os.Getenv("HCP_RESOURCE_ID"), + ClientID: os.Getenv("HCP_CLIENT_ID"), + ClientSecret: os.Getenv("HCP_CLIENT_SECRET"), + AuthURL: os.Getenv("HCP_AUTH_URL"), + Hostname: envHostname, + ScadaAddress: os.Getenv("HCP_SCADA_ADDRESS"), + TLSConfig: envTLSConfig, } + // Node id might get overridden in setup.go:142 nodeID := stringVal(v.NodeID) val.NodeID = types.NodeID(nodeID) @@ -2582,15 +2608,31 @@ func (b *builder) cloudConfigVal(v Config) hcpconfig.CloudConfig { return val } - val.ClientID = stringVal(v.Cloud.ClientID) - val.ClientSecret = stringVal(v.Cloud.ClientSecret) - val.AuthURL = stringVal(v.Cloud.AuthURL) - val.Hostname = stringVal(v.Cloud.Hostname) - val.ScadaAddress = stringVal(v.Cloud.ScadaAddress) + // Load configuration file variables for anything not set by environment variables + if val.AuthURL == "" { + val.AuthURL = stringVal(v.Cloud.AuthURL) + } - if resourceID := stringVal(v.Cloud.ResourceID); resourceID != "" { - val.ResourceID = resourceID + if val.Hostname == "" { + val.Hostname = stringVal(v.Cloud.Hostname) } + + if val.ScadaAddress == "" { + val.ScadaAddress = stringVal(v.Cloud.ScadaAddress) + } + + if val.ResourceID == "" { + val.ResourceID = stringVal(v.Cloud.ResourceID) + } + + if val.ClientID == "" { + val.ClientID = stringVal(v.Cloud.ClientID) + } + + if val.ClientSecret == "" { + val.ClientSecret = stringVal(v.Cloud.ClientSecret) + } + return val } diff --git a/agent/config/builder_test.go b/agent/config/builder_test.go index 6f8fdc9598a0..26d20bdfbacc 100644 --- a/agent/config/builder_test.go +++ b/agent/config/builder_test.go @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + hcpconfig "github.com/hashicorp/consul/agent/hcp/config" "github.com/hashicorp/consul/types" ) @@ -576,47 +577,14 @@ func TestBuidler_hostMetricsWithCloud(t *testing.T) { require.True(t, cfg.Telemetry.EnableHostMetrics) } -func TestBuilder_WarnCloudConfigWithResourceApis(t *testing.T) { - tests := []struct { - name string +func TestBuilder_CheckExperimentsInSecondaryDatacenters(t *testing.T) { + + type testcase struct { hcl string expectErr bool - override bool - }{ - { - name: "base_case", - hcl: ``, - }, - { - name: "resource-apis_no_cloud", - hcl: `experiments = ["resource-apis"]`, - }, - { - name: "cloud-config_no_experiments", - hcl: `cloud{ resource_id = "abc" client_id = "abc" client_secret = "abc"}`, - }, - { - name: "cloud-config_resource-apis_experiment", - hcl: ` - experiments = ["resource-apis"] - cloud{ resource_id = "abc" client_id = "abc" client_secret = "abc"}`, - expectErr: true, - }, - { - name: "cloud-config_other_experiment", - hcl: ` - experiments = ["test"] - cloud{ resource_id = "abc" client_id = "abc" client_secret = "abc"}`, - }, - { - name: "cloud-config_resource-apis_experiment_override", - hcl: ` - experiments = ["resource-apis"] - cloud{ resource_id = "abc" client_id = "abc" client_secret = "abc"}`, - override: true, - }, } - for _, tc := range tests { + + run := func(t *testing.T, tc testcase) { // using dev mode skips the need for a data dir devMode := true builderOpts := LoadOpts{ @@ -629,18 +597,137 @@ func TestBuilder_WarnCloudConfigWithResourceApis(t *testing.T) { }, }, } - if tc.override { - os.Setenv("CONSUL_OVERRIDE_HCP_RESOURCE_APIS_CHECK", "1") - } _, err := Load(builderOpts) - if tc.override { - os.Unsetenv("CONSUL_OVERRIDE_HCP_RESOURCE_APIS_CHECK") - } if tc.expectErr { require.Error(t, err) - require.Contains(t, err.Error(), "cannot include 'resource-apis' when HCP") + require.Contains(t, err.Error(), "`experiments` cannot include") } else { require.NoError(t, err) } } + + const ( + primary = `server = true primary_datacenter = "dc1" datacenter = "dc1" ` + secondary = `server = true primary_datacenter = "dc1" datacenter = "dc2" ` + ) + + cases := map[string]testcase{ + "primary server no experiments": { + hcl: primary + `experiments = []`, + }, + "secondary server no experiments": { + hcl: secondary + `experiments = []`, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + run(t, tc) + }) + } +} + +func TestBuilder_CloudConfigWithEnvironmentVars(t *testing.T) { + tests := map[string]struct { + hcl string + env map[string]string + expected hcpconfig.CloudConfig + }{ + "ConfigurationOnly": { + hcl: `cloud{ resource_id = "config-resource-id" client_id = "config-client-id" + client_secret = "config-client-secret" auth_url = "auth.config.com" + hostname = "api.config.com" scada_address = "scada.config.com"}`, + expected: hcpconfig.CloudConfig{ + ResourceID: "config-resource-id", + ClientID: "config-client-id", + ClientSecret: "config-client-secret", + AuthURL: "auth.config.com", + Hostname: "api.config.com", + ScadaAddress: "scada.config.com", + }, + }, + "EnvVarsOnly": { + env: map[string]string{ + "HCP_RESOURCE_ID": "env-resource-id", + "HCP_CLIENT_ID": "env-client-id", + "HCP_CLIENT_SECRET": "env-client-secret", + "HCP_AUTH_URL": "auth.env.com", + "HCP_API_ADDRESS": "api.env.com", + "HCP_SCADA_ADDRESS": "scada.env.com", + }, + expected: hcpconfig.CloudConfig{ + ResourceID: "env-resource-id", + ClientID: "env-client-id", + ClientSecret: "env-client-secret", + AuthURL: "auth.env.com", + Hostname: "api.env.com", + ScadaAddress: "scada.env.com", + }, + }, + "EnvVarsOverrideConfig": { + hcl: `cloud{ resource_id = "config-resource-id" client_id = "config-client-id" + client_secret = "config-client-secret" auth_url = "auth.config.com" + hostname = "api.config.com" scada_address = "scada.config.com"}`, + env: map[string]string{ + "HCP_RESOURCE_ID": "env-resource-id", + "HCP_CLIENT_ID": "env-client-id", + "HCP_CLIENT_SECRET": "env-client-secret", + "HCP_AUTH_URL": "auth.env.com", + "HCP_API_ADDRESS": "api.env.com", + "HCP_SCADA_ADDRESS": "scada.env.com", + }, + expected: hcpconfig.CloudConfig{ + ResourceID: "env-resource-id", + ClientID: "env-client-id", + ClientSecret: "env-client-secret", + AuthURL: "auth.env.com", + Hostname: "api.env.com", + ScadaAddress: "scada.env.com", + }, + }, + "Combination": { + hcl: `cloud{ resource_id = "config-resource-id" client_id = "config-client-id" + client_secret = "config-client-secret"}`, + env: map[string]string{ + "HCP_AUTH_URL": "auth.env.com", + "HCP_API_ADDRESS": "api.env.com", + "HCP_SCADA_ADDRESS": "scada.env.com", + }, + expected: hcpconfig.CloudConfig{ + ResourceID: "config-resource-id", + ClientID: "config-client-id", + ClientSecret: "config-client-secret", + AuthURL: "auth.env.com", + Hostname: "api.env.com", + ScadaAddress: "scada.env.com", + }, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + for k, v := range tc.env { + t.Setenv(k, v) + } + devMode := true + builderOpts := LoadOpts{ + DevMode: &devMode, + Overrides: []Source{ + FileSource{ + Name: "overrides", + Format: "hcl", + Data: tc.hcl, + }, + }, + } + loaded, err := Load(builderOpts) + require.NoError(t, err) + + nodeName, err := os.Hostname() + require.NoError(t, err) + tc.expected.NodeName = nodeName + + actual := loaded.RuntimeConfig.Cloud + require.Equal(t, tc.expected, actual) + }) + } } diff --git a/agent/config/config.deepcopy.go b/agent/config/config.deepcopy.go index 2a5ebfce276c..bd9b85fca4ac 100644 --- a/agent/config/config.deepcopy.go +++ b/agent/config/config.deepcopy.go @@ -1,7 +1,4 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// generated by deep-copy -pointer-receiver -o ./config.deepcopy.go -type RuntimeConfig ./; DO NOT EDIT. +// Code generated by deep-copy -pointer-receiver -o ./config.deepcopy.go -type RuntimeConfig ./; DO NOT EDIT. package config @@ -359,6 +356,10 @@ func (o *RuntimeConfig) DeepCopy() *RuntimeConfig { } } } + if o.Cloud.TLSConfig.Certificates[i5].Leaf.Policies != nil { + cp.Cloud.TLSConfig.Certificates[i5].Leaf.Policies = make([]x509.OID, len(o.Cloud.TLSConfig.Certificates[i5].Leaf.Policies)) + copy(cp.Cloud.TLSConfig.Certificates[i5].Leaf.Policies, o.Cloud.TLSConfig.Certificates[i5].Leaf.Policies) + } } } } @@ -698,6 +699,10 @@ func (o *RuntimeConfig) DeepCopy() *RuntimeConfig { } } } + if v5.Leaf.Policies != nil { + cp_Cloud_TLSConfig_NameToCertificate_v5.Leaf.Policies = make([]x509.OID, len(v5.Leaf.Policies)) + copy(cp_Cloud_TLSConfig_NameToCertificate_v5.Leaf.Policies, v5.Leaf.Policies) + } } } cp.Cloud.TLSConfig.NameToCertificate[k5] = cp_Cloud_TLSConfig_NameToCertificate_v5 diff --git a/agent/config/config.go b/agent/config/config.go index d620b8c2f4e4..3201f790a752 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -165,6 +165,7 @@ type Config struct { DataDir *string `mapstructure:"data_dir" json:"data_dir,omitempty"` Datacenter *string `mapstructure:"datacenter" json:"datacenter,omitempty"` DefaultQueryTime *string `mapstructure:"default_query_time" json:"default_query_time,omitempty"` + DefaultIntentionPolicy *string `mapstructure:"default_intention_policy" json:"default_intention_policy,omitempty"` DisableAnonymousSignature *bool `mapstructure:"disable_anonymous_signature" json:"disable_anonymous_signature,omitempty"` DisableCoordinates *bool `mapstructure:"disable_coordinates" json:"disable_coordinates,omitempty"` DisableHostNodeID *bool `mapstructure:"disable_host_node_id" json:"disable_host_node_id,omitempty"` @@ -696,6 +697,7 @@ type Telemetry struct { CirconusSubmissionInterval *string `mapstructure:"circonus_submission_interval" json:"circonus_submission_interval,omitempty"` CirconusSubmissionURL *string `mapstructure:"circonus_submission_url" json:"circonus_submission_url,omitempty"` DisableHostname *bool `mapstructure:"disable_hostname" json:"disable_hostname,omitempty"` + DisablePerTenancyUsageMetrics *bool `mapstructure:"disable_per_tenancy_usage_metrics" json:"disable_per_tenancy_usage_metrics,omitempty"` EnableHostMetrics *bool `mapstructure:"enable_host_metrics" json:"enable_host_metrics,omitempty"` DogstatsdAddr *string `mapstructure:"dogstatsd_addr" json:"dogstatsd_addr,omitempty"` DogstatsdTags []string `mapstructure:"dogstatsd_tags" json:"dogstatsd_tags,omitempty"` diff --git a/agent/config/runtime.go b/agent/config/runtime.go index 954aa7198e25..2ac7ea19d9f1 100644 --- a/agent/config/runtime.go +++ b/agent/config/runtime.go @@ -16,7 +16,6 @@ import ( "github.com/hashicorp/consul/agent/cache" "github.com/hashicorp/consul/agent/consul" consulrate "github.com/hashicorp/consul/agent/consul/rate" - "github.com/hashicorp/consul/agent/dns" hcpconfig "github.com/hashicorp/consul/agent/hcp/config" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/token" @@ -253,7 +252,7 @@ type RuntimeConfig struct { // client agents try the first server in the list every time. // // hcl: dns_config { recursor_strategy = "(random|sequential)" } - DNSRecursorStrategy dns.RecursorStrategy + DNSRecursorStrategy structs.RecursorStrategy // DNSRecursorTimeout specifies the timeout in seconds // for Consul's internal dns client used for recursion. @@ -273,7 +272,7 @@ type RuntimeConfig struct { // Records returned in the ANSWER section of a DNS response for UDP // responses without EDNS support (limited to 512 bytes). // This parameter is deprecated, if you want to limit the number of - // records returned by A or AAAA questions, please use DNSARecordLimit + // records returned by A or AAAA questions, please use TestDNS_ServiceLookup_Randomize // instead. // // hcl: dns_config { udp_answer_limit = int } @@ -565,6 +564,15 @@ type RuntimeConfig struct { // flag: -data-dir string DataDir string + // DefaultIntentionPolicy is used to define a default intention action for all + // sources and destinations. Possible values are "allow", "deny", or "" (blank). + // For compatibility, falls back to ACLResolverSettings.ACLDefaultPolicy (which + // itself has a default of "allow") if left blank. Future versions of Consul + // will default this field to "deny" to be secure by default. + // + // hcl: default_intention_policy = string + DefaultIntentionPolicy string + // DefaultQueryTime is the amount of time a blocking query will wait before // Consul will force a response. This value can be overridden by the 'wait' // query parameter. diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index 7158b014d15d..a36d5f67dad9 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -69,6 +69,9 @@ var defaultGrpcTlsAddr = net.TCPAddrFromAddrPort(netip.MustParseAddrPort("127.0. // checks for warnings on deprecated fields and flags. These tests // should check one option at a time if possible func TestLoad_IntegrationWithFlags(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } dataDir := testutil.TempDir(t, "config") run := func(t *testing.T, tc testCase) { @@ -2326,7 +2329,6 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { expected: func(rt *RuntimeConfig) { rt.DataDir = dataDir rt.Cloud = hcpconfig.CloudConfig{ - // ID is only populated from env if not populated from other sources. ResourceID: "env-id", NodeName: "thehostname", NodeID: "", @@ -2368,8 +2370,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { expected: func(rt *RuntimeConfig) { rt.DataDir = dataDir rt.Cloud = hcpconfig.CloudConfig{ - // ID is only populated from env if not populated from other sources. - ResourceID: "file-id", + ResourceID: "env-id", NodeName: "thehostname", } @@ -6014,24 +6015,6 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { rt.RaftLogStoreConfig.WAL.SegmentSize = 64 * 1024 * 1024 }, }) - run(t, testCase{ - desc: "logstore defaults", - args: []string{ - `-data-dir=` + dataDir, - }, - json: []string{` - { - "experiments": ["resource-apis"] - } - `}, - hcl: []string{`experiments=["resource-apis"]`}, - expected: func(rt *RuntimeConfig) { - rt.DataDir = dataDir - rt.RaftLogStoreConfig.Backend = consul.LogStoreBackendDefault - rt.RaftLogStoreConfig.WAL.SegmentSize = 64 * 1024 * 1024 - rt.Experiments = []string{"resource-apis"} - }, - }) run(t, testCase{ // this was a bug in the initial config commit. Specifying part of this // stanza should still result in sensible defaults for the other parts. @@ -6224,6 +6207,9 @@ func (tc testCase) run(format string, dataDir string) func(t *testing.T) { expected.ACLResolverSettings.NodeName = expected.NodeName expected.ACLResolverSettings.EnterpriseMeta = *structs.NodeEnterpriseMetaInPartition(expected.PartitionOrDefault()) + for i, e := range expected.ConfigEntryBootstrap { + e.SetHash(actual.ConfigEntryBootstrap[i].GetHash()) + } prototest.AssertDeepEqual(t, expected, actual, cmpopts.EquateEmpty()) if tc.cleanup != nil { tc.cleanup() @@ -6970,7 +6956,8 @@ func TestLoad_FullConfig(t *testing.T) { Expiration: 15 * time.Second, Name: "ftO6DySn", // notice this is the same as the metrics prefix }, - EnableHostMetrics: true, + EnableHostMetrics: true, + DisablePerTenancyUsageMetrics: true, }, TLS: tlsutil.Config{ InternalRPC: tlsutil.ProtocolConfig{ @@ -7119,6 +7106,9 @@ func TestLoad_FullConfig(t *testing.T) { time.Date(2019, 11, 20, 5, 0, 0, 0, time.UTC))) r, err := Load(opts) require.NoError(t, err) + for i, e := range expected.ConfigEntryBootstrap { + e.SetHash(r.RuntimeConfig.ConfigEntryBootstrap[i].GetHash()) + } prototest.AssertDeepEqual(t, expected, r.RuntimeConfig) require.ElementsMatch(t, expectedWarns, r.Warnings, "Warnings: %#v", r.Warnings) }) diff --git a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden index 56397ad94d0f..5ead1e2f764c 100644 --- a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden +++ b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden @@ -134,11 +134,11 @@ "ClientSecret": "hidden", "Hostname": "", "ManagementToken": "hidden", + "NodeID": "", + "NodeName": "", "ResourceID": "cluster1", "ScadaAddress": "", - "TLSConfig": null, - "NodeID": "", - "NodeName": "" + "TLSConfig": null }, "ConfigEntryBootstrap": [], "ConnectCAConfig": {}, @@ -185,6 +185,7 @@ "DNSUseCache": false, "DataDir": "", "Datacenter": "", + "DefaultIntentionPolicy": "", "DefaultQueryTime": "0s", "DevMode": false, "DisableAnonymousSignature": false, @@ -207,11 +208,11 @@ "ExposeMaxPort": 0, "ExposeMinPort": 0, "GRPCAddrs": [], + "GRPCKeepaliveInterval": "0s", + "GRPCKeepaliveTimeout": "0s", "GRPCPort": 0, "GRPCTLSAddrs": [], "GRPCTLSPort": 0, - "GRPCKeepaliveInterval": "0s", - "GRPCKeepaliveTimeout": "0s", "GossipLANGossipInterval": "0s", "GossipLANGossipNodes": 0, "GossipLANProbeInterval": "0s", @@ -471,6 +472,7 @@ "CirconusSubmissionURL": "", "Disable": false, "DisableHostname": false, + "DisablePerTenancyUsageMetrics": false, "DogstatsdAddr": "", "DogstatsdTags": [], "EnableHostMetrics": false, diff --git a/agent/config/testdata/full-config.hcl b/agent/config/testdata/full-config.hcl index 4c734265fd41..bf3187962748 100644 --- a/agent/config/testdata/full-config.hcl +++ b/agent/config/testdata/full-config.hcl @@ -718,6 +718,7 @@ telemetry { prometheus_retention_time = "15s" statsd_address = "drce87cy" statsite_address = "HpFwKB8R" + disable_per_tenancy_usage_metrics = true } tls { defaults { diff --git a/agent/config/testdata/full-config.json b/agent/config/testdata/full-config.json index 30ede7dd18f1..5816a6713f8a 100644 --- a/agent/config/testdata/full-config.json +++ b/agent/config/testdata/full-config.json @@ -841,7 +841,8 @@ "metrics_prefix": "ftO6DySn", "prometheus_retention_time": "15s", "statsd_address": "drce87cy", - "statsite_address": "HpFwKB8R" + "statsite_address": "HpFwKB8R", + "disable_per_tenancy_usage_metrics": true }, "tls": { "defaults": { @@ -944,4 +945,4 @@ "xds": { "update_max_per_second": 9526.2 } -} \ No newline at end of file +} diff --git a/agent/config_endpoint.go b/agent/config_endpoint.go index e1b3f0eeef41..73d755786b85 100644 --- a/agent/config_endpoint.go +++ b/agent/config_endpoint.go @@ -10,7 +10,12 @@ import ( "strings" "github.com/hashicorp/consul/acl" + external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/proto/private/pbconfigentry" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" ) const ConfigEntryNotFoundErr string = "Config entry not found" @@ -176,3 +181,45 @@ func (s *HTTPHandlers) parseEntMetaForConfigEntryKind(kind string, req *http.Req } return s.parseEntMetaNoWildcard(req, entMeta) } + +// ExportedServices returns all the exported services by resolving wildcards and sameness groups +// in the exported services configuration entry +func (s *HTTPHandlers) ExportedServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) { + var entMeta acl.EnterpriseMeta + if err := s.parseEntMetaPartition(req, &entMeta); err != nil { + return nil, err + } + args := pbconfigentry.GetResolvedExportedServicesRequest{ + Partition: entMeta.PartitionOrEmpty(), + } + + var dc string + options := structs.QueryOptions{} + s.parse(resp, req, &dc, &options) + ctx, err := external.ContextWithQueryOptions(req.Context(), options) + if err != nil { + return nil, err + } + + var header metadata.MD + result, err := s.agent.grpcClientConfigEntry.GetResolvedExportedServices(ctx, &args, grpc.Header(&header)) + if err != nil { + return nil, err + } + + meta, err := external.QueryMetaFromGRPCMeta(header) + if err != nil { + return result.Services, fmt.Errorf("could not convert gRPC metadata to query meta: %w", err) + } + if err := setMeta(resp, &meta); err != nil { + return nil, err + } + + svcs := make([]api.ResolvedExportedService, len(result.Services)) + + for idx, svc := range result.Services { + svcs[idx] = *svc.ToAPI() + } + + return svcs, nil +} diff --git a/agent/config_endpoint_test.go b/agent/config_endpoint_test.go index 43a8ec206e9f..42de720c7993 100644 --- a/agent/config_endpoint_test.go +++ b/agent/config_endpoint_test.go @@ -16,26 +16,10 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/testrpc" ) -func TestConfigEndpointsFailInV2(t *testing.T) { - t.Parallel() - - a := NewTestAgent(t, `experiments = ["resource-apis"]`) - - checkRequest := func(method, url string) { - t.Run(method+" "+url, func(t *testing.T) { - assertV1CatalogEndpointDoesNotWorkWithV2(t, a, method, url, `{"kind":"service-defaults", "name":"web"}`) - }) - } - - checkRequest("GET", "/v1/config/service-defaults") - checkRequest("GET", "/v1/config/service-defaults/web") - checkRequest("DELETE", "/v1/config/service-defaults/web") - checkRequest("PUT", "/v1/config") -} - func TestConfig_Get(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") @@ -141,6 +125,7 @@ func TestConfig_Get(t *testing.T) { // Set indexes and EnterpriseMeta to expected values for assertions ce.CreateIndex = 12 ce.ModifyIndex = 13 + ce.Hash = 0 ce.EnterpriseMeta = acl.EnterpriseMeta{} out, err := a.srv.marshalJSON(req, obj) @@ -450,6 +435,7 @@ func TestConfig_Apply_IngressGateway(t *testing.T) { // Ignore create and modify indices got.CreateIndex = 0 got.ModifyIndex = 0 + got.Hash = 0 expect := &structs.IngressGatewayConfigEntry{ Name: "ingress", @@ -514,6 +500,58 @@ func TestConfig_Apply_ProxyDefaultsMeshGateway(t *testing.T) { } } +func TestConfig_Apply_ProxyDefaultsProtocol(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + + writeConf := func(body string) { + req, _ := http.NewRequest("PUT", "/v1/config", bytes.NewBuffer([]byte(body))) + resp := httptest.NewRecorder() + _, err := a.srv.ConfigApply(resp, req) + require.NoError(t, err) + require.Equal(t, 200, resp.Code, "non-200 Response Code: %s", resp.Body.String()) + } + + // Set the default protocol + writeConf(`{ + "Kind": "proxy-defaults", + "Name": "global", + "Config": { + "Protocol": "http" + } + }`) + + // Create a router that depends on the protocol + writeConf(`{ + "Kind": "service-router", + "Name": "route1" + }`) + + // Ensure we can rewrite the proxy-defaults without a protocol-mismatch error. + // This should be taken care of in the ProxyConfigEntry.Normalize() function. + writeConf(`{ + "Kind": "proxy-defaults", + "Name": "global", + "Config": { + "Protocol": "http", + "some-field": "is_changed" + } + }`) + + // Rewrite the router that depends on the protocol + writeConf(`{ + "Kind": "service-router", + "Name": "route1" + }`) +} + func TestConfig_Apply_CAS(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") @@ -557,7 +595,7 @@ func TestConfig_Apply_CAS(t *testing.T) { { "Kind": "service-defaults", "Name": "foo", - "Protocol": "udp" + "Protocol": "http" } `)) req, _ = http.NewRequest("PUT", "/v1/config?cas=0", body) @@ -573,7 +611,7 @@ func TestConfig_Apply_CAS(t *testing.T) { { "Kind": "service-defaults", "Name": "foo", - "Protocol": "udp" + "Protocol": "http" } `)) req, _ = http.NewRequest("PUT", fmt.Sprintf("/v1/config?cas=%d", entry.GetRaftIndex().ModifyIndex), body) @@ -734,3 +772,84 @@ func TestConfig_Apply_ProxyDefaultsExpose(t *testing.T) { require.Equal(t, expose, entry.Expose) } } + +func TestConfig_Exported_Services(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + a := NewTestAgent(t, "") + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + defer a.Shutdown() + + { + // Register exported services + args := &structs.ExportedServicesConfigEntry{ + Name: "default", + Services: []structs.ExportedService{ + { + Name: "api", + Consumers: []structs.ServiceConsumer{ + { + Peer: "east", + }, + { + Peer: "west", + }, + }, + }, + { + Name: "db", + Consumers: []structs.ServiceConsumer{ + { + Peer: "east", + }, + }, + }, + }, + } + req := structs.ConfigEntryRequest{ + Datacenter: "dc1", + Entry: args, + } + var configOutput bool + require.NoError(t, a.RPC(context.Background(), "ConfigEntry.Apply", &req, &configOutput)) + require.True(t, configOutput) + } + + t.Run("exported services", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/exported-services", nil) + resp := httptest.NewRecorder() + raw, err := a.srv.ExportedServices(resp, req) + require.NoError(t, err) + require.Equal(t, http.StatusOK, resp.Code) + + services, ok := raw.([]api.ResolvedExportedService) + require.True(t, ok) + require.Len(t, services, 2) + assertIndex(t, resp) + + entMeta := acl.DefaultEnterpriseMeta() + + expected := []api.ResolvedExportedService{ + { + Service: "api", + Partition: entMeta.PartitionOrEmpty(), + Namespace: entMeta.NamespaceOrEmpty(), + Consumers: api.ResolvedConsumers{ + Peers: []string{"east", "west"}, + }, + }, + { + Service: "db", + Partition: entMeta.PartitionOrEmpty(), + Namespace: entMeta.NamespaceOrEmpty(), + Consumers: api.ResolvedConsumers{ + Peers: []string{"east"}, + }, + }, + } + require.Equal(t, expected, services) + }) +} diff --git a/agent/configentry/compare.go b/agent/configentry/compare.go index 3bf761dba828..c6a469f25f79 100644 --- a/agent/configentry/compare.go +++ b/agent/configentry/compare.go @@ -38,3 +38,10 @@ func EqualID(e1, e2 structs.ConfigEntry) bool { e1.GetEnterpriseMeta().IsSame(e2.GetEnterpriseMeta()) && e1.GetName() == e2.GetName() } + +func SameHash(e1, e2 structs.ConfigEntry) bool { + if e1.GetHash() == 0 || e2.GetHash() == 0 { + return false + } + return e1.GetHash() == e2.GetHash() +} diff --git a/agent/connect/ca/provider_vault_test.go b/agent/connect/ca/provider_vault_test.go index edd094f5502a..5b74946cada9 100644 --- a/agent/connect/ca/provider_vault_test.go +++ b/agent/connect/ca/provider_vault_test.go @@ -295,7 +295,7 @@ func TestVaultCAProvider_ConfigureFailureGoroutineLeakCheck(t *testing.T) { profile := pprof.Lookup("goroutine") sb := strings.Builder{} require.NoError(r, profile.WriteTo(&sb, 2)) - t.Log(sb.String()) + r.Log(sb.String()) require.Contains(r, sb.String(), "created by github.com/hashicorp/consul/agent/connect/ca.(*VaultProvider).Configure", "expected renewal goroutine, got none") @@ -628,6 +628,9 @@ func TestVaultCAProvider_SignLeaf(t *testing.T) { } func TestVaultCAProvider_CrossSignCA(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } SkipIfVaultNotPresent(t) t.Parallel() diff --git a/agent/connect/ca/testing.go b/agent/connect/ca/testing.go index 7386deea9494..8fcf8a3c6533 100644 --- a/agent/connect/ca/testing.go +++ b/agent/connect/ca/testing.go @@ -126,7 +126,7 @@ func SkipIfVaultNotPresent(t testing.T, reqs ...vaultRequirements) { } } -func NewTestVaultServer(t testing.T) *TestVaultServer { +func NewTestVaultServer(t retry.TestingTB) *TestVaultServer { vaultBinaryName := os.Getenv("VAULT_BINARY_NAME") if vaultBinaryName == "" { vaultBinaryName = "vault" @@ -204,7 +204,7 @@ func (v *TestVaultServer) Client() *vaultapi.Client { return v.client } -func (v *TestVaultServer) WaitUntilReady(t testing.T) { +func (v *TestVaultServer) WaitUntilReady(t retry.TestingTB) { var version string retry.Run(t, func(r *retry.R) { resp, err := v.client.Sys().Health() diff --git a/agent/connect/generate.go b/agent/connect/generate.go index 84c91a246846..4679e2057b92 100644 --- a/agent/connect/generate.go +++ b/agent/connect/generate.go @@ -21,6 +21,11 @@ const ( DefaultPrivateKeyType = "ec" DefaultPrivateKeyBits = 256 DefaultIntermediateCertTTL = 24 * 365 * time.Hour + + // RSA specific settings. + PrivateKeyTypeRSA = "rsa" + MinPrivateKeyBitsRSA = 2048 + DefaultPrivateKeyBitsRSA = 4096 ) func pemEncode(value []byte, blockType string) (string, error) { @@ -35,6 +40,11 @@ func pemEncode(value []byte, blockType string) (string, error) { func generateRSAKey(keyBits int) (crypto.Signer, string, error) { var pk *rsa.PrivateKey + // Check for a secure key length. + if keyBits < MinPrivateKeyBitsRSA { + return nil, "", fmt.Errorf("error generating RSA private key: invalid key size %d, must be at least %d bits", keyBits, MinPrivateKeyBitsRSA) + } + pk, err := rsa.GenerateKey(rand.Reader, keyBits) if err != nil { return nil, "", fmt.Errorf("error generating RSA private key: %s", err) @@ -87,9 +97,9 @@ func generateECDSAKey(keyBits int) (crypto.Signer, string, error) { // GeneratePrivateKey generates a new Private key func GeneratePrivateKeyWithConfig(keyType string, keyBits int) (crypto.Signer, string, error) { switch strings.ToLower(keyType) { - case "rsa": + case PrivateKeyTypeRSA: return generateRSAKey(keyBits) - case "ec": + case DefaultPrivateKeyType: return generateECDSAKey(keyBits) default: return nil, "", fmt.Errorf("unknown private key type requested: %s", keyType) diff --git a/agent/connect/testing_spiffe.go b/agent/connect/testing_spiffe.go index fdbff5eda67d..e50b2b3b90cd 100644 --- a/agent/connect/testing_spiffe.go +++ b/agent/connect/testing_spiffe.go @@ -3,24 +3,22 @@ package connect -import ( - "github.com/mitchellh/go-testing-interface" -) +import "github.com/hashicorp/consul/sdk/testutil" // TestSpiffeIDService returns a SPIFFE ID representing a service. -func TestSpiffeIDService(t testing.T, service string) *SpiffeIDService { +func TestSpiffeIDService(t testutil.TestingTB, service string) *SpiffeIDService { return TestSpiffeIDServiceWithHost(t, service, TestClusterID+".consul") } // TestSpiffeIDServiceWithHost returns a SPIFFE ID representing a service with // the specified trust domain. -func TestSpiffeIDServiceWithHost(t testing.T, service, host string) *SpiffeIDService { +func TestSpiffeIDServiceWithHost(t testutil.TestingTB, service, host string) *SpiffeIDService { return TestSpiffeIDServiceWithHostDC(t, service, host, "dc1") } // TestSpiffeIDServiceWithHostDC returns a SPIFFE ID representing a service with // the specified trust domain for the given datacenter. -func TestSpiffeIDServiceWithHostDC(t testing.T, service, host, datacenter string) *SpiffeIDService { +func TestSpiffeIDServiceWithHostDC(t testutil.TestingTB, service, host, datacenter string) *SpiffeIDService { return &SpiffeIDService{ Host: host, Namespace: "default", diff --git a/agent/connect/uri.go b/agent/connect/uri.go index bc898f78654f..d9d5aa037d8a 100644 --- a/agent/connect/uri.go +++ b/agent/connect/uri.go @@ -23,8 +23,6 @@ type CertURI interface { } var ( - spiffeIDWorkloadIdentityRegexp = regexp.MustCompile( - `^(?:/ap/([^/]+))/ns/([^/]+)/identity/([^/]+)$`) spiffeIDServiceRegexp = regexp.MustCompile( `^(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/]+)$`) spiffeIDAgentRegexp = regexp.MustCompile( @@ -96,32 +94,6 @@ func ParseCertURI(input *url.URL) (CertURI, error) { Datacenter: dc, Service: service, }, nil - } else if v := spiffeIDWorkloadIdentityRegexp.FindStringSubmatch(path); v != nil { - // Determine the values. We assume they're reasonable to save cycles, - // but if the raw path is not empty that means that something is - // URL encoded so we go to the slow path. - ap := v[1] - ns := v[2] - workloadIdentity := v[3] - if input.RawPath != "" { - var err error - if ap, err = url.PathUnescape(v[1]); err != nil { - return nil, fmt.Errorf("Invalid admin partition: %s", err) - } - if ns, err = url.PathUnescape(v[2]); err != nil { - return nil, fmt.Errorf("Invalid namespace: %s", err) - } - if workloadIdentity, err = url.PathUnescape(v[3]); err != nil { - return nil, fmt.Errorf("Invalid workload identity: %s", err) - } - } - - return &SpiffeIDWorkloadIdentity{ - TrustDomain: input.Host, - Partition: ap, - Namespace: ns, - WorkloadIdentity: workloadIdentity, - }, nil } else if v := spiffeIDAgentRegexp.FindStringSubmatch(path); v != nil { // Determine the values. We assume they're reasonable to save cycles, // but if the raw path is not empty that means that something is diff --git a/agent/connect/uri_service.go b/agent/connect/uri_service.go index b35d1e0df437..3be7cf4797a3 100644 --- a/agent/connect/uri_service.go +++ b/agent/connect/uri_service.go @@ -8,7 +8,6 @@ import ( "net/url" "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/proto-public/pbresource" ) // SpiffeIDService is the structure to represent the SPIFFE ID for a service. @@ -53,14 +52,3 @@ func (id SpiffeIDService) uriPath() string { } return path } - -// SpiffeIDFromIdentityRef creates the SPIFFE ID from a workload identity. -// TODO (ishustava): make sure ref type is workload identity. -func SpiffeIDFromIdentityRef(trustDomain string, ref *pbresource.Reference) string { - return SpiffeIDWorkloadIdentity{ - TrustDomain: trustDomain, - Partition: ref.Tenancy.Partition, - Namespace: ref.Tenancy.Namespace, - WorkloadIdentity: ref.Name, - }.URI().String() -} diff --git a/agent/connect/uri_signing.go b/agent/connect/uri_signing.go index 1913ae6bdfdf..9f2807d2ba68 100644 --- a/agent/connect/uri_signing.go +++ b/agent/connect/uri_signing.go @@ -51,12 +51,6 @@ func (id SpiffeIDSigning) CanSign(cu CertURI) bool { // worry about Unicode domains if we start allowing customisation beyond the // built-in cluster ids. return strings.ToLower(other.Host) == id.Host() - case *SpiffeIDWorkloadIdentity: - // The trust domain component of the workload identity SPIFFE ID must be an exact match for now under - // ascii case folding (since hostnames are case-insensitive). Later we might - // worry about Unicode domains if we start allowing customisation beyond the - // built-in cluster ids. - return strings.ToLower(other.TrustDomain) == id.Host() case *SpiffeIDMeshGateway: // The host component of the mesh gateway SPIFFE ID must be an exact match for now under // ascii case folding (since hostnames are case-insensitive). Later we might diff --git a/agent/connect/uri_signing_test.go b/agent/connect/uri_signing_test.go index 737ca460542b..edd3d468931b 100644 --- a/agent/connect/uri_signing_test.go +++ b/agent/connect/uri_signing_test.go @@ -98,30 +98,6 @@ func TestSpiffeIDSigning_CanSign(t *testing.T) { input: &SpiffeIDService{Host: TestClusterID + ".fake", Namespace: "default", Datacenter: "dc1", Service: "web"}, want: false, }, - { - name: "workload - good", - id: testSigning, - input: &SpiffeIDWorkloadIdentity{TrustDomain: TestClusterID + ".consul", Namespace: "default", WorkloadIdentity: "web"}, - want: true, - }, - { - name: "workload - good mixed case", - id: testSigning, - input: &SpiffeIDWorkloadIdentity{TrustDomain: strings.ToUpper(TestClusterID) + ".CONsuL", Namespace: "defAUlt", WorkloadIdentity: "WEB"}, - want: true, - }, - { - name: "workload - different cluster", - id: testSigning, - input: &SpiffeIDWorkloadIdentity{TrustDomain: "55555555-4444-3333-2222-111111111111.consul", Namespace: "default", WorkloadIdentity: "web"}, - want: false, - }, - { - name: "workload - different TLD", - id: testSigning, - input: &SpiffeIDWorkloadIdentity{TrustDomain: TestClusterID + ".fake", Namespace: "default", WorkloadIdentity: "web"}, - want: false, - }, { name: "mesh gateway - good", id: testSigning, diff --git a/agent/connect/uri_test.go b/agent/connect/uri_test.go index 52116845975b..fcbcf42ab3a2 100644 --- a/agent/connect/uri_test.go +++ b/agent/connect/uri_test.go @@ -51,61 +51,6 @@ func TestParseCertURIFromString(t *testing.T) { }, ParseError: "", }, - { - Name: "basic workload ID", - URI: "spiffe://1234.consul/ap/default/ns/default/identity/web", - Struct: &SpiffeIDWorkloadIdentity{ - TrustDomain: "1234.consul", - Partition: defaultEntMeta.PartitionOrDefault(), - Namespace: "default", - WorkloadIdentity: "web", - }, - ParseError: "", - }, - { - Name: "basic workload ID with nondefault partition", - URI: "spiffe://1234.consul/ap/bizdev/ns/default/identity/web", - Struct: &SpiffeIDWorkloadIdentity{ - TrustDomain: "1234.consul", - Partition: "bizdev", - Namespace: "default", - WorkloadIdentity: "web", - }, - ParseError: "", - }, - { - Name: "workload ID error - missing identity", - URI: "spiffe://1234.consul/ns/default", - Struct: &SpiffeIDWorkloadIdentity{ - TrustDomain: "1234.consul", - Partition: defaultEntMeta.PartitionOrDefault(), - Namespace: "default", - WorkloadIdentity: "web", - }, - ParseError: "SPIFFE ID is not in the expected format", - }, - { - Name: "workload ID error - missing partition", - URI: "spiffe://1234.consul/ns/default/identity/web", - Struct: &SpiffeIDWorkloadIdentity{ - TrustDomain: "1234.consul", - Partition: defaultEntMeta.PartitionOrDefault(), - Namespace: "default", - WorkloadIdentity: "web", - }, - ParseError: "SPIFFE ID is not in the expected format", - }, - { - Name: "workload ID error - missing namespace", - URI: "spiffe://1234.consul/ap/default/identity/web", - Struct: &SpiffeIDWorkloadIdentity{ - TrustDomain: "1234.consul", - Partition: defaultEntMeta.PartitionOrDefault(), - Namespace: "default", - WorkloadIdentity: "web", - }, - ParseError: "SPIFFE ID is not in the expected format", - }, { Name: "basic agent ID", URI: "spiffe://1234.consul/agent/client/dc/dc1/id/uuid", diff --git a/agent/connect/uri_workload_identity.go b/agent/connect/uri_workload_identity.go deleted file mode 100644 index 48afd1f534b2..000000000000 --- a/agent/connect/uri_workload_identity.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package connect - -import ( - "fmt" - "net/url" - - "github.com/hashicorp/consul/acl" -) - -// SpiffeIDWorkloadIdentity is the structure to represent the SPIFFE ID for a workload. -type SpiffeIDWorkloadIdentity struct { - TrustDomain string - Partition string - Namespace string - WorkloadIdentity string -} - -func (id SpiffeIDWorkloadIdentity) NamespaceOrDefault() string { - return acl.NamespaceOrDefault(id.Namespace) -} - -// URI returns the *url.URL for this SPIFFE ID. -func (id SpiffeIDWorkloadIdentity) URI() *url.URL { - var result url.URL - result.Scheme = "spiffe" - result.Host = id.TrustDomain - result.Path = id.uriPath() - return &result -} - -func (id SpiffeIDWorkloadIdentity) uriPath() string { - // Although CE has no support for partitions, it still needs to be able to - // handle exportedPartition from peered Consul Enterprise clusters in order - // to generate the correct SpiffeID. - // We intentionally avoid using pbpartition.DefaultName here to be CE friendly. - path := fmt.Sprintf("/ap/%s/ns/%s/identity/%s", - id.PartitionOrDefault(), - id.NamespaceOrDefault(), - id.WorkloadIdentity, - ) - - return path -} diff --git a/agent/connect/uri_workload_identity_ce.go b/agent/connect/uri_workload_identity_ce.go deleted file mode 100644 index 99544b014efa..000000000000 --- a/agent/connect/uri_workload_identity_ce.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent - -package connect - -import ( - "strings" - - "github.com/hashicorp/consul/acl" -) - -// GetEnterpriseMeta will synthesize an EnterpriseMeta struct from the SpiffeIDWorkloadIdentity. -// in CE this just returns an empty (but never nil) struct pointer -func (id SpiffeIDWorkloadIdentity) GetEnterpriseMeta() *acl.EnterpriseMeta { - return &acl.EnterpriseMeta{} -} - -// PartitionOrDefault breaks from CE's pattern of returning empty strings. -// Although CE has no support for partitions, it still needs to be able to -// handle exportedPartition from peered Consul Enterprise clusters in order -// to generate the correct SpiffeID. -func (id SpiffeIDWorkloadIdentity) PartitionOrDefault() string { - if id.Partition == "" { - return "default" - } - - return strings.ToLower(id.Partition) -} diff --git a/agent/connect/uri_workload_identity_ce_test.go b/agent/connect/uri_workload_identity_ce_test.go deleted file mode 100644 index 17a2cc3d4a0e..000000000000 --- a/agent/connect/uri_workload_identity_ce_test.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent - -package connect - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestSpiffeIDWorkloadURI(t *testing.T) { - t.Run("default partition; default namespace", func(t *testing.T) { - wl := &SpiffeIDWorkloadIdentity{ - TrustDomain: "1234.consul", - WorkloadIdentity: "web", - } - require.Equal(t, "spiffe://1234.consul/ap/default/ns/default/identity/web", wl.URI().String()) - }) - - t.Run("namespaces are ignored", func(t *testing.T) { - wl := &SpiffeIDWorkloadIdentity{ - TrustDomain: "1234.consul", - WorkloadIdentity: "web", - Namespace: "other", - } - require.Equal(t, "spiffe://1234.consul/ap/default/ns/default/identity/web", wl.URI().String()) - }) - - t.Run("partitions are not ignored", func(t *testing.T) { - wl := &SpiffeIDWorkloadIdentity{ - TrustDomain: "1234.consul", - WorkloadIdentity: "web", - Partition: "other", - } - require.Equal(t, "spiffe://1234.consul/ap/other/ns/default/identity/web", wl.URI().String()) - }) -} diff --git a/agent/consul/acl.go b/agent/consul/acl.go index ddba359d949f..cdfcad640a3c 100644 --- a/agent/consul/acl.go +++ b/agent/consul/acl.go @@ -221,6 +221,23 @@ type ACLResolverSettings struct { ACLDefaultPolicy string } +func (a ACLResolverSettings) CheckACLs() error { + switch a.ACLDefaultPolicy { + case "allow": + case "deny": + default: + return fmt.Errorf("Unsupported default ACL policy: %s", a.ACLDefaultPolicy) + } + switch a.ACLDownPolicy { + case "allow": + case "deny": + case "async-cache", "extend-cache": + default: + return fmt.Errorf("Unsupported down ACL policy: %s", a.ACLDownPolicy) + } + return nil +} + func (s ACLResolverSettings) IsDefaultAllow() (bool, error) { switch s.ACLDefaultPolicy { case "allow": diff --git a/agent/consul/acl_endpoint_test.go b/agent/consul/acl_endpoint_test.go index 39840942d185..4ed159a8aa64 100644 --- a/agent/consul/acl_endpoint_test.go +++ b/agent/consul/acl_endpoint_test.go @@ -11,9 +11,9 @@ import ( "testing" "time" + "github.com/go-jose/go-jose/v3/jwt" "github.com/hashicorp/go-uuid" "github.com/stretchr/testify/require" - "gopkg.in/square/go-jose.v2/jwt" msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc" "github.com/hashicorp/consul-net-rpc/net/rpc" @@ -3663,6 +3663,37 @@ func TestACLEndpoint_BindingRuleSet(t *testing.T) { require.Equal(t, "test-node", rule.BindName) }) + t.Run("Bind Policy", func(t *testing.T) { + req := structs.ACLBindingRuleSetRequest{ + Datacenter: "dc1", + BindingRule: structs.ACLBindingRule{ + Description: "foobar policy", + AuthMethod: testAuthMethod.Name, + Selector: "serviceaccount.name==abc", + BindType: structs.BindingRuleBindTypePolicy, + BindName: "test-policy", + }, + WriteRequest: structs.WriteRequest{Token: TestDefaultInitialManagementToken}, + } + var resp structs.ACLBindingRule + + err := aclEp.BindingRuleSet(&req, &resp) + require.NoError(t, err) + require.NotNil(t, resp.ID) + + // Get the rule directly to validate that it exists + ruleResp, err := retrieveTestBindingRule(codec, TestDefaultInitialManagementToken, "dc1", resp.ID) + require.NoError(t, err) + rule := ruleResp.BindingRule + + require.NotEmpty(t, rule.ID) + require.Equal(t, rule.Description, "foobar policy") + require.Equal(t, rule.AuthMethod, testAuthMethod.Name) + require.Equal(t, "serviceaccount.name==abc", rule.Selector) + require.Equal(t, structs.BindingRuleBindTypePolicy, rule.BindType) + require.Equal(t, "test-policy", rule.BindName) + }) + t.Run("templated policy", func(t *testing.T) { req := structs.ACLBindingRuleSetRequest{ Datacenter: "dc1", @@ -3841,7 +3872,7 @@ func TestACLEndpoint_BindingRuleSet(t *testing.T) { t.Run("Create fails; invalid bind type", func(t *testing.T) { reqRule := newRule() reqRule.BindType = "invalid" - requireSetErrors(t, reqRule, "Invalid Binding Rule: unknown BindType") + requireSetErrors(t, reqRule, "invalid Binding Rule: unknown BindType") }) t.Run("Create fails; bind name with unknown vars", func(t *testing.T) { @@ -4540,6 +4571,11 @@ func TestACLEndpoint_Login(t *testing.T) { "fake-node", "default", "mynode", "jkl101", ) + testauth.InstallSessionToken( + testSessionID, + "fake-policy", // 1 rule (policy) + "default", "mypolicy", "jkl012", + ) method, err := upsertTestAuthMethod(codec, TestDefaultInitialManagementToken, "dc1", testSessionID) require.NoError(t, err) @@ -4587,6 +4623,15 @@ func TestACLEndpoint_Login(t *testing.T) { ) require.NoError(t, err) + // policy rule + _, err = upsertTestBindingRule( + codec, TestDefaultInitialManagementToken, "dc1", method.Name, + "serviceaccount.namespace==default and serviceaccount.name==mypolicy", + structs.BindingRuleBindTypePolicy, + "method-${serviceaccount.name}", + ) + require.NoError(t, err) + t.Run("do not provide a token", func(t *testing.T) { req := structs.ACLLoginRequest{ Auth: &structs.ACLLoginParams{ diff --git a/agent/consul/auth/binder.go b/agent/consul/auth/binder.go index 1964cc5a877e..ba66bc916bdb 100644 --- a/agent/consul/auth/binder.go +++ b/agent/consul/auth/binder.go @@ -36,14 +36,16 @@ func NewBinder(store BinderStateStore, datacenter string) *Binder { type BinderStateStore interface { ACLBindingRuleList(ws memdb.WatchSet, methodName string, entMeta *acl.EnterpriseMeta) (uint64, structs.ACLBindingRules, error) ACLRoleGetByName(ws memdb.WatchSet, roleName string, entMeta *acl.EnterpriseMeta) (uint64, *structs.ACLRole, error) + ACLPolicyGetByName(ws memdb.WatchSet, policyName string, entMeta *acl.EnterpriseMeta) (uint64, *structs.ACLPolicy, error) } -// Bindings contains the ACL roles, service identities, node identities, +// Bindings contains the ACL roles, service identities, node identities, policies, // templated policies, and enterprise meta to be assigned to the created token. type Bindings struct { Roles []structs.ACLTokenRoleLink ServiceIdentities []*structs.ACLServiceIdentity NodeIdentities []*structs.ACLNodeIdentity + Policies []structs.ACLTokenPolicyLink TemplatedPolicies structs.ACLTemplatedPolicies EnterpriseMeta acl.EnterpriseMeta } @@ -58,7 +60,8 @@ func (b *Bindings) None() bool { return len(b.ServiceIdentities) == 0 && len(b.NodeIdentities) == 0 && len(b.TemplatedPolicies) == 0 && - len(b.Roles) == 0 + len(b.Roles) == 0 && + len(b.Policies) == 0 } // Bind collects the ACL roles, service identities, etc. to be assigned to the @@ -119,6 +122,24 @@ func (b *Binder) Bind(authMethod *structs.ACLAuthMethod, verifiedIdentity *authm } bindings.TemplatedPolicies = append(bindings.TemplatedPolicies, templatedPolicy) + case structs.BindingRuleBindTypePolicy: + bindName, err := computeBindName(rule.BindName, verifiedIdentity.ProjectedVars, acl.IsValidRoleName) + if err != nil { + return nil, err + } + + _, policy, err := b.store.ACLPolicyGetByName(nil, bindName, &bindings.EnterpriseMeta) + if err != nil { + return nil, err + } + + if policy != nil { + bindings.Policies = append(bindings.Policies, structs.ACLTokenPolicyLink{ + ID: policy.ID, + Name: policy.Name, + }) + } + case structs.BindingRuleBindTypeRole: bindName, err := computeBindName(rule.BindName, verifiedIdentity.ProjectedVars, acl.IsValidRoleName) if err != nil { @@ -177,8 +198,13 @@ func IsValidBindingRule(bindType, bindName string, bindVars *structs.ACLTemplate if _, err := computeBindName(bindName, fakeVarMap, acl.IsValidRoleName); err != nil { return fmt.Errorf("failed to validate bindType %q: %w", bindType, err) } + + case structs.BindingRuleBindTypePolicy: + if _, err := computeBindName(bindName, fakeVarMap, acl.IsValidPolicyName); err != nil { + return fmt.Errorf("failed to validate bindType %q: %w", bindType, err) + } default: - return fmt.Errorf("Invalid Binding Rule: unknown BindType %q", bindType) + return fmt.Errorf("invalid Binding Rule: unknown BindType %q", bindType) } return nil diff --git a/agent/consul/auth/binder_test.go b/agent/consul/auth/binder_test.go index 41e0d14ddc35..3220ff2b303c 100644 --- a/agent/consul/auth/binder_test.go +++ b/agent/consul/auth/binder_test.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/consul/agent/consul/authmethod" "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" ) func TestBindings_None(t *testing.T) { @@ -27,11 +28,79 @@ func TestBindings_None(t *testing.T) { b = &Bindings{Roles: []structs.ACLTokenRoleLink{{ID: generateID(t)}}} require.False(t, b.None()) + b = &Bindings{Policies: []structs.ACLTokenPolicyLink{{ID: generateID(t)}}} + require.False(t, b.None()) + b = &Bindings{ServiceIdentities: []*structs.ACLServiceIdentity{{ServiceName: "web"}}} require.False(t, b.None()) b = &Bindings{NodeIdentities: []*structs.ACLNodeIdentity{{NodeName: "node-123"}}} require.False(t, b.None()) + + b = &Bindings{TemplatedPolicies: []*structs.ACLTemplatedPolicy{{TemplateName: api.ACLTemplatedPolicyDNSName}}} + require.False(t, b.None()) +} + +func TestBinder_Policy_Success(t *testing.T) { + store := testStateStore(t) + binder := &Binder{store: store} + + authMethod := &structs.ACLAuthMethod{ + Name: "test-auth-method", + Type: "testing", + } + require.NoError(t, store.ACLAuthMethodSet(0, authMethod)) + + targetPolicy := &structs.ACLPolicy{ + ID: generateID(t), + Name: "foo-policy", + } + require.NoError(t, store.ACLPolicySet(0, targetPolicy)) + + otherPolicy := &structs.ACLPolicy{ + ID: generateID(t), + Name: "not-my-policy", + } + require.NoError(t, store.ACLPolicySet(0, otherPolicy)) + + bindingRules := structs.ACLBindingRules{ + { + ID: generateID(t), + Selector: "role==engineer", + BindType: structs.BindingRuleBindTypePolicy, + BindName: "${editor}-policy", + AuthMethod: authMethod.Name, + }, + { + ID: generateID(t), + Selector: "role==engineer", + BindType: structs.BindingRuleBindTypePolicy, + BindName: "this-policy-does-not-exist", + AuthMethod: authMethod.Name, + }, + { + ID: generateID(t), + Selector: "language==js", + BindType: structs.BindingRuleBindTypePolicy, + BindName: otherPolicy.Name, + AuthMethod: authMethod.Name, + }, + } + require.NoError(t, store.ACLBindingRuleBatchSet(0, bindingRules)) + + result, err := binder.Bind(&structs.ACLAuthMethod{}, &authmethod.Identity{ + SelectableFields: map[string]string{ + "role": "engineer", + "language": "go", + }, + ProjectedVars: map[string]string{ + "editor": "foo", + }, + }) + require.NoError(t, err) + require.Equal(t, []structs.ACLTokenPolicyLink{ + {ID: targetPolicy.ID, Name: targetPolicy.Name}, + }, result.Policies) } func TestBinder_Roles_Success(t *testing.T) { @@ -122,6 +191,32 @@ func TestBinder_Roles_NameValidation(t *testing.T) { require.Contains(t, err.Error(), "invalid bind name") } +func TestBinder_Policy_NameValidation(t *testing.T) { + store := testStateStore(t) + binder := &Binder{store: store} + + authMethod := &structs.ACLAuthMethod{ + Name: "test-auth-method", + Type: "testing", + } + require.NoError(t, store.ACLAuthMethodSet(0, authMethod)) + + bindingRules := structs.ACLBindingRules{ + { + ID: generateID(t), + Selector: "", + BindType: structs.BindingRuleBindTypePolicy, + BindName: "INVALID!", + AuthMethod: authMethod.Name, + }, + } + require.NoError(t, store.ACLBindingRuleBatchSet(0, bindingRules)) + + _, err := binder.Bind(&structs.ACLAuthMethod{}, &authmethod.Identity{}) + require.Error(t, err) + require.Contains(t, err.Error(), "invalid bind name") +} + func TestBinder_ServiceIdentities_Success(t *testing.T) { store := testStateStore(t) binder := &Binder{store: store} @@ -275,54 +370,60 @@ func Test_IsValidBindingRule(t *testing.T) { "invalid", "blah", nil, "", true}, // valid HIL, invalid name {"empty", - "both", "", nil, "", true}, + "all", "", nil, "", true}, {"just end", - "both", "}", nil, "", true}, + "all", "}", nil, "", true}, {"var without start", - "both", " item }", nil, "item", true}, + "all", " item }", nil, "item", true}, {"two vars missing second start", - "both", "before-${ item }after--more }", nil, "item,more", true}, + "all", "before-${ item }after--more }", nil, "item,more", true}, // names for the two types are validated differently {"@ is disallowed", - "both", "bad@name", nil, "", true}, + "all", "bad@name", nil, "", true}, {"leading dash", "role", "-name", nil, "", false}, + {"leading dash", + "policy", "-name", nil, "", false}, {"leading dash", "service", "-name", nil, "", true}, {"trailing dash", "role", "name-", nil, "", false}, + {"trailing dash", + "policy", "name-", nil, "", false}, {"trailing dash", "service", "name-", nil, "", true}, {"inner dash", - "both", "name-end", nil, "", false}, + "all", "name-end", nil, "", false}, {"upper case", "role", "NAME", nil, "", false}, + {"upper case", + "policy", "NAME", nil, "", false}, {"upper case", "service", "NAME", nil, "", true}, // valid HIL, valid name {"no vars", - "both", "nothing", nil, "", false}, + "all", "nothing", nil, "", false}, {"just var", - "both", "${item}", nil, "item", false}, + "all", "${item}", nil, "item", false}, {"var in middle", - "both", "before-${item}after", nil, "item", false}, + "all", "before-${item}after", nil, "item", false}, {"two vars", - "both", "before-${item}after-${more}", nil, "item,more", false}, + "all", "before-${item}after-${more}", nil, "item,more", false}, // bad {"no bind name", - "both", "", nil, "", true}, + "all", "", nil, "", true}, {"just start", - "both", "${", nil, "", true}, + "all", "${", nil, "", true}, {"backwards", - "both", "}${", nil, "", true}, + "all", "}${", nil, "", true}, {"no varname", - "both", "${}", nil, "", true}, + "all", "${}", nil, "", true}, {"missing map key", - "both", "${item}", nil, "", true}, + "all", "${item}", nil, "", true}, {"var without end", - "both", "${ item ", nil, "item", true}, + "all", "${ item ", nil, "item", true}, {"two vars missing first end", - "both", "before-${ item after-${ more }", nil, "item,more", true}, + "all", "before-${ item after-${ more }", nil, "item,more", true}, // bind type: templated policy - bad input {"templated-policy missing bindvars", "templated-policy", "builtin/service", nil, "", true}, @@ -338,12 +439,16 @@ func Test_IsValidBindingRule(t *testing.T) { "templated-policy", "builtin/service", &structs.ACLTemplatedPolicyVariables{Name: "before-${item}after-${more}"}, "item,more", false}, } { var cases []testcase - if test.bindType == "both" { + if test.bindType == "all" { test1 := test test1.bindType = "role" test2 := test test2.bindType = "service" - cases = []testcase{test1, test2} + test3 := test + test3.bindType = "policy" + test4 := test + test4.bindType = "node" + cases = []testcase{test1, test2, test3, test4} } else { cases = []testcase{test} } diff --git a/agent/consul/auth/login.go b/agent/consul/auth/login.go index a084f33bf19b..0b9b5eeac77a 100644 --- a/agent/consul/auth/login.go +++ b/agent/consul/auth/login.go @@ -48,6 +48,7 @@ func (l *Login) TokenForVerifiedIdentity(identity *authmethod.Identity, authMeth NodeIdentities: bindings.NodeIdentities, TemplatedPolicies: bindings.TemplatedPolicies, Roles: bindings.Roles, + Policies: bindings.Policies, EnterpriseMeta: bindings.EnterpriseMeta, } token.ACLAuthMethodEnterpriseMeta.FillWithEnterpriseMeta(&authMethod.EnterpriseMeta) diff --git a/agent/consul/authmethod/kubeauth/k8s.go b/agent/consul/authmethod/kubeauth/k8s.go index 274dd2ec9d03..f223c68555d2 100644 --- a/agent/consul/authmethod/kubeauth/k8s.go +++ b/agent/consul/authmethod/kubeauth/k8s.go @@ -9,9 +9,9 @@ import ( "fmt" "strings" + "github.com/go-jose/go-jose/v3/jwt" cleanhttp "github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/go-hclog" - "gopkg.in/square/go-jose.v2/jwt" authv1 "k8s.io/api/authentication/v1" client_metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" k8s "k8s.io/client-go/kubernetes" diff --git a/agent/consul/authmethod/ssoauth/sso_test.go b/agent/consul/authmethod/ssoauth/sso_test.go index 357612fad689..ff2ea63d112e 100644 --- a/agent/consul/authmethod/ssoauth/sso_test.go +++ b/agent/consul/authmethod/ssoauth/sso_test.go @@ -8,9 +8,9 @@ import ( "testing" "time" + "github.com/go-jose/go-jose/v3/jwt" "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/require" - "gopkg.in/square/go-jose.v2/jwt" "github.com/hashicorp/consul/agent/consul/authmethod" "github.com/hashicorp/consul/agent/structs" diff --git a/agent/consul/auto_config_endpoint.go b/agent/consul/auto_config_endpoint.go index f491bcbad832..6c4a1b4f71f4 100644 --- a/agent/consul/auto_config_endpoint.go +++ b/agent/consul/auto_config_endpoint.go @@ -11,12 +11,12 @@ import ( "regexp" "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/internal/dnsutil" bexpr "github.com/hashicorp/go-bexpr" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/authmethod/ssoauth" - "github.com/hashicorp/consul/agent/dns" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/lib/template" "github.com/hashicorp/consul/proto/private/pbautoconf" @@ -80,7 +80,7 @@ func (a *jwtAuthorizer) Authorize(req *pbautoconf.AutoConfigRequest) (AutoConfig if invalidSegmentName.MatchString(req.Segment) { return AutoConfigOptions{}, fmt.Errorf("Invalid request field. %v = `%v`", "segment", req.Segment) } - if req.Partition != "" && !dns.IsValidLabel(req.Partition) { + if req.Partition != "" && !dnsutil.IsValidLabel(req.Partition) { return AutoConfigOptions{}, fmt.Errorf("Invalid request field. %v = `%v`", "partition", req.Partition) } diff --git a/agent/consul/auto_config_endpoint_test.go b/agent/consul/auto_config_endpoint_test.go index 39c4f3a7a5ef..461a80331736 100644 --- a/agent/consul/auto_config_endpoint_test.go +++ b/agent/consul/auto_config_endpoint_test.go @@ -34,7 +34,7 @@ import ( "github.com/hashicorp/consul/tlsutil" "github.com/hashicorp/consul/types" - "gopkg.in/square/go-jose.v2/jwt" + "github.com/go-jose/go-jose/v3/jwt" ) type mockAutoConfigBackend struct { diff --git a/agent/consul/catalog_endpoint_test.go b/agent/consul/catalog_endpoint_test.go index 628ad83ae4db..18827dc9811c 100644 --- a/agent/consul/catalog_endpoint_test.go +++ b/agent/consul/catalog_endpoint_test.go @@ -10,19 +10,18 @@ import ( "testing" "time" - "github.com/hashicorp/go-uuid" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc" "github.com/hashicorp/consul-net-rpc/net/rpc" + "github.com/hashicorp/go-uuid" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/lib/stringslice" "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" @@ -1234,9 +1233,9 @@ func TestCatalog_ListNodes_DistanceSort(t *testing.T) { // Set all but one of the nodes to known coordinates. updates := structs.Coordinates{ - {Node: "foo", Coord: lib.GenerateCoordinate(2 * time.Millisecond)}, - {Node: "bar", Coord: lib.GenerateCoordinate(5 * time.Millisecond)}, - {Node: "baz", Coord: lib.GenerateCoordinate(1 * time.Millisecond)}, + {Node: "foo", Coord: librtt.GenerateCoordinate(2 * time.Millisecond)}, + {Node: "bar", Coord: librtt.GenerateCoordinate(5 * time.Millisecond)}, + {Node: "baz", Coord: librtt.GenerateCoordinate(1 * time.Millisecond)}, } if err := s1.fsm.State().CoordinateBatchUpdate(5, updates); err != nil { t.Fatalf("err: %v", err) @@ -2138,9 +2137,9 @@ func TestCatalog_ListServiceNodes_DistanceSort(t *testing.T) { // Set all but one of the nodes to known coordinates. updates := structs.Coordinates{ - {Node: "foo", Coord: lib.GenerateCoordinate(2 * time.Millisecond)}, - {Node: "bar", Coord: lib.GenerateCoordinate(5 * time.Millisecond)}, - {Node: "baz", Coord: lib.GenerateCoordinate(1 * time.Millisecond)}, + {Node: "foo", Coord: librtt.GenerateCoordinate(2 * time.Millisecond)}, + {Node: "bar", Coord: librtt.GenerateCoordinate(5 * time.Millisecond)}, + {Node: "baz", Coord: librtt.GenerateCoordinate(1 * time.Millisecond)}, } if err := s1.fsm.State().CoordinateBatchUpdate(9, updates); err != nil { t.Fatalf("err: %v", err) @@ -3187,33 +3186,36 @@ func TestCatalog_GatewayServices_TerminatingGateway(t *testing.T) { expect := structs.GatewayServices{ { - Service: structs.NewServiceName("api", nil), - Gateway: structs.NewServiceName("gateway", nil), - GatewayKind: structs.ServiceKindTerminatingGateway, - CAFile: "api/ca.crt", - CertFile: "api/client.crt", - KeyFile: "api/client.key", - SNI: "my-domain", - ServiceKind: structs.GatewayServiceKindService, + Service: structs.NewServiceName("api", nil), + Gateway: structs.NewServiceName("gateway", nil), + GatewayKind: structs.ServiceKindTerminatingGateway, + CAFile: "api/ca.crt", + CertFile: "api/client.crt", + KeyFile: "api/client.key", + SNI: "my-domain", + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { - Service: structs.NewServiceName("db", nil), - Gateway: structs.NewServiceName("gateway", nil), - GatewayKind: structs.ServiceKindTerminatingGateway, - CAFile: "", - CertFile: "", - KeyFile: "", - ServiceKind: structs.GatewayServiceKindService, + Service: structs.NewServiceName("db", nil), + Gateway: structs.NewServiceName("gateway", nil), + GatewayKind: structs.ServiceKindTerminatingGateway, + CAFile: "", + CertFile: "", + KeyFile: "", + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { - Service: structs.NewServiceName("redis", nil), - Gateway: structs.NewServiceName("gateway", nil), - GatewayKind: structs.ServiceKindTerminatingGateway, - CAFile: "ca.crt", - CertFile: "client.crt", - KeyFile: "client.key", - SNI: "my-alt-domain", - FromWildcard: true, + Service: structs.NewServiceName("redis", nil), + Gateway: structs.NewServiceName("gateway", nil), + GatewayKind: structs.ServiceKindTerminatingGateway, + CAFile: "ca.crt", + CertFile: "client.crt", + KeyFile: "client.key", + SNI: "my-alt-domain", + FromWildcard: true, + AutoHostRewrite: true, }, } @@ -3345,10 +3347,11 @@ func TestCatalog_GatewayServices_BothGateways(t *testing.T) { expect := structs.GatewayServices{ { - Service: structs.NewServiceName("api", nil), - Gateway: structs.NewServiceName("gateway", nil), - GatewayKind: structs.ServiceKindTerminatingGateway, - ServiceKind: structs.GatewayServiceKindService, + Service: structs.NewServiceName("api", nil), + Gateway: structs.NewServiceName("gateway", nil), + GatewayKind: structs.ServiceKindTerminatingGateway, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } @@ -3568,16 +3571,18 @@ service "gateway" { expect := structs.GatewayServices{ { - Service: structs.NewServiceName("db", nil), - Gateway: structs.NewServiceName("gateway", nil), - GatewayKind: structs.ServiceKindTerminatingGateway, - ServiceKind: structs.GatewayServiceKindService, + Service: structs.NewServiceName("db", nil), + Gateway: structs.NewServiceName("gateway", nil), + GatewayKind: structs.ServiceKindTerminatingGateway, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { - Service: structs.NewServiceName("db_replica", nil), - Gateway: structs.NewServiceName("gateway", nil), - GatewayKind: structs.ServiceKindTerminatingGateway, - ServiceKind: structs.GatewayServiceKindUnknown, + Service: structs.NewServiceName("db_replica", nil), + Gateway: structs.NewServiceName("gateway", nil), + GatewayKind: structs.ServiceKindTerminatingGateway, + ServiceKind: structs.GatewayServiceKindUnknown, + AutoHostRewrite: true, }, } diff --git a/agent/consul/client.go b/agent/consul/client.go index fa5f1239e134..3632828794b1 100644 --- a/agent/consul/client.go +++ b/agent/consul/client.go @@ -14,15 +14,17 @@ import ( "github.com/armon/go-metrics" "github.com/armon/go-metrics/prometheus" + "golang.org/x/time/rate" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/serf/serf" - "golang.org/x/time/rate" "github.com/hashicorp/consul/acl" rpcRate "github.com/hashicorp/consul/agent/consul/rate" "github.com/hashicorp/consul/agent/pool" "github.com/hashicorp/consul/agent/router" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/proto-public/pbresource" @@ -107,7 +109,7 @@ func NewClient(config *Config, deps Deps) (*Client, error) { if config.DataDir == "" { return nil, fmt.Errorf("Config must provide a DataDir") } - if err := config.CheckACL(); err != nil { + if err := config.CheckEnumStrings(); err != nil { return nil, err } @@ -288,15 +290,17 @@ func (c *Client) RPC(ctx context.Context, method string, args interface{}, reply firstCheck := time.Now() retryCount := 0 previousJitter := time.Duration(0) + + metrics.IncrCounter([]string{"client", "rpc"}, 1) TRY: retryCount++ manager, server := c.router.FindLANRoute() if server == nil { + metrics.IncrCounter([]string{"client", "rpc", "failed"}, 1) return structs.ErrNoServers } // Enforce the RPC limit. - metrics.IncrCounter([]string{"client", "rpc"}, 1) if !c.rpcLimiter.Load().(*rate.Limiter).Allow() { metrics.IncrCounter([]string{"client", "rpc", "exceeded"}, 1) return structs.ErrRPCRateExceeded @@ -437,13 +441,13 @@ func (c *Client) Stats() map[string]map[string]string { // are ancillary members of. // // NOTE: This assumes coordinates are enabled, so check that before calling. -func (c *Client) GetLANCoordinate() (lib.CoordinateSet, error) { +func (c *Client) GetLANCoordinate() (librtt.CoordinateSet, error) { lan, err := c.serf.GetCoordinate() if err != nil { return nil, err } - cs := lib.CoordinateSet{c.config.Segment: lan} + cs := librtt.CoordinateSet{c.config.Segment: lan} return cs, nil } diff --git a/agent/consul/client_serf.go b/agent/consul/client_serf.go index c92fdd1726c3..a6f479c04ebe 100644 --- a/agent/consul/client_serf.go +++ b/agent/consul/client_serf.go @@ -12,8 +12,8 @@ import ( "github.com/hashicorp/serf/serf" "github.com/hashicorp/consul/agent/metadata" + "github.com/hashicorp/consul/internal/gossip/libserf" "github.com/hashicorp/consul/lib" - libserf "github.com/hashicorp/consul/lib/serf" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/types" ) diff --git a/agent/consul/client_test.go b/agent/consul/client_test.go index 1d6fa28b526c..b308450800b8 100644 --- a/agent/consul/client_test.go +++ b/agent/consul/client_test.go @@ -7,9 +7,6 @@ import ( "bytes" "context" "fmt" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/mesh" - "github.com/hashicorp/consul/internal/resource/demo" "net" "os" "strings" @@ -17,8 +14,6 @@ import ( "testing" "time" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/go-hclog" "github.com/hashicorp/serf/serf" "github.com/stretchr/testify/require" @@ -509,7 +504,7 @@ func newClient(t *testing.T, config *Config) *Client { return client } -func newTestResolverConfig(t *testing.T, suffix string, dc, agentType string) resolver.Config { +func newTestResolverConfig(t testutil.TestingTB, suffix string, dc, agentType string) resolver.Config { n := t.Name() s := strings.Replace(n, "/", "", -1) s = strings.Replace(s, "_", "", -1) @@ -520,7 +515,7 @@ func newTestResolverConfig(t *testing.T, suffix string, dc, agentType string) re } } -func newDefaultDeps(t *testing.T, c *Config) Deps { +func newDefaultDeps(t testutil.TestingTB, c *Config) Deps { t.Helper() logger := hclog.NewInterceptLogger(&hclog.LoggerOptions{ @@ -562,10 +557,6 @@ func newDefaultDeps(t *testing.T, c *Config) Deps { RPCHoldTimeout: c.RPCHoldTimeout, } connPool.SetRPCClientTimeout(c.RPCClientTimeout) - registry := resource.NewRegistry() - demo.RegisterTypes(registry) - mesh.RegisterTypes(registry) - catalog.RegisterTypes(registry) return Deps{ EventPublisher: stream.NewEventPublisher(10 * time.Second), Logger: logger, @@ -585,7 +576,7 @@ func newDefaultDeps(t *testing.T, c *Config) Deps { GetNetRPCInterceptorFunc: middleware.GetNetRPCInterceptor, EnterpriseDeps: newDefaultDepsEnterprise(t, logger, c), XDSStreamLimiter: limiter.NewSessionLimiter(), - Registry: registry, + Registry: NewTypeRegistry(), } } diff --git a/agent/consul/config.go b/agent/consul/config.go index 8e3bb92e4eb1..1cba0f4ef169 100644 --- a/agent/consul/config.go +++ b/agent/consul/config.go @@ -9,15 +9,17 @@ import ( "os" "time" + "golang.org/x/time/rate" + "github.com/hashicorp/memberlist" "github.com/hashicorp/raft" "github.com/hashicorp/serf/serf" - "golang.org/x/time/rate" "github.com/hashicorp/consul/agent/checks" consulrate "github.com/hashicorp/consul/agent/consul/rate" + hcpconfig "github.com/hashicorp/consul/agent/hcp/config" "github.com/hashicorp/consul/agent/structs" - libserf "github.com/hashicorp/consul/lib/serf" + "github.com/hashicorp/consul/internal/gossip/libserf" "github.com/hashicorp/consul/tlsutil" "github.com/hashicorp/consul/types" "github.com/hashicorp/consul/version" @@ -403,6 +405,8 @@ type Config struct { // report usage metrics to the configured go-metrics Sinks. MetricsReportingInterval time.Duration + DisablePerTenancyUsageMetrics bool + // ConnectEnabled is whether to enable Connect features such as the CA. ConnectEnabled bool @@ -410,6 +414,13 @@ type Config struct { // datacenters should exclusively traverse mesh gateways. ConnectMeshGatewayWANFederationEnabled bool + // DefaultIntentionPolicy is used to define a default intention action for all + // sources and destinations. Possible values are "allow", "deny", or "" (blank). + // For compatibility, falls back to ACLResolverSettings.ACLDefaultPolicy (which + // itself has a default of "allow") if left blank. Future versions of Consul + // will default this field to "deny" to be secure by default. + DefaultIntentionPolicy string + // DisableFederationStateAntiEntropy solely exists for use in unit tests to // disable a background routine. DisableFederationStateAntiEntropy bool @@ -442,7 +453,7 @@ type Config struct { Locality *structs.Locality - Cloud CloudConfig + Cloud hcpconfig.CloudConfig Reporting Reporting @@ -469,21 +480,17 @@ func (c *Config) CheckProtocolVersion() error { return nil } -// CheckACL validates the ACL configuration. -// TODO: move this to ACLResolverSettings -func (c *Config) CheckACL() error { - switch c.ACLResolverSettings.ACLDefaultPolicy { - case "allow": - case "deny": - default: - return fmt.Errorf("Unsupported default ACL policy: %s", c.ACLResolverSettings.ACLDefaultPolicy) +// CheckEnumStrings validates string configuration which must be specific values. +func (c *Config) CheckEnumStrings() error { + if err := c.ACLResolverSettings.CheckACLs(); err != nil { + return err } - switch c.ACLResolverSettings.ACLDownPolicy { - case "allow": - case "deny": - case "async-cache", "extend-cache": + switch c.DefaultIntentionPolicy { + case structs.IntentionDefaultPolicyAllow: + case structs.IntentionDefaultPolicyDeny: + case "": default: - return fmt.Errorf("Unsupported down ACL policy: %s", c.ACLResolverSettings.ACLDownPolicy) + return fmt.Errorf("Unsupported default intention policy: %s", c.DefaultIntentionPolicy) } return nil } diff --git a/agent/consul/config_cloud.go b/agent/consul/config_cloud.go deleted file mode 100644 index 5b62574c811b..000000000000 --- a/agent/consul/config_cloud.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package consul - -type CloudConfig struct { - ManagementToken string -} diff --git a/agent/consul/config_endpoint.go b/agent/consul/config_endpoint.go index a78859c35058..96906dac6824 100644 --- a/agent/consul/config_endpoint.go +++ b/agent/consul/config_endpoint.go @@ -10,10 +10,11 @@ import ( metrics "github.com/armon/go-metrics" "github.com/armon/go-metrics/prometheus" + hashstructure_v2 "github.com/mitchellh/hashstructure/v2" + "github.com/hashicorp/go-bexpr" "github.com/hashicorp/go-hclog" memdb "github.com/hashicorp/go-memdb" - hashstructure_v2 "github.com/mitchellh/hashstructure/v2" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/configentry" @@ -85,6 +86,7 @@ func (c *ConfigEntry) Apply(args *structs.ConfigEntryRequest, reply *bool) error } // Normalize and validate the incoming config entry as if it came from a user. + // Ensure Normalize is called before Validate for accurate validation if err := args.Entry.Normalize(); err != nil { return err } diff --git a/agent/consul/config_replication.go b/agent/consul/config_replication.go index d9573ad58bf9..f3e5635007aa 100644 --- a/agent/consul/config_replication.go +++ b/agent/consul/config_replication.go @@ -30,7 +30,9 @@ func diffConfigEntries(local []structs.ConfigEntry, remote []structs.ConfigEntry if configentry.EqualID(local[localIdx], remote[remoteIdx]) { // config is in both the local and remote state - need to check raft indices if remote[remoteIdx].GetRaftIndex().ModifyIndex > lastRemoteIndex { - updates = append(updates, remote[remoteIdx]) + if !configentry.SameHash(local[localIdx], remote[remoteIdx]) { + updates = append(updates, remote[remoteIdx]) + } } // increment both indices when equal localIdx += 1 diff --git a/agent/consul/config_replication_test.go b/agent/consul/config_replication_test.go index 41ccf53362d5..3117e046a463 100644 --- a/agent/consul/config_replication_test.go +++ b/agent/consul/config_replication_test.go @@ -9,6 +9,8 @@ import ( "os" "testing" + "github.com/oklog/ulid/v2" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/hashicorp/consul/agent/structs" @@ -127,7 +129,7 @@ func TestReplication_ConfigEntries(t *testing.T) { Entry: &structs.ServiceConfigEntry{ Kind: structs.ServiceDefaults, Name: fmt.Sprintf("svc-%d", i), - Protocol: "udp", + Protocol: "tcp", }, } @@ -268,3 +270,63 @@ func TestReplication_ConfigEntries_GraphValidationErrorDuringReplication(t *test checkSame(r) }) } + +func createConfigEntries(num int, indexStart int) []structs.ConfigEntry { + entries := make([]structs.ConfigEntry, num) + for i := range entries { + entries[i] = &structs.ServiceConfigEntry{Name: ulid.Make().String(), RaftIndex: structs.RaftIndex{ModifyIndex: uint64(i + indexStart)}} + } + return entries +} + +func mutateIDs(e []structs.ConfigEntry, indexStart int) []structs.ConfigEntry { + entries := make([]structs.ConfigEntry, len(e)) + for i := range entries { + entries[i] = &structs.ServiceConfigEntry{Name: e[i].GetName(), RaftIndex: structs.RaftIndex{ModifyIndex: uint64(i + indexStart)}} + } + return entries +} + +func Test_diffConfigEntries(t *testing.T) { + type args struct { + local []structs.ConfigEntry + remote []structs.ConfigEntry + lastRemoteIndex uint64 + normalize bool + } + + entries1 := createConfigEntries(10, 10) + entries2 := createConfigEntries(10, 20) + entries3 := append(entries1, entries2...) + entries4 := mutateIDs(entries1, 20) + entries5 := mutateIDs(entries1, 0) + tests := []struct { + name string + args args + updated []structs.ConfigEntry + deleted []structs.ConfigEntry + }{ + {"empty", args{local: make([]structs.ConfigEntry, 0), remote: make([]structs.ConfigEntry, 0), lastRemoteIndex: 0, normalize: true}, nil, nil}, + {"same", args{local: entries1, remote: entries1, lastRemoteIndex: 0, normalize: true}, nil, nil}, + {"new remote", args{local: nil, remote: entries1, lastRemoteIndex: 0, normalize: true}, entries1, nil}, + {"extra remote", args{local: entries1, remote: entries3, lastRemoteIndex: 0, normalize: true}, entries2, nil}, + {"extra local", args{local: entries3, remote: entries1, lastRemoteIndex: 0, normalize: true}, nil, entries2}, + {"same, same size, different raft ID", args{local: entries1, remote: entries4, lastRemoteIndex: 0, normalize: true}, nil, nil}, + {"when hash is empty, avoid hash compare", args{local: entries5, remote: entries4, lastRemoteIndex: 0, normalize: false}, entries4, nil}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.args.normalize { + for _, l := range tt.args.local { + require.NoError(t, l.Normalize()) + } + for _, r := range tt.args.remote { + require.NoError(t, r.Normalize()) + } + } + deletions, updates := diffConfigEntries(tt.args.local, tt.args.remote, tt.args.lastRemoteIndex) + assert.Equalf(t, tt.updated, updates, "updated diffConfigEntries(%v, %v, %v)", tt.args.local, tt.args.remote, tt.args.lastRemoteIndex) + assert.Equalf(t, tt.deleted, deletions, "deleted diffConfigEntries(%v, %v, %v)", tt.args.local, tt.args.remote, tt.args.lastRemoteIndex) + }) + } +} diff --git a/agent/consul/configentry_backend.go b/agent/consul/configentry_backend.go new file mode 100644 index 000000000000..2a572fcb68d8 --- /dev/null +++ b/agent/consul/configentry_backend.go @@ -0,0 +1,31 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package consul + +import ( + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/acl/resolver" + "github.com/hashicorp/consul/agent/grpc-external/services/configentry" +) + +type ConfigEntryBackend struct { + srv *Server +} + +var _ configentry.Backend = (*ConfigEntryBackend)(nil) + +// NewConfigEntryBackend returns a configentry.Backend implementation that is bound to the given server. +func NewConfigEntryBackend(srv *Server) *ConfigEntryBackend { + return &ConfigEntryBackend{ + srv: srv, + } +} + +func (b *ConfigEntryBackend) EnterpriseCheckPartitions(partition string) error { + return b.enterpriseCheckPartitions(partition) +} + +func (b *ConfigEntryBackend) ResolveTokenAndDefaultMeta(token string, entMeta *acl.EnterpriseMeta, authzCtx *acl.AuthorizerContext) (resolver.Result, error) { + return b.srv.ResolveTokenAndDefaultMeta(token, entMeta, authzCtx) +} diff --git a/agent/consul/configentry_backend_ce.go b/agent/consul/configentry_backend_ce.go new file mode 100644 index 000000000000..082f64532d42 --- /dev/null +++ b/agent/consul/configentry_backend_ce.go @@ -0,0 +1,18 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +//go:build !consulent + +package consul + +import ( + "fmt" + "strings" +) + +func (b *ConfigEntryBackend) enterpriseCheckPartitions(partition string) error { + if partition == "" || strings.EqualFold(partition, "default") { + return nil + } + return fmt.Errorf("Partitions are a Consul Enterprise feature") +} diff --git a/agent/consul/configentry_backend_ce_test.go b/agent/consul/configentry_backend_ce_test.go new file mode 100644 index 000000000000..f8a945cbfdf4 --- /dev/null +++ b/agent/consul/configentry_backend_ce_test.go @@ -0,0 +1,87 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +//go:build !consulent + +package consul + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + gogrpc "google.golang.org/grpc" + + "github.com/hashicorp/consul/proto/private/pbconfigentry" + "github.com/hashicorp/consul/sdk/freeport" + "github.com/hashicorp/consul/testrpc" +) + +func TestConfigEntryBackend_RejectsPartition(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + _, s1 := testServerWithConfig(t, func(c *Config) { + c.GRPCTLSPort = freeport.GetOne(t) + }) + testrpc.WaitForLeader(t, s1.RPC, "dc1") + + // make a grpc client to dial s1 directly + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + t.Cleanup(cancel) + + conn, err := gogrpc.DialContext(ctx, s1.config.RPCAddr.String(), + gogrpc.WithContextDialer(newServerDialer(s1.config.RPCAddr.String())), + //nolint:staticcheck + gogrpc.WithInsecure(), + gogrpc.WithBlock()) + require.NoError(t, err) + t.Cleanup(func() { conn.Close() }) + + configEntryClient := pbconfigentry.NewConfigEntryServiceClient(conn) + + req := pbconfigentry.GetResolvedExportedServicesRequest{ + Partition: "test", + } + _, err = configEntryClient.GetResolvedExportedServices(ctx, &req) + require.Error(t, err) + require.Contains(t, err.Error(), "Partitions are a Consul Enterprise feature") +} + +func TestConfigEntryBackend_IgnoresDefaultPartition(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + _, s1 := testServerWithConfig(t, func(c *Config) { + c.GRPCTLSPort = freeport.GetOne(t) + }) + + testrpc.WaitForLeader(t, s1.RPC, "dc1") + + // make a grpc client to dial s1 directly + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + t.Cleanup(cancel) + + conn, err := gogrpc.DialContext(ctx, s1.config.RPCAddr.String(), + gogrpc.WithContextDialer(newServerDialer(s1.config.RPCAddr.String())), + //nolint:staticcheck + gogrpc.WithInsecure(), + gogrpc.WithBlock()) + require.NoError(t, err) + t.Cleanup(func() { conn.Close() }) + + configEntryClient := pbconfigentry.NewConfigEntryServiceClient(conn) + + req := pbconfigentry.GetResolvedExportedServicesRequest{ + Partition: "DeFaUlT", + } + _, err = configEntryClient.GetResolvedExportedServices(ctx, &req) + require.NoError(t, err) +} diff --git a/agent/consul/configentry_backend_test.go b/agent/consul/configentry_backend_test.go new file mode 100644 index 000000000000..30c8346e27c0 --- /dev/null +++ b/agent/consul/configentry_backend_test.go @@ -0,0 +1,49 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package consul + +import ( + "context" + "testing" + "time" + + "github.com/hashicorp/consul/proto/private/pbconfigentry" + "github.com/hashicorp/consul/sdk/freeport" + "github.com/hashicorp/consul/testrpc" + "github.com/stretchr/testify/require" + gogrpc "google.golang.org/grpc" +) + +func TestConfigEntryBackend_EmptyPartition(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + _, s1 := testServerWithConfig(t, func(c *Config) { + c.GRPCTLSPort = freeport.GetOne(t) + }) + testrpc.WaitForLeader(t, s1.RPC, "dc1") + + // make a grpc client to dial s1 directly + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + t.Cleanup(cancel) + + conn, err := gogrpc.DialContext(ctx, s1.config.RPCAddr.String(), + gogrpc.WithContextDialer(newServerDialer(s1.config.RPCAddr.String())), + //nolint:staticcheck + gogrpc.WithInsecure(), + gogrpc.WithBlock()) + require.NoError(t, err) + t.Cleanup(func() { conn.Close() }) + + configEntryClient := pbconfigentry.NewConfigEntryServiceClient(conn) + + req := pbconfigentry.GetResolvedExportedServicesRequest{ + Partition: "", + } + _, err = configEntryClient.GetResolvedExportedServices(ctx, &req) + require.NoError(t, err) +} diff --git a/agent/consul/controller/controller.go b/agent/consul/controller/controller.go index 1eccb7e7aba0..9f49b9cb91bb 100644 --- a/agent/consul/controller/controller.go +++ b/agent/consul/controller/controller.go @@ -11,13 +11,15 @@ import ( "sync/atomic" "time" - "github.com/hashicorp/go-hclog" "golang.org/x/sync/errgroup" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/consul/agent/consul/controller/queue" "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/stream" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/lib/retry" ) // much of this is a re-implementation of @@ -216,38 +218,41 @@ func (c *controller) Run(ctx context.Context) error { for _, sub := range c.subscriptions { // store a reference for the closure sub := sub + // Fetch data from subscriptions repeatedly until the context is cancelled. c.group.Go(func() error { - var index uint64 - - subscription, err := c.publisher.Subscribe(sub.request) - if err != nil { - return err + defer c.logger.Debug("stopping controller subscription", "topic", sub.request.Topic) + lastFailTime := time.Now() + retryWaiter := &retry.Waiter{ + MinFailures: 1, + MinWait: 1 * time.Second, + MaxWait: 20 * time.Second, } - defer subscription.Unsubscribe() - - for { - event, err := subscription.Next(ctx) + // Ensure the subscription is restarted when non-context errors happen. + // Stop if either the parent context or the group ctx is cancelled. + for c.groupCtx.Err() == nil { + c.logger.Debug("rewatching controller subscription", "topic", sub.request.Topic) + err := c.watchSubscription(ctx, sub) switch { case errors.Is(err, context.Canceled): return nil + case errors.Is(err, stream.ErrSubForceClosed): + c.logger.Debug("controller subscription force closed", "topic", sub.request.Topic) case err != nil: - return err - } - - if event.IsFramingEvent() { - continue - } - - if event.Index <= index { - continue - } - - index = event.Index - - if err := c.processEvent(sub, event); err != nil { - return err + // Log the error and backoff wait. Do not return the error + // or else the subscriptions will stop being watched. + c.logger.Warn("error watching controller subscription", + "topic", sub.request.Topic, + "err", err) + // Reset the waiter if the last failure was more than 10 minutes ago. + // This simply prevents the backoff from being too aggressive. + if time.Now().After(lastFailTime.Add(10 * time.Minute)) { + retryWaiter.Reset() + } + lastFailTime = time.Now() + retryWaiter.Wait(c.groupCtx) } } + return nil }) } @@ -271,6 +276,38 @@ func (c *controller) Run(ctx context.Context) error { return nil } +// watchSubscription fetches events in a loop that stops on the first error. +func (c *controller) watchSubscription(ctx context.Context, sub subscription) error { + var index uint64 + subscription, err := c.publisher.Subscribe(sub.request) + if err != nil { + return err + } + defer subscription.Unsubscribe() + + for ctx.Err() == nil { + event, err := subscription.Next(ctx) + if err != nil { + return err + } + + if event.IsFramingEvent() { + continue + } + + if event.Index <= index { + continue + } + + index = event.Index + + if err := c.processEvent(sub, event); err != nil { + return err + } + } + return ctx.Err() +} + // AddTrigger allows for triggering a reconciliation request every time that the // triggering function returns, when the passed in context is canceled // the trigger must return @@ -380,7 +417,7 @@ func (c *controller) reconcileHandler(ctx context.Context, req Request) { var requeueAfter RequeueAfterError if errors.As(err, &requeueAfter) { c.work.Forget(req) - c.work.AddAfter(req, time.Duration(requeueAfter)) + c.work.AddAfter(req, time.Duration(requeueAfter), false) return } diff --git a/agent/consul/controller/queue/defer.go b/agent/consul/controller/queue/defer.go index e9b8a9c3ad75..6ba5d09aa97d 100644 --- a/agent/consul/controller/queue/defer.go +++ b/agent/consul/controller/queue/defer.go @@ -18,8 +18,10 @@ type DeferQueue[T ItemType] interface { // Defer defers processing a Request until a given time. When // the timeout is hit, the request will be processed by the // callback given in the Process loop. If the given context - // is canceled, the item is not deferred. - Defer(ctx context.Context, item T, until time.Time) + // is canceled, the item is not deferred. Override replaces + // any existing item regardless of the enqueue time when true. + Defer(ctx context.Context, item T, until time.Time, override bool) + // Process processes all items in the defer queue with the // given callback, blocking until the given context is canceled. // Callers should only ever call Process once, likely in a @@ -32,6 +34,9 @@ type DeferQueue[T ItemType] interface { type deferredRequest[T ItemType] struct { enqueueAt time.Time item T + // override replaces any existing item when true regardless + // of the enqueue time + override bool // index holds the index for the given heap entry so that if // the entry is updated the heap can be re-sorted index int @@ -64,10 +69,11 @@ func NewDeferQueue[T ItemType](tick time.Duration) DeferQueue[T] { // Defer defers the given Request until the given time in the future. If the // passed in context is canceled before the Request is deferred, then this // immediately returns. -func (q *deferQueue[T]) Defer(ctx context.Context, item T, until time.Time) { +func (q *deferQueue[T]) Defer(ctx context.Context, item T, until time.Time, override bool) { entry := &deferredRequest[T]{ enqueueAt: until, item: item, + override: override, } select { @@ -79,9 +85,9 @@ func (q *deferQueue[T]) Defer(ctx context.Context, item T, until time.Time) { // deferEntry adds a deferred request to the priority queue func (q *deferQueue[T]) deferEntry(entry *deferredRequest[T]) { existing, exists := q.entries[entry.item.Key()] + // insert or update the item deferral time if exists { - // insert or update the item deferral time - if existing.enqueueAt.After(entry.enqueueAt) { + if entry.override || entry.enqueueAt.Before(existing.enqueueAt) { existing.enqueueAt = entry.enqueueAt heap.Fix(q.heap, existing.index) } diff --git a/agent/consul/controller/queue/queue.go b/agent/consul/controller/queue/queue.go index 92c624cc2a73..ed26ca6ff50f 100644 --- a/agent/consul/controller/queue/queue.go +++ b/agent/consul/controller/queue/queue.go @@ -27,8 +27,9 @@ type WorkQueue[T ItemType] interface { Get() (item T, shutdown bool) // Add immediately adds a Request to the work queue. Add(item T) - // AddAfter adds a Request to the work queue after a given amount of time. - AddAfter(item T, duration time.Duration) + // AddAfter adds a Request to the work queue after a given amount of time + // with the option to override any existing Request that may be scheduled. + AddAfter(item T, duration time.Duration, override bool) // AddRateLimited adds a Request to the work queue after the amount of time // specified by applying the queue's rate limiter. AddRateLimited(item T) @@ -41,10 +42,10 @@ type WorkQueue[T ItemType] interface { // queue implements a rate-limited work queue type queue[T ItemType] struct { - // queue holds an ordered list of Requests needing to be processed + // queue holds an ordered list of non-deferred Requests needing to be processed queue []T - // dirty holds the working set of all Requests, whether they are being + // dirty holds the working set of all non-deferred Requests, whether they are being // processed or not dirty map[string]struct{} // processing holds the set of current requests being processed @@ -145,8 +146,9 @@ func (q *queue[T]) Add(item T) { q.cond.Signal() } -// AddAfter adds a Request to the work queue after a given amount of time. -func (q *queue[T]) AddAfter(item T, duration time.Duration) { +// AddAfter adds a Request to the work queue after a given amount of time with +// the option to override any existing Request that may be scheduled. +func (q *queue[T]) AddAfter(item T, duration time.Duration, override bool) { // don't add if we're already shutting down if q.shuttingDown() { return @@ -158,13 +160,13 @@ func (q *queue[T]) AddAfter(item T, duration time.Duration) { return } - q.deferred.Defer(q.ctx, item, time.Now().Add(duration)) + q.deferred.Defer(q.ctx, item, time.Now().Add(duration), override) } // AddRateLimited adds the given Request to the queue after applying the // rate limiter to determine when the Request should next be processed. func (q *queue[T]) AddRateLimited(item T) { - q.AddAfter(item, q.ratelimiter.NextRetry(item)) + q.AddAfter(item, q.ratelimiter.NextRetry(item), false) } // Forget signals the queue to reset the rate-limiting for the given Request. diff --git a/agent/consul/controller/queue_test.go b/agent/consul/controller/queue_test.go index cb6f60982910..b7aa08af650c 100644 --- a/agent/consul/controller/queue_test.go +++ b/agent/consul/controller/queue_test.go @@ -59,8 +59,8 @@ func (c *countingWorkQueue[T]) adds() uint64 { return atomic.LoadUint64(&c.addCounter) } -func (c *countingWorkQueue[T]) AddAfter(item T, duration time.Duration) { - c.inner.AddAfter(item, duration) +func (c *countingWorkQueue[T]) AddAfter(item T, duration time.Duration, override bool) { + c.inner.AddAfter(item, duration, override) atomic.AddUint64(&c.addAfterCounter, 1) } diff --git a/agent/consul/controller/reconciler_test.go b/agent/consul/controller/reconciler_test.go index c3b8a450b18b..5229e7d1d474 100644 --- a/agent/consul/controller/reconciler_test.go +++ b/agent/consul/controller/reconciler_test.go @@ -47,6 +47,7 @@ func (r *testReconciler) setResponse(err error) { func (r *testReconciler) step() { r.stepChan <- struct{}{} } + func (r *testReconciler) stepFor(duration time.Duration) { select { case r.stepChan <- struct{}{}: diff --git a/agent/consul/coordinate_endpoint_test.go b/agent/consul/coordinate_endpoint_test.go index 1c693ba83bbf..6ca7a32595d9 100644 --- a/agent/consul/coordinate_endpoint_test.go +++ b/agent/consul/coordinate_endpoint_test.go @@ -12,15 +12,15 @@ import ( "testing" "time" - "github.com/hashicorp/serf/coordinate" "github.com/stretchr/testify/require" msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc" "github.com/hashicorp/consul-net-rpc/net/rpc" + "github.com/hashicorp/serf/coordinate" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/testrpc" ) @@ -92,13 +92,13 @@ func TestCoordinate_Update(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } - require.Equal(t, lib.CoordinateSet{}, c) + require.Equal(t, librtt.CoordinateSet{}, c) _, c, err = state.Coordinate(nil, "node2", nil) if err != nil { t.Fatalf("err: %v", err) } - require.Equal(t, lib.CoordinateSet{}, c) + require.Equal(t, librtt.CoordinateSet{}, c) // Send another update for the second node. It should take precedence // since there will be two updates in the same batch. @@ -113,7 +113,7 @@ func TestCoordinate_Update(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } - expected := lib.CoordinateSet{ + expected := librtt.CoordinateSet{ "": arg1.Coord, } require.Equal(t, expected, c) @@ -122,7 +122,7 @@ func TestCoordinate_Update(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } - expected = lib.CoordinateSet{ + expected = librtt.CoordinateSet{ "": arg2.Coord, } require.Equal(t, expected, c) diff --git a/agent/consul/discoverychain/compile.go b/agent/consul/discoverychain/compile.go index 32a6408be544..c1cb3157a242 100644 --- a/agent/consul/discoverychain/compile.go +++ b/agent/consul/discoverychain/compile.go @@ -8,14 +8,12 @@ import ( "strings" "time" - "github.com/mitchellh/hashstructure" - "github.com/mitchellh/mapstructure" - "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/configentry" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto/private/pbpeering" + "github.com/mitchellh/hashstructure" ) type CompileRequest struct { @@ -244,21 +242,13 @@ func (c *compiler) recordServiceProtocol(sid structs.ServiceID) error { return c.recordProtocol(sid, serviceDefault.Protocol) } if proxyDefault := c.entries.GetProxyDefaults(sid.PartitionOrDefault()); proxyDefault != nil { - var cfg proxyConfig - // Ignore errors and fallback on defaults if it does happen. - _ = mapstructure.WeakDecode(proxyDefault.Config, &cfg) - if cfg.Protocol != "" { - return c.recordProtocol(sid, cfg.Protocol) + if proxyDefault.Protocol != "" { + return c.recordProtocol(sid, proxyDefault.Protocol) } } return c.recordProtocol(sid, "") } -// proxyConfig is a snippet from agent/xds/config.go:ProxyConfig -type proxyConfig struct { - Protocol string `mapstructure:"protocol"` -} - func (c *compiler) recordProtocol(fromService structs.ServiceID, protocol string) error { if protocol == "" { protocol = "tcp" diff --git a/agent/consul/discoverychain/compile_test.go b/agent/consul/discoverychain/compile_test.go index dda28780431d..8c9c9dfec7f8 100644 --- a/agent/consul/discoverychain/compile_test.go +++ b/agent/consul/discoverychain/compile_test.go @@ -1142,8 +1142,9 @@ func testcase_PeerRedirect() compileTestCase { func testcase_PeerRedirectProxyDefHTTP() compileTestCase { entries := newEntries() entries.AddProxyDefaults(&structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, + Kind: structs.ProxyDefaults, + Name: structs.ProxyConfigGlobal, + Protocol: "http", Config: map[string]interface{}{ "Protocol": "http", }, @@ -1768,11 +1769,9 @@ func testcase_DefaultResolver_WithProxyDefaults() compileTestCase { entries := newEntries() entries.AddProxyDefaults(&structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, - Config: map[string]interface{}{ - "protocol": "grpc", - }, + Kind: structs.ProxyDefaults, + Name: structs.ProxyConfigGlobal, + Protocol: "grpc", MeshGateway: structs.MeshGatewayConfig{ Mode: structs.MeshGatewayModeRemote, }, @@ -3263,8 +3262,9 @@ func newSimpleRoute(name string, muts ...func(*structs.ServiceRoute)) structs.Se func setGlobalProxyProtocol(entries *configentry.DiscoveryChainSet, protocol string) { entries.AddProxyDefaults(&structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, + Kind: structs.ProxyDefaults, + Name: structs.ProxyConfigGlobal, + Protocol: protocol, Config: map[string]interface{}{ "protocol": protocol, }, diff --git a/agent/consul/discoverychain/gateway.go b/agent/consul/discoverychain/gateway.go index c60c77b028fb..3435233aafed 100644 --- a/agent/consul/discoverychain/gateway.go +++ b/agent/consul/discoverychain/gateway.go @@ -257,7 +257,7 @@ func targetForResolverNode(nodeName string, chains []*structs.CompiledDiscoveryC splitterName := splitterPrefix + strings.TrimPrefix(nodeName, resolverPrefix) for _, c := range chains { - targetChainPrefix := resolverPrefix + c.ServiceName + "." + targetChainPrefix := resolverPrefix + c.ID() if strings.HasPrefix(nodeName, targetChainPrefix) && len(c.Nodes) == 1 { // we have a virtual resolver that just maps to another resolver, return // the given node name diff --git a/agent/consul/discoverychain/gateway_test.go b/agent/consul/discoverychain/gateway_test.go index 00c37e8aa407..91931337c42e 100644 --- a/agent/consul/discoverychain/gateway_test.go +++ b/agent/consul/discoverychain/gateway_test.go @@ -712,6 +712,7 @@ func TestGatewayChainSynthesizer_Synthesize(t *testing.T) { chain: &structs.CompiledDiscoveryChain{ ServiceName: "foo", Namespace: "default", + Partition: "default", Datacenter: "dc1", StartNode: "resolver:foo-2.default.default.dc2", Nodes: map[string]*structs.DiscoveryGraphNode{ @@ -879,8 +880,9 @@ func TestGatewayChainSynthesizer_ComplexChain(t *testing.T) { }}, }, &structs.ProxyConfigEntry{ - Kind: structs.ProxyConfigGlobal, - Name: "global", + Kind: structs.ProxyConfigGlobal, + Name: "global", + Protocol: "http", Config: map[string]interface{}{ "protocol": "http", }, diff --git a/agent/consul/enterprise_server_ce_test.go b/agent/consul/enterprise_server_ce_test.go index 1a3622d5d743..c039997a03f5 100644 --- a/agent/consul/enterprise_server_ce_test.go +++ b/agent/consul/enterprise_server_ce_test.go @@ -6,12 +6,11 @@ package consul import ( - "testing" - + "github.com/hashicorp/consul/sdk/testutil" hclog "github.com/hashicorp/go-hclog" ) -func newDefaultDepsEnterprise(t *testing.T, _ hclog.Logger, _ *Config) EnterpriseDeps { +func newDefaultDepsEnterprise(t testutil.TestingTB, _ hclog.Logger, _ *Config) EnterpriseDeps { t.Helper() return EnterpriseDeps{} } diff --git a/agent/consul/federation_state_endpoint.go b/agent/consul/federation_state_endpoint.go index 4afa481a397b..a27958ae871a 100644 --- a/agent/consul/federation_state_endpoint.go +++ b/agent/consul/federation_state_endpoint.go @@ -84,7 +84,7 @@ func (c *FederationState) Apply(args *structs.FederationStateRequest, reply *boo return fmt.Errorf("Invalid federation state operation: %v", args.Op) } - resp, err := c.srv.raftApply(structs.FederationStateRequestType, args) + resp, err := c.srv.raftApply(structs.FederationStateRequestType | structs.IgnoreUnknownTypeFlag, args) if err != nil { return err } diff --git a/agent/consul/federation_state_replication.go b/agent/consul/federation_state_replication.go index 2f5a6dd150f3..4cc12bf534d8 100644 --- a/agent/consul/federation_state_replication.go +++ b/agent/consul/federation_state_replication.go @@ -157,7 +157,7 @@ func (r *FederationStateReplicator) PerformDeletions(ctx context.Context, deleti State: state, } - _, err := r.srv.leaderRaftApply("FederationState.Delete", structs.FederationStateRequestType, &req) + _, err := r.srv.leaderRaftApply("FederationState.Delete", structs.FederationStateRequestType | structs.IgnoreUnknownTypeFlag, &req) if err != nil { return false, err } @@ -198,7 +198,7 @@ func (r *FederationStateReplicator) PerformUpdates(ctx context.Context, updatesR State: state2, } - _, err := r.srv.leaderRaftApply("FederationState.Apply", structs.FederationStateRequestType, &req) + _, err := r.srv.leaderRaftApply("FederationState.Apply", structs.FederationStateRequestType | structs.IgnoreUnknownTypeFlag, &req) if err != nil { return false, err } diff --git a/agent/consul/fsm/commands_ce_test.go b/agent/consul/fsm/commands_ce_test.go index 445f4c019076..c24dd2ea8f40 100644 --- a/agent/consul/fsm/commands_ce_test.go +++ b/agent/consul/fsm/commands_ce_test.go @@ -1539,7 +1539,6 @@ func TestFSM_Resources(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "default", - PeerName: "local", Namespace: "default", }, Name: "bar", diff --git a/agent/consul/fsm/decode_downgrade.go b/agent/consul/fsm/decode_downgrade.go index 7b8e2fce719f..bdf922f3c84c 100644 --- a/agent/consul/fsm/decode_downgrade.go +++ b/agent/consul/fsm/decode_downgrade.go @@ -619,6 +619,8 @@ func MakeShadowConfigEntry(kind, name string) (structs.ConfigEntry, error) { return &ShadowAPIGatewayConfigEntry{APIGatewayConfigEntry: &structs.APIGatewayConfigEntry{Name: name}}, nil case structs.BoundAPIGateway: return &ShadowBoundAPIGatewayConfigEntry{BoundAPIGatewayConfigEntry: &structs.BoundAPIGatewayConfigEntry{Name: name}}, nil + case structs.FileSystemCertificate: + return &ShadowFileSystemCertificateConfigEntry{FileSystemCertificateConfigEntry: &structs.FileSystemCertificateConfigEntry{Name: name}}, nil case structs.InlineCertificate: return &ShadowInlineCertificateConfigEntry{InlineCertificateConfigEntry: &structs.InlineCertificateConfigEntry{Name: name}}, nil case structs.HTTPRoute: @@ -931,6 +933,15 @@ func (s ShadowBoundAPIGatewayConfigEntry) GetRealConfigEntry() structs.ConfigEnt return s.BoundAPIGatewayConfigEntry } +type ShadowFileSystemCertificateConfigEntry struct { + ShadowBase + *structs.FileSystemCertificateConfigEntry +} + +func (s ShadowFileSystemCertificateConfigEntry) GetRealConfigEntry() structs.ConfigEntry { + return s.FileSystemCertificateConfigEntry +} + type ShadowInlineCertificateConfigEntry struct { ShadowBase *structs.InlineCertificateConfigEntry diff --git a/agent/consul/fsm/fsm.go b/agent/consul/fsm/fsm.go index 5a350e4dae77..fba299f83729 100644 --- a/agent/consul/fsm/fsm.go +++ b/agent/consul/fsm/fsm.go @@ -196,7 +196,7 @@ func (c *FSM) Apply(log *raft.Log) interface{} { return nil } if structs.CEDowngrade && msgType >= 64 { - c.logger.Warn("ignoring enterprise message, for downgrading to oss", "type", msgType) + c.logger.Warn("ignoring enterprise message as part of downgrade to CE", "type", msgType) return nil } panic(fmt.Errorf("failed to apply request: %#v", buf)) @@ -268,8 +268,9 @@ func (c *FSM) Restore(old io.ReadCloser) error { } default: if structs.CEDowngrade && msg >= 64 { - c.logger.Warn("ignoring enterprise message , for downgrading to oss", "type", msg) - return nil + c.logger.Warn("ignoring enterprise message as part of downgrade to CE", "type", msg) + var ignore interface{} + return dec.Decode(&ignore) } else if msg >= 64 { return fmt.Errorf("msg type <%d> is a Consul Enterprise log entry. Consul CE cannot restore it", msg) } else { @@ -303,9 +304,7 @@ func (c *FSM) Restore(old io.ReadCloser) error { // for new data. To prevent that inconsistency we refresh the topics while holding // the lock which ensures that any subscriptions to topics for FSM generated events if c.deps.Publisher != nil { - c.deps.Publisher.RefreshTopic(state.EventTopicServiceHealth) - c.deps.Publisher.RefreshTopic(state.EventTopicServiceHealthConnect) - c.deps.Publisher.RefreshTopic(state.EventTopicCARoots) + c.deps.Publisher.RefreshAllTopics() } c.stateLock.Unlock() @@ -343,6 +342,10 @@ func ReadSnapshot(r io.Reader, handler func(header *SnapshotHeader, msg structs. // Decode msg := structs.MessageType(msgType[0]) + if msg == structs.FederationStateRequestType|structs.IgnoreUnknownTypeFlag { + msg = structs.FederationStateRequestType + } + if err := handler(&header, msg, dec); err != nil { return err } @@ -404,6 +407,11 @@ func (c *FSM) registerStreamSnapshotHandlers() { }, true) panicIfErr(err) + err = c.deps.Publisher.RegisterHandler(state.EventTopicFileSystemCertificate, func(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return c.State().FileSystemCertificateSnapshot(req, buf) + }, true) + panicIfErr(err) + err = c.deps.Publisher.RegisterHandler(state.EventTopicInlineCertificate, func(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { return c.State().InlineCertificateSnapshot(req, buf) }, true) @@ -437,7 +445,11 @@ func (c *FSM) registerStreamSnapshotHandlers() { err = c.deps.Publisher.RegisterHandler(state.EventTopicJWTProvider, func(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { return c.State().JWTProviderSnapshot(req, buf) }, true) + panicIfErr(err) + err = c.deps.Publisher.RegisterHandler(state.EventTopicExportedServices, func(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return c.State().ExportedServicesSnapshot(req, buf) + }, true) panicIfErr(err) } diff --git a/agent/consul/fsm/snapshot_ce.go b/agent/consul/fsm/snapshot_ce.go index 0fcd38703661..6a93f0b666f5 100644 --- a/agent/consul/fsm/snapshot_ce.go +++ b/agent/consul/fsm/snapshot_ce.go @@ -472,7 +472,7 @@ func (s *snapshot) persistFederationStates(sink raft.SnapshotSink, encoder *code } for _, fedState := range fedStates { - if _, err := sink.Write([]byte{byte(structs.FederationStateRequestType)}); err != nil { + if _, err := sink.Write([]byte{byte(structs.FederationStateRequestType | structs.IgnoreUnknownTypeFlag)}); err != nil { return err } // Encode the entry request without an operation since we don't need it for restoring. diff --git a/agent/consul/fsm/snapshot_ce_test.go b/agent/consul/fsm/snapshot_ce_test.go index 70ab2000faa4..01d4e230798f 100644 --- a/agent/consul/fsm/snapshot_ce_test.go +++ b/agent/consul/fsm/snapshot_ce_test.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/lib/stringslice" "github.com/hashicorp/consul/sdk/testutil" ) @@ -60,3 +61,101 @@ func TestRestoreFromEnterprise(t *testing.T) { require.EqualError(t, fsm.Restore(sink), "msg type <65> is a Consul Enterprise log entry. Consul CE cannot restore it") sink.Cancel() } + +func TestRestoreFromEnterprise_CEDowngrade(t *testing.T) { + logger := testutil.Logger(t) + + handle := &testRaftHandle{} + storageBackend := newStorageBackend(t, handle) + handle.apply = func(buf []byte) (any, error) { return storageBackend.Apply(buf, 123), nil } + + fsm := NewFromDeps(Deps{ + Logger: logger, + NewStateStore: func() *state.Store { + return state.NewStateStore(nil) + }, + StorageBackend: storageBackend, + }) + + // To verify if a proper message is displayed when Consul CE tries to + // unsuccessfully restore entries from a Consul Ent snapshot. + buf := bytes.NewBuffer(nil) + sink := &MockSink{buf, false} + + type EntMock struct { + ID int + Type string + } + + entMockEntry := EntMock{ + ID: 65, + Type: "A Consul Ent Log Type", + } + + // Create one entry to exercise the Go struct marshaller, and one to exercise the + // Binary Marshaller interface. This verifies that regardless of whether the struct gets + // encoded as a msgpack byte string (binary marshaller) or msgpack map (other struct), + // it will still be skipped over correctly. + registerEntry := structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + ID: "db", + Service: "db", + Tags: []string{"primary"}, + Port: 8000, + }, + } + proxyDefaultsEntry := &structs.ConfigEntryRequest{ + Op: structs.ConfigEntryUpsert, + Entry: &structs.ProxyConfigEntry{ + Kind: structs.ProxyDefaults, + Name: "global", + Config: map[string]interface{}{ + "foo": "bar", + }, + EnterpriseMeta: *structs.DefaultEnterpriseMetaInDefaultPartition(), + }, + } + + // Write the header and records. + header := SnapshotHeader{ + LastIndex: 0, + } + encoder := codec.NewEncoder(sink, structs.MsgpackHandle) + encoder.Encode(&header) + sink.Write([]byte{byte(structs.MessageType(entMockEntry.ID))}) + encoder.Encode(entMockEntry) + sink.Write([]byte{byte(structs.RegisterRequestType)}) + encoder.Encode(registerEntry) + sink.Write([]byte{byte(structs.ConfigEntryRequestType)}) + encoder.Encode(proxyDefaultsEntry) + + defer func() { + structs.CEDowngrade = false + }() + structs.CEDowngrade = true + + require.NoError(t, fsm.Restore(sink), "failed to decode Ent snapshot to CE") + + // Verify the register request + _, nodes, err := fsm.state.Nodes(nil, nil, "") + require.NoError(t, err) + require.Len(t, nodes, 1, "incorrect number of nodes: %v", nodes) + require.Equal(t, "foo", nodes[0].Node) + require.Equal(t, "dc1", nodes[0].Datacenter) + require.Equal(t, "127.0.0.1", nodes[0].Address) + _, fooSrv, err := fsm.state.NodeServices(nil, "foo", nil, "") + require.NoError(t, err) + require.Len(t, fooSrv.Services, 1) + require.Contains(t, fooSrv.Services["db"].Tags, "primary") + require.True(t, stringslice.Contains(fooSrv.Services["db"].Tags, "primary")) + require.Equal(t, 8000, fooSrv.Services["db"].Port) + + // Verify the proxy defaults request + _, configEntry, err := fsm.state.ConfigEntry(nil, structs.ProxyDefaults, "global", structs.DefaultEnterpriseMetaInDefaultPartition()) + require.NoError(t, err) + configEntry.SetHash(proxyDefaultsEntry.Entry.GetHash()) + require.Equal(t, proxyDefaultsEntry.Entry, configEntry) +} diff --git a/agent/consul/fsm/snapshot_test.go b/agent/consul/fsm/snapshot_test.go index 22d6f5e956ee..de4e64e344c3 100644 --- a/agent/consul/fsm/snapshot_test.go +++ b/agent/consul/fsm/snapshot_test.go @@ -566,7 +566,6 @@ func TestFSM_SnapshotRestore_CE(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "default", - PeerName: "local", Namespace: "default", }, Name: "bar", @@ -815,14 +814,17 @@ func TestFSM_SnapshotRestore_CE(t *testing.T) { // Verify config entries are restored _, serviceConfEntry, err := fsm2.state.ConfigEntry(nil, structs.ServiceDefaults, "foo", structs.DefaultEnterpriseMetaInDefaultPartition()) require.NoError(t, err) + serviceConfig.SetHash(serviceConfEntry.GetHash()) require.Equal(t, serviceConfig, serviceConfEntry) _, proxyConfEntry, err := fsm2.state.ConfigEntry(nil, structs.ProxyDefaults, "global", structs.DefaultEnterpriseMetaInDefaultPartition()) require.NoError(t, err) + proxyConfig.SetHash(proxyConfEntry.GetHash()) require.Equal(t, proxyConfig, proxyConfEntry) _, ingressRestored, err := fsm2.state.ConfigEntry(nil, structs.IngressGateway, "ingress", structs.DefaultEnterpriseMetaInDefaultPartition()) require.NoError(t, err) + ingress.SetHash(ingressRestored.GetHash()) require.Equal(t, ingress, ingressRestored) _, restoredGatewayServices, err := fsm2.state.GatewayServices(nil, "ingress", structs.DefaultEnterpriseMetaInDefaultPartition()) @@ -856,11 +858,13 @@ func TestFSM_SnapshotRestore_CE(t *testing.T) { // Verify service-intentions is restored _, serviceIxnEntry, err := fsm2.state.ConfigEntry(nil, structs.ServiceIntentions, "foo", structs.DefaultEnterpriseMetaInDefaultPartition()) require.NoError(t, err) + serviceIxn.SetHash(serviceIxnEntry.GetHash()) require.Equal(t, serviceIxn, serviceIxnEntry) // Verify mesh config entry is restored _, meshConfigEntry, err := fsm2.state.ConfigEntry(nil, structs.MeshConfig, structs.MeshConfigMesh, structs.DefaultEnterpriseMetaInDefaultPartition()) require.NoError(t, err) + meshConfig.SetHash(meshConfigEntry.GetHash()) require.Equal(t, meshConfig, meshConfigEntry) _, restoredServiceNames, err := fsm2.state.ServiceNamesOfKind(nil, structs.ServiceKindTypical) diff --git a/agent/consul/gateways/controller_gateways.go b/agent/consul/gateways/controller_gateways.go index ae82bdddc449..a4bd69441475 100644 --- a/agent/consul/gateways/controller_gateways.go +++ b/agent/consul/gateways/controller_gateways.go @@ -61,7 +61,7 @@ func (r *apiGatewayReconciler) Reconcile(ctx context.Context, req controller.Req return reconcileEntry(r.fsm.State(), r.logger, ctx, req, r.reconcileHTTPRoute, r.cleanupRoute) case structs.TCPRoute: return reconcileEntry(r.fsm.State(), r.logger, ctx, req, r.reconcileTCPRoute, r.cleanupRoute) - case structs.InlineCertificate: + case structs.InlineCertificate, structs.FileSystemCertificate: return r.enqueueCertificateReferencedGateways(r.fsm.State(), ctx, req) case structs.JWTProvider: return r.enqueueJWTProviderReferencedGatewaysAndHTTPRoutes(r.fsm.State(), ctx, req) @@ -540,7 +540,8 @@ func NewAPIGatewayController(fsm *fsm.FSM, publisher state.EventPublisher, updat logger: logger, updater: updater, } - reconciler.controller = controller.New(publisher, reconciler) + reconciler.controller = controller.New(publisher, reconciler). + WithLogger(logger.With("controller", "apiGatewayController")) return reconciler.controller.Subscribe( &stream.SubscribeRequest{ Topic: state.EventTopicAPIGateway, @@ -624,6 +625,7 @@ func getAllGatewayMeta(store *state.Store) ([]*gatewayMeta, error) { meta := make([]*gatewayMeta, 0, len(boundGateways)) for _, b := range boundGateways { bound := b.(*structs.BoundAPIGatewayConfigEntry) + bound = bound.DeepCopy() for _, g := range gateways { gateway := g.(*structs.APIGatewayConfigEntry) if bound.IsInitializedForGateway(gateway) { @@ -667,6 +669,10 @@ func (g *gatewayMeta) updateRouteBinding(route structs.BoundRoute) (bool, []stru return nil }) + if g.BoundGateway.Services == nil { + g.BoundGateway.Services = make(structs.ServiceRouteReferences) + } + // now try and bind all of the route's current refs for _, ref := range route.GetParents() { if !g.shouldBindRoute(ref) { @@ -708,6 +714,9 @@ func (g *gatewayMeta) updateRouteBinding(route structs.BoundRoute) (bool, []stru } if refDidBind { + for _, serviceName := range route.GetServiceNames() { + g.BoundGateway.Services.AddService(structs.NewServiceName(serviceName.Name, &serviceName.EnterpriseMeta), routeRef) + } boundRefs = append(boundRefs, ref) } } @@ -1138,6 +1147,7 @@ func removeRoute(route structs.ResourceReference, entries ...*gatewayMeta) []*ga for _, entry := range entries { if entry.unbindRoute(route) { modified = append(modified, entry) + entry.BoundGateway.Services.RemoveRouteRef(route) } } diff --git a/agent/consul/gateways/controller_gateways_test.go b/agent/consul/gateways/controller_gateways_test.go index 5acb06f0411b..666f9e002cf4 100644 --- a/agent/consul/gateways/controller_gateways_test.go +++ b/agent/consul/gateways/controller_gateways_test.go @@ -217,6 +217,7 @@ func TestBoundAPIGatewayBindRoute(t *testing.T) { Kind: structs.TerminatingGateway, Name: "Gateway", Listeners: []structs.BoundAPIGatewayListener{}, + Services: make(structs.ServiceRouteReferences), }, expectedDidBind: false, }, @@ -484,6 +485,7 @@ func TestBindRoutesToGateways(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, }, expectedReferenceErrors: map[structs.ResourceReference]error{}, @@ -533,6 +535,7 @@ func TestBindRoutesToGateways(t *testing.T) { Routes: []structs.ResourceReference{}, }, }, + Services: make(structs.ServiceRouteReferences), }, }, expectedReferenceErrors: map[structs.ResourceReference]error{}, @@ -628,6 +631,7 @@ func TestBindRoutesToGateways(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, { Name: "Gateway 2", @@ -643,6 +647,7 @@ func TestBindRoutesToGateways(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, }, expectedReferenceErrors: map[structs.ResourceReference]error{}, @@ -720,6 +725,7 @@ func TestBindRoutesToGateways(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, }, expectedReferenceErrors: map[structs.ResourceReference]error{}, @@ -803,6 +809,7 @@ func TestBindRoutesToGateways(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, }, expectedReferenceErrors: map[structs.ResourceReference]error{}, @@ -892,6 +899,7 @@ func TestBindRoutesToGateways(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, }, expectedReferenceErrors: map[structs.ResourceReference]error{}, @@ -1007,6 +1015,7 @@ func TestBindRoutesToGateways(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, { Name: "Gateway 2", @@ -1026,6 +1035,7 @@ func TestBindRoutesToGateways(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, }, expectedReferenceErrors: map[structs.ResourceReference]error{}, @@ -1109,6 +1119,7 @@ func TestBindRoutesToGateways(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, }, expectedReferenceErrors: map[structs.ResourceReference]error{}, @@ -1215,6 +1226,7 @@ func TestBindRoutesToGateways(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, { Name: "Gateway 2", @@ -1230,6 +1242,7 @@ func TestBindRoutesToGateways(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, }, expectedReferenceErrors: map[structs.ResourceReference]error{}, @@ -1362,6 +1375,7 @@ func TestBindRoutesToGateways(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, }, expectedReferenceErrors: map[structs.ResourceReference]error{}, @@ -1999,6 +2013,11 @@ func TestAPIGatewayController(t *testing.T) { EnterpriseMeta: *defaultMeta, }}, }}, + + Services: structs.ServiceRouteReferences{structs.NewServiceName("tcp-upstream", nil): []structs.ResourceReference{{ + Kind: "tcp-route", + Name: "tcp-route", + }}}, }, &structs.APIGatewayConfigEntry{ Kind: structs.APIGateway, @@ -2226,6 +2245,16 @@ func TestAPIGatewayController(t *testing.T) { EnterpriseMeta: *defaultMeta, }}, }}, + Services: structs.ServiceRouteReferences{structs.NewServiceName("tcp-upstream", nil): []structs.ResourceReference{ + { + Kind: "tcp-route", + Name: "tcp-route-one", + }, + { + Kind: "tcp-route", + Name: "tcp-route-two", + }, + }}, }, &structs.APIGatewayConfigEntry{ Kind: structs.APIGateway, @@ -2375,6 +2404,16 @@ func TestAPIGatewayController(t *testing.T) { EnterpriseMeta: *defaultMeta, }}, }}, + Services: structs.ServiceRouteReferences{structs.NewServiceName("http-upstream", nil): []structs.ResourceReference{ + { + Kind: "http-route", + Name: "http-route-one", + }, + { + Kind: "http-route", + Name: "http-route-two", + }, + }}, }, &structs.APIGatewayConfigEntry{ Kind: structs.APIGateway, @@ -2522,6 +2561,10 @@ func TestAPIGatewayController(t *testing.T) { EnterpriseMeta: *defaultMeta, }}, }}, + Services: structs.ServiceRouteReferences{structs.NewServiceName("http-upstream", nil): []structs.ResourceReference{{ + Kind: "http-route", + Name: "http-route", + }}}, }, &structs.APIGatewayConfigEntry{ Kind: structs.APIGateway, @@ -2682,6 +2725,20 @@ func TestAPIGatewayController(t *testing.T) { EnterpriseMeta: *defaultMeta, }}, }}, + Services: structs.ServiceRouteReferences{ + structs.NewServiceName("http-upstream", nil): []structs.ResourceReference{ + { + Kind: "http-route", + Name: "http-route", + }, + }, + structs.NewServiceName("tcp-upstream", nil): []structs.ResourceReference{ + { + Kind: "tcp-route", + Name: "tcp-route", + }, + }, + }, }, &structs.APIGatewayConfigEntry{ Kind: structs.APIGateway, @@ -2809,6 +2866,7 @@ func TestAPIGatewayController(t *testing.T) { Name: "tcp-listener", Routes: []structs.ResourceReference{}, }}, + Services: make(structs.ServiceRouteReferences), }, &structs.APIGatewayConfigEntry{ Kind: structs.APIGateway, @@ -2898,6 +2956,7 @@ func TestAPIGatewayController(t *testing.T) { Name: "tcp-listener", Routes: []structs.ResourceReference{}, }}, + Services: make(structs.ServiceRouteReferences), }, &structs.APIGatewayConfigEntry{ Kind: structs.APIGateway, @@ -3041,6 +3100,14 @@ func TestAPIGatewayController(t *testing.T) { EnterpriseMeta: *defaultMeta, }}, }}, + Services: structs.ServiceRouteReferences{ + structs.NewServiceName("http-upstream", nil): []structs.ResourceReference{ + { + Kind: "http-route", + Name: "http-route", + }, + }, + }, }, &structs.APIGatewayConfigEntry{ Kind: structs.APIGateway, @@ -3214,6 +3281,7 @@ func TestAPIGatewayController(t *testing.T) { Name: "tcp-listener", Routes: []structs.ResourceReference{}, }}, + Services: make(structs.ServiceRouteReferences), }, &structs.APIGatewayConfigEntry{ Kind: structs.APIGateway, @@ -3353,6 +3421,7 @@ func TestAPIGatewayController(t *testing.T) { Listeners: []structs.BoundAPIGatewayListener{{ Name: "http-listener", }}, + Services: make(structs.ServiceRouteReferences), }, }, }, @@ -3427,6 +3496,7 @@ func TestAPIGatewayController(t *testing.T) { EnterpriseMeta: *defaultMeta, }}, }}, + Services: make(structs.ServiceRouteReferences), }, }, }, @@ -3552,6 +3622,7 @@ func TestAPIGatewayController(t *testing.T) { }, }, }, + Services: make(structs.ServiceRouteReferences), }, }, }, @@ -3651,6 +3722,7 @@ func TestAPIGatewayController(t *testing.T) { {Name: "listener-1"}, {Name: "listener-2"}, }, + Services: make(structs.ServiceRouteReferences), }, }, }, @@ -3766,6 +3838,7 @@ func TestAPIGatewayController(t *testing.T) { Name: "invalid-listener", }, }, + Services: make(structs.ServiceRouteReferences), }, }, }, @@ -3854,6 +3927,7 @@ func TestAPIGatewayController(t *testing.T) { EnterpriseMeta: *defaultMeta, }}, }}, + Services: make(structs.ServiceRouteReferences), }, }, }, diff --git a/agent/consul/health_endpoint.go b/agent/consul/health_endpoint.go index d26bbcd3b6f2..6f00ec4b08bf 100644 --- a/agent/consul/health_endpoint.go +++ b/agent/consul/health_endpoint.go @@ -8,15 +8,15 @@ import ( "sort" "github.com/armon/go-metrics" - bexpr "github.com/hashicorp/go-bexpr" - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-memdb" hashstructure_v2 "github.com/mitchellh/hashstructure/v2" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/configentry" "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/go-bexpr" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-memdb" ) // Health endpoint is used to query the health information @@ -250,68 +250,86 @@ func (h *Health) ServiceNodes(args *structs.ServiceSpecificRequest, reply *struc func(ws memdb.WatchSet, state *state.Store) error { var thisReply structs.IndexedCheckServiceNodes - index, nodes, err := f(ws, state, args) + sgIdx, sgArgs, err := h.getArgsForSamenessGroupMembers(args, ws, state) if err != nil { return err } - resolvedNodes := nodes - if args.MergeCentralConfig { - for _, node := range resolvedNodes { - ns := node.Service - if ns.IsSidecarProxy() || ns.IsGateway() { - cfgIndex, mergedns, err := configentry.MergeNodeServiceWithCentralConfig(ws, state, ns, h.logger) - if err != nil { - return err - } - if cfgIndex > index { - index = cfgIndex + for _, arg := range sgArgs { + index, nodes, err := f(ws, state, arg) + if err != nil { + return err + } + + resolvedNodes := nodes + if arg.MergeCentralConfig { + for _, node := range resolvedNodes { + ns := node.Service + if ns.IsSidecarProxy() || ns.IsGateway() { + cfgIndex, mergedns, err := configentry.MergeNodeServiceWithCentralConfig(ws, state, ns, h.logger) + if err != nil { + return err + } + if cfgIndex > index { + index = cfgIndex + } + *node.Service = *mergedns } - *node.Service = *mergedns } - } - // Generate a hash of the resolvedNodes driving this response. - // Use it to determine if the response is identical to a prior wakeup. - newMergeHash, err := hashstructure_v2.Hash(resolvedNodes, hashstructure_v2.FormatV2, nil) - if err != nil { - return fmt.Errorf("error hashing reply for spurious wakeup suppression: %w", err) - } - if ranMergeOnce && priorMergeHash == newMergeHash { - // the below assignment is not required as the if condition already validates equality, - // but makes it more clear that prior value is being reset to the new hash on each run. - priorMergeHash = newMergeHash - reply.Index = index - // NOTE: the prior response is still alive inside of *reply, which is desirable - return errNotChanged - } else { - priorMergeHash = newMergeHash - ranMergeOnce = true - } + // Generate a hash of the resolvedNodes driving this response. + // Use it to determine if the response is identical to a prior wakeup. + newMergeHash, err := hashstructure_v2.Hash(resolvedNodes, hashstructure_v2.FormatV2, nil) + if err != nil { + return fmt.Errorf("error hashing reply for spurious wakeup suppression: %w", err) + } + if ranMergeOnce && priorMergeHash == newMergeHash { + // the below assignment is not required as the if condition already validates equality, + // but makes it more clear that prior value is being reset to the new hash on each run. + priorMergeHash = newMergeHash + reply.Index = index + // NOTE: the prior response is still alive inside of *reply, which is desirable + return errNotChanged + } else { + priorMergeHash = newMergeHash + ranMergeOnce = true + } - } + } - thisReply.Index, thisReply.Nodes = index, resolvedNodes + thisReply.Index, thisReply.Nodes = index, resolvedNodes - if len(args.NodeMetaFilters) > 0 { - thisReply.Nodes = nodeMetaFilter(args.NodeMetaFilters, thisReply.Nodes) - } + if len(arg.NodeMetaFilters) > 0 { + thisReply.Nodes = nodeMetaFilter(arg.NodeMetaFilters, thisReply.Nodes) + } - raw, err := filter.Execute(thisReply.Nodes) - if err != nil { - return err - } - thisReply.Nodes = raw.(structs.CheckServiceNodes) + raw, err := filter.Execute(thisReply.Nodes) + if err != nil { + return err + } + filteredNodes := raw.(structs.CheckServiceNodes) + thisReply.Nodes = filteredNodes.Filter(structs.CheckServiceNodeFilterOptions{FilterType: arg.HealthFilterType}) + + // Note: we filter the results with ACLs *after* applying the user-supplied + // bexpr filter, to ensure QueryMeta.ResultsFilteredByACLs does not include + // results that would be filtered out even if the user did have permission. + if err := h.srv.filterACL(arg.Token, &thisReply); err != nil { + return err + } - // Note: we filter the results with ACLs *after* applying the user-supplied - // bexpr filter, to ensure QueryMeta.ResultsFilteredByACLs does not include - // results that would be filtered out even if the user did have permission. - if err := h.srv.filterACL(args.Token, &thisReply); err != nil { - return err + if err := h.srv.sortNodesByDistanceFrom(arg.Source, thisReply.Nodes); err != nil { + return err + } + if len(thisReply.Nodes) > 0 { + break + } } - if err := h.srv.sortNodesByDistanceFrom(args.Source, thisReply.Nodes); err != nil { - return err + // If sameness group was used, evaluate the index of the sameness group + // and update the index of the response if it is greater. If sameness group is not + // used, the sgIdx will be 0 in this evaluation. + if sgIdx > thisReply.Index { + thisReply.Index = sgIdx } *reply = thisReply diff --git a/agent/consul/health_endpoint_ce.go b/agent/consul/health_endpoint_ce.go new file mode 100644 index 000000000000..1580054e5d94 --- /dev/null +++ b/agent/consul/health_endpoint_ce.go @@ -0,0 +1,38 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +//go:build !consulent + +package consul + +import ( + "errors" + + "github.com/hashicorp/go-memdb" + + "github.com/hashicorp/consul/agent/consul/state" + "github.com/hashicorp/consul/agent/structs" +) + +// getArgsForSamenessGroupMembers returns the arguments for the sameness group members if SamenessGroup +// field is set in the ServiceSpecificRequest. It returns the index of the sameness group, the arguments +// for the sameness group members and an error if any. +// If SamenessGroup is not set, it returns: +// - the index 0 +// - an array containing the original arguments +// - nil error +// If SamenessGroup is set on CE, it returns:: +// - the index of 0 +// - nil array +// - an error indicating that sameness groups are not supported in consul CE +// If SamenessGroup is set on ENT, it returns: +// - the index of the sameness group +// - an array containing the arguments for the sameness group members +// - nil error +func (h *Health) getArgsForSamenessGroupMembers(args *structs.ServiceSpecificRequest, + ws memdb.WatchSet, state *state.Store) (uint64, []*structs.ServiceSpecificRequest, error) { + if args.SamenessGroup != "" { + return 0, nil, errors.New("sameness groups are not supported in consul CE") + } + return 0, []*structs.ServiceSpecificRequest{args}, nil +} diff --git a/agent/consul/health_endpoint_test.go b/agent/consul/health_endpoint_test.go index b47159c22942..07f23cc2e0c1 100644 --- a/agent/consul/health_endpoint_test.go +++ b/agent/consul/health_endpoint_test.go @@ -15,7 +15,7 @@ import ( "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/testrpc" @@ -193,8 +193,8 @@ func TestHealth_ChecksInState_DistanceSort(t *testing.T) { t.Fatalf("err: %v", err) } updates := structs.Coordinates{ - {Node: "foo", Coord: lib.GenerateCoordinate(1 * time.Millisecond)}, - {Node: "bar", Coord: lib.GenerateCoordinate(2 * time.Millisecond)}, + {Node: "foo", Coord: librtt.GenerateCoordinate(1 * time.Millisecond)}, + {Node: "bar", Coord: librtt.GenerateCoordinate(2 * time.Millisecond)}, } if err := s1.fsm.State().CoordinateBatchUpdate(3, updates); err != nil { t.Fatalf("err: %v", err) @@ -482,8 +482,8 @@ func TestHealth_ServiceChecks_DistanceSort(t *testing.T) { t.Fatalf("err: %v", err) } updates := structs.Coordinates{ - {Node: "foo", Coord: lib.GenerateCoordinate(1 * time.Millisecond)}, - {Node: "bar", Coord: lib.GenerateCoordinate(2 * time.Millisecond)}, + {Node: "foo", Coord: librtt.GenerateCoordinate(1 * time.Millisecond)}, + {Node: "bar", Coord: librtt.GenerateCoordinate(2 * time.Millisecond)}, } if err := s1.fsm.State().CoordinateBatchUpdate(3, updates); err != nil { t.Fatalf("err: %v", err) @@ -969,8 +969,8 @@ func TestHealth_ServiceNodes_DistanceSort(t *testing.T) { t.Fatalf("err: %v", err) } updates := structs.Coordinates{ - {Node: "foo", Coord: lib.GenerateCoordinate(1 * time.Millisecond)}, - {Node: "bar", Coord: lib.GenerateCoordinate(2 * time.Millisecond)}, + {Node: "foo", Coord: librtt.GenerateCoordinate(1 * time.Millisecond)}, + {Node: "bar", Coord: librtt.GenerateCoordinate(2 * time.Millisecond)}, } if err := s1.fsm.State().CoordinateBatchUpdate(3, updates); err != nil { t.Fatalf("err: %v", err) diff --git a/agent/consul/intention_endpoint.go b/agent/consul/intention_endpoint.go index a3e4ad678b1d..df0542814597 100644 --- a/agent/consul/intention_endpoint.go +++ b/agent/consul/intention_endpoint.go @@ -752,19 +752,7 @@ func (s *Intention) Check(args *structs.IntentionQueryRequest, reply *structs.In } } - // Note: the default intention policy is like an intention with a - // wildcarded destination in that it is limited to L4-only. - - // No match, we need to determine the default behavior. We do this by - // fetching the default intention behavior from the resolved authorizer. - // The default behavior if ACLs are disabled is to allow connections - // to mimic the behavior of Consul itself: everything is allowed if - // ACLs are disabled. - // - // NOTE(mitchellh): This is the same behavior as the agent authorize - // endpoint. If this behavior is incorrect, we should also change it there - // which is much more important. - defaultDecision := authz.IntentionDefaultAllow(nil) + defaultAllow := DefaultIntentionAllow(authz, s.srv.config.DefaultIntentionPolicy) store := s.srv.fsm.State() @@ -784,7 +772,7 @@ func (s *Intention) Check(args *structs.IntentionQueryRequest, reply *structs.In Partition: query.DestinationPartition, Intentions: intentions, MatchType: structs.IntentionMatchDestination, - DefaultDecision: defaultDecision, + DefaultAllow: defaultAllow, AllowPermissions: false, } decision, err := store.IntentionDecision(opts) diff --git a/agent/consul/intention_endpoint_test.go b/agent/consul/intention_endpoint_test.go index d7e469b80326..08480501d7bf 100644 --- a/agent/consul/intention_endpoint_test.go +++ b/agent/consul/intention_endpoint_test.go @@ -551,7 +551,7 @@ func TestIntentionApply_WithoutIDs(t *testing.T) { }, RaftIndex: entry.RaftIndex, } - + entry.Hash = 0 require.Equal(t, expect, entry) } @@ -690,7 +690,7 @@ func TestIntentionApply_WithoutIDs(t *testing.T) { }, RaftIndex: entry.RaftIndex, } - + entry.Hash = 0 require.Equal(t, expect, entry) } @@ -759,7 +759,7 @@ func TestIntentionApply_WithoutIDs(t *testing.T) { }, RaftIndex: entry.RaftIndex, } - + entry.Hash = 0 require.Equal(t, expect, entry) } @@ -1960,106 +1960,89 @@ func TestIntentionMatch_acl(t *testing.T) { } } -// Test the Check method defaults to allow with no ACL set. -func TestIntentionCheck_defaultNoACL(t *testing.T) { +func TestIntentionCheck(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } t.Parallel() - dir1, s1 := testServer(t) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - codec := rpcClient(t, s1) - defer codec.Close() - - waitForLeaderEstablishment(t, s1) - - // Test - req := &structs.IntentionQueryRequest{ - Datacenter: "dc1", - Check: &structs.IntentionQueryCheck{ - SourceName: "bar", - DestinationName: "qux", - SourceType: structs.IntentionSourceConsul, - }, - } - var resp structs.IntentionQueryCheckResponse - require.NoError(t, msgpackrpc.CallWithCodec(codec, "Intention.Check", req, &resp)) - require.True(t, resp.Allowed) -} - -// Test the Check method defaults to deny with allowlist ACLs. -func TestIntentionCheck_defaultACLDeny(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") + type testcase struct { + aclsEnabled bool + defaultACL string + defaultIxn string + expectAllowed bool } - - t.Parallel() - - dir1, s1 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "deny" - }) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - codec := rpcClient(t, s1) - defer codec.Close() - - waitForLeaderEstablishment(t, s1) - - // Check - req := &structs.IntentionQueryRequest{ - Datacenter: "dc1", - Check: &structs.IntentionQueryCheck{ - SourceName: "bar", - DestinationName: "qux", - SourceType: structs.IntentionSourceConsul, + tcs := map[string]testcase{ + "acls disabled, no default intention policy": { + aclsEnabled: false, + expectAllowed: true, + }, + "acls disabled, default intention allow": { + aclsEnabled: false, + defaultIxn: "allow", + expectAllowed: true, + }, + "acls disabled, default intention deny": { + aclsEnabled: false, + defaultIxn: "deny", + expectAllowed: false, + }, + "acls deny, no default intention policy": { + aclsEnabled: true, + defaultACL: "deny", + expectAllowed: false, + }, + "acls allow, no default intention policy": { + aclsEnabled: true, + defaultACL: "allow", + expectAllowed: true, + }, + "acls deny, default intention allow": { + aclsEnabled: true, + defaultACL: "deny", + defaultIxn: "allow", + expectAllowed: true, + }, + "acls allow, default intention deny": { + aclsEnabled: true, + defaultACL: "allow", + defaultIxn: "deny", + expectAllowed: false, }, } - req.Token = "root" - var resp structs.IntentionQueryCheckResponse - require.NoError(t, msgpackrpc.CallWithCodec(codec, "Intention.Check", req, &resp)) - require.False(t, resp.Allowed) -} - -// Test the Check method defaults to deny with denylist ACLs. -func TestIntentionCheck_defaultACLAllow(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() + for name, tc := range tcs { + tc := tc + t.Run(name, func(t *testing.T) { + t.Parallel() + _, s1 := testServerWithConfig(t, func(c *Config) { + if tc.aclsEnabled { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = tc.defaultACL + } + c.DefaultIntentionPolicy = tc.defaultIxn + }) + codec := rpcClient(t, s1) - dir1, s1 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "allow" - }) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - codec := rpcClient(t, s1) - defer codec.Close() + waitForLeaderEstablishment(t, s1) - waitForLeaderEstablishment(t, s1) + req := &structs.IntentionQueryRequest{ + Datacenter: "dc1", + Check: &structs.IntentionQueryCheck{ + SourceName: "bar", + DestinationName: "qux", + SourceType: structs.IntentionSourceConsul, + }, + } + req.Token = "root" - // Check - req := &structs.IntentionQueryRequest{ - Datacenter: "dc1", - Check: &structs.IntentionQueryCheck{ - SourceName: "bar", - DestinationName: "qux", - SourceType: structs.IntentionSourceConsul, - }, + var resp structs.IntentionQueryCheckResponse + require.NoError(t, msgpackrpc.CallWithCodec(codec, "Intention.Check", req, &resp)) + require.Equal(t, tc.expectAllowed, resp.Allowed) + }) } - req.Token = "root" - var resp structs.IntentionQueryCheckResponse - require.NoError(t, msgpackrpc.CallWithCodec(codec, "Intention.Check", req, &resp)) - require.True(t, resp.Allowed) } // Test the Check method requires service:read permission. diff --git a/agent/consul/internal_endpoint.go b/agent/consul/internal_endpoint.go index 1a8a0fca3028..af27842d2045 100644 --- a/agent/consul/internal_endpoint.go +++ b/agent/consul/internal_endpoint.go @@ -197,43 +197,44 @@ func (m *Internal) ServiceDump(args *structs.ServiceDumpRequest, reply *structs. } reply.Nodes = nodes - // get a list of all peerings - index, listedPeerings, err := state.PeeringList(ws, args.EnterpriseMeta) - if err != nil { - return fmt.Errorf("could not list peers for service dump %w", err) - } - - if index > maxIndex { - maxIndex = index - } - - for _, p := range listedPeerings { - // Note we fetch imported services with wildcard namespace because imported services' namespaces - // are in a different locality; regardless of our local namespace, we return all imported services - // of the local partition. - index, importedNodes, err := state.ServiceDump(ws, args.ServiceKind, args.UseServiceKind, args.EnterpriseMeta.WithWildcardNamespace(), p.Name) + if !args.NodesOnly { + // get a list of all peerings + index, listedPeerings, err := state.PeeringList(ws, args.EnterpriseMeta) if err != nil { - return fmt.Errorf("could not get a service dump for peer %q: %w", p.Name, err) + return fmt.Errorf("could not list peers for service dump %w", err) } if index > maxIndex { maxIndex = index } - reply.ImportedNodes = append(reply.ImportedNodes, importedNodes...) - } - // Get, store, and filter gateway services - idx, gatewayServices, err := state.DumpGatewayServices(ws) - if err != nil { - return err - } - reply.Gateways = gatewayServices + for _, p := range listedPeerings { + // Note we fetch imported services with wildcard namespace because imported services' namespaces + // are in a different locality; regardless of our local namespace, we return all imported services + // of the local partition. + index, importedNodes, err := state.ServiceDump(ws, args.ServiceKind, args.UseServiceKind, args.EnterpriseMeta.WithWildcardNamespace(), p.Name) + if err != nil { + return fmt.Errorf("could not get a service dump for peer %q: %w", p.Name, err) + } + + if index > maxIndex { + maxIndex = index + } + reply.ImportedNodes = append(reply.ImportedNodes, importedNodes...) + } + + // Get, store, and filter gateway services + idx, gatewayServices, err := state.DumpGatewayServices(ws) + if err != nil { + return err + } + reply.Gateways = gatewayServices - if idx > maxIndex { - maxIndex = idx + if idx > maxIndex { + maxIndex = idx + } } reply.Index = maxIndex - raw, err := filter.Execute(reply.Nodes) if err != nil { return fmt.Errorf("could not filter local service dump: %w", err) @@ -241,12 +242,13 @@ func (m *Internal) ServiceDump(args *structs.ServiceDumpRequest, reply *structs. reply.Nodes = raw.(structs.CheckServiceNodes) } - importedRaw, err := filter.Execute(reply.ImportedNodes) - if err != nil { - return fmt.Errorf("could not filter peer service dump: %w", err) + if !args.NodesOnly { + importedRaw, err := filter.Execute(reply.ImportedNodes) + if err != nil { + return fmt.Errorf("could not filter peer service dump: %w", err) + } + reply.ImportedNodes = importedRaw.(structs.CheckServiceNodes) } - reply.ImportedNodes = importedRaw.(structs.CheckServiceNodes) - // Note: we filter the results with ACLs *after* applying the user-supplied // bexpr filter, to ensure QueryMeta.ResultsFilteredByACLs does not include // results that would be filtered out even if the user did have permission. @@ -304,7 +306,7 @@ func (m *Internal) ServiceTopology(args *structs.ServiceSpecificRequest, reply * &args.QueryOptions, &reply.QueryMeta, func(ws memdb.WatchSet, state *state.Store) error { - defaultAllow := authz.IntentionDefaultAllow(nil) + defaultAllow := DefaultIntentionAllow(authz, m.srv.config.DefaultIntentionPolicy) index, topology, err := state.ServiceTopology(ws, args.Datacenter, args.ServiceName, args.ServiceKind, defaultAllow, &args.EnterpriseMeta) if err != nil { @@ -373,10 +375,10 @@ func (m *Internal) internalUpstreams(args *structs.ServiceSpecificRequest, reply &args.QueryOptions, &reply.QueryMeta, func(ws memdb.WatchSet, state *state.Store) error { - defaultDecision := authz.IntentionDefaultAllow(nil) + defaultAllow := DefaultIntentionAllow(authz, m.srv.config.DefaultIntentionPolicy) sn := structs.NewServiceName(args.ServiceName, &args.EnterpriseMeta) - index, services, err := state.IntentionTopology(ws, sn, false, defaultDecision, intentionTarget) + index, services, err := state.IntentionTopology(ws, sn, false, defaultAllow, intentionTarget) if err != nil { return err } diff --git a/agent/consul/internal_endpoint_test.go b/agent/consul/internal_endpoint_test.go index 3f853df7ceb2..e4b9a14b700d 100644 --- a/agent/consul/internal_endpoint_test.go +++ b/agent/consul/internal_endpoint_test.go @@ -1217,10 +1217,11 @@ func TestInternal_GatewayServiceDump_Terminating(t *testing.T) { }, }, GatewayService: &structs.GatewayService{ - Gateway: structs.NewServiceName("terminating-gateway", nil), - Service: structs.NewServiceName("db", nil), - GatewayKind: "terminating-gateway", - ServiceKind: structs.GatewayServiceKindService, + Gateway: structs.NewServiceName("terminating-gateway", nil), + Service: structs.NewServiceName("db", nil), + GatewayKind: "terminating-gateway", + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, }, { @@ -1251,21 +1252,23 @@ func TestInternal_GatewayServiceDump_Terminating(t *testing.T) { }, }, GatewayService: &structs.GatewayService{ - Gateway: structs.NewServiceName("terminating-gateway", nil), - Service: structs.NewServiceName("db", nil), - GatewayKind: "terminating-gateway", - ServiceKind: structs.GatewayServiceKindService, + Gateway: structs.NewServiceName("terminating-gateway", nil), + Service: structs.NewServiceName("db", nil), + GatewayKind: "terminating-gateway", + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, }, { // Only GatewayService should be returned when linked service isn't registered GatewayService: &structs.GatewayService{ - Gateway: structs.NewServiceName("terminating-gateway", nil), - Service: structs.NewServiceName("redis", nil), - GatewayKind: "terminating-gateway", - CAFile: "/etc/certs/ca.pem", - CertFile: "/etc/certs/cert.pem", - KeyFile: "/etc/certs/key.pem", + Gateway: structs.NewServiceName("terminating-gateway", nil), + Service: structs.NewServiceName("redis", nil), + GatewayKind: "terminating-gateway", + CAFile: "/etc/certs/ca.pem", + CertFile: "/etc/certs/cert.pem", + KeyFile: "/etc/certs/key.pem", + AutoHostRewrite: true, }, }, } @@ -1779,10 +1782,11 @@ func TestInternal_ServiceDump_Peering(t *testing.T) { // prep the cluster with some data we can use in our filters registerTestCatalogEntries(t, codec) - doRequest := func(t *testing.T, filter string) structs.IndexedNodesWithGateways { + doRequest := func(t *testing.T, filter string, onlyNodes bool) structs.IndexedNodesWithGateways { t.Helper() - args := structs.DCSpecificRequest{ + args := structs.ServiceDumpRequest{ QueryOptions: structs.QueryOptions{Filter: filter}, + NodesOnly: onlyNodes, } var out structs.IndexedNodesWithGateways @@ -1792,7 +1796,7 @@ func TestInternal_ServiceDump_Peering(t *testing.T) { } t.Run("No peerings", func(t *testing.T) { - nodes := doRequest(t, "") + nodes := doRequest(t, "", false) // redis (3), web (3), critical (1), warning (1) and consul (1) require.Len(t, nodes.Nodes, 9) require.Len(t, nodes.ImportedNodes, 0) @@ -1809,19 +1813,27 @@ func TestInternal_ServiceDump_Peering(t *testing.T) { require.NoError(t, err) t.Run("peerings", func(t *testing.T) { - nodes := doRequest(t, "") + nodes := doRequest(t, "", false) // redis (3), web (3), critical (1), warning (1) and consul (1) require.Len(t, nodes.Nodes, 9) // service (1) require.Len(t, nodes.ImportedNodes, 1) }) + t.Run("peerings onlynodes", func(t *testing.T) { + nodes := doRequest(t, "", true) + // redis (3), web (3), critical (1), warning (1) and consul (1) + require.Len(t, nodes.Nodes, 9) + // service (1) + require.Len(t, nodes.ImportedNodes, 0) + }) + t.Run("peerings w filter", func(t *testing.T) { - nodes := doRequest(t, "Node.PeerName == foo") + nodes := doRequest(t, "Node.PeerName == foo", false) require.Len(t, nodes.Nodes, 0) require.Len(t, nodes.ImportedNodes, 0) - nodes2 := doRequest(t, "Node.PeerName == peer1") + nodes2 := doRequest(t, "Node.PeerName == peer1", false) require.Len(t, nodes2.Nodes, 0) require.Len(t, nodes2.ImportedNodes, 1) }) @@ -2375,14 +2387,12 @@ func TestInternal_ServiceTopology_ACL(t *testing.T) { } t.Parallel() - dir1, s1 := testServerWithConfig(t, func(c *Config) { + _, s1 := testServerWithConfig(t, func(c *Config) { c.PrimaryDatacenter = "dc1" c.ACLsEnabled = true c.ACLInitialManagementToken = TestDefaultInitialManagementToken c.ACLResolverSettings.ACLDefaultPolicy = "deny" }) - defer os.RemoveAll(dir1) - defer s1.Shutdown() testrpc.WaitForLeader(t, s1.RPC, "dc1") @@ -2464,6 +2474,40 @@ service "web" { policy = "read" } }) } +// Tests that default intention deny policy overrides the ACL allow policy. +// More comprehensive tests are done at the state store so this is minimal +// coverage to be confident that the override happens. +func TestInternal_ServiceTopology_DefaultIntentionPolicy(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + _, s1 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = TestDefaultInitialManagementToken + c.ACLResolverSettings.ACLDefaultPolicy = "allow" + c.DefaultIntentionPolicy = "deny" + }) + + testrpc.WaitForLeader(t, s1.RPC, "dc1") + codec := rpcClient(t, s1) + + registerTestTopologyEntries(t, codec, TestDefaultInitialManagementToken) + + args := structs.ServiceSpecificRequest{ + Datacenter: "dc1", + ServiceName: "redis", + QueryOptions: structs.QueryOptions{Token: TestDefaultInitialManagementToken}, + } + var out structs.IndexedServiceTopology + require.NoError(t, msgpackrpc.CallWithCodec(codec, "Internal.ServiceTopology", &args, &out)) + + webSN := structs.NewServiceName("web", acl.DefaultEnterpriseMeta()) + require.False(t, out.ServiceTopology.DownstreamDecisions[webSN.String()].DefaultAllow) +} + func TestInternal_IntentionUpstreams(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") diff --git a/agent/consul/kvs_endpoint.go b/agent/consul/kvs_endpoint.go index 65dc2cd56d40..bfad9fa1932a 100644 --- a/agent/consul/kvs_endpoint.go +++ b/agent/consul/kvs_endpoint.go @@ -42,7 +42,8 @@ func kvsPreApply(logger hclog.Logger, srv *Server, authz resolver.Result, op api return false, fmt.Errorf("Must provide key") } - // Apply the ACL policy if any. + // Apply the ACL policy if any, and validate operation. + // enumcover:api.KVOp switch op { case api.KVDeleteTree: var authzContext acl.AuthorizerContext @@ -66,13 +67,15 @@ func kvsPreApply(logger hclog.Logger, srv *Server, authz resolver.Result, op api return false, err } - default: + case api.KVCheckNotExists, api.KVUnlock, api.KVLock, api.KVCAS, api.KVDeleteCAS, api.KVDelete, api.KVSet: var authzContext acl.AuthorizerContext dirEnt.FillAuthzContext(&authzContext) if err := authz.ToAllowAuthorizer().KeyWriteAllowed(dirEnt.Key, &authzContext); err != nil { return false, err } + default: + return false, fmt.Errorf("unknown KV operation: %s", op) } // If this is a lock, we must check for a lock-delay. Since lock-delay diff --git a/agent/consul/leader.go b/agent/consul/leader.go index fcbf794541f3..8b0db34b2356 100644 --- a/agent/consul/leader.go +++ b/agent/consul/leader.go @@ -7,7 +7,6 @@ import ( "context" "fmt" "net" - "reflect" "strconv" "strings" "sync" @@ -16,12 +15,13 @@ import ( "github.com/armon/go-metrics" "github.com/armon/go-metrics/prometheus" + "golang.org/x/time/rate" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-uuid" "github.com/hashicorp/go-version" "github.com/hashicorp/raft" "github.com/hashicorp/serf/serf" - "golang.org/x/time/rate" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/metadata" @@ -30,7 +30,6 @@ import ( "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/logging" - "github.com/hashicorp/consul/types" ) var LeaderSummaries = []prometheus.SummaryDefinition{ @@ -566,6 +565,87 @@ func (s *Server) initializeManagementToken(name, secretID string) error { return nil } +func (s *Server) upsertManagementToken(name, secretID string) error { + state := s.fsm.State() + if _, err := uuid.ParseUUID(secretID); err != nil { + s.logger.Warn("Configuring a non-UUID management token is deprecated") + } + + _, token, err := state.ACLTokenGetBySecret(nil, secretID, nil) + if err != nil { + return fmt.Errorf("failed to get %s: %v", name, err) + } + + if token != nil { + return nil + } + + accessor, err := lib.GenerateUUID(s.checkTokenUUID) + if err != nil { + return fmt.Errorf("failed to generate the accessor ID for %s: %v", name, err) + } + + newToken := structs.ACLToken{ + AccessorID: accessor, + SecretID: secretID, + Description: name, + Policies: []structs.ACLTokenPolicyLink{ + { + ID: structs.ACLPolicyGlobalManagementID, + }, + }, + CreateTime: time.Now(), + Local: false, + EnterpriseMeta: *structs.DefaultEnterpriseMetaInDefaultPartition(), + } + + newToken.SetHash(true) + + req := structs.ACLTokenBatchSetRequest{ + Tokens: structs.ACLTokens{&newToken}, + CAS: false, + } + if _, err := s.raftApply(structs.ACLTokenSetRequestType, &req); err != nil { + return fmt.Errorf("failed to create %s: %v", name, err) + } + + s.logger.Info("Created ACL token", "description", name) + + return nil +} + +func (s *Server) deleteManagementToken(secretId string) error { + state := s.fsm.State() + + // Fetch the token to get its accessor ID and to verify that it's a management token + _, token, err := state.ACLTokenGetBySecret(nil, secretId, nil) + if err != nil { + return fmt.Errorf("failed to get management token: %v", err) + } + + if token == nil { + // token is already deleted + return nil + } + + accessorID := token.AccessorID + if len(token.Policies) != 1 && token.Policies[0].ID != structs.ACLPolicyGlobalManagementID { + return fmt.Errorf("failed to delete management token: not a management token") + } + + // Delete the token + req := structs.ACLTokenBatchDeleteRequest{ + TokenIDs: []string{accessorID}, + } + if _, err := s.raftApply(structs.ACLTokenDeleteRequestType, &req); err != nil { + return fmt.Errorf("failed to delete management token: %v", err) + } + + s.logger.Info("deleted ACL token", "description", token.Description) + + return nil +} + func (s *Server) insertAnonymousToken() error { state := s.fsm.State() _, token, err := state.ACLTokenGetBySecret(nil, anonymousToken, nil) @@ -944,13 +1024,21 @@ func (s *Server) reconcileReaped(known map[string]struct{}, nodeEntMeta *acl.Ent } // Attempt to reap this member - if err := s.handleReapMember(member, nodeEntMeta); err != nil { + if err := s.registrator.HandleReapMember(member, nodeEntMeta, s.removeConsulServer); err != nil { return err } } return nil } +// ConsulRegistrator is an interface that manages the catalog registration lifecycle of Consul servers from serf events. +type ConsulRegistrator interface { + HandleAliveMember(member serf.Member, nodeEntMeta *acl.EnterpriseMeta, joinServer func(m serf.Member, parts *metadata.Server) error) error + HandleFailedMember(member serf.Member, nodeEntMeta *acl.EnterpriseMeta) error + HandleLeftMember(member serf.Member, nodeEntMeta *acl.EnterpriseMeta, removeServerFunc func(m serf.Member) error) error + HandleReapMember(member serf.Member, nodeEntMeta *acl.EnterpriseMeta, removeServerFunc func(m serf.Member) error) error +} + // reconcileMember is used to do an async reconcile of a single // serf member func (s *Server) reconcileMember(member serf.Member) error { @@ -969,13 +1057,13 @@ func (s *Server) reconcileMember(member serf.Member) error { var err error switch member.Status { case serf.StatusAlive: - err = s.handleAliveMember(member, nodeEntMeta) + err = s.registrator.HandleAliveMember(member, nodeEntMeta, s.joinConsulServer) case serf.StatusFailed: - err = s.handleFailedMember(member, nodeEntMeta) + err = s.registrator.HandleFailedMember(member, nodeEntMeta) case serf.StatusLeft: - err = s.handleLeftMember(member, nodeEntMeta) + err = s.registrator.HandleLeftMember(member, nodeEntMeta, s.removeConsulServer) case StatusReap: - err = s.handleReapMember(member, nodeEntMeta) + err = s.registrator.HandleReapMember(member, nodeEntMeta, s.removeConsulServer) } if err != nil { s.logger.Error("failed to reconcile member", @@ -1006,254 +1094,6 @@ func (s *Server) shouldHandleMember(member serf.Member) bool { return false } -// handleAliveMember is used to ensure the node -// is registered, with a passing health check. -func (s *Server) handleAliveMember(member serf.Member, nodeEntMeta *acl.EnterpriseMeta) error { - if nodeEntMeta == nil { - nodeEntMeta = structs.NodeEnterpriseMetaInDefaultPartition() - } - - // Register consul service if a server - var service *structs.NodeService - if valid, parts := metadata.IsConsulServer(member); valid { - service = &structs.NodeService{ - ID: structs.ConsulServiceID, - Service: structs.ConsulServiceName, - Port: parts.Port, - Weights: &structs.Weights{ - Passing: 1, - Warning: 1, - }, - EnterpriseMeta: *nodeEntMeta, - Meta: map[string]string{ - // DEPRECATED - remove nonvoter in favor of read_replica in a future version of consul - "non_voter": strconv.FormatBool(member.Tags["nonvoter"] == "1"), - "read_replica": strconv.FormatBool(member.Tags["read_replica"] == "1"), - "raft_version": strconv.Itoa(parts.RaftVersion), - "serf_protocol_current": strconv.FormatUint(uint64(member.ProtocolCur), 10), - "serf_protocol_min": strconv.FormatUint(uint64(member.ProtocolMin), 10), - "serf_protocol_max": strconv.FormatUint(uint64(member.ProtocolMax), 10), - "version": parts.Build.String(), - }, - } - - if parts.ExternalGRPCPort > 0 { - service.Meta["grpc_port"] = strconv.Itoa(parts.ExternalGRPCPort) - } - if parts.ExternalGRPCTLSPort > 0 { - service.Meta["grpc_tls_port"] = strconv.Itoa(parts.ExternalGRPCTLSPort) - } - - // Attempt to join the consul server - if err := s.joinConsulServer(member, parts); err != nil { - return err - } - } - - // Check if the node exists - state := s.fsm.State() - _, node, err := state.GetNode(member.Name, nodeEntMeta, structs.DefaultPeerKeyword) - if err != nil { - return err - } - if node != nil && node.Address == member.Addr.String() { - // Check if the associated service is available - if service != nil { - match := false - _, services, err := state.NodeServices(nil, member.Name, nodeEntMeta, structs.DefaultPeerKeyword) - if err != nil { - return err - } - if services != nil { - for id, serv := range services.Services { - if id == service.ID { - // If metadata are different, be sure to update it - match = reflect.DeepEqual(serv.Meta, service.Meta) - } - } - } - if !match { - goto AFTER_CHECK - } - } - - // Check if the serfCheck is in the passing state - _, checks, err := state.NodeChecks(nil, member.Name, nodeEntMeta, structs.DefaultPeerKeyword) - if err != nil { - return err - } - for _, check := range checks { - if check.CheckID == structs.SerfCheckID && check.Status == api.HealthPassing { - return nil - } - } - } -AFTER_CHECK: - s.logger.Info("member joined, marking health alive", - "member", member.Name, - "partition", getSerfMemberEnterpriseMeta(member).PartitionOrDefault(), - ) - - // Get consul version from serf member - // add this as node meta in catalog register request - buildVersion, err := metadata.Build(&member) - if err != nil { - return err - } - - // Register with the catalog. - req := structs.RegisterRequest{ - Datacenter: s.config.Datacenter, - Node: member.Name, - ID: types.NodeID(member.Tags["id"]), - Address: member.Addr.String(), - Service: service, - Check: &structs.HealthCheck{ - Node: member.Name, - CheckID: structs.SerfCheckID, - Name: structs.SerfCheckName, - Status: api.HealthPassing, - Output: structs.SerfCheckAliveOutput, - }, - EnterpriseMeta: *nodeEntMeta, - NodeMeta: map[string]string{ - structs.MetaConsulVersion: buildVersion.String(), - }, - } - if node != nil { - req.TaggedAddresses = node.TaggedAddresses - req.NodeMeta = node.Meta - } - - _, err = s.raftApply(structs.RegisterRequestType, &req) - return err -} - -// handleFailedMember is used to mark the node's status -// as being critical, along with all checks as unknown. -func (s *Server) handleFailedMember(member serf.Member, nodeEntMeta *acl.EnterpriseMeta) error { - if nodeEntMeta == nil { - nodeEntMeta = structs.NodeEnterpriseMetaInDefaultPartition() - } - - // Check if the node exists - state := s.fsm.State() - _, node, err := state.GetNode(member.Name, nodeEntMeta, structs.DefaultPeerKeyword) - if err != nil { - return err - } - - if node == nil { - s.logger.Info("ignoring failed event for member because it does not exist in the catalog", - "member", member.Name, - "partition", getSerfMemberEnterpriseMeta(member).PartitionOrDefault(), - ) - return nil - } - - if node.Address == member.Addr.String() { - // Check if the serfCheck is in the critical state - _, checks, err := state.NodeChecks(nil, member.Name, nodeEntMeta, structs.DefaultPeerKeyword) - if err != nil { - return err - } - for _, check := range checks { - if check.CheckID == structs.SerfCheckID && check.Status == api.HealthCritical { - return nil - } - } - } - s.logger.Info("member failed, marking health critical", - "member", member.Name, - "partition", getSerfMemberEnterpriseMeta(member).PartitionOrDefault(), - ) - - // Register with the catalog - req := structs.RegisterRequest{ - Datacenter: s.config.Datacenter, - Node: member.Name, - EnterpriseMeta: *nodeEntMeta, - ID: types.NodeID(member.Tags["id"]), - Address: member.Addr.String(), - Check: &structs.HealthCheck{ - Node: member.Name, - CheckID: structs.SerfCheckID, - Name: structs.SerfCheckName, - Status: api.HealthCritical, - Output: structs.SerfCheckFailedOutput, - }, - - // If there's existing information about the node, do not - // clobber it. - SkipNodeUpdate: true, - } - _, err = s.raftApply(structs.RegisterRequestType, &req) - return err -} - -// handleLeftMember is used to handle members that gracefully -// left. They are deregistered if necessary. -func (s *Server) handleLeftMember(member serf.Member, nodeEntMeta *acl.EnterpriseMeta) error { - return s.handleDeregisterMember("left", member, nodeEntMeta) -} - -// handleReapMember is used to handle members that have been -// reaped after a prolonged failure. They are deregistered. -func (s *Server) handleReapMember(member serf.Member, nodeEntMeta *acl.EnterpriseMeta) error { - return s.handleDeregisterMember("reaped", member, nodeEntMeta) -} - -// handleDeregisterMember is used to deregister a member of a given reason -func (s *Server) handleDeregisterMember(reason string, member serf.Member, nodeEntMeta *acl.EnterpriseMeta) error { - if nodeEntMeta == nil { - nodeEntMeta = structs.NodeEnterpriseMetaInDefaultPartition() - } - - // Do not deregister ourself. This can only happen if the current leader - // is leaving. Instead, we should allow a follower to take-over and - // deregister us later. - // - // TODO(partitions): check partitions here too? server names should be unique in general though - if strings.EqualFold(member.Name, s.config.NodeName) { - s.logger.Warn("deregistering self should be done by follower", - "name", s.config.NodeName, - "partition", getSerfMemberEnterpriseMeta(member).PartitionOrDefault(), - ) - return nil - } - - // Remove from Raft peers if this was a server - if valid, _ := metadata.IsConsulServer(member); valid { - if err := s.removeConsulServer(member); err != nil { - return err - } - } - - // Check if the node does not exist - state := s.fsm.State() - _, node, err := state.GetNode(member.Name, nodeEntMeta, structs.DefaultPeerKeyword) - if err != nil { - return err - } - if node == nil { - return nil - } - - // Deregister the node - s.logger.Info("deregistering member", - "member", member.Name, - "partition", getSerfMemberEnterpriseMeta(member).PartitionOrDefault(), - "reason", reason, - ) - req := structs.DeregisterRequest{ - Datacenter: s.config.Datacenter, - Node: member.Name, - EnterpriseMeta: *nodeEntMeta, - } - _, err = s.raftApply(structs.DeregisterRequestType, &req) - return err -} - // joinConsulServer is used to try to join another consul server func (s *Server) joinConsulServer(m serf.Member, parts *metadata.Server) error { // Check for possibility of multiple bootstrap nodes diff --git a/agent/consul/leader_ce_test.go b/agent/consul/leader_ce_test.go index 8988adb9f778..367a9fbcae83 100644 --- a/agent/consul/leader_ce_test.go +++ b/agent/consul/leader_ce_test.go @@ -5,7 +5,9 @@ package consul -import libserf "github.com/hashicorp/consul/lib/serf" +import ( + "github.com/hashicorp/consul/internal/gossip/libserf" +) func updateSerfTags(s *Server, key, value string) { libserf.UpdateTag(s.serfLAN, key, value) diff --git a/agent/consul/leader_connect_ca.go b/agent/consul/leader_connect_ca.go index 92cdf40a6abd..ee6562912fe5 100644 --- a/agent/consul/leader_connect_ca.go +++ b/agent/consul/leader_connect_ca.go @@ -14,9 +14,10 @@ import ( "sync" "time" + "golang.org/x/time/rate" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-uuid" - "golang.org/x/time/rate" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/connect" @@ -1455,11 +1456,6 @@ func (c *CAManager) AuthorizeAndSignCertificate(csr *x509.CertificateRequest, au return nil, connect.InvalidCSRError("SPIFFE ID in CSR from a different datacenter: %s, "+ "we are %s", v.Datacenter, dc) } - case *connect.SpiffeIDWorkloadIdentity: - v.GetEnterpriseMeta().FillAuthzContext(&authzContext) - if err := allow.IdentityWriteAllowed(v.WorkloadIdentity, &authzContext); err != nil { - return nil, err - } case *connect.SpiffeIDAgent: v.GetEnterpriseMeta().FillAuthzContext(&authzContext) if err := allow.NodeWriteAllowed(v.Agent, &authzContext); err != nil { @@ -1520,7 +1516,6 @@ func (c *CAManager) SignCertificate(csr *x509.CertificateRequest, spiffeID conne agentID, isAgent := spiffeID.(*connect.SpiffeIDAgent) serverID, isServer := spiffeID.(*connect.SpiffeIDServer) mgwID, isMeshGateway := spiffeID.(*connect.SpiffeIDMeshGateway) - wID, isWorkloadIdentity := spiffeID.(*connect.SpiffeIDWorkloadIdentity) var entMeta acl.EnterpriseMeta switch { @@ -1530,12 +1525,6 @@ func (c *CAManager) SignCertificate(csr *x509.CertificateRequest, spiffeID conne "we are %s", serviceID.Host, signingID.Host()) } entMeta.Merge(serviceID.GetEnterpriseMeta()) - case isWorkloadIdentity: - if !signingID.CanSign(spiffeID) { - return nil, connect.InvalidCSRError("SPIFFE ID in CSR from a different trust domain: %s, "+ - "we are %s", wID.TrustDomain, signingID.Host()) - } - entMeta.Merge(wID.GetEnterpriseMeta()) case isMeshGateway: if !signingID.CanSign(spiffeID) { return nil, connect.InvalidCSRError("SPIFFE ID in CSR from a different trust domain: %s, "+ @@ -1658,9 +1647,6 @@ func (c *CAManager) SignCertificate(csr *x509.CertificateRequest, spiffeID conne case isService: reply.Service = serviceID.Service reply.ServiceURI = cert.URIs[0].String() - case isWorkloadIdentity: - reply.WorkloadIdentity = wID.WorkloadIdentity - reply.WorkloadIdentityURI = cert.URIs[0].String() case isMeshGateway: reply.Kind = structs.ServiceKindMeshGateway reply.KindURI = cert.URIs[0].String() diff --git a/agent/consul/leader_connect_ca_test.go b/agent/consul/leader_connect_ca_test.go index e372c010a706..4560e97380c4 100644 --- a/agent/consul/leader_connect_ca_test.go +++ b/agent/consul/leader_connect_ca_test.go @@ -19,13 +19,14 @@ import ( "testing" "time" - msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc" - "github.com/hashicorp/consul-net-rpc/net/rpc" - vaultapi "github.com/hashicorp/vault/api" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" + msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc" + "github.com/hashicorp/consul-net-rpc/net/rpc" + vaultapi "github.com/hashicorp/vault/api" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/connect/ca" @@ -566,7 +567,7 @@ func TestCAManager_Initialize_Logging(t *testing.T) { deps := newDefaultDeps(t, conf1) deps.Logger = logger - s1, err := NewServer(conf1, deps, grpc.NewServer(), nil, logger, nil) + s1, err := NewServer(conf1, deps, grpc.NewServer(), nil, logger) require.NoError(t, err) defer s1.Shutdown() testrpc.WaitForLeader(t, s1.RPC, "dc1") @@ -1317,12 +1318,6 @@ func TestCAManager_AuthorizeAndSignCertificate(t *testing.T) { Host: "test-host", Partition: "test-partition", }.URI() - identityURL := connect.SpiffeIDWorkloadIdentity{ - TrustDomain: "test-trust-domain", - Partition: "test-partition", - Namespace: "test-namespace", - WorkloadIdentity: "test-workload-identity", - }.URI() tests := []struct { name string @@ -1418,15 +1413,6 @@ func TestCAManager_AuthorizeAndSignCertificate(t *testing.T) { } }, }, - { - name: "err_identity_write_not_allowed", - expectErr: "Permission denied", - getCSR: func() *x509.CertificateRequest { - return &x509.CertificateRequest{ - URIs: []*url.URL{identityURL}, - } - }, - }, } for _, tc := range tests { diff --git a/agent/consul/leader_federation_state_ae.go b/agent/consul/leader_federation_state_ae.go index 870dc5460e2b..a658166edd37 100644 --- a/agent/consul/leader_federation_state_ae.go +++ b/agent/consul/leader_federation_state_ae.go @@ -121,7 +121,7 @@ func (s *Server) updateOurFederationState(curr *structs.FederationState) error { if s.config.Datacenter == s.config.PrimaryDatacenter { // We are the primary, so we can't do an RPC as we don't have a replication token. - _, err := s.leaderRaftApply("FederationState.Apply", structs.FederationStateRequestType, args) + _, err := s.leaderRaftApply("FederationState.Apply", structs.FederationStateRequestType | structs.IgnoreUnknownTypeFlag, args) if err != nil { return err } @@ -226,7 +226,7 @@ func (s *Server) pruneStaleFederationStates() error { Datacenter: dc, }, } - _, err := s.leaderRaftApply("FederationState.Delete", structs.FederationStateRequestType, &req) + _, err := s.leaderRaftApply("FederationState.Delete", structs.FederationStateRequestType | structs.IgnoreUnknownTypeFlag, &req) if err != nil { return fmt.Errorf("Failed to delete federation state %s: %v", dc, err) diff --git a/agent/consul/leader_peering_test.go b/agent/consul/leader_peering_test.go index 8db496273d28..ae5d2ae83e81 100644 --- a/agent/consul/leader_peering_test.go +++ b/agent/consul/leader_peering_test.go @@ -1426,7 +1426,7 @@ func TestLeader_PeeringMetrics_emitPeeringMetrics(t *testing.T) { require.NoError(t, s2.fsm.State().PeeringWrite(lastIdx, &pbpeering.PeeringWriteRequest{Peering: p2})) // connect the stream - mst1, err := s2.peeringServer.Tracker.Connected(s2PeerID1) + mst1, err := s2.peerStreamServer.Tracker.Connected(s2PeerID1) require.NoError(t, err) // mimic tracking exported services @@ -1437,7 +1437,7 @@ func TestLeader_PeeringMetrics_emitPeeringMetrics(t *testing.T) { }) // connect the stream - mst2, err := s2.peeringServer.Tracker.Connected(s2PeerID2) + mst2, err := s2.peerStreamServer.Tracker.Connected(s2PeerID2) require.NoError(t, err) // mimic tracking exported services diff --git a/agent/consul/leader_registrator_v1.go b/agent/consul/leader_registrator_v1.go new file mode 100644 index 000000000000..6c131a44d9b6 --- /dev/null +++ b/agent/consul/leader_registrator_v1.go @@ -0,0 +1,279 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package consul + +import ( + "reflect" + "strconv" + "strings" + + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/serf/serf" + + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/agent/consul/fsm" + "github.com/hashicorp/consul/agent/metadata" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/types" +) + +var _ ConsulRegistrator = (*V1ConsulRegistrator)(nil) + +type V1ConsulRegistrator struct { + Datacenter string + FSM *fsm.FSM + Logger hclog.Logger + NodeName string + + RaftApplyFunc func(t structs.MessageType, msg any) (any, error) +} + +// HandleAliveMember is used to ensure the node +// is registered, with a passing health check. +func (r V1ConsulRegistrator) HandleAliveMember(member serf.Member, nodeEntMeta *acl.EnterpriseMeta, joinServer func(m serf.Member, parts *metadata.Server) error) error { + if nodeEntMeta == nil { + nodeEntMeta = structs.NodeEnterpriseMetaInDefaultPartition() + } + + // Register consul service if a server + var service *structs.NodeService + if valid, parts := metadata.IsConsulServer(member); valid { + service = &structs.NodeService{ + ID: structs.ConsulServiceID, + Service: structs.ConsulServiceName, + Port: parts.Port, + Weights: &structs.Weights{ + Passing: 1, + Warning: 1, + }, + EnterpriseMeta: *nodeEntMeta, + Meta: map[string]string{ + // DEPRECATED - remove nonvoter in favor of read_replica in a future version of consul + "non_voter": strconv.FormatBool(member.Tags["nonvoter"] == "1"), + "read_replica": strconv.FormatBool(member.Tags["read_replica"] == "1"), + "raft_version": strconv.Itoa(parts.RaftVersion), + "serf_protocol_current": strconv.FormatUint(uint64(member.ProtocolCur), 10), + "serf_protocol_min": strconv.FormatUint(uint64(member.ProtocolMin), 10), + "serf_protocol_max": strconv.FormatUint(uint64(member.ProtocolMax), 10), + "version": parts.Build.String(), + }, + } + + if parts.ExternalGRPCPort > 0 { + service.Meta["grpc_port"] = strconv.Itoa(parts.ExternalGRPCPort) + } + if parts.ExternalGRPCTLSPort > 0 { + service.Meta["grpc_tls_port"] = strconv.Itoa(parts.ExternalGRPCTLSPort) + } + + // Attempt to join the consul server + if err := joinServer(member, parts); err != nil { + return err + } + } + + // Check if the node exists + state := r.FSM.State() + _, node, err := state.GetNode(member.Name, nodeEntMeta, structs.DefaultPeerKeyword) + if err != nil { + return err + } + if node != nil && node.Address == member.Addr.String() { + // Check if the associated service is available + if service != nil { + match := false + _, services, err := state.NodeServices(nil, member.Name, nodeEntMeta, structs.DefaultPeerKeyword) + if err != nil { + return err + } + if services != nil { + for id, serv := range services.Services { + if id == service.ID { + // If metadata are different, be sure to update it + match = reflect.DeepEqual(serv.Meta, service.Meta) + } + } + } + if !match { + goto AFTER_CHECK + } + } + + // Check if the serfCheck is in the passing state + _, checks, err := state.NodeChecks(nil, member.Name, nodeEntMeta, structs.DefaultPeerKeyword) + if err != nil { + return err + } + for _, check := range checks { + if check.CheckID == structs.SerfCheckID && check.Status == api.HealthPassing { + return nil + } + } + } +AFTER_CHECK: + r.Logger.Info("member joined, marking health alive", + "member", member.Name, + "partition", getSerfMemberEnterpriseMeta(member).PartitionOrDefault(), + ) + + // Get consul version from serf member + // add this as node meta in catalog register request + buildVersion, err := metadata.Build(&member) + if err != nil { + return err + } + + // Register with the catalog. + req := structs.RegisterRequest{ + Datacenter: r.Datacenter, + Node: member.Name, + ID: types.NodeID(member.Tags["id"]), + Address: member.Addr.String(), + Service: service, + Check: &structs.HealthCheck{ + Node: member.Name, + CheckID: structs.SerfCheckID, + Name: structs.SerfCheckName, + Status: api.HealthPassing, + Output: structs.SerfCheckAliveOutput, + }, + EnterpriseMeta: *nodeEntMeta, + NodeMeta: map[string]string{ + structs.MetaConsulVersion: buildVersion.String(), + }, + } + if node != nil { + req.TaggedAddresses = node.TaggedAddresses + req.NodeMeta = node.Meta + } + + _, err = r.RaftApplyFunc(structs.RegisterRequestType, &req) + return err +} + +// HandleFailedMember is used to mark the node's status +// as being critical, along with all checks as unknown. +func (r V1ConsulRegistrator) HandleFailedMember(member serf.Member, nodeEntMeta *acl.EnterpriseMeta) error { + if nodeEntMeta == nil { + nodeEntMeta = structs.NodeEnterpriseMetaInDefaultPartition() + } + + // Check if the node exists + state := r.FSM.State() + _, node, err := state.GetNode(member.Name, nodeEntMeta, structs.DefaultPeerKeyword) + if err != nil { + return err + } + + if node == nil { + r.Logger.Info("ignoring failed event for member because it does not exist in the catalog", + "member", member.Name, + "partition", getSerfMemberEnterpriseMeta(member).PartitionOrDefault(), + ) + return nil + } + + if node.Address == member.Addr.String() { + // Check if the serfCheck is in the critical state + _, checks, err := state.NodeChecks(nil, member.Name, nodeEntMeta, structs.DefaultPeerKeyword) + if err != nil { + return err + } + for _, check := range checks { + if check.CheckID == structs.SerfCheckID && check.Status == api.HealthCritical { + return nil + } + } + } + r.Logger.Info("member failed, marking health critical", + "member", member.Name, + "partition", getSerfMemberEnterpriseMeta(member).PartitionOrDefault(), + ) + + // Register with the catalog + req := structs.RegisterRequest{ + Datacenter: r.Datacenter, + Node: member.Name, + EnterpriseMeta: *nodeEntMeta, + ID: types.NodeID(member.Tags["id"]), + Address: member.Addr.String(), + Check: &structs.HealthCheck{ + Node: member.Name, + CheckID: structs.SerfCheckID, + Name: structs.SerfCheckName, + Status: api.HealthCritical, + Output: structs.SerfCheckFailedOutput, + }, + + // If there's existing information about the node, do not + // clobber it. + SkipNodeUpdate: true, + } + _, err = r.RaftApplyFunc(structs.RegisterRequestType, &req) + return err +} + +// HandleLeftMember is used to handle members that gracefully +// left. They are deregistered if necessary. +func (r V1ConsulRegistrator) HandleLeftMember(member serf.Member, nodeEntMeta *acl.EnterpriseMeta, removeServerFunc func(m serf.Member) error) error { + return r.handleDeregisterMember("left", member, nodeEntMeta, removeServerFunc) +} + +// HandleReapMember is used to handle members that have been +// reaped after a prolonged failure. They are deregistered. +func (r V1ConsulRegistrator) HandleReapMember(member serf.Member, nodeEntMeta *acl.EnterpriseMeta, removeServerFunc func(m serf.Member) error) error { + return r.handleDeregisterMember("reaped", member, nodeEntMeta, removeServerFunc) +} + +// handleDeregisterMember is used to deregister a member of a given reason +func (r V1ConsulRegistrator) handleDeregisterMember(reason string, member serf.Member, nodeEntMeta *acl.EnterpriseMeta, removeServerFunc func(m serf.Member) error) error { + if nodeEntMeta == nil { + nodeEntMeta = structs.NodeEnterpriseMetaInDefaultPartition() + } + + // Do not deregister ourself. This can only happen if the current leader + // is leaving. Instead, we should allow a follower to take-over and + // deregister us later. + // + // TODO(partitions): check partitions here too? server names should be unique in general though + if strings.EqualFold(member.Name, r.NodeName) { + r.Logger.Warn("deregistering self should be done by follower", + "name", r.NodeName, + "partition", getSerfMemberEnterpriseMeta(member).PartitionOrDefault(), + ) + return nil + } + + // Remove from Raft peers if this was a server + if valid, _ := metadata.IsConsulServer(member); valid { + if err := removeServerFunc(member); err != nil { + return err + } + } + + // Check if the node does not exist + state := r.FSM.State() + _, node, err := state.GetNode(member.Name, nodeEntMeta, structs.DefaultPeerKeyword) + if err != nil { + return err + } + if node == nil { + return nil + } + + // Deregister the node + r.Logger.Info("deregistering member", + "member", member.Name, + "partition", getSerfMemberEnterpriseMeta(member).PartitionOrDefault(), + "reason", reason, + ) + req := structs.DeregisterRequest{ + Datacenter: r.Datacenter, + Node: member.Name, + EnterpriseMeta: *nodeEntMeta, + } + _, err = r.RaftApplyFunc(structs.DeregisterRequestType, &req) + return err +} diff --git a/agent/consul/leader_registrator_v1_test.go b/agent/consul/leader_registrator_v1_test.go new file mode 100644 index 000000000000..276e3b7c8ed8 --- /dev/null +++ b/agent/consul/leader_registrator_v1_test.go @@ -0,0 +1,887 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package consul + +import ( + "context" + "os" + "strconv" + "strings" + "testing" + "time" + + "github.com/hashicorp/serf/serf" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/freeport" + "github.com/hashicorp/consul/sdk/testutil/retry" + "github.com/hashicorp/consul/testrpc" +) + +func TestLeader_RegisterMember(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + dir1, s1 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "deny" + }) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + dir2, c1 := testClient(t) + defer os.RemoveAll(dir2) + defer c1.Shutdown() + + // Try to join + joinLAN(t, c1, s1) + + testrpc.WaitForLeader(t, s1.RPC, "dc1") + + // Client should be registered + state := s1.fsm.State() + retry.Run(t, func(r *retry.R) { + _, node, err := state.GetNode(c1.config.NodeName, nil, "") + if err != nil { + r.Fatalf("err: %v", err) + } + if node == nil { + r.Fatal("client not registered") + } + }) + + // Should have a check + _, checks, err := state.NodeChecks(nil, c1.config.NodeName, nil, "") + if err != nil { + t.Fatalf("err: %v", err) + } + if len(checks) != 1 { + t.Fatalf("client missing check") + } + if checks[0].CheckID != structs.SerfCheckID { + t.Fatalf("bad check: %v", checks[0]) + } + if checks[0].Name != structs.SerfCheckName { + t.Fatalf("bad check: %v", checks[0]) + } + if checks[0].Status != api.HealthPassing { + t.Fatalf("bad check: %v", checks[0]) + } + + // Server should be registered + retry.Run(t, func(r *retry.R) { + _, node, err := state.GetNode(s1.config.NodeName, nil, "") + if err != nil { + r.Fatalf("err: %v", err) + } + if node == nil { + r.Fatalf("server not registered") + } + }) + + // Service should be registered + _, services, err := state.NodeServices(nil, s1.config.NodeName, nil, "") + if err != nil { + t.Fatalf("err: %v", err) + } + if _, ok := services.Services["consul"]; !ok { + t.Fatalf("consul service not registered: %v", services) + } +} + +func TestLeader_FailedMember(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + dir1, s1 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "deny" + }) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + dir2, c1 := testClient(t) + defer os.RemoveAll(dir2) + defer c1.Shutdown() + + testrpc.WaitForLeader(t, s1.RPC, "dc1") + + // Try to join + joinLAN(t, c1, s1) + + // Fail the member + c1.Shutdown() + + // Should be registered + state := s1.fsm.State() + retry.Run(t, func(r *retry.R) { + _, node, err := state.GetNode(c1.config.NodeName, nil, "") + if err != nil { + r.Fatalf("err: %v", err) + } + if node == nil { + r.Fatal("client not registered") + } + }) + + // Should have a check + _, checks, err := state.NodeChecks(nil, c1.config.NodeName, nil, "") + if err != nil { + t.Fatalf("err: %v", err) + } + if len(checks) != 1 { + t.Fatalf("client missing check") + } + if checks[0].CheckID != structs.SerfCheckID { + t.Fatalf("bad check: %v", checks[0]) + } + if checks[0].Name != structs.SerfCheckName { + t.Fatalf("bad check: %v", checks[0]) + } + + retry.Run(t, func(r *retry.R) { + _, checks, err = state.NodeChecks(nil, c1.config.NodeName, nil, "") + if err != nil { + r.Fatalf("err: %v", err) + } + if len(checks) != 1 { + r.Fatalf("client missing check") + } + if got, want := checks[0].Status, api.HealthCritical; got != want { + r.Fatalf("got status %q want %q", got, want) + } + }) +} + +func TestLeader_LeftMember(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + dir1, s1 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "deny" + }) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + dir2, c1 := testClient(t) + defer os.RemoveAll(dir2) + defer c1.Shutdown() + + // Try to join + joinLAN(t, c1, s1) + + state := s1.fsm.State() + + // Should be registered + retry.Run(t, func(r *retry.R) { + _, node, err := state.GetNode(c1.config.NodeName, nil, "") + require.NoError(r, err) + require.NotNil(r, node, "client not registered") + }) + + // Node should leave + c1.Leave() + c1.Shutdown() + + // Should be deregistered + retry.Run(t, func(r *retry.R) { + _, node, err := state.GetNode(c1.config.NodeName, nil, "") + require.NoError(r, err) + require.Nil(r, node, "client still registered") + }) +} + +func TestLeader_ReapMember(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + dir1, s1 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "deny" + }) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + dir2, c1 := testClient(t) + defer os.RemoveAll(dir2) + defer c1.Shutdown() + + // Try to join + joinLAN(t, c1, s1) + + state := s1.fsm.State() + + // Should be registered + retry.Run(t, func(r *retry.R) { + _, node, err := state.GetNode(c1.config.NodeName, nil, "") + require.NoError(r, err) + require.NotNil(r, node, "client not registered") + }) + + // Simulate a node reaping + mems := s1.LANMembersInAgentPartition() + var c1mem serf.Member + for _, m := range mems { + if m.Name == c1.config.NodeName { + c1mem = m + c1mem.Status = StatusReap + break + } + } + s1.reconcileCh <- c1mem + + // Should be deregistered; we have to poll quickly here because + // anti-entropy will put it back. + reaped := false + for start := time.Now(); time.Since(start) < 5*time.Second; { + _, node, err := state.GetNode(c1.config.NodeName, nil, "") + require.NoError(t, err) + if node == nil { + reaped = true + break + } + } + if !reaped { + t.Fatalf("client should not be registered") + } +} + +func TestLeader_ReapOrLeftMember_IgnoreSelf(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + run := func(t *testing.T, status serf.MemberStatus, nameFn func(string) string) { + t.Parallel() + dir1, s1 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "deny" + }) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + nodeName := s1.config.NodeName + if nameFn != nil { + nodeName = nameFn(nodeName) + } + + state := s1.fsm.State() + + // Should be registered + retry.Run(t, func(r *retry.R) { + _, node, err := state.GetNode(nodeName, nil, "") + require.NoError(r, err) + require.NotNil(r, node, "server not registered") + }) + + // Simulate THIS node reaping or leaving + mems := s1.LANMembersInAgentPartition() + var s1mem serf.Member + for _, m := range mems { + if strings.EqualFold(m.Name, nodeName) { + s1mem = m + s1mem.Status = status + s1mem.Name = nodeName + break + } + } + s1.reconcileCh <- s1mem + + // Should NOT be deregistered; we have to poll quickly here because + // anti-entropy will put it back if it did get deleted. + reaped := false + for start := time.Now(); time.Since(start) < 5*time.Second; { + _, node, err := state.GetNode(nodeName, nil, "") + require.NoError(t, err) + if node == nil { + reaped = true + break + } + } + if reaped { + t.Fatalf("server should still be registered") + } + } + + t.Run("original name", func(t *testing.T) { + t.Parallel() + t.Run("left", func(t *testing.T) { + run(t, serf.StatusLeft, nil) + }) + t.Run("reap", func(t *testing.T) { + run(t, StatusReap, nil) + }) + }) + + t.Run("uppercased name", func(t *testing.T) { + t.Parallel() + t.Run("left", func(t *testing.T) { + run(t, serf.StatusLeft, strings.ToUpper) + }) + t.Run("reap", func(t *testing.T) { + run(t, StatusReap, strings.ToUpper) + }) + }) +} + +func TestLeader_CheckServersMeta(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + t.Parallel() + + ports := freeport.GetN(t, 2) // s3 grpc, s3 grpc_tls + + dir1, s1 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "allow" + c.Bootstrap = true + }) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + dir2, s2 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "allow" + c.Bootstrap = false + }) + defer os.RemoveAll(dir2) + defer s2.Shutdown() + + dir3, s3 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "allow" + c.Bootstrap = false + c.GRPCPort = ports[0] + c.GRPCTLSPort = ports[1] + }) + defer os.RemoveAll(dir3) + defer s3.Shutdown() + + // Try to join + joinLAN(t, s1, s2) + joinLAN(t, s1, s3) + + testrpc.WaitForLeader(t, s1.RPC, "dc1") + testrpc.WaitForLeader(t, s2.RPC, "dc1") + testrpc.WaitForLeader(t, s3.RPC, "dc1") + state := s1.fsm.State() + + consulService := &structs.NodeService{ + ID: "consul", + Service: "consul", + } + // s3 should be registered + retry.Run(t, func(r *retry.R) { + _, service, err := state.NodeService(nil, s3.config.NodeName, "consul", &consulService.EnterpriseMeta, "") + if err != nil { + r.Fatalf("err: %v", err) + } + if service == nil { + r.Fatal("client not registered") + } + if service.Meta["non_voter"] != "false" { + r.Fatalf("Expected to be non_voter == false, was: %s", service.Meta["non_voter"]) + } + }) + + member := serf.Member{} + for _, m := range s1.serfLAN.Members() { + if m.Name == s3.config.NodeName { + member = m + member.Tags = make(map[string]string) + for key, value := range m.Tags { + member.Tags[key] = value + } + } + } + if member.Name != s3.config.NodeName { + t.Fatal("could not find node in serf members") + } + versionToExpect := "19.7.9" + + retry.Run(t, func(r *retry.R) { + // DEPRECATED - remove nonvoter tag in favor of read_replica in a future version of consul + member.Tags["nonvoter"] = "1" + member.Tags["read_replica"] = "1" + member.Tags["build"] = versionToExpect + err := s1.registrator.HandleAliveMember(member, nil, s1.joinConsulServer) + if err != nil { + r.Fatalf("Unexpected error :%v", err) + } + _, service, err := state.NodeService(nil, s3.config.NodeName, "consul", &consulService.EnterpriseMeta, "") + if err != nil { + r.Fatalf("err: %v", err) + } + if service == nil { + r.Fatal("client not registered") + } + // DEPRECATED - remove non_voter in favor of read_replica in a future version of consul + if service.Meta["non_voter"] != "true" { + r.Fatalf("Expected to be non_voter == true, was: %s", service.Meta["non_voter"]) + } + if service.Meta["read_replica"] != "true" { + r.Fatalf("Expected to be read_replica == true, was: %s", service.Meta["non_voter"]) + } + newVersion := service.Meta["version"] + if newVersion != versionToExpect { + r.Fatalf("Expected version to be updated to %s, was %s", versionToExpect, newVersion) + } + grpcPort := service.Meta["grpc_port"] + if grpcPort != strconv.Itoa(ports[0]) { + r.Fatalf("Expected grpc port to be %d, was %s", ports[0], grpcPort) + } + grpcTLSPort := service.Meta["grpc_tls_port"] + if grpcTLSPort != strconv.Itoa(ports[1]) { + r.Fatalf("Expected grpc tls port to be %d, was %s", ports[1], grpcTLSPort) + } + }) +} + +func TestLeader_ReapServer(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + dir1, s1 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "allow" + c.Bootstrap = true + }) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + dir2, s2 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "allow" + c.Bootstrap = false + }) + defer os.RemoveAll(dir2) + defer s2.Shutdown() + + dir3, s3 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "allow" + c.Bootstrap = false + }) + defer os.RemoveAll(dir3) + defer s3.Shutdown() + + // Try to join + joinLAN(t, s1, s2) + joinLAN(t, s1, s3) + + testrpc.WaitForLeader(t, s1.RPC, "dc1") + testrpc.WaitForLeader(t, s2.RPC, "dc1") + testrpc.WaitForLeader(t, s3.RPC, "dc1") + state := s1.fsm.State() + + // s3 should be registered + retry.Run(t, func(r *retry.R) { + _, node, err := state.GetNode(s3.config.NodeName, nil, "") + if err != nil { + r.Fatalf("err: %v", err) + } + if node == nil { + r.Fatal("client not registered") + } + }) + + // call reconcileReaped with a map that does not contain s3 + knownMembers := make(map[string]struct{}) + knownMembers[s1.config.NodeName] = struct{}{} + knownMembers[s2.config.NodeName] = struct{}{} + + err := s1.reconcileReaped(knownMembers, nil) + + if err != nil { + t.Fatalf("Unexpected error :%v", err) + } + // s3 should be deregistered + retry.Run(t, func(r *retry.R) { + _, node, err := state.GetNode(s3.config.NodeName, nil, "") + if err != nil { + r.Fatalf("err: %v", err) + } + if node != nil { + r.Fatalf("server with id %v should not be registered", s3.config.NodeID) + } + }) + +} + +func TestLeader_Reconcile_ReapMember(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + dir1, s1 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "deny" + }) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + testrpc.WaitForLeader(t, s1.RPC, "dc1") + + // Register a non-existing member + dead := structs.RegisterRequest{ + Datacenter: s1.config.Datacenter, + Node: "no-longer-around", + Address: "127.1.1.1", + Check: &structs.HealthCheck{ + Node: "no-longer-around", + CheckID: structs.SerfCheckID, + Name: structs.SerfCheckName, + Status: api.HealthCritical, + }, + WriteRequest: structs.WriteRequest{ + Token: "root", + }, + } + var out struct{} + if err := s1.RPC(context.Background(), "Catalog.Register", &dead, &out); err != nil { + t.Fatalf("err: %v", err) + } + + // Force a reconciliation + if err := s1.reconcile(); err != nil { + t.Fatalf("err: %v", err) + } + + // Node should be gone + state := s1.fsm.State() + _, node, err := state.GetNode("no-longer-around", nil, "") + if err != nil { + t.Fatalf("err: %v", err) + } + if node != nil { + t.Fatalf("client registered") + } +} + +func TestLeader_Reconcile(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + dir1, s1 := testServerWithConfig(t, func(c *Config) { + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + c.ACLInitialManagementToken = "root" + c.ACLResolverSettings.ACLDefaultPolicy = "deny" + }) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + dir2, c1 := testClient(t) + defer os.RemoveAll(dir2) + defer c1.Shutdown() + + // Join before we have a leader, this should cause a reconcile! + joinLAN(t, c1, s1) + + // Should not be registered + state := s1.fsm.State() + _, node, err := state.GetNode(c1.config.NodeName, nil, "") + if err != nil { + t.Fatalf("err: %v", err) + } + if node != nil { + t.Fatalf("client registered") + } + + // Should be registered + retry.Run(t, func(r *retry.R) { + _, node, err := state.GetNode(c1.config.NodeName, nil, "") + if err != nil { + r.Fatalf("err: %v", err) + } + if node == nil { + r.Fatal("client not registered") + } + }) +} + +func TestLeader_Reconcile_Races(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + dir1, s1 := testServer(t) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + testrpc.WaitForLeader(t, s1.RPC, "dc1") + + dir2, c1 := testClient(t) + defer os.RemoveAll(dir2) + defer c1.Shutdown() + + joinLAN(t, c1, s1) + + // Wait for the server to reconcile the client and register it. + state := s1.fsm.State() + var nodeAddr string + retry.Run(t, func(r *retry.R) { + _, node, err := state.GetNode(c1.config.NodeName, nil, "") + if err != nil { + r.Fatalf("err: %v", err) + } + if node == nil { + r.Fatal("client not registered") + } + nodeAddr = node.Address + }) + + // Add in some metadata via the catalog (as if the agent synced it + // there). We also set the serfHealth check to failing so the reconcile + // will attempt to flip it back + req := structs.RegisterRequest{ + Datacenter: s1.config.Datacenter, + Node: c1.config.NodeName, + ID: c1.config.NodeID, + Address: nodeAddr, + NodeMeta: map[string]string{"hello": "world"}, + Check: &structs.HealthCheck{ + Node: c1.config.NodeName, + CheckID: structs.SerfCheckID, + Name: structs.SerfCheckName, + Status: api.HealthCritical, + Output: "", + }, + } + var out struct{} + if err := s1.RPC(context.Background(), "Catalog.Register", &req, &out); err != nil { + t.Fatalf("err: %v", err) + } + + // Force a reconcile and make sure the metadata stuck around. + if err := s1.reconcile(); err != nil { + t.Fatalf("err: %v", err) + } + _, node, err := state.GetNode(c1.config.NodeName, nil, "") + if err != nil { + t.Fatalf("err: %v", err) + } + if node == nil { + t.Fatalf("bad") + } + if hello, ok := node.Meta["hello"]; !ok || hello != "world" { + t.Fatalf("bad") + } + + // Fail the member and wait for the health to go critical. + c1.Shutdown() + retry.Run(t, func(r *retry.R) { + _, checks, err := state.NodeChecks(nil, c1.config.NodeName, nil, "") + if err != nil { + r.Fatalf("err: %v", err) + } + if len(checks) != 1 { + r.Fatalf("client missing check") + } + if got, want := checks[0].Status, api.HealthCritical; got != want { + r.Fatalf("got state %q want %q", got, want) + } + }) + + // Make sure the metadata didn't get clobbered. + _, node, err = state.GetNode(c1.config.NodeName, nil, "") + if err != nil { + t.Fatalf("err: %v", err) + } + if node == nil { + t.Fatalf("bad") + } + if hello, ok := node.Meta["hello"]; !ok || hello != "world" { + t.Fatalf("bad") + } +} + +func TestLeader_LeftServer(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + dir1, s1 := testServer(t) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + dir2, s2 := testServerDCBootstrap(t, "dc1", false) + defer os.RemoveAll(dir2) + defer s2.Shutdown() + + dir3, s3 := testServerDCBootstrap(t, "dc1", false) + defer os.RemoveAll(dir3) + defer s3.Shutdown() + + // Put s1 last so we don't trigger a leader election. + servers := []*Server{s2, s3, s1} + + // Try to join + joinLAN(t, s2, s1) + joinLAN(t, s3, s1) + for _, s := range servers { + retry.Run(t, func(r *retry.R) { r.Check(wantPeers(s, 3)) }) + } + + // Kill any server + servers[0].Shutdown() + + // Force remove the non-leader (transition to left state) + if err := servers[1].RemoveFailedNode(servers[0].config.NodeName, false, nil); err != nil { + t.Fatalf("err: %v", err) + } + + // Wait until the remaining servers show only 2 peers. + for _, s := range servers[1:] { + retry.Run(t, func(r *retry.R) { r.Check(wantPeers(s, 2)) }) + } + s1.Shutdown() +} + +func TestLeader_LeftLeader(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + dir1, s1 := testServer(t) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + dir2, s2 := testServerDCBootstrap(t, "dc1", false) + defer os.RemoveAll(dir2) + defer s2.Shutdown() + + dir3, s3 := testServerDCBootstrap(t, "dc1", false) + defer os.RemoveAll(dir3) + defer s3.Shutdown() + servers := []*Server{s1, s2, s3} + + // Try to join + joinLAN(t, s2, s1) + joinLAN(t, s3, s1) + + for _, s := range servers { + retry.Run(t, func(r *retry.R) { r.Check(wantPeers(s, 3)) }) + } + + // Kill the leader! + var leader *Server + for _, s := range servers { + if s.IsLeader() { + leader = s + break + } + } + if leader == nil { + t.Fatalf("Should have a leader") + } + if !leader.isReadyForConsistentReads() { + t.Fatalf("Expected leader to be ready for consistent reads ") + } + leader.Leave() + if leader.isReadyForConsistentReads() { + t.Fatalf("Expected consistent read state to be false ") + } + leader.Shutdown() + time.Sleep(100 * time.Millisecond) + + var remain *Server + for _, s := range servers { + if s == leader { + continue + } + remain = s + retry.Run(t, func(r *retry.R) { r.Check(wantPeers(s, 2)) }) + } + + // Verify the old leader is deregistered + state := remain.fsm.State() + retry.Run(t, func(r *retry.R) { + _, node, err := state.GetNode(leader.config.NodeName, nil, "") + if err != nil { + r.Fatalf("err: %v", err) + } + if node != nil { + r.Fatal("leader should be deregistered") + } + }) +} + +func TestLeader_MultiBootstrap(t *testing.T) { + t.Parallel() + dir1, s1 := testServer(t) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + dir2, s2 := testServer(t) + defer os.RemoveAll(dir2) + defer s2.Shutdown() + + servers := []*Server{s1, s2} + + // Try to join + joinLAN(t, s2, s1) + + for _, s := range servers { + retry.Run(t, func(r *retry.R) { + if got, want := len(s.serfLAN.Members()), 2; got != want { + r.Fatalf("got %d peers want %d", got, want) + } + }) + } + + // Ensure we don't have multiple raft peers + for _, s := range servers { + peers, _ := s.autopilot.NumVoters() + if peers != 1 { + t.Fatalf("should only have 1 raft peer!") + } + } +} diff --git a/agent/consul/leader_test.go b/agent/consul/leader_test.go index 7a4b63eb05ee..9709e391ebcf 100644 --- a/agent/consul/leader_test.go +++ b/agent/consul/leader_test.go @@ -10,893 +10,26 @@ import ( "fmt" "io" "os" - "strconv" "strings" "testing" "time" - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-uuid" - "github.com/hashicorp/serf/serf" - "github.com/stretchr/testify/require" - "google.golang.org/grpc" - - msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/structs" - tokenStore "github.com/hashicorp/consul/agent/token" - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/freeport" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" - "github.com/hashicorp/consul/testrpc" -) - -func TestLeader_RegisterMember(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - dir1, s1 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "deny" - }) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - dir2, c1 := testClient(t) - defer os.RemoveAll(dir2) - defer c1.Shutdown() - - // Try to join - joinLAN(t, c1, s1) - - testrpc.WaitForLeader(t, s1.RPC, "dc1") - - // Client should be registered - state := s1.fsm.State() - retry.Run(t, func(r *retry.R) { - _, node, err := state.GetNode(c1.config.NodeName, nil, "") - if err != nil { - r.Fatalf("err: %v", err) - } - if node == nil { - r.Fatal("client not registered") - } - }) - - // Should have a check - _, checks, err := state.NodeChecks(nil, c1.config.NodeName, nil, "") - if err != nil { - t.Fatalf("err: %v", err) - } - if len(checks) != 1 { - t.Fatalf("client missing check") - } - if checks[0].CheckID != structs.SerfCheckID { - t.Fatalf("bad check: %v", checks[0]) - } - if checks[0].Name != structs.SerfCheckName { - t.Fatalf("bad check: %v", checks[0]) - } - if checks[0].Status != api.HealthPassing { - t.Fatalf("bad check: %v", checks[0]) - } - - // Server should be registered - retry.Run(t, func(r *retry.R) { - _, node, err := state.GetNode(s1.config.NodeName, nil, "") - if err != nil { - r.Fatalf("err: %v", err) - } - if node == nil { - r.Fatalf("server not registered") - } - }) - - // Service should be registered - _, services, err := state.NodeServices(nil, s1.config.NodeName, nil, "") - if err != nil { - t.Fatalf("err: %v", err) - } - if _, ok := services.Services["consul"]; !ok { - t.Fatalf("consul service not registered: %v", services) - } -} - -func TestLeader_FailedMember(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - dir1, s1 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "deny" - }) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - dir2, c1 := testClient(t) - defer os.RemoveAll(dir2) - defer c1.Shutdown() - - testrpc.WaitForLeader(t, s1.RPC, "dc1") - - // Try to join - joinLAN(t, c1, s1) - - // Fail the member - c1.Shutdown() - - // Should be registered - state := s1.fsm.State() - retry.Run(t, func(r *retry.R) { - _, node, err := state.GetNode(c1.config.NodeName, nil, "") - if err != nil { - r.Fatalf("err: %v", err) - } - if node == nil { - r.Fatal("client not registered") - } - }) - - // Should have a check - _, checks, err := state.NodeChecks(nil, c1.config.NodeName, nil, "") - if err != nil { - t.Fatalf("err: %v", err) - } - if len(checks) != 1 { - t.Fatalf("client missing check") - } - if checks[0].CheckID != structs.SerfCheckID { - t.Fatalf("bad check: %v", checks[0]) - } - if checks[0].Name != structs.SerfCheckName { - t.Fatalf("bad check: %v", checks[0]) - } - - retry.Run(t, func(r *retry.R) { - _, checks, err = state.NodeChecks(nil, c1.config.NodeName, nil, "") - if err != nil { - r.Fatalf("err: %v", err) - } - if len(checks) != 1 { - r.Fatalf("client missing check") - } - if got, want := checks[0].Status, api.HealthCritical; got != want { - r.Fatalf("got status %q want %q", got, want) - } - }) -} - -func TestLeader_LeftMember(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - dir1, s1 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "deny" - }) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - dir2, c1 := testClient(t) - defer os.RemoveAll(dir2) - defer c1.Shutdown() - - // Try to join - joinLAN(t, c1, s1) - - state := s1.fsm.State() - - // Should be registered - retry.Run(t, func(r *retry.R) { - _, node, err := state.GetNode(c1.config.NodeName, nil, "") - require.NoError(r, err) - require.NotNil(r, node, "client not registered") - }) - - // Node should leave - c1.Leave() - c1.Shutdown() - - // Should be deregistered - retry.Run(t, func(r *retry.R) { - _, node, err := state.GetNode(c1.config.NodeName, nil, "") - require.NoError(r, err) - require.Nil(r, node, "client still registered") - }) -} - -func TestLeader_ReapMember(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - dir1, s1 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "deny" - }) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - dir2, c1 := testClient(t) - defer os.RemoveAll(dir2) - defer c1.Shutdown() - - // Try to join - joinLAN(t, c1, s1) - - state := s1.fsm.State() - - // Should be registered - retry.Run(t, func(r *retry.R) { - _, node, err := state.GetNode(c1.config.NodeName, nil, "") - require.NoError(r, err) - require.NotNil(r, node, "client not registered") - }) - - // Simulate a node reaping - mems := s1.LANMembersInAgentPartition() - var c1mem serf.Member - for _, m := range mems { - if m.Name == c1.config.NodeName { - c1mem = m - c1mem.Status = StatusReap - break - } - } - s1.reconcileCh <- c1mem - - // Should be deregistered; we have to poll quickly here because - // anti-entropy will put it back. - reaped := false - for start := time.Now(); time.Since(start) < 5*time.Second; { - _, node, err := state.GetNode(c1.config.NodeName, nil, "") - require.NoError(t, err) - if node == nil { - reaped = true - break - } - } - if !reaped { - t.Fatalf("client should not be registered") - } -} - -func TestLeader_ReapOrLeftMember_IgnoreSelf(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - - run := func(t *testing.T, status serf.MemberStatus, nameFn func(string) string) { - t.Parallel() - dir1, s1 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "deny" - }) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - nodeName := s1.config.NodeName - if nameFn != nil { - nodeName = nameFn(nodeName) - } - - state := s1.fsm.State() - - // Should be registered - retry.Run(t, func(r *retry.R) { - _, node, err := state.GetNode(nodeName, nil, "") - require.NoError(r, err) - require.NotNil(r, node, "server not registered") - }) - - // Simulate THIS node reaping or leaving - mems := s1.LANMembersInAgentPartition() - var s1mem serf.Member - for _, m := range mems { - if strings.EqualFold(m.Name, nodeName) { - s1mem = m - s1mem.Status = status - s1mem.Name = nodeName - break - } - } - s1.reconcileCh <- s1mem - - // Should NOT be deregistered; we have to poll quickly here because - // anti-entropy will put it back if it did get deleted. - reaped := false - for start := time.Now(); time.Since(start) < 5*time.Second; { - _, node, err := state.GetNode(nodeName, nil, "") - require.NoError(t, err) - if node == nil { - reaped = true - break - } - } - if reaped { - t.Fatalf("server should still be registered") - } - } - - t.Run("original name", func(t *testing.T) { - t.Parallel() - t.Run("left", func(t *testing.T) { - run(t, serf.StatusLeft, nil) - }) - t.Run("reap", func(t *testing.T) { - run(t, StatusReap, nil) - }) - }) - - t.Run("uppercased name", func(t *testing.T) { - t.Parallel() - t.Run("left", func(t *testing.T) { - run(t, serf.StatusLeft, strings.ToUpper) - }) - t.Run("reap", func(t *testing.T) { - run(t, StatusReap, strings.ToUpper) - }) - }) -} - -func TestLeader_CheckServersMeta(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - t.Parallel() - - ports := freeport.GetN(t, 2) // s3 grpc, s3 grpc_tls - - dir1, s1 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "allow" - c.Bootstrap = true - }) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - dir2, s2 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "allow" - c.Bootstrap = false - }) - defer os.RemoveAll(dir2) - defer s2.Shutdown() - - dir3, s3 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "allow" - c.Bootstrap = false - c.GRPCPort = ports[0] - c.GRPCTLSPort = ports[1] - }) - defer os.RemoveAll(dir3) - defer s3.Shutdown() - - // Try to join - joinLAN(t, s1, s2) - joinLAN(t, s1, s3) - - testrpc.WaitForLeader(t, s1.RPC, "dc1") - testrpc.WaitForLeader(t, s2.RPC, "dc1") - testrpc.WaitForLeader(t, s3.RPC, "dc1") - state := s1.fsm.State() - - consulService := &structs.NodeService{ - ID: "consul", - Service: "consul", - } - // s3 should be registered - retry.Run(t, func(r *retry.R) { - _, service, err := state.NodeService(nil, s3.config.NodeName, "consul", &consulService.EnterpriseMeta, "") - if err != nil { - r.Fatalf("err: %v", err) - } - if service == nil { - r.Fatal("client not registered") - } - if service.Meta["non_voter"] != "false" { - r.Fatalf("Expected to be non_voter == false, was: %s", service.Meta["non_voter"]) - } - }) - - member := serf.Member{} - for _, m := range s1.serfLAN.Members() { - if m.Name == s3.config.NodeName { - member = m - member.Tags = make(map[string]string) - for key, value := range m.Tags { - member.Tags[key] = value - } - } - } - if member.Name != s3.config.NodeName { - t.Fatal("could not find node in serf members") - } - versionToExpect := "19.7.9" - - retry.Run(t, func(r *retry.R) { - // DEPRECATED - remove nonvoter tag in favor of read_replica in a future version of consul - member.Tags["nonvoter"] = "1" - member.Tags["read_replica"] = "1" - member.Tags["build"] = versionToExpect - err := s1.handleAliveMember(member, nil) - if err != nil { - r.Fatalf("Unexpected error :%v", err) - } - _, service, err := state.NodeService(nil, s3.config.NodeName, "consul", &consulService.EnterpriseMeta, "") - if err != nil { - r.Fatalf("err: %v", err) - } - if service == nil { - r.Fatal("client not registered") - } - // DEPRECATED - remove non_voter in favor of read_replica in a future version of consul - if service.Meta["non_voter"] != "true" { - r.Fatalf("Expected to be non_voter == true, was: %s", service.Meta["non_voter"]) - } - if service.Meta["read_replica"] != "true" { - r.Fatalf("Expected to be read_replica == true, was: %s", service.Meta["non_voter"]) - } - newVersion := service.Meta["version"] - if newVersion != versionToExpect { - r.Fatalf("Expected version to be updated to %s, was %s", versionToExpect, newVersion) - } - grpcPort := service.Meta["grpc_port"] - if grpcPort != strconv.Itoa(ports[0]) { - r.Fatalf("Expected grpc port to be %d, was %s", ports[0], grpcPort) - } - grpcTLSPort := service.Meta["grpc_tls_port"] - if grpcTLSPort != strconv.Itoa(ports[1]) { - r.Fatalf("Expected grpc tls port to be %d, was %s", ports[1], grpcTLSPort) - } - }) -} - -func TestLeader_ReapServer(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - dir1, s1 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "allow" - c.Bootstrap = true - }) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - dir2, s2 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "allow" - c.Bootstrap = false - }) - defer os.RemoveAll(dir2) - defer s2.Shutdown() - - dir3, s3 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "allow" - c.Bootstrap = false - }) - defer os.RemoveAll(dir3) - defer s3.Shutdown() - - // Try to join - joinLAN(t, s1, s2) - joinLAN(t, s1, s3) - - testrpc.WaitForLeader(t, s1.RPC, "dc1") - testrpc.WaitForLeader(t, s2.RPC, "dc1") - testrpc.WaitForLeader(t, s3.RPC, "dc1") - state := s1.fsm.State() - - // s3 should be registered - retry.Run(t, func(r *retry.R) { - _, node, err := state.GetNode(s3.config.NodeName, nil, "") - if err != nil { - r.Fatalf("err: %v", err) - } - if node == nil { - r.Fatal("client not registered") - } - }) - - // call reconcileReaped with a map that does not contain s3 - knownMembers := make(map[string]struct{}) - knownMembers[s1.config.NodeName] = struct{}{} - knownMembers[s2.config.NodeName] = struct{}{} - - err := s1.reconcileReaped(knownMembers, nil) - - if err != nil { - t.Fatalf("Unexpected error :%v", err) - } - // s3 should be deregistered - retry.Run(t, func(r *retry.R) { - _, node, err := state.GetNode(s3.config.NodeName, nil, "") - if err != nil { - r.Fatalf("err: %v", err) - } - if node != nil { - r.Fatalf("server with id %v should not be registered", s3.config.NodeID) - } - }) - -} - -func TestLeader_Reconcile_ReapMember(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - dir1, s1 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "deny" - }) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - testrpc.WaitForLeader(t, s1.RPC, "dc1") - - // Register a non-existing member - dead := structs.RegisterRequest{ - Datacenter: s1.config.Datacenter, - Node: "no-longer-around", - Address: "127.1.1.1", - Check: &structs.HealthCheck{ - Node: "no-longer-around", - CheckID: structs.SerfCheckID, - Name: structs.SerfCheckName, - Status: api.HealthCritical, - }, - WriteRequest: structs.WriteRequest{ - Token: "root", - }, - } - var out struct{} - if err := s1.RPC(context.Background(), "Catalog.Register", &dead, &out); err != nil { - t.Fatalf("err: %v", err) - } - - // Force a reconciliation - if err := s1.reconcile(); err != nil { - t.Fatalf("err: %v", err) - } - - // Node should be gone - state := s1.fsm.State() - _, node, err := state.GetNode("no-longer-around", nil, "") - if err != nil { - t.Fatalf("err: %v", err) - } - if node != nil { - t.Fatalf("client registered") - } -} - -func TestLeader_Reconcile(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - dir1, s1 := testServerWithConfig(t, func(c *Config) { - c.PrimaryDatacenter = "dc1" - c.ACLsEnabled = true - c.ACLInitialManagementToken = "root" - c.ACLResolverSettings.ACLDefaultPolicy = "deny" - }) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - dir2, c1 := testClient(t) - defer os.RemoveAll(dir2) - defer c1.Shutdown() - - // Join before we have a leader, this should cause a reconcile! - joinLAN(t, c1, s1) - - // Should not be registered - state := s1.fsm.State() - _, node, err := state.GetNode(c1.config.NodeName, nil, "") - if err != nil { - t.Fatalf("err: %v", err) - } - if node != nil { - t.Fatalf("client registered") - } - - // Should be registered - retry.Run(t, func(r *retry.R) { - _, node, err := state.GetNode(c1.config.NodeName, nil, "") - if err != nil { - r.Fatalf("err: %v", err) - } - if node == nil { - r.Fatal("client not registered") - } - }) -} - -func TestLeader_Reconcile_Races(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - dir1, s1 := testServer(t) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - testrpc.WaitForLeader(t, s1.RPC, "dc1") - - dir2, c1 := testClient(t) - defer os.RemoveAll(dir2) - defer c1.Shutdown() - - joinLAN(t, c1, s1) - - // Wait for the server to reconcile the client and register it. - state := s1.fsm.State() - var nodeAddr string - retry.Run(t, func(r *retry.R) { - _, node, err := state.GetNode(c1.config.NodeName, nil, "") - if err != nil { - r.Fatalf("err: %v", err) - } - if node == nil { - r.Fatal("client not registered") - } - nodeAddr = node.Address - }) - - // Add in some metadata via the catalog (as if the agent synced it - // there). We also set the serfHealth check to failing so the reconcile - // will attempt to flip it back - req := structs.RegisterRequest{ - Datacenter: s1.config.Datacenter, - Node: c1.config.NodeName, - ID: c1.config.NodeID, - Address: nodeAddr, - NodeMeta: map[string]string{"hello": "world"}, - Check: &structs.HealthCheck{ - Node: c1.config.NodeName, - CheckID: structs.SerfCheckID, - Name: structs.SerfCheckName, - Status: api.HealthCritical, - Output: "", - }, - } - var out struct{} - if err := s1.RPC(context.Background(), "Catalog.Register", &req, &out); err != nil { - t.Fatalf("err: %v", err) - } - - // Force a reconcile and make sure the metadata stuck around. - if err := s1.reconcile(); err != nil { - t.Fatalf("err: %v", err) - } - _, node, err := state.GetNode(c1.config.NodeName, nil, "") - if err != nil { - t.Fatalf("err: %v", err) - } - if node == nil { - t.Fatalf("bad") - } - if hello, ok := node.Meta["hello"]; !ok || hello != "world" { - t.Fatalf("bad") - } - - // Fail the member and wait for the health to go critical. - c1.Shutdown() - retry.Run(t, func(r *retry.R) { - _, checks, err := state.NodeChecks(nil, c1.config.NodeName, nil, "") - if err != nil { - r.Fatalf("err: %v", err) - } - if len(checks) != 1 { - r.Fatalf("client missing check") - } - if got, want := checks[0].Status, api.HealthCritical; got != want { - r.Fatalf("got state %q want %q", got, want) - } - }) - - // Make sure the metadata didn't get clobbered. - _, node, err = state.GetNode(c1.config.NodeName, nil, "") - if err != nil { - t.Fatalf("err: %v", err) - } - if node == nil { - t.Fatalf("bad") - } - if hello, ok := node.Meta["hello"]; !ok || hello != "world" { - t.Fatalf("bad") - } -} - -func TestLeader_LeftServer(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - dir1, s1 := testServer(t) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - dir2, s2 := testServerDCBootstrap(t, "dc1", false) - defer os.RemoveAll(dir2) - defer s2.Shutdown() - - dir3, s3 := testServerDCBootstrap(t, "dc1", false) - defer os.RemoveAll(dir3) - defer s3.Shutdown() - - // Put s1 last so we don't trigger a leader election. - servers := []*Server{s2, s3, s1} - - // Try to join - joinLAN(t, s2, s1) - joinLAN(t, s3, s1) - for _, s := range servers { - retry.Run(t, func(r *retry.R) { r.Check(wantPeers(s, 3)) }) - } - - // Kill any server - servers[0].Shutdown() - - // Force remove the non-leader (transition to left state) - if err := servers[1].RemoveFailedNode(servers[0].config.NodeName, false, nil); err != nil { - t.Fatalf("err: %v", err) - } - - // Wait until the remaining servers show only 2 peers. - for _, s := range servers[1:] { - retry.Run(t, func(r *retry.R) { r.Check(wantPeers(s, 2)) }) - } - s1.Shutdown() -} - -func TestLeader_LeftLeader(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - dir1, s1 := testServer(t) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - dir2, s2 := testServerDCBootstrap(t, "dc1", false) - defer os.RemoveAll(dir2) - defer s2.Shutdown() - - dir3, s3 := testServerDCBootstrap(t, "dc1", false) - defer os.RemoveAll(dir3) - defer s3.Shutdown() - servers := []*Server{s1, s2, s3} - - // Try to join - joinLAN(t, s2, s1) - joinLAN(t, s3, s1) - - for _, s := range servers { - retry.Run(t, func(r *retry.R) { r.Check(wantPeers(s, 3)) }) - } - - // Kill the leader! - var leader *Server - for _, s := range servers { - if s.IsLeader() { - leader = s - break - } - } - if leader == nil { - t.Fatalf("Should have a leader") - } - if !leader.isReadyForConsistentReads() { - t.Fatalf("Expected leader to be ready for consistent reads ") - } - leader.Leave() - if leader.isReadyForConsistentReads() { - t.Fatalf("Expected consistent read state to be false ") - } - leader.Shutdown() - time.Sleep(100 * time.Millisecond) - - var remain *Server - for _, s := range servers { - if s == leader { - continue - } - remain = s - retry.Run(t, func(r *retry.R) { r.Check(wantPeers(s, 2)) }) - } - - // Verify the old leader is deregistered - state := remain.fsm.State() - retry.Run(t, func(r *retry.R) { - _, node, err := state.GetNode(leader.config.NodeName, nil, "") - if err != nil { - r.Fatalf("err: %v", err) - } - if node != nil { - r.Fatal("leader should be deregistered") - } - }) -} - -func TestLeader_MultiBootstrap(t *testing.T) { - t.Parallel() - dir1, s1 := testServer(t) - defer os.RemoveAll(dir1) - defer s1.Shutdown() - - dir2, s2 := testServer(t) - defer os.RemoveAll(dir2) - defer s2.Shutdown() - - servers := []*Server{s1, s2} - - // Try to join - joinLAN(t, s2, s1) + "github.com/stretchr/testify/require" + "google.golang.org/grpc" - for _, s := range servers { - retry.Run(t, func(r *retry.R) { - if got, want := len(s.serfLAN.Members()), 2; got != want { - r.Fatalf("got %d peers want %d", got, want) - } - }) - } + msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/serf/serf" - // Ensure we don't have multiple raft peers - for _, s := range servers { - peers, _ := s.autopilot.NumVoters() - if peers != 1 { - t.Fatalf("should only have 1 raft peer!") - } - } -} + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/agent/structs" + tokenStore "github.com/hashicorp/consul/agent/token" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/consul/sdk/testutil/retry" + "github.com/hashicorp/consul/testrpc" +) func TestLeader_TombstoneGC_Reset(t *testing.T) { if testing.Short() { @@ -1640,7 +773,7 @@ func TestLeader_ConfigEntryBootstrap_Fail(t *testing.T) { deps := newDefaultDeps(t, config) deps.Logger = logger - srv, err := NewServer(config, deps, grpc.NewServer(), nil, logger, nil) + srv, err := NewServer(config, deps, grpc.NewServer(), nil, logger) require.NoError(t, err) defer srv.Shutdown() @@ -2003,6 +1136,7 @@ func TestDatacenterSupportsIntentionsAsConfigEntries(t *testing.T) { if err := srv.RPC(context.Background(), "ConfigEntry.Get", &arg, &reply); err != nil { return nil, err } + reply.Entry.SetHash(0) return reply.Entry, nil } @@ -2087,7 +1221,7 @@ func TestDatacenterSupportsIntentionsAsConfigEntries(t *testing.T) { RaftIndex: got.RaftIndex, } - + got.Hash = 0 require.Equal(t, expect, got) }) diff --git a/agent/consul/operator_backend_test.go b/agent/consul/operator_backend_test.go index 0a4650359ec1..6127868b9f00 100644 --- a/agent/consul/operator_backend_test.go +++ b/agent/consul/operator_backend_test.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/consul/acl" external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/lib/testhelpers" "github.com/hashicorp/consul/proto/private/pboperator" "github.com/hashicorp/consul/sdk/testutil/retry" "google.golang.org/grpc/credentials/insecure" @@ -25,6 +26,8 @@ import ( func TestOperatorBackend_TransferLeader(t *testing.T) { t.Parallel() + testhelpers.SkipFlake(t) + conf := testClusterConfig{ Datacenter: "dc1", Servers: 3, diff --git a/agent/consul/operator_usage_endpoint.go b/agent/consul/operator_usage_endpoint.go index 68f3137d0a61..fba51389c147 100644 --- a/agent/consul/operator_usage_endpoint.go +++ b/agent/consul/operator_usage_endpoint.go @@ -54,7 +54,7 @@ func (op *Operator) Usage(args *structs.OperatorUsageRequest, reply *structs.Usa &reply.QueryMeta, func(ws memdb.WatchSet, state *state.Store) error { // Get service usage. - index, serviceUsage, err := state.ServiceUsage(ws) + index, serviceUsage, err := state.ServiceUsage(ws, true) if err != nil { return err } diff --git a/agent/consul/options.go b/agent/consul/options.go index 88c16bd1a99c..8c9fe05f4873 100644 --- a/agent/consul/options.go +++ b/agent/consul/options.go @@ -4,7 +4,6 @@ package consul import ( - "github.com/hashicorp/consul/lib/stringslice" "google.golang.org/grpc" "github.com/hashicorp/consul-net-rpc/net/rpc" @@ -49,24 +48,6 @@ type Deps struct { EnterpriseDeps } -// UseV2Resources returns true if "resource-apis" is present in the Experiments -// array of the agent config. -func (d Deps) UseV2Resources() bool { - if stringslice.Contains(d.Experiments, CatalogResourceExperimentName) { - return true - } - return false -} - -// UseV2Tenancy returns true if "v2tenancy" is present in the Experiments -// array of the agent config. -func (d Deps) UseV2Tenancy() bool { - if stringslice.Contains(d.Experiments, V2TenancyExperimentName) { - return true - } - return false -} - type GRPCClientConner interface { ClientConn(datacenter string) (*grpc.ClientConn, error) ClientConnLeader() (*grpc.ClientConn, error) diff --git a/agent/consul/prepared_query_endpoint.go b/agent/consul/prepared_query_endpoint.go index 139556bb1af8..7c2bf1f96057 100644 --- a/agent/consul/prepared_query_endpoint.go +++ b/agent/consul/prepared_query_endpoint.go @@ -562,8 +562,14 @@ func (p *PreparedQuery) execute(query *structs.PreparedQuery, } // Filter out any unhealthy nodes. - nodes = nodes.FilterIgnore(query.Service.OnlyPassing, - query.Service.IgnoreCheckIDs) + filterType := structs.HealthFilterExcludeCritical + if query.Service.OnlyPassing { + filterType = structs.HealthFilterIncludeOnlyPassing + + } + + nodes = nodes.Filter(structs.CheckServiceNodeFilterOptions{FilterType: filterType, + IgnoreCheckIDs: query.Service.IgnoreCheckIDs}) // Apply the node metadata filters, if any. if len(query.Service.NodeMeta) > 0 { diff --git a/agent/consul/prepared_query_endpoint_test.go b/agent/consul/prepared_query_endpoint_test.go index f0d63dc277c1..2761df4093fa 100644 --- a/agent/consul/prepared_query_endpoint_test.go +++ b/agent/consul/prepared_query_endpoint_test.go @@ -3357,6 +3357,7 @@ type executeServers struct { func createExecuteServers(t *testing.T) *executeServers { es := newExecuteServers(t) + es.initPeering(t, "") es.initWanFed(t) es.exportPeeringServices(t) es.initTokens(t) @@ -3365,7 +3366,6 @@ func createExecuteServers(t *testing.T) *executeServers { } func newExecuteServers(t *testing.T) *executeServers { - // Setup server dir1, s1 := testServerWithConfig(t, func(c *Config) { c.PrimaryDatacenter = "dc1" @@ -3416,67 +3416,6 @@ func newExecuteServers(t *testing.T) *executeServers { testrpc.WaitForLeader(t, s1.RPC, "dc1", testrpc.WithToken("root")) testrpc.WaitForLeader(t, s3.RPC, "dc3") - acceptingPeerName := "my-peer-accepting-server" - dialingPeerName := "my-peer-dialing-server" - - // Set up peering between dc1 (dialing) and dc3 (accepting) and export the foo service - { - // Create a peering by generating a token. - ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) - t.Cleanup(cancel) - - options := structs.QueryOptions{Token: "root"} - ctx, err := grpcexternal.ContextWithQueryOptions(ctx, options) - require.NoError(t, err) - - conn, err := grpc.DialContext(ctx, s3.config.RPCAddr.String(), - grpc.WithContextDialer(newServerDialer(s3.config.RPCAddr.String())), - //nolint:staticcheck - grpc.WithInsecure(), - grpc.WithBlock()) - require.NoError(t, err) - t.Cleanup(func() { - conn.Close() - }) - - peeringClient := pbpeering.NewPeeringServiceClient(conn) - req := pbpeering.GenerateTokenRequest{ - PeerName: dialingPeerName, - } - resp, err := peeringClient.GenerateToken(ctx, &req) - require.NoError(t, err) - - conn, err = grpc.DialContext(ctx, s1.config.RPCAddr.String(), - grpc.WithContextDialer(newServerDialer(s1.config.RPCAddr.String())), - //nolint:staticcheck - grpc.WithInsecure(), - grpc.WithBlock()) - require.NoError(t, err) - t.Cleanup(func() { - conn.Close() - }) - - peeringClient = pbpeering.NewPeeringServiceClient(conn) - establishReq := pbpeering.EstablishRequest{ - PeerName: acceptingPeerName, - PeeringToken: resp.PeeringToken, - } - establishResp, err := peeringClient.Establish(ctx, &establishReq) - require.NoError(t, err) - require.NotNil(t, establishResp) - - readResp, err := peeringClient.PeeringRead(ctx, &pbpeering.PeeringReadRequest{Name: acceptingPeerName}) - require.NoError(t, err) - require.NotNil(t, readResp) - - // Wait for the stream to be connected. - retry.Run(t, func(r *retry.R) { - status, found := s1.peerStreamServer.StreamStatus(readResp.GetPeering().GetID()) - require.True(r, found) - require.True(r, status.Connected) - }) - } - es := executeServers{ server: &serverTestMetadata{ server: s1, @@ -3487,8 +3426,8 @@ func newExecuteServers(t *testing.T) *executeServers { server: s3, codec: codec3, datacenter: "dc3", - dialingPeerName: dialingPeerName, - acceptingPeerName: acceptingPeerName, + dialingPeerName: "my-peer-dialing-server", + acceptingPeerName: "my-peer-accepting-server", }, } @@ -3562,3 +3501,64 @@ func (es *executeServers) initWanFed(t *testing.T) { datacenter: "dc2", } } + +func (es *executeServers) initPeering(t *testing.T, localPartition string) { + // Create a peering by generating a token. + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + t.Cleanup(cancel) + + options := structs.QueryOptions{Token: "root"} + ctx, err := grpcexternal.ContextWithQueryOptions(ctx, options) + require.NoError(t, err) + + conn, err := grpc.DialContext(ctx, es.peeringServer.server.config.RPCAddr.String(), + grpc.WithContextDialer(newServerDialer(es.peeringServer.server.config.RPCAddr.String())), + //nolint:staticcheck + grpc.WithInsecure(), + grpc.WithBlock()) + require.NoError(t, err) + t.Cleanup(func() { + conn.Close() + }) + + peeringClient := pbpeering.NewPeeringServiceClient(conn) + req := pbpeering.GenerateTokenRequest{ + PeerName: es.peeringServer.dialingPeerName, + } + resp, err := peeringClient.GenerateToken(ctx, &req) + require.NoError(t, err) + + conn, err = grpc.DialContext(ctx, es.server.server.config.RPCAddr.String(), + grpc.WithContextDialer(newServerDialer(es.server.server.config.RPCAddr.String())), + //nolint:staticcheck + grpc.WithInsecure(), + grpc.WithBlock()) + require.NoError(t, err) + t.Cleanup(func() { + conn.Close() + }) + + peeringClient = pbpeering.NewPeeringServiceClient(conn) + establishReq := pbpeering.EstablishRequest{ + Partition: localPartition, + PeerName: es.peeringServer.acceptingPeerName, + PeeringToken: resp.PeeringToken, + } + establishResp, err := peeringClient.Establish(ctx, &establishReq) + require.NoError(t, err) + require.NotNil(t, establishResp) + + readResp, err := peeringClient.PeeringRead(ctx, &pbpeering.PeeringReadRequest{ + Partition: localPartition, + Name: es.peeringServer.acceptingPeerName, + }) + require.NoError(t, err) + require.NotNil(t, readResp) + + // Wait for the stream to be connected. + retry.Run(t, func(r *retry.R) { + status, found := es.server.server.peerStreamServer.StreamStatus(readResp.GetPeering().GetID()) + require.True(r, found) + require.True(r, status.Connected) + }) +} diff --git a/agent/consul/replication.go b/agent/consul/replication.go index 08b8811129be..ebed1377e1ff 100644 --- a/agent/consul/replication.go +++ b/agent/consul/replication.go @@ -153,6 +153,12 @@ func (r *Replicator) Run(ctx context.Context) error { // Perform a single round of replication index, exit, err := r.delegate.Replicate(ctx, atomic.LoadUint64(&r.lastRemoteIndex), r.logger) if exit { + metrics.SetGauge([]string{"leader", "replication", r.delegate.MetricName(), "status"}, + 0, + ) + metrics.SetGauge([]string{"leader", "replication", r.delegate.MetricName(), "index"}, + 0, + ) return nil } if err != nil { diff --git a/agent/consul/reporting/.mockery.yaml b/agent/consul/reporting/.mockery.yaml new file mode 100644 index 000000000000..bafba6b32d7b --- /dev/null +++ b/agent/consul/reporting/.mockery.yaml @@ -0,0 +1,12 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +with-expecter: true +all: true +recursive: false +mockname: "{{.InterfaceName}}" +dir: "reportingmock" +filename: "mock_{{.InterfaceName}}.go" +outpkg: "reportingmock" +packages: + github.com/hashicorp/consul/agent/consul/reporting: diff --git a/agent/consul/reporting/reporting.go b/agent/consul/reporting/reporting.go index d6c480f6bace..0eedfb7d7dde 100644 --- a/agent/consul/reporting/reporting.go +++ b/agent/consul/reporting/reporting.go @@ -36,7 +36,7 @@ type ServerDelegate interface { type StateDelegate interface { NodeUsage() (uint64, state.NodeUsage, error) - ServiceUsage(ws memdb.WatchSet) (uint64, structs.ServiceUsage, error) + ServiceUsage(ws memdb.WatchSet, tenantUsage bool) (uint64, structs.ServiceUsage, error) } func NewReportingManager(logger hclog.Logger, deps EntDeps, server ServerDelegate, stateProvider StateDelegate) *ReportingManager { diff --git a/agent/consul/reporting/reportingmock/mock_ServerDelegate.go b/agent/consul/reporting/reportingmock/mock_ServerDelegate.go new file mode 100644 index 000000000000..9acfa83aee96 --- /dev/null +++ b/agent/consul/reporting/reportingmock/mock_ServerDelegate.go @@ -0,0 +1,168 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package reportingmock + +import mock "github.com/stretchr/testify/mock" + +// ServerDelegate is an autogenerated mock type for the ServerDelegate type +type ServerDelegate struct { + mock.Mock +} + +type ServerDelegate_Expecter struct { + mock *mock.Mock +} + +func (_m *ServerDelegate) EXPECT() *ServerDelegate_Expecter { + return &ServerDelegate_Expecter{mock: &_m.Mock} +} + +// GetSystemMetadata provides a mock function with given fields: key +func (_m *ServerDelegate) GetSystemMetadata(key string) (string, error) { + ret := _m.Called(key) + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(string) (string, error)); ok { + return rf(key) + } + if rf, ok := ret.Get(0).(func(string) string); ok { + r0 = rf(key) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ServerDelegate_GetSystemMetadata_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSystemMetadata' +type ServerDelegate_GetSystemMetadata_Call struct { + *mock.Call +} + +// GetSystemMetadata is a helper method to define mock.On call +// - key string +func (_e *ServerDelegate_Expecter) GetSystemMetadata(key interface{}) *ServerDelegate_GetSystemMetadata_Call { + return &ServerDelegate_GetSystemMetadata_Call{Call: _e.mock.On("GetSystemMetadata", key)} +} + +func (_c *ServerDelegate_GetSystemMetadata_Call) Run(run func(key string)) *ServerDelegate_GetSystemMetadata_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *ServerDelegate_GetSystemMetadata_Call) Return(_a0 string, _a1 error) *ServerDelegate_GetSystemMetadata_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ServerDelegate_GetSystemMetadata_Call) RunAndReturn(run func(string) (string, error)) *ServerDelegate_GetSystemMetadata_Call { + _c.Call.Return(run) + return _c +} + +// IsLeader provides a mock function with given fields: +func (_m *ServerDelegate) IsLeader() bool { + ret := _m.Called() + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// ServerDelegate_IsLeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsLeader' +type ServerDelegate_IsLeader_Call struct { + *mock.Call +} + +// IsLeader is a helper method to define mock.On call +func (_e *ServerDelegate_Expecter) IsLeader() *ServerDelegate_IsLeader_Call { + return &ServerDelegate_IsLeader_Call{Call: _e.mock.On("IsLeader")} +} + +func (_c *ServerDelegate_IsLeader_Call) Run(run func()) *ServerDelegate_IsLeader_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ServerDelegate_IsLeader_Call) Return(_a0 bool) *ServerDelegate_IsLeader_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDelegate_IsLeader_Call) RunAndReturn(run func() bool) *ServerDelegate_IsLeader_Call { + _c.Call.Return(run) + return _c +} + +// SetSystemMetadataKey provides a mock function with given fields: key, val +func (_m *ServerDelegate) SetSystemMetadataKey(key string, val string) error { + ret := _m.Called(key, val) + + var r0 error + if rf, ok := ret.Get(0).(func(string, string) error); ok { + r0 = rf(key, val) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ServerDelegate_SetSystemMetadataKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetSystemMetadataKey' +type ServerDelegate_SetSystemMetadataKey_Call struct { + *mock.Call +} + +// SetSystemMetadataKey is a helper method to define mock.On call +// - key string +// - val string +func (_e *ServerDelegate_Expecter) SetSystemMetadataKey(key interface{}, val interface{}) *ServerDelegate_SetSystemMetadataKey_Call { + return &ServerDelegate_SetSystemMetadataKey_Call{Call: _e.mock.On("SetSystemMetadataKey", key, val)} +} + +func (_c *ServerDelegate_SetSystemMetadataKey_Call) Run(run func(key string, val string)) *ServerDelegate_SetSystemMetadataKey_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(string)) + }) + return _c +} + +func (_c *ServerDelegate_SetSystemMetadataKey_Call) Return(_a0 error) *ServerDelegate_SetSystemMetadataKey_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDelegate_SetSystemMetadataKey_Call) RunAndReturn(run func(string, string) error) *ServerDelegate_SetSystemMetadataKey_Call { + _c.Call.Return(run) + return _c +} + +// NewServerDelegate creates a new instance of ServerDelegate. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewServerDelegate(t interface { + mock.TestingT + Cleanup(func()) +}) *ServerDelegate { + mock := &ServerDelegate{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/agent/consul/reporting/reportingmock/mock_StateDelegate.go b/agent/consul/reporting/reportingmock/mock_StateDelegate.go new file mode 100644 index 000000000000..cd9a2378c1aa --- /dev/null +++ b/agent/consul/reporting/reportingmock/mock_StateDelegate.go @@ -0,0 +1,157 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package reportingmock + +import ( + memdb "github.com/hashicorp/go-memdb" + mock "github.com/stretchr/testify/mock" + + state "github.com/hashicorp/consul/agent/consul/state" + + structs "github.com/hashicorp/consul/agent/structs" +) + +// StateDelegate is an autogenerated mock type for the StateDelegate type +type StateDelegate struct { + mock.Mock +} + +type StateDelegate_Expecter struct { + mock *mock.Mock +} + +func (_m *StateDelegate) EXPECT() *StateDelegate_Expecter { + return &StateDelegate_Expecter{mock: &_m.Mock} +} + +// NodeUsage provides a mock function with given fields: +func (_m *StateDelegate) NodeUsage() (uint64, state.NodeUsage, error) { + ret := _m.Called() + + var r0 uint64 + var r1 state.NodeUsage + var r2 error + if rf, ok := ret.Get(0).(func() (uint64, state.NodeUsage, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() uint64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func() state.NodeUsage); ok { + r1 = rf() + } else { + r1 = ret.Get(1).(state.NodeUsage) + } + + if rf, ok := ret.Get(2).(func() error); ok { + r2 = rf() + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// StateDelegate_NodeUsage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NodeUsage' +type StateDelegate_NodeUsage_Call struct { + *mock.Call +} + +// NodeUsage is a helper method to define mock.On call +func (_e *StateDelegate_Expecter) NodeUsage() *StateDelegate_NodeUsage_Call { + return &StateDelegate_NodeUsage_Call{Call: _e.mock.On("NodeUsage")} +} + +func (_c *StateDelegate_NodeUsage_Call) Run(run func()) *StateDelegate_NodeUsage_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *StateDelegate_NodeUsage_Call) Return(_a0 uint64, _a1 state.NodeUsage, _a2 error) *StateDelegate_NodeUsage_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *StateDelegate_NodeUsage_Call) RunAndReturn(run func() (uint64, state.NodeUsage, error)) *StateDelegate_NodeUsage_Call { + _c.Call.Return(run) + return _c +} + +// ServiceUsage provides a mock function with given fields: ws, tenantUsage +func (_m *StateDelegate) ServiceUsage(ws memdb.WatchSet, tenantUsage bool) (uint64, structs.ServiceUsage, error) { + ret := _m.Called(ws, tenantUsage) + + var r0 uint64 + var r1 structs.ServiceUsage + var r2 error + if rf, ok := ret.Get(0).(func(memdb.WatchSet, bool) (uint64, structs.ServiceUsage, error)); ok { + return rf(ws, tenantUsage) + } + if rf, ok := ret.Get(0).(func(memdb.WatchSet, bool) uint64); ok { + r0 = rf(ws, tenantUsage) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(memdb.WatchSet, bool) structs.ServiceUsage); ok { + r1 = rf(ws, tenantUsage) + } else { + r1 = ret.Get(1).(structs.ServiceUsage) + } + + if rf, ok := ret.Get(2).(func(memdb.WatchSet, bool) error); ok { + r2 = rf(ws, tenantUsage) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// StateDelegate_ServiceUsage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ServiceUsage' +type StateDelegate_ServiceUsage_Call struct { + *mock.Call +} + +// ServiceUsage is a helper method to define mock.On call +// - ws memdb.WatchSet +// - tenantUsage bool +func (_e *StateDelegate_Expecter) ServiceUsage(ws interface{}, tenantUsage interface{}) *StateDelegate_ServiceUsage_Call { + return &StateDelegate_ServiceUsage_Call{Call: _e.mock.On("ServiceUsage", ws, tenantUsage)} +} + +func (_c *StateDelegate_ServiceUsage_Call) Run(run func(ws memdb.WatchSet, tenantUsage bool)) *StateDelegate_ServiceUsage_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(memdb.WatchSet), args[1].(bool)) + }) + return _c +} + +func (_c *StateDelegate_ServiceUsage_Call) Return(_a0 uint64, _a1 structs.ServiceUsage, _a2 error) *StateDelegate_ServiceUsage_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *StateDelegate_ServiceUsage_Call) RunAndReturn(run func(memdb.WatchSet, bool) (uint64, structs.ServiceUsage, error)) *StateDelegate_ServiceUsage_Call { + _c.Call.Return(run) + return _c +} + +// NewStateDelegate creates a new instance of StateDelegate. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewStateDelegate(t interface { + mock.TestingT + Cleanup(func()) +}) *StateDelegate { + mock := &StateDelegate{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/agent/consul/rpc.go b/agent/consul/rpc.go index dbb781951e34..8c5ad14efffd 100644 --- a/agent/consul/rpc.go +++ b/agent/consul/rpc.go @@ -244,7 +244,7 @@ func (s *Server) handleConn(conn net.Conn, isTLS bool) { s.handleInsecureConn(conn) case pool.RPCGRPC: - s.grpcHandler.Handle(conn) + s.internalGRPCHandler.Handle(conn) case pool.RPCRaftForwarding: s.handleRaftForwarding(conn) @@ -315,7 +315,7 @@ func (s *Server) handleNativeTLS(conn net.Conn) { s.handleSnapshotConn(tlsConn) case pool.ALPN_RPCGRPC: - s.grpcHandler.Handle(tlsConn) + s.internalGRPCHandler.Handle(tlsConn) case pool.ALPN_RPCRaftForwarding: s.handleRaftForwarding(tlsConn) diff --git a/agent/consul/rpc_test.go b/agent/consul/rpc_test.go index 39351c98ca92..11dbeef5db54 100644 --- a/agent/consul/rpc_test.go +++ b/agent/consul/rpc_test.go @@ -24,7 +24,6 @@ import ( "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-memdb" "github.com/hashicorp/raft" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" @@ -232,136 +231,12 @@ func (m *MockSink) Close() error { return nil } +// TestServer_blockingQuery tests authenticated and unauthenticated calls. The +// other blocking query tests reside in blockingquery_test.go in the blockingquery package. func TestServer_blockingQuery(t *testing.T) { t.Parallel() _, s := testServerWithConfig(t) - // Perform a non-blocking query. Note that it's significant that the meta has - // a zero index in response - the implied opts.MinQueryIndex is also zero but - // this should not block still. - t.Run("non-blocking query", func(t *testing.T) { - var opts structs.QueryOptions - var meta structs.QueryMeta - var calls int - fn := func(_ memdb.WatchSet, _ *state.Store) error { - calls++ - return nil - } - err := s.blockingQuery(&opts, &meta, fn) - require.NoError(t, err) - require.Equal(t, 1, calls) - }) - - // Perform a blocking query that gets woken up and loops around once. - t.Run("blocking query - single loop", func(t *testing.T) { - opts := structs.QueryOptions{ - MinQueryIndex: 3, - } - var meta structs.QueryMeta - var calls int - fn := func(ws memdb.WatchSet, _ *state.Store) error { - if calls == 0 { - meta.Index = 3 - - fakeCh := make(chan struct{}) - close(fakeCh) - ws.Add(fakeCh) - } else { - meta.Index = 4 - } - calls++ - return nil - } - err := s.blockingQuery(&opts, &meta, fn) - require.NoError(t, err) - require.Equal(t, 2, calls) - }) - - // Perform a blocking query that returns a zero index from blocking func (e.g. - // no state yet). This should still return an empty response immediately, but - // with index of 1 and then block on the next attempt. In one sense zero index - // is not really a valid response from a state method that is not an error but - // in practice a lot of state store operations do return it unless they - // explicitly special checks to turn 0 into 1. Often this is not caught or - // covered by tests but eventually when hit in the wild causes blocking - // clients to busy loop and burn CPU. This test ensure that blockingQuery - // systematically does the right thing to prevent future bugs like that. - t.Run("blocking query with 0 modifyIndex from state func", func(t *testing.T) { - opts := structs.QueryOptions{ - MinQueryIndex: 0, - } - var meta structs.QueryMeta - var calls int - fn := func(ws memdb.WatchSet, _ *state.Store) error { - if opts.MinQueryIndex > 0 { - // If client requested blocking, block forever. This is simulating - // waiting for the watched resource to be initialized/written to giving - // it a non-zero index. Note the timeout on the query options is relied - // on to stop the test taking forever. - fakeCh := make(chan struct{}) - ws.Add(fakeCh) - } - meta.Index = 0 - calls++ - return nil - } - require.NoError(t, s.blockingQuery(&opts, &meta, fn)) - assert.Equal(t, 1, calls) - assert.Equal(t, uint64(1), meta.Index, - "expect fake index of 1 to force client to block on next update") - - // Simulate client making next request - opts.MinQueryIndex = 1 - opts.MaxQueryTime = 20 * time.Millisecond // Don't wait too long - - // This time we should block even though the func returns index 0 still - t0 := time.Now() - require.NoError(t, s.blockingQuery(&opts, &meta, fn)) - t1 := time.Now() - assert.Equal(t, 2, calls) - assert.Equal(t, uint64(1), meta.Index, - "expect fake index of 1 to force client to block on next update") - assert.True(t, t1.Sub(t0) > 20*time.Millisecond, - "should have actually blocked waiting for timeout") - - }) - - // Perform a query that blocks and gets interrupted when the state store - // is abandoned. - t.Run("blocking query interrupted by abandonCh", func(t *testing.T) { - opts := structs.QueryOptions{ - MinQueryIndex: 3, - } - var meta structs.QueryMeta - var calls int - fn := func(_ memdb.WatchSet, _ *state.Store) error { - if calls == 0 { - meta.Index = 3 - - snap, err := s.fsm.Snapshot() - if err != nil { - t.Fatalf("err: %v", err) - } - defer snap.Release() - - buf := bytes.NewBuffer(nil) - sink := &MockSink{buf, false} - if err := snap.Persist(sink); err != nil { - t.Fatalf("err: %v", err) - } - - if err := s.fsm.Restore(sink); err != nil { - t.Fatalf("err: %v", err) - } - } - calls++ - return nil - } - err := s.blockingQuery(&opts, &meta, fn) - require.NoError(t, err) - require.Equal(t, 1, calls) - }) - t.Run("ResultsFilteredByACLs is reset for unauthenticated calls", func(t *testing.T) { opts := structs.QueryOptions{ Token: "", @@ -394,93 +269,6 @@ func TestServer_blockingQuery(t *testing.T) { require.NoError(t, err) require.True(t, meta.ResultsFilteredByACLs, "ResultsFilteredByACLs should be honored for authenticated calls") }) - - t.Run("non-blocking query for item that does not exist", func(t *testing.T) { - opts := structs.QueryOptions{} - meta := structs.QueryMeta{} - calls := 0 - fn := func(_ memdb.WatchSet, _ *state.Store) error { - calls++ - return errNotFound - } - - err := s.blockingQuery(&opts, &meta, fn) - require.NoError(t, err) - require.Equal(t, 1, calls) - }) - - t.Run("blocking query for item that does not exist", func(t *testing.T) { - opts := structs.QueryOptions{MinQueryIndex: 3, MaxQueryTime: 100 * time.Millisecond} - meta := structs.QueryMeta{} - calls := 0 - fn := func(ws memdb.WatchSet, _ *state.Store) error { - calls++ - if calls == 1 { - meta.Index = 3 - - ch := make(chan struct{}) - close(ch) - ws.Add(ch) - return errNotFound - } - meta.Index = 5 - return errNotFound - } - - err := s.blockingQuery(&opts, &meta, fn) - require.NoError(t, err) - require.Equal(t, 2, calls) - }) - - t.Run("blocking query for item that existed and is removed", func(t *testing.T) { - opts := structs.QueryOptions{MinQueryIndex: 3, MaxQueryTime: 100 * time.Millisecond} - meta := structs.QueryMeta{} - calls := 0 - fn := func(ws memdb.WatchSet, _ *state.Store) error { - calls++ - if calls == 1 { - meta.Index = 3 - - ch := make(chan struct{}) - close(ch) - ws.Add(ch) - return nil - } - meta.Index = 5 - return errNotFound - } - - start := time.Now() - err := s.blockingQuery(&opts, &meta, fn) - require.True(t, time.Since(start) < opts.MaxQueryTime, "query timed out") - require.NoError(t, err) - require.Equal(t, 2, calls) - }) - - t.Run("blocking query for non-existent item that is created", func(t *testing.T) { - opts := structs.QueryOptions{MinQueryIndex: 3, MaxQueryTime: 100 * time.Millisecond} - meta := structs.QueryMeta{} - calls := 0 - fn := func(ws memdb.WatchSet, _ *state.Store) error { - calls++ - if calls == 1 { - meta.Index = 3 - - ch := make(chan struct{}) - close(ch) - ws.Add(ch) - return errNotFound - } - meta.Index = 5 - return nil - } - - start := time.Now() - err := s.blockingQuery(&opts, &meta, fn) - require.True(t, time.Since(start) < opts.MaxQueryTime, "query timed out") - require.NoError(t, err) - require.Equal(t, 2, calls) - }) } func TestRPC_ReadyForConsistentReads(t *testing.T) { diff --git a/agent/consul/rtt.go b/agent/consul/rtt.go index 1599301e158d..ca1ebc361056 100644 --- a/agent/consul/rtt.go +++ b/agent/consul/rtt.go @@ -8,7 +8,7 @@ import ( "sort" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" ) // nodeSorter takes a list of nodes and a parallel vector of distances and @@ -21,7 +21,7 @@ type nodeSorter struct { // newNodeSorter returns a new sorter for the given source coordinate and set of // nodes. -func (s *Server) newNodeSorter(cs lib.CoordinateSet, nodes structs.Nodes) (sort.Interface, error) { +func (s *Server) newNodeSorter(cs librtt.CoordinateSet, nodes structs.Nodes) (sort.Interface, error) { state := s.fsm.State() vec := make([]float64, len(nodes)) for i, node := range nodes { @@ -30,7 +30,7 @@ func (s *Server) newNodeSorter(cs lib.CoordinateSet, nodes structs.Nodes) (sort. return nil, err } c1, c2 := cs.Intersect(other) - vec[i] = lib.ComputeDistance(c1, c2) + vec[i] = librtt.ComputeDistance(c1, c2) } return &nodeSorter{nodes, vec}, nil } @@ -61,7 +61,7 @@ type serviceNodeSorter struct { // newServiceNodeSorter returns a new sorter for the given source coordinate and // set of service nodes. -func (s *Server) newServiceNodeSorter(cs lib.CoordinateSet, nodes structs.ServiceNodes) (sort.Interface, error) { +func (s *Server) newServiceNodeSorter(cs librtt.CoordinateSet, nodes structs.ServiceNodes) (sort.Interface, error) { state := s.fsm.State() vec := make([]float64, len(nodes)) for i, node := range nodes { @@ -70,7 +70,7 @@ func (s *Server) newServiceNodeSorter(cs lib.CoordinateSet, nodes structs.Servic return nil, err } c1, c2 := cs.Intersect(other) - vec[i] = lib.ComputeDistance(c1, c2) + vec[i] = librtt.ComputeDistance(c1, c2) } return &serviceNodeSorter{nodes, vec}, nil } @@ -101,7 +101,7 @@ type healthCheckSorter struct { // newHealthCheckSorter returns a new sorter for the given source coordinate and // set of health checks with nodes. -func (s *Server) newHealthCheckSorter(cs lib.CoordinateSet, checks structs.HealthChecks) (sort.Interface, error) { +func (s *Server) newHealthCheckSorter(cs librtt.CoordinateSet, checks structs.HealthChecks) (sort.Interface, error) { state := s.fsm.State() vec := make([]float64, len(checks)) for i, check := range checks { @@ -110,7 +110,7 @@ func (s *Server) newHealthCheckSorter(cs lib.CoordinateSet, checks structs.Healt return nil, err } c1, c2 := cs.Intersect(other) - vec[i] = lib.ComputeDistance(c1, c2) + vec[i] = librtt.ComputeDistance(c1, c2) } return &healthCheckSorter{checks, vec}, nil } @@ -141,7 +141,7 @@ type checkServiceNodeSorter struct { // newCheckServiceNodeSorter returns a new sorter for the given source coordinate // and set of nodes with health checks. -func (s *Server) newCheckServiceNodeSorter(cs lib.CoordinateSet, nodes structs.CheckServiceNodes) (sort.Interface, error) { +func (s *Server) newCheckServiceNodeSorter(cs librtt.CoordinateSet, nodes structs.CheckServiceNodes) (sort.Interface, error) { state := s.fsm.State() vec := make([]float64, len(nodes)) for i, node := range nodes { @@ -150,7 +150,7 @@ func (s *Server) newCheckServiceNodeSorter(cs lib.CoordinateSet, nodes structs.C return nil, err } c1, c2 := cs.Intersect(other) - vec[i] = lib.ComputeDistance(c1, c2) + vec[i] = librtt.ComputeDistance(c1, c2) } return &checkServiceNodeSorter{nodes, vec}, nil } @@ -172,7 +172,7 @@ func (n *checkServiceNodeSorter) Less(i, j int) bool { } // newSorterByDistanceFrom returns a sorter for the given type. -func (s *Server) newSorterByDistanceFrom(cs lib.CoordinateSet, subj interface{}) (sort.Interface, error) { +func (s *Server) newSorterByDistanceFrom(cs librtt.CoordinateSet, subj interface{}) (sort.Interface, error) { switch v := subj.(type) { case structs.Nodes: return s.newNodeSorter(cs, v) diff --git a/agent/consul/rtt_test.go b/agent/consul/rtt_test.go index aeed0b66f50d..1f4a19ddfe67 100644 --- a/agent/consul/rtt_test.go +++ b/agent/consul/rtt_test.go @@ -10,12 +10,12 @@ import ( "testing" "time" + msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc" + "github.com/hashicorp/consul-net-rpc/net/rpc" + "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/testrpc" - - "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc" - "github.com/hashicorp/consul-net-rpc/net/rpc" ) // verifyNodeSort makes sure the order of the nodes in the slice is the same as @@ -98,27 +98,27 @@ func seedCoordinates(t *testing.T, codec rpc.ClientCodec, server *Server) { { Datacenter: "dc1", Node: "node1", - Coord: lib.GenerateCoordinate(10 * time.Millisecond), + Coord: librtt.GenerateCoordinate(10 * time.Millisecond), }, { Datacenter: "dc1", Node: "node2", - Coord: lib.GenerateCoordinate(2 * time.Millisecond), + Coord: librtt.GenerateCoordinate(2 * time.Millisecond), }, { Datacenter: "dc1", Node: "node3", - Coord: lib.GenerateCoordinate(1 * time.Millisecond), + Coord: librtt.GenerateCoordinate(1 * time.Millisecond), }, { Datacenter: "dc1", Node: "node4", - Coord: lib.GenerateCoordinate(8 * time.Millisecond), + Coord: librtt.GenerateCoordinate(8 * time.Millisecond), }, { Datacenter: "dc1", Node: "node5", - Coord: lib.GenerateCoordinate(3 * time.Millisecond), + Coord: librtt.GenerateCoordinate(3 * time.Millisecond), }, } diff --git a/agent/consul/server.go b/agent/consul/server.go index 7986725b8016..979d9e3cd434 100644 --- a/agent/consul/server.go +++ b/agent/consul/server.go @@ -20,6 +20,12 @@ import ( "time" "github.com/armon/go-metrics" + "github.com/fullstorydev/grpchan/inprocgrpc" + "go.etcd.io/bbolt" + "golang.org/x/time/rate" + "google.golang.org/grpc" + + "github.com/hashicorp/consul-net-rpc/net/rpc" "github.com/hashicorp/go-connlimit" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-memdb" @@ -30,16 +36,10 @@ import ( walmetrics "github.com/hashicorp/raft-wal/metrics" "github.com/hashicorp/raft-wal/verifier" "github.com/hashicorp/serf/serf" - "go.etcd.io/bbolt" - "golang.org/x/time/rate" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/reflection" - "github.com/hashicorp/consul-net-rpc/net/rpc" "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/agent/blockingquery" + "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/authmethod" "github.com/hashicorp/consul/agent/consul/authmethod/ssoauth" "github.com/hashicorp/consul/agent/consul/fsm" @@ -51,42 +51,31 @@ import ( "github.com/hashicorp/consul/agent/consul/usagemetrics" "github.com/hashicorp/consul/agent/consul/wanfed" "github.com/hashicorp/consul/agent/consul/xdscapacity" - aclgrpc "github.com/hashicorp/consul/agent/grpc-external/services/acl" - "github.com/hashicorp/consul/agent/grpc-external/services/connectca" - "github.com/hashicorp/consul/agent/grpc-external/services/dataplane" "github.com/hashicorp/consul/agent/grpc-external/services/peerstream" - resourcegrpc "github.com/hashicorp/consul/agent/grpc-external/services/resource" - "github.com/hashicorp/consul/agent/grpc-external/services/serverdiscovery" - agentgrpc "github.com/hashicorp/consul/agent/grpc-internal" - "github.com/hashicorp/consul/agent/grpc-internal/services/subscribe" "github.com/hashicorp/consul/agent/hcp" + "github.com/hashicorp/consul/agent/hcp/bootstrap" hcpclient "github.com/hashicorp/consul/agent/hcp/client" logdrop "github.com/hashicorp/consul/agent/log-drop" "github.com/hashicorp/consul/agent/metadata" "github.com/hashicorp/consul/agent/pool" "github.com/hashicorp/consul/agent/router" "github.com/hashicorp/consul/agent/rpc/middleware" - "github.com/hashicorp/consul/agent/rpc/operator" "github.com/hashicorp/consul/agent/rpc/peering" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/token" - "github.com/hashicorp/consul/internal/auth" - "github.com/hashicorp/consul/internal/catalog" "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" + "github.com/hashicorp/consul/internal/gossip/librtt" + hcpctl "github.com/hashicorp/consul/internal/hcp" + "github.com/hashicorp/consul/internal/multicluster" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/internal/resource/reaper" + "github.com/hashicorp/consul/internal/storage" raftstorage "github.com/hashicorp/consul/internal/storage/raft" - "github.com/hashicorp/consul/internal/tenancy" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/routine" - "github.com/hashicorp/consul/lib/stringslice" "github.com/hashicorp/consul/logging" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/pbsubscribe" "github.com/hashicorp/consul/tlsutil" "github.com/hashicorp/consul/types" cslversion "github.com/hashicorp/consul/version" @@ -136,9 +125,6 @@ const ( reconcileChSize = 256 LeaderTransferMinVersion = "1.6.0" - - CatalogResourceExperimentName = "resource-apis" - V2TenancyExperimentName = "v2tenancy" ) const ( @@ -277,6 +263,9 @@ type Server struct { // raftStorageBackend is the Raft-backed storage backend for resources. raftStorageBackend *raftstorage.Backend + // the currently in use storage backend + storageBackend storage.Backend + // reconcileCh is used to pass events from the serf handler // into the leader manager, so that the strong state can be // updated @@ -292,20 +281,35 @@ type Server struct { // is only ever closed. leaveCh chan struct{} - // externalACLServer serves the ACL service exposed on the external gRPC port. - // It is also exposed on the internal multiplexed "server" port to enable - // RPC forwarding. - externalACLServer *aclgrpc.Server - - // externalConnectCAServer serves the Connect CA service exposed on the external - // gRPC port. It is also exposed on the internal multiplexed "server" port to - // enable RPC forwarding. - externalConnectCAServer *connectca.Server - // externalGRPCServer has a gRPC server exposed on the dedicated gRPC ports, as // opposed to the multiplexed "server" port which is served by grpcHandler. externalGRPCServer *grpc.Server + // insecureUnsafeGRPCChan is used to access gRPC services on the server without going + // through protobuf serialization/deserialization, performing any network IO or requiring + // authorization. This may be passed as the gRPC client conn to any standard gRPC client + // constructor instead of a standard network protocol based client conn. Using this as the + // client conn will cut down on CPU and memory usage for doing in-process gRPC but comes + // with the drawbacks that any data sent over this interface is inherently shared + // and both ends must cooperate with regards to the immutability. Therefore, in + // most cases the insecureSafeGRPCChannel should be used instead which will clone the protobuf + // types as they pass through. + insecureUnsafeGRPCChan *inprocgrpc.Channel + + // insecureSafeGRPCChan is used to access gRPC services on the server without going + // through the standard protobuf serialization/deserialization, performing network + // io or requiring authorization. This gRPC client conn implementation will still + // clone protobuf messages as they pass through and so the client and server + // implementations do not need to coordinate with regards to data immutability. + insecureSafeGRPCChan *inprocgrpc.Channel + + // secureSafeGRPCChan is used to access gRPC services on the server without going + // through the standard protobuf serialization/deserialization or performing network + // io. This gRPC client conn implementation will still clone protobuf messages as + // they pass through and so the client and server implementations do not need + // to coordinate with regards to data immutability. + secureSafeGRPCChan *inprocgrpc.Channel + // router is used to map out Consul servers in the WAN and in Consul // Enterprise user-defined areas. router *router.Router @@ -318,9 +322,9 @@ type Server struct { rpcConnLimiter connlimit.Limiter // Listener is used to listen for incoming connections - Listener net.Listener - grpcHandler connHandler - rpcServer *rpc.Server + Listener net.Listener + internalGRPCHandler connHandler + rpcServer *rpc.Server // incomingRPCLimiter rate-limits incoming net/rpc and gRPC calls. incomingRPCLimiter rpcRate.RequestLimitsHandler @@ -411,6 +415,9 @@ type Server struct { // Manager to handle starting/stopping go routines when establishing/revoking raft leadership leaderRoutineManager *routine.Manager + // registrator is an implemenation that translates serf events of Consul servers into catalog events + registrator ConsulRegistrator + // publisher is the EventPublisher to be shared amongst various server components. Events from // modifications to the FSM, autopilot and others will flow through here. If in the future we // need Events generated outside of the Server and all its components, then we could move @@ -420,45 +427,23 @@ type Server struct { // peeringBackend is shared between the external and internal gRPC services for peering peeringBackend *PeeringBackend - // operatorBackend is shared between the external and internal gRPC services for peering - operatorBackend *OperatorBackend - // peerStreamServer is a server used to handle peering streams from external clusters. peerStreamServer *peerstream.Server - // peeringServer handles peering RPC requests internal to this cluster, like generating peering tokens. - peeringServer *peering.Server - // xdsCapacityController controls the number of concurrent xDS streams the // server is able to handle. xdsCapacityController *xdscapacity.Controller // hcpManager handles pushing server status updates to the HashiCorp Cloud Platform when enabled - hcpManager *hcp.Manager + hcpManager *hcp.HCPManager // embedded struct to hold all the enterprise specific data EnterpriseServer - operatorServer *operator.Server // routineManager is responsible for managing longer running go routines // run by the Server routineManager *routine.Manager - // resourceServiceServer implements the Resource Service. - resourceServiceServer *resourcegrpc.Server - - // insecureResourceServiceClient is a client that can be used to communicate - // with the Resource Service in-process (i.e. not via the network) *without* - // auth. It should only be used for purely-internal workloads, such as - // controllers. - insecureResourceServiceClient pbresource.ResourceServiceClient - - // secureResourceServiceClient is a client that can be used to communicate - // with the Resource Service in-process (i.e. not via the network) *with* auth. - // It can be used to make requests to the Resource Service on behalf of the user - // (e.g. from the HTTP API). - secureResourceServiceClient pbresource.ResourceServiceClient - // controllerManager schedules the execution of controllers. controllerManager *controller.Manager @@ -466,11 +451,6 @@ type Server struct { reportingManager *reporting.ReportingManager registry resource.Registry - - useV2Resources bool - - // useV2Tenancy is tied to the "v2tenancy" feature flag. - useV2Tenancy bool } func (s *Server) DecrementBlockingQueries() uint64 { @@ -486,27 +466,16 @@ func (s *Server) IncrementBlockingQueries() uint64 { } type connHandler interface { + RegisterService(*grpc.ServiceDesc, any) Run() error Handle(conn net.Conn) Shutdown() error } -// ProxyUpdater is an interface for ProxyTracker. -type ProxyUpdater interface { - // PushChange allows pushing a computed ProxyState to xds for xds resource generation to send to a proxy. - PushChange(id *pbresource.ID, snapshot proxysnapshot.ProxySnapshot) error - - // ProxyConnectedToServer returns whether this id is connected to this server. If it is connected, it also returns - // the token as the first argument. - ProxyConnectedToServer(id *pbresource.ID) (string, bool) - - EventChannel() chan controller.Event -} - // NewServer is used to construct a new Consul server from the configuration // and extra options, potentially returning an error. func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, - incomingRPCLimiter rpcRate.RequestLimitsHandler, serverLogger hclog.InterceptLogger, proxyUpdater ProxyUpdater) (*Server, error) { + incomingRPCLimiter rpcRate.RequestLimitsHandler, serverLogger hclog.InterceptLogger) (*Server, error) { logger := flat.Logger if err := config.CheckProtocolVersion(); err != nil { return nil, err @@ -514,7 +483,7 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, if config.DataDir == "" && !config.DevMode { return nil, fmt.Errorf("Config must provide a DataDir") } - if err := config.CheckACL(); err != nil { + if err := config.CheckEnumStrings(); err != nil { return nil, err } @@ -559,8 +528,6 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, incomingRPCLimiter: incomingRPCLimiter, routineManager: routine.NewManager(logger.Named(logging.ConsulServer)), registry: flat.Registry, - useV2Resources: flat.UseV2Resources(), - useV2Tenancy: flat.UseV2Tenancy(), } incomingRPCLimiter.Register(s) @@ -570,6 +537,8 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, } go s.raftStorageBackend.Run(&lib.StopChannelContext{StopCh: shutdownCh}) + s.storageBackend = s.raftStorageBackend + s.fsm = fsm.NewFromDeps(fsm.Deps{ Logger: flat.Logger, NewStateStore: func() *state.Store { @@ -579,11 +548,34 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, StorageBackend: s.raftStorageBackend, }) - s.hcpManager = hcp.NewManager(hcp.ManagerConfig{ - Client: flat.HCP.Client, - StatusFn: s.hcpServerStatus(flat), - Logger: logger.Named("hcp_manager"), - }) + if s.config.Cloud.IsConfigured() { + s.hcpManager = hcp.NewManager(hcp.ManagerConfig{ + CloudConfig: flat.HCP.Config, + StatusFn: s.hcpServerStatus(flat), + Logger: logger.Named("hcp_manager"), + SCADAProvider: flat.HCP.Provider, + TelemetryProvider: flat.HCP.TelemetryProvider, + ManagementTokenUpserterFn: func(name, secretId string) error { + // Check the state of the server before attempting to upsert the token. Otherwise, + // the upsert will fail and log errors that do not require action from the user. + if s.config.ACLsEnabled && s.IsLeader() && s.InPrimaryDatacenter() { + // Idea for improvement: Upsert a token with a well-known accessorId here instead + // of a randomly generated one. This would prevent any possible insertion collision between + // this and the insertion that happens during the ACL initialization process (initializeACLs function) + return s.upsertManagementToken(name, secretId) + } + return nil + }, + ManagementTokenDeleterFn: func(secretId string) error { + // Check the state of the server before attempting to delete the token.Otherwise, + // the delete will fail and log errors that do not require action from the user. + if s.config.ACLsEnabled && s.IsLeader() && s.InPrimaryDatacenter() { + return s.deleteManagementToken(secretId) + } + return nil + }, + }) + } var recorder *middleware.RequestRecorder if flat.NewRequestRecorderFunc != nil { @@ -597,15 +589,7 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, rpcServerOpts := []func(*rpc.Server){ rpc.WithPreBodyInterceptor( - middleware.ChainedRPCPreBodyInterceptor( - func(reqServiceMethod string, sourceAddr net.Addr) error { - if s.useV2Resources && isV1CatalogRequest(reqServiceMethod) { - return structs.ErrUsingV2CatalogExperiment - } - return nil - }, - middleware.GetNetRPCRateLimitingInterceptor(s.incomingRPCLimiter, middleware.NewPanicHandler(s.logger)), - ), + middleware.GetNetRPCRateLimitingInterceptor(s.incomingRPCLimiter, middleware.NewPanicHandler(s.logger)), ), } @@ -708,7 +692,7 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, } // Initialize the Raft server. - if err := s.setupRaft(stringslice.Contains(flat.Experiments, CatalogResourceExperimentName)); err != nil { + if err := s.setupRaft(); err != nil { s.Shutdown() return nil, fmt.Errorf("Failed to start Raft: %v", err) } @@ -815,6 +799,7 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, WithStateProvider(s.fsm). WithLogger(s.logger). WithDatacenter(s.config.Datacenter). + WithDisabledTenancyMetrics(s.config.DisablePerTenancyUsageMetrics). WithReportingInterval(s.config.MetricsReportingInterval). WithGetMembersFunc(func() []serf.Member { members, err := s.lanPoolAllMembers() @@ -837,17 +822,13 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, s.reportingManager = reporting.NewReportingManager(s.logger, getEnterpriseReportingDeps(flat), s, s.fsm.State()) go s.reportingManager.Run(&lib.StopChannelContext{StopCh: s.shutdownCh}) - // Setup insecure resource service client. - if err := s.setupInsecureResourceServiceClient(flat.Registry, logger); err != nil { + // configure the server specific grpc interfaces (in-process + internal multiplexed grpc) + if err := s.setupGRPCInterfaces(config, flat); err != nil { return nil, err } - // Initialize external gRPC server - s.setupExternalGRPC(config, flat, logger) - - // Setup secure resource service client. We need to do it after we setup the - // gRPC server because it needs the server to be instantiated. - if err := s.setupSecureResourceServiceClient(); err != nil { + // register server specific grpc services with all the interfaces they should be exposed on. + if err := s.setupGRPCServices(config, flat); err != nil { return nil, err } @@ -855,14 +836,41 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, // // Note: some "external" gRPC services are also exposed on the internal gRPC server // to enable RPC forwarding. - s.grpcHandler = newGRPCHandlerFromConfig(flat, config, s) s.grpcLeaderForwarder = flat.LeaderForwarder + if s.config.Cloud.IsConfigured() { + // Start watching HCP Link resource. This needs to be created after + // the GRPC services are set up in order for the resource service client to + // function. This uses the insecure grpc channel so that it doesn't need to + // present a valid ACL token. + go hcp.RunHCPLinkWatcher( + &lib.StopChannelContext{StopCh: shutdownCh}, + logger.Named("hcp-link-watcher"), + pbresource.NewResourceServiceClient(s.insecureSafeGRPCChan), + hcp.HCPManagerLifecycleFn( + s.hcpManager, + hcpclient.NewClient, + bootstrap.LoadManagementToken, + flat.HCP.Config, + flat.HCP.DataDir, + ), + ) + } + s.controllerManager = controller.NewManager( - s.insecureResourceServiceClient, - logger.Named(logging.ControllerRuntime), + // Usage of the insecure + unsafe grpc chan is required for the controller + // manager. It must be unauthorized so that controllers do not need to + // present valid ACL tokens for their requests and it must use the unsafe + // variant so that the controller runtimes indexing/caching layer doesn't + // keep many copies of resources around in memory for long. Care will + // be taken within the controller manager to wrap this client with another + // which clones protobuf types passing through to ensure controllers + // cannot modify the canonical resource service data that has flowed + // through the storage backend. + pbresource.NewResourceServiceClient(s.insecureUnsafeGRPCChan), + s.loggers.Named(logging.ControllerRuntime), ) - if err := s.registerControllers(flat, proxyUpdater); err != nil { + if err := s.registerControllers(flat); err != nil { return nil, err } go s.controllerManager.Run(&lib.StopChannelContext{StopCh: shutdownCh}) @@ -880,13 +888,21 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, // as establishing leadership could attempt to use autopilot and cause a panic. s.initAutopilot(config) + s.registrator = V1ConsulRegistrator{ + Datacenter: s.config.Datacenter, + FSM: s.fsm, + Logger: serverLogger, + NodeName: s.config.NodeName, + RaftApplyFunc: s.raftApplyMsgpack, + } + // Start monitoring leadership. This must happen after Serf is set up // since it can fire events when leadership is obtained. go s.monitorLeadership() // Start listening for RPC requests. go func() { - if err := s.grpcHandler.Run(); err != nil { + if err := s.internalGRPCHandler.Run(); err != nil { s.logger.Error("gRPC server failed", "error", err) } }() @@ -904,9 +920,6 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, // Start the metrics handlers. go s.updateMetrics() - // Now we are setup, configure the HCP manager - go s.hcpManager.Run(&lib.StopChannelContext{StopCh: shutdownCh}) - err = s.runEnterpriseRateLimiterConfigEntryController() if err != nil { return nil, err @@ -915,73 +928,17 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, return s, nil } -func isV1CatalogRequest(rpcName string) bool { - switch { - case strings.HasPrefix(rpcName, "Catalog."), - strings.HasPrefix(rpcName, "Health."), - strings.HasPrefix(rpcName, "ConfigEntry."): - return true - } - - switch rpcName { - case "Internal.EventFire", "Internal.KeyringOperation", "Internal.OIDCAuthMethods": - return false - default: - if strings.HasPrefix(rpcName, "Internal.") { - return true - } - return false - } -} - -func (s *Server) registerControllers(deps Deps, proxyUpdater ProxyUpdater) error { - // When not enabled, the v1 tenancy bridge is used by default. - if s.useV2Tenancy { - tenancy.RegisterControllers( - s.controllerManager, - tenancy.Dependencies{Registry: deps.Registry}, +func (s *Server) registerControllers(deps Deps) error { + if s.config.Cloud.IsConfigured() { + hcpctl.RegisterControllers( + s.controllerManager, hcpctl.ControllerDependencies{ + CloudConfig: deps.HCP.Config, + }, ) } - if s.useV2Resources { - catalog.RegisterControllers(s.controllerManager, catalog.DefaultControllerDependencies()) - - defaultAllow, err := s.config.ACLResolverSettings.IsDefaultAllow() - if err != nil { - return err - } - - mesh.RegisterControllers(s.controllerManager, mesh.ControllerDependencies{ - TrustBundleFetcher: func() (*pbproxystate.TrustBundle, error) { - var bundle pbproxystate.TrustBundle - roots, err := s.getCARoots(nil, s.GetState()) - if err != nil { - return nil, err - } - bundle.TrustDomain = roots.TrustDomain - for _, root := range roots.Roots { - bundle.Roots = append(bundle.Roots, root.RootCert) - } - return &bundle, nil - }, - // This function is adapted from server_connect.go:getCARoots. - TrustDomainFetcher: func() (string, error) { - _, caConfig, err := s.fsm.State().CAConfig(nil) - if err != nil { - return "", err - } - - return s.getTrustDomain(caConfig) - }, - - LeafCertManager: deps.LeafCertManager, - LocalDatacenter: s.config.Datacenter, - DefaultAllow: defaultAllow, - ProxyUpdater: proxyUpdater, - }) - - auth.RegisterControllers(s.controllerManager, auth.DefaultControllerDependencies()) - } + shim := NewExportedServicesShim(s) + multicluster.RegisterCompatControllers(s.controllerManager, multicluster.DefaultCompatControllerDependencies(shim)) reaper.RegisterControllers(s.controllerManager) @@ -992,64 +949,6 @@ func (s *Server) registerControllers(deps Deps, proxyUpdater ProxyUpdater) error return s.controllerManager.ValidateDependencies(s.registry.Types()) } -func newGRPCHandlerFromConfig(deps Deps, config *Config, s *Server) connHandler { - if s.peeringBackend == nil { - panic("peeringBackend is required during construction") - } - - p := peering.NewServer(peering.Config{ - Backend: s.peeringBackend, - Tracker: s.peerStreamServer.Tracker, - Logger: deps.Logger.Named("grpc-api.peering"), - ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { - // Only forward the request if the dc in the request matches the server's datacenter. - if info.RequestDatacenter() != "" && info.RequestDatacenter() != config.Datacenter { - return false, fmt.Errorf("requests to generate peering tokens cannot be forwarded to remote datacenters") - } - return s.ForwardGRPC(s.grpcConnPool, info, fn) - }, - Datacenter: config.Datacenter, - ConnectEnabled: config.ConnectEnabled, - PeeringEnabled: config.PeeringEnabled, - Locality: config.Locality, - FSMServer: s, - }) - s.peeringServer = p - o := operator.NewServer(operator.Config{ - Backend: s.operatorBackend, - Logger: deps.Logger.Named("grpc-api.operator"), - ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { - // Only forward the request if the dc in the request matches the server's datacenter. - if info.RequestDatacenter() != "" && info.RequestDatacenter() != config.Datacenter { - return false, fmt.Errorf("requests to transfer leader cannot be forwarded to remote datacenters") - } - return s.ForwardGRPC(s.grpcConnPool, info, fn) - }, - Datacenter: config.Datacenter, - }) - s.operatorServer = o - - register := func(srv *grpc.Server) { - if config.RPCConfig.EnableStreaming { - pbsubscribe.RegisterStateChangeSubscriptionServer(srv, subscribe.NewServer( - &subscribeBackend{srv: s, connPool: deps.GRPCConnPool}, - deps.Logger.Named("grpc-api.subscription"))) - } - s.peeringServer.Register(srv) - s.operatorServer.Register(srv) - s.registerEnterpriseGRPCServices(deps, srv) - - // Note: these external gRPC services are also exposed on the internal server to - // enable RPC forwarding. - s.peerStreamServer.Register(srv) - s.externalACLServer.Register(srv) - s.externalConnectCAServer.Register(srv) - s.resourceServiceServer.Register(srv) - } - - return agentgrpc.NewHandler(deps.Logger, config.RPCAddr, register, nil, s.incomingRPCLimiter) -} - func (s *Server) connectCARootsMonitor(ctx context.Context) { for { ws := memdb.NewWatchSet() @@ -1076,7 +975,7 @@ func (s *Server) connectCARootsMonitor(ctx context.Context) { } // setupRaft is used to setup and initialize Raft -func (s *Server) setupRaft(isCatalogResourceExperiment bool) error { +func (s *Server) setupRaft() error { // If we have an unclean exit then attempt to close the Raft store. defer func() { if s.raft == nil && s.raftStore != nil { @@ -1157,7 +1056,7 @@ func (s *Server) setupRaft(isCatalogResourceExperiment bool) error { return nil } // Only use WAL if there is no existing raft.db, even if it's enabled. - if s.config.LogStoreConfig.Backend == LogStoreBackendDefault && !boltFileExists && isCatalogResourceExperiment { + if s.config.LogStoreConfig.Backend == LogStoreBackendDefault && !boltFileExists { s.config.LogStoreConfig.Backend = LogStoreBackendWAL if !s.config.LogStoreConfig.Verification.Enabled { s.config.LogStoreConfig.Verification.Enabled = true @@ -1399,169 +1298,6 @@ func (s *Server) setupRPC() error { return nil } -// Initialize and register services on external gRPC server. -func (s *Server) setupExternalGRPC(config *Config, deps Deps, logger hclog.Logger) { - s.externalACLServer = aclgrpc.NewServer(aclgrpc.Config{ - ACLsEnabled: s.config.ACLsEnabled, - ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { - return s.ForwardGRPC(s.grpcConnPool, info, fn) - }, - InPrimaryDatacenter: s.InPrimaryDatacenter(), - LoadAuthMethod: func(methodName string, entMeta *acl.EnterpriseMeta) (*structs.ACLAuthMethod, aclgrpc.Validator, error) { - return s.loadAuthMethod(methodName, entMeta) - }, - LocalTokensEnabled: s.LocalTokensEnabled, - Logger: logger.Named("grpc-api.acl"), - NewLogin: func() aclgrpc.Login { return s.aclLogin() }, - NewTokenWriter: func() aclgrpc.TokenWriter { return s.aclTokenWriter() }, - PrimaryDatacenter: s.config.PrimaryDatacenter, - ValidateEnterpriseRequest: s.validateEnterpriseRequest, - }) - s.externalACLServer.Register(s.externalGRPCServer) - - s.externalConnectCAServer = connectca.NewServer(connectca.Config{ - Publisher: s.publisher, - GetStore: func() connectca.StateStore { return s.FSM().State() }, - Logger: logger.Named("grpc-api.connect-ca"), - ACLResolver: s.ACLResolver, - CAManager: s.caManager, - ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { - return s.ForwardGRPC(s.grpcConnPool, info, fn) - }, - ConnectEnabled: s.config.ConnectEnabled, - }) - s.externalConnectCAServer.Register(s.externalGRPCServer) - - dataplane.NewServer(dataplane.Config{ - GetStore: func() dataplane.StateStore { return s.FSM().State() }, - Logger: logger.Named("grpc-api.dataplane"), - ACLResolver: s.ACLResolver, - Datacenter: s.config.Datacenter, - EnableV2: stringslice.Contains(deps.Experiments, CatalogResourceExperimentName), - ResourceAPIClient: s.insecureResourceServiceClient, - }).Register(s.externalGRPCServer) - - serverdiscovery.NewServer(serverdiscovery.Config{ - Publisher: s.publisher, - ACLResolver: s.ACLResolver, - Logger: logger.Named("grpc-api.server-discovery"), - }).Register(s.externalGRPCServer) - - s.peeringBackend = NewPeeringBackend(s) - s.operatorBackend = NewOperatorBackend(s) - - s.peerStreamServer = peerstream.NewServer(peerstream.Config{ - Backend: s.peeringBackend, - GetStore: func() peerstream.StateStore { return s.FSM().State() }, - Logger: logger.Named("grpc-api.peerstream"), - ACLResolver: s.ACLResolver, - Datacenter: s.config.Datacenter, - ConnectEnabled: s.config.ConnectEnabled, - ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { - // Only forward the request if the dc in the request matches the server's datacenter. - if info.RequestDatacenter() != "" && info.RequestDatacenter() != config.Datacenter { - return false, fmt.Errorf("requests to generate peering tokens cannot be forwarded to remote datacenters") - } - return s.ForwardGRPC(s.grpcConnPool, info, fn) - }, - }) - s.peerStreamServer.Register(s.externalGRPCServer) - - tenancyBridge := NewV1TenancyBridge(s) - if s.useV2Tenancy { - tenancyBridgeV2 := tenancy.NewV2TenancyBridge() - tenancyBridge = tenancyBridgeV2.WithClient(s.insecureResourceServiceClient) - } - - s.resourceServiceServer = resourcegrpc.NewServer(resourcegrpc.Config{ - Registry: deps.Registry, - Backend: s.raftStorageBackend, - ACLResolver: s.ACLResolver, - Logger: logger.Named("grpc-api.resource"), - TenancyBridge: tenancyBridge, - UseV2Tenancy: s.useV2Tenancy, - }) - s.resourceServiceServer.Register(s.externalGRPCServer) - - reflection.Register(s.externalGRPCServer) -} - -func (s *Server) setupInsecureResourceServiceClient(typeRegistry resource.Registry, logger hclog.Logger) error { - if s.raftStorageBackend == nil { - return fmt.Errorf("raft storage backend cannot be nil") - } - - // Can't use interface type var here since v2 specific "WithClient(...)" is called futher down. - tenancyBridge := NewV1TenancyBridge(s) - tenancyBridgeV2 := tenancy.NewV2TenancyBridge() - if s.useV2Tenancy { - tenancyBridge = tenancyBridgeV2 - } - server := resourcegrpc.NewServer(resourcegrpc.Config{ - Registry: typeRegistry, - Backend: s.raftStorageBackend, - ACLResolver: resolver.DANGER_NO_AUTH{}, - Logger: logger.Named("grpc-api.resource"), - TenancyBridge: tenancyBridge, - UseV2Tenancy: s.useV2Tenancy, - }) - - conn, err := s.runInProcessGRPCServer(server.Register) - if err != nil { - return err - } - s.insecureResourceServiceClient = pbresource.NewResourceServiceClient(conn) - tenancyBridgeV2.WithClient(s.insecureResourceServiceClient) - return nil -} - -func (s *Server) setupSecureResourceServiceClient() error { - if s.resourceServiceServer == nil { - return fmt.Errorf("resource service server cannot be nil") - } - conn, err := s.runInProcessGRPCServer(s.resourceServiceServer.Register) - if err != nil { - return err - } - s.secureResourceServiceClient = pbresource.NewResourceServiceClient(conn) - - return nil -} - -// runInProcessGRPCServer runs a gRPC server that can only be accessed in the -// same process, rather than over the network, using a pipe listener. -func (s *Server) runInProcessGRPCServer(registerFn ...func(*grpc.Server)) (*grpc.ClientConn, error) { - server := grpc.NewServer() - - for _, fn := range registerFn { - fn(server) - } - - pipe := agentgrpc.NewPipeListener() - go server.Serve(pipe) - - go func() { - <-s.shutdownCh - server.Stop() - }() - - conn, err := grpc.Dial("", - grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithContextDialer(pipe.DialContext), - grpc.WithBlock(), - ) - if err != nil { - server.Stop() - return nil, err - } - go func() { - <-s.shutdownCh - conn.Close() - }() - - return conn, nil -} - // Shutdown is used to shutdown the server func (s *Server) Shutdown() error { s.logger.Info("shutting down server") @@ -1608,8 +1344,8 @@ func (s *Server) Shutdown() error { s.Listener.Close() } - if s.grpcHandler != nil { - if err := s.grpcHandler.Shutdown(); err != nil { + if s.internalGRPCHandler != nil { + if err := s.internalGRPCHandler.Shutdown(); err != nil { s.logger.Warn("failed to stop gRPC server", "error", err) } } @@ -2088,13 +1824,13 @@ func (s *Server) Stats() map[string]map[string]string { // are ancillary members of. // // NOTE: This assumes coordinates are enabled, so check that before calling. -func (s *Server) GetLANCoordinate() (lib.CoordinateSet, error) { +func (s *Server) GetLANCoordinate() (librtt.CoordinateSet, error) { lan, err := s.serfLAN.GetCoordinate() if err != nil { return nil, err } - cs := lib.CoordinateSet{"": lan} + cs := librtt.CoordinateSet{"": lan} if err := s.addEnterpriseLANCoordinates(cs); err != nil { return nil, err } @@ -2212,8 +1948,10 @@ func (s *Server) trackLeaderChanges() { s.raftStorageBackend.LeaderChanged() s.controllerManager.SetRaftLeader(s.IsLeader()) - // Trigger sending an update to HCP status - s.hcpManager.SendUpdate() + if s.config.Cloud.IsConfigured() { + // Trigger sending an update to HCP status + s.hcpManager.SendUpdate() + } case <-s.shutdownCh: s.raft.DeregisterObserver(observer) return @@ -2233,24 +1971,9 @@ func (s *Server) hcpServerStatus(deps Deps) hcp.StatusCallback { status.RPCPort = s.config.RPCAddr.Port status.Datacenter = s.config.Datacenter - tlsCert := s.tlsConfigurator.Cert() - if tlsCert != nil { - status.TLS.Enabled = true - leaf := tlsCert.Leaf - if leaf == nil { - // Parse the leaf cert - leaf, err = x509.ParseCertificate(tlsCert.Certificate[0]) - if err != nil { - // Shouldn't be possible - return - } - } - status.TLS.CertName = leaf.Subject.CommonName - status.TLS.CertSerial = leaf.SerialNumber.String() - status.TLS.CertExpiry = leaf.NotAfter - status.TLS.VerifyIncoming = s.tlsConfigurator.VerifyIncomingRPC() - status.TLS.VerifyOutgoing = s.tlsConfigurator.Base().InternalRPC.VerifyOutgoing - status.TLS.VerifyServerHostname = s.tlsConfigurator.VerifyServerHostname() + err = addServerTLSInfo(&status, s.tlsConfigurator) + if err != nil { + return status, fmt.Errorf("error adding server tls info: %w", err) } status.Raft.IsLeader = s.raft.State() == raft.Leader @@ -2280,7 +2003,7 @@ func (s *Server) hcpServerStatus(deps Deps) hcp.StatusCallback { } func (s *Server) ResourceServiceClient() pbresource.ResourceServiceClient { - return s.secureResourceServiceClient + return pbresource.NewResourceServiceClient(s.secureSafeGRPCChan) } func fileExists(name string) (bool, error) { @@ -2339,6 +2062,83 @@ func convertConsulConfigToRateLimitHandlerConfig(limitsConfig RequestLimits, mul return hc } +// addServerTLSInfo adds the server's TLS information if available to the status +func addServerTLSInfo(status *hcpclient.ServerStatus, tlsConfigurator tlsutil.ConfiguratorIface) error { + tlsCert := tlsConfigurator.Cert() + if tlsCert == nil { + return nil + } + + leaf := tlsCert.Leaf + var err error + if leaf == nil { + // Parse the leaf cert + if len(tlsCert.Certificate) == 0 { + return fmt.Errorf("expected a leaf certificate but there was none") + } + leaf, err = x509.ParseCertificate(tlsCert.Certificate[0]) + if err != nil { + // Shouldn't be possible + return fmt.Errorf("error parsing leaf cert: %w", err) + } + } + + tlsInfo := hcpclient.ServerTLSInfo{ + Enabled: true, + CertIssuer: leaf.Issuer.CommonName, + CertName: leaf.Subject.CommonName, + CertSerial: leaf.SerialNumber.String(), + CertExpiry: leaf.NotAfter, + VerifyIncoming: tlsConfigurator.VerifyIncomingRPC(), + VerifyOutgoing: tlsConfigurator.Base().InternalRPC.VerifyOutgoing, + VerifyServerHostname: tlsConfigurator.VerifyServerHostname(), + } + + // Collect metadata for all CA certs used for internal RPC + metadata := make([]hcpclient.CertificateMetadata, 0) + for _, pemStr := range tlsConfigurator.ManualCAPems() { + cert, err := connect.ParseCert(pemStr) + if err != nil { + return fmt.Errorf("error parsing manual ca pem: %w", err) + } + + metadatum := hcpclient.CertificateMetadata{ + CertExpiry: cert.NotAfter, + CertName: cert.Subject.CommonName, + CertSerial: cert.SerialNumber.String(), + } + metadata = append(metadata, metadatum) + } + for ix, certBytes := range tlsCert.Certificate { + if ix == 0 { + // Skip the leaf cert at index 0. Only collect intermediates + continue + } + + cert, err := x509.ParseCertificate(certBytes) + if err != nil { + return fmt.Errorf("error parsing tls cert index %d: %w", ix, err) + } + + metadatum := hcpclient.CertificateMetadata{ + CertExpiry: cert.NotAfter, + CertName: cert.Subject.CommonName, + CertSerial: cert.SerialNumber.String(), + } + metadata = append(metadata, metadatum) + } + tlsInfo.CertificateAuthorities = metadata + + status.ServerTLSMetadata.InternalRPC = tlsInfo + + // TODO: remove status.TLS in preference for server.ServerTLSMetadata.InternalRPC + // when deprecation path is ready + // https://hashicorp.atlassian.net/browse/CC-7015 + status.TLS = tlsInfo + + return nil +} + // peersInfoContent is used to help operators understand what happened to the // peers.json file. This is written to a file called peers.info in the same // location. diff --git a/agent/consul/server_ce.go b/agent/consul/server_ce.go index fb3e55e76519..dae8dc1516c5 100644 --- a/agent/consul/server_ce.go +++ b/agent/consul/server_ce.go @@ -11,15 +11,18 @@ import ( "time" "github.com/armon/go-metrics" + "github.com/hashicorp/go-multierror" "github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/serf" - "google.golang.org/grpc" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/reporting" + resourcegrpc "github.com/hashicorp/consul/agent/grpc-external/services/resource" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/logging" ) // runEnterpriseRateLimiterConfigEntryController start the rate limiter config controller @@ -27,7 +30,9 @@ func (s *Server) runEnterpriseRateLimiterConfigEntryController() error { return nil } -func (s *Server) registerEnterpriseGRPCServices(deps Deps, srv *grpc.Server) {} +func (s *Server) setupEnterpriseGRPCServices(config *Config, deps Deps) error { + return nil +} func (s *Server) enterpriseValidateJoinWAN() error { return nil // no-op @@ -112,7 +117,7 @@ func (s *Server) GetMatchingLANCoordinate(_, _ string) (*coordinate.Coordinate, return s.serfLAN.GetCoordinate() } -func (s *Server) addEnterpriseLANCoordinates(cs lib.CoordinateSet) error { +func (s *Server) addEnterpriseLANCoordinates(cs librtt.CoordinateSet) error { return nil } @@ -191,3 +196,14 @@ func getEnterpriseReportingDeps(deps Deps) reporting.EntDeps { // no-op return reporting.EntDeps{} } + +// CE version without LicenseManager +func (s *Server) newResourceServiceConfig(typeRegistry resource.Registry, resolver resourcegrpc.ACLResolver, tenancyBridge resourcegrpc.TenancyBridge) resourcegrpc.Config { + return resourcegrpc.Config{ + Registry: typeRegistry, + Backend: s.storageBackend, + ACLResolver: resolver, + Logger: s.loggers.Named(logging.GRPCAPI).Named(logging.Resource), + TenancyBridge: tenancyBridge, + } +} diff --git a/agent/consul/server_grpc.go b/agent/consul/server_grpc.go new file mode 100644 index 000000000000..a190c44a0598 --- /dev/null +++ b/agent/consul/server_grpc.go @@ -0,0 +1,542 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package consul + +import ( + "fmt" + + "github.com/armon/go-metrics" + "github.com/fullstorydev/grpchan/inprocgrpc" + middleware "github.com/grpc-ecosystem/go-grpc-middleware" + recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" + + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/acl/resolver" + aclgrpc "github.com/hashicorp/consul/agent/grpc-external/services/acl" + "github.com/hashicorp/consul/agent/grpc-external/services/configentry" + "github.com/hashicorp/consul/agent/grpc-external/services/connectca" + "github.com/hashicorp/consul/agent/grpc-external/services/dataplane" + "github.com/hashicorp/consul/agent/grpc-external/services/peerstream" + resourcegrpc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + "github.com/hashicorp/consul/agent/grpc-external/services/serverdiscovery" + agentgrpc "github.com/hashicorp/consul/agent/grpc-internal" + "github.com/hashicorp/consul/agent/grpc-internal/services/subscribe" + agentmiddleware "github.com/hashicorp/consul/agent/grpc-middleware" + "github.com/hashicorp/consul/agent/rpc/operator" + "github.com/hashicorp/consul/agent/rpc/peering" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/logging" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/pbsubscribe" +) + +func (s *Server) setupGRPCInterfaces(config *Config, deps Deps) error { + // A server has 5 different gRPC interfaces + // + // * External - This is the main public gRPC network listener. This + // is an actual *grpc.Server that we have listening on both the + // grpc and grpc_tls ports. Generally this interface will not be + // used by the server itself. All services which are intended + // to be public APIs must be registered to this interface. This + // interface is created outside of the server in the agent code + // and then passed to the NewServer constructor. Some services + // like xDS and DNS get registered outside of the server code. + // + // * Internal / Multiplexed - Our internal_rpc port uses yamux and + // various byte prefixes to multiplex different protocols over + // the single connection. One of the multiplexed protocols is + // gRPC. gRPC in this fashion works using a custom net.Listener + // implementation that receives net.Conns to be handled through + // a channel. When a new yamux session is opened which produces + // a yamux conn (which implements the net.Conn interface), the + // connection is then sent to the custom listener. Then the + // standard grpc.Server.Serve method can accept the conn from + // the listener and operate on it like any other standard conn. + // Historically, the external gRPC interface was optional and + // so all services which needed leader or DC forwarding had to + // be exposed on this interface in order to guarantee they + // would be available. In the future, an external gRPC interface + // likely will be required and the services which need registering + // to the multiplexed listener will be greatly reduced. In the + // very long term we want to get rid of this internal multiplexed + // port/listener and instead have all component communications use + // gRPC natively. For now though, if your service will need to + // RECEIVE forwarded requests then it must be registered to this + // interface. + // + // * In-Process - For routines running on the server we don't want them + // to require network i/o as that will incur a lot of unnecessary + // overhead. To avoid that we are utilizing the `grpchan` library + // (github.com/fullstorydev/grpchan) and its `inprocgrpc` package. + // The library provides the `inprocgrpc.Channel` which implements + // both the `grpc.ServiceRegistrar` and `grpc.ClientConnInterface` + // interfaces. Services get registered to the `Channel` and then + // gRPC service clients can be created with the `Channel` used + // for the backing `ClientConn`. When a client then uses the + // `Invoke` or `NewStream` methods on the `Channel`, the `Channel` + // will lookup in its registry of services to find the service's + // server implementation and then have the standard + // grpc.MethodDesc.Handler function handle the request. We use + // a few variants of the in-process gRPC Channel. For now all + // these channels are created and managed in server code but we + // may need to move these into the higher level agent setup. + // + // * Insecure + Unsafe - The insecure + unsafe gRPC Channel has + // services registered to it that wont do typical ACL + // resolution. Instead when the service resolves ACL tokens + // a resolver is used which always grants unrestricted + // privileges. Additionally, this "unsafe" variant DOES + // NOT clone resources as they pass through the channel. Care + // Must be taken to note mutate the data passed through the + // Channel or else we could easily cause data race related + // or consistency bugs. + // + // * Insecure + Safe - Similar to the Insecure + Unsafe variant, + // ACL resolution always provides an authorizer with unrestricted + // privileges. However, this interface is concurrency/memory safe + // in that protobuf messages passing through the interface are + // cloned so that the client is free to mutate those messages + // once the request is complete. All services registered to the + // Unsafe variant should also be registered to this interface. + // + // * Secure + Safe - This Channel will do typical ACL resolution from + // tokens and will clone protobuf messages that pass through. This + // interface will be useful for something like the HTTP server that + // is crafting the gRPC requests from a user request and wants to + // assume no implicit privileges by the nature of running on the + // server. All services registered to the insecure variants should + // also be registered to this interface. Additionally other services + // that correspond to user requests should also be registered to this + // interface. + // + // Currently there is not a need for a Secure + Unsafe variant. We could + // add it if needed in the future. + + recoveryOpts := agentmiddleware.PanicHandlerMiddlewareOpts(s.loggers.Named(logging.GRPCAPI)) + + inprocLabels := []metrics.Label{{ + Name: "server_type", + Value: "in-process", + }} + + statsHandler := agentmiddleware.NewStatsHandler(metrics.Default(), inprocLabels) + + // TODO(inproc-grpc) - figure out what to do with rate limiting inproc grpc. If we + // want to rate limit in-process clients then we are going to need a unary interceptor + // to do that. Another idea would be to create rate limited clients which can be given + // to controllers or other internal code so that the whole Channel isn't limited but + // rather individual consumers of that channel. + + // Build the Insecure + Unsafe gRPC Channel + s.insecureUnsafeGRPCChan = new(inprocgrpc.Channel). + // Bypass the in-process gRPCs cloning functionality by providing + // a Cloner implementation which doesn't actually clone the data. + // Note that this is only done for the Unsafe gRPC Channel and + // all the Safe variants will utilize the default cloning + // functionality. + WithCloner(inprocgrpc.CloneFunc(func(in any) (any, error) { + return in, nil + })). + WithServerUnaryInterceptor(middleware.ChainUnaryServer( + recovery.UnaryServerInterceptor(recoveryOpts...), + statsHandler.Intercept, + )). + WithServerStreamInterceptor(middleware.ChainStreamServer( + recovery.StreamServerInterceptor(recoveryOpts...), + agentmiddleware.NewActiveStreamCounter(metrics.Default(), inprocLabels).Intercept, + )) + + // Build the Insecure + Safe gRPC Channel + s.insecureSafeGRPCChan = new(inprocgrpc.Channel). + WithServerUnaryInterceptor(middleware.ChainUnaryServer( + recovery.UnaryServerInterceptor(recoveryOpts...), + statsHandler.Intercept, + )). + WithServerStreamInterceptor(middleware.ChainStreamServer( + recovery.StreamServerInterceptor(recoveryOpts...), + agentmiddleware.NewActiveStreamCounter(metrics.Default(), inprocLabels).Intercept, + )) + + // Build the Secure + Safe gRPC Channel + s.secureSafeGRPCChan = new(inprocgrpc.Channel). + WithServerUnaryInterceptor(middleware.ChainUnaryServer( + recovery.UnaryServerInterceptor(recoveryOpts...), + statsHandler.Intercept, + )). + WithServerStreamInterceptor(middleware.ChainStreamServer( + recovery.StreamServerInterceptor(recoveryOpts...), + agentmiddleware.NewActiveStreamCounter(metrics.Default(), inprocLabels).Intercept, + )) + + // create the internal multiplexed gRPC interface + s.internalGRPCHandler = agentgrpc.NewHandler(deps.Logger, config.RPCAddr, nil, s.incomingRPCLimiter) + + return nil +} + +func (s *Server) setupGRPCServices(config *Config, deps Deps) error { + // Register the resource service with the in-process registrars WITHOUT AUTHORIZATION + err := s.registerResourceServiceServer( + deps.Registry, + resolver.DANGER_NO_AUTH{}, + s.insecureUnsafeGRPCChan, + s.insecureSafeGRPCChan) + if err != nil { + return err + } + + // Register the resource service with all other registrars other + // than the internal/multiplexed interface. Currently there is + // no need to forward resource service RPCs and therefore the + // service doesn't need to be available on that interface. + err = s.registerResourceServiceServer( + deps.Registry, + s.ACLResolver, + s.secureSafeGRPCChan, + s.internalGRPCHandler, + s.externalGRPCServer, + ) + if err != nil { + return err + } + + // The ACL grpc services get registered with all "secure" gRPC interfaces + err = s.registerACLServer( + s.secureSafeGRPCChan, + s.externalGRPCServer, + s.internalGRPCHandler, + ) + if err != nil { + return err + } + + // register the Connect CA service on all "secure" interfaces + err = s.registerConnectCAServer( + s.secureSafeGRPCChan, + s.externalGRPCServer, + s.internalGRPCHandler, + ) + if err != nil { + return err + } + + // Initializing the peering backend must be done before + // creating any peering servers. There is other code which + // calls methods on this and so the backend must be stored + // on the Server type. In the future we should investigate + // whether we can not require the backend in that other code. + s.peeringBackend = NewPeeringBackend(s) + + // register the peering service on the external gRPC server only + // As this service is only ever accessed externally there is + // no need to register it on the various in-process Channels + s.peerStreamServer, err = s.registerPeerStreamServer( + config, + s.externalGRPCServer, + s.internalGRPCHandler, + ) + if err != nil { + return err + } + + // register the peering service on the internal interface only. As + // the peering gRPC service is a private API its only ever accessed + // via the internalGRPCHandler with an actual network conn managed + // by the Agents GRPCConnPool. + err = s.registerPeeringServer( + config, + s.internalGRPCHandler, + ) + if err != nil { + return err + } + + // Register the Operator service on all "secure" interfaces. The + // operator service is currently only accessed via the + // internalGRPCHandler but in the future these APIs are likely to + // become part of our "public" API and so it should be exposed on + // more interfaces. + err = s.registerOperatorServer( + config, + deps, + s.internalGRPCHandler, + s.secureSafeGRPCChan, + s.externalGRPCServer, + ) + if err != nil { + return err + } + + // register the stream subscription service on the multiplexed internal interface + // if stream is enabled. + if config.RPCConfig.EnableStreaming { + err = s.registerStreamSubscriptionServer( + deps, + s.internalGRPCHandler, + ) + if err != nil { + return err + } + } + + // register the server discovery service on all "secure" interfaces other + // than the multiplexed internal interface. This service is mainly consumed + // by the consul-server-connection-manager library which is used by various + // other system components other than the agent. + err = s.registerServerDiscoveryServer( + s.ACLResolver, + s.secureSafeGRPCChan, + s.externalGRPCServer, + ) + if err != nil { + return err + } + + // register the server discovery service on the insecure in-process channels. + // Currently, this is unused but eventually things such as the peering service + // should be refactored to consume the in-memory service instead of hooking + // directly into an the event publisher and subscribing to specific events. + err = s.registerServerDiscoveryServer( + resolver.DANGER_NO_AUTH{}, + s.insecureUnsafeGRPCChan, + s.insecureSafeGRPCChan, + ) + if err != nil { + return err + } + + // register the data plane service on the external gRPC server only. This + // service is only access by dataplanes and at this time there is no need + // for anything internal in Consul to use the service. If that changes + // we could register it on the in-process interfaces as well. + err = s.registerDataplaneServer( + s.externalGRPCServer, + ) + if err != nil { + return err + } + + // register the configEntry service on the internal interface only. As + // it is only accessed via the internalGRPCHandler with an actual network + // conn managed by the Agents GRPCConnPool. + err = s.registerConfigEntryServer( + s.internalGRPCHandler, + ) + if err != nil { + return err + } + + // enable grpc server reflection for the external gRPC interface only + reflection.Register(s.externalGRPCServer) + + return s.setupEnterpriseGRPCServices(config, deps) +} + +func (s *Server) registerResourceServiceServer(typeRegistry resource.Registry, resolver resourcegrpc.ACLResolver, registrars ...grpc.ServiceRegistrar) error { + if s.storageBackend == nil { + return fmt.Errorf("storage backend cannot be nil") + } + + tenancyBridge := NewV1TenancyBridge(s) + + // Create the Resource Service Server + srv := resourcegrpc.NewServer(s.newResourceServiceConfig(typeRegistry, resolver, tenancyBridge)) + + // Register the server to all the desired interfaces + for _, reg := range registrars { + pbresource.RegisterResourceServiceServer(reg, srv) + } + return nil +} + +func (s *Server) registerACLServer(registrars ...grpc.ServiceRegistrar) error { + srv := aclgrpc.NewServer(aclgrpc.Config{ + ACLsEnabled: s.config.ACLsEnabled, + ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { + return s.ForwardGRPC(s.grpcConnPool, info, fn) + }, + InPrimaryDatacenter: s.InPrimaryDatacenter(), + LoadAuthMethod: func(methodName string, entMeta *acl.EnterpriseMeta) (*structs.ACLAuthMethod, aclgrpc.Validator, error) { + return s.loadAuthMethod(methodName, entMeta) + }, + LocalTokensEnabled: s.LocalTokensEnabled, + Logger: s.loggers.Named(logging.GRPCAPI).Named(logging.ACL), + NewLogin: func() aclgrpc.Login { return s.aclLogin() }, + NewTokenWriter: func() aclgrpc.TokenWriter { return s.aclTokenWriter() }, + PrimaryDatacenter: s.config.PrimaryDatacenter, + ValidateEnterpriseRequest: s.validateEnterpriseRequest, + }) + + for _, reg := range registrars { + srv.Register(reg) + } + + return nil +} + +func (s *Server) registerPeerStreamServer(config *Config, registrars ...grpc.ServiceRegistrar) (*peerstream.Server, error) { + if s.peeringBackend == nil { + panic("peeringBackend is required during construction") + } + + srv := peerstream.NewServer(peerstream.Config{ + Backend: s.peeringBackend, + GetStore: func() peerstream.StateStore { return s.FSM().State() }, + Logger: s.loggers.Named(logging.GRPCAPI).Named(logging.PeerStream), + ACLResolver: s.ACLResolver, + Datacenter: s.config.Datacenter, + ConnectEnabled: s.config.ConnectEnabled, + ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { + // Only forward the request if the dc in the request matches the server's datacenter. + if info.RequestDatacenter() != "" && info.RequestDatacenter() != config.Datacenter { + return false, fmt.Errorf("requests to generate peering tokens cannot be forwarded to remote datacenters") + } + return s.ForwardGRPC(s.grpcConnPool, info, fn) + }, + }) + + for _, reg := range registrars { + srv.Register(reg) + } + + return srv, nil +} + +func (s *Server) registerPeeringServer(config *Config, registrars ...grpc.ServiceRegistrar) error { + if s.peeringBackend == nil { + panic("peeringBackend is required during construction") + } + + if s.peerStreamServer == nil { + panic("the peer stream server must be configured before the peering server") + } + + srv := peering.NewServer(peering.Config{ + Backend: s.peeringBackend, + Tracker: s.peerStreamServer.Tracker, + Logger: s.loggers.Named(logging.GRPCAPI).Named(logging.Peering), + ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { + // Only forward the request if the dc in the request matches the server's datacenter. + if info.RequestDatacenter() != "" && info.RequestDatacenter() != config.Datacenter { + return false, fmt.Errorf("requests to generate peering tokens cannot be forwarded to remote datacenters") + } + return s.ForwardGRPC(s.grpcConnPool, info, fn) + }, + Datacenter: config.Datacenter, + ConnectEnabled: config.ConnectEnabled, + PeeringEnabled: config.PeeringEnabled, + Locality: config.Locality, + FSMServer: s, + }) + + for _, reg := range registrars { + srv.Register(reg) + } + + return nil +} + +func (s *Server) registerOperatorServer(config *Config, deps Deps, registrars ...grpc.ServiceRegistrar) error { + srv := operator.NewServer(operator.Config{ + Backend: NewOperatorBackend(s), + Logger: deps.Logger.Named("grpc-api.operator"), + ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { + // Only forward the request if the dc in the request matches the server's datacenter. + if info.RequestDatacenter() != "" && info.RequestDatacenter() != config.Datacenter { + return false, fmt.Errorf("requests to transfer leader cannot be forwarded to remote datacenters") + } + return s.ForwardGRPC(s.grpcConnPool, info, fn) + }, + Datacenter: config.Datacenter, + }) + + for _, reg := range registrars { + srv.Register(reg) + } + + return nil +} + +func (s *Server) registerStreamSubscriptionServer(deps Deps, registrars ...grpc.ServiceRegistrar) error { + srv := subscribe.NewServer( + &subscribeBackend{srv: s, connPool: deps.GRPCConnPool}, + s.loggers.Named(logging.GRPCAPI).Named("subscription"), + ) + + for _, reg := range registrars { + pbsubscribe.RegisterStateChangeSubscriptionServer(reg, srv) + } + + return nil +} + +func (s *Server) registerConnectCAServer(registrars ...grpc.ServiceRegistrar) error { + srv := connectca.NewServer(connectca.Config{ + Publisher: s.publisher, + GetStore: func() connectca.StateStore { return s.FSM().State() }, + Logger: s.loggers.Named(logging.GRPCAPI).Named(logging.ConnectCA), + ACLResolver: s.ACLResolver, + CAManager: s.caManager, + ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { + return s.ForwardGRPC(s.grpcConnPool, info, fn) + }, + ConnectEnabled: s.config.ConnectEnabled, + }) + + for _, reg := range registrars { + srv.Register(reg) + } + + return nil +} + +func (s *Server) registerDataplaneServer(registrars ...grpc.ServiceRegistrar) error { + srv := dataplane.NewServer(dataplane.Config{ + GetStore: func() dataplane.StateStore { return s.FSM().State() }, + Logger: s.loggers.Named(logging.GRPCAPI).Named(logging.Dataplane), + ACLResolver: s.ACLResolver, + Datacenter: s.config.Datacenter, + }) + + for _, reg := range registrars { + srv.Register(reg) + } + + return nil +} + +func (s *Server) registerServerDiscoveryServer(resolver serverdiscovery.ACLResolver, registrars ...grpc.ServiceRegistrar) error { + srv := serverdiscovery.NewServer(serverdiscovery.Config{ + Publisher: s.publisher, + ACLResolver: resolver, + Logger: s.loggers.Named(logging.GRPCAPI).Named(logging.ServerDiscovery), + }) + + for _, reg := range registrars { + srv.Register(reg) + } + + return nil +} + +func (s *Server) registerConfigEntryServer(registrars ...grpc.ServiceRegistrar) error { + + srv := configentry.NewServer(configentry.Config{ + Backend: NewConfigEntryBackend(s), + Logger: s.loggers.Named(logging.GRPCAPI).Named(logging.ConfigEntry), + ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { + return s.ForwardGRPC(s.grpcConnPool, info, fn) + }, + FSMServer: s, + }) + + for _, reg := range registrars { + srv.Register(reg) + } + + return nil +} diff --git a/agent/consul/server_metadata.go b/agent/consul/server_metadata.go index 03e4751a290c..b9a4eaf2eb39 100644 --- a/agent/consul/server_metadata.go +++ b/agent/consul/server_metadata.go @@ -8,6 +8,8 @@ import ( "io" "os" "time" + + "github.com/rboyer/safeio" ) // ServerMetadataFile is the name of the file on disk that server metadata @@ -31,7 +33,7 @@ func (md *ServerMetadata) IsLastSeenStale(d time.Duration) bool { // OpenServerMetadata is a helper function for opening the server metadata file // with the correct permissions. func OpenServerMetadata(filename string) (io.WriteCloser, error) { - return os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + return safeio.OpenFile(filename, 0600) } type ServerMetadataReadFunc func(filename string) (*ServerMetadata, error) diff --git a/agent/consul/server_metadata_test.go b/agent/consul/server_metadata_test.go index bf993bc1be57..a263902a2ce2 100644 --- a/agent/consul/server_metadata_test.go +++ b/agent/consul/server_metadata_test.go @@ -6,6 +6,7 @@ package consul import ( "bytes" "errors" + "os" "testing" "time" @@ -66,3 +67,35 @@ func TestWriteServerMetadata(t *testing.T) { assert.True(t, b.Len() > 0) }) } + +func TestWriteServerMetadata_MultipleTimes(t *testing.T) { + file, err := os.CreateTemp("", "server_metadata.json") + assert.NoError(t, err) + defer os.Remove(file.Name()) + + // prepare some data in server_metadata.json + _, err = OpenServerMetadata(file.Name()) + assert.NoError(t, err) + err = WriteServerMetadata(file) + assert.NoError(t, err) + stat, err := file.Stat() + assert.NoError(t, err) + + t.Run("reopen not truncate file", func(t *testing.T) { + _, err = OpenServerMetadata(file.Name()) + assert.NoError(t, err) + + // file size unchanged + stat2, err := file.Stat() + assert.NoError(t, err) + assert.Equal(t, stat.Size(), stat2.Size()) + }) + + t.Run("write updates the file", func(t *testing.T) { + err = WriteServerMetadata(file) + assert.NoError(t, err) + stat2, err := file.Stat() + assert.NoError(t, err) + assert.Equal(t, stat2.ModTime(), stat2.ModTime()) + }) +} diff --git a/agent/consul/server_serf.go b/agent/consul/server_serf.go index aea50aa6dd19..ec2ad94688f4 100644 --- a/agent/consul/server_serf.go +++ b/agent/consul/server_serf.go @@ -12,6 +12,7 @@ import ( "time" "github.com/armon/go-metrics" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/memberlist" "github.com/hashicorp/raft" @@ -20,8 +21,8 @@ import ( "github.com/hashicorp/consul/agent/consul/wanfed" "github.com/hashicorp/consul/agent/metadata" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/internal/gossip/libserf" "github.com/hashicorp/consul/lib" - libserf "github.com/hashicorp/consul/lib/serf" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/types" ) diff --git a/agent/consul/server_test.go b/agent/consul/server_test.go index 95fa102d4a46..f157fa6dd517 100644 --- a/agent/consul/server_test.go +++ b/agent/consul/server_test.go @@ -5,12 +5,11 @@ package consul import ( "context" + "crypto/tls" "crypto/x509" - "flag" "fmt" "net" "os" - "path/filepath" "reflect" "strings" "sync" @@ -20,10 +19,6 @@ import ( "github.com/armon/go-metrics" "github.com/google/tcpproxy" - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-uuid" - "github.com/hashicorp/memberlist" - "github.com/hashicorp/raft" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "golang.org/x/time/rate" @@ -31,6 +26,10 @@ import ( "google.golang.org/grpc/keepalive" "github.com/hashicorp/consul-net-rpc/net/rpc" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/memberlist" + "github.com/hashicorp/raft" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/multilimiter" @@ -38,12 +37,12 @@ import ( external "github.com/hashicorp/consul/agent/grpc-external" grpcmiddleware "github.com/hashicorp/consul/agent/grpc-middleware" hcpclient "github.com/hashicorp/consul/agent/hcp/client" + hcpconfig "github.com/hashicorp/consul/agent/hcp/config" "github.com/hashicorp/consul/agent/leafcert" "github.com/hashicorp/consul/agent/metadata" "github.com/hashicorp/consul/agent/rpc/middleware" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/token" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/sdk/freeport" "github.com/hashicorp/consul/sdk/testutil" @@ -120,7 +119,7 @@ func waitForLeaderEstablishment(t *testing.T, servers ...*Server) { }) } -func testServerConfig(t *testing.T) (string, *Config) { +func testServerConfig(t testutil.TestingTB) (string, *Config) { dir := testutil.TempDir(t, "consul") config := DefaultConfig() @@ -229,6 +228,12 @@ func testServerDCExpect(t *testing.T, dc string, expect int) (string, *Server) { } func testServerWithConfig(t *testing.T, configOpts ...func(*Config)) (string, *Server) { + return testServerWithDepsAndConfig(t, nil, configOpts...) +} + +// testServerWithDepsAndConfig is similar to testServerWithConfig except that it also allows modifying dependencies. +// This is useful for things like injecting experiment flags. +func testServerWithDepsAndConfig(t *testing.T, depOpts func(*Deps), configOpts ...func(*Config)) (string, *Server) { var dir string var srv *Server @@ -236,7 +241,7 @@ func testServerWithConfig(t *testing.T, configOpts ...func(*Config)) (string, *S var deps Deps // Retry added to avoid cases where bind addr is already in use retry.RunWith(retry.ThreeTimes(), t, func(r *retry.R) { - dir, config = testServerConfig(t) + dir, config = testServerConfig(r) for _, fn := range configOpts { fn(config) } @@ -249,8 +254,13 @@ func testServerWithConfig(t *testing.T, configOpts ...func(*Config)) (string, *S config.ACLResolverSettings.EnterpriseMeta = *config.AgentEnterpriseMeta() var err error - deps = newDefaultDeps(t, config) - srv, err = newServerWithDeps(t, config, deps) + deps = newDefaultDeps(r, config) + + if depOpts != nil { + depOpts(&deps) + } + + srv, err = newServerWithDeps(r, config, deps) if err != nil { r.Fatalf("err: %v", err) } @@ -330,7 +340,7 @@ func newServer(t *testing.T, c *Config) (*Server, error) { return newServerWithDeps(t, c, newDefaultDeps(t, c)) } -func newServerWithDeps(t *testing.T, c *Config, deps Deps) (*Server, error) { +func newServerWithDeps(t testutil.TestingTB, c *Config, deps Deps) (*Server, error) { // chain server up notification oldNotify := c.NotifyListen up := make(chan struct{}) @@ -340,9 +350,8 @@ func newServerWithDeps(t *testing.T, c *Config, deps Deps) (*Server, error) { oldNotify() } } - grpcServer := external.NewServer(deps.Logger.Named("grpc.external"), nil, deps.TLSConfigurator, rpcRate.NullRequestLimitsHandler(), keepalive.ServerParameters{}) - proxyUpdater := proxytracker.NewProxyTracker(proxytracker.ProxyTrackerConfig{}) - srv, err := NewServer(c, deps, grpcServer, nil, deps.Logger, proxyUpdater) + grpcServer := external.NewServer(deps.Logger.Named("grpc.external"), nil, deps.TLSConfigurator, rpcRate.NullRequestLimitsHandler(), keepalive.ServerParameters{}, nil) + srv, err := NewServer(c, deps, grpcServer, nil, deps.Logger) if err != nil { return nil, err } @@ -1249,7 +1258,7 @@ func TestServer_RPC_MetricsIntercept_Off(t *testing.T) { } } - s1, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger, nil) + s1, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger) if err != nil { t.Fatalf("err: %v", err) } @@ -1287,7 +1296,7 @@ func TestServer_RPC_MetricsIntercept_Off(t *testing.T) { return nil } - s2, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger, nil) + s2, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger) if err != nil { t.Fatalf("err: %v", err) } @@ -1321,7 +1330,7 @@ func TestServer_RPC_RequestRecorder(t *testing.T) { deps := newDefaultDeps(t, conf) deps.NewRequestRecorderFunc = nil - s1, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger, nil) + s1, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger) require.Error(t, err, "need err when provider func is nil") require.Equal(t, err.Error(), "cannot initialize server without an RPC request recorder provider") @@ -1340,7 +1349,7 @@ func TestServer_RPC_RequestRecorder(t *testing.T) { return nil } - s2, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger, nil) + s2, err := NewServer(conf, deps, grpc.NewServer(), nil, deps.Logger) require.Error(t, err, "need err when RequestRecorder is nil") require.Equal(t, err.Error(), "cannot initialize server with a nil RPC request recorder") @@ -2085,8 +2094,13 @@ func TestServer_Peering_LeadershipCheck(t *testing.T) { func TestServer_hcpManager(t *testing.T) { _, conf1 := testServerConfig(t) + + // Configure the server for the StatusFn conf1.BootstrapExpect = 1 conf1.RPCAdvertise = &net.TCPAddr{IP: []byte{127, 0, 0, 2}, Port: conf1.RPCAddr.Port} + conf1.Cloud.ClientID = "test-client-id" + conf1.Cloud.ResourceID = "test-resource-id" + conf1.Cloud.ClientSecret = "test-client-secret" hcp1 := hcpclient.NewMockClient(t) hcp1.EXPECT().PushServerStatus(mock.Anything, mock.MatchedBy(func(status *hcpclient.ServerStatus) bool { return status.ID == string(conf1.NodeID) @@ -2094,8 +2108,10 @@ func TestServer_hcpManager(t *testing.T) { require.Equal(t, status.LanAddress, "127.0.0.2") }).Call.Return(nil) + // Configure the server for the ManagementTokenUpserterFn + conf1.ACLsEnabled = true + deps1 := newDefaultDeps(t, conf1) - deps1.HCP.Client = hcp1 s1, err := newServerWithDeps(t, conf1, deps1) if err != nil { t.Fatalf("err: %v", err) @@ -2103,30 +2119,197 @@ func TestServer_hcpManager(t *testing.T) { defer s1.Shutdown() require.NotNil(t, s1.hcpManager) waitForLeaderEstablishment(t, s1) + + // Update the HCP manager and start it + token, err := uuid.GenerateUUID() + require.NoError(t, err) + s1.hcpManager.UpdateConfig(hcp1, hcpconfig.CloudConfig{ + ManagementToken: token, + }) + err = s1.hcpManager.Start(context.Background()) + require.NoError(t, err) + + // Validate that the server status pushed as expected hcp1.AssertExpectations(t) + // Validate that the HCP token has been created as expected + retry.Run(t, func(r *retry.R) { + _, createdToken, err := s1.fsm.State().ACLTokenGetBySecret(nil, token, nil) + require.NoError(r, err) + require.NotNil(r, createdToken) + }) + + // Stop the HCP manager + err = s1.hcpManager.Stop() + require.NoError(t, err) + + // Validate that the HCP token has been deleted as expected + retry.Run(t, func(r *retry.R) { + _, createdToken, err := s1.fsm.State().ACLTokenGetBySecret(nil, token, nil) + require.NoError(r, err) + require.Nil(r, createdToken) + }) } -// goldenMarkdown reads and optionally writes the expected data to the goldenMarkdown file, -// returning the contents as a string. -func goldenMarkdown(t *testing.T, name, got string) string { - t.Helper() +func TestServer_addServerTLSInfo(t *testing.T) { + testCases := map[string]struct { + errMsg string + setupConfigurator func(*testing.T) tlsutil.ConfiguratorIface + checkStatus func(*testing.T, hcpclient.ServerStatus) + }{ + "Success": { + setupConfigurator: func(t *testing.T) tlsutil.ConfiguratorIface { + tlsConfig := tlsutil.Config{ + InternalRPC: tlsutil.ProtocolConfig{ + CAFile: "../../test/ca/root.cer", + CertFile: "../../test/key/ourdomain_with_intermediate.cer", + KeyFile: "../../test/key/ourdomain.key", + VerifyIncoming: true, + VerifyOutgoing: true, + VerifyServerHostname: true, + }, + } - golden := filepath.Join("testdata", name+".md") - update := flag.Lookup("update").Value.(flag.Getter).Get().(bool) - if update && got != "" { - err := os.WriteFile(golden, []byte(got), 0644) - require.NoError(t, err) - } + tlsConfigurator, err := tlsutil.NewConfigurator(tlsConfig, hclog.NewNullLogger()) + require.NoError(t, err) + return tlsConfigurator + }, + checkStatus: func(t *testing.T, s hcpclient.ServerStatus) { + expected := hcpclient.ServerTLSInfo{ + Enabled: true, + CertIssuer: "test.internal", + CertName: "testco.internal", + CertSerial: "40", + CertExpiry: time.Date(2123, time.October, 9, 17, 20, 16, 0, time.UTC), + VerifyIncoming: true, + VerifyOutgoing: true, + VerifyServerHostname: true, + CertificateAuthorities: []hcpclient.CertificateMetadata{ + { // manual ca pem + CertExpiry: time.Date(2033, time.October, 30, 15, 50, 29, 0, time.UTC), + CertName: "test.internal", + CertSerial: "191297809789001034260919865367524695178070761520", + }, + { // certificate intermediate + CertExpiry: time.Date(2033, time.October, 30, 15, 50, 29, 0, time.UTC), + CertName: "test.internal", + CertSerial: "191297809789001034260919865367524695178070761520", + }, + }, + } - expected, err := os.ReadFile(golden) - require.NoError(t, err) + require.Equal(t, expected, s.ServerTLSMetadata.InternalRPC) + + // TODO: remove check for status.TLS once deprecation is ready + // https://hashicorp.atlassian.net/browse/CC-7015 + require.Equal(t, expected, s.TLS) + }, + }, + "Nil Cert": { + setupConfigurator: func(t *testing.T) tlsutil.ConfiguratorIface { + tlsConfigurator, err := tlsutil.NewConfigurator(tlsutil.Config{}, + hclog.NewNullLogger()) + require.NoError(t, err) + return tlsConfigurator + }, + checkStatus: func(t *testing.T, s hcpclient.ServerStatus) { + require.Empty(t, s.TLS) + require.Empty(t, s.ServerTLSMetadata.InternalRPC) + }, + }, + "Fail: No leaf": { + errMsg: "expected a leaf certificate", + setupConfigurator: func(t *testing.T) tlsutil.ConfiguratorIface { + return tlsutil.MockConfigurator{ + TlsCert: &tls.Certificate{}, + } + }, + }, + "Fail: Parse leaf cert": { + errMsg: "error parsing leaf cert", + setupConfigurator: func(t *testing.T) tlsutil.ConfiguratorIface { + return tlsutil.MockConfigurator{ + TlsCert: &tls.Certificate{ + Certificate: [][]byte{{}}, + }, + } + }, + }, + "Fail: Parse manual ca pems": { + errMsg: "error parsing manual ca pem", + setupConfigurator: func(t *testing.T) tlsutil.ConfiguratorIface { + tlsConfig := tlsutil.Config{ + InternalRPC: tlsutil.ProtocolConfig{ + CertFile: "../../test/key/ourdomain.cer", + KeyFile: "../../test/key/ourdomain.key", + }, + } + tlsConfigurator, err := tlsutil.NewConfigurator(tlsConfig, hclog.NewNullLogger()) + require.NoError(t, err) - return string(expected) + return tlsutil.MockConfigurator{ + TlsCert: tlsConfigurator.Cert(), + ManualCAPemsArr: []string{"invalid-format"}, + } + }, + }, + "Fail: Parse tls cert intermediate": { + errMsg: "error parsing tls cert", + setupConfigurator: func(t *testing.T) tlsutil.ConfiguratorIface { + tlsConfig := tlsutil.Config{ + InternalRPC: tlsutil.ProtocolConfig{ + CertFile: "../../test/key/ourdomain.cer", + KeyFile: "../../test/key/ourdomain.key", + }, + } + tlsConfigurator, err := tlsutil.NewConfigurator(tlsConfig, hclog.NewNullLogger()) + require.NoError(t, err) + cert := tlsConfigurator.Cert().Certificate + cert = append(cert, []byte{}) + return tlsutil.MockConfigurator{ + TlsCert: &tls.Certificate{ + Certificate: cert, + }, + } + }, + }, + } + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + require.NotNil(t, tc.setupConfigurator) + tlsConfigurator := tc.setupConfigurator(t) + + status := hcpclient.ServerStatus{} + err := addServerTLSInfo(&status, tlsConfigurator) + + if len(tc.errMsg) > 0 { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errMsg) + require.Empty(t, status) + } else { + require.NoError(t, err) + require.NotNil(t, tc.checkStatus) + tc.checkStatus(t, status) + } + }) + } } func TestServer_ControllerDependencies(t *testing.T) { - t.Parallel() + // The original goal of this test was to track controller/resource type dependencies + // as they change over time. However, the test is difficult to maintain and provides + // only limited value as we were not even performing validations on them. The Server + // type itself will validate that no cyclical dependencies exist so this test really + // only produces a visual representation of the dependencies. That comes at the expense + // of having to maintain the golden files. What further complicates this is that + // Consul Enterprise will have potentially different dependencies that don't exist + // in CE. Therefore if we want to maintain this test, we would need to have a separate + // Enterprise and CE golden files and any CE PR which causes regeneration of the golden + // file would require another commit in enterprise to regen the enterprise golden file + // even if no new enterprise watches were added. + // + // Therefore until we have a better way of managing this, the test will be skipped. + t.Skip("This test would be very difficult to maintain and provides limited value") _, conf := testServerConfig(t) deps := newDefaultDeps(t, conf) @@ -2137,7 +2320,13 @@ func TestServer_ControllerDependencies(t *testing.T) { require.NoError(t, err) waitForLeaderEstablishment(t, s1) - actual := fmt.Sprintf("```mermaid\n%s\n```", s1.controllerManager.CalculateDependencies(s1.registry.Types()).ToMermaid()) - expected := goldenMarkdown(t, "v2-resource-dependencies", actual) - require.Equal(t, expected, actual) + // gotest.tools/v3 defines CLI flags which are incompatible wit the golden package + // Once we eliminate gotest.tools/v3 from usage within Consul we could uncomment this + // actual := fmt.Sprintf("```mermaid\n%s\n```", s1.controllerManager.CalculateDependencies(s1.registry.Types()).ToMermaid()) + // markdownFileName := "v2-resource-dependencies" + // if versiontest.IsEnterprise() { + // markdownFileName += "-enterprise" + // } + // expected := golden.Get(t, actual, markdownFileName) + // require.Equal(t, expected, actual) } diff --git a/agent/consul/state/acl_schema.go b/agent/consul/state/acl_schema.go index 17c772b37e01..d96e09712225 100644 --- a/agent/consul/state/acl_schema.go +++ b/agent/consul/state/acl_schema.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/go-memdb" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" ) const ( @@ -409,7 +410,7 @@ func indexExpiresFromACLToken(t *structs.ACLToken, local bool) ([]byte, error) { } func indexServiceNameFromACLToken(token *structs.ACLToken) ([][]byte, error) { - vals := make([][]byte, 0, len(token.ServiceIdentities)) + vals := make([][]byte, 0, len(token.ServiceIdentities)+len(token.TemplatedPolicies)) for _, id := range token.ServiceIdentities { if id != nil && id.ServiceName != "" { var b indexBuilder @@ -417,6 +418,15 @@ func indexServiceNameFromACLToken(token *structs.ACLToken) ([][]byte, error) { vals = append(vals, b.Bytes()) } } + + for _, tp := range token.TemplatedPolicies { + if tp != nil && tp.TemplateName == api.ACLTemplatedPolicyServiceName && tp.TemplateVariables != nil && tp.TemplateVariables.Name != "" { + var b indexBuilder + b.String(strings.ToLower(tp.TemplateVariables.Name)) + vals = append(vals, b.Bytes()) + } + } + if len(vals) == 0 { return nil, errMissingValueForIndex } diff --git a/agent/consul/state/acl_test.go b/agent/consul/state/acl_test.go index f72f96111468..358d2d07fdb8 100644 --- a/agent/consul/state/acl_test.go +++ b/agent/consul/state/acl_test.go @@ -868,6 +868,33 @@ func TestStateStore_ACLToken_List(t *testing.T) { }, Local: true, }, + // templated policy: the serviceName specific token + &structs.ACLToken{ + AccessorID: "2f89e357-dedb-8d8f-7f30-1f465a41508a", + SecretID: "21ab62c9-5372-038c-b6ba-424961cb38c7", + TemplatedPolicies: []*structs.ACLTemplatedPolicy{ + { + TemplateName: "builtin/service", + TemplateVariables: &structs.ACLTemplatedPolicyVariables{ + Name: "service-1", + }, + }, + }, + }, + // templated policy: the serviceName specific token and local + &structs.ACLToken{ + AccessorID: "5e5d6269-f933-3af2-fe30-259b050223f9", + SecretID: "89a456eb-5d55-9a65-92e1-96935dc5b358", + TemplatedPolicies: []*structs.ACLTemplatedPolicy{ + { + TemplateName: "builtin/service", + TemplateVariables: &structs.ACLTemplatedPolicyVariables{ + Name: "service-1", + }, + }, + }, + Local: true, + }, } require.NoError(t, s.ACLTokenBatchSet(2, tokens, ACLTokenSetOptions{})) @@ -893,6 +920,7 @@ func TestStateStore_ACLToken_List(t *testing.T) { methodName: "", accessors: []string{ acl.AnonymousTokenID, + "2f89e357-dedb-8d8f-7f30-1f465a41508a", // templated policy: serviceName + global "47eea4da-bda1-48a6-901c-3e36d2d9262f", // policy + global "54866514-3cf2-4fec-8a8a-710583831834", // mgmt + global "74277ae1-6a9b-4035-b444-2370fe6a2cb5", // authMethod + global @@ -910,6 +938,7 @@ func TestStateStore_ACLToken_List(t *testing.T) { accessors: []string{ "211f0360-ef53-41d3-9d4d-db84396eb6c0", // authMethod + local "4915fc9d-3726-4171-b588-6c271f45eecd", // policy + local + "5e5d6269-f933-3af2-fe30-259b050223f9", // templated policies: serviceName + local "a14fa45e-0afe-4b44-961d-a430030ccfe2", // serviceName + local "cadb4f13-f62a-49ab-ab3f-5a7e01b925d9", // role + local "f1093997-b6c7-496d-bfb8-6b1b1895641b", // mgmt + local @@ -1030,18 +1059,58 @@ func TestStateStore_ACLToken_List(t *testing.T) { }, }, { - name: "All", - local: true, - global: true, - policy: "", - role: "", - methodName: "", + name: "templated policy: ServiceName - Global", + local: false, + global: true, + policy: "", + role: "", + methodName: "", + serviceName: "service-1", + accessors: []string{ + "2f89e357-dedb-8d8f-7f30-1f465a41508a", // serviceName + global + }, + }, + { + name: "templated policy: ServiceName - Local", + local: true, + global: false, + policy: "", + role: "", + methodName: "", + serviceName: "service-1", + accessors: []string{ + "5e5d6269-f933-3af2-fe30-259b050223f9", // serviceName + local + }, + }, + { + name: "templated policy: ServiceName - All", + local: true, + global: true, + policy: "", + role: "", + methodName: "", + serviceName: "service-1", + accessors: []string{ + "2f89e357-dedb-8d8f-7f30-1f465a41508a", // serviceName + global + "5e5d6269-f933-3af2-fe30-259b050223f9", // serviceName + local + }, + }, + { + name: "All", + local: true, + global: true, + policy: "", + role: "", + methodName: "", + serviceName: "", accessors: []string{ acl.AnonymousTokenID, "211f0360-ef53-41d3-9d4d-db84396eb6c0", // authMethod + local + "2f89e357-dedb-8d8f-7f30-1f465a41508a", // templated policy: serviceName + global "47eea4da-bda1-48a6-901c-3e36d2d9262f", // policy + global "4915fc9d-3726-4171-b588-6c271f45eecd", // policy + local "54866514-3cf2-4fec-8a8a-710583831834", // mgmt + global + "5e5d6269-f933-3af2-fe30-259b050223f9", // templated policy: serviceName + local "74277ae1-6a9b-4035-b444-2370fe6a2cb5", // authMethod + global "80c900e1-2fc5-4685-ae29-1b2d17fc30e4", // serviceName + global "a14fa45e-0afe-4b44-961d-a430030ccfe2", // serviceName + local diff --git a/agent/consul/state/catalog.go b/agent/consul/state/catalog.go index 02abd77132ac..dcfe4ec91f29 100644 --- a/agent/consul/state/catalog.go +++ b/agent/consul/state/catalog.go @@ -942,7 +942,7 @@ func ensureServiceTxn(tx WriteTxn, idx uint64, node string, preserveIndexes bool } if conf != nil { termGatewayConf := conf.(*structs.TerminatingGatewayConfigEntry) - addrs, err := getTermGatewayVirtualIPs(tx, idx, termGatewayConf.Services, &svc.EnterpriseMeta) + addrs, err := getTermGatewayVirtualIPs(tx, idx, termGatewayConf.Services) if err != nil { return err } @@ -3557,7 +3557,7 @@ func updateGatewayServices(tx WriteTxn, idx uint64, conf structs.ConfigEntry, en for _, svc := range gatewayServices { // If the service is a wildcard we need to target all services within the namespace if svc.Service.Name == structs.WildcardSpecifier { - if err := updateGatewayNamespace(tx, idx, svc, entMeta); err != nil { + if err := updateGatewayNamespace(tx, idx, svc, &svc.Service.EnterpriseMeta); err != nil { return fmt.Errorf("failed to associate gateway %q with wildcard: %v", gateway.String(), err) } // Skip service-specific update below if there was a wildcard update @@ -3585,11 +3585,10 @@ func getTermGatewayVirtualIPs( tx WriteTxn, idx uint64, services []structs.LinkedService, - entMeta *acl.EnterpriseMeta, ) (map[string]structs.ServiceAddress, error) { addrs := make(map[string]structs.ServiceAddress, len(services)) for _, s := range services { - sn := structs.ServiceName{Name: s.Name, EnterpriseMeta: *entMeta} + sn := structs.ServiceName{Name: s.Name, EnterpriseMeta: s.EnterpriseMeta} // Terminating Gateways cannot route to services in peered clusters psn := structs.PeeredServiceName{ServiceName: sn, Peer: structs.DefaultPeerKeyword} vip, err := assignServiceVirtualIP(tx, idx, psn) @@ -3606,7 +3605,7 @@ func getTermGatewayVirtualIPs( func updateTerminatingGatewayVirtualIPs(tx WriteTxn, idx uint64, conf *structs.TerminatingGatewayConfigEntry, entMeta *acl.EnterpriseMeta) error { // Build the current map of services with virtual IPs for this gateway services := conf.Services - addrs, err := getTermGatewayVirtualIPs(tx, idx, services, entMeta) + addrs, err := getTermGatewayVirtualIPs(tx, idx, services) if err != nil { return err } @@ -3757,14 +3756,15 @@ func terminatingConfigGatewayServices( return false, nil, fmt.Errorf("failed to get gateway service kind for service %s: %v", svc.Name, err) } mapping := &structs.GatewayService{ - Gateway: gateway, - Service: structs.NewServiceName(svc.Name, &svc.EnterpriseMeta), - GatewayKind: structs.ServiceKindTerminatingGateway, - KeyFile: svc.KeyFile, - CertFile: svc.CertFile, - CAFile: svc.CAFile, - SNI: svc.SNI, - ServiceKind: kind, + Gateway: gateway, + Service: structs.NewServiceName(svc.Name, &svc.EnterpriseMeta), + GatewayKind: structs.ServiceKindTerminatingGateway, + KeyFile: svc.KeyFile, + CertFile: svc.CertFile, + CAFile: svc.CAFile, + SNI: svc.SNI, + ServiceKind: kind, + AutoHostRewrite: !svc.DisableAutoHostRewrite, } gatewayServices = append(gatewayServices, mapping) @@ -3831,6 +3831,9 @@ func updateGatewayNamespace(tx WriteTxn, idx uint64, service *structs.GatewaySer if service.GatewayKind == structs.ServiceKindTerminatingGateway && !hasNonConnectInstance { continue } + if service.GatewayKind == structs.ServiceKindAPIGateway && !hasConnectInstance { + continue + } existing, err := tx.First(tableGatewayServices, indexID, service.Gateway, sn.CompoundServiceName().ServiceName, service.Port) if err != nil { @@ -4231,6 +4234,36 @@ func serviceGatewayNodes(tx ReadTxn, ws memdb.WatchSet, service string, kind str return maxIdx, ret, nil } +// metricsProtocolForAPIGateway determines the protocol that should be used when fetching metrics for an api gateway +// Since api gateways may have listeners with different protocols, favor capturing all traffic by only returning HTTP +// when all listeners are HTTP-like. +func metricsProtocolForAPIGateway(tx ReadTxn, ws memdb.WatchSet, sn structs.ServiceName) (uint64, string, error) { + idx, conf, err := configEntryTxn(tx, ws, structs.APIGateway, sn.Name, &sn.EnterpriseMeta) + if err != nil { + return 0, "", fmt.Errorf("failed to get api-gateway config entry for %q: %v", sn.String(), err) + } + if conf == nil { + return 0, "", nil + } + entry, ok := conf.(*structs.APIGatewayConfigEntry) + if !ok { + return 0, "", fmt.Errorf("unexpected config entry type: %T", conf) + } + counts := make(map[string]int) + for _, l := range entry.Listeners { + if structs.IsProtocolHTTPLike(string(l.Protocol)) { + counts["http"] += 1 + } else { + counts["tcp"] += 1 + } + } + protocol := "tcp" + if counts["tcp"] == 0 && counts["http"] > 0 { + protocol = "http" + } + return idx, protocol, nil +} + // metricsProtocolForIngressGateway determines the protocol that should be used when fetching metrics for an ingress gateway // Since ingress gateways may have listeners with different protocols, favor capturing all traffic by only returning HTTP // when all listeners are HTTP-like. @@ -4282,7 +4315,7 @@ func (s *Store) ServiceTopology( ws memdb.WatchSet, dc, service string, kind structs.ServiceKind, - defaultAllow acl.EnforcementDecision, + defaultAllow bool, entMeta *acl.EnterpriseMeta, ) (uint64, *structs.ServiceTopology, error) { tx := s.db.ReadTxn() @@ -4304,7 +4337,11 @@ func (s *Store) ServiceTopology( if err != nil { return 0, nil, fmt.Errorf("failed to fetch protocol for service %s: %v", sn.String(), err) } - + case structs.ServiceKindAPIGateway: + maxIdx, protocol, err = metricsProtocolForAPIGateway(tx, ws, sn) + if err != nil { + return 0, nil, fmt.Errorf("failed to fetch protocol for service %s: %v", sn.String(), err) + } case structs.ServiceKindTypical: maxIdx, protocol, err = protocolForService(tx, ws, sn) if err != nil { @@ -4362,11 +4399,23 @@ func (s *Store) ServiceTopology( maxIdx = idx } - var upstreamSources = make(map[string]string) + upstreamSources := make(map[string]string) for _, un := range upstreamNames { upstreamSources[un.String()] = structs.TopologySourceRegistration } + if kind == structs.ServiceKind(structs.APIGateway) { + upstreamFromGW, err := upstreamServicesForGatewayTxn(tx, sn) + if err != nil { + return 0, nil, err + } + + for _, dn := range upstreamFromGW { + upstreamNames = append(upstreamNames, dn) + upstreamSources[dn.String()] = structs.TopologySourceRegistration + } + } + upstreamDecisions := make(map[string]structs.IntentionDecisionSummary) // Only transparent proxies / connect native services have upstreams from intentions @@ -4417,7 +4466,7 @@ func (s *Store) ServiceTopology( Partition: un.PartitionOrDefault(), Intentions: srcIntentions, MatchType: structs.IntentionMatchDestination, - DefaultDecision: defaultAllow, + DefaultAllow: defaultAllow, AllowPermissions: false, } decision, err := s.IntentionDecision(opts) @@ -4483,11 +4532,24 @@ func (s *Store) ServiceTopology( maxIdx = idx } - var downstreamSources = make(map[string]string) + downstreamSources := make(map[string]string) for _, dn := range downstreamNames { downstreamSources[dn.String()] = structs.TopologySourceRegistration } + idx, downstreamGWs, err := s.downstreamGatewaysForServiceTxn(tx, sn) + if err != nil { + return 0, nil, err + } + if idx > maxIdx { + maxIdx = idx + } + + for _, dn := range downstreamGWs { + downstreamNames = append(downstreamNames, dn) + downstreamSources[dn.String()] = structs.TopologySourceRegistration + } + idx, intentionDownstreams, err := s.intentionTopologyTxn(tx, ws, sn, true, defaultAllow, structs.IntentionTargetService) if err != nil { return 0, nil, err @@ -4528,7 +4590,7 @@ func (s *Store) ServiceTopology( Partition: dn.PartitionOrDefault(), Intentions: dstIntentions, MatchType: structs.IntentionMatchSource, - DefaultDecision: defaultAllow, + DefaultAllow: defaultAllow, AllowPermissions: false, } decision, err := s.IntentionDecision(opts) @@ -4628,6 +4690,61 @@ func (s *Store) combinedServiceNodesTxn(tx ReadTxn, ws memdb.WatchSet, names []s return maxIdx, resp, nil } +func upstreamServicesForGatewayTxn(tx ReadTxn, service structs.ServiceName) ([]structs.ServiceName, error) { + val, err := tx.First(tableConfigEntries, indexID, configentry.KindName{Kind: structs.BoundAPIGateway, Name: service.Name}) + if err != nil { + return nil, err + } + + if gw, ok := val.(*structs.BoundAPIGatewayConfigEntry); ok { + serviceIDs := gw.ListRelatedServices() + names := make([]structs.ServiceName, 0, len(serviceIDs)) + for _, id := range serviceIDs { + names = append(names, structs.NewServiceName(id.ID, &id.EnterpriseMeta)) + } + return names, nil + } + + return nil, errors.New("not an APIGateway") +} + +// downstreamsForServiceTxn will find all downstream services that could route traffic to the input service. +// There are two factors at play. Upstreams defined in a proxy registration, and the discovery chain for those upstreams. +func (s *Store) downstreamGatewaysForServiceTxn(tx ReadTxn, service structs.ServiceName) (uint64, []structs.ServiceName, error) { + iter, err := tx.Get(tableConfigEntries, indexLink, service.ToServiceID()) + if err != nil { + return 0, nil, err + } + + var ( + idx uint64 + resp []structs.ServiceName + seen = make(map[structs.ServiceName]struct{}) + ) + for raw := iter.Next(); raw != nil; raw = iter.Next() { + entry, ok := raw.(*structs.BoundAPIGatewayConfigEntry) + if !ok { + continue + } + + if entry.ModifyIndex > idx { + idx = entry.ModifyIndex + } + + gwServiceName := structs.NewServiceName(entry.Name, &entry.EnterpriseMeta) + if _, ok := seen[gwServiceName]; ok { + continue + } + + seen[gwServiceName] = struct{}{} + + resp = append(resp, gwServiceName) + + } + + return idx, resp, nil +} + // downstreamsForServiceTxn will find all downstream services that could route traffic to the input service. // There are two factors at play. Upstreams defined in a proxy registration, and the discovery chain for those upstreams. func (s *Store) downstreamsForServiceTxn(tx ReadTxn, ws memdb.WatchSet, dc string, service structs.ServiceName) (uint64, []structs.ServiceName, error) { diff --git a/agent/consul/state/catalog_schema.deepcopy.go b/agent/consul/state/catalog_schema.deepcopy.go index af4d430d2f97..43937edd8765 100644 --- a/agent/consul/state/catalog_schema.deepcopy.go +++ b/agent/consul/state/catalog_schema.deepcopy.go @@ -1,7 +1,4 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// generated by deep-copy -pointer-receiver -o ./catalog_schema.deepcopy.go -type upstreamDownstream ./; DO NOT EDIT. +// Code generated by deep-copy -pointer-receiver -o ./catalog_schema.deepcopy.go -type upstreamDownstream ./; DO NOT EDIT. package state diff --git a/agent/consul/state/catalog_test.go b/agent/consul/state/catalog_test.go index f18b9beae843..cef608bc1c51 100644 --- a/agent/consul/state/catalog_test.go +++ b/agent/consul/state/catalog_test.go @@ -5197,7 +5197,8 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 21, ModifyIndex: 21, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("db", nil), @@ -5207,7 +5208,8 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 21, ModifyIndex: 21, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -5241,7 +5243,8 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 21, ModifyIndex: 21, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("db", nil), @@ -5251,7 +5254,8 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 21, ModifyIndex: 21, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -5302,7 +5306,8 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 22, ModifyIndex: 22, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("db", nil), @@ -5312,7 +5317,8 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 22, ModifyIndex: 22, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -5340,7 +5346,8 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 22, ModifyIndex: 22, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("db", nil), @@ -5350,7 +5357,8 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 22, ModifyIndex: 22, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("redis", nil), @@ -5365,7 +5373,8 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 23, ModifyIndex: 23, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -5393,7 +5402,8 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 22, ModifyIndex: 22, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("db", nil), @@ -5403,7 +5413,8 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 22, ModifyIndex: 22, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -5435,7 +5446,8 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 25, ModifyIndex: 25, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -5467,6 +5479,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 26, ModifyIndex: 26, }, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("db", nil), @@ -5477,6 +5490,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 26, ModifyIndex: 26, }, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -5504,6 +5518,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 26, ModifyIndex: 26, }, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("db", nil), @@ -5514,6 +5529,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 26, ModifyIndex: 26, }, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("destination1", nil), @@ -5525,6 +5541,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) { CreateIndex: 27, ModifyIndex: 27, }, + AutoHostRewrite: true, }, } assert.ElementsMatch(t, expectWildcardIncludesDest, out) @@ -6018,7 +6035,8 @@ func TestStateStore_GatewayServices_ServiceDeletion(t *testing.T) { CreateIndex: 19, ModifyIndex: 19, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -6040,6 +6058,7 @@ func TestStateStore_GatewayServices_ServiceDeletion(t *testing.T) { CreateIndex: 20, ModifyIndex: 20, }, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("db", nil), @@ -6050,6 +6069,7 @@ func TestStateStore_GatewayServices_ServiceDeletion(t *testing.T) { CreateIndex: 20, ModifyIndex: 20, }, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -6077,6 +6097,7 @@ func TestStateStore_GatewayServices_ServiceDeletion(t *testing.T) { CreateIndex: 19, ModifyIndex: 20, }, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -6097,6 +6118,7 @@ func TestStateStore_GatewayServices_ServiceDeletion(t *testing.T) { CreateIndex: 20, ModifyIndex: 20, }, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -7016,6 +7038,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { // Read everything back. ws = memdb.NewWatchSet() idx, out, err := s.DumpGatewayServices(ws) + fmt.Println(out) assert.Nil(t, err) assert.Equal(t, idx, uint64(21)) assert.Len(t, out, 2) @@ -7033,7 +7056,8 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { CreateIndex: 21, ModifyIndex: 21, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("db", nil), @@ -7043,7 +7067,8 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { CreateIndex: 21, ModifyIndex: 21, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -7077,6 +7102,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { assert.False(t, watchFired(ws)) idx, out, err := s.DumpGatewayServices(ws) + fmt.Println(out) assert.Nil(t, err) assert.Equal(t, idx, uint64(21)) assert.Len(t, out, 2) @@ -7094,7 +7120,8 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { CreateIndex: 21, ModifyIndex: 21, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("db", nil), @@ -7104,7 +7131,8 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { CreateIndex: 21, ModifyIndex: 21, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -7134,7 +7162,8 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { CreateIndex: 21, ModifyIndex: 21, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("db", nil), @@ -7144,7 +7173,8 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { CreateIndex: 21, ModifyIndex: 21, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("redis", nil), @@ -7159,7 +7189,8 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { CreateIndex: 22, ModifyIndex: 22, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -7189,7 +7220,8 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { CreateIndex: 21, ModifyIndex: 21, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("db", nil), @@ -7199,7 +7231,8 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { CreateIndex: 21, ModifyIndex: 21, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -7233,7 +7266,8 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { CreateIndex: 24, ModifyIndex: 24, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, } assert.Equal(t, expect, out) @@ -7291,7 +7325,8 @@ func TestStateStore_DumpGatewayServices(t *testing.T) { CreateIndex: 24, ModifyIndex: 24, }, - ServiceKind: structs.GatewayServiceKindService, + ServiceKind: structs.GatewayServiceKindService, + AutoHostRewrite: true, }, { Service: structs.NewServiceName("api", nil), diff --git a/agent/consul/state/config_entry.go b/agent/consul/state/config_entry.go index b298b6122080..40bd02f8ca06 100644 --- a/agent/consul/state/config_entry.go +++ b/agent/consul/state/config_entry.go @@ -102,6 +102,13 @@ func (s *Snapshot) ConfigEntries() ([]structs.ConfigEntry, error) { // ConfigEntry is used when restoring from a snapshot. func (s *Restore) ConfigEntry(c structs.ConfigEntry) error { + // the hash is recalculated when restoring config entries + // in case a new field is added in a newer version. + h, err := structs.HashConfigEntry(c) + if err != nil { + return err + } + c.SetHash(h) return insertConfigEntryWithTxn(s.tx, c.GetRaftIndex().ModifyIndex, c) } @@ -519,6 +526,16 @@ func insertConfigEntryWithTxn(tx WriteTxn, idx uint64, conf structs.ConfigEntry) if err != nil { return err } + case structs.ProxyDefaults: + proxyDefaults, ok := conf.(*structs.ProxyConfigEntry) + if !ok { + return fmt.Errorf("unable to cast config entry to proxy-defaults") + } + // Ensure we pre-compute the protocol before persisting always. + err := proxyDefaults.ComputeProtocol() + if err != nil { + return err + } } // Assign virtual-ips, if needed @@ -629,6 +646,7 @@ func validateProposedConfigEntryInGraph( case structs.ExportedServices: case structs.APIGateway: // TODO Consider checkGatewayClash case structs.BoundAPIGateway: + case structs.FileSystemCertificate: case structs.InlineCertificate: case structs.HTTPRoute: case structs.TCPRoute: diff --git a/agent/consul/state/config_entry_events.go b/agent/consul/state/config_entry_events.go index c6c19fce3453..a8831edb1e80 100644 --- a/agent/consul/state/config_entry_events.go +++ b/agent/consul/state/config_entry_events.go @@ -15,19 +15,21 @@ import ( // Adding events for a new config entry kind? Remember to update ConfigEntryFromStructs and ConfigEntryToStructs. var configEntryKindToTopic = map[string]stream.Topic{ - structs.MeshConfig: EventTopicMeshConfig, - structs.ServiceResolver: EventTopicServiceResolver, - structs.IngressGateway: EventTopicIngressGateway, - structs.ServiceIntentions: EventTopicServiceIntentions, - structs.ServiceDefaults: EventTopicServiceDefaults, - structs.APIGateway: EventTopicAPIGateway, - structs.TCPRoute: EventTopicTCPRoute, - structs.HTTPRoute: EventTopicHTTPRoute, - structs.InlineCertificate: EventTopicInlineCertificate, - structs.BoundAPIGateway: EventTopicBoundAPIGateway, - structs.RateLimitIPConfig: EventTopicIPRateLimit, - structs.SamenessGroup: EventTopicSamenessGroup, - structs.JWTProvider: EventTopicJWTProvider, + structs.MeshConfig: EventTopicMeshConfig, + structs.ServiceResolver: EventTopicServiceResolver, + structs.IngressGateway: EventTopicIngressGateway, + structs.ServiceIntentions: EventTopicServiceIntentions, + structs.ServiceDefaults: EventTopicServiceDefaults, + structs.APIGateway: EventTopicAPIGateway, + structs.TCPRoute: EventTopicTCPRoute, + structs.HTTPRoute: EventTopicHTTPRoute, + structs.FileSystemCertificate: EventTopicFileSystemCertificate, + structs.InlineCertificate: EventTopicInlineCertificate, + structs.BoundAPIGateway: EventTopicBoundAPIGateway, + structs.RateLimitIPConfig: EventTopicIPRateLimit, + structs.SamenessGroup: EventTopicSamenessGroup, + structs.JWTProvider: EventTopicJWTProvider, + structs.ExportedServices: EventTopicExportedServices, } // EventSubjectConfigEntry is a stream.Subject used to route and receive events @@ -146,6 +148,12 @@ func (s *Store) HTTPRouteSnapshot(req stream.SubscribeRequest, buf stream.Snapsh return s.configEntrySnapshot(structs.HTTPRoute, req, buf) } +// FileSystemCertificateSnapshot is a stream.SnapshotFunc that returns a snapshot of +// inline-certificate config entries. +func (s *Store) FileSystemCertificateSnapshot(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return s.configEntrySnapshot(structs.FileSystemCertificate, req, buf) +} + // InlineCertificateSnapshot is a stream.SnapshotFunc that returns a snapshot of // inline-certificate config entries. func (s *Store) InlineCertificateSnapshot(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { @@ -176,6 +184,12 @@ func (s *Store) JWTProviderSnapshot(req stream.SubscribeRequest, buf stream.Snap return s.configEntrySnapshot(structs.JWTProvider, req, buf) } +// ExportedServicesSnapshot is a stream.SnapshotFunc that returns a snapshot of +// exported-services config entries. +func (s *Store) ExportedServicesSnapshot(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return s.configEntrySnapshot(structs.ExportedServices, req, buf) +} + func (s *Store) configEntrySnapshot(kind string, req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { var ( idx uint64 diff --git a/agent/consul/state/config_entry_exported_services.go b/agent/consul/state/config_entry_exported_services.go index 7534613ae137..18d9553dc015 100644 --- a/agent/consul/state/config_entry_exported_services.go +++ b/agent/consul/state/config_entry_exported_services.go @@ -5,10 +5,13 @@ package state import ( "fmt" + "sort" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/configentry" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/proto/private/pbconfigentry" "github.com/hashicorp/go-memdb" ) @@ -64,3 +67,108 @@ func getExportedServicesConfigEntryTxn( } return idx, export, nil } + +// ResolvedExportedServices returns the list of exported services along with consumers. +// Sameness Groups and wild card entries are resolved. +func (s *Store) ResolvedExportedServices(ws memdb.WatchSet, entMeta *acl.EnterpriseMeta) (uint64, []*pbconfigentry.ResolvedExportedService, error) { + tx := s.db.ReadTxn() + defer tx.Abort() + + return resolvedExportedServicesTxn(tx, ws, entMeta) +} + +func resolvedExportedServicesTxn(tx ReadTxn, ws memdb.WatchSet, entMeta *acl.EnterpriseMeta) (uint64, []*pbconfigentry.ResolvedExportedService, error) { + var resp []*pbconfigentry.ResolvedExportedService + + // getSimplifiedExportedServices resolves the sameness group information to partitions and peers. + maxIdx, exports, err := getSimplifiedExportedServices(tx, ws, nil, *entMeta) + if err != nil { + return 0, nil, err + } + if exports == nil { + return maxIdx, nil, nil + } + + var exportedServices []structs.ExportedService + + for _, svc := range exports.Services { + // Prevent exporting the "consul" service. + if svc.Name == structs.ConsulServiceName { + continue + } + + // If this isn't a wildcard, we can simply add it to the list of exportedServices and move to the next entry. + if svc.Name != structs.WildcardSpecifier { + exportedServices = append(exportedServices, svc) + continue + } + + svcEntMeta := acl.NewEnterpriseMetaWithPartition(entMeta.PartitionOrDefault(), svc.Namespace) + + // If all services in the namespace are exported by the wildcard, query those service names. + idx, typicalServices, err := serviceNamesOfKindTxn(tx, ws, structs.ServiceKindTypical, svcEntMeta) + if err != nil { + return 0, nil, fmt.Errorf("failed to get typical service names: %w", err) + } + + maxIdx = lib.MaxUint64(maxIdx, idx) + + for _, sn := range typicalServices { + // Prevent exporting the "consul" service. + if sn.Service.Name != structs.ConsulServiceName { + exportedServices = append(exportedServices, structs.ExportedService{ + Name: sn.Service.Name, + Namespace: sn.Service.NamespaceOrDefault(), + Consumers: svc.Consumers, + }) + } + } + } + + uniqueExportedServices := getUniqueExportedServices(exportedServices, entMeta) + resp = prepareExportedServicesResponse(uniqueExportedServices, entMeta) + + return maxIdx, resp, nil +} + +// getUniqueExportedServices removes duplicate services and consumers. Services are also sorted in ascending order +func getUniqueExportedServices(exportedServices []structs.ExportedService, entMeta *acl.EnterpriseMeta) []structs.ExportedService { + // Services -> ServiceConsumers + var exportedServicesMapper = make(map[structs.ServiceName]map[structs.ServiceConsumer]struct{}) + for _, svc := range exportedServices { + svcEntMeta := acl.NewEnterpriseMetaWithPartition(entMeta.PartitionOrDefault(), svc.Namespace) + svcName := structs.NewServiceName(svc.Name, &svcEntMeta) + + for _, c := range svc.Consumers { + cons, ok := exportedServicesMapper[svcName] + if !ok { + cons = make(map[structs.ServiceConsumer]struct{}) + exportedServicesMapper[svcName] = cons + } + cons[c] = struct{}{} + } + } + + uniqueExportedServices := make([]structs.ExportedService, 0, len(exportedServicesMapper)) + + for svc, cons := range exportedServicesMapper { + consumers := make([]structs.ServiceConsumer, 0, len(cons)) + for con := range cons { + consumers = append(consumers, con) + } + + uniqueExportedServices = append(uniqueExportedServices, structs.ExportedService{ + Name: svc.Name, + Namespace: svc.NamespaceOrDefault(), + Consumers: consumers, + }) + + } + + sort.Slice(uniqueExportedServices, func(i, j int) bool { + return (uniqueExportedServices[i].Name < uniqueExportedServices[j].Name) || + (uniqueExportedServices[i].Name == uniqueExportedServices[j].Name && uniqueExportedServices[i].Namespace < uniqueExportedServices[j].Namespace) + }) + + return uniqueExportedServices +} diff --git a/agent/consul/state/config_entry_exported_services_ce.go b/agent/consul/state/config_entry_exported_services_ce.go index aa495fb0d8f4..3418270902eb 100644 --- a/agent/consul/state/config_entry_exported_services_ce.go +++ b/agent/consul/state/config_entry_exported_services_ce.go @@ -6,9 +6,12 @@ package state import ( + "sort" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/configentry" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/proto/private/pbconfigentry" "github.com/hashicorp/go-memdb" ) @@ -31,3 +34,29 @@ func (s *Store) GetSimplifiedExportedServices(ws memdb.WatchSet, entMeta acl.Ent defer tx.Abort() return getSimplifiedExportedServices(tx, ws, nil, entMeta) } + +func prepareExportedServicesResponse(exportedServices []structs.ExportedService, entMeta *acl.EnterpriseMeta) []*pbconfigentry.ResolvedExportedService { + + resp := make([]*pbconfigentry.ResolvedExportedService, len(exportedServices)) + + for idx, exportedService := range exportedServices { + consumerPeers := []string{} + + for _, consumer := range exportedService.Consumers { + if consumer.Peer != "" { + consumerPeers = append(consumerPeers, consumer.Peer) + } + } + + sort.Strings(consumerPeers) + + resp[idx] = &pbconfigentry.ResolvedExportedService{ + Service: exportedService.Name, + Consumers: &pbconfigentry.Consumers{ + Peers: consumerPeers, + }, + } + } + + return resp +} diff --git a/agent/consul/state/config_entry_exported_services_ce_test.go b/agent/consul/state/config_entry_exported_services_ce_test.go new file mode 100644 index 000000000000..a96e5cb3f981 --- /dev/null +++ b/agent/consul/state/config_entry_exported_services_ce_test.go @@ -0,0 +1,317 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +//go:build !consulent + +package state + +import ( + "testing" + + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/proto/private/pbconfigentry" + "github.com/hashicorp/go-memdb" + "github.com/stretchr/testify/require" +) + +func TestStore_prepareExportedServicesResponse(t *testing.T) { + + exportedServices := []structs.ExportedService{ + { + Name: "db", + Consumers: []structs.ServiceConsumer{ + { + Peer: "west", + }, + { + Peer: "east", + }, + { + Partition: "part", + }, + }, + }, + { + Name: "web", + Consumers: []structs.ServiceConsumer{ + { + Peer: "peer-a", + }, + { + Peer: "peer-b", + }, + }, + }, + } + + resp := prepareExportedServicesResponse(exportedServices, nil) + + expected := []*pbconfigentry.ResolvedExportedService{ + { + Service: "db", + Consumers: &pbconfigentry.Consumers{ + Peers: []string{"east", "west"}, + }, + }, + { + Service: "web", + Consumers: &pbconfigentry.Consumers{ + Peers: []string{"peer-a", "peer-b"}, + }, + }, + } + + require.Equal(t, expected, resp) +} + +func TestStore_ResolvedExportingServices(t *testing.T) { + s := NewStateStore(nil) + var c indexCounter + + { + require.NoError(t, s.EnsureNode(c.Next(), &structs.Node{ + Node: "foo", Address: "127.0.0.1", + })) + + require.NoError(t, s.EnsureService(c.Next(), "foo", &structs.NodeService{ + ID: "db", Service: "db", Port: 5000, + })) + + require.NoError(t, s.EnsureService(c.Next(), "foo", &structs.NodeService{ + ID: "cache", Service: "cache", Port: 5000, + })) + + entry := &structs.ExportedServicesConfigEntry{ + Name: "default", + Services: []structs.ExportedService{ + { + Name: "db", + Consumers: []structs.ServiceConsumer{ + { + Peer: "east", + }, + { + Peer: "west", + }, + }, + }, + { + Name: "cache", + Consumers: []structs.ServiceConsumer{ + { + Peer: "east", + }, + }, + }, + }, + } + err := s.EnsureConfigEntry(c.Next(), entry) + require.NoError(t, err) + + // Adding services to check wildcard config later on + + require.NoError(t, s.EnsureService(c.Next(), "foo", &structs.NodeService{ + ID: "frontend", Service: "frontend", Port: 5000, + })) + + require.NoError(t, s.EnsureService(c.Next(), "foo", &structs.NodeService{ + ID: "backend", Service: "backend", Port: 5000, + })) + + // The consul service should never be exported. + require.NoError(t, s.EnsureService(c.Next(), "foo", &structs.NodeService{ + ID: structs.ConsulServiceID, Service: structs.ConsulServiceName, Port: 8000, + })) + + } + + type testCase struct { + expect []*pbconfigentry.ResolvedExportedService + idx uint64 + } + + run := func(t *testing.T, tc testCase) { + ws := memdb.NewWatchSet() + defaultMeta := structs.DefaultEnterpriseMetaInDefaultPartition() + idx, services, err := s.ResolvedExportedServices(ws, defaultMeta) + require.NoError(t, err) + require.Equal(t, tc.idx, idx) + require.Equal(t, tc.expect, services) + } + + t.Run("only exported services are included", func(t *testing.T) { + tc := testCase{ + expect: []*pbconfigentry.ResolvedExportedService{ + { + Service: "cache", + Consumers: &pbconfigentry.Consumers{ + Peers: []string{"east"}, + }, + }, + { + Service: "db", + Consumers: &pbconfigentry.Consumers{ + Peers: []string{"east", "west"}, + }, + }, + }, + idx: 4, + } + + run(t, tc) + }) + + t.Run("wild card includes all services", func(t *testing.T) { + entry := &structs.ExportedServicesConfigEntry{ + Name: "default", + Services: []structs.ExportedService{ + { + Name: "*", + Consumers: []structs.ServiceConsumer{ + {Peer: "west"}, + }, + }, + }, + } + + err := s.EnsureConfigEntry(c.Next(), entry) + require.NoError(t, err) + + tc := testCase{ + expect: []*pbconfigentry.ResolvedExportedService{ + { + Service: "backend", + Consumers: &pbconfigentry.Consumers{ + Peers: []string{"west"}, + }, + }, + { + Service: "cache", + Consumers: &pbconfigentry.Consumers{ + Peers: []string{"west"}, + }, + }, + { + Service: "db", + Consumers: &pbconfigentry.Consumers{ + Peers: []string{"west"}, + }, + }, + + { + Service: "frontend", + Consumers: &pbconfigentry.Consumers{ + Peers: []string{"west"}, + }, + }, + }, + idx: c.Last(), + } + + run(t, tc) + }) + + t.Run("deleting the config entry clears the services", func(t *testing.T) { + defaultMeta := structs.DefaultEnterpriseMetaInDefaultPartition() + err := s.DeleteConfigEntry(c.Next(), structs.ExportedServices, "default", nil) + require.NoError(t, err) + + idx, result, err := s.ResolvedExportedServices(nil, defaultMeta) + require.NoError(t, err) + require.Equal(t, c.Last(), idx) + require.Nil(t, result) + }) +} + +func TestStore_getUniqueExportedServices(t *testing.T) { + + exportedServices := []structs.ExportedService{ + { + Name: "db", + Consumers: []structs.ServiceConsumer{ + { + Peer: "west", + }, + { + Peer: "east", + }, + { + Partition: "part", + }, + }, + }, + { + Name: "web", + Consumers: []structs.ServiceConsumer{ + { + Peer: "peer-a", + }, + { + Peer: "peer-b", + }, + }, + }, + { + Name: "db", + Consumers: []structs.ServiceConsumer{ + { + Peer: "west", + }, + { + Peer: "west-2", + }, + }, + }, + { + Name: "db", + Consumers: []structs.ServiceConsumer{ + { + Peer: "west", + }, + { + Peer: "west-2", + }, + }, + }, + } + + resp := getUniqueExportedServices(exportedServices, nil) + + expected := []structs.ExportedService{ + { + Name: "db", + Consumers: []structs.ServiceConsumer{ + { + Peer: "west", + }, + { + Peer: "east", + }, + { + Partition: "part", + }, + { + Peer: "west-2", + }, + }, + }, + { + Name: "web", + Consumers: []structs.ServiceConsumer{ + { + Peer: "peer-a", + }, + { + Peer: "peer-b", + }, + }, + }, + } + + require.Equal(t, 2, len(resp)) + + for idx, expSvc := range expected { + require.Equal(t, expSvc.Name, resp[idx].Name) + require.ElementsMatch(t, expSvc.Consumers, resp[idx].Consumers) + } +} diff --git a/agent/consul/state/config_entry_test.go b/agent/consul/state/config_entry_test.go index af9dc0997156..f2794d504313 100644 --- a/agent/consul/state/config_entry_test.go +++ b/agent/consul/state/config_entry_test.go @@ -24,16 +24,27 @@ import ( func TestStore_ConfigEntry(t *testing.T) { s := testConfigStateStore(t) + cfg := &structs.ProxyConfigEntry{ + Kind: structs.ProxyDefaults, + Name: "global", + Config: map[string]interface{}{ + "DestinationServiceName": "foo", + "protocol": "udp", + }, + } + expected := &structs.ProxyConfigEntry{ Kind: structs.ProxyDefaults, Name: "global", Config: map[string]interface{}{ "DestinationServiceName": "foo", + "protocol": "udp", }, + Protocol: "udp", } // Create - require.NoError(t, s.EnsureConfigEntry(0, expected)) + require.NoError(t, s.EnsureConfigEntry(0, cfg)) idx, config, err := s.ConfigEntry(nil, structs.ProxyDefaults, "global", nil) require.NoError(t, err) @@ -761,6 +772,7 @@ func TestStore_ServiceDefaults_Kind_Destination_Wildcard(t *testing.T) { CreateIndex: 8, ModifyIndex: 8, }, + AutoHostRewrite: true, }, } require.Equal(t, expected, gatewayServices) @@ -808,6 +820,7 @@ func TestStore_ServiceDefaults_Kind_Destination_Wildcard(t *testing.T) { CreateIndex: 7, ModifyIndex: 7, }, + AutoHostRewrite: true, }, } require.Equal(t, expected, gatewayServices) @@ -832,6 +845,7 @@ func TestStore_ServiceDefaults_Kind_Destination_Wildcard(t *testing.T) { CreateIndex: 7, ModifyIndex: 9, }, + AutoHostRewrite: true, }, } require.Equal(t, expected, gatewayServices) diff --git a/agent/consul/state/coordinate.go b/agent/consul/state/coordinate.go index bcd71e5a0f08..90983708bf39 100644 --- a/agent/consul/state/coordinate.go +++ b/agent/consul/state/coordinate.go @@ -11,7 +11,7 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" ) const tableCoordinates = "coordinates" @@ -117,7 +117,7 @@ func (s *Restore) Coordinates(idx uint64, updates structs.Coordinates) error { // Coordinate returns a map of coordinates for the given node, indexed by // network segment. -func (s *Store) Coordinate(ws memdb.WatchSet, node string, entMeta *acl.EnterpriseMeta) (uint64, lib.CoordinateSet, error) { +func (s *Store) Coordinate(ws memdb.WatchSet, node string, entMeta *acl.EnterpriseMeta) (uint64, librtt.CoordinateSet, error) { tx := s.db.Txn(false) defer tx.Abort() @@ -137,7 +137,7 @@ func (s *Store) Coordinate(ws memdb.WatchSet, node string, entMeta *acl.Enterpri } ws.Add(iter.WatchCh()) - results := make(lib.CoordinateSet) + results := make(librtt.CoordinateSet) for raw := iter.Next(); raw != nil; raw = iter.Next() { coord := raw.(*structs.Coordinate) results[coord.Segment] = coord.Coord diff --git a/agent/consul/state/coordinate_test.go b/agent/consul/state/coordinate_test.go index dad0ce3e32ec..408b06e4c075 100644 --- a/agent/consul/state/coordinate_test.go +++ b/agent/consul/state/coordinate_test.go @@ -8,12 +8,13 @@ import ( "math/rand" "testing" + "github.com/stretchr/testify/require" + "github.com/hashicorp/go-memdb" "github.com/hashicorp/serf/coordinate" - "github.com/stretchr/testify/require" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/sdk/testutil" ) @@ -52,7 +53,7 @@ func TestStateStore_Coordinate_Updates(t *testing.T) { coordinateWs := memdb.NewWatchSet() _, coords, err := s.Coordinate(coordinateWs, "nope", nil) require.NoError(t, err) - require.Equal(t, lib.CoordinateSet{}, coords) + require.Equal(t, librtt.CoordinateSet{}, coords) // Make an update for nodes that don't exist and make sure they get // ignored. @@ -104,7 +105,7 @@ func TestStateStore_Coordinate_Updates(t *testing.T) { idx, coords, err := s.Coordinate(nodeWs[i], update.Node, nil) require.NoError(t, err) require.Equal(t, uint64(3), idx, "bad index") - expected := lib.CoordinateSet{ + expected := librtt.CoordinateSet{ "": update.Coord, } require.Equal(t, expected, coords) @@ -133,7 +134,7 @@ func TestStateStore_Coordinate_Updates(t *testing.T) { idx, coords, err := s.Coordinate(nil, update.Node, nil) require.NoError(t, err) require.Equal(t, uint64(4), idx, "bad index") - expected := lib.CoordinateSet{ + expected := librtt.CoordinateSet{ "": update.Coord, } require.Equal(t, expected, coords) @@ -178,7 +179,7 @@ func TestStateStore_Coordinate_Cleanup(t *testing.T) { // Make sure it's in there. _, coords, err := s.Coordinate(nil, "node1", nil) require.NoError(t, err) - expected := lib.CoordinateSet{ + expected := librtt.CoordinateSet{ "alpha": updates[0].Coord, "beta": updates[1].Coord, } @@ -190,7 +191,7 @@ func TestStateStore_Coordinate_Cleanup(t *testing.T) { // Make sure the coordinate is gone. _, coords, err = s.Coordinate(nil, "node1", nil) require.NoError(t, err) - require.Equal(t, lib.CoordinateSet{}, coords) + require.Equal(t, librtt.CoordinateSet{}, coords) // Make sure the index got updated. idx, all, err := s.Coordinates(nil, nil) diff --git a/agent/consul/state/events.go b/agent/consul/state/events.go index 0d4f4eb4fe40..996f77806c8e 100644 --- a/agent/consul/state/events.go +++ b/agent/consul/state/events.go @@ -46,7 +46,8 @@ func PBToStreamSubscribeRequest(req *pbsubscribe.SubscribeRequest, entMeta acl.E case EventTopicMeshConfig, EventTopicServiceResolver, EventTopicIngressGateway, EventTopicServiceIntentions, EventTopicServiceDefaults, EventTopicAPIGateway, EventTopicTCPRoute, EventTopicHTTPRoute, EventTopicJWTProvider, EventTopicInlineCertificate, - EventTopicBoundAPIGateway, EventTopicSamenessGroup: + EventTopicBoundAPIGateway, EventTopicSamenessGroup, EventTopicExportedServices, + EventTopicFileSystemCertificate: subject = EventSubjectConfigEntry{ Name: named.Key, EnterpriseMeta: &entMeta, diff --git a/agent/consul/state/intention.go b/agent/consul/state/intention.go index f36055522858..12c79cad5c94 100644 --- a/agent/consul/state/intention.go +++ b/agent/consul/state/intention.go @@ -743,7 +743,7 @@ type IntentionDecisionOpts struct { Peer string Intentions structs.SimplifiedIntentions MatchType structs.IntentionMatchType - DefaultDecision acl.EnforcementDecision + DefaultAllow bool AllowPermissions bool } @@ -763,7 +763,7 @@ func (s *Store) IntentionDecision(opts IntentionDecisionOpts) (structs.Intention } resp := structs.IntentionDecisionSummary{ - DefaultAllow: opts.DefaultDecision == acl.Allow, + DefaultAllow: opts.DefaultAllow, } if ixnMatch == nil { // No intention found, fall back to default @@ -1029,13 +1029,13 @@ func (s *Store) IntentionTopology( ws memdb.WatchSet, target structs.ServiceName, downstreams bool, - defaultDecision acl.EnforcementDecision, + defaultAllow bool, intentionTarget structs.IntentionTargetType, ) (uint64, structs.ServiceList, error) { tx := s.db.ReadTxn() defer tx.Abort() - idx, services, err := s.intentionTopologyTxn(tx, ws, target, downstreams, defaultDecision, intentionTarget) + idx, services, err := s.intentionTopologyTxn(tx, ws, target, downstreams, defaultAllow, intentionTarget) if err != nil { requested := "upstreams" if downstreams { @@ -1055,7 +1055,7 @@ func (s *Store) intentionTopologyTxn( tx ReadTxn, ws memdb.WatchSet, target structs.ServiceName, downstreams bool, - defaultDecision acl.EnforcementDecision, + defaultAllow bool, intentionTarget structs.IntentionTargetType, ) (uint64, []ServiceWithDecision, error) { @@ -1163,7 +1163,7 @@ func (s *Store) intentionTopologyTxn( Partition: candidate.PartitionOrDefault(), Intentions: intentions, MatchType: decisionMatchType, - DefaultDecision: defaultDecision, + DefaultAllow: defaultAllow, AllowPermissions: true, } decision, err := s.IntentionDecision(opts) diff --git a/agent/consul/state/intention_test.go b/agent/consul/state/intention_test.go index 72455565d582..b1c7ccf7b89c 100644 --- a/agent/consul/state/intention_test.go +++ b/agent/consul/state/intention_test.go @@ -313,6 +313,7 @@ func testStore_IntentionMutation(t *testing.T, s *Store) { src.LegacyMeta = nil } } + expect.SetHash(got.GetHash()) require.Equal(t, expect, got) } @@ -1965,27 +1966,27 @@ func TestStore_IntentionDecision(t *testing.T) { src string dst string matchType structs.IntentionMatchType - defaultDecision acl.EnforcementDecision + defaultAllow bool allowPermissions bool expect structs.IntentionDecisionSummary }{ { - name: "no matching intention and default deny", - src: "does-not-exist", - dst: "ditto", - matchType: structs.IntentionMatchDestination, - defaultDecision: acl.Deny, + name: "no matching intention and default deny", + src: "does-not-exist", + dst: "ditto", + matchType: structs.IntentionMatchDestination, + defaultAllow: false, expect: structs.IntentionDecisionSummary{ Allowed: false, DefaultAllow: false, }, }, { - name: "no matching intention and default allow", - src: "does-not-exist", - dst: "ditto", - matchType: structs.IntentionMatchDestination, - defaultDecision: acl.Allow, + name: "no matching intention and default allow", + src: "does-not-exist", + dst: "ditto", + matchType: structs.IntentionMatchDestination, + defaultAllow: true, expect: structs.IntentionDecisionSummary{ Allowed: true, DefaultAllow: true, @@ -2078,7 +2079,7 @@ func TestStore_IntentionDecision(t *testing.T) { Partition: acl.DefaultPartitionName, Intentions: intentions, MatchType: tc.matchType, - DefaultDecision: tc.defaultDecision, + DefaultAllow: tc.defaultAllow, AllowPermissions: tc.allowPermissions, } decision, err := s.IntentionDecision(opts) @@ -2160,7 +2161,7 @@ func TestStore_IntentionTopology(t *testing.T) { } tests := []struct { name string - defaultDecision acl.EnforcementDecision + defaultAllow bool intentions []structs.ServiceIntentionsConfigEntry discoveryChains []structs.ConfigEntry target structs.ServiceName @@ -2168,8 +2169,8 @@ func TestStore_IntentionTopology(t *testing.T) { expect expect }{ { - name: "(upstream) acl allow all but intentions deny one", - defaultDecision: acl.Allow, + name: "(upstream) default allow all but intentions deny one", + defaultAllow: true, intentions: []structs.ServiceIntentionsConfigEntry{ { Kind: structs.ServiceIntentions, @@ -2195,8 +2196,8 @@ func TestStore_IntentionTopology(t *testing.T) { }, }, { - name: "(upstream) acl allow includes virtual service", - defaultDecision: acl.Allow, + name: "(upstream) default allow includes virtual service", + defaultAllow: true, discoveryChains: []structs.ConfigEntry{ &structs.ServiceResolverConfigEntry{ Kind: structs.ServiceResolver, @@ -2224,8 +2225,8 @@ func TestStore_IntentionTopology(t *testing.T) { }, }, { - name: "(upstream) acl deny all intentions allow virtual service", - defaultDecision: acl.Deny, + name: "(upstream) default deny intentions allow virtual service", + defaultAllow: false, discoveryChains: []structs.ConfigEntry{ &structs.ServiceResolverConfigEntry{ Kind: structs.ServiceResolver, @@ -2257,8 +2258,8 @@ func TestStore_IntentionTopology(t *testing.T) { }, }, { - name: "(upstream) acl deny all intentions allow one", - defaultDecision: acl.Deny, + name: "(upstream) default deny intentions allow one", + defaultAllow: false, intentions: []structs.ServiceIntentionsConfigEntry{ { Kind: structs.ServiceIntentions, @@ -2284,8 +2285,8 @@ func TestStore_IntentionTopology(t *testing.T) { }, }, { - name: "(downstream) acl allow all but intentions deny one", - defaultDecision: acl.Allow, + name: "(downstream) default allow but intentions deny one", + defaultAllow: true, intentions: []structs.ServiceIntentionsConfigEntry{ { Kind: structs.ServiceIntentions, @@ -2315,8 +2316,8 @@ func TestStore_IntentionTopology(t *testing.T) { }, }, { - name: "(downstream) acl deny all intentions allow one", - defaultDecision: acl.Deny, + name: "(downstream) default deny all intentions allow one", + defaultAllow: false, intentions: []structs.ServiceIntentionsConfigEntry{ { Kind: structs.ServiceIntentions, @@ -2342,8 +2343,8 @@ func TestStore_IntentionTopology(t *testing.T) { }, }, { - name: "acl deny but intention allow all overrides it", - defaultDecision: acl.Deny, + name: "default deny but intention allow all overrides it", + defaultAllow: false, intentions: []structs.ServiceIntentionsConfigEntry{ { Kind: structs.ServiceIntentions, @@ -2373,8 +2374,8 @@ func TestStore_IntentionTopology(t *testing.T) { }, }, { - name: "acl allow but intention deny all overrides it", - defaultDecision: acl.Allow, + name: "default allow but intention deny all overrides it", + defaultAllow: true, intentions: []structs.ServiceIntentionsConfigEntry{ { Kind: structs.ServiceIntentions, @@ -2395,8 +2396,8 @@ func TestStore_IntentionTopology(t *testing.T) { }, }, { - name: "acl deny but intention allow all overrides it", - defaultDecision: acl.Deny, + name: "default deny but intention allow all overrides it", + defaultAllow: false, intentions: []structs.ServiceIntentionsConfigEntry{ { Kind: structs.ServiceIntentions, @@ -2447,7 +2448,7 @@ func TestStore_IntentionTopology(t *testing.T) { idx++ } - idx, got, err := s.IntentionTopology(nil, tt.target, tt.downstreams, tt.defaultDecision, structs.IntentionTargetService) + idx, got, err := s.IntentionTopology(nil, tt.target, tt.downstreams, tt.defaultAllow, structs.IntentionTargetService) require.NoError(t, err) require.Equal(t, tt.expect.idx, idx) @@ -2501,16 +2502,16 @@ func TestStore_IntentionTopology_Destination(t *testing.T) { services structs.ServiceList } tests := []struct { - name string - defaultDecision acl.EnforcementDecision - intentions []structs.ServiceIntentionsConfigEntry - target structs.ServiceName - downstreams bool - expect expect + name string + defaultAllow bool + intentions []structs.ServiceIntentionsConfigEntry + target structs.ServiceName + downstreams bool + expect expect }{ { - name: "(upstream) acl allow all but intentions deny one, destination target", - defaultDecision: acl.Allow, + name: "(upstream) default allow all but intentions deny one, destination target", + defaultAllow: true, intentions: []structs.ServiceIntentionsConfigEntry{ { Kind: structs.ServiceIntentions, @@ -2536,8 +2537,8 @@ func TestStore_IntentionTopology_Destination(t *testing.T) { }, }, { - name: "(upstream) acl deny all intentions allow one, destination target", - defaultDecision: acl.Deny, + name: "(upstream) default deny intentions allow one, destination target", + defaultAllow: false, intentions: []structs.ServiceIntentionsConfigEntry{ { Kind: structs.ServiceIntentions, @@ -2563,8 +2564,8 @@ func TestStore_IntentionTopology_Destination(t *testing.T) { }, }, { - name: "(upstream) acl deny all check only destinations show, service target", - defaultDecision: acl.Deny, + name: "(upstream) default deny check only destinations show, service target", + defaultAllow: false, intentions: []structs.ServiceIntentionsConfigEntry{ { Kind: structs.ServiceIntentions, @@ -2585,8 +2586,8 @@ func TestStore_IntentionTopology_Destination(t *testing.T) { }, }, { - name: "(upstream) acl allow all check only destinations show, service target", - defaultDecision: acl.Allow, + name: "(upstream) default allow check only destinations show, service target", + defaultAllow: true, intentions: []structs.ServiceIntentionsConfigEntry{ { Kind: structs.ServiceIntentions, @@ -2637,7 +2638,7 @@ func TestStore_IntentionTopology_Destination(t *testing.T) { idx++ } - idx, got, err := s.IntentionTopology(nil, tt.target, tt.downstreams, tt.defaultDecision, structs.IntentionTargetDestination) + idx, got, err := s.IntentionTopology(nil, tt.target, tt.downstreams, tt.defaultAllow, structs.IntentionTargetDestination) require.NoError(t, err) require.Equal(t, tt.expect.idx, idx) @@ -2664,7 +2665,7 @@ func TestStore_IntentionTopology_Watches(t *testing.T) { target := structs.NewServiceName("web", structs.DefaultEnterpriseMetaInDefaultPartition()) ws := memdb.NewWatchSet() - index, got, err := s.IntentionTopology(ws, target, false, acl.Deny, structs.IntentionTargetService) + index, got, err := s.IntentionTopology(ws, target, false, false, structs.IntentionTargetService) require.NoError(t, err) require.Equal(t, uint64(0), index) require.Empty(t, got) @@ -2686,7 +2687,7 @@ func TestStore_IntentionTopology_Watches(t *testing.T) { // Reset the WatchSet ws = memdb.NewWatchSet() - index, got, err = s.IntentionTopology(ws, target, false, acl.Deny, structs.IntentionTargetService) + index, got, err = s.IntentionTopology(ws, target, false, false, structs.IntentionTargetService) require.NoError(t, err) require.Equal(t, uint64(2), index) // Because API is a virtual service, it is included in this output. @@ -2708,7 +2709,7 @@ func TestStore_IntentionTopology_Watches(t *testing.T) { // require.False(t, watchFired(ws)) // Result should not have changed - index, got, err = s.IntentionTopology(ws, target, false, acl.Deny, structs.IntentionTargetService) + index, got, err = s.IntentionTopology(ws, target, false, false, structs.IntentionTargetService) require.NoError(t, err) require.Equal(t, uint64(3), index) require.Equal(t, structs.ServiceList{structs.NewServiceName("api", nil)}, got) @@ -2723,7 +2724,7 @@ func TestStore_IntentionTopology_Watches(t *testing.T) { require.True(t, watchFired(ws)) // Reset the WatchSet - index, got, err = s.IntentionTopology(nil, target, false, acl.Deny, structs.IntentionTargetService) + index, got, err = s.IntentionTopology(nil, target, false, false, structs.IntentionTargetService) require.NoError(t, err) require.Equal(t, uint64(4), index) diff --git a/agent/consul/state/memdb.go b/agent/consul/state/memdb.go index 93707d0e0751..7dcce173f99b 100644 --- a/agent/consul/state/memdb.go +++ b/agent/consul/state/memdb.go @@ -196,22 +196,24 @@ func (db *readDB) ReadTxn() AbortTxn { } var ( - EventTopicServiceHealth = pbsubscribe.Topic_ServiceHealth - EventTopicServiceHealthConnect = pbsubscribe.Topic_ServiceHealthConnect - EventTopicMeshConfig = pbsubscribe.Topic_MeshConfig - EventTopicServiceResolver = pbsubscribe.Topic_ServiceResolver - EventTopicIngressGateway = pbsubscribe.Topic_IngressGateway - EventTopicServiceIntentions = pbsubscribe.Topic_ServiceIntentions - EventTopicServiceDefaults = pbsubscribe.Topic_ServiceDefaults - EventTopicServiceList = pbsubscribe.Topic_ServiceList - EventTopicAPIGateway = pbsubscribe.Topic_APIGateway - EventTopicTCPRoute = pbsubscribe.Topic_TCPRoute - EventTopicHTTPRoute = pbsubscribe.Topic_HTTPRoute - EventTopicInlineCertificate = pbsubscribe.Topic_InlineCertificate - EventTopicBoundAPIGateway = pbsubscribe.Topic_BoundAPIGateway - EventTopicIPRateLimit = pbsubscribe.Topic_IPRateLimit - EventTopicSamenessGroup = pbsubscribe.Topic_SamenessGroup - EventTopicJWTProvider = pbsubscribe.Topic_JWTProvider + EventTopicServiceHealth = pbsubscribe.Topic_ServiceHealth + EventTopicServiceHealthConnect = pbsubscribe.Topic_ServiceHealthConnect + EventTopicMeshConfig = pbsubscribe.Topic_MeshConfig + EventTopicServiceResolver = pbsubscribe.Topic_ServiceResolver + EventTopicIngressGateway = pbsubscribe.Topic_IngressGateway + EventTopicServiceIntentions = pbsubscribe.Topic_ServiceIntentions + EventTopicServiceDefaults = pbsubscribe.Topic_ServiceDefaults + EventTopicServiceList = pbsubscribe.Topic_ServiceList + EventTopicAPIGateway = pbsubscribe.Topic_APIGateway + EventTopicTCPRoute = pbsubscribe.Topic_TCPRoute + EventTopicHTTPRoute = pbsubscribe.Topic_HTTPRoute + EventTopicFileSystemCertificate = pbsubscribe.Topic_FileSystemCertificate + EventTopicInlineCertificate = pbsubscribe.Topic_InlineCertificate + EventTopicBoundAPIGateway = pbsubscribe.Topic_BoundAPIGateway + EventTopicIPRateLimit = pbsubscribe.Topic_IPRateLimit + EventTopicSamenessGroup = pbsubscribe.Topic_SamenessGroup + EventTopicJWTProvider = pbsubscribe.Topic_JWTProvider + EventTopicExportedServices = pbsubscribe.Topic_ExportedServices ) func processDBChanges(tx ReadTxn, changes Changes) ([]stream.Event, error) { diff --git a/agent/consul/state/store_integration_test.go b/agent/consul/state/store_integration_test.go index 25a91c558646..bf51039e2508 100644 --- a/agent/consul/state/store_integration_test.go +++ b/agent/consul/state/store_integration_test.go @@ -72,7 +72,7 @@ func TestStore_IntegrationWithEventPublisher_ACLTokenUpdate(t *testing.T) { // Ensure the reset event was sent. err = assertErr(t, eventCh) - require.Equal(t, stream.ErrSubForceClosed, err) + require.Equal(t, stream.ErrACLChanged, err) // Register another subscription. subscription2 := &stream.SubscribeRequest{ @@ -101,7 +101,7 @@ func TestStore_IntegrationWithEventPublisher_ACLTokenUpdate(t *testing.T) { // Ensure the reset event was sent. err = assertErr(t, eventCh2) - require.Equal(t, stream.ErrSubForceClosed, err) + require.Equal(t, stream.ErrACLChanged, err) } func TestStore_IntegrationWithEventPublisher_ACLPolicyUpdate(t *testing.T) { @@ -191,7 +191,7 @@ func TestStore_IntegrationWithEventPublisher_ACLPolicyUpdate(t *testing.T) { // Ensure the reload event was sent. err = assertErr(t, eventCh) - require.Equal(t, stream.ErrSubForceClosed, err) + require.Equal(t, stream.ErrACLChanged, err) // Register another subscription. subscription3 := &stream.SubscribeRequest{ @@ -381,7 +381,7 @@ func assertReset(t *testing.T, eventCh <-chan nextResult, allowEOS bool) { } } require.Error(t, next.Err) - require.Equal(t, stream.ErrSubForceClosed, next.Err) + require.Equal(t, stream.ErrACLChanged, next.Err) return case <-time.After(100 * time.Millisecond): t.Fatalf("no err after 100ms") diff --git a/agent/consul/state/txn.go b/agent/consul/state/txn.go index 30189fc1ed60..66cc4bb33d40 100644 --- a/agent/consul/state/txn.go +++ b/agent/consul/state/txn.go @@ -4,17 +4,31 @@ package state import ( + "errors" "fmt" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" ) +type UnsupportedFSMApplyPanicError struct { + Wrapped error +} + +func (e *UnsupportedFSMApplyPanicError) Unwrap() error { + return e.Wrapped +} + +func (e *UnsupportedFSMApplyPanicError) Error() string { + return e.Wrapped.Error() +} + // txnKVS handles all KV-related operations. func (s *Store) txnKVS(tx WriteTxn, idx uint64, op *structs.TxnKVOp) (structs.TxnResults, error) { var entry *structs.DirEntry var err error + // enumcover: api.KVOp switch op.Verb { case api.KVSet: entry = &op.DirEnt @@ -95,7 +109,7 @@ func (s *Store) txnKVS(tx WriteTxn, idx uint64, op *structs.TxnKVOp) (structs.Tx } default: - err = fmt.Errorf("unknown KV verb %q", op.Verb) + err = &UnsupportedFSMApplyPanicError{fmt.Errorf("unknown KV verb %q", op.Verb)} } if err != nil { return nil, err @@ -123,11 +137,12 @@ func (s *Store) txnKVS(tx WriteTxn, idx uint64, op *structs.TxnKVOp) (structs.Tx func txnSession(tx WriteTxn, idx uint64, op *structs.TxnSessionOp) error { var err error + // enumcover: api.SessionOp switch op.Verb { case api.SessionDelete: err = sessionDeleteWithSession(tx, &op.Session, idx) default: - err = fmt.Errorf("unknown Session verb %q", op.Verb) + return &UnsupportedFSMApplyPanicError{fmt.Errorf("unknown session verb %q", op.Verb)} } if err != nil { return fmt.Errorf("failed to delete session: %v", err) @@ -146,11 +161,17 @@ func txnLegacyIntention(tx WriteTxn, idx uint64, op *structs.TxnIntentionOp) err case structs.IntentionOpDelete: return legacyIntentionDeleteTxn(tx, idx, op.Intention.ID) case structs.IntentionOpDeleteAll: - fallthrough // deliberately not available via this api + // deliberately not available via this api + return fmt.Errorf("Intention op not supported %q", op.Op) case structs.IntentionOpUpsert: - fallthrough // deliberately not available via this api + // deliberately not available via this api + return fmt.Errorf("Intention op not supported %q", op.Op) default: - return fmt.Errorf("unknown Intention op %q", op.Op) + // If we've gotten to this point, the unknown verb has slipped by + // endpoint validation. This means it could be a mismatch in Server versions + // that are sending known verbs as part of Raft logs. We panic rather than silently + // swallowing the error during Raft Apply. + panic(fmt.Sprintf("unknown Intention op %q", op.Op)) } } @@ -202,7 +223,7 @@ func (s *Store) txnNode(tx WriteTxn, idx uint64, op *structs.TxnNodeOp) (structs } default: - err = fmt.Errorf("unknown Node verb %q", op.Verb) + err = &UnsupportedFSMApplyPanicError{fmt.Errorf("unknown Node verb %q", op.Verb)} } if err != nil { return nil, err @@ -271,7 +292,7 @@ func (s *Store) txnService(tx WriteTxn, idx uint64, op *structs.TxnServiceOp) (s return nil, err default: - return nil, fmt.Errorf("unknown Service verb %q", op.Verb) + return nil, &UnsupportedFSMApplyPanicError{fmt.Errorf("unknown Service verb %q", op.Verb)} } } @@ -326,7 +347,7 @@ func (s *Store) txnCheck(tx WriteTxn, idx uint64, op *structs.TxnCheckOp) (struc } default: - err = fmt.Errorf("unknown Check verb %q", op.Verb) + err = &UnsupportedFSMApplyPanicError{fmt.Errorf("unknown check verb %q", op.Verb)} } if err != nil { return nil, err @@ -352,7 +373,7 @@ func (s *Store) txnCheck(tx WriteTxn, idx uint64, op *structs.TxnCheckOp) (struc // txnDispatch runs the given operations inside the state store transaction. func (s *Store) txnDispatch(tx WriteTxn, idx uint64, ops structs.TxnOps) (structs.TxnResults, structs.TxnErrors) { results := make(structs.TxnResults, 0, len(ops)) - errors := make(structs.TxnErrors, 0, len(ops)) + errs := make(structs.TxnErrors, 0, len(ops)) for i, op := range ops { var ret structs.TxnResults var err error @@ -374,24 +395,33 @@ func (s *Store) txnDispatch(tx WriteTxn, idx uint64, ops structs.TxnOps) (struct // compatibility with pre-1.9.0 raft logs and during upgrades. err = txnLegacyIntention(tx, idx, op.Intention) default: - err = fmt.Errorf("no operation specified") + panic("no operation specified") } // Accumulate the results. results = append(results, ret...) + var panicErr *UnsupportedFSMApplyPanicError + if errors.As(err, &panicErr) { + // If we've gotten to this point, the unknown verb has slipped by + // endpoint validation. This means it could be a mismatch in Server versions + // that are sending known verbs as part of Raft logs. We panic rather than silently + // swallowing the error during Raft Apply. See NET-9016 for historical context. + panic(panicErr.Wrapped) + } + // Capture any error along with the index of the operation that // failed. if err != nil { - errors = append(errors, &structs.TxnError{ + errs = append(errs, &structs.TxnError{ OpIndex: i, What: err.Error(), }) } } - if len(errors) > 0 { - return nil, errors + if len(errs) > 0 { + return nil, errs } return results, nil diff --git a/agent/consul/state/txn_test.go b/agent/consul/state/txn_test.go index bda004a63a3b..c3d95a4efe3e 100644 --- a/agent/consul/state/txn_test.go +++ b/agent/consul/state/txn_test.go @@ -1058,14 +1058,6 @@ func TestStateStore_Txn_KVS_Rollback(t *testing.T) { }, }, }, - &structs.TxnOp{ - KV: &structs.TxnKVOp{ - Verb: "nope", - DirEnt: structs.DirEntry{ - Key: "foo/delete", - }, - }, - }, } results, errors := s.TxnRW(7, ops) if len(errors) != len(ops) { @@ -1086,7 +1078,6 @@ func TestStateStore_Txn_KVS_Rollback(t *testing.T) { `key "nope" doesn't exist`, "current modify index", `key "nope" doesn't exist`, - "unknown KV verb", } if len(errors) != len(expected) { t.Fatalf("bad len: %d != %d", len(errors), len(expected)) @@ -1415,3 +1406,64 @@ func TestStateStore_Txn_KVS_ModifyIndexes(t *testing.T) { } } } + +// TestStateStore_UnknownTxnOperationsPanic validates that unknown txn operations panic. +// If we error in this case this is from an FSM Apply, the state store of this agent could potentially be out of +// sync with other agents that applied the operation. In the case of responding to a local endpoint, we require +// that the operation type be validated prior to being sent to the state store. +// See NET-9016 for historical context. +func TestStateStore_UnknownTxnOperationsPanic(t *testing.T) { + s := testStateStore(t) + + testCases := []structs.TxnOps{ + { + &structs.TxnOp{ + KV: &structs.TxnKVOp{ + Verb: "sand-the-floor", + DirEnt: structs.DirEntry{ + Key: "foo/a", + }, + }, + }, + }, + { + &structs.TxnOp{ + Node: &structs.TxnNodeOp{ + Verb: "wax-the-car", + }, + }, + }, + { + &structs.TxnOp{ + Service: &structs.TxnServiceOp{ + Verb: "paint-the-house", + }, + }, + }, + { + &structs.TxnOp{ + Check: &structs.TxnCheckOp{ + Verb: "paint-the-fence", + }, + }, + }, + { + &structs.TxnOp{ + Session: &structs.TxnSessionOp{ + Verb: "sweep-the-knee", + }, + }, + }, + { + &structs.TxnOp{ + Intention: &structs.TxnIntentionOp{ // nolint:staticcheck // SA1019 intentional use of deprecated field + Op: "flying-crane-kick", + }, + }, + }, + } + + for _, tc := range testCases { + require.Panics(t, func() { s.TxnRW(3, tc) }) + } +} diff --git a/agent/consul/state/usage.go b/agent/consul/state/usage.go index 20515e2e7b0c..90f89a673fa3 100644 --- a/agent/consul/state/usage.go +++ b/agent/consul/state/usage.go @@ -410,7 +410,7 @@ func (s *Store) PeeringUsage() (uint64, PeeringUsage, error) { // ServiceUsage returns the latest seen Raft index, a compiled set of service // usage data, and any errors. -func (s *Store) ServiceUsage(ws memdb.WatchSet) (uint64, structs.ServiceUsage, error) { +func (s *Store) ServiceUsage(ws memdb.WatchSet, tenantUsage bool) (uint64, structs.ServiceUsage, error) { tx := s.db.ReadTxn() defer tx.Abort() @@ -450,6 +450,12 @@ func (s *Store) ServiceUsage(ws memdb.WatchSet) (uint64, structs.ServiceUsage, e BillableServiceInstances: billableServiceInstances.Count, Nodes: nodes.Count, } + + // Unless we need to gather per-tenant usage go ahead and return what we have + if !tenantUsage { + return serviceInstances.Index, usage, nil + } + results, err := compileEnterpriseServiceUsage(ws, tx, usage) if err != nil { return 0, structs.ServiceUsage{}, fmt.Errorf("failed services lookup: %s", err) diff --git a/agent/consul/state/usage_test.go b/agent/consul/state/usage_test.go index 4195779b8c03..ed0d68862859 100644 --- a/agent/consul/state/usage_test.go +++ b/agent/consul/state/usage_test.go @@ -155,7 +155,7 @@ func TestStateStore_Usage_ServiceUsageEmpty(t *testing.T) { s := testStateStore(t) // No services have been registered, and thus no usage entry exists - idx, usage, err := s.ServiceUsage(nil) + idx, usage, err := s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, idx, uint64(0)) require.Equal(t, usage.Services, 0) @@ -186,7 +186,7 @@ func TestStateStore_Usage_ServiceUsage(t *testing.T) { testRegisterAPIService(t, s, 20, "node2", "api") ws := memdb.NewWatchSet() - idx, usage, err := s.ServiceUsage(ws) + idx, usage, err := s.ServiceUsage(ws, true) require.NoError(t, err) require.Equal(t, idx, uint64(20)) require.Equal(t, 9, usage.Services) @@ -232,7 +232,7 @@ func TestStateStore_Usage_ServiceUsage_DeleteNode(t *testing.T) { testRegisterSidecarProxy(t, s, 3, "node1", "service2") testRegisterConnectNativeService(t, s, 4, "node1", "service-connect") - idx, usage, err := s.ServiceUsage(nil) + idx, usage, err := s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, idx, uint64(4)) require.Equal(t, 3, usage.Services) @@ -243,7 +243,7 @@ func TestStateStore_Usage_ServiceUsage_DeleteNode(t *testing.T) { require.NoError(t, s.DeleteNode(4, "node1", nil, "")) - idx, usage, err = s.ServiceUsage(nil) + idx, usage, err = s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, idx, uint64(4)) require.Equal(t, usage.Services, 0) @@ -272,7 +272,7 @@ func TestStateStore_Usage_ServiceUsagePeering(t *testing.T) { testRegisterConnectNativeService(t, s, 7, "node2", "service-native") testutil.RunStep(t, "writes", func(t *testing.T) { - idx, usage, err := s.ServiceUsage(nil) + idx, usage, err := s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, uint64(7), idx) require.Equal(t, 3, usage.Services) @@ -285,7 +285,7 @@ func TestStateStore_Usage_ServiceUsagePeering(t *testing.T) { testutil.RunStep(t, "deletes", func(t *testing.T) { require.NoError(t, s.DeleteNode(7, "node1", nil, peerName)) require.NoError(t, s.DeleteNode(8, "node2", nil, "")) - idx, usage, err := s.ServiceUsage(nil) + idx, usage, err := s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, uint64(8), idx) require.Equal(t, 0, usage.Services) @@ -324,7 +324,7 @@ func TestStateStore_Usage_Restore(t *testing.T) { require.Equal(t, idx, uint64(9)) require.Equal(t, nodeUsage.Nodes, 1) - idx, usage, err := s.ServiceUsage(nil) + idx, usage, err := s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, idx, uint64(9)) require.Equal(t, usage.Services, 1) @@ -425,7 +425,7 @@ func TestStateStore_Usage_ServiceUsage_updatingService(t *testing.T) { require.NoError(t, s.EnsureService(2, "node1", svc)) // We renamed a service with a single instance, so we maintain 1 service. - idx, usage, err := s.ServiceUsage(nil) + idx, usage, err := s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, idx, uint64(2)) require.Equal(t, usage.Services, 1) @@ -446,7 +446,7 @@ func TestStateStore_Usage_ServiceUsage_updatingService(t *testing.T) { require.NoError(t, s.EnsureService(3, "node1", svc)) // We renamed a service with a single instance, so we maintain 1 service. - idx, usage, err := s.ServiceUsage(nil) + idx, usage, err := s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, idx, uint64(3)) require.Equal(t, usage.Services, 1) @@ -468,7 +468,7 @@ func TestStateStore_Usage_ServiceUsage_updatingService(t *testing.T) { require.NoError(t, s.EnsureService(4, "node1", svc)) // We renamed a service with a single instance, so we maintain 1 service. - idx, usage, err := s.ServiceUsage(nil) + idx, usage, err := s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, idx, uint64(4)) require.Equal(t, usage.Services, 1) @@ -500,7 +500,7 @@ func TestStateStore_Usage_ServiceUsage_updatingService(t *testing.T) { } require.NoError(t, s.EnsureService(6, "node1", svc3)) - idx, usage, err := s.ServiceUsage(nil) + idx, usage, err := s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, idx, uint64(6)) require.Equal(t, usage.Services, 2) @@ -519,7 +519,7 @@ func TestStateStore_Usage_ServiceUsage_updatingService(t *testing.T) { } require.NoError(t, s.EnsureService(7, "node1", update)) - idx, usage, err = s.ServiceUsage(nil) + idx, usage, err = s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, idx, uint64(7)) require.Equal(t, usage.Services, 3) @@ -546,7 +546,7 @@ func TestStateStore_Usage_ServiceUsage_updatingConnectProxy(t *testing.T) { require.NoError(t, s.EnsureService(2, "node1", svc)) // We renamed a service with a single instance, so we maintain 1 service. - idx, usage, err := s.ServiceUsage(nil) + idx, usage, err := s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, idx, uint64(2)) require.Equal(t, usage.Services, 1) @@ -573,7 +573,7 @@ func TestStateStore_Usage_ServiceUsage_updatingConnectProxy(t *testing.T) { } require.NoError(t, s.EnsureService(4, "node1", svc3)) - idx, usage, err := s.ServiceUsage(nil) + idx, usage, err := s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, idx, uint64(4)) require.Equal(t, usage.Services, 2) @@ -589,7 +589,7 @@ func TestStateStore_Usage_ServiceUsage_updatingConnectProxy(t *testing.T) { } require.NoError(t, s.EnsureService(5, "node1", update)) - idx, usage, err = s.ServiceUsage(nil) + idx, usage, err = s.ServiceUsage(nil, true) require.NoError(t, err) require.Equal(t, idx, uint64(5)) require.Equal(t, usage.Services, 3) diff --git a/agent/consul/stream/event_publisher.go b/agent/consul/stream/event_publisher.go index bb6d87f8bacf..cf1454bce802 100644 --- a/agent/consul/stream/event_publisher.go +++ b/agent/consul/stream/event_publisher.go @@ -23,7 +23,7 @@ type EventPublisher struct { // seconds. snapCacheTTL time.Duration - // This lock protects the snapCache, topicBuffers and topicBuffer.refs. + // This lock protects the snapCache, topicBuffers, snapshotHandlers, and topicBuffer.refs. lock sync.RWMutex // topicBuffers stores the head of the linked-list buffers to publish events to @@ -116,16 +116,18 @@ func NewEventPublisher(snapCacheTTL time.Duration) *EventPublisher { } // RegisterHandler will register a new snapshot handler function. The expectation is -// that all handlers get registered prior to the event publisher being Run. Handler -// registration is therefore not concurrency safe and access to handlers is internally -// not synchronized. Passing supportsWildcard allows consumers to subscribe to events -// on this topic with *any* subject (by requesting SubjectWildcard) but this must be -// supported by the handler function. +// that all handlers get registered prior to the event publisher being Run. Passing +// supportsWildcard allows consumers to subscribe to events on this topic with *any* +// subject (by requesting SubjectWildcard) but this must be supported by the handler +// function. func (e *EventPublisher) RegisterHandler(topic Topic, handler SnapshotFunc, supportsWildcard bool) error { if topic.String() == "" { return fmt.Errorf("the topic cannnot be empty") } + e.lock.Lock() + defer e.lock.Unlock() + if _, found := e.snapshotHandlers[topic]; found { return fmt.Errorf("a handler is already registered for the topic: %s", topic.String()) } @@ -142,12 +144,33 @@ func (e *EventPublisher) RegisterHandler(topic Topic, handler SnapshotFunc, supp return nil } +func (e *EventPublisher) RefreshAllTopics() { + topics := make(map[Topic]struct{}) + + e.lock.Lock() + for topic := range e.snapshotHandlers { + topics[topic] = struct{}{} + e.forceEvictByTopicLocked(topic) + } + e.lock.Unlock() + + for topic := range topics { + e.subscriptions.closeAllByTopic(topic) + } +} + func (e *EventPublisher) RefreshTopic(topic Topic) error { - if _, found := e.snapshotHandlers[topic]; !found { + e.lock.Lock() + _, found := e.snapshotHandlers[topic] + e.lock.Unlock() + + if !found { return fmt.Errorf("topic %s is not registered", topic) } - e.forceEvictByTopic(topic) + e.lock.Lock() + e.forceEvictByTopicLocked(topic) + e.lock.Unlock() e.subscriptions.closeAllByTopic(topic) return nil @@ -370,7 +393,7 @@ func (s *subscriptions) closeSubscriptionsForTokens(tokenSecretIDs []string) { for _, secretID := range tokenSecretIDs { if subs, ok := s.byToken[secretID]; ok { for _, sub := range subs { - sub.forceClose() + sub.closeACLChanged() } } } @@ -438,14 +461,12 @@ func (e *EventPublisher) setCachedSnapshotLocked(req *SubscribeRequest, snap *ev }) } -// forceEvictByTopic will remove all entries from the snapshot cache for a given topic. -// This method should be called while holding the publishers lock. -func (e *EventPublisher) forceEvictByTopic(topic Topic) { - e.lock.Lock() +// forceEvictByTopicLocked will remove all entries from the snapshot cache for a given topic. +// This method should be called while holding the EventPublisher's lock. +func (e *EventPublisher) forceEvictByTopicLocked(topic Topic) { for key := range e.snapCache { if key.Topic == topic.String() { delete(e.snapCache, key) } } - e.lock.Unlock() } diff --git a/agent/consul/stream/event_publisher_test.go b/agent/consul/stream/event_publisher_test.go index 4ae53ebcbf8f..09e3bc70911d 100644 --- a/agent/consul/stream/event_publisher_test.go +++ b/agent/consul/stream/event_publisher_test.go @@ -210,9 +210,11 @@ func TestEventPublisher_SubscribeWithIndex0_FromCache(t *testing.T) { require.NoError(t, err) defer sub.Unsubscribe() + publisher.lock.Lock() publisher.snapshotHandlers[testTopic] = func(_ SubscribeRequest, _ SnapshotAppender) (uint64, error) { return 0, fmt.Errorf("error should not be seen, cache should have been used") } + publisher.lock.Unlock() sub, err = publisher.Subscribe(req) require.NoError(t, err) @@ -394,9 +396,11 @@ func TestEventPublisher_SubscribeWithIndexNotZero_NewSnapshotFromCache(t *testin publisher.publishEvent([]Event{nextEvent}) }) + publisher.lock.Lock() publisher.snapshotHandlers[testTopic] = func(_ SubscribeRequest, _ SnapshotAppender) (uint64, error) { return 0, fmt.Errorf("error should not be seen, cache should have been used") } + publisher.lock.Unlock() testutil.RunStep(t, "resume the subscription", func(t *testing.T) { newReq := *req @@ -476,9 +480,11 @@ func TestEventPublisher_SubscribeWithIndexNotZero_NewSnapshot_WithCache(t *testi require.Equal(t, uint64(3), next.Index) }) + publisher.lock.Lock() publisher.snapshotHandlers[testTopic] = func(_ SubscribeRequest, _ SnapshotAppender) (uint64, error) { return 0, fmt.Errorf("error should not be seen, cache should have been used") } + publisher.lock.Unlock() testutil.RunStep(t, "resume the subscription", func(t *testing.T) { newReq := *req diff --git a/agent/consul/stream/subscription.go b/agent/consul/stream/subscription.go index 23911eff2e65..187b2c92d471 100644 --- a/agent/consul/stream/subscription.go +++ b/agent/consul/stream/subscription.go @@ -25,9 +25,13 @@ const ( // will not return new events. subStateUnsub = 2 - // subStateShutting down indicates the subscription was closed due to + // subStateShuttingDown indicates the subscription was closed due to // the server being shut down. subStateShuttingDown = 3 + + // subStateACLChanged indicates the subscription was closed due to + // a change in ACLs. + subStateACLChanged = 4 ) // ErrSubForceClosed is a error signalling the subscription has been @@ -39,6 +43,12 @@ var ErrSubForceClosed = errors.New("subscription closed by server, client must r // subscribe to a different server to get streaming event updates. var ErrShuttingDown = errors.New("subscription closed by server, server is shutting down") +// ErrACLChanged is an error to signal that the subscription has +// been closed because a change in ACL token or its associated roles or policies has occurred. +// If the token or policy is no longer valid, the client should resubscribe using a valid token. Otherwise, +// the client should resubscribe using the same token. +var ErrACLChanged = errors.New("subscription closed by server, ACL change occurred") + // Subscription provides events on a Topic. Events may be filtered by Key. // Events are returned by Next(), and may start with a Snapshot of events. type Subscription struct { @@ -131,6 +141,8 @@ func (s *Subscription) requireStateOpen() error { return ErrSubForceClosed case subStateShuttingDown: return ErrShuttingDown + case subStateACLChanged: + return ErrACLChanged case subStateUnsub: return fmt.Errorf("subscription was closed by unsubscribe") default: @@ -166,6 +178,14 @@ func (s *Subscription) shutDown() { } } +// Close the subscription and indicate that an ACL change occurred. This change may require +// a client to subscribe with a new token or re-subscribe with an existing token. +func (s *Subscription) closeACLChanged() { + if atomic.CompareAndSwapUint32(&s.state, subStateOpen, subStateACLChanged) { + close(s.closed) + } +} + // Unsubscribe the subscription, freeing resources. func (s *Subscription) Unsubscribe() { if atomic.CompareAndSwapUint32(&s.state, subStateOpen, subStateUnsub) { diff --git a/agent/consul/testdata/v2-resource-dependencies.md b/agent/consul/testdata/v2-resource-dependencies.md index 1e34812446a4..7bcb0d55c4f4 100644 --- a/agent/consul/testdata/v2-resource-dependencies.md +++ b/agent/consul/testdata/v2-resource-dependencies.md @@ -1,15 +1,5 @@ ```mermaid flowchart TD - auth/v2beta1/computedtrafficpermissions --> auth/v2beta1/trafficpermissions - auth/v2beta1/computedtrafficpermissions --> auth/v2beta1/workloadidentity - catalog/v2beta1/failoverpolicy --> catalog/v2beta1/service - catalog/v2beta1/healthstatus - catalog/v2beta1/node --> catalog/v2beta1/healthstatus - catalog/v2beta1/service - catalog/v2beta1/serviceendpoints --> catalog/v2beta1/service - catalog/v2beta1/serviceendpoints --> catalog/v2beta1/workload - catalog/v2beta1/workload --> catalog/v2beta1/healthstatus - catalog/v2beta1/workload --> catalog/v2beta1/node demo/v1/album demo/v1/artist demo/v1/concept @@ -17,29 +7,13 @@ flowchart TD demo/v1/recordlabel demo/v2/album demo/v2/artist + hcp/v2/link + hcp/v2/telemetrystate internal/v1/tombstone - mesh/v2beta1/computedexplicitdestinations --> catalog/v2beta1/service - mesh/v2beta1/computedexplicitdestinations --> catalog/v2beta1/workload - mesh/v2beta1/computedexplicitdestinations --> mesh/v2beta1/computedroutes - mesh/v2beta1/computedexplicitdestinations --> mesh/v2beta1/destinations - mesh/v2beta1/computedproxyconfiguration --> catalog/v2beta1/workload - mesh/v2beta1/computedproxyconfiguration --> mesh/v2beta1/proxyconfiguration - mesh/v2beta1/computedroutes --> catalog/v2beta1/failoverpolicy - mesh/v2beta1/computedroutes --> catalog/v2beta1/service - mesh/v2beta1/computedroutes --> mesh/v2beta1/destinationpolicy - mesh/v2beta1/computedroutes --> mesh/v2beta1/grpcroute - mesh/v2beta1/computedroutes --> mesh/v2beta1/httproute - mesh/v2beta1/computedroutes --> mesh/v2beta1/tcproute - mesh/v2beta1/destinationpolicy - mesh/v2beta1/destinations - mesh/v2beta1/grpcroute - mesh/v2beta1/httproute - mesh/v2beta1/proxyconfiguration - mesh/v2beta1/proxystatetemplate --> auth/v2beta1/computedtrafficpermissions - mesh/v2beta1/proxystatetemplate --> catalog/v2beta1/service - mesh/v2beta1/proxystatetemplate --> catalog/v2beta1/workload - mesh/v2beta1/proxystatetemplate --> mesh/v2beta1/computedexplicitdestinations - mesh/v2beta1/proxystatetemplate --> mesh/v2beta1/computedproxyconfiguration - mesh/v2beta1/proxystatetemplate --> mesh/v2beta1/computedroutes - mesh/v2beta1/tcproute + multicluster/v2/computedexportedservices --> multicluster/v2/exportedservices + multicluster/v2/computedexportedservices --> multicluster/v2/namespaceexportedservices + multicluster/v2/computedexportedservices --> multicluster/v2/partitionexportedservices + multicluster/v2/exportedservices + multicluster/v2/namespaceexportedservices + multicluster/v2/partitionexportedservices ``` \ No newline at end of file diff --git a/agent/consul/txn_endpoint.go b/agent/consul/txn_endpoint.go index f39cd502cb17..e704c9a2eda1 100644 --- a/agent/consul/txn_endpoint.go +++ b/agent/consul/txn_endpoint.go @@ -57,8 +57,15 @@ func (t *Txn) preCheck(authorizer resolver.Result, ops structs.TxnOps) structs.T }) } case op.Node != nil: - // Skip the pre-apply checks if this is a GET. - if op.Node.Verb == api.NodeGet { + requiresPreApply, err := nodeVerbValidate(op.Node.Verb) + if err != nil { + errors = append(errors, &structs.TxnError{ + OpIndex: i, + What: err.Error(), + }) + break + } + if !requiresPreApply { break } @@ -79,8 +86,15 @@ func (t *Txn) preCheck(authorizer resolver.Result, ops structs.TxnOps) structs.T }) } case op.Service != nil: - // Skip the pre-apply checks if this is a GET. - if op.Service.Verb == api.ServiceGet { + requiresPreApply, err := serviceVerbValidate(op.Service.Verb) + if err != nil { + errors = append(errors, &structs.TxnError{ + OpIndex: i, + What: err.Error(), + }) + break + } + if !requiresPreApply { break } @@ -92,8 +106,15 @@ func (t *Txn) preCheck(authorizer resolver.Result, ops structs.TxnOps) structs.T }) } case op.Check != nil: - // Skip the pre-apply checks if this is a GET. - if op.Check.Verb == api.CheckGet { + requiresPreApply, err := checkVerbValidate(op.Check.Verb) + if err != nil { + errors = append(errors, &structs.TxnError{ + OpIndex: i, + What: err.Error(), + }) + break + } + if !requiresPreApply { break } @@ -106,6 +127,25 @@ func (t *Txn) preCheck(authorizer resolver.Result, ops structs.TxnOps) structs.T What: err.Error(), }) } + case op.Intention != nil: + if err := intentionVerbValidate(op.Intention.Op); err != nil { + errors = append(errors, &structs.TxnError{ + OpIndex: i, + What: err.Error(), + }) + } + case op.Session != nil: + if err := sessionVerbValidate(op.Session.Verb); err != nil { + errors = append(errors, &structs.TxnError{ + OpIndex: i, + What: err.Error(), + }) + } + default: + errors = append(errors, &structs.TxnError{ + OpIndex: i, + What: "unknown operation type", + }) } } @@ -224,3 +264,70 @@ func (t *Txn) Read(args *structs.TxnReadRequest, reply *structs.TxnReadResponse) return nil } + +// nodeVerbValidate checks for a known operation type. For certain operations, +// it also indicated if further "preApply" checks are required. +func nodeVerbValidate(op api.NodeOp) (bool, error) { + // enumcover: api.NodeOp + switch op { + // Skip the pre-apply checks if this is a GET. + case api.NodeGet: + return false, nil + case api.NodeSet, api.NodeCAS, api.NodeDelete, api.NodeDeleteCAS: + return true, nil + default: + return false, fmt.Errorf("unknown node operation: %s", op) + } +} + +// serviceVerbValidate checks for a known operation type. For certain operations, +// it also indicated if further "preApply" checks are required. +func serviceVerbValidate(op api.ServiceOp) (bool, error) { + // enumcover: api.ServiceOp + switch op { + // Skip the pre-apply checks if this is a GET. + case api.ServiceGet: + return false, nil + case api.ServiceSet, api.ServiceCAS, api.ServiceDelete, api.ServiceDeleteCAS: + return true, nil + default: + return false, fmt.Errorf("unknown service operation: %s", op) + } +} + +// checkVerbValidate checks for a known operation type. For certain operations, +// it also indicated if further "preApply" checks are required. +func checkVerbValidate(op api.CheckOp) (bool, error) { + // enumcover: api.CheckOp + switch op { + // Skip the pre-apply checks if this is a GET. + case api.CheckGet: + return false, nil + case api.CheckSet, api.CheckCAS, api.CheckDelete, api.CheckDeleteCAS: + return true, nil + default: + return false, fmt.Errorf("unknown check operation: %s", op) + } +} + +// intentionVerbValidate checks for a known operation type. +func intentionVerbValidate(op structs.IntentionOp) error { + // enumcover: structs.IntentionOp + switch op { + case structs.IntentionOpCreate, structs.IntentionOpDelete, structs.IntentionOpUpdate, structs.IntentionOpDeleteAll, structs.IntentionOpUpsert: + return nil + default: + return fmt.Errorf("unknown intention operation: %s", op) + } +} + +// sessionVerbValidate checks for a known operation type. +func sessionVerbValidate(op api.SessionOp) error { + // enumcover: api.SessionOp + switch op { + case api.SessionDelete: + return nil + default: + return fmt.Errorf("unknown session operation: %s", op) + } +} diff --git a/agent/consul/txn_endpoint_test.go b/agent/consul/txn_endpoint_test.go index ef2ecd13a3f8..03bccf95ff5e 100644 --- a/agent/consul/txn_endpoint_test.go +++ b/agent/consul/txn_endpoint_test.go @@ -946,3 +946,128 @@ func TestTxn_Read_ACLDeny(t *testing.T) { require.Empty(t, out.Results) }) } + +// TestTxn_Validation works across RW and RO Txn endpoints validating the "preCheck()" operation consistently +// validates operations provided in the request. +func TestTxn_Validation(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + dir1, s1 := testServer(t) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + codec := rpcClient(t, s1) + defer codec.Close() + + testrpc.WaitForLeader(t, s1.RPC, "dc1") + + // Each one of these test cases should error as invalid. + testCases := []struct { + request structs.TxnReadRequest + expectedError string + }{ + { + request: structs.TxnReadRequest{ + Datacenter: "dc1", + Ops: structs.TxnOps{ + &structs.TxnOp{ + KV: &structs.TxnKVOp{ + Verb: "tick", + DirEnt: structs.DirEntry{ + Key: "nope", + }, + }, + }, + }, + }, + expectedError: "unknown KV operation", + }, + { + request: structs.TxnReadRequest{ + Datacenter: "dc1", + Ops: structs.TxnOps{ + &structs.TxnOp{ + Node: &structs.TxnNodeOp{ + Verb: "tick", + }, + }, + }, + }, + expectedError: "unknown node operation", + }, + { + request: structs.TxnReadRequest{ + Datacenter: "dc1", + Ops: structs.TxnOps{ + &structs.TxnOp{ + Service: &structs.TxnServiceOp{ + Verb: "tick", + }, + }, + }, + }, + expectedError: "unknown service operation", + }, + { + request: structs.TxnReadRequest{ + Datacenter: "dc1", + Ops: structs.TxnOps{ + &structs.TxnOp{ + Check: &structs.TxnCheckOp{ + Verb: "tick", + }, + }, + }, + }, + expectedError: "unknown check operation", + }, + { + request: structs.TxnReadRequest{ + Datacenter: "dc1", + Ops: structs.TxnOps{ + &structs.TxnOp{ + Session: &structs.TxnSessionOp{ + Verb: "tick", + }, + }, + }, + }, + expectedError: "unknown session operation", + }, + { + request: structs.TxnReadRequest{ + Datacenter: "dc1", + Ops: structs.TxnOps{ + &structs.TxnOp{ + Intention: &structs.TxnIntentionOp{ // nolint:staticcheck // SA1019 intentional use of deprecated field + Op: "BOOM!", + }, + }, + }, + }, + expectedError: "unknown intention operation", + }, + { + request: structs.TxnReadRequest{ + Datacenter: "dc1", + Ops: structs.TxnOps{ + &structs.TxnOp{ + // Intentionally Empty + }, + }, + }, + expectedError: "unknown operation type", + }, + } + + for _, tc := range testCases { + var out structs.TxnReadResponse + err := msgpackrpc.CallWithCodec(codec, "Txn.Read", &tc.request, &out) + require.NoError(t, err) + require.Greater(t, len(out.Errors), 0) + require.Contains(t, out.Errors[0].Error(), tc.expectedError) + } +} diff --git a/agent/consul/type_registry.go b/agent/consul/type_registry.go index 8bf093c41a11..cd2087e48f12 100644 --- a/agent/consul/type_registry.go +++ b/agent/consul/type_registry.go @@ -4,13 +4,10 @@ package consul import ( - "github.com/hashicorp/consul/internal/auth" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/mesh" + "github.com/hashicorp/consul/internal/hcp" "github.com/hashicorp/consul/internal/multicluster" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" - "github.com/hashicorp/consul/internal/tenancy" ) // NewTypeRegistry returns a registry populated with all supported resource @@ -24,11 +21,8 @@ func NewTypeRegistry() resource.Registry { registry := resource.NewRegistry() demo.RegisterTypes(registry) - mesh.RegisterTypes(registry) - catalog.RegisterTypes(registry) - auth.RegisterTypes(registry) - tenancy.RegisterTypes(registry) multicluster.RegisterTypes(registry) + hcp.RegisterTypes(registry) return registry } diff --git a/agent/consul/usagemetrics/usagemetrics.go b/agent/consul/usagemetrics/usagemetrics.go index 9539a743bbe6..a0336d7e5d32 100644 --- a/agent/consul/usagemetrics/usagemetrics.go +++ b/agent/consul/usagemetrics/usagemetrics.go @@ -15,79 +15,44 @@ import ( "github.com/hashicorp/serf/serf" "github.com/hashicorp/consul/agent/consul/state" + "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/version" ) var Gauges = []prometheus.GaugeDefinition{ - { - Name: []string{"consul", "state", "nodes"}, - Help: "Deprecated - please use state_nodes instead.", - }, { Name: []string{"state", "nodes"}, Help: "Measures the current number of nodes registered with Consul. It is only emitted by Consul servers. Added in v1.9.0.", }, - { - Name: []string{"consul", "state", "peerings"}, - Help: "Deprecated - please use state_peerings instead.", - }, { Name: []string{"state", "peerings"}, Help: "Measures the current number of peerings registered with Consul. It is only emitted by Consul servers. Added in v1.13.0.", }, - { - Name: []string{"consul", "state", "services"}, - Help: "Deprecated - please use state_services instead.", - }, { Name: []string{"state", "services"}, Help: "Measures the current number of unique services registered with Consul, based on service name. It is only emitted by Consul servers. Added in v1.9.0.", }, - { - Name: []string{"consul", "state", "service_instances"}, - Help: "Deprecated - please use state_service_instances instead.", - }, { Name: []string{"state", "service_instances"}, Help: "Measures the current number of unique services registered with Consul, based on service name. It is only emitted by Consul servers. Added in v1.9.0.", }, - { - Name: []string{"consul", "members", "clients"}, - Help: "Deprecated - please use members_clients instead.", - }, { Name: []string{"members", "clients"}, Help: "Measures the current number of client agents registered with Consul. It is only emitted by Consul servers. Added in v1.9.6.", }, - { - Name: []string{"consul", "members", "servers"}, - Help: "Deprecated - please use members_servers instead.", - }, { Name: []string{"members", "servers"}, Help: "Measures the current number of server agents registered with Consul. It is only emitted by Consul servers. Added in v1.9.6.", }, - { - Name: []string{"consul", "state", "kv_entries"}, - Help: "Deprecated - please use kv_entries instead.", - }, { Name: []string{"state", "kv_entries"}, Help: "Measures the current number of entries in the Consul KV store. It is only emitted by Consul servers. Added in v1.10.3.", }, - { - Name: []string{"consul", "state", "connect_instances"}, - Help: "Deprecated - please use state_connect_instances instead.", - }, { Name: []string{"state", "connect_instances"}, Help: "Measures the current number of unique connect service instances registered with Consul, labeled by Kind. It is only emitted by Consul servers. Added in v1.10.4.", }, - { - Name: []string{"consul", "state", "config_entries"}, - Help: "Deprecated - please use state_config_entries instead.", - }, { Name: []string{"state", "config_entries"}, Help: "Measures the current number of unique configuration entries registered with Consul, labeled by Kind. It is only emitted by Consul servers. Added in v1.10.4.", @@ -112,6 +77,7 @@ type Config struct { stateProvider StateProvider tickerInterval time.Duration getMembersFunc getMembersFunc + excludeTenancy bool } // WithDatacenter adds the datacenter as a label to all metrics emitted by the @@ -121,6 +87,12 @@ func (c *Config) WithDatacenter(dc string) *Config { return c } +// WithDisabledTenancyMetrics opts the user out of specifying usage metrics for each tenancy. +func (c *Config) WithDisabledTenancyMetrics(disabled bool) *Config { + c.excludeTenancy = disabled + return c +} + // WithLogger takes a logger and creates a new, named sub-logger to use when // running func (c *Config) WithLogger(logger hclog.Logger) *Config { @@ -161,6 +133,9 @@ type UsageMetricsReporter struct { stateProvider StateProvider tickerInterval time.Duration getMembersFunc getMembersFunc + excludeTenancy bool + + usageReporter } func NewUsageMetricsReporter(cfg *Config) (*UsageMetricsReporter, error) { @@ -187,8 +162,11 @@ func NewUsageMetricsReporter(cfg *Config) (*UsageMetricsReporter, error) { metricLabels: cfg.metricLabels, tickerInterval: cfg.tickerInterval, getMembersFunc: cfg.getMembersFunc, + excludeTenancy: cfg.excludeTenancy, } + u.usageReporter = newTenancyUsageReporter(u) + return u, nil } @@ -226,7 +204,7 @@ func (u *UsageMetricsReporter) runOnce() { u.emitPeeringUsage(peeringUsage) - _, serviceUsage, err := state.ServiceUsage(nil) + _, serviceUsage, err := state.ServiceUsage(nil, !u.excludeTenancy) if err != nil { u.logger.Warn("failed to retrieve services from state store", "error", err) } @@ -295,3 +273,112 @@ func versionWithMetadata() string { return vsn } + +type usageReporter interface { + emitNodeUsage(nodeUsage state.NodeUsage) + emitPeeringUsage(peeringUsage state.PeeringUsage) + emitMemberUsage(members []serf.Member) + emitServiceUsage(serviceUsage structs.ServiceUsage) + emitKVUsage(kvUsage state.KVUsage) + emitConfigEntryUsage(configUsage state.ConfigEntryUsage) +} + +type baseUsageReporter struct { + metricLabels []metrics.Label +} + +var _ usageReporter = (*baseUsageReporter)(nil) + +func newBaseUsageReporter(u *UsageMetricsReporter) *baseUsageReporter { + return &baseUsageReporter{ + metricLabels: u.metricLabels, + } +} + +func (u *baseUsageReporter) emitNodeUsage(nodeUsage state.NodeUsage) { + metrics.SetGaugeWithLabels( + []string{"state", "nodes"}, + float32(nodeUsage.Nodes), + u.metricLabels, + ) +} + +func (u *baseUsageReporter) emitPeeringUsage(peeringUsage state.PeeringUsage) { + metrics.SetGaugeWithLabels( + []string{"state", "peerings"}, + float32(peeringUsage.Peerings), + u.metricLabels, + ) +} + +func (u *baseUsageReporter) emitMemberUsage(members []serf.Member) { + var ( + servers int + clients int + ) + for _, m := range members { + switch m.Tags["role"] { + case "node": + clients++ + case "consul": + servers++ + } + } + + metrics.SetGaugeWithLabels( + []string{"members", "clients"}, + float32(clients), + u.metricLabels, + ) + + metrics.SetGaugeWithLabels( + []string{"members", "servers"}, + float32(servers), + u.metricLabels, + ) +} + +func (u *baseUsageReporter) emitServiceUsage(serviceUsage structs.ServiceUsage) { + metrics.SetGaugeWithLabels( + []string{"state", "services"}, + float32(serviceUsage.Services), + u.metricLabels, + ) + + metrics.SetGaugeWithLabels( + []string{"state", "service_instances"}, + float32(serviceUsage.ServiceInstances), + u.metricLabels, + ) + metrics.SetGaugeWithLabels( + []string{"state", "billable_service_instances"}, + float32(serviceUsage.BillableServiceInstances), + u.metricLabels, + ) + + for k, i := range serviceUsage.ConnectServiceInstances { + metrics.SetGaugeWithLabels( + []string{"state", "connect_instances"}, + float32(i), + append(u.metricLabels, metrics.Label{Name: "kind", Value: k}), + ) + } +} + +func (u *baseUsageReporter) emitKVUsage(kvUsage state.KVUsage) { + metrics.SetGaugeWithLabels( + []string{"state", "kv_entries"}, + float32(kvUsage.KVCount), + u.metricLabels, + ) +} + +func (u *baseUsageReporter) emitConfigEntryUsage(configUsage state.ConfigEntryUsage) { + for k, i := range configUsage.ConfigByKind { + metrics.SetGaugeWithLabels( + []string{"state", "config_entries"}, + float32(i), + append(u.metricLabels, metrics.Label{Name: "kind", Value: k}), + ) + } +} diff --git a/agent/consul/usagemetrics/usagemetrics_ce.go b/agent/consul/usagemetrics/usagemetrics_ce.go index 71457cbb48a1..519617b2100e 100644 --- a/agent/consul/usagemetrics/usagemetrics_ce.go +++ b/agent/consul/usagemetrics/usagemetrics_ce.go @@ -5,144 +5,6 @@ package usagemetrics -import ( - "github.com/armon/go-metrics" - - "github.com/hashicorp/serf/serf" - - "github.com/hashicorp/consul/agent/consul/state" - "github.com/hashicorp/consul/agent/structs" -) - -func (u *UsageMetricsReporter) emitNodeUsage(nodeUsage state.NodeUsage) { - metrics.SetGaugeWithLabels( - []string{"consul", "state", "nodes"}, - float32(nodeUsage.Nodes), - u.metricLabels, - ) - metrics.SetGaugeWithLabels( - []string{"state", "nodes"}, - float32(nodeUsage.Nodes), - u.metricLabels, - ) -} - -func (u *UsageMetricsReporter) emitPeeringUsage(peeringUsage state.PeeringUsage) { - metrics.SetGaugeWithLabels( - []string{"consul", "state", "peerings"}, - float32(peeringUsage.Peerings), - u.metricLabels, - ) - metrics.SetGaugeWithLabels( - []string{"state", "peerings"}, - float32(peeringUsage.Peerings), - u.metricLabels, - ) -} - -func (u *UsageMetricsReporter) emitMemberUsage(members []serf.Member) { - var ( - servers int - clients int - ) - for _, m := range members { - switch m.Tags["role"] { - case "node": - clients++ - case "consul": - servers++ - } - } - - metrics.SetGaugeWithLabels( - []string{"consul", "members", "clients"}, - float32(clients), - u.metricLabels, - ) - metrics.SetGaugeWithLabels( - []string{"members", "clients"}, - float32(clients), - u.metricLabels, - ) - - metrics.SetGaugeWithLabels( - []string{"consul", "members", "servers"}, - float32(servers), - u.metricLabels, - ) - metrics.SetGaugeWithLabels( - []string{"members", "servers"}, - float32(servers), - u.metricLabels, - ) -} - -func (u *UsageMetricsReporter) emitServiceUsage(serviceUsage structs.ServiceUsage) { - metrics.SetGaugeWithLabels( - []string{"consul", "state", "services"}, - float32(serviceUsage.Services), - u.metricLabels, - ) - metrics.SetGaugeWithLabels( - []string{"state", "services"}, - float32(serviceUsage.Services), - u.metricLabels, - ) - - metrics.SetGaugeWithLabels( - []string{"consul", "state", "service_instances"}, - float32(serviceUsage.ServiceInstances), - u.metricLabels, - ) - metrics.SetGaugeWithLabels( - []string{"state", "service_instances"}, - float32(serviceUsage.ServiceInstances), - u.metricLabels, - ) - metrics.SetGaugeWithLabels( - []string{"state", "billable_service_instances"}, - float32(serviceUsage.BillableServiceInstances), - u.metricLabels, - ) - - for k, i := range serviceUsage.ConnectServiceInstances { - metrics.SetGaugeWithLabels( - []string{"consul", "state", "connect_instances"}, - float32(i), - append(u.metricLabels, metrics.Label{Name: "kind", Value: k}), - ) - metrics.SetGaugeWithLabels( - []string{"state", "connect_instances"}, - float32(i), - append(u.metricLabels, metrics.Label{Name: "kind", Value: k}), - ) - } -} - -func (u *UsageMetricsReporter) emitKVUsage(kvUsage state.KVUsage) { - metrics.SetGaugeWithLabels( - []string{"consul", "state", "kv_entries"}, - float32(kvUsage.KVCount), - u.metricLabels, - ) - metrics.SetGaugeWithLabels( - []string{"state", "kv_entries"}, - float32(kvUsage.KVCount), - u.metricLabels, - ) -} - -func (u *UsageMetricsReporter) emitConfigEntryUsage(configUsage state.ConfigEntryUsage) { - for k, i := range configUsage.ConfigByKind { - metrics.SetGaugeWithLabels( - []string{"consul", "state", "config_entries"}, - float32(i), - append(u.metricLabels, metrics.Label{Name: "kind", Value: k}), - ) - metrics.SetGaugeWithLabels( - []string{"state", "config_entries"}, - float32(i), - append(u.metricLabels, metrics.Label{Name: "kind", Value: k}), - ) - } +func newTenancyUsageReporter(u *UsageMetricsReporter) usageReporter { + return newBaseUsageReporter(u) } diff --git a/agent/consul/usagemetrics/usagemetrics_ce_test.go b/agent/consul/usagemetrics/usagemetrics_ce_test.go index d0b7587d068c..1aa5867a5e90 100644 --- a/agent/consul/usagemetrics/usagemetrics_ce_test.go +++ b/agent/consul/usagemetrics/usagemetrics_ce_test.go @@ -6,1488 +6,46 @@ package usagemetrics import ( - "fmt" "testing" "time" "github.com/armon/go-metrics" - "github.com/hashicorp/serf/serf" "github.com/stretchr/testify/require" - "github.com/hashicorp/go-uuid" - - "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/state" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/proto/private/pbpeering" "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/version" ) func newStateStore() (*state.Store, error) { return state.NewStateStore(nil), nil } -type testCase struct { - modfiyStateStore func(t *testing.T, s *state.Store) - getMembersFunc getMembersFunc - expectedGauges map[string]metrics.GaugeValue -} - -var baseCases = map[string]testCase{ - "empty-state": { - expectedGauges: map[string]metrics.GaugeValue{ - // --- node --- - "consul.usage.test.consul.state.nodes;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.state.nodes", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.state.nodes;datacenter=dc1": { - Name: "consul.usage.test.state.nodes", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - // --- peering --- - "consul.usage.test.consul.state.peerings;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.state.peerings", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.state.peerings;datacenter=dc1": { - Name: "consul.usage.test.state.peerings", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - // --- member --- - "consul.usage.test.consul.members.clients;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.members.clients", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.members.clients;datacenter=dc1": { - Name: "consul.usage.test.members.clients", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.consul.members.servers;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.members.servers", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.members.servers;datacenter=dc1": { - Name: "consul.usage.test.members.servers", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - // --- service --- - "consul.usage.test.consul.state.services;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.state.services", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.state.services;datacenter=dc1": { - Name: "consul.usage.test.state.services", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.consul.state.service_instances;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.state.service_instances", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.state.service_instances;datacenter=dc1": { - Name: "consul.usage.test.state.service_instances", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - // --- service mesh --- - "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=connect-proxy": { // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "connect-proxy"}, - }, - }, - "consul.usage.test.state.connect_instances;datacenter=dc1;kind=connect-proxy": { - Name: "consul.usage.test.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "connect-proxy"}, - }, - }, - "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=terminating-gateway": { // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "terminating-gateway"}, - }, - }, - "consul.usage.test.state.connect_instances;datacenter=dc1;kind=terminating-gateway": { - Name: "consul.usage.test.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "terminating-gateway"}, - }, - }, - "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=ingress-gateway": { // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "ingress-gateway"}, - }, - }, - "consul.usage.test.state.connect_instances;datacenter=dc1;kind=ingress-gateway": { - Name: "consul.usage.test.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "ingress-gateway"}, - }, - }, - "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=api-gateway": { // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "api-gateway"}, - }, - }, - "consul.usage.test.state.connect_instances;datacenter=dc1;kind=api-gateway": { - Name: "consul.usage.test.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "api-gateway"}, - }, - }, - "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=mesh-gateway": { // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "mesh-gateway"}, - }, - }, - "consul.usage.test.state.connect_instances;datacenter=dc1;kind=mesh-gateway": { - Name: "consul.usage.test.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "mesh-gateway"}, - }, - }, - "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=connect-native": { // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "connect-native"}, - }, - }, - "consul.usage.test.state.connect_instances;datacenter=dc1;kind=connect-native": { - Name: "consul.usage.test.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "connect-native"}, - }, - }, - "consul.usage.test.state.billable_service_instances;datacenter=dc1": { - Name: "consul.usage.test.state.billable_service_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - }, - }, - // --- kv --- - "consul.usage.test.consul.state.kv_entries;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.state.kv_entries", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.state.kv_entries;datacenter=dc1": { - Name: "consul.usage.test.state.kv_entries", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - // --- config entries --- - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-intentions": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-intentions"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-intentions": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-intentions"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-resolver": { // Legacy - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-resolver"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-resolver": { - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-resolver"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-router": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-router"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-router": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-router"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-defaults": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-defaults"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-defaults": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-defaults"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=ingress-gateway": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "ingress-gateway"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=ingress-gateway": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "ingress-gateway"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-splitter": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-splitter"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-splitter": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-splitter"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=mesh": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "mesh"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=mesh": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "mesh"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=proxy-defaults": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "proxy-defaults"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=proxy-defaults": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "proxy-defaults"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=terminating-gateway": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "terminating-gateway"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=terminating-gateway": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "terminating-gateway"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=exported-services": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "exported-services"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=exported-services": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "exported-services"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=sameness-group": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "sameness-group"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=sameness-group": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "sameness-group"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=api-gateway": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "api-gateway"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=api-gateway": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "api-gateway"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=bound-api-gateway": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "bound-api-gateway"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=bound-api-gateway": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "bound-api-gateway"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=inline-certificate": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "inline-certificate"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=inline-certificate": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "inline-certificate"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=http-route": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "http-route"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=http-route": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "http-route"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=tcp-route": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "tcp-route"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=tcp-route": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "tcp-route"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=jwt-provider": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "jwt-provider"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=jwt-provider": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "jwt-provider"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=control-plane-request-limit": { - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "control-plane-request-limit"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=control-plane-request-limit": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "control-plane-request-limit"}, - }, - }, - // --- version --- - fmt.Sprintf("consul.usage.test.version;version=%s;pre_release=%s", versionWithMetadata(), version.VersionPrerelease): { - Name: "consul.usage.test.version", - Value: 1, - Labels: []metrics.Label{ - {Name: "version", Value: versionWithMetadata()}, - {Name: "pre_release", Value: version.VersionPrerelease}, - }, - }, - }, - getMembersFunc: func() []serf.Member { return []serf.Member{} }, - }, - "nodes": { - modfiyStateStore: func(t *testing.T, s *state.Store) { - require.NoError(t, s.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})) - require.NoError(t, s.EnsureNode(2, &structs.Node{Node: "bar", Address: "127.0.0.2"})) - }, - getMembersFunc: func() []serf.Member { - return []serf.Member{ - { - Name: "foo", - Tags: map[string]string{"role": "consul"}, - Status: serf.StatusAlive, - }, - { - Name: "bar", - Tags: map[string]string{"role": "consul"}, - Status: serf.StatusAlive, - }, - } - }, - expectedGauges: map[string]metrics.GaugeValue{ - // --- node --- - "consul.usage.test.consul.state.nodes;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.state.nodes", - Value: 2, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.state.nodes;datacenter=dc1": { - Name: "consul.usage.test.state.nodes", - Value: 2, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - // --- peering --- - "consul.usage.test.consul.state.peerings;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.state.peerings", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.state.peerings;datacenter=dc1": { - Name: "consul.usage.test.state.peerings", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - // --- member --- - "consul.usage.test.consul.members.servers;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.members.servers", - Value: 2, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.members.servers;datacenter=dc1": { - Name: "consul.usage.test.members.servers", - Value: 2, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.consul.members.clients;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.members.clients", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.members.clients;datacenter=dc1": { - Name: "consul.usage.test.members.clients", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - // --- service --- - "consul.usage.test.consul.state.services;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.state.services", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.state.services;datacenter=dc1": { - Name: "consul.usage.test.state.services", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.consul.state.service_instances;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.state.service_instances", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.state.service_instances;datacenter=dc1": { - Name: "consul.usage.test.state.service_instances", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - // --- service mesh --- - "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=connect-proxy": { // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "connect-proxy"}, - }, - }, - "consul.usage.test.state.connect_instances;datacenter=dc1;kind=connect-proxy": { - Name: "consul.usage.test.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "connect-proxy"}, - }, - }, - "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=terminating-gateway": { // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "terminating-gateway"}, - }, - }, - "consul.usage.test.state.connect_instances;datacenter=dc1;kind=terminating-gateway": { - Name: "consul.usage.test.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "terminating-gateway"}, - }, - }, - "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=ingress-gateway": { // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "ingress-gateway"}, - }, - }, - "consul.usage.test.state.connect_instances;datacenter=dc1;kind=ingress-gateway": { - Name: "consul.usage.test.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "ingress-gateway"}, - }, - }, - "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=api-gateway": { // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "api-gateway"}, - }, - }, - "consul.usage.test.state.connect_instances;datacenter=dc1;kind=api-gateway": { - Name: "consul.usage.test.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "api-gateway"}, - }, - }, - "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=mesh-gateway": { // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "mesh-gateway"}, - }, - }, - "consul.usage.test.state.connect_instances;datacenter=dc1;kind=mesh-gateway": { - Name: "consul.usage.test.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "mesh-gateway"}, - }, - }, - "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=connect-native": { // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "connect-native"}, - }, - }, - "consul.usage.test.state.connect_instances;datacenter=dc1;kind=connect-native": { - Name: "consul.usage.test.state.connect_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "connect-native"}, - }, - }, - "consul.usage.test.state.billable_service_instances;datacenter=dc1": { - Name: "consul.usage.test.state.billable_service_instances", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - }, - }, - // --- kv --- - "consul.usage.test.consul.state.kv_entries;datacenter=dc1": { // Legacy - Name: "consul.usage.test.consul.state.kv_entries", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - "consul.usage.test.state.kv_entries;datacenter=dc1": { - Name: "consul.usage.test.state.kv_entries", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - }, - // --- config entries --- - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-intentions": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-intentions"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-intentions": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-intentions"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-resolver": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-resolver"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-resolver": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-resolver"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-router": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-router"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-router": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-router"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-defaults": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-defaults"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-defaults": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-defaults"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=ingress-gateway": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "ingress-gateway"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=ingress-gateway": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "ingress-gateway"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-splitter": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-splitter"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-splitter": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "service-splitter"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=mesh": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "mesh"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=mesh": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "mesh"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=proxy-defaults": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "proxy-defaults"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=proxy-defaults": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "proxy-defaults"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=terminating-gateway": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "terminating-gateway"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=terminating-gateway": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "terminating-gateway"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=exported-services": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "exported-services"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=exported-services": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "exported-services"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=sameness-group": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "sameness-group"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=sameness-group": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "sameness-group"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=api-gateway": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "api-gateway"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=api-gateway": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "api-gateway"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=bound-api-gateway": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "bound-api-gateway"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=bound-api-gateway": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "bound-api-gateway"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=inline-certificate": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "inline-certificate"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=inline-certificate": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "inline-certificate"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=http-route": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "http-route"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=http-route": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "http-route"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=tcp-route": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "tcp-route"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=tcp-route": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "tcp-route"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=jwt-provider": { // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "jwt-provider"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=jwt-provider": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "jwt-provider"}, - }, - }, - "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=control-plane-request-limit": { - Name: "consul.usage.test.consul.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "control-plane-request-limit"}, - }, - }, - "consul.usage.test.state.config_entries;datacenter=dc1;kind=control-plane-request-limit": { - Name: "consul.usage.test.state.config_entries", - Value: 0, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "control-plane-request-limit"}, - }, - }, - // --- version --- - fmt.Sprintf("consul.usage.test.version;version=%s;pre_release=%s", versionWithMetadata(), version.VersionPrerelease): { - Name: "consul.usage.test.version", - Value: 1, - Labels: []metrics.Label{ - {Name: "version", Value: versionWithMetadata()}, - {Name: "pre_release", Value: version.VersionPrerelease}, - }, - }, - }, - }, -} - -func TestUsageReporter_emitNodeUsage_CE(t *testing.T) { - cases := baseCases - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - // Only have a single interval for the test - sink := metrics.NewInmemSink(1*time.Minute, 1*time.Minute) - cfg := metrics.DefaultConfig("consul.usage.test") - cfg.EnableHostname = false - metrics.NewGlobal(cfg, sink) +func TestUsageReporter_CE(t *testing.T) { + getMetricsReporter := func(tc testCase) (*UsageMetricsReporter, *metrics.InmemSink, error) { + // Only have a single interval for the test + sink := metrics.NewInmemSink(1*time.Minute, 1*time.Minute) + cfg := metrics.DefaultConfig("consul.usage.test") + cfg.EnableHostname = false + metrics.NewGlobal(cfg, sink) - mockStateProvider := &mockStateProvider{} - s, err := newStateStore() - require.NoError(t, err) - if tcase.modfiyStateStore != nil { - tcase.modfiyStateStore(t, s) - } - mockStateProvider.On("State").Return(s) - - reporter, err := NewUsageMetricsReporter( - new(Config). - WithStateProvider(mockStateProvider). - WithLogger(testutil.Logger(t)). - WithDatacenter("dc1"). - WithGetMembersFunc(tcase.getMembersFunc), - ) - require.NoError(t, err) - - reporter.runOnce() - - intervals := sink.Data() - require.Len(t, intervals, 1) - intv := intervals[0] - - assertEqualGaugeMaps(t, tcase.expectedGauges, intv.Gauges) - }) - } -} - -func TestUsageReporter_emitPeeringUsage_CE(t *testing.T) { - cases := make(map[string]testCase) - for k, v := range baseCases { - eg := make(map[string]metrics.GaugeValue) - for k, v := range v.expectedGauges { - eg[k] = v - } - cases[k] = testCase{v.modfiyStateStore, v.getMembersFunc, eg} - } - peeringsCase := cases["nodes"] - peeringsCase.modfiyStateStore = func(t *testing.T, s *state.Store) { - id, err := uuid.GenerateUUID() - require.NoError(t, err) - require.NoError(t, s.PeeringWrite(1, &pbpeering.PeeringWriteRequest{Peering: &pbpeering.Peering{Name: "foo", ID: id}})) - id, err = uuid.GenerateUUID() + mockStateProvider := &mockStateProvider{} + s, err := newStateStore() require.NoError(t, err) - require.NoError(t, s.PeeringWrite(2, &pbpeering.PeeringWriteRequest{Peering: &pbpeering.Peering{Name: "bar", ID: id}})) - id, err = uuid.GenerateUUID() - require.NoError(t, err) - require.NoError(t, s.PeeringWrite(3, &pbpeering.PeeringWriteRequest{Peering: &pbpeering.Peering{Name: "baz", ID: id}})) - } - peeringsCase.getMembersFunc = func() []serf.Member { - return []serf.Member{ - { - Name: "foo", - Tags: map[string]string{"role": "consul"}, - Status: serf.StatusAlive, - }, - { - Name: "bar", - Tags: map[string]string{"role": "consul"}, - Status: serf.StatusAlive, - }, + if tc.modifyStateStore != nil { + tc.modifyStateStore(t, s) } - } - peeringsCase.expectedGauges["consul.usage.test.consul.state.nodes;datacenter=dc1"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.nodes", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - peeringsCase.expectedGauges["consul.usage.test.state.nodes;datacenter=dc1"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.nodes", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - peeringsCase.expectedGauges["consul.usage.test.consul.state.peerings;datacenter=dc1"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.peerings", - Value: 3, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - peeringsCase.expectedGauges["consul.usage.test.state.peerings;datacenter=dc1"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.peerings", - Value: 3, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - peeringsCase.expectedGauges["consul.usage.test.consul.members.clients;datacenter=dc1"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.members.clients", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - peeringsCase.expectedGauges["consul.usage.test.members.clients;datacenter=dc1"] = metrics.GaugeValue{ - Name: "consul.usage.test.members.clients", - Value: 0, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - cases["peerings"] = peeringsCase - delete(cases, "nodes") - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - // Only have a single interval for the test - sink := metrics.NewInmemSink(1*time.Minute, 1*time.Minute) - cfg := metrics.DefaultConfig("consul.usage.test") - cfg.EnableHostname = false - metrics.NewGlobal(cfg, sink) - - mockStateProvider := &mockStateProvider{} - s, err := newStateStore() - require.NoError(t, err) - if tcase.modfiyStateStore != nil { - tcase.modfiyStateStore(t, s) - } - mockStateProvider.On("State").Return(s) + mockStateProvider.On("State").Return(s) - reporter, err := NewUsageMetricsReporter( - new(Config). - WithStateProvider(mockStateProvider). - WithLogger(testutil.Logger(t)). - WithDatacenter("dc1"). - WithGetMembersFunc(tcase.getMembersFunc), - ) - require.NoError(t, err) + reporter, err := NewUsageMetricsReporter( + new(Config). + WithStateProvider(mockStateProvider). + WithLogger(testutil.Logger(t)). + WithDatacenter("dc1"). + WithGetMembersFunc(tc.getMembersFunc), + ) - reporter.runOnce() - - intervals := sink.Data() - require.Len(t, intervals, 1) - intv := intervals[0] - - assertEqualGaugeMaps(t, tcase.expectedGauges, intv.Gauges) - }) + return reporter, sink, err } -} -func TestUsageReporter_emitServiceUsage_CE(t *testing.T) { - cases := make(map[string]testCase) - for k, v := range baseCases { - eg := make(map[string]metrics.GaugeValue) - for k, v := range v.expectedGauges { - eg[k] = v - } - cases[k] = testCase{v.modfiyStateStore, v.getMembersFunc, eg} - } - - nodesAndSvcsCase := cases["nodes"] - nodesAndSvcsCase.modfiyStateStore = func(t *testing.T, s *state.Store) { - require.NoError(t, s.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})) - require.NoError(t, s.EnsureNode(2, &structs.Node{Node: "bar", Address: "127.0.0.2"})) - require.NoError(t, s.EnsureNode(3, &structs.Node{Node: "baz", Address: "127.0.0.2"})) - require.NoError(t, s.EnsureNode(4, &structs.Node{Node: "qux", Address: "127.0.0.3"})) - - apigw := structs.TestNodeServiceAPIGateway(t) - apigw.ID = "api-gateway" - - mgw := structs.TestNodeServiceMeshGateway(t) - mgw.ID = "mesh-gateway" - - tgw := structs.TestNodeServiceTerminatingGateway(t, "1.1.1.1") - tgw.ID = "terminating-gateway" - // Typical services and some consul services spread across two nodes - require.NoError(t, s.EnsureService(5, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: nil, Address: "", Port: 5000})) - require.NoError(t, s.EnsureService(6, "bar", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000})) - require.NoError(t, s.EnsureService(7, "foo", &structs.NodeService{ID: "consul", Service: "consul", Tags: nil})) - require.NoError(t, s.EnsureService(8, "bar", &structs.NodeService{ID: "consul", Service: "consul", Tags: nil})) - require.NoError(t, s.EnsureService(9, "foo", &structs.NodeService{ID: "db-connect-proxy", Service: "db-connect-proxy", Tags: nil, Address: "", Port: 5000, Kind: structs.ServiceKindConnectProxy})) - require.NoError(t, s.EnsureRegistration(10, structs.TestRegisterIngressGateway(t))) - require.NoError(t, s.EnsureService(11, "foo", mgw)) - require.NoError(t, s.EnsureService(12, "foo", tgw)) - require.NoError(t, s.EnsureService(13, "foo", apigw)) - require.NoError(t, s.EnsureService(14, "bar", &structs.NodeService{ID: "db-native", Service: "db", Tags: nil, Address: "", Port: 5000, Connect: structs.ServiceConnect{Native: true}})) - require.NoError(t, s.EnsureConfigEntry(15, &structs.IngressGatewayConfigEntry{ - Kind: structs.IngressGateway, - Name: "foo", - })) - require.NoError(t, s.EnsureConfigEntry(16, &structs.IngressGatewayConfigEntry{ - Kind: structs.IngressGateway, - Name: "bar", - })) - require.NoError(t, s.EnsureConfigEntry(17, &structs.IngressGatewayConfigEntry{ - Kind: structs.IngressGateway, - Name: "baz", - })) - } - baseCaseMembers := nodesAndSvcsCase.getMembersFunc() - nodesAndSvcsCase.getMembersFunc = func() []serf.Member { - baseCaseMembers = append(baseCaseMembers, serf.Member{ - Name: "baz", - Tags: map[string]string{"role": "node", "segment": "a"}, - Status: serf.StatusAlive, - }) - baseCaseMembers = append(baseCaseMembers, serf.Member{ - Name: "qux", - Tags: map[string]string{"role": "node", "segment": "b"}, - Status: serf.StatusAlive, - }) - return baseCaseMembers - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.nodes;datacenter=dc1"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.nodes", - Value: 4, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.state.nodes;datacenter=dc1"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.nodes", - Value: 4, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.members.clients;datacenter=dc1"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.members.clients", - Value: 2, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.members.clients;datacenter=dc1"] = metrics.GaugeValue{ - Name: "consul.usage.test.members.clients", - Value: 2, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.services;datacenter=dc1"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.services", - Value: 8, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.state.services;datacenter=dc1"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.services", - Value: 8, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.service_instances;datacenter=dc1"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.service_instances", - Value: 10, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.state.service_instances;datacenter=dc1"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.service_instances", - Value: 10, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=connect-proxy"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 1, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "connect-proxy"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=connect-proxy"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.connect_instances", - Value: 1, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "connect-proxy"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=terminating-gateway"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 1, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "terminating-gateway"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=terminating-gateway"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.connect_instances", - Value: 1, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "terminating-gateway"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=ingress-gateway"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 1, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "ingress-gateway"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=ingress-gateway"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.connect_instances", - Value: 1, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "ingress-gateway"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=api-gateway"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 1, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "api-gateway"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=api-gateway"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.connect_instances", - Value: 1, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "api-gateway"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=mesh-gateway"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 1, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "mesh-gateway"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=mesh-gateway"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.connect_instances", - Value: 1, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "mesh-gateway"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=connect-native"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.connect_instances", - Value: 1, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "connect-native"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=connect-native"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.connect_instances", - Value: 1, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "connect-native"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.state.billable_service_instances;datacenter=dc1"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.billable_service_instances", - Value: 3, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=ingress-gateway"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.config_entries", - Value: 3, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "ingress-gateway"}, - }, - } - nodesAndSvcsCase.expectedGauges["consul.usage.test.state.config_entries;datacenter=dc1;kind=ingress-gateway"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.config_entries", - Value: 3, - Labels: []metrics.Label{ - {Name: "datacenter", Value: "dc1"}, - {Name: "kind", Value: "ingress-gateway"}, - }, - } - cases["nodes-and-services"] = nodesAndSvcsCase - delete(cases, "nodes") - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - // Only have a single interval for the test - sink := metrics.NewInmemSink(1*time.Minute, 1*time.Minute) - cfg := metrics.DefaultConfig("consul.usage.test") - cfg.EnableHostname = false - metrics.NewGlobal(cfg, sink) - - mockStateProvider := &mockStateProvider{} - s := state.NewStateStore(nil) - if tcase.modfiyStateStore != nil { - tcase.modfiyStateStore(t, s) - } - mockStateProvider.On("State").Return(s) - - reporter, err := NewUsageMetricsReporter( - new(Config). - WithStateProvider(mockStateProvider). - WithLogger(testutil.Logger(t)). - WithDatacenter("dc1"). - WithGetMembersFunc(tcase.getMembersFunc), - ) - require.NoError(t, err) - - reporter.runOnce() - - intervals := sink.Data() - require.Len(t, intervals, 1) - intv := intervals[0] - - assertEqualGaugeMaps(t, tcase.expectedGauges, intv.Gauges) - }) - } -} - -func TestUsageReporter_emitKVUsage_CE(t *testing.T) { - cases := make(map[string]testCase) - for k, v := range baseCases { - eg := make(map[string]metrics.GaugeValue) - for k, v := range v.expectedGauges { - eg[k] = v - } - cases[k] = testCase{v.modfiyStateStore, v.getMembersFunc, eg} - } - - nodesCase := cases["nodes"] - mss := nodesCase.modfiyStateStore - nodesCase.modfiyStateStore = func(t *testing.T, s *state.Store) { - mss(t, s) - require.NoError(t, s.KVSSet(4, &structs.DirEntry{Key: "a", Value: []byte{1}})) - require.NoError(t, s.KVSSet(5, &structs.DirEntry{Key: "b", Value: []byte{1}})) - require.NoError(t, s.KVSSet(6, &structs.DirEntry{Key: "c", Value: []byte{1}})) - require.NoError(t, s.KVSSet(7, &structs.DirEntry{Key: "d", Value: []byte{1}})) - require.NoError(t, s.KVSDelete(8, "d", &acl.EnterpriseMeta{})) - require.NoError(t, s.KVSDelete(9, "c", &acl.EnterpriseMeta{})) - require.NoError(t, s.KVSSet(10, &structs.DirEntry{Key: "e", Value: []byte{1}})) - require.NoError(t, s.KVSSet(11, &structs.DirEntry{Key: "f", Value: []byte{1}})) - } - nodesCase.expectedGauges["consul.usage.test.consul.state.kv_entries;datacenter=dc1"] = metrics.GaugeValue{ // Legacy - Name: "consul.usage.test.consul.state.kv_entries", - Value: 4, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - nodesCase.expectedGauges["consul.usage.test.state.kv_entries;datacenter=dc1"] = metrics.GaugeValue{ - Name: "consul.usage.test.state.kv_entries", - Value: 4, - Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, - } - cases["nodes"] = nodesCase - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - // Only have a single interval for the test - sink := metrics.NewInmemSink(1*time.Minute, 1*time.Minute) - cfg := metrics.DefaultConfig("consul.usage.test") - cfg.EnableHostname = false - metrics.NewGlobal(cfg, sink) - - mockStateProvider := &mockStateProvider{} - s, err := newStateStore() - require.NoError(t, err) - if tcase.modfiyStateStore != nil { - tcase.modfiyStateStore(t, s) - } - mockStateProvider.On("State").Return(s) - - reporter, err := NewUsageMetricsReporter( - new(Config). - WithStateProvider(mockStateProvider). - WithLogger(testutil.Logger(t)). - WithDatacenter("dc1"). - WithGetMembersFunc(tcase.getMembersFunc), - ) - require.NoError(t, err) - - reporter.runOnce() - - intervals := sink.Data() - require.Len(t, intervals, 1) - intv := intervals[0] - - assertEqualGaugeMaps(t, tcase.expectedGauges, intv.Gauges) - }) - } + testUsageReporter_Tenantless(t, getMetricsReporter) } diff --git a/agent/consul/usagemetrics/usagemetrics_test.go b/agent/consul/usagemetrics/usagemetrics_test.go index 4e48beb0a3b2..84ed050ef3a8 100644 --- a/agent/consul/usagemetrics/usagemetrics_test.go +++ b/agent/consul/usagemetrics/usagemetrics_test.go @@ -4,13 +4,25 @@ package usagemetrics import ( + "fmt" "testing" + "time" "github.com/armon/go-metrics" + "github.com/armon/go-metrics/prometheus" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/serf/serf" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/state" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/proto/private/pbpeering" + "github.com/hashicorp/consul/version" ) type mockStateProvider struct { @@ -39,3 +51,944 @@ func assertEqualGaugeMaps(t *testing.T, expectedMap, foundMap map[string]metrics assert.Equal(t, expected, foundMap[key], "gauge key mismatch on %q", key) } } + +func BenchmarkRunOnce(b *testing.B) { + const index = 123 + + store := state.NewStateStore(nil) + + // This loop generates: + // + // 4 (service kind) * 100 (service) * 5 * (node) = 2000 proxy services. And 500 non-proxy services. + for _, kind := range []structs.ServiceKind{ + // These will be included in the count. + structs.ServiceKindConnectProxy, + structs.ServiceKindIngressGateway, + structs.ServiceKindTerminatingGateway, + structs.ServiceKindMeshGateway, + + // This one will not. + structs.ServiceKindTypical, + } { + for i := 0; i < 100; i++ { + serviceName := fmt.Sprintf("%s-%d", kind, i) + + for j := 0; j < 5; j++ { + nodeName := fmt.Sprintf("%s-node-%d", serviceName, j) + + require.NoError(b, store.EnsureRegistration(index, &structs.RegisterRequest{ + Node: nodeName, + Service: &structs.NodeService{ + ID: serviceName, + Service: serviceName, + Kind: kind, + }, + })) + } + } + } + + benchmarkRunOnce(b, store) +} + +func benchmarkRunOnce(b *testing.B, store *state.Store) { + b.Helper() + + config := lib.TelemetryConfig{ + MetricsPrefix: "consul", + FilterDefault: true, + PrometheusOpts: prometheus.PrometheusOpts{ + Expiration: time.Second * 30, + Name: "consul", + }, + } + + lib.InitTelemetry(config, hclog.NewNullLogger()) + + um, err := NewUsageMetricsReporter(&Config{ + stateProvider: benchStateProvider(func() *state.Store { return store }), + logger: hclog.NewNullLogger(), + getMembersFunc: func() []serf.Member { return nil }, + }) + require.NoError(b, err) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + um.runOnce() + } +} + +type benchStateProvider func() *state.Store + +func (b benchStateProvider) State() *state.Store { + return b() +} + +type testCase struct { + modifyStateStore func(t *testing.T, s *state.Store) + getMembersFunc getMembersFunc + expectedGauges map[string]metrics.GaugeValue +} + +var baseCases = map[string]testCase{ + "empty-state": { + expectedGauges: map[string]metrics.GaugeValue{ + // --- node --- + "consul.usage.test.state.nodes;datacenter=dc1": { + Name: "consul.usage.test.state.nodes", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + // --- peering --- + "consul.usage.test.state.peerings;datacenter=dc1": { + Name: "consul.usage.test.state.peerings", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + // --- member --- + "consul.usage.test.members.clients;datacenter=dc1": { + Name: "consul.usage.test.members.clients", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + "consul.usage.test.members.servers;datacenter=dc1": { + Name: "consul.usage.test.members.servers", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + // --- service --- + "consul.usage.test.state.services;datacenter=dc1": { + Name: "consul.usage.test.state.services", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + "consul.usage.test.state.service_instances;datacenter=dc1": { + Name: "consul.usage.test.state.service_instances", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + // --- service mesh --- + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=connect-proxy": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "connect-proxy"}, + }, + }, + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=terminating-gateway": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "terminating-gateway"}, + }, + }, + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=ingress-gateway": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "ingress-gateway"}, + }, + }, + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=api-gateway": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + }, + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=mesh-gateway": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "mesh-gateway"}, + }, + }, + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=connect-native": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "connect-native"}, + }, + }, + "consul.usage.test.state.billable_service_instances;datacenter=dc1": { + Name: "consul.usage.test.state.billable_service_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + }, + }, + // --- kv --- + "consul.usage.test.state.kv_entries;datacenter=dc1": { + Name: "consul.usage.test.state.kv_entries", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + // --- config entries --- + "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-intentions": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "service-intentions"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-resolver": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "service-resolver"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-router": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "service-router"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-defaults": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "service-defaults"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=ingress-gateway": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "ingress-gateway"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-splitter": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "service-splitter"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=mesh": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "mesh"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=proxy-defaults": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "proxy-defaults"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=terminating-gateway": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "terminating-gateway"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=exported-services": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "exported-services"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=sameness-group": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "sameness-group"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=api-gateway": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=bound-api-gateway": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "bound-api-gateway"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=file-system-certificate": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "file-system-certificate"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=inline-certificate": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "inline-certificate"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=http-route": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "http-route"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=tcp-route": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "tcp-route"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=jwt-provider": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "jwt-provider"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=control-plane-request-limit": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "control-plane-request-limit"}, + }, + }, + // --- version --- + fmt.Sprintf("consul.usage.test.version;version=%s;pre_release=%s", versionWithMetadata(), version.VersionPrerelease): { + Name: "consul.usage.test.version", + Value: 1, + Labels: []metrics.Label{ + {Name: "version", Value: versionWithMetadata()}, + {Name: "pre_release", Value: version.VersionPrerelease}, + }, + }, + }, + getMembersFunc: func() []serf.Member { return []serf.Member{} }, + }, + "nodes": { + modifyStateStore: func(t *testing.T, s *state.Store) { + require.NoError(t, s.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})) + require.NoError(t, s.EnsureNode(2, &structs.Node{Node: "bar", Address: "127.0.0.2"})) + }, + getMembersFunc: func() []serf.Member { + return []serf.Member{ + { + Name: "foo", + Tags: map[string]string{"role": "consul"}, + Status: serf.StatusAlive, + }, + { + Name: "bar", + Tags: map[string]string{"role": "consul"}, + Status: serf.StatusAlive, + }, + } + }, + expectedGauges: map[string]metrics.GaugeValue{ + // --- node --- + "consul.usage.test.state.nodes;datacenter=dc1": { + Name: "consul.usage.test.state.nodes", + Value: 2, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + // --- peering --- + "consul.usage.test.state.peerings;datacenter=dc1": { + Name: "consul.usage.test.state.peerings", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + // --- member --- + "consul.usage.test.members.servers;datacenter=dc1": { + Name: "consul.usage.test.members.servers", + Value: 2, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + "consul.usage.test.members.clients;datacenter=dc1": { + Name: "consul.usage.test.members.clients", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + // --- service --- + "consul.usage.test.state.services;datacenter=dc1": { + Name: "consul.usage.test.state.services", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + "consul.usage.test.state.service_instances;datacenter=dc1": { + Name: "consul.usage.test.state.service_instances", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + // --- service mesh --- + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=connect-proxy": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "connect-proxy"}, + }, + }, + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=terminating-gateway": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "terminating-gateway"}, + }, + }, + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=ingress-gateway": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "ingress-gateway"}, + }, + }, + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=api-gateway": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + }, + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=mesh-gateway": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "mesh-gateway"}, + }, + }, + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=connect-native": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "connect-native"}, + }, + }, + "consul.usage.test.state.billable_service_instances;datacenter=dc1": { + Name: "consul.usage.test.state.billable_service_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + }, + }, + // --- kv --- + "consul.usage.test.state.kv_entries;datacenter=dc1": { + Name: "consul.usage.test.state.kv_entries", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + }, + // --- config entries --- + "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-intentions": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "service-intentions"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-resolver": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "service-resolver"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-router": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "service-router"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-defaults": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "service-defaults"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=ingress-gateway": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "ingress-gateway"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=service-splitter": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "service-splitter"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=mesh": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "mesh"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=proxy-defaults": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "proxy-defaults"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=terminating-gateway": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "terminating-gateway"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=exported-services": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "exported-services"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=sameness-group": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "sameness-group"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=api-gateway": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=bound-api-gateway": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "bound-api-gateway"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=file-system-certificate": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "file-system-certificate"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=inline-certificate": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "inline-certificate"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=http-route": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "http-route"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=tcp-route": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "tcp-route"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=jwt-provider": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "jwt-provider"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=control-plane-request-limit": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "control-plane-request-limit"}, + }, + }, + // --- version --- + fmt.Sprintf("consul.usage.test.version;version=%s;pre_release=%s", versionWithMetadata(), version.VersionPrerelease): { + Name: "consul.usage.test.version", + Value: 1, + Labels: []metrics.Label{ + {Name: "version", Value: versionWithMetadata()}, + {Name: "pre_release", Value: version.VersionPrerelease}, + }, + }, + }, + }, +} + +func testUsageReporter_Tenantless(t *testing.T, getMetricsReporter func(tc testCase) (*UsageMetricsReporter, *metrics.InmemSink, error)) { + t.Run("emitNodeUsage", func(t *testing.T) { + testUsageReporter_emitNodeUsage_CE(t, getMetricsReporter) + }) + + t.Run("emitPeeringUsage", func(t *testing.T) { + testUsageReporter_emitPeeringUsage_CE(t, getMetricsReporter) + }) + + t.Run("emitServiceUsage", func(t *testing.T) { + testUsageReporter_emitServiceUsage_CE(t, getMetricsReporter) + }) + + t.Run("emitKVUsage", func(t *testing.T) { + testUsageReporter_emitKVUsage_CE(t, getMetricsReporter) + }) +} + +func testUsageReporter_emitNodeUsage_CE(t *testing.T, getReporter func(testCase) (*UsageMetricsReporter, *metrics.InmemSink, error)) { + cases := baseCases + + for name, tcase := range cases { + t.Run(name, func(t *testing.T) { + reporter, sink, err := getReporter(tcase) + require.NoError(t, err) + + reporter.runOnce() + + intervals := sink.Data() + require.Len(t, intervals, 1) + intv := intervals[0] + + assertEqualGaugeMaps(t, tcase.expectedGauges, intv.Gauges) + }) + } +} + +func testUsageReporter_emitPeeringUsage_CE(t *testing.T, getMetricsReporter func(testCase) (*UsageMetricsReporter, *metrics.InmemSink, error)) { + cases := make(map[string]testCase) + for k, v := range baseCases { + eg := make(map[string]metrics.GaugeValue) + for k, v := range v.expectedGauges { + eg[k] = v + } + cases[k] = testCase{v.modifyStateStore, v.getMembersFunc, eg} + } + peeringsCase := cases["nodes"] + peeringsCase.modifyStateStore = func(t *testing.T, s *state.Store) { + id, err := uuid.GenerateUUID() + require.NoError(t, err) + require.NoError(t, s.PeeringWrite(1, &pbpeering.PeeringWriteRequest{Peering: &pbpeering.Peering{Name: "foo", ID: id}})) + id, err = uuid.GenerateUUID() + require.NoError(t, err) + require.NoError(t, s.PeeringWrite(2, &pbpeering.PeeringWriteRequest{Peering: &pbpeering.Peering{Name: "bar", ID: id}})) + id, err = uuid.GenerateUUID() + require.NoError(t, err) + require.NoError(t, s.PeeringWrite(3, &pbpeering.PeeringWriteRequest{Peering: &pbpeering.Peering{Name: "baz", ID: id}})) + } + peeringsCase.getMembersFunc = func() []serf.Member { + return []serf.Member{ + { + Name: "foo", + Tags: map[string]string{"role": "consul"}, + Status: serf.StatusAlive, + }, + { + Name: "bar", + Tags: map[string]string{"role": "consul"}, + Status: serf.StatusAlive, + }, + } + } + peeringsCase.expectedGauges["consul.usage.test.state.nodes;datacenter=dc1"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.nodes", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + } + peeringsCase.expectedGauges["consul.usage.test.state.peerings;datacenter=dc1"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.peerings", + Value: 3, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + } + peeringsCase.expectedGauges["consul.usage.test.members.clients;datacenter=dc1"] = metrics.GaugeValue{ + Name: "consul.usage.test.members.clients", + Value: 0, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + } + cases["peerings"] = peeringsCase + delete(cases, "nodes") + + for name, tcase := range cases { + t.Run(name, func(t *testing.T) { + reporter, sink, err := getMetricsReporter(tcase) + require.NoError(t, err) + + reporter.runOnce() + + intervals := sink.Data() + require.Len(t, intervals, 1) + intv := intervals[0] + + assertEqualGaugeMaps(t, tcase.expectedGauges, intv.Gauges) + }) + } +} + +func testUsageReporter_emitServiceUsage_CE(t *testing.T, getMetricsReporter func(testCase) (*UsageMetricsReporter, *metrics.InmemSink, error)) { + cases := make(map[string]testCase) + for k, v := range baseCases { + eg := make(map[string]metrics.GaugeValue) + for k, v := range v.expectedGauges { + eg[k] = v + } + cases[k] = testCase{v.modifyStateStore, v.getMembersFunc, eg} + } + + nodesAndSvcsCase := cases["nodes"] + nodesAndSvcsCase.modifyStateStore = func(t *testing.T, s *state.Store) { + require.NoError(t, s.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})) + require.NoError(t, s.EnsureNode(2, &structs.Node{Node: "bar", Address: "127.0.0.2"})) + require.NoError(t, s.EnsureNode(3, &structs.Node{Node: "baz", Address: "127.0.0.2"})) + require.NoError(t, s.EnsureNode(4, &structs.Node{Node: "qux", Address: "127.0.0.3"})) + + apigw := structs.TestNodeServiceAPIGateway(t) + apigw.ID = "api-gateway" + + mgw := structs.TestNodeServiceMeshGateway(t) + mgw.ID = "mesh-gateway" + + tgw := structs.TestNodeServiceTerminatingGateway(t, "1.1.1.1") + tgw.ID = "terminating-gateway" + // Typical services and some consul services spread across two nodes + require.NoError(t, s.EnsureService(5, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: nil, Address: "", Port: 5000})) + require.NoError(t, s.EnsureService(6, "bar", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000})) + require.NoError(t, s.EnsureService(7, "foo", &structs.NodeService{ID: "consul", Service: "consul", Tags: nil})) + require.NoError(t, s.EnsureService(8, "bar", &structs.NodeService{ID: "consul", Service: "consul", Tags: nil})) + require.NoError(t, s.EnsureService(9, "foo", &structs.NodeService{ID: "db-connect-proxy", Service: "db-connect-proxy", Tags: nil, Address: "", Port: 5000, Kind: structs.ServiceKindConnectProxy})) + require.NoError(t, s.EnsureRegistration(10, structs.TestRegisterIngressGateway(t))) + require.NoError(t, s.EnsureService(11, "foo", mgw)) + require.NoError(t, s.EnsureService(12, "foo", tgw)) + require.NoError(t, s.EnsureService(13, "foo", apigw)) + require.NoError(t, s.EnsureService(14, "bar", &structs.NodeService{ID: "db-native", Service: "db", Tags: nil, Address: "", Port: 5000, Connect: structs.ServiceConnect{Native: true}})) + require.NoError(t, s.EnsureConfigEntry(15, &structs.IngressGatewayConfigEntry{ + Kind: structs.IngressGateway, + Name: "foo", + })) + require.NoError(t, s.EnsureConfigEntry(16, &structs.IngressGatewayConfigEntry{ + Kind: structs.IngressGateway, + Name: "bar", + })) + require.NoError(t, s.EnsureConfigEntry(17, &structs.IngressGatewayConfigEntry{ + Kind: structs.IngressGateway, + Name: "baz", + })) + } + baseCaseMembers := nodesAndSvcsCase.getMembersFunc() + nodesAndSvcsCase.getMembersFunc = func() []serf.Member { + baseCaseMembers = append(baseCaseMembers, serf.Member{ + Name: "baz", + Tags: map[string]string{"role": "node", "segment": "a"}, + Status: serf.StatusAlive, + }) + baseCaseMembers = append(baseCaseMembers, serf.Member{ + Name: "qux", + Tags: map[string]string{"role": "node", "segment": "b"}, + Status: serf.StatusAlive, + }) + return baseCaseMembers + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.state.nodes;datacenter=dc1"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.nodes", + Value: 4, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.members.clients;datacenter=dc1"] = metrics.GaugeValue{ + Name: "consul.usage.test.members.clients", + Value: 2, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.state.services;datacenter=dc1"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.services", + Value: 8, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.state.service_instances;datacenter=dc1"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.service_instances", + Value: 10, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=connect-proxy"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.connect_instances", + Value: 1, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "connect-proxy"}, + }, + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=terminating-gateway"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.connect_instances", + Value: 1, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "terminating-gateway"}, + }, + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=ingress-gateway"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.connect_instances", + Value: 1, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "ingress-gateway"}, + }, + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=api-gateway"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.connect_instances", + Value: 1, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=mesh-gateway"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.connect_instances", + Value: 1, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "mesh-gateway"}, + }, + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=connect-native"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.connect_instances", + Value: 1, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "connect-native"}, + }, + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.state.billable_service_instances;datacenter=dc1"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.billable_service_instances", + Value: 3, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + }, + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.state.config_entries;datacenter=dc1;kind=ingress-gateway"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.config_entries", + Value: 3, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "ingress-gateway"}, + }, + } + cases["nodes-and-services"] = nodesAndSvcsCase + delete(cases, "nodes") + + for name, tcase := range cases { + t.Run(name, func(t *testing.T) { + reporter, sink, err := getMetricsReporter(tcase) + require.NoError(t, err) + + reporter.runOnce() + + intervals := sink.Data() + require.Len(t, intervals, 1) + intv := intervals[0] + + assertEqualGaugeMaps(t, tcase.expectedGauges, intv.Gauges) + }) + } +} + +func testUsageReporter_emitKVUsage_CE(t *testing.T, getMetricsReporter func(testCase) (*UsageMetricsReporter, *metrics.InmemSink, error)) { + cases := make(map[string]testCase) + for k, v := range baseCases { + eg := make(map[string]metrics.GaugeValue) + for k, v := range v.expectedGauges { + eg[k] = v + } + cases[k] = testCase{v.modifyStateStore, v.getMembersFunc, eg} + } + + nodesCase := cases["nodes"] + mss := nodesCase.modifyStateStore + nodesCase.modifyStateStore = func(t *testing.T, s *state.Store) { + mss(t, s) + require.NoError(t, s.KVSSet(4, &structs.DirEntry{Key: "a", Value: []byte{1}})) + require.NoError(t, s.KVSSet(5, &structs.DirEntry{Key: "b", Value: []byte{1}})) + require.NoError(t, s.KVSSet(6, &structs.DirEntry{Key: "c", Value: []byte{1}})) + require.NoError(t, s.KVSSet(7, &structs.DirEntry{Key: "d", Value: []byte{1}})) + require.NoError(t, s.KVSDelete(8, "d", &acl.EnterpriseMeta{})) + require.NoError(t, s.KVSDelete(9, "c", &acl.EnterpriseMeta{})) + require.NoError(t, s.KVSSet(10, &structs.DirEntry{Key: "e", Value: []byte{1}})) + require.NoError(t, s.KVSSet(11, &structs.DirEntry{Key: "f", Value: []byte{1}})) + } + nodesCase.expectedGauges["consul.usage.test.state.kv_entries;datacenter=dc1"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.kv_entries", + Value: 4, + Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, + } + cases["nodes"] = nodesCase + + for name, tcase := range cases { + t.Run(name, func(t *testing.T) { + reporter, sink, err := getMetricsReporter(tcase) + require.NoError(t, err) + + reporter.runOnce() + + intervals := sink.Data() + require.Len(t, intervals, 1) + intv := intervals[0] + + assertEqualGaugeMaps(t, tcase.expectedGauges, intv.Gauges) + }) + } +} diff --git a/agent/consul/util.go b/agent/consul/util.go index 0fd88e14c8eb..b5827f659a38 100644 --- a/agent/consul/util.go +++ b/agent/consul/util.go @@ -11,7 +11,9 @@ import ( "github.com/hashicorp/go-version" "github.com/hashicorp/serf/serf" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/metadata" + "github.com/hashicorp/consul/agent/structs" ) // CanServersUnderstandProtocol checks to see if all the servers in the given @@ -171,3 +173,14 @@ func isSerfMember(s *serf.Serf, nodeName string) bool { } return false } + +func DefaultIntentionAllow(authz acl.Authorizer, defaultIntentionPolicy string) bool { + // The default intention policy inherits from ACLs but + // is overridden by the agent's DefaultIntentionPolicy. + //nolint:staticcheck + defaultAllow := authz.IntentionDefaultAllow(nil) == acl.Allow + if defaultIntentionPolicy != "" { + defaultAllow = defaultIntentionPolicy == structs.IntentionDefaultPolicyAllow + } + return defaultAllow +} diff --git a/agent/consul/v2_config_entry_exports_shim.go b/agent/consul/v2_config_entry_exports_shim.go new file mode 100644 index 000000000000..8b2ddaf3a706 --- /dev/null +++ b/agent/consul/v2_config_entry_exports_shim.go @@ -0,0 +1,169 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package consul + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/agent/consul/controller/queue" + "github.com/hashicorp/consul/agent/consul/state" + "github.com/hashicorp/consul/agent/consul/stream" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/logging" + "github.com/hashicorp/consul/proto/private/pbconfigentry" + "github.com/hashicorp/go-hclog" +) + +type v1ServiceExportsShim struct { + s *Server + eventCh chan controller.Event +} + +func NewExportedServicesShim(s *Server) *v1ServiceExportsShim { + eventCh := make(chan controller.Event) + return &v1ServiceExportsShim{ + s: s, + eventCh: eventCh, + } +} + +func (s *v1ServiceExportsShim) Start(ctx context.Context) { + logger := s.s.logger.Named(logging.V2ExportsShim) + + // TODO replace this with a proper supervisor. + for ctx.Err() == nil { + err := subscribeToExportedServicesEvents(ctx, logger, s.s.publisher, s.eventCh) + + if err != nil { + logger.Warn("encountered an error while streaming exported services", "error", err) + select { + case <-time.After(time.Second): + case <-ctx.Done(): + return + } + } else { + return + } + } +} + +func subscribeToExportedServicesEvents(ctx context.Context, logger hclog.Logger, publisher *stream.EventPublisher, eventCh chan controller.Event) error { + subscription, err := publisher.Subscribe(&stream.SubscribeRequest{ + Topic: state.EventTopicExportedServices, + Subject: stream.SubjectWildcard, + }) + if err != nil { + return err + } + defer subscription.Unsubscribe() + var index uint64 + + for { + event, err := subscription.Next(ctx) + switch { + case errors.Is(err, context.Canceled): + return nil + case err != nil: + return err + } + + if event.IsFramingEvent() { + continue + } + + if event.Index <= index { + continue + } + + index = event.Index + e := event.Payload.ToSubscriptionEvent(event.Index) + configEntry := e.GetConfigEntry().GetConfigEntry() + + if configEntry.GetKind() != pbconfigentry.Kind_KindExportedServices { + logger.Error("unexpected config entry kind", "kind", configEntry.GetKind()) + continue + } + partition := acl.PartitionOrDefault(configEntry.GetEnterpriseMeta().GetPartition()) + + eventCh <- controller.Event{ + Obj: exportedServiceItemType{partition: partition}, + } + } +} + +func (s *v1ServiceExportsShim) EventChannel() chan controller.Event { + return s.eventCh +} + +func (s *v1ServiceExportsShim) GetExportedServicesConfigEntry(_ context.Context, name string, entMeta *acl.EnterpriseMeta) (*structs.ExportedServicesConfigEntry, error) { + _, entry, err := s.s.fsm.State().ConfigEntry(nil, structs.ExportedServices, name, entMeta) + if err != nil { + return nil, err + } + + if entry == nil { + return nil, nil + } + + exp, ok := entry.(*structs.ExportedServicesConfigEntry) + if !ok { + return nil, fmt.Errorf("exported services config entry is the wrong type: expected ExportedServicesConfigEntry, actual: %T", entry) + } + + return exp, nil +} + +func (s *v1ServiceExportsShim) WriteExportedServicesConfigEntry(_ context.Context, cfg *structs.ExportedServicesConfigEntry) error { + if err := cfg.Normalize(); err != nil { + return err + } + + if err := cfg.Validate(); err != nil { + return err + } + + req := &structs.ConfigEntryRequest{ + Op: structs.ConfigEntryUpsert, + Entry: cfg, + } + + _, err := s.s.raftApply(structs.ConfigEntryRequestType, req) + return err +} + +func (s *v1ServiceExportsShim) DeleteExportedServicesConfigEntry(_ context.Context, name string, entMeta *acl.EnterpriseMeta) error { + if entMeta == nil { + entMeta = acl.DefaultEnterpriseMeta() + } + + req := &structs.ConfigEntryRequest{ + Op: structs.ConfigEntryDelete, + Entry: &structs.ExportedServicesConfigEntry{ + Name: name, + EnterpriseMeta: *entMeta, + }, + } + + if err := req.Entry.Normalize(); err != nil { + return err + } + + _, err := s.s.raftApply(structs.ConfigEntryRequestType, req) + return err +} + +type exportedServiceItemType struct { + partition string +} + +var _ queue.ItemType = (*exportedServiceItemType)(nil) + +func (e exportedServiceItemType) Key() string { + return e.partition +} diff --git a/agent/consul/v2_config_entry_exports_shim_test.go b/agent/consul/v2_config_entry_exports_shim_test.go new file mode 100644 index 000000000000..f44eae0681bc --- /dev/null +++ b/agent/consul/v2_config_entry_exports_shim_test.go @@ -0,0 +1,97 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package consul + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/testrpc" +) + +func TestV1ServiceExportsShim_Integration(t *testing.T) { + t.Parallel() + _, srv := testServerDC(t, "dc1") + + shim := NewExportedServicesShim(srv) + testrpc.WaitForLeader(t, srv.RPC, "dc1") + + v1ServiceExportsShimTests(t, shim, []*structs.ExportedServicesConfigEntry{ + { + Name: "default", + Services: []structs.ExportedService{ + { + Name: "foo", + Consumers: []structs.ServiceConsumer{ + {Peer: "cluster-01"}, + }, + }, + }, + RaftIndex: structs.RaftIndex{ + CreateIndex: 0, + ModifyIndex: 1, + }, + }, + { + Name: "default", + Services: []structs.ExportedService{ + { + Name: "bar", + Consumers: []structs.ServiceConsumer{ + {Peer: "cluster-01"}, + }, + }, + }, + RaftIndex: structs.RaftIndex{ + CreateIndex: 0, + ModifyIndex: 2, + }, + }, + }) +} + +func v1ServiceExportsShimTests(t *testing.T, shim *v1ServiceExportsShim, configs []*structs.ExportedServicesConfigEntry) { + ctx := context.Background() + + go shim.Start(context.Background()) + + partitions := make(map[string]*acl.EnterpriseMeta) + for _, config := range configs { + partitions[config.PartitionOrDefault()] = config.GetEnterpriseMeta() + } + + for _, entMeta := range partitions { + exportedServices, err := shim.GetExportedServicesConfigEntry(ctx, entMeta.PartitionOrDefault(), entMeta) + require.Nil(t, err) + require.Nil(t, exportedServices) + } + + for _, config := range configs { + err := shim.WriteExportedServicesConfigEntry(ctx, config) + require.NoError(t, err) + shim.assertPartitionEvent(t, config.PartitionOrDefault()) + } + + for _, entMeta := range partitions { + err := shim.DeleteExportedServicesConfigEntry(ctx, entMeta.PartitionOrDefault(), entMeta) + require.NoError(t, err) + shim.assertPartitionEvent(t, entMeta.PartitionOrDefault()) + } +} + +func (s *v1ServiceExportsShim) assertPartitionEvent(t *testing.T, partition string) { + t.Helper() + + select { + case event := <-s.eventCh: + require.Equal(t, partition, event.Obj.Key()) + case <-time.After(250 * time.Millisecond): + t.Fatal("timeout waiting for view to receive events") + } +} diff --git a/agent/consul/xdscapacity/capacity.go b/agent/consul/xdscapacity/capacity.go index bf3cf4ced02a..b3c6df2978e2 100644 --- a/agent/consul/xdscapacity/capacity.go +++ b/agent/consul/xdscapacity/capacity.go @@ -15,6 +15,7 @@ import ( "golang.org/x/time/rate" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/lib/channels" "github.com/hashicorp/consul/lib/retry" ) @@ -72,7 +73,7 @@ type SessionLimiter interface { func NewController(cfg Config) *Controller { return &Controller{ cfg: cfg, - serverCh: make(chan uint32), + serverCh: make(chan uint32, 1), doneCh: make(chan struct{}), } } @@ -109,9 +110,9 @@ func (c *Controller) Run(ctx context.Context) { // SetServerCount updates the number of healthy servers that is used when // determining capacity. It is called by the autopilot delegate. func (c *Controller) SetServerCount(count uint32) { - select { - case c.serverCh <- count: - case <-c.doneCh: + if err := channels.DeliverLatest(count, c.serverCh); err != nil { + // This should not be possible since only one producer should ever exist, but log anyway. + c.cfg.Logger.Error("failed to deliver latest server count to xDS capacity controller") } } @@ -186,7 +187,9 @@ func (c *Controller) countProxies(ctx context.Context) (<-chan error, uint32, er ws.Add(store.AbandonCh()) var count uint32 - _, usage, err := store.ServiceUsage(ws) + // we don't care about the per-tenant counts so avoid excessive cpu utilization + // and don't aggregate that information + _, usage, err := store.ServiceUsage(ws, false) // Query failed? Wait for a while, and then go to the top of the loop to // retry (unless the context is cancelled). @@ -208,5 +211,5 @@ func (c *Controller) countProxies(ctx context.Context) (<-chan error, uint32, er type Store interface { AbandonCh() <-chan struct{} - ServiceUsage(ws memdb.WatchSet) (uint64, structs.ServiceUsage, error) + ServiceUsage(ws memdb.WatchSet, tenantUsage bool) (uint64, structs.ServiceUsage, error) } diff --git a/agent/consul/xdscapacity/capacity_test.go b/agent/consul/xdscapacity/capacity_test.go index b3a3935a8806..bb6f4cc0d4a7 100644 --- a/agent/consul/xdscapacity/capacity_test.go +++ b/agent/consul/xdscapacity/capacity_test.go @@ -137,3 +137,56 @@ func TestCalcRateLimit(t *testing.T) { require.Equalf(t, out, calcRateLimit(in), "calcRateLimit(%d)", in) } } + +func BenchmarkCountProxies(b *testing.B) { + const index = 123 + + store := state.NewStateStore(nil) + + // This loop generates: + // + // 4 (service kind) * 100 (service) * 5 * (node) = 2000 proxy services. And 500 non-proxy services. + for _, kind := range []structs.ServiceKind{ + // These will be included in the count. + structs.ServiceKindConnectProxy, + structs.ServiceKindIngressGateway, + structs.ServiceKindTerminatingGateway, + structs.ServiceKindMeshGateway, + + // This one will not. + structs.ServiceKindTypical, + } { + for i := 0; i < 100; i++ { + serviceName := fmt.Sprintf("%s-%d", kind, i) + + for j := 0; j < 5; j++ { + nodeName := fmt.Sprintf("%s-node-%d", serviceName, j) + + require.NoError(b, store.EnsureRegistration(index, &structs.RegisterRequest{ + Node: nodeName, + Service: &structs.NodeService{ + ID: serviceName, + Service: serviceName, + Kind: kind, + }, + })) + } + } + } + + ctx := testutil.TestContext(b) + c := &Controller{ + cfg: Config{ + GetStore: func() Store { return store }, + }, + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, numProxies, err := c.countProxies(ctx); err != nil { + b.Fatalf("encountered unexpected error: %v", err) + } else if numProxies != 2000 { + b.Fatalf("unexpected count: %d", numProxies) + } + } +} diff --git a/agent/delegate_mock_test.go b/agent/delegate_mock_test.go index a75cf2d1e262..206aac9c7e6b 100644 --- a/agent/delegate_mock_test.go +++ b/agent/delegate_mock_test.go @@ -14,7 +14,7 @@ import ( "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/agent/consul" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/proto-public/pbresource" ) @@ -22,9 +22,9 @@ type delegateMock struct { mock.Mock } -func (m *delegateMock) GetLANCoordinate() (lib.CoordinateSet, error) { +func (m *delegateMock) GetLANCoordinate() (librtt.CoordinateSet, error) { ret := m.Called() - return ret.Get(0).(lib.CoordinateSet), ret.Error(1) + return ret.Get(0).(librtt.CoordinateSet), ret.Error(1) } func (m *delegateMock) Leave() error { diff --git a/agent/dns.go b/agent/dns.go index b55338ea3e67..dd34b3b8bda7 100644 --- a/agent/dns.go +++ b/agent/dns.go @@ -8,6 +8,7 @@ import ( "encoding/hex" "errors" "fmt" + agentdns "github.com/hashicorp/consul/agent/dns" "math" "net" "regexp" @@ -16,41 +17,22 @@ import ( "time" "github.com/armon/go-metrics" - "github.com/armon/go-metrics/prometheus" "github.com/armon/go-radix" - "github.com/coredns/coredns/plugin/pkg/dnsutil" "github.com/hashicorp/go-hclog" "github.com/miekg/dns" "github.com/hashicorp/consul/acl" cachetype "github.com/hashicorp/consul/agent/cache-types" "github.com/hashicorp/consul/agent/config" - agentdns "github.com/hashicorp/consul/agent/dns" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" + dnsutil "github.com/hashicorp/consul/internal/dnsutil" + libdns "github.com/hashicorp/consul/internal/dnsutil" "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/logging" ) -var DNSCounters = []prometheus.CounterDefinition{ - { - Name: []string{"dns", "stale_queries"}, - Help: "Increments when an agent serves a query within the allowed stale threshold.", - }, -} - -var DNSSummaries = []prometheus.SummaryDefinition{ - { - Name: []string{"dns", "ptr_query"}, - Help: "Measures the time spent handling a reverse DNS query for the given node.", - }, - { - Name: []string{"dns", "domain_query"}, - Help: "Measures the time spent handling a domain query for the given node.", - }, -} - const ( // UDP can fit ~25 A records in a 512B response, and ~14 AAAA // records. Limit further to prevent unintentional configuration @@ -80,7 +62,17 @@ type dnsSOAConfig struct { Minttl uint32 // 0 } -type dnsConfig struct { +// dnsRequestConfig returns the DNS request configuration that encapsulates: +// - the DNS server configuration. +// - the token from the request, if available. +// - the enterprise meta from the request, if available. +type dnsRequestConfig struct { + *dnsServerConfig + token string + defaultEnterpriseMeta acl.EnterpriseMeta +} + +type dnsServerConfig struct { AllowStale bool Datacenter string EnableTruncate bool @@ -90,7 +82,7 @@ type dnsConfig struct { NodeName string NodeTTL time.Duration OnlyPassing bool - RecursorStrategy agentdns.RecursorStrategy + RecursorStrategy structs.RecursorStrategy RecursorTimeout time.Duration Recursors []string SegmentName string @@ -111,6 +103,7 @@ type serviceLookup struct { PeerName string Datacenter string Service string + SamenessGroup string Tag string MaxRecursionLevel int Connect bool @@ -137,7 +130,7 @@ type DNSServer struct { altDomain string logger hclog.Logger - // config stores the config as an atomic value (for hot-reloading). It is always of type *dnsConfig + // config stores the config as an atomic value (for hot-reloading). It is always of type *dnsServerConfig config atomic.Value // recursorEnabled stores whever the recursor handler is enabled as an atomic flag. @@ -159,7 +152,7 @@ func NewDNSServer(a *Agent) (*DNSServer, error) { defaultEnterpriseMeta: *a.AgentEnterpriseMeta(), mux: dns.NewServeMux(), } - cfg, err := GetDNSConfig(a.config) + cfg, err := getDNSServerConfig(a.config) if err != nil { return nil, err } @@ -181,9 +174,9 @@ func NewDNSServer(a *Agent) (*DNSServer, error) { return srv, nil } -// GetDNSConfig takes global config and creates the config used by DNS server -func GetDNSConfig(conf *config.RuntimeConfig) (*dnsConfig, error) { - cfg := &dnsConfig{ +// getDNSServerConfig takes global config and creates the config used by DNS server +func getDNSServerConfig(conf *config.RuntimeConfig) (*dnsServerConfig, error) { + cfg := &dnsServerConfig{ AllowStale: conf.DNSAllowStale, ARecordLimit: conf.DNSARecordLimit, Datacenter: conf.Datacenter, @@ -235,7 +228,7 @@ func GetDNSConfig(conf *config.RuntimeConfig) (*dnsConfig, error) { // GetTTLForService Find the TTL for a given service. // return ttl, true if found, 0, false otherwise -func (cfg *dnsConfig) GetTTLForService(service string) (time.Duration, bool) { +func (cfg *dnsServerConfig) GetTTLForService(service string) (time.Duration, bool) { if cfg.TTLStrict != nil { ttl, ok := cfg.TTLStrict[service] if ok { @@ -264,8 +257,30 @@ func (d *DNSServer) ListenAndServe(network, addr string, notif func()) error { return d.Server.ListenAndServe() } +func (d *DNSServer) Shutdown() { + if d.Server != nil { + d.logger.Info("Stopping server", + "protocol", "DNS", + "address", d.Server.Addr, + "network", d.Server.Net, + ) + err := d.Server.Shutdown() + if err != nil { + d.logger.Error("Error stopping DNS server", "error", err) + } + } +} + +// GetAddr is a function to return the server address if is not nil. +func (d *DNSServer) GetAddr() string { + if d.Server != nil { + return d.Server.Addr + } + return "" +} + // toggleRecursorHandlerFromConfig enables or disables the recursor handler based on config idempotently -func (d *DNSServer) toggleRecursorHandlerFromConfig(cfg *dnsConfig) { +func (d *DNSServer) toggleRecursorHandlerFromConfig(cfg *dnsServerConfig) { shouldEnable := len(cfg.Recursors) > 0 if shouldEnable && atomic.CompareAndSwapUint32(&d.recursorEnabled, 0, 1) { @@ -283,7 +298,7 @@ func (d *DNSServer) toggleRecursorHandlerFromConfig(cfg *dnsConfig) { // ReloadConfig hot-reloads the server config with new parameters under config.RuntimeConfig.DNS* func (d *DNSServer) ReloadConfig(newCfg *config.RuntimeConfig) error { - cfg, err := GetDNSConfig(newCfg) + cfg, err := getDNSServerConfig(newCfg) if err != nil { return err } @@ -384,8 +399,17 @@ func (d *DNSServer) getResponseDomain(questionName string) string { func (d *DNSServer) handlePtr(resp dns.ResponseWriter, req *dns.Msg) { q := req.Question[0] defer func(s time.Time) { + // V1 DNS-style metrics metrics.MeasureSinceWithLabels([]string{"dns", "ptr_query"}, s, []metrics.Label{{Name: "node", Value: d.agent.config.NodeName}}) + + // V2 DNS-style metrics for forward compatibility + metrics.MeasureSinceWithLabels([]string{"dns", "query"}, s, + []metrics.Label{ + {Name: "node", Value: d.agent.config.NodeName}, + {Name: "type", Value: dns.Type(dns.TypePTR).String()}, + }) + d.logger.Debug("request served from client", "question", q, "latency", time.Since(s).String(), @@ -394,18 +418,19 @@ func (d *DNSServer) handlePtr(resp dns.ResponseWriter, req *dns.Msg) { ) }(time.Now()) - cfg := d.config.Load().(*dnsConfig) + cfg := d.getRequestConfig(resp) // Setup the message response m := new(dns.Msg) m.SetReply(req) m.Compress = !cfg.DisableCompression m.Authoritative = true - m.RecursionAvailable = (len(cfg.Recursors) > 0) + recursionAvailable := atomic.LoadUint32(&(d.recursorEnabled)) == 1 + m.RecursionAvailable = recursionAvailable // Only add the SOA if requested if req.Question[0].Qtype == dns.TypeSOA { - d.addSOA(cfg, m, q.Name) + d.addSOAToMessage(cfg, m, q.Name) } datacenter := d.agent.config.Datacenter @@ -416,7 +441,7 @@ func (d *DNSServer) handlePtr(resp dns.ResponseWriter, req *dns.Msg) { args := structs.DCSpecificRequest{ Datacenter: datacenter, QueryOptions: structs.QueryOptions{ - Token: d.coalesceDNSToken(), + Token: d.coalesceDNSToken(cfg.token), AllowStale: cfg.AllowStale, }, } @@ -426,18 +451,11 @@ func (d *DNSServer) handlePtr(resp dns.ResponseWriter, req *dns.Msg) { // server side to avoid transferring the entire node list. if err := d.agent.RPC(context.Background(), "Catalog.ListNodes", &args, &out); err == nil { for _, n := range out.Nodes { - lookup := serviceLookup{ - // Peering PTR lookups are currently not supported, so we don't - // need to populate that field for creating the node FQDN. - // PeerName: n.PeerName, - Datacenter: n.Datacenter, - EnterpriseMeta: *n.GetEnterpriseMeta(), - } arpa, _ := dns.ReverseAddr(n.Address) if arpa == qName { ptr := &dns.PTR{ Hdr: dns.RR_Header{Name: q.Name, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: 0}, - Ptr: nodeCanonicalDNSName(lookup, n.Node, d.domain), + Ptr: nodeCanonicalDNSName(n, d.domain), } m.Answer = append(m.Answer, ptr) break @@ -448,15 +466,19 @@ func (d *DNSServer) handlePtr(resp dns.ResponseWriter, req *dns.Msg) { // only look into the services if we didn't find a node if len(m.Answer) == 0 { // lookup the service address - serviceAddress := dnsutil.ExtractAddressFromReverse(qName) + ip := libdns.IPFromARPA(qName) + var serviceAddress string + if ip != nil { + serviceAddress = ip.String() + } sargs := structs.ServiceSpecificRequest{ Datacenter: datacenter, QueryOptions: structs.QueryOptions{ - Token: d.coalesceDNSToken(), + Token: d.coalesceDNSToken(cfg.token), AllowStale: cfg.AllowStale, }, ServiceAddress: serviceAddress, - EnterpriseMeta: *d.defaultEnterpriseMeta.WithWildcardNamespace(), + EnterpriseMeta: *cfg.defaultEnterpriseMeta.WithWildcardNamespace(), } var sout structs.IndexedServiceNodes @@ -476,8 +498,13 @@ func (d *DNSServer) handlePtr(resp dns.ResponseWriter, req *dns.Msg) { // nothing found locally, recurse if len(m.Answer) == 0 { - d.handleRecurse(resp, req) - return + if recursionAvailable { + d.handleRecurse(resp, req) + return + } else { + m.SetRcode(req, dns.RcodeNameError) + d.addSOAToMessage(cfg, m, q.Name) + } } // ptr record responses are globally valid @@ -493,12 +520,21 @@ func (d *DNSServer) handlePtr(resp dns.ResponseWriter, req *dns.Msg) { func (d *DNSServer) handleQuery(resp dns.ResponseWriter, req *dns.Msg) { q := req.Question[0] defer func(s time.Time) { + // V1 DNS-style metrics metrics.MeasureSinceWithLabels([]string{"dns", "domain_query"}, s, []metrics.Label{{Name: "node", Value: d.agent.config.NodeName}}) + + // V2 DNS-style metrics for forward compatibility + metrics.MeasureSinceWithLabels([]string{"dns", "query"}, s, + []metrics.Label{ + {Name: "node", Value: d.agent.config.NodeName}, + {Name: "type", Value: dns.Type(q.Qtype).String()}, + }) + d.logger.Debug("request served from client", "name", q.Name, - "type", dns.Type(q.Qtype), - "class", dns.Class(q.Qclass), + "type", dns.Type(q.Qtype).String(), + "class", dns.Class(q.Qclass).String(), "latency", time.Since(s).String(), "client", resp.RemoteAddr().String(), "client_network", resp.RemoteAddr().Network(), @@ -511,7 +547,7 @@ func (d *DNSServer) handleQuery(resp dns.ResponseWriter, req *dns.Msg) { network = "tcp" } - cfg := d.config.Load().(*dnsConfig) + cfg := d.getRequestConfig(resp) // Set up the message response m := new(dns.Msg) @@ -524,14 +560,14 @@ func (d *DNSServer) handleQuery(resp dns.ResponseWriter, req *dns.Msg) { switch req.Question[0].Qtype { case dns.TypeSOA: - ns, glue := d.nameservers(req.Question[0].Name, cfg, maxRecursionLevelDefault) - m.Answer = append(m.Answer, d.soa(cfg, q.Name)) + ns, glue := d.getNameserversAndNodeRecord(req.Question[0].Name, cfg, maxRecursionLevelDefault) + m.Answer = append(m.Answer, d.makeSOARecord(cfg, q.Name)) m.Ns = append(m.Ns, ns...) m.Extra = append(m.Extra, glue...) m.SetRcode(req, dns.RcodeSuccess) case dns.TypeNS: - ns, glue := d.nameservers(req.Question[0].Name, cfg, maxRecursionLevelDefault) + ns, glue := d.getNameserversAndNodeRecord(req.Question[0].Name, cfg, maxRecursionLevelDefault) m.Answer = ns m.Extra = glue m.SetRcode(req, dns.RcodeSuccess) @@ -540,10 +576,10 @@ func (d *DNSServer) handleQuery(resp dns.ResponseWriter, req *dns.Msg) { m.SetRcode(req, dns.RcodeNotImplemented) default: - err = d.dispatch(resp.RemoteAddr(), req, m, maxRecursionLevelDefault) + err = d.dispatch(resp.RemoteAddr(), req, m, cfg, maxRecursionLevelDefault) rCode := rCodeFromError(err) if rCode == dns.RcodeNameError || errors.Is(err, errNoData) { - d.addSOA(cfg, m, q.Name) + d.addSOAToMessage(cfg, m, q.Name) } m.SetRcode(req, rCode) } @@ -557,7 +593,8 @@ func (d *DNSServer) handleQuery(resp dns.ResponseWriter, req *dns.Msg) { } } -func (d *DNSServer) soa(cfg *dnsConfig, questionName string) *dns.SOA { +// Craft dns records for an SOA +func (d *DNSServer) makeSOARecord(cfg *dnsRequestConfig, questionName string) *dns.SOA { domain := d.domain if d.altDomain != "" && strings.HasSuffix(questionName, "."+d.altDomain) { domain = d.altDomain @@ -582,20 +619,19 @@ func (d *DNSServer) soa(cfg *dnsConfig, questionName string) *dns.SOA { } // addSOA is used to add an SOA record to a message for the given domain -func (d *DNSServer) addSOA(cfg *dnsConfig, msg *dns.Msg, questionName string) { - msg.Ns = append(msg.Ns, d.soa(cfg, questionName)) +func (d *DNSServer) addSOAToMessage(cfg *dnsRequestConfig, msg *dns.Msg, questionName string) { + msg.Ns = append(msg.Ns, d.makeSOARecord(cfg, questionName)) } -// nameservers returns the names and ip addresses of up to three random servers +// getNameserversAndNodeRecord returns the names and ip addresses of up to three random servers // in the current cluster which serve as authoritative name servers for zone. - -func (d *DNSServer) nameservers(questionName string, cfg *dnsConfig, maxRecursionLevel int) (ns []dns.RR, extra []dns.RR) { +func (d *DNSServer) getNameserversAndNodeRecord(questionName string, cfg *dnsRequestConfig, maxRecursionLevel int) (ns []dns.RR, extra []dns.RR) { out, err := d.lookupServiceNodes(cfg, serviceLookup{ Datacenter: d.agent.config.Datacenter, Service: structs.ConsulServiceName, Connect: false, Ingress: false, - EnterpriseMeta: d.defaultEnterpriseMeta, + EnterpriseMeta: cfg.defaultEnterpriseMeta, }) if err != nil { d.logger.Warn("Unable to get list of servers", "error", err) @@ -613,7 +649,7 @@ func (d *DNSServer) nameservers(questionName string, cfg *dnsConfig, maxRecursio for _, o := range out.Nodes { name, dc := o.Node.Node, o.Node.Datacenter - if agentdns.InvalidNameRe.MatchString(name) { + if libdns.InvalidNameRe.MatchString(name) { d.logger.Warn("Skipping invalid node for NS records", "node", name) continue } @@ -633,7 +669,7 @@ func (d *DNSServer) nameservers(questionName string, cfg *dnsConfig, maxRecursio } ns = append(ns, nsrr) - extra = append(extra, d.makeRecordFromNode(o.Node, dns.TypeANY, fqdn, cfg.NodeTTL, maxRecursionLevel)...) + extra = append(extra, d.makeRecordFromNode(o.Node, dns.TypeANY, fqdn, cfg, maxRecursionLevel)...) // don't provide more than 3 servers if len(ns) >= 3 { @@ -644,12 +680,10 @@ func (d *DNSServer) nameservers(questionName string, cfg *dnsConfig, maxRecursio return } -func (d *DNSServer) invalidQuery(req, resp *dns.Msg, cfg *dnsConfig, qName string) { - d.logger.Warn("QName invalid", "qname", qName) - d.addSOA(cfg, resp, qName) - resp.SetRcode(req, dns.RcodeNameError) -} - +// parseDatacenter will do the following: +// - if zero labels are passed, return true without modifying the datacenter parameter +// - if one label is passed, set the datacenter parameter to the label and return true +// - Otherwise it will return false without modifying the datacenter parameter func (d *DNSServer) parseDatacenter(labels []string, datacenter *string) bool { switch len(labels) { case 1: @@ -709,6 +743,10 @@ type queryLocality struct { // not be shared between datacenters. In all other cases, it should be considered a DC. peerOrDatacenter string + // samenessGroup is the samenessGroup name parsed from a label that has explicit parts. + // Example query: .service..sg.consul + samenessGroup string + acl.EnterpriseMeta } @@ -727,7 +765,7 @@ func (l queryLocality) effectiveDatacenter(defaultDC string) string { // dispatch is used to parse a request and invoke the correct handler. // parameter maxRecursionLevel will handle whether recursive call can be performed -func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursionLevel int) error { +func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, cfg *dnsRequestConfig, maxRecursionLevel int) error { // Choose correct response domain respDomain := d.getResponseDomain(req.Question[0].Name) @@ -738,8 +776,6 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi // Split into the label parts labels := dns.SplitDomainName(qName) - cfg := d.config.Load().(*dnsConfig) - var queryKind string var queryParts []string var querySuffixes []string @@ -776,59 +812,56 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi return invalid() } - localities, err := d.parseSamenessGroupLocality(cfg, querySuffixes, invalid) + locality, err := d.parseSamenessGroupLocality(cfg, querySuffixes, invalid) if err != nil { return err } - // Loop over the localities and return as soon as a lookup is successful - for _, locality := range localities { - d.logger.Debug("labels", "querySuffixes", querySuffixes) - - lookup := serviceLookup{ - Datacenter: locality.effectiveDatacenter(d.agent.config.Datacenter), - PeerName: locality.peer, - Connect: false, - Ingress: false, - MaxRecursionLevel: maxRecursionLevel, - EnterpriseMeta: locality.EnterpriseMeta, - } - // Only one of dc or peer can be used. - if lookup.PeerName != "" { - lookup.Datacenter = "" - } - - // Support RFC 2782 style syntax - if n == 2 && strings.HasPrefix(queryParts[1], "_") && strings.HasPrefix(queryParts[0], "_") { - // Grab the tag since we make nuke it if it's tcp - tag := queryParts[1][1:] + lookup := serviceLookup{ + Datacenter: locality.effectiveDatacenter(d.agent.config.Datacenter), + PeerName: locality.peer, + SamenessGroup: locality.samenessGroup, + Connect: false, + Ingress: false, + MaxRecursionLevel: maxRecursionLevel, + EnterpriseMeta: locality.EnterpriseMeta, + } - // Treat _name._tcp.service.consul as a default, no need to filter on that tag - if tag == "tcp" { - tag = "" - } + // Only one of dc or peer can be used. + if lookup.PeerName != "" { + lookup.Datacenter = "" + } - lookup.Tag = tag - lookup.Service = queryParts[0][1:] - // _name._tag.service.consul - } else { - // Consul 0.3 and prior format for SRV queries - // Support "." in the label, re-join all the parts - tag := "" - if n >= 2 { - tag = strings.Join(queryParts[:n-1], ".") - } + // Support RFC 2782 style syntax + if n == 2 && strings.HasPrefix(queryParts[1], "_") && strings.HasPrefix(queryParts[0], "_") { + // Grab the tag since we make nuke it if it's tcp + tag := queryParts[1][1:] - lookup.Tag = tag - lookup.Service = queryParts[n-1] - // tag[.tag].name.service.consul + // Treat _name._tcp.service.consul as a default, no need to filter on that tag + if tag == "tcp" { + tag = "" } - err = d.serviceLookup(cfg, lookup, req, resp) - // Return if we are error free right away, otherwise loop again if we can - if err == nil { - return nil + lookup.Tag = tag + lookup.Service = queryParts[0][1:] + // _name._tag.service.consul + } else { + // Consul 0.3 and prior format for SRV queries + // Support "." in the label, re-join all the parts + tag := "" + if n >= 2 { + tag = strings.Join(queryParts[:n-1], ".") } + + lookup.Tag = tag + lookup.Service = queryParts[n-1] + // tag[.tag].name.service.consul + } + + err = d.handleServiceQuery(cfg, lookup, req, resp) + // Return if we are error free right away, otherwise loop again if we can + if err == nil { + return nil } // We've exhausted all DNS possibilities so return here @@ -855,7 +888,7 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi EnterpriseMeta: locality.EnterpriseMeta, } // name.connect.consul - return d.serviceLookup(cfg, lookup, req, resp) + return d.handleServiceQuery(cfg, lookup, req, resp) case "virtual": if len(queryParts) < 1 { @@ -875,7 +908,7 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi ServiceName: queryParts[len(queryParts)-1], EnterpriseMeta: locality.EnterpriseMeta, QueryOptions: structs.QueryOptions{ - Token: d.coalesceDNSToken(), + Token: d.coalesceDNSToken(cfg.token), }, } if args.PeerName == "" { @@ -922,7 +955,7 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi EnterpriseMeta: locality.EnterpriseMeta, } // name.ingress.consul - return d.serviceLookup(cfg, lookup, req, resp) + return d.handleServiceQuery(cfg, lookup, req, resp) case "node": if len(queryParts) < 1 { @@ -955,7 +988,7 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi lookup.Datacenter = "" } - return d.nodeLookup(cfg, lookup, req, resp) + return d.handleNodeQuery(cfg, lookup, req, resp) case "query": n := len(queryParts) @@ -987,7 +1020,7 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi query = strings.Join(queryParts, ".") } - err := d.preparedQueryLookup(cfg, datacenter, query, remoteAddr, req, resp, maxRecursionLevel) + err := d.handlePreparedQuery(cfg, datacenter, query, remoteAddr, req, resp, maxRecursionLevel) return ecsNotGlobalError{error: err} case "addr": @@ -1040,6 +1073,8 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi } else { resp.Answer = append(resp.Answer, aaaaRecord) } + default: + return invalid() } return nil default: @@ -1070,17 +1105,19 @@ func rCodeFromError(err error) int { return dns.RcodeSuccess case errors.Is(err, errECSNotGlobal): return rCodeFromError(errors.Unwrap(err)) - case errors.Is(err, errNameNotFound): - return dns.RcodeNameError - case structs.IsErrNoDCPath(err) || structs.IsErrQueryNotFound(err): + case errors.Is(err, errNameNotFound), + structs.IsErrNoDCPath(err), + structs.IsErrQueryNotFound(err), + structs.IsErrSamenessGroupMustBeDefaultForFailover(err), + structs.IsErrSamenessGroupNotFound(err): return dns.RcodeNameError default: return dns.RcodeServerFailure } } -// nodeLookup is used to handle a node query -func (d *DNSServer) nodeLookup(cfg *dnsConfig, lookup nodeLookup, req, resp *dns.Msg) error { +// handleNodeQuery is used to handle a node query +func (d *DNSServer) handleNodeQuery(cfg *dnsRequestConfig, lookup nodeLookup, req, resp *dns.Msg) error { // Only handle ANY, A, AAAA, and TXT type requests qType := req.Question[0].Qtype if qType != dns.TypeANY && qType != dns.TypeA && qType != dns.TypeAAAA && qType != dns.TypeTXT { @@ -1093,7 +1130,7 @@ func (d *DNSServer) nodeLookup(cfg *dnsConfig, lookup nodeLookup, req, resp *dns PeerName: lookup.PeerName, Node: lookup.Node, QueryOptions: structs.QueryOptions{ - Token: d.coalesceDNSToken(), + Token: d.coalesceDNSToken(cfg.token), AllowStale: cfg.AllowStale, }, EnterpriseMeta: lookup.EnterpriseMeta, @@ -1119,18 +1156,20 @@ func (d *DNSServer) nodeLookup(cfg *dnsConfig, lookup nodeLookup, req, resp *dns q := req.Question[0] // Only compute A and CNAME record if query is not TXT type if qType != dns.TypeTXT { - records := d.makeRecordFromNode(n, q.Qtype, q.Name, cfg.NodeTTL, lookup.MaxRecursionLevel) + records := d.makeRecordFromNode(n, q.Qtype, q.Name, cfg, lookup.MaxRecursionLevel) resp.Answer = append(resp.Answer, records...) } if cfg.NodeMetaTXT || qType == dns.TypeTXT || qType == dns.TypeANY { - metas := d.generateMeta(q.Name, n, cfg.NodeTTL) + metas := d.makeTXTRecordFromNodeMeta(q.Name, n, cfg.NodeTTL) *metaTarget = append(*metaTarget, metas...) } return nil } -func (d *DNSServer) lookupNode(cfg *dnsConfig, args *structs.NodeSpecificRequest) (*structs.IndexedNodeServices, error) { +// lookupNode is used to look up a node in the Consul catalog within NodeServices. +// If the config is set to UseCache, it will get the record from the agent cache. +func (d *DNSServer) lookupNode(cfg *dnsRequestConfig, args *structs.NodeSpecificRequest) (*structs.IndexedNodeServices, error) { var out structs.IndexedNodeServices useCache := cfg.UseCache @@ -1387,7 +1426,7 @@ func trimUDPResponse(req, resp *dns.Msg, udpAnswerLimit int) (trimmed bool) { } // trimDNSResponse will trim the response for UDP and TCP -func (d *DNSServer) trimDNSResponse(cfg *dnsConfig, network string, req, resp *dns.Msg) { +func (d *DNSServer) trimDNSResponse(cfg *dnsRequestConfig, network string, req, resp *dns.Msg) { var trimmed bool originalSize := resp.Len() originalNumRecords := len(resp.Answer) @@ -1410,22 +1449,29 @@ func (d *DNSServer) trimDNSResponse(cfg *dnsConfig, network string, req, resp *d } } -// lookupServiceNodes returns nodes with a given service. -func (d *DNSServer) lookupServiceNodes(cfg *dnsConfig, lookup serviceLookup) (structs.IndexedCheckServiceNodes, error) { +// lookupServiceNodes is used to look up a node in the Consul health catalog within ServiceNodes. +// If the config is set to UseCache, it will get the record from the agent cache. +func (d *DNSServer) lookupServiceNodes(cfg *dnsRequestConfig, lookup serviceLookup) (structs.IndexedCheckServiceNodes, error) { serviceTags := []string{} if lookup.Tag != "" { serviceTags = []string{lookup.Tag} } + healthFilterType := structs.HealthFilterExcludeCritical + if cfg.OnlyPassing { + healthFilterType = structs.HealthFilterIncludeOnlyPassing + } args := structs.ServiceSpecificRequest{ - PeerName: lookup.PeerName, - Connect: lookup.Connect, - Ingress: lookup.Ingress, - Datacenter: lookup.Datacenter, - ServiceName: lookup.Service, - ServiceTags: serviceTags, - TagFilter: lookup.Tag != "", + PeerName: lookup.PeerName, + SamenessGroup: lookup.SamenessGroup, + Connect: lookup.Connect, + Ingress: lookup.Ingress, + Datacenter: lookup.Datacenter, + ServiceName: lookup.Service, + ServiceTags: serviceTags, + TagFilter: lookup.Tag != "", + HealthFilterType: healthFilterType, QueryOptions: structs.QueryOptions{ - Token: d.coalesceDNSToken(), + Token: d.coalesceDNSToken(cfg.token), AllowStale: cfg.AllowStale, MaxAge: cfg.CacheMaxAge, UseCache: cfg.UseCache, @@ -1439,16 +1485,11 @@ func (d *DNSServer) lookupServiceNodes(cfg *dnsConfig, lookup serviceLookup) (st return out, err } - // Filter out any service nodes due to health checks - // We copy the slice to avoid modifying the result if it comes from the cache - nodes := make(structs.CheckServiceNodes, len(out.Nodes)) - copy(nodes, out.Nodes) - out.Nodes = nodes.Filter(cfg.OnlyPassing) return out, nil } -// serviceLookup is used to handle a service query -func (d *DNSServer) serviceLookup(cfg *dnsConfig, lookup serviceLookup, req, resp *dns.Msg) error { +// handleServiceQuery is used to handle a service query +func (d *DNSServer) handleServiceQuery(cfg *dnsRequestConfig, lookup serviceLookup, req, resp *dns.Msg) error { out, err := d.lookupServiceNodes(cfg, lookup) if err != nil { return fmt.Errorf("rpc request failed: %w", err) @@ -1468,9 +1509,9 @@ func (d *DNSServer) serviceLookup(cfg *dnsConfig, lookup serviceLookup, req, res // Add various responses depending on the request qType := req.Question[0].Qtype if qType == dns.TypeSRV { - d.serviceSRVRecords(cfg, lookup, out.Nodes, req, resp, ttl, lookup.MaxRecursionLevel) + d.addServiceSRVRecordsToMessage(cfg, lookup, out.Nodes, req, resp, ttl, lookup.MaxRecursionLevel) } else { - d.serviceNodeRecords(cfg, lookup, out.Nodes, req, resp, ttl, lookup.MaxRecursionLevel) + d.addServiceNodeRecordsToMessage(cfg, lookup, out.Nodes, req, resp, ttl, lookup.MaxRecursionLevel) } if len(resp.Answer) == 0 { @@ -1496,14 +1537,14 @@ func ednsSubnetForRequest(req *dns.Msg) *dns.EDNS0_SUBNET { return nil } -// preparedQueryLookup is used to handle a prepared query. -func (d *DNSServer) preparedQueryLookup(cfg *dnsConfig, datacenter, query string, remoteAddr net.Addr, req, resp *dns.Msg, maxRecursionLevel int) error { +// handlePreparedQuery is used to handle a prepared query. +func (d *DNSServer) handlePreparedQuery(cfg *dnsRequestConfig, datacenter, query string, remoteAddr net.Addr, req, resp *dns.Msg, maxRecursionLevel int) error { // Execute the prepared query. args := structs.PreparedQueryExecuteRequest{ Datacenter: datacenter, QueryIDOrName: query, QueryOptions: structs.QueryOptions{ - Token: d.coalesceDNSToken(), + Token: d.coalesceDNSToken(cfg.token), AllowStale: cfg.AllowStale, MaxAge: cfg.CacheMaxAge, }, @@ -1578,9 +1619,9 @@ func (d *DNSServer) preparedQueryLookup(cfg *dnsConfig, datacenter, query string // because peering is not supported with prepared queries. lookup := serviceLookup{Datacenter: out.Datacenter} if qType == dns.TypeSRV { - d.serviceSRVRecords(cfg, lookup, out.Nodes, req, resp, ttl, maxRecursionLevel) + d.addServiceSRVRecordsToMessage(cfg, lookup, out.Nodes, req, resp, ttl, maxRecursionLevel) } else { - d.serviceNodeRecords(cfg, lookup, out.Nodes, req, resp, ttl, maxRecursionLevel) + d.addServiceNodeRecordsToMessage(cfg, lookup, out.Nodes, req, resp, ttl, maxRecursionLevel) } if len(resp.Answer) == 0 { @@ -1589,7 +1630,9 @@ func (d *DNSServer) preparedQueryLookup(cfg *dnsConfig, datacenter, query string return nil } -func (d *DNSServer) lookupPreparedQuery(cfg *dnsConfig, args structs.PreparedQueryExecuteRequest) (*structs.PreparedQueryExecuteResponse, error) { +// lookupPreparedQuery is used to execute a PreparedQuery against the Consul catalog. +// If the config is set to UseCache, it will use agent cache. +func (d *DNSServer) lookupPreparedQuery(cfg *dnsRequestConfig, args structs.PreparedQueryExecuteRequest) (*structs.PreparedQueryExecuteResponse, error) { var out structs.PreparedQueryExecuteResponse RPC: @@ -1630,8 +1673,8 @@ RPC: return &out, nil } -// serviceNodeRecords is used to add the node records for a service lookup -func (d *DNSServer) serviceNodeRecords(cfg *dnsConfig, lookup serviceLookup, nodes structs.CheckServiceNodes, req, resp *dns.Msg, ttl time.Duration, maxRecursionLevel int) { +// addServiceNodeRecordsToMessage is used to add the node records for a service lookup +func (d *DNSServer) addServiceNodeRecordsToMessage(cfg *dnsRequestConfig, lookup serviceLookup, nodes structs.CheckServiceNodes, req, resp *dns.Msg, ttl time.Duration, maxRecursionLevel int) { handled := make(map[string]struct{}) var answerCNAME []dns.RR = nil @@ -1639,7 +1682,7 @@ func (d *DNSServer) serviceNodeRecords(cfg *dnsConfig, lookup serviceLookup, nod for _, node := range nodes { // Add the node record had_answer := false - records, _ := d.nodeServiceRecords(lookup, node, req, ttl, cfg, maxRecursionLevel) + records, _ := d.makeNodeServiceRecords(lookup, node, req, ttl, cfg, maxRecursionLevel) if len(records) == 0 { continue } @@ -1722,22 +1765,23 @@ func findWeight(node structs.CheckServiceNode) int { } } -func (d *DNSServer) encodeIPAsFqdn(questionName string, lookup serviceLookup, ip net.IP) string { +func (d *DNSServer) encodeIPAsFqdn(questionName string, serviceNode structs.CheckServiceNode, ip net.IP) string { ipv4 := ip.To4() respDomain := d.getResponseDomain(questionName) ipStr := hex.EncodeToString(ip) if ipv4 != nil { ipStr = ipStr[len(ipStr)-(net.IPv4len*2):] } - if lookup.PeerName != "" { + if serviceNode.Service.PeerName != "" { // Exclude the datacenter from the FQDN on the addr for peers. // This technically makes no difference, since the addr endpoint ignores the DC // component of the request, but do it anyway for a less confusing experience. return fmt.Sprintf("%s.addr.%s", ipStr, respDomain) } - return fmt.Sprintf("%s.addr.%s.%s", ipStr, lookup.Datacenter, respDomain) + return fmt.Sprintf("%s.addr.%s.%s", ipStr, serviceNode.Node.Datacenter, respDomain) } +// Craft dns records for a an A record for an IP address func makeARecord(qType uint16, ip net.IP, ttl time.Duration) dns.RR { var ipRecord dns.RR @@ -1769,14 +1813,15 @@ func makeARecord(qType uint16, ip net.IP, ttl time.Duration) dns.RR { // Craft dns records for a node // In case of an SRV query the answer will be a IN SRV and additional data will store an IN A to the node IP // Otherwise it will return a IN A record -func (d *DNSServer) makeRecordFromNode(node *structs.Node, qType uint16, qName string, ttl time.Duration, maxRecursionLevel int) []dns.RR { - addrTranslate := TranslateAddressAcceptDomain +func (d *DNSServer) makeRecordFromNode(node *structs.Node, qType uint16, qName string, cfg *dnsRequestConfig, maxRecursionLevel int) []dns.RR { + ttl := cfg.NodeTTL + addrTranslate := dnsutil.TranslateAddressAcceptDomain if qType == dns.TypeA { - addrTranslate |= TranslateAddressAcceptIPv4 + addrTranslate |= dnsutil.TranslateAddressAcceptIPv4 } else if qType == dns.TypeAAAA { - addrTranslate |= TranslateAddressAcceptIPv6 + addrTranslate |= dnsutil.TranslateAddressAcceptIPv6 } else { - addrTranslate |= TranslateAddressAcceptAny + addrTranslate |= dnsutil.TranslateAddressAcceptAny } addr := d.agent.TranslateAddress(node.Datacenter, node.Address, node.TaggedAddresses, addrTranslate) @@ -1796,7 +1841,7 @@ func (d *DNSServer) makeRecordFromNode(node *structs.Node, qType uint16, qName s }) res = append(res, - d.resolveCNAME(d.config.Load().(*dnsConfig), dns.Fqdn(node.Address), maxRecursionLevel)..., + d.resolveCNAME(cfg, dns.Fqdn(node.Address), maxRecursionLevel)..., ) return res @@ -1823,7 +1868,7 @@ func (d *DNSServer) makeRecordFromServiceNode(lookup serviceLookup, serviceNode if q.Qtype == dns.TypeSRV { respDomain := d.getResponseDomain(q.Name) - nodeFQDN := nodeCanonicalDNSName(lookup, serviceNode.Node.Node, respDomain) + nodeFQDN := nodeCanonicalDNSName(serviceNode.Node, respDomain) answers := []dns.RR{ &dns.SRV{ Hdr: dns.RR_Header{ @@ -1858,7 +1903,7 @@ func (d *DNSServer) makeRecordFromIP(lookup serviceLookup, addr net.IP, serviceN } if q.Qtype == dns.TypeSRV { - ipFQDN := d.encodeIPAsFqdn(q.Name, lookup, addr) + ipFQDN := d.encodeIPAsFqdn(q.Name, serviceNode, addr) answers := []dns.RR{ &dns.SRV{ Hdr: dns.RR_Header{ @@ -1885,7 +1930,7 @@ func (d *DNSServer) makeRecordFromIP(lookup serviceLookup, addr net.IP, serviceN // Craft dns records for an FQDN // In case of an SRV query the answer will be a IN SRV and additional data will store an IN A to the IP // Otherwise it will return a CNAME and a IN A record -func (d *DNSServer) makeRecordFromFQDN(lookup serviceLookup, fqdn string, serviceNode structs.CheckServiceNode, req *dns.Msg, ttl time.Duration, cfg *dnsConfig, maxRecursionLevel int) ([]dns.RR, []dns.RR) { +func (d *DNSServer) makeRecordFromFQDN(lookup serviceLookup, fqdn string, serviceNode structs.CheckServiceNode, req *dns.Msg, ttl time.Duration, cfg *dnsRequestConfig, maxRecursionLevel int) ([]dns.RR, []dns.RR) { edns := req.IsEdns0() != nil q := req.Question[0] @@ -1940,14 +1985,15 @@ MORE_REC: return answers, nil } -func (d *DNSServer) nodeServiceRecords(lookup serviceLookup, node structs.CheckServiceNode, req *dns.Msg, ttl time.Duration, cfg *dnsConfig, maxRecursionLevel int) ([]dns.RR, []dns.RR) { - addrTranslate := TranslateAddressAcceptDomain +// Craft dns records from a CheckServiceNode struct +func (d *DNSServer) makeNodeServiceRecords(lookup serviceLookup, node structs.CheckServiceNode, req *dns.Msg, ttl time.Duration, cfg *dnsRequestConfig, maxRecursionLevel int) ([]dns.RR, []dns.RR) { + addrTranslate := dnsutil.TranslateAddressAcceptDomain if req.Question[0].Qtype == dns.TypeA { - addrTranslate |= TranslateAddressAcceptIPv4 + addrTranslate |= dnsutil.TranslateAddressAcceptIPv4 } else if req.Question[0].Qtype == dns.TypeAAAA { - addrTranslate |= TranslateAddressAcceptIPv6 + addrTranslate |= dnsutil.TranslateAddressAcceptIPv6 } else { - addrTranslate |= TranslateAddressAcceptAny + addrTranslate |= dnsutil.TranslateAddressAcceptAny } // The datacenter should be empty during translation if it is a peering lookup. @@ -1991,7 +2037,8 @@ func (d *DNSServer) nodeServiceRecords(lookup serviceLookup, node structs.CheckS return d.makeRecordFromFQDN(lookup, serviceAddr, node, req, ttl, cfg, maxRecursionLevel) } -func (d *DNSServer) generateMeta(qName string, node *structs.Node, ttl time.Duration) []dns.RR { +// Craft dns records for TXT from a node's metadata +func (d *DNSServer) makeTXTRecordFromNodeMeta(qName string, node *structs.Node, ttl time.Duration) []dns.RR { extra := make([]dns.RR, 0, len(node.Meta)) for key, value := range node.Meta { txt := value @@ -2012,8 +2059,8 @@ func (d *DNSServer) generateMeta(qName string, node *structs.Node, ttl time.Dura return extra } -// serviceARecords is used to add the SRV records for a service lookup -func (d *DNSServer) serviceSRVRecords(cfg *dnsConfig, lookup serviceLookup, nodes structs.CheckServiceNodes, req, resp *dns.Msg, ttl time.Duration, maxRecursionLevel int) { +// addServiceSRVRecordsToMessage is used to add the SRV records for a service lookup +func (d *DNSServer) addServiceSRVRecordsToMessage(cfg *dnsRequestConfig, lookup serviceLookup, nodes structs.CheckServiceNodes, req, resp *dns.Msg, ttl time.Duration, maxRecursionLevel int) { handled := make(map[string]struct{}) for _, node := range nodes { @@ -2022,7 +2069,7 @@ func (d *DNSServer) serviceSRVRecords(cfg *dnsConfig, lookup serviceLookup, node // The datacenter should be empty during translation if it is a peering lookup. // This should be fine because we should always prefer the WAN address. - serviceAddress := d.agent.TranslateServiceAddress(lookup.Datacenter, node.Service.Address, node.Service.TaggedAddresses, TranslateAddressAcceptAny) + serviceAddress := d.agent.TranslateServiceAddress(lookup.Datacenter, node.Service.Address, node.Service.TaggedAddresses, dnsutil.TranslateAddressAcceptAny) servicePort := d.agent.TranslateServicePort(lookup.Datacenter, node.Service.Port, node.Service.TaggedAddresses) tuple := fmt.Sprintf("%s:%s:%d", node.Node.Node, serviceAddress, servicePort) if _, ok := handled[tuple]; ok { @@ -2030,21 +2077,21 @@ func (d *DNSServer) serviceSRVRecords(cfg *dnsConfig, lookup serviceLookup, node } handled[tuple] = struct{}{} - answers, extra := d.nodeServiceRecords(lookup, node, req, ttl, cfg, maxRecursionLevel) + answers, extra := d.makeNodeServiceRecords(lookup, node, req, ttl, cfg, maxRecursionLevel) respDomain := d.getResponseDomain(req.Question[0].Name) resp.Answer = append(resp.Answer, answers...) resp.Extra = append(resp.Extra, extra...) if cfg.NodeMetaTXT { - resp.Extra = append(resp.Extra, d.generateMeta(nodeCanonicalDNSName(lookup, node.Node.Node, respDomain), node.Node, ttl)...) + resp.Extra = append(resp.Extra, d.makeTXTRecordFromNodeMeta(nodeCanonicalDNSName(node.Node, respDomain), node.Node, ttl)...) } } } // handleRecurse is used to handle recursive DNS queries func (d *DNSServer) handleRecurse(resp dns.ResponseWriter, req *dns.Msg) { - cfg := d.config.Load().(*dnsConfig) + cfg := d.getRequestConfig(resp) q := req.Question[0] network := "udp" @@ -2120,7 +2167,7 @@ func (d *DNSServer) handleRecurse(resp dns.ResponseWriter, req *dns.Msg) { } // resolveCNAME is used to recursively resolve CNAME records -func (d *DNSServer) resolveCNAME(cfg *dnsConfig, name string, maxRecursionLevel int) []dns.RR { +func (d *DNSServer) resolveCNAME(cfg *dnsRequestConfig, name string, maxRecursionLevel int) []dns.RR { // If the CNAME record points to a Consul address, resolve it internally // Convert query to lowercase because DNS is case insensitive; d.domain and // d.altDomain are already converted @@ -2135,7 +2182,7 @@ func (d *DNSServer) resolveCNAME(cfg *dnsConfig, name string, maxRecursionLevel req.SetQuestion(name, dns.TypeANY) // TODO: handle error response - d.dispatch(nil, req, resp, maxRecursionLevel-1) + d.dispatch(nil, req, resp, cfg, maxRecursionLevel-1) return resp.Answer } @@ -2173,10 +2220,46 @@ func (d *DNSServer) resolveCNAME(cfg *dnsConfig, name string, maxRecursionLevel return nil } -func (d *DNSServer) coalesceDNSToken() string { +// coalesceDNSToken returns the ACL token to use for DNS queries. +// It returns the first token found in the following order: +// 1. The token from the request, if available. +// 2. The DNSToken from the agent. +// 3. The UserToken from the agent. +func (d *DNSServer) coalesceDNSToken(requestToken string) string { + // if the request token is set, which occurs when consul-dataplane forwards requests over gRPC, use it + if requestToken != "" { + return requestToken + } if d.agent.tokens.DNSToken() != "" { return d.agent.tokens.DNSToken() - } else { - return d.agent.tokens.UserToken() } + return d.agent.tokens.UserToken() +} + +// getRequestConfig returns the DNS request configuration that encapsulates: +// - the DNS server configuration. +// - the token from the request, if available. +// - the enterprise meta from the request, if available. +func (d *DNSServer) getRequestConfig(resp dns.ResponseWriter) *dnsRequestConfig { + dnsServerConfig := d.config.Load().(*dnsServerConfig) + requestDnsConfig := &dnsRequestConfig{ + dnsServerConfig: dnsServerConfig, + defaultEnterpriseMeta: d.defaultEnterpriseMeta, + } + + // DNS uses *dns.ServeMux, which takes a ResponseWriter interface and a DNS message both + // from the github.com/miekg/dns module, so we are limited in what we can pass as arguments. + // We can't pass a context.Context, so we have to add the RequestContext field to our + // implementation of dns.ResponseWriter to pass the context from the request. + if rw, ok := resp.(*agentdns.BufferResponseWriter); ok { + // use the ACL token from the request if available. Regular DNS hitting the + // agent will not carry a token, but gRPC requests from consul-dataplane will. + if rw.RequestContext.Token != "" { + requestDnsConfig.token = rw.RequestContext.Token + } + + d.setEnterpriseMetaFromRequestContext(rw.RequestContext, requestDnsConfig) + } + + return requestDnsConfig } diff --git a/agent/dns/buffer_response_writer.go b/agent/dns/buffer_response_writer.go new file mode 100644 index 000000000000..ed240758bea5 --- /dev/null +++ b/agent/dns/buffer_response_writer.go @@ -0,0 +1,78 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dns + +import ( + "github.com/hashicorp/go-hclog" + "github.com/miekg/dns" + "net" +) + +// BufferResponseWriter writes a DNS response to a byte buffer. +type BufferResponseWriter struct { + // responseBuffer is the buffer that the response is written to. + responseBuffer []byte + // RequestContext is the context of the request that carries the ACL token and tenancy of the request. + RequestContext Context + // LocalAddress is the address of the server. + LocalAddress net.Addr + // RemoteAddress is the address of the client that sent the request. + RemoteAddress net.Addr + // Logger is the logger for the response writer. + Logger hclog.Logger +} + +var _ dns.ResponseWriter = (*BufferResponseWriter)(nil) + +// ResponseBuffer returns the buffer containing the response. +func (b *BufferResponseWriter) ResponseBuffer() []byte { + return b.responseBuffer +} + +// LocalAddr returns the net.Addr of the server +func (b *BufferResponseWriter) LocalAddr() net.Addr { + return b.LocalAddress +} + +// RemoteAddr returns the net.Addr of the client that sent the current request. +func (b *BufferResponseWriter) RemoteAddr() net.Addr { + return b.RemoteAddress +} + +// WriteMsg writes a reply back to the client. +func (b *BufferResponseWriter) WriteMsg(m *dns.Msg) error { + // Pack message to bytes first. + msgBytes, err := m.Pack() + if err != nil { + b.Logger.Error("error packing message", "err", err) + return err + } + b.responseBuffer = msgBytes + return nil +} + +// Write writes a raw buffer back to the client. +func (b *BufferResponseWriter) Write(m []byte) (int, error) { + b.Logger.Trace("Write was called") + return copy(b.responseBuffer, m), nil +} + +// Close closes the connection. +func (b *BufferResponseWriter) Close() error { + // There's nothing for us to do here as we don't handle the connection. + return nil +} + +// TsigStatus returns the status of the Tsig. +func (b *BufferResponseWriter) TsigStatus() error { + // TSIG doesn't apply to this response writer. + return nil +} + +// TsigTimersOnly sets the tsig timers only boolean. +func (b *BufferResponseWriter) TsigTimersOnly(bool) {} + +// Hijack lets the caller take over the connection. +// After a call to Hijack(), the DNS package will not do anything with the connection. { +func (b *BufferResponseWriter) Hijack() {} diff --git a/agent/dns/context.go b/agent/dns/context.go new file mode 100644 index 000000000000..2054d6316a91 --- /dev/null +++ b/agent/dns/context.go @@ -0,0 +1,56 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dns + +import ( + "context" + "fmt" + + "github.com/mitchellh/mapstructure" + "google.golang.org/grpc/metadata" +) + +// Context is used augment a DNS message with Consul-specific metadata. +type Context struct { + Token string `mapstructure:"x-consul-token,omitempty"` + DefaultNamespace string `mapstructure:"x-consul-namespace,omitempty"` + DefaultPartition string `mapstructure:"x-consul-partition,omitempty"` +} + +// NewContextFromGRPCContext returns the request context using the gRPC metadata attached to the +// given context. If there is no gRPC metadata, it returns an empty context. +func NewContextFromGRPCContext(ctx context.Context) (Context, error) { + if ctx == nil { + return Context{}, nil + } + + reqCtx := Context{} + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return reqCtx, nil + } + + m := map[string]string{} + for k, v := range md { + m[k] = v[0] + } + + decoderConfig := &mapstructure.DecoderConfig{ + Metadata: nil, + Result: &reqCtx, + WeaklyTypedInput: true, + } + + decoder, err := mapstructure.NewDecoder(decoderConfig) + if err != nil { + return Context{}, fmt.Errorf("error creating mapstructure decoder: %w", err) + } + + err = decoder.Decode(m) + if err != nil { + return Context{}, fmt.Errorf("error decoding metadata: %w", err) + } + + return reqCtx, nil +} diff --git a/agent/dns/context_test.go b/agent/dns/context_test.go new file mode 100644 index 000000000000..44ad9055d060 --- /dev/null +++ b/agent/dns/context_test.go @@ -0,0 +1,70 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dns + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/grpc/metadata" +) + +func TestNewContextFromGRPCContext(t *testing.T) { + t.Parallel() + + md := metadata.MD{} + testMeta := map[string]string{ + "x-consul-token": "test-token", + "x-consul-namespace": "test-namespace", + "x-consul-partition": "test-partition", + } + + for k, v := range testMeta { + md.Set(k, v) + } + testGRPCContext := metadata.NewIncomingContext(context.Background(), md) + + testCases := []struct { + name string + grpcCtx context.Context + expected *Context + error error + }{ + { + name: "nil grpc context", + grpcCtx: nil, + expected: &Context{}, + }, + { + name: "grpc context w/o metadata", + grpcCtx: context.Background(), + expected: &Context{}, + }, + { + name: "grpc context w/ kitchen sink", + grpcCtx: testGRPCContext, + expected: &Context{ + Token: "test-token", + DefaultNamespace: "test-namespace", + DefaultPartition: "test-partition", + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + ctx, err := NewContextFromGRPCContext(tc.grpcCtx) + if tc.error != nil { + require.Error(t, err) + require.Equal(t, Context{}, &ctx) + require.Equal(t, tc.error, err) + return + } + + require.NotNil(t, ctx) + require.Equal(t, tc.expected, &ctx) + }) + } +} diff --git a/agent/dns/dns.go b/agent/dns/dns.go deleted file mode 100644 index 1942a1fdd8d2..000000000000 --- a/agent/dns/dns.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package dns - -import ( - "math/rand" - "regexp" -) - -// MaxLabelLength is the maximum length for a name that can be used in DNS. -const MaxLabelLength = 63 - -// InvalidNameRe is a regex that matches characters which can not be included in -// a DNS name. -var InvalidNameRe = regexp.MustCompile(`[^A-Za-z0-9\\-]+`) - -type RecursorStrategy string - -const ( - RecursorStrategySequential RecursorStrategy = "sequential" - RecursorStrategyRandom RecursorStrategy = "random" -) - -func (s RecursorStrategy) Indexes(max int) []int { - switch s { - case RecursorStrategyRandom: - return rand.Perm(max) - default: - idxs := make([]int, max) - for i := range idxs { - idxs[i] = i - } - return idxs - - } -} diff --git a/agent/dns/dns_test.go b/agent/dns/dns_test.go deleted file mode 100644 index 3acd2260e0a7..000000000000 --- a/agent/dns/dns_test.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package dns - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/sdk/testutil/retry" -) - -func TestDNS_Recursor_StrategyRandom(t *testing.T) { - configuredRecursors := []string{"1.1.1.1", "8.8.4.4", "8.8.8.8"} - recursorStrategy := RecursorStrategy("random") - - retry.RunWith(&retry.Counter{Count: 5}, t, func(r *retry.R) { - recursorsToQuery := make([]string, 0) - for _, idx := range recursorStrategy.Indexes(len(configuredRecursors)) { - recursorsToQuery = append(recursorsToQuery, configuredRecursors[idx]) - } - - // Ensure the slices contain the same elements - require.ElementsMatch(r, configuredRecursors, recursorsToQuery) - - // Ensure the elements are not in the same order - require.NotEqual(r, configuredRecursors, recursorsToQuery) - }) -} - -func TestDNS_Recursor_StrategySequential(t *testing.T) { - expectedRecursors := []string{"1.1.1.1", "8.8.4.4", "8.8.8.8"} - recursorStrategy := RecursorStrategy("sequential") - - recursorsToQuery := make([]string, 0) - for _, idx := range recursorStrategy.Indexes(len(expectedRecursors)) { - recursorsToQuery = append(recursorsToQuery, expectedRecursors[idx]) - } - - // The list of recursors should match the order in which they were defined - // in the configuration - require.Equal(t, recursorsToQuery, expectedRecursors) -} diff --git a/agent/dns/validation.go b/agent/dns/validation.go deleted file mode 100644 index a88aaff2dbcb..000000000000 --- a/agent/dns/validation.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package dns - -import ( - "errors" - "regexp" -) - -// matches valid DNS labels according to RFC 1123, should be at most 63 -// characters according to the RFC -var validLabel = regexp.MustCompile(`^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?$`) - -// IsValidLabel returns true if the string given is a valid DNS label (RFC 1123). -// Note: the only difference between RFC 1035 and RFC 1123 labels is that in -// RFC 1123 labels can begin with a number. -func IsValidLabel(name string) bool { - return validLabel.MatchString(name) -} - -// ValidateLabel is similar to IsValidLabel except it returns an error -// instead of false when name is not a valid DNS label. The error will contain -// reference to what constitutes a valid DNS label. -func ValidateLabel(name string) error { - if !IsValidLabel(name) { - return errors.New("a valid DNS label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character") - } - return nil -} diff --git a/agent/dns/validation_test.go b/agent/dns/validation_test.go deleted file mode 100644 index 8855e375c5f9..000000000000 --- a/agent/dns/validation_test.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package dns_test - -import ( - "testing" - - "github.com/hashicorp/consul/agent/dns" - "github.com/stretchr/testify/require" -) - -func TestValidLabel(t *testing.T) { - cases := map[string]bool{ - "CrEaTeD": true, - "created": true, - "create-deleted": true, - "foo": true, - "": false, - "_foo_": false, - "-foo": false, - "foo-": false, - "-foo-": false, - "-foo-bar-": false, - "no spaces allowed": false, - "thisvaluecontainsalotofcharactersbutnottoomanyandthecaseisatrue": true, // 63 chars - "thisvaluecontainstoomanycharactersandisthusinvalidandtestisfalse": false, // 64 chars - } - - t.Run("*", func(t *testing.T) { - t.Run("IsValidLabel", func(t *testing.T) { - require.False(t, dns.IsValidLabel("*")) - }) - t.Run("ValidateLabel", func(t *testing.T) { - require.Error(t, dns.ValidateLabel("*")) - }) - }) - - for name, expect := range cases { - t.Run(name, func(t *testing.T) { - t.Run("IsValidDNSLabel", func(t *testing.T) { - require.Equal(t, expect, dns.IsValidLabel(name)) - }) - t.Run("ValidateLabel", func(t *testing.T) { - if expect { - require.NoError(t, dns.ValidateLabel(name)) - } else { - require.Error(t, dns.ValidateLabel(name)) - } - }) - }) - } -} diff --git a/agent/dns_ce.go b/agent/dns_ce.go index bc6216e30a42..03595cb5bd18 100644 --- a/agent/dns_ce.go +++ b/agent/dns_ce.go @@ -10,8 +10,14 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/config" + agentdns "github.com/hashicorp/consul/agent/dns" + "github.com/hashicorp/consul/agent/structs" ) +// NOTE: these functions have also been copied to agent/dns package for dns v2. +// If you change these functions, please also change the ones in agent/dns as well. +// These v1 versions will soon be deprecated. + type enterpriseDNSConfig struct{} func getEnterpriseDNSConfig(conf *config.RuntimeConfig) enterpriseDNSConfig { @@ -21,9 +27,9 @@ func getEnterpriseDNSConfig(conf *config.RuntimeConfig) enterpriseDNSConfig { // parseLocality can parse peer name or datacenter from a DNS query's labels. // Peer name is parsed from the same query part that datacenter is, so given this ambiguity // we parse a "peerOrDatacenter". The caller or RPC handler are responsible for disambiguating. -func (d *DNSServer) parseLocality(labels []string, cfg *dnsConfig) (queryLocality, bool) { +func (d *DNSServer) parseLocality(labels []string, cfg *dnsRequestConfig) (queryLocality, bool) { locality := queryLocality{ - EnterpriseMeta: d.defaultEnterpriseMeta, + EnterpriseMeta: cfg.defaultEnterpriseMeta, } switch len(labels) { @@ -47,7 +53,10 @@ func (d *DNSServer) parseLocality(labels []string, cfg *dnsConfig) (queryLocalit } return locality, true case 1: - return queryLocality{peerOrDatacenter: labels[0]}, true + return queryLocality{ + peerOrDatacenter: labels[0], + EnterpriseMeta: cfg.defaultEnterpriseMeta, + }, true case 0: return queryLocality{}, true @@ -59,27 +68,35 @@ func (d *DNSServer) parseLocality(labels []string, cfg *dnsConfig) (queryLocalit type querySameness struct{} // parseSamenessGroupLocality wraps parseLocality in CE -func (d *DNSServer) parseSamenessGroupLocality(cfg *dnsConfig, labels []string, errfnc func() error) ([]queryLocality, error) { +func (d *DNSServer) parseSamenessGroupLocality(cfg *dnsRequestConfig, labels []string, errfnc func() error) (queryLocality, error) { locality, ok := d.parseLocality(labels, cfg) if !ok { - return nil, errfnc() + return queryLocality{ + EnterpriseMeta: cfg.defaultEnterpriseMeta, + }, errfnc() } - return []queryLocality{locality}, nil + return locality, nil } func serviceCanonicalDNSName(name, kind, datacenter, domain string, _ *acl.EnterpriseMeta) string { return fmt.Sprintf("%s.%s.%s.%s", name, kind, datacenter, domain) } -func nodeCanonicalDNSName(lookup serviceLookup, nodeName, respDomain string) string { - if lookup.PeerName != "" { +func nodeCanonicalDNSName(node *structs.Node, respDomain string) string { + if node.PeerName != "" { // We must return a more-specific DNS name for peering so // that there is no ambiguity with lookups. return fmt.Sprintf("%s.node.%s.peer.%s", - nodeName, - lookup.PeerName, + node.Node, + node.PeerName, respDomain) } // Return a simpler format for non-peering nodes. - return fmt.Sprintf("%s.node.%s.%s", nodeName, lookup.Datacenter, respDomain) + return fmt.Sprintf("%s.node.%s.%s", node.Node, node.Datacenter, respDomain) +} + +// setEnterpriseMetaFromRequestContext sets the DefaultNamespace and DefaultPartition on the requestDnsConfig +// based on the requestContext's DefaultNamespace and DefaultPartition. +func (d *DNSServer) setEnterpriseMetaFromRequestContext(requestContext agentdns.Context, requestDnsConfig *dnsRequestConfig) { + // do nothing } diff --git a/agent/dns_ce_test.go b/agent/dns_ce_test.go index 976b7e7ebe54..6787c42577dc 100644 --- a/agent/dns_ce_test.go +++ b/agent/dns_ce_test.go @@ -22,7 +22,7 @@ func TestDNS_CE_PeeredServices(t *testing.T) { t.Skip("too slow for testing.Short") } - a := StartTestAgent(t, TestAgent{HCL: ``, Overrides: `peering = { test_allow_peer_registrations = true }`}) + a := StartTestAgent(t, TestAgent{HCL: ``, Overrides: `peering = { test_allow_peer_registrations = true } `}) defer a.Shutdown() testrpc.WaitForTestAgent(t, a.RPC, "dc1") @@ -129,3 +129,53 @@ func TestDNS_CE_PeeredServices(t *testing.T) { assertARec(t, q.Answer[0], "web-proxy.service.peer1.peer.consul.", "199.0.0.1") }) } + +func getTestCasesParseLocality() []testCaseParseLocality { + testCases := []testCaseParseLocality{ + { + name: "test [..dc]", + labels: []string{"test-dc", "dc"}, + enterpriseDNSConfig: enterpriseDNSConfig{}, + expectedResult: queryLocality{ + EnterpriseMeta: acl.EnterpriseMeta{}, + datacenter: "test-dc", + }, + expectedOK: true, + }, + { + name: "test [..peer]", + labels: []string{"test-peer", "peer"}, + enterpriseDNSConfig: enterpriseDNSConfig{}, + expectedResult: queryLocality{ + EnterpriseMeta: acl.EnterpriseMeta{}, + peer: "test-peer", + }, + expectedOK: true, + }, + { + name: "test 1 label", + labels: []string{"test-peer"}, + enterpriseDNSConfig: enterpriseDNSConfig{}, + expectedResult: queryLocality{ + EnterpriseMeta: acl.EnterpriseMeta{}, + peerOrDatacenter: "test-peer", + }, + expectedOK: true, + }, + { + name: "test 0 labels", + labels: []string{}, + enterpriseDNSConfig: enterpriseDNSConfig{}, + expectedResult: queryLocality{}, + expectedOK: true, + }, + { + name: "test 3 labels returns not found", + labels: []string{"test-dc", "dc", "test-blah"}, + enterpriseDNSConfig: enterpriseDNSConfig{}, + expectedResult: queryLocality{}, + expectedOK: false, + }, + } + return testCases +} diff --git a/agent/dns_node_lookup_test.go b/agent/dns_node_lookup_test.go new file mode 100644 index 000000000000..e66fca99abaa --- /dev/null +++ b/agent/dns_node_lookup_test.go @@ -0,0 +1,660 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package agent + +import ( + "context" + "testing" + + "github.com/miekg/dns" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/testrpc" +) + +func TestDNS_NodeLookup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + TaggedAddresses: map[string]string{ + "wan": "127.0.0.2", + }, + NodeMeta: map[string]string{ + "key": "value", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("foo.node.consul.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + require.Len(t, in.Answer, 2) + require.Len(t, in.Extra, 0) + + aRec, ok := in.Answer[0].(*dns.A) + require.True(t, ok, "First answer is not an A record") + require.Equal(t, "127.0.0.1", aRec.A.String()) + require.Equal(t, uint32(0), aRec.Hdr.Ttl) + + txt, ok := in.Answer[1].(*dns.TXT) + require.True(t, ok, "Second answer is not a TXT record") + require.Len(t, txt.Txt, 1) + require.Equal(t, "key=value", txt.Txt[0]) + + // Re-do the query, but only for an A RR + + m = new(dns.Msg) + m.SetQuestion("foo.node.consul.", dns.TypeA) + + c = new(dns.Client) + in, _, err = c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + require.Len(t, in.Answer, 1) + require.Len(t, in.Extra, 1) + + aRec, ok = in.Answer[0].(*dns.A) + require.True(t, ok, "Answer is not an A record") + require.Equal(t, "127.0.0.1", aRec.A.String()) + require.Equal(t, uint32(0), aRec.Hdr.Ttl) + + txt, ok = in.Extra[0].(*dns.TXT) + require.True(t, ok, "Extra record is not a TXT record") + require.Len(t, txt.Txt, 1) + require.Equal(t, "key=value", txt.Txt[0]) + + // Re-do the query, but specify the DC + m = new(dns.Msg) + m.SetQuestion("foo.node.dc1.consul.", dns.TypeANY) + + c = new(dns.Client) + in, _, err = c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + require.Len(t, in.Answer, 2) + require.Len(t, in.Extra, 0) + + aRec, ok = in.Answer[0].(*dns.A) + require.True(t, ok, "First answer is not an A record") + require.Equal(t, "127.0.0.1", aRec.A.String()) + require.Equal(t, uint32(0), aRec.Hdr.Ttl) + + _, ok = in.Answer[1].(*dns.TXT) + require.True(t, ok, "Second answer is not a TXT record") + + // lookup a non-existing node, we should receive a SOA + m = new(dns.Msg) + m.SetQuestion("nofoo.node.dc1.consul.", dns.TypeANY) + + c = new(dns.Client) + in, _, err = c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + require.Len(t, in.Ns, 1) + soaRec, ok := in.Ns[0].(*dns.SOA) + require.True(t, ok, "NS RR is not a SOA record") + require.Equal(t, uint32(0), soaRec.Hdr.Ttl) +} + +func TestDNS_NodeLookup_CaseInsensitive(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "Foo", + Address: "127.0.0.1", + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("fOO.node.dc1.consul.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("empty lookup: %#v", in) + } +} + +// V2 DNS does not support node names with a period. This will be deprecated. +func TestDNS_NodeLookup_PeriodName(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node with period in name + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo.bar", + Address: "127.0.0.1", + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("foo.bar.node.consul.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + aRec, ok := in.Answer[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if aRec.A.String() != "127.0.0.1" { + t.Fatalf("Bad: %#v", in.Answer[0]) + } +} + +func TestDNS_NodeLookup_AAAA(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "::4242:4242", + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("bar.node.consul.", dns.TypeAAAA) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + aRec, ok := in.Answer[0].(*dns.AAAA) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if aRec.AAAA.String() != "::4242:4242" { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if aRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } +} + +func TestDNS_NodeLookup_CNAME(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + recursor := makeRecursor(t, dns.Msg{ + Answer: []dns.RR{ + dnsCNAME("www.google.com", "google.com"), + dnsA("google.com", "1.2.3.4"), + dnsTXT("google.com", []string{"my_txt_value"}), + }, + }) + defer recursor.Shutdown() + + a := NewTestAgent(t, ` + recursors = ["`+recursor.Addr+`"] + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "google", + Address: "www.google.com", + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("google.node.consul.", dns.TypeANY) + m.SetEdns0(8192, true) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + wantAnswer := []dns.RR{ + &dns.CNAME{ + Hdr: dns.RR_Header{Name: "google.node.consul.", Rrtype: dns.TypeCNAME, Class: dns.ClassINET, Ttl: 0, Rdlength: 0x10}, + Target: "www.google.com.", + }, + &dns.CNAME{ + Hdr: dns.RR_Header{Name: "www.google.com.", Rrtype: dns.TypeCNAME, Class: dns.ClassINET, Rdlength: 0x2}, + Target: "google.com.", + }, + &dns.A{ + Hdr: dns.RR_Header{Name: "google.com.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4}, + A: []byte{0x1, 0x2, 0x3, 0x4}, // 1.2.3.4 + }, + &dns.TXT{ + Hdr: dns.RR_Header{Name: "google.com.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Rdlength: 0xd}, + Txt: []string{"my_txt_value"}, + }, + } + require.Equal(t, wantAnswer, in.Answer) +} + +func TestDNS_NodeLookup_TXT(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "google", + Address: "127.0.0.1", + NodeMeta: map[string]string{ + "rfc1035-00": "value0", + "key0": "value1", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("google.node.consul.", dns.TypeTXT) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Should have the 1 TXT record reply + if len(in.Answer) != 2 { + t.Fatalf("Bad: %#v", in) + } + + txtRec, ok := in.Answer[0].(*dns.TXT) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if len(txtRec.Txt) != 1 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if txtRec.Txt[0] != "value0" && txtRec.Txt[0] != "key0=value1" { + t.Fatalf("Bad: %#v", in.Answer[0]) + } +} + +func TestDNS_NodeLookup_TXT_DontSuppress(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = false } `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "google", + Address: "127.0.0.1", + NodeMeta: map[string]string{ + "rfc1035-00": "value0", + "key0": "value1", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("google.node.consul.", dns.TypeTXT) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Should have the 1 TXT record reply + if len(in.Answer) != 2 { + t.Fatalf("Bad: %#v", in) + } + + txtRec, ok := in.Answer[0].(*dns.TXT) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if len(txtRec.Txt) != 1 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if txtRec.Txt[0] != "value0" && txtRec.Txt[0] != "key0=value1" { + t.Fatalf("Bad: %#v", in.Answer[0]) + } +} + +func TestDNS_NodeLookup_ANY(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "127.0.0.1", + NodeMeta: map[string]string{ + "key": "value", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("bar.node.consul.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + wantAnswer := []dns.RR{ + &dns.A{ + Hdr: dns.RR_Header{Name: "bar.node.consul.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4}, + A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1 + }, + &dns.TXT{ + Hdr: dns.RR_Header{Name: "bar.node.consul.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Rdlength: 0xa}, + Txt: []string{"key=value"}, + }, + } + require.Equal(t, wantAnswer, in.Answer) +} + +func TestDNS_NodeLookup_ANY_DontSuppressTXT(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = false } `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "127.0.0.1", + NodeMeta: map[string]string{ + "key": "value", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("bar.node.consul.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + wantAnswer := []dns.RR{ + &dns.A{ + Hdr: dns.RR_Header{Name: "bar.node.consul.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4}, + A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1 + }, + &dns.TXT{ + Hdr: dns.RR_Header{Name: "bar.node.consul.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Rdlength: 0xa}, + Txt: []string{"key=value"}, + }, + } + require.Equal(t, wantAnswer, in.Answer) +} + +func TestDNS_NodeLookup_A_SuppressTXT(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = false } `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "127.0.0.1", + NodeMeta: map[string]string{ + "key": "value", + }, + } + + var out struct{} + require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) + + m := new(dns.Msg) + m.SetQuestion("bar.node.consul.", dns.TypeA) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + + wantAnswer := []dns.RR{ + &dns.A{ + Hdr: dns.RR_Header{Name: "bar.node.consul.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4}, + A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1 + }, + } + require.Equal(t, wantAnswer, in.Answer) + + // ensure TXT RR suppression + require.Len(t, in.Extra, 0) +} + +func TestDNS_NodeLookup_TTL(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + recursor := makeRecursor(t, dns.Msg{ + Answer: []dns.RR{ + dnsCNAME("www.google.com", "google.com"), + dnsA("google.com", "1.2.3.4"), + }, + }) + defer recursor.Shutdown() + + a := NewTestAgent(t, ` + recursors = ["`+recursor.Addr+`"] + dns_config { + node_ttl = "10s" + allow_stale = true + max_stale = "1s" + } + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("foo.node.consul.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + aRec, ok := in.Answer[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if aRec.A.String() != "127.0.0.1" { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if aRec.Hdr.Ttl != 10 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + // Register node with IPv6 + args = &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "::4242:4242", + } + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + // Check an IPv6 record + m = new(dns.Msg) + m.SetQuestion("bar.node.consul.", dns.TypeANY) + + in, _, err = c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + aaaaRec, ok := in.Answer[0].(*dns.AAAA) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if aaaaRec.AAAA.String() != "::4242:4242" { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if aaaaRec.Hdr.Ttl != 10 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + // Register node with CNAME + args = &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "google", + Address: "www.google.com", + } + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m = new(dns.Msg) + m.SetQuestion("google.node.consul.", dns.TypeANY) + + in, _, err = c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Should have the CNAME record + a few A records + if len(in.Answer) < 2 { + t.Fatalf("Bad: %#v", in) + } + + cnRec, ok := in.Answer[0].(*dns.CNAME) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if cnRec.Target != "www.google.com." { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if cnRec.Hdr.Ttl != 10 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } +} diff --git a/agent/dns_reverse_lookup_test.go b/agent/dns_reverse_lookup_test.go new file mode 100644 index 000000000000..755921833b52 --- /dev/null +++ b/agent/dns_reverse_lookup_test.go @@ -0,0 +1,439 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package agent + +import ( + "context" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/testrpc" + "github.com/miekg/dns" + "github.com/stretchr/testify/require" + "testing" +) + +func TestDNS_ReverseLookup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo2", + Address: "127.0.0.2", + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("2.0.0.127.in-addr.arpa.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + ptrRec, ok := in.Answer[0].(*dns.PTR) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if ptrRec.Ptr != "foo2.node.dc1.consul." { + t.Fatalf("Bad: %#v", ptrRec) + } +} + +func TestDNS_ReverseLookup_CustomDomain(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, ` + domain = "custom" + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo2", + Address: "127.0.0.2", + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("2.0.0.127.in-addr.arpa.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + ptrRec, ok := in.Answer[0].(*dns.PTR) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if ptrRec.Ptr != "foo2.node.dc1.custom." { + t.Fatalf("Bad: %#v", ptrRec) + } +} + +func TestDNS_ReverseLookup_IPV6(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "::4242:4242", + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("2.4.2.4.2.4.2.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + ptrRec, ok := in.Answer[0].(*dns.PTR) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if ptrRec.Ptr != "bar.node.dc1.consul." { + t.Fatalf("Bad: %#v", ptrRec) + } +} + +func TestDNS_Compression_ReverseLookup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node. + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo2", + Address: "127.0.0.2", + } + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("2.0.0.127.in-addr.arpa.", dns.TypeANY) + + conn, err := dns.Dial("udp", a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Do a manual exchange with compression on (the default). + if err := conn.WriteMsg(m); err != nil { + t.Fatalf("err: %v", err) + } + p := make([]byte, dns.MaxMsgSize) + compressed, err := conn.Read(p) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Disable compression and try again. + a.DNSDisableCompression(true) + if err := conn.WriteMsg(m); err != nil { + t.Fatalf("err: %v", err) + } + unc, err := conn.Read(p) + if err != nil { + t.Fatalf("err: %v", err) + } + + // We can't see the compressed status given the DNS API, so we just make + // sure the message is smaller to see if it's respecting the flag. + if compressed == 0 || unc == 0 || compressed >= unc { + t.Fatalf("doesn't look compressed: %d vs. %d", compressed, unc) + } +} + +func TestDNS_ServiceReverseLookup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + Address: "127.0.0.2", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + m := new(dns.Msg) + m.SetQuestion("2.0.0.127.in-addr.arpa.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + ptrRec, ok := in.Answer[0].(*dns.PTR) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if ptrRec.Ptr != serviceCanonicalDNSName("db", "service", "dc1", "consul", nil)+"." { + t.Fatalf("Bad: %#v", ptrRec) + } +} + +func TestDNS_ServiceReverseLookup_IPV6(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "2001:db8::1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + Address: "2001:db8::ff00:42:8329", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + m := new(dns.Msg) + m.SetQuestion("9.2.3.8.2.4.0.0.0.0.f.f.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + ptrRec, ok := in.Answer[0].(*dns.PTR) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if ptrRec.Ptr != serviceCanonicalDNSName("db", "service", "dc1", "consul", nil)+"." { + t.Fatalf("Bad: %#v", ptrRec) + } +} + +func TestDNS_ServiceReverseLookup_CustomDomain(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, ` + domain = "custom" + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + Address: "127.0.0.2", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + m := new(dns.Msg) + m.SetQuestion("2.0.0.127.in-addr.arpa.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + ptrRec, ok := in.Answer[0].(*dns.PTR) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if ptrRec.Ptr != serviceCanonicalDNSName("db", "service", "dc1", "custom", nil)+"." { + t.Fatalf("Bad: %#v", ptrRec) + } +} + +func TestDNS_ServiceReverseLookupNodeAddress(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + Address: "127.0.0.1", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + m := new(dns.Msg) + m.SetQuestion("1.0.0.127.in-addr.arpa.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + ptrRec, ok := in.Answer[0].(*dns.PTR) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if ptrRec.Ptr != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", ptrRec) + } +} + +func TestDNS_ReverseLookup_NotFound(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + // do not configure recursors + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Do not register any nodes + m := new(dns.Msg) + qName := "2.0.0.127.in-addr.arpa." + m.SetQuestion(qName, dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + require.Nil(t, in.Answer) + require.Nil(t, in.Extra) + + require.Equal(t, dns.RcodeNameError, in.Rcode) + + question := in.Question[0] + require.Equal(t, qName, question.Name) + require.Equal(t, dns.TypeANY, question.Qtype) + require.Equal(t, uint16(dns.ClassINET), question.Qclass) + + soa, ok := in.Ns[0].(*dns.SOA) + require.True(t, ok) + require.Equal(t, "ns.consul.", soa.Ns) + require.Equal(t, "hostmaster.consul.", soa.Mbox) +} diff --git a/agent/dns_service_lookup_test.go b/agent/dns_service_lookup_test.go new file mode 100644 index 000000000000..34a48b75ba90 --- /dev/null +++ b/agent/dns_service_lookup_test.go @@ -0,0 +1,3852 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package agent + +import ( + "context" + "fmt" + "net" + "sort" + "strings" + "testing" + + "github.com/miekg/dns" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/sdk/testutil/retry" + "github.com/hashicorp/consul/testrpc" +) + +func TestDNS_ServiceLookupNoMultiCNAME(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "198.18.0.1", + Service: &structs.NodeService{ + Service: "db", + Port: 12345, + Address: "foo.node.consul", + }, + } + + var out struct{} + require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) + } + + // Register a second node node with the same service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "198.18.0.2", + Service: &structs.NodeService{ + Service: "db", + Port: 12345, + Address: "bar.node.consul", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + m := new(dns.Msg) + m.SetQuestion("db.service.consul.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + + // expect a CNAME and an A RR + require.Len(t, in.Answer, 2) + require.IsType(t, &dns.CNAME{}, in.Answer[0]) + require.IsType(t, &dns.A{}, in.Answer[1]) +} + +func TestDNS_ServiceLookupPreferNoCNAME(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "198.18.0.1", + Service: &structs.NodeService{ + Service: "db", + Port: 12345, + Address: "198.18.0.1", + }, + } + + var out struct{} + require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) + } + + // Register a second node node with the same service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "198.18.0.2", + Service: &structs.NodeService{ + Service: "db", + Port: 12345, + Address: "bar.node.consul", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + m := new(dns.Msg) + m.SetQuestion("db.service.consul.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + + // expect an A RR + require.Len(t, in.Answer, 1) + aRec, ok := in.Answer[0].(*dns.A) + require.Truef(t, ok, "Not an A RR") + + require.Equal(t, "db.service.consul.", aRec.Hdr.Name) + require.Equal(t, "198.18.0.1", aRec.A.String()) +} + +func TestDNS_ServiceLookupMultiAddrNoCNAME(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "198.18.0.1", + Service: &structs.NodeService{ + Service: "db", + Port: 12345, + Address: "198.18.0.1", + }, + } + + var out struct{} + require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) + } + + // Register a second node node with the same service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "198.18.0.2", + Service: &structs.NodeService{ + Service: "db", + Port: 12345, + Address: "bar.node.consul", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register a second node node with the same service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "baz", + Address: "198.18.0.3", + Service: &structs.NodeService{ + Service: "db", + Port: 12345, + Address: "198.18.0.3", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + m := new(dns.Msg) + m.SetQuestion("db.service.consul.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + + // expect two A RRs + require.Len(t, in.Answer, 2) + require.IsType(t, &dns.A{}, in.Answer[0]) + require.Equal(t, "db.service.consul.", in.Answer[0].Header().Name) + isOneOfTheseIPs := func(ip net.IP) bool { + if ip.Equal(net.ParseIP("198.18.0.1")) || ip.Equal(net.ParseIP("198.18.0.3")) { + return true + } + return false + } + require.True(t, isOneOfTheseIPs(in.Answer[0].(*dns.A).A)) + require.IsType(t, &dns.A{}, in.Answer[1]) + require.Equal(t, "db.service.consul.", in.Answer[1].Header().Name) + require.True(t, isOneOfTheseIPs(in.Answer[1].(*dns.A).A)) +} + +func TestDNS_ServiceLookup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + }, + DNS: structs.QueryDNSOptions{ + TTL: "3s", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []string{ + "db.service.consul.", + id + ".query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", srvRec) + } + + aRec, ok := in.Extra[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Name != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.A.String() != "127.0.0.1" { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + + if strings.Contains(question, "query") { + // The query should have the TTL associated with the query registration. + if srvRec.Hdr.Ttl != 3 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if aRec.Hdr.Ttl != 3 { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + } else { + if srvRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if aRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + } + + } + + // Lookup a non-existing service/query, we should receive an SOA. + questions = []string{ + "nodb.service.consul.", + "nope.query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Ns) != 1 { + t.Fatalf("Bad: %#v", in) + } + + soaRec, ok := in.Ns[0].(*dns.SOA) + if !ok { + t.Fatalf("Bad: %#v", in.Ns[0]) + } + if soaRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Ns[0]) + } + } +} + +// TestDNS_ServiceAddressWithTagLookup tests some specific cases that Nomad would exercise, +// Like registering a service w/o a Node. https://github.com/hashicorp/nomad/blob/1174019676ff3d65b39323eb0c7234fb1e09b80c/command/agent/consul/service_client.go#L1366-L1381 +// Errors with this were reported in https://github.com/hashicorp/consul/issues/21325#issuecomment-2166845574 +// Also we test that only one tag is valid in the URL. +func TestDNS_ServiceAddressWithTagLookup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + { + // This emulates a Nomad service registration. + // Using an internal RPC for Catalog.Register will not trigger the same condition. + err := a.Client().Agent().ServiceRegister(&api.AgentServiceRegistration{ + Kind: api.ServiceKindTypical, + ID: "db-1", + Name: "db", + Tags: []string{"primary"}, + Address: "127.0.0.1", + Port: 12345, + Checks: make([]*api.AgentServiceCheck, 0), + }) + require.NoError(t, err) + } + + { + err := a.Client().Agent().ServiceRegister(&api.AgentServiceRegistration{ + Kind: api.ServiceKindTypical, + ID: "db-2", + Name: "db", + Tags: []string{"secondary"}, + Address: "127.0.0.2", // The address here has to be different, or the DNS server will dedupe it. + Port: 12345, + Checks: make([]*api.AgentServiceCheck, 0), + }) + require.NoError(t, err) + } + + // Query the service using a tag - this also checks that we're filtering correctly + questions := []string{ + "_db._primary.service.dc1.consul.", // w/ RFC 2782 style syntax + "primary.db.service.dc1.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + require.Len(t, in.Answer, 1, "Expected only one result in the Answer section") + + srvRec, ok := in.Answer[0].(*dns.SRV) + require.True(t, ok, "Expected an SRV record in the Answer section") + require.Equal(t, uint16(12345), srvRec.Port) + require.Equal(t, "7f000001.addr.dc1.consul.", srvRec.Target) + + aRec, ok := in.Extra[0].(*dns.A) + require.True(t, ok, "Expected an A record in the Extra section") + require.Equal(t, "7f000001.addr.dc1.consul.", aRec.Hdr.Name) + require.Equal(t, "127.0.0.1", aRec.A.String()) + + if strings.Contains(question, "query") { + // The query should have the TTL associated with the query registration. + require.Equal(t, uint32(3), srvRec.Hdr.Ttl) + require.Equal(t, uint32(3), aRec.Hdr.Ttl) + } else { + require.Equal(t, uint32(0), srvRec.Hdr.Ttl) + require.Equal(t, uint32(0), aRec.Hdr.Ttl) + } + } + + // Multiple tags are not supported in the legacy DNS server + questions = []string{ + "banana._db._primary.service.dc1.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + require.Len(t, in.Answer, 0, "Expected no results in the Answer section") + + // We combine the tags with a period, which results in NXDOMAIN + // The reported issue says that v2dns this is returning valid results. + require.Equal(t, dns.RcodeNameError, in.Rcode) + } +} + +func TestDNS_ServiceLookupWithInternalServiceAddress(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, ` + node_name = "my.test-node" + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + // The service is using the consul DNS name as service address + // which triggers a lookup loop and a subsequent stack overflow + // crash. + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Address: "db.service.consul", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + // Looking up the service should not trigger a loop + m := new(dns.Msg) + m.SetQuestion("db.service.consul.", dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + wantAnswer := []dns.RR{ + &dns.SRV{ + Hdr: dns.RR_Header{Name: "db.service.consul.", Rrtype: 0x21, Class: 0x1, Rdlength: 0x1b}, + Priority: 0x1, + Weight: 0x1, + Port: 12345, + Target: "foo.node.dc1.consul.", + }, + } + require.Equal(t, wantAnswer, in.Answer, "answer") + wantExtra := []dns.RR{ + &dns.A{ + Hdr: dns.RR_Header{Name: "foo.node.dc1.consul.", Rrtype: 0x1, Class: 0x1, Rdlength: 0x4}, + A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1 + }, + } + require.Equal(t, wantExtra, in.Extra, "extra") +} + +func TestDNS_ConnectServiceLookup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register + { + args := structs.TestRegisterRequestProxy(t) + args.Address = "127.0.0.55" + args.Service.Proxy.DestinationServiceName = "db" + args.Service.Address = "" + args.Service.Port = 12345 + var out struct{} + require.Nil(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) + } + + // Look up the service + questions := []string{ + "db.connect.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.Nil(t, err) + require.Len(t, in.Answer, 1) + + srvRec, ok := in.Answer[0].(*dns.SRV) + require.True(t, ok) + require.Equal(t, uint16(12345), srvRec.Port) + require.Equal(t, "foo.node.dc1.consul.", srvRec.Target) + require.Equal(t, uint32(0), srvRec.Hdr.Ttl) + + cnameRec, ok := in.Extra[0].(*dns.A) + require.True(t, ok) + require.Equal(t, "foo.node.dc1.consul.", cnameRec.Hdr.Name) + require.Equal(t, uint32(0), srvRec.Hdr.Ttl) + require.Equal(t, "127.0.0.55", cnameRec.A.String()) + } + +} + +func TestDNS_IngressServiceLookup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register ingress-gateway service + { + args := structs.TestRegisterIngressGateway(t) + var out struct{} + require.Nil(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) + } + + // Register db service + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Address: "", + Port: 80, + }, + } + + var out struct{} + require.Nil(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) + } + + // Register proxy-defaults with 'http' protocol + { + req := structs.ConfigEntryRequest{ + Op: structs.ConfigEntryUpsert, + Datacenter: "dc1", + Entry: &structs.ProxyConfigEntry{ + Kind: structs.ProxyDefaults, + Name: structs.ProxyConfigGlobal, + Config: map[string]interface{}{ + "protocol": "http", + }, + }, + WriteRequest: structs.WriteRequest{Token: "root"}, + } + var out bool + require.Nil(t, a.RPC(context.Background(), "ConfigEntry.Apply", req, &out)) + require.True(t, out) + } + + // Register ingress-gateway config entry + { + args := &structs.IngressGatewayConfigEntry{ + Name: "ingress-gateway", + Kind: structs.IngressGateway, + Listeners: []structs.IngressListener{ + { + Port: 8888, + Protocol: "http", + Services: []structs.IngressService{ + {Name: "db"}, + {Name: "api"}, + }, + }, + }, + } + + req := structs.ConfigEntryRequest{ + Op: structs.ConfigEntryUpsert, + Datacenter: "dc1", + Entry: args, + } + var out bool + require.Nil(t, a.RPC(context.Background(), "ConfigEntry.Apply", req, &out)) + require.True(t, out) + } + + // Look up the service + questions := []string{ + "api.ingress.consul.", + "api.ingress.dc1.consul.", + "db.ingress.consul.", + "db.ingress.dc1.consul.", + } + for _, question := range questions { + t.Run(question, func(t *testing.T) { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeA) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.Nil(t, err) + require.Len(t, in.Answer, 1) + + cnameRec, ok := in.Answer[0].(*dns.A) + require.True(t, ok) + require.Equal(t, question, cnameRec.Hdr.Name) + require.Equal(t, uint32(0), cnameRec.Hdr.Ttl) + require.Equal(t, "127.0.0.1", cnameRec.A.String()) + }) + } +} + +func TestDNS_ExternalServiceLookup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with an external service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "www.google.com", + Service: &structs.NodeService{ + Service: "db", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service + questions := []string{ + "db.service.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 || len(in.Extra) > 0 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "www.google.com." { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + } +} + +func TestDNS_ExternalServiceToConsulCNAMELookup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, ` + domain = "CONSUL." + node_name = "test node" + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register the initial node with a service + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "web", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "web", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an external service pointing to the 'web' service + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "alias", + Address: "web.service.consul", + Service: &structs.NodeService{ + Service: "alias", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly + questions := []string{ + "alias.service.consul.", + "alias.service.CoNsUl.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "web.service.consul." { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + if len(in.Extra) != 1 { + t.Fatalf("Bad: %#v", in) + } + + aRec, ok := in.Extra[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Name != "web.service.consul." { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.A.String() != "127.0.0.1" { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + } + +} + +func TestDNS_ExternalServiceToConsulCNAMENestedLookup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, ` + node_name = "test-node" + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register the initial node with a service + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "web", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "web", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an external service pointing to the 'web' service + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "alias", + Address: "web.service.consul", + Service: &structs.NodeService{ + Service: "alias", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an external service pointing to the 'alias' service + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "alias2", + Address: "alias.service.consul", + Service: &structs.NodeService{ + Service: "alias2", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly + questions := []string{ + "alias2.service.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "alias.service.consul." { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if len(in.Extra) != 2 { + t.Fatalf("Bad: %#v", in) + } + + cnameRec, ok := in.Extra[0].(*dns.CNAME) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if cnameRec.Hdr.Name != "alias.service.consul." { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if cnameRec.Target != "web.service.consul." { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if cnameRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + + aRec, ok := in.Extra[1].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[1]) + } + if aRec.Hdr.Name != "web.service.consul." { + t.Fatalf("Bad: %#v", in.Extra[1]) + } + if aRec.A.String() != "127.0.0.1" { + t.Fatalf("Bad: %#v", in.Extra[1]) + } + if aRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Extra[1]) + } + } +} + +func TestDNS_ServiceLookup_ServiceAddress_A(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Address: "127.0.0.2", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []string{ + "db.service.consul.", + id + ".query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "7f000002.addr.dc1.consul." { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + aRec, ok := in.Extra[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Name != "7f000002.addr.dc1.consul." { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.A.String() != "127.0.0.2" { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + } + +} + +func TestDNS_AltDomain_ServiceLookup_ServiceAddress_A(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, ` + alt_domain = "test-domain" + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Address: "127.0.0.2", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []struct { + ask string + wantDomain string + }{ + {"db.service.consul.", "consul."}, + {id + ".query.consul.", "consul."}, + {"db.service.test-domain.", "test-domain."}, + {id + ".query.test-domain.", "test-domain."}, + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question.ask, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "7f000002.addr.dc1."+question.wantDomain { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + aRec, ok := in.Extra[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Name != "7f000002.addr.dc1."+question.wantDomain { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.A.String() != "127.0.0.2" { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + } +} + +func TestDNS_ServiceLookup_ServiceAddress_SRV(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + recursor := makeRecursor(t, dns.Msg{ + Answer: []dns.RR{ + dnsCNAME("www.google.com", "google.com"), + dnsA("google.com", "1.2.3.4"), + }, + }) + defer recursor.Shutdown() + + a := NewTestAgent(t, ` + recursors = ["`+recursor.Addr+`"] + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service whose address isn't an IP. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Address: "www.google.com", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + // Specify prepared query name containing "." to test + // since that is technically supported (though atypical). + var id string + preparedQueryName := "query.name.with.dots" + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: preparedQueryName, + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []string{ + "db.service.consul.", + id + ".query.consul.", + preparedQueryName + ".query.consul.", + fmt.Sprintf("_%s._tcp.query.consul.", id), + fmt.Sprintf("_%s._tcp.query.consul.", preparedQueryName), + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "www.google.com." { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + // Should have google CNAME + cnRec, ok := in.Extra[0].(*dns.CNAME) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if cnRec.Target != "google.com." { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + + // Check we recursively resolve + aRec, ok := in.Extra[1].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[1]) + } + if aRec.A.String() != "1.2.3.4" { + t.Fatalf("Bad: %s", aRec.A.String()) + } + } +} + +func TestDNS_ServiceLookup_ServiceAddressIPV6(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Address: "2607:20:4005:808::200e", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []string{ + "db.service.consul.", + id + ".query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "2607002040050808000000000000200e.addr.dc1.consul." { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + aRec, ok := in.Extra[0].(*dns.AAAA) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Name != "2607002040050808000000000000200e.addr.dc1.consul." { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.AAAA.String() != "2607:20:4005:808::200e" { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + } +} + +func TestDNS_AltDomain_ServiceLookup_ServiceAddressIPV6(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, ` + alt_domain = "test-domain" + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Address: "2607:20:4005:808::200e", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []struct { + ask string + want string + }{ + {"db.service.consul.", "2607002040050808000000000000200e.addr.dc1.consul."}, + {"db.service.test-domain.", "2607002040050808000000000000200e.addr.dc1.test-domain."}, + {id + ".query.consul.", "2607002040050808000000000000200e.addr.dc1.consul."}, + {id + ".query.test-domain.", "2607002040050808000000000000200e.addr.dc1.test-domain."}, + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question.ask, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != question.want { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + aRec, ok := in.Extra[0].(*dns.AAAA) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Name != question.want { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.AAAA.String() != "2607:20:4005:808::200e" { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + } +} + +func TestDNS_ServiceLookup_WanTranslation(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a1 := NewTestAgent(t, ` + datacenter = "dc1" + translate_wan_addrs = true + acl_datacenter = "" + `) + defer a1.Shutdown() + + a2 := NewTestAgent(t, ` + datacenter = "dc2" + translate_wan_addrs = true + acl_datacenter = "" + `) + defer a2.Shutdown() + + // Join WAN cluster + addr := fmt.Sprintf("127.0.0.1:%d", a1.Config.SerfPortWAN) + _, err := a2.JoinWAN([]string{addr}) + require.NoError(t, err) + retry.Run(t, func(r *retry.R) { + require.Len(r, a1.WANMembers(), 2) + require.Len(r, a2.WANMembers(), 2) + }) + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc2", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + require.NoError(t, a2.RPC(context.Background(), "PreparedQuery.Apply", args, &id)) + } + + type testCase struct { + nodeTaggedAddresses map[string]string + serviceAddress string + serviceTaggedAddresses map[string]structs.ServiceAddress + + dnsAddr string + + expectedPort uint16 + expectedAddress string + expectedARRName string + } + + cases := map[string]testCase{ + "node-addr-from-dc1": { + dnsAddr: a1.config.DNSAddrs[0].String(), + expectedPort: 8080, + expectedAddress: "127.0.0.1", + expectedARRName: "foo.node.dc2.consul.", + }, + "node-wan-from-dc1": { + dnsAddr: a1.config.DNSAddrs[0].String(), + nodeTaggedAddresses: map[string]string{ + "wan": "127.0.0.2", + }, + expectedPort: 8080, + expectedAddress: "127.0.0.2", + expectedARRName: "7f000002.addr.dc2.consul.", + }, + "service-addr-from-dc1": { + dnsAddr: a1.config.DNSAddrs[0].String(), + nodeTaggedAddresses: map[string]string{ + "wan": "127.0.0.2", + }, + serviceAddress: "10.0.1.1", + expectedPort: 8080, + expectedAddress: "10.0.1.1", + expectedARRName: "0a000101.addr.dc2.consul.", + }, + "service-wan-from-dc1": { + dnsAddr: a1.config.DNSAddrs[0].String(), + nodeTaggedAddresses: map[string]string{ + "wan": "127.0.0.2", + }, + serviceAddress: "10.0.1.1", + serviceTaggedAddresses: map[string]structs.ServiceAddress{ + "wan": { + Address: "198.18.0.1", + Port: 80, + }, + }, + expectedPort: 80, + expectedAddress: "198.18.0.1", + expectedARRName: "c6120001.addr.dc2.consul.", + }, + "node-addr-from-dc2": { + dnsAddr: a2.config.DNSAddrs[0].String(), + expectedPort: 8080, + expectedAddress: "127.0.0.1", + expectedARRName: "foo.node.dc2.consul.", + }, + "node-wan-from-dc2": { + dnsAddr: a2.config.DNSAddrs[0].String(), + nodeTaggedAddresses: map[string]string{ + "wan": "127.0.0.2", + }, + expectedPort: 8080, + expectedAddress: "127.0.0.1", + expectedARRName: "foo.node.dc2.consul.", + }, + "service-addr-from-dc2": { + dnsAddr: a2.config.DNSAddrs[0].String(), + nodeTaggedAddresses: map[string]string{ + "wan": "127.0.0.2", + }, + serviceAddress: "10.0.1.1", + expectedPort: 8080, + expectedAddress: "10.0.1.1", + expectedARRName: "0a000101.addr.dc2.consul.", + }, + "service-wan-from-dc2": { + dnsAddr: a2.config.DNSAddrs[0].String(), + nodeTaggedAddresses: map[string]string{ + "wan": "127.0.0.2", + }, + serviceAddress: "10.0.1.1", + serviceTaggedAddresses: map[string]structs.ServiceAddress{ + "wan": { + Address: "198.18.0.1", + Port: 80, + }, + }, + expectedPort: 8080, + expectedAddress: "10.0.1.1", + expectedARRName: "0a000101.addr.dc2.consul.", + }, + } + + for name, tc := range cases { + name := name + tc := tc + t.Run(name, func(t *testing.T) { + // Register a remote node with a service. This is in a retry since we + // need the datacenter to have a route which takes a little more time + // beyond the join, and we don't have direct access to the router here. + retry.Run(t, func(r *retry.R) { + args := &structs.RegisterRequest{ + Datacenter: "dc2", + Node: "foo", + Address: "127.0.0.1", + TaggedAddresses: tc.nodeTaggedAddresses, + Service: &structs.NodeService{ + Service: "db", + Address: tc.serviceAddress, + Port: 8080, + TaggedAddresses: tc.serviceTaggedAddresses, + }, + } + + var out struct{} + require.NoError(r, a2.RPC(context.Background(), "Catalog.Register", args, &out)) + }) + + // Look up the SRV record via service and prepared query. + questions := []string{ + "db.service.dc2.consul.", + id + ".query.dc2.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + + addr := tc.dnsAddr + in, _, err := c.Exchange(m, addr) + require.NoError(t, err) + require.Len(t, in.Answer, 1) + srvRec, ok := in.Answer[0].(*dns.SRV) + require.True(t, ok, "Bad: %#v", in.Answer[0]) + require.Equal(t, tc.expectedPort, srvRec.Port) + + aRec, ok := in.Extra[0].(*dns.A) + require.True(t, ok, "Bad: %#v", in.Extra[0]) + require.Equal(t, tc.expectedARRName, aRec.Hdr.Name) + require.Equal(t, tc.expectedAddress, aRec.A.String()) + } + + // Also check the A record directly + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeA) + + c := new(dns.Client) + addr := tc.dnsAddr + in, _, err := c.Exchange(m, addr) + require.NoError(t, err) + require.Len(t, in.Answer, 1) + + aRec, ok := in.Answer[0].(*dns.A) + require.True(t, ok, "Bad: %#v", in.Answer[0]) + require.Equal(t, question, aRec.Hdr.Name) + require.Equal(t, tc.expectedAddress, aRec.A.String()) + } + }) + } +} + +func TestDNS_ServiceLookup_CaseInsensitive(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + tests := []struct { + name string + config string + }{ + // UDP + EDNS + {"normal", ""}, + {"cache", `dns_config{ allow_stale=true, max_stale="3h", use_cache=true, "cache_max_age"="3h"}`}, + {"cache-with-streaming", ` + rpc{ + enable_streaming=true + } + use_streaming_backend=true + dns_config{ allow_stale=true, max_stale="3h", use_cache=true, "cache_max_age"="3h"} + `}, + } + for _, tst := range tests { + t.Run(fmt.Sprintf("A lookup %v", tst.name), func(t *testing.T) { + + a := NewTestAgent(t, tst.config) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "Db", + Tags: []string{"Primary"}, + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query, as well as a name. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "somequery", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Try some variations to make sure case doesn't matter. + questions := []string{ + "primary.Db.service.consul.", + "primary.db.service.consul.", + "pRIMARY.dB.service.consul.", + "PRIMARY.dB.service.consul.", + "db.service.consul.", + "DB.service.consul.", + "Db.service.consul.", + "somequery.query.consul.", + "SomeQuery.query.consul.", + "SOMEQUERY.query.consul.", + } + + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + retry.Run(t, func(r *retry.R) { + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + r.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + r.Fatalf("question %v, empty lookup: %#v", question, in) + } + }) + } + }) + } +} + +// We have deprecated support for service tags w/ periods +func TestDNS_ServiceLookup_TagPeriod(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"v1.primary"}, + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m1 := new(dns.Msg) + m1.SetQuestion("v1.primary2.db.service.consul.", dns.TypeSRV) + + c1 := new(dns.Client) + in, _, err := c1.Exchange(m1, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 0 { + t.Fatalf("Bad: %#v", in) + } + + m := new(dns.Msg) + m.SetQuestion("v1.primary.db.service.consul.", dns.TypeSRV) + + c := new(dns.Client) + in, _, err = c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", srvRec) + } + + aRec, ok := in.Extra[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Name != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.A.String() != "127.0.0.1" { + t.Fatalf("Bad: %#v", in.Extra[0]) + } +} + +// TestDNS_ServiceLookup_ExtraTags tests tag behavior. +func TestDNS_ServiceLookup_ExtraTags(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m1 := new(dns.Msg) + m1.SetQuestion("dummy.primary.db.service.consul.", dns.TypeSRV) + + c1 := new(dns.Client) + in, _, err := c1.Exchange(m1, a.DNSAddr()) + require.NoError(t, err) + require.Len(t, in.Answer, 0, "Expected no answer") + require.Equal(t, dns.RcodeNameError, in.Rcode) +} + +func TestDNS_ServiceLookup_PreparedQueryNamePeriod(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register a prepared query with a period in the name. + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "some.query.we.like", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + + var id string + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + m := new(dns.Msg) + m.SetQuestion("some.query.we.like.query.consul.", dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", srvRec) + } + + aRec, ok := in.Extra[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Name != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.A.String() != "127.0.0.1" { + t.Fatalf("Bad: %#v", in.Extra[0]) + } +} + +func TestDNS_ServiceLookup_Dedup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a single node with multiple instances of a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + args = &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + ID: "db2", + Service: "db", + Tags: []string{"replica"}, + Port: 12345, + }, + } + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + args = &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + ID: "db3", + Service: "db", + Tags: []string{"replica"}, + Port: 12346, + }, + } + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query, make sure only + // one IP is returned. + questions := []string{ + "db.service.consul.", + id + ".query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + aRec, ok := in.Answer[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if aRec.A.String() != "127.0.0.1" { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + } +} + +func TestDNS_ServiceLookup_Dedup_SRV(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a single node with multiple instances of a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + args = &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + ID: "db2", + Service: "db", + Tags: []string{"replica"}, + Port: 12345, + }, + } + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + args = &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + ID: "db3", + Service: "db", + Tags: []string{"replica"}, + Port: 12346, + }, + } + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query, make sure only + // one IP is returned and two unique ports are returned. + questions := []string{ + "db.service.consul.", + id + ".query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 2 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 && srvRec.Port != 12346 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", srvRec) + } + + srvRec, ok = in.Answer[1].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[1]) + } + if srvRec.Port != 12346 && srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Port == in.Answer[0].(*dns.SRV).Port { + t.Fatalf("should be a different port") + } + if srvRec.Target != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", srvRec) + } + + aRec, ok := in.Extra[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Name != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.A.String() != "127.0.0.1" { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + } +} + +func TestDNS_ServiceLookup_FilterCritical(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register nodes with health checks in various states. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + Check: &structs.HealthCheck{ + CheckID: "serf", + Name: "serf", + Status: api.HealthCritical, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + args2 := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "127.0.0.2", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + Check: &structs.HealthCheck{ + CheckID: "serf", + Name: "serf", + Status: api.HealthCritical, + }, + } + if err := a.RPC(context.Background(), "Catalog.Register", args2, &out); err != nil { + t.Fatalf("err: %v", err) + } + + args3 := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "127.0.0.2", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + Check: &structs.HealthCheck{ + CheckID: "db", + Name: "db", + ServiceID: "db", + Status: api.HealthCritical, + }, + } + if err := a.RPC(context.Background(), "Catalog.Register", args3, &out); err != nil { + t.Fatalf("err: %v", err) + } + + args4 := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "baz", + Address: "127.0.0.3", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + } + if err := a.RPC(context.Background(), "Catalog.Register", args4, &out); err != nil { + t.Fatalf("err: %v", err) + } + + args5 := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "quux", + Address: "127.0.0.4", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + Check: &structs.HealthCheck{ + CheckID: "db", + Name: "db", + ServiceID: "db", + Status: api.HealthWarning, + }, + } + if err := a.RPC(context.Background(), "Catalog.Register", args5, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []string{ + "db.service.consul.", + id + ".query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Only 4 and 5 are not failing, so we should get 2 answers + if len(in.Answer) != 2 { + t.Fatalf("Bad: %#v", in) + } + + ips := make(map[string]bool) + for _, resp := range in.Answer { + aRec := resp.(*dns.A) + ips[aRec.A.String()] = true + } + + if !ips["127.0.0.3"] { + t.Fatalf("Bad: %#v should contain 127.0.0.3 (state healthy)", in) + } + if !ips["127.0.0.4"] { + t.Fatalf("Bad: %#v should contain 127.0.0.4 (state warning)", in) + } + } +} + +func TestDNS_ServiceLookup_OnlyFailing(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register nodes with all health checks in a critical state. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + Check: &structs.HealthCheck{ + CheckID: "serf", + Name: "serf", + Status: api.HealthCritical, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + args2 := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "127.0.0.2", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + Check: &structs.HealthCheck{ + CheckID: "serf", + Name: "serf", + Status: api.HealthCritical, + }, + } + if err := a.RPC(context.Background(), "Catalog.Register", args2, &out); err != nil { + t.Fatalf("err: %v", err) + } + + args3 := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "127.0.0.2", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + Check: &structs.HealthCheck{ + CheckID: "db", + Name: "db", + ServiceID: "db", + Status: api.HealthCritical, + }, + } + if err := a.RPC(context.Background(), "Catalog.Register", args3, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []string{ + "db.service.consul.", + id + ".query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + // All 3 are failing, so we should get 0 answers and an NXDOMAIN response + if len(in.Answer) != 0 { + t.Fatalf("Bad: %#v", in) + } + + if in.Rcode != dns.RcodeNameError { + t.Fatalf("Bad: %#v", in) + } + } +} + +func TestDNS_ServiceLookup_OnlyPassing(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, ` + dns_config { + only_passing = true + } + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register nodes with health checks in various states. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + Check: &structs.HealthCheck{ + CheckID: "db", + Name: "db", + ServiceID: "db", + Status: api.HealthPassing, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + args2 := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "127.0.0.2", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + Check: &structs.HealthCheck{ + CheckID: "db", + Name: "db", + ServiceID: "db", + Status: api.HealthWarning, + }, + } + + if err := a.RPC(context.Background(), "Catalog.Register", args2, &out); err != nil { + t.Fatalf("err: %v", err) + } + + args3 := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "baz", + Address: "127.0.0.3", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + Check: &structs.HealthCheck{ + CheckID: "db", + Name: "db", + ServiceID: "db", + Status: api.HealthCritical, + }, + } + + if err := a.RPC(context.Background(), "Catalog.Register", args3, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + OnlyPassing: true, + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []string{ + "db.service.consul.", + id + ".query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Only 1 is passing, so we should only get 1 answer + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + resp := in.Answer[0] + aRec := resp.(*dns.A) + + if aRec.A.String() != "127.0.0.1" { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + } + + newCfg := *a.Config + newCfg.DNSOnlyPassing = false + err := a.reloadConfigInternal(&newCfg) + require.NoError(t, err) + + // only_passing is now false. we should now get two nodes + m := new(dns.Msg) + m.SetQuestion("db.service.consul.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + + require.Equal(t, 2, len(in.Answer)) + ips := []string{in.Answer[0].(*dns.A).A.String(), in.Answer[1].(*dns.A).A.String()} + sort.Strings(ips) + require.Equal(t, []string{"127.0.0.1", "127.0.0.2"}, ips) +} + +func TestDNS_ServiceLookup_Randomize(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a large number of nodes. + for i := 0; i < generateNumNodes; i++ { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: fmt.Sprintf("foo%d", i), + Address: fmt.Sprintf("127.0.0.%d", i+1), + Service: &structs.NodeService{ + Service: "web", + Port: 8000, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "web", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. Ensure the + // response is randomized each time. + questions := []string{ + "web.service.consul.", + id + ".query.consul.", + } + for _, question := range questions { + uniques := map[string]struct{}{} + for i := 0; i < 10; i++ { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeANY) + + c := &dns.Client{Net: "udp"} + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Response length should be truncated and we should get + // an A record for each response. + if len(in.Answer) != defaultNumUDPResponses { + t.Fatalf("Bad: %#v", len(in.Answer)) + } + + // Collect all the names. + var names []string + for _, rec := range in.Answer { + switch v := rec.(type) { + case *dns.SRV: + names = append(names, v.Target) + case *dns.A: + names = append(names, v.A.String()) + } + } + nameS := strings.Join(names, "|") + + // Tally the results. + uniques[nameS] = struct{}{} + } + + // Give some wiggle room. Since the responses are randomized and + // there is a finite number of combinations, requiring 0 + // duplicates every test run eventually gives us failures. + if len(uniques) < 2 { + t.Fatalf("unique response ratio too low: %d/10\n%v", len(uniques), uniques) + } + } +} + +func TestDNS_ServiceLookup_Truncate(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, ` + dns_config { + enable_truncate = true + } + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a large number of nodes. + for i := 0; i < generateNumNodes; i++ { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: fmt.Sprintf("foo%d", i), + Address: fmt.Sprintf("127.0.0.%d", i+1), + Service: &structs.NodeService{ + Service: "web", + Port: 8000, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "web", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. Ensure the + // response is truncated each time. + questions := []string{ + "web.service.consul.", + id + ".query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Check for the truncate bit + if !in.Truncated { + t.Fatalf("should have truncate bit") + } + } +} + +func TestDNS_ServiceLookup_LargeResponses(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, ` + dns_config { + enable_truncate = true + } + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + longServiceName := "this-is-a-very-very-very-very-very-long-name-for-a-service" + + // Register a lot of nodes. + for i := 0; i < 4; i++ { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: fmt.Sprintf("foo%d", i), + Address: fmt.Sprintf("127.0.0.%d", i+1), + Service: &structs.NodeService{ + Service: longServiceName, + Tags: []string{"primary"}, + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: longServiceName, + Service: structs.ServiceQuery{ + Service: longServiceName, + Tags: []string{"primary"}, + }, + }, + } + var id string + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []string{ + "_" + longServiceName + "._primary.service.consul.", + longServiceName + ".query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if !in.Truncated { + t.Fatalf("should have truncate bit") + } + + // Make sure the response size is RFC 1035-compliant for UDP messages + if in.Len() > 512 { + t.Fatalf("Bad: %d", in.Len()) + } + + // We should only have two answers now + if len(in.Answer) != 2 { + t.Fatalf("Bad: %d", len(in.Answer)) + } + + // Make sure the ADDITIONAL section matches the ANSWER section. + if len(in.Answer) != len(in.Extra) { + t.Fatalf("Bad: %d vs. %d", len(in.Answer), len(in.Extra)) + } + for i := 0; i < len(in.Answer); i++ { + srv, ok := in.Answer[i].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[i]) + } + + a, ok := in.Extra[i].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[i]) + } + + if srv.Target != a.Hdr.Name { + t.Fatalf("Bad: %#v %#v", srv, a) + } + } + + // Check for the truncate bit + if !in.Truncated { + t.Fatalf("should have truncate bit") + } + } +} + +func testDNSServiceLookupResponseLimits(questions []string, answerLimit int, qType uint16, + expectedService, expectedQuery, expectedQueryID int, a *TestAgent) (bool, error) { + for idx, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, qType) + + c := &dns.Client{Net: "udp"} + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + return false, fmt.Errorf("err: %v", err) + } + + switch idx { + case 0: + if (expectedService > 0 && len(in.Answer) != expectedService) || + (expectedService < -1 && len(in.Answer) < lib.AbsInt(expectedService)) { + return false, fmt.Errorf("%d/%d answers received for type %v for %s, sz:=%d", len(in.Answer), answerLimit, qType, question, in.Len()) + } + case 1: + if (expectedQuery > 0 && len(in.Answer) != expectedQuery) || + (expectedQuery < -1 && len(in.Answer) < lib.AbsInt(expectedQuery)) { + return false, fmt.Errorf("%d/%d answers received for type %v for %s, sz:=%d", len(in.Answer), answerLimit, qType, question, in.Len()) + } + case 2: + if (expectedQueryID > 0 && len(in.Answer) != expectedQueryID) || + (expectedQueryID < -1 && len(in.Answer) < lib.AbsInt(expectedQueryID)) { + return false, fmt.Errorf("%d/%d answers received for type %v for %s, sz:=%d", len(in.Answer), answerLimit, qType, question, in.Len()) + } + default: + panic("abort") + } + } + + return true, nil +} + +func checkDNSService( + t *testing.T, + protocol string, + questions []string, + a *TestAgent, + qType uint16, + expectedResultsCount int, + udpSize uint16, + setEDNS0 bool, +) { + for _, question := range questions { + t.Run("question: "+question, func(t *testing.T) { + + m := new(dns.Msg) + + m.SetQuestion(question, qType) + if setEDNS0 { + m.SetEdns0(udpSize, true) + } + c := &dns.Client{Net: protocol, UDPSize: udpSize} + in, _, err := c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + + t.Logf("DNS Response for %+v - %+v", m, in) + + require.Equal(t, expectedResultsCount, len(in.Answer), + "%d/%d answers received for type %v for %s (%s)", len(in.Answer), expectedResultsCount, qType, question, protocol) + }) + } +} + +func registerServicesAndPreparedQuery(t *testing.T, generateNumNodes int, a *TestAgent, serviceUniquenessKey string) []string { + choices := perfectlyRandomChoices(generateNumNodes, pctNodesWithIPv6) + serviceName := fmt.Sprintf("api-tier-%s", serviceUniquenessKey) + for i := 0; i < generateNumNodes; i++ { + nodeAddress := fmt.Sprintf("127.0.0.%d", i+1) + if choices[i] { + nodeAddress = fmt.Sprintf("fe80::%d", i+1) + } + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: fmt.Sprintf("foo%d", i), + Address: nodeAddress, + Service: &structs.NodeService{ + Service: serviceName, + Port: 8080, + }, + } + + var out struct{} + require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) + } + var preparedQueryID string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: serviceName, + Service: structs.ServiceQuery{ + Service: serviceName, + }, + }, + } + + require.NoError(t, a.RPC(context.Background(), "PreparedQuery.Apply", args, &preparedQueryID)) + } + + // Look up the service directly and via prepared query. + questions := []string{ + fmt.Sprintf("%s.service.consul.", serviceName), + fmt.Sprintf("%s.query.consul.", serviceName), + preparedQueryID + ".query.consul.", + } + return questions +} + +func TestDNS_ServiceLookup_ARecordLimits(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + const ( + UDP = "udp" + TCP = "tcp" + ) + + type testCase struct { + protocol string + aRecordLimit int + expectedAResults int + expectedAAAAResults int + expectedANYResults int + expectedSRVResults int + numNodesTotal int + udpSize uint16 + setEDNS0 bool + } + + type aRecordLimit struct { + name string + limit int + } + + tests := map[string]testCase{ + // UDP + EDNS + "udp-edns-1": {UDP, 1, 1, 1, 1, 30, 30, 8192, true}, + "udp-edns-2": {UDP, 2, 2, 2, 2, 30, 30, 8192, true}, + "udp-edns-3": {UDP, 3, 3, 3, 3, 30, 30, 8192, true}, + "udp-edns-4": {UDP, 4, 4, 4, 4, 30, 30, 8192, true}, + "udp-edns-5": {UDP, 5, 5, 5, 5, 30, 30, 8192, true}, + "udp-edns-6": {UDP, 6, 6, 6, 6, 30, 30, 8192, true}, + "udp-edns-max": {UDP, 6, 2, 1, 3, 3, 3, 8192, true}, + // All UDP without EDNS and no udpAnswerLimit + // Size of records is limited by UDP payload + "udp-1": {UDP, 1, 1, 0, 1, 1, 1, 512, false}, + "udp-2": {UDP, 2, 1, 1, 2, 2, 2, 512, false}, + "udp-3": {UDP, 3, 1, 1, 2, 2, 2, 512, false}, + "udp-4": {UDP, 4, 1, 1, 2, 2, 2, 512, false}, + "udp-5": {UDP, 5, 1, 1, 2, 2, 2, 512, false}, + "udp-6": {UDP, 6, 1, 1, 2, 2, 2, 512, false}, + // Only 3 A and 3 SRV records on 512 bytes + "udp-max": {UDP, 6, 1, 1, 2, 2, 2, 512, false}, + + "tcp-1": {TCP, 1, 1, 1, 1, 30, 30, 0, false}, + "tcp-2": {TCP, 2, 2, 2, 2, 30, 30, 0, false}, + "tcp-3": {TCP, 3, 3, 3, 3, 30, 30, 0, false}, + "tcp-4": {TCP, 4, 4, 4, 4, 30, 30, 0, false}, + "tcp-5": {TCP, 5, 5, 5, 5, 30, 30, 0, false}, + "tcp-6": {TCP, 6, 6, 6, 6, 30, 30, 0, false}, + "tcp-max": {TCP, 6, 1, 1, 2, 2, 2, 0, false}, + } + for _, recordLimit := range []aRecordLimit{ + {"1", 1}, + {"2", 2}, + {"3", 3}, + {"4", 4}, + {"5", 5}, + {"6", 6}, + {"max", 6}, + } { + t.Run("record-limit-"+recordLimit.name, func(t *testing.T) { + a := NewTestAgent(t, ` + node_name = "test-node" + dns_config { + a_record_limit = `+fmt.Sprintf("%d", recordLimit.limit)+` + udp_answer_limit = `+fmt.Sprintf("%d", recordLimit.limit)+` + } + `) + + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + + for _, testName := range []string{ + fmt.Sprintf("udp-edns-%s", recordLimit.name), + fmt.Sprintf("udp-%s", recordLimit.name), + fmt.Sprintf("tcp-%s", recordLimit.name), + } { + t.Run(testName, func(t *testing.T) { + test := tests[testName] + questions := registerServicesAndPreparedQuery(t, test.numNodesTotal, a, testName) + + t.Run("A", func(t *testing.T) { + checkDNSService(t, test.protocol, questions, a, dns.TypeA, test.expectedAResults, test.udpSize, test.setEDNS0) + }) + + t.Run("AAAA", func(t *testing.T) { + checkDNSService(t, test.protocol, questions, a, dns.TypeAAAA, test.expectedAAAAResults, test.udpSize, test.setEDNS0) + }) + + t.Run("ANY", func(t *testing.T) { + checkDNSService(t, test.protocol, questions, a, dns.TypeANY, test.expectedANYResults, test.udpSize, test.setEDNS0) + }) + + // No limits but the size of records for SRV records, since not subject to randomization issues + t.Run("SRV", func(t *testing.T) { + checkDNSService(t, test.protocol, questions, a, dns.TypeSRV, test.numNodesTotal, test.udpSize, test.setEDNS0) + }) + }) + } + }) + } +} + +func TestDNS_ServiceLookup_AnswerLimits(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + // Build a matrix of config parameters (udpAnswerLimit), and the + // length of the response per query type and question. Negative + // values imply the test must return at least the abs(value) number + // of records in the answer section. This is required because, for + // example, on OS-X and Linux, the number of answers returned in a + // 512B response is different even though both platforms are x86_64 + // and using the same version of Go. + // + // TODO(sean@): Why is it not identical everywhere when using the + // same compiler? + tests := []struct { + name string + udpAnswerLimit int + expectedAService int + expectedAQuery int + expectedAQueryID int + expectedAAAAService int + expectedAAAAQuery int + expectedAAAAQueryID int + expectedANYService int + expectedANYQuery int + expectedANYQueryID int + }{ + {"0", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {"1", 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {"2", 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, + {"3", 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + {"4", 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + {"5", 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}, + {"6", 6, 6, 6, 6, 6, 6, 5, 6, 6, -5}, + {"7", 7, 7, 7, 6, 7, 7, 5, 7, 7, -5}, + {"8", 8, 8, 8, 6, 8, 8, 5, 8, 8, -5}, + {"9", 9, 8, 8, 6, 8, 8, 5, 8, 8, -5}, + {"20", 20, 8, 8, 6, 8, 8, 5, 8, -5, -5}, + {"30", 30, 8, 8, 6, 8, 8, 5, 8, -5, -5}, + } + for _, test := range tests { + test := test // capture loop var + t.Run(fmt.Sprintf("answer-limit-%s", test.name), func(t *testing.T) { + a := NewTestAgent(t, fmt.Sprintf(` + node_name = "test-node" + dns_config { + udp_answer_limit = %d + }`, test.udpAnswerLimit)) + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + questions := registerServicesAndPreparedQuery(t, generateNumNodes, a, test.name) + + t.Run(fmt.Sprintf("A lookup %v", test), func(t *testing.T) { + ok, err := testDNSServiceLookupResponseLimits(questions, test.udpAnswerLimit, dns.TypeA, test.expectedAService, test.expectedAQuery, test.expectedAQueryID, a) + if !ok { + t.Fatalf("Expected service A lookup %s to pass: %v", test.name, err) + } + }) + + t.Run(fmt.Sprintf("AAAA lookup %v", test), func(t *testing.T) { + ok, err := testDNSServiceLookupResponseLimits(questions, test.udpAnswerLimit, dns.TypeAAAA, test.expectedAAAAService, test.expectedAAAAQuery, test.expectedAAAAQueryID, a) + if !ok { + t.Fatalf("Expected service AAAA lookup %s to pass: %v", test.name, err) + } + }) + + t.Run(fmt.Sprintf("ANY lookup %v", test), func(t *testing.T) { + ok, err := testDNSServiceLookupResponseLimits(questions, test.udpAnswerLimit, dns.TypeANY, test.expectedANYService, test.expectedANYQuery, test.expectedANYQueryID, a) + if !ok { + t.Fatalf("Expected service ANY lookup %s to pass: %v", test.name, err) + } + }) + }) + } +} + +func TestDNS_ServiceLookup_CNAME(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + recursor := makeRecursor(t, dns.Msg{ + Answer: []dns.RR{ + dnsCNAME("www.google.com", "google.com"), + dnsA("google.com", "1.2.3.4"), + }, + }) + defer recursor.Shutdown() + + a := NewTestAgent(t, ` + recursors = ["`+recursor.Addr+`"] + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a name for an address. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "google", + Address: "www.google.com", + Service: &structs.NodeService{ + Service: "search", + Port: 80, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "search", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []string{ + "search.service.consul.", + id + ".query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Service CNAME, google CNAME, google A record + if len(in.Answer) != 3 { + t.Fatalf("Bad: %#v", in) + } + + // Should have service CNAME + cnRec, ok := in.Answer[0].(*dns.CNAME) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if cnRec.Target != "www.google.com." { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + // Should have google CNAME + cnRec, ok = in.Answer[1].(*dns.CNAME) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[1]) + } + if cnRec.Target != "google.com." { + t.Fatalf("Bad: %#v", in.Answer[1]) + } + + // Check we recursively resolve + if _, ok := in.Answer[2].(*dns.A); !ok { + t.Fatalf("Bad: %#v", in.Answer[2]) + } + } +} + +func TestDNS_ServiceLookup_ServiceAddress_CNAME(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + recursor := makeRecursor(t, dns.Msg{ + Answer: []dns.RR{ + dnsCNAME("www.google.com", "google.com"), + dnsA("google.com", "1.2.3.4"), + }, + }) + defer recursor.Shutdown() + + a := NewTestAgent(t, ` + recursors = ["`+recursor.Addr+`"] + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a name for an address. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "google", + Address: "1.2.3.4", + Service: &structs.NodeService{ + Service: "search", + Port: 80, + Address: "www.google.com", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "search", + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []string{ + "search.service.consul.", + id + ".query.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Service CNAME, google CNAME, google A record + if len(in.Answer) != 3 { + t.Fatalf("Bad: %#v", in) + } + + // Should have service CNAME + cnRec, ok := in.Answer[0].(*dns.CNAME) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if cnRec.Target != "www.google.com." { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + // Should have google CNAME + cnRec, ok = in.Answer[1].(*dns.CNAME) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[1]) + } + if cnRec.Target != "google.com." { + t.Fatalf("Bad: %#v", in.Answer[1]) + } + + // Check we recursively resolve + if _, ok := in.Answer[2].(*dns.A); !ok { + t.Fatalf("Bad: %#v", in.Answer[2]) + } + } +} + +func TestDNS_ServiceLookup_TTL(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, ` + dns_config { + service_ttl = { + "d*" = "42s" + "db" = "10s" + "db*" = "66s" + "*" = "5s" + } + allow_stale = true + max_stale = "1s" + } + `) + defer a.Shutdown() + + for idx, service := range []string{"db", "dblb", "dk", "api"} { + nodeName := fmt.Sprintf("foo%d", idx) + address := fmt.Sprintf("127.0.0.%d", idx) + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: nodeName, + Address: address, + Service: &structs.NodeService{ + Service: service, + Tags: []string{"primary"}, + Port: 12345 + idx, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + c := new(dns.Client) + expectResult := func(dnsQuery string, expectedTTL uint32) { + t.Run(dnsQuery, func(t *testing.T) { + m := new(dns.Msg) + m.SetQuestion(dnsQuery, dns.TypeSRV) + + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v, len is %d", in, len(in.Answer)) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Hdr.Ttl != expectedTTL { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + aRec, ok := in.Extra[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Ttl != expectedTTL { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + }) + } + // Should have its exact TTL + expectResult("db.service.consul.", 10) + // Should match db* + expectResult("dblb.service.consul.", 66) + // Should match d* + expectResult("dk.service.consul.", 42) + // Should match * + expectResult("api.service.consul.", 5) +} + +func TestDNS_ServiceLookup_SRV_RFC(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + questions := []string{ + "_db._primary.service.dc1.consul.", + "_db._primary.service.consul.", + "_db._primary.dc1.consul.", + "_db._primary.consul.", + } + + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + aRec, ok := in.Extra[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Name != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.A.String() != "127.0.0.1" { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + } +} + +func TestDNS_ServiceLookup_SRV_RFC_TCP_Default(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register node + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + questions := []string{ + "_db._tcp.service.dc1.consul.", + "_db._tcp.service.consul.", + "_db._tcp.dc1.consul.", + "_db._tcp.consul.", + } + + for _, question := range questions { + t.Run(question, func(t *testing.T) { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + aRec, ok := in.Extra[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Name != "foo.node.dc1.consul." { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.A.String() != "127.0.0.1" { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + }) + } +} + +func initDNSToken(t *testing.T, rpc RPC) { + t.Helper() + + reqToken := structs.ACLTokenSetRequest{ + Datacenter: "dc1", + ACLToken: structs.ACLToken{ + SecretID: "279d4735-f8ca-4d48-b5cc-c00a9713bbf8", + Policies: nil, + TemplatedPolicies: []*structs.ACLTemplatedPolicy{{TemplateName: "builtin/dns"}}, + }, + WriteRequest: structs.WriteRequest{Token: "root"}, + } + err := rpc.RPC(context.Background(), "ACL.TokenSet", &reqToken, &structs.ACLToken{}) + require.NoError(t, err) +} + +func TestDNS_ServiceLookup_FilterACL(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + tests := []struct { + token string + results int + }{ + {"root", 1}, + {"anonymous", 0}, + {"dns", 1}, + } + for _, tt := range tests { + t.Run("ACLToken == "+tt.token, func(t *testing.T) { + hcl := ` + primary_datacenter = "dc1" + + acl { + enabled = true + default_policy = "deny" + down_policy = "deny" + + tokens { + initial_management = "root" +` + if tt.token == "dns" { + // Create a UUID for dns token since it doesn't have an alias + dnsToken := "279d4735-f8ca-4d48-b5cc-c00a9713bbf8" + + hcl = hcl + ` + default = "anonymous" + dns = "` + dnsToken + `" +` + } else { + hcl = hcl + ` + default = "` + tt.token + `" +` + } + + hcl = hcl + ` + } + } + ` + + a := NewTestAgent(t, hcl) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + if tt.token == "dns" { + initDNSToken(t, a) + } + + // Register a service + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "foo", + Port: 12345, + }, + WriteRequest: structs.WriteRequest{Token: "root"}, + } + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + // Set up the DNS query + c := new(dns.Client) + m := new(dns.Msg) + m.SetQuestion("foo.service.consul.", dns.TypeA) + + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + if len(in.Answer) != tt.results { + t.Fatalf("Bad: %#v", in) + } + }) + } +} + +func TestDNS_ServiceLookup_MetaTXT(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = true } `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "127.0.0.1", + NodeMeta: map[string]string{ + "key": "value", + }, + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("db.service.consul.", dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + wantAdditional := []dns.RR{ + &dns.A{ + Hdr: dns.RR_Header{Name: "bar.node.dc1.consul.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4}, + A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1 + }, + &dns.TXT{ + Hdr: dns.RR_Header{Name: "bar.node.dc1.consul.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Rdlength: 0xa}, + Txt: []string{"key=value"}, + }, + } + require.Equal(t, wantAdditional, in.Extra) +} + +func TestDNS_ServiceLookup_SuppressTXT(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = false } `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "127.0.0.1", + NodeMeta: map[string]string{ + "key": "value", + }, + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + m := new(dns.Msg) + m.SetQuestion("db.service.consul.", dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + wantAdditional := []dns.RR{ + &dns.A{ + Hdr: dns.RR_Header{Name: "bar.node.dc1.consul.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4}, + A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1 + }, + } + require.Equal(t, wantAdditional, in.Extra) +} diff --git a/agent/dns_test.go b/agent/dns_test.go index 3c447db36ee2..c5a8c1db2c54 100644 --- a/agent/dns_test.go +++ b/agent/dns_test.go @@ -3,6 +3,15 @@ package agent +/* Note: this file got to be 10k lines long and caused multiple IDE issues + * as well as GitHub's UI unable to display diffs with large changes to this file. + * This file has been broken up by moving: + * - Node Lookup tests into dns_node_lookup_test.go + * - Service Lookup tests into dn_service_lookup_test.go + * + * Please be aware of the size of each of these files and add tests / break + * up tests accordingly. + */ import ( "context" "errors" @@ -11,22 +20,21 @@ import ( "math/rand" "net" "reflect" - "sort" "strings" "testing" "time" - "github.com/hashicorp/serf/coordinate" "github.com/miekg/dns" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" + "github.com/hashicorp/serf/coordinate" + + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/config" "github.com/hashicorp/consul/agent/consul" - agentdns "github.com/hashicorp/consul/agent/dns" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/testrpc" ) @@ -109,8 +117,8 @@ func dnsTXT(src string, txt []string) *dns.TXT { } } -func TestRecursorAddr(t *testing.T) { - t.Parallel() +// Copied to agent/dns/recursor_test.go +func TestDNS_RecursorAddr(t *testing.T) { addr, err := recursorAddr("8.8.8.8") if err != nil { t.Fatalf("err: %v", err) @@ -135,7 +143,7 @@ func TestRecursorAddr(t *testing.T) { } } -func TestEncodeKVasRFC1464(t *testing.T) { +func TestDNS_EncodeKVasRFC1464(t *testing.T) { // Test cases are from rfc1464 type rfc1464Test struct { key, value, internalForm, externalForm string @@ -169,7 +177,6 @@ func TestDNS_Over_TCP(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -206,7 +213,6 @@ func TestDNS_EmptyAltDomain(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -220,238 +226,11 @@ func TestDNS_EmptyAltDomain(t *testing.T) { require.Empty(t, in.Answer) } -func TestDNS_NodeLookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register node - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - TaggedAddresses: map[string]string{ - "wan": "127.0.0.2", - }, - NodeMeta: map[string]string{ - "key": "value", - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - m := new(dns.Msg) - m.SetQuestion("foo.node.consul.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - require.NoError(t, err) - require.Len(t, in.Answer, 2) - require.Len(t, in.Extra, 0) - - aRec, ok := in.Answer[0].(*dns.A) - require.True(t, ok, "First answer is not an A record") - require.Equal(t, "127.0.0.1", aRec.A.String()) - require.Equal(t, uint32(0), aRec.Hdr.Ttl) - - txt, ok := in.Answer[1].(*dns.TXT) - require.True(t, ok, "Second answer is not a TXT record") - require.Len(t, txt.Txt, 1) - require.Equal(t, "key=value", txt.Txt[0]) - - // Re-do the query, but only for an A RR - - m = new(dns.Msg) - m.SetQuestion("foo.node.consul.", dns.TypeA) - - c = new(dns.Client) - in, _, err = c.Exchange(m, a.DNSAddr()) - require.NoError(t, err) - require.Len(t, in.Answer, 1) - require.Len(t, in.Extra, 1) - - aRec, ok = in.Answer[0].(*dns.A) - require.True(t, ok, "Answer is not an A record") - require.Equal(t, "127.0.0.1", aRec.A.String()) - require.Equal(t, uint32(0), aRec.Hdr.Ttl) - - txt, ok = in.Extra[0].(*dns.TXT) - require.True(t, ok, "Extra record is not a TXT record") - require.Len(t, txt.Txt, 1) - require.Equal(t, "key=value", txt.Txt[0]) - - // Re-do the query, but specify the DC - m = new(dns.Msg) - m.SetQuestion("foo.node.dc1.consul.", dns.TypeANY) - - c = new(dns.Client) - in, _, err = c.Exchange(m, a.DNSAddr()) - require.NoError(t, err) - require.Len(t, in.Answer, 2) - require.Len(t, in.Extra, 0) - - aRec, ok = in.Answer[0].(*dns.A) - require.True(t, ok, "First answer is not an A record") - require.Equal(t, "127.0.0.1", aRec.A.String()) - require.Equal(t, uint32(0), aRec.Hdr.Ttl) - - _, ok = in.Answer[1].(*dns.TXT) - require.True(t, ok, "Second answer is not a TXT record") - - // lookup a non-existing node, we should receive a SOA - m = new(dns.Msg) - m.SetQuestion("nofoo.node.dc1.consul.", dns.TypeANY) - - c = new(dns.Client) - in, _, err = c.Exchange(m, a.DNSAddr()) - require.NoError(t, err) - require.Len(t, in.Ns, 1) - soaRec, ok := in.Ns[0].(*dns.SOA) - require.True(t, ok, "NS RR is not a SOA record") - require.Equal(t, uint32(0), soaRec.Hdr.Ttl) -} - -func TestDNS_CaseInsensitiveNodeLookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register node - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "Foo", - Address: "127.0.0.1", - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - m := new(dns.Msg) - m.SetQuestion("fOO.node.dc1.consul.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("empty lookup: %#v", in) - } -} - -func TestDNS_NodeLookup_PeriodName(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register node with period in name - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo.bar", - Address: "127.0.0.1", - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - m := new(dns.Msg) - m.SetQuestion("foo.bar.node.consul.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - aRec, ok := in.Answer[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if aRec.A.String() != "127.0.0.1" { - t.Fatalf("Bad: %#v", in.Answer[0]) - } -} - -func TestDNS_NodeLookup_AAAA(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register node - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "::4242:4242", - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - m := new(dns.Msg) - m.SetQuestion("bar.node.consul.", dns.TypeAAAA) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - aRec, ok := in.Answer[0].(*dns.AAAA) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if aRec.AAAA.String() != "::4242:4242" { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if aRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } -} - -func TestDNSCycleRecursorCheck(t *testing.T) { +func TestDNS_CycleRecursorCheck(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - t.Parallel() // Start a DNS recursor that returns a SERVFAIL server1 := makeRecursor(t, dns.Msg{ MsgHdr: dns.MsgHdr{Rcode: dns.RcodeServerFailure}, @@ -482,14 +261,14 @@ func TestDNSCycleRecursorCheck(t *testing.T) { A: []byte{0xAC, 0x15, 0x2D, 0x43}, // 172 , 21, 45, 67 }, } + require.NotNil(t, in) require.Equal(t, wantAnswer, in.Answer) } -func TestDNSCycleRecursorCheckAllFail(t *testing.T) { +func TestDNS_CycleRecursorCheckAllFail(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - t.Parallel() // Start 3 DNS recursors that returns a REFUSED status server1 := makeRecursor(t, dns.Msg{ MsgHdr: dns.MsgHdr{Rcode: dns.RcodeRefused}, @@ -513,36 +292,27 @@ func TestDNSCycleRecursorCheckAllFail(t *testing.T) { m.SetQuestion("google.com.", dns.TypeA) // Agent request client := new(dns.Client) - in, _, _ := client.Exchange(m, agent.DNSAddr()) + in, _, err := client.Exchange(m, agent.DNSAddr()) + require.NoError(t, err) // Verify if we hit SERVFAIL from Consul + require.NotNil(t, in) require.Equal(t, dns.RcodeServerFailure, in.Rcode) } -func TestDNS_NodeLookup_CNAME(t *testing.T) { + +func TestDNS_EDNS0(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - t.Parallel() - recursor := makeRecursor(t, dns.Msg{ - Answer: []dns.RR{ - dnsCNAME("www.google.com", "google.com"), - dnsA("google.com", "1.2.3.4"), - dnsTXT("google.com", []string{"my_txt_value"}), - }, - }) - defer recursor.Shutdown() - - a := NewTestAgent(t, ` - recursors = ["`+recursor.Addr+`"] - `) + a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") // Register node args := &structs.RegisterRequest{ Datacenter: "dc1", - Node: "google", - Address: "www.google.com", + Node: "foo", + Address: "127.0.0.2", } var out struct{} @@ -551,8 +321,8 @@ func TestDNS_NodeLookup_CNAME(t *testing.T) { } m := new(dns.Msg) - m.SetQuestion("google.node.consul.", dns.TypeANY) - m.SetEdns0(8192, true) + m.SetEdns0(12345, true) + m.SetQuestion("foo.node.dc1.consul.", dns.TypeANY) c := new(dns.Client) in, _, err := c.Exchange(m, a.DNSAddr()) @@ -560,197 +330,313 @@ func TestDNS_NodeLookup_CNAME(t *testing.T) { t.Fatalf("err: %v", err) } - wantAnswer := []dns.RR{ - &dns.CNAME{ - Hdr: dns.RR_Header{Name: "google.node.consul.", Rrtype: dns.TypeCNAME, Class: dns.ClassINET, Ttl: 0, Rdlength: 0x10}, - Target: "www.google.com.", - }, - &dns.CNAME{ - Hdr: dns.RR_Header{Name: "www.google.com.", Rrtype: dns.TypeCNAME, Class: dns.ClassINET, Rdlength: 0x2}, - Target: "google.com.", - }, - &dns.A{ - Hdr: dns.RR_Header{Name: "google.com.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4}, - A: []byte{0x1, 0x2, 0x3, 0x4}, // 1.2.3.4 - }, - &dns.TXT{ - Hdr: dns.RR_Header{Name: "google.com.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Rdlength: 0xd}, - Txt: []string{"my_txt_value"}, - }, + if len(in.Answer) != 1 { + t.Fatalf("empty lookup: %#v", in) + } + edns := in.IsEdns0() + if edns == nil { + t.Fatalf("empty edns: %#v", in) + } + if edns.UDPSize() != 12345 { + t.Fatalf("bad edns size: %d", edns.UDPSize()) } - require.Equal(t, wantAnswer, in.Answer) } -func TestDNS_NodeLookup_TXT(t *testing.T) { +func TestDNS_EDNS0_ECS(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - a := NewTestAgent(t, ``) + a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "google", - Address: "127.0.0.1", - NodeMeta: map[string]string{ - "rfc1035-00": "value0", - "key0": "value1", - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - m := new(dns.Msg) - m.SetQuestion("google.node.consul.", dns.TypeTXT) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Port: 12345, + }, + } - // Should have the 1 TXT record reply - if len(in.Answer) != 2 { - t.Fatalf("Bad: %#v", in) + var out struct{} + require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) } - txtRec, ok := in.Answer[0].(*dns.TXT) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if len(txtRec.Txt) != 1 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if txtRec.Txt[0] != "value0" && txtRec.Txt[0] != "key0=value1" { - t.Fatalf("Bad: %#v", in.Answer[0]) + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + require.NoError(t, a.RPC(context.Background(), "PreparedQuery.Apply", args, &id)) } -} -func TestDNS_NodeLookup_TXT_DontSuppress(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") + cases := []struct { + Name string + Question string + SubnetAddr string + SourceNetmask uint8 + ExpectedScope uint8 + }{ + {"global", "db.service.consul.", "198.18.0.1", 32, 0}, + {"query", "test.query.consul.", "198.18.0.1", 32, 32}, + {"query-subnet", "test.query.consul.", "198.18.0.0", 21, 21}, } - a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = false }`) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") + for _, tc := range cases { + t.Run(tc.Name, func(t *testing.T) { + c := new(dns.Client) + // Query the service directly - should have a globally valid scope (0) + m := new(dns.Msg) + edns := new(dns.OPT) + edns.Hdr.Name = "." + edns.Hdr.Rrtype = dns.TypeOPT + edns.SetUDPSize(12345) + edns.SetDo(true) + subnetOp := new(dns.EDNS0_SUBNET) + subnetOp.Code = dns.EDNS0SUBNET + subnetOp.Family = 1 + subnetOp.SourceNetmask = tc.SourceNetmask + subnetOp.Address = net.ParseIP(tc.SubnetAddr) + edns.Option = append(edns.Option, subnetOp) + m.Extra = append(m.Extra, edns) + m.SetQuestion(tc.Question, dns.TypeA) - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "google", - Address: "127.0.0.1", - NodeMeta: map[string]string{ - "rfc1035-00": "value0", - "key0": "value1", - }, + in, _, err := c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + require.Len(t, in.Answer, 1) + aRec, ok := in.Answer[0].(*dns.A) + require.True(t, ok) + require.Equal(t, "127.0.0.1", aRec.A.String()) + + optRR := in.IsEdns0() + require.NotNil(t, optRR) + require.Len(t, optRR.Option, 1) + + subnet, ok := optRR.Option[0].(*dns.EDNS0_SUBNET) + require.True(t, ok) + require.Equal(t, uint16(1), subnet.Family) + require.Equal(t, tc.SourceNetmask, subnet.SourceNetmask) + require.Equal(t, tc.ExpectedScope, subnet.SourceScope) + require.Equal(t, net.ParseIP(tc.SubnetAddr), subnet.Address) + }) } +} - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) +func TestDNS_SOA_Settings(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") } - m := new(dns.Msg) - m.SetQuestion("google.node.consul.", dns.TypeTXT) + testSoaWithConfig := func(config string, ttl, expire, refresh, retry uint) { + a := NewTestAgent(t, config) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } + // lookup a non-existing node, we should receive a SOA + m := new(dns.Msg) + m.SetQuestion("nofoo.node.dc1.consul.", dns.TypeANY) - // Should have the 1 TXT record reply - if len(in.Answer) != 2 { - t.Fatalf("Bad: %#v", in) + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.NoError(t, err) + require.Len(t, in.Ns, 1) + soaRec, ok := in.Ns[0].(*dns.SOA) + require.True(t, ok, "NS RR is not a SOA record") + require.Equal(t, uint32(ttl), soaRec.Minttl) + require.Equal(t, uint32(expire), soaRec.Expire) + require.Equal(t, uint32(refresh), soaRec.Refresh) + require.Equal(t, uint32(retry), soaRec.Retry) + require.Equal(t, uint32(ttl), soaRec.Hdr.Ttl) } - txtRec, ok := in.Answer[0].(*dns.TXT) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if len(txtRec.Txt) != 1 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if txtRec.Txt[0] != "value0" && txtRec.Txt[0] != "key0=value1" { - t.Fatalf("Bad: %#v", in.Answer[0]) - } + // Default configuration + testSoaWithConfig("", 0, 86400, 3600, 600) + // Override all settings + testSoaWithConfig("dns_config={soa={min_ttl=60,expire=43200,refresh=1800,retry=300}} ", 60, 43200, 1800, 300) + // Override partial settings + testSoaWithConfig("dns_config={soa={min_ttl=60,expire=43200}} ", 60, 43200, 3600, 600) + // Override partial settings, part II + testSoaWithConfig("dns_config={soa={refresh=1800,retry=300}} ", 0, 86400, 1800, 300) } -func TestDNS_NodeLookup_ANY(t *testing.T) { +func TestDNS_VirtualIPLookup(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - a := NewTestAgent(t, ``) + a := StartTestAgent(t, TestAgent{HCL: "", Overrides: `peering = { test_allow_peer_registrations = true } log_level = "debug"`}) defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "127.0.0.1", - NodeMeta: map[string]string{ - "key": "value", - }, - } + server, ok := a.delegate.(*consul.Server) + require.True(t, ok) - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) + // The proxy service will not receive a virtual IP if the server is not assigning virtual IPs yet. + retry.Run(t, func(r *retry.R) { + _, entry, err := server.FSM().State().SystemMetadataGet(nil, structs.SystemMetadataVirtualIPsEnabled) + require.NoError(r, err) + require.NotNil(r, entry) + }) + + type testCase struct { + name string + reg *structs.RegisterRequest + question string + expect string } - m := new(dns.Msg) - m.SetQuestion("bar.node.consul.", dns.TypeANY) + run := func(t *testing.T, tc testCase) { + var out struct{} + require.Nil(t, a.RPC(context.Background(), "Catalog.Register", tc.reg, &out)) - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) + m := new(dns.Msg) + m.SetQuestion(tc.question, dns.TypeA) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + require.Nil(t, err) + require.Len(t, in.Answer, 1) + + aRec, ok := in.Answer[0].(*dns.A) + require.True(t, ok) + require.Equal(t, tc.expect, aRec.A.String()) } - wantAnswer := []dns.RR{ - &dns.A{ - Hdr: dns.RR_Header{Name: "bar.node.consul.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4}, - A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1 + tt := []testCase{ + { + name: "local query", + reg: &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.55", + Service: &structs.NodeService{ + Kind: structs.ServiceKindConnectProxy, + Service: "web-proxy", + Port: 12345, + Proxy: structs.ConnectProxyConfig{ + DestinationServiceName: "db", + }, + }, + }, + question: "db.virtual.consul.", + expect: "240.0.0.1", }, - &dns.TXT{ - Hdr: dns.RR_Header{Name: "bar.node.consul.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Rdlength: 0xa}, - Txt: []string{"key=value"}, + { + name: "query for imported service", + reg: &structs.RegisterRequest{ + PeerName: "frontend", + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.55", + Service: &structs.NodeService{ + PeerName: "frontend", + Kind: structs.ServiceKindConnectProxy, + Service: "web-proxy", + Port: 12345, + Proxy: structs.ConnectProxyConfig{ + DestinationServiceName: "db", + }, + }, + }, + question: "db.virtual.frontend.consul.", + expect: "240.0.0.2", }, } - require.Equal(t, wantAnswer, in.Answer) + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + run(t, tc) + }) + } } -func TestDNS_NodeLookup_ANY_DontSuppressTXT(t *testing.T) { +func TestDNS_InifiniteRecursion(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = false }`) + // This test should not create an infinite recursion + a := NewTestAgent(t, ` + domain = "CONSUL." + node_name = "test node" + `) defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "127.0.0.1", - NodeMeta: map[string]string{ - "key": "value", - }, + // Register the initial node with a service + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "web", + Address: "web.service.consul.", + Service: &structs.NodeService{ + Service: "web", + Port: 12345, + Address: "web.service.consul.", + }, + } + + var out struct{} + if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } } - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) + // Look up the service directly + questions := []string{ + "web.service.consul.", + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeA) + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) < 1 { + t.Fatalf("Bad: %#v", in) + } + aRec, ok := in.Answer[0].(*dns.CNAME) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if aRec.Target != "web.service.consul." { + t.Fatalf("Bad: %#v, target:=%s", aRec, aRec.Target) + } + } +} + +func TestDNS_NSRecords(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") } + a := NewTestAgent(t, ` + domain = "CONSUL." + node_name = "server1" + `) + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + m := new(dns.Msg) - m.SetQuestion("bar.node.consul.", dns.TypeANY) + m.SetQuestion("something.node.consul.", dns.TypeNS) c := new(dns.Client) in, _, err := c.Exchange(m, a.DNSAddr()) @@ -759,83 +645,87 @@ func TestDNS_NodeLookup_ANY_DontSuppressTXT(t *testing.T) { } wantAnswer := []dns.RR{ - &dns.A{ - Hdr: dns.RR_Header{Name: "bar.node.consul.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4}, - A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1 + &dns.NS{ + Hdr: dns.RR_Header{Name: "consul.", Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 0, Rdlength: 0x13}, + Ns: "server1.node.dc1.consul.", }, - &dns.TXT{ - Hdr: dns.RR_Header{Name: "bar.node.consul.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Rdlength: 0xa}, - Txt: []string{"key=value"}, + } + require.Equal(t, wantAnswer, in.Answer, "answer") + wantExtra := []dns.RR{ + &dns.A{ + Hdr: dns.RR_Header{Name: "server1.node.dc1.consul.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4, Ttl: 0}, + A: net.ParseIP("127.0.0.1").To4(), }, } - require.Equal(t, wantAnswer, in.Answer) + + require.Equal(t, wantExtra, in.Extra, "extra") } -func TestDNS_NodeLookup_A_SuppressTXT(t *testing.T) { +func TestDNS_AltDomain_NSRecords(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = false }`) + a := NewTestAgent(t, ` + domain = "CONSUL." + node_name = "server1" + alt_domain = "test-domain." + `) defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") + testrpc.WaitForTestAgent(t, a.RPC, "dc1") - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "127.0.0.1", - NodeMeta: map[string]string{ - "key": "value", - }, + questions := []struct { + ask string + domain string + wantDomain string + }{ + {"something.node.consul.", "consul.", "server1.node.dc1.consul."}, + {"something.node.test-domain.", "test-domain.", "server1.node.dc1.test-domain."}, } - var out struct{} - require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question.ask, dns.TypeNS) - m := new(dns.Msg) - m.SetQuestion("bar.node.consul.", dns.TypeA) + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - require.NoError(t, err) + wantAnswer := []dns.RR{ + &dns.NS{ + Hdr: dns.RR_Header{Name: question.domain, Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 0, Rdlength: 0x13}, + Ns: question.wantDomain, + }, + } + require.Equal(t, wantAnswer, in.Answer, "answer") + wantExtra := []dns.RR{ + &dns.A{ + Hdr: dns.RR_Header{Name: question.wantDomain, Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4, Ttl: 0}, + A: net.ParseIP("127.0.0.1").To4(), + }, + } - wantAnswer := []dns.RR{ - &dns.A{ - Hdr: dns.RR_Header{Name: "bar.node.consul.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4}, - A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1 - }, + require.Equal(t, wantExtra, in.Extra, "extra") } - require.Equal(t, wantAnswer, in.Answer) - - // ensure TXT RR suppression - require.Len(t, in.Extra, 0) } -func TestDNS_EDNS0(t *testing.T) { +func TestDNS_NSRecords_IPV6(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - t.Parallel() - a := NewTestAgent(t, "") + a := NewTestAgent(t, ` + domain = "CONSUL." + node_name = "server1" + advertise_addr = "::1" + `) defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register node - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.2", - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } + testrpc.WaitForTestAgent(t, a.RPC, "dc1") m := new(dns.Msg) - m.SetEdns0(12345, true) - m.SetQuestion("foo.node.dc1.consul.", dns.TypeANY) + m.SetQuestion("server1.node.dc1.consul.", dns.TypeNS) c := new(dns.Client) in, _, err := c.Exchange(m, a.DNSAddr()) @@ -843,45 +733,83 @@ func TestDNS_EDNS0(t *testing.T) { t.Fatalf("err: %v", err) } - if len(in.Answer) != 1 { - t.Fatalf("empty lookup: %#v", in) - } - edns := in.IsEdns0() - if edns == nil { - t.Fatalf("empty edns: %#v", in) + wantAnswer := []dns.RR{ + &dns.NS{ + Hdr: dns.RR_Header{Name: "consul.", Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 0, Rdlength: 0x2}, + Ns: "server1.node.dc1.consul.", + }, } - if edns.UDPSize() != 12345 { - t.Fatalf("bad edns size: %d", edns.UDPSize()) + require.Equal(t, wantAnswer, in.Answer, "answer") + wantExtra := []dns.RR{ + &dns.AAAA{ + Hdr: dns.RR_Header{Name: "server1.node.dc1.consul.", Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Rdlength: 0x10, Ttl: 0}, + AAAA: net.ParseIP("::1"), + }, } + + require.Equal(t, wantExtra, in.Extra, "extra") } -func TestDNS_EDNS0_ECS(t *testing.T) { +func TestDNS_AltDomain_NSRecords_IPV6(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - t.Parallel() - a := NewTestAgent(t, "") + a := NewTestAgent(t, ` + domain = "CONSUL." + node_name = "server1" + advertise_addr = "::1" + alt_domain = "test-domain." + `) defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") + testrpc.WaitForTestAgent(t, a.RPC, "dc1") - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, + questions := []struct { + ask string + domain string + wantDomain string + }{ + {"server1.node.dc1.consul.", "consul.", "server1.node.dc1.consul."}, + {"server1.node.dc1.test-domain.", "test-domain.", "server1.node.dc1.test-domain."}, + } + + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question.ask, dns.TypeNS) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + wantAnswer := []dns.RR{ + &dns.NS{ + Hdr: dns.RR_Header{Name: question.domain, Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 0, Rdlength: 0x2}, + Ns: question.wantDomain, + }, + } + require.Equal(t, wantAnswer, in.Answer, "answer") + wantExtra := []dns.RR{ + &dns.AAAA{ + Hdr: dns.RR_Header{Name: question.wantDomain, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Rdlength: 0x10, Ttl: 0}, + AAAA: net.ParseIP("::1"), }, } - var out struct{} - require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) + require.Equal(t, wantExtra, in.Extra, "extra") + } +} + +func TestDNS_Lookup_TaggedIPAddresses(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") } + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + // Register an equivalent prepared query. var id string { @@ -898,5615 +826,701 @@ func TestDNS_EDNS0_ECS(t *testing.T) { require.NoError(t, a.RPC(context.Background(), "PreparedQuery.Apply", args, &id)) } - cases := []struct { - Name string - Question string - SubnetAddr string - SourceNetmask uint8 - ExpectedScope uint8 - }{ - {"global", "db.service.consul.", "198.18.0.1", 32, 0}, - {"query", "test.query.consul.", "198.18.0.1", 32, 32}, - {"query-subnet", "test.query.consul.", "198.18.0.0", 21, 21}, - } - - for _, tc := range cases { - t.Run(tc.Name, func(t *testing.T) { - c := new(dns.Client) - // Query the service directly - should have a globally valid scope (0) - m := new(dns.Msg) - edns := new(dns.OPT) - edns.Hdr.Name = "." - edns.Hdr.Rrtype = dns.TypeOPT - edns.SetUDPSize(12345) - edns.SetDo(true) - subnetOp := new(dns.EDNS0_SUBNET) - subnetOp.Code = dns.EDNS0SUBNET - subnetOp.Family = 1 - subnetOp.SourceNetmask = tc.SourceNetmask - subnetOp.Address = net.ParseIP(tc.SubnetAddr) - edns.Option = append(edns.Option, subnetOp) - m.Extra = append(m.Extra, edns) - m.SetQuestion(tc.Question, dns.TypeA) - - in, _, err := c.Exchange(m, a.DNSAddr()) - require.NoError(t, err) - require.Len(t, in.Answer, 1) - aRec, ok := in.Answer[0].(*dns.A) - require.True(t, ok) - require.Equal(t, "127.0.0.1", aRec.A.String()) - - optRR := in.IsEdns0() - require.NotNil(t, optRR) - require.Len(t, optRR.Option, 1) - - subnet, ok := optRR.Option[0].(*dns.EDNS0_SUBNET) - require.True(t, ok) - require.Equal(t, uint16(1), subnet.Family) - require.Equal(t, tc.SourceNetmask, subnet.SourceNetmask) - require.Equal(t, tc.ExpectedScope, subnet.SourceScope) - require.Equal(t, net.ParseIP(tc.SubnetAddr), subnet.Address) - }) - } -} + type testCase struct { + nodeAddress string + nodeTaggedAddresses map[string]string + serviceAddress string + serviceTaggedAddresses map[string]structs.ServiceAddress -func TestDNS_ReverseLookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") + expectedServiceIPv4Address string + expectedServiceIPv6Address string + expectedNodeIPv4Address string + expectedNodeIPv6Address string } - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") + cases := map[string]testCase{ + "simple-ipv4": { + serviceAddress: "127.0.0.2", + nodeAddress: "127.0.0.1", - // Register node - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo2", - Address: "127.0.0.2", - } + expectedServiceIPv4Address: "127.0.0.2", + expectedServiceIPv6Address: "", + expectedNodeIPv4Address: "127.0.0.1", + expectedNodeIPv6Address: "", + }, + "simple-ipv6": { + serviceAddress: "::2", + nodeAddress: "::1", - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } + expectedServiceIPv6Address: "::2", + expectedServiceIPv4Address: "", + expectedNodeIPv6Address: "::1", + expectedNodeIPv4Address: "", + }, + "ipv4-with-tagged-ipv6": { + serviceAddress: "127.0.0.2", + nodeAddress: "127.0.0.1", - m := new(dns.Msg) - m.SetQuestion("2.0.0.127.in-addr.arpa.", dns.TypeANY) + serviceTaggedAddresses: map[string]structs.ServiceAddress{ + structs.TaggedAddressLANIPv6: {Address: "::2"}, + }, + nodeTaggedAddresses: map[string]string{ + structs.TaggedAddressLANIPv6: "::1", + }, - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - ptrRec, ok := in.Answer[0].(*dns.PTR) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if ptrRec.Ptr != "foo2.node.dc1.consul." { - t.Fatalf("Bad: %#v", ptrRec) - } -} - -func TestDNS_ReverseLookup_CustomDomain(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - domain = "custom" - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register node - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo2", - Address: "127.0.0.2", - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - m := new(dns.Msg) - m.SetQuestion("2.0.0.127.in-addr.arpa.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - ptrRec, ok := in.Answer[0].(*dns.PTR) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if ptrRec.Ptr != "foo2.node.dc1.custom." { - t.Fatalf("Bad: %#v", ptrRec) - } -} - -func TestDNS_ReverseLookup_IPV6(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register node - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "::4242:4242", - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - m := new(dns.Msg) - m.SetQuestion("2.4.2.4.2.4.2.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - ptrRec, ok := in.Answer[0].(*dns.PTR) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if ptrRec.Ptr != "bar.node.dc1.consul." { - t.Fatalf("Bad: %#v", ptrRec) - } -} - -func TestDNS_ServiceReverseLookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - Address: "127.0.0.2", - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - m := new(dns.Msg) - m.SetQuestion("2.0.0.127.in-addr.arpa.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - ptrRec, ok := in.Answer[0].(*dns.PTR) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if ptrRec.Ptr != serviceCanonicalDNSName("db", "service", "dc1", "consul", nil)+"." { - t.Fatalf("Bad: %#v", ptrRec) - } -} - -func TestDNS_ServiceReverseLookup_IPV6(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "2001:db8::1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - Address: "2001:db8::ff00:42:8329", - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - m := new(dns.Msg) - m.SetQuestion("9.2.3.8.2.4.0.0.0.0.f.f.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - ptrRec, ok := in.Answer[0].(*dns.PTR) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if ptrRec.Ptr != serviceCanonicalDNSName("db", "service", "dc1", "consul", nil)+"." { - t.Fatalf("Bad: %#v", ptrRec) - } -} - -func TestDNS_ServiceReverseLookup_CustomDomain(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - domain = "custom" - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - Address: "127.0.0.2", - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - m := new(dns.Msg) - m.SetQuestion("2.0.0.127.in-addr.arpa.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - ptrRec, ok := in.Answer[0].(*dns.PTR) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if ptrRec.Ptr != serviceCanonicalDNSName("db", "service", "dc1", "custom", nil)+"." { - t.Fatalf("Bad: %#v", ptrRec) - } -} - -func TestDNS_SOA_Settings(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - testSoaWithConfig := func(config string, ttl, expire, refresh, retry uint) { - a := NewTestAgent(t, config) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // lookup a non-existing node, we should receive a SOA - m := new(dns.Msg) - m.SetQuestion("nofoo.node.dc1.consul.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - require.NoError(t, err) - require.Len(t, in.Ns, 1) - soaRec, ok := in.Ns[0].(*dns.SOA) - require.True(t, ok, "NS RR is not a SOA record") - require.Equal(t, uint32(ttl), soaRec.Minttl) - require.Equal(t, uint32(expire), soaRec.Expire) - require.Equal(t, uint32(refresh), soaRec.Refresh) - require.Equal(t, uint32(retry), soaRec.Retry) - require.Equal(t, uint32(ttl), soaRec.Hdr.Ttl) - } - // Default configuration - testSoaWithConfig("", 0, 86400, 3600, 600) - // Override all settings - testSoaWithConfig("dns_config={soa={min_ttl=60,expire=43200,refresh=1800,retry=300}}", 60, 43200, 1800, 300) - // Override partial settings - testSoaWithConfig("dns_config={soa={min_ttl=60,expire=43200}}", 60, 43200, 3600, 600) - // Override partial settings, part II - testSoaWithConfig("dns_config={soa={refresh=1800,retry=300}}", 0, 86400, 1800, 300) -} - -func TestDNS_ServiceReverseLookupNodeAddress(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - Address: "127.0.0.1", - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - m := new(dns.Msg) - m.SetQuestion("1.0.0.127.in-addr.arpa.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - ptrRec, ok := in.Answer[0].(*dns.PTR) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if ptrRec.Ptr != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", ptrRec) - } -} - -func TestDNS_ServiceLookupNoMultiCNAME(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "198.18.0.1", - Service: &structs.NodeService{ - Service: "db", - Port: 12345, - Address: "foo.node.consul", - }, - } - - var out struct{} - require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) - } - - // Register a second node node with the same service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "198.18.0.2", - Service: &structs.NodeService{ - Service: "db", - Port: 12345, - Address: "bar.node.consul", - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - m := new(dns.Msg) - m.SetQuestion("db.service.consul.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - require.NoError(t, err) - - // expect a CNAME and an A RR - require.Len(t, in.Answer, 2) - require.IsType(t, &dns.CNAME{}, in.Answer[0]) - require.IsType(t, &dns.A{}, in.Answer[1]) -} - -func TestDNS_ServiceLookupPreferNoCNAME(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "198.18.0.1", - Service: &structs.NodeService{ - Service: "db", - Port: 12345, - Address: "198.18.0.1", - }, - } - - var out struct{} - require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) - } - - // Register a second node node with the same service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "198.18.0.2", - Service: &structs.NodeService{ - Service: "db", - Port: 12345, - Address: "bar.node.consul", - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - m := new(dns.Msg) - m.SetQuestion("db.service.consul.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - require.NoError(t, err) - - // expect a CNAME and an A RR - require.Len(t, in.Answer, 1) - aRec, ok := in.Answer[0].(*dns.A) - require.Truef(t, ok, "Not an A RR") - - require.Equal(t, "db.service.consul.", aRec.Hdr.Name) - require.Equal(t, "198.18.0.1", aRec.A.String()) -} - -func TestDNS_ServiceLookupMultiAddrNoCNAME(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "198.18.0.1", - Service: &structs.NodeService{ - Service: "db", - Port: 12345, - Address: "198.18.0.1", - }, - } - - var out struct{} - require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) - } - - // Register a second node node with the same service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "198.18.0.2", - Service: &structs.NodeService{ - Service: "db", - Port: 12345, - Address: "bar.node.consul", - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register a second node node with the same service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "baz", - Address: "198.18.0.3", - Service: &structs.NodeService{ - Service: "db", - Port: 12345, - Address: "198.18.0.3", - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - m := new(dns.Msg) - m.SetQuestion("db.service.consul.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - require.NoError(t, err) - - // expect a CNAME and an A RR - require.Len(t, in.Answer, 2) - require.IsType(t, &dns.A{}, in.Answer[0]) - require.IsType(t, &dns.A{}, in.Answer[1]) -} - -func TestDNS_ServiceLookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []string{ - "db.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - - aRec, ok := in.Extra[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Name != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.A.String() != "127.0.0.1" { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - } - - // Lookup a non-existing service/query, we should receive an SOA. - questions = []string{ - "nodb.service.consul.", - "nope.query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Ns) != 1 { - t.Fatalf("Bad: %#v", in) - } - - soaRec, ok := in.Ns[0].(*dns.SOA) - if !ok { - t.Fatalf("Bad: %#v", in.Ns[0]) - } - if soaRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Ns[0]) - } - - } -} - -func TestDNS_ServiceLookupWithInternalServiceAddress(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - node_name = "my.test-node" - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - // The service is using the consul DNS name as service address - // which triggers a lookup loop and a subsequent stack overflow - // crash. - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Address: "db.service.consul", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - // Looking up the service should not trigger a loop - m := new(dns.Msg) - m.SetQuestion("db.service.consul.", dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - wantAnswer := []dns.RR{ - &dns.SRV{ - Hdr: dns.RR_Header{Name: "db.service.consul.", Rrtype: 0x21, Class: 0x1, Rdlength: 0x1b}, - Priority: 0x1, - Weight: 0x1, - Port: 12345, - Target: "foo.node.dc1.consul.", - }, - } - require.Equal(t, wantAnswer, in.Answer, "answer") - wantExtra := []dns.RR{ - &dns.A{ - Hdr: dns.RR_Header{Name: "foo.node.dc1.consul.", Rrtype: 0x1, Class: 0x1, Rdlength: 0x4}, - A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1 - }, - } - require.Equal(t, wantExtra, in.Extra, "extra") -} - -func TestDNS_ConnectServiceLookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register - { - args := structs.TestRegisterRequestProxy(t) - args.Address = "127.0.0.55" - args.Service.Proxy.DestinationServiceName = "db" - args.Service.Address = "" - args.Service.Port = 12345 - var out struct{} - require.Nil(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) - } - - // Look up the service - questions := []string{ - "db.connect.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - require.Nil(t, err) - require.Len(t, in.Answer, 1) - - srvRec, ok := in.Answer[0].(*dns.SRV) - require.True(t, ok) - require.Equal(t, uint16(12345), srvRec.Port) - require.Equal(t, "foo.node.dc1.consul.", srvRec.Target) - require.Equal(t, uint32(0), srvRec.Hdr.Ttl) - - cnameRec, ok := in.Extra[0].(*dns.A) - require.True(t, ok) - require.Equal(t, "foo.node.dc1.consul.", cnameRec.Hdr.Name) - require.Equal(t, uint32(0), srvRec.Hdr.Ttl) - require.Equal(t, "127.0.0.55", cnameRec.A.String()) - } -} - -func TestDNS_VirtualIPLookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - - a := StartTestAgent(t, TestAgent{HCL: ``, Overrides: `peering = { test_allow_peer_registrations = true }`}) - defer a.Shutdown() - - testrpc.WaitForLeader(t, a.RPC, "dc1") - - server, ok := a.delegate.(*consul.Server) - require.True(t, ok) - - // The proxy service will not receive a virtual IP if the server is not assigning virtual IPs yet. - retry.Run(t, func(r *retry.R) { - _, entry, err := server.FSM().State().SystemMetadataGet(nil, structs.SystemMetadataVirtualIPsEnabled) - require.NoError(r, err) - require.NotNil(r, entry) - }) - - type testCase struct { - name string - reg *structs.RegisterRequest - question string - expect string - } - - run := func(t *testing.T, tc testCase) { - var out struct{} - require.Nil(t, a.RPC(context.Background(), "Catalog.Register", tc.reg, &out)) - - m := new(dns.Msg) - m.SetQuestion(tc.question, dns.TypeA) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - require.Nil(t, err) - require.Len(t, in.Answer, 1) - - aRec, ok := in.Answer[0].(*dns.A) - require.True(t, ok) - require.Equal(t, tc.expect, aRec.A.String()) - } - - tt := []testCase{ - { - name: "local query", - reg: &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.55", - Service: &structs.NodeService{ - Kind: structs.ServiceKindConnectProxy, - Service: "web-proxy", - Port: 12345, - Proxy: structs.ConnectProxyConfig{ - DestinationServiceName: "db", - }, - }, - }, - question: "db.virtual.consul.", - expect: "240.0.0.1", - }, - { - name: "query for imported service", - reg: &structs.RegisterRequest{ - PeerName: "frontend", - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.55", - Service: &structs.NodeService{ - PeerName: "frontend", - Kind: structs.ServiceKindConnectProxy, - Service: "web-proxy", - Port: 12345, - Proxy: structs.ConnectProxyConfig{ - DestinationServiceName: "db", - }, - }, - }, - question: "db.virtual.frontend.consul.", - expect: "240.0.0.2", - }, - } - - for _, tc := range tt { - t.Run(tc.name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestDNS_IngressServiceLookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register ingress-gateway service - { - args := structs.TestRegisterIngressGateway(t) - var out struct{} - require.Nil(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) - } - - // Register db service - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Address: "", - Port: 80, - }, - } - - var out struct{} - require.Nil(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) - } - - // Register proxy-defaults with 'http' protocol - { - req := structs.ConfigEntryRequest{ - Op: structs.ConfigEntryUpsert, - Datacenter: "dc1", - Entry: &structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, - Config: map[string]interface{}{ - "protocol": "http", - }, - }, - WriteRequest: structs.WriteRequest{Token: "root"}, - } - var out bool - require.Nil(t, a.RPC(context.Background(), "ConfigEntry.Apply", req, &out)) - require.True(t, out) - } - - // Register ingress-gateway config entry - { - args := &structs.IngressGatewayConfigEntry{ - Name: "ingress-gateway", - Kind: structs.IngressGateway, - Listeners: []structs.IngressListener{ - { - Port: 8888, - Protocol: "http", - Services: []structs.IngressService{ - {Name: "db"}, - {Name: "api"}, - }, - }, - }, - } - - req := structs.ConfigEntryRequest{ - Op: structs.ConfigEntryUpsert, - Datacenter: "dc1", - Entry: args, - } - var out bool - require.Nil(t, a.RPC(context.Background(), "ConfigEntry.Apply", req, &out)) - require.True(t, out) - } - - // Look up the service - questions := []string{ - "api.ingress.consul.", - "api.ingress.dc1.consul.", - "db.ingress.consul.", - "db.ingress.dc1.consul.", - } - for _, question := range questions { - t.Run(question, func(t *testing.T) { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeA) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - require.Nil(t, err) - require.Len(t, in.Answer, 1) - - cnameRec, ok := in.Answer[0].(*dns.A) - require.True(t, ok) - require.Equal(t, question, cnameRec.Hdr.Name) - require.Equal(t, uint32(0), cnameRec.Hdr.Ttl) - require.Equal(t, "127.0.0.1", cnameRec.A.String()) - }) - } -} - -func TestDNS_ExternalServiceLookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with an external service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "www.google.com", - Service: &structs.NodeService{ - Service: "db", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service - questions := []string{ - "db.service.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "www.google.com." { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - } -} - -func TestDNS_InifiniteRecursion(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - // This test should not create an infinite recursion - t.Parallel() - a := NewTestAgent(t, ` - domain = "CONSUL." - node_name = "test node" - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register the initial node with a service - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "web", - Address: "web.service.consul.", - Service: &structs.NodeService{ - Service: "web", - Port: 12345, - Address: "web.service.consul.", - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly - questions := []string{ - "web.service.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeA) - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) < 1 { - t.Fatalf("Bad: %#v", in) - } - aRec, ok := in.Answer[0].(*dns.CNAME) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if aRec.Target != "web.service.consul." { - t.Fatalf("Bad: %#v, target:=%s", aRec, aRec.Target) - } - } -} - -func TestDNS_ExternalServiceToConsulCNAMELookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - domain = "CONSUL." - node_name = "test node" - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register the initial node with a service - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "web", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "web", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an external service pointing to the 'web' service - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "alias", - Address: "web.service.consul", - Service: &structs.NodeService{ - Service: "alias", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly - questions := []string{ - "alias.service.consul.", - "alias.service.CoNsUl.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "web.service.consul." { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - - if len(in.Extra) != 1 { - t.Fatalf("Bad: %#v", in) - } - - aRec, ok := in.Extra[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Name != "web.service.consul." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.A.String() != "127.0.0.1" { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - - } -} - -func TestDNS_NSRecords(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - domain = "CONSUL." - node_name = "server1" - `) - defer a.Shutdown() - testrpc.WaitForTestAgent(t, a.RPC, "dc1") - - m := new(dns.Msg) - m.SetQuestion("something.node.consul.", dns.TypeNS) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - wantAnswer := []dns.RR{ - &dns.NS{ - Hdr: dns.RR_Header{Name: "consul.", Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 0, Rdlength: 0x13}, - Ns: "server1.node.dc1.consul.", - }, - } - require.Equal(t, wantAnswer, in.Answer, "answer") - wantExtra := []dns.RR{ - &dns.A{ - Hdr: dns.RR_Header{Name: "server1.node.dc1.consul.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4, Ttl: 0}, - A: net.ParseIP("127.0.0.1").To4(), - }, - } - - require.Equal(t, wantExtra, in.Extra, "extra") -} - -func TestDNS_AltDomain_NSRecords(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - domain = "CONSUL." - node_name = "server1" - alt_domain = "test-domain." - `) - defer a.Shutdown() - testrpc.WaitForTestAgent(t, a.RPC, "dc1") - - questions := []struct { - ask string - domain string - wantDomain string - }{ - {"something.node.consul.", "consul.", "server1.node.dc1.consul."}, - {"something.node.test-domain.", "test-domain.", "server1.node.dc1.test-domain."}, - } - - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question.ask, dns.TypeNS) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - wantAnswer := []dns.RR{ - &dns.NS{ - Hdr: dns.RR_Header{Name: question.domain, Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 0, Rdlength: 0x13}, - Ns: question.wantDomain, - }, - } - require.Equal(t, wantAnswer, in.Answer, "answer") - wantExtra := []dns.RR{ - &dns.A{ - Hdr: dns.RR_Header{Name: question.wantDomain, Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4, Ttl: 0}, - A: net.ParseIP("127.0.0.1").To4(), - }, - } - - require.Equal(t, wantExtra, in.Extra, "extra") - } - -} - -func TestDNS_NSRecords_IPV6(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - domain = "CONSUL." - node_name = "server1" - advertise_addr = "::1" - `) - defer a.Shutdown() - testrpc.WaitForTestAgent(t, a.RPC, "dc1") - - m := new(dns.Msg) - m.SetQuestion("server1.node.dc1.consul.", dns.TypeNS) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - wantAnswer := []dns.RR{ - &dns.NS{ - Hdr: dns.RR_Header{Name: "consul.", Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 0, Rdlength: 0x2}, - Ns: "server1.node.dc1.consul.", - }, - } - require.Equal(t, wantAnswer, in.Answer, "answer") - wantExtra := []dns.RR{ - &dns.AAAA{ - Hdr: dns.RR_Header{Name: "server1.node.dc1.consul.", Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Rdlength: 0x10, Ttl: 0}, - AAAA: net.ParseIP("::1"), - }, - } - - require.Equal(t, wantExtra, in.Extra, "extra") - -} - -func TestDNS_AltDomain_NSRecords_IPV6(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - domain = "CONSUL." - node_name = "server1" - advertise_addr = "::1" - alt_domain = "test-domain." - `) - defer a.Shutdown() - testrpc.WaitForTestAgent(t, a.RPC, "dc1") - - questions := []struct { - ask string - domain string - wantDomain string - }{ - {"server1.node.dc1.consul.", "consul.", "server1.node.dc1.consul."}, - {"server1.node.dc1.test-domain.", "test-domain.", "server1.node.dc1.test-domain."}, - } - - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question.ask, dns.TypeNS) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - wantAnswer := []dns.RR{ - &dns.NS{ - Hdr: dns.RR_Header{Name: question.domain, Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 0, Rdlength: 0x2}, - Ns: question.wantDomain, - }, - } - require.Equal(t, wantAnswer, in.Answer, "answer") - wantExtra := []dns.RR{ - &dns.AAAA{ - Hdr: dns.RR_Header{Name: question.wantDomain, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Rdlength: 0x10, Ttl: 0}, - AAAA: net.ParseIP("::1"), - }, - } - - require.Equal(t, wantExtra, in.Extra, "extra") - } - -} - -func TestDNS_ExternalServiceToConsulCNAMENestedLookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - node_name = "test-node" - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register the initial node with a service - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "web", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "web", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an external service pointing to the 'web' service - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "alias", - Address: "web.service.consul", - Service: &structs.NodeService{ - Service: "alias", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an external service pointing to the 'alias' service - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "alias2", - Address: "alias.service.consul", - Service: &structs.NodeService{ - Service: "alias2", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly - questions := []string{ - "alias2.service.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "alias.service.consul." { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if len(in.Extra) != 2 { - t.Fatalf("Bad: %#v", in) - } - - cnameRec, ok := in.Extra[0].(*dns.CNAME) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if cnameRec.Hdr.Name != "alias.service.consul." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if cnameRec.Target != "web.service.consul." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if cnameRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - - aRec, ok := in.Extra[1].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[1]) - } - if aRec.Hdr.Name != "web.service.consul." { - t.Fatalf("Bad: %#v", in.Extra[1]) - } - if aRec.A.String() != "127.0.0.1" { - t.Fatalf("Bad: %#v", in.Extra[1]) - } - if aRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Extra[1]) - } - } -} - -func TestDNS_ServiceLookup_ServiceAddress_A(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Address: "127.0.0.2", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []string{ - "db.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "7f000002.addr.dc1.consul." { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - - aRec, ok := in.Extra[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Name != "7f000002.addr.dc1.consul." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.A.String() != "127.0.0.2" { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - } -} - -func TestDNS_AltDomain_ServiceLookup_ServiceAddress_A(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - alt_domain = "test-domain" - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Address: "127.0.0.2", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []struct { - ask string - wantDomain string - }{ - {"db.service.consul.", "consul."}, - {id + ".query.consul.", "consul."}, - {"db.service.test-domain.", "test-domain."}, - {id + ".query.test-domain.", "test-domain."}, - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question.ask, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "7f000002.addr.dc1."+question.wantDomain { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - - aRec, ok := in.Extra[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Name != "7f000002.addr.dc1."+question.wantDomain { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.A.String() != "127.0.0.2" { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - } -} - -func TestDNS_ServiceLookup_ServiceAddress_SRV(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - recursor := makeRecursor(t, dns.Msg{ - Answer: []dns.RR{ - dnsCNAME("www.google.com", "google.com"), - dnsA("google.com", "1.2.3.4"), - }, - }) - defer recursor.Shutdown() - - a := NewTestAgent(t, ` - recursors = ["`+recursor.Addr+`"] - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service whose address isn't an IP. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Address: "www.google.com", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - // Specify prepared query name containing "." to test - // since that is technically supported (though atypical). - var id string - preparedQueryName := "query.name.with.dots" - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: preparedQueryName, - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []string{ - "db.service.consul.", - id + ".query.consul.", - preparedQueryName + ".query.consul.", - fmt.Sprintf("_%s._tcp.query.consul.", id), - fmt.Sprintf("_%s._tcp.query.consul.", preparedQueryName), - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "www.google.com." { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - - // Should have google CNAME - cnRec, ok := in.Extra[0].(*dns.CNAME) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if cnRec.Target != "google.com." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - - // Check we recursively resolve - aRec, ok := in.Extra[1].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[1]) - } - if aRec.A.String() != "1.2.3.4" { - t.Fatalf("Bad: %s", aRec.A.String()) - } - } -} - -func TestDNS_ServiceLookup_ServiceAddressIPV6(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Address: "2607:20:4005:808::200e", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []string{ - "db.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "2607002040050808000000000000200e.addr.dc1.consul." { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - - aRec, ok := in.Extra[0].(*dns.AAAA) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Name != "2607002040050808000000000000200e.addr.dc1.consul." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.AAAA.String() != "2607:20:4005:808::200e" { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - } -} - -func TestDNS_AltDomain_ServiceLookup_ServiceAddressIPV6(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - alt_domain = "test-domain" - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Address: "2607:20:4005:808::200e", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []struct { - ask string - want string - }{ - {"db.service.consul.", "2607002040050808000000000000200e.addr.dc1.consul."}, - {"db.service.test-domain.", "2607002040050808000000000000200e.addr.dc1.test-domain."}, - {id + ".query.consul.", "2607002040050808000000000000200e.addr.dc1.consul."}, - {id + ".query.test-domain.", "2607002040050808000000000000200e.addr.dc1.test-domain."}, - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question.ask, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != question.want { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - - aRec, ok := in.Extra[0].(*dns.AAAA) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Name != question.want { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.AAAA.String() != "2607:20:4005:808::200e" { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - } -} - -func TestDNS_ServiceLookup_WanTranslation(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a1 := NewTestAgent(t, ` - datacenter = "dc1" - translate_wan_addrs = true - acl_datacenter = "" - `) - defer a1.Shutdown() - - a2 := NewTestAgent(t, ` - datacenter = "dc2" - translate_wan_addrs = true - acl_datacenter = "" - `) - defer a2.Shutdown() - - // Join WAN cluster - addr := fmt.Sprintf("127.0.0.1:%d", a1.Config.SerfPortWAN) - _, err := a2.JoinWAN([]string{addr}) - require.NoError(t, err) - retry.Run(t, func(r *retry.R) { - require.Len(r, a1.WANMembers(), 2) - require.Len(r, a2.WANMembers(), 2) - }) - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc2", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - require.NoError(t, a2.RPC(context.Background(), "PreparedQuery.Apply", args, &id)) - } - - type testCase struct { - nodeTaggedAddresses map[string]string - serviceAddress string - serviceTaggedAddresses map[string]structs.ServiceAddress - - dnsAddr string - - expectedPort uint16 - expectedAddress string - expectedARRName string - } - - cases := map[string]testCase{ - "node-addr-from-dc1": { - dnsAddr: a1.config.DNSAddrs[0].String(), - expectedPort: 8080, - expectedAddress: "127.0.0.1", - expectedARRName: "foo.node.dc2.consul.", - }, - "node-wan-from-dc1": { - dnsAddr: a1.config.DNSAddrs[0].String(), - nodeTaggedAddresses: map[string]string{ - "wan": "127.0.0.2", - }, - expectedPort: 8080, - expectedAddress: "127.0.0.2", - expectedARRName: "7f000002.addr.dc2.consul.", - }, - "service-addr-from-dc1": { - dnsAddr: a1.config.DNSAddrs[0].String(), - nodeTaggedAddresses: map[string]string{ - "wan": "127.0.0.2", - }, - serviceAddress: "10.0.1.1", - expectedPort: 8080, - expectedAddress: "10.0.1.1", - expectedARRName: "0a000101.addr.dc2.consul.", - }, - "service-wan-from-dc1": { - dnsAddr: a1.config.DNSAddrs[0].String(), - nodeTaggedAddresses: map[string]string{ - "wan": "127.0.0.2", - }, - serviceAddress: "10.0.1.1", - serviceTaggedAddresses: map[string]structs.ServiceAddress{ - "wan": { - Address: "198.18.0.1", - Port: 80, - }, - }, - expectedPort: 80, - expectedAddress: "198.18.0.1", - expectedARRName: "c6120001.addr.dc2.consul.", - }, - "node-addr-from-dc2": { - dnsAddr: a2.config.DNSAddrs[0].String(), - expectedPort: 8080, - expectedAddress: "127.0.0.1", - expectedARRName: "foo.node.dc2.consul.", - }, - "node-wan-from-dc2": { - dnsAddr: a2.config.DNSAddrs[0].String(), - nodeTaggedAddresses: map[string]string{ - "wan": "127.0.0.2", - }, - expectedPort: 8080, - expectedAddress: "127.0.0.1", - expectedARRName: "foo.node.dc2.consul.", - }, - "service-addr-from-dc2": { - dnsAddr: a2.config.DNSAddrs[0].String(), - nodeTaggedAddresses: map[string]string{ - "wan": "127.0.0.2", - }, - serviceAddress: "10.0.1.1", - expectedPort: 8080, - expectedAddress: "10.0.1.1", - expectedARRName: "0a000101.addr.dc2.consul.", - }, - "service-wan-from-dc2": { - dnsAddr: a2.config.DNSAddrs[0].String(), - nodeTaggedAddresses: map[string]string{ - "wan": "127.0.0.2", - }, - serviceAddress: "10.0.1.1", - serviceTaggedAddresses: map[string]structs.ServiceAddress{ - "wan": { - Address: "198.18.0.1", - Port: 80, - }, - }, - expectedPort: 8080, - expectedAddress: "10.0.1.1", - expectedARRName: "0a000101.addr.dc2.consul.", - }, - } - - for name, tc := range cases { - name := name - tc := tc - t.Run(name, func(t *testing.T) { - // Register a remote node with a service. This is in a retry since we - // need the datacenter to have a route which takes a little more time - // beyond the join, and we don't have direct access to the router here. - retry.Run(t, func(r *retry.R) { - args := &structs.RegisterRequest{ - Datacenter: "dc2", - Node: "foo", - Address: "127.0.0.1", - TaggedAddresses: tc.nodeTaggedAddresses, - Service: &structs.NodeService{ - Service: "db", - Address: tc.serviceAddress, - Port: 8080, - TaggedAddresses: tc.serviceTaggedAddresses, - }, - } - - var out struct{} - require.NoError(r, a2.RPC(context.Background(), "Catalog.Register", args, &out)) - }) - - // Look up the SRV record via service and prepared query. - questions := []string{ - "db.service.dc2.consul.", - id + ".query.dc2.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - - addr := tc.dnsAddr - in, _, err := c.Exchange(m, addr) - require.NoError(t, err) - require.Len(t, in.Answer, 1) - srvRec, ok := in.Answer[0].(*dns.SRV) - require.True(t, ok, "Bad: %#v", in.Answer[0]) - require.Equal(t, tc.expectedPort, srvRec.Port) - - aRec, ok := in.Extra[0].(*dns.A) - require.True(t, ok, "Bad: %#v", in.Extra[0]) - require.Equal(t, tc.expectedARRName, aRec.Hdr.Name) - require.Equal(t, tc.expectedAddress, aRec.A.String()) - } - - // Also check the A record directly - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeA) - - c := new(dns.Client) - addr := tc.dnsAddr - in, _, err := c.Exchange(m, addr) - require.NoError(t, err) - require.Len(t, in.Answer, 1) - - aRec, ok := in.Answer[0].(*dns.A) - require.True(t, ok, "Bad: %#v", in.Answer[0]) - require.Equal(t, question, aRec.Hdr.Name) - require.Equal(t, tc.expectedAddress, aRec.A.String()) - } - }) - } -} - -func TestDNS_Lookup_TaggedIPAddresses(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - require.NoError(t, a.RPC(context.Background(), "PreparedQuery.Apply", args, &id)) - } - - type testCase struct { - nodeAddress string - nodeTaggedAddresses map[string]string - serviceAddress string - serviceTaggedAddresses map[string]structs.ServiceAddress - - expectedServiceIPv4Address string - expectedServiceIPv6Address string - expectedNodeIPv4Address string - expectedNodeIPv6Address string - } - - cases := map[string]testCase{ - "simple-ipv4": { - serviceAddress: "127.0.0.2", - nodeAddress: "127.0.0.1", - - expectedServiceIPv4Address: "127.0.0.2", - expectedServiceIPv6Address: "", - expectedNodeIPv4Address: "127.0.0.1", - expectedNodeIPv6Address: "", - }, - "simple-ipv6": { - serviceAddress: "::2", - nodeAddress: "::1", - - expectedServiceIPv6Address: "::2", - expectedServiceIPv4Address: "", - expectedNodeIPv6Address: "::1", - expectedNodeIPv4Address: "", - }, - "ipv4-with-tagged-ipv6": { - serviceAddress: "127.0.0.2", - nodeAddress: "127.0.0.1", - - serviceTaggedAddresses: map[string]structs.ServiceAddress{ - structs.TaggedAddressLANIPv6: {Address: "::2"}, - }, - nodeTaggedAddresses: map[string]string{ - structs.TaggedAddressLANIPv6: "::1", - }, - - expectedServiceIPv4Address: "127.0.0.2", - expectedServiceIPv6Address: "::2", - expectedNodeIPv4Address: "127.0.0.1", - expectedNodeIPv6Address: "::1", - }, - "ipv6-with-tagged-ipv4": { - serviceAddress: "::2", - nodeAddress: "::1", - - serviceTaggedAddresses: map[string]structs.ServiceAddress{ - structs.TaggedAddressLANIPv4: {Address: "127.0.0.2"}, - }, - nodeTaggedAddresses: map[string]string{ - structs.TaggedAddressLANIPv4: "127.0.0.1", - }, - - expectedServiceIPv4Address: "127.0.0.2", - expectedServiceIPv6Address: "::2", - expectedNodeIPv4Address: "127.0.0.1", - expectedNodeIPv6Address: "::1", - }, - } - - for name, tc := range cases { - name := name - tc := tc - t.Run(name, func(t *testing.T) { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: tc.nodeAddress, - TaggedAddresses: tc.nodeTaggedAddresses, - Service: &structs.NodeService{ - Service: "db", - Address: tc.serviceAddress, - Port: 8080, - TaggedAddresses: tc.serviceTaggedAddresses, - }, - } - - var out struct{} - require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) - - // Look up the SRV record via service and prepared query. - questions := []string{ - "db.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeA) - - c := new(dns.Client) - addr := a.config.DNSAddrs[0].String() - in, _, err := c.Exchange(m, addr) - require.NoError(t, err) - - if tc.expectedServiceIPv4Address != "" { - require.Len(t, in.Answer, 1) - aRec, ok := in.Answer[0].(*dns.A) - require.True(t, ok, "Bad: %#v", in.Answer[0]) - require.Equal(t, question, aRec.Hdr.Name) - require.Equal(t, tc.expectedServiceIPv4Address, aRec.A.String()) - } else { - require.Len(t, in.Answer, 0) - } - - m = new(dns.Msg) - m.SetQuestion(question, dns.TypeAAAA) - - c = new(dns.Client) - addr = a.config.DNSAddrs[0].String() - in, _, err = c.Exchange(m, addr) - require.NoError(t, err) - - if tc.expectedServiceIPv6Address != "" { - require.Len(t, in.Answer, 1) - aRec, ok := in.Answer[0].(*dns.AAAA) - require.True(t, ok, "Bad: %#v", in.Answer[0]) - require.Equal(t, question, aRec.Hdr.Name) - require.Equal(t, tc.expectedServiceIPv6Address, aRec.AAAA.String()) - } else { - require.Len(t, in.Answer, 0) - } - } - - // Look up node - m := new(dns.Msg) - m.SetQuestion("foo.node.consul.", dns.TypeA) - - c := new(dns.Client) - addr := a.config.DNSAddrs[0].String() - in, _, err := c.Exchange(m, addr) - require.NoError(t, err) - - if tc.expectedNodeIPv4Address != "" { - require.Len(t, in.Answer, 1) - aRec, ok := in.Answer[0].(*dns.A) - require.True(t, ok, "Bad: %#v", in.Answer[0]) - require.Equal(t, "foo.node.consul.", aRec.Hdr.Name) - require.Equal(t, tc.expectedNodeIPv4Address, aRec.A.String()) - } else { - require.Len(t, in.Answer, 0) - } - - m = new(dns.Msg) - m.SetQuestion("foo.node.consul.", dns.TypeAAAA) - - c = new(dns.Client) - addr = a.config.DNSAddrs[0].String() - in, _, err = c.Exchange(m, addr) - require.NoError(t, err) - - if tc.expectedNodeIPv6Address != "" { - require.Len(t, in.Answer, 1) - aRec, ok := in.Answer[0].(*dns.AAAA) - require.True(t, ok, "Bad: %#v", in.Answer[0]) - require.Equal(t, "foo.node.consul.", aRec.Hdr.Name) - require.Equal(t, tc.expectedNodeIPv6Address, aRec.AAAA.String()) - } else { - require.Len(t, in.Answer, 0) - } - }) - } -} - -func TestDNS_CaseInsensitiveServiceLookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - tests := []struct { - name string - config string - }{ - // UDP + EDNS - {"normal", ""}, - {"cache", `dns_config{ allow_stale=true, max_stale="3h", use_cache=true, "cache_max_age"="3h"}`}, - {"cache-with-streaming", ` - rpc{ - enable_streaming=true - } - use_streaming_backend=true - dns_config{ allow_stale=true, max_stale="3h", use_cache=true, "cache_max_age"="3h"} - `}, - } - for _, tst := range tests { - t.Run(fmt.Sprintf("A lookup %v", tst.name), func(t *testing.T) { - a := NewTestAgent(t, tst.config) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "Db", - Tags: []string{"Primary"}, - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query, as well as a name. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "somequery", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Try some variations to make sure case doesn't matter. - questions := []string{ - "primary.Db.service.consul.", - "primary.db.service.consul.", - "pRIMARY.dB.service.consul.", - "PRIMARY.dB.service.consul.", - "db.service.consul.", - "DB.service.consul.", - "Db.service.consul.", - "somequery.query.consul.", - "SomeQuery.query.consul.", - "SOMEQUERY.query.consul.", - } - - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - retry.Run(t, func(r *retry.R) { - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - r.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - r.Fatalf("question %v, empty lookup: %#v", question, in) - } - }) - } - }) - } -} - -func TestDNS_ServiceLookup_TagPeriod(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register node - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"v1.primary"}, - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - m1 := new(dns.Msg) - m1.SetQuestion("v1.primary2.db.service.consul.", dns.TypeSRV) - - c1 := new(dns.Client) - in, _, err := c1.Exchange(m1, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 0 { - t.Fatalf("Bad: %#v", in) - } - - m := new(dns.Msg) - m.SetQuestion("v1.primary.db.service.consul.", dns.TypeSRV) - - c := new(dns.Client) - in, _, err = c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", srvRec) - } - - aRec, ok := in.Extra[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Name != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.A.String() != "127.0.0.1" { - t.Fatalf("Bad: %#v", in.Extra[0]) - } -} - -func TestDNS_PreparedQueryNearIPEDNS(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - ipCoord := lib.GenerateCoordinate(1 * time.Millisecond) - serviceNodes := []struct { - name string - address string - coord *coordinate.Coordinate - }{ - {"foo1", "198.18.0.1", lib.GenerateCoordinate(1 * time.Millisecond)}, - {"foo2", "198.18.0.2", lib.GenerateCoordinate(10 * time.Millisecond)}, - {"foo3", "198.18.0.3", lib.GenerateCoordinate(30 * time.Millisecond)}, - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - added := 0 - - // Register nodes with a service - for _, cfg := range serviceNodes { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: cfg.name, - Address: cfg.address, - Service: &structs.NodeService{ - Service: "db", - Port: 12345, - }, - } - - var out struct{} - err := a.RPC(context.Background(), "Catalog.Register", args, &out) - require.NoError(t, err) - - // Send coordinate updates - coordArgs := structs.CoordinateUpdateRequest{ - Datacenter: "dc1", - Node: cfg.name, - Coord: cfg.coord, - } - err = a.RPC(context.Background(), "Coordinate.Update", &coordArgs, &out) - require.NoError(t, err) - - added += 1 - } - - fmt.Printf("Added %d service nodes\n", added) - - // Register a node without a service - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "198.18.0.9", - } - - var out struct{} - err := a.RPC(context.Background(), "Catalog.Register", args, &out) - require.NoError(t, err) - - // Send coordinate updates for a few nodes. - coordArgs := structs.CoordinateUpdateRequest{ - Datacenter: "dc1", - Node: "bar", - Coord: ipCoord, - } - err = a.RPC(context.Background(), "Coordinate.Update", &coordArgs, &out) - require.NoError(t, err) - } - - // Register a prepared query Near = _ip - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "some.query.we.like", - Service: structs.ServiceQuery{ - Service: "db", - Near: "_ip", - }, - }, - } - - var id string - err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id) - require.NoError(t, err) - } - retry.Run(t, func(r *retry.R) { - m := new(dns.Msg) - m.SetQuestion("some.query.we.like.query.consul.", dns.TypeA) - m.SetEdns0(4096, false) - o := new(dns.OPT) - o.Hdr.Name = "." - o.Hdr.Rrtype = dns.TypeOPT - e := new(dns.EDNS0_SUBNET) - e.Code = dns.EDNS0SUBNET - e.Family = 1 - e.SourceNetmask = 32 - e.SourceScope = 0 - e.Address = net.ParseIP("198.18.0.9").To4() - o.Option = append(o.Option, e) - m.Extra = append(m.Extra, o) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - r.Fatalf("Error with call to dns.Client.Exchange: %s", err) - } - - if len(serviceNodes) != len(in.Answer) { - r.Fatalf("Expecting %d A RRs in response, Actual found was %d", len(serviceNodes), len(in.Answer)) - } - - for i, rr := range in.Answer { - if aRec, ok := rr.(*dns.A); ok { - if actual := aRec.A.String(); serviceNodes[i].address != actual { - r.Fatalf("Expecting A RR #%d = %s, Actual RR was %s", i, serviceNodes[i].address, actual) - } - } else { - r.Fatalf("DNS Answer contained a non-A RR") - } - } - }) -} - -func TestDNS_PreparedQueryNearIP(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - ipCoord := lib.GenerateCoordinate(1 * time.Millisecond) - serviceNodes := []struct { - name string - address string - coord *coordinate.Coordinate - }{ - {"foo1", "198.18.0.1", lib.GenerateCoordinate(1 * time.Millisecond)}, - {"foo2", "198.18.0.2", lib.GenerateCoordinate(10 * time.Millisecond)}, - {"foo3", "198.18.0.3", lib.GenerateCoordinate(30 * time.Millisecond)}, - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - added := 0 - - // Register nodes with a service - for _, cfg := range serviceNodes { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: cfg.name, - Address: cfg.address, - Service: &structs.NodeService{ - Service: "db", - Port: 12345, - }, - } - - var out struct{} - err := a.RPC(context.Background(), "Catalog.Register", args, &out) - require.NoError(t, err) - - // Send coordinate updates - coordArgs := structs.CoordinateUpdateRequest{ - Datacenter: "dc1", - Node: cfg.name, - Coord: cfg.coord, - } - err = a.RPC(context.Background(), "Coordinate.Update", &coordArgs, &out) - require.NoError(t, err) - - added += 1 - } - - fmt.Printf("Added %d service nodes\n", added) - - // Register a node without a service - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "198.18.0.9", - } - - var out struct{} - err := a.RPC(context.Background(), "Catalog.Register", args, &out) - require.NoError(t, err) - - // Send coordinate updates for a few nodes. - coordArgs := structs.CoordinateUpdateRequest{ - Datacenter: "dc1", - Node: "bar", - Coord: ipCoord, - } - err = a.RPC(context.Background(), "Coordinate.Update", &coordArgs, &out) - require.NoError(t, err) - } - - // Register a prepared query Near = _ip - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "some.query.we.like", - Service: structs.ServiceQuery{ - Service: "db", - Near: "_ip", - }, - }, - } - - var id string - err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id) - require.NoError(t, err) - } - - retry.Run(t, func(r *retry.R) { - m := new(dns.Msg) - m.SetQuestion("some.query.we.like.query.consul.", dns.TypeA) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - r.Fatalf("Error with call to dns.Client.Exchange: %s", err) - } - - if len(serviceNodes) != len(in.Answer) { - r.Fatalf("Expecting %d A RRs in response, Actual found was %d", len(serviceNodes), len(in.Answer)) - } - - for i, rr := range in.Answer { - if aRec, ok := rr.(*dns.A); ok { - if actual := aRec.A.String(); serviceNodes[i].address != actual { - r.Fatalf("Expecting A RR #%d = %s, Actual RR was %s", i, serviceNodes[i].address, actual) - } - } else { - r.Fatalf("DNS Answer contained a non-A RR") - } - } - }) -} - -func TestDNS_ServiceLookup_PreparedQueryNamePeriod(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register a prepared query with a period in the name. - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "some.query.we.like", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - - var id string - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - m := new(dns.Msg) - m.SetQuestion("some.query.we.like.query.consul.", dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", srvRec) - } - - aRec, ok := in.Extra[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Name != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.A.String() != "127.0.0.1" { - t.Fatalf("Bad: %#v", in.Extra[0]) - } -} - -func TestDNS_ServiceLookup_Dedup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a single node with multiple instances of a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - args = &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - ID: "db2", - Service: "db", - Tags: []string{"replica"}, - Port: 12345, - }, - } - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - args = &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - ID: "db3", - Service: "db", - Tags: []string{"replica"}, - Port: 12346, - }, - } - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query, make sure only - // one IP is returned. - questions := []string{ - "db.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - aRec, ok := in.Answer[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if aRec.A.String() != "127.0.0.1" { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - } -} - -func TestDNS_ServiceLookup_Dedup_SRV(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a single node with multiple instances of a service. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - args = &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - ID: "db2", - Service: "db", - Tags: []string{"replica"}, - Port: 12345, - }, - } - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - args = &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - ID: "db3", - Service: "db", - Tags: []string{"replica"}, - Port: 12346, - }, - } - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query, make sure only - // one IP is returned and two unique ports are returned. - questions := []string{ - "db.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 2 { - t.Fatalf("Bad: %#v", in) - } - - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 && srvRec.Port != 12346 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", srvRec) - } - - srvRec, ok = in.Answer[1].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[1]) - } - if srvRec.Port != 12346 && srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Port == in.Answer[0].(*dns.SRV).Port { - t.Fatalf("should be a different port") - } - if srvRec.Target != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", srvRec) - } - - aRec, ok := in.Extra[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Name != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.A.String() != "127.0.0.1" { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - } -} - -func TestDNS_Recurse(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - recursor := makeRecursor(t, dns.Msg{ - Answer: []dns.RR{dnsA("apple.com", "1.2.3.4")}, - }) - defer recursor.Shutdown() - - a := NewTestAgent(t, ` - recursors = ["`+recursor.Addr+`"] - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - m := new(dns.Msg) - m.SetQuestion("apple.com.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) == 0 { - t.Fatalf("Bad: %#v", in) - } - if in.Rcode != dns.RcodeSuccess { - t.Fatalf("Bad: %#v", in) - } -} - -func TestDNS_Recurse_Truncation(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - - recursor := makeRecursor(t, dns.Msg{ - MsgHdr: dns.MsgHdr{Truncated: true}, - Answer: []dns.RR{dnsA("apple.com", "1.2.3.4")}, - }) - defer recursor.Shutdown() - - a := NewTestAgent(t, ` - recursors = ["`+recursor.Addr+`"] - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - m := new(dns.Msg) - m.SetQuestion("apple.com.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - if in.Truncated != true { - t.Fatalf("err: message should have been truncated %v", in) - } - if len(in.Answer) == 0 { - t.Fatalf("Bad: Truncated message ignored, expected some reply %#v", in) - } - if in.Rcode != dns.RcodeSuccess { - t.Fatalf("Bad: %#v", in) - } -} - -func TestDNS_RecursorTimeout(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - serverClientTimeout := 3 * time.Second - testClientTimeout := serverClientTimeout + 5*time.Second - - resolverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0") - if err != nil { - t.Error(err) - } - - resolver, err := net.ListenUDP("udp", resolverAddr) - if err != nil { - t.Error(err) - } - defer resolver.Close() - - a := NewTestAgent(t, ` - recursors = ["`+resolver.LocalAddr().String()+`"] // host must cause a connection|read|write timeout - dns_config { - recursor_timeout = "`+serverClientTimeout.String()+`" - } - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - m := new(dns.Msg) - m.SetQuestion("apple.com.", dns.TypeANY) - - // This client calling the server under test must have a longer timeout than the one we set internally - c := &dns.Client{Timeout: testClientTimeout} - - start := time.Now() - in, _, err := c.Exchange(m, a.DNSAddr()) - - duration := time.Since(start) - - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 0 { - t.Fatalf("Bad: %#v", in) - } - if in.Rcode != dns.RcodeServerFailure { - t.Fatalf("Bad: %#v", in) - } - - if duration < serverClientTimeout { - t.Fatalf("Expected the call to return after at least %f seconds but lasted only %f", serverClientTimeout.Seconds(), duration.Seconds()) - } - -} - -func TestDNS_ServiceLookup_FilterCritical(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register nodes with health checks in various states. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - Check: &structs.HealthCheck{ - CheckID: "serf", - Name: "serf", - Status: api.HealthCritical, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - args2 := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "127.0.0.2", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - Check: &structs.HealthCheck{ - CheckID: "serf", - Name: "serf", - Status: api.HealthCritical, - }, - } - if err := a.RPC(context.Background(), "Catalog.Register", args2, &out); err != nil { - t.Fatalf("err: %v", err) - } - - args3 := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "127.0.0.2", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - Check: &structs.HealthCheck{ - CheckID: "db", - Name: "db", - ServiceID: "db", - Status: api.HealthCritical, - }, - } - if err := a.RPC(context.Background(), "Catalog.Register", args3, &out); err != nil { - t.Fatalf("err: %v", err) - } - - args4 := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "baz", - Address: "127.0.0.3", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - } - if err := a.RPC(context.Background(), "Catalog.Register", args4, &out); err != nil { - t.Fatalf("err: %v", err) - } - - args5 := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "quux", - Address: "127.0.0.4", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - Check: &structs.HealthCheck{ - CheckID: "db", - Name: "db", - ServiceID: "db", - Status: api.HealthWarning, - }, - } - if err := a.RPC(context.Background(), "Catalog.Register", args5, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []string{ - "db.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - // Only 4 and 5 are not failing, so we should get 2 answers - if len(in.Answer) != 2 { - t.Fatalf("Bad: %#v", in) - } - - ips := make(map[string]bool) - for _, resp := range in.Answer { - aRec := resp.(*dns.A) - ips[aRec.A.String()] = true - } - - if !ips["127.0.0.3"] { - t.Fatalf("Bad: %#v should contain 127.0.0.3 (state healthy)", in) - } - if !ips["127.0.0.4"] { - t.Fatalf("Bad: %#v should contain 127.0.0.4 (state warning)", in) - } - } -} - -func TestDNS_ServiceLookup_OnlyFailing(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register nodes with all health checks in a critical state. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - Check: &structs.HealthCheck{ - CheckID: "serf", - Name: "serf", - Status: api.HealthCritical, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - args2 := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "127.0.0.2", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - Check: &structs.HealthCheck{ - CheckID: "serf", - Name: "serf", - Status: api.HealthCritical, - }, - } - if err := a.RPC(context.Background(), "Catalog.Register", args2, &out); err != nil { - t.Fatalf("err: %v", err) - } - - args3 := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "127.0.0.2", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - Check: &structs.HealthCheck{ - CheckID: "db", - Name: "db", - ServiceID: "db", - Status: api.HealthCritical, - }, - } - if err := a.RPC(context.Background(), "Catalog.Register", args3, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "db", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []string{ - "db.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - // All 3 are failing, so we should get 0 answers and an NXDOMAIN response - if len(in.Answer) != 0 { - t.Fatalf("Bad: %#v", in) - } - - if in.Rcode != dns.RcodeNameError { - t.Fatalf("Bad: %#v", in) - } - } -} - -func TestDNS_ServiceLookup_OnlyPassing(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - dns_config { - only_passing = true - } - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register nodes with health checks in various states. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - Check: &structs.HealthCheck{ - CheckID: "db", - Name: "db", - ServiceID: "db", - Status: api.HealthPassing, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - args2 := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "127.0.0.2", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - Check: &structs.HealthCheck{ - CheckID: "db", - Name: "db", - ServiceID: "db", - Status: api.HealthWarning, - }, - } - - if err := a.RPC(context.Background(), "Catalog.Register", args2, &out); err != nil { - t.Fatalf("err: %v", err) - } - - args3 := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "baz", - Address: "127.0.0.3", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - Check: &structs.HealthCheck{ - CheckID: "db", - Name: "db", - ServiceID: "db", - Status: api.HealthCritical, - }, - } - - if err := a.RPC(context.Background(), "Catalog.Register", args3, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "db", - OnlyPassing: true, - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []string{ - "db.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - // Only 1 is passing, so we should only get 1 answer - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - resp := in.Answer[0] - aRec := resp.(*dns.A) - - if aRec.A.String() != "127.0.0.1" { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - } - - newCfg := *a.Config - newCfg.DNSOnlyPassing = false - err := a.reloadConfigInternal(&newCfg) - require.NoError(t, err) - - // only_passing is now false. we should now get two nodes - m := new(dns.Msg) - m.SetQuestion("db.service.consul.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - require.NoError(t, err) - - require.Equal(t, 2, len(in.Answer)) - ips := []string{in.Answer[0].(*dns.A).A.String(), in.Answer[1].(*dns.A).A.String()} - sort.Strings(ips) - require.Equal(t, []string{"127.0.0.1", "127.0.0.2"}, ips) -} - -func TestDNS_ServiceLookup_Randomize(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a large number of nodes. - for i := 0; i < generateNumNodes; i++ { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: fmt.Sprintf("foo%d", i), - Address: fmt.Sprintf("127.0.0.%d", i+1), - Service: &structs.NodeService{ - Service: "web", - Port: 8000, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "web", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. Ensure the - // response is randomized each time. - questions := []string{ - "web.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - uniques := map[string]struct{}{} - for i := 0; i < 10; i++ { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeANY) - - c := &dns.Client{Net: "udp"} - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - // Response length should be truncated and we should get - // an A record for each response. - if len(in.Answer) != defaultNumUDPResponses { - t.Fatalf("Bad: %#v", len(in.Answer)) - } - - // Collect all the names. - var names []string - for _, rec := range in.Answer { - switch v := rec.(type) { - case *dns.SRV: - names = append(names, v.Target) - case *dns.A: - names = append(names, v.A.String()) - } - } - nameS := strings.Join(names, "|") - - // Tally the results. - uniques[nameS] = struct{}{} - } - - // Give some wiggle room. Since the responses are randomized and - // there is a finite number of combinations, requiring 0 - // duplicates every test run eventually gives us failures. - if len(uniques) < 2 { - t.Fatalf("unique response ratio too low: %d/10\n%v", len(uniques), uniques) - } - } -} - -func TestBinarySearch(t *testing.T) { - t.Parallel() - msgSrc := new(dns.Msg) - msgSrc.Compress = true - msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV) - - for i := 0; i < 5000; i++ { - target := fmt.Sprintf("host-redis-%d-%d.test.acme.com.node.dc1.consul.", i/256, i%256) - msgSrc.Answer = append(msgSrc.Answer, &dns.SRV{Hdr: dns.RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: dns.TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target}) - msgSrc.Extra = append(msgSrc.Extra, &dns.CNAME{Hdr: dns.RR_Header{Name: target, Class: 1, Rrtype: dns.TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", i/256, i%256)}) - } - for _, compress := range []bool{true, false} { - for idx, maxSize := range []int{12, 256, 512, 8192, 65535} { - t.Run(fmt.Sprintf("binarySearch %d", maxSize), func(t *testing.T) { - msg := new(dns.Msg) - msgSrc.Compress = compress - msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV) - msg.Answer = msgSrc.Answer - msg.Extra = msgSrc.Extra - msg.Ns = msgSrc.Ns - index := make(map[string]dns.RR, len(msg.Extra)) - indexRRs(msg.Extra, index) - blen := dnsBinaryTruncate(msg, maxSize, index, true) - msg.Answer = msg.Answer[:blen] - syncExtra(index, msg) - predicted := msg.Len() - buf, err := msg.Pack() - if err != nil { - t.Error(err) - } - if predicted < len(buf) { - t.Fatalf("Bug in DNS library: %d != %d", predicted, len(buf)) - } - if len(buf) > maxSize || (idx != 0 && len(buf) < 16) { - t.Fatalf("bad[%d]: %d > %d", idx, len(buf), maxSize) - } - }) - } - } -} - -func TestDNS_TCP_and_UDP_Truncate(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - dns_config { - enable_truncate = true - } - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - services := []string{"normal", "truncated"} - for index, service := range services { - numServices := (index * 5000) + 2 - var eg errgroup.Group - for i := 1; i < numServices; i++ { - j := i - eg.Go(func() error { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: fmt.Sprintf("%s-%d.acme.com", service, j), - Address: fmt.Sprintf("127.%d.%d.%d", 0, (j / 255), j%255), - Service: &structs.NodeService{ - Service: service, - Port: 8000, - }, - } - - var out struct{} - return a.RPC(context.Background(), "Catalog.Register", args, &out) - }) - } - if err := eg.Wait(); err != nil { - t.Fatalf("error registering: %v", err) - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: service, - Service: structs.ServiceQuery{ - Service: service, - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. Ensure the - // response is truncated each time. - questions := []string{ - fmt.Sprintf("%s.service.consul.", service), - id + ".query.consul.", - } - protocols := []string{ - "tcp", - "udp", - } - for _, maxSize := range []uint16{8192, 65535} { - for _, qType := range []uint16{dns.TypeANY, dns.TypeA, dns.TypeSRV} { - for _, question := range questions { - for _, protocol := range protocols { - for _, compress := range []bool{true, false} { - t.Run(fmt.Sprintf("lookup %s %s (qType:=%d) compressed=%v", question, protocol, qType, compress), func(t *testing.T) { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeANY) - maxSz := maxSize - if protocol == "udp" { - maxSz = 8192 - } - m.SetEdns0(maxSz, true) - c := new(dns.Client) - c.Net = protocol - m.Compress = compress - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - // actually check if we need to have the truncate bit - resbuf, err := in.Pack() - if err != nil { - t.Fatalf("Error while packing answer: %s", err) - } - if !in.Truncated && len(resbuf) > int(maxSz) { - t.Fatalf("should have truncate bit %#v %#v", in, len(in.Answer)) - } - // Check for the truncate bit - buf, err := m.Pack() - info := fmt.Sprintf("service %s question:=%s (%s) (%d total records) sz:= %d in %v", - service, question, protocol, numServices, len(in.Answer), in) - if err != nil { - t.Fatalf("Error while packing: %v ; info:=%s", err, info) - } - if len(buf) > int(maxSz) { - t.Fatalf("len(buf) := %d > maxSz=%d for %v", len(buf), maxSz, info) - } - }) - } - } - } - } - } - } -} - -func TestDNS_ServiceLookup_Truncate(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - dns_config { - enable_truncate = true - } - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a large number of nodes. - for i := 0; i < generateNumNodes; i++ { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: fmt.Sprintf("foo%d", i), - Address: fmt.Sprintf("127.0.0.%d", i+1), - Service: &structs.NodeService{ - Service: "web", - Port: 8000, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "web", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. Ensure the - // response is truncated each time. - questions := []string{ - "web.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - // Check for the truncate bit - if !in.Truncated { - t.Fatalf("should have truncate bit") - } - } -} - -func TestDNS_ServiceLookup_LargeResponses(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - dns_config { - enable_truncate = true - } - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - longServiceName := "this-is-a-very-very-very-very-very-long-name-for-a-service" - - // Register a lot of nodes. - for i := 0; i < 4; i++ { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: fmt.Sprintf("foo%d", i), - Address: fmt.Sprintf("127.0.0.%d", i+1), - Service: &structs.NodeService{ - Service: longServiceName, - Tags: []string{"primary"}, - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: longServiceName, - Service: structs.ServiceQuery{ - Service: longServiceName, - Tags: []string{"primary"}, - }, - }, - } - var id string - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []string{ - "_" + longServiceName + "._primary.service.consul.", - longServiceName + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if !in.Truncated { - t.Fatalf("should have truncate bit") - } - - // Make sure the response size is RFC 1035-compliant for UDP messages - if in.Len() > 512 { - t.Fatalf("Bad: %d", in.Len()) - } - - // We should only have two answers now - if len(in.Answer) != 2 { - t.Fatalf("Bad: %d", len(in.Answer)) - } - - // Make sure the ADDITIONAL section matches the ANSWER section. - if len(in.Answer) != len(in.Extra) { - t.Fatalf("Bad: %d vs. %d", len(in.Answer), len(in.Extra)) - } - for i := 0; i < len(in.Answer); i++ { - srv, ok := in.Answer[i].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[i]) - } - - a, ok := in.Extra[i].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[i]) - } - - if srv.Target != a.Hdr.Name { - t.Fatalf("Bad: %#v %#v", srv, a) - } - } - - // Check for the truncate bit - if !in.Truncated { - t.Fatalf("should have truncate bit") - } - } -} - -func testDNSServiceLookupResponseLimits(t *testing.T, answerLimit int, qType uint16, - expectedService, expectedQuery, expectedQueryID int) (bool, error) { - a := NewTestAgent(t, ` - node_name = "test-node" - dns_config { - udp_answer_limit = `+fmt.Sprintf("%d", answerLimit)+` - } - `) - defer a.Shutdown() - testrpc.WaitForTestAgent(t, a.RPC, "dc1") - - choices := perfectlyRandomChoices(generateNumNodes, pctNodesWithIPv6) - for i := 0; i < generateNumNodes; i++ { - nodeAddress := fmt.Sprintf("127.0.0.%d", i+1) - if choices[i] { - nodeAddress = fmt.Sprintf("fe80::%d", i+1) - } - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: fmt.Sprintf("foo%d", i), - Address: nodeAddress, - Service: &structs.NodeService{ - Service: "api-tier", - Port: 8080, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - return false, fmt.Errorf("err: %v", err) - } - } - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "api-tier", - Service: structs.ServiceQuery{ - Service: "api-tier", - }, - }, - } - - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - return false, fmt.Errorf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []string{ - "api-tier.service.consul.", - "api-tier.query.consul.", - id + ".query.consul.", - } - for idx, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, qType) - - c := &dns.Client{Net: "udp"} - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - return false, fmt.Errorf("err: %v", err) - } - - switch idx { - case 0: - if (expectedService > 0 && len(in.Answer) != expectedService) || - (expectedService < -1 && len(in.Answer) < lib.AbsInt(expectedService)) { - return false, fmt.Errorf("%d/%d answers received for type %v for %s, sz:=%d", len(in.Answer), answerLimit, qType, question, in.Len()) - } - case 1: - if (expectedQuery > 0 && len(in.Answer) != expectedQuery) || - (expectedQuery < -1 && len(in.Answer) < lib.AbsInt(expectedQuery)) { - return false, fmt.Errorf("%d/%d answers received for type %v for %s, sz:=%d", len(in.Answer), answerLimit, qType, question, in.Len()) - } - case 2: - if (expectedQueryID > 0 && len(in.Answer) != expectedQueryID) || - (expectedQueryID < -1 && len(in.Answer) < lib.AbsInt(expectedQueryID)) { - return false, fmt.Errorf("%d/%d answers received for type %v for %s, sz:=%d", len(in.Answer), answerLimit, qType, question, in.Len()) - } - default: - panic("abort") - } - } - - return true, nil -} - -func checkDNSService( - t *testing.T, - generateNumNodes int, - aRecordLimit int, - qType uint16, - expectedResultsCount int, - udpSize uint16, -) { - a := NewTestAgent(t, ` - node_name = "test-node" - dns_config { - a_record_limit = `+fmt.Sprintf("%d", aRecordLimit)+` - udp_answer_limit = `+fmt.Sprintf("%d", aRecordLimit)+` - } - `) - testrpc.WaitForTestAgent(t, a.RPC, "dc1") - - choices := perfectlyRandomChoices(generateNumNodes, pctNodesWithIPv6) - for i := 0; i < generateNumNodes; i++ { - nodeAddress := fmt.Sprintf("127.0.0.%d", i+1) - if choices[i] { - nodeAddress = fmt.Sprintf("fe80::%d", i+1) - } - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: fmt.Sprintf("foo%d", i), - Address: nodeAddress, - Service: &structs.NodeService{ - Service: "api-tier", - Port: 8080, - }, - } - - var out struct{} - require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) - } - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "api-tier", - Service: structs.ServiceQuery{ - Service: "api-tier", - }, - }, - } - - require.NoError(t, a.RPC(context.Background(), "PreparedQuery.Apply", args, &id)) - } - - // Look up the service directly and via prepared query. - questions := []string{ - "api-tier.service.consul.", - "api-tier.query.consul.", - id + ".query.consul.", - } - for _, question := range questions { - question := question - t.Run("question: "+question, func(t *testing.T) { - - m := new(dns.Msg) - - m.SetQuestion(question, qType) - protocol := "tcp" - if udpSize > 0 { - protocol = "udp" - } - if udpSize > 512 { - m.SetEdns0(udpSize, true) - } - c := &dns.Client{Net: protocol, UDPSize: 8192} - in, _, err := c.Exchange(m, a.DNSAddr()) - require.NoError(t, err) - - t.Logf("DNS Response for %+v - %+v", m, in) - - require.Equal(t, expectedResultsCount, len(in.Answer), - "%d/%d answers received for type %v for %s (%s)", len(in.Answer), expectedResultsCount, qType, question, protocol) - }) - } -} - -func TestDNS_ServiceLookup_ARecordLimits(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - tests := []struct { - name string - aRecordLimit int - expectedAResults int - expectedAAAAResults int - expectedANYResults int - expectedSRVResults int - numNodesTotal int - udpSize uint16 - _unused_udpAnswerLimit int // NOTE: this field is not used - }{ - // UDP + EDNS - {"udp-edns-1", 1, 1, 1, 1, 30, 30, 8192, 3}, - {"udp-edns-2", 2, 2, 2, 2, 30, 30, 8192, 3}, - {"udp-edns-3", 3, 3, 3, 3, 30, 30, 8192, 3}, - {"udp-edns-4", 4, 4, 4, 4, 30, 30, 8192, 3}, - {"udp-edns-5", 5, 5, 5, 5, 30, 30, 8192, 3}, - {"udp-edns-6", 6, 6, 6, 6, 30, 30, 8192, 3}, - {"udp-edns-max", 6, 2, 1, 3, 3, 3, 8192, 3}, - // All UDP without EDNS have a limit of 2 answers due to udpAnswerLimit - // Even SRV records are limit to 2 records - {"udp-limit-1", 1, 1, 0, 1, 1, 1, 512, 2}, - {"udp-limit-2", 2, 1, 1, 2, 2, 2, 512, 2}, - // AAAA results limited by size of payload - {"udp-limit-3", 3, 1, 1, 2, 2, 2, 512, 2}, - {"udp-limit-4", 4, 1, 1, 2, 2, 2, 512, 2}, - {"udp-limit-5", 5, 1, 1, 2, 2, 2, 512, 2}, - {"udp-limit-6", 6, 1, 1, 2, 2, 2, 512, 2}, - {"udp-limit-max", 6, 1, 1, 2, 2, 2, 512, 2}, - // All UDP without EDNS and no udpAnswerLimit - // Size of records is limited by UDP payload - {"udp-1", 1, 1, 0, 1, 1, 1, 512, 0}, - {"udp-2", 2, 1, 1, 2, 2, 2, 512, 0}, - {"udp-3", 3, 1, 1, 2, 2, 2, 512, 0}, - {"udp-4", 4, 1, 1, 2, 2, 2, 512, 0}, - {"udp-5", 5, 1, 1, 2, 2, 2, 512, 0}, - {"udp-6", 6, 1, 1, 2, 2, 2, 512, 0}, - // Only 3 A and 3 SRV records on 512 bytes - {"udp-max", 6, 1, 1, 2, 2, 2, 512, 0}, - - {"tcp-1", 1, 1, 1, 1, 30, 30, 0, 0}, - {"tcp-2", 2, 2, 2, 2, 30, 30, 0, 0}, - {"tcp-3", 3, 3, 3, 3, 30, 30, 0, 0}, - {"tcp-4", 4, 4, 4, 4, 30, 30, 0, 0}, - {"tcp-5", 5, 5, 5, 5, 30, 30, 0, 0}, - {"tcp-6", 6, 6, 6, 6, 30, 30, 0, 0}, - {"tcp-max", 6, 1, 1, 2, 2, 2, 0, 0}, - } - for _, test := range tests { - test := test // capture loop var - - t.Run(test.name, func(t *testing.T) { - t.Parallel() - - // All those queries should have at max queriesLimited elements - - t.Run("A", func(t *testing.T) { - t.Parallel() - checkDNSService(t, test.numNodesTotal, test.aRecordLimit, dns.TypeA, test.expectedAResults, test.udpSize) - }) - - t.Run("AAAA", func(t *testing.T) { - t.Parallel() - checkDNSService(t, test.numNodesTotal, test.aRecordLimit, dns.TypeAAAA, test.expectedAAAAResults, test.udpSize) - }) - - t.Run("ANY", func(t *testing.T) { - t.Parallel() - checkDNSService(t, test.numNodesTotal, test.aRecordLimit, dns.TypeANY, test.expectedANYResults, test.udpSize) - }) - - // No limits but the size of records for SRV records, since not subject to randomization issues - t.Run("SRV", func(t *testing.T) { - t.Parallel() - checkDNSService(t, test.expectedSRVResults, test.aRecordLimit, dns.TypeSRV, test.numNodesTotal, test.udpSize) - }) - }) - } -} - -func TestDNS_ServiceLookup_AnswerLimits(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - // Build a matrix of config parameters (udpAnswerLimit), and the - // length of the response per query type and question. Negative - // values imply the test must return at least the abs(value) number - // of records in the answer section. This is required because, for - // example, on OS-X and Linux, the number of answers returned in a - // 512B response is different even though both platforms are x86_64 - // and using the same version of Go. - // - // TODO(sean@): Why is it not identical everywhere when using the - // same compiler? - tests := []struct { - name string - udpAnswerLimit int - expectedAService int - expectedAQuery int - expectedAQueryID int - expectedAAAAService int - expectedAAAAQuery int - expectedAAAAQueryID int - expectedANYService int - expectedANYQuery int - expectedANYQueryID int - }{ - {"0", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {"1", 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, - {"2", 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, - {"3", 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, - {"4", 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, - {"5", 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}, - {"6", 6, 6, 6, 6, 6, 6, 5, 6, 6, -5}, - {"7", 7, 7, 7, 6, 7, 7, 5, 7, 7, -5}, - {"8", 8, 8, 8, 6, 8, 8, 5, 8, 8, -5}, - {"9", 9, 8, 8, 6, 8, 8, 5, 8, 8, -5}, - {"20", 20, 8, 8, 6, 8, 8, 5, 8, -5, -5}, - {"30", 30, 8, 8, 6, 8, 8, 5, 8, -5, -5}, - } - for _, test := range tests { - test := test // capture loop var - t.Run(fmt.Sprintf("A lookup %v", test), func(t *testing.T) { - t.Parallel() - ok, err := testDNSServiceLookupResponseLimits(t, test.udpAnswerLimit, dns.TypeA, test.expectedAService, test.expectedAQuery, test.expectedAQueryID) - if !ok { - t.Fatalf("Expected service A lookup %s to pass: %v", test.name, err) - } - }) - - t.Run(fmt.Sprintf("AAAA lookup %v", test), func(t *testing.T) { - t.Parallel() - ok, err := testDNSServiceLookupResponseLimits(t, test.udpAnswerLimit, dns.TypeAAAA, test.expectedAAAAService, test.expectedAAAAQuery, test.expectedAAAAQueryID) - if !ok { - t.Fatalf("Expected service AAAA lookup %s to pass: %v", test.name, err) - } - }) - - t.Run(fmt.Sprintf("ANY lookup %v", test), func(t *testing.T) { - t.Parallel() - ok, err := testDNSServiceLookupResponseLimits(t, test.udpAnswerLimit, dns.TypeANY, test.expectedANYService, test.expectedANYQuery, test.expectedANYQueryID) - if !ok { - t.Fatalf("Expected service ANY lookup %s to pass: %v", test.name, err) - } - }) - } -} - -func TestDNS_ServiceLookup_CNAME(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - recursor := makeRecursor(t, dns.Msg{ - Answer: []dns.RR{ - dnsCNAME("www.google.com", "google.com"), - dnsA("google.com", "1.2.3.4"), - }, - }) - defer recursor.Shutdown() - - a := NewTestAgent(t, ` - recursors = ["`+recursor.Addr+`"] - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a name for an address. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "google", - Address: "www.google.com", - Service: &structs.NodeService{ - Service: "search", - Port: 80, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "search", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []string{ - "search.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - // Service CNAME, google CNAME, google A record - if len(in.Answer) != 3 { - t.Fatalf("Bad: %#v", in) - } - - // Should have service CNAME - cnRec, ok := in.Answer[0].(*dns.CNAME) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if cnRec.Target != "www.google.com." { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - - // Should have google CNAME - cnRec, ok = in.Answer[1].(*dns.CNAME) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[1]) - } - if cnRec.Target != "google.com." { - t.Fatalf("Bad: %#v", in.Answer[1]) - } - - // Check we recursively resolve - if _, ok := in.Answer[2].(*dns.A); !ok { - t.Fatalf("Bad: %#v", in.Answer[2]) - } - } -} - -func TestDNS_ServiceLookup_ServiceAddress_CNAME(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - recursor := makeRecursor(t, dns.Msg{ - Answer: []dns.RR{ - dnsCNAME("www.google.com", "google.com"), - dnsA("google.com", "1.2.3.4"), - }, - }) - defer recursor.Shutdown() - - a := NewTestAgent(t, ` - recursors = ["`+recursor.Addr+`"] - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register a node with a name for an address. - { - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "google", - Address: "1.2.3.4", - Service: &structs.NodeService{ - Service: "search", - Port: 80, - Address: "www.google.com", - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Register an equivalent prepared query. - var id string - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: "test", - Service: structs.ServiceQuery{ - Service: "search", - }, - }, - } - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - } - - // Look up the service directly and via prepared query. - questions := []string{ - "search.service.consul.", - id + ".query.consul.", - } - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - // Service CNAME, google CNAME, google A record - if len(in.Answer) != 3 { - t.Fatalf("Bad: %#v", in) - } - - // Should have service CNAME - cnRec, ok := in.Answer[0].(*dns.CNAME) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if cnRec.Target != "www.google.com." { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - - // Should have google CNAME - cnRec, ok = in.Answer[1].(*dns.CNAME) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[1]) - } - if cnRec.Target != "google.com." { - t.Fatalf("Bad: %#v", in.Answer[1]) - } - - // Check we recursively resolve - if _, ok := in.Answer[2].(*dns.A); !ok { - t.Fatalf("Bad: %#v", in.Answer[2]) - } - } -} - -func TestDNS_NodeLookup_TTL(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - recursor := makeRecursor(t, dns.Msg{ - Answer: []dns.RR{ - dnsCNAME("www.google.com", "google.com"), - dnsA("google.com", "1.2.3.4"), - }, - }) - defer recursor.Shutdown() - - a := NewTestAgent(t, ` - recursors = ["`+recursor.Addr+`"] - dns_config { - node_ttl = "10s" - allow_stale = true - max_stale = "1s" - } - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register node - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - m := new(dns.Msg) - m.SetQuestion("foo.node.consul.", dns.TypeANY) - - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - aRec, ok := in.Answer[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if aRec.A.String() != "127.0.0.1" { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if aRec.Hdr.Ttl != 10 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - - // Register node with IPv6 - args = &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "::4242:4242", - } - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - // Check an IPv6 record - m = new(dns.Msg) - m.SetQuestion("bar.node.consul.", dns.TypeANY) - - in, _, err = c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - - aaaaRec, ok := in.Answer[0].(*dns.AAAA) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if aaaaRec.AAAA.String() != "::4242:4242" { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if aaaaRec.Hdr.Ttl != 10 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - - // Register node with CNAME - args = &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "google", - Address: "www.google.com", - } - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - m = new(dns.Msg) - m.SetQuestion("google.node.consul.", dns.TypeANY) - - in, _, err = c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - // Should have the CNAME record + a few A records - if len(in.Answer) < 2 { - t.Fatalf("Bad: %#v", in) - } - - cnRec, ok := in.Answer[0].(*dns.CNAME) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if cnRec.Target != "www.google.com." { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if cnRec.Hdr.Ttl != 10 { - t.Fatalf("Bad: %#v", in.Answer[0]) - } -} - -func TestDNS_ServiceLookup_TTL(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, ` - dns_config { - service_ttl = { - "d*" = "42s" - "db" = "10s" - "db*" = "66s" - "*" = "5s" - } - allow_stale = true - max_stale = "1s" - } - `) - defer a.Shutdown() + expectedServiceIPv4Address: "127.0.0.2", + expectedServiceIPv6Address: "::2", + expectedNodeIPv4Address: "127.0.0.1", + expectedNodeIPv6Address: "::1", + }, + "ipv6-with-tagged-ipv4": { + serviceAddress: "::2", + nodeAddress: "::1", - for idx, service := range []string{"db", "dblb", "dk", "api"} { - nodeName := fmt.Sprintf("foo%d", idx) - address := fmt.Sprintf("127.0.0.%d", idx) - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: nodeName, - Address: address, - Service: &structs.NodeService{ - Service: service, - Tags: []string{"primary"}, - Port: 12345 + idx, + serviceTaggedAddresses: map[string]structs.ServiceAddress{ + structs.TaggedAddressLANIPv4: {Address: "127.0.0.2"}, + }, + nodeTaggedAddresses: map[string]string{ + structs.TaggedAddressLANIPv4: "127.0.0.1", }, - } - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } + expectedServiceIPv4Address: "127.0.0.2", + expectedServiceIPv6Address: "::2", + expectedNodeIPv4Address: "127.0.0.1", + expectedNodeIPv6Address: "::1", + }, } - c := new(dns.Client) - expectResult := func(dnsQuery string, expectedTTL uint32) { - t.Run(dnsQuery, func(t *testing.T) { - m := new(dns.Msg) - m.SetQuestion(dnsQuery, dns.TypeSRV) - - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v, len is %d", in, len(in.Answer)) + for name, tc := range cases { + name := name + tc := tc + t.Run(name, func(t *testing.T) { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: tc.nodeAddress, + TaggedAddresses: tc.nodeTaggedAddresses, + Service: &structs.NodeService{ + Service: "db", + Address: tc.serviceAddress, + Port: 8080, + TaggedAddresses: tc.serviceTaggedAddresses, + }, } - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Hdr.Ttl != expectedTTL { - t.Fatalf("Bad: %#v", in.Answer[0]) - } + var out struct{} + require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) - aRec, ok := in.Extra[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Ttl != expectedTTL { - t.Fatalf("Bad: %#v", in.Extra[0]) + // Look up the SRV record via service and prepared query. + questions := []string{ + "db.service.consul.", + id + ".query.consul.", } - }) - } - // Should have its exact TTL - expectResult("db.service.consul.", 10) - // Should match db* - expectResult("dblb.service.consul.", 66) - // Should match d* - expectResult("dk.service.consul.", 42) - // Should match * - expectResult("api.service.consul.", 5) -} - -func TestDNS_PreparedQuery_TTL(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeA) - t.Parallel() - a := NewTestAgent(t, ` - dns_config { - service_ttl = { - "d*" = "42s" - "db" = "10s" - "db*" = "66s" - "*" = "5s" - } - allow_stale = true - max_stale = "1s" - } - `) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") + c := new(dns.Client) + addr := a.config.DNSAddrs[0].String() + in, _, err := c.Exchange(m, addr) + require.NoError(t, err) - for idx, service := range []string{"db", "dblb", "dk", "api"} { - nodeName := fmt.Sprintf("foo%d", idx) - address := fmt.Sprintf("127.0.0.%d", idx) - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: nodeName, - Address: address, - Service: &structs.NodeService{ - Service: service, - Tags: []string{"primary"}, - Port: 12345 + idx, - }, - } + if tc.expectedServiceIPv4Address != "" { + require.Len(t, in.Answer, 1) + aRec, ok := in.Answer[0].(*dns.A) + require.True(t, ok, "Bad: %#v", in.Answer[0]) + require.Equal(t, question, aRec.Hdr.Name) + require.Equal(t, tc.expectedServiceIPv4Address, aRec.A.String()) + } else { + require.Len(t, in.Answer, 0) + } - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - // Register prepared query without TTL and with TTL - { - args := &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: service, - Service: structs.ServiceQuery{ - Service: service, - }, - }, - } + m = new(dns.Msg) + m.SetQuestion(question, dns.TypeAAAA) - var id string - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } - queryTTL := fmt.Sprintf("%s-ttl", service) - args = &structs.PreparedQueryRequest{ - Datacenter: "dc1", - Op: structs.PreparedQueryCreate, - Query: &structs.PreparedQuery{ - Name: queryTTL, - Service: structs.ServiceQuery{ - Service: service, - }, - DNS: structs.QueryDNSOptions{ - TTL: "18s", - }, - }, - } + c = new(dns.Client) + addr = a.config.DNSAddrs[0].String() + in, _, err = c.Exchange(m, addr) + require.NoError(t, err) - if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) + if tc.expectedServiceIPv6Address != "" { + require.Len(t, in.Answer, 1) + aRec, ok := in.Answer[0].(*dns.AAAA) + require.True(t, ok, "Bad: %#v", in.Answer[0]) + require.Equal(t, question, aRec.Hdr.Name) + require.Equal(t, tc.expectedServiceIPv6Address, aRec.AAAA.String()) + } else { + require.Len(t, in.Answer, 0) + } } - } - } - c := new(dns.Client) - expectResult := func(dnsQuery string, expectedTTL uint32) { - t.Run(dnsQuery, func(t *testing.T) { + // Look up node m := new(dns.Msg) - m.SetQuestion(dnsQuery, dns.TypeSRV) + m.SetQuestion("foo.node.consul.", dns.TypeA) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } + c := new(dns.Client) + addr := a.config.DNSAddrs[0].String() + in, _, err := c.Exchange(m, addr) + require.NoError(t, err) - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v, len is %d", in, len(in.Answer)) + if tc.expectedNodeIPv4Address != "" { + require.Len(t, in.Answer, 1) + aRec, ok := in.Answer[0].(*dns.A) + require.True(t, ok, "Bad: %#v", in.Answer[0]) + require.Equal(t, "foo.node.consul.", aRec.Hdr.Name) + require.Equal(t, tc.expectedNodeIPv4Address, aRec.A.String()) + } else { + require.Len(t, in.Answer, 0) } - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Hdr.Ttl != expectedTTL { - t.Fatalf("Bad: %#v", in.Answer[0]) - } + m = new(dns.Msg) + m.SetQuestion("foo.node.consul.", dns.TypeAAAA) + + c = new(dns.Client) + addr = a.config.DNSAddrs[0].String() + in, _, err = c.Exchange(m, addr) + require.NoError(t, err) - aRec, ok := in.Extra[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Ttl != expectedTTL { - t.Fatalf("Bad: %#v", in.Extra[0]) + if tc.expectedNodeIPv6Address != "" { + require.Len(t, in.Answer, 1) + aRec, ok := in.Answer[0].(*dns.AAAA) + require.True(t, ok, "Bad: %#v", in.Answer[0]) + require.Equal(t, "foo.node.consul.", aRec.Hdr.Name) + require.Equal(t, tc.expectedNodeIPv6Address, aRec.AAAA.String()) + } else { + require.Len(t, in.Answer, 0) } }) } - - // Should have its exact TTL - expectResult("db.query.consul.", 10) - expectResult("db-ttl.query.consul.", 18) - // Should match db* - expectResult("dblb.query.consul.", 66) - expectResult("dblb-ttl.query.consul.", 18) - // Should match d* - expectResult("dk.query.consul.", 42) - expectResult("dk-ttl.query.consul.", 18) - // Should be the default value - expectResult("api.query.consul.", 5) - expectResult("api-ttl.query.consul.", 18) } -func TestDNS_PreparedQuery_Failover(t *testing.T) { +func TestDNS_PreparedQueryNearIPEDNS(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - t.Parallel() - a1 := NewTestAgent(t, ` - datacenter = "dc1" - translate_wan_addrs = true - acl_datacenter = "" - `) - defer a1.Shutdown() + ipCoord := librtt.GenerateCoordinate(1 * time.Millisecond) + serviceNodes := []struct { + name string + address string + coord *coordinate.Coordinate + }{ + {"foo1", "198.18.0.1", librtt.GenerateCoordinate(1 * time.Millisecond)}, + {"foo2", "198.18.0.2", librtt.GenerateCoordinate(10 * time.Millisecond)}, + {"foo3", "198.18.0.3", librtt.GenerateCoordinate(30 * time.Millisecond)}, + } - a2 := NewTestAgent(t, ` - datacenter = "dc2" - translate_wan_addrs = true - acl_datacenter = "" - `) - defer a2.Shutdown() + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") - // Join WAN cluster. - addr := fmt.Sprintf("127.0.0.1:%d", a1.Config.SerfPortWAN) - if _, err := a2.JoinWAN([]string{addr}); err != nil { - t.Fatalf("err: %v", err) - } - retry.Run(t, func(r *retry.R) { - if got, want := len(a1.WANMembers()), 2; got < want { - r.Fatalf("got %d WAN members want at least %d", got, want) - } - if got, want := len(a2.WANMembers()), 2; got < want { - r.Fatalf("got %d WAN members want at least %d", got, want) - } - }) + added := 0 - // Register a remote node with a service. This is in a retry since we - // need the datacenter to have a route which takes a little more time - // beyond the join, and we don't have direct access to the router here. - retry.Run(t, func(r *retry.R) { + // Register nodes with a service + for _, cfg := range serviceNodes { args := &structs.RegisterRequest{ - Datacenter: "dc2", - Node: "foo", - Address: "127.0.0.1", - TaggedAddresses: map[string]string{ - "wan": "127.0.0.2", - }, + Datacenter: "dc1", + Node: cfg.name, + Address: cfg.address, Service: &structs.NodeService{ Service: "db", + Port: 12345, }, } var out struct{} - if err := a2.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - r.Fatalf("err: %v", err) + err := a.RPC(context.Background(), "Catalog.Register", args, &out) + require.NoError(t, err) + + // Send coordinate updates + coordArgs := structs.CoordinateUpdateRequest{ + Datacenter: "dc1", + Node: cfg.name, + Coord: cfg.coord, } - }) + err = a.RPC(context.Background(), "Coordinate.Update", &coordArgs, &out) + require.NoError(t, err) + + added += 1 + } + + fmt.Printf("Added %d service nodes\n", added) + + // Register a node without a service + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "198.18.0.9", + } + + var out struct{} + err := a.RPC(context.Background(), "Catalog.Register", args, &out) + require.NoError(t, err) + + // Send coordinate updates for a few nodes. + coordArgs := structs.CoordinateUpdateRequest{ + Datacenter: "dc1", + Node: "bar", + Coord: ipCoord, + } + err = a.RPC(context.Background(), "Coordinate.Update", &coordArgs, &out) + require.NoError(t, err) + } - // Register a local prepared query. + // Register a prepared query Near = _ip { args := &structs.PreparedQueryRequest{ Datacenter: "dc1", Op: structs.PreparedQueryCreate, Query: &structs.PreparedQuery{ - Name: "my-query", + Name: "some.query.we.like", Service: structs.ServiceQuery{ Service: "db", - Failover: structs.QueryFailoverOptions{ - Datacenters: []string{"dc2"}, - }, + Near: "_ip", }, }, } + var id string - if err := a1.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { - t.Fatalf("err: %v", err) - } + err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id) + require.NoError(t, err) } + retry.Run(t, func(r *retry.R) { + m := new(dns.Msg) + m.SetQuestion("some.query.we.like.query.consul.", dns.TypeA) + m.SetEdns0(4096, false) + o := new(dns.OPT) + o.Hdr.Name = "." + o.Hdr.Rrtype = dns.TypeOPT + e := new(dns.EDNS0_SUBNET) + e.Code = dns.EDNS0SUBNET + e.Family = 1 + e.SourceNetmask = 32 + e.SourceScope = 0 + e.Address = net.ParseIP("198.18.0.9").To4() + o.Option = append(o.Option, e) + m.Extra = append(m.Extra, o) - // Look up the SRV record via the query. - m := new(dns.Msg) - m.SetQuestion("my-query.query.consul.", dns.TypeSRV) - - c := new(dns.Client) - clAddr := a1.config.DNSAddrs[0] - in, _, err := c.Exchange(m, clAddr.String()) - if err != nil { - t.Fatalf("err: %v", err) - } + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + r.Fatalf("Error with call to dns.Client.Exchange: %s", err) + } - // Make sure we see the remote DC and that the address gets - // translated. - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } - if in.Answer[0].Header().Name != "my-query.query.consul." { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - srv, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srv.Target != "7f000002.addr.dc2.consul." { - t.Fatalf("Bad: %#v", in.Answer[0]) - } + if len(serviceNodes) != len(in.Answer) { + r.Fatalf("Expecting %d A RRs in response, Actual found was %d", len(serviceNodes), len(in.Answer)) + } - a, ok := in.Extra[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if a.Hdr.Name != "7f000002.addr.dc2.consul." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if a.A.String() != "127.0.0.2" { - t.Fatalf("Bad: %#v", in.Extra[0]) - } + for i, rr := range in.Answer { + if aRec, ok := rr.(*dns.A); ok { + if actual := aRec.A.String(); serviceNodes[i].address != actual { + r.Fatalf("Expecting A RR #%d = %s, Actual RR was %s", i, serviceNodes[i].address, actual) + } + } else { + r.Fatalf("DNS Answer contained a non-A RR") + } + } + }) } -func TestDNS_ServiceLookup_SRV_RFC(t *testing.T) { +func TestDNS_PreparedQueryNearIP(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - t.Parallel() + ipCoord := librtt.GenerateCoordinate(1 * time.Millisecond) + serviceNodes := []struct { + name string + address string + coord *coordinate.Coordinate + }{ + {"foo1", "198.18.0.1", librtt.GenerateCoordinate(1 * time.Millisecond)}, + {"foo2", "198.18.0.2", librtt.GenerateCoordinate(10 * time.Millisecond)}, + {"foo3", "198.18.0.3", librtt.GenerateCoordinate(30 * time.Millisecond)}, + } + a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") - // Register node - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - questions := []string{ - "_db._primary.service.dc1.consul.", - "_db._primary.service.consul.", - "_db._primary.dc1.consul.", - "_db._primary.consul.", - } - - for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) + added := 0 - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) + // Register nodes with a service + for _, cfg := range serviceNodes { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: cfg.name, + Address: cfg.address, + Service: &structs.NodeService{ + Service: "db", + Port: 12345, + }, } - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) - } + var out struct{} + err := a.RPC(context.Background(), "Catalog.Register", args, &out) + require.NoError(t, err) - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Answer[0]) + // Send coordinate updates + coordArgs := structs.CoordinateUpdateRequest{ + Datacenter: "dc1", + Node: cfg.name, + Coord: cfg.coord, } + err = a.RPC(context.Background(), "Coordinate.Update", &coordArgs, &out) + require.NoError(t, err) - aRec, ok := in.Extra[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Name != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.A.String() != "127.0.0.1" { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Extra[0]) - } + added += 1 } -} + fmt.Printf("Added %d service nodes\n", added) -func TestDNS_ServiceLookup_SRV_RFC_TCP_Default(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } + // Register a node without a service + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "bar", + Address: "198.18.0.9", + } - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") + var out struct{} + err := a.RPC(context.Background(), "Catalog.Register", args, &out) + require.NoError(t, err) - // Register node - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, + // Send coordinate updates for a few nodes. + coordArgs := structs.CoordinateUpdateRequest{ + Datacenter: "dc1", + Node: "bar", + Coord: ipCoord, + } + err = a.RPC(context.Background(), "Coordinate.Update", &coordArgs, &out) + require.NoError(t, err) } - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } + // Register a prepared query Near = _ip + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "some.query.we.like", + Service: structs.ServiceQuery{ + Service: "db", + Near: "_ip", + }, + }, + } - questions := []string{ - "_db._tcp.service.dc1.consul.", - "_db._tcp.service.consul.", - "_db._tcp.dc1.consul.", - "_db._tcp.consul.", + var id string + err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id) + require.NoError(t, err) } - for _, question := range questions { + retry.Run(t, func(r *retry.R) { m := new(dns.Msg) - m.SetQuestion(question, dns.TypeSRV) + m.SetQuestion("some.query.we.like.query.consul.", dns.TypeA) c := new(dns.Client) in, _, err := c.Exchange(m, a.DNSAddr()) if err != nil { - t.Fatalf("err: %v", err) + r.Fatalf("Error with call to dns.Client.Exchange: %s", err) } - if len(in.Answer) != 1 { - t.Fatalf("Bad: %#v", in) + if len(serviceNodes) != len(in.Answer) { + r.Fatalf("Expecting %d A RRs in response, Actual found was %d", len(serviceNodes), len(in.Answer)) } - srvRec, ok := in.Answer[0].(*dns.SRV) - if !ok { - t.Fatalf("Bad: %#v", in.Answer[0]) - } - if srvRec.Port != 12345 { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Target != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", srvRec) - } - if srvRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Answer[0]) + for i, rr := range in.Answer { + if aRec, ok := rr.(*dns.A); ok { + if actual := aRec.A.String(); serviceNodes[i].address != actual { + r.Fatalf("Expecting A RR #%d = %s, Actual RR was %s", i, serviceNodes[i].address, actual) + } + } else { + r.Fatalf("DNS Answer contained a non-A RR") + } } + }) +} - aRec, ok := in.Extra[0].(*dns.A) - if !ok { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Name != "foo.node.dc1.consul." { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.A.String() != "127.0.0.1" { - t.Fatalf("Bad: %#v", in.Extra[0]) - } - if aRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Extra[0]) - } +func TestDNS_Recurse(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") } -} + recursor := makeRecursor(t, dns.Msg{ + Answer: []dns.RR{dnsA("apple.com", "1.2.3.4")}, + }) + defer recursor.Shutdown() -func initDNSToken(t *testing.T, rpc RPC) { - t.Helper() + a := NewTestAgent(t, ` + recursors = ["`+recursor.Addr+`"] + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") - reqToken := structs.ACLTokenSetRequest{ - Datacenter: "dc1", - ACLToken: structs.ACLToken{ - SecretID: "279d4735-f8ca-4d48-b5cc-c00a9713bbf8", - Policies: nil, - TemplatedPolicies: []*structs.ACLTemplatedPolicy{{TemplateName: "builtin/dns"}}, - }, - WriteRequest: structs.WriteRequest{Token: "root"}, + m := new(dns.Msg) + m.SetQuestion("apple.com.", dns.TypeANY) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) } - err := rpc.RPC(context.Background(), "ACL.TokenSet", &reqToken, &structs.ACLToken{}) - require.NoError(t, err) + + if len(in.Answer) == 0 { + t.Fatalf("Bad: %#v", in) + } + if in.Rcode != dns.RcodeSuccess { + t.Fatalf("Bad: %#v", in) + } + } -func TestDNS_ServiceLookup_FilterACL(t *testing.T) { +func TestDNS_Recurse_Truncation(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - t.Parallel() - tests := []struct { - token string - results int - }{ - {"root", 1}, - {"anonymous", 0}, - {"dns", 1}, - } - for _, tt := range tests { - t.Run("ACLToken == "+tt.token, func(t *testing.T) { - hcl := ` - primary_datacenter = "dc1" - - acl { - enabled = true - default_policy = "deny" - down_policy = "deny" - - tokens { - initial_management = "root" -` - if tt.token == "dns" { - // Create a UUID for dns token since it doesn't have an alias - dnsToken := "279d4735-f8ca-4d48-b5cc-c00a9713bbf8" - - hcl = hcl + ` - default = "anonymous" - dns = "` + dnsToken + `" -` - } else { - hcl = hcl + ` - default = "` + tt.token + `" -` - } - - hcl = hcl + ` - } - } - ` - - a := NewTestAgent(t, hcl) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - if tt.token == "dns" { - initDNSToken(t, a) - } + recursor := makeRecursor(t, dns.Msg{ + MsgHdr: dns.MsgHdr{Truncated: true}, + Answer: []dns.RR{dnsA("apple.com", "1.2.3.4")}, + }) + defer recursor.Shutdown() - // Register a service - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo", - Address: "127.0.0.1", - Service: &structs.NodeService{ - Service: "foo", - Port: 12345, - }, - WriteRequest: structs.WriteRequest{Token: "root"}, - } - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } + a := NewTestAgent(t, ` + recursors = ["`+recursor.Addr+`"] + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") - // Set up the DNS query - c := new(dns.Client) - m := new(dns.Msg) - m.SetQuestion("foo.service.consul.", dns.TypeA) + m := new(dns.Msg) + m.SetQuestion("apple.com.", dns.TypeANY) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - if len(in.Answer) != tt.results { - t.Fatalf("Bad: %#v", in) - } - }) + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + if in.Truncated != true { + t.Fatalf("err: message should have been truncated %v", in) + } + if len(in.Answer) == 0 { + t.Fatalf("Bad: Truncated message ignored, expected some reply %#v", in) + } + if in.Rcode != dns.RcodeSuccess { + t.Fatalf("Bad: %#v", in) } } -func TestDNS_ServiceLookup_MetaTXT(t *testing.T) { +func TestDNS_RecursorTimeout(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = true }`) - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") + serverClientTimeout := 3 * time.Second + testClientTimeout := serverClientTimeout + 5*time.Second - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "127.0.0.1", - NodeMeta: map[string]string{ - "key": "value", - }, - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, + resolverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0") + if err != nil { + t.Error(err) } - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) + resolver, err := net.ListenUDP("udp", resolverAddr) + if err != nil { + t.Error(err) } + defer resolver.Close() + + a := NewTestAgent(t, ` + recursors = ["`+resolver.LocalAddr().String()+`"] // host must cause a connection|read|write timeout + dns_config { + recursor_timeout = "`+serverClientTimeout.String()+`" + } + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") m := new(dns.Msg) - m.SetQuestion("db.service.consul.", dns.TypeSRV) + m.SetQuestion("apple.com.", dns.TypeANY) - c := new(dns.Client) + // This client calling the server under test must have a longer timeout than the one we set internally + c := &dns.Client{Timeout: testClientTimeout} + + start := time.Now() in, _, err := c.Exchange(m, a.DNSAddr()) + + duration := time.Since(start) + if err != nil { t.Fatalf("err: %v", err) } - wantAdditional := []dns.RR{ - &dns.A{ - Hdr: dns.RR_Header{Name: "bar.node.dc1.consul.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4}, - A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1 - }, - &dns.TXT{ - Hdr: dns.RR_Header{Name: "bar.node.dc1.consul.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Rdlength: 0xa}, - Txt: []string{"key=value"}, - }, + if len(in.Answer) != 0 { + t.Fatalf("Bad: %#v", in) + } + if in.Rcode != dns.RcodeServerFailure { + t.Fatalf("Bad: %#v", in) + } + + if duration < serverClientTimeout { + t.Fatalf("Expected the call to return after at least %f seconds but lasted only %f", serverClientTimeout.Seconds(), duration.Seconds()) } - require.Equal(t, wantAdditional, in.Extra) } -func TestDNS_ServiceLookup_SuppressTXT(t *testing.T) { +// no way to run a v2 version of this test since it is calling a private function and not +// using a test agent. +func TestDNS_BinarySearch(t *testing.T) { + msgSrc := new(dns.Msg) + msgSrc.Compress = true + msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV) + + for i := 0; i < 5000; i++ { + target := fmt.Sprintf("host-redis-%d-%d.test.acme.com.node.dc1.consul.", i/256, i%256) + msgSrc.Answer = append(msgSrc.Answer, &dns.SRV{Hdr: dns.RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: dns.TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target}) + msgSrc.Extra = append(msgSrc.Extra, &dns.CNAME{Hdr: dns.RR_Header{Name: target, Class: 1, Rrtype: dns.TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", i/256, i%256)}) + } + for _, compress := range []bool{true, false} { + for idx, maxSize := range []int{12, 256, 512, 8192, 65535} { + t.Run(fmt.Sprintf("binarySearch %d", maxSize), func(t *testing.T) { + msg := new(dns.Msg) + msgSrc.Compress = compress + msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV) + msg.Answer = msgSrc.Answer + msg.Extra = msgSrc.Extra + msg.Ns = msgSrc.Ns + index := make(map[string]dns.RR, len(msg.Extra)) + indexRRs(msg.Extra, index) + blen := dnsBinaryTruncate(msg, maxSize, index, true) + msg.Answer = msg.Answer[:blen] + syncExtra(index, msg) + predicted := msg.Len() + buf, err := msg.Pack() + if err != nil { + t.Error(err) + } + if predicted < len(buf) { + t.Fatalf("Bug in DNS library: %d != %d", predicted, len(buf)) + } + if len(buf) > maxSize || (idx != 0 && len(buf) < 16) { + t.Fatalf("bad[%d]: %d > %d", idx, len(buf), maxSize) + } + }) + } + } +} + +func TestDNS_TCP_and_UDP_Truncate(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - a := NewTestAgent(t, `dns_config = { enable_additional_node_meta_txt = false }`) + a := NewTestAgent(t, ` + dns_config { + enable_truncate = true + } + `) defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") - // Register a node with a service. - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "bar", - Address: "127.0.0.1", - NodeMeta: map[string]string{ - "key": "value", - }, - Service: &structs.NodeService{ - Service: "db", - Tags: []string{"primary"}, - Port: 12345, - }, - } - - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } + services := []string{"normal", "truncated"} + for index, service := range services { + numServices := (index * 5000) + 2 + var eg errgroup.Group + for i := 1; i < numServices; i++ { + j := i + eg.Go(func() error { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: fmt.Sprintf("%s-%d.acme.com", service, j), + Address: fmt.Sprintf("127.%d.%d.%d", 0, (j / 255), j%255), + Service: &structs.NodeService{ + Service: service, + Port: 8000, + }, + } - m := new(dns.Msg) - m.SetQuestion("db.service.consul.", dns.TypeSRV) + var out struct{} + return a.RPC(context.Background(), "Catalog.Register", args, &out) + }) + } + if err := eg.Wait(); err != nil { + t.Fatalf("error registering: %v", err) + } - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: service, + Service: structs.ServiceQuery{ + Service: service, + }, + }, + } + if err := a.RPC(context.Background(), "PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } - wantAdditional := []dns.RR{ - &dns.A{ - Hdr: dns.RR_Header{Name: "bar.node.dc1.consul.", Rrtype: dns.TypeA, Class: dns.ClassINET, Rdlength: 0x4}, - A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1 - }, + // Look up the service directly and via prepared query. Ensure the + // response is truncated each time. + questions := []string{ + fmt.Sprintf("%s.service.consul.", service), + id + ".query.consul.", + } + protocols := []string{ + "tcp", + "udp", + } + for _, maxSize := range []uint16{8192, 65535} { + for _, qType := range []uint16{dns.TypeANY, dns.TypeA, dns.TypeSRV} { + for _, question := range questions { + for _, protocol := range protocols { + for _, compress := range []bool{true, false} { + t.Run(fmt.Sprintf("lookup %s %s (qType:=%d) compressed=%v", question, protocol, qType, compress), func(t *testing.T) { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeANY) + maxSz := maxSize + if protocol == "udp" { + maxSz = 8192 + } + m.SetEdns0(maxSz, true) + c := new(dns.Client) + c.Net = protocol + m.Compress = compress + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + // actually check if we need to have the truncate bit + resbuf, err := in.Pack() + if err != nil { + t.Fatalf("Error while packing answer: %s", err) + } + if !in.Truncated && len(resbuf) > int(maxSz) { + t.Fatalf("should have truncate bit %#v %#v", in, len(in.Answer)) + } + // Check for the truncate bit + buf, err := m.Pack() + info := fmt.Sprintf("service %s question:=%s (%s) (%d total records) sz:= %d in %v", + service, question, protocol, numServices, len(in.Answer), in) + if err != nil { + t.Fatalf("Error while packing: %v ; info:=%s", err, info) + } + if len(buf) > int(maxSz) { + t.Fatalf("len(buf) := %d > maxSz=%d for %v", len(buf), maxSz, info) + } + }) + } + } + } + } + } } - require.Equal(t, wantAdditional, in.Extra) } func TestDNS_AddressLookup(t *testing.T) { @@ -6514,7 +1528,6 @@ func TestDNS_AddressLookup(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -6540,6 +1553,8 @@ func TestDNS_AddressLookup(t *testing.T) { require.True(t, ok) require.Equal(t, aRec.A.To4().String(), answer) require.Zero(t, aRec.Hdr.Ttl) + require.Nil(t, in.Ns) + require.Nil(t, in.Extra) } } @@ -6548,7 +1563,6 @@ func TestDNS_AddressLookupANY(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -6580,7 +1594,6 @@ func TestDNS_AddressLookupInvalidType(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -6600,6 +1613,11 @@ func TestDNS_AddressLookupInvalidType(t *testing.T) { require.Nil(t, in.Answer) require.NotNil(t, in.Extra) require.Len(t, in.Extra, 1) + aRecord := in.Extra[0].(*dns.A) + require.Equal(t, "7f000001.addr.dc1.consul.", aRecord.Hdr.Name) + require.Equal(t, dns.TypeA, aRecord.Hdr.Rrtype) + require.Zero(t, aRecord.Hdr.Ttl) + require.Equal(t, "127.0.0.1", aRecord.A.String()) } } @@ -6608,7 +1626,6 @@ func TestDNS_AddressLookupIPV6(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -6653,7 +1670,6 @@ func TestDNS_AddressLookupIPV6InvalidType(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -6687,7 +1703,6 @@ func TestDNS_NonExistentDC_Server(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -6701,9 +1716,14 @@ func TestDNS_NonExistentDC_Server(t *testing.T) { t.Fatalf("err: %v", err) } - if in.Rcode != dns.RcodeNameError { - t.Fatalf("Expected RCode: %#v, had: %#v", dns.RcodeNameError, in.Rcode) - } + require.Equal(t, dns.RcodeNameError, in.Rcode) + require.Equal(t, 0, len(in.Answer)) + require.Equal(t, 0, len(in.Extra)) + require.Equal(t, 1, len(in.Ns)) + soa := in.Ns[0].(*dns.SOA) + require.Equal(t, "consul.", soa.Hdr.Name) + require.Equal(t, "ns.consul.", soa.Ns) + require.Equal(t, "hostmaster.consul.", soa.Mbox) } // TestDNS_NonExistentDC_RPC verifies NXDOMAIN is returned when @@ -6714,7 +1734,6 @@ func TestDNS_NonExistentDC_RPC(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() s := NewTestAgent(t, ` node_name = "test-server" `) @@ -6747,12 +1766,11 @@ func TestDNS_NonExistentDC_RPC(t *testing.T) { } } -func TestDNS_NonExistingLookup(t *testing.T) { +func TestDNS_NonExistentLookup(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -6780,12 +1798,11 @@ func TestDNS_NonExistingLookup(t *testing.T) { } } -func TestDNS_NonExistingLookupEmptyAorAAAA(t *testing.T) { +func TestDNS_NonExistentLookupEmptyAorAAAA(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -6863,25 +1880,27 @@ func TestDNS_NonExistingLookupEmptyAorAAAA(t *testing.T) { "webv4.query.consul.", } for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeAAAA) + t.Run(question, func(t *testing.T) { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeAAAA) - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } - require.Len(t, in.Ns, 1) - soaRec, ok := in.Ns[0].(*dns.SOA) - if !ok { - t.Fatalf("Bad: %#v", in.Ns[0]) - } - if soaRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Ns[0]) - } + require.Len(t, in.Ns, 1) + soaRec, ok := in.Ns[0].(*dns.SOA) + if !ok { + t.Fatalf("Bad: %#v", in.Ns[0]) + } + if soaRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Ns[0]) + } - require.Equal(t, dns.RcodeSuccess, in.Rcode) + require.Equal(t, dns.RcodeSuccess, in.Rcode) + }) } // Check for ipv4 records on ipv6-only service directly and via the @@ -6891,30 +1910,32 @@ func TestDNS_NonExistingLookupEmptyAorAAAA(t *testing.T) { "webv6.query.consul.", } for _, question := range questions { - m := new(dns.Msg) - m.SetQuestion(question, dns.TypeA) + t.Run(question, func(t *testing.T) { + m := new(dns.Msg) + m.SetQuestion(question, dns.TypeA) - c := new(dns.Client) - in, _, err := c.Exchange(m, a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } - if len(in.Ns) != 1 { - t.Fatalf("Bad: %#v", in) - } + if len(in.Ns) != 1 { + t.Fatalf("Bad: %#v", in) + } - soaRec, ok := in.Ns[0].(*dns.SOA) - if !ok { - t.Fatalf("Bad: %#v", in.Ns[0]) - } - if soaRec.Hdr.Ttl != 0 { - t.Fatalf("Bad: %#v", in.Ns[0]) - } + soaRec, ok := in.Ns[0].(*dns.SOA) + if !ok { + t.Fatalf("Bad: %#v", in.Ns[0]) + } + if soaRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Ns[0]) + } - if in.Rcode != dns.RcodeSuccess { - t.Fatalf("Bad: %#v", in) - } + if in.Rcode != dns.RcodeSuccess { + t.Fatalf("Bad: %#v", in) + } + }) } } @@ -6923,7 +1944,6 @@ func TestDNS_AltDomains_Service(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, ` alt_domain = "test-domain." `) @@ -7018,7 +2038,6 @@ func TestDNS_AltDomains_SOA(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, ` node_name = "test-node" alt_domain = "test-domain." @@ -7070,7 +2089,6 @@ func TestDNS_AltDomains_Overlap(t *testing.T) { // this tests the domain matching logic in DNSServer when encountering more // than one potential match (i.e. ambiguous match) // it should select the longer matching domain when dispatching - t.Parallel() a := NewTestAgent(t, ` node_name = "test-node" alt_domain = "test.consul." @@ -7117,7 +2135,6 @@ func TestDNS_AltDomain_DCName_Overlap(t *testing.T) { // this tests the DC name overlap with the consul domain/alt-domain // we should get response when DC suffix is a prefix of consul alt-domain - t.Parallel() a := NewTestAgent(t, ` datacenter = "dc-test" node_name = "test-node" @@ -7154,7 +2171,6 @@ func TestDNS_PreparedQuery_AllowStale(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, ` dns_config { allow_stale = true @@ -7199,7 +2215,6 @@ func TestDNS_PreparedQuery_AllowStale(t *testing.T) { if soaRec.Hdr.Ttl != 0 { t.Fatalf("Bad: %#v", in.Ns[0]) } - } } @@ -7208,7 +2223,6 @@ func TestDNS_InvalidQueries(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -7245,7 +2259,6 @@ func TestDNS_InvalidQueries(t *testing.T) { if soaRec.Hdr.Ttl != 0 { t.Fatalf("Bad: %#v", in.Ns[0]) } - } } @@ -7254,7 +2267,6 @@ func TestDNS_PreparedQuery_AgentSource(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -7291,7 +2303,6 @@ func TestDNS_EDNS_Truncate_AgentSource(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, ` dns_config { enable_truncate = true @@ -7332,7 +2343,6 @@ func TestDNS_EDNS_Truncate_AgentSource(t *testing.T) { } func TestDNS_trimUDPResponse_NoTrim(t *testing.T) { - t.Parallel() req := &dns.Msg{} resp := &dns.Msg{ Answer: []dns.RR{ @@ -7357,7 +2367,7 @@ func TestDNS_trimUDPResponse_NoTrim(t *testing.T) { }, } - cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy"`) + cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `) if trimmed := trimUDPResponse(req, resp, cfg.DNSUDPAnswerLimit); trimmed { t.Fatalf("Bad %#v", *resp) } @@ -7390,8 +2400,7 @@ func TestDNS_trimUDPResponse_NoTrim(t *testing.T) { } func TestDNS_trimUDPResponse_TrimLimit(t *testing.T) { - t.Parallel() - cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy"`) + cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `) req, resp, expected := &dns.Msg{}, &dns.Msg{}, &dns.Msg{} for i := 0; i < cfg.DNSUDPAnswerLimit+1; i++ { @@ -7430,8 +2439,7 @@ func TestDNS_trimUDPResponse_TrimLimit(t *testing.T) { } func TestDNS_trimUDPResponse_TrimLimitWithNS(t *testing.T) { - t.Parallel() - cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy"`) + cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `) req, resp, expected := &dns.Msg{}, &dns.Msg{}, &dns.Msg{} for i := 0; i < cfg.DNSUDPAnswerLimit+1; i++ { @@ -7478,8 +2486,7 @@ func TestDNS_trimUDPResponse_TrimLimitWithNS(t *testing.T) { } func TestDNS_trimTCPResponse_TrimLimitWithNS(t *testing.T) { - t.Parallel() - cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy"`) + cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `) req, resp, expected := &dns.Msg{}, &dns.Msg{}, &dns.Msg{} for i := 0; i < 5000; i++ { @@ -7535,8 +2542,7 @@ func loadRuntimeConfig(t *testing.T, hcl string) *config.RuntimeConfig { } func TestDNS_trimUDPResponse_TrimSize(t *testing.T) { - t.Parallel() - cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy"`) + cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `) req, resp := &dns.Msg{}, &dns.Msg{} for i := 0; i < 100; i++ { @@ -7588,8 +2594,7 @@ func TestDNS_trimUDPResponse_TrimSize(t *testing.T) { } func TestDNS_trimUDPResponse_TrimSizeEDNS(t *testing.T) { - t.Parallel() - cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy"`) + cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `) req, resp := &dns.Msg{}, &dns.Msg{} @@ -7667,8 +2672,7 @@ func TestDNS_trimUDPResponse_TrimSizeEDNS(t *testing.T) { } func TestDNS_trimUDPResponse_TrimSizeMaxSize(t *testing.T) { - t.Parallel() - cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy"`) + cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `) resp := &dns.Msg{} @@ -7712,11 +2716,9 @@ func TestDNS_trimUDPResponse_TrimSizeMaxSize(t *testing.T) { if len(respEDNS.Answer) == 0 || len(respEDNS.Answer) != len(respEDNS.Extra) { t.Errorf("bad edns answer length: %#v", resp) } - } func TestDNS_syncExtra(t *testing.T) { - t.Parallel() resp := &dns.Msg{ Answer: []dns.RR{ // These two are on the same host so the redundant extra @@ -7940,8 +2942,7 @@ func TestDNS_syncExtra(t *testing.T) { } func TestDNS_Compression_trimUDPResponse(t *testing.T) { - t.Parallel() - cfg := loadRuntimeConfig(t, `data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy"`) + cfg := loadRuntimeConfig(t, `data_dir = "a" bind_addr = "127.0.0.1" node_name = "dummy" `) req, m := dns.Msg{}, dns.Msg{} trimUDPResponse(&req, &m, cfg.DNSUDPAnswerLimit) @@ -7963,7 +2964,6 @@ func TestDNS_Compression_Query(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -8049,68 +3049,11 @@ func TestDNS_Compression_Query(t *testing.T) { } } -func TestDNS_Compression_ReverseLookup(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - a := NewTestAgent(t, "") - defer a.Shutdown() - testrpc.WaitForLeader(t, a.RPC, "dc1") - - // Register node. - args := &structs.RegisterRequest{ - Datacenter: "dc1", - Node: "foo2", - Address: "127.0.0.2", - } - var out struct{} - if err := a.RPC(context.Background(), "Catalog.Register", args, &out); err != nil { - t.Fatalf("err: %v", err) - } - - m := new(dns.Msg) - m.SetQuestion("2.0.0.127.in-addr.arpa.", dns.TypeANY) - - conn, err := dns.Dial("udp", a.DNSAddr()) - if err != nil { - t.Fatalf("err: %v", err) - } - - // Do a manual exchange with compression on (the default). - if err := conn.WriteMsg(m); err != nil { - t.Fatalf("err: %v", err) - } - p := make([]byte, dns.MaxMsgSize) - compressed, err := conn.Read(p) - if err != nil { - t.Fatalf("err: %v", err) - } - - // Disable compression and try again. - a.DNSDisableCompression(true) - if err := conn.WriteMsg(m); err != nil { - t.Fatalf("err: %v", err) - } - unc, err := conn.Read(p) - if err != nil { - t.Fatalf("err: %v", err) - } - - // We can't see the compressed status given the DNS API, so we just make - // sure the message is smaller to see if it's respecting the flag. - if compressed == 0 || unc == 0 || compressed >= unc { - t.Fatalf("doesn't look compressed: %d vs. %d", compressed, unc) - } -} - func TestDNS_Compression_Recurse(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - t.Parallel() recursor := makeRecursor(t, dns.Msg{ Answer: []dns.RR{dnsA("apple.com", "1.2.3.4")}, }) @@ -8157,36 +3100,13 @@ func TestDNS_Compression_Recurse(t *testing.T) { } } -func TestDNSInvalidRegex(t *testing.T) { - tests := []struct { - desc string - in string - invalid bool - }{ - {"Valid Hostname", "testnode", false}, - {"Valid Hostname", "test-node", false}, - {"Invalid Hostname with special chars", "test#$$!node", true}, - {"Invalid Hostname with special chars in the end", "testnode%^", true}, - {"Whitespace", " ", true}, - {"Only special chars", "./$", true}, - } - for _, test := range tests { - t.Run(test.desc, func(t *testing.T) { - if got, want := agentdns.InvalidNameRe.MatchString(test.in), test.invalid; got != want { - t.Fatalf("Expected %v to return %v", test.in, want) - } - }) - - } -} - -func TestDNS_ConfigReload(t *testing.T) { +// TestDNS_V1ConfigReload validates that the dns configuration is saved to the +// DNS server when v1 DNS is configured and reload config internal is called. +func TestDNS_V1ConfigReload(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") } - t.Parallel() - a := NewTestAgent(t, ` recursors = ["8.8.8.8:53"] dns_config = { @@ -8216,9 +3136,12 @@ func TestDNS_ConfigReload(t *testing.T) { testrpc.WaitForLeader(t, a.RPC, "dc1") for _, s := range a.dnsServers { - cfg := s.config.Load().(*dnsConfig) + server, ok := s.(*DNSServer) + require.True(t, ok) + + cfg := server.config.Load().(*dnsServerConfig) require.Equal(t, []string{"8.8.8.8:53"}, cfg.Recursors) - require.Equal(t, agentdns.RecursorStrategy("sequential"), cfg.RecursorStrategy) + require.Equal(t, structs.RecursorStrategy("sequential"), cfg.RecursorStrategy) require.False(t, cfg.AllowStale) require.Equal(t, 20*time.Second, cfg.MaxStale) require.Equal(t, 10*time.Second, cfg.NodeTTL) @@ -8263,9 +3186,12 @@ func TestDNS_ConfigReload(t *testing.T) { require.NoError(t, err) for _, s := range a.dnsServers { - cfg := s.config.Load().(*dnsConfig) + server, ok := s.(*DNSServer) + require.True(t, ok) + + cfg := server.config.Load().(*dnsServerConfig) require.Equal(t, []string{"1.1.1.1:53"}, cfg.Recursors) - require.Equal(t, agentdns.RecursorStrategy("random"), cfg.RecursorStrategy) + require.Equal(t, structs.RecursorStrategy("random"), cfg.RecursorStrategy) require.True(t, cfg.AllowStale) require.Equal(t, 21*time.Second, cfg.MaxStale) require.Equal(t, 11*time.Second, cfg.NodeTTL) @@ -8295,7 +3221,6 @@ func TestDNS_ReloadConfig_DuringQuery(t *testing.T) { t.Skip("too slow for testing.Short") } - t.Parallel() a := NewTestAgent(t, "") defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -8358,7 +3283,7 @@ func TestDNS_ReloadConfig_DuringQuery(t *testing.T) { } } -func TestECSNotGlobalError(t *testing.T) { +func TestDNS_ECSNotGlobalError(t *testing.T) { t.Run("wrap nil", func(t *testing.T) { e := ecsNotGlobalError{} require.True(t, errors.Is(e, errECSNotGlobal)) @@ -8390,7 +3315,7 @@ func perfectlyRandomChoices(size int, frac float64) []bool { return out } -func TestPerfectlyRandomChoices(t *testing.T) { +func TestDNS_PerfectlyRandomChoices(t *testing.T) { count := func(got []bool) int { var x int for _, v := range got { @@ -8442,3 +3367,75 @@ func TestPerfectlyRandomChoices(t *testing.T) { }) } } + +type testCaseParseLocality struct { + name string + labels []string + defaultEntMeta acl.EnterpriseMeta + enterpriseDNSConfig enterpriseDNSConfig + expectedResult queryLocality + expectedOK bool +} + +func TestDNS_ParseLocality(t *testing.T) { + testCases := getTestCasesParseLocality() + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + d := &DNSServer{ + defaultEnterpriseMeta: tc.defaultEntMeta, + } + actualResult, actualOK := d.parseLocality(tc.labels, + &dnsRequestConfig{ + dnsServerConfig: &dnsServerConfig{ + enterpriseDNSConfig: tc.enterpriseDNSConfig, + }, + defaultEnterpriseMeta: tc.defaultEntMeta, + }) + require.Equal(t, tc.expectedOK, actualOK) + require.Equal(t, tc.expectedResult, actualResult) + + }) + } + +} + +func TestDNS_EffectiveDatacenter(t *testing.T) { + type testCase struct { + name string + queryLocality queryLocality + defaultDC string + expected string + } + testCases := []testCase{ + { + name: "return datacenter first", + queryLocality: queryLocality{ + datacenter: "test-dc", + peerOrDatacenter: "test-peer", + }, + defaultDC: "default-dc", + expected: "test-dc", + }, + { + name: "return PeerOrDatacenter second", + queryLocality: queryLocality{ + peerOrDatacenter: "test-peer", + }, + defaultDC: "default-dc", + expected: "test-peer", + }, + { + name: "return defaultDC as fallback", + queryLocality: queryLocality{}, + defaultDC: "default-dc", + expected: "default-dc", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := tc.queryLocality.effectiveDatacenter(tc.defaultDC) + require.Equal(t, tc.expected, got) + }) + } +} diff --git a/agent/envoyextensions/builtin/ext-authz/structs.go b/agent/envoyextensions/builtin/ext-authz/structs.go index 0a7e7dcce43a..d85d6c022587 100644 --- a/agent/envoyextensions/builtin/ext-authz/structs.go +++ b/agent/envoyextensions/builtin/ext-authz/structs.go @@ -547,8 +547,7 @@ func (s *StringMatcher) toEnvoy() *envoy_type_matcher_v3.StringMatcher { return &envoy_type_matcher_v3.StringMatcher{ MatchPattern: &envoy_type_matcher_v3.StringMatcher_SafeRegex{ SafeRegex: &envoy_type_matcher_v3.RegexMatcher{ - EngineType: &envoy_type_matcher_v3.RegexMatcher_GoogleRe2{}, - Regex: s.SafeRegex, + Regex: s.SafeRegex, }, }, } diff --git a/agent/envoyextensions/builtin/lua/lua.go b/agent/envoyextensions/builtin/lua/lua.go index ba08d9d286c0..91e912842ef4 100644 --- a/agent/envoyextensions/builtin/lua/lua.go +++ b/agent/envoyextensions/builtin/lua/lua.go @@ -6,6 +6,7 @@ package lua import ( "errors" "fmt" + envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_lua_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/lua/v3" @@ -97,7 +98,11 @@ func (l *lua) PatchFilter(p extensioncommon.FilterPayload) (*envoy_listener_v3.F luaHttpFilter, err := extensioncommon.MakeEnvoyHTTPFilter( "envoy.filters.http.lua", &envoy_lua_v3.Lua{ - InlineCode: l.Script, + DefaultSourceCode: &envoy_core_v3.DataSource{ + Specifier: &envoy_core_v3.DataSource_InlineString{ + InlineString: l.Script, + }, + }, }, ) if err != nil { diff --git a/agent/event_endpoint_test.go b/agent/event_endpoint_test.go index a041088c448c..f28b913cfd00 100644 --- a/agent/event_endpoint_test.go +++ b/agent/event_endpoint_test.go @@ -234,7 +234,7 @@ func TestEventList_ACLFilter(t *testing.T) { t.Run("token with access to one event type", func(t *testing.T) { retry.Run(t, func(r *retry.R) { - token := testCreateToken(t, a, ` + token := testCreateToken(r, a, ` event "foo" { policy = "read" } diff --git a/agent/grpc-external/server.go b/agent/grpc-external/server.go index 30af8f2e6e1a..8e3928eb7d82 100644 --- a/agent/grpc-external/server.go +++ b/agent/grpc-external/server.go @@ -4,20 +4,30 @@ package external import ( + "context" + "fmt" + "strings" "time" "github.com/armon/go-metrics" middleware "github.com/grpc-ecosystem/go-grpc-middleware" recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" + "github.com/hashi-derek/grpc-proxy/proxy" + "github.com/hashicorp/go-hclog" "google.golang.org/grpc" + "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/keepalive" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" "github.com/hashicorp/consul/agent/consul/rate" agentmiddleware "github.com/hashicorp/consul/agent/grpc-middleware" "github.com/hashicorp/consul/tlsutil" ) +const FORWARD_SERVICE_NAME_PREFIX = "/hashicorp.consul." + var ( metricsLabels = []metrics.Label{{ Name: "server_type", @@ -28,11 +38,12 @@ var ( // NewServer constructs a gRPC server for the external gRPC port, to which // handlers can be registered. func NewServer( - logger agentmiddleware.Logger, + logger hclog.Logger, metricsObj *metrics.Metrics, tls *tlsutil.Configurator, limiter rate.RequestLimitsHandler, keepaliveParams keepalive.ServerParameters, + serverConn *grpc.ClientConn, ) *grpc.Server { if metricsObj == nil { metricsObj = metrics.Default() @@ -71,6 +82,11 @@ func NewServer( }), } + // forward FORWARD_SERVICE_NAME_PREFIX services from client agent to server agent + if serverConn != nil { + opts = append(opts, grpc.UnknownServiceHandler(proxy.TransparentHandler(makeDirector(serverConn, logger)))) + } + if tls != nil { // Attach TLS credentials, if provided. tlsCreds := agentmiddleware.NewOptionalTransportCredentials( @@ -80,3 +96,24 @@ func NewServer( } return grpc.NewServer(opts...) } + +func makeDirector(serverConn *grpc.ClientConn, logger hclog.Logger) func(ctx context.Context, fullMethodName string) (context.Context, *grpc.ClientConn, error) { + return func(ctx context.Context, fullMethodName string) (context.Context, *grpc.ClientConn, error) { + var mdCopy metadata.MD + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + mdCopy = metadata.MD{} + } else { + mdCopy = md.Copy() + } + outCtx := metadata.NewOutgoingContext(ctx, mdCopy) + + logger.Debug("forwarding the request to the consul server", "method", fullMethodName) + // throw unimplemented error if the method is not meant to be forwarded + if !strings.HasPrefix(fullMethodName, FORWARD_SERVICE_NAME_PREFIX) { + return outCtx, nil, status.Errorf(codes.Unimplemented, fmt.Sprintf("Unknown method %s", fullMethodName)) + } + + return outCtx, serverConn, nil + } +} diff --git a/agent/grpc-external/services/acl/server.go b/agent/grpc-external/services/acl/server.go index 2393f11aa106..cc7e35d1e622 100644 --- a/agent/grpc-external/services/acl/server.go +++ b/agent/grpc-external/services/acl/server.go @@ -53,8 +53,8 @@ func NewServer(cfg Config) *Server { return &Server{cfg} } -func (s *Server) Register(grpcServer *grpc.Server) { - pbacl.RegisterACLServiceServer(grpcServer, s) +func (s *Server) Register(registrar grpc.ServiceRegistrar) { + pbacl.RegisterACLServiceServer(registrar, s) } func (s *Server) requireACLsEnabled(logger hclog.Logger) error { diff --git a/agent/grpc-external/services/configentry/server.go b/agent/grpc-external/services/configentry/server.go new file mode 100644 index 000000000000..15b989515912 --- /dev/null +++ b/agent/grpc-external/services/configentry/server.go @@ -0,0 +1,133 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package configentry + +import ( + "context" + "fmt" + "time" + + "github.com/armon/go-metrics" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-memdb" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + grpcstatus "google.golang.org/grpc/status" + + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/acl/resolver" + "github.com/hashicorp/consul/agent/blockingquery" + "github.com/hashicorp/consul/agent/consul/state" + external "github.com/hashicorp/consul/agent/grpc-external" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/proto/private/pbconfigentry" +) + +// Server implements pbconfigentry.ConfigEntryService to provide RPC operations related to +// configentries +type Server struct { + Config +} + +type Config struct { + Backend Backend + Logger hclog.Logger + ForwardRPC func(structs.RPCInfo, func(*grpc.ClientConn) error) (bool, error) + FSMServer blockingquery.FSMServer +} + +type Backend interface { + EnterpriseCheckPartitions(partition string) error + + ResolveTokenAndDefaultMeta(token string, entMeta *acl.EnterpriseMeta, authzCtx *acl.AuthorizerContext) (resolver.Result, error) +} + +func NewServer(cfg Config) *Server { + external.RequireNotNil(cfg.Backend, "Backend") + external.RequireNotNil(cfg.Logger, "Logger") + external.RequireNotNil(cfg.FSMServer, "FSMServer") + + return &Server{ + Config: cfg, + } +} + +var _ pbconfigentry.ConfigEntryServiceServer = (*Server)(nil) + +type readRequest struct { + structs.QueryOptions + structs.DCSpecificRequest +} + +func (s *Server) Register(grpcServer grpc.ServiceRegistrar) { + pbconfigentry.RegisterConfigEntryServiceServer(grpcServer, s) +} + +func (s *Server) GetResolvedExportedServices( + ctx context.Context, + req *pbconfigentry.GetResolvedExportedServicesRequest, +) (*pbconfigentry.GetResolvedExportedServicesResponse, error) { + + if err := s.Backend.EnterpriseCheckPartitions(req.Partition); err != nil { + return nil, grpcstatus.Error(codes.InvalidArgument, err.Error()) + } + + options, err := external.QueryOptionsFromContext(ctx) + if err != nil { + return nil, err + } + + var resp *pbconfigentry.GetResolvedExportedServicesResponse + var emptyDCSpecificRequest structs.DCSpecificRequest + + handled, err := s.ForwardRPC(&readRequest{options, emptyDCSpecificRequest}, func(conn *grpc.ClientConn) error { + var err error + resp, err = pbconfigentry.NewConfigEntryServiceClient(conn).GetResolvedExportedServices(ctx, req) + return err + }) + if handled || err != nil { + return resp, err + } + + defer metrics.MeasureSince([]string{"configentry", "get_resolved_exported_services"}, time.Now()) + + var authzCtx acl.AuthorizerContext + entMeta := structs.DefaultEnterpriseMetaInPartition(req.Partition) + + authz, err := s.Backend.ResolveTokenAndDefaultMeta(options.Token, entMeta, &authzCtx) + if err != nil { + return nil, err + } + + if err := authz.ToAllowAuthorizer().MeshReadAllowed(&authzCtx); err != nil { + return nil, err + } + + res := &pbconfigentry.GetResolvedExportedServicesResponse{} + meta := structs.QueryMeta{} + err = blockingquery.Query(s.FSMServer, &options, &meta, func(ws memdb.WatchSet, store *state.Store) error { + idx, exportedSvcs, err := store.ResolvedExportedServices(ws, entMeta) + if err != nil { + return err + } + + meta.SetIndex(idx) + + res.Services = exportedSvcs + return nil + }) + if err != nil { + return nil, fmt.Errorf("error executing exported services blocking query: %w", err) + } + + header, err := external.GRPCMetadataFromQueryMeta(meta) + if err != nil { + return nil, fmt.Errorf("could not convert query metadata to gRPC header") + } + if err := grpc.SendHeader(ctx, header); err != nil { + return nil, fmt.Errorf("could not send gRPC header") + } + + return res, nil +} diff --git a/agent/grpc-external/services/configentry/server_ce_test.go b/agent/grpc-external/services/configentry/server_ce_test.go new file mode 100644 index 000000000000..953cbde464e1 --- /dev/null +++ b/agent/grpc-external/services/configentry/server_ce_test.go @@ -0,0 +1,83 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package configentry + +import ( + "context" + "testing" + + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/agent/grpc-external/testutils" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/proto/private/pbconfigentry" + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" +) + +func TestGetResolvedExportedServices(t *testing.T) { + authorizer := acl.MockAuthorizer{} + authorizer.On("MeshRead", mock.Anything).Return(acl.Allow) + + backend := &MockBackend{authorizer: &authorizer} + backend.On("EnterpriseCheckPartitions", mock.Anything).Return(nil) + + fakeFSM := testutils.NewFakeBlockingFSM(t) + + c := Config{ + Backend: backend, + Logger: hclog.New(nil), + ForwardRPC: doForwardRPC, + FSMServer: fakeFSM, + } + server := NewServer(c) + + // Add config entry + entry := &structs.ExportedServicesConfigEntry{ + Name: "default", + Services: []structs.ExportedService{ + { + Name: "db", + Consumers: []structs.ServiceConsumer{ + { + Peer: "east", + }, + { + Peer: "west", + }, + }, + }, + { + Name: "cache", + Consumers: []structs.ServiceConsumer{ + { + Peer: "east", + }, + }, + }, + }, + } + fakeFSM.GetState().EnsureConfigEntry(1, entry) + + expected := []*pbconfigentry.ResolvedExportedService{ + { + Service: "cache", + Consumers: &pbconfigentry.Consumers{ + Peers: []string{"east"}, + }, + }, + { + Service: "db", + Consumers: &pbconfigentry.Consumers{ + Peers: []string{"east", "west"}, + }, + }, + } + + ctx := grpc.NewContextWithServerTransportStream(context.Background(), &testutils.MockServerTransportStream{}) + resp, err := server.GetResolvedExportedServices(ctx, &pbconfigentry.GetResolvedExportedServicesRequest{}) + require.NoError(t, err) + require.Equal(t, expected, resp.Services) +} diff --git a/agent/grpc-external/services/configentry/server_test.go b/agent/grpc-external/services/configentry/server_test.go new file mode 100644 index 000000000000..f89d15233e1a --- /dev/null +++ b/agent/grpc-external/services/configentry/server_test.go @@ -0,0 +1,236 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package configentry + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/armon/go-metrics" + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/acl/resolver" + "github.com/hashicorp/consul/agent/grpc-external/testutils" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/proto/private/pbconfigentry" + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" +) + +type MockBackend struct { + mock.Mock + authorizer acl.Authorizer +} + +func (m *MockBackend) ResolveTokenAndDefaultMeta(string, *acl.EnterpriseMeta, *acl.AuthorizerContext) (resolver.Result, error) { + return resolver.Result{Authorizer: m.authorizer}, nil +} + +func (m *MockBackend) EnterpriseCheckPartitions(partition string) error { + called := m.Called(partition) + ret := called.Get(0) + + if ret == nil { + return nil + } else { + return ret.(error) + } +} + +func TestGetResolvedExportedServices_ACL_Deny(t *testing.T) { + authorizer := acl.MockAuthorizer{} + authorizer.On("MeshRead", mock.Anything).Return(acl.Deny) + + backend := &MockBackend{authorizer: &authorizer} + backend.On("EnterpriseCheckPartitions", mock.Anything).Return(nil) + + fakeFSM := testutils.NewFakeBlockingFSM(t) + + c := Config{ + Backend: backend, + Logger: hclog.New(nil), + ForwardRPC: doForwardRPC, + FSMServer: fakeFSM, + } + + server := NewServer(c) + + _, err := server.GetResolvedExportedServices(context.Background(), &pbconfigentry.GetResolvedExportedServicesRequest{}) + require.Error(t, err) +} + +func TestGetResolvedExportedServices_AC_Allow(t *testing.T) { + authorizer := acl.MockAuthorizer{} + authorizer.On("MeshRead", mock.Anything).Return(acl.Allow) + + backend := &MockBackend{authorizer: &authorizer} + backend.On("EnterpriseCheckPartitions", mock.Anything).Return(nil) + + fakeFSM := testutils.NewFakeBlockingFSM(t) + + c := Config{ + Backend: backend, + Logger: hclog.New(nil), + ForwardRPC: doForwardRPC, + FSMServer: fakeFSM, + } + server := NewServer(c) + + ctx := grpc.NewContextWithServerTransportStream(context.Background(), &testutils.MockServerTransportStream{}) + _, err := server.GetResolvedExportedServices(ctx, &pbconfigentry.GetResolvedExportedServicesRequest{}) + require.NoError(t, err) +} + +func TestGetResolvedExportedServices_PartitionCheck(t *testing.T) { + authorizer := acl.MockAuthorizer{} + authorizer.On("MeshRead", mock.Anything).Return(acl.Allow) + + backend := &MockBackend{authorizer: &authorizer} + backend.On("EnterpriseCheckPartitions", mock.Anything).Return(fmt.Errorf("partition not supported")) + + fakeFSM := testutils.NewFakeBlockingFSM(t) + + c := Config{ + Backend: backend, + Logger: hclog.New(nil), + ForwardRPC: doForwardRPC, + FSMServer: fakeFSM, + } + + server := NewServer(c) + + ctx := grpc.NewContextWithServerTransportStream(context.Background(), &testutils.MockServerTransportStream{}) + + resp, err := server.GetResolvedExportedServices(ctx, &pbconfigentry.GetResolvedExportedServicesRequest{}) + require.EqualError(t, err, "rpc error: code = InvalidArgument desc = partition not supported") + require.Nil(t, resp) +} + +func TestGetResolvedExportedServices_Index(t *testing.T) { + authorizer := acl.MockAuthorizer{} + authorizer.On("MeshRead", mock.Anything).Return(acl.Allow) + + backend := &MockBackend{authorizer: &authorizer} + backend.On("EnterpriseCheckPartitions", mock.Anything).Return(nil) + + fakeFSM := testutils.NewFakeBlockingFSM(t) + + c := Config{ + Backend: backend, + Logger: hclog.New(nil), + ForwardRPC: doForwardRPC, + FSMServer: fakeFSM, + } + server := NewServer(c) + + // Add config entry + entry := &structs.ExportedServicesConfigEntry{ + Name: "default", + Services: []structs.ExportedService{ + { + Name: "db", + Consumers: []structs.ServiceConsumer{ + { + Peer: "east", + }, + { + Peer: "west", + }, + }, + }, + { + Name: "cache", + Consumers: []structs.ServiceConsumer{ + { + Peer: "east", + }, + }, + }, + }, + } + fakeFSM.GetState().EnsureConfigEntry(1, entry) + + headerStream := &testutils.MockServerTransportStream{} + + ctx := grpc.NewContextWithServerTransportStream(context.Background(), headerStream) + resp, err := server.GetResolvedExportedServices(ctx, &pbconfigentry.GetResolvedExportedServicesRequest{}) + require.NoError(t, err) + require.Equal(t, 2, len(resp.Services)) + require.Equal(t, []string{"1"}, headerStream.MD.Get("index")) + + // Updating the index + fakeFSM.GetState().EnsureConfigEntry(2, entry) + + headerStream = &testutils.MockServerTransportStream{} + + ctx = grpc.NewContextWithServerTransportStream(context.Background(), headerStream) + resp, err = server.GetResolvedExportedServices(ctx, &pbconfigentry.GetResolvedExportedServicesRequest{}) + require.NoError(t, err) + require.Equal(t, 2, len(resp.Services)) + require.Equal(t, []string{"2"}, headerStream.MD.Get("index")) +} + +func TestGetResolvedExportedServices_Metrics(t *testing.T) { + sink := metrics.NewInmemSink(5*time.Second, time.Minute) + cfg := metrics.DefaultConfig("consul") + metrics.NewGlobal(cfg, sink) + + authorizer := acl.MockAuthorizer{} + authorizer.On("MeshRead", mock.Anything).Return(acl.Allow) + + backend := &MockBackend{authorizer: &authorizer} + backend.On("EnterpriseCheckPartitions", mock.Anything).Return(nil) + + fakeFSM := testutils.NewFakeBlockingFSM(t) + + c := Config{ + Backend: backend, + Logger: hclog.New(nil), + ForwardRPC: doForwardRPC, + FSMServer: fakeFSM, + } + server := NewServer(c) + + // Add config entry + entry := &structs.ExportedServicesConfigEntry{ + Name: "default", + Services: []structs.ExportedService{ + { + Name: "db", + Consumers: []structs.ServiceConsumer{ + { + Peer: "east", + }, + { + Peer: "west", + }, + }, + }, + { + Name: "cache", + Consumers: []structs.ServiceConsumer{ + { + Peer: "east", + }, + }, + }, + }, + } + fakeFSM.GetState().EnsureConfigEntry(1, entry) + + ctx := grpc.NewContextWithServerTransportStream(context.Background(), &testutils.MockServerTransportStream{}) + resp, err := server.GetResolvedExportedServices(ctx, &pbconfigentry.GetResolvedExportedServicesRequest{}) + require.NoError(t, err) + require.Equal(t, 2, len(resp.Services)) + + // Checking if metrics were added + require.NotNil(t, sink.Data()[0].Samples[`consul.configentry.get_resolved_exported_services`]) +} + +func doForwardRPC(structs.RPCInfo, func(*grpc.ClientConn) error) (bool, error) { + return false, nil +} diff --git a/agent/grpc-external/services/connectca/server.go b/agent/grpc-external/services/connectca/server.go index 4ef91705f7a1..fbdabc1bd899 100644 --- a/agent/grpc-external/services/connectca/server.go +++ b/agent/grpc-external/services/connectca/server.go @@ -57,8 +57,8 @@ func NewServer(cfg Config) *Server { return &Server{cfg} } -func (s *Server) Register(grpcServer *grpc.Server) { - pbconnectca.RegisterConnectCAServiceServer(grpcServer, s) +func (s *Server) Register(registrar grpc.ServiceRegistrar) { + pbconnectca.RegisterConnectCAServiceServer(registrar, s) } func (s *Server) requireConnect() error { diff --git a/agent/grpc-external/services/connectca/watch_roots.go b/agent/grpc-external/services/connectca/watch_roots.go index ddd02ca56e0f..058fdd41349f 100644 --- a/agent/grpc-external/services/connectca/watch_roots.go +++ b/agent/grpc-external/services/connectca/watch_roots.go @@ -47,7 +47,7 @@ func (s *Server) WatchRoots(_ *pbconnectca.WatchRootsRequest, serverStream pbcon for { var err error idx, err = s.serveRoots(options.Token, idx, serverStream, logger) - if errors.Is(err, stream.ErrSubForceClosed) { + if errors.Is(err, stream.ErrSubForceClosed) || errors.Is(err, stream.ErrACLChanged) { logger.Trace("subscription force-closed due to an ACL change or snapshot restore, will attempt to re-auth and resume") } else { return err @@ -90,7 +90,7 @@ func (s *Server) serveRoots( for { event, err := sub.Next(serverStream.Context()) switch { - case errors.Is(err, stream.ErrSubForceClosed): + case errors.Is(err, stream.ErrSubForceClosed) || errors.Is(err, stream.ErrACLChanged): // If the subscription was closed because the state store was abandoned (e.g. // following a snapshot restore) reset idx to ensure we don't skip over the // new store's events. diff --git a/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params.go b/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params.go index ea4852efab2b..bbc2390a776b 100644 --- a/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params.go +++ b/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params.go @@ -8,16 +8,12 @@ import ( "errors" "strings" - "github.com/hashicorp/go-hclog" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/structpb" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/configentry" @@ -50,72 +46,6 @@ func (s *Server) GetEnvoyBootstrapParams(ctx context.Context, req *pbdataplane.G return nil, status.Error(codes.Unauthenticated, err.Error()) } - if s.EnableV2 { - // Get the workload. - workloadId := &pbresource.ID{ - Name: proxyID, - Tenancy: &pbresource.Tenancy{ - Namespace: req.Namespace, - Partition: req.Partition, - }, - Type: pbcatalog.WorkloadType, - } - workloadRsp, err := s.ResourceAPIClient.Read(ctx, &pbresource.ReadRequest{ - Id: workloadId, - }) - if err != nil { - // This error should already include the gRPC status code and so we don't need to wrap it - // in status.Error. - logger.Error("Error looking up workload", "error", err) - return nil, err - } - var workload pbcatalog.Workload - err = workloadRsp.Resource.Data.UnmarshalTo(&workload) - if err != nil { - return nil, status.Error(codes.Internal, "failed to parse workload data") - } - - // Only workloads that have an associated identity can ask for proxy bootstrap parameters. - if workload.Identity == "" { - return nil, status.Errorf(codes.InvalidArgument, "workload %q doesn't have identity associated with it", req.ProxyId) - } - - // verify identity:write is allowed. if not, give permission denied error. - if err := authz.ToAllowAuthorizer().IdentityWriteAllowed(workload.Identity, &authzContext); err != nil { - return nil, err - } - - computedProxyConfig, err := resource.GetDecodedResource[*pbmesh.ComputedProxyConfiguration]( - ctx, - s.ResourceAPIClient, - resource.ReplaceType(pbmesh.ComputedProxyConfigurationType, workloadId)) - - if err != nil { - logger.Error("Error looking up ComputedProxyConfiguration for this workload", "error", err) - return nil, err - } - - rsp := &pbdataplane.GetEnvoyBootstrapParamsResponse{ - Identity: workload.Identity, - Partition: workloadRsp.Resource.Id.Tenancy.Partition, - Namespace: workloadRsp.Resource.Id.Tenancy.Namespace, - Datacenter: s.Datacenter, - NodeName: workload.NodeName, - } - - if computedProxyConfig != nil { - if computedProxyConfig.GetData().GetDynamicConfig() != nil { - rsp.AccessLogs = makeAccessLogs(computedProxyConfig.GetData().GetDynamicConfig().GetAccessLogs(), logger) - } - - rsp.BootstrapConfig = computedProxyConfig.GetData().GetBootstrapConfig() - } - - return rsp, nil - } - - // The remainder of this file focuses on v1 implementation of this endpoint. - store := s.GetStore() _, svc, err := store.ServiceNode(req.GetNodeId(), req.GetNodeName(), proxyID, &entMeta, structs.DefaultPeerKeyword) @@ -181,9 +111,9 @@ func (s *Server) GetEnvoyBootstrapParams(ctx context.Context, req *pbdataplane.G }, nil } -func makeAccessLogs(logs structs.AccessLogs, logger hclog.Logger) []string { +func makeAccessLogs(logs *structs.AccessLogsConfig, logger hclog.Logger) []string { var accessLogs []string - if logs.GetEnabled() { + if logs.Enabled { envoyLoggers, err := accesslogs.MakeAccessLogs(logs, false) if err != nil { logger.Warn("Error creating the envoy access log config", "error", err) diff --git a/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params_test.go b/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params_test.go index 3ae0670e5cf0..bcff21cce50b 100644 --- a/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params_test.go +++ b/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params_test.go @@ -7,22 +7,13 @@ import ( "context" "testing" - "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/structpb" - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/mesh" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl/resolver" @@ -252,154 +243,6 @@ func TestGetEnvoyBootstrapParams_Success(t *testing.T) { } } -func TestGetEnvoyBootstrapParams_Success_EnableV2(t *testing.T) { - type testCase struct { - name string - workloadData *pbcatalog.Workload - proxyCfg *pbmesh.ComputedProxyConfiguration - expBootstrapCfg *pbmesh.BootstrapConfig - expAccessLogs string - } - - run := func(t *testing.T, tc testCase) { - resourceClient := svctest.RunResourceService(t, catalog.RegisterTypes, mesh.RegisterTypes) - - options := structs.QueryOptions{Token: testToken} - ctx, err := external.ContextWithQueryOptions(context.Background(), options) - require.NoError(t, err) - - aclResolver := &MockACLResolver{} - - server := NewServer(Config{ - Logger: hclog.NewNullLogger(), - ACLResolver: aclResolver, - Datacenter: serverDC, - EnableV2: true, - ResourceAPIClient: resourceClient, - }) - client := testClient(t, server) - - // Add required fields to workload data. - tc.workloadData.Addresses = []*pbcatalog.WorkloadAddress{ - { - Host: "127.0.0.1", - }, - } - tc.workloadData.Ports = map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - } - workloadResource := resourcetest.Resource(pbcatalog.WorkloadType, "test-workload"). - WithData(t, tc.workloadData). - WithTenancy(resource.DefaultNamespacedTenancy()). - Write(t, resourceClient) - - // Create computed proxy cfg resource. - resourcetest.Resource(pbmesh.ComputedProxyConfigurationType, workloadResource.Id.Name). - WithData(t, tc.proxyCfg). - WithTenancy(resource.DefaultNamespacedTenancy()). - Write(t, resourceClient) - - req := &pbdataplane.GetEnvoyBootstrapParamsRequest{ - ProxyId: workloadResource.Id.Name, - Namespace: workloadResource.Id.Tenancy.Namespace, - Partition: workloadResource.Id.Tenancy.Partition, - } - - aclResolver.On("ResolveTokenAndDefaultMeta", testToken, mock.Anything, mock.Anything). - Return(testutils.ACLUseProvidedPolicy(t, - &acl.Policy{ - PolicyRules: acl.PolicyRules{ - Services: []*acl.ServiceRule{ - { - Name: workloadResource.Id.Name, - Policy: acl.PolicyRead, - }, - }, - Identities: []*acl.IdentityRule{ - { - Name: testIdentity, - Policy: acl.PolicyWrite, - }, - }, - }, - }), nil) - - resp, err := client.GetEnvoyBootstrapParams(ctx, req) - require.NoError(t, err) - - require.Equal(t, tc.workloadData.Identity, resp.Identity) - require.Equal(t, serverDC, resp.Datacenter) - require.Equal(t, workloadResource.Id.Tenancy.Partition, resp.Partition) - require.Equal(t, workloadResource.Id.Tenancy.Namespace, resp.Namespace) - require.Equal(t, resp.NodeName, tc.workloadData.NodeName) - prototest.AssertDeepEqual(t, tc.expBootstrapCfg, resp.BootstrapConfig) - if tc.expAccessLogs != "" { - require.JSONEq(t, tc.expAccessLogs, resp.AccessLogs[0]) - } - } - - testCases := []testCase{ - { - name: "workload without node", - workloadData: &pbcatalog.Workload{ - Identity: testIdentity, - }, - expBootstrapCfg: nil, - }, - { - name: "workload with node", - workloadData: &pbcatalog.Workload{ - Identity: testIdentity, - NodeName: "test-node", - }, - expBootstrapCfg: nil, - }, - { - name: "single proxy configuration", - workloadData: &pbcatalog.Workload{ - Identity: testIdentity, - }, - proxyCfg: &pbmesh.ComputedProxyConfiguration{ - BootstrapConfig: &pbmesh.BootstrapConfig{ - DogstatsdUrl: "dogstats-url", - }, - }, - expBootstrapCfg: &pbmesh.BootstrapConfig{ - DogstatsdUrl: "dogstats-url", - }, - }, - { - name: "multiple proxy configurations", - workloadData: &pbcatalog.Workload{ - Identity: testIdentity, - }, - proxyCfg: &pbmesh.ComputedProxyConfiguration{ - BootstrapConfig: &pbmesh.BootstrapConfig{ - DogstatsdUrl: "dogstats-url", - StatsdUrl: "stats-url", - }, - DynamicConfig: &pbmesh.DynamicConfig{ - AccessLogs: &pbmesh.AccessLogsConfig{ - Enabled: true, - JsonFormat: "{ \"custom_field\": \"%START_TIME%\" }", - }, - }, - }, - expBootstrapCfg: &pbmesh.BootstrapConfig{ - DogstatsdUrl: "dogstats-url", - StatsdUrl: "stats-url", - }, - expAccessLogs: testAccessLogs, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - run(t, tc) - }) - } -} - func TestGetEnvoyBootstrapParams_Error(t *testing.T) { type testCase struct { name string @@ -481,98 +324,6 @@ func TestGetEnvoyBootstrapParams_Error(t *testing.T) { } -func TestGetEnvoyBootstrapParams_Error_EnableV2(t *testing.T) { - type testCase struct { - name string - expectedErrCode codes.Code - expecteErrMsg string - workload *pbresource.Resource - } - - run := func(t *testing.T, tc testCase) { - resourceClient := svctest.RunResourceService(t, catalog.RegisterTypes, mesh.RegisterTypes) - - options := structs.QueryOptions{Token: testToken} - ctx, err := external.ContextWithQueryOptions(context.Background(), options) - require.NoError(t, err) - - aclResolver := &MockACLResolver{} - aclResolver.On("ResolveTokenAndDefaultMeta", testToken, mock.Anything, mock.Anything). - Return(testutils.ACLServiceRead(t, "doesn't matter"), nil) - - server := NewServer(Config{ - Logger: hclog.NewNullLogger(), - ACLResolver: aclResolver, - Datacenter: serverDC, - EnableV2: true, - ResourceAPIClient: resourceClient, - }) - client := testClient(t, server) - - var req pbdataplane.GetEnvoyBootstrapParamsRequest - // Write the workload resource. - if tc.workload != nil { - _, err = resourceClient.Write(context.Background(), &pbresource.WriteRequest{ - Resource: tc.workload, - }) - require.NoError(t, err) - - req = pbdataplane.GetEnvoyBootstrapParamsRequest{ - ProxyId: tc.workload.Id.Name, - Namespace: tc.workload.Id.Tenancy.Namespace, - Partition: tc.workload.Id.Tenancy.Partition, - } - } else { - req = pbdataplane.GetEnvoyBootstrapParamsRequest{ - ProxyId: "not-found", - Namespace: "default", - Partition: "default", - } - } - - resp, err := client.GetEnvoyBootstrapParams(ctx, &req) - require.Nil(t, resp) - require.Error(t, err) - errStatus, ok := status.FromError(err) - require.True(t, ok) - require.Equal(t, tc.expectedErrCode.String(), errStatus.Code().String()) - require.Equal(t, tc.expecteErrMsg, errStatus.Message()) - } - - workload := resourcetest.Resource(pbcatalog.WorkloadType, "test-workload"). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - - testCases := []testCase{ - { - name: "workload doesn't exist", - expectedErrCode: codes.NotFound, - expecteErrMsg: "resource not found", - }, - { - name: "workload without identity", - expectedErrCode: codes.InvalidArgument, - expecteErrMsg: "workload \"test-workload\" doesn't have identity associated with it", - workload: workload, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - run(t, tc) - }) - } - -} - func TestGetEnvoyBootstrapParams_Unauthenticated(t *testing.T) { // Mock the ACL resolver to return ErrNotFound. aclResolver := &MockACLResolver{} diff --git a/agent/grpc-external/services/dataplane/server.go b/agent/grpc-external/services/dataplane/server.go index fbce372f0efa..68972ce25224 100644 --- a/agent/grpc-external/services/dataplane/server.go +++ b/agent/grpc-external/services/dataplane/server.go @@ -4,7 +4,6 @@ package dataplane import ( - "github.com/hashicorp/consul/proto-public/pbresource" "google.golang.org/grpc" "github.com/hashicorp/go-hclog" @@ -27,10 +26,6 @@ type Config struct { ACLResolver ACLResolver // Datacenter of the Consul server this gRPC server is hosted on Datacenter string - - // EnableV2 indicates whether a feature flag for v2 APIs is provided. - EnableV2 bool - ResourceAPIClient pbresource.ResourceServiceClient } type StateStore interface { @@ -49,6 +44,6 @@ func NewServer(cfg Config) *Server { var _ pbdataplane.DataplaneServiceServer = (*Server)(nil) -func (s *Server) Register(grpcServer *grpc.Server) { - pbdataplane.RegisterDataplaneServiceServer(grpcServer, s) +func (s *Server) Register(registrar grpc.ServiceRegistrar) { + pbdataplane.RegisterDataplaneServiceServer(registrar, s) } diff --git a/agent/grpc-external/services/dns/server.go b/agent/grpc-external/services/dns/server.go index a6f2249733c1..120b1875efd2 100644 --- a/agent/grpc-external/services/dns/server.go +++ b/agent/grpc-external/services/dns/server.go @@ -6,6 +6,7 @@ package dns import ( "context" "fmt" + agentdns "github.com/hashicorp/consul/agent/dns" "net" "github.com/hashicorp/go-hclog" @@ -37,65 +38,10 @@ func NewServer(cfg Config) *Server { return &Server{cfg} } -func (s *Server) Register(grpcServer *grpc.Server) { - pbdns.RegisterDNSServiceServer(grpcServer, s) +func (s *Server) Register(registrar grpc.ServiceRegistrar) { + pbdns.RegisterDNSServiceServer(registrar, s) } -// BufferResponseWriter writes a DNS response to a byte buffer. -type BufferResponseWriter struct { - responseBuffer []byte - LocalAddress net.Addr - RemoteAddress net.Addr - Logger hclog.Logger -} - -// LocalAddr returns the net.Addr of the server -func (b *BufferResponseWriter) LocalAddr() net.Addr { - return b.LocalAddress -} - -// RemoteAddr returns the net.Addr of the client that sent the current request. -func (b *BufferResponseWriter) RemoteAddr() net.Addr { - return b.RemoteAddress -} - -// WriteMsg writes a reply back to the client. -func (b *BufferResponseWriter) WriteMsg(m *dns.Msg) error { - // Pack message to bytes first. - msgBytes, err := m.Pack() - if err != nil { - b.Logger.Error("error packing message", "err", err) - return err - } - b.responseBuffer = msgBytes - return nil -} - -// Write writes a raw buffer back to the client. -func (b *BufferResponseWriter) Write(m []byte) (int, error) { - b.Logger.Debug("Write was called") - return copy(b.responseBuffer, m), nil -} - -// Close closes the connection. -func (b *BufferResponseWriter) Close() error { - // There's nothing for us to do here as we don't handle the connection. - return nil -} - -// TsigStatus returns the status of the Tsig. -func (b *BufferResponseWriter) TsigStatus() error { - // TSIG doesn't apply to this response writer. - return nil -} - -// TsigTimersOnly sets the tsig timers only boolean. -func (b *BufferResponseWriter) TsigTimersOnly(bool) {} - -// Hijack lets the caller take over the connection. -// After a call to Hijack(), the DNS package will not do anything with the connection. { -func (b *BufferResponseWriter) Hijack() {} - // Query is a gRPC endpoint that will serve dns requests. It will be consumed primarily by the // consul dataplane to proxy dns requests to consul. func (s *Server) Query(ctx context.Context, req *pbdns.QueryRequest) (*pbdns.QueryResponse, error) { @@ -121,21 +67,29 @@ func (s *Server) Query(ctx context.Context, req *pbdns.QueryRequest) (*pbdns.Que return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("error protocol type not set: %v", req.GetProtocol())) } - respWriter := &BufferResponseWriter{ - LocalAddress: local, - RemoteAddress: remote, - Logger: s.Logger, + reqCtx, err := agentdns.NewContextFromGRPCContext(ctx) + if err != nil { + s.Logger.Error("error parsing DNS context from grpc metadata", "err", err) + return nil, status.Error(codes.Internal, fmt.Sprintf("error parsing DNS context from grpc metadata: %s", err.Error())) + } + + respWriter := &agentdns.BufferResponseWriter{ + LocalAddress: local, + RemoteAddress: remote, + Logger: s.Logger, + RequestContext: reqCtx, } msg := &dns.Msg{} - err := msg.Unpack(req.Msg) + err = msg.Unpack(req.Msg) if err != nil { s.Logger.Error("error unpacking message", "err", err) return nil, status.Error(codes.Internal, fmt.Sprintf("failure decoding dns request: %s", err.Error())) } + s.DNSServeMux.ServeDNS(respWriter, msg) - queryResponse := &pbdns.QueryResponse{Msg: respWriter.responseBuffer} + queryResponse := &pbdns.QueryResponse{Msg: respWriter.ResponseBuffer()} return queryResponse, nil } diff --git a/agent/grpc-external/services/dns/server_test.go b/agent/grpc-external/services/dns/server_test.go index a6576b51adcf..b95221fe94cc 100644 --- a/agent/grpc-external/services/dns/server_test.go +++ b/agent/grpc-external/services/dns/server_test.go @@ -33,7 +33,7 @@ func helloServer(w dns.ResponseWriter, req *dns.Msg) { w.WriteMsg(m) } -func testClient(t *testing.T, server *Server) pbdns.DNSServiceClient { +func testClient(t *testing.T, server testutils.GRPCService) pbdns.DNSServiceClient { t.Helper() addr := testutils.RunTestServer(t, server) diff --git a/agent/grpc-external/services/peerstream/server.go b/agent/grpc-external/services/peerstream/server.go index 4127312fe72c..6cd32c9287b9 100644 --- a/agent/grpc-external/services/peerstream/server.go +++ b/agent/grpc-external/services/peerstream/server.go @@ -83,8 +83,8 @@ func requireNotNil(v interface{}, name string) { var _ pbpeerstream.PeerStreamServiceServer = (*Server)(nil) -func (s *Server) Register(grpcServer *grpc.Server) { - pbpeerstream.RegisterPeerStreamServiceServer(grpcServer, s) +func (s *Server) Register(registrar grpc.ServiceRegistrar) { + pbpeerstream.RegisterPeerStreamServiceServer(registrar, s) } type Backend interface { diff --git a/agent/grpc-external/services/peerstream/stream_test.go b/agent/grpc-external/services/peerstream/stream_test.go index ad3399b79f5a..37e5e99a76f7 100644 --- a/agent/grpc-external/services/peerstream/stream_test.go +++ b/agent/grpc-external/services/peerstream/stream_test.go @@ -690,7 +690,7 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { req := msg.GetRequest() require.NotNil(r, req) require.Equal(r, pbpeerstream.TypeURLExportedService, req.ResourceURL) - prototest.AssertDeepEqual(t, expectAck, msg) + prototest.AssertDeepEqual(r, expectAck, msg) }) expect := Status{ @@ -1175,7 +1175,7 @@ func TestStreamResources_Server_CARootUpdates(t *testing.T) { func TestStreamResources_Server_AckNackNonce(t *testing.T) { srv, store := newTestServer(t, func(c *Config) { - c.incomingHeartbeatTimeout = 10 * time.Millisecond + c.incomingHeartbeatTimeout = 5 * time.Second }) p := writePeeringToBeDialed(t, store, 1, "my-peer") @@ -1222,7 +1222,7 @@ func TestStreamResources_Server_AckNackNonce(t *testing.T) { }) // Add in a sleep to prevent the test from flaking. // The mock client expects certain calls to be made. - time.Sleep(50 * time.Millisecond) + time.Sleep(500 * time.Millisecond) } // Test that when the client doesn't send a heartbeat in time, the stream is disconnected. diff --git a/agent/grpc-external/services/peerstream/subscription_manager.go b/agent/grpc-external/services/peerstream/subscription_manager.go index bd2d36ffd942..92be1bb6b09d 100644 --- a/agent/grpc-external/services/peerstream/subscription_manager.go +++ b/agent/grpc-external/services/peerstream/subscription_manager.go @@ -882,6 +882,10 @@ func (m *subscriptionManager) subscribeServerAddrs( idx uint64, updateCh chan<- cache.UpdateEvent, ) (uint64, error) { + // TODO(inproc-grpc) - Look into using the insecure in-process gRPC Channel + // to get notified for server address updates instead of hooking into the + // subscription service. + // following code adapted from serverdiscovery/watch_servers.go sub, err := m.backend.Subscribe(&stream.SubscribeRequest{ Topic: autopilotevents.EventTopicReadyServers, diff --git a/agent/grpc-external/services/peerstream/testing.go b/agent/grpc-external/services/peerstream/testing.go index 47cc8d1dbec6..b5e79a634707 100644 --- a/agent/grpc-external/services/peerstream/testing.go +++ b/agent/grpc-external/services/peerstream/testing.go @@ -30,7 +30,7 @@ func (c *MockClient) Send(r *pbpeerstream.ReplicationMessage) error { } func (c *MockClient) Recv() (*pbpeerstream.ReplicationMessage, error) { - return c.RecvWithTimeout(10 * time.Millisecond) + return c.RecvWithTimeout(100 * time.Millisecond) } func (c *MockClient) RecvWithTimeout(dur time.Duration) (*pbpeerstream.ReplicationMessage, error) { diff --git a/agent/grpc-external/services/resource/delete.go b/agent/grpc-external/services/resource/delete.go index aef2934141c8..839bc7fa704a 100644 --- a/agent/grpc-external/services/resource/delete.go +++ b/agent/grpc-external/services/resource/delete.go @@ -27,6 +27,7 @@ import ( // - Delete of a previously deleted or non-existent resource is a no-op to support idempotency. // - Errors with Aborted if the requested Version does not match the stored Version. // - Errors with PermissionDenied if ACL check fails +// - Errors with PermissionDenied if a license feature tied to the resource type is not allowed. func (s *Server) Delete(ctx context.Context, req *pbresource.DeleteRequest) (*pbresource.DeleteResponse, error) { reg, err := s.ensureDeleteRequestValid(req) if err != nil { @@ -49,65 +50,74 @@ func (s *Server) Delete(ctx context.Context, req *pbresource.DeleteRequest) (*pb // Apply defaults when tenancy units empty. v1EntMetaToV2Tenancy(reg, entMeta, req.Id.Tenancy) - existing, err := s.Backend.Read(ctx, consistency, req.Id) - switch { - case errors.Is(err, storage.ErrNotFound): - // Deletes are idempotent so no-op when not found - return &pbresource.DeleteResponse{}, nil - case err != nil: - return nil, status.Errorf(codes.Internal, "failed read: %v", err) - } + // Only non-CAS deletes (version=="") are automatically retried. + err = s.retryCAS(ctx, req.Version, func() error { + existing, err := s.Backend.Read(ctx, consistency, req.Id) + switch { + case errors.Is(err, storage.ErrNotFound): + // Deletes are idempotent so no-op when not found + return nil + case err != nil: + return status.Errorf(codes.Internal, "failed read: %v", err) + } - // Check ACLs - err = reg.ACLs.Write(authz, authzContext, existing) - switch { - case acl.IsErrPermissionDenied(err): - return nil, status.Error(codes.PermissionDenied, err.Error()) - case err != nil: - return nil, status.Errorf(codes.Internal, "failed write acl: %v", err) - } + // Check ACLs + err = reg.ACLs.Write(authz, authzContext, existing) + switch { + case acl.IsErrPermissionDenied(err): + return status.Error(codes.PermissionDenied, err.Error()) + case err != nil: + return status.Errorf(codes.Internal, "failed write acl: %v", err) + } - deleteVersion := req.Version - deleteId := req.Id - if deleteVersion == "" || deleteId.Uid == "" { - deleteVersion = existing.Version - deleteId = existing.Id - } + deleteVersion := req.Version + deleteId := req.Id + if deleteVersion == "" || deleteId.Uid == "" { + deleteVersion = existing.Version + deleteId = existing.Id + } - // Check finalizers for a deferred delete - if resource.HasFinalizers(existing) { - if resource.IsMarkedForDeletion(existing) { - // Delete previously requested and finalizers still present so nothing to do - return &pbresource.DeleteResponse{}, nil + // Check finalizers for a deferred delete + if resource.HasFinalizers(existing) { + if resource.IsMarkedForDeletion(existing) { + // Delete previously requested and finalizers still present so nothing to do + return nil + } + + // Mark for deletion and let controllers that put finalizers in place do their + // thing. Note we're passing in a clone of the recently read resource since + // we've not crossed a network/serialization boundary since the read and we + // don't want to mutate the in-mem reference. + _, err := s.markForDeletion(ctx, clone(existing)) + return err } - // Mark for deletion and let controllers that put finalizers in place do their thing - return s.markForDeletion(ctx, existing) - } + // Continue with an immediate delete + if err := s.maybeCreateTombstone(ctx, deleteId); err != nil { + return err + } - // Continue with an immediate delete - if err := s.maybeCreateTombstone(ctx, deleteId); err != nil { - return nil, err - } + err = s.Backend.DeleteCAS(ctx, deleteId, deleteVersion) + return err + }) - err = s.Backend.DeleteCAS(ctx, deleteId, deleteVersion) switch { case err == nil: return &pbresource.DeleteResponse{}, nil case errors.Is(err, storage.ErrCASFailure): return nil, status.Error(codes.Aborted, err.Error()) + case isGRPCStatusError(err): + // Pass through gRPC errors from internal calls to resource service + // endpoints (e.g. Write when marking for deletion). + return nil, err default: return nil, status.Errorf(codes.Internal, "failed delete: %v", err) } } func (s *Server) markForDeletion(ctx context.Context, res *pbresource.Resource) (*pbresource.DeleteResponse, error) { - if res.Metadata == nil { - res.Metadata = map[string]string{} - } - res.Metadata[resource.DeletionTimestampKey] = time.Now().Format(time.RFC3339) - // Write the deletion timestamp + res.Metadata[resource.DeletionTimestampKey] = time.Now().Format(time.RFC3339) _, err := s.Write(ctx, &pbresource.WriteRequest{Resource: res}) if err != nil { return nil, err @@ -146,7 +156,7 @@ func (s *Server) maybeCreateTombstone(ctx context.Context, deleteId *pbresource. Id: &pbresource.ID{ Type: resource.TypeV1Tombstone, Tenancy: deleteId.Tenancy, - Name: tombstoneName(deleteId), + Name: TombstoneNameFor(deleteId), Uid: ulid.Make().String(), }, Generation: ulid.Make().String(), @@ -185,18 +195,12 @@ func (s *Server) ensureDeleteRequestValid(req *pbresource.DeleteRequest) (*resou return nil, err } - if err = checkV2Tenancy(s.UseV2Tenancy, req.Id.Type); err != nil { + if err = s.FeatureCheck(reg); err != nil { return nil, err } - // Check scope - if reg.Scope == resource.ScopePartition && req.Id.Tenancy.Namespace != "" { - return nil, status.Errorf( - codes.InvalidArgument, - "partition scoped resource %s cannot have a namespace. got: %s", - resource.ToGVK(req.Id.Type), - req.Id.Tenancy.Namespace, - ) + if err := validateScopedTenancy(reg.Scope, reg.Type, req.Id.Tenancy, false); err != nil { + return nil, err } return reg, nil @@ -204,7 +208,7 @@ func (s *Server) ensureDeleteRequestValid(req *pbresource.DeleteRequest) (*resou // Maintains a deterministic mapping between a resource and it's tombstone's // name by embedding the resources's Uid in the name. -func tombstoneName(deleteId *pbresource.ID) string { +func TombstoneNameFor(deleteId *pbresource.ID) string { // deleteId.Name is just included for easier identification return fmt.Sprintf("tombstone-%v-%v", deleteId.Name, strings.ToLower(deleteId.Uid)) } diff --git a/agent/grpc-external/services/resource/delete_test.go b/agent/grpc-external/services/resource/delete_test.go index 4c1339313862..25a801205188 100644 --- a/agent/grpc-external/services/resource/delete_test.go +++ b/agent/grpc-external/services/resource/delete_test.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package resource +package resource_test import ( "context" @@ -15,6 +15,8 @@ import ( "google.golang.org/protobuf/proto" "github.com/hashicorp/consul/acl/resolver" + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" rtest "github.com/hashicorp/consul/internal/resource/resourcetest" @@ -23,115 +25,138 @@ import ( ) func TestDelete_InputValidation(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) - type testCase struct { - modFn func(artistId, recordLabelId *pbresource.ID) *pbresource.ID + modFn func(artistId, recordLabelId, executiveId *pbresource.ID) *pbresource.ID errContains string } + run := func(t *testing.T, client pbresource.ResourceServiceClient, tc testCase) { + executive, err := demo.GenerateV1Executive("marvin", "CEO") + require.NoError(t, err) + + recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + require.NoError(t, err) + + artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + req := &pbresource.DeleteRequest{Id: tc.modFn(artist.Id, recordLabel.Id, executive.Id), Version: ""} + _, err = client.Delete(context.Background(), req) + require.Error(t, err) + require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) + require.ErrorContains(t, err, tc.errContains) + } + testCases := map[string]testCase{ "no id": { - modFn: func(_, _ *pbresource.ID) *pbresource.ID { + modFn: func(_, _, _ *pbresource.ID) *pbresource.ID { return nil }, errContains: "id is required", }, "no type": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Type = nil return artistId }, errContains: "id.type is required", }, "no name": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Name = "" return artistId }, errContains: "id.name invalid", }, "mixed case name": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Name = "DepecheMode" return artistId }, errContains: "id.name invalid", }, "name too long": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Name = strings.Repeat("n", resource.MaxNameLength+1) return artistId }, errContains: "id.name invalid", }, "partition mixed case": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Tenancy.Partition = "Default" return artistId }, errContains: "id.tenancy.partition invalid", }, "partition name too long": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) return artistId }, errContains: "id.tenancy.partition invalid", }, "namespace mixed case": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Tenancy.Namespace = "Default" return artistId }, errContains: "id.tenancy.namespace invalid", }, "namespace name too long": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) return artistId }, errContains: "id.tenancy.namespace invalid", }, "partition scoped resource with namespace": { - modFn: func(_, recordLabelId *pbresource.ID) *pbresource.ID { + modFn: func(_, recordLabelId, _ *pbresource.ID) *pbresource.ID { recordLabelId.Tenancy.Namespace = "ishouldnothaveanamespace" return recordLabelId }, errContains: "cannot have a namespace", }, + "cluster scoped resource with partition": { + modFn: func(_, _, executiveId *pbresource.ID) *pbresource.ID { + executiveId.Tenancy.Partition = "ishouldnothaveapartition" + executiveId.Tenancy.Namespace = "" + return executiveId + }, + errContains: "cannot have a partition", + }, + "cluster scoped resource with namespace": { + modFn: func(_, _, executiveId *pbresource.ID) *pbresource.ID { + executiveId.Tenancy.Partition = "" + executiveId.Tenancy.Namespace = "ishouldnothaveanamespace" + return executiveId + }, + errContains: "cannot have a namespace", + }, } - for desc, tc := range testCases { - t.Run(desc, func(t *testing.T) { - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") - require.NoError(t, err) - - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - req := &pbresource.DeleteRequest{Id: tc.modFn(artist.Id, recordLabel.Id), Version: ""} + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) - _, err = client.Delete(testContext(t), req) - require.Error(t, err) - require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.ErrorContains(t, err, tc.errContains) + for desc, tc := range testCases { + t.Run(desc, func(t *testing.T) { + run(t, client, tc) }) } } func TestDelete_TypeNotRegistered(t *testing.T) { - t.Parallel() + client := svctest.NewResourceServiceBuilder().Run(t) - _, client, ctx := testDeps(t) artist, err := demo.GenerateV2Artist() require.NoError(t, err) // delete artist with unregistered type - _, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: artist.Id, Version: ""}) + _, err = client.Delete(context.Background(), &pbresource.DeleteRequest{Id: artist.Id, Version: ""}) require.Error(t, err) require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) + require.ErrorContains(t, err, "not registered") } func TestDelete_ACLs(t *testing.T) { @@ -144,7 +169,7 @@ func TestDelete_ACLs(t *testing.T) { authz: AuthorizerFrom(t, demo.ArtistV1WritePolicy), assertErrFn: func(err error) { require.Error(t, err) - require.Equal(t, codes.PermissionDenied.String(), status.Code(err).String()) + require.Equal(t, codes.PermissionDenied.String(), status.Code(err).String(), err) }, }, "delete allowed": { @@ -157,9 +182,8 @@ func TestDelete_ACLs(t *testing.T) { for desc, tc := range testcases { t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + builder := svctest.NewResourceServiceBuilder().WithRegisterFns(demo.RegisterTypes) + client := builder.Run(t) artist, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -169,10 +193,10 @@ func TestDelete_ACLs(t *testing.T) { require.NoError(t, err) // Mock is put in place after the above "write" since the "write" must also pass the ACL check. - mockACLResolver := &MockACLResolver{} + mockACLResolver := &svc.MockACLResolver{} mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). Return(tc.authz, nil) - server.ACLResolver = mockACLResolver + builder.ServiceImpl().Config.ACLResolver = mockACLResolver // Exercise ACL. _, err = client.Delete(testContext(t), &pbresource.DeleteRequest{Id: rsp.Resource.Id}) @@ -184,70 +208,124 @@ func TestDelete_ACLs(t *testing.T) { func TestDelete_Success(t *testing.T) { t.Parallel() + run := func(t *testing.T, client pbresource.ResourceServiceClient, tc deleteTestCase, modFn func(artistId, recordlabelId *pbresource.ID) *pbresource.ID) { + ctx := context.Background() + + recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + require.NoError(t, err) + writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: recordLabel}) + require.NoError(t, err) + recordLabel = writeRsp.Resource + originalRecordLabelId := clone(recordLabel.Id) + + artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + writeRsp, err = client.Write(ctx, &pbresource.WriteRequest{Resource: artist}) + require.NoError(t, err) + artist = writeRsp.Resource + originalArtistId := clone(artist.Id) + + // Pick the resource to be deleted based on type's scope and mod tenancy + // based on the tenancy test case. + deleteId := modFn(artist.Id, recordLabel.Id) + deleteReq := tc.deleteReqFn(recordLabel) + if proto.Equal(deleteId.Type, demo.TypeV2Artist) { + deleteReq = tc.deleteReqFn(artist) + } + + // Delete + _, err = client.Delete(ctx, deleteReq) + require.NoError(t, err) + + // Verify deleted + _, err = client.Read(ctx, &pbresource.ReadRequest{Id: deleteId}) + require.Error(t, err) + require.Equal(t, codes.NotFound.String(), status.Code(err).String()) + + // Derive tombstone name from resource that was deleted. + tname := svc.TombstoneNameFor(originalRecordLabelId) + if proto.Equal(deleteId.Type, demo.TypeV2Artist) { + tname = svc.TombstoneNameFor(originalArtistId) + } + + // Verify tombstone created + _, err = client.Read(ctx, &pbresource.ReadRequest{ + Id: &pbresource.ID{ + Name: tname, + Type: resource.TypeV1Tombstone, + Tenancy: deleteReq.Id.Tenancy, + }, + }) + require.NoError(t, err, "expected tombstone to be found") + } + for desc, tc := range deleteTestCases() { t.Run(desc, func(t *testing.T) { for tenancyDesc, modFn := range tenancyCases() { t.Run(tenancyDesc, func(t *testing.T) { - server, client, ctx := testDeps(t) - demo.RegisterTypes(server.Registry) - - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") - require.NoError(t, err) - writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: recordLabel}) - require.NoError(t, err) - recordLabel = writeRsp.Resource - originalRecordLabelId := clone(recordLabel.Id) - - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - writeRsp, err = client.Write(ctx, &pbresource.WriteRequest{Resource: artist}) - require.NoError(t, err) - artist = writeRsp.Resource - originalArtistId := clone(artist.Id) - - // Pick the resource to be deleted based on type's scope and mod tenancy - // based on the tenancy test case. - deleteId := modFn(artist.Id, recordLabel.Id) - deleteReq := tc.deleteReqFn(recordLabel) - if proto.Equal(deleteId.Type, demo.TypeV2Artist) { - deleteReq = tc.deleteReqFn(artist) - } - - // Delete - _, err = client.Delete(ctx, deleteReq) - require.NoError(t, err) - - // Verify deleted - _, err = client.Read(ctx, &pbresource.ReadRequest{Id: deleteId}) - require.Error(t, err) - require.Equal(t, codes.NotFound.String(), status.Code(err).String()) - - // Derive tombstone name from resource that was deleted. - tname := tombstoneName(originalRecordLabelId) - if proto.Equal(deleteId.Type, demo.TypeV2Artist) { - tname = tombstoneName(originalArtistId) - } - - // Verify tombstone created - _, err = client.Read(ctx, &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Name: tname, - Type: resource.TypeV1Tombstone, - Tenancy: deleteReq.Id.Tenancy, - }, - }) - require.NoError(t, err, "expected tombstone to be found") + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + run(t, client, tc, modFn) }) } }) } } +func TestDelete_NonCAS_Retry(t *testing.T) { + server := testServer(t) + client := testClient(t, server) + demo.RegisterTypes(server.Registry) + + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + rsp1, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + // Simulate conflicting versions by blocking the RPC after it has read the + // current version of the resource, but before it tries to do a CAS delete + // based on that version. + backend := &blockOnceBackend{ + Backend: server.Backend, + + readCompletedCh: make(chan struct{}), + blockCh: make(chan struct{}), + } + server.Backend = backend + + deleteResultCh := make(chan error) + go func() { + _, err := client.Delete(testContext(t), &pbresource.DeleteRequest{Id: rsp1.Resource.Id, Version: ""}) + deleteResultCh <- err + }() + + // Wait for the read, to ensure the Delete in the goroutine above has read the + // current version of the resource. + <-backend.readCompletedCh + + // Update the artist so that its version is different from the version read by Delete + res = modifyArtist(t, rsp1.Resource) + _, err = backend.WriteCAS(testContext(t), res) + require.NoError(t, err) + + // Unblock the Delete by allowing the backend read to return and attempt a CAS delete. + // The CAS delete should fail once, and they retry the backend read/delete cycle again + // successfully. + close(backend.blockCh) + + // Check that the delete succeeded anyway because of a retry. + require.NoError(t, <-deleteResultCh) +} + func TestDelete_TombstoneDeletionDoesNotCreateNewTombstone(t *testing.T) { t.Parallel() - server, client, ctx := testDeps(t) - demo.RegisterTypes(server.Registry) + ctx := context.Background() + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) artist, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -263,7 +341,7 @@ func TestDelete_TombstoneDeletionDoesNotCreateNewTombstone(t *testing.T) { // verify artist's tombstone created rsp2, err := client.Read(ctx, &pbresource.ReadRequest{ Id: &pbresource.ID{ - Name: tombstoneName(artist.Id), + Name: svc.TombstoneNameFor(artist.Id), Type: resource.TypeV1Tombstone, Tenancy: artist.Id.Tenancy, }, @@ -284,16 +362,22 @@ func TestDelete_TombstoneDeletionDoesNotCreateNewTombstone(t *testing.T) { func TestDelete_NotFound(t *testing.T) { t.Parallel() + run := func(t *testing.T, client pbresource.ResourceServiceClient, tc deleteTestCase) { + artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + // verify delete of non-existant or already deleted resource is a no-op + _, err = client.Delete(context.Background(), tc.deleteReqFn(artist)) + require.NoError(t, err) + } + + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + for desc, tc := range deleteTestCases() { t.Run(desc, func(t *testing.T) { - server, client, ctx := testDeps(t) - demo.RegisterTypes(server.Registry) - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - - // verify delete of non-existant or already deleted resource is a no-op - _, err = client.Delete(ctx, tc.deleteReqFn(artist)) - require.NoError(t, err) + run(t, client, tc) }) } } @@ -301,23 +385,27 @@ func TestDelete_NotFound(t *testing.T) { func TestDelete_VersionMismatch(t *testing.T) { t.Parallel() - server, client, ctx := testDeps(t) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + artist, err := demo.GenerateV2Artist() require.NoError(t, err) - rsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: artist}) + rsp, err := client.Write(context.Background(), &pbresource.WriteRequest{Resource: artist}) require.NoError(t, err) // delete with a version that is different from the stored version - _, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: rsp.Resource.Id, Version: "non-existent-version"}) + _, err = client.Delete(context.Background(), &pbresource.DeleteRequest{Id: rsp.Resource.Id, Version: "non-existent-version"}) require.Error(t, err) require.Equal(t, codes.Aborted.String(), status.Code(err).String()) require.ErrorContains(t, err, "CAS operation failed") } func TestDelete_MarkedForDeletionWhenFinalizersPresent(t *testing.T) { - server, client, ctx := testDeps(t) - demo.RegisterTypes(server.Registry) + ctx := context.Background() + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) // Create a resource with a finalizer res := rtest.Resource(demo.TypeV1Artist, "manwithnoname"). @@ -346,8 +434,10 @@ func TestDelete_MarkedForDeletionWhenFinalizersPresent(t *testing.T) { } func TestDelete_ImmediatelyDeletedAfterFinalizersRemoved(t *testing.T) { - server, client, ctx := testDeps(t) - demo.RegisterTypes(server.Registry) + ctx := context.Background() + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) // Create a resource with a finalizer res := rtest.Resource(demo.TypeV1Artist, "manwithnoname"). @@ -377,12 +467,6 @@ func TestDelete_ImmediatelyDeletedAfterFinalizersRemoved(t *testing.T) { require.Equal(t, codes.NotFound.String(), status.Code(err).String()) } -func testDeps(t *testing.T) (*Server, pbresource.ResourceServiceClient, context.Context) { - server := testServer(t) - client := testClient(t, server) - return server, client, context.Background() -} - type deleteTestCase struct { deleteReqFn func(r *pbresource.Resource) *pbresource.DeleteRequest } diff --git a/agent/grpc-external/services/resource/list.go b/agent/grpc-external/services/resource/list.go index dc7f88a404c8..2e51c443d4a7 100644 --- a/agent/grpc-external/services/resource/list.go +++ b/agent/grpc-external/services/resource/list.go @@ -100,16 +100,16 @@ func (s *Server) ensureListRequestValid(req *pbresource.ListRequest) (*resource. return nil, err } - if err = checkV2Tenancy(s.UseV2Tenancy, req.Type); err != nil { - return nil, err - } + // Ignore return value since read ops are allowed but will log a warning if the feature is + // not enabled in the license. + _ = s.FeatureCheck(reg) if err := validateWildcardTenancy(req.Tenancy, req.NamePrefix); err != nil { return nil, err } // Error when partition scoped and namespace not empty. - if reg.Scope == resource.ScopePartition && req.Tenancy.Namespace != "" { + if reg.Scope == resource.ScopePartition && req.Tenancy.Namespace != "" && req.Tenancy.Namespace != storage.Wildcard { return nil, status.Errorf( codes.InvalidArgument, "partition scoped type %s cannot have a namespace. got: %s", diff --git a/agent/grpc-external/services/resource/list_by_owner.go b/agent/grpc-external/services/resource/list_by_owner.go index e810ce31a4d0..29e14e407246 100644 --- a/agent/grpc-external/services/resource/list_by_owner.go +++ b/agent/grpc-external/services/resource/list_by_owner.go @@ -42,11 +42,6 @@ func (s *Server) ListByOwner(ctx context.Context, req *pbresource.ListByOwnerReq return nil, status.Errorf(codes.Internal, "failed list acl: %v", err) } - // Check tenancy exists for the v2 resource. - if err = tenancyExists(reg, s.TenancyBridge, req.Owner.Tenancy, codes.InvalidArgument); err != nil { - return nil, err - } - // Get owned resources. children, err := s.Backend.ListByOwner(ctx, req.Owner) if err != nil { @@ -105,19 +100,9 @@ func (s *Server) ensureListByOwnerRequestValid(req *pbresource.ListByOwnerReques return nil, err } - if err = checkV2Tenancy(s.UseV2Tenancy, req.Owner.Type); err != nil { + if err = validateScopedTenancy(reg.Scope, reg.Type, req.Owner.Tenancy, true); err != nil { return nil, err } - // Error when partition scoped and namespace not empty. - if reg.Scope == resource.ScopePartition && req.Owner.Tenancy.Namespace != "" { - return nil, status.Errorf( - codes.InvalidArgument, - "partition scoped type %s cannot have a namespace. got: %s", - resource.ToGVK(req.Owner.Type), - req.Owner.Tenancy.Namespace, - ) - } - return reg, nil } diff --git a/agent/grpc-external/services/resource/list_by_owner_test.go b/agent/grpc-external/services/resource/list_by_owner_test.go index 78024e68d0fb..23c537dcd6fd 100644 --- a/agent/grpc-external/services/resource/list_by_owner_test.go +++ b/agent/grpc-external/services/resource/list_by_owner_test.go @@ -1,7 +1,7 @@ // // Copyright (c) HashiCorp, Inc. // // SPDX-License-Identifier: BUSL-1.1 -package resource +package resource_test import ( "context" @@ -9,107 +9,127 @@ import ( "strings" "testing" - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/demo" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" "github.com/oklog/ulid/v2" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" + + "github.com/hashicorp/consul/acl" + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/demo" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v1" + "github.com/hashicorp/consul/proto/private/prototest" ) func TestListByOwner_InputValidation(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) type testCase struct { - modFn func(artistId, recordlabelId *pbresource.ID) *pbresource.ID + modFn func(artistId, recordlabelId, executiveId *pbresource.ID) *pbresource.ID errContains string } testCases := map[string]testCase{ "no owner": { - modFn: func(artistId, recordLabelId *pbresource.ID) *pbresource.ID { + modFn: func(_, _, _ *pbresource.ID) *pbresource.ID { return nil }, errContains: "owner is required", }, "no type": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Type = nil return artistId }, errContains: "owner.type is required", }, "no name": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Name = "" return artistId }, errContains: "owner.name invalid", }, "name mixed case": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Name = "U2" return artistId }, errContains: "owner.name invalid", }, "name too long": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Name = strings.Repeat("n", resource.MaxNameLength+1) return artistId }, errContains: "owner.name invalid", }, "partition mixed case": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Tenancy.Partition = "Default" return artistId }, errContains: "owner.tenancy.partition invalid", }, "partition too long": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) return artistId }, errContains: "owner.tenancy.partition invalid", }, "namespace mixed case": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Tenancy.Namespace = "Default" return artistId }, errContains: "owner.tenancy.namespace invalid", }, "namespace too long": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) return artistId }, errContains: "owner.tenancy.namespace invalid", }, "no uid": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { + modFn: func(artistId, _, _ *pbresource.ID) *pbresource.ID { artistId.Uid = "" return artistId }, errContains: "owner uid is required", }, "partition scope with non-empty namespace": { - modFn: func(_, recordLabelId *pbresource.ID) *pbresource.ID { + modFn: func(_, recordLabelId, _ *pbresource.ID) *pbresource.ID { recordLabelId.Uid = ulid.Make().String() recordLabelId.Tenancy.Namespace = "ishouldnothaveanamespace" return recordLabelId }, errContains: "cannot have a namespace", }, + "cluster scope with non-empty partition": { + modFn: func(_, _, executiveId *pbresource.ID) *pbresource.ID { + executiveId.Uid = ulid.Make().String() + executiveId.Tenancy.Partition = "ishouldnothaveapartition" + return executiveId + }, + errContains: "cannot have a partition", + }, + "cluster scope with non-empty namespace": { + modFn: func(_, _, executiveId *pbresource.ID) *pbresource.ID { + executiveId.Uid = ulid.Make().String() + executiveId.Tenancy.Namespace = "ishouldnothaveanamespace" + return executiveId + }, + errContains: "cannot have a namespace", + }, } for desc, tc := range testCases { t.Run(desc, func(t *testing.T) { @@ -119,8 +139,11 @@ func TestListByOwner_InputValidation(t *testing.T) { recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") require.NoError(t, err) + executive, err := demo.GenerateV1Executive("marvin", "CEO") + require.NoError(t, err) + // Each test case picks which resource to use based on the resource type's scope. - req := &pbresource.ListByOwnerRequest{Owner: tc.modFn(artist.Id, recordLabel.Id)} + req := &pbresource.ListByOwnerRequest{Owner: tc.modFn(artist.Id, recordLabel.Id, executive.Id)} _, err = client.ListByOwner(testContext(t), req) require.Error(t, err) @@ -131,8 +154,7 @@ func TestListByOwner_InputValidation(t *testing.T) { } func TestListByOwner_TypeNotRegistered(t *testing.T) { - server := testServer(t) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder().Run(t) _, err := client.ListByOwner(context.Background(), &pbresource.ListByOwnerRequest{ Owner: &pbresource.ID{ @@ -148,9 +170,9 @@ func TestListByOwner_TypeNotRegistered(t *testing.T) { } func TestListByOwner_Empty(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -164,9 +186,9 @@ func TestListByOwner_Empty(t *testing.T) { } func TestListByOwner_Many(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -197,59 +219,52 @@ func TestListByOwner_Many(t *testing.T) { func TestListByOwner_OwnerTenancyDoesNotExist(t *testing.T) { type testCase struct { - modFn func(artistId, recordlabelId *pbresource.ID) *pbresource.ID - errContains string + modFn func(artistId, recordlabelId *pbresource.ID) *pbresource.ID } tenancyCases := map[string]testCase{ - "partition not found when namespace scoped": { + "namespace scoped owner with non-existent partition": { modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { id := clone(artistId) - id.Uid = "doesnotmatter" id.Tenancy.Partition = "boguspartition" return id }, - errContains: "partition not found", }, - "namespace not found when namespace scoped": { + "namespace scoped owner with non-existent namespace": { modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { id := clone(artistId) - id.Uid = "doesnotmatter" id.Tenancy.Namespace = "bogusnamespace" return id }, - errContains: "namespace not found", }, - "partition not found when partition scoped": { + "partition scoped owner with non-existent partition": { modFn: func(_, recordLabelId *pbresource.ID) *pbresource.ID { id := clone(recordLabelId) - id.Uid = "doesnotmatter" id.Tenancy.Partition = "boguspartition" return id }, - errContains: "partition not found", }, } for desc, tc := range tenancyCases { t.Run(desc, func(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) - - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") - require.NoError(t, err) - recordLabel, err = server.Backend.WriteCAS(testContext(t), recordLabel) - require.NoError(t, err) - - artist, err := demo.GenerateV2Artist() + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + recordLabel := resourcetest.Resource(demo.TypeV1RecordLabel, "looney-tunes"). + WithTenancy(resource.DefaultPartitionedTenancy()). + WithData(t, &pbdemo.RecordLabel{Name: "Looney Tunes"}). + Write(t, client) + + artist := resourcetest.Resource(demo.TypeV1Artist, "blur"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, &pbdemo.Artist{Name: "Blur"}). + WithOwner(recordLabel.Id). + Write(t, client) + + // Verify non-existant tenancy units in owner return empty list. + rsp, err := client.ListByOwner(testContext(t), &pbresource.ListByOwnerRequest{Owner: tc.modFn(artist.Id, recordLabel.Id)}) require.NoError(t, err) - artist, err = server.Backend.WriteCAS(testContext(t), artist) - require.NoError(t, err) - - // Verify non-existant tenancy units in owner err with invalid arg. - _, err = client.ListByOwner(testContext(t), &pbresource.ListByOwnerRequest{Owner: tc.modFn(artist.Id, recordLabel.Id)}) - require.Error(t, err) - require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.ErrorContains(t, err, tc.errContains) + require.Empty(t, rsp.Resources) }) } } @@ -257,9 +272,9 @@ func TestListByOwner_OwnerTenancyDoesNotExist(t *testing.T) { func TestListByOwner_Tenancy_Defaults_And_Normalization(t *testing.T) { for tenancyDesc, modFn := range tenancyCases() { t.Run(tenancyDesc, func(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) // Create partition scoped recordLabel. recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") @@ -329,9 +344,9 @@ func TestListByOwner_ACL_PerTypeAllowed(t *testing.T) { // roundtrip a ListByOwner which attempts to return a single resource func roundTripListByOwner(t *testing.T, authz acl.Authorizer) (*pbresource.Resource, *pbresource.ListByOwnerResponse, error) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + builder := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes) + client := builder.Run(t) artist, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -347,10 +362,11 @@ func roundTripListByOwner(t *testing.T, authz acl.Authorizer) (*pbresource.Resou album = rsp2.Resource require.NoError(t, err) - mockACLResolver := &MockACLResolver{} + // Mock has to be put in place after the above writes so writes will succeed. + mockACLResolver := &svc.MockACLResolver{} mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). Return(authz, nil) - server.ACLResolver = mockACLResolver + builder.ServiceImpl().ACLResolver = mockACLResolver rsp3, err := client.ListByOwner(testContext(t), &pbresource.ListByOwnerRequest{Owner: artist.Id}) return album, rsp3, err diff --git a/agent/grpc-external/services/resource/list_test.go b/agent/grpc-external/services/resource/list_test.go index 5af6747f8444..43d5def0c37b 100644 --- a/agent/grpc-external/services/resource/list_test.go +++ b/agent/grpc-external/services/resource/list_test.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package resource +package resource_test import ( "context" @@ -10,25 +10,27 @@ import ( "strings" "testing" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "github.com/hashicorp/consul/acl" + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" "github.com/hashicorp/consul/agent/grpc-external/testutils" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/internal/storage" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/proto/private/prototest" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" ) func TestList_InputValidation(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) type testCase struct { modReqFn func(req *pbresource.ListRequest) @@ -93,8 +95,7 @@ func TestList_InputValidation(t *testing.T) { } func TestList_TypeNotFound(t *testing.T) { - server := testServer(t) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder().Run(t) _, err := client.List(context.Background(), &pbresource.ListRequest{ Type: demo.TypeV2Artist, @@ -109,9 +110,9 @@ func TestList_TypeNotFound(t *testing.T) { func TestList_Empty(t *testing.T) { for desc, tc := range listTestCases() { t.Run(desc, func(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) rsp, err := client.List(tc.ctx, &pbresource.ListRequest{ Type: demo.TypeV1Artist, @@ -127,9 +128,9 @@ func TestList_Empty(t *testing.T) { func TestList_Many(t *testing.T) { for desc, tc := range listTestCases() { t.Run(desc, func(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) resources := make([]*pbresource.Resource, 10) for i := 0; i < len(resources); i++ { @@ -159,9 +160,9 @@ func TestList_Many(t *testing.T) { func TestList_NamePrefix(t *testing.T) { for desc, tc := range listTestCases() { t.Run(desc, func(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) expectedResources := []*pbresource.Resource{} @@ -201,9 +202,9 @@ func TestList_Tenancy_Defaults_And_Normalization(t *testing.T) { ctx := context.Background() for desc, tc := range wildcardTenancyCases() { t.Run(desc, func(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) // Write partition scoped record label recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") @@ -217,6 +218,12 @@ func TestList_Tenancy_Defaults_And_Normalization(t *testing.T) { artistRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: artist}) require.NoError(t, err) + // Write a cluster scoped Executive + executive, err := demo.GenerateV1Executive("king-arthur", "CEO") + require.NoError(t, err) + executiveRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: executive}) + require.NoError(t, err) + // List and verify correct resource returned for empty tenancy units. listRsp, err := client.List(ctx, &pbresource.ListRequest{ Type: tc.typ, @@ -224,10 +231,13 @@ func TestList_Tenancy_Defaults_And_Normalization(t *testing.T) { }) require.NoError(t, err) require.Len(t, listRsp.Resources, 1) - if tc.typ == demo.TypeV1RecordLabel { + switch tc.typ { + case demo.TypeV1RecordLabel: prototest.AssertDeepEqual(t, recordLabelRsp.Resource, listRsp.Resources[0]) - } else { + case demo.TypeV1Artist: prototest.AssertDeepEqual(t, artistRsp.Resource, listRsp.Resources[0]) + case demo.TypeV1Executive: + prototest.AssertDeepEqual(t, executiveRsp.Resource, listRsp.Resources[0]) } }) } @@ -236,14 +246,14 @@ func TestList_Tenancy_Defaults_And_Normalization(t *testing.T) { func TestList_GroupVersionMismatch(t *testing.T) { for desc, tc := range listTestCases() { t.Run(desc, func(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) artist, err := demo.GenerateV2Artist() require.NoError(t, err) - _, err = server.Backend.WriteCAS(tc.ctx, artist) + _, err = client.Write(tc.ctx, &pbresource.WriteRequest{Resource: artist}) require.NoError(t, err) rsp, err := client.List(tc.ctx, &pbresource.ListRequest{ @@ -261,7 +271,7 @@ func TestList_VerifyReadConsistencyArg(t *testing.T) { // Uses a mockBackend instead of the inmem Backend to verify the ReadConsistency argument is set correctly. for desc, tc := range listTestCases() { t.Run(desc, func(t *testing.T) { - mockBackend := NewMockBackend(t) + mockBackend := svc.NewMockBackend(t) server := testServer(t) server.Backend = mockBackend demo.RegisterTypes(server.Registry) @@ -322,25 +332,24 @@ func TestList_ACL_ListAllowed_ReadAllowed(t *testing.T) { prototest.AssertDeepEqual(t, artist, rsp.Resources[0]) } -// roundtrip a List which attempts to return a single resource func roundTripList(t *testing.T, authz acl.Authorizer) (*pbresource.Resource, *pbresource.ListResponse, error) { - server := testServer(t) - client := testClient(t, server) ctx := testContext(t) - - mockACLResolver := &MockACLResolver{} - mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). - Return(authz, nil) - server.ACLResolver = mockACLResolver - demo.RegisterTypes(server.Registry) + builder := svctest.NewResourceServiceBuilder().WithRegisterFns(demo.RegisterTypes) + client := builder.Run(t) artist, err := demo.GenerateV2Artist() require.NoError(t, err) - artist, err = server.Backend.WriteCAS(ctx, artist) + rsp1, err := client.Write(ctx, &pbresource.WriteRequest{Resource: artist}) require.NoError(t, err) - rsp, err := client.List( + // Put ACLResolver in place after above writes so writes not subject to ACLs + mockACLResolver := &svc.MockACLResolver{} + mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). + Return(authz, nil) + builder.ServiceImpl().Config.ACLResolver = mockACLResolver + + rsp2, err := client.List( ctx, &pbresource.ListRequest{ Type: artist.Id.Type, @@ -348,8 +357,7 @@ func roundTripList(t *testing.T, authz acl.Authorizer) (*pbresource.Resource, *p NamePrefix: "", }, ) - - return artist, rsp, err + return rsp1.Resource, rsp2, err } type listTestCase struct { diff --git a/agent/grpc-external/services/resource/mock_Registry.go b/agent/grpc-external/services/resource/mock_Registry.go index 288e8bcde8b6..c97b5428a303 100644 --- a/agent/grpc-external/services/resource/mock_Registry.go +++ b/agent/grpc-external/services/resource/mock_Registry.go @@ -43,6 +43,22 @@ func (_m *MockRegistry) Resolve(typ *pbresource.Type) (internalresource.Registra return r0, r1 } +// Types provides a mock function with given fields: +func (_m *MockRegistry) Types() []internalresource.Registration { + ret := _m.Called() + + var r0 []internalresource.Registration + if rf, ok := ret.Get(0).(func() []internalresource.Registration); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]internalresource.Registration) + } + } + + return r0 +} + type mockConstructorTestingTNewMockRegistry interface { mock.TestingT Cleanup(func()) diff --git a/agent/grpc-external/services/resource/mutate_and_validate.go b/agent/grpc-external/services/resource/mutate_and_validate.go new file mode 100644 index 000000000000..c58fd4a09572 --- /dev/null +++ b/agent/grpc-external/services/resource/mutate_and_validate.go @@ -0,0 +1,141 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package resource + +import ( + "context" + "strings" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +func (s *Server) MutateAndValidate(ctx context.Context, req *pbresource.MutateAndValidateRequest) (*pbresource.MutateAndValidateResponse, error) { + tenancyMarkedForDeletion, err := s.mutateAndValidate(ctx, req.Resource, false) + if err != nil { + return nil, err + } + + if tenancyMarkedForDeletion { + return nil, status.Errorf( + codes.InvalidArgument, + "tenancy marked for deletion: %s/%s", + req.Resource.Id.Tenancy.Partition, + req.Resource.Id.Tenancy.Namespace, + ) + } + return &pbresource.MutateAndValidateResponse{Resource: req.Resource}, nil +} + +// private DRY impl that is used by both the Write and MutateAndValidate RPCs. +func (s *Server) mutateAndValidate(ctx context.Context, res *pbresource.Resource, enforceLicenseCheck bool) (tenancyMarkedForDeletion bool, err error) { + reg, err := s.ensureResourceValid(res, enforceLicenseCheck) + if err != nil { + return false, err + } + + v1EntMeta := v2TenancyToV1EntMeta(res.Id.Tenancy) + authz, authzContext, err := s.getAuthorizer(tokenFromContext(ctx), v1EntMeta) + if err != nil { + return false, err + } + v1EntMetaToV2Tenancy(reg, v1EntMeta, res.Id.Tenancy) + + // Check the user sent the correct type of data. + if res.Data != nil && !res.Data.MessageIs(reg.Proto) { + got := strings.TrimPrefix(res.Data.TypeUrl, "type.googleapis.com/") + + return false, status.Errorf( + codes.InvalidArgument, + "resource.data is of wrong type (expected=%q, got=%q)", + reg.Proto.ProtoReflect().Descriptor().FullName(), + got, + ) + } + + if err = reg.Mutate(res); err != nil { + return false, status.Errorf(codes.Internal, "failed mutate hook: %v", err.Error()) + } + + if err = reg.Validate(res); err != nil { + return false, status.Error(codes.InvalidArgument, err.Error()) + } + + // ACL check comes before tenancy existence checks to not leak tenancy "existence". + err = reg.ACLs.Write(authz, authzContext, res) + switch { + case acl.IsErrPermissionDenied(err): + return false, status.Error(codes.PermissionDenied, err.Error()) + case err != nil: + return false, status.Errorf(codes.Internal, "failed write acl: %v", err) + } + + // Check tenancy exists for the V2 resource + if err = tenancyExists(reg, s.TenancyBridge, res.Id.Tenancy, codes.InvalidArgument); err != nil { + return false, err + } + + // This is used later in the "create" and "update" paths to block non-delete related writes + // when a tenancy unit has been marked for deletion. + tenancyMarkedForDeletion, err = isTenancyMarkedForDeletion(reg, s.TenancyBridge, res.Id.Tenancy) + if err != nil { + return false, status.Errorf(codes.Internal, "failed tenancy marked for deletion check: %v", err) + } + if tenancyMarkedForDeletion { + return true, nil + } + return false, nil +} + +func (s *Server) ensureResourceValid(res *pbresource.Resource, enforceLicenseCheck bool) (*resource.Registration, error) { + var field string + switch { + case res == nil: + field = "resource" + case res.Id == nil: + field = "resource.id" + } + + if field != "" { + return nil, status.Errorf(codes.InvalidArgument, "%s is required", field) + } + + if err := validateId(res.Id, "resource.id"); err != nil { + return nil, err + } + + if res.Owner != nil { + if err := validateId(res.Owner, "resource.owner"); err != nil { + return nil, err + } + } + + // Check type exists. + reg, err := s.resolveType(res.Id.Type) + if err != nil { + return nil, err + } + + // Since this is shared by Write and MutateAndValidate, only fail the operation + // if it's a write operation and the feature is not allowed by the license. + if err = s.FeatureCheck(reg); err != nil && enforceLicenseCheck { + return nil, err + } + + // Check scope + if reg.Scope == resource.ScopePartition && res.Id.Tenancy.Namespace != "" { + return nil, status.Errorf( + codes.InvalidArgument, + "partition scoped resource %s cannot have a namespace. got: %s", + resource.ToGVK(res.Id.Type), + res.Id.Tenancy.Namespace, + ) + } + + return reg, nil +} diff --git a/agent/grpc-external/services/resource/mutate_and_validate_test.go b/agent/grpc-external/services/resource/mutate_and_validate_test.go new file mode 100644 index 000000000000..6644f108d402 --- /dev/null +++ b/agent/grpc-external/services/resource/mutate_and_validate_test.go @@ -0,0 +1,162 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package resource_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" + "github.com/hashicorp/consul/internal/resource/demo" + "github.com/hashicorp/consul/proto-public/pbresource" + pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2" + "github.com/hashicorp/consul/proto/private/prototest" +) + +func TestMutateAndValidate_InputValidation(t *testing.T) { + run := func(t *testing.T, client pbresource.ResourceServiceClient, tc resourceValidTestCase) { + artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + require.NoError(t, err) + + req := &pbresource.MutateAndValidateRequest{Resource: tc.modFn(artist, recordLabel)} + _, err = client.MutateAndValidate(testContext(t), req) + require.Error(t, err) + require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) + require.ErrorContains(t, err, tc.errContains) + } + + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + for desc, tc := range resourceValidTestCases(t) { + t.Run(desc, func(t *testing.T) { + run(t, client, tc) + }) + } +} + +func TestMutateAndValidate_OwnerValidation(t *testing.T) { + run := func(t *testing.T, client pbresource.ResourceServiceClient, tc ownerValidTestCase) { + artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + album, err := demo.GenerateV2Album(artist.Id) + require.NoError(t, err) + + tc.modFn(album) + + _, err = client.MutateAndValidate(testContext(t), &pbresource.MutateAndValidateRequest{Resource: album}) + require.Error(t, err) + require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) + require.ErrorContains(t, err, tc.errorContains) + } + + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + for desc, tc := range ownerValidationTestCases(t) { + t.Run(desc, func(t *testing.T) { + run(t, client, tc) + }) + } +} + +func TestMutateAndValidate_TypeNotFound(t *testing.T) { + client := svctest.NewResourceServiceBuilder().Run(t) + + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + _, err = client.MutateAndValidate(testContext(t), &pbresource.MutateAndValidateRequest{Resource: res}) + require.Error(t, err) + require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) + require.Contains(t, err.Error(), "resource type demo.v2.Artist not registered") +} + +func TestMutateAndValidate_Success(t *testing.T) { + run := func(t *testing.T, client pbresource.ResourceServiceClient, tc mavOrWriteSuccessTestCase) { + recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + require.NoError(t, err) + + artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + rsp, err := client.MutateAndValidate(testContext(t), &pbresource.MutateAndValidateRequest{Resource: tc.modFn(artist, recordLabel)}) + require.NoError(t, err) + prototest.AssertDeepEqual(t, tc.expectedTenancy, rsp.Resource.Id.Tenancy) + } + + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + for desc, tc := range mavOrWriteSuccessTestCases(t) { + t.Run(desc, func(t *testing.T) { + run(t, client, tc) + }) + } +} + +func TestMutateAndValidate_Mutate(t *testing.T) { + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + artistData := &pbdemov2.Artist{} + artist.Data.UnmarshalTo(artistData) + require.NoError(t, err) + + // mutate hook sets genre to disco when unspecified + artistData.Genre = pbdemov2.Genre_GENRE_UNSPECIFIED + artist.Data.MarshalFrom(artistData) + require.NoError(t, err) + + rsp, err := client.MutateAndValidate(testContext(t), &pbresource.MutateAndValidateRequest{Resource: artist}) + require.NoError(t, err) + + // verify mutate hook set genre to disco + require.NoError(t, rsp.Resource.Data.UnmarshalTo(artistData)) + require.Equal(t, pbdemov2.Genre_GENRE_DISCO, artistData.Genre) +} + +func TestMutateAndValidate_TenancyMarkedForDeletion_Fails(t *testing.T) { + for desc, tc := range mavOrWriteTenancyMarkedForDeletionTestCases(t) { + t.Run(desc, func(t *testing.T) { + server := testServer(t) + client := testClient(t, server) + demo.RegisterTypes(server.Registry) + + recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") + require.NoError(t, err) + recordLabel.Id.Tenancy.Partition = "ap1" + + artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + artist.Id.Tenancy.Partition = "ap1" + artist.Id.Tenancy.Namespace = "ns1" + + mockTenancyBridge := &svc.MockTenancyBridge{} + mockTenancyBridge.On("PartitionExists", "ap1").Return(true, nil) + mockTenancyBridge.On("NamespaceExists", "ap1", "ns1").Return(true, nil) + server.TenancyBridge = mockTenancyBridge + + _, err = client.MutateAndValidate(testContext(t), &pbresource.MutateAndValidateRequest{Resource: tc.modFn(artist, recordLabel, mockTenancyBridge)}) + require.Error(t, err) + require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) + require.Contains(t, err.Error(), tc.errContains) + }) + } +} diff --git a/agent/grpc-external/services/resource/read.go b/agent/grpc-external/services/resource/read.go index 9fe59024ce8e..bf69e2549a35 100644 --- a/agent/grpc-external/services/resource/read.go +++ b/agent/grpc-external/services/resource/read.go @@ -24,7 +24,7 @@ func (s *Server) Read(ctx context.Context, req *pbresource.ReadRequest) (*pbreso } // acl.EnterpriseMeta acl.AuthorizerContext follow rules for V1 resources since they integrate with the V1 acl subsystem. - // pbresource.Tenacy follows rules for V2 resources and the Resource service. + // pbresource.Tenancy follows rules for V2 resources and the Resource service. // Example: // // A CE namespace scoped resource: @@ -102,12 +102,12 @@ func (s *Server) ensureReadRequestValid(req *pbresource.ReadRequest) (*resource. return nil, err } - if err = checkV2Tenancy(s.UseV2Tenancy, req.Id.Type); err != nil { - return nil, err - } + // Ignore return value since read ops are allowed but will log a warning if the feature is + // not enabled in the license. + _ = s.FeatureCheck(reg) // Check scope - if err = validateScopedTenancy(reg.Scope, req.Id.Type, req.Id.Tenancy); err != nil { + if err = validateScopedTenancy(reg.Scope, req.Id.Type, req.Id.Tenancy, false); err != nil { return nil, err } diff --git a/agent/grpc-external/services/resource/read_test.go b/agent/grpc-external/services/resource/read_test.go index 2afdfeab0e1e..fbea0137af68 100644 --- a/agent/grpc-external/services/resource/read_test.go +++ b/agent/grpc-external/services/resource/read_test.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package resource +package resource_test import ( "context" @@ -19,21 +19,21 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl/resolver" + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" "github.com/hashicorp/consul/agent/grpc-external/testutils" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/internal/storage" - "github.com/hashicorp/consul/internal/tenancy" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/proto/private/prototest" "github.com/hashicorp/consul/sdk/testutil" ) func TestRead_InputValidation(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - tenancy.RegisterTypes(server.Registry) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) type testCase struct { modFn func(artistId, recordlabelId, executiveId *pbresource.ID) *pbresource.ID @@ -148,7 +148,7 @@ func TestRead_InputValidation(t *testing.T) { } func TestRead_TypeNotFound(t *testing.T) { - server := NewServer(Config{Registry: resource.NewRegistry()}) + server := svc.NewServer(svc.Config{Registry: resource.NewRegistry()}) client := testClient(t, server) artist, err := demo.GenerateV2Artist() @@ -160,85 +160,17 @@ func TestRead_TypeNotFound(t *testing.T) { require.Contains(t, err.Error(), "resource type demo.v2.Artist not registered") } -func TestRead_ResourceNotFound(t *testing.T) { - for desc, tc := range readTestCases() { - t.Run(desc, func(t *testing.T) { - type tenancyCase struct { - modFn func(artistId, recordlabelId *pbresource.ID) *pbresource.ID - errContains string - } - tenancyCases := map[string]tenancyCase{ - "resource not found by name": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - artistId.Name = "bogusname" - return artistId - }, - errContains: "resource not found", - }, - "partition not found when namespace scoped": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - id := clone(artistId) - id.Tenancy.Partition = "boguspartition" - return id - }, - errContains: "partition not found", - }, - "namespace not found when namespace scoped": { - modFn: func(artistId, _ *pbresource.ID) *pbresource.ID { - id := clone(artistId) - id.Tenancy.Namespace = "bogusnamespace" - return id - }, - errContains: "namespace not found", - }, - "partition not found when partition scoped": { - modFn: func(_, recordLabelId *pbresource.ID) *pbresource.ID { - id := clone(recordLabelId) - id.Tenancy.Partition = "boguspartition" - return id - }, - errContains: "partition not found", - }, - } - for tenancyDesc, tenancyCase := range tenancyCases { - t.Run(tenancyDesc, func(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) - - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") - require.NoError(t, err) - recordLabel, err = server.Backend.WriteCAS(tc.ctx, recordLabel) - require.NoError(t, err) - - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - artist, err = server.Backend.WriteCAS(tc.ctx, artist) - require.NoError(t, err) - - // Each tenancy test case picks which resource to use based on the resource type's scope. - _, err = client.Read(tc.ctx, &pbresource.ReadRequest{Id: tenancyCase.modFn(artist.Id, recordLabel.Id)}) - require.Error(t, err) - require.Equal(t, codes.NotFound.String(), status.Code(err).String()) - require.ErrorContains(t, err, tenancyCase.errContains) - }) - } - }) - } -} - func TestRead_GroupVersionMismatch(t *testing.T) { for desc, tc := range readTestCases() { t.Run(desc, func(t *testing.T) { - server := testServer(t) - - demo.RegisterTypes(server.Registry) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) artist, err := demo.GenerateV2Artist() require.NoError(t, err) - _, err = server.Backend.WriteCAS(tc.ctx, artist) + _, err = client.Write(tc.ctx, &pbresource.WriteRequest{Resource: artist}) require.NoError(t, err) id := clone(artist.Id) @@ -257,18 +189,20 @@ func TestRead_Success(t *testing.T) { t.Run(desc, func(t *testing.T) { for tenancyDesc, modFn := range tenancyCases() { t.Run(tenancyDesc, func(t *testing.T) { - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") require.NoError(t, err) - recordLabel, err = server.Backend.WriteCAS(tc.ctx, recordLabel) + rsp1, err := client.Write(tc.ctx, &pbresource.WriteRequest{Resource: recordLabel}) + recordLabel = rsp1.Resource require.NoError(t, err) artist, err := demo.GenerateV2Artist() require.NoError(t, err) - artist, err = server.Backend.WriteCAS(tc.ctx, artist) + rsp2, err := client.Write(tc.ctx, &pbresource.WriteRequest{Resource: artist}) + artist = rsp2.Resource require.NoError(t, err) // Each tenancy test case picks which resource to use based on the resource type's scope. @@ -295,7 +229,7 @@ func TestRead_VerifyReadConsistencyArg(t *testing.T) { for desc, tc := range readTestCases() { t.Run(desc, func(t *testing.T) { server := testServer(t) - mockBackend := NewMockBackend(t) + mockBackend := svc.NewMockBackend(t) server.Backend = mockBackend demo.RegisterTypes(server.Registry) @@ -364,15 +298,14 @@ func TestRead_ACLs(t *testing.T) { for desc, tc := range testcases { t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - dr := &dummyACLResolver{ result: testutils.ACLsDisabled(t), } - server.ACLResolver = dr - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + WithACLResolver(dr). + Run(t) dr.SetResult(tc.authz) testutil.RunStep(t, "does not exist", func(t *testing.T) { @@ -410,7 +343,7 @@ type dummyACLResolver struct { result resolver.Result } -var _ ACLResolver = (*dummyACLResolver)(nil) +var _ svc.ACLResolver = (*dummyACLResolver)(nil) func (r *dummyACLResolver) SetResult(result resolver.Result) { r.lock.Lock() diff --git a/agent/grpc-external/services/resource/server.go b/agent/grpc-external/services/resource/server.go index e2615ec4b3ba..21ad4bd45d2b 100644 --- a/agent/grpc-external/services/resource/server.go +++ b/agent/grpc-external/services/resource/server.go @@ -5,9 +5,10 @@ package resource import ( "context" + "errors" "strings" + "time" - "github.com/hashicorp/go-hclog" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" @@ -18,6 +19,7 @@ import ( "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/storage" + "github.com/hashicorp/consul/lib/retry" "github.com/hashicorp/consul/proto-public/pbresource" ) @@ -25,23 +27,6 @@ type Server struct { Config } -type Config struct { - Logger hclog.Logger - Registry Registry - - // Backend is the storage backend that will be used for resource persistence. - Backend Backend - ACLResolver ACLResolver - // TenancyBridge temporarily allows us to use V1 implementations of - // partitions and namespaces until V2 implementations are available. - TenancyBridge TenancyBridge - - // UseV2Tenancy is true if the "v2tenancy" experiement is active, false otherwise. - // Attempts to create v2 tenancy resources (partition or namespace) will fail when the - // flag is false. - UseV2Tenancy bool -} - //go:generate mockery --name Registry --inpackage type Registry interface { resource.Registry @@ -71,11 +56,11 @@ func NewServer(cfg Config) *Server { var _ pbresource.ResourceServiceServer = (*Server)(nil) -func (s *Server) Register(grpcServer *grpc.Server) { - pbresource.RegisterResourceServiceServer(grpcServer, s) +func (s *Server) Register(registrar grpc.ServiceRegistrar) { + pbresource.RegisterResourceServiceServer(registrar, s) } -// Get token from grpc metadata or AnonymounsTokenId if not found +// Get token from grpc metadata or AnonymousTokenId if not found func tokenFromContext(ctx context.Context) string { md, ok := metadata.FromIncomingContext(ctx) if !ok { @@ -149,8 +134,6 @@ func validateId(id *pbresource.ID, errorPrefix string) error { id.Tenancy = &pbresource.Tenancy{ Partition: "", Namespace: "", - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - PeerName: "local", } } @@ -164,10 +147,6 @@ func validateId(id *pbresource.ID, errorPrefix string) error { return status.Errorf(codes.InvalidArgument, "%s.tenancy.namespace invalid: %v", errorPrefix, err) } } - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - if id.Tenancy.PeerName == "" { - id.Tenancy.PeerName = resource.DefaultPeerName - } return nil } @@ -210,11 +189,6 @@ func validateWildcardTenancy(tenancy *pbresource.Tenancy, namePrefix string) err return status.Errorf(codes.InvalidArgument, "name_prefix invalid: must be lowercase alphanumeric, got: %v", namePrefix) } - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - if tenancy.PeerName == "" { - tenancy.PeerName = resource.DefaultPeerName - } - return nil } @@ -242,8 +216,8 @@ func tenancyExists(reg *resource.Registration, tenancyBridge TenancyBridge, tena return nil } -func validateScopedTenancy(scope resource.Scope, resourceType *pbresource.Type, tenancy *pbresource.Tenancy) error { - if scope == resource.ScopePartition && tenancy.Namespace != "" { +func validateScopedTenancy(scope resource.Scope, resourceType *pbresource.Type, tenancy *pbresource.Tenancy, allowWildcards bool) error { + if scope == resource.ScopePartition && tenancy.Namespace != "" && (!allowWildcards || tenancy.Namespace != storage.Wildcard) { return status.Errorf( codes.InvalidArgument, "partition scoped resource %s cannot have a namespace. got: %s", @@ -251,8 +225,9 @@ func validateScopedTenancy(scope resource.Scope, resourceType *pbresource.Type, tenancy.Namespace, ) } + if scope == resource.ScopeCluster { - if tenancy.Partition != "" { + if tenancy.Partition != "" && (!allowWildcards || tenancy.Partition != storage.Wildcard) { return status.Errorf( codes.InvalidArgument, "cluster scoped resource %s cannot have a partition: %s", @@ -260,7 +235,7 @@ func validateScopedTenancy(scope resource.Scope, resourceType *pbresource.Type, tenancy.Partition, ) } - if tenancy.Namespace != "" { + if tenancy.Namespace != "" && (!allowWildcards || tenancy.Namespace != storage.Wildcard) { return status.Errorf( codes.InvalidArgument, "cluster scoped resource %s cannot have a namespace: %s", @@ -272,28 +247,62 @@ func validateScopedTenancy(scope resource.Scope, resourceType *pbresource.Type, return nil } -// tenancyMarkedForDeletion returns a gRPC InvalidArgument when either partition or namespace is marked for deletion. -func tenancyMarkedForDeletion(reg *resource.Registration, tenancyBridge TenancyBridge, tenancy *pbresource.Tenancy) error { +func isTenancyMarkedForDeletion(reg *resource.Registration, tenancyBridge TenancyBridge, tenancy *pbresource.Tenancy) (bool, error) { if reg.Scope == resource.ScopePartition || reg.Scope == resource.ScopeNamespace { marked, err := tenancyBridge.IsPartitionMarkedForDeletion(tenancy.Partition) - switch { - case err != nil: - return err - case marked: - return status.Errorf(codes.InvalidArgument, "partition marked for deletion: %v", tenancy.Partition) + if err != nil { + return false, err + } + if marked { + return marked, nil } } if reg.Scope == resource.ScopeNamespace { marked, err := tenancyBridge.IsNamespaceMarkedForDeletion(tenancy.Partition, tenancy.Namespace) - switch { - case err != nil: - return err - case marked: - return status.Errorf(codes.InvalidArgument, "namespace marked for deletion: %v", tenancy.Namespace) + if err != nil { + return false, err } + return marked, nil } - return nil + + // Cluster scope has no tenancy so always return false + return false, nil +} + +// retryCAS retries the given operation with exponential backoff if the user +// didn't provide a version. This is intended to hide failures when the user +// isn't intentionally performing a CAS operation (all writes are, by design, +// CAS operations at the storage backend layer). +func (s *Server) retryCAS(ctx context.Context, vsn string, cas func() error) error { + if vsn != "" { + return cas() + } + + const maxAttempts = 5 + + // These parameters are fairly arbitrary, so if you find better ones then go + // ahead and swap them out! In general, we want to wait long enough to smooth + // over small amounts of storage replication lag, but not so long that we make + // matters worse by holding onto load. + backoff := &retry.Waiter{ + MinWait: 50 * time.Millisecond, + MaxWait: 1 * time.Second, + Jitter: retry.NewJitter(50), + Factor: 75 * time.Millisecond, + } + + var err error + for i := 1; i <= maxAttempts; i++ { + if err = cas(); !errors.Is(err, storage.ErrCASFailure) { + break + } + if backoff.Wait(ctx) != nil { + break + } + s.Logger.Trace("retrying failed CAS operation", "failure_count", i) + } + return err } func clone[T proto.Message](v T) T { return proto.Clone(v).(T) } diff --git a/agent/grpc-external/services/resource/server_ce.go b/agent/grpc-external/services/resource/server_ce.go index 2e3f792fe1d1..88f6e60add28 100644 --- a/agent/grpc-external/services/resource/server_ce.go +++ b/agent/grpc-external/services/resource/server_ce.go @@ -6,13 +6,11 @@ package resource import ( - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" ) func v2TenancyToV1EntMeta(tenancy *pbresource.Tenancy) *acl.EnterpriseMeta { @@ -29,11 +27,19 @@ func v1EntMetaToV2Tenancy(reg *resource.Registration, entMeta *acl.EnterpriseMet } } -// checkV2Tenancy returns FailedPrecondition error for namespace resource type -// when the "v2tenancy" feature flag is not enabled. -func checkV2Tenancy(useV2Tenancy bool, rtype *pbresource.Type) error { - if resource.EqualType(rtype, pbtenancy.NamespaceType) && !useV2Tenancy { - return status.Errorf(codes.FailedPrecondition, "use of the v2 namespace resource requires the \"v2tenancy\" feature flag") - } +type Config struct { + Logger hclog.Logger + Registry Registry + + // Backend is the storage backend that will be used for resource persistence. + Backend Backend + ACLResolver ACLResolver + // TenancyBridge temporarily allows us to use V1 implementations of + // partitions and namespaces until V2 implementations are available. + TenancyBridge TenancyBridge +} + +// FeatureCheck does not apply to the community edition. +func (s *Server) FeatureCheck(reg *resource.Registration) error { return nil } diff --git a/agent/grpc-external/services/resource/server_ce_test.go b/agent/grpc-external/services/resource/server_ce_test.go index c385b65f3ceb..f48ff3b52b99 100644 --- a/agent/grpc-external/services/resource/server_ce_test.go +++ b/agent/grpc-external/services/resource/server_ce_test.go @@ -3,7 +3,7 @@ //go:build !consulent -package resource +package resource_test import "github.com/hashicorp/consul/acl" diff --git a/agent/grpc-external/services/resource/server_test.go b/agent/grpc-external/services/resource/server_test.go index e0b52263901f..f069296c88bc 100644 --- a/agent/grpc-external/services/resource/server_test.go +++ b/agent/grpc-external/services/resource/server_test.go @@ -1,26 +1,30 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package resource +package resource_test import ( "context" "fmt" + "sync/atomic" "testing" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "google.golang.org/grpc" + "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" "github.com/hashicorp/go-uuid" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl/resolver" + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" "github.com/hashicorp/consul/agent/grpc-external/testutils" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" + "github.com/hashicorp/consul/internal/storage" "github.com/hashicorp/consul/internal/storage/inmem" "github.com/hashicorp/consul/proto-public/pbresource" pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2" @@ -51,7 +55,8 @@ func AuthorizerFrom(t *testing.T, policyStrs ...string) resolver.Result { } } -func testServer(t *testing.T) *Server { +// Deprecated: use NewResourceServiceBuilder instead +func testServer(t *testing.T) *svc.Server { t.Helper() backend, err := inmem.NewBackend() @@ -59,7 +64,7 @@ func testServer(t *testing.T) *Server { go backend.Run(testContext(t)) // Mock the ACL Resolver to "allow all" for testing. - mockACLResolver := &MockACLResolver{} + mockACLResolver := &svc.MockACLResolver{} mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). Return(testutils.ACLsDisabled(t), nil). Run(func(args mock.Arguments) { @@ -76,7 +81,7 @@ func testServer(t *testing.T) *Server { }) // Mock the tenancy bridge since we can't use the real thing. - mockTenancyBridge := &MockTenancyBridge{} + mockTenancyBridge := &svc.MockTenancyBridge{} mockTenancyBridge.On("PartitionExists", resource.DefaultPartitionName).Return(true, nil) mockTenancyBridge.On("NamespaceExists", resource.DefaultPartitionName, resource.DefaultNamespaceName).Return(true, nil) mockTenancyBridge.On("PartitionExists", mock.Anything).Return(false, nil) @@ -84,7 +89,7 @@ func testServer(t *testing.T) *Server { mockTenancyBridge.On("IsPartitionMarkedForDeletion", resource.DefaultPartitionName).Return(false, nil) mockTenancyBridge.On("IsNamespaceMarkedForDeletion", resource.DefaultPartitionName, resource.DefaultNamespaceName).Return(false, nil) - return NewServer(Config{ + return svc.NewServer(svc.Config{ Logger: testutil.Logger(t), Registry: resource.NewRegistry(), Backend: backend, @@ -93,7 +98,8 @@ func testServer(t *testing.T) *Server { }) } -func testClient(t *testing.T, server *Server) pbresource.ResourceServiceClient { +// Deprecated: use NewResourceServiceBuilder instead +func testClient(t *testing.T, server *svc.Server) pbresource.ResourceServiceClient { t.Helper() addr := testutils.RunTestServer(t, server) @@ -146,7 +152,6 @@ func wildcardTenancyCases() map[string]struct { tenancy: &pbresource.Tenancy{ Partition: "", Namespace: resource.DefaultNamespaceName, - PeerName: "local", }, }, "namespaced type with empty namespace": { @@ -154,16 +159,6 @@ func wildcardTenancyCases() map[string]struct { tenancy: &pbresource.Tenancy{ Partition: resource.DefaultPartitionName, Namespace: "", - PeerName: "local", - }, - }, - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - "namespaced type with empty peername": { - typ: demo.TypeV2Artist, - tenancy: &pbresource.Tenancy{ - Partition: resource.DefaultPartitionName, - Namespace: resource.DefaultNamespaceName, - PeerName: "", }, }, "namespaced type with empty partition and namespace": { @@ -171,7 +166,6 @@ func wildcardTenancyCases() map[string]struct { tenancy: &pbresource.Tenancy{ Partition: "", Namespace: "", - PeerName: "local", }, }, "namespaced type with wildcard partition and empty namespace": { @@ -179,7 +173,6 @@ func wildcardTenancyCases() map[string]struct { tenancy: &pbresource.Tenancy{ Partition: "*", Namespace: "", - PeerName: "local", }, }, "namespaced type with empty partition and wildcard namespace": { @@ -187,7 +180,6 @@ func wildcardTenancyCases() map[string]struct { tenancy: &pbresource.Tenancy{ Partition: "", Namespace: "*", - PeerName: "local", }, }, "partitioned type with empty partition": { @@ -195,14 +187,34 @@ func wildcardTenancyCases() map[string]struct { tenancy: &pbresource.Tenancy{ Partition: "", Namespace: "", - PeerName: "local", }, }, "partitioned type with wildcard partition": { typ: demo.TypeV1RecordLabel, tenancy: &pbresource.Tenancy{ Partition: "*", - PeerName: "local", + }, + }, + "partitioned type with wildcard partition and namespace": { + typ: demo.TypeV1RecordLabel, + tenancy: &pbresource.Tenancy{ + Partition: "*", + Namespace: "*", + }, + }, + "cluster type with empty partition and namespace": { + typ: demo.TypeV1Executive, + tenancy: &pbresource.Tenancy{ + Partition: "", + Namespace: "", + }, + }, + + "cluster type with wildcard partition and namespace": { + typ: demo.TypeV1Executive, + tenancy: &pbresource.Tenancy{ + Partition: "*", + Namespace: "*", }, }, } @@ -232,7 +244,7 @@ func tenancyCases() map[string]func(artistId, recordlabelId *pbresource.ID) *pbr id.Tenancy.Namespace = "" return id }, - "namespaced resource inherits tokens partition and namespace when tenacy nil": func(artistId, _ *pbresource.ID) *pbresource.ID { + "namespaced resource inherits tokens partition and namespace when tenancy nil": func(artistId, _ *pbresource.ID) *pbresource.ID { id := clone(artistId) id.Tenancy = nil return id @@ -253,3 +265,26 @@ func tenancyCases() map[string]func(artistId, recordlabelId *pbresource.ID) *pbr } return tenancyCases } + +type blockOnceBackend struct { + storage.Backend + + done uint32 + readCompletedCh chan struct{} + blockCh chan struct{} +} + +func (b *blockOnceBackend) Read(ctx context.Context, consistency storage.ReadConsistency, id *pbresource.ID) (*pbresource.Resource, error) { + res, err := b.Backend.Read(ctx, consistency, id) + + // Block for exactly one call to Read. All subsequent calls (including those + // concurrent to the blocked call) will return immediately. + if atomic.CompareAndSwapUint32(&b.done, 0, 1) { + close(b.readCompletedCh) + <-b.blockCh + } + + return res, err +} + +func clone[T proto.Message](v T) T { return proto.Clone(v).(T) } diff --git a/agent/grpc-external/services/resource/testing/builder.go b/agent/grpc-external/services/resource/testing/builder.go new file mode 100644 index 000000000000..8c4209674683 --- /dev/null +++ b/agent/grpc-external/services/resource/testing/builder.go @@ -0,0 +1,153 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package testing + +import ( + "context" + + "github.com/fullstorydev/grpchan/inprocgrpc" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/acl" + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + "github.com/hashicorp/consul/agent/grpc-external/testutils" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/storage/inmem" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil" +) + +// NewResourceServiceBuilder is the preferred way to configure and run +// an isolated in-process instance of the resource service for unit +// testing. The final call to `Run()` returns a client you can use for +// making requests. +func NewResourceServiceBuilder() *Builder { + b := &Builder{ + registry: resource.NewRegistry(), + // Always make sure the builtin tenancy exists. + tenancies: []*pbresource.Tenancy{resource.DefaultNamespacedTenancy()}, + cloning: true, + } + return b +} + +// Registry provides access to the constructed registry post-Run() when +// needed by other test dependencies. +func (b *Builder) Registry() resource.Registry { + return b.registry +} + +// ServiceImpl provides access to the actual server side implementation of the resource service. This should never be +// used/accessed without good reason. The current justifying use case is to monkeypatch the ACL resolver post-creation +// to allow unfettered writes which some ACL related tests require to put test data in place. +func (b *Builder) ServiceImpl() *svc.Server { + return b.serviceImpl +} + +func (b *Builder) WithRegisterFns(registerFns ...func(resource.Registry)) *Builder { + for _, registerFn := range registerFns { + b.registerFns = append(b.registerFns, registerFn) + } + return b +} + +func (b *Builder) WithACLResolver(aclResolver svc.ACLResolver) *Builder { + b.aclResolver = aclResolver + return b +} + +// WithTenancies adds additional partitions and namespaces if default/default +// is not sufficient. +func (b *Builder) WithTenancies(tenancies ...*pbresource.Tenancy) *Builder { + for _, tenancy := range tenancies { + b.tenancies = append(b.tenancies, tenancy) + } + return b +} + +// WithCloningDisabled disables resource service client functionality that will +// clone protobuf message types as they pass through. By default +// cloning is enabled. +// +// For in-process gRPC interactions we prefer to use an in-memory gRPC client. This +// allows our controller infrastructure to avoid any unnecessary protobuf serialization +// and deserialization and for controller caching to not duplicate memory that the +// resource service is already holding on to. However, clients (including controllers) +// often want to be able to perform read-modify-write ops and for the sake of not +// forcing all call sites to be aware of the shared memory and to not touch it we +// enable cloning in the clients that we give to those bits of code. +func (b *Builder) WithCloningDisabled() *Builder { + b.cloning = false + return b +} + +// Run starts the resource service and returns a client. +func (b *Builder) Run(t testutil.TestingTB) pbresource.ResourceServiceClient { + // backend cannot be customized + backend, err := inmem.NewBackend() + require.NoError(t, err) + + // start the backend and add teardown hook + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + go backend.Run(ctx) + + for _, registerFn := range b.registerFns { + registerFn(b.registry) + } + + // use mock tenancy bridge. default/default has already been added out of the box + mockTenancyBridge := &svc.MockTenancyBridge{} + + for _, tenancy := range b.tenancies { + mockTenancyBridge.On("PartitionExists", tenancy.Partition).Return(true, nil) + mockTenancyBridge.On("NamespaceExists", tenancy.Partition, tenancy.Namespace).Return(true, nil) + mockTenancyBridge.On("IsPartitionMarkedForDeletion", tenancy.Partition).Return(false, nil) + mockTenancyBridge.On("IsNamespaceMarkedForDeletion", tenancy.Partition, tenancy.Namespace).Return(false, nil) + } + + tenancyBridge := mockTenancyBridge + + if b.aclResolver == nil { + // When not provided (regardless of V1 tenancy or V2 tenancy), configure an ACL resolver + // that has ACLs disabled and fills in "default" for the partition and namespace when + // not provided. This is similar to user initiated requests. + // + // Controllers under test should be providing full tenancy since they will run with the DANGER_NO_AUTH. + mockACLResolver := &svc.MockACLResolver{} + mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). + Return(testutils.ACLsDisabled(t), nil). + Run(func(args mock.Arguments) { + // Caller expecting passed in tokenEntMeta and authorizerContext to be filled in. + tokenEntMeta := args.Get(1).(*acl.EnterpriseMeta) + if tokenEntMeta != nil { + FillEntMeta(tokenEntMeta) + } + + authzContext := args.Get(2).(*acl.AuthorizerContext) + if authzContext != nil { + FillAuthorizerContext(authzContext) + } + }) + b.aclResolver = mockACLResolver + } + + // ent only + b.ensureLicenseManager() + + config := b.newConfig(testutil.Logger(t), backend, tenancyBridge) + + b.serviceImpl = svc.NewServer(*config) + ch := &inprocgrpc.Channel{} + pbresource.RegisterResourceServiceServer(ch, b.serviceImpl) + client := pbresource.NewResourceServiceClient(ch) + + if b.cloning { + // enable protobuf cloning wrapper + client = pbresource.NewCloningResourceServiceClient(client) + } + + return client +} diff --git a/agent/grpc-external/services/resource/testing/builder_ce.go b/agent/grpc-external/services/resource/testing/builder_ce.go new file mode 100644 index 000000000000..90954e4bfb46 --- /dev/null +++ b/agent/grpc-external/services/resource/testing/builder_ce.go @@ -0,0 +1,36 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +//go:build !consulent + +package testing + +import ( + "github.com/hashicorp/go-hclog" + + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +type Builder struct { + registry resource.Registry + registerFns []func(resource.Registry) + tenancies []*pbresource.Tenancy + aclResolver svc.ACLResolver + serviceImpl *svc.Server + cloning bool +} + +func (b *Builder) ensureLicenseManager() { +} + +func (b *Builder) newConfig(logger hclog.Logger, backend svc.Backend, tenancyBridge resource.TenancyBridge) *svc.Config { + return &svc.Config{ + Logger: logger, + Registry: b.registry, + Backend: backend, + ACLResolver: b.aclResolver, + TenancyBridge: tenancyBridge, + } +} diff --git a/agent/grpc-external/services/resource/testing/testing.go b/agent/grpc-external/services/resource/testing/testing.go index c9f03bea1a25..906953b034af 100644 --- a/agent/grpc-external/services/resource/testing/testing.go +++ b/agent/grpc-external/services/resource/testing/testing.go @@ -4,26 +4,15 @@ package testing import ( - "context" "testing" - "github.com/hashicorp/go-uuid" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" + + "github.com/hashicorp/go-uuid" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl/resolver" - svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" - "github.com/hashicorp/consul/agent/grpc-external/testutils" - internal "github.com/hashicorp/consul/agent/grpc-internal" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/storage/inmem" - "github.com/hashicorp/consul/internal/tenancy" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" ) func randomACLIdentity(t *testing.T) structs.ACLIdentity { @@ -49,112 +38,3 @@ func AuthorizerFrom(t *testing.T, policyStrs ...string) resolver.Result { ACLIdentity: randomACLIdentity(t), } } - -// RunResourceService runs a Resource Service for the duration of the test and -// returns a client to interact with it. ACLs will be disabled and only the -// default partition and namespace are available. -func RunResourceService(t *testing.T, registerFns ...func(resource.Registry)) pbresource.ResourceServiceClient { - return RunResourceServiceWithConfig(t, svc.Config{}, registerFns...) -} - -// RunResourceServiceWithConfig runs a ResourceService with caller injectable config to ease mocking dependencies. -// Any nil config field is replaced with a reasonable default with the following behavior: -// -// config.Backend - cannot be configured and must be nil -// config.Registry - empty registry -// config.TenancyBridge - mock provided with only the default partition and namespace -// config.ACLResolver - mock provided with ACLs disabled. Fills entMeta and authzContext with default partition and namespace -func RunResourceServiceWithConfig(t *testing.T, config svc.Config, registerFns ...func(resource.Registry)) pbresource.ResourceServiceClient { - t.Helper() - - if config.Backend != nil { - panic("backend can not be configured") - } - - backend, err := inmem.NewBackend() - require.NoError(t, err) - - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(cancel) - go backend.Run(ctx) - config.Backend = backend - - if config.Registry == nil { - config.Registry = resource.NewRegistry() - } - - for _, fn := range registerFns { - fn(config.Registry) - } - - server := grpc.NewServer() - - if config.TenancyBridge == nil { - mockTenancyBridge := &svc.MockTenancyBridge{} - mockTenancyBridge.On("PartitionExists", resource.DefaultPartitionName).Return(true, nil) - mockTenancyBridge.On("PartitionExists", "foo").Return(true, nil) - mockTenancyBridge.On("NamespaceExists", resource.DefaultPartitionName, resource.DefaultNamespaceName).Return(true, nil) - mockTenancyBridge.On("PartitionExists", "foo").Return(true, nil) - mockTenancyBridge.On("IsPartitionMarkedForDeletion", resource.DefaultPartitionName).Return(false, nil) - mockTenancyBridge.On("IsPartitionMarkedForDeletion", "foo").Return(false, nil) - mockTenancyBridge.On("IsNamespaceMarkedForDeletion", resource.DefaultPartitionName, resource.DefaultNamespaceName).Return(false, nil) - config.TenancyBridge = mockTenancyBridge - } else { - switch config.TenancyBridge.(type) { - case *tenancy.V2TenancyBridge: - err = initTenancy(ctx, backend) - require.NoError(t, err) - } - } - - if config.ACLResolver == nil { - // Provide a resolver which will default partition and namespace when not provided. This is similar to user - // initiated requests. - // - // Controllers under test should be providing full tenancy since they will run with the DANGER_NO_AUTH. - mockACLResolver := &svc.MockACLResolver{} - mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). - Return(testutils.ACLsDisabled(t), nil). - Run(func(args mock.Arguments) { - // Caller expecting passed in tokenEntMeta and authorizerContext to be filled in. - tokenEntMeta := args.Get(1).(*acl.EnterpriseMeta) - if tokenEntMeta != nil { - FillEntMeta(tokenEntMeta) - } - - authzContext := args.Get(2).(*acl.AuthorizerContext) - if authzContext != nil { - FillAuthorizerContext(authzContext) - } - }) - config.ACLResolver = mockACLResolver - } - - if config.Logger == nil { - config.Logger = testutil.Logger(t) - } - - svc.NewServer(config).Register(server) - - pipe := internal.NewPipeListener() - go server.Serve(pipe) - t.Cleanup(server.Stop) - - conn, err := grpc.Dial("", - grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithContextDialer(pipe.DialContext), - grpc.WithBlock(), - ) - require.NoError(t, err) - t.Cleanup(func() { _ = conn.Close() }) - client := pbresource.NewResourceServiceClient(conn) - if config.TenancyBridge != nil { - switch config.TenancyBridge.(type) { - case *tenancy.V2TenancyBridge: - config.TenancyBridge.(*tenancy.V2TenancyBridge).WithClient(client) - } - - } - - return client -} diff --git a/agent/grpc-external/services/resource/testing/testing_ce.go b/agent/grpc-external/services/resource/testing/testing_ce.go index da20be3533d4..023fa5189ccc 100644 --- a/agent/grpc-external/services/resource/testing/testing_ce.go +++ b/agent/grpc-external/services/resource/testing/testing_ce.go @@ -6,19 +6,7 @@ package testing import ( - "context" - "errors" - "time" - - "github.com/oklog/ulid/v2" - "google.golang.org/protobuf/types/known/anypb" - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/storage" - "github.com/hashicorp/consul/internal/storage/inmem" - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" ) func FillEntMeta(entMeta *acl.EnterpriseMeta) { @@ -28,38 +16,3 @@ func FillEntMeta(entMeta *acl.EnterpriseMeta) { func FillAuthorizerContext(authzContext *acl.AuthorizerContext) { // nothing to to in CE. } - -// initTenancy create the base tenancy objects (default/default) -func initTenancy(ctx context.Context, b *inmem.Backend) error { - //TODO(dhiaayachi): This is now called for testing purpose but at some point we need to add something similar - // when bootstrapping a server, probably in the tenancy controllers. - nsData, err := anypb.New(&pbtenancy.Namespace{Description: "default namespace in default partition"}) - if err != nil { - return err - } - nsID := &pbresource.ID{ - Type: pbtenancy.NamespaceType, - Name: resource.DefaultNamespaceName, - Tenancy: resource.DefaultPartitionedTenancy(), - Uid: ulid.Make().String(), - } - read, err := b.Read(ctx, storage.StrongConsistency, nsID) - if err != nil && !errors.Is(err, storage.ErrNotFound) { - return err - } - if read == nil && errors.Is(err, storage.ErrNotFound) { - _, err = b.WriteCAS(ctx, &pbresource.Resource{ - Id: nsID, - Generation: ulid.Make().String(), - Data: nsData, - Metadata: map[string]string{ - "generated_at": time.Now().Format(time.RFC3339), - }, - }) - if err != nil { - return err - } - } - return nil - -} diff --git a/agent/grpc-external/services/resource/watch.go b/agent/grpc-external/services/resource/watch.go index adabb3d256ee..246ae4e296cf 100644 --- a/agent/grpc-external/services/resource/watch.go +++ b/agent/grpc-external/services/resource/watch.go @@ -62,22 +62,41 @@ func (s *Server) WatchList(req *pbresource.WatchListRequest, stream pbresource.R return status.Errorf(codes.Internal, "failed next: %v", err) } + var resource *pbresource.Resource + switch { + case event.GetUpsert() != nil: + resource = event.GetUpsert().GetResource() + case event.GetDelete() != nil: + resource = event.GetDelete().GetResource() + case event.GetEndOfSnapshot() != nil: + // skip the rest and send the event. + if err = stream.Send(event); err != nil { + return err + } + continue + default: + // skip unknown type of operation + continue + } + + // From here on out we assume the event is operating on a non-nil resource. + // drop group versions that don't match - if event.Resource.Id.Type.GroupVersion != req.Type.GroupVersion { + if resource.Id.Type.GroupVersion != req.Type.GroupVersion { continue } // Need to rebuild authorizer per resource since wildcard inputs may // result in different tenancies. Consider caching per tenancy if this // is deemed expensive. - entMeta = v2TenancyToV1EntMeta(event.Resource.Id.Tenancy) + entMeta = v2TenancyToV1EntMeta(resource.Id.Tenancy) authz, authzContext, err = s.getAuthorizer(token, entMeta) if err != nil { return err } // filter out items that don't pass read ACLs - err = reg.ACLs.Read(authz, authzContext, event.Resource.Id, event.Resource) + err = reg.ACLs.Read(authz, authzContext, resource.Id, resource) switch { case acl.IsErrPermissionDenied(err): continue @@ -102,21 +121,21 @@ func (s *Server) ensureWatchListRequestValid(req *pbresource.WatchListRequest) ( return nil, err } + // Ignore return value since read ops are allowed but will log a warning if the feature is + // not enabled in the license. + _ = s.FeatureCheck(reg) + // if no tenancy is passed defaults to wildcard if req.Tenancy == nil { req.Tenancy = wildcardTenancyFor(reg.Scope) } - if err = checkV2Tenancy(s.UseV2Tenancy, req.Type); err != nil { - return nil, err - } - if err := validateWildcardTenancy(req.Tenancy, req.NamePrefix); err != nil { return nil, err } // Check scope - if err = validateScopedTenancy(reg.Scope, req.Type, req.Tenancy); err != nil { + if err = validateScopedTenancy(reg.Scope, req.Type, req.Tenancy, true); err != nil { return nil, err } @@ -128,18 +147,14 @@ func wildcardTenancyFor(scope resource.Scope) *pbresource.Tenancy { switch scope { case resource.ScopeCluster: - defaultTenancy = &pbresource.Tenancy{ - PeerName: storage.Wildcard, - } + defaultTenancy = &pbresource.Tenancy{} case resource.ScopePartition: defaultTenancy = &pbresource.Tenancy{ Partition: storage.Wildcard, - PeerName: storage.Wildcard, } default: defaultTenancy = &pbresource.Tenancy{ Partition: storage.Wildcard, - PeerName: storage.Wildcard, Namespace: storage.Wildcard, } } diff --git a/agent/grpc-external/services/resource/watch_test.go b/agent/grpc-external/services/resource/watch_test.go index 1c9da4b68d0d..73f164e1a999 100644 --- a/agent/grpc-external/services/resource/watch_test.go +++ b/agent/grpc-external/services/resource/watch_test.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package resource +package resource_test import ( "context" @@ -11,24 +11,26 @@ import ( "testing" "time" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/acl/resolver" + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" "github.com/hashicorp/consul/agent/grpc-external/testutils" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/proto/private/prototest" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" ) func TestWatchList_InputValidation(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) type testCase struct { modFn func(*pbresource.WatchListRequest) @@ -108,8 +110,7 @@ func TestWatchList_InputValidation(t *testing.T) { func TestWatchList_TypeNotFound(t *testing.T) { t.Parallel() - server := testServer(t) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder().Run(t) stream, err := client.WatchList(context.Background(), &pbresource.WatchListRequest{ Type: demo.TypeV2Artist, @@ -127,9 +128,10 @@ func TestWatchList_TypeNotFound(t *testing.T) { func TestWatchList_GroupVersionMatches(t *testing.T) { t.Parallel() - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + b := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes) + client := b.Run(t) + ctx := context.Background() // create a watch @@ -141,29 +143,34 @@ func TestWatchList_GroupVersionMatches(t *testing.T) { require.NoError(t, err) rspCh := handleResourceStream(t, stream) + mustGetEndOfSnapshot(t, rspCh) + artist, err := demo.GenerateV2Artist() require.NoError(t, err) // insert and verify upsert event received - r1, err := server.Backend.WriteCAS(ctx, artist) + r1Resp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: artist}) + r1 := r1Resp.Resource require.NoError(t, err) rsp := mustGetResource(t, rspCh) - require.Equal(t, pbresource.WatchEvent_OPERATION_UPSERT, rsp.Operation) - prototest.AssertDeepEqual(t, r1, rsp.Resource) + require.NotNil(t, rsp.GetUpsert()) + prototest.AssertDeepEqual(t, r1, rsp.GetUpsert().Resource) // update and verify upsert event received r2 := modifyArtist(t, r1) - r2, err = server.Backend.WriteCAS(ctx, r2) + r2Resp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: r2}) require.NoError(t, err) + r2 = r2Resp.Resource rsp = mustGetResource(t, rspCh) - require.Equal(t, pbresource.WatchEvent_OPERATION_UPSERT, rsp.Operation) - prototest.AssertDeepEqual(t, r2, rsp.Resource) + require.NotNil(t, rsp.GetUpsert()) + prototest.AssertDeepEqual(t, r2, rsp.GetUpsert().Resource) // delete and verify delete event received - err = server.Backend.DeleteCAS(ctx, r2.Id, r2.Version) + _, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: r2.Id, Version: r2.Version}) require.NoError(t, err) rsp = mustGetResource(t, rspCh) - require.Equal(t, pbresource.WatchEvent_OPERATION_DELETE, rsp.Operation) + require.NotNil(t, rsp.GetDelete()) + prototest.AssertDeepEqual(t, r2.Id, rsp.GetDelete().Resource.Id) } func TestWatchList_Tenancy_Defaults_And_Normalization(t *testing.T) { @@ -171,9 +178,9 @@ func TestWatchList_Tenancy_Defaults_And_Normalization(t *testing.T) { for desc, tc := range wildcardTenancyCases() { t.Run(desc, func(t *testing.T) { ctx := context.Background() - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) // Create a watch. stream, err := client.WatchList(ctx, &pbresource.WatchListRequest{ @@ -184,33 +191,40 @@ func TestWatchList_Tenancy_Defaults_And_Normalization(t *testing.T) { require.NoError(t, err) rspCh := handleResourceStream(t, stream) - // Testcase will pick one of recordLabel or artist based on scope of type. + mustGetEndOfSnapshot(t, rspCh) + + // Testcase will pick one of executive, recordLabel or artist based on scope of type. recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") require.NoError(t, err) artist, err := demo.GenerateV2Artist() require.NoError(t, err) + executive, err := demo.GenerateV1Executive("king-arthur", "CEO") + require.NoError(t, err) // Create and verify upsert event received. - recordLabel, err = server.Backend.WriteCAS(ctx, recordLabel) + rlRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: recordLabel}) require.NoError(t, err) - artist, err = server.Backend.WriteCAS(ctx, artist) + artistRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: artist}) + require.NoError(t, err) + executiveRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: executive}) require.NoError(t, err) var expected *pbresource.Resource switch { - case proto.Equal(tc.typ, demo.TypeV1RecordLabel): - expected = recordLabel - case proto.Equal(tc.typ, demo.TypeV2Artist): - expected = artist + case resource.EqualType(tc.typ, demo.TypeV1RecordLabel): + expected = rlRsp.Resource + case resource.EqualType(tc.typ, demo.TypeV2Artist): + expected = artistRsp.Resource + case resource.EqualType(tc.typ, demo.TypeV1Executive): + expected = executiveRsp.Resource default: require.Fail(t, "unsupported type", tc.typ) } rsp := mustGetResource(t, rspCh) - require.Equal(t, pbresource.WatchEvent_OPERATION_UPSERT, rsp.Operation) - prototest.AssertDeepEqual(t, expected, rsp.Resource) + require.NotNil(t, rsp.GetUpsert()) + prototest.AssertDeepEqual(t, expected, rsp.GetUpsert().Resource) }) - } } @@ -220,9 +234,10 @@ func TestWatchList_GroupVersionMismatch(t *testing.T) { // Then no watch events should be emitted t.Parallel() - server := testServer(t) - demo.RegisterTypes(server.Registry) - client := testClient(t, server) + b := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes) + client := b.Run(t) + ctx := context.Background() // create a watch for TypeArtistV1 @@ -234,20 +249,24 @@ func TestWatchList_GroupVersionMismatch(t *testing.T) { require.NoError(t, err) rspCh := handleResourceStream(t, stream) + mustGetEndOfSnapshot(t, rspCh) + artist, err := demo.GenerateV2Artist() require.NoError(t, err) // insert - r1, err := server.Backend.WriteCAS(ctx, artist) + r1Resp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: artist}) require.NoError(t, err) + r1 := r1Resp.Resource // update r2 := clone(r1) - r2, err = server.Backend.WriteCAS(ctx, r2) + r2Resp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: r2}) require.NoError(t, err) + r2 = r2Resp.Resource // delete - err = server.Backend.DeleteCAS(ctx, r2.Id, r2.Version) + _, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: r2.Id, Version: r2.Version}) require.NoError(t, err) // verify no events received @@ -259,7 +278,7 @@ func TestWatchList_ACL_ListDenied(t *testing.T) { t.Parallel() // deny all - rspCh, _ := roundTripACL(t, testutils.ACLNoPermissions(t)) + rspCh, _ := roundTripACL(t, testutils.ACLNoPermissions(t), true) // verify key:list denied err := mustGetError(t, rspCh) @@ -277,7 +296,7 @@ func TestWatchList_ACL_ListAllowed_ReadDenied(t *testing.T) { key_prefix "resource/" { policy = "list" } key_prefix "resource/demo.v2.Artist/" { policy = "deny" } `) - rspCh, _ := roundTripACL(t, authz) + rspCh, _ := roundTripACL(t, authz, false) // verify resource filtered out by key:read denied, hence no events mustGetNoResource(t, rspCh) @@ -292,23 +311,26 @@ func TestWatchList_ACL_ListAllowed_ReadAllowed(t *testing.T) { key_prefix "resource/" { policy = "list" } key_prefix "resource/demo.v2.Artist/" { policy = "read" } `) - rspCh, artist := roundTripACL(t, authz) + rspCh, artist := roundTripACL(t, authz, false) // verify resource not filtered out by acl event := mustGetResource(t, rspCh) - prototest.AssertDeepEqual(t, artist, event.Resource) + + require.NotNil(t, event.GetUpsert()) + prototest.AssertDeepEqual(t, artist, event.GetUpsert().Resource) } // roundtrip a WatchList which attempts to stream back a single write event -func roundTripACL(t *testing.T, authz acl.Authorizer) (<-chan resourceOrError, *pbresource.Resource) { - server := testServer(t) - client := testClient(t, server) - - mockACLResolver := &MockACLResolver{} +func roundTripACL(t *testing.T, authz acl.Authorizer, expectErr bool) (<-chan resourceOrError, *pbresource.Resource) { + mockACLResolver := &svc.MockACLResolver{} mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). - Return(authz, nil) - server.ACLResolver = mockACLResolver - demo.RegisterTypes(server.Registry) + Return(resolver.Result{Authorizer: authz}, nil) + + b := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + WithACLResolver(mockACLResolver) + client := b.Run(t) + server := b.ServiceImpl() artist, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -321,6 +343,10 @@ func roundTripACL(t *testing.T, authz acl.Authorizer) (<-chan resourceOrError, * require.NoError(t, err) rspCh := handleResourceStream(t, stream) + if !expectErr { + mustGetEndOfSnapshot(t, rspCh) + } + // induce single watch event artist, err = server.Backend.WriteCAS(context.Background(), artist) require.NoError(t, err) @@ -341,6 +367,11 @@ func mustGetNoResource(t *testing.T, ch <-chan resourceOrError) { } } +func mustGetEndOfSnapshot(t *testing.T, ch <-chan resourceOrError) { + event := mustGetResource(t, ch) + require.NotNil(t, event.GetEndOfSnapshot(), "expected EndOfSnapshot but got got event %T", event.GetEvent()) +} + func mustGetResource(t *testing.T, ch <-chan resourceOrError) *pbresource.WatchEvent { t.Helper() @@ -395,10 +426,11 @@ type resourceOrError struct { func TestWatchList_NoTenancy(t *testing.T) { t.Parallel() + ctx := context.Background() - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) // Create a watch. stream, err := client.WatchList(ctx, &pbresource.WatchListRequest{ @@ -407,15 +439,17 @@ func TestWatchList_NoTenancy(t *testing.T) { require.NoError(t, err) rspCh := handleResourceStream(t, stream) + mustGetEndOfSnapshot(t, rspCh) + recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") require.NoError(t, err) // Create and verify upsert event received. - recordLabel, err = server.Backend.WriteCAS(ctx, recordLabel) + rsp1, err := client.Write(ctx, &pbresource.WriteRequest{Resource: recordLabel}) require.NoError(t, err) - rsp := mustGetResource(t, rspCh) + rsp2 := mustGetResource(t, rspCh) - require.Equal(t, pbresource.WatchEvent_OPERATION_UPSERT, rsp.Operation) - prototest.AssertDeepEqual(t, recordLabel, rsp.Resource) + require.NotNil(t, rsp2.GetUpsert()) + prototest.AssertDeepEqual(t, rsp1.Resource, rsp2.GetUpsert().Resource) } diff --git a/agent/grpc-external/services/resource/write.go b/agent/grpc-external/services/resource/write.go index 63c87f11a18a..99341b9ba52b 100644 --- a/agent/grpc-external/services/resource/write.go +++ b/agent/grpc-external/services/resource/write.go @@ -6,17 +6,15 @@ package resource import ( "context" "errors" - "strings" - "time" "github.com/oklog/ulid/v2" + "golang.org/x/exp/maps" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" - "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/storage" - "github.com/hashicorp/consul/lib/retry" "github.com/hashicorp/consul/proto-public/pbresource" ) @@ -37,57 +35,11 @@ import ( var errUseWriteStatus = status.Error(codes.InvalidArgument, "resource.status can only be set using the WriteStatus endpoint") func (s *Server) Write(ctx context.Context, req *pbresource.WriteRequest) (*pbresource.WriteResponse, error) { - reg, err := s.ensureWriteRequestValid(req) + tenancyMarkedForDeletion, err := s.mutateAndValidate(ctx, req.Resource, true) if err != nil { return nil, err } - v1EntMeta := v2TenancyToV1EntMeta(req.Resource.Id.Tenancy) - authz, authzContext, err := s.getAuthorizer(tokenFromContext(ctx), v1EntMeta) - if err != nil { - return nil, err - } - v1EntMetaToV2Tenancy(reg, v1EntMeta, req.Resource.Id.Tenancy) - - // Check the user sent the correct type of data. - if req.Resource.Data != nil && !req.Resource.Data.MessageIs(reg.Proto) { - got := strings.TrimPrefix(req.Resource.Data.TypeUrl, "type.googleapis.com/") - - return nil, status.Errorf( - codes.InvalidArgument, - "resource.data is of wrong type (expected=%q, got=%q)", - reg.Proto.ProtoReflect().Descriptor().FullName(), - got, - ) - } - - if err = reg.Mutate(req.Resource); err != nil { - return nil, status.Errorf(codes.Internal, "failed mutate hook: %v", err.Error()) - } - - if err = reg.Validate(req.Resource); err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - - // ACL check comes before tenancy existence checks to not leak tenancy "existence". - err = reg.ACLs.Write(authz, authzContext, req.Resource) - switch { - case acl.IsErrPermissionDenied(err): - return nil, status.Error(codes.PermissionDenied, err.Error()) - case err != nil: - return nil, status.Errorf(codes.Internal, "failed write acl: %v", err) - } - - // Check tenancy exists for the V2 resource - if err = tenancyExists(reg, s.TenancyBridge, req.Resource.Id.Tenancy, codes.InvalidArgument); err != nil { - return nil, err - } - - // Check tenancy not marked for deletion. - if err = tenancyMarkedForDeletion(reg, s.TenancyBridge, req.Resource.Id.Tenancy); err != nil { - return nil, err - } - // At the storage backend layer, all writes are CAS operations. // // This makes it possible to *safely* do things like keeping the Uid stable @@ -127,6 +79,16 @@ func (s *Server) Write(ctx context.Context, req *pbresource.WriteRequest) (*pbre return errUseWriteStatus } + // Reject creation in tenancy unit marked for deletion. + if tenancyMarkedForDeletion { + return status.Errorf(codes.InvalidArgument, "tenancy marked for deletion: %v", input.Id.Tenancy.String()) + } + + // Reject attempts to create a resource with a deletionTimestamp. + if resource.IsMarkedForDeletion(input) { + return status.Errorf(codes.InvalidArgument, "resource.metadata.%s can't be set on resource creation", resource.DeletionTimestampKey) + } + // Generally, we expect resources with owners to be created by controllers, // and they should provide the Uid. In cases where no Uid is given (e.g. the // owner is specified in the resource HCL) we'll look up whatever the current @@ -168,9 +130,11 @@ func (s *Server) Write(ctx context.Context, req *pbresource.WriteRequest) (*pbre // just want to update the current resource. input.Id = existing.Id - // User is doing a non-CAS write, use the current version. + // User is doing a non-CAS write, use the current version and preserve + // deferred deletion metadata if not present. if input.Version == "" { input.Version = existing.Version + preserveDeferredDeletionMetadata(input, existing) } // Check the stored version matches the user-given version. @@ -208,6 +172,13 @@ func (s *Server) Write(ctx context.Context, req *pbresource.WriteRequest) (*pbre return errUseWriteStatus } + // If the write is related to a deferred deletion (marking for deletion or removal + // of finalizers), make sure nothing else is changed. + if err := vetIfDeleteRelated(input, existing, tenancyMarkedForDeletion); err != nil { + return err + } + + // Otherwise, let the write continue default: return err } @@ -230,83 +201,139 @@ func (s *Server) Write(ctx context.Context, req *pbresource.WriteRequest) (*pbre return &pbresource.WriteResponse{Resource: result}, nil } -// retryCAS retries the given operation with exponential backoff if the user -// didn't provide a version. This is intended to hide failures when the user -// isn't intentionally performing a CAS operation (all writes are, by design, -// CAS operations at the storage backend layer). -func (s *Server) retryCAS(ctx context.Context, vsn string, cas func() error) error { - if vsn != "" { - return cas() +func ensureMetadataSameExceptFor(input *pbresource.Resource, existing *pbresource.Resource, ignoreKey string) error { + // Work on copies since we're mutating them + inputCopy := maps.Clone(input.Metadata) + existingCopy := maps.Clone(existing.Metadata) + + delete(inputCopy, ignoreKey) + delete(existingCopy, ignoreKey) + + if !maps.Equal(inputCopy, existingCopy) { + return status.Error(codes.InvalidArgument, "cannot modify metadata") } - const maxAttempts = 5 - - // These parameters are fairly arbitrary, so if you find better ones then go - // ahead and swap them out! In general, we want to wait long enough to smooth - // over small amounts of storage replication lag, but not so long that we make - // matters worse by holding onto load. - backoff := &retry.Waiter{ - MinWait: 50 * time.Millisecond, - MaxWait: 1 * time.Second, - Jitter: retry.NewJitter(50), - Factor: 75 * time.Millisecond, + return nil +} + +func ensureDataUnchanged(input *pbresource.Resource, existing *pbresource.Resource) error { + // Check data last since this could potentially be the most expensive comparison. + if !proto.Equal(input.Data, existing.Data) { + return status.Error(codes.InvalidArgument, "cannot modify data") } + return nil +} - var err error - for i := 1; i <= maxAttempts; i++ { - if err = cas(); !errors.Is(err, storage.ErrCASFailure) { - break - } - if backoff.Wait(ctx) != nil { - break - } - s.Logger.Trace("retrying failed CAS operation", "failure_count", i) +// EnsureFinalizerRemoved ensures at least one finalizer was removed. +// TODO: only public for test to access +func EnsureFinalizerRemoved(input *pbresource.Resource, existing *pbresource.Resource) error { + inputFinalizers := resource.GetFinalizers(input) + existingFinalizers := resource.GetFinalizers(existing) + if !inputFinalizers.IsProperSubset(existingFinalizers) { + return status.Error(codes.InvalidArgument, "expected at least one finalizer to be removed") } - return err + return nil } -func (s *Server) ensureWriteRequestValid(req *pbresource.WriteRequest) (*resource.Registration, error) { - var field string - switch { - case req.Resource == nil: - field = "resource" - case req.Resource.Id == nil: - field = "resource.id" +func vetIfDeleteRelated(input, existing *pbresource.Resource, tenancyMarkedForDeletion bool) error { + // Keep track of whether this write is a normal write or a write that is related + // to deferred resource deletion involving setting the deletionTimestamp or the + // removal of finalizers. + deleteRelated := false + + existingMarked := resource.IsMarkedForDeletion(existing) + inputMarked := resource.IsMarkedForDeletion(input) + + // Block removal of deletion timestamp + if !inputMarked && existingMarked { + return status.Errorf(codes.InvalidArgument, "cannot remove %s", resource.DeletionTimestampKey) } - if field != "" { - return nil, status.Errorf(codes.InvalidArgument, "%s is required", field) + // Block modification of existing deletion timestamp + if existing.Metadata[resource.DeletionTimestampKey] != "" && (existing.Metadata[resource.DeletionTimestampKey] != input.Metadata[resource.DeletionTimestampKey]) { + return status.Errorf(codes.InvalidArgument, "cannot modify %s", resource.DeletionTimestampKey) } - if err := validateId(req.Resource.Id, "resource.id"); err != nil { - return nil, err + // Block writes that do more than just adding a deletion timestamp + if inputMarked && !existingMarked { + deleteRelated = deleteRelated || true + // Verify rest of resource is unchanged + if err := ensureMetadataSameExceptFor(input, existing, resource.DeletionTimestampKey); err != nil { + return err + } + if err := ensureDataUnchanged(input, existing); err != nil { + return err + } } - if req.Resource.Owner != nil { - if err := validateId(req.Resource.Owner, "resource.owner"); err != nil { - return nil, err + // Block no-op writes writes to resource that already has a deletion timestamp. The + // only valid writes should be removal of finalizers. + if inputMarked && existingMarked { + deleteRelated = deleteRelated || true + // Check if a no-op + errMetadataSame := ensureMetadataSameExceptFor(input, existing, resource.DeletionTimestampKey) + errDataUnchanged := ensureDataUnchanged(input, existing) + if errMetadataSame == nil && errDataUnchanged == nil { + return status.Error(codes.InvalidArgument, "cannot no-op write resource marked for deletion") } } - // Check type exists. - reg, err := s.resolveType(req.Resource.Id.Type) - if err != nil { - return nil, err + // Block writes that do more than removing finalizers if previously marked for deletion. + if inputMarked && existingMarked && resource.HasFinalizers(existing) { + deleteRelated = deleteRelated || true + if err := ensureMetadataSameExceptFor(input, existing, resource.FinalizerKey); err != nil { + return err + } + if err := ensureDataUnchanged(input, existing); err != nil { + return err + } + if err := EnsureFinalizerRemoved(input, existing); err != nil { + return err + } } - if err = checkV2Tenancy(s.UseV2Tenancy, req.Resource.Id.Type); err != nil { - return nil, err + // Classify writes that just remove finalizer as deleteRelated regardless of deletion state. + if err := EnsureFinalizerRemoved(input, existing); err == nil { + if err := ensureDataUnchanged(input, existing); err == nil { + deleteRelated = deleteRelated || true + } } - // Check scope - if reg.Scope == resource.ScopePartition && req.Resource.Id.Tenancy.Namespace != "" { - return nil, status.Errorf( - codes.InvalidArgument, - "partition scoped resource %s cannot have a namespace. got: %s", - resource.ToGVK(req.Resource.Id.Type), - req.Resource.Id.Tenancy.Namespace, - ) + // Lastly, block writes when the resource's tenancy unit has been marked for deletion and + // the write is not related a valid delete scenario. + if tenancyMarkedForDeletion && !deleteRelated { + return status.Errorf(codes.InvalidArgument, "cannot write resource when tenancy marked for deletion: %s", existing.Id.Tenancy) } - return reg, nil + return nil +} + +// preserveDeferredDeletionMetadata only applies to user writes (Version == "") which is a precondition. +func preserveDeferredDeletionMetadata(input, existing *pbresource.Resource) { + // preserve existing deletionTimestamp if not provided in input + if !resource.IsMarkedForDeletion(input) && resource.IsMarkedForDeletion(existing) { + if input.Metadata == nil { + input.Metadata = make(map[string]string) + } + input.Metadata[resource.DeletionTimestampKey] = existing.Metadata[resource.DeletionTimestampKey] + } + + // Only preserve finalizers if the is key absent from input and present in existing. + // If the key is present in input, the user clearly wants to remove finalizers! + inputHasKey := false + if input.Metadata != nil { + _, inputHasKey = input.Metadata[resource.FinalizerKey] + } + + existingHasKey := false + if existing.Metadata != nil { + _, existingHasKey = existing.Metadata[resource.FinalizerKey] + } + + if !inputHasKey && existingHasKey { + if input.Metadata == nil { + input.Metadata = make(map[string]string) + } + input.Metadata[resource.FinalizerKey] = existing.Metadata[resource.FinalizerKey] + } } diff --git a/agent/grpc-external/services/resource/write_mav_common_test.go b/agent/grpc-external/services/resource/write_mav_common_test.go new file mode 100644 index 000000000000..6b6a82b44e9f --- /dev/null +++ b/agent/grpc-external/services/resource/write_mav_common_test.go @@ -0,0 +1,314 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package resource_test + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/protobuf/types/known/anypb" + + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" + pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2" +) + +// Common test structs and test cases shared by the Write and MutateAndValidate RPCs +// only. These are not intended to be used by other tests. + +type resourceValidTestCase struct { + modFn func(artist, recordLabel *pbresource.Resource) *pbresource.Resource + errContains string +} + +func resourceValidTestCases(t *testing.T) map[string]resourceValidTestCase { + return map[string]resourceValidTestCase{ + "no resource": { + modFn: func(_, _ *pbresource.Resource) *pbresource.Resource { + return nil + }, + errContains: "resource is required", + }, + "no id": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id = nil + return artist + }, + errContains: "resource.id is required", + }, + "no type": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Type = nil + return artist + }, + errContains: "resource.id.type is required", + }, + "no name": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Name = "" + return artist + }, + errContains: "resource.id.name invalid", + }, + "name is mixed case": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Name = "MixedCaseNotAllowed" + return artist + }, + errContains: "resource.id.name invalid", + }, + "name too long": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Name = strings.Repeat("a", resource.MaxNameLength+1) + return artist + }, + errContains: "resource.id.name invalid", + }, + "wrong data type": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + var err error + artist.Data, err = anypb.New(&pbdemov2.Album{}) + require.NoError(t, err) + return artist + }, + errContains: "resource.data is of wrong type", + }, + "partition is mixed case": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Tenancy.Partition = "Default" + return artist + }, + errContains: "resource.id.tenancy.partition invalid", + }, + "partition too long": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) + return artist + }, + errContains: "resource.id.tenancy.partition invalid", + }, + "namespace is mixed case": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Tenancy.Namespace = "Default" + return artist + }, + errContains: "resource.id.tenancy.namespace invalid", + }, + "namespace too long": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) + return artist + }, + errContains: "resource.id.tenancy.namespace invalid", + }, + "fail validation hook": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + buffer := &pbdemov2.Artist{} + require.NoError(t, artist.Data.UnmarshalTo(buffer)) + buffer.Name = "" // name cannot be empty + require.NoError(t, artist.Data.MarshalFrom(buffer)) + return artist + }, + errContains: "artist.name required", + }, + "partition scope with non-empty namespace": { + modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { + recordLabel.Id.Tenancy.Namespace = "bogus" + return recordLabel + }, + errContains: "cannot have a namespace", + }, + } +} + +type ownerValidTestCase struct { + modFn func(res *pbresource.Resource) + errorContains string +} + +func ownerValidationTestCases(t *testing.T) map[string]ownerValidTestCase { + return map[string]ownerValidTestCase{ + "no owner type": { + modFn: func(res *pbresource.Resource) { res.Owner.Type = nil }, + errorContains: "resource.owner.type is required", + }, + "no owner name": { + modFn: func(res *pbresource.Resource) { res.Owner.Name = "" }, + errorContains: "resource.owner.name invalid", + }, + "mixed case owner name": { + modFn: func(res *pbresource.Resource) { res.Owner.Name = strings.ToUpper(res.Owner.Name) }, + errorContains: "resource.owner.name invalid", + }, + "owner name too long": { + modFn: func(res *pbresource.Resource) { + res.Owner.Name = strings.Repeat("a", resource.MaxNameLength+1) + }, + errorContains: "resource.owner.name invalid", + }, + "owner partition is mixed case": { + modFn: func(res *pbresource.Resource) { + res.Owner.Tenancy.Partition = "Default" + }, + errorContains: "resource.owner.tenancy.partition invalid", + }, + "owner partition too long": { + modFn: func(res *pbresource.Resource) { + res.Owner.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) + }, + errorContains: "resource.owner.tenancy.partition invalid", + }, + "owner namespace is mixed case": { + modFn: func(res *pbresource.Resource) { + res.Owner.Tenancy.Namespace = "Default" + }, + errorContains: "resource.owner.tenancy.namespace invalid", + }, + "owner namespace too long": { + modFn: func(res *pbresource.Resource) { + res.Owner.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) + }, + errorContains: "resource.owner.tenancy.namespace invalid", + }, + } +} + +// Test case struct shared by MutateAndValidate and Write success test cases +type mavOrWriteSuccessTestCase struct { + modFn func(artist, recordLabel *pbresource.Resource) *pbresource.Resource + expectedTenancy *pbresource.Tenancy +} + +// Test case struct shared by MutateAndValidate and Write success test cases +func mavOrWriteSuccessTestCases(t *testing.T) map[string]mavOrWriteSuccessTestCase { + return map[string]mavOrWriteSuccessTestCase{ + "namespaced resource provides nonempty partition and namespace": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + return artist + }, + expectedTenancy: resource.DefaultNamespacedTenancy(), + }, + "namespaced resource inherits tokens partition when empty": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Tenancy.Partition = "" + return artist + }, + expectedTenancy: resource.DefaultNamespacedTenancy(), + }, + "namespaced resource inherits tokens namespace when empty": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Tenancy.Namespace = "" + return artist + }, + expectedTenancy: resource.DefaultNamespacedTenancy(), + }, + "namespaced resource inherits tokens partition and namespace when empty": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Tenancy.Partition = "" + artist.Id.Tenancy.Namespace = "" + return artist + }, + expectedTenancy: resource.DefaultNamespacedTenancy(), + }, + "namespaced resource inherits tokens partition and namespace when tenancy nil": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Tenancy = nil + return artist + }, + expectedTenancy: resource.DefaultNamespacedTenancy(), + }, + "partitioned resource provides nonempty partition": { + modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { + return recordLabel + }, + expectedTenancy: resource.DefaultPartitionedTenancy(), + }, + "partitioned resource inherits tokens partition when empty": { + modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { + recordLabel.Id.Tenancy.Partition = "" + return recordLabel + }, + expectedTenancy: resource.DefaultPartitionedTenancy(), + }, + "partitioned resource inherits tokens partition when tenancy nil": { + modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { + recordLabel.Id.Tenancy = nil + return recordLabel + }, + expectedTenancy: resource.DefaultPartitionedTenancy(), + }, + } +} + +// Test case struct shared by MutateAndValidate and Write test cases where tenancy is not found +type mavOrWriteTenancyNotFoundTestCase map[string]struct { + modFn func(artist, recordLabel *pbresource.Resource) *pbresource.Resource + errCode codes.Code + errContains string +} + +// Test case struct shared by MutateAndValidate and Write test cases where tenancy is not found +func mavOrWriteTenancyNotFoundTestCases(t *testing.T) mavOrWriteTenancyNotFoundTestCase { + return mavOrWriteTenancyNotFoundTestCase{ + "namespaced resource provides nonexistant partition": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Tenancy.Partition = "boguspartition" + return artist + }, + errCode: codes.InvalidArgument, + errContains: "partition not found", + }, + "namespaced resource provides nonexistant namespace": { + modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { + artist.Id.Tenancy.Namespace = "bogusnamespace" + return artist + }, + errCode: codes.InvalidArgument, + errContains: "namespace not found", + }, + "partitioned resource provides nonexistant partition": { + modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { + recordLabel.Id.Tenancy.Partition = "boguspartition" + return recordLabel + }, + errCode: codes.InvalidArgument, + errContains: "partition not found", + }, + } +} + +type mavOrWriteTenancyMarkedForDeletionTestCase struct { + modFn func(artist, recordLabel *pbresource.Resource, mockTenancyBridge *svc.MockTenancyBridge) *pbresource.Resource + errContains string +} + +func mavOrWriteTenancyMarkedForDeletionTestCases(t *testing.T) map[string]mavOrWriteTenancyMarkedForDeletionTestCase { + return map[string]mavOrWriteTenancyMarkedForDeletionTestCase{ + "namespaced resources partition marked for deletion": { + modFn: func(artist, _ *pbresource.Resource, mockTenancyBridge *svc.MockTenancyBridge) *pbresource.Resource { + mockTenancyBridge.On("IsPartitionMarkedForDeletion", "ap1").Return(true, nil) + return artist + }, + errContains: "tenancy marked for deletion", + }, + "namespaced resources namespace marked for deletion": { + modFn: func(artist, _ *pbresource.Resource, mockTenancyBridge *svc.MockTenancyBridge) *pbresource.Resource { + mockTenancyBridge.On("IsPartitionMarkedForDeletion", "ap1").Return(false, nil) + mockTenancyBridge.On("IsNamespaceMarkedForDeletion", "ap1", "ns1").Return(true, nil) + return artist + }, + errContains: "tenancy marked for deletion", + }, + "partitioned resources partition marked for deletion": { + modFn: func(_, recordLabel *pbresource.Resource, mockTenancyBridge *svc.MockTenancyBridge) *pbresource.Resource { + mockTenancyBridge.On("IsPartitionMarkedForDeletion", "ap1").Return(true, nil) + return recordLabel + }, + errContains: "tenancy marked for deletion", + }, + } +} diff --git a/agent/grpc-external/services/resource/write_status.go b/agent/grpc-external/services/resource/write_status.go index 7009a7fd72bb..fc209cd91252 100644 --- a/agent/grpc-external/services/resource/write_status.go +++ b/agent/grpc-external/services/resource/write_status.go @@ -173,8 +173,6 @@ func (s *Server) validateWriteStatusRequest(req *pbresource.WriteStatusRequest) req.Id.Tenancy = &pbresource.Tenancy{ Partition: "", Namespace: "", - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - PeerName: "local", } } diff --git a/agent/grpc-external/services/resource/write_status_test.go b/agent/grpc-external/services/resource/write_status_test.go index 1ddf73863236..4c524430251b 100644 --- a/agent/grpc-external/services/resource/write_status_test.go +++ b/agent/grpc-external/services/resource/write_status_test.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package resource +package resource_test import ( "fmt" @@ -16,6 +16,8 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "github.com/hashicorp/consul/acl/resolver" + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/proto-public/pbresource" @@ -44,9 +46,8 @@ func TestWriteStatus_ACL(t *testing.T) { for desc, tc := range testcases { t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + builder := svctest.NewResourceServiceBuilder().WithRegisterFns(demo.RegisterTypes) + client := builder.Run(t) artist, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -56,10 +57,10 @@ func TestWriteStatus_ACL(t *testing.T) { artist = rsp.Resource // Defer mocking out authz since above write is necessary to set up the test resource. - mockACLResolver := &MockACLResolver{} + mockACLResolver := &svc.MockACLResolver{} mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). Return(tc.authz, nil) - server.ACLResolver = mockACLResolver + builder.ServiceImpl().Config.ACLResolver = mockACLResolver // exercise ACL _, err = client.WriteStatus(testContext(t), validWriteStatusRequest(t, artist)) @@ -69,9 +70,9 @@ func TestWriteStatus_ACL(t *testing.T) { } func TestWriteStatus_InputValidation(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) testCases := map[string]struct { typ *pbresource.Type @@ -259,9 +260,9 @@ func TestWriteStatus_Success(t *testing.T) { "Non CAS": func(req *pbresource.WriteStatusRequest) { req.Version = "" }, } { t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -331,9 +332,9 @@ func TestWriteStatus_Tenancy_Defaults(t *testing.T) { }, } { t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) // Pick resource based on scope of type in testcase. var res *pbresource.Resource @@ -368,70 +369,10 @@ func TestWriteStatus_Tenancy_Defaults(t *testing.T) { } } -func TestWriteStatus_Tenancy_NotFound(t *testing.T) { - for desc, tc := range map[string]struct { - scope resource.Scope - modFn func(req *pbresource.WriteStatusRequest) - errCode codes.Code - errContains string - }{ - "namespaced resource provides nonexistant partition": { - scope: resource.ScopeNamespace, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Partition = "bad" }, - errCode: codes.InvalidArgument, - errContains: "partition", - }, - "namespaced resource provides nonexistant namespace": { - scope: resource.ScopeNamespace, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Namespace = "bad" }, - errCode: codes.InvalidArgument, - errContains: "namespace", - }, - "partitioned resource provides nonexistant partition": { - scope: resource.ScopePartition, - modFn: func(req *pbresource.WriteStatusRequest) { req.Id.Tenancy.Partition = "bad" }, - errCode: codes.InvalidArgument, - errContains: "partition", - }, - } { - t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) - - // Pick resource based on scope of type in testcase. - var res *pbresource.Resource - var err error - switch tc.scope { - case resource.ScopeNamespace: - res, err = demo.GenerateV2Artist() - case resource.ScopePartition: - res, err = demo.GenerateV1RecordLabel("looney-tunes") - } - require.NoError(t, err) - - // Fill in required fields so validation continues until tenancy is checked - req := validWriteStatusRequest(t, res) - req.Id.Uid = ulid.Make().String() - req.Status.ObservedGeneration = ulid.Make().String() - - // Write status with tenancy modded by testcase. - tc.modFn(req) - _, err = client.WriteStatus(testContext(t), req) - - // Verify non-existant tenancy field is the cause of the error. - require.Error(t, err) - require.Equal(t, tc.errCode.String(), status.Code(err).String()) - require.Contains(t, err.Error(), tc.errContains) - }) - } -} - func TestWriteStatus_CASFailure(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -449,8 +390,7 @@ func TestWriteStatus_CASFailure(t *testing.T) { } func TestWriteStatus_TypeNotFound(t *testing.T) { - server := testServer(t) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder().Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -464,9 +404,9 @@ func TestWriteStatus_TypeNotFound(t *testing.T) { } func TestWriteStatus_ResourceNotFound(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -479,9 +419,9 @@ func TestWriteStatus_ResourceNotFound(t *testing.T) { } func TestWriteStatus_WrongUid(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -516,8 +456,8 @@ func TestWriteStatus_NonCASUpdate_Retry(t *testing.T) { backend := &blockOnceBackend{ Backend: server.Backend, - readCh: make(chan struct{}), - blockCh: make(chan struct{}), + readCompletedCh: make(chan struct{}), + blockCh: make(chan struct{}), } server.Backend = backend @@ -532,7 +472,7 @@ func TestWriteStatus_NonCASUpdate_Retry(t *testing.T) { // Wait for the read, to ensure the Write in the goroutine above has read the // current version of the resource. - <-backend.readCh + <-backend.readCompletedCh // Update the resource. _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: modifyArtist(t, res)}) diff --git a/agent/grpc-external/services/resource/write_test.go b/agent/grpc-external/services/resource/write_test.go index 9f7704b52b97..c14aaad0e1eb 100644 --- a/agent/grpc-external/services/resource/write_test.go +++ b/agent/grpc-external/services/resource/write_test.go @@ -1,12 +1,9 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package resource +package resource_test import ( - "context" - "strings" - "sync/atomic" "testing" "github.com/oklog/ulid/v2" @@ -14,12 +11,13 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "google.golang.org/protobuf/types/known/anypb" "github.com/hashicorp/consul/acl/resolver" + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" - "github.com/hashicorp/consul/internal/storage" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" "github.com/hashicorp/consul/proto-public/pbresource" pbdemov1 "github.com/hashicorp/consul/proto/private/pbdemo/v1" pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2" @@ -27,113 +25,11 @@ import ( ) func TestWrite_InputValidation(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) - - type testCase struct { - modFn func(artist, recordLabel *pbresource.Resource) *pbresource.Resource - errContains string - } + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) - testCases := map[string]testCase{ - "no resource": { - modFn: func(_, _ *pbresource.Resource) *pbresource.Resource { - return nil - }, - errContains: "resource is required", - }, - "no id": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id = nil - return artist - }, - errContains: "resource.id is required", - }, - "no type": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Type = nil - return artist - }, - errContains: "resource.id.type is required", - }, - "no name": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Name = "" - return artist - }, - errContains: "resource.id.name invalid", - }, - "name is mixed case": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Name = "MixedCaseNotAllowed" - return artist - }, - errContains: "resource.id.name invalid", - }, - "name too long": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Name = strings.Repeat("a", resource.MaxNameLength+1) - return artist - }, - errContains: "resource.id.name invalid", - }, - "wrong data type": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - var err error - artist.Data, err = anypb.New(&pbdemov2.Album{}) - require.NoError(t, err) - return artist - }, - errContains: "resource.data is of wrong type", - }, - "partition is mixed case": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Partition = "Default" - return artist - }, - errContains: "resource.id.tenancy.partition invalid", - }, - "partition too long": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) - return artist - }, - errContains: "resource.id.tenancy.partition invalid", - }, - "namespace is mixed case": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Namespace = "Default" - return artist - }, - errContains: "resource.id.tenancy.namespace invalid", - }, - "namespace too long": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) - return artist - }, - errContains: "resource.id.tenancy.namespace invalid", - }, - "fail validation hook": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - buffer := &pbdemov2.Artist{} - require.NoError(t, artist.Data.UnmarshalTo(buffer)) - buffer.Name = "" // name cannot be empty - require.NoError(t, artist.Data.MarshalFrom(buffer)) - return artist - }, - errContains: "artist.name required", - }, - "partition scope with non-empty namespace": { - modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { - recordLabel.Id.Tenancy.Namespace = "bogus" - return recordLabel - }, - errContains: "cannot have a namespace", - }, - } - for desc, tc := range testCases { + for desc, tc := range resourceValidTestCases(t) { t.Run(desc, func(t *testing.T) { artist, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -151,62 +47,19 @@ func TestWrite_InputValidation(t *testing.T) { } func TestWrite_OwnerValidation(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) - type testCase struct { - modReqFn func(req *pbresource.WriteRequest) - errorContains string - } - testCases := map[string]testCase{ - "no owner type": { - modReqFn: func(req *pbresource.WriteRequest) { req.Resource.Owner.Type = nil }, - errorContains: "resource.owner.type is required", - }, - "no owner tenancy": { - modReqFn: func(req *pbresource.WriteRequest) { req.Resource.Owner.Tenancy = nil }, - errorContains: "resource.owner does not exist", - }, - "no owner name": { - modReqFn: func(req *pbresource.WriteRequest) { req.Resource.Owner.Name = "" }, - errorContains: "resource.owner.name invalid", - }, - "mixed case owner name": { - modReqFn: func(req *pbresource.WriteRequest) { req.Resource.Owner.Name = strings.ToUpper(req.Resource.Owner.Name) }, - errorContains: "resource.owner.name invalid", - }, - "owner name too long": { - modReqFn: func(req *pbresource.WriteRequest) { - req.Resource.Owner.Name = strings.Repeat("a", resource.MaxNameLength+1) - }, - errorContains: "resource.owner.name invalid", - }, - "owner partition is mixed case": { - modReqFn: func(req *pbresource.WriteRequest) { - req.Resource.Owner.Tenancy.Partition = "Default" - }, - errorContains: "resource.owner.tenancy.partition invalid", - }, - "owner partition too long": { - modReqFn: func(req *pbresource.WriteRequest) { - req.Resource.Owner.Tenancy.Partition = strings.Repeat("p", resource.MaxNameLength+1) - }, - errorContains: "resource.owner.tenancy.partition invalid", - }, - "owner namespace is mixed case": { - modReqFn: func(req *pbresource.WriteRequest) { - req.Resource.Owner.Tenancy.Namespace = "Default" - }, - errorContains: "resource.owner.tenancy.namespace invalid", - }, - "owner namespace too long": { - modReqFn: func(req *pbresource.WriteRequest) { - req.Resource.Owner.Tenancy.Namespace = strings.Repeat("n", resource.MaxNameLength+1) - }, - errorContains: "resource.owner.tenancy.namespace invalid", - }, + testCases := ownerValidationTestCases(t) + + // This is not part of ownerValidationTestCases because it is a special case + // that only gets caught deeper into the write path. + testCases["no owner tenancy"] = ownerValidTestCase{ + modFn: func(res *pbresource.Resource) { res.Owner.Tenancy = nil }, + errorContains: "resource.owner does not exist", } + for desc, tc := range testCases { t.Run(desc, func(t *testing.T) { artist, err := demo.GenerateV2Artist() @@ -215,10 +68,9 @@ func TestWrite_OwnerValidation(t *testing.T) { album, err := demo.GenerateV2Album(artist.Id) require.NoError(t, err) - albumReq := &pbresource.WriteRequest{Resource: album} - tc.modReqFn(albumReq) + tc.modFn(album) - _, err = client.Write(testContext(t), albumReq) + _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: album}) require.Error(t, err) require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) require.ErrorContains(t, err, tc.errorContains) @@ -227,8 +79,7 @@ func TestWrite_OwnerValidation(t *testing.T) { } func TestWrite_TypeNotFound(t *testing.T) { - server := testServer(t) - client := testClient(t, server) + client := svctest.NewResourceServiceBuilder().Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -262,14 +113,14 @@ func TestWrite_ACLs(t *testing.T) { for desc, tc := range testcases { t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - mockACLResolver := &MockACLResolver{} + mockACLResolver := &svc.MockACLResolver{} mockACLResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). Return(tc.authz, nil) - server.ACLResolver = mockACLResolver - demo.RegisterTypes(server.Registry) + + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + WithACLResolver(mockACLResolver). + Run(t) artist, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -282,9 +133,9 @@ func TestWrite_ACLs(t *testing.T) { } func TestWrite_Mutate(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) artist, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -307,88 +158,11 @@ func TestWrite_Mutate(t *testing.T) { } func TestWrite_Create_Success(t *testing.T) { - testCases := map[string]struct { - modFn func(artist, recordLabel *pbresource.Resource) *pbresource.Resource - expectedTenancy *pbresource.Tenancy - }{ - "namespaced resource provides nonempty partition and namespace": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - return artist - }, - expectedTenancy: resource.DefaultNamespacedTenancy(), - }, - "namespaced resource inherits tokens partition when empty": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Partition = "" - return artist - }, - expectedTenancy: resource.DefaultNamespacedTenancy(), - }, - "namespaced resource inherits tokens namespace when empty": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Namespace = "" - return artist - }, - expectedTenancy: resource.DefaultNamespacedTenancy(), - }, - "namespaced resource inherits tokens partition and namespace when empty": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Partition = "" - artist.Id.Tenancy.Namespace = "" - return artist - }, - expectedTenancy: resource.DefaultNamespacedTenancy(), - }, - "namespaced resource inherits tokens partition and namespace when tenancy nil": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy = nil - return artist - }, - expectedTenancy: resource.DefaultNamespacedTenancy(), - }, - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - "namespaced resource defaults peername to local when empty": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.PeerName = "" - return artist - }, - expectedTenancy: resource.DefaultNamespacedTenancy(), - }, - "partitioned resource provides nonempty partition": { - modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { - return recordLabel - }, - expectedTenancy: resource.DefaultPartitionedTenancy(), - }, - "partitioned resource inherits tokens partition when empty": { - modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { - recordLabel.Id.Tenancy.Partition = "" - return recordLabel - }, - expectedTenancy: resource.DefaultPartitionedTenancy(), - }, - "partitioned resource inherits tokens partition when tenancy nil": { - modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { - recordLabel.Id.Tenancy = nil - return recordLabel - }, - expectedTenancy: resource.DefaultPartitionedTenancy(), - }, - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - "partitioned resource defaults peername to local when empty": { - modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { - recordLabel.Id.Tenancy.PeerName = "" - return recordLabel - }, - expectedTenancy: resource.DefaultPartitionedTenancy(), - }, - // TODO(spatel): Add cluster scope tests when we have an actual cluster scoped resource (e.g. partition) - } - for desc, tc := range testCases { + for desc, tc := range mavOrWriteSuccessTestCases(t) { t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") require.NoError(t, err) @@ -406,91 +180,13 @@ func TestWrite_Create_Success(t *testing.T) { } } -func TestWrite_Create_Tenancy_NotFound(t *testing.T) { - testCases := map[string]struct { - modFn func(artist, recordLabel *pbresource.Resource) *pbresource.Resource - errCode codes.Code - errContains string - }{ - "namespaced resource provides nonexistant partition": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Partition = "boguspartition" - return artist - }, - errCode: codes.InvalidArgument, - errContains: "partition not found", - }, - "namespaced resource provides nonexistant namespace": { - modFn: func(artist, _ *pbresource.Resource) *pbresource.Resource { - artist.Id.Tenancy.Namespace = "bogusnamespace" - return artist - }, - errCode: codes.InvalidArgument, - errContains: "namespace not found", - }, - "partitioned resource provides nonexistant partition": { - modFn: func(_, recordLabel *pbresource.Resource) *pbresource.Resource { - recordLabel.Id.Tenancy.Partition = "boguspartition" - return recordLabel - }, - errCode: codes.InvalidArgument, - errContains: "partition not found", - }, - } - for desc, tc := range testCases { +func TestWrite_Create_With_TenancyMarkedForDeletion_Fails(t *testing.T) { + for desc, tc := range mavOrWriteTenancyMarkedForDeletionTestCases(t) { t.Run(desc, func(t *testing.T) { server := testServer(t) client := testClient(t, server) demo.RegisterTypes(server.Registry) - recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") - require.NoError(t, err) - - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - - _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: tc.modFn(artist, recordLabel)}) - require.Error(t, err) - require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) - require.Contains(t, err.Error(), tc.errContains) - }) - } -} - -func TestWrite_Tenancy_MarkedForDeletion(t *testing.T) { - // Verify resource write fails when its partition or namespace is marked for deletion. - testCases := map[string]struct { - modFn func(artist, recordLabel *pbresource.Resource, mockTenancyBridge *MockTenancyBridge) *pbresource.Resource - errContains string - }{ - "namespaced resources partition marked for deletion": { - modFn: func(artist, _ *pbresource.Resource, mockTenancyBridge *MockTenancyBridge) *pbresource.Resource { - mockTenancyBridge.On("IsPartitionMarkedForDeletion", "ap1").Return(true, nil) - return artist - }, - errContains: "partition marked for deletion", - }, - "namespaced resources namespace marked for deletion": { - modFn: func(artist, _ *pbresource.Resource, mockTenancyBridge *MockTenancyBridge) *pbresource.Resource { - mockTenancyBridge.On("IsPartitionMarkedForDeletion", "ap1").Return(false, nil) - mockTenancyBridge.On("IsNamespaceMarkedForDeletion", "ap1", "ns1").Return(true, nil) - return artist - }, - errContains: "namespace marked for deletion", - }, - "partitioned resources partition marked for deletion": { - modFn: func(_, recordLabel *pbresource.Resource, mockTenancyBridge *MockTenancyBridge) *pbresource.Resource { - mockTenancyBridge.On("IsPartitionMarkedForDeletion", "ap1").Return(true, nil) - return recordLabel - }, - errContains: "partition marked for deletion", - }, - } - for desc, tc := range testCases { - t.Run(desc, func(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - demo.RegisterTypes(server.Registry) recordLabel, err := demo.GenerateV1RecordLabel("looney-tunes") require.NoError(t, err) recordLabel.Id.Tenancy.Partition = "ap1" @@ -500,7 +196,7 @@ func TestWrite_Tenancy_MarkedForDeletion(t *testing.T) { artist.Id.Tenancy.Partition = "ap1" artist.Id.Tenancy.Namespace = "ns1" - mockTenancyBridge := &MockTenancyBridge{} + mockTenancyBridge := &svc.MockTenancyBridge{} mockTenancyBridge.On("PartitionExists", "ap1").Return(true, nil) mockTenancyBridge.On("NamespaceExists", "ap1", "ns1").Return(true, nil) server.TenancyBridge = mockTenancyBridge @@ -514,10 +210,9 @@ func TestWrite_Tenancy_MarkedForDeletion(t *testing.T) { } func TestWrite_CASUpdate_Success(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -536,10 +231,9 @@ func TestWrite_CASUpdate_Success(t *testing.T) { } func TestWrite_ResourceCreation_StatusProvided(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -555,10 +249,9 @@ func TestWrite_ResourceCreation_StatusProvided(t *testing.T) { } func TestWrite_CASUpdate_Failure(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -576,10 +269,9 @@ func TestWrite_CASUpdate_Failure(t *testing.T) { } func TestWrite_Update_WrongUid(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -597,10 +289,9 @@ func TestWrite_Update_WrongUid(t *testing.T) { } func TestWrite_Update_StatusModified(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -612,7 +303,7 @@ func TestWrite_Update_StatusModified(t *testing.T) { require.NoError(t, err) res = statusRsp.Resource - // Passing the staus unmodified should be fine. + // Passing the status unmodified should be fine. rsp2, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) require.NoError(t, err) @@ -627,10 +318,9 @@ func TestWrite_Update_StatusModified(t *testing.T) { } func TestWrite_Update_NilStatus(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -651,10 +341,9 @@ func TestWrite_Update_NilStatus(t *testing.T) { } func TestWrite_Update_NoUid(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -670,10 +359,9 @@ func TestWrite_Update_NoUid(t *testing.T) { } func TestWrite_Update_GroupVersion(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -700,10 +388,9 @@ func TestWrite_Update_GroupVersion(t *testing.T) { } func TestWrite_NonCASUpdate_Success(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -723,7 +410,6 @@ func TestWrite_NonCASUpdate_Success(t *testing.T) { func TestWrite_NonCASUpdate_Retry(t *testing.T) { server := testServer(t) client := testClient(t, server) - demo.RegisterTypes(server.Registry) res, err := demo.GenerateV2Artist() @@ -737,8 +423,8 @@ func TestWrite_NonCASUpdate_Retry(t *testing.T) { backend := &blockOnceBackend{ Backend: server.Backend, - readCh: make(chan struct{}), - blockCh: make(chan struct{}), + readCompletedCh: make(chan struct{}), + blockCh: make(chan struct{}), } server.Backend = backend @@ -753,7 +439,7 @@ func TestWrite_NonCASUpdate_Retry(t *testing.T) { // Wait for the read, to ensure the Write in the goroutine above has read the // current version of the resource. - <-backend.readCh + <-backend.readCompletedCh // Update the resource. res = modifyArtist(t, rsp1.Resource) @@ -768,10 +454,9 @@ func TestWrite_NonCASUpdate_Retry(t *testing.T) { } func TestWrite_NoData(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) res, err := demo.GenerateV1Concept("jazz") require.NoError(t, err) @@ -786,10 +471,9 @@ func TestWrite_Owner_Immutable(t *testing.T) { // Use of proto.Equal(..) in implementation covers all permutations // (nil -> non-nil, non-nil -> nil, owner1 -> owner2) so only the first one // is tested. - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) artist, err := demo.GenerateV2Artist() require.NoError(t, err) @@ -814,10 +498,9 @@ func TestWrite_Owner_Immutable(t *testing.T) { } func TestWrite_Owner_Uid(t *testing.T) { - server := testServer(t) - client := testClient(t, server) - - demo.RegisterTypes(server.Registry) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) t.Run("uid given", func(t *testing.T) { artist, err := demo.GenerateV2Artist() @@ -883,23 +566,81 @@ func TestWrite_Owner_Uid(t *testing.T) { }) } -type blockOnceBackend struct { - storage.Backend - - done uint32 - readCh chan struct{} - blockCh chan struct{} -} - -func (b *blockOnceBackend) Read(ctx context.Context, consistency storage.ReadConsistency, id *pbresource.ID) (*pbresource.Resource, error) { - res, err := b.Backend.Read(ctx, consistency, id) +func TestEnsureFinalizerRemoved(t *testing.T) { + type testCase struct { + mod func(input, existing *pbresource.Resource) + errContains string + } - // Block for exactly one call to Read. All subsequent calls (including those - // concurrent to the blocked call) will return immediately. - if atomic.CompareAndSwapUint32(&b.done, 0, 1) { - close(b.readCh) - <-b.blockCh + testCases := map[string]testCase{ + "one finalizer removed from input": { + mod: func(input, existing *pbresource.Resource) { + resource.AddFinalizer(existing, "f1") + resource.AddFinalizer(existing, "f2") + resource.AddFinalizer(input, "f1") + }, + }, + "all finalizers removed from input": { + mod: func(input, existing *pbresource.Resource) { + resource.AddFinalizer(existing, "f1") + resource.AddFinalizer(existing, "f2") + resource.AddFinalizer(input, "f1") + resource.RemoveFinalizer(input, "f1") + }, + }, + "all finalizers removed from input and no finalizer key": { + mod: func(input, existing *pbresource.Resource) { + resource.AddFinalizer(existing, "f1") + resource.AddFinalizer(existing, "f2") + }, + }, + "no finalizers removed from input": { + mod: func(input, existing *pbresource.Resource) { + resource.AddFinalizer(existing, "f1") + resource.AddFinalizer(input, "f1") + }, + errContains: "expected at least one finalizer to be removed", + }, + "input finalizers not proper subset of existing": { + mod: func(input, existing *pbresource.Resource) { + resource.AddFinalizer(existing, "f1") + resource.AddFinalizer(existing, "f2") + resource.AddFinalizer(input, "f3") + }, + errContains: "expected at least one finalizer to be removed", + }, + "existing has no finalizers for input to remove": { + mod: func(input, existing *pbresource.Resource) { + resource.AddFinalizer(input, "f3") + }, + errContains: "expected at least one finalizer to be removed", + }, } - return res, err + for desc, tc := range testCases { + t.Run(desc, func(t *testing.T) { + input := rtest.Resource(demo.TypeV1Artist, "artist1"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, &pbdemov1.Artist{Name: "artist1"}). + WithMeta(resource.DeletionTimestampKey, "someTimestamp"). + Build() + + existing := rtest.Resource(demo.TypeV1Artist, "artist1"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(t, &pbdemov1.Artist{Name: "artist1"}). + WithMeta(resource.DeletionTimestampKey, "someTimestamp"). + Build() + + tc.mod(input, existing) + + err := svc.EnsureFinalizerRemoved(input, existing) + if tc.errContains != "" { + require.Error(t, err) + require.Equal(t, codes.InvalidArgument.String(), status.Code(err).String()) + require.ErrorContains(t, err, tc.errContains) + } else { + require.NoError(t, err) + } + }) + } } diff --git a/agent/grpc-external/services/serverdiscovery/server.go b/agent/grpc-external/services/serverdiscovery/server.go index 99011c6d076f..805b95c3780d 100644 --- a/agent/grpc-external/services/serverdiscovery/server.go +++ b/agent/grpc-external/services/serverdiscovery/server.go @@ -37,6 +37,6 @@ func NewServer(cfg Config) *Server { return &Server{cfg} } -func (s *Server) Register(grpcServer *grpc.Server) { - pbserverdiscovery.RegisterServerDiscoveryServiceServer(grpcServer, s) +func (s *Server) Register(registrar grpc.ServiceRegistrar) { + pbserverdiscovery.RegisterServerDiscoveryServiceServer(registrar, s) } diff --git a/agent/grpc-external/services/serverdiscovery/watch_servers.go b/agent/grpc-external/services/serverdiscovery/watch_servers.go index 94ed7ac58aef..15586111f5b7 100644 --- a/agent/grpc-external/services/serverdiscovery/watch_servers.go +++ b/agent/grpc-external/services/serverdiscovery/watch_servers.go @@ -6,6 +6,7 @@ package serverdiscovery import ( "context" "errors" + "math/rand" "github.com/hashicorp/go-hclog" "google.golang.org/grpc/codes" @@ -39,7 +40,7 @@ func (s *Server) WatchServers(req *pbserverdiscovery.WatchServersRequest, server for { var err error idx, err = s.serveReadyServers(options.Token, idx, req, serverStream, logger) - if errors.Is(err, stream.ErrSubForceClosed) { + if errors.Is(err, stream.ErrSubForceClosed) || errors.Is(err, stream.ErrACLChanged) { logger.Trace("subscription force-closed due to an ACL change or snapshot restore, will attempt to re-auth and resume") } else { return err @@ -68,7 +69,7 @@ func (s *Server) serveReadyServers(token string, index uint64, req *pbserverdisc for { event, err := sub.Next(serverStream.Context()) switch { - case errors.Is(err, stream.ErrSubForceClosed): + case errors.Is(err, stream.ErrSubForceClosed) || errors.Is(err, stream.ErrACLChanged): return index, err case errors.Is(err, context.Canceled): return 0, nil @@ -130,6 +131,10 @@ func eventToResponse(req *pbserverdiscovery.WatchServersRequest, event stream.Ev }) } + // Shuffle servers so that consul-dataplane doesn't consistently choose the same connections on startup. + rand.Shuffle(len(servers), func(i, j int) { + servers[i], servers[j] = servers[j], servers[i] + }) return &pbserverdiscovery.WatchServersResponse{ Servers: servers, }, nil diff --git a/agent/grpc-external/services/serverdiscovery/watch_servers_test.go b/agent/grpc-external/services/serverdiscovery/watch_servers_test.go index 0df48f3bb35c..85daa9b60663 100644 --- a/agent/grpc-external/services/serverdiscovery/watch_servers_test.go +++ b/agent/grpc-external/services/serverdiscovery/watch_servers_test.go @@ -166,7 +166,7 @@ func TestWatchServers_StreamLifeCycle(t *testing.T) { // 4. See the corresponding message sent back through the stream. rsp = mustGetServers(t, rspCh) require.NotNil(t, rsp) - prototest.AssertDeepEqual(t, twoServerResponse, rsp) + prototest.AssertElementsMatch(t, twoServerResponse.Servers, rsp.Servers) // 5. Send a NewCloseSubscriptionEvent for the token secret. publisher.Publish([]stream.Event{ @@ -176,7 +176,7 @@ func TestWatchServers_StreamLifeCycle(t *testing.T) { // 6. Observe another snapshot message rsp = mustGetServers(t, rspCh) require.NotNil(t, rsp) - prototest.AssertDeepEqual(t, twoServerResponse, rsp) + prototest.AssertElementsMatch(t, twoServerResponse.Servers, rsp.Servers) // 7. Publish another event to move to 3 servers. publisher.Publish([]stream.Event{ @@ -192,7 +192,7 @@ func TestWatchServers_StreamLifeCycle(t *testing.T) { // seen after stream reinitialization. rsp = mustGetServers(t, rspCh) require.NotNil(t, rsp) - prototest.AssertDeepEqual(t, threeServerResponse, rsp) + prototest.AssertElementsMatch(t, threeServerResponse.Servers, rsp.Servers) } func TestWatchServers_ACLToken_AnonymousToken(t *testing.T) { diff --git a/agent/grpc-external/stats_test.go b/agent/grpc-external/stats_test.go index 3bd5c777cd16..7f59871db1fb 100644 --- a/agent/grpc-external/stats_test.go +++ b/agent/grpc-external/stats_test.go @@ -28,7 +28,7 @@ import ( func TestServer_EmitsStats(t *testing.T) { sink, metricsObj := testutil.NewFakeSink(t) - srv := NewServer(hclog.Default(), metricsObj, nil, rate.NullRequestLimitsHandler(), keepalive.ServerParameters{}) + srv := NewServer(hclog.Default(), metricsObj, nil, rate.NullRequestLimitsHandler(), keepalive.ServerParameters{}, nil) testservice.RegisterSimpleServer(srv, &testservice.Simple{}) diff --git a/agent/grpc-external/testutils/acl.go b/agent/grpc-external/testutils/acl.go index 72e0897e71fd..ea4294e657d7 100644 --- a/agent/grpc-external/testutils/acl.go +++ b/agent/grpc-external/testutils/acl.go @@ -4,8 +4,6 @@ package testutils import ( - "testing" - "github.com/stretchr/testify/require" "github.com/hashicorp/go-uuid" @@ -13,9 +11,10 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/sdk/testutil" ) -func ACLAnonymous(t *testing.T) resolver.Result { +func ACLAnonymous(t testutil.TestingTB) resolver.Result { t.Helper() return resolver.Result{ @@ -26,7 +25,7 @@ func ACLAnonymous(t *testing.T) resolver.Result { } } -func ACLsDisabled(t *testing.T) resolver.Result { +func ACLsDisabled(t testutil.TestingTB) resolver.Result { t.Helper() return resolver.Result{ @@ -34,7 +33,7 @@ func ACLsDisabled(t *testing.T) resolver.Result { } } -func ACLNoPermissions(t *testing.T) resolver.Result { +func ACLNoPermissions(t testutil.TestingTB) resolver.Result { t.Helper() return resolver.Result{ @@ -43,7 +42,7 @@ func ACLNoPermissions(t *testing.T) resolver.Result { } } -func ACLServiceWriteAny(t *testing.T) resolver.Result { +func ACLServiceWriteAny(t testutil.TestingTB) resolver.Result { t.Helper() policy, err := acl.NewPolicyFromSource(` @@ -62,7 +61,7 @@ func ACLServiceWriteAny(t *testing.T) resolver.Result { } } -func ACLServiceRead(t *testing.T, serviceName string) resolver.Result { +func ACLServiceRead(t testutil.TestingTB, serviceName string) resolver.Result { t.Helper() aclRule := &acl.Policy{ @@ -84,7 +83,7 @@ func ACLServiceRead(t *testing.T, serviceName string) resolver.Result { } } -func ACLUseProvidedPolicy(t *testing.T, aclPolicy *acl.Policy) resolver.Result { +func ACLUseProvidedPolicy(t testutil.TestingTB, aclPolicy *acl.Policy) resolver.Result { t.Helper() authz, err := acl.NewPolicyAuthorizerWithDefaults(acl.DenyAll(), []*acl.Policy{aclPolicy}, nil) @@ -96,7 +95,7 @@ func ACLUseProvidedPolicy(t *testing.T, aclPolicy *acl.Policy) resolver.Result { } } -func ACLOperatorRead(t *testing.T) resolver.Result { +func ACLOperatorRead(t testutil.TestingTB) resolver.Result { t.Helper() aclRule := &acl.Policy{ @@ -113,7 +112,7 @@ func ACLOperatorRead(t *testing.T) resolver.Result { } } -func ACLOperatorWrite(t *testing.T) resolver.Result { +func ACLOperatorWrite(t testutil.TestingTB) resolver.Result { t.Helper() aclRule := &acl.Policy{ @@ -130,7 +129,7 @@ func ACLOperatorWrite(t *testing.T) resolver.Result { } } -func randomACLIdentity(t *testing.T) structs.ACLIdentity { +func randomACLIdentity(t testutil.TestingTB) structs.ACLIdentity { id, err := uuid.GenerateUUID() require.NoError(t, err) diff --git a/agent/grpc-external/testutils/fsm.go b/agent/grpc-external/testutils/fsm.go index fdec1b109ed3..fb243ac36520 100644 --- a/agent/grpc-external/testutils/fsm.go +++ b/agent/grpc-external/testutils/fsm.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "github.com/hashicorp/consul/agent/blockingquery" "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/stream" "github.com/stretchr/testify/require" @@ -70,6 +71,47 @@ func (f *FakeFSM) ReplaceStore(store *state.Store) { } } +type FakeBlockingFSM struct { + store *state.Store +} + +func NewFakeBlockingFSM(t *testing.T) *FakeBlockingFSM { + t.Helper() + + store := TestStateStore(t, nil) + + fsm := &FakeBlockingFSM{store: store} + + return fsm +} + +func (f *FakeBlockingFSM) GetState() *state.Store { + return f.store +} + +func (f *FakeBlockingFSM) ConsistentRead() error { + return nil +} + +func (f *FakeBlockingFSM) DecrementBlockingQueries() uint64 { + return 0 +} + +func (f *FakeBlockingFSM) IncrementBlockingQueries() uint64 { + return 0 +} + +func (f *FakeBlockingFSM) GetShutdownChannel() chan struct{} { + return nil +} + +func (f *FakeBlockingFSM) RPCQueryTimeout(queryTimeout time.Duration) time.Duration { + return queryTimeout +} + +func (f *FakeBlockingFSM) SetQueryMeta(blockingquery.ResponseMeta, string) { +} + func SetupFSMAndPublisher(t *testing.T, config FakeFSMConfig) (*FakeFSM, state.EventPublisher) { t.Helper() config.publisher = stream.NewEventPublisher(10 * time.Second) diff --git a/agent/grpc-external/testutils/mock_server_transport_stream.go b/agent/grpc-external/testutils/mock_server_transport_stream.go new file mode 100644 index 000000000000..b57bc737d326 --- /dev/null +++ b/agent/grpc-external/testutils/mock_server_transport_stream.go @@ -0,0 +1,27 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package testutils + +import "google.golang.org/grpc/metadata" + +type MockServerTransportStream struct { + MD metadata.MD +} + +func (m *MockServerTransportStream) Method() string { + return "" +} + +func (m *MockServerTransportStream) SetHeader(md metadata.MD) error { + return nil +} + +func (m *MockServerTransportStream) SendHeader(md metadata.MD) error { + m.MD = metadata.Join(m.MD, md) + return nil +} + +func (m *MockServerTransportStream) SetTrailer(md metadata.MD) error { + return nil +} diff --git a/agent/grpc-external/testutils/server.go b/agent/grpc-external/testutils/server.go index 13cbb985e564..8613bec65c27 100644 --- a/agent/grpc-external/testutils/server.go +++ b/agent/grpc-external/testutils/server.go @@ -12,7 +12,7 @@ import ( ) type GRPCService interface { - Register(*grpc.Server) + Register(grpc.ServiceRegistrar) } func RunTestServer(t *testing.T, services ...GRPCService) net.Addr { diff --git a/agent/grpc-external/utils.go b/agent/grpc-external/utils.go index 13c84c75c1ce..8d915943da67 100644 --- a/agent/grpc-external/utils.go +++ b/agent/grpc-external/utils.go @@ -44,3 +44,9 @@ func RequireAnyValidACLToken(resolver ACLResolver, token string) error { return nil } + +func RequireNotNil(v interface{}, name string) { + if v == nil { + panic(name + " is required") + } +} diff --git a/agent/grpc-internal/balancer/balancer.go b/agent/grpc-internal/balancer/balancer.go index 884c2a1dec3d..c8ceb31ace57 100644 --- a/agent/grpc-internal/balancer/balancer.go +++ b/agent/grpc-internal/balancer/balancer.go @@ -353,7 +353,7 @@ func (b *balancer) switchServerLocked(newServer *serverInfo) { b.updatePickerLocked() if prevConn != nil { - b.conn.RemoveSubConn(prevConn) + prevConn.Shutdown() } } diff --git a/agent/grpc-internal/balancer/balancer_test.go b/agent/grpc-internal/balancer/balancer_test.go index f0c6db9f5329..989f7d745d5b 100644 --- a/agent/grpc-internal/balancer/balancer_test.go +++ b/agent/grpc-internal/balancer/balancer_test.go @@ -256,7 +256,6 @@ func stubResolver(t *testing.T, servers ...*server) (string, string, *manual.Res r.InitialState(resolver.State{Addresses: addresses}) resolver.Register(r) - t.Cleanup(func() { resolver.UnregisterForTesting(scheme) }) authority, err := uuid.GenerateUUID() require.NoError(t, err) diff --git a/agent/grpc-internal/handler.go b/agent/grpc-internal/handler.go index b0eeaa8a4f0c..3cda5087be47 100644 --- a/agent/grpc-internal/handler.go +++ b/agent/grpc-internal/handler.go @@ -28,9 +28,7 @@ var ( ) // NewHandler returns a gRPC server that accepts connections from Handle(conn). -// The register function will be called with the grpc.Server to register -// gRPC services with the server. -func NewHandler(logger Logger, addr net.Addr, register func(server *grpc.Server), metricsObj *metrics.Metrics, rateLimiter rate.RequestLimitsHandler) *Handler { +func NewHandler(logger Logger, addr net.Addr, metricsObj *metrics.Metrics, rateLimiter rate.RequestLimitsHandler) *Handler { if metricsObj == nil { metricsObj = metrics.Default() } @@ -59,7 +57,6 @@ func NewHandler(logger Logger, addr net.Addr, register func(server *grpc.Server) // We don't need to pass tls.Config to the server since it's multiplexed // behind the RPC listener, which already has TLS configured. srv := grpc.NewServer(opts...) - register(srv) return &Handler{srv: srv, listener: NewListener(addr)} } @@ -80,6 +77,12 @@ func (h *Handler) Run() error { return h.srv.Serve(h.listener) } +// Implements the grpc.ServiceRegistrar interface to allow registering services +// with the Handler. +func (h *Handler) RegisterService(svc *grpc.ServiceDesc, impl any) { + h.srv.RegisterService(svc, impl) +} + func (h *Handler) Shutdown() error { h.srv.Stop() return nil diff --git a/agent/grpc-internal/resolver/resolver_test.go b/agent/grpc-internal/resolver/resolver_test.go index 0914eba147ba..53e7f6c743ae 100644 --- a/agent/grpc-internal/resolver/resolver_test.go +++ b/agent/grpc-internal/resolver/resolver_test.go @@ -42,9 +42,7 @@ func TestServerResolverBuilder(t *testing.T) { cc := &fakeClientConn{} _, err := rs.Build(resolver.Target{ - Scheme: "consul", - Authority: rs.Authority(), - URL: url.URL{Opaque: endpoint}, + URL: url.URL{Opaque: endpoint, Scheme: "consul", Host: rs.Authority()}, }, cc, resolver.BuildOptions{}) require.NoError(t, err) diff --git a/agent/grpc-internal/server_test.go b/agent/grpc-internal/server_test.go index 12f420979b6e..65b43580a17b 100644 --- a/agent/grpc-internal/server_test.go +++ b/agent/grpc-internal/server_test.go @@ -44,21 +44,22 @@ func (s testServer) Metadata() *metadata.Server { } func newSimpleTestServer(t *testing.T, name, dc string, tlsConf *tlsutil.Configurator) testServer { - return newTestServer(t, hclog.Default(), name, dc, tlsConf, func(server *grpc.Server) { + return newTestServer(t, hclog.Default(), name, dc, tlsConf, func(server grpc.ServiceRegistrar) { testservice.RegisterSimpleServer(server, &testservice.Simple{Name: name, DC: dc}) }) } // newPanicTestServer sets up a simple server with handlers that panic. func newPanicTestServer(t *testing.T, logger hclog.Logger, name, dc string, tlsConf *tlsutil.Configurator) testServer { - return newTestServer(t, logger, name, dc, tlsConf, func(server *grpc.Server) { + return newTestServer(t, logger, name, dc, tlsConf, func(server grpc.ServiceRegistrar) { testservice.RegisterSimpleServer(server, &testservice.SimplePanic{Name: name, DC: dc}) }) } -func newTestServer(t *testing.T, logger hclog.Logger, name, dc string, tlsConf *tlsutil.Configurator, register func(server *grpc.Server)) testServer { +func newTestServer(t *testing.T, logger hclog.Logger, name, dc string, tlsConf *tlsutil.Configurator, register func(server grpc.ServiceRegistrar)) testServer { addr := &net.IPAddr{IP: net.ParseIP("127.0.0.1")} - handler := NewHandler(logger, addr, register, nil, rate.NullRequestLimitsHandler()) + handler := NewHandler(logger, addr, nil, rate.NullRequestLimitsHandler()) + register(handler) lis, err := net.Listen("tcp", "127.0.0.1:0") require.NoError(t, err) diff --git a/agent/grpc-internal/services/subscribe/subscribe.go b/agent/grpc-internal/services/subscribe/subscribe.go index a728b0164c97..5075d9e3dd51 100644 --- a/agent/grpc-internal/services/subscribe/subscribe.go +++ b/agent/grpc-internal/services/subscribe/subscribe.go @@ -77,6 +77,14 @@ func (h *Server) Subscribe(req *pbsubscribe.SubscribeRequest, serverStream pbsub case errors.Is(err, stream.ErrSubForceClosed): logger.Trace("subscription reset by server") return status.Error(codes.Aborted, err.Error()) + case errors.Is(err, stream.ErrACLChanged): + logger.Trace("ACL change occurred; re-authenticating") + _, authzErr := h.Backend.ResolveTokenAndDefaultMeta(req.Token, &entMeta, nil) + if authzErr != nil { + return authzErr + } + // Otherwise, abort the stream so the client re-subscribes. + return status.Error(codes.Aborted, err.Error()) case err != nil: return err } diff --git a/agent/grpc-internal/services/subscribe/subscribe_test.go b/agent/grpc-internal/services/subscribe/subscribe_test.go index 910862d4cfbd..a574da3fa825 100644 --- a/agent/grpc-internal/services/subscribe/subscribe_test.go +++ b/agent/grpc-internal/services/subscribe/subscribe_test.go @@ -6,6 +6,7 @@ package subscribe import ( "context" "errors" + "fmt" "io" "net" "testing" @@ -323,17 +324,21 @@ func getEvent(t *testing.T, ch chan eventOrError) *pbsubscribe.Event { } type testBackend struct { - publisher *stream.EventPublisher - store *state.Store - authorizer func(token string, entMeta *acl.EnterpriseMeta) acl.Authorizer - forwardConn *gogrpc.ClientConn + publisher *stream.EventPublisher + store *state.Store + authorizer func(token string, entMeta *acl.EnterpriseMeta) acl.Authorizer + resolveTokenAndDefaultMeta func(token string, entMeta *acl.EnterpriseMeta, _ *acl.AuthorizerContext) (acl.Authorizer, error) + forwardConn *gogrpc.ClientConn } func (b testBackend) ResolveTokenAndDefaultMeta( token string, entMeta *acl.EnterpriseMeta, - _ *acl.AuthorizerContext, + authCtx *acl.AuthorizerContext, ) (acl.Authorizer, error) { + if b.resolveTokenAndDefaultMeta != nil { + return b.resolveTokenAndDefaultMeta(token, entMeta, authCtx) + } return b.authorizer(token, entMeta), nil } @@ -377,36 +382,62 @@ func newTestBackend(t *testing.T) *testBackend { var _ Backend = (*testBackend)(nil) func runTestServer(t *testing.T, server *Server) net.Addr { + // create the errgroup and register its cleanup. Its cleanup needs to occur + // after all others and that is why this is being done so early on in this function + // as cleanup routines are processed in reverse order of them being added. + g := new(errgroup.Group) + // this cleanup needs to happen after others defined in this func so we do it early + // on up here. + t.Cleanup(func() { + if err := g.Wait(); err != nil { + t.Logf("grpc server error: %v", err) + } + }) + + // start the handler addr := &net.IPAddr{IP: net.ParseIP("127.0.0.1")} - var grpcServer *gogrpc.Server handler := grpc.NewHandler( hclog.New(nil), addr, - func(srv *gogrpc.Server) { - grpcServer = srv - pbsubscribe.RegisterStateChangeSubscriptionServer(srv, server) - }, nil, rate.NullRequestLimitsHandler(), ) - - lis, err := net.Listen("tcp", "127.0.0.1:0") - require.NoError(t, err) - t.Cleanup(logError(t, lis.Close)) - - go grpcServer.Serve(lis) - g := new(errgroup.Group) - g.Go(func() error { - return grpcServer.Serve(lis) - }) + pbsubscribe.RegisterStateChangeSubscriptionServer(handler, server) + g.Go(handler.Run) t.Cleanup(func() { if err := handler.Shutdown(); err != nil { t.Logf("grpc server shutdown: %v", err) } - if err := g.Wait(); err != nil { - t.Logf("grpc server error: %v", err) + }) + + // create the routing to forward network conns to the gRPC handler + lis, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + g.Go(func() error { + for { + // select { + // case <-ctx.Done(): + // return ctx.Err() + // default: + // } + + conn, err := lis.Accept() + if err != nil { + return err + } + + // select { + // case <-ctx.Done(): + // return ctx.Err() + // default: + // } + + handler.Handle(conn) } }) + // closing the listener should cause the Accept to unblock and error out + t.Cleanup(logError(t, lis.Close)) + return lis.Addr() } @@ -960,6 +991,47 @@ node "node1" { t.Fatalf("timeout waiting for aborted error") } }) + + // Re-subscribe because the previous test step terminated the stream. + chEvents = make(chan eventOrError, 0) + streamClient := pbsubscribe.NewStateChangeSubscriptionClient(conn) + streamHandle, err := streamClient.Subscribe(ctx, &pbsubscribe.SubscribeRequest{ + Topic: pbsubscribe.Topic_ServiceHealth, + Subject: &pbsubscribe.SubscribeRequest_NamedSubject{ + NamedSubject: &pbsubscribe.NamedSubject{ + Key: "foo", + }, + }, + Token: token, + }) + require.NoError(t, err) + + go recvEvents(chEvents, streamHandle) + + // Stub out token authn function so that the token is no longer considered valid. + backend.resolveTokenAndDefaultMeta = func(t string, entMeta *acl.EnterpriseMeta, _ *acl.AuthorizerContext) (acl.Authorizer, error) { + return nil, fmt.Errorf("ACL not found") + } + + testutil.RunStep(t, "invalid token should return an error", func(t *testing.T) { + // Force another ACL update. + tokenID, err := uuid.GenerateUUID() + require.NoError(t, err) + + aclToken := &structs.ACLToken{ + AccessorID: tokenID, + SecretID: token, + } + require.NoError(t, backend.store.ACLTokenSet(ids.Next("update"), aclToken)) + + select { + case item := <-chEvents: + require.Error(t, item.err, "got event instead of an error: %v", item.event) + require.EqualError(t, item.err, "rpc error: code = Unknown desc = ACL not found") + case <-time.After(2 * time.Second): + t.Fatalf("timeout waiting for ACL not found error") + } + }) } func assertNoEvents(t *testing.T, chEvents chan eventOrError) { diff --git a/agent/grpc-internal/stats_test.go b/agent/grpc-internal/stats_test.go index d14c4c46bc45..e08e869dea9b 100644 --- a/agent/grpc-internal/stats_test.go +++ b/agent/grpc-internal/stats_test.go @@ -23,15 +23,13 @@ import ( "github.com/hashicorp/consul/proto/private/prototest" ) -func noopRegister(*grpc.Server) {} - func TestHandler_EmitsStats(t *testing.T) { sink, metricsObj := testutil.NewFakeSink(t) addr := &net.IPAddr{IP: net.ParseIP("127.0.0.1")} - handler := NewHandler(hclog.Default(), addr, noopRegister, metricsObj, rate.NullRequestLimitsHandler()) + handler := NewHandler(hclog.Default(), addr, metricsObj, rate.NullRequestLimitsHandler()) - testservice.RegisterSimpleServer(handler.srv, &testservice.Simple{}) + testservice.RegisterSimpleServer(handler, &testservice.Simple{}) lis, err := net.Listen("tcp", "127.0.0.1:0") require.NoError(t, err) diff --git a/agent/grpc-middleware/rate_limit_mappings.gen.go b/agent/grpc-middleware/rate_limit_mappings.gen.go index fc73aa9d9cf2..2f6364b1b29a 100644 --- a/agent/grpc-middleware/rate_limit_mappings.gen.go +++ b/agent/grpc-middleware/rate_limit_mappings.gen.go @@ -4,35 +4,37 @@ package middleware import "github.com/hashicorp/consul/agent/consul/rate" var rpcRateLimitSpecs = map[string]rate.OperationSpec{ - "/hashicorp.consul.acl.ACLService/Login": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryACL}, - "/hashicorp.consul.acl.ACLService/Logout": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryACL}, - "/hashicorp.consul.connectca.ConnectCAService/Sign": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryConnectCA}, - "/hashicorp.consul.connectca.ConnectCAService/WatchRoots": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryConnectCA}, - "/hashicorp.consul.dataplane.DataplaneService/GetEnvoyBootstrapParams": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryDataPlane}, - "/hashicorp.consul.dataplane.DataplaneService/GetSupportedDataplaneFeatures": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryDataPlane}, - "/hashicorp.consul.dns.DNSService/Query": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryDNS}, - "/hashicorp.consul.internal.operator.OperatorService/TransferLeader": {Type: rate.OperationTypeExempt, Category: rate.OperationCategoryOperator}, - "/hashicorp.consul.internal.peering.PeeringService/Establish": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryPeering}, - "/hashicorp.consul.internal.peering.PeeringService/GenerateToken": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryPeering}, - "/hashicorp.consul.internal.peering.PeeringService/PeeringDelete": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryPeering}, - "/hashicorp.consul.internal.peering.PeeringService/PeeringList": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryPeering}, - "/hashicorp.consul.internal.peering.PeeringService/PeeringRead": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryPeering}, - "/hashicorp.consul.internal.peering.PeeringService/PeeringWrite": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryPeering}, - "/hashicorp.consul.internal.peering.PeeringService/TrustBundleListByService": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryPeering}, - "/hashicorp.consul.internal.peering.PeeringService/TrustBundleRead": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryPeering}, - "/hashicorp.consul.internal.peerstream.PeerStreamService/ExchangeSecret": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryPeerStream}, - "/hashicorp.consul.internal.peerstream.PeerStreamService/StreamResources": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryPeerStream}, - "/hashicorp.consul.internal.storage.raft.ForwardingService/Delete": {Type: rate.OperationTypeExempt, Category: rate.OperationCategoryResource}, - "/hashicorp.consul.internal.storage.raft.ForwardingService/List": {Type: rate.OperationTypeExempt, Category: rate.OperationCategoryResource}, - "/hashicorp.consul.internal.storage.raft.ForwardingService/Read": {Type: rate.OperationTypeExempt, Category: rate.OperationCategoryResource}, - "/hashicorp.consul.internal.storage.raft.ForwardingService/Write": {Type: rate.OperationTypeExempt, Category: rate.OperationCategoryResource}, - "/hashicorp.consul.resource.ResourceService/Delete": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryResource}, - "/hashicorp.consul.resource.ResourceService/List": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryResource}, - "/hashicorp.consul.resource.ResourceService/ListByOwner": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryResource}, - "/hashicorp.consul.resource.ResourceService/Read": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryResource}, - "/hashicorp.consul.resource.ResourceService/WatchList": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryResource}, - "/hashicorp.consul.resource.ResourceService/Write": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryResource}, - "/hashicorp.consul.resource.ResourceService/WriteStatus": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryResource}, - "/hashicorp.consul.serverdiscovery.ServerDiscoveryService/WatchServers": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryServerDiscovery}, - "/subscribe.StateChangeSubscription/Subscribe": {Type: rate.OperationTypeRead, Category: rate.OperationCategorySubscribe}, + "/hashicorp.consul.acl.ACLService/Login": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryACL}, + "/hashicorp.consul.acl.ACLService/Logout": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryACL}, + "/hashicorp.consul.connectca.ConnectCAService/Sign": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryConnectCA}, + "/hashicorp.consul.connectca.ConnectCAService/WatchRoots": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryConnectCA}, + "/hashicorp.consul.dataplane.DataplaneService/GetEnvoyBootstrapParams": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryDataPlane}, + "/hashicorp.consul.dataplane.DataplaneService/GetSupportedDataplaneFeatures": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryDataPlane}, + "/hashicorp.consul.dns.DNSService/Query": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryDNS}, + "/hashicorp.consul.internal.configentry.ConfigEntryService/GetResolvedExportedServices": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryConfigEntry}, + "/hashicorp.consul.internal.operator.OperatorService/TransferLeader": {Type: rate.OperationTypeExempt, Category: rate.OperationCategoryOperator}, + "/hashicorp.consul.internal.peering.PeeringService/Establish": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryPeering}, + "/hashicorp.consul.internal.peering.PeeringService/GenerateToken": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryPeering}, + "/hashicorp.consul.internal.peering.PeeringService/PeeringDelete": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryPeering}, + "/hashicorp.consul.internal.peering.PeeringService/PeeringList": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryPeering}, + "/hashicorp.consul.internal.peering.PeeringService/PeeringRead": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryPeering}, + "/hashicorp.consul.internal.peering.PeeringService/PeeringWrite": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryPeering}, + "/hashicorp.consul.internal.peering.PeeringService/TrustBundleListByService": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryPeering}, + "/hashicorp.consul.internal.peering.PeeringService/TrustBundleRead": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryPeering}, + "/hashicorp.consul.internal.peerstream.PeerStreamService/ExchangeSecret": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryPeerStream}, + "/hashicorp.consul.internal.peerstream.PeerStreamService/StreamResources": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryPeerStream}, + "/hashicorp.consul.internal.storage.raft.ForwardingService/Delete": {Type: rate.OperationTypeExempt, Category: rate.OperationCategoryResource}, + "/hashicorp.consul.internal.storage.raft.ForwardingService/List": {Type: rate.OperationTypeExempt, Category: rate.OperationCategoryResource}, + "/hashicorp.consul.internal.storage.raft.ForwardingService/Read": {Type: rate.OperationTypeExempt, Category: rate.OperationCategoryResource}, + "/hashicorp.consul.internal.storage.raft.ForwardingService/Write": {Type: rate.OperationTypeExempt, Category: rate.OperationCategoryResource}, + "/hashicorp.consul.resource.ResourceService/Delete": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryResource}, + "/hashicorp.consul.resource.ResourceService/List": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryResource}, + "/hashicorp.consul.resource.ResourceService/ListByOwner": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryResource}, + "/hashicorp.consul.resource.ResourceService/MutateAndValidate": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryResource}, + "/hashicorp.consul.resource.ResourceService/Read": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryResource}, + "/hashicorp.consul.resource.ResourceService/WatchList": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryResource}, + "/hashicorp.consul.resource.ResourceService/Write": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryResource}, + "/hashicorp.consul.resource.ResourceService/WriteStatus": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryResource}, + "/hashicorp.consul.serverdiscovery.ServerDiscoveryService/WatchServers": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryServerDiscovery}, + "/subscribe.StateChangeSubscription/Subscribe": {Type: rate.OperationTypeRead, Category: rate.OperationCategorySubscribe}, } diff --git a/agent/grpc-middleware/stats.go b/agent/grpc-middleware/stats.go index a6bf1d2c59be..b17fe7138588 100644 --- a/agent/grpc-middleware/stats.go +++ b/agent/grpc-middleware/stats.go @@ -107,6 +107,13 @@ func (c *statsHandler) HandleConn(_ context.Context, s stats.ConnStats) { c.metrics.SetGaugeWithLabels([]string{"grpc", label, "connections"}, float32(count), c.labels) } +// Intercept matches the Unary interceptor function signature. This unary interceptor will count RPC requests +// but does not handle any connection processing or perform RPC "tagging" +func (c *statsHandler) Intercept(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { + c.metrics.IncrCounterWithLabels([]string{"grpc", "server", "request", "count"}, 1, c.labels) + return handler(ctx, req) +} + type activeStreamCounter struct { // count is used with sync/atomic and MUST be 64-bit aligned. To ensure // alignment on 32-bit platforms this field must remain the first field in diff --git a/agent/grpc-middleware/testutil/testservice/simple.pb.go b/agent/grpc-middleware/testutil/testservice/simple.pb.go index b4f664bf1ca7..f727e0e39a50 100644 --- a/agent/grpc-middleware/testutil/testservice/simple.pb.go +++ b/agent/grpc-middleware/testutil/testservice/simple.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: simple.proto diff --git a/agent/hcp/bootstrap/bootstrap.go b/agent/hcp/bootstrap/bootstrap.go index 8e544bdec312..914a1890f3eb 100644 --- a/agent/hcp/bootstrap/bootstrap.go +++ b/agent/hcp/bootstrap/bootstrap.go @@ -1,10 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -// Package bootstrap handles bootstrapping an agent's config from HCP. It must be a -// separate package from other HCP components because it has a dependency on -// agent/config while other components need to be imported and run within the -// server process in agent/consul and that would create a dependency cycle. +// Package bootstrap handles bootstrapping an agent's config from HCP. package bootstrap import ( @@ -21,27 +18,25 @@ import ( "strings" "time" - "github.com/hashicorp/consul/agent/config" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/consul/agent/connect" + "github.com/hashicorp/consul/agent/hcp/bootstrap/constants" hcpclient "github.com/hashicorp/consul/agent/hcp/client" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/retry" - "github.com/hashicorp/go-uuid" ) const ( - subDir = "hcp-config" - - caFileName = "server-tls-cas.pem" - certFileName = "server-tls-cert.pem" - configFileName = "server-config.json" - keyFileName = "server-tls-key.pem" - tokenFileName = "hcp-management-token" - successFileName = "successful-bootstrap" + CAFileName = "server-tls-cas.pem" + CertFileName = "server-tls-cert.pem" + ConfigFileName = "server-config.json" + KeyFileName = "server-tls-key.pem" + TokenFileName = "hcp-management-token" + SuccessFileName = "successful-bootstrap" ) -type ConfigLoader func(source config.Source) (config.LoadResult, error) - // UI is a shim to allow the agent command to pass in it's mitchelh/cli.UI so we // can output useful messages to the user during bootstrapping. For example if // we have to retry several times to bootstrap we don't want the agent to just @@ -61,142 +56,27 @@ type RawBootstrapConfig struct { ManagementToken string } -// LoadConfig will attempt to load previously-fetched config from disk and fall back to -// fetch from HCP servers if the local data is incomplete. -// It must be passed a (CLI) UI implementation so it can deliver progress -// updates to the user, for example if it is waiting to retry for a long period. -func LoadConfig(ctx context.Context, client hcpclient.Client, dataDir string, loader ConfigLoader, ui UI) (ConfigLoader, error) { - ui.Output("Loading configuration from HCP") - - // See if we have existing config on disk - // - // OPTIMIZE: We could probably be more intelligent about config loading. - // The currently implemented approach is: - // 1. Attempt to load data from disk - // 2. If that fails or the data is incomplete, block indefinitely fetching remote config. - // - // What if instead we had the following flow: - // 1. Attempt to fetch config from HCP. - // 2. If that fails, fall back to data on disk from last fetch. - // 3. If that fails, go into blocking loop to fetch remote config. - // - // This should allow us to more gracefully transition cases like when - // an existing cluster is linked, but then wants to receive TLS materials - // at a later time. Currently, if we observe the existing-cluster marker we - // don't attempt to fetch any additional configuration from HCP. - - cfg, ok := loadPersistedBootstrapConfig(dataDir, ui) - if !ok { - ui.Info("Fetching configuration from HCP servers") - - var err error - cfg, err = fetchBootstrapConfig(ctx, client, dataDir, ui) - if err != nil { - return nil, fmt.Errorf("failed to bootstrap from HCP: %w", err) - } - ui.Info("Configuration fetched from HCP and saved on local disk") - - } else { - ui.Info("Loaded HCP configuration from local disk") - - } - - // Create a new loader func to return - newLoader := bootstrapConfigLoader(loader, cfg) - return newLoader, nil -} - -// bootstrapConfigLoader is a ConfigLoader for passing bootstrap JSON config received from HCP -// to the config.builder. ConfigLoaders are functions used to build an agent's RuntimeConfig -// from various sources like files and flags. This config is contained in the config.LoadResult. -// -// The flow to include bootstrap config from HCP as a loader's data source is as follows: -// -// 1. A base ConfigLoader function (baseLoader) is created on agent start, and it sets the input -// source argument as the DefaultConfig. -// -// 2. When a server agent can be configured by HCP that baseLoader is wrapped in this bootstrapConfigLoader. -// -// 3. The bootstrapConfigLoader calls that base loader with the bootstrap JSON config as the -// default source. This data will be merged with other valid sources in the config.builder. -// -// 4. The result of the call to baseLoader() below contains the resulting RuntimeConfig, and we do some -// additional modifications to attach data that doesn't get populated during the build in the config pkg. -// -// Note that since the ConfigJSON is stored as the baseLoader's DefaultConfig, its data is the first -// to be merged by the config.builder and could be overwritten by user-provided values in config files or -// CLI flags. However, values set to RuntimeConfig after the baseLoader call are final. -func bootstrapConfigLoader(baseLoader ConfigLoader, cfg *RawBootstrapConfig) ConfigLoader { - return func(source config.Source) (config.LoadResult, error) { - // Don't allow any further attempts to provide a DefaultSource. This should - // only ever be needed later in client agent AutoConfig code but that should - // be mutually exclusive from this bootstrapping mechanism since this is - // only for servers. If we ever try to change that, this clear failure - // should alert future developers that the assumptions are changing rather - // than quietly not applying the config they expect! - if source != nil { - return config.LoadResult{}, - fmt.Errorf("non-nil config source provided to a loader after HCP bootstrap already provided a DefaultSource") - } - - // Otherwise, just call to the loader we were passed with our own additional - // JSON as the source. - // - // OPTIMIZE: We could check/log whether any fields set by the remote config were overwritten by a user-provided flag. - res, err := baseLoader(config.FileSource{ - Name: "HCP Bootstrap", - Format: "json", - Data: cfg.ConfigJSON, - }) - if err != nil { - return res, fmt.Errorf("failed to load HCP Bootstrap config: %w", err) - } - - finalizeRuntimeConfig(res.RuntimeConfig, cfg) - return res, nil - } -} - -const ( - accessControlHeaderName = "Access-Control-Expose-Headers" - accessControlHeaderValue = "x-consul-default-acl-policy" -) - -// finalizeRuntimeConfig will set additional HCP-specific values that are not -// handled by the config.builder. -func finalizeRuntimeConfig(rc *config.RuntimeConfig, cfg *RawBootstrapConfig) { - rc.Cloud.ManagementToken = cfg.ManagementToken - - // HTTP response headers are modified for the HCP UI to work. - if rc.HTTPResponseHeaders == nil { - rc.HTTPResponseHeaders = make(map[string]string) - } - prevValue, ok := rc.HTTPResponseHeaders[accessControlHeaderName] - if !ok { - rc.HTTPResponseHeaders[accessControlHeaderName] = accessControlHeaderValue - } else { - rc.HTTPResponseHeaders[accessControlHeaderName] = prevValue + "," + accessControlHeaderValue - } -} - -// fetchBootstrapConfig will fetch boostrap configuration from remote servers and persist it to disk. +// FetchBootstrapConfig will fetch bootstrap configuration from remote servers and persist it to disk. // It will retry until successful or a terminal error condition is found (e.g. permission denied). -func fetchBootstrapConfig(ctx context.Context, client hcpclient.Client, dataDir string, ui UI) (*RawBootstrapConfig, error) { +func FetchBootstrapConfig(ctx context.Context, client hcpclient.Client, dataDir string, ui UI) (*RawBootstrapConfig, error) { w := retry.Waiter{ MinWait: 1 * time.Second, MaxWait: 5 * time.Minute, Jitter: retry.NewJitter(50), } - var bsCfg *hcpclient.BootstrapConfig for { // Note we don't want to shadow `ctx` here since we need that for the Wait // below. reqCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() - resp, err := client.FetchBootstrap(reqCtx) + cfg, err := fetchBootstrapConfig(reqCtx, client, dataDir) if err != nil { + if errors.Is(err, hcpclient.ErrUnauthorized) || errors.Is(err, hcpclient.ErrForbidden) { + // Don't retry on terminal errors + return nil, err + } ui.Error(fmt.Sprintf("Error: failed to fetch bootstrap config from HCP, will retry in %s: %s", w.NextWait().Round(time.Second), err)) if err := w.Wait(ctx); err != nil { @@ -205,12 +85,22 @@ func fetchBootstrapConfig(ctx context.Context, client hcpclient.Client, dataDir // Finished waiting, restart loop continue } - bsCfg = resp - break + return cfg, nil } +} - devMode := dataDir == "" +// fetchBootstrapConfig will fetch the bootstrap configuration from remote servers and persist it to disk. +func fetchBootstrapConfig(ctx context.Context, client hcpclient.Client, dataDir string) (*RawBootstrapConfig, error) { + reqCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + resp, err := client.FetchBootstrap(reqCtx) + if err != nil { + return nil, fmt.Errorf("failed to fetch bootstrap config from HCP: %w", err) + } + bsCfg := resp + devMode := dataDir == "" cfgJSON, err := persistAndProcessConfig(dataDir, devMode, bsCfg) if err != nil { return nil, fmt.Errorf("failed to persist config for existing cluster: %w", err) @@ -238,7 +128,7 @@ func persistAndProcessConfig(dataDir string, devMode bool, bsCfg *hcpclient.Boot } // Create subdir if it's not already there. - dir := filepath.Join(dataDir, subDir) + dir := filepath.Join(dataDir, constants.SubDir) if err := lib.EnsurePath(dir, true); err != nil { return "", fmt.Errorf("failed to ensure directory %q: %w", dir, err) } @@ -268,7 +158,7 @@ func persistAndProcessConfig(dataDir string, devMode bool, bsCfg *hcpclient.Boot var cfgJSON string if bsCfg.TLSCert != "" { - if err := validateTLSCerts(bsCfg.TLSCert, bsCfg.TLSCertKey, bsCfg.TLSCAs); err != nil { + if err := ValidateTLSCerts(bsCfg.TLSCert, bsCfg.TLSCertKey, bsCfg.TLSCAs); err != nil { return "", fmt.Errorf("invalid certificates: %w", err) } @@ -279,9 +169,9 @@ func persistAndProcessConfig(dataDir string, devMode bool, bsCfg *hcpclient.Boot } // Store paths to the persisted TLS cert files. - cfg["ca_file"] = filepath.Join(dir, caFileName) - cfg["cert_file"] = filepath.Join(dir, certFileName) - cfg["key_file"] = filepath.Join(dir, keyFileName) + cfg["ca_file"] = filepath.Join(dir, CAFileName) + cfg["cert_file"] = filepath.Join(dir, CertFileName) + cfg["key_file"] = filepath.Join(dir, KeyFileName) // Convert the bootstrap config map back into a string cfgJSONBytes, err := json.Marshal(cfg) @@ -317,7 +207,7 @@ func persistAndProcessConfig(dataDir string, devMode bool, bsCfg *hcpclient.Boot } func persistSuccessMarker(dir string) error { - name := filepath.Join(dir, successFileName) + name := filepath.Join(dir, SuccessFileName) return os.WriteFile(name, []byte(""), 0600) } @@ -330,7 +220,7 @@ func persistTLSCerts(dir string, serverCert, serverKey string, caCerts []string) // Write out CA cert(s). We write them all to one file because Go's x509 // machinery will read as many certs as it finds from each PEM file provided // and add them separaetly to the CertPool for validation - f, err := os.OpenFile(filepath.Join(dir, caFileName), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) + f, err := os.OpenFile(filepath.Join(dir, CAFileName), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return err } @@ -345,11 +235,11 @@ func persistTLSCerts(dir string, serverCert, serverKey string, caCerts []string) return err } - if err := os.WriteFile(filepath.Join(dir, certFileName), []byte(serverCert), 0600); err != nil { + if err := os.WriteFile(filepath.Join(dir, CertFileName), []byte(serverCert), 0600); err != nil { return err } - if err := os.WriteFile(filepath.Join(dir, keyFileName), []byte(serverKey), 0600); err != nil { + if err := os.WriteFile(filepath.Join(dir, KeyFileName), []byte(serverKey), 0600); err != nil { return err } @@ -366,26 +256,26 @@ func validateManagementToken(token string) error { } func persistManagementToken(dir, token string) error { - name := filepath.Join(dir, tokenFileName) + name := filepath.Join(dir, TokenFileName) return os.WriteFile(name, []byte(token), 0600) } func persistBootstrapConfig(dir, cfgJSON string) error { // Persist the important bits we got from bootstrapping. The TLS certs are // already persisted, just need to persist the config we are going to add. - name := filepath.Join(dir, configFileName) + name := filepath.Join(dir, ConfigFileName) return os.WriteFile(name, []byte(cfgJSON), 0600) } -func loadPersistedBootstrapConfig(dataDir string, ui UI) (*RawBootstrapConfig, bool) { +func LoadPersistedBootstrapConfig(dataDir string, ui UI) (*RawBootstrapConfig, bool) { if dataDir == "" { // There's no files to load when in dev mode. return nil, false } - dir := filepath.Join(dataDir, subDir) + dir := filepath.Join(dataDir, constants.SubDir) - _, err := os.Stat(filepath.Join(dir, successFileName)) + _, err := os.Stat(filepath.Join(dir, SuccessFileName)) if os.IsNotExist(err) { // Haven't bootstrapped from HCP. return nil, false @@ -419,7 +309,7 @@ func loadPersistedBootstrapConfig(dataDir string, ui UI) (*RawBootstrapConfig, b } func loadBootstrapConfigJSON(dataDir string) (string, error) { - filename := filepath.Join(dataDir, subDir, configFileName) + filename := filepath.Join(dataDir, constants.SubDir, ConfigFileName) _, err := os.Stat(filename) if os.IsNotExist(err) { @@ -429,21 +319,6 @@ func loadBootstrapConfigJSON(dataDir string) (string, error) { return "", fmt.Errorf("failed to check for bootstrap config: %w", err) } - // Attempt to load persisted config to check for errors and basic validity. - // Errors here will raise issues like referencing unsupported config fields. - _, err = config.Load(config.LoadOpts{ - ConfigFiles: []string{filename}, - HCL: []string{ - "server = true", - `bind_addr = "127.0.0.1"`, - fmt.Sprintf("data_dir = %q", dataDir), - }, - ConfigFormat: "json", - }) - if err != nil { - return "", fmt.Errorf("failed to parse local bootstrap config: %w", err) - } - jsonBs, err := os.ReadFile(filename) if err != nil { return "", fmt.Errorf(fmt.Sprintf("failed to read local bootstrap config file: %s", err)) @@ -452,7 +327,7 @@ func loadBootstrapConfigJSON(dataDir string) (string, error) { } func loadManagementToken(dir string) (string, error) { - name := filepath.Join(dir, tokenFileName) + name := filepath.Join(dir, TokenFileName) bytes, err := os.ReadFile(name) if os.IsNotExist(err) { return "", errors.New("configuration files on disk are incomplete, missing: " + name) @@ -471,9 +346,9 @@ func loadManagementToken(dir string) (string, error) { func checkCerts(dir string) error { files := []string{ - filepath.Join(dir, caFileName), - filepath.Join(dir, certFileName), - filepath.Join(dir, keyFileName), + filepath.Join(dir, CAFileName), + filepath.Join(dir, CertFileName), + filepath.Join(dir, KeyFileName), } missing := make([]string, 0) @@ -499,28 +374,28 @@ func checkCerts(dir string) error { return fmt.Errorf("configuration files on disk are incomplete, missing: %v", missing) } - cert, key, caCerts, err := loadCerts(dir) + cert, key, caCerts, err := LoadCerts(dir) if err != nil { return fmt.Errorf("failed to load certs from disk: %w", err) } - if err = validateTLSCerts(cert, key, caCerts); err != nil { + if err = ValidateTLSCerts(cert, key, caCerts); err != nil { return fmt.Errorf("invalid certs on disk: %w", err) } return nil } -func loadCerts(dir string) (cert, key string, caCerts []string, err error) { - certPEMBlock, err := os.ReadFile(filepath.Join(dir, certFileName)) +func LoadCerts(dir string) (cert, key string, caCerts []string, err error) { + certPEMBlock, err := os.ReadFile(filepath.Join(dir, CertFileName)) if err != nil { return "", "", nil, err } - keyPEMBlock, err := os.ReadFile(filepath.Join(dir, keyFileName)) + keyPEMBlock, err := os.ReadFile(filepath.Join(dir, KeyFileName)) if err != nil { return "", "", nil, err } - caPEMs, err := os.ReadFile(filepath.Join(dir, caFileName)) + caPEMs, err := os.ReadFile(filepath.Join(dir, CAFileName)) if err != nil { return "", "", nil, err } @@ -559,12 +434,12 @@ func splitCACerts(caPEMs []byte) ([]string, error) { return out, nil } -// validateTLSCerts checks that the CA cert, server cert, and key on disk are structurally valid. +// ValidateTLSCerts checks that the CA cert, server cert, and key on disk are structurally valid. // // OPTIMIZE: This could be improved by returning an error if certs are expired or close to expiration. // However, that requires issuing new certs on bootstrap requests, since returning an error // would trigger a re-fetch from HCP. -func validateTLSCerts(cert, key string, caCerts []string) error { +func ValidateTLSCerts(cert, key string, caCerts []string) error { leaf, err := tls.X509KeyPair([]byte(cert), []byte(key)) if err != nil { return errors.New("invalid server certificate or key") @@ -582,3 +457,25 @@ func validateTLSCerts(cert, key string, caCerts []string) error { } return nil } + +// LoadManagementToken returns the management token, either by loading it from the persisted +// token config file or by fetching it from HCP if the token file does not exist. +func LoadManagementToken(ctx context.Context, logger hclog.Logger, client hcpclient.Client, dataDir string) (string, error) { + hcpCfgDir := filepath.Join(dataDir, constants.SubDir) + token, err := loadManagementToken(hcpCfgDir) + + if err != nil { + logger.Debug("failed to load management token from local disk, fetching configuration from HCP", "error", err) + var err error + cfg, err := fetchBootstrapConfig(ctx, client, dataDir) + if err != nil { + return "", err + } + logger.Debug("configuration fetched from HCP and saved on local disk") + token = cfg.ManagementToken + } else { + logger.Trace("loaded HCP configuration from local disk") + } + + return token, nil +} diff --git a/agent/hcp/bootstrap/bootstrap_test.go b/agent/hcp/bootstrap/bootstrap_test.go index b475223ff8cf..3f2f84da87d1 100644 --- a/agent/hcp/bootstrap/bootstrap_test.go +++ b/agent/hcp/bootstrap/bootstrap_test.go @@ -5,302 +5,25 @@ package bootstrap import ( "context" - "crypto/tls" - "crypto/x509" - "fmt" - "net/http/httptest" + "errors" "os" "path/filepath" "testing" + "time" - "github.com/hashicorp/consul/agent/config" - "github.com/hashicorp/consul/agent/hcp" - hcpclient "github.com/hashicorp/consul/agent/hcp/client" - "github.com/hashicorp/consul/lib" - "github.com/hashicorp/consul/tlsutil" - "github.com/hashicorp/go-uuid" "github.com/mitchellh/cli" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" -) - -func TestBootstrapConfigLoader(t *testing.T) { - baseLoader := func(source config.Source) (config.LoadResult, error) { - return config.Load(config.LoadOpts{ - DefaultConfig: source, - HCL: []string{ - `server = true`, - `bind_addr = "127.0.0.1"`, - `data_dir = "/tmp/consul-data"`, - }, - }) - } - - bootstrapLoader := func(source config.Source) (config.LoadResult, error) { - return bootstrapConfigLoader(baseLoader, &RawBootstrapConfig{ - ConfigJSON: `{"bootstrap_expect": 8}`, - ManagementToken: "test-token", - })(source) - } - - result, err := bootstrapLoader(nil) - require.NoError(t, err) - - // bootstrap_expect and management token are injected from bootstrap config received from HCP. - require.Equal(t, 8, result.RuntimeConfig.BootstrapExpect) - require.Equal(t, "test-token", result.RuntimeConfig.Cloud.ManagementToken) - - // Response header is always injected from a constant. - require.Equal(t, "x-consul-default-acl-policy", result.RuntimeConfig.HTTPResponseHeaders[accessControlHeaderName]) -} - -func Test_finalizeRuntimeConfig(t *testing.T) { - type testCase struct { - rc *config.RuntimeConfig - cfg *RawBootstrapConfig - verifyFn func(t *testing.T, rc *config.RuntimeConfig) - } - run := func(t *testing.T, tc testCase) { - finalizeRuntimeConfig(tc.rc, tc.cfg) - tc.verifyFn(t, tc.rc) - } - - tt := map[string]testCase{ - "set header if not present": { - rc: &config.RuntimeConfig{}, - cfg: &RawBootstrapConfig{ - ManagementToken: "test-token", - }, - verifyFn: func(t *testing.T, rc *config.RuntimeConfig) { - require.Equal(t, "test-token", rc.Cloud.ManagementToken) - require.Equal(t, "x-consul-default-acl-policy", rc.HTTPResponseHeaders[accessControlHeaderName]) - }, - }, - "append to header if present": { - rc: &config.RuntimeConfig{ - HTTPResponseHeaders: map[string]string{ - accessControlHeaderName: "Content-Encoding", - }, - }, - cfg: &RawBootstrapConfig{ - ManagementToken: "test-token", - }, - verifyFn: func(t *testing.T, rc *config.RuntimeConfig) { - require.Equal(t, "test-token", rc.Cloud.ManagementToken) - require.Equal(t, "Content-Encoding,x-consul-default-acl-policy", rc.HTTPResponseHeaders[accessControlHeaderName]) - }, - }, - } - - for name, tc := range tt { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func boolPtr(value bool) *bool { - return &value -} - -func TestLoadConfig_Persistence(t *testing.T) { - type testCase struct { - // resourceID is the HCP resource ID. If set, a server is considered to be cloud-enabled. - resourceID string - - // devMode indicates whether the loader should not have a data directory. - devMode bool - - // verifyFn issues case-specific assertions. - verifyFn func(t *testing.T, rc *config.RuntimeConfig) - } - - run := func(t *testing.T, tc testCase) { - dir, err := os.MkdirTemp(os.TempDir(), "bootstrap-test-") - require.NoError(t, err) - t.Cleanup(func() { os.RemoveAll(dir) }) - - s := hcp.NewMockHCPServer() - s.AddEndpoint(TestEndpoint()) - - // Use an HTTPS server since that's what the HCP SDK expects for auth. - srv := httptest.NewTLSServer(s) - defer srv.Close() - - caCert, err := x509.ParseCertificate(srv.TLS.Certificates[0].Certificate[0]) - require.NoError(t, err) - - pool := x509.NewCertPool() - pool.AddCert(caCert) - clientTLS := &tls.Config{RootCAs: pool} - - baseOpts := config.LoadOpts{ - HCL: []string{ - `server = true`, - `bind_addr = "127.0.0.1"`, - fmt.Sprintf(`http_config = { response_headers = { %s = "Content-Encoding" } }`, accessControlHeaderName), - fmt.Sprintf(`cloud { client_id="test" client_secret="test" hostname=%q auth_url=%q resource_id=%q }`, - srv.Listener.Addr().String(), srv.URL, tc.resourceID), - }, - } - if tc.devMode { - baseOpts.DevMode = boolPtr(true) - } else { - baseOpts.HCL = append(baseOpts.HCL, fmt.Sprintf(`data_dir = %q`, dir)) - } - - baseLoader := func(source config.Source) (config.LoadResult, error) { - baseOpts.DefaultConfig = source - return config.Load(baseOpts) - } - - ui := cli.NewMockUi() - - // Load initial config to check whether bootstrapping from HCP is enabled. - initial, err := baseLoader(nil) - require.NoError(t, err) - - // Override the client TLS config so that the test server can be trusted. - initial.RuntimeConfig.Cloud.WithTLSConfig(clientTLS) - client, err := hcpclient.NewClient(initial.RuntimeConfig.Cloud) - require.NoError(t, err) - - loader, err := LoadConfig(context.Background(), client, initial.RuntimeConfig.DataDir, baseLoader, ui) - require.NoError(t, err) - - // Load the agent config with the potentially wrapped loader. - fromRemote, err := loader(nil) - require.NoError(t, err) - - // HCP-enabled cases should fetch from HCP on the first run of LoadConfig. - require.Contains(t, ui.OutputWriter.String(), "Fetching configuration from HCP") - - // Run case-specific verification. - tc.verifyFn(t, fromRemote.RuntimeConfig) - - require.Empty(t, fromRemote.RuntimeConfig.ACLInitialManagementToken, - "initial_management token should have been sanitized") - - if tc.devMode { - // Re-running the bootstrap func below isn't relevant to dev mode - // since they don't have a data directory to load data from. - return - } - - // Run LoadConfig again to exercise the logic of loading config from disk. - loader, err = LoadConfig(context.Background(), client, initial.RuntimeConfig.DataDir, baseLoader, ui) - require.NoError(t, err) - - fromDisk, err := loader(nil) - require.NoError(t, err) - - // HCP-enabled cases should fetch from disk on the second run. - require.Contains(t, ui.OutputWriter.String(), "Loaded HCP configuration from local disk") - - // Config loaded from disk should be the same as the one that was initially fetched from the HCP servers. - require.Equal(t, fromRemote.RuntimeConfig, fromDisk.RuntimeConfig) - } - - tt := map[string]testCase{ - "dev mode": { - devMode: true, - - resourceID: "organization/0b9de9a3-8403-4ca6-aba8-fca752f42100/" + - "project/0b9de9a3-8403-4ca6-aba8-fca752f42100/" + - "consul.cluster/new-cluster-id", - - verifyFn: func(t *testing.T, rc *config.RuntimeConfig) { - require.Empty(t, rc.DataDir) - - // Dev mode should have persisted certs since they can't be inlined. - require.NotEmpty(t, rc.TLS.HTTPS.CertFile) - require.NotEmpty(t, rc.TLS.HTTPS.KeyFile) - require.NotEmpty(t, rc.TLS.HTTPS.CAFile) - - // Find the temporary directory they got stored in. - dir := filepath.Dir(rc.TLS.HTTPS.CertFile) - - // Ensure we only stored the TLS materials. - entries, err := os.ReadDir(dir) - require.NoError(t, err) - require.Len(t, entries, 3) - - haveFiles := make([]string, 3) - for i, entry := range entries { - haveFiles[i] = entry.Name() - } - wantFiles := []string{caFileName, certFileName, keyFileName} - require.ElementsMatch(t, wantFiles, haveFiles) - }, - }, - "new cluster": { - resourceID: "organization/0b9de9a3-8403-4ca6-aba8-fca752f42100/" + - "project/0b9de9a3-8403-4ca6-aba8-fca752f42100/" + - "consul.cluster/new-cluster-id", - - // New clusters should have received and persisted the whole suite of config. - verifyFn: func(t *testing.T, rc *config.RuntimeConfig) { - dir := filepath.Join(rc.DataDir, subDir) - - entries, err := os.ReadDir(dir) - require.NoError(t, err) - require.Len(t, entries, 6) - - files := []string{ - filepath.Join(dir, configFileName), - filepath.Join(dir, caFileName), - filepath.Join(dir, certFileName), - filepath.Join(dir, keyFileName), - filepath.Join(dir, tokenFileName), - filepath.Join(dir, successFileName), - } - for _, name := range files { - _, err := os.Stat(name) - require.NoError(t, err) - } - - require.Equal(t, filepath.Join(dir, certFileName), rc.TLS.HTTPS.CertFile) - require.Equal(t, filepath.Join(dir, keyFileName), rc.TLS.HTTPS.KeyFile) - require.Equal(t, filepath.Join(dir, caFileName), rc.TLS.HTTPS.CAFile) - - cert, key, caCerts, err := loadCerts(dir) - require.NoError(t, err) - - require.NoError(t, validateTLSCerts(cert, key, caCerts)) - }, - }, - "existing cluster": { - resourceID: "organization/0b9de9a3-8403-4ca6-aba8-fca752f42100/" + - "project/0b9de9a3-8403-4ca6-aba8-fca752f42100/" + - "consul.cluster/" + TestExistingClusterID, - - // Existing clusters should have only received and persisted the management token. - verifyFn: func(t *testing.T, rc *config.RuntimeConfig) { - dir := filepath.Join(rc.DataDir, subDir) - - entries, err := os.ReadDir(dir) - require.NoError(t, err) - require.Len(t, entries, 3) - - files := []string{ - filepath.Join(dir, tokenFileName), - filepath.Join(dir, successFileName), - filepath.Join(dir, configFileName), - } - for _, name := range files { - _, err := os.Stat(name) - require.NoError(t, err) - } - }, - }, - } + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-uuid" - for name, tc := range tt { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} + "github.com/hashicorp/consul/agent/hcp/bootstrap/constants" + hcpclient "github.com/hashicorp/consul/agent/hcp/client" + "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/consul/tlsutil" +) func Test_loadPersistedBootstrapConfig(t *testing.T) { type expect struct { @@ -315,11 +38,9 @@ func Test_loadPersistedBootstrapConfig(t *testing.T) { } run := func(t *testing.T, tc testCase) { - dataDir, err := os.MkdirTemp(os.TempDir(), "load-bootstrap-test-") - require.NoError(t, err) - t.Cleanup(func() { os.RemoveAll(dataDir) }) + dataDir := testutil.TempDir(t, "load-bootstrap-cfg") - dir := filepath.Join(dataDir, subDir) + dir := filepath.Join(dataDir, constants.SubDir) // Do some common setup as if we received config from HCP and persisted it to disk. require.NoError(t, lib.EnsurePath(dir, true)) @@ -339,6 +60,7 @@ func Test_loadPersistedBootstrapConfig(t *testing.T) { var token string if !tc.disableManagementToken { + var err error token, err = uuid.GenerateUUID() require.NoError(t, err) require.NoError(t, persistManagementToken(dir, token)) @@ -350,7 +72,7 @@ func Test_loadPersistedBootstrapConfig(t *testing.T) { } ui := cli.NewMockUi() - cfg, loaded := loadPersistedBootstrapConfig(dataDir, ui) + cfg, loaded := LoadPersistedBootstrapConfig(dataDir, ui) require.Equal(t, tc.expect.loaded, loaded, ui.ErrorWriter.String()) if loaded { require.Equal(t, token, cfg.ManagementToken) @@ -407,7 +129,7 @@ func Test_loadPersistedBootstrapConfig(t *testing.T) { "new cluster some files": { mutateFn: func(t *testing.T, dir string) { // Remove one of the required files - require.NoError(t, os.Remove(filepath.Join(dir, certFileName))) + require.NoError(t, os.Remove(filepath.Join(dir, CertFileName))) }, expect: expect{ loaded: false, @@ -427,7 +149,7 @@ func Test_loadPersistedBootstrapConfig(t *testing.T) { }, "new cluster invalid cert": { mutateFn: func(t *testing.T, dir string) { - name := filepath.Join(dir, certFileName) + name := filepath.Join(dir, CertFileName) require.NoError(t, os.WriteFile(name, []byte("not-a-cert"), 0600)) }, expect: expect{ @@ -437,7 +159,7 @@ func Test_loadPersistedBootstrapConfig(t *testing.T) { }, "new cluster invalid CA": { mutateFn: func(t *testing.T, dir string) { - name := filepath.Join(dir, caFileName) + name := filepath.Join(dir, CAFileName) require.NoError(t, os.WriteFile(name, []byte("not-a-ca-cert"), 0600)) }, expect: expect{ @@ -445,20 +167,10 @@ func Test_loadPersistedBootstrapConfig(t *testing.T) { warning: "invalid CA certificate", }, }, - "new cluster invalid config flag": { - mutateFn: func(t *testing.T, dir string) { - name := filepath.Join(dir, configFileName) - require.NoError(t, os.WriteFile(name, []byte(`{"not_a_consul_agent_config_field" = "zap"}`), 0600)) - }, - expect: expect{ - loaded: false, - warning: "failed to parse local bootstrap config", - }, - }, "existing cluster invalid token": { existingCluster: true, mutateFn: func(t *testing.T, dir string) { - name := filepath.Join(dir, tokenFileName) + name := filepath.Join(dir, TokenFileName) require.NoError(t, os.WriteFile(name, []byte("not-a-uuid"), 0600)) }, expect: expect{ @@ -474,3 +186,136 @@ func Test_loadPersistedBootstrapConfig(t *testing.T) { }) } } + +func TestFetchBootstrapConfig(t *testing.T) { + type testCase struct { + expectFetchErr error + expectRetry bool + } + + run := func(t *testing.T, tc testCase) { + ui := cli.NewMockUi() + dataDir := testutil.TempDir(t, "fetch-bootstrap-cfg") + clientM := hcpclient.NewMockClient(t) + + if tc.expectFetchErr != nil && tc.expectRetry { + clientM.On("FetchBootstrap", mock.Anything). + Return(nil, tc.expectFetchErr) + } else if tc.expectFetchErr != nil && !tc.expectRetry { + clientM.On("FetchBootstrap", mock.Anything). + Return(nil, tc.expectFetchErr).Once() + } else { + validToken, err := uuid.GenerateUUID() + require.NoError(t, err) + clientM.EXPECT().FetchBootstrap(mock.Anything).Return(&hcpclient.BootstrapConfig{ + ManagementToken: validToken, + ConsulConfig: "{}", + }, nil).Once() + } + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + cfg, err := FetchBootstrapConfig(ctx, clientM, dataDir, ui) + + if tc.expectFetchErr == nil { + require.NoError(t, err) + require.NotNil(t, cfg) + return + } + + require.Error(t, err) + require.Nil(t, cfg) + if tc.expectRetry { + require.ErrorIs(t, err, context.DeadlineExceeded) + } else { + require.ErrorIs(t, err, tc.expectFetchErr) + } + } + + tt := map[string]testCase{ + "success": {}, + "unauthorized": { + expectFetchErr: hcpclient.ErrUnauthorized, + }, + "forbidden": { + expectFetchErr: hcpclient.ErrForbidden, + }, + "retryable fetch error": { + expectFetchErr: errors.New("error"), + expectRetry: true, + }, + } + + for name, tc := range tt { + t.Run(name, func(t *testing.T) { + run(t, tc) + }) + } +} + +func TestLoadManagementToken(t *testing.T) { + type testCase struct { + skipHCPConfigDir bool + skipTokenFile bool + tokenFileContent string + skipBootstrap bool + } + + validToken, err := uuid.GenerateUUID() + require.NoError(t, err) + + run := func(t *testing.T, tc testCase) { + dataDir := testutil.TempDir(t, "load-management-token") + + hcpCfgDir := filepath.Join(dataDir, constants.SubDir) + if !tc.skipHCPConfigDir { + err := os.Mkdir(hcpCfgDir, 0755) + require.NoError(t, err) + } + + tokenFilePath := filepath.Join(hcpCfgDir, TokenFileName) + if !tc.skipTokenFile { + err := os.WriteFile(tokenFilePath, []byte(tc.tokenFileContent), 0600) + require.NoError(t, err) + } + + clientM := hcpclient.NewMockClient(t) + if !tc.skipBootstrap { + clientM.EXPECT().FetchBootstrap(mock.Anything).Return(&hcpclient.BootstrapConfig{ + ManagementToken: validToken, + ConsulConfig: "{}", + }, nil).Once() + } + + token, err := LoadManagementToken(context.Background(), hclog.NewNullLogger(), clientM, dataDir) + require.NoError(t, err) + require.Equal(t, validToken, token) + + bytes, err := os.ReadFile(tokenFilePath) + require.NoError(t, err) + require.Equal(t, validToken, string(bytes)) + } + + tt := map[string]testCase{ + "token configured": { + skipBootstrap: true, + tokenFileContent: validToken, + }, + "no token configured": { + skipTokenFile: true, + }, + "invalid token configured": { + tokenFileContent: "invalid", + }, + "no hcp-config directory": { + skipHCPConfigDir: true, + skipTokenFile: true, + }, + } + + for name, tc := range tt { + t.Run(name, func(t *testing.T) { + run(t, tc) + }) + } +} diff --git a/agent/hcp/bootstrap/config-loader/loader.go b/agent/hcp/bootstrap/config-loader/loader.go new file mode 100644 index 000000000000..05e8d1910225 --- /dev/null +++ b/agent/hcp/bootstrap/config-loader/loader.go @@ -0,0 +1,179 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +// Package loader handles loading the bootstrap agent config fetched from HCP into +// the agent's config. It must be a separate package from other HCP components +// because it has a dependency on agent/config while other components need to be +// imported and run within the server process in agent/consul and that would create +// a dependency cycle. +package loader + +import ( + "context" + "fmt" + "path/filepath" + + "github.com/hashicorp/consul/agent/config" + "github.com/hashicorp/consul/agent/hcp/bootstrap" + "github.com/hashicorp/consul/agent/hcp/bootstrap/constants" + hcpclient "github.com/hashicorp/consul/agent/hcp/client" +) + +type ConfigLoader func(source config.Source) (config.LoadResult, error) + +// LoadConfig will attempt to load previously-fetched config from disk and fall back to +// fetch from HCP servers if the local data is incomplete. +// It must be passed a (CLI) UI implementation so it can deliver progress +// updates to the user, for example if it is waiting to retry for a long period. +func LoadConfig(ctx context.Context, client hcpclient.Client, dataDir string, loader ConfigLoader, ui bootstrap.UI) (ConfigLoader, error) { + ui.Output("Loading configuration from HCP") + + // See if we have existing config on disk + // + // OPTIMIZE: We could probably be more intelligent about config loading. + // The currently implemented approach is: + // 1. Attempt to load data from disk + // 2. If that fails or the data is incomplete, block indefinitely fetching remote config. + // + // What if instead we had the following flow: + // 1. Attempt to fetch config from HCP. + // 2. If that fails, fall back to data on disk from last fetch. + // 3. If that fails, go into blocking loop to fetch remote config. + // + // This should allow us to more gracefully transition cases like when + // an existing cluster is linked, but then wants to receive TLS materials + // at a later time. Currently, if we observe the existing-cluster marker we + // don't attempt to fetch any additional configuration from HCP. + + cfg, ok := bootstrap.LoadPersistedBootstrapConfig(dataDir, ui) + if ok { + // Persisted bootstrap config exists, but needs to be validated + err := validatePersistedConfig(dataDir) + if err != nil { + ok = false + } + } + if !ok { + ui.Info("Fetching configuration from HCP servers") + + var err error + cfg, err = bootstrap.FetchBootstrapConfig(ctx, client, dataDir, ui) + if err != nil { + return nil, fmt.Errorf("failed to bootstrap from HCP: %w", err) + } + ui.Info("Configuration fetched from HCP and saved on local disk") + + } else { + ui.Info("Loaded HCP configuration from local disk") + + } + + // Create a new loader func to return + newLoader := bootstrapConfigLoader(loader, cfg) + return newLoader, nil +} + +func AddAclPolicyAccessControlHeader(baseLoader ConfigLoader) ConfigLoader { + return func(source config.Source) (config.LoadResult, error) { + res, err := baseLoader(source) + if err != nil { + return res, err + } + + rc := res.RuntimeConfig + + // HTTP response headers are modified for the HCP UI to work. + if rc.HTTPResponseHeaders == nil { + rc.HTTPResponseHeaders = make(map[string]string) + } + prevValue, ok := rc.HTTPResponseHeaders[accessControlHeaderName] + if !ok { + rc.HTTPResponseHeaders[accessControlHeaderName] = accessControlHeaderValue + } else { + rc.HTTPResponseHeaders[accessControlHeaderName] = prevValue + "," + accessControlHeaderValue + } + + return res, nil + } +} + +// bootstrapConfigLoader is a ConfigLoader for passing bootstrap JSON config received from HCP +// to the config.builder. ConfigLoaders are functions used to build an agent's RuntimeConfig +// from various sources like files and flags. This config is contained in the config.LoadResult. +// +// The flow to include bootstrap config from HCP as a loader's data source is as follows: +// +// 1. A base ConfigLoader function (baseLoader) is created on agent start, and it sets the input +// source argument as the DefaultConfig. +// +// 2. When a server agent can be configured by HCP that baseLoader is wrapped in this bootstrapConfigLoader. +// +// 3. The bootstrapConfigLoader calls that base loader with the bootstrap JSON config as the +// default source. This data will be merged with other valid sources in the config.builder. +// +// 4. The result of the call to baseLoader() below contains the resulting RuntimeConfig, and we do some +// additional modifications to attach data that doesn't get populated during the build in the config pkg. +// +// Note that since the ConfigJSON is stored as the baseLoader's DefaultConfig, its data is the first +// to be merged by the config.builder and could be overwritten by user-provided values in config files or +// CLI flags. However, values set to RuntimeConfig after the baseLoader call are final. +func bootstrapConfigLoader(baseLoader ConfigLoader, cfg *bootstrap.RawBootstrapConfig) ConfigLoader { + return func(source config.Source) (config.LoadResult, error) { + // Don't allow any further attempts to provide a DefaultSource. This should + // only ever be needed later in client agent AutoConfig code but that should + // be mutually exclusive from this bootstrapping mechanism since this is + // only for servers. If we ever try to change that, this clear failure + // should alert future developers that the assumptions are changing rather + // than quietly not applying the config they expect! + if source != nil { + return config.LoadResult{}, + fmt.Errorf("non-nil config source provided to a loader after HCP bootstrap already provided a DefaultSource") + } + + // Otherwise, just call to the loader we were passed with our own additional + // JSON as the source. + // + // OPTIMIZE: We could check/log whether any fields set by the remote config were overwritten by a user-provided flag. + res, err := baseLoader(config.FileSource{ + Name: "HCP Bootstrap", + Format: "json", + Data: cfg.ConfigJSON, + }) + if err != nil { + return res, fmt.Errorf("failed to load HCP Bootstrap config: %w", err) + } + + finalizeRuntimeConfig(res.RuntimeConfig, cfg) + return res, nil + } +} + +const ( + accessControlHeaderName = "Access-Control-Expose-Headers" + accessControlHeaderValue = "x-consul-default-acl-policy" +) + +// finalizeRuntimeConfig will set additional HCP-specific values that are not +// handled by the config.builder. +func finalizeRuntimeConfig(rc *config.RuntimeConfig, cfg *bootstrap.RawBootstrapConfig) { + rc.Cloud.ManagementToken = cfg.ManagementToken +} + +// validatePersistedConfig attempts to load persisted config to check for errors and basic validity. +// Errors here will raise issues like referencing unsupported config fields. +func validatePersistedConfig(dataDir string) error { + filename := filepath.Join(dataDir, constants.SubDir, bootstrap.ConfigFileName) + _, err := config.Load(config.LoadOpts{ + ConfigFiles: []string{filename}, + HCL: []string{ + "server = true", + `bind_addr = "127.0.0.1"`, + fmt.Sprintf("data_dir = %q", dataDir), + }, + ConfigFormat: "json", + }) + if err != nil { + return fmt.Errorf("failed to parse local bootstrap config: %w", err) + } + return nil +} diff --git a/agent/hcp/bootstrap/config-loader/loader_test.go b/agent/hcp/bootstrap/config-loader/loader_test.go new file mode 100644 index 000000000000..8171c6c30f41 --- /dev/null +++ b/agent/hcp/bootstrap/config-loader/loader_test.go @@ -0,0 +1,391 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package loader + +import ( + "context" + "crypto/tls" + "crypto/x509" + "fmt" + "net/http/httptest" + "os" + "path/filepath" + "testing" + + "github.com/mitchellh/cli" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/agent/config" + "github.com/hashicorp/consul/agent/hcp" + "github.com/hashicorp/consul/agent/hcp/bootstrap" + "github.com/hashicorp/consul/agent/hcp/bootstrap/constants" + hcpclient "github.com/hashicorp/consul/agent/hcp/client" + "github.com/hashicorp/consul/lib" +) + +func TestBootstrapConfigLoader(t *testing.T) { + baseLoader := func(source config.Source) (config.LoadResult, error) { + return config.Load(config.LoadOpts{ + DefaultConfig: source, + HCL: []string{ + `server = true`, + `bind_addr = "127.0.0.1"`, + `data_dir = "/tmp/consul-data"`, + }, + }) + } + + bootstrapLoader := func(source config.Source) (config.LoadResult, error) { + return bootstrapConfigLoader(baseLoader, &bootstrap.RawBootstrapConfig{ + ConfigJSON: `{"bootstrap_expect": 8}`, + ManagementToken: "test-token", + })(source) + } + + result, err := bootstrapLoader(nil) + require.NoError(t, err) + + // bootstrap_expect and management token are injected from bootstrap config received from HCP. + require.Equal(t, 8, result.RuntimeConfig.BootstrapExpect) + require.Equal(t, "test-token", result.RuntimeConfig.Cloud.ManagementToken) +} + +func Test_finalizeRuntimeConfig(t *testing.T) { + type testCase struct { + rc *config.RuntimeConfig + cfg *bootstrap.RawBootstrapConfig + verifyFn func(t *testing.T, rc *config.RuntimeConfig) + } + run := func(t *testing.T, tc testCase) { + finalizeRuntimeConfig(tc.rc, tc.cfg) + tc.verifyFn(t, tc.rc) + } + + tt := map[string]testCase{ + "set management token": { + rc: &config.RuntimeConfig{}, + cfg: &bootstrap.RawBootstrapConfig{ + ManagementToken: "test-token", + }, + verifyFn: func(t *testing.T, rc *config.RuntimeConfig) { + require.Equal(t, "test-token", rc.Cloud.ManagementToken) + }, + }, + } + + for name, tc := range tt { + t.Run(name, func(t *testing.T) { + run(t, tc) + }) + } +} + +func Test_AddAclPolicyAccessControlHeader(t *testing.T) { + type testCase struct { + baseLoader ConfigLoader + verifyFn func(t *testing.T, rc *config.RuntimeConfig) + } + run := func(t *testing.T, tc testCase) { + loader := AddAclPolicyAccessControlHeader(tc.baseLoader) + result, err := loader(nil) + require.NoError(t, err) + tc.verifyFn(t, result.RuntimeConfig) + } + + tt := map[string]testCase{ + "append to header if present": { + baseLoader: func(source config.Source) (config.LoadResult, error) { + return config.Load(config.LoadOpts{ + DefaultConfig: config.DefaultSource(), + HCL: []string{ + `server = true`, + `bind_addr = "127.0.0.1"`, + `data_dir = "/tmp/consul-data"`, + fmt.Sprintf(`http_config = { response_headers = { %s = "test" } }`, accessControlHeaderName), + }, + }) + }, + verifyFn: func(t *testing.T, rc *config.RuntimeConfig) { + require.Equal(t, "test,x-consul-default-acl-policy", rc.HTTPResponseHeaders[accessControlHeaderName]) + }, + }, + "set header if not present": { + baseLoader: func(source config.Source) (config.LoadResult, error) { + return config.Load(config.LoadOpts{ + DefaultConfig: config.DefaultSource(), + HCL: []string{ + `server = true`, + `bind_addr = "127.0.0.1"`, + `data_dir = "/tmp/consul-data"`, + }, + }) + }, + verifyFn: func(t *testing.T, rc *config.RuntimeConfig) { + require.Equal(t, "x-consul-default-acl-policy", rc.HTTPResponseHeaders[accessControlHeaderName]) + }, + }, + } + + for name, tc := range tt { + t.Run(name, func(t *testing.T) { + run(t, tc) + }) + } +} + +func boolPtr(value bool) *bool { + return &value +} + +func TestLoadConfig_Persistence(t *testing.T) { + type testCase struct { + // resourceID is the HCP resource ID. If set, a server is considered to be cloud-enabled. + resourceID string + + // devMode indicates whether the loader should not have a data directory. + devMode bool + + // verifyFn issues case-specific assertions. + verifyFn func(t *testing.T, rc *config.RuntimeConfig) + } + + run := func(t *testing.T, tc testCase) { + dir, err := os.MkdirTemp(os.TempDir(), "bootstrap-test-") + require.NoError(t, err) + t.Cleanup(func() { os.RemoveAll(dir) }) + + s := hcp.NewMockHCPServer() + s.AddEndpoint(bootstrap.TestEndpoint()) + + // Use an HTTPS server since that's what the HCP SDK expects for auth. + srv := httptest.NewTLSServer(s) + defer srv.Close() + + caCert, err := x509.ParseCertificate(srv.TLS.Certificates[0].Certificate[0]) + require.NoError(t, err) + + pool := x509.NewCertPool() + pool.AddCert(caCert) + clientTLS := &tls.Config{RootCAs: pool} + + baseOpts := config.LoadOpts{ + HCL: []string{ + `server = true`, + `bind_addr = "127.0.0.1"`, + fmt.Sprintf(`http_config = { response_headers = { %s = "Content-Encoding" } }`, accessControlHeaderName), + fmt.Sprintf(`cloud { client_id="test" client_secret="test" hostname=%q auth_url=%q resource_id=%q }`, + srv.Listener.Addr().String(), srv.URL, tc.resourceID), + }, + } + if tc.devMode { + baseOpts.DevMode = boolPtr(true) + } else { + baseOpts.HCL = append(baseOpts.HCL, fmt.Sprintf(`data_dir = %q`, dir)) + } + + baseLoader := func(source config.Source) (config.LoadResult, error) { + baseOpts.DefaultConfig = source + return config.Load(baseOpts) + } + + ui := cli.NewMockUi() + + // Load initial config to check whether bootstrapping from HCP is enabled. + initial, err := baseLoader(nil) + require.NoError(t, err) + + // Override the client TLS config so that the test server can be trusted. + initial.RuntimeConfig.Cloud.WithTLSConfig(clientTLS) + client, err := hcpclient.NewClient(initial.RuntimeConfig.Cloud) + require.NoError(t, err) + + loader, err := LoadConfig(context.Background(), client, initial.RuntimeConfig.DataDir, baseLoader, ui) + require.NoError(t, err) + + // Load the agent config with the potentially wrapped loader. + fromRemote, err := loader(nil) + require.NoError(t, err) + + // HCP-enabled cases should fetch from HCP on the first run of LoadConfig. + require.Contains(t, ui.OutputWriter.String(), "Fetching configuration from HCP") + + // Run case-specific verification. + tc.verifyFn(t, fromRemote.RuntimeConfig) + + require.Empty(t, fromRemote.RuntimeConfig.ACLInitialManagementToken, + "initial_management token should have been sanitized") + + if tc.devMode { + // Re-running the bootstrap func below isn't relevant to dev mode + // since they don't have a data directory to load data from. + return + } + + // Run LoadConfig again to exercise the logic of loading config from disk. + loader, err = LoadConfig(context.Background(), client, initial.RuntimeConfig.DataDir, baseLoader, ui) + require.NoError(t, err) + + fromDisk, err := loader(nil) + require.NoError(t, err) + + // HCP-enabled cases should fetch from disk on the second run. + require.Contains(t, ui.OutputWriter.String(), "Loaded HCP configuration from local disk") + + // Config loaded from disk should be the same as the one that was initially fetched from the HCP servers. + require.Equal(t, fromRemote.RuntimeConfig, fromDisk.RuntimeConfig) + } + + tt := map[string]testCase{ + "dev mode": { + devMode: true, + + resourceID: "organization/0b9de9a3-8403-4ca6-aba8-fca752f42100/" + + "project/0b9de9a3-8403-4ca6-aba8-fca752f42100/" + + "consul.cluster/new-cluster-id", + + verifyFn: func(t *testing.T, rc *config.RuntimeConfig) { + require.Empty(t, rc.DataDir) + + // Dev mode should have persisted certs since they can't be inlined. + require.NotEmpty(t, rc.TLS.HTTPS.CertFile) + require.NotEmpty(t, rc.TLS.HTTPS.KeyFile) + require.NotEmpty(t, rc.TLS.HTTPS.CAFile) + + // Find the temporary directory they got stored in. + dir := filepath.Dir(rc.TLS.HTTPS.CertFile) + + // Ensure we only stored the TLS materials. + entries, err := os.ReadDir(dir) + require.NoError(t, err) + require.Len(t, entries, 3) + + haveFiles := make([]string, 3) + for i, entry := range entries { + haveFiles[i] = entry.Name() + } + + wantFiles := []string{bootstrap.CAFileName, bootstrap.CertFileName, bootstrap.KeyFileName} + require.ElementsMatch(t, wantFiles, haveFiles) + }, + }, + "new cluster": { + resourceID: "organization/0b9de9a3-8403-4ca6-aba8-fca752f42100/" + + "project/0b9de9a3-8403-4ca6-aba8-fca752f42100/" + + "consul.cluster/new-cluster-id", + + // New clusters should have received and persisted the whole suite of config. + verifyFn: func(t *testing.T, rc *config.RuntimeConfig) { + dir := filepath.Join(rc.DataDir, constants.SubDir) + + entries, err := os.ReadDir(dir) + require.NoError(t, err) + require.Len(t, entries, 6) + + files := []string{ + filepath.Join(dir, bootstrap.ConfigFileName), + filepath.Join(dir, bootstrap.CAFileName), + filepath.Join(dir, bootstrap.CertFileName), + filepath.Join(dir, bootstrap.KeyFileName), + filepath.Join(dir, bootstrap.TokenFileName), + filepath.Join(dir, bootstrap.SuccessFileName), + } + for _, name := range files { + _, err := os.Stat(name) + require.NoError(t, err) + } + + require.Equal(t, filepath.Join(dir, bootstrap.CertFileName), rc.TLS.HTTPS.CertFile) + require.Equal(t, filepath.Join(dir, bootstrap.KeyFileName), rc.TLS.HTTPS.KeyFile) + require.Equal(t, filepath.Join(dir, bootstrap.CAFileName), rc.TLS.HTTPS.CAFile) + + cert, key, caCerts, err := bootstrap.LoadCerts(dir) + require.NoError(t, err) + + require.NoError(t, bootstrap.ValidateTLSCerts(cert, key, caCerts)) + }, + }, + "existing cluster": { + resourceID: "organization/0b9de9a3-8403-4ca6-aba8-fca752f42100/" + + "project/0b9de9a3-8403-4ca6-aba8-fca752f42100/" + + "consul.cluster/" + bootstrap.TestExistingClusterID, + + // Existing clusters should have only received and persisted the management token. + verifyFn: func(t *testing.T, rc *config.RuntimeConfig) { + dir := filepath.Join(rc.DataDir, constants.SubDir) + + entries, err := os.ReadDir(dir) + require.NoError(t, err) + require.Len(t, entries, 3) + + files := []string{ + filepath.Join(dir, bootstrap.TokenFileName), + filepath.Join(dir, bootstrap.SuccessFileName), + filepath.Join(dir, bootstrap.ConfigFileName), + } + for _, name := range files { + _, err := os.Stat(name) + require.NoError(t, err) + } + }, + }, + } + + for name, tc := range tt { + t.Run(name, func(t *testing.T) { + run(t, tc) + }) + } +} + +func TestValidatePersistedConfig(t *testing.T) { + type testCase struct { + configContents string + expectErr string + } + + run := func(t *testing.T, tc testCase) { + dataDir, err := os.MkdirTemp(os.TempDir(), "load-bootstrap-test-") + require.NoError(t, err) + t.Cleanup(func() { os.RemoveAll(dataDir) }) + + dir := filepath.Join(dataDir, constants.SubDir) + require.NoError(t, lib.EnsurePath(dir, true)) + + if tc.configContents != "" { + name := filepath.Join(dir, bootstrap.ConfigFileName) + require.NoError(t, os.WriteFile(name, []byte(tc.configContents), 0600)) + } + + err = validatePersistedConfig(dataDir) + if tc.expectErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectErr) + } else { + require.NoError(t, err) + } + } + + tt := map[string]testCase{ + "valid": { + configContents: `{"bootstrap_expect": 1, "cloud": {"resource_id": "id"}}`, + }, + "invalid config key": { + configContents: `{"not_a_consul_agent_config_field": "zap"}`, + expectErr: "invalid config key not_a_consul_agent_config_field", + }, + "invalid format": { + configContents: `{"not_json" = "invalid"}`, + expectErr: "invalid character '=' after object key", + }, + "missing configuration file": { + expectErr: "no such file or directory", + }, + } + + for name, tc := range tt { + t.Run(name, func(t *testing.T) { + run(t, tc) + }) + } +} diff --git a/agent/hcp/bootstrap/constants/constants.go b/agent/hcp/bootstrap/constants/constants.go new file mode 100644 index 000000000000..1f39bf4712da --- /dev/null +++ b/agent/hcp/bootstrap/constants/constants.go @@ -0,0 +1,9 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +// Package constants declares some constants for use in the HCP bootstrapping +// process. It is in its own package with no other dependencies in order +// to avoid a dependency cycle. +package constants + +const SubDir = "hcp-config" diff --git a/agent/hcp/client/client.go b/agent/hcp/client/client.go index c0526c0e4acf..41f3eb97749e 100644 --- a/agent/hcp/client/client.go +++ b/agent/hcp/client/client.go @@ -5,12 +5,16 @@ package client import ( "context" + "errors" "fmt" + "net/http" + "net/url" "strconv" "time" httptransport "github.com/go-openapi/runtime/client" "github.com/go-openapi/strfmt" + "golang.org/x/oauth2" hcptelemetry "github.com/hashicorp/hcp-sdk-go/clients/cloud-consul-telemetry-gateway/preview/2023-04-14/client/consul_telemetry_service" hcpgnm "github.com/hashicorp/hcp-sdk-go/clients/cloud-global-network-manager-service/preview/2022-02-15/client/global_network_manager_service" @@ -31,8 +35,10 @@ const metricsGatewayPath = "/v1/metrics" type Client interface { FetchBootstrap(ctx context.Context) (*BootstrapConfig, error) FetchTelemetryConfig(ctx context.Context) (*TelemetryConfig, error) + GetObservabilitySecret(ctx context.Context) (clientID, clientSecret string, err error) PushServerStatus(ctx context.Context, status *ServerStatus) error DiscoverServers(ctx context.Context) ([]string, error) + GetCluster(ctx context.Context) (*Cluster, error) } type BootstrapConfig struct { @@ -46,6 +52,12 @@ type BootstrapConfig struct { ManagementToken string } +type Cluster struct { + Name string + HCPPortalURL string + AccessLevel *gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevel +} + type hcpClient struct { hc *httptransport.Runtime cfg config.CloudConfig @@ -117,9 +129,8 @@ func (c *hcpClient) FetchBootstrap(ctx context.Context) (*BootstrapConfig, error resp, err := c.gnm.AgentBootstrapConfig(params, nil) if err != nil { - return nil, err + return nil, decodeError(err) } - return bootstrapConfigFromHCP(resp.Payload), nil } @@ -155,6 +166,8 @@ func (c *hcpClient) PushServerStatus(ctx context.Context, s *ServerStatus) error return err } +// ServerStatus is used to collect server status information in order to push +// to HCP. Fields should mirror HashicorpCloudGlobalNetworkManager20220215ServerState type ServerStatus struct { ID string Name string @@ -164,10 +177,15 @@ type ServerStatus struct { RPCPort int Datacenter string - Autopilot ServerAutopilot - Raft ServerRaft - TLS ServerTLSInfo - ACL ServerACLInfo + Autopilot ServerAutopilot + Raft ServerRaft + ACL ServerACLInfo + ServerTLSMetadata ServerTLSMetadata + + // TODO: TLS will be deprecated in favor of ServerTLSInfo in GNM. Handle + // removal in a subsequent PR + // https://hashicorp.atlassian.net/browse/CC-7015 + TLS ServerTLSInfo ScadaStatus string } @@ -191,20 +209,47 @@ type ServerACLInfo struct { Enabled bool } +// ServerTLSInfo mirrors HashicorpCloudGlobalNetworkManager20220215TLSInfo type ServerTLSInfo struct { - Enabled bool - CertExpiry time.Time - CertName string - CertSerial string - VerifyIncoming bool - VerifyOutgoing bool - VerifyServerHostname bool + Enabled bool + CertExpiry time.Time + CertIssuer string + CertName string + CertSerial string + CertificateAuthorities []CertificateMetadata + VerifyIncoming bool + VerifyOutgoing bool + VerifyServerHostname bool +} + +// ServerTLSMetadata mirrors HashicorpCloudGlobalNetworkManager20220215ServerTLSMetadata +type ServerTLSMetadata struct { + InternalRPC ServerTLSInfo +} + +// CertificateMetadata mirrors HashicorpCloudGlobalNetworkManager20220215CertificateMetadata +type CertificateMetadata struct { + CertExpiry time.Time + CertName string + CertSerial string } func serverStatusToHCP(s *ServerStatus) *gnmmod.HashicorpCloudGlobalNetworkManager20220215ServerState { if s == nil { return nil } + + // Convert CA metadata + caCerts := make([]*gnmmod.HashicorpCloudGlobalNetworkManager20220215CertificateMetadata, + len(s.ServerTLSMetadata.InternalRPC.CertificateAuthorities)) + for ix, ca := range s.ServerTLSMetadata.InternalRPC.CertificateAuthorities { + caCerts[ix] = &gnmmod.HashicorpCloudGlobalNetworkManager20220215CertificateMetadata{ + CertExpiry: strfmt.DateTime(ca.CertExpiry), + CertName: ca.CertName, + CertSerial: ca.CertSerial, + } + } + return &gnmmod.HashicorpCloudGlobalNetworkManager20220215ServerState{ Autopilot: &gnmmod.HashicorpCloudGlobalNetworkManager20220215AutoPilotInfo{ FailureTolerance: int32(s.Autopilot.FailureTolerance), @@ -225,6 +270,9 @@ func serverStatusToHCP(s *ServerStatus) *gnmmod.HashicorpCloudGlobalNetworkManag }, RPCPort: int32(s.RPCPort), TLS: &gnmmod.HashicorpCloudGlobalNetworkManager20220215TLSInfo{ + // TODO: remove TLS in preference for ServerTLSMetadata.InternalRPC + // when deprecation path is ready + // https://hashicorp.atlassian.net/browse/CC-7015 CertExpiry: strfmt.DateTime(s.TLS.CertExpiry), CertName: s.TLS.CertName, CertSerial: s.TLS.CertSerial, @@ -233,6 +281,19 @@ func serverStatusToHCP(s *ServerStatus) *gnmmod.HashicorpCloudGlobalNetworkManag VerifyOutgoing: s.TLS.VerifyOutgoing, VerifyServerHostname: s.TLS.VerifyServerHostname, }, + ServerTLS: &gnmmod.HashicorpCloudGlobalNetworkManager20220215ServerTLSMetadata{ + InternalRPC: &gnmmod.HashicorpCloudGlobalNetworkManager20220215TLSInfo{ + CertExpiry: strfmt.DateTime(s.ServerTLSMetadata.InternalRPC.CertExpiry), + CertIssuer: s.ServerTLSMetadata.InternalRPC.CertIssuer, + CertName: s.ServerTLSMetadata.InternalRPC.CertName, + CertSerial: s.ServerTLSMetadata.InternalRPC.CertSerial, + Enabled: s.ServerTLSMetadata.InternalRPC.Enabled, + VerifyIncoming: s.ServerTLSMetadata.InternalRPC.VerifyIncoming, + VerifyOutgoing: s.ServerTLSMetadata.InternalRPC.VerifyOutgoing, + VerifyServerHostname: s.ServerTLSMetadata.InternalRPC.VerifyServerHostname, + CertificateAuthorities: caCerts, + }, + }, Version: s.Version, ScadaStatus: s.ScadaStatus, ACL: &gnmmod.HashicorpCloudGlobalNetworkManager20220215ACLInfo{ @@ -261,3 +322,70 @@ func (c *hcpClient) DiscoverServers(ctx context.Context) ([]string, error) { return servers, nil } + +func (c *hcpClient) GetCluster(ctx context.Context) (*Cluster, error) { + params := hcpgnm.NewGetClusterParamsWithContext(ctx). + WithID(c.resource.ID). + WithLocationOrganizationID(c.resource.Organization). + WithLocationProjectID(c.resource.Project) + + resp, err := c.gnm.GetCluster(params, nil) + if err != nil { + return nil, decodeError(err) + } + + return clusterFromHCP(resp.Payload), nil +} + +func clusterFromHCP(payload *gnmmod.HashicorpCloudGlobalNetworkManager20220215GetClusterResponse) *Cluster { + return &Cluster{ + Name: payload.Cluster.ID, + AccessLevel: payload.Cluster.ConsulAccessLevel, + HCPPortalURL: payload.Cluster.HcpPortalURL, + } +} + +func decodeError(err error) error { + // Determine the code from the type of error + var code int + switch e := err.(type) { + case *url.Error: + oauthErr, ok := errors.Unwrap(e.Err).(*oauth2.RetrieveError) + if ok { + code = oauthErr.Response.StatusCode + } + case *hcpgnm.AgentBootstrapConfigDefault: + code = e.Code() + case *hcpgnm.GetClusterDefault: + code = e.Code() + } + + // Return specific error for codes if relevant + switch code { + case http.StatusUnauthorized: + return ErrUnauthorized + case http.StatusForbidden: + return ErrForbidden + } + + return err +} + +func (c *hcpClient) GetObservabilitySecret(ctx context.Context) (string, string, error) { + params := hcpgnm.NewGetObservabilitySecretParamsWithContext(ctx). + WithID(c.resource.ID). + WithLocationOrganizationID(c.resource.Organization). + WithLocationProjectID(c.resource.Project) + + resp, err := c.gnm.GetObservabilitySecret(params, nil) + if err != nil { + return "", "", err + } + + if len(resp.GetPayload().Keys) == 0 { + return "", "", fmt.Errorf("no observability keys returned for cluster") + } + + key := resp.GetPayload().Keys[len(resp.GetPayload().Keys)-1] + return key.ClientID, key.ClientSecret, nil +} diff --git a/agent/hcp/client/client_test.go b/agent/hcp/client/client_test.go index 5571630ad45a..c9c5bc63f2dd 100644 --- a/agent/hcp/client/client_test.go +++ b/agent/hcp/client/client_test.go @@ -32,6 +32,9 @@ func (m *mockTGW) QueryRangeBatch(params *hcptelemetry.QueryRangeBatchParams, au return hcptelemetry.NewQueryRangeBatchOK(), nil } func (m *mockTGW) SetTransport(transport runtime.ClientTransport) {} +func (m *mockTGW) GetServiceTopology(params *hcptelemetry.GetServiceTopologyParams, authInfo runtime.ClientAuthInfoWriter, opts ...hcptelemetry.ClientOption) (*hcptelemetry.GetServiceTopologyOK, error) { + return hcptelemetry.NewGetServiceTopologyOK(), nil +} type expectedTelemetryCfg struct { endpoint string diff --git a/agent/hcp/client/errors.go b/agent/hcp/client/errors.go new file mode 100644 index 000000000000..5f0716979247 --- /dev/null +++ b/agent/hcp/client/errors.go @@ -0,0 +1,11 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import "errors" + +var ( + ErrUnauthorized = errors.New("unauthorized") + ErrForbidden = errors.New("forbidden") +) diff --git a/agent/hcp/client/http_client.go b/agent/hcp/client/http_client.go new file mode 100644 index 000000000000..4854f8c022cd --- /dev/null +++ b/agent/hcp/client/http_client.go @@ -0,0 +1,57 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import ( + "crypto/tls" + "net/http" + "time" + + "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-retryablehttp" + "golang.org/x/oauth2" +) + +const ( + // HTTP Client config + defaultStreamTimeout = 15 * time.Second + + // Retry config + // TODO: Eventually, we'd like to configure these values dynamically. + defaultRetryWaitMin = 1 * time.Second + defaultRetryWaitMax = 15 * time.Second + // defaultRetryMax is set to 0 to turn off retry functionality, until dynamic configuration is possible. + // This is to circumvent any spikes in load that may cause or exacerbate server-side issues for now. + defaultRetryMax = 0 +) + +// NewHTTPClient configures the retryable HTTP client. +func NewHTTPClient(tlsCfg *tls.Config, source oauth2.TokenSource) *retryablehttp.Client { + tlsTransport := cleanhttp.DefaultPooledTransport() + tlsTransport.TLSClientConfig = tlsCfg + + var transport http.RoundTripper = &oauth2.Transport{ + Base: tlsTransport, + Source: source, + } + + client := &http.Client{ + Transport: transport, + Timeout: defaultStreamTimeout, + } + + retryClient := &retryablehttp.Client{ + HTTPClient: client, + // We already log failed requests elsewhere, we pass a null logger here to avoid redundant logs. + Logger: hclog.NewNullLogger(), + RetryWaitMin: defaultRetryWaitMin, + RetryWaitMax: defaultRetryWaitMax, + RetryMax: defaultRetryMax, + CheckRetry: retryablehttp.DefaultRetryPolicy, + Backoff: retryablehttp.DefaultBackoff, + } + + return retryClient +} diff --git a/agent/hcp/client/http_client_test.go b/agent/hcp/client/http_client_test.go new file mode 100644 index 000000000000..b8971040892a --- /dev/null +++ b/agent/hcp/client/http_client_test.go @@ -0,0 +1,30 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/hashicorp/consul/agent/hcp/config" + "github.com/stretchr/testify/require" +) + +func TestNewHTTPClient(t *testing.T) { + mockCfg := config.MockCloudCfg{} + mockHCPCfg, err := mockCfg.HCPConfig() + require.NoError(t, err) + + client := NewHTTPClient(mockHCPCfg.APITLSConfig(), mockHCPCfg) + require.NotNil(t, client) + + var req *http.Request + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + req = r + })) + _, err = client.Get(srv.URL) + require.NoError(t, err) + require.Equal(t, "Bearer test-token", req.Header.Get("Authorization")) +} diff --git a/agent/hcp/client/metrics_client.go b/agent/hcp/client/metrics_client.go index b3c1c6a6b3dc..47dd7d52800f 100644 --- a/agent/hcp/client/metrics_client.go +++ b/agent/hcp/client/metrics_client.go @@ -6,126 +6,55 @@ package client import ( "bytes" "context" + "errors" "fmt" "io" "net/http" - "time" - "github.com/hashicorp/go-cleanhttp" - "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-retryablehttp" - hcpcfg "github.com/hashicorp/hcp-sdk-go/config" - "github.com/hashicorp/hcp-sdk-go/resource" colmetricpb "go.opentelemetry.io/proto/otlp/collector/metrics/v1" metricpb "go.opentelemetry.io/proto/otlp/metrics/v1" - "golang.org/x/oauth2" "google.golang.org/protobuf/proto" "github.com/hashicorp/consul/agent/hcp/telemetry" - "github.com/hashicorp/consul/version" ) const ( - // HTTP Client config - defaultStreamTimeout = 15 * time.Second - - // Retry config - // TODO: Eventually, we'd like to configure these values dynamically. - defaultRetryWaitMin = 1 * time.Second - defaultRetryWaitMax = 15 * time.Second - // defaultRetryMax is set to 0 to turn off retry functionality, until dynamic configuration is possible. - // This is to circumvent any spikes in load that may cause or exacerbate server-side issues for now. - defaultRetryMax = 0 - // defaultErrRespBodyLength refers to the max character length of the body on a failure to export metrics. // anything beyond we will truncate. defaultErrRespBodyLength = 100 ) -// cloudConfig represents cloud config for TLS abstracted in an interface for easy testing. -type CloudConfig interface { - HCPConfig(opts ...hcpcfg.HCPConfigOption) (hcpcfg.HCPConfig, error) - Resource() (resource.Resource, error) +// MetricsClientProvider provides the retryable HTTP client and headers to use for exporting metrics +// by the metrics client. +type MetricsClientProvider interface { + GetHTTPClient() *retryablehttp.Client + GetHeader() http.Header } // otlpClient is an implementation of MetricsClient with a retryable http client for retries and to honor throttle. // It also holds default HTTP headers to add to export requests. type otlpClient struct { - client *retryablehttp.Client - header *http.Header + provider MetricsClientProvider } // NewMetricsClient returns a configured MetricsClient. // The current implementation uses otlpClient to provide retry functionality. -func NewMetricsClient(ctx context.Context, cfg CloudConfig) (telemetry.MetricsClient, error) { - if cfg == nil { - return nil, fmt.Errorf("failed to init telemetry client: provide valid cloudCfg (Cloud Configuration for TLS)") - } - - if ctx == nil { - return nil, fmt.Errorf("failed to init telemetry client: provide a valid context") - } - - logger := hclog.FromContext(ctx) - - c, err := newHTTPClient(cfg, logger) - if err != nil { - return nil, fmt.Errorf("failed to init telemetry client: %v", err) - } - - r, err := cfg.Resource() - if err != nil { - return nil, fmt.Errorf("failed to init telemetry client: %v", err) - } - - header := make(http.Header) - header.Set("content-type", "application/x-protobuf") - header.Set("x-hcp-resource-id", r.String()) - header.Set("x-channel", fmt.Sprintf("consul/%s", version.GetHumanVersion())) - +func NewMetricsClient(ctx context.Context, provider MetricsClientProvider) telemetry.MetricsClient { return &otlpClient{ - client: c, - header: &header, - }, nil -} - -// newHTTPClient configures the retryable HTTP client. -func newHTTPClient(cloudCfg CloudConfig, logger hclog.Logger) (*retryablehttp.Client, error) { - hcpCfg, err := cloudCfg.HCPConfig() - if err != nil { - return nil, err + provider: provider, } - - tlsTransport := cleanhttp.DefaultPooledTransport() - tlsTransport.TLSClientConfig = hcpCfg.APITLSConfig() - - var transport http.RoundTripper = &oauth2.Transport{ - Base: tlsTransport, - Source: hcpCfg, - } - - client := &http.Client{ - Transport: transport, - Timeout: defaultStreamTimeout, - } - - retryClient := &retryablehttp.Client{ - HTTPClient: client, - Logger: logger.Named("hcp_telemetry_client"), - RetryWaitMin: defaultRetryWaitMin, - RetryWaitMax: defaultRetryWaitMax, - RetryMax: defaultRetryMax, - CheckRetry: retryablehttp.DefaultRetryPolicy, - Backoff: retryablehttp.DefaultBackoff, - } - - return retryClient, nil } // ExportMetrics is the single method exposed by MetricsClient to export OTLP metrics to the desired HCP endpoint. // The endpoint is configurable as the endpoint can change during periodic refresh of CCM telemetry config. // By configuring the endpoint here, we can re-use the same client and override the endpoint when making a request. func (o *otlpClient) ExportMetrics(ctx context.Context, protoMetrics *metricpb.ResourceMetrics, endpoint string) error { + client := o.provider.GetHTTPClient() + if client == nil { + return errors.New("http client not configured") + } + pbRequest := &colmetricpb.ExportMetricsServiceRequest{ ResourceMetrics: []*metricpb.ResourceMetrics{protoMetrics}, } @@ -139,9 +68,9 @@ func (o *otlpClient) ExportMetrics(ctx context.Context, protoMetrics *metricpb.R if err != nil { return fmt.Errorf("failed to create request: %w", err) } - req.Header = *o.header + req.Header = o.provider.GetHeader() - resp, err := o.client.Do(req.WithContext(ctx)) + resp, err := client.Do(req.WithContext(ctx)) if err != nil { return fmt.Errorf("failed to post metrics: %w", err) } diff --git a/agent/hcp/client/metrics_client_test.go b/agent/hcp/client/metrics_client_test.go index 20a5f010ec4c..cea6efca3750 100644 --- a/agent/hcp/client/metrics_client_test.go +++ b/agent/hcp/client/metrics_client_test.go @@ -5,7 +5,6 @@ package client import ( "context" - "fmt" "math/rand" "net/http" "net/http/httptest" @@ -16,55 +15,26 @@ import ( metricpb "go.opentelemetry.io/proto/otlp/metrics/v1" "google.golang.org/protobuf/proto" - "github.com/hashicorp/consul/version" + "github.com/hashicorp/go-retryablehttp" ) -func TestNewMetricsClient(t *testing.T) { - for name, test := range map[string]struct { - wantErr string - cfg CloudConfig - ctx context.Context - }{ - "success": { - cfg: &MockCloudCfg{}, - ctx: context.Background(), - }, - "failsWithoutCloudCfg": { - wantErr: "failed to init telemetry client: provide valid cloudCfg (Cloud Configuration for TLS)", - cfg: nil, - ctx: context.Background(), - }, - "failsWithoutContext": { - wantErr: "failed to init telemetry client: provide a valid context", - cfg: MockCloudCfg{}, - ctx: nil, - }, - "failsHCPConfig": { - wantErr: "failed to init telemetry client", - cfg: MockCloudCfg{ - ConfigErr: fmt.Errorf("test bad hcp config"), - }, - ctx: context.Background(), - }, - "failsBadResource": { - wantErr: "failed to init telemetry client", - cfg: MockCloudCfg{ - ResourceErr: fmt.Errorf("test bad resource"), - }, - ctx: context.Background(), - }, - } { - t.Run(name, func(t *testing.T) { - client, err := NewMetricsClient(test.ctx, test.cfg) - if test.wantErr != "" { - require.Error(t, err) - require.Contains(t, err.Error(), test.wantErr) - return - } +type mockClientProvider struct { + client *retryablehttp.Client + header *http.Header +} - require.Nil(t, err) - require.NotNil(t, client) - }) +func (m *mockClientProvider) GetHTTPClient() *retryablehttp.Client { return m.client } +func (m *mockClientProvider) GetHeader() http.Header { return m.header.Clone() } + +func newMockClientProvider() *mockClientProvider { + header := make(http.Header) + header.Set("content-type", "application/x-protobuf") + + client := retryablehttp.NewClient() + + return &mockClientProvider{ + header: &header, + client: client, } } @@ -83,6 +53,7 @@ func TestExportMetrics(t *testing.T) { wantErr string status int largeBodyError bool + mutateProvider func(*mockClientProvider) }{ "success": { status: http.StatusOK, @@ -96,14 +67,17 @@ func TestExportMetrics(t *testing.T) { wantErr: "failed to export metrics: code 400", largeBodyError: true, }, + "failsWithClientNotConfigured": { + mutateProvider: func(m *mockClientProvider) { + m.client = nil + }, + wantErr: "http client not configured", + }, } { t.Run(name, func(t *testing.T) { randomBody := randStringRunes(1000) srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { require.Equal(t, r.Header.Get("content-type"), "application/x-protobuf") - require.Equal(t, r.Header.Get("x-hcp-resource-id"), testResourceID) - require.Equal(t, r.Header.Get("x-channel"), fmt.Sprintf("consul/%s", version.GetHumanVersion())) - require.Equal(t, r.Header.Get("Authorization"), "Bearer test-token") body := colpb.ExportMetricsServiceResponse{} bytes, err := proto.Marshal(&body) @@ -121,12 +95,15 @@ func TestExportMetrics(t *testing.T) { })) defer srv.Close() - client, err := NewMetricsClient(context.Background(), MockCloudCfg{}) - require.NoError(t, err) + provider := newMockClientProvider() + if test.mutateProvider != nil { + test.mutateProvider(provider) + } + client := NewMetricsClient(context.Background(), provider) ctx := context.Background() metrics := &metricpb.ResourceMetrics{} - err = client.ExportMetrics(ctx, metrics, srv.URL) + err := client.ExportMetrics(ctx, metrics, srv.URL) if test.wantErr != "" { require.Error(t, err) diff --git a/agent/hcp/client/mock_Client.go b/agent/hcp/client/mock_Client.go index 06853ceb86f7..8e5437c22ddf 100644 --- a/agent/hcp/client/mock_Client.go +++ b/agent/hcp/client/mock_Client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.22.1. DO NOT EDIT. +// Code generated by mockery v2.39.2. DO NOT EDIT. package client @@ -25,6 +25,10 @@ func (_m *MockClient) EXPECT() *MockClient_Expecter { func (_m *MockClient) DiscoverServers(ctx context.Context) ([]string, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for DiscoverServers") + } + var r0 []string var r1 error if rf, ok := ret.Get(0).(func(context.Context) ([]string, error)); ok { @@ -79,6 +83,10 @@ func (_c *MockClient_DiscoverServers_Call) RunAndReturn(run func(context.Context func (_m *MockClient) FetchBootstrap(ctx context.Context) (*BootstrapConfig, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for FetchBootstrap") + } + var r0 *BootstrapConfig var r1 error if rf, ok := ret.Get(0).(func(context.Context) (*BootstrapConfig, error)); ok { @@ -133,6 +141,10 @@ func (_c *MockClient_FetchBootstrap_Call) RunAndReturn(run func(context.Context) func (_m *MockClient) FetchTelemetryConfig(ctx context.Context) (*TelemetryConfig, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for FetchTelemetryConfig") + } + var r0 *TelemetryConfig var r1 error if rf, ok := ret.Get(0).(func(context.Context) (*TelemetryConfig, error)); ok { @@ -183,10 +195,135 @@ func (_c *MockClient_FetchTelemetryConfig_Call) RunAndReturn(run func(context.Co return _c } +// GetCluster provides a mock function with given fields: ctx +func (_m *MockClient) GetCluster(ctx context.Context) (*Cluster, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetCluster") + } + + var r0 *Cluster + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*Cluster, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *Cluster); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*Cluster) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockClient_GetCluster_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCluster' +type MockClient_GetCluster_Call struct { + *mock.Call +} + +// GetCluster is a helper method to define mock.On call +// - ctx context.Context +func (_e *MockClient_Expecter) GetCluster(ctx interface{}) *MockClient_GetCluster_Call { + return &MockClient_GetCluster_Call{Call: _e.mock.On("GetCluster", ctx)} +} + +func (_c *MockClient_GetCluster_Call) Run(run func(ctx context.Context)) *MockClient_GetCluster_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *MockClient_GetCluster_Call) Return(_a0 *Cluster, _a1 error) *MockClient_GetCluster_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockClient_GetCluster_Call) RunAndReturn(run func(context.Context) (*Cluster, error)) *MockClient_GetCluster_Call { + _c.Call.Return(run) + return _c +} + +// GetObservabilitySecret provides a mock function with given fields: ctx +func (_m *MockClient) GetObservabilitySecret(ctx context.Context) (string, string, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetObservabilitySecret") + } + + var r0 string + var r1 string + var r2 error + if rf, ok := ret.Get(0).(func(context.Context) (string, string, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) string); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(context.Context) string); ok { + r1 = rf(ctx) + } else { + r1 = ret.Get(1).(string) + } + + if rf, ok := ret.Get(2).(func(context.Context) error); ok { + r2 = rf(ctx) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MockClient_GetObservabilitySecret_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetObservabilitySecret' +type MockClient_GetObservabilitySecret_Call struct { + *mock.Call +} + +// GetObservabilitySecret is a helper method to define mock.On call +// - ctx context.Context +func (_e *MockClient_Expecter) GetObservabilitySecret(ctx interface{}) *MockClient_GetObservabilitySecret_Call { + return &MockClient_GetObservabilitySecret_Call{Call: _e.mock.On("GetObservabilitySecret", ctx)} +} + +func (_c *MockClient_GetObservabilitySecret_Call) Run(run func(ctx context.Context)) *MockClient_GetObservabilitySecret_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *MockClient_GetObservabilitySecret_Call) Return(clientID string, clientSecret string, err error) *MockClient_GetObservabilitySecret_Call { + _c.Call.Return(clientID, clientSecret, err) + return _c +} + +func (_c *MockClient_GetObservabilitySecret_Call) RunAndReturn(run func(context.Context) (string, string, error)) *MockClient_GetObservabilitySecret_Call { + _c.Call.Return(run) + return _c +} + // PushServerStatus provides a mock function with given fields: ctx, status func (_m *MockClient) PushServerStatus(ctx context.Context, status *ServerStatus) error { ret := _m.Called(ctx, status) + if len(ret) == 0 { + panic("no return value specified for PushServerStatus") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *ServerStatus) error); ok { r0 = rf(ctx, status) @@ -226,13 +363,12 @@ func (_c *MockClient_PushServerStatus_Call) RunAndReturn(run func(context.Contex return _c } -type mockConstructorTestingTNewMockClient interface { +// NewMockClient creates a new instance of MockClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockClient(t interface { mock.TestingT Cleanup(func()) -} - -// NewMockClient creates a new instance of MockClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewMockClient(t mockConstructorTestingTNewMockClient) *MockClient { +}) *MockClient { mock := &MockClient{} mock.Mock.Test(t) diff --git a/agent/hcp/config/config.go b/agent/hcp/config/config.go index 59977ef46f37..420af129adda 100644 --- a/agent/hcp/config/config.go +++ b/agent/hcp/config/config.go @@ -11,6 +11,13 @@ import ( "github.com/hashicorp/hcp-sdk-go/resource" ) +// CloudConfigurer abstracts the cloud config methods needed to connect to HCP +// in an interface for easier testing. +type CloudConfigurer interface { + HCPConfig(opts ...hcpcfg.HCPConfigOption) (hcpcfg.HCPConfig, error) + Resource() (resource.Resource, error) +} + // CloudConfig defines configuration for connecting to HCP services type CloudConfig struct { ResourceID string @@ -39,6 +46,8 @@ func (c *CloudConfig) Resource() (resource.Resource, error) { return resource.FromString(c.ResourceID) } +// HCPConfig returns a configuration to use with the HCP SDK. It assumes that the environment +// variables for the HCP configuration have already been loaded and set in the CloudConfig. func (c *CloudConfig) HCPConfig(opts ...hcpcfg.HCPConfigOption) (hcpcfg.HCPConfig, error) { if c.TLSConfig == nil { c.TLSConfig = &tls.Config{} @@ -55,6 +64,59 @@ func (c *CloudConfig) HCPConfig(opts ...hcpcfg.HCPConfigOption) (hcpcfg.HCPConfi if c.ScadaAddress != "" { opts = append(opts, hcpcfg.WithSCADA(c.ScadaAddress, c.TLSConfig)) } - opts = append(opts, hcpcfg.FromEnv(), hcpcfg.WithoutBrowserLogin()) + opts = append(opts, hcpcfg.WithoutBrowserLogin()) return hcpcfg.NewHCPConfig(opts...) } + +// IsConfigured returns whether the cloud configuration has been set either +// in the configuration file or via environment variables. +func (c *CloudConfig) IsConfigured() bool { + return c.ResourceID != "" && c.ClientID != "" && c.ClientSecret != "" +} + +// Merge returns a cloud configuration that is the combined the values of +// two configurations. +func Merge(o CloudConfig, n CloudConfig) CloudConfig { + c := o + if n.ResourceID != "" { + c.ResourceID = n.ResourceID + } + + if n.ClientID != "" { + c.ClientID = n.ClientID + } + + if n.ClientSecret != "" { + c.ClientSecret = n.ClientSecret + } + + if n.Hostname != "" { + c.Hostname = n.Hostname + } + + if n.AuthURL != "" { + c.AuthURL = n.AuthURL + } + + if n.ScadaAddress != "" { + c.ScadaAddress = n.ScadaAddress + } + + if n.ManagementToken != "" { + c.ManagementToken = n.ManagementToken + } + + if n.TLSConfig != nil { + c.TLSConfig = n.TLSConfig + } + + if n.NodeID != "" { + c.NodeID = n.NodeID + } + + if n.NodeName != "" { + c.NodeName = n.NodeName + } + + return c +} diff --git a/agent/hcp/config/config_test.go b/agent/hcp/config/config_test.go new file mode 100644 index 000000000000..ca07d4d94eaa --- /dev/null +++ b/agent/hcp/config/config_test.go @@ -0,0 +1,82 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package config + +import ( + "crypto/tls" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestMerge(t *testing.T) { + oldCfg := CloudConfig{ + ResourceID: "old-resource-id", + ClientID: "old-client-id", + ClientSecret: "old-client-secret", + Hostname: "old-hostname", + AuthURL: "old-auth-url", + ScadaAddress: "old-scada-address", + ManagementToken: "old-token", + TLSConfig: &tls.Config{ + ServerName: "old-server-name", + }, + NodeID: "old-node-id", + NodeName: "old-node-name", + } + + newCfg := CloudConfig{ + ResourceID: "new-resource-id", + ClientID: "new-client-id", + ClientSecret: "new-client-secret", + Hostname: "new-hostname", + AuthURL: "new-auth-url", + ScadaAddress: "new-scada-address", + ManagementToken: "new-token", + TLSConfig: &tls.Config{ + ServerName: "new-server-name", + }, + NodeID: "new-node-id", + NodeName: "new-node-name", + } + + for name, tc := range map[string]struct { + newCfg CloudConfig + expectedCfg CloudConfig + }{ + "Empty": { + newCfg: CloudConfig{}, + expectedCfg: oldCfg, + }, + "All": { + newCfg: newCfg, + expectedCfg: newCfg, + }, + "Partial": { + newCfg: CloudConfig{ + ResourceID: newCfg.ResourceID, + ClientID: newCfg.ClientID, + ClientSecret: newCfg.ClientSecret, + ManagementToken: newCfg.ManagementToken, + }, + expectedCfg: CloudConfig{ + ResourceID: newCfg.ResourceID, + ClientID: newCfg.ClientID, + ClientSecret: newCfg.ClientSecret, + ManagementToken: newCfg.ManagementToken, + Hostname: oldCfg.Hostname, + AuthURL: oldCfg.AuthURL, + ScadaAddress: oldCfg.ScadaAddress, + TLSConfig: oldCfg.TLSConfig, + NodeID: oldCfg.NodeID, + NodeName: oldCfg.NodeName, + }, + }, + } { + t.Run(name, func(t *testing.T) { + merged := Merge(oldCfg, tc.newCfg) + require.Equal(t, tc.expectedCfg, merged) + }) + } +} diff --git a/agent/hcp/client/mock_CloudConfig.go b/agent/hcp/config/mock_CloudConfig.go similarity index 94% rename from agent/hcp/client/mock_CloudConfig.go rename to agent/hcp/config/mock_CloudConfig.go index 574f83e55fd5..e2c6ba0c53be 100644 --- a/agent/hcp/client/mock_CloudConfig.go +++ b/agent/hcp/config/mock_CloudConfig.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package client +package config import ( "crypto/tls" @@ -29,6 +29,7 @@ func (m *mockHCPCfg) SCADATLSConfig() *tls.Config { return &tls.Config{} } func (m *mockHCPCfg) APIAddress() string { return "" } func (m *mockHCPCfg) PortalURL() *url.URL { return &url.URL{} } func (m *mockHCPCfg) Profile() *profile.UserProfile { return nil } +func (m *mockHCPCfg) Logout() error { return nil } type MockCloudCfg struct { ConfigErr error diff --git a/agent/hcp/deps.go b/agent/hcp/deps.go index 7bf384747dbd..05e65708b6d1 100644 --- a/agent/hcp/deps.go +++ b/agent/hcp/deps.go @@ -9,6 +9,7 @@ import ( "github.com/armon/go-metrics" "github.com/hashicorp/go-hclog" + "go.opentelemetry.io/otel" "github.com/hashicorp/consul/agent/hcp/client" "github.com/hashicorp/consul/agent/hcp/config" @@ -18,53 +19,61 @@ import ( // Deps contains the interfaces that the rest of Consul core depends on for HCP integration. type Deps struct { - Client client.Client - Provider scada.Provider - Sink metrics.MetricSink + Config config.CloudConfig + Provider scada.Provider + Sink metrics.ShutdownSink + TelemetryProvider *hcpProviderImpl + DataDir string } -func NewDeps(cfg config.CloudConfig, logger hclog.Logger) (Deps, error) { +func NewDeps(cfg config.CloudConfig, logger hclog.Logger, dataDir string) (Deps, error) { ctx := context.Background() ctx = hclog.WithContext(ctx, logger) - hcpClient, err := client.NewClient(cfg) - if err != nil { - return Deps{}, fmt.Errorf("failed to init client: %w", err) - } - - provider, err := scada.New(cfg, logger.Named("scada")) + provider, err := scada.New(logger.Named("scada")) if err != nil { return Deps{}, fmt.Errorf("failed to init scada: %w", err) } - metricsClient, err := client.NewMetricsClient(ctx, &cfg) + metricsProvider := NewHCPProvider(ctx) if err != nil { - logger.Error("failed to init metrics client", "error", err) - return Deps{}, fmt.Errorf("failed to init metrics client: %w", err) + logger.Error("failed to init HCP metrics provider", "error", err) + return Deps{}, fmt.Errorf("failed to init HCP metrics provider: %w", err) } - sink, err := sink(ctx, metricsClient, NewHCPProvider(ctx, hcpClient)) + metricsClient := client.NewMetricsClient(ctx, metricsProvider) + + sink, err := newSink(ctx, metricsClient, metricsProvider) if err != nil { // Do not prevent server start if sink init fails, only log error. logger.Error("failed to init sink", "error", err) } return Deps{ - Client: hcpClient, - Provider: provider, - Sink: sink, + Config: cfg, + Provider: provider, + Sink: sink, + TelemetryProvider: metricsProvider, + DataDir: dataDir, }, nil } -// sink initializes an OTELSink which forwards Consul metrics to HCP. +// newSink initializes an OTELSink which forwards Consul metrics to HCP. // This step should not block server initialization, errors are returned, only to be logged. -func sink( +func newSink( ctx context.Context, metricsClient telemetry.MetricsClient, cfgProvider *hcpProviderImpl, -) (metrics.MetricSink, error) { +) (metrics.ShutdownSink, error) { logger := hclog.FromContext(ctx) + // Set the global OTEL error handler. Without this, on any failure to publish metrics in + // otelExporter.Export, the default OTEL handler logs to stderr without the formatting or group + // that hclog provides. Here we override that global error handler once so logs are + // in the standard format and include "hcp" in the group name like: + // 2024-02-06T22:35:19.072Z [ERROR] agent.hcp: failed to export metrics: failed to export metrics: code 404: 404 page not found + otel.SetErrorHandler(&otelErrorHandler{logger: logger}) + reader := telemetry.NewOTELReader(metricsClient, cfgProvider) sinkOpts := &telemetry.OTELSinkOpts{ Reader: reader, @@ -80,3 +89,11 @@ func sink( return sink, nil } + +type otelErrorHandler struct { + logger hclog.Logger +} + +func (o *otelErrorHandler) Handle(err error) { + o.logger.Error(err.Error()) +} diff --git a/agent/hcp/deps_test.go b/agent/hcp/deps_test.go index 7375dad68cb7..84a34dd697c2 100644 --- a/agent/hcp/deps_test.go +++ b/agent/hcp/deps_test.go @@ -21,7 +21,7 @@ func TestSink(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - s, err := sink(ctx, mockMetricsClient{}, &hcpProviderImpl{}) + s, err := newSink(ctx, mockMetricsClient{}, &hcpProviderImpl{}) require.NotNil(t, s) require.NoError(t, err) diff --git a/agent/hcp/link_watch.go b/agent/hcp/link_watch.go new file mode 100644 index 000000000000..b89ba942e465 --- /dev/null +++ b/agent/hcp/link_watch.go @@ -0,0 +1,68 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package hcp + +import ( + "context" + "time" + + "github.com/hashicorp/go-hclog" + + hcpctl "github.com/hashicorp/consul/internal/hcp" + "github.com/hashicorp/consul/lib/retry" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +type LinkEventHandler = func(context.Context, hclog.Logger, *pbresource.WatchEvent) + +func handleLinkEvents(ctx context.Context, logger hclog.Logger, watchClient pbresource.ResourceService_WatchListClient, linkEventHandler LinkEventHandler) { + for { + select { + case <-ctx.Done(): + logger.Debug("context canceled, exiting") + return + default: + watchEvent, err := watchClient.Recv() + + if err != nil { + logger.Error("error receiving link watch event", "error", err) + return + } + + linkEventHandler(ctx, logger, watchEvent) + } + } +} + +func RunHCPLinkWatcher( + ctx context.Context, logger hclog.Logger, client pbresource.ResourceServiceClient, linkEventHandler LinkEventHandler, +) { + errorBackoff := &retry.Waiter{ + MinFailures: 10, + MinWait: 0, + MaxWait: 1 * time.Minute, + } + for { + select { + case <-ctx.Done(): + logger.Debug("context canceled, exiting") + return + default: + watchClient, err := client.WatchList( + ctx, &pbresource.WatchListRequest{ + Type: pbhcp.LinkType, + NamePrefix: hcpctl.LinkName, + }, + ) + if err != nil { + logger.Error("failed to create watch on Link", "error", err) + errorBackoff.Wait(ctx) + continue + } + errorBackoff.Reset() + handleLinkEvents(ctx, logger, watchClient, linkEventHandler) + } + } +} diff --git a/agent/hcp/link_watch_test.go b/agent/hcp/link_watch_test.go new file mode 100644 index 000000000000..22d2204a817d --- /dev/null +++ b/agent/hcp/link_watch_test.go @@ -0,0 +1,101 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package hcp + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" + + "github.com/hashicorp/go-hclog" + + mockpbresource "github.com/hashicorp/consul/grpcmocks/proto-public/pbresource" + hcpctl "github.com/hashicorp/consul/internal/hcp" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// This tests that when we get a watch event from the Recv call, we get that same event on the +// output channel, then we +func TestLinkWatcher_Ok(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + + testWatchEvent := &pbresource.WatchEvent{} + mockWatchListClient := mockpbresource.NewResourceService_WatchListClient(t) + mockWatchListClient.EXPECT().Recv().Return(testWatchEvent, nil) + + eventCh := make(chan *pbresource.WatchEvent) + mockLinkHandler := func(_ context.Context, _ hclog.Logger, event *pbresource.WatchEvent) { + eventCh <- event + } + + client := mockpbresource.NewResourceServiceClient(t) + client.EXPECT().WatchList(mock.Anything, &pbresource.WatchListRequest{ + Type: pbhcp.LinkType, + NamePrefix: hcpctl.LinkName, + }).Return(mockWatchListClient, nil) + + go RunHCPLinkWatcher(ctx, hclog.Default(), client, mockLinkHandler) + + // Assert that the link handler is called with the testWatchEvent + receivedWatchEvent := <-eventCh + require.Equal(t, testWatchEvent, receivedWatchEvent) +} + +func TestLinkWatcher_RecvError(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + + // Our mock WatchListClient will simulate 5 errors, then will cancel the context. + // We expect RunHCPLinkWatcher to attempt to create the WatchListClient 6 times (initial attempt plus 5 retries) + // before exiting due to context cancellation. + mockWatchListClient := mockpbresource.NewResourceService_WatchListClient(t) + numFailures := 5 + failures := 0 + mockWatchListClient.EXPECT().Recv().RunAndReturn(func() (*pbresource.WatchEvent, error) { + if failures < numFailures { + failures++ + return nil, errors.New("unexpectedError") + } + defer cancel() + return &pbresource.WatchEvent{}, nil + }) + + client := mockpbresource.NewResourceServiceClient(t) + client.EXPECT().WatchList(mock.Anything, &pbresource.WatchListRequest{ + Type: pbhcp.LinkType, + NamePrefix: hcpctl.LinkName, + }).Return(mockWatchListClient, nil).Times(numFailures + 1) + + RunHCPLinkWatcher(ctx, hclog.Default(), client, func(_ context.Context, _ hclog.Logger, _ *pbresource.WatchEvent) {}) +} + +func TestLinkWatcher_WatchListError(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + + // Our mock WatchList will simulate 5 errors, then will cancel the context. + // We expect RunHCPLinkWatcher to attempt to create the WatchListClient 6 times (initial attempt plus 5 retries) + // before exiting due to context cancellation. + numFailures := 5 + failures := 0 + + client := mockpbresource.NewResourceServiceClient(t) + client.EXPECT().WatchList(mock.Anything, &pbresource.WatchListRequest{ + Type: pbhcp.LinkType, + NamePrefix: hcpctl.LinkName, + }).RunAndReturn(func(_ context.Context, _ *pbresource.WatchListRequest, _ ...grpc.CallOption) (pbresource.ResourceService_WatchListClient, error) { + if failures < numFailures { + failures++ + return nil, errors.New("unexpectedError") + } + defer cancel() + return mockpbresource.NewResourceService_WatchListClient(t), nil + }).Times(numFailures + 1) + + RunHCPLinkWatcher(ctx, hclog.Default(), client, func(_ context.Context, _ hclog.Logger, _ *pbresource.WatchEvent) {}) +} diff --git a/agent/hcp/manager.go b/agent/hcp/manager.go index a3664b0608df..8fb1ac67c852 100644 --- a/agent/hcp/manager.go +++ b/agent/hcp/manager.go @@ -5,12 +5,16 @@ package hcp import ( "context" + "reflect" "sync" "time" + "github.com/hashicorp/go-hclog" + hcpclient "github.com/hashicorp/consul/agent/hcp/client" + "github.com/hashicorp/consul/agent/hcp/config" + "github.com/hashicorp/consul/agent/hcp/scada" "github.com/hashicorp/consul/lib" - "github.com/hashicorp/go-hclog" ) var ( @@ -18,12 +22,21 @@ var ( defaultManagerMaxInterval = 75 * time.Minute ) -type ManagerConfig struct { - Client hcpclient.Client +var _ Manager = (*HCPManager)(nil) - StatusFn StatusCallback - MinInterval time.Duration - MaxInterval time.Duration +type ManagerConfig struct { + Client hcpclient.Client + CloudConfig config.CloudConfig + SCADAProvider scada.Provider + TelemetryProvider TelemetryProvider + + StatusFn StatusCallback + // Idempotent function to upsert the HCP management token. This will be called periodically in + // the manager's main loop. + ManagementTokenUpserterFn ManagementTokenUpserter + ManagementTokenDeleterFn ManagementTokenDeleter + MinInterval time.Duration + MaxInterval time.Duration Logger hclog.Logger } @@ -49,24 +62,36 @@ func (cfg *ManagerConfig) nextHeartbeat() time.Duration { } type StatusCallback func(context.Context) (hcpclient.ServerStatus, error) +type ManagementTokenUpserter func(name, secretId string) error +type ManagementTokenDeleter func(secretId string) error + +//go:generate mockery --name Manager --with-expecter --inpackage +type Manager interface { + Start(context.Context) error + Stop() error + GetCloudConfig() config.CloudConfig + UpdateConfig(hcpclient.Client, config.CloudConfig) +} -type Manager struct { +type HCPManager struct { logger hclog.Logger + running bool + runLock sync.RWMutex + cfg ManagerConfig cfgMu sync.RWMutex updateCh chan struct{} + stopCh chan struct{} // testUpdateSent is set by unit tests to signal when the manager's status update has triggered testUpdateSent chan struct{} } -// NewManager returns an initialized Manager with a zero configuration. It won't -// do anything until UpdateConfig is called with a config that provides -// credentials to contact HCP. -func NewManager(cfg ManagerConfig) *Manager { - return &Manager{ +// NewManager returns a Manager initialized with the given configuration. +func NewManager(cfg ManagerConfig) *HCPManager { + return &HCPManager{ logger: cfg.Logger, cfg: cfg, @@ -74,66 +99,162 @@ func NewManager(cfg ManagerConfig) *Manager { } } -// Run executes the Manager it's designed to be run in its own goroutine for -// the life of a server agent. It should be run even if HCP is not configured -// yet for servers since a config update might configure it later and -// UpdateConfig called. It will effectively do nothing if there are no HCP -// credentials set other than wait for some to be added. -func (m *Manager) Run(ctx context.Context) { +// Start executes the logic for connecting to HCP and sending periodic server updates. If the +// manager has been previously started, it will not start again. +func (m *HCPManager) Start(ctx context.Context) error { + // Check if the manager has already started + changed := m.setRunning(true) + if !changed { + m.logger.Trace("HCP manager already started") + return nil + } + var err error - m.logger.Debug("HCP manager starting") + m.logger.Info("HCP manager starting") + + // Update and start the SCADA provider + err = m.startSCADAProvider() + if err != nil { + m.logger.Error("failed to start scada provider", "error", err) + m.setRunning(false) + return err + } + + // Update and start the telemetry provider to enable the HCP metrics sink + if err := m.startTelemetryProvider(ctx); err != nil { + m.logger.Error("failed to update telemetry config provider", "error", err) + m.setRunning(false) + return err + } // immediately send initial update select { case <-ctx.Done(): - return + m.setRunning(false) + return nil + case <-m.stopCh: + return nil case <-m.updateCh: // empty the update chan if there is a queued update to prevent repeated update in main loop err = m.sendUpdate() + if err != nil { + m.setRunning(false) + return err + } default: err = m.sendUpdate() + if err != nil { + m.setRunning(false) + return err + } } // main loop - for { - m.cfgMu.RLock() - cfg := m.cfg - m.cfgMu.RUnlock() - nextUpdate := cfg.nextHeartbeat() - if err != nil { - m.logger.Error("failed to send server status to HCP", "err", err, "next_heartbeat", nextUpdate.String()) - } + go func() { + for { + m.cfgMu.RLock() + cfg := m.cfg + m.cfgMu.RUnlock() + + // Check for configured management token from HCP and upsert it if found + if hcpManagement := cfg.CloudConfig.ManagementToken; len(hcpManagement) > 0 { + if cfg.ManagementTokenUpserterFn != nil { + upsertTokenErr := cfg.ManagementTokenUpserterFn("HCP Management Token", hcpManagement) + if upsertTokenErr != nil { + m.logger.Error("failed to upsert HCP management token", "err", upsertTokenErr) + } + } + } + + nextUpdate := cfg.nextHeartbeat() + if err != nil { + m.logger.Error("failed to send server status to HCP", "err", err, "next_heartbeat", nextUpdate.String()) + } + + select { + case <-ctx.Done(): + m.setRunning(false) + return - select { - case <-ctx.Done(): - return + case <-m.stopCh: + return - case <-m.updateCh: - err = m.sendUpdate() + case <-m.updateCh: + err = m.sendUpdate() - case <-time.After(nextUpdate): - err = m.sendUpdate() + case <-time.After(nextUpdate): + err = m.sendUpdate() + } } + }() + + return err +} + +func (m *HCPManager) startSCADAProvider() error { + provider := m.cfg.SCADAProvider + if provider == nil { + return nil } + + // Update the SCADA provider configuration with HCP configurations + m.logger.Debug("updating scada provider with HCP configuration") + err := provider.UpdateHCPConfig(m.cfg.CloudConfig) + if err != nil { + m.logger.Error("failed to update scada provider with HCP configuration", "err", err) + return err + } + + // Update the SCADA provider metadata + provider.UpdateMeta(map[string]string{ + "consul_server_id": string(m.cfg.CloudConfig.NodeID), + }) + + // Start the SCADA provider + err = provider.Start() + if err != nil { + return err + } + return nil } -func (m *Manager) UpdateConfig(cfg ManagerConfig) { - m.cfgMu.Lock() - defer m.cfgMu.Unlock() - old := m.cfg - m.cfg = cfg - if old.enabled() || cfg.enabled() { - // Only log about this if cloud is actually configured or it would be - // confusing. We check both old and new in case we are disabling cloud or - // enabling it or just updating it. - m.logger.Info("updated HCP configuration") +func (m *HCPManager) startTelemetryProvider(ctx context.Context) error { + if m.cfg.TelemetryProvider == nil || reflect.ValueOf(m.cfg.TelemetryProvider).IsNil() { + return nil } - // Send a new status update since we might have just gotten connection details - // for the first time. - m.SendUpdate() + m.cfg.TelemetryProvider.Start(ctx, &HCPProviderCfg{ + HCPClient: m.cfg.Client, + HCPConfig: &m.cfg.CloudConfig, + }) + + return nil +} + +func (m *HCPManager) GetCloudConfig() config.CloudConfig { + m.cfgMu.RLock() + defer m.cfgMu.RUnlock() + + return m.cfg.CloudConfig +} + +func (m *HCPManager) UpdateConfig(client hcpclient.Client, cloudCfg config.CloudConfig) { + m.cfgMu.Lock() + // Save original values + originalCfg := m.cfg.CloudConfig + originalClient := m.cfg.Client + + // Update with new values + m.cfg.Client = client + m.cfg.CloudConfig = cloudCfg + m.cfgMu.Unlock() + + // Send update if already running and values were updated + if m.isRunning() && (originalClient != client || originalCfg != cloudCfg) { + m.SendUpdate() + } } -func (m *Manager) SendUpdate() { +func (m *HCPManager) SendUpdate() { m.logger.Debug("HCP triggering status update") select { case m.updateCh <- struct{}{}: @@ -151,7 +272,7 @@ func (m *Manager) SendUpdate() { // and a "isRetrying" state or something so that we attempt to send update, but // then fetch fresh info on each attempt to send so if we are already in a retry // backoff a new push is a no-op. -func (m *Manager) sendUpdate() error { +func (m *HCPManager) sendUpdate() error { m.cfgMu.RLock() cfg := m.cfg m.cfgMu.RUnlock() @@ -177,5 +298,67 @@ func (m *Manager) sendUpdate() error { return err } - return m.cfg.Client.PushServerStatus(ctx, &s) + return cfg.Client.PushServerStatus(ctx, &s) +} + +func (m *HCPManager) isRunning() bool { + m.runLock.RLock() + defer m.runLock.RUnlock() + return m.running +} + +// setRunning sets the running status of the manager to the given value. If the +// given value is the same as the current running status, it returns false. If +// current status is updated to the given status, it returns true. +func (m *HCPManager) setRunning(r bool) bool { + m.runLock.Lock() + defer m.runLock.Unlock() + + if m.running == r { + return false + } + + // Initialize or close the stop channel depending what running status + // we're transitioning to. Channel must be initialized on start since + // a provider can be stopped and started multiple times. + if r { + m.stopCh = make(chan struct{}) + } else { + close(m.stopCh) + } + + m.running = r + return true +} + +// Stop stops the manager's main loop that sends updates +// and stops the SCADA provider and telemetry provider. +func (m *HCPManager) Stop() error { + changed := m.setRunning(false) + if !changed { + m.logger.Trace("HCP manager already stopped") + return nil + } + m.logger.Info("HCP manager stopping") + + m.cfgMu.RLock() + defer m.cfgMu.RUnlock() + + if m.cfg.SCADAProvider != nil { + m.cfg.SCADAProvider.Stop() + } + + if m.cfg.TelemetryProvider != nil && !reflect.ValueOf(m.cfg.TelemetryProvider).IsNil() { + m.cfg.TelemetryProvider.Stop() + } + + if m.cfg.ManagementTokenDeleterFn != nil && m.cfg.CloudConfig.ManagementToken != "" { + err := m.cfg.ManagementTokenDeleterFn(m.cfg.CloudConfig.ManagementToken) + if err != nil { + return err + } + } + + m.logger.Info("HCP manager stopped") + return nil } diff --git a/agent/hcp/manager_lifecycle.go b/agent/hcp/manager_lifecycle.go new file mode 100644 index 000000000000..6b7b6a46dc71 --- /dev/null +++ b/agent/hcp/manager_lifecycle.go @@ -0,0 +1,107 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package hcp + +import ( + "context" + "os" + "path/filepath" + + "github.com/hashicorp/go-hclog" + + "github.com/hashicorp/consul/agent/hcp/bootstrap/constants" + hcpclient "github.com/hashicorp/consul/agent/hcp/client" + "github.com/hashicorp/consul/agent/hcp/config" + hcpctl "github.com/hashicorp/consul/internal/hcp" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// HCPManagerLifecycleFn returns a LinkEventHandler function which will appropriately +// Start and Stop the HCP Manager based on the Link event received. If a link is upserted, +// the HCP Manager is started, and if a link is deleted, the HCP manager is stopped. +func HCPManagerLifecycleFn( + m Manager, + hcpClientFn func(cfg config.CloudConfig) (hcpclient.Client, error), + loadMgmtTokenFn func( + ctx context.Context, logger hclog.Logger, hcpClient hcpclient.Client, dataDir string, + ) (string, error), + cloudConfig config.CloudConfig, + dataDir string, +) LinkEventHandler { + return func(ctx context.Context, logger hclog.Logger, watchEvent *pbresource.WatchEvent) { + // This indicates that a Link was deleted + if watchEvent.GetDelete() != nil { + logger.Debug("HCP Link deleted, stopping HCP manager") + + if dataDir != "" { + hcpConfigDir := filepath.Join(dataDir, constants.SubDir) + logger.Debug("deleting hcp-config dir", "dir", hcpConfigDir) + err := os.RemoveAll(hcpConfigDir) + if err != nil { + logger.Error("failed to delete hcp-config dir", "dir", hcpConfigDir, "err", err) + } + } + + err := m.Stop() + if err != nil { + logger.Error("error stopping HCP manager", "error", err) + } + return + } + + // This indicates that a Link was either created or updated + if watchEvent.GetUpsert() != nil { + logger.Debug("HCP Link upserted, starting manager if not already started") + + res := watchEvent.GetUpsert().GetResource() + var link pbhcp.Link + if err := res.GetData().UnmarshalTo(&link); err != nil { + logger.Error("error unmarshalling link data", "error", err) + return + } + + if validated, reason := hcpctl.IsValidated(res); !validated { + logger.Debug("HCP Link not validated, not starting manager", "reason", reason) + return + } + + // Update the HCP manager configuration with the link values + // Merge the link data with the existing cloud config so that we only overwrite the + // fields that are provided by the link. This ensures that: + // 1. The HCP configuration (i.e., how to connect to HCP) is preserved + // 2. The Consul agent's node ID and node name are preserved + newCfg := config.CloudConfig{ + ResourceID: link.ResourceId, + ClientID: link.ClientId, + ClientSecret: link.ClientSecret, + } + mergedCfg := config.Merge(cloudConfig, newCfg) + hcpClient, err := hcpClientFn(mergedCfg) + if err != nil { + logger.Error("error creating HCP client", "error", err) + return + } + + // Load the management token if access is set to read-write. Read-only clusters + // will not have a management token provided by HCP. + var token string + if link.GetAccessLevel() == pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE { + token, err = loadMgmtTokenFn(ctx, logger, hcpClient, dataDir) + if err != nil { + logger.Error("error loading management token", "error", err) + return + } + } + + mergedCfg.ManagementToken = token + m.UpdateConfig(hcpClient, mergedCfg) + + err = m.Start(ctx) + if err != nil { + logger.Error("error starting HCP manager", "error", err) + } + } + } +} diff --git a/agent/hcp/manager_lifecycle_test.go b/agent/hcp/manager_lifecycle_test.go new file mode 100644 index 000000000000..b40a772ab4c8 --- /dev/null +++ b/agent/hcp/manager_lifecycle_test.go @@ -0,0 +1,236 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package hcp + +import ( + "context" + "errors" + "io" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/anypb" + + "github.com/hashicorp/go-hclog" + + "github.com/hashicorp/consul/agent/hcp/bootstrap/constants" + hcpclient "github.com/hashicorp/consul/agent/hcp/client" + "github.com/hashicorp/consul/agent/hcp/config" + hcpctl "github.com/hashicorp/consul/internal/hcp" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil" +) + +func TestHCPManagerLifecycleFn(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + + logger := hclog.New(&hclog.LoggerOptions{Output: io.Discard}) + + mockHCPClient := hcpclient.NewMockClient(t) + mockHcpClientFn := func(_ config.CloudConfig) (hcpclient.Client, error) { + return mockHCPClient, nil + } + + mockLoadMgmtTokenFn := func(ctx context.Context, logger hclog.Logger, hcpClient hcpclient.Client, dataDir string) (string, error) { + return "test-mgmt-token", nil + } + + dataDir := testutil.TempDir(t, "test-link-controller") + err := os.Mkdir(filepath.Join(dataDir, constants.SubDir), os.ModeDir) + require.NoError(t, err) + existingCfg := config.CloudConfig{ + AuthURL: "test.com", + } + + type testCase struct { + mutateLink func(*pbhcp.Link) + mutateUpsertEvent func(*pbresource.WatchEvent_Upsert) + applyMocksAndAssertions func(*testing.T, *MockManager, *pbhcp.Link) + hcpClientFn func(config.CloudConfig) (hcpclient.Client, error) + loadMgmtTokenFn func(context.Context, hclog.Logger, hcpclient.Client, string) (string, error) + } + + testCases := map[string]testCase{ + // HCP manager should be started when link is created and stopped when link is deleted + "Ok": { + applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) { + mgr.EXPECT().Start(mock.Anything).Return(nil).Once() + + expectedCfg := config.CloudConfig{ + ResourceID: link.ResourceId, + ClientID: link.ClientId, + ClientSecret: link.ClientSecret, + AuthURL: "test.com", + ManagementToken: "test-mgmt-token", + } + mgr.EXPECT().UpdateConfig(mockHCPClient, expectedCfg).Once() + + mgr.EXPECT().Stop().Return(nil).Once() + }, + }, + // HCP manager should not be updated with management token + "ReadOnly": { + mutateLink: func(link *pbhcp.Link) { + link.AccessLevel = pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_ONLY + }, + applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) { + mgr.EXPECT().Start(mock.Anything).Return(nil).Once() + + expectedCfg := config.CloudConfig{ + ResourceID: link.ResourceId, + ClientID: link.ClientId, + ClientSecret: link.ClientSecret, + AuthURL: "test.com", + ManagementToken: "", + } + mgr.EXPECT().UpdateConfig(mockHCPClient, expectedCfg).Once() + + mgr.EXPECT().Stop().Return(nil).Once() + }, + }, + // HCP manager should not be started or updated if link is not validated + "ValidationError": { + mutateUpsertEvent: func(upsert *pbresource.WatchEvent_Upsert) { + upsert.Resource.Status = map[string]*pbresource.Status{ + hcpctl.StatusKey: { + Conditions: []*pbresource.Condition{hcpctl.ConditionValidatedFailed}, + }, + } + }, + applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) { + mgr.AssertNotCalled(t, "Start", mock.Anything) + mgr.AssertNotCalled(t, "UpdateConfig", mock.Anything, mock.Anything) + mgr.EXPECT().Stop().Return(nil).Once() + }, + }, + "Error_InvalidLink": { + mutateUpsertEvent: func(upsert *pbresource.WatchEvent_Upsert) { + upsert.Resource = nil + }, + applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) { + mgr.AssertNotCalled(t, "Start", mock.Anything) + mgr.AssertNotCalled(t, "UpdateConfig", mock.Anything, mock.Anything) + mgr.EXPECT().Stop().Return(nil).Once() + }, + }, + "Error_HCPManagerStop": { + applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) { + mgr.EXPECT().Start(mock.Anything).Return(nil).Once() + mgr.EXPECT().UpdateConfig(mock.Anything, mock.Anything).Return().Once() + mgr.EXPECT().Stop().Return(errors.New("could not stop HCP manager")).Once() + }, + }, + "Error_CreatingHCPClient": { + applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) { + mgr.AssertNotCalled(t, "Start", mock.Anything) + mgr.AssertNotCalled(t, "UpdateConfig", mock.Anything, mock.Anything) + mgr.EXPECT().Stop().Return(nil).Once() + }, + hcpClientFn: func(_ config.CloudConfig) (hcpclient.Client, error) { + return nil, errors.New("could not create HCP client") + }, + }, + // This should result in the HCP manager not being started + "Error_LoadMgmtToken": { + applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) { + mgr.AssertNotCalled(t, "Start", mock.Anything) + mgr.AssertNotCalled(t, "UpdateConfig", mock.Anything, mock.Anything) + mgr.EXPECT().Stop().Return(nil).Once() + }, + loadMgmtTokenFn: func(ctx context.Context, logger hclog.Logger, hcpClient hcpclient.Client, dataDir string) (string, error) { + return "", errors.New("could not load management token") + }, + }, + "Error_HCPManagerStart": { + applyMocksAndAssertions: func(t *testing.T, mgr *MockManager, link *pbhcp.Link) { + mgr.EXPECT().Start(mock.Anything).Return(errors.New("could not start HCP manager")).Once() + mgr.EXPECT().UpdateConfig(mock.Anything, mock.Anything).Return().Once() + mgr.EXPECT().Stop().Return(nil).Once() + }, + }, + } + + for name, test := range testCases { + t.Run(name, func(t2 *testing.T) { + mgr := NewMockManager(t2) + + // Set up a link + link := pbhcp.Link{ + ResourceId: "abc", + ClientId: "def", + ClientSecret: "ghi", + AccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE, + } + + if test.mutateLink != nil { + test.mutateLink(&link) + } + + linkResource, err := anypb.New(&link) + require.NoError(t2, err) + + if test.applyMocksAndAssertions != nil { + test.applyMocksAndAssertions(t2, mgr, &link) + } + + testHcpClientFn := mockHcpClientFn + if test.hcpClientFn != nil { + testHcpClientFn = test.hcpClientFn + } + + testLoadMgmtToken := mockLoadMgmtTokenFn + if test.loadMgmtTokenFn != nil { + testLoadMgmtToken = test.loadMgmtTokenFn + } + + updateManagerLifecycle := HCPManagerLifecycleFn( + mgr, testHcpClientFn, + testLoadMgmtToken, existingCfg, dataDir, + ) + + upsertEvent := &pbresource.WatchEvent_Upsert{ + Resource: &pbresource.Resource{ + Id: &pbresource.ID{ + Name: "global", + Type: pbhcp.LinkType, + }, + Status: map[string]*pbresource.Status{ + hcpctl.StatusKey: { + Conditions: []*pbresource.Condition{hcpctl.ConditionValidatedSuccess}, + }, + }, + Data: linkResource, + }, + } + if test.mutateUpsertEvent != nil { + test.mutateUpsertEvent(upsertEvent) + } + + // Handle upsert event + updateManagerLifecycle(ctx, logger, &pbresource.WatchEvent{ + Event: &pbresource.WatchEvent_Upsert_{ + Upsert: upsertEvent, + }, + }) + + // Handle delete event. This should stop HCP manager + updateManagerLifecycle(ctx, logger, &pbresource.WatchEvent{ + Event: &pbresource.WatchEvent_Delete_{ + Delete: &pbresource.WatchEvent_Delete{}, + }, + }) + + // Ensure hcp-config directory is removed + file := filepath.Join(dataDir, constants.SubDir) + if _, err := os.Stat(file); err == nil || !os.IsNotExist(err) { + require.Fail(t2, "should have removed hcp-config directory") + } + }) + } +} diff --git a/agent/hcp/manager_test.go b/agent/hcp/manager_test.go index 8432e63ed528..83773791727d 100644 --- a/agent/hcp/manager_test.go +++ b/agent/hcp/manager_test.go @@ -4,45 +4,266 @@ package hcp import ( + "fmt" "io" "testing" "time" - hcpclient "github.com/hashicorp/consul/agent/hcp/client" - "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "golang.org/x/net/context" + "google.golang.org/protobuf/types/known/anypb" + + "github.com/hashicorp/go-hclog" + + hcpclient "github.com/hashicorp/consul/agent/hcp/client" + "github.com/hashicorp/consul/agent/hcp/config" + "github.com/hashicorp/consul/agent/hcp/scada" + hcpctl "github.com/hashicorp/consul/internal/hcp" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil" ) -func TestManager_Run(t *testing.T) { +func TestManager_MonitorHCPLink(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + logger := hclog.New(&hclog.LoggerOptions{Output: io.Discard}) + + mgr := NewManager( + ManagerConfig{ + Logger: hclog.New(&hclog.LoggerOptions{Output: io.Discard}), + }, + ) + mockHCPClient := hcpclient.NewMockClient(t) + mockHcpClientFn := func(_ config.CloudConfig) (hcpclient.Client, error) { + return mockHCPClient, nil + } + loadMgmtTokenFn := func(ctx context.Context, logger hclog.Logger, hcpClient hcpclient.Client, dataDir string) (string, error) { + return "test-mgmt-token", nil + } + + require.False(t, mgr.isRunning()) + updateManagerLifecycle := HCPManagerLifecycleFn( + mgr, mockHcpClientFn, + loadMgmtTokenFn, config.CloudConfig{}, "", + ) + + // Set up a link + link := pbhcp.Link{ + ResourceId: "abc", + ClientId: "def", + ClientSecret: "ghi", + AccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE, + } + linkResource, err := anypb.New(&link) + require.NoError(t, err) + updateManagerLifecycle(ctx, logger, &pbresource.WatchEvent{ + Event: &pbresource.WatchEvent_Upsert_{ + Upsert: &pbresource.WatchEvent_Upsert{ + Resource: &pbresource.Resource{ + Id: &pbresource.ID{ + Name: "global", + Type: pbhcp.LinkType, + }, + Status: map[string]*pbresource.Status{ + hcpctl.StatusKey: { + Conditions: []*pbresource.Condition{hcpctl.ConditionValidatedSuccess}, + }, + }, + Data: linkResource, + }, + }, + }, + }) + + // Validate that the HCP manager is started + require.True(t, mgr.isRunning()) +} + +func TestManager_Start(t *testing.T) { client := hcpclient.NewMockClient(t) statusF := func(ctx context.Context) (hcpclient.ServerStatus, error) { return hcpclient.ServerStatus{ID: t.Name()}, nil } + upsertManagementTokenCalled := make(chan struct{}, 1) + upsertManagementTokenF := func(name, secretID string) error { + upsertManagementTokenCalled <- struct{}{} + return nil + } updateCh := make(chan struct{}, 1) client.EXPECT().PushServerStatus(mock.Anything, &hcpclient.ServerStatus{ID: t.Name()}).Return(nil).Once() - mgr := NewManager(ManagerConfig{ - Client: client, - Logger: hclog.New(&hclog.LoggerOptions{Output: io.Discard}), - StatusFn: statusF, - }) + + cloudCfg := config.CloudConfig{ + ResourceID: "resource-id", + NodeID: "node-1", + ManagementToken: "fake-token", + } + scadaM := scada.NewMockProvider(t) + scadaM.EXPECT().UpdateHCPConfig(cloudCfg).Return(nil).Once() + scadaM.EXPECT().UpdateMeta( + map[string]string{ + "consul_server_id": string(cloudCfg.NodeID), + }, + ).Return().Once() + scadaM.EXPECT().Start().Return(nil) + + telemetryM := NewMockTelemetryProvider(t) + telemetryM.EXPECT().Start( + mock.Anything, &HCPProviderCfg{ + HCPClient: client, + HCPConfig: &cloudCfg, + }, + ).Return(nil).Once() + + mgr := NewManager( + ManagerConfig{ + Logger: hclog.New(&hclog.LoggerOptions{Output: io.Discard}), + StatusFn: statusF, + ManagementTokenUpserterFn: upsertManagementTokenF, + SCADAProvider: scadaM, + TelemetryProvider: telemetryM, + }, + ) mgr.testUpdateSent = updateCh ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) - go mgr.Run(ctx) + mgr.UpdateConfig(client, cloudCfg) + mgr.Start(ctx) select { case <-updateCh: case <-time.After(time.Second): require.Fail(t, "manager did not send update in expected time") } + select { + case <-upsertManagementTokenCalled: + case <-time.After(time.Second): + require.Fail(t, "manager did not upsert management token in expected time") + } + // Make sure after manager has stopped no more statuses are pushed. cancel() client.AssertExpectations(t) } +func TestManager_StartMultipleTimes(t *testing.T) { + client := hcpclient.NewMockClient(t) + statusF := func(ctx context.Context) (hcpclient.ServerStatus, error) { + return hcpclient.ServerStatus{ID: t.Name()}, nil + } + + updateCh := make(chan struct{}, 1) + client.EXPECT().PushServerStatus(mock.Anything, &hcpclient.ServerStatus{ID: t.Name()}).Return(nil).Once() + + cloudCfg := config.CloudConfig{ + ResourceID: "organization/85702e73-8a3d-47dc-291c-379b783c5804/project/8c0547c0-10e8-1ea2-dffe-384bee8da634/hashicorp.consul.global-network-manager.cluster/test", + NodeID: "node-1", + ManagementToken: "fake-token", + } + + mgr := NewManager( + ManagerConfig{ + Logger: hclog.New(&hclog.LoggerOptions{Output: io.Discard}), + StatusFn: statusF, + }, + ) + + mgr.testUpdateSent = updateCh + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + + // Start the manager twice concurrently, expect only one update + mgr.UpdateConfig(client, cloudCfg) + go mgr.Start(ctx) + go mgr.Start(ctx) + select { + case <-updateCh: + case <-time.After(time.Second): + require.Fail(t, "manager did not send update in expected time") + } + + select { + case <-updateCh: + require.Fail(t, "manager sent an update when not expected") + case <-time.After(time.Second): + } + + // Try start the manager again, still don't expect an update since already running + mgr.Start(ctx) + select { + case <-updateCh: + require.Fail(t, "manager sent an update when not expected") + case <-time.After(time.Second): + } +} + +func TestManager_UpdateConfig(t *testing.T) { + client := hcpclient.NewMockClient(t) + statusF := func(ctx context.Context) (hcpclient.ServerStatus, error) { + return hcpclient.ServerStatus{ID: t.Name()}, nil + } + + updateCh := make(chan struct{}, 1) + + cloudCfg := config.CloudConfig{ + ResourceID: "organization/85702e73-8a3d-47dc-291c-379b783c5804/project/8c0547c0-10e8-1ea2-dffe-384bee8da634/hashicorp.consul.global-network-manager.cluster/test", + NodeID: "node-1", + } + + mgr := NewManager( + ManagerConfig{ + Logger: hclog.New(&hclog.LoggerOptions{Output: io.Discard}), + StatusFn: statusF, + CloudConfig: cloudCfg, + Client: client, + }, + ) + + mgr.testUpdateSent = updateCh + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + + // Start the manager, expect an initial status update + client.EXPECT().PushServerStatus(mock.Anything, &hcpclient.ServerStatus{ID: t.Name()}).Return(nil).Once() + mgr.Start(ctx) + select { + case <-updateCh: + case <-time.After(time.Second): + require.Fail(t, "manager did not send update in expected time") + } + + // Update the cloud configuration, expect a status update + client.EXPECT().PushServerStatus(mock.Anything, &hcpclient.ServerStatus{ID: t.Name()}).Return(nil).Once() + updatedCfg := cloudCfg + updatedCfg.ManagementToken = "token" + mgr.UpdateConfig(client, updatedCfg) + select { + case <-updateCh: + case <-time.After(time.Second): + require.Fail(t, "manager did not send update in expected time") + } + + // Update the client, expect a status update + updatedClient := hcpclient.NewMockClient(t) + updatedClient.EXPECT().PushServerStatus(mock.Anything, &hcpclient.ServerStatus{ID: t.Name()}).Return(nil).Once() + mgr.UpdateConfig(updatedClient, updatedCfg) + select { + case <-updateCh: + case <-time.After(time.Second): + require.Fail(t, "manager did not send update in expected time") + } + + // Update with the same values, don't expect a status update + mgr.UpdateConfig(updatedClient, updatedCfg) + select { + case <-updateCh: + require.Fail(t, "manager sent an update when not expected") + case <-time.After(time.Second): + } +} + func TestManager_SendUpdate(t *testing.T) { client := hcpclient.NewMockClient(t) statusF := func(ctx context.Context) (hcpclient.ServerStatus, error) { @@ -52,17 +273,19 @@ func TestManager_SendUpdate(t *testing.T) { // Expect two calls, once during run startup and again when SendUpdate is called client.EXPECT().PushServerStatus(mock.Anything, &hcpclient.ServerStatus{ID: t.Name()}).Return(nil).Twice() - mgr := NewManager(ManagerConfig{ - Client: client, - Logger: hclog.New(&hclog.LoggerOptions{Output: io.Discard}), - StatusFn: statusF, - }) + mgr := NewManager( + ManagerConfig{ + Client: client, + Logger: hclog.New(&hclog.LoggerOptions{Output: io.Discard}), + StatusFn: statusF, + }, + ) mgr.testUpdateSent = updateCh ctx, cancel := context.WithCancel(context.Background()) defer cancel() - go mgr.Run(ctx) + mgr.Start(ctx) select { case <-updateCh: case <-time.After(time.Second): @@ -86,19 +309,21 @@ func TestManager_SendUpdate_Periodic(t *testing.T) { // Expect two calls, once during run startup and again when SendUpdate is called client.EXPECT().PushServerStatus(mock.Anything, &hcpclient.ServerStatus{ID: t.Name()}).Return(nil).Twice() - mgr := NewManager(ManagerConfig{ - Client: client, - Logger: hclog.New(&hclog.LoggerOptions{Output: io.Discard}), - StatusFn: statusF, - MaxInterval: time.Second, - MinInterval: 100 * time.Millisecond, - }) + mgr := NewManager( + ManagerConfig{ + Client: client, + Logger: hclog.New(&hclog.LoggerOptions{Output: io.Discard}), + StatusFn: statusF, + MaxInterval: time.Second, + MinInterval: 100 * time.Millisecond, + }, + ) mgr.testUpdateSent = updateCh ctx, cancel := context.WithCancel(context.Background()) defer cancel() - go mgr.Run(ctx) + mgr.Start(ctx) select { case <-updateCh: case <-time.After(time.Second): @@ -111,3 +336,105 @@ func TestManager_SendUpdate_Periodic(t *testing.T) { } client.AssertExpectations(t) } + +func TestManager_Stop(t *testing.T) { + client := hcpclient.NewMockClient(t) + + // Configure status functions called in sendUpdate + statusF := func(ctx context.Context) (hcpclient.ServerStatus, error) { + return hcpclient.ServerStatus{ID: t.Name()}, nil + } + updateCh := make(chan struct{}, 1) + client.EXPECT().PushServerStatus(mock.Anything, &hcpclient.ServerStatus{ID: t.Name()}).Return(nil).Twice() + + // Configure management token creation and cleanup + token := "test-token" + upsertManagementTokenCalled := make(chan struct{}, 1) + upsertManagementTokenF := func(name, secretID string) error { + upsertManagementTokenCalled <- struct{}{} + if secretID != token { + return fmt.Errorf("expected token %q, got %q", token, secretID) + } + return nil + } + deleteManagementTokenCalled := make(chan struct{}, 1) + deleteManagementTokenF := func(secretID string) error { + deleteManagementTokenCalled <- struct{}{} + if secretID != token { + return fmt.Errorf("expected token %q, got %q", token, secretID) + } + return nil + } + + // Configure the SCADA provider + scadaM := scada.NewMockProvider(t) + scadaM.EXPECT().UpdateHCPConfig(mock.Anything).Return(nil).Once() + scadaM.EXPECT().UpdateMeta(mock.Anything).Return().Once() + scadaM.EXPECT().Start().Return(nil).Once() + scadaM.EXPECT().Stop().Return(nil).Once() + + // Configure the telemetry provider + telemetryM := NewMockTelemetryProvider(t) + telemetryM.EXPECT().Start(mock.Anything, mock.Anything).Return(nil).Once() + telemetryM.EXPECT().Stop().Return().Once() + + // Configure manager with all its dependencies + mgr := NewManager( + ManagerConfig{ + Logger: testutil.Logger(t), + StatusFn: statusF, + Client: client, + ManagementTokenUpserterFn: upsertManagementTokenF, + ManagementTokenDeleterFn: deleteManagementTokenF, + SCADAProvider: scadaM, + TelemetryProvider: telemetryM, + CloudConfig: config.CloudConfig{ + ManagementToken: token, + }, + }, + ) + mgr.testUpdateSent = updateCh + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + + // Start the manager + err := mgr.Start(ctx) + require.NoError(t, err) + select { + case <-updateCh: + case <-time.After(time.Second): + require.Fail(t, "manager did not send update in expected time") + } + select { + case <-upsertManagementTokenCalled: + case <-time.After(time.Second): + require.Fail(t, "manager did not create token in expected time") + } + + // Send an update to ensure the manager is running in its main loop + mgr.SendUpdate() + select { + case <-updateCh: + case <-time.After(time.Second): + require.Fail(t, "manager did not send update in expected time") + } + + // Stop the manager + err = mgr.Stop() + require.NoError(t, err) + + // Validate that the management token delete function is called + select { + case <-deleteManagementTokenCalled: + case <-time.After(time.Millisecond * 100): + require.Fail(t, "manager did not create token in expected time") + } + + // Send an update, expect no update since manager is stopped + mgr.SendUpdate() + select { + case <-updateCh: + require.Fail(t, "manager sent update after stopped") + case <-time.After(time.Second): + } +} diff --git a/agent/hcp/mock_Manager.go b/agent/hcp/mock_Manager.go new file mode 100644 index 000000000000..422d9034d88d --- /dev/null +++ b/agent/hcp/mock_Manager.go @@ -0,0 +1,209 @@ +// Code generated by mockery v2.38.0. DO NOT EDIT. + +package hcp + +import ( + client "github.com/hashicorp/consul/agent/hcp/client" + config "github.com/hashicorp/consul/agent/hcp/config" + + context "context" + + mock "github.com/stretchr/testify/mock" +) + +// MockManager is an autogenerated mock type for the Manager type +type MockManager struct { + mock.Mock +} + +type MockManager_Expecter struct { + mock *mock.Mock +} + +func (_m *MockManager) EXPECT() *MockManager_Expecter { + return &MockManager_Expecter{mock: &_m.Mock} +} + +// GetCloudConfig provides a mock function with given fields: +func (_m *MockManager) GetCloudConfig() config.CloudConfig { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetCloudConfig") + } + + var r0 config.CloudConfig + if rf, ok := ret.Get(0).(func() config.CloudConfig); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(config.CloudConfig) + } + + return r0 +} + +// MockManager_GetCloudConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCloudConfig' +type MockManager_GetCloudConfig_Call struct { + *mock.Call +} + +// GetCloudConfig is a helper method to define mock.On call +func (_e *MockManager_Expecter) GetCloudConfig() *MockManager_GetCloudConfig_Call { + return &MockManager_GetCloudConfig_Call{Call: _e.mock.On("GetCloudConfig")} +} + +func (_c *MockManager_GetCloudConfig_Call) Run(run func()) *MockManager_GetCloudConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *MockManager_GetCloudConfig_Call) Return(_a0 config.CloudConfig) *MockManager_GetCloudConfig_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockManager_GetCloudConfig_Call) RunAndReturn(run func() config.CloudConfig) *MockManager_GetCloudConfig_Call { + _c.Call.Return(run) + return _c +} + +// Start provides a mock function with given fields: _a0 +func (_m *MockManager) Start(_a0 context.Context) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Start") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockManager_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type MockManager_Start_Call struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +// - _a0 context.Context +func (_e *MockManager_Expecter) Start(_a0 interface{}) *MockManager_Start_Call { + return &MockManager_Start_Call{Call: _e.mock.On("Start", _a0)} +} + +func (_c *MockManager_Start_Call) Run(run func(_a0 context.Context)) *MockManager_Start_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *MockManager_Start_Call) Return(_a0 error) *MockManager_Start_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockManager_Start_Call) RunAndReturn(run func(context.Context) error) *MockManager_Start_Call { + _c.Call.Return(run) + return _c +} + +// Stop provides a mock function with given fields: +func (_m *MockManager) Stop() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Stop") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockManager_Stop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Stop' +type MockManager_Stop_Call struct { + *mock.Call +} + +// Stop is a helper method to define mock.On call +func (_e *MockManager_Expecter) Stop() *MockManager_Stop_Call { + return &MockManager_Stop_Call{Call: _e.mock.On("Stop")} +} + +func (_c *MockManager_Stop_Call) Run(run func()) *MockManager_Stop_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *MockManager_Stop_Call) Return(_a0 error) *MockManager_Stop_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockManager_Stop_Call) RunAndReturn(run func() error) *MockManager_Stop_Call { + _c.Call.Return(run) + return _c +} + +// UpdateConfig provides a mock function with given fields: _a0, _a1 +func (_m *MockManager) UpdateConfig(_a0 client.Client, _a1 config.CloudConfig) { + _m.Called(_a0, _a1) +} + +// MockManager_UpdateConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateConfig' +type MockManager_UpdateConfig_Call struct { + *mock.Call +} + +// UpdateConfig is a helper method to define mock.On call +// - _a0 client.Client +// - _a1 config.CloudConfig +func (_e *MockManager_Expecter) UpdateConfig(_a0 interface{}, _a1 interface{}) *MockManager_UpdateConfig_Call { + return &MockManager_UpdateConfig_Call{Call: _e.mock.On("UpdateConfig", _a0, _a1)} +} + +func (_c *MockManager_UpdateConfig_Call) Run(run func(_a0 client.Client, _a1 config.CloudConfig)) *MockManager_UpdateConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(client.Client), args[1].(config.CloudConfig)) + }) + return _c +} + +func (_c *MockManager_UpdateConfig_Call) Return() *MockManager_UpdateConfig_Call { + _c.Call.Return() + return _c +} + +func (_c *MockManager_UpdateConfig_Call) RunAndReturn(run func(client.Client, config.CloudConfig)) *MockManager_UpdateConfig_Call { + _c.Call.Return(run) + return _c +} + +// NewMockManager creates a new instance of MockManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockManager(t interface { + mock.TestingT + Cleanup(func()) +}) *MockManager { + mock := &MockManager{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/agent/hcp/mock_TelemetryProvider.go b/agent/hcp/mock_TelemetryProvider.go new file mode 100644 index 000000000000..f654575f5bae --- /dev/null +++ b/agent/hcp/mock_TelemetryProvider.go @@ -0,0 +1,115 @@ +// Code generated by mockery v2.38.0. DO NOT EDIT. + +package hcp + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" +) + +// MockTelemetryProvider is an autogenerated mock type for the TelemetryProvider type +type MockTelemetryProvider struct { + mock.Mock +} + +type MockTelemetryProvider_Expecter struct { + mock *mock.Mock +} + +func (_m *MockTelemetryProvider) EXPECT() *MockTelemetryProvider_Expecter { + return &MockTelemetryProvider_Expecter{mock: &_m.Mock} +} + +// Start provides a mock function with given fields: ctx, c +func (_m *MockTelemetryProvider) Start(ctx context.Context, c *HCPProviderCfg) error { + ret := _m.Called(ctx, c) + + if len(ret) == 0 { + panic("no return value specified for Start") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *HCPProviderCfg) error); ok { + r0 = rf(ctx, c) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockTelemetryProvider_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type MockTelemetryProvider_Start_Call struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +// - ctx context.Context +// - c *HCPProviderCfg +func (_e *MockTelemetryProvider_Expecter) Start(ctx interface{}, c interface{}) *MockTelemetryProvider_Start_Call { + return &MockTelemetryProvider_Start_Call{Call: _e.mock.On("Start", ctx, c)} +} + +func (_c *MockTelemetryProvider_Start_Call) Run(run func(ctx context.Context, c *HCPProviderCfg)) *MockTelemetryProvider_Start_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*HCPProviderCfg)) + }) + return _c +} + +func (_c *MockTelemetryProvider_Start_Call) Return(_a0 error) *MockTelemetryProvider_Start_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockTelemetryProvider_Start_Call) RunAndReturn(run func(context.Context, *HCPProviderCfg) error) *MockTelemetryProvider_Start_Call { + _c.Call.Return(run) + return _c +} + +// Stop provides a mock function with given fields: +func (_m *MockTelemetryProvider) Stop() { + _m.Called() +} + +// MockTelemetryProvider_Stop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Stop' +type MockTelemetryProvider_Stop_Call struct { + *mock.Call +} + +// Stop is a helper method to define mock.On call +func (_e *MockTelemetryProvider_Expecter) Stop() *MockTelemetryProvider_Stop_Call { + return &MockTelemetryProvider_Stop_Call{Call: _e.mock.On("Stop")} +} + +func (_c *MockTelemetryProvider_Stop_Call) Run(run func()) *MockTelemetryProvider_Stop_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *MockTelemetryProvider_Stop_Call) Return() *MockTelemetryProvider_Stop_Call { + _c.Call.Return() + return _c +} + +func (_c *MockTelemetryProvider_Stop_Call) RunAndReturn(run func()) *MockTelemetryProvider_Stop_Call { + _c.Call.Return(run) + return _c +} + +// NewMockTelemetryProvider creates a new instance of MockTelemetryProvider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockTelemetryProvider(t interface { + mock.TestingT + Cleanup(func()) +}) *MockTelemetryProvider { + mock := &MockTelemetryProvider{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/agent/hcp/scada/mock_Provider.go b/agent/hcp/scada/mock_Provider.go index b9a0fd2d4967..7e922cb21bc4 100644 --- a/agent/hcp/scada/mock_Provider.go +++ b/agent/hcp/scada/mock_Provider.go @@ -1,12 +1,13 @@ -// Code generated by mockery v2.20.0. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package scada import ( - net "net" - + config "github.com/hashicorp/consul/agent/hcp/config" mock "github.com/stretchr/testify/mock" + net "net" + provider "github.com/hashicorp/hcp-scada-provider" time "time" @@ -121,6 +122,10 @@ func (_c *MockProvider_DeleteMeta_Call) RunAndReturn(run func(...string)) *MockP func (_m *MockProvider) GetMeta() map[string]string { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetMeta") + } + var r0 map[string]string if rf, ok := ret.Get(0).(func() map[string]string); ok { r0 = rf() @@ -164,6 +169,10 @@ func (_c *MockProvider_GetMeta_Call) RunAndReturn(run func() map[string]string) func (_m *MockProvider) LastError() (time.Time, error) { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for LastError") + } + var r0 time.Time var r1 error if rf, ok := ret.Get(0).(func() (time.Time, error)); ok { @@ -215,6 +224,10 @@ func (_c *MockProvider_LastError_Call) RunAndReturn(run func() (time.Time, error func (_m *MockProvider) Listen(capability string) (net.Listener, error) { ret := _m.Called(capability) + if len(ret) == 0 { + panic("no return value specified for Listen") + } + var r0 net.Listener var r1 error if rf, ok := ret.Get(0).(func(string) (net.Listener, error)); ok { @@ -269,6 +282,10 @@ func (_c *MockProvider_Listen_Call) RunAndReturn(run func(string) (net.Listener, func (_m *MockProvider) SessionStatus() string { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for SessionStatus") + } + var r0 string if rf, ok := ret.Get(0).(func() string); ok { r0 = rf() @@ -310,6 +327,10 @@ func (_c *MockProvider_SessionStatus_Call) RunAndReturn(run func() string) *Mock func (_m *MockProvider) Start() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Start") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -351,6 +372,10 @@ func (_c *MockProvider_Start_Call) RunAndReturn(run func() error) *MockProvider_ func (_m *MockProvider) Stop() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Stop") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -388,6 +413,98 @@ func (_c *MockProvider_Stop_Call) RunAndReturn(run func() error) *MockProvider_S return _c } +// UpdateConfig provides a mock function with given fields: _a0 +func (_m *MockProvider) UpdateConfig(_a0 *provider.Config) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for UpdateConfig") + } + + var r0 error + if rf, ok := ret.Get(0).(func(*provider.Config) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockProvider_UpdateConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateConfig' +type MockProvider_UpdateConfig_Call struct { + *mock.Call +} + +// UpdateConfig is a helper method to define mock.On call +// - _a0 *provider.Config +func (_e *MockProvider_Expecter) UpdateConfig(_a0 interface{}) *MockProvider_UpdateConfig_Call { + return &MockProvider_UpdateConfig_Call{Call: _e.mock.On("UpdateConfig", _a0)} +} + +func (_c *MockProvider_UpdateConfig_Call) Run(run func(_a0 *provider.Config)) *MockProvider_UpdateConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*provider.Config)) + }) + return _c +} + +func (_c *MockProvider_UpdateConfig_Call) Return(_a0 error) *MockProvider_UpdateConfig_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockProvider_UpdateConfig_Call) RunAndReturn(run func(*provider.Config) error) *MockProvider_UpdateConfig_Call { + _c.Call.Return(run) + return _c +} + +// UpdateHCPConfig provides a mock function with given fields: cfg +func (_m *MockProvider) UpdateHCPConfig(cfg config.CloudConfig) error { + ret := _m.Called(cfg) + + if len(ret) == 0 { + panic("no return value specified for UpdateHCPConfig") + } + + var r0 error + if rf, ok := ret.Get(0).(func(config.CloudConfig) error); ok { + r0 = rf(cfg) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockProvider_UpdateHCPConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateHCPConfig' +type MockProvider_UpdateHCPConfig_Call struct { + *mock.Call +} + +// UpdateHCPConfig is a helper method to define mock.On call +// - cfg config.CloudConfig +func (_e *MockProvider_Expecter) UpdateHCPConfig(cfg interface{}) *MockProvider_UpdateHCPConfig_Call { + return &MockProvider_UpdateHCPConfig_Call{Call: _e.mock.On("UpdateHCPConfig", cfg)} +} + +func (_c *MockProvider_UpdateHCPConfig_Call) Run(run func(cfg config.CloudConfig)) *MockProvider_UpdateHCPConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(config.CloudConfig)) + }) + return _c +} + +func (_c *MockProvider_UpdateHCPConfig_Call) Return(_a0 error) *MockProvider_UpdateHCPConfig_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockProvider_UpdateHCPConfig_Call) RunAndReturn(run func(config.CloudConfig) error) *MockProvider_UpdateHCPConfig_Call { + _c.Call.Return(run) + return _c +} + // UpdateMeta provides a mock function with given fields: _a0 func (_m *MockProvider) UpdateMeta(_a0 map[string]string) { _m.Called(_a0) @@ -421,13 +538,12 @@ func (_c *MockProvider_UpdateMeta_Call) RunAndReturn(run func(map[string]string) return _c } -type mockConstructorTestingTNewMockProvider interface { +// NewMockProvider creates a new instance of MockProvider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockProvider(t interface { mock.TestingT Cleanup(func()) -} - -// NewMockProvider creates a new instance of MockProvider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewMockProvider(t mockConstructorTestingTNewMockProvider) *MockProvider { +}) *MockProvider { mock := &MockProvider{} mock.Mock.Test(t) diff --git a/agent/hcp/scada/scada.go b/agent/hcp/scada/scada.go index 151e1b6862ef..c62f45908bcf 100644 --- a/agent/hcp/scada/scada.go +++ b/agent/hcp/scada/scada.go @@ -11,7 +11,8 @@ import ( "github.com/hashicorp/go-hclog" libscada "github.com/hashicorp/hcp-scada-provider" "github.com/hashicorp/hcp-scada-provider/capability" - "github.com/hashicorp/hcp-sdk-go/resource" + cloud "github.com/hashicorp/hcp-sdk-go/clients/cloud-shared/v1/models" + hcpcfg "github.com/hashicorp/hcp-sdk-go/config" ) // Provider is the interface used in the rest of Consul core when using SCADA, it is aliased here to the same interface @@ -21,34 +22,72 @@ import ( //go:generate mockery --name Provider --with-expecter --inpackage type Provider interface { libscada.SCADAProvider + UpdateHCPConfig(cfg config.CloudConfig) error } const ( scadaConsulServiceKey = "consul" ) -func New(cfg config.CloudConfig, logger hclog.Logger) (Provider, error) { - resource, err := resource.FromString(cfg.ResourceID) - if err != nil { - return nil, fmt.Errorf("failed to parse cloud resource_id: %w", err) +type scadaProvider struct { + libscada.SCADAProvider + logger hclog.Logger +} + +// New returns an initialized SCADA provider with a zero configuration. +// It can listen but cannot start until UpdateHCPConfig is called with +// a configuration that provides credentials to contact HCP. +func New(logger hclog.Logger) (*scadaProvider, error) { + // Create placeholder resource link + resourceLink := cloud.HashicorpCloudLocationLink{ + Type: "no-op", + ID: "no-op", + Location: &cloud.HashicorpCloudLocationLocation{}, } - hcpConfig, err := cfg.HCPConfig() + // Configure with an empty HCP configuration + hcpConfig, err := hcpcfg.NewHCPConfig(hcpcfg.WithoutBrowserLogin()) if err != nil { - return nil, fmt.Errorf("failed to build HCPConfig: %w", err) + return nil, fmt.Errorf("failed to configure SCADA provider: %w", err) } pvd, err := libscada.New(&libscada.Config{ Service: scadaConsulServiceKey, HCPConfig: hcpConfig, - Resource: *resource.Link(), + Resource: resourceLink, Logger: logger, }) if err != nil { return nil, err } - return pvd, nil + return &scadaProvider{pvd, logger}, nil +} + +// UpdateHCPConfig updates the SCADA provider with the given HCP +// configurations. +func (p *scadaProvider) UpdateHCPConfig(cfg config.CloudConfig) error { + resource, err := cfg.Resource() + if err != nil { + return err + } + + hcpCfg, err := cfg.HCPConfig() + if err != nil { + return err + } + + err = p.UpdateConfig(&libscada.Config{ + Service: scadaConsulServiceKey, + HCPConfig: hcpCfg, + Resource: *resource.Link(), + Logger: p.logger, + }) + if err != nil { + return err + } + + return nil } // IsCapability takes a net.Addr and returns true if it is a SCADA capability.Addr diff --git a/agent/hcp/scada/scada_test.go b/agent/hcp/scada/scada_test.go new file mode 100644 index 000000000000..0cebed1b93a4 --- /dev/null +++ b/agent/hcp/scada/scada_test.go @@ -0,0 +1,52 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package scada + +import ( + "testing" + + "github.com/hashicorp/consul/agent/hcp/config" + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/require" +) + +func TestUpdateHCPConfig(t *testing.T) { + for name, tc := range map[string]struct { + cfg config.CloudConfig + expectedErr string + }{ + "Success": { + cfg: config.CloudConfig{ + ResourceID: "organization/85702e73-8a3d-47dc-291c-379b783c5804/project/8c0547c0-10e8-1ea2-dffe-384bee8da634/hashicorp.consul.global-network-manager.cluster/test", + ClientID: "test", + ClientSecret: "test", + }, + }, + "Empty": { + cfg: config.CloudConfig{}, + expectedErr: "could not parse resource: unexpected number of tokens 1", + }, + "InvalidResource": { + cfg: config.CloudConfig{ + ResourceID: "invalid", + }, + expectedErr: "could not parse resource: unexpected number of tokens 1", + }, + } { + t.Run(name, func(t *testing.T) { + // Create a provider + p, err := New(hclog.NewNullLogger()) + require.NoError(t, err) + + // Update the provider + err = p.UpdateHCPConfig(tc.cfg) + if tc.expectedErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectedErr) + return + } + require.NoError(t, err) + }) + } +} diff --git a/agent/hcp/telemetry/otel_sink.go b/agent/hcp/telemetry/otel_sink.go index 12aae982016c..ad310774047b 100644 --- a/agent/hcp/telemetry/otel_sink.go +++ b/agent/hcp/telemetry/otel_sink.go @@ -136,6 +136,10 @@ func NewOTELSink(ctx context.Context, opts *OTELSinkOpts) (*OTELSink, error) { }, nil } +func (o *OTELSink) Shutdown() { + o.meterProvider.Shutdown(context.TODO()) +} + // SetGauge emits a Consul gauge metric. func (o *OTELSink) SetGauge(key []string, val float32) { o.SetGaugeWithLabels(key, val, nil) diff --git a/agent/hcp/telemetry_provider.go b/agent/hcp/telemetry_provider.go index 22bb0f2f00b8..a575d63f8a82 100644 --- a/agent/hcp/telemetry_provider.go +++ b/agent/hcp/telemetry_provider.go @@ -5,7 +5,11 @@ package hcp import ( "context" + "errors" + "fmt" + "net/http" "net/url" + "reflect" "regexp" "sync" "time" @@ -13,9 +17,12 @@ import ( "github.com/armon/go-metrics" "github.com/go-openapi/runtime" "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-retryablehttp" "github.com/hashicorp/consul/agent/hcp/client" + "github.com/hashicorp/consul/agent/hcp/config" "github.com/hashicorp/consul/agent/hcp/telemetry" + "github.com/hashicorp/consul/version" ) var ( @@ -28,21 +35,39 @@ var ( ) // Ensure hcpProviderImpl implements telemetry provider interfaces. +var _ TelemetryProvider = &hcpProviderImpl{} var _ telemetry.ConfigProvider = &hcpProviderImpl{} var _ telemetry.EndpointProvider = &hcpProviderImpl{} +var _ client.MetricsClientProvider = &hcpProviderImpl{} // hcpProviderImpl holds telemetry configuration and settings for continuous fetch of new config from HCP. // it updates configuration, if changes are detected. type hcpProviderImpl struct { // cfg holds configuration that can be dynamically updated. cfg *dynamicConfig + // httpCfg holds configuration for the HTTP client + httpCfg *httpCfg - // A reader-writer mutex is used as the provider is read heavy. + // Reader-writer mutexes are used as the provider is read heavy. // OTEL components access telemetryConfig during metrics collection and export (read). - // Meanwhile, config is only updated when there are changes (write). - rw sync.RWMutex + // Meanwhile, configs are only updated when there are changes (write). + rw sync.RWMutex + httpCfgRW sync.RWMutex + + // running indicates if the HCP telemetry config provider has been started + running bool + + // stopCh is used to signal that the telemetry config provider should stop running. + stopCh chan struct{} + // hcpClient is an authenticated client used to make HTTP requests to HCP. hcpClient client.Client + + // logger is the HCP logger for the provider + logger hclog.Logger + + // testUpdateConfigCh is used by unit tests to signal when an update config has occurred + testUpdateConfigCh chan struct{} } // dynamicConfig is a set of configurable settings for metrics collection, processing and export. @@ -67,25 +92,64 @@ func defaultDisabledCfg() *dynamicConfig { } } +// httpCfg is a set of configurable settings for the HTTP client used to export metrics +type httpCfg struct { + header *http.Header + client *retryablehttp.Client +} + +//go:generate mockery --name TelemetryProvider --with-expecter --inpackage +type TelemetryProvider interface { + Start(ctx context.Context, c *HCPProviderCfg) error + Stop() +} + +type HCPProviderCfg struct { + HCPClient client.Client + HCPConfig config.CloudConfigurer +} + // NewHCPProvider initializes and starts a HCP Telemetry provider. -func NewHCPProvider(ctx context.Context, hcpClient client.Client) *hcpProviderImpl { +func NewHCPProvider(ctx context.Context) *hcpProviderImpl { h := &hcpProviderImpl{ // Initialize with default config values. - cfg: defaultDisabledCfg(), - hcpClient: hcpClient, + cfg: defaultDisabledCfg(), + httpCfg: &httpCfg{}, + logger: hclog.FromContext(ctx), + } + + return h +} + +// Start starts a process that continuously checks for updates to the telemetry configuration +// by making a request to HCP. It only starts running if it's not already running. +func (h *hcpProviderImpl) Start(ctx context.Context, c *HCPProviderCfg) error { + changed := h.setRunning(true) + if !changed { + // Provider is already running. + return nil + } + + // Update the provider with the HCP configurations + h.hcpClient = c.HCPClient + err := h.updateHTTPConfig(c.HCPConfig) + if err != nil { + return fmt.Errorf("failed to initialize HCP telemetry provider: %v", err) } go h.run(ctx) - return h + return nil } -// run continously checks for updates to the telemetry configuration by making a request to HCP. -func (h *hcpProviderImpl) run(ctx context.Context) { +// run continuously checks for updates to the telemetry configuration by making a request to HCP. +func (h *hcpProviderImpl) run(ctx context.Context) error { + h.logger.Debug("starting telemetry config provider") + // Try to initialize config once before starting periodic fetch. h.updateConfig(ctx) - ticker := time.NewTicker(h.cfg.refreshInterval) + ticker := time.NewTicker(h.getRefreshInterval()) defer ticker.Stop() for { select { @@ -94,18 +158,37 @@ func (h *hcpProviderImpl) run(ctx context.Context) { ticker.Reset(newRefreshInterval) } case <-ctx.Done(): - return + return nil + case <-h.stopCh: + return nil } } } // updateConfig makes a HTTP request to HCP to update metrics configuration held in the provider. func (h *hcpProviderImpl) updateConfig(ctx context.Context) time.Duration { - logger := hclog.FromContext(ctx).Named("telemetry_config_provider") + logger := h.logger.Named("telemetry_config_provider") + + if h.testUpdateConfigCh != nil { + defer func() { + select { + case h.testUpdateConfigCh <- struct{}{}: + default: + } + }() + } + + if h.hcpClient == nil || reflect.ValueOf(h.hcpClient).IsNil() { + // Disable metrics if HCP client is not configured + disabledMetricsCfg := defaultDisabledCfg() + h.modifyDynamicCfg(disabledMetricsCfg) + return disabledMetricsCfg.refreshInterval + } ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() + logger.Trace("fetching telemetry config") telemetryCfg, err := h.hcpClient.FetchTelemetryConfig(ctx) if err != nil { // Only disable metrics on 404 or 401 to handle the case of an unlinked cluster. @@ -121,6 +204,7 @@ func (h *hcpProviderImpl) updateConfig(ctx context.Context) time.Duration { metrics.IncrCounter(internalMetricRefreshFailure, 1) return 0 } + logger.Trace("successfully fetched telemetry config") // newRefreshInterval of 0 or less can cause ticker Reset() panic. newRefreshInterval := telemetryCfg.RefreshConfig.RefreshInterval @@ -152,6 +236,13 @@ func (h *hcpProviderImpl) modifyDynamicCfg(newCfg *dynamicConfig) { metrics.IncrCounter(internalMetricRefreshSuccess, 1) } +func (h *hcpProviderImpl) getRefreshInterval() time.Duration { + h.rw.RLock() + defer h.rw.RUnlock() + + return h.cfg.refreshInterval +} + // GetEndpoint acquires a read lock to return endpoint configuration for consumers. func (h *hcpProviderImpl) GetEndpoint() *url.URL { h.rw.RLock() @@ -183,3 +274,96 @@ func (h *hcpProviderImpl) IsDisabled() bool { return h.cfg.disabled } + +// updateHTTPConfig updates the HTTP configuration values that rely on the HCP configuration. +func (h *hcpProviderImpl) updateHTTPConfig(cfg config.CloudConfigurer) error { + h.httpCfgRW.Lock() + defer h.httpCfgRW.Unlock() + + if cfg == nil { + return errors.New("must provide valid HCP configuration") + } + + // Update headers + r, err := cfg.Resource() + if err != nil { + return fmt.Errorf("failed set telemetry client headers: %v", err) + } + header := make(http.Header) + header.Set("content-type", "application/x-protobuf") + header.Set("x-hcp-resource-id", r.String()) + header.Set("x-channel", fmt.Sprintf("consul/%s", version.GetHumanVersion())) + h.httpCfg.header = &header + + // Update HTTP client + hcpCfg, err := cfg.HCPConfig() + if err != nil { + return fmt.Errorf("failed to configure telemetry HTTP client: %v", err) + } + h.httpCfg.client = client.NewHTTPClient(hcpCfg.APITLSConfig(), hcpCfg) + + return nil +} + +// GetHeader acquires a read lock to return the HTTP request headers needed +// to export metrics. +func (h *hcpProviderImpl) GetHeader() http.Header { + h.httpCfgRW.RLock() + defer h.httpCfgRW.RUnlock() + + if h.httpCfg.header == nil { + return nil + } + + return h.httpCfg.header.Clone() +} + +// GetHTTPClient acquires a read lock to return the retryable HTTP client needed +// to export metrics. +func (h *hcpProviderImpl) GetHTTPClient() *retryablehttp.Client { + h.httpCfgRW.RLock() + defer h.httpCfgRW.RUnlock() + + return h.httpCfg.client +} + +// setRunning acquires a write lock to set whether the provider is running. +// If the given value is the same as the current running status, it returns +// false. If current status is updated to the given status, it returns true. +func (h *hcpProviderImpl) setRunning(r bool) bool { + h.rw.Lock() + defer h.rw.Unlock() + + if h.running == r { + return false + } + + // Initialize or close the stop channel depending what running status + // we're transitioning to. Channel must be initialized on start since + // a provider can be stopped and started multiple times. + if r { + h.stopCh = make(chan struct{}) + } else { + close(h.stopCh) + } + + h.running = r + + return true +} + +// Stop acquires a write lock to mark the provider as not running and sends a stop signal to the +// main run loop. It also updates the provider with a disabled configuration. +func (h *hcpProviderImpl) Stop() { + changed := h.setRunning(false) + if !changed { + h.logger.Trace("telemetry config provider already stopped") + return + } + + h.rw.Lock() + h.cfg = defaultDisabledCfg() + h.rw.Unlock() + + h.logger.Debug("telemetry config provider stopped") +} diff --git a/agent/hcp/telemetry_provider_test.go b/agent/hcp/telemetry_provider_test.go index a147183df44d..6801b9271ebc 100644 --- a/agent/hcp/telemetry_provider_test.go +++ b/agent/hcp/telemetry_provider_test.go @@ -5,8 +5,8 @@ package hcp import ( "context" - "errors" "fmt" + "net/http" "net/url" "regexp" "strings" @@ -21,6 +21,9 @@ import ( "github.com/stretchr/testify/require" "github.com/hashicorp/consul/agent/hcp/client" + "github.com/hashicorp/consul/agent/hcp/config" + "github.com/hashicorp/consul/version" + "github.com/hashicorp/go-hclog" ) const ( @@ -49,11 +52,8 @@ func TestNewTelemetryConfigProvider_DefaultConfig(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - // Initialize new provider, but fail all HCP fetches. - mc := client.NewMockClient(t) - mc.EXPECT().FetchTelemetryConfig(mock.Anything).Return(nil, errors.New("failed to fetch config")) - - provider := NewHCPProvider(ctx, mc) + // Initialize new provider + provider := NewHCPProvider(ctx) provider.updateConfig(ctx) // Assert provider has default configuration and metrics processing is disabled. @@ -74,6 +74,7 @@ func TestTelemetryConfigProvider_UpdateConfig(t *testing.T) { initCfg *dynamicConfig expected *dynamicConfig expectedInterval time.Duration + skipHCPClient bool }{ "noChanges": { initCfg: testDynamicCfg(&testConfig{ @@ -236,16 +237,34 @@ func TestTelemetryConfigProvider_UpdateConfig(t *testing.T) { metricKey: testMetricKeySuccess, expectedInterval: defaultTelemetryConfigRefreshInterval, }, + "hcpClientNotConfigured": { + skipHCPClient: true, + initCfg: testDynamicCfg(&testConfig{ + endpoint: "http://test.com/v1/metrics", + filters: "test", + labels: map[string]string{ + "test_label": "123", + }, + refreshInterval: testRefreshInterval, + }), + expected: defaultDisabledCfg(), + metricKey: testMetricKeySuccess, + expectedInterval: defaultTelemetryConfigRefreshInterval, + }, } { tc := tc t.Run(name, func(t *testing.T) { sink := initGlobalSink() - mockClient := client.NewMockClient(t) - tc.mockExpect(mockClient) + var mockClient *client.MockClient + if !tc.skipHCPClient { + mockClient = client.NewMockClient(t) + tc.mockExpect(mockClient) + } provider := &hcpProviderImpl{ hcpClient: mockClient, cfg: tc.initCfg, + logger: hclog.NewNullLogger(), } newInterval := provider.updateConfig(context.Background()) @@ -267,6 +286,212 @@ func TestTelemetryConfigProvider_UpdateConfig(t *testing.T) { } } +func TestTelemetryConfigProvider_Start(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + provider := NewHCPProvider(ctx) + + testUpdateConfigCh := make(chan struct{}, 1) + provider.testUpdateConfigCh = testUpdateConfigCh + + // Configure mocks + mockClient := client.NewMockClient(t) + mTelemetryCfg, err := testTelemetryCfg(&testConfig{ + endpoint: "http://test.com/v1/metrics", + filters: "test", + labels: map[string]string{ + "test_label": "123", + }, + refreshInterval: testRefreshInterval, + }) + require.NoError(t, err) + mockClient.EXPECT().FetchTelemetryConfig(mock.Anything).Return(mTelemetryCfg, nil) + mockHCPCfg := &config.MockCloudCfg{} + + // Run provider + go provider.Start(context.Background(), &HCPProviderCfg{ + HCPClient: mockClient, + HCPConfig: mockHCPCfg, + }) + + // Expect at least two update config calls to validate provider is running + // and has entered the main run loop + select { + case <-testUpdateConfigCh: + case <-time.After(time.Second): + require.Fail(t, "provider did not attempt to update config in expected time") + } + select { + case <-testUpdateConfigCh: + case <-time.After(time.Millisecond * 500): + require.Fail(t, "provider did not attempt to update config in expected time") + } + + mockClient.AssertExpectations(t) +} + +func TestTelemetryConfigProvider_MultipleRun(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + provider := NewHCPProvider(ctx) + + testUpdateConfigCh := make(chan struct{}, 1) + provider.testUpdateConfigCh = testUpdateConfigCh + + // Configure mocks + mockClient := client.NewMockClient(t) + mTelemetryCfg, err := testTelemetryCfg(&testConfig{ + refreshInterval: 30 * time.Minute, + }) + require.NoError(t, err) + mockClient.EXPECT().FetchTelemetryConfig(mock.Anything).Return(mTelemetryCfg, nil) + mockHCPCfg := &config.MockCloudCfg{} + + // Run provider twice in parallel + go provider.Start(context.Background(), &HCPProviderCfg{ + HCPClient: mockClient, + HCPConfig: mockHCPCfg, + }) + go provider.Start(context.Background(), &HCPProviderCfg{ + HCPClient: mockClient, + HCPConfig: mockHCPCfg, + }) + + // Expect only one update config call + select { + case <-testUpdateConfigCh: + case <-time.After(time.Second): + require.Fail(t, "provider did not attempt to update config in expected time") + } + + select { + case <-testUpdateConfigCh: + require.Fail(t, "provider unexpectedly updated config") + case <-time.After(time.Second): + } + + // Try calling run again, should not update again + provider.Start(context.Background(), &HCPProviderCfg{ + HCPClient: mockClient, + HCPConfig: mockHCPCfg, + }) + + select { + case <-testUpdateConfigCh: + require.Fail(t, "provider unexpectedly updated config") + case <-time.After(time.Second): + } + + mockClient.AssertExpectations(t) +} + +func TestTelemetryConfigProvider_updateHTTPConfig(t *testing.T) { + for name, test := range map[string]struct { + wantErr string + cfg config.CloudConfigurer + }{ + "success": { + cfg: &config.MockCloudCfg{}, + }, + "failsWithoutCloudCfg": { + wantErr: "must provide valid HCP configuration", + cfg: nil, + }, + "failsHCPConfig": { + wantErr: "failed to configure telemetry HTTP client", + cfg: config.MockCloudCfg{ + ConfigErr: fmt.Errorf("test bad hcp config"), + }, + }, + "failsBadResource": { + wantErr: "failed set telemetry client headers", + cfg: config.MockCloudCfg{ + ResourceErr: fmt.Errorf("test bad resource"), + }, + }, + } { + t.Run(name, func(t *testing.T) { + provider := NewHCPProvider(context.Background()) + err := provider.updateHTTPConfig(test.cfg) + + if test.wantErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), test.wantErr) + return + } + + require.NoError(t, err) + require.NotNil(t, provider.GetHTTPClient()) + + expectedHeader := make(http.Header) + expectedHeader.Set("content-type", "application/x-protobuf") + expectedHeader.Set("x-hcp-resource-id", "organization/test-org/project/test-project/test-type/test-id") + expectedHeader.Set("x-channel", fmt.Sprintf("consul/%s", version.GetHumanVersion())) + require.Equal(t, expectedHeader, provider.GetHeader()) + }) + } +} + +func TestTelemetryConfigProvider_Stop(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + provider := NewHCPProvider(ctx) + + testUpdateConfigCh := make(chan struct{}, 1) + provider.testUpdateConfigCh = testUpdateConfigCh + + // Configure mocks + mockClient := client.NewMockClient(t) + mTelemetryCfg, err := testTelemetryCfg(&testConfig{ + endpoint: "http://test.com/v1/metrics", + filters: "test", + labels: map[string]string{ + "test_label": "123", + }, + refreshInterval: testRefreshInterval, + }) + require.NoError(t, err) + mockClient.EXPECT().FetchTelemetryConfig(mock.Anything).Return(mTelemetryCfg, nil) + mockHCPCfg := &config.MockCloudCfg{} + + // Run provider + provider.Start(context.Background(), &HCPProviderCfg{ + HCPClient: mockClient, + HCPConfig: mockHCPCfg, + }) + + // Wait for at least two update config calls to ensure provider is running + // and has entered the main run loop + select { + case <-testUpdateConfigCh: + case <-time.After(time.Second): + require.Fail(t, "provider did not attempt to update config in expected time") + } + select { + case <-testUpdateConfigCh: + case <-time.After(time.Millisecond * 500): + require.Fail(t, "provider did not attempt to update config in expected time") + } + + // Stop the provider + provider.Stop() + require.Equal(t, defaultDisabledCfg(), provider.cfg) + select { + case <-testUpdateConfigCh: + require.Fail(t, "provider should not attempt to update config after stop") + case <-time.After(time.Second): + // Success, no updates have happened after stopping + } + + mockClient.AssertExpectations(t) +} + // mockRaceClient is a mock HCP client that fetches TelemetryConfig. // The mock TelemetryConfig returned can be manually updated at any time. // It manages concurrent read/write access to config with a sync.RWMutex. @@ -335,7 +560,9 @@ func TestTelemetryConfigProvider_Race(t *testing.T) { } // Start the provider goroutine, which fetches client TelemetryConfig every RefreshInterval. - provider := NewHCPProvider(ctx, m) + provider := NewHCPProvider(ctx) + err = provider.Start(context.Background(), &HCPProviderCfg{m, config.MockCloudCfg{}}) + require.NoError(t, err) for count := 0; count < testRaceWriteSampleCount; count++ { // Force a TelemetryConfig value change in the mockRaceClient. diff --git a/agent/hcp/testing.go b/agent/hcp/testing.go index 30f7ba7bcdeb..1c0f364b0dd3 100644 --- a/agent/hcp/testing.go +++ b/agent/hcp/testing.go @@ -154,7 +154,7 @@ func (s *MockHCPServer) handleStatus(r *http.Request, cluster resource.Resource) req.ServerState.Raft.IsLeader, req.ServerState.Raft.KnownLeader, req.ServerState.Autopilot.Healthy, - time.Until(time.Time(req.ServerState.TLS.CertExpiry)).Hours()/24, + time.Until(time.Time(req.ServerState.ServerTLS.InternalRPC.CertExpiry)).Hours()/24, ) s.servers[req.ServerState.Name] = &gnmmod.HashicorpCloudGlobalNetworkManager20220215Server{ GossipPort: req.ServerState.GossipPort, diff --git a/agent/health_endpoint.go b/agent/health_endpoint.go index 3b888988d273..0001c35a1121 100644 --- a/agent/health_endpoint.go +++ b/agent/health_endpoint.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/internal/dnsutil" ) const ( @@ -187,6 +188,10 @@ func (s *HTTPHandlers) healthServiceNodes(resp http.ResponseWriter, req *http.Re } s.parsePeerName(req, &args) + s.parseSamenessGroup(req, &args) + if args.SamenessGroup != "" && args.PeerName != "" { + return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "peer-name and sameness-group are mutually exclusive"} + } // Check for tags params := req.URL.Query() @@ -213,12 +218,24 @@ func (s *HTTPHandlers) healthServiceNodes(resp http.ResponseWriter, req *http.Re prefix = "/v1/health/service/" } - // Pull out the service name + // Parse the service name from the query params args.ServiceName = strings.TrimPrefix(req.URL.Path, prefix) if args.ServiceName == "" { return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "Missing service name"} } + // Parse the passing flag from the query params and use to set the health filter type + // to HealthFilterIncludeOnlyPassing if it is present. Otherwise, do not filter by health. + passing, err := getBoolQueryParam(params, api.HealthPassing) + if err != nil { + return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "Invalid value for ?passing"} + } + healthFilterType := structs.HealthFilterIncludeAll + if passing { + healthFilterType = structs.HealthFilterIncludeOnlyPassing + } + args.HealthFilterType = healthFilterType + out, md, err := s.agent.rpcClientHealth.ServiceNodes(req.Context(), args) if err != nil { return nil, err @@ -228,22 +245,10 @@ func (s *HTTPHandlers) healthServiceNodes(resp http.ResponseWriter, req *http.Re setCacheMeta(resp, &md) } out.QueryMeta.ConsistencyLevel = args.QueryOptions.ConsistencyLevel() - setMeta(resp, &out.QueryMeta) - - // FIXME: argument parsing should be done before performing the rpc - // Filter to only passing if specified - filter, err := getBoolQueryParam(params, api.HealthPassing) - if err != nil { - return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "Invalid value for ?passing"} - } - - // FIXME: remove filterNonPassing, replace with nodes.Filter, which is used by DNSServer - if filter { - out.Nodes = filterNonPassing(out.Nodes) - } + _ = setMeta(resp, &out.QueryMeta) // Translate addresses after filtering so we don't waste effort. - s.agent.TranslateAddresses(args.Datacenter, out.Nodes, TranslateAddressAcceptAny) + s.agent.TranslateAddresses(args.Datacenter, out.Nodes, dnsutil.TranslateAddressAcceptAny) // Use empty list instead of nil if out.Nodes == nil { @@ -289,25 +294,3 @@ func getBoolQueryParam(params url.Values, key string) (bool, error) { } return param, nil } - -// filterNonPassing is used to filter out any nodes that have check that are not passing -func filterNonPassing(nodes structs.CheckServiceNodes) structs.CheckServiceNodes { - n := len(nodes) - - // Make a copy of the cached nodes rather than operating on the cache directly - out := append(nodes[:0:0], nodes...) - -OUTER: - for i := 0; i < n; i++ { - node := out[i] - for _, check := range node.Checks { - if check.Status != api.HealthPassing { - out[i], out[n-1] = out[n-1], structs.CheckServiceNode{} - n-- - i-- - continue OUTER - } - } - } - return out[:n] -} diff --git a/agent/health_endpoint_ce_test.go b/agent/health_endpoint_ce_test.go new file mode 100644 index 000000000000..fd02d5a55390 --- /dev/null +++ b/agent/health_endpoint_ce_test.go @@ -0,0 +1,30 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +//go:build !consulent + +package agent + +import ( + "github.com/hashicorp/consul/testrpc" + "github.com/stretchr/testify/require" + "net/http" + "net/http/httptest" + "testing" +) + +func TestHealthServiceNodes_SamenessGroup_ErrorsOnCE(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + + req, _ := http.NewRequest("GET", "/v1/health/service/consul?dc=dc1&sameness-group=foo", nil) + resp := httptest.NewRecorder() + _, err := a.srv.HealthServiceNodes(resp, req) + require.ErrorContains(t, err, "sameness groups are not supported in consul CE") +} diff --git a/agent/health_endpoint_test.go b/agent/health_endpoint_test.go index 4c491e9cb276..0768cbb22329 100644 --- a/agent/health_endpoint_test.go +++ b/agent/health_endpoint_test.go @@ -9,17 +9,17 @@ import ( "net/http" "net/http/httptest" "net/url" - "reflect" "strconv" "strings" "testing" "time" "github.com/armon/go-metrics" - "github.com/hashicorp/serf/coordinate" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/hashicorp/serf/coordinate" + "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil" @@ -28,25 +28,6 @@ import ( "github.com/hashicorp/consul/types" ) -func TestHealthEndpointsFailInV2(t *testing.T) { - t.Parallel() - - a := NewTestAgent(t, `experiments = ["resource-apis"]`) - - checkRequest := func(method, url string) { - t.Run(method+" "+url, func(t *testing.T) { - assertV1CatalogEndpointDoesNotWorkWithV2(t, a, method, url, "{}") - }) - } - - checkRequest("GET", "/v1/health/node/web") - checkRequest("GET", "/v1/health/checks/web") - checkRequest("GET", "/v1/health/state/web") - checkRequest("GET", "/v1/health/service/web") - checkRequest("GET", "/v1/health/connect/web") - checkRequest("GET", "/v1/health/ingress/web") -} - func TestHealthChecksInState(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") @@ -258,7 +239,7 @@ func TestHealthChecksInState_DistanceSort(t *testing.T) { if err != nil { r.Fatalf("err: %v", err) } - assertIndex(t, resp) + assertIndex(r, resp) nodes = obj.(structs.HealthChecks) if len(nodes) != 2 { r.Fatalf("bad: %v", nodes) @@ -613,7 +594,7 @@ func TestHealthServiceChecks_DistanceSort(t *testing.T) { if err != nil { r.Fatalf("err: %v", err) } - assertIndex(t, resp) + assertIndex(r, resp) nodes = obj.(structs.HealthChecks) if len(nodes) != 2 { r.Fatalf("bad: %v", obj) @@ -627,13 +608,54 @@ func TestHealthServiceChecks_DistanceSort(t *testing.T) { }) } +type queryBackendConfiguration struct { + name string + config string + cached bool + queryBackend string +} + +var queryBackendConfigs = []*queryBackendConfiguration{ + { + name: "blocking-query-without-cache", + config: `use_streaming_backend=false`, + cached: false, + queryBackend: "blocking-query", + }, + { + name: "blocking-query-with-cache", + config: `use_streaming_backend=false`, + cached: true, + queryBackend: "blocking-query", + }, + { + name: "streaming-with-cache-setting", + config: ` + rpc{ + enable_streaming=true + } + use_streaming_backend=true + `, + cached: true, + queryBackend: "streaming", + }, +} + func TestHealthServiceNodes(t *testing.T) { + for _, cfg := range queryBackendConfigs { + t.Run(cfg.name, func(t *testing.T) { + testHealthServiceNodes(t, cfg) + }) + } +} + +func testHealthServiceNodes(t *testing.T, backendCfg *queryBackendConfiguration) { if testing.Short() { t.Skip("too slow for testing.Short") } t.Parallel() - a := StartTestAgent(t, TestAgent{HCL: ``, Overrides: `peering = { test_allow_peer_registrations = true }`}) + a := StartTestAgent(t, TestAgent{HCL: backendCfg.config, Overrides: `peering = { test_allow_peer_registrations = true }`}) defer a.Shutdown() testrpc.WaitForTestAgent(t, a.RPC, "dc1") @@ -718,30 +740,44 @@ func TestHealthServiceNodes(t *testing.T) { // Test caching { // List instances with cache enabled - req, err := http.NewRequest("GET", "/v1/health/service/test?cached"+peerQuerySuffix(peerName), nil) + req, err := http.NewRequest("GET", "/v1/health/service/test?"+peerQuerySuffix(peerName), nil) require.NoError(t, err) + if backendCfg.cached { + addQueryParam(req, "cached", "true") + } resp := httptest.NewRecorder() obj, err := a.srv.HealthServiceNodes(resp, req) require.NoError(t, err) nodes := obj.(structs.CheckServiceNodes) verify(t, peerName, nodes) - // Should be a cache miss - require.Equal(t, "MISS", resp.Header().Get("X-Cache")) + if backendCfg.cached { + // Should be a cache miss + require.Equal(t, "MISS", resp.Header().Get("X-Cache")) + } + + require.Equal(t, backendCfg.queryBackend, resp.Header().Get("X-Consul-Query-Backend")) } { // List instances with cache enabled - req, err := http.NewRequest("GET", "/v1/health/service/test?cached"+peerQuerySuffix(peerName), nil) + req, err := http.NewRequest("GET", "/v1/health/service/test?"+peerQuerySuffix(peerName), nil) require.NoError(t, err) + if backendCfg.cached { + addQueryParam(req, "cached", "true") + } resp := httptest.NewRecorder() obj, err := a.srv.HealthServiceNodes(resp, req) require.NoError(t, err) nodes := obj.(structs.CheckServiceNodes) verify(t, peerName, nodes) - // Should be a cache HIT now! - require.Equal(t, "HIT", resp.Header().Get("X-Cache")) + if backendCfg.cached { + // Should be a cache HIT now! + require.Equal(t, "HIT", resp.Header().Get("X-Cache")) + } + + require.Equal(t, backendCfg.queryBackend, resp.Header().Get("X-Consul-Query-Backend")) } } @@ -761,8 +797,11 @@ func TestHealthServiceNodes(t *testing.T) { for _, peerName := range testingPeerNames { retry.Run(t, func(r *retry.R) { // List it again - req, err := http.NewRequest("GET", "/v1/health/service/test?cached"+peerQuerySuffix(peerName), nil) + req, err := http.NewRequest("GET", "/v1/health/service/test?"+peerQuerySuffix(peerName), nil) require.NoError(r, err) + if backendCfg.cached { + addQueryParam(req, "cached", "true") + } resp := httptest.NewRecorder() obj, err := a.srv.HealthServiceNodes(resp, req) require.NoError(r, err) @@ -777,12 +816,15 @@ func TestHealthServiceNodes(t *testing.T) { _, err = strconv.ParseUint(header, 10, 64) require.NoError(r, err) - // Should be a cache hit! The data should've updated in the cache - // in the background so this should've been fetched directly from - // the cache. - if resp.Header().Get("X-Cache") != "HIT" { - r.Fatalf("should be a cache hit") + if backendCfg.cached { + // Should be a cache hit! The data should've updated in the cache + // in the background so this should've been fetched directly from + // the cache. + if resp.Header().Get("X-Cache") != "HIT" { + r.Fatalf("should be a cache hit") + } } + require.Equal(r, backendCfg.queryBackend, resp.Header().Get("X-Consul-Query-Backend")) }) } } @@ -1237,12 +1279,20 @@ func TestHealthServiceNodes_NodeMetaFilter(t *testing.T) { } func TestHealthServiceNodes_Filter(t *testing.T) { + for _, cfg := range queryBackendConfigs { + t.Run(cfg.name, func(t *testing.T) { + testHealthServiceNodes_Filter(t, cfg) + }) + } +} + +func testHealthServiceNodes_Filter(t *testing.T, backendCfg *queryBackendConfiguration) { if testing.Short() { t.Skip("too slow for testing.Short") } t.Parallel() - a := NewTestAgent(t, "") + a := NewTestAgent(t, backendCfg.config) defer a.Shutdown() testrpc.WaitForTestAgent(t, a.RPC, "dc1") @@ -1290,6 +1340,9 @@ func TestHealthServiceNodes_Filter(t *testing.T) { require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) req, _ = http.NewRequest("GET", "/v1/health/service/consul?dc=dc1&filter="+url.QueryEscape("Node.Node == `test-health-node`"), nil) + if backendCfg.cached { + addQueryParam(req, "cached", "true") + } resp = httptest.NewRecorder() obj, err = a.srv.HealthServiceNodes(resp, req) require.NoError(t, err) @@ -1300,6 +1353,8 @@ func TestHealthServiceNodes_Filter(t *testing.T) { nodes = obj.(structs.CheckServiceNodes) require.Len(t, nodes, 1) require.Len(t, nodes[0].Checks, 1) + + require.Equal(t, backendCfg.queryBackend, resp.Header().Get("X-Consul-Query-Backend")) } func TestHealthServiceNodes_DistanceSort(t *testing.T) { @@ -1371,7 +1426,7 @@ func TestHealthServiceNodes_DistanceSort(t *testing.T) { if err != nil { r.Fatalf("err: %v", err) } - assertIndex(t, resp) + assertIndex(r, resp) nodes = obj.(structs.CheckServiceNodes) if len(nodes) != 2 { r.Fatalf("bad: %v", obj) @@ -1386,12 +1441,20 @@ func TestHealthServiceNodes_DistanceSort(t *testing.T) { } func TestHealthServiceNodes_PassingFilter(t *testing.T) { + for _, cfg := range queryBackendConfigs { + t.Run(cfg.name, func(t *testing.T) { + testHealthServiceNodes_PassingFilter(t, cfg) + }) + } +} + +func testHealthServiceNodes_PassingFilter(t *testing.T, backendCfg *queryBackendConfiguration) { if testing.Short() { t.Skip("too slow for testing.Short") } t.Parallel() - a := NewTestAgent(t, "") + a := NewTestAgent(t, backendCfg.config) defer a.Shutdown() dc := "dc1" @@ -1417,6 +1480,9 @@ func TestHealthServiceNodes_PassingFilter(t *testing.T) { t.Run("bc_no_query_value", func(t *testing.T) { req, _ := http.NewRequest("GET", "/v1/health/service/consul?passing", nil) + if backendCfg.cached { + addQueryParam(req, "cached", "") + } resp := httptest.NewRecorder() obj, err := a.srv.HealthServiceNodes(resp, req) if err != nil { @@ -1428,12 +1494,16 @@ func TestHealthServiceNodes_PassingFilter(t *testing.T) { // Should be 0 health check for consul nodes := obj.(structs.CheckServiceNodes) if len(nodes) != 0 { - t.Fatalf("bad: %v", obj) + t.Fatalf("bad: %v", nodes) } + require.Equal(t, backendCfg.queryBackend, resp.Header().Get("X-Consul-Query-Backend")) }) t.Run("passing_true", func(t *testing.T) { req, _ := http.NewRequest("GET", "/v1/health/service/consul?passing=true", nil) + if backendCfg.cached { + addQueryParam(req, "cached", "") + } resp := httptest.NewRecorder() obj, err := a.srv.HealthServiceNodes(resp, req) if err != nil { @@ -1447,10 +1517,14 @@ func TestHealthServiceNodes_PassingFilter(t *testing.T) { if len(nodes) != 0 { t.Fatalf("bad: %v", obj) } + require.Equal(t, backendCfg.queryBackend, resp.Header().Get("X-Consul-Query-Backend")) }) t.Run("passing_false", func(t *testing.T) { req, _ := http.NewRequest("GET", "/v1/health/service/consul?passing=false", nil) + if backendCfg.cached { + addQueryParam(req, "cached", "") + } resp := httptest.NewRecorder() obj, err := a.srv.HealthServiceNodes(resp, req) if err != nil { @@ -1465,16 +1539,21 @@ func TestHealthServiceNodes_PassingFilter(t *testing.T) { if len(nodes) != 1 { t.Fatalf("bad: %v", obj) } + require.Equal(t, backendCfg.queryBackend, resp.Header().Get("X-Consul-Query-Backend")) }) t.Run("passing_bad", func(t *testing.T) { req, _ := http.NewRequest("GET", "/v1/health/service/consul?passing=nope-nope-nope", nil) + if backendCfg.cached { + addQueryParam(req, "cached", "") + } resp := httptest.NewRecorder() _, err := a.srv.HealthServiceNodes(resp, req) require.True(t, isHTTPBadRequest(err), fmt.Sprintf("Expected bad request HTTP error but got %v", err)) if !strings.Contains(err.Error(), "Invalid value for ?passing") { t.Errorf("bad %s", err.Error()) } + require.Equal(t, "", resp.Header().Get("X-Consul-Query-Backend")) }) } @@ -1626,13 +1705,21 @@ func TestHealthServiceNodes_WanTranslation(t *testing.T) { } func TestHealthConnectServiceNodes(t *testing.T) { + for _, cfg := range queryBackendConfigs { + t.Run(cfg.name, func(t *testing.T) { + testHealthConnectServiceNodes(t, cfg) + }) + } +} + +func testHealthConnectServiceNodes(t *testing.T, backendCfg *queryBackendConfiguration) { if testing.Short() { t.Skip("too slow for testing.Short") } t.Parallel() - a := NewTestAgent(t, "") + a := NewTestAgent(t, backendCfg.config) defer a.Shutdown() // Register @@ -1643,6 +1730,9 @@ func TestHealthConnectServiceNodes(t *testing.T) { // Request req, _ := http.NewRequest("GET", fmt.Sprintf( "/v1/health/connect/%s?dc=dc1", args.Service.Proxy.DestinationServiceName), nil) + if backendCfg.cached { + addQueryParam(req, "cached", "true") + } resp := httptest.NewRecorder() obj, err := a.srv.HealthConnectServiceNodes(resp, req) assert.Nil(t, err) @@ -1652,6 +1742,8 @@ func TestHealthConnectServiceNodes(t *testing.T) { nodes := obj.(structs.CheckServiceNodes) assert.Len(t, nodes, 1) assert.Len(t, nodes[0].Checks, 0) + + require.Equal(t, backendCfg.queryBackend, resp.Header().Get("X-Consul-Query-Backend")) } func TestHealthIngressServiceNodes(t *testing.T) { @@ -1771,13 +1863,21 @@ func testHealthIngressServiceNodes(t *testing.T, agentHCL string) { } func TestHealthConnectServiceNodes_Filter(t *testing.T) { + for _, cfg := range queryBackendConfigs { + t.Run(cfg.name, func(t *testing.T) { + testHealthConnectServiceNodes_Filter(t, cfg) + }) + } +} + +func testHealthConnectServiceNodes_Filter(t *testing.T, backendCfg *queryBackendConfiguration) { if testing.Short() { t.Skip("too slow for testing.Short") } t.Parallel() - a := NewTestAgent(t, "") + a := NewTestAgent(t, backendCfg.config) defer a.Shutdown() testrpc.WaitForLeader(t, a.RPC, "dc1") @@ -1788,6 +1888,12 @@ func TestHealthConnectServiceNodes_Filter(t *testing.T) { require.NoError(t, a.RPC(context.Background(), "Catalog.Register", args, &out)) args = structs.TestRegisterRequestProxy(t) + // when using streaming these come back as empty slices rather than nil. + // rather than changing structs.TestRegisterRequestProxy(t) and the many places + // it is referenced without using caching, we'll just set them to empty slices here. + args.Service.Proxy.EnvoyExtensions = []structs.EnvoyExtension{} + args.Service.Proxy.Expose.Paths = []structs.ExposePath{} + args.Service.Address = "127.0.0.55" args.Service.Meta = map[string]string{ "version": "2", @@ -1800,6 +1906,9 @@ func TestHealthConnectServiceNodes_Filter(t *testing.T) { "/v1/health/connect/%s?filter=%s", args.Service.Proxy.DestinationServiceName, url.QueryEscape("Service.Meta.version == 2")), nil) + if backendCfg.cached { + addQueryParam(req, "cached", "true") + } resp := httptest.NewRecorder() obj, err := a.srv.HealthConnectServiceNodes(resp, req) require.NoError(t, err) @@ -1810,16 +1919,26 @@ func TestHealthConnectServiceNodes_Filter(t *testing.T) { require.Equal(t, structs.ServiceKindConnectProxy, nodes[0].Service.Kind) require.Equal(t, args.Service.Address, nodes[0].Service.Address) require.Equal(t, args.Service.Proxy, nodes[0].Service.Proxy) + + require.Equal(t, backendCfg.queryBackend, resp.Header().Get("X-Consul-Query-Backend")) } func TestHealthConnectServiceNodes_PassingFilter(t *testing.T) { + for _, cfg := range queryBackendConfigs { + t.Run(cfg.name, func(t *testing.T) { + testHealthConnectServiceNodes_PassingFilter(t, cfg) + }) + } +} + +func testHealthConnectServiceNodes_PassingFilter(t *testing.T, backendCfg *queryBackendConfiguration) { if testing.Short() { t.Skip("too slow for testing.Short") } t.Parallel() - a := NewTestAgent(t, "") + a := NewTestAgent(t, backendCfg.config) defer a.Shutdown() // Register @@ -1836,6 +1955,9 @@ func TestHealthConnectServiceNodes_PassingFilter(t *testing.T) { t.Run("bc_no_query_value", func(t *testing.T) { req, _ := http.NewRequest("GET", fmt.Sprintf( "/v1/health/connect/%s?passing", args.Service.Proxy.DestinationServiceName), nil) + if backendCfg.cached { + addQueryParam(req, "cached", "true") + } resp := httptest.NewRecorder() obj, err := a.srv.HealthConnectServiceNodes(resp, req) assert.Nil(t, err) @@ -1844,11 +1966,16 @@ func TestHealthConnectServiceNodes_PassingFilter(t *testing.T) { // Should be 0 health check for consul nodes := obj.(structs.CheckServiceNodes) assert.Len(t, nodes, 0) + + require.Equal(t, backendCfg.queryBackend, resp.Header().Get("X-Consul-Query-Backend")) }) t.Run("passing_true", func(t *testing.T) { req, _ := http.NewRequest("GET", fmt.Sprintf( "/v1/health/connect/%s?passing=true", args.Service.Proxy.DestinationServiceName), nil) + if backendCfg.cached { + addQueryParam(req, "cached", "true") + } resp := httptest.NewRecorder() obj, err := a.srv.HealthConnectServiceNodes(resp, req) assert.Nil(t, err) @@ -1857,11 +1984,16 @@ func TestHealthConnectServiceNodes_PassingFilter(t *testing.T) { // Should be 0 health check for consul nodes := obj.(structs.CheckServiceNodes) assert.Len(t, nodes, 0) + + require.Equal(t, backendCfg.queryBackend, resp.Header().Get("X-Consul-Query-Backend")) }) t.Run("passing_false", func(t *testing.T) { req, _ := http.NewRequest("GET", fmt.Sprintf( "/v1/health/connect/%s?passing=false", args.Service.Proxy.DestinationServiceName), nil) + if backendCfg.cached { + addQueryParam(req, "cached", "true") + } resp := httptest.NewRecorder() obj, err := a.srv.HealthConnectServiceNodes(resp, req) assert.Nil(t, err) @@ -1870,57 +2002,25 @@ func TestHealthConnectServiceNodes_PassingFilter(t *testing.T) { // Should be 1 nodes := obj.(structs.CheckServiceNodes) assert.Len(t, nodes, 1) + require.Equal(t, backendCfg.queryBackend, resp.Header().Get("X-Consul-Query-Backend")) }) t.Run("passing_bad", func(t *testing.T) { req, _ := http.NewRequest("GET", fmt.Sprintf( "/v1/health/connect/%s?passing=nope-nope", args.Service.Proxy.DestinationServiceName), nil) + if backendCfg.cached { + addQueryParam(req, "cached", "true") + } resp := httptest.NewRecorder() _, err := a.srv.HealthConnectServiceNodes(resp, req) assert.NotNil(t, err) assert.True(t, isHTTPBadRequest(err)) assert.True(t, strings.Contains(err.Error(), "Invalid value for ?passing")) + require.Equal(t, "", resp.Header().Get("X-Consul-Query-Backend")) }) } -func TestFilterNonPassing(t *testing.T) { - t.Parallel() - nodes := structs.CheckServiceNodes{ - structs.CheckServiceNode{ - Checks: structs.HealthChecks{ - &structs.HealthCheck{ - Status: api.HealthCritical, - }, - &structs.HealthCheck{ - Status: api.HealthCritical, - }, - }, - }, - structs.CheckServiceNode{ - Checks: structs.HealthChecks{ - &structs.HealthCheck{ - Status: api.HealthCritical, - }, - &structs.HealthCheck{ - Status: api.HealthCritical, - }, - }, - }, - structs.CheckServiceNode{ - Checks: structs.HealthChecks{ - &structs.HealthCheck{ - Status: api.HealthPassing, - }, - }, - }, - } - out := filterNonPassing(nodes) - if len(out) != 1 && reflect.DeepEqual(out[0], nodes[2]) { - t.Fatalf("bad: %v", out) - } -} - func TestListHealthyServiceNodes_MergeCentralConfig(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") diff --git a/agent/http.go b/agent/http.go index aed7c920cdf9..506377074a6e 100644 --- a/agent/http.go +++ b/agent/http.go @@ -6,6 +6,7 @@ package agent import ( "encoding/json" "fmt" + "github.com/hashicorp/go-hclog" "io" "net" "net/http" @@ -22,12 +23,13 @@ import ( "github.com/NYTimes/gziphandler" "github.com/armon/go-metrics" "github.com/armon/go-metrics/prometheus" - "github.com/hashicorp/go-cleanhttp" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/cache" "github.com/hashicorp/consul/agent/config" @@ -42,6 +44,11 @@ import ( "github.com/hashicorp/consul/proto/private/pbcommon" ) +const ( + contentTypeHeader = "Content-Type" + plainContentType = "text/plain; charset=utf-8" +) + var HTTPSummaries = []prometheus.SummaryDefinition{ { Name: []string{"api", "http"}, @@ -188,7 +195,9 @@ func (s *HTTPHandlers) handler() http.Handler { // Register the wrapper. wrapper := func(resp http.ResponseWriter, req *http.Request) { start := time.Now() - handler(resp, req) + + // this method is implemented by different flavours of consul e.g. oss, ce. ent. + s.enterpriseRequest(resp, req, handler) labels := []metrics.Label{{Name: "method", Value: req.Method}, {Name: "path", Value: path_label}} metrics.MeasureSinceWithLabels([]string{"api", "http"}, start, labels) @@ -217,6 +226,7 @@ func (s *HTTPHandlers) handler() http.Handler { // If enableDebug register wrapped pprof handlers if !s.agent.enableDebug.Load() && s.checkACLDisabled() { resp.WriteHeader(http.StatusNotFound) + resp.Header().Set(contentTypeHeader, plainContentType) return } @@ -225,6 +235,7 @@ func (s *HTTPHandlers) handler() http.Handler { authz, err := s.agent.delegate.ResolveTokenAndDefaultMeta(token, nil, nil) if err != nil { + resp.Header().Set(contentTypeHeader, plainContentType) resp.WriteHeader(http.StatusForbidden) return } @@ -234,6 +245,7 @@ func (s *HTTPHandlers) handler() http.Handler { // TODO(partitions): should this be possible in a partition? // TODO(acl-error-enhancements): We should return error details somehow here. if authz.OperatorRead(nil) != acl.Allow { + resp.Header().Set(contentTypeHeader, plainContentType) resp.WriteHeader(http.StatusForbidden) return } @@ -260,9 +272,11 @@ func (s *HTTPHandlers) handler() http.Handler { handlePProf("/debug/pprof/symbol", pprof.Symbol) handlePProf("/debug/pprof/trace", pprof.Trace) - mux.Handle("/api/", - http.StripPrefix("/api", + resourceAPIPrefix := "/api" + mux.Handle(resourceAPIPrefix+"/", + http.StripPrefix(resourceAPIPrefix, resourcehttp.NewHandler( + resourceAPIPrefix, s.agent.delegate.ResourceServiceClient(), s.agent.baseDeps.Registry, s.parseToken, @@ -311,8 +325,9 @@ func (s *HTTPHandlers) handler() http.Handler { h = mux } - h = s.enterpriseHandler(h) h = withRemoteAddrHandler(h) + h = ensureContentTypeHeader(h, s.agent.logger) + s.h = &wrappedMux{ mux: mux, handler: h, @@ -333,6 +348,20 @@ func withRemoteAddrHandler(next http.Handler) http.Handler { }) } +// Injects content type explicitly if not already set into response to prevent XSS +func ensureContentTypeHeader(next http.Handler, logger hclog.Logger) http.Handler { + + return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { + next.ServeHTTP(resp, req) + + val := resp.Header().Get(contentTypeHeader) + if val == "" { + resp.Header().Set(contentTypeHeader, plainContentType) + logger.Debug("warning: content-type header not explicitly set.", "request-path", req.URL) + } + }) +} + // nodeName returns the node name of the agent func (s *HTTPHandlers) nodeName() string { return s.agent.config.NodeName @@ -376,6 +405,8 @@ func (s *HTTPHandlers) wrap(handler endpoint, methods []string) http.HandlerFunc "from", req.RemoteAddr, "error", err, ) + //set response type to plain to prevent XSS + resp.Header().Set(contentTypeHeader, plainContentType) resp.WriteHeader(http.StatusInternalServerError) return } @@ -389,16 +420,11 @@ func (s *HTTPHandlers) wrap(handler endpoint, methods []string) http.HandlerFunc logURL = strings.Replace(logURL, token, "", -1) } httpLogger.Warn("This request used the token query parameter "+ - "which is deprecated and will be removed in Consul 1.17", + "which is deprecated and will be removed in a future Consul version", "logUrl", logURL) } logURL = aclEndpointRE.ReplaceAllString(logURL, "$1$4") - rejectCatalogV1Endpoint := false - if s.agent.baseDeps.UseV2Resources() { - rejectCatalogV1Endpoint = isV1CatalogRequest(req.URL.Path) - } - if s.denylist.Block(req.URL.Path) { errMsg := "Endpoint is blocked by agent configuration" httpLogger.Error("Request error", @@ -407,6 +433,8 @@ func (s *HTTPHandlers) wrap(handler endpoint, methods []string) http.HandlerFunc "from", req.RemoteAddr, "error", errMsg, ) + //set response type to plain to prevent XSS + resp.Header().Set(contentTypeHeader, plainContentType) resp.WriteHeader(http.StatusForbidden) fmt.Fprint(resp, errMsg) return @@ -460,14 +488,6 @@ func (s *HTTPHandlers) wrap(handler endpoint, methods []string) http.HandlerFunc return strings.Contains(err.Error(), rate.ErrRetryLater.Error()) } - isUsingV2CatalogExperiment := func(err error) bool { - if err == nil { - return false - } - - return structs.IsErrUsingV2CatalogExperiment(err) - } - isMethodNotAllowed := func(err error) bool { _, ok := err.(MethodNotAllowedError) return ok @@ -503,10 +523,6 @@ func (s *HTTPHandlers) wrap(handler endpoint, methods []string) http.HandlerFunc msg = s.Message() } - if isUsingV2CatalogExperiment(err) && !isHTTPError(err) { - err = newRejectV1RequestWhenV2EnabledError() - } - switch { case isForbidden(err): resp.WriteHeader(http.StatusForbidden) @@ -583,12 +599,7 @@ func (s *HTTPHandlers) wrap(handler endpoint, methods []string) http.HandlerFunc if err == nil { // Invoke the handler - if rejectCatalogV1Endpoint { - obj = nil - err = s.rejectV1RequestWhenV2Enabled() - } else { - obj, err = handler(resp, req) - } + obj, err = handler(resp, req) } } contentType := "application/json" @@ -603,6 +614,8 @@ func (s *HTTPHandlers) wrap(handler endpoint, methods []string) http.HandlerFunc resp.Header().Add("X-Consul-Reason", errPayload.Reason) } } else { + //set response type to plain to prevent XSS + resp.Header().Set(contentTypeHeader, plainContentType) handleErr(err) return } @@ -614,6 +627,8 @@ func (s *HTTPHandlers) wrap(handler endpoint, methods []string) http.HandlerFunc if contentType == "application/json" { buf, err = s.marshalJSON(req, obj) if err != nil { + //set response type to plain to prevent XSS + resp.Header().Set(contentTypeHeader, plainContentType) handleErr(err) return } @@ -624,52 +639,12 @@ func (s *HTTPHandlers) wrap(handler endpoint, methods []string) http.HandlerFunc } } } - resp.Header().Set("Content-Type", contentType) + resp.Header().Set(contentTypeHeader, contentType) resp.WriteHeader(httpCode) resp.Write(buf) } } -func isV1CatalogRequest(logURL string) bool { - switch { - case strings.HasPrefix(logURL, "/v1/catalog/"), - strings.HasPrefix(logURL, "/v1/health/"), - strings.HasPrefix(logURL, "/v1/config/"): - return true - - case strings.HasPrefix(logURL, "/v1/agent/token/"), - logURL == "/v1/agent/self", - logURL == "/v1/agent/host", - logURL == "/v1/agent/version", - logURL == "/v1/agent/reload", - logURL == "/v1/agent/monitor", - logURL == "/v1/agent/metrics", - logURL == "/v1/agent/metrics/stream", - logURL == "/v1/agent/members", - strings.HasPrefix(logURL, "/v1/agent/join/"), - logURL == "/v1/agent/leave", - strings.HasPrefix(logURL, "/v1/agent/force-leave/"), - logURL == "/v1/agent/connect/authorize", - logURL == "/v1/agent/connect/ca/roots", - strings.HasPrefix(logURL, "/v1/agent/connect/ca/leaf/"): - return false - - case strings.HasPrefix(logURL, "/v1/agent/"): - return true - - case logURL == "/v1/internal/acl/authorize", - logURL == "/v1/internal/service-virtual-ip", - logURL == "/v1/internal/ui/oidc-auth-methods", - strings.HasPrefix(logURL, "/v1/internal/ui/metrics-proxy/"): - return false - - case strings.HasPrefix(logURL, "/v1/internal/"): - return true - default: - return false - } -} - // marshalJSON marshals the object into JSON, respecting the user's pretty-ness // configuration. func (s *HTTPHandlers) marshalJSON(req *http.Request, obj interface{}) ([]byte, error) { @@ -736,7 +711,7 @@ func decodeBody(body io.Reader, out interface{}) error { return lib.DecodeJSON(body, out) } -// decodeBodyDeprecated is deprecated, please ues decodeBody above. +// decodeBodyDeprecated is deprecated, please use decodeBody above. // decodeBodyDeprecated is used to decode a JSON request body func decodeBodyDeprecated(req *http.Request, out interface{}, cb func(interface{}) error) error { // This generally only happens in tests since real HTTP requests set @@ -1146,20 +1121,6 @@ func (s *HTTPHandlers) parseToken(req *http.Request, token *string) { s.parseTokenWithDefault(req, token) } -func (s *HTTPHandlers) rejectV1RequestWhenV2Enabled() error { - if s.agent.baseDeps.UseV2Resources() { - return newRejectV1RequestWhenV2EnabledError() - } - return nil -} - -func newRejectV1RequestWhenV2EnabledError() error { - return HTTPError{ - StatusCode: http.StatusBadRequest, - Reason: structs.ErrUsingV2CatalogExperiment.Error(), - } -} - func sourceAddrFromRequest(req *http.Request) string { xff := req.Header.Get("X-Forwarded-For") forwardHosts := strings.Split(xff, ",") @@ -1205,6 +1166,15 @@ func (s *HTTPHandlers) parsePeerName(req *http.Request, args *structs.ServiceSpe } } +func (s *HTTPHandlers) parseSamenessGroup(req *http.Request, args *structs.ServiceSpecificRequest) { + if sg := req.URL.Query().Get("sg"); sg != "" { + args.SamenessGroup = sg + } + if sg := req.URL.Query().Get("sameness-group"); sg != "" { + args.SamenessGroup = sg + } +} + // parseMetaFilter is used to parse the ?node-meta=key:value query parameter, used for // filtering results to nodes with the given metadata key/value func (s *HTTPHandlers) parseMetaFilter(req *http.Request) map[string]string { diff --git a/agent/http_ce.go b/agent/http_ce.go index da6bef723776..0259dc738fb4 100644 --- a/agent/http_ce.go +++ b/agent/http_ce.go @@ -95,9 +95,9 @@ func parseACLAuthMethodEnterpriseMeta(req *http.Request, _ *structs.ACLAuthMetho return nil } -// enterpriseHandler is a noop for the enterprise implementation. we pass the original back -func (s *HTTPHandlers) enterpriseHandler(next http.Handler) http.Handler { - return next +func (s *HTTPHandlers) enterpriseRequest(w http.ResponseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) { + // no special handling for CE. Calling the default handler with default params. + handler(w, req) } // uiTemplateDataTransform returns an optional uiserver.UIDataTransform to allow diff --git a/agent/http_register.go b/agent/http_register.go index 340f7ef0fe04..69820c4d7cfe 100644 --- a/agent/http_register.go +++ b/agent/http_register.go @@ -86,6 +86,7 @@ func init() { registerEndpoint("/v1/internal/federation-states/mesh-gateways", []string{"GET"}, (*HTTPHandlers).FederationStateListMeshGateways) registerEndpoint("/v1/internal/federation-state/", []string{"GET"}, (*HTTPHandlers).FederationStateGet) registerEndpoint("/v1/discovery-chain/", []string{"GET", "POST"}, (*HTTPHandlers).DiscoveryChainRead) + registerEndpoint("/v1/exported-services", []string{"GET"}, (*HTTPHandlers).ExportedServices) registerEndpoint("/v1/event/fire/", []string{"PUT"}, (*HTTPHandlers).EventFire) registerEndpoint("/v1/event/list", []string{"GET"}, (*HTTPHandlers).EventList) registerEndpoint("/v1/health/node/", []string{"GET"}, (*HTTPHandlers).HealthNodeChecks) diff --git a/agent/http_test.go b/agent/http_test.go index f2469acc8352..497789f68949 100644 --- a/agent/http_test.go +++ b/agent/http_test.go @@ -639,14 +639,14 @@ func TestHTTPAPIResponseHeaders(t *testing.T) { `) defer a.Shutdown() - requireHasHeadersSet(t, a, "/v1/agent/self") + requireHasHeadersSet(t, a, "/v1/agent/self", "application/json") // Check the Index page that just renders a simple message with UI disabled // also gets the right headers. - requireHasHeadersSet(t, a, "/") + requireHasHeadersSet(t, a, "/", "text/plain; charset=utf-8") } -func requireHasHeadersSet(t *testing.T, a *TestAgent, path string) { +func requireHasHeadersSet(t *testing.T, a *TestAgent, path string, contentType string) { t.Helper() resp := httptest.NewRecorder() @@ -661,6 +661,9 @@ func requireHasHeadersSet(t *testing.T, a *TestAgent, path string) { require.Equal(t, "1; mode=block", hdrs.Get("X-XSS-Protection"), "X-XSS-Protection header value incorrect") + + require.Equal(t, contentType, hdrs.Get("Content-Type"), + "") } func TestUIResponseHeaders(t *testing.T) { @@ -680,7 +683,28 @@ func TestUIResponseHeaders(t *testing.T) { `) defer a.Shutdown() - requireHasHeadersSet(t, a, "/ui") + //response header for the UI appears to be being handled by the UI itself. + requireHasHeadersSet(t, a, "/ui", "text/plain; charset=utf-8") +} + +func TestErrorContentTypeHeaderSet(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + a := NewTestAgent(t, ` + http_config { + response_headers = { + "Access-Control-Allow-Origin" = "*" + "X-XSS-Protection" = "1; mode=block" + "X-Frame-Options" = "SAMEORIGIN" + } + } + `) + defer a.Shutdown() + + requireHasHeadersSet(t, a, "/fake-path-doesn't-exist", "text/plain; charset=utf-8") } func TestAcceptEncodingGzip(t *testing.T) { @@ -1628,10 +1652,8 @@ func TestAllowedNets(t *testing.T) { } // assertIndex tests that X-Consul-Index is set and non-zero -func assertIndex(t require.TestingT, resp *httptest.ResponseRecorder) { - if tt, ok := t.(*testing.T); ok { - tt.Helper() - } +func assertIndex(t testutil.TestingTB, resp *httptest.ResponseRecorder) { + t.Helper() require.NoError(t, checkIndex(resp)) } diff --git a/agent/kvs_endpoint.go b/agent/kvs_endpoint.go index e60567cd5b80..65ec44307802 100644 --- a/agent/kvs_endpoint.go +++ b/agent/kvs_endpoint.go @@ -293,7 +293,7 @@ func conflictingFlags(resp http.ResponseWriter, req *http.Request, flags ...stri if _, ok := params[conflict]; ok { if found { resp.WriteHeader(http.StatusBadRequest) - fmt.Fprint(resp, "Conflicting flags: "+params.Encode()) + fmt.Fprintf(resp, "Conflicting flags: %v\n", params.Encode()) return true } found = true diff --git a/agent/leafcert/generate.go b/agent/leafcert/generate.go index 19dbdbbaf4bb..dc9c3b287101 100644 --- a/agent/leafcert/generate.go +++ b/agent/leafcert/generate.go @@ -230,15 +230,6 @@ func (m *Manager) generateNewLeaf( var ipAddresses []net.IP switch { - case req.WorkloadIdentity != "": - id = &connect.SpiffeIDWorkloadIdentity{ - TrustDomain: roots.TrustDomain, - Partition: req.TargetPartition(), - Namespace: req.TargetNamespace(), - WorkloadIdentity: req.WorkloadIdentity, - } - dnsNames = append(dnsNames, req.DNSSAN...) - case req.Service != "": id = &connect.SpiffeIDService{ Host: roots.TrustDomain, @@ -281,7 +272,7 @@ func (m *Manager) generateNewLeaf( dnsNames = append(dnsNames, connect.PeeringServerSAN(req.Datacenter, roots.TrustDomain)) default: - return nil, newState, errors.New("URI must be either workload identity, service, agent, server, or kind") + return nil, newState, errors.New("URI must be either service, agent, server, or kind") } // Create a new private key diff --git a/agent/leafcert/leafcert_test_helpers.go b/agent/leafcert/leafcert_test_helpers.go index 0779033dccfd..5b0b3226cb38 100644 --- a/agent/leafcert/leafcert_test_helpers.go +++ b/agent/leafcert/leafcert_test_helpers.go @@ -180,16 +180,10 @@ func (s *TestSigner) SignCert(ctx context.Context, req *structs.CASignRequest) ( return nil, fmt.Errorf("error parsing CSR URI: %w", err) } - var isService bool var serviceID *connect.SpiffeIDService - var workloadID *connect.SpiffeIDWorkloadIdentity - switch spiffeID.(type) { case *connect.SpiffeIDService: - isService = true serviceID = spiffeID.(*connect.SpiffeIDService) - case *connect.SpiffeIDWorkloadIdentity: - workloadID = spiffeID.(*connect.SpiffeIDWorkloadIdentity) default: return nil, fmt.Errorf("unexpected spiffeID type %T", spiffeID) } @@ -270,35 +264,19 @@ func (s *TestSigner) SignCert(ctx context.Context, req *structs.CASignRequest) ( } index := s.nextIndex() - if isService { - // Service Spiffe ID case - return &structs.IssuedCert{ - SerialNumber: connect.EncodeSerialNumber(leafCert.SerialNumber), - CertPEM: leafPEM, - Service: serviceID.Service, - ServiceURI: leafCert.URIs[0].String(), - ValidAfter: leafCert.NotBefore, - ValidBefore: leafCert.NotAfter, - RaftIndex: structs.RaftIndex{ - CreateIndex: index, - ModifyIndex: index, - }, - }, nil - } else { - // Workload identity Spiffe ID case - return &structs.IssuedCert{ - SerialNumber: connect.EncodeSerialNumber(leafCert.SerialNumber), - CertPEM: leafPEM, - WorkloadIdentity: workloadID.WorkloadIdentity, - WorkloadIdentityURI: leafCert.URIs[0].String(), - ValidAfter: leafCert.NotBefore, - ValidBefore: leafCert.NotAfter, - RaftIndex: structs.RaftIndex{ - CreateIndex: index, - ModifyIndex: index, - }, - }, nil - } + // Service Spiffe ID case + return &structs.IssuedCert{ + SerialNumber: connect.EncodeSerialNumber(leafCert.SerialNumber), + CertPEM: leafPEM, + Service: serviceID.Service, + ServiceURI: leafCert.URIs[0].String(), + ValidAfter: leafCert.NotBefore, + ValidBefore: leafCert.NotAfter, + RaftIndex: structs.RaftIndex{ + CreateIndex: index, + ModifyIndex: index, + }, + }, nil } type testRootsReader struct { diff --git a/agent/leafcert/structs.go b/agent/leafcert/structs.go index 685756c8dc8c..8cd7375731fc 100644 --- a/agent/leafcert/structs.go +++ b/agent/leafcert/structs.go @@ -31,27 +31,16 @@ type ConnectCALeafRequest struct { // The following flags indicate the entity we are requesting a cert for. // Only one of these must be specified. - WorkloadIdentity string // Given a WorkloadIdentity name, the request is for a SpiffeIDWorkload. - Service string // Given a Service name, not ID, the request is for a SpiffeIDService. - Agent string // Given an Agent name, not ID, the request is for a SpiffeIDAgent. - Kind structs.ServiceKind // Given "mesh-gateway", the request is for a SpiffeIDMeshGateway. No other kinds supported. - Server bool // If true, the request is for a SpiffeIDServer. + Service string // Given a Service name, not ID, the request is for a SpiffeIDService. + Agent string // Given an Agent name, not ID, the request is for a SpiffeIDAgent. + Kind structs.ServiceKind // Given "mesh-gateway", the request is for a SpiffeIDMeshGateway. No other kinds supported. + Server bool // If true, the request is for a SpiffeIDServer. } func (r *ConnectCALeafRequest) Key() string { r.EnterpriseMeta.Normalize() switch { - case r.WorkloadIdentity != "": - v, err := hashstructure.Hash([]any{ - r.WorkloadIdentity, - r.EnterpriseMeta, - r.DNSSAN, - r.IPSAN, - }, nil) - if err == nil { - return fmt.Sprintf("workloadidentity:%d", v) - } case r.Agent != "": v, err := hashstructure.Hash([]any{ r.Agent, diff --git a/agent/metrics_test.go b/agent/metrics_test.go index 44d561e01793..c65fcc802d29 100644 --- a/agent/metrics_test.go +++ b/agent/metrics_test.go @@ -150,28 +150,6 @@ func assertMetricExistsWithValue(t *testing.T, respRec *httptest.ResponseRecorde } } -func assertMetricsWithLabelIsNonZero(t *testing.T, respRec *httptest.ResponseRecorder, label, labelValue string) { - if respRec.Body.String() == "" { - t.Fatalf("Response body is empty.") - } - - metrics := respRec.Body.String() - labelWithValueTarget := label + "=" + "\"" + labelValue + "\"" - - for _, line := range strings.Split(metrics, "\n") { - if len(line) < 1 || line[0] == '#' { - continue - } - - if strings.Contains(line, labelWithValueTarget) { - s := strings.SplitN(line, " ", 2) - if s[1] == "0" { - t.Fatalf("Metric with label provided \"%s:%s\" has the value 0", label, labelValue) - } - } - } -} - func assertMetricNotExists(t *testing.T, respRec *httptest.ResponseRecorder, metric string) { if respRec.Body.String() == "" { t.Fatalf("Response body is empty.") @@ -241,8 +219,6 @@ func TestAgent_OneTwelveRPCMetrics(t *testing.T) { assertMetricExistsWithLabels(t, respRec, metricsPrefix+"_rpc_server_call", []string{"errored", "method", "request_type", "rpc_type", "leader"}) // make sure we see 3 Status.Ping metrics corresponding to the calls we made above assertLabelWithValueForMetricExistsNTime(t, respRec, metricsPrefix+"_rpc_server_call", "method", "Status.Ping", 3) - // make sure rpc calls with elapsed time below 1ms are reported as decimal - assertMetricsWithLabelIsNonZero(t, respRec, "method", "Status.Ping") }) } @@ -253,6 +229,7 @@ func TestHTTPHandlers_AgentMetrics_LeaderShipMetrics(t *testing.T) { t.Run("check that metric isLeader is set properly on server", func(t *testing.T) { metricsPrefix1 := getUniqueMetricsPrefix() metricsPrefix2 := getUniqueMetricsPrefix() + metricsPrefix3 := getUniqueMetricsPrefix() hcl1 := fmt.Sprintf(` server = true @@ -272,16 +249,29 @@ func TestHTTPHandlers_AgentMetrics_LeaderShipMetrics(t *testing.T) { } `, metricsPrefix2) + hcl3 := fmt.Sprintf(` + server = true + telemetry = { + prometheus_retention_time = "25s", + disable_hostname = true + metrics_prefix = "%s" + } + `, metricsPrefix3) + overrides := ` bootstrap = false - bootstrap_expect = 2 + bootstrap_expect = 3 ` s1 := StartTestAgent(t, TestAgent{Name: "s1", HCL: hcl1, Overrides: overrides}) - s2 := StartTestAgent(t, TestAgent{Name: "s2", HCL: hcl2, Overrides: overrides}) defer s1.Shutdown() + + s2 := StartTestAgent(t, TestAgent{Name: "s2", HCL: hcl2, Overrides: overrides}) defer s2.Shutdown() + s3 := StartTestAgent(t, TestAgent{Name: "s3", HCL: hcl3, Overrides: overrides}) + defer s3.Shutdown() + // agent hasn't become a leader retry.RunWith(retry.ThirtySeconds(), t, func(r *testretry.R) { respRec := httptest.NewRecorder() @@ -292,8 +282,12 @@ func TestHTTPHandlers_AgentMetrics_LeaderShipMetrics(t *testing.T) { _, err := s2.JoinLAN([]string{s1.Config.SerfBindAddrLAN.String()}, nil) require.NoError(t, err) + _, err = s3.JoinLAN([]string{s1.Config.SerfBindAddrLAN.String()}, nil) + require.NoError(t, err) + testrpc.WaitForLeader(t, s1.RPC, "dc1") testrpc.WaitForLeader(t, s2.RPC, "dc1") + testrpc.WaitForLeader(t, s3.RPC, "dc1") // Verify agent's isLeader metrics is 1 retry.RunWith(retry.ThirtySeconds(), t, func(r *testretry.R) { @@ -305,7 +299,11 @@ func TestHTTPHandlers_AgentMetrics_LeaderShipMetrics(t *testing.T) { recordPromMetrics(r, s2, respRec2) found2 := strings.Contains(respRec2.Body.String(), metricsPrefix2+"_server_isLeader 1") - require.True(r, found1 || found2, "leader server should have isLeader 1") + respRec3 := httptest.NewRecorder() + recordPromMetrics(r, s3, respRec3) + found3 := strings.Contains(respRec3.Body.String(), metricsPrefix3+"_server_isLeader 1") + + require.True(r, found1 || found2 || found3, "leader server should have isLeader 1") }) }) } diff --git a/agent/peering_endpoint_test.go b/agent/peering_endpoint_test.go index ba3b704b8b5a..925033f3342f 100644 --- a/agent/peering_endpoint_test.go +++ b/agent/peering_endpoint_test.go @@ -556,6 +556,8 @@ func TestHTTP_Peering_Read(t *testing.T) { _, err = a.rpcClientPeering.PeeringWrite(ctx, bar) require.NoError(t, err) + var lastIndex uint64 + t.Run("return foo", func(t *testing.T) { req, err := http.NewRequest("GET", "/v1/peering/foo", nil) require.NoError(t, err) @@ -578,6 +580,8 @@ func TestHTTP_Peering_Read(t *testing.T) { require.Equal(t, 0, len(apiResp.StreamStatus.ImportedServices)) require.Equal(t, 0, len(apiResp.StreamStatus.ExportedServices)) + + lastIndex = getIndex(t, resp) }) t.Run("not found", func(t *testing.T) { @@ -588,6 +592,43 @@ func TestHTTP_Peering_Read(t *testing.T) { require.Equal(t, http.StatusNotFound, resp.Code) require.Equal(t, "Peering not found for \"baz\"", resp.Body.String()) }) + + const timeout = 5 * time.Second + t.Run("read blocking query result", func(t *testing.T) { + var ( + // out and resp are not safe to read until reading from errCh + out api.Peering + resp = httptest.NewRecorder() + errCh = make(chan error, 1) + ) + go func() { + url := fmt.Sprintf("/v1/peering/foo?index=%d&wait=%s", lastIndex, timeout) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + errCh <- err + return + } + + a.srv.h.ServeHTTP(resp, req) + require.Equal(t, http.StatusOK, resp.Code) + err = json.NewDecoder(resp.Body).Decode(&out) + errCh <- err + }() + + time.Sleep(200 * time.Millisecond) + + // update peering + foo.Peering.Meta["spooky-key"] = "boo!" + _, err = a.rpcClientPeering.PeeringWrite(ctx, foo) + require.NoError(t, err) + + if err := <-errCh; err != nil { + require.NoError(t, err) + } + + require.Equal(t, "boo!", out.Meta["spooky-key"]) + require.Equal(t, "blocking-query", resp.Header().Get("X-Consul-Query-Backend")) + }) } func TestHTTP_Peering_Delete(t *testing.T) { diff --git a/agent/prepared_query_endpoint.go b/agent/prepared_query_endpoint.go index 15ab1005e48b..8a3f1f038eb0 100644 --- a/agent/prepared_query_endpoint.go +++ b/agent/prepared_query_endpoint.go @@ -11,6 +11,7 @@ import ( cachetype "github.com/hashicorp/consul/agent/cache-types" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/internal/dnsutil" ) // preparedQueryCreateResponse is used to wrap the query ID. @@ -162,7 +163,7 @@ func (s *HTTPHandlers) preparedQueryExecute(id string, resp http.ResponseWriter, // a query can fail over to a different DC than where the execute request // was sent to. That's why we use the reply's DC and not the one from // the args. - s.agent.TranslateAddresses(reply.Datacenter, reply.Nodes, TranslateAddressAcceptAny) + s.agent.TranslateAddresses(reply.Datacenter, reply.Nodes, dnsutil.TranslateAddressAcceptAny) // Use empty list instead of nil. if reply.Nodes == nil { diff --git a/agent/proxycfg-glue/config_entry.go b/agent/proxycfg-glue/config_entry.go index 3a79e228277d..4983edbad14e 100644 --- a/agent/proxycfg-glue/config_entry.go +++ b/agent/proxycfg-glue/config_entry.go @@ -69,6 +69,8 @@ func newConfigEntryRequest(req *structs.ConfigEntryQuery, deps ServerDataSourceD topic = pbsubscribe.Topic_HTTPRoute case structs.TCPRoute: topic = pbsubscribe.Topic_TCPRoute + case structs.FileSystemCertificate: + topic = pbsubscribe.Topic_FileSystemCertificate case structs.InlineCertificate: topic = pbsubscribe.Topic_InlineCertificate case structs.BoundAPIGateway: diff --git a/agent/proxycfg-glue/glue.go b/agent/proxycfg-glue/glue.go index a4fa538b9285..b88c7d2a419e 100644 --- a/agent/proxycfg-glue/glue.go +++ b/agent/proxycfg-glue/glue.go @@ -43,7 +43,7 @@ type Store interface { FederationStateList(ws memdb.WatchSet) (uint64, []*structs.FederationState, error) GatewayServices(ws memdb.WatchSet, gateway string, entMeta *acl.EnterpriseMeta) (uint64, structs.GatewayServices, error) IntentionMatchOne(ws memdb.WatchSet, entry structs.IntentionMatchEntry, matchType structs.IntentionMatchType, destinationType structs.IntentionTargetType) (uint64, structs.SimplifiedIntentions, error) - IntentionTopology(ws memdb.WatchSet, target structs.ServiceName, downstreams bool, defaultDecision acl.EnforcementDecision, intentionTarget structs.IntentionTargetType) (uint64, structs.ServiceList, error) + IntentionTopology(ws memdb.WatchSet, target structs.ServiceName, downstreams bool, defaultDecision bool, intentionTarget structs.IntentionTargetType) (uint64, structs.ServiceList, error) ReadResolvedServiceConfigEntries(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, upstreamIDs []structs.ServiceID, proxyMode structs.ProxyMode) (uint64, *configentry.ResolvedServiceConfigSet, error) ServiceDiscoveryChain(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, req discoverychain.CompileRequest) (uint64, *structs.CompiledDiscoveryChain, *configentry.DiscoveryChainSet, error) ServiceDump(ws memdb.WatchSet, kind structs.ServiceKind, useKind bool, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) diff --git a/agent/proxycfg-glue/health_blocking.go b/agent/proxycfg-glue/health_blocking.go index 8ed384f837ef..0b2bcba8b972 100644 --- a/agent/proxycfg-glue/health_blocking.go +++ b/agent/proxycfg-glue/health_blocking.go @@ -128,7 +128,8 @@ func (h *serverHealthBlocking) Notify(ctx context.Context, args *structs.Service if err != nil { return 0, nil, err } - thisReply.Nodes = raw.(structs.CheckServiceNodes) + filteredNodes := raw.(structs.CheckServiceNodes) + thisReply.Nodes = filteredNodes.Filter(structs.CheckServiceNodeFilterOptions{FilterType: args.HealthFilterType}) // Note: we filter the results with ACLs *after* applying the user-supplied // bexpr filter, to ensure QueryMeta.ResultsFilteredByACLs does not include diff --git a/agent/proxycfg-glue/intention_upstreams.go b/agent/proxycfg-glue/intention_upstreams.go index dc6731372271..846eb2a72b26 100644 --- a/agent/proxycfg-glue/intention_upstreams.go +++ b/agent/proxycfg-glue/intention_upstreams.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/consul/agent/cache" cachetype "github.com/hashicorp/consul/agent/cache-types" + "github.com/hashicorp/consul/agent/consul" "github.com/hashicorp/consul/agent/consul/watch" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" @@ -33,20 +34,21 @@ func CacheIntentionUpstreamsDestination(c *cache.Cache) proxycfg.IntentionUpstre // ServerIntentionUpstreams satisfies the proxycfg.IntentionUpstreams interface // by sourcing upstreams for the given service, inferred from intentions, from // the server's state store. -func ServerIntentionUpstreams(deps ServerDataSourceDeps) proxycfg.IntentionUpstreams { - return serverIntentionUpstreams{deps, structs.IntentionTargetService} +func ServerIntentionUpstreams(deps ServerDataSourceDeps, defaultIntentionPolicy string) proxycfg.IntentionUpstreams { + return serverIntentionUpstreams{deps, structs.IntentionTargetService, defaultIntentionPolicy} } // ServerIntentionUpstreamsDestination satisfies the proxycfg.IntentionUpstreams // interface by sourcing upstreams for the given destination, inferred from // intentions, from the server's state store. -func ServerIntentionUpstreamsDestination(deps ServerDataSourceDeps) proxycfg.IntentionUpstreams { - return serverIntentionUpstreams{deps, structs.IntentionTargetDestination} +func ServerIntentionUpstreamsDestination(deps ServerDataSourceDeps, defaultIntentionPolicy string) proxycfg.IntentionUpstreams { + return serverIntentionUpstreams{deps, structs.IntentionTargetDestination, defaultIntentionPolicy} } type serverIntentionUpstreams struct { - deps ServerDataSourceDeps - target structs.IntentionTargetType + deps ServerDataSourceDeps + target structs.IntentionTargetType + defaultIntentionPolicy string } func (s serverIntentionUpstreams) Notify(ctx context.Context, req *structs.ServiceSpecificRequest, correlationID string, ch chan<- proxycfg.UpdateEvent) error { @@ -58,9 +60,10 @@ func (s serverIntentionUpstreams) Notify(ctx context.Context, req *structs.Servi if err != nil { return 0, nil, err } - defaultDecision := authz.IntentionDefaultAllow(nil) - index, services, err := store.IntentionTopology(ws, target, false, defaultDecision, s.target) + defaultAllow := consul.DefaultIntentionAllow(authz, s.defaultIntentionPolicy) + + index, services, err := store.IntentionTopology(ws, target, false, defaultAllow, s.target) if err != nil { return 0, nil, err } diff --git a/agent/proxycfg-glue/intention_upstreams_test.go b/agent/proxycfg-glue/intention_upstreams_test.go index bfaeb55b3864..b1c77aaf3ae9 100644 --- a/agent/proxycfg-glue/intention_upstreams_test.go +++ b/agent/proxycfg-glue/intention_upstreams_test.go @@ -66,7 +66,7 @@ func TestServerIntentionUpstreams(t *testing.T) { dataSource := ServerIntentionUpstreams(ServerDataSourceDeps{ ACLResolver: newStaticResolver(authz), GetStore: func() Store { return store }, - }) + }, "") ch := make(chan proxycfg.UpdateEvent) err := dataSource.Notify(ctx, &structs.ServiceSpecificRequest{ServiceName: serviceName}, "", ch) @@ -84,6 +84,47 @@ func TestServerIntentionUpstreams(t *testing.T) { require.Equal(t, "db", result.Services[0].Name) } +// Variant of TestServerIntentionUpstreams where a default allow intention policy +// returns "db" service as an IntentionUpstream even if there are no explicit +// intentions for "db". +func TestServerIntentionUpstreams_DefaultIntentionPolicy(t *testing.T) { + const serviceName = "web" + + var index uint64 + getIndex := func() uint64 { + index++ + return index + } + + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + + store := state.NewStateStore(nil) + disableLegacyIntentions(t, store) + + require.NoError(t, store.EnsureRegistration(getIndex(), &structs.RegisterRequest{ + Node: "node-1", + Service: &structs.NodeService{ + Service: "db", + }, + })) + + // Ensures that "db" service will not be filtered due to ACLs + authz := policyAuthorizer(t, `service "db" { policy = "read" }`) + + dataSource := ServerIntentionUpstreams(ServerDataSourceDeps{ + ACLResolver: newStaticResolver(authz), + GetStore: func() Store { return store }, + }, "allow") + + ch := make(chan proxycfg.UpdateEvent) + require.NoError(t, dataSource.Notify(ctx, &structs.ServiceSpecificRequest{ServiceName: serviceName}, "", ch)) + + result := getEventResult[*structs.IndexedServiceList](t, ch) + require.Len(t, result.Services, 1) + require.Equal(t, "db", result.Services[0].Name) +} + func disableLegacyIntentions(t *testing.T, store *state.Store) { t.Helper() diff --git a/agent/proxycfg-sources/catalog/config_source.go b/agent/proxycfg-sources/catalog/config_source.go index 9ded9aa7fd4e..ec4aabeeb143 100644 --- a/agent/proxycfg-sources/catalog/config_source.go +++ b/agent/proxycfg-sources/catalog/config_source.go @@ -17,8 +17,6 @@ import ( "github.com/hashicorp/consul/agent/local" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - "github.com/hashicorp/consul/proto-public/pbresource" ) const source proxycfg.ProxySource = "catalog" @@ -34,9 +32,12 @@ type ConfigSource struct { shutdownCh chan struct{} } +var _ Watcher = (*ConfigSource)(nil) + type watch struct { - numWatchers int // guarded by ConfigSource.mu. - closeCh chan chan struct{} + numWatchers int // guarded by ConfigSource.mu. + stopSyncLoopCh chan struct{} + syncLoopDoneCh chan struct{} } // NewConfigSource creates a ConfigSource with the given configuration. @@ -50,13 +51,11 @@ func NewConfigSource(cfg Config) *ConfigSource { // Watch wraps the underlying proxycfg.Manager and dynamically registers // services from the catalog with it when requested by the xDS server. -func (m *ConfigSource) Watch(id *pbresource.ID, nodeName string, token string) (<-chan proxysnapshot.ProxySnapshot, limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) { - // Create service ID - serviceID := structs.NewServiceID(id.Name, GetEnterpriseMetaFromResourceID(id)) +func (m *ConfigSource) Watch(serviceID structs.ServiceID, nodeName string, token string) (<-chan *proxycfg.ConfigSnapshot, limiter.SessionTerminatedChan, proxycfg.SrcTerminatedChan, context.CancelFunc, error) { // If the service is registered to the local agent, use the LocalConfigSource // rather than trying to configure it from the catalog. if nodeName == m.NodeName && m.LocalState.ServiceExists(serviceID) { - return m.LocalConfigSource.Watch(id, nodeName, token) + return m.LocalConfigSource.Watch(serviceID, nodeName, token) } // Begin a session with the xDS session concurrency limiter. @@ -67,7 +66,7 @@ func (m *ConfigSource) Watch(id *pbresource.ID, nodeName string, token string) ( // See: https://github.com/hashicorp/consul/issues/15753 session, err := m.SessionLimiter.BeginSession() if err != nil { - return nil, nil, nil, err + return nil, nil, nil, nil, err } proxyID := proxycfg.ProxyID{ @@ -79,16 +78,6 @@ func (m *ConfigSource) Watch(id *pbresource.ID, nodeName string, token string) ( // Start the watch on the real proxycfg Manager. snapCh, cancelWatch := m.Manager.Watch(proxyID) - // Wrap the cancelWatch function with our bookkeeping. m.mu must be held when calling. - var cancelOnce sync.Once - cancel := func() { - cancelOnce.Do(func() { - cancelWatch() - m.cleanup(proxyID) - session.End() - }) - } - m.mu.Lock() defer m.mu.Unlock() @@ -96,18 +85,31 @@ func (m *ConfigSource) Watch(id *pbresource.ID, nodeName string, token string) ( if ok { w.numWatchers++ } else { - w = &watch{closeCh: make(chan chan struct{}), numWatchers: 1} + w = &watch{ + numWatchers: 1, + stopSyncLoopCh: make(chan struct{}), + syncLoopDoneCh: make(chan struct{}), + } m.watches[proxyID] = w - if err := m.startSync(w.closeCh, proxyID); err != nil { + if err := m.startSync(w.stopSyncLoopCh, w.syncLoopDoneCh, proxyID); err != nil { delete(m.watches, proxyID) cancelWatch() session.End() - return nil, nil, nil, err + return nil, nil, nil, nil, err } } - return snapCh, session.Terminated(), cancel, nil + // Wrap the cancelWatch function with our bookkeeping. m.mu must be held when calling. + var cancelOnce sync.Once + cancel := func() { + cancelOnce.Do(func() { + cancelWatch() + m.cleanup(proxyID) + session.End() + }) + } + return snapCh, session.Terminated(), w.syncLoopDoneCh, cancel, nil } func (m *ConfigSource) Shutdown() { @@ -122,7 +124,11 @@ func (m *ConfigSource) Shutdown() { // // If the first attempt to fetch and register the service fails, startSync // will return an error (and no goroutine will be started). -func (m *ConfigSource) startSync(closeCh <-chan chan struct{}, proxyID proxycfg.ProxyID) error { +func (m *ConfigSource) startSync( + stopSyncLoopCh <-chan struct{}, + syncLoopDoneCh chan<- struct{}, + proxyID proxycfg.ProxyID, +) error { logger := m.Logger.With( "proxy_service_id", proxyID.ServiceID.String(), "node", proxyID.NodeName, @@ -170,7 +176,13 @@ func (m *ConfigSource) startSync(closeCh <-chan chan struct{}, proxyID proxycfg. syncLoop := func(ws memdb.WatchSet) { // Cancel the context on return to clean up the goroutine started by WatchCh. ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + defer func() { + cancel() + logger.Debug("de-registering service with proxycfg manager because all watchers have gone away") + m.Manager.Deregister(proxyID, source) + close(syncLoopDoneCh) + logger.Debug("sync-loop terminated") + }() for { select { @@ -179,16 +191,13 @@ func (m *ConfigSource) startSync(closeCh <-chan chan struct{}, proxyID proxycfg. // // It is expected that all other branches of this select will return and // cancel the context given to WatchCh (to clean up its goroutine). - case doneCh := <-closeCh: + case <-stopSyncLoopCh: // All watchers of this service (xDS streams) have gone away, so it's time // to free its resources. // // TODO(agentless): we should probably wait for a short grace period before // de-registering the service to allow clients to reconnect after a network // blip. - logger.Trace("de-registering service with proxycfg manager because all watchers have gone away") - m.Manager.Deregister(proxyID, source) - close(doneCh) return case <-m.shutdownCh: // Manager is shutting down, stop the goroutine. @@ -198,6 +207,7 @@ func (m *ConfigSource) startSync(closeCh <-chan chan struct{}, proxyID proxycfg. var err error ws, err = fetchAndRegister() if err != nil { + logger.Debug("error in syncLoop.fetchAndRegister", "err", err) return } } @@ -233,18 +243,14 @@ func (m *ConfigSource) cleanup(id proxycfg.ProxyID) { h.numWatchers-- if h.numWatchers == 0 { - // We wait for doneCh to be closed by the sync goroutine, so that the lock is + // Notify the sync loop that it should terminate. + close(h.stopSyncLoopCh) + // We wait for sync loop to be closed, so that the lock is // held until after the service is de-registered - this prevents a potential // race where another sync goroutine is started for the service and we undo // its call to register the service. - // - // This cannot deadlock because closeCh is unbuffered. Sending will only - // succeed if the sync goroutine is ready to receive (which always closes - // doneCh). - doneCh := make(chan struct{}) select { - case h.closeCh <- doneCh: - <-doneCh + case <-h.syncLoopDoneCh: case <-m.shutdownCh: // ConfigSource is shutting down, so the goroutine will be stopped anyway. } @@ -280,7 +286,7 @@ type Config struct { //go:generate mockery --name ConfigManager --inpackage type ConfigManager interface { - Watch(req proxycfg.ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc) + Watch(req proxycfg.ProxyID) (<-chan *proxycfg.ConfigSnapshot, context.CancelFunc) Register(proxyID proxycfg.ProxyID, service *structs.NodeService, source proxycfg.ProxySource, token string, overwrite bool) error Deregister(proxyID proxycfg.ProxyID, source proxycfg.ProxySource) } @@ -293,7 +299,7 @@ type Store interface { //go:generate mockery --name Watcher --inpackage type Watcher interface { - Watch(proxyID *pbresource.ID, nodeName string, token string) (<-chan proxysnapshot.ProxySnapshot, limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) + Watch(proxyID structs.ServiceID, nodeName string, token string) (<-chan *proxycfg.ConfigSnapshot, limiter.SessionTerminatedChan, proxycfg.SrcTerminatedChan, context.CancelFunc, error) } //go:generate mockery --name SessionLimiter --inpackage diff --git a/agent/proxycfg-sources/catalog/config_source_oss.go b/agent/proxycfg-sources/catalog/config_source_oss.go deleted file mode 100644 index 233ad64cee8f..000000000000 --- a/agent/proxycfg-sources/catalog/config_source_oss.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent - -package catalog - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func GetEnterpriseMetaFromResourceID(id *pbresource.ID) *acl.EnterpriseMeta { - return acl.DefaultEnterpriseMeta() -} diff --git a/agent/proxycfg-sources/catalog/config_source_test.go b/agent/proxycfg-sources/catalog/config_source_test.go index 94d939e8cad5..79a7a8578902 100644 --- a/agent/proxycfg-sources/catalog/config_source_test.go +++ b/agent/proxycfg-sources/catalog/config_source_test.go @@ -6,13 +6,15 @@ package catalog import ( "context" "errors" + "fmt" "testing" "time" - "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/stream" "github.com/hashicorp/consul/agent/grpc-external/limiter" @@ -20,9 +22,6 @@ import ( "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/token" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" ) func TestConfigSource_Success(t *testing.T) { @@ -79,15 +78,15 @@ func TestConfigSource_Success(t *testing.T) { }) t.Cleanup(mgr.Shutdown) - snapCh, termCh, cancelWatch1, err := mgr.Watch(rtest.Resource(pbmesh.ProxyConfigurationType, serviceID.ID).ID(), nodeName, token) + snapCh, termCh, _, cancelWatch1, err := mgr.Watch(serviceID, nodeName, token) require.NoError(t, err) require.Equal(t, session1TermCh, termCh) // Expect Register to have been called with the proxy's inital port. select { case snap := <-snapCh: - require.Equal(t, 9999, snap.(*proxycfg.ConfigSnapshot).Port) - require.Equal(t, token, snap.(*proxycfg.ConfigSnapshot).ProxyID.Token) + require.Equal(t, 9999, snap.Port) + require.Equal(t, token, snap.ProxyID.Token) case <-time.After(100 * time.Millisecond): t.Fatal("timeout waiting for snapshot") } @@ -111,7 +110,7 @@ func TestConfigSource_Success(t *testing.T) { // Expect Register to have been called again with the proxy's new port. select { case snap := <-snapCh: - require.Equal(t, 8888, snap.(*proxycfg.ConfigSnapshot).Port) + require.Equal(t, 8888, snap.Port) case <-time.After(100 * time.Millisecond): t.Fatal("timeout waiting for snapshot") } @@ -130,13 +129,13 @@ func TestConfigSource_Success(t *testing.T) { require.Equal(t, map[string]any{ "local_connect_timeout_ms": 123, "max_inbound_connections": 321, - }, snap.(*proxycfg.ConfigSnapshot).Proxy.Config) + }, snap.Proxy.Config) case <-time.After(100 * time.Millisecond): t.Fatal("timeout waiting for snapshot") } // Start another watch. - _, termCh2, cancelWatch2, err := mgr.Watch(rtest.Resource(pbmesh.ProxyConfigurationType, serviceID.ID).ID(), nodeName, token) + _, termCh2, _, cancelWatch2, err := mgr.Watch(serviceID, nodeName, token) require.NoError(t, err) require.Equal(t, session2TermCh, termCh2) @@ -170,7 +169,7 @@ func TestConfigSource_Success(t *testing.T) { func TestConfigSource_LocallyManagedService(t *testing.T) { serviceID := structs.NewServiceID("web-sidecar-proxy-1", nil) - proxyID := rtest.Resource(pbmesh.ProxyConfigurationType, serviceID.ID).ID() + proxyID := serviceID nodeName := "node-1" token := "token" @@ -179,7 +178,7 @@ func TestConfigSource_LocallyManagedService(t *testing.T) { localWatcher := NewMockWatcher(t) localWatcher.On("Watch", proxyID, nodeName, token). - Return(make(<-chan proxysnapshot.ProxySnapshot), nil, proxysnapshot.CancelFunc(func() {}), nil) + Return(make(<-chan *proxycfg.ConfigSnapshot), nil, nil, context.CancelFunc(func() {}), nil) mgr := NewConfigSource(Config{ NodeName: nodeName, @@ -191,7 +190,7 @@ func TestConfigSource_LocallyManagedService(t *testing.T) { }) t.Cleanup(mgr.Shutdown) - _, _, _, err := mgr.Watch(proxyID, nodeName, token) + _, _, _, _, err := mgr.Watch(proxyID, nodeName, token) require.NoError(t, err) } @@ -213,12 +212,12 @@ func TestConfigSource_ErrorRegisteringService(t *testing.T) { })) var canceledWatch bool - cancel := proxysnapshot.CancelFunc(func() { canceledWatch = true }) + cancel := context.CancelFunc(func() { canceledWatch = true }) cfgMgr := NewMockConfigManager(t) cfgMgr.On("Watch", mock.Anything). - Return(make(<-chan proxysnapshot.ProxySnapshot), cancel) + Return(make(<-chan *proxycfg.ConfigSnapshot), cancel) cfgMgr.On("Register", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). Return(errors.New("KABOOM")) @@ -238,13 +237,173 @@ func TestConfigSource_ErrorRegisteringService(t *testing.T) { }) t.Cleanup(mgr.Shutdown) - _, _, _, err := mgr.Watch(rtest.Resource(pbmesh.ProxyConfigurationType, serviceID.ID).ID(), nodeName, token) + _, _, _, _, err := mgr.Watch(serviceID, nodeName, token) require.Error(t, err) require.True(t, canceledWatch, "watch should've been canceled") session.AssertCalled(t, "End") } +func TestConfigSource_ErrorInSyncLoop(t *testing.T) { + serviceID := structs.NewServiceID("web-sidecar-proxy-1", nil) + nodeName := "node-name" + token := "token" + + store := testStateStore(t) + + // Register the proxy in the catalog/state store at port 9999. + require.NoError(t, store.EnsureRegistration(0, &structs.RegisterRequest{ + Node: nodeName, + Service: &structs.NodeService{ + ID: serviceID.ID, + Service: "web-sidecar-proxy", + Port: 9999, + Kind: structs.ServiceKindConnectProxy, + Proxy: structs.ConnectProxyConfig{ + Config: map[string]any{ + "local_connect_timeout_ms": 123, + }, + }, + }, + })) + + cfgMgr := NewMockConfigManager(t) + { + proxyID := proxycfg.ProxyID{ + ServiceID: serviceID, + NodeName: nodeName, + Token: token, + } + snapCh := make(chan *proxycfg.ConfigSnapshot, 1) + cfgMgr.On("Watch", proxyID). + Return((<-chan *proxycfg.ConfigSnapshot)(snapCh), context.CancelFunc(func() {}), nil) + + // Answer the register call successfully for session 1 starting (Repeatability = 1). + // Session 2 should not have caused a re-register to happen. + cfgMgr.On("Register", mock.Anything, mock.Anything, source, token, false). + Run(func(args mock.Arguments) { + id := args.Get(0).(proxycfg.ProxyID) + ns := args.Get(1).(*structs.NodeService) + + snapCh <- &proxycfg.ConfigSnapshot{ + ProxyID: id, + Port: ns.Port, + Proxy: ns.Proxy, + } + }). + Return(nil). + Repeatability = 1 + + // Error on subsequent registrations afterwards (during the sync loop). + cfgMgr.On("Register", mock.Anything, mock.Anything, source, token, false). + Return(fmt.Errorf("intentional registration error")) + + cfgMgr.On("Deregister", proxyID, source). + Run(func(mock.Arguments) { close(snapCh) }). + Return() + } + + lim := NewMockSessionLimiter(t) + session1TermCh := make(limiter.SessionTerminatedChan) + session2TermCh := make(limiter.SessionTerminatedChan) + { + session1 := newMockSession(t) + session1.On("Terminated").Return(session1TermCh) + session1.On("End").Return() + + session2 := newMockSession(t) + session2.On("Terminated").Return(session2TermCh) + session2.On("End").Return() + + lim.On("BeginSession").Return(session1, nil).Once() + lim.On("BeginSession").Return(session2, nil).Once() + } + + mgr := NewConfigSource(Config{ + Manager: cfgMgr, + LocalState: testLocalState(t), + Logger: hclog.NewNullLogger(), + GetStore: func() Store { return store }, + SessionLimiter: lim, + }) + t.Cleanup(mgr.Shutdown) + + snapCh, termCh, cfgSrcTerminated1, cancelWatch1, err := mgr.Watch(serviceID, nodeName, token) + require.NoError(t, err) + require.Equal(t, session1TermCh, termCh) + + // Expect Register to have been called with the proxy's inital port. + select { + case snap := <-snapCh: + require.Equal(t, 9999, snap.Port) + require.Equal(t, token, snap.ProxyID.Token) + case <-time.After(100 * time.Millisecond): + t.Fatal("timeout waiting for snapshot") + } + + // Start another watch. + _, termCh2, cfgSrcTerminated2, cancelWatch2, err := mgr.Watch(serviceID, nodeName, token) + require.NoError(t, err) + require.Equal(t, session2TermCh, termCh2) + + // Expect the service to have not been re-registered by the second watch. + select { + case <-snapCh: + t.Fatal("service shouldn't have been re-registered") + case <-time.After(100 * time.Millisecond): + } + + // Ensure that no config-source syncLoops were terminated. + select { + case <-cfgSrcTerminated1: + t.Fatal("unexpected config-source termination 1") + case <-cfgSrcTerminated2: + t.Fatal("unexpected config-source termination 2") + default: + } + + // Update the proxy's port to 8888. + // This should trigger the config-source syncLoop termination channel due to an error. + require.NoError(t, store.EnsureRegistration(0, &structs.RegisterRequest{ + Node: nodeName, + Service: &structs.NodeService{ + ID: serviceID.ID, + Service: "web-sidecar-proxy", + Port: 8888, + Kind: structs.ServiceKindConnectProxy, + Proxy: structs.ConnectProxyConfig{ + Config: map[string]any{ + "local_connect_timeout_ms": 123, + }, + }, + }, + })) + + // Expect both config sources to have terminated when the syncLoop errors. + select { + case _, ok := <-cfgSrcTerminated1: + cancelWatch1() + require.False(t, ok) + case <-time.After(100 * time.Millisecond): + t.Fatal("timeout waiting for config-source termination 1") + } + select { + case _, ok := <-cfgSrcTerminated2: + cancelWatch2() + require.False(t, ok) + case <-time.After(100 * time.Millisecond): + t.Fatal("timeout waiting for config-source termination 2") + } + + // Expect the snap channels to have been closed. + select { + case _, ok := <-snapCh: + require.False(t, ok) + case <-time.After(100 * time.Millisecond): + t.Fatal("snap channel was not closed") + } +} + func TestConfigSource_NotProxyService(t *testing.T) { serviceID := structs.NewServiceID("web", nil) nodeName := "node-name" @@ -263,12 +422,12 @@ func TestConfigSource_NotProxyService(t *testing.T) { })) var canceledWatch bool - cancel := proxysnapshot.CancelFunc(func() { canceledWatch = true }) + cancel := context.CancelFunc(func() { canceledWatch = true }) cfgMgr := NewMockConfigManager(t) cfgMgr.On("Watch", mock.Anything). - Return(make(<-chan proxysnapshot.ProxySnapshot), cancel) + Return(make(<-chan *proxycfg.ConfigSnapshot), cancel) mgr := NewConfigSource(Config{ Manager: cfgMgr, @@ -279,7 +438,7 @@ func TestConfigSource_NotProxyService(t *testing.T) { }) t.Cleanup(mgr.Shutdown) - _, _, _, err := mgr.Watch(rtest.Resource(pbmesh.ProxyConfigurationType, serviceID.ID).ID(), nodeName, token) + _, _, _, _, err := mgr.Watch(serviceID, nodeName, token) require.Error(t, err) require.Contains(t, err.Error(), "must be a sidecar proxy or gateway") require.True(t, canceledWatch, "watch should've been canceled") @@ -295,15 +454,15 @@ func TestConfigSource_SessionLimiterError(t *testing.T) { }) t.Cleanup(src.Shutdown) - _, _, _, err := src.Watch( - rtest.Resource(pbmesh.ProxyConfigurationType, "web-sidecar-proxy-1").ID(), + _, _, _, _, err := src.Watch( + structs.NewServiceID("web-sidecar-proxy-1", nil), "node-name", "token", ) require.Equal(t, limiter.ErrCapacityReached, err) } -func testConfigManager(t *testing.T, serviceID structs.ServiceID, nodeName string, token string) ConfigManager { +func testConfigManager(t *testing.T, serviceID structs.ServiceID, nodeName string, token string) *MockConfigManager { t.Helper() cfgMgr := NewMockConfigManager(t) @@ -314,9 +473,9 @@ func testConfigManager(t *testing.T, serviceID structs.ServiceID, nodeName strin Token: token, } - snapCh := make(chan proxysnapshot.ProxySnapshot, 1) + snapCh := make(chan *proxycfg.ConfigSnapshot, 1) cfgMgr.On("Watch", proxyID). - Return((<-chan proxysnapshot.ProxySnapshot)(snapCh), proxysnapshot.CancelFunc(func() {}), nil) + Return((<-chan *proxycfg.ConfigSnapshot)(snapCh), context.CancelFunc(func() {}), nil) cfgMgr.On("Register", mock.Anything, mock.Anything, source, token, false). Run(func(args mock.Arguments) { diff --git a/agent/proxycfg-sources/catalog/mock_ConfigManager.go b/agent/proxycfg-sources/catalog/mock_ConfigManager.go index 37deffb022d8..dbd82e702b7d 100644 --- a/agent/proxycfg-sources/catalog/mock_ConfigManager.go +++ b/agent/proxycfg-sources/catalog/mock_ConfigManager.go @@ -1,12 +1,12 @@ -// Code generated by mockery v2.33.1. DO NOT EDIT. +// Code generated by mockery v2.37.1. DO NOT EDIT. package catalog import ( proxycfg "github.com/hashicorp/consul/agent/proxycfg" mock "github.com/stretchr/testify/mock" + "context" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" structs "github.com/hashicorp/consul/agent/structs" ) @@ -36,27 +36,27 @@ func (_m *MockConfigManager) Register(proxyID proxycfg.ProxyID, service *structs } // Watch provides a mock function with given fields: req -func (_m *MockConfigManager) Watch(req proxycfg.ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc) { +func (_m *MockConfigManager) Watch(req proxycfg.ProxyID) (<-chan *proxycfg.ConfigSnapshot, context.CancelFunc) { ret := _m.Called(req) - var r0 <-chan proxysnapshot.ProxySnapshot - var r1 proxysnapshot.CancelFunc - if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc)); ok { + var r0 <-chan *proxycfg.ConfigSnapshot + var r1 context.CancelFunc + if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) (<-chan *proxycfg.ConfigSnapshot, context.CancelFunc)); ok { return rf(req) } - if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) <-chan proxysnapshot.ProxySnapshot); ok { + if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) <-chan *proxycfg.ConfigSnapshot); ok { r0 = rf(req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan proxysnapshot.ProxySnapshot) + r0 = ret.Get(0).(<-chan *proxycfg.ConfigSnapshot) } } - if rf, ok := ret.Get(1).(func(proxycfg.ProxyID) proxysnapshot.CancelFunc); ok { + if rf, ok := ret.Get(1).(func(proxycfg.ProxyID) context.CancelFunc); ok { r1 = rf(req) } else { if ret.Get(1) != nil { - r1 = ret.Get(1).(proxysnapshot.CancelFunc) + r1 = ret.Get(1).(context.CancelFunc) } } diff --git a/agent/proxycfg-sources/catalog/mock_SessionLimiter.go b/agent/proxycfg-sources/catalog/mock_SessionLimiter.go index 39cd430f06d3..baa2d3591e3e 100644 --- a/agent/proxycfg-sources/catalog/mock_SessionLimiter.go +++ b/agent/proxycfg-sources/catalog/mock_SessionLimiter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.33.1. DO NOT EDIT. +// Code generated by mockery v2.37.1. DO NOT EDIT. package catalog diff --git a/agent/proxycfg-sources/catalog/mock_Watcher.go b/agent/proxycfg-sources/catalog/mock_Watcher.go index b77be5d98ea8..1fc6ba7c6ea3 100644 --- a/agent/proxycfg-sources/catalog/mock_Watcher.go +++ b/agent/proxycfg-sources/catalog/mock_Watcher.go @@ -1,14 +1,13 @@ -// Code generated by mockery v2.33.1. DO NOT EDIT. +// Code generated by mockery v2.37.1. DO NOT EDIT. package catalog import ( limiter "github.com/hashicorp/consul/agent/grpc-external/limiter" mock "github.com/stretchr/testify/mock" - - pbresource "github.com/hashicorp/consul/proto-public/pbresource" - - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" + "github.com/hashicorp/consul/agent/structs" + proxycfg "github.com/hashicorp/consul/agent/proxycfg" + "context" ) // MockWatcher is an autogenerated mock type for the Watcher type @@ -17,25 +16,26 @@ type MockWatcher struct { } // Watch provides a mock function with given fields: proxyID, nodeName, token -func (_m *MockWatcher) Watch(proxyID *pbresource.ID, nodeName string, token string) (<-chan proxysnapshot.ProxySnapshot, limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) { +func (_m *MockWatcher) Watch(proxyID structs.ServiceID, nodeName string, token string) (<-chan *proxycfg.ConfigSnapshot, limiter.SessionTerminatedChan, proxycfg.SrcTerminatedChan, context.CancelFunc, error) { ret := _m.Called(proxyID, nodeName, token) - var r0 <-chan proxysnapshot.ProxySnapshot + var r0 <-chan *proxycfg.ConfigSnapshot var r1 limiter.SessionTerminatedChan - var r2 proxysnapshot.CancelFunc - var r3 error - if rf, ok := ret.Get(0).(func(*pbresource.ID, string, string) (<-chan proxysnapshot.ProxySnapshot, limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error)); ok { + var r2 proxycfg.SrcTerminatedChan + var r3 context.CancelFunc + var r4 error + if rf, ok := ret.Get(0).(func(structs.ServiceID, string, string) (<-chan *proxycfg.ConfigSnapshot, limiter.SessionTerminatedChan, proxycfg.SrcTerminatedChan, context.CancelFunc, error)); ok { return rf(proxyID, nodeName, token) } - if rf, ok := ret.Get(0).(func(*pbresource.ID, string, string) <-chan proxysnapshot.ProxySnapshot); ok { + if rf, ok := ret.Get(0).(func(structs.ServiceID, string, string) <-chan *proxycfg.ConfigSnapshot); ok { r0 = rf(proxyID, nodeName, token) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan proxysnapshot.ProxySnapshot) + r0 = ret.Get(0).(<-chan *proxycfg.ConfigSnapshot) } } - if rf, ok := ret.Get(1).(func(*pbresource.ID, string, string) limiter.SessionTerminatedChan); ok { + if rf, ok := ret.Get(1).(func(structs.ServiceID, string, string) limiter.SessionTerminatedChan); ok { r1 = rf(proxyID, nodeName, token) } else { if ret.Get(1) != nil { @@ -43,21 +43,29 @@ func (_m *MockWatcher) Watch(proxyID *pbresource.ID, nodeName string, token stri } } - if rf, ok := ret.Get(2).(func(*pbresource.ID, string, string) proxysnapshot.CancelFunc); ok { + if rf, ok := ret.Get(2).(func(structs.ServiceID, string, string) proxycfg.SrcTerminatedChan); ok { r2 = rf(proxyID, nodeName, token) } else { if ret.Get(2) != nil { - r2 = ret.Get(2).(proxysnapshot.CancelFunc) + r2 = ret.Get(2).(proxycfg.SrcTerminatedChan) } } - if rf, ok := ret.Get(3).(func(*pbresource.ID, string, string) error); ok { + if rf, ok := ret.Get(3).(func(structs.ServiceID, string, string) context.CancelFunc); ok { r3 = rf(proxyID, nodeName, token) } else { - r3 = ret.Error(3) + if ret.Get(3) != nil { + r3 = ret.Get(3).(context.CancelFunc) + } + } + + if rf, ok := ret.Get(4).(func(structs.ServiceID, string, string) error); ok { + r4 = rf(proxyID, nodeName, token) + } else { + r4 = ret.Error(4) } - return r0, r1, r2, r3 + return r0, r1, r2, r3, r4 } // NewMockWatcher creates a new instance of MockWatcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. diff --git a/agent/proxycfg-sources/local/config_source.go b/agent/proxycfg-sources/local/config_source.go index 7b3a835fb819..e3176c597d99 100644 --- a/agent/proxycfg-sources/local/config_source.go +++ b/agent/proxycfg-sources/local/config_source.go @@ -4,12 +4,11 @@ package local import ( + "context" + "github.com/hashicorp/consul/agent/grpc-external/limiter" "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/proxycfg-sources/catalog" structs "github.com/hashicorp/consul/agent/structs" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - "github.com/hashicorp/consul/proto-public/pbresource" ) // ConfigSource wraps a proxycfg.Manager to create watches on services @@ -23,9 +22,13 @@ func NewConfigSource(cfgMgr ConfigManager) *ConfigSource { return &ConfigSource{cfgMgr} } -func (m *ConfigSource) Watch(proxyID *pbresource.ID, nodeName string, _ string) (<-chan proxysnapshot.ProxySnapshot, - limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) { - serviceID := structs.NewServiceID(proxyID.Name, catalog.GetEnterpriseMetaFromResourceID(proxyID)) +func (m *ConfigSource) Watch(serviceID structs.ServiceID, nodeName string, _ string) ( + <-chan *proxycfg.ConfigSnapshot, + limiter.SessionTerminatedChan, + proxycfg.SrcTerminatedChan, + context.CancelFunc, + error, +) { watchCh, cancelWatch := m.manager.Watch(proxycfg.ProxyID{ ServiceID: serviceID, NodeName: nodeName, @@ -36,5 +39,5 @@ func (m *ConfigSource) Watch(proxyID *pbresource.ID, nodeName string, _ string) // is checked before the watch is created). Token: "", }) - return watchCh, nil, cancelWatch, nil + return watchCh, nil, nil, cancelWatch, nil } diff --git a/agent/proxycfg-sources/local/mock_ConfigManager.go b/agent/proxycfg-sources/local/mock_ConfigManager.go index e3b2d3a44587..66b204d1312f 100644 --- a/agent/proxycfg-sources/local/mock_ConfigManager.go +++ b/agent/proxycfg-sources/local/mock_ConfigManager.go @@ -5,8 +5,8 @@ package local import ( proxycfg "github.com/hashicorp/consul/agent/proxycfg" mock "github.com/stretchr/testify/mock" + "context" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" structs "github.com/hashicorp/consul/agent/structs" ) @@ -52,27 +52,27 @@ func (_m *MockConfigManager) RegisteredProxies(source proxycfg.ProxySource) []pr } // Watch provides a mock function with given fields: id -func (_m *MockConfigManager) Watch(id proxycfg.ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc) { +func (_m *MockConfigManager) Watch(id proxycfg.ProxyID) (<-chan *proxycfg.ConfigSnapshot, context.CancelFunc) { ret := _m.Called(id) - var r0 <-chan proxysnapshot.ProxySnapshot - var r1 proxysnapshot.CancelFunc - if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc)); ok { + var r0 <-chan *proxycfg.ConfigSnapshot + var r1 context.CancelFunc + if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) (<-chan *proxycfg.ConfigSnapshot, context.CancelFunc)); ok { return rf(id) } - if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) <-chan proxysnapshot.ProxySnapshot); ok { + if rf, ok := ret.Get(0).(func(proxycfg.ProxyID) <-chan *proxycfg.ConfigSnapshot); ok { r0 = rf(id) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan proxysnapshot.ProxySnapshot) + r0 = ret.Get(0).(<-chan *proxycfg.ConfigSnapshot) } } - if rf, ok := ret.Get(1).(func(proxycfg.ProxyID) proxysnapshot.CancelFunc); ok { + if rf, ok := ret.Get(1).(func(proxycfg.ProxyID) context.CancelFunc); ok { r1 = rf(id) } else { if ret.Get(1) != nil { - r1 = ret.Get(1).(proxysnapshot.CancelFunc) + r1 = ret.Get(1).(context.CancelFunc) } } diff --git a/agent/proxycfg-sources/local/sync.go b/agent/proxycfg-sources/local/sync.go index 54d95e6594f2..a8047c82f115 100644 --- a/agent/proxycfg-sources/local/sync.go +++ b/agent/proxycfg-sources/local/sync.go @@ -7,8 +7,6 @@ import ( "context" "time" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - "github.com/hashicorp/go-hclog" "github.com/hashicorp/consul/agent/local" @@ -148,7 +146,7 @@ func sync(cfg SyncConfig) { //go:generate mockery --name ConfigManager --inpackage type ConfigManager interface { - Watch(id proxycfg.ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc) + Watch(id proxycfg.ProxyID) (<-chan *proxycfg.ConfigSnapshot, context.CancelFunc) Register(proxyID proxycfg.ProxyID, service *structs.NodeService, source proxycfg.ProxySource, token string, overwrite bool) error Deregister(proxyID proxycfg.ProxyID, source proxycfg.ProxySource) RegisteredProxies(source proxycfg.ProxySource) []proxycfg.ProxyID diff --git a/agent/proxycfg/api_gateway.go b/agent/proxycfg/api_gateway.go index 43798239a353..eb5d2464629c 100644 --- a/agent/proxycfg/api_gateway.go +++ b/agent/proxycfg/api_gateway.go @@ -63,7 +63,8 @@ func (h *handlerAPIGateway) initialize(ctx context.Context) (ConfigSnapshot, err snap.APIGateway.BoundListeners = make(map[string]structs.BoundAPIGatewayListener) snap.APIGateway.HTTPRoutes = watch.NewMap[structs.ResourceReference, *structs.HTTPRouteConfigEntry]() snap.APIGateway.TCPRoutes = watch.NewMap[structs.ResourceReference, *structs.TCPRouteConfigEntry]() - snap.APIGateway.Certificates = watch.NewMap[structs.ResourceReference, *structs.InlineCertificateConfigEntry]() + snap.APIGateway.InlineCertificates = watch.NewMap[structs.ResourceReference, *structs.InlineCertificateConfigEntry]() + snap.APIGateway.FileSystemCertificates = watch.NewMap[structs.ResourceReference, *structs.FileSystemCertificateConfigEntry]() snap.APIGateway.Upstreams = make(listenerRouteUpstreams) snap.APIGateway.UpstreamsSet = make(routeUpstreamSet) @@ -96,7 +97,8 @@ func (h *handlerAPIGateway) subscribeToConfigEntry(ctx context.Context, kind, na // handleUpdate responds to changes in the api-gateway. In general, we want // to crawl the various resources related to or attached to the gateway and // collect the list of things need to generate xDS. This list of resources -// includes the bound-api-gateway, http-routes, tcp-routes, and inline-certificates. +// includes the bound-api-gateway, http-routes, tcp-routes, +// file-system-certificates and inline-certificates. func (h *handlerAPIGateway) handleUpdate(ctx context.Context, u UpdateEvent, snap *ConfigSnapshot) error { if u.Err != nil { return fmt.Errorf("error filling agent cache: %v", u.Err) @@ -113,6 +115,11 @@ func (h *handlerAPIGateway) handleUpdate(ctx context.Context, u UpdateEvent, sna if err := h.handleGatewayConfigUpdate(ctx, u, snap, u.CorrelationID); err != nil { return err } + case fileSystemCertificateConfigWatchID: + // Handle change in an attached file-system-certificate config entry + if err := h.handleFileSystemCertConfigUpdate(ctx, u, snap); err != nil { + return err + } case inlineCertificateConfigWatchID: // Handle change in an attached inline-certificate config entry if err := h.handleInlineCertConfigUpdate(ctx, u, snap); err != nil { @@ -205,12 +212,21 @@ func (h *handlerAPIGateway) handleGatewayConfigUpdate(ctx context.Context, u Upd for _, ref := range listener.Certificates { ctx, cancel := context.WithCancel(ctx) seenRefs[ref] = struct{}{} - snap.APIGateway.Certificates.InitWatch(ref, cancel) - err := h.subscribeToConfigEntry(ctx, ref.Kind, ref.Name, ref.EnterpriseMeta, inlineCertificateConfigWatchID) - if err != nil { - // TODO May want to continue - return err + if ref.Kind == structs.FileSystemCertificate { + snap.APIGateway.FileSystemCertificates.InitWatch(ref, cancel) + + err := h.subscribeToConfigEntry(ctx, ref.Kind, ref.Name, ref.EnterpriseMeta, fileSystemCertificateConfigWatchID) + if err != nil { + return err + } + } else { + snap.APIGateway.InlineCertificates.InitWatch(ref, cancel) + + err := h.subscribeToConfigEntry(ctx, ref.Kind, ref.Name, ref.EnterpriseMeta, inlineCertificateConfigWatchID) + if err != nil { + return err + } } } } @@ -234,9 +250,16 @@ func (h *handlerAPIGateway) handleGatewayConfigUpdate(ctx context.Context, u Upd return true }) - snap.APIGateway.Certificates.ForEachKey(func(ref structs.ResourceReference) bool { + snap.APIGateway.InlineCertificates.ForEachKey(func(ref structs.ResourceReference) bool { if _, ok := seenRefs[ref]; !ok { - snap.APIGateway.Certificates.CancelWatch(ref) + snap.APIGateway.InlineCertificates.CancelWatch(ref) + } + return true + }) + + snap.APIGateway.FileSystemCertificates.ForEachKey(func(ref structs.ResourceReference) bool { + if _, ok := seenRefs[ref]; !ok { + snap.APIGateway.FileSystemCertificates.CancelWatch(ref) } return true }) @@ -265,6 +288,30 @@ func (h *handlerAPIGateway) handleGatewayConfigUpdate(ctx context.Context, u Upd return h.watchIngressLeafCert(ctx, snap) } +func (h *handlerAPIGateway) handleFileSystemCertConfigUpdate(_ context.Context, u UpdateEvent, snap *ConfigSnapshot) error { + resp, ok := u.Result.(*structs.ConfigEntryResponse) + if !ok { + return fmt.Errorf("invalid type for response: %T", u.Result) + } else if resp == nil || resp.Entry == nil { + return nil + } + + cfg, ok := resp.Entry.(*structs.FileSystemCertificateConfigEntry) + if !ok || cfg == nil { + return fmt.Errorf("invalid type for config entry: %T", resp.Entry) + } + + ref := structs.ResourceReference{ + Kind: cfg.GetKind(), + Name: cfg.GetName(), + EnterpriseMeta: *cfg.GetEnterpriseMeta(), + } + + snap.APIGateway.FileSystemCertificates.Set(ref, cfg) + + return nil +} + // handleInlineCertConfigUpdate stores the certificate for the gateway func (h *handlerAPIGateway) handleInlineCertConfigUpdate(_ context.Context, u UpdateEvent, snap *ConfigSnapshot) error { resp, ok := u.Result.(*structs.ConfigEntryResponse) @@ -285,7 +332,7 @@ func (h *handlerAPIGateway) handleInlineCertConfigUpdate(_ context.Context, u Up EnterpriseMeta: *cfg.GetEnterpriseMeta(), } - snap.APIGateway.Certificates.Set(ref, cfg) + snap.APIGateway.InlineCertificates.Set(ref, cfg) return nil } diff --git a/agent/proxycfg/manager.go b/agent/proxycfg/manager.go index 71b6270fefc4..f2f7978a0a03 100644 --- a/agent/proxycfg/manager.go +++ b/agent/proxycfg/manager.go @@ -4,15 +4,17 @@ package proxycfg import ( + "context" "errors" "runtime/debug" "sync" - "github.com/hashicorp/go-hclog" "golang.org/x/time/rate" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/consul/agent/structs" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" + "github.com/hashicorp/consul/lib/channels" "github.com/hashicorp/consul/tlsutil" ) @@ -37,6 +39,10 @@ type ProxyID struct { // from overwriting each other's registrations. type ProxySource string +// SrcTerminatedChan indicates that the config-source for the proxycfg is no longer running +// and will stop receiving updates when it is closed. +type SrcTerminatedChan <-chan struct{} + // Manager provides an API with which proxy services can be registered, and // coordinates the fetching (and refreshing) of intentions, upstreams, discovery // chain, certificates etc. @@ -52,7 +58,7 @@ type Manager struct { mu sync.Mutex proxies map[ProxyID]*state - watchers map[ProxyID]map[uint64]chan proxysnapshot.ProxySnapshot + watchers map[ProxyID]map[uint64]chan *ConfigSnapshot maxWatchID uint64 } @@ -103,7 +109,7 @@ func NewManager(cfg ManagerConfig) (*Manager, error) { m := &Manager{ ManagerConfig: cfg, proxies: make(map[ProxyID]*state), - watchers: make(map[ProxyID]map[uint64]chan proxysnapshot.ProxySnapshot), + watchers: make(map[ProxyID]map[uint64]chan *ConfigSnapshot), rateLimiter: rate.NewLimiter(cfg.UpdateRateLimit, 1), } return m, nil @@ -259,53 +265,31 @@ func (m *Manager) notify(snap *ConfigSnapshot) { // it will drain the chan and then re-attempt delivery so that a slow consumer // gets the latest config earlier. This MUST be called from a method where m.mu // is held to be safe since it assumes we are the only goroutine sending on ch. -func (m *Manager) deliverLatest(snap *ConfigSnapshot, ch chan proxysnapshot.ProxySnapshot) { - // Send if chan is empty - select { - case ch <- snap: - return - default: - } - - // Not empty, drain the chan of older snapshots and redeliver. For now we only - // use 1-buffered chans but this will still work if we change that later. -OUTER: - for { - select { - case <-ch: - continue - default: - break OUTER - } - } - - // Now send again - select { - case ch <- snap: - return - default: - // This should not be possible since we should be the only sender, enforced - // by m.mu but error and drop the update rather than panic. - m.Logger.Error("failed to deliver ConfigSnapshot to proxy", - "proxy", snap.ProxyID.String(), +func (m *Manager) deliverLatest(snap *ConfigSnapshot, ch chan *ConfigSnapshot) { + m.Logger.Trace("delivering latest proxy snapshot to proxy", "proxyID", snap.ProxyID) + err := channels.DeliverLatest(snap, ch) + if err != nil { + m.Logger.Error("failed to deliver proxyState to proxy", + "proxy", snap.ProxyID, ) } + } // Watch registers a watch on a proxy. It might not exist yet in which case this // will not fail, but no updates will be delivered until the proxy is // registered. If there is already a valid snapshot in memory, it will be // delivered immediately. -func (m *Manager) Watch(id ProxyID) (<-chan proxysnapshot.ProxySnapshot, proxysnapshot.CancelFunc) { +func (m *Manager) Watch(id ProxyID) (<-chan *ConfigSnapshot, context.CancelFunc) { m.mu.Lock() defer m.mu.Unlock() // This buffering is crucial otherwise we'd block immediately trying to // deliver the current snapshot below if we already have one. - ch := make(chan proxysnapshot.ProxySnapshot, 1) + ch := make(chan *ConfigSnapshot, 1) watchers, ok := m.watchers[id] if !ok { - watchers = make(map[uint64]chan proxysnapshot.ProxySnapshot) + watchers = make(map[uint64]chan *ConfigSnapshot) } watchID := m.maxWatchID m.maxWatchID++ diff --git a/agent/proxycfg/manager_test.go b/agent/proxycfg/manager_test.go index feaa4e431d03..e751364ddb0c 100644 --- a/agent/proxycfg/manager_test.go +++ b/agent/proxycfg/manager_test.go @@ -17,7 +17,6 @@ import ( "github.com/hashicorp/consul/agent/proxycfg/internal/watch" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" "github.com/hashicorp/consul/proto/private/pbpeering" "github.com/hashicorp/consul/sdk/testutil" ) @@ -73,8 +72,9 @@ func TestManager_BasicLifecycle(t *testing.T) { dbSplitChain := func() *structs.CompiledDiscoveryChain { set := configentry.NewDiscoveryChainSet() set.AddEntries(&structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, + Kind: structs.ProxyDefaults, + Name: structs.ProxyConfigGlobal, + Protocol: "http", Config: map[string]interface{}{ "protocol": "http", }, @@ -470,7 +470,7 @@ func testManager_BasicLifecycle( require.Len(t, m.watchers, 0) } -func assertWatchChanBlocks(t *testing.T, ch <-chan proxysnapshot.ProxySnapshot) { +func assertWatchChanBlocks(t *testing.T, ch <-chan *ConfigSnapshot) { t.Helper() select { @@ -480,7 +480,7 @@ func assertWatchChanBlocks(t *testing.T, ch <-chan proxysnapshot.ProxySnapshot) } } -func assertWatchChanRecvs(t *testing.T, ch <-chan proxysnapshot.ProxySnapshot, expect proxysnapshot.ProxySnapshot) { +func assertWatchChanRecvs(t *testing.T, ch <-chan *ConfigSnapshot, expect *ConfigSnapshot) { t.Helper() select { @@ -518,7 +518,7 @@ func TestManager_deliverLatest(t *testing.T) { } // test 1 buffered chan - ch1 := make(chan proxysnapshot.ProxySnapshot, 1) + ch1 := make(chan *ConfigSnapshot, 1) // Sending to an unblocked chan should work m.deliverLatest(snap1, ch1) @@ -534,7 +534,7 @@ func TestManager_deliverLatest(t *testing.T) { require.Equal(t, snap2, <-ch1) // Same again for 5-buffered chan - ch5 := make(chan proxysnapshot.ProxySnapshot, 5) + ch5 := make(chan *ConfigSnapshot, 5) // Sending to an unblocked chan should work m.deliverLatest(snap1, ch5) diff --git a/agent/proxycfg/mesh_gateway.go b/agent/proxycfg/mesh_gateway.go index 0237e8423290..3d8bcd43a9aa 100644 --- a/agent/proxycfg/mesh_gateway.go +++ b/agent/proxycfg/mesh_gateway.go @@ -127,6 +127,17 @@ func (s *handlerMeshGateway) initialize(ctx context.Context) (ConfigSnapshot, er if err != nil { return snap, err } + // Watch for service default object that matches this mesh gateway's name + err = s.dataSources.ConfigEntry.Notify(ctx, &structs.ConfigEntryQuery{ + Kind: structs.ServiceDefaults, + Name: s.service, + Datacenter: s.source.Datacenter, + QueryOptions: structs.QueryOptions{Token: s.token}, + EnterpriseMeta: s.proxyID.EnterpriseMeta, + }, serviceDefaultsWatchID, s.ch) + if err != nil { + return snap, err + } snap.MeshGateway.WatchedServices = make(map[structs.ServiceName]context.CancelFunc) snap.MeshGateway.WatchedGateways = make(map[string]context.CancelFunc) @@ -295,6 +306,7 @@ func (s *handlerMeshGateway) handleUpdate(ctx context.Context, u UpdateEvent, sn QueryOptions: structs.QueryOptions{Token: s.token}, ServiceKind: structs.ServiceKindMeshGateway, UseServiceKind: true, + NodesOnly: true, Source: *s.source, EnterpriseMeta: *entMeta, }, fmt.Sprintf("mesh-gateway:%s", gk.String()), s.ch) @@ -647,6 +659,25 @@ func (s *handlerMeshGateway) handleUpdate(ctx context.Context, u UpdateEvent, sn } snap.MeshGateway.PeerServers = peerServers + case serviceDefaultsWatchID: + resp, ok := u.Result.(*structs.ConfigEntryResponse) + if !ok { + return fmt.Errorf("invalid type for config entry: %T", resp.Entry) + } + + if resp.Entry == nil { + return nil + } + serviceDefaults, ok := resp.Entry.(*structs.ServiceConfigEntry) + if !ok { + return fmt.Errorf("invalid type for config entry: %T", resp.Entry) + } + + if serviceDefaults.UpstreamConfig != nil && serviceDefaults.UpstreamConfig.Defaults != nil { + if serviceDefaults.UpstreamConfig.Defaults.Limits != nil { + snap.MeshGateway.Limits = serviceDefaults.UpstreamConfig.Defaults.Limits + } + } default: switch { diff --git a/agent/proxycfg/proxycfg.deepcopy.go b/agent/proxycfg/proxycfg.deepcopy.go index ebe052d1088f..1922810fe557 100644 --- a/agent/proxycfg/proxycfg.deepcopy.go +++ b/agent/proxycfg/proxycfg.deepcopy.go @@ -1,10 +1,11 @@ -// generated by deep-copy -pointer-receiver -o ./proxycfg.deepcopy.go -type ConfigSnapshot -type ConfigSnapshotUpstreams -type PeerServersValue -type PeeringServiceValue -type configSnapshotAPIGateway -type configSnapshotConnectProxy -type configSnapshotIngressGateway -type configSnapshotMeshGateway -type configSnapshotTerminatingGateway ./; DO NOT EDIT. +// Code generated by deep-copy -pointer-receiver -o ./proxycfg.deepcopy.go -type ConfigSnapshot -type ConfigSnapshotUpstreams -type PeerServersValue -type PeeringServiceValue -type configSnapshotAPIGateway -type configSnapshotConnectProxy -type configSnapshotIngressGateway -type configSnapshotMeshGateway -type configSnapshotTerminatingGateway ./; DO NOT EDIT. package proxycfg import ( "context" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/agent/xds/config" "github.com/hashicorp/consul/proto/private/pbpeering" "github.com/hashicorp/consul/types" "time" @@ -147,6 +148,36 @@ func (o *ConfigSnapshot) DeepCopy() *ConfigSnapshot { retV := o.APIGateway.DeepCopy() cp.APIGateway = *retV } + if o.computedFields.xdsCommonConfig != nil { + cp.computedFields.xdsCommonConfig = new(config.XDSCommonConfig) + *cp.computedFields.xdsCommonConfig = *o.computedFields.xdsCommonConfig + if o.computedFields.xdsCommonConfig.XDSFetchTimeoutMs != nil { + cp.computedFields.xdsCommonConfig.XDSFetchTimeoutMs = new(int) + *cp.computedFields.xdsCommonConfig.XDSFetchTimeoutMs = *o.computedFields.xdsCommonConfig.XDSFetchTimeoutMs + } + } + if o.computedFields.proxyConfig != nil { + cp.computedFields.proxyConfig = new(config.ProxyConfig) + *cp.computedFields.proxyConfig = *o.computedFields.proxyConfig + if o.computedFields.proxyConfig.LocalRequestTimeoutMs != nil { + cp.computedFields.proxyConfig.LocalRequestTimeoutMs = new(int) + *cp.computedFields.proxyConfig.LocalRequestTimeoutMs = *o.computedFields.proxyConfig.LocalRequestTimeoutMs + } + if o.computedFields.proxyConfig.LocalIdleTimeoutMs != nil { + cp.computedFields.proxyConfig.LocalIdleTimeoutMs = new(int) + *cp.computedFields.proxyConfig.LocalIdleTimeoutMs = *o.computedFields.proxyConfig.LocalIdleTimeoutMs + } + } + if o.computedFields.gatewayConfig != nil { + cp.computedFields.gatewayConfig = new(config.GatewayConfig) + *cp.computedFields.gatewayConfig = *o.computedFields.gatewayConfig + if o.computedFields.gatewayConfig.BindAddresses != nil { + cp.computedFields.gatewayConfig.BindAddresses = make(map[string]structs.ServiceAddress, len(o.computedFields.gatewayConfig.BindAddresses)) + for k5, v5 := range o.computedFields.gatewayConfig.BindAddresses { + cp.computedFields.gatewayConfig.BindAddresses[k5] = v5 + } + } + } return &cp } @@ -390,7 +421,8 @@ func (o *configSnapshotAPIGateway) DeepCopy() *configSnapshotAPIGateway { } cp.HTTPRoutes = o.HTTPRoutes.DeepCopy() cp.TCPRoutes = o.TCPRoutes.DeepCopy() - cp.Certificates = o.Certificates.DeepCopy() + cp.InlineCertificates = o.InlineCertificates.DeepCopy() + cp.FileSystemCertificates = o.FileSystemCertificates.DeepCopy() if o.Listeners != nil { cp.Listeners = make(map[string]structs.APIGatewayListener, len(o.Listeners)) for k2, v2 := range o.Listeners { @@ -696,6 +728,22 @@ func (o *configSnapshotMeshGateway) DeepCopy() *configSnapshotMeshGateway { } } } + if o.Limits != nil { + cp.Limits = new(structs.UpstreamLimits) + *cp.Limits = *o.Limits + if o.Limits.MaxConnections != nil { + cp.Limits.MaxConnections = new(int) + *cp.Limits.MaxConnections = *o.Limits.MaxConnections + } + if o.Limits.MaxPendingRequests != nil { + cp.Limits.MaxPendingRequests = new(int) + *cp.Limits.MaxPendingRequests = *o.Limits.MaxPendingRequests + } + if o.Limits.MaxConcurrentRequests != nil { + cp.Limits.MaxConcurrentRequests = new(int) + *cp.Limits.MaxConcurrentRequests = *o.Limits.MaxConcurrentRequests + } + } return &cp } diff --git a/agent/proxycfg/snapshot.go b/agent/proxycfg/snapshot.go index 8d7aebd456e1..bac6e8b6dad4 100644 --- a/agent/proxycfg/snapshot.go +++ b/agent/proxycfg/snapshot.go @@ -9,11 +9,14 @@ import ( "sort" "strings" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/discoverychain" "github.com/hashicorp/consul/agent/proxycfg/internal/watch" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/agent/xds/config" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/proto/private/pbpeering" ) @@ -495,6 +498,9 @@ type configSnapshotMeshGateway struct { // PeeringTrustBundlesSet indicates that the watch on the peer trust // bundles has completed at least once. PeeringTrustBundlesSet bool + + // Limits + Limits *structs.UpstreamLimits } // MeshGatewayValidExportedServices ensures that the following data is present @@ -733,9 +739,11 @@ type configSnapshotAPIGateway struct { // UpstreamsSet is the unique set of UpstreamID the gateway routes to. UpstreamsSet routeUpstreamSet - HTTPRoutes watch.Map[structs.ResourceReference, *structs.HTTPRouteConfigEntry] - TCPRoutes watch.Map[structs.ResourceReference, *structs.TCPRouteConfigEntry] - Certificates watch.Map[structs.ResourceReference, *structs.InlineCertificateConfigEntry] + HTTPRoutes watch.Map[structs.ResourceReference, *structs.HTTPRouteConfigEntry] + TCPRoutes watch.Map[structs.ResourceReference, *structs.TCPRouteConfigEntry] + + InlineCertificates watch.Map[structs.ResourceReference, *structs.InlineCertificateConfigEntry] + FileSystemCertificates watch.Map[structs.ResourceReference, *structs.FileSystemCertificateConfigEntry] // LeafCertWatchCancel is a CancelFunc to use when refreshing this gateway's // leaf cert watch with different parameters. @@ -963,6 +971,18 @@ type ConfigSnapshot struct { // api-gateway specific APIGateway configSnapshotAPIGateway + + // computedFields exists as a place to store relatively expensive + // computed data (such as parsed opaque maps) rather than parsing it + // multiple times during xDS generation. All data in this should be + // lazy-loaded / memoized when requested. + computedFields computedFields +} + +type computedFields struct { + xdsCommonConfig *config.XDSCommonConfig + proxyConfig *config.ProxyConfig + gatewayConfig *config.GatewayConfig } // Valid returns whether or not the snapshot has all required fields filled yet. @@ -1016,6 +1036,7 @@ func (s *ConfigSnapshot) Valid() bool { // without worrying that they will racily read or mutate shared maps etc. func (s *ConfigSnapshot) Clone() *ConfigSnapshot { snap := s.DeepCopy() + snap.computedFields = computedFields{} // nil these out as anything receiving one of these clones does not need them and should never "cancel" our watches switch s.Kind { @@ -1180,3 +1201,54 @@ func (u *ConfigSnapshotUpstreams) PeeredUpstreamIDs() []UpstreamID { }) return out } + +// GetXDSCommonConfig attempts to parse and return the xds config from the config snapshot. +// Subsequent calls to this function will return the temporary cached value to reduce +// cost of parsing. This function always returns a non-nil pointer to a config. +// Any errors will be output to the logger during the initial parse time only. +func (s *ConfigSnapshot) GetXDSCommonConfig(logger hclog.Logger) *config.XDSCommonConfig { + if s.computedFields.xdsCommonConfig == nil { + cfg, err := config.ParseXDSCommonConfig(s.Proxy.Config) + s.computedFields.xdsCommonConfig = &cfg + if err != nil { + // Don't hard fail on a config typo, just warn. The parse func returns + // default config if there is an error so it's safe to continue. + logger.Warn("failed to parse Connect.Proxy.Config", "error", err) + } + } + return s.computedFields.xdsCommonConfig +} + +// GetProxyConfig attempts to parse and return the proxy config from the config snapshot. +// Subsequent calls to this function will return the temporary cached value to reduce +// cost of parsing. This function always returns a non-nil pointer to a config. +// Any errors will be output to the logger during the initial parse time only. +func (s *ConfigSnapshot) GetProxyConfig(logger hclog.Logger) *config.ProxyConfig { + if s.computedFields.proxyConfig == nil { + cfg, err := config.ParseProxyConfig(s.Proxy.Config) + s.computedFields.proxyConfig = &cfg + if err != nil { + // Don't hard fail on a config typo, just warn. The parse func returns + // default config if there is an error so it's safe to continue. + logger.Warn("failed to parse proxy Connect.Proxy.Config", "error", err) + } + } + return s.computedFields.proxyConfig +} + +// GetGatewayConfig attempts to parse and return the gateway config from the config snapshot. +// Subsequent calls to this function will return the temporary cached value to reduce +// cost of parsing. This function always returns a non-nil pointer to a config. +// Any errors will be output to the logger during the initial parse time only. +func (s *ConfigSnapshot) GetGatewayConfig(logger hclog.Logger) *config.GatewayConfig { + if s.computedFields.gatewayConfig == nil { + cfg, err := config.ParseGatewayConfig(s.Proxy.Config) + s.computedFields.gatewayConfig = &cfg + if err != nil { + // Don't hard fail on a config typo, just warn. The parse func returns + // default config if there is an error so it's safe to continue. + logger.Warn("failed to parse gateway Connect.Proxy.Config", "error", err) + } + } + return s.computedFields.gatewayConfig +} diff --git a/agent/proxycfg/snapshot_test.go b/agent/proxycfg/snapshot_test.go index b4b0ab57c957..4978316c0b98 100644 --- a/agent/proxycfg/snapshot_test.go +++ b/agent/proxycfg/snapshot_test.go @@ -47,6 +47,7 @@ func TestConfigSnapshot_Clone(t *testing.T) { cmpopts.IgnoreUnexported(indexedTarget{}), cmpopts.IgnoreUnexported(pbpeering.PeeringTrustBundle{}), cmpopts.IgnoreTypes(context.CancelFunc(nil)), + cmpopts.IgnoreTypes(computedFields{}), ) if diff != "" { t.Logf("Copied snaspshot is different to the original. You may need to re-run `make deep-copy`.\nDiff:\n%s", diff) diff --git a/agent/proxycfg/state.go b/agent/proxycfg/state.go index 853dca5a9f1b..b6b9c78f3201 100644 --- a/agent/proxycfg/state.go +++ b/agent/proxycfg/state.go @@ -34,10 +34,12 @@ const ( consulServerListWatchID = "consul-server-list" datacentersWatchID = "datacenters" serviceResolversWatchID = "service-resolvers" + serviceDefaultsWatchID = "service-defaults" gatewayServicesWatchID = "gateway-services" gatewayConfigWatchID = "gateway-config" apiGatewayConfigWatchID = "api-gateway-config" boundGatewayConfigWatchID = "bound-gateway-config" + fileSystemCertificateConfigWatchID = "file-system-certificate-config" inlineCertificateConfigWatchID = "inline-certificate-config" routeConfigWatchID = "route-config" externalServiceIDPrefix = "external-service:" @@ -544,6 +546,7 @@ func watchMeshGateway(ctx context.Context, opts gatewayWatchOpts) error { QueryOptions: structs.QueryOptions{Token: opts.token}, ServiceKind: structs.ServiceKindMeshGateway, UseServiceKind: true, + NodesOnly: true, Source: opts.source, EnterpriseMeta: *structs.DefaultEnterpriseMetaInPartition(opts.key.Partition), }, correlationId, opts.notifyCh) diff --git a/agent/proxycfg/state_test.go b/agent/proxycfg/state_test.go index 2a6792aa22e9..43743eb40a03 100644 --- a/agent/proxycfg/state_test.go +++ b/agent/proxycfg/state_test.go @@ -838,6 +838,282 @@ func TestState_WatchesAndUpdates(t *testing.T) { stages: []verificationStage{stage0, stage1}, } } + newConnectProxyCaseMeshDefault := func() testCase { + ns := structs.NodeService{ + Kind: structs.ServiceKindConnectProxy, + ID: "web-sidecar-proxy", + Service: "web-sidecar-proxy", + Address: "10.0.1.1", + Port: 443, + Proxy: structs.ConnectProxyConfig{ + DestinationServiceName: "web", + Upstreams: structs.Upstreams{ + structs.Upstream{ + DestinationType: structs.UpstreamDestTypePreparedQuery, + DestinationName: "query", + LocalBindPort: 10001, + }, + structs.Upstream{ + DestinationType: structs.UpstreamDestTypeService, + DestinationName: "api", + LocalBindPort: 10002, + }, + structs.Upstream{ + DestinationType: structs.UpstreamDestTypeService, + DestinationName: "api-failover-direct", + Datacenter: "dc2", + LocalBindPort: 10005, + MeshGateway: structs.MeshGatewayConfig{ + Mode: structs.MeshGatewayModeNone, + }, + }, + structs.Upstream{ + DestinationType: structs.UpstreamDestTypeService, + DestinationName: "api-failover-to-peer", + LocalBindPort: 10007, + }, + structs.Upstream{ + DestinationType: structs.UpstreamDestTypeService, + DestinationName: "api-dc2", + LocalBindPort: 10006, + }, + }, + }, + } + + ixnMatch := TestIntentions() + + stage0 := verificationStage{ + requiredWatches: map[string]verifyWatchRequest{ + intentionsWatchID: genVerifyIntentionWatch("web", "dc1"), + meshConfigEntryID: genVerifyMeshConfigWatch("dc1"), + fmt.Sprintf("discovery-chain:%s", apiUID.String()): genVerifyDiscoveryChainWatch(&structs.DiscoveryChainRequest{ + Name: "api", + EvaluateInDatacenter: "dc1", + EvaluateInNamespace: "default", + EvaluateInPartition: "default", + Datacenter: "dc1", + OverrideMeshGateway: structs.MeshGatewayConfig{ + Mode: structs.MeshGatewayModeDefault, + }, + QueryOptions: structs.QueryOptions{ + Token: aclToken, + }, + }), + fmt.Sprintf("discovery-chain:%s-failover-direct?dc=dc2", apiUID.String()): genVerifyDiscoveryChainWatch(&structs.DiscoveryChainRequest{ + Name: "api-failover-direct", + EvaluateInDatacenter: "dc2", + EvaluateInNamespace: "default", + EvaluateInPartition: "default", + Datacenter: "dc1", + OverrideMeshGateway: structs.MeshGatewayConfig{ + Mode: structs.MeshGatewayModeNone, + }, + QueryOptions: structs.QueryOptions{ + Token: aclToken, + }, + }), + fmt.Sprintf("discovery-chain:%s-failover-to-peer", apiUID.String()): genVerifyDiscoveryChainWatch(&structs.DiscoveryChainRequest{ + Name: "api-failover-to-peer", + EvaluateInDatacenter: "dc1", + EvaluateInNamespace: "default", + EvaluateInPartition: "default", + Datacenter: "dc1", + OverrideMeshGateway: structs.MeshGatewayConfig{ + Mode: structs.MeshGatewayModeDefault, + }, + QueryOptions: structs.QueryOptions{ + Token: aclToken, + }, + }), + fmt.Sprintf("discovery-chain:%s-dc2", apiUID.String()): genVerifyDiscoveryChainWatch(&structs.DiscoveryChainRequest{ + Name: "api-dc2", + EvaluateInDatacenter: "dc1", + EvaluateInNamespace: "default", + EvaluateInPartition: "default", + Datacenter: "dc1", + OverrideMeshGateway: structs.MeshGatewayConfig{ + Mode: structs.MeshGatewayModeDefault, + }, + QueryOptions: structs.QueryOptions{ + Token: aclToken, + }, + }), + "upstream:" + pqUID.String(): genVerifyPreparedQueryWatch("query", "dc1"), + rootsWatchID: genVerifyDCSpecificWatch("dc1"), + leafWatchID: genVerifyLeafWatch("web", "dc1"), + }, + events: []UpdateEvent{ + rootWatchEvent(), + { + CorrelationID: leafWatchID, + Result: issuedCert, + Err: nil, + }, + { + CorrelationID: intentionsWatchID, + Result: ixnMatch, + Err: nil, + }, + { + CorrelationID: meshConfigEntryID, + Result: &structs.ConfigEntryResponse{}, + }, + { + CorrelationID: fmt.Sprintf("discovery-chain:%s", apiUID.String()), + Result: &structs.DiscoveryChainResponse{ + Chain: discoverychain.TestCompileConfigEntries(t, "api", "default", "default", "dc1", "trustdomain.consul", + func(req *discoverychain.CompileRequest) { + req.OverrideMeshGateway.Mode = structs.MeshGatewayModeDefault + }, nil), + }, + Err: nil, + }, + { + CorrelationID: fmt.Sprintf("discovery-chain:%s-failover-remote?dc=dc2", apiUID.String()), + Result: &structs.DiscoveryChainResponse{ + Chain: discoverychain.TestCompileConfigEntries(t, "api-failover-remote", "default", "default", "dc2", "trustdomain.consul", + func(req *discoverychain.CompileRequest) { + req.OverrideMeshGateway.Mode = structs.MeshGatewayModeDefault + }, nil), + }, + Err: nil, + }, + { + CorrelationID: fmt.Sprintf("discovery-chain:%s-failover-local?dc=dc2", apiUID.String()), + Result: &structs.DiscoveryChainResponse{ + Chain: discoverychain.TestCompileConfigEntries(t, "api-failover-local", "default", "default", "dc2", "trustdomain.consul", + func(req *discoverychain.CompileRequest) { + req.OverrideMeshGateway.Mode = structs.MeshGatewayModeDefault + }, nil), + }, + Err: nil, + }, + { + CorrelationID: fmt.Sprintf("discovery-chain:%s-failover-direct?dc=dc2", apiUID.String()), + Result: &structs.DiscoveryChainResponse{ + Chain: discoverychain.TestCompileConfigEntries(t, "api-failover-direct", "default", "default", "dc2", "trustdomain.consul", + func(req *discoverychain.CompileRequest) { + req.OverrideMeshGateway.Mode = structs.MeshGatewayModeDefault + }, nil), + }, + Err: nil, + }, + { + CorrelationID: fmt.Sprintf("discovery-chain:%s-dc2", apiUID.String()), + Result: &structs.DiscoveryChainResponse{ + Chain: discoverychain.TestCompileConfigEntries(t, "api-dc2", "default", "default", "dc1", "trustdomain.consul", + func(req *discoverychain.CompileRequest) { + req.OverrideMeshGateway.Mode = structs.MeshGatewayModeDefault + }, discoChainSetWithEntries(&structs.ServiceResolverConfigEntry{ + Kind: structs.ServiceResolver, + Name: "api-dc2", + Redirect: &structs.ServiceResolverRedirect{ + Service: "api", + Datacenter: "dc2", + }, + })), + }, + Err: nil, + }, + { + CorrelationID: fmt.Sprintf("discovery-chain:%s-failover-to-peer", apiUID.String()), + Result: &structs.DiscoveryChainResponse{ + Chain: discoverychain.TestCompileConfigEntries(t, "api-failover-to-peer", "default", "default", "dc1", "trustdomain.consul", + func(req *discoverychain.CompileRequest) { + req.OverrideMeshGateway.Mode = structs.MeshGatewayModeDefault + }, discoChainSetWithEntries(&structs.ServiceResolverConfigEntry{ + Kind: structs.ServiceResolver, + Name: "api-failover-to-peer", + Failover: map[string]structs.ServiceResolverFailover{ + "*": { + Targets: []structs.ServiceResolverFailoverTarget{ + {Peer: "cluster-01"}, + }, + }, + }, + })), + }, + Err: nil, + }, + { + CorrelationID: "mesh-gateway:dc1", + Result: &structs.IndexedCheckServiceNodes{ + Nodes: structs.CheckServiceNodes{ + { + Node: &structs.Node{ + Node: "node1", + Address: "10.1.2.3", + }, + Service: structs.TestNodeServiceMeshGateway(t), + }, + }, + }, + }, + }, + verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) { + require.True(t, snap.Valid()) + require.True(t, snap.MeshGateway.isEmpty()) + require.Equal(t, indexedRoots, snap.Roots) + + require.Equal(t, issuedCert, snap.ConnectProxy.Leaf) + require.Len(t, snap.ConnectProxy.DiscoveryChain, 4, "%+v", snap.ConnectProxy.DiscoveryChain) + require.Len(t, snap.ConnectProxy.WatchedUpstreams, 4, "%+v", snap.ConnectProxy.WatchedUpstreams) + require.Len(t, snap.ConnectProxy.WatchedUpstreamEndpoints, 4, "%+v", snap.ConnectProxy.WatchedUpstreamEndpoints) + require.Len(t, snap.ConnectProxy.WatchedGateways, 4, "%+v", snap.ConnectProxy.WatchedGateways) + require.Len(t, snap.ConnectProxy.WatchedGatewayEndpoints, 4, "%+v", snap.ConnectProxy.WatchedGatewayEndpoints) + + require.Len(t, snap.ConnectProxy.WatchedServiceChecks, 0, "%+v", snap.ConnectProxy.WatchedServiceChecks) + require.Len(t, snap.ConnectProxy.PreparedQueryEndpoints, 0, "%+v", snap.ConnectProxy.PreparedQueryEndpoints) + + require.Equal(t, 1, snap.ConnectProxy.ConfigSnapshotUpstreams.PeerUpstreamEndpoints.Len()) + require.Equal(t, 1, snap.ConnectProxy.ConfigSnapshotUpstreams.UpstreamPeerTrustBundles.Len()) + + require.True(t, snap.ConnectProxy.IntentionsSet) + require.Equal(t, ixnMatch, snap.ConnectProxy.Intentions) + require.True(t, snap.ConnectProxy.MeshConfigSet) + + // No event is expected as all services use default or remote mode + require.Equal(t, 0, snap.ConnectProxy.WatchedLocalGWEndpoints.Len()) + }, + } + + stage1 := verificationStage{ + requiredWatches: map[string]verifyWatchRequest{ + fmt.Sprintf("upstream-target:api.default.default.dc1:%s", apiUID.String()): genVerifyServiceSpecificRequest("api", "", "dc1", true), + fmt.Sprintf("upstream-target:api-failover-direct.default.default.dc2:%s-failover-direct?dc=dc2", apiUID.String()): genVerifyServiceSpecificRequest("api-failover-direct", "", "dc2", true), + upstreamPeerWatchIDPrefix + fmt.Sprintf("%s-failover-to-peer?peer=cluster-01", apiUID.String()): genVerifyServiceSpecificPeeredRequest("api-failover-to-peer", "", "dc1", "cluster-01", true), + }, + verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) { + require.True(t, snap.Valid()) + require.True(t, snap.MeshGateway.isEmpty()) + require.Equal(t, indexedRoots, snap.Roots) + + require.Equal(t, issuedCert, snap.ConnectProxy.Leaf) + require.Len(t, snap.ConnectProxy.DiscoveryChain, 4, "%+v", snap.ConnectProxy.DiscoveryChain) + require.Len(t, snap.ConnectProxy.WatchedUpstreams, 4, "%+v", snap.ConnectProxy.WatchedUpstreams) + require.Len(t, snap.ConnectProxy.WatchedUpstreamEndpoints, 4, "%+v", snap.ConnectProxy.WatchedUpstreamEndpoints) + require.Len(t, snap.ConnectProxy.WatchedGateways, 4, "%+v", snap.ConnectProxy.WatchedGateways) + require.Len(t, snap.ConnectProxy.WatchedGatewayEndpoints, 4, "%+v", snap.ConnectProxy.WatchedGatewayEndpoints) + + require.Len(t, snap.ConnectProxy.WatchedServiceChecks, 0, "%+v", snap.ConnectProxy.WatchedServiceChecks) + require.Len(t, snap.ConnectProxy.PreparedQueryEndpoints, 0, "%+v", snap.ConnectProxy.PreparedQueryEndpoints) + + require.Equal(t, 1, snap.ConnectProxy.ConfigSnapshotUpstreams.PeerUpstreamEndpoints.Len()) + require.Equal(t, 1, snap.ConnectProxy.ConfigSnapshotUpstreams.UpstreamPeerTrustBundles.Len()) + + require.True(t, snap.ConnectProxy.IntentionsSet) + require.Equal(t, ixnMatch, snap.ConnectProxy.Intentions) + + }, + } + + return testCase{ + ns: ns, + sourceDC: "dc1", + stages: []verificationStage{stage0, stage1}, + } + } dbIxnMatch := structs.SimplifiedIntentions{ { @@ -3444,8 +3720,9 @@ func TestState_WatchesAndUpdates(t *testing.T) { }, }, }, - "connect-proxy": newConnectProxyCase(structs.MeshGatewayModeDefault), - "connect-proxy-mesh-gateway-local": newConnectProxyCase(structs.MeshGatewayModeLocal), + "connect-proxy": newConnectProxyCase(structs.MeshGatewayModeDefault), + "connect-proxy-mesh-gateway-default": newConnectProxyCaseMeshDefault(), + "connect-proxy-mesh-gateway-local": newConnectProxyCase(structs.MeshGatewayModeLocal), "connect-proxy-with-peers": { ns: structs.NodeService{ Kind: structs.ServiceKindConnectProxy, diff --git a/agent/proxycfg/testing_ingress_gateway.go b/agent/proxycfg/testing_ingress_gateway.go index 96918a261bd0..f178955c18ab 100644 --- a/agent/proxycfg/testing_ingress_gateway.go +++ b/agent/proxycfg/testing_ingress_gateway.go @@ -1364,7 +1364,7 @@ func TestConfigSnapshotIngressGateway_TLSMinVersionListenersGatewayDefaults(t te Port: 8083, Protocol: "http", Services: []structs.IngressService{ - {Name: "s3"}, + {Name: "s4"}, }, TLS: &structs.GatewayTLSConfig{ Enabled: true, diff --git a/agent/proxycfg/testing_mesh_gateway.go b/agent/proxycfg/testing_mesh_gateway.go index 865e219cd435..80d37220ccd8 100644 --- a/agent/proxycfg/testing_mesh_gateway.go +++ b/agent/proxycfg/testing_mesh_gateway.go @@ -264,6 +264,25 @@ func TestConfigSnapshotMeshGateway(t testing.T, variant string, nsFn func(ns *st }, }, }) + case "limits-added": + extraUpdates = append(extraUpdates, UpdateEvent{ + CorrelationID: serviceDefaultsWatchID, + Result: &structs.ConfigEntryResponse{ + Entry: &structs.ServiceConfigEntry{ + Kind: structs.ServiceDefaults, + Name: "mesh-gateway", + UpstreamConfig: &structs.UpstreamConfiguration{ + Defaults: &structs.UpstreamConfig{ + Limits: &structs.UpstreamLimits{ + MaxConnections: pointerTo(1), + MaxPendingRequests: pointerTo(10), + MaxConcurrentRequests: pointerTo(100), + }, + }, + }, + }, + }, + }) default: t.Fatalf("unknown variant: %s", variant) return nil @@ -649,6 +668,7 @@ func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func( ) case "default-services-http": proxyDefaults := &structs.ProxyConfigEntry{ + Protocol: "http", Config: map[string]interface{}{ "protocol": "http", }, @@ -817,8 +837,9 @@ func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func( case "chain-and-l7-stuff": entries = []structs.ConfigEntry{ &structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, + Kind: structs.ProxyDefaults, + Name: structs.ProxyConfigGlobal, + Protocol: "http", Config: map[string]interface{}{ "protocol": "http", }, @@ -1122,3 +1143,7 @@ func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func( }, }, nsFn, nil, testSpliceEvents(baseEvents, extraUpdates)) } + +func pointerTo[T any](v T) *T { + return &v +} diff --git a/agent/proxycfg/testing_peering.go b/agent/proxycfg/testing_peering.go index 0af8bafa9f08..ee5e7eaceba4 100644 --- a/agent/proxycfg/testing_peering.go +++ b/agent/proxycfg/testing_peering.go @@ -15,18 +15,18 @@ import ( ) func TestConfigSnapshotPeering(t testing.T) *ConfigSnapshot { - return testConfigSnapshot(t, false, false) + return testConfigSnapshot(t, false, false, nil) } func TestConfigSnapshotPeeringWithEscapeOverrides(t testing.T) *ConfigSnapshot { - return testConfigSnapshot(t, true, false) + return testConfigSnapshot(t, true, false, nil) } -func TestConfigSnapshotPeeringWithHTTP2(t testing.T) *ConfigSnapshot { - return testConfigSnapshot(t, false, true) +func TestConfigSnapshotPeeringWithHTTP2(t testing.T, nsFn func(ns *structs.NodeService)) *ConfigSnapshot { + return testConfigSnapshot(t, false, true, nsFn) } -func testConfigSnapshot(t testing.T, escapeOverride bool, useHTTP2 bool) *ConfigSnapshot { +func testConfigSnapshot(t testing.T, escapeOverride bool, useHTTP2 bool, nsFn func(ns *structs.NodeService)) *ConfigSnapshot { var ( paymentsUpstream = structs.Upstream{ DestinationName: "payments", @@ -72,7 +72,9 @@ func testConfigSnapshot(t testing.T, escapeOverride bool, useHTTP2 bool) *Config Name: uid.EnvoyID() + ":custom-upstream", }) } - + if nsFn != nil { + nsFn(ns) + } }, []UpdateEvent{ { CorrelationID: peerTrustBundleIDPrefix + "cloud", diff --git a/agent/proxycfg/testing_terminating_gateway.go b/agent/proxycfg/testing_terminating_gateway.go index 6a718779943f..8fb02ffe67c2 100644 --- a/agent/proxycfg/testing_terminating_gateway.go +++ b/agent/proxycfg/testing_terminating_gateway.go @@ -160,20 +160,24 @@ func TestConfigSnapshotTerminatingGateway(t testing.T, populateServices bool, ns tgtwyServices = append(tgtwyServices, &structs.GatewayService{ - Service: web, - CAFile: "ca.cert.pem", + Service: web, + CAFile: "ca.cert.pem", + AutoHostRewrite: true, }, &structs.GatewayService{ - Service: api, - CAFile: "ca.cert.pem", - CertFile: "api.cert.pem", - KeyFile: "api.key.pem", + Service: api, + CAFile: "ca.cert.pem", + CertFile: "api.cert.pem", + KeyFile: "api.key.pem", + AutoHostRewrite: true, }, &structs.GatewayService{ - Service: db, + Service: db, + AutoHostRewrite: true, }, &structs.GatewayService{ - Service: cache, + Service: cache, + AutoHostRewrite: true, }, ) @@ -359,26 +363,31 @@ func TestConfigSnapshotTerminatingGatewayDestinations(t testing.T, populateDesti if populateDestinations { tgtwyServices = append(tgtwyServices, &structs.GatewayService{ - Service: externalIPTCP, - ServiceKind: structs.GatewayServiceKindDestination, + Service: externalIPTCP, + ServiceKind: structs.GatewayServiceKindDestination, + AutoHostRewrite: true, }, &structs.GatewayService{ - Service: externalHostnameTCP, - ServiceKind: structs.GatewayServiceKindDestination, + Service: externalHostnameTCP, + ServiceKind: structs.GatewayServiceKindDestination, + AutoHostRewrite: true, }, &structs.GatewayService{ - Service: externalIPHTTP, - ServiceKind: structs.GatewayServiceKindDestination, + Service: externalIPHTTP, + ServiceKind: structs.GatewayServiceKindDestination, + AutoHostRewrite: true, }, &structs.GatewayService{ - Service: externalHostnameHTTP, - ServiceKind: structs.GatewayServiceKindDestination, + Service: externalHostnameHTTP, + ServiceKind: structs.GatewayServiceKindDestination, + AutoHostRewrite: true, }, &structs.GatewayService{ - Service: externalHostnameWithSNI, - ServiceKind: structs.GatewayServiceKindDestination, - CAFile: "cert.pem", - SNI: "api.test.com", + Service: externalHostnameWithSNI, + ServiceKind: structs.GatewayServiceKindDestination, + CAFile: "cert.pem", + SNI: "api.test.com", + AutoHostRewrite: true, }, ) @@ -530,12 +539,12 @@ func TestConfigSnapshotTerminatingGatewayDestinations(t testing.T, populateDesti } func TestConfigSnapshotTerminatingGatewayServiceSubsets(t testing.T) *ConfigSnapshot { - return testConfigSnapshotTerminatingGatewayServiceSubsets(t, false) + return testConfigSnapshotTerminatingGatewayServiceSubsets(t, false, nil) } -func TestConfigSnapshotTerminatingGatewayServiceSubsetsWebAndCache(t testing.T) *ConfigSnapshot { - return testConfigSnapshotTerminatingGatewayServiceSubsets(t, true) +func TestConfigSnapshotTerminatingGatewayServiceSubsetsWebAndCache(t testing.T, nsFn func(ns *structs.NodeService)) *ConfigSnapshot { + return testConfigSnapshotTerminatingGatewayServiceSubsets(t, true, nsFn) } -func testConfigSnapshotTerminatingGatewayServiceSubsets(t testing.T, alsoAdjustCache bool) *ConfigSnapshot { +func testConfigSnapshotTerminatingGatewayServiceSubsets(t testing.T, alsoAdjustCache bool, nsFn func(ns *structs.NodeService)) *ConfigSnapshot { var ( web = structs.NewServiceName("web", nil) cache = structs.NewServiceName("cache", nil) @@ -593,7 +602,7 @@ func testConfigSnapshotTerminatingGatewayServiceSubsets(t testing.T, alsoAdjustC }) } - return TestConfigSnapshotTerminatingGateway(t, true, nil, events) + return TestConfigSnapshotTerminatingGateway(t, true, nsFn, events) } func TestConfigSnapshotTerminatingGatewayDefaultServiceSubset(t testing.T) *ConfigSnapshot { @@ -713,16 +722,18 @@ func TestConfigSnapshotTerminatingGatewaySNI(t testing.T) *ConfigSnapshot { Result: &structs.IndexedGatewayServices{ Services: []*structs.GatewayService{ { - Service: structs.NewServiceName("web", nil), - CAFile: "ca.cert.pem", - SNI: "foo.com", + Service: structs.NewServiceName("web", nil), + CAFile: "ca.cert.pem", + SNI: "foo.com", + AutoHostRewrite: true, }, { - Service: structs.NewServiceName("api", nil), - CAFile: "ca.cert.pem", - CertFile: "api.cert.pem", - KeyFile: "api.key.pem", - SNI: "bar.com", + Service: structs.NewServiceName("api", nil), + CAFile: "ca.cert.pem", + CertFile: "api.cert.pem", + KeyFile: "api.key.pem", + SNI: "bar.com", + AutoHostRewrite: true, }, }, }, @@ -739,8 +750,9 @@ func TestConfigSnapshotTerminatingGatewayHTTP2(t testing.T) *ConfigSnapshot { Result: &structs.IndexedGatewayServices{ Services: []*structs.GatewayService{ { - Service: web, - CAFile: "ca.cert.pem", + Service: web, + CAFile: "ca.cert.pem", + AutoHostRewrite: true, }, }, }, @@ -799,8 +811,9 @@ func TestConfigSnapshotTerminatingGatewaySubsetsHTTP2(t testing.T) *ConfigSnapsh Result: &structs.IndexedGatewayServices{ Services: []*structs.GatewayService{ { - Service: web, - CAFile: "ca.cert.pem", + Service: web, + CAFile: "ca.cert.pem", + AutoHostRewrite: true, }, }, }, diff --git a/agent/proxycfg/testing_tproxy.go b/agent/proxycfg/testing_tproxy.go index 9c1c0934e2b8..7cb9455177e6 100644 --- a/agent/proxycfg/testing_tproxy.go +++ b/agent/proxycfg/testing_tproxy.go @@ -128,11 +128,12 @@ func TestConfigSnapshotTransparentProxy(t testing.T) *ConfigSnapshot { }) } -func TestConfigSnapshotTransparentProxyHTTPUpstream(t testing.T, additionalEntries ...structs.ConfigEntry) *ConfigSnapshot { +func TestConfigSnapshotTransparentProxyHTTPUpstream(t testing.T, nsFn func(*structs.NodeService), additionalEntries ...structs.ConfigEntry) *ConfigSnapshot { // Set default service protocol to HTTP entries := append(additionalEntries, &structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, + Kind: structs.ProxyDefaults, + Name: structs.ProxyConfigGlobal, + Protocol: "http", Config: map[string]interface{}{ "protocol": "http", }, @@ -174,6 +175,9 @@ func TestConfigSnapshotTransparentProxyHTTPUpstream(t testing.T, additionalEntri return TestConfigSnapshot(t, func(ns *structs.NodeService) { ns.Proxy.Mode = structs.ProxyModeTransparent + if nsFn != nil { + nsFn(ns) + } }, []UpdateEvent{ { CorrelationID: meshConfigEntryID, diff --git a/agent/proxycfg/testing_upstreams.go b/agent/proxycfg/testing_upstreams.go index aa8c6c2e04d6..819d4f63d9ba 100644 --- a/agent/proxycfg/testing_upstreams.go +++ b/agent/proxycfg/testing_upstreams.go @@ -481,6 +481,7 @@ func setupTestVariationDiscoveryChain( Kind: structs.ProxyDefaults, Name: structs.ProxyConfigGlobal, EnterpriseMeta: em, + Protocol: "http", Config: map[string]interface{}{ "protocol": "http", }, @@ -534,22 +535,67 @@ func setupTestVariationDiscoveryChain( Kind: structs.ServiceResolver, Name: "db", EnterpriseMeta: entMeta, - ConnectTimeout: 33 * time.Second, - RequestTimeout: 33 * time.Second, + ConnectTimeout: 25 * time.Second, }, &structs.ProxyConfigEntry{ Kind: structs.ProxyDefaults, Name: structs.ProxyConfigGlobal, EnterpriseMeta: entMeta, + Protocol: "http", Config: map[string]interface{}{ "protocol": "http", }, }, + // Adding a ServiceRouter in this case allows testing ServiceRoute.Destination timeouts. + &structs.ServiceRouterConfigEntry{ + Kind: structs.ServiceRouter, + Name: "db", + EnterpriseMeta: entMeta, + Routes: []structs.ServiceRoute{ + { + Match: &structs.ServiceRouteMatch{ + HTTP: &structs.ServiceRouteHTTPMatch{ + PathPrefix: "/big-side", + }, + }, + Destination: &structs.ServiceRouteDestination{ + Service: "big-side", + // Test disabling idle timeout. + IdleTimeout: -1 * time.Second, + // Test a positive value for request timeout. + RequestTimeout: 10 * time.Second, + }, + }, + { + Match: &structs.ServiceRouteMatch{ + HTTP: &structs.ServiceRouteHTTPMatch{ + PathPrefix: "/lil-bit-side", + }, + }, + Destination: &structs.ServiceRouteDestination{ + Service: "lil-bit-side", + // Test zero values for these timeouts. + IdleTimeout: 0 * time.Second, + RequestTimeout: 0 * time.Second, + }, + }, + }, + }, &structs.ServiceSplitterConfigEntry{ Kind: structs.ServiceSplitter, Name: "db", EnterpriseMeta: entMeta, Splits: []structs.ServiceSplit{ + { + Weight: 1, + Service: "db", + RequestHeaders: &structs.HTTPHeaderModifiers{ + Set: map[string]string{"x-split-leg": "db"}, + }, + ResponseHeaders: &structs.HTTPHeaderModifiers{ + Set: map[string]string{"x-split-leg": "db"}, + }, + }, { Weight: 95.5, Service: "big-side", @@ -561,7 +607,7 @@ func setupTestVariationDiscoveryChain( }, }, { - Weight: 4, + Weight: 3, Service: "goldilocks-side", RequestHeaders: &structs.HTTPHeaderModifiers{ Set: map[string]string{"x-split-leg": "goldilocks"}, @@ -596,6 +642,7 @@ func setupTestVariationDiscoveryChain( Kind: structs.ProxyDefaults, Name: structs.ProxyConfigGlobal, EnterpriseMeta: entMeta, + Protocol: "http", Config: map[string]interface{}{ "protocol": "http", }, @@ -651,6 +698,7 @@ func setupTestVariationDiscoveryChain( Kind: structs.ProxyDefaults, Name: structs.ProxyConfigGlobal, EnterpriseMeta: entMeta, + Protocol: "grpc", Config: map[string]interface{}{ "protocol": "grpc", }, @@ -686,6 +734,7 @@ func setupTestVariationDiscoveryChain( Kind: structs.ProxyDefaults, Name: structs.ProxyConfigGlobal, EnterpriseMeta: entMeta, + Protocol: "http", Config: map[string]interface{}{ "protocol": "http", }, @@ -937,6 +986,7 @@ func setupTestVariationDiscoveryChain( Kind: structs.ProxyDefaults, Name: structs.ProxyConfigGlobal, EnterpriseMeta: entMeta, + Protocol: "http", Config: map[string]interface{}{ "protocol": "http", }, @@ -992,6 +1042,7 @@ func setupTestVariationDiscoveryChain( Kind: structs.ProxyDefaults, Name: structs.ProxyConfigGlobal, EnterpriseMeta: entMeta, + Protocol: "http", Config: map[string]interface{}{ "protocol": "http", }, @@ -1028,6 +1079,7 @@ func setupTestVariationDiscoveryChain( Kind: structs.ProxyDefaults, Name: structs.ProxyConfigGlobal, EnterpriseMeta: entMeta, + Protocol: "http", Config: map[string]interface{}{ "protocol": "http", }, diff --git a/agent/proxycfg/upstreams.go b/agent/proxycfg/upstreams.go index fe2d502339c4..209a3446d981 100644 --- a/agent/proxycfg/upstreams.go +++ b/agent/proxycfg/upstreams.go @@ -354,6 +354,14 @@ func (s *handlerUpstreams) resetWatchesFromChain( Partition: s.proxyID.PartitionOrDefault(), Datacenter: s.source.Datacenter, } + default: + // if target.MeshGateway.Mode is not set and target is not peered we don't want to set up watches for the gateway. + // This is important specifically in wan-fed without mesh gateway use case, as for this case + //the source and target DC could be different but there is not mesh-gateway so no need to watch + // a costly watch (Internal.ServiceDump) + if target.Peer == "" { + continue + } } if s.source.Datacenter != target.Datacenter || s.proxyID.PartitionOrDefault() != target.Partition { needGateways[gk.String()] = struct{}{} @@ -393,6 +401,7 @@ func (s *handlerUpstreams) resetWatchesFromChain( if _, ok := snap.WatchedGateways[uid][key]; ok { continue } + gwKey := gatewayKeyFromString(key) s.logger.Trace("initializing watch of mesh gateway", @@ -411,13 +420,14 @@ func (s *handlerUpstreams) resetWatchesFromChain( key: gwKey, upstreamID: uid, } + err := watchMeshGateway(ctx, opts) if err != nil { cancel() return err } - snap.WatchedGateways[uid][key] = cancel + } for key, cancelFn := range snap.WatchedGateways[uid] { diff --git a/agent/proxycfg_test.go b/agent/proxycfg_test.go index c8141e407faf..d692c2578965 100644 --- a/agent/proxycfg_test.go +++ b/agent/proxycfg_test.go @@ -4,6 +4,7 @@ package agent import ( + "context" "encoding/json" "net/http" "net/http/httptest" @@ -13,11 +14,9 @@ import ( "github.com/stretchr/testify/require" "github.com/hashicorp/consul/agent/grpc-external/limiter" + "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" "github.com/hashicorp/consul/testrpc" ) @@ -64,9 +63,9 @@ func TestAgent_local_proxycfg(t *testing.T) { var ( firstTime = true - ch <-chan proxysnapshot.ProxySnapshot + ch <-chan *proxycfg.ConfigSnapshot stc limiter.SessionTerminatedChan - cancel proxysnapshot.CancelFunc + cancel context.CancelFunc ) defer func() { if cancel != nil { @@ -87,7 +86,7 @@ func TestAgent_local_proxycfg(t *testing.T) { // Prior to fixes in https://github.com/hashicorp/consul/pull/16497 // this call to Watch() would deadlock. var err error - ch, stc, cancel, err = cfg.Watch(rtest.Resource(pbmesh.ProxyConfigurationType, sid.ID).ID(), a.config.NodeName, token) + ch, stc, _, cancel, err = cfg.Watch(sid, a.config.NodeName, token) require.NoError(t, err) } select { diff --git a/agent/remote_exec_test.go b/agent/remote_exec_test.go index f077de895a39..2488f6b4f2e0 100644 --- a/agent/remote_exec_test.go +++ b/agent/remote_exec_test.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/testrpc" "github.com/hashicorp/go-uuid" @@ -358,9 +359,9 @@ func testHandleRemoteExec(t *testing.T, command string, expectedSubstring string retry.Run(t, func(r *retry.R) { event := &remoteExecEvent{ Prefix: "_rexec", - Session: makeRexecSession(t, a.Agent, ""), + Session: makeRexecSession(r, a.Agent, ""), } - defer destroySession(t, a.Agent, event.Session, "") + defer destroySession(r, a.Agent, event.Session, "") spec := &remoteExecSpec{ Command: command, @@ -429,7 +430,7 @@ func TestHandleRemoteExecFailed(t *testing.T) { testHandleRemoteExec(t, "echo failing;exit 2", "failing", "2") } -func makeRexecSession(t *testing.T, a *Agent, token string) string { +func makeRexecSession(t testutil.TestingTB, a *Agent, token string) string { args := structs.SessionRequest{ Datacenter: a.config.Datacenter, Op: structs.SessionCreate, @@ -448,7 +449,7 @@ func makeRexecSession(t *testing.T, a *Agent, token string) string { return out } -func destroySession(t *testing.T, a *Agent, session string, token string) { +func destroySession(t testutil.TestingTB, a *Agent, session string, token string) { args := structs.SessionRequest{ Datacenter: a.config.Datacenter, Op: structs.SessionDestroy, diff --git a/agent/router/router.go b/agent/router/router.go index c261b6ed7cd5..af6b0987cfff 100644 --- a/agent/router/router.go +++ b/agent/router/router.go @@ -14,7 +14,7 @@ import ( "github.com/hashicorp/consul/agent/metadata" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/types" ) @@ -578,7 +578,7 @@ func (r *Router) GetDatacentersByDistance() ([]string, error) { // It's OK to get a nil coordinate back, ComputeDistance // will put the RTT at positive infinity. other, _ := info.cluster.GetCachedCoordinate(parts.Name) - rtt := lib.ComputeDistance(coord, other) + rtt := librtt.ComputeDistance(coord, other) index[parts.Datacenter] = append(existing, rtt) } } diff --git a/agent/router/router_test.go b/agent/router/router_test.go index 206b0befe811..452f1c5a4993 100644 --- a/agent/router/router_test.go +++ b/agent/router/router_test.go @@ -12,15 +12,15 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/serf" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/types" - - "github.com/stretchr/testify/require" ) type mockCluster struct { @@ -109,12 +109,12 @@ func (m *mockCluster) AddLANMember(dc, name, role string, coord *coordinate.Coor // mysterious dcX with no nodes with known coordinates. func testCluster(self string) *mockCluster { c := newMockCluster(self) - c.AddMember("dc0", "node0", lib.GenerateCoordinate(10*time.Millisecond)) - c.AddMember("dc1", "node1", lib.GenerateCoordinate(3*time.Millisecond)) - c.AddMember("dc1", "node2", lib.GenerateCoordinate(2*time.Millisecond)) - c.AddMember("dc1", "node3", lib.GenerateCoordinate(5*time.Millisecond)) + c.AddMember("dc0", "node0", librtt.GenerateCoordinate(10*time.Millisecond)) + c.AddMember("dc1", "node1", librtt.GenerateCoordinate(3*time.Millisecond)) + c.AddMember("dc1", "node2", librtt.GenerateCoordinate(2*time.Millisecond)) + c.AddMember("dc1", "node3", librtt.GenerateCoordinate(5*time.Millisecond)) c.AddMember("dc1", "node4", nil) - c.AddMember("dc2", "node1", lib.GenerateCoordinate(8*time.Millisecond)) + c.AddMember("dc2", "node1", librtt.GenerateCoordinate(8*time.Millisecond)) c.AddMember("dcX", "node1", nil) return c } @@ -427,8 +427,8 @@ func TestRouter_GetDatacentersByDistance(t *testing.T) { // Now add another area with a closer route for dc1. otherID := types.AreaID("other") other := newMockCluster(self) - other.AddMember("dc0", "node0", lib.GenerateCoordinate(20*time.Millisecond)) - other.AddMember("dc1", "node1", lib.GenerateCoordinate(21*time.Millisecond)) + other.AddMember("dc0", "node0", librtt.GenerateCoordinate(20*time.Millisecond)) + other.AddMember("dc1", "node1", librtt.GenerateCoordinate(21*time.Millisecond)) if err := r.AddArea(otherID, other, &fauxConnPool{}); err != nil { t.Fatalf("err: %v", err) } @@ -468,7 +468,7 @@ func TestRouter_GetDatacenterMaps(t *testing.T) { Coordinates: structs.Coordinates{ &structs.Coordinate{ Node: "node0.dc0", - Coord: lib.GenerateCoordinate(10 * time.Millisecond), + Coord: librtt.GenerateCoordinate(10 * time.Millisecond), }, }, }) { @@ -481,15 +481,15 @@ func TestRouter_GetDatacenterMaps(t *testing.T) { Coordinates: structs.Coordinates{ &structs.Coordinate{ Node: "node1.dc1", - Coord: lib.GenerateCoordinate(3 * time.Millisecond), + Coord: librtt.GenerateCoordinate(3 * time.Millisecond), }, &structs.Coordinate{ Node: "node2.dc1", - Coord: lib.GenerateCoordinate(2 * time.Millisecond), + Coord: librtt.GenerateCoordinate(2 * time.Millisecond), }, &structs.Coordinate{ Node: "node3.dc1", - Coord: lib.GenerateCoordinate(5 * time.Millisecond), + Coord: librtt.GenerateCoordinate(5 * time.Millisecond), }, }, }) { @@ -502,7 +502,7 @@ func TestRouter_GetDatacenterMaps(t *testing.T) { Coordinates: structs.Coordinates{ &structs.Coordinate{ Node: "node1.dc2", - Coord: lib.GenerateCoordinate(8 * time.Millisecond), + Coord: librtt.GenerateCoordinate(8 * time.Millisecond), }, }, }) { @@ -518,9 +518,9 @@ func TestRouter_FindLANServer(t *testing.T) { r := testRouter(t, "dc0") lan := newMockCluster("node4.dc0") - lan.AddLANMember("dc0", "node0", "consul", lib.GenerateCoordinate(10*time.Millisecond)) - lan.AddLANMember("dc0", "node1", "", lib.GenerateCoordinate(20*time.Millisecond)) - lan.AddLANMember("dc0", "node2", "", lib.GenerateCoordinate(21*time.Millisecond)) + lan.AddLANMember("dc0", "node0", "consul", librtt.GenerateCoordinate(10*time.Millisecond)) + lan.AddLANMember("dc0", "node1", "", librtt.GenerateCoordinate(20*time.Millisecond)) + lan.AddLANMember("dc0", "node2", "", librtt.GenerateCoordinate(21*time.Millisecond)) require.NoError(t, r.AddArea(types.AreaLAN, lan, &fauxConnPool{})) diff --git a/agent/rpc/operator/service.go b/agent/rpc/operator/service.go index 697b0db25432..ec88c5aa04a9 100644 --- a/agent/rpc/operator/service.go +++ b/agent/rpc/operator/service.go @@ -94,8 +94,8 @@ func requireNotNil(v interface{}, name string) { var _ pboperator.OperatorServiceServer = (*Server)(nil) -func (s *Server) Register(grpcServer *grpc.Server) { - pboperator.RegisterOperatorServiceServer(grpcServer, s) +func (s *Server) Register(registrar grpc.ServiceRegistrar) { + pboperator.RegisterOperatorServiceServer(registrar, s) } // Backend defines the core integrations the Operator endpoint depends on. A diff --git a/agent/rpc/peering/service.go b/agent/rpc/peering/service.go index d57e0378f98c..2c6655be6682 100644 --- a/agent/rpc/peering/service.go +++ b/agent/rpc/peering/service.go @@ -121,8 +121,8 @@ func requireNotNil(v interface{}, name string) { var _ pbpeering.PeeringServiceServer = (*Server)(nil) -func (s *Server) Register(grpcServer *grpc.Server) { - pbpeering.RegisterPeeringServiceServer(grpcServer, s) +func (s *Server) Register(registrar grpc.ServiceRegistrar) { + pbpeering.RegisterPeeringServiceServer(registrar, s) } // Backend defines the core integrations the Peering endpoint depends on. A @@ -764,16 +764,15 @@ func (s *Server) PeeringList(ctx context.Context, req *pbpeering.PeeringListRequ // -- ImportedServicesCount and ExportedServicesCount // NOTE: we return a new peering with this additional data func (s *Server) reconcilePeering(peering *pbpeering.Peering) *pbpeering.Peering { + cp := copyPeering(peering) streamState, found := s.Tracker.StreamStatus(peering.ID) if !found { // TODO(peering): this may be noise on non-leaders s.Logger.Warn("did not find peer in stream tracker; cannot populate imported and"+ " exported services count or reconcile peering state", "peerID", peering.ID) - peering.StreamStatus = &pbpeering.StreamStatus{} - return peering + cp.StreamStatus = &pbpeering.StreamStatus{} + return cp } else { - cp := copyPeering(peering) - // reconcile pbpeering.PeeringState_Active if streamState.Connected { cp.State = pbpeering.PeeringState_ACTIVE @@ -1160,6 +1159,5 @@ func validatePeer(peering *pbpeering.Peering, shouldDial bool) error { func copyPeering(p *pbpeering.Peering) *pbpeering.Peering { var copyP pbpeering.Peering proto.Merge(©P, p) - return ©P } diff --git a/agent/rpc/peering/service_test.go b/agent/rpc/peering/service_test.go index b2b207515720..f385a11c28cf 100644 --- a/agent/rpc/peering/service_test.go +++ b/agent/rpc/peering/service_test.go @@ -15,11 +15,7 @@ import ( "testing" "time" - "github.com/hashicorp/consul/internal/resource" - "github.com/google/tcpproxy" - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-uuid" "github.com/stretchr/testify/require" gogrpc "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -28,6 +24,9 @@ import ( grpcstatus "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul" @@ -754,6 +753,7 @@ func TestPeeringService_Read(t *testing.T) { PeerCAPems: nil, PeerServerName: "test", PeerServerAddresses: []string{"addr1"}, + StreamStatus: &pbpeering.StreamStatus{}, } err := s.Server.FSM().State().PeeringWrite(10, &pbpeering.PeeringWriteRequest{Peering: p}) require.NoError(t, err) @@ -815,6 +815,7 @@ func TestPeeringService_Read_ACLEnforcement(t *testing.T) { PeerCAPems: nil, PeerServerName: "test", PeerServerAddresses: []string{"addr1"}, + StreamStatus: &pbpeering.StreamStatus{}, } err := s.Server.FSM().State().PeeringWrite(10, &pbpeering.PeeringWriteRequest{Peering: p}) require.NoError(t, err) @@ -879,8 +880,10 @@ func TestPeeringService_Read_Blocking(t *testing.T) { PeerCAPems: nil, PeerServerName: "test", PeerServerAddresses: []string{"addr1"}, + StreamStatus: &pbpeering.StreamStatus{}, } - err := s.Server.FSM().State().PeeringWrite(lastIdx, &pbpeering.PeeringWriteRequest{Peering: p}) + toWrite := proto.Clone(p).(*pbpeering.Peering) + err := s.Server.FSM().State().PeeringWrite(lastIdx, &pbpeering.PeeringWriteRequest{Peering: toWrite}) require.NoError(t, err) client := pbpeering.NewPeeringServiceClient(s.ClientConn(t)) @@ -891,37 +894,44 @@ func TestPeeringService_Read_Blocking(t *testing.T) { options := structs.QueryOptions{ MinQueryIndex: lastIdx, - MaxQueryTime: 1 * time.Second, + MaxQueryTime: 10 * time.Second, } ctx, err = external.ContextWithQueryOptions(ctx, options) require.NoError(t, err) // Mutate the original peering - p = proto.Clone(p).(*pbpeering.Peering) p.PeerServerAddresses = append(p.PeerServerAddresses, "addr2") // Async change to trigger update - marker := time.Now() + recvChan := make(chan *pbpeering.PeeringReadResponse) + errChan := make(chan error) + var header metadata.MD go func() { - time.Sleep(100 * time.Millisecond) - lastIdx++ - require.NoError(t, s.Server.FSM().State().PeeringWrite(lastIdx, &pbpeering.PeeringWriteRequest{Peering: p})) + resp, err := client.PeeringRead(ctx, &pbpeering.PeeringReadRequest{Name: "foo"}, gogrpc.Header(&header)) + if err != nil { + errChan <- err + return + } + recvChan <- resp }() - var header metadata.MD - resp, err := client.PeeringRead(ctx, &pbpeering.PeeringReadRequest{Name: "foo"}, gogrpc.Header(&header)) - require.NoError(t, err) - - // The query should return after the async change, but before the timeout - require.True(t, time.Since(marker) >= 100*time.Millisecond) - require.True(t, time.Since(marker) < 1*time.Second) - - // Verify query results - meta, err := external.QueryMetaFromGRPCMeta(header) - require.NoError(t, err) - require.Equal(t, lastIdx, meta.Index) + lastIdx++ + toWrite = proto.Clone(p).(*pbpeering.Peering) + require.NoError(t, s.Server.FSM().State().PeeringWrite(lastIdx, &pbpeering.PeeringWriteRequest{Peering: toWrite})) - prototest.AssertDeepEqual(t, p, resp.Peering) + select { + case err := <-errChan: + require.NoError(t, err) + case resp := <-recvChan: + meta, err := external.QueryMetaFromGRPCMeta(header) + require.NoError(t, err) + require.Equal(t, lastIdx, meta.Index) + resp.Peering.CreateIndex = 0 + resp.Peering.ModifyIndex = 0 + prototest.AssertDeepEqual(t, p, resp.Peering) + case <-time.After(2 * time.Second): + t.Error("blocking query timed out while waiting") + } } func TestPeeringService_Delete(t *testing.T) { @@ -1064,6 +1074,7 @@ func TestPeeringService_List(t *testing.T) { PeerCAPems: nil, PeerServerName: "fooservername", PeerServerAddresses: []string{"addr1"}, + StreamStatus: &pbpeering.StreamStatus{}, } require.NoError(t, s.Server.FSM().State().PeeringWrite(lastIdx, &pbpeering.PeeringWriteRequest{Peering: foo})) @@ -1075,6 +1086,7 @@ func TestPeeringService_List(t *testing.T) { PeerCAPems: nil, PeerServerName: "barservername", PeerServerAddresses: []string{"addr1"}, + StreamStatus: &pbpeering.StreamStatus{}, } require.NoError(t, s.Server.FSM().State().PeeringWrite(lastIdx, &pbpeering.PeeringWriteRequest{Peering: bar})) @@ -1120,6 +1132,7 @@ func TestPeeringService_List(t *testing.T) { PeerCAPems: nil, PeerServerName: "bazservername", PeerServerAddresses: []string{"addr1"}, + StreamStatus: &pbpeering.StreamStatus{}, } go func() { time.Sleep(100 * time.Millisecond) @@ -1166,6 +1179,7 @@ func TestPeeringService_List_ACLEnforcement(t *testing.T) { PeerCAPems: nil, PeerServerName: "fooservername", PeerServerAddresses: []string{"addr1"}, + StreamStatus: &pbpeering.StreamStatus{}, } require.NoError(t, s.Server.FSM().State().PeeringWrite(10, &pbpeering.PeeringWriteRequest{Peering: foo})) bar := &pbpeering.Peering{ @@ -1175,6 +1189,7 @@ func TestPeeringService_List_ACLEnforcement(t *testing.T) { PeerCAPems: nil, PeerServerName: "barservername", PeerServerAddresses: []string{"addr1"}, + StreamStatus: &pbpeering.StreamStatus{}, } require.NoError(t, s.Server.FSM().State().PeeringWrite(15, &pbpeering.PeeringWriteRequest{Peering: bar})) @@ -1819,9 +1834,9 @@ func newTestServer(t *testing.T, cb func(conf *consul.Config)) testingServer { conf.ACLResolverSettings.EnterpriseMeta = *conf.AgentEnterpriseMeta() deps := newDefaultDeps(t, conf) - externalGRPCServer := external.NewServer(deps.Logger, nil, deps.TLSConfigurator, rate.NullRequestLimitsHandler(), keepalive.ServerParameters{}) + externalGRPCServer := external.NewServer(deps.Logger, nil, deps.TLSConfigurator, rate.NullRequestLimitsHandler(), keepalive.ServerParameters{}, nil) - server, err := consul.NewServer(conf, deps, externalGRPCServer, nil, deps.Logger, nil) + server, err := consul.NewServer(conf, deps, externalGRPCServer, nil, deps.Logger) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, server.Shutdown()) @@ -1953,7 +1968,7 @@ func newDefaultDeps(t *testing.T, c *consul.Config) consul.Deps { NewRequestRecorderFunc: middleware.NewRequestRecorder, GetNetRPCInterceptorFunc: middleware.GetNetRPCInterceptor, XDSStreamLimiter: limiter.NewSessionLimiter(), - Registry: resource.NewRegistry(), + Registry: consul.NewTypeRegistry(), } } diff --git a/agent/rpcclient/health/health.go b/agent/rpcclient/health/health.go index f062d2aac284..c20daa2e82a3 100644 --- a/agent/rpcclient/health/health.go +++ b/agent/rpcclient/health/health.go @@ -100,7 +100,17 @@ func (c *Client) Notify( } func (c *Client) useStreaming(req structs.ServiceSpecificRequest) bool { - return c.UseStreamingBackend && !req.Ingress && req.Source.Node == "" + return c.UseStreamingBackend && + !req.Ingress && + // Streaming is incompatible with NearestN queries (due to lack of ordering), + // so we can only use it if the NearestN would never work (Node == "") + // or if we explicitly say to ignore the Node field for queries (agentless xDS). + (req.Source.Node == "" || req.Source.DisableNode) && + // Streaming is incompatible with SamenessGroup queries at the moment because + // the subscribe functionality maps to queries based on the service name and tenancy information + // it does not support the ability to subscribe to the same service in different partitions or peers + // and materialize the results into a single view with the first healthy sameness group member. + req.SamenessGroup == "" } func (c *Client) newServiceRequest(req structs.ServiceSpecificRequest) serviceRequest { diff --git a/agent/rpcclient/health/health_test.go b/agent/rpcclient/health/health_test.go index 30900bc04cc0..24c1de120f2c 100644 --- a/agent/rpcclient/health/health_test.go +++ b/agent/rpcclient/health/health_test.go @@ -98,6 +98,17 @@ func TestClient_ServiceNodes_BackendRouting(t *testing.T) { }, expected: useRPC, }, + { + name: "rpc if sameness group", + req: structs.ServiceSpecificRequest{ + Datacenter: "dc1", + ServiceName: "web1", + SamenessGroup: "sg1", + MergeCentralConfig: false, + QueryOptions: structs.QueryOptions{MinQueryIndex: 22}, + }, + expected: useRPC, + }, } for _, tc := range testCases { @@ -246,6 +257,15 @@ func TestClient_Notify_BackendRouting(t *testing.T) { }, expected: useCache, }, + { + name: "use cache for sameness group request", + req: structs.ServiceSpecificRequest{ + Datacenter: "dc1", + ServiceName: "web1", + SamenessGroup: "test-group", + }, + expected: useCache, + }, } for _, tc := range testCases { diff --git a/agent/rpcclient/health/view.go b/agent/rpcclient/health/view.go index 8e08ba801e5f..2f5b43a4d0cc 100644 --- a/agent/rpcclient/health/view.go +++ b/agent/rpcclient/health/view.go @@ -46,10 +46,11 @@ func NewHealthView(req structs.ServiceSpecificRequest) (*HealthView, error) { return nil, err } return &HealthView{ - state: make(map[string]structs.CheckServiceNode), - filter: fe, - connect: req.Connect, - kind: req.ServiceKind, + state: make(map[string]structs.CheckServiceNode), + filter: fe, + connect: req.Connect, + kind: req.ServiceKind, + healthFilterType: req.HealthFilterType, }, nil } @@ -61,10 +62,11 @@ var _ submatview.View = (*HealthView)(nil) // (IndexedCheckServiceNodes) and update it in place for each event - that // involves re-sorting each time etc. though. type HealthView struct { - connect bool - kind structs.ServiceKind - state map[string]structs.CheckServiceNode - filter filterEvaluator + connect bool + kind structs.ServiceKind + state map[string]structs.CheckServiceNode + filter filterEvaluator + healthFilterType structs.HealthFilterType } // Update implements View @@ -87,6 +89,11 @@ func (s *HealthView) Update(events []*pbsubscribe.Event) error { return errors.New("check service node was unexpectedly nil") } + if csn.ExcludeBasedOnChecks(structs.CheckServiceNodeFilterOptions{FilterType: s.healthFilterType}) { + delete(s.state, id) + continue + } + // check if we intentionally need to skip the filter if s.skipFilter(csn) { s.state[id] = *csn diff --git a/agent/session_endpoint_test.go b/agent/session_endpoint_test.go index ae5a492808d7..d44285f29bb7 100644 --- a/agent/session_endpoint_test.go +++ b/agent/session_endpoint_test.go @@ -15,13 +15,14 @@ import ( "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/testrpc" "github.com/hashicorp/consul/types" "github.com/stretchr/testify/require" ) -func verifySession(t *testing.T, r *retry.R, a *TestAgent, want structs.Session) { +func verifySession(t testutil.TestingTB, a *TestAgent, want structs.Session) { t.Helper() args := &structs.SessionSpecificRequest{ @@ -30,10 +31,10 @@ func verifySession(t *testing.T, r *retry.R, a *TestAgent, want structs.Session) } var out structs.IndexedSessions if err := a.RPC(context.Background(), "Session.Get", args, &out); err != nil { - r.Fatalf("err: %v", err) + t.Fatalf("err: %v", err) } if len(out.Sessions) != 1 { - r.Fatalf("bad: %#v", out.Sessions) + t.Fatalf("bad: %#v", out.Sessions) } // Make a copy so we don't modify the state store copy for an in-mem @@ -123,7 +124,7 @@ func TestSessionCreate(t *testing.T) { LockDelay: 20 * time.Second, Behavior: structs.SessionKeysRelease, } - verifySession(t, r, a, want) + verifySession(r, a, want) }) } @@ -188,7 +189,7 @@ func TestSessionCreate_NodeChecks(t *testing.T) { LockDelay: 20 * time.Second, Behavior: structs.SessionKeysRelease, } - verifySession(t, r, a, want) + verifySession(r, a, want) }) } @@ -250,7 +251,7 @@ func TestSessionCreate_Delete(t *testing.T) { LockDelay: 20 * time.Second, Behavior: structs.SessionKeysDelete, } - verifySession(t, r, a, want) + verifySession(r, a, want) }) } @@ -288,7 +289,7 @@ func TestSessionCreate_DefaultCheck(t *testing.T) { LockDelay: 20 * time.Second, Behavior: structs.SessionKeysRelease, } - verifySession(t, r, a, want) + verifySession(r, a, want) }) } @@ -329,7 +330,7 @@ func TestSessionCreate_NoCheck(t *testing.T) { LockDelay: 20 * time.Second, Behavior: structs.SessionKeysRelease, } - verifySession(t, r, a, want) + verifySession(r, a, want) }) }) @@ -359,7 +360,7 @@ func TestSessionCreate_NoCheck(t *testing.T) { LockDelay: 20 * time.Second, Behavior: structs.SessionKeysRelease, } - verifySession(t, r, a, want) + verifySession(r, a, want) }) }) @@ -391,7 +392,7 @@ func TestSessionCreate_NoCheck(t *testing.T) { LockDelay: 20 * time.Second, Behavior: structs.SessionKeysRelease, } - verifySession(t, r, a, want) + verifySession(r, a, want) }) }) } @@ -430,7 +431,7 @@ func makeTestSessionDelete(t *testing.T, srv *HTTPHandlers) string { return sessResp.ID } -func makeTestSessionTTL(t *testing.T, srv *HTTPHandlers, ttl string) string { +func makeTestSessionTTL(t testutil.TestingTB, srv *HTTPHandlers, ttl string) string { t.Helper() // Create Session with TTL body := bytes.NewBuffer(nil) @@ -488,7 +489,7 @@ func TestSessionCustomTTL(t *testing.T) { testrpc.WaitForTestAgent(t, a.RPC, "dc1") retry.Run(t, func(r *retry.R) { - id := makeTestSessionTTL(t, a.srv, ttl.String()) + id := makeTestSessionTTL(r, a.srv, ttl.String()) req, _ := http.NewRequest("GET", "/v1/session/info/"+id, nil) resp := httptest.NewRecorder() diff --git a/agent/setup.go b/agent/setup.go index 70770cb7cdf3..ce64aa7eb2df 100644 --- a/agent/setup.go +++ b/agent/setup.go @@ -141,7 +141,7 @@ func NewBaseDeps(configLoader ConfigLoader, logOut io.Writer, providedLogger hcl // This values is set late within newNodeIDFromConfig above cfg.Cloud.NodeID = cfg.NodeID - d.HCP, err = hcp.NewDeps(cfg.Cloud, d.Logger.Named("hcp")) + d.HCP, err = hcp.NewDeps(cfg.Cloud, d.Logger.Named("hcp"), cfg.DataDir) if err != nil { return d, err } @@ -273,6 +273,9 @@ func (bd BaseDeps) Close() { bd.AutoConfig.Stop() bd.LeafCertManager.Stop() bd.MetricsConfig.Cancel() + if bd.HCP.Sink != nil { + bd.HCP.Sink.Shutdown() + } for _, fn := range []func(){bd.deregisterBalancer, bd.deregisterResolver, bd.stopHostCollector} { if fn != nil { diff --git a/agent/structs/acl.go b/agent/structs/acl.go index 4d76dffa4e8e..579e8d231e22 100644 --- a/agent/structs/acl.go +++ b/agent/structs/acl.go @@ -13,13 +13,12 @@ import ( "strings" "time" - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/lib/stringslice" - "golang.org/x/crypto/blake2b" "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/lib/stringslice" ) type ACLMode string @@ -63,10 +62,6 @@ agent_prefix "" { event_prefix "" { policy = "%[1]s" } -identity_prefix "" { - policy = "%[1]s" - intentions = "%[1]s" -} key_prefix "" { policy = "%[1]s" } @@ -1084,6 +1079,21 @@ const ( // }, // } BindingRuleBindTypeTemplatedPolicy = "templated-policy" + + // BindingRuleBindTypePolicy is the binding rule bind type that only allows + // the binding rule to function if a policy with the given name (BindName) + // exists at login-time. If it does the token that is created is directly + // linked to that policy like: + // + // &ACLToken{ + // ...other fields... + // Policies: *ACLTokenPolicyLink{ + // { Name: "" }, + // } + // } + // + // If it does not exist at login-time the rule is ignored. + BindingRuleBindTypePolicy = "policy" ) type ACLBindingRule struct { @@ -1106,6 +1116,7 @@ type ACLBindingRule struct { // - BindingRuleBindTypeService = "service" // - BindingRuleBindTypeNode = "node" // - BindingRuleBindTypeRole = "role" + // - BindingRuleBindTypePolicy = "policy" // - BindingRuleBindTypeTemplatedPolicy = "templated-policy" BindType string diff --git a/agent/structs/acl_templated_policy.go b/agent/structs/acl_templated_policy.go index d0da96e4eb4a..076d6ae256e8 100644 --- a/agent/structs/acl_templated_policy.go +++ b/agent/structs/acl_templated_policy.go @@ -9,12 +9,13 @@ import ( "fmt" "hash" "hash/fnv" - "html/template" + "text/template" - "github.com/hashicorp/go-multierror" "github.com/xeipuuv/gojsonschema" "golang.org/x/exp/slices" + "github.com/hashicorp/go-multierror" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/lib/stringslice" @@ -26,17 +27,26 @@ var ACLTemplatedPolicyNodeSchema string //go:embed acltemplatedpolicy/schemas/service.json var ACLTemplatedPolicyServiceSchema string -//go:embed acltemplatedpolicy/schemas/workload-identity.json -var ACLTemplatedPolicyWorkloadIdentitySchema string +//go:embed acltemplatedpolicy/schemas/api-gateway.json +var ACLTemplatedPolicyAPIGatewaySchema string type ACLTemplatedPolicies []*ACLTemplatedPolicy const ( - ACLTemplatedPolicyServiceID = "00000000-0000-0000-0000-000000000003" - ACLTemplatedPolicyNodeID = "00000000-0000-0000-0000-000000000004" - ACLTemplatedPolicyDNSID = "00000000-0000-0000-0000-000000000005" - ACLTemplatedPolicyNomadServerID = "00000000-0000-0000-0000-000000000006" - ACLTemplatedPolicyWorkloadIdentityID = "00000000-0000-0000-0000-000000000007" + ACLTemplatedPolicyServiceID = "00000000-0000-0000-0000-000000000003" + ACLTemplatedPolicyNodeID = "00000000-0000-0000-0000-000000000004" + ACLTemplatedPolicyDNSID = "00000000-0000-0000-0000-000000000005" + ACLTemplatedPolicyNomadServerID = "00000000-0000-0000-0000-000000000006" + _ = "00000000-0000-0000-0000-000000000007" // formerly workload identity + ACLTemplatedPolicyAPIGatewayID = "00000000-0000-0000-0000-000000000008" + ACLTemplatedPolicyNomadClientID = "00000000-0000-0000-0000-000000000009" + + ACLTemplatedPolicyServiceDescription = "Gives the token or role permissions to register a service and discover services in the Consul catalog. It also gives the specified service's sidecar proxy the permission to discover and route traffic to other services." + ACLTemplatedPolicyNodeDescription = "Gives the token or role permissions for a register an agent/node into the catalog. A node is typically a consul agent but can also be a physical server, cloud instance or a container." + ACLTemplatedPolicyDNSDescription = "Gives the token or role permissions for the Consul DNS to query services in the network." + ACLTemplatedPolicyNomadServerDescription = "Gives the token or role permissions required for integration with a nomad server." + ACLTemplatedPolicyAPIGatewayDescription = "Gives the token or role permissions for a Consul api gateway" + ACLTemplatedPolicyNomadClientDescription = "Gives the token or role permissions required for integration with a nomad client." ACLTemplatedPolicyNoRequiredVariablesSchema = "" // catch-all schema for all templated policy that don't require a schema ) @@ -48,6 +58,7 @@ type ACLTemplatedPolicyBase struct { TemplateID string Schema string Template string + Description string } var ( @@ -59,30 +70,42 @@ var ( TemplateName: api.ACLTemplatedPolicyServiceName, Schema: ACLTemplatedPolicyServiceSchema, Template: ACLTemplatedPolicyService, + Description: ACLTemplatedPolicyServiceDescription, }, api.ACLTemplatedPolicyNodeName: { TemplateID: ACLTemplatedPolicyNodeID, TemplateName: api.ACLTemplatedPolicyNodeName, Schema: ACLTemplatedPolicyNodeSchema, Template: ACLTemplatedPolicyNode, + Description: ACLTemplatedPolicyNodeDescription, }, api.ACLTemplatedPolicyDNSName: { TemplateID: ACLTemplatedPolicyDNSID, TemplateName: api.ACLTemplatedPolicyDNSName, Schema: ACLTemplatedPolicyNoRequiredVariablesSchema, Template: ACLTemplatedPolicyDNS, + Description: ACLTemplatedPolicyDNSDescription, }, api.ACLTemplatedPolicyNomadServerName: { TemplateID: ACLTemplatedPolicyNomadServerID, TemplateName: api.ACLTemplatedPolicyNomadServerName, Schema: ACLTemplatedPolicyNoRequiredVariablesSchema, Template: ACLTemplatedPolicyNomadServer, + Description: ACLTemplatedPolicyNomadServerDescription, }, - api.ACLTemplatedPolicyWorkloadIdentityName: { - TemplateID: ACLTemplatedPolicyWorkloadIdentityID, - TemplateName: api.ACLTemplatedPolicyWorkloadIdentityName, - Schema: ACLTemplatedPolicyWorkloadIdentitySchema, - Template: ACLTemplatedPolicyWorkloadIdentity, + api.ACLTemplatedPolicyAPIGatewayName: { + TemplateID: ACLTemplatedPolicyAPIGatewayID, + TemplateName: api.ACLTemplatedPolicyAPIGatewayName, + Schema: ACLTemplatedPolicyAPIGatewaySchema, + Template: ACLTemplatedPolicyAPIGateway, + Description: ACLTemplatedPolicyAPIGatewayDescription, + }, + api.ACLTemplatedPolicyNomadClientName: { + TemplateID: ACLTemplatedPolicyNomadClientID, + TemplateName: api.ACLTemplatedPolicyNomadClientName, + Schema: ACLTemplatedPolicyNoRequiredVariablesSchema, + Template: ACLTemplatedPolicyNomadClient, + Description: ACLTemplatedPolicyNomadClientDescription, }, } ) @@ -160,6 +183,17 @@ func (tp *ACLTemplatedPolicy) ValidateTemplatedPolicy(schema string) error { return fmt.Errorf("failed to load json schema for validation %w", err) } + // validate service and node identity names + if tp.TemplateVariables != nil { + if tp.TemplateName == api.ACLTemplatedPolicyServiceName && !acl.IsValidServiceIdentityName(tp.TemplateVariables.Name) { + return fmt.Errorf("service identity %q has an invalid name. Only lowercase alphanumeric characters, '-' and '_' are allowed", tp.TemplateVariables.Name) + } + + if tp.TemplateName == api.ACLTemplatedPolicyNodeName && !acl.IsValidNodeIdentityName(tp.TemplateVariables.Name) { + return fmt.Errorf("node identity %q has an invalid name. Only lowercase alphanumeric characters, '-' and '_' are allowed", tp.TemplateVariables.Name) + } + } + if res.Valid() { return nil } diff --git a/agent/structs/acl_templated_policy_ce.go b/agent/structs/acl_templated_policy_ce.go index cd9a52248a98..3cbaa22217cc 100644 --- a/agent/structs/acl_templated_policy_ce.go +++ b/agent/structs/acl_templated_policy_ce.go @@ -19,8 +19,11 @@ var ACLTemplatedPolicyDNS string //go:embed acltemplatedpolicy/policies/ce/nomad-server.hcl var ACLTemplatedPolicyNomadServer string -//go:embed acltemplatedpolicy/policies/ce/workload-identity.hcl -var ACLTemplatedPolicyWorkloadIdentity string +//go:embed acltemplatedpolicy/policies/ce/api-gateway.hcl +var ACLTemplatedPolicyAPIGateway string + +//go:embed acltemplatedpolicy/policies/ce/nomad-client.hcl +var ACLTemplatedPolicyNomadClient string func (t *ACLToken) TemplatedPolicyList() []*ACLTemplatedPolicy { if len(t.TemplatedPolicies) == 0 { diff --git a/agent/structs/acl_templated_policy_ce_test.go b/agent/structs/acl_templated_policy_ce_test.go index e160a911cb89..63f42ca83e6f 100644 --- a/agent/structs/acl_templated_policy_ce_test.go +++ b/agent/structs/acl_templated_policy_ce_test.go @@ -83,17 +83,24 @@ query_prefix "" { }`, }, }, - "workload-identity-template": { + "api-gateway-template": { templatedPolicy: &ACLTemplatedPolicy{ - TemplateID: ACLTemplatedPolicyWorkloadIdentityID, - TemplateName: api.ACLTemplatedPolicyWorkloadIdentityName, + TemplateID: ACLTemplatedPolicyAPIGatewayID, + TemplateName: api.ACLTemplatedPolicyAPIGatewayName, TemplateVariables: &ACLTemplatedPolicyVariables{ - Name: "api", + Name: "api-gateway", }, }, expectedPolicy: &ACLPolicy{ - Description: "synthetic policy generated from templated policy: builtin/workload-identity", - Rules: `identity "api" { + Description: "synthetic policy generated from templated policy: builtin/api-gateway", + Rules: `mesh = "read" +node_prefix "" { + policy = "read" +} +service_prefix "" { + policy = "read" +} +service "api-gateway" { policy = "write" }`, }, diff --git a/agent/structs/acltemplatedpolicy/policies/ce/api-gateway.hcl b/agent/structs/acltemplatedpolicy/policies/ce/api-gateway.hcl new file mode 100644 index 000000000000..7bb2e4908130 --- /dev/null +++ b/agent/structs/acltemplatedpolicy/policies/ce/api-gateway.hcl @@ -0,0 +1,10 @@ +mesh = "read" +node_prefix "" { + policy = "read" +} +service_prefix "" { + policy = "read" +} +service "{{.Name}}" { + policy = "write" +} \ No newline at end of file diff --git a/agent/structs/acltemplatedpolicy/policies/ce/nomad-client.hcl b/agent/structs/acltemplatedpolicy/policies/ce/nomad-client.hcl new file mode 100644 index 000000000000..4ea9f1e6df51 --- /dev/null +++ b/agent/structs/acltemplatedpolicy/policies/ce/nomad-client.hcl @@ -0,0 +1,12 @@ +agent_prefix "" { + policy = "read" +} +node_prefix "" { + policy = "read" +} +service_prefix "" { + policy = "write" +} +key_prefix "" { + policy = "read" +} \ No newline at end of file diff --git a/agent/structs/acltemplatedpolicy/policies/ce/workload-identity.hcl b/agent/structs/acltemplatedpolicy/policies/ce/workload-identity.hcl deleted file mode 100644 index ccd1e0564633..000000000000 --- a/agent/structs/acltemplatedpolicy/policies/ce/workload-identity.hcl +++ /dev/null @@ -1,3 +0,0 @@ -identity "{{.Name}}" { - policy = "write" -} \ No newline at end of file diff --git a/agent/structs/acltemplatedpolicy/schemas/api-gateway.json b/agent/structs/acltemplatedpolicy/schemas/api-gateway.json new file mode 100644 index 000000000000..8a3d19326821 --- /dev/null +++ b/agent/structs/acltemplatedpolicy/schemas/api-gateway.json @@ -0,0 +1,13 @@ +{ + "type": "object", + "properties": { + "name": { "type": "string", "$ref": "#/definitions/min-length-one" } + }, + "required": ["name"], + "definitions": { + "min-length-one": { + "type": "string", + "minLength": 1 + } + } +} \ No newline at end of file diff --git a/agent/structs/acltemplatedpolicy/schemas/workload-identity.json b/agent/structs/acltemplatedpolicy/schemas/workload-identity.json deleted file mode 100644 index 31064f36af7f..000000000000 --- a/agent/structs/acltemplatedpolicy/schemas/workload-identity.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "type": "object", - "properties": { - "name": { "type": "string", "$ref": "#/definitions/min-length-one" } - }, - "required": ["name"], - "definitions": { - "min-length-one": { - "type": "string", - "minLength": 1 - } - } -} \ No newline at end of file diff --git a/agent/structs/config_entry.go b/agent/structs/config_entry.go index 544820f4d607..32b4e0c89de0 100644 --- a/agent/structs/config_entry.go +++ b/agent/structs/config_entry.go @@ -12,12 +12,11 @@ import ( "time" "github.com/miekg/dns" - - "github.com/hashicorp/go-multierror" "github.com/mitchellh/hashstructure" "github.com/mitchellh/mapstructure" "github.com/hashicorp/consul-net-rpc/go-msgpack/codec" + "github.com/hashicorp/go-multierror" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/cache" @@ -27,22 +26,23 @@ import ( ) const ( - ServiceDefaults string = "service-defaults" - ProxyDefaults string = "proxy-defaults" - ServiceRouter string = "service-router" - ServiceSplitter string = "service-splitter" - ServiceResolver string = "service-resolver" - IngressGateway string = "ingress-gateway" - TerminatingGateway string = "terminating-gateway" - ServiceIntentions string = "service-intentions" - MeshConfig string = "mesh" - ExportedServices string = "exported-services" - SamenessGroup string = "sameness-group" - APIGateway string = "api-gateway" - BoundAPIGateway string = "bound-api-gateway" - InlineCertificate string = "inline-certificate" - HTTPRoute string = "http-route" - TCPRoute string = "tcp-route" + ServiceDefaults string = "service-defaults" + ProxyDefaults string = "proxy-defaults" + ServiceRouter string = "service-router" + ServiceSplitter string = "service-splitter" + ServiceResolver string = "service-resolver" + IngressGateway string = "ingress-gateway" + TerminatingGateway string = "terminating-gateway" + ServiceIntentions string = "service-intentions" + MeshConfig string = "mesh" + ExportedServices string = "exported-services" + SamenessGroup string = "sameness-group" + APIGateway string = "api-gateway" + BoundAPIGateway string = "bound-api-gateway" + FileSystemCertificate string = "file-system-certificate" + InlineCertificate string = "inline-certificate" + HTTPRoute string = "http-route" + TCPRoute string = "tcp-route" // TODO: decide if we want to highlight 'ip' keyword in the name of RateLimitIPConfig RateLimitIPConfig string = "control-plane-request-limit" JWTProvider string = "jwt-provider" @@ -71,6 +71,7 @@ var AllConfigEntryKinds = []string{ BoundAPIGateway, HTTPRoute, TCPRoute, + FileSystemCertificate, InlineCertificate, RateLimitIPConfig, JWTProvider, @@ -95,6 +96,16 @@ type ConfigEntry interface { GetMeta() map[string]string GetEnterpriseMeta() *acl.EnterpriseMeta GetRaftIndex() *RaftIndex + GetHash() uint64 + SetHash(h uint64) +} + +func HashConfigEntry(conf ConfigEntry) (uint64, error) { + hash, err := hashstructure.Hash(conf, nil) + if err != nil { + return hash, err + } + return hash, nil } // ControlledConfigEntry is an optional interface implemented by a ConfigEntry @@ -169,8 +180,17 @@ type ServiceConfigEntry struct { EnvoyExtensions EnvoyExtensions `json:",omitempty" alias:"envoy_extensions"` Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *ServiceConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *ServiceConfigEntry) GetHash() uint64 { + return e.Hash } func (e *ServiceConfigEntry) Clone() *ServiceConfigEntry { @@ -225,6 +245,11 @@ func (e *ServiceConfigEntry) Normalize() error { } } } + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h return validationErr } @@ -243,6 +268,12 @@ func (e *ServiceConfigEntry) Validate() error { validationErr = multierror.Append(validationErr, fmt.Errorf("invalid value for balance_inbound_connections: %v", e.BalanceInboundConnections)) } + switch e.Protocol { + case "", "http", "http2", "grpc", "tcp": + default: + validationErr = multierror.Append(validationErr, fmt.Errorf("invalid value for protocol: %v", e.Protocol)) + } + // External endpoints are invalid with an existing service's upstream configuration if e.UpstreamConfig != nil && e.Destination != nil { validationErr = multierror.Append(validationErr, errors.New("UpstreamConfig and Destination are mutually exclusive for service defaults")) @@ -439,6 +470,7 @@ type ProxyConfigEntry struct { Kind string Name string Config map[string]interface{} + Protocol string `json:"-"` Mode ProxyMode `json:",omitempty"` TransparentProxy TransparentProxyConfig `json:",omitempty" alias:"transparent_proxy"` MutualTLSMode MutualTLSMode `json:",omitempty" alias:"mutual_tls_mode"` @@ -450,8 +482,17 @@ type ProxyConfigEntry struct { PrioritizeByLocality *ServiceResolverPrioritizeByLocality `json:",omitempty" alias:"prioritize_by_locality"` Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *ProxyConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *ProxyConfigEntry) GetHash() uint64 { + return e.Hash } func (e *ProxyConfigEntry) GetKind() string { @@ -473,6 +514,22 @@ func (e *ProxyConfigEntry) GetMeta() map[string]string { return e.Meta } +func (e *ProxyConfigEntry) ComputeProtocol() error { + // proxyConfig is a snippet from agent/xds/config.go:ProxyConfig + // We calculate this up-front so that the expensive mapstructure decode + // is not needed during discovery chain compile time. + type proxyConfig struct { + Protocol string `mapstructure:"protocol"` + } + var cfg proxyConfig + err := mapstructure.WeakDecode(e.Config, &cfg) + if err != nil { + return err + } + e.Protocol = cfg.Protocol + return nil +} + func (e *ProxyConfigEntry) Normalize() error { if e == nil { return fmt.Errorf("config entry is nil") @@ -490,7 +547,17 @@ func (e *ProxyConfigEntry) Normalize() error { e.EnterpriseMeta.Normalize() + if err := e.ComputeProtocol(); err != nil { + return err + } + + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h return nil + } func (e *ProxyConfigEntry) Validate() error { @@ -772,6 +839,8 @@ func MakeConfigEntry(kind, name string) (ConfigEntry, error) { return &APIGatewayConfigEntry{Name: name}, nil case BoundAPIGateway: return &BoundAPIGatewayConfigEntry{Name: name}, nil + case FileSystemCertificate: + return &FileSystemCertificateConfigEntry{Name: name}, nil case InlineCertificate: return &InlineCertificateConfigEntry{Name: name}, nil case HTTPRoute: diff --git a/agent/structs/config_entry_discoverychain.go b/agent/structs/config_entry_discoverychain.go index ed81726830ed..8b43c4f9243a 100644 --- a/agent/structs/config_entry_discoverychain.go +++ b/agent/structs/config_entry_discoverychain.go @@ -79,8 +79,17 @@ type ServiceRouterConfigEntry struct { Routes []ServiceRoute Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *ServiceRouterConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *ServiceRouterConfigEntry) GetHash() uint64 { + return e.Hash } func (e *ServiceRouterConfigEntry) GetKind() string { @@ -129,6 +138,11 @@ func (e *ServiceRouterConfigEntry) Normalize() error { } } + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h return nil } @@ -358,9 +372,10 @@ func (m *ServiceRouteMatch) IsEmpty() bool { // ServiceRouteHTTPMatch is a set of http-specific match criteria. type ServiceRouteHTTPMatch struct { - PathExact string `json:",omitempty" alias:"path_exact"` - PathPrefix string `json:",omitempty" alias:"path_prefix"` - PathRegex string `json:",omitempty" alias:"path_regex"` + PathExact string `json:",omitempty" alias:"path_exact"` + PathPrefix string `json:",omitempty" alias:"path_prefix"` + PathRegex string `json:",omitempty" alias:"path_regex"` + CaseInsensitive bool `json:",omitempty" alias:"case_insensitive"` Header []ServiceRouteHTTPMatchHeader `json:",omitempty"` QueryParam []ServiceRouteHTTPMatchQueryParam `json:",omitempty" alias:"query_param"` @@ -371,6 +386,7 @@ func (m *ServiceRouteHTTPMatch) IsEmpty() bool { return m.PathExact == "" && m.PathPrefix == "" && m.PathRegex == "" && + !m.CaseInsensitive && len(m.Header) == 0 && len(m.QueryParam) == 0 && len(m.Methods) == 0 @@ -537,8 +553,17 @@ type ServiceSplitterConfigEntry struct { Splits []ServiceSplit Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *ServiceSplitterConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *ServiceSplitterConfigEntry) GetHash() uint64 { + return e.Hash } func (e *ServiceSplitterConfigEntry) GetKind() string { @@ -581,6 +606,11 @@ func (e *ServiceSplitterConfigEntry) Normalize() error { } } + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h return nil } @@ -876,8 +906,17 @@ type ServiceResolverConfigEntry struct { LoadBalancer *LoadBalancer `json:",omitempty" alias:"load_balancer"` Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *ServiceResolverConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *ServiceResolverConfigEntry) GetHash() uint64 { + return e.Hash } func (e *ServiceResolverConfigEntry) RelatedPeers() []string { @@ -998,6 +1037,11 @@ func (e *ServiceResolverConfigEntry) Normalize() error { e.EnterpriseMeta.Normalize() + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h return nil } diff --git a/agent/structs/config_entry_discoverychain_test.go b/agent/structs/config_entry_discoverychain_test.go index b2547a7ace20..2403c62c8f18 100644 --- a/agent/structs/config_entry_discoverychain_test.go +++ b/agent/structs/config_entry_discoverychain_test.go @@ -2742,6 +2742,20 @@ func TestServiceRouterConfigEntry(t *testing.T) { }), validateErr: "contains an invalid retry condition: \"invalid-retry-condition\"", }, + //////////////// + { + name: "default route with case insensitive match", + entry: makerouter(routeMatch(httpMatch(&ServiceRouteHTTPMatch{ + CaseInsensitive: true, + }))), + }, + { + name: "route with path prefix and case insensitive match /apI", + entry: makerouter(routeMatch(httpMatch(&ServiceRouteHTTPMatch{ + PathPrefix: "/apI", + CaseInsensitive: true, + }))), + }, } for _, tc := range cases { diff --git a/agent/structs/config_entry_exports.go b/agent/structs/config_entry_exports.go index 97e33dd6e705..cabdd6d7cb8b 100644 --- a/agent/structs/config_entry_exports.go +++ b/agent/structs/config_entry_exports.go @@ -20,8 +20,17 @@ type ExportedServicesConfigEntry struct { Services []ExportedService `json:",omitempty"` Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *ExportedServicesConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *ExportedServicesConfigEntry) GetHash() uint64 { + return e.Hash } // ExportedService manages the exporting of a service in the local partition to @@ -79,6 +88,11 @@ func (e *ExportedServicesConfigEntry) Normalize() error { for i := range e.Services { e.Services[i].Namespace = acl.NormalizeNamespace(e.Services[i].Namespace) } + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h return nil } diff --git a/agent/structs/config_entry_file_system_certificate.go b/agent/structs/config_entry_file_system_certificate.go new file mode 100644 index 000000000000..04292fefd193 --- /dev/null +++ b/agent/structs/config_entry_file_system_certificate.go @@ -0,0 +1,73 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package structs + +import ( + "github.com/hashicorp/consul/acl" +) + +// FileSystemCertificateConfigEntry manages the configuration for a certificate +// and private key located in the local file system. +type FileSystemCertificateConfigEntry struct { + // Kind of config entry. This will be set to structs.FileSystemCertificate. + Kind string + + // Name is used to match the config entry with its associated file system certificate. + Name string + + // Certificate is the optional path to a client certificate to use for TLS connections. + Certificate string + + // PrivateKey is the optional path to a private key to use for TLS connections. + PrivateKey string + + Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` + acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` + RaftIndex `hash:"ignore"` +} + +func (e *FileSystemCertificateConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *FileSystemCertificateConfigEntry) GetHash() uint64 { + return e.Hash +} + +func (e *FileSystemCertificateConfigEntry) GetKind() string { return FileSystemCertificate } +func (e *FileSystemCertificateConfigEntry) GetName() string { return e.Name } +func (e *FileSystemCertificateConfigEntry) Normalize() error { + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h + return nil +} +func (e *FileSystemCertificateConfigEntry) GetMeta() map[string]string { return e.Meta } +func (e *FileSystemCertificateConfigEntry) GetEnterpriseMeta() *acl.EnterpriseMeta { + return &e.EnterpriseMeta +} +func (e *FileSystemCertificateConfigEntry) GetRaftIndex() *RaftIndex { return &e.RaftIndex } + +func (e *FileSystemCertificateConfigEntry) Validate() error { + return validateConfigEntryMeta(e.Meta) +} + +func (e *FileSystemCertificateConfigEntry) Hosts() ([]string, error) { + return []string{}, nil +} + +func (e *FileSystemCertificateConfigEntry) CanRead(authz acl.Authorizer) error { + var authzContext acl.AuthorizerContext + e.FillAuthzContext(&authzContext) + return authz.ToAllowAuthorizer().MeshReadAllowed(&authzContext) +} + +func (e *FileSystemCertificateConfigEntry) CanWrite(authz acl.Authorizer) error { + var authzContext acl.AuthorizerContext + e.FillAuthzContext(&authzContext) + return authz.ToAllowAuthorizer().MeshWriteAllowed(&authzContext) +} diff --git a/agent/structs/config_entry_gateways.go b/agent/structs/config_entry_gateways.go index 00c2687d1ec9..c130073dbb66 100644 --- a/agent/structs/config_entry_gateways.go +++ b/agent/structs/config_entry_gateways.go @@ -4,12 +4,14 @@ package structs import ( + "encoding/json" "fmt" "regexp" "sort" "strings" "github.com/miekg/dns" + "golang.org/x/exp/slices" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/lib/stringslice" @@ -43,8 +45,17 @@ type IngressGatewayConfigEntry struct { Defaults *IngressServiceConfig `json:",omitempty"` Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *IngressGatewayConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *IngressGatewayConfigEntry) GetHash() uint64 { + return e.Hash } type IngressServiceConfig struct { @@ -194,6 +205,12 @@ func (e *IngressGatewayConfigEntry) Normalize() error { e.Listeners[i] = listener } + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h + return nil } @@ -468,8 +485,17 @@ type TerminatingGatewayConfigEntry struct { Services []LinkedService Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *TerminatingGatewayConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *TerminatingGatewayConfigEntry) GetHash() uint64 { + return e.Hash } // A LinkedService is a service represented by a terminating gateway @@ -492,6 +518,9 @@ type LinkedService struct { // SNI is the optional name to specify during the TLS handshake with a linked service SNI string `json:",omitempty"` + //DisableAutoHostRewrite disables terminating gateways auto host rewrite feature when set to true. + DisableAutoHostRewrite bool `json:",omitempty"` + acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` } @@ -527,6 +556,11 @@ func (e *TerminatingGatewayConfigEntry) Normalize() error { e.Services[i].EnterpriseMeta.Normalize() } + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h return nil } @@ -637,6 +671,7 @@ type GatewayService struct { FromWildcard bool `json:",omitempty"` ServiceKind GatewayServiceKind `json:",omitempty"` RaftIndex + AutoHostRewrite bool `json:",omitempty"` } type GatewayServices []*GatewayService @@ -684,14 +719,15 @@ func (g *GatewayService) Clone() *GatewayService { Port: g.Port, Protocol: g.Protocol, // See https://github.com/go101/go101/wiki/How-to-efficiently-clone-a-slice%3F - Hosts: append(g.Hosts[:0:0], g.Hosts...), - CAFile: g.CAFile, - CertFile: g.CertFile, - KeyFile: g.KeyFile, - SNI: g.SNI, - FromWildcard: g.FromWildcard, - RaftIndex: g.RaftIndex, - ServiceKind: g.ServiceKind, + Hosts: append(g.Hosts[:0:0], g.Hosts...), + CAFile: g.CAFile, + CertFile: g.CertFile, + KeyFile: g.KeyFile, + SNI: g.SNI, + FromWildcard: g.FromWildcard, + RaftIndex: g.RaftIndex, + ServiceKind: g.ServiceKind, + AutoHostRewrite: g.AutoHostRewrite, } } @@ -713,8 +749,17 @@ type APIGatewayConfigEntry struct { Status Status Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *APIGatewayConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *APIGatewayConfigEntry) GetHash() uint64 { + return e.Hash } func (e *APIGatewayConfigEntry) GetKind() string { return APIGateway } @@ -765,6 +810,11 @@ func (e *APIGatewayConfigEntry) Normalize() error { } } + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h return nil } @@ -820,7 +870,8 @@ func (e *APIGatewayConfigEntry) validateListeners() error { ListenerProtocolTCP: true, } allowedCertificateKinds := map[string]bool{ - InlineCertificate: true, + FileSystemCertificate: true, + InlineCertificate: true, } for _, listener := range e.Listeners { @@ -839,7 +890,7 @@ func (e *APIGatewayConfigEntry) validateListeners() error { } for _, certificate := range listener.TLS.Certificates { if !allowedCertificateKinds[certificate.Kind] { - return fmt.Errorf("unsupported certificate kind: %q, must be 'inline-certificate'", certificate.Kind) + return fmt.Errorf("unsupported certificate kind: %q, must be 'file-system-certificate' or 'inline-certificate'", certificate.Kind) } if certificate.Name == "" { return fmt.Errorf("certificate reference must have a name") @@ -928,6 +979,55 @@ func (a *APIGatewayTLSConfiguration) IsEmpty() bool { return len(a.Certificates) == 0 && len(a.MaxVersion) == 0 && len(a.MinVersion) == 0 && len(a.CipherSuites) == 0 } +func (a *APIGatewayTLSConfiguration) ToGatewayTLSConfig() GatewayTLSConfig { + return GatewayTLSConfig{ + Enabled: true, + SDS: nil, + TLSMinVersion: a.MinVersion, + TLSMaxVersion: a.MaxVersion, + CipherSuites: a.CipherSuites, + } +} + +// ServiceRouteReferences is a map with a key of ServiceName type for a routed to service from a +// bound gateway listener with a value being a slice of resource references of the routes that reference the service +type ServiceRouteReferences map[ServiceName][]ResourceReference + +func (s ServiceRouteReferences) AddService(key ServiceName, routeRef ResourceReference) { + if s[key] == nil { + s[key] = make([]ResourceReference, 0) + } + + if slices.Contains(s[key], routeRef) { + return + } + + s[key] = append(s[key], routeRef) +} + +func (s ServiceRouteReferences) RemoveRouteRef(routeRef ResourceReference) { + for key := range s { + for idx, ref := range s[key] { + if ref.IsSame(&routeRef) { + s[key] = append(s[key][0:idx], s[key][idx+1:]...) + if len(s[key]) == 0 { + delete(s, key) + } + } + } + } +} + +// this is to make the map value serializable for tests that compare the json output of the +// boundAPIGateway +func (s ServiceRouteReferences) MarshalJSON() ([]byte, error) { + m := make(map[string][]ResourceReference, len(s)) + for key, val := range s { + m[key.String()] = val + } + return json.Marshal(m) +} + // BoundAPIGatewayConfigEntry manages the configuration for a bound API // gateway with the given name. This type is never written from the client. // It is only written by the controller in order to represent an API gateway @@ -945,9 +1045,21 @@ type BoundAPIGatewayConfigEntry struct { // what certificates and routes have successfully bound to it. Listeners []BoundAPIGatewayListener + // Services are all the services that are routed to from an APIGateway + Services ServiceRouteReferences + Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *BoundAPIGatewayConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *BoundAPIGatewayConfigEntry) GetHash() uint64 { + return e.Hash } func (e *BoundAPIGatewayConfigEntry) IsSame(other *BoundAPIGatewayConfigEntry) bool { @@ -975,6 +1087,26 @@ func (e *BoundAPIGatewayConfigEntry) IsSame(other *BoundAPIGatewayConfigEntry) b } } + if len(e.Services) != len(other.Services) { + return false + } + + for key, refs := range e.Services { + if _, ok := other.Services[key]; !ok { + return false + } + + if len(refs) != len(other.Services[key]) { + return false + } + + for idx, ref := range refs { + if !ref.IsSame(&other.Services[key][idx]) { + return false + } + } + } + return true } @@ -1019,6 +1151,12 @@ func (e *BoundAPIGatewayConfigEntry) Normalize() error { e.Listeners[i] = listener } + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h + return nil } @@ -1079,6 +1217,18 @@ func (e *BoundAPIGatewayConfigEntry) GetEnterpriseMeta() *acl.EnterpriseMeta { return &e.EnterpriseMeta } +func (e *BoundAPIGatewayConfigEntry) ListRelatedServices() []ServiceID { + if len(e.Services) == 0 { + return nil + } + + ids := make([]ServiceID, 0, len(e.Services)) + for key := range e.Services { + ids = append(ids, key.ToServiceID()) + } + return ids +} + // BoundAPIGatewayListener is an API gateway listener with information // about the routes and certificates that have successfully bound to it. type BoundAPIGatewayListener struct { diff --git a/agent/structs/config_entry_gateways_test.go b/agent/structs/config_entry_gateways_test.go index f05638ec4d2e..16e8e2cbf50b 100644 --- a/agent/structs/config_entry_gateways_test.go +++ b/agent/structs/config_entry_gateways_test.go @@ -7,6 +7,8 @@ import ( "testing" "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/acl" ) func TestIngressGatewayConfigEntry(t *testing.T) { @@ -1566,3 +1568,223 @@ func TestListenerUnbindRoute(t *testing.T) { }) } } + +func Test_ServiceRouteReferences_AddService(t *testing.T) { + t.Parallel() + + key := ServiceName{Name: "service", EnterpriseMeta: acl.EnterpriseMeta{}} + testCases := map[string]struct { + routeRef ResourceReference + subject ServiceRouteReferences + expectedRefs ServiceRouteReferences + }{ + "key does not exist yet": { + routeRef: ResourceReference{ + Kind: "http-route", + Name: "http-route", + }, + subject: make(ServiceRouteReferences), + expectedRefs: ServiceRouteReferences{ + key: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route", + }, + }, + }, + }, + "key exists adding new route": { + routeRef: ResourceReference{ + Kind: "http-route", + Name: "http-route", + }, + subject: ServiceRouteReferences{ + key: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route-other", + }, + }, + }, + + expectedRefs: ServiceRouteReferences{ + key: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route-other", + }, + { + Kind: "http-route", + Name: "http-route", + }, + }, + }, + }, + "key exists adding existing route": { + routeRef: ResourceReference{ + Kind: "http-route", + Name: "http-route", + }, + subject: ServiceRouteReferences{ + key: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route", + }, + }, + }, + + expectedRefs: ServiceRouteReferences{ + key: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route", + }, + }, + }, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + tc.subject.AddService(key, tc.routeRef) + + require.Equal(t, tc.subject, tc.expectedRefs) + }) + } +} + +func Test_ServiceRouteReferences_RemoveRouteRef(t *testing.T) { + t.Parallel() + + keySvcOne := ServiceName{Name: "service-one", EnterpriseMeta: acl.EnterpriseMeta{}} + keySvcTwo := ServiceName{Name: "service-two", EnterpriseMeta: acl.EnterpriseMeta{}} + testCases := map[string]struct { + routeRef ResourceReference + subject ServiceRouteReferences + expectedRefs ServiceRouteReferences + }{ + "route ref exists for one service": { + routeRef: ResourceReference{ + Kind: "http-route", + Name: "http-route", + }, + subject: ServiceRouteReferences{ + keySvcOne: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route", + }, + { + Kind: "http-route", + Name: "http-route-other", + }, + }, + keySvcTwo: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route-other", + }, + }, + }, + expectedRefs: ServiceRouteReferences{ + keySvcOne: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route-other", + }, + }, + keySvcTwo: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route-other", + }, + }, + }, + }, + "route ref exists for multiple services": { + routeRef: ResourceReference{ + Kind: "http-route", + Name: "http-route", + }, + + subject: ServiceRouteReferences{ + keySvcOne: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route", + }, + { + Kind: "http-route", + Name: "http-route-other", + }, + }, + keySvcTwo: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route", + }, + { + Kind: "http-route", + Name: "http-route-other", + }, + }, + }, + expectedRefs: ServiceRouteReferences{ + keySvcOne: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route-other", + }, + }, + keySvcTwo: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route-other", + }, + }, + }, + }, + "route exists and is only ref for service--service is removed from refs": { + routeRef: ResourceReference{ + Kind: "http-route", + Name: "http-route", + }, + + subject: ServiceRouteReferences{ + keySvcOne: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route", + }, + }, + keySvcTwo: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route", + }, + { + Kind: "http-route", + Name: "http-route-other", + }, + }, + }, + expectedRefs: ServiceRouteReferences{ + keySvcTwo: []ResourceReference{ + { + Kind: "http-route", + Name: "http-route-other", + }, + }, + }, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + tc.subject.RemoveRouteRef(tc.routeRef) + + require.Equal(t, tc.subject, tc.expectedRefs) + }) + } +} diff --git a/agent/structs/config_entry_inline_certificate.go b/agent/structs/config_entry_inline_certificate.go index f397ee2ba16e..a13b1d720a24 100644 --- a/agent/structs/config_entry_inline_certificate.go +++ b/agent/structs/config_entry_inline_certificate.go @@ -31,13 +31,29 @@ type InlineCertificateConfigEntry struct { PrivateKey string Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` } -func (e *InlineCertificateConfigEntry) GetKind() string { return InlineCertificate } -func (e *InlineCertificateConfigEntry) GetName() string { return e.Name } -func (e *InlineCertificateConfigEntry) Normalize() error { return nil } +func (e *InlineCertificateConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *InlineCertificateConfigEntry) GetHash() uint64 { + return e.Hash +} + +func (e *InlineCertificateConfigEntry) GetKind() string { return InlineCertificate } +func (e *InlineCertificateConfigEntry) GetName() string { return e.Name } +func (e *InlineCertificateConfigEntry) Normalize() error { + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h + return nil +} func (e *InlineCertificateConfigEntry) GetMeta() map[string]string { return e.Meta } func (e *InlineCertificateConfigEntry) GetEnterpriseMeta() *acl.EnterpriseMeta { return &e.EnterpriseMeta diff --git a/agent/structs/config_entry_intentions.go b/agent/structs/config_entry_intentions.go index f32aafa9a87d..6da3160dd610 100644 --- a/agent/structs/config_entry_intentions.go +++ b/agent/structs/config_entry_intentions.go @@ -26,7 +26,16 @@ type ServiceIntentionsConfigEntry struct { Meta map[string]string `json:",omitempty"` // formerly Intention.Meta acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` // formerly DestinationNS - RaftIndex + Hash uint64 `json:",omitempty" hash:"ignore"` + RaftIndex `hash:"ignore"` +} + +func (e *ServiceIntentionsConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *ServiceIntentionsConfigEntry) GetHash() uint64 { + return e.Hash } var _ UpdatableConfigEntry = (*ServiceIntentionsConfigEntry)(nil) @@ -417,13 +426,15 @@ func (p *IntentionHTTPPermission) Clone() *IntentionHTTPPermission { } type IntentionHTTPHeaderPermission struct { - Name string - Present bool `json:",omitempty"` - Exact string `json:",omitempty"` - Prefix string `json:",omitempty"` - Suffix string `json:",omitempty"` - Regex string `json:",omitempty"` - Invert bool `json:",omitempty"` + Name string + Present bool `json:",omitempty"` + Exact string `json:",omitempty"` + Prefix string `json:",omitempty"` + Suffix string `json:",omitempty"` + Contains string `json:",omitempty"` + Regex string `json:",omitempty"` + Invert bool `json:",omitempty"` + IgnoreCase bool `json:",omitempty" alias:"ignore_case"` } func cloneStringStringMap(m map[string]string) map[string]string { @@ -577,6 +588,11 @@ func (e *ServiceIntentionsConfigEntry) normalize(legacyWrite bool) error { return e.Sources[i].Precedence > e.Sources[j].Precedence }) + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h return nil } @@ -866,8 +882,14 @@ func (e *ServiceIntentionsConfigEntry) validate(legacyWrite bool) error { if hdr.Suffix != "" { hdrParts++ } + if hdr.Contains != "" { + hdrParts++ + } if hdrParts != 1 { - return fmt.Errorf(errorPrefix+".Header[%d] should only contain one of Present, Exact, Prefix, Suffix, or Regex", i, j, k) + return fmt.Errorf(errorPrefix+".Header[%d] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex", i, j, k) + } + if hdr.IgnoreCase && (hdr.Present || hdr.Regex != "") { + return fmt.Errorf(errorPrefix+".Header[%d] should set one of Exact, Prefix, Suffix, or Contains when using IgnoreCase", i, j, k) } permParts++ } diff --git a/agent/structs/config_entry_intentions_test.go b/agent/structs/config_entry_intentions_test.go index ea8703de05d8..9449dc9b7771 100644 --- a/agent/structs/config_entry_intentions_test.go +++ b/agent/structs/config_entry_intentions_test.go @@ -574,323 +574,164 @@ func TestServiceIntentionsConfigEntry(t *testing.T) { validateErr: `Sources[0].Permissions[0].HTTP.Header[0] missing required Name field`, }, "permission header has too many parts (1)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - Present: true, - Exact: "foo", - // Regex: "foo", - // Prefix: "foo", - // Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + Exact: "foo", + // Regex: "foo", + // Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (2)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - Present: true, - // Exact: "foo", - Regex: "foo", - // Prefix: "foo", - // Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + // Exact: "foo", + Regex: "foo", + Prefix: "foo", + // Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (3)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - Present: true, - // Exact: "foo", - // Regex: "foo", - Prefix: "foo", - // Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + // Exact: "foo", + // Regex: "foo", + Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (4)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - Present: true, - // Exact: "foo", - // Regex: "foo", - // Prefix: "foo", - Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + Exact: "foo", + // Regex: "foo", + Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (5)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - // Present: true, - Exact: "foo", - Regex: "foo", - // Prefix: "foo", - // Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + Present: true, + Exact: "foo", + Regex: "foo", + Prefix: "foo", + Suffix: "foo", + Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (6)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - // Present: true, - Exact: "foo", - // Regex: "foo", - Prefix: "foo", - // Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + Present: true, + Exact: "foo", + // Regex: "foo", + Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (7)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - // Present: true, - Exact: "foo", - // Regex: "foo", - // Prefix: "foo", - Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + Exact: "foo", + // Regex: "foo", + Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (8)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - // Present: true, - // Exact: "foo", - Regex: "foo", - Prefix: "foo", - // Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + // Exact: "foo", + Regex: "foo", + Prefix: "foo", + // Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (9)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - // Present: true, - // Exact: "foo", - Regex: "foo", - // Prefix: "foo", - Suffix: "foo", - }, - }, - }, - }, - }, - }, - }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + // Exact: "foo", + Regex: "foo", + // Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, }, "permission header has too many parts (10)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - // Present: true, - // Exact: "foo", - // Regex: "foo", - Prefix: "foo", - Suffix: "foo", - }, - }, - }, - }, - }, - }, + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + // Present: true, + // Exact: "foo", + // Regex: "foo", + Prefix: "foo", + Suffix: "foo", + // Contains: "foo", + }, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, Contains, or Regex`, + }, + "permission header invalid ignore case (1)": { + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + Present: true, + IgnoreCase: true, }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should set one of Exact, Prefix, Suffix, or Contains when using IgnoreCase`, }, - "permission header has too many parts (11)": { - entry: &ServiceIntentionsConfigEntry{ - Kind: ServiceIntentions, - Name: "test", - Sources: []*SourceIntention{ - { - Name: "foo", - Permissions: []*IntentionPermission{ - { - Action: IntentionActionAllow, - HTTP: &IntentionHTTPPermission{ - Header: []IntentionHTTPHeaderPermission{ - { - Name: "x-abc", - Present: true, - Exact: "foo", - Regex: "foo", - Prefix: "foo", - Suffix: "foo", - }, - }, - }, - }, - }, - }, + "permission header invalid ignore case (2)": { + entry: httpHeaderPermissionEntry([]IntentionHTTPHeaderPermission{ + { + Name: "x-abc", + Regex: "qux", + IgnoreCase: true, }, - }, - validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should only contain one of Present, Exact, Prefix, Suffix, or Regex`, + }), + validateErr: `Sources[0].Permissions[0].HTTP.Header[0] should set one of Exact, Prefix, Suffix, or Contains when using IgnoreCase`, }, "permission invalid method": { entry: &ServiceIntentionsConfigEntry{ @@ -1677,3 +1518,25 @@ func TestMigrateIntentions(t *testing.T) { }) } } + +// httpHeaderPermissionEntry is a helper to generate a ServiceIntentionsConfigEntry for testing +// IntentionHTTPHeaderPermission values. +func httpHeaderPermissionEntry(header []IntentionHTTPHeaderPermission) *ServiceIntentionsConfigEntry { + return &ServiceIntentionsConfigEntry{ + Kind: ServiceIntentions, + Name: "test", + Sources: []*SourceIntention{ + { + Name: "foo", + Permissions: []*IntentionPermission{ + { + Action: IntentionActionAllow, + HTTP: &IntentionHTTPPermission{ + Header: header, + }, + }, + }, + }, + }, + } +} diff --git a/agent/structs/config_entry_jwt_provider.go b/agent/structs/config_entry_jwt_provider.go index 12bc7c89d9ed..5a1944cb4660 100644 --- a/agent/structs/config_entry_jwt_provider.go +++ b/agent/structs/config_entry_jwt_provider.go @@ -68,8 +68,17 @@ type JWTProviderConfigEntry struct { CacheConfig *JWTCacheConfig `json:",omitempty" alias:"cache_config"` Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *JWTProviderConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *JWTProviderConfigEntry) GetHash() uint64 { + return e.Hash } // JWTLocation is a location where the JWT could be present in requests. @@ -546,5 +555,11 @@ func (e *JWTProviderConfigEntry) Normalize() error { e.ClockSkewSeconds = DefaultClockSkewSeconds } + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h + return nil } diff --git a/agent/structs/config_entry_mesh.go b/agent/structs/config_entry_mesh.go index a531821650d8..0fa36d0854d7 100644 --- a/agent/structs/config_entry_mesh.go +++ b/agent/structs/config_entry_mesh.go @@ -6,6 +6,7 @@ package structs import ( "encoding/json" "fmt" + "strings" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/types" @@ -20,6 +21,14 @@ type MeshConfigEntry struct { // MutualTLSMode=permissive in either service-defaults or proxy-defaults. AllowEnablingPermissiveMutualTLS bool `json:",omitempty" alias:"allow_enabling_permissive_mutual_tls"` + // ValidateClusters controls whether the clusters the route table refers to are validated. The default value is + // false. When set to false and a route refers to a cluster that does not exist, the route table loads and routing + // to a non-existent cluster results in a 404. When set to true and the route is set to a cluster that do not exist, + // the route table will not load. For more information, refer to + // [HTTP route configuration in the Envoy docs](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route.proto#envoy-v3-api-field-config-route-v3-routeconfiguration-validate-clusters) + // for more details. + ValidateClusters bool `json:",omitempty" alias:"validate_clusters"` + TLS *MeshTLSConfig `json:",omitempty"` HTTP *MeshHTTPConfig `json:",omitempty"` @@ -27,8 +36,17 @@ type MeshConfigEntry struct { Peering *PeeringMeshConfig `json:",omitempty"` Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *MeshConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *MeshConfigEntry) GetHash() uint64 { + return e.Hash } // TransparentProxyMeshConfig contains cluster-wide options pertaining to @@ -55,6 +73,17 @@ type MeshDirectionalTLSConfig struct { type MeshHTTPConfig struct { SanitizeXForwardedClientCert bool `alias:"sanitize_x_forwarded_client_cert"` + // Incoming configures settings for incoming HTTP traffic to mesh proxies. + Incoming *MeshDirectionalHTTPConfig `json:",omitempty"` + // There is not currently an outgoing MeshDirectionalHTTPConfig, as + // the only required config for either direction at present is inbound + // request normalization. +} + +// MeshDirectionalHTTPConfig holds mesh configuration specific to HTTP +// requests for a given traffic direction. +type MeshDirectionalHTTPConfig struct { + RequestNormalization *RequestNormalizationMeshConfig `json:",omitempty" alias:"request_normalization"` } // PeeringMeshConfig contains cluster-wide options pertaining to peering. @@ -67,6 +96,104 @@ type PeeringMeshConfig struct { PeerThroughMeshGateways bool `alias:"peer_through_mesh_gateways"` } +// RequestNormalizationMeshConfig contains options pertaining to the +// normalization of HTTP requests processed by mesh proxies. +type RequestNormalizationMeshConfig struct { + // InsecureDisablePathNormalization sets the value of the \`normalize_path\` option in the Envoy listener's + // `HttpConnectionManager`. The default value is \`false\`. When set to \`true\` in Consul, \`normalize_path\` is + // set to \`false\` for the Envoy proxy. This parameter disables the normalization of request URL paths according to + // RFC 3986, conversion of \`\\\` to \`/\`, and decoding non-reserved %-encoded characters. When using L7 intentions + // with path match rules, we recommend enabling path normalization in order to avoid match rule circumvention with + // non-normalized path values. + InsecureDisablePathNormalization bool `alias:"insecure_disable_path_normalization"` + // MergeSlashes sets the value of the \`merge_slashes\` option in the Envoy listener's \`HttpConnectionManager\`. + // The default value is \`false\`. This option controls the normalization of request URL paths by merging + // consecutive \`/\` characters. This normalization is not part of RFC 3986. When using L7 intentions with path + // match rules, we recommend enabling this setting to avoid match rule circumvention through non-normalized path + // values, unless legitimate service traffic depends on allowing for repeat \`/\` characters, or upstream services + // are configured to differentiate between single and multiple slashes. + MergeSlashes bool `alias:"merge_slashes"` + // PathWithEscapedSlashesAction sets the value of the \`path_with_escaped_slashes_action\` option in the Envoy + // listener's \`HttpConnectionManager\`. The default value of this option is empty, which is equivalent to + // \`IMPLEMENTATION_SPECIFIC_DEFAULT\`. This parameter controls the action taken in response to request URL paths + // with escaped slashes in the path. When using L7 intentions with path match rules, we recommend enabling this + // setting to avoid match rule circumvention through non-normalized path values, unless legitimate service traffic + // depends on allowing for escaped \`/\` or \`\\\` characters, or upstream services are configured to differentiate + // between escaped and unescaped slashes. Refer to the Envoy documentation for more information on available + // options. + PathWithEscapedSlashesAction PathWithEscapedSlashesAction `alias:"path_with_escaped_slashes_action"` + // HeadersWithUnderscoresAction sets the value of the \`headers_with_underscores_action\` option in the Envoy + // listener's \`HttpConnectionManager\` under \`common_http_protocol_options\`. The default value of this option is + // empty, which is equivalent to \`ALLOW\`. Refer to the Envoy documentation for more information on available + // options. + HeadersWithUnderscoresAction HeadersWithUnderscoresAction `alias:"headers_with_underscores_action"` +} + +// PathWithEscapedSlashesAction is an enum that defines the action to take when +// a request path contains escaped slashes. It mirrors exactly the set of options +// in Envoy's UriPathNormalizationOptions.PathWithEscapedSlashesAction enum. +type PathWithEscapedSlashesAction string + +// See github.com/envoyproxy/go-control-plane envoy_http_v3.HttpConnectionManager_PathWithEscapedSlashesAction. +const ( + PathWithEscapedSlashesActionDefault PathWithEscapedSlashesAction = "IMPLEMENTATION_SPECIFIC_DEFAULT" + PathWithEscapedSlashesActionKeep PathWithEscapedSlashesAction = "KEEP_UNCHANGED" + PathWithEscapedSlashesActionReject PathWithEscapedSlashesAction = "REJECT_REQUEST" + PathWithEscapedSlashesActionUnescapeAndRedirect PathWithEscapedSlashesAction = "UNESCAPE_AND_REDIRECT" + PathWithEscapedSlashesActionUnescapeAndForward PathWithEscapedSlashesAction = "UNESCAPE_AND_FORWARD" +) + +// PathWithEscapedSlashesActionStrings returns an ordered slice of all PathWithEscapedSlashesAction values as strings. +func PathWithEscapedSlashesActionStrings() []string { + return []string{ + string(PathWithEscapedSlashesActionDefault), + string(PathWithEscapedSlashesActionKeep), + string(PathWithEscapedSlashesActionReject), + string(PathWithEscapedSlashesActionUnescapeAndRedirect), + string(PathWithEscapedSlashesActionUnescapeAndForward), + } +} + +// pathWithEscapedSlashesActions contains the canonical set of PathWithEscapedSlashesActionValues values. +var pathWithEscapedSlashesActions = (func() map[PathWithEscapedSlashesAction]struct{} { + m := make(map[PathWithEscapedSlashesAction]struct{}) + for _, v := range PathWithEscapedSlashesActionStrings() { + m[PathWithEscapedSlashesAction(v)] = struct{}{} + } + return m +})() + +// HeadersWithUnderscoresAction is an enum that defines the action to take when +// a request contains headers with underscores. It mirrors exactly the set of +// options in Envoy's HttpProtocolOptions.HeadersWithUnderscoresAction enum. +type HeadersWithUnderscoresAction string + +// See github.com/envoyproxy/go-control-plane envoy_core_v3.HttpProtocolOptions_HeadersWithUnderscoresAction. +const ( + HeadersWithUnderscoresActionAllow HeadersWithUnderscoresAction = "ALLOW" + HeadersWithUnderscoresActionRejectRequest HeadersWithUnderscoresAction = "REJECT_REQUEST" + HeadersWithUnderscoresActionDropHeader HeadersWithUnderscoresAction = "DROP_HEADER" +) + +// HeadersWithUnderscoresActionStrings returns an ordered slice of all HeadersWithUnderscoresAction values as strings +// for use in returning validation errors. +func HeadersWithUnderscoresActionStrings() []string { + return []string{ + string(HeadersWithUnderscoresActionAllow), + string(HeadersWithUnderscoresActionRejectRequest), + string(HeadersWithUnderscoresActionDropHeader), + } +} + +// headersWithUnderscoresActions contains the canonical set of HeadersWithUnderscoresAction values. +var headersWithUnderscoresActions = (func() map[HeadersWithUnderscoresAction]struct{} { + m := make(map[HeadersWithUnderscoresAction]struct{}) + for _, v := range HeadersWithUnderscoresActionStrings() { + m[HeadersWithUnderscoresAction(v)] = struct{}{} + } + return m +})() + func (e *MeshConfigEntry) GetKind() string { return MeshConfig } @@ -92,6 +219,13 @@ func (e *MeshConfigEntry) Normalize() error { } e.EnterpriseMeta.Normalize() + + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h + return nil } @@ -117,6 +251,10 @@ func (e *MeshConfigEntry) Validate() error { } } + if err := validateRequestNormalizationMeshConfig(e.GetHTTPIncomingRequestNormalization()); err != nil { + return fmt.Errorf("error in HTTP incoming request normalization configuration: %v", err) + } + return e.validateEnterpriseMeta() } @@ -169,6 +307,61 @@ func (e *MeshConfigEntry) PeerThroughMeshGateways() bool { return e.Peering.PeerThroughMeshGateways } +func (e *MeshConfigEntry) GetHTTP() *MeshHTTPConfig { + if e == nil { + return nil + } + return e.HTTP +} + +func (e *MeshHTTPConfig) GetIncoming() *MeshDirectionalHTTPConfig { + if e == nil { + return nil + } + return e.Incoming +} + +func (e *MeshDirectionalHTTPConfig) GetRequestNormalization() *RequestNormalizationMeshConfig { + if e == nil { + return nil + } + return e.RequestNormalization +} + +// GetHTTPIncomingRequestNormalization is a convenience accessor for mesh.http.incoming.request_normalization +// since no other fields currently exist under mesh.http.incoming. +func (e *MeshConfigEntry) GetHTTPIncomingRequestNormalization() *RequestNormalizationMeshConfig { + return e.GetHTTP().GetIncoming().GetRequestNormalization() +} + +func (r *RequestNormalizationMeshConfig) GetInsecureDisablePathNormalization() bool { + if r == nil { + return false + } + return r.InsecureDisablePathNormalization +} + +func (r *RequestNormalizationMeshConfig) GetMergeSlashes() bool { + if r == nil { + return false + } + return r.MergeSlashes +} + +func (r *RequestNormalizationMeshConfig) GetPathWithEscapedSlashesAction() PathWithEscapedSlashesAction { + if r == nil || r.PathWithEscapedSlashesAction == "" { + return PathWithEscapedSlashesActionDefault + } + return r.PathWithEscapedSlashesAction +} + +func (r *RequestNormalizationMeshConfig) GetHeadersWithUnderscoresAction() HeadersWithUnderscoresAction { + if r == nil || r.HeadersWithUnderscoresAction == "" { + return HeadersWithUnderscoresActionAllow + } + return r.HeadersWithUnderscoresAction +} + func validateMeshDirectionalTLSConfig(cfg *MeshDirectionalTLSConfig) error { if cfg == nil { return nil @@ -213,3 +406,36 @@ func validateTLSConfig( return nil } + +func validateRequestNormalizationMeshConfig(cfg *RequestNormalizationMeshConfig) error { + if cfg == nil { + return nil + } + if err := validatePathWithEscapedSlashesAction(cfg.PathWithEscapedSlashesAction); err != nil { + return err + } + if err := validateHeadersWithUnderscoresAction(cfg.HeadersWithUnderscoresAction); err != nil { + return err + } + return nil +} + +func validatePathWithEscapedSlashesAction(v PathWithEscapedSlashesAction) error { + if v == "" { + return nil + } + if _, ok := pathWithEscapedSlashesActions[v]; !ok { + return fmt.Errorf("no matching PathWithEscapedSlashesAction value found for %s, please specify one of [%s]", string(v), strings.Join(PathWithEscapedSlashesActionStrings(), ", ")) + } + return nil +} + +func validateHeadersWithUnderscoresAction(v HeadersWithUnderscoresAction) error { + if v == "" { + return nil + } + if _, ok := headersWithUnderscoresActions[v]; !ok { + return fmt.Errorf("no matching HeadersWithUnderscoresAction value found for %s, please specify one of [%s]", string(v), strings.Join(HeadersWithUnderscoresActionStrings(), ", ")) + } + return nil +} diff --git a/agent/structs/config_entry_mesh_test.go b/agent/structs/config_entry_mesh_test.go index f6eaea9e9c54..a4afbc6c9ff5 100644 --- a/agent/structs/config_entry_mesh_test.go +++ b/agent/structs/config_entry_mesh_test.go @@ -47,3 +47,164 @@ func TestMeshConfigEntry_PeerThroughMeshGateways(t *testing.T) { }) } } + +func TestMeshConfigEntry_GetHTTPIncomingRequestNormalization(t *testing.T) { + tests := map[string]struct { + input *MeshConfigEntry + want *RequestNormalizationMeshConfig + }{ + // Ensure nil is gracefully handled at each level of config path. + "nil entry": { + input: nil, + want: nil, + }, + "nil http config": { + input: &MeshConfigEntry{ + HTTP: nil, + }, + want: nil, + }, + "nil http incoming config": { + input: &MeshConfigEntry{ + HTTP: &MeshHTTPConfig{ + Incoming: nil, + }, + }, + want: nil, + }, + "nil http incoming request normalization config": { + input: &MeshConfigEntry{ + HTTP: &MeshHTTPConfig{ + Incoming: &MeshDirectionalHTTPConfig{ + RequestNormalization: nil, + }, + }, + }, + want: nil, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tc.want, tc.input.GetHTTPIncomingRequestNormalization()) + }) + } +} + +func TestMeshConfigEntry_RequestNormalizationMeshConfig(t *testing.T) { + tests := map[string]struct { + input *RequestNormalizationMeshConfig + getFn func(*RequestNormalizationMeshConfig) any + want any + }{ + // Ensure defaults are returned when config is not set. + "nil entry gets false GetInsecureDisablePathNormalization": { + input: nil, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetInsecureDisablePathNormalization() + }, + want: false, + }, + "nil entry gets false GetMergeSlashes": { + input: nil, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetMergeSlashes() + }, + want: false, + }, + "nil entry gets default GetPathWithEscapedSlashesAction": { + input: nil, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetPathWithEscapedSlashesAction() + }, + want: PathWithEscapedSlashesAction("IMPLEMENTATION_SPECIFIC_DEFAULT"), + }, + "nil entry gets default GetHeadersWithUnderscoresAction": { + input: nil, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetHeadersWithUnderscoresAction() + }, + want: HeadersWithUnderscoresAction("ALLOW"), + }, + "empty entry gets default GetPathWithEscapedSlashesAction": { + input: &RequestNormalizationMeshConfig{}, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetPathWithEscapedSlashesAction() + }, + want: PathWithEscapedSlashesAction("IMPLEMENTATION_SPECIFIC_DEFAULT"), + }, + "empty entry gets default GetHeadersWithUnderscoresAction": { + input: &RequestNormalizationMeshConfig{}, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetHeadersWithUnderscoresAction() + }, + want: HeadersWithUnderscoresAction("ALLOW"), + }, + // Ensure values are returned when set. + "non-default entry gets expected InsecureDisablePathNormalization": { + input: &RequestNormalizationMeshConfig{InsecureDisablePathNormalization: true}, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetInsecureDisablePathNormalization() + }, + want: true, + }, + "non-default entry gets expected MergeSlashes": { + input: &RequestNormalizationMeshConfig{MergeSlashes: true}, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetMergeSlashes() + }, + want: true, + }, + "non-default entry gets expected PathWithEscapedSlashesAction": { + input: &RequestNormalizationMeshConfig{PathWithEscapedSlashesAction: "UNESCAPE_AND_FORWARD"}, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetPathWithEscapedSlashesAction() + }, + want: PathWithEscapedSlashesAction("UNESCAPE_AND_FORWARD"), + }, + "non-default entry gets expected HeadersWithUnderscoresAction": { + input: &RequestNormalizationMeshConfig{HeadersWithUnderscoresAction: "REJECT_REQUEST"}, + getFn: func(c *RequestNormalizationMeshConfig) any { + return c.GetHeadersWithUnderscoresAction() + }, + want: HeadersWithUnderscoresAction("REJECT_REQUEST"), + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tc.want, tc.getFn(tc.input)) + }) + } +} + +func TestMeshConfigEntry_validateRequestNormalizationMeshConfig(t *testing.T) { + tests := map[string]struct { + input *RequestNormalizationMeshConfig + wantErr string + }{ + "nil entry is valid": { + input: nil, + wantErr: "", + }, + "invalid PathWithEscapedSlashesAction is rejected": { + input: &RequestNormalizationMeshConfig{ + PathWithEscapedSlashesAction: PathWithEscapedSlashesAction("INVALID"), + }, + wantErr: "no matching PathWithEscapedSlashesAction value found for INVALID, please specify one of [IMPLEMENTATION_SPECIFIC_DEFAULT, KEEP_UNCHANGED, REJECT_REQUEST, UNESCAPE_AND_REDIRECT, UNESCAPE_AND_FORWARD]", + }, + "invalid HeadersWithUnderscoresAction is rejected": { + input: &RequestNormalizationMeshConfig{ + HeadersWithUnderscoresAction: HeadersWithUnderscoresAction("INVALID"), + }, + wantErr: "no matching HeadersWithUnderscoresAction value found for INVALID, please specify one of [ALLOW, REJECT_REQUEST, DROP_HEADER]", + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + if tc.wantErr == "" { + assert.NoError(t, validateRequestNormalizationMeshConfig(tc.input)) + } else { + assert.EqualError(t, validateRequestNormalizationMeshConfig(tc.input), tc.wantErr) + } + }) + } +} diff --git a/agent/structs/config_entry_routes.go b/agent/structs/config_entry_routes.go index 741404769e5d..7b5ac179aab0 100644 --- a/agent/structs/config_entry_routes.go +++ b/agent/structs/config_entry_routes.go @@ -44,8 +44,17 @@ type HTTPRouteConfigEntry struct { Meta map[string]string `json:",omitempty"` // Status is the asynchronous reconciliation status which an HTTPRoute propagates to the user. Status Status + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *HTTPRouteConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *HTTPRouteConfigEntry) GetHash() uint64 { + return e.Hash } func (e *HTTPRouteConfigEntry) GetKind() string { return HTTPRoute } @@ -102,6 +111,12 @@ func (e *HTTPRouteConfigEntry) Normalize() error { e.Rules[i] = rule } + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h + return nil } @@ -545,8 +560,17 @@ type TCPRouteConfigEntry struct { Meta map[string]string `json:",omitempty"` // Status is the asynchronous reconciliation status which a TCPRoute propagates to the user. Status Status + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (e *TCPRouteConfigEntry) SetHash(h uint64) { + e.Hash = h +} + +func (e *TCPRouteConfigEntry) GetHash() uint64 { + return e.Hash } func (e *TCPRouteConfigEntry) GetKind() string { return TCPRoute } @@ -592,6 +616,11 @@ func (e *TCPRouteConfigEntry) Normalize() error { e.Services[i] = service } + h, err := HashConfigEntry(e) + if err != nil { + return err + } + e.Hash = h return nil } diff --git a/agent/structs/config_entry_sameness_group.go b/agent/structs/config_entry_sameness_group.go index dd1b84aa85ed..8fefb193537b 100644 --- a/agent/structs/config_entry_sameness_group.go +++ b/agent/structs/config_entry_sameness_group.go @@ -16,8 +16,17 @@ type SamenessGroupConfigEntry struct { IncludeLocal bool `json:",omitempty" alias:"include_local"` Members []SamenessGroupMember Meta map[string]string `json:",omitempty"` + Hash uint64 `json:",omitempty" hash:"ignore"` acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` - RaftIndex + RaftIndex `hash:"ignore"` +} + +func (s *SamenessGroupConfigEntry) SetHash(h uint64) { + s.Hash = h +} + +func (s *SamenessGroupConfigEntry) GetHash() uint64 { + return s.Hash } func (s *SamenessGroupConfigEntry) GetKind() string { return SamenessGroup } @@ -45,6 +54,12 @@ func (s *SamenessGroupConfigEntry) Normalize() error { return fmt.Errorf("config entry is nil") } s.EnterpriseMeta.Normalize() + h, err := HashConfigEntry(s) + if err != nil { + return err + } + s.Hash = h + return nil } diff --git a/agent/structs/config_entry_test.go b/agent/structs/config_entry_test.go index 9151ef815b15..978e808be443 100644 --- a/agent/structs/config_entry_test.go +++ b/agent/structs/config_entry_test.go @@ -10,12 +10,12 @@ import ( "time" "github.com/google/go-cmp/cmp" - "github.com/hashicorp/hcl" "github.com/mitchellh/copystructure" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/hashicorp/consul-net-rpc/go-msgpack/codec" + "github.com/hashicorp/hcl" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/cache" @@ -24,6 +24,20 @@ import ( "github.com/hashicorp/consul/types" ) +func TestNormalizeGenerateHash(t *testing.T) { + for _, cType := range AllConfigEntryKinds { + //this is an enterprise only config entry + if cType == RateLimitIPConfig { + continue + } + entry, err := MakeConfigEntry(cType, "global") + require.NoError(t, err) + require.NoError(t, entry.Normalize()) + require.NotEmpty(t, entry.GetHash(), entry.GetKind()) + } + +} + func TestConfigEntries_ACLs(t *testing.T) { type testACL = configEntryTestACL type testcase = configEntryACLTestCase @@ -875,6 +889,310 @@ func TestDecodeConfigEntry(t *testing.T) { }, }, }, + { + name: "service-router: kitchen sink case insensitive", + snake: ` + kind = "service-router" + name = "main" + meta { + "foo" = "bar" + "gir" = "zim" + } + routes = [ + { + match { + http { + path_exact = "/foo" + case_insensitive = true + header = [ + { + name = "debug1" + present = true + }, + { + name = "debug2" + present = false + invert = true + }, + { + name = "debug3" + exact = "1" + }, + { + name = "debug4" + prefix = "aaa" + }, + { + name = "debug5" + suffix = "bbb" + }, + { + name = "debug6" + regex = "a.*z" + }, + ] + } + } + destination { + service = "carrot" + service_subset = "kale" + namespace = "leek" + prefix_rewrite = "/alternate" + request_timeout = "99s" + idle_timeout = "99s" + num_retries = 12345 + retry_on_connect_failure = true + retry_on_status_codes = [401, 209] + request_headers { + add { + x-foo = "bar" + } + set { + bar = "baz" + } + remove = ["qux"] + } + response_headers { + add { + x-foo = "bar" + } + set { + bar = "baz" + } + remove = ["qux"] + } + } + }, + { + match { + http { + path_prefix = "/foo" + methods = [ "GET", "DELETE" ] + query_param = [ + { + name = "hack1" + present = true + }, + { + name = "hack2" + exact = "1" + }, + { + name = "hack3" + regex = "a.*z" + }, + ] + } + } + }, + { + match { + http { + path_regex = "/foo" + } + } + }, + ] + `, + camel: ` + Kind = "service-router" + Name = "main" + Meta { + "foo" = "bar" + "gir" = "zim" + } + Routes = [ + { + Match { + HTTP { + PathExact = "/foo" + CaseInsensitive = true + Header = [ + { + Name = "debug1" + Present = true + }, + { + Name = "debug2" + Present = false + Invert = true + }, + { + Name = "debug3" + Exact = "1" + }, + { + Name = "debug4" + Prefix = "aaa" + }, + { + Name = "debug5" + Suffix = "bbb" + }, + { + Name = "debug6" + Regex = "a.*z" + }, + ] + } + } + Destination { + Service = "carrot" + ServiceSubset = "kale" + Namespace = "leek" + PrefixRewrite = "/alternate" + RequestTimeout = "99s" + IdleTimeout = "99s" + NumRetries = 12345 + RetryOnConnectFailure = true + RetryOnStatusCodes = [401, 209] + RequestHeaders { + Add { + x-foo = "bar" + } + Set { + bar = "baz" + } + Remove = ["qux"] + } + ResponseHeaders { + Add { + x-foo = "bar" + } + Set { + bar = "baz" + } + Remove = ["qux"] + } + } + }, + { + Match { + HTTP { + PathPrefix = "/foo" + Methods = [ "GET", "DELETE" ] + QueryParam = [ + { + Name = "hack1" + Present = true + }, + { + Name = "hack2" + Exact = "1" + }, + { + Name = "hack3" + Regex = "a.*z" + }, + ] + } + } + }, + { + Match { + HTTP { + PathRegex = "/foo" + } + } + }, + ] + `, + expect: &ServiceRouterConfigEntry{ + Kind: "service-router", + Name: "main", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + Routes: []ServiceRoute{ + { + Match: &ServiceRouteMatch{ + HTTP: &ServiceRouteHTTPMatch{ + PathExact: "/foo", + CaseInsensitive: true, + Header: []ServiceRouteHTTPMatchHeader{ + { + Name: "debug1", + Present: true, + }, + { + Name: "debug2", + Present: false, + Invert: true, + }, + { + Name: "debug3", + Exact: "1", + }, + { + Name: "debug4", + Prefix: "aaa", + }, + { + Name: "debug5", + Suffix: "bbb", + }, + { + Name: "debug6", + Regex: "a.*z", + }, + }, + }, + }, + Destination: &ServiceRouteDestination{ + Service: "carrot", + ServiceSubset: "kale", + Namespace: "leek", + PrefixRewrite: "/alternate", + RequestTimeout: 99 * time.Second, + IdleTimeout: 99 * time.Second, + NumRetries: 12345, + RetryOnConnectFailure: true, + RetryOnStatusCodes: []uint32{401, 209}, + RequestHeaders: &HTTPHeaderModifiers{ + Add: map[string]string{"x-foo": "bar"}, + Set: map[string]string{"bar": "baz"}, + Remove: []string{"qux"}, + }, + ResponseHeaders: &HTTPHeaderModifiers{ + Add: map[string]string{"x-foo": "bar"}, + Set: map[string]string{"bar": "baz"}, + Remove: []string{"qux"}, + }, + }, + }, + { + Match: &ServiceRouteMatch{ + HTTP: &ServiceRouteHTTPMatch{ + PathPrefix: "/foo", + Methods: []string{"GET", "DELETE"}, + QueryParam: []ServiceRouteHTTPMatchQueryParam{ + { + Name: "hack1", + Present: true, + }, + { + Name: "hack2", + Exact: "1", + }, + { + Name: "hack3", + Regex: "a.*z", + }, + }, + }, + }, + }, + { + Match: &ServiceRouteMatch{ + HTTP: &ServiceRouteHTTPMatch{ + PathRegex: "/foo", + }, + }, + }, + }, + }, + }, { name: "service-splitter: kitchen sink", snake: ` @@ -1592,6 +1910,10 @@ func TestDecodeConfigEntry(t *testing.T) { name = "hdr-suffix" suffix = "suffix" }, + { + name = "hdr-contains" + contains = "contains" + }, { name = "hdr-regex" regex = "regex" @@ -1600,7 +1922,12 @@ func TestDecodeConfigEntry(t *testing.T) { name = "hdr-absent" present = true invert = true - } + }, + { + name = "hdr-ignore-case" + exact = "exact" + ignore_case = true + }, ] } }, @@ -1669,6 +1996,10 @@ func TestDecodeConfigEntry(t *testing.T) { Name = "hdr-suffix" Suffix = "suffix" }, + { + Name = "hdr-contains" + Contains = "contains" + }, { Name = "hdr-regex" Regex = "regex" @@ -1677,6 +2008,11 @@ func TestDecodeConfigEntry(t *testing.T) { Name = "hdr-absent" Present = true Invert = true + }, + { + Name = "hdr-ignore-case" + Exact = "exact" + IgnoreCase = true } ] } @@ -1746,6 +2082,10 @@ func TestDecodeConfigEntry(t *testing.T) { Name: "hdr-suffix", Suffix: "suffix", }, + { + Name: "hdr-contains", + Contains: "contains", + }, { Name: "hdr-regex", Regex: "regex", @@ -1755,6 +2095,11 @@ func TestDecodeConfigEntry(t *testing.T) { Present: true, Invert: true, }, + { + Name: "hdr-ignore-case", + Exact: "exact", + IgnoreCase: true, + }, }, }, }, @@ -1816,7 +2161,7 @@ func TestDecodeConfigEntry(t *testing.T) { }, }, { - name: "mesh", + name: "mesh: kitchen sink", snake: ` kind = "mesh" meta { @@ -1827,6 +2172,7 @@ func TestDecodeConfigEntry(t *testing.T) { mesh_destinations_only = true } allow_enabling_permissive_mutual_tls = true + validate_clusters = true tls { incoming { tls_min_version = "TLSv1_1" @@ -1845,9 +2191,17 @@ func TestDecodeConfigEntry(t *testing.T) { ] } } - http { - sanitize_x_forwarded_client_cert = true - } + http { + sanitize_x_forwarded_client_cert = true + incoming { + request_normalization { + insecure_disable_path_normalization = true + merge_slashes = true + path_with_escaped_slashes_action = "UNESCAPE_AND_FORWARD" + headers_with_underscores_action = "DROP_HEADER" + } + } + } peering { peer_through_mesh_gateways = true } @@ -1862,6 +2216,7 @@ func TestDecodeConfigEntry(t *testing.T) { MeshDestinationsOnly = true } AllowEnablingPermissiveMutualTLS = true + ValidateClusters = true TLS { Incoming { TLSMinVersion = "TLSv1_1" @@ -1880,9 +2235,17 @@ func TestDecodeConfigEntry(t *testing.T) { ] } } - HTTP { - SanitizeXForwardedClientCert = true - } + HTTP { + SanitizeXForwardedClientCert = true + Incoming { + RequestNormalization { + InsecureDisablePathNormalization = true + MergeSlashes = true + PathWithEscapedSlashesAction = "UNESCAPE_AND_FORWARD" + HeadersWithUnderscoresAction = "DROP_HEADER" + } + } + } Peering { PeerThroughMeshGateways = true } @@ -1896,6 +2259,7 @@ func TestDecodeConfigEntry(t *testing.T) { MeshDestinationsOnly: true, }, AllowEnablingPermissiveMutualTLS: true, + ValidateClusters: true, TLS: &MeshTLSConfig{ Incoming: &MeshDirectionalTLSConfig{ TLSMinVersion: types.TLSv1_1, @@ -1916,6 +2280,14 @@ func TestDecodeConfigEntry(t *testing.T) { }, HTTP: &MeshHTTPConfig{ SanitizeXForwardedClientCert: true, + Incoming: &MeshDirectionalHTTPConfig{ + RequestNormalization: &RequestNormalizationMeshConfig{ + InsecureDisablePathNormalization: true, // note: this is the opposite of the recommended default + MergeSlashes: true, + PathWithEscapedSlashesAction: "UNESCAPE_AND_FORWARD", + HeadersWithUnderscoresAction: "DROP_HEADER", + }, + }, }, Peering: &PeeringMeshConfig{ PeerThroughMeshGateways: true, @@ -2907,6 +3279,14 @@ func TestServiceConfigEntry(t *testing.T) { }, validateErr: `Invalid MutualTLSMode "invalid-mtls-mode". Must be one of "", "strict", or "permissive".`, }, + "validate: invalid Protocol in service-defaults": { + entry: &ServiceConfigEntry{ + Kind: ServiceDefaults, + Name: "web", + Protocol: "blah", + }, + validateErr: `invalid value for protocol: blah`, + }, } testConfigEntryNormalizeAndValidate(t, cases) } @@ -3344,6 +3724,47 @@ func TestProxyConfigEntry(t *testing.T) { testConfigEntryNormalizeAndValidate(t, cases) } +func TestProxyConfigEntry_ComputeProtocol(t *testing.T) { + t.Run("ComputeProtocol sets protocol field correctly", func(t *testing.T) { + pd := &ProxyConfigEntry{ + Kind: ProxyDefaults, + Name: "global", + Config: map[string]interface{}{ + "protocol": "http", + }, + } + require.NoError(t, pd.ComputeProtocol()) + require.Equal(t, &ProxyConfigEntry{ + Kind: ProxyDefaults, + Name: "global", + Protocol: "http", + Config: map[string]interface{}{ + "protocol": "http", + }, + }, pd) + }) + t.Run("Normalize sets protocol field correctly", func(t *testing.T) { + pd := &ProxyConfigEntry{ + Kind: ProxyDefaults, + Name: "global", + Config: map[string]interface{}{ + "protocol": "http", + }, + } + require.NoError(t, pd.Normalize()) + pd.Hash = 0 + require.Equal(t, &ProxyConfigEntry{ + Kind: ProxyDefaults, + Name: "global", + Protocol: "http", + Config: map[string]interface{}{ + "protocol": "http", + }, + EnterpriseMeta: *acl.DefaultEnterpriseMeta(), + }, pd) + }) +} + func requireContainsLower(t *testing.T, haystack, needle string) { t.Helper() require.Contains(t, strings.ToLower(haystack), strings.ToLower(needle)) @@ -3407,6 +3828,7 @@ func testConfigEntryNormalizeAndValidate(t *testing.T, cases map[string]configEn } if tc.expected != nil { + tc.expected.SetHash(tc.entry.GetHash()) require.Equal(t, tc.expected, tc.entry) } @@ -3420,6 +3842,7 @@ func testConfigEntryNormalizeAndValidate(t *testing.T, cases map[string]configEn return a.IsSame(&b) }), } + beforeNormalize.(ConfigEntry).SetHash(tc.entry.GetHash()) if diff := cmp.Diff(beforeNormalize, tc.entry, opts); diff != "" { t.Fatalf("expect unchanged after Normalize, got diff:\n%s", diff) } diff --git a/agent/structs/connect_ca.go b/agent/structs/connect_ca.go index 267aeba5e63d..5fa7b0771549 100644 --- a/agent/structs/connect_ca.go +++ b/agent/structs/connect_ca.go @@ -8,12 +8,11 @@ import ( "reflect" "time" - "github.com/hashicorp/consul/lib/stringslice" - "github.com/mitchellh/mapstructure" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/lib/stringslice" ) const ( @@ -217,11 +216,6 @@ type IssuedCert struct { // PrivateKeyPEM is the PEM encoded private key associated with CertPEM. PrivateKeyPEM string `json:",omitempty"` - // WorkloadIdentity is the name of the workload identity for which the cert was issued. - WorkloadIdentity string `json:",omitempty"` - // WorkloadIdentityURI is the cert URI value. - WorkloadIdentityURI string `json:",omitempty"` - // Service is the name of the service for which the cert was issued. Service string `json:",omitempty"` // ServiceURI is the cert URI value. diff --git a/agent/structs/connect_proxy_config.go b/agent/structs/connect_proxy_config.go index d84953e1b0e7..3bd5276f8279 100644 --- a/agent/structs/connect_proxy_config.go +++ b/agent/structs/connect_proxy_config.go @@ -11,7 +11,6 @@ import ( "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/lib" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" ) const ( @@ -181,39 +180,6 @@ type AccessLogsConfig struct { TextFormat string `json:",omitempty" alias:"text_format"` } -func (c *AccessLogsConfig) GetEnabled() bool { - return c.Enabled -} - -func (c *AccessLogsConfig) GetDisableListenerLogs() bool { - return c.DisableListenerLogs -} - -func (c *AccessLogsConfig) GetType() pbmesh.LogSinkType { - switch c.Type { - case FileLogSinkType: - return pbmesh.LogSinkType_LOG_SINK_TYPE_FILE - case StdErrLogSinkType: - return pbmesh.LogSinkType_LOG_SINK_TYPE_STDERR - case StdOutLogSinkType: - return pbmesh.LogSinkType_LOG_SINK_TYPE_STDOUT - } - - return pbmesh.LogSinkType_LOG_SINK_TYPE_DEFAULT -} - -func (c *AccessLogsConfig) GetPath() string { - return c.Path -} - -func (c *AccessLogsConfig) GetJsonFormat() string { - return c.JSONFormat -} - -func (c *AccessLogsConfig) GetTextFormat() string { - return c.TextFormat -} - func (c *AccessLogsConfig) IsZero() bool { if c == nil { return true @@ -839,12 +805,3 @@ func (e *ExposeConfig) Finalize() { } } } - -type AccessLogs interface { - GetEnabled() bool - GetDisableListenerLogs() bool - GetType() pbmesh.LogSinkType - GetPath() string - GetJsonFormat() string - GetTextFormat() string -} diff --git a/agent/structs/deep-copy.sh b/agent/structs/deep-copy.sh index cbc1bdc42ae5..242d4e5ab235 100755 --- a/agent/structs/deep-copy.sh +++ b/agent/structs/deep-copy.sh @@ -24,6 +24,7 @@ deep-copy \ -type DiscoverySplit \ -type ExposeConfig \ -type ExportedServicesConfigEntry \ + -type FileSystemCertificateConfigEntry \ -type GatewayService \ -type GatewayServiceTLSConfig \ -type HTTPHeaderModifiers \ @@ -51,6 +52,7 @@ deep-copy \ -type ServiceRoute \ -type ServiceRouteDestination \ -type ServiceRouteMatch \ + -type ServiceSpecificRequest \ -type TCPRouteConfigEntry \ -type Upstream \ -type UpstreamConfiguration \ diff --git a/agent/structs/discovery_chain.go b/agent/structs/discovery_chain.go index c81dd1ec0836..4f2f7f41c46d 100644 --- a/agent/structs/discovery_chain.go +++ b/agent/structs/discovery_chain.go @@ -116,7 +116,7 @@ func (s *DiscoveryGraphNode) IsResolver() bool { } func (s *DiscoveryGraphNode) MapKey() string { - return fmt.Sprintf("%s:%s", s.Type, s.Name) + return s.Type + ":" + s.Name } // compiled form of ServiceResolverConfigEntry diff --git a/agent/structs/dns.go b/agent/structs/dns.go new file mode 100644 index 000000000000..eea42e8d37c7 --- /dev/null +++ b/agent/structs/dns.go @@ -0,0 +1,27 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package structs + +import "math/rand" + +type RecursorStrategy string + +const ( + RecursorStrategySequential RecursorStrategy = "sequential" + RecursorStrategyRandom RecursorStrategy = "random" +) + +func (s RecursorStrategy) Indexes(max int) []int { + switch s { + case RecursorStrategyRandom: + return rand.Perm(max) + default: + idxs := make([]int, max) + for i := range idxs { + idxs[i] = i + } + return idxs + + } +} diff --git a/agent/structs/dns_test.go b/agent/structs/dns_test.go new file mode 100644 index 000000000000..908473d2095c --- /dev/null +++ b/agent/structs/dns_test.go @@ -0,0 +1,44 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package structs + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/sdk/testutil/retry" +) + +func TestDNS_Recursor_StrategyRandom(t *testing.T) { + configuredRecursors := []string{"1.1.1.1", "8.8.4.4", "8.8.8.8"} + recursorStrategy := RecursorStrategy("random") + + retry.RunWith(&retry.Counter{Count: 5}, t, func(r *retry.R) { + recursorsToQuery := make([]string, 0) + for _, idx := range recursorStrategy.Indexes(len(configuredRecursors)) { + recursorsToQuery = append(recursorsToQuery, configuredRecursors[idx]) + } + + // Ensure the slices contain the same elements + require.ElementsMatch(r, configuredRecursors, recursorsToQuery) + + // Ensure the elements are not in the same order + require.NotEqual(r, configuredRecursors, recursorsToQuery) + }) +} + +func TestDNS_Recursor_StrategySequential(t *testing.T) { + expectedRecursors := []string{"1.1.1.1", "8.8.4.4", "8.8.8.8"} + recursorStrategy := RecursorStrategy("sequential") + + recursorsToQuery := make([]string, 0) + for _, idx := range recursorStrategy.Indexes(len(expectedRecursors)) { + recursorsToQuery = append(recursorsToQuery, expectedRecursors[idx]) + } + + // The list of recursors should match the order in which they were defined + // in the configuration + require.Equal(t, recursorsToQuery, expectedRecursors) +} diff --git a/agent/structs/errors.go b/agent/structs/errors.go index 31a818bd62f2..029f958ec4ab 100644 --- a/agent/structs/errors.go +++ b/agent/structs/errors.go @@ -9,38 +9,40 @@ import ( ) const ( - errNoLeader = "No cluster leader" - errNoDCPath = "No path to datacenter" - errDCNotAvailable = "Remote DC has no server currently reachable" - errNoServers = "No known Consul servers" - errNotReadyForConsistentReads = "Not ready to serve consistent reads" - errSegmentsNotSupported = "Network segments are not supported in this version of Consul" - errRPCRateExceeded = "RPC rate limit exceeded" - errServiceNotFound = "Service not found: " - errQueryNotFound = "Query not found" - errLeaderNotTracked = "Raft leader not found in server lookup mapping" - errConnectNotEnabled = "Connect must be enabled in order to use this endpoint" - errRateLimited = "Rate limit reached, try again later" // Note: we depend on this error message in the gRPC ConnectCA.Sign endpoint (see: isRateLimitError). - errNotPrimaryDatacenter = "not the primary datacenter" - errStateReadOnly = "CA Provider State is read-only" - errUsingV2CatalogExperiment = "V1 catalog is disabled when V2 is enabled" + errNoLeader = "No cluster leader" + errNoDCPath = "No path to datacenter" + errDCNotAvailable = "Remote DC has no server currently reachable" + errNoServers = "No known Consul servers" + errNotReadyForConsistentReads = "Not ready to serve consistent reads" + errSegmentsNotSupported = "Network segments are not supported in this version of Consul" + errRPCRateExceeded = "RPC rate limit exceeded" + errServiceNotFound = "Service not found: " + errQueryNotFound = "Query not found" + errLeaderNotTracked = "Raft leader not found in server lookup mapping" + errConnectNotEnabled = "Connect must be enabled in order to use this endpoint" + errRateLimited = "Rate limit reached, try again later" // Note: we depend on this error message in the gRPC ConnectCA.Sign endpoint (see: isRateLimitError). + errNotPrimaryDatacenter = "not the primary datacenter" + errStateReadOnly = "CA Provider State is read-only" + errSamenessGroupNotFound = "Sameness Group not found" + errSamenessGroupMustBeDefaultForFailover = "Sameness Group must have DefaultForFailover set to true in order to use this endpoint" ) var ( - ErrNoLeader = errors.New(errNoLeader) - ErrNoDCPath = errors.New(errNoDCPath) - ErrNoServers = errors.New(errNoServers) - ErrNotReadyForConsistentReads = errors.New(errNotReadyForConsistentReads) - ErrSegmentsNotSupported = errors.New(errSegmentsNotSupported) - ErrRPCRateExceeded = errors.New(errRPCRateExceeded) - ErrDCNotAvailable = errors.New(errDCNotAvailable) - ErrQueryNotFound = errors.New(errQueryNotFound) - ErrLeaderNotTracked = errors.New(errLeaderNotTracked) - ErrConnectNotEnabled = errors.New(errConnectNotEnabled) - ErrRateLimited = errors.New(errRateLimited) // Note: we depend on this error message in the gRPC ConnectCA.Sign endpoint (see: isRateLimitError). - ErrNotPrimaryDatacenter = errors.New(errNotPrimaryDatacenter) - ErrStateReadOnly = errors.New(errStateReadOnly) - ErrUsingV2CatalogExperiment = errors.New(errUsingV2CatalogExperiment) + ErrNoLeader = errors.New(errNoLeader) + ErrNoDCPath = errors.New(errNoDCPath) + ErrNoServers = errors.New(errNoServers) + ErrNotReadyForConsistentReads = errors.New(errNotReadyForConsistentReads) + ErrSegmentsNotSupported = errors.New(errSegmentsNotSupported) + ErrRPCRateExceeded = errors.New(errRPCRateExceeded) + ErrDCNotAvailable = errors.New(errDCNotAvailable) + ErrQueryNotFound = errors.New(errQueryNotFound) + ErrLeaderNotTracked = errors.New(errLeaderNotTracked) + ErrConnectNotEnabled = errors.New(errConnectNotEnabled) + ErrRateLimited = errors.New(errRateLimited) // Note: we depend on this error message in the gRPC ConnectCA.Sign endpoint (see: isRateLimitError). + ErrNotPrimaryDatacenter = errors.New(errNotPrimaryDatacenter) + ErrStateReadOnly = errors.New(errStateReadOnly) + ErrSamenessGroupNotFound = errors.New(errSamenessGroupNotFound) + ErrSamenessGroupMustBeDefaultForFailover = errors.New(errSamenessGroupMustBeDefaultForFailover) ) func IsErrNoDCPath(err error) bool { @@ -59,10 +61,10 @@ func IsErrRPCRateExceeded(err error) bool { return err != nil && strings.Contains(err.Error(), errRPCRateExceeded) } -func IsErrServiceNotFound(err error) bool { - return err != nil && strings.Contains(err.Error(), errServiceNotFound) +func IsErrSamenessGroupNotFound(err error) bool { + return err != nil && strings.Contains(err.Error(), errSamenessGroupNotFound) } -func IsErrUsingV2CatalogExperiment(err error) bool { - return err != nil && strings.Contains(err.Error(), errUsingV2CatalogExperiment) +func IsErrSamenessGroupMustBeDefaultForFailover(err error) bool { + return err != nil && strings.Contains(err.Error(), errSamenessGroupMustBeDefaultForFailover) } diff --git a/agent/structs/intention.go b/agent/structs/intention.go index 3bbc2584f70f..95e9d8388aae 100644 --- a/agent/structs/intention.go +++ b/agent/structs/intention.go @@ -30,6 +30,9 @@ const ( // fix up all the places where this was used with the proper namespace // value. IntentionDefaultNamespace = "default" + + IntentionDefaultPolicyAllow = "allow" + IntentionDefaultPolicyDeny = "deny" ) // Intention defines an intention for the Connect Service Graph. This defines @@ -727,7 +730,7 @@ type IntentionQueryCheckResponse struct { // - Whether the matching intention has L7 permissions attached // - Whether the intention is managed by an external source like k8s // - Whether there is an exact, or wildcard, intention referencing the two services -// - Whether ACLs are in DefaultAllow mode +// - Whether intentions are in DefaultAllow mode type IntentionDecisionSummary struct { Allowed bool HasPermissions bool diff --git a/agent/structs/structs.deepcopy.go b/agent/structs/structs.deepcopy.go index 017b0c943ca6..893514538a5b 100644 --- a/agent/structs/structs.deepcopy.go +++ b/agent/structs/structs.deepcopy.go @@ -1,4 +1,4 @@ -// generated by deep-copy -pointer-receiver -o ./structs.deepcopy.go -type APIGatewayListener -type BoundAPIGatewayListener -type CARoot -type CheckServiceNode -type CheckType -type CompiledDiscoveryChain -type ConnectProxyConfig -type DiscoveryFailover -type DiscoveryGraphNode -type DiscoveryResolver -type DiscoveryRoute -type DiscoverySplit -type ExposeConfig -type ExportedServicesConfigEntry -type GatewayService -type GatewayServiceTLSConfig -type HTTPHeaderModifiers -type HTTPRouteConfigEntry -type HashPolicy -type HealthCheck -type IndexedCARoots -type IngressListener -type InlineCertificateConfigEntry -type Intention -type IntentionPermission -type LoadBalancer -type MeshConfigEntry -type MeshDirectionalTLSConfig -type MeshTLSConfig -type Node -type NodeService -type PeeringServiceMeta -type ServiceConfigEntry -type ServiceConfigResponse -type ServiceConnect -type ServiceDefinition -type ServiceResolverConfigEntry -type ServiceResolverFailover -type ServiceRoute -type ServiceRouteDestination -type ServiceRouteMatch -type TCPRouteConfigEntry -type Upstream -type UpstreamConfiguration -type Status -type BoundAPIGatewayConfigEntry ./; DO NOT EDIT. +// Code generated by deep-copy -pointer-receiver -o ./structs.deepcopy.go -type APIGatewayListener -type BoundAPIGatewayListener -type CARoot -type CheckServiceNode -type CheckType -type CompiledDiscoveryChain -type ConnectProxyConfig -type DiscoveryFailover -type DiscoveryGraphNode -type DiscoveryResolver -type DiscoveryRoute -type DiscoverySplit -type ExposeConfig -type ExportedServicesConfigEntry -type FileSystemCertificateConfigEntry -type GatewayService -type GatewayServiceTLSConfig -type HTTPHeaderModifiers -type HTTPRouteConfigEntry -type HashPolicy -type HealthCheck -type IndexedCARoots -type IngressListener -type InlineCertificateConfigEntry -type Intention -type IntentionPermission -type LoadBalancer -type MeshConfigEntry -type MeshDirectionalTLSConfig -type MeshTLSConfig -type Node -type NodeService -type PeeringServiceMeta -type ServiceConfigEntry -type ServiceConfigResponse -type ServiceConnect -type ServiceDefinition -type ServiceResolverConfigEntry -type ServiceResolverFailover -type ServiceRoute -type ServiceRouteDestination -type ServiceRouteMatch -type ServiceSpecificRequest -type TCPRouteConfigEntry -type Upstream -type UpstreamConfiguration -type Status -type BoundAPIGatewayConfigEntry ./; DO NOT EDIT. package structs @@ -318,6 +318,18 @@ func (o *ExportedServicesConfigEntry) DeepCopy() *ExportedServicesConfigEntry { return &cp } +// DeepCopy generates a deep copy of *FileSystemCertificateConfigEntry +func (o *FileSystemCertificateConfigEntry) DeepCopy() *FileSystemCertificateConfigEntry { + var cp FileSystemCertificateConfigEntry = *o + if o.Meta != nil { + cp.Meta = make(map[string]string, len(o.Meta)) + for k2, v2 := range o.Meta { + cp.Meta[k2] = v2 + } + } + return &cp +} + // DeepCopy generates a deep copy of *GatewayService func (o *GatewayService) DeepCopy() *GatewayService { var cp GatewayService = *o @@ -797,6 +809,14 @@ func (o *MeshConfigEntry) DeepCopy() *MeshConfigEntry { if o.HTTP != nil { cp.HTTP = new(MeshHTTPConfig) *cp.HTTP = *o.HTTP + if o.HTTP.Incoming != nil { + cp.HTTP.Incoming = new(MeshDirectionalHTTPConfig) + *cp.HTTP.Incoming = *o.HTTP.Incoming + if o.HTTP.Incoming.RequestNormalization != nil { + cp.HTTP.Incoming.RequestNormalization = new(RequestNormalizationMeshConfig) + *cp.HTTP.Incoming.RequestNormalization = *o.HTTP.Incoming.RequestNormalization + } + } } if o.Peering != nil { cp.Peering = new(PeeringMeshConfig) @@ -1185,6 +1205,22 @@ func (o *ServiceRouteMatch) DeepCopy() *ServiceRouteMatch { return &cp } +// DeepCopy generates a deep copy of *ServiceSpecificRequest +func (o *ServiceSpecificRequest) DeepCopy() *ServiceSpecificRequest { + var cp ServiceSpecificRequest = *o + if o.NodeMetaFilters != nil { + cp.NodeMetaFilters = make(map[string]string, len(o.NodeMetaFilters)) + for k2, v2 := range o.NodeMetaFilters { + cp.NodeMetaFilters[k2] = v2 + } + } + if o.ServiceTags != nil { + cp.ServiceTags = make([]string, len(o.ServiceTags)) + copy(cp.ServiceTags, o.ServiceTags) + } + return &cp +} + // DeepCopy generates a deep copy of *TCPRouteConfigEntry func (o *TCPRouteConfigEntry) DeepCopy() *TCPRouteConfigEntry { var cp TCPRouteConfigEntry = *o @@ -1342,6 +1378,17 @@ func (o *BoundAPIGatewayConfigEntry) DeepCopy() *BoundAPIGatewayConfigEntry { } } } + if o.Services != nil { + cp.Services = make(map[ServiceName][]ResourceReference, len(o.Services)) + for k2, v2 := range o.Services { + var cp_Services_v2 []ResourceReference + if v2 != nil { + cp_Services_v2 = make([]ResourceReference, len(v2)) + copy(cp_Services_v2, v2) + } + cp.Services[k2] = cp_Services_v2 + } + } if o.Meta != nil { cp.Meta = make(map[string]string, len(o.Meta)) for k2, v2 := range o.Meta { diff --git a/agent/structs/structs.go b/agent/structs/structs.go index 9b2685946cbe..cae14af52b01 100644 --- a/agent/structs/structs.go +++ b/agent/structs/structs.go @@ -13,6 +13,7 @@ import ( "os" "reflect" "regexp" + "slices" "sort" "strconv" "strings" @@ -582,7 +583,11 @@ type QuerySource struct { Segment string Node string NodePartition string `json:",omitempty"` - Ip string + // DisableNode indicates that the Node and NodePartition fields should not be used + // for determining the flow of the RPC. This is needed for agentless + wanfed to + // utilize streaming RPCs. + DisableNode bool `json:",omitempty"` + Ip string } func (s QuerySource) NodeEnterpriseMeta() *acl.EnterpriseMeta { @@ -666,6 +671,7 @@ type ServiceDumpRequest struct { Datacenter string ServiceKind ServiceKind UseServiceKind bool + NodesOnly bool Source QuerySource acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` PeerName string @@ -698,6 +704,7 @@ func (r *ServiceDumpRequest) CacheInfo() cache.RequestInfo { v, err := hashstructure.Hash([]interface{}{ keyKind, r.UseServiceKind, + r.NodesOnly, r.Filter, r.EnterpriseMeta, }, nil) @@ -746,16 +753,20 @@ type ServiceSpecificRequest struct { // The name of the peer that the requested service was imported from. PeerName string + // The name of the sameness group that should be the target of the query. + SamenessGroup string + NodeMetaFilters map[string]string ServiceName string ServiceKind ServiceKind // DEPRECATED (singular-service-tag) - remove this when backwards RPC compat // with 1.2.x is not required. - ServiceTag string - ServiceTags []string - ServiceAddress string - TagFilter bool // Controls tag filtering - Source QuerySource + ServiceTag string + ServiceTags []string + ServiceAddress string + TagFilter bool // Controls tag filtering + HealthFilterType HealthFilterType + Source QuerySource // Connect if true will only search for Connect-compatible services. Connect bool @@ -813,9 +824,11 @@ func (r *ServiceSpecificRequest) CacheInfo() cache.RequestInfo { r.Filter, r.EnterpriseMeta, r.PeerName, + r.SamenessGroup, r.Ingress, r.ServiceKind, r.MergeCentralConfig, + r.HealthFilterType, }, nil) if err == nil { // If there is an error, we don't set the key. A blank key forces @@ -2116,6 +2129,19 @@ func (csn *CheckServiceNode) Locality() *Locality { return nil } +func (csn *CheckServiceNode) ExcludeBasedOnChecks(opts CheckServiceNodeFilterOptions) bool { + for _, check := range csn.Checks { + if slices.Contains(opts.IgnoreCheckIDs, check.CheckID) { + // Skip this _check_ but keep looking at other checks for this node. + continue + } + if opts.FilterType.ExcludeBasedOnStatus(check.Status) { + return true + } + } + return false +} + type CheckServiceNodes []CheckServiceNode func (csns CheckServiceNodes) DeepCopy() CheckServiceNodes { @@ -2155,39 +2181,42 @@ func (nodes CheckServiceNodes) ShallowClone() CheckServiceNodes { return dup } +// HealthFilterType is used to filter nodes based on their health status. +type HealthFilterType int32 + +func (h HealthFilterType) ExcludeBasedOnStatus(status string) bool { + switch { + case h == HealthFilterExcludeCritical && status == api.HealthCritical: + return true + case h == HealthFilterIncludeOnlyPassing && status != api.HealthPassing: + return true + } + return false +} + +// These are listed from most to least inclusive. +const ( + HealthFilterIncludeAll HealthFilterType = 0 + HealthFilterExcludeCritical HealthFilterType = 1 + HealthFilterIncludeOnlyPassing HealthFilterType = 2 +) + +type CheckServiceNodeFilterOptions struct { + FilterType HealthFilterType + IgnoreCheckIDs []types.CheckID + disableReceiverModification bool +} + // Filter removes nodes that are failing health checks (and any non-passing // check if that option is selected). Note that this returns the filtered // results AND modifies the receiver for performance. -func (nodes CheckServiceNodes) Filter(onlyPassing bool) CheckServiceNodes { - return nodes.FilterIgnore(onlyPassing, nil) -} - -// FilterIgnore removes nodes that are failing health checks just like Filter. -// It also ignores the status of any check with an ID present in ignoreCheckIDs -// as if that check didn't exist. Note that this returns the filtered results -// AND modifies the receiver for performance. -func (nodes CheckServiceNodes) FilterIgnore(onlyPassing bool, - ignoreCheckIDs []types.CheckID) CheckServiceNodes { +func (nodes CheckServiceNodes) Filter(opts CheckServiceNodeFilterOptions) CheckServiceNodes { n := len(nodes) -OUTER: for i := 0; i < n; i++ { - node := nodes[i] - INNER: - for _, check := range node.Checks { - for _, ignore := range ignoreCheckIDs { - if check.CheckID == ignore { - // Skip this _check_ but keep looking at other checks for this node. - continue INNER - } - } - if check.Status == api.HealthCritical || - (onlyPassing && check.Status != api.HealthPassing) { - nodes[i], nodes[n-1] = nodes[n-1], CheckServiceNode{} - n-- - i-- - // Skip this _node_ now we've swapped it off the end of the list. - continue OUTER - } + if nodes[i].ExcludeBasedOnChecks(opts) { + nodes[i], nodes[n-1] = nodes[n-1], CheckServiceNode{} + n-- + i-- } } return nodes[:n] diff --git a/agent/structs/structs_test.go b/agent/structs/structs_test.go index bf909aa41903..3f73e0cc287a 100644 --- a/agent/structs/structs_test.go +++ b/agent/structs/structs_test.go @@ -1725,7 +1725,7 @@ func TestCheckServiceNodes_Filter(t *testing.T) { if n := copy(twiddle, nodes); n != len(nodes) { t.Fatalf("bad: %d", n) } - filtered := twiddle.Filter(false) + filtered := twiddle.Filter(CheckServiceNodeFilterOptions{FilterType: HealthFilterExcludeCritical}) expected := CheckServiceNodes{ nodes[0], nodes[1], @@ -1741,7 +1741,7 @@ func TestCheckServiceNodes_Filter(t *testing.T) { if n := copy(twiddle, nodes); n != len(nodes) { t.Fatalf("bad: %d", n) } - filtered := twiddle.Filter(true) + filtered := twiddle.Filter(CheckServiceNodeFilterOptions{FilterType: HealthFilterIncludeOnlyPassing}) expected := CheckServiceNodes{ nodes[1], } @@ -1757,7 +1757,7 @@ func TestCheckServiceNodes_Filter(t *testing.T) { if n := copy(twiddle, nodes); n != len(nodes) { t.Fatalf("bad: %d", n) } - filtered := twiddle.FilterIgnore(true, []types.CheckID{""}) + filtered := twiddle.Filter(CheckServiceNodeFilterOptions{FilterType: HealthFilterIncludeOnlyPassing, IgnoreCheckIDs: []types.CheckID{""}}) expected := CheckServiceNodes{ nodes[0], nodes[1], diff --git a/agent/testagent.go b/agent/testagent.go index 037bdc76da68..5f0225c42579 100644 --- a/agent/testagent.go +++ b/agent/testagent.go @@ -13,11 +13,14 @@ import ( "net/http/httptest" "path/filepath" "strconv" + "strings" "testing" "text/template" "time" "github.com/armon/go-metrics" + "github.com/stretchr/testify/require" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-uuid" @@ -74,7 +77,7 @@ type TestAgent struct { // dns is a reference to the first started DNS endpoint. // It is valid after Start(). - dns *DNSServer + dns dnsServer // srv is an HTTPHandlers that may be used to test http endpoints. srv *HTTPHandlers @@ -86,15 +89,32 @@ type TestAgent struct { // allows the BaseDeps to be modified before starting the embedded agent OverrideDeps func(deps *BaseDeps) + // Skips asserting that the ACL bootstrap has occurred. This may be required + // for various tests where multiple servers are joined later. + disableACLBootstrapCheck bool + // Agent is the embedded consul agent. // It is valid after Start(). *Agent } +type TestAgentOpts struct { + // Skips asserting that the ACL bootstrap has occurred. This may be required + // for various tests where multiple servers are joined later. + DisableACLBootstrapCheck bool +} + // NewTestAgent returns a started agent with the given configuration. It fails // the test if the Agent could not be started. -func NewTestAgent(t *testing.T, hcl string) *TestAgent { - a := StartTestAgent(t, TestAgent{HCL: hcl}) +func NewTestAgent(t testing.TB, hcl string, opts ...TestAgentOpts) *TestAgent { + // This varargs approach is used so that we don't have to modify all of the `NewTestAgent()` calls + // in order to introduce more optional arguments. + require.LessOrEqual(t, len(opts), 1, "NewTestAgent cannot accept more than one opts argument") + ta := TestAgent{HCL: hcl} + if len(opts) == 1 { + ta.disableACLBootstrapCheck = opts[0].DisableACLBootstrapCheck + } + a := StartTestAgent(t, ta) t.Cleanup(func() { a.Shutdown() }) return a } @@ -114,11 +134,11 @@ func NewTestAgentWithConfigFile(t *testing.T, hcl string, configFiles []string) // // The caller is responsible for calling Shutdown() to stop the agent and remove // temporary directories. -func StartTestAgent(t *testing.T, a TestAgent) *TestAgent { +func StartTestAgent(t testing.TB, a TestAgent) *TestAgent { t.Helper() retry.RunWith(retry.ThreeTimes(), t, func(r *retry.R) { - t.Helper() - if err := a.Start(t); err != nil { + r.Helper() + if err := a.Start(r); err != nil { r.Fatal(err) } }) @@ -152,7 +172,7 @@ func TestConfigHCL(nodeID string) string { // Start starts a test agent. It returns an error if the agent could not be started. // If no error is returned, the caller must call Shutdown() when finished. -func (a *TestAgent) Start(t *testing.T) error { +func (a *TestAgent) Start(t testutil.TestingTB) error { t.Helper() if a.Agent != nil { return fmt.Errorf("TestAgent already started") @@ -286,20 +306,14 @@ func (a *TestAgent) waitForUp() error { continue // fail, try again } if a.Config.Bootstrap && a.Config.ServerMode { - if a.baseDeps.UseV2Resources() { - args := structs.DCSpecificRequest{ - Datacenter: "dc1", - } - var leader string - if err := a.RPC(context.Background(), "Status.Leader", args, &leader); err != nil { - retErr = fmt.Errorf("Status.Leader failed: %v", err) + if !a.disableACLBootstrapCheck { + if ok, err := a.isACLBootstrapped(); err != nil { + retErr = fmt.Errorf("error checking for acl bootstrap: %w", err) continue // fail, try again - } - if leader == "" { - retErr = fmt.Errorf("No leader") + } else if !ok { + retErr = fmt.Errorf("acl system not bootstrapped yet") continue // fail, try again } - return nil // success } // Ensure we have a leader and a node registration. @@ -337,11 +351,56 @@ func (a *TestAgent) waitForUp() error { } return nil // success } + } return fmt.Errorf("unavailable. last error: %v", retErr) } +func (a *TestAgent) isACLBootstrapped() (bool, error) { + if a.config.ACLInitialManagementToken == "" { + logger := a.Agent.logger.Named("test") + logger.Warn("Skipping check for ACL bootstrapping") + + return true, nil // We lie because we can't check. + } + + const policyName = structs.ACLPolicyGlobalManagementName + + req := httptest.NewRequest("GET", "/v1/acl/policy/name/"+policyName, nil) + req.Header.Add("X-Consul-Token", a.config.ACLInitialManagementToken) + resp := httptest.NewRecorder() + + raw, err := a.srv.ACLPolicyReadByName(resp, req) + if err != nil { + if strings.Contains(err.Error(), "Unexpected response code: 403 (ACL not found)") { + return false, nil + } else if isACLNotBootstrapped(err) { + return false, nil + } + return false, err + } + if raw == nil { + return false, nil + } + policy, ok := raw.(*structs.ACLPolicy) + if !ok { + return false, fmt.Errorf("expected ACLPolicy got %T", raw) + } + + return policy != nil, nil +} + +func isACLNotBootstrapped(err error) bool { + switch { + case strings.Contains(err.Error(), "ACL system must be bootstrapped before making any requests that require authorization"): + return true + case strings.Contains(err.Error(), "The ACL system is currently in legacy mode"): + return true + } + return false +} + // Shutdown stops the agent and removes the data directory if it is // managed by the test agent. func (a *TestAgent) Shutdown() error { @@ -362,7 +421,7 @@ func (a *TestAgent) DNSAddr() string { if a.dns == nil { return "" } - return a.dns.Addr + return a.dns.GetAddr() } func (a *TestAgent) HTTPAddr() string { @@ -442,10 +501,10 @@ func (r *retryShim) Name() string { // chance of port conflicts for concurrently executed test binaries. // Instead of relying on one set of ports to be sufficient we retry // starting the agent with different ports on port conflict. -func randomPortsSource(t *testing.T, useHTTPS bool) string { +func randomPortsSource(t testutil.TestingTB, useHTTPS bool) string { var ports []int retry.RunWith(retry.TwoSeconds(), t, func(r *retry.R) { - ports = freeport.GetN(&retryShim{r, t.Name()}, 7) + ports = freeport.GetN(r, 7) }) var http, https int diff --git a/agent/translate_addr.go b/agent/translate_addr.go index 1c0f8a400305..326117cc9866 100644 --- a/agent/translate_addr.go +++ b/agent/translate_addr.go @@ -5,21 +5,12 @@ package agent import ( "fmt" + "github.com/hashicorp/consul/internal/dnsutil" "net" "github.com/hashicorp/consul/agent/structs" ) -type TranslateAddressAccept int - -const ( - TranslateAddressAcceptDomain TranslateAddressAccept = 1 << iota - TranslateAddressAcceptIPv4 - TranslateAddressAcceptIPv6 - - TranslateAddressAcceptAny TranslateAddressAccept = ^0 -) - // TranslateServicePort is used to provide the final, translated port for a service, // depending on how the agent and the other node are configured. The dc // parameter is the dc the datacenter this node is from. @@ -35,7 +26,7 @@ func (a *Agent) TranslateServicePort(dc string, port int, taggedAddresses map[st // TranslateServiceAddress is used to provide the final, translated address for a node, // depending on how the agent and the other node are configured. The dc // parameter is the dc the datacenter this node is from. -func (a *Agent) TranslateServiceAddress(dc string, addr string, taggedAddresses map[string]structs.ServiceAddress, accept TranslateAddressAccept) string { +func (a *Agent) TranslateServiceAddress(dc string, addr string, taggedAddresses map[string]structs.ServiceAddress, accept dnsutil.TranslateAddressAccept) string { def := addr v4 := taggedAddresses[structs.TaggedAddressLANIPv4].Address v6 := taggedAddresses[structs.TaggedAddressLANIPv6].Address @@ -59,7 +50,7 @@ func (a *Agent) TranslateServiceAddress(dc string, addr string, taggedAddresses // TranslateAddress is used to provide the final, translated address for a node, // depending on how the agent and the other node are configured. The dc // parameter is the dc the datacenter this node is from. -func (a *Agent) TranslateAddress(dc string, addr string, taggedAddresses map[string]string, accept TranslateAddressAccept) string { +func (a *Agent) TranslateAddress(dc string, addr string, taggedAddresses map[string]string, accept dnsutil.TranslateAddressAccept) string { def := addr v4 := taggedAddresses[structs.TaggedAddressLANIPv4] v6 := taggedAddresses[structs.TaggedAddressLANIPv6] @@ -80,22 +71,22 @@ func (a *Agent) TranslateAddress(dc string, addr string, taggedAddresses map[str return translateAddressAccept(accept, def, v4, v6) } -func translateAddressAccept(accept TranslateAddressAccept, def, v4, v6 string) string { +func translateAddressAccept(accept dnsutil.TranslateAddressAccept, def, v4, v6 string) string { switch { - case accept&TranslateAddressAcceptIPv6 > 0 && v6 != "": + case accept&dnsutil.TranslateAddressAcceptIPv6 > 0 && v6 != "": return v6 - case accept&TranslateAddressAcceptIPv4 > 0 && v4 != "": + case accept&dnsutil.TranslateAddressAcceptIPv4 > 0 && v4 != "": return v4 - case accept&TranslateAddressAcceptAny > 0 && def != "": + case accept&dnsutil.TranslateAddressAcceptAny > 0 && def != "": return def default: defIP := net.ParseIP(def) switch { - case defIP != nil && defIP.To4() != nil && accept&TranslateAddressAcceptIPv4 > 0: + case defIP != nil && defIP.To4() != nil && accept&dnsutil.TranslateAddressAcceptIPv4 > 0: return def - case defIP != nil && defIP.To4() == nil && accept&TranslateAddressAcceptIPv6 > 0: + case defIP != nil && defIP.To4() == nil && accept&dnsutil.TranslateAddressAcceptIPv6 > 0: return def - case defIP == nil && accept&TranslateAddressAcceptDomain > 0: + case defIP == nil && accept&dnsutil.TranslateAddressAcceptDomain > 0: return def } } @@ -106,7 +97,7 @@ func translateAddressAccept(accept TranslateAddressAccept, def, v4, v6 string) s // TranslateAddresses translates addresses in the given structure into the // final, translated address, depending on how the agent and the other node are // configured. The dc parameter is the datacenter this structure is from. -func (a *Agent) TranslateAddresses(dc string, subj interface{}, accept TranslateAddressAccept) { +func (a *Agent) TranslateAddresses(dc string, subj interface{}, accept dnsutil.TranslateAddressAccept) { // CAUTION - SUBTLE! An agent running on a server can, in some cases, // return pointers directly into the immutable state store for // performance (it's via the in-memory RPC mechanism). It's never safe diff --git a/agent/ui_endpoint.go b/agent/ui_endpoint.go index d0cc8a5be832..94c354564705 100644 --- a/agent/ui_endpoint.go +++ b/agent/ui_endpoint.go @@ -438,7 +438,7 @@ func (s *HTTPHandlers) UIServiceTopology(resp http.ResponseWriter, req *http.Req args.ServiceKind = structs.ServiceKind(kind[0]) switch args.ServiceKind { - case structs.ServiceKindTypical, structs.ServiceKindIngressGateway: + case structs.ServiceKindTypical, structs.ServiceKindIngressGateway, structs.ServiceKindAPIGateway: // allowed default: return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: fmt.Sprintf("Unsupported service kind %q", args.ServiceKind)} @@ -669,7 +669,7 @@ func prepSummaryOutput(summaries map[structs.PeeredServiceName]*ServiceSummary, sum.ChecksCritical++ } } - if excludeSidecars && sum.Kind != structs.ServiceKindTypical && sum.Kind != structs.ServiceKindIngressGateway { + if excludeSidecars && sum.Kind != structs.ServiceKindTypical && sum.Kind != structs.ServiceKindIngressGateway && sum.Kind != structs.ServiceKindAPIGateway { continue } resp = append(resp, sum) diff --git a/agent/ui_endpoint_test.go b/agent/ui_endpoint_test.go index dd1c6d8134b2..2df3cb784989 100644 --- a/agent/ui_endpoint_test.go +++ b/agent/ui_endpoint_test.go @@ -18,10 +18,11 @@ import ( "testing" "time" - cleanhttp "github.com/hashicorp/go-cleanhttp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cleanhttp "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/consul/agent/config" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" @@ -32,28 +33,6 @@ import ( "github.com/hashicorp/consul/types" ) -func TestUIEndpointsFailInV2(t *testing.T) { - t.Parallel() - - a := NewTestAgent(t, `experiments = ["resource-apis"]`) - - checkRequest := func(method, url string) { - t.Run(method+" "+url, func(t *testing.T) { - assertV1CatalogEndpointDoesNotWorkWithV2(t, a, method, url, "{}") - }) - } - - checkRequest("GET", "/v1/internal/ui/nodes") - checkRequest("GET", "/v1/internal/ui/node/web") - checkRequest("GET", "/v1/internal/ui/services") - checkRequest("GET", "/v1/internal/ui/exported-services") - checkRequest("GET", "/v1/internal/ui/catalog-overview") - checkRequest("GET", "/v1/internal/ui/gateway-services-nodes/web") - checkRequest("GET", "/v1/internal/ui/gateway-intentions/web") - checkRequest("GET", "/v1/internal/ui/service-topology/web") - checkRequest("PUT", "/v1/internal/service-virtual-ip") -} - func TestUIIndex(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") diff --git a/agent/uiserver/dist/assets/chunk.121.ea70a154d4cf1227b100.js b/agent/uiserver/dist/assets/chunk.121.ea70a154d4cf1227b100.js new file mode 100644 index 000000000000..937fa68879d8 --- /dev/null +++ b/agent/uiserver/dist/assets/chunk.121.ea70a154d4cf1227b100.js @@ -0,0 +1,65 @@ +"use strict";(globalThis.webpackChunk_ember_auto_import_=globalThis.webpackChunk_ember_auto_import_||[]).push([[121],{4121:(e,t,o)=>{o.r(t),o.d(t,{default:()=>_}) +var i=window.CustomEvent +function n(e,t){var o="on"+t.type.toLowerCase() +return"function"==typeof e[o]&&e[o](t),e.dispatchEvent(t)}function a(e){for(;e;){if("dialog"===e.localName)return e +e=e.parentElement?e.parentElement:e.parentNode?e.parentNode.host:null}return null}function r(e){for(;e&&e.shadowRoot&&e.shadowRoot.activeElement;)e=e.shadowRoot.activeElement +e&&e.blur&&e!==document.body&&e.blur()}function l(e,t){for(var o=0;o=0&&(e=this.dialog_),e||(e=d(this.dialog_)),r(document.activeElement),e&&e.focus()},updateZIndex:function(e,t){if(e, the polyfill may not work correctly",e),"dialog"!==e.localName)throw new Error("Failed to register dialog: The element is not a dialog.") +new p(e)},registerDialog:function(e){e.showModal||g.forceRegisterDialog(e)},DialogManager:function(){this.pendingDialogStack=[] +var e=this.checkDOM_.bind(this) +this.overlay=document.createElement("div"),this.overlay.className="_dialog_overlay",this.overlay.addEventListener("click",function(t){this.forwardTab_=void 0,t.stopPropagation(),e([])}.bind(this)),this.handleKey_=this.handleKey_.bind(this),this.handleFocus_=this.handleFocus_.bind(this),this.zIndexLow_=1e5,this.zIndexHigh_=100150,this.forwardTab_=void 0,"MutationObserver"in window&&(this.mo_=new MutationObserver((function(t){var o=[] +t.forEach((function(e){for(var t,i=0;t=e.removedNodes[i];++i)t instanceof Element&&("dialog"===t.localName&&o.push(t),o=o.concat(t.querySelectorAll("dialog")))})),o.length&&e(o)})))}} +if(g.DialogManager.prototype.blockDocument=function(){document.documentElement.addEventListener("focus",this.handleFocus_,!0),document.addEventListener("keydown",this.handleKey_),this.mo_&&this.mo_.observe(document,{childList:!0,subtree:!0})},g.DialogManager.prototype.unblockDocument=function(){document.documentElement.removeEventListener("focus",this.handleFocus_,!0),document.removeEventListener("keydown",this.handleKey_),this.mo_&&this.mo_.disconnect()},g.DialogManager.prototype.updateStacking=function(){for(var e,t=this.zIndexHigh_,o=0;e=this.pendingDialogStack[o];++o)e.updateZIndex(--t,--t),0===o&&(this.overlay.style.zIndex=--t) +var i=this.pendingDialogStack[0] +i?(i.dialog.parentNode||document.body).appendChild(this.overlay):this.overlay.parentNode&&this.overlay.parentNode.removeChild(this.overlay)},g.DialogManager.prototype.containedByTopDialog_=function(e){for(;e=a(e);){for(var t,o=0;t=this.pendingDialogStack[o];++o)if(t.dialog===e)return 0===o +e=e.parentElement}return!1},g.DialogManager.prototype.handleFocus_=function(e){var t=e.composedPath?e.composedPath()[0]:e.target +if(!this.containedByTopDialog_(t)&&document.activeElement!==document.documentElement&&(e.preventDefault(),e.stopPropagation(),r(t),void 0!==this.forwardTab_)){var o=this.pendingDialogStack[0] +return o.dialog.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_PRECEDING&&(this.forwardTab_?o.focus_():t!==document.documentElement&&document.documentElement.focus()),!1}},g.DialogManager.prototype.handleKey_=function(e){if(this.forwardTab_=void 0,27===e.keyCode){e.preventDefault(),e.stopPropagation() +var t=new i("cancel",{bubbles:!1,cancelable:!0}),o=this.pendingDialogStack[0] +o&&n(o.dialog,t)&&o.dialog.close()}else 9===e.keyCode&&(this.forwardTab_=!e.shiftKey)},g.DialogManager.prototype.checkDOM_=function(e){this.pendingDialogStack.slice().forEach((function(t){-1!==e.indexOf(t.dialog)?t.downgradeModal():t.maybeHideModal()}))},g.DialogManager.prototype.pushDialog=function(e){var t=(this.zIndexHigh_-this.zIndexLow_)/2-1 +return!(this.pendingDialogStack.length>=t||(1===this.pendingDialogStack.unshift(e)&&this.blockDocument(),this.updateStacking(),0))},g.DialogManager.prototype.removeDialog=function(e){var t=this.pendingDialogStack.indexOf(e);-1!==t&&(this.pendingDialogStack.splice(t,1),0===this.pendingDialogStack.length&&this.unblockDocument(),this.updateStacking())},g.dm=new g.DialogManager,g.formSubmitter=null,g.imagemapUseValue=null,void 0===window.HTMLDialogElement){var m=document.createElement("form") +if(m.setAttribute("method","dialog"),"dialog"!==m.method){var f=Object.getOwnPropertyDescriptor(HTMLFormElement.prototype,"method") +if(f){var b=f.get +f.get=function(){return s(this)?"dialog":b.call(this)} +var v=f.set +f.set=function(e){return"string"==typeof e&&"dialog"===e.toLowerCase()?this.setAttribute("method",e):v.call(this,e)},Object.defineProperty(HTMLFormElement.prototype,"method",f)}}document.addEventListener("click",(function(e){if(g.formSubmitter=null,g.imagemapUseValue=null,!e.defaultPrevented){var t=e.target +if("composedPath"in e&&(t=e.composedPath().shift()||t),t&&s(t.form)){if(!("submit"===t.type&&["button","input"].indexOf(t.localName)>-1)){if("input"!==t.localName||"image"!==t.type)return +g.imagemapUseValue=e.offsetX+","+e.offsetY}a(t)&&(g.formSubmitter=t)}}}),!1),document.addEventListener("submit",(function(e){var t=e.target +if(!a(t)){var o=c(e) +"dialog"===(o&&o.getAttribute("formmethod")||t.getAttribute("method"))&&e.preventDefault()}})) +var y=HTMLFormElement.prototype.submit +HTMLFormElement.prototype.submit=function(){if(!s(this))return y.call(this) +var e=a(this) +e&&e.close()}}const _=g}}]) diff --git a/agent/uiserver/dist/assets/chunk.143.514eb80cfd7d0554773a.css b/agent/uiserver/dist/assets/chunk.143.514eb80cfd7d0554773a.css new file mode 100644 index 000000000000..792cf60b3317 --- /dev/null +++ b/agent/uiserver/dist/assets/chunk.143.514eb80cfd7d0554773a.css @@ -0,0 +1,3 @@ +.tippy-box[data-placement^=top]>.tippy-svg-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-svg-arrow:after,.tippy-box[data-placement^=top]>.tippy-svg-arrow>svg{top:16px;transform:rotate(180deg)}.tippy-box[data-placement^=bottom]>.tippy-svg-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-svg-arrow>svg{bottom:16px}.tippy-box[data-placement^=left]>.tippy-svg-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-svg-arrow:after,.tippy-box[data-placement^=left]>.tippy-svg-arrow>svg{transform:rotate(90deg);top:calc(50% - 3px);left:11px}.tippy-box[data-placement^=right]>.tippy-svg-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-svg-arrow:after,.tippy-box[data-placement^=right]>.tippy-svg-arrow>svg{transform:rotate(-90deg);top:calc(50% - 3px);right:11px}.tippy-svg-arrow{width:16px;height:16px;fill:#333;text-align:initial}.tippy-svg-arrow,.tippy-svg-arrow>svg{position:absolute} + +/*# sourceMappingURL=chunk.143.514eb80cfd7d0554773a.css-dab4810f7765b133c18bff2650e193b5.map*/ \ No newline at end of file diff --git a/agent/uiserver/dist/assets/chunk.143.514eb80cfd7d0554773a.js b/agent/uiserver/dist/assets/chunk.143.514eb80cfd7d0554773a.js new file mode 100644 index 000000000000..401037dc38bd --- /dev/null +++ b/agent/uiserver/dist/assets/chunk.143.514eb80cfd7d0554773a.js @@ -0,0 +1,52 @@ +var __ember_auto_import__;(()=>{var e,r,t,n={1292:e=>{"use strict" +e.exports=require("@ember/application")},6354:e=>{"use strict" +e.exports=require("@ember/component/helper")},3353:e=>{"use strict" +e.exports=require("@ember/debug")},9341:e=>{"use strict" +e.exports=require("@ember/destroyable")},4927:e=>{"use strict" +e.exports=require("@ember/modifier")},7219:e=>{"use strict" +e.exports=require("@ember/object")},8773:e=>{"use strict" +e.exports=require("@ember/runloop")},8574:e=>{"use strict" +e.exports=require("@ember/service")},1866:e=>{"use strict" +e.exports=require("@ember/utils")},9357:(e,r,t)=>{var n,o +e.exports=(n=_eai_d,o=_eai_r,window.emberAutoImportDynamic=function(e){return 1===arguments.length?o("_eai_dyn_"+e):o("_eai_dynt_"+e)(Array.prototype.slice.call(arguments,1))},window.emberAutoImportSync=function(e){return o("_eai_sync_"+e)(Array.prototype.slice.call(arguments,1))},n("@hashicorp/flight-icons/svg",[],(function(){return t(6604)})),n("@hashicorp/flight-icons/svg-sprite/svg-sprite-module",[],(function(){return t(2654)})),n("@lit/reactive-element",[],(function(){return t(8531)})),n("@xstate/fsm",[],(function(){return t(7440)})),n("a11y-dialog",[],(function(){return t(1413)})),n("base64-js",[],(function(){return t(8294)})),n("clipboard",[],(function(){return t(9079)})),n("d3-array",[],(function(){return t(5447)})),n("d3-scale",[],(function(){return t(5134)})),n("d3-scale-chromatic",[],(function(){return t(2331)})),n("d3-selection",[],(function(){return t(8740)})),n("d3-shape",[],(function(){return t(5043)})),n("dayjs",[],(function(){return t(2350)})),n("dayjs/plugin/calendar",[],(function(){return t(8888)})),n("dayjs/plugin/relativeTime",[],(function(){return t(2543)})),n("deepmerge",[],(function(){return t(3924)})),n("ember-focus-trap/modifiers/focus-trap.js",["@ember/modifier"],(function(){return t(3109)})),n("ember-keyboard/helpers/if-key.js",["@ember/component/helper","@ember/debug","@ember/utils"],(function(){return t(3481)})),n("ember-keyboard/helpers/on-key.js",["@ember/component/helper","@ember/debug","@ember/service"],(function(){return t(6415)})),n("ember-keyboard/modifiers/on-key.js",["@ember/application","@ember/modifier","@ember/destroyable","@ember/service","@ember/object","@ember/debug","@ember/utils"],(function(){return t(4146)})),n("ember-keyboard/services/keyboard.js",["@ember/service","@ember/application","@ember/object","@ember/runloop","@ember/debug","@ember/utils"],(function(){return t(9690)})),n("ember-modifier",["@ember/application","@ember/modifier","@ember/destroyable"],(function(){return t(2509)})),n("fast-memoize",[],(function(){return t(3276)})),n("flat",[],(function(){return t(2349)})),n("intl-messageformat",[],(function(){return t(5861)})),n("intl-messageformat-parser",[],(function(){return t(5011)})),n("mnemonist/multi-map",[],(function(){return t(5709)})),n("mnemonist/set",[],(function(){return t(2519)})),n("ngraph.graph",[],(function(){return t(6001)})),n("parse-duration",[],(function(){return t(89)})),n("pretty-ms",[],(function(){return t(9837)})),n("tippy.js",[],(function(){return t(9640)})),n("tippy.js/dist/svg-arrow.css",[],(function(){return t(2959)})),n("validated-changeset",[],(function(){return t(6885)})),n("wayfarer",[],(function(){return t(7116)})),n("_eai_dyn_dialog-polyfill",[],(function(){return t.e(121).then(t.bind(t,4121))})),void n("_eai_dyn_dialog-polyfill-css",[],(function(){return t.e(744).then(t.bind(t,7744))})))},3404:function(e,r){window._eai_r=require,window._eai_d=define}},o={} +function i(e){var r=o[e] +if(void 0!==r)return r.exports +var t=o[e]={exports:{}} +return n[e].call(t.exports,t,t.exports,i),t.exports}i.m=n,e=[],i.O=(r,t,n,o)=>{if(!t){var u=1/0 +for(l=0;l=o)&&Object.keys(i.O).every((e=>i.O[e](t[s])))?t.splice(s--,1):(a=!1,o0&&e[l-1][2]>o;l--)e[l]=e[l-1] +e[l]=[t,n,o]},i.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e +return i.d(r,{a:r}),r},i.d=(e,r)=>{for(var t in r)i.o(r,t)&&!i.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},i.f={},i.e=e=>Promise.all(Object.keys(i.f).reduce(((r,t)=>(i.f[t](e,r),r)),[])),i.u=e=>"chunk."+e+"."+{121:"ea70a154d4cf1227b100",744:"60c31f269c98ac39ce46"}[e]+".js",i.miniCssF=e=>"chunk."+e+".60c31f269c98ac39ce46.css",i.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r={},t="__ember_auto_import__:",i.l=(e,n,o,u)=>{if(r[e])r[e].push(n) +else{var a,s +if(void 0!==o)for(var c=document.getElementsByTagName("script"),l=0;l{a.onerror=a.onload=null,clearTimeout(f) +var o=r[e] +if(delete r[e],a.parentNode&&a.parentNode.removeChild(a),o&&o.forEach((e=>e(n))),t)return t(n)},f=setTimeout(m.bind(null,void 0,{type:"timeout",target:a}),12e4) +a.onerror=m.bind(null,a.onerror),a.onload=m.bind(null,a.onload),s&&document.head.appendChild(a)}},i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.p="{{.ContentPath}}assets/",(()=>{if("undefined"!=typeof document){var e={143:0} +i.f.miniCss=(r,t)=>{e[r]?t.push(e[r]):0!==e[r]&&{744:1}[r]&&t.push(e[r]=(e=>new Promise(((r,t)=>{var n=i.miniCssF(e),o=i.p+n +if(((e,r)=>{for(var t=document.getElementsByTagName("link"),n=0;n{var i=document.createElement("link") +i.rel="stylesheet",i.type="text/css",i.onerror=i.onload=t=>{if(i.onerror=i.onload=null,"load"===t.type)n() +else{var u=t&&("load"===t.type?"missing":t.type),a=t&&t.target&&t.target.href||r,s=new Error("Loading CSS chunk "+e+" failed.\n("+a+")") +s.code="CSS_CHUNK_LOAD_FAILED",s.type=u,s.request=a,i.parentNode&&i.parentNode.removeChild(i),o(s)}},i.href=r,document.head.appendChild(i)})(e,o,0,r,t)})))(r).then((()=>{e[r]=0}),(t=>{throw delete e[r],t})))}}})(),(()=>{var e={143:0} +i.f.j=(r,t)=>{var n=i.o(e,r)?e[r]:void 0 +if(0!==n)if(n)t.push(n[2]) +else{var o=new Promise(((t,o)=>n=e[r]=[t,o])) +t.push(n[2]=o) +var u=i.p+i.u(r),a=new Error +i.l(u,(t=>{if(i.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var o=t&&("load"===t.type?"missing":t.type),u=t&&t.target&&t.target.src +a.message="Loading chunk "+r+" failed.\n("+o+": "+u+")",a.name="ChunkLoadError",a.type=o,a.request=u,n[1](a)}}),"chunk-"+r,r)}},i.O.j=r=>0===e[r] +var r=(r,t)=>{var n,o,[u,a,s]=t,c=0 +if(u.some((r=>0!==e[r]))){for(n in a)i.o(a,n)&&(i.m[n]=a[n]) +if(s)var l=s(i)}for(r&&r(t);ci(3404))) +var u=i.O(void 0,[924],(()=>i(9357))) +u=i.O(u),__ember_auto_import__=u})() diff --git a/agent/uiserver/dist/assets/chunk.143.ff39f0b820a97e2c6d5d.js b/agent/uiserver/dist/assets/chunk.143.ff39f0b820a97e2c6d5d.js deleted file mode 100644 index 343ded1152bc..000000000000 --- a/agent/uiserver/dist/assets/chunk.143.ff39f0b820a97e2c6d5d.js +++ /dev/null @@ -1,52 +0,0 @@ -var __ember_auto_import__;(()=>{var e,r,t,n,o,i={6466:(e,r,t)=>{var n,o -e.exports=(n=_eai_d,o=_eai_r,window.emberAutoImportDynamic=function(e){return 1===arguments.length?o("_eai_dyn_"+e):o("_eai_dynt_"+e)(Array.prototype.slice.call(arguments,1))},window.emberAutoImportSync=function(e){return o("_eai_sync_"+e)(Array.prototype.slice.call(arguments,1))},n("@hashicorp/flight-icons/svg",[],(function(){return t(218)})),n("@lit/reactive-element",[],(function(){return t(3493)})),n("@xstate/fsm",[],(function(){return t(9454)})),n("a11y-dialog",[],(function(){return t(6313)})),n("base64-js",[],(function(){return t(3305)})),n("clipboard",[],(function(){return t(2309)})),n("d3-array",[],(function(){return t(1286)})),n("d3-scale",[],(function(){return t(113)})),n("d3-scale-chromatic",[],(function(){return t(9677)})),n("d3-selection",[],(function(){return t(1058)})),n("d3-shape",[],(function(){return t(6736)})),n("dayjs",[],(function(){return t(4434)})),n("dayjs/plugin/calendar",[],(function(){return t(9379)})),n("dayjs/plugin/relativeTime",[],(function(){return t(8275)})),n("deepmerge",[],(function(){return t(2999)})),n("ember-focus-trap/modifiers/focus-trap.js",[],(function(){return t(6673)})),n("ember-keyboard/helpers/if-key.js",[],(function(){return t(6866)})),n("ember-keyboard/helpers/on-key.js",[],(function(){return t(9930)})),n("ember-keyboard/modifiers/on-key.js",[],(function(){return t(6222)})),n("ember-keyboard/services/keyboard.js",[],(function(){return t(6918)})),n("fast-deep-equal",[],(function(){return t(7889)})),n("fast-memoize",[],(function(){return t(4564)})),n("flat",[],(function(){return t(8581)})),n("intersection-observer-admin",[],(function(){return t(2914)})),n("intl-messageformat",[],(function(){return t(4143)})),n("intl-messageformat-parser",[],(function(){return t(4857)})),n("mnemonist/multi-map",[],(function(){return t(6196)})),n("mnemonist/set",[],(function(){return t(3333)})),n("ngraph.graph",[],(function(){return t(1832)})),n("parse-duration",[],(function(){return t(1813)})),n("pretty-ms",[],(function(){return t(3385)})),n("raf-pool",[],(function(){return t(7114)})),n("tippy.js",[],(function(){return t(1499)})),n("validated-changeset",[],(function(){return t(6530)})),n("wayfarer",[],(function(){return t(6841)})),n("_eai_dyn_dialog-polyfill",[],(function(){return t.e(83).then(t.bind(t,7083))})),void n("_eai_dyn_dialog-polyfill-css",[],(function(){return t.e(744).then(t.bind(t,7744))})))},6760:function(e,r){window._eai_r=require,window._eai_d=define},1292:e=>{"use strict" -e.exports=require("@ember/application")},8797:e=>{"use strict" -e.exports=require("@ember/component/helper")},3353:e=>{"use strict" -e.exports=require("@ember/debug")},9341:e=>{"use strict" -e.exports=require("@ember/destroyable")},4927:e=>{"use strict" -e.exports=require("@ember/modifier")},7219:e=>{"use strict" -e.exports=require("@ember/object")},8773:e=>{"use strict" -e.exports=require("@ember/runloop")},8574:e=>{"use strict" -e.exports=require("@ember/service")},1866:e=>{"use strict" -e.exports=require("@ember/utils")},5831:e=>{"use strict" -e.exports=require("ember-modifier")}},u={} -function a(e){var r=u[e] -if(void 0!==r)return r.exports -var t=u[e]={exports:{}} -return i[e].call(t.exports,t,t.exports,a),t.exports}a.m=i,e=[],a.O=(r,t,n,o)=>{if(!t){var i=1/0 -for(l=0;l=o)&&Object.keys(a.O).every((e=>a.O[e](t[s])))?t.splice(s--,1):(u=!1,o0&&e[l-1][2]>o;l--)e[l]=e[l-1] -e[l]=[t,n,o]},a.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e -return a.d(r,{a:r}),r},a.d=(e,r)=>{for(var t in r)a.o(r,t)&&!a.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},a.f={},a.e=e=>Promise.all(Object.keys(a.f).reduce(((r,t)=>(a.f[t](e,r),r)),[])),a.u=e=>"chunk."+e+"."+{83:"85cc25a28afe28f711a3",744:"c0eb6726020fc4af8d3f"}[e]+".js",a.miniCssF=e=>"chunk."+e+".c0eb6726020fc4af8d3f.css",a.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r={},t="__ember_auto_import__:",a.l=(e,n,o,i)=>{if(r[e])r[e].push(n) -else{var u,s -if(void 0!==o)for(var c=document.getElementsByTagName("script"),l=0;l{u.onerror=u.onload=null,clearTimeout(p) -var o=r[e] -if(delete r[e],u.parentNode&&u.parentNode.removeChild(u),o&&o.forEach((e=>e(n))),t)return t(n)},p=setTimeout(d.bind(null,void 0,{type:"timeout",target:u}),12e4) -u.onerror=d.bind(null,u.onerror),u.onload=d.bind(null,u.onload),s&&document.head.appendChild(u)}},a.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.p="{{.ContentPath}}assets/",n=e=>new Promise(((r,t)=>{var n=a.miniCssF(e),o=a.p+n -if(((e,r)=>{for(var t=document.getElementsByTagName("link"),n=0;n{var o=document.createElement("link") -o.rel="stylesheet",o.type="text/css",o.onerror=o.onload=i=>{if(o.onerror=o.onload=null,"load"===i.type)t() -else{var u=i&&("load"===i.type?"missing":i.type),a=i&&i.target&&i.target.href||r,s=new Error("Loading CSS chunk "+e+" failed.\n("+a+")") -s.code="CSS_CHUNK_LOAD_FAILED",s.type=u,s.request=a,o.parentNode.removeChild(o),n(s)}},o.href=r,document.head.appendChild(o)})(e,o,r,t)})),o={143:0},a.f.miniCss=(e,r)=>{o[e]?r.push(o[e]):0!==o[e]&&{744:1}[e]&&r.push(o[e]=n(e).then((()=>{o[e]=0}),(r=>{throw delete o[e],r})))},(()=>{var e={143:0} -a.f.j=(r,t)=>{var n=a.o(e,r)?e[r]:void 0 -if(0!==n)if(n)t.push(n[2]) -else{var o=new Promise(((t,o)=>n=e[r]=[t,o])) -t.push(n[2]=o) -var i=a.p+a.u(r),u=new Error -a.l(i,(t=>{if(a.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var o=t&&("load"===t.type?"missing":t.type),i=t&&t.target&&t.target.src -u.message="Loading chunk "+r+" failed.\n("+o+": "+i+")",u.name="ChunkLoadError",u.type=o,u.request=i,n[1](u)}}),"chunk-"+r,r)}},a.O.j=r=>0===e[r] -var r=(r,t)=>{var n,o,[i,u,s]=t,c=0 -if(i.some((r=>0!==e[r]))){for(n in u)a.o(u,n)&&(a.m[n]=u[n]) -if(s)var l=s(a)}for(r&&r(t);ca(6760))) -var s=a.O(void 0,[412],(()=>a(6466))) -s=a.O(s),__ember_auto_import__=s})() diff --git a/agent/uiserver/dist/assets/chunk.178.00380c6ad3fa678e07b6.js b/agent/uiserver/dist/assets/chunk.178.00380c6ad3fa678e07b6.js deleted file mode 100644 index 884e5a3cb913..000000000000 --- a/agent/uiserver/dist/assets/chunk.178.00380c6ad3fa678e07b6.js +++ /dev/null @@ -1,21 +0,0 @@ -var __ember_auto_import__;(()=>{var r,e={6760:function(r,e){window._eai_r=require,window._eai_d=define},4593:(r,e,t)=>{var o,n -r.exports=(o=_eai_d,n=_eai_r,window.emberAutoImportDynamic=function(r){return 1===arguments.length?n("_eai_dyn_"+r):n("_eai_dynt_"+r)(Array.prototype.slice.call(arguments,1))},window.emberAutoImportSync=function(r){return n("_eai_sync_"+r)(Array.prototype.slice.call(arguments,1))},o("lodash.castarray",[],(function(){return t(5665)})),o("lodash.last",[],(function(){return t(66)})),o("lodash.omit",[],(function(){return t(9254)})),o("qunit",[],(function(){return t(3409)})),void o("yadda",[],(function(){return t(409)})))},9265:()=>{},3642:()=>{}},t={} -function o(r){var n=t[r] -if(void 0!==n)return n.exports -var i=t[r]={id:r,loaded:!1,exports:{}} -return e[r].call(i.exports,i,i.exports,o),i.loaded=!0,i.exports}o.m=e,r=[],o.O=(e,t,n,i)=>{if(!t){var a=1/0 -for(c=0;c=i)&&Object.keys(o.O).every((r=>o.O[r](t[l])))?t.splice(l--,1):(u=!1,i0&&r[c-1][2]>i;c--)r[c]=r[c-1] -r[c]=[t,n,i]},o.g=function(){if("object"==typeof globalThis)return globalThis -try{return this||new Function("return this")()}catch(r){if("object"==typeof window)return window}}(),o.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),o.nmd=r=>(r.paths=[],r.children||(r.children=[]),r),(()=>{var r={178:0} -o.O.j=e=>0===r[e] -var e=(e,t)=>{var n,i,[a,u,l]=t,_=0 -if(a.some((e=>0!==r[e]))){for(n in u)o.o(u,n)&&(o.m[n]=u[n]) -if(l)var c=l(o)}for(e&&e(t);_o(6760))) -var n=o.O(void 0,[336],(()=>o(4593))) -n=o.O(n),__ember_auto_import__=n})() diff --git a/agent/uiserver/dist/assets/chunk.178.6f0fd5b292c40b1ce063.js b/agent/uiserver/dist/assets/chunk.178.6f0fd5b292c40b1ce063.js new file mode 100644 index 000000000000..fa8fae203c3b --- /dev/null +++ b/agent/uiserver/dist/assets/chunk.178.6f0fd5b292c40b1ce063.js @@ -0,0 +1,21 @@ +var __ember_auto_import__;(()=>{var r,e={9265:()=>{},3642:()=>{},3404:function(r,e){window._eai_r=require,window._eai_d=define},974:(r,e,t)=>{var o,n +r.exports=(o=_eai_d,n=_eai_r,window.emberAutoImportDynamic=function(r){return 1===arguments.length?n("_eai_dyn_"+r):n("_eai_dynt_"+r)(Array.prototype.slice.call(arguments,1))},window.emberAutoImportSync=function(r){return n("_eai_sync_"+r)(Array.prototype.slice.call(arguments,1))},o("lodash.castarray",[],(function(){return t(9542)})),o("lodash.last",[],(function(){return t(9644)})),o("lodash.omit",[],(function(){return t(1609)})),o("qunit",[],(function(){return t(2053)})),void o("yadda",[],(function(){return t(2216)})))}},t={} +function o(r){var n=t[r] +if(void 0!==n)return n.exports +var i=t[r]={id:r,loaded:!1,exports:{}} +return e[r].call(i.exports,i,i.exports,o),i.loaded=!0,i.exports}o.m=e,r=[],o.O=(e,t,n,i)=>{if(!t){var a=1/0 +for(c=0;c=i)&&Object.keys(o.O).every((r=>o.O[r](t[l])))?t.splice(l--,1):(u=!1,i0&&r[c-1][2]>i;c--)r[c]=r[c-1] +r[c]=[t,n,i]},o.g=function(){if("object"==typeof globalThis)return globalThis +try{return this||new Function("return this")()}catch(r){if("object"==typeof window)return window}}(),o.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),o.nmd=r=>(r.paths=[],r.children||(r.children=[]),r),(()=>{var r={178:0} +o.O.j=e=>0===r[e] +var e=(e,t)=>{var n,i,[a,u,l]=t,_=0 +if(a.some((e=>0!==r[e]))){for(n in u)o.o(u,n)&&(o.m[n]=u[n]) +if(l)var c=l(o)}for(e&&e(t);_o(3404))) +var n=o.O(void 0,[778],(()=>o(974))) +n=o.O(n),__ember_auto_import__=n})() diff --git a/agent/uiserver/dist/assets/chunk.336.f5cb05e551aa08eb7125.js b/agent/uiserver/dist/assets/chunk.336.f5cb05e551aa08eb7125.js deleted file mode 100644 index b4ef3eadadc1..000000000000 --- a/agent/uiserver/dist/assets/chunk.336.f5cb05e551aa08eb7125.js +++ /dev/null @@ -1,908 +0,0 @@ -/*! For license information please see chunk.336.f5cb05e551aa08eb7125.js.LICENSE.txt */ -(globalThis.webpackChunk_ember_auto_import_=globalThis.webpackChunk_ember_auto_import_||[]).push([[336],{3409:(e,t,n)=>{var r -e=n.nmd(e),function(){"use strict" -function i(e){return i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i(e)}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function s(e,t){for(var n=0;ne.length)&&(t=e.length) -for(var n=0,r=new Array(t);n1&&void 0!==arguments[1])||arguments[1],n=t&&q("array",e)?[]:{} -for(var r in e)if(E.call(e,r)){var i=e[r] -n[r]=i===Object(i)?j(i,t):i}return n}function N(e,t){if(e!==Object(e))return e -var n={} -for(var r in t)E.call(t,r)&&E.call(e,r)&&(n[r]=N(e[r],t[r])) -return n}function M(e,t,n){for(var r in t)E.call(t,r)&&(void 0===t[r]?delete e[r]:n&&void 0!==e[r]||(e[r]=t[r])) -return e}function O(e){if(void 0===e)return"undefined" -if(null===e)return"null" -var t=k.call(e).match(/^\[object\s(.*)\]$/),n=t&&t[1] -switch(n){case"Number":return isNaN(e)?"nan":"number" -case"String":case"Boolean":case"Array":case"Set":case"Map":case"Date":case"RegExp":case"Function":case"Symbol":return n.toLowerCase() -default:return i(e)}}function q(e,t){return O(t)===e}function A(e,t){for(var n=e+""+t,r=0,i=0;is.maxDepth)return"[object Array]" -this.up() -for(var r=e.length,i=new Array(r);r--;)i[r]=this.parse(e[r],void 0,t) -return this.down(),n("[",i,"]")}var o=/^function (\w+)/,s={parse:function(e,t,n){var r=(n=n||[]).indexOf(e) -if(-1!==r)return"recursion(".concat(r-n.length,")") -t=t||this.typeOf(e) -var o=this.parsers[t],s=i(o) -if("function"===s){n.push(e) -var a=o.call(this,e,n) -return n.pop(),a}return"string"===s?o:"[ERROR: Missing QUnit.dump formatter for type "+t+"]"},typeOf:function(e){var t -return t=null===e?"null":void 0===e?"undefined":q("regexp",e)?"regexp":q("date",e)?"date":q("function",e)?"function":void 0!==e.setInterval&&void 0!==e.document&&void 0===e.nodeType?"window":9===e.nodeType?"document":e.nodeType?"node":function(e){return"[object Array]"===k.call(e)||"number"==typeof e.length&&void 0!==e.item&&(e.length?e.item(0)===e[0]:null===e.item(0)&&void 0===e[0])}(e)?"array":e.constructor===Error.prototype.constructor?"error":i(e),t},separator:function(){return this.multiline?this.HTML?"
":"\n":this.HTML?" ":" "},indent:function(e){if(!this.multiline)return"" -var t=this.indentChar -return this.HTML&&(t=t.replace(/\t/g," ").replace(/ /g," ")),new Array(this.depth+(e||0)).join(t)},up:function(e){this.depth+=e||1},down:function(e){this.depth-=e||1},setParser:function(e,t){this.parsers[e]=t},quote:e,literal:t,join:n,depth:1,maxDepth:F.maxDepth,parsers:{window:"[Window]",document:"[Document]",error:function(e){return'Error("'+e.message+'")'},unknown:"[Unknown]",null:"null",undefined:"undefined",function:function(e){var t="function",r="name"in e?e.name:(o.exec(e)||[])[1] -return r&&(t+=" "+r),n(t=[t+="(",s.parse(e,"functionArgs"),"){"].join(""),s.parse(e,"functionCode"),"}")},array:r,nodelist:r,arguments:r,object:function(e,t){var r=[] -if(s.maxDepth&&s.depth>s.maxDepth)return"[object Object]" -s.up() -var i=[] -for(var o in e)i.push(o) -var a=["message","name"] -for(var u in a){var c=a[u] -c in e&&!T(c,i)&&i.push(c)}i.sort() -for(var l=0;l",r=e.nodeName.toLowerCase(),i=t+r,o=e.attributes -if(o)for(var a=0;a0&&void 0!==arguments[0]?arguments[0]:{passed:0,failed:0,skipped:0,todo:0,total:0} -return e.failed+=this.globalFailureCount,e.total+=this.globalFailureCount,e=this.tests.reduce((function(e,t){return t.valid&&(e[t.getStatus()]++,e.total++),e}),e),this.childSuites.reduce((function(e,t){return t.getTestCounts(e)}),e)}},{key:"getStatus",value:function(){var e=this.getTestCounts(),t=e.total,n=e.failed,r=e.skipped,i=e.todo -return n?"failed":r===t?"skipped":i===t?"todo":"passed"}}]),e}(),B=[],U=new L -function H(e,t,n){var r=B.length?B.slice(-1)[0]:null,i=null!==r?[r.name,e].join(" > "):e,o=r?r.suiteReport:U,s=null!==r&&r.skip||n.skip,a=null!==r&&r.todo||n.todo,u={} -r&&M(u,r.testEnvironment),M(u,t) -var c={name:i,parentModule:r,hooks:{before:[],beforeEach:[],afterEach:[],after:[]},testEnvironment:u,tests:[],moduleId:A(i),testsRun:0,testsIgnored:0,childModules:[],suiteReport:new L(e,o),stats:null,skip:s,todo:!s&&a,ignored:n.ignored||!1} -return r&&r.childModules.push(c),F.modules.push(c),c}function z(e,t,n){var r=t[n] -"function"==typeof r&&e[n].push(r),delete t[n]}function $(e,t){return function(n){F.currentModule!==e&&x.warn("The `"+t+"` hook was called inside the wrong module (`"+F.currentModule.name+"`). Instead, use hooks provided by the callback to the containing module (`"+e.name+"`). This will become an error in QUnit 3.0."),e.hooks[t].push(n)}}function Q(e,t,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{} -"function"==typeof t&&(n=t,t=void 0) -var i=H(e,t,r),o=i.testEnvironment,s=i.hooks -z(s,o,"before"),z(s,o,"beforeEach"),z(s,o,"afterEach"),z(s,o,"after") -var a={before:$(i,"before"),beforeEach:$(i,"beforeEach"),afterEach:$(i,"afterEach"),after:$(i,"after")},u=F.currentModule -if(F.currentModule=i,"function"==typeof n){B.push(i) -try{var c=n.call(i.testEnvironment,a) -c&&"function"==typeof c.then&&x.warn("Returning a promise from a module callback is not supported. Instead, use hooks for async behavior. This will become an error in QUnit 3.0.")}finally{B.pop(),F.currentModule=i.parentModule||u}}}var G=!1 -function W(e,t,n){var r,i=G&&(r=F.modules.filter((function(e){return!e.ignored})).map((function(e){return e.moduleId})),!B.some((function(e){return r.includes(e.moduleId)}))) -Q(e,t,n,{ignored:i})}W.only=function(){G||(F.modules.length=0,F.queue.length=0,F.currentModule.ignored=!0),G=!0,Q.apply(void 0,arguments)},W.skip=function(e,t,n){G||Q(e,t,n,{skip:!0})},W.todo=function(e,t,n){G||Q(e,t,n,{todo:!0})} -var Y=(J(0)||"").replace(/(:\d+)+\)?/,"").replace(/.+[/\\]/,"") -function V(e,t){if(t=void 0===t?4:t,e&&e.stack){var n=e.stack.split("\n") -if(/^error$/i.test(n[0])&&n.shift(),Y){for(var r=[],i=t;i0&&this.test.internalResetTimeout(this.test.timeout))}},{key:"step",value:function(e){var t=e,n=!!e -this.test.steps.push(e),void 0===e||""===e?t="You must provide a message to assert.step":"string"!=typeof e&&(t="You must provide a string value to assert.step",n=!1),this.pushResult({result:n,message:t})}},{key:"verifySteps",value:function(e,t){var n=this.test.steps.slice() -this.deepEqual(n,e,t),this.test.steps.length=0}},{key:"expect",value:function(e){if(1!==arguments.length)return this.test.expected -this.test.expected=e}},{key:"async",value:function(e){var t=void 0===e?1:e -return this.test.internalStop(t)}},{key:"push",value:function(t,n,r,i,o){return x.warn("assert.push is deprecated and will be removed in QUnit 3.0. Please use assert.pushResult instead (https://api.qunitjs.com/assert/pushResult)."),(this instanceof e?this:F.current.assert).pushResult({result:t,actual:n,expected:r,message:i,negative:o})}},{key:"pushResult",value:function(t){var n=this,r=n instanceof e&&n.test||F.current -if(!r)throw new Error("assertion outside test context, in "+J(2)) -return n instanceof e||(n=r.assert),n.test.pushResult(t)}},{key:"ok",value:function(e,t){t||(t=e?"okay":"failed, expected argument to be truthy, was: ".concat(D.parse(e))),this.pushResult({result:!!e,actual:e,expected:!0,message:t})}},{key:"notOk",value:function(e,t){t||(t=e?"failed, expected argument to be falsy, was: ".concat(D.parse(e)):"okay"),this.pushResult({result:!e,actual:e,expected:!1,message:t})}},{key:"true",value:function(e,t){this.pushResult({result:!0===e,actual:e,expected:!0,message:t})}},{key:"false",value:function(e,t){this.pushResult({result:!1===e,actual:e,expected:!1,message:t})}},{key:"equal",value:function(e,t,n){var r=t==e -this.pushResult({result:r,actual:e,expected:t,message:n})}},{key:"notEqual",value:function(e,t,n){var r=t!=e -this.pushResult({result:r,actual:e,expected:t,message:n,negative:!0})}},{key:"propEqual",value:function(e,t,n){e=j(e),t=j(t),this.pushResult({result:I(e,t),actual:e,expected:t,message:n})}},{key:"notPropEqual",value:function(e,t,n){e=j(e),t=j(t),this.pushResult({result:!I(e,t),actual:e,expected:t,message:n,negative:!0})}},{key:"propContains",value:function(e,t,n){e=N(e,t),t=j(t,!1),this.pushResult({result:I(e,t),actual:e,expected:t,message:n})}},{key:"notPropContains",value:function(e,t,n){e=N(e,t),t=j(t),this.pushResult({result:!I(e,t),actual:e,expected:t,message:n,negative:!0})}},{key:"deepEqual",value:function(e,t,n){this.pushResult({result:I(e,t),actual:e,expected:t,message:n})}},{key:"notDeepEqual",value:function(e,t,n){this.pushResult({result:!I(e,t),actual:e,expected:t,message:n,negative:!0})}},{key:"strictEqual",value:function(e,t,n){this.pushResult({result:t===e,actual:e,expected:t,message:n})}},{key:"notStrictEqual",value:function(e,t,n){this.pushResult({result:t!==e,actual:e,expected:t,message:n,negative:!0})}},{key:"throws",value:function(t,n,r){var i=u(Z(n,r,"throws"),2) -n=i[0],r=i[1] -var o=this instanceof e&&this.test||F.current -if("function"==typeof t){var s,a=!1 -o.ignoreGlobalErrors=!0 -try{t.call(o.testEnvironment)}catch(e){s=e}if(o.ignoreGlobalErrors=!1,s){var c=u(K(s,n,r),3) -a=c[0],n=c[1],r=c[2]}o.assert.pushResult({result:a,actual:s&&R(s),expected:n,message:r})}else{var l='The value provided to `assert.throws` in "'+o.testName+'" was not a function.' -o.assert.pushResult({result:!1,actual:t,message:l})}}},{key:"rejects",value:function(t,n,r){var i=u(Z(n,r,"rejects"),2) -n=i[0],r=i[1] -var o=this instanceof e&&this.test||F.current,s=t&&t.then -if("function"==typeof s){var a=this.async() -return s.call(t,(function(){var e='The promise returned by the `assert.rejects` callback in "'+o.testName+'" did not reject.' -o.assert.pushResult({result:!1,message:e,actual:t}),a()}),(function(e){var t,i=u(K(e,n,r),3) -t=i[0],n=i[1],r=i[2],o.assert.pushResult({result:t,actual:e&&R(e),expected:n,message:r}),a()}))}var c='The value provided to `assert.rejects` in "'+o.testName+'" was not a promise.' -o.assert.pushResult({result:!1,message:c,actual:t})}}]),e}() -function Z(e,t,n){var r=O(e) -if("string"===r){if(void 0===t)return t=e,[e=void 0,t] -throw new Error("assert."+n+" does not accept a string value for the expected argument.\nUse a non-string object value (e.g. RegExp or validator function) instead if necessary.")}if(e&&"regexp"!==r&&"function"!==r&&"object"!==r)throw new Error("Invalid expected value type ("+r+") provided to assert."+n+".") -return[e,t]}function K(e,t,n){var r=!1,i=O(t) -if(t){if("regexp"===i)r=t.test(R(e)),t=String(t) -else if("function"===i&&void 0!==t.prototype&&e instanceof t)r=!0 -else if("object"===i)r=e instanceof t.constructor&&e.name===t.name&&e.message===t.message,t=R(t) -else if("function"===i)try{r=!0===t.call({},e),t=null}catch(e){t=R(e)}}else r=!0 -return[r,t,n]}X.prototype.raises=X.prototype.throws -var ee=Object.create(null),te=["error","runStart","suiteStart","testStart","assertion","testEnd","suiteEnd","runEnd"] -function ne(e,t){if("string"!=typeof e)throw new TypeError("eventName must be a string when emitting an event") -for(var n=ee[e],r=n?c(n):[],i=0;i0&&ue--,le()):function(){var e -if(0===F.stats.testCount&&!0===F.failOnZeroTests)return e=F.filter&&F.filter.length?new Error('No tests matched the filter "'.concat(F.filter,'".')):F.module&&F.module.length?new Error('No tests matched the module "'.concat(F.module,'".')):F.moduleId&&F.moduleId.length?new Error('No tests matched the moduleId "'.concat(F.moduleId,'".')):F.testId&&F.testId.length?new Error('No tests matched the testId "'.concat(F.testId,'".')):new Error("No tests were run."),we("global failure",M((function(t){t.pushResult({result:!1,message:e.message,source:e.stack})}),{validTest:!0})),void le() -var t=F.storage,n=Math.round(S.now()-F.started),r=F.stats.all-F.stats.bad -he.finished=!0,ne("runEnd",U.end(!0)),se("done",{passed:r,failed:F.stats.bad,total:F.stats.all,runtime:n}).then((function(){if(t&&0===F.stats.bad)for(var e=t.length-1;e>=0;e--){var n=t.key(e) -0===n.indexOf("qunit-test-")&&t.removeItem(n)}}))}())}function fe(e){if(ce.length&&!F.blocking){var t=S.now()-e -if(!g||F.updateRate<=0||t>>17,(t^=t<<5)<0&&(t+=4294967296),t/4294967296}}(n)) -var r=Math.floor(ae()*(F.queue.length-ue+1)) -F.queue.splice(ue+r,0,e)}else F.queue.push(e)},advance:le,taskCount:function(){return ce.length}},de=function(){function e(t,n,r){o(this,e),this.name=t,this.suiteName=n.name,this.fullName=n.fullName.concat(t),this.runtime=0,this.assertions=[],this.skipped=!!r.skip,this.todo=!!r.todo,this.valid=r.valid,this._startTime=0,this._endTime=0,n.pushTest(this)}return a(e,[{key:"start",value:function(e){return e&&(this._startTime=S.now(),S.mark("qunit_test_start")),{name:this.name,suiteName:this.suiteName,fullName:this.fullName.slice()}}},{key:"end",value:function(e){if(e&&(this._endTime=S.now(),S)){S.mark("qunit_test_end") -var t=this.fullName.join(" – ") -S.measure("QUnit Test: ".concat(t),"qunit_test_start","qunit_test_end")}return M(this.start(),{runtime:this.getRuntime(),status:this.getStatus(),errors:this.getFailedAssertions(),assertions:this.getAssertions()})}},{key:"pushAssertion",value:function(e){this.assertions.push(e)}},{key:"getRuntime",value:function(){return Math.round(this._endTime-this._startTime)}},{key:"getStatus",value:function(){return this.skipped?"skipped":(this.getFailedAssertions().length>0?this.todo:!this.todo)?this.todo?"todo":"passed":"failed"}},{key:"getFailedAssertions",value:function(){return this.assertions.filter((function(e){return!e.passed}))}},{key:"getAssertions",value:function(){return this.assertions.slice()}},{key:"slimAssertions",value:function(){this.assertions=this.assertions.map((function(e){return delete e.actual,delete e.expected,e}))}}]),e}() -function pe(e){if(this.expected=null,this.assertions=[],this.module=F.currentModule,this.steps=[],this.timeout=void 0,this.data=void 0,this.withData=!1,this.pauses=new w,this.nextPauseId=1,this.stackOffset=3,M(this,e),this.module.skip?(this.skip=!0,this.todo=!1):this.module.todo&&!this.skip&&(this.todo=!0),he.finished)x.warn("Unexpected test after runEnd. This is unstable and will fail in QUnit 3.0.") -else{if(!this.skip&&"function"!=typeof this.callback){var t=this.todo?"QUnit.todo":"QUnit.test" -throw new TypeError("You must provide a callback to ".concat(t,'("').concat(this.testName,'")'))}++pe.count,this.errorForStack=new Error,this.callback&&this.callback.validTest&&(this.errorForStack.stack=void 0),this.testReport=new de(this.testName,this.module.suiteReport,{todo:this.todo,skip:this.skip,valid:this.valid()}) -for(var n=0,r=this.module.tests;n0&&ge("Test did not finish synchronously even though assert.timeout( 0 ) was used.",J(2))}},after:function(){!function(){var e=F.pollution -ve() -var t=C(F.pollution,e) -t.length>0&&ge("Introduced global variable(s): "+t.join(", ")) -var n=C(e,F.pollution) -n.length>0&&ge("Deleted global variable(s): "+n.join(", "))}()},queueGlobalHook:function(e,t){var n=this -return function(){var r -if(F.current=n,F.notrycatch)r=e.call(n.testEnvironment,n.assert) -else try{r=e.call(n.testEnvironment,n.assert)}catch(e){return void n.pushFailure("Global "+t+" failed on "+n.testName+": "+R(e),V(e,0))}n.resolvePromise(r,t)}},queueHook:function(e,t,n){var r=this,i=function(){var n=e.call(r.testEnvironment,r.assert) -r.resolvePromise(n,t)} -return function(){if("before"===t){if(0!==n.testsRun)return -r.preserveEnvironment=!0}if("after"!==t||function(e){return e.testsRun===Se(e).filter((function(e){return!e.skip})).length-1}(n)||!(F.queue.length>0||he.taskCount()>2))if(F.current=r,F.notrycatch)i() -else try{i()}catch(e){r.pushFailure(t+" failed on "+r.testName+": "+(e.message||e),V(e,0))}}},hooks:function(e){var t=[] -return this.skip||(function(n){if(("beforeEach"===e||"afterEach"===e)&&F.globalHooks[e])for(var r=0;r Test: "+n+"\n> Message: "+t+"\n")}var r={module:this.module.name,name:this.testName,result:e.result,message:e.message,actual:e.actual,testId:this.testId,negative:e.negative||!1,runtime:Math.round(S.now()-this.started),todo:!!this.todo} -if(E.call(e,"expected")&&(r.expected=e.expected),!e.result){var i=e.source||J() -i&&(r.source=i)}this.logAssertion(r),this.assertions.push({result:!!e.result,message:e.message})},pushFailure:function(e,t,n){if(!(this instanceof pe))throw new Error("pushFailure() assertion outside test context, was "+J(2)) -this.pushResult({result:!1,message:e||"error",actual:n||null,source:t})},logAssertion:function(e){se("log",e) -var t={passed:e.result,actual:e.actual,expected:e.expected,message:e.message,stack:e.source,todo:e.todo} -this.testReport.pushAssertion(t),ne("assertion",t)},internalResetTimeout:function(e){v(F.timeout),F.timeout=g(F.timeoutHandler(e),e)},internalStop:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1 -F.blocking=!0 -var t,n=this,r=this.nextPauseId++,i={cancelled:!1,remaining:e} -function o(){if(!i.cancelled){if(void 0===F.current)throw new Error("Unexpected release of async pause after tests finished.\n"+"> Test: ".concat(n.testName," [async #").concat(r,"]")) -if(F.current!==n)throw new Error("Unexpected release of async pause during a different test.\n"+"> Test: ".concat(n.testName," [async #").concat(r,"]")) -if(i.remaining<=0)throw new Error("Tried to release async pause that was already released.\n"+"> Test: ".concat(n.testName," [async #").concat(r,"]")) -i.remaining--,0===i.remaining&&n.pauses.delete(r),_e(n)}}return n.pauses.set(r,i),g&&("number"==typeof n.timeout?t=n.timeout:"number"==typeof F.testTimeout&&(t=F.testTimeout),"number"==typeof t&&t>0&&(F.timeoutHandler=function(e){return function(){F.timeout=null,i.cancelled=!0,n.pauses.delete(r),n.pushFailure("Test took longer than ".concat(e,"ms; test timed out."),J(2)),_e(n)}},v(F.timeout),F.timeout=g(F.timeoutHandler(t),t))),o},resolvePromise:function(e,t){if(null!=e){var n=this,r=e.then -if("function"==typeof r){var i=n.internalStop(),o=function(){i()} -F.notrycatch?r.call(e,o):r.call(e,o,(function(e){var r="Promise rejected "+(t?t.replace(/Each$/,""):"during")+' "'+n.testName+'": '+(e&&e.message||e) -n.pushFailure(r,V(e,0)),ve(),Ee(n)}))}}},valid:function(){if(this.callback&&this.callback.validTest)return!0 -if(!function e(t,n){return!n||!n.length||T(t.moduleId,n)||t.parentModule&&e(t.parentModule,n)}(this.module,F.moduleId))return!1 -if(F.testId&&F.testId.length&&!T(this.testId,F.testId))return!1 -var e=F.module&&F.module.toLowerCase() -if(!function e(t,n){return!n||(t.name?t.name.toLowerCase():null)===n||!!t.parentModule&&e(t.parentModule,n)}(this.module,e))return!1 -var t=F.filter -if(!t)return!0 -var n=/^(!?)\/([\w\W]*)\/(i?$)/.exec(t),r=this.module.name+": "+this.testName -return n?this.regexFilter(!!n[1],n[2],n[3],r):this.stringFilter(t,r)},regexFilter:function(e,t,n,r){return new RegExp(t,n).test(r)!==e},stringFilter:function(e,t){e=e.toLowerCase(),t=t.toLowerCase() -var n="!"!==e.charAt(0) -return n||(e=e.slice(1)),-1!==t.indexOf(e)?n:!n}} -var me=!1 -function ye(e){me||F.currentModule.ignored||new pe(e).queue()}function be(e){F.currentModule.ignored||(me||(F.queue.length=0,me=!0),new pe(e).queue())}function we(e,t){ye({testName:e,callback:t})}function xe(e,t){return"".concat(e," [").concat(t,"]")}function ke(e,t){if(Array.isArray(e))for(var n=0;n0||(g?(v(F.timeout),F.timeout=g((function(){e.pauses.size>0||(v(F.timeout),F.timeout=null,F.blocking=!1,he.advance())}))):(F.blocking=!1,he.advance()))}function Se(e){for(var t=[].concat(e.tests),n=c(e.childModules);n.length;){var r=n.shift() -t.push.apply(t,r.tests),n.push.apply(n,c(r.childModules))}return t}function Ce(e){return e.testsRun+e.testsIgnored===Se(e).length}function Te(e){for(e.testsIgnored++;e=e.parentModule;)e.testsIgnored++}M(we,{todo:function(e,t){ye({testName:e,callback:t,todo:!0})},skip:function(e){ye({testName:e,skip:!0})},only:function(e,t){be({testName:e,callback:t})},each:function(e,t,n){ke(t,(function(t,r){ye({testName:xe(e,r),callback:n,withData:!0,stackOffset:5,data:t})}))}}),we.todo.each=function(e,t,n){ke(t,(function(t,r){ye({testName:xe(e,r),callback:n,todo:!0,withData:!0,stackOffset:5,data:t})}))},we.skip.each=function(e,t){ke(t,(function(t,n){ye({testName:xe(e,n),stackOffset:5,skip:!0})}))},we.only.each=function(e,t,n){ke(t,(function(t,r){be({testName:xe(e,r),callback:n,withData:!0,stackOffset:5,data:t})}))} -var je,Ne,Me,Oe,qe=function(){function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -o(this,e),this.log=n.log||Function.prototype.bind.call(p.log,p),t.on("error",this.onError.bind(this)),t.on("runStart",this.onRunStart.bind(this)),t.on("testStart",this.onTestStart.bind(this)),t.on("testEnd",this.onTestEnd.bind(this)),t.on("runEnd",this.onRunEnd.bind(this))}return a(e,[{key:"onError",value:function(e){this.log("error",e)}},{key:"onRunStart",value:function(e){this.log("runStart",e)}},{key:"onTestStart",value:function(e){this.log("testStart",e)}},{key:"onTestEnd",value:function(e){this.log("testEnd",e)}},{key:"onRunEnd",value:function(e){this.log("runEnd",e)}}],[{key:"init",value:function(t,n){return new e(t,n)}}]),e}(),Ae=!0 -if("undefined"!=typeof process){var Re=process.env -je=Re.FORCE_COLOR,Ne=Re.NODE_DISABLE_COLORS,Me=Re.NO_COLOR,Oe=Re.TERM,Ae=process.stdout&&process.stdout.isTTY}var Ie={enabled:!Ne&&null==Me&&"dumb"!==Oe&&(null!=je&&"0"!==je||Ae),reset:Pe(0,0),bold:Pe(1,22),dim:Pe(2,22),italic:Pe(3,23),underline:Pe(4,24),inverse:Pe(7,27),hidden:Pe(8,28),strikethrough:Pe(9,29),black:Pe(30,39),red:Pe(31,39),green:Pe(32,39),yellow:Pe(33,39),blue:Pe(34,39),magenta:Pe(35,39),cyan:Pe(36,39),white:Pe(37,39),gray:Pe(90,39),grey:Pe(90,39),bgBlack:Pe(40,49),bgRed:Pe(41,49),bgGreen:Pe(42,49),bgYellow:Pe(43,49),bgBlue:Pe(44,49),bgMagenta:Pe(45,49),bgCyan:Pe(46,49),bgWhite:Pe(47,49)} -function Fe(e,t){for(var n,r=0,i="",o="";r1&&void 0!==arguments[1]?arguments[1]:4 -if(void 0===e&&(e=String(e)),"number"!=typeof e||isFinite(e)||(e=String(e)),"number"==typeof e)return JSON.stringify(e) -if("string"==typeof e){var n=/['"\\/[{}\]\r\n]/,r=/[-?:,[\]{}#&*!|=>'"%@`]/,i=/(^\s|\s$)/,o=/^[\d._-]+$/,s=/^(true|false|y|n|yes|no|on|off)$/i -if(""===e||n.test(e)||r.test(e[0])||i.test(e)||o.test(e)||s.test(e)){if(!/\n/.test(e))return JSON.stringify(e) -var a=new Array(t+1).join(" "),u=e.match(/\n+$/),c=u?u[0].length:0 -if(1===c){var l=e.replace(/\n$/,"").split("\n").map((function(e){return a+e})) -return"|\n"+l.join("\n")}var f=e.split("\n").map((function(e){return a+e})) -return"|+\n"+f.join("\n")}return e}return JSON.stringify(Be(e),null,2)}function Be(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[] -if(-1!==t.indexOf(e))return"[Circular]" -var n,r=Object.prototype.toString.call(e).replace(/^\[.+\s(.+?)]$/,"$1").toLowerCase() -switch(r){case"array":t.push(e),n=e.map((function(e){return Be(e,t)})),t.pop() -break -case"object":t.push(e),n={},Object.keys(e).forEach((function(r){n[r]=Be(e[r],t)})),t.pop() -break -default:n=e}return n}var Ue=function(){function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -o(this,e),this.log=n.log||Function.prototype.bind.call(p.log,p),this.testCount=0,this.ended=!1,this.bailed=!1,t.on("error",this.onError.bind(this)),t.on("runStart",this.onRunStart.bind(this)),t.on("testEnd",this.onTestEnd.bind(this)),t.on("runEnd",this.onRunEnd.bind(this))}return a(e,[{key:"onRunStart",value:function(e){this.log("TAP version 13")}},{key:"onError",value:function(e){this.bailed||(this.bailed=!0,this.ended||(this.testCount=this.testCount+1,this.log(Ie.red("not ok ".concat(this.testCount," global failure"))),this.logError(e)),this.log("Bail out! "+R(e).split("\n")[0]),this.ended&&this.logError(e))}},{key:"onTestEnd",value:function(e){var t=this -this.testCount=this.testCount+1,"passed"===e.status?this.log("ok ".concat(this.testCount," ").concat(e.fullName.join(" > "))):"skipped"===e.status?this.log(Ie.yellow("ok ".concat(this.testCount," # SKIP ").concat(e.fullName.join(" > ")))):"todo"===e.status?(this.log(Ie.cyan("not ok ".concat(this.testCount," # TODO ").concat(e.fullName.join(" > ")))),e.errors.forEach((function(e){return t.logAssertion(e,"todo")}))):(this.log(Ie.red("not ok ".concat(this.testCount," ").concat(e.fullName.join(" > ")))),e.errors.forEach((function(e){return t.logAssertion(e)})))}},{key:"onRunEnd",value:function(e){this.ended=!0,this.log("1..".concat(e.testCounts.total)),this.log("# pass ".concat(e.testCounts.passed)),this.log(Ie.yellow("# skip ".concat(e.testCounts.skipped))),this.log(Ie.cyan("# todo ".concat(e.testCounts.todo))),this.log(Ie.red("# fail ".concat(e.testCounts.failed)))}},{key:"logAssertion",value:function(e,t){var n=" ---" -n+="\n message: ".concat(Le(e.message||"failed")),n+="\n severity: ".concat(Le(t||"failed")),De.call(e,"actual")&&(n+="\n actual : ".concat(Le(e.actual))),De.call(e,"expected")&&(n+="\n expected: ".concat(Le(e.expected))),e.stack&&(n+="\n stack: ".concat(Le(e.stack+"\n"))),n+="\n ...",this.log(n)}},{key:"logError",value:function(e){var t=" ---" -t+="\n message: ".concat(Le(R(e))),t+="\n severity: ".concat(Le("failed")),e&&e.stack&&(t+="\n stack: ".concat(Le(e.stack+"\n"))),t+="\n ...",this.log(t)}}],[{key:"init",value:function(t,n){return new e(t,n)}}]),e}(),He={console:qe,tap:Ue} -function ze(e){return function(t){F.globalHooks[e]||(F.globalHooks[e]=[]),F.globalHooks[e].push(t)}}var $e={beforeEach:ze("beforeEach"),afterEach:ze("afterEach")} -function Qe(e){F.current?F.current.assert.pushResult({result:!1,message:"global failure: ".concat(R(e)),source:e&&e.stack||J(2)}):(U.globalFailureCount++,F.stats.bad++,F.stats.all++,ne("error",e))}var Ge={} -F.currentModule.suiteReport=U -var We=!1,Ye=!1 -function Ve(){Ye=!0,g?g((function(){Xe()})):Xe()}function Je(){F.blocking=!1,he.advance()}function Xe(){if(F.started)Je() -else{F.started=S.now(),""===F.modules[0].name&&0===F.modules[0].tests.length&&F.modules.shift() -for(var e=[],t=0;t1)throw new Error("Called start() outside of a test context too many times") -if(F.autostart)throw new Error("Called start() outside of a test context when QUnit.config.autostart was true") -if(!F.pageLoaded)return F.autostart=!0,void(m||Ge.load()) -Ve()},onUnhandledRejection:function(e){x.warn("QUnit.onUnhandledRejection is deprecated and will be removed in QUnit 3.0. Please use QUnit.onUncaughtException instead."),Qe(e)},extend:function(){x.warn("QUnit.extend is deprecated and will be removed in QUnit 3.0. Please use Object.assign instead.") -for(var e=arguments.length,t=new Array(e),n=0;n=0;--n){var r=e[n] -if(null!==r){var i=r.score -i>t&&(t=i)}}return-9007199254740991===t?null:t}function l(e,t){var n=e[t] -if(void 0!==n)return n -var r=t -Array.isArray(t)||(r=t.split(".")) -for(var i=r.length,o=-1;e&&++o>1]=e[n],i=1+(n<<1)}for(var s=n-1>>1;n>0&&r.score>1)e[n]=e[s] -e[n]=r}return n.add=function(n){var r=t -e[t++]=n -for(var i=r-1>>1;r>0&&n.score>1)e[r]=e[i] -e[r]=n},n.poll=function(){if(0!==t){var n=e[0] -return e[0]=e[--t],r(),n}},n.peek=function(n){if(0!==t)return e[0]},n.replaceTop=function(t){e[0]=t,r()},n},d=h() -return function t(i){var p={single:function(e,t,n){return"farzher"==e?{target:"farzher was here (^-^*)/",score:0,indexes:[0,1,2,3,4,5,6]}:e?(f(e)||(e=p.getPreparedSearch(e)),t?(f(t)||(t=p.getPrepared(t)),((n&&void 0!==n.allowTypo?n.allowTypo:!i||void 0===i.allowTypo||i.allowTypo)?p.algorithm:p.algorithmNoTypo)(e,t,e[0])):null):null},go:function(e,t,n){if("farzher"==e)return[{target:"farzher was here (^-^*)/",score:0,indexes:[0,1,2,3,4,5,6],obj:t?t[0]:null}] -if(!e)return o -var r=(e=p.prepareSearch(e))[0],s=n&&n.threshold||i&&i.threshold||-9007199254740991,a=n&&n.limit||i&&i.limit||9007199254740991,u=(n&&void 0!==n.allowTypo?n.allowTypo:!i||void 0===i.allowTypo||i.allowTypo)?p.algorithm:p.algorithmNoTypo,h=0,g=0,v=t.length -if(n&&n.keys)for(var m=n.scoreFn||c,y=n.keys,b=y.length,w=v-1;w>=0;--w){for(var x=t[w],k=new Array(b),E=b-1;E>=0;--E)(C=l(x,S=y[E]))?(f(C)||(C=p.getPrepared(C)),k[E]=u(e,C,r)):k[E]=null -k.obj=x -var _=m(k) -null!==_&&(_d.peek().score&&d.replaceTop(k))))}else if(n&&n.key){var S=n.key -for(w=v-1;w>=0;--w)(C=l(x=t[w],S))&&(f(C)||(C=p.getPrepared(C)),null!==(T=u(e,C,r))&&(T.scored.peek().score&&d.replaceTop(T)))))}else for(w=v-1;w>=0;--w){var C,T;(C=t[w])&&(f(C)||(C=p.getPrepared(C)),null!==(T=u(e,C,r))&&(T.scored.peek().score&&d.replaceTop(T)))))}if(0===h)return o -var j=new Array(h) -for(w=h-1;w>=0;--w)j[w]=d.poll() -return j.total=h+g,j},goAsync:function(t,n,r){var s=!1,a=new Promise((function(a,u){if("farzher"==t)return a([{target:"farzher was here (^-^*)/",score:0,indexes:[0,1,2,3,4,5,6],obj:n?n[0]:null}]) -if(!t)return a(o) -var d=(t=p.prepareSearch(t))[0],g=h(),v=n.length-1,m=r&&r.threshold||i&&i.threshold||-9007199254740991,y=r&&r.limit||i&&i.limit||9007199254740991,b=(r&&void 0!==r.allowTypo?r.allowTypo:!i||void 0===i.allowTypo||i.allowTypo)?p.algorithm:p.algorithmNoTypo,w=0,x=0 -function k(){if(s)return u("canceled") -var i=Date.now() -if(r&&r.keys)for(var h=r.scoreFn||c,E=r.keys,_=E.length;v>=0;--v){if(v%1e3==0&&Date.now()-i>=10)return void(e?setImmediate(k):setTimeout(k)) -for(var S=n[v],C=new Array(_),T=_-1;T>=0;--T)(M=l(S,N=E[T]))?(f(M)||(M=p.getPrepared(M)),C[T]=b(t,M,d)):C[T]=null -C.obj=S -var j=h(C) -null!==j&&(jg.peek().score&&g.replaceTop(C))))}else if(r&&r.key)for(var N=r.key;v>=0;--v){if(v%1e3==0&&Date.now()-i>=10)return void(e?setImmediate(k):setTimeout(k));(M=l(S=n[v],N))&&(f(M)||(M=p.getPrepared(M)),null!==(O=b(t,M,d))&&(O.scoreg.peek().score&&g.replaceTop(O)))))}else for(;v>=0;--v){if(v%1e3==0&&Date.now()-i>=10)return void(e?setImmediate(k):setTimeout(k)) -var M,O;(M=n[v])&&(f(M)||(M=p.getPrepared(M)),null!==(O=b(t,M,d))&&(O.scoreg.peek().score&&g.replaceTop(O)))))}if(0===w)return a(o) -for(var q=new Array(w),A=w-1;A>=0;--A)q[A]=g.poll() -q.total=w+x,a(q)}e?setImmediate(k):k()})) -return a.cancel=function(){s=!0},a},highlight:function(e,t,n){if("function"==typeof t)return p.highlightCallback(e,t) -if(null===e)return null -void 0===t&&(t=""),void 0===n&&(n="") -for(var r="",i=0,o=!1,s=e.target,a=s.length,u=e.indexes,c=0;c999)return p.prepare(e) -var t=n.get(e) -return void 0!==t||(t=p.prepare(e),n.set(e,t)),t},getPreparedSearch:function(e){if(e.length>999)return p.prepareSearch(e) -var t=r.get(e) -return void 0!==t||(t=p.prepareSearch(e),r.set(e,t)),t},algorithm:function(e,t,n){for(var r=t._targetLowerCodes,i=e.length,o=r.length,u=0,c=0,l=0,f=0;;){if(n===r[c]){if(s[f++]=c,++u===i)break -n=e[0===l?u:l===u?u+1:l===u-1?u-1:u]}if(++c>=o)for(;;){if(u<=1)return null -if(0===l){if(n===e[--u])continue -l=u}else{if(1===l)return null -if((n=e[1+(u=--l)])===e[u])continue}c=s[(f=u)-1]+1 -break}}u=0 -var h=0,d=!1,g=0,v=t._nextBeginningIndexes -null===v&&(v=t._nextBeginningIndexes=p.prepareNextBeginningIndexes(t.target)) -var m=c=0===s[0]?0:v[s[0]-1] -if(c!==o)for(;;)if(c>=o){if(u<=0){if(++h>i-2)break -if(e[h]===e[h+1])continue -c=m -continue}--u,c=v[a[--g]]}else if(e[0===h?u:h===u?u+1:h===u-1?u-1:u]===r[c]){if(a[g++]=c,++u===i){d=!0 -break}++c}else c=v[c] -if(d)var y=a,b=g -else y=s,b=f -for(var w=0,x=-1,k=0;k=0;--k)t.indexes[k]=y[k] -return t},algorithmNoTypo:function(e,t,n){for(var r=t._targetLowerCodes,i=e.length,o=r.length,u=0,c=0,l=0;;){if(n===r[c]){if(s[l++]=c,++u===i)break -n=e[u]}if(++c>=o)return null}u=0 -var f=!1,h=0,d=t._nextBeginningIndexes -if(null===d&&(d=t._nextBeginningIndexes=p.prepareNextBeginningIndexes(t.target)),(c=0===s[0]?0:d[s[0]-1])!==o)for(;;)if(c>=o){if(u<=0)break;--u,c=d[a[--h]]}else if(e[u]===r[c]){if(a[h++]=c,++u===i){f=!0 -break}++c}else c=d[c] -if(f)var g=a,v=h -else g=s,v=l -for(var m=0,y=-1,b=0;b=0;--b)t.indexes[b]=g[b] -return t},prepareLowerCodes:function(e){for(var t=e.length,n=[],r=e.toLowerCase(),i=0;i=65&&a<=90,c=u||a>=97&&a<=122||a>=48&&a<=57,l=u&&!i||!o||!c -i=u,o=c,l&&(n[r++]=s)}return n},prepareNextBeginningIndexes:function(e){for(var t=e.length,n=p.prepareBeginningIndexes(e),r=[],i=n[0],o=0,s=0;ss?r[s]=i:(i=n[++o],r[s]=void 0===i?t:i) -return r},cleanup:u,new:t} -return p}()},e.exports?e.exports=n():t.fuzzysort=n()}(Ze) -var Ke=Ze.exports,et={failedTests:[],defined:0,completed:0} -function tt(e){return e?(""+e).replace(/['"<>&]/g,(function(e){switch(e){case"'":return"'" -case'"':return""" -case"<":return"<" -case">":return">" -case"&":return"&"}})):""}!function(){if(d&&m){var e=Ge.config,t=[],n=!1,r=Object.prototype.hasOwnProperty,i=j({filter:void 0,module:void 0,moduleId:void 0,testId:void 0}),o=null -Ge.on("runStart",(function(e){et.defined=e.testCounts.total})),Ge.begin((function(t){!function(t){var n,s,a,u,l,f,p,b,E=_("qunit") -E&&(E.setAttribute("role","main"),E.innerHTML="

"+tt(m.title)+"

"+(!(n=Ge.config.testId)||n.length<=0?"":"
Rerunning selected tests: "+tt(n.join(", "))+" Run all tests
")+"

    "),(s=_("qunit-header"))&&(s.innerHTML=""+s.innerHTML+" "),(a=_("qunit-banner"))&&(a.className=""),p=_("qunit-tests"),(b=_("qunit-testresult"))&&b.parentNode.removeChild(b),p&&(p.innerHTML="",(b=m.createElement("p")).id="qunit-testresult",b.className="result",p.parentNode.insertBefore(b,p),b.innerHTML='
    Running...
     
    ',l=_("qunit-testresult-controls")),l&&l.appendChild(((f=m.createElement("button")).id="qunit-abort-tests-button",f.innerHTML="Abort",h(f,"click",S),f)),(u=_("qunit-userAgent"))&&(u.innerHTML="",u.appendChild(m.createTextNode("QUnit "+Ge.version+"; "+y.userAgent))),function(t){var n,i,s,a,u,l=_("qunit-testrunner-toolbar") -if(l){l.appendChild(((u=m.createElement("span")).innerHTML=function(){for(var t=!1,n=e.urlConfig,i="",o=0;o"+s.label+": "}else i+=""}return i}(),x(u,"qunit-url-config"),v(u.getElementsByTagName("input"),"change",T),v(u.getElementsByTagName("select"),"change",T),u)) -var f=m.createElement("span") -f.id="qunit-toolbar-filters",f.appendChild((n=m.createElement("form"),i=m.createElement("label"),s=m.createElement("input"),a=m.createElement("button"),x(n,"qunit-filter"),i.innerHTML="Filter: ",s.type="text",s.value=e.filter||"",s.name="filter",s.id="qunit-filter-input",a.innerHTML="Go",i.appendChild(s),n.appendChild(i),n.appendChild(m.createTextNode(" ")),n.appendChild(a),h(n,"submit",C),n)),f.appendChild(function(t){var n=null -if(o={options:t.modules.slice(),selectedMap:new w,isDirty:function(){return c(o.selectedMap.keys()).sort().join(",")!==c(n.keys()).sort().join(",")}},e.moduleId.length)for(var r=0;r","",u," assertions of ",e.stats.all," passed, ",e.stats.bad," failed.",A(et.failedTests)].join("") -if(a&&a.disabled){c="Tests aborted after "+t.runtime+" milliseconds." -for(var l=0;l":"Running: ",I(e.name,e.module),A(et.failedTests)].join(""))})),Ge.log((function(e){var t=_("qunit-test-output-"+e.testId) -if(t){var n,i,o,s=tt(e.message)||(e.result?"okay":"failed") -s=""+s+"",s+="@ "+e.runtime+" ms" -var a=!1 -!e.result&&r.call(e,"expected")?(n=e.negative?"NOT "+Ge.dump.parse(e.expected):Ge.dump.parse(e.expected),i=Ge.dump.parse(e.actual),s+="",i!==n?(s+="","number"==typeof e.actual&&"number"==typeof e.expected?isNaN(e.actual)||isNaN(e.expected)||(a=!0,o=((o=e.actual-e.expected)>0?"+":"")+o):"boolean"!=typeof e.actual&&"boolean"!=typeof e.expected&&(a=P(o=Ge.diff(n,i)).length!==P(n).length+P(i).length),a&&(s+="")):-1!==n.indexOf("[object Array]")||-1!==n.indexOf("[object Object]")?s+="":s+="",e.source&&(s+=""),s+="
    Expected:
    "+tt(n)+"
    Result:
    "+tt(i)+"
    Diff:
    "+o+"
    Message: Diff suppressed as the depth of object is more than current max depth ("+Ge.config.maxDepth+").

    Hint: Use QUnit.dump.maxDepth to run with a higher max depth or Rerun without max depth.

    Message: Diff suppressed as the expected and actual results have an equivalent serialization
    Source:
    "+tt(e.source)+"
    "):!e.result&&e.source&&(s+="
    Source:
    "+tt(e.source)+"
    ") -var u=t.getElementsByTagName("ol")[0],c=m.createElement("li") -c.className=e.result?"pass":"fail",c.innerHTML=s,u.appendChild(c)}})),Ge.testDone((function(r){var i=_("qunit-tests"),o=_("qunit-test-output-"+r.testId) -if(i&&o){var s -E(o,"running"),s=r.failed>0?"failed":r.todo?"todo":r.skipped?"skipped":"passed" -var a=o.getElementsByTagName("ol")[0],u=r.passed,c=r.failed,l=r.failed>0?r.todo:!r.todo -l?x(a,"qunit-collapsed"):(et.failedTests.push(r.testId),e.collapse&&(n?x(a,"qunit-collapsed"):n=!0)) -var f=o.firstChild,d=c?""+c+", "+u+", ":"" -if(f.innerHTML+=" ("+d+r.assertions.length+")",et.completed++,r.skipped){o.className="skipped" -var p=m.createElement("em") -p.className="qunit-skipped-label",p.innerHTML="skipped",o.insertBefore(p,f)}else{if(h(f,"click",(function(){k(a,"qunit-collapsed")})),o.className=l?"pass":"fail",r.todo){var g=m.createElement("em") -g.className="qunit-todo-label",g.innerHTML="todo",o.className+=" todo",o.insertBefore(g,f)}var v=m.createElement("span") -v.className="runtime",v.innerHTML=r.runtime+" ms",o.insertBefore(v,a)}if(r.source){var y=m.createElement("p") -y.innerHTML="Source: "+tt(r.source),x(y,"qunit-source"),l&&x(y,"qunit-collapsed"),h(f,"click",(function(){k(y,"qunit-collapsed")})),o.appendChild(y)}e.hidepassed&&("passed"===s||r.skipped)&&(t.push(o),i.removeChild(o))}})),Ge.on("error",(function(e){var t=q("global failure") -if(t){var n=tt(R(e)) -n=""+n+"",e&&e.stack&&(n+="
    Source:
    "+tt(e.stack)+"
    ") -var r=t.getElementsByTagName("ol")[0],i=m.createElement("li") -i.className="fail",i.innerHTML=n,r.appendChild(i),t.className="fail"}})) -var s,a=(s=d.phantom)&&s.version&&s.version.major>0 -a&&p.warn("Support for PhantomJS is deprecated and will be removed in QUnit 3.0."),a||"complete"!==m.readyState?h(d,"load",Ge.load):Ge.load() -var u=d.onerror -d.onerror=function(t,n,r,i,o){var s=!1 -if(u){for(var a=arguments.length,c=new Array(a>5?a-5:0),l=5;l=0}function x(e,t){b(e,t)||(e.className+=(e.className?" ":"")+t)}function k(e,t,n){n||void 0===n&&!b(e,t)?x(e,t):E(e,t)}function E(e,t){for(var n=" "+e.className+" ";n.indexOf(" "+t+" ")>=0;)n=n.replace(" "+t+" "," ") -e.className=f(n)}function _(e){return m.getElementById&&m.getElementById(e)}function S(){var e=_("qunit-abort-tests-button") -return e&&(e.disabled=!0,e.innerHTML="Aborting..."),Ge.config.queue.length=0,!1}function C(e){var t=_("qunit-filter-input") -return t.value=f(t.value),N(),e&&e.preventDefault&&e.preventDefault(),!1}function T(){var n,r=this,i={} -n="selectedIndex"in r?r.options[r.selectedIndex].value||void 0:r.checked?r.defaultValue||!0:void 0,i[r.name]=n -var o=j(i) -if("hidepassed"===r.name&&"replaceState"in d.history){Ge.urlParams[r.name]=n,e[r.name]=n||!1 -var s=_("qunit-tests") -if(s){var a=s.children.length,u=s.children -if(r.checked){for(var c=0;c-1,g=h.indexOf("skipped")>-1;(p||g)&&t.push(f)}var v,m=function(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"] -if(!n){if(Array.isArray(e)||(n=l(e))){n&&(e=n) -var r=0,i=function(){} -return{s:i,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1 -return{s:function(){n=n.call(e)},n:function(){var e=n.next() -return s=e.done,e},e:function(e){a=!0,o=e},f:function(){try{s||null==n.return||n.return()}finally{if(a)throw o}}}}(t) -try{for(m.s();!(v=m.n()).done;){var y=v.value -s.removeChild(y)}}catch(e){m.e(e)}finally{m.f()}}else for(var b;null!=(b=t.pop());)s.appendChild(b)}d.history.replaceState(null,"",o)}else d.location=o}function j(e){var t="?",n=d.location -for(var i in e=M(M({},Ge.urlParams),e))if(r.call(e,i)&&void 0!==e[i])for(var o=[].concat(e[i]),s=0;s"}function q(e,t,n){var r=_("qunit-tests") -if(r){var i=m.createElement("strong") -i.innerHTML=I(e,n) -var o=m.createElement("li") -if(o.appendChild(i),void 0!==t){var s=m.createElement("a") -s.innerHTML="Rerun",s.href=j({testId:t}),o.id="qunit-test-output-"+t,o.appendChild(s)}var a=m.createElement("ol") -return a.className="qunit-assert-list",o.appendChild(a),r.appendChild(o),o}}function A(e){return 0===e.length?"":["
    ",1===e.length?"Rerun 1 failed test":"Rerun "+e.length+" failed tests",""].join("")}function I(e,t){var n="" -return t&&(n=""+tt(t)+": "),n+""+tt(e)+""}function F(e){return[e.completed," / ",e.defined," tests completed.
    "].join("")}function P(e){return e.replace(/<\/?[^>]+(>|$)/g,"").replace(/"/g,"").replace(/\s+/g,"")}}(),Ge.diff=function(){function e(){}var t=-1,n=Object.prototype.hasOwnProperty -return e.prototype.DiffMain=function(e,t,n){var r,i,o,s,a,u -if(r=(new Date).getTime()+1e3,null===e||null===t)throw new Error("Null input. (DiffMain)") -return e===t?e?[[0,e]]:[]:(void 0===n&&(n=!0),i=n,o=this.diffCommonPrefix(e,t),s=e.substring(0,o),e=e.substring(o),t=t.substring(o),o=this.diffCommonSuffix(e,t),a=e.substring(e.length-o),e=e.substring(0,e.length-o),t=t.substring(0,t.length-o),u=this.diffCompute(e,t,i,r),s&&u.unshift([0,s]),a&&u.push([0,a]),this.diffCleanupMerge(u),u)},e.prototype.diffCleanupEfficiency=function(e){var n,r,i,o,s,a,u,c,l -for(n=!1,r=[],i=0,o=null,s=0,a=!1,u=!1,c=!1,l=!1;s0?r[i-1]:-1,c=l=!1),n=!0)),s++ -n&&this.diffCleanupMerge(e)},e.prototype.diffPrettyHtml=function(e){for(var n=[],r=0;r" -break -case t:n[r]=""+tt(o)+"" -break -case 0:n[r]=""+tt(o)+""}}return n.join("")},e.prototype.diffCommonPrefix=function(e,t){var n,r,i,o -if(!e||!t||e.charAt(0)!==t.charAt(0))return 0 -for(i=0,n=r=Math.min(e.length,t.length),o=0;in.length?e:n,a=e.length>n.length?n:e,-1!==(u=s.indexOf(a))?(o=[[1,s.substring(0,u)],[0,a],[1,s.substring(u+a.length)]],e.length>n.length&&(o[0][0]=o[2][0]=t),o):1===a.length?[[t,e],[1,n]]:(c=this.diffHalfMatch(e,n))?(l=c[0],h=c[1],f=c[2],d=c[3],p=c[4],g=this.DiffMain(l,f,r,i),v=this.DiffMain(h,d,r,i),g.concat([[0,p]],v)):r&&e.length>100&&n.length>100?this.diffLineMode(e,n,i):this.diffBisect(e,n,i)):[[t,e]]:[[1,n]]},e.prototype.diffHalfMatch=function(e,t){var n,r,i,o,s,a,u,c,l,f -if(n=e.length>t.length?e:t,r=e.length>t.length?t:e,n.length<4||2*r.length=e.length?[c,l,f,h,s]:null}return i=this,c=h(n,r,Math.ceil(n.length/4)),l=h(n,r,Math.ceil(n.length/2)),c||l?(f=l?c&&c[4].length>l[4].length?c:l:c,e.length>t.length?(o=f[0],u=f[1],a=f[2],s=f[3]):(a=f[0],s=f[1],o=f[2],u=f[3]),[o,u,a,s,f[4]]):null},e.prototype.diffLineMode=function(e,n,r){var i,o,s,a,u,c,l,f,h -for(e=(i=this.diffLinesToChars(e,n)).chars1,n=i.chars2,s=i.lineArray,o=this.DiffMain(e,n,!1,r),this.diffCharsToLines(o,s),this.diffCleanupSemantic(o),o.push([0,""]),a=0,c=0,u=0,f="",l="";a=1&&u>=1){for(o.splice(a-c-u,c+u),a=a-c-u,h=(i=this.DiffMain(f,l,!1,r)).length-1;h>=0;h--)o.splice(a,0,i[h]) -a+=i.length}u=0,c=0,f="",l=""}a++}return o.pop(),o},e.prototype.diffBisect=function(e,n,r){var i,o,s,a,u,c,l,f,h,d,p,g,v,m,y,b,w,x,k,E,_,S,C -for(i=e.length,o=n.length,a=s=Math.ceil((i+o)/2),u=2*s,c=new Array(u),l=new Array(u),f=0;fr);_++){for(S=-_+p;S<=_-g;S+=2){for(b=a+S,k=(w=S===-_||S!==_&&c[b-1]i)g+=2 -else if(k>o)p+=2 -else if(d&&(y=a+h-S)>=0&&y=(x=i-l[y]))return this.diffBisectSplit(e,n,w,k,r)}for(C=-_+v;C<=_-m;C+=2){for(y=a+C,E=(x=C===-_||C!==_&&l[y-1]i)m+=2 -else if(E>o)v+=2 -else if(!d&&(b=a+h-C)>=0&&b=(x=i-x)))return this.diffBisectSplit(e,n,w,k,r)}}return[[t,e],[1,n]]},e.prototype.diffBisectSplit=function(e,t,n,r,i){var o,s,a,u,c,l -return o=e.substring(0,n),a=t.substring(0,r),s=e.substring(n),u=t.substring(r),c=this.DiffMain(o,a,!1,i),l=this.DiffMain(s,u,!1,i),c.concat(l)},e.prototype.diffCleanupSemantic=function(e){var n,r,i,o,s,a,u,c,l,f,h,d,p -for(n=!1,r=[],i=0,o=null,s=0,c=0,l=0,a=0,u=0;s0?r[i-1]:-1,c=0,l=0,a=0,u=0,o=null,n=!0)),s++ -for(n&&this.diffCleanupMerge(e),s=1;s=(p=this.diffCommonOverlap(h,f))?(d>=f.length/2||d>=h.length/2)&&(e.splice(s,0,[0,h.substring(0,d)]),e[s-1][1]=f.substring(0,f.length-d),e[s+1][1]=h.substring(d),s++):(p>=f.length/2||p>=h.length/2)&&(e.splice(s,0,[0,f.substring(0,p)]),e[s-1][0]=1,e[s-1][1]=h.substring(0,h.length-p),e[s+1][0]=t,e[s+1][1]=f.substring(p),s++),s++),s++},e.prototype.diffCommonOverlap=function(e,t){var n,r,i,o,s,a,u -if(n=e.length,r=t.length,0===n||0===r)return 0 -if(n>r?e=e.substring(n-r):n1?(0!==r&&0!==i&&(0!==(a=this.diffCommonPrefix(o,s))&&(n-r-i>0&&0===e[n-r-i-1][0]?e[n-r-i-1][1]+=o.substring(0,a):(e.splice(0,0,[0,o.substring(0,a)]),n++),o=o.substring(a),s=s.substring(a)),0!==(a=this.diffCommonSuffix(o,s))&&(e[n][1]=o.substring(o.length-a)+e[n][1],o=o.substring(0,o.length-a),s=s.substring(0,s.length-a))),0===r?e.splice(n-i,r+i,[1,o]):0===i?e.splice(n-r,r+i,[t,s]):e.splice(n-r-i,r+i,[t,s],[1,o]),n=n-r-i+(r?1:0)+(i?1:0)+1):0!==n&&0===e[n-1][0]?(e[n-1][1]+=e[n][1],e.splice(n,1)):n++,i=0,r=0,s="",o=""}for(""===e[e.length-1][1]&&e.pop(),u=!1,n=1;n{var t=Array.isArray -e.exports=function(){if(!arguments.length)return[] -var e=arguments[0] -return t(e)?e:[e]}},66:e=>{e.exports=function(e){var t=e?e.length:0 -return t?e[t-1]:void 0}},9254:(e,t,n)=>{var r="__lodash_hash_undefined__",i=9007199254740991,o=/^\[object .+?Constructor\]$/,s=/^(?:0|[1-9]\d*)$/,a="object"==typeof n.g&&n.g&&n.g.Object===Object&&n.g,u="object"==typeof self&&self&&self.Object===Object&&self,c=a||u||Function("return this")() -function l(e,t,n){switch(n.length){case 0:return e.call(t) -case 1:return e.call(t,n[0]) -case 2:return e.call(t,n[0],n[1]) -case 3:return e.call(t,n[0],n[1],n[2])}return e.apply(t,n)}function f(e,t){return!(!e||!e.length)&&function(e,t,n){if(t!=t)return function(e,t,n,r){for(var i=e.length,o=-1;++o-1}function h(e,t){for(var n=-1,r=t.length,i=e.length;++n0&&n(a)?t>1?B(a,t-1,n,r,i):h(i,a):r||(i[i.length]=a)}return i}function U(e,t){var n,r,i=e.__data__ -return("string"==(r=typeof(n=t))||"number"==r||"symbol"==r||"boolean"==r?"__proto__"!==n:null===n)?i["string"==typeof t?"string":"hash"]:i.map}function H(e,t){var n=function(e,t){return null==e?void 0:e[t]}(e,t) -return function(e){if(!Z(e)||x&&x in e)return!1 -var t=X(e)||function(e){var t=!1 -if(null!=e&&"function"!=typeof e.toString)try{t=!!(e+"")}catch(e){}return t}(e)?S:o -return t.test(function(e){if(null!=e){try{return k.call(e)}catch(e){}try{return e+""}catch(e){}}return""}(e))}(n)?n:void 0}I.prototype.clear=function(){this.__data__=R?R(null):{}},I.prototype.delete=function(e){return this.has(e)&&delete this.__data__[e]},I.prototype.get=function(e){var t=this.__data__ -if(R){var n=t[e] -return n===r?void 0:n}return E.call(t,e)?t[e]:void 0},I.prototype.has=function(e){var t=this.__data__ -return R?void 0!==t[e]:E.call(t,e)},I.prototype.set=function(e,t){return this.__data__[e]=R&&void 0===t?r:t,this},F.prototype.clear=function(){this.__data__=[]},F.prototype.delete=function(e){var t=this.__data__,n=L(t,e) -return!(n<0||(n==t.length-1?t.pop():N.call(t,n,1),0))},F.prototype.get=function(e){var t=this.__data__,n=L(t,e) -return n<0?void 0:t[n][1]},F.prototype.has=function(e){return L(this.__data__,e)>-1},F.prototype.set=function(e,t){var n=this.__data__,r=L(n,e) -return r<0?n.push([e,t]):n[r][1]=t,this},P.prototype.clear=function(){this.__data__={hash:new I,map:new(A||F),string:new I}},P.prototype.delete=function(e){return U(this,e).delete(e)},P.prototype.get=function(e){return U(this,e).get(e)},P.prototype.has=function(e){return U(this,e).has(e)},P.prototype.set=function(e,t){return U(this,e).set(e,t),this},D.prototype.add=D.prototype.push=function(e){return this.__data__.set(e,r),this},D.prototype.has=function(e){return this.__data__.has(e)} -var z=O?g(O,Object):ie,$=O?function(e){for(var t=[];e;)h(t,z(e)),e=T(e) -return t}:ie -function Q(e){return V(e)||Y(e)||!!(M&&e&&e[M])}function G(e,t){return!!(t=null==t?i:t)&&("number"==typeof e||s.test(e))&&e>-1&&e%1==0&&e-1&&e%1==0&&e<=i}(e.length)&&!X(e)}function X(e){var t=Z(e)?_.call(e):"" -return"[object Function]"==t||"[object GeneratorFunction]"==t}function Z(e){var t=typeof e -return!!e&&("object"==t||"function"==t)}function K(e){return!!e&&"object"==typeof e}function ee(e){return J(e)?function(e,t){var n=V(e)||Y(e)?function(e,t){for(var n=-1,r=Array(e);++n=200&&(o=p,s=!1,t=new D(t)) -e:for(;++i{"use strict" -var r=n(526) -e.exports=function(e){function t(e){var t=e?[].concat(e):[] -return t.in_array=r.curry(t,n,t),t.each=r.curry(t,o,t),t.each_async=r.curry(t,s,t),t.collect=r.curry(t,a,t),t.collect_async=r.curry(t,u,t),t.flatten=r.curry(t,i,t),t.inject=r.curry(t,c,t),t.push_all=r.curry(t,l,t),t.fill=r.curry(t,f,t),t.find_all=r.curry(t,h,t),t.find=r.curry(t,d,t),t.last=r.curry(t,p,t),t.naked=r.curry(t,g,t),t}function n(e,t){for(var n=0;n=e.length?n(null,r):void o()}))} -o()}function a(e,n){for(var r=t(),i=0;i{"use strict" -var r=n(4633),i=n(5901),o=n(6882),s=n(3143) -e.exports=function(e,t,n){var a=[] -function u(){return 0===a.length}function c(){return a.length>1&&a[0].score.equals(a[1].score)}function l(){return a.find_all(h).collect(d).join(", ")}function f(e,t){return t.score.compare(e.score)}function h(e){return e.score.equals(a[0].score)}function d(e){return e.macro.toString()}this.validate=function(){return u()?{step:e,valid:!1,reason:"Undefined Step"}:c()?{step:e,valid:!1,reason:"Ambiguous Step (Patterns ["+l()+"] are all equally good candidates)"}:{step:e,valid:!0,winner:this.winner()}},this.clear_winner=function(){if(u())throw new Error("Undefined Step: ["+e+"]") -if(c())throw new Error("Ambiguous Step: ["+e+"]. Patterns ["+l()+"] match equally well.") -return this.winner()},this.winner=function(){return a[0].macro},function(e,t){a=t.collect((function(t){return{macro:t,score:new o([new r(e,t.levenshtein_signature()),new i(t,n)])}})).sort(f)}(e,s(t))}},9174:e=>{"use strict" -var t=function(e){this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp=!0,this.properties={},this.merge=function(e){return e&&e.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp?this.merge(e.properties):new t(this.properties)._merge(e)},this._merge=function(e){for(var t in e)this.properties[t]=e[t] -return this},this._merge(e)} -e.exports=t},3591:(e,t,n)=>{"use strict" -var r=n(3143),i=n(6690),o=n(9076),s=function(e){e=e||"$" -var t={},n=new i(new RegExp("(?:^|[^\\\\])\\"+e+"(\\w+)","g")),a=new RegExp("(\\"+e+"\\w+)"),u=this -function c(t,n){return l(t).each((function(r){if(n.in_array(r))throw new Error("Circular Definition: ["+n.join(", ")+"]") -var i=f(r,n) -return t=t.replace(e+r,i)}))}function l(e){return n.groups(e)}function f(e,n){var r=t[e]?t[e].pattern:"(.+)" -return p(r)?u.expand(r,n.concat(e)).pattern:r}function h(e){return e.toString().replace(/^\/|\/$/g,"")}function d(e){return!!t[e]}function p(e){return n.test(e)}function g(e){return r(e.split(a)).inject(r(),(function(e,n){return e.push_all(p(n)?function(e){return l(e).inject(r(),(function(e,n){return d(n)?e.push_all(t[n].converters):e.push_all(g(f(n,[])))}))}(n):v(n))}))}function v(e){return r().fill(o,m(e))}function m(e){return new RegExp(e+"|").exec("").length-1}this.define=function(e,n,i){if(d(e))throw new Error("Duplicate term: ["+e+"]") -if(i&&p(n))throw new Error("Expandable terms cannot use converters: ["+e+"]") -if(i&&!function(e,t){return function(e){return r(e).inject(0,(function(e,t){return e+t.length-1}))}(e)===m(t)}(i,n))throw new Error("Wrong number of converters for: ["+e+"]") -return p(n)||i||(i=v(n)),t[e]={pattern:h(n),converters:r(i)},this},this.merge=function(t){if(t._prefix()!==this._prefix())throw new Error("Cannot merge dictionaries with different prefixes") -return new s(e)._merge(this)._merge(t)},this._merge=function(e){return e.each((function(e,t){u.define(e,t.pattern)})),this},this._prefix=function(){return e},this.each=function(e){for(var n in t)e(n,t[n])},this.expand=function(e,t){var n=h(e) -return p(n)?{pattern:c(n,r(t)),converters:g(n)}:{pattern:n,converters:g(n)}}} -e.exports=s},7453:(e,t,n)=>{"use strict" -var r=n(3143),i=n(526),o=new function(){var e=r() -this.send=function(e,n,r){return 1===arguments.length?this.send(e,{}):2===arguments.length&&i.is_function(n)?this.send(e,{},n):(t(e,n),r&&r(),this)},this.on=function(t,n){return e.push({pattern:t,callback:n}),this} -var t=function(e,t){n(e).each((function(n){n({name:e,data:t})}))},n=function(t){return e.find_all((function(e){return new RegExp(e.pattern).test(t)})).collect((function(e){return e.callback}))}} -e.exports={instance:function(){return o},ON_SCENARIO:"__ON_SCENARIO__",ON_STEP:"__ON_STEP__",ON_EXECUTE:"__ON_EXECUTE__",ON_DEFINE:"__ON_DEFINE__"}},8392:(e,t,n)=>{"use strict" -var r=n(3527),i=function(e){this.constructor(e,/.*\.(?:feature|spec|specification)$/)} -i.prototype=new r,e.exports=i},3527:(e,t,n)=>{"use strict" -var r=n(9782),i=r.path,o=r.fs,s=n(3143) -e.exports=function(e,t){t=t||/.*/,this.each=function(e){this.list().forEach(e)},this.list=function(){return s(e).inject(s(),(function(e,t){return e.concat(n(t).find_all(f))}))} -var n=function(e){return s(r(e).concat(a(e)))},r=function(e){return u(e).find_all(c)},a=function(e){return u(e).find_all(l).inject(s(),(function(e,t){return e.concat(n(t))}))},u=function(e){return o.existsSync(e)?s(o.readdirSync(e)).collect((function(t){return i.join(e,t)})):s()},c=function(e){return!l(e)},l=function(e){return o.statSync(e).isDirectory()},f=function(e){return s(t).find((function(t){return new RegExp(t).test(e)}))}}},4404:(e,t,n)=>{"use strict" -var r=n(8071),i=n(9174),o=n(7453),s=n(3143),a=n(526) -e.exports=function(e){e=s(e) -var t,n=o.instance(),u=this -function c(e){return!e.valid}function l(e){return e.step+(e.valid?"":" <-- "+e.reason)}this.requires=function(t){return e.push_all(t),this},this.validate=function(e){var n=s(e).collect((function(e){var n=u.rank_macros(e).validate() -return t=n.winner,n})) -if(n.find(c))throw new Error("Scenario cannot be interpreted\n"+n.collect(l).join("\n"))},this.interpret=function(e,t,r){t=(new i).merge(t),n.send(o.ON_SCENARIO,{scenario:e,ctx:t.properties}) -var a=f(t,r) -s(e).each_async(a,r)} -var f=function(e,t){var n=function(t,n,r){u.interpret_step(t,e,r)} -return t?n:a.asynchronize(null,n)} -this.interpret_step=function(e,r,s){var a=(new i).merge(r) -n.send(o.ON_STEP,{step:e,ctx:a.properties}) -var u=this.rank_macros(e).clear_winner() -t=u,u.interpret(e,a||{},s)},this.rank_macros=function(e){return new r(e,h(e),t)} -var h=function(t){return e.inject([],(function(e,n){return e.concat(n.find_compatible_macros(t))}))}}},6877:(e,t,n)=>{"use strict" -var r=n(386),i=n(3591),o=n(3143) -e.exports=function(e){e=e||new i -var t=o(),n=this -this.define=function(e,t,n,r){return o(e).each((function(e){s(e,t,n,r)})),this} -var s=function(i,o,s,a){if(n.get_macro(i))throw new Error("Duplicate macro: ["+i+"]") -t.push(new r(i,e.expand(i),o,s,n,a))} -this.get_macro=function(e){return t.find((function(t){return t.is_identified_by(e)}))},this.find_compatible_macros=function(e){return t.find_all((function(t){return t.can_interpret(e)}))}}},386:(e,t,n)=>{"use strict" -var r=n(526),i=n(3143),o=n(9174),s=n(6690),a=n(7453) -e.exports=function(e,t,n,u,c,l){e=p(e) -var f=new s(t.pattern),h=(n=n||r.async_noop,a.instance()) -function d(e){return l.mode?"sync"===l.mode:n!==r.async_noop&&n.length!==e.length+1}function p(e){return new RegExp(e).toString()}l=l||{},this.library=c,this.is_identified_by=function(t){return e===p(t)},this.can_interpret=function(e){return f.test(e)},this.interpret=function(e,s,c){var p=new o({step:e}).merge(u).merge(s) -!function(e,n){var r=0 -i(t.converters).collect((function(t){return function(n){t.apply(null,e.slice(r,r+=t.length-1).concat(n))}})).collect_async((function(e,t,n){e(n)}),n)}(f.groups(e),(function(t,i){if(t)return c(t) -var o -h.send(a.ON_EXECUTE,{step:e,ctx:p.properties,pattern:f.toString(),args:i}) -try{o=r.invoke(n,p.properties,d(i)?i:i.concat(c))}catch(t){if(c)return c(t) -throw t}return function(e){return l.mode?"promise"===l.mode:e&&e.then}(o)?o.then(r.noargs(c)).catch(c):d(i)?c&&c():void 0}))},this.is_sibling=function(e){return e&&e.defined_in(c)},this.defined_in=function(e){return c===e},this.levenshtein_signature=function(){return f.without_expressions()},this.toString=function(){return e},h.send(a.ON_DEFINE,{signature:e,pattern:f.toString()})}},886:(e,t,n)=>{"use strict" -e.exports=function(){function e(){return"undefined"!=typeof process&&void 0!==n.g&&!0}function t(){return"undefined"!=typeof window}function r(){return"undefined"!=typeof phantom}return{get_container:function(){return t()?window:r()?phantom:e()?n.g:void 0},is_node:e,is_browser:t,is_phantom:r,is_karma:function(){return"undefined"!=typeof window&&void 0!==window.__karma__}}}},6690:(e,t,n)=>{"use strict" -var r=n(3143) -e.exports=function(e){var t=/(^|[^\\\\])\(.*?\)/g,n=/(^|[^\\\\])\[.*?\]/g,i=/(^|[^\\\\])\{.*?\}/g,o=/(^|[^\\\\])\\./g,s=/[^\w\s]/g,a=new RegExp(e) -this.test=function(e){var t=a.test(e) -return this.reset(),t},this.groups=function(e){for(var t=r(),n=a.exec(e);n;){var i=n.slice(1,n.length) -t.push(i),n=a.global&&a.exec(e)}return this.reset(),t.flatten()},this.reset=function(){return a.lastIndex=0,this},this.without_expressions=function(){return a.source.replace(t,"$1").replace(n,"$1").replace(i,"$1").replace(o,"$1").replace(s,"")},this.equals=function(e){return this.toString()===e.toString()},this.toString=function(){return"/"+a.source+"/"}}},6007:e=>{"use strict" -e.exports={trim:function(e){return e.replace(/^\s+|\s+$/g,"")},rtrim:function(e){return e.replace(/\s+$/g,"")},isBlank:function(e){return/^\s*$/g.test(e)},isNotBlank:function(e){return!this.isBlank(e)},indentation:function(e){var t=/^(\s*)/.exec(e) -return t&&t[0].length||0}}},5682:(e,t,n)=>{"use strict" -var r=n(4404),i=n(9174),o=n(526),s=function(e,t){if(!(this instanceof s))return new s(e,t) -this.interpreter=new r(e),this.requires=function(e){return this.interpreter.requires(e),this},this.yadda=function(e,n,r){return 0===arguments.length?this:2===arguments.length&&o.is_function(n)?this.yadda(e,{},n):(this.interpreter.validate(e),void this.interpreter.interpret(e,(new i).merge(t).merge(n),r))},this.run=this.yadda,this.toString=function(){return"Yadda 2.1.0 Copyright 2010 Stephen Cresswell / Energized Work Ltd"}} -e.exports=s},7182:e=>{"use strict" -e.exports=function(e,t){var n=Date.parse(e) -return isNaN(n)?t(new Error("Cannot convert ["+e+"] to a date")):t(null,new Date(n))}},3986:e=>{"use strict" -e.exports=function(e,t){var n=parseFloat(e) -return isNaN(n)?t(new Error("Cannot convert ["+e+"] to a float")):t(null,n)}},2453:(e,t,n)=>{"use strict" -e.exports={date:n(7182),integer:n(7444),float:n(3986),list:n(3488),table:n(3337),pass_through:n(9076)}},7444:e=>{"use strict" -e.exports=function(e,t){var n=parseInt(e) -return isNaN(n)?t(new Error("Cannot convert ["+e+"] to an integer")):t(null,n)}},3488:e=>{"use strict" -e.exports=function(e,t){return t(null,e.split(/\n/))}},9076:e=>{"use strict" -e.exports=function(e,t){return t(null,e)}},3337:(e,t,n)=>{"use strict" -var r=n(3143),i=n(6007),o=/[\|\u2506]/,s=/^[\|\u2506]|[\|\u2506]$/g,a=/^[\\|\u2506]?-{3,}/ -e.exports=function(e,t){var n,u=e.split(/\n/),c=(n=u.shift(),r(n.replace(s,"").split(o)).collect((function(e){return{text:i.trim(e),indentation:i.indentation(e)}})).naked()),l=h(u[0])?function(e){if(h(e))return d() -p(e)}:function(e){if(h(e))throw new Error("Dashes are unexpected at this time") -d(),p(e)},f=r() -try{r(u).each(l),t(null,function(e){return e.collect((function(e){var t={} -for(var n in e)t[n]=e[n].join("\n") -return t})).naked()}(f))}catch(e){t(e)}function h(e){return a.test(e)}function d(){f.push({})}function p(e){var t=f.last() -r(e.replace(s,"").split(o)).each((function(e,n){var r=c[n].text,o=c[n].indentation,s=i.rtrim(e.substr(o)) -if(i.isNotBlank(e)&&i.indentation(e){"use strict" -e.exports=function(){var e=Array.prototype.slice -function t(){}function n(t,n){return function(){var r=e.call(arguments,arguments.length-1)[0],i=e.call(arguments,0,arguments.length-2) -n.apply(t,i),r&&r()}}return{noop:t,noargs:function(e){return function(){return e()}},async_noop:n(null,t),asynchronize:n,is_function:function(e){return e&&"[object Function]"==={}.toString.call(e)},curry:function(t,n){var r=e.call(arguments,2) -return function(){return n.apply(t,r.concat(e.call(arguments)))}},invoke:function(e,t,n){return e.apply(t,n)}}}()},409:(e,t,n)=>{"use strict" -var r={Yadda:n(5682),EventBus:n(7453),Interpreter:n(4404),Context:n(9174),Library:n(6877),Dictionary:n(3591),FeatureFileSearch:n(8392),FileSearch:n(3527),Platform:n(886),localisation:n(5534),converters:n(2453),parsers:n(3574),plugins:n(918),shims:n(9782),createInstance:function(){return r.Yadda.apply(null,Array.prototype.slice.call(arguments,0))}} -e.exports=r},2889:(e,t,n)=>{"use strict" -var r=n(8271) -e.exports=new r("Chinese",{feature:"[Ff]eature|功能",scenario:"(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)",examples:"(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)",pending:"(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)",only:"(?:[Oo]nly|仅仅?)",background:"[Bb]ackground|背景|前提",given:"(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)",when:"(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)",then:"(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)",_steps:["given","when","then"]})},8555:(e,t,n)=>{"use strict" -var r=n(8271) -e.exports=new r("Dutch",{feature:"(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)",scenario:"(?:[Ss]cenario|[Gg|eval)",examples:"(?:[Vv]oorbeelden?)",pending:"(?:[Tt]odo|[Mm]oet nog)",only:"(?:[Aa]lleen)",background:"(?:[Aa]chtergrond)",given:"(?:[Ss]tel|[Gg]egeven(?:\\sdat)?|[Ee]n|[Mm]aar)",when:"(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)",then:"(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)",_steps:["given","when","then"]})},9307:(e,t,n)=>{"use strict" -var r=n(8271) -e.exports=new r("English",{feature:"[Ff]eature",scenario:"(?:[Ss]cenario|[Ss]cenario [Oo]utline)",examples:"(?:[Ee]xamples|[Ww]here)",pending:"(?:[Pp]ending|[Tt]odo)",only:"(?:[Oo]nly)",background:"[Bb]ackground",given:"(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)",when:"(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)",then:"(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)",_steps:["given","when","then"]})},298:(e,t,n)=>{"use strict" -var r=n(8271) -e.exports=new r("French",{feature:"(?:[Ff]onctionnalité)",scenario:"(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)",examples:"(?:[Ee]xemples|[Ee]xemple|[Oo][uù])",pending:"(?:[Ee]n attente|[Ee]n cours|[Tt]odo)",only:"(?:[Ss]eulement])",background:"(?:[Cc]ontexte)",given:"(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)",when:"(?:[Qq]uand|[Ll]orsqu'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)",then:"(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)",_steps:["given","when","then","soit","etantdonnees","etantdonnee","etantdonne","quand","lorsque","alors"],get soit(){return this.given},get etantdonnees(){return this.given},get etantdonnee(){return this.given},get etantdonne(){return this.given},get quand(){return this.when},get lorsque(){return this.when},get alors(){return this.then}})},4430:(e,t,n)=>{"use strict" -var r=n(8271) -e.exports=new r("German",{feature:"(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)",scenario:"(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)",examples:"(?:[Bb]eispiele?)",pending:"(?:[Tt]odo|[Oo]ffen)",only:"(?:[Nn]ur|[Ee]inzig)",background:"(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)",given:"(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)",when:"(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)",then:"(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)",_steps:["given","when","then"]})},8271:(e,t,n)=>{"use strict" -var r=n(6877),i=n(3143) -e.exports=function(e,t){var n=this -this.is_language=!0,this.library=function(e){return n.localise_library(new r(e))},this.localise_library=function(e){return i(t._steps).each((function(t){e[t]=function(r,s,a,u){return i(r).each((function(r){return r=o(n.localise(t),r),e.define(r,s,a,u)}))}})),e} -var o=function(e,t){var n=new RegExp("^/|/$","g"),r=new RegExp(/^(?:\^)?/) -return t.toString().replace(n,"").replace(r,"^(?:\\s)*"+e+"\\s+")} -this.localise=function(n){if(void 0===t[n])throw new Error('Keyword "'+n+'" has not been translated into '+e+".") -return t[n]}}},5821:(e,t,n)=>{"use strict" -var r=n(8271) -e.exports=new r("Norwegian",{feature:"[Ee]genskap",scenario:"[Ss]cenario",examples:"[Ee]ksempler",pending:"[Aa]vventer",only:"[Bb]are",background:"[Bb]akgrunn",given:"(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)",when:"(?:[Nn]år|[Oo]g|[Mm]en)",then:"(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)",_steps:["given","when","then","gitt","når","så"],get gitt(){return this.given},get"når"(){return this.when},get"så"(){return this.then}})},3040:(e,t,n)=>{"use strict" -var r=n(8271) -e.exports=new r("Pirate",{feature:"(?:[Tt]ale|[Yy]arn)",scenario:"(?:[Aa]dventure|[Ss]ortie)",examples:"[Ww]herest",pending:"[Bb]rig",only:"[Bb]lack [Ss]pot",background:"[Aa]ftground",given:"(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)",when:"(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)",then:"(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)",_steps:["given","when","then","giveth","whence","thence"],get giveth(){return this.given},get whence(){return this.when},get thence(){return this.then}})},5991:(e,t,n)=>{"use strict" -var r=n(8271) -e.exports=new r("Polish",{feature:"(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)",scenario:"(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)",examples:"[Pp]rzykłady",pending:"(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)",only:"[Tt]ylko",background:"[Zz]ałożenia",given:"(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)",when:"(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)",then:"(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)",_steps:["given","when","then","zakladajac","majac","jezeli","jesli","gdy","kiedy","wtedy"],get zakladajac(){return this.given},get majac(){return this.given},get jezeli(){return this.when},get jesli(){return this.when},get gdy(){return this.when},get kiedy(){return this.when},get wtedy(){return this.then}})},2482:(e,t,n)=>{"use strict" -var r=n(8271) -e.exports=new r("Portuguese",{feature:"(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)",scenario:"(?:[Cc]en[aá]rio|[Cc]aso)",examples:"(?:[Ee]xemplos|[Ee]xemplo)",pending:"[Pp]endente",only:"[S][óo]",background:"[Ff]undo",given:"(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)",when:"(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)",then:"(?:[Ee]nt[aã]o|[Ee]|[Mm]as)",_steps:["given","when","then","seja","sejam","dado","dada","dados","dadas","quando","se","entao"],get seja(){return this.given},get sejam(){return this.given},get dado(){return this.given},get dada(){return this.given},get dados(){return this.given},get dadas(){return this.given},get quando(){return this.when},get se(){return this.when},get entao(){return this.then}})},9494:(e,t,n)=>{"use strict" -var r=n(8271) -e.exports=new r("Russian",{feature:"(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)",scenario:"Сценарий",examples:"Примеры?",pending:"(?:[Ww]ip|[Tt]odo)",only:"Только",background:"(?:[Пп]редыстория|[Кк]онтекст)",given:"(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\s[Яя])?",when:"(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\s[Яя])?",then:"(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\s[Яя])?",_steps:["given","when","then"]})},4029:(e,t,n)=>{"use strict" -var r=n(8271) -e.exports=new r("Spanish",{feature:"(?:[Ff]uncionalidad|[Cc]aracterística)",scenario:"(?:[Ee]scenario|[Cc]aso)",examples:"(?:[Ee]jemplos|[Ee]jemplo)",pending:"[Pp]endiente",only:"[S]ólo",background:"[Ff]ondo",given:"(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)",when:"(?:[Cc]uando|[Ss]i|[Qq]ue)",then:"(?:[Ee]ntonces)",_steps:["given","when","then","sea","sean","dado","dada","dados","dadas","cuando","si","entonces"],get sea(){return this.given},get sean(){return this.given},get dado(){return this.given},get dada(){return this.given},get dados(){return this.given},get dadas(){return this.given},get cuando(){return this.when},get si(){return this.when},get entonces(){return this.then}})},6076:(e,t,n)=>{"use strict" -var r=n(8271) -e.exports=new r("Ukrainian",{feature:"(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)",scenario:"(?:[Сс]ценарій|[Шш]аблон)",examples:"[Пп]риклади",pending:"(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)",only:"[Тт]ільки",background:"[Кк]онтекст",given:"(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)",when:"(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)",then:"(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)",_steps:["given","when","then"]})},5534:(e,t,n)=>{"use strict" -e.exports={Chinese:n(2889),English:n(9307),French:n(298),German:n(4430),Dutch:n(8555),Norwegian:n(5821),Pirate:n(3040),Ukrainian:n(6076),Polish:n(5991),Spanish:n(4029),Russian:n(9494),Portuguese:n(2482),default:n(9307),Language:n(8271)}},5070:(e,t,n)=>{"use strict" -e.exports=function(e){var t=n(9782).fs,r=new(n(3610))(e) -this.parse=function(e,n){var i=t.readFileSync(e,"utf8"),o=r.parse(i) -return n&&n(o)||o}}},3610:(e,t,n)=>{"use strict" -var r=n(3143),i=n(526),o=n(6007),s=n(5534) -e.exports=function(e){var t,n,a={language:s.default,leftPlaceholderChar:"[",rightPlaceholderChar:"]"},u=(e=e&&e.is_language?{language:e}:e||a).language||a.language,c=e.leftPlaceholderChar||a.leftPlaceholderChar,l=e.rightPlaceholderChar||a.rightPlaceholderChar,f=new RegExp("^\\s*"+u.localise("feature")+":\\s*(.*)","i"),h=new RegExp("^\\s*"+u.localise("scenario")+":\\s*(.*)","i"),d=new RegExp("^\\s*"+u.localise("background")+":\\s*(.*)","i"),p=new RegExp("^\\s*"+u.localise("examples")+":","i"),g=new RegExp("^(.*)$","i"),v=new RegExp("^\\s*#"),m=new RegExp("^\\s*#{3,}"),y=new RegExp("^(\\s*)$"),b=new RegExp("(^\\s*[\\|┆]?-{3,})"),w=new RegExp("^\\s*@([^=]*)$"),x=new RegExp("^\\s*@([^=]*)=(.*)$") -function k(e,r){var i,s=r+1 -try{if(i=m.test(e))return n=!n -if(n)return -if(i=v.test(e))return -if(i=w.exec(e))return t.handle("Annotation",{key:o.trim(i[1]),value:!0},s) -if(i=x.exec(e))return t.handle("Annotation",{key:o.trim(i[1]),value:o.trim(i[2])},s) -if(i=f.exec(e))return t.handle("Feature",i[1],s) -if(i=h.exec(e))return t.handle("Scenario",i[1],s) -if(i=d.exec(e))return t.handle("Background",i[1],s) -if(i=p.exec(e))return t.handle("Examples",s) -if(i=y.exec(e))return t.handle("Blank",i[0],s) -if(i=b.exec(e))return t.handle("Dash",i[1],s) -if(i=g.exec(e))return t.handle("Text",i[1],s)}catch(t){throw t.message="Error parsing line "+s+', "'+e+'".\nOriginal error was: '+t.message,t}}this.parse=function(e,i){return t=new _,n=!1,function(e){return r(e.split(/\r\n|\n/))}(e).each(k),i&&i(t.export())||t.export()} -var E=function(e){e=e||{},this.register=function(t,n){e[t]=n},this.unregister=function(){r(Array.prototype.slice.call(arguments)).each((function(t){delete e[t]}))},this.find=function(t){if(!e[t.toLowerCase()])throw new Error(t+" is unexpected at this time") -return{handle:e[t.toLowerCase()]}}},_=function(){var e,t=this,n=new S,r=new E({text:i.noop,blank:i.noop,annotation:function(e,t){r.unregister("background"),n.stash(t.key,t.value)},feature:function(t,r){return e=new C(r,n,new S)},scenario:o,background:s}) -function o(t,r,i){return(e=new C(r,new S,n)).on(t,r,i)}var s=o -this.handle=function(e,n,r){t=t.on(e,n,r)},this.on=function(e,t,n){return r.find(e).handle(e,t,n)||this},this.export=function(){if(!e)throw new Error("A feature must contain one or more scenarios") -return e.export()}},S=function(){var e={} -this.stash=function(t,n){if(/\s/.test(t))throw new Error("Invalid annotation: "+t) -e[t.toLowerCase()]=n},this.export=function(){return e}},C=function(e,t,n){var s=[],a=[],u=new j,c=new E({text:function(e,t){s.push(o.trim(t))},blank:i.noop,annotation:function(e,t){c.unregister("background","text"),n.stash(t.key,t.value)},scenario:function(e,t){var r=new N(t,u,n,l) -return a.push(r),n=new S,r},background:function(e,t){return u=new T(t,l),n=new S,u}}),l=this -this.on=function(e,t,n){return c.find(e).handle(e,t,n)||this},this.export=function(){return function(){if(0===a.length)throw new Error("Feature requires one or more scenarios")}(),{title:e,annotations:t.export(),description:s,scenarios:r(a).collect((function(e){return e.export()})).flatten().naked()}}},T=function(e,t){var n=[],r=[],s=0,a=new E({text:u,blank:i.noop,annotation:v,scenario:m}) -function u(e,t,r){a.register("dash",c),n.push(o.trim(t))}function c(e,t,n){a.unregister("dash","annotation","scenario"),a.register("text",l),a.register("blank",h),s=o.indentation(t)}function l(e,t,n){a.register("dash",p),a.register("text",f),a.register("blank",h),a.register("annotation",v),a.register("scenario",m),g(t,"\n")}function f(e,t,n){d(),g(t,"\n")}function h(e,t,n){r.push(t)}function d(){r.length&&(g(r.join("\n"),"\n"),r=[])}function p(e,t,n){a.unregister("dash"),a.register("text",u),a.register("blank",i.noop),d()}function g(e,t){if(o.isNotBlank(e)&&o.indentation(e)=0?"┆":"|",i=r(e.split(n)) -if(void 0!==t&&t!==i.length)throw new Error("Incorrect number of fields in example table. Expected "+t+" but found "+i.length) -return i}function w(t,n,r){return x(),e.on(t,n,r)}function x(){if(0===t.length)throw new Error("Examples table requires one or more headings") -if(0===n.length)throw new Error("Examples table requires one or more rows")}function k(){var e={} -return r(Array.prototype.slice.call(arguments)).each((function(t){for(var n in t)e[n]=t[n]})),e}function _(e,t){return r(t).collect((function(t){return C(e,t)})).naked()}function C(e,t){for(var n in e)t=t.replace(new RegExp("\\"+c+"\\s*"+n+"\\s*\\"+l,"g"),o.rtrim(e[n].join("\n"))) -return t}this.on=function(e,t,n){return a.find(e).handle(e,t,n)||this},this.expand=function(e){return x(),n.collect((function(t){return{title:C(t.fields,e.title),annotations:k(t.annotations.export(),e.annotations),description:_(t,e.description),steps:_(t.fields,e.steps)}})).naked()}}}},7724:(e,t,n)=>{"use strict" -var r=n(3143) -e.exports=function(){var e=/[^\s]/ -this.parse=function(e,r){var i=t(e).find_all(n) -return r&&r(i)||i} -var t=function(e){return r(e.split(/\n/))},n=function(t){return t&&e.test(t)}}},3574:(e,t,n)=>{"use strict" -e.exports={StepParser:n(7724),FeatureParser:n(3610),FeatureFileParser:n(5070)}},8418:(e,t,n)=>{"use strict" -if(!(e=n.nmd(e)).client){var r=n(9782).fs -n.g.process=n.g.process||{cwd:function(){return r.workingDirectory}}}e.exports=function(e,t){var r=n(409).EventBus -e.interpreter.interpret_step=function(e,n,i){var o=this -t.then((function(){t.test.info(e),r.instance().send(r.ON_STEP,{step:e,ctx:n}),o.rank_macros(e).clear_winner().interpret(e,n,i)}))},t.yadda=function(t,n){if(void 0===t)return this -e.run(t,n)}}},918:(e,t,n)=>{"use strict" -e.exports={casper:n(8418),mocha:{ScenarioLevelPlugin:n(616),StepLevelPlugin:n(2271)},get jasmine(){return this.mocha}}},749:(e,t,n)=>{"use strict" -var r=n(5534),i=n(886),o=n(5070),s=n(3143) -e.exports.create=function(e){var t=new i,n=e.language||r.default,a=e.parser||new o(n),u=e.container||t.get_container() -function c(e,t){s(e).each((function(e){l(e.title,e,t)}))}function l(e,t,n){var r;(h(r=t.annotations,"pending")?u.xdescribe:h(r,"only")?u.describe.only||u.fdescribe||u.ddescribe:u.describe)(e,(function(){n(t)}))}function f(e,t){return h(e,"pending")?u.xit:h(e,"only")?u.it.only||u.fit||u.iit:u.it}function h(e,t){var r=new RegExp("^"+n.localise(t)+"$","i") -for(var i in e)if(r.test(i))return!0}return{featureFiles:function(e,t){s(e).each((function(e){c(a.parse(e),t)}))},features:c,describe:l,it_async:function(e,t,n){f(t.annotations)(e,(function(e){n(this,t,e)}))},it_sync:function(e,t,n){f(t.annotations)(e,(function(){n(this,t)}))}}}},616:(e,t,n)=>{"use strict" -var r=n(3143),i=n(886),o=n(749) -e.exports.init=function(e){e=e||{} -var t=new i,n=e.container||t.get_container(),s=o.create(e) -n.featureFiles=n.featureFile=s.featureFiles,n.features=n.feature=s.features,n.scenarios=n.scenario=function(e,t){r(e).each((function(e){(1===t.length?s.it_sync:s.it_async)(e.title,e,(function(e,n,r){t(n,r)}))}))}}},2271:(e,t,n)=>{"use strict" -var r=n(3143),i=n(886),o=n(749) -e.exports.init=function(e){e=e||{} -var t=new i,n=e.container||t.get_container(),s=o.create(e) -n.featureFiles=n.featureFile=s.featureFiles,n.features=n.feature=s.features,n.scenarios=n.scenario=function(e,t){r(e).each((function(e){s.describe(e.title,e,t)}))},n.steps=function(e,t){var n=!1 -function i(e,t){s.it_async(e,e,(function(e,r,i){if(n)return e.skip?e.skip():i() -n=!0,t.bind(e)(r,(function(e){if(e)return(i.fail||i)(e) -n=!1,i()}))}))}function o(e,t){s.it_sync(e,e,(function(e,r){if(n)return e.skip&&e.skip() -n=!0,t.bind(e)(r),n=!1}))}r(e).each((function(e){(1===t.length?o:i)(e,t)}))}}},4633:e=>{"use strict" -e.exports=function(e,t){var n -this.value,this.type="LevenshteinDistanceScore" -var r=this -this.compare=function(e){return e.value-this.value},this.equals=function(e){return!!e&&this.type===e.type&&this.value===e.value},function(){var r=e.length,i=t.length -n=new Array(r+1) -for(var o=0;o<=r;o++)n[o]=new Array(i+1) -for(o=0;o<=r;o++)for(var s=0;s<=i;s++)n[o][s]=0 -for(o=0;o<=r;o++)n[o][0]=o -for(s=0;s<=i;s++)n[0][s]=s}(),function(){if(e===t)return r.value=0 -for(var i=0;i{"use strict" -var r=n(3143) -e.exports=function(e){this.scores=r(e),this.type="MultiScore",this.compare=function(e){for(var t=0;t{"use strict" -e.exports=function(e,t){this.value=e.is_sibling(t)?1:0,this.type="SameLibraryScore",this.compare=function(e){return this.value-e.value},this.equals=function(e){return!!e&&this.type===e.type&&this.value===e.value}}},9782:(e,t,n)=>{"use strict" -var r,i,o,s,a=n(886) -e.exports=(i=function(){return{fs:n(9265),path:n(3642),process:process}},o=function(){return{fs:n(4044),path:n(4152),process:n(5284)}},s=function(){return{fs:n(2459),path:n(8281),process:n(7804)}},(r=new a).is_phantom()?o():r.is_browser()&&r.is_karma()?s():r.is_node()?i():{})},2459:(e,t,n)=>{e.exports=function(){"use strict" -var e=n(8281) -function t(t){return e.resolve(e.normalize(t.split("\\").join("/")))}var r=function(){this.registry=new i,this.converter=new o("/base/","/"),this.reader=new s(this.converter) -var e=Object.keys(window.__karma__.files) -this.converter.parseUris(e).forEach(this.registry.addFile,this.registry)} -r.prototype={constructor:r,workingDirectory:"/",existsSync:function(e){return this.registry.exists(e)},readdirSync:function(e){return this.registry.getContent(e)},statSync:function(e){return{isDirectory:function(){return this.registry.isDirectory(e)}.bind(this)}},readFileSync:function(e,t){if("utf8"!==t)throw new Error("This fs.readFileSync() shim does not support other than utf8 encoding.") -if(!this.registry.isFile(e))throw new Error("File does not exist: "+e) -return this.reader.readFile(e)}} -var i=function(){this.paths={}} -i.prototype={constructor:i,addFile:function(n){n=t(n),this.paths[n]=i.TYPE_FILE -var r=e.dirname(n) -this.addDirectory(r)},addDirectory:function(n){n=t(n),this.paths[n]=i.TYPE_DIRECTORY -var r=e.dirname(n) -r!==n&&this.addDirectory(r)},isFile:function(e){return e=t(e),this.exists(e)&&this.paths[e]===i.TYPE_FILE},isDirectory:function(e){return e=t(e),this.exists(e)&&this.paths[e]===i.TYPE_DIRECTORY},exists:function(e){return e=t(e),this.paths.hasOwnProperty(e)},getContent:function(n){if(!this.isDirectory(n))throw new Error("Not a directory: "+n) -return n=t(n),Object.keys(this.paths).filter((function(t){return t!==n&&e.dirname(t)===n}),this).map((function(t){return e.basename(t)}))}},i.TYPE_FILE=0,i.TYPE_DIRECTORY=1 -var o=function(e,t){this.workingDirectory=t,this.workingDirectoryPattern=this.patternFromBase(t),this.baseUri=e,this.baseUriPattern=this.patternFromBase(e)} -o.prototype={constructor:o,patternFromBase:function(e,t){var n="^"+e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&") -return new RegExp(n,t)},parseUris:function(e){return e.filter((function(e){return this.baseUriPattern.test(e)}),this).map((function(e){return e.replace(this.baseUriPattern,this.workingDirectory)}),this)},buildUri:function(e){if(e=t(e),!this.workingDirectoryPattern.test(e))throw new Error("Path is not in working directory: "+e) -return e.replace(this.workingDirectoryPattern,this.baseUri)}} -var s=function(e){this.converter=e} -return s.prototype={constructor:s,readFile:function(e){var t=this.converter.buildUri(e),n=new XMLHttpRequest -return n.open("get",t,!1),n.send(),n.responseText}},new r}()},8281:(e,t,n)=>{e.exports=function(){"use strict" -var e={} -try{e=n(3642)}catch(e){throw new Error("The environment does not support the path module, it's probably not using browserify.")}if("function"!=typeof e.normalize||"function"!=typeof e.dirname)throw new Error("The path module emulation does not contain implementations of required functions.") -return e}()},7804:(e,t,n)=>{e.exports=function(){"use strict" -var e=n(2459) -return{cwd:function(){return e.workingDirectory}}}()},4044:(e,t,n)=>{"use strict";(e=n.nmd(e)).exports=function(){if(e.client)return{} -var t=n(9265) -return t.existsSync=t.existsSync||t.exists,t.readdirSync=t.readdirSync||function(e){return t.list(e).filter((function(e){return"."!==e&&".."!==e}))},t.statSync=t.statSync||function(e){return{isDirectory:function(){return t.isDirectory(e)}}},t}()},4152:(e,t,n)=>{"use strict";(e=n.nmd(e)).exports=function(){if(e.client)return{} -var t=n(9265),r={} -try{r=n(3642)}catch(e){}return r.join=r.join||function(){return Array.prototype.join.call(arguments,t.separator)},r.relative=r.relative||function(e,n){return e+t.separator+n},r}()},5284:(e,t,n)=>{"use strict";(e=n.nmd(e)).exports=function(){if(e.client)return{} -var t=n(9265),r=void 0!==r?r:{} -return r.cwd=function(){return t.workingDirectory},r}()}}]) diff --git a/agent/uiserver/dist/assets/chunk.336.f5cb05e551aa08eb7125.js.LICENSE.txt b/agent/uiserver/dist/assets/chunk.336.f5cb05e551aa08eb7125.js.LICENSE.txt deleted file mode 100644 index 54e228a74b61..000000000000 --- a/agent/uiserver/dist/assets/chunk.336.f5cb05e551aa08eb7125.js.LICENSE.txt +++ /dev/null @@ -1,8 +0,0 @@ -/*! - * QUnit 2.19.1 - * https://qunitjs.com/ - * - * Copyright OpenJS Foundation and other contributors - * Released under the MIT license - * https://jquery.org/license - */ diff --git a/agent/uiserver/dist/assets/chunk.412.2df22e4bf69d8f15ebdb.js b/agent/uiserver/dist/assets/chunk.412.2df22e4bf69d8f15ebdb.js deleted file mode 100644 index eaf09b0c7c70..000000000000 --- a/agent/uiserver/dist/assets/chunk.412.2df22e4bf69d8f15ebdb.js +++ /dev/null @@ -1,2276 +0,0 @@ -/*! For license information please see chunk.412.2df22e4bf69d8f15ebdb.js.LICENSE.txt */ -(globalThis.webpackChunk_ember_auto_import_=globalThis.webpackChunk_ember_auto_import_||[]).push([[412],{218:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{iconNames:()=>r}) -const r=["loading","running","apple","apple-color","alibaba","alibaba-color","amazon-ecs","amazon-ecs-color","amazon-eks","amazon-eks-color","auth0","auth0-color","aws","aws-color","aws-cloudwatch","aws-cloudwatch-color","aws-ec2","aws-ec2-color","aws-lambda","aws-lambda-color","aws-s3","aws-s3-color","azure","azure-color","azure-aks","azure-aks-color","azure-blob-storage","azure-blob-storage-color","azure-devops","azure-devops-color","azure-vms","azure-vms-color","bitbucket","bitbucket-color","bridgecrew","bridgecrew-color","cisco","cisco-color","codepen","codepen-color","datadog","datadog-color","digital-ocean","digital-ocean-color","docker","docker-color","f5","f5-color","facebook","facebook-color","figma","figma-color","gcp","gcp-color","gitlab","gitlab-color","github","github-color","google","google-color","grafana","grafana-color","helm","helm-color","infracost","infracost-color","kubernetes","kubernetes-color","lightlytics","lightlytics-color","linkedin","linkedin-color","linode","linode-color","linux","linux-color","loom","loom-color","microsoft","microsoft-color","microsoft-teams","microsoft-teams-color","okta","okta-color","oracle","oracle-color","opa","opa-color","pack","pack-color","saml","saml-color","slack","slack-color","snyk","snyk-color","splunk","splunk-color","twitch","twitch-color","twitter","twitter-color","vantage","vantage-color","vmware","vmware-color","youtube","youtube-color","boundary","boundary-color","consul","consul-color","nomad","nomad-color","packer","packer-color","terraform","terraform-color","vagrant","vagrant-color","vault","vault-color","waypoint","waypoint-color","hashicorp","hashicorp-color","hcp","hcp-color","activity","alert-circle","alert-circle-fill","alert-diamond","alert-diamond-fill","alert-triangle","alert-triangle-fill","alert-octagon","alert-octagon-fill","align-center","align-justify","align-left","align-right","api","archive","arrow-down","arrow-down-circle","arrow-down-left","arrow-down-right","arrow-left","arrow-left-circle","arrow-right","arrow-right-circle","arrow-up","arrow-up-circle","arrow-up-left","arrow-up-right","at-sign","award","auto-apply","bank-vault","bar-chart","bar-chart-alt","battery","battery-charging","beaker","bell","bell-active-fill","bell-active","bell-off","bookmark","bookmark-fill","bookmark-add","bookmark-add-fill","bookmark-remove","bookmark-remove-fill","bottom","box","briefcase","bug","build","bulb","calendar","camera","camera-off","caret","cast","certificate","change","change-circle","change-square","check","check-circle","check-circle-fill","check-diamond","check-diamond-fill","check-hexagon","check-hexagon-fill","check-square","check-square-fill","chevron-down","chevron-left","chevron-right","chevron-up","chevrons-down","chevrons-left","chevrons-right","chevrons-up","circle","circle-dot","circle-fill","circle-half","clipboard","clipboard-checked","clipboard-copy","clock","clock-filled","cloud","closed-caption","cloud-check","cloud-download","cloud-lightning","cloud-lock","cloud-off","cloud-upload","cloud-x","code","collections","command","compass","connection","connection-gateway","corner-down-left","corner-down-right","corner-left-down","corner-left-up","corner-right-down","corner-right-up","corner-up-left","corner-up-right","cpu","credit-card","crop","crosshair","dashboard","database","delay","delete","diamond","diamond-fill","disc","discussion-circle","discussion-square","docs","docs-download","docs-link","dollar-sign","dot","dot-half","download","droplet","duplicate","edit","enterprise","entry-point","exit-point","external-link","event","eye","eye-off","fast-forward","file","file-check","file-change","file-diff","file-minus","file-plus","file-source","file-text","file-x","files","film","filter","filter-circle","filter-fill","fingerprint","flag","folder","folder-fill","folder-minus","folder-minus-fill","folder-plus","folder-plus-fill","folder-star","folder-users","frown","gateway","gift","git-branch","git-commit","git-merge","git-pull-request","git-repo","globe","globe-private","government","grid","grid-alt","guide","guide-link","hammer","handshake","hard-drive","hash","headphones","heart","heart-fill","heart-off","help","hexagon","hexagon-fill","history","home","hourglass","identity-user","identity-service","image","inbox","info","info-fill","jump-link","key","keychain","key-values","labyrinth","layers","layout","learn","learn-link","line-chart","line-chart-up","link","list","load-balancer","lock","lock-fill","lock-off","logs","mail","mail-open","mainframe","map","map-pin","maximize","maximize-alt","meh","menu","mesh","message-circle","message-circle-fill","message-square","message-square-fill","mic","mic-off","migrate","minimize","minimize-alt","minus","minus-circle","minus-square","minus-square-fill","minus-plus","minus-plus-circle","minus-plus-square","module","monitor","moon","more-horizontal","more-vertical","mouse-pointer","move","music","navigation","navigation-alt","network","network-alt","newspaper","node","octagon","org","outline","package","paperclip","path","pause","pause-circle","pen-tool","pencil-tool","phone","phone-call","phone-off","pie-chart","pin","pipeline","play","play-circle","plug","plus","plus-circle","plus-square","power","printer","provider","queue","radio","random","redirect","reload","repeat","replication-direct","replication-perf","rewind","rocket","rotate-cw","rotate-ccw","rss","save","scissors","search","send","server","serverless","server-cluster","settings","service","share","shield","shield-alert","shield-check","shield-off","shield-x","shopping-bag","shopping-cart","shuffle","sidebar","sidebar-hide","sidebar-show","sign-in","sign-out","skip","skip-forward","skip-back","slash","slash-square","sliders","smartphone","smile","socket","sort-asc","sort-desc","speaker","square","square-fill","star","star-circle","star-fill","star-off","step","stop-circle","sun","support","swap-horizontal","swap-vertical","switcher","sync","sync-alert","sync-reverse","tablet","tag","target","terminal","terminal-screen","test","thumbs-up","thumbs-down","toggle-left","toggle-right","token","tools","top","trash","trend-down","trend-up","triangle","triangle-fill","truck","tv","type","unfold-open","unfold-close","unlock","upload","user","user-check","user-circle","user-circle-fill","user-minus","user-plus","user-x","users","verified","video","video-off","volume","volume-down","volume-2","volume-x","wall","wand","watch","webhook","wifi","wifi-off","wrench","x","x-circle","x-circle-fill","x-diamond","x-diamond-fill","x-hexagon","x-hexagon-fill","x-square","x-square-fill","zap","zap-off","zoom-in","zoom-out"]},9454:(t,e,n)=>{"use strict" -function r(t,e){var n="function"==typeof Symbol&&t[Symbol.iterator] -if(!n)return t -var r,i,o=n.call(t),a=[] -try{for(;(void 0===e||e-- >0)&&!(r=o.next()).done;)a.push(r.value)}catch(t){i={error:t}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return a}var i -n.r(e),n.d(e,{InterpreterStatus:()=>i,assign:()=>u,createMachine:()=>d,interpret:()=>y}),function(t){t[t.NotStarted=0]="NotStarted",t[t.Running=1]="Running",t[t.Stopped=2]="Stopped"}(i||(i={})) -var o={type:"xstate.init"} -function a(t){return void 0===t?[]:[].concat(t)}function u(t){return{type:"xstate.assign",assignment:t}}function c(t,e){return"string"==typeof(t="string"==typeof t&&e&&e[t]?e[t]:t)?{type:t}:"function"==typeof t?{type:t.name,exec:t}:t}function s(t){return function(e){return t===e}}function f(t){return"string"==typeof t?{type:t}:t}function l(t,e){return{value:t,context:e,actions:[],changed:!1,matches:s(t)}}function h(t,e,n){var r=e,i=!1 -return[t.filter((function(t){if("xstate.assign"===t.type){i=!0 -var e=Object.assign({},r) -return"function"==typeof t.assignment?e=t.assignment(r,n):Object.keys(t.assignment).forEach((function(i){e[i]="function"==typeof t.assignment[i]?t.assignment[i](r,n):t.assignment[i]})),r=e,!1}return!0})),r,i]}function d(t,e){void 0===e&&(e={}) -var n=r(h(a(t.states[t.initial].entry).map((function(t){return c(t,e.actions)})),t.context,o),2),i=n[0],u=n[1],d={config:t,_options:e,initialState:{value:t.initial,actions:i,context:u,matches:s(t.initial)},transition:function(e,n){var i,o,u="string"==typeof e?{value:e,context:t.context}:e,p=u.value,y=u.context,b=f(n),v=t.states[p] -if(v.on){var g=a(v.on[b.type]) -try{for(var m=function(t){var e="function"==typeof Symbol&&Symbol.iterator,n=e&&t[e],r=0 -if(n)return n.call(t) -if(t&&"number"==typeof t.length)return{next:function(){return t&&r>=t.length&&(t=void 0),{value:t&&t[r++],done:!t}}} -throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}(g),_=m.next();!_.done;_=m.next()){var w=_.value -if(void 0===w)return l(p,y) -var x="string"==typeof w?{target:w}:w,A=x.target,E=x.actions,k=void 0===E?[]:E,D=x.cond,C=void 0===A -if((void 0===D?function(){return!0}:D)(y,b)){var O=t.states[null!=A?A:p],S=r(h((C?a(k):[].concat(v.exit,k,O.entry).filter((function(t){return t}))).map((function(t){return c(t,d._options.actions)})),y,b),3),M=S[0],F=S[1],T=S[2],B=null!=A?A:p -return{value:B,context:F,actions:M,changed:A!==p||M.length>0||T,matches:s(B)}}}}catch(t){i={error:t}}finally{try{_&&!_.done&&(o=m.return)&&o.call(m)}finally{if(i)throw i.error}}}return l(p,y)}} -return d}var p=function(t,e){return t.actions.forEach((function(n){var r=n.exec -return r&&r(t.context,e)}))} -function y(t){var e=t.initialState,n=i.NotStarted,r=new Set,a={_machine:t,send:function(o){n===i.Running&&(e=t.transition(e,o),p(e,f(o)),r.forEach((function(t){return t(e)})))},subscribe:function(t){return r.add(t),t(e),{unsubscribe:function(){return r.delete(t)}}},start:function(r){if(r){var u="object"==typeof r?r:{context:t.config.context,value:r} -e={value:u.value,actions:[],context:u.context,matches:s(u.value)}}return n=i.Running,p(e,o),a},stop:function(){return n=i.Stopped,r.clear(),a},get state(){return e},get status(){return n}} -return a}},6313:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{default:()=>f}) -var r=['a[href]:not([tabindex^="-"])','area[href]:not([tabindex^="-"])','input:not([type="hidden"]):not([type="radio"]):not([disabled]):not([tabindex^="-"])','input[type="radio"]:not([disabled]):not([tabindex^="-"]):checked','select:not([disabled]):not([tabindex^="-"])','textarea:not([disabled]):not([tabindex^="-"])','button:not([disabled]):not([tabindex^="-"])','iframe:not([tabindex^="-"])','audio[controls]:not([tabindex^="-"])','video[controls]:not([tabindex^="-"])','[contenteditable]:not([tabindex^="-"])','[tabindex]:not([tabindex^="-"])'] -function i(t,e){this._show=this.show.bind(this),this._hide=this.hide.bind(this),this._maintainFocus=this._maintainFocus.bind(this),this._bindKeypress=this._bindKeypress.bind(this),this._previouslyFocused=null,this.container=t,this.dialog=t.querySelector('dialog, [role="dialog"], [role="alertdialog"]'),this.role=this.dialog.getAttribute("role")||"dialog",this.useDialog="show"in this.dialog,this._listeners={},this.create(e)}function o(t){return Array.prototype.slice.call(t)}function a(t,e){return o((e||document).querySelectorAll(t))}function u(t){var e=c(t),n=t.querySelector("[autofocus]")||e[0] -n&&n.focus()}function c(t){return a(r.join(","),t).filter((function(t){return!!(t.offsetWidth||t.offsetHeight||t.getClientRects().length)}))}function s(){a("[data-a11y-dialog]").forEach((function(t){new i(t,t.getAttribute("data-a11y-dialog")||void 0)}))}i.prototype.create=function(t){var e,n,r -return this._targets=this._targets||(r=t,NodeList.prototype.isPrototypeOf(r)?o(r):Element.prototype.isPrototypeOf(r)?[r]:"string"==typeof r?a(r):void 0)||((n=o((e=this.container).parentNode.childNodes).filter((function(t){return 1===t.nodeType}))).splice(n.indexOf(e),1),n),this.shown=this.dialog.hasAttribute("open"),this.dialog.setAttribute("role",this.role),this.useDialog?(this.container.setAttribute("data-a11y-dialog-native",""),this.container.removeAttribute("aria-hidden")):this.shown?this.container.removeAttribute("aria-hidden"):this.container.setAttribute("aria-hidden",!0),this._openers=a('[data-a11y-dialog-show="'+this.container.id+'"]'),this._openers.forEach(function(t){t.addEventListener("click",this._show)}.bind(this)),this._closers=a("[data-a11y-dialog-hide]",this.container).concat(a('[data-a11y-dialog-hide="'+this.container.id+'"]')),this._closers.forEach(function(t){t.addEventListener("click",this._hide)}.bind(this)),this._fire("create"),this},i.prototype.show=function(t){return this.shown||(this.shown=!0,this._previouslyFocused=document.activeElement,this.useDialog?this.dialog.showModal(t instanceof Event?void 0:t):(this.dialog.setAttribute("open",""),this.container.removeAttribute("aria-hidden"),this._targets.forEach((function(t){t.hasAttribute("aria-hidden")&&t.setAttribute("data-a11y-dialog-original-aria-hidden",t.getAttribute("aria-hidden")),t.setAttribute("aria-hidden","true")}))),u(this.dialog),document.body.addEventListener("focus",this._maintainFocus,!0),document.addEventListener("keydown",this._bindKeypress),this._fire("show",t)),this},i.prototype.hide=function(t){return this.shown?(this.shown=!1,this.useDialog?this.dialog.close(t instanceof Event?void 0:t):(this.dialog.removeAttribute("open"),this.container.setAttribute("aria-hidden","true"),this._targets.forEach((function(t){t.hasAttribute("data-a11y-dialog-original-aria-hidden")?(t.setAttribute("aria-hidden",t.getAttribute("data-a11y-dialog-original-aria-hidden")),t.removeAttribute("data-a11y-dialog-original-aria-hidden")):t.removeAttribute("aria-hidden")}))),this._previouslyFocused&&this._previouslyFocused.focus&&this._previouslyFocused.focus(),document.body.removeEventListener("focus",this._maintainFocus,!0),document.removeEventListener("keydown",this._bindKeypress),this._fire("hide",t),this):this},i.prototype.destroy=function(){return this.hide(),this._openers.forEach(function(t){t.removeEventListener("click",this._show)}.bind(this)),this._closers.forEach(function(t){t.removeEventListener("click",this._hide)}.bind(this)),this._fire("destroy"),this._listeners={},this},i.prototype.on=function(t,e){return void 0===this._listeners[t]&&(this._listeners[t]=[]),this._listeners[t].push(e),this},i.prototype.off=function(t,e){var n=(this._listeners[t]||[]).indexOf(e) -return n>-1&&this._listeners[t].splice(n,1),this},i.prototype._fire=function(t,e){(this._listeners[t]||[]).forEach(function(t){t(this.container,e)}.bind(this))},i.prototype._bindKeypress=function(t){this.dialog.contains(document.activeElement)&&(this.shown&&27===t.which&&"alertdialog"!==this.role&&(t.preventDefault(),this.hide(t)),this.shown&&9===t.which&&function(t,e){var n=c(t),r=n.indexOf(document.activeElement) -e.shiftKey&&0===r?(n[n.length-1].focus(),e.preventDefault()):e.shiftKey||r!==n.length-1||(n[0].focus(),e.preventDefault())}(this.dialog,t))},i.prototype._maintainFocus=function(t){var e=t.target.getAttribute("data-a11y-dialog-show") -this.shown&&!this.container.contains(t.target)&&e===this.container.id&&u(this.container)},"undefined"!=typeof document&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",s):window.requestAnimationFrame?window.requestAnimationFrame(s):window.setTimeout(s,16)) -const f=i},3305:(t,e)=>{"use strict" -e.byteLength=function(t){var e=c(t),n=e[0],r=e[1] -return 3*(n+r)/4-r},e.toByteArray=function(t){var e,n,o=c(t),a=o[0],u=o[1],s=new i(function(t,e,n){return 3*(e+n)/4-n}(0,a,u)),f=0,l=u>0?a-4:a -for(n=0;n>16&255,s[f++]=e>>8&255,s[f++]=255&e -return 2===u&&(e=r[t.charCodeAt(n)]<<2|r[t.charCodeAt(n+1)]>>4,s[f++]=255&e),1===u&&(e=r[t.charCodeAt(n)]<<10|r[t.charCodeAt(n+1)]<<4|r[t.charCodeAt(n+2)]>>2,s[f++]=e>>8&255,s[f++]=255&e),s},e.fromByteArray=function(t){for(var e,r=t.length,i=r%3,o=[],a=16383,u=0,c=r-i;uc?c:u+a)) -return 1===i?(e=t[r-1],o.push(n[e>>2]+n[e<<4&63]+"==")):2===i&&(e=(t[r-2]<<8)+t[r-1],o.push(n[e>>10]+n[e>>4&63]+n[e<<2&63]+"=")),o.join("")} -for(var n=[],r=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,u=o.length;a0)throw new Error("Invalid string. Length must be a multiple of 4") -var n=t.indexOf("=") -return-1===n&&(n=e),[n,n===e?0:4-n%4]}function s(t,e,r){for(var i,o,a=[],u=e;u>18&63]+n[o>>12&63]+n[o>>6&63]+n[63&o]) -return a.join("")}r["-".charCodeAt(0)]=62,r["_".charCodeAt(0)]=63},2309:function(t){var e -e=function(){return function(){var t={134:function(t,e,n){"use strict" -n.d(e,{default:function(){return m}}) -var r=n(279),i=n.n(r),o=n(370),a=n.n(o),u=n(817),c=n.n(u) -function s(t){return s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},s(t)}var f=function(){function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.resolveOptions(e),this.initSelection()}var n -return n=[{key:"resolveOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{} -this.action=t.action,this.container=t.container,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""}},{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"createFakeElement",value:function(){var t="rtl"===document.documentElement.getAttribute("dir") -this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[t?"right":"left"]="-9999px" -var e=window.pageYOffset||document.documentElement.scrollTop -return this.fakeElem.style.top="".concat(e,"px"),this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.fakeElem}},{key:"selectFake",value:function(){var t=this,e=this.createFakeElement() -this.fakeHandlerCallback=function(){return t.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.container.appendChild(e),this.selectedText=c()(e),this.copyText(),this.removeFake()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=c()(this.target),this.copyText()}},{key:"copyText",value:function(){var t -try{t=document.execCommand(this.action)}catch(e){t=!1}this.handleResult(t)}},{key:"handleResult",value:function(t){this.emitter.emit(t?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),document.activeElement.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy" -if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(t){if(void 0!==t){if(!t||"object"!==s(t)||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element') -if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute') -if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes') -this._target=t}},get:function(){return this._target}}],n&&function(t,e){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{} -this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText,this.container="object"===h(t.container)?t.container:document.body}},{key:"listenClick",value:function(t){var e=this -this.listener=a()(t,"click",(function(t){return e.onClick(t)}))}},{key:"onClick",value:function(t){var e=t.delegateTarget||t.currentTarget -this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new l({action:this.action(e),target:this.target(e),text:this.text(e),container:this.container,trigger:e,emitter:this})}},{key:"defaultAction",value:function(t){return v("action",t)}},{key:"defaultTarget",value:function(t){var e=v("target",t) -if(e)return document.querySelector(e)}},{key:"defaultText",value:function(t){return v("text",t)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],r=[{key:"isSupported",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],e="string"==typeof t?[t]:t,n=!!document.queryCommandSupported -return e.forEach((function(t){n=n&&!!document.queryCommandSupported(t)})),n}}],n&&d(e.prototype,n),r&&d(e,r),c}(i()),m=g},828:function(t){if("undefined"!=typeof Element&&!Element.prototype.matches){var e=Element.prototype -e.matches=e.matchesSelector||e.mozMatchesSelector||e.msMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector}t.exports=function(t,e){for(;t&&9!==t.nodeType;){if("function"==typeof t.matches&&t.matches(e))return t -t=t.parentNode}}},438:function(t,e,n){var r=n(828) -function i(t,e,n,r,i){var a=o.apply(this,arguments) -return t.addEventListener(n,a,i),{destroy:function(){t.removeEventListener(n,a,i)}}}function o(t,e,n,i){return function(n){n.delegateTarget=r(n.target,e),n.delegateTarget&&i.call(t,n)}}t.exports=function(t,e,n,r,o){return"function"==typeof t.addEventListener?i.apply(null,arguments):"function"==typeof n?i.bind(null,document).apply(null,arguments):("string"==typeof t&&(t=document.querySelectorAll(t)),Array.prototype.map.call(t,(function(t){return i(t,e,n,r,o)})))}},879:function(t,e){e.node=function(t){return void 0!==t&&t instanceof HTMLElement&&1===t.nodeType},e.nodeList=function(t){var n=Object.prototype.toString.call(t) -return void 0!==t&&("[object NodeList]"===n||"[object HTMLCollection]"===n)&&"length"in t&&(0===t.length||e.node(t[0]))},e.string=function(t){return"string"==typeof t||t instanceof String},e.fn=function(t){return"[object Function]"===Object.prototype.toString.call(t)}},370:function(t,e,n){var r=n(879),i=n(438) -t.exports=function(t,e,n){if(!t&&!e&&!n)throw new Error("Missing required arguments") -if(!r.string(e))throw new TypeError("Second argument must be a String") -if(!r.fn(n))throw new TypeError("Third argument must be a Function") -if(r.node(t))return function(t,e,n){return t.addEventListener(e,n),{destroy:function(){t.removeEventListener(e,n)}}}(t,e,n) -if(r.nodeList(t))return function(t,e,n){return Array.prototype.forEach.call(t,(function(t){t.addEventListener(e,n)})),{destroy:function(){Array.prototype.forEach.call(t,(function(t){t.removeEventListener(e,n)}))}}}(t,e,n) -if(r.string(t))return function(t,e,n){return i(document.body,t,e,n)}(t,e,n) -throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}},817:function(t){t.exports=function(t){var e -if("SELECT"===t.nodeName)t.focus(),e=t.value -else if("INPUT"===t.nodeName||"TEXTAREA"===t.nodeName){var n=t.hasAttribute("readonly") -n||t.setAttribute("readonly",""),t.select(),t.setSelectionRange(0,t.value.length),n||t.removeAttribute("readonly"),e=t.value}else{t.hasAttribute("contenteditable")&&t.focus() -var r=window.getSelection(),i=document.createRange() -i.selectNodeContents(t),r.removeAllRanges(),r.addRange(i),e=r.toString()}return e}},279:function(t){function e(){}e.prototype={on:function(t,e,n){var r=this.e||(this.e={}) -return(r[t]||(r[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){var r=this -function i(){r.off(t,i),e.apply(n,arguments)}return i._=e,this.on(t,i,n)},emit:function(t){for(var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),r=0,i=n.length;r{"use strict" -function r(t,e){return te?1:t>=e?0:NaN}n.d(e,{Z:()=>r})},4376:(t,e,n)=>{"use strict" -n.d(e,{Nw:()=>c,ZP:()=>f,ZR:()=>s,ml:()=>u}) -var r=n(7604),i=n(9354),o=n(9750) -const a=(0,i.Z)(r.Z),u=a.right,c=a.left,s=(0,i.Z)(o.Z).center,f=u},9354:(t,e,n)=>{"use strict" -n.d(e,{Z:()=>i}) -var r=n(7604) -function i(t){let e=t,n=t -function i(t,e,r,i){for(null==r&&(r=0),null==i&&(i=t.length);r>>1 -n(t[o],e)<0?r=o+1:i=o}return r}return 1===t.length&&(e=(e,n)=>t(e)-n,n=function(t){return(e,n)=>(0,r.Z)(t(e),n)}(t)),{left:i,center:function(t,n,r,o){null==r&&(r=0),null==o&&(o=t.length) -const a=i(t,n,r,o-1) -return a>r&&e(t[a-1],n)>-e(t[a],n)?a-1:a},right:function(t,e,r,i){for(null==r&&(r=0),null==i&&(i=t.length);r>>1 -n(t[o],e)>0?i=o:r=o+1}return r}}}},1286:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{Adder:()=>v,InternMap:()=>_,InternSet:()=>w,ascending:()=>i.Z,bin:()=>q,bisect:()=>r.ZP,bisectCenter:()=>r.ZR,bisectLeft:()=>r.Nw,bisectRight:()=>r.ml,bisector:()=>o.Z,count:()=>a,cross:()=>l,cumsum:()=>h,descending:()=>d,deviation:()=>y,difference:()=>xt,disjoint:()=>At,every:()=>bt,extent:()=>b,fcumsum:()=>m,filter:()=>gt,fsum:()=>g,greatest:()=>ut,greatestIndex:()=>ct,group:()=>C,groupSort:()=>R,groups:()=>O,histogram:()=>q,index:()=>F,indexes:()=>T,intersection:()=>kt,least:()=>ot,leastIndex:()=>at,map:()=>mt,max:()=>G.Z,maxIndex:()=>K,mean:()=>W,median:()=>X,merge:()=>J,min:()=>Q.Z,minIndex:()=>tt,nice:()=>z,pairs:()=>et,permute:()=>j,quantile:()=>V.Z,quantileSorted:()=>V.s,quickselect:()=>rt.Z,range:()=>it.Z,reduce:()=>_t,reverse:()=>wt,rollup:()=>S,rollups:()=>M,scan:()=>st,shuffle:()=>ft,shuffler:()=>lt,some:()=>vt,sort:()=>N,subset:()=>Ct,sum:()=>ht,superset:()=>Dt,thresholdFreedmanDiaconis:()=>H,thresholdScott:()=>Y,thresholdSturges:()=>Z,tickIncrement:()=>U.G9,tickStep:()=>U.ly,ticks:()=>U.ZP,transpose:()=>dt,union:()=>Ot,variance:()=>p,zip:()=>yt}) -var r=n(4376),i=n(7604),o=n(9354) -function a(t,e){let n=0 -if(void 0===e)for(let r of t)null!=r&&(r=+r)>=r&&++n -else{let r=-1 -for(let i of t)null!=(i=e(i,++r,t))&&(i=+i)>=i&&++n}return n}function u(t){return 0|t.length}function c(t){return!(t>0)}function s(t){return"object"!=typeof t||"length"in t?t:Array.from(t)}function f(t){return e=>t(...e)}function l(){for(var t=arguments.length,e=new Array(t),n=0;ne[n][t]))) -let t=o -for(;++a[t]===i[t];){if(0===t)return r?l.map(r):l -a[t--]=0}}}function h(t,e){var n=0,r=0 -return Float64Array.from(t,void 0===e?t=>n+=+t||0:i=>n+=+e(i,r++,t)||0)}function d(t,e){return et?1:e>=t?0:NaN}function p(t,e){let n,r=0,i=0,o=0 -if(void 0===e)for(let a of t)null!=a&&(a=+a)>=a&&(n=a-i,i+=n/++r,o+=n*(a-i)) -else{let a=-1 -for(let u of t)null!=(u=e(u,++a,t))&&(u=+u)>=u&&(n=u-i,i+=n/++r,o+=n*(u-i))}if(r>1)return o/(r-1)}function y(t,e){const n=p(t,e) -return n?Math.sqrt(n):n}function b(t,e){let n,r -if(void 0===e)for(const i of t)null!=i&&(void 0===n?i>=i&&(n=r=i):(n>i&&(n=i),r=o&&(n=r=o):(n>o&&(n=o),r0){for(o=t[--i];i>0&&(e=o,n=t[--i],o=e+n,r=n-(o-e),!r););i>0&&(r<0&&t[i-1]<0||r>0&&t[i-1]>0)&&(n=2*r,e=o+n,n==e-o&&(o=e))}return o}}function g(t,e){const n=new v -if(void 0===e)for(let r of t)(r=+r)&&n.add(r) -else{let r=-1 -for(let i of t)(i=+e(i,++r,t))&&n.add(i)}return+n}function m(t,e){const n=new v -let r=-1 -return Float64Array.from(t,void 0===e?t=>n.add(+t||0):i=>n.add(+e(i,++r,t)||0))}class _ extends Map{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:k -if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:e}}),null!=t)for(const[n,r]of t)this.set(n,r)}get(t){return super.get(x(this,t))}has(t){return super.has(x(this,t))}set(t,e){return super.set(A(this,t),e)}delete(t){return super.delete(E(this,t))}}class w extends Set{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:k -if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:e}}),null!=t)for(const n of t)this.add(n)}has(t){return super.has(x(this,t))}add(t){return super.add(A(this,t))}delete(t){return super.delete(E(this,t))}}function x(t,e){let{_intern:n,_key:r}=t -const i=r(e) -return n.has(i)?n.get(i):e}function A(t,e){let{_intern:n,_key:r}=t -const i=r(e) -return n.has(i)?n.get(i):(n.set(i,e),e)}function E(t,e){let{_intern:n,_key:r}=t -const i=r(e) -return n.has(i)&&(e=n.get(e),n.delete(i)),e}function k(t){return null!==t&&"object"==typeof t?t.valueOf():t}function D(t){return t}function C(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r1?e-1:0),r=1;r2?n-2:0),i=2;i2?n-2:0),i=2;i1?e-1:0),r=1;r1?e-1:0),r=1;r=r.length)return n(i) -const a=new _,u=r[o++] -let c=-1 -for(const e of i){const t=u(e,++c,i),n=a.get(t) -n?n.push(e):a.set(t,[e])}for(const[e,n]of a)a.set(e,t(n,o)) -return e(a)}(t,0)}function j(t,e){return Array.from(e,(e=>t[e]))}function N(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r1){const e=Uint32Array.from(t,((t,e)=>e)) -return n.length>1?(n=n.map((e=>t.map(e))),e.sort(((t,e)=>{for(const r of n){const n=(0,i.Z)(r[t],r[e]) -if(n)return n}}))):(o=t.map(o),e.sort(((t,e)=>(0,i.Z)(o[t],o[e])))),j(t,e)}return t.sort(o)}function R(t,e,n){return(1===e.length?N(S(t,e,n),((t,e)=>{let[n,r]=t,[o,a]=e -return(0,i.Z)(r,a)||(0,i.Z)(n,o)})):N(C(t,n),((t,n)=>{let[r,o]=t,[a,u]=n -return e(o,u)||(0,i.Z)(r,a)}))).map((t=>{let[e]=t -return e}))}var L=Array.prototype,I=L.slice -function $(t){return function(){return t}}L.map -var U=n(458) -function z(t,e,n){let r -for(;;){const i=(0,U.G9)(t,e,n) -if(i===r||0===i||!isFinite(i))return[t,e] -i>0?(t=Math.floor(t/i)*i,e=Math.ceil(e/i)*i):i<0&&(t=Math.ceil(t*i)/i,e=Math.floor(e*i)/i),r=i}}function Z(t){return Math.ceil(Math.log(a(t))/Math.LN2)+1}function q(){var t=D,e=b,n=Z -function i(i){Array.isArray(i)||(i=Array.from(i)) -var o,a,u=i.length,c=new Array(u) -for(o=0;o=l)if(t>=l&&e===b){const t=(0,U.G9)(f,l,n) -isFinite(t)&&(t>0?l=(Math.floor(l/t)+1)*t:t<0&&(l=(Math.ceil(l*-t)+1)/-t))}else h.pop()}for(var d=h.length;h[0]<=f;)h.shift(),--d -for(;h[d-1]>l;)h.pop(),--d -var p,y=new Array(d+1) -for(o=0;o<=d;++o)(p=y[o]=[]).x0=o>0?h[o-1]:f,p.x1=o=o)&&(n=o,r=i) -else for(let o of t)null!=(o=e(o,++i,t))&&(n=o)&&(n=o,r=i) -return r}function W(t,e){let n=0,r=0 -if(void 0===e)for(let i of t)null!=i&&(i=+i)>=i&&(++n,r+=i) -else{let i=-1 -for(let o of t)null!=(o=e(o,++i,t))&&(o=+o)>=o&&(++n,r+=o)}if(n)return r/n}function X(t,e){return(0,V.Z)(t,.5,e)}function J(t){return Array.from(function*(t){for(const e of t)yield*e}(t))}var Q=n(4007) -function tt(t,e){let n,r=-1,i=-1 -if(void 0===e)for(const o of t)++i,null!=o&&(n>o||void 0===n&&o>=o)&&(n=o,r=i) -else for(let o of t)null!=(o=e(o,++i,t))&&(n>o||void 0===n&&o>=o)&&(n=o,r=i) -return r}function et(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:nt -const n=[] -let r,i=!1 -for(const o of t)i&&n.push(e(r,o)),r=o,i=!0 -return n}function nt(t,e){return[t,e]}var rt=n(3767),it=n(1204) -function ot(t){let e,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.Z,r=!1 -if(1===n.length){let o -for(const a of t){const t=n(a);(r?(0,i.Z)(t,o)<0:0===(0,i.Z)(t,t))&&(e=a,o=t,r=!0)}}else for(const i of t)(r?n(i,e)<0:0===n(i,i))&&(e=i,r=!0) -return e}function at(t){let e,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.Z -if(1===n.length)return tt(t,n) -let r=-1,o=-1 -for(const i of t)++o,(r<0?0===n(i,i):n(i,e)<0)&&(e=i,r=o) -return r}function ut(t){let e,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.Z,r=!1 -if(1===n.length){let o -for(const a of t){const t=n(a);(r?(0,i.Z)(t,o)>0:0===(0,i.Z)(t,t))&&(e=a,o=t,r=!0)}}else for(const i of t)(r?n(i,e)>0:0===n(i,i))&&(e=i,r=!0) -return e}function ct(t){let e,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.Z -if(1===n.length)return K(t,n) -let r=-1,o=-1 -for(const i of t)++o,(r<0?0===n(i,i):n(i,e)>0)&&(e=i,r=o) -return r}function st(t,e){const n=at(t,e) -return n<0?void 0:n}const ft=lt(Math.random) -function lt(t){return function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:e.length,i=r-(n=+n) -for(;i;){const r=t()*i--|0,o=e[i+n] -e[i+n]=e[r+n],e[r+n]=o}return e}}function ht(t,e){let n=0 -if(void 0===e)for(let r of t)(r=+r)&&(n+=r) -else{let r=-1 -for(let i of t)(i=+e(i,++r,t))&&(n+=i)}return n}function dt(t){if(!(i=t.length))return[] -for(var e=-1,n=(0,Q.Z)(t,pt),r=new Array(n);++ee(n,r,t)))}function _t(t,e,n){if("function"!=typeof e)throw new TypeError("reducer is not a function") -const r=t[Symbol.iterator]() -let i,o,a=-1 -if(arguments.length<3){if(({done:i,value:n}=r.next()),i)return;++a}for(;({done:i,value:o}=r.next()),!i;)n=e(n,o,++a,t) -return n}function wt(t){if("function"!=typeof t[Symbol.iterator])throw new TypeError("values is not iterable") -return Array.from(t).reverse()}function xt(t){t=new Set(t) -for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r1?e-1:0),r=1;r{"use strict" -function r(t,e){let n -if(void 0===e)for(const r of t)null!=r&&(n=r)&&(n=r) -else{let r=-1 -for(let i of t)null!=(i=e(i,++r,t))&&(n=i)&&(n=i)}return n}n.d(e,{Z:()=>r})},4007:(t,e,n)=>{"use strict" -function r(t,e){let n -if(void 0===e)for(const r of t)null!=r&&(n>r||void 0===n&&r>=r)&&(n=r) -else{let r=-1 -for(let i of t)null!=(i=e(i,++r,t))&&(n>i||void 0===n&&i>=i)&&(n=i)}return n}n.d(e,{Z:()=>r})},9750:(t,e,n)=>{"use strict" -function r(t){return null===t?NaN:+t}function*i(t,e){if(void 0===e)for(let n of t)null!=n&&(n=+n)>=n&&(yield n) -else{let n=-1 -for(let r of t)null!=(r=e(r,++n,t))&&(r=+r)>=r&&(yield r)}}n.d(e,{K:()=>i,Z:()=>r})},801:(t,e,n)=>{"use strict" -n.d(e,{Z:()=>u,s:()=>c}) -var r=n(2368),i=n(4007),o=n(3767),a=n(9750) -function u(t,e,n){if(u=(t=Float64Array.from((0,a.K)(t,n))).length){if((e=+e)<=0||u<2)return(0,i.Z)(t) -if(e>=1)return(0,r.Z)(t) -var u,c=(u-1)*e,s=Math.floor(c),f=(0,r.Z)((0,o.Z)(t,s).subarray(0,s+1)) -return f+((0,i.Z)(t.subarray(s+1))-f)*(c-s)}}function c(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:a.Z -if(r=t.length){if((e=+e)<=0||r<2)return+n(t[0],0,t) -if(e>=1)return+n(t[r-1],r-1,t) -var r,i=(r-1)*e,o=Math.floor(i),u=+n(t[o],o,t),c=+n(t[o+1],o+1,t) -return u+(c-u)*(i-o)}}},3767:(t,e,n)=>{"use strict" -n.d(e,{Z:()=>i}) -var r=n(7604) -function i(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:t.length-1,u=arguments.length>4&&void 0!==arguments[4]?arguments[4]:r.Z -for(;a>n;){if(a-n>600){const r=a-n+1,o=e-n+1,c=Math.log(r),s=.5*Math.exp(2*c/3),f=.5*Math.sqrt(c*s*(r-s)/r)*(o-r/2<0?-1:1) -i(t,e,Math.max(n,Math.floor(e-o*s/r+f)),Math.min(a,Math.floor(e+(r-o)*s/r+f)),u)}const r=t[e] -let c=n,s=a -for(o(t,n,e),u(t[a],r)>0&&o(t,n,a);c0;)--s}0===u(t[n],r)?o(t,n,s):(++s,o(t,s,a)),s<=e&&(n=s+1),e<=s&&(a=s-1)}return t}function o(t,e,n){const r=t[e] -t[e]=t[n],t[n]=r}},1204:(t,e,n)=>{"use strict" -function r(t,e,n){t=+t,e=+e,n=(i=arguments.length)<2?(e=t,t=0,1):i<3?1:+n -for(var r=-1,i=0|Math.max(0,Math.ceil((e-t)/n)),o=new Array(i);++rr})},458:(t,e,n)=>{"use strict" -n.d(e,{G9:()=>u,ZP:()=>a,ly:()=>c}) -var r=Math.sqrt(50),i=Math.sqrt(10),o=Math.sqrt(2) -function a(t,e,n){var r,i,o,a,c=-1 -if(n=+n,(t=+t)==(e=+e)&&n>0)return[t] -if((r=e0)for(t=Math.ceil(t/a),e=Math.floor(e/a),o=new Array(i=Math.ceil(e-t+1));++c=0?(c>=r?10:c>=i?5:c>=o?2:1)*Math.pow(10,u):-Math.pow(10,-u)/(c>=r?10:c>=i?5:c>=o?2:1)}function c(t,e,n){var a=Math.abs(e-t)/Math.max(0,n),u=Math.pow(10,Math.floor(Math.log(a)/Math.LN10)),c=a/u -return c>=r?u*=10:c>=i?u*=5:c>=o&&(u*=2),e{"use strict" -n.d(e,{B8:()=>E,Il:()=>i,J5:()=>a,SU:()=>A,Ss:()=>k,ZP:()=>_,xV:()=>o}) -var r=n(1572) -function i(){}var o=.7,a=1/o,u="\\s*([+-]?\\d+)\\s*",c="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",s="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",f=/^#([0-9a-f]{3,8})$/,l=new RegExp("^rgb\\("+[u,u,u]+"\\)$"),h=new RegExp("^rgb\\("+[s,s,s]+"\\)$"),d=new RegExp("^rgba\\("+[u,u,u,c]+"\\)$"),p=new RegExp("^rgba\\("+[s,s,s,c]+"\\)$"),y=new RegExp("^hsl\\("+[c,s,s]+"\\)$"),b=new RegExp("^hsla\\("+[c,s,s,c]+"\\)$"),v={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074} -function g(){return this.rgb().formatHex()}function m(){return this.rgb().formatRgb()}function _(t){var e,n -return t=(t+"").trim().toLowerCase(),(e=f.exec(t))?(n=e[1].length,e=parseInt(e[1],16),6===n?w(e):3===n?new k(e>>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?x(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?x(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=l.exec(t))?new k(e[1],e[2],e[3],1):(e=h.exec(t))?new k(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=d.exec(t))?x(e[1],e[2],e[3],e[4]):(e=p.exec(t))?x(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=y.exec(t))?S(e[1],e[2]/100,e[3]/100,1):(e=b.exec(t))?S(e[1],e[2]/100,e[3]/100,e[4]):v.hasOwnProperty(t)?w(v[t]):"transparent"===t?new k(NaN,NaN,NaN,0):null}function w(t){return new k(t>>16&255,t>>8&255,255&t,1)}function x(t,e,n,r){return r<=0&&(t=e=n=NaN),new k(t,e,n,r)}function A(t){return t instanceof i||(t=_(t)),t?new k((t=t.rgb()).r,t.g,t.b,t.opacity):new k}function E(t,e,n,r){return 1===arguments.length?A(t):new k(t,e,n,null==r?1:r)}function k(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function D(){return"#"+O(this.r)+O(this.g)+O(this.b)}function C(){var t=this.opacity -return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function O(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function S(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new F(t,e,n,r)}function M(t){if(t instanceof F)return new F(t.h,t.s,t.l,t.opacity) -if(t instanceof i||(t=_(t)),!t)return new F -if(t instanceof F)return t -var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,o=Math.min(e,n,r),a=Math.max(e,n,r),u=NaN,c=a-o,s=(a+o)/2 -return c?(u=e===a?(n-r)/c+6*(n0&&s<1?0:u,new F(u,c,s,t.opacity)}function F(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function T(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}(0,r.Z)(i,_,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:g,formatHex:g,formatHsl:function(){return M(this).formatHsl()},formatRgb:m,toString:m}),(0,r.Z)(k,E,(0,r.l)(i,{brighter:function(t){return t=null==t?a:Math.pow(a,t),new k(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?o:Math.pow(o,t),new k(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:D,formatHex:D,formatRgb:C,toString:C})),(0,r.Z)(F,(function(t,e,n,r){return 1===arguments.length?M(t):new F(t,e,n,null==r?1:r)}),(0,r.l)(i,{brighter:function(t){return t=null==t?a:Math.pow(a,t),new F(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?o:Math.pow(o,t),new F(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r -return new k(T(t>=240?t-240:t+120,i,r),T(t,i,r),T(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity -return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}))},1572:(t,e,n)=>{"use strict" -function r(t,e,n){t.prototype=e.prototype=n,n.constructor=t}function i(t,e){var n=Object.create(t.prototype) -for(var r in e)n[r]=e[r] -return n}n.d(e,{Z:()=>r,l:()=>i})},901:(t,e,n)=>{"use strict" -n.d(e,{ZP:()=>u,wx:()=>o,yi:()=>a}) -var r=n(6436) -function i(t,e){return function(n){return t+n*e}}function o(t,e){var n=e-t -return n?i(t,n>180||n<-180?n-360*Math.round(n/360):n):(0,r.Z)(isNaN(t)?e:t)}function a(t){return 1==(t=+t)?u:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):(0,r.Z)(isNaN(e)?n:e)}}function u(t,e){var n=e-t -return n?i(t,n):(0,r.Z)(isNaN(t)?e:t)}},6436:(t,e,n)=>{"use strict" -n.d(e,{Z:()=>r}) -const r=t=>()=>t},9663:(t,e,n)=>{"use strict" -n.d(e,{ZP:()=>a,hD:()=>c}) -var r=n(7128) -function i(t,e,n,r,i){var o=t*t,a=o*t -return((1-3*t+3*o-a)*e+(4-6*o+3*a)*n+(1+3*t+3*o-3*a)*r+a*i)/6}var o=n(901) -const a=function t(e){var n=(0,o.yi)(e) -function i(t,e){var i=n((t=(0,r.B8)(t)).r,(e=(0,r.B8)(e)).r),a=n(t.g,e.g),u=n(t.b,e.b),c=(0,o.ZP)(t.opacity,e.opacity) -return function(e){return t.r=i(e),t.g=a(e),t.b=u(e),t.opacity=c(e),t+""}}return i.gamma=t,i}(1) -function u(t){return function(e){var n,i,o=e.length,a=new Array(o),u=new Array(o),c=new Array(o) -for(n=0;n=1?(n=1,e-1):Math.floor(n*e),o=t[r],a=t[r+1],u=r>0?t[r-1]:2*o-a,c=r{"use strict" -function r(t){for(var e=t.length/6|0,n=new Array(e),r=0;rot,interpolateBrBG:()=>v,interpolateBuGn:()=>j,interpolateBuPu:()=>R,interpolateCividis:()=>bt,interpolateCool:()=>Rt,interpolateCubehelixDefault:()=>jt,interpolateGnBu:()=>I,interpolateGreens:()=>ut,interpolateGreys:()=>st,interpolateInferno:()=>Gt,interpolateMagma:()=>Yt,interpolateOrRd:()=>U,interpolateOranges:()=>yt,interpolatePRGn:()=>m,interpolatePiYG:()=>w,interpolatePlasma:()=>Kt,interpolatePuBu:()=>V,interpolatePuBuGn:()=>Z,interpolatePuOr:()=>A,interpolatePuRd:()=>Y,interpolatePurples:()=>lt,interpolateRainbow:()=>It,interpolateRdBu:()=>k,interpolateRdGy:()=>C,interpolateRdPu:()=>K,interpolateRdYlBu:()=>S,interpolateRdYlGn:()=>F,interpolateReds:()=>dt,interpolateSinebow:()=>Zt,interpolateSpectral:()=>B,interpolateTurbo:()=>qt,interpolateViridis:()=>Ht,interpolateWarm:()=>Nt,interpolateYlGn:()=>Q,interpolateYlGnBu:()=>X,interpolateYlOrBr:()=>et,interpolateYlOrRd:()=>rt,schemeAccent:()=>o,schemeBlues:()=>it,schemeBrBG:()=>b,schemeBuGn:()=>P,schemeBuPu:()=>N,schemeCategory10:()=>i,schemeDark2:()=>a,schemeGnBu:()=>L,schemeGreens:()=>at,schemeGreys:()=>ct,schemeOrRd:()=>$,schemeOranges:()=>pt,schemePRGn:()=>g,schemePaired:()=>u,schemePastel1:()=>c,schemePastel2:()=>s,schemePiYG:()=>_,schemePuBu:()=>q,schemePuBuGn:()=>z,schemePuOr:()=>x,schemePuRd:()=>H,schemePurples:()=>ft,schemeRdBu:()=>E,schemeRdGy:()=>D,schemeRdPu:()=>G,schemeRdYlBu:()=>O,schemeRdYlGn:()=>M,schemeReds:()=>ht,schemeSet1:()=>f,schemeSet2:()=>l,schemeSet3:()=>h,schemeSpectral:()=>T,schemeTableau10:()=>d,schemeYlGn:()=>J,schemeYlGnBu:()=>W,schemeYlOrBr:()=>tt,schemeYlOrRd:()=>nt}) -const i=r("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"),o=r("7fc97fbeaed4fdc086ffff99386cb0f0027fbf5b17666666"),a=r("1b9e77d95f027570b3e7298a66a61ee6ab02a6761d666666"),u=r("a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928"),c=r("fbb4aeb3cde3ccebc5decbe4fed9a6ffffcce5d8bdfddaecf2f2f2"),s=r("b3e2cdfdcdaccbd5e8f4cae4e6f5c9fff2aef1e2cccccccc"),f=r("e41a1c377eb84daf4a984ea3ff7f00ffff33a65628f781bf999999"),l=r("66c2a5fc8d628da0cbe78ac3a6d854ffd92fe5c494b3b3b3"),h=r("8dd3c7ffffb3bebadafb807280b1d3fdb462b3de69fccde5d9d9d9bc80bdccebc5ffed6f"),d=r("4e79a7f28e2ce1575976b7b259a14fedc949af7aa1ff9da79c755fbab0ab") -var p=n(9663) -const y=t=>(0,p.hD)(t[t.length-1]) -var b=new Array(3).concat("d8b365f5f5f55ab4ac","a6611adfc27d80cdc1018571","a6611adfc27df5f5f580cdc1018571","8c510ad8b365f6e8c3c7eae55ab4ac01665e","8c510ad8b365f6e8c3f5f5f5c7eae55ab4ac01665e","8c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e","8c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e","5430058c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e003c30","5430058c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e003c30").map(r) -const v=y(b) -var g=new Array(3).concat("af8dc3f7f7f77fbf7b","7b3294c2a5cfa6dba0008837","7b3294c2a5cff7f7f7a6dba0008837","762a83af8dc3e7d4e8d9f0d37fbf7b1b7837","762a83af8dc3e7d4e8f7f7f7d9f0d37fbf7b1b7837","762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b7837","762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b7837","40004b762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b783700441b","40004b762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b783700441b").map(r) -const m=y(g) -var _=new Array(3).concat("e9a3c9f7f7f7a1d76a","d01c8bf1b6dab8e1864dac26","d01c8bf1b6daf7f7f7b8e1864dac26","c51b7de9a3c9fde0efe6f5d0a1d76a4d9221","c51b7de9a3c9fde0eff7f7f7e6f5d0a1d76a4d9221","c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221","c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221","8e0152c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221276419","8e0152c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221276419").map(r) -const w=y(_) -var x=new Array(3).concat("998ec3f7f7f7f1a340","5e3c99b2abd2fdb863e66101","5e3c99b2abd2f7f7f7fdb863e66101","542788998ec3d8daebfee0b6f1a340b35806","542788998ec3d8daebf7f7f7fee0b6f1a340b35806","5427888073acb2abd2d8daebfee0b6fdb863e08214b35806","5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b35806","2d004b5427888073acb2abd2d8daebfee0b6fdb863e08214b358067f3b08","2d004b5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b358067f3b08").map(r) -const A=y(x) -var E=new Array(3).concat("ef8a62f7f7f767a9cf","ca0020f4a58292c5de0571b0","ca0020f4a582f7f7f792c5de0571b0","b2182bef8a62fddbc7d1e5f067a9cf2166ac","b2182bef8a62fddbc7f7f7f7d1e5f067a9cf2166ac","b2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac","b2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac","67001fb2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac053061","67001fb2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac053061").map(r) -const k=y(E) -var D=new Array(3).concat("ef8a62ffffff999999","ca0020f4a582bababa404040","ca0020f4a582ffffffbababa404040","b2182bef8a62fddbc7e0e0e09999994d4d4d","b2182bef8a62fddbc7ffffffe0e0e09999994d4d4d","b2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d","b2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d","67001fb2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d1a1a1a","67001fb2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d1a1a1a").map(r) -const C=y(D) -var O=new Array(3).concat("fc8d59ffffbf91bfdb","d7191cfdae61abd9e92c7bb6","d7191cfdae61ffffbfabd9e92c7bb6","d73027fc8d59fee090e0f3f891bfdb4575b4","d73027fc8d59fee090ffffbfe0f3f891bfdb4575b4","d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4","d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4","a50026d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4313695","a50026d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4313695").map(r) -const S=y(O) -var M=new Array(3).concat("fc8d59ffffbf91cf60","d7191cfdae61a6d96a1a9641","d7191cfdae61ffffbfa6d96a1a9641","d73027fc8d59fee08bd9ef8b91cf601a9850","d73027fc8d59fee08bffffbfd9ef8b91cf601a9850","d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850","d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850","a50026d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850006837","a50026d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850006837").map(r) -const F=y(M) -var T=new Array(3).concat("fc8d59ffffbf99d594","d7191cfdae61abdda42b83ba","d7191cfdae61ffffbfabdda42b83ba","d53e4ffc8d59fee08be6f59899d5943288bd","d53e4ffc8d59fee08bffffbfe6f59899d5943288bd","d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd","d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd","9e0142d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd5e4fa2","9e0142d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd5e4fa2").map(r) -const B=y(T) -var P=new Array(3).concat("e5f5f999d8c92ca25f","edf8fbb2e2e266c2a4238b45","edf8fbb2e2e266c2a42ca25f006d2c","edf8fbccece699d8c966c2a42ca25f006d2c","edf8fbccece699d8c966c2a441ae76238b45005824","f7fcfde5f5f9ccece699d8c966c2a441ae76238b45005824","f7fcfde5f5f9ccece699d8c966c2a441ae76238b45006d2c00441b").map(r) -const j=y(P) -var N=new Array(3).concat("e0ecf49ebcda8856a7","edf8fbb3cde38c96c688419d","edf8fbb3cde38c96c68856a7810f7c","edf8fbbfd3e69ebcda8c96c68856a7810f7c","edf8fbbfd3e69ebcda8c96c68c6bb188419d6e016b","f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d6e016b","f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d810f7c4d004b").map(r) -const R=y(N) -var L=new Array(3).concat("e0f3dba8ddb543a2ca","f0f9e8bae4bc7bccc42b8cbe","f0f9e8bae4bc7bccc443a2ca0868ac","f0f9e8ccebc5a8ddb57bccc443a2ca0868ac","f0f9e8ccebc5a8ddb57bccc44eb3d32b8cbe08589e","f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe08589e","f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe0868ac084081").map(r) -const I=y(L) -var $=new Array(3).concat("fee8c8fdbb84e34a33","fef0d9fdcc8afc8d59d7301f","fef0d9fdcc8afc8d59e34a33b30000","fef0d9fdd49efdbb84fc8d59e34a33b30000","fef0d9fdd49efdbb84fc8d59ef6548d7301f990000","fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301f990000","fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301fb300007f0000").map(r) -const U=y($) -var z=new Array(3).concat("ece2f0a6bddb1c9099","f6eff7bdc9e167a9cf02818a","f6eff7bdc9e167a9cf1c9099016c59","f6eff7d0d1e6a6bddb67a9cf1c9099016c59","f6eff7d0d1e6a6bddb67a9cf3690c002818a016450","fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016450","fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016c59014636").map(r) -const Z=y(z) -var q=new Array(3).concat("ece7f2a6bddb2b8cbe","f1eef6bdc9e174a9cf0570b0","f1eef6bdc9e174a9cf2b8cbe045a8d","f1eef6d0d1e6a6bddb74a9cf2b8cbe045a8d","f1eef6d0d1e6a6bddb74a9cf3690c00570b0034e7b","fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0034e7b","fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0045a8d023858").map(r) -const V=y(q) -var H=new Array(3).concat("e7e1efc994c7dd1c77","f1eef6d7b5d8df65b0ce1256","f1eef6d7b5d8df65b0dd1c77980043","f1eef6d4b9dac994c7df65b0dd1c77980043","f1eef6d4b9dac994c7df65b0e7298ace125691003f","f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125691003f","f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125698004367001f").map(r) -const Y=y(H) -var G=new Array(3).concat("fde0ddfa9fb5c51b8a","feebe2fbb4b9f768a1ae017e","feebe2fbb4b9f768a1c51b8a7a0177","feebe2fcc5c0fa9fb5f768a1c51b8a7a0177","feebe2fcc5c0fa9fb5f768a1dd3497ae017e7a0177","fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a0177","fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a017749006a").map(r) -const K=y(G) -var W=new Array(3).concat("edf8b17fcdbb2c7fb8","ffffcca1dab441b6c4225ea8","ffffcca1dab441b6c42c7fb8253494","ffffccc7e9b47fcdbb41b6c42c7fb8253494","ffffccc7e9b47fcdbb41b6c41d91c0225ea80c2c84","ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea80c2c84","ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea8253494081d58").map(r) -const X=y(W) -var J=new Array(3).concat("f7fcb9addd8e31a354","ffffccc2e69978c679238443","ffffccc2e69978c67931a354006837","ffffccd9f0a3addd8e78c67931a354006837","ffffccd9f0a3addd8e78c67941ab5d238443005a32","ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443005a32","ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443006837004529").map(r) -const Q=y(J) -var tt=new Array(3).concat("fff7bcfec44fd95f0e","ffffd4fed98efe9929cc4c02","ffffd4fed98efe9929d95f0e993404","ffffd4fee391fec44ffe9929d95f0e993404","ffffd4fee391fec44ffe9929ec7014cc4c028c2d04","ffffe5fff7bcfee391fec44ffe9929ec7014cc4c028c2d04","ffffe5fff7bcfee391fec44ffe9929ec7014cc4c02993404662506").map(r) -const et=y(tt) -var nt=new Array(3).concat("ffeda0feb24cf03b20","ffffb2fecc5cfd8d3ce31a1c","ffffb2fecc5cfd8d3cf03b20bd0026","ffffb2fed976feb24cfd8d3cf03b20bd0026","ffffb2fed976feb24cfd8d3cfc4e2ae31a1cb10026","ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cb10026","ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cbd0026800026").map(r) -const rt=y(nt) -var it=new Array(3).concat("deebf79ecae13182bd","eff3ffbdd7e76baed62171b5","eff3ffbdd7e76baed63182bd08519c","eff3ffc6dbef9ecae16baed63182bd08519c","eff3ffc6dbef9ecae16baed64292c62171b5084594","f7fbffdeebf7c6dbef9ecae16baed64292c62171b5084594","f7fbffdeebf7c6dbef9ecae16baed64292c62171b508519c08306b").map(r) -const ot=y(it) -var at=new Array(3).concat("e5f5e0a1d99b31a354","edf8e9bae4b374c476238b45","edf8e9bae4b374c47631a354006d2c","edf8e9c7e9c0a1d99b74c47631a354006d2c","edf8e9c7e9c0a1d99b74c47641ab5d238b45005a32","f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45005a32","f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45006d2c00441b").map(r) -const ut=y(at) -var ct=new Array(3).concat("f0f0f0bdbdbd636363","f7f7f7cccccc969696525252","f7f7f7cccccc969696636363252525","f7f7f7d9d9d9bdbdbd969696636363252525","f7f7f7d9d9d9bdbdbd969696737373525252252525","fffffff0f0f0d9d9d9bdbdbd969696737373525252252525","fffffff0f0f0d9d9d9bdbdbd969696737373525252252525000000").map(r) -const st=y(ct) -var ft=new Array(3).concat("efedf5bcbddc756bb1","f2f0f7cbc9e29e9ac86a51a3","f2f0f7cbc9e29e9ac8756bb154278f","f2f0f7dadaebbcbddc9e9ac8756bb154278f","f2f0f7dadaebbcbddc9e9ac8807dba6a51a34a1486","fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a34a1486","fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a354278f3f007d").map(r) -const lt=y(ft) -var ht=new Array(3).concat("fee0d2fc9272de2d26","fee5d9fcae91fb6a4acb181d","fee5d9fcae91fb6a4ade2d26a50f15","fee5d9fcbba1fc9272fb6a4ade2d26a50f15","fee5d9fcbba1fc9272fb6a4aef3b2ccb181d99000d","fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181d99000d","fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181da50f1567000d").map(r) -const dt=y(ht) -var pt=new Array(3).concat("fee6cefdae6be6550d","feeddefdbe85fd8d3cd94701","feeddefdbe85fd8d3ce6550da63603","feeddefdd0a2fdae6bfd8d3ce6550da63603","feeddefdd0a2fdae6bfd8d3cf16913d948018c2d04","fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d948018c2d04","fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d94801a636037f2704").map(r) -const yt=y(pt) -function bt(t){return t=Math.max(0,Math.min(1,t)),"rgb("+Math.max(0,Math.min(255,Math.round(-4.54-t*(35.34-t*(2381.73-t*(6402.7-t*(7024.72-2710.57*t)))))))+", "+Math.max(0,Math.min(255,Math.round(32.49+t*(170.73+t*(52.82-t*(131.46-t*(176.58-67.37*t)))))))+", "+Math.max(0,Math.min(255,Math.round(81.24+t*(442.36-t*(2482.43-t*(6167.24-t*(6614.94-2475.67*t)))))))+")"}var vt=n(1572),gt=n(7128) -const mt=Math.PI/180,_t=180/Math.PI -var wt=-.14861,xt=1.78277,At=-.29227,Et=-.90649,kt=1.97294,Dt=kt*Et,Ct=kt*xt,Ot=xt*At-Et*wt -function St(t){if(t instanceof Ft)return new Ft(t.h,t.s,t.l,t.opacity) -t instanceof gt.Ss||(t=(0,gt.SU)(t)) -var e=t.r/255,n=t.g/255,r=t.b/255,i=(Ot*r+Dt*e-Ct*n)/(Ot+Dt-Ct),o=r-i,a=(kt*(n-i)-At*o)/Et,u=Math.sqrt(a*a+o*o)/(kt*i*(1-i)),c=u?Math.atan2(a,o)*_t-120:NaN -return new Ft(c<0?c+360:c,u,i,t.opacity)}function Mt(t,e,n,r){return 1===arguments.length?St(t):new Ft(t,e,n,null==r?1:r)}function Ft(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}(0,vt.Z)(Ft,Mt,(0,vt.l)(gt.Il,{brighter:function(t){return t=null==t?gt.J5:Math.pow(gt.J5,t),new Ft(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?gt.xV:Math.pow(gt.xV,t),new Ft(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=isNaN(this.h)?0:(this.h+120)*mt,e=+this.l,n=isNaN(this.s)?0:this.s*e*(1-e),r=Math.cos(t),i=Math.sin(t) -return new gt.Ss(255*(e+n*(wt*r+xt*i)),255*(e+n*(At*r+Et*i)),255*(e+n*(kt*r)),this.opacity)}})) -var Tt=n(901) -function Bt(t){return function e(n){function r(e,r){var i=t((e=Mt(e)).h,(r=Mt(r)).h),o=(0,Tt.ZP)(e.s,r.s),a=(0,Tt.ZP)(e.l,r.l),u=(0,Tt.ZP)(e.opacity,r.opacity) -return function(t){return e.h=i(t),e.s=o(t),e.l=a(Math.pow(t,n)),e.opacity=u(t),e+""}}return n=+n,r.gamma=e,r}(1)}Bt(Tt.wx) -var Pt=Bt(Tt.ZP) -const jt=Pt(Mt(300,.5,0),Mt(-240,.5,1)) -var Nt=Pt(Mt(-100,.75,.35),Mt(80,1.5,.8)),Rt=Pt(Mt(260,.75,.35),Mt(80,1.5,.8)),Lt=Mt() -function It(t){(t<0||t>1)&&(t-=Math.floor(t)) -var e=Math.abs(t-.5) -return Lt.h=360*t-100,Lt.s=1.5-1.5*e,Lt.l=.8-.9*e,Lt+""}var $t=(0,gt.B8)(),Ut=Math.PI/3,zt=2*Math.PI/3 -function Zt(t){var e -return t=(.5-t)*Math.PI,$t.r=255*(e=Math.sin(t))*e,$t.g=255*(e=Math.sin(t+Ut))*e,$t.b=255*(e=Math.sin(t+zt))*e,$t+""}function qt(t){return t=Math.max(0,Math.min(1,t)),"rgb("+Math.max(0,Math.min(255,Math.round(34.61+t*(1172.33-t*(10793.56-t*(33300.12-t*(38394.49-14825.05*t)))))))+", "+Math.max(0,Math.min(255,Math.round(23.31+t*(557.33+t*(1225.33-t*(3574.96-t*(1073.77+707.56*t)))))))+", "+Math.max(0,Math.min(255,Math.round(27.2+t*(3211.1-t*(15327.97-t*(27814-t*(22569.18-6838.66*t)))))))+")"}function Vt(t){var e=t.length -return function(n){return t[Math.max(0,Math.min(e-1,Math.floor(n*e)))]}}const Ht=Vt(r("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")) -var Yt=Vt(r("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")),Gt=Vt(r("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")),Kt=Vt(r("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"))},113:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{scaleBand:()=>c,scaleDiverging:()=>ur,scaleDivergingLog:()=>cr,scaleDivergingPow:()=>fr,scaleDivergingSqrt:()=>lr,scaleDivergingSymlog:()=>sr,scaleIdentity:()=>J,scaleImplicit:()=>a,scaleLinear:()=>X,scaleLog:()=>ut,scaleOrdinal:()=>u,scalePoint:()=>f,scalePow:()=>bt,scaleQuantile:()=>At,scaleQuantize:()=>Et,scaleRadial:()=>_t,scaleSequential:()=>Qn,scaleSequentialLog:()=>tr,scaleSequentialPow:()=>nr,scaleSequentialQuantile:()=>ir,scaleSequentialSqrt:()=>rr,scaleSequentialSymlog:()=>er,scaleSqrt:()=>vt,scaleSymlog:()=>lt,scaleThreshold:()=>kt,scaleTime:()=>Zn,scaleUtc:()=>Wn,tickFormat:()=>K}) -var r=n(1204) -function i(t,e){switch(arguments.length){case 0:break -case 1:this.range(t) -break -default:this.range(e).domain(t)}return this}function o(t,e){switch(arguments.length){case 0:break -case 1:"function"==typeof t?this.interpolator(t):this.range(t) -break -default:this.domain(t),"function"==typeof e?this.interpolator(e):this.range(e)}return this}const a=Symbol("implicit") -function u(){var t=new Map,e=[],n=[],r=a -function o(i){var o=i+"",u=t.get(o) -if(!u){if(r!==a)return r -t.set(o,u=e.push(i))}return n[(u-1)%n.length]}return o.domain=function(n){if(!arguments.length)return e.slice() -e=[],t=new Map -for(const r of n){const n=r+"" -t.has(n)||t.set(n,e.push(r))}return o},o.range=function(t){return arguments.length?(n=Array.from(t),o):n.slice()},o.unknown=function(t){return arguments.length?(r=t,o):r},o.copy=function(){return u(e,n).unknown(r)},i.apply(o,arguments),o}function c(){var t,e,n=u().unknown(void 0),o=n.domain,a=n.range,s=0,f=1,l=!1,h=0,d=0,p=.5 -function y(){var n=o().length,i=fo&&(i=e.slice(o,i),u[a]?u[a]+=i:u[++a]=i),(n=n[0])===(r=r[0])?u[a]?u[a]+=r:u[++a]=r:(u[++a]=null,c.push({i:a,x:v(n,r)})),o=_.lastIndex -return oe&&(n=t,t=e,e=n),s=function(n){return Math.max(t,Math.min(e,n))}),r=c>2?F:M,i=o=null,l}function l(e){return isNaN(e=+e)?n:(i||(i=r(a.map(t),u,c)))(t(s(e)))}return l.invert=function(n){return s(e((o||(o=r(u,a.map(t),v)))(n)))},l.domain=function(t){return arguments.length?(a=Array.from(t,D),f()):a.slice()},l.range=function(t){return arguments.length?(u=Array.from(t),f()):u.slice()},l.rangeRound=function(t){return u=Array.from(t),c=k,f()},l.clamp=function(t){return arguments.length?(s=!!t||O,f()):s!==O},l.interpolate=function(t){return arguments.length?(c=t,f()):c},l.unknown=function(t){return arguments.length?(n=t,l):n},function(n,r){return t=n,e=r,f()}}function P(){return B()(O,O)}var j,N=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i -function R(t){if(!(e=N.exec(t)))throw new Error("invalid format: "+t) -var e -return new L({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}function L(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function I(t,e){if((n=(t=e?t.toExponential(e-1):t.toExponential()).indexOf("e"))<0)return null -var n,r=t.slice(0,n) -return[r.length>1?r[0]+r.slice(2):r,+t.slice(n+1)]}function $(t){return(t=I(Math.abs(t)))?t[1]:NaN}function U(t,e){var n=I(t,e) -if(!n)return t+"" -var r=n[0],i=n[1] -return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}R.prototype=L.prototype,L.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type} -const z={"%":(t,e)=>(100*t).toFixed(e),b:t=>Math.round(t).toString(2),c:t=>t+"",d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:(t,e)=>t.toExponential(e),f:(t,e)=>t.toFixed(e),g:(t,e)=>t.toPrecision(e),o:t=>Math.round(t).toString(8),p:(t,e)=>U(100*t,e),r:U,s:function(t,e){var n=I(t,e) -if(!n)return t+"" -var r=n[0],i=n[1],o=i-(j=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,a=r.length -return o===a?r:o>a?r+new Array(o-a+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+I(t,Math.max(0,e+o-1))[0]},X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)} -function Z(t){return t}var q,V,H,Y=Array.prototype.map,G=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"] -function K(t,e,n,r){var i,o=(0,l.ly)(t,e,n) -switch((r=R(null==r?",f":r)).type){case"s":var a=Math.max(Math.abs(t),Math.abs(e)) -return null!=r.precision||isNaN(i=function(t,e){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor($(e)/3)))-$(Math.abs(t)))}(o,a))||(r.precision=i),H(r,a) -case"":case"e":case"g":case"p":case"r":null!=r.precision||isNaN(i=function(t,e){return t=Math.abs(t),e=Math.abs(e)-t,Math.max(0,$(e)-$(t))+1}(o,Math.max(Math.abs(t),Math.abs(e))))||(r.precision=i-("e"===r.type)) -break -case"f":case"%":null!=r.precision||isNaN(i=function(t){return Math.max(0,-$(Math.abs(t)))}(o))||(r.precision=i-2*("%"===r.type))}return V(r)}function W(t){var e=t.domain -return t.ticks=function(t){var n=e() -return(0,l.ZP)(n[0],n[n.length-1],null==t?10:t)},t.tickFormat=function(t,n){var r=e() -return K(r[0],r[r.length-1],null==t?10:t,n)},t.nice=function(n){null==n&&(n=10) -var r,i,o=e(),a=0,u=o.length-1,c=o[a],s=o[u],f=10 -for(s0;){if((i=(0,l.G9)(c,s,n))===r)return o[a]=c,o[u]=s,e(o) -if(i>0)c=Math.floor(c/i)*i,s=Math.ceil(s/i)*i -else{if(!(i<0))break -c=Math.ceil(c*i)/i,s=Math.floor(s*i)/i}r=i}return t},t}function X(){var t=P() -return t.copy=function(){return T(t,X())},i.apply(t,arguments),W(t)}function J(t){var e -function n(t){return isNaN(t=+t)?e:t}return n.invert=n,n.domain=n.range=function(e){return arguments.length?(t=Array.from(e,D),n):t.slice()},n.unknown=function(t){return arguments.length?(e=t,n):e},n.copy=function(){return J(t).unknown(e)},t=arguments.length?Array.from(t,D):[0,1],W(n)}function Q(t,e){var n,r=0,i=(t=t.slice()).length-1,o=t[r],a=t[i] -return a0){for(;d<=p;++d)for(f=1,s=n(d);fc)break -b.push(h)}}else for(;d<=p;++d)for(f=o-1,s=n(d);f>=1;--f)if(!((h=s*f)c)break -b.push(h)}2*b.length0&&u>0&&(c+u+1>r&&(u=Math.max(1,r-c)),o.push(t.substring(i-=u,i+u)),!((c+=u+1)>r));)u=e[a=(a+1)%e.length] -return o.reverse().join(n)}),i=void 0===t.currency?"":t.currency[0]+"",o=void 0===t.currency?"":t.currency[1]+"",a=void 0===t.decimal?".":t.decimal+"",u=void 0===t.numerals?Z:function(t){return function(e){return e.replace(/[0-9]/g,(function(e){return t[+e]}))}}(Y.call(t.numerals,String)),c=void 0===t.percent?"%":t.percent+"",s=void 0===t.minus?"−":t.minus+"",f=void 0===t.nan?"NaN":t.nan+"" -function l(t){var e=(t=R(t)).fill,n=t.align,l=t.sign,h=t.symbol,d=t.zero,p=t.width,y=t.comma,b=t.precision,v=t.trim,g=t.type -"n"===g?(y=!0,g="g"):z[g]||(void 0===b&&(b=12),v=!0,g="g"),(d||"0"===e&&"="===n)&&(d=!0,e="0",n="=") -var m="$"===h?i:"#"===h&&/[boxX]/.test(g)?"0"+g.toLowerCase():"",_="$"===h?o:/[%p]/.test(g)?c:"",w=z[g],x=/[defgprs%]/.test(g) -function A(t){var i,o,c,h=m,A=_ -if("c"===g)A=w(t)+A,t="" -else{var E=(t=+t)<0||1/t<0 -if(t=isNaN(t)?f:w(Math.abs(t),b),v&&(t=function(t){t:for(var e,n=t.length,r=1,i=-1;r0&&(i=0)}return i>0?t.slice(0,i)+t.slice(e+1):t}(t)),E&&0==+t&&"+"!==l&&(E=!1),h=(E?"("===l?l:s:"-"===l||"("===l?"":l)+h,A=("s"===g?G[8+j/3]:"")+A+(E&&"("===l?")":""),x)for(i=-1,o=t.length;++i(c=t.charCodeAt(i))||c>57){A=(46===c?a+t.slice(i+1):t.slice(i))+A,t=t.slice(0,i) -break}}y&&!d&&(t=r(t,1/0)) -var k=h.length+t.length+A.length,D=k>1)+h+t+A+D.slice(k) -break -default:t=D+h+t+A}return u(t)}return b=void 0===b?6:/[gprs]/.test(g)?Math.max(1,Math.min(21,b)):Math.max(0,Math.min(20,b)),A.toString=function(){return t+""},A}return{format:l,formatPrefix:function(t,e){var n=l(((t=R(t)).type="f",t)),r=3*Math.max(-8,Math.min(8,Math.floor($(e)/3))),i=Math.pow(10,-r),o=G[8+r/3] -return function(t){return n(i*t)+o}}}}({thousands:",",grouping:[3],currency:["$",""]}),V=q.format,H=q.formatPrefix -var wt=n(801),xt=n(7604) -function At(){var t,e=[],n=[],r=[] -function o(){var t=0,i=Math.max(1,n.length) -for(r=new Array(i-1);++t0?r[i-1]:e[0],i=r?[o[r-1],n]:[o[i-1],o[i]]},u.unknown=function(e){return arguments.length?(t=e,u):u},u.thresholds=function(){return o.slice()},u.copy=function(){return Et().domain([e,n]).range(a).unknown(t)},i.apply(W(u),arguments)}function kt(){var t,e=[.5],n=[0,1],r=1 -function o(i){return i<=i?n[(0,h.ZP)(e,i,0,r)]:t}return o.domain=function(t){return arguments.length?(e=Array.from(t),r=Math.min(e.length,n.length-1),o):e.slice()},o.range=function(t){return arguments.length?(n=Array.from(t),r=Math.min(e.length,n.length-1),o):n.slice()},o.invertExtent=function(t){var r=n.indexOf(t) -return[e[r-1],e[r]]},o.unknown=function(e){return arguments.length?(t=e,o):t},o.copy=function(){return kt().domain(e).range(n).unknown(t)},i.apply(o,arguments)}var Dt=n(9354),Ct=new Date,Ot=new Date -function St(t,e,n,r){function i(e){return t(e=0===arguments.length?new Date:new Date(+e)),e}return i.floor=function(e){return t(e=new Date(+e)),e},i.ceil=function(n){return t(n=new Date(n-1)),e(n,1),t(n),n},i.round=function(t){var e=i(t),n=i.ceil(t) -return t-e0))return u -do{u.push(a=new Date(+n)),e(n,o),t(n)}while(a=e)for(;t(e),!n(e);)e.setTime(e-1)}),(function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;e(t,-1),!n(t););else for(;--r>=0;)for(;e(t,1),!n(t););}))},n&&(i.count=function(e,r){return Ct.setTime(+e),Ot.setTime(+r),t(Ct),t(Ot),Math.floor(n(Ct,Ot))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(e){return r(e)%t==0}:function(e){return i.count(0,e)%t==0}):i:null}),i}var Mt=St((function(t){t.setMonth(0,1),t.setHours(0,0,0,0)}),(function(t,e){t.setFullYear(t.getFullYear()+e)}),(function(t,e){return e.getFullYear()-t.getFullYear()}),(function(t){return t.getFullYear()})) -Mt.every=function(t){return isFinite(t=Math.floor(t))&&t>0?St((function(e){e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)}),(function(e,n){e.setFullYear(e.getFullYear()+n*t)})):null} -const Ft=Mt -Mt.range -var Tt=St((function(t){t.setDate(1),t.setHours(0,0,0,0)}),(function(t,e){t.setMonth(t.getMonth()+e)}),(function(t,e){return e.getMonth()-t.getMonth()+12*(e.getFullYear()-t.getFullYear())}),(function(t){return t.getMonth()})) -const Bt=Tt -Tt.range -var Pt=1e3,jt=6e4,Nt=36e5,Rt=864e5,Lt=6048e5 -function It(t){return St((function(e){e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)}),(function(t,e){t.setDate(t.getDate()+7*e)}),(function(t,e){return(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*jt)/Lt}))}var $t=It(0),Ut=It(1),zt=It(2),Zt=It(3),qt=It(4),Vt=It(5),Ht=It(6),Yt=($t.range,Ut.range,zt.range,Zt.range,qt.range,Vt.range,Ht.range,St((t=>t.setHours(0,0,0,0)),((t,e)=>t.setDate(t.getDate()+e)),((t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*jt)/Rt),(t=>t.getDate()-1))) -const Gt=Yt -Yt.range -var Kt=St((function(t){t.setTime(t-t.getMilliseconds()-t.getSeconds()*Pt-t.getMinutes()*jt)}),(function(t,e){t.setTime(+t+e*Nt)}),(function(t,e){return(e-t)/Nt}),(function(t){return t.getHours()})) -const Wt=Kt -Kt.range -var Xt=St((function(t){t.setTime(t-t.getMilliseconds()-t.getSeconds()*Pt)}),(function(t,e){t.setTime(+t+e*jt)}),(function(t,e){return(e-t)/jt}),(function(t){return t.getMinutes()})) -const Jt=Xt -Xt.range -var Qt=St((function(t){t.setTime(t-t.getMilliseconds())}),(function(t,e){t.setTime(+t+e*Pt)}),(function(t,e){return(e-t)/Pt}),(function(t){return t.getUTCSeconds()})) -const te=Qt -Qt.range -var ee=St((function(){}),(function(t,e){t.setTime(+t+e)}),(function(t,e){return e-t})) -ee.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?St((function(e){e.setTime(Math.floor(e/t)*t)}),(function(e,n){e.setTime(+e+n*t)}),(function(e,n){return(n-e)/t})):ee:null} -const ne=ee -function re(t){return St((function(e){e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+7*e)}),(function(t,e){return(e-t)/Lt}))}ee.range -var ie=re(0),oe=re(1),ae=re(2),ue=re(3),ce=re(4),se=re(5),fe=re(6),le=(ie.range,oe.range,ae.range,ue.range,ce.range,se.range,fe.range,St((function(t){t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+e)}),(function(t,e){return(e-t)/Rt}),(function(t){return t.getUTCDate()-1}))) -const he=le -le.range -var de=St((function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCFullYear(t.getUTCFullYear()+e)}),(function(t,e){return e.getUTCFullYear()-t.getUTCFullYear()}),(function(t){return t.getUTCFullYear()})) -de.every=function(t){return isFinite(t=Math.floor(t))&&t>0?St((function(e){e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)}),(function(e,n){e.setUTCFullYear(e.getUTCFullYear()+n*t)})):null} -const pe=de -function ye(t){if(0<=t.y&&t.y<100){var e=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L) -return e.setFullYear(t.y),e}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function be(t){if(0<=t.y&&t.y<100){var e=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L)) -return e.setUTCFullYear(t.y),e}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function ve(t,e,n){return{y:t,m:e,d:n,H:0,M:0,S:0,L:0}}de.range -var ge,me,_e,we={"-":"",_:" ",0:"0"},xe=/^\s*\d+/,Ae=/^%/,Ee=/[\\^$*+?|[\]().{}]/g -function ke(t,e,n){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length -return r+(o[t.toLowerCase(),e])))}function Se(t,e,n){var r=xe.exec(e.slice(n,n+1)) -return r?(t.w=+r[0],n+r[0].length):-1}function Me(t,e,n){var r=xe.exec(e.slice(n,n+1)) -return r?(t.u=+r[0],n+r[0].length):-1}function Fe(t,e,n){var r=xe.exec(e.slice(n,n+2)) -return r?(t.U=+r[0],n+r[0].length):-1}function Te(t,e,n){var r=xe.exec(e.slice(n,n+2)) -return r?(t.V=+r[0],n+r[0].length):-1}function Be(t,e,n){var r=xe.exec(e.slice(n,n+2)) -return r?(t.W=+r[0],n+r[0].length):-1}function Pe(t,e,n){var r=xe.exec(e.slice(n,n+4)) -return r?(t.y=+r[0],n+r[0].length):-1}function je(t,e,n){var r=xe.exec(e.slice(n,n+2)) -return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function Ne(t,e,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(n,n+6)) -return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function Re(t,e,n){var r=xe.exec(e.slice(n,n+1)) -return r?(t.q=3*r[0]-3,n+r[0].length):-1}function Le(t,e,n){var r=xe.exec(e.slice(n,n+2)) -return r?(t.m=r[0]-1,n+r[0].length):-1}function Ie(t,e,n){var r=xe.exec(e.slice(n,n+2)) -return r?(t.d=+r[0],n+r[0].length):-1}function $e(t,e,n){var r=xe.exec(e.slice(n,n+3)) -return r?(t.m=0,t.d=+r[0],n+r[0].length):-1}function Ue(t,e,n){var r=xe.exec(e.slice(n,n+2)) -return r?(t.H=+r[0],n+r[0].length):-1}function ze(t,e,n){var r=xe.exec(e.slice(n,n+2)) -return r?(t.M=+r[0],n+r[0].length):-1}function Ze(t,e,n){var r=xe.exec(e.slice(n,n+2)) -return r?(t.S=+r[0],n+r[0].length):-1}function qe(t,e,n){var r=xe.exec(e.slice(n,n+3)) -return r?(t.L=+r[0],n+r[0].length):-1}function Ve(t,e,n){var r=xe.exec(e.slice(n,n+6)) -return r?(t.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function He(t,e,n){var r=Ae.exec(e.slice(n,n+1)) -return r?n+r[0].length:-1}function Ye(t,e,n){var r=xe.exec(e.slice(n)) -return r?(t.Q=+r[0],n+r[0].length):-1}function Ge(t,e,n){var r=xe.exec(e.slice(n)) -return r?(t.s=+r[0],n+r[0].length):-1}function Ke(t,e){return ke(t.getDate(),e,2)}function We(t,e){return ke(t.getHours(),e,2)}function Xe(t,e){return ke(t.getHours()%12||12,e,2)}function Je(t,e){return ke(1+Gt.count(Ft(t),t),e,3)}function Qe(t,e){return ke(t.getMilliseconds(),e,3)}function tn(t,e){return Qe(t,e)+"000"}function en(t,e){return ke(t.getMonth()+1,e,2)}function nn(t,e){return ke(t.getMinutes(),e,2)}function rn(t,e){return ke(t.getSeconds(),e,2)}function on(t){var e=t.getDay() -return 0===e?7:e}function an(t,e){return ke($t.count(Ft(t)-1,t),e,2)}function un(t){var e=t.getDay() -return e>=4||0===e?qt(t):qt.ceil(t)}function cn(t,e){return t=un(t),ke(qt.count(Ft(t),t)+(4===Ft(t).getDay()),e,2)}function sn(t){return t.getDay()}function fn(t,e){return ke(Ut.count(Ft(t)-1,t),e,2)}function ln(t,e){return ke(t.getFullYear()%100,e,2)}function hn(t,e){return ke((t=un(t)).getFullYear()%100,e,2)}function dn(t,e){return ke(t.getFullYear()%1e4,e,4)}function pn(t,e){var n=t.getDay() -return ke((t=n>=4||0===n?qt(t):qt.ceil(t)).getFullYear()%1e4,e,4)}function yn(t){var e=t.getTimezoneOffset() -return(e>0?"-":(e*=-1,"+"))+ke(e/60|0,"0",2)+ke(e%60,"0",2)}function bn(t,e){return ke(t.getUTCDate(),e,2)}function vn(t,e){return ke(t.getUTCHours(),e,2)}function gn(t,e){return ke(t.getUTCHours()%12||12,e,2)}function mn(t,e){return ke(1+he.count(pe(t),t),e,3)}function _n(t,e){return ke(t.getUTCMilliseconds(),e,3)}function wn(t,e){return _n(t,e)+"000"}function xn(t,e){return ke(t.getUTCMonth()+1,e,2)}function An(t,e){return ke(t.getUTCMinutes(),e,2)}function En(t,e){return ke(t.getUTCSeconds(),e,2)}function kn(t){var e=t.getUTCDay() -return 0===e?7:e}function Dn(t,e){return ke(ie.count(pe(t)-1,t),e,2)}function Cn(t){var e=t.getUTCDay() -return e>=4||0===e?ce(t):ce.ceil(t)}function On(t,e){return t=Cn(t),ke(ce.count(pe(t),t)+(4===pe(t).getUTCDay()),e,2)}function Sn(t){return t.getUTCDay()}function Mn(t,e){return ke(oe.count(pe(t)-1,t),e,2)}function Fn(t,e){return ke(t.getUTCFullYear()%100,e,2)}function Tn(t,e){return ke((t=Cn(t)).getUTCFullYear()%100,e,2)}function Bn(t,e){return ke(t.getUTCFullYear()%1e4,e,4)}function Pn(t,e){var n=t.getUTCDay() -return ke((t=n>=4||0===n?ce(t):ce.ceil(t)).getUTCFullYear()%1e4,e,4)}function jn(){return"+0000"}function Nn(){return"%"}function Rn(t){return+t}function Ln(t){return Math.floor(+t/1e3)}ge=function(t){var e=t.dateTime,n=t.date,r=t.time,i=t.periods,o=t.days,a=t.shortDays,u=t.months,c=t.shortMonths,s=Ce(i),f=Oe(i),l=Ce(o),h=Oe(o),d=Ce(a),p=Oe(a),y=Ce(u),b=Oe(u),v=Ce(c),g=Oe(c),m={a:function(t){return a[t.getDay()]},A:function(t){return o[t.getDay()]},b:function(t){return c[t.getMonth()]},B:function(t){return u[t.getMonth()]},c:null,d:Ke,e:Ke,f:tn,g:hn,G:pn,H:We,I:Xe,j:Je,L:Qe,m:en,M:nn,p:function(t){return i[+(t.getHours()>=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:Rn,s:Ln,S:rn,u:on,U:an,V:cn,w:sn,W:fn,x:null,X:null,y:ln,Y:dn,Z:yn,"%":Nn},_={a:function(t){return a[t.getUTCDay()]},A:function(t){return o[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return u[t.getUTCMonth()]},c:null,d:bn,e:bn,f:wn,g:Tn,G:Pn,H:vn,I:gn,j:mn,L:_n,m:xn,M:An,p:function(t){return i[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:Rn,s:Ln,S:En,u:kn,U:Dn,V:On,w:Sn,W:Mn,x:null,X:null,y:Fn,Y:Bn,Z:jn,"%":Nn},w={a:function(t,e,n){var r=d.exec(e.slice(n)) -return r?(t.w=p.get(r[0].toLowerCase()),n+r[0].length):-1},A:function(t,e,n){var r=l.exec(e.slice(n)) -return r?(t.w=h.get(r[0].toLowerCase()),n+r[0].length):-1},b:function(t,e,n){var r=v.exec(e.slice(n)) -return r?(t.m=g.get(r[0].toLowerCase()),n+r[0].length):-1},B:function(t,e,n){var r=y.exec(e.slice(n)) -return r?(t.m=b.get(r[0].toLowerCase()),n+r[0].length):-1},c:function(t,n,r){return E(t,e,n,r)},d:Ie,e:Ie,f:Ve,g:je,G:Pe,H:Ue,I:Ue,j:$e,L:qe,m:Le,M:ze,p:function(t,e,n){var r=s.exec(e.slice(n)) -return r?(t.p=f.get(r[0].toLowerCase()),n+r[0].length):-1},q:Re,Q:Ye,s:Ge,S:Ze,u:Me,U:Fe,V:Te,w:Se,W:Be,x:function(t,e,r){return E(t,n,e,r)},X:function(t,e,n){return E(t,r,e,n)},y:je,Y:Pe,Z:Ne,"%":He} -function x(t,e){return function(n){var r,i,o,a=[],u=-1,c=0,s=t.length -for(n instanceof Date||(n=new Date(+n));++u53)return null -"w"in o||(o.w=1),"Z"in o?(i=(r=be(ve(o.y,0,1))).getUTCDay(),r=i>4||0===i?oe.ceil(r):oe(r),r=he.offset(r,7*(o.V-1)),o.y=r.getUTCFullYear(),o.m=r.getUTCMonth(),o.d=r.getUTCDate()+(o.w+6)%7):(i=(r=ye(ve(o.y,0,1))).getDay(),r=i>4||0===i?Ut.ceil(r):Ut(r),r=Gt.offset(r,7*(o.V-1)),o.y=r.getFullYear(),o.m=r.getMonth(),o.d=r.getDate()+(o.w+6)%7)}else("W"in o||"U"in o)&&("w"in o||(o.w="u"in o?o.u%7:"W"in o?1:0),i="Z"in o?be(ve(o.y,0,1)).getUTCDay():ye(ve(o.y,0,1)).getDay(),o.m=0,o.d="W"in o?(o.w+6)%7+7*o.W-(i+5)%7:o.w+7*o.U-(i+6)%7) -return"Z"in o?(o.H+=o.Z/100|0,o.M+=o.Z%100,be(o)):ye(o)}}function E(t,e,n,r){for(var i,o,a=0,u=e.length,c=n.length;a=c)return-1 -if(37===(i=e.charCodeAt(a++))){if(i=e.charAt(a++),!(o=w[i in we?e.charAt(a++):i])||(r=o(t,n,r))<0)return-1}else if(i!=n.charCodeAt(r++))return-1}return r}return m.x=x(n,m),m.X=x(r,m),m.c=x(e,m),_.x=x(n,_),_.X=x(r,_),_.c=x(e,_),{format:function(t){var e=x(t+="",m) -return e.toString=function(){return t},e},parse:function(t){var e=A(t+="",!1) -return e.toString=function(){return t},e},utcFormat:function(t){var e=x(t+="",_) -return e.toString=function(){return t},e},utcParse:function(t){var e=A(t+="",!0) -return e.toString=function(){return t},e}}}({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}),me=ge.format,ge.parse,_e=ge.utcFormat,ge.utcParse -var In=31536e6 -function $n(t){return new Date(t)}function Un(t){return t instanceof Date?+t:+new Date(+t)}function zn(t,e,n,r,i,o,a,u,c){var s=P(),f=s.invert,h=s.domain,d=c(".%L"),p=c(":%S"),y=c("%I:%M"),b=c("%I %p"),v=c("%a %d"),g=c("%b %d"),m=c("%B"),_=c("%Y"),w=[[a,1,1e3],[a,5,5e3],[a,15,15e3],[a,30,3e4],[o,1,6e4],[o,5,3e5],[o,15,9e5],[o,30,18e5],[i,1,36e5],[i,3,108e5],[i,6,216e5],[i,12,432e5],[r,1,864e5],[r,2,1728e5],[n,1,6048e5],[e,1,2592e6],[e,3,7776e6],[t,1,In]] -function x(u){return(a(u)e(r/(t.length-1))))},n.quantiles=function(e){return Array.from({length:e+1},((n,r)=>(0,wt.Z)(t,r/e)))},n.copy=function(){return ir(e).domain(t)},o.apply(n,arguments)}function or(t,e){void 0===e&&(e=t,t=E) -for(var n=0,r=e.length-1,i=e[0],o=new Array(r<0?0:r);n{"use strict" -n.r(e),n.d(e,{create:()=>gt,creator:()=>c,local:()=>_t,matcher:()=>p,namespace:()=>o,namespaces:()=>i,pointer:()=>At,pointers:()=>Et,select:()=>vt,selectAll:()=>kt,selection:()=>bt,selector:()=>f,selectorAll:()=>d,style:()=>R,window:()=>B}) -var r="http://www.w3.org/1999/xhtml" -const i={svg:"http://www.w3.org/2000/svg",xhtml:r,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"} -function o(t){var e=t+="",n=e.indexOf(":") -return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),i.hasOwnProperty(e)?{space:i[e],local:t}:t}function a(t){return function(){var e=this.ownerDocument,n=this.namespaceURI -return n===r&&e.documentElement.namespaceURI===r?e.createElement(t):e.createElementNS(n,t)}}function u(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function c(t){var e=o(t) -return(e.local?u:a)(e)}function s(){}function f(t){return null==t?s:function(){return this.querySelector(t)}}function l(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}function h(){return[]}function d(t){return null==t?h:function(){return this.querySelectorAll(t)}}function p(t){return function(){return this.matches(t)}}function y(t){return function(e){return e.matches(t)}}var b=Array.prototype.find -function v(){return this.firstElementChild}var g=Array.prototype.filter -function m(){return this.children}function _(t){return new Array(t.length)}function w(t,e){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=e}function x(t){return function(){return t}}function A(t,e,n,r,i,o){for(var a,u=0,c=e.length,s=o.length;ue?1:t>=e?0:NaN}function C(t){return function(){this.removeAttribute(t)}}function O(t){return function(){this.removeAttributeNS(t.space,t.local)}}function S(t,e){return function(){this.setAttribute(t,e)}}function M(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function F(t,e){return function(){var n=e.apply(this,arguments) -null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function T(t,e){return function(){var n=e.apply(this,arguments) -null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}function B(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function P(t){return function(){this.style.removeProperty(t)}}function j(t,e,n){return function(){this.style.setProperty(t,e,n)}}function N(t,e,n){return function(){var r=e.apply(this,arguments) -null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function R(t,e){return t.style.getPropertyValue(e)||B(t).getComputedStyle(t,null).getPropertyValue(e)}function L(t){return function(){delete this[t]}}function I(t,e){return function(){this[t]=e}}function $(t,e){return function(){var n=e.apply(this,arguments) -null==n?delete this[t]:this[t]=n}}function U(t){return t.trim().split(/^|\s+/)}function z(t){return t.classList||new Z(t)}function Z(t){this._node=t,this._names=U(t.getAttribute("class")||"")}function q(t,e){for(var n=z(t),r=-1,i=e.length;++r=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function ct(t){return function(){var e=this.__on -if(e){for(var n,r=0,i=-1,o=e.length;r=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}} -var dt=[null] -function pt(t,e){this._groups=t,this._parents=e}function yt(){return new pt([[document.documentElement]],dt)}pt.prototype=yt.prototype={constructor:pt,select:function(t){"function"!=typeof t&&(t=f(t)) -for(var e=this._groups,n=e.length,r=new Array(n),i=0;i=D&&(D=w+1);!(_=v[D])&&++D=0;)(r=i[o])&&(a&&4^r.compareDocumentPosition(a)&&a.parentNode.insertBefore(r,a),a=r) -return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=D) -for(var n=this._groups,r=n.length,i=new Array(r),o=0;o1?this.each((null==e?P:"function"==typeof e?N:j)(t,e,null==n?"":n)):R(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?L:"function"==typeof e?$:I)(t,e)):this.node()[t]},classed:function(t,e){var n=U(t+"") -if(arguments.length<2){for(var r=z(this.node()),i=-1,o=n.length;++iAt(t,e)))}function kt(t){return"string"==typeof t?new pt([document.querySelectorAll(t)],[document.documentElement]):new pt([null==t?[]:l(t)],dt)}wt.prototype=_t.prototype={constructor:wt,get:function(t){for(var e=this._;!(e in t);)if(!(t=t.parentNode))return -return t[e]},set:function(t,e){return t[this._]=e},remove:function(t){return this._ in t&&delete t[this._]},toString:function(){return this._}}},6736:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{arc:()=>F,area:()=>I,areaRadial:()=>G,curveBasis:()=>Ct,curveBasisClosed:()=>St,curveBasisOpen:()=>Ft,curveBumpX:()=>Bt,curveBumpY:()=>Pt,curveBundle:()=>Nt,curveCardinal:()=>It,curveCardinalClosed:()=>Ut,curveCardinalOpen:()=>Zt,curveCatmullRom:()=>Ht,curveCatmullRomClosed:()=>Gt,curveCatmullRomOpen:()=>Wt,curveLinear:()=>j,curveLinearClosed:()=>Jt,curveMonotoneX:()=>ae,curveMonotoneY:()=>ue,curveNatural:()=>fe,curveStep:()=>he,curveStepAfter:()=>pe,curveStepBefore:()=>de,line:()=>L,lineRadial:()=>Y,linkHorizontal:()=>nt,linkRadial:()=>it,linkVertical:()=>rt,pie:()=>z,pointRadial:()=>K,radialArea:()=>G,radialLine:()=>Y,stack:()=>me,stackOffsetDiverging:()=>we,stackOffsetExpand:()=>_e,stackOffsetNone:()=>ye,stackOffsetSilhouette:()=>xe,stackOffsetWiggle:()=>Ae,stackOrderAppearance:()=>Ee,stackOrderAscending:()=>De,stackOrderDescending:()=>Oe,stackOrderInsideOut:()=>Se,stackOrderNone:()=>be,stackOrderReverse:()=>Me,symbol:()=>At,symbolCircle:()=>ot,symbolCross:()=>at,symbolDiamond:()=>st,symbolSquare:()=>pt,symbolStar:()=>dt,symbolTriangle:()=>bt,symbolWye:()=>wt,symbols:()=>xt}) -const r=Math.PI,i=2*r,o=1e-6,a=i-o -function u(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function c(){return new u}u.prototype=c.prototype={constructor:u,moveTo:function(t,e){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)},closePath:function(){null!==this._x1&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,e){this._+="L"+(this._x1=+t)+","+(this._y1=+e)},quadraticCurveTo:function(t,e,n,r){this._+="Q"+ +t+","+ +e+","+(this._x1=+n)+","+(this._y1=+r)},bezierCurveTo:function(t,e,n,r,i,o){this._+="C"+ +t+","+ +e+","+ +n+","+ +r+","+(this._x1=+i)+","+(this._y1=+o)},arcTo:function(t,e,n,i,a){t=+t,e=+e,n=+n,i=+i,a=+a -var u=this._x1,c=this._y1,s=n-t,f=i-e,l=u-t,h=c-e,d=l*l+h*h -if(a<0)throw new Error("negative radius: "+a) -if(null===this._x1)this._+="M"+(this._x1=t)+","+(this._y1=e) -else if(d>o)if(Math.abs(h*s-f*l)>o&&a){var p=n-u,y=i-c,b=s*s+f*f,v=p*p+y*y,g=Math.sqrt(b),m=Math.sqrt(d),_=a*Math.tan((r-Math.acos((b+d-v)/(2*g*m)))/2),w=_/m,x=_/g -Math.abs(w-1)>o&&(this._+="L"+(t+w*l)+","+(e+w*h)),this._+="A"+a+","+a+",0,0,"+ +(h*p>l*y)+","+(this._x1=t+x*s)+","+(this._y1=e+x*f)}else this._+="L"+(this._x1=t)+","+(this._y1=e)},arc:function(t,e,n,u,c,s){t=+t,e=+e,s=!!s -var f=(n=+n)*Math.cos(u),l=n*Math.sin(u),h=t+f,d=e+l,p=1^s,y=s?u-c:c-u -if(n<0)throw new Error("negative radius: "+n) -null===this._x1?this._+="M"+h+","+d:(Math.abs(this._x1-h)>o||Math.abs(this._y1-d)>o)&&(this._+="L"+h+","+d),n&&(y<0&&(y=y%i+i),y>a?this._+="A"+n+","+n+",0,1,"+p+","+(t-f)+","+(e-l)+"A"+n+","+n+",0,1,"+p+","+(this._x1=h)+","+(this._y1=d):y>o&&(this._+="A"+n+","+n+",0,"+ +(y>=r)+","+p+","+(this._x1=t+n*Math.cos(c))+","+(this._y1=e+n*Math.sin(c))))},rect:function(t,e,n,r){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)+"h"+ +n+"v"+ +r+"h"+-n+"Z"},toString:function(){return this._}} -const s=c -function f(t){return function(){return t}}var l=Math.abs,h=Math.atan2,d=Math.cos,p=Math.max,y=Math.min,b=Math.sin,v=Math.sqrt,g=1e-12,m=Math.PI,_=m/2,w=2*m -function x(t){return t>1?0:t<-1?m:Math.acos(t)}function A(t){return t>=1?_:t<=-1?-_:Math.asin(t)}function E(t){return t.innerRadius}function k(t){return t.outerRadius}function D(t){return t.startAngle}function C(t){return t.endAngle}function O(t){return t&&t.padAngle}function S(t,e,n,r,i,o,a,u){var c=n-t,s=r-e,f=a-i,l=u-o,h=l*c-f*s -if(!(h*hT*T+B*B&&(D=O,C=S),{cx:D,cy:C,x01:-f,y01:-l,x11:D*(i/A-1),y11:C*(i/A-1)}}function F(){var t=E,e=k,n=f(0),r=null,i=D,o=C,a=O,u=null -function c(){var c,f,p=+t.apply(this,arguments),E=+e.apply(this,arguments),k=i.apply(this,arguments)-_,D=o.apply(this,arguments)-_,C=l(D-k),O=D>k -if(u||(u=c=s()),Eg)if(C>w-g)u.moveTo(E*d(k),E*b(k)),u.arc(0,0,E,k,D,!O),p>g&&(u.moveTo(p*d(D),p*b(D)),u.arc(0,0,p,D,k,O)) -else{var F,T,B=k,P=D,j=k,N=D,R=C,L=C,I=a.apply(this,arguments)/2,$=I>g&&(r?+r.apply(this,arguments):v(p*p+E*E)),U=y(l(E-p)/2,+n.apply(this,arguments)),z=U,Z=U -if($>g){var q=A($/p*b(I)),V=A($/E*b(I));(R-=2*q)>g?(j+=q*=O?1:-1,N-=q):(R=0,j=N=(k+D)/2),(L-=2*V)>g?(B+=V*=O?1:-1,P-=V):(L=0,B=P=(k+D)/2)}var H=E*d(B),Y=E*b(B),G=p*d(N),K=p*b(N) -if(U>g){var W,X=E*d(P),J=E*b(P),Q=p*d(j),tt=p*b(j) -if(Cg?Z>g?(F=M(Q,tt,H,Y,E,Z,O),T=M(X,J,G,K,E,Z,O),u.moveTo(F.cx+F.x01,F.cy+F.y01),Zg&&R>g?z>g?(F=M(G,K,X,J,p,-z,O),T=M(H,Y,Q,tt,p,-z,O),u.lineTo(F.cx+F.x01,F.cy+F.y01),z=l;--h)u.point(v[h],g[h]) -u.lineEnd(),u.areaEnd()}b&&(v[f]=+t(d,f,c),g[f]=+e(d,f,c),u.point(r?+r(d,f,c):v[f],n?+n(d,f,c):g[f]))}if(p)return u=null,p+""||null}function l(){return L().defined(i).curve(a).context(o)}return t="function"==typeof t?t:void 0===t?N:f(+t),e="function"==typeof e?e:f(void 0===e?0:+e),n="function"==typeof n?n:void 0===n?R:f(+n),c.x=function(e){return arguments.length?(t="function"==typeof e?e:f(+e),r=null,c):t},c.x0=function(e){return arguments.length?(t="function"==typeof e?e:f(+e),c):t},c.x1=function(t){return arguments.length?(r=null==t?null:"function"==typeof t?t:f(+t),c):r},c.y=function(t){return arguments.length?(e="function"==typeof t?t:f(+t),n=null,c):e},c.y0=function(t){return arguments.length?(e="function"==typeof t?t:f(+t),c):e},c.y1=function(t){return arguments.length?(n=null==t?null:"function"==typeof t?t:f(+t),c):n},c.lineX0=c.lineY0=function(){return l().x(t).y(e)},c.lineY1=function(){return l().x(t).y(n)},c.lineX1=function(){return l().x(r).y(e)},c.defined=function(t){return arguments.length?(i="function"==typeof t?t:f(!!t),c):i},c.curve=function(t){return arguments.length?(a=t,null!=o&&(u=a(o)),c):a},c.context=function(t){return arguments.length?(null==t?o=u=null:u=a(o=t),c):o},c}function $(t,e){return et?1:e>=t?0:NaN}function U(t){return t}function z(){var t=U,e=$,n=null,r=f(0),i=f(w),o=f(0) -function a(a){var u,c,s,f,l,h=(a=B(a)).length,d=0,p=new Array(h),y=new Array(h),b=+r.apply(this,arguments),v=Math.min(w,Math.max(-w,i.apply(this,arguments)-b)),g=Math.min(Math.abs(v)/h,o.apply(this,arguments)),m=g*(v<0?-1:1) -for(u=0;u0&&(d+=l) -for(null!=e?p.sort((function(t,n){return e(y[t],y[n])})):null!=n&&p.sort((function(t,e){return n(a[t],a[e])})),u=0,s=d?(v-h*m)/d:0;u0?l*s:0)+m,y[c]={data:a[c],index:u,value:l,startAngle:b,endAngle:f,padAngle:g} -return y}return a.value=function(e){return arguments.length?(t="function"==typeof e?e:f(+e),a):t},a.sortValues=function(t){return arguments.length?(e=t,n=null,a):e},a.sort=function(t){return arguments.length?(n=t,e=null,a):n},a.startAngle=function(t){return arguments.length?(r="function"==typeof t?t:f(+t),a):r},a.endAngle=function(t){return arguments.length?(i="function"==typeof t?t:f(+t),a):i},a.padAngle=function(t){return arguments.length?(o="function"==typeof t?t:f(+t),a):o},a}P.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e) -break -case 1:this._point=2 -default:this._context.lineTo(t,e)}}} -var Z=V(j) -function q(t){this._curve=t}function V(t){function e(e){return new q(t(e))}return e._curve=t,e}function H(t){var e=t.curve -return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t.curve=function(t){return arguments.length?e(V(t)):e()._curve},t}function Y(){return H(L().curve(Z))}function G(){var t=I().curve(Z),e=t.curve,n=t.lineX0,r=t.lineX1,i=t.lineY0,o=t.lineY1 -return t.angle=t.x,delete t.x,t.startAngle=t.x0,delete t.x0,t.endAngle=t.x1,delete t.x1,t.radius=t.y,delete t.y,t.innerRadius=t.y0,delete t.y0,t.outerRadius=t.y1,delete t.y1,t.lineStartAngle=function(){return H(n())},delete t.lineX0,t.lineEndAngle=function(){return H(r())},delete t.lineX1,t.lineInnerRadius=function(){return H(i())},delete t.lineY0,t.lineOuterRadius=function(){return H(o())},delete t.lineY1,t.curve=function(t){return arguments.length?e(V(t)):e()._curve},t}function K(t,e){return[(e=+e)*Math.cos(t-=Math.PI/2),e*Math.sin(t)]}function W(t){return t.source}function X(t){return t.target}function J(t){var e=W,n=X,r=N,i=R,o=null -function a(){var a,u=T.call(arguments),c=e.apply(this,u),f=n.apply(this,u) -if(o||(o=a=s()),t(o,+r.apply(this,(u[0]=c,u)),+i.apply(this,u),+r.apply(this,(u[0]=f,u)),+i.apply(this,u)),a)return o=null,a+""||null}return a.source=function(t){return arguments.length?(e=t,a):e},a.target=function(t){return arguments.length?(n=t,a):n},a.x=function(t){return arguments.length?(r="function"==typeof t?t:f(+t),a):r},a.y=function(t){return arguments.length?(i="function"==typeof t?t:f(+t),a):i},a.context=function(t){return arguments.length?(o=null==t?null:t,a):o},a}function Q(t,e,n,r,i){t.moveTo(e,n),t.bezierCurveTo(e=(e+r)/2,n,e,i,r,i)}function tt(t,e,n,r,i){t.moveTo(e,n),t.bezierCurveTo(e,n=(n+i)/2,r,n,r,i)}function et(t,e,n,r,i){var o=K(e,n),a=K(e,n=(n+i)/2),u=K(r,n),c=K(r,i) -t.moveTo(o[0],o[1]),t.bezierCurveTo(a[0],a[1],u[0],u[1],c[0],c[1])}function nt(){return J(Q)}function rt(){return J(tt)}function it(){var t=J(et) -return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t}q.prototype={areaStart:function(){this._curve.areaStart()},areaEnd:function(){this._curve.areaEnd()},lineStart:function(){this._curve.lineStart()},lineEnd:function(){this._curve.lineEnd()},point:function(t,e){this._curve.point(e*Math.sin(t),e*-Math.cos(t))}} -const ot={draw:function(t,e){var n=Math.sqrt(e/m) -t.moveTo(n,0),t.arc(0,0,n,0,w)}},at={draw:function(t,e){var n=Math.sqrt(e/5)/2 -t.moveTo(-3*n,-n),t.lineTo(-n,-n),t.lineTo(-n,-3*n),t.lineTo(n,-3*n),t.lineTo(n,-n),t.lineTo(3*n,-n),t.lineTo(3*n,n),t.lineTo(n,n),t.lineTo(n,3*n),t.lineTo(-n,3*n),t.lineTo(-n,n),t.lineTo(-3*n,n),t.closePath()}} -var ut=Math.sqrt(1/3),ct=2*ut -const st={draw:function(t,e){var n=Math.sqrt(e/ct),r=n*ut -t.moveTo(0,-n),t.lineTo(r,0),t.lineTo(0,n),t.lineTo(-r,0),t.closePath()}} -var ft=Math.sin(m/10)/Math.sin(7*m/10),lt=Math.sin(w/10)*ft,ht=-Math.cos(w/10)*ft -const dt={draw:function(t,e){var n=Math.sqrt(.8908130915292852*e),r=lt*n,i=ht*n -t.moveTo(0,-n),t.lineTo(r,i) -for(var o=1;o<5;++o){var a=w*o/5,u=Math.cos(a),c=Math.sin(a) -t.lineTo(c*n,-u*n),t.lineTo(u*r-c*i,c*r+u*i)}t.closePath()}},pt={draw:function(t,e){var n=Math.sqrt(e),r=-n/2 -t.rect(r,r,n,n)}} -var yt=Math.sqrt(3) -const bt={draw:function(t,e){var n=-Math.sqrt(e/(3*yt)) -t.moveTo(0,2*n),t.lineTo(-yt*n,-n),t.lineTo(yt*n,-n),t.closePath()}} -var vt=-.5,gt=Math.sqrt(3)/2,mt=1/Math.sqrt(12),_t=3*(mt/2+1) -const wt={draw:function(t,e){var n=Math.sqrt(e/_t),r=n/2,i=n*mt,o=r,a=n*mt+n,u=-o,c=a -t.moveTo(r,i),t.lineTo(o,a),t.lineTo(u,c),t.lineTo(vt*r-gt*i,gt*r+vt*i),t.lineTo(vt*o-gt*a,gt*o+vt*a),t.lineTo(vt*u-gt*c,gt*u+vt*c),t.lineTo(vt*r+gt*i,vt*i-gt*r),t.lineTo(vt*o+gt*a,vt*a-gt*o),t.lineTo(vt*u+gt*c,vt*c-gt*u),t.closePath()}} -var xt=[ot,at,st,pt,dt,bt,wt] -function At(t,e){var n=null -function r(){var r -if(n||(n=r=s()),t.apply(this,arguments).draw(n,+e.apply(this,arguments)),r)return n=null,r+""||null}return t="function"==typeof t?t:f(t||ot),e="function"==typeof e?e:f(void 0===e?64:+e),r.type=function(e){return arguments.length?(t="function"==typeof e?e:f(e),r):t},r.size=function(t){return arguments.length?(e="function"==typeof t?t:f(+t),r):e},r.context=function(t){return arguments.length?(n=null==t?null:t,r):n},r}function Et(){}function kt(t,e,n){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+e)/6,(t._y0+4*t._y1+n)/6)}function Dt(t){this._context=t}function Ct(t){return new Dt(t)}function Ot(t){this._context=t}function St(t){return new Ot(t)}function Mt(t){this._context=t}function Ft(t){return new Mt(t)}Dt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:kt(this,this._x1,this._y1) -case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e) -break -case 1:this._point=2 -break -case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6) -default:kt(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},Ot.prototype={areaStart:Et,areaEnd:Et,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath() -break -case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath() -break -case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._x2=t,this._y2=e -break -case 1:this._point=2,this._x3=t,this._y3=e -break -case 2:this._point=3,this._x4=t,this._y4=e,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+e)/6) -break -default:kt(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},Mt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1 -break -case 1:this._point=2 -break -case 2:this._point=3 -var n=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+e)/6 -this._line?this._context.lineTo(n,r):this._context.moveTo(n,r) -break -case 3:this._point=4 -default:kt(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}} -class Tt{constructor(t,e){this._context=t,this._x=e}areaStart(){this._line=0}areaEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line}point(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e) -break -case 1:this._point=2 -default:this._x?this._context.bezierCurveTo(this._x0=(this._x0+t)/2,this._y0,this._x0,e,t,e):this._context.bezierCurveTo(this._x0,this._y0=(this._y0+e)/2,t,this._y0,t,e)}this._x0=t,this._y0=e}}function Bt(t){return new Tt(t,!0)}function Pt(t){return new Tt(t,!1)}function jt(t,e){this._basis=new Dt(t),this._beta=e}jt.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var t=this._x,e=this._y,n=t.length-1 -if(n>0)for(var r,i=t[0],o=e[0],a=t[n]-i,u=e[n]-o,c=-1;++c<=n;)r=c/n,this._basis.point(this._beta*t[c]+(1-this._beta)*(i+r*a),this._beta*e[c]+(1-this._beta)*(o+r*u)) -this._x=this._y=null,this._basis.lineEnd()},point:function(t,e){this._x.push(+t),this._y.push(+e)}} -const Nt=function t(e){function n(t){return 1===e?new Dt(t):new jt(t,e)}return n.beta=function(e){return t(+e)},n}(.85) -function Rt(t,e,n){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._y1+t._k*(t._y2-t._y0),t._x2+t._k*(t._x1-e),t._y2+t._k*(t._y1-n),t._x2,t._y2)}function Lt(t,e){this._context=t,this._k=(1-e)/6}Lt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2) -break -case 3:Rt(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e) -break -case 1:this._point=2,this._x1=t,this._y1=e -break -case 2:this._point=3 -default:Rt(this,t,e)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}} -const It=function t(e){function n(t){return new Lt(t,e)}return n.tension=function(e){return t(+e)},n}(0) -function $t(t,e){this._context=t,this._k=(1-e)/6}$t.prototype={areaStart:Et,areaEnd:Et,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath() -break -case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath() -break -case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._x3=t,this._y3=e -break -case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=e) -break -case 2:this._point=3,this._x5=t,this._y5=e -break -default:Rt(this,t,e)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}} -const Ut=function t(e){function n(t){return new $t(t,e)}return n.tension=function(e){return t(+e)},n}(0) -function zt(t,e){this._context=t,this._k=(1-e)/6}zt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1 -break -case 1:this._point=2 -break -case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2) -break -case 3:this._point=4 -default:Rt(this,t,e)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}} -const Zt=function t(e){function n(t){return new zt(t,e)}return n.tension=function(e){return t(+e)},n}(0) -function qt(t,e,n){var r=t._x1,i=t._y1,o=t._x2,a=t._y2 -if(t._l01_a>g){var u=2*t._l01_2a+3*t._l01_a*t._l12_a+t._l12_2a,c=3*t._l01_a*(t._l01_a+t._l12_a) -r=(r*u-t._x0*t._l12_2a+t._x2*t._l01_2a)/c,i=(i*u-t._y0*t._l12_2a+t._y2*t._l01_2a)/c}if(t._l23_a>g){var s=2*t._l23_2a+3*t._l23_a*t._l12_a+t._l12_2a,f=3*t._l23_a*(t._l23_a+t._l12_a) -o=(o*s+t._x1*t._l23_2a-e*t._l12_2a)/f,a=(a*s+t._y1*t._l23_2a-n*t._l12_2a)/f}t._context.bezierCurveTo(r,i,o,a,t._x2,t._y2)}function Vt(t,e){this._context=t,this._alpha=e}Vt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2) -break -case 3:this.point(this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){if(t=+t,e=+e,this._point){var n=this._x2-t,r=this._y2-e -this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e) -break -case 1:this._point=2 -break -case 2:this._point=3 -default:qt(this,t,e)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}} -const Ht=function t(e){function n(t){return e?new Vt(t,e):new Lt(t,0)}return n.alpha=function(e){return t(+e)},n}(.5) -function Yt(t,e){this._context=t,this._alpha=e}Yt.prototype={areaStart:Et,areaEnd:Et,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath() -break -case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath() -break -case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,e){if(t=+t,e=+e,this._point){var n=this._x2-t,r=this._y2-e -this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=t,this._y3=e -break -case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=e) -break -case 2:this._point=3,this._x5=t,this._y5=e -break -default:qt(this,t,e)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}} -const Gt=function t(e){function n(t){return e?new Yt(t,e):new $t(t,0)}return n.alpha=function(e){return t(+e)},n}(.5) -function Kt(t,e){this._context=t,this._alpha=e}Kt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){if(t=+t,e=+e,this._point){var n=this._x2-t,r=this._y2-e -this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1 -break -case 1:this._point=2 -break -case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2) -break -case 3:this._point=4 -default:qt(this,t,e)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}} -const Wt=function t(e){function n(t){return e?new Kt(t,e):new zt(t,0)}return n.alpha=function(e){return t(+e)},n}(.5) -function Xt(t){this._context=t}function Jt(t){return new Xt(t)}function Qt(t){return t<0?-1:1}function te(t,e,n){var r=t._x1-t._x0,i=e-t._x1,o=(t._y1-t._y0)/(r||i<0&&-0),a=(n-t._y1)/(i||r<0&&-0),u=(o*i+a*r)/(r+i) -return(Qt(o)+Qt(a))*Math.min(Math.abs(o),Math.abs(a),.5*Math.abs(u))||0}function ee(t,e){var n=t._x1-t._x0 -return n?(3*(t._y1-t._y0)/n-e)/2:e}function ne(t,e,n){var r=t._x0,i=t._y0,o=t._x1,a=t._y1,u=(o-r)/3 -t._context.bezierCurveTo(r+u,i+u*e,o-u,a-u*n,o,a)}function re(t){this._context=t}function ie(t){this._context=new oe(t)}function oe(t){this._context=t}function ae(t){return new re(t)}function ue(t){return new ie(t)}function ce(t){this._context=t}function se(t){var e,n,r=t.length-1,i=new Array(r),o=new Array(r),a=new Array(r) -for(i[0]=0,o[0]=2,a[0]=t[0]+2*t[1],e=1;e=0;--e)i[e]=(a[e]-i[e+1])/o[e] -for(o[r-1]=(t[r]+i[r-1])/2,e=0;e1)for(var n,r,i,o=1,a=t[e[0]],u=a.length;o=0;)n[e]=e -return n}function ve(t,e){return t[e]}function ge(t){const e=[] -return e.key=t,e}function me(){var t=f([]),e=be,n=ye,r=ve -function i(i){var o,a,u=Array.from(t.apply(this,arguments),ge),c=u.length,s=-1 -for(const t of i)for(o=0,++s;o0){for(var n,r,i,o=0,a=t[0].length;o0)for(var n,r,i,o,a,u,c=0,s=t[e[0]].length;c0?(r[0]=o,r[1]=o+=i):i<0?(r[1]=a,r[0]=a+=i):(r[0]=0,r[1]=i)}function xe(t,e){if((n=t.length)>0){for(var n,r=0,i=t[e[0]],o=i.length;r0&&(r=(n=t[e[0]]).length)>0){for(var n,r,i,o=0,a=1;ao&&(o=e,r=n) -return r}function De(t){var e=t.map(Ce) -return be(t).sort((function(t,n){return e[t]-e[n]}))}function Ce(t){for(var e,n=0,r=-1,i=t.length;++r=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e) -break -case 1:this._point=2 -default:if(this._t<=0)this._context.lineTo(this._x,e),this._context.lineTo(t,e) -else{var n=this._x*(1-this._t)+t*this._t -this._context.lineTo(n,this._y),this._context.lineTo(n,e)}}this._x=t,this._y=e}}},4434:function(t){t.exports=function(){"use strict" -var t="millisecond",e="second",n="minute",r="hour",i="day",o="week",a="month",u="quarter",c="year",s="date",f=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[^0-9]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,l=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,h={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_")},d=function(t,e,n){var r=String(t) -return!r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},p={s:d,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60 -return(e<=0?"+":"-")+d(r,2,"0")+":"+d(i,2,"0")},m:function t(e,n){if(e.date()0,b<=y.r||!y.r){b<=1&&p>0&&(y=h[p-1]) -var v=l[y.l] -u&&(b=u(""+b)),s="string"==typeof v?v.replace("%d",b):v(b,r,y.l,f) -break}}if(r)return s -var g=f?l.future:l.past -return"function"==typeof g?g(s):g.replace("%s",s)},r.to=function(t,e){return o(t,e,this,!0)},r.from=function(t,e){return o(t,e,this)} -var a=function(t){return t.$u?n.utc():n()} -r.toNow=function(t){return this.to(a(this),t)},r.fromNow=function(t){return this.from(a(this),t)}}}()},2999:t=>{"use strict" -var e=function(t){return function(t){return!!t&&"object"==typeof t}(t)&&!function(t){var e=Object.prototype.toString.call(t) -return"[object RegExp]"===e||"[object Date]"===e||function(t){return t.$$typeof===n}(t)}(t)},n="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103 -function r(t,e){return!1!==e.clone&&e.isMergeableObject(t)?u((n=t,Array.isArray(n)?[]:{}),t,e):t -var n}function i(t,e,n){return t.concat(e).map((function(t){return r(t,n)}))}function o(t){return Object.keys(t).concat(function(t){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(t).filter((function(e){return t.propertyIsEnumerable(e)})):[]}(t))}function a(t,e){try{return e in t}catch(t){return!1}}function u(t,n,c){(c=c||{}).arrayMerge=c.arrayMerge||i,c.isMergeableObject=c.isMergeableObject||e,c.cloneUnlessOtherwiseSpecified=r -var s=Array.isArray(n) -return s===Array.isArray(t)?s?c.arrayMerge(t,n,c):function(t,e,n){var i={} -return n.isMergeableObject(t)&&o(t).forEach((function(e){i[e]=r(t[e],n)})),o(e).forEach((function(o){(function(t,e){return a(t,e)&&!(Object.hasOwnProperty.call(t,e)&&Object.propertyIsEnumerable.call(t,e))})(t,o)||(a(t,o)&&n.isMergeableObject(e[o])?i[o]=function(t,e){if(!e.customMerge)return u -var n=e.customMerge(t) -return"function"==typeof n?n:u}(o,n)(t[o],e[o],n):i[o]=r(e[o],n))})),i}(t,n,c):r(n,c)}u.all=function(t,e){if(!Array.isArray(t))throw new Error("first argument should be an array") -return t.reduce((function(t,n){return u(t,n,e)}),{})} -var c=u -t.exports=c},6673:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{default:()=>P}) -var r=n(4927),i=["input","select","textarea","a[href]","button","[tabindex]:not(slot)","audio[controls]","video[controls]",'[contenteditable]:not([contenteditable="false"])',"details>summary:first-of-type","details"],o=i.join(","),a="undefined"==typeof Element,u=a?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector,c=!a&&Element.prototype.getRootNode?function(t){return t.getRootNode()}:function(t){return t.ownerDocument},s=function(t,e,n){var r=Array.prototype.slice.apply(t.querySelectorAll(o)) -return e&&u.call(t,o)&&r.unshift(t),r.filter(n)},f=function t(e,n,r){for(var i=[],a=Array.from(e);a.length;){var c=a.shift() -if("SLOT"===c.tagName){var s=c.assignedElements(),f=t(s.length?s:c.children,!0,r) -r.flatten?i.push.apply(i,f):i.push({scope:c,candidates:f})}else{u.call(c,o)&&r.filter(c)&&(n||!e.includes(c))&&i.push(c) -var l=c.shadowRoot||"function"==typeof r.getShadowRoot&&r.getShadowRoot(c),h=!r.shadowRootFilter||r.shadowRootFilter(c) -if(l&&h){var d=t(!0===l?c.children:l.children,!0,r) -r.flatten?i.push.apply(i,d):i.push({scope:c,candidates:d})}else a.unshift.apply(a,c.children)}}return i},l=function(t,e){return t.tabIndex<0&&(e||/^(AUDIO|VIDEO|DETAILS)$/.test(t.tagName)||t.isContentEditable)&&isNaN(parseInt(t.getAttribute("tabindex"),10))?0:t.tabIndex},h=function(t,e){return t.tabIndex===e.tabIndex?t.documentOrder-e.documentOrder:t.tabIndex-e.tabIndex},d=function(t){return"INPUT"===t.tagName},p=function(t){var e=t.getBoundingClientRect(),n=e.width,r=e.height -return 0===n&&0===r},y=function(t,e){return!(e.disabled||function(t){return d(t)&&"hidden"===t.type}(e)||function(t,e){var n=e.displayCheck,r=e.getShadowRoot -if("hidden"===getComputedStyle(t).visibility)return!0 -var i=u.call(t,"details>summary:first-of-type")?t.parentElement:t -if(u.call(i,"details:not([open]) *"))return!0 -var o=c(t).host,a=(null==o?void 0:o.ownerDocument.contains(o))||t.ownerDocument.contains(t) -if(n&&"full"!==n){if("non-zero-area"===n)return p(t)}else{if("function"==typeof r){for(var s=t;t;){var f=t.parentElement,l=c(t) -if(f&&!f.shadowRoot&&!0===r(f))return p(t) -t=t.assignedSlot?t.assignedSlot:f||l===t.ownerDocument?f:l.host}t=s}if(a)return!t.getClientRects().length}return!1}(e,t)||function(t){return"DETAILS"===t.tagName&&Array.prototype.slice.apply(t.children).some((function(t){return"SUMMARY"===t.tagName}))}(e)||function(t){if(/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(t.tagName))for(var e=t.parentElement;e;){if("FIELDSET"===e.tagName&&e.disabled){for(var n=0;n=0)},g=function t(e){var n=[],r=[] -return e.forEach((function(e,i){var o=!!e.scope,a=o?e.scope:e,u=l(a,o),c=o?t(e.candidates):a -0===u?o?n.push.apply(n,c):n.push(a):r.push({documentOrder:i,tabIndex:u,item:e,isScope:o,content:c})})),r.sort(h).reduce((function(t,e){return e.isScope?t.push.apply(t,e.content):t.push(e.content),t}),[]).concat(n)},m=function(t,e){var n -return n=(e=e||{}).getShadowRoot?f([t],e.includeContainer,{filter:b.bind(null,e),flatten:!1,getShadowRoot:e.getShadowRoot,shadowRootFilter:v}):s(t,e.includeContainer,b.bind(null,e)),g(n)},_=function(t,e){if(e=e||{},!t)throw new Error("No node provided") -return!1!==u.call(t,o)&&b(e,t)},w=i.concat("iframe").join(","),x=function(t,e){if(e=e||{},!t)throw new Error("No node provided") -return!1!==u.call(t,w)&&y(e,t)} -function A(t,e){var n=Object.keys(t) -if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t) -e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function E(t){for(var e=1;e0){var e=D[D.length-1] -e!==t&&e.pause()}var n=D.indexOf(t);-1===n||D.splice(n,1),D.push(t)},deactivateTrap:function(t){var e=D.indexOf(t);-1!==e&&D.splice(e,1),D.length>0&&D[D.length-1].unpause()}}),O=function(t){return setTimeout(t,0)},S=function(t,e){var n=-1 -return t.every((function(t,r){return!e(t)||(n=r,!1)})),n},M=function(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r1?n-1:0),a=1;a=0)t=r.activeElement -else{var e=o.tabbableGroups[0] -t=e&&e.firstTabbableNode||c("fallbackFocus")}if(!t)throw new Error("Your focus-trap needs to have at least one focusable element") -return t},h=function(){if(o.containerGroups=o.containers.map((function(t){var e,n,r=m(t,i.tabbableOptions),o=(e=t,(n=(n=i.tabbableOptions)||{}).getShadowRoot?f([e],n.includeContainer,{filter:y.bind(null,n),flatten:!0,getShadowRoot:n.getShadowRoot}):s(e,n.includeContainer,y.bind(null,n))) -return{container:t,tabbableNodes:r,focusableNodes:o,firstTabbableNode:r.length>0?r[0]:null,lastTabbableNode:r.length>0?r[r.length-1]:null,nextTabbableNode:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=o.findIndex((function(e){return e===t})) -if(!(n<0))return e?o.slice(n+1).find((function(t){return _(t,i.tabbableOptions)})):o.slice(0,n).reverse().find((function(t){return _(t,i.tabbableOptions)}))}}})),o.tabbableGroups=o.containerGroups.filter((function(t){return t.tabbableNodes.length>0})),o.tabbableGroups.length<=0&&!c("fallbackFocus"))throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times")},d=function t(e){!1!==e&&e!==r.activeElement&&(e&&e.focus?(e.focus({preventScroll:!!i.preventScroll}),o.mostRecentlyFocusedNode=e,function(t){return t.tagName&&"input"===t.tagName.toLowerCase()&&"function"==typeof t.select}(e)&&e.select()):t(l()))},p=function(t){var e=c("setReturnFocus",t) -return e||!1!==e&&t},b=function(t){var e=F(t) -u(e)>=0||(M(i.clickOutsideDeactivates,t)?n.deactivate({returnFocus:i.returnFocusOnDeactivate&&!x(e,i.tabbableOptions)}):M(i.allowOutsideClick,t)||t.preventDefault())},v=function(t){var e=F(t),n=u(e)>=0 -n||e instanceof Document?n&&(o.mostRecentlyFocusedNode=e):(t.stopImmediatePropagation(),d(o.mostRecentlyFocusedNode||l()))},g=function(t){if(function(t){return"Escape"===t.key||"Esc"===t.key||27===t.keyCode}(t)&&!1!==M(i.escapeDeactivates,t))return t.preventDefault(),void n.deactivate();(function(t){return"Tab"===t.key||9===t.keyCode})(t)&&function(t){var e=F(t) -h() -var n=null -if(o.tabbableGroups.length>0){var r=u(e),a=r>=0?o.containerGroups[r]:void 0 -if(r<0)n=t.shiftKey?o.tabbableGroups[o.tabbableGroups.length-1].lastTabbableNode:o.tabbableGroups[0].firstTabbableNode -else if(t.shiftKey){var s=S(o.tabbableGroups,(function(t){var n=t.firstTabbableNode -return e===n})) -if(s<0&&(a.container===e||x(e,i.tabbableOptions)&&!_(e,i.tabbableOptions)&&!a.nextTabbableNode(e,!1))&&(s=r),s>=0){var f=0===s?o.tabbableGroups.length-1:s-1 -n=o.tabbableGroups[f].lastTabbableNode}}else{var l=S(o.tabbableGroups,(function(t){var n=t.lastTabbableNode -return e===n})) -if(l<0&&(a.container===e||x(e,i.tabbableOptions)&&!_(e,i.tabbableOptions)&&!a.nextTabbableNode(e))&&(l=r),l>=0){var p=l===o.tabbableGroups.length-1?0:l+1 -n=o.tabbableGroups[p].firstTabbableNode}}}else n=c("fallbackFocus") -n&&(t.preventDefault(),d(n))}(t)},w=function(t){var e=F(t) -u(e)>=0||M(i.clickOutsideDeactivates,t)||M(i.allowOutsideClick,t)||(t.preventDefault(),t.stopImmediatePropagation())},A=function(){if(o.active)return C.activateTrap(n),o.delayInitialFocusTimer=i.delayInitialFocus?O((function(){d(l())})):d(l()),r.addEventListener("focusin",v,!0),r.addEventListener("mousedown",b,{capture:!0,passive:!1}),r.addEventListener("touchstart",b,{capture:!0,passive:!1}),r.addEventListener("click",w,{capture:!0,passive:!1}),r.addEventListener("keydown",g,{capture:!0,passive:!1}),n},k=function(){if(o.active)return r.removeEventListener("focusin",v,!0),r.removeEventListener("mousedown",b,!0),r.removeEventListener("touchstart",b,!0),r.removeEventListener("click",w,!0),r.removeEventListener("keydown",g,!0),n} -return(n={get active(){return o.active},get paused(){return o.paused},activate:function(t){if(o.active)return this -var e=a(t,"onActivate"),n=a(t,"onPostActivate"),i=a(t,"checkCanFocusTrap") -i||h(),o.active=!0,o.paused=!1,o.nodeFocusedBeforeActivation=r.activeElement,e&&e() -var u=function(){i&&h(),A(),n&&n()} -return i?(i(o.containers.concat()).then(u,u),this):(u(),this)},deactivate:function(t){if(!o.active)return this -var e=E({onDeactivate:i.onDeactivate,onPostDeactivate:i.onPostDeactivate,checkCanReturnFocus:i.checkCanReturnFocus},t) -clearTimeout(o.delayInitialFocusTimer),o.delayInitialFocusTimer=void 0,k(),o.active=!1,o.paused=!1,C.deactivateTrap(n) -var r=a(e,"onDeactivate"),u=a(e,"onPostDeactivate"),c=a(e,"checkCanReturnFocus"),s=a(e,"returnFocus","returnFocusOnDeactivate") -r&&r() -var f=function(){O((function(){s&&d(p(o.nodeFocusedBeforeActivation)),u&&u()}))} -return s&&c?(c(p(o.nodeFocusedBeforeActivation)).then(f,f),this):(f(),this)},pause:function(){return o.paused||!o.active||(o.paused=!0,k()),this},unpause:function(){return o.paused&&o.active?(o.paused=!1,h(),A(),this):this},updateContainerElements:function(t){var e=[].concat(t).filter(Boolean) -return o.containers=e.map((function(t){return"string"==typeof t?r.querySelector(t):t})),o.active&&h(),this}}).updateContainerElements(t),n} -let B -try{B=(0,r.capabilities)("3.22")}catch{B=(0,r.capabilities)("3.13")}var P=(0,r.setModifierManager)((()=>({capabilities:B,createModifier:()=>({focusTrapOptions:void 0,isActive:!0,isPaused:!1,shouldSelfFocus:!1,focusTrap:void 0}),installModifier(t,e,n){let{named:{isActive:r,isPaused:i,shouldSelfFocus:o,focusTrapOptions:a,_createFocusTrap:u}}=n -t.focusTrapOptions={...a}||{},void 0!==r&&(t.isActive=r),void 0!==i&&(t.isPaused=i),t.focusTrapOptions&&void 0===t.focusTrapOptions.initialFocus&&o&&(t.focusTrapOptions.initialFocus=e) -let c=T -u&&(c=u),!1!==t.focusTrapOptions.returnFocusOnDeactivate&&(t.focusTrapOptions.returnFocusOnDeactivate=!0),t.focusTrap=c(e,t.focusTrapOptions),t.isActive&&t.focusTrap.activate(),t.isPaused&&t.focusTrap.pause()},updateModifier(t,e){let{named:n}=e -const r=n.focusTrapOptions||{} -if(t.isActive&&!n.isActive){const{returnFocusOnDeactivate:e}=r,n=void 0===e -t.focusTrap.deactivate({returnFocus:n})}else!t.isActive&&n.isActive&&t.focusTrap.activate() -t.isPaused&&!n.isPaused?t.focusTrap.unpause():!t.isPaused&&n.isPaused&&t.focusTrap.pause(),t.focusTrapOptions=r,void 0!==n.isActive&&(t.isActive=n.isActive),void 0!==n.isPaused&&(t.isPaused=n.isPaused)},destroyModifier(t){let{focusTrap:e}=t -e.deactivate()}})),class{})},7889:t=>{"use strict" -var e=Array.isArray,n=Object.keys,r=Object.prototype.hasOwnProperty -t.exports=function t(i,o){if(i===o)return!0 -if(i&&o&&"object"==typeof i&&"object"==typeof o){var a,u,c,s=e(i),f=e(o) -if(s&&f){if((u=i.length)!=o.length)return!1 -for(a=u;0!=a--;)if(!t(i[a],o[a]))return!1 -return!0}if(s!=f)return!1 -var l=i instanceof Date,h=o instanceof Date -if(l!=h)return!1 -if(l&&h)return i.getTime()==o.getTime() -var d=i instanceof RegExp,p=o instanceof RegExp -if(d!=p)return!1 -if(d&&p)return i.toString()==o.toString() -var y=n(i) -if((u=y.length)!==n(o).length)return!1 -for(a=u;0!=a--;)if(!r.call(o,y[a]))return!1 -for(a=u;0!=a--;)if(!t(i[c=y[a]],o[c]))return!1 -return!0}return i!=i&&o!=o}},9763:(t,e,n)=>{"use strict" -function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function i(t,e,n,r){n&&Object.defineProperty(t,e,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(r):void 0})}function o(t,e,n,r,i){var o={} -return Object.keys(r).forEach((function(t){o[t]=r[t]})),o.enumerable=!!o.enumerable,o.configurable=!!o.configurable,("value"in o||o.initializer)&&(o.writable=!0),o=n.slice().reverse().reduce((function(n,r){return r(t,e,n)||n}),o),i&&void 0!==o.initializer&&(o.value=o.initializer?o.initializer.call(i):void 0,o.initializer=void 0),void 0===o.initializer&&(Object.defineProperty(t,e,o),o=null),o}n.d(e,{_:()=>r,a:()=>o,b:()=>i})},5989:(t,e,n)=>{"use strict" -n.d(e,{Bq:()=>i,sd:()=>o,zA:()=>r}) -const r={A:"a",B:"b",C:"c",D:"d",E:"e",F:"f",G:"g",H:"h",I:"i",J:"j",K:"k",L:"l",M:"m",N:"n",O:"o",P:"p",Q:"q",R:"r",S:"s",T:"t",U:"u",V:"v",W:"w",X:"x",Y:"y",Z:"z","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=","<":",",">":".","?":"/",":":";",'"':"'","~":"`","{":"[","}":"]","|":"\\"},i={"å":"a",b:"b","ç":"c","∂":"d","ƒ":"f","©":"g","˙":"h","∆":"j","˚":"k","¬":"l","µ":"m","ø":"o","π":"p","œ":"q","®":"r","ß":"s","†":"t","√":"v","∑":"w","≈":"x","¥":"y","Ω":"z","¡":"1","™":"2","£":"3","¢":"4","∞":"5","§":"6","¶":"7","•":"8","ª":"9","º":"0","–":"-","≠":"=","≤":",","≥":".","÷":"/","…":";","æ":"'","“":"[","‘":"]","«":"\\"},o={"Å":"a","ı":"b","Î":"d","Ï":"f","˝":"g","Ó":"h","ˆ":"i","Ô":"j","":"k","Ò":"l","Â":"m","˜":"n","Ø":"o","Œ":"q","‰":"r","Í":"s","ˇ":"t","¨":"u","◊":"v","„":"w","˛":"x","Á":"y","¸":"z","⁄":"1","€":"2","‹":"3","›":"4","fi":"5","fl":"6","‡":"7","°":"8","·":"9","‚":"0","—":"-","±":"=","¯":",","˘":".","¿":"/","Ú":";","Æ":"'","`":"`","”":"[","’":"]","»":"\\"}},6866:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{default:()=>u}) -var r=n(8797),i=n(3353),o=n(4784),a=n(1377),u=(n(5780),n(2001),n(5989),n(2995),n(1866),(0,r.helper)((function(t){let[e,n]=t -return function(t){(0,i.assert)("ember-keyboard: You must pass a function as the second argument to the `if-key` helper","function"==typeof n),(0,i.assert)("ember-keyboard: The `if-key` helper expects to be invoked with a KeyboardEvent",t instanceof KeyboardEvent),(0,o.Z)((0,a.Z)(t.type,e),t)&&n(t)}})))},9930:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{default:()=>l}) -var r,i,o=n(9763),a=n(8797),u=n.n(a),c=n(3353),s=n(8574),f=n(1377) -let l=(r=class extends(u()){constructor(){super(...arguments),(0,o.b)(this,"keyboard",i,this),(0,o._)(this,"keyCombo",void 0),(0,o._)(this,"callback",void 0),(0,o._)(this,"keyboardActivated",!0),(0,o._)(this,"keyboardPriority",0),(0,o._)(this,"eventName","keydown"),(0,o._)(this,"keyboardHandlers",void 0)}compute(t,e){let[n,r]=t,{event:i="keydown",activated:o=!0,priority:a=0}=e;(0,c.assert)("ember-keyboard: You must pass a function as the second argument to the `on-key` helper","function"==typeof r),this.keyCombo=n,this.callback=r,this.eventName=i,this.keyboardActivated=o,this.keyboardPriority=a,this.keyboardHandlers={},this.keyboardHandlers[(0,f.Z)(i,n)]=r,this.keyboard.register(this)}willDestroy(){this.keyboard.unregister(this),super.willDestroy(...arguments)}},i=(0,o.a)(r.prototype,"keyboard",[s.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),r)},6222:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{default:()=>y}) -var r=n(9763),i=n(5831),o=n.n(i),a=n(8574),u=n(7219),c=n(9341),s=n(1377),f=n(4784) -n(5780),n(2001),n(3353),n(5989),n(2995),n(1866) -const l=["input","select","textarea"] -let h -var d,p -d=class extends(o()){constructor(t,e){super(t,e),(0,r.b)(this,"keyboard",p,this),(0,r._)(this,"element",void 0),(0,r._)(this,"keyboardPriority",0),(0,r._)(this,"activatedParamValue",!0),(0,r._)(this,"eventName","keydown"),(0,r._)(this,"onlyWhenFocused",!0),(0,r._)(this,"listenerName",void 0),(0,r._)(this,"removeEventListeners",(()=>{this.onlyWhenFocused&&(this.element.removeEventListener("click",this.onFocus,!0),this.element.removeEventListener("focus",this.onFocus,!0),this.element.removeEventListener("focusout",this.onFocusOut,!0))})),this.keyboard.register(this),(0,c.registerDestructor)(this,(()=>{this.removeEventListeners(),this.keyboard.unregister(this)}))}modify(t,e,n){this.element=t,this.removeEventListeners(),this.setupProperties(e,n),this.onlyWhenFocused&&this.addEventListeners()}setupProperties(t,e){let[n,r]=t,{activated:i,event:o,priority:a,onlyWhenFocused:u}=e -this.keyCombo=n,this.callback=r,this.eventName=o||"keydown",this.activatedParamValue="activated"in e?!!i:void 0,this.keyboardPriority=a?parseInt(a,10):0,this.listenerName=(0,s.Z)(this.eventName,this.keyCombo),this.onlyWhenFocused=void 0!==u?u:l.includes(this.element.tagName.toLowerCase())}addEventListeners(){this.element.addEventListener("click",this.onFocus,!0),this.element.addEventListener("focus",this.onFocus,!0),this.element.addEventListener("focusout",this.onFocusOut,!0)}onFocus(){this.isFocused=!0}onFocusOut(){this.isFocused=!1}get keyboardActivated(){return!1!==this.activatedParamValue&&(!this.onlyWhenFocused||this.isFocused)}get keyboardFirstResponder(){return!!this.onlyWhenFocused&&this.isFocused}canHandleKeyboardEvent(t){return(0,f.Z)(this.listenerName,t)}handleKeyboardEvent(t,e){(0,f.Z)(this.listenerName,t)&&(this.callback?this.callback(t,e):this.element.click())}},p=(0,r.a)(d.prototype,"keyboard",[a.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),(0,r.a)(d.prototype,"onFocus",[u.action],Object.getOwnPropertyDescriptor(d.prototype,"onFocus"),d.prototype),(0,r.a)(d.prototype,"onFocusOut",[u.action],Object.getOwnPropertyDescriptor(d.prototype,"onFocusOut"),d.prototype),h=d -var y=h},6918:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{default:()=>p}) -var r,i=n(9763),o=n(8574),a=n.n(o),u=n(1292),c=n(7219),s=n(8773),f=n(1377),l=n(4784) -function h(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null -if(t.handleKeyboardEvent){if(t.canHandleKeyboardEvent&&!t.canHandleKeyboardEvent(e))return -t.handleKeyboardEvent(e,n)}else{if(!t.keyboardHandlers)throw new Error("A responder registered with the ember-keyboard service must implement either `keyboardHandlers` (property returning a dictionary of listenerNames to handler functions), or `handleKeyboardEvent(event)`)") -Object.keys(t.keyboardHandlers).forEach((r=>{(0,l.Z)(r,e)&&(n?t.keyboardHandlers[r](e,n):t.keyboardHandlers[r](e))}))}}function d(t,e,n,r){return function(t,e){let n=t-e -return(n>0)-(n<0)}(r?r((0,c.get)(t,n)):(0,c.get)(t,n),r?r((0,c.get)(e,n)):(0,c.get)(e,n))}n(5780),n(2001),n(3353),n(5989),n(2995),n(1866) -let p=(r=class extends(a()){get activeResponders(){let{registeredResponders:t}=this -return Array.from(t).filter((t=>t.keyboardActivated))}get sortedResponders(){return this.activeResponders.sort(((t,e)=>function(t,e,n){return d(e,t,n,arguments.length>3&&void 0!==arguments[3]?arguments[3]:null)}(t,e,"keyboardPriority")))}get firstResponders(){return this.sortedResponders.filter((t=>t.keyboardFirstResponder))}get normalResponders(){return this.sortedResponders.filter((t=>!t.keyboardFirstResponder))}constructor(){if(super(...arguments),(0,i._)(this,"registeredResponders",new Set),"undefined"!=typeof FastBoot)return -let t=((0,u.getOwner)(this).resolveRegistration("config:environment")||{}).emberKeyboard||{} -t.disableOnInputFields&&(this._disableOnInput=!0),this._listeners=t.listeners||["keyUp","keyDown","keyPress"],this._listeners=this._listeners.map((t=>t.toLowerCase())),this._listeners.forEach((t=>{document.addEventListener(t,this._respond)}))}willDestroy(){super.willDestroy(...arguments),"undefined"==typeof FastBoot&&this._listeners.forEach((t=>{document.removeEventListener(t,this._respond)}))}_respond(t){if(this._disableOnInput&&t.target){var e -const n=null!==(e=t.composedPath()[0])&&void 0!==e?e:t.target,r=n.tagName -if(n.getAttribute&&null!=n.getAttribute("contenteditable")||"TEXTAREA"===r||"INPUT"===r)return}(0,s.run)((()=>{let{firstResponders:e,normalResponders:n}=this -!function(t,e){let{firstResponders:n,normalResponders:r}=e,i=!1,o=!1 -const a={stopImmediatePropagation(){i=!0},stopPropagation(){o=!0}} -for(const c of n)if(h(c,t,a),i)break -if(o)return -i=!1 -let u=Number.POSITIVE_INFINITY -for(const c of r){const e=Number(c.keyboardPriority) -if(!i||e!==u){if(e{"use strict" -n.d(e,{Z:()=>i}) -var r=n(1866) -function i(t){if(!(0,r.isNone)(t))switch(t){case 0:return"left" -case 1:return"middle" -case 2:return"right"}}},4784:(t,e,n)=>{"use strict" -n.d(e,{Z:()=>c}) -var r=n(5780),i=n(2001),o=n(5989),a=n(2995) -n(3353),n(1866) -const u="_all" -function c(t,e){let n,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:(0,i.Z)() -if(t instanceof r.Z)n=t -else{if("string"!=typeof t)throw new Error("Expected a `string` or `KeyCombo` as `keyComboOrKeyComboString` argument to `isKey`") -n=r.Z.parse(t,o)}return n.type===e.type&&(!!s(n)||!(!f(n,e)||!l(n,e)&&!h(n,e))||d(n,e,o))}function s(t){return t.keyOrCode===u&&!1===t.altKey&&!1===t.ctrlKey&&!1===t.metaKey&&!1===t.shiftKey}function f(t,e){return t.type===e.type&&t.altKey===e.altKey&&t.ctrlKey===e.ctrlKey&&t.metaKey===e.metaKey&&t.shiftKey===e.shiftKey}function l(t,e){return e instanceof KeyboardEvent&&(t.keyOrCode===u||t.keyOrCode===e.code||t.keyOrCode===e.key)}function h(t,e){return e instanceof MouseEvent&&(t.keyOrCode===u||t.keyOrCode===(0,a.Z)(e.button))}function d(t,e,n){return y([],t)&&y(["shift"],e)?e.key===t.keyOrCode:y(["shift"],t)&&y(["shift"],e)?(r=e.key,(o.zA[r]||r)===t.keyOrCode):"Macintosh"===n&&y(["alt"],t)&&y(["alt"],e)?function(t){return o.Bq[t]||t}(e.key)===t.keyOrCode:!("Macintosh"!==n||!y(["shift","alt"],t)||!y(["shift","alt"],e))&&function(t){return o.sd[t]||t}(e.key)===t.keyOrCode -var r}const p=["alt","ctrl","meta","shift","cmd"].filter((t=>"cmd"!=t)) -function y(t,e){for(let n of p){if(t.includes(n)&&!e[`${n}Key`])return!1 -if(!t.includes(n)&&e[`${n}Key`])return!1}return!0}},5780:(t,e,n)=>{"use strict" -n.d(e,{Z:()=>f}) -var r=n(9763),i=n(2001) -n(3353) -const o=/^alt$/i,a=/^shift$/i,u=/^ctrl$/i,c=/^meta$/i,s=/^cmd$/i -class f{constructor(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:(0,i.Z)();(0,r._)(this,"type",void 0),(0,r._)(this,"altKey",!1),(0,r._)(this,"ctrlKey",!1),(0,r._)(this,"shiftKey",!1),(0,r._)(this,"metaKey",!1),(0,r._)(this,"keyOrCode",void 0),(0,r._)(this,"platform",void 0),this.platform=t}static parse(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:(0,i.Z)(),n=new f(e),[r,l]=t.split(":") -return n.type=r,"+"===l?(n.keyOrCode=l,n):(l.split("+").forEach((t=>{o.test(t)?n.altKey=!0:u.test(t)?n.ctrlKey=!0:c.test(t)?n.metaKey=!0:a.test(t)?n.shiftKey=!0:s.test(t)?e.indexOf("Mac")>-1?n.metaKey=!0:n.ctrlKey=!0:n.keyOrCode=t})),n)}createMatchingKeyboardEvent(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{} -return new KeyboardEvent(this.type,Object.assign({key:this.keyOrCode,code:this.keyOrCode,altKey:this.altKey,ctrlKey:this.ctrlKey,metaKey:this.metaKey,shiftKey:this.shiftKey},t))}}},1377:(t,e,n)=>{"use strict" -function r(t){if("undefined"==typeof FastBoot)return void 0===t&&(t=navigator.platform),t.indexOf("Mac")>-1?"meta":"ctrl"}function i(t){return t.sort().join("+")}function o(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=e -"string"==typeof e&&(n=e.split("+")),n.indexOf("cmd")>-1&&(n[n.indexOf("cmd")]=r()) -let o=i(n||[]) -return""===o&&(o="_all"),`${t}:${o}`}n.d(e,{Z:()=>o})},2001:(t,e,n)=>{"use strict" -n.d(e,{Z:()=>o}) -var r=n(3353) -let i -function o(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:navigator.userAgent -if((0,r.runInDebug)((()=>{i=null})),!i){let e="Unknown OS";-1!=t.indexOf("Win")&&(e="Windows"),-1!=t.indexOf("Mac")&&(e="Macintosh"),-1!=t.indexOf("Linux")&&(e="Linux"),-1!=t.indexOf("Android")&&(e="Android"),-1!=t.indexOf("like Mac")&&(e="iOS"),i=e}return i}},4564:t=>{function e(t,e,n,r){var i,o=null==(i=r)||"number"==typeof i||"boolean"==typeof i?r:n(r),a=e.get(o) -return void 0===a&&(a=t.call(this,r),e.set(o,a)),a}function n(t,e,n){var r=Array.prototype.slice.call(arguments,3),i=n(r),o=e.get(i) -return void 0===o&&(o=t.apply(this,r),e.set(i,o)),o}function r(t,e,n,r,i){return n.bind(e,t,r,i)}function i(t,i){return r(t,this,1===t.length?e:n,i.cache.create(),i.serializer)}function o(){return JSON.stringify(arguments)}function a(){this.cache=Object.create(null)}a.prototype.has=function(t){return t in this.cache},a.prototype.get=function(t){return this.cache[t]},a.prototype.set=function(t,e){this.cache[t]=e} -var u={create:function(){return new a}} -t.exports=function(t,e){var n=e&&e.cache?e.cache:u,r=e&&e.serializer?e.serializer:o -return(e&&e.strategy?e.strategy:i)(t,{cache:n,serializer:r})},t.exports.strategies={variadic:function(t,e){return r(t,this,n,e.cache.create(),e.serializer)},monadic:function(t,n){return r(t,this,e,n.cache.create(),n.serializer)}}},8581:t=>{function e(t){return t&&t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}function n(t){return t}function r(t,r){const i=(r=r||{}).delimiter||".",o=r.maxDepth,a=r.transformKey||n,u={} -return function t(n,c,s){s=s||1,Object.keys(n).forEach((function(f){const l=n[f],h=r.safe&&Array.isArray(l),d=Object.prototype.toString.call(l),p=e(l),y="[object Object]"===d||"[object Array]"===d,b=c?c+i+a(f):a(f) -if(!h&&!p&&y&&Object.keys(l).length&&(!r.maxDepth||s0&&(r=f(n.shift()),l=f(n[0]))}h[r]=t(i[e],o)})),s}},2914:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{default:()=>s}) -var r,i=function(){function t(){this.registry=new WeakMap}return t.prototype.elementExists=function(t){return this.registry.has(t)},t.prototype.getElement=function(t){return this.registry.get(t)},t.prototype.addElement=function(t,e){t&&this.registry.set(t,e||{})},t.prototype.removeElement=function(t){this.registry.delete(t)},t.prototype.destroyRegistry=function(){this.registry=new WeakMap},t}(),o=function(){} -!function(t){t.enter="enter",t.exit="exit"}(r||(r={})) -var a,u=function(){function t(){this.registry=new i}return t.prototype.addCallback=function(t,e,n){var i,o,a -t===r.enter?((i={})[r.enter]=n,a=i):((o={})[r.exit]=n,a=o),this.registry.addElement(e,Object.assign({},this.registry.getElement(e),a))},t.prototype.dispatchCallback=function(t,e,n){if(t===r.enter){var i=this.registry.getElement(e).enter;(void 0===i?o:i)(n)}else{var a=this.registry.getElement(e).exit;(void 0===a?o:a)(n)}},t}(),c=(a=function(t,e){return a=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])},a(t,e)},function(t,e){function n(){this.constructor=t}a(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}) -const s=function(t){function e(){var e=t.call(this)||this -return e.elementRegistry=new i,e}return c(e,t),e.prototype.observe=function(t,e){void 0===e&&(e={}),t&&(this.elementRegistry.addElement(t,e),this.setupObserver(t,e))},e.prototype.unobserve=function(t,e){var n=this.findMatchingRootEntry(e) -n&&n.intersectionObserver.unobserve(t)},e.prototype.addEnterCallback=function(t,e){this.addCallback(r.enter,t,e)},e.prototype.addExitCallback=function(t,e){this.addCallback(r.exit,t,e)},e.prototype.dispatchEnterCallback=function(t,e){this.dispatchCallback(r.enter,t,e)},e.prototype.dispatchExitCallback=function(t,e){this.dispatchCallback(r.exit,t,e)},e.prototype.destroy=function(){this.elementRegistry.destroyRegistry()},e.prototype.setupOnIntersection=function(t){var e=this -return function(n){return e.onIntersection(t,n)}},e.prototype.setupObserver=function(t,e){var n,r,i=e.root,o=void 0===i?window:i,a=this.findRootFromRegistry(o) -if(a&&(r=this.determineMatchingElements(e,a)),r){var u=r.elements,c=r.intersectionObserver -u.push(t),c&&c.observe(t)}else{var s={elements:[t],intersectionObserver:c=this.newObserver(t,e),options:e},f=this.stringifyOptions(e) -a?a[f]=s:this.elementRegistry.addElement(o,((n={})[f]=s,n))}},e.prototype.newObserver=function(t,e){var n=e.root,r=e.rootMargin,i=e.threshold,o=new IntersectionObserver(this.setupOnIntersection(e).bind(this),{root:n,rootMargin:r,threshold:i}) -return o.observe(t),o},e.prototype.onIntersection=function(t,e){var n=this -e.forEach((function(e){var r=e.isIntersecting,i=e.intersectionRatio,o=t.threshold||0 -Array.isArray(o)&&(o=o[o.length-1]) -var a=n.findMatchingRootEntry(t) -r||i>o?a&&a.elements.some((function(t){return!(!t||t!==e.target||(n.dispatchEnterCallback(t,e),0))})):a&&a.elements.some((function(t){return!(!t||t!==e.target||(n.dispatchExitCallback(t,e),0))}))}))},e.prototype.findRootFromRegistry=function(t){if(this.elementRegistry)return this.elementRegistry.getElement(t)},e.prototype.findMatchingRootEntry=function(t){var e=t.root,n=void 0===e?window:e,r=this.findRootFromRegistry(n) -if(r)return r[this.stringifyOptions(t)]},e.prototype.determineMatchingElements=function(t,e){var n=this,r=Object.keys(e).filter((function(r){var i=e[r].options -return n.areOptionsSame(t,i)}))[0] -return e[r]},e.prototype.areOptionsSame=function(t,e){if(t===e)return!0 -var n=Object.prototype.toString.call(t),r=Object.prototype.toString.call(e) -if(n!==r)return!1 -if("[object Object]"!==n&&"[object Object]"!==r)return t===e -if(t&&e&&"object"==typeof t&&"object"==typeof e)for(var i in t)if(Object.prototype.hasOwnProperty.call(t,i)&&!1===this.areOptionsSame(t[i],e[i]))return!1 -return!0},e.prototype.stringifyOptions=function(t){var e=t.root -return JSON.stringify(t,(function(t,n){if("root"===t&&e){var r=Array.prototype.slice.call(e.classList).reduce((function(t,e){return t+e}),"") -return e.id+"-"+r}return n}))},e}(u)},4857:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{SKELETON_TYPE:()=>i.aV,SyntaxError:()=>y,TYPE:()=>i.wD,createLiteralElement:()=>i.mD,createNumberElement:()=>i.qx,isArgumentElement:()=>i.VG,isDateElement:()=>i.rp,isDateTimeSkeleton:()=>i.Ii,isLiteralElement:()=>i.O4,isNumberElement:()=>i.uf,isNumberSkeleton:()=>i.Wh,isPluralElement:()=>i.Jo,isPoundElement:()=>i.yx,isSelectElement:()=>i.Wi,isTagElement:()=>i.HI,isTimeElement:()=>i.pe,parse:()=>m,pegParse:()=>b}) -var r=n(2247),i=n(8131),o=/(?:[Eec]{1,6}|G{1,5}|[Qq]{1,5}|(?:[yYur]+|U{1,5})|[ML]{1,5}|d{1,2}|D{1,3}|F{1}|[abB]{1,5}|[hkHK]{1,2}|w{1,2}|W{1}|m{1,2}|s{1,2}|[zZOvVxX]{1,4})(?=([^']*'[^']*')*[^']*$)/g,a=/^\.(?:(0+)(\*)?|(#+)|(0+)(#+))$/g,u=/^(@+)?(\+|#+)?$/g,c=/(\*)(0+)|(#+)(0+)|(0+)/g,s=/^(0+)$/ -function f(t){var e={} -return t.replace(u,(function(t,n,r){return"string"!=typeof r?(e.minimumSignificantDigits=n.length,e.maximumSignificantDigits=n.length):"+"===r?e.minimumSignificantDigits=n.length:"#"===n[0]?e.maximumSignificantDigits=n.length:(e.minimumSignificantDigits=n.length,e.maximumSignificantDigits=n.length+("string"==typeof r?r.length:0)),""})),e}function l(t){switch(t){case"sign-auto":return{signDisplay:"auto"} -case"sign-accounting":case"()":return{currencySign:"accounting"} -case"sign-always":case"+!":return{signDisplay:"always"} -case"sign-accounting-always":case"()!":return{signDisplay:"always",currencySign:"accounting"} -case"sign-except-zero":case"+?":return{signDisplay:"exceptZero"} -case"sign-accounting-except-zero":case"()?":return{signDisplay:"exceptZero",currencySign:"accounting"} -case"sign-never":case"+_":return{signDisplay:"never"}}}function h(t){var e -if("E"===t[0]&&"E"===t[1]?(e={notation:"engineering"},t=t.slice(2)):"E"===t[0]&&(e={notation:"scientific"},t=t.slice(1)),e){var n=t.slice(0,2) -if("+!"===n?(e.signDisplay="always",t=t.slice(2)):"+?"===n&&(e.signDisplay="exceptZero",t=t.slice(2)),!s.test(t))throw new Error("Malformed concise eng/scientific notation") -e.minimumIntegerDigits=t.length}return e}function d(t){return l(t)||{}}function p(t){for(var e={},n=0,i=t;n1)throw new RangeError("integer-width stems only accept a single optional option") -o.options[0].replace(c,(function(t,n,r,i,o,a){if(n)e.minimumIntegerDigits=r.length -else{if(i&&o)throw new Error("We currently do not support maximum integer digits") -if(a)throw new Error("We currently do not support exact integer digits")}return""})) -continue}if(s.test(o.stem))e.minimumIntegerDigits=o.stem.length -else if(a.test(o.stem)){if(o.options.length>1)throw new RangeError("Fraction-precision stems only accept a single optional option") -o.stem.replace(a,(function(t,n,r,i,o,a){return"*"===r?e.minimumFractionDigits=n.length:i&&"#"===i[0]?e.maximumFractionDigits=i.length:o&&a?(e.minimumFractionDigits=o.length,e.maximumFractionDigits=o.length+a.length):(e.minimumFractionDigits=n.length,e.maximumFractionDigits=n.length),""})),o.options.length&&(e=(0,r.pi)((0,r.pi)({},e),f(o.options[0])))}else if(u.test(o.stem))e=(0,r.pi)((0,r.pi)({},e),f(o.stem)) -else{var p=l(o.stem) -p&&(e=(0,r.pi)((0,r.pi)({},e),p)) -var y=h(o.stem) -y&&(e=(0,r.pi)((0,r.pi)({},e),y))}}return e}var y=function(t){function e(n,r,i,o){var a=t.call(this)||this -return a.message=n,a.expected=r,a.found=i,a.location=o,a.name="SyntaxError","function"==typeof Error.captureStackTrace&&Error.captureStackTrace(a,e),a}return(0,r.ZT)(e,t),e.buildMessage=function(t,e){function n(t){return t.charCodeAt(0).toString(16).toUpperCase()}function r(t){return t.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,(function(t){return"\\x0"+n(t)})).replace(/[\x10-\x1F\x7F-\x9F]/g,(function(t){return"\\x"+n(t)}))}function i(t){return t.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replace(/\^/g,"\\^").replace(/-/g,"\\-").replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,(function(t){return"\\x0"+n(t)})).replace(/[\x10-\x1F\x7F-\x9F]/g,(function(t){return"\\x"+n(t)}))}function o(t){switch(t.type){case"literal":return'"'+r(t.text)+'"' -case"class":var e=t.parts.map((function(t){return Array.isArray(t)?i(t[0])+"-"+i(t[1]):i(t)})) -return"["+(t.inverted?"^":"")+e+"]" -case"any":return"any character" -case"end":return"end of input" -case"other":return t.description}}return"Expected "+function(t){var e,n,r=t.map(o) -if(r.sort(),r.length>0){for(e=1,n=1;e",!1),v=Lt(">",!1),g=Lt("Tt&&(Tt=St,Bt=[]),Bt.push(t))}function qt(){return Vt()}function Vt(){var t,e -for(t=[],e=Ht();e!==a;)t.push(e),e=Ht() -return t}function Ht(){var e,n -return e=St,Mt=St,(xe?a:void 0)!==a?(n=function(){var t,e,n,o,u,c,s -return Pt++,(t=Kt())===a&&(t=St,(e=Wt())!==a&&(n=Vt())!==a&&(o=Xt())!==a?(Mt=t,c=n,(u=e)!==(s=o)&&Rt('Mismatch tag "'+u+'" !== "'+s+'"',Nt()),t=e=(0,r.pi)({type:i.wD.tag,value:u,children:c},ge())):(St=t,t=a)),Pt--,t===a&&(e=a,0===Pt&&Zt(d)),t}(),n!==a?(Mt=e,e=n):(St=e,e=a)):(St=e,e=a),e===a&&(e=function(){var t,e,n -return t=St,(e=Yt())!==a&&(Mt=t,n=e,e=(0,r.pi)({type:i.wD.literal,value:n},ge())),e}())===a&&(e=function(){var e,n,o,u,c -return Pt++,e=St,123===t.charCodeAt(St)?(n=_,St++):(n=a,0===Pt&&Zt(w)),n!==a&&ue()!==a&&(o=he())!==a&&ue()!==a?(125===t.charCodeAt(St)?(u=x,St++):(u=a,0===Pt&&Zt(A)),u!==a?(Mt=e,c=o,e=n=(0,r.pi)({type:i.wD.argument,value:c},ge())):(St=e,e=a)):(St=e,e=a),Pt--,e===a&&(n=a,0===Pt&&Zt(m)),e}())===a&&(e=function(){var e -return e=function(){var e,n,o,u,c,s,f,l,h -return e=St,123===t.charCodeAt(St)?(n=_,St++):(n=a,0===Pt&&Zt(w)),n!==a&&ue()!==a&&(o=he())!==a&&ue()!==a?(44===t.charCodeAt(St)?(u=P,St++):(u=a,0===Pt&&Zt(j)),u!==a&&ue()!==a?(t.substr(St,6)===N?(c=N,St+=6):(c=a,0===Pt&&Zt(R)),c!==a&&ue()!==a?(s=St,44===t.charCodeAt(St)?(f=P,St++):(f=a,0===Pt&&Zt(j)),f!==a&&(l=ue())!==a?(h=function(){var e,n,o -return e=St,t.substr(St,2)===F?(n=F,St+=2):(n=a,0===Pt&&Zt(T)),n!==a?(o=function(){var t,e,n,o -if(t=St,e=[],(n=te())!==a)for(;n!==a;)e.push(n),n=te() -else e=a -return e!==a&&(Mt=t,o=e,e=(0,r.pi)({type:i.aV.number,tokens:o,parsedOptions:Ae?p(o):{}},ge())),e}(),o!==a?(Mt=e,e=n=o):(St=e,e=a)):(St=e,e=a),e===a&&(e=St,Mt=St,be.push("numberArgStyle"),(n=(n=!0)?void 0:a)!==a&&(o=Yt())!==a?(Mt=e,e=n=B(o)):(St=e,e=a)),e}(),h!==a?s=f=[f,l,h]:(St=s,s=a)):(St=s,s=a),s===a&&(s=null),s!==a&&(f=ue())!==a?(125===t.charCodeAt(St)?(l=x,St++):(l=a,0===Pt&&Zt(A)),l!==a?(Mt=e,e=n=L(o,c,s)):(St=e,e=a)):(St=e,e=a)):(St=e,e=a)):(St=e,e=a)):(St=e,e=a),e}(),e===a&&(e=function(){var e,n,u,c,s,f,l,h,d -return e=St,123===t.charCodeAt(St)?(n=_,St++):(n=a,0===Pt&&Zt(w)),n!==a&&ue()!==a&&(u=he())!==a&&ue()!==a?(44===t.charCodeAt(St)?(c=P,St++):(c=a,0===Pt&&Zt(j)),c!==a&&ue()!==a?(t.substr(St,4)===Y?(s=Y,St+=4):(s=a,0===Pt&&Zt(G)),s===a&&(t.substr(St,4)===K?(s=K,St+=4):(s=a,0===Pt&&Zt(W))),s!==a&&ue()!==a?(f=St,44===t.charCodeAt(St)?(l=P,St++):(l=a,0===Pt&&Zt(j)),l!==a&&(h=ue())!==a?(d=function(){var e,n,u -return e=St,t.substr(St,2)===F?(n=F,St+=2):(n=a,0===Pt&&Zt(T)),n!==a?(u=function(){var e,n,u,c,s,f,l -if(e=St,n=St,u=[],(c=ee())===a&&(c=ne()),c!==a)for(;c!==a;)u.push(c),(c=ee())===a&&(c=ne()) -else u=a -return(n=u!==a?t.substring(n,St):u)!==a&&(Mt=e,s=n,n=(0,r.pi)({type:i.aV.dateTime,pattern:s,parsedOptions:Ae?(f=s,l={},f.replace(o,(function(t){var e=t.length -switch(t[0]){case"G":l.era=4===e?"long":5===e?"narrow":"short" -break -case"y":l.year=2===e?"2-digit":"numeric" -break -case"Y":case"u":case"U":case"r":throw new RangeError("`Y/u/U/r` (year) patterns are not supported, use `y` instead") -case"q":case"Q":throw new RangeError("`q/Q` (quarter) patterns are not supported") -case"M":case"L":l.month=["numeric","2-digit","short","long","narrow"][e-1] -break -case"w":case"W":throw new RangeError("`w/W` (week) patterns are not supported") -case"d":l.day=["numeric","2-digit"][e-1] -break -case"D":case"F":case"g":throw new RangeError("`D/F/g` (day) patterns are not supported, use `d` instead") -case"E":l.weekday=4===e?"short":5===e?"narrow":"short" -break -case"e":if(e<4)throw new RangeError("`e..eee` (weekday) patterns are not supported") -l.weekday=["short","long","narrow","short"][e-4] -break -case"c":if(e<4)throw new RangeError("`c..ccc` (weekday) patterns are not supported") -l.weekday=["short","long","narrow","short"][e-4] -break -case"a":l.hour12=!0 -break -case"b":case"B":throw new RangeError("`b/B` (period) patterns are not supported, use `a` instead") -case"h":l.hourCycle="h12",l.hour=["numeric","2-digit"][e-1] -break -case"H":l.hourCycle="h23",l.hour=["numeric","2-digit"][e-1] -break -case"K":l.hourCycle="h11",l.hour=["numeric","2-digit"][e-1] -break -case"k":l.hourCycle="h24",l.hour=["numeric","2-digit"][e-1] -break -case"j":case"J":case"C":throw new RangeError("`j/J/C` (hour) patterns are not supported, use `h/H/K/k` instead") -case"m":l.minute=["numeric","2-digit"][e-1] -break -case"s":l.second=["numeric","2-digit"][e-1] -break -case"S":case"A":throw new RangeError("`S/A` (second) patterns are not supported, use `s` instead") -case"z":l.timeZoneName=e<4?"short":"long" -break -case"Z":case"O":case"v":case"V":case"X":case"x":throw new RangeError("`Z/O/v/V/X/x` (timeZone) patterns are not supported, use `z` instead")}return""})),l):{}},ge())),n}(),u!==a?(Mt=e,e=n=u):(St=e,e=a)):(St=e,e=a),e===a&&(e=St,Mt=St,be.push("dateOrTimeArgStyle"),(n=(n=!0)?void 0:a)!==a&&(u=Yt())!==a?(Mt=e,e=n=B(u)):(St=e,e=a)),e}(),d!==a?f=l=[l,h,d]:(St=f,f=a)):(St=f,f=a),f===a&&(f=null),f!==a&&(l=ue())!==a?(125===t.charCodeAt(St)?(h=x,St++):(h=a,0===Pt&&Zt(A)),h!==a?(Mt=e,e=n=L(u,s,f)):(St=e,e=a)):(St=e,e=a)):(St=e,e=a)):(St=e,e=a)):(St=e,e=a),e}()),e}(),e===a&&(e=function(){var e,n,o,u,c,s,f,l,h,d,p -if(e=St,123===t.charCodeAt(St)?(n=_,St++):(n=a,0===Pt&&Zt(w)),n!==a)if(ue()!==a)if((o=he())!==a)if(ue()!==a)if(44===t.charCodeAt(St)?(u=P,St++):(u=a,0===Pt&&Zt(j)),u!==a)if(ue()!==a)if(t.substr(St,6)===X?(c=X,St+=6):(c=a,0===Pt&&Zt(J)),c===a&&(t.substr(St,13)===Q?(c=Q,St+=13):(c=a,0===Pt&&Zt(tt))),c!==a)if(ue()!==a)if(44===t.charCodeAt(St)?(s=P,St++):(s=a,0===Pt&&Zt(j)),s!==a)if(ue()!==a)if(f=St,t.substr(St,7)===et?(l=et,St+=7):(l=a,0===Pt&&Zt(nt)),l!==a&&(h=ue())!==a&&(d=ce())!==a?f=l=[l,h,d]:(St=f,f=a),f===a&&(f=null),f!==a)if((l=ue())!==a){if(h=[],(d=ie())!==a)for(;d!==a;)h.push(d),d=ie() -else h=a -h!==a&&(d=ue())!==a?(125===t.charCodeAt(St)?(p=x,St++):(p=a,0===Pt&&Zt(A)),p!==a?(Mt=e,n=function(t,e,n,o){return(0,r.pi)({type:i.wD.plural,pluralType:"plural"===e?"cardinal":"ordinal",value:t,offset:n?n[2]:0,options:o.reduce((function(t,e){var n=e.id,r=e.value,i=e.location -return n in t&&Rt('Duplicate option "'+n+'" in plural element: "'+jt()+'"',Nt()),t[n]={value:r,location:i},t}),{})},ge())}(o,c,f,h),e=n):(St=e,e=a)):(St=e,e=a)}else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -return e}(),e===a&&(e=function(){var e,n,o,u,c,s,f,l,h -if(e=St,123===t.charCodeAt(St)?(n=_,St++):(n=a,0===Pt&&Zt(w)),n!==a)if(ue()!==a)if((o=he())!==a)if(ue()!==a)if(44===t.charCodeAt(St)?(u=P,St++):(u=a,0===Pt&&Zt(j)),u!==a)if(ue()!==a)if(t.substr(St,6)===rt?(c=rt,St+=6):(c=a,0===Pt&&Zt(it)),c!==a)if(ue()!==a)if(44===t.charCodeAt(St)?(s=P,St++):(s=a,0===Pt&&Zt(j)),s!==a)if(ue()!==a){if(f=[],(l=re())!==a)for(;l!==a;)f.push(l),l=re() -else f=a -f!==a&&(l=ue())!==a?(125===t.charCodeAt(St)?(h=x,St++):(h=a,0===Pt&&Zt(A)),h!==a?(Mt=e,n=function(t,e){return(0,r.pi)({type:i.wD.select,value:t,options:e.reduce((function(t,e){var n=e.id,r=e.value,i=e.location -return n in t&&Rt('Duplicate option "'+n+'" in select element: "'+jt()+'"',Nt()),t[n]={value:r,location:i},t}),{})},ge())}(o,f),e=n):(St=e,e=a)):(St=e,e=a)}else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -else St=e,e=a -return e}(),e===a&&(e=function(){var e,n -return e=St,35===t.charCodeAt(St)?(n="#",St++):(n=a,0===Pt&&Zt(h)),n!==a&&(Mt=e,n=(0,r.pi)({type:i.wD.pound},ge())),n}())))),e}function Yt(){var e,n,r,i -if(e=St,Mt=St,(n=(n=xe)?void 0:a)!==a){if(r=[],(i=se())===a&&(i=fe())===a&&(i=le())===a&&(60===t.charCodeAt(St)?(i=s,St++):(i=a,0===Pt&&Zt(f))),i!==a)for(;i!==a;)r.push(i),(i=se())===a&&(i=fe())===a&&(i=le())===a&&(60===t.charCodeAt(St)?(i=s,St++):(i=a,0===Pt&&Zt(f))) -else r=a -r!==a?(Mt=e,e=n=l(r)):(St=e,e=a)}else St=e,e=a -if(e===a){if(e=St,n=[],(r=se())===a&&(r=fe())===a&&(r=le())===a&&(r=Gt()),r!==a)for(;r!==a;)n.push(r),(r=se())===a&&(r=fe())===a&&(r=le())===a&&(r=Gt()) -else n=a -n!==a&&(Mt=e,n=l(n)),e=n}return e}function Gt(){var e,n,r -return e=St,n=St,Pt++,(r=Wt())===a&&(r=Xt())===a&&(r=Kt()),Pt--,r===a?n=void 0:(St=n,n=a),n!==a?(60===t.charCodeAt(St)?(r=s,St++):(r=a,0===Pt&&Zt(f)),r!==a?(Mt=e,e=n="<"):(St=e,e=a)):(St=e,e=a),e}function Kt(){var e,n,o,u,c,l,h -return e=St,n=St,60===t.charCodeAt(St)?(o=s,St++):(o=a,0===Pt&&Zt(f)),o!==a&&(u=de())!==a&&(c=ue())!==a?("/>"===t.substr(St,2)?(l="/>",St+=2):(l=a,0===Pt&&Zt(b)),l!==a?n=o=[o,u,c,l]:(St=n,n=a)):(St=n,n=a),n!==a&&(Mt=e,h=n,n=(0,r.pi)({type:i.wD.literal,value:h.join("")},ge())),n}function Wt(){var e,n,r,i -return e=St,60===t.charCodeAt(St)?(n=s,St++):(n=a,0===Pt&&Zt(f)),n!==a&&(r=de())!==a?(62===t.charCodeAt(St)?(i=">",St++):(i=a,0===Pt&&Zt(v)),i!==a?(Mt=e,e=n=r):(St=e,e=a)):(St=e,e=a),e}function Xt(){var e,n,r,i -return e=St,"",St++):(i=a,0===Pt&&Zt(v)),i!==a?(Mt=e,e=n=r):(St=e,e=a)):(St=e,e=a),e}function Jt(){var e,n,r,i,o -if(Pt++,e=St,n=[],r=St,i=St,Pt++,(o=oe())===a&&(k.test(t.charAt(St))?(o=t.charAt(St),St++):(o=a,0===Pt&&Zt(D))),Pt--,o===a?i=void 0:(St=i,i=a),i!==a?(t.length>St?(o=t.charAt(St),St++):(o=a,0===Pt&&Zt(C)),o!==a?r=i=[i,o]:(St=r,r=a)):(St=r,r=a),r!==a)for(;r!==a;)n.push(r),r=St,i=St,Pt++,(o=oe())===a&&(k.test(t.charAt(St))?(o=t.charAt(St),St++):(o=a,0===Pt&&Zt(D))),Pt--,o===a?i=void 0:(St=i,i=a),i!==a?(t.length>St?(o=t.charAt(St),St++):(o=a,0===Pt&&Zt(C)),o!==a?r=i=[i,o]:(St=r,r=a)):(St=r,r=a) -else n=a -return e=n!==a?t.substring(e,St):n,Pt--,e===a&&(n=a,0===Pt&&Zt(E)),e}function Qt(){var e,n,r -return Pt++,e=St,47===t.charCodeAt(St)?(n="/",St++):(n=a,0===Pt&&Zt(S)),n!==a&&(r=Jt())!==a?(Mt=e,e=n=r):(St=e,e=a),Pt--,e===a&&(n=a,0===Pt&&Zt(O)),e}function te(){var t,e,n,r,i -if(Pt++,t=St,(e=ue())!==a)if((n=Jt())!==a){for(r=[],i=Qt();i!==a;)r.push(i),i=Qt() -r!==a?(Mt=t,e=function(t,e){return{stem:t,options:e}}(n,r),t=e):(St=t,t=a)}else St=t,t=a -else St=t,t=a -return Pt--,t===a&&(e=a,0===Pt&&Zt(M)),t}function ee(){var e,n,r,i -if(e=St,39===t.charCodeAt(St)?(n=I,St++):(n=a,0===Pt&&Zt($)),n!==a){if(r=[],(i=se())===a&&(U.test(t.charAt(St))?(i=t.charAt(St),St++):(i=a,0===Pt&&Zt(z))),i!==a)for(;i!==a;)r.push(i),(i=se())===a&&(U.test(t.charAt(St))?(i=t.charAt(St),St++):(i=a,0===Pt&&Zt(z))) -else r=a -r!==a?(39===t.charCodeAt(St)?(i=I,St++):(i=a,0===Pt&&Zt($)),i!==a?e=n=[n,r,i]:(St=e,e=a)):(St=e,e=a)}else St=e,e=a -if(e===a)if(e=[],(n=se())===a&&(Z.test(t.charAt(St))?(n=t.charAt(St),St++):(n=a,0===Pt&&Zt(q))),n!==a)for(;n!==a;)e.push(n),(n=se())===a&&(Z.test(t.charAt(St))?(n=t.charAt(St),St++):(n=a,0===Pt&&Zt(q))) -else e=a -return e}function ne(){var e,n -if(e=[],V.test(t.charAt(St))?(n=t.charAt(St),St++):(n=a,0===Pt&&Zt(H)),n!==a)for(;n!==a;)e.push(n),V.test(t.charAt(St))?(n=t.charAt(St),St++):(n=a,0===Pt&&Zt(H)) -else e=a -return e}function re(){var e,n,i,o,u,c,s -return e=St,ue()!==a&&(n=ye())!==a&&ue()!==a?(123===t.charCodeAt(St)?(i=_,St++):(i=a,0===Pt&&Zt(w)),i!==a?(Mt=St,be.push("select"),void 0!==a&&(o=Vt())!==a?(125===t.charCodeAt(St)?(u=x,St++):(u=a,0===Pt&&Zt(A)),u!==a?(Mt=e,c=n,s=o,be.pop(),e=(0,r.pi)({id:c,value:s},ge())):(St=e,e=a)):(St=e,e=a)):(St=e,e=a)):(St=e,e=a),e}function ie(){var e,n,i,o,u,c,s -return e=St,ue()!==a?(n=function(){var e,n,r,i -return e=St,n=St,61===t.charCodeAt(St)?(r="=",St++):(r=a,0===Pt&&Zt(ot)),r!==a&&(i=ce())!==a?n=r=[r,i]:(St=n,n=a),(e=n!==a?t.substring(e,St):n)===a&&(e=ye()),e}(),n!==a&&ue()!==a?(123===t.charCodeAt(St)?(i=_,St++):(i=a,0===Pt&&Zt(w)),i!==a?(Mt=St,be.push("plural"),void 0!==a&&(o=Vt())!==a?(125===t.charCodeAt(St)?(u=x,St++):(u=a,0===Pt&&Zt(A)),u!==a?(Mt=e,c=n,s=o,be.pop(),e=(0,r.pi)({id:c,value:s},ge())):(St=e,e=a)):(St=e,e=a)):(St=e,e=a)):(St=e,e=a)):(St=e,e=a),e}function oe(){var e -return Pt++,ut.test(t.charAt(St))?(e=t.charAt(St),St++):(e=a,0===Pt&&Zt(ct)),Pt--,e===a&&0===Pt&&Zt(at),e}function ae(){var e -return Pt++,ft.test(t.charAt(St))?(e=t.charAt(St),St++):(e=a,0===Pt&&Zt(lt)),Pt--,e===a&&0===Pt&&Zt(st),e}function ue(){var e,n,r -for(Pt++,e=St,n=[],r=oe();r!==a;)n.push(r),r=oe() -return e=n!==a?t.substring(e,St):n,Pt--,e===a&&(n=a,0===Pt&&Zt(ht)),e}function ce(){var e,n,r,i -return Pt++,e=St,45===t.charCodeAt(St)?(n="-",St++):(n=a,0===Pt&&Zt(pt)),n===a&&(n=null),n!==a&&(r=pe())!==a?(Mt=e,e=n=(i=r)?n?-i:i:0):(St=e,e=a),Pt--,e===a&&(n=a,0===Pt&&Zt(dt)),e}function se(){var e,n -return Pt++,e=St,t.substr(St,2)===bt?(n=bt,St+=2):(n=a,0===Pt&&Zt(vt)),n!==a&&(Mt=e,n="'"),Pt--,(e=n)===a&&(n=a,0===Pt&&Zt(yt)),e}function fe(){var e,n,r,i,o,u -if(e=St,39===t.charCodeAt(St)?(n=I,St++):(n=a,0===Pt&&Zt($)),n!==a)if(r=function(){var e,n,r,i,o -return e=St,n=St,t.length>St?(r=t.charAt(St),St++):(r=a,0===Pt&&Zt(C)),r!==a?(Mt=St,(i=(i="<"===(o=r)||">"===o||"{"===o||"}"===o||ve()&&"#"===o)?void 0:a)!==a?n=r=[r,i]:(St=n,n=a)):(St=n,n=a),n!==a?t.substring(e,St):n}(),r!==a){for(i=St,o=[],t.substr(St,2)===bt?(u=bt,St+=2):(u=a,0===Pt&&Zt(vt)),u===a&&(U.test(t.charAt(St))?(u=t.charAt(St),St++):(u=a,0===Pt&&Zt(z)));u!==a;)o.push(u),t.substr(St,2)===bt?(u=bt,St+=2):(u=a,0===Pt&&Zt(vt)),u===a&&(U.test(t.charAt(St))?(u=t.charAt(St),St++):(u=a,0===Pt&&Zt(z)));(i=o!==a?t.substring(i,St):o)!==a?(39===t.charCodeAt(St)?(o=I,St++):(o=a,0===Pt&&Zt($)),o===a&&(o=null),o!==a?(Mt=e,e=n=r+i.replace("''","'")):(St=e,e=a)):(St=e,e=a)}else St=e,e=a -else St=e,e=a -return e}function le(){var e,n,r,i,o -return e=St,n=St,t.length>St?(r=t.charAt(St),St++):(r=a,0===Pt&&Zt(C)),r!==a?(Mt=St,(i=(i=!("<"===(o=r)||"{"===o||ve()&&"#"===o||be.length>1&&"}"===o))?void 0:a)!==a?n=r=[r,i]:(St=n,n=a)):(St=n,n=a),n===a&&(10===t.charCodeAt(St)?(n="\n",St++):(n=a,0===Pt&&Zt(gt))),n!==a?t.substring(e,St):n}function he(){var e,n -return Pt++,e=St,(n=pe())===a&&(n=ye()),e=n!==a?t.substring(e,St):n,Pt--,e===a&&(n=a,0===Pt&&Zt(mt)),e}function de(){var e,n -return Pt++,e=St,(n=pe())===a&&(n=function(){var e,n,r,i,o -if(Pt++,e=St,n=[],45===t.charCodeAt(St)?(r="-",St++):(r=a,0===Pt&&Zt(pt)),r===a&&(r=St,i=St,Pt++,(o=oe())===a&&(o=ae()),Pt--,o===a?i=void 0:(St=i,i=a),i!==a?(t.length>St?(o=t.charAt(St),St++):(o=a,0===Pt&&Zt(C)),o!==a?r=i=[i,o]:(St=r,r=a)):(St=r,r=a)),r!==a)for(;r!==a;)n.push(r),45===t.charCodeAt(St)?(r="-",St++):(r=a,0===Pt&&Zt(pt)),r===a&&(r=St,i=St,Pt++,(o=oe())===a&&(o=ae()),Pt--,o===a?i=void 0:(St=i,i=a),i!==a?(t.length>St?(o=t.charAt(St),St++):(o=a,0===Pt&&Zt(C)),o!==a?r=i=[i,o]:(St=r,r=a)):(St=r,r=a)) -else n=a -return e=n!==a?t.substring(e,St):n,Pt--,e===a&&(n=a,0===Pt&&Zt(Ot)),e}()),e=n!==a?t.substring(e,St):n,Pt--,e===a&&(n=a,0===Pt&&Zt(_t)),e}function pe(){var e,n,r,i,o -if(Pt++,e=St,48===t.charCodeAt(St)?(n="0",St++):(n=a,0===Pt&&Zt(xt)),n!==a&&(Mt=e,n=0),(e=n)===a){if(e=St,n=St,At.test(t.charAt(St))?(r=t.charAt(St),St++):(r=a,0===Pt&&Zt(Et)),r!==a){for(i=[],kt.test(t.charAt(St))?(o=t.charAt(St),St++):(o=a,0===Pt&&Zt(Dt));o!==a;)i.push(o),kt.test(t.charAt(St))?(o=t.charAt(St),St++):(o=a,0===Pt&&Zt(Dt)) -i!==a?n=r=[r,i]:(St=n,n=a)}else St=n,n=a -n!==a&&(Mt=e,n=parseInt(n.join(""),10)),e=n}return Pt--,e===a&&(n=a,0===Pt&&Zt(wt)),e}function ye(){var e,n,r,i,o -if(Pt++,e=St,n=[],r=St,i=St,Pt++,(o=oe())===a&&(o=ae()),Pt--,o===a?i=void 0:(St=i,i=a),i!==a?(t.length>St?(o=t.charAt(St),St++):(o=a,0===Pt&&Zt(C)),o!==a?r=i=[i,o]:(St=r,r=a)):(St=r,r=a),r!==a)for(;r!==a;)n.push(r),r=St,i=St,Pt++,(o=oe())===a&&(o=ae()),Pt--,o===a?i=void 0:(St=i,i=a),i!==a?(t.length>St?(o=t.charAt(St),St++):(o=a,0===Pt&&Zt(C)),o!==a?r=i=[i,o]:(St=r,r=a)):(St=r,r=a) -else n=a -return e=n!==a?t.substring(e,St):n,Pt--,e===a&&(n=a,0===Pt&&Zt(Ct)),e}var be=["root"] -function ve(){return"plural"===be[be.length-1]}function ge(){return e&&e.captureLocation?{location:Nt()}:{}}var me,_e,we,xe=e&&e.ignoreTag,Ae=e&&e.shouldParseSkeleton -if((n=c())!==a&&St===t.length)return n -throw n!==a&&St{"use strict" -var r,i -function o(t){return t.type===r.literal}function a(t){return t.type===r.argument}function u(t){return t.type===r.number}function c(t){return t.type===r.date}function s(t){return t.type===r.time}function f(t){return t.type===r.select}function l(t){return t.type===r.plural}function h(t){return t.type===r.pound}function d(t){return t.type===r.tag}function p(t){return!(!t||"object"!=typeof t||t.type!==i.number)}function y(t){return!(!t||"object"!=typeof t||t.type!==i.dateTime)}function b(t){return{type:r.literal,value:t}}function v(t,e){return{type:r.number,value:t,style:e}}n.d(e,{HI:()=>d,Ii:()=>y,Jo:()=>l,O4:()=>o,VG:()=>a,Wh:()=>p,Wi:()=>f,aV:()=>i,mD:()=>b,pe:()=>s,qx:()=>v,rp:()=>c,uf:()=>u,wD:()=>r,yx:()=>h}),function(t){t[t.literal=0]="literal",t[t.argument=1]="argument",t[t.number=2]="number",t[t.date=3]="date",t[t.time=4]="time",t[t.select=5]="select",t[t.plural=6]="plural",t[t.pound=7]="pound",t[t.tag=8]="tag"}(r||(r={})),function(t){t[t.number=0]="number",t[t.dateTime=1]="dateTime"}(i||(i={}))},4143:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{ErrorCode:()=>r,FormatError:()=>f,IntlMessageFormat:()=>g,InvalidValueError:()=>l,InvalidValueTypeError:()=>h,MissingValueError:()=>d,PART_TYPE:()=>s,default:()=>m,formatToParts:()=>y,isFormatXMLElementFn:()=>p}) -var r,i=n(2247),o=n(4857),a=n(4564),u=n.n(a),c=n(8131) -!function(t){t.MISSING_VALUE="MISSING_VALUE",t.INVALID_VALUE="INVALID_VALUE",t.MISSING_INTL_API="MISSING_INTL_API"}(r||(r={})) -var s,f=function(t){function e(e,n,r){var i=t.call(this,e)||this -return i.code=n,i.originalMessage=r,i}return(0,i.ZT)(e,t),e.prototype.toString=function(){return"[formatjs Error: "+this.code+"] "+this.message},e}(Error),l=function(t){function e(e,n,i,o){return t.call(this,'Invalid values for "'+e+'": "'+n+'". Options are "'+Object.keys(i).join('", "')+'"',r.INVALID_VALUE,o)||this}return(0,i.ZT)(e,t),e}(f),h=function(t){function e(e,n,i){return t.call(this,'Value for "'+e+'" must be of type '+n,r.INVALID_VALUE,i)||this}return(0,i.ZT)(e,t),e}(f),d=function(t){function e(e,n){return t.call(this,'The intl string context variable "'+e+'" was not provided to the string "'+n+'"',r.MISSING_VALUE,n)||this}return(0,i.ZT)(e,t),e}(f) -function p(t){return"function"==typeof t}function y(t,e,n,i,o,a,u){if(1===t.length&&(0,c.O4)(t[0]))return[{type:s.literal,value:t[0].value}] -for(var b=[],v=0,g=t;v{var r=n(1219),i=n(2251) -function o(t){this.Container=t||Array,this.items=new Map,this.clear(),Object.defineProperty(this.items,"constructor",{value:o,enumerable:!1})}o.prototype.clear=function(){this.size=0,this.dimension=0,this.items.clear()},o.prototype.set=function(t,e){var n,r=this.items.get(t) -return r||(this.dimension++,r=new this.Container,this.items.set(t,r)),this.Container===Set?(n=r.size,r.add(e),n1?e:this,this.items.forEach((function(t,e){n=e,t.forEach(r)}))},o.prototype.forEachAssociation=function(t,e){e=arguments.length>1?e:this,this.items.forEach(t,e)},o.prototype.keys=function(){return this.items.keys()},o.prototype.values=function(){var t,e,n,i,o=this.items.values(),a=!1 -return this.Container===Set?new r((function n(){if(!a){if((e=o.next()).done)return{done:!0} -a=!0,t=e.value.values()}return(e=t.next()).done?(a=!1,n()):{done:!1,value:e.value}})):new r((function r(){if(!a){if((e=o.next()).done)return{done:!0} -a=!0,t=e.value,n=0,i=t.length}return n>=i?(a=!1,r()):{done:!1,value:t[n++]}}))},o.prototype.entries=function(){var t,e,n,i,o,a=this.items.entries(),u=!1 -return this.Container===Set?new r((function r(){if(!u){if((e=a.next()).done)return{done:!0} -u=!0,n=e.value[0],t=e.value[1].values()}return(e=t.next()).done?(u=!1,r()):{done:!1,value:[n,e.value]}})):new r((function r(){if(!u){if((e=a.next()).done)return{done:!0} -u=!0,n=e.value[0],t=e.value[1],i=0,o=t.length}return i>=o?(u=!1,r()):{done:!1,value:[n,t[i++]]}}))},o.prototype.containers=function(){return this.items.values()},o.prototype.associations=function(){return this.items.entries()},"undefined"!=typeof Symbol&&(o.prototype[Symbol.iterator]=o.prototype.entries),o.prototype.inspect=function(){return this.items},"undefined"!=typeof Symbol&&(o.prototype[Symbol.for("nodejs.util.inspect.custom")]=o.prototype.inspect),o.prototype.toJSON=function(){return this.items},o.from=function(t,e){var n=new o(e) -return i(t,(function(t,e){n.set(e,t)})),n},t.exports=o},3333:(t,e)=>{e.intersection=function(){if(arguments.length<2)throw new Error("mnemonist/Set.intersection: needs at least two arguments.") -var t,e,n=new Set,r=1/0,i=null,o=arguments.length -for(e=0;ee.size)return!1 -for(;!(n=r.next()).done;)if(!e.has(n.value))return!1 -return!0},e.isSuperset=function(t,n){return e.isSubset(n,t)},e.add=function(t,e){for(var n,r=e.values();!(n=r.next()).done;)t.add(n.value)},e.subtract=function(t,e){for(var n,r=e.values();!(n=r.next()).done;)t.delete(n.value)},e.intersect=function(t,e){for(var n,r=t.values();!(n=r.next()).done;)e.has(n.value)||t.delete(n.value)},e.disjunct=function(t,e){for(var n,r=t.values(),i=[];!(n=r.next()).done;)e.has(n.value)&&i.push(n.value) -for(r=e.values();!(n=r.next()).done;)t.has(n.value)||t.add(n.value) -for(var o=0,a=i.length;oe.size&&(n=t,t=e,e=n),0===t.size)return 0 -if(t===e)return t.size -for(var r,i=t.values(),o=0;!(r=i.next()).done;)e.has(r.value)&&o++ -return o},e.unionSize=function(t,n){var r=e.intersectionSize(t,n) -return t.size+n.size-r},e.jaccard=function(t,n){var r=e.intersectionSize(t,n) -return 0===r?0:r/(t.size+n.size-r)},e.overlap=function(t,n){var r=e.intersectionSize(t,n) -return 0===r?0:r/Math.min(t.size,n.size)}},260:t=>{function e(t,e){if(!t)throw new Error(e||"AssertionError")}e.notEqual=function(t,n,r){e(t!=n,r)},e.notOk=function(t,n){e(!t,n)},e.equal=function(t,n,r){e(t==n,r)},e.ok=e,t.exports=e},4662:t=>{t.exports=function(t){!function(t){if(!t)throw new Error("Eventify cannot use falsy object as events subject") -for(var e=["on","fire","off"],n=0;n1&&(r=Array.prototype.splice.call(arguments,1)) -for(var o=0;o{t.exports=function(t){if("uniqueLinkId"in(t=t||{})&&(console.warn("ngraph.graph: Starting from version 0.14 `uniqueLinkId` is deprecated.\nUse `multigraph` option instead\n","\n","Note: there is also change in default behavior: From now on each graph\nis considered to be not a multigraph by default (each edge is unique)."),t.multigraph=t.uniqueLinkId),void 0===t.multigraph&&(t.multigraph=!1),"function"!=typeof Map)throw new Error("ngraph.graph requires `Map` to be defined. Please polyfill it before using ngraph") -var e,n=new Map,s=[],f={},l=0,h=t.multigraph?function(t,e,n){var r=c(t,e),i=f.hasOwnProperty(r) -if(i||C(t,e)){i||(f[r]=0) -var o="@"+ ++f[r] -r=c(t+o,e+o)}return new u(t,e,n,r)}:function(t,e,n){return new u(t,e,n,c(t,e))},d=[],p=O,y=O,b=O,v=O,g={addNode:w,addLink:function(t,e,n){b() -var r=x(t)||w(t),i=x(e)||w(e),o=h(t,e,n) -return s.push(o),a(r,o),t!==e&&a(i,o),p(o,"add"),v(),o},removeLink:D,removeNode:A,getNode:x,getNodeCount:E,getLinkCount:k,getLinksCount:k,getNodesCount:E,getLinks:function(t){var e=x(t) -return e?e.links:null},forEachNode:F,forEachLinkedNode:function(t,e,r){var i=x(t) -if(i&&i.links&&"function"==typeof e)return r?function(t,e,r){for(var i=0;i=0&&n.links.splice(e,1),r&&(e=i(t,r.links))>=0&&r.links.splice(e,1),p(t,"remove"),v(),!0}function C(t,e){var n,r=x(t) -if(!r||!r.links)return null -for(n=0;n0&&(g.fire("changed",d),d.length=0)}function F(t){if("function"!=typeof t)throw new Error("Function is expected to iterate over graph nodes. You passed "+t) -for(var e=n.values(),r=e.next();!r.done;){if(t(r.value))return!0 -r=e.next()}}} -var r=n(4662) -function i(t,e){if(!e)return-1 -if(e.indexOf)return e.indexOf(t) -var n,r=e.length -for(n=0;n{var e="undefined"!=typeof ArrayBuffer,n="undefined"!=typeof Symbol -function r(t,r){var i,o,a,u,c -if(!t)throw new Error("obliterator/forEach: invalid iterable.") -if("function"!=typeof r)throw new Error("obliterator/forEach: expecting a callback.") -if(Array.isArray(t)||e&&ArrayBuffer.isView(t)||"string"==typeof t||"[object Arguments]"===t.toString())for(a=0,u=t.length;a{function e(t){Object.defineProperty(this,"_next",{writable:!1,enumerable:!1,value:t}),this.done=!1}e.prototype.next=function(){if(this.done)return{done:!0} -var t=this._next() -return t.done&&(this.done=!0),t},"undefined"!=typeof Symbol&&(e.prototype[Symbol.iterator]=function(){return this}),e.of=function(){var t=arguments,n=t.length,r=0 -return new e((function(){return r>=n?{done:!0}:{done:!1,value:t[r++]}}))},e.empty=function(){var t=new e(null) -return t.done=!0,t},e.is=function(t){return t instanceof e||"object"==typeof t&&null!==t&&"function"==typeof t.next},t.exports=e},1813:t=>{"use strict" -var e=/(\x2D?(?:\d+\.?\d*|\d*\.?\d+)(?:e[-+]?\d+)?)\s*([A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5D\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC\u{10000}-\u{1000B}\u{1000D}-\u{10026}\u{10028}-\u{1003A}\u{1003C}\u{1003D}\u{1003F}-\u{1004D}\u{10050}-\u{1005D}\u{10080}-\u{100FA}\u{10280}-\u{1029C}\u{102A0}-\u{102D0}\u{10300}-\u{1031F}\u{1032D}-\u{10340}\u{10342}-\u{10349}\u{10350}-\u{10375}\u{10380}-\u{1039D}\u{103A0}-\u{103C3}\u{103C8}-\u{103CF}\u{10400}-\u{1049D}\u{104B0}-\u{104D3}\u{104D8}-\u{104FB}\u{10500}-\u{10527}\u{10530}-\u{10563}\u{10570}-\u{1057A}\u{1057C}-\u{1058A}\u{1058C}-\u{10592}\u{10594}\u{10595}\u{10597}-\u{105A1}\u{105A3}-\u{105B1}\u{105B3}-\u{105B9}\u{105BB}\u{105BC}\u{10600}-\u{10736}\u{10740}-\u{10755}\u{10760}-\u{10767}\u{10780}-\u{10785}\u{10787}-\u{107B0}\u{107B2}-\u{107BA}\u{10800}-\u{10805}\u{10808}\u{1080A}-\u{10835}\u{10837}\u{10838}\u{1083C}\u{1083F}-\u{10855}\u{10860}-\u{10876}\u{10880}-\u{1089E}\u{108E0}-\u{108F2}\u{108F4}\u{108F5}\u{10900}-\u{10915}\u{10920}-\u{10939}\u{10980}-\u{109B7}\u{109BE}\u{109BF}\u{10A00}\u{10A10}-\u{10A13}\u{10A15}-\u{10A17}\u{10A19}-\u{10A35}\u{10A60}-\u{10A7C}\u{10A80}-\u{10A9C}\u{10AC0}-\u{10AC7}\u{10AC9}-\u{10AE4}\u{10B00}-\u{10B35}\u{10B40}-\u{10B55}\u{10B60}-\u{10B72}\u{10B80}-\u{10B91}\u{10C00}-\u{10C48}\u{10C80}-\u{10CB2}\u{10CC0}-\u{10CF2}\u{10D00}-\u{10D23}\u{10E80}-\u{10EA9}\u{10EB0}\u{10EB1}\u{10F00}-\u{10F1C}\u{10F27}\u{10F30}-\u{10F45}\u{10F70}-\u{10F81}\u{10FB0}-\u{10FC4}\u{10FE0}-\u{10FF6}\u{11003}-\u{11037}\u{11071}\u{11072}\u{11075}\u{11083}-\u{110AF}\u{110D0}-\u{110E8}\u{11103}-\u{11126}\u{11144}\u{11147}\u{11150}-\u{11172}\u{11176}\u{11183}-\u{111B2}\u{111C1}-\u{111C4}\u{111DA}\u{111DC}\u{11200}-\u{11211}\u{11213}-\u{1122B}\u{11280}-\u{11286}\u{11288}\u{1128A}-\u{1128D}\u{1128F}-\u{1129D}\u{1129F}-\u{112A8}\u{112B0}-\u{112DE}\u{11305}-\u{1130C}\u{1130F}\u{11310}\u{11313}-\u{11328}\u{1132A}-\u{11330}\u{11332}\u{11333}\u{11335}-\u{11339}\u{1133D}\u{11350}\u{1135D}-\u{11361}\u{11400}-\u{11434}\u{11447}-\u{1144A}\u{1145F}-\u{11461}\u{11480}-\u{114AF}\u{114C4}\u{114C5}\u{114C7}\u{11580}-\u{115AE}\u{115D8}-\u{115DB}\u{11600}-\u{1162F}\u{11644}\u{11680}-\u{116AA}\u{116B8}\u{11700}-\u{1171A}\u{11740}-\u{11746}\u{11800}-\u{1182B}\u{118A0}-\u{118DF}\u{118FF}-\u{11906}\u{11909}\u{1190C}-\u{11913}\u{11915}\u{11916}\u{11918}-\u{1192F}\u{1193F}\u{11941}\u{119A0}-\u{119A7}\u{119AA}-\u{119D0}\u{119E1}\u{119E3}\u{11A00}\u{11A0B}-\u{11A32}\u{11A3A}\u{11A50}\u{11A5C}-\u{11A89}\u{11A9D}\u{11AB0}-\u{11AF8}\u{11C00}-\u{11C08}\u{11C0A}-\u{11C2E}\u{11C40}\u{11C72}-\u{11C8F}\u{11D00}-\u{11D06}\u{11D08}\u{11D09}\u{11D0B}-\u{11D30}\u{11D46}\u{11D60}-\u{11D65}\u{11D67}\u{11D68}\u{11D6A}-\u{11D89}\u{11D98}\u{11EE0}-\u{11EF2}\u{11FB0}\u{12000}-\u{12399}\u{12480}-\u{12543}\u{12F90}-\u{12FF0}\u{13000}-\u{1342E}\u{14400}-\u{14646}\u{16800}-\u{16A38}\u{16A40}-\u{16A5E}\u{16A70}-\u{16ABE}\u{16AD0}-\u{16AED}\u{16B00}-\u{16B2F}\u{16B40}-\u{16B43}\u{16B63}-\u{16B77}\u{16B7D}-\u{16B8F}\u{16E40}-\u{16E7F}\u{16F00}-\u{16F4A}\u{16F50}\u{16F93}-\u{16F9F}\u{16FE0}\u{16FE1}\u{16FE3}\u{17000}-\u{187F7}\u{18800}-\u{18CD5}\u{18D00}-\u{18D08}\u{1AFF0}-\u{1AFF3}\u{1AFF5}-\u{1AFFB}\u{1AFFD}\u{1AFFE}\u{1B000}-\u{1B122}\u{1B150}-\u{1B152}\u{1B164}-\u{1B167}\u{1B170}-\u{1B2FB}\u{1BC00}-\u{1BC6A}\u{1BC70}-\u{1BC7C}\u{1BC80}-\u{1BC88}\u{1BC90}-\u{1BC99}\u{1D400}-\u{1D454}\u{1D456}-\u{1D49C}\u{1D49E}\u{1D49F}\u{1D4A2}\u{1D4A5}\u{1D4A6}\u{1D4A9}-\u{1D4AC}\u{1D4AE}-\u{1D4B9}\u{1D4BB}\u{1D4BD}-\u{1D4C3}\u{1D4C5}-\u{1D505}\u{1D507}-\u{1D50A}\u{1D50D}-\u{1D514}\u{1D516}-\u{1D51C}\u{1D51E}-\u{1D539}\u{1D53B}-\u{1D53E}\u{1D540}-\u{1D544}\u{1D546}\u{1D54A}-\u{1D550}\u{1D552}-\u{1D6A5}\u{1D6A8}-\u{1D6C0}\u{1D6C2}-\u{1D6DA}\u{1D6DC}-\u{1D6FA}\u{1D6FC}-\u{1D714}\u{1D716}-\u{1D734}\u{1D736}-\u{1D74E}\u{1D750}-\u{1D76E}\u{1D770}-\u{1D788}\u{1D78A}-\u{1D7A8}\u{1D7AA}-\u{1D7C2}\u{1D7C4}-\u{1D7CB}\u{1DF00}-\u{1DF1E}\u{1E100}-\u{1E12C}\u{1E137}-\u{1E13D}\u{1E14E}\u{1E290}-\u{1E2AD}\u{1E2C0}-\u{1E2EB}\u{1E7E0}-\u{1E7E6}\u{1E7E8}-\u{1E7EB}\u{1E7ED}\u{1E7EE}\u{1E7F0}-\u{1E7FE}\u{1E800}-\u{1E8C4}\u{1E900}-\u{1E943}\u{1E94B}\u{1EE00}-\u{1EE03}\u{1EE05}-\u{1EE1F}\u{1EE21}\u{1EE22}\u{1EE24}\u{1EE27}\u{1EE29}-\u{1EE32}\u{1EE34}-\u{1EE37}\u{1EE39}\u{1EE3B}\u{1EE42}\u{1EE47}\u{1EE49}\u{1EE4B}\u{1EE4D}-\u{1EE4F}\u{1EE51}\u{1EE52}\u{1EE54}\u{1EE57}\u{1EE59}\u{1EE5B}\u{1EE5D}\u{1EE5F}\u{1EE61}\u{1EE62}\u{1EE64}\u{1EE67}-\u{1EE6A}\u{1EE6C}-\u{1EE72}\u{1EE74}-\u{1EE77}\u{1EE79}-\u{1EE7C}\u{1EE7E}\u{1EE80}-\u{1EE89}\u{1EE8B}-\u{1EE9B}\u{1EEA1}-\u{1EEA3}\u{1EEA5}-\u{1EEA9}\u{1EEAB}-\u{1EEBB}\u{20000}-\u{2A6DF}\u{2A700}-\u{2B738}\u{2B740}-\u{2B81D}\u{2B820}-\u{2CEA1}\u{2CEB0}-\u{2EBE0}\u{2F800}-\u{2FA1D}\u{30000}-\u{3134A}]*)/giu -function n(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"ms" -var i=null -return t=(t+"").replace(/(\d)[,_](\d)/g,"$1$2"),t.replace(e,(function(t,e,n){(n=r(n))&&(i=(i||0)+parseFloat(e,10)*n)})),i&&i/(r(n)||1)}function r(t){return n[t]||n[t.toLowerCase().replace(/s$/,"")]}t.exports=n,t.exports.default=n,n.nanosecond=n.ns=1e-6,n["µs"]=n["μs"]=n.us=n.microsecond=.001,n.millisecond=n.ms=n[""]=1,n.second=n.sec=n.s=1e3*n.ms,n.minute=n.min=n.m=60*n.s,n.hour=n.hr=n.h=60*n.m,n.day=n.d=24*n.h,n.week=n.wk=n.w=7*n.d,n.month=n.b=30.4375*n.d,n.year=n.yr=n.y=365.25*n.d},2610:t=>{"use strict" -t.exports=t=>{if("number"!=typeof t)throw new TypeError("Expected a number") -const e=t>0?Math.floor:Math.ceil -return{days:e(t/864e5),hours:e(t/36e5)%24,minutes:e(t/6e4)%60,seconds:e(t/1e3)%60,milliseconds:e(t)%1e3,microseconds:e(1e3*t)%1e3,nanoseconds:e(1e6*t)%1e3}}},3385:(t,e,n)=>{"use strict" -const r=n(2610),i=(t,e)=>1===e?t:`${t}s` -t.exports=function(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -if(!Number.isFinite(t))throw new TypeError("Expected a finite number") -e.colonNotation&&(e.compact=!1,e.formatSubMilliseconds=!1,e.separateMilliseconds=!1,e.verbose=!1),e.compact&&(e.secondsDecimalDigits=0,e.millisecondsDecimalDigits=0) -const n=[],o=(t,e)=>{const n=Math.floor(t*10**e+1e-7) -return(Math.round(n)/10**e).toFixed(e)},a=(t,r,o,a)=>{if(!(0!==n.length&&e.colonNotation||0!==t||e.colonNotation&&"m"===o))return -let u,c -if(a=(a||t||"0").toString(),e.colonNotation){u=n.length>0?":":"",c="" -const t=a.includes(".")?a.split(".")[0].length:a.length,e=n.length>0?2:1 -a="0".repeat(Math.max(0,e-t))+a}else u="",c=e.verbose?" "+i(r,t):o -n.push(u+a+c)},u=r(t) -if(a(Math.trunc(u.days/365),"year","y"),a(u.days%365,"day","d"),a(u.hours,"hour","h"),a(u.minutes,"minute","m"),e.separateMilliseconds||e.formatSubMilliseconds||!e.colonNotation&&t<1e3)if(a(u.seconds,"second","s"),e.formatSubMilliseconds)a(u.milliseconds,"millisecond","ms"),a(u.microseconds,"microsecond","µs"),a(u.nanoseconds,"nanosecond","ns") -else{const t=u.milliseconds+u.microseconds/1e3+u.nanoseconds/1e6,n="number"==typeof e.millisecondsDecimalDigits?e.millisecondsDecimalDigits:0,r=t>=1?Math.round(t):Math.ceil(t),i=n?t.toFixed(n):r -a(Number.parseFloat(i,10),"millisecond","ms",i)}else{const n=o(t/1e3%60,"number"==typeof e.secondsDecimalDigits?e.secondsDecimalDigits:1),r=e.keepDecimalsOnWholeSeconds?n:n.replace(/\.0+$/,"") -a(Number.parseFloat(r,10),"second","s",r)}if(0===n.length)return"0"+(e.verbose?" milliseconds":"ms") -if(e.compact)return n[0] -if("number"==typeof e.unitCount){const t=e.colonNotation?"":" " -return n.slice(0,Math.max(e.unitCount,1)).join(t)}return e.colonNotation?n.join(""):n.join(" ")}},7114:(t,e,n)=>{"use strict" -var r -n.r(e),n.d(e,{default:()=>i}) -const i=function(){function t(){this.pool=[],this.flush()}return t.prototype.flush=function(){var t=this -r=window.requestAnimationFrame((function(){var e=t.pool -t.reset(),e.forEach((function(t){t[Object.keys(t)[0]]()})),t.flush()}))},t.prototype.add=function(t,e){var n -return this.pool.push(((n={})[t]=e,n)),e},t.prototype.remove=function(t){this.pool=this.pool.filter((function(e){return!e[t]}))},t.prototype.reset=function(){this.pool=[]},t.prototype.stop=function(){window.cancelAnimationFrame(r)},t}()},1499:(t,e,n)=>{"use strict" -function r(t){var e=t.getBoundingClientRect() -return{width:e.width,height:e.height,top:e.top,right:e.right,bottom:e.bottom,left:e.left,x:e.left,y:e.top}}function i(t){if(null==t)return window -if("[object Window]"!==t.toString()){var e=t.ownerDocument -return e&&e.defaultView||window}return t}function o(t){var e=i(t) -return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function a(t){return t instanceof i(t).Element||t instanceof Element}function u(t){return t instanceof i(t).HTMLElement||t instanceof HTMLElement}function c(t){return"undefined"!=typeof ShadowRoot&&(t instanceof i(t).ShadowRoot||t instanceof ShadowRoot)}function s(t){return t?(t.nodeName||"").toLowerCase():null}function f(t){return((a(t)?t.ownerDocument:t.document)||window.document).documentElement}function l(t){return r(f(t)).left+o(t).scrollLeft}function h(t){return i(t).getComputedStyle(t)}function d(t){var e=h(t),n=e.overflow,r=e.overflowX,i=e.overflowY -return/auto|scroll|overlay|hidden/.test(n+i+r)}function p(t,e,n){void 0===n&&(n=!1) -var a,c,h=f(e),p=r(t),y=u(e),b={scrollLeft:0,scrollTop:0},v={x:0,y:0} -return(y||!y&&!n)&&(("body"!==s(e)||d(h))&&(b=(a=e)!==i(a)&&u(a)?{scrollLeft:(c=a).scrollLeft,scrollTop:c.scrollTop}:o(a)),u(e)?((v=r(e)).x+=e.clientLeft,v.y+=e.clientTop):h&&(v.x=l(h))),{x:p.left+b.scrollLeft-v.x,y:p.top+b.scrollTop-v.y,width:p.width,height:p.height}}function y(t){var e=r(t),n=t.offsetWidth,i=t.offsetHeight -return Math.abs(e.width-n)<=1&&(n=e.width),Math.abs(e.height-i)<=1&&(i=e.height),{x:t.offsetLeft,y:t.offsetTop,width:n,height:i}}function b(t){return"html"===s(t)?t:t.assignedSlot||t.parentNode||(c(t)?t.host:null)||f(t)}function v(t){return["html","body","#document"].indexOf(s(t))>=0?t.ownerDocument.body:u(t)&&d(t)?t:v(b(t))}function g(t,e){var n -void 0===e&&(e=[]) -var r=v(t),o=r===(null==(n=t.ownerDocument)?void 0:n.body),a=i(r),u=o?[a].concat(a.visualViewport||[],d(r)?r:[]):r,c=e.concat(u) -return o?c:c.concat(g(b(u)))}function m(t){return["table","td","th"].indexOf(s(t))>=0}function _(t){return u(t)&&"fixed"!==h(t).position?t.offsetParent:null}function w(t){for(var e=i(t),n=_(t);n&&m(n)&&"static"===h(n).position;)n=_(n) -return n&&("html"===s(n)||"body"===s(n)&&"static"===h(n).position)?e:n||function(t){for(var e=-1!==navigator.userAgent.toLowerCase().indexOf("firefox"),n=b(t);u(n)&&["html","body"].indexOf(s(n))<0;){var r=h(n) -if("none"!==r.transform||"none"!==r.perspective||"paint"===r.contain||-1!==["transform","perspective"].indexOf(r.willChange)||e&&"filter"===r.willChange||e&&r.filter&&"none"!==r.filter)return n -n=n.parentNode}return null}(t)||e}n.r(e),n.d(e,{animateFill:()=>oe,createSingleton:()=>ne,default:()=>de,delegate:()=>ie,followCursor:()=>se,hideAll:()=>te,inlinePositioning:()=>fe,roundArrow:()=>lt,sticky:()=>le}) -var x="top",A="bottom",E="right",k="left",D="auto",C=[x,A,E,k],O="start",S="end",M="viewport",F="popper",T=C.reduce((function(t,e){return t.concat([e+"-"+O,e+"-"+S])}),[]),B=[].concat(C,[D]).reduce((function(t,e){return t.concat([e,e+"-"+O,e+"-"+S])}),[]),P=["beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite"] -function j(t){var e=new Map,n=new Set,r=[] -function i(t){n.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!n.has(t)){var r=e.get(t) -r&&i(r)}})),r.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){n.has(t.name)||i(t)})),r}var N={placement:"bottom",modifiers:[],strategy:"absolute"} -function R(){for(var t=arguments.length,e=new Array(t),n=0;n=0?"x":"y"}function Z(t){var e,n=t.reference,r=t.element,i=t.placement,o=i?$(i):null,a=i?U(i):null,u=n.x+n.width/2-r.width/2,c=n.y+n.height/2-r.height/2 -switch(o){case x:e={x:u,y:n.y-r.height} -break -case A:e={x:u,y:n.y+n.height} -break -case E:e={x:n.x+n.width,y:c} -break -case k:e={x:n.x-r.width,y:c} -break -default:e={x:n.x,y:n.y}}var s=o?z(o):null -if(null!=s){var f="y"===s?"height":"width" -switch(a){case O:e[s]=e[s]-(n[f]/2-r[f]/2) -break -case S:e[s]=e[s]+(n[f]/2-r[f]/2)}}return e}const q={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,n=t.name -e.modifiersData[n]=Z({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}} -var V=Math.max,H=Math.min,Y=Math.round,G={top:"auto",right:"auto",bottom:"auto",left:"auto"} -function K(t){var e,n=t.popper,r=t.popperRect,o=t.placement,a=t.offsets,u=t.position,c=t.gpuAcceleration,s=t.adaptive,l=t.roundOffsets,d=!0===l?function(t){var e=t.x,n=t.y,r=window.devicePixelRatio||1 -return{x:Y(Y(e*r)/r)||0,y:Y(Y(n*r)/r)||0}}(a):"function"==typeof l?l(a):a,p=d.x,y=void 0===p?0:p,b=d.y,v=void 0===b?0:b,g=a.hasOwnProperty("x"),m=a.hasOwnProperty("y"),_=k,D=x,C=window -if(s){var O=w(n),S="clientHeight",M="clientWidth" -O===i(n)&&"static"!==h(O=f(n)).position&&(S="scrollHeight",M="scrollWidth"),o===x&&(D=A,v-=O[S]-r.height,v*=c?1:-1),o===k&&(_=E,y-=O[M]-r.width,y*=c?1:-1)}var F,T=Object.assign({position:u},s&&G) -return c?Object.assign({},T,((F={})[D]=m?"0":"",F[_]=g?"0":"",F.transform=(C.devicePixelRatio||1)<2?"translate("+y+"px, "+v+"px)":"translate3d("+y+"px, "+v+"px, 0)",F)):Object.assign({},T,((e={})[D]=m?v+"px":"",e[_]=g?y+"px":"",e.transform="",e))}const W={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state -Object.keys(e.elements).forEach((function(t){var n=e.styles[t]||{},r=e.attributes[t]||{},i=e.elements[t] -u(i)&&s(i)&&(Object.assign(i.style,n),Object.keys(r).forEach((function(t){var e=r[t] -!1===e?i.removeAttribute(t):i.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,n={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}} -return Object.assign(e.elements.popper.style,n.popper),e.styles=n,e.elements.arrow&&Object.assign(e.elements.arrow.style,n.arrow),function(){Object.keys(e.elements).forEach((function(t){var r=e.elements[t],i=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:n[t]).reduce((function(t,e){return t[e]="",t}),{}) -u(r)&&s(r)&&(Object.assign(r.style,o),Object.keys(i).forEach((function(t){r.removeAttribute(t)})))}))}},requires:["computeStyles"]} -var X={left:"right",right:"left",bottom:"top",top:"bottom"} -function J(t){return t.replace(/left|right|bottom|top/g,(function(t){return X[t]}))}var Q={start:"end",end:"start"} -function tt(t){return t.replace(/start|end/g,(function(t){return Q[t]}))}function et(t,e){var n=e.getRootNode&&e.getRootNode() -if(t.contains(e))return!0 -if(n&&c(n)){var r=e -do{if(r&&t.isSameNode(r))return!0 -r=r.parentNode||r.host}while(r)}return!1}function nt(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function rt(t,e){return e===M?nt(function(t){var e=i(t),n=f(t),r=e.visualViewport,o=n.clientWidth,a=n.clientHeight,u=0,c=0 -return r&&(o=r.width,a=r.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(u=r.offsetLeft,c=r.offsetTop)),{width:o,height:a,x:u+l(t),y:c}}(t)):u(e)?function(t){var e=r(t) -return e.top=e.top+t.clientTop,e.left=e.left+t.clientLeft,e.bottom=e.top+t.clientHeight,e.right=e.left+t.clientWidth,e.width=t.clientWidth,e.height=t.clientHeight,e.x=e.left,e.y=e.top,e}(e):nt(function(t){var e,n=f(t),r=o(t),i=null==(e=t.ownerDocument)?void 0:e.body,a=V(n.scrollWidth,n.clientWidth,i?i.scrollWidth:0,i?i.clientWidth:0),u=V(n.scrollHeight,n.clientHeight,i?i.scrollHeight:0,i?i.clientHeight:0),c=-r.scrollLeft+l(t),s=-r.scrollTop -return"rtl"===h(i||n).direction&&(c+=V(n.clientWidth,i?i.clientWidth:0)-a),{width:a,height:u,x:c,y:s}}(f(t)))}function it(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function ot(t,e){return e.reduce((function(e,n){return e[n]=t,e}),{})}function at(t,e){void 0===e&&(e={}) -var n=e,i=n.placement,o=void 0===i?t.placement:i,c=n.boundary,l=void 0===c?"clippingParents":c,d=n.rootBoundary,p=void 0===d?M:d,y=n.elementContext,v=void 0===y?F:y,m=n.altBoundary,_=void 0!==m&&m,k=n.padding,D=void 0===k?0:k,O=it("number"!=typeof D?D:ot(D,C)),S=v===F?"reference":F,T=t.elements.reference,B=t.rects.popper,P=t.elements[_?S:v],j=function(t,e,n){var r="clippingParents"===e?function(t){var e=g(b(t)),n=["absolute","fixed"].indexOf(h(t).position)>=0&&u(t)?w(t):t -return a(n)?e.filter((function(t){return a(t)&&et(t,n)&&"body"!==s(t)})):[]}(t):[].concat(e),i=[].concat(r,[n]),o=i[0],c=i.reduce((function(e,n){var r=rt(t,n) -return e.top=V(r.top,e.top),e.right=H(r.right,e.right),e.bottom=H(r.bottom,e.bottom),e.left=V(r.left,e.left),e}),rt(t,o)) -return c.width=c.right-c.left,c.height=c.bottom-c.top,c.x=c.left,c.y=c.top,c}(a(P)?P:P.contextElement||f(t.elements.popper),l,p),N=r(T),R=Z({reference:N,element:B,strategy:"absolute",placement:o}),L=nt(Object.assign({},B,R)),I=v===F?L:N,$={top:j.top-I.top+O.top,bottom:I.bottom-j.bottom+O.bottom,left:j.left-I.left+O.left,right:I.right-j.right+O.right},U=t.modifiersData.offset -if(v===F&&U){var z=U[o] -Object.keys($).forEach((function(t){var e=[E,A].indexOf(t)>=0?1:-1,n=[x,A].indexOf(t)>=0?"y":"x" -$[t]+=z[n]*e}))}return $}function ut(t,e,n){return V(t,H(e,n))}function ct(t,e,n){return void 0===n&&(n={x:0,y:0}),{top:t.top-e.height-n.y,right:t.right-e.width+n.x,bottom:t.bottom-e.height+n.y,left:t.left-e.width-n.x}}function st(t){return[x,E,A,k].some((function(e){return t[e]>=0}))}var ft=function(t){void 0===t&&(t={}) -var e=t,n=e.defaultModifiers,r=void 0===n?[]:n,i=e.defaultOptions,o=void 0===i?N:i -return function(t,e,n){void 0===n&&(n=o) -var i,u,c={placement:"bottom",orderedModifiers:[],options:Object.assign({},N,o),modifiersData:{},elements:{reference:t,popper:e},attributes:{},styles:{}},s=[],f=!1,l={state:c,setOptions:function(n){h(),c.options=Object.assign({},o,c.options,n),c.scrollParents={reference:a(t)?g(t):t.contextElement?g(t.contextElement):[],popper:g(e)} -var i,u,f=function(t){var e=j(t) -return P.reduce((function(t,n){return t.concat(e.filter((function(t){return t.phase===n})))}),[])}((i=[].concat(r,c.options.modifiers),u=i.reduce((function(t,e){var n=t[e.name] -return t[e.name]=n?Object.assign({},n,e,{options:Object.assign({},n.options,e.options),data:Object.assign({},n.data,e.data)}):e,t}),{}),Object.keys(u).map((function(t){return u[t]})))) -return c.orderedModifiers=f.filter((function(t){return t.enabled})),c.orderedModifiers.forEach((function(t){var e=t.name,n=t.options,r=void 0===n?{}:n,i=t.effect -if("function"==typeof i){var o=i({state:c,name:e,instance:l,options:r}) -s.push(o||function(){})}})),l.update()},forceUpdate:function(){if(!f){var t=c.elements,e=t.reference,n=t.popper -if(R(e,n)){c.rects={reference:p(e,w(n),"fixed"===c.options.strategy),popper:y(n)},c.reset=!1,c.placement=c.options.placement,c.orderedModifiers.forEach((function(t){return c.modifiersData[t.name]=Object.assign({},t.data)})) -for(var r=0;r=0?-1:1,o="function"==typeof n?n(Object.assign({},e,{placement:t})):n,a=o[0],u=o[1] -return a=a||0,u=(u||0)*i,[k,E].indexOf(r)>=0?{x:u,y:a}:{x:a,y:u}}(n,e.rects,o),t}),{}),u=a[e.placement],c=u.x,s=u.y -null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=c,e.modifiersData.popperOffsets.y+=s),e.modifiersData[r]=a}},{name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,n=t.options,r=t.name -if(!e.modifiersData[r]._skip){for(var i=n.mainAxis,o=void 0===i||i,a=n.altAxis,u=void 0===a||a,c=n.fallbackPlacements,s=n.padding,f=n.boundary,l=n.rootBoundary,h=n.altBoundary,d=n.flipVariations,p=void 0===d||d,y=n.allowedAutoPlacements,b=e.options.placement,v=$(b),g=c||(v!==b&&p?function(t){if($(t)===D)return[] -var e=J(t) -return[tt(t),e,tt(e)]}(b):[J(b)]),m=[b].concat(g).reduce((function(t,n){return t.concat($(n)===D?function(t,e){void 0===e&&(e={}) -var n=e,r=n.placement,i=n.boundary,o=n.rootBoundary,a=n.padding,u=n.flipVariations,c=n.allowedAutoPlacements,s=void 0===c?B:c,f=U(r),l=f?u?T:T.filter((function(t){return U(t)===f})):C,h=l.filter((function(t){return s.indexOf(t)>=0})) -0===h.length&&(h=l) -var d=h.reduce((function(e,n){return e[n]=at(t,{placement:n,boundary:i,rootBoundary:o,padding:a})[$(n)],e}),{}) -return Object.keys(d).sort((function(t,e){return d[t]-d[e]}))}(e,{placement:n,boundary:f,rootBoundary:l,padding:s,flipVariations:p,allowedAutoPlacements:y}):n)}),[]),_=e.rects.reference,w=e.rects.popper,S=new Map,M=!0,F=m[0],P=0;P=0,I=L?"width":"height",z=at(e,{placement:j,boundary:f,rootBoundary:l,altBoundary:h,padding:s}),Z=L?R?E:k:R?A:x -_[I]>w[I]&&(Z=J(Z)) -var q=J(Z),V=[] -if(o&&V.push(z[N]<=0),u&&V.push(z[Z]<=0,z[q]<=0),V.every((function(t){return t}))){F=j,M=!1 -break}S.set(j,V)}if(M)for(var H=function(t){var e=m.find((function(e){var n=S.get(e) -if(n)return n.slice(0,t).every((function(t){return t}))})) -if(e)return F=e,"break"},Y=p?3:1;Y>0&&"break"!==H(Y);Y--);e.placement!==F&&(e.modifiersData[r]._skip=!0,e.placement=F,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}},{name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,n=t.options,r=t.name,i=n.mainAxis,o=void 0===i||i,a=n.altAxis,u=void 0!==a&&a,c=n.boundary,s=n.rootBoundary,f=n.altBoundary,l=n.padding,h=n.tether,d=void 0===h||h,p=n.tetherOffset,b=void 0===p?0:p,v=at(e,{boundary:c,rootBoundary:s,padding:l,altBoundary:f}),g=$(e.placement),m=U(e.placement),_=!m,D=z(g),C="x"===D?"y":"x",S=e.modifiersData.popperOffsets,M=e.rects.reference,F=e.rects.popper,T="function"==typeof b?b(Object.assign({},e.rects,{placement:e.placement})):b,B={x:0,y:0} -if(S){if(o||u){var P="y"===D?x:k,j="y"===D?A:E,N="y"===D?"height":"width",R=S[D],L=S[D]+v[P],I=S[D]-v[j],Z=d?-F[N]/2:0,q=m===O?M[N]:F[N],Y=m===O?-F[N]:-M[N],G=e.elements.arrow,K=d&&G?y(G):{width:0,height:0},W=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},X=W[P],J=W[j],Q=ut(0,M[N],K[N]),tt=_?M[N]/2-Z-Q-X-T:q-Q-X-T,et=_?-M[N]/2+Z+Q+J+T:Y+Q+J+T,nt=e.elements.arrow&&w(e.elements.arrow),rt=nt?"y"===D?nt.clientTop||0:nt.clientLeft||0:0,it=e.modifiersData.offset?e.modifiersData.offset[e.placement][D]:0,ot=S[D]+tt-it-rt,ct=S[D]+et-it -if(o){var st=ut(d?H(L,ot):L,R,d?V(I,ct):I) -S[D]=st,B[D]=st-R}if(u){var ft="x"===D?x:k,lt="x"===D?A:E,ht=S[C],dt=ht+v[ft],pt=ht-v[lt],yt=ut(d?H(dt,ot):dt,ht,d?V(pt,ct):pt) -S[C]=yt,B[C]=yt-ht}}e.modifiersData[r]=B}},requiresIfExists:["offset"]},{name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,n=t.state,r=t.name,i=t.options,o=n.elements.arrow,a=n.modifiersData.popperOffsets,u=$(n.placement),c=z(u),s=[k,E].indexOf(u)>=0?"height":"width" -if(o&&a){var f=function(t,e){return it("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:ot(t,C))}(i.padding,n),l=y(o),h="y"===c?x:k,d="y"===c?A:E,p=n.rects.reference[s]+n.rects.reference[c]-a[c]-n.rects.popper[s],b=a[c]-n.rects.reference[c],v=w(o),g=v?"y"===c?v.clientHeight||0:v.clientWidth||0:0,m=p/2-b/2,_=f[h],D=g-l[s]-f[d],O=g/2-l[s]/2+m,S=ut(_,O,D),M=c -n.modifiersData[r]=((e={})[M]=S,e.centerOffset=S-O,e)}},effect:function(t){var e=t.state,n=t.options.element,r=void 0===n?"[data-popper-arrow]":n -null!=r&&("string"!=typeof r||(r=e.elements.popper.querySelector(r)))&&et(e.elements.popper,r)&&(e.elements.arrow=r)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]},{name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,n=t.name,r=e.rects.reference,i=e.rects.popper,o=e.modifiersData.preventOverflow,a=at(e,{elementContext:"reference"}),u=at(e,{altBoundary:!0}),c=ct(a,r),s=ct(u,i,o),f=st(c),l=st(s) -e.modifiersData[n]={referenceClippingOffsets:c,popperEscapeOffsets:s,isReferenceHidden:f,hasPopperEscaped:l},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":f,"data-popper-escaped":l})}}]}),lt='',ht="tippy-content",dt="tippy-backdrop",pt="tippy-arrow",yt="tippy-svg-arrow",bt={passive:!0,capture:!0} -function vt(t,e,n){if(Array.isArray(t)){var r=t[e] -return null==r?Array.isArray(n)?n[e]:n:r}return t}function gt(t,e){var n={}.toString.call(t) -return 0===n.indexOf("[object")&&n.indexOf(e+"]")>-1}function mt(t,e){return"function"==typeof t?t.apply(void 0,e):t}function _t(t,e){return 0===e?t:function(r){clearTimeout(n),n=setTimeout((function(){t(r)}),e)} -var n}function wt(t,e){var n=Object.assign({},t) -return e.forEach((function(t){delete n[t]})),n}function xt(t){return[].concat(t)}function At(t,e){-1===t.indexOf(e)&&t.push(e)}function Et(t){return t.split("-")[0]}function kt(t){return[].slice.call(t)}function Dt(){return document.createElement("div")}function Ct(t){return["Element","Fragment"].some((function(e){return gt(t,e)}))}function Ot(t){return gt(t,"MouseEvent")}function St(t){return!(!t||!t._tippy||t._tippy.reference!==t)}function Mt(t,e){t.forEach((function(t){t&&(t.style.transitionDuration=e+"ms")}))}function Ft(t,e){t.forEach((function(t){t&&t.setAttribute("data-state",e)}))}function Tt(t){var e,n=xt(t)[0] -return(null==n||null==(e=n.ownerDocument)?void 0:e.body)?n.ownerDocument:document}function Bt(t,e,n){var r=e+"EventListener";["transitionend","webkitTransitionEnd"].forEach((function(e){t[r](e,n)}))}var Pt={isTouch:!1},jt=0 -function Nt(){Pt.isTouch||(Pt.isTouch=!0,window.performance&&document.addEventListener("mousemove",Rt))}function Rt(){var t=performance.now() -t-jt<20&&(Pt.isTouch=!1,document.removeEventListener("mousemove",Rt)),jt=t}function Lt(){var t=document.activeElement -if(St(t)){var e=t._tippy -t.blur&&!e.state.isVisible&&t.blur()}}var It="undefined"!=typeof window&&"undefined"!=typeof document?navigator.userAgent:"",$t=/MSIE |Trident\//.test(It),Ut=Object.assign({appendTo:function(){return document.body},aria:{content:"auto",expanded:"auto"},delay:0,duration:[300,250],getReferenceClientRect:null,hideOnClick:!0,ignoreAttributes:!1,interactive:!1,interactiveBorder:2,interactiveDebounce:0,moveTransition:"",offset:[0,10],onAfterUpdate:function(){},onBeforeUpdate:function(){},onCreate:function(){},onDestroy:function(){},onHidden:function(){},onHide:function(){},onMount:function(){},onShow:function(){},onShown:function(){},onTrigger:function(){},onUntrigger:function(){},onClickOutside:function(){},placement:"top",plugins:[],popperOptions:{},render:null,showOnCreate:!1,touch:!0,trigger:"mouseenter focus",triggerTarget:null},{animateFill:!1,followCursor:!1,inlinePositioning:!1,sticky:!1},{},{allowHTML:!1,animation:"fade",arrow:!0,content:"",inertia:!1,maxWidth:350,role:"tooltip",theme:"",zIndex:9999}),zt=Object.keys(Ut) -function Zt(t){var e=(t.plugins||[]).reduce((function(e,n){var r=n.name,i=n.defaultValue -return r&&(e[r]=void 0!==t[r]?t[r]:i),e}),{}) -return Object.assign({},t,{},e)}function qt(t,e){var n=Object.assign({},e,{content:mt(e.content,[t])},e.ignoreAttributes?{}:function(t,e){return(e?Object.keys(Zt(Object.assign({},Ut,{plugins:e}))):zt).reduce((function(e,n){var r=(t.getAttribute("data-tippy-"+n)||"").trim() -if(!r)return e -if("content"===n)e[n]=r -else try{e[n]=JSON.parse(r)}catch(t){e[n]=r}return e}),{})}(t,e.plugins)) -return n.aria=Object.assign({},Ut.aria,{},n.aria),n.aria={expanded:"auto"===n.aria.expanded?e.interactive:n.aria.expanded,content:"auto"===n.aria.content?e.interactive?null:"describedby":n.aria.content},n}function Vt(t,e){t.innerHTML=e}function Ht(t){var e=Dt() -return!0===t?e.className=pt:(e.className=yt,Ct(t)?e.appendChild(t):Vt(e,t)),e}function Yt(t,e){Ct(e.content)?(Vt(t,""),t.appendChild(e.content)):"function"!=typeof e.content&&(e.allowHTML?Vt(t,e.content):t.textContent=e.content)}function Gt(t){var e=t.firstElementChild,n=kt(e.children) -return{box:e,content:n.find((function(t){return t.classList.contains(ht)})),arrow:n.find((function(t){return t.classList.contains(pt)||t.classList.contains(yt)})),backdrop:n.find((function(t){return t.classList.contains(dt)}))}}function Kt(t){var e=Dt(),n=Dt() -n.className="tippy-box",n.setAttribute("data-state","hidden"),n.setAttribute("tabindex","-1") -var r=Dt() -function i(n,r){var i=Gt(e),o=i.box,a=i.content,u=i.arrow -r.theme?o.setAttribute("data-theme",r.theme):o.removeAttribute("data-theme"),"string"==typeof r.animation?o.setAttribute("data-animation",r.animation):o.removeAttribute("data-animation"),r.inertia?o.setAttribute("data-inertia",""):o.removeAttribute("data-inertia"),o.style.maxWidth="number"==typeof r.maxWidth?r.maxWidth+"px":r.maxWidth,r.role?o.setAttribute("role",r.role):o.removeAttribute("role"),n.content===r.content&&n.allowHTML===r.allowHTML||Yt(a,t.props),r.arrow?u?n.arrow!==r.arrow&&(o.removeChild(u),o.appendChild(Ht(r.arrow))):o.appendChild(Ht(r.arrow)):u&&o.removeChild(u)}return r.className=ht,r.setAttribute("data-state","hidden"),Yt(r,t.props),e.appendChild(n),n.appendChild(r),i(t.props,t.props),{popper:e,onUpdate:i}}Kt.$$tippy=!0 -var Wt=1,Xt=[],Jt=[] -function Qt(t,e){void 0===e&&(e={}) -var n=Ut.plugins.concat(e.plugins||[]) -document.addEventListener("touchstart",Nt,bt),window.addEventListener("blur",Lt) -var r,i=Object.assign({},e,{plugins:n}),o=(r=t,Ct(r)?[r]:function(t){return gt(t,"NodeList")}(r)?kt(r):Array.isArray(r)?r:kt(document.querySelectorAll(r))).reduce((function(t,e){var n=e&&function(t,e){var n,r,i,o,a,u,c,s,f,l=qt(t,Object.assign({},Ut,{},Zt((n=e,Object.keys(n).reduce((function(t,e){return void 0!==n[e]&&(t[e]=n[e]),t}),{}))))),h=!1,d=!1,p=!1,y=!1,b=[],v=_t(G,l.interactiveDebounce),g=Wt++,m=(f=l.plugins).filter((function(t,e){return f.indexOf(t)===e})),_={id:g,reference:t,popper:Dt(),popperInstance:null,props:l,state:{isEnabled:!0,isVisible:!1,isDestroyed:!1,isMounted:!1,isShown:!1},plugins:m,clearDelayTimeouts:function(){clearTimeout(r),clearTimeout(i),cancelAnimationFrame(o)},setProps:function(e){if(!_.state.isDestroyed){P("onBeforeUpdate",[_,e]),H() -var n=_.props,r=qt(t,Object.assign({},_.props,{},e,{ignoreAttributes:!0})) -_.props=r,V(),n.interactiveDebounce!==r.interactiveDebounce&&(R(),v=_t(G,r.interactiveDebounce)),n.triggerTarget&&!r.triggerTarget?xt(n.triggerTarget).forEach((function(t){t.removeAttribute("aria-expanded")})):r.triggerTarget&&t.removeAttribute("aria-expanded"),N(),B(),A&&A(n,r),_.popperInstance&&(J(),tt().forEach((function(t){requestAnimationFrame(t._tippy.popperInstance.forceUpdate)}))),P("onAfterUpdate",[_,e])}},setContent:function(t){_.setProps({content:t})},show:function(){var t=_.state.isVisible,e=_.state.isDestroyed,n=!_.state.isEnabled,r=Pt.isTouch&&!_.props.touch,i=vt(_.props.duration,0,Ut.duration) -if(!(t||e||n||r||S().hasAttribute("disabled")||(P("onShow",[_],!1),!1===_.props.onShow(_)))){if(_.state.isVisible=!0,O()&&(x.style.visibility="visible"),B(),U(),_.state.isMounted||(x.style.transition="none"),O()){var o=F() -Mt([o.box,o.content],0)}var a,u,s -c=function(){var t -if(_.state.isVisible&&!y){if(y=!0,x.offsetHeight,x.style.transition=_.props.moveTransition,O()&&_.props.animation){var e=F(),n=e.box,r=e.content -Mt([n,r],i),Ft([n,r],"visible")}j(),N(),At(Jt,_),null==(t=_.popperInstance)||t.forceUpdate(),_.state.isMounted=!0,P("onMount",[_]),_.props.animation&&O()&&function(t,e){Z(t,(function(){_.state.isShown=!0,P("onShown",[_])}))}(i)}},u=_.props.appendTo,s=S(),(a=_.props.interactive&&u===Ut.appendTo||"parent"===u?s.parentNode:mt(u,[s])).contains(x)||a.appendChild(x),J()}},hide:function(){var t=!_.state.isVisible,e=_.state.isDestroyed,n=!_.state.isEnabled,r=vt(_.props.duration,1,Ut.duration) -if(!(t||e||n)&&(P("onHide",[_],!1),!1!==_.props.onHide(_))){if(_.state.isVisible=!1,_.state.isShown=!1,y=!1,h=!1,O()&&(x.style.visibility="hidden"),R(),z(),B(),O()){var i=F(),o=i.box,a=i.content -_.props.animation&&(Mt([o,a],r),Ft([o,a],"hidden"))}j(),N(),_.props.animation?O()&&function(t,e){Z(t,(function(){!_.state.isVisible&&x.parentNode&&x.parentNode.contains(x)&&e()}))}(r,_.unmount):_.unmount()}},hideWithInteractivity:function(t){M().addEventListener("mousemove",v),At(Xt,v),v(t)},enable:function(){_.state.isEnabled=!0},disable:function(){_.hide(),_.state.isEnabled=!1},unmount:function(){_.state.isVisible&&_.hide(),_.state.isMounted&&(Q(),tt().forEach((function(t){t._tippy.unmount()})),x.parentNode&&x.parentNode.removeChild(x),Jt=Jt.filter((function(t){return t!==_})),_.state.isMounted=!1,P("onHidden",[_]))},destroy:function(){_.state.isDestroyed||(_.clearDelayTimeouts(),_.unmount(),H(),delete t._tippy,_.state.isDestroyed=!0,P("onDestroy",[_]))}} -if(!l.render)return _ -var w=l.render(_),x=w.popper,A=w.onUpdate -x.setAttribute("data-tippy-root",""),x.id="tippy-"+_.id,_.popper=x,t._tippy=_,x._tippy=_ -var E=m.map((function(t){return t.fn(_)})),k=t.hasAttribute("aria-expanded") -return V(),N(),B(),P("onCreate",[_]),l.showOnCreate&&et(),x.addEventListener("mouseenter",(function(){_.props.interactive&&_.state.isVisible&&_.clearDelayTimeouts()})),x.addEventListener("mouseleave",(function(t){_.props.interactive&&_.props.trigger.indexOf("mouseenter")>=0&&(M().addEventListener("mousemove",v),v(t))})),_ -function D(){var t=_.props.touch -return Array.isArray(t)?t:[t,0]}function C(){return"hold"===D()[0]}function O(){var t -return!!(null==(t=_.props.render)?void 0:t.$$tippy)}function S(){return s||t}function M(){var t=S().parentNode -return t?Tt(t):document}function F(){return Gt(x)}function T(t){return _.state.isMounted&&!_.state.isVisible||Pt.isTouch||a&&"focus"===a.type?0:vt(_.props.delay,t?0:1,Ut.delay)}function B(){x.style.pointerEvents=_.props.interactive&&_.state.isVisible?"":"none",x.style.zIndex=""+_.props.zIndex}function P(t,e,n){var r -void 0===n&&(n=!0),E.forEach((function(n){n[t]&&n[t].apply(void 0,e)})),n&&(r=_.props)[t].apply(r,e)}function j(){var e=_.props.aria -if(e.content){var n="aria-"+e.content,r=x.id -xt(_.props.triggerTarget||t).forEach((function(t){var e=t.getAttribute(n) -if(_.state.isVisible)t.setAttribute(n,e?e+" "+r:r) -else{var i=e&&e.replace(r,"").trim() -i?t.setAttribute(n,i):t.removeAttribute(n)}}))}}function N(){!k&&_.props.aria.expanded&&xt(_.props.triggerTarget||t).forEach((function(t){_.props.interactive?t.setAttribute("aria-expanded",_.state.isVisible&&t===S()?"true":"false"):t.removeAttribute("aria-expanded")}))}function R(){M().removeEventListener("mousemove",v),Xt=Xt.filter((function(t){return t!==v}))}function L(t){if(!(Pt.isTouch&&(p||"mousedown"===t.type)||_.props.interactive&&x.contains(t.target))){if(S().contains(t.target)){if(Pt.isTouch)return -if(_.state.isVisible&&_.props.trigger.indexOf("click")>=0)return}else P("onClickOutside",[_,t]) -!0===_.props.hideOnClick&&(_.clearDelayTimeouts(),_.hide(),d=!0,setTimeout((function(){d=!1})),_.state.isMounted||z())}}function I(){p=!0}function $(){p=!1}function U(){var t=M() -t.addEventListener("mousedown",L,!0),t.addEventListener("touchend",L,bt),t.addEventListener("touchstart",$,bt),t.addEventListener("touchmove",I,bt)}function z(){var t=M() -t.removeEventListener("mousedown",L,!0),t.removeEventListener("touchend",L,bt),t.removeEventListener("touchstart",$,bt),t.removeEventListener("touchmove",I,bt)}function Z(t,e){var n=F().box -function r(t){t.target===n&&(Bt(n,"remove",r),e())}if(0===t)return e() -Bt(n,"remove",u),Bt(n,"add",r),u=r}function q(e,n,r){void 0===r&&(r=!1),xt(_.props.triggerTarget||t).forEach((function(t){t.addEventListener(e,n,r),b.push({node:t,eventType:e,handler:n,options:r})}))}function V(){var t -C()&&(q("touchstart",Y,{passive:!0}),q("touchend",K,{passive:!0})),(t=_.props.trigger,t.split(/\s+/).filter(Boolean)).forEach((function(t){if("manual"!==t)switch(q(t,Y),t){case"mouseenter":q("mouseleave",K) -break -case"focus":q($t?"focusout":"blur",W) -break -case"focusin":q("focusout",W)}}))}function H(){b.forEach((function(t){var e=t.node,n=t.eventType,r=t.handler,i=t.options -e.removeEventListener(n,r,i)})),b=[]}function Y(t){var e,n=!1 -if(_.state.isEnabled&&!X(t)&&!d){var r="focus"===(null==(e=a)?void 0:e.type) -a=t,s=t.currentTarget,N(),!_.state.isVisible&&Ot(t)&&Xt.forEach((function(e){return e(t)})),"click"===t.type&&(_.props.trigger.indexOf("mouseenter")<0||h)&&!1!==_.props.hideOnClick&&_.state.isVisible?n=!0:et(t),"click"===t.type&&(h=!n),n&&!r&&nt(t)}}function G(t){var e=t.target,n=S().contains(e)||x.contains(e) -if("mousemove"!==t.type||!n){var r=tt().concat(x).map((function(t){var e,n=null==(e=t._tippy.popperInstance)?void 0:e.state -return n?{popperRect:t.getBoundingClientRect(),popperState:n,props:l}:null})).filter(Boolean);(function(t,e){var n=e.clientX,r=e.clientY -return t.every((function(t){var e=t.popperRect,i=t.popperState,o=t.props.interactiveBorder,a=Et(i.placement),u=i.modifiersData.offset -if(!u)return!0 -var c="bottom"===a?u.top.y:0,s="top"===a?u.bottom.y:0,f="right"===a?u.left.x:0,l="left"===a?u.right.x:0,h=e.top-r+c>o,d=r-e.bottom-s>o,p=e.left-n+f>o,y=n-e.right-l>o -return h||d||p||y}))})(r,t)&&(R(),nt(t))}}function K(t){X(t)||_.props.trigger.indexOf("click")>=0&&h||(_.props.interactive?_.hideWithInteractivity(t):nt(t))}function W(t){_.props.trigger.indexOf("focusin")<0&&t.target!==S()||_.props.interactive&&t.relatedTarget&&x.contains(t.relatedTarget)||nt(t)}function X(t){return!!Pt.isTouch&&C()!==t.type.indexOf("touch")>=0}function J(){Q() -var e=_.props,n=e.popperOptions,r=e.placement,i=e.offset,o=e.getReferenceClientRect,a=e.moveTransition,u=O()?Gt(x).arrow:null,s=o?{getBoundingClientRect:o,contextElement:o.contextElement||S()}:t,f=[{name:"offset",options:{offset:i}},{name:"preventOverflow",options:{padding:{top:2,bottom:2,left:5,right:5}}},{name:"flip",options:{padding:5}},{name:"computeStyles",options:{adaptive:!a}},{name:"$$tippy",enabled:!0,phase:"beforeWrite",requires:["computeStyles"],fn:function(t){var e=t.state -if(O()){var n=F().box;["placement","reference-hidden","escaped"].forEach((function(t){"placement"===t?n.setAttribute("data-placement",e.placement):e.attributes.popper["data-popper-"+t]?n.setAttribute("data-"+t,""):n.removeAttribute("data-"+t)})),e.attributes.popper={}}}}] -O()&&u&&f.push({name:"arrow",options:{element:u,padding:3}}),f.push.apply(f,(null==n?void 0:n.modifiers)||[]),_.popperInstance=ft(s,x,Object.assign({},n,{placement:r,onFirstUpdate:c,modifiers:f}))}function Q(){_.popperInstance&&(_.popperInstance.destroy(),_.popperInstance=null)}function tt(){return kt(x.querySelectorAll("[data-tippy-root]"))}function et(t){_.clearDelayTimeouts(),t&&P("onTrigger",[_,t]),U() -var e=T(!0),n=D(),i=n[0],o=n[1] -Pt.isTouch&&"hold"===i&&o&&(e=o),e?r=setTimeout((function(){_.show()}),e):_.show()}function nt(t){if(_.clearDelayTimeouts(),P("onUntrigger",[_,t]),_.state.isVisible){if(!(_.props.trigger.indexOf("mouseenter")>=0&&_.props.trigger.indexOf("click")>=0&&["mouseleave","mousemove"].indexOf(t.type)>=0&&h)){var e=T(!1) -e?i=setTimeout((function(){_.state.isVisible&&_.hide()}),e):o=requestAnimationFrame((function(){_.hide()}))}}else z()}}(e,i) -return n&&t.push(n),t}),[]) -return Ct(t)?o[0]:o}Qt.defaultProps=Ut,Qt.setDefaultProps=function(t){Object.keys(t).forEach((function(e){Ut[e]=t[e]}))},Qt.currentInput=Pt -var te=function(t){var e=void 0===t?{}:t,n=e.exclude,r=e.duration -Jt.forEach((function(t){var e=!1 -if(n&&(e=St(n)?t.reference===n:t.popper===n.popper),!e){var i=t.props.duration -t.setProps({duration:r}),t.hide(),t.state.isDestroyed||t.setProps({duration:i})}}))},ee=Object.assign({},W,{effect:function(t){var e=t.state,n={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}} -Object.assign(e.elements.popper.style,n.popper),e.styles=n,e.elements.arrow&&Object.assign(e.elements.arrow.style,n.arrow)}}),ne=function(t,e){var n -void 0===e&&(e={}) -var r,i=t,o=[],a=e.overrides,u=[],c=!1 -function s(){o=i.map((function(t){return t.reference}))}function f(t){i.forEach((function(e){t?e.enable():e.disable()}))}function l(t){return i.map((function(e){var n=e.setProps -return e.setProps=function(i){n(i),e.reference===r&&t.setProps(i)},function(){e.setProps=n}}))}function h(t,e){var n=o.indexOf(e) -if(e!==r){r=e -var u=(a||[]).concat("content").reduce((function(t,e){return t[e]=i[n].props[e],t}),{}) -t.setProps(Object.assign({},u,{getReferenceClientRect:"function"==typeof u.getReferenceClientRect?u.getReferenceClientRect:function(){return e.getBoundingClientRect()}}))}}f(!1),s() -var d={fn:function(){return{onDestroy:function(){f(!0)},onHidden:function(){r=null},onClickOutside:function(t){t.props.showOnCreate&&!c&&(c=!0,r=null)},onShow:function(t){t.props.showOnCreate&&!c&&(c=!0,h(t,o[0]))},onTrigger:function(t,e){h(t,e.currentTarget)}}}},p=Qt(Dt(),Object.assign({},wt(e,["overrides"]),{plugins:[d].concat(e.plugins||[]),triggerTarget:o,popperOptions:Object.assign({},e.popperOptions,{modifiers:[].concat((null==(n=e.popperOptions)?void 0:n.modifiers)||[],[ee])})})),y=p.show -p.show=function(t){if(y(),!r&&null==t)return h(p,o[0]) -if(!r||null!=t){if("number"==typeof t)return o[t]&&h(p,o[t]) -if(i.includes(t)){var e=t.reference -return h(p,e)}return o.includes(t)?h(p,t):void 0}},p.showNext=function(){var t=o[0] -if(!r)return p.show(0) -var e=o.indexOf(r) -p.show(o[e+1]||t)},p.showPrevious=function(){var t=o[o.length-1] -if(!r)return p.show(t) -var e=o.indexOf(r),n=o[e-1]||t -p.show(n)} -var b=p.setProps -return p.setProps=function(t){a=t.overrides||a,b(t)},p.setInstances=function(t){f(!0),u.forEach((function(t){return t()})),i=t,f(!1),s(),l(p),p.setProps({triggerTarget:o})},u=l(p),p},re={mouseover:"mouseenter",focusin:"focus",click:"click"} -function ie(t,e){var n=[],r=[],i=!1,o=e.target,a=wt(e,["target"]),u=Object.assign({},a,{trigger:"manual",touch:!1}),c=Object.assign({},a,{showOnCreate:!0}),s=Qt(t,u) -function f(t){if(t.target&&!i){var n=t.target.closest(o) -if(n){var a=n.getAttribute("data-tippy-trigger")||e.trigger||Ut.trigger -if(!n._tippy&&!("touchstart"===t.type&&"boolean"==typeof c.touch||"touchstart"!==t.type&&a.indexOf(re[t.type])<0)){var u=Qt(n,c) -u&&(r=r.concat(u))}}}}function l(t,e,r,i){void 0===i&&(i=!1),t.addEventListener(e,r,i),n.push({node:t,eventType:e,handler:r,options:i})}return xt(s).forEach((function(t){var e=t.destroy,o=t.enable,a=t.disable -t.destroy=function(t){void 0===t&&(t=!0),t&&r.forEach((function(t){t.destroy()})),r=[],n.forEach((function(t){var e=t.node,n=t.eventType,r=t.handler,i=t.options -e.removeEventListener(n,r,i)})),n=[],e()},t.enable=function(){o(),r.forEach((function(t){return t.enable()})),i=!1},t.disable=function(){a(),r.forEach((function(t){return t.disable()})),i=!0},function(t){var e=t.reference -l(e,"touchstart",f,bt),l(e,"mouseover",f),l(e,"focusin",f),l(e,"click",f)}(t)})),s}var oe={name:"animateFill",defaultValue:!1,fn:function(t){var e -if(!(null==(e=t.props.render)?void 0:e.$$tippy))return{} -var n=Gt(t.popper),r=n.box,i=n.content,o=t.props.animateFill?function(){var t=Dt() -return t.className=dt,Ft([t],"hidden"),t}():null -return{onCreate:function(){o&&(r.insertBefore(o,r.firstElementChild),r.setAttribute("data-animatefill",""),r.style.overflow="hidden",t.setProps({arrow:!1,animation:"shift-away"}))},onMount:function(){if(o){var t=r.style.transitionDuration,e=Number(t.replace("ms","")) -i.style.transitionDelay=Math.round(e/10)+"ms",o.style.transitionDuration=t,Ft([o],"visible")}},onShow:function(){o&&(o.style.transitionDuration="0ms")},onHide:function(){o&&Ft([o],"hidden")}}}},ae={clientX:0,clientY:0},ue=[] -function ce(t){var e=t.clientX,n=t.clientY -ae={clientX:e,clientY:n}}var se={name:"followCursor",defaultValue:!1,fn:function(t){var e=t.reference,n=Tt(t.props.triggerTarget||e),r=!1,i=!1,o=!0,a=t.props -function u(){return"initial"===t.props.followCursor&&t.state.isVisible}function c(){n.addEventListener("mousemove",l)}function s(){n.removeEventListener("mousemove",l)}function f(){r=!0,t.setProps({getReferenceClientRect:null}),r=!1}function l(n){var r=!n.target||e.contains(n.target),i=t.props.followCursor,o=n.clientX,a=n.clientY,u=e.getBoundingClientRect(),c=o-u.left,s=a-u.top -!r&&t.props.interactive||t.setProps({getReferenceClientRect:function(){var t=e.getBoundingClientRect(),n=o,r=a -"initial"===i&&(n=t.left+c,r=t.top+s) -var u="horizontal"===i?t.top:r,f="vertical"===i?t.right:n,l="horizontal"===i?t.bottom:r,h="vertical"===i?t.left:n -return{width:f-h,height:l-u,top:u,right:f,bottom:l,left:h}}})}function h(){t.props.followCursor&&(ue.push({instance:t,doc:n}),function(t){t.addEventListener("mousemove",ce)}(n))}function d(){0===(ue=ue.filter((function(e){return e.instance!==t}))).filter((function(t){return t.doc===n})).length&&function(t){t.removeEventListener("mousemove",ce)}(n)}return{onCreate:h,onDestroy:d,onBeforeUpdate:function(){a=t.props},onAfterUpdate:function(e,n){var o=n.followCursor -r||void 0!==o&&a.followCursor!==o&&(d(),o?(h(),!t.state.isMounted||i||u()||c()):(s(),f()))},onMount:function(){t.props.followCursor&&!i&&(o&&(l(ae),o=!1),u()||c())},onTrigger:function(t,e){Ot(e)&&(ae={clientX:e.clientX,clientY:e.clientY}),i="focus"===e.type},onHidden:function(){t.props.followCursor&&(f(),s(),o=!0)}}}},fe={name:"inlinePositioning",defaultValue:!1,fn:function(t){var e,n=t.reference,r=-1,i=!1,o={name:"tippyInlinePositioning",enabled:!0,phase:"afterWrite",fn:function(i){var o=i.state -t.props.inlinePositioning&&(e!==o.placement&&t.setProps({getReferenceClientRect:function(){return function(t){return function(t,e,n,r){if(n.length<2||null===t)return e -if(2===n.length&&r>=0&&n[0].left>n[1].right)return n[r]||e -switch(t){case"top":case"bottom":var i=n[0],o=n[n.length-1],a="top"===t,u=i.top,c=o.bottom,s=a?i.left:o.left,f=a?i.right:o.right -return{top:u,bottom:c,left:s,right:f,width:f-s,height:c-u} -case"left":case"right":var l=Math.min.apply(Math,n.map((function(t){return t.left}))),h=Math.max.apply(Math,n.map((function(t){return t.right}))),d=n.filter((function(e){return"left"===t?e.left===l:e.right===h})),p=d[0].top,y=d[d.length-1].bottom -return{top:p,bottom:y,left:l,right:h,width:h-l,height:y-p} -default:return e}}(Et(t),n.getBoundingClientRect(),kt(n.getClientRects()),r)}(o.placement)}}),e=o.placement)}} -function a(){var e -i||(e=function(t,e){var n -return{popperOptions:Object.assign({},t.popperOptions,{modifiers:[].concat(((null==(n=t.popperOptions)?void 0:n.modifiers)||[]).filter((function(t){return t.name!==e.name})),[e])})}}(t.props,o),i=!0,t.setProps(e),i=!1)}return{onCreate:a,onAfterUpdate:a,onTrigger:function(e,n){if(Ot(n)){var i=kt(t.reference.getClientRects()),o=i.find((function(t){return t.left-2<=n.clientX&&t.right+2>=n.clientX&&t.top-2<=n.clientY&&t.bottom+2>=n.clientY})) -r=i.indexOf(o)}},onUntrigger:function(){r=-1}}}},le={name:"sticky",defaultValue:!1,fn:function(t){var e=t.reference,n=t.popper -function r(e){return!0===t.props.sticky||t.props.sticky===e}var i=null,o=null -function a(){var u=r("reference")?(t.popperInstance?t.popperInstance.state.elements.reference:e).getBoundingClientRect():null,c=r("popper")?n.getBoundingClientRect():null;(u&&he(i,u)||c&&he(o,c))&&t.popperInstance&&t.popperInstance.update(),i=u,o=c,t.state.isMounted&&requestAnimationFrame(a)}return{onMount:function(){t.props.sticky&&a()}}}} -function he(t,e){return!t||!e||t.top!==e.top||t.right!==e.right||t.bottom!==e.bottom||t.left!==e.left}Qt.setDefaultProps({render:Kt}) -const de=Qt},2247:(t,e,n)=>{"use strict" -n.d(e,{ZT:()=>i,ev:()=>a,pi:()=>o}) -var r=function(t,e){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},r(t,e)} -function i(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null") -function n(){this.constructor=t}r(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}var o=function(){return o=Object.assign||function(t){for(var e,n=1,r=arguments.length;n{"use strict" -function r(t){return null!==t&&"object"==typeof t&&!(t instanceof Date||t instanceof RegExp)&&!Array.isArray(t)}n.r(e),n.d(e,{BufferedChangeset:()=>vt,CHANGESET:()=>F,Change:()=>o,Changeset:()=>_t,Err:()=>c,ValidatedChangeset:()=>mt,buildOldValues:()=>q,changeset:()=>gt,getChangeValue:()=>u,getDeep:()=>y,getKeyValues:()=>l,isChange:()=>a,isChangeset:()=>T,isObject:()=>r,isPromise:()=>d,keyInObject:()=>B,lookupValidator:()=>b,mergeDeep:()=>J,mergeNested:()=>Z,normalizeObject:()=>E,objectWithout:()=>rt,propertyIsUnsafe:()=>K,pureAssign:()=>D,setDeep:()=>U,take:()=>it}) -var i=Symbol("__value__"),o=function(t){this[i]=t},a=function(t){return r(t)&&i in t} -function u(t){if(a(t))return t[i]}var c=function(t,e){this.value=t,this.validation=e},s=function(t,e){var n="function"==typeof Symbol&&t[Symbol.iterator] -if(!n)return t -var r,i,o=n.call(t),a=[] -try{for(;(void 0===e||e-- >0)&&!(r=o.next()).done;)a.push(r.value)}catch(t){i={error:t}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return a},f=function(){for(var t=[],e=0;e0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0 -continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0)&&!(r=o.next()).done;)a.push(r.value)}catch(t){i={error:t}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return a},g=function(){for(var t=[],e=0;e=t.length&&(t=void 0),{value:t&&t[r++],done:!t}}} -throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")},A=function(){return A=Object.assign||function(t){for(var e,n=1,r=arguments.length;n0)&&!(r=o.next()).done;)a.push(r.value)}catch(t){i={error:t}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return a},O=function(){for(var t=[],e=0;e=t.length&&(t=void 0),{value:t&&t[r++],done:!t}}} -throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}(n),c=u.next();!c.done;c=u.next()){var s=c.value,f=t[s] -"function"==typeof f.validate?e[s]=f:r(f)?S(f,e,Object.keys(f),O(i,[s])):("function"==typeof f||Array.isArray(f)&&f.every((function(t){return"function"==typeof t||"function"==typeof t.validate})))&&(e[O(i,[s]).join(".")]=f)}}catch(t){o={error:t}}finally{try{c&&!c.done&&(a=u.return)&&a.call(u)}finally{if(o)throw o.error}}return e}function M(t){return t?S(t,{},Object.keys(t)):{}}var F="__CHANGESET__" -function T(t){return t&&t.__changeset__===F}function B(t,e){var n=function(t,e){var n="function"==typeof Symbol&&t[Symbol.iterator] -if(!n)return t -var r,i,o=n.call(t),a=[] -try{for(;(void 0===e||e-- >0)&&!(r=o.next()).done;)a.push(r.value)}catch(t){i={error:t}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return a}(e.split(".")),r=n[0],i=n.slice(1) -if(!r||!(r in t))return!1 -if(!i.length)return r in t -var o=t[r] -return null!==o&&"object"==typeof o&&B(t[r],i.join("."))}var P=function(t,e){var n="function"==typeof Symbol&&t[Symbol.iterator] -if(!n)return t -var r,i,o=n.call(t),a=[] -try{for(;(void 0===e||e-- >0)&&!(r=o.next()).done;)a.push(r.value)}catch(t){i={error:t}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return a} -function j(t){return!!t&&Object.keys(t).every((function(t){return Number.isInteger(parseInt(t,10))}))}function N(t){return t.reduce((function(t,e,n){return t[n]=e,t}),{})}function R(t){var e,n,r=[] -try{for(var i=function(t){var e="function"==typeof Symbol&&Symbol.iterator,n=e&&t[e],r=0 -if(n)return n.call(t) -if(t&&"number"==typeof t.length)return{next:function(){return t&&r>=t.length&&(t=void 0),{value:t&&t[r++],done:!t}}} -throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}(Object.entries(t)),o=i.next();!o.done;o=i.next()){var a=P(o.value,2),u=a[0],c=a[1] -r[parseInt(u,10)]=c}}catch(t){e={error:t}}finally{try{o&&!o.done&&(n=i.return)&&n.call(i)}finally{if(e)throw e.error}}return r}var L=function(){return L=Object.assign||function(t){for(var e,n=1,r=arguments.length;n0)&&!(r=o.next()).done;)a.push(r.value)}catch(t){i={error:t}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return a}(e.slice(-1),1)[0],r=Object.keys(t).filter((function(t){return t!==n})).reduce((function(e,n){return e[n]=t[n],e}),Object.create(null)) -return L({},r)}function $(t){return"__proto__"!==t&&"constructor"!==t&&"prototype"!==t}function U(t,e,n,i){void 0===i&&(i={safeSet:void 0,safeGet:void 0}) -var c=function(t){return t.split(".")}(e).filter($),s=t -if(i.safeSet=i.safeSet||function(t,e,n){return t[e]=n},i.safeGet=i.safeGet||function(t,e){return t?t[e]:t},1===c.length)return i.safeSet(t,e,n),t -for(var f=0;f=t.length&&(t=void 0),{value:t&&t[r++],done:!t}}} -throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}(e),u=a.next();!u.done;u=a.next()){var c=u.value -o[c.key]=n(t,c.key)}}catch(t){r={error:t}}finally{try{u&&!u.done&&(i=a.return)&&i.call(a)}finally{if(r)throw r.error}}return o}var V=function(t,e){var n="function"==typeof Symbol&&t[Symbol.iterator] -if(!n)return t -var r,i,o=n.call(t),a=[] -try{for(;(void 0===e||e-- >0)&&!(r=o.next()).done;)a.push(r.value)}catch(t){i={error:t}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return a},H=function(){for(var t=[],e=0;e0)for(r in i){var o=i[r] -n.safeSet(t,r,o)}}}else{if(!G(t,r)||!function(t){return!!t&&"object"==typeof t}(s=e[r])||function(t){var e=Object.prototype.toString.call(t) -return"[object RegExp]"===e||"[object Date]"===e}(s)||a(e[r])){var c=e[r] -return c&&a(c)?n.safeSet(t,r,u(c)):n.safeSet(t,r,E(c))}n.safeSet(t,r,J(n.safeGet(t,r),n.safeGet(e,r),n))}var s})),t}function J(t,e,n){void 0===n&&(n={safeGet:void 0,safeSet:void 0,propertyIsUnsafe:void 0,getKeys:void 0}),n.getKeys=n.getKeys||Y,n.propertyIsUnsafe=n.propertyIsUnsafe||K,n.safeGet=n.safeGet||function(t,e){return t[e]},n.safeSet=n.safeSet||function(t,e,n){return t[e]=n} -var r=Array.isArray(e),i=Array.isArray(t) -if(r===i)return r||null==t?e:X(t,e,n) -var o=j(e) -return i&&o?R(X(N(t),e,n)):e}var Q=function(){return Q=Object.assign||function(t){for(var e,n=1,r=arguments.length;n0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0 -continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0)&&!(r=o.next()).done;)a.push(r.value)}catch(t){i={error:t}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return a},st=function(){for(var t=[],e=0;e0)||r.find((function(e){return t.match(e)}))){var i=this._content,o=this.safeGet(i,t) -if(n.skipValidate)return this._setProperty({key:t,value:e,oldValue:o}),void this._handleValidation(!0,{key:t,value:e}) -this._setProperty({key:t,value:e,oldValue:o}),this._validateKey(t,e)}},Object.defineProperty(t.prototype,Symbol.toStringTag,{get:function(){return"changeset:"+D(this._content,{}).toString()},enumerable:!1,configurable:!0}),t.prototype.toString=function(){return"changeset:"+D(this._content,{}).toString()},t.prototype.prepare=function(t){var e=t(this._bareChanges) -if(this.isObject(e),this.isObject(e)){var n=ft(e).reduce((function(t,n){return t[n]=new o(e[n]),t}),{}) -this._changes=n}return this},t.prototype.execute=function(){var t -if(this.isValid&&this.isDirty){var e=this._content,n=this._changes -t=q(e,this.changes,this.getDeep),this._content=this.mergeDeep(e,n)}return this.trigger("execute"),this._changes={},this._previousContent=t,this},t.prototype.unexecute=function(){return this._previousContent&&(this._content=this.mergeDeep(this._content,this._previousContent,{safeGet:this.safeGet,safeSet:this.safeSet})),this},t.prototype.save=function(t){return at(this,void 0,void 0,(function(){var e,n,r,i -return ut(this,(function(o){switch(o.label){case 0:e=this._content,n=Promise.resolve(this),this.execute(),"function"==typeof e.save?n=e.save(t):"function"==typeof this.safeGet(e,"save")&&(r=this.maybeUnwrapProxy(e).save())&&(n=r),o.label=1 -case 1:return o.trys.push([1,3,,4]),[4,n] -case 2:return i=o.sent(),this.rollback(),[2,i] -case 3:throw o.sent() -case 4:return[2]}}))}))},t.prototype.merge=function(t){var e=this._content -if(T(t),t._content,this.isPristine&&t.isPristine)return this -var n=this._changes,r=t._changes,i=this._errors,o=t._errors,a=new mt(e,this._validator),u=rt(ft(r),i),c=rt(ft(o),n),s=Z(u,o),f=Z(c,r) -return a._errors=s,a._changes=f,a._notifyVirtualProperties(),a},t.prototype.rollback=function(){var t=this._rollbackKeys() -return this._changes={},this._errors={},this._errorsCache={},this._notifyVirtualProperties(t),this.trigger("afterRollback"),this},t.prototype.rollbackInvalid=function(t){var e=this,n=ft(this._errors) -return t?(this._notifyVirtualProperties([t]),this._errors=this._deleteKey(ht,t),this._errorsCache=this._errors,n.indexOf(t)>-1&&(this._changes=this._deleteKey(lt,t))):(this._notifyVirtualProperties(),this._errors={},this._errorsCache=this._errors,n.forEach((function(t){e._changes=e._deleteKey(lt,t)}))),this},t.prototype.rollbackProperty=function(t){return this._changes=this._deleteKey(lt,t),this._errors=this._deleteKey(ht,t),this._errorsCache=this._errors,this},t.prototype.validate=function(){for(var t=[],e=0;e0?t:ft(M(this.validationMap)),e=t.map((function(t){var e=n[t],r=e instanceof nt?e.unwrap():e -return n._validateKey(t,r)})),[2,Promise.all(e)]):[2,Promise.resolve(null)]}))}))},t.prototype.addError=function(t,e){var n,r=this -if(function(t){return r.isObject(t)&&!Array.isArray(t)}(e))e.hasOwnProperty("value")||e.value,e.hasOwnProperty("validation"),n=new c(e.value,e.validation) -else{var i=this[t] -n=new c(i,e)}var o=this._errors -return this._errors=this.setDeep(o,t,n,{safeSet:this.safeSet}),this._errorsCache=this._errors,e},t.prototype.pushErrors=function(t){for(var e=[],n=1;n0},t.prototype._validateKey=function(t,e){var n=this,r=this._content,i=this.getDeep(r,t),o=this._validate(t,e,i) -if(this.trigger("beforeValidation",t),d(o)){this._setIsValidating(t,o) -var a=this._runningValidations,u=Object.entries(a) -return Promise.all(u).then((function(){return o.then((function(r){return delete a[t],n._handleValidation(r,{key:t,value:e})})).then((function(e){return n.trigger(dt,t),e}))}))}var c=this._handleValidation(o,{key:t,value:e}) -return this.trigger(dt,t),c},t.prototype._handleValidation=function(t,e){var n=e.key,r=e.value,i=!0===t||Array.isArray(t)&&1===t.length&&!0===t[0] -return this._errors=this._deleteKey("_errorsCache",n),i?r:this.addError(n,{value:r,validation:t})},t.prototype._validate=function(t,e,n){var r=this._validator,i=this._content -if("function"==typeof r){var o=r({key:t,newValue:e,oldValue:n,changes:this.change,content:i}) -return void 0===o||o}return!0},t.prototype._setProperty=function(t){var e,n,r=t.key,i=t.value,a=t.oldValue,u=this._changes -if(n=a,((e=i)instanceof Date&&n instanceof Date?e.getTime()===n.getTime():e===n)&&void 0!==a)B(u,r)&&(this._changes=this._deleteKey(lt,r)) -else{var c=this.setDeep(u,r,new o(i),{safeSet:this.safeSet}) -this._changes=c}},t.prototype._setIsValidating=function(t,e){var n=this._runningValidations -this.setDeep(n,t,e)},t.prototype._notifyVirtualProperties=function(t){return t||(t=this._rollbackKeys()),t},t.prototype._rollbackKeys=function(){var t=this._changes,e=this._errors -return st(new Set(st(ft(t),ft(e))))},t.prototype._deleteKey=function(t,e){void 0===e&&(e="") -var n=this[t],r=e.split(".") -if(1===r.length&&n.hasOwnProperty(e))delete n[e] -else if(n[r[0]])for(var i=ct(r),o=i[0],u=i.slice(1),c=n,s=n[o],f=o;this.isObject(s)&&f;){var l=s;(a(l)||void 0!==l.value||l.validation)&&delete c[f],c=s,(f=u.shift())&&(s=s[f])}return n},t.prototype.get=function(t){var e=ct(t.split(".")),n=e[0],i=e.slice(1),o=this._changes,c=this._content -if(Object.prototype.hasOwnProperty.call(o,n)){var s=this.getDeep(o,t) -if(!this.isObject(s)&&void 0!==s)return s}if(Object.prototype.hasOwnProperty.call(o,n)&&k(o)){var f=o[n],l=E(f) -if(this.isObject(l)){var h=this.maybeUnwrapProxy(this.getDeep(l,i.join("."))) -if(void 0===h&&function(t,e,n){var r,i -if(a(t))return!1 -var o=e.split("."),u=t -try{for(var c=x(o),s=c.next();!s.done;s=c.next()){var f=s.value -if(!u)return!1 -if(o[o.length-1]!==f&&a(n(u,f)))return!0 -u=n(u,f)}}catch(t){r={error:t}}finally{try{s&&!s.done&&(i=c.return)&&i.call(c)}finally{if(r)throw r.error}}return!1}(o,t,this.safeGet)&&!function(t,e,n){var r,i,o=e.split("."),c=t -try{for(var s=x(o),f=s.next();!f.done;f=s.next()){var l=f.value -if(!c||!Object.prototype.hasOwnProperty.call(c,l))return!1 -c=n(c,l),a(c)&&(c=u(c))}}catch(t){r={error:t}}finally{try{f&&!f.done&&(i=s.return)&&i.call(s)}finally{if(r)throw r.error}}return!0}(o,t,this.safeGet)&&this.getDeep(c,t))return -if(this.isObject(h)){if(a(h))return u(h) -var d=this.safeGet(c,n)||{},p=this.getDeep(d,i.join(".")),y=function(t,e){var n=t -if(-1===e.indexOf("."))return n[e] -for(var r="string"==typeof e?e.split("."):e,i=0;i{var r=n(260),i=n(8806) -t.exports=function t(e){if(!(this instanceof t))return new t(e) -var n=(e||"").replace(/^\//,""),o=i() -return a._trie=o,a.on=function(t,e){if(r.equal(typeof t,"string"),r.equal(typeof e,"function"),t=t||"/",e._wayfarer&&e._trie)o.mount(t,e._trie.trie) -else{var n=o.create(t) -n.cb=e,n.route=t}return a},a.emit=a,a.match=u,a._wayfarer=!0,a -function a(t){var e=u(t),n=new Array(arguments.length) -n[0]=e.params -for(var r=1;r{var r=n(260) -function i(){if(!(this instanceof i))return new i -this.trie={nodes:{}}}function o(t,e){return Object.prototype.hasOwnProperty.call(t,e)}t.exports=i,i.prototype.create=function(t){r.equal(typeof t,"string","route should be a string") -var e=t.replace(/^\//,"").split("/") -return function t(n,r){var i=o(e,n)&&e[n] -if(!1===i)return r -var a=null -return/^:|^\*/.test(i)?(o(r.nodes,"$$")?a=r.nodes.$$:(a={nodes:{}},r.nodes.$$=a),"*"===i[0]&&(r.wildcard=!0),r.name=i.replace(/^:|^\*/,"")):o(r.nodes,i)?a=r.nodes[i]:(a={nodes:{}},r.nodes[i]=a),t(n+1,a)}(0,this.trie)},i.prototype.match=function(t){r.equal(typeof t,"string","route should be a string") -var e=t.replace(/^\//,"").split("/"),n={},i=function t(r,i){if(void 0!==i){var a=e[r] -if(void 0===a)return i -if(o(i.nodes,a))return t(r+1,i.nodes[a]) -if(i.name){try{n[i.name]=decodeURIComponent(a)}catch(e){return t(r,void 0)}return t(r+1,i.nodes.$$)}if(i.wildcard){try{n.wildcard=decodeURIComponent(e.slice(r).join("/"))}catch(e){return t(r,void 0)}return i.nodes.$$}return t(r+1)}}(0,this.trie) -if(i)return(i=Object.assign({},i)).params=n,i},i.prototype.mount=function(t,e){r.equal(typeof t,"string","route should be a string"),r.equal(typeof e,"object","trie should be a object") -var n=t.replace(/^\//,"").split("/"),i=null,o=null -if(1===n.length)o=n[0],i=this.create(o) -else{var a=n.join("/") -o=n[0],i=this.create(a)}Object.assign(i.nodes,e.nodes),e.name&&(i.name=e.name),i.nodes[""]&&(Object.keys(i.nodes[""]).forEach((function(t){"nodes"!==t&&(i[t]=i.nodes[""][t])})),Object.assign(i.nodes,i.nodes[""].nodes),delete i.nodes[""].nodes)}},3493:(t,e,n)=>{"use strict" -n.r(e),n.d(e,{CSSResult:()=>a,ReactiveElement:()=>g,adoptStyles:()=>s,css:()=>c,defaultConverter:()=>y,getCompatibleStyle:()=>f,notEqual:()=>b,supportsAdoptingStyleSheets:()=>r,unsafeCSS:()=>u}) -const r=window.ShadowRoot&&(void 0===window.ShadyCSS||window.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,i=Symbol(),o=new Map -class a{constructor(t,e){if(this._$cssResult$=!0,e!==i)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.") -this.cssText=t}get styleSheet(){let t=o.get(this.cssText) -return r&&void 0===t&&(o.set(this.cssText,t=new CSSStyleSheet),t.replaceSync(this.cssText)),t}toString(){return this.cssText}}const u=t=>new a("string"==typeof t?t:t+"",i),c=function(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;re+(t=>{if(!0===t._$cssResult$)return t.cssText -if("number"==typeof t)return t -throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(n)+t[r+1]),t[0]) -return new a(o,i)},s=(t,e)=>{r?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const n=document.createElement("style"),r=window.litNonce -void 0!==r&&n.setAttribute("nonce",r),n.textContent=e.cssText,t.appendChild(n)}))},f=r?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="" -for(const n of t.cssRules)e+=n.cssText -return u(e)})(t):t -var l -const h=window.trustedTypes,d=h?h.emptyScript:"",p=window.reactiveElementPolyfillSupport,y={toAttribute(t,e){switch(e){case Boolean:t=t?d:null -break -case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let n=t -switch(e){case Boolean:n=null!==t -break -case Number:n=null===t?null:Number(t) -break -case Object:case Array:try{n=JSON.parse(t)}catch(t){n=null}}return n}},b=(t,e)=>e!==t&&(e==e||t==t),v={attribute:!0,type:String,converter:y,reflect:!1,hasChanged:b} -class g extends HTMLElement{constructor(){super(),this._$Et=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Ei=null,this.o()}static addInitializer(t){var e -null!==(e=this.l)&&void 0!==e||(this.l=[]),this.l.push(t)}static get observedAttributes(){this.finalize() -const t=[] -return this.elementProperties.forEach(((e,n)=>{const r=this._$Eh(n,e) -void 0!==r&&(this._$Eu.set(r,n),t.push(r))})),t}static createProperty(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:v -if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const n="symbol"==typeof t?Symbol():"__"+t,r=this.getPropertyDescriptor(t,n,e) -void 0!==r&&Object.defineProperty(this.prototype,t,r)}}static getPropertyDescriptor(t,e,n){return{get(){return this[e]},set(r){const i=this[t] -this[e]=r,this.requestUpdate(t,i,n)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||v}static finalize(){if(this.hasOwnProperty("finalized"))return!1 -this.finalized=!0 -const t=Object.getPrototypeOf(this) -if(t.finalize(),this.elementProperties=new Map(t.elementProperties),this._$Eu=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)] -for(const n of e)this.createProperty(n,t[n])}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(t){const e=[] -if(Array.isArray(t)){const n=new Set(t.flat(1/0).reverse()) -for(const t of n)e.unshift(f(t))}else void 0!==t&&e.push(f(t)) -return e}static _$Eh(t,e){const n=e.attribute -return!1===n?void 0:"string"==typeof n?n:"string"==typeof t?t.toLowerCase():void 0}o(){var t -this._$Ep=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Em(),this.requestUpdate(),null===(t=this.constructor.l)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,n;(null!==(e=this._$Eg)&&void 0!==e?e:this._$Eg=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(n=t.hostConnected)||void 0===n||n.call(t))}removeController(t){var e -null===(e=this._$Eg)||void 0===e||e.splice(this._$Eg.indexOf(t)>>>0,1)}_$Em(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Et.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t -const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions) -return s(e,this.constructor.elementStyles),e}connectedCallback(){var t -void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$Eg)||void 0===t||t.forEach((t=>{var e -return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t -null===(t=this._$Eg)||void 0===t||t.forEach((t=>{var e -return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,n){this._$AK(t,n)}_$ES(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:v -var r,i -const o=this.constructor._$Eh(t,n) -if(void 0!==o&&!0===n.reflect){const a=(null!==(i=null===(r=n.converter)||void 0===r?void 0:r.toAttribute)&&void 0!==i?i:y.toAttribute)(e,n.type) -this._$Ei=t,null==a?this.removeAttribute(o):this.setAttribute(o,a),this._$Ei=null}}_$AK(t,e){var n,r,i -const o=this.constructor,a=o._$Eu.get(t) -if(void 0!==a&&this._$Ei!==a){const t=o.getPropertyOptions(a),u=t.converter,c=null!==(i=null!==(r=null===(n=u)||void 0===n?void 0:n.fromAttribute)&&void 0!==r?r:"function"==typeof u?u:null)&&void 0!==i?i:y.fromAttribute -this._$Ei=a,this[a]=c(e,t.type),this._$Ei=null}}requestUpdate(t,e,n){let r=!0 -void 0!==t&&(((n=n||this.constructor.getPropertyOptions(t)).hasChanged||b)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===n.reflect&&this._$Ei!==t&&(void 0===this._$E_&&(this._$E_=new Map),this._$E_.set(t,n))):r=!1),!this.isUpdatePending&&r&&(this._$Ep=this._$EC())}async _$EC(){this.isUpdatePending=!0 -try{await this._$Ep}catch(t){Promise.reject(t)}const t=this.scheduleUpdate() -return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t -if(!this.isUpdatePending)return -this.hasUpdated,this._$Et&&(this._$Et.forEach(((t,e)=>this[e]=t)),this._$Et=void 0) -let e=!1 -const n=this._$AL -try{e=this.shouldUpdate(n),e?(this.willUpdate(n),null===(t=this._$Eg)||void 0===t||t.forEach((t=>{var e -return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(n)):this._$EU()}catch(t){throw e=!1,this._$EU(),t}e&&this._$AE(n)}willUpdate(t){}_$AE(t){var e -null===(e=this._$Eg)||void 0===e||e.forEach((t=>{var e -return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EU(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$Ep}shouldUpdate(t){return!0}update(t){void 0!==this._$E_&&(this._$E_.forEach(((t,e)=>this._$ES(e,this[e],t))),this._$E_=void 0),this._$EU()}updated(t){}firstUpdated(t){}}g.finalized=!0,g.elementProperties=new Map,g.elementStyles=[],g.shadowRootOptions={mode:"open"},null==p||p({ReactiveElement:g}),(null!==(l=globalThis.reactiveElementVersions)&&void 0!==l?l:globalThis.reactiveElementVersions=[]).push("1.2.1")}}]) diff --git a/agent/uiserver/dist/assets/chunk.412.2df22e4bf69d8f15ebdb.js.LICENSE.txt b/agent/uiserver/dist/assets/chunk.412.2df22e4bf69d8f15ebdb.js.LICENSE.txt deleted file mode 100644 index b25e5082df0f..000000000000 --- a/agent/uiserver/dist/assets/chunk.412.2df22e4bf69d8f15ebdb.js.LICENSE.txt +++ /dev/null @@ -1,38 +0,0 @@ -/*! - * clipboard.js v2.0.8 - * https://clipboardjs.com/ - * - * Licensed MIT © Zeno Rocha - */ - -/*! -* focus-trap 6.9.4 -* @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE -*/ - -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -***************************************************************************** */ - -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ - -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ diff --git a/agent/uiserver/dist/assets/chunk.744.60c31f269c98ac39ce46.css b/agent/uiserver/dist/assets/chunk.744.60c31f269c98ac39ce46.css new file mode 100644 index 000000000000..cd2d6bfc876d --- /dev/null +++ b/agent/uiserver/dist/assets/chunk.744.60c31f269c98ac39ce46.css @@ -0,0 +1,39 @@ +dialog { + position: absolute; + left: 0; right: 0; + width: -moz-fit-content; + width: -webkit-fit-content; + width: fit-content; + height: -moz-fit-content; + height: -webkit-fit-content; + height: fit-content; + margin: auto; + border: solid; + padding: 1em; + background: white; + color: black; + display: block; +} + +dialog:not([open]) { + display: none; +} + +dialog + .backdrop { + position: fixed; + top: 0; right: 0; bottom: 0; left: 0; + background: rgba(0,0,0,0.1); +} + +._dialog_overlay { + position: fixed; + top: 0; right: 0; bottom: 0; left: 0; +} + +dialog.fixed { + position: fixed; + top: 50%; + transform: translate(0, -50%); +} + +/*# sourceMappingURL=chunk.744.60c31f269c98ac39ce46.css-a42bd71a0a3384cc22270ac338164b86.map*/ \ No newline at end of file diff --git a/agent/uiserver/dist/assets/chunk.744.c0eb6726020fc4af8d3f.js b/agent/uiserver/dist/assets/chunk.744.60c31f269c98ac39ce46.js similarity index 100% rename from agent/uiserver/dist/assets/chunk.744.c0eb6726020fc4af8d3f.js rename to agent/uiserver/dist/assets/chunk.744.60c31f269c98ac39ce46.js diff --git a/agent/uiserver/dist/assets/chunk.744.c0eb6726020fc4af8d3f.css b/agent/uiserver/dist/assets/chunk.744.c0eb6726020fc4af8d3f.css deleted file mode 100644 index cf28e28e68b5..000000000000 --- a/agent/uiserver/dist/assets/chunk.744.c0eb6726020fc4af8d3f.css +++ /dev/null @@ -1,39 +0,0 @@ -dialog { - position: absolute; - left: 0; right: 0; - width: -moz-fit-content; - width: -webkit-fit-content; - width: fit-content; - height: -moz-fit-content; - height: -webkit-fit-content; - height: fit-content; - margin: auto; - border: solid; - padding: 1em; - background: white; - color: black; - display: block; -} - -dialog:not([open]) { - display: none; -} - -dialog + .backdrop { - position: fixed; - top: 0; right: 0; bottom: 0; left: 0; - background: rgba(0,0,0,0.1); -} - -._dialog_overlay { - position: fixed; - top: 0; right: 0; bottom: 0; left: 0; -} - -dialog.fixed { - position: fixed; - top: 50%; - transform: translate(0, -50%); -} - -/*# sourceMappingURL=chunk.744.c0eb6726020fc4af8d3f.css-e0c9c028789323db3f70d794b7d8bdc8.map*/ \ No newline at end of file diff --git a/agent/uiserver/dist/assets/chunk.778.b0fb1162d11e4184d9d0.js b/agent/uiserver/dist/assets/chunk.778.b0fb1162d11e4184d9d0.js new file mode 100644 index 000000000000..21cb32de7952 --- /dev/null +++ b/agent/uiserver/dist/assets/chunk.778.b0fb1162d11e4184d9d0.js @@ -0,0 +1,913 @@ +/*! For license information please see chunk.778.b0fb1162d11e4184d9d0.js.LICENSE.txt */ +(globalThis.webpackChunk_ember_auto_import_=globalThis.webpackChunk_ember_auto_import_||[]).push([[778],{9542:e=>{var t=Array.isArray +e.exports=function(){if(!arguments.length)return[] +var e=arguments[0] +return t(e)?e:[e]}},9644:e=>{e.exports=function(e){var t=e?e.length:0 +return t?e[t-1]:void 0}},1609:(e,t,n)=>{var r="__lodash_hash_undefined__",i=1/0,o=9007199254740991,s="[object Arguments]",a="[object Function]",u="[object GeneratorFunction]",c="[object Symbol]",l=/^\[object .+?Constructor\]$/,f=/^(?:0|[1-9]\d*)$/,h="object"==typeof n.g&&n.g&&n.g.Object===Object&&n.g,d="object"==typeof self&&self&&self.Object===Object&&self,p=h||d||Function("return this")() +function g(e,t){return!(!e||!e.length)&&function(e,t,n){if(t!=t)return function(e,t,n,r){for(var i=e.length,o=-1;++o-1}function v(e,t){for(var n=-1,r=t.length,i=e.length;++n0&&n(a)?t>1?$(a,t-1,n,r,i):v(i,a):r||(i[i.length]=a)}return i}function Q(e,t){var n,r,i=e.__data__ +return("string"==(r=typeof(n=t))||"number"==r||"symbol"==r||"boolean"==r?"__proto__"!==n:null===n)?i["string"==typeof t?"string":"hash"]:i.map}function G(e,t){var n=function(e,t){return null==e?void 0:e[t]}(e,t) +return function(e){if(!ne(e)||S&&S in e)return!1 +var t=te(e)||function(e){var t=!1 +if(null!=e&&"function"!=typeof e.toString)try{t=!!(e+"")}catch(e){}return t}(e)?N:l +return t.test(function(e){if(null!=e){try{return C.call(e)}catch(e){}try{return e+""}catch(e){}}return""}(e))}(n)?n:void 0}L.prototype.clear=function(){this.__data__=D?D(null):{}},L.prototype.delete=function(e){return this.has(e)&&delete this.__data__[e]},L.prototype.get=function(e){var t=this.__data__ +if(D){var n=t[e] +return n===r?void 0:n}return T.call(t,e)?t[e]:void 0},L.prototype.has=function(e){var t=this.__data__ +return D?void 0!==t[e]:T.call(t,e)},L.prototype.set=function(e,t){return this.__data__[e]=D&&void 0===t?r:t,this},B.prototype.clear=function(){this.__data__=[]},B.prototype.delete=function(e){var t=this.__data__,n=z(t,e) +return!(n<0||(n==t.length-1?t.pop():A.call(t,n,1),0))},B.prototype.get=function(e){var t=this.__data__,n=z(t,e) +return n<0?void 0:t[n][1]},B.prototype.has=function(e){return z(this.__data__,e)>-1},B.prototype.set=function(e,t){var n=this.__data__,r=z(n,e) +return r<0?n.push([e,t]):n[r][1]=t,this},U.prototype.clear=function(){this.__data__={hash:new L,map:new(P||B),string:new L}},U.prototype.delete=function(e){return Q(this,e).delete(e)},U.prototype.get=function(e){return Q(this,e).get(e)},U.prototype.has=function(e){return Q(this,e).has(e)},U.prototype.set=function(e,t){return Q(this,e).set(e,t),this},H.prototype.add=H.prototype.push=function(e){return this.__data__.set(e,r),this},H.prototype.has=function(e){return this.__data__.has(e)} +var Y=I?b(I,Object):ue,W=I?function(e){for(var t=[];e;)v(t,Y(e)),e=O(e) +return t}:ue +function V(e){return K(e)||Z(e)||!!(R&&e&&e[R])}function J(e,t){return!!(t=null==t?o:t)&&("number"==typeof e||f.test(e))&&e>-1&&e%1==0&&e-1&&e%1==0&&e<=o}(e.length)&&!te(e)}function te(e){var t=ne(e)?j.call(e):"" +return t==a||t==u}function ne(e){var t=typeof e +return!!e&&("object"==t||"function"==t)}function re(e){return!!e&&"object"==typeof e}function ie(e){return ee(e)?function(e,t){var n=K(e)||Z(e)?function(e,t){for(var n=-1,r=Array(e);++n=200&&(o=y,s=!1,t=new H(t)) +e:for(;++i{var r +e=n.nmd(e),function(){"use strict" +function i(e){return i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i(e)}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function s(e,t){for(var n=0;ne.length)&&(t=e.length) +for(var n=0,r=new Array(t);n1&&void 0!==arguments[1])||arguments[1],n=t&&A("array",e)?[]:{} +for(var r in e)if(_.call(e,r)){var i=e[r] +n[r]=i===Object(i)?N(i,t):i}return n}function M(e,t){if(e!==Object(e))return e +var n={} +for(var r in t)_.call(t,r)&&_.call(e,r)&&(n[r]=M(e[r],t[r])) +return n}function O(e,t,n){for(var r in t)_.call(t,r)&&(void 0===t[r]?delete e[r]:n&&void 0!==e[r]||(e[r]=t[r])) +return e}function q(e){if(void 0===e)return"undefined" +if(null===e)return"null" +var t=E.call(e).match(/^\[object\s(.*)\]$/),n=t&&t[1] +switch(n){case"Number":return isNaN(e)?"nan":"number" +case"String":case"Boolean":case"Array":case"Set":case"Map":case"Date":case"RegExp":case"Function":case"Symbol":return n.toLowerCase() +default:return i(e)}}function A(e,t){return q(t)===e}function R(e,t){for(var n=e+""+t,r=0,i=0;i0;){if(!Q(arguments[n-1],arguments[n]))return!1 +n--}return!0}var Y={altertitle:!0,collapse:!0,failOnZeroTests:!0,filter:void 0,maxDepth:5,module:void 0,moduleId:void 0,reorder:!0,requireExpects:!1,scrolltop:!0,storage:b,testId:void 0,urlConfig:[],currentModule:{name:"",tests:[],childModules:[],testsRun:0,testsIgnored:0,hooks:{before:[],beforeEach:[],afterEach:[],after:[]}},globalHooks:{},blocking:!0,callbacks:{},modules:[],queue:[],stats:{all:0,bad:0,testCount:0}},W=h&&h.QUnit&&!h.QUnit.version&&h.QUnit.config +W&&O(Y,W),Y.modules.push(Y.currentModule) +var V=function(){function e(e){return'"'+e.toString().replace(/\\/g,"\\\\").replace(/"/g,'\\"')+'"'}function t(e){return e+""}function n(e,t,n){var r=s.separator(),i=s.indent(1) +return t.join&&(t=t.join(","+r+i)),t?[e,i+t,s.indent()+n].join(r):e+n}function r(e,t){if(s.maxDepth&&s.depth>s.maxDepth)return"[object Array]" +this.up() +for(var r=e.length,i=new Array(r);r--;)i[r]=this.parse(e[r],void 0,t) +return this.down(),n("[",i,"]")}var o=/^function (\w+)/,s={parse:function(e,t,n){var r=(n=n||[]).indexOf(e) +if(-1!==r)return"recursion(".concat(r-n.length,")") +t=t||this.typeOf(e) +var o=this.parsers[t],s=i(o) +if("function"===s){n.push(e) +var a=o.call(this,e,n) +return n.pop(),a}return"string"===s?o:"[ERROR: Missing QUnit.dump formatter for type "+t+"]"},typeOf:function(e){var t +return t=null===e?"null":void 0===e?"undefined":A("regexp",e)?"regexp":A("date",e)?"date":A("function",e)?"function":void 0!==e.setInterval&&void 0!==e.document&&void 0===e.nodeType?"window":9===e.nodeType?"document":e.nodeType?"node":function(e){return"[object Array]"===E.call(e)||"number"==typeof e.length&&void 0!==e.item&&(e.length?e.item(0)===e[0]:null===e.item(0)&&void 0===e[0])}(e)?"array":e.constructor===Error.prototype.constructor?"error":i(e),t},separator:function(){return this.multiline?this.HTML?"
    ":"\n":this.HTML?" ":" "},indent:function(e){if(!this.multiline)return"" +var t=this.indentChar +return this.HTML&&(t=t.replace(/\t/g," ").replace(/ /g," ")),new Array(this.depth+(e||0)).join(t)},up:function(e){this.depth+=e||1},down:function(e){this.depth-=e||1},setParser:function(e,t){this.parsers[e]=t},quote:e,literal:t,join:n,depth:1,maxDepth:Y.maxDepth,parsers:{window:"[Window]",document:"[Document]",error:function(e){return'Error("'+e.message+'")'},unknown:"[Unknown]",null:"null",undefined:"undefined",function:function(e){var t="function",r="name"in e?e.name:(o.exec(e)||[])[1] +return r&&(t+=" "+r),n(t=[t+="(",s.parse(e,"functionArgs"),"){"].join(""),s.parse(e,"functionCode"),"}")},array:r,nodelist:r,arguments:r,object:function(e,t){var r=[] +if(s.maxDepth&&s.depth>s.maxDepth)return"[object Object]" +s.up() +var i=[] +for(var o in e)i.push(o) +var a=["message","name"] +for(var u in a){var c=a[u] +c in e&&!j(c,i)&&i.push(c)}i.sort() +for(var l=0;l",r=e.nodeName.toLowerCase(),i=t+r,o=e.attributes +if(o)for(var a=0;a0&&void 0!==arguments[0]?arguments[0]:{passed:0,failed:0,skipped:0,todo:0,total:0} +return e.failed+=this.globalFailureCount,e.total+=this.globalFailureCount,e=this.tests.reduce((function(e,t){return t.valid&&(e[t.getStatus()]++,e.total++),e}),e),this.childSuites.reduce((function(e,t){return t.getTestCounts(e)}),e)}},{key:"getStatus",value:function(){var e=this.getTestCounts(),t=e.total,n=e.failed,r=e.skipped,i=e.todo +return n?"failed":r===t?"skipped":i===t?"todo":"passed"}}]),e}(),X=[],Z=new J +function K(e,t,n){var r=t[n] +"function"==typeof r&&e[n].push(r),delete t[n]}function ee(e,t){return function(n){Y.currentModule!==e&&k.warn("The `"+t+"` hook was called inside the wrong module (`"+Y.currentModule.name+"`). Instead, use hooks provided by the callback to the containing module (`"+e.name+"`). This will become an error in QUnit 3.0."),e.hooks[t].push(n)}}function te(e,t,n){"function"==typeof t&&(n=t,t=void 0) +var r=function(e,t,n){var r=X.length?X.slice(-1)[0]:null,i=null!==r?[r.name,e].join(" > "):e,o=r?r.suiteReport:Z,s=null!==r&&r.skip||n.skip,a=null!==r&&r.todo||n.todo,u={} +r&&O(u,r.testEnvironment),O(u,t) +var c={name:i,parentModule:r,hooks:{before:[],beforeEach:[],afterEach:[],after:[]},testEnvironment:u,tests:[],moduleId:R(i),testsRun:0,testsIgnored:0,childModules:[],suiteReport:new J(e,o),stats:null,skip:s,todo:!s&&a,ignored:n.ignored||!1} +return r&&r.childModules.push(c),Y.modules.push(c),c}(e,t,arguments.length>3&&void 0!==arguments[3]?arguments[3]:{}),i=r.testEnvironment,o=r.hooks +K(o,i,"before"),K(o,i,"beforeEach"),K(o,i,"afterEach"),K(o,i,"after") +var s={before:ee(r,"before"),beforeEach:ee(r,"beforeEach"),afterEach:ee(r,"afterEach"),after:ee(r,"after")},a=Y.currentModule +if(Y.currentModule=r,"function"==typeof n){X.push(r) +try{var u=n.call(r.testEnvironment,s) +u&&"function"==typeof u.then&&k.warn("Returning a promise from a module callback is not supported. Instead, use hooks for async behavior. This will become an error in QUnit 3.0.")}finally{X.pop(),Y.currentModule=r.parentModule||a}}}var ne=!1 +function re(e,t,n){var r,i=ne&&(r=Y.modules.filter((function(e){return!e.ignored})).map((function(e){return e.moduleId})),!X.some((function(e){return r.includes(e.moduleId)}))) +te(e,t,n,{ignored:i})}re.only=function(){ne||(Y.modules.length=0,Y.queue.length=0,Y.currentModule.ignored=!0),ne=!0,te.apply(void 0,arguments)},re.skip=function(e,t,n){ne||te(e,t,n,{skip:!0})},re.todo=function(e,t,n){ne||te(e,t,n,{todo:!0})} +var ie=(se(0)||"").replace(/(:\d+)+\)?/,"").replace(/.+[/\\]/,"") +function oe(e,t){if(t=void 0===t?4:t,e&&e.stack){var n=e.stack.split("\n") +if(/^error$/i.test(n[0])&&n.shift(),ie){for(var r=[],i=t;i0&&this.test.internalResetTimeout(this.test.timeout))}},{key:"step",value:function(e){var t=e,n=!!e +this.test.steps.push(e),void 0===e||""===e?t="You must provide a message to assert.step":"string"!=typeof e&&(t="You must provide a string value to assert.step",n=!1),this.pushResult({result:n,message:t})}},{key:"verifySteps",value:function(e,t){var n=this.test.steps.slice() +this.deepEqual(n,e,t),this.test.steps.length=0}},{key:"expect",value:function(e){if(1!==arguments.length)return this.test.expected +this.test.expected=e}},{key:"async",value:function(e){var t=void 0===e?1:e +return this.test.internalStop(t)}},{key:"push",value:function(t,n,r,i,o){return k.warn("assert.push is deprecated and will be removed in QUnit 3.0. Please use assert.pushResult instead (https://api.qunitjs.com/assert/pushResult)."),(this instanceof e?this:Y.current.assert).pushResult({result:t,actual:n,expected:r,message:i,negative:o})}},{key:"pushResult",value:function(t){var n=this,r=n instanceof e&&n.test||Y.current +if(!r)throw new Error("assertion outside test context, in "+se(2)) +return n instanceof e||(n=r.assert),n.test.pushResult(t)}},{key:"ok",value:function(e,t){t||(t=e?"okay":"failed, expected argument to be truthy, was: ".concat(V.parse(e))),this.pushResult({result:!!e,actual:e,expected:!0,message:t})}},{key:"notOk",value:function(e,t){t||(t=e?"failed, expected argument to be falsy, was: ".concat(V.parse(e)):"okay"),this.pushResult({result:!e,actual:e,expected:!1,message:t})}},{key:"true",value:function(e,t){this.pushResult({result:!0===e,actual:e,expected:!0,message:t})}},{key:"false",value:function(e,t){this.pushResult({result:!1===e,actual:e,expected:!1,message:t})}},{key:"equal",value:function(e,t,n){this.pushResult({result:t==e,actual:e,expected:t,message:n})}},{key:"notEqual",value:function(e,t,n){this.pushResult({result:t!=e,actual:e,expected:t,message:n,negative:!0})}},{key:"propEqual",value:function(e,t,n){e=N(e),t=N(t),this.pushResult({result:G(e,t),actual:e,expected:t,message:n})}},{key:"notPropEqual",value:function(e,t,n){e=N(e),t=N(t),this.pushResult({result:!G(e,t),actual:e,expected:t,message:n,negative:!0})}},{key:"propContains",value:function(e,t,n){e=M(e,t),t=N(t,!1),this.pushResult({result:G(e,t),actual:e,expected:t,message:n})}},{key:"notPropContains",value:function(e,t,n){e=M(e,t),t=N(t),this.pushResult({result:!G(e,t),actual:e,expected:t,message:n,negative:!0})}},{key:"deepEqual",value:function(e,t,n){this.pushResult({result:G(e,t),actual:e,expected:t,message:n})}},{key:"notDeepEqual",value:function(e,t,n){this.pushResult({result:!G(e,t),actual:e,expected:t,message:n,negative:!0})}},{key:"strictEqual",value:function(e,t,n){this.pushResult({result:t===e,actual:e,expected:t,message:n})}},{key:"notStrictEqual",value:function(e,t,n){this.pushResult({result:t!==e,actual:e,expected:t,message:n,negative:!0})}},{key:"throws",value:function(t,n,r){var i=u(ue(n,r,"throws"),2) +n=i[0],r=i[1] +var o=this instanceof e&&this.test||Y.current +if("function"==typeof t){var s,a=!1 +o.ignoreGlobalErrors=!0 +try{t.call(o.testEnvironment)}catch(e){s=e}if(o.ignoreGlobalErrors=!1,s){var c=u(ce(s,n,r),3) +a=c[0],n=c[1],r=c[2]}o.assert.pushResult({result:a,actual:s&&I(s),expected:n,message:r})}else o.assert.pushResult({result:!1,actual:t,message:'The value provided to `assert.throws` in "'+o.testName+'" was not a function.'})}},{key:"rejects",value:function(t,n,r){var i=u(ue(n,r,"rejects"),2) +n=i[0],r=i[1] +var o=this instanceof e&&this.test||Y.current,s=t&&t.then +if("function"==typeof s){var a=this.async() +return s.call(t,(function(){o.assert.pushResult({result:!1,message:'The promise returned by the `assert.rejects` callback in "'+o.testName+'" did not reject.',actual:t}),a()}),(function(e){var t,i=u(ce(e,n,r),3) +t=i[0],n=i[1],r=i[2],o.assert.pushResult({result:t,actual:e&&I(e),expected:n,message:r}),a()}))}o.assert.pushResult({result:!1,message:'The value provided to `assert.rejects` in "'+o.testName+'" was not a promise.',actual:t})}}]),e}() +function ue(e,t,n){var r=q(e) +if("string"===r){if(void 0===t)return t=e,[e=void 0,t] +throw new Error("assert."+n+" does not accept a string value for the expected argument.\nUse a non-string object value (e.g. RegExp or validator function) instead if necessary.")}if(e&&"regexp"!==r&&"function"!==r&&"object"!==r)throw new Error("Invalid expected value type ("+r+") provided to assert."+n+".") +return[e,t]}function ce(e,t,n){var r=!1,i=q(t) +if(t){if("regexp"===i)r=t.test(I(e)),t=String(t) +else if("function"===i&&void 0!==t.prototype&&e instanceof t)r=!0 +else if("object"===i)r=e instanceof t.constructor&&e.name===t.name&&e.message===t.message,t=I(t) +else if("function"===i)try{r=!0===t.call({},e),t=null}catch(e){t=I(e)}}else r=!0 +return[r,t,n]}ae.prototype.raises=ae.prototype.throws +var le=Object.create(null),fe=["error","runStart","suiteStart","testStart","assertion","testEnd","suiteEnd","runEnd"] +function he(e,t){if("string"!=typeof e)throw new TypeError("eventName must be a string when emitting an event") +for(var n=le[e],r=n?c(n):[],i=0;i0&&be--,xe()):function(){var e +if(0===Y.stats.testCount&&!0===Y.failOnZeroTests)return e=Y.filter&&Y.filter.length?new Error('No tests matched the filter "'.concat(Y.filter,'".')):Y.module&&Y.module.length?new Error('No tests matched the module "'.concat(Y.module,'".')):Y.moduleId&&Y.moduleId.length?new Error('No tests matched the moduleId "'.concat(Y.moduleId,'".')):Y.testId&&Y.testId.length?new Error('No tests matched the testId "'.concat(Y.testId,'".')):new Error("No tests were run."),Oe("global failure",O((function(t){t.pushResult({result:!1,message:e.message,source:e.stack})}),{validTest:!0})),void xe() +var t=Y.storage,n=Math.round(C.now()-Y.started),r=Y.stats.all-Y.stats.bad +Ee.finished=!0,he("runEnd",Z.end(!0)),me("done",{passed:r,failed:Y.stats.bad,total:Y.stats.all,runtime:n}).then((function(){if(t&&0===Y.stats.bad)for(var e=t.length-1;e>=0;e--){var n=t.key(e) +0===n.indexOf("qunit-test-")&&t.removeItem(n)}}))}())}function ke(e){if(we.length&&!Y.blocking){var t=C.now()-e +if(!g||Y.updateRate<=0||t>>17,(t^=t<<5)<0&&(t+=4294967296),t/4294967296}}(n)) +var r=Math.floor(ye()*(Y.queue.length-be+1)) +Y.queue.splice(be+r,0,e)}else Y.queue.push(e)},advance:xe,taskCount:function(){return we.length}},_e=function(){function e(t,n,r){o(this,e),this.name=t,this.suiteName=n.name,this.fullName=n.fullName.concat(t),this.runtime=0,this.assertions=[],this.skipped=!!r.skip,this.todo=!!r.todo,this.valid=r.valid,this._startTime=0,this._endTime=0,n.pushTest(this)}return a(e,[{key:"start",value:function(e){return e&&(this._startTime=C.now(),C.mark("qunit_test_start")),{name:this.name,suiteName:this.suiteName,fullName:this.fullName.slice()}}},{key:"end",value:function(e){if(e&&(this._endTime=C.now(),C)){C.mark("qunit_test_end") +var t=this.fullName.join(" – ") +C.measure("QUnit Test: ".concat(t),"qunit_test_start","qunit_test_end")}return O(this.start(),{runtime:this.getRuntime(),status:this.getStatus(),errors:this.getFailedAssertions(),assertions:this.getAssertions()})}},{key:"pushAssertion",value:function(e){this.assertions.push(e)}},{key:"getRuntime",value:function(){return Math.round(this._endTime-this._startTime)}},{key:"getStatus",value:function(){return this.skipped?"skipped":(this.getFailedAssertions().length>0?this.todo:!this.todo)?this.todo?"todo":"passed":"failed"}},{key:"getFailedAssertions",value:function(){return this.assertions.filter((function(e){return!e.passed}))}},{key:"getAssertions",value:function(){return this.assertions.slice()}},{key:"slimAssertions",value:function(){this.assertions=this.assertions.map((function(e){return delete e.actual,delete e.expected,e}))}}]),e}() +function Se(e){if(this.expected=null,this.assertions=[],this.module=Y.currentModule,this.steps=[],this.timeout=void 0,this.data=void 0,this.withData=!1,this.pauses=new w,this.nextPauseId=1,this.stackOffset=3,O(this,e),this.module.skip?(this.skip=!0,this.todo=!1):this.module.todo&&!this.skip&&(this.todo=!0),Ee.finished)k.warn("Unexpected test after runEnd. This is unstable and will fail in QUnit 3.0.") +else{if(!this.skip&&"function"!=typeof this.callback){var t=this.todo?"QUnit.todo":"QUnit.test" +throw new TypeError("You must provide a callback to ".concat(t,'("').concat(this.testName,'")'))}for(var n=0,r=this.module.tests;n0&&Ce("Test did not finish synchronously even though assert.timeout( 0 ) was used.",se(2))}},after:function(){!function(){var e=Y.pollution +Te() +var t=T(Y.pollution,e) +t.length>0&&Ce("Introduced global variable(s): "+t.join(", ")) +var n=T(e,Y.pollution) +n.length>0&&Ce("Deleted global variable(s): "+n.join(", "))}()},queueGlobalHook:function(e,t){var n=this +return function(){var r +if(Y.current=n,Y.notrycatch)r=e.call(n.testEnvironment,n.assert) +else try{r=e.call(n.testEnvironment,n.assert)}catch(e){return void n.pushFailure("Global "+t+" failed on "+n.testName+": "+I(e),oe(e,0))}n.resolvePromise(r,t)}},queueHook:function(e,t,n){var r=this,i=function(){var n=e.call(r.testEnvironment,r.assert) +r.resolvePromise(n,t)} +return function(){if("before"===t){if(0!==n.testsRun)return +r.preserveEnvironment=!0}if("after"!==t||function(e){return e.testsRun===Fe(e).filter((function(e){return!e.skip})).length-1}(n)||!(Y.queue.length>0||Ee.taskCount()>2))if(Y.current=r,Y.notrycatch)i() +else try{i()}catch(e){r.pushFailure(t+" failed on "+r.testName+": "+(e.message||e),oe(e,0))}}},hooks:function(e){var t=[] +return this.skip||(function(n){if(("beforeEach"===e||"afterEach"===e)&&Y.globalHooks[e])for(var r=0;r Test: "+n+"\n> Message: "+t+"\n")}var r={module:this.module.name,name:this.testName,result:e.result,message:e.message,actual:e.actual,testId:this.testId,negative:e.negative||!1,runtime:Math.round(C.now()-this.started),todo:!!this.todo} +if(_.call(e,"expected")&&(r.expected=e.expected),!e.result){var i=e.source||se() +i&&(r.source=i)}this.logAssertion(r),this.assertions.push({result:!!e.result,message:e.message})},pushFailure:function(e,t,n){if(!(this instanceof Se))throw new Error("pushFailure() assertion outside test context, was "+se(2)) +this.pushResult({result:!1,message:e||"error",actual:n||null,source:t})},logAssertion:function(e){me("log",e) +var t={passed:e.result,actual:e.actual,expected:e.expected,message:e.message,stack:e.source,todo:e.todo} +this.testReport.pushAssertion(t),he("assertion",t)},internalResetTimeout:function(e){v(Y.timeout),Y.timeout=g(Y.timeoutHandler(e),e)},internalStop:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1 +Y.blocking=!0 +var t,n=this,r=this.nextPauseId++,i={cancelled:!1,remaining:e} +return n.pauses.set(r,i),g&&("number"==typeof n.timeout?t=n.timeout:"number"==typeof Y.testTimeout&&(t=Y.testTimeout),"number"==typeof t&&t>0&&(Y.timeoutHandler=function(e){return function(){Y.timeout=null,i.cancelled=!0,n.pauses.delete(r),n.pushFailure("Test took longer than ".concat(e,"ms; test timed out."),se(2)),Ie(n)}},v(Y.timeout),Y.timeout=g(Y.timeoutHandler(t),t))),function(){if(!i.cancelled){if(void 0===Y.current)throw new Error("Unexpected release of async pause after tests finished.\n"+"> Test: ".concat(n.testName," [async #").concat(r,"]")) +if(Y.current!==n)throw new Error("Unexpected release of async pause during a different test.\n"+"> Test: ".concat(n.testName," [async #").concat(r,"]")) +if(i.remaining<=0)throw new Error("Tried to release async pause that was already released.\n"+"> Test: ".concat(n.testName," [async #").concat(r,"]")) +i.remaining--,0===i.remaining&&n.pauses.delete(r),Ie(n)}}},resolvePromise:function(e,t){if(null!=e){var n=this,r=e.then +if("function"==typeof r){var i=n.internalStop(),o=function(){i()} +Y.notrycatch?r.call(e,o):r.call(e,o,(function(e){var r="Promise rejected "+(t?t.replace(/Each$/,""):"during")+' "'+n.testName+'": '+(e&&e.message||e) +n.pushFailure(r,oe(e,0)),Te(),Re(n)}))}}},valid:function(){if(this.callback&&this.callback.validTest)return!0 +if(!function e(t,n){return!n||!n.length||j(t.moduleId,n)||t.parentModule&&e(t.parentModule,n)}(this.module,Y.moduleId))return!1 +if(Y.testId&&Y.testId.length&&!j(this.testId,Y.testId))return!1 +var e=Y.module&&Y.module.toLowerCase() +if(!function e(t,n){return!n||(t.name?t.name.toLowerCase():null)===n||!!t.parentModule&&e(t.parentModule,n)}(this.module,e))return!1 +var t=Y.filter +if(!t)return!0 +var n=/^(!?)\/([\w\W]*)\/(i?$)/.exec(t),r=this.module.name+": "+this.testName +return n?this.regexFilter(!!n[1],n[2],n[3],r):this.stringFilter(t,r)},regexFilter:function(e,t,n,r){return new RegExp(t,n).test(r)!==e},stringFilter:function(e,t){e=e.toLowerCase(),t=t.toLowerCase() +var n="!"!==e.charAt(0) +return n||(e=e.slice(1)),-1!==t.indexOf(e)?n:!n}} +var je=!1 +function Ne(e){je||Y.currentModule.ignored||new Se(e).queue()}function Me(e){Y.currentModule.ignored||(je||(Y.queue.length=0,je=!0),new Se(e).queue())}function Oe(e,t){Ne({testName:e,callback:t})}function qe(e,t){return"".concat(e," [").concat(t,"]")}function Ae(e,t){if(Array.isArray(e))for(var n=0;n0||(g?(v(Y.timeout),Y.timeout=g((function(){e.pauses.size>0||(v(Y.timeout),Y.timeout=null,Y.blocking=!1,Ee.advance())}))):(Y.blocking=!1,Ee.advance()))}function Fe(e){for(var t=[].concat(e.tests),n=c(e.childModules);n.length;){var r=n.shift() +t.push.apply(t,r.tests),n.push.apply(n,c(r.childModules))}return t}function Pe(e){return e.testsRun+e.testsIgnored===Fe(e).length}function De(e){for(e.testsIgnored++;e=e.parentModule;)e.testsIgnored++}O(Oe,{todo:function(e,t){Ne({testName:e,callback:t,todo:!0})},skip:function(e){Ne({testName:e,skip:!0})},only:function(e,t){Me({testName:e,callback:t})},each:function(e,t,n){Ae(t,(function(t,r){Ne({testName:qe(e,r),callback:n,withData:!0,stackOffset:5,data:t})}))}}),Oe.todo.each=function(e,t,n){Ae(t,(function(t,r){Ne({testName:qe(e,r),callback:n,todo:!0,withData:!0,stackOffset:5,data:t})}))},Oe.skip.each=function(e,t){Ae(t,(function(t,n){Ne({testName:qe(e,n),stackOffset:5,skip:!0})}))},Oe.only.each=function(e,t,n){Ae(t,(function(t,r){Me({testName:qe(e,r),callback:n,withData:!0,stackOffset:5,data:t})}))} +var Le,Be,Ue,He,ze=function(){function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +o(this,e),this.log=n.log||Function.prototype.bind.call(p.log,p),t.on("error",this.onError.bind(this)),t.on("runStart",this.onRunStart.bind(this)),t.on("testStart",this.onTestStart.bind(this)),t.on("testEnd",this.onTestEnd.bind(this)),t.on("runEnd",this.onRunEnd.bind(this))}return a(e,[{key:"onError",value:function(e){this.log("error",e)}},{key:"onRunStart",value:function(e){this.log("runStart",e)}},{key:"onTestStart",value:function(e){this.log("testStart",e)}},{key:"onTestEnd",value:function(e){this.log("testEnd",e)}},{key:"onRunEnd",value:function(e){this.log("runEnd",e)}}],[{key:"init",value:function(t,n){return new e(t,n)}}]),e}(),$e=!0 +if("undefined"!=typeof process){var Qe=process.env||{} +Le=Qe.FORCE_COLOR,Be=Qe.NODE_DISABLE_COLORS,Ue=Qe.NO_COLOR,He=Qe.TERM,$e=process.stdout&&process.stdout.isTTY}var Ge={enabled:!Be&&null==Ue&&"dumb"!==He&&(null!=Le&&"0"!==Le||$e),reset:We(0,0),bold:We(1,22),dim:We(2,22),italic:We(3,23),underline:We(4,24),inverse:We(7,27),hidden:We(8,28),strikethrough:We(9,29),black:We(30,39),red:We(31,39),green:We(32,39),yellow:We(33,39),blue:We(34,39),magenta:We(35,39),cyan:We(36,39),white:We(37,39),gray:We(90,39),grey:We(90,39),bgBlack:We(40,49),bgRed:We(41,49),bgGreen:We(42,49),bgYellow:We(43,49),bgBlue:We(44,49),bgMagenta:We(45,49),bgCyan:We(46,49),bgWhite:We(47,49)} +function Ye(e,t){for(var n,r=0,i="",o="";r1&&void 0!==arguments[1]?arguments[1]:4 +if(void 0===e&&(e=String(e)),"number"!=typeof e||isFinite(e)||(e=String(e)),"number"==typeof e)return JSON.stringify(e) +if("string"==typeof e){if(""===e||/['"\\/[{}\]\r\n]/.test(e)||/[-?:,[\]{}#&*!|=>'"%@`]/.test(e[0])||/(^\s|\s$)/.test(e)||/^[\d._-]+$/.test(e)||/^(true|false|y|n|yes|no|on|off)$/i.test(e)){if(!/\n/.test(e))return JSON.stringify(e) +var n=new Array(t+1).join(" "),r=e.match(/\n+$/) +return 1===(r?r[0].length:0)?"|\n"+e.replace(/\n$/,"").split("\n").map((function(e){return n+e})).join("\n"):"|+\n"+e.split("\n").map((function(e){return n+e})).join("\n")}return e}return JSON.stringify(Xe(e),null,2)}function Xe(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[] +if(-1!==n.indexOf(e))return"[Circular]" +switch(Object.prototype.toString.call(e).replace(/^\[.+\s(.+?)]$/,"$1").toLowerCase()){case"array":n.push(e),t=e.map((function(e){return Xe(e,n)})),n.pop() +break +case"object":n.push(e),t={},Object.keys(e).forEach((function(r){t[r]=Xe(e[r],n)})),n.pop() +break +default:t=e}return t}var Ze=function(){function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +o(this,e),this.log=n.log||Function.prototype.bind.call(p.log,p),this.testCount=0,this.ended=!1,this.bailed=!1,t.on("error",this.onError.bind(this)),t.on("runStart",this.onRunStart.bind(this)),t.on("testEnd",this.onTestEnd.bind(this)),t.on("runEnd",this.onRunEnd.bind(this))}return a(e,[{key:"onRunStart",value:function(e){this.log("TAP version 13")}},{key:"onError",value:function(e){this.bailed||(this.bailed=!0,this.ended||(this.testCount=this.testCount+1,this.log(Ge.red("not ok ".concat(this.testCount," global failure"))),this.logError(e)),this.log("Bail out! "+I(e).split("\n")[0]),this.ended&&this.logError(e))}},{key:"onTestEnd",value:function(e){var t=this +this.testCount=this.testCount+1,"passed"===e.status?this.log("ok ".concat(this.testCount," ").concat(e.fullName.join(" > "))):"skipped"===e.status?this.log(Ge.yellow("ok ".concat(this.testCount," # SKIP ").concat(e.fullName.join(" > ")))):"todo"===e.status?(this.log(Ge.cyan("not ok ".concat(this.testCount," # TODO ").concat(e.fullName.join(" > ")))),e.errors.forEach((function(e){return t.logAssertion(e,"todo")}))):(this.log(Ge.red("not ok ".concat(this.testCount," ").concat(e.fullName.join(" > ")))),e.errors.forEach((function(e){return t.logAssertion(e)})))}},{key:"onRunEnd",value:function(e){this.ended=!0,this.log("1..".concat(e.testCounts.total)),this.log("# pass ".concat(e.testCounts.passed)),this.log(Ge.yellow("# skip ".concat(e.testCounts.skipped))),this.log(Ge.cyan("# todo ".concat(e.testCounts.todo))),this.log(Ge.red("# fail ".concat(e.testCounts.failed)))}},{key:"logAssertion",value:function(e,t){var n=" ---" +n+="\n message: ".concat(Je(e.message||"failed")),n+="\n severity: ".concat(Je(t||"failed")),Ve.call(e,"actual")&&(n+="\n actual : ".concat(Je(e.actual))),Ve.call(e,"expected")&&(n+="\n expected: ".concat(Je(e.expected))),e.stack&&(n+="\n stack: ".concat(Je(e.stack+"\n"))),n+="\n ...",this.log(n)}},{key:"logError",value:function(e){var t=" ---" +t+="\n message: ".concat(Je(I(e))),t+="\n severity: ".concat(Je("failed")),e&&e.stack&&(t+="\n stack: ".concat(Je(e.stack+"\n"))),t+="\n ...",this.log(t)}}],[{key:"init",value:function(t,n){return new e(t,n)}}]),e}(),Ke={console:ze,tap:Ze} +function et(e){return function(t){Y.globalHooks[e]||(Y.globalHooks[e]=[]),Y.globalHooks[e].push(t)}}var tt={beforeEach:et("beforeEach"),afterEach:et("afterEach")} +function nt(e){Y.current?Y.current.assert.pushResult({result:!1,message:"global failure: ".concat(I(e)),source:e&&e.stack||se(2)}):(Z.globalFailureCount++,Y.stats.bad++,Y.stats.all++,he("error",e))}var rt={} +Y.currentModule.suiteReport=Z +var it=!1,ot=!1 +function st(){ot=!0,g?g((function(){ut()})):ut()}function at(){Y.blocking=!1,Ee.advance()}function ut(){if(Y.started)at() +else{Y.started=C.now(),""===Y.modules[0].name&&0===Y.modules[0].tests.length&&Y.modules.shift() +for(var e=[],t=0;t1)throw new Error("Called start() outside of a test context too many times") +if(Y.autostart)throw new Error("Called start() outside of a test context when QUnit.config.autostart was true") +if(!Y.pageLoaded)return Y.autostart=!0,void(m||rt.load()) +st()},onUnhandledRejection:function(e){k.warn("QUnit.onUnhandledRejection is deprecated and will be removed in QUnit 3.0. Please use QUnit.onUncaughtException instead."),nt(e)},extend:function(){k.warn("QUnit.extend is deprecated and will be removed in QUnit 3.0. Please use Object.assign instead.") +for(var e=arguments.length,t=new Array(e),n=0;n=0;--n){var r=e[n] +if(null!==r){var i=r.score +i>t&&(t=i)}}return-9007199254740991===t?null:t}function l(e,t){var n=e[t] +if(void 0!==n)return n +var r=t +Array.isArray(t)||(r=t.split(".")) +for(var i=r.length,o=-1;e&&++o>1]=e[n],i=1+(n<<1)}for(var s=n-1>>1;n>0&&r.score>1)e[n]=e[s] +e[n]=r}return n.add=function(n){var r=t +e[t++]=n +for(var i=r-1>>1;r>0&&n.score>1)e[r]=e[i] +e[r]=n},n.poll=function(){if(0!==t){var n=e[0] +return e[0]=e[--t],r(),n}},n.peek=function(n){if(0!==t)return e[0]},n.replaceTop=function(t){e[0]=t,r()},n},d=h() +return function t(i){var p={single:function(e,t,n){return"farzher"==e?{target:"farzher was here (^-^*)/",score:0,indexes:[0,1,2,3,4,5,6]}:e?(f(e)||(e=p.getPreparedSearch(e)),t?(f(t)||(t=p.getPrepared(t)),((n&&void 0!==n.allowTypo?n.allowTypo:!i||void 0===i.allowTypo||i.allowTypo)?p.algorithm:p.algorithmNoTypo)(e,t,e[0])):null):null},go:function(e,t,n){if("farzher"==e)return[{target:"farzher was here (^-^*)/",score:0,indexes:[0,1,2,3,4,5,6],obj:t?t[0]:null}] +if(!e)return o +var r=(e=p.prepareSearch(e))[0],s=n&&n.threshold||i&&i.threshold||-9007199254740991,a=n&&n.limit||i&&i.limit||9007199254740991,u=(n&&void 0!==n.allowTypo?n.allowTypo:!i||void 0===i.allowTypo||i.allowTypo)?p.algorithm:p.algorithmNoTypo,h=0,g=0,v=t.length +if(n&&n.keys)for(var m=n.scoreFn||c,y=n.keys,b=y.length,w=v-1;w>=0;--w){for(var x=t[w],k=new Array(b),E=b-1;E>=0;--E)(C=l(x,S=y[E]))?(f(C)||(C=p.getPrepared(C)),k[E]=u(e,C,r)):k[E]=null +k.obj=x +var _=m(k) +null!==_&&(_d.peek().score&&d.replaceTop(k))))}else if(n&&n.key){var S=n.key +for(w=v-1;w>=0;--w)(C=l(x=t[w],S))&&(f(C)||(C=p.getPrepared(C)),null!==(T=u(e,C,r))&&(T.scored.peek().score&&d.replaceTop(T)))))}else for(w=v-1;w>=0;--w){var C,T;(C=t[w])&&(f(C)||(C=p.getPrepared(C)),null!==(T=u(e,C,r))&&(T.scored.peek().score&&d.replaceTop(T)))))}if(0===h)return o +var j=new Array(h) +for(w=h-1;w>=0;--w)j[w]=d.poll() +return j.total=h+g,j},goAsync:function(t,n,r){var s=!1,a=new Promise((function(a,u){if("farzher"==t)return a([{target:"farzher was here (^-^*)/",score:0,indexes:[0,1,2,3,4,5,6],obj:n?n[0]:null}]) +if(!t)return a(o) +var d=(t=p.prepareSearch(t))[0],g=h(),v=n.length-1,m=r&&r.threshold||i&&i.threshold||-9007199254740991,y=r&&r.limit||i&&i.limit||9007199254740991,b=(r&&void 0!==r.allowTypo?r.allowTypo:!i||void 0===i.allowTypo||i.allowTypo)?p.algorithm:p.algorithmNoTypo,w=0,x=0 +function k(){if(s)return u("canceled") +var i=Date.now() +if(r&&r.keys)for(var h=r.scoreFn||c,E=r.keys,_=E.length;v>=0;--v){if(v%1e3==0&&Date.now()-i>=10)return void(e?setImmediate(k):setTimeout(k)) +for(var S=n[v],C=new Array(_),T=_-1;T>=0;--T)(M=l(S,N=E[T]))?(f(M)||(M=p.getPrepared(M)),C[T]=b(t,M,d)):C[T]=null +C.obj=S +var j=h(C) +null!==j&&(jg.peek().score&&g.replaceTop(C))))}else if(r&&r.key)for(var N=r.key;v>=0;--v){if(v%1e3==0&&Date.now()-i>=10)return void(e?setImmediate(k):setTimeout(k));(M=l(S=n[v],N))&&(f(M)||(M=p.getPrepared(M)),null!==(O=b(t,M,d))&&(O.scoreg.peek().score&&g.replaceTop(O)))))}else for(;v>=0;--v){if(v%1e3==0&&Date.now()-i>=10)return void(e?setImmediate(k):setTimeout(k)) +var M,O;(M=n[v])&&(f(M)||(M=p.getPrepared(M)),null!==(O=b(t,M,d))&&(O.scoreg.peek().score&&g.replaceTop(O)))))}if(0===w)return a(o) +for(var q=new Array(w),A=w-1;A>=0;--A)q[A]=g.poll() +q.total=w+x,a(q)}e?setImmediate(k):k()})) +return a.cancel=function(){s=!0},a},highlight:function(e,t,n){if("function"==typeof t)return p.highlightCallback(e,t) +if(null===e)return null +void 0===t&&(t=""),void 0===n&&(n="") +for(var r="",i=0,o=!1,s=e.target,a=s.length,u=e.indexes,c=0;c999)return p.prepare(e) +var t=n.get(e) +return void 0!==t||(t=p.prepare(e),n.set(e,t)),t},getPreparedSearch:function(e){if(e.length>999)return p.prepareSearch(e) +var t=r.get(e) +return void 0!==t||(t=p.prepareSearch(e),r.set(e,t)),t},algorithm:function(e,t,n){for(var r=t._targetLowerCodes,i=e.length,o=r.length,u=0,c=0,l=0,f=0;;){if(n===r[c]){if(s[f++]=c,++u===i)break +n=e[0===l?u:l===u?u+1:l===u-1?u-1:u]}if(++c>=o)for(;;){if(u<=1)return null +if(0===l){if(n===e[--u])continue +l=u}else{if(1===l)return null +if((n=e[1+(u=--l)])===e[u])continue}c=s[(f=u)-1]+1 +break}}u=0 +var h=0,d=!1,g=0,v=t._nextBeginningIndexes +null===v&&(v=t._nextBeginningIndexes=p.prepareNextBeginningIndexes(t.target)) +var m=c=0===s[0]?0:v[s[0]-1] +if(c!==o)for(;;)if(c>=o){if(u<=0){if(++h>i-2)break +if(e[h]===e[h+1])continue +c=m +continue}--u,c=v[a[--g]]}else if(e[0===h?u:h===u?u+1:h===u-1?u-1:u]===r[c]){if(a[g++]=c,++u===i){d=!0 +break}++c}else c=v[c] +if(d)var y=a,b=g +else y=s,b=f +for(var w=0,x=-1,k=0;k=0;--k)t.indexes[k]=y[k] +return t},algorithmNoTypo:function(e,t,n){for(var r=t._targetLowerCodes,i=e.length,o=r.length,u=0,c=0,l=0;;){if(n===r[c]){if(s[l++]=c,++u===i)break +n=e[u]}if(++c>=o)return null}u=0 +var f=!1,h=0,d=t._nextBeginningIndexes +if(null===d&&(d=t._nextBeginningIndexes=p.prepareNextBeginningIndexes(t.target)),(c=0===s[0]?0:d[s[0]-1])!==o)for(;;)if(c>=o){if(u<=0)break;--u,c=d[a[--h]]}else if(e[u]===r[c]){if(a[h++]=c,++u===i){f=!0 +break}++c}else c=d[c] +if(f)var g=a,v=h +else g=s,v=l +for(var m=0,y=-1,b=0;b=0;--b)t.indexes[b]=g[b] +return t},prepareLowerCodes:function(e){for(var t=e.length,n=[],r=e.toLowerCase(),i=0;i=65&&a<=90,c=u||a>=97&&a<=122||a>=48&&a<=57,l=u&&!i||!o||!c +i=u,o=c,l&&(n[r++]=s)}return n},prepareNextBeginningIndexes:function(e){for(var t=e.length,n=p.prepareBeginningIndexes(e),r=[],i=n[0],o=0,s=0;ss?r[s]=i:(i=n[++o],r[s]=void 0===i?t:i) +return r},cleanup:u,new:t} +return p}()},e.exports?e.exports=n():t.fuzzysort=n()}(ct) +var lt=ct.exports,ft={failedTests:[],defined:0,completed:0} +function ht(e){return e?(""+e).replace(/['"<>&]/g,(function(e){switch(e){case"'":return"'" +case'"':return""" +case"<":return"<" +case">":return">" +case"&":return"&"}})):""}!function(){if(d&&m){var e=rt.config,t=[],n=!1,r=Object.prototype.hasOwnProperty,i=j({filter:void 0,module:void 0,moduleId:void 0,testId:void 0}),o=null +rt.on("runStart",(function(e){ft.defined=e.testCounts.total})),rt.begin((function(t){!function(t){var n,s,a,u,l,f,p,b,E=_("qunit") +E&&(E.setAttribute("role","main"),E.innerHTML="

    "+ht(m.title)+"

    "+(!(n=rt.config.testId)||n.length<=0?"":"
    Rerunning selected tests: "+ht(n.join(", "))+" Run all tests
    ")+"

      "),(s=_("qunit-header"))&&(s.innerHTML=""+s.innerHTML+" "),(a=_("qunit-banner"))&&(a.className=""),p=_("qunit-tests"),(b=_("qunit-testresult"))&&b.parentNode.removeChild(b),p&&(p.innerHTML="",(b=m.createElement("p")).id="qunit-testresult",b.className="result",p.parentNode.insertBefore(b,p),b.innerHTML='
      Running...
       
      ',l=_("qunit-testresult-controls")),l&&l.appendChild(((f=m.createElement("button")).id="qunit-abort-tests-button",f.innerHTML="Abort",h(f,"click",S),f)),(u=_("qunit-userAgent"))&&(u.innerHTML="",u.appendChild(m.createTextNode("QUnit "+rt.version+"; "+y.userAgent))),function(t){var n,i,s,a,u,l=_("qunit-testrunner-toolbar") +if(l){l.appendChild(((u=m.createElement("span")).innerHTML=function(){for(var t=!1,n=e.urlConfig,i="",o=0;o"+s.label+": "}else i+=""}return i}(),x(u,"qunit-url-config"),v(u.getElementsByTagName("input"),"change",T),v(u.getElementsByTagName("select"),"change",T),u)) +var f=m.createElement("span") +f.id="qunit-toolbar-filters",f.appendChild((n=m.createElement("form"),i=m.createElement("label"),s=m.createElement("input"),a=m.createElement("button"),x(n,"qunit-filter"),i.innerHTML="Filter: ",s.type="text",s.value=e.filter||"",s.name="filter",s.id="qunit-filter-input",a.innerHTML="Go",i.appendChild(s),n.appendChild(i),n.appendChild(m.createTextNode(" ")),n.appendChild(a),h(n,"submit",C),n)),f.appendChild(function(t){var n=null +if(o={options:t.modules.slice(),selectedMap:new w,isDirty:function(){return c(o.selectedMap.keys()).sort().join(",")!==c(n.keys()).sort().join(",")}},e.moduleId.length)for(var r=0;r","",u," assertions of ",e.stats.all," passed, ",e.stats.bad," failed.",A(ft.failedTests)].join("") +if(a&&a.disabled){c="Tests aborted after "+t.runtime+" milliseconds." +for(var l=0;l":"Running: ",R(e.name,e.module),A(ft.failedTests)].join(""))})),rt.log((function(e){var t=_("qunit-test-output-"+e.testId) +if(t){var n,i,o,s=ht(e.message)||(e.result?"okay":"failed") +s=""+s+"",s+="@ "+e.runtime+" ms" +var a=!1 +!e.result&&r.call(e,"expected")?(n=e.negative?"NOT "+rt.dump.parse(e.expected):rt.dump.parse(e.expected),i=rt.dump.parse(e.actual),s+="",i!==n?(s+="","number"==typeof e.actual&&"number"==typeof e.expected?isNaN(e.actual)||isNaN(e.expected)||(a=!0,o=((o=e.actual-e.expected)>0?"+":"")+o):"boolean"!=typeof e.actual&&"boolean"!=typeof e.expected&&(a=P(o=rt.diff(n,i)).length!==P(n).length+P(i).length),a&&(s+="")):-1!==n.indexOf("[object Array]")||-1!==n.indexOf("[object Object]")?s+="":s+="",e.source&&(s+=""),s+="
      Expected:
      "+ht(n)+"
      Result:
      "+ht(i)+"
      Diff:
      "+o+"
      Message: Diff suppressed as the depth of object is more than current max depth ("+rt.config.maxDepth+").

      Hint: Use QUnit.dump.maxDepth to run with a higher max depth or Rerun without max depth.

      Message: Diff suppressed as the expected and actual results have an equivalent serialization
      Source:
      "+ht(e.source)+"
      "):!e.result&&e.source&&(s+="
      Source:
      "+ht(e.source)+"
      ") +var u=t.getElementsByTagName("ol")[0],c=m.createElement("li") +c.className=e.result?"pass":"fail",c.innerHTML=s,u.appendChild(c)}})),rt.testDone((function(r){var i=_("qunit-tests"),o=_("qunit-test-output-"+r.testId) +if(i&&o){var s +E(o,"running"),s=r.failed>0?"failed":r.todo?"todo":r.skipped?"skipped":"passed" +var a=o.getElementsByTagName("ol")[0],u=r.passed,c=r.failed,l=r.failed>0?r.todo:!r.todo +l?x(a,"qunit-collapsed"):(ft.failedTests.push(r.testId),e.collapse&&(n?x(a,"qunit-collapsed"):n=!0)) +var f=o.firstChild,d=c?""+c+", "+u+", ":"" +if(f.innerHTML+=" ("+d+r.assertions.length+")",ft.completed++,r.skipped){o.className="skipped" +var p=m.createElement("em") +p.className="qunit-skipped-label",p.innerHTML="skipped",o.insertBefore(p,f)}else{if(h(f,"click",(function(){k(a,"qunit-collapsed")})),o.className=l?"pass":"fail",r.todo){var g=m.createElement("em") +g.className="qunit-todo-label",g.innerHTML="todo",o.className+=" todo",o.insertBefore(g,f)}var v=m.createElement("span") +v.className="runtime",v.innerHTML=r.runtime+" ms",o.insertBefore(v,a)}if(r.source){var y=m.createElement("p") +y.innerHTML="Source: "+ht(r.source),x(y,"qunit-source"),l&&x(y,"qunit-collapsed"),h(f,"click",(function(){k(y,"qunit-collapsed")})),o.appendChild(y)}e.hidepassed&&("passed"===s||r.skipped)&&(t.push(o),i.removeChild(o))}})),rt.on("error",(function(e){var t=q("global failure") +if(t){var n=ht(I(e)) +n=""+n+"",e&&e.stack&&(n+="
      Source:
      "+ht(e.stack)+"
      ") +var r=t.getElementsByTagName("ol")[0],i=m.createElement("li") +i.className="fail",i.innerHTML=n,r.appendChild(i),t.className="fail"}})) +var s,a=(s=d.phantom)&&s.version&&s.version.major>0 +a&&p.warn("Support for PhantomJS is deprecated and will be removed in QUnit 3.0."),a||"complete"!==m.readyState?h(d,"load",rt.load):rt.load() +var u=d.onerror +d.onerror=function(t,n,r,i,o){var s=!1 +if(u){for(var a=arguments.length,c=new Array(a>5?a-5:0),l=5;l=0}function x(e,t){b(e,t)||(e.className+=(e.className?" ":"")+t)}function k(e,t,n){n||void 0===n&&!b(e,t)?x(e,t):E(e,t)}function E(e,t){for(var n=" "+e.className+" ";n.indexOf(" "+t+" ")>=0;)n=n.replace(" "+t+" "," ") +e.className=f(n)}function _(e){return m.getElementById&&m.getElementById(e)}function S(){var e=_("qunit-abort-tests-button") +return e&&(e.disabled=!0,e.innerHTML="Aborting..."),rt.config.queue.length=0,!1}function C(e){var t=_("qunit-filter-input") +return t.value=f(t.value),N(),e&&e.preventDefault&&e.preventDefault(),!1}function T(){var n,r=this,i={} +n="selectedIndex"in r?r.options[r.selectedIndex].value||void 0:r.checked?r.defaultValue||!0:void 0,i[r.name]=n +var o=j(i) +if("hidepassed"===r.name&&"replaceState"in d.history){rt.urlParams[r.name]=n,e[r.name]=n||!1 +var s=_("qunit-tests") +if(s){var a=s.children.length,u=s.children +if(r.checked){for(var c=0;c-1,g=h.indexOf("skipped")>-1;(p||g)&&t.push(f)}var v,m=function(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"] +if(!n){if(Array.isArray(e)||(n=l(e))){n&&(e=n) +var r=0,i=function(){} +return{s:i,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1 +return{s:function(){n=n.call(e)},n:function(){var e=n.next() +return s=e.done,e},e:function(e){a=!0,o=e},f:function(){try{s||null==n.return||n.return()}finally{if(a)throw o}}}}(t) +try{for(m.s();!(v=m.n()).done;){var y=v.value +s.removeChild(y)}}catch(e){m.e(e)}finally{m.f()}}else for(var b;null!=(b=t.pop());)s.appendChild(b)}d.history.replaceState(null,"",o)}else d.location=o}function j(e){var t="?",n=d.location +for(var i in e=O(O({},rt.urlParams),e))if(r.call(e,i)&&void 0!==e[i])for(var o=[].concat(e[i]),s=0;s"}function q(e,t,n){var r=_("qunit-tests") +if(r){var i=m.createElement("strong") +i.innerHTML=R(e,n) +var o=m.createElement("li") +if(o.appendChild(i),void 0!==t){var s=m.createElement("a") +s.innerHTML="Rerun",s.href=j({testId:t}),o.id="qunit-test-output-"+t,o.appendChild(s)}var a=m.createElement("ol") +return a.className="qunit-assert-list",o.appendChild(a),r.appendChild(o),o}}function A(e){return 0===e.length?"":["
      ",1===e.length?"Rerun 1 failed test":"Rerun "+e.length+" failed tests",""].join("")}function R(e,t){var n="" +return t&&(n=""+ht(t)+": "),n+""+ht(e)+""}function F(e){return[e.completed," / ",e.defined," tests completed.
      "].join("")}function P(e){return e.replace(/<\/?[^>]+(>|$)/g,"").replace(/"/g,"").replace(/\s+/g,"")}}(),rt.diff=function(){function e(){}var t=-1,n=Object.prototype.hasOwnProperty +return e.prototype.DiffMain=function(e,t,n){var r=Date.now()+1e3 +if(null===e||null===t)throw new Error("Cannot diff null input.") +if(e===t)return e?[[0,e]]:[] +void 0===n&&(n=!0) +var i=this.diffCommonPrefix(e,t),o=e.substring(0,i) +e=e.substring(i),t=t.substring(i),i=this.diffCommonSuffix(e,t) +var s=e.substring(e.length-i) +e=e.substring(0,e.length-i),t=t.substring(0,t.length-i) +var a=this.diffCompute(e,t,n,r) +return o&&a.unshift([0,o]),s&&a.push([0,s]),this.diffCleanupMerge(a),a},e.prototype.diffCleanupEfficiency=function(e){var n,r,i,o,s,a,u,c,l +for(n=!1,r=[],i=0,o=null,s=0,a=!1,u=!1,c=!1,l=!1;s0?r[i-1]:-1,c=l=!1),n=!0)),s++ +n&&this.diffCleanupMerge(e)},e.prototype.diffPrettyHtml=function(e){for(var n=[],r=0;r" +break +case t:n[r]=""+ht(o)+"" +break +case 0:n[r]=""+ht(o)+""}}return n.join("")},e.prototype.diffCommonPrefix=function(e,t){var n,r,i,o +if(!e||!t||e.charAt(0)!==t.charAt(0))return 0 +for(i=0,n=r=Math.min(e.length,t.length),o=0;in.length?e:n,a=e.length>n.length?n:e,-1!==(u=s.indexOf(a))?(o=[[1,s.substring(0,u)],[0,a],[1,s.substring(u+a.length)]],e.length>n.length&&(o[0][0]=o[2][0]=t),o):1===a.length?[[t,e],[1,n]]:(c=this.diffHalfMatch(e,n))?(l=c[0],h=c[1],f=c[2],d=c[3],p=c[4],g=this.DiffMain(l,f,r,i),v=this.DiffMain(h,d,r,i),g.concat([[0,p]],v)):r&&e.length>100&&n.length>100?this.diffLineMode(e,n,i):this.diffBisect(e,n,i)):[[t,e]]:[[1,n]]},e.prototype.diffHalfMatch=function(e,t){var n,r,i,o,s,a,u,c,l,f +if(n=e.length>t.length?e:t,r=e.length>t.length?t:e,n.length<4||2*r.length=e.length?[c,l,f,h,s]:null}return i=this,c=h(n,r,Math.ceil(n.length/4)),l=h(n,r,Math.ceil(n.length/2)),c||l?(f=l?c&&c[4].length>l[4].length?c:l:c,e.length>t.length?(o=f[0],u=f[1],a=f[2],s=f[3]):(a=f[0],s=f[1],o=f[2],u=f[3]),[o,u,a,s,f[4]]):null},e.prototype.diffLineMode=function(e,n,r){var i,o,s,a,u,c,l,f,h +for(e=(i=this.diffLinesToChars(e,n)).chars1,n=i.chars2,s=i.lineArray,o=this.DiffMain(e,n,!1,r),this.diffCharsToLines(o,s),this.diffCleanupSemantic(o),o.push([0,""]),a=0,c=0,u=0,f="",l="";a=1&&u>=1){for(o.splice(a-c-u,c+u),a=a-c-u,h=(i=this.DiffMain(f,l,!1,r)).length-1;h>=0;h--)o.splice(a,0,i[h]) +a+=i.length}u=0,c=0,f="",l=""}a++}return o.pop(),o},e.prototype.diffBisect=function(e,n,r){var i,o,s,a,u,c,l,f,h,d,p,g,v,m,y,b,w,x,k,E,_,S,C +for(i=e.length,o=n.length,a=s=Math.ceil((i+o)/2),u=2*s,c=new Array(u),l=new Array(u),f=0;fr);_++){for(S=-_+p;S<=_-g;S+=2){for(b=a+S,k=(w=S===-_||S!==_&&c[b-1]i)g+=2 +else if(k>o)p+=2 +else if(d&&(y=a+h-S)>=0&&y=(x=i-l[y]))return this.diffBisectSplit(e,n,w,k,r)}for(C=-_+v;C<=_-m;C+=2){for(y=a+C,E=(x=C===-_||C!==_&&l[y-1]i)m+=2 +else if(E>o)v+=2 +else if(!d&&(b=a+h-C)>=0&&b=(x=i-x)))return this.diffBisectSplit(e,n,w,k,r)}}return[[t,e],[1,n]]},e.prototype.diffBisectSplit=function(e,t,n,r,i){var o,s,a,u,c,l +return o=e.substring(0,n),a=t.substring(0,r),s=e.substring(n),u=t.substring(r),c=this.DiffMain(o,a,!1,i),l=this.DiffMain(s,u,!1,i),c.concat(l)},e.prototype.diffCleanupSemantic=function(e){for(var n,r,i,o,s=!1,a=[],u=0,c=null,l=0,f=0,h=0,d=0,p=0;l0?a[u-1]:-1,f=0,h=0,d=0,p=0,c=null,s=!0)),l++ +for(s&&this.diffCleanupMerge(e),l=1;l=(o=this.diffCommonOverlap(r,n))?(i>=n.length/2||i>=r.length/2)&&(e.splice(l,0,[0,r.substring(0,i)]),e[l-1][1]=n.substring(0,n.length-i),e[l+1][1]=r.substring(i),l++):(o>=n.length/2||o>=r.length/2)&&(e.splice(l,0,[0,n.substring(0,o)]),e[l-1][0]=1,e[l-1][1]=r.substring(0,r.length-o),e[l+1][0]=t,e[l+1][1]=n.substring(o),l++),l++),l++},e.prototype.diffCommonOverlap=function(e,t){var n=e.length,r=t.length +if(0===n||0===r)return 0 +n>r?e=e.substring(n-r):n1){if(0!==r&&0!==i){var a=this.diffCommonPrefix(s,o) +0!==a&&(n-r-i>0&&0===e[n-r-i-1][0]?e[n-r-i-1][1]+=s.substring(0,a):(e.splice(0,0,[0,s.substring(0,a)]),n++),s=s.substring(a),o=o.substring(a)),0!==(a=this.diffCommonSuffix(s,o))&&(e[n][1]=s.substring(s.length-a)+e[n][1],s=s.substring(0,s.length-a),o=o.substring(0,o.length-a))}0===r?e.splice(n-i,r+i,[1,s]):0===i?e.splice(n-r,r+i,[t,o]):e.splice(n-r-i,r+i,[t,o],[1,s]),n=n-r-i+(r?1:0)+(i?1:0)+1}else 0!==n&&0===e[n-1][0]?(e[n-1][1]+=e[n][1],e.splice(n,1)):n++ +i=0,r=0,o="",s=""}""===e[e.length-1][1]&&e.pop() +var u=!1 +for(n=1;n{"use strict" +var r=n(1996) +e.exports=function(e){function t(e){var t=e?[].concat(e):[] +return t.in_array=r.curry(t,n,t),t.each=r.curry(t,o,t),t.each_async=r.curry(t,s,t),t.collect=r.curry(t,a,t),t.collect_async=r.curry(t,u,t),t.flatten=r.curry(t,i,t),t.inject=r.curry(t,c,t),t.push_all=r.curry(t,l,t),t.fill=r.curry(t,f,t),t.find_all=r.curry(t,h,t),t.find=r.curry(t,d,t),t.last=r.curry(t,p,t),t.naked=r.curry(t,g,t),t}function n(e,t){for(var n=0;n=e.length?n(null,r):void o()}))} +o()}function a(e,n){for(var r=t(),i=0;i{"use strict" +var r=n(7131),i=n(2062),o=n(8090),s=n(1627) +e.exports=function(e,t,n){var a=[] +function u(){return 0===a.length}function c(){return a.length>1&&a[0].score.equals(a[1].score)}function l(){return a.find_all(h).collect(d).join(", ")}function f(e,t){return t.score.compare(e.score)}function h(e){return e.score.equals(a[0].score)}function d(e){return e.macro.toString()}this.validate=function(){return u()?{step:e,valid:!1,reason:"Undefined Step"}:c()?{step:e,valid:!1,reason:"Ambiguous Step (Patterns ["+l()+"] are all equally good candidates)"}:{step:e,valid:!0,winner:this.winner()}},this.clear_winner=function(){if(u())throw new Error("Undefined Step: ["+e+"]") +if(c())throw new Error("Ambiguous Step: ["+e+"]. Patterns ["+l()+"] match equally well.") +return this.winner()},this.winner=function(){return a[0].macro},function(e,t){a=t.collect((function(t){return{macro:t,score:new o([new r(e,t.levenshtein_signature()),new i(t,n)])}})).sort(f)}(e,s(t))}},891:e=>{"use strict" +var t=function(e){this.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp=!0,this.properties={},this.merge=function(e){return e&&e.pTFUHht733hM6wfnruGLgAu6Uqvy7MVp?this.merge(e.properties):new t(this.properties)._merge(e)},this._merge=function(e){for(var t in e)this.properties[t]=e[t] +return this},this._merge(e)} +e.exports=t},6754:(e,t,n)=>{"use strict" +var r=n(1627),i=n(7191),o=n(1234),s=function(e){e=e||"$" +var t={},n=new i(new RegExp("(?:^|[^\\\\])\\"+e+"(\\w+)","g")),a=new RegExp("(\\"+e+"\\w+)"),u=this +function c(t,n){return l(t).each((function(r){if(n.in_array(r))throw new Error("Circular Definition: ["+n.join(", ")+"]") +var i=f(r,n) +return t=t.replace(e+r,i)}))}function l(e){return n.groups(e)}function f(e,n){var r=t[e]?t[e].pattern:"(.+)" +return p(r)?u.expand(r,n.concat(e)).pattern:r}function h(e){return e.toString().replace(/^\/|\/$/g,"")}function d(e){return!!t[e]}function p(e){return n.test(e)}function g(e){return r(e.split(a)).inject(r(),(function(e,n){return e.push_all(p(n)?function(e){return l(e).inject(r(),(function(e,n){return d(n)?e.push_all(t[n].converters):e.push_all(g(f(n,[])))}))}(n):v(n))}))}function v(e){return r().fill(o,m(e))}function m(e){return new RegExp(e+"|").exec("").length-1}this.define=function(e,n,i){if(d(e))throw new Error("Duplicate term: ["+e+"]") +if(i&&p(n))throw new Error("Expandable terms cannot use converters: ["+e+"]") +if(i&&!function(e,t){return function(e){return r(e).inject(0,(function(e,t){return e+t.length-1}))}(e)===m(t)}(i,n))throw new Error("Wrong number of converters for: ["+e+"]") +return p(n)||i||(i=v(n)),t[e]={pattern:h(n),converters:r(i)},this},this.merge=function(t){if(t._prefix()!==this._prefix())throw new Error("Cannot merge dictionaries with different prefixes") +return new s(e)._merge(this)._merge(t)},this._merge=function(e){return e.each((function(e,t){u.define(e,t.pattern)})),this},this._prefix=function(){return e},this.each=function(e){for(var n in t)e(n,t[n])},this.expand=function(e,t){var n=h(e) +return p(n)?{pattern:c(n,r(t)),converters:g(n)}:{pattern:n,converters:g(n)}}} +e.exports=s},1235:(e,t,n)=>{"use strict" +var r=n(1627),i=n(1996),o=new function(){var e=r() +this.send=function(e,n,r){return 1===arguments.length?this.send(e,{}):2===arguments.length&&i.is_function(n)?this.send(e,{},n):(t(e,n),r&&r(),this)},this.on=function(t,n){return e.push({pattern:t,callback:n}),this} +var t=function(e,t){n(e).each((function(n){n({name:e,data:t})}))},n=function(t){return e.find_all((function(e){return new RegExp(e.pattern).test(t)})).collect((function(e){return e.callback}))}} +e.exports={instance:function(){return o},ON_SCENARIO:"__ON_SCENARIO__",ON_STEP:"__ON_STEP__",ON_EXECUTE:"__ON_EXECUTE__",ON_DEFINE:"__ON_DEFINE__"}},5748:(e,t,n)=>{"use strict" +var r=n(29),i=function(e){this.constructor(e,/.*\.(?:feature|spec|specification)$/)} +i.prototype=new r,e.exports=i},29:(e,t,n)=>{"use strict" +var r=n(4061),i=r.path,o=r.fs,s=n(1627) +e.exports=function(e,t){t=t||/.*/,this.each=function(e){this.list().forEach(e)},this.list=function(){return s(e).inject(s(),(function(e,t){return e.concat(n(t).find_all(f))}))} +var n=function(e){return s(r(e).concat(a(e)))},r=function(e){return u(e).find_all(c)},a=function(e){return u(e).find_all(l).inject(s(),(function(e,t){return e.concat(n(t))}))},u=function(e){return o.existsSync(e)?s(o.readdirSync(e)).collect((function(t){return i.join(e,t)})):s()},c=function(e){return!l(e)},l=function(e){return o.statSync(e).isDirectory()},f=function(e){return s(t).find((function(t){return new RegExp(t).test(e)}))}}},7774:(e,t,n)=>{"use strict" +var r=n(2880),i=n(891),o=n(1235),s=n(1627),a=n(1996) +e.exports=function(e){e=s(e) +var t,n=o.instance(),u=this +function c(e){return!e.valid}function l(e){return e.step+(e.valid?"":" <-- "+e.reason)}this.requires=function(t){return e.push_all(t),this},this.validate=function(e){var n=s(e).collect((function(e){var n=u.rank_macros(e).validate() +return t=n.winner,n})) +if(n.find(c))throw new Error("Scenario cannot be interpreted\n"+n.collect(l).join("\n"))},this.interpret=function(e,t,r){t=(new i).merge(t),n.send(o.ON_SCENARIO,{scenario:e,ctx:t.properties}) +var a=f(t,r) +s(e).each_async(a,r)} +var f=function(e,t){var n=function(t,n,r){u.interpret_step(t,e,r)} +return t?n:a.asynchronize(null,n)} +this.interpret_step=function(e,r,s){var a=(new i).merge(r) +n.send(o.ON_STEP,{step:e,ctx:a.properties}) +var u=this.rank_macros(e).clear_winner() +t=u,u.interpret(e,a||{},s)},this.rank_macros=function(e){return new r(e,h(e),t)} +var h=function(t){return e.inject([],(function(e,n){return e.concat(n.find_compatible_macros(t))}))}}},5798:(e,t,n)=>{"use strict" +var r=n(1483),i=n(6754),o=n(1627) +e.exports=function(e){e=e||new i +var t=o(),n=this +this.define=function(e,t,n,r){return o(e).each((function(e){s(e,t,n,r)})),this} +var s=function(i,o,s,a){if(n.get_macro(i))throw new Error("Duplicate macro: ["+i+"]") +t.push(new r(i,e.expand(i),o,s,n,a))} +this.get_macro=function(e){return t.find((function(t){return t.is_identified_by(e)}))},this.find_compatible_macros=function(e){return t.find_all((function(t){return t.can_interpret(e)}))}}},1483:(e,t,n)=>{"use strict" +var r=n(1996),i=n(1627),o=n(891),s=n(7191),a=n(1235) +e.exports=function(e,t,n,u,c,l){e=p(e) +var f=new s(t.pattern),h=(n=n||r.async_noop,a.instance()) +function d(e){return l.mode?"sync"===l.mode:n!==r.async_noop&&n.length!==e.length+1}function p(e){return new RegExp(e).toString()}l=l||{},this.library=c,this.is_identified_by=function(t){return e===p(t)},this.can_interpret=function(e){return f.test(e)},this.interpret=function(e,s,c){var p=new o({step:e}).merge(u).merge(s) +!function(e,n){var r=0 +i(t.converters).collect((function(t){return function(n){t.apply(null,e.slice(r,r+=t.length-1).concat(n))}})).collect_async((function(e,t,n){e(n)}),n)}(f.groups(e),(function(t,i){if(t)return c(t) +var o +h.send(a.ON_EXECUTE,{step:e,ctx:p.properties,pattern:f.toString(),args:i}) +try{o=r.invoke(n,p.properties,d(i)?i:i.concat(c))}catch(t){if(c)return c(t) +throw t}return function(e){return l.mode?"promise"===l.mode:e&&e.then}(o)?o.then(r.noargs(c)).catch(c):d(i)?c&&c():void 0}))},this.is_sibling=function(e){return e&&e.defined_in(c)},this.defined_in=function(e){return c===e},this.levenshtein_signature=function(){return f.without_expressions()},this.toString=function(){return e},h.send(a.ON_DEFINE,{signature:e,pattern:f.toString()})}},6947:(e,t,n)=>{"use strict" +e.exports=function(){function e(){return"undefined"!=typeof process&&void 0!==n.g&&!0}function t(){return"undefined"!=typeof window}function r(){return"undefined"!=typeof phantom}return{get_container:function(){return t()?window:r()?phantom:e()?n.g:void 0},is_node:e,is_browser:t,is_phantom:r,is_karma:function(){return"undefined"!=typeof window&&void 0!==window.__karma__}}}},7191:(e,t,n)=>{"use strict" +var r=n(1627) +e.exports=function(e){var t=/(^|[^\\\\])\(.*?\)/g,n=/(^|[^\\\\])\[.*?\]/g,i=/(^|[^\\\\])\{.*?\}/g,o=/(^|[^\\\\])\\./g,s=/[^\w\s]/g,a=new RegExp(e) +this.test=function(e){var t=a.test(e) +return this.reset(),t},this.groups=function(e){for(var t=r(),n=a.exec(e);n;){var i=n.slice(1,n.length) +t.push(i),n=a.global&&a.exec(e)}return this.reset(),t.flatten()},this.reset=function(){return a.lastIndex=0,this},this.without_expressions=function(){return a.source.replace(t,"$1").replace(n,"$1").replace(i,"$1").replace(o,"$1").replace(s,"")},this.equals=function(e){return this.toString()===e.toString()},this.toString=function(){return"/"+a.source+"/"}}},3575:e=>{"use strict" +e.exports={trim:function(e){return e.replace(/^\s+|\s+$/g,"")},rtrim:function(e){return e.replace(/\s+$/g,"")},isBlank:function(e){return/^\s*$/g.test(e)},isNotBlank:function(e){return!this.isBlank(e)},indentation:function(e){var t=/^(\s*)/.exec(e) +return t&&t[0].length||0}}},1481:(e,t,n)=>{"use strict" +var r=n(7774),i=n(891),o=n(1996),s=function(e,t){if(!(this instanceof s))return new s(e,t) +this.interpreter=new r(e),this.requires=function(e){return this.interpreter.requires(e),this},this.yadda=function(e,n,r){return 0===arguments.length?this:2===arguments.length&&o.is_function(n)?this.yadda(e,{},n):(this.interpreter.validate(e),void this.interpreter.interpret(e,(new i).merge(t).merge(n),r))},this.run=this.yadda,this.toString=function(){return"Yadda 2.2.0 Copyright 2010 Stephen Cresswell"}} +e.exports=s},4636:e=>{"use strict" +e.exports=function(e,t){var n=Date.parse(e) +return isNaN(n)?t(new Error("Cannot convert ["+e+"] to a date")):t(null,new Date(n))}},2066:e=>{"use strict" +e.exports=function(e,t){var n=parseFloat(e) +return isNaN(n)?t(new Error("Cannot convert ["+e+"] to a float")):t(null,n)}},9627:(e,t,n)=>{"use strict" +e.exports={date:n(4636),integer:n(9858),float:n(2066),list:n(9999),table:n(4084),pass_through:n(1234)}},9858:e=>{"use strict" +e.exports=function(e,t){var n=parseInt(e) +return isNaN(n)?t(new Error("Cannot convert ["+e+"] to an integer")):t(null,n)}},9999:e=>{"use strict" +e.exports=function(e,t){return t(null,e.split(/\n/))}},1234:e=>{"use strict" +e.exports=function(e,t){return t(null,e)}},4084:(e,t,n)=>{"use strict" +var r=n(1627),i=n(3575),o=/[\|\u2506]/,s=/^[\|\u2506]|[\|\u2506]$/g,a=/^[\\|\u2506]?-{3,}/ +e.exports=function(e,t){var n,u=e.split(/\n/),c=(n=u.shift(),r(n.replace(s,"").split(o)).collect((function(e){return{text:i.trim(e),indentation:i.indentation(e)}})).naked()),l=h(u[0])?function(e){if(h(e))return d() +p(e)}:function(e){if(h(e))throw new Error("Dashes are unexpected at this time") +d(),p(e)},f=r() +try{r(u).each(l),t(null,function(e){return e.collect((function(e){var t={} +for(var n in e)t[n]=e[n].join("\n") +return t})).naked()}(f))}catch(e){t(e)}function h(e){return a.test(e)}function d(){f.push({})}function p(e){var t=f.last() +r(e.replace(s,"").split(o)).each((function(e,n){var r=c[n].text,o=c[n].indentation,s=i.rtrim(e.substr(o)) +if(i.isNotBlank(e)&&i.indentation(e){"use strict" +e.exports=function(){var e=Array.prototype.slice +function t(){}function n(t,n){return function(){var r=e.call(arguments,arguments.length-1)[0],i=e.call(arguments,0,arguments.length-2) +n.apply(t,i),r&&r()}}return{noop:t,noargs:function(e){return function(){return e()}},async_noop:n(null,t),asynchronize:n,is_function:function(e){return e&&"[object Function]"==={}.toString.call(e)},curry:function(t,n){var r=e.call(arguments,2) +return function(){return n.apply(t,r.concat(e.call(arguments)))}},invoke:function(e,t,n){return e.apply(t,n)}}}()},2216:(e,t,n)=>{"use strict" +var r={Yadda:n(1481),EventBus:n(1235),Interpreter:n(7774),Context:n(891),Library:n(5798),Dictionary:n(6754),FeatureFileSearch:n(5748),FileSearch:n(29),Platform:n(6947),localisation:n(7679),converters:n(9627),parsers:n(1979),plugins:n(6827),shims:n(4061),createInstance:function(){return r.Yadda.apply(null,Array.prototype.slice.call(arguments,0))}} +e.exports=r},6404:(e,t,n)=>{"use strict" +var r=n(6767) +e.exports=new r("Chinese",{feature:"[Ff]eature|功能",scenario:"(?:[Ss]cenario|[Ss]cenario [Oo]utline|场景|剧本|(?:场景|剧本)?大纲)",examples:"(?:[Ee]xamples|[Ww]here|例子|示例|举例|样例)",pending:"(?:[Pp]ending|[Tt]odo|待定|待做|待办|暂停|暂缓)",only:"(?:[Oo]nly|仅仅?)",background:"[Bb]ackground|背景|前提",given:"(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept|假如|假设|假定|并且|而且|同时|但是)",when:"(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut|当|如果|并且|而且|同时|但是)",then:"(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut|那么|期望|并且|而且|同时|但是)",_steps:["given","when","then"]})},3399:(e,t,n)=>{"use strict" +var r=n(6767) +e.exports=new r("Dutch",{feature:"(?:[Ff]eature|[Ff]unctionaliteit|[Ee]igenschap)",scenario:"(?:[Ss]cenario|[Gg|eval)",examples:"(?:[Vv]oorbeelden?)",pending:"(?:[Tt]odo|[Mm]oet nog)",only:"(?:[Aa]lleen)",background:"(?:[Aa]chtergrond)",given:"(?:[Ss]tel|[Gg]egeven(?:\\sdat)?|[Ee]n|[Mm]aar)",when:"(?:[Aa]ls|[Ww]anneer|[Ee]n|[Mm]aar)",then:"(?:[Dd]an|[Vv]ervolgens|[Ee]n|[Mm]aar)",_steps:["given","when","then"]})},1447:(e,t,n)=>{"use strict" +var r=n(6767) +e.exports=new r("English",{feature:"[Ff]eature",scenario:"(?:[Ss]cenario|[Ss]cenario [Oo]utline)",examples:"(?:[Ee]xamples|[Ww]here)",pending:"(?:[Pp]ending|[Tt]odo)",only:"(?:[Oo]nly)",background:"[Bb]ackground",given:"(?:[Gg]iven|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)",when:"(?:[Ww]hen|[Ii]f|[Aa]nd|[Bb]ut)",then:"(?:[Tt]hen|[Ee]xpect|[Aa]nd|[Bb]ut)",_steps:["given","when","then"]})},7226:(e,t,n)=>{"use strict" +var r=n(6767) +e.exports=new r("French",{feature:"(?:[Ff]onctionnalité)",scenario:"(?:[Ss]cénario|[Pp]lan [Dd]u [Ss]cénario)",examples:"(?:[Ee]xemples|[Ee]xemple|[Oo][uù])",pending:"(?:[Ee]n attente|[Ee]n cours|[Tt]odo)",only:"(?:[Ss]eulement])",background:"(?:[Cc]ontexte)",given:"(?:[Ss]oit|[ÉéEe]tant données|[ÉéEe]tant donnée|[ÉéEe]tant donnés|[ÉéEe]tant donné|[Aa]vec|[Ee]t|[Mm]ais|[Aa]ttendre)",when:"(?:[Qq]uand|[Ll]orsqu'|[Ll]orsque|[Ss]i|[Ee]t|[Mm]ais)",then:"(?:[Aa]lors|[Aa]ttendre|[Ee]t|[Mm]ais)",_steps:["given","when","then","soit","etantdonnees","etantdonnee","etantdonne","quand","lorsque","alors"],get soit(){return this.given},get etantdonnees(){return this.given},get etantdonnee(){return this.given},get etantdonne(){return this.given},get quand(){return this.when},get lorsque(){return this.when},get alors(){return this.then}})},5805:(e,t,n)=>{"use strict" +var r=n(6767) +e.exports=new r("German",{feature:"(?:[Ff]unktionalität|[Ff]eature|[Aa]spekt|[Uu]secase|[Aa]nwendungsfall)",scenario:"(?:[Ss]zenario|[Ss]zenario( g|G)rundriss|[Gg]eschehnis)",examples:"(?:[Bb]eispiele?)",pending:"(?:[Tt]odo|[Oo]ffen)",only:"(?:[Nn]ur|[Ee]inzig)",background:"(?:[Gg]rundlage|[Hh]intergrund|[Ss]etup|[Vv]orausgesetzt)",given:"(?:[Aa]ngenommen|[Gg]egeben( sei(en)?)?|[Mm]it|[Uu]nd|[Aa]ber|[Aa]ußer)",when:"(?:[Ww]enn|[Ff]alls|[Uu]nd|[Aa]ber)",then:"(?:[Dd]ann|[Ff]olglich|[Aa]ußer|[Uu]nd|[Aa]ber)",_steps:["given","when","then"]})},6767:(e,t,n)=>{"use strict" +var r=n(5798),i=n(1627) +e.exports=function(e,t){var n=this +this.is_language=!0,this.library=function(e){return n.localise_library(new r(e))},this.localise_library=function(e){return i(t._steps).each((function(t){e[t]=function(r,s,a,u){return i(r).each((function(r){return r=o(n.localise(t),r),e.define(r,s,a,u)}))}})),e} +var o=function(e,t){var n=new RegExp("^/|/$","g"),r=new RegExp(/^(?:\^)?/) +return t.toString().replace(n,"").replace(r,"^(?:\\s)*"+e+"\\s+")} +this.localise=function(n){if(void 0===t[n])throw new Error('Keyword "'+n+'" has not been translated into '+e+".") +return t[n]}}},683:(e,t,n)=>{"use strict" +var r=n(6767) +e.exports=new r("Norwegian",{feature:"[Ee]genskap",scenario:"[Ss]cenario",examples:"[Ee]ksempler",pending:"[Aa]vventer",only:"[Bb]are",background:"[Bb]akgrunn",given:"(?:[Gg]itt|[Mm]ed|[Oo]g|[Mm]en|[Uu]nntatt)",when:"(?:[Nn]år|[Oo]g|[Mm]en)",then:"(?:[Ss]å|[Ff]forvent|[Oo]g|[Mm]en)",_steps:["given","when","then","gitt","når","så"],get gitt(){return this.given},get"når"(){return this.when},get"så"(){return this.then}})},3411:(e,t,n)=>{"use strict" +var r=n(6767) +e.exports=new r("Pirate",{feature:"(?:[Tt]ale|[Yy]arn)",scenario:"(?:[Aa]dventure|[Ss]ortie)",examples:"[Ww]herest",pending:"[Bb]rig",only:"[Bb]lack [Ss]pot",background:"[Aa]ftground",given:"(?:[Gg]iveth|[Ww]ith|[Aa]nd|[Bb]ut|[Ee]xcept)",when:"(?:[Ww]hence|[Ii]f|[Aa]nd|[Bb]ut)",then:"(?:[Tt]hence|[Ee]xpect|[Aa]nd|[Bb]ut)",_steps:["given","when","then","giveth","whence","thence"],get giveth(){return this.given},get whence(){return this.when},get thence(){return this.then}})},8617:(e,t,n)=>{"use strict" +var r=n(6767) +e.exports=new r("Polish",{feature:"(?:[Ww]łaściwość|[Ff]unkcja|[Aa]spekt|[Pp]otrzeba [Bb]iznesowa)",scenario:"(?:[Ss]cenariusz|[Ss]zablon [Ss]cenariusza)",examples:"[Pp]rzykłady",pending:"(?:[Oo]czekujący|[Nn]iezweryfikowany|[Tt]odo)",only:"[Tt]ylko",background:"[Zz]ałożenia",given:"(?:[Zz]akładając|[Mm]ając|[Oo]raz|[Ii]|[Aa]le)",when:"(?:[Jj]eżeli|[Jj]eśli|[Gg]dy|[Kk]iedy|[Oo]raz|[Ii]|[Aa]le)",then:"(?:[Ww]tedy|[Oo]raz|[Ii]|[Aa]le)",_steps:["given","when","then","zakladajac","majac","jezeli","jesli","gdy","kiedy","wtedy"],get zakladajac(){return this.given},get majac(){return this.given},get jezeli(){return this.when},get jesli(){return this.when},get gdy(){return this.when},get kiedy(){return this.when},get wtedy(){return this.then}})},7291:(e,t,n)=>{"use strict" +var r=n(6767) +e.exports=new r("Portuguese",{feature:"(?:[Ff]uncionalidade|[Cc]aracter[íi]stica)",scenario:"(?:[Cc]en[aá]rio|[Cc]aso)",examples:"(?:[Ee]xemplos|[Ee]xemplo)",pending:"[Pp]endente",only:"[S][óo]",background:"[Ff]undo",given:"(?:[Ss]eja|[Ss]ejam|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas|[Ee]|[Mm]as)",when:"(?:[Qq]uando|[Ss]e|[Qq]ue|[Ee]|[Mm]as)",then:"(?:[Ee]nt[aã]o|[Ee]|[Mm]as)",_steps:["given","when","then","seja","sejam","dado","dada","dados","dadas","quando","se","entao"],get seja(){return this.given},get sejam(){return this.given},get dado(){return this.given},get dada(){return this.given},get dados(){return this.given},get dadas(){return this.given},get quando(){return this.when},get se(){return this.when},get entao(){return this.then}})},342:(e,t,n)=>{"use strict" +var r=n(6767) +e.exports=new r("Russian",{feature:"(?:[Фф]ункция|[Фф]ункционал|[Сс]войство)",scenario:"Сценарий",examples:"Примеры?",pending:"(?:[Ww]ip|[Tt]odo)",only:"Только",background:"(?:[Пп]редыстория|[Кк]онтекст)",given:"(?:[Дд]опустим|[Дд]ано|[Пп]усть|[Ии]|[Н]о)(?:\\s[Яя])?",when:"(?:[Ее]сли|[Кк]огда|[Ии]|[Н]о)(?:\\s[Яя])?",then:"(?:[Тт]о|[Тт]огда|[Ии]|[Н]о)(?:\\s[Яя])?",_steps:["given","when","then"]})},7202:(e,t,n)=>{"use strict" +var r=n(6767) +e.exports=new r("Spanish",{feature:"(?:[Ff]uncionalidad|[Cc]aracterística)",scenario:"(?:[Ee]scenario|[Cc]aso)",examples:"(?:[Ee]jemplos|[Ee]jemplo)",pending:"[Pp]endiente",only:"[S]ólo",background:"[Ff]ondo",given:"(?:[Ss]ea|[Ss]ean|[Dd]ado|[Dd]ada|[Dd]ados|[Dd]adas)",when:"(?:[Cc]uando|[Ss]i|[Qq]ue)",then:"(?:[Ee]ntonces)",_steps:["given","when","then","sea","sean","dado","dada","dados","dadas","cuando","si","entonces"],get sea(){return this.given},get sean(){return this.given},get dado(){return this.given},get dada(){return this.given},get dados(){return this.given},get dadas(){return this.given},get cuando(){return this.when},get si(){return this.when},get entonces(){return this.then}})},3845:(e,t,n)=>{"use strict" +var r=n(6767) +e.exports=new r("Ukrainian",{feature:"(?:[Фф]ункція|[Фф]ункціонал|[Пп]отреба|[Аа]спект|[Оо]собливість|[Вв]ластивість)",scenario:"(?:[Сс]ценарій|[Шш]аблон)",examples:"[Пп]риклади",pending:"(?:[Нн]еперевірений|[Чч]екаючий|[Pp]ending|[Tt]odo)",only:"[Тт]ільки",background:"[Кк]онтекст",given:"(?:[Дд]ано|[Пп]ри|[Нн]ехай|[Іі]|[Тт]а|[Аа]ле)",when:"(?:[Яя]кщо|[Дд]е|[Кк]оли|[Іі]|[Тт]а|[Аа]ле)",then:"(?:[Тт]оді|[Іі]|[Тт]а|[Аа]ле)",_steps:["given","when","then"]})},7679:(e,t,n)=>{"use strict" +e.exports={Chinese:n(6404),English:n(1447),French:n(7226),German:n(5805),Dutch:n(3399),Norwegian:n(683),Pirate:n(3411),Ukrainian:n(3845),Polish:n(8617),Spanish:n(7202),Russian:n(342),Portuguese:n(7291),default:n(1447),Language:n(6767)}},691:(e,t,n)=>{"use strict" +e.exports=function(e){var t=n(4061).fs,r=new(n(5968))(e) +this.parse=function(e,n){var i=t.readFileSync(e,"utf8"),o=r.parse(i) +return n&&n(o)||o}}},5968:(e,t,n)=>{"use strict" +var r=n(1627),i=n(1996),o=n(3575),s=n(7679) +e.exports=function(e){var t,n,a={language:s.default,leftPlaceholderChar:"[",rightPlaceholderChar:"]"},u=(e=e&&e.is_language?{language:e}:e||a).language||a.language,c=e.leftPlaceholderChar||a.leftPlaceholderChar,l=e.rightPlaceholderChar||a.rightPlaceholderChar,f=new RegExp("^\\s*"+u.localise("feature")+":\\s*(.*)","i"),h=new RegExp("^\\s*"+u.localise("scenario")+":\\s*(.*)","i"),d=new RegExp("^\\s*"+u.localise("background")+":\\s*(.*)","i"),p=new RegExp("^\\s*"+u.localise("examples")+":","i"),g=new RegExp("^(.*)$","i"),v=new RegExp("^\\s*#"),m=new RegExp("^\\s*#{3,}"),y=new RegExp("^(\\s*)$"),b=new RegExp("(^\\s*[\\|┆]?-{3,})"),w=new RegExp("^\\s*@([^=]*)$"),x=new RegExp("^\\s*@([^=]*)=(.*)$") +function k(e,r){var i,s=r+1 +try{if(i=m.test(e))return n=!n +if(n)return +if(i=v.test(e))return +if(i=w.exec(e))return t.handle("Annotation",{key:o.trim(i[1]),value:!0},s) +if(i=x.exec(e))return t.handle("Annotation",{key:o.trim(i[1]),value:o.trim(i[2])},s) +if(i=f.exec(e))return t.handle("Feature",i[1],s) +if(i=h.exec(e))return t.handle("Scenario",i[1],s) +if(i=d.exec(e))return t.handle("Background",i[1],s) +if(i=p.exec(e))return t.handle("Examples",s) +if(i=y.exec(e))return t.handle("Blank",i[0],s) +if(i=b.exec(e))return t.handle("Dash",i[1],s) +if(i=g.exec(e))return t.handle("Text",i[1],s)}catch(t){throw t.message="Error parsing line "+s+', "'+e+'".\nOriginal error was: '+t.message,t}}this.parse=function(e,i){return t=new _,n=!1,function(e){return r(e.split(/\r\n|\n/))}(e).each(k),i&&i(t.export())||t.export()} +var E=function(e){e=e||{},this.register=function(t,n){e[t]=n},this.unregister=function(){r(Array.prototype.slice.call(arguments)).each((function(t){delete e[t]}))},this.find=function(t){if(!e[t.toLowerCase()])throw new Error(t+" is unexpected at this time") +return{handle:e[t.toLowerCase()]}}},_=function(){var e,t=this,n=new S,r=new E({text:i.noop,blank:i.noop,annotation:function(e,t){r.unregister("background"),n.stash(t.key,t.value)},feature:function(t,r){return e=new C(r,n,new S)},scenario:o,background:s}) +function o(t,r,i){return(e=new C(r,new S,n)).on(t,r,i)}var s=o +this.handle=function(e,n,r){t=t.on(e,n,r)},this.on=function(e,t,n){return r.find(e).handle(e,t,n)||this},this.export=function(){if(!e)throw new Error("A feature must contain one or more scenarios") +return e.export()}},S=function(){var e={} +this.stash=function(t,n){if(/\s/.test(t))throw new Error("Invalid annotation: "+t) +e[t.toLowerCase()]=n},this.export=function(){return e}},C=function(e,t,n){var s=[],a=[],u=new j,c=new E({text:function(e,t){s.push(o.trim(t))},blank:i.noop,annotation:function(e,t){c.unregister("background","text"),n.stash(t.key,t.value)},scenario:function(e,t){var r=new N(t,u,n,l) +return a.push(r),n=new S,r},background:function(e,t){return u=new T(t,l),n=new S,u}}),l=this +this.on=function(e,t,n){return c.find(e).handle(e,t,n)||this},this.export=function(){return function(){if(0===a.length)throw new Error("Feature requires one or more scenarios")}(),{title:e,annotations:t.export(),description:s,scenarios:r(a).collect((function(e){return e.export()})).flatten().naked()}}},T=function(e,t){var n=[],r=[],s=0,a=new E({text:u,blank:i.noop,annotation:v,scenario:m}) +function u(e,t,r){a.register("dash",c),n.push(o.trim(t))}function c(e,t,n){a.unregister("dash","annotation","scenario"),a.register("text",l),a.register("blank",h),s=o.indentation(t)}function l(e,t,n){a.register("dash",p),a.register("text",f),a.register("blank",h),a.register("annotation",v),a.register("scenario",m),g(t,"\n")}function f(e,t,n){d(),g(t,"\n")}function h(e,t,n){r.push(t)}function d(){r.length&&(g(r.join("\n"),"\n"),r=[])}function p(e,t,n){a.unregister("dash"),a.register("text",u),a.register("blank",i.noop),d()}function g(e,t){if(o.isNotBlank(e)&&o.indentation(e)=0?"┆":"|",i=r(e.split(n)) +if(void 0!==t&&t!==i.length)throw new Error("Incorrect number of fields in example table. Expected "+t+" but found "+i.length) +return i}function w(t,n,r){return x(),e.on(t,n,r)}function x(){if(0===t.length)throw new Error("Examples table requires one or more headings") +if(0===n.length)throw new Error("Examples table requires one or more rows")}function k(){var e={} +return r(Array.prototype.slice.call(arguments)).each((function(t){for(var n in t)e[n]=t[n]})),e}function _(e,t){return r(t).collect((function(t){return C(e,t)})).naked()}function C(e,t){for(var n in e)t=t.replace(new RegExp("\\"+c+"\\s*"+n+"\\s*\\"+l,"g"),o.rtrim(e[n].join("\n"))) +return t}this.on=function(e,t,n){return a.find(e).handle(e,t,n)||this},this.expand=function(e){return x(),n.collect((function(t){return{title:C(t.fields,e.title),annotations:k(t.annotations.export(),e.annotations),description:_(t,e.description),steps:_(t.fields,e.steps)}})).naked()}}}},4245:(e,t,n)=>{"use strict" +var r=n(1627) +e.exports=function(){var e=/[^\s]/ +this.parse=function(e,r){var i=t(e).find_all(n) +return r&&r(i)||i} +var t=function(e){return r(e.split(/\n/))},n=function(t){return t&&e.test(t)}}},1979:(e,t,n)=>{"use strict" +e.exports={StepParser:n(4245),FeatureParser:n(5968),FeatureFileParser:n(691)}},5807:(e,t,n)=>{"use strict" +if(!(e=n.nmd(e)).client){var r=n(4061).fs +n.g.process=n.g.process||{cwd:function(){return r.workingDirectory}}}e.exports=function(e,t){var r=n(2216).EventBus +e.interpreter.interpret_step=function(e,n,i){var o=this +t.then((function(){t.test.info(e),r.instance().send(r.ON_STEP,{step:e,ctx:n}),o.rank_macros(e).clear_winner().interpret(e,n,i)}))},t.yadda=function(t,n){if(void 0===t)return this +e.run(t,n)}}},6827:(e,t,n)=>{"use strict" +e.exports={casper:n(5807),mocha:{ScenarioLevelPlugin:n(1908),StepLevelPlugin:n(809)},get jasmine(){return this.mocha}}},1034:(e,t,n)=>{"use strict" +var r=n(7679),i=n(6947),o=n(691),s=n(1627) +e.exports.create=function(e){var t=new i,n=e.language||r.default,a=e.parser||new o(e),u=e.container||t.get_container() +function c(e,t){s(e).each((function(e){l(e.title,e,t)}))}function l(e,t,n){var r;(h(r=t.annotations,"pending")?u.xdescribe:h(r,"only")?u.describe.only||u.fdescribe||u.ddescribe:u.describe)(e,(function(){n(t)}))}function f(e,t){return h(e,"pending")?u.xit:h(e,"only")?u.it.only||u.fit||u.iit:u.it}function h(e,t){var r=new RegExp("^"+n.localise(t)+"$","i") +for(var i in e)if(r.test(i))return!0}return{featureFiles:function(e,t){s(e).each((function(e){c(a.parse(e),t)}))},features:c,describe:l,it_async:function(e,t,n){f(t.annotations)(e,(function(e){n(this,t,e)}))},it_sync:function(e,t,n){f(t.annotations)(e,(function(){n(this,t)}))}}}},1908:(e,t,n)=>{"use strict" +var r=n(1627),i=n(6947),o=n(1034) +e.exports.init=function(e){e=e||{} +var t=new i,n=e.container||t.get_container(),s=o.create(e) +n.featureFiles=n.featureFile=s.featureFiles,n.features=n.feature=s.features,n.scenarios=n.scenario=function(e,t){r(e).each((function(e){(1===t.length?s.it_sync:s.it_async)(e.title,e,(function(e,n,r){t(n,r)}))}))}}},809:(e,t,n)=>{"use strict" +var r=n(1627),i=n(6947),o=n(1034) +e.exports.init=function(e){e=e||{} +var t=new i,n=e.container||t.get_container(),s=o.create(e) +n.featureFiles=n.featureFile=s.featureFiles,n.features=n.feature=s.features,n.scenarios=n.scenario=function(e,t){r(e).each((function(e){s.describe(e.title,e,t)}))},n.steps=function(e,t){var n=!1 +function i(e,t){s.it_async(e,e,(function(e,r,i){if(n)return e.skip?e.skip():i() +n=!0,t.bind(e)(r,(function(e){if(e)return(i.fail||i)(e) +n=!1,i()}))}))}function o(e,t){s.it_sync(e,e,(function(e,r){if(n)return e.skip&&e.skip() +n=!0,t.bind(e)(r),n=!1}))}r(e).each((function(e){(1===t.length?o:i)(e,t)}))}}},7131:e=>{"use strict" +e.exports=function(e,t){var n +this.value,this.type="LevenshteinDistanceScore" +var r=this +this.compare=function(e){return e.value-this.value},this.equals=function(e){return!!e&&this.type===e.type&&this.value===e.value},function(){var r=e.length,i=t.length +n=new Array(r+1) +for(var o=0;o<=r;o++)n[o]=new Array(i+1) +for(o=0;o<=r;o++)for(var s=0;s<=i;s++)n[o][s]=0 +for(o=0;o<=r;o++)n[o][0]=o +for(s=0;s<=i;s++)n[0][s]=s}(),function(){if(e===t)return r.value=0 +for(var i=0;i{"use strict" +var r=n(1627) +e.exports=function(e){this.scores=r(e),this.type="MultiScore",this.compare=function(e){for(var t=0;t{"use strict" +e.exports=function(e,t){this.value=e.is_sibling(t)?1:0,this.type="SameLibraryScore",this.compare=function(e){return this.value-e.value},this.equals=function(e){return!!e&&this.type===e.type&&this.value===e.value}}},4061:(e,t,n)=>{"use strict" +var r,i,o=n(6947) +e.exports=(i={node:function(){return{fs:n(9265),path:n(3642),process:process}},phantom:function(){return{fs:n(8091),path:n(6656),process:n(4661)}},karma:function(){return{fs:n(1702),path:n(8104),process:n(5917)}}},(r=new o).is_phantom()?i.phantom():r.is_browser()&&r.is_karma()?i.karma():r.is_node()?i.node():{})},1702:(e,t,n)=>{e.exports=function(){"use strict" +var e=n(8104) +function t(t){return e.resolve(e.normalize(t.split("\\").join("/")))}var r=function(){this.registry=new i,this.converter=new o("/base/","/"),this.reader=new s(this.converter) +var e=Object.keys(window.__karma__.files) +this.converter.parseUris(e).forEach(this.registry.addFile,this.registry)} +r.prototype={constructor:r,workingDirectory:"/",existsSync:function(e){return this.registry.exists(e)},readdirSync:function(e){return this.registry.getContent(e)},statSync:function(e){return{isDirectory:function(){return this.registry.isDirectory(e)}.bind(this)}},readFileSync:function(e,t){if("utf8"!==t)throw new Error("This fs.readFileSync() shim does not support other than utf8 encoding.") +if(!this.registry.isFile(e))throw new Error("File does not exist: "+e) +return this.reader.readFile(e)}} +var i=function(){this.paths={}} +i.prototype={constructor:i,addFile:function(n){n=t(n),this.paths[n]=i.TYPE_FILE +var r=e.dirname(n) +this.addDirectory(r)},addDirectory:function(n){n=t(n),this.paths[n]=i.TYPE_DIRECTORY +var r=e.dirname(n) +r!==n&&this.addDirectory(r)},isFile:function(e){return e=t(e),this.exists(e)&&this.paths[e]===i.TYPE_FILE},isDirectory:function(e){return e=t(e),this.exists(e)&&this.paths[e]===i.TYPE_DIRECTORY},exists:function(e){return e=t(e),this.paths.hasOwnProperty(e)},getContent:function(n){if(!this.isDirectory(n))throw new Error("Not a directory: "+n) +return n=t(n),Object.keys(this.paths).filter((function(t){return t!==n&&e.dirname(t)===n}),this).map((function(t){return e.basename(t)}))}},i.TYPE_FILE=0,i.TYPE_DIRECTORY=1 +var o=function(e,t){this.workingDirectory=t,this.workingDirectoryPattern=this.patternFromBase(t),this.baseUri=e,this.baseUriPattern=this.patternFromBase(e)} +o.prototype={constructor:o,patternFromBase:function(e,t){var n="^"+e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&") +return new RegExp(n,t)},parseUris:function(e){return e.filter((function(e){return this.baseUriPattern.test(e)}),this).map((function(e){return e.replace(this.baseUriPattern,this.workingDirectory)}),this)},buildUri:function(e){if(e=t(e),!this.workingDirectoryPattern.test(e))throw new Error("Path is not in working directory: "+e) +return e.replace(this.workingDirectoryPattern,this.baseUri)}} +var s=function(e){this.converter=e} +return s.prototype={constructor:s,readFile:function(e){var t=this.converter.buildUri(e),n=new XMLHttpRequest +return n.open("get",t,!1),n.send(),n.responseText}},new r}()},8104:(e,t,n)=>{e.exports=function(){"use strict" +var e={} +try{e=n(3642)}catch(e){throw new Error("The environment does not support the path module, it's probably not using browserify.")}if("function"!=typeof e.normalize||"function"!=typeof e.dirname)throw new Error("The path module emulation does not contain implementations of required functions.") +return e}()},5917:(e,t,n)=>{e.exports=function(){"use strict" +var e=n(1702) +return{cwd:function(){return e.workingDirectory}}}()},8091:(e,t,n)=>{"use strict";(e=n.nmd(e)).exports=function(){if(e.client)return{} +var t=n(9265) +return t.existsSync=t.existsSync||t.exists,t.readdirSync=t.readdirSync||function(e){return t.list(e).filter((function(e){return"."!==e&&".."!==e}))},t.statSync=t.statSync||function(e){return{isDirectory:function(){return t.isDirectory(e)}}},t}()},6656:(e,t,n)=>{"use strict";(e=n.nmd(e)).exports=function(){if(e.client)return{} +var t=n(9265),r={} +try{r=n(3642)}catch(e){}return r.join=r.join||function(){return Array.prototype.join.call(arguments,t.separator)},r.relative=r.relative||function(e,n){return e+t.separator+n},r}()},4661:(e,t,n)=>{"use strict";(e=n.nmd(e)).exports=function(){if(e.client)return{} +var t=n(9265),r=void 0!==r?r:{} +return r.cwd=function(){return t.workingDirectory},r}()}}]) diff --git a/agent/uiserver/dist/assets/chunk.778.b0fb1162d11e4184d9d0.js.LICENSE.txt b/agent/uiserver/dist/assets/chunk.778.b0fb1162d11e4184d9d0.js.LICENSE.txt new file mode 100644 index 000000000000..3ff66ab722d4 --- /dev/null +++ b/agent/uiserver/dist/assets/chunk.778.b0fb1162d11e4184d9d0.js.LICENSE.txt @@ -0,0 +1,8 @@ +/*! + * QUnit 2.19.4 + * https://qunitjs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + */ diff --git a/agent/uiserver/dist/assets/chunk.83.85cc25a28afe28f711a3.js b/agent/uiserver/dist/assets/chunk.83.85cc25a28afe28f711a3.js deleted file mode 100644 index d49ebc2f6d6f..000000000000 --- a/agent/uiserver/dist/assets/chunk.83.85cc25a28afe28f711a3.js +++ /dev/null @@ -1,65 +0,0 @@ -"use strict";(globalThis.webpackChunk_ember_auto_import_=globalThis.webpackChunk_ember_auto_import_||[]).push([[83],{7083:(e,t,o)=>{o.r(t),o.d(t,{default:()=>_}) -var i=window.CustomEvent -function n(e,t){var o="on"+t.type.toLowerCase() -return"function"==typeof e[o]&&e[o](t),e.dispatchEvent(t)}function a(e){for(;e;){if("dialog"===e.localName)return e -e=e.parentElement?e.parentElement:e.parentNode?e.parentNode.host:null}return null}function r(e){for(;e&&e.shadowRoot&&e.shadowRoot.activeElement;)e=e.shadowRoot.activeElement -e&&e.blur&&e!==document.body&&e.blur()}function l(e,t){for(var o=0;o=0&&(e=this.dialog_),e||(e=d(this.dialog_)),r(document.activeElement),e&&e.focus()},updateZIndex:function(e,t){if(e, the polyfill may not work correctly",e),"dialog"!==e.localName)throw new Error("Failed to register dialog: The element is not a dialog.") -new p(e)},registerDialog:function(e){e.showModal||g.forceRegisterDialog(e)},DialogManager:function(){this.pendingDialogStack=[] -var e=this.checkDOM_.bind(this) -this.overlay=document.createElement("div"),this.overlay.className="_dialog_overlay",this.overlay.addEventListener("click",function(t){this.forwardTab_=void 0,t.stopPropagation(),e([])}.bind(this)),this.handleKey_=this.handleKey_.bind(this),this.handleFocus_=this.handleFocus_.bind(this),this.zIndexLow_=1e5,this.zIndexHigh_=100150,this.forwardTab_=void 0,"MutationObserver"in window&&(this.mo_=new MutationObserver((function(t){var o=[] -t.forEach((function(e){for(var t,i=0;t=e.removedNodes[i];++i)t instanceof Element&&("dialog"===t.localName&&o.push(t),o=o.concat(t.querySelectorAll("dialog")))})),o.length&&e(o)})))}} -if(g.DialogManager.prototype.blockDocument=function(){document.documentElement.addEventListener("focus",this.handleFocus_,!0),document.addEventListener("keydown",this.handleKey_),this.mo_&&this.mo_.observe(document,{childList:!0,subtree:!0})},g.DialogManager.prototype.unblockDocument=function(){document.documentElement.removeEventListener("focus",this.handleFocus_,!0),document.removeEventListener("keydown",this.handleKey_),this.mo_&&this.mo_.disconnect()},g.DialogManager.prototype.updateStacking=function(){for(var e,t=this.zIndexHigh_,o=0;e=this.pendingDialogStack[o];++o)e.updateZIndex(--t,--t),0===o&&(this.overlay.style.zIndex=--t) -var i=this.pendingDialogStack[0] -i?(i.dialog.parentNode||document.body).appendChild(this.overlay):this.overlay.parentNode&&this.overlay.parentNode.removeChild(this.overlay)},g.DialogManager.prototype.containedByTopDialog_=function(e){for(;e=a(e);){for(var t,o=0;t=this.pendingDialogStack[o];++o)if(t.dialog===e)return 0===o -e=e.parentElement}return!1},g.DialogManager.prototype.handleFocus_=function(e){var t=e.composedPath?e.composedPath()[0]:e.target -if(!this.containedByTopDialog_(t)&&document.activeElement!==document.documentElement&&(e.preventDefault(),e.stopPropagation(),r(t),void 0!==this.forwardTab_)){var o=this.pendingDialogStack[0] -return o.dialog.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_PRECEDING&&(this.forwardTab_?o.focus_():t!==document.documentElement&&document.documentElement.focus()),!1}},g.DialogManager.prototype.handleKey_=function(e){if(this.forwardTab_=void 0,27===e.keyCode){e.preventDefault(),e.stopPropagation() -var t=new i("cancel",{bubbles:!1,cancelable:!0}),o=this.pendingDialogStack[0] -o&&n(o.dialog,t)&&o.dialog.close()}else 9===e.keyCode&&(this.forwardTab_=!e.shiftKey)},g.DialogManager.prototype.checkDOM_=function(e){this.pendingDialogStack.slice().forEach((function(t){-1!==e.indexOf(t.dialog)?t.downgradeModal():t.maybeHideModal()}))},g.DialogManager.prototype.pushDialog=function(e){var t=(this.zIndexHigh_-this.zIndexLow_)/2-1 -return!(this.pendingDialogStack.length>=t||(1===this.pendingDialogStack.unshift(e)&&this.blockDocument(),this.updateStacking(),0))},g.DialogManager.prototype.removeDialog=function(e){var t=this.pendingDialogStack.indexOf(e);-1!==t&&(this.pendingDialogStack.splice(t,1),0===this.pendingDialogStack.length&&this.unblockDocument(),this.updateStacking())},g.dm=new g.DialogManager,g.formSubmitter=null,g.imagemapUseValue=null,void 0===window.HTMLDialogElement){var m=document.createElement("form") -if(m.setAttribute("method","dialog"),"dialog"!==m.method){var f=Object.getOwnPropertyDescriptor(HTMLFormElement.prototype,"method") -if(f){var b=f.get -f.get=function(){return s(this)?"dialog":b.call(this)} -var v=f.set -f.set=function(e){return"string"==typeof e&&"dialog"===e.toLowerCase()?this.setAttribute("method",e):v.call(this,e)},Object.defineProperty(HTMLFormElement.prototype,"method",f)}}document.addEventListener("click",(function(e){if(g.formSubmitter=null,g.imagemapUseValue=null,!e.defaultPrevented){var t=e.target -if("composedPath"in e&&(t=e.composedPath().shift()||t),t&&s(t.form)){if(!("submit"===t.type&&["button","input"].indexOf(t.localName)>-1)){if("input"!==t.localName||"image"!==t.type)return -g.imagemapUseValue=e.offsetX+","+e.offsetY}a(t)&&(g.formSubmitter=t)}}}),!1),document.addEventListener("submit",(function(e){var t=e.target -if(!a(t)){var o=c(e) -"dialog"===(o&&o.getAttribute("formmethod")||t.getAttribute("method"))&&e.preventDefault()}})) -var y=HTMLFormElement.prototype.submit -HTMLFormElement.prototype.submit=function(){if(!s(this))return y.call(this) -var e=a(this) -e&&e.close()}}const _=g}}]) diff --git a/agent/uiserver/dist/assets/chunk.924.719761ac5e77d019056f.js b/agent/uiserver/dist/assets/chunk.924.719761ac5e77d019056f.js new file mode 100644 index 000000000000..051c778463d6 --- /dev/null +++ b/agent/uiserver/dist/assets/chunk.924.719761ac5e77d019056f.js @@ -0,0 +1,2523 @@ +/*! For license information please see chunk.924.719761ac5e77d019056f.js.LICENSE.txt */ +(globalThis.webpackChunk_ember_auto_import_=globalThis.webpackChunk_ember_auto_import_||[]).push([[924],{2654:e=>{e.exports=''},6604:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{iconNames:()=>l}) +const l=["loading","loading-static","running","running-static","apple","apple-color","alibaba","alibaba-color","amazon-ecs","amazon-ecs-color","amazon-eks","amazon-eks-color","auth0","auth0-color","aws","aws-color","aws-cdk","aws-cdk-color","aws-cloudwatch","aws-cloudwatch-color","aws-ec2","aws-ec2-color","aws-lambda","aws-lambda-color","aws-s3","aws-s3-color","azure","azure-color","azure-aks","azure-aks-color","azure-blob-storage","azure-blob-storage-color","azure-devops","azure-devops-color","azure-vms","azure-vms-color","bitbucket","bitbucket-color","bridgecrew","bridgecrew-color","cisco","cisco-color","codepen","codepen-color","datadog","datadog-color","digital-ocean","digital-ocean-color","docker","docker-color","elastic-observability","elastic-observability-color","f5","f5-color","facebook","facebook-color","figma","figma-color","gcp","gcp-color","gitlab","gitlab-color","github","github-color","google","google-color","google-docs","google-docs-color","google-drive","google-drive-color","google-forms","google-forms-color","google-sheets","google-sheets-color","google-slides","google-slides-color","grafana","grafana-color","helm","helm-color","infracost","infracost-color","jfrog","jfrog-color","jira","jira-color","kubernetes","kubernetes-color","lightlytics","lightlytics-color","linkedin","linkedin-color","linode","linode-color","linux","linux-color","loom","loom-color","microsoft","microsoft-color","microsoft-teams","microsoft-teams-color","new-relic","new-relic-color","okta","okta-color","oracle","oracle-color","opa","opa-color","pack","pack-color","saml","saml-color","slack","slack-color","snyk","snyk-color","splunk","splunk-color","twitch","twitch-color","twitter","twitter-color","twitter-x","twitter-x-color","vantage","vantage-color","venafi","venafi-color","vercel","vercel-color","vmware","vmware-color","youtube","youtube-color","boundary","boundary-color","consul","consul-color","nomad","nomad-color","packer","packer-color","terraform","terraform-color","vagrant","vagrant-color","vault","vault-color","vault-secrets","vault-secrets-color","waypoint","waypoint-color","hashicorp","hashicorp-color","hcp","hcp-color","activity","alert-circle","alert-circle-fill","alert-diamond","alert-diamond-fill","alert-triangle","alert-triangle-fill","alert-octagon","alert-octagon-fill","align-center","align-justify","align-left","align-right","ampersand","api","archive","arrow-down","arrow-down-circle","arrow-down-left","arrow-down-right","arrow-left","arrow-left-circle","arrow-right","arrow-right-circle","arrow-up","arrow-up-circle","arrow-up-left","arrow-up-right","at-sign","award","auto-apply","bank-vault","bar-chart","bar-chart-alt","battery","battery-charging","beaker","bell","bell-active-fill","bell-active","bell-off","bookmark","bookmark-fill","bookmark-add","bookmark-add-fill","bookmark-remove","bookmark-remove-fill","bottom","box","briefcase","bug","build","bulb","calendar","camera","camera-off","caret","cast","certificate","change","change-circle","change-square","check","check-circle","check-circle-fill","check-diamond","check-diamond-fill","check-hexagon","check-hexagon-fill","check-square","check-square-fill","chevron-down","chevron-left","chevron-right","chevron-up","chevrons-down","chevrons-left","chevrons-right","chevrons-up","circle","circle-dot","circle-fill","circle-half","clipboard","clipboard-checked","clipboard-copy","clipboard-x","clock","clock-filled","cloud","closed-caption","cloud-check","cloud-download","cloud-lightning","cloud-lock","cloud-off","cloud-upload","cloud-x","code","collections","command","compass","connection","connection-gateway","corner-down-left","corner-down-right","corner-left-down","corner-left-up","corner-right-down","corner-right-up","corner-up-left","corner-up-right","cpu","credit-card","crop","crosshair","dashboard","database","delay","delete","diamond","diamond-fill","disc","discussion-circle","discussion-square","docs","docs-download","docs-link","dollar-sign","dot","dot-half","download","droplet","duplicate","edit","enterprise","entry-point","exit-point","external-link","event","eye","eye-off","fast-forward","file","file-check","file-change","file-diff","file-minus","file-plus","file-source","file-text","file-x","files","film","filter","filter-circle","filter-fill","fingerprint","flag","folder","folder-fill","folder-minus","folder-minus-fill","folder-plus","folder-plus-fill","folder-star","folder-users","frown","gateway","gift","git-branch","git-commit","git-merge","git-pull-request","git-repo","globe","globe-private","government","grid","grid-alt","guide","guide-link","hammer","handshake","hard-drive","hash","headphones","heart","heart-fill","heart-off","help","hexagon","hexagon-fill","history","home","hourglass","identity-user","identity-service","image","inbox","info","info-fill","jump-link","key","keychain","key-values","labyrinth","layers","layout","learn","learn-link","line-chart","line-chart-up","link","list","load-balancer","lock","lock-fill","lock-off","logs","mail","mail-open","mainframe","map","map-pin","maximize","maximize-alt","meh","menu","mesh","message-circle","message-circle-fill","message-square","message-square-fill","mic","mic-off","migrate","minimize","minimize-alt","minus","minus-circle","minus-square","minus-square-fill","minus-plus","minus-plus-circle","minus-plus-square","module","monitor","moon","more-horizontal","more-vertical","mouse-pointer","move","music","navigation","navigation-alt","network","network-alt","newspaper","node","octagon","org","outline","package","paperclip","path","pause","pause-circle","pen-tool","pencil-tool","phone","phone-call","phone-off","pie-chart","pin","pipeline","play","play-circle","plug","plus","plus-circle","plus-square","power","printer","provider","queue","radio","random","redirect","reload","repeat","replication-direct","replication-perf","rewind","robot","rocket","rotate-cw","rotate-ccw","rss","save","scissors","search","send","server","serverless","server-cluster","settings","service","share","shield","shield-alert","shield-check","shield-off","shield-x","shopping-bag","shopping-cart","shuffle","sidebar","sidebar-hide","sidebar-show","sign-in","sign-out","skip","skip-forward","skip-back","slash","slash-square","sliders","smartphone","smile","socket","sort-asc","sort-desc","speaker","square","square-fill","star","star-circle","star-fill","star-off","step","stop-circle","sun","support","swap-horizontal","swap-vertical","switcher","sync","sync-alert","sync-reverse","tablet","tag","target","terminal","terminal-screen","test","thumbs-up","thumbs-down","toggle-left","toggle-right","token","tools","top","trash","trend-down","trend-up","triangle","triangle-fill","truck","tv","type","unfold-open","unfold-close","unlock","upload","user","user-check","user-circle","user-circle-fill","user-minus","user-plus","user-x","users","verified","video","video-off","volume","volume-down","volume-2","volume-x","wall","wand","watch","webhook","wifi","wifi-off","wrench","x","x-circle","x-circle-fill","x-diamond","x-diamond-fill","x-hexagon","x-hexagon-fill","x-square","x-square-fill","zap","zap-off","zoom-in","zoom-out"]},7440:(e,t,a)=>{"use strict" +function l(e,t){var a="function"==typeof Symbol&&e[Symbol.iterator] +if(!a)return e +var l,i,o=a.call(e),n=[] +try{for(;(void 0===t||t-- >0)&&!(l=o.next()).done;)n.push(l.value)}catch(e){i={error:e}}finally{try{l&&!l.done&&(a=o.return)&&a.call(o)}finally{if(i)throw i.error}}return n}var i +a.r(t),a.d(t,{InterpreterStatus:()=>i,assign:()=>r,createMachine:()=>f,interpret:()=>p}),function(e){e[e.NotStarted=0]="NotStarted",e[e.Running=1]="Running",e[e.Stopped=2]="Stopped"}(i||(i={})) +var o={type:"xstate.init"} +function n(e){return void 0===e?[]:[].concat(e)}function r(e){return{type:"xstate.assign",assignment:e}}function c(e,t){return"string"==typeof(e="string"==typeof e&&t&&t[e]?t[e]:e)?{type:e}:"function"==typeof e?{type:e.name,exec:e}:e}function h(e){return function(t){return e===t}}function s(e){return"string"==typeof e?{type:e}:e}function d(e,t){return{value:e,context:t,actions:[],changed:!1,matches:h(e)}}function u(e,t,a){var l=t,i=!1 +return[e.filter((function(e){if("xstate.assign"===e.type){i=!0 +var t=Object.assign({},l) +return"function"==typeof e.assignment?t=e.assignment(l,a):Object.keys(e.assignment).forEach((function(i){t[i]="function"==typeof e.assignment[i]?e.assignment[i](l,a):e.assignment[i]})),l=t,!1}return!0})),l,i]}function f(e,t){void 0===t&&(t={}) +var a=l(u(n(e.states[e.initial].entry).map((function(e){return c(e,t.actions)})),e.context,o),2),i=a[0],r=a[1],f={config:e,_options:t,initialState:{value:e.initial,actions:i,context:r,matches:h(e.initial)},transition:function(t,a){var i,o,r="string"==typeof t?{value:t,context:e.context}:t,v=r.value,p=r.context,m=s(a),y=e.states[v] +if(y.on){var g=n(y.on[m.type]) +try{for(var b=function(e){var t="function"==typeof Symbol&&Symbol.iterator,a=t&&e[t],l=0 +if(a)return a.call(e) +if(e&&"number"==typeof e.length)return{next:function(){return e&&l>=e.length&&(e=void 0),{value:e&&e[l++],done:!e}}} +throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}(g),z=b.next();!z.done;z=b.next()){var M=z.value +if(void 0===M)return d(v,p) +var A="string"==typeof M?{target:M}:M,w=A.target,x=A.actions,H=void 0===x?[]:x,V=A.cond,_=void 0===V?function(){return!0}:V,B=void 0===w,L=null!=w?w:v,C=e.states[L] +if(_(p,m)){var E=l(u((B?n(H):[].concat(y.exit,H,C.entry).filter((function(e){return e}))).map((function(e){return c(e,f._options.actions)})),p,m),3),k=E[0],D=E[1],S=E[2],F=null!=w?w:v +return{value:F,context:D,actions:k,changed:w!==v||k.length>0||S,matches:h(F)}}}}catch(e){i={error:e}}finally{try{z&&!z.done&&(o=b.return)&&o.call(b)}finally{if(i)throw i.error}}}return d(v,p)}} +return f}var v=function(e,t){return e.actions.forEach((function(a){var l=a.exec +return l&&l(e.context,t)}))} +function p(e){var t=e.initialState,a=i.NotStarted,l=new Set,n={_machine:e,send:function(o){a===i.Running&&(t=e.transition(t,o),v(t,s(o)),l.forEach((function(e){return e(t)})))},subscribe:function(e){return l.add(e),e(t),{unsubscribe:function(){return l.delete(e)}}},start:function(l){if(l){var r="object"==typeof l?l:{context:e.config.context,value:l} +t={value:r.value,actions:[],context:r.context,matches:h(r.value)}}return a=i.Running,v(t,o),n},stop:function(){return a=i.Stopped,l.clear(),n},get state(){return t},get status(){return a}} +return n}},1413:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{default:()=>s}) +var l=['a[href]:not([tabindex^="-"])','area[href]:not([tabindex^="-"])','input:not([type="hidden"]):not([type="radio"]):not([disabled]):not([tabindex^="-"])','input[type="radio"]:not([disabled]):not([tabindex^="-"]):checked','select:not([disabled]):not([tabindex^="-"])','textarea:not([disabled]):not([tabindex^="-"])','button:not([disabled]):not([tabindex^="-"])','iframe:not([tabindex^="-"])','audio[controls]:not([tabindex^="-"])','video[controls]:not([tabindex^="-"])','[contenteditable]:not([tabindex^="-"])','[tabindex]:not([tabindex^="-"])'] +function i(e,t){this._show=this.show.bind(this),this._hide=this.hide.bind(this),this._maintainFocus=this._maintainFocus.bind(this),this._bindKeypress=this._bindKeypress.bind(this),this._previouslyFocused=null,this.container=e,this.dialog=e.querySelector('dialog, [role="dialog"], [role="alertdialog"]'),this.role=this.dialog.getAttribute("role")||"dialog",this.useDialog="show"in this.dialog,this._listeners={},this.create(t)}function o(e){return Array.prototype.slice.call(e)}function n(e,t){return o((t||document).querySelectorAll(e))}function r(e){var t=c(e),a=e.querySelector("[autofocus]")||t[0] +a&&a.focus()}function c(e){return n(l.join(","),e).filter((function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)}))}function h(){n("[data-a11y-dialog]").forEach((function(e){new i(e,e.getAttribute("data-a11y-dialog")||void 0)}))}i.prototype.create=function(e){var t,a,l +return this._targets=this._targets||(l=e,NodeList.prototype.isPrototypeOf(l)?o(l):Element.prototype.isPrototypeOf(l)?[l]:"string"==typeof l?n(l):void 0)||((a=o((t=this.container).parentNode.childNodes).filter((function(e){return 1===e.nodeType}))).splice(a.indexOf(t),1),a),this.shown=this.dialog.hasAttribute("open"),this.dialog.setAttribute("role",this.role),this.useDialog?(this.container.setAttribute("data-a11y-dialog-native",""),this.container.removeAttribute("aria-hidden")):this.shown?this.container.removeAttribute("aria-hidden"):this.container.setAttribute("aria-hidden",!0),this._openers=n('[data-a11y-dialog-show="'+this.container.id+'"]'),this._openers.forEach(function(e){e.addEventListener("click",this._show)}.bind(this)),this._closers=n("[data-a11y-dialog-hide]",this.container).concat(n('[data-a11y-dialog-hide="'+this.container.id+'"]')),this._closers.forEach(function(e){e.addEventListener("click",this._hide)}.bind(this)),this._fire("create"),this},i.prototype.show=function(e){return this.shown||(this.shown=!0,this._previouslyFocused=document.activeElement,this.useDialog?this.dialog.showModal(e instanceof Event?void 0:e):(this.dialog.setAttribute("open",""),this.container.removeAttribute("aria-hidden"),this._targets.forEach((function(e){e.hasAttribute("aria-hidden")&&e.setAttribute("data-a11y-dialog-original-aria-hidden",e.getAttribute("aria-hidden")),e.setAttribute("aria-hidden","true")}))),r(this.dialog),document.body.addEventListener("focus",this._maintainFocus,!0),document.addEventListener("keydown",this._bindKeypress),this._fire("show",e)),this},i.prototype.hide=function(e){return this.shown?(this.shown=!1,this.useDialog?this.dialog.close(e instanceof Event?void 0:e):(this.dialog.removeAttribute("open"),this.container.setAttribute("aria-hidden","true"),this._targets.forEach((function(e){e.hasAttribute("data-a11y-dialog-original-aria-hidden")?(e.setAttribute("aria-hidden",e.getAttribute("data-a11y-dialog-original-aria-hidden")),e.removeAttribute("data-a11y-dialog-original-aria-hidden")):e.removeAttribute("aria-hidden")}))),this._previouslyFocused&&this._previouslyFocused.focus&&this._previouslyFocused.focus(),document.body.removeEventListener("focus",this._maintainFocus,!0),document.removeEventListener("keydown",this._bindKeypress),this._fire("hide",e),this):this},i.prototype.destroy=function(){return this.hide(),this._openers.forEach(function(e){e.removeEventListener("click",this._show)}.bind(this)),this._closers.forEach(function(e){e.removeEventListener("click",this._hide)}.bind(this)),this._fire("destroy"),this._listeners={},this},i.prototype.on=function(e,t){return void 0===this._listeners[e]&&(this._listeners[e]=[]),this._listeners[e].push(t),this},i.prototype.off=function(e,t){var a=(this._listeners[e]||[]).indexOf(t) +return a>-1&&this._listeners[e].splice(a,1),this},i.prototype._fire=function(e,t){(this._listeners[e]||[]).forEach(function(e){e(this.container,t)}.bind(this))},i.prototype._bindKeypress=function(e){this.dialog.contains(document.activeElement)&&(this.shown&&27===e.which&&"alertdialog"!==this.role&&(e.preventDefault(),this.hide(e)),this.shown&&9===e.which&&function(e,t){var a=c(e),l=a.indexOf(document.activeElement) +t.shiftKey&&0===l?(a[a.length-1].focus(),t.preventDefault()):t.shiftKey||l!==a.length-1||(a[0].focus(),t.preventDefault())}(this.dialog,e))},i.prototype._maintainFocus=function(e){this.shown&&!e.target.closest('dialog, [role="dialog"], [role="alertdialog"]')&&r(this.container)},"undefined"!=typeof document&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",h):window.requestAnimationFrame?window.requestAnimationFrame(h):window.setTimeout(h,16)) +const s=i},8294:(e,t)=>{"use strict" +t.byteLength=function(e){var t=c(e),a=t[0],l=t[1] +return 3*(a+l)/4-l},t.toByteArray=function(e){var t,a,o=c(e),n=o[0],r=o[1],h=new i(function(e,t,a){return 3*(t+a)/4-a}(0,n,r)),s=0,d=r>0?n-4:n +for(a=0;a>16&255,h[s++]=t>>8&255,h[s++]=255&t +return 2===r&&(t=l[e.charCodeAt(a)]<<2|l[e.charCodeAt(a+1)]>>4,h[s++]=255&t),1===r&&(t=l[e.charCodeAt(a)]<<10|l[e.charCodeAt(a+1)]<<4|l[e.charCodeAt(a+2)]>>2,h[s++]=t>>8&255,h[s++]=255&t),h},t.fromByteArray=function(e){for(var t,l=e.length,i=l%3,o=[],n=16383,r=0,c=l-i;rc?c:r+n)) +return 1===i?(t=e[l-1],o.push(a[t>>2]+a[t<<4&63]+"==")):2===i&&(t=(e[l-2]<<8)+e[l-1],o.push(a[t>>10]+a[t>>4&63]+a[t<<2&63]+"=")),o.join("")} +for(var a=[],l=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",n=0,r=o.length;n0)throw new Error("Invalid string. Length must be a multiple of 4") +var a=e.indexOf("=") +return-1===a&&(a=t),[a,a===t?0:4-a%4]}function h(e,t,l){for(var i,o,n=[],r=t;r>18&63]+a[o>>12&63]+a[o>>6&63]+a[63&o]) +return n.join("")}l["-".charCodeAt(0)]=62,l["_".charCodeAt(0)]=63},9079:function(e){var t +t=function(){return function(){var e={686:function(e,t,a){"use strict" +a.d(t,{default:function(){return z}}) +var l=a(279),i=a.n(l),o=a(370),n=a.n(o),r=a(817),c=a.n(r) +function h(e){try{return document.execCommand(e)}catch(e){return!1}}var s=function(e){var t=c()(e) +return h("cut"),t},d=function(e,t){var a=function(e){var t="rtl"===document.documentElement.getAttribute("dir"),a=document.createElement("textarea") +a.style.fontSize="12pt",a.style.border="0",a.style.padding="0",a.style.margin="0",a.style.position="absolute",a.style[t?"right":"left"]="-9999px" +var l=window.pageYOffset||document.documentElement.scrollTop +return a.style.top="".concat(l,"px"),a.setAttribute("readonly",""),a.value=e,a}(e) +t.container.appendChild(a) +var l=c()(a) +return h("copy"),a.remove(),l},u=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{container:document.body},a="" +return"string"==typeof e?a=d(e,t):e instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(null==e?void 0:e.type)?a=d(e.value,t):(a=c()(e),h("copy")),a} +function f(e){return f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},f(e)}function v(e){return v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},v(e)}function p(e,t){for(var a=0;a0&&void 0!==arguments[0]?arguments[0]:{} +this.action="function"==typeof e.action?e.action:this.defaultAction,this.target="function"==typeof e.target?e.target:this.defaultTarget,this.text="function"==typeof e.text?e.text:this.defaultText,this.container="object"===v(e.container)?e.container:document.body}},{key:"listenClick",value:function(e){var t=this +this.listener=n()(e,"click",(function(e){return t.onClick(e)}))}},{key:"onClick",value:function(e){var t=e.delegateTarget||e.currentTarget,a=this.action(t)||"copy",l=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.action,a=void 0===t?"copy":t,l=e.container,i=e.target,o=e.text +if("copy"!==a&&"cut"!==a)throw new Error('Invalid "action" value, use either "copy" or "cut"') +if(void 0!==i){if(!i||"object"!==f(i)||1!==i.nodeType)throw new Error('Invalid "target" value, use a valid Element') +if("copy"===a&&i.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute') +if("cut"===a&&(i.hasAttribute("readonly")||i.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes')}return o?u(o,{container:l}):i?"cut"===a?s(i):u(i,{container:l}):void 0}({action:a,container:this.container,target:this.target(t),text:this.text(t)}) +this.emit(l?"success":"error",{action:a,text:l,trigger:t,clearSelection:function(){t&&t.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(e){return g("action",e)}},{key:"defaultTarget",value:function(e){var t=g("target",e) +if(t)return document.querySelector(t)}},{key:"defaultText",value:function(e){return g("text",e)}},{key:"destroy",value:function(){this.listener.destroy()}}],l=[{key:"copy",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{container:document.body} +return u(e,t)}},{key:"cut",value:function(e){return s(e)}},{key:"isSupported",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],t="string"==typeof e?[e]:e,a=!!document.queryCommandSupported +return t.forEach((function(e){a=a&&!!document.queryCommandSupported(e)})),a}}],a&&p(t.prototype,a),l&&p(t,l),c}(i()),z=b},828:function(e){if("undefined"!=typeof Element&&!Element.prototype.matches){var t=Element.prototype +t.matches=t.matchesSelector||t.mozMatchesSelector||t.msMatchesSelector||t.oMatchesSelector||t.webkitMatchesSelector}e.exports=function(e,t){for(;e&&9!==e.nodeType;){if("function"==typeof e.matches&&e.matches(t))return e +e=e.parentNode}}},438:function(e,t,a){var l=a(828) +function i(e,t,a,l,i){var n=o.apply(this,arguments) +return e.addEventListener(a,n,i),{destroy:function(){e.removeEventListener(a,n,i)}}}function o(e,t,a,i){return function(a){a.delegateTarget=l(a.target,t),a.delegateTarget&&i.call(e,a)}}e.exports=function(e,t,a,l,o){return"function"==typeof e.addEventListener?i.apply(null,arguments):"function"==typeof a?i.bind(null,document).apply(null,arguments):("string"==typeof e&&(e=document.querySelectorAll(e)),Array.prototype.map.call(e,(function(e){return i(e,t,a,l,o)})))}},879:function(e,t){t.node=function(e){return void 0!==e&&e instanceof HTMLElement&&1===e.nodeType},t.nodeList=function(e){var a=Object.prototype.toString.call(e) +return void 0!==e&&("[object NodeList]"===a||"[object HTMLCollection]"===a)&&"length"in e&&(0===e.length||t.node(e[0]))},t.string=function(e){return"string"==typeof e||e instanceof String},t.fn=function(e){return"[object Function]"===Object.prototype.toString.call(e)}},370:function(e,t,a){var l=a(879),i=a(438) +e.exports=function(e,t,a){if(!e&&!t&&!a)throw new Error("Missing required arguments") +if(!l.string(t))throw new TypeError("Second argument must be a String") +if(!l.fn(a))throw new TypeError("Third argument must be a Function") +if(l.node(e))return function(e,t,a){return e.addEventListener(t,a),{destroy:function(){e.removeEventListener(t,a)}}}(e,t,a) +if(l.nodeList(e))return function(e,t,a){return Array.prototype.forEach.call(e,(function(e){e.addEventListener(t,a)})),{destroy:function(){Array.prototype.forEach.call(e,(function(e){e.removeEventListener(t,a)}))}}}(e,t,a) +if(l.string(e))return function(e,t,a){return i(document.body,e,t,a)}(e,t,a) +throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}},817:function(e){e.exports=function(e){var t +if("SELECT"===e.nodeName)e.focus(),t=e.value +else if("INPUT"===e.nodeName||"TEXTAREA"===e.nodeName){var a=e.hasAttribute("readonly") +a||e.setAttribute("readonly",""),e.select(),e.setSelectionRange(0,e.value.length),a||e.removeAttribute("readonly"),t=e.value}else{e.hasAttribute("contenteditable")&&e.focus() +var l=window.getSelection(),i=document.createRange() +i.selectNodeContents(e),l.removeAllRanges(),l.addRange(i),t=l.toString()}return t}},279:function(e){function t(){}t.prototype={on:function(e,t,a){var l=this.e||(this.e={}) +return(l[e]||(l[e]=[])).push({fn:t,ctx:a}),this},once:function(e,t,a){var l=this +function i(){l.off(e,i),t.apply(a,arguments)}return i._=t,this.on(e,i,a)},emit:function(e){for(var t=[].slice.call(arguments,1),a=((this.e||(this.e={}))[e]||[]).slice(),l=0,i=a.length;l{"use strict" +function l(e,t){return et?1:e>=t?0:NaN}a.d(t,{Z:()=>l})},8734:(e,t,a)=>{"use strict" +a.d(t,{Nw:()=>c,ZP:()=>s,ZR:()=>h,ml:()=>r}) +var l=a(9731),i=a(7870),o=a(3342) +const n=(0,i.Z)(l.Z),r=n.right,c=n.left,h=(0,i.Z)(o.Z).center,s=r},7870:(e,t,a)=>{"use strict" +a.d(t,{Z:()=>i}) +var l=a(9731) +function i(e){let t=e,a=e +function i(e,t,l,i){for(null==l&&(l=0),null==i&&(i=e.length);l>>1 +a(e[o],t)<0?l=o+1:i=o}return l}return 1===e.length&&(t=(t,a)=>e(t)-a,a=function(e){return(t,a)=>(0,l.Z)(e(t),a)}(e)),{left:i,center:function(e,a,l,o){null==l&&(l=0),null==o&&(o=e.length) +const n=i(e,a,l,o-1) +return n>l&&t(e[n-1],a)>-t(e[n],a)?n-1:n},right:function(e,t,l,i){for(null==l&&(l=0),null==i&&(i=e.length);l>>1 +a(e[o],t)>0?i=o:l=o+1}return l}}}},5447:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{Adder:()=>m,InternMap:()=>b,InternSet:()=>z,ascending:()=>i.Z,bin:()=>I,bisect:()=>l.ZP,bisectCenter:()=>l.ZR,bisectLeft:()=>l.Nw,bisectRight:()=>l.ml,bisector:()=>o.Z,count:()=>n,cross:()=>s,cumsum:()=>d,descending:()=>u,deviation:()=>v,difference:()=>Me,disjoint:()=>Ae,every:()=>pe,extent:()=>p,fcumsum:()=>g,filter:()=>ye,fsum:()=>y,greatest:()=>ne,greatestIndex:()=>re,group:()=>V,groupSort:()=>O,groups:()=>_,histogram:()=>I,index:()=>C,indexes:()=>E,intersection:()=>xe,least:()=>ie,leastIndex:()=>oe,map:()=>ge,max:()=>Z.Z,maxIndex:()=>Y,mean:()=>K,median:()=>W,merge:()=>X,min:()=>J.Z,minIndex:()=>Q,nice:()=>R,pairs:()=>ee,permute:()=>S,quantile:()=>G.Z,quantileSorted:()=>G.s,quickselect:()=>ae.Z,range:()=>le.Z,reduce:()=>be,reverse:()=>ze,rollup:()=>B,rollups:()=>L,scan:()=>ce,shuffle:()=>he,shuffler:()=>se,some:()=>me,sort:()=>F,subset:()=>Ve,sum:()=>de,superset:()=>He,thresholdFreedmanDiaconis:()=>$,thresholdScott:()=>q,thresholdSturges:()=>j,tickIncrement:()=>U.G9,tickStep:()=>U.ly,ticks:()=>U.ZP,transpose:()=>ue,union:()=>_e,variance:()=>f,zip:()=>ve}) +var l=a(8734),i=a(9731),o=a(7870) +function n(e,t){let a=0 +if(void 0===t)for(let l of e)null!=l&&(l=+l)>=l&&++a +else{let l=-1 +for(let i of e)null!=(i=t(i,++l,e))&&(i=+i)>=i&&++a}return a}function r(e){return 0|e.length}function c(e){return!(e>0)}function h(e){return"object"!=typeof e||"length"in e?e:Array.from(e)}function s(){for(var e=arguments.length,t=new Array(e),a=0;ae(...t)}(t.pop()),i=(t=t.map(h)).map(r),o=t.length-1,n=new Array(o+1).fill(0),s=[] +if(o<0||i.some(c))return s +for(;;){s.push(n.map(((e,a)=>t[a][e]))) +let e=o +for(;++n[e]===i[e];){if(0===e)return l?s.map(l):s +n[e--]=0}}}function d(e,t){var a=0,l=0 +return Float64Array.from(e,void 0===t?e=>a+=+e||0:i=>a+=+t(i,l++,e)||0)}function u(e,t){return te?1:t>=e?0:NaN}function f(e,t){let a,l=0,i=0,o=0 +if(void 0===t)for(let n of e)null!=n&&(n=+n)>=n&&(a=n-i,i+=a/++l,o+=a*(n-i)) +else{let n=-1 +for(let r of e)null!=(r=t(r,++n,e))&&(r=+r)>=r&&(a=r-i,i+=a/++l,o+=a*(r-i))}if(l>1)return o/(l-1)}function v(e,t){const a=f(e,t) +return a?Math.sqrt(a):a}function p(e,t){let a,l +if(void 0===t)for(const i of e)null!=i&&(void 0===a?i>=i&&(a=l=i):(a>i&&(a=i),l=o&&(a=l=o):(a>o&&(a=o),l0){for(o=e[--i];i>0&&(t=o,a=e[--i],o=t+a,l=a-(o-t),!l););i>0&&(l<0&&e[i-1]<0||l>0&&e[i-1]>0)&&(a=2*l,t=o+a,a==t-o&&(o=t))}return o}}function y(e,t){const a=new m +if(void 0===t)for(let l of e)(l=+l)&&a.add(l) +else{let l=-1 +for(let i of e)(i=+t(i,++l,e))&&a.add(i)}return+a}function g(e,t){const a=new m +let l=-1 +return Float64Array.from(e,void 0===t?e=>a.add(+e||0):i=>a.add(+t(i,++l,e)||0))}class b extends Map{constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:x +if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:t}}),null!=e)for(const[a,l]of e)this.set(a,l)}get(e){return super.get(M(this,e))}has(e){return super.has(M(this,e))}set(e,t){return super.set(A(this,e),t)}delete(e){return super.delete(w(this,e))}}class z extends Set{constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:x +if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:t}}),null!=e)for(const a of e)this.add(a)}has(e){return super.has(M(this,e))}add(e){return super.add(A(this,e))}delete(e){return super.delete(w(this,e))}}function M(e,t){let{_intern:a,_key:l}=e +const i=l(t) +return a.has(i)?a.get(i):t}function A(e,t){let{_intern:a,_key:l}=e +const i=l(t) +return a.has(i)?a.get(i):(a.set(i,t),t)}function w(e,t){let{_intern:a,_key:l}=e +const i=l(t) +return a.has(i)&&(t=a.get(t),a.delete(i)),t}function x(e){return null!==e&&"object"==typeof e?e.valueOf():e}function H(e){return e}function V(e){for(var t=arguments.length,a=new Array(t>1?t-1:0),l=1;l1?t-1:0),l=1;l2?a-2:0),i=2;i2?a-2:0),i=2;i1?t-1:0),l=1;l1?t-1:0),l=1;l=l.length)return a(i) +const n=new b,r=l[o++] +let c=-1 +for(const t of i){const e=r(t,++c,i),a=n.get(e) +a?a.push(t):n.set(e,[t])}for(const[t,a]of n)n.set(t,e(a,o)) +return t(n)}(e,0)}function S(e,t){return Array.from(t,(t=>e[t]))}function F(e){for(var t=arguments.length,a=new Array(t>1?t-1:0),l=1;l1){const t=Uint32Array.from(e,((e,t)=>t)) +return a.length>1?(a=a.map((t=>e.map(t))),t.sort(((e,t)=>{for(const l of a){const a=(0,i.Z)(l[e],l[t]) +if(a)return a}}))):(o=e.map(o),t.sort(((e,t)=>(0,i.Z)(o[e],o[t])))),S(e,t)}return e.sort(o)}function O(e,t,a){return(1===t.length?F(B(e,t,a),((e,t)=>{let[a,l]=e,[o,n]=t +return(0,i.Z)(l,n)||(0,i.Z)(a,o)})):F(V(e,a),((e,a)=>{let[l,o]=e,[n,r]=a +return t(o,r)||(0,i.Z)(l,n)}))).map((e=>{let[t]=e +return t}))}var T=Array.prototype,P=T.slice +function N(e){return function(){return e}}T.map +var U=a(7666) +function R(e,t,a){let l +for(;;){const i=(0,U.G9)(e,t,a) +if(i===l||0===i||!isFinite(i))return[e,t] +i>0?(e=Math.floor(e/i)*i,t=Math.ceil(t/i)*i):i<0&&(e=Math.ceil(e*i)/i,t=Math.floor(t*i)/i),l=i}}function j(e){return Math.ceil(Math.log(n(e))/Math.LN2)+1}function I(){var e=H,t=p,a=j +function i(i){Array.isArray(i)||(i=Array.from(i)) +var o,n,r=i.length,c=new Array(r) +for(o=0;o=d)if(e>=d&&t===p){const e=(0,U.G9)(s,d,a) +isFinite(e)&&(e>0?d=(Math.floor(d/e)+1)*e:e<0&&(d=(Math.ceil(d*-e)+1)/-e))}else u.pop()}for(var f=u.length;u[0]<=s;)u.shift(),--f +for(;u[f-1]>d;)u.pop(),--f +var v,m=new Array(f+1) +for(o=0;o<=f;++o)(v=m[o]=[]).x0=o>0?u[o-1]:s,v.x1=o=o)&&(a=o,l=i) +else for(let o of e)null!=(o=t(o,++i,e))&&(a=o)&&(a=o,l=i) +return l}function K(e,t){let a=0,l=0 +if(void 0===t)for(let i of e)null!=i&&(i=+i)>=i&&(++a,l+=i) +else{let i=-1 +for(let o of e)null!=(o=t(o,++i,e))&&(o=+o)>=o&&(++a,l+=o)}if(a)return l/a}function W(e,t){return(0,G.Z)(e,.5,t)}function X(e){return Array.from(function*(e){for(const t of e)yield*t}(e))}var J=a(3631) +function Q(e,t){let a,l=-1,i=-1 +if(void 0===t)for(const o of e)++i,null!=o&&(a>o||void 0===a&&o>=o)&&(a=o,l=i) +else for(let o of e)null!=(o=t(o,++i,e))&&(a>o||void 0===a&&o>=o)&&(a=o,l=i) +return l}function ee(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:te +const a=[] +let l,i=!1 +for(const o of e)i&&a.push(t(l,o)),l=o,i=!0 +return a}function te(e,t){return[e,t]}var ae=a(8608),le=a(5232) +function ie(e){let t,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.Z,l=!1 +if(1===a.length){let o +for(const n of e){const e=a(n);(l?(0,i.Z)(e,o)<0:0===(0,i.Z)(e,e))&&(t=n,o=e,l=!0)}}else for(const i of e)(l?a(i,t)<0:0===a(i,i))&&(t=i,l=!0) +return t}function oe(e){let t,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.Z +if(1===a.length)return Q(e,a) +let l=-1,o=-1 +for(const i of e)++o,(l<0?0===a(i,i):a(i,t)<0)&&(t=i,l=o) +return l}function ne(e){let t,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.Z,l=!1 +if(1===a.length){let o +for(const n of e){const e=a(n);(l?(0,i.Z)(e,o)>0:0===(0,i.Z)(e,e))&&(t=n,o=e,l=!0)}}else for(const i of e)(l?a(i,t)>0:0===a(i,i))&&(t=i,l=!0) +return t}function re(e){let t,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.Z +if(1===a.length)return Y(e,a) +let l=-1,o=-1 +for(const i of e)++o,(l<0?0===a(i,i):a(i,t)>0)&&(t=i,l=o) +return l}function ce(e,t){const a=oe(e,t) +return a<0?void 0:a}const he=se(Math.random) +function se(e){return function(t){let a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,l=(arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.length)-(a=+a) +for(;l;){const i=e()*l--|0,o=t[l+a] +t[l+a]=t[i+a],t[i+a]=o}return t}}function de(e,t){let a=0 +if(void 0===t)for(let l of e)(l=+l)&&(a+=l) +else{let l=-1 +for(let i of e)(i=+t(i,++l,e))&&(a+=i)}return a}function ue(e){if(!(i=e.length))return[] +for(var t=-1,a=(0,J.Z)(e,fe),l=new Array(a);++tt(a,l,e)))}function be(e,t,a){if("function"!=typeof t)throw new TypeError("reducer is not a function") +const l=e[Symbol.iterator]() +let i,o,n=-1 +if(arguments.length<3){if(({done:i,value:a}=l.next()),i)return;++n}for(;({done:i,value:o}=l.next()),!i;)a=t(a,o,++n,e) +return a}function ze(e){if("function"!=typeof e[Symbol.iterator])throw new TypeError("values is not iterable") +return Array.from(e).reverse()}function Me(e){e=new Set(e) +for(var t=arguments.length,a=new Array(t>1?t-1:0),l=1;l1?t-1:0),l=1;l{"use strict" +function l(e,t){let a +if(void 0===t)for(const l of e)null!=l&&(a=l)&&(a=l) +else{let l=-1 +for(let i of e)null!=(i=t(i,++l,e))&&(a=i)&&(a=i)}return a}a.d(t,{Z:()=>l})},3631:(e,t,a)=>{"use strict" +function l(e,t){let a +if(void 0===t)for(const l of e)null!=l&&(a>l||void 0===a&&l>=l)&&(a=l) +else{let l=-1 +for(let i of e)null!=(i=t(i,++l,e))&&(a>i||void 0===a&&i>=i)&&(a=i)}return a}a.d(t,{Z:()=>l})},3342:(e,t,a)=>{"use strict" +function l(e){return null===e?NaN:+e}function*i(e,t){if(void 0===t)for(let a of e)null!=a&&(a=+a)>=a&&(yield a) +else{let a=-1 +for(let l of e)null!=(l=t(l,++a,e))&&(l=+l)>=l&&(yield l)}}a.d(t,{K:()=>i,Z:()=>l})},1657:(e,t,a)=>{"use strict" +a.d(t,{Z:()=>r,s:()=>c}) +var l=a(6780),i=a(3631),o=a(8608),n=a(3342) +function r(e,t,a){if(r=(e=Float64Array.from((0,n.K)(e,a))).length){if((t=+t)<=0||r<2)return(0,i.Z)(e) +if(t>=1)return(0,l.Z)(e) +var r,c=(r-1)*t,h=Math.floor(c),s=(0,l.Z)((0,o.Z)(e,h).subarray(0,h+1)) +return s+((0,i.Z)(e.subarray(h+1))-s)*(c-h)}}function c(e,t){let a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:n.Z +if(l=e.length){if((t=+t)<=0||l<2)return+a(e[0],0,e) +if(t>=1)return+a(e[l-1],l-1,e) +var l,i=(l-1)*t,o=Math.floor(i),r=+a(e[o],o,e) +return r+(+a(e[o+1],o+1,e)-r)*(i-o)}}},8608:(e,t,a)=>{"use strict" +a.d(t,{Z:()=>i}) +var l=a(9731) +function i(e,t){let a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:e.length-1,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:l.Z +for(;n>a;){if(n-a>600){const l=n-a+1,o=t-a+1,c=Math.log(l),h=.5*Math.exp(2*c/3),s=.5*Math.sqrt(c*h*(l-h)/l)*(o-l/2<0?-1:1) +i(e,t,Math.max(a,Math.floor(t-o*h/l+s)),Math.min(n,Math.floor(t+(l-o)*h/l+s)),r)}const l=e[t] +let c=a,h=n +for(o(e,a,t),r(e[n],l)>0&&o(e,a,n);c0;)--h}0===r(e[a],l)?o(e,a,h):(++h,o(e,h,n)),h<=t&&(a=h+1),t<=h&&(n=h-1)}return e}function o(e,t,a){const l=e[t] +e[t]=e[a],e[a]=l}},5232:(e,t,a)=>{"use strict" +function l(e,t,a){e=+e,t=+t,a=(i=arguments.length)<2?(t=e,e=0,1):i<3?1:+a +for(var l=-1,i=0|Math.max(0,Math.ceil((t-e)/a)),o=new Array(i);++ll})},7666:(e,t,a)=>{"use strict" +a.d(t,{G9:()=>r,ZP:()=>n,ly:()=>c}) +var l=Math.sqrt(50),i=Math.sqrt(10),o=Math.sqrt(2) +function n(e,t,a){var l,i,o,n,c=-1 +if(a=+a,(e=+e)==(t=+t)&&a>0)return[e] +if((l=t0){let a=Math.round(e/n),l=Math.round(t/n) +for(a*nt&&--l,o=new Array(i=l-a+1);++ct&&--l,o=new Array(i=l-a+1);++c=0?(c>=l?10:c>=i?5:c>=o?2:1)*Math.pow(10,r):-Math.pow(10,-r)/(c>=l?10:c>=i?5:c>=o?2:1)}function c(e,t,a){var n=Math.abs(t-e)/Math.max(0,a),r=Math.pow(10,Math.floor(Math.log(n)/Math.LN10)),c=n/r +return c>=l?r*=10:c>=i?r*=5:c>=o&&(r*=2),t{"use strict" +a.d(t,{B8:()=>x,Il:()=>i,J5:()=>n,SU:()=>w,Ss:()=>H,ZP:()=>z,xV:()=>o}) +var l=a(8797) +function i(){}var o=.7,n=1/o,r="\\s*([+-]?\\d+)\\s*",c="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",h="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",s=/^#([0-9a-f]{3,8})$/,d=new RegExp("^rgb\\("+[r,r,r]+"\\)$"),u=new RegExp("^rgb\\("+[h,h,h]+"\\)$"),f=new RegExp("^rgba\\("+[r,r,r,c]+"\\)$"),v=new RegExp("^rgba\\("+[h,h,h,c]+"\\)$"),p=new RegExp("^hsl\\("+[c,h,h]+"\\)$"),m=new RegExp("^hsla\\("+[c,h,h,c]+"\\)$"),y={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074} +function g(){return this.rgb().formatHex()}function b(){return this.rgb().formatRgb()}function z(e){var t,a +return e=(e+"").trim().toLowerCase(),(t=s.exec(e))?(a=t[1].length,t=parseInt(t[1],16),6===a?M(t):3===a?new H(t>>8&15|t>>4&240,t>>4&15|240&t,(15&t)<<4|15&t,1):8===a?A(t>>24&255,t>>16&255,t>>8&255,(255&t)/255):4===a?A(t>>12&15|t>>8&240,t>>8&15|t>>4&240,t>>4&15|240&t,((15&t)<<4|15&t)/255):null):(t=d.exec(e))?new H(t[1],t[2],t[3],1):(t=u.exec(e))?new H(255*t[1]/100,255*t[2]/100,255*t[3]/100,1):(t=f.exec(e))?A(t[1],t[2],t[3],t[4]):(t=v.exec(e))?A(255*t[1]/100,255*t[2]/100,255*t[3]/100,t[4]):(t=p.exec(e))?L(t[1],t[2]/100,t[3]/100,1):(t=m.exec(e))?L(t[1],t[2]/100,t[3]/100,t[4]):y.hasOwnProperty(e)?M(y[e]):"transparent"===e?new H(NaN,NaN,NaN,0):null}function M(e){return new H(e>>16&255,e>>8&255,255&e,1)}function A(e,t,a,l){return l<=0&&(e=t=a=NaN),new H(e,t,a,l)}function w(e){return e instanceof i||(e=z(e)),e?new H((e=e.rgb()).r,e.g,e.b,e.opacity):new H}function x(e,t,a,l){return 1===arguments.length?w(e):new H(e,t,a,null==l?1:l)}function H(e,t,a,l){this.r=+e,this.g=+t,this.b=+a,this.opacity=+l}function V(){return"#"+B(this.r)+B(this.g)+B(this.b)}function _(){var e=this.opacity +return(1===(e=isNaN(e)?1:Math.max(0,Math.min(1,e)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===e?")":", "+e+")")}function B(e){return((e=Math.max(0,Math.min(255,Math.round(e)||0)))<16?"0":"")+e.toString(16)}function L(e,t,a,l){return l<=0?e=t=a=NaN:a<=0||a>=1?e=t=NaN:t<=0&&(e=NaN),new E(e,t,a,l)}function C(e){if(e instanceof E)return new E(e.h,e.s,e.l,e.opacity) +if(e instanceof i||(e=z(e)),!e)return new E +if(e instanceof E)return e +var t=(e=e.rgb()).r/255,a=e.g/255,l=e.b/255,o=Math.min(t,a,l),n=Math.max(t,a,l),r=NaN,c=n-o,h=(n+o)/2 +return c?(r=t===n?(a-l)/c+6*(a0&&h<1?0:r,new E(r,c,h,e.opacity)}function E(e,t,a,l){this.h=+e,this.s=+t,this.l=+a,this.opacity=+l}function k(e,t,a){return 255*(e<60?t+(a-t)*e/60:e<180?a:e<240?t+(a-t)*(240-e)/60:t)}(0,l.Z)(i,z,{copy:function(e){return Object.assign(new this.constructor,this,e)},displayable:function(){return this.rgb().displayable()},hex:g,formatHex:g,formatHsl:function(){return C(this).formatHsl()},formatRgb:b,toString:b}),(0,l.Z)(H,x,(0,l.l)(i,{brighter:function(e){return e=null==e?n:Math.pow(n,e),new H(this.r*e,this.g*e,this.b*e,this.opacity)},darker:function(e){return e=null==e?o:Math.pow(o,e),new H(this.r*e,this.g*e,this.b*e,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:V,formatHex:V,formatRgb:_,toString:_})),(0,l.Z)(E,(function(e,t,a,l){return 1===arguments.length?C(e):new E(e,t,a,null==l?1:l)}),(0,l.l)(i,{brighter:function(e){return e=null==e?n:Math.pow(n,e),new E(this.h,this.s,this.l*e,this.opacity)},darker:function(e){return e=null==e?o:Math.pow(o,e),new E(this.h,this.s,this.l*e,this.opacity)},rgb:function(){var e=this.h%360+360*(this.h<0),t=isNaN(e)||isNaN(this.s)?0:this.s,a=this.l,l=a+(a<.5?a:1-a)*t,i=2*a-l +return new H(k(e>=240?e-240:e+120,i,l),k(e,i,l),k(e<120?e+240:e-120,i,l),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var e=this.opacity +return(1===(e=isNaN(e)?1:Math.max(0,Math.min(1,e)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===e?")":", "+e+")")}}))},8797:(e,t,a)=>{"use strict" +function l(e,t,a){e.prototype=t.prototype=a,a.constructor=e}function i(e,t){var a=Object.create(e.prototype) +for(var l in t)a[l]=t[l] +return a}a.d(t,{Z:()=>l,l:()=>i})},3068:(e,t,a)=>{"use strict" +a.d(t,{ZP:()=>r,wx:()=>o,yi:()=>n}) +var l=a(4472) +function i(e,t){return function(a){return e+a*t}}function o(e,t){var a=t-e +return a?i(e,a>180||a<-180?a-360*Math.round(a/360):a):(0,l.Z)(isNaN(e)?t:e)}function n(e){return 1==(e=+e)?r:function(t,a){return a-t?function(e,t,a){return e=Math.pow(e,a),t=Math.pow(t,a)-e,a=1/a,function(l){return Math.pow(e+l*t,a)}}(t,a,e):(0,l.Z)(isNaN(t)?a:t)}}function r(e,t){var a=t-e +return a?i(e,a):(0,l.Z)(isNaN(e)?t:e)}},4472:(e,t,a)=>{"use strict" +a.d(t,{Z:()=>l}) +const l=e=>()=>e},6016:(e,t,a)=>{"use strict" +a.d(t,{ZP:()=>n,hD:()=>c}) +var l=a(2622) +function i(e,t,a,l,i){var o=e*e,n=o*e +return((1-3*e+3*o-n)*t+(4-6*o+3*n)*a+(1+3*e+3*o-3*n)*l+n*i)/6}var o=a(3068) +const n=function e(t){var a=(0,o.yi)(t) +function i(e,t){var i=a((e=(0,l.B8)(e)).r,(t=(0,l.B8)(t)).r),n=a(e.g,t.g),r=a(e.b,t.b),c=(0,o.ZP)(e.opacity,t.opacity) +return function(t){return e.r=i(t),e.g=n(t),e.b=r(t),e.opacity=c(t),e+""}}return i.gamma=e,i}(1) +function r(e){return function(t){var a,i,o=t.length,n=new Array(o),r=new Array(o),c=new Array(o) +for(a=0;a=1?(a=1,t-1):Math.floor(a*t),o=e[l],n=e[l+1],r=l>0?e[l-1]:2*o-n,c=l{"use strict" +function l(e){for(var t=e.length/6|0,a=new Array(t),l=0;loe,interpolateBrBG:()=>y,interpolateBuGn:()=>F,interpolateBuPu:()=>T,interpolateCividis:()=>me,interpolateCool:()=>Oe,interpolateCubehelixDefault:()=>Se,interpolateGnBu:()=>N,interpolateGreens:()=>re,interpolateGreys:()=>he,interpolateInferno:()=>Ze,interpolateMagma:()=>qe,interpolateOrRd:()=>R,interpolateOranges:()=>pe,interpolatePRGn:()=>b,interpolatePiYG:()=>M,interpolatePlasma:()=>Ye,interpolatePuBu:()=>$,interpolatePuBuGn:()=>I,interpolatePuOr:()=>w,interpolatePuRd:()=>Z,interpolatePurples:()=>de,interpolateRainbow:()=>Pe,interpolateRdBu:()=>H,interpolateRdGy:()=>_,interpolateRdPu:()=>K,interpolateRdYlBu:()=>L,interpolateRdYlGn:()=>E,interpolateReds:()=>fe,interpolateSinebow:()=>je,interpolateSpectral:()=>D,interpolateTurbo:()=>Ie,interpolateViridis:()=>$e,interpolateWarm:()=>Fe,interpolateYlGn:()=>Q,interpolateYlGnBu:()=>X,interpolateYlOrBr:()=>te,interpolateYlOrRd:()=>le,schemeAccent:()=>o,schemeBlues:()=>ie,schemeBrBG:()=>m,schemeBuGn:()=>S,schemeBuPu:()=>O,schemeCategory10:()=>i,schemeDark2:()=>n,schemeGnBu:()=>P,schemeGreens:()=>ne,schemeGreys:()=>ce,schemeOrRd:()=>U,schemeOranges:()=>ve,schemePRGn:()=>g,schemePaired:()=>r,schemePastel1:()=>c,schemePastel2:()=>h,schemePiYG:()=>z,schemePuBu:()=>G,schemePuBuGn:()=>j,schemePuOr:()=>A,schemePuRd:()=>q,schemePurples:()=>se,schemeRdBu:()=>x,schemeRdGy:()=>V,schemeRdPu:()=>Y,schemeRdYlBu:()=>B,schemeRdYlGn:()=>C,schemeReds:()=>ue,schemeSet1:()=>s,schemeSet2:()=>d,schemeSet3:()=>u,schemeSpectral:()=>k,schemeTableau10:()=>f,schemeYlGn:()=>J,schemeYlGnBu:()=>W,schemeYlOrBr:()=>ee,schemeYlOrRd:()=>ae}) +const i=l("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"),o=l("7fc97fbeaed4fdc086ffff99386cb0f0027fbf5b17666666"),n=l("1b9e77d95f027570b3e7298a66a61ee6ab02a6761d666666"),r=l("a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928"),c=l("fbb4aeb3cde3ccebc5decbe4fed9a6ffffcce5d8bdfddaecf2f2f2"),h=l("b3e2cdfdcdaccbd5e8f4cae4e6f5c9fff2aef1e2cccccccc"),s=l("e41a1c377eb84daf4a984ea3ff7f00ffff33a65628f781bf999999"),d=l("66c2a5fc8d628da0cbe78ac3a6d854ffd92fe5c494b3b3b3"),u=l("8dd3c7ffffb3bebadafb807280b1d3fdb462b3de69fccde5d9d9d9bc80bdccebc5ffed6f"),f=l("4e79a7f28e2ce1575976b7b259a14fedc949af7aa1ff9da79c755fbab0ab") +var v=a(6016) +const p=e=>(0,v.hD)(e[e.length-1]) +var m=new Array(3).concat("d8b365f5f5f55ab4ac","a6611adfc27d80cdc1018571","a6611adfc27df5f5f580cdc1018571","8c510ad8b365f6e8c3c7eae55ab4ac01665e","8c510ad8b365f6e8c3f5f5f5c7eae55ab4ac01665e","8c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e","8c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e","5430058c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e003c30","5430058c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e003c30").map(l) +const y=p(m) +var g=new Array(3).concat("af8dc3f7f7f77fbf7b","7b3294c2a5cfa6dba0008837","7b3294c2a5cff7f7f7a6dba0008837","762a83af8dc3e7d4e8d9f0d37fbf7b1b7837","762a83af8dc3e7d4e8f7f7f7d9f0d37fbf7b1b7837","762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b7837","762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b7837","40004b762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b783700441b","40004b762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b783700441b").map(l) +const b=p(g) +var z=new Array(3).concat("e9a3c9f7f7f7a1d76a","d01c8bf1b6dab8e1864dac26","d01c8bf1b6daf7f7f7b8e1864dac26","c51b7de9a3c9fde0efe6f5d0a1d76a4d9221","c51b7de9a3c9fde0eff7f7f7e6f5d0a1d76a4d9221","c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221","c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221","8e0152c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221276419","8e0152c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221276419").map(l) +const M=p(z) +var A=new Array(3).concat("998ec3f7f7f7f1a340","5e3c99b2abd2fdb863e66101","5e3c99b2abd2f7f7f7fdb863e66101","542788998ec3d8daebfee0b6f1a340b35806","542788998ec3d8daebf7f7f7fee0b6f1a340b35806","5427888073acb2abd2d8daebfee0b6fdb863e08214b35806","5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b35806","2d004b5427888073acb2abd2d8daebfee0b6fdb863e08214b358067f3b08","2d004b5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b358067f3b08").map(l) +const w=p(A) +var x=new Array(3).concat("ef8a62f7f7f767a9cf","ca0020f4a58292c5de0571b0","ca0020f4a582f7f7f792c5de0571b0","b2182bef8a62fddbc7d1e5f067a9cf2166ac","b2182bef8a62fddbc7f7f7f7d1e5f067a9cf2166ac","b2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac","b2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac","67001fb2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac053061","67001fb2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac053061").map(l) +const H=p(x) +var V=new Array(3).concat("ef8a62ffffff999999","ca0020f4a582bababa404040","ca0020f4a582ffffffbababa404040","b2182bef8a62fddbc7e0e0e09999994d4d4d","b2182bef8a62fddbc7ffffffe0e0e09999994d4d4d","b2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d","b2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d","67001fb2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d1a1a1a","67001fb2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d1a1a1a").map(l) +const _=p(V) +var B=new Array(3).concat("fc8d59ffffbf91bfdb","d7191cfdae61abd9e92c7bb6","d7191cfdae61ffffbfabd9e92c7bb6","d73027fc8d59fee090e0f3f891bfdb4575b4","d73027fc8d59fee090ffffbfe0f3f891bfdb4575b4","d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4","d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4","a50026d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4313695","a50026d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4313695").map(l) +const L=p(B) +var C=new Array(3).concat("fc8d59ffffbf91cf60","d7191cfdae61a6d96a1a9641","d7191cfdae61ffffbfa6d96a1a9641","d73027fc8d59fee08bd9ef8b91cf601a9850","d73027fc8d59fee08bffffbfd9ef8b91cf601a9850","d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850","d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850","a50026d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850006837","a50026d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850006837").map(l) +const E=p(C) +var k=new Array(3).concat("fc8d59ffffbf99d594","d7191cfdae61abdda42b83ba","d7191cfdae61ffffbfabdda42b83ba","d53e4ffc8d59fee08be6f59899d5943288bd","d53e4ffc8d59fee08bffffbfe6f59899d5943288bd","d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd","d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd","9e0142d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd5e4fa2","9e0142d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd5e4fa2").map(l) +const D=p(k) +var S=new Array(3).concat("e5f5f999d8c92ca25f","edf8fbb2e2e266c2a4238b45","edf8fbb2e2e266c2a42ca25f006d2c","edf8fbccece699d8c966c2a42ca25f006d2c","edf8fbccece699d8c966c2a441ae76238b45005824","f7fcfde5f5f9ccece699d8c966c2a441ae76238b45005824","f7fcfde5f5f9ccece699d8c966c2a441ae76238b45006d2c00441b").map(l) +const F=p(S) +var O=new Array(3).concat("e0ecf49ebcda8856a7","edf8fbb3cde38c96c688419d","edf8fbb3cde38c96c68856a7810f7c","edf8fbbfd3e69ebcda8c96c68856a7810f7c","edf8fbbfd3e69ebcda8c96c68c6bb188419d6e016b","f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d6e016b","f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d810f7c4d004b").map(l) +const T=p(O) +var P=new Array(3).concat("e0f3dba8ddb543a2ca","f0f9e8bae4bc7bccc42b8cbe","f0f9e8bae4bc7bccc443a2ca0868ac","f0f9e8ccebc5a8ddb57bccc443a2ca0868ac","f0f9e8ccebc5a8ddb57bccc44eb3d32b8cbe08589e","f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe08589e","f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe0868ac084081").map(l) +const N=p(P) +var U=new Array(3).concat("fee8c8fdbb84e34a33","fef0d9fdcc8afc8d59d7301f","fef0d9fdcc8afc8d59e34a33b30000","fef0d9fdd49efdbb84fc8d59e34a33b30000","fef0d9fdd49efdbb84fc8d59ef6548d7301f990000","fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301f990000","fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301fb300007f0000").map(l) +const R=p(U) +var j=new Array(3).concat("ece2f0a6bddb1c9099","f6eff7bdc9e167a9cf02818a","f6eff7bdc9e167a9cf1c9099016c59","f6eff7d0d1e6a6bddb67a9cf1c9099016c59","f6eff7d0d1e6a6bddb67a9cf3690c002818a016450","fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016450","fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016c59014636").map(l) +const I=p(j) +var G=new Array(3).concat("ece7f2a6bddb2b8cbe","f1eef6bdc9e174a9cf0570b0","f1eef6bdc9e174a9cf2b8cbe045a8d","f1eef6d0d1e6a6bddb74a9cf2b8cbe045a8d","f1eef6d0d1e6a6bddb74a9cf3690c00570b0034e7b","fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0034e7b","fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0045a8d023858").map(l) +const $=p(G) +var q=new Array(3).concat("e7e1efc994c7dd1c77","f1eef6d7b5d8df65b0ce1256","f1eef6d7b5d8df65b0dd1c77980043","f1eef6d4b9dac994c7df65b0dd1c77980043","f1eef6d4b9dac994c7df65b0e7298ace125691003f","f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125691003f","f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125698004367001f").map(l) +const Z=p(q) +var Y=new Array(3).concat("fde0ddfa9fb5c51b8a","feebe2fbb4b9f768a1ae017e","feebe2fbb4b9f768a1c51b8a7a0177","feebe2fcc5c0fa9fb5f768a1c51b8a7a0177","feebe2fcc5c0fa9fb5f768a1dd3497ae017e7a0177","fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a0177","fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a017749006a").map(l) +const K=p(Y) +var W=new Array(3).concat("edf8b17fcdbb2c7fb8","ffffcca1dab441b6c4225ea8","ffffcca1dab441b6c42c7fb8253494","ffffccc7e9b47fcdbb41b6c42c7fb8253494","ffffccc7e9b47fcdbb41b6c41d91c0225ea80c2c84","ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea80c2c84","ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea8253494081d58").map(l) +const X=p(W) +var J=new Array(3).concat("f7fcb9addd8e31a354","ffffccc2e69978c679238443","ffffccc2e69978c67931a354006837","ffffccd9f0a3addd8e78c67931a354006837","ffffccd9f0a3addd8e78c67941ab5d238443005a32","ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443005a32","ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443006837004529").map(l) +const Q=p(J) +var ee=new Array(3).concat("fff7bcfec44fd95f0e","ffffd4fed98efe9929cc4c02","ffffd4fed98efe9929d95f0e993404","ffffd4fee391fec44ffe9929d95f0e993404","ffffd4fee391fec44ffe9929ec7014cc4c028c2d04","ffffe5fff7bcfee391fec44ffe9929ec7014cc4c028c2d04","ffffe5fff7bcfee391fec44ffe9929ec7014cc4c02993404662506").map(l) +const te=p(ee) +var ae=new Array(3).concat("ffeda0feb24cf03b20","ffffb2fecc5cfd8d3ce31a1c","ffffb2fecc5cfd8d3cf03b20bd0026","ffffb2fed976feb24cfd8d3cf03b20bd0026","ffffb2fed976feb24cfd8d3cfc4e2ae31a1cb10026","ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cb10026","ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cbd0026800026").map(l) +const le=p(ae) +var ie=new Array(3).concat("deebf79ecae13182bd","eff3ffbdd7e76baed62171b5","eff3ffbdd7e76baed63182bd08519c","eff3ffc6dbef9ecae16baed63182bd08519c","eff3ffc6dbef9ecae16baed64292c62171b5084594","f7fbffdeebf7c6dbef9ecae16baed64292c62171b5084594","f7fbffdeebf7c6dbef9ecae16baed64292c62171b508519c08306b").map(l) +const oe=p(ie) +var ne=new Array(3).concat("e5f5e0a1d99b31a354","edf8e9bae4b374c476238b45","edf8e9bae4b374c47631a354006d2c","edf8e9c7e9c0a1d99b74c47631a354006d2c","edf8e9c7e9c0a1d99b74c47641ab5d238b45005a32","f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45005a32","f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45006d2c00441b").map(l) +const re=p(ne) +var ce=new Array(3).concat("f0f0f0bdbdbd636363","f7f7f7cccccc969696525252","f7f7f7cccccc969696636363252525","f7f7f7d9d9d9bdbdbd969696636363252525","f7f7f7d9d9d9bdbdbd969696737373525252252525","fffffff0f0f0d9d9d9bdbdbd969696737373525252252525","fffffff0f0f0d9d9d9bdbdbd969696737373525252252525000000").map(l) +const he=p(ce) +var se=new Array(3).concat("efedf5bcbddc756bb1","f2f0f7cbc9e29e9ac86a51a3","f2f0f7cbc9e29e9ac8756bb154278f","f2f0f7dadaebbcbddc9e9ac8756bb154278f","f2f0f7dadaebbcbddc9e9ac8807dba6a51a34a1486","fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a34a1486","fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a354278f3f007d").map(l) +const de=p(se) +var ue=new Array(3).concat("fee0d2fc9272de2d26","fee5d9fcae91fb6a4acb181d","fee5d9fcae91fb6a4ade2d26a50f15","fee5d9fcbba1fc9272fb6a4ade2d26a50f15","fee5d9fcbba1fc9272fb6a4aef3b2ccb181d99000d","fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181d99000d","fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181da50f1567000d").map(l) +const fe=p(ue) +var ve=new Array(3).concat("fee6cefdae6be6550d","feeddefdbe85fd8d3cd94701","feeddefdbe85fd8d3ce6550da63603","feeddefdd0a2fdae6bfd8d3ce6550da63603","feeddefdd0a2fdae6bfd8d3cf16913d948018c2d04","fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d948018c2d04","fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d94801a636037f2704").map(l) +const pe=p(ve) +function me(e){return e=Math.max(0,Math.min(1,e)),"rgb("+Math.max(0,Math.min(255,Math.round(-4.54-e*(35.34-e*(2381.73-e*(6402.7-e*(7024.72-2710.57*e)))))))+", "+Math.max(0,Math.min(255,Math.round(32.49+e*(170.73+e*(52.82-e*(131.46-e*(176.58-67.37*e)))))))+", "+Math.max(0,Math.min(255,Math.round(81.24+e*(442.36-e*(2482.43-e*(6167.24-e*(6614.94-2475.67*e)))))))+")"}var ye=a(8797),ge=a(2622) +const be=Math.PI/180,ze=180/Math.PI +var Me=-.14861,Ae=1.78277,we=-.29227,xe=-.90649,He=1.97294,Ve=He*xe,_e=He*Ae,Be=Ae*we-xe*Me +function Le(e,t,a,l){return 1===arguments.length?function(e){if(e instanceof Ce)return new Ce(e.h,e.s,e.l,e.opacity) +e instanceof ge.Ss||(e=(0,ge.SU)(e)) +var t=e.r/255,a=e.g/255,l=e.b/255,i=(Be*l+Ve*t-_e*a)/(Be+Ve-_e),o=l-i,n=(He*(a-i)-we*o)/xe,r=Math.sqrt(n*n+o*o)/(He*i*(1-i)),c=r?Math.atan2(n,o)*ze-120:NaN +return new Ce(c<0?c+360:c,r,i,e.opacity)}(e):new Ce(e,t,a,null==l?1:l)}function Ce(e,t,a,l){this.h=+e,this.s=+t,this.l=+a,this.opacity=+l}(0,ye.Z)(Ce,Le,(0,ye.l)(ge.Il,{brighter:function(e){return e=null==e?ge.J5:Math.pow(ge.J5,e),new Ce(this.h,this.s,this.l*e,this.opacity)},darker:function(e){return e=null==e?ge.xV:Math.pow(ge.xV,e),new Ce(this.h,this.s,this.l*e,this.opacity)},rgb:function(){var e=isNaN(this.h)?0:(this.h+120)*be,t=+this.l,a=isNaN(this.s)?0:this.s*t*(1-t),l=Math.cos(e),i=Math.sin(e) +return new ge.Ss(255*(t+a*(Me*l+Ae*i)),255*(t+a*(we*l+xe*i)),255*(t+a*(He*l)),this.opacity)}})) +var Ee=a(3068) +function ke(e){return function t(a){function l(t,l){var i=e((t=Le(t)).h,(l=Le(l)).h),o=(0,Ee.ZP)(t.s,l.s),n=(0,Ee.ZP)(t.l,l.l),r=(0,Ee.ZP)(t.opacity,l.opacity) +return function(e){return t.h=i(e),t.s=o(e),t.l=n(Math.pow(e,a)),t.opacity=r(e),t+""}}return a=+a,l.gamma=t,l}(1)}ke(Ee.wx) +var De=ke(Ee.ZP) +const Se=De(Le(300,.5,0),Le(-240,.5,1)) +var Fe=De(Le(-100,.75,.35),Le(80,1.5,.8)),Oe=De(Le(260,.75,.35),Le(80,1.5,.8)),Te=Le() +function Pe(e){(e<0||e>1)&&(e-=Math.floor(e)) +var t=Math.abs(e-.5) +return Te.h=360*e-100,Te.s=1.5-1.5*t,Te.l=.8-.9*t,Te+""}var Ne=(0,ge.B8)(),Ue=Math.PI/3,Re=2*Math.PI/3 +function je(e){var t +return e=(.5-e)*Math.PI,Ne.r=255*(t=Math.sin(e))*t,Ne.g=255*(t=Math.sin(e+Ue))*t,Ne.b=255*(t=Math.sin(e+Re))*t,Ne+""}function Ie(e){return e=Math.max(0,Math.min(1,e)),"rgb("+Math.max(0,Math.min(255,Math.round(34.61+e*(1172.33-e*(10793.56-e*(33300.12-e*(38394.49-14825.05*e)))))))+", "+Math.max(0,Math.min(255,Math.round(23.31+e*(557.33+e*(1225.33-e*(3574.96-e*(1073.77+707.56*e)))))))+", "+Math.max(0,Math.min(255,Math.round(27.2+e*(3211.1-e*(15327.97-e*(27814-e*(22569.18-6838.66*e)))))))+")"}function Ge(e){var t=e.length +return function(a){return e[Math.max(0,Math.min(t-1,Math.floor(a*t)))]}}const $e=Ge(l("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")) +var qe=Ge(l("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")),Ze=Ge(l("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")),Ye=Ge(l("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"))},5134:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{scaleBand:()=>c,scaleDiverging:()=>sl,scaleDivergingLog:()=>dl,scaleDivergingPow:()=>fl,scaleDivergingSqrt:()=>vl,scaleDivergingSymlog:()=>ul,scaleIdentity:()=>J,scaleImplicit:()=>n,scaleLinear:()=>X,scaleLog:()=>re,scaleOrdinal:()=>r,scalePoint:()=>s,scalePow:()=>me,scaleQuantile:()=>Ae,scaleQuantize:()=>we,scaleRadial:()=>be,scaleSequential:()=>ll,scaleSequentialLog:()=>il,scaleSequentialPow:()=>nl,scaleSequentialQuantile:()=>cl,scaleSequentialSqrt:()=>rl,scaleSequentialSymlog:()=>ol,scaleSqrt:()=>ye,scaleSymlog:()=>de,scaleThreshold:()=>xe,scaleTime:()=>Qa,scaleUtc:()=>el,tickFormat:()=>K}) +var l=a(5232) +function i(e,t){switch(arguments.length){case 0:break +case 1:this.range(e) +break +default:this.range(t).domain(e)}return this}function o(e,t){switch(arguments.length){case 0:break +case 1:"function"==typeof e?this.interpolator(e):this.range(e) +break +default:this.domain(e),"function"==typeof t?this.interpolator(t):this.range(t)}return this}const n=Symbol("implicit") +function r(){var e=new Map,t=[],a=[],l=n +function o(i){var o=i+"",r=e.get(o) +if(!r){if(l!==n)return l +e.set(o,r=t.push(i))}return a[(r-1)%a.length]}return o.domain=function(a){if(!arguments.length)return t.slice() +t=[],e=new Map +for(const l of a){const a=l+"" +e.has(a)||e.set(a,t.push(l))}return o},o.range=function(e){return arguments.length?(a=Array.from(e),o):a.slice()},o.unknown=function(e){return arguments.length?(l=e,o):l},o.copy=function(){return r(t,a).unknown(l)},i.apply(o,arguments),o}function c(){var e,t,a=r().unknown(void 0),o=a.domain,n=a.range,h=0,s=1,d=!1,u=0,f=0,v=.5 +function p(){var a=o().length,i=so&&(i=t.slice(o,i),r[n]?r[n]+=i:r[++n]=i),(a=a[0])===(l=l[0])?r[n]?r[n]+=l:r[++n]=l:(r[++n]=null,c.push({i:n,x:y(a,l)})),o=z.lastIndex +return ot&&(a=e,e=t,t=a),h=function(a){return Math.max(e,Math.min(t,a))}),l=c>2?E:C,i=o=null,d}function d(t){return null==t||isNaN(t=+t)?a:(i||(i=l(n.map(e),r,c)))(e(h(t)))}return d.invert=function(a){return h(t((o||(o=l(r,n.map(e),y)))(a)))},d.domain=function(e){return arguments.length?(n=Array.from(e,V),s()):n.slice()},d.range=function(e){return arguments.length?(r=Array.from(e),s()):r.slice()},d.rangeRound=function(e){return r=Array.from(e),c=H,s()},d.clamp=function(e){return arguments.length?(h=!!e||B,s()):h!==B},d.interpolate=function(e){return arguments.length?(c=e,s()):c},d.unknown=function(e){return arguments.length?(a=e,d):a},function(a,l){return e=a,t=l,s()}}function S(){return D()(B,B)}var F,O=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i +function T(e){if(!(t=O.exec(e)))throw new Error("invalid format: "+e) +var t +return new P({fill:t[1],align:t[2],sign:t[3],symbol:t[4],zero:t[5],width:t[6],comma:t[7],precision:t[8]&&t[8].slice(1),trim:t[9],type:t[10]})}function P(e){this.fill=void 0===e.fill?" ":e.fill+"",this.align=void 0===e.align?">":e.align+"",this.sign=void 0===e.sign?"-":e.sign+"",this.symbol=void 0===e.symbol?"":e.symbol+"",this.zero=!!e.zero,this.width=void 0===e.width?void 0:+e.width,this.comma=!!e.comma,this.precision=void 0===e.precision?void 0:+e.precision,this.trim=!!e.trim,this.type=void 0===e.type?"":e.type+""}function N(e,t){if((a=(e=t?e.toExponential(t-1):e.toExponential()).indexOf("e"))<0)return null +var a,l=e.slice(0,a) +return[l.length>1?l[0]+l.slice(2):l,+e.slice(a+1)]}function U(e){return(e=N(Math.abs(e)))?e[1]:NaN}function R(e,t){var a=N(e,t) +if(!a)return e+"" +var l=a[0],i=a[1] +return i<0?"0."+new Array(-i).join("0")+l:l.length>i+1?l.slice(0,i+1)+"."+l.slice(i+1):l+new Array(i-l.length+2).join("0")}T.prototype=P.prototype,P.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type} +const j={"%":(e,t)=>(100*e).toFixed(t),b:e=>Math.round(e).toString(2),c:e=>e+"",d:function(e){return Math.abs(e=Math.round(e))>=1e21?e.toLocaleString("en").replace(/,/g,""):e.toString(10)},e:(e,t)=>e.toExponential(t),f:(e,t)=>e.toFixed(t),g:(e,t)=>e.toPrecision(t),o:e=>Math.round(e).toString(8),p:(e,t)=>R(100*e,t),r:R,s:function(e,t){var a=N(e,t) +if(!a)return e+"" +var l=a[0],i=a[1],o=i-(F=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,n=l.length +return o===n?l:o>n?l+new Array(o-n+1).join("0"):o>0?l.slice(0,o)+"."+l.slice(o):"0."+new Array(1-o).join("0")+N(e,Math.max(0,t+o-1))[0]},X:e=>Math.round(e).toString(16).toUpperCase(),x:e=>Math.round(e).toString(16)} +function I(e){return e}var G,$,q,Z=Array.prototype.map,Y=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"] +function K(e,t,a,l){var i,o=(0,d.ly)(e,t,a) +switch((l=T(null==l?",f":l)).type){case"s":var n=Math.max(Math.abs(e),Math.abs(t)) +return null!=l.precision||isNaN(i=function(e,t){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(U(t)/3)))-U(Math.abs(e)))}(o,n))||(l.precision=i),q(l,n) +case"":case"e":case"g":case"p":case"r":null!=l.precision||isNaN(i=function(e,t){return e=Math.abs(e),t=Math.abs(t)-e,Math.max(0,U(t)-U(e))+1}(o,Math.max(Math.abs(e),Math.abs(t))))||(l.precision=i-("e"===l.type)) +break +case"f":case"%":null!=l.precision||isNaN(i=function(e){return Math.max(0,-U(Math.abs(e)))}(o))||(l.precision=i-2*("%"===l.type))}return $(l)}function W(e){var t=e.domain +return e.ticks=function(e){var a=t() +return(0,d.ZP)(a[0],a[a.length-1],null==e?10:e)},e.tickFormat=function(e,a){var l=t() +return K(l[0],l[l.length-1],null==e?10:e,a)},e.nice=function(a){null==a&&(a=10) +var l,i,o=t(),n=0,r=o.length-1,c=o[n],h=o[r],s=10 +for(h0;){if((i=(0,d.G9)(c,h,a))===l)return o[n]=c,o[r]=h,t(o) +if(i>0)c=Math.floor(c/i)*i,h=Math.ceil(h/i)*i +else{if(!(i<0))break +c=Math.ceil(c*i)/i,h=Math.floor(h*i)/i}l=i}return e},e}function X(){var e=S() +return e.copy=function(){return k(e,X())},i.apply(e,arguments),W(e)}function J(e){var t +function a(e){return null==e||isNaN(e=+e)?t:e}return a.invert=a,a.domain=a.range=function(t){return arguments.length?(e=Array.from(t,V),a):e.slice()},a.unknown=function(e){return arguments.length?(t=e,a):t},a.copy=function(){return J(e).unknown(t)},e=arguments.length?Array.from(e,V):[0,1],W(a)}function Q(e,t){var a,l=0,i=(e=e.slice()).length-1,o=e[l],n=e[i] +return n0){for(;f<=v;++f)for(s=1,h=a(f);sc)break +m.push(u)}}else for(;f<=v;++f)for(s=o-1,h=a(f);s>=1;--s)if(!((u=h*s)c)break +m.push(u)}2*m.length0&&r>0&&(c+r+1>l&&(r=Math.max(1,l-c)),o.push(e.substring(i-=r,i+r)),!((c+=r+1)>l));)r=t[n=(n+1)%t.length] +return o.reverse().join(a)}),i=void 0===e.currency?"":e.currency[0]+"",o=void 0===e.currency?"":e.currency[1]+"",n=void 0===e.decimal?".":e.decimal+"",r=void 0===e.numerals?I:function(e){return function(t){return t.replace(/[0-9]/g,(function(t){return e[+t]}))}}(Z.call(e.numerals,String)),c=void 0===e.percent?"%":e.percent+"",h=void 0===e.minus?"−":e.minus+"",s=void 0===e.nan?"NaN":e.nan+"" +function d(e){var t=(e=T(e)).fill,a=e.align,d=e.sign,u=e.symbol,f=e.zero,v=e.width,p=e.comma,m=e.precision,y=e.trim,g=e.type +"n"===g?(p=!0,g="g"):j[g]||(void 0===m&&(m=12),y=!0,g="g"),(f||"0"===t&&"="===a)&&(f=!0,t="0",a="=") +var b="$"===u?i:"#"===u&&/[boxX]/.test(g)?"0"+g.toLowerCase():"",z="$"===u?o:/[%p]/.test(g)?c:"",M=j[g],A=/[defgprs%]/.test(g) +function w(e){var i,o,c,u=b,w=z +if("c"===g)w=M(e)+w,e="" +else{var x=(e=+e)<0||1/e<0 +if(e=isNaN(e)?s:M(Math.abs(e),m),y&&(e=function(e){e:for(var t,a=e.length,l=1,i=-1;l0&&(i=0)}return i>0?e.slice(0,i)+e.slice(t+1):e}(e)),x&&0==+e&&"+"!==d&&(x=!1),u=(x?"("===d?d:h:"-"===d||"("===d?"":d)+u,w=("s"===g?Y[8+F/3]:"")+w+(x&&"("===d?")":""),A)for(i=-1,o=e.length;++i(c=e.charCodeAt(i))||c>57){w=(46===c?n+e.slice(i+1):e.slice(i))+w,e=e.slice(0,i) +break}}p&&!f&&(e=l(e,1/0)) +var H=u.length+e.length+w.length,V=H>1)+u+e+w+V.slice(H) +break +default:e=V+u+e+w}return r(e)}return m=void 0===m?6:/[gprs]/.test(g)?Math.max(1,Math.min(21,m)):Math.max(0,Math.min(20,m)),w.toString=function(){return e+""},w}return{format:d,formatPrefix:function(e,t){var a=d(((e=T(e)).type="f",e)),l=3*Math.max(-8,Math.min(8,Math.floor(U(t)/3))),i=Math.pow(10,-l),o=Y[8+l/3] +return function(e){return a(i*e)+o}}}}({thousands:",",grouping:[3],currency:["$",""]}),$=G.format,q=G.formatPrefix +var ze=a(1657),Me=a(9731) +function Ae(){var e,t=[],a=[],l=[] +function o(){var e=0,i=Math.max(1,a.length) +for(l=new Array(i-1);++e0?l[i-1]:t[0],i=l?[o[l-1],a]:[o[i-1],o[i]]},r.unknown=function(t){return arguments.length?(e=t,r):r},r.thresholds=function(){return o.slice()},r.copy=function(){return we().domain([t,a]).range(n).unknown(e)},i.apply(W(r),arguments)}function xe(){var e,t=[.5],a=[0,1],l=1 +function o(i){return null!=i&&i<=i?a[(0,u.ZP)(t,i,0,l)]:e}return o.domain=function(e){return arguments.length?(t=Array.from(e),l=Math.min(t.length,a.length-1),o):t.slice()},o.range=function(e){return arguments.length?(a=Array.from(e),l=Math.min(t.length,a.length-1),o):a.slice()},o.invertExtent=function(e){var l=a.indexOf(e) +return[t[l-1],t[l]]},o.unknown=function(t){return arguments.length?(e=t,o):e},o.copy=function(){return xe().domain(t).range(a).unknown(e)},i.apply(o,arguments)}var He=a(7870) +const Ve=1e3,_e=60*Ve,Be=60*_e,Le=24*Be,Ce=7*Le,Ee=30*Le,ke=365*Le +var De=new Date,Se=new Date +function Fe(e,t,a,l){function i(t){return e(t=0===arguments.length?new Date:new Date(+t)),t}return i.floor=function(t){return e(t=new Date(+t)),t},i.ceil=function(a){return e(a=new Date(a-1)),t(a,1),e(a),a},i.round=function(e){var t=i(e),a=i.ceil(e) +return e-t0))return r +do{r.push(n=new Date(+a)),t(a,o),e(a)}while(n=t)for(;e(t),!a(t);)t.setTime(t-1)}),(function(e,l){if(e>=e)if(l<0)for(;++l<=0;)for(;t(e,-1),!a(e););else for(;--l>=0;)for(;t(e,1),!a(e););}))},a&&(i.count=function(t,l){return De.setTime(+t),Se.setTime(+l),e(De),e(Se),Math.floor(a(De,Se))},i.every=function(e){return e=Math.floor(e),isFinite(e)&&e>0?e>1?i.filter(l?function(t){return l(t)%e==0}:function(t){return i.count(0,t)%e==0}):i:null}),i}var Oe=Fe((function(){}),(function(e,t){e.setTime(+e+t)}),(function(e,t){return t-e})) +Oe.every=function(e){return e=Math.floor(e),isFinite(e)&&e>0?e>1?Fe((function(t){t.setTime(Math.floor(t/e)*e)}),(function(t,a){t.setTime(+t+a*e)}),(function(t,a){return(a-t)/e})):Oe:null} +const Te=Oe +Oe.range +var Pe=Fe((function(e){e.setTime(e-e.getMilliseconds())}),(function(e,t){e.setTime(+e+t*Ve)}),(function(e,t){return(t-e)/Ve}),(function(e){return e.getUTCSeconds()})) +const Ne=Pe +Pe.range +var Ue=Fe((function(e){e.setTime(e-e.getMilliseconds()-e.getSeconds()*Ve)}),(function(e,t){e.setTime(+e+t*_e)}),(function(e,t){return(t-e)/_e}),(function(e){return e.getMinutes()})) +const Re=Ue +Ue.range +var je=Fe((function(e){e.setTime(e-e.getMilliseconds()-e.getSeconds()*Ve-e.getMinutes()*_e)}),(function(e,t){e.setTime(+e+t*Be)}),(function(e,t){return(t-e)/Be}),(function(e){return e.getHours()})) +const Ie=je +je.range +var Ge=Fe((e=>e.setHours(0,0,0,0)),((e,t)=>e.setDate(e.getDate()+t)),((e,t)=>(t-e-(t.getTimezoneOffset()-e.getTimezoneOffset())*_e)/Le),(e=>e.getDate()-1)) +const $e=Ge +function qe(e){return Fe((function(t){t.setDate(t.getDate()-(t.getDay()+7-e)%7),t.setHours(0,0,0,0)}),(function(e,t){e.setDate(e.getDate()+7*t)}),(function(e,t){return(t-e-(t.getTimezoneOffset()-e.getTimezoneOffset())*_e)/Ce}))}Ge.range +var Ze=qe(0),Ye=qe(1),Ke=qe(2),We=qe(3),Xe=qe(4),Je=qe(5),Qe=qe(6),et=(Ze.range,Ye.range,Ke.range,We.range,Xe.range,Je.range,Qe.range,Fe((function(e){e.setDate(1),e.setHours(0,0,0,0)}),(function(e,t){e.setMonth(e.getMonth()+t)}),(function(e,t){return t.getMonth()-e.getMonth()+12*(t.getFullYear()-e.getFullYear())}),(function(e){return e.getMonth()}))) +const tt=et +et.range +var at=Fe((function(e){e.setMonth(0,1),e.setHours(0,0,0,0)}),(function(e,t){e.setFullYear(e.getFullYear()+t)}),(function(e,t){return t.getFullYear()-e.getFullYear()}),(function(e){return e.getFullYear()})) +at.every=function(e){return isFinite(e=Math.floor(e))&&e>0?Fe((function(t){t.setFullYear(Math.floor(t.getFullYear()/e)*e),t.setMonth(0,1),t.setHours(0,0,0,0)}),(function(t,a){t.setFullYear(t.getFullYear()+a*e)})):null} +const lt=at +at.range +var it=Fe((function(e){e.setUTCSeconds(0,0)}),(function(e,t){e.setTime(+e+t*_e)}),(function(e,t){return(t-e)/_e}),(function(e){return e.getUTCMinutes()})) +const ot=it +it.range +var nt=Fe((function(e){e.setUTCMinutes(0,0,0)}),(function(e,t){e.setTime(+e+t*Be)}),(function(e,t){return(t-e)/Be}),(function(e){return e.getUTCHours()})) +const rt=nt +nt.range +var ct=Fe((function(e){e.setUTCHours(0,0,0,0)}),(function(e,t){e.setUTCDate(e.getUTCDate()+t)}),(function(e,t){return(t-e)/Le}),(function(e){return e.getUTCDate()-1})) +const ht=ct +function st(e){return Fe((function(t){t.setUTCDate(t.getUTCDate()-(t.getUTCDay()+7-e)%7),t.setUTCHours(0,0,0,0)}),(function(e,t){e.setUTCDate(e.getUTCDate()+7*t)}),(function(e,t){return(t-e)/Ce}))}ct.range +var dt=st(0),ut=st(1),ft=st(2),vt=st(3),pt=st(4),mt=st(5),yt=st(6),gt=(dt.range,ut.range,ft.range,vt.range,pt.range,mt.range,yt.range,Fe((function(e){e.setUTCDate(1),e.setUTCHours(0,0,0,0)}),(function(e,t){e.setUTCMonth(e.getUTCMonth()+t)}),(function(e,t){return t.getUTCMonth()-e.getUTCMonth()+12*(t.getUTCFullYear()-e.getUTCFullYear())}),(function(e){return e.getUTCMonth()}))) +const bt=gt +gt.range +var zt=Fe((function(e){e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)}),(function(e,t){e.setUTCFullYear(e.getUTCFullYear()+t)}),(function(e,t){return t.getUTCFullYear()-e.getUTCFullYear()}),(function(e){return e.getUTCFullYear()})) +zt.every=function(e){return isFinite(e=Math.floor(e))&&e>0?Fe((function(t){t.setUTCFullYear(Math.floor(t.getUTCFullYear()/e)*e),t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),(function(t,a){t.setUTCFullYear(t.getUTCFullYear()+a*e)})):null} +const Mt=zt +function At(e,t,a,l,i,o){const n=[[Ne,1,Ve],[Ne,5,5*Ve],[Ne,15,15*Ve],[Ne,30,30*Ve],[o,1,_e],[o,5,5*_e],[o,15,15*_e],[o,30,30*_e],[i,1,Be],[i,3,3*Be],[i,6,6*Be],[i,12,12*Be],[l,1,Le],[l,2,2*Le],[a,1,Ce],[t,1,Ee],[t,3,3*Ee],[e,1,ke]] +function r(t,a,l){const i=Math.abs(a-t)/l,o=(0,He.Z)((e=>{let[,,t]=e +return t})).right(n,i) +if(o===n.length)return e.every((0,d.ly)(t/ke,a/ke,l)) +if(0===o)return Te.every(Math.max((0,d.ly)(t,a,l),1)) +const[r,c]=n[i/n[o-1][2][e.toLowerCase(),t])))}function Rt(e,t,a){var l=St.exec(t.slice(a,a+1)) +return l?(e.w=+l[0],a+l[0].length):-1}function jt(e,t,a){var l=St.exec(t.slice(a,a+1)) +return l?(e.u=+l[0],a+l[0].length):-1}function It(e,t,a){var l=St.exec(t.slice(a,a+2)) +return l?(e.U=+l[0],a+l[0].length):-1}function Gt(e,t,a){var l=St.exec(t.slice(a,a+2)) +return l?(e.V=+l[0],a+l[0].length):-1}function $t(e,t,a){var l=St.exec(t.slice(a,a+2)) +return l?(e.W=+l[0],a+l[0].length):-1}function qt(e,t,a){var l=St.exec(t.slice(a,a+4)) +return l?(e.y=+l[0],a+l[0].length):-1}function Zt(e,t,a){var l=St.exec(t.slice(a,a+2)) +return l?(e.y=+l[0]+(+l[0]>68?1900:2e3),a+l[0].length):-1}function Yt(e,t,a){var l=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(t.slice(a,a+6)) +return l?(e.Z=l[1]?0:-(l[2]+(l[3]||"00")),a+l[0].length):-1}function Kt(e,t,a){var l=St.exec(t.slice(a,a+1)) +return l?(e.q=3*l[0]-3,a+l[0].length):-1}function Wt(e,t,a){var l=St.exec(t.slice(a,a+2)) +return l?(e.m=l[0]-1,a+l[0].length):-1}function Xt(e,t,a){var l=St.exec(t.slice(a,a+2)) +return l?(e.d=+l[0],a+l[0].length):-1}function Jt(e,t,a){var l=St.exec(t.slice(a,a+3)) +return l?(e.m=0,e.d=+l[0],a+l[0].length):-1}function Qt(e,t,a){var l=St.exec(t.slice(a,a+2)) +return l?(e.H=+l[0],a+l[0].length):-1}function ea(e,t,a){var l=St.exec(t.slice(a,a+2)) +return l?(e.M=+l[0],a+l[0].length):-1}function ta(e,t,a){var l=St.exec(t.slice(a,a+2)) +return l?(e.S=+l[0],a+l[0].length):-1}function aa(e,t,a){var l=St.exec(t.slice(a,a+3)) +return l?(e.L=+l[0],a+l[0].length):-1}function la(e,t,a){var l=St.exec(t.slice(a,a+6)) +return l?(e.L=Math.floor(l[0]/1e3),a+l[0].length):-1}function ia(e,t,a){var l=Ft.exec(t.slice(a,a+1)) +return l?a+l[0].length:-1}function oa(e,t,a){var l=St.exec(t.slice(a)) +return l?(e.Q=+l[0],a+l[0].length):-1}function na(e,t,a){var l=St.exec(t.slice(a)) +return l?(e.s=+l[0],a+l[0].length):-1}function ra(e,t){return Tt(e.getDate(),t,2)}function ca(e,t){return Tt(e.getHours(),t,2)}function ha(e,t){return Tt(e.getHours()%12||12,t,2)}function sa(e,t){return Tt(1+$e.count(lt(e),e),t,3)}function da(e,t){return Tt(e.getMilliseconds(),t,3)}function ua(e,t){return da(e,t)+"000"}function fa(e,t){return Tt(e.getMonth()+1,t,2)}function va(e,t){return Tt(e.getMinutes(),t,2)}function pa(e,t){return Tt(e.getSeconds(),t,2)}function ma(e){var t=e.getDay() +return 0===t?7:t}function ya(e,t){return Tt(Ze.count(lt(e)-1,e),t,2)}function ga(e){var t=e.getDay() +return t>=4||0===t?Xe(e):Xe.ceil(e)}function ba(e,t){return e=ga(e),Tt(Xe.count(lt(e),e)+(4===lt(e).getDay()),t,2)}function za(e){return e.getDay()}function Ma(e,t){return Tt(Ye.count(lt(e)-1,e),t,2)}function Aa(e,t){return Tt(e.getFullYear()%100,t,2)}function wa(e,t){return Tt((e=ga(e)).getFullYear()%100,t,2)}function xa(e,t){return Tt(e.getFullYear()%1e4,t,4)}function Ha(e,t){var a=e.getDay() +return Tt((e=a>=4||0===a?Xe(e):Xe.ceil(e)).getFullYear()%1e4,t,4)}function Va(e){var t=e.getTimezoneOffset() +return(t>0?"-":(t*=-1,"+"))+Tt(t/60|0,"0",2)+Tt(t%60,"0",2)}function _a(e,t){return Tt(e.getUTCDate(),t,2)}function Ba(e,t){return Tt(e.getUTCHours(),t,2)}function La(e,t){return Tt(e.getUTCHours()%12||12,t,2)}function Ca(e,t){return Tt(1+ht.count(Mt(e),e),t,3)}function Ea(e,t){return Tt(e.getUTCMilliseconds(),t,3)}function ka(e,t){return Ea(e,t)+"000"}function Da(e,t){return Tt(e.getUTCMonth()+1,t,2)}function Sa(e,t){return Tt(e.getUTCMinutes(),t,2)}function Fa(e,t){return Tt(e.getUTCSeconds(),t,2)}function Oa(e){var t=e.getUTCDay() +return 0===t?7:t}function Ta(e,t){return Tt(dt.count(Mt(e)-1,e),t,2)}function Pa(e){var t=e.getUTCDay() +return t>=4||0===t?pt(e):pt.ceil(e)}function Na(e,t){return e=Pa(e),Tt(pt.count(Mt(e),e)+(4===Mt(e).getUTCDay()),t,2)}function Ua(e){return e.getUTCDay()}function Ra(e,t){return Tt(ut.count(Mt(e)-1,e),t,2)}function ja(e,t){return Tt(e.getUTCFullYear()%100,t,2)}function Ia(e,t){return Tt((e=Pa(e)).getUTCFullYear()%100,t,2)}function Ga(e,t){return Tt(e.getUTCFullYear()%1e4,t,4)}function $a(e,t){var a=e.getUTCDay() +return Tt((e=a>=4||0===a?pt(e):pt.ceil(e)).getUTCFullYear()%1e4,t,4)}function qa(){return"+0000"}function Za(){return"%"}function Ya(e){return+e}function Ka(e){return Math.floor(+e/1e3)}function Wa(e){return new Date(e)}function Xa(e){return e instanceof Date?+e:+new Date(+e)}function Ja(e,t,a,l,i,o,n,r,c,h){var s=S(),d=s.invert,u=s.domain,f=h(".%L"),v=h(":%S"),p=h("%I:%M"),m=h("%I %p"),y=h("%a %d"),g=h("%b %d"),b=h("%B"),z=h("%Y") +function M(e){return(c(e)t(l/(e.length-1))))},a.quantiles=function(t){return Array.from({length:t+1},((a,l)=>(0,ze.Z)(e,l/t)))},a.copy=function(){return cl(t).domain(e)},o.apply(a,arguments)}function hl(){var e,t,a,l,i,o,n,r=0,c=.5,h=1,s=1,d=B,u=!1 +function f(e){return isNaN(e=+e)?n:(e=.5+((e=+o(e))-t)*(s*e=12)]},q:function(e){return 1+~~(e.getMonth()/3)},Q:Ya,s:Ka,S:pa,u:ma,U:ya,V:ba,w:za,W:Ma,x:null,X:null,y:Aa,Y:xa,Z:Va,"%":Za},z={a:function(e){return n[e.getUTCDay()]},A:function(e){return o[e.getUTCDay()]},b:function(e){return c[e.getUTCMonth()]},B:function(e){return r[e.getUTCMonth()]},c:null,d:_a,e:_a,f:ka,g:Ia,G:$a,H:Ba,I:La,j:Ca,L:Ea,m:Da,M:Sa,p:function(e){return i[+(e.getUTCHours()>=12)]},q:function(e){return 1+~~(e.getUTCMonth()/3)},Q:Ya,s:Ka,S:Fa,u:Oa,U:Ta,V:Na,w:Ua,W:Ra,x:null,X:null,y:ja,Y:Ga,Z:qa,"%":Za},M={a:function(e,t,a){var l=f.exec(t.slice(a)) +return l?(e.w=v.get(l[0].toLowerCase()),a+l[0].length):-1},A:function(e,t,a){var l=d.exec(t.slice(a)) +return l?(e.w=u.get(l[0].toLowerCase()),a+l[0].length):-1},b:function(e,t,a){var l=y.exec(t.slice(a)) +return l?(e.m=g.get(l[0].toLowerCase()),a+l[0].length):-1},B:function(e,t,a){var l=p.exec(t.slice(a)) +return l?(e.m=m.get(l[0].toLowerCase()),a+l[0].length):-1},c:function(e,a,l){return x(e,t,a,l)},d:Xt,e:Xt,f:la,g:Zt,G:qt,H:Qt,I:Qt,j:Jt,L:aa,m:Wt,M:ea,p:function(e,t,a){var l=h.exec(t.slice(a)) +return l?(e.p=s.get(l[0].toLowerCase()),a+l[0].length):-1},q:Kt,Q:oa,s:na,S:ta,u:jt,U:It,V:Gt,w:Rt,W:$t,x:function(e,t,l){return x(e,a,t,l)},X:function(e,t,a){return x(e,l,t,a)},y:Zt,Y:qt,Z:Yt,"%":ia} +function A(e,t){return function(a){var l,i,o,n=[],r=-1,c=0,h=e.length +for(a instanceof Date||(a=new Date(+a));++r53)return null +"w"in o||(o.w=1),"Z"in o?(i=(l=Bt(Lt(o.y,0,1))).getUTCDay(),l=i>4||0===i?ut.ceil(l):ut(l),l=ht.offset(l,7*(o.V-1)),o.y=l.getUTCFullYear(),o.m=l.getUTCMonth(),o.d=l.getUTCDate()+(o.w+6)%7):(i=(l=_t(Lt(o.y,0,1))).getDay(),l=i>4||0===i?Ye.ceil(l):Ye(l),l=$e.offset(l,7*(o.V-1)),o.y=l.getFullYear(),o.m=l.getMonth(),o.d=l.getDate()+(o.w+6)%7)}else("W"in o||"U"in o)&&("w"in o||(o.w="u"in o?o.u%7:"W"in o?1:0),i="Z"in o?Bt(Lt(o.y,0,1)).getUTCDay():_t(Lt(o.y,0,1)).getDay(),o.m=0,o.d="W"in o?(o.w+6)%7+7*o.W-(i+5)%7:o.w+7*o.U-(i+6)%7) +return"Z"in o?(o.H+=o.Z/100|0,o.M+=o.Z%100,Bt(o)):_t(o)}}function x(e,t,a,l){for(var i,o,n=0,r=t.length,c=a.length;n=c)return-1 +if(37===(i=t.charCodeAt(n++))){if(i=t.charAt(n++),!(o=M[i in Dt?t.charAt(n++):i])||(l=o(e,a,l))<0)return-1}else if(i!=a.charCodeAt(l++))return-1}return l}return b.x=A(a,b),b.X=A(l,b),b.c=A(t,b),z.x=A(a,z),z.X=A(l,z),z.c=A(t,z),{format:function(e){var t=A(e+="",b) +return t.toString=function(){return e},t},parse:function(e){var t=w(e+="",!1) +return t.toString=function(){return e},t},utcFormat:function(e){var t=A(e+="",z) +return t.toString=function(){return e},t},utcParse:function(e){var t=w(e+="",!0) +return t.toString=function(){return e},t}}}({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}),Et=Ct.format,Ct.parse,kt=Ct.utcFormat,Ct.utcParse},8740:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{create:()=>me,creator:()=>c,local:()=>ge,matcher:()=>v,namespace:()=>o,namespaces:()=>i,pointer:()=>Me,pointers:()=>Ae,select:()=>pe,selectAll:()=>we,selection:()=>ve,selector:()=>s,selectorAll:()=>f,style:()=>O,window:()=>k}) +var l="http://www.w3.org/1999/xhtml" +const i={svg:"http://www.w3.org/2000/svg",xhtml:l,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"} +function o(e){var t=e+="",a=t.indexOf(":") +return a>=0&&"xmlns"!==(t=e.slice(0,a))&&(e=e.slice(a+1)),i.hasOwnProperty(t)?{space:i[t],local:e}:e}function n(e){return function(){var t=this.ownerDocument,a=this.namespaceURI +return a===l&&t.documentElement.namespaceURI===l?t.createElement(e):t.createElementNS(a,e)}}function r(e){return function(){return this.ownerDocument.createElementNS(e.space,e.local)}}function c(e){var t=o(e) +return(t.local?r:n)(t)}function h(){}function s(e){return null==e?h:function(){return this.querySelector(e)}}function d(e){return"object"==typeof e&&"length"in e?e:Array.from(e)}function u(){return[]}function f(e){return null==e?u:function(){return this.querySelectorAll(e)}}function v(e){return function(){return this.matches(e)}}function p(e){return function(t){return t.matches(e)}}var m=Array.prototype.find +function y(){return this.firstElementChild}var g=Array.prototype.filter +function b(){return this.children}function z(e){return new Array(e.length)}function M(e,t){this.ownerDocument=e.ownerDocument,this.namespaceURI=e.namespaceURI,this._next=null,this._parent=e,this.__data__=t}function A(e,t,a,l,i,o){for(var n,r=0,c=t.length,h=o.length;rt?1:e>=t?0:NaN}function V(e){return function(){this.removeAttribute(e)}}function _(e){return function(){this.removeAttributeNS(e.space,e.local)}}function B(e,t){return function(){this.setAttribute(e,t)}}function L(e,t){return function(){this.setAttributeNS(e.space,e.local,t)}}function C(e,t){return function(){var a=t.apply(this,arguments) +null==a?this.removeAttribute(e):this.setAttribute(e,a)}}function E(e,t){return function(){var a=t.apply(this,arguments) +null==a?this.removeAttributeNS(e.space,e.local):this.setAttributeNS(e.space,e.local,a)}}function k(e){return e.ownerDocument&&e.ownerDocument.defaultView||e.document&&e||e.defaultView}function D(e){return function(){this.style.removeProperty(e)}}function S(e,t,a){return function(){this.style.setProperty(e,t,a)}}function F(e,t,a){return function(){var l=t.apply(this,arguments) +null==l?this.style.removeProperty(e):this.style.setProperty(e,l,a)}}function O(e,t){return e.style.getPropertyValue(t)||k(e).getComputedStyle(e,null).getPropertyValue(t)}function T(e){return function(){delete this[e]}}function P(e,t){return function(){this[e]=t}}function N(e,t){return function(){var a=t.apply(this,arguments) +null==a?delete this[e]:this[e]=a}}function U(e){return e.trim().split(/^|\s+/)}function R(e){return e.classList||new j(e)}function j(e){this._node=e,this._names=U(e.getAttribute("class")||"")}function I(e,t){for(var a=R(e),l=-1,i=t.length;++l=0&&(this._names.splice(t,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(e){return this._names.indexOf(e)>=0}} +var de=[null] +function ue(e,t){this._groups=e,this._parents=t}function fe(){return new ue([[document.documentElement]],de)}ue.prototype=fe.prototype={constructor:ue,select:function(e){"function"!=typeof e&&(e=s(e)) +for(var t=this._groups,a=t.length,l=new Array(a),i=0;i=H&&(H=M+1);!(z=g[H])&&++H=0;)(l=i[o])&&(n&&4^l.compareDocumentPosition(n)&&n.parentNode.insertBefore(l,n),n=l) +return this},sort:function(e){function t(t,a){return t&&a?e(t.__data__,a.__data__):!t-!a}e||(e=H) +for(var a=this._groups,l=a.length,i=new Array(l),o=0;o1?this.each((null==t?D:"function"==typeof t?F:S)(e,t,null==a?"":a)):O(this.node(),e)},property:function(e,t){return arguments.length>1?this.each((null==t?T:"function"==typeof t?N:P)(e,t)):this.node()[e]},classed:function(e,t){var a=U(e+"") +if(arguments.length<2){for(var l=R(this.node()),i=-1,o=a.length;++i=0&&(t=e.slice(a+1),e=e.slice(0,a)),{type:e,name:t}}))}(e+""),n=o.length +if(!(arguments.length<2)){for(r=t?re:ne,l=0;lMe(e,t)))}function we(e){return"string"==typeof e?new ue([document.querySelectorAll(e)],[document.documentElement]):new ue([null==e?[]:d(e)],de)}be.prototype=ge.prototype={constructor:be,get:function(e){for(var t=this._;!(t in e);)if(!(e=e.parentNode))return +return e[t]},set:function(e,t){return e[this._]=t},remove:function(e){return this._ in e&&delete e[this._]},toString:function(){return this._}}},5043:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{arc:()=>L,area:()=>T,areaRadial:()=>q,curveBasis:()=>He,curveBasisClosed:()=>_e,curveBasisOpen:()=>Le,curveBumpX:()=>Ee,curveBumpY:()=>ke,curveBundle:()=>Se,curveCardinal:()=>Te,curveCardinalClosed:()=>Ne,curveCardinalOpen:()=>Re,curveCatmullRom:()=>Ge,curveCatmullRomClosed:()=>qe,curveCatmullRomOpen:()=>Ye,curveLinear:()=>D,curveLinearClosed:()=>We,curveMonotoneX:()=>it,curveMonotoneY:()=>ot,curveNatural:()=>ct,curveStep:()=>st,curveStepAfter:()=>ut,curveStepBefore:()=>dt,line:()=>O,lineRadial:()=>$,linkHorizontal:()=>ee,linkRadial:()=>ae,linkVertical:()=>te,pie:()=>U,pointRadial:()=>Z,radialArea:()=>q,radialLine:()=>$,stack:()=>yt,stackOffsetDiverging:()=>bt,stackOffsetExpand:()=>gt,stackOffsetNone:()=>ft,stackOffsetSilhouette:()=>zt,stackOffsetWiggle:()=>Mt,stackOrderAppearance:()=>At,stackOrderAscending:()=>xt,stackOrderDescending:()=>Vt,stackOrderInsideOut:()=>_t,stackOrderNone:()=>vt,stackOrderReverse:()=>Bt,symbol:()=>Me,symbolCircle:()=>le,symbolCross:()=>ie,symbolDiamond:()=>re,symbolSquare:()=>ue,symbolStar:()=>de,symbolTriangle:()=>ve,symbolWye:()=>be,symbols:()=>ze}) +const l=Math.PI,i=2*l,o=1e-6,n=i-o +function r(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function c(){return new r}r.prototype=c.prototype={constructor:r,moveTo:function(e,t){this._+="M"+(this._x0=this._x1=+e)+","+(this._y0=this._y1=+t)},closePath:function(){null!==this._x1&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(e,t){this._+="L"+(this._x1=+e)+","+(this._y1=+t)},quadraticCurveTo:function(e,t,a,l){this._+="Q"+ +e+","+ +t+","+(this._x1=+a)+","+(this._y1=+l)},bezierCurveTo:function(e,t,a,l,i,o){this._+="C"+ +e+","+ +t+","+ +a+","+ +l+","+(this._x1=+i)+","+(this._y1=+o)},arcTo:function(e,t,a,i,n){e=+e,t=+t,a=+a,i=+i,n=+n +var r=this._x1,c=this._y1,h=a-e,s=i-t,d=r-e,u=c-t,f=d*d+u*u +if(n<0)throw new Error("negative radius: "+n) +if(null===this._x1)this._+="M"+(this._x1=e)+","+(this._y1=t) +else if(f>o)if(Math.abs(u*h-s*d)>o&&n){var v=a-r,p=i-c,m=h*h+s*s,y=v*v+p*p,g=Math.sqrt(m),b=Math.sqrt(f),z=n*Math.tan((l-Math.acos((m+f-y)/(2*g*b)))/2),M=z/b,A=z/g +Math.abs(M-1)>o&&(this._+="L"+(e+M*d)+","+(t+M*u)),this._+="A"+n+","+n+",0,0,"+ +(u*v>d*p)+","+(this._x1=e+A*h)+","+(this._y1=t+A*s)}else this._+="L"+(this._x1=e)+","+(this._y1=t)},arc:function(e,t,a,r,c,h){e=+e,t=+t,h=!!h +var s=(a=+a)*Math.cos(r),d=a*Math.sin(r),u=e+s,f=t+d,v=1^h,p=h?r-c:c-r +if(a<0)throw new Error("negative radius: "+a) +null===this._x1?this._+="M"+u+","+f:(Math.abs(this._x1-u)>o||Math.abs(this._y1-f)>o)&&(this._+="L"+u+","+f),a&&(p<0&&(p=p%i+i),p>n?this._+="A"+a+","+a+",0,1,"+v+","+(e-s)+","+(t-d)+"A"+a+","+a+",0,1,"+v+","+(this._x1=u)+","+(this._y1=f):p>o&&(this._+="A"+a+","+a+",0,"+ +(p>=l)+","+v+","+(this._x1=e+a*Math.cos(c))+","+(this._y1=t+a*Math.sin(c))))},rect:function(e,t,a,l){this._+="M"+(this._x0=this._x1=+e)+","+(this._y0=this._y1=+t)+"h"+ +a+"v"+ +l+"h"+-a+"Z"},toString:function(){return this._}} +const h=c +function s(e){return function(){return e}}var d=Math.abs,u=Math.atan2,f=Math.cos,v=Math.max,p=Math.min,m=Math.sin,y=Math.sqrt,g=1e-12,b=Math.PI,z=b/2,M=2*b +function A(e){return e>=1?z:e<=-1?-z:Math.asin(e)}function w(e){return e.innerRadius}function x(e){return e.outerRadius}function H(e){return e.startAngle}function V(e){return e.endAngle}function _(e){return e&&e.padAngle}function B(e,t,a,l,i,o,n){var r=e-a,c=t-l,h=(n?o:-o)/y(r*r+c*c),s=h*c,d=-h*r,u=e+s,f=t+d,p=a+s,m=l+d,g=(u+p)/2,b=(f+m)/2,z=p-u,M=m-f,A=z*z+M*M,w=i-o,x=u*m-p*f,H=(M<0?-1:1)*y(v(0,w*w*A-x*x)),V=(x*M-z*H)/A,_=(-x*z-M*H)/A,B=(x*M+z*H)/A,L=(-x*z+M*H)/A,C=V-g,E=_-b,k=B-g,D=L-b +return C*C+E*E>k*k+D*D&&(V=B,_=L),{cx:V,cy:_,x01:-s,y01:-d,x11:V*(i/w-1),y11:_*(i/w-1)}}function L(){var e=w,t=x,a=s(0),l=null,i=H,o=V,n=_,r=null +function c(){var c,s,v,w=+e.apply(this,arguments),x=+t.apply(this,arguments),H=i.apply(this,arguments)-z,V=o.apply(this,arguments)-z,_=d(V-H),L=V>H +if(r||(r=c=h()),xg)if(_>M-g)r.moveTo(x*f(H),x*m(H)),r.arc(0,0,x,H,V,!L),w>g&&(r.moveTo(w*f(V),w*m(V)),r.arc(0,0,w,V,H,L)) +else{var C,E,k=H,D=V,S=H,F=V,O=_,T=_,P=n.apply(this,arguments)/2,N=P>g&&(l?+l.apply(this,arguments):y(w*w+x*x)),U=p(d(x-w)/2,+a.apply(this,arguments)),R=U,j=U +if(N>g){var I=A(N/w*m(P)),G=A(N/x*m(P));(O-=2*I)>g?(S+=I*=L?1:-1,F-=I):(O=0,S=F=(H+V)/2),(T-=2*G)>g?(k+=G*=L?1:-1,D-=G):(T=0,k=D=(H+V)/2)}var $=x*f(k),q=x*m(k),Z=w*f(F),Y=w*m(F) +if(U>g){var K,W=x*f(D),X=x*m(D),J=w*f(S),Q=w*m(S) +if(_1?0:v<-1?b:Math.acos(v))/2),oe=y(K[0]*K[0]+K[1]*K[1]) +R=p(U,(w-oe)/(ie-1)),j=p(U,(x-oe)/(ie+1))}}T>g?j>g?(C=B(J,Q,$,q,x,j,L),E=B(W,X,Z,Y,x,j,L),r.moveTo(C.cx+C.x01,C.cy+C.y01),jg&&O>g?R>g?(C=B(Z,Y,W,X,w,-R,L),E=B($,q,J,Q,w,-R,L),r.lineTo(C.cx+C.x01,C.cy+C.y01),R=d;--u)r.point(y[u],g[u]) +r.lineEnd(),r.areaEnd()}m&&(y[s]=+e(f,s,c),g[s]=+t(f,s,c),r.point(l?+l(f,s,c):y[s],a?+a(f,s,c):g[s]))}if(v)return r=null,v+""||null}function d(){return O().defined(i).curve(n).context(o)}return e="function"==typeof e?e:void 0===e?S:s(+e),t="function"==typeof t?t:s(void 0===t?0:+t),a="function"==typeof a?a:void 0===a?F:s(+a),c.x=function(t){return arguments.length?(e="function"==typeof t?t:s(+t),l=null,c):e},c.x0=function(t){return arguments.length?(e="function"==typeof t?t:s(+t),c):e},c.x1=function(e){return arguments.length?(l=null==e?null:"function"==typeof e?e:s(+e),c):l},c.y=function(e){return arguments.length?(t="function"==typeof e?e:s(+e),a=null,c):t},c.y0=function(e){return arguments.length?(t="function"==typeof e?e:s(+e),c):t},c.y1=function(e){return arguments.length?(a=null==e?null:"function"==typeof e?e:s(+e),c):a},c.lineX0=c.lineY0=function(){return d().x(e).y(t)},c.lineY1=function(){return d().x(e).y(a)},c.lineX1=function(){return d().x(l).y(t)},c.defined=function(e){return arguments.length?(i="function"==typeof e?e:s(!!e),c):i},c.curve=function(e){return arguments.length?(n=e,null!=o&&(r=n(o)),c):n},c.context=function(e){return arguments.length?(null==e?o=r=null:r=n(o=e),c):o},c}function P(e,t){return te?1:t>=e?0:NaN}function N(e){return e}function U(){var e=N,t=P,a=null,l=s(0),i=s(M),o=s(0) +function n(n){var r,c,h,s,d,u=(n=E(n)).length,f=0,v=new Array(u),p=new Array(u),m=+l.apply(this,arguments),y=Math.min(M,Math.max(-M,i.apply(this,arguments)-m)),g=Math.min(Math.abs(y)/u,o.apply(this,arguments)),b=g*(y<0?-1:1) +for(r=0;r0&&(f+=d) +for(null!=t?v.sort((function(e,a){return t(p[e],p[a])})):null!=a&&v.sort((function(e,t){return a(n[e],n[t])})),r=0,h=f?(y-u*b)/f:0;r0?d*h:0)+b,p[c]={data:n[c],index:r,value:d,startAngle:m,endAngle:s,padAngle:g} +return p}return n.value=function(t){return arguments.length?(e="function"==typeof t?t:s(+t),n):e},n.sortValues=function(e){return arguments.length?(t=e,a=null,n):t},n.sort=function(e){return arguments.length?(a=e,t=null,n):a},n.startAngle=function(e){return arguments.length?(l="function"==typeof e?e:s(+e),n):l},n.endAngle=function(e){return arguments.length?(i="function"==typeof e?e:s(+e),n):i},n.padAngle=function(e){return arguments.length?(o="function"==typeof e?e:s(+e),n):o},n}k.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t) +break +case 1:this._point=2 +default:this._context.lineTo(e,t)}}} +var R=I(D) +function j(e){this._curve=e}function I(e){function t(t){return new j(e(t))}return t._curve=e,t}function G(e){var t=e.curve +return e.angle=e.x,delete e.x,e.radius=e.y,delete e.y,e.curve=function(e){return arguments.length?t(I(e)):t()._curve},e}function $(){return G(O().curve(R))}function q(){var e=T().curve(R),t=e.curve,a=e.lineX0,l=e.lineX1,i=e.lineY0,o=e.lineY1 +return e.angle=e.x,delete e.x,e.startAngle=e.x0,delete e.x0,e.endAngle=e.x1,delete e.x1,e.radius=e.y,delete e.y,e.innerRadius=e.y0,delete e.y0,e.outerRadius=e.y1,delete e.y1,e.lineStartAngle=function(){return G(a())},delete e.lineX0,e.lineEndAngle=function(){return G(l())},delete e.lineX1,e.lineInnerRadius=function(){return G(i())},delete e.lineY0,e.lineOuterRadius=function(){return G(o())},delete e.lineY1,e.curve=function(e){return arguments.length?t(I(e)):t()._curve},e}function Z(e,t){return[(t=+t)*Math.cos(e-=Math.PI/2),t*Math.sin(e)]}function Y(e){return e.source}function K(e){return e.target}function W(e){var t=Y,a=K,l=S,i=F,o=null +function n(){var n,r=C.call(arguments),c=t.apply(this,r),s=a.apply(this,r) +if(o||(o=n=h()),e(o,+l.apply(this,(r[0]=c,r)),+i.apply(this,r),+l.apply(this,(r[0]=s,r)),+i.apply(this,r)),n)return o=null,n+""||null}return n.source=function(e){return arguments.length?(t=e,n):t},n.target=function(e){return arguments.length?(a=e,n):a},n.x=function(e){return arguments.length?(l="function"==typeof e?e:s(+e),n):l},n.y=function(e){return arguments.length?(i="function"==typeof e?e:s(+e),n):i},n.context=function(e){return arguments.length?(o=null==e?null:e,n):o},n}function X(e,t,a,l,i){e.moveTo(t,a),e.bezierCurveTo(t=(t+l)/2,a,t,i,l,i)}function J(e,t,a,l,i){e.moveTo(t,a),e.bezierCurveTo(t,a=(a+i)/2,l,a,l,i)}function Q(e,t,a,l,i){var o=Z(t,a),n=Z(t,a=(a+i)/2),r=Z(l,a),c=Z(l,i) +e.moveTo(o[0],o[1]),e.bezierCurveTo(n[0],n[1],r[0],r[1],c[0],c[1])}function ee(){return W(X)}function te(){return W(J)}function ae(){var e=W(Q) +return e.angle=e.x,delete e.x,e.radius=e.y,delete e.y,e}j.prototype={areaStart:function(){this._curve.areaStart()},areaEnd:function(){this._curve.areaEnd()},lineStart:function(){this._curve.lineStart()},lineEnd:function(){this._curve.lineEnd()},point:function(e,t){this._curve.point(t*Math.sin(e),t*-Math.cos(e))}} +const le={draw:function(e,t){var a=Math.sqrt(t/b) +e.moveTo(a,0),e.arc(0,0,a,0,M)}},ie={draw:function(e,t){var a=Math.sqrt(t/5)/2 +e.moveTo(-3*a,-a),e.lineTo(-a,-a),e.lineTo(-a,-3*a),e.lineTo(a,-3*a),e.lineTo(a,-a),e.lineTo(3*a,-a),e.lineTo(3*a,a),e.lineTo(a,a),e.lineTo(a,3*a),e.lineTo(-a,3*a),e.lineTo(-a,a),e.lineTo(-3*a,a),e.closePath()}} +var oe=Math.sqrt(1/3),ne=2*oe +const re={draw:function(e,t){var a=Math.sqrt(t/ne),l=a*oe +e.moveTo(0,-a),e.lineTo(l,0),e.lineTo(0,a),e.lineTo(-l,0),e.closePath()}} +var ce=Math.sin(b/10)/Math.sin(7*b/10),he=Math.sin(M/10)*ce,se=-Math.cos(M/10)*ce +const de={draw:function(e,t){var a=Math.sqrt(.8908130915292852*t),l=he*a,i=se*a +e.moveTo(0,-a),e.lineTo(l,i) +for(var o=1;o<5;++o){var n=M*o/5,r=Math.cos(n),c=Math.sin(n) +e.lineTo(c*a,-r*a),e.lineTo(r*l-c*i,c*l+r*i)}e.closePath()}},ue={draw:function(e,t){var a=Math.sqrt(t),l=-a/2 +e.rect(l,l,a,a)}} +var fe=Math.sqrt(3) +const ve={draw:function(e,t){var a=-Math.sqrt(t/(3*fe)) +e.moveTo(0,2*a),e.lineTo(-fe*a,-a),e.lineTo(fe*a,-a),e.closePath()}} +var pe=-.5,me=Math.sqrt(3)/2,ye=1/Math.sqrt(12),ge=3*(ye/2+1) +const be={draw:function(e,t){var a=Math.sqrt(t/ge),l=a/2,i=a*ye,o=l,n=a*ye+a,r=-o,c=n +e.moveTo(l,i),e.lineTo(o,n),e.lineTo(r,c),e.lineTo(pe*l-me*i,me*l+pe*i),e.lineTo(pe*o-me*n,me*o+pe*n),e.lineTo(pe*r-me*c,me*r+pe*c),e.lineTo(pe*l+me*i,pe*i-me*l),e.lineTo(pe*o+me*n,pe*n-me*o),e.lineTo(pe*r+me*c,pe*c-me*r),e.closePath()}} +var ze=[le,ie,re,ue,de,ve,be] +function Me(e,t){var a=null +function l(){var l +if(a||(a=l=h()),e.apply(this,arguments).draw(a,+t.apply(this,arguments)),l)return a=null,l+""||null}return e="function"==typeof e?e:s(e||le),t="function"==typeof t?t:s(void 0===t?64:+t),l.type=function(t){return arguments.length?(e="function"==typeof t?t:s(t),l):e},l.size=function(e){return arguments.length?(t="function"==typeof e?e:s(+e),l):t},l.context=function(e){return arguments.length?(a=null==e?null:e,l):a},l}function Ae(){}function we(e,t,a){e._context.bezierCurveTo((2*e._x0+e._x1)/3,(2*e._y0+e._y1)/3,(e._x0+2*e._x1)/3,(e._y0+2*e._y1)/3,(e._x0+4*e._x1+t)/6,(e._y0+4*e._y1+a)/6)}function xe(e){this._context=e}function He(e){return new xe(e)}function Ve(e){this._context=e}function _e(e){return new Ve(e)}function Be(e){this._context=e}function Le(e){return new Be(e)}xe.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:we(this,this._x1,this._y1) +case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t) +break +case 1:this._point=2 +break +case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6) +default:we(this,e,t)}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}},Ve.prototype={areaStart:Ae,areaEnd:Ae,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath() +break +case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath() +break +case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._x2=e,this._y2=t +break +case 1:this._point=2,this._x3=e,this._y3=t +break +case 2:this._point=3,this._x4=e,this._y4=t,this._context.moveTo((this._x0+4*this._x1+e)/6,(this._y0+4*this._y1+t)/6) +break +default:we(this,e,t)}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}},Be.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1 +break +case 1:this._point=2 +break +case 2:this._point=3 +var a=(this._x0+4*this._x1+e)/6,l=(this._y0+4*this._y1+t)/6 +this._line?this._context.lineTo(a,l):this._context.moveTo(a,l) +break +case 3:this._point=4 +default:we(this,e,t)}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}} +class Ce{constructor(e,t){this._context=e,this._x=t}areaStart(){this._line=0}areaEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line}point(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t) +break +case 1:this._point=2 +default:this._x?this._context.bezierCurveTo(this._x0=(this._x0+e)/2,this._y0,this._x0,t,e,t):this._context.bezierCurveTo(this._x0,this._y0=(this._y0+t)/2,e,this._y0,e,t)}this._x0=e,this._y0=t}}function Ee(e){return new Ce(e,!0)}function ke(e){return new Ce(e,!1)}function De(e,t){this._basis=new xe(e),this._beta=t}De.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var e=this._x,t=this._y,a=e.length-1 +if(a>0)for(var l,i=e[0],o=t[0],n=e[a]-i,r=t[a]-o,c=-1;++c<=a;)l=c/a,this._basis.point(this._beta*e[c]+(1-this._beta)*(i+l*n),this._beta*t[c]+(1-this._beta)*(o+l*r)) +this._x=this._y=null,this._basis.lineEnd()},point:function(e,t){this._x.push(+e),this._y.push(+t)}} +const Se=function e(t){function a(e){return 1===t?new xe(e):new De(e,t)}return a.beta=function(t){return e(+t)},a}(.85) +function Fe(e,t,a){e._context.bezierCurveTo(e._x1+e._k*(e._x2-e._x0),e._y1+e._k*(e._y2-e._y0),e._x2+e._k*(e._x1-t),e._y2+e._k*(e._y1-a),e._x2,e._y2)}function Oe(e,t){this._context=e,this._k=(1-t)/6}Oe.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2) +break +case 3:Fe(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t) +break +case 1:this._point=2,this._x1=e,this._y1=t +break +case 2:this._point=3 +default:Fe(this,e,t)}this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}} +const Te=function e(t){function a(e){return new Oe(e,t)}return a.tension=function(t){return e(+t)},a}(0) +function Pe(e,t){this._context=e,this._k=(1-t)/6}Pe.prototype={areaStart:Ae,areaEnd:Ae,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath() +break +case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath() +break +case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._x3=e,this._y3=t +break +case 1:this._point=2,this._context.moveTo(this._x4=e,this._y4=t) +break +case 2:this._point=3,this._x5=e,this._y5=t +break +default:Fe(this,e,t)}this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}} +const Ne=function e(t){function a(e){return new Pe(e,t)}return a.tension=function(t){return e(+t)},a}(0) +function Ue(e,t){this._context=e,this._k=(1-t)/6}Ue.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1 +break +case 1:this._point=2 +break +case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2) +break +case 3:this._point=4 +default:Fe(this,e,t)}this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}} +const Re=function e(t){function a(e){return new Ue(e,t)}return a.tension=function(t){return e(+t)},a}(0) +function je(e,t,a){var l=e._x1,i=e._y1,o=e._x2,n=e._y2 +if(e._l01_a>g){var r=2*e._l01_2a+3*e._l01_a*e._l12_a+e._l12_2a,c=3*e._l01_a*(e._l01_a+e._l12_a) +l=(l*r-e._x0*e._l12_2a+e._x2*e._l01_2a)/c,i=(i*r-e._y0*e._l12_2a+e._y2*e._l01_2a)/c}if(e._l23_a>g){var h=2*e._l23_2a+3*e._l23_a*e._l12_a+e._l12_2a,s=3*e._l23_a*(e._l23_a+e._l12_a) +o=(o*h+e._x1*e._l23_2a-t*e._l12_2a)/s,n=(n*h+e._y1*e._l23_2a-a*e._l12_2a)/s}e._context.bezierCurveTo(l,i,o,n,e._x2,e._y2)}function Ie(e,t){this._context=e,this._alpha=t}Ie.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2) +break +case 3:this.point(this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){if(e=+e,t=+t,this._point){var a=this._x2-e,l=this._y2-t +this._l23_a=Math.sqrt(this._l23_2a=Math.pow(a*a+l*l,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t) +break +case 1:this._point=2 +break +case 2:this._point=3 +default:je(this,e,t)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}} +const Ge=function e(t){function a(e){return t?new Ie(e,t):new Oe(e,0)}return a.alpha=function(t){return e(+t)},a}(.5) +function $e(e,t){this._context=e,this._alpha=t}$e.prototype={areaStart:Ae,areaEnd:Ae,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath() +break +case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath() +break +case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(e,t){if(e=+e,t=+t,this._point){var a=this._x2-e,l=this._y2-t +this._l23_a=Math.sqrt(this._l23_2a=Math.pow(a*a+l*l,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=e,this._y3=t +break +case 1:this._point=2,this._context.moveTo(this._x4=e,this._y4=t) +break +case 2:this._point=3,this._x5=e,this._y5=t +break +default:je(this,e,t)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}} +const qe=function e(t){function a(e){return t?new $e(e,t):new Pe(e,0)}return a.alpha=function(t){return e(+t)},a}(.5) +function Ze(e,t){this._context=e,this._alpha=t}Ze.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){if(e=+e,t=+t,this._point){var a=this._x2-e,l=this._y2-t +this._l23_a=Math.sqrt(this._l23_2a=Math.pow(a*a+l*l,this._alpha))}switch(this._point){case 0:this._point=1 +break +case 1:this._point=2 +break +case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2) +break +case 3:this._point=4 +default:je(this,e,t)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}} +const Ye=function e(t){function a(e){return t?new Ze(e,t):new Ue(e,0)}return a.alpha=function(t){return e(+t)},a}(.5) +function Ke(e){this._context=e}function We(e){return new Ke(e)}function Xe(e){return e<0?-1:1}function Je(e,t,a){var l=e._x1-e._x0,i=t-e._x1,o=(e._y1-e._y0)/(l||i<0&&-0),n=(a-e._y1)/(i||l<0&&-0),r=(o*i+n*l)/(l+i) +return(Xe(o)+Xe(n))*Math.min(Math.abs(o),Math.abs(n),.5*Math.abs(r))||0}function Qe(e,t){var a=e._x1-e._x0 +return a?(3*(e._y1-e._y0)/a-t)/2:t}function et(e,t,a){var l=e._x0,i=e._y0,o=e._x1,n=e._y1,r=(o-l)/3 +e._context.bezierCurveTo(l+r,i+r*t,o-r,n-r*a,o,n)}function tt(e){this._context=e}function at(e){this._context=new lt(e)}function lt(e){this._context=e}function it(e){return new tt(e)}function ot(e){return new at(e)}function nt(e){this._context=e}function rt(e){var t,a,l=e.length-1,i=new Array(l),o=new Array(l),n=new Array(l) +for(i[0]=0,o[0]=2,n[0]=e[0]+2*e[1],t=1;t=0;--t)i[t]=(n[t]-i[t+1])/o[t] +for(o[l-1]=(e[l]+i[l-1])/2,t=0;t1)for(var a,l,i,o=1,n=e[t[0]],r=n.length;o=0;)a[t]=t +return a}function pt(e,t){return e[t]}function mt(e){const t=[] +return t.key=e,t}function yt(){var e=s([]),t=vt,a=ft,l=pt +function i(i){var o,n,r=Array.from(e.apply(this,arguments),mt),c=r.length,h=-1 +for(const e of i)for(o=0,++h;o0){for(var a,l,i,o=0,n=e[0].length;o0)for(var a,l,i,o,n,r,c=0,h=e[t[0]].length;c0?(l[0]=o,l[1]=o+=i):i<0?(l[1]=n,l[0]=n+=i):(l[0]=0,l[1]=i)}function zt(e,t){if((a=e.length)>0){for(var a,l=0,i=e[t[0]],o=i.length;l0&&(l=(a=e[t[0]]).length)>0){for(var a,l,i,o=0,n=1;no&&(o=t,l=a) +return l}function xt(e){var t=e.map(Ht) +return vt(e).sort((function(e,a){return t[e]-t[a]}))}function Ht(e){for(var t,a=0,l=-1,i=e.length;++l=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t) +break +case 1:this._point=2 +default:if(this._t<=0)this._context.lineTo(this._x,t),this._context.lineTo(e,t) +else{var a=this._x*(1-this._t)+e*this._t +this._context.lineTo(a,this._y),this._context.lineTo(a,t)}}this._x=e,this._y=t}}},2350:function(e){e.exports=function(){"use strict" +var e=6e4,t=36e5,a="millisecond",l="second",i="minute",o="hour",n="day",r="week",c="month",h="quarter",s="year",d="date",u="Invalid Date",f=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,v=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,p={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(e){var t=["th","st","nd","rd"],a=e%100 +return"["+e+(t[(a-20)%10]||t[a]||t[0])+"]"}},m=function(e,t,a){var l=String(e) +return!l||l.length>=t?e:""+Array(t+1-l.length).join(a)+e},y={s:m,z:function(e){var t=-e.utcOffset(),a=Math.abs(t),l=Math.floor(a/60),i=a%60 +return(t<=0?"+":"-")+m(l,2,"0")+":"+m(i,2,"0")},m:function e(t,a){if(t.date()1)return e(n[0])}else{var r=t.name +b[r]=t,i=r}return!l&&i&&(g=i),i||!l&&g},A=function(e,t){if(z(e))return e.clone() +var a="object"==typeof t?t:{} +return a.date=e,a.args=arguments,new x(a)},w=y +w.l=M,w.i=z,w.w=function(e,t){return A(e,{locale:t.$L,utc:t.$u,x:t.$x,$offset:t.$offset})} +var x=function(){function p(e){this.$L=M(e.locale,null,!0),this.parse(e)}var m=p.prototype +return m.parse=function(e){this.$d=function(e){var t=e.date,a=e.utc +if(null===t)return new Date(NaN) +if(w.u(t))return new Date +if(t instanceof Date)return new Date(t) +if("string"==typeof t&&!/Z$/i.test(t)){var l=t.match(f) +if(l){var i=l[2]-1||0,o=(l[7]||"0").substring(0,3) +return a?new Date(Date.UTC(l[1],i,l[3]||1,l[4]||0,l[5]||0,l[6]||0,o)):new Date(l[1],i,l[3]||1,l[4]||0,l[5]||0,l[6]||0,o)}}return new Date(t)}(e),this.$x=e.x||{},this.init()},m.init=function(){var e=this.$d +this.$y=e.getFullYear(),this.$M=e.getMonth(),this.$D=e.getDate(),this.$W=e.getDay(),this.$H=e.getHours(),this.$m=e.getMinutes(),this.$s=e.getSeconds(),this.$ms=e.getMilliseconds()},m.$utils=function(){return w},m.isValid=function(){return!(this.$d.toString()===u)},m.isSame=function(e,t){var a=A(e) +return this.startOf(t)<=a&&a<=this.endOf(t)},m.isAfter=function(e,t){return A(e)0,m<=p.r||!p.r){m<=1&&v>0&&(p=u[v-1]) +var y=d[p.l] +r&&(m=r(""+m)),h="string"==typeof y?y.replace("%d",m):y(m,l,p.l,s) +break}}if(l)return h +var g=s?d.future:d.past +return"function"==typeof g?g(h):g.replace("%s",h)},l.to=function(e,t){return o(e,t,this,!0)},l.from=function(e,t){return o(e,t,this)} +var n=function(e){return e.$u?a.utc():a()} +l.toNow=function(e){return this.to(n(this),e)},l.fromNow=function(e){return this.from(n(this),e)}}}()},3924:e=>{"use strict" +var t=function(e){return function(e){return!!e&&"object"==typeof e}(e)&&!function(e){var t=Object.prototype.toString.call(e) +return"[object RegExp]"===t||"[object Date]"===t||function(e){return e.$$typeof===a}(e)}(e)},a="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103 +function l(e,t){return!1!==t.clone&&t.isMergeableObject(e)?r((a=e,Array.isArray(a)?[]:{}),e,t):e +var a}function i(e,t,a){return e.concat(t).map((function(e){return l(e,a)}))}function o(e){return Object.keys(e).concat(function(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter((function(t){return Object.propertyIsEnumerable.call(e,t)})):[]}(e))}function n(e,t){try{return t in e}catch(e){return!1}}function r(e,a,c){(c=c||{}).arrayMerge=c.arrayMerge||i,c.isMergeableObject=c.isMergeableObject||t,c.cloneUnlessOtherwiseSpecified=l +var h=Array.isArray(a) +return h===Array.isArray(e)?h?c.arrayMerge(e,a,c):function(e,t,a){var i={} +return a.isMergeableObject(e)&&o(e).forEach((function(t){i[t]=l(e[t],a)})),o(t).forEach((function(o){(function(e,t){return n(e,t)&&!(Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))})(e,o)||(n(e,o)&&a.isMergeableObject(t[o])?i[o]=function(e,t){if(!t.customMerge)return r +var a=t.customMerge(e) +return"function"==typeof a?a:r}(o,a)(e[o],t[o],a):i[o]=l(t[o],a))})),i}(e,a,c):l(a,c)}r.all=function(e,t){if(!Array.isArray(e))throw new Error("first argument should be an array") +return e.reduce((function(e,a){return r(e,a,t)}),{})} +var c=r +e.exports=c},3109:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{default:()=>S}) +var l=a(4927),i=["input","select","textarea","a[href]","button","[tabindex]:not(slot)","audio[controls]","video[controls]",'[contenteditable]:not([contenteditable="false"])',"details>summary:first-of-type","details"],o=i.join(","),n="undefined"==typeof Element,r=n?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector,c=!n&&Element.prototype.getRootNode?function(e){return e.getRootNode()}:function(e){return e.ownerDocument},h=function(e,t,a){var l=Array.prototype.slice.apply(e.querySelectorAll(o)) +return t&&r.call(e,o)&&l.unshift(e),l.filter(a)},s=function e(t,a,l){for(var i=[],n=Array.from(t);n.length;){var c=n.shift() +if("SLOT"===c.tagName){var h=c.assignedElements(),s=e(h.length?h:c.children,!0,l) +l.flatten?i.push.apply(i,s):i.push({scope:c,candidates:s})}else{r.call(c,o)&&l.filter(c)&&(a||!t.includes(c))&&i.push(c) +var d=c.shadowRoot||"function"==typeof l.getShadowRoot&&l.getShadowRoot(c),u=!l.shadowRootFilter||l.shadowRootFilter(c) +if(d&&u){var f=e(!0===d?c.children:d.children,!0,l) +l.flatten?i.push.apply(i,f):i.push({scope:c,candidates:f})}else n.unshift.apply(n,c.children)}}return i},d=function(e,t){return e.tabIndex<0&&(t||/^(AUDIO|VIDEO|DETAILS)$/.test(e.tagName)||e.isContentEditable)&&isNaN(parseInt(e.getAttribute("tabindex"),10))?0:e.tabIndex},u=function(e,t){return e.tabIndex===t.tabIndex?e.documentOrder-t.documentOrder:e.tabIndex-t.tabIndex},f=function(e){return"INPUT"===e.tagName},v=function(e){var t=e.getBoundingClientRect(),a=t.width,l=t.height +return 0===a&&0===l},p=function(e,t){return!(t.disabled||function(e){return f(e)&&"hidden"===e.type}(t)||function(e,t){var a=t.displayCheck,l=t.getShadowRoot +if("hidden"===getComputedStyle(e).visibility)return!0 +var i=r.call(e,"details>summary:first-of-type")?e.parentElement:e +if(r.call(i,"details:not([open]) *"))return!0 +var o=c(e).host,n=(null==o?void 0:o.ownerDocument.contains(o))||e.ownerDocument.contains(e) +if(a&&"full"!==a){if("non-zero-area"===a)return v(e)}else{if("function"==typeof l){for(var h=e;e;){var s=e.parentElement,d=c(e) +if(s&&!s.shadowRoot&&!0===l(s))return v(e) +e=e.assignedSlot?e.assignedSlot:s||d===e.ownerDocument?s:d.host}e=h}if(n)return!e.getClientRects().length}return!1}(t,e)||function(e){return"DETAILS"===e.tagName&&Array.prototype.slice.apply(e.children).some((function(e){return"SUMMARY"===e.tagName}))}(t)||function(e){if(/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(e.tagName))for(var t=e.parentElement;t;){if("FIELDSET"===t.tagName&&t.disabled){for(var a=0;a=0)},g=function e(t){var a=[],l=[] +return t.forEach((function(t,i){var o=!!t.scope,n=o?t.scope:t,r=d(n,o),c=o?e(t.candidates):n +0===r?o?a.push.apply(a,c):a.push(n):l.push({documentOrder:i,tabIndex:r,item:t,isScope:o,content:c})})),l.sort(u).reduce((function(e,t){return t.isScope?e.push.apply(e,t.content):e.push(t.content),e}),[]).concat(a)},b=function(e,t){var a +return a=(t=t||{}).getShadowRoot?s([e],t.includeContainer,{filter:m.bind(null,t),flatten:!1,getShadowRoot:t.getShadowRoot,shadowRootFilter:y}):h(e,t.includeContainer,m.bind(null,t)),g(a)},z=function(e,t){if(t=t||{},!e)throw new Error("No node provided") +return!1!==r.call(e,o)&&m(t,e)},M=i.concat("iframe").join(","),A=function(e,t){if(t=t||{},!e)throw new Error("No node provided") +return!1!==r.call(e,M)&&p(t,e)} +function w(e,t){var a=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,l)}return a}function x(e){for(var t=1;t0){var t=V[V.length-1] +t!==e&&t.pause()}var a=V.indexOf(e);-1===a||V.splice(a,1),V.push(e)},deactivateTrap:function(e){var t=V.indexOf(e);-1!==t&&V.splice(t,1),V.length>0&&V[V.length-1].unpause()}}),B=function(e){return setTimeout(e,0)},L=function(e,t){var a=-1 +return e.every((function(e,l){return!t(e)||(a=l,!1)})),a},C=function(e){for(var t=arguments.length,a=new Array(t>1?t-1:0),l=1;l1?a-1:0),n=1;n=0)e=l.activeElement +else{var t=o.tabbableGroups[0] +e=t&&t.firstTabbableNode||c("fallbackFocus")}if(!e)throw new Error("Your focus-trap needs to have at least one focusable element") +return e},u=function(){if(o.containerGroups=o.containers.map((function(e){var t,a,l=b(e,i.tabbableOptions),o=(t=e,(a=(a=i.tabbableOptions)||{}).getShadowRoot?s([t],a.includeContainer,{filter:p.bind(null,a),flatten:!0,getShadowRoot:a.getShadowRoot}):h(t,a.includeContainer,p.bind(null,a))) +return{container:e,tabbableNodes:l,focusableNodes:o,firstTabbableNode:l.length>0?l[0]:null,lastTabbableNode:l.length>0?l[l.length-1]:null,nextTabbableNode:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],a=o.findIndex((function(t){return t===e})) +if(!(a<0))return t?o.slice(a+1).find((function(e){return z(e,i.tabbableOptions)})):o.slice(0,a).reverse().find((function(e){return z(e,i.tabbableOptions)}))}}})),o.tabbableGroups=o.containerGroups.filter((function(e){return e.tabbableNodes.length>0})),o.tabbableGroups.length<=0&&!c("fallbackFocus"))throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times")},f=function e(t){!1!==t&&t!==l.activeElement&&(t&&t.focus?(t.focus({preventScroll:!!i.preventScroll}),o.mostRecentlyFocusedNode=t,function(e){return e.tagName&&"input"===e.tagName.toLowerCase()&&"function"==typeof e.select}(t)&&t.select()):e(d()))},v=function(e){var t=c("setReturnFocus",e) +return t||!1!==t&&e},m=function(e){var t=E(e) +r(t)>=0||(C(i.clickOutsideDeactivates,e)?a.deactivate({returnFocus:i.returnFocusOnDeactivate&&!A(t,i.tabbableOptions)}):C(i.allowOutsideClick,e)||e.preventDefault())},y=function(e){var t=E(e),a=r(t)>=0 +a||t instanceof Document?a&&(o.mostRecentlyFocusedNode=t):(e.stopImmediatePropagation(),f(o.mostRecentlyFocusedNode||d()))},g=function(e){if(function(e){return"Escape"===e.key||"Esc"===e.key||27===e.keyCode}(e)&&!1!==C(i.escapeDeactivates,e))return e.preventDefault(),void a.deactivate();(function(e){return"Tab"===e.key||9===e.keyCode})(e)&&function(e){var t=E(e) +u() +var a=null +if(o.tabbableGroups.length>0){var l=r(t),n=l>=0?o.containerGroups[l]:void 0 +if(l<0)a=e.shiftKey?o.tabbableGroups[o.tabbableGroups.length-1].lastTabbableNode:o.tabbableGroups[0].firstTabbableNode +else if(e.shiftKey){var h=L(o.tabbableGroups,(function(e){var a=e.firstTabbableNode +return t===a})) +if(h<0&&(n.container===t||A(t,i.tabbableOptions)&&!z(t,i.tabbableOptions)&&!n.nextTabbableNode(t,!1))&&(h=l),h>=0){var s=0===h?o.tabbableGroups.length-1:h-1 +a=o.tabbableGroups[s].lastTabbableNode}}else{var d=L(o.tabbableGroups,(function(e){var a=e.lastTabbableNode +return t===a})) +if(d<0&&(n.container===t||A(t,i.tabbableOptions)&&!z(t,i.tabbableOptions)&&!n.nextTabbableNode(t))&&(d=l),d>=0){var v=d===o.tabbableGroups.length-1?0:d+1 +a=o.tabbableGroups[v].firstTabbableNode}}}else a=c("fallbackFocus") +a&&(e.preventDefault(),f(a))}(e)},M=function(e){var t=E(e) +r(t)>=0||C(i.clickOutsideDeactivates,e)||C(i.allowOutsideClick,e)||(e.preventDefault(),e.stopImmediatePropagation())},w=function(){if(o.active)return _.activateTrap(a),o.delayInitialFocusTimer=i.delayInitialFocus?B((function(){f(d())})):f(d()),l.addEventListener("focusin",y,!0),l.addEventListener("mousedown",m,{capture:!0,passive:!1}),l.addEventListener("touchstart",m,{capture:!0,passive:!1}),l.addEventListener("click",M,{capture:!0,passive:!1}),l.addEventListener("keydown",g,{capture:!0,passive:!1}),a},H=function(){if(o.active)return l.removeEventListener("focusin",y,!0),l.removeEventListener("mousedown",m,!0),l.removeEventListener("touchstart",m,!0),l.removeEventListener("click",M,!0),l.removeEventListener("keydown",g,!0),a} +return(a={get active(){return o.active},get paused(){return o.paused},activate:function(e){if(o.active)return this +var t=n(e,"onActivate"),a=n(e,"onPostActivate"),i=n(e,"checkCanFocusTrap") +i||u(),o.active=!0,o.paused=!1,o.nodeFocusedBeforeActivation=l.activeElement,t&&t() +var r=function(){i&&u(),w(),a&&a()} +return i?(i(o.containers.concat()).then(r,r),this):(r(),this)},deactivate:function(e){if(!o.active)return this +var t=x({onDeactivate:i.onDeactivate,onPostDeactivate:i.onPostDeactivate,checkCanReturnFocus:i.checkCanReturnFocus},e) +clearTimeout(o.delayInitialFocusTimer),o.delayInitialFocusTimer=void 0,H(),o.active=!1,o.paused=!1,_.deactivateTrap(a) +var l=n(t,"onDeactivate"),r=n(t,"onPostDeactivate"),c=n(t,"checkCanReturnFocus"),h=n(t,"returnFocus","returnFocusOnDeactivate") +l&&l() +var s=function(){B((function(){h&&f(v(o.nodeFocusedBeforeActivation)),r&&r()}))} +return h&&c?(c(v(o.nodeFocusedBeforeActivation)).then(s,s),this):(s(),this)},pause:function(){return o.paused||!o.active||(o.paused=!0,H()),this},unpause:function(){return o.paused&&o.active?(o.paused=!1,u(),w(),this):this},updateContainerElements:function(e){var t=[].concat(e).filter(Boolean) +return o.containers=t.map((function(e){return"string"==typeof e?l.querySelector(e):e})),o.active&&u(),this}}).updateContainerElements(e),a} +let D +try{D=(0,l.capabilities)("3.22")}catch{D=(0,l.capabilities)("3.13")}var S=(0,l.setModifierManager)((()=>({capabilities:D,createModifier:()=>({focusTrapOptions:void 0,isActive:!0,isPaused:!1,shouldSelfFocus:!1,focusTrap:void 0}),installModifier(e,t,a){let{named:{isActive:l,isPaused:i,shouldSelfFocus:o,focusTrapOptions:n,additionalElements:r,_createFocusTrap:c}}=a +e.focusTrapOptions={...n}||{},void 0!==l&&(e.isActive=l),void 0!==i&&(e.isPaused=i),e.focusTrapOptions&&void 0===e.focusTrapOptions.initialFocus&&o&&(e.focusTrapOptions.initialFocus=t) +let h=k +c&&(h=c),!1!==e.focusTrapOptions.returnFocusOnDeactivate&&(e.focusTrapOptions.returnFocusOnDeactivate=!0),e.focusTrap=h(void 0!==r?[t,...r]:t,e.focusTrapOptions),e.isActive&&e.focusTrap.activate(),e.isPaused&&e.focusTrap.pause()},updateModifier(e,t){let{named:a}=t +const l=a.focusTrapOptions||{} +if(e.isActive&&!a.isActive){const{returnFocusOnDeactivate:t}=l,a=void 0===t +e.focusTrap.deactivate({returnFocus:a})}else!e.isActive&&a.isActive&&e.focusTrap.activate() +e.isPaused&&!a.isPaused?e.focusTrap.unpause():!e.isPaused&&a.isPaused&&e.focusTrap.pause(),e.focusTrapOptions=l,void 0!==a.isActive&&(e.isActive=a.isActive),void 0!==a.isPaused&&(e.isPaused=a.isPaused)},destroyModifier(e){let{focusTrap:t}=e +t.deactivate()}})),class{})},3720:(e,t,a)=>{"use strict" +function l(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t,a,l){a&&Object.defineProperty(e,t,{enumerable:a.enumerable,configurable:a.configurable,writable:a.writable,value:a.initializer?a.initializer.call(l):void 0})}function o(e,t,a,l,i){var o={} +return Object.keys(l).forEach((function(e){o[e]=l[e]})),o.enumerable=!!o.enumerable,o.configurable=!!o.configurable,("value"in o||o.initializer)&&(o.writable=!0),o=a.slice().reverse().reduce((function(a,l){return l(e,t,a)||a}),o),i&&void 0!==o.initializer&&(o.value=o.initializer?o.initializer.call(i):void 0,o.initializer=void 0),void 0===o.initializer&&(Object.defineProperty(e,t,o),o=null),o}a.d(t,{_:()=>l,a:()=>o,b:()=>i})},5487:(e,t,a)=>{"use strict" +a.d(t,{Bq:()=>i,sd:()=>o,zA:()=>l}) +const l={A:"a",B:"b",C:"c",D:"d",E:"e",F:"f",G:"g",H:"h",I:"i",J:"j",K:"k",L:"l",M:"m",N:"n",O:"o",P:"p",Q:"q",R:"r",S:"s",T:"t",U:"u",V:"v",W:"w",X:"x",Y:"y",Z:"z","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=","<":",",">":".","?":"/",":":";",'"':"'","~":"`","{":"[","}":"]","|":"\\"},i={"å":"a",b:"b","ç":"c","∂":"d","ƒ":"f","©":"g","˙":"h","∆":"j","˚":"k","¬":"l","µ":"m","ø":"o","π":"p","œ":"q","®":"r","ß":"s","†":"t","√":"v","∑":"w","≈":"x","¥":"y","Ω":"z","¡":"1","™":"2","£":"3","¢":"4","∞":"5","§":"6","¶":"7","•":"8","ª":"9","º":"0","–":"-","≠":"=","≤":",","≥":".","÷":"/","…":";","æ":"'","“":"[","‘":"]","«":"\\"},o={"Å":"a","ı":"b","Î":"d","Ï":"f","˝":"g","Ó":"h","ˆ":"i","Ô":"j","":"k","Ò":"l","Â":"m","˜":"n","Ø":"o","Œ":"q","‰":"r","Í":"s","ˇ":"t","¨":"u","◊":"v","„":"w","˛":"x","Á":"y","¸":"z","⁄":"1","€":"2","‹":"3","›":"4","fi":"5","fl":"6","‡":"7","°":"8","·":"9","‚":"0","—":"-","±":"=","¯":",","˘":".","¿":"/","Ú":";","Æ":"'","`":"`","”":"[","’":"]","»":"\\"}},3481:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{default:()=>r}) +var l=a(6354),i=a(3353),o=a(4005),n=a(9026),r=(a(3800),a(2956),a(5487),a(6826),a(1866),(0,l.helper)((function(e){let[t,a]=e +return function(e){(0,i.assert)("ember-keyboard: You must pass a function as the second argument to the `if-key` helper","function"==typeof a),(0,i.assert)("ember-keyboard: The `if-key` helper expects to be invoked with a KeyboardEvent",e instanceof KeyboardEvent),(0,o.Z)((0,n.Z)(e.type,t),e)&&a(e)}})))},6415:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{default:()=>d}) +var l,i,o=a(3720),n=a(6354),r=a.n(n),c=a(3353),h=a(8574),s=a(9026) +let d=(l=class extends(r()){constructor(){super(...arguments),(0,o.b)(this,"keyboard",i,this),(0,o._)(this,"keyCombo",void 0),(0,o._)(this,"callback",void 0),(0,o._)(this,"keyboardActivated",!0),(0,o._)(this,"keyboardPriority",0),(0,o._)(this,"eventName","keydown"),(0,o._)(this,"keyboardHandlers",void 0)}compute(e,t){let[a,l]=e,{event:i="keydown",activated:o=!0,priority:n=0}=t;(0,c.assert)("ember-keyboard: You must pass a function as the second argument to the `on-key` helper","function"==typeof l),this.keyCombo=a,this.callback=l,this.eventName=i,this.keyboardActivated=o,this.keyboardPriority=n,this.keyboardHandlers={},this.keyboardHandlers[(0,s.Z)(i,a)]=l,this.keyboard.register(this)}willDestroy(){this.keyboard.unregister(this),super.willDestroy(...arguments)}},i=(0,o.a)(l.prototype,"keyboard",[h.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),l)},4146:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{default:()=>v}) +var l=a(3720),i=a(2509),o=a(8574),n=a(7219),r=a(9341),c=a(9026),h=a(4005) +a(3800),a(2956),a(3353),a(5487),a(6826),a(1866) +const s=["input","select","textarea"] +let d +var u,f +u=class extends i.default{constructor(e,t){super(e,t),(0,l.b)(this,"keyboard",f,this),(0,l._)(this,"element",void 0),(0,l._)(this,"keyboardPriority",0),(0,l._)(this,"activatedParamValue",!0),(0,l._)(this,"eventName","keydown"),(0,l._)(this,"onlyWhenFocused",!0),(0,l._)(this,"listenerName",void 0),(0,l._)(this,"removeEventListeners",(()=>{this.onlyWhenFocused&&(this.element.removeEventListener("click",this.onFocus,!0),this.element.removeEventListener("focus",this.onFocus,!0),this.element.removeEventListener("focusout",this.onFocusOut,!0))})),this.keyboard.register(this),(0,r.registerDestructor)(this,(()=>{this.removeEventListeners(),this.keyboard.unregister(this)}))}modify(e,t,a){this.element=e,this.removeEventListeners(),this.setupProperties(t,a),this.onlyWhenFocused&&this.addEventListeners()}setupProperties(e,t){let[a,l]=e,{activated:i,event:o,priority:n,onlyWhenFocused:r}=t +this.keyCombo=a,this.callback=l,this.eventName=o||"keydown",this.activatedParamValue="activated"in t?!!i:void 0,this.keyboardPriority=n?parseInt(n,10):0,this.listenerName=(0,c.Z)(this.eventName,this.keyCombo),this.onlyWhenFocused=void 0!==r?r:s.includes(this.element.tagName.toLowerCase())}addEventListeners(){this.element.addEventListener("click",this.onFocus,!0),this.element.addEventListener("focus",this.onFocus,!0),this.element.addEventListener("focusout",this.onFocusOut,!0)}onFocus(){this.isFocused=!0}onFocusOut(){this.isFocused=!1}get keyboardActivated(){return!1!==this.activatedParamValue&&(!this.onlyWhenFocused||this.isFocused)}get keyboardFirstResponder(){return!!this.onlyWhenFocused&&this.isFocused}canHandleKeyboardEvent(e){return(0,h.Z)(this.listenerName,e)}handleKeyboardEvent(e,t){(0,h.Z)(this.listenerName,e)&&(this.callback?this.callback(e,t):this.element.click())}},f=(0,l.a)(u.prototype,"keyboard",[o.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),(0,l.a)(u.prototype,"onFocus",[n.action],Object.getOwnPropertyDescriptor(u.prototype,"onFocus"),u.prototype),(0,l.a)(u.prototype,"onFocusOut",[n.action],Object.getOwnPropertyDescriptor(u.prototype,"onFocusOut"),u.prototype),d=u +var v=d},9690:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{default:()=>f}) +var l,i=a(3720),o=a(8574),n=a.n(o),r=a(1292),c=a(7219),h=a(8773),s=a(9026),d=a(4005) +function u(e,t){let a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null +if(e.handleKeyboardEvent){if(e.canHandleKeyboardEvent&&!e.canHandleKeyboardEvent(t))return +e.handleKeyboardEvent(t,a)}else{if(!e.keyboardHandlers)throw new Error("A responder registered with the ember-keyboard service must implement either `keyboardHandlers` (property returning a dictionary of listenerNames to handler functions), or `handleKeyboardEvent(event)`)") +Object.keys(e.keyboardHandlers).forEach((l=>{(0,d.Z)(l,t)&&(a?e.keyboardHandlers[l](t,a):e.keyboardHandlers[l](t))}))}}a(3800),a(2956),a(3353),a(5487),a(6826),a(1866) +let f=(l=class extends(n()){get activeResponders(){let{registeredResponders:e}=this +return Array.from(e).filter((e=>e.keyboardActivated))}get sortedResponders(){return this.activeResponders.sort(((e,t)=>function(e,t,a){return function(e,t,a,l){return function(e,t){let a=e-t +return(a>0)-(a<0)}(l?l((0,c.get)(e,a)):(0,c.get)(e,a),l?l((0,c.get)(t,a)):(0,c.get)(t,a))}(t,e,a,arguments.length>3&&void 0!==arguments[3]?arguments[3]:null)}(e,t,"keyboardPriority")))}get firstResponders(){return this.sortedResponders.filter((e=>e.keyboardFirstResponder))}get normalResponders(){return this.sortedResponders.filter((e=>!e.keyboardFirstResponder))}constructor(){if(super(...arguments),(0,i._)(this,"registeredResponders",new Set),"undefined"!=typeof FastBoot)return +let e=((0,r.getOwner)(this).resolveRegistration("config:environment")||{}).emberKeyboard||{} +e.disableOnInputFields&&(this._disableOnInput=!0),this._listeners=e.listeners||["keyUp","keyDown","keyPress"],this._listeners=this._listeners.map((e=>e.toLowerCase())),this._listeners.forEach((e=>{document.addEventListener(e,this._respond)}))}willDestroy(){super.willDestroy(...arguments),"undefined"==typeof FastBoot&&this._listeners.forEach((e=>{document.removeEventListener(e,this._respond)}))}_respond(e){if(this._disableOnInput&&e.target){var t +const a=null!==(t=e.composedPath()[0])&&void 0!==t?t:e.target,l=a.tagName +if(a.getAttribute&&null!=a.getAttribute("contenteditable")||"TEXTAREA"===l||"INPUT"===l)return}(0,h.run)((()=>{let{firstResponders:t,normalResponders:a}=this +!function(e,t){let{firstResponders:a,normalResponders:l}=t,i=!1,o=!1 +const n={stopImmediatePropagation(){i=!0},stopPropagation(){o=!0}} +for(const c of a)if(u(c,e,n),i)break +if(o)return +i=!1 +let r=Number.POSITIVE_INFINITY +for(const c of l){const t=Number(c.keyboardPriority) +if(!i||t!==r){if(t{"use strict" +a.d(t,{Z:()=>i}) +var l=a(1866) +function i(e){if(!(0,l.isNone)(e))switch(e){case 0:return"left" +case 1:return"middle" +case 2:return"right"}}},4005:(e,t,a)=>{"use strict" +a.d(t,{Z:()=>c}) +var l=a(3800),i=a(2956),o=a(5487),n=a(6826) +a(3353),a(1866) +const r="_all" +function c(e,t){let a,c=arguments.length>2&&void 0!==arguments[2]?arguments[2]:(0,i.Z)() +if(e instanceof l.Z)a=e +else{if("string"!=typeof e)throw new Error("Expected a `string` or `KeyCombo` as `keyComboOrKeyComboString` argument to `isKey`") +a=l.Z.parse(e,c)}return a.type===t.type&&(!!function(e){return e.keyOrCode===r&&!1===e.altKey&&!1===e.ctrlKey&&!1===e.metaKey&&!1===e.shiftKey}(a)||!(!function(e,t){return e.type===t.type&&e.altKey===t.altKey&&e.ctrlKey===t.ctrlKey&&e.metaKey===t.metaKey&&e.shiftKey===t.shiftKey}(a,t)||!function(e,t){return t instanceof KeyboardEvent&&(e.keyOrCode===r||e.keyOrCode===t.code||e.keyOrCode===t.key)}(a,t)&&!function(e,t){return t instanceof MouseEvent&&(e.keyOrCode===r||e.keyOrCode===(0,n.Z)(t.button))}(a,t))||function(e,t,a){return s([],e)&&s(["shift"],t)?t.key===e.keyOrCode:s(["shift"],e)&&s(["shift"],t)?(l=t.key,(o.zA[l]||l)===e.keyOrCode):"Macintosh"===a&&s(["alt"],e)&&s(["alt"],t)?function(e){return o.Bq[e]||e}(t.key)===e.keyOrCode:!("Macintosh"!==a||!s(["shift","alt"],e)||!s(["shift","alt"],t))&&function(e){return o.sd[e]||e}(t.key)===e.keyOrCode +var l}(a,t,c))}const h=["alt","ctrl","meta","shift","cmd"].filter((e=>"cmd"!=e)) +function s(e,t){for(let a of h){if(e.includes(a)&&!t[`${a}Key`])return!1 +if(!e.includes(a)&&t[`${a}Key`])return!1}return!0}},3800:(e,t,a)=>{"use strict" +a.d(t,{Z:()=>s}) +var l=a(3720),i=a(2956) +a(3353) +const o=/^alt$/i,n=/^shift$/i,r=/^ctrl$/i,c=/^meta$/i,h=/^cmd$/i +class s{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:(0,i.Z)();(0,l._)(this,"type",void 0),(0,l._)(this,"altKey",!1),(0,l._)(this,"ctrlKey",!1),(0,l._)(this,"shiftKey",!1),(0,l._)(this,"metaKey",!1),(0,l._)(this,"keyOrCode",void 0),(0,l._)(this,"platform",void 0),this.platform=e}static parse(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:(0,i.Z)(),a=new s(t),[l,...d]=e.split(":") +return d=d.join(":"),a.type=l,"+"===d?(a.keyOrCode=d,a):(d.split("+").forEach((e=>{o.test(e)?a.altKey=!0:r.test(e)?a.ctrlKey=!0:c.test(e)?a.metaKey=!0:n.test(e)?a.shiftKey=!0:h.test(e)?t.indexOf("Mac")>-1?a.metaKey=!0:a.ctrlKey=!0:a.keyOrCode=e})),a)}createMatchingKeyboardEvent(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{} +return new KeyboardEvent(this.type,Object.assign({key:this.keyOrCode,code:this.keyOrCode,altKey:this.altKey,ctrlKey:this.ctrlKey,metaKey:this.metaKey,shiftKey:this.shiftKey},e))}}},9026:(e,t,a)=>{"use strict" +function l(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],a=t +"string"==typeof t&&(a=t.split("+")),a.indexOf("cmd")>-1&&(a[a.indexOf("cmd")]=function(e){if("undefined"==typeof FastBoot)return void 0===e&&(e=navigator.platform),e.indexOf("Mac")>-1?"meta":"ctrl"}()) +let l=function(e){return e.sort().join("+")}(a||[]) +return""===l&&(l="_all"),`${e}:${l}`}a.d(t,{Z:()=>l})},2956:(e,t,a)=>{"use strict" +a.d(t,{Z:()=>o}) +var l=a(3353) +let i +function o(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:navigator.userAgent +if((0,l.runInDebug)((()=>{i=null})),!i){let t="Unknown OS";-1!=e.indexOf("Win")&&(t="Windows"),-1!=e.indexOf("Mac")&&(t="Macintosh"),-1!=e.indexOf("Linux")&&(t="Linux"),-1!=e.indexOf("Android")&&(t="Android"),-1!=e.indexOf("like Mac")&&(t="iOS"),i=t}return i}},2509:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{default:()=>c,modifier:()=>s}) +var l=a(1292),i=a(4927),o=a(9341) +function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}class r{constructor(e){this.owner=e,n(this,"capabilities",(0,i.capabilities)("3.22"))}createModifier(e,t){return{instance:new e(this.owner,t),element:null}}installModifier(e,t,a){const l=function(e,t){const a=e +return a.element=t,a}(e,t) +l.instance.modify(t,a.positional,a.named)}updateModifier(e,t){e.instance.modify(e.element,t.positional,t.named)}destroyModifier(e){let{instance:t}=e;(0,o.destroy)(t)}}class c{constructor(e,t){(0,l.setOwner)(this,e)}modify(e,t,a){}}(0,i.setModifierManager)((e=>new r(e)),c) +const h=new class{constructor(){n(this,"capabilities",(0,i.capabilities)("3.22"))}createModifier(e){return{element:null,instance:e}}installModifier(e,t,a){const l=function(e,t){const a=e +return a.element=t,a}(e,t),{positional:i,named:o}=a,n=e.instance(t,i,o) +"function"==typeof n&&(l.teardown=n)}updateModifier(e,t){"function"==typeof e.teardown&&e.teardown() +const a=e.instance(e.element,t.positional,t.named) +"function"==typeof a&&(e.teardown=a)}destroyModifier(e){"function"==typeof e.teardown&&e.teardown()}} +function s(e){return(0,i.setModifierManager)((()=>h),e)}},3276:e=>{function t(e,t,a,l){var i,o=null==(i=l)||"number"==typeof i||"boolean"==typeof i?l:a(l),n=t.get(o) +return void 0===n&&(n=e.call(this,l),t.set(o,n)),n}function a(e,t,a){var l=Array.prototype.slice.call(arguments,3),i=a(l),o=t.get(i) +return void 0===o&&(o=e.apply(this,l),t.set(i,o)),o}function l(e,t,a,l,i){return a.bind(t,e,l,i)}function i(e,i){return l(e,this,1===e.length?t:a,i.cache.create(),i.serializer)}function o(){return JSON.stringify(arguments)}function n(){this.cache=Object.create(null)}n.prototype.has=function(e){return e in this.cache},n.prototype.get=function(e){return this.cache[e]},n.prototype.set=function(e,t){this.cache[e]=t} +var r={create:function(){return new n}} +e.exports=function(e,t){var a=t&&t.cache?t.cache:r,l=t&&t.serializer?t.serializer:o +return(t&&t.strategy?t.strategy:i)(e,{cache:a,serializer:l})},e.exports.strategies={variadic:function(e,t){return l(e,this,a,t.cache.create(),t.serializer)},monadic:function(e,a){return l(e,this,t,a.cache.create(),a.serializer)}}},2349:e=>{function t(e){return e&&e.constructor&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}function a(e){return e}function l(e,l){const i=(l=l||{}).delimiter||".",o=l.maxDepth,n=l.transformKey||a,r={} +return function e(a,c,h){h=h||1,Object.keys(a).forEach((function(s){const d=a[s],u=l.safe&&Array.isArray(d),f=Object.prototype.toString.call(d),v=t(d),p="[object Object]"===f||"[object Array]"===f,m=c?c+i+n(s):n(s) +if(!u&&!v&&p&&Object.keys(d).length&&(!l.maxDepth||h0&&(l=s(a.shift()),d=s(a[0]))}u[l]=e(i[t],o)})),h}},5011:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{SKELETON_TYPE:()=>i,SyntaxError:()=>L,TYPE:()=>l,createLiteralElement:()=>y,createNumberElement:()=>g,isArgumentElement:()=>r,isDateElement:()=>h,isDateTimeSkeleton:()=>m,isLiteralElement:()=>n,isNumberElement:()=>c,isNumberSkeleton:()=>p,isPluralElement:()=>u,isPoundElement:()=>f,isSelectElement:()=>d,isTagElement:()=>v,isTimeElement:()=>s,parse:()=>D,pegParse:()=>C}) +var l,i,o=a(2985) +function n(e){return e.type===l.literal}function r(e){return e.type===l.argument}function c(e){return e.type===l.number}function h(e){return e.type===l.date}function s(e){return e.type===l.time}function d(e){return e.type===l.select}function u(e){return e.type===l.plural}function f(e){return e.type===l.pound}function v(e){return e.type===l.tag}function p(e){return!(!e||"object"!=typeof e||e.type!==i.number)}function m(e){return!(!e||"object"!=typeof e||e.type!==i.dateTime)}function y(e){return{type:l.literal,value:e}}function g(e,t){return{type:l.number,value:e,style:t}}!function(e){e[e.literal=0]="literal",e[e.argument=1]="argument",e[e.number=2]="number",e[e.date=3]="date",e[e.time=4]="time",e[e.select=5]="select",e[e.plural=6]="plural",e[e.pound=7]="pound",e[e.tag=8]="tag"}(l||(l={})),function(e){e[e.number=0]="number",e[e.dateTime=1]="dateTime"}(i||(i={})) +var b=/(?:[Eec]{1,6}|G{1,5}|[Qq]{1,5}|(?:[yYur]+|U{1,5})|[ML]{1,5}|d{1,2}|D{1,3}|F{1}|[abB]{1,5}|[hkHK]{1,2}|w{1,2}|W{1}|m{1,2}|s{1,2}|[zZOvVxX]{1,4})(?=([^']*'[^']*')*[^']*$)/g,z=/^\.(?:(0+)(\*)?|(#+)|(0+)(#+))$/g,M=/^(@+)?(\+|#+)?$/g,A=/(\*)(0+)|(#+)(0+)|(0+)/g,w=/^(0+)$/ +function x(e){var t={} +return e.replace(M,(function(e,a,l){return"string"!=typeof l?(t.minimumSignificantDigits=a.length,t.maximumSignificantDigits=a.length):"+"===l?t.minimumSignificantDigits=a.length:"#"===a[0]?t.maximumSignificantDigits=a.length:(t.minimumSignificantDigits=a.length,t.maximumSignificantDigits=a.length+("string"==typeof l?l.length:0)),""})),t}function H(e){switch(e){case"sign-auto":return{signDisplay:"auto"} +case"sign-accounting":case"()":return{currencySign:"accounting"} +case"sign-always":case"+!":return{signDisplay:"always"} +case"sign-accounting-always":case"()!":return{signDisplay:"always",currencySign:"accounting"} +case"sign-except-zero":case"+?":return{signDisplay:"exceptZero"} +case"sign-accounting-except-zero":case"()?":return{signDisplay:"exceptZero",currencySign:"accounting"} +case"sign-never":case"+_":return{signDisplay:"never"}}}function V(e){var t +if("E"===e[0]&&"E"===e[1]?(t={notation:"engineering"},e=e.slice(2)):"E"===e[0]&&(t={notation:"scientific"},e=e.slice(1)),t){var a=e.slice(0,2) +if("+!"===a?(t.signDisplay="always",e=e.slice(2)):"+?"===a&&(t.signDisplay="exceptZero",e=e.slice(2)),!w.test(e))throw new Error("Malformed concise eng/scientific notation") +t.minimumIntegerDigits=e.length}return t}function _(e){return H(e)||{}}function B(e){for(var t={},a=0,l=e;a1)throw new RangeError("integer-width stems only accept a single optional option") +i.options[0].replace(A,(function(e,a,l,i,o,n){if(a)t.minimumIntegerDigits=l.length +else{if(i&&o)throw new Error("We currently do not support maximum integer digits") +if(n)throw new Error("We currently do not support exact integer digits")}return""})) +continue}if(w.test(i.stem))t.minimumIntegerDigits=i.stem.length +else if(z.test(i.stem)){if(i.options.length>1)throw new RangeError("Fraction-precision stems only accept a single optional option") +i.stem.replace(z,(function(e,a,l,i,o,n){return"*"===l?t.minimumFractionDigits=a.length:i&&"#"===i[0]?t.maximumFractionDigits=i.length:o&&n?(t.minimumFractionDigits=o.length,t.maximumFractionDigits=o.length+n.length):(t.minimumFractionDigits=a.length,t.maximumFractionDigits=a.length),""})),i.options.length&&(t=(0,o.pi)((0,o.pi)({},t),x(i.options[0])))}else if(M.test(i.stem))t=(0,o.pi)((0,o.pi)({},t),x(i.stem)) +else{var n=H(i.stem) +n&&(t=(0,o.pi)((0,o.pi)({},t),n)) +var r=V(i.stem) +r&&(t=(0,o.pi)((0,o.pi)({},t),r))}}return t}var L=function(e){function t(a,l,i,o){var n=e.call(this)||this +return n.message=a,n.expected=l,n.found=i,n.location=o,n.name="SyntaxError","function"==typeof Error.captureStackTrace&&Error.captureStackTrace(n,t),n}return(0,o.ZT)(t,e),t.buildMessage=function(e,t){function a(e){return e.charCodeAt(0).toString(16).toUpperCase()}function l(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,(function(e){return"\\x0"+a(e)})).replace(/[\x10-\x1F\x7F-\x9F]/g,(function(e){return"\\x"+a(e)}))}function i(e){return e.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replace(/\^/g,"\\^").replace(/-/g,"\\-").replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,(function(e){return"\\x0"+a(e)})).replace(/[\x10-\x1F\x7F-\x9F]/g,(function(e){return"\\x"+a(e)}))}function o(e){switch(e.type){case"literal":return'"'+l(e.text)+'"' +case"class":var t=e.parts.map((function(e){return Array.isArray(e)?i(e[0])+"-"+i(e[1]):i(e)})) +return"["+(e.inverted?"^":"")+t+"]" +case"any":return"any character" +case"end":return"end of input" +case"other":return e.description}}return"Expected "+function(e){var t,a,l=e.map(o) +if(l.sort(),l.length>0){for(t=1,a=1;t",!1),H=function(e){return(0,o.pi)({type:l.literal,value:e.join("")},ia())},V=">",_=xt(">",!1),C=function(e){return e},E="1&&"}"===e)},Qe="\n",et=xt("\n",!1),tt=function(e){return"<"===e||">"===e||"{"===e||"}"===e||la()&&"#"===e},at=Vt("argNameOrNumber"),lt=Vt("validTag"),it=Vt("argNumber"),ot="0",nt=xt("0",!1),rt=function(){return 0},ct=/^[1-9]/,ht=Ht([["1","9"]],!1,!1),st=/^[0-9]/,dt=Ht([["0","9"]],!1,!1),ut=function(e){return parseInt(e.join(""),10)},ft=Vt("argName"),vt=Vt("tagName"),pt=0,mt=0,yt=[{line:1,column:1}],gt=0,bt=[],zt=0 +if(void 0!==t.startRule){if(!(t.startRule in r))throw new Error("Can't start parsing from rule \""+t.startRule+'".') +c=r[t.startRule]}function Mt(){return e.substring(mt,pt)}function At(){return Bt(mt,pt)}function wt(e,t){throw function(e,t){return new L(e,[],"",t)}(e,t=void 0!==t?t:Bt(mt,pt))}function xt(e,t){return{type:"literal",text:e,ignoreCase:t}}function Ht(e,t,a){return{type:"class",parts:e,inverted:t,ignoreCase:a}}function Vt(e){return{type:"other",description:e}}function _t(t){var a,l=yt[t] +if(l)return l +for(a=t-1;!yt[a];)a-- +for(l={line:(l=yt[a]).line,column:l.column};agt&&(gt=pt,bt=[]),bt.push(e))}function Ct(){return Et()}function Et(){var e,t +for(e=[],t=kt();t!==n;)e.push(t),t=kt() +return e}function kt(){var t,a +return t=pt,mt=pt,(h()?void 0:n)!==n?(a=function(){var e,t,a,l +return zt++,(e=Ft())===n&&(e=pt,(t=Ot())!==n&&(a=Et())!==n&&(l=Tt())!==n?(mt=e,e=t=A(t,a,l)):(pt=e,e=n)),zt--,e===n&&(t=n,0===zt&&Lt(M)),e}(),a!==n?(mt=t,t=s(a)):(pt=t,t=n)):(pt=t,t=n),t===n&&(t=function(){var e,t +return e=pt,(t=Dt())!==n&&(mt=e,t=m(t)),t}())===n&&(t=function(){var t,a,l,i +return zt++,t=pt,123===e.charCodeAt(pt)?(a=S,pt++):(a=n,0===zt&&Lt(F)),a!==n&&Zt()!==n&&(l=Jt())!==n&&Zt()!==n?(125===e.charCodeAt(pt)?(i=O,pt++):(i=n,0===zt&&Lt(T)),i!==n?(mt=t,t=a=P(l)):(pt=t,t=n)):(pt=t,t=n),zt--,t===n&&(a=n,0===zt&&Lt(D)),t}())===n&&(t=function(){var t +return t=function(){var t,a,l,i,o,r,c,h,s +return t=pt,123===e.charCodeAt(pt)?(a=S,pt++):(a=n,0===zt&&Lt(F)),a!==n&&Zt()!==n&&(l=Jt())!==n&&Zt()!==n?(44===e.charCodeAt(pt)?(i=te,pt++):(i=n,0===zt&&Lt(ae)),i!==n&&Zt()!==n?(e.substr(pt,6)===le?(o=le,pt+=6):(o=n,0===zt&&Lt(ie)),o!==n&&Zt()!==n?(r=pt,44===e.charCodeAt(pt)?(c=te,pt++):(c=n,0===zt&&Lt(ae)),c!==n&&(h=Zt())!==n?(s=function(){var t,a,l +return t=pt,e.substr(pt,2)===W?(a=W,pt+=2):(a=n,0===zt&&Lt(X)),a!==n?(l=function(){var e,t,a +if(e=pt,t=[],(a=Ut())!==n)for(;a!==n;)t.push(a),a=Ut() +else t=n +return t!==n&&(mt=e,t=K(t)),t}(),l!==n?(mt=t,t=a=J(l)):(pt=t,t=n)):(pt=t,t=n),t===n&&(t=pt,mt=pt,(a=(a=Q())?void 0:n)!==n&&(l=Dt())!==n?(mt=t,t=a=ee(l)):(pt=t,t=n)),t}(),s!==n?r=c=[c,h,s]:(pt=r,r=n)):(pt=r,r=n),r===n&&(r=null),r!==n&&(c=Zt())!==n?(125===e.charCodeAt(pt)?(h=O,pt++):(h=n,0===zt&&Lt(T)),h!==n?(mt=t,t=a=oe(l,o,r)):(pt=t,t=n)):(pt=t,t=n)):(pt=t,t=n)):(pt=t,t=n)):(pt=t,t=n),t}(),t===n&&(t=function(){var t,a,l,i,o,r,c,h,s +return t=pt,123===e.charCodeAt(pt)?(a=S,pt++):(a=n,0===zt&&Lt(F)),a!==n&&Zt()!==n&&(l=Jt())!==n&&Zt()!==n?(44===e.charCodeAt(pt)?(i=te,pt++):(i=n,0===zt&&Lt(ae)),i!==n&&Zt()!==n?(e.substr(pt,4)===me?(o=me,pt+=4):(o=n,0===zt&&Lt(ye)),o===n&&(e.substr(pt,4)===ge?(o=ge,pt+=4):(o=n,0===zt&&Lt(be))),o!==n&&Zt()!==n?(r=pt,44===e.charCodeAt(pt)?(c=te,pt++):(c=n,0===zt&&Lt(ae)),c!==n&&(h=Zt())!==n?(s=function(){var t,a,l +return t=pt,e.substr(pt,2)===W?(a=W,pt+=2):(a=n,0===zt&&Lt(X)),a!==n?(l=function(){var t,a,l,i +if(t=pt,a=pt,l=[],(i=Rt())===n&&(i=jt()),i!==n)for(;i!==n;)l.push(i),(i=Rt())===n&&(i=jt()) +else l=n +return(a=l!==n?e.substring(a,pt):l)!==n&&(mt=t,a=ve(a)),a}(),l!==n?(mt=t,t=a=J(l)):(pt=t,t=n)):(pt=t,t=n),t===n&&(t=pt,mt=pt,(a=(a=pe())?void 0:n)!==n&&(l=Dt())!==n?(mt=t,t=a=ee(l)):(pt=t,t=n)),t}(),s!==n?r=c=[c,h,s]:(pt=r,r=n)):(pt=r,r=n),r===n&&(r=null),r!==n&&(c=Zt())!==n?(125===e.charCodeAt(pt)?(h=O,pt++):(h=n,0===zt&&Lt(T)),h!==n?(mt=t,t=a=oe(l,o,r)):(pt=t,t=n)):(pt=t,t=n)):(pt=t,t=n)):(pt=t,t=n)):(pt=t,t=n),t}()),t}(),t===n&&(t=function(){var t,a,l,i,o,r,c,h,s,d,u +if(t=pt,123===e.charCodeAt(pt)?(a=S,pt++):(a=n,0===zt&&Lt(F)),a!==n)if(Zt()!==n)if((l=Jt())!==n)if(Zt()!==n)if(44===e.charCodeAt(pt)?(i=te,pt++):(i=n,0===zt&&Lt(ae)),i!==n)if(Zt()!==n)if(e.substr(pt,6)===ze?(o=ze,pt+=6):(o=n,0===zt&&Lt(Me)),o===n&&(e.substr(pt,13)===Ae?(o=Ae,pt+=13):(o=n,0===zt&&Lt(we))),o!==n)if(Zt()!==n)if(44===e.charCodeAt(pt)?(r=te,pt++):(r=n,0===zt&&Lt(ae)),r!==n)if(Zt()!==n)if(c=pt,e.substr(pt,7)===xe?(h=xe,pt+=7):(h=n,0===zt&&Lt(He)),h!==n&&(s=Zt())!==n&&(d=Yt())!==n?c=h=[h,s,d]:(pt=c,c=n),c===n&&(c=null),c!==n)if((h=Zt())!==n){if(s=[],(d=Gt())!==n)for(;d!==n;)s.push(d),d=Gt() +else s=n +s!==n&&(d=Zt())!==n?(125===e.charCodeAt(pt)?(u=O,pt++):(u=n,0===zt&&Lt(T)),u!==n?(mt=t,t=a=Ve(l,o,c,s)):(pt=t,t=n)):(pt=t,t=n)}else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +return t}())===n&&(t=function(){var t,a,l,i,o,r,c,h,s +if(t=pt,123===e.charCodeAt(pt)?(a=S,pt++):(a=n,0===zt&&Lt(F)),a!==n)if(Zt()!==n)if((l=Jt())!==n)if(Zt()!==n)if(44===e.charCodeAt(pt)?(i=te,pt++):(i=n,0===zt&&Lt(ae)),i!==n)if(Zt()!==n)if(e.substr(pt,6)===_e?(o=_e,pt+=6):(o=n,0===zt&&Lt(Be)),o!==n)if(Zt()!==n)if(44===e.charCodeAt(pt)?(r=te,pt++):(r=n,0===zt&&Lt(ae)),r!==n)if(Zt()!==n){if(c=[],(h=It())!==n)for(;h!==n;)c.push(h),h=It() +else c=n +c!==n&&(h=Zt())!==n?(125===e.charCodeAt(pt)?(s=O,pt++):(s=n,0===zt&&Lt(T)),s!==n?(mt=t,t=a=Le(l,c)):(pt=t,t=n)):(pt=t,t=n)}else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +else pt=t,t=n +return t}())===n&&(t=function(){var t,a +return t=pt,35===e.charCodeAt(pt)?(a=y,pt++):(a=n,0===zt&&Lt(g)),a!==n&&(mt=t,a=z()),a}())),t}function Dt(){var t,a,l,i +if(t=pt,mt=pt,(a=(a=d())?void 0:n)!==n){if(l=[],(i=Kt())===n&&(i=Wt())===n&&(i=Xt())===n&&(60===e.charCodeAt(pt)?(i=u,pt++):(i=n,0===zt&&Lt(f))),i!==n)for(;i!==n;)l.push(i),(i=Kt())===n&&(i=Wt())===n&&(i=Xt())===n&&(60===e.charCodeAt(pt)?(i=u,pt++):(i=n,0===zt&&Lt(f))) +else l=n +l!==n?(mt=t,t=a=v(l)):(pt=t,t=n)}else pt=t,t=n +if(t===n){if(t=pt,a=[],(l=Kt())===n&&(l=Wt())===n&&(l=Xt())===n&&(l=St()),l!==n)for(;l!==n;)a.push(l),(l=Kt())===n&&(l=Wt())===n&&(l=Xt())===n&&(l=St()) +else a=n +a!==n&&(mt=t,a=v(a)),t=a}return t}function St(){var t,a,l +return t=pt,a=pt,zt++,(l=Ot())===n&&(l=Tt())===n&&(l=Ft()),zt--,l===n?a=void 0:(pt=a,a=n),a!==n?(60===e.charCodeAt(pt)?(l=u,pt++):(l=n,0===zt&&Lt(f)),l!==n?(mt=t,t=a=p()):(pt=t,t=n)):(pt=t,t=n),t}function Ft(){var t,a,l,i,o,r +return t=pt,a=pt,60===e.charCodeAt(pt)?(l=u,pt++):(l=n,0===zt&&Lt(f)),l!==n&&(i=Qt())!==n&&(o=Zt())!==n?(e.substr(pt,2)===w?(r=w,pt+=2):(r=n,0===zt&&Lt(x)),r!==n?a=l=[l,i,o,r]:(pt=a,a=n)):(pt=a,a=n),a!==n&&(mt=t,a=H(a)),a}function Ot(){var t,a,l,i +return t=pt,60===e.charCodeAt(pt)?(a=u,pt++):(a=n,0===zt&&Lt(f)),a!==n&&(l=Qt())!==n?(62===e.charCodeAt(pt)?(i=V,pt++):(i=n,0===zt&&Lt(_)),i!==n?(mt=t,t=a=C(l)):(pt=t,t=n)):(pt=t,t=n),t}function Tt(){var t,a,l,i +return t=pt,e.substr(pt,2)===E?(a=E,pt+=2):(a=n,0===zt&&Lt(k)),a!==n&&(l=Qt())!==n?(62===e.charCodeAt(pt)?(i=V,pt++):(i=n,0===zt&&Lt(_)),i!==n?(mt=t,t=a=C(l)):(pt=t,t=n)):(pt=t,t=n),t}function Pt(){var t,a,l,i,o +if(zt++,t=pt,a=[],l=pt,i=pt,zt++,(o=$t())===n&&(U.test(e.charAt(pt))?(o=e.charAt(pt),pt++):(o=n,0===zt&&Lt(R))),zt--,o===n?i=void 0:(pt=i,i=n),i!==n?(e.length>pt?(o=e.charAt(pt),pt++):(o=n,0===zt&&Lt(j)),o!==n?l=i=[i,o]:(pt=l,l=n)):(pt=l,l=n),l!==n)for(;l!==n;)a.push(l),l=pt,i=pt,zt++,(o=$t())===n&&(U.test(e.charAt(pt))?(o=e.charAt(pt),pt++):(o=n,0===zt&&Lt(R))),zt--,o===n?i=void 0:(pt=i,i=n),i!==n?(e.length>pt?(o=e.charAt(pt),pt++):(o=n,0===zt&&Lt(j)),o!==n?l=i=[i,o]:(pt=l,l=n)):(pt=l,l=n) +else a=n +return t=a!==n?e.substring(t,pt):a,zt--,t===n&&(a=n,0===zt&&Lt(N)),t}function Nt(){var t,a,l +return zt++,t=pt,47===e.charCodeAt(pt)?(a=G,pt++):(a=n,0===zt&&Lt($)),a!==n&&(l=Pt())!==n?(mt=t,t=a=q(l)):(pt=t,t=n),zt--,t===n&&(a=n,0===zt&&Lt(I)),t}function Ut(){var e,t,a,l +if(zt++,e=pt,Zt()!==n)if((t=Pt())!==n){for(a=[],l=Nt();l!==n;)a.push(l),l=Nt() +a!==n?(mt=e,e=Y(t,a)):(pt=e,e=n)}else pt=e,e=n +else pt=e,e=n +return zt--,e===n&&0===zt&&Lt(Z),e}function Rt(){var t,a,l,i +if(t=pt,39===e.charCodeAt(pt)?(a=ne,pt++):(a=n,0===zt&&Lt(re)),a!==n){if(l=[],(i=Kt())===n&&(ce.test(e.charAt(pt))?(i=e.charAt(pt),pt++):(i=n,0===zt&&Lt(he))),i!==n)for(;i!==n;)l.push(i),(i=Kt())===n&&(ce.test(e.charAt(pt))?(i=e.charAt(pt),pt++):(i=n,0===zt&&Lt(he))) +else l=n +l!==n?(39===e.charCodeAt(pt)?(i=ne,pt++):(i=n,0===zt&&Lt(re)),i!==n?t=a=[a,l,i]:(pt=t,t=n)):(pt=t,t=n)}else pt=t,t=n +if(t===n)if(t=[],(a=Kt())===n&&(se.test(e.charAt(pt))?(a=e.charAt(pt),pt++):(a=n,0===zt&&Lt(de))),a!==n)for(;a!==n;)t.push(a),(a=Kt())===n&&(se.test(e.charAt(pt))?(a=e.charAt(pt),pt++):(a=n,0===zt&&Lt(de))) +else t=n +return t}function jt(){var t,a +if(t=[],ue.test(e.charAt(pt))?(a=e.charAt(pt),pt++):(a=n,0===zt&&Lt(fe)),a!==n)for(;a!==n;)t.push(a),ue.test(e.charAt(pt))?(a=e.charAt(pt),pt++):(a=n,0===zt&&Lt(fe)) +else t=n +return t}function It(){var t,a,l,i,o +return t=pt,Zt()!==n&&(a=ta())!==n&&Zt()!==n?(123===e.charCodeAt(pt)?(l=S,pt++):(l=n,0===zt&&Lt(F)),l!==n?(mt=pt,(ke(a)?void 0:n)!==n&&(i=Et())!==n?(125===e.charCodeAt(pt)?(o=O,pt++):(o=n,0===zt&&Lt(T)),o!==n?(mt=t,t=De(a,i)):(pt=t,t=n)):(pt=t,t=n)):(pt=t,t=n)):(pt=t,t=n),t}function Gt(){var t,a,l,i,o +return t=pt,Zt()!==n?(a=function(){var t,a,l,i +return t=pt,a=pt,61===e.charCodeAt(pt)?(l=Ce,pt++):(l=n,0===zt&&Lt(Ee)),l!==n&&(i=Yt())!==n?a=l=[l,i]:(pt=a,a=n),(t=a!==n?e.substring(t,pt):a)===n&&(t=ta()),t}(),a!==n&&Zt()!==n?(123===e.charCodeAt(pt)?(l=S,pt++):(l=n,0===zt&&Lt(F)),l!==n?(mt=pt,(Se(a)?void 0:n)!==n&&(i=Et())!==n?(125===e.charCodeAt(pt)?(o=O,pt++):(o=n,0===zt&&Lt(T)),o!==n?(mt=t,t=Fe(a,i)):(pt=t,t=n)):(pt=t,t=n)):(pt=t,t=n)):(pt=t,t=n)):(pt=t,t=n),t}function $t(){var t +return zt++,Te.test(e.charAt(pt))?(t=e.charAt(pt),pt++):(t=n,0===zt&&Lt(Pe)),zt--,t===n&&0===zt&&Lt(Oe),t}function qt(){var t +return zt++,Ue.test(e.charAt(pt))?(t=e.charAt(pt),pt++):(t=n,0===zt&&Lt(Re)),zt--,t===n&&0===zt&&Lt(Ne),t}function Zt(){var t,a,l +for(zt++,t=pt,a=[],l=$t();l!==n;)a.push(l),l=$t() +return t=a!==n?e.substring(t,pt):a,zt--,t===n&&(a=n,0===zt&&Lt(je)),t}function Yt(){var t,a,l +return zt++,t=pt,45===e.charCodeAt(pt)?(a=Ge,pt++):(a=n,0===zt&&Lt($e)),a===n&&(a=null),a!==n&&(l=ea())!==n?(mt=t,t=a=qe(a,l)):(pt=t,t=n),zt--,t===n&&(a=n,0===zt&&Lt(Ie)),t}function Kt(){var t,a +return zt++,t=pt,e.substr(pt,2)===Ye?(a=Ye,pt+=2):(a=n,0===zt&&Lt(Ke)),a!==n&&(mt=t,a=We()),zt--,(t=a)===n&&(a=n,0===zt&&Lt(Ze)),t}function Wt(){var t,a,l,i,o,r +if(t=pt,39===e.charCodeAt(pt)?(a=ne,pt++):(a=n,0===zt&&Lt(re)),a!==n)if(l=function(){var t,a,l,i +return t=pt,a=pt,e.length>pt?(l=e.charAt(pt),pt++):(l=n,0===zt&&Lt(j)),l!==n?(mt=pt,(i=(i=tt(l))?void 0:n)!==n?a=l=[l,i]:(pt=a,a=n)):(pt=a,a=n),a!==n?e.substring(t,pt):a}(),l!==n){for(i=pt,o=[],e.substr(pt,2)===Ye?(r=Ye,pt+=2):(r=n,0===zt&&Lt(Ke)),r===n&&(ce.test(e.charAt(pt))?(r=e.charAt(pt),pt++):(r=n,0===zt&&Lt(he)));r!==n;)o.push(r),e.substr(pt,2)===Ye?(r=Ye,pt+=2):(r=n,0===zt&&Lt(Ke)),r===n&&(ce.test(e.charAt(pt))?(r=e.charAt(pt),pt++):(r=n,0===zt&&Lt(he)));(i=o!==n?e.substring(i,pt):o)!==n?(39===e.charCodeAt(pt)?(o=ne,pt++):(o=n,0===zt&&Lt(re)),o===n&&(o=null),o!==n?(mt=t,t=a=Xe(l,i)):(pt=t,t=n)):(pt=t,t=n)}else pt=t,t=n +else pt=t,t=n +return t}function Xt(){var t,a,l,i +return t=pt,a=pt,e.length>pt?(l=e.charAt(pt),pt++):(l=n,0===zt&&Lt(j)),l!==n?(mt=pt,(i=(i=Je(l))?void 0:n)!==n?a=l=[l,i]:(pt=a,a=n)):(pt=a,a=n),a===n&&(10===e.charCodeAt(pt)?(a=Qe,pt++):(a=n,0===zt&&Lt(et))),a!==n?e.substring(t,pt):a}function Jt(){var t,a +return zt++,t=pt,(a=ea())===n&&(a=ta()),t=a!==n?e.substring(t,pt):a,zt--,t===n&&(a=n,0===zt&&Lt(at)),t}function Qt(){var t,a +return zt++,t=pt,(a=ea())===n&&(a=function(){var t,a,l,i,o +if(zt++,t=pt,a=[],45===e.charCodeAt(pt)?(l=Ge,pt++):(l=n,0===zt&&Lt($e)),l===n&&(l=pt,i=pt,zt++,(o=$t())===n&&(o=qt()),zt--,o===n?i=void 0:(pt=i,i=n),i!==n?(e.length>pt?(o=e.charAt(pt),pt++):(o=n,0===zt&&Lt(j)),o!==n?l=i=[i,o]:(pt=l,l=n)):(pt=l,l=n)),l!==n)for(;l!==n;)a.push(l),45===e.charCodeAt(pt)?(l=Ge,pt++):(l=n,0===zt&&Lt($e)),l===n&&(l=pt,i=pt,zt++,(o=$t())===n&&(o=qt()),zt--,o===n?i=void 0:(pt=i,i=n),i!==n?(e.length>pt?(o=e.charAt(pt),pt++):(o=n,0===zt&&Lt(j)),o!==n?l=i=[i,o]:(pt=l,l=n)):(pt=l,l=n)) +else a=n +return t=a!==n?e.substring(t,pt):a,zt--,t===n&&(a=n,0===zt&&Lt(vt)),t}()),t=a!==n?e.substring(t,pt):a,zt--,t===n&&(a=n,0===zt&&Lt(lt)),t}function ea(){var t,a,l,i,o +if(zt++,t=pt,48===e.charCodeAt(pt)?(a=ot,pt++):(a=n,0===zt&&Lt(nt)),a!==n&&(mt=t,a=rt()),(t=a)===n){if(t=pt,a=pt,ct.test(e.charAt(pt))?(l=e.charAt(pt),pt++):(l=n,0===zt&&Lt(ht)),l!==n){for(i=[],st.test(e.charAt(pt))?(o=e.charAt(pt),pt++):(o=n,0===zt&&Lt(dt));o!==n;)i.push(o),st.test(e.charAt(pt))?(o=e.charAt(pt),pt++):(o=n,0===zt&&Lt(dt)) +i!==n?a=l=[l,i]:(pt=a,a=n)}else pt=a,a=n +a!==n&&(mt=t,a=ut(a)),t=a}return zt--,t===n&&(a=n,0===zt&&Lt(it)),t}function ta(){var t,a,l,i,o +if(zt++,t=pt,a=[],l=pt,i=pt,zt++,(o=$t())===n&&(o=qt()),zt--,o===n?i=void 0:(pt=i,i=n),i!==n?(e.length>pt?(o=e.charAt(pt),pt++):(o=n,0===zt&&Lt(j)),o!==n?l=i=[i,o]:(pt=l,l=n)):(pt=l,l=n),l!==n)for(;l!==n;)a.push(l),l=pt,i=pt,zt++,(o=$t())===n&&(o=qt()),zt--,o===n?i=void 0:(pt=i,i=n),i!==n?(e.length>pt?(o=e.charAt(pt),pt++):(o=n,0===zt&&Lt(j)),o!==n?l=i=[i,o]:(pt=l,l=n)):(pt=l,l=n) +else a=n +return t=a!==n?e.substring(t,pt):a,zt--,t===n&&(a=n,0===zt&&Lt(ft)),t}var aa=["root"] +function la(){return"plural"===aa[aa.length-1]}function ia(){return t&&t.captureLocation?{location:At()}:{}}var oa,na,ra,ca=t&&t.ignoreTag,ha=t&&t.shouldParseSkeleton +if((a=c())!==n&&pt===e.length)return a +throw a!==n&&pt{"use strict" +a.r(t),a.d(t,{ErrorCode:()=>fe,FormatError:()=>ye,IntlMessageFormat:()=>xe,InvalidValueError:()=>ge,InvalidValueTypeError:()=>be,MissingValueError:()=>ze,PART_TYPE:()=>me,default:()=>He,formatToParts:()=>Ae,isFormatXMLElementFn:()=>Me}) +var l,i,o,n=a(2985) +function r(e){return e.type===i.literal}function c(e){return e.type===i.argument}function h(e){return e.type===i.number}function s(e){return e.type===i.date}function d(e){return e.type===i.time}function u(e){return e.type===i.select}function f(e){return e.type===i.plural}function v(e){return e.type===i.pound}function p(e){return e.type===i.tag}function m(e){return!(!e||"object"!=typeof e||e.type!==o.number)}function y(e){return!(!e||"object"!=typeof e||e.type!==o.dateTime)}!function(e){e[e.EXPECT_ARGUMENT_CLOSING_BRACE=1]="EXPECT_ARGUMENT_CLOSING_BRACE",e[e.EMPTY_ARGUMENT=2]="EMPTY_ARGUMENT",e[e.MALFORMED_ARGUMENT=3]="MALFORMED_ARGUMENT",e[e.EXPECT_ARGUMENT_TYPE=4]="EXPECT_ARGUMENT_TYPE",e[e.INVALID_ARGUMENT_TYPE=5]="INVALID_ARGUMENT_TYPE",e[e.EXPECT_ARGUMENT_STYLE=6]="EXPECT_ARGUMENT_STYLE",e[e.INVALID_NUMBER_SKELETON=7]="INVALID_NUMBER_SKELETON",e[e.INVALID_DATE_TIME_SKELETON=8]="INVALID_DATE_TIME_SKELETON",e[e.EXPECT_NUMBER_SKELETON=9]="EXPECT_NUMBER_SKELETON",e[e.EXPECT_DATE_TIME_SKELETON=10]="EXPECT_DATE_TIME_SKELETON",e[e.UNCLOSED_QUOTE_IN_ARGUMENT_STYLE=11]="UNCLOSED_QUOTE_IN_ARGUMENT_STYLE",e[e.EXPECT_SELECT_ARGUMENT_OPTIONS=12]="EXPECT_SELECT_ARGUMENT_OPTIONS",e[e.EXPECT_PLURAL_ARGUMENT_OFFSET_VALUE=13]="EXPECT_PLURAL_ARGUMENT_OFFSET_VALUE",e[e.INVALID_PLURAL_ARGUMENT_OFFSET_VALUE=14]="INVALID_PLURAL_ARGUMENT_OFFSET_VALUE",e[e.EXPECT_SELECT_ARGUMENT_SELECTOR=15]="EXPECT_SELECT_ARGUMENT_SELECTOR",e[e.EXPECT_PLURAL_ARGUMENT_SELECTOR=16]="EXPECT_PLURAL_ARGUMENT_SELECTOR",e[e.EXPECT_SELECT_ARGUMENT_SELECTOR_FRAGMENT=17]="EXPECT_SELECT_ARGUMENT_SELECTOR_FRAGMENT",e[e.EXPECT_PLURAL_ARGUMENT_SELECTOR_FRAGMENT=18]="EXPECT_PLURAL_ARGUMENT_SELECTOR_FRAGMENT",e[e.INVALID_PLURAL_ARGUMENT_SELECTOR=19]="INVALID_PLURAL_ARGUMENT_SELECTOR",e[e.DUPLICATE_PLURAL_ARGUMENT_SELECTOR=20]="DUPLICATE_PLURAL_ARGUMENT_SELECTOR",e[e.DUPLICATE_SELECT_ARGUMENT_SELECTOR=21]="DUPLICATE_SELECT_ARGUMENT_SELECTOR",e[e.MISSING_OTHER_CLAUSE=22]="MISSING_OTHER_CLAUSE",e[e.INVALID_TAG=23]="INVALID_TAG",e[e.INVALID_TAG_NAME=25]="INVALID_TAG_NAME",e[e.UNMATCHED_CLOSING_TAG=26]="UNMATCHED_CLOSING_TAG",e[e.UNCLOSED_TAG=27]="UNCLOSED_TAG"}(l||(l={})),function(e){e[e.literal=0]="literal",e[e.argument=1]="argument",e[e.number=2]="number",e[e.date=3]="date",e[e.time=4]="time",e[e.select=5]="select",e[e.plural=6]="plural",e[e.pound=7]="pound",e[e.tag=8]="tag"}(i||(i={})),function(e){e[e.number=0]="number",e[e.dateTime=1]="dateTime"}(o||(o={})) +var g=/[ \xA0\u1680\u2000-\u200A\u202F\u205F\u3000]/,b=/(?:[Eec]{1,6}|G{1,5}|[Qq]{1,5}|(?:[yYur]+|U{1,5})|[ML]{1,5}|d{1,2}|D{1,3}|F{1}|[abB]{1,5}|[hkHK]{1,2}|w{1,2}|W{1}|m{1,2}|s{1,2}|[zZOvVxX]{1,4})(?=([^']*'[^']*')*[^']*$)/g +function z(e){var t={} +return e.replace(b,(function(e){var a=e.length +switch(e[0]){case"G":t.era=4===a?"long":5===a?"narrow":"short" +break +case"y":t.year=2===a?"2-digit":"numeric" +break +case"Y":case"u":case"U":case"r":throw new RangeError("`Y/u/U/r` (year) patterns are not supported, use `y` instead") +case"q":case"Q":throw new RangeError("`q/Q` (quarter) patterns are not supported") +case"M":case"L":t.month=["numeric","2-digit","short","long","narrow"][a-1] +break +case"w":case"W":throw new RangeError("`w/W` (week) patterns are not supported") +case"d":t.day=["numeric","2-digit"][a-1] +break +case"D":case"F":case"g":throw new RangeError("`D/F/g` (day) patterns are not supported, use `d` instead") +case"E":t.weekday=4===a?"short":5===a?"narrow":"short" +break +case"e":if(a<4)throw new RangeError("`e..eee` (weekday) patterns are not supported") +t.weekday=["short","long","narrow","short"][a-4] +break +case"c":if(a<4)throw new RangeError("`c..ccc` (weekday) patterns are not supported") +t.weekday=["short","long","narrow","short"][a-4] +break +case"a":t.hour12=!0 +break +case"b":case"B":throw new RangeError("`b/B` (period) patterns are not supported, use `a` instead") +case"h":t.hourCycle="h12",t.hour=["numeric","2-digit"][a-1] +break +case"H":t.hourCycle="h23",t.hour=["numeric","2-digit"][a-1] +break +case"K":t.hourCycle="h11",t.hour=["numeric","2-digit"][a-1] +break +case"k":t.hourCycle="h24",t.hour=["numeric","2-digit"][a-1] +break +case"j":case"J":case"C":throw new RangeError("`j/J/C` (hour) patterns are not supported, use `h/H/K/k` instead") +case"m":t.minute=["numeric","2-digit"][a-1] +break +case"s":t.second=["numeric","2-digit"][a-1] +break +case"S":case"A":throw new RangeError("`S/A` (second) patterns are not supported, use `s` instead") +case"z":t.timeZoneName=a<4?"short":"long" +break +case"Z":case"O":case"v":case"V":case"X":case"x":throw new RangeError("`Z/O/v/V/X/x` (timeZone) patterns are not supported, use `z` instead")}return""})),t}var M=/[\t-\r \x85\u200E\u200F\u2028\u2029]/i,A=/^\.(?:(0+)(\*)?|(#+)|(0+)(#+))$/g,w=/^(@+)?(\+|#+)?[rs]?$/g,x=/(\*)(0+)|(#+)(0+)|(0+)/g,H=/^(0+)$/ +function V(e){var t={} +return"r"===e[e.length-1]?t.roundingPriority="morePrecision":"s"===e[e.length-1]&&(t.roundingPriority="lessPrecision"),e.replace(w,(function(e,a,l){return"string"!=typeof l?(t.minimumSignificantDigits=a.length,t.maximumSignificantDigits=a.length):"+"===l?t.minimumSignificantDigits=a.length:"#"===a[0]?t.maximumSignificantDigits=a.length:(t.minimumSignificantDigits=a.length,t.maximumSignificantDigits=a.length+("string"==typeof l?l.length:0)),""})),t}function _(e){switch(e){case"sign-auto":return{signDisplay:"auto"} +case"sign-accounting":case"()":return{currencySign:"accounting"} +case"sign-always":case"+!":return{signDisplay:"always"} +case"sign-accounting-always":case"()!":return{signDisplay:"always",currencySign:"accounting"} +case"sign-except-zero":case"+?":return{signDisplay:"exceptZero"} +case"sign-accounting-except-zero":case"()?":return{signDisplay:"exceptZero",currencySign:"accounting"} +case"sign-never":case"+_":return{signDisplay:"never"}}}function B(e){var t +if("E"===e[0]&&"E"===e[1]?(t={notation:"engineering"},e=e.slice(2)):"E"===e[0]&&(t={notation:"scientific"},e=e.slice(1)),t){var a=e.slice(0,2) +if("+!"===a?(t.signDisplay="always",e=e.slice(2)):"+?"===a&&(t.signDisplay="exceptZero",e=e.slice(2)),!H.test(e))throw new Error("Malformed concise eng/scientific notation") +t.minimumIntegerDigits=e.length}return t}function L(e){return _(e)||{}}function C(e){for(var t={},a=0,l=e;a1)throw new RangeError("integer-width stems only accept a single optional option") +i.options[0].replace(x,(function(e,a,l,i,o,n){if(a)t.minimumIntegerDigits=l.length +else{if(i&&o)throw new Error("We currently do not support maximum integer digits") +if(n)throw new Error("We currently do not support exact integer digits")}return""})) +continue}if(H.test(i.stem))t.minimumIntegerDigits=i.stem.length +else if(A.test(i.stem)){if(i.options.length>1)throw new RangeError("Fraction-precision stems only accept a single optional option") +i.stem.replace(A,(function(e,a,l,i,o,n){return"*"===l?t.minimumFractionDigits=a.length:i&&"#"===i[0]?t.maximumFractionDigits=i.length:o&&n?(t.minimumFractionDigits=o.length,t.maximumFractionDigits=o.length+n.length):(t.minimumFractionDigits=a.length,t.maximumFractionDigits=a.length),""})) +var o=i.options[0] +"w"===o?t=(0,n.pi)((0,n.pi)({},t),{trailingZeroDisplay:"stripIfInteger"}):o&&(t=(0,n.pi)((0,n.pi)({},t),V(o)))}else if(w.test(i.stem))t=(0,n.pi)((0,n.pi)({},t),V(i.stem)) +else{var r=_(i.stem) +r&&(t=(0,n.pi)((0,n.pi)({},t),r)) +var c=B(i.stem) +c&&(t=(0,n.pi)((0,n.pi)({},t),c))}}return t}var E,k={AX:["H"],BQ:["H"],CP:["H"],CZ:["H"],DK:["H"],FI:["H"],ID:["H"],IS:["H"],ML:["H"],NE:["H"],RU:["H"],SE:["H"],SJ:["H"],SK:["H"],AS:["h","H"],BT:["h","H"],DJ:["h","H"],ER:["h","H"],GH:["h","H"],IN:["h","H"],LS:["h","H"],PG:["h","H"],PW:["h","H"],SO:["h","H"],TO:["h","H"],VU:["h","H"],WS:["h","H"],"001":["H","h"],AL:["h","H","hB"],TD:["h","H","hB"],"ca-ES":["H","h","hB"],CF:["H","h","hB"],CM:["H","h","hB"],"fr-CA":["H","h","hB"],"gl-ES":["H","h","hB"],"it-CH":["H","h","hB"],"it-IT":["H","h","hB"],LU:["H","h","hB"],NP:["H","h","hB"],PF:["H","h","hB"],SC:["H","h","hB"],SM:["H","h","hB"],SN:["H","h","hB"],TF:["H","h","hB"],VA:["H","h","hB"],CY:["h","H","hb","hB"],GR:["h","H","hb","hB"],CO:["h","H","hB","hb"],DO:["h","H","hB","hb"],KP:["h","H","hB","hb"],KR:["h","H","hB","hb"],NA:["h","H","hB","hb"],PA:["h","H","hB","hb"],PR:["h","H","hB","hb"],VE:["h","H","hB","hb"],AC:["H","h","hb","hB"],AI:["H","h","hb","hB"],BW:["H","h","hb","hB"],BZ:["H","h","hb","hB"],CC:["H","h","hb","hB"],CK:["H","h","hb","hB"],CX:["H","h","hb","hB"],DG:["H","h","hb","hB"],FK:["H","h","hb","hB"],GB:["H","h","hb","hB"],GG:["H","h","hb","hB"],GI:["H","h","hb","hB"],IE:["H","h","hb","hB"],IM:["H","h","hb","hB"],IO:["H","h","hb","hB"],JE:["H","h","hb","hB"],LT:["H","h","hb","hB"],MK:["H","h","hb","hB"],MN:["H","h","hb","hB"],MS:["H","h","hb","hB"],NF:["H","h","hb","hB"],NG:["H","h","hb","hB"],NR:["H","h","hb","hB"],NU:["H","h","hb","hB"],PN:["H","h","hb","hB"],SH:["H","h","hb","hB"],SX:["H","h","hb","hB"],TA:["H","h","hb","hB"],ZA:["H","h","hb","hB"],"af-ZA":["H","h","hB","hb"],AR:["H","h","hB","hb"],CL:["H","h","hB","hb"],CR:["H","h","hB","hb"],CU:["H","h","hB","hb"],EA:["H","h","hB","hb"],"es-BO":["H","h","hB","hb"],"es-BR":["H","h","hB","hb"],"es-EC":["H","h","hB","hb"],"es-ES":["H","h","hB","hb"],"es-GQ":["H","h","hB","hb"],"es-PE":["H","h","hB","hb"],GT:["H","h","hB","hb"],HN:["H","h","hB","hb"],IC:["H","h","hB","hb"],KG:["H","h","hB","hb"],KM:["H","h","hB","hb"],LK:["H","h","hB","hb"],MA:["H","h","hB","hb"],MX:["H","h","hB","hb"],NI:["H","h","hB","hb"],PY:["H","h","hB","hb"],SV:["H","h","hB","hb"],UY:["H","h","hB","hb"],JP:["H","h","K"],AD:["H","hB"],AM:["H","hB"],AO:["H","hB"],AT:["H","hB"],AW:["H","hB"],BE:["H","hB"],BF:["H","hB"],BJ:["H","hB"],BL:["H","hB"],BR:["H","hB"],CG:["H","hB"],CI:["H","hB"],CV:["H","hB"],DE:["H","hB"],EE:["H","hB"],FR:["H","hB"],GA:["H","hB"],GF:["H","hB"],GN:["H","hB"],GP:["H","hB"],GW:["H","hB"],HR:["H","hB"],IL:["H","hB"],IT:["H","hB"],KZ:["H","hB"],MC:["H","hB"],MD:["H","hB"],MF:["H","hB"],MQ:["H","hB"],MZ:["H","hB"],NC:["H","hB"],NL:["H","hB"],PM:["H","hB"],PT:["H","hB"],RE:["H","hB"],RO:["H","hB"],SI:["H","hB"],SR:["H","hB"],ST:["H","hB"],TG:["H","hB"],TR:["H","hB"],WF:["H","hB"],YT:["H","hB"],BD:["h","hB","H"],PK:["h","hB","H"],AZ:["H","hB","h"],BA:["H","hB","h"],BG:["H","hB","h"],CH:["H","hB","h"],GE:["H","hB","h"],LI:["H","hB","h"],ME:["H","hB","h"],RS:["H","hB","h"],UA:["H","hB","h"],UZ:["H","hB","h"],XK:["H","hB","h"],AG:["h","hb","H","hB"],AU:["h","hb","H","hB"],BB:["h","hb","H","hB"],BM:["h","hb","H","hB"],BS:["h","hb","H","hB"],CA:["h","hb","H","hB"],DM:["h","hb","H","hB"],"en-001":["h","hb","H","hB"],FJ:["h","hb","H","hB"],FM:["h","hb","H","hB"],GD:["h","hb","H","hB"],GM:["h","hb","H","hB"],GU:["h","hb","H","hB"],GY:["h","hb","H","hB"],JM:["h","hb","H","hB"],KI:["h","hb","H","hB"],KN:["h","hb","H","hB"],KY:["h","hb","H","hB"],LC:["h","hb","H","hB"],LR:["h","hb","H","hB"],MH:["h","hb","H","hB"],MP:["h","hb","H","hB"],MW:["h","hb","H","hB"],NZ:["h","hb","H","hB"],SB:["h","hb","H","hB"],SG:["h","hb","H","hB"],SL:["h","hb","H","hB"],SS:["h","hb","H","hB"],SZ:["h","hb","H","hB"],TC:["h","hb","H","hB"],TT:["h","hb","H","hB"],UM:["h","hb","H","hB"],US:["h","hb","H","hB"],VC:["h","hb","H","hB"],VG:["h","hb","H","hB"],VI:["h","hb","H","hB"],ZM:["h","hb","H","hB"],BO:["H","hB","h","hb"],EC:["H","hB","h","hb"],ES:["H","hB","h","hb"],GQ:["H","hB","h","hb"],PE:["H","hB","h","hb"],AE:["h","hB","hb","H"],"ar-001":["h","hB","hb","H"],BH:["h","hB","hb","H"],DZ:["h","hB","hb","H"],EG:["h","hB","hb","H"],EH:["h","hB","hb","H"],HK:["h","hB","hb","H"],IQ:["h","hB","hb","H"],JO:["h","hB","hb","H"],KW:["h","hB","hb","H"],LB:["h","hB","hb","H"],LY:["h","hB","hb","H"],MO:["h","hB","hb","H"],MR:["h","hB","hb","H"],OM:["h","hB","hb","H"],PH:["h","hB","hb","H"],PS:["h","hB","hb","H"],QA:["h","hB","hb","H"],SA:["h","hB","hb","H"],SD:["h","hB","hb","H"],SY:["h","hB","hb","H"],TN:["h","hB","hb","H"],YE:["h","hB","hb","H"],AF:["H","hb","hB","h"],LA:["H","hb","hB","h"],CN:["H","hB","hb","h"],LV:["H","hB","hb","h"],TL:["H","hB","hb","h"],"zu-ZA":["H","hB","hb","h"],CD:["hB","H"],IR:["hB","H"],"hi-IN":["hB","h","H"],"kn-IN":["hB","h","H"],"ml-IN":["hB","h","H"],"te-IN":["hB","h","H"],KH:["hB","h","H","hb"],"ta-IN":["hB","h","hb","H"],BN:["hb","hB","h","H"],MY:["hb","hB","h","H"],ET:["hB","hb","h","H"],"gu-IN":["hB","hb","h","H"],"mr-IN":["hB","hb","h","H"],"pa-IN":["hB","hb","h","H"],TW:["hB","hb","h","H"],KE:["hB","hb","H","h"],MM:["hB","hb","H","h"],TZ:["hB","hb","H","h"],UG:["hB","hb","H","h"]} +function D(e){var t=e.hourCycle +if(void 0===t&&e.hourCycles&&e.hourCycles.length&&(t=e.hourCycles[0]),t)switch(t){case"h24":return"k" +case"h23":return"H" +case"h12":return"h" +case"h11":return"K" +default:throw new Error("Invalid hourCycle")}var a,l=e.language +return"root"!==l&&(a=e.maximize().region),(k[a||""]||k[l||""]||k["".concat(l,"-001")]||k["001"])[0]}var S=new RegExp("^".concat(g.source,"*")),F=new RegExp("".concat(g.source,"*$")) +function O(e,t){return{start:e,end:t}}var T=!!String.prototype.startsWith,P=!!String.fromCodePoint,N=!!Object.fromEntries,U=!!String.prototype.codePointAt,R=!!String.prototype.trimStart,j=!!String.prototype.trimEnd,I=Number.isSafeInteger?Number.isSafeInteger:function(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e&&Math.abs(e)<=9007199254740991},G=!0 +try{G="a"===(null===(E=J("([^\\p{White_Space}\\p{Pattern_Syntax}]*)","yu").exec("a"))||void 0===E?void 0:E[0])}catch(e){G=!1}var $,q=T?function(e,t,a){return e.startsWith(t,a)}:function(e,t,a){return e.slice(a,a+t.length)===t},Z=P?String.fromCodePoint:function(){for(var e=[],t=0;to;){if((a=e[o++])>1114111)throw RangeError(a+" is not a valid code point") +l+=a<65536?String.fromCharCode(a):String.fromCharCode(55296+((a-=65536)>>10),a%1024+56320)}return l},Y=N?Object.fromEntries:function(e){for(var t={},a=0,l=e;a=a)){var l,i=e.charCodeAt(t) +return i<55296||i>56319||t+1===a||(l=e.charCodeAt(t+1))<56320||l>57343?i:l-56320+(i-55296<<10)+65536}},W=R?function(e){return e.trimStart()}:function(e){return e.replace(S,"")},X=j?function(e){return e.trimEnd()}:function(e){return e.replace(F,"")} +function J(e,t){return new RegExp(e,t)}if(G){var Q=J("([^\\p{White_Space}\\p{Pattern_Syntax}]*)","yu") +$=function(e,t){var a +return Q.lastIndex=t,null!==(a=Q.exec(e)[1])&&void 0!==a?a:""}}else $=function(e,t){for(var a=[];;){var l=K(e,t) +if(void 0===l||ae(l)||le(l))break +a.push(l),t+=l>=65536?2:1}return Z.apply(void 0,a)} +var ee=function(){function e(e,t){void 0===t&&(t={}),this.message=e,this.position={offset:0,line:1,column:1},this.ignoreTag=!!t.ignoreTag,this.locale=t.locale,this.requiresOtherClause=!!t.requiresOtherClause,this.shouldParseSkeletons=!!t.shouldParseSkeletons}return e.prototype.parse=function(){if(0!==this.offset())throw Error("parser can only be used once") +return this.parseMessage(0,"",!1)},e.prototype.parseMessage=function(e,t,a){for(var o=[];!this.isEOF();){var n=this.char() +if(123===n){if((r=this.parseArgument(e,a)).err)return r +o.push(r.val)}else{if(125===n&&e>0)break +if(35!==n||"plural"!==t&&"selectordinal"!==t){if(60===n&&!this.ignoreTag&&47===this.peek()){if(a)break +return this.error(l.UNMATCHED_CLOSING_TAG,O(this.clonePosition(),this.clonePosition()))}if(60===n&&!this.ignoreTag&&te(this.peek()||0)){if((r=this.parseTag(e,t)).err)return r +o.push(r.val)}else{var r +if((r=this.parseLiteral(e,t)).err)return r +o.push(r.val)}}else{var c=this.clonePosition() +this.bump(),o.push({type:i.pound,location:O(c,this.clonePosition())})}}}return{val:o,err:null}},e.prototype.parseTag=function(e,t){var a=this.clonePosition() +this.bump() +var o=this.parseTagName() +if(this.bumpSpace(),this.bumpIf("/>"))return{val:{type:i.literal,value:"<".concat(o,"/>"),location:O(a,this.clonePosition())},err:null} +if(this.bumpIf(">")){var n=this.parseMessage(e+1,t,!0) +if(n.err)return n +var r=n.val,c=this.clonePosition() +if(this.bumpIf("")?{val:{type:i.tag,value:o,children:r,location:O(a,this.clonePosition())},err:null}:this.error(l.INVALID_TAG,O(c,this.clonePosition())))}return this.error(l.UNCLOSED_TAG,O(a,this.clonePosition()))}return this.error(l.INVALID_TAG,O(a,this.clonePosition()))},e.prototype.parseTagName=function(){var e,t=this.offset() +for(this.bump();!this.isEOF()&&(45===(e=this.char())||46===e||e>=48&&e<=57||95===e||e>=97&&e<=122||e>=65&&e<=90||183==e||e>=192&&e<=214||e>=216&&e<=246||e>=248&&e<=893||e>=895&&e<=8191||e>=8204&&e<=8205||e>=8255&&e<=8256||e>=8304&&e<=8591||e>=11264&&e<=12271||e>=12289&&e<=55295||e>=63744&&e<=64975||e>=65008&&e<=65533||e>=65536&&e<=983039);)this.bump() +return this.message.slice(t,this.offset())},e.prototype.parseLiteral=function(e,t){for(var a=this.clonePosition(),l="";;){var o=this.tryParseQuote(t) +if(o)l+=o +else{var n=this.tryParseUnquoted(e,t) +if(n)l+=n +else{var r=this.tryParseLeftAngleBracket() +if(!r)break +l+=r}}}var c=O(a,this.clonePosition()) +return{val:{type:i.literal,value:l,location:c},err:null}},e.prototype.tryParseLeftAngleBracket=function(){return this.isEOF()||60!==this.char()||!this.ignoreTag&&(te(e=this.peek()||0)||47===e)?null:(this.bump(),"<") +var e},e.prototype.tryParseQuote=function(e){if(this.isEOF()||39!==this.char())return null +switch(this.peek()){case 39:return this.bump(),this.bump(),"'" +case 123:case 60:case 62:case 125:break +case 35:if("plural"===e||"selectordinal"===e)break +return null +default:return null}this.bump() +var t=[this.char()] +for(this.bump();!this.isEOF();){var a=this.char() +if(39===a){if(39!==this.peek()){this.bump() +break}t.push(39),this.bump()}else t.push(a) +this.bump()}return Z.apply(void 0,t)},e.prototype.tryParseUnquoted=function(e,t){if(this.isEOF())return null +var a=this.char() +return 60===a||123===a||35===a&&("plural"===t||"selectordinal"===t)||125===a&&e>0?null:(this.bump(),Z(a))},e.prototype.parseArgument=function(e,t){var a=this.clonePosition() +if(this.bump(),this.bumpSpace(),this.isEOF())return this.error(l.EXPECT_ARGUMENT_CLOSING_BRACE,O(a,this.clonePosition())) +if(125===this.char())return this.bump(),this.error(l.EMPTY_ARGUMENT,O(a,this.clonePosition())) +var o=this.parseIdentifierIfPossible().value +if(!o)return this.error(l.MALFORMED_ARGUMENT,O(a,this.clonePosition())) +if(this.bumpSpace(),this.isEOF())return this.error(l.EXPECT_ARGUMENT_CLOSING_BRACE,O(a,this.clonePosition())) +switch(this.char()){case 125:return this.bump(),{val:{type:i.argument,value:o,location:O(a,this.clonePosition())},err:null} +case 44:return this.bump(),this.bumpSpace(),this.isEOF()?this.error(l.EXPECT_ARGUMENT_CLOSING_BRACE,O(a,this.clonePosition())):this.parseArgumentOptions(e,t,o,a) +default:return this.error(l.MALFORMED_ARGUMENT,O(a,this.clonePosition()))}},e.prototype.parseIdentifierIfPossible=function(){var e=this.clonePosition(),t=this.offset(),a=$(this.message,t),l=t+a.length +return this.bumpTo(l),{value:a,location:O(e,this.clonePosition())}},e.prototype.parseArgumentOptions=function(e,t,a,r){var c,h=this.clonePosition(),s=this.parseIdentifierIfPossible().value,d=this.clonePosition() +switch(s){case"":return this.error(l.EXPECT_ARGUMENT_TYPE,O(h,d)) +case"number":case"date":case"time":this.bumpSpace() +var u=null +if(this.bumpIf(",")){this.bumpSpace() +var f=this.clonePosition() +if((A=this.parseSimpleArgStyleIfPossible()).err)return A +if(0===(y=X(A.val)).length)return this.error(l.EXPECT_ARGUMENT_STYLE,O(this.clonePosition(),this.clonePosition())) +u={style:y,styleLocation:O(f,this.clonePosition())}}if((w=this.tryParseArgumentClose(r)).err)return w +var v=O(r,this.clonePosition()) +if(u&&q(null==u?void 0:u.style,"::",0)){var p=W(u.style.slice(2)) +if("number"===s)return(A=this.parseNumberSkeletonFromString(p,u.styleLocation)).err?A:{val:{type:i.number,value:a,location:v,style:A.val},err:null} +if(0===p.length)return this.error(l.EXPECT_DATE_TIME_SKELETON,v) +var m=p +this.locale&&(m=function(e,t){for(var a="",l=0;l>1),c=D(t) +for("H"!=c&&"k"!=c||(r=0);r-- >0;)a+="a" +for(;n-- >0;)a=c+a}else a+="J"===i?"H":i}return a}(p,this.locale)) +var y={type:o.dateTime,pattern:m,location:u.styleLocation,parsedOptions:this.shouldParseSkeletons?z(m):{}} +return{val:{type:"date"===s?i.date:i.time,value:a,location:v,style:y},err:null}}return{val:{type:"number"===s?i.number:"date"===s?i.date:i.time,value:a,location:v,style:null!==(c=null==u?void 0:u.style)&&void 0!==c?c:null},err:null} +case"plural":case"selectordinal":case"select":var g=this.clonePosition() +if(this.bumpSpace(),!this.bumpIf(","))return this.error(l.EXPECT_SELECT_ARGUMENT_OPTIONS,O(g,(0,n.pi)({},g))) +this.bumpSpace() +var b=this.parseIdentifierIfPossible(),M=0 +if("select"!==s&&"offset"===b.value){if(!this.bumpIf(":"))return this.error(l.EXPECT_PLURAL_ARGUMENT_OFFSET_VALUE,O(this.clonePosition(),this.clonePosition())) +var A +if(this.bumpSpace(),(A=this.tryParseDecimalInteger(l.EXPECT_PLURAL_ARGUMENT_OFFSET_VALUE,l.INVALID_PLURAL_ARGUMENT_OFFSET_VALUE)).err)return A +this.bumpSpace(),b=this.parseIdentifierIfPossible(),M=A.val}var w,x=this.tryParsePluralOrSelectOptions(e,s,t,b) +if(x.err)return x +if((w=this.tryParseArgumentClose(r)).err)return w +var H=O(r,this.clonePosition()) +return"select"===s?{val:{type:i.select,value:a,options:Y(x.val),location:H},err:null}:{val:{type:i.plural,value:a,options:Y(x.val),offset:M,pluralType:"plural"===s?"cardinal":"ordinal",location:H},err:null} +default:return this.error(l.INVALID_ARGUMENT_TYPE,O(h,d))}},e.prototype.tryParseArgumentClose=function(e){return this.isEOF()||125!==this.char()?this.error(l.EXPECT_ARGUMENT_CLOSING_BRACE,O(e,this.clonePosition())):(this.bump(),{val:!0,err:null})},e.prototype.parseSimpleArgStyleIfPossible=function(){for(var e=0,t=this.clonePosition();!this.isEOF();)switch(this.char()){case 39:this.bump() +var a=this.clonePosition() +if(!this.bumpUntil("'"))return this.error(l.UNCLOSED_QUOTE_IN_ARGUMENT_STYLE,O(a,this.clonePosition())) +this.bump() +break +case 123:e+=1,this.bump() +break +case 125:if(!(e>0))return{val:this.message.slice(t.offset,this.offset()),err:null} +e-=1 +break +default:this.bump()}return{val:this.message.slice(t.offset,this.offset()),err:null}},e.prototype.parseNumberSkeletonFromString=function(e,t){var a=[] +try{a=function(e){if(0===e.length)throw new Error("Number skeleton cannot be empty") +for(var t=[],a=0,l=e.split(M).filter((function(e){return e.length>0}));a=48&&n<=57))break +i=!0,o=10*o+(n-48),this.bump()}var r=O(l,this.clonePosition()) +return i?I(o*=a)?{val:o,err:null}:this.error(t,r):this.error(e,r)},e.prototype.offset=function(){return this.position.offset},e.prototype.isEOF=function(){return this.offset()===this.message.length},e.prototype.clonePosition=function(){return{offset:this.position.offset,line:this.position.line,column:this.position.column}},e.prototype.char=function(){var e=this.position.offset +if(e>=this.message.length)throw Error("out of bound") +var t=K(this.message,e) +if(void 0===t)throw Error("Offset ".concat(e," is at invalid UTF-16 code unit boundary")) +return t},e.prototype.error=function(e,t){return{val:null,err:{kind:e,message:this.message,location:t}}},e.prototype.bump=function(){if(!this.isEOF()){var e=this.char() +10===e?(this.position.line+=1,this.position.column=1,this.position.offset+=1):(this.position.column+=1,this.position.offset+=e<65536?1:2)}},e.prototype.bumpIf=function(e){if(q(this.message,e,this.offset())){for(var t=0;t=0?(this.bumpTo(a),!0):(this.bumpTo(this.message.length),!1)},e.prototype.bumpTo=function(e){if(this.offset()>e)throw Error("targetOffset ".concat(e," must be greater than or equal to the current offset ").concat(this.offset())) +for(e=Math.min(e,this.message.length);;){var t=this.offset() +if(t===e)break +if(t>e)throw Error("targetOffset ".concat(e," is at invalid UTF-16 code unit boundary")) +if(this.bump(),this.isEOF())break}},e.prototype.bumpSpace=function(){for(;!this.isEOF()&&ae(this.char());)this.bump()},e.prototype.peek=function(){if(this.isEOF())return null +var e=this.char(),t=this.offset(),a=this.message.charCodeAt(t+(e>=65536?2:1)) +return null!=a?a:null},e}() +function te(e){return e>=97&&e<=122||e>=65&&e<=90}function ae(e){return e>=9&&e<=13||32===e||133===e||e>=8206&&e<=8207||8232===e||8233===e}function le(e){return e>=33&&e<=35||36===e||e>=37&&e<=39||40===e||41===e||42===e||43===e||44===e||45===e||e>=46&&e<=47||e>=58&&e<=59||e>=60&&e<=62||e>=63&&e<=64||91===e||92===e||93===e||94===e||96===e||123===e||124===e||125===e||126===e||161===e||e>=162&&e<=165||166===e||167===e||169===e||171===e||172===e||174===e||176===e||177===e||182===e||187===e||191===e||215===e||247===e||e>=8208&&e<=8213||e>=8214&&e<=8215||8216===e||8217===e||8218===e||e>=8219&&e<=8220||8221===e||8222===e||8223===e||e>=8224&&e<=8231||e>=8240&&e<=8248||8249===e||8250===e||e>=8251&&e<=8254||e>=8257&&e<=8259||8260===e||8261===e||8262===e||e>=8263&&e<=8273||8274===e||8275===e||e>=8277&&e<=8286||e>=8592&&e<=8596||e>=8597&&e<=8601||e>=8602&&e<=8603||e>=8604&&e<=8607||8608===e||e>=8609&&e<=8610||8611===e||e>=8612&&e<=8613||8614===e||e>=8615&&e<=8621||8622===e||e>=8623&&e<=8653||e>=8654&&e<=8655||e>=8656&&e<=8657||8658===e||8659===e||8660===e||e>=8661&&e<=8691||e>=8692&&e<=8959||e>=8960&&e<=8967||8968===e||8969===e||8970===e||8971===e||e>=8972&&e<=8991||e>=8992&&e<=8993||e>=8994&&e<=9e3||9001===e||9002===e||e>=9003&&e<=9083||9084===e||e>=9085&&e<=9114||e>=9115&&e<=9139||e>=9140&&e<=9179||e>=9180&&e<=9185||e>=9186&&e<=9254||e>=9255&&e<=9279||e>=9280&&e<=9290||e>=9291&&e<=9311||e>=9472&&e<=9654||9655===e||e>=9656&&e<=9664||9665===e||e>=9666&&e<=9719||e>=9720&&e<=9727||e>=9728&&e<=9838||9839===e||e>=9840&&e<=10087||10088===e||10089===e||10090===e||10091===e||10092===e||10093===e||10094===e||10095===e||10096===e||10097===e||10098===e||10099===e||10100===e||10101===e||e>=10132&&e<=10175||e>=10176&&e<=10180||10181===e||10182===e||e>=10183&&e<=10213||10214===e||10215===e||10216===e||10217===e||10218===e||10219===e||10220===e||10221===e||10222===e||10223===e||e>=10224&&e<=10239||e>=10240&&e<=10495||e>=10496&&e<=10626||10627===e||10628===e||10629===e||10630===e||10631===e||10632===e||10633===e||10634===e||10635===e||10636===e||10637===e||10638===e||10639===e||10640===e||10641===e||10642===e||10643===e||10644===e||10645===e||10646===e||10647===e||10648===e||e>=10649&&e<=10711||10712===e||10713===e||10714===e||10715===e||e>=10716&&e<=10747||10748===e||10749===e||e>=10750&&e<=11007||e>=11008&&e<=11055||e>=11056&&e<=11076||e>=11077&&e<=11078||e>=11079&&e<=11084||e>=11085&&e<=11123||e>=11124&&e<=11125||e>=11126&&e<=11157||11158===e||e>=11159&&e<=11263||e>=11776&&e<=11777||11778===e||11779===e||11780===e||11781===e||e>=11782&&e<=11784||11785===e||11786===e||11787===e||11788===e||11789===e||e>=11790&&e<=11798||11799===e||e>=11800&&e<=11801||11802===e||11803===e||11804===e||11805===e||e>=11806&&e<=11807||11808===e||11809===e||11810===e||11811===e||11812===e||11813===e||11814===e||11815===e||11816===e||11817===e||e>=11818&&e<=11822||11823===e||e>=11824&&e<=11833||e>=11834&&e<=11835||e>=11836&&e<=11839||11840===e||11841===e||11842===e||e>=11843&&e<=11855||e>=11856&&e<=11857||11858===e||e>=11859&&e<=11903||e>=12289&&e<=12291||12296===e||12297===e||12298===e||12299===e||12300===e||12301===e||12302===e||12303===e||12304===e||12305===e||e>=12306&&e<=12307||12308===e||12309===e||12310===e||12311===e||12312===e||12313===e||12314===e||12315===e||12316===e||12317===e||e>=12318&&e<=12319||12320===e||12336===e||64830===e||64831===e||e>=65093&&e<=65094}function ie(e){e.forEach((function(e){if(delete e.location,u(e)||f(e))for(var t in e.options)delete e.options[t].location,ie(e.options[t].value) +else h(e)&&m(e.style)||(s(e)||d(e))&&y(e.style)?delete e.style.location:p(e)&&ie(e.children)}))}function oe(e,t){void 0===t&&(t={}),t=(0,n.pi)({shouldParseSkeletons:!0,requiresOtherClause:!0},t) +var a=new ee(e,t).parse() +if(a.err){var i=SyntaxError(l[a.err.kind]) +throw i.location=a.err.location,i.originalMessage=a.err.message,i}return(null==t?void 0:t.captureLocation)||ie(a.val),a.val}function ne(e,t){var a=t&&t.cache?t.cache:ve,l=t&&t.serializer?t.serializer:de +return(t&&t.strategy?t.strategy:se)(e,{cache:a,serializer:l})}function re(e,t,a,l){var i,o=null==(i=l)||"number"==typeof i||"boolean"==typeof i?l:a(l),n=t.get(o) +return void 0===n&&(n=e.call(this,l),t.set(o,n)),n}function ce(e,t,a){var l=Array.prototype.slice.call(arguments,3),i=a(l),o=t.get(i) +return void 0===o&&(o=e.apply(this,l),t.set(i,o)),o}function he(e,t,a,l,i){return a.bind(t,e,l,i)}function se(e,t){return he(e,this,1===e.length?re:ce,t.cache.create(),t.serializer)}var de=function(){return JSON.stringify(arguments)} +function ue(){this.cache=Object.create(null)}ue.prototype.get=function(e){return this.cache[e]},ue.prototype.set=function(e,t){this.cache[e]=t} +var fe,ve={create:function(){return new ue}},pe={variadic:function(e,t){return he(e,this,ce,t.cache.create(),t.serializer)},monadic:function(e,t){return he(e,this,re,t.cache.create(),t.serializer)}} +!function(e){e.MISSING_VALUE="MISSING_VALUE",e.INVALID_VALUE="INVALID_VALUE",e.MISSING_INTL_API="MISSING_INTL_API"}(fe||(fe={})) +var me,ye=function(e){function t(t,a,l){var i=e.call(this,t)||this +return i.code=a,i.originalMessage=l,i}return(0,n.ZT)(t,e),t.prototype.toString=function(){return"[formatjs Error: ".concat(this.code,"] ").concat(this.message)},t}(Error),ge=function(e){function t(t,a,l,i){return e.call(this,'Invalid values for "'.concat(t,'": "').concat(a,'". Options are "').concat(Object.keys(l).join('", "'),'"'),fe.INVALID_VALUE,i)||this}return(0,n.ZT)(t,e),t}(ye),be=function(e){function t(t,a,l){return e.call(this,'Value for "'.concat(t,'" must be of type ').concat(a),fe.INVALID_VALUE,l)||this}return(0,n.ZT)(t,e),t}(ye),ze=function(e){function t(t,a){return e.call(this,'The intl string context variable "'.concat(t,'" was not provided to the string "').concat(a,'"'),fe.MISSING_VALUE,a)||this}return(0,n.ZT)(t,e),t}(ye) +function Me(e){return"function"==typeof e}function Ae(e,t,a,l,i,o,n){if(1===e.length&&r(e[0]))return[{type:me.literal,value:e[0].value}] +for(var g=[],b=0,z=e;b0?new Intl.Locale(t[0]):new Intl.Locale("string"==typeof e?e:e[0])},e.__parse=oe,e.formats={number:{integer:{maximumFractionDigits:0},currency:{style:"currency"},percent:{style:"percent"}},date:{short:{month:"numeric",day:"numeric",year:"2-digit"},medium:{month:"short",day:"numeric",year:"numeric"},long:{month:"long",day:"numeric",year:"numeric"},full:{weekday:"long",month:"long",day:"numeric",year:"numeric"}},time:{short:{hour:"numeric",minute:"numeric"},medium:{hour:"numeric",minute:"numeric",second:"numeric"},long:{hour:"numeric",minute:"numeric",second:"numeric",timeZoneName:"short"},full:{hour:"numeric",minute:"numeric",second:"numeric",timeZoneName:"short"}}},e}() +const He=xe},5709:(e,t,a)=>{var l=a(9958),i=a(2451) +function o(e){this.Container=e||Array,this.items=new Map,this.clear(),Object.defineProperty(this.items,"constructor",{value:o,enumerable:!1})}o.prototype.clear=function(){this.size=0,this.dimension=0,this.items.clear()},o.prototype.set=function(e,t){var a,l=this.items.get(e) +return l||(this.dimension++,l=new this.Container,this.items.set(e,l)),this.Container===Set?(a=l.size,l.add(t),a1?t:this,this.items.forEach((function(e,t){a=t,e.forEach(l)}))},o.prototype.forEachAssociation=function(e,t){t=arguments.length>1?t:this,this.items.forEach(e,t)},o.prototype.keys=function(){return this.items.keys()},o.prototype.values=function(){var e,t,a,i,o=this.items.values(),n=!1 +return this.Container===Set?new l((function a(){if(!n){if((t=o.next()).done)return{done:!0} +n=!0,e=t.value.values()}return(t=e.next()).done?(n=!1,a()):{done:!1,value:t.value}})):new l((function l(){if(!n){if((t=o.next()).done)return{done:!0} +n=!0,e=t.value,a=0,i=e.length}return a>=i?(n=!1,l()):{done:!1,value:e[a++]}}))},o.prototype.entries=function(){var e,t,a,i,o,n=this.items.entries(),r=!1 +return this.Container===Set?new l((function l(){if(!r){if((t=n.next()).done)return{done:!0} +r=!0,a=t.value[0],e=t.value[1].values()}return(t=e.next()).done?(r=!1,l()):{done:!1,value:[a,t.value]}})):new l((function l(){if(!r){if((t=n.next()).done)return{done:!0} +r=!0,a=t.value[0],e=t.value[1],i=0,o=e.length}return i>=o?(r=!1,l()):{done:!1,value:[a,e[i++]]}}))},o.prototype.containers=function(){return this.items.values()},o.prototype.associations=function(){return this.items.entries()},"undefined"!=typeof Symbol&&(o.prototype[Symbol.iterator]=o.prototype.entries),o.prototype.inspect=function(){return this.items},"undefined"!=typeof Symbol&&(o.prototype[Symbol.for("nodejs.util.inspect.custom")]=o.prototype.inspect),o.prototype.toJSON=function(){return this.items},o.from=function(e,t){var a=new o(t) +return i(e,(function(e,t){a.set(t,e)})),a},e.exports=o},2519:(e,t)=>{t.intersection=function(){if(arguments.length<2)throw new Error("mnemonist/Set.intersection: needs at least two arguments.") +var e,t,a=new Set,l=1/0,i=null,o=arguments.length +for(t=0;tt.size)return!1 +for(;!(a=l.next()).done;)if(!t.has(a.value))return!1 +return!0},t.isSuperset=function(e,a){return t.isSubset(a,e)},t.add=function(e,t){for(var a,l=t.values();!(a=l.next()).done;)e.add(a.value)},t.subtract=function(e,t){for(var a,l=t.values();!(a=l.next()).done;)e.delete(a.value)},t.intersect=function(e,t){for(var a,l=e.values();!(a=l.next()).done;)t.has(a.value)||e.delete(a.value)},t.disjunct=function(e,t){for(var a,l=e.values(),i=[];!(a=l.next()).done;)t.has(a.value)&&i.push(a.value) +for(l=t.values();!(a=l.next()).done;)e.has(a.value)||e.add(a.value) +for(var o=0,n=i.length;ot.size&&(a=e,e=t,t=a),0===e.size)return 0 +if(e===t)return e.size +for(var l,i=e.values(),o=0;!(l=i.next()).done;)t.has(l.value)&&o++ +return o},t.unionSize=function(e,a){var l=t.intersectionSize(e,a) +return e.size+a.size-l},t.jaccard=function(e,a){var l=t.intersectionSize(e,a) +return 0===l?0:l/(e.size+a.size-l)},t.overlap=function(e,a){var l=t.intersectionSize(e,a) +return 0===l?0:l/Math.min(e.size,a.size)}},4977:e=>{function t(e,t){if(!e)throw new Error(t||"AssertionError")}t.notEqual=function(e,a,l){t(e!=a,l)},t.notOk=function(e,a){t(!e,a)},t.equal=function(e,a,l){t(e==a,l)},t.ok=t,e.exports=t},4208:e=>{e.exports=function(e){!function(e){if(!e)throw new Error("Eventify cannot use falsy object as events subject") +for(var t=["on","fire","off"],a=0;a1&&(l=Array.prototype.splice.call(arguments,1)) +for(var o=0;o{e.exports=function(e){if("uniqueLinkId"in(e=e||{})&&(console.warn("ngraph.graph: Starting from version 0.14 `uniqueLinkId` is deprecated.\nUse `multigraph` option instead\n","\n","Note: there is also change in default behavior: From now on each graph\nis considered to be not a multigraph by default (each edge is unique)."),e.multigraph=e.uniqueLinkId),void 0===e.multigraph&&(e.multigraph=!1),"function"!=typeof Map)throw new Error("ngraph.graph requires `Map` to be defined. Please polyfill it before using ngraph") +var t,a=new Map,h=[],s={},d=0,u=e.multigraph?function(e,t,a){var l=c(e,t),i=s.hasOwnProperty(l) +if(i||_(e,t)){i||(s[l]=0) +var o="@"+ ++s[l] +l=c(e+o,t+o)}return new r(e,t,a,l)}:function(e,t,a){return new r(e,t,a,c(e,t))},f=[],v=B,p=B,m=B,y=B,g={addNode:M,addLink:function(e,t,a){m() +var l=A(e)||M(e),i=A(t)||M(t),o=u(e,t,a) +return h.push(o),n(l,o),e!==t&&n(i,o),v(o,"add"),y(),o},removeLink:V,removeNode:w,getNode:A,getNodeCount:x,getLinkCount:H,getLinksCount:H,getNodesCount:x,getLinks:function(e){var t=A(e) +return t?t.links:null},forEachNode:E,forEachLinkedNode:function(e,t,l){var i=A(e) +if(i&&i.links&&"function"==typeof t)return l?function(e,t,l){for(var i=0;i=0&&a.links.splice(t,1),l&&(t=i(e,l.links))>=0&&l.links.splice(t,1),v(e,"remove"),y(),!0}function _(e,t){var a,l=A(e) +if(!l||!l.links)return null +for(a=0;a0&&(g.fire("changed",f),f.length=0)}function E(e){if("function"!=typeof e)throw new Error("Function is expected to iterate over graph nodes. You passed "+e) +for(var t=a.values(),l=t.next();!l.done;){if(e(l.value))return!0 +l=t.next()}}} +var l=a(4208) +function i(e,t){if(!t)return-1 +if(t.indexOf)return t.indexOf(e) +var a,l=t.length +for(a=0;a{var l=a(1317),i=l.ARRAY_BUFFER_SUPPORT,o=l.SYMBOL_SUPPORT +e.exports=function(e,t){var a,l,n,r,c +if(!e)throw new Error("obliterator/forEach: invalid iterable.") +if("function"!=typeof t)throw new Error("obliterator/forEach: expecting a callback.") +if(Array.isArray(e)||i&&ArrayBuffer.isView(e)||"string"==typeof e||"[object Arguments]"===e.toString())for(n=0,r=e.length;n{function t(e){if("function"!=typeof e)throw new Error("obliterator/iterator: expecting a function!") +this.next=e}"undefined"!=typeof Symbol&&(t.prototype[Symbol.iterator]=function(){return this}),t.of=function(){var e=arguments,a=e.length,l=0 +return new t((function(){return l>=a?{done:!0}:{done:!1,value:e[l++]}}))},t.empty=function(){return new t((function(){return{done:!0}}))},t.fromSequence=function(e){var a=0,l=e.length +return new t((function(){return a>=l?{done:!0}:{done:!1,value:e[a++]}}))},t.is=function(e){return e instanceof t||"object"==typeof e&&null!==e&&"function"==typeof e.next},e.exports=t},1317:(e,t)=>{t.ARRAY_BUFFER_SUPPORT="undefined"!=typeof ArrayBuffer,t.SYMBOL_SUPPORT="undefined"!=typeof Symbol},89:e=>{"use strict" +var t=/(\x2D?(?:\d+\.?\d*|\d*\.?\d+)(?:e[-+]?\d+)?)\s*([A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5D\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC\u{10000}-\u{1000B}\u{1000D}-\u{10026}\u{10028}-\u{1003A}\u{1003C}\u{1003D}\u{1003F}-\u{1004D}\u{10050}-\u{1005D}\u{10080}-\u{100FA}\u{10280}-\u{1029C}\u{102A0}-\u{102D0}\u{10300}-\u{1031F}\u{1032D}-\u{10340}\u{10342}-\u{10349}\u{10350}-\u{10375}\u{10380}-\u{1039D}\u{103A0}-\u{103C3}\u{103C8}-\u{103CF}\u{10400}-\u{1049D}\u{104B0}-\u{104D3}\u{104D8}-\u{104FB}\u{10500}-\u{10527}\u{10530}-\u{10563}\u{10570}-\u{1057A}\u{1057C}-\u{1058A}\u{1058C}-\u{10592}\u{10594}\u{10595}\u{10597}-\u{105A1}\u{105A3}-\u{105B1}\u{105B3}-\u{105B9}\u{105BB}\u{105BC}\u{10600}-\u{10736}\u{10740}-\u{10755}\u{10760}-\u{10767}\u{10780}-\u{10785}\u{10787}-\u{107B0}\u{107B2}-\u{107BA}\u{10800}-\u{10805}\u{10808}\u{1080A}-\u{10835}\u{10837}\u{10838}\u{1083C}\u{1083F}-\u{10855}\u{10860}-\u{10876}\u{10880}-\u{1089E}\u{108E0}-\u{108F2}\u{108F4}\u{108F5}\u{10900}-\u{10915}\u{10920}-\u{10939}\u{10980}-\u{109B7}\u{109BE}\u{109BF}\u{10A00}\u{10A10}-\u{10A13}\u{10A15}-\u{10A17}\u{10A19}-\u{10A35}\u{10A60}-\u{10A7C}\u{10A80}-\u{10A9C}\u{10AC0}-\u{10AC7}\u{10AC9}-\u{10AE4}\u{10B00}-\u{10B35}\u{10B40}-\u{10B55}\u{10B60}-\u{10B72}\u{10B80}-\u{10B91}\u{10C00}-\u{10C48}\u{10C80}-\u{10CB2}\u{10CC0}-\u{10CF2}\u{10D00}-\u{10D23}\u{10E80}-\u{10EA9}\u{10EB0}\u{10EB1}\u{10F00}-\u{10F1C}\u{10F27}\u{10F30}-\u{10F45}\u{10F70}-\u{10F81}\u{10FB0}-\u{10FC4}\u{10FE0}-\u{10FF6}\u{11003}-\u{11037}\u{11071}\u{11072}\u{11075}\u{11083}-\u{110AF}\u{110D0}-\u{110E8}\u{11103}-\u{11126}\u{11144}\u{11147}\u{11150}-\u{11172}\u{11176}\u{11183}-\u{111B2}\u{111C1}-\u{111C4}\u{111DA}\u{111DC}\u{11200}-\u{11211}\u{11213}-\u{1122B}\u{1123F}\u{11240}\u{11280}-\u{11286}\u{11288}\u{1128A}-\u{1128D}\u{1128F}-\u{1129D}\u{1129F}-\u{112A8}\u{112B0}-\u{112DE}\u{11305}-\u{1130C}\u{1130F}\u{11310}\u{11313}-\u{11328}\u{1132A}-\u{11330}\u{11332}\u{11333}\u{11335}-\u{11339}\u{1133D}\u{11350}\u{1135D}-\u{11361}\u{11400}-\u{11434}\u{11447}-\u{1144A}\u{1145F}-\u{11461}\u{11480}-\u{114AF}\u{114C4}\u{114C5}\u{114C7}\u{11580}-\u{115AE}\u{115D8}-\u{115DB}\u{11600}-\u{1162F}\u{11644}\u{11680}-\u{116AA}\u{116B8}\u{11700}-\u{1171A}\u{11740}-\u{11746}\u{11800}-\u{1182B}\u{118A0}-\u{118DF}\u{118FF}-\u{11906}\u{11909}\u{1190C}-\u{11913}\u{11915}\u{11916}\u{11918}-\u{1192F}\u{1193F}\u{11941}\u{119A0}-\u{119A7}\u{119AA}-\u{119D0}\u{119E1}\u{119E3}\u{11A00}\u{11A0B}-\u{11A32}\u{11A3A}\u{11A50}\u{11A5C}-\u{11A89}\u{11A9D}\u{11AB0}-\u{11AF8}\u{11C00}-\u{11C08}\u{11C0A}-\u{11C2E}\u{11C40}\u{11C72}-\u{11C8F}\u{11D00}-\u{11D06}\u{11D08}\u{11D09}\u{11D0B}-\u{11D30}\u{11D46}\u{11D60}-\u{11D65}\u{11D67}\u{11D68}\u{11D6A}-\u{11D89}\u{11D98}\u{11EE0}-\u{11EF2}\u{11F02}\u{11F04}-\u{11F10}\u{11F12}-\u{11F33}\u{11FB0}\u{12000}-\u{12399}\u{12480}-\u{12543}\u{12F90}-\u{12FF0}\u{13000}-\u{1342F}\u{13441}-\u{13446}\u{14400}-\u{14646}\u{16800}-\u{16A38}\u{16A40}-\u{16A5E}\u{16A70}-\u{16ABE}\u{16AD0}-\u{16AED}\u{16B00}-\u{16B2F}\u{16B40}-\u{16B43}\u{16B63}-\u{16B77}\u{16B7D}-\u{16B8F}\u{16E40}-\u{16E7F}\u{16F00}-\u{16F4A}\u{16F50}\u{16F93}-\u{16F9F}\u{16FE0}\u{16FE1}\u{16FE3}\u{17000}-\u{187F7}\u{18800}-\u{18CD5}\u{18D00}-\u{18D08}\u{1AFF0}-\u{1AFF3}\u{1AFF5}-\u{1AFFB}\u{1AFFD}\u{1AFFE}\u{1B000}-\u{1B122}\u{1B132}\u{1B150}-\u{1B152}\u{1B155}\u{1B164}-\u{1B167}\u{1B170}-\u{1B2FB}\u{1BC00}-\u{1BC6A}\u{1BC70}-\u{1BC7C}\u{1BC80}-\u{1BC88}\u{1BC90}-\u{1BC99}\u{1D400}-\u{1D454}\u{1D456}-\u{1D49C}\u{1D49E}\u{1D49F}\u{1D4A2}\u{1D4A5}\u{1D4A6}\u{1D4A9}-\u{1D4AC}\u{1D4AE}-\u{1D4B9}\u{1D4BB}\u{1D4BD}-\u{1D4C3}\u{1D4C5}-\u{1D505}\u{1D507}-\u{1D50A}\u{1D50D}-\u{1D514}\u{1D516}-\u{1D51C}\u{1D51E}-\u{1D539}\u{1D53B}-\u{1D53E}\u{1D540}-\u{1D544}\u{1D546}\u{1D54A}-\u{1D550}\u{1D552}-\u{1D6A5}\u{1D6A8}-\u{1D6C0}\u{1D6C2}-\u{1D6DA}\u{1D6DC}-\u{1D6FA}\u{1D6FC}-\u{1D714}\u{1D716}-\u{1D734}\u{1D736}-\u{1D74E}\u{1D750}-\u{1D76E}\u{1D770}-\u{1D788}\u{1D78A}-\u{1D7A8}\u{1D7AA}-\u{1D7C2}\u{1D7C4}-\u{1D7CB}\u{1DF00}-\u{1DF1E}\u{1DF25}-\u{1DF2A}\u{1E030}-\u{1E06D}\u{1E100}-\u{1E12C}\u{1E137}-\u{1E13D}\u{1E14E}\u{1E290}-\u{1E2AD}\u{1E2C0}-\u{1E2EB}\u{1E4D0}-\u{1E4EB}\u{1E7E0}-\u{1E7E6}\u{1E7E8}-\u{1E7EB}\u{1E7ED}\u{1E7EE}\u{1E7F0}-\u{1E7FE}\u{1E800}-\u{1E8C4}\u{1E900}-\u{1E943}\u{1E94B}\u{1EE00}-\u{1EE03}\u{1EE05}-\u{1EE1F}\u{1EE21}\u{1EE22}\u{1EE24}\u{1EE27}\u{1EE29}-\u{1EE32}\u{1EE34}-\u{1EE37}\u{1EE39}\u{1EE3B}\u{1EE42}\u{1EE47}\u{1EE49}\u{1EE4B}\u{1EE4D}-\u{1EE4F}\u{1EE51}\u{1EE52}\u{1EE54}\u{1EE57}\u{1EE59}\u{1EE5B}\u{1EE5D}\u{1EE5F}\u{1EE61}\u{1EE62}\u{1EE64}\u{1EE67}-\u{1EE6A}\u{1EE6C}-\u{1EE72}\u{1EE74}-\u{1EE77}\u{1EE79}-\u{1EE7C}\u{1EE7E}\u{1EE80}-\u{1EE89}\u{1EE8B}-\u{1EE9B}\u{1EEA1}-\u{1EEA3}\u{1EEA5}-\u{1EEA9}\u{1EEAB}-\u{1EEBB}\u{20000}-\u{2A6DF}\u{2A700}-\u{2B739}\u{2B740}-\u{2B81D}\u{2B820}-\u{2CEA1}\u{2CEB0}-\u{2EBE0}\u{2F800}-\u{2FA1D}\u{30000}-\u{3134A}\u{31350}-\u{323AF}]*)/giu +function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"ms" +var i=null +return e=(e+"").replace(/(\d)[,_](\d)/g,"$1$2"),e.replace(t,(function(e,t,a){(a=l(a))&&(i=(i||0)+parseFloat(t,10)*a)})),i&&i/(l(a)||1)}function l(e){return a[e]||a[e.toLowerCase().replace(/s$/,"")]}e.exports=a,e.exports.default=a,a.nanosecond=a.ns=1e-6,a["µs"]=a["μs"]=a.us=a.microsecond=.001,a.millisecond=a.ms=a[""]=1,a.second=a.sec=a.s=1e3*a.ms,a.minute=a.min=a.m=60*a.s,a.hour=a.hr=a.h=60*a.m,a.day=a.d=24*a.h,a.week=a.wk=a.w=7*a.d,a.month=a.b=30.4375*a.d,a.year=a.yr=a.y=365.25*a.d},3507:e=>{"use strict" +e.exports=e=>{if("number"!=typeof e)throw new TypeError("Expected a number") +const t=e>0?Math.floor:Math.ceil +return{days:t(e/864e5),hours:t(e/36e5)%24,minutes:t(e/6e4)%60,seconds:t(e/1e3)%60,milliseconds:t(e)%1e3,microseconds:t(1e3*e)%1e3,nanoseconds:t(1e6*e)%1e3}}},9837:(e,t,a)=>{"use strict" +const l=a(3507) +e.exports=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +if(!Number.isFinite(e))throw new TypeError("Expected a finite number") +t.colonNotation&&(t.compact=!1,t.formatSubMilliseconds=!1,t.separateMilliseconds=!1,t.verbose=!1),t.compact&&(t.secondsDecimalDigits=0,t.millisecondsDecimalDigits=0) +const a=[],i=(e,l,i,o)=>{if(!(0!==a.length&&t.colonNotation||0!==e||t.colonNotation&&"m"===i))return +let n,r +if(o=(o||e||"0").toString(),t.colonNotation){n=a.length>0?":":"",r="" +const e=o.includes(".")?o.split(".")[0].length:o.length,t=a.length>0?2:1 +o="0".repeat(Math.max(0,t-e))+o}else n="",r=t.verbose?" "+(c=l,1===e?c:`${c}s`):i +var c +a.push(n+o+r)},o=l(e) +if(i(Math.trunc(o.days/365),"year","y"),i(o.days%365,"day","d"),i(o.hours,"hour","h"),i(o.minutes,"minute","m"),t.separateMilliseconds||t.formatSubMilliseconds||!t.colonNotation&&e<1e3)if(i(o.seconds,"second","s"),t.formatSubMilliseconds)i(o.milliseconds,"millisecond","ms"),i(o.microseconds,"microsecond","µs"),i(o.nanoseconds,"nanosecond","ns") +else{const e=o.milliseconds+o.microseconds/1e3+o.nanoseconds/1e6,a="number"==typeof t.millisecondsDecimalDigits?t.millisecondsDecimalDigits:0,l=e>=1?Math.round(e):Math.ceil(e),n=a?e.toFixed(a):l +i(Number.parseFloat(n,10),"millisecond","ms",n)}else{const a=((e,t)=>{const a=Math.floor(e*10**t+1e-7) +return(Math.round(a)/10**t).toFixed(t)})(e/1e3%60,"number"==typeof t.secondsDecimalDigits?t.secondsDecimalDigits:1),l=t.keepDecimalsOnWholeSeconds?a:a.replace(/\.0+$/,"") +i(Number.parseFloat(l,10),"second","s",l)}if(0===a.length)return"0"+(t.verbose?" milliseconds":"ms") +if(t.compact)return a[0] +if("number"==typeof t.unitCount){const e=t.colonNotation?"":" " +return a.slice(0,Math.max(t.unitCount,1)).join(e)}return t.colonNotation?a.join(""):a.join(" ")}},9640:(e,t,a)=>{"use strict" +function l(e){if(null==e)return window +if("[object Window]"!==e.toString()){var t=e.ownerDocument +return t&&t.defaultView||window}return e}function i(e){return e instanceof l(e).Element||e instanceof Element}function o(e){return e instanceof l(e).HTMLElement||e instanceof HTMLElement}function n(e){return"undefined"!=typeof ShadowRoot&&(e instanceof l(e).ShadowRoot||e instanceof ShadowRoot)}a.r(t),a.d(t,{animateFill:()=>dt,createSingleton:()=>ct,default:()=>bt,delegate:()=>st,followCursor:()=>pt,hideAll:()=>nt,inlinePositioning:()=>mt,roundArrow:()=>fe,sticky:()=>yt}) +var r=Math.max,c=Math.min,h=Math.round +function s(){var e=navigator.userAgentData +return null!=e&&e.brands?e.brands.map((function(e){return e.brand+"/"+e.version})).join(" "):navigator.userAgent}function d(){return!/^((?!chrome|android).)*safari/i.test(s())}function u(e,t,a){void 0===t&&(t=!1),void 0===a&&(a=!1) +var n=e.getBoundingClientRect(),r=1,c=1 +t&&o(e)&&(r=e.offsetWidth>0&&h(n.width)/e.offsetWidth||1,c=e.offsetHeight>0&&h(n.height)/e.offsetHeight||1) +var s=(i(e)?l(e):window).visualViewport,u=!d()&&a,f=(n.left+(u&&s?s.offsetLeft:0))/r,v=(n.top+(u&&s?s.offsetTop:0))/c,p=n.width/r,m=n.height/c +return{width:p,height:m,top:v,right:f+p,bottom:v+m,left:f,x:f,y:v}}function f(e){var t=l(e) +return{scrollLeft:t.pageXOffset,scrollTop:t.pageYOffset}}function v(e){return e?(e.nodeName||"").toLowerCase():null}function p(e){return((i(e)?e.ownerDocument:e.document)||window.document).documentElement}function m(e){return u(p(e)).left+f(e).scrollLeft}function y(e){return l(e).getComputedStyle(e)}function g(e){var t=y(e),a=t.overflow,l=t.overflowX,i=t.overflowY +return/auto|scroll|overlay|hidden/.test(a+i+l)}function b(e,t,a){void 0===a&&(a=!1) +var i,n,r=o(t),c=o(t)&&function(e){var t=e.getBoundingClientRect(),a=h(t.width)/e.offsetWidth||1,l=h(t.height)/e.offsetHeight||1 +return 1!==a||1!==l}(t),s=p(t),d=u(e,c,a),y={scrollLeft:0,scrollTop:0},b={x:0,y:0} +return(r||!r&&!a)&&(("body"!==v(t)||g(s))&&(y=(i=t)!==l(i)&&o(i)?{scrollLeft:(n=i).scrollLeft,scrollTop:n.scrollTop}:f(i)),o(t)?((b=u(t,!0)).x+=t.clientLeft,b.y+=t.clientTop):s&&(b.x=m(s))),{x:d.left+y.scrollLeft-b.x,y:d.top+y.scrollTop-b.y,width:d.width,height:d.height}}function z(e){var t=u(e),a=e.offsetWidth,l=e.offsetHeight +return Math.abs(t.width-a)<=1&&(a=t.width),Math.abs(t.height-l)<=1&&(l=t.height),{x:e.offsetLeft,y:e.offsetTop,width:a,height:l}}function M(e){return"html"===v(e)?e:e.assignedSlot||e.parentNode||(n(e)?e.host:null)||p(e)}function A(e){return["html","body","#document"].indexOf(v(e))>=0?e.ownerDocument.body:o(e)&&g(e)?e:A(M(e))}function w(e,t){var a +void 0===t&&(t=[]) +var i=A(e),o=i===(null==(a=e.ownerDocument)?void 0:a.body),n=l(i),r=o?[n].concat(n.visualViewport||[],g(i)?i:[]):i,c=t.concat(r) +return o?c:c.concat(w(M(r)))}function x(e){return["table","td","th"].indexOf(v(e))>=0}function H(e){return o(e)&&"fixed"!==y(e).position?e.offsetParent:null}function V(e){for(var t=l(e),a=H(e);a&&x(a)&&"static"===y(a).position;)a=H(a) +return a&&("html"===v(a)||"body"===v(a)&&"static"===y(a).position)?t:a||function(e){var t=/firefox/i.test(s()) +if(/Trident/i.test(s())&&o(e)&&"fixed"===y(e).position)return null +var a=M(e) +for(n(a)&&(a=a.host);o(a)&&["html","body"].indexOf(v(a))<0;){var l=y(a) +if("none"!==l.transform||"none"!==l.perspective||"paint"===l.contain||-1!==["transform","perspective"].indexOf(l.willChange)||t&&"filter"===l.willChange||t&&l.filter&&"none"!==l.filter)return a +a=a.parentNode}return null}(e)||t}var _="top",B="bottom",L="right",C="left",E="auto",k=[_,B,L,C],D="start",S="end",F="clippingParents",O="viewport",T="popper",P="reference",N=k.reduce((function(e,t){return e.concat([t+"-"+D,t+"-"+S])}),[]),U=[].concat(k,[E]).reduce((function(e,t){return e.concat([t,t+"-"+D,t+"-"+S])}),[]),R=["beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite"] +function j(e){var t=new Map,a=new Set,l=[] +function i(e){a.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){if(!a.has(e)){var l=t.get(e) +l&&i(l)}})),l.push(e)}return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){a.has(e.name)||i(e)})),l}var I={placement:"bottom",modifiers:[],strategy:"absolute"} +function G(){for(var e=arguments.length,t=new Array(e),a=0;a=0?"x":"y"}function K(e){var t,a=e.reference,l=e.element,i=e.placement,o=i?q(i):null,n=i?Z(i):null,r=a.x+a.width/2-l.width/2,c=a.y+a.height/2-l.height/2 +switch(o){case _:t={x:r,y:a.y-l.height} +break +case B:t={x:r,y:a.y+a.height} +break +case L:t={x:a.x+a.width,y:c} +break +case C:t={x:a.x-l.width,y:c} +break +default:t={x:a.x,y:a.y}}var h=o?Y(o):null +if(null!=h){var s="y"===h?"height":"width" +switch(n){case D:t[h]=t[h]-(a[s]/2-l[s]/2) +break +case S:t[h]=t[h]+(a[s]/2-l[s]/2)}}return t}var W={top:"auto",right:"auto",bottom:"auto",left:"auto"} +function X(e){var t,a=e.popper,i=e.popperRect,o=e.placement,n=e.variation,r=e.offsets,c=e.position,s=e.gpuAcceleration,d=e.adaptive,u=e.roundOffsets,f=e.isFixed,v=r.x,m=void 0===v?0:v,g=r.y,b=void 0===g?0:g,z="function"==typeof u?u({x:m,y:b}):{x:m,y:b} +m=z.x,b=z.y +var M=r.hasOwnProperty("x"),A=r.hasOwnProperty("y"),w=C,x=_,H=window +if(d){var E=V(a),k="clientHeight",D="clientWidth" +E===l(a)&&"static"!==y(E=p(a)).position&&"absolute"===c&&(k="scrollHeight",D="scrollWidth"),(o===_||(o===C||o===L)&&n===S)&&(x=B,b-=(f&&E===H&&H.visualViewport?H.visualViewport.height:E[k])-i.height,b*=s?1:-1),o!==C&&(o!==_&&o!==B||n!==S)||(w=L,m-=(f&&E===H&&H.visualViewport?H.visualViewport.width:E[D])-i.width,m*=s?1:-1)}var F,O=Object.assign({position:c},d&&W),T=!0===u?function(e){var t=e.x,a=e.y,l=window.devicePixelRatio||1 +return{x:h(t*l)/l||0,y:h(a*l)/l||0}}({x:m,y:b}):{x:m,y:b} +return m=T.x,b=T.y,s?Object.assign({},O,((F={})[x]=A?"0":"",F[w]=M?"0":"",F.transform=(H.devicePixelRatio||1)<=1?"translate("+m+"px, "+b+"px)":"translate3d("+m+"px, "+b+"px, 0)",F)):Object.assign({},O,((t={})[x]=A?b+"px":"",t[w]=M?m+"px":"",t.transform="",t))}const J={name:"applyStyles",enabled:!0,phase:"write",fn:function(e){var t=e.state +Object.keys(t.elements).forEach((function(e){var a=t.styles[e]||{},l=t.attributes[e]||{},i=t.elements[e] +o(i)&&v(i)&&(Object.assign(i.style,a),Object.keys(l).forEach((function(e){var t=l[e] +!1===t?i.removeAttribute(e):i.setAttribute(e,!0===t?"":t)})))}))},effect:function(e){var t=e.state,a={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}} +return Object.assign(t.elements.popper.style,a.popper),t.styles=a,t.elements.arrow&&Object.assign(t.elements.arrow.style,a.arrow),function(){Object.keys(t.elements).forEach((function(e){var l=t.elements[e],i=t.attributes[e]||{},n=Object.keys(t.styles.hasOwnProperty(e)?t.styles[e]:a[e]).reduce((function(e,t){return e[t]="",e}),{}) +o(l)&&v(l)&&(Object.assign(l.style,n),Object.keys(i).forEach((function(e){l.removeAttribute(e)})))}))}},requires:["computeStyles"]} +var Q={left:"right",right:"left",bottom:"top",top:"bottom"} +function ee(e){return e.replace(/left|right|bottom|top/g,(function(e){return Q[e]}))}var te={start:"end",end:"start"} +function ae(e){return e.replace(/start|end/g,(function(e){return te[e]}))}function le(e,t){var a=t.getRootNode&&t.getRootNode() +if(e.contains(t))return!0 +if(a&&n(a)){var l=t +do{if(l&&e.isSameNode(l))return!0 +l=l.parentNode||l.host}while(l)}return!1}function ie(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function oe(e,t,a){return t===O?ie(function(e,t){var a=l(e),i=p(e),o=a.visualViewport,n=i.clientWidth,r=i.clientHeight,c=0,h=0 +if(o){n=o.width,r=o.height +var s=d();(s||!s&&"fixed"===t)&&(c=o.offsetLeft,h=o.offsetTop)}return{width:n,height:r,x:c+m(e),y:h}}(e,a)):i(t)?function(e,t){var a=u(e,!1,"fixed"===t) +return a.top=a.top+e.clientTop,a.left=a.left+e.clientLeft,a.bottom=a.top+e.clientHeight,a.right=a.left+e.clientWidth,a.width=e.clientWidth,a.height=e.clientHeight,a.x=a.left,a.y=a.top,a}(t,a):ie(function(e){var t,a=p(e),l=f(e),i=null==(t=e.ownerDocument)?void 0:t.body,o=r(a.scrollWidth,a.clientWidth,i?i.scrollWidth:0,i?i.clientWidth:0),n=r(a.scrollHeight,a.clientHeight,i?i.scrollHeight:0,i?i.clientHeight:0),c=-l.scrollLeft+m(e),h=-l.scrollTop +return"rtl"===y(i||a).direction&&(c+=r(a.clientWidth,i?i.clientWidth:0)-o),{width:o,height:n,x:c,y:h}}(p(e)))}function ne(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},e)}function re(e,t){return t.reduce((function(t,a){return t[a]=e,t}),{})}function ce(e,t){void 0===t&&(t={}) +var a=t,l=a.placement,n=void 0===l?e.placement:l,h=a.strategy,s=void 0===h?e.strategy:h,d=a.boundary,f=void 0===d?F:d,m=a.rootBoundary,g=void 0===m?O:m,b=a.elementContext,z=void 0===b?T:b,A=a.altBoundary,x=void 0!==A&&A,H=a.padding,C=void 0===H?0:H,E=ne("number"!=typeof C?C:re(C,k)),D=z===T?P:T,S=e.rects.popper,N=e.elements[x?D:z],U=function(e,t,a,l){var n="clippingParents"===t?function(e){var t=w(M(e)),a=["absolute","fixed"].indexOf(y(e).position)>=0&&o(e)?V(e):e +return i(a)?t.filter((function(e){return i(e)&&le(e,a)&&"body"!==v(e)})):[]}(e):[].concat(t),h=[].concat(n,[a]),s=h[0],d=h.reduce((function(t,a){var i=oe(e,a,l) +return t.top=r(i.top,t.top),t.right=c(i.right,t.right),t.bottom=c(i.bottom,t.bottom),t.left=r(i.left,t.left),t}),oe(e,s,l)) +return d.width=d.right-d.left,d.height=d.bottom-d.top,d.x=d.left,d.y=d.top,d}(i(N)?N:N.contextElement||p(e.elements.popper),f,g,s),R=u(e.elements.reference),j=K({reference:R,element:S,strategy:"absolute",placement:n}),I=ie(Object.assign({},S,j)),G=z===T?I:R,$={top:U.top-G.top+E.top,bottom:G.bottom-U.bottom+E.bottom,left:U.left-G.left+E.left,right:G.right-U.right+E.right},q=e.modifiersData.offset +if(z===T&&q){var Z=q[n] +Object.keys($).forEach((function(e){var t=[L,B].indexOf(e)>=0?1:-1,a=[_,B].indexOf(e)>=0?"y":"x" +$[e]+=Z[a]*t}))}return $}function he(e,t,a){return r(e,c(t,a))}function se(e,t,a){return void 0===a&&(a={x:0,y:0}),{top:e.top-t.height-a.y,right:e.right-t.width+a.x,bottom:e.bottom-t.height+a.y,left:e.left-t.width-a.x}}function de(e){return[_,L,B,C].some((function(t){return e[t]>=0}))}var ue=function(e){void 0===e&&(e={}) +var t=e,a=t.defaultModifiers,l=void 0===a?[]:a,o=t.defaultOptions,n=void 0===o?I:o +return function(e,t,a){void 0===a&&(a=n) +var o,r,c={placement:"bottom",orderedModifiers:[],options:Object.assign({},I,n),modifiersData:{},elements:{reference:e,popper:t},attributes:{},styles:{}},h=[],s=!1,d={state:c,setOptions:function(a){var o="function"==typeof a?a(c.options):a +u(),c.options=Object.assign({},n,c.options,o),c.scrollParents={reference:i(e)?w(e):e.contextElement?w(e.contextElement):[],popper:w(t)} +var r,s,f=function(e){var t=j(e) +return R.reduce((function(e,a){return e.concat(t.filter((function(e){return e.phase===a})))}),[])}((r=[].concat(l,c.options.modifiers),s=r.reduce((function(e,t){var a=e[t.name] +return e[t.name]=a?Object.assign({},a,t,{options:Object.assign({},a.options,t.options),data:Object.assign({},a.data,t.data)}):t,e}),{}),Object.keys(s).map((function(e){return s[e]})))) +return c.orderedModifiers=f.filter((function(e){return e.enabled})),c.orderedModifiers.forEach((function(e){var t=e.name,a=e.options,l=void 0===a?{}:a,i=e.effect +if("function"==typeof i){var o=i({state:c,name:t,instance:d,options:l}) +h.push(o||function(){})}})),d.update()},forceUpdate:function(){if(!s){var e=c.elements,t=e.reference,a=e.popper +if(G(t,a)){c.rects={reference:b(t,V(a),"fixed"===c.options.strategy),popper:z(a)},c.reset=!1,c.placement=c.options.placement,c.orderedModifiers.forEach((function(e){return c.modifiersData[e.name]=Object.assign({},e.data)})) +for(var l=0;l=0?-1:1,o="function"==typeof a?a(Object.assign({},t,{placement:e})):a,n=o[0],r=o[1] +return n=n||0,r=(r||0)*i,[C,L].indexOf(l)>=0?{x:r,y:n}:{x:n,y:r}}(a,t.rects,o),e}),{}),r=n[t.placement],c=r.x,h=r.y +null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=c,t.modifiersData.popperOffsets.y+=h),t.modifiersData[l]=n}},{name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,a=e.options,l=e.name +if(!t.modifiersData[l]._skip){for(var i=a.mainAxis,o=void 0===i||i,n=a.altAxis,r=void 0===n||n,c=a.fallbackPlacements,h=a.padding,s=a.boundary,d=a.rootBoundary,u=a.altBoundary,f=a.flipVariations,v=void 0===f||f,p=a.allowedAutoPlacements,m=t.options.placement,y=q(m),g=c||(y!==m&&v?function(e){if(q(e)===E)return[] +var t=ee(e) +return[ae(e),t,ae(t)]}(m):[ee(m)]),b=[m].concat(g).reduce((function(e,a){return e.concat(q(a)===E?function(e,t){void 0===t&&(t={}) +var a=t,l=a.placement,i=a.boundary,o=a.rootBoundary,n=a.padding,r=a.flipVariations,c=a.allowedAutoPlacements,h=void 0===c?U:c,s=Z(l),d=s?r?N:N.filter((function(e){return Z(e)===s})):k,u=d.filter((function(e){return h.indexOf(e)>=0})) +0===u.length&&(u=d) +var f=u.reduce((function(t,a){return t[a]=ce(e,{placement:a,boundary:i,rootBoundary:o,padding:n})[q(a)],t}),{}) +return Object.keys(f).sort((function(e,t){return f[e]-f[t]}))}(t,{placement:a,boundary:s,rootBoundary:d,padding:h,flipVariations:v,allowedAutoPlacements:p}):a)}),[]),z=t.rects.reference,M=t.rects.popper,A=new Map,w=!0,x=b[0],H=0;H=0,T=O?"width":"height",P=ce(t,{placement:V,boundary:s,rootBoundary:d,altBoundary:u,padding:h}),R=O?F?L:C:F?B:_ +z[T]>M[T]&&(R=ee(R)) +var j=ee(R),I=[] +if(o&&I.push(P[S]<=0),r&&I.push(P[R]<=0,P[j]<=0),I.every((function(e){return e}))){x=V,w=!1 +break}A.set(V,I)}if(w)for(var G=function(e){var t=b.find((function(t){var a=A.get(t) +if(a)return a.slice(0,e).every((function(e){return e}))})) +if(t)return x=t,"break"},$=v?3:1;$>0&&"break"!==G($);$--);t.placement!==x&&(t.modifiersData[l]._skip=!0,t.placement=x,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}},{name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,a=e.options,l=e.name,i=a.mainAxis,o=void 0===i||i,n=a.altAxis,h=void 0!==n&&n,s=a.boundary,d=a.rootBoundary,u=a.altBoundary,f=a.padding,v=a.tether,p=void 0===v||v,m=a.tetherOffset,y=void 0===m?0:m,g=ce(t,{boundary:s,rootBoundary:d,padding:f,altBoundary:u}),b=q(t.placement),M=Z(t.placement),A=!M,w=Y(b),x="x"===w?"y":"x",H=t.modifiersData.popperOffsets,E=t.rects.reference,k=t.rects.popper,S="function"==typeof y?y(Object.assign({},t.rects,{placement:t.placement})):y,F="number"==typeof S?{mainAxis:S,altAxis:S}:Object.assign({mainAxis:0,altAxis:0},S),O=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,T={x:0,y:0} +if(H){if(o){var P,N="y"===w?_:C,U="y"===w?B:L,R="y"===w?"height":"width",j=H[w],I=j+g[N],G=j-g[U],$=p?-k[R]/2:0,K=M===D?E[R]:k[R],W=M===D?-k[R]:-E[R],X=t.elements.arrow,J=p&&X?z(X):{width:0,height:0},Q=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},ee=Q[N],te=Q[U],ae=he(0,E[R],J[R]),le=A?E[R]/2-$-ae-ee-F.mainAxis:K-ae-ee-F.mainAxis,ie=A?-E[R]/2+$+ae+te+F.mainAxis:W+ae+te+F.mainAxis,oe=t.elements.arrow&&V(t.elements.arrow),ne=oe?"y"===w?oe.clientTop||0:oe.clientLeft||0:0,re=null!=(P=null==O?void 0:O[w])?P:0,se=j+ie-re,de=he(p?c(I,j+le-re-ne):I,j,p?r(G,se):G) +H[w]=de,T[w]=de-j}if(h){var ue,fe="x"===w?_:C,ve="x"===w?B:L,pe=H[x],me="y"===x?"height":"width",ye=pe+g[fe],ge=pe-g[ve],be=-1!==[_,C].indexOf(b),ze=null!=(ue=null==O?void 0:O[x])?ue:0,Me=be?ye:pe-E[me]-k[me]-ze+F.altAxis,Ae=be?pe+E[me]+k[me]-ze-F.altAxis:ge,we=p&&be?function(e,t,a){var l=he(e,t,a) +return l>a?a:l}(Me,pe,Ae):he(p?Me:ye,pe,p?Ae:ge) +H[x]=we,T[x]=we-pe}t.modifiersData[l]=T}},requiresIfExists:["offset"]},{name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,a=e.state,l=e.name,i=e.options,o=a.elements.arrow,n=a.modifiersData.popperOffsets,r=q(a.placement),c=Y(r),h=[C,L].indexOf(r)>=0?"height":"width" +if(o&&n){var s=function(e,t){return ne("number"!=typeof(e="function"==typeof e?e(Object.assign({},t.rects,{placement:t.placement})):e)?e:re(e,k))}(i.padding,a),d=z(o),u="y"===c?_:C,f="y"===c?B:L,v=a.rects.reference[h]+a.rects.reference[c]-n[c]-a.rects.popper[h],p=n[c]-a.rects.reference[c],m=V(o),y=m?"y"===c?m.clientHeight||0:m.clientWidth||0:0,g=v/2-p/2,b=s[u],M=y-d[h]-s[f],A=y/2-d[h]/2+g,w=he(b,A,M),x=c +a.modifiersData[l]=((t={})[x]=w,t.centerOffset=w-A,t)}},effect:function(e){var t=e.state,a=e.options.element,l=void 0===a?"[data-popper-arrow]":a +null!=l&&("string"!=typeof l||(l=t.elements.popper.querySelector(l)))&&le(t.elements.popper,l)&&(t.elements.arrow=l)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]},{name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(e){var t=e.state,a=e.name,l=t.rects.reference,i=t.rects.popper,o=t.modifiersData.preventOverflow,n=ce(t,{elementContext:"reference"}),r=ce(t,{altBoundary:!0}),c=se(n,l),h=se(r,i,o),s=de(c),d=de(h) +t.modifiersData[a]={referenceClippingOffsets:c,popperEscapeOffsets:h,isReferenceHidden:s,hasPopperEscaped:d},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":s,"data-popper-escaped":d})}}]}),fe='',ve="tippy-box",pe="tippy-content",me="tippy-backdrop",ye="tippy-arrow",ge="tippy-svg-arrow",be={passive:!0,capture:!0},ze=function(){return document.body} +function Me(e,t,a){if(Array.isArray(e)){var l=e[t] +return null==l?Array.isArray(a)?a[t]:a:l}return e}function Ae(e,t){var a={}.toString.call(e) +return 0===a.indexOf("[object")&&a.indexOf(t+"]")>-1}function we(e,t){return"function"==typeof e?e.apply(void 0,t):e}function xe(e,t){return 0===t?e:function(l){clearTimeout(a),a=setTimeout((function(){e(l)}),t)} +var a}function He(e,t){var a=Object.assign({},e) +return t.forEach((function(e){delete a[e]})),a}function Ve(e){return[].concat(e)}function _e(e,t){-1===e.indexOf(t)&&e.push(t)}function Be(e){return e.split("-")[0]}function Le(e){return[].slice.call(e)}function Ce(e){return Object.keys(e).reduce((function(t,a){return void 0!==e[a]&&(t[a]=e[a]),t}),{})}function Ee(){return document.createElement("div")}function ke(e){return["Element","Fragment"].some((function(t){return Ae(e,t)}))}function De(e){return Ae(e,"MouseEvent")}function Se(e){return!(!e||!e._tippy||e._tippy.reference!==e)}function Fe(e,t){e.forEach((function(e){e&&(e.style.transitionDuration=t+"ms")}))}function Oe(e,t){e.forEach((function(e){e&&e.setAttribute("data-state",t)}))}function Te(e){var t,a=Ve(e)[0] +return null!=a&&null!=(t=a.ownerDocument)&&t.body?a.ownerDocument:document}function Pe(e,t,a){var l=t+"EventListener";["transitionend","webkitTransitionEnd"].forEach((function(t){e[l](t,a)}))}function Ne(e,t){for(var a=t;a;){var l +if(e.contains(a))return!0 +a=null==a.getRootNode||null==(l=a.getRootNode())?void 0:l.host}return!1}var Ue={isTouch:!1},Re=0 +function je(){Ue.isTouch||(Ue.isTouch=!0,window.performance&&document.addEventListener("mousemove",Ie))}function Ie(){var e=performance.now() +e-Re<20&&(Ue.isTouch=!1,document.removeEventListener("mousemove",Ie)),Re=e}function Ge(){var e=document.activeElement +if(Se(e)){var t=e._tippy +e.blur&&!t.state.isVisible&&e.blur()}}var $e=!("undefined"==typeof window||"undefined"==typeof document||!window.msCrypto),qe=Object.assign({appendTo:ze,aria:{content:"auto",expanded:"auto"},delay:0,duration:[300,250],getReferenceClientRect:null,hideOnClick:!0,ignoreAttributes:!1,interactive:!1,interactiveBorder:2,interactiveDebounce:0,moveTransition:"",offset:[0,10],onAfterUpdate:function(){},onBeforeUpdate:function(){},onCreate:function(){},onDestroy:function(){},onHidden:function(){},onHide:function(){},onMount:function(){},onShow:function(){},onShown:function(){},onTrigger:function(){},onUntrigger:function(){},onClickOutside:function(){},placement:"top",plugins:[],popperOptions:{},render:null,showOnCreate:!1,touch:!0,trigger:"mouseenter focus",triggerTarget:null},{animateFill:!1,followCursor:!1,inlinePositioning:!1,sticky:!1},{allowHTML:!1,animation:"fade",arrow:!0,content:"",inertia:!1,maxWidth:350,role:"tooltip",theme:"",zIndex:9999}),Ze=Object.keys(qe) +function Ye(e){var t=(e.plugins||[]).reduce((function(t,a){var l,i=a.name,o=a.defaultValue +return i&&(t[i]=void 0!==e[i]?e[i]:null!=(l=qe[i])?l:o),t}),{}) +return Object.assign({},e,t)}function Ke(e,t){var a=Object.assign({},t,{content:we(t.content,[e])},t.ignoreAttributes?{}:function(e,t){return(t?Object.keys(Ye(Object.assign({},qe,{plugins:t}))):Ze).reduce((function(t,a){var l=(e.getAttribute("data-tippy-"+a)||"").trim() +if(!l)return t +if("content"===a)t[a]=l +else try{t[a]=JSON.parse(l)}catch(e){t[a]=l}return t}),{})}(e,t.plugins)) +return a.aria=Object.assign({},qe.aria,a.aria),a.aria={expanded:"auto"===a.aria.expanded?t.interactive:a.aria.expanded,content:"auto"===a.aria.content?t.interactive?null:"describedby":a.aria.content},a}var We=function(){return"innerHTML"} +function Xe(e,t){e[We()]=t}function Je(e){var t=Ee() +return!0===e?t.className=ye:(t.className=ge,ke(e)?t.appendChild(e):Xe(t,e)),t}function Qe(e,t){ke(t.content)?(Xe(e,""),e.appendChild(t.content)):"function"!=typeof t.content&&(t.allowHTML?Xe(e,t.content):e.textContent=t.content)}function et(e){var t=e.firstElementChild,a=Le(t.children) +return{box:t,content:a.find((function(e){return e.classList.contains(pe)})),arrow:a.find((function(e){return e.classList.contains(ye)||e.classList.contains(ge)})),backdrop:a.find((function(e){return e.classList.contains(me)}))}}function tt(e){var t=Ee(),a=Ee() +a.className=ve,a.setAttribute("data-state","hidden"),a.setAttribute("tabindex","-1") +var l=Ee() +function i(a,l){var i=et(t),o=i.box,n=i.content,r=i.arrow +l.theme?o.setAttribute("data-theme",l.theme):o.removeAttribute("data-theme"),"string"==typeof l.animation?o.setAttribute("data-animation",l.animation):o.removeAttribute("data-animation"),l.inertia?o.setAttribute("data-inertia",""):o.removeAttribute("data-inertia"),o.style.maxWidth="number"==typeof l.maxWidth?l.maxWidth+"px":l.maxWidth,l.role?o.setAttribute("role",l.role):o.removeAttribute("role"),a.content===l.content&&a.allowHTML===l.allowHTML||Qe(n,e.props),l.arrow?r?a.arrow!==l.arrow&&(o.removeChild(r),o.appendChild(Je(l.arrow))):o.appendChild(Je(l.arrow)):r&&o.removeChild(r)}return l.className=pe,l.setAttribute("data-state","hidden"),Qe(l,e.props),t.appendChild(a),a.appendChild(l),i(e.props,e.props),{popper:t,onUpdate:i}}tt.$$tippy=!0 +var at=1,lt=[],it=[] +function ot(e,t){void 0===t&&(t={}) +var a=qe.plugins.concat(t.plugins||[]) +document.addEventListener("touchstart",je,be),window.addEventListener("blur",Ge) +var l,i=Object.assign({},t,{plugins:a}),o=(l=e,ke(l)?[l]:function(e){return Ae(e,"NodeList")}(l)?Le(l):Array.isArray(l)?l:Le(document.querySelectorAll(l))).reduce((function(e,t){var a=t&&function(e,t){var a,l,i,o,n,r,c,h,s=Ke(e,Object.assign({},qe,Ye(Ce(t)))),d=!1,u=!1,f=!1,v=!1,p=[],m=xe(Z,s.interactiveDebounce),y=at++,g=(h=s.plugins).filter((function(e,t){return h.indexOf(e)===t})),b={id:y,reference:e,popper:Ee(),popperInstance:null,props:s,state:{isEnabled:!0,isVisible:!1,isDestroyed:!1,isMounted:!1,isShown:!1},plugins:g,clearDelayTimeouts:function(){clearTimeout(a),clearTimeout(l),cancelAnimationFrame(i)},setProps:function(t){if(!b.state.isDestroyed){D("onBeforeUpdate",[b,t]),$() +var a=b.props,l=Ke(e,Object.assign({},a,Ce(t),{ignoreAttributes:!0})) +b.props=l,G(),a.interactiveDebounce!==l.interactiveDebounce&&(O(),m=xe(Z,l.interactiveDebounce)),a.triggerTarget&&!l.triggerTarget?Ve(a.triggerTarget).forEach((function(e){e.removeAttribute("aria-expanded")})):l.triggerTarget&&e.removeAttribute("aria-expanded"),F(),k(),A&&A(a,l),b.popperInstance&&(X(),Q().forEach((function(e){requestAnimationFrame(e._tippy.popperInstance.forceUpdate)}))),D("onAfterUpdate",[b,t])}},setContent:function(e){b.setProps({content:e})},show:function(){var e=b.state.isVisible,t=b.state.isDestroyed,a=!b.state.isEnabled,l=Ue.isTouch&&!b.props.touch,i=Me(b.props.duration,0,qe.duration) +if(!(e||t||a||l||B().hasAttribute("disabled")||(D("onShow",[b],!1),!1===b.props.onShow(b)))){if(b.state.isVisible=!0,_()&&(M.style.visibility="visible"),k(),U(),b.state.isMounted||(M.style.transition="none"),_()){var o=C() +Fe([o.box,o.content],0)}var n,c,h +r=function(){var e +if(b.state.isVisible&&!v){if(v=!0,M.offsetHeight,M.style.transition=b.props.moveTransition,_()&&b.props.animation){var t=C(),a=t.box,l=t.content +Fe([a,l],i),Oe([a,l],"visible")}S(),F(),_e(it,b),null==(e=b.popperInstance)||e.forceUpdate(),D("onMount",[b]),b.props.animation&&_()&&function(e,t){j(e,(function(){b.state.isShown=!0,D("onShown",[b])}))}(i)}},c=b.props.appendTo,h=B(),(n=b.props.interactive&&c===ze||"parent"===c?h.parentNode:we(c,[h])).contains(M)||n.appendChild(M),b.state.isMounted=!0,X()}},hide:function(){var e=!b.state.isVisible,t=b.state.isDestroyed,a=!b.state.isEnabled,l=Me(b.props.duration,1,qe.duration) +if(!(e||t||a)&&(D("onHide",[b],!1),!1!==b.props.onHide(b))){if(b.state.isVisible=!1,b.state.isShown=!1,v=!1,d=!1,_()&&(M.style.visibility="hidden"),O(),R(),k(!0),_()){var i=C(),o=i.box,n=i.content +b.props.animation&&(Fe([o,n],l),Oe([o,n],"hidden"))}S(),F(),b.props.animation?_()&&function(e,t){j(e,(function(){!b.state.isVisible&&M.parentNode&&M.parentNode.contains(M)&&t()}))}(l,b.unmount):b.unmount()}},hideWithInteractivity:function(e){L().addEventListener("mousemove",m),_e(lt,m),m(e)},enable:function(){b.state.isEnabled=!0},disable:function(){b.hide(),b.state.isEnabled=!1},unmount:function(){b.state.isVisible&&b.hide(),b.state.isMounted&&(J(),Q().forEach((function(e){e._tippy.unmount()})),M.parentNode&&M.parentNode.removeChild(M),it=it.filter((function(e){return e!==b})),b.state.isMounted=!1,D("onHidden",[b]))},destroy:function(){b.state.isDestroyed||(b.clearDelayTimeouts(),b.unmount(),$(),delete e._tippy,b.state.isDestroyed=!0,D("onDestroy",[b]))}} +if(!s.render)return b +var z=s.render(b),M=z.popper,A=z.onUpdate +M.setAttribute("data-tippy-root",""),M.id="tippy-"+b.id,b.popper=M,e._tippy=b,M._tippy=b +var w=g.map((function(e){return e.fn(b)})),x=e.hasAttribute("aria-expanded") +return G(),F(),k(),D("onCreate",[b]),s.showOnCreate&&ee(),M.addEventListener("mouseenter",(function(){b.props.interactive&&b.state.isVisible&&b.clearDelayTimeouts()})),M.addEventListener("mouseleave",(function(){b.props.interactive&&b.props.trigger.indexOf("mouseenter")>=0&&L().addEventListener("mousemove",m)})),b +function H(){var e=b.props.touch +return Array.isArray(e)?e:[e,0]}function V(){return"hold"===H()[0]}function _(){var e +return!(null==(e=b.props.render)||!e.$$tippy)}function B(){return c||e}function L(){var e=B().parentNode +return e?Te(e):document}function C(){return et(M)}function E(e){return b.state.isMounted&&!b.state.isVisible||Ue.isTouch||o&&"focus"===o.type?0:Me(b.props.delay,e?0:1,qe.delay)}function k(e){void 0===e&&(e=!1),M.style.pointerEvents=b.props.interactive&&!e?"":"none",M.style.zIndex=""+b.props.zIndex}function D(e,t,a){var l +void 0===a&&(a=!0),w.forEach((function(a){a[e]&&a[e].apply(a,t)})),a&&(l=b.props)[e].apply(l,t)}function S(){var t=b.props.aria +if(t.content){var a="aria-"+t.content,l=M.id +Ve(b.props.triggerTarget||e).forEach((function(e){var t=e.getAttribute(a) +if(b.state.isVisible)e.setAttribute(a,t?t+" "+l:l) +else{var i=t&&t.replace(l,"").trim() +i?e.setAttribute(a,i):e.removeAttribute(a)}}))}}function F(){!x&&b.props.aria.expanded&&Ve(b.props.triggerTarget||e).forEach((function(e){b.props.interactive?e.setAttribute("aria-expanded",b.state.isVisible&&e===B()?"true":"false"):e.removeAttribute("aria-expanded")}))}function O(){L().removeEventListener("mousemove",m),lt=lt.filter((function(e){return e!==m}))}function T(t){if(!Ue.isTouch||!f&&"mousedown"!==t.type){var a=t.composedPath&&t.composedPath()[0]||t.target +if(!b.props.interactive||!Ne(M,a)){if(Ve(b.props.triggerTarget||e).some((function(e){return Ne(e,a)}))){if(Ue.isTouch)return +if(b.state.isVisible&&b.props.trigger.indexOf("click")>=0)return}else D("onClickOutside",[b,t]) +!0===b.props.hideOnClick&&(b.clearDelayTimeouts(),b.hide(),u=!0,setTimeout((function(){u=!1})),b.state.isMounted||R())}}}function P(){f=!0}function N(){f=!1}function U(){var e=L() +e.addEventListener("mousedown",T,!0),e.addEventListener("touchend",T,be),e.addEventListener("touchstart",N,be),e.addEventListener("touchmove",P,be)}function R(){var e=L() +e.removeEventListener("mousedown",T,!0),e.removeEventListener("touchend",T,be),e.removeEventListener("touchstart",N,be),e.removeEventListener("touchmove",P,be)}function j(e,t){var a=C().box +function l(e){e.target===a&&(Pe(a,"remove",l),t())}if(0===e)return t() +Pe(a,"remove",n),Pe(a,"add",l),n=l}function I(t,a,l){void 0===l&&(l=!1),Ve(b.props.triggerTarget||e).forEach((function(e){e.addEventListener(t,a,l),p.push({node:e,eventType:t,handler:a,options:l})}))}function G(){var e +V()&&(I("touchstart",q,{passive:!0}),I("touchend",Y,{passive:!0})),(e=b.props.trigger,e.split(/\s+/).filter(Boolean)).forEach((function(e){if("manual"!==e)switch(I(e,q),e){case"mouseenter":I("mouseleave",Y) +break +case"focus":I($e?"focusout":"blur",K) +break +case"focusin":I("focusout",K)}}))}function $(){p.forEach((function(e){var t=e.node,a=e.eventType,l=e.handler,i=e.options +t.removeEventListener(a,l,i)})),p=[]}function q(e){var t,a=!1 +if(b.state.isEnabled&&!W(e)&&!u){var l="focus"===(null==(t=o)?void 0:t.type) +o=e,c=e.currentTarget,F(),!b.state.isVisible&&De(e)&<.forEach((function(t){return t(e)})),"click"===e.type&&(b.props.trigger.indexOf("mouseenter")<0||d)&&!1!==b.props.hideOnClick&&b.state.isVisible?a=!0:ee(e),"click"===e.type&&(d=!a),a&&!l&&te(e)}}function Z(e){var t=e.target,a=B().contains(t)||M.contains(t) +if("mousemove"!==e.type||!a){var l=Q().concat(M).map((function(e){var t,a=null==(t=e._tippy.popperInstance)?void 0:t.state +return a?{popperRect:e.getBoundingClientRect(),popperState:a,props:s}:null})).filter(Boolean);(function(e,t){var a=t.clientX,l=t.clientY +return e.every((function(e){var t=e.popperRect,i=e.popperState,o=e.props.interactiveBorder,n=Be(i.placement),r=i.modifiersData.offset +if(!r)return!0 +var c="bottom"===n?r.top.y:0,h="top"===n?r.bottom.y:0,s="right"===n?r.left.x:0,d="left"===n?r.right.x:0,u=t.top-l+c>o,f=l-t.bottom-h>o,v=t.left-a+s>o,p=a-t.right-d>o +return u||f||v||p}))})(l,e)&&(O(),te(e))}}function Y(e){W(e)||b.props.trigger.indexOf("click")>=0&&d||(b.props.interactive?b.hideWithInteractivity(e):te(e))}function K(e){b.props.trigger.indexOf("focusin")<0&&e.target!==B()||b.props.interactive&&e.relatedTarget&&M.contains(e.relatedTarget)||te(e)}function W(e){return!!Ue.isTouch&&V()!==e.type.indexOf("touch")>=0}function X(){J() +var t=b.props,a=t.popperOptions,l=t.placement,i=t.offset,o=t.getReferenceClientRect,n=t.moveTransition,c=_()?et(M).arrow:null,h=o?{getBoundingClientRect:o,contextElement:o.contextElement||B()}:e,s=[{name:"offset",options:{offset:i}},{name:"preventOverflow",options:{padding:{top:2,bottom:2,left:5,right:5}}},{name:"flip",options:{padding:5}},{name:"computeStyles",options:{adaptive:!n}},{name:"$$tippy",enabled:!0,phase:"beforeWrite",requires:["computeStyles"],fn:function(e){var t=e.state +if(_()){var a=C().box;["placement","reference-hidden","escaped"].forEach((function(e){"placement"===e?a.setAttribute("data-placement",t.placement):t.attributes.popper["data-popper-"+e]?a.setAttribute("data-"+e,""):a.removeAttribute("data-"+e)})),t.attributes.popper={}}}}] +_()&&c&&s.push({name:"arrow",options:{element:c,padding:3}}),s.push.apply(s,(null==a?void 0:a.modifiers)||[]),b.popperInstance=ue(h,M,Object.assign({},a,{placement:l,onFirstUpdate:r,modifiers:s}))}function J(){b.popperInstance&&(b.popperInstance.destroy(),b.popperInstance=null)}function Q(){return Le(M.querySelectorAll("[data-tippy-root]"))}function ee(e){b.clearDelayTimeouts(),e&&D("onTrigger",[b,e]),U() +var t=E(!0),l=H(),i=l[0],o=l[1] +Ue.isTouch&&"hold"===i&&o&&(t=o),t?a=setTimeout((function(){b.show()}),t):b.show()}function te(e){if(b.clearDelayTimeouts(),D("onUntrigger",[b,e]),b.state.isVisible){if(!(b.props.trigger.indexOf("mouseenter")>=0&&b.props.trigger.indexOf("click")>=0&&["mouseleave","mousemove"].indexOf(e.type)>=0&&d)){var t=E(!1) +t?l=setTimeout((function(){b.state.isVisible&&b.hide()}),t):i=requestAnimationFrame((function(){b.hide()}))}}else R()}}(t,i) +return a&&e.push(a),e}),[]) +return ke(e)?o[0]:o}ot.defaultProps=qe,ot.setDefaultProps=function(e){Object.keys(e).forEach((function(t){qe[t]=e[t]}))},ot.currentInput=Ue +var nt=function(e){var t=void 0===e?{}:e,a=t.exclude,l=t.duration +it.forEach((function(e){var t=!1 +if(a&&(t=Se(a)?e.reference===a:e.popper===a.popper),!t){var i=e.props.duration +e.setProps({duration:l}),e.hide(),e.state.isDestroyed||e.setProps({duration:i})}}))},rt=Object.assign({},J,{effect:function(e){var t=e.state,a={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}} +Object.assign(t.elements.popper.style,a.popper),t.styles=a,t.elements.arrow&&Object.assign(t.elements.arrow.style,a.arrow)}}),ct=function(e,t){var a +void 0===t&&(t={}) +var l,i=e,o=[],n=[],r=t.overrides,c=[],h=!1 +function s(){n=i.map((function(e){return Ve(e.props.triggerTarget||e.reference)})).reduce((function(e,t){return e.concat(t)}),[])}function d(){o=i.map((function(e){return e.reference}))}function u(e){i.forEach((function(t){e?t.enable():t.disable()}))}function f(e){return i.map((function(t){var a=t.setProps +return t.setProps=function(i){a(i),t.reference===l&&e.setProps(i)},function(){t.setProps=a}}))}function v(e,t){var a=n.indexOf(t) +if(t!==l){l=t +var c=(r||[]).concat("content").reduce((function(e,t){return e[t]=i[a].props[t],e}),{}) +e.setProps(Object.assign({},c,{getReferenceClientRect:"function"==typeof c.getReferenceClientRect?c.getReferenceClientRect:function(){var e +return null==(e=o[a])?void 0:e.getBoundingClientRect()}}))}}u(!1),d(),s() +var p={fn:function(){return{onDestroy:function(){u(!0)},onHidden:function(){l=null},onClickOutside:function(e){e.props.showOnCreate&&!h&&(h=!0,l=null)},onShow:function(e){e.props.showOnCreate&&!h&&(h=!0,v(e,o[0]))},onTrigger:function(e,t){v(e,t.currentTarget)}}}},m=ot(Ee(),Object.assign({},He(t,["overrides"]),{plugins:[p].concat(t.plugins||[]),triggerTarget:n,popperOptions:Object.assign({},t.popperOptions,{modifiers:[].concat((null==(a=t.popperOptions)?void 0:a.modifiers)||[],[rt])})})),y=m.show +m.show=function(e){if(y(),!l&&null==e)return v(m,o[0]) +if(!l||null!=e){if("number"==typeof e)return o[e]&&v(m,o[e]) +if(i.indexOf(e)>=0){var t=e.reference +return v(m,t)}return o.indexOf(e)>=0?v(m,e):void 0}},m.showNext=function(){var e=o[0] +if(!l)return m.show(0) +var t=o.indexOf(l) +m.show(o[t+1]||e)},m.showPrevious=function(){var e=o[o.length-1] +if(!l)return m.show(e) +var t=o.indexOf(l),a=o[t-1]||e +m.show(a)} +var g=m.setProps +return m.setProps=function(e){r=e.overrides||r,g(e)},m.setInstances=function(e){u(!0),c.forEach((function(e){return e()})),i=e,u(!1),d(),s(),c=f(m),m.setProps({triggerTarget:n})},c=f(m),m},ht={mouseover:"mouseenter",focusin:"focus",click:"click"} +function st(e,t){var a=[],l=[],i=!1,o=t.target,n=He(t,["target"]),r=Object.assign({},n,{trigger:"manual",touch:!1}),c=Object.assign({touch:qe.touch},n,{showOnCreate:!0}),h=ot(e,r) +function s(e){if(e.target&&!i){var a=e.target.closest(o) +if(a){var n=a.getAttribute("data-tippy-trigger")||t.trigger||qe.trigger +if(!a._tippy&&!("touchstart"===e.type&&"boolean"==typeof c.touch||"touchstart"!==e.type&&n.indexOf(ht[e.type])<0)){var r=ot(a,c) +r&&(l=l.concat(r))}}}}function d(e,t,l,i){void 0===i&&(i=!1),e.addEventListener(t,l,i),a.push({node:e,eventType:t,handler:l,options:i})}return Ve(h).forEach((function(e){var t=e.destroy,o=e.enable,n=e.disable +e.destroy=function(e){void 0===e&&(e=!0),e&&l.forEach((function(e){e.destroy()})),l=[],a.forEach((function(e){var t=e.node,a=e.eventType,l=e.handler,i=e.options +t.removeEventListener(a,l,i)})),a=[],t()},e.enable=function(){o(),l.forEach((function(e){return e.enable()})),i=!1},e.disable=function(){n(),l.forEach((function(e){return e.disable()})),i=!0},function(e){var t=e.reference +d(t,"touchstart",s,be),d(t,"mouseover",s),d(t,"focusin",s),d(t,"click",s)}(e)})),h}var dt={name:"animateFill",defaultValue:!1,fn:function(e){var t +if(null==(t=e.props.render)||!t.$$tippy)return{} +var a=et(e.popper),l=a.box,i=a.content,o=e.props.animateFill?function(){var e=Ee() +return e.className=me,Oe([e],"hidden"),e}():null +return{onCreate:function(){o&&(l.insertBefore(o,l.firstElementChild),l.setAttribute("data-animatefill",""),l.style.overflow="hidden",e.setProps({arrow:!1,animation:"shift-away"}))},onMount:function(){if(o){var e=l.style.transitionDuration,t=Number(e.replace("ms","")) +i.style.transitionDelay=Math.round(t/10)+"ms",o.style.transitionDuration=e,Oe([o],"visible")}},onShow:function(){o&&(o.style.transitionDuration="0ms")},onHide:function(){o&&Oe([o],"hidden")}}}},ut={clientX:0,clientY:0},ft=[] +function vt(e){var t=e.clientX,a=e.clientY +ut={clientX:t,clientY:a}}var pt={name:"followCursor",defaultValue:!1,fn:function(e){var t=e.reference,a=Te(e.props.triggerTarget||t),l=!1,i=!1,o=!0,n=e.props +function r(){return"initial"===e.props.followCursor&&e.state.isVisible}function c(){a.addEventListener("mousemove",d)}function h(){a.removeEventListener("mousemove",d)}function s(){l=!0,e.setProps({getReferenceClientRect:null}),l=!1}function d(a){var l=!a.target||t.contains(a.target),i=e.props.followCursor,o=a.clientX,n=a.clientY,r=t.getBoundingClientRect(),c=o-r.left,h=n-r.top +!l&&e.props.interactive||e.setProps({getReferenceClientRect:function(){var e=t.getBoundingClientRect(),a=o,l=n +"initial"===i&&(a=e.left+c,l=e.top+h) +var r="horizontal"===i?e.top:l,s="vertical"===i?e.right:a,d="horizontal"===i?e.bottom:l,u="vertical"===i?e.left:a +return{width:s-u,height:d-r,top:r,right:s,bottom:d,left:u}}})}function u(){e.props.followCursor&&(ft.push({instance:e,doc:a}),function(e){e.addEventListener("mousemove",vt)}(a))}function f(){0===(ft=ft.filter((function(t){return t.instance!==e}))).filter((function(e){return e.doc===a})).length&&function(e){e.removeEventListener("mousemove",vt)}(a)}return{onCreate:u,onDestroy:f,onBeforeUpdate:function(){n=e.props},onAfterUpdate:function(t,a){var o=a.followCursor +l||void 0!==o&&n.followCursor!==o&&(f(),o?(u(),!e.state.isMounted||i||r()||c()):(h(),s()))},onMount:function(){e.props.followCursor&&!i&&(o&&(d(ut),o=!1),r()||c())},onTrigger:function(e,t){De(t)&&(ut={clientX:t.clientX,clientY:t.clientY}),i="focus"===t.type},onHidden:function(){e.props.followCursor&&(s(),h(),o=!0)}}}},mt={name:"inlinePositioning",defaultValue:!1,fn:function(e){var t,a=e.reference,l=-1,i=!1,o=[],n={name:"tippyInlinePositioning",enabled:!0,phase:"afterWrite",fn:function(i){var n=i.state +e.props.inlinePositioning&&(-1!==o.indexOf(n.placement)&&(o=[]),t!==n.placement&&-1===o.indexOf(n.placement)&&(o.push(n.placement),e.setProps({getReferenceClientRect:function(){return function(e){return function(e,t,a,l){if(a.length<2||null===e)return t +if(2===a.length&&l>=0&&a[0].left>a[1].right)return a[l]||t +switch(e){case"top":case"bottom":var i=a[0],o=a[a.length-1],n="top"===e,r=i.top,c=o.bottom,h=n?i.left:o.left,s=n?i.right:o.right +return{top:r,bottom:c,left:h,right:s,width:s-h,height:c-r} +case"left":case"right":var d=Math.min.apply(Math,a.map((function(e){return e.left}))),u=Math.max.apply(Math,a.map((function(e){return e.right}))),f=a.filter((function(t){return"left"===e?t.left===d:t.right===u})),v=f[0].top,p=f[f.length-1].bottom +return{top:v,bottom:p,left:d,right:u,width:u-d,height:p-v} +default:return t}}(Be(e),a.getBoundingClientRect(),Le(a.getClientRects()),l)}(n.placement)}})),t=n.placement)}} +function r(){var t +i||(t=function(e,t){var a +return{popperOptions:Object.assign({},e.popperOptions,{modifiers:[].concat(((null==(a=e.popperOptions)?void 0:a.modifiers)||[]).filter((function(e){return e.name!==t.name})),[t])})}}(e.props,n),i=!0,e.setProps(t),i=!1)}return{onCreate:r,onAfterUpdate:r,onTrigger:function(t,a){if(De(a)){var i=Le(e.reference.getClientRects()),o=i.find((function(e){return e.left-2<=a.clientX&&e.right+2>=a.clientX&&e.top-2<=a.clientY&&e.bottom+2>=a.clientY})),n=i.indexOf(o) +l=n>-1?n:l}},onHidden:function(){l=-1}}}},yt={name:"sticky",defaultValue:!1,fn:function(e){var t=e.reference,a=e.popper +function l(t){return!0===e.props.sticky||e.props.sticky===t}var i=null,o=null +function n(){var r=l("reference")?(e.popperInstance?e.popperInstance.state.elements.reference:t).getBoundingClientRect():null,c=l("popper")?a.getBoundingClientRect():null;(r&>(i,r)||c&>(o,c))&&e.popperInstance&&e.popperInstance.update(),i=r,o=c,e.state.isMounted&&requestAnimationFrame(n)}return{onMount:function(){e.props.sticky&&n()}}}} +function gt(e,t){return!e||!t||e.top!==t.top||e.right!==t.right||e.bottom!==t.bottom||e.left!==t.left}ot.setDefaultProps({render:tt}) +const bt=ot},2985:(e,t,a)=>{"use strict" +a.d(t,{ZT:()=>i,ev:()=>n,pi:()=>o}) +var l=function(e,t){return l=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a])},l(e,t)} +function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null") +function a(){this.constructor=e}l(e,t),e.prototype=null===t?Object.create(t):(a.prototype=t.prototype,new a)}var o=function(){return o=Object.assign||function(e){for(var t,a=1,l=arguments.length;a{"use strict" +function l(e){return null!==e&&"object"==typeof e&&!(e instanceof Date||e instanceof RegExp)&&!Array.isArray(e)}a.r(t),a.d(t,{BufferedChangeset:()=>Ee,CHANGESET:()=>D,Change:()=>o,Changeset:()=>Se,Err:()=>c,ValidatedChangeset:()=>De,buildOldValues:()=>W,changeset:()=>ke,getChangeValue:()=>r,getDeep:()=>y,getKeyValues:()=>d,isChange:()=>n,isChangeset:()=>S,isObject:()=>l,isPromise:()=>f,keyInObject:()=>O,lookupValidator:()=>g,mergeDeep:()=>ie,mergeNested:()=>Y,normalizeObject:()=>H,objectWithout:()=>he,propertyIsUnsafe:()=>te,pureAssign:()=>_,setDeep:()=>q,take:()=>se}) +var i=Symbol("__value__"),o=function(e){this[i]=e},n=function(e){return l(e)&&i in e} +function r(e){if(n(e))return e[i]}var c=function(e,t){this.value=e,this.validation=t},h=function(e,t){var a="function"==typeof Symbol&&e[Symbol.iterator] +if(!a)return e +var l,i,o=a.call(e),n=[] +try{for(;(void 0===t||t-- >0)&&!(l=o.next()).done;)n.push(l.value)}catch(e){i={error:e}}finally{try{l&&!l.done&&(a=o.return)&&a.call(o)}finally{if(i)throw i.error}}return n},s=function(){for(var e=[],t=0;t0&&i[i.length-1])||6!==o[0]&&2!==o[0])){n=0 +continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0)&&!(l=o.next()).done;)n.push(l.value)}catch(e){i={error:e}}finally{try{l&&!l.done&&(a=o.return)&&a.call(o)}finally{if(i)throw i.error}}return n},z=function(){function e(){this.listeners=[]}return e.prototype.addListener=function(e){var t=this +return this.listeners.push(e),function(){return t.removeListener(e)}},e.prototype.removeListener=function(e){for(var t=0;t=e.length&&(e=void 0),{value:e&&e[l++],done:!e}}} +throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},x=function(){return x=Object.assign||function(e){for(var t,a=1,l=arguments.length;a=e.length&&(e=void 0),{value:e&&e[l++],done:!e}}} +throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},L=function(e,t){var a="function"==typeof Symbol&&e[Symbol.iterator] +if(!a)return e +var l,i,o=a.call(e),n=[] +try{for(;(void 0===t||t-- >0)&&!(l=o.next()).done;)n.push(l.value)}catch(e){i={error:e}}finally{try{l&&!l.done&&(a=o.return)&&a.call(o)}finally{if(i)throw i.error}}return n},C=function(){for(var e=[],t=0;t0)&&!(l=o.next()).done;)n.push(l.value)}catch(e){i={error:e}}finally{try{l&&!l.done&&(a=o.return)&&a.call(o)}finally{if(i)throw i.error}}return n} +function O(e,t){var a=F(t.split(".")),l=a[0],i=a.slice(1) +if(!l||!(l in e))return!1 +if(!i.length)return l in e +var o=e[l] +return null!==o&&"object"==typeof o&&O(e[l],i.join("."))}var T=function(e){var t="function"==typeof Symbol&&Symbol.iterator,a=t&&e[t],l=0 +if(a)return a.call(e) +if(e&&"number"==typeof e.length)return{next:function(){return e&&l>=e.length&&(e=void 0),{value:e&&e[l++],done:!e}}} +throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},P=function(e,t){var a="function"==typeof Symbol&&e[Symbol.iterator] +if(!a)return e +var l,i,o=a.call(e),n=[] +try{for(;(void 0===t||t-- >0)&&!(l=o.next()).done;)n.push(l.value)}catch(e){i={error:e}}finally{try{l&&!l.done&&(a=o.return)&&a.call(o)}finally{if(i)throw i.error}}return n} +function N(e){return!!e&&Object.keys(e).every((function(e){return Number.isInteger(parseInt(e,10))}))}function U(e){return e.reduce((function(e,t,a){return e[a]=t,e}),{})}function R(e){var t,a,l=[] +try{for(var i=T(Object.entries(e)),o=i.next();!o.done;o=i.next()){var n=P(o.value,2),r=n[0],c=n[1] +l[parseInt(r,10)]=c}}catch(e){t={error:e}}finally{try{o&&!o.done&&(a=i.return)&&a.call(i)}finally{if(t)throw t.error}}return l}var j=function(){return j=Object.assign||function(e){for(var t,a=1,l=arguments.length;a0)&&!(l=o.next()).done;)n.push(l.value)}catch(e){i={error:e}}finally{try{l&&!l.done&&(a=o.return)&&a.call(o)}finally{if(i)throw i.error}}return n} +function G(e,t){var a=I(t.slice(-1),1)[0],l=Object.keys(e).filter((function(e){return e!==a})).reduce((function(t,a){return t[a]=e[a],t}),Object.create(null)) +return j({},l)}function $(e){return"__proto__"!==e&&"constructor"!==e&&"prototype"!==e}function q(e,t,a,i){void 0===i&&(i={safeSet:void 0,safeGet:void 0}) +var c=function(e){return e.split(".")}(t).filter($),h=e +if(i.safeSet=i.safeSet||function(e,t,a){return e[t]=a},i.safeGet=i.safeGet||function(e,t){return e?e[t]:e},1===c.length)return i.safeSet(e,t,a),e +for(var s=0;s=e.length&&(e=void 0),{value:e&&e[l++],done:!e}}} +throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")} +function W(e,t,a){var l,i,o=Object.create(null) +try{for(var n=K(t),r=n.next();!r.done;r=n.next()){var c=r.value +o[c.key]=a(e,c.key)}}catch(e){l={error:e}}finally{try{r&&!r.done&&(i=n.return)&&i.call(n)}finally{if(l)throw l.error}}return o}var X=function(e,t){var a="function"==typeof Symbol&&e[Symbol.iterator] +if(!a)return e +var l,i,o=a.call(e),n=[] +try{for(;(void 0===t||t-- >0)&&!(l=o.next()).done;)n.push(l.value)}catch(e){i={error:e}}finally{try{l&&!l.done&&(a=o.return)&&a.call(o)}finally{if(i)throw i.error}}return n},J=function(){for(var e=[],t=0;t0)for(l in i){var o=i[l] +a.safeSet(e,l,o)}}}else{if(!ee(e,l)||!function(e){return!!e&&"object"==typeof e}(h=t[l])||function(e){var t=Object.prototype.toString.call(e) +return"[object RegExp]"===t||"[object Date]"===t}(h)||n(t[l])){var c=t[l] +return c&&n(c)?a.safeSet(e,l,r(c)):a.safeSet(e,l,H(c))}a.safeSet(e,l,ie(a.safeGet(e,l),a.safeGet(t,l),a))}var h})),e}function ie(e,t,a){void 0===a&&(a={safeGet:void 0,safeSet:void 0,propertyIsUnsafe:void 0,getKeys:void 0}),a.getKeys=a.getKeys||Q,a.propertyIsUnsafe=a.propertyIsUnsafe||te,a.safeGet=a.safeGet||function(e,t){return e[t]},a.safeSet=a.safeSet||function(e,t,a){return e[t]=a} +var l=Array.isArray(t),i=Array.isArray(e) +if(l===i)return l||null==e?t:le(e,t,a) +var o=N(t) +return i&&o?R(le(U(e),t,a)):t}var oe=function(){return oe=Object.assign||function(e){for(var t,a=1,l=arguments.length;a0&&i[i.length-1])||6!==o[0]&&2!==o[0])){n=0 +continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0)&&!(l=o.next()).done;)n.push(l.value)}catch(e){i={error:e}}finally{try{l&&!l.done&&(a=o.return)&&a.call(o)}finally{if(i)throw i.error}}return n},pe=function(){for(var e=[],t=0;t0)||l.find((function(t){return e.match(t)}))){var i=this[ye],o=this.safeGet(i,e) +if(a.skipValidate)return this._setProperty({key:e,value:t,oldValue:o}),void this._handleValidation(!0,{key:e,value:t}) +this._setProperty({key:e,value:t,oldValue:o}),this._validateKey(e,t)}},Object.defineProperty(e.prototype,Symbol.toStringTag,{get:function(){return"changeset:"+_(this[ye],{}).toString()},enumerable:!1,configurable:!0}),e.prototype.toString=function(){return"changeset:"+_(this[ye],{}).toString()},e.prototype.prepare=function(e){var t=e(this._bareChanges) +if(Le("Callback to `changeset.prepare` must return an object",this.isObject(t)),this.isObject(t)){var a=me(t).reduce((function(e,a){return e[a]=new o(t[a]),e}),{}) +this[be]=a}return this},e.prototype.execute=function(){var e +if(this.isValid&&this.isDirty){var t=this[ye],a=this[be] +e=W(t,this.changes,this.getDeep),this[ye]=this.mergeDeep(t,a)}return this.trigger("execute"),this[be]={},this[ge]=e,this},e.prototype.unexecute=function(){return this[ge]&&(this[ye]=this.mergeDeep(this[ye],this[ge],{safeGet:this.safeGet,safeSet:this.safeSet})),this},e.prototype.save=function(e){return ue(this,void 0,void 0,(function(){var t,a,l,i +return fe(this,(function(o){switch(o.label){case 0:t=this[ye],a=Promise.resolve(this),this.execute(),"function"==typeof t.save?a=t.save(e):"function"==typeof this.safeGet(t,"save")&&(l=this.maybeUnwrapProxy(t).save())&&(a=l),o.label=1 +case 1:return o.trys.push([1,3,,4]),[4,a] +case 2:return i=o.sent(),this.rollback(),[2,i] +case 3:throw o.sent() +case 4:return[2]}}))}))},e.prototype.merge=function(e){var t=this[ye] +if(Le("Cannot merge with a non-changeset",S(e)),Le("Cannot merge with a changeset of different content",e[ye]===t),this.isPristine&&e.isPristine)return this +var a=this[be],l=e[be],i=this[ze],o=e[ze],n=new De(t,this[Ae]),r=he(me(l),i),c=he(me(o),a),h=Y(r,o),s=Y(c,l) +return n[ze]=h,n[be]=s,n._notifyVirtualProperties(),n},e.prototype.rollback=function(){var e=this._rollbackKeys() +return this[be]={},this[ze]={},this[Me]={},this._notifyVirtualProperties(e),this.trigger("afterRollback"),this},e.prototype.rollbackInvalid=function(e){var t=this,a=me(this[ze]) +return e?(this._notifyVirtualProperties([e]),this[ze]=this._deleteKey(ze,e),this[Me]=this[ze],a.indexOf(e)>-1&&(this[be]=this._deleteKey(be,e))):(this._notifyVirtualProperties(),this[ze]={},this[Me]=this[ze],a.forEach((function(e){t[be]=t._deleteKey(be,e)}))),this},e.prototype.rollbackProperty=function(e){return this[be]=this._deleteKey(be,e),this[ze]=this._deleteKey(ze,e),this[Me]=this[ze],this},e.prototype.validate=function(){for(var e=[],t=0;t0?e:me(k(this.validationMap)),t=e.map((function(e){var t=a[e],l=t instanceof ce?t.unwrap():t +return a._validateKey(e,l)})),[2,Promise.all(t)]):[2,Promise.resolve(null)]}))}))},e.prototype.addError=function(e,t){var a,l=this +if(function(e){return l.isObject(e)&&!Array.isArray(e)}(t))Le("Error must have value.",t.hasOwnProperty("value")||void 0!==t.value),Le("Error must have validation.",t.hasOwnProperty("validation")),a=new c(t.value,t.validation) +else{var i=this[e] +a=new c(i,t)}var o=this[ze] +return this[ze]=this.setDeep(o,e,a,{safeSet:this.safeSet}),this[Me]=this[ze],t},e.prototype.pushErrors=function(e){for(var t=[],a=1;a0},e.prototype._validateKey=function(e,t){var a=this,l=this[ye],i=this.getDeep(l,e),o=this._validate(e,t,i) +if(this.trigger("beforeValidation",e),f(o)){this._setIsValidating(e,o) +var n=this[xe],r=Object.entries(n) +return Promise.all(r).then((function(){return o.then((function(l){return delete n[e],a._handleValidation(l,{key:e,value:t})})).then((function(t){return a.trigger(He,e),t}))}))}var c=this._handleValidation(o,{key:e,value:t}) +return this.trigger(He,e),c},e.prototype._handleValidation=function(e,t){var a=t.key,l=t.value,i=!0===e||Array.isArray(e)&&1===e.length&&!0===e[0] +return this[ze]=this._deleteKey(Me,a),i?l:this.addError(a,{value:l,validation:e})},e.prototype._validate=function(e,t,a){var l=this[Ae],i=this[ye] +if("function"==typeof l){var o=l({key:e,newValue:t,oldValue:a,changes:this.change,content:i}) +return void 0===o||o}return!0},e.prototype._setProperty=function(e){var t,a,l=e.key,i=e.value,n=e.oldValue,r=this[be] +if(a=n,((t=i)instanceof Date&&a instanceof Date?t.getTime()===a.getTime():t===a)&&void 0!==n)O(r,l)&&(this[be]=this._deleteKey(be,l)) +else{var c=this.setDeep(r,l,new o(i),{safeSet:this.safeSet}) +this[be]=c}},e.prototype._setIsValidating=function(e,t){var a=this[xe] +this.setDeep(a,e,t)},e.prototype._notifyVirtualProperties=function(e){return e||(e=this._rollbackKeys()),e},e.prototype._rollbackKeys=function(){var e=this[be],t=this[ze] +return pe(new Set(pe(me(e),me(t))))},e.prototype._deleteKey=function(e,t){void 0===t&&(t="") +var a=this[e],l=t.split(".") +if(1===l.length&&a.hasOwnProperty(t))delete a[t] +else if(a[l[0]])for(var i=ve(l),o=i[0],r=i.slice(1),c=a,h=a[o],s=o;this.isObject(h)&&s;){var d=h;(n(d)||void 0!==d.value||d.validation)&&delete c[s],c=h,(s=r.shift())&&(h=h[s])}return a},e.prototype.get=function(e){var t=ve(e.split(".")),a=t[0],i=t.slice(1),o=this[be],c=this[ye] +if(Object.prototype.hasOwnProperty.call(o,a)){var h=this.getDeep(o,e) +if(!this.isObject(h)&&void 0!==h)return h}if(Object.prototype.hasOwnProperty.call(o,a)&&V(o)){var s=o[a],d=H(s) +if(this.isObject(d)){var u=this.maybeUnwrapProxy(this.getDeep(d,i.join("."))) +if(void 0===u&&function(e,t,a){var l,i +if(n(e))return!1 +var o=t.split("."),r=e +try{for(var c=w(o),h=c.next();!h.done;h=c.next()){var s=h.value +if(!r)return!1 +if(o[o.length-1]!==s&&n(a(r,s)))return!0 +r=a(r,s)}}catch(e){l={error:e}}finally{try{h&&!h.done&&(i=c.return)&&i.call(c)}finally{if(l)throw l.error}}return!1}(o,e,this.safeGet)&&!function(e,t,a){var l,i,o=t.split("."),c=e +try{for(var h=w(o),s=h.next();!s.done;s=h.next()){var d=s.value +if(!c||!Object.prototype.hasOwnProperty.call(c,d))return!1 +c=a(c,d),n(c)&&(c=r(c))}}catch(e){l={error:e}}finally{try{s&&!s.done&&(i=h.return)&&i.call(h)}finally{if(l)throw l.error}}return!0}(o,e,this.safeGet)&&this.getDeep(c,e))return +if(this.isObject(u)){if(n(u))return r(u) +var f=this.safeGet(c,a)||{},v=this.getDeep(f,i.join(".")),p=function(e,t){var a=e +if(-1===t.indexOf("."))return a[t] +for(var l="string"==typeof t?t.split("."):t,i=0;i{var l=a(4977),i=a(5689) +e.exports=function e(t){if(!(this instanceof e))return new e(t) +var a=(t||"").replace(/^\//,""),o=i() +return n._trie=o,n.on=function(e,t){if(l.equal(typeof e,"string"),l.equal(typeof t,"function"),e=e||"/",t._wayfarer&&t._trie)o.mount(e,t._trie.trie) +else{var a=o.create(e) +a.cb=t,a.route=e}return n},n.emit=n,n.match=r,n._wayfarer=!0,n +function n(e){var t=r(e),a=new Array(arguments.length) +a[0]=t.params +for(var l=1;l{var l=a(4977) +function i(){if(!(this instanceof i))return new i +this.trie={nodes:{}}}function o(e,t){return Object.prototype.hasOwnProperty.call(e,t)}e.exports=i,i.prototype.create=function(e){l.equal(typeof e,"string","route should be a string") +var t=e.replace(/^\//,"").split("/") +return function e(a,l){var i=o(t,a)&&t[a] +if(!1===i)return l +var n=null +return/^:|^\*/.test(i)?(o(l.nodes,"$$")?n=l.nodes.$$:(n={nodes:{}},l.nodes.$$=n),"*"===i[0]&&(l.wildcard=!0),l.name=i.replace(/^:|^\*/,"")):o(l.nodes,i)?n=l.nodes[i]:(n={nodes:{}},l.nodes[i]=n),e(a+1,n)}(0,this.trie)},i.prototype.match=function(e){l.equal(typeof e,"string","route should be a string") +var t=e.replace(/^\//,"").split("/"),a={},i=function e(l,i){if(void 0!==i){var n=t[l] +if(void 0===n)return i +if(o(i.nodes,n))return e(l+1,i.nodes[n]) +if(i.name){try{a[i.name]=decodeURIComponent(n)}catch(t){return e(l,void 0)}return e(l+1,i.nodes.$$)}if(i.wildcard){try{a.wildcard=decodeURIComponent(t.slice(l).join("/"))}catch(t){return e(l,void 0)}return i.nodes.$$}return e(l+1)}}(0,this.trie) +if(i)return(i=Object.assign({},i)).params=a,i},i.prototype.mount=function(e,t){l.equal(typeof e,"string","route should be a string"),l.equal(typeof t,"object","trie should be a object") +var a=e.replace(/^\//,"").split("/"),i=null,o=null +if(1===a.length)o=a[0],i=this.create(o) +else{var n=a.join("/") +o=a[0],i=this.create(n)}Object.assign(i.nodes,t.nodes),t.name&&(i.name=t.name),i.nodes[""]&&(Object.keys(i.nodes[""]).forEach((function(e){"nodes"!==e&&(i[e]=i.nodes[""][e])})),Object.assign(i.nodes,i.nodes[""].nodes),delete i.nodes[""].nodes)}},2959:(e,t,a)=>{"use strict" +a.r(t)},8531:(e,t,a)=>{"use strict" +a.r(t),a.d(t,{CSSResult:()=>r,ReactiveElement:()=>z,adoptStyles:()=>s,css:()=>h,defaultConverter:()=>y,getCompatibleStyle:()=>d,notEqual:()=>g,supportsAdoptingStyleSheets:()=>i,unsafeCSS:()=>c}) +const l=window,i=l.ShadowRoot&&(void 0===l.ShadyCSS||l.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,o=Symbol(),n=new WeakMap +class r{constructor(e,t,a){if(this._$cssResult$=!0,a!==o)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.") +this.cssText=e,this.t=t}get styleSheet(){let e=this.o +const t=this.t +if(i&&void 0===e){const a=void 0!==t&&1===t.length +a&&(e=n.get(t)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),a&&n.set(t,e))}return e}toString(){return this.cssText}}const c=e=>new r("string"==typeof e?e:e+"",void 0,o),h=function(e){for(var t=arguments.length,a=new Array(t>1?t-1:0),l=1;lt+(e=>{if(!0===e._$cssResult$)return e.cssText +if("number"==typeof e)return e +throw Error("Value passed to 'css' function must be a 'css' function result: "+e+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(a)+e[l+1]),e[0]) +return new r(i,e,o)},s=(e,t)=>{i?e.adoptedStyleSheets=t.map((e=>e instanceof CSSStyleSheet?e:e.styleSheet)):t.forEach((t=>{const a=document.createElement("style"),i=l.litNonce +void 0!==i&&a.setAttribute("nonce",i),a.textContent=t.cssText,e.appendChild(a)}))},d=i?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="" +for(const a of e.cssRules)t+=a.cssText +return c(t)})(e):e +var u +const f=window,v=f.trustedTypes,p=v?v.emptyScript:"",m=f.reactiveElementPolyfillSupport,y={toAttribute(e,t){switch(t){case Boolean:e=e?p:null +break +case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let a=e +switch(t){case Boolean:a=null!==e +break +case Number:a=null===e?null:Number(e) +break +case Object:case Array:try{a=JSON.parse(e)}catch(e){a=null}}return a}},g=(e,t)=>t!==e&&(t==t||e==e),b={attribute:!0,type:String,converter:y,reflect:!1,hasChanged:g} +class z extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this.u()}static addInitializer(e){var t +this.finalize(),(null!==(t=this.h)&&void 0!==t?t:this.h=[]).push(e)}static get observedAttributes(){this.finalize() +const e=[] +return this.elementProperties.forEach(((t,a)=>{const l=this._$Ep(a,t) +void 0!==l&&(this._$Ev.set(l,a),e.push(l))})),e}static createProperty(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:b +if(t.state&&(t.attribute=!1),this.finalize(),this.elementProperties.set(e,t),!t.noAccessor&&!this.prototype.hasOwnProperty(e)){const a="symbol"==typeof e?Symbol():"__"+e,l=this.getPropertyDescriptor(e,a,t) +void 0!==l&&Object.defineProperty(this.prototype,e,l)}}static getPropertyDescriptor(e,t,a){return{get(){return this[t]},set(l){const i=this[e] +this[t]=l,this.requestUpdate(e,i,a)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)||b}static finalize(){if(this.hasOwnProperty("finalized"))return!1 +this.finalized=!0 +const e=Object.getPrototypeOf(this) +if(e.finalize(),void 0!==e.h&&(this.h=[...e.h]),this.elementProperties=new Map(e.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const e=this.properties,t=[...Object.getOwnPropertyNames(e),...Object.getOwnPropertySymbols(e)] +for(const a of t)this.createProperty(a,e[a])}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(e){const t=[] +if(Array.isArray(e)){const a=new Set(e.flat(1/0).reverse()) +for(const e of a)t.unshift(d(e))}else void 0!==e&&t.push(d(e)) +return t}static _$Ep(e,t){const a=t.attribute +return!1===a?void 0:"string"==typeof a?a:"string"==typeof e?e.toLowerCase():void 0}u(){var e +this._$E_=new Promise((e=>this.enableUpdating=e)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(e=this.constructor.h)||void 0===e||e.forEach((e=>e(this)))}addController(e){var t,a;(null!==(t=this._$ES)&&void 0!==t?t:this._$ES=[]).push(e),void 0!==this.renderRoot&&this.isConnected&&(null===(a=e.hostConnected)||void 0===a||a.call(e))}removeController(e){var t +null===(t=this._$ES)||void 0===t||t.splice(this._$ES.indexOf(e)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((e,t)=>{this.hasOwnProperty(t)&&(this._$Ei.set(t,this[t]),delete this[t])}))}createRenderRoot(){var e +const t=null!==(e=this.shadowRoot)&&void 0!==e?e:this.attachShadow(this.constructor.shadowRootOptions) +return s(t,this.constructor.elementStyles),t}connectedCallback(){var e +void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(e=this._$ES)||void 0===e||e.forEach((e=>{var t +return null===(t=e.hostConnected)||void 0===t?void 0:t.call(e)}))}enableUpdating(e){}disconnectedCallback(){var e +null===(e=this._$ES)||void 0===e||e.forEach((e=>{var t +return null===(t=e.hostDisconnected)||void 0===t?void 0:t.call(e)}))}attributeChangedCallback(e,t,a){this._$AK(e,a)}_$EO(e,t){let a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:b +var l +const i=this.constructor._$Ep(e,a) +if(void 0!==i&&!0===a.reflect){const o=(void 0!==(null===(l=a.converter)||void 0===l?void 0:l.toAttribute)?a.converter:y).toAttribute(t,a.type) +this._$El=e,null==o?this.removeAttribute(i):this.setAttribute(i,o),this._$El=null}}_$AK(e,t){var a +const l=this.constructor,i=l._$Ev.get(e) +if(void 0!==i&&this._$El!==i){const e=l.getPropertyOptions(i),o="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==(null===(a=e.converter)||void 0===a?void 0:a.fromAttribute)?e.converter:y +this._$El=i,this[i]=o.fromAttribute(t,e.type),this._$El=null}}requestUpdate(e,t,a){let l=!0 +void 0!==e&&(((a=a||this.constructor.getPropertyOptions(e)).hasChanged||g)(this[e],t)?(this._$AL.has(e)||this._$AL.set(e,t),!0===a.reflect&&this._$El!==e&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(e,a))):l=!1),!this.isUpdatePending&&l&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0 +try{await this._$E_}catch(e){Promise.reject(e)}const e=this.scheduleUpdate() +return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var e +if(!this.isUpdatePending)return +this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((e,t)=>this[t]=e)),this._$Ei=void 0) +let t=!1 +const a=this._$AL +try{t=this.shouldUpdate(a),t?(this.willUpdate(a),null===(e=this._$ES)||void 0===e||e.forEach((e=>{var t +return null===(t=e.hostUpdate)||void 0===t?void 0:t.call(e)})),this.update(a)):this._$Ek()}catch(e){throw t=!1,this._$Ek(),e}t&&this._$AE(a)}willUpdate(e){}_$AE(e){var t +null===(t=this._$ES)||void 0===t||t.forEach((e=>{var t +return null===(t=e.hostUpdated)||void 0===t?void 0:t.call(e)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(e){return!0}update(e){void 0!==this._$EC&&(this._$EC.forEach(((e,t)=>this._$EO(t,this[t],e))),this._$EC=void 0),this._$Ek()}updated(e){}firstUpdated(e){}}z.finalized=!0,z.elementProperties=new Map,z.elementStyles=[],z.shadowRootOptions={mode:"open"},null==m||m({ReactiveElement:z}),(null!==(u=f.reactiveElementVersions)&&void 0!==u?u:f.reactiveElementVersions=[]).push("1.6.1")}}]) diff --git a/agent/uiserver/dist/assets/chunk.924.719761ac5e77d019056f.js.LICENSE.txt b/agent/uiserver/dist/assets/chunk.924.719761ac5e77d019056f.js.LICENSE.txt new file mode 100644 index 000000000000..987cdda7ee18 --- /dev/null +++ b/agent/uiserver/dist/assets/chunk.924.719761ac5e77d019056f.js.LICENSE.txt @@ -0,0 +1,38 @@ +/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ + +/*! +* focus-trap 6.9.4 +* @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE +*/ + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ diff --git a/agent/uiserver/dist/assets/codemirror/mode/javascript/javascript-a5e5d64b0f9ff6b6e21f5f48aa1ef464.js b/agent/uiserver/dist/assets/codemirror/mode/javascript/javascript-a5e5d64b0f9ff6b6e21f5f48aa1ef464.js index 4da59f70de85..d852d63f9299 100644 --- a/agent/uiserver/dist/assets/codemirror/mode/javascript/javascript-a5e5d64b0f9ff6b6e21f5f48aa1ef464.js +++ b/agent/uiserver/dist/assets/codemirror/mode/javascript/javascript-a5e5d64b0f9ff6b6e21f5f48aa1ef464.js @@ -93,44 +93,45 @@ if(f.test(i)){e.eatWhile(f) var a=e.current(),s=h.propertyIsEnumerable(a)&&h[a] return s&&"."!=r.lastType?y(s.type,s.style,a):y("variable","variable",a)}}function v(e,t){for(var r,n=!1;r=e.next();){if("/"==r&&n){t.tokenize=m break}n="*"==r}return y("comment","comment")}function g(e,t){for(var r,n=!1;null!=(r=e.next());){if(!n&&("`"==r||"$"==r&&e.eat("{"))){t.tokenize=m -break}n=!n&&"\\"==r}return y("quasi","string-2",e.current())}function x(e,t){t.fatArrowAt&&(t.fatArrowAt=null) +break}n=!n&&"\\"==r}return y("quasi","string-2",e.current())}var x="([{}])" +function b(e,t){t.fatArrowAt&&(t.fatArrowAt=null) var r=e.string.indexOf("=>",e.start) -if(!(r<0)){for(var n=0,i=!1,a=r-1;a>=0;--a){var s=e.string.charAt(a),o="([{}])".indexOf(s) +if(!(r<0)){for(var n=0,i=!1,a=r-1;a>=0;--a){var s=e.string.charAt(a),o=x.indexOf(s) if(o>=0&&o<3){if(!n){++a break}if(0==--n)break}else if(o>=3&&o<6)++n else if(f.test(s))i=!0 else{if(/["'\/]/.test(s))return if(i&&!n){++a -break}}}i&&!n&&(t.fatArrowAt=a)}}var b={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,this:!0,"jsonld-keyword":!0} -function k(e,t,r,n,i,a){this.indented=e,this.column=t,this.type=r,this.prev=i,this.info=a,null!=n&&(this.align=n)}function w(e,t){for(var r=e.localVars;r;r=r.next)if(r.name==t)return!0 -for(var n=e.context;n;n=n.prev)for(r=n.vars;r;r=r.next)if(r.name==t)return!0}var _={state:null,column:null,marked:null,cc:null} -function E(){for(var e=arguments.length-1;e>=0;e--)_.cc.push(arguments[e])}function j(){return E.apply(null,arguments),!0}function S(e){function t(t){for(var r=t;r;r=r.next)if(r.name==e)return!0 -return!1}var r=_.state -if(_.marked="def",r.context){if(t(r.localVars))return +break}}}i&&!n&&(t.fatArrowAt=a)}}var k={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,this:!0,"jsonld-keyword":!0} +function w(e,t,r,n,i,a){this.indented=e,this.column=t,this.type=r,this.prev=i,this.info=a,null!=n&&(this.align=n)}function _(e,t){for(var r=e.localVars;r;r=r.next)if(r.name==t)return!0 +for(var n=e.context;n;n=n.prev)for(r=n.vars;r;r=r.next)if(r.name==t)return!0}var E={state:null,column:null,marked:null,cc:null} +function j(){for(var e=arguments.length-1;e>=0;e--)E.cc.push(arguments[e])}function S(){return j.apply(null,arguments),!0}function I(e){function t(t){for(var r=t;r;r=r.next)if(r.name==e)return!0 +return!1}var r=E.state +if(E.marked="def",r.context){if(t(r.localVars))return r.localVars={name:e,next:r.localVars}}else{if(t(r.globalVars))return -n.globalVars&&(r.globalVars={name:e,next:r.globalVars})}}var I={name:"this",next:{name:"arguments"}} -function $(){_.state.context={prev:_.state.context,vars:_.state.localVars},_.state.localVars=I}function A(){_.state.localVars=_.state.context.vars,_.state.context=_.state.context.prev}function M(e,t){var r=function(){var r=_.state,n=r.indented +n.globalVars&&(r.globalVars={name:e,next:r.globalVars})}}var $={name:"this",next:{name:"arguments"}} +function A(){E.state.context={prev:E.state.context,vars:E.state.localVars},E.state.localVars=$}function M(){E.state.localVars=E.state.context.vars,E.state.context=E.state.context.prev}function N(e,t){var r=function(){var r=E.state,n=r.indented if("stat"==r.lexical.type)n=r.lexical.indented else for(var i=r.lexical;i&&")"==i.type&&i.align;i=i.prev)n=i.indented -r.lexical=new k(n,_.stream.column(),e,null,r.lexical,t)} -return r.lex=!0,r}function N(){var e=_.state -e.lexical.prev&&(")"==e.lexical.type&&(e.indented=e.lexical.indented),e.lexical=e.lexical.prev)}function O(e){return function t(r){return r==e?j():";"==e?E():j(t)}}function V(e,t){return"var"==e?j(M("vardef",t.length),ae,O(";"),N):"keyword a"==e?j(M("form"),T,V,N):"keyword b"==e?j(M("form"),V,N):"{"==e?j(M("}"),ee,N):";"==e?j():"if"==e?("else"==_.state.lexical.info&&_.state.cc[_.state.cc.length-1]==N&&_.state.cc.pop()(),j(M("form"),T,V,N,ue)):"function"==e?j(me):"for"==e?j(M("form"),fe,V,N):"variable"==e?j(M("stat"),D):"switch"==e?j(M("form"),T,M("}","switch"),O("{"),ee,N,N):"case"==e?j(T,O(":")):"default"==e?j(O(":")):"catch"==e?j(M("form"),$,O("("),ve,O(")"),V,N,A):"class"==e?j(M("form"),ge,N):"export"==e?j(M("stat"),we,N):"import"==e?j(M("stat"),_e,N):"module"==e?j(M("form"),se,M("}"),O("{"),ee,N,N):"async"==e?j(V):E(M("stat"),T,O(";"),N)}function T(e){return L(e,!1)}function z(e){return L(e,!0)}function L(e,t){if(_.state.fatArrowAt==_.stream.start){var r=t?W:C -if("("==e)return j($,M(")"),Y(se,")"),N,O("=>"),r,A) -if("variable"==e)return E($,se,O("=>"),r,A)}var n=t?F:J -return b.hasOwnProperty(e)?j(n):"function"==e?j(me,n):"keyword c"==e?j(t?P:q):"("==e?j(M(")"),q,Ae,O(")"),N,n):"operator"==e||"spread"==e?j(t?z:T):"["==e?j(M("]"),Ie,N,n):"{"==e?Z(K,"}",null,n):"quasi"==e?E(U,n):"new"==e?j(function(e){return function(t){return"."==t?j(e?G:B):E(e?z:T)}}(t)):j()}function q(e){return e.match(/[;\}\)\],]/)?E():E(T)}function P(e){return e.match(/[;\}\)\],]/)?E():E(z)}function J(e,t){return","==e?j(T):F(e,t,!1)}function F(e,t,r){var n=0==r?J:F,i=0==r?T:z -return"=>"==e?j($,r?W:C,A):"operator"==e?/\+\+|--/.test(t)?j(n):"?"==t?j(T,O(":"),i):j(i):"quasi"==e?E(U,n):";"!=e?"("==e?Z(z,")","call",n):"."==e?j(H,n):"["==e?j(M("]"),q,O("]"),N,n):void 0:void 0}function U(e,t){return"quasi"!=e?E():"${"!=t.slice(t.length-2)?j(U):j(T,R)}function R(e){if("}"==e)return _.marked="string-2",_.state.tokenize=g,j(U)}function C(e){return x(_.stream,_.state),E("{"==e?V:T)}function W(e){return x(_.stream,_.state),E("{"==e?V:z)}function B(e,t){if("target"==t)return _.marked="keyword",j(J)}function G(e,t){if("target"==t)return _.marked="keyword",j(F)}function D(e){return":"==e?j(N,V):E(J,O(";"),N)}function H(e){if("variable"==e)return _.marked="property",j()}function K(e,t){return"variable"==e||"keyword"==_.style?(_.marked="property",j("get"==t||"set"==t?Q:X)):"number"==e||"string"==e?(_.marked=l?"property":_.style+" property",j(X)):"jsonld-keyword"==e?j(X):"modifier"==e?j(K):"["==e?j(T,O("]"),X):"spread"==e?j(T):void 0}function Q(e){return"variable"!=e?E(X):(_.marked="property",j(me))}function X(e){return":"==e?j(z):"("==e?E(me):void 0}function Y(e,t){function r(n,i){if(","==n){var a=_.state.lexical -return"call"==a.info&&(a.pos=(a.pos||0)+1),j(e,r)}return n==t||i==t?j():j(O(t))}return function(n,i){return n==t||i==t?j():E(e,r)}}function Z(e,t,r){for(var n=3;n"),ie):"["==e?j(O("]"),ie):void 0}function ae(){return E(se,te,le,ce)}function se(e,t){return"modifier"==e?j(se):"variable"==e?(S(t),j()):"spread"==e?j(se):"["==e?Z(se,"]"):"{"==e?Z(oe,"}"):void 0}function oe(e,t){return"variable"!=e||_.stream.match(/^\s*:/,!1)?("variable"==e&&(_.marked="property"),"spread"==e?j(se):"}"==e?E():j(O(":"),se,le)):(S(t),j(le))}function le(e,t){if("="==t)return j(z)}function ce(e){if(","==e)return j(ae)}function ue(e,t){if("keyword b"==e&&"else"==t)return j(M("form","else"),V,N)}function fe(e){if("("==e)return j(M(")"),he,O(")"),N)}function he(e){return"var"==e?j(ae,O(";"),de):";"==e?j(de):"variable"==e?j(pe):E(T,O(";"),de)}function pe(e,t){return"in"==t||"of"==t?(_.marked="keyword",j(T)):j(J,de)}function de(e,t){return";"==e?j(ye):"in"==t||"of"==t?(_.marked="keyword",j(T)):E(T,O(";"),ye)}function ye(e){")"!=e&&j(T)}function me(e,t){return"*"==t?(_.marked="keyword",j(me)):"variable"==e?(S(t),j(me)):"("==e?j($,M(")"),Y(ve,")"),N,te,V,A):void 0}function ve(e){return"spread"==e?j(ve):E(se,te,re)}function ge(e,t){if("variable"==e)return S(t),j(xe)}function xe(e,t){return"extends"==t?j(T,xe):"{"==e?j(M("}"),be,N):void 0}function be(e,t){return"variable"==e||"keyword"==_.style?"static"==t?(_.marked="keyword",j(be)):(_.marked="property","get"==t||"set"==t?j(ke,me,be):j(me,be)):"*"==t?(_.marked="keyword",j(be)):";"==e?j(be):"}"==e?j():void 0}function ke(e){return"variable"!=e?E():(_.marked="property",j())}function we(e,t){return"*"==t?(_.marked="keyword",j(Se,O(";"))):"default"==t?(_.marked="keyword",j(T,O(";"))):E(V)}function _e(e){return"string"==e?j():E(Ee,Se)}function Ee(e,t){return"{"==e?Z(Ee,"}"):("variable"==e&&S(t),"*"==t&&(_.marked="keyword"),j(je))}function je(e,t){if("as"==t)return _.marked="keyword",j(Ee)}function Se(e,t){if("from"==t)return _.marked="keyword",j(T)}function Ie(e){return"]"==e?j():E(z,$e)}function $e(e){return"for"==e?E(Ae,O("]")):","==e?j(Y(P,"]")):E(Y(z,"]"))}function Ae(e){return"for"==e?j(fe,Ae):"if"==e?j(T,Ae):void 0}return N.lex=!0,{startState:function(e){var t={tokenize:m,lastType:"sof",cc:[],lexical:new k((e||0)-s,0,"block",!1),localVars:n.localVars,context:n.localVars&&{vars:n.localVars},indented:e||0} -return n.globalVars&&"object"==typeof n.globalVars&&(t.globalVars=n.globalVars),t},token:function(e,t){if(e.sol()&&(t.lexical.hasOwnProperty("align")||(t.lexical.align=!1),t.indented=e.indentation(),x(e,t)),t.tokenize!=v&&e.eatSpace())return null +r.lexical=new w(n,E.stream.column(),e,null,r.lexical,t)} +return r.lex=!0,r}function O(){var e=E.state +e.lexical.prev&&(")"==e.lexical.type&&(e.indented=e.lexical.indented),e.lexical=e.lexical.prev)}function V(e){return function t(r){return r==e?S():";"==e?j():S(t)}}function T(e,t){return"var"==e?S(N("vardef",t.length),se,V(";"),O):"keyword a"==e?S(N("form"),z,T,O):"keyword b"==e?S(N("form"),T,O):"{"==e?S(N("}"),te,O):";"==e?S():"if"==e?("else"==E.state.lexical.info&&E.state.cc[E.state.cc.length-1]==O&&E.state.cc.pop()(),S(N("form"),z,T,O,fe)):"function"==e?S(ve):"for"==e?S(N("form"),he,T,O):"variable"==e?S(N("stat"),H):"switch"==e?S(N("form"),z,N("}","switch"),V("{"),te,O,O):"case"==e?S(z,V(":")):"default"==e?S(V(":")):"catch"==e?S(N("form"),A,V("("),ge,V(")"),T,O,M):"class"==e?S(N("form"),xe,O):"export"==e?S(N("stat"),_e,O):"import"==e?S(N("stat"),Ee,O):"module"==e?S(N("form"),oe,N("}"),V("{"),te,O,O):"async"==e?S(T):j(N("stat"),z,V(";"),O)}function z(e){return q(e,!1)}function L(e){return q(e,!0)}function q(e,t){if(E.state.fatArrowAt==E.stream.start){var r=t?B:W +if("("==e)return S(A,N(")"),Z(oe,")"),O,V("=>"),r,M) +if("variable"==e)return j(A,oe,V("=>"),r,M)}var n=t?U:F +return k.hasOwnProperty(e)?S(n):"function"==e?S(ve,n):"keyword c"==e?S(t?J:P):"("==e?S(N(")"),P,Me,V(")"),O,n):"operator"==e||"spread"==e?S(t?L:z):"["==e?S(N("]"),$e,O,n):"{"==e?ee(Q,"}",null,n):"quasi"==e?j(R,n):"new"==e?S(function(e){return function(t){return"."==t?S(e?D:G):j(e?L:z)}}(t)):S()}function P(e){return e.match(/[;\}\)\],]/)?j():j(z)}function J(e){return e.match(/[;\}\)\],]/)?j():j(L)}function F(e,t){return","==e?S(z):U(e,t,!1)}function U(e,t,r){var n=0==r?F:U,i=0==r?z:L +return"=>"==e?S(A,r?B:W,M):"operator"==e?/\+\+|--/.test(t)?S(n):"?"==t?S(z,V(":"),i):S(i):"quasi"==e?j(R,n):";"!=e?"("==e?ee(L,")","call",n):"."==e?S(K,n):"["==e?S(N("]"),P,V("]"),O,n):void 0:void 0}function R(e,t){return"quasi"!=e?j():"${"!=t.slice(t.length-2)?S(R):S(z,C)}function C(e){if("}"==e)return E.marked="string-2",E.state.tokenize=g,S(R)}function W(e){return b(E.stream,E.state),j("{"==e?T:z)}function B(e){return b(E.stream,E.state),j("{"==e?T:L)}function G(e,t){if("target"==t)return E.marked="keyword",S(F)}function D(e,t){if("target"==t)return E.marked="keyword",S(U)}function H(e){return":"==e?S(O,T):j(F,V(";"),O)}function K(e){if("variable"==e)return E.marked="property",S()}function Q(e,t){return"variable"==e||"keyword"==E.style?(E.marked="property",S("get"==t||"set"==t?X:Y)):"number"==e||"string"==e?(E.marked=l?"property":E.style+" property",S(Y)):"jsonld-keyword"==e?S(Y):"modifier"==e?S(Q):"["==e?S(z,V("]"),Y):"spread"==e?S(z):void 0}function X(e){return"variable"!=e?j(Y):(E.marked="property",S(ve))}function Y(e){return":"==e?S(L):"("==e?j(ve):void 0}function Z(e,t){function r(n,i){if(","==n){var a=E.state.lexical +return"call"==a.info&&(a.pos=(a.pos||0)+1),S(e,r)}return n==t||i==t?S():S(V(t))}return function(n,i){return n==t||i==t?S():j(e,r)}}function ee(e,t,r){for(var n=3;n"),ae):"["==e?S(V("]"),ae):void 0}function se(){return j(oe,re,ce,ue)}function oe(e,t){return"modifier"==e?S(oe):"variable"==e?(I(t),S()):"spread"==e?S(oe):"["==e?ee(oe,"]"):"{"==e?ee(le,"}"):void 0}function le(e,t){return"variable"!=e||E.stream.match(/^\s*:/,!1)?("variable"==e&&(E.marked="property"),"spread"==e?S(oe):"}"==e?j():S(V(":"),oe,ce)):(I(t),S(ce))}function ce(e,t){if("="==t)return S(L)}function ue(e){if(","==e)return S(se)}function fe(e,t){if("keyword b"==e&&"else"==t)return S(N("form","else"),T,O)}function he(e){if("("==e)return S(N(")"),pe,V(")"),O)}function pe(e){return"var"==e?S(se,V(";"),ye):";"==e?S(ye):"variable"==e?S(de):j(z,V(";"),ye)}function de(e,t){return"in"==t||"of"==t?(E.marked="keyword",S(z)):S(F,ye)}function ye(e,t){return";"==e?S(me):"in"==t||"of"==t?(E.marked="keyword",S(z)):j(z,V(";"),me)}function me(e){")"!=e&&S(z)}function ve(e,t){return"*"==t?(E.marked="keyword",S(ve)):"variable"==e?(I(t),S(ve)):"("==e?S(A,N(")"),Z(ge,")"),O,re,T,M):void 0}function ge(e){return"spread"==e?S(ge):j(oe,re,ne)}function xe(e,t){if("variable"==e)return I(t),S(be)}function be(e,t){return"extends"==t?S(z,be):"{"==e?S(N("}"),ke,O):void 0}function ke(e,t){return"variable"==e||"keyword"==E.style?"static"==t?(E.marked="keyword",S(ke)):(E.marked="property","get"==t||"set"==t?S(we,ve,ke):S(ve,ke)):"*"==t?(E.marked="keyword",S(ke)):";"==e?S(ke):"}"==e?S():void 0}function we(e){return"variable"!=e?j():(E.marked="property",S())}function _e(e,t){return"*"==t?(E.marked="keyword",S(Ie,V(";"))):"default"==t?(E.marked="keyword",S(z,V(";"))):j(T)}function Ee(e){return"string"==e?S():j(je,Ie)}function je(e,t){return"{"==e?ee(je,"}"):("variable"==e&&I(t),"*"==t&&(E.marked="keyword"),S(Se))}function Se(e,t){if("as"==t)return E.marked="keyword",S(je)}function Ie(e,t){if("from"==t)return E.marked="keyword",S(z)}function $e(e){return"]"==e?S():j(L,Ae)}function Ae(e){return"for"==e?j(Me,V("]")):","==e?S(Z(J,"]")):j(Z(L,"]"))}function Me(e){return"for"==e?S(he,Me):"if"==e?S(z,Me):void 0}return O.lex=!0,{startState:function(e){var t={tokenize:m,lastType:"sof",cc:[],lexical:new w((e||0)-s,0,"block",!1),localVars:n.localVars,context:n.localVars&&{vars:n.localVars},indented:e||0} +return n.globalVars&&"object"==typeof n.globalVars&&(t.globalVars=n.globalVars),t},token:function(e,t){if(e.sol()&&(t.lexical.hasOwnProperty("align")||(t.lexical.align=!1),t.indented=e.indentation(),b(e,t)),t.tokenize!=v&&e.eatSpace())return null var r=t.tokenize(e,t) return"comment"==i?r:(t.lastType="operator"!=i||"++"!=a&&"--"!=a?i:"incdec",function(e,t,r,n,i){var a=e.cc -for(_.state=e,_.stream=i,_.marked=null,_.cc=a,_.style=t,e.lexical.hasOwnProperty("align")||(e.lexical.align=!0);;)if((a.length?a.pop():c?T:V)(r,n)){for(;a.length&&a[a.length-1].lex;)a.pop()() -return _.marked?_.marked:"variable"==r&&w(e,n)?"variable-2":t}}(t,r,i,a,e))},indent:function(t,r){if(t.tokenize==v)return e.Pass +for(E.state=e,E.stream=i,E.marked=null,E.cc=a,E.style=t,e.lexical.hasOwnProperty("align")||(e.lexical.align=!0);;)if((a.length?a.pop():c?z:T)(r,n)){for(;a.length&&a[a.length-1].lex;)a.pop()() +return E.marked?E.marked:"variable"==r&&_(e,n)?"variable-2":t}}(t,r,i,a,e))},indent:function(t,r){if(t.tokenize==v)return e.Pass if(t.tokenize!=m)return 0 var i=r&&r.charAt(0),a=t.lexical if(!/^\s*else\b/.test(r))for(var l=t.cc.length-1;l>=0;--l){var c=t.cc[l] -if(c==N)a=a.prev -else if(c!=ue)break}"stat"==a.type&&"}"==i&&(a=a.prev),o&&")"==a.type&&"stat"==a.prev.type&&(a=a.prev) +if(c==O)a=a.prev +else if(c!=fe)break}"stat"==a.type&&"}"==i&&(a=a.prev),o&&")"==a.type&&"stat"==a.prev.type&&(a=a.prev) var u=a.type,f=i==u return"vardef"==u?a.indented+("operator"==t.lastType||","==t.lastType?a.info+1:0):"form"==u&&"{"==i?a.indented:"form"==u?a.indented+s:"stat"==u?a.indented+(function(e,t){return"operator"==e.lastType||","==e.lastType||p.test(t.charAt(0))||/[,.]/.test(t.charAt(0))}(t,r)?o||s:0):"switch"!=a.info||f||0==n.doubleIndentSwitch?a.align?a.column+(f?0:1):a.indented+(f?0:s):a.indented+(/^(?:case|default)\b/.test(r)?s:2*s)},electricInput:/^\s*(?:case .*?:|default:|\{|\})$/,blockCommentStart:c?null:"/*",blockCommentEnd:c?null:"*/",lineComment:c?null:"//",fold:"brace",closeBrackets:"()[]{}''\"\"``",helperType:c?"json":"javascript",jsonldMode:l,jsonMode:c,expressionAllowed:t,skipExpression:function(e){var t=e.cc[e.cc.length-1] -t!=T&&t!=z||e.cc.pop()}}})),e.registerHelper("wordChars","javascript",/[\w$]/),e.defineMIME("text/javascript","javascript"),e.defineMIME("text/ecmascript","javascript"),e.defineMIME("application/javascript","javascript"),e.defineMIME("application/x-javascript","javascript"),e.defineMIME("application/ecmascript","javascript"),e.defineMIME("application/json",{name:"javascript",json:!0}),e.defineMIME("application/x-json",{name:"javascript",json:!0}),e.defineMIME("application/ld+json",{name:"javascript",jsonld:!0}),e.defineMIME("text/typescript",{name:"javascript",typescript:!0}),e.defineMIME("application/typescript",{name:"javascript",typescript:!0})})) +t!=z&&t!=L||e.cc.pop()}}})),e.registerHelper("wordChars","javascript",/[\w$]/),e.defineMIME("text/javascript","javascript"),e.defineMIME("text/ecmascript","javascript"),e.defineMIME("application/javascript","javascript"),e.defineMIME("application/x-javascript","javascript"),e.defineMIME("application/ecmascript","javascript"),e.defineMIME("application/json",{name:"javascript",json:!0}),e.defineMIME("application/x-json",{name:"javascript",json:!0}),e.defineMIME("application/ld+json",{name:"javascript",jsonld:!0}),e.defineMIME("text/typescript",{name:"javascript",typescript:!0}),e.defineMIME("application/typescript",{name:"javascript",typescript:!0})})) diff --git a/agent/uiserver/dist/assets/codemirror/mode/yaml/yaml-39582b60e653cf0b8d42292ddfabefb2.js b/agent/uiserver/dist/assets/codemirror/mode/yaml/yaml-39582b60e653cf0b8d42292ddfabefb2.js deleted file mode 100644 index a52cfdfb93fd..000000000000 --- a/agent/uiserver/dist/assets/codemirror/mode/yaml/yaml-39582b60e653cf0b8d42292ddfabefb2.js +++ /dev/null @@ -1,276 +0,0 @@ -/*! js-yaml 4.0.0 https://github.com/nodeca/js-yaml @license MIT */ -(function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).jsyaml={})})(this,(function(e){"use strict" -function t(e){return null==e}var n={isNothing:t,isObject:function(e){return"object"==typeof e&&null!==e},toArray:function(e){return Array.isArray(e)?e:t(e)?[]:[e]},repeat:function(e,t){var n,i="" -for(n=0;nl&&(t=i-l+(o=" ... ").length),n-i>l&&(n=i+l-(a=" ...").length),{str:o+e.slice(t,n).replace(/\t/g,"→")+a,pos:i-t+o.length}}function l(e,t){return n.repeat(" ",t-e.length)+e}var c=function(e,t){if(t=Object.create(t||null),!e.buffer)return null -t.maxLength||(t.maxLength=79),"number"!=typeof t.indent&&(t.indent=1),"number"!=typeof t.linesBefore&&(t.linesBefore=3),"number"!=typeof t.linesAfter&&(t.linesAfter=2) -for(var i,r=/\r?\n|\r|\0/g,o=[0],c=[],s=-1;i=r.exec(e.buffer);)c.push(i.index),o.push(i.index+i[0].length),e.position<=i.index&&s<0&&(s=o.length-2) -s<0&&(s=o.length-1) -var u,p,f="",d=Math.min(e.line+t.linesAfter,c.length).toString().length,h=t.maxLength-(t.indent+d+3) -for(u=1;u<=t.linesBefore&&!(s-u<0);u++)p=a(e.buffer,o[s-u],c[s-u],e.position-(o[s]-o[s-u]),h),f=n.repeat(" ",t.indent)+l((e.line-u+1).toString(),d)+" | "+p.str+"\n"+f -for(p=a(e.buffer,o[s],c[s],e.position,h),f+=n.repeat(" ",t.indent)+l((e.line+1).toString(),d)+" | "+p.str+"\n",f+=n.repeat("-",t.indent+d+3+p.pos)+"^\n",u=1;u<=t.linesAfter&&!(s+u>=c.length);u++)p=a(e.buffer,o[s+u],c[s+u],e.position-(o[s]-o[s+u]),h),f+=n.repeat(" ",t.indent)+l((e.line+u+1).toString(),d)+" | "+p.str+"\n" -return f.replace(/\n$/,"")},s=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],u=["scalar","sequence","mapping"] -var p=function(e,t){if(t=t||{},Object.keys(t).forEach((function(t){if(-1===s.indexOf(t))throw new o('Unknown option "'+t+'" is met in definition of "'+e+'" YAML type.')})),this.tag=e,this.kind=t.kind||null,this.resolve=t.resolve||function(){return!0},this.construct=t.construct||function(e){return e},this.instanceOf=t.instanceOf||null,this.predicate=t.predicate||null,this.represent=t.represent||null,this.representName=t.representName||null,this.defaultStyle=t.defaultStyle||null,this.multi=t.multi||!1,this.styleAliases=function(e){var t={} -return null!==e&&Object.keys(e).forEach((function(n){e[n].forEach((function(e){t[String(e)]=n}))})),t}(t.styleAliases||null),-1===u.indexOf(this.kind))throw new o('Unknown kind "'+this.kind+'" is specified for "'+e+'" YAML type.')} -function f(e,t,n){var i=[] -return e[t].forEach((function(e){n.forEach((function(t,n){t.tag===e.tag&&t.kind===e.kind&&t.multi===e.multi&&i.push(n)})),n.push(e)})),n.filter((function(e,t){return-1===i.indexOf(t)}))}function d(e){return this.extend(e)}d.prototype.extend=function(e){var t=[],n=[] -if(e instanceof p)n.push(e) -else if(Array.isArray(e))n=n.concat(e) -else{if(!e||!Array.isArray(e.implicit)&&!Array.isArray(e.explicit))throw new o("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })") -e.implicit&&(t=t.concat(e.implicit)),e.explicit&&(n=n.concat(e.explicit))}t.forEach((function(e){if(!(e instanceof p))throw new o("Specified list of YAML types (or a single Type object) contains a non-Type object.") -if(e.loadKind&&"scalar"!==e.loadKind)throw new o("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.") -if(e.multi)throw new o("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.")})),n.forEach((function(e){if(!(e instanceof p))throw new o("Specified list of YAML types (or a single Type object) contains a non-Type object.")})) -var i=Object.create(d.prototype) -return i.implicit=(this.implicit||[]).concat(t),i.explicit=(this.explicit||[]).concat(n),i.compiledImplicit=f(i,"implicit",[]),i.compiledExplicit=f(i,"explicit",[]),i.compiledTypeMap=function(){var e,t,n={scalar:{},sequence:{},mapping:{},fallback:{},multi:{scalar:[],sequence:[],mapping:[],fallback:[]}} -function i(e){e.multi?(n.multi[e.kind].push(e),n.multi.fallback.push(e)):n[e.kind][e.tag]=n.fallback[e.tag]=e}for(e=0,t=arguments.length;e=0?"0b"+e.toString(2):"-0b"+e.toString(2).slice(1)},octal:function(e){return e>=0?"0o"+e.toString(8):"-0o"+e.toString(8).slice(1)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return e>=0?"0x"+e.toString(16).toUpperCase():"-0x"+e.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),k=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$") -var w=/^[-+]?[0-9]+e/ -var C=new p("tag:yaml.org,2002:float",{kind:"scalar",resolve:function(e){return null!==e&&!(!k.test(e)||"_"===e[e.length-1])},construct:function(e){var t,n -return n="-"===(t=e.replace(/_/g,"").toLowerCase())[0]?-1:1,"+-".indexOf(t[0])>=0&&(t=t.slice(1)),".inf"===t?1===n?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===t?NaN:n*parseFloat(t,10)},predicate:function(e){return"[object Number]"===Object.prototype.toString.call(e)&&(e%1!=0||n.isNegativeZero(e))},represent:function(e,t){var i -if(isNaN(e))switch(t){case"lowercase":return".nan" -case"uppercase":return".NAN" -case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===e)switch(t){case"lowercase":return".inf" -case"uppercase":return".INF" -case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case"lowercase":return"-.inf" -case"uppercase":return"-.INF" -case"camelcase":return"-.Inf"}else if(n.isNegativeZero(e))return"-0.0" -return i=e.toString(10),w.test(i)?i.replace("e",".e"):i},defaultStyle:"lowercase"}),x=m.extend({implicit:[g,y,v,C]}),I=x,S=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),O=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$") -var j=new p("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:function(e){return null!==e&&(null!==S.exec(e)||null!==O.exec(e))},construct:function(e){var t,n,i,r,o,a,l,c,s=0,u=null -if(null===(t=S.exec(e))&&(t=O.exec(e)),null===t)throw new Error("Date resolve error") -if(n=+t[1],i=+t[2]-1,r=+t[3],!t[4])return new Date(Date.UTC(n,i,r)) -if(o=+t[4],a=+t[5],l=+t[6],t[7]){for(s=t[7].slice(0,3);s.length<3;)s+="0" -s=+s}return t[9]&&(u=6e4*(60*+t[10]+ +(t[11]||0)),"-"===t[9]&&(u=-u)),c=new Date(Date.UTC(n,i,r,o,a,l,s)),u&&c.setTime(c.getTime()-u),c},instanceOf:Date,represent:function(e){return e.toISOString()}}) -var T=new p("tag:yaml.org,2002:merge",{kind:"scalar",resolve:function(e){return"<<"===e||null===e}}),E="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r" -var M=new p("tag:yaml.org,2002:binary",{kind:"scalar",resolve:function(e){if(null===e)return!1 -var t,n,i=0,r=e.length,o=E -for(n=0;n64)){if(t<0)return!1 -i+=6}return i%8==0},construct:function(e){var t,n,i=e.replace(/[\r\n=]/g,""),r=i.length,o=E,a=0,l=[] -for(t=0;t>16&255),l.push(a>>8&255),l.push(255&a)),a=a<<6|o.indexOf(i.charAt(t)) -return 0===(n=r%4*6)?(l.push(a>>16&255),l.push(a>>8&255),l.push(255&a)):18===n?(l.push(a>>10&255),l.push(a>>2&255)):12===n&&l.push(a>>4&255),new Uint8Array(l)},predicate:function(e){return"[object Uint8Array]"===Object.prototype.toString.call(e)},represent:function(e){var t,n,i="",r=0,o=e.length,a=E -for(t=0;t>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]),r=(r<<8)+e[t] -return 0===(n=o%3)?(i+=a[r>>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]):2===n?(i+=a[r>>10&63],i+=a[r>>4&63],i+=a[r<<2&63],i+=a[64]):1===n&&(i+=a[r>>2&63],i+=a[r<<4&63],i+=a[64],i+=a[64]),i}}),L=Object.prototype.hasOwnProperty,N=Object.prototype.toString -var F=new p("tag:yaml.org,2002:omap",{kind:"sequence",resolve:function(e){if(null===e)return!0 -var t,n,i,r,o,a=[],l=e -for(t=0,n=l.length;t>10),56320+(e-65536&1023))}for(var ee=new Array(256),te=new Array(256),ne=0;ne<256;ne++)ee[ne]=Q(ne)?1:0,te[ne]=Q(ne) -function ie(e,t){this.input=e,this.filename=t.filename||null,this.schema=t.schema||Y,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.firstTabInLine=-1,this.documents=[]}function re(e,t){var n={name:e.filename,buffer:e.input.slice(0,-1),position:e.position,line:e.line,column:e.position-e.lineStart} -return n.snippet=c(n),new o(t,n)}function oe(e,t){throw re(e,t)}function ae(e,t){e.onWarning&&e.onWarning.call(null,re(e,t))}var le={YAML:function(e,t,n){var i,r,o -null!==e.version&&oe(e,"duplication of %YAML directive"),1!==n.length&&oe(e,"YAML directive accepts exactly one argument"),null===(i=/^([0-9]+)\.([0-9]+)$/.exec(n[0]))&&oe(e,"ill-formed argument of the YAML directive"),r=parseInt(i[1],10),o=parseInt(i[2],10),1!==r&&oe(e,"unacceptable YAML version of the document"),e.version=n[0],e.checkLineBreaks=o<2,1!==o&&2!==o&&ae(e,"unsupported YAML version of the document")},TAG:function(e,t,n){var i,r -2!==n.length&&oe(e,"TAG directive accepts exactly two arguments"),i=n[0],r=n[1],K.test(i)||oe(e,"ill-formed tag handle (first argument) of the TAG directive"),P.call(e.tagMap,i)&&oe(e,'there is a previously declared suffix for "'+i+'" tag handle'),W.test(r)||oe(e,"ill-formed tag prefix (second argument) of the TAG directive") -try{r=decodeURIComponent(r)}catch(o){oe(e,"tag prefix is malformed: "+r)}e.tagMap[i]=r}} -function ce(e,t,n,i){var r,o,a,l -if(t1&&(e.result+=n.repeat("\n",t-1))}function me(e,t){var n,i,r=e.tag,o=e.anchor,a=[],l=!1 -if(-1!==e.firstTabInLine)return!1 -for(null!==e.anchor&&(e.anchorMap[e.anchor]=a),i=e.input.charCodeAt(e.position);0!==i&&(-1!==e.firstTabInLine&&(e.position=e.firstTabInLine,oe(e,"tab characters must not be used in indentation")),45===i)&&Z(e.input.charCodeAt(e.position+1));)if(l=!0,e.position++,fe(e,!0,-1)&&e.lineIndent<=t)a.push(null),i=e.input.charCodeAt(e.position) -else if(n=e.line,be(e,t,3,!1,!0),a.push(e.result),fe(e,!0,-1),i=e.input.charCodeAt(e.position),(e.line===n||e.lineIndent>t)&&0!==i)oe(e,"bad indentation of a sequence entry") -else if(e.lineIndentt?m=1:e.lineIndent===t?m=0:e.lineIndentt?m=1:e.lineIndent===t?m=0:e.lineIndentt)&&(y&&(a=e.line,l=e.lineStart,c=e.position),be(e,t,4,!0,r)&&(y?m=e.result:g=e.result),y||(ue(e,f,d,h,m,g,a,l,c),h=m=g=null),fe(e,!0,-1),s=e.input.charCodeAt(e.position)),(e.line===o||e.lineIndent>t)&&0!==s)oe(e,"bad indentation of a mapping entry") -else if(e.lineIndent=0))break -0===o?oe(e,"bad explicit indentation width of a block scalar; it cannot be less than one"):u?oe(e,"repeat of an indentation width identifier"):(p=t+o-1,u=!0)}if(V(a)){do{a=e.input.charCodeAt(++e.position)}while(V(a)) -if(35===a)do{a=e.input.charCodeAt(++e.position)}while(!G(a)&&0!==a)}for(;0!==a;){for(pe(e),e.lineIndent=0,a=e.input.charCodeAt(e.position);(!u||e.lineIndentp&&(p=e.lineIndent),G(a))f++ -else{if(e.lineIndent0){for(r=a,o=0;r>0;r--)(a=J(l=e.input.charCodeAt(++e.position)))>=0?o=(o<<4)+a:oe(e,"expected hexadecimal character") -e.result+=X(o),e.position++}else oe(e,"unknown escape sequence") -n=i=e.position}else G(l)?(ce(e,n,i,!0),he(e,fe(e,!1,t)),n=i=e.position):e.position===e.lineStart&&de(e)?oe(e,"unexpected end of the document within a double quoted scalar"):(e.position++,i=e.position)}oe(e,"unexpected end of the stream within a double quoted scalar")}(e,d)?y=!0:!function(e){var t,n,i -if(42!==(i=e.input.charCodeAt(e.position)))return!1 -for(i=e.input.charCodeAt(++e.position),t=e.position;0!==i&&!Z(i)&&!z(i);)i=e.input.charCodeAt(++e.position) -return e.position===t&&oe(e,"name of an alias node must contain at least one character"),n=e.input.slice(t,e.position),P.call(e.anchorMap,n)||oe(e,'unidentified alias "'+n+'"'),e.result=e.anchorMap[n],fe(e,!0,-1),!0}(e)?function(e,t,n){var i,r,o,a,l,c,s,u,p=e.kind,f=e.result -if(Z(u=e.input.charCodeAt(e.position))||z(u)||35===u||38===u||42===u||33===u||124===u||62===u||39===u||34===u||37===u||64===u||96===u)return!1 -if((63===u||45===u)&&(Z(i=e.input.charCodeAt(e.position+1))||n&&z(i)))return!1 -for(e.kind="scalar",e.result="",r=o=e.position,a=!1;0!==u;){if(58===u){if(Z(i=e.input.charCodeAt(e.position+1))||n&&z(i))break}else if(35===u){if(Z(e.input.charCodeAt(e.position-1)))break}else{if(e.position===e.lineStart&&de(e)||n&&z(u))break -if(G(u)){if(l=e.line,c=e.lineStart,s=e.lineIndent,fe(e,!1,-1),e.lineIndent>=t){a=!0,u=e.input.charCodeAt(e.position) -continue}e.position=o,e.line=l,e.lineStart=c,e.lineIndent=s -break}}a&&(ce(e,r,o,!1),he(e,e.line-l),r=o=e.position,a=!1),V(u)||(o=e.position+1),u=e.input.charCodeAt(++e.position)}return ce(e,r,o,!1),!!e.result||(e.kind=p,e.result=f,!1)}(e,d,1===i)&&(y=!0,null===e.tag&&(e.tag="?")):(y=!0,null===e.tag&&null===e.anchor||oe(e,"alias node should not have any properties")),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):0===m&&(y=c&&me(e,h))),null===e.tag)null!==e.anchor&&(e.anchorMap[e.anchor]=e.result) -else if("?"===e.tag){for(null!==e.result&&"scalar"!==e.kind&&oe(e,'unacceptable node kind for ! tag; it should be "scalar", not "'+e.kind+'"'),s=0,u=e.implicitTypes.length;s"),null!==e.result&&f.kind!==e.kind&&oe(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+f.kind+'", not "'+e.kind+'"'),f.resolve(e.result,e.tag)?(e.result=f.construct(e.result,e.tag),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):oe(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")}return null!==e.listener&&e.listener("close",e),null!==e.tag||null!==e.anchor||y}function Ae(e){var t,n,i,r,o=e.position,a=!1 -for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap=Object.create(null),e.anchorMap=Object.create(null);0!==(r=e.input.charCodeAt(e.position))&&(fe(e,!0,-1),r=e.input.charCodeAt(e.position),!(e.lineIndent>0||37!==r));){for(a=!0,r=e.input.charCodeAt(++e.position),t=e.position;0!==r&&!Z(r);)r=e.input.charCodeAt(++e.position) -for(i=[],(n=e.input.slice(t,e.position)).length<1&&oe(e,"directive name must not be less than one character in length");0!==r;){for(;V(r);)r=e.input.charCodeAt(++e.position) -if(35===r){do{r=e.input.charCodeAt(++e.position)}while(0!==r&&!G(r)) -break}if(G(r))break -for(t=e.position;0!==r&&!Z(r);)r=e.input.charCodeAt(++e.position) -i.push(e.input.slice(t,e.position))}0!==r&&pe(e),P.call(le,n)?le[n](e,n,i):ae(e,'unknown document directive "'+n+'"')}fe(e,!0,-1),0===e.lineIndent&&45===e.input.charCodeAt(e.position)&&45===e.input.charCodeAt(e.position+1)&&45===e.input.charCodeAt(e.position+2)?(e.position+=3,fe(e,!0,-1)):a&&oe(e,"directives end mark is expected"),be(e,e.lineIndent-1,4,!1,!0),fe(e,!0,-1),e.checkLineBreaks&&$.test(e.input.slice(o,e.position))&&ae(e,"non-ASCII line breaks are interpreted as content"),e.documents.push(e.result),e.position===e.lineStart&&de(e)?46===e.input.charCodeAt(e.position)&&(e.position+=3,fe(e,!0,-1)):e.position=55296&&i<=56319&&t+1=56320&&n<=57343?1024*(i-55296)+n-56320+65536:i}function Ue(e){return/^\n* /.test(e)}function qe(e,t,n,i,r,o,a,l){var c,s,u=0,p=null,f=!1,d=!1,h=-1!==i,m=-1,g=Ne(s=De(e,0))&&s!==xe&&!Le(s)&&45!==s&&63!==s&&58!==s&&44!==s&&91!==s&&93!==s&&123!==s&&125!==s&&35!==s&&38!==s&&42!==s&&33!==s&&124!==s&&61!==s&&62!==s&&39!==s&&34!==s&&37!==s&&64!==s&&96!==s&&function(e){return!Le(e)&&58!==e}(De(e,e.length-1)) -if(t||a)for(c=0;c=65536?c+=2:c++){if(!Ne(u=De(e,c)))return 5 -g=g&&_e(u,p,l),p=u}else{for(c=0;c=65536?c+=2:c++){if(10===(u=De(e,c)))f=!0,h&&(d=d||c-m-1>i&&" "!==e[m+1],m=c) -else if(!Ne(u))return 5 -g=g&&_e(u,p,l),p=u}d=d||h&&c-m-1>i&&" "!==e[m+1]}return f||d?n>9&&Ue(e)?5:a?2===o?5:2:d?4:3:!g||a||r(e)?2===o?5:2:1}function Ye(e,t,n,i,r){e.dump=function(){if(0===t.length)return 2===e.quotingType?'""':"''" -if(!e.noCompatMode&&(-1!==Se.indexOf(t)||Oe.test(t)))return 2===e.quotingType?'"'+t+'"':"'"+t+"'" -var a=e.indent*Math.max(1,n),l=-1===e.lineWidth?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-a),c=i||e.flowLevel>-1&&n>=e.flowLevel -switch(qe(t,c,e.indent,l,(function(t){return function(e,t){var n,i -for(n=0,i=e.implicitTypes.length;n"+Pe(t,e.indent)+Re(Ee(function(e,t){var n,i,r=/(\n+)([^\n]*)/g,o=(l=e.indexOf("\n"),l=-1!==l?l:e.length,r.lastIndex=l,$e(e.slice(0,l),t)),a="\n"===e[0]||" "===e[0] -var l -for(;i=r.exec(e);){var c=i[1],s=i[2] -n=" "===s[0],o+=c+(a||n||""===s?"":"\n")+$e(s,t),a=n}return o}(t,l),a)) -case 5:return'"'+function(e){for(var t,n="",i=0,r=0;r=65536?r+=2:r++)i=De(e,r),!(t=Ie[i])&&Ne(i)?(n+=e[r],i>=65536&&(n+=e[r+1])):n+=t||je(i) -return n}(t)+'"' -default:throw new o("impossible error: invalid scalar style")}}()}function Pe(e,t){var n=Ue(e)?String(t):"",i="\n"===e[e.length-1] -return n+(i&&("\n"===e[e.length-2]||"\n"===e)?"+":i?"":"-")+"\n"}function Re(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}function $e(e,t){if(""===e||" "===e[0])return e -for(var n,i,r=/ [^ ]/g,o=0,a=0,l=0,c="";n=r.exec(e);)(l=n.index)-o>t&&(i=a>o?a:l,c+="\n"+e.slice(o,i),o=i+1),a=l -return c+="\n",e.length-o>t&&a>o?c+=e.slice(o,a)+"\n"+e.slice(a+1):c+=e.slice(o),c.slice(1)}function Be(e,t,n,i){var r,o,a,l="",c=e.tag -for(r=0,o=n.length;r tag resolver accepts not "'+s+'" style') -i=c.represent[s](t,s)}e.dump=i}return!0}return!1}function We(e,t,n,i,r,a,l){e.tag=null,e.dump=n,Ke(e,n,!1)||Ke(e,n,!0) -var c,s=we.call(e.dump),u=i -i&&(i=e.flowLevel<0||e.flowLevel>t) -var p,f,d="[object Object]"===s||"[object Array]"===s -if(d&&(f=-1!==(p=e.duplicates.indexOf(n))),(null!==e.tag&&"?"!==e.tag||f||2!==e.indent&&t>0)&&(r=!1),f&&e.usedDuplicates[p])e.dump="*ref_"+p -else{if(d&&f&&!e.usedDuplicates[p]&&(e.usedDuplicates[p]=!0),"[object Object]"===s)i&&0!==Object.keys(e.dump).length?(function(e,t,n,i){var r,a,l,c,s,u,p="",f=e.tag,d=Object.keys(n) -if(!0===e.sortKeys)d.sort() -else if("function"==typeof e.sortKeys)d.sort(e.sortKeys) -else if(e.sortKeys)throw new o("sortKeys must be a boolean or a function") -for(r=0,a=d.length;r1024)&&(e.dump&&10===e.dump.charCodeAt(0)?u+="?":u+="? "),u+=e.dump,s&&(u+=Me(e,t)),We(e,t+1,c,!0,s)&&(e.dump&&10===e.dump.charCodeAt(0)?u+=":":u+=": ",p+=u+=e.dump)) -e.tag=f,e.dump=p||"{}"}(e,t,e.dump,r),f&&(e.dump="&ref_"+p+e.dump)):(function(e,t,n){var i,r,o,a,l,c="",s=e.tag,u=Object.keys(n) -for(i=0,r=u.length;i1024&&(l+="? "),l+=e.dump+(e.condenseFlow?'"':"")+":"+(e.condenseFlow?"":" "),We(e,t,a,!1,!1)&&(c+=l+=e.dump)) -e.tag=s,e.dump="{"+c+"}"}(e,t,e.dump),f&&(e.dump="&ref_"+p+" "+e.dump)) -else if("[object Array]"===s)i&&0!==e.dump.length?(e.noArrayIndent&&!l&&t>0?Be(e,t-1,e.dump,r):Be(e,t,e.dump,r),f&&(e.dump="&ref_"+p+e.dump)):(function(e,t,n){var i,r,o,a="",l=e.tag -for(i=0,r=n.length;i",e.dump=c+" "+e.dump)}return!0}function He(e,t){var n,i,r=[],o=[] -for(Ge(e,r,o),n=0,i=o.length;nn.keyCol)return t.skipToEnd(),"string" -if(n.literal&&(n.literal=!1),t.sol()){if(n.keyCol=0,n.pair=!1,n.pairStart=!1,t.match(/---/))return"def" -if(t.match(/\.\.\./))return"def" -if(t.match(/\s*-\s+/))return"meta"}if(t.match(/^(\{|\}|\[|\])/))return"{"==i?n.inlinePairs++:"}"==i?n.inlinePairs--:"["==i?n.inlineList++:n.inlineList--,"meta" -if(n.inlineList>0&&!r&&","==i)return t.next(),"meta" -if(n.inlinePairs>0&&!r&&","==i)return n.keyCol=0,n.pair=!1,n.pairStart=!1,t.next(),"meta" -if(n.pairStart){if(t.match(/^\s*(\||\>)\s*/))return n.literal=!0,"meta" -if(t.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i))return"variable-2" -if(0==n.inlinePairs&&t.match(/^\s*-?[0-9\.\,]+\s?$/))return"number" -if(n.inlinePairs>0&&t.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/))return"number" -if(t.match(e))return"keyword"}return!n.pair&&t.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)?(n.pair=!0,n.keyCol=t.indentation(),"atom"):n.pair&&t.match(/^:\s*/)?(n.pairStart=!0,"meta"):(n.pairStart=!1,n.escaped="\\"==i,t.next(),null)},startState:function(){return{pair:!1,pairStart:!1,keyCol:0,inlinePairs:0,inlineList:0,literal:!1,escaped:!1}}}})),e.defineMIME("text/x-yaml","yaml")})) diff --git a/agent/uiserver/dist/assets/codemirror/mode/yaml/yaml-d1dfef3221c9d73c6c8042ca73949aa2.js b/agent/uiserver/dist/assets/codemirror/mode/yaml/yaml-d1dfef3221c9d73c6c8042ca73949aa2.js new file mode 100644 index 000000000000..e68f7e1eac04 --- /dev/null +++ b/agent/uiserver/dist/assets/codemirror/mode/yaml/yaml-d1dfef3221c9d73c6c8042ca73949aa2.js @@ -0,0 +1,279 @@ +/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */ +(function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).jsyaml={})})(this,(function(e){"use strict" +function t(e){return null==e}var n={isNothing:t,isObject:function(e){return"object"==typeof e&&null!==e},toArray:function(e){return Array.isArray(e)?e:t(e)?[]:[e]},repeat:function(e,t){var n,i="" +for(n=0;nl&&(t=i-l+(o=" ... ").length),n-i>l&&(n=i+l-(a=" ...").length),{str:o+e.slice(t,n).replace(/\t/g,"→")+a,pos:i-t+o.length}}function l(e,t){return n.repeat(" ",t-e.length)+e}var s=function(e,t){if(t=Object.create(t||null),!e.buffer)return null +t.maxLength||(t.maxLength=79),"number"!=typeof t.indent&&(t.indent=1),"number"!=typeof t.linesBefore&&(t.linesBefore=3),"number"!=typeof t.linesAfter&&(t.linesAfter=2) +for(var i,r=/\r?\n|\r|\0/g,o=[0],s=[],c=-1;i=r.exec(e.buffer);)s.push(i.index),o.push(i.index+i[0].length),e.position<=i.index&&c<0&&(c=o.length-2) +c<0&&(c=o.length-1) +var u,p,f="",d=Math.min(e.line+t.linesAfter,s.length).toString().length,h=t.maxLength-(t.indent+d+3) +for(u=1;u<=t.linesBefore&&!(c-u<0);u++)p=a(e.buffer,o[c-u],s[c-u],e.position-(o[c]-o[c-u]),h),f=n.repeat(" ",t.indent)+l((e.line-u+1).toString(),d)+" | "+p.str+"\n"+f +for(p=a(e.buffer,o[c],s[c],e.position,h),f+=n.repeat(" ",t.indent)+l((e.line+1).toString(),d)+" | "+p.str+"\n",f+=n.repeat("-",t.indent+d+3+p.pos)+"^\n",u=1;u<=t.linesAfter&&!(c+u>=s.length);u++)p=a(e.buffer,o[c+u],s[c+u],e.position-(o[c]-o[c+u]),h),f+=n.repeat(" ",t.indent)+l((e.line+u+1).toString(),d)+" | "+p.str+"\n" +return f.replace(/\n$/,"")},c=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],u=["scalar","sequence","mapping"] +var p=function(e,t){if(t=t||{},Object.keys(t).forEach((function(t){if(-1===c.indexOf(t))throw new o('Unknown option "'+t+'" is met in definition of "'+e+'" YAML type.')})),this.options=t,this.tag=e,this.kind=t.kind||null,this.resolve=t.resolve||function(){return!0},this.construct=t.construct||function(e){return e},this.instanceOf=t.instanceOf||null,this.predicate=t.predicate||null,this.represent=t.represent||null,this.representName=t.representName||null,this.defaultStyle=t.defaultStyle||null,this.multi=t.multi||!1,this.styleAliases=function(e){var t={} +return null!==e&&Object.keys(e).forEach((function(n){e[n].forEach((function(e){t[String(e)]=n}))})),t}(t.styleAliases||null),-1===u.indexOf(this.kind))throw new o('Unknown kind "'+this.kind+'" is specified for "'+e+'" YAML type.')} +function f(e,t){var n=[] +return e[t].forEach((function(e){var t=n.length +n.forEach((function(n,i){n.tag===e.tag&&n.kind===e.kind&&n.multi===e.multi&&(t=i)})),n[t]=e})),n}function d(e){return this.extend(e)}d.prototype.extend=function(e){var t=[],n=[] +if(e instanceof p)n.push(e) +else if(Array.isArray(e))n=n.concat(e) +else{if(!e||!Array.isArray(e.implicit)&&!Array.isArray(e.explicit))throw new o("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })") +e.implicit&&(t=t.concat(e.implicit)),e.explicit&&(n=n.concat(e.explicit))}t.forEach((function(e){if(!(e instanceof p))throw new o("Specified list of YAML types (or a single Type object) contains a non-Type object.") +if(e.loadKind&&"scalar"!==e.loadKind)throw new o("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.") +if(e.multi)throw new o("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.")})),n.forEach((function(e){if(!(e instanceof p))throw new o("Specified list of YAML types (or a single Type object) contains a non-Type object.")})) +var i=Object.create(d.prototype) +return i.implicit=(this.implicit||[]).concat(t),i.explicit=(this.explicit||[]).concat(n),i.compiledImplicit=f(i,"implicit"),i.compiledExplicit=f(i,"explicit"),i.compiledTypeMap=function(){var e,t,n={scalar:{},sequence:{},mapping:{},fallback:{},multi:{scalar:[],sequence:[],mapping:[],fallback:[]}} +function i(e){e.multi?(n.multi[e.kind].push(e),n.multi.fallback.push(e)):n[e.kind][e.tag]=n.fallback[e.tag]=e}for(e=0,t=arguments.length;e=0?"0b"+e.toString(2):"-0b"+e.toString(2).slice(1)},octal:function(e){return e>=0?"0o"+e.toString(8):"-0o"+e.toString(8).slice(1)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return e>=0?"0x"+e.toString(16).toUpperCase():"-0x"+e.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),x=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$") +var I=/^[-+]?[0-9]+e/ +var S=new p("tag:yaml.org,2002:float",{kind:"scalar",resolve:function(e){return null!==e&&!(!x.test(e)||"_"===e[e.length-1])},construct:function(e){var t,n +return n="-"===(t=e.replace(/_/g,"").toLowerCase())[0]?-1:1,"+-".indexOf(t[0])>=0&&(t=t.slice(1)),".inf"===t?1===n?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===t?NaN:n*parseFloat(t,10)},predicate:function(e){return"[object Number]"===Object.prototype.toString.call(e)&&(e%1!=0||n.isNegativeZero(e))},represent:function(e,t){var i +if(isNaN(e))switch(t){case"lowercase":return".nan" +case"uppercase":return".NAN" +case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===e)switch(t){case"lowercase":return".inf" +case"uppercase":return".INF" +case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case"lowercase":return"-.inf" +case"uppercase":return"-.INF" +case"camelcase":return"-.Inf"}else if(n.isNegativeZero(e))return"-0.0" +return i=e.toString(10),I.test(i)?i.replace("e",".e"):i},defaultStyle:"lowercase"}),j=b.extend({implicit:[A,v,C,S]}),O=j,T=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),E=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$") +var M=new p("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:function(e){return null!==e&&(null!==T.exec(e)||null!==E.exec(e))},construct:function(e){var t,n,i,r,o,a,l,s,c=0,u=null +if(null===(t=T.exec(e))&&(t=E.exec(e)),null===t)throw new Error("Date resolve error") +if(n=+t[1],i=+t[2]-1,r=+t[3],!t[4])return new Date(Date.UTC(n,i,r)) +if(o=+t[4],a=+t[5],l=+t[6],t[7]){for(c=t[7].slice(0,3);c.length<3;)c+="0" +c=+c}return t[9]&&(u=6e4*(60*+t[10]+ +(t[11]||0)),"-"===t[9]&&(u=-u)),s=new Date(Date.UTC(n,i,r,o,a,l,c)),u&&s.setTime(s.getTime()-u),s},instanceOf:Date,represent:function(e){return e.toISOString()}}) +var L=new p("tag:yaml.org,2002:merge",{kind:"scalar",resolve:function(e){return"<<"===e||null===e}}),N="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r" +var F=new p("tag:yaml.org,2002:binary",{kind:"scalar",resolve:function(e){if(null===e)return!1 +var t,n,i=0,r=e.length,o=N +for(n=0;n64)){if(t<0)return!1 +i+=6}return i%8==0},construct:function(e){var t,n,i=e.replace(/[\r\n=]/g,""),r=i.length,o=N,a=0,l=[] +for(t=0;t>16&255),l.push(a>>8&255),l.push(255&a)),a=a<<6|o.indexOf(i.charAt(t)) +return 0===(n=r%4*6)?(l.push(a>>16&255),l.push(a>>8&255),l.push(255&a)):18===n?(l.push(a>>10&255),l.push(a>>2&255)):12===n&&l.push(a>>4&255),new Uint8Array(l)},predicate:function(e){return"[object Uint8Array]"===Object.prototype.toString.call(e)},represent:function(e){var t,n,i="",r=0,o=e.length,a=N +for(t=0;t>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]),r=(r<<8)+e[t] +return 0===(n=o%3)?(i+=a[r>>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]):2===n?(i+=a[r>>10&63],i+=a[r>>4&63],i+=a[r<<2&63],i+=a[64]):1===n&&(i+=a[r>>2&63],i+=a[r<<4&63],i+=a[64],i+=a[64]),i}}),_=Object.prototype.hasOwnProperty,D=Object.prototype.toString +var q=new p("tag:yaml.org,2002:omap",{kind:"sequence",resolve:function(e){if(null===e)return!0 +var t,n,i,r,o,a=[],l=e +for(t=0,n=l.length;t>10),56320+(e-65536&1023))}for(var ue=new Array(256),pe=new Array(256),fe=0;fe<256;fe++)ue[fe]=se(fe)?1:0,pe[fe]=se(fe) +function de(e,t){this.input=e,this.filename=t.filename||null,this.schema=t.schema||$,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.firstTabInLine=-1,this.documents=[]}function he(e,t){var n={name:e.filename,buffer:e.input.slice(0,-1),position:e.position,line:e.line,column:e.position-e.lineStart} +return n.snippet=s(n),new o(t,n)}function me(e,t){throw he(e,t)}function ge(e,t){e.onWarning&&e.onWarning.call(null,he(e,t))}var ye={YAML:function(e,t,n){var i,r,o +null!==e.version&&me(e,"duplication of %YAML directive"),1!==n.length&&me(e,"YAML directive accepts exactly one argument"),null===(i=/^([0-9]+)\.([0-9]+)$/.exec(n[0]))&&me(e,"ill-formed argument of the YAML directive"),r=parseInt(i[1],10),o=parseInt(i[2],10),1!==r&&me(e,"unacceptable YAML version of the document"),e.version=n[0],e.checkLineBreaks=o<2,1!==o&&2!==o&&ge(e,"unsupported YAML version of the document")},TAG:function(e,t,n){var i,r +2!==n.length&&me(e,"TAG directive accepts exactly two arguments"),i=n[0],r=n[1],ee.test(i)||me(e,"ill-formed tag handle (first argument) of the TAG directive"),B.call(e.tagMap,i)&&me(e,'there is a previously declared suffix for "'+i+'" tag handle'),te.test(r)||me(e,"ill-formed tag prefix (second argument) of the TAG directive") +try{r=decodeURIComponent(r)}catch(o){me(e,"tag prefix is malformed: "+r)}e.tagMap[i]=r}} +function be(e,t,n,i){var r,o,a,l +if(t1&&(e.result+=n.repeat("\n",t-1))}function Ie(e,t){var n,i,r=e.tag,o=e.anchor,a=[],l=!1 +if(-1!==e.firstTabInLine)return!1 +for(null!==e.anchor&&(e.anchorMap[e.anchor]=a),i=e.input.charCodeAt(e.position);0!==i&&(-1!==e.firstTabInLine&&(e.position=e.firstTabInLine,me(e,"tab characters must not be used in indentation")),45===i)&&oe(e.input.charCodeAt(e.position+1));)if(l=!0,e.position++,we(e,!0,-1)&&e.lineIndent<=t)a.push(null),i=e.input.charCodeAt(e.position) +else if(n=e.line,Oe(e,t,H,!1,!0),a.push(e.result),we(e,!0,-1),i=e.input.charCodeAt(e.position),(e.line===n||e.lineIndent>t)&&0!==i)me(e,"bad indentation of a sequence entry") +else if(e.lineIndentt?m=1:e.lineIndent===t?m=0:e.lineIndentt?m=1:e.lineIndent===t?m=0:e.lineIndentt)&&(y&&(a=e.line,l=e.lineStart,s=e.position),Oe(e,t,G,!0,r)&&(y?m=e.result:g=e.result),y||(ve(e,f,d,h,m,g,a,l,s),h=m=g=null),we(e,!0,-1),c=e.input.charCodeAt(e.position)),(e.line===o||e.lineIndent>t)&&0!==c)me(e,"bad indentation of a mapping entry") +else if(e.lineIndent=0))break +0===o?me(e,"bad explicit indentation width of a block scalar; it cannot be less than one"):u?me(e,"repeat of an indentation width identifier"):(p=t+o-1,u=!0)}if(re(a)){do{a=e.input.charCodeAt(++e.position)}while(re(a)) +if(35===a)do{a=e.input.charCodeAt(++e.position)}while(!ie(a)&&0!==a)}for(;0!==a;){for(ke(e),e.lineIndent=0,a=e.input.charCodeAt(e.position);(!u||e.lineIndentp&&(p=e.lineIndent),ie(a))f++ +else{if(e.lineIndent0){for(r=a,o=0;r>0;r--)(a=le(l=e.input.charCodeAt(++e.position)))>=0?o=(o<<4)+a:me(e,"expected hexadecimal character") +e.result+=ce(o),e.position++}else me(e,"unknown escape sequence") +n=i=e.position}else ie(l)?(be(e,n,i,!0),xe(e,we(e,!1,t)),n=i=e.position):e.position===e.lineStart&&Ce(e)?me(e,"unexpected end of the document within a double quoted scalar"):(e.position++,i=e.position)}me(e,"unexpected end of the stream within a double quoted scalar")}(e,d)?y=!0:!function(e){var t,n,i +if(42!==(i=e.input.charCodeAt(e.position)))return!1 +for(i=e.input.charCodeAt(++e.position),t=e.position;0!==i&&!oe(i)&&!ae(i);)i=e.input.charCodeAt(++e.position) +return e.position===t&&me(e,"name of an alias node must contain at least one character"),n=e.input.slice(t,e.position),B.call(e.anchorMap,n)||me(e,'unidentified alias "'+n+'"'),e.result=e.anchorMap[n],we(e,!0,-1),!0}(e)?function(e,t,n){var i,r,o,a,l,s,c,u,p=e.kind,f=e.result +if(oe(u=e.input.charCodeAt(e.position))||ae(u)||35===u||38===u||42===u||33===u||124===u||62===u||39===u||34===u||37===u||64===u||96===u)return!1 +if((63===u||45===u)&&(oe(i=e.input.charCodeAt(e.position+1))||n&&ae(i)))return!1 +for(e.kind="scalar",e.result="",r=o=e.position,a=!1;0!==u;){if(58===u){if(oe(i=e.input.charCodeAt(e.position+1))||n&&ae(i))break}else if(35===u){if(oe(e.input.charCodeAt(e.position-1)))break}else{if(e.position===e.lineStart&&Ce(e)||n&&ae(u))break +if(ie(u)){if(l=e.line,s=e.lineStart,c=e.lineIndent,we(e,!1,-1),e.lineIndent>=t){a=!0,u=e.input.charCodeAt(e.position) +continue}e.position=o,e.line=l,e.lineStart=s,e.lineIndent=c +break}}a&&(be(e,r,o,!1),xe(e,e.line-l),r=o=e.position,a=!1),re(u)||(o=e.position+1),u=e.input.charCodeAt(++e.position)}return be(e,r,o,!1),!!e.result||(e.kind=p,e.result=f,!1)}(e,d,K===i)&&(y=!0,null===e.tag&&(e.tag="?")):(y=!0,null===e.tag&&null===e.anchor||me(e,"alias node should not have any properties")),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):0===m&&(y=s&&Ie(e,h))),null===e.tag)null!==e.anchor&&(e.anchorMap[e.anchor]=e.result) +else if("?"===e.tag){for(null!==e.result&&"scalar"!==e.kind&&me(e,'unacceptable node kind for ! tag; it should be "scalar", not "'+e.kind+'"'),c=0,u=e.implicitTypes.length;c"),null!==e.result&&f.kind!==e.kind&&me(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+f.kind+'", not "'+e.kind+'"'),f.resolve(e.result,e.tag)?(e.result=f.construct(e.result,e.tag),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):me(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")}return null!==e.listener&&e.listener("close",e),null!==e.tag||null!==e.anchor||y}function Te(e){var t,n,i,r,o=e.position,a=!1 +for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap=Object.create(null),e.anchorMap=Object.create(null);0!==(r=e.input.charCodeAt(e.position))&&(we(e,!0,-1),r=e.input.charCodeAt(e.position),!(e.lineIndent>0||37!==r));){for(a=!0,r=e.input.charCodeAt(++e.position),t=e.position;0!==r&&!oe(r);)r=e.input.charCodeAt(++e.position) +for(i=[],(n=e.input.slice(t,e.position)).length<1&&me(e,"directive name must not be less than one character in length");0!==r;){for(;re(r);)r=e.input.charCodeAt(++e.position) +if(35===r){do{r=e.input.charCodeAt(++e.position)}while(0!==r&&!ie(r)) +break}if(ie(r))break +for(t=e.position;0!==r&&!oe(r);)r=e.input.charCodeAt(++e.position) +i.push(e.input.slice(t,e.position))}0!==r&&ke(e),B.call(ye,n)?ye[n](e,n,i):ge(e,'unknown document directive "'+n+'"')}we(e,!0,-1),0===e.lineIndent&&45===e.input.charCodeAt(e.position)&&45===e.input.charCodeAt(e.position+1)&&45===e.input.charCodeAt(e.position+2)?(e.position+=3,we(e,!0,-1)):a&&me(e,"directives end mark is expected"),Oe(e,e.lineIndent-1,G,!1,!0),we(e,!0,-1),e.checkLineBreaks&&Q.test(e.input.slice(o,e.position))&&ge(e,"non-ASCII line breaks are interpreted as content"),e.documents.push(e.result),e.position===e.lineStart&&Ce(e)?46===e.input.charCodeAt(e.position)&&(e.position+=3,we(e,!0,-1)):e.position=55296&&i<=56319&&t+1=56320&&n<=57343?1024*(i-55296)+n-56320+65536:i}function At(e){return/^\n* /.test(e)}var vt=1,kt=2,wt=3,Ct=4,xt=5 +function It(e,t,n,i,r,o,a,l){var s,c,u=0,p=null,f=!1,d=!1,h=-1!==i,m=-1,g=mt(c=bt(e,0))&&c!==Fe&&!ht(c)&&c!==Ge&&c!==Je&&c!==Ve&&c!==He&&c!==Xe&&c!==et&&c!==nt&&c!==rt&&c!==Re&&c!==Be&&c!==We&&c!==Ye&&c!==it&&c!==Ze&&c!==ze&&c!==Ke&&c!==Pe&&c!==$e&&c!==Qe&&c!==tt&&function(e){return!ht(e)&&e!==Ve}(bt(e,e.length-1)) +if(t||a)for(s=0;s=65536?s+=2:s++){if(!mt(u=bt(e,s)))return xt +g=g&&yt(u,p,l),p=u}else{for(s=0;s=65536?s+=2:s++){if((u=bt(e,s))===De)f=!0,h&&(d=d||s-m-1>i&&" "!==e[m+1],m=s) +else if(!mt(u))return xt +g=g&&yt(u,p,l),p=u}d=d||h&&s-m-1>i&&" "!==e[m+1]}return f||d?n>9&&At(e)?xt:a?o===ut?xt:kt:d?Ct:wt:!g||a||r(e)?o===ut?xt:kt:vt}function St(e,t,n,i,r){e.dump=function(){if(0===t.length)return e.quotingType===ut?'""':"''" +if(!e.noCompatMode&&(-1!==at.indexOf(t)||lt.test(t)))return e.quotingType===ut?'"'+t+'"':"'"+t+"'" +var a=e.indent*Math.max(1,n),l=-1===e.lineWidth?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-a),s=i||e.flowLevel>-1&&n>=e.flowLevel +switch(It(t,s,e.indent,l,(function(t){return function(e,t){var n,i +for(n=0,i=e.implicitTypes.length;n"+jt(t,e.indent)+Ot(ft(function(e,t){var n,i,r=/(\n+)([^\n]*)/g,o=(l=e.indexOf("\n"),l=-1!==l?l:e.length,r.lastIndex=l,Tt(e.slice(0,l),t)),a="\n"===e[0]||" "===e[0] +var l +for(;i=r.exec(e);){var s=i[1],c=i[2] +n=" "===c[0],o+=s+(a||n||""===c?"":"\n")+Tt(c,t),a=n}return o}(t,l),a)) +case xt:return'"'+function(e){for(var t,n="",i=0,r=0;r=65536?r+=2:r++)i=bt(e,r),!(t=ot[i])&&mt(i)?(n+=e[r],i>=65536&&(n+=e[r+1])):n+=t||st(i) +return n}(t)+'"' +default:throw new o("impossible error: invalid scalar style")}}()}function jt(e,t){var n=At(e)?String(t):"",i="\n"===e[e.length-1] +return n+(i&&("\n"===e[e.length-2]||"\n"===e)?"+":i?"":"-")+"\n"}function Ot(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}function Tt(e,t){if(""===e||" "===e[0])return e +for(var n,i,r=/ [^ ]/g,o=0,a=0,l=0,s="";n=r.exec(e);)(l=n.index)-o>t&&(i=a>o?a:l,s+="\n"+e.slice(o,i),o=i+1),a=l +return s+="\n",e.length-o>t&&a>o?s+=e.slice(o,a)+"\n"+e.slice(a+1):s+=e.slice(o),s.slice(1)}function Et(e,t,n,i){var r,o,a,l="",s=e.tag +for(r=0,o=n.length;r tag resolver accepts not "'+c+'" style') +i=s.represent[c](t,c)}e.dump=i}return!0}return!1}function Lt(e,t,n,i,r,a,l){e.tag=null,e.dump=n,Mt(e,n,!1)||Mt(e,n,!0) +var s,c=Le.call(e.dump),u=i +i&&(i=e.flowLevel<0||e.flowLevel>t) +var p,f,d="[object Object]"===c||"[object Array]"===c +if(d&&(f=-1!==(p=e.duplicates.indexOf(n))),(null!==e.tag&&"?"!==e.tag||f||2!==e.indent&&t>0)&&(r=!1),f&&e.usedDuplicates[p])e.dump="*ref_"+p +else{if(d&&f&&!e.usedDuplicates[p]&&(e.usedDuplicates[p]=!0),"[object Object]"===c)i&&0!==Object.keys(e.dump).length?(function(e,t,n,i){var r,a,l,s,c,u,p="",f=e.tag,d=Object.keys(n) +if(!0===e.sortKeys)d.sort() +else if("function"==typeof e.sortKeys)d.sort(e.sortKeys) +else if(e.sortKeys)throw new o("sortKeys must be a boolean or a function") +for(r=0,a=d.length;r1024)&&(e.dump&&De===e.dump.charCodeAt(0)?u+="?":u+="? "),u+=e.dump,c&&(u+=dt(e,t)),Lt(e,t+1,s,!0,c)&&(e.dump&&De===e.dump.charCodeAt(0)?u+=":":u+=": ",p+=u+=e.dump)) +e.tag=f,e.dump=p||"{}"}(e,t,e.dump,r),f&&(e.dump="&ref_"+p+e.dump)):(function(e,t,n){var i,r,o,a,l,s="",c=e.tag,u=Object.keys(n) +for(i=0,r=u.length;i1024&&(l+="? "),l+=e.dump+(e.condenseFlow?'"':"")+":"+(e.condenseFlow?"":" "),Lt(e,t,a,!1,!1)&&(s+=l+=e.dump)) +e.tag=c,e.dump="{"+s+"}"}(e,t,e.dump),f&&(e.dump="&ref_"+p+" "+e.dump)) +else if("[object Array]"===c)i&&0!==e.dump.length?(e.noArrayIndent&&!l&&t>0?Et(e,t-1,e.dump,r):Et(e,t,e.dump,r),f&&(e.dump="&ref_"+p+e.dump)):(function(e,t,n){var i,r,o,a="",l=e.tag +for(i=0,r=n.length;i",e.dump=s+" "+e.dump)}return!0}function Nt(e,t){var n,i,r=[],o=[] +for(Ft(e,r,o),n=0,i=o.length;nn.keyCol)return t.skipToEnd(),"string" +if(n.literal&&(n.literal=!1),t.sol()){if(n.keyCol=0,n.pair=!1,n.pairStart=!1,t.match(/---/))return"def" +if(t.match(/\.\.\./))return"def" +if(t.match(/\s*-\s+/))return"meta"}if(t.match(/^(\{|\}|\[|\])/))return"{"==i?n.inlinePairs++:"}"==i?n.inlinePairs--:"["==i?n.inlineList++:n.inlineList--,"meta" +if(n.inlineList>0&&!r&&","==i)return t.next(),"meta" +if(n.inlinePairs>0&&!r&&","==i)return n.keyCol=0,n.pair=!1,n.pairStart=!1,t.next(),"meta" +if(n.pairStart){if(t.match(/^\s*(\||\>)\s*/))return n.literal=!0,"meta" +if(t.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i))return"variable-2" +if(0==n.inlinePairs&&t.match(/^\s*-?[0-9\.\,]+\s?$/))return"number" +if(n.inlinePairs>0&&t.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/))return"number" +if(t.match(e))return"keyword"}return!n.pair&&t.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)?(n.pair=!0,n.keyCol=t.indentation(),"atom"):n.pair&&t.match(/^:\s*/)?(n.pairStart=!0,"meta"):(n.pairStart=!1,n.escaped="\\"==i,t.next(),null)},startState:function(){return{pair:!1,pairStart:!1,keyCol:0,inlinePairs:0,inlineList:0,literal:!1,escaped:!1}}}})),e.defineMIME("text/x-yaml","yaml")})) diff --git a/agent/uiserver/dist/assets/consul-acls/routes-0c01f9c463b81fdc3929288f31c23040.js b/agent/uiserver/dist/assets/consul-acls/routes-e55feae2bb3c7d46658daac388c6d28b.js similarity index 100% rename from agent/uiserver/dist/assets/consul-acls/routes-0c01f9c463b81fdc3929288f31c23040.js rename to agent/uiserver/dist/assets/consul-acls/routes-e55feae2bb3c7d46658daac388c6d28b.js diff --git a/agent/uiserver/dist/assets/consul-acls/services-70b9e635f1e8e9a316e3773fccadb7c7.js b/agent/uiserver/dist/assets/consul-acls/services-1c7ca8671626e96e6ea4d8652235a7ed.js similarity index 100% rename from agent/uiserver/dist/assets/consul-acls/services-70b9e635f1e8e9a316e3773fccadb7c7.js rename to agent/uiserver/dist/assets/consul-acls/services-1c7ca8671626e96e6ea4d8652235a7ed.js diff --git a/agent/uiserver/dist/assets/consul-hcp/routes-282630d2b2c8bf766b7e0d4f512828cc.js b/agent/uiserver/dist/assets/consul-hcp/routes-282630d2b2c8bf766b7e0d4f512828cc.js deleted file mode 100644 index 703c18772062..000000000000 --- a/agent/uiserver/dist/assets/consul-hcp/routes-282630d2b2c8bf766b7e0d4f512828cc.js +++ /dev/null @@ -1 +0,0 @@ -((e,t=("undefined"!=typeof document?document.currentScript.dataset:module.exports))=>{t.routes=JSON.stringify(e)})({dc:{show:null}}) diff --git a/agent/uiserver/dist/assets/consul-hcp/services-51af43ae095119987dadf6f2392a59b3.js b/agent/uiserver/dist/assets/consul-hcp/services-51af43ae095119987dadf6f2392a59b3.js deleted file mode 100644 index dc9973925465..000000000000 --- a/agent/uiserver/dist/assets/consul-hcp/services-51af43ae095119987dadf6f2392a59b3.js +++ /dev/null @@ -1 +0,0 @@ -((e,o=("undefined"!=typeof document?document.currentScript.dataset:module.exports))=>{o.services=JSON.stringify(e)})({"component:consul/hcp/home":{class:"consul-ui/components/consul/hcp/home"}}) diff --git a/agent/uiserver/dist/assets/consul-lock-sessions/routes-7718d309039e9f8b3b185656b6dd7f05.js b/agent/uiserver/dist/assets/consul-lock-sessions/routes-74df2f8452a25372c7dbaf121357ff4e.js similarity index 100% rename from agent/uiserver/dist/assets/consul-lock-sessions/routes-7718d309039e9f8b3b185656b6dd7f05.js rename to agent/uiserver/dist/assets/consul-lock-sessions/routes-74df2f8452a25372c7dbaf121357ff4e.js diff --git a/agent/uiserver/dist/assets/consul-lock-sessions/services-70b9e635f1e8e9a316e3773fccadb7c7.js b/agent/uiserver/dist/assets/consul-lock-sessions/services-1c7ca8671626e96e6ea4d8652235a7ed.js similarity index 100% rename from agent/uiserver/dist/assets/consul-lock-sessions/services-70b9e635f1e8e9a316e3773fccadb7c7.js rename to agent/uiserver/dist/assets/consul-lock-sessions/services-1c7ca8671626e96e6ea4d8652235a7ed.js diff --git a/agent/uiserver/dist/assets/consul-nspaces/routes-71c32de6a0307211d1299dac7688bfbf.js b/agent/uiserver/dist/assets/consul-nspaces/routes-63906dec24f0e6ddffea3b1604011f6a.js similarity index 100% rename from agent/uiserver/dist/assets/consul-nspaces/routes-71c32de6a0307211d1299dac7688bfbf.js rename to agent/uiserver/dist/assets/consul-nspaces/routes-63906dec24f0e6ddffea3b1604011f6a.js diff --git a/agent/uiserver/dist/assets/consul-nspaces/services-70b9e635f1e8e9a316e3773fccadb7c7.js b/agent/uiserver/dist/assets/consul-nspaces/services-1c7ca8671626e96e6ea4d8652235a7ed.js similarity index 100% rename from agent/uiserver/dist/assets/consul-nspaces/services-70b9e635f1e8e9a316e3773fccadb7c7.js rename to agent/uiserver/dist/assets/consul-nspaces/services-1c7ca8671626e96e6ea4d8652235a7ed.js diff --git a/agent/uiserver/dist/assets/consul-partitions/routes-1bdd3b7ae99c7d7ce0425b2412f10d5e.js b/agent/uiserver/dist/assets/consul-partitions/routes-afd0605ddd15bb1b9f6d29ff9c3520a6.js similarity index 100% rename from agent/uiserver/dist/assets/consul-partitions/routes-1bdd3b7ae99c7d7ce0425b2412f10d5e.js rename to agent/uiserver/dist/assets/consul-partitions/routes-afd0605ddd15bb1b9f6d29ff9c3520a6.js diff --git a/agent/uiserver/dist/assets/consul-partitions/services-1a3b6937a8bc5f6e68df884b1650eaf0.js b/agent/uiserver/dist/assets/consul-partitions/services-aff2ecb993421b18439e13717fc0d5b9.js similarity index 100% rename from agent/uiserver/dist/assets/consul-partitions/services-1a3b6937a8bc5f6e68df884b1650eaf0.js rename to agent/uiserver/dist/assets/consul-partitions/services-aff2ecb993421b18439e13717fc0d5b9.js diff --git a/agent/uiserver/dist/assets/consul-peerings/routes-989d6de4b58a54c8638e37694240f29a.js b/agent/uiserver/dist/assets/consul-peerings/routes-3d7de4222e3d59c0731f3c185920e3ad.js similarity index 100% rename from agent/uiserver/dist/assets/consul-peerings/routes-989d6de4b58a54c8638e37694240f29a.js rename to agent/uiserver/dist/assets/consul-peerings/routes-3d7de4222e3d59c0731f3c185920e3ad.js diff --git a/agent/uiserver/dist/assets/consul-peerings/services-e5a754eca7f3fbb406035f10b8dfbb77.js b/agent/uiserver/dist/assets/consul-peerings/services-2f4bca619d25ae9a31801359d4ed18a8.js similarity index 100% rename from agent/uiserver/dist/assets/consul-peerings/services-e5a754eca7f3fbb406035f10b8dfbb77.js rename to agent/uiserver/dist/assets/consul-peerings/services-2f4bca619d25ae9a31801359d4ed18a8.js diff --git a/agent/uiserver/dist/assets/consul-ui-6998e44e8a8ea2039fda574ce1ac1be5.css b/agent/uiserver/dist/assets/consul-ui-6998e44e8a8ea2039fda574ce1ac1be5.css new file mode 100644 index 000000000000..ce065de1b5f6 --- /dev/null +++ b/agent/uiserver/dist/assets/consul-ui-6998e44e8a8ea2039fda574ce1ac1be5.css @@ -0,0 +1,2 @@ +@charset "UTF-8";/*! tailwindcss v3.2.7 | MIT License | https://tailwindcss.com + */.hds-table,table{border-spacing:0}input[type=checkbox],input[type=radio],progress,sub,sup{vertical-align:baseline}.hover\:scale-125:hover,.scale-100,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.ease-in-out,.transition{transition-timing-function:cubic-bezier(.4,0,.2,1)}*,::after,::before{border-width:0;border-style:solid;border-color:currentColor}html{line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-feature-settings:normal}a,hr{color:inherit}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto}[hidden]{display:none}*,::after,::backdrop,::before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scroll-snap-strictness:proximity;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.hds-side-nav,.sticky{position:sticky}.bottom-0{bottom:0}.isolate{isolation:isolate}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-4{margin-left:1rem}.mr-0{margin-right:0}.mr-0\.5{margin-right:.125rem}.mr-1{margin-right:.25rem}.mr-1\.5{margin-right:.375rem}.mr-2{margin-right:.5rem}.mr-2\.5{margin-right:.625rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.contents{display:contents}.hidden{display:none}.h-12{height:3rem}.h-16{height:4rem}.h-24{height:6rem}.h-4{height:1rem}.h-48{height:12rem}.h-8{height:2rem}.h-full{height:100%}.h-screen{height:100vh}.\!w-80{width:20rem!important}.w-24{width:6rem}.w-4{width:1rem}.w-8{width:2rem}.w-full{width:100%}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.flex-col,.hds-accordion{flex-direction:column}.scale-100{--tw-scale-x:1;--tw-scale-y:1}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-nowrap{flex-wrap:nowrap}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.space-x-12>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(3rem * var(--tw-space-x-reverse));margin-left:calc(3rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.overflow-x-auto{overflow-x:auto}.overflow-y-scroll{overflow-y:scroll}.hds-breadcrumb__text,.hds-card__container--overflow-hidden,.truncate{overflow:hidden}.truncate{text-overflow:ellipsis;white-space:nowrap}.rounded{border-radius:.25rem}.border{border-width:1px}.p-6{padding:1.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize,.type-source.popover-select li:not(.partition) button{text-transform:capitalize}.underline{text-decoration-line:underline}.opacity-0{opacity:0}.shadow{--tw-shadow:0 1px 3px 0 rgb(0 0 0 / 0.1),0 1px 2px -1px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hds-elevation-inset,.hds-form-checkbox:not(:checked,:indeterminate){box-shadow:var(--token-elevation-inset-box-shadow)}.outline{outline-style:solid}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-duration:150ms}.consul-surface-nav{background:var(--token-color-palette-neutral-700)}:root{--token-color-palette-blue-500:#1c345f;--token-color-palette-blue-400:#0046d1;--token-color-palette-blue-300:#0c56e9;--token-color-palette-blue-200:#1060ff;--token-color-palette-blue-100:#cce3fe;--token-color-palette-blue-50:#f2f8ff;--token-color-palette-purple-500:#42215b;--token-color-palette-purple-400:#7b00db;--token-color-palette-purple-300:#911ced;--token-color-palette-purple-200:#a737ff;--token-color-palette-purple-100:#ead2fe;--token-color-palette-purple-50:#f9f2ff;--token-color-palette-green-500:#054220;--token-color-palette-green-400:#006619;--token-color-palette-green-300:#00781e;--token-color-palette-green-200:#008a22;--token-color-palette-green-100:#cceeda;--token-color-palette-green-50:#f2fbf6;--token-color-palette-amber-500:#542800;--token-color-palette-amber-400:#803d00;--token-color-palette-amber-300:#9e4b00;--token-color-palette-amber-200:#bb5a00;--token-color-palette-amber-100:#fbeabf;--token-color-palette-amber-50:#fff9e8;--token-color-palette-red-500:#51130a;--token-color-palette-red-400:#940004;--token-color-palette-red-300:#c00005;--token-color-palette-red-200:#e52228;--token-color-palette-red-100:#fbd4d4;--token-color-palette-red-50:#fff5f5;--token-color-palette-neutral-700:#0c0c0e;--token-color-palette-neutral-600:#3b3d45;--token-color-palette-neutral-500:#656a76;--token-color-palette-neutral-400:#8c909c;--token-color-palette-neutral-300:#c2c5cb;--token-color-palette-neutral-200:#dedfe3;--token-color-palette-neutral-100:#f1f2f3;--token-color-palette-neutral-50:#fafafa;--token-color-palette-neutral-0:#ffffff;--token-color-palette-alpha-300:#3b3d4566;--token-color-palette-alpha-200:#656a7633;--token-color-palette-alpha-100:#656a761a;--token-color-border-primary:#656a7633;--token-color-border-faint:#656a761a;--token-color-border-strong:#3b3d4566;--token-color-border-action:#cce3fe;--token-color-border-highlight:#ead2fe;--token-color-border-success:#cceeda;--token-color-border-warning:#fbeabf;--token-color-border-critical:#fbd4d4;--token-color-focus-action-internal:#0c56e9;--token-color-focus-action-external:#5990ff;--token-color-focus-critical-internal:#c00005;--token-color-focus-critical-external:#dd7578;--token-color-foreground-strong:#0c0c0e;--token-color-foreground-primary:#3b3d45;--token-color-foreground-faint:#656a76;--token-color-foreground-high-contrast:#ffffff;--token-color-foreground-disabled:#8c909c;--token-color-foreground-action:#1060ff;--token-color-foreground-action-hover:#0c56e9;--token-color-foreground-action-active:#0046d1;--token-color-foreground-highlight:#a737ff;--token-color-foreground-highlight-on-surface:#911ced;--token-color-foreground-highlight-high-contrast:#42215b;--token-color-foreground-success:#008a22;--token-color-foreground-success-on-surface:#00781e;--token-color-foreground-success-high-contrast:#054220;--token-color-foreground-warning:#bb5a00;--token-color-foreground-warning-on-surface:#9e4b00;--token-color-foreground-warning-high-contrast:#542800;--token-color-foreground-critical:#e52228;--token-color-foreground-critical-on-surface:#c00005;--token-color-foreground-critical-high-contrast:#51130a;--token-color-page-primary:#ffffff;--token-color-page-faint:#fafafa;--token-color-surface-primary:#ffffff;--token-color-surface-faint:#fafafa;--token-color-surface-strong:#f1f2f3;--token-color-surface-interactive:#ffffff;--token-color-surface-interactive-hover:#f1f2f3;--token-color-surface-interactive-active:#dedfe3;--token-color-surface-interactive-disabled:#fafafa;--token-color-surface-action:#f2f8ff;--token-color-surface-highlight:#f9f2ff;--token-color-surface-success:#f2fbf6;--token-color-surface-warning:#fff9e8;--token-color-surface-critical:#fff5f5;--token-color-hashicorp-brand:#000000;--token-color-boundary-brand:#f24c53;--token-color-boundary-foreground:#cf2d32;--token-color-boundary-surface:#ffecec;--token-color-boundary-border:#fbd7d8;--token-color-boundary-gradient-primary-start:#f97076;--token-color-boundary-gradient-primary-stop:#db363b;--token-color-boundary-gradient-faint-start:#fffafa;--token-color-boundary-gradient-faint-stop:#ffecec;--token-color-consul-brand:#e03875;--token-color-consul-foreground:#d01c5b;--token-color-consul-surface:#ffe9f1;--token-color-consul-border:#ffcede;--token-color-consul-gradient-primary-start:#ff99be;--token-color-consul-gradient-primary-stop:#da306e;--token-color-consul-gradient-faint-start:#fff9fb;--token-color-consul-gradient-faint-stop:#ffe9f1;--token-color-hcp-brand:#000000;--token-color-nomad-brand:#06d092;--token-color-nomad-foreground:#008661;--token-color-nomad-surface:#d3fdeb;--token-color-nomad-border:#bff3dd;--token-color-nomad-gradient-primary-start:#bff3dd;--token-color-nomad-gradient-primary-stop:#60dea9;--token-color-nomad-gradient-faint-start:#f3fff9;--token-color-nomad-gradient-faint-stop:#d3fdeb;--token-color-packer-brand:#02a8ef;--token-color-packer-foreground:#007eb4;--token-color-packer-surface:#d4f2ff;--token-color-packer-border:#b4e4ff;--token-color-packer-gradient-primary-start:#b4e4ff;--token-color-packer-gradient-primary-stop:#63d0ff;--token-color-packer-gradient-faint-start:#f3fcff;--token-color-packer-gradient-faint-stop:#d4f2ff;--token-color-terraform-brand:#7b42bc;--token-color-terraform-foreground:#773cb4;--token-color-terraform-surface:#f4ecff;--token-color-terraform-border:#ebdbfc;--token-color-terraform-gradient-primary-start:#bb8deb;--token-color-terraform-gradient-primary-stop:#844fba;--token-color-terraform-gradient-faint-start:#fcfaff;--token-color-terraform-gradient-faint-stop:#f4ecff;--token-color-vagrant-brand:#1868f2;--token-color-vagrant-foreground:#1c61d8;--token-color-vagrant-surface:#d6ebff;--token-color-vagrant-border:#c7dbfc;--token-color-vagrant-gradient-primary-start:#c7dbfc;--token-color-vagrant-gradient-primary-stop:#7dadff;--token-color-vagrant-gradient-faint-start:#f4faff;--token-color-vagrant-gradient-faint-stop:#d6ebff;--token-color-vault-secrets-brand:#ffd814;--token-color-vault-secrets-brand-alt:#000000;--token-color-vault-secrets-foreground:#9a6f00;--token-color-vault-secrets-surface:#fff9cf;--token-color-vault-secrets-border:#feec7b;--token-color-vault-secrets-gradient-primary-start:#feec7b;--token-color-vault-secrets-gradient-primary-stop:#ffe543;--token-color-vault-secrets-gradient-faint-start:#fffdf2;--token-color-vault-secrets-gradient-faint-stop:#fff9cf;--token-color-vault-brand:#ffd814;--token-color-vault-brand-alt:#000000;--token-color-vault-foreground:#9a6f00;--token-color-vault-surface:#fff9cf;--token-color-vault-border:#feec7b;--token-color-vault-gradient-primary-start:#feec7b;--token-color-vault-gradient-primary-stop:#ffe543;--token-color-vault-gradient-faint-start:#fffdf2;--token-color-vault-gradient-faint-stop:#fff9cf;--token-color-waypoint-brand:#14c6cb;--token-color-waypoint-foreground:#008196;--token-color-waypoint-surface:#e0fcff;--token-color-waypoint-border:#cbf1f3;--token-color-waypoint-gradient-primary-start:#cbf1f3;--token-color-waypoint-gradient-primary-stop:#62d4dc;--token-color-waypoint-gradient-faint-start:#f6feff;--token-color-waypoint-gradient-faint-stop:#e0fcff;--token-elevation-inset-box-shadow:inset 0px 1px 2px 1px #656a761a;--token-elevation-low-box-shadow:0px 1px 1px 0px #656a760d,0px 2px 2px 0px #656a760d;--token-elevation-mid-box-shadow:0px 2px 3px 0px #656a761a,0px 8px 16px -10px #656a7633;--token-elevation-high-box-shadow:0px 2px 3px 0px #656a7626,0px 16px 16px -10px #656a7633;--token-elevation-higher-box-shadow:0px 2px 3px 0px #656a761a,0px 12px 28px 0px #656a7640;--token-elevation-overlay-box-shadow:0px 2px 3px 0px #3b3d4540,0px 12px 24px 0px #3b3d4559;--token-surface-inset-box-shadow:inset 0 0 0 1px #656a764d,inset 0px 1px 2px 1px #656a761a;--token-surface-base-box-shadow:0 0 0 1px #656a7633;--token-surface-low-box-shadow:0 0 0 1px #656a7626,0px 1px 1px 0px #656a760d,0px 2px 2px 0px #656a760d;--token-surface-mid-box-shadow:0 0 0 1px #656a7626,0px 2px 3px 0px #656a761a,0px 8px 16px -10px #656a7633;--token-surface-high-box-shadow:0 0 0 1px #656a7640,0px 2px 3px 0px #656a7626,0px 16px 16px -10px #656a7633;--token-surface-higher-box-shadow:0 0 0 1px #656a7633,0px 2px 3px 0px #656a761a,0px 12px 28px 0px #656a7640;--token-surface-overlay-box-shadow:0 0 0 1px #3b3d4540,0px 2px 3px 0px #3b3d4540,0px 12px 24px 0px #3b3d4559;--token-focus-ring-action-box-shadow:inset 0 0 0 1px #0c56e9,0 0 0 3px #5990ff;--token-focus-ring-critical-box-shadow:inset 0 0 0 1px #c00005,0 0 0 3px #dd7578;--token-form-label-color:#0c0c0e;--token-form-legend-color:#0c0c0e;--token-form-helper-text-color:#656a76;--token-form-indicator-optional-color:#656a76;--token-form-error-color:#c00005;--token-form-error-icon-size:14px;--token-form-checkbox-size:16px;--token-form-checkbox-border-radius:3px;--token-form-checkbox-border-width:1px;--token-form-checkbox-background-image-size:12px;--token-form-checkbox-background-image-data-url:url("data:image/svg+xml,%3csvg viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M9.78033 3.21967C10.0732 3.51256 10.0732 3.98744 9.78033 4.28033L5.28033 8.78033C4.98744 9.07322 4.51256 9.07322 4.21967 8.78033L2.21967 6.78033C1.92678 6.48744 1.92678 6.01256 2.21967 5.71967C2.51256 5.42678 2.98744 5.42678 3.28033 5.71967L4.75 7.18934L8.71967 3.21967C9.01256 2.92678 9.48744 2.92678 9.78033 3.21967Z' fill='%23FFF'/%3e%3c/svg%3e");--token-form-checkbox-background-image-data-url-indeterminate:url("data:image/svg+xml,%3csvg viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='m2.03125,6a0.66146,0.75 0 0 1 0.66146,-0.75l6.61458,0a0.66146,0.75 0 0 1 0,1.5l-6.61458,0a0.66146,0.75 0 0 1 -0.66146,-0.75z' fill='%23FFF'/%3e%3c/svg%3e");--token-form-checkbox-background-image-data-url-disabled:url("data:image/svg+xml,%3csvg viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M9.78033 3.21967C10.0732 3.51256 10.0732 3.98744 9.78033 4.28033L5.28033 8.78033C4.98744 9.07322 4.51256 9.07322 4.21967 8.78033L2.21967 6.78033C1.92678 6.48744 1.92678 6.01256 2.21967 5.71967C2.51256 5.42678 2.98744 5.42678 3.28033 5.71967L4.75 7.18934L8.71967 3.21967C9.01256 2.92678 9.48744 2.92678 9.78033 3.21967Z' fill='%238C909C'/%3e%3c/svg%3e");--token-form-checkbox-background-image-data-url-indeterminate-disabled:url("data:image/svg+xml,%3csvg viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='m2.03125,6a0.66146,0.75 0 0 1 0.66146,-0.75l6.61458,0a0.66146,0.75 0 0 1 0,1.5l-6.61458,0a0.66146,0.75 0 0 1 -0.66146,-0.75z' fill='%238C909C'/%3e%3c/svg%3e");--token-form-control-base-foreground-value-color:#0c0c0e;--token-form-control-base-foreground-placeholder-color:#656a76;--token-form-control-base-surface-color-default:#ffffff;--token-form-control-base-surface-color-hover:#f1f2f3;--token-form-control-base-border-color-default:#8c909c;--token-form-control-base-border-color-hover:#656a76;--token-form-control-checked-foreground-color:#ffffff;--token-form-control-checked-surface-color-default:#1060ff;--token-form-control-checked-surface-color-hover:#0c56e9;--token-form-control-checked-border-color-default:#0c56e9;--token-form-control-checked-border-color-hover:#0046d1;--token-form-control-invalid-border-color-default:#c00005;--token-form-control-invalid-border-color-hover:#940004;--token-form-control-readonly-foreground-color:#3b3d45;--token-form-control-readonly-surface-color:#f1f2f3;--token-form-control-readonly-border-color:#656a761a;--token-form-control-disabled-foreground-color:#8c909c;--token-form-control-disabled-surface-color:#fafafa;--token-form-control-disabled-border-color:#656a7633;--token-form-control-padding:7px;--token-form-control-border-radius:5px;--token-form-control-border-width:1px;--token-form-radio-size:16px;--token-form-radio-border-width:1px;--token-form-radio-background-image-size:12px;--token-form-radio-background-image-data-url:url("data:image/svg+xml,%3csvg width='12' height='12' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='6' cy='6' r='2.5' fill='%23ffffff'/%3e%3c/svg%3e");--token-form-radio-background-image-data-url-disabled:url("data:image/svg+xml,%3csvg width='12' height='12' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='6' cy='6' r='2.5' fill='%238C909C'/%3e%3c/svg%3e");--token-form-radiocard-group-gap:16px;--token-form-radiocard-border-width:1px;--token-form-radiocard-border-radius:6px;--token-form-radiocard-content-padding:24px;--token-form-radiocard-control-padding:8px;--token-form-radiocard-transition-duration:0.2s;--token-form-select-background-image-size:16px;--token-form-select-background-image-position-right-x:7px;--token-form-select-background-image-position-top-y:9px;--token-form-select-background-image-data-url:url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.55 2.24a.75.75 0 0 0-1.1 0L4.2 5.74a.75.75 0 1 0 1.1 1.02L8 3.852l2.7 2.908a.75.75 0 1 0 1.1-1.02l-3.25-3.5Zm-1.1 11.52a.75.75 0 0 0 1.1 0l3.25-3.5a.75.75 0 1 0-1.1-1.02L8 12.148 5.3 9.24a.75.75 0 0 0-1.1 1.02l3.25 3.5Z' fill='%23656A76'/%3E%3C/svg%3E");--token-form-select-background-image-data-url-disabled:url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.55 2.24a.75.75 0 0 0-1.1 0L4.2 5.74a.75.75 0 1 0 1.1 1.02L8 3.852l2.7 2.908a.75.75 0 1 0 1.1-1.02l-3.25-3.5Zm-1.1 11.52a.75.75 0 0 0 1.1 0l3.25-3.5a.75.75 0 1 0-1.1-1.02L8 12.148 5.3 9.24a.75.75 0 0 0-1.1 1.02l3.25 3.5Z' fill='%238C909C'/%3E%3C/svg%3E");--token-form-text-input-background-image-size:16px;--token-form-text-input-background-image-position-x:7px;--token-form-text-input-background-image-data-url-date:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M11.5.75a.75.75 0 00-1.5 0V1H6V.75a.75.75 0 00-1.5 0V1H3.25A2.25 2.25 0 001 3.25v9.5A2.25 2.25 0 003.25 15h9.5A2.25 2.25 0 0015 12.75v-9.5A2.25 2.25 0 0012.75 1H11.5V.75zm-7 2.5V2.5H3.25a.75.75 0 00-.75.75V5h11V3.25a.75.75 0 00-.75-.75H11.5v.75a.75.75 0 01-1.5 0V2.5H6v.75a.75.75 0 01-1.5 0zm9 3.25h-11v6.25c0 .414.336.75.75.75h9.5a.75.75 0 00.75-.75V6.5z' fill-rule='evenodd' clip-rule='evenodd' fill='%233B3D45'/%3e%3c/svg%3e");--token-form-text-input-background-image-data-url-time:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3e%3cg fill='%233B3D45'%3e%3cpath d='M8.5 3.75a.75.75 0 00-1.5 0V8c0 .284.16.544.415.67l2.5 1.25a.75.75 0 10.67-1.34L8.5 7.535V3.75z'/%3e%3cpath d='M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z' fill-rule='evenodd' clip-rule='evenodd'/%3e%3c/g%3e%3c/svg%3e");--token-form-text-input-background-image-data-url-search:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3e%3cg fill='%23656A76'%3e%3cpath d='M7.25 2a5.25 5.25 0 103.144 9.455l2.326 2.325a.75.75 0 101.06-1.06l-2.325-2.326A5.25 5.25 0 007.25 2zM3.5 7.25a3.75 3.75 0 117.5 0 3.75 3.75 0 01-7.5 0z' fill-rule='evenodd' clip-rule='evenodd'/%3e%3c/g%3e%3c/svg%3e");--token-form-text-input-background-image-data-url-search-cancel:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.78 4.28a.75.75 0 00-1.06-1.06L8 6.94 4.28 3.22a.75.75 0 00-1.06 1.06L6.94 8l-3.72 3.72a.75.75 0 101.06 1.06L8 9.06l3.72 3.72a.75.75 0 101.06-1.06L9.06 8l3.72-3.72z'/%3e%3c/svg%3e");--token-form-text-input-background-image-data-url-search-loading:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' %3e%3cg fill='%23656A76' fill-rule='evenodd' clip-rule='evenodd'%3e%3canimateTransform attributeName='transform' type='rotate' dur='0.9s' from='0 8 8' to='360 8 8' repeatCount='indefinite'/%3e%3cpath d='M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8z' opacity='.2'/%3e%3cpath d='M7.25.75A.75.75 0 018 0a8 8 0 018 8 .75.75 0 01-1.5 0A6.5 6.5 0 008 1.5a.75.75 0 01-.75-.75z'/%3e%3c/g%3e%3c/svg%3e");--token-form-toggle-width:32px;--token-form-toggle-height:16px;--token-form-toggle-base-surface-color-default:#f1f2f3;--token-form-toggle-border-radius:3px;--token-form-toggle-border-width:1px;--token-form-toggle-background-image-size:12px;--token-form-toggle-background-image-position-x:2px;--token-form-toggle-background-image-data-url:url("data:image/svg+xml,%3csvg viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M9.78033 3.21967C10.0732 3.51256 10.0732 3.98744 9.78033 4.28033L5.28033 8.78033C4.98744 9.07322 4.51256 9.07322 4.21967 8.78033L2.21967 6.78033C1.92678 6.48744 1.92678 6.01256 2.21967 5.71967C2.51256 5.42678 2.98744 5.42678 3.28033 5.71967L4.75 7.18934L8.71967 3.21967C9.01256 2.92678 9.48744 2.92678 9.78033 3.21967Z' fill='%23FFF'/%3e%3c/svg%3e");--token-form-toggle-background-image-data-url-disabled:url("data:image/svg+xml,%3csvg viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M9.78033 3.21967C10.0732 3.51256 10.0732 3.98744 9.78033 4.28033L5.28033 8.78033C4.98744 9.07322 4.51256 9.07322 4.21967 8.78033L2.21967 6.78033C1.92678 6.48744 1.92678 6.01256 2.21967 5.71967C2.51256 5.42678 2.98744 5.42678 3.28033 5.71967L4.75 7.18934L8.71967 3.21967C9.01256 2.92678 9.48744 2.92678 9.78033 3.21967Z' fill='%238C909C'/%3e%3c/svg%3e");--token-form-toggle-transition-duration:0.2s;--token-form-toggle-transition-timing-function:cubic-bezier(0.68, -0.2, 0.265, 1.15);--token-form-toggle-thumb-size:16px;--token-pagination-nav-control-height:36px;--token-pagination-nav-control-padding-horizontal:12px;--token-pagination-nav-control-focus-inset:4px;--token-pagination-nav-control-icon-spacing:6px;--token-pagination-nav-indicator-height:2px;--token-pagination-nav-indicator-spacing:6px;--token-pagination-child-spacing-vertical:8px;--token-pagination-child-spacing-horizontal:20px;--token-side-nav-wrapper-border-width:1px;--token-side-nav-wrapper-border-color:#656a76;--token-side-nav-wrapper-padding-horizontal:16px;--token-side-nav-wrapper-padding-vertical:16px;--token-side-nav-wrapper-padding-horizontal-minimized:8px;--token-side-nav-wrapper-padding-vertical-minimized:22px;--token-side-nav-toggle-button-border-radius:5px;--token-side-nav-header-home-link-padding:4px;--token-side-nav-header-home-link-logo-size:48px;--token-side-nav-header-home-link-logo-size-minimized:32px;--token-side-nav-header-actions-spacing:8px;--token-side-nav-body-list-margin-vertical:24px;--token-side-nav-body-list-item-height:36px;--token-side-nav-body-list-item-padding-horizontal:8px;--token-side-nav-body-list-item-padding-vertical:4px;--token-side-nav-body-list-item-spacing-vertical:2px;--token-side-nav-body-list-item-content-spacing-horizontal:8px;--token-side-nav-body-list-item-border-radius:5px;--token-side-nav-color-foreground-primary:#dedfe3;--token-side-nav-color-foreground-strong:#fff;--token-side-nav-color-foreground-faint:#8c909c;--token-side-nav-color-surface-primary:#0c0c0e;--token-side-nav-color-surface-interactive-hover:#3b3d45;--token-side-nav-color-surface-interactive-active:#656a76;--token-tabs-tab-height:36px;--token-tabs-tab-padding-horizontal:12px;--token-tabs-tab-padding-vertical:0px;--token-tabs-tab-border-radius:5px;--token-tabs-tab-focus-inset:6px;--token-tabs-tab-gutter:6px;--token-tabs-indicator-height:3px;--token-tabs-indicator-transition-function:cubic-bezier(0.5, 1, 0.89, 1);--token-tabs-indicator-transition-duration:0.6s;--token-tabs-divider-height:1px;--token-tooltip-border-radius:5px;--token-tooltip-color-foreground-primary:var(--token-color-foreground-high-contrast);--token-tooltip-color-surface-primary:var(--token-color-palette-neutral-700);--token-tooltip-focus-offset:-2px;--token-tooltip-max-width:280px;--token-tooltip-padding-horizontal:12px;--token-tooltip-padding-vertical:8px;--token-tooltip-transition-function:cubic-bezier(0.54, 1.5, 0.38, 1.11);--token-typography-font-stack-display:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-font-stack-text:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-font-stack-code:ui-monospace,Menlo,Consolas,monospace;--token-typography-font-weight-regular:400;--token-typography-font-weight-medium:500;--token-typography-font-weight-semibold:600;--token-typography-font-weight-bold:700;--token-typography-display-500-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-display-500-font-size:1.875rem;--token-typography-display-500-line-height:1.2666;--token-typography-display-400-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-display-400-font-size:1.5rem;--token-typography-display-400-line-height:1.3333;--token-typography-display-300-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-display-300-font-size:1.125rem;--token-typography-display-300-line-height:1.3333;--token-typography-display-300-letter-spacing:-0.5px;--token-typography-display-200-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-display-200-font-size:1rem;--token-typography-display-200-line-height:1.5;--token-typography-display-200-letter-spacing:-0.5px;--token-typography-display-100-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-display-100-font-size:0.8125rem;--token-typography-display-100-line-height:1.3846;--token-typography-body-300-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-body-300-font-size:1rem;--token-typography-body-300-line-height:1.5;--token-typography-body-200-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-body-200-font-size:0.875rem;--token-typography-body-200-line-height:1.4286;--token-typography-body-100-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-body-100-font-size:0.8125rem;--token-typography-body-100-line-height:1.3846;--token-typography-code-100-font-family:ui-monospace,Menlo,Consolas,monospace;--token-typography-code-100-font-size:0.8125rem;--token-typography-code-100-line-height:1.23;--token-typography-code-200-font-family:ui-monospace,Menlo,Consolas,monospace;--token-typography-code-200-font-size:0.875rem;--token-typography-code-200-line-height:1.125;--token-typography-code-300-font-family:ui-monospace,Menlo,Consolas,monospace;--token-typography-code-300-font-size:1rem;--token-typography-code-300-line-height:1.25;--hds-app-desktop-breakpoint:1088px;--hds-app-sidenav-width-minimized:48px;--hds-app-sidenav-width-expanded:280px;--hds-app-sidenav-width-fixed:var(--hds-app-sidenav-width-expanded);--hds-app-sidenav-animation-duration:200ms;--hds-app-sidenav-animation-delay:var(--hds-app-sidenav-animation-duration);--hds-app-sidenav-animation-easing:cubic-bezier(0.65, 0, 0.35, 1);--decor-radius-000:0;--decor-radius-100:2px;--decor-radius-200:4px;--decor-radius-250:6px;--decor-radius-300:7px;--decor-radius-999:9999px;--decor-radius-full:100%;--decor-border-000:none;--decor-border-100:1px solid;--decor-border-200:2px solid;--decor-border-300:3px solid;--decor-border-400:4px solid;--icon-alert-triangle-16:url('data:image/svg+xml;charset=UTF-8,');--icon-alert-triangle-24:url('data:image/svg+xml;charset=UTF-8,');--icon-arrow-left-16:url('data:image/svg+xml;charset=UTF-8,');--icon-arrow-left-24:url('data:image/svg+xml;charset=UTF-8,');--icon-arrow-right-16:url('data:image/svg+xml;charset=UTF-8,');--icon-arrow-right-24:url('data:image/svg+xml;charset=UTF-8,');--icon-x-square-fill-16:url('data:image/svg+xml;charset=UTF-8,');--icon-x-square-fill-24:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-down-16:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-down-24:url('data:image/svg+xml;charset=UTF-8,');--icon-clipboard-copy-16:url('data:image/svg+xml;charset=UTF-8,');--icon-clipboard-copy-24:url('data:image/svg+xml;charset=UTF-8,');--icon-docs-16:url('data:image/svg+xml;charset=UTF-8,');--icon-docs-24:url('data:image/svg+xml;charset=UTF-8,');--icon-external-link-16:url('data:image/svg+xml;charset=UTF-8,');--icon-external-link-24:url('data:image/svg+xml;charset=UTF-8,');--icon-file-16:url('data:image/svg+xml;charset=UTF-8,');--icon-file-24:url('data:image/svg+xml;charset=UTF-8,');--icon-folder-16:url('data:image/svg+xml;charset=UTF-8,');--icon-folder-24:url('data:image/svg+xml;charset=UTF-8,');--icon-activity-16:url('data:image/svg+xml;charset=UTF-8,');--icon-activity-24:url('data:image/svg+xml;charset=UTF-8,');--icon-help-16:url('data:image/svg+xml;charset=UTF-8,');--icon-help-24:url('data:image/svg+xml;charset=UTF-8,');--icon-learn-16:url('data:image/svg+xml;charset=UTF-8,');--icon-learn-24:url('data:image/svg+xml;charset=UTF-8,');--icon-github-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-github-color-24:url('data:image/svg+xml;charset=UTF-8,');--icon-google-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-google-color-24:url('data:image/svg+xml;charset=UTF-8,');--icon-kubernetes-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-kubernetes-color-24:url('data:image/svg+xml;charset=UTF-8,');--icon-menu-16:url('data:image/svg+xml;charset=UTF-8,');--icon-menu-24:url('data:image/svg+xml;charset=UTF-8,');--icon-minus-square-16:url('data:image/svg+xml;charset=UTF-8,');--icon-minus-square-24:url('data:image/svg+xml;charset=UTF-8,');--icon-more-horizontal-16:url('data:image/svg+xml;charset=UTF-8,');--icon-more-horizontal-24:url('data:image/svg+xml;charset=UTF-8,');--icon-globe-16:url('data:image/svg+xml;charset=UTF-8,');--icon-globe-24:url('data:image/svg+xml;charset=UTF-8,');--icon-search-16:url('data:image/svg+xml;charset=UTF-8,');--icon-search-24:url('data:image/svg+xml;charset=UTF-8,');--icon-star-16:url('data:image/svg+xml;charset=UTF-8,');--icon-star-24:url('data:image/svg+xml;charset=UTF-8,');--icon-org-16:url('data:image/svg+xml;charset=UTF-8,');--icon-org-24:url('data:image/svg+xml;charset=UTF-8,');--icon-user-16:url('data:image/svg+xml;charset=UTF-8,');--icon-user-24:url('data:image/svg+xml;charset=UTF-8,');--icon-users-16:url('data:image/svg+xml;charset=UTF-8,');--icon-users-24:url('data:image/svg+xml;charset=UTF-8,');--icon-alert-circle-16:url('data:image/svg+xml;charset=UTF-8,');--icon-alert-circle-24:url('data:image/svg+xml;charset=UTF-8,');--icon-check-16:url('data:image/svg+xml;charset=UTF-8,');--icon-check-24:url('data:image/svg+xml;charset=UTF-8,');--icon-check-circle-16:url('data:image/svg+xml;charset=UTF-8,');--icon-check-circle-24:url('data:image/svg+xml;charset=UTF-8,');--icon-check-circle-fill-16:url('data:image/svg+xml;charset=UTF-8,');--icon-check-circle-fill-24:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-left-16:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-left-24:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-right-16:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-right-24:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-up-16:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-up-24:url('data:image/svg+xml;charset=UTF-8,');--icon-delay-16:url('data:image/svg+xml;charset=UTF-8,');--icon-delay-24:url('data:image/svg+xml;charset=UTF-8,');--icon-docs-link-16:url('data:image/svg+xml;charset=UTF-8,');--icon-docs-link-24:url('data:image/svg+xml;charset=UTF-8,');--icon-eye-16:url('data:image/svg+xml;charset=UTF-8,');--icon-eye-24:url('data:image/svg+xml;charset=UTF-8,');--icon-eye-off-16:url('data:image/svg+xml;charset=UTF-8,');--icon-eye-off-24:url('data:image/svg+xml;charset=UTF-8,');--icon-file-text-16:url('data:image/svg+xml;charset=UTF-8,');--icon-file-text-24:url('data:image/svg+xml;charset=UTF-8,');--icon-gateway-16:url('data:image/svg+xml;charset=UTF-8,');--icon-gateway-24:url('data:image/svg+xml;charset=UTF-8,');--icon-git-commit-16:url('data:image/svg+xml;charset=UTF-8,');--icon-git-commit-24:url('data:image/svg+xml;charset=UTF-8,');--icon-hexagon-16:url('data:image/svg+xml;charset=UTF-8,');--icon-hexagon-24:url('data:image/svg+xml;charset=UTF-8,');--icon-history-16:url('data:image/svg+xml;charset=UTF-8,');--icon-history-24:url('data:image/svg+xml;charset=UTF-8,');--icon-info-16:url('data:image/svg+xml;charset=UTF-8,');--icon-info-24:url('data:image/svg+xml;charset=UTF-8,');--icon-layers-16:url('data:image/svg+xml;charset=UTF-8,');--icon-layers-24:url('data:image/svg+xml;charset=UTF-8,');--icon-loading-16:url('data:image/svg+xml;charset=UTF-8,');--icon-loading-24:url('data:image/svg+xml;charset=UTF-8,');--icon-network-alt-16:url('data:image/svg+xml;charset=UTF-8,');--icon-network-alt-24:url('data:image/svg+xml;charset=UTF-8,');--icon-path-16:url('data:image/svg+xml;charset=UTF-8,');--icon-path-24:url('data:image/svg+xml;charset=UTF-8,');--icon-running-16:url('data:image/svg+xml;charset=UTF-8,');--icon-running-24:url('data:image/svg+xml;charset=UTF-8,');--icon-skip-16:url('data:image/svg+xml;charset=UTF-8,');--icon-skip-24:url('data:image/svg+xml;charset=UTF-8,');--icon-socket-16:url('data:image/svg+xml;charset=UTF-8,');--icon-socket-24:url('data:image/svg+xml;charset=UTF-8,');--icon-star-circle-16:url('data:image/svg+xml;charset=UTF-8,');--icon-star-circle-24:url('data:image/svg+xml;charset=UTF-8,');--icon-star-fill-16:url('data:image/svg+xml;charset=UTF-8,');--icon-star-fill-24:url('data:image/svg+xml;charset=UTF-8,');--icon-tag-16:url('data:image/svg+xml;charset=UTF-8,');--icon-tag-24:url('data:image/svg+xml;charset=UTF-8,');--icon-x-16:url('data:image/svg+xml;charset=UTF-8,');--icon-x-24:url('data:image/svg+xml;charset=UTF-8,');--icon-x-circle-16:url('data:image/svg+xml;charset=UTF-8,');--icon-x-circle-24:url('data:image/svg+xml;charset=UTF-8,');--icon-x-square-16:url('data:image/svg+xml;charset=UTF-8,');--icon-x-square-24:url('data:image/svg+xml;charset=UTF-8,');--icon-cloud-cross-16:url('data:image/svg+xml;charset=UTF-8,');--icon-loading-motion-16:url('data:image/svg+xml;charset=UTF-8,');--icon-auth0-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-auth0-color-24:url('data:image/svg+xml;charset=UTF-8,');--icon-logo-ember-circle-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-logo-glimmer-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-logo-jwt-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-microsoft-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-microsoft-color-24:url('data:image/svg+xml;charset=UTF-8,');--icon-logo-oidc-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-okta-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-okta-color-24:url('data:image/svg+xml;charset=UTF-8,');--icon-mesh-16:url('data:image/svg+xml;charset=UTF-8,');--icon-mesh-24:url('data:image/svg+xml;charset=UTF-8,');--icon-port-16:url('data:image/svg+xml;charset=UTF-8,');--icon-protocol-16:url('data:image/svg+xml;charset=UTF-8,');--icon-redirect-16:url('data:image/svg+xml;charset=UTF-8,');--icon-redirect-24:url('data:image/svg+xml;charset=UTF-8,');--icon-search-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-sort-desc-16:url('data:image/svg+xml;charset=UTF-8,');--icon-sort-desc-24:url('data:image/svg+xml;charset=UTF-8,');--icon-union-16:url('data:image/svg+xml;charset=UTF-8,');--chrome-width:280px;--chrome-height:64px;--typo-action:var(--token-color-foreground-action);--decor-error:var(--token-color-foreground-critical);--typo-contrast:var(--token-color-hashicorp-brand);--syntax-light-grey:#dde3e7;--syntax-light-gray:#a4a4a4;--syntax-light-grey-blue:#6c7b81;--syntax-dark-grey:#788290;--syntax-faded-gray:#eaeaea;--syntax-atlas:#127eff;--syntax-vagrant:#2f88f7;--syntax-consul:#69499a;--syntax-terraform:#822ff7;--syntax-serf:#dd4e58;--syntax-packer:#1ddba3;--syntax-gray:lighten(#000, 89%);--syntax-red:#ff3d3d;--syntax-green:#39b54a;--syntax-dark-gray:#535f73;--syntax-gutter-grey:#2a2f36;--syntax-yellow:var(--token-color-vault-brand);--horizontal-kv-list-separator-width:18px;--horizontal-kv-list-key-separator:":";--horizontal-kv-list-key-wrapper-start:"(";--horizontal-kv-list-key-wrapper-end:")";--csv-list-separator:",";--icon-loading:icon-loading-motion;--color-info:var(--token-color-foreground-action);--color-alert:var(--token-color-palette-amber-200)}.hds-border-primary{border:1px solid var(--token-color-border-primary)}.hds-border-faint{border:1px solid var(--token-color-border-faint)}.hds-border-strong{border:1px solid var(--token-color-border-strong)}.hds-border-action{border:1px solid var(--token-color-border-action)}.hds-border-highlight{border:1px solid var(--token-color-border-highlight)}.hds-border-success{border:1px solid var(--token-color-border-success)}.hds-border-warning{border:1px solid var(--token-color-border-warning)}.hds-border-critical{border:1px solid var(--token-color-border-critical)}.hds-foreground-strong{color:var(--token-color-foreground-strong)}.hds-foreground-primary{color:var(--token-color-foreground-primary)}.hds-foreground-faint{color:var(--token-color-foreground-faint)}.hds-foreground-high-contrast{color:var(--token-color-foreground-high-contrast)}.hds-foreground-disabled{color:var(--token-color-foreground-disabled)}.hds-foreground-action{color:var(--token-color-foreground-action)}.hds-foreground-action-hover{color:var(--token-color-foreground-action-hover)}.hds-foreground-action-active{color:var(--token-color-foreground-action-active)}.hds-foreground-highlight{color:var(--token-color-foreground-highlight)}.hds-foreground-highlight-on-surface{color:var(--token-color-foreground-highlight-on-surface)}.hds-foreground-highlight-high-contrast{color:var(--token-color-foreground-highlight-high-contrast)}.hds-foreground-success{color:var(--token-color-foreground-success)}.hds-foreground-success-on-surface{color:var(--token-color-foreground-success-on-surface)}.hds-foreground-success-high-contrast{color:var(--token-color-foreground-success-high-contrast)}.hds-foreground-warning{color:var(--token-color-foreground-warning)}.hds-foreground-warning-on-surface{color:var(--token-color-foreground-warning-on-surface)}.hds-foreground-warning-high-contrast{color:var(--token-color-foreground-warning-high-contrast)}.hds-foreground-critical{color:var(--token-color-foreground-critical)}.hds-foreground-critical-on-surface{color:var(--token-color-foreground-critical-on-surface)}.hds-foreground-critical-high-contrast{color:var(--token-color-foreground-critical-high-contrast)}.hds-page-primary{background-color:var(--token-color-page-primary)}.hds-page-faint{background-color:var(--token-color-page-faint)}.hds-surface-primary{background-color:var(--token-color-surface-primary)}.hds-surface-faint{background-color:var(--token-color-surface-faint)}.hds-badge--color-neutral.hds-badge--type-filled,.hds-surface-strong{background-color:var(--token-color-surface-strong)}.hds-surface-interactive{background-color:var(--token-color-surface-interactive)}.hds-surface-interactive-hover{background-color:var(--token-color-surface-interactive-hover)}.hds-surface-interactive-active{background-color:var(--token-color-surface-interactive-active)}.hds-surface-interactive-disabled{background-color:var(--token-color-surface-interactive-disabled)}.hds-surface-action{background-color:var(--token-color-surface-action)}.hds-surface-highlight{background-color:var(--token-color-surface-highlight)}.hds-surface-success{background-color:var(--token-color-surface-success)}.hds-surface-warning{background-color:var(--token-color-surface-warning)}.hds-surface-critical{background-color:var(--token-color-surface-critical)}.hds-elevation-low{box-shadow:var(--token-elevation-low-box-shadow)}.hds-elevation-mid{box-shadow:var(--token-elevation-mid-box-shadow)}.hds-elevation-high{box-shadow:var(--token-elevation-high-box-shadow)}.hds-elevation-higher{box-shadow:var(--token-elevation-higher-box-shadow)}.consul-server-list a:hover div,.hds-elevation-overlay,.modal-dialog [role=document]{box-shadow:var(--token-elevation-overlay-box-shadow)}.hds-surface-inset{box-shadow:var(--token-surface-inset-box-shadow)}.hds-surface-base{box-shadow:var(--token-surface-base-box-shadow)}.hds-surface-low{box-shadow:var(--token-surface-low-box-shadow)}.hds-accordion-item.hds-accordion-item--does-not-contain-interactive,.hds-surface-mid{box-shadow:var(--token-surface-mid-box-shadow)}.hds-surface-high{box-shadow:var(--token-surface-high-box-shadow)}.hds-surface-higher{box-shadow:var(--token-surface-higher-box-shadow)}.hds-surface-overlay{box-shadow:var(--token-surface-overlay-box-shadow)}.hds-focus-ring-action-box-shadow{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-focus-ring-critical-box-shadow{box-shadow:var(--token-focus-ring-critical-box-shadow)}.hds-font-family-sans-display{font-family:var(--token-typography-font-stack-display)}.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive,.hds-badge-count,.hds-badge__text,.hds-breadcrumb__text,.hds-button,.hds-font-family-sans-text{font-family:var(--token-typography-font-stack-text)}.hds-font-family-mono-code{font-family:var(--token-typography-font-stack-code)}#metrics-container .sparkline-wrapper .tooltip,.app-view h1 span.kind-proxy,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password],.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text],.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea,.app-view>div form:not(.filter-bar) [role=radiogroup] label>em,.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.app-view>div form:not(.filter-bar) [role=radiogroup] label>strong,.auth-form em,.consul-auth-method-type,.consul-auth-method-view section,.consul-external-source,.consul-health-check-list .health-check-output dd em,.consul-health-check-list .health-check-output dl>dd,.consul-intention-fieldsets .permissions>button,.consul-intention-list td strong,.consul-intention-list td.destination em,.consul-intention-list td.permissions,.consul-intention-list td.source em,.consul-intention-permission-header-list>ul>li dd,.consul-intention-permission-list strong,.consul-intention-permission-list>ul>li dd,.consul-intention-search-bar li button span,.consul-kind,.consul-peer-search-bar li button span,.consul-server-card .health-status+dd,.consul-source,.consul-transparent-proxy,.disclosure-menu [aria-expanded]~*>div,.discovery-chain .resolvers>header>*,.discovery-chain .route-card header dt,.discovery-chain .route-card>header ul li,.discovery-chain .routes>header>*,.discovery-chain .splitters>header>*,.empty-state header :nth-child(2),.empty-state p,.empty-state>ul>li>*,.empty-state>ul>li>::before,.empty-state>ul>li>label>button,.empty-state>ul>li>label>button::before,.has-error>strong,.has-error>strong::before,.hds-font-weight-regular,.informed-action p,.leader,.menu-panel>div,.modal-dialog [role=document] .type-password [type=password],.modal-dialog [role=document] .type-password [type=text],.modal-dialog [role=document] .type-password textarea,.modal-dialog [role=document] .type-password>em,.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-password>strong,.modal-dialog [role=document] .type-select [type=password],.modal-dialog [role=document] .type-select [type=text],.modal-dialog [role=document] .type-select textarea,.modal-dialog [role=document] .type-select>em,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-select>strong,.modal-dialog [role=document] .type-text [type=password],.modal-dialog [role=document] .type-text [type=text],.modal-dialog [role=document] .type-text textarea,.modal-dialog [role=document] .type-text>em,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] .type-text>strong,.modal-dialog [role=document] [role=radiogroup] label [type=password],.modal-dialog [role=document] [role=radiogroup] label [type=text],.modal-dialog [role=document] [role=radiogroup] label textarea,.modal-dialog [role=document] [role=radiogroup] label>em,.modal-dialog [role=document] [role=radiogroup] label>span,.modal-dialog [role=document] [role=radiogroup] label>strong,.modal-dialog [role=document] form button+em,.modal-dialog [role=document] label a[rel*=help],.modal-dialog [role=document] p,.modal-dialog [role=document] table td,.modal-dialog [role=document] table td p,.modal-dialog [role=document] table th em,.more-popover-menu>[type=checkbox]+label+div>div,.oidc-select button.reset,.oidc-select label [type=password],.oidc-select label [type=text],.oidc-select label textarea,.oidc-select label>em,.oidc-select label>span,.oidc-select label>strong,.popover-menu>[type=checkbox]+label+div>div,.search-bar-status li:not(.remove-all),.tippy-box[data-theme~=tooltip] .tippy-content,.topology-metrics-source-type,.topology-metrics-status-error,.topology-metrics-status-loader,.type-toggle [type=password],.type-toggle [type=text],.type-toggle textarea,.type-toggle>em,.type-toggle>span,.type-toggle>strong,body,html[data-route^="dc.acls.index"] main td strong,main .type-password [type=password],main .type-password [type=text],main .type-password textarea,main .type-password>em,main .type-password>span,main .type-password>strong,main .type-select [type=password],main .type-select [type=text],main .type-select textarea,main .type-select>em,main .type-select>span,main .type-select>strong,main .type-text [type=password],main .type-text [type=text],main .type-text textarea,main .type-text>em,main .type-text>span,main .type-text>strong,main form button+em,main label a[rel*=help],main p,main table td,main table td p,main table th em,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl,section[data-route="dc.show.serverstatus"] .server-failure-tolerance dt,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em,section[data-route="dc.show.license"] .validity dl,span.label,span.policy-node-identity,span.policy-service-identity,table.has-actions tr>.actions>[type=checkbox]+label+div>div,table.with-details tr>.actions>[type=checkbox]+label+div>div{font-weight:400}.app-view h1 em,.consul-exposed-path-list>ul>li .copy-button button,.consul-exposed-path-list>ul>li>.header,.consul-lock-session-list ul>li:not(:first-child) .copy-button button,.consul-lock-session-list ul>li:not(:first-child)>.header,.consul-peer-search-bar .value-active span,.consul-peer-search-bar .value-deleting span,.consul-peer-search-bar .value-establishing span,.consul-peer-search-bar .value-failing span,.consul-peer-search-bar .value-pending span,.consul-peer-search-bar .value-terminated span,.consul-upstream-instance-list li .copy-button button,.consul-upstream-instance-list li>.header,.disclosure-menu [aria-expanded]~* [role=separator],.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.hds-font-weight-medium,.informed-action>ul>li>*,.list-collection>ul>li:not(:first-child) .copy-button button,.list-collection>ul>li:not(:first-child)>.header,.menu-panel [role=separator],.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.more-popover-menu>[type=checkbox]+label+div [role=separator],.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.peerings-badge .peerings-badge__text,.popover-menu>[type=checkbox]+label+div [role=separator],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.tab-nav,main header nav:first-child ol li>*,table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div [role=separator],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{font-weight:500}#downstream-container .topology-metrics-card p,#metrics-container .sparkline-wrapper .tooltip .sparkline-time,#metrics-container div:first-child,#upstream-container .topology-metrics-card p,.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.code-editor .toolbar-container .toolbar .title,.consul-auth-method-binding-list h2,.consul-auth-method-nspace-list thead td,.consul-auth-method-view section h2,.consul-auth-method-view section table thead td,.consul-bucket-list .service+dd,.consul-health-check-list .health-check-output dt,.consul-health-check-list .health-check-output header>*,.consul-intention-action-warn-modal button.dangerous,.consul-intention-list td.destination,.consul-intention-list td.source,.consul-intention-permission-form h2,.consul-intention-view h2,.consul-peer-form-generate li::after,.consul-server-card .name+dd,.copy-button button,.definition-table dt,.empty-state header :first-child,.hds-font-weight-semibold,.informed-action header,.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label>span,.modal-dialog [role=document] form h2,.modal-dialog [role=document] table caption,.modal-dialog [role=document] table td:first-child,.modal-dialog [role=document] table td:first-child p,.modal-dialog [role=document] table th,.modal-dialog [role=document]>header>:not(button),.modal-dialog-body h2,.oidc-select label>span,.popover-select label>*,.radio-card header,.sparkline-key h3,.topology-notices button,.type-sort.popover-select label>*,.type-toggle label span,.type-toggle>span,.warning.modal-dialog header>:not(label),fieldset>header,html[data-route^="dc.services.instance.metadata"] .tab-section section h2,html[data-route^="dc.kv.edit"] h2,main .type-password>span,main .type-select>span,main .type-text>span,main form h2,main table caption,main table td:first-child,main table td:first-child p,main table th,section[data-route="dc.show.serverstatus"] .redundancy-zones h3,section[data-route="dc.show.serverstatus"] .server-failure-tolerance dd,section[data-route="dc.show.serverstatus"] h2,section[data-route="dc.show.serverstatus"] h3,section[data-route="dc.show.license"] aside header>:first-child,section[data-route="dc.show.license"] h2,span.label,strong{font-weight:600}.discovery-chain .route-card header:not(.short) dd,.discovery-chain .route-card section dt,.discovery-chain .splitter-card>header,.hds-font-weight-bold,h1{font-weight:700}.hds-typography-display-500,h1{font-family:var(--token-typography-display-500-font-family);font-size:var(--token-typography-display-500-font-size);line-height:var(--token-typography-display-500-line-height);margin:0;padding:0}.consul-auth-method-binding-list h2,.consul-auth-method-view section h2,.consul-intention-permission-form h2,.consul-intention-view h2,.empty-state header :first-child,.hds-typography-display-400,.modal-dialog [role=document] form h2,.modal-dialog [role=document]>header>:not(button),.modal-dialog-body h2,html[data-route^="dc.kv.edit"] h2,main form h2,section[data-route="dc.show.license"] h2{font-family:var(--token-typography-display-400-font-family);font-size:var(--token-typography-display-400-font-size);line-height:var(--token-typography-display-400-line-height);margin:0;padding:0}#downstream-container .topology-metrics-card p,#upstream-container .topology-metrics-card p,.consul-exposed-path-list>ul>li>.header,.consul-health-check-list .health-check-output header>*,.consul-lock-session-list ul>li:not(:first-child)>.header,.consul-upstream-instance-list li>.header,.hds-typography-display-300,.list-collection>ul>li:not(:first-child)>.header,.sparkline-key h3,.warning.modal-dialog header>:not(label),html[data-route^="dc.services.instance.metadata"] .tab-section section h2,section[data-route="dc.show.serverstatus"] .redundancy-zones h3,section[data-route="dc.show.serverstatus"] .server-failure-tolerance dd,section[data-route="dc.show.serverstatus"] h2,section[data-route="dc.show.serverstatus"] h3,section[data-route="dc.show.license"] aside header>:first-child{font-family:var(--token-typography-display-300-font-family);font-size:var(--token-typography-display-300-font-size);line-height:var(--token-typography-display-300-line-height);margin:0;padding:0}.consul-server-card .name+dd,.hds-side-nav .ember-a11y-refocus-skip-link,.hds-typography-display-200{font-size:var(--token-typography-display-200-font-size);line-height:var(--token-typography-display-200-line-height)}.consul-server-card .name+dd,.hds-typography-display-200{font-family:var(--token-typography-display-200-font-family);margin:0;padding:0}.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.consul-intention-list td.destination,.consul-intention-list td.source,.definition-table dt,.hds-typography-display-100,.informed-action header,.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label>span,.modal-dialog [role=document] table caption,.modal-dialog [role=document] table th,.oidc-select label>span,.radio-card header,.type-toggle>span,fieldset>header,main .type-password>span,main .type-select>span,main .type-text>span,main table caption,main table th{font-family:var(--token-typography-display-100-font-family);font-size:var(--token-typography-display-100-font-size);line-height:var(--token-typography-display-100-line-height);margin:0;padding:0}#metrics-container div:first-child,.hds-typography-body-300,section[data-route="dc.show.license"] .validity dl{font-family:var(--token-typography-body-300-font-family);font-size:var(--token-typography-body-300-font-size);line-height:var(--token-typography-body-300-line-height);margin:0;padding:0}#metrics-container .sparkline-wrapper .tooltip,#metrics-container .sparkline-wrapper .tooltip .sparkline-time,.app-view h1 em,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password],.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text],.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea,.code-editor .toolbar-container .toolbar .title,.consul-auth-method-nspace-list thead td,.consul-auth-method-view section,.consul-auth-method-view section table thead td,.consul-external-source,.consul-health-check-list .health-check-output dl>dd,.consul-health-check-list .health-check-output dt,.consul-kind,.consul-peer-form-generate li::after,.consul-source,.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.empty-state>ul>li>::before,.empty-state>ul>li>label>button::before,.has-error>strong::before,.hds-typography-body-200,.informed-action>ul>li>*,.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.modal-dialog [role=document] .type-password [type=password],.modal-dialog [role=document] .type-password [type=text],.modal-dialog [role=document] .type-password textarea,.modal-dialog [role=document] .type-select [type=password],.modal-dialog [role=document] .type-select [type=text],.modal-dialog [role=document] .type-select textarea,.modal-dialog [role=document] .type-text [type=password],.modal-dialog [role=document] .type-text [type=text],.modal-dialog [role=document] .type-text textarea,.modal-dialog [role=document] [role=radiogroup] label [type=password],.modal-dialog [role=document] [role=radiogroup] label [type=text],.modal-dialog [role=document] [role=radiogroup] label textarea,.modal-dialog [role=document] table td,.modal-dialog [role=document] table td p,.modal-dialog [role=document] table td:first-child,.modal-dialog [role=document] table td:first-child p,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.oidc-select label [type=password],.oidc-select label [type=text],.oidc-select label textarea,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.tab-nav,.topology-metrics-status-error,.topology-metrics-status-loader,.type-toggle [type=password],.type-toggle [type=text],.type-toggle label span,.type-toggle textarea,body,main .type-password [type=password],main .type-password [type=text],main .type-password textarea,main .type-select [type=password],main .type-select [type=text],main .type-select textarea,main .type-text [type=password],main .type-text [type=text],main .type-text textarea,main header nav:first-child ol li>*,main table td,main table td p,main table td:first-child,main table td:first-child p,strong,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{font-family:var(--token-typography-body-200-font-family);font-size:var(--token-typography-body-200-font-size);line-height:var(--token-typography-body-200-line-height);margin:0;padding:0}.app-view h1 span.kind-proxy,.app-view>div form:not(.filter-bar) [role=radiogroup] label>em,.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.auth-form em,.consul-exposed-path-list>ul>li .copy-button button,.consul-intention-action-warn-modal button.dangerous,.consul-intention-fieldsets .permissions>button,.consul-intention-list td.permissions,.consul-intention-permission-header-list>ul>li dd,.consul-intention-permission-list>ul>li dd,.consul-lock-session-list ul>li:not(:first-child) .copy-button button,.consul-server-card .health-status+dd,.consul-upstream-instance-list li .copy-button button,.copy-button button,.disclosure-menu [aria-expanded]~* [role=separator],.disclosure-menu [aria-expanded]~*>div,.discovery-chain .resolvers>header>*,.discovery-chain .routes>header>*,.discovery-chain .splitters>header>*,.empty-state header :nth-child(2),.empty-state p,.empty-state>ul>li>*,.empty-state>ul>li>label>button,.has-error>strong,.hds-typography-body-100,.informed-action p,.list-collection>ul>li:not(:first-child) .copy-button button,.menu-panel [role=separator],.menu-panel>div,.modal-dialog [role=document] .type-password>em,.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>em,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text>em,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label>em,.modal-dialog [role=document] [role=radiogroup] label>span,.modal-dialog [role=document] form button+em,.modal-dialog [role=document] p,.more-popover-menu>[type=checkbox]+label+div [role=separator],.more-popover-menu>[type=checkbox]+label+div>div,.oidc-select button.reset,.oidc-select label>em,.oidc-select label>span,.peerings-badge .peerings-badge__text,.popover-menu>[type=checkbox]+label+div [role=separator],.popover-menu>[type=checkbox]+label+div>div,.popover-select label>*,.tippy-box[data-theme~=tooltip] .tippy-content,.topology-notices button,.type-sort.popover-select label>*,.type-toggle>em,.type-toggle>span,main .type-password>em,main .type-password>span,main .type-select>em,main .type-select>span,main .type-text>em,main .type-text>span,main form button+em,main p,section[data-route="dc.show.serverstatus"] .server-failure-tolerance dt,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em,span.label,table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],table.has-actions tr>.actions>[type=checkbox]+label+div>div,table.with-details tr>.actions>[type=checkbox]+label+div [role=separator],table.with-details tr>.actions>[type=checkbox]+label+div>div{font-family:var(--token-typography-body-100-font-family);font-size:var(--token-typography-body-100-font-size);line-height:var(--token-typography-body-100-line-height);margin:0;padding:0}.hds-typography-code-100{font-family:var(--token-typography-code-100-font-family);font-size:var(--token-typography-code-100-font-size);line-height:var(--token-typography-code-100-line-height);margin:0;padding:0}.hds-typography-code-200{font-family:var(--token-typography-code-200-font-family);font-size:var(--token-typography-code-200-font-size);line-height:var(--token-typography-code-200-line-height);margin:0;padding:0}.hds-typography-code-300{font-family:var(--token-typography-code-300-font-family);font-size:var(--token-typography-code-300-font-size);line-height:var(--token-typography-code-300-line-height);margin:0;padding:0}.hds-accordion{display:flex;gap:12px}.hds-accordion-item{background:var(--token-color-surface-primary);border-radius:6px}.hds-accordion-item.hds-accordion-item--does-not-contain-interactive.mock-hover,.hds-accordion-item.hds-accordion-item--does-not-contain-interactive:hover{box-shadow:var(--token-surface-high-box-shadow)}.hds-accordion-item.hds-accordion-item--contains-interactive{box-shadow:var(--token-surface-base-box-shadow)}.hds-accordion-item__toggle{position:relative;display:flex;gap:12px;align-items:center;padding:16px 16px 16px 12px}.hds-accordion-item__button{padding:0}.hds-accordion-item__button:hover{cursor:pointer}.hds-accordion-item__button.hds-accordion-item__button--parent-does-not-contain-interactive{outline-style:solid;outline-color:transparent;isolation:isolate;position:static;margin:-1px 0;color:var(--token-color-foreground-primary);background:0 0;border:1px solid transparent}.hds-accordion-item__button.hds-accordion-item__button--parent-does-not-contain-interactive::before{position:absolute;top:0;right:0;bottom:0;left:0;z-index:-1;border-radius:5px;content:""}.hds-accordion-item__button.hds-accordion-item__button--parent-does-not-contain-interactive.mock-focus::before,.hds-accordion-item__button.hds-accordion-item__button--parent-does-not-contain-interactive:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-accordion-item__button.hds-accordion-item__button--parent-does-not-contain-interactive:focus:not(:focus-visible)::before{box-shadow:none}.hds-accordion-item__button.hds-accordion-item__button--parent-does-not-contain-interactive:focus-visible::before,.hds-breadcrumb__link.mock-focus,.hds-breadcrumb__link:focus{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-accordion-item__button.hds-accordion-item__button--parent-does-not-contain-interactive.mock-focus.mock-active::before,.hds-accordion-item__button.hds-accordion-item__button--parent-does-not-contain-interactive:focus:active::before{box-shadow:none}.hds-accordion-item__button.hds-accordion-item__button--parent-does-not-contain-interactive::after{position:absolute;display:block;border-radius:6px;content:"";inset:0}.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive{position:relative;display:flex;gap:.375rem;align-items:center;justify-content:center;font-weight:var(--token-typography-font-weight-regular);text-decoration:none;border:1px solid transparent;border-radius:5px;outline-style:solid;outline-color:transparent;isolation:isolate;width:24px;height:24px;color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-strong);box-shadow:var(--token-elevation-low-box-shadow)}.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive.mock-focus::before,.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive:focus::before{position:absolute;top:-4px;right:-4px;bottom:-4px;left:-4px;z-index:-1;border:3px solid transparent;border-radius:8px;content:""}.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive.mock-hover,.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive:hover{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-primary);border-color:var(--token-color-border-strong);cursor:pointer}.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive.mock-focus,.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive:focus{box-shadow:none;color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint);border-color:var(--token-color-focus-action-internal)}.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive.mock-focus::before,.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive:focus::before{border-color:var(--token-color-focus-action-external)}.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive.mock-active,.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive:active{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong);box-shadow:none}.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive.mock-active::before,.hds-accordion-item__button.hds-accordion-item__button--parent-contains-interactive:active::before{border-color:transparent}.hds-accordion-item__button.hds-accordion-item__button--is-open .flight-icon-chevron-down{transform:rotate(-180deg)}.hds-accordion-item__toggle-content{flex:1}.hds-accordion-item__content{padding:4px 16px 16px}.hds-alert{display:flex;align-items:flex-start}.hds-alert__icon{flex:none;width:20px;height:20px;margin-right:12px}.hds-alert__content{flex:1 1 auto}.hds-alert__text{display:flex;flex-direction:column;gap:4px;justify-content:center;color:var(--token-color-foreground-warning-on-surface)}.hds-alert__description{word-break:break-word}.hds-alert__description strong{font-weight:var(--token-typography-font-weight-semibold)}.hds-alert__description code,.hds-alert__description pre{display:inline;padding:1px 5px;font-size:.9em;font-family:var(--token-typography-code-100-font-family);line-height:1em;background-color:var(--token-color-surface-primary);border:1px solid var(--token-color-palette-neutral-200);border-radius:5px}.hds-alert__description a:not([class*=hds-]){color:var(--token-color-foreground-strong)}.hds-alert__description a:not([class*=hds-]):focus,.hds-alert__description a:not([class*=hds-]):focus-visible{text-decoration:none;outline:var(--token-color-focus-action-internal) solid 2px;outline-offset:1px}.hds-alert__description a:not([class*=hds-]):hover{color:var(--token-color-foreground-primary)}.hds-alert--color-neutral .hds-alert__icon,.hds-alert__description a:not([class*=hds-]):active{color:var(--token-color-foreground-faint)}.hds-alert__actions{display:flex;gap:16px;align-items:center}.hds-alert__actions>*{margin-top:16px}.hds-alert__dismiss{margin-top:2px;margin-left:16px}.hds-alert--type-compact .hds-alert__dismiss{margin-top:1px}.hds-alert--type-page{padding:16px 48px}.hds-alert--type-inline{padding:16px;border-style:solid;border-width:1px;border-radius:6px}.hds-alert--type-compact .hds-alert__icon{width:14px;height:14px;margin-top:2px;margin-right:8px}.hds-alert--type-compact .hds-alert__title{display:none}.hds-alert--type-compact .hds-alert__title+.hds-alert__description{margin-top:0}.hds-alert--color-neutral.hds-alert--type-page{background-color:var(--token-color-surface-faint);box-shadow:0 1px 0 0 var(--token-color-palette-alpha-300)}.hds-alert--color-neutral.hds-alert--type-inline{background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-strong)}.hds-alert--color-neutral .hds-alert__title{color:var(--token-color-foreground-primary)}.hds-alert--color-highlight.hds-alert--type-page{background-color:var(--token-color-surface-highlight);box-shadow:0 1px 0 0 var(--token-color-border-highlight)}.hds-alert--color-highlight.hds-alert--type-inline{background-color:var(--token-color-surface-highlight);border-color:var(--token-color-border-highlight)}.hds-alert--color-highlight .hds-alert__icon,.hds-alert--color-highlight .hds-alert__title{color:var(--token-color-foreground-highlight-on-surface)}.hds-alert--color-success.hds-alert--type-page{background-color:var(--token-color-surface-success);box-shadow:0 1px 0 0 var(--token-color-border-success)}.hds-alert--color-success.hds-alert--type-inline{background-color:var(--token-color-surface-success);border-color:var(--token-color-border-success)}.hds-alert--color-success .hds-alert__icon,.hds-alert--color-success .hds-alert__title{color:var(--token-color-foreground-success-on-surface)}.hds-alert--color-warning.hds-alert--type-page{background-color:var(--token-color-surface-warning);box-shadow:0 1px 0 0 var(--token-color-border-warning)}.hds-alert--color-warning.hds-alert--type-inline{background-color:var(--token-color-surface-warning);border-color:var(--token-color-border-warning)}.hds-alert--color-warning .hds-alert__icon,.hds-alert--color-warning .hds-alert__title{color:var(--token-color-foreground-warning-on-surface)}.hds-alert--color-critical.hds-alert--type-page{background-color:var(--token-color-surface-critical);box-shadow:0 1px 0 0 var(--token-color-border-critical)}.hds-alert--color-critical.hds-alert--type-inline{background-color:var(--token-color-surface-critical);border-color:var(--token-color-border-critical)}.hds-alert--color-critical .hds-alert__icon,.hds-alert--color-critical .hds-alert__title{color:var(--token-color-foreground-critical-on-surface)}.hds-app-footer{display:flex;flex-wrap:wrap;gap:24px;justify-content:flex-end;padding:24px;color:var(--app-footer-foreground-color);border-top:1px solid var(--app-footer-border-top-color)}.hds-app-footer__list:not(:has(li)){display:none}.hds-app-footer__legal-links,.hds-app-footer__list{display:flex;flex-wrap:wrap;gap:24px;align-items:center;justify-content:flex-end;width:-moz-fit-content;width:fit-content;min-width:0;margin:0;padding:0;list-style-type:none}.hds-app-footer__status-link.hds-link-inline--icon-leading>.hds-link-inline__icon{margin-right:6px}.hds-app-footer__status-link .flight-icon{fill:var(--hds-app-footer-status-icon-color,currentColor)}.hds-app-footer__status-link--operational .flight-icon{fill:var(--app-footer-status-link-icon-operational-color)}.hds-app-footer__status-link--degraded .flight-icon{fill:var(--app-footer-status-link-icon-degraded-color)}.hds-app-footer__status-link--maintenance .flight-icon{fill:var(--app-footer-status-link-icon-maintenance-color)}.hds-app-footer__status-link--critical .flight-icon{fill:var(--app-footer-status-link-icon-critical-color)}.hds-app-footer__link.hds-link-inline--color-secondary,.hds-app-footer__status-link{color:var(--app-footer-link-default-color);text-align:right}.hds-app-footer__link.hds-link-inline--color-secondary.mock-hover,.hds-app-footer__link.hds-link-inline--color-secondary:hover,.hds-app-footer__status-link.mock-hover,.hds-app-footer__status-link:hover{color:var(--app-footer-link-hover-color)}.hds-app-footer__link.hds-link-inline--color-secondary.mock-active,.hds-app-footer__link.hds-link-inline--color-secondary:active,.hds-app-footer__status-link.mock-active,.hds-app-footer__status-link:active{color:var(--app-footer-link-active-color)}.hds-app-footer__link.hds-link-inline--color-secondary.mock-focus,.hds-app-footer__link.hds-link-inline--color-secondary:focus,.hds-app-footer__link.hds-link-inline--color-secondary:focus-visible,.hds-app-footer__status-link.mock-focus,.hds-app-footer__status-link:focus,.hds-app-footer__status-link:focus-visible{color:var(--app-footer-link-focus-color);outline-color:var(--app-footer-link-focus-outline-color)}.hds-app-footer__list-item{display:flex;align-items:center}.hds-app-footer__copyright{display:flex;gap:6px;align-items:center;color:var(--app-footer-copyright-text-color)}.hds-app-footer__copyright .flight-icon{fill:var(--app-footer-copyright-icon-color)}.hds-app-footer--theme-light{--app-footer-foreground-color:var(--token-color-foreground-primary);--app-footer-border-top-color:var(--token-color-border-primary);--app-footer-link-default-color:var(--token-color-foreground-faint);--app-footer-link-hover-color:var(--token-color-palette-neutral-600);--app-footer-link-active-color:var(--token-color-palette-neutral-700);--app-footer-link-focus-color:var(--token-color-foreground-faint);--app-footer-link-focus-outline-color:var(--token-color-focus-action-internal);--app-footer-copyright-text-color:var(--token-color-foreground-primary);--app-footer-copyright-icon-color:var(--token-color-hashicorp-brand);--app-footer-status-link-icon-operational-color:var(--token-color-foreground-success);--app-footer-status-link-icon-degraded-color:var(--token-color-foreground-warning);--app-footer-status-link-icon-maintenance-color:var(--token-color-foreground-warning);--app-footer-status-link-icon-critical-color:var(--token-color-foreground-critical)}.hds-app-footer--theme-dark{--app-footer-foreground-color:#b2b6bd;--app-footer-border-top-color:#b2b6bd66;--app-footer-link-default-color:#b2b6bd;--app-footer-link-hover-color:#d5d7db;--app-footer-link-active-color:#efeff1;--app-footer-link-focus-color:#b2b6bd;--app-footer-link-focus-outline-color:#389aff;--app-footer-copyright-text-color:#b2b6bd;--app-footer-copyright-icon-color:#fff;--app-footer-status-link-icon-operational-color:#009241;--app-footer-status-link-icon-degraded-color:#e88c03;--app-footer-status-link-icon-maintenance-color:#e88c03;--app-footer-status-link-icon-critical-color:#ef3016}.hds-app-frame{display:grid;grid-template-areas:"header header" "sidebar main" "sidebar footer";grid-template-rows:auto 1fr auto;grid-template-columns:auto 1fr;min-height:100vh}.hds-app-frame__modals:empty,button.hds-button[href] .hds-button__text,button.hds-button[href]::before{display:none}.hds-app-frame__header{z-index:7;grid-area:header}.hds-app-frame__sidebar{z-index:6;grid-area:sidebar}.hds-app-frame__main{grid-area:main}.hds-app-frame__footer{grid-area:footer}.hds-app-frame__modals{position:fixed;top:0;left:0;z-index:100;width:100vw;height:100vh;pointer-events:none}.hds-application-state{width:19.5rem;max-width:100%;margin:0 auto}.hds-application-state__header{display:grid;grid-template-columns:min-content 1fr;align-items:start;color:var(--token-color-foreground-faint)}.hds-application-state__icon{margin-right:8px;padding-top:4px}.hds-application-state__error-code,.hds-application-state__title{grid-column-start:2}.hds-application-state__body{padding:12px 0;color:var(--token-color-foreground-faint)}.hds-application-state__footer{display:flex;gap:8px;justify-content:space-between}.hds-application-state__footer.hds-application-state__footer--has-divider{padding:12px 0;border-top:1px solid var(--token-color-border-strong)}.hds-avatar{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:32px;height:32px}.hds-avatar svg,.hds-dropdown--is-inline,.hds-form-toggle{display:inline-block}.hds-avatar img{width:inherit;height:inherit;border-radius:2px}.hds-badge{display:inline-flex;align-items:center;max-width:100%;vertical-align:middle;border:1px solid transparent;border-radius:5px}.hds-badge__icon{display:block;flex:0 0 auto}.hds-badge__text{flex:1 0 0;font-weight:var(--token-typography-font-weight-medium)}.hds-badge--size-small{gap:.25rem;min-height:1.25rem;padding:calc(.125rem - 1px) calc(.375rem - 1px)}.hds-badge--size-small .hds-badge__icon{width:.75rem;height:.75rem}.hds-badge--size-large .hds-badge__icon,.hds-badge--size-medium .hds-badge__icon{width:1rem;height:1rem}.hds-badge--size-small .hds-badge__text{font-size:.8125rem;line-height:1.2308}.hds-badge--size-medium{gap:.25rem;min-height:1.5rem;padding:calc(.25rem - 1px) calc(.5rem - 1px)}.hds-badge--size-medium .hds-badge__text{font-size:.8125rem;line-height:1.2308}.hds-badge--size-large{gap:.375rem;min-height:2rem;padding:calc(.25rem - 1px) calc(.5rem - 1px)}.hds-badge--size-large .hds-badge__text{font-size:1rem;line-height:1.5}.hds-badge--color-neutral.hds-badge--type-filled{color:var(--token-color-foreground-primary)}.hds-badge--color-neutral.hds-badge--type-inverted{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-faint)}.hds-badge--color-neutral.hds-badge--type-outlined{color:var(--token-color-foreground-primary);background-color:transparent;border-color:var(--token-color-foreground-faint)}.hds-badge--color-neutral-dark-mode.hds-badge--type-filled{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-faint)}.hds-badge--color-neutral-dark-mode.hds-badge--type-inverted{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint)}.hds-badge--color-neutral-dark-mode.hds-badge--type-outlined{color:var(--token-color-foreground-high-contrast);background-color:transparent;border-color:var(--token-color-palette-neutral-100)}.hds-badge--color-highlight.hds-badge--type-filled{color:var(--token-color-foreground-highlight-on-surface);background-color:var(--token-color-surface-highlight)}.hds-badge--color-highlight.hds-badge--type-inverted{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-highlight)}.hds-badge--color-highlight.hds-badge--type-outlined{color:var(--token-color-foreground-highlight);background-color:transparent;border-color:currentColor}.hds-badge--color-success.hds-badge--type-filled{color:var(--token-color-foreground-success-on-surface);background-color:var(--token-color-surface-success)}.hds-badge--color-success.hds-badge--type-inverted{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-success)}.hds-badge--color-success.hds-badge--type-outlined{color:var(--token-color-foreground-success);background-color:transparent;border-color:currentColor}.hds-badge--color-warning.hds-badge--type-filled{color:var(--token-color-foreground-warning-on-surface);background-color:var(--token-color-surface-warning)}.hds-badge--color-warning.hds-badge--type-inverted{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-warning)}.hds-badge--color-warning.hds-badge--type-outlined{color:var(--token-color-foreground-warning);background-color:transparent;border-color:currentColor}.hds-badge--color-critical.hds-badge--type-filled{color:var(--token-color-foreground-critical-on-surface);background-color:var(--token-color-surface-critical)}.hds-badge--color-critical.hds-badge--type-inverted{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-critical)}.hds-badge--color-critical.hds-badge--type-outlined{color:var(--token-color-foreground-critical);background-color:transparent;border-color:currentColor}.hds-badge-count{display:inline-flex;align-items:center;max-width:100%;font-weight:var(--token-typography-font-weight-medium);border:1px solid transparent}.hds-button,.hds-dropdown-toggle-button{font-weight:var(--token-typography-font-weight-regular)}.hds-badge-count--size-small{min-height:1.25rem;padding:calc(.125rem - 1px) calc(.5rem - 1px);font-size:.8125rem;line-height:1.2308;border-radius:.625rem}.hds-badge-count--size-medium{min-height:1.5rem;padding:calc(.25rem - 1px) calc(.75rem - 1px);font-size:.8125rem;line-height:1.2308;border-radius:.75rem}.hds-badge-count--size-large{min-height:2rem;padding:calc(.25rem - 1px) calc(.875rem - 1px);font-size:1rem;line-height:1.5;border-radius:1rem}.hds-breadcrumb__list,.hds-breadcrumb__sublist{margin:0;padding:0;list-style:none}.hds-badge-count--color-neutral.hds-badge-count--type-filled{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-strong)}.hds-badge-count--color-neutral.hds-badge-count--type-inverted{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-faint)}.hds-badge-count--color-neutral.hds-badge-count--type-outlined{color:var(--token-color-foreground-primary);background-color:transparent;border-color:var(--token-color-foreground-faint)}.hds-badge-count--color-neutral-dark-mode.hds-badge-count--type-filled{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-faint)}.hds-badge-count--color-neutral-dark-mode.hds-badge-count--type-inverted{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint)}.hds-badge-count--color-neutral-dark-mode.hds-badge-count--type-outlined{color:var(--token-color-foreground-high-contrast);background-color:transparent;border-color:var(--token-color-palette-neutral-100)}.hds-breadcrumb{position:relative}.hds-breadcrumb__list{display:flex}.hds-breadcrumb--items-can-wrap .hds-breadcrumb__list{flex-wrap:wrap}.hds-breadcrumb__item{position:relative;display:flex;flex-direction:row;align-items:center;min-width:0}.hds-breadcrumb__list>.hds-breadcrumb__item:not(:last-child)::after{padding:0 8px;color:var(--token-color-palette-neutral-300);content:"/"}.hds-breadcrumb__sublist>.hds-breadcrumb__item+.hds-breadcrumb__item{margin-top:4px}.hds-breadcrumb__current,.hds-breadcrumb__link{margin:0 -4px;padding:0 4px;display:flex;min-width:0}.hds-breadcrumb__item--is-truncation{flex:none}.hds-breadcrumb__link{flex-direction:row;align-items:center;color:var(--token-color-foreground-faint);border-radius:5px;text-decoration-color:transparent;outline-style:solid;outline-color:transparent}.hds-breadcrumb__link.mock-active>.hds-breadcrumb__text,.hds-breadcrumb__link.mock-hover>.hds-breadcrumb__text,.hds-breadcrumb__link:active>.hds-breadcrumb__text,.hds-breadcrumb__link:hover>.hds-breadcrumb__text{text-decoration-color:currentColor}.hds-breadcrumb__link.mock-hover,.hds-breadcrumb__link:hover{color:var(--token-color-palette-neutral-600)}.hds-breadcrumb__link:focus:not(:focus-visible){box-shadow:none}.hds-breadcrumb__link:focus-visible{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-breadcrumb__link.mock-focus.mock-active,.hds-breadcrumb__link:focus:active{box-shadow:none}.hds-breadcrumb__link.mock-active,.hds-breadcrumb__link:active{color:var(--token-color-foreground-secondary)}.hds-breadcrumb__current{flex-direction:row;align-items:center;color:var(--token-color-foreground-strong)}.hds-breadcrumb__icon{flex:none;width:13px;height:13px;margin-right:6px}.hds-breadcrumb__text{padding:calc((28px - 1rem)/ 2) 0;font-size:.8125rem;line-height:1rem;white-space:nowrap;text-decoration:underline;text-overflow:ellipsis;text-decoration-color:transparent}.hds-breadcrumb__sublist .hds-breadcrumb__text{white-space:normal}.hds-breadcrumb__truncation-toggle{display:flex;flex:none;align-items:center;justify-content:center;width:28px;height:28px;margin:0 -4px;padding:0;color:var(--token-color-foreground-faint);background-color:transparent;border:1px solid transparent;border-radius:5px;outline:transparent solid 0;cursor:pointer}.hds-button,.hds-copy-snippet{align-items:center;isolation:isolate}.hds-button,.hds-copy-snippet,.hds-dismiss-button,.hds-dropdown-toggle-button,.hds-dropdown-toggle-icon{outline-style:solid;outline-color:transparent}.hds-breadcrumb__truncation-toggle.mock-hover,.hds-breadcrumb__truncation-toggle:hover{color:var(--token-color-foreground-faint);border-color:var(--token-color-border-strong)}.hds-breadcrumb__truncation-toggle.mock-focus,.hds-breadcrumb__truncation-toggle:focus{box-shadow:var(--token-focus-ring-action-box-shadow);background-color:transparent;border:none}.hds-breadcrumb__truncation-toggle:focus:not(:focus-visible){box-shadow:none}.hds-breadcrumb__truncation-toggle:focus-visible,.hds-copy-snippet.mock-focus::before,.hds-copy-snippet:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-breadcrumb__truncation-toggle.mock-focus.mock-active,.hds-breadcrumb__truncation-toggle:focus:active{box-shadow:none}.hds-breadcrumb__truncation-toggle.mock-active,.hds-breadcrumb__truncation-toggle:active{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong)}.hds-breadcrumb__truncation-content{position:absolute;top:100%;left:-4px;z-index:300;width:-moz-max-content;width:max-content;max-width:200px;margin-top:4px;padding:6px 12px;background-color:var(--token-color-surface-primary);border-radius:6px;box-shadow:var(--token-surface-high-box-shadow)}.hds-button.hds-button--width-full,.hds-copy-snippet--is-truncated,.hds-copy-snippet--width-full,.hds-dropdown-toggle-button--width-full{max-width:100%;width:100%}.hds-button--size-small,.hds-dropdown-toggle-button--size-small{padding:.375rem .6875rem;min-height:1.75rem}.hds-button{position:relative;display:flex;gap:.375rem;justify-content:center;width:auto;text-decoration:none;border:1px solid transparent;border-radius:5px}a.hds-button{width:-moz-fit-content;width:fit-content}a.hds-button.mock-active,a.hds-button.mock-focus,a.hds-button.mock-hover,a.hds-button:active,a.hds-button:focus,a.hds-button:hover{text-decoration:underline}.hds-button.mock-disabled,.hds-button.mock-disabled:focus,.hds-button.mock-disabled:hover,.hds-button:disabled,.hds-button:disabled:focus,.hds-button:disabled:hover,.hds-button[disabled],.hds-button[disabled]:focus,.hds-button[disabled]:hover{color:var(--token-color-foreground-disabled);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-primary);box-shadow:none;cursor:not-allowed}.hds-button.mock-disabled::before,.hds-button.mock-disabled:focus::before,.hds-button.mock-disabled:hover::before,.hds-button:disabled::before,.hds-button:disabled:focus::before,.hds-button:disabled:hover::before,.hds-button[disabled]::before,.hds-button[disabled]:focus::before,.hds-button[disabled]:hover::before{border-color:transparent}.hds-button.hds-button--width-full .hds-button__text{flex:0 0 auto}.hds-button__text,.hds-copy-snippet__text,.hds-form-group--radio-cards .hds-form-radio-card--has-fluid-width{flex:1 0 0}.hds-button.mock-focus,.hds-button:focus{box-shadow:none}.hds-button.mock-focus::before,.hds-button:focus::before{position:absolute;top:-4px;right:-4px;bottom:-4px;left:-4px;z-index:-1;border:3px solid transparent;border-radius:8px;content:""}.hds-button__text{text-align:center}.hds-button--size-small .hds-button__icon{width:.75rem;height:.75rem}.hds-button--size-small .hds-button__text{font-size:.8125rem;line-height:.875rem}.hds-button--size-small.hds-button--is-icon-only{min-width:1.75rem;padding-right:.375rem;padding-left:.375rem}.hds-button--size-medium{min-height:2.25rem;padding:.5625rem .9375rem}.hds-button--size-medium .hds-button__icon{width:1rem;height:1rem}.hds-button--size-medium .hds-button__text{font-size:.875rem;line-height:1rem}.hds-button--size-medium.hds-button--is-icon-only{min-width:2.25rem;padding-right:.5625rem;padding-left:.5625rem}.hds-button--size-large{min-height:3rem;padding:.6875rem 1.1875rem}.hds-button--size-large .hds-button__icon{width:1.5rem;height:1.5rem}.hds-button--size-large .hds-button__text{font-size:1rem;line-height:1.5rem}.hds-button--size-large.hds-button--is-icon-only{min-width:3rem;padding-right:.6875rem;padding-left:.6875rem}.hds-button--color-primary{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-blue-200);border-color:var(--token-color-palette-blue-300);box-shadow:var(--token-elevation-low-box-shadow)}.hds-button--color-primary.mock-hover,.hds-button--color-primary:hover{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-blue-300);border-color:var(--token-color-palette-blue-400);cursor:pointer}.hds-button--color-primary.mock-focus,.hds-button--color-primary:focus{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-blue-200);border-color:var(--token-color-focus-action-internal)}.hds-button--color-primary.mock-focus::before,.hds-button--color-primary:focus::before{top:-6px;right:-6px;bottom:-6px;left:-6px;border-color:var(--token-color-focus-action-external);border-radius:10px}.hds-button--color-primary.mock-active,.hds-button--color-primary:active{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-blue-400);border-color:var(--token-color-palette-blue-400);box-shadow:none}.hds-button--color-primary.mock-active::before,.hds-button--color-primary:active::before{border-color:transparent}.hds-button--color-secondary{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-strong);box-shadow:var(--token-elevation-low-box-shadow)}.hds-button--color-secondary.mock-hover,.hds-button--color-secondary:hover{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-primary);border-color:var(--token-color-border-strong);cursor:pointer}.hds-button--color-secondary.mock-focus,.hds-button--color-secondary:focus{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint);border-color:var(--token-color-focus-action-internal)}.hds-button--color-secondary.mock-focus::before,.hds-button--color-secondary:focus::before{border-color:var(--token-color-focus-action-external)}.hds-button--color-secondary.mock-active,.hds-button--color-secondary:active{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong);box-shadow:none}.hds-button--color-secondary.mock-active::before,.hds-button--color-secondary:active::before{border-color:transparent}.hds-button--color-tertiary{color:var(--token-color-foreground-action);background-color:transparent;border-color:transparent}.hds-button--color-tertiary.mock-hover,.hds-button--color-tertiary:hover{color:var(--token-color-foreground-action-hover);background-color:var(--token-color-surface-primary);border-color:var(--token-color-border-strong);cursor:pointer}.hds-button--color-tertiary.mock-focus,.hds-button--color-tertiary:focus{color:var(--token-color-foreground-action);border-color:var(--token-color-focus-action-internal)}.hds-button--color-tertiary.mock-focus::before,.hds-button--color-tertiary:focus::before{border-color:var(--token-color-focus-action-external)}.hds-button--color-tertiary.mock-active,.hds-button--color-tertiary:active{color:var(--token-color-foreground-action-active);background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong);box-shadow:none}.hds-button--color-tertiary.mock-active::before,.hds-button--color-tertiary:active::before{border-color:transparent}.hds-button--color-tertiary.mock-disabled,.hds-button--color-tertiary.mock-disabled:focus,.hds-button--color-tertiary.mock-disabled:hover,.hds-button--color-tertiary:disabled,.hds-button--color-tertiary:disabled:focus,.hds-button--color-tertiary:disabled:hover,.hds-button--color-tertiary[disabled],.hds-button--color-tertiary[disabled]:focus,.hds-button--color-tertiary[disabled]:hover{background-color:transparent;border-color:transparent}.hds-button--color-tertiary.mock-disabled::before,.hds-button--color-tertiary.mock-disabled:focus::before,.hds-button--color-tertiary.mock-disabled:hover::before,.hds-button--color-tertiary:disabled::before,.hds-button--color-tertiary:disabled:focus::before,.hds-button--color-tertiary:disabled:hover::before,.hds-button--color-tertiary[disabled]::before,.hds-button--color-tertiary[disabled]:focus::before,.hds-button--color-tertiary[disabled]:hover::before{border-color:transparent}.hds-button--color-critical{color:var(--token-color-foreground-critical-on-surface);background-color:var(--token-color-surface-critical);border-color:var(--token-color-foreground-critical-on-surface);box-shadow:var(--token-elevation-low-box-shadow)}.hds-button--color-critical.mock-hover,.hds-button--color-critical:hover{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-red-300);border-color:var(--token-color-palette-red-400);cursor:pointer}.hds-button--color-critical.mock-focus,.hds-button--color-critical:focus{color:var(--token-color-foreground-critical-on-surface);background-color:var(--token-color-surface-critical);border-color:var(--token-color-focus-critical-internal)}.hds-button--color-critical.mock-focus::before,.hds-button--color-critical:focus::before{border-color:var(--token-color-focus-critical-external)}.hds-button--color-critical.mock-active,.hds-button--color-critical:active{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-red-400);border-color:var(--token-color-palette-red-400);box-shadow:none}.hds-button--color-critical.mock-active::before,.hds-button--color-critical:active::before{border-color:transparent}button.hds-button[href]{color:#fff!important;background-color:red!important;border:none}button.hds-button[href]::after{content:' Attention: you’re passing a "href" attribute to the "Hds::Button" component, you should use an "@href" argument.'}.hds-button-set{display:flex;gap:16px}.hds-card__container{position:relative;background-color:#fff;border-radius:6px}.hds-card__container--level-surface-base{box-shadow:var(--token-surface-base-box-shadow)}.hds-card__container--level-surface-mid{box-shadow:var(--token-surface-mid-box-shadow)}.hds-card__container--level-surface-high{box-shadow:var(--token-surface-high-box-shadow)}.hds-card__container--hover-level-surface-base.mock-hover,.hds-card__container--hover-level-surface-base:hover{box-shadow:var(--token-surface-base-box-shadow)}.hds-card__container--hover-level-surface-mid.mock-hover,.hds-card__container--hover-level-surface-mid:hover{box-shadow:var(--token-surface-mid-box-shadow)}.hds-card__container--hover-level-surface-high.mock-hover,.hds-card__container--hover-level-surface-high:hover{box-shadow:var(--token-surface-high-box-shadow)}.hds-card__container--active-level-surface-base.mock-active,.hds-card__container--active-level-surface-base:active{box-shadow:var(--token-surface-base-box-shadow)}.hds-card__container--active-level-surface-mid.mock-active,.hds-card__container--active-level-surface-mid:active{box-shadow:var(--token-surface-mid-box-shadow)}.hds-card__container--active-level-surface-high.mock-active,.hds-card__container--active-level-surface-high:active{box-shadow:var(--token-surface-high-box-shadow)}.hds-card__container--level-elevation-base{box-shadow:var(--token-elevation-base-box-shadow)}.hds-card__container--level-elevation-mid{box-shadow:var(--token-elevation-mid-box-shadow)}.hds-card__container--level-elevation-high{box-shadow:var(--token-elevation-high-box-shadow)}.hds-card__container--hover-level-elevation-base.mock-hover,.hds-card__container--hover-level-elevation-base:hover{box-shadow:var(--token-elevation-base-box-shadow)}.hds-card__container--hover-level-elevation-mid.mock-hover,.hds-card__container--hover-level-elevation-mid:hover{box-shadow:var(--token-elevation-mid-box-shadow)}.hds-card__container--hover-level-elevation-high.mock-hover,.hds-card__container--hover-level-elevation-high:hover{box-shadow:var(--token-elevation-high-box-shadow)}.hds-card__container--active-level-elevation-base.mock-active,.hds-card__container--active-level-elevation-base:active{box-shadow:var(--token-elevation-base-box-shadow)}.hds-card__container--active-level-elevation-mid.mock-active,.hds-card__container--active-level-elevation-mid:active{box-shadow:var(--token-elevation-mid-box-shadow)}.hds-card__container--active-level-elevation-high.mock-active,.hds-card__container--active-level-elevation-high:active{box-shadow:var(--token-elevation-high-box-shadow)}.hds-card__container--background-neutral-primary{background-color:var(--token-color-surface-primary)}.hds-card__container--background-neutral-secondary{background-color:var(--token-color-surface-faint)}.hds-card__container--overflow-visible{overflow:visible}.hds-copy-button{cursor:pointer}.hds-copy-button .hds-button__icon{color:var(--token-color-foreground-action)}.hds-copy-button.hds-copy-button--status-success .hds-button__icon{color:var(--token-color-foreground-success)}.hds-copy-button.hds-copy-button--status-error .hds-button__icon{color:var(--token-color-foreground-critical)}.hds-copy-snippet{position:relative;display:flex;gap:8px;justify-content:space-between;padding:6px 4px;text-align:left;border:1px solid transparent;border-radius:5px;cursor:pointer}.hds-copy-snippet::before,.hds-dismiss-button::before{position:absolute;z-index:-1;content:""}.hds-copy-snippet::before{top:0;right:0;bottom:0;left:0;border-radius:5px}.hds-copy-snippet:focus:not(:focus-visible)::before{box-shadow:none}.hds-copy-snippet:focus-visible::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-copy-snippet.mock-focus.mock-active::before,.hds-copy-snippet:focus:active::before{box-shadow:none}.hds-copy-snippet--color-primary{color:var(--token-color-foreground-action);background-color:transparent}.hds-copy-snippet--color-primary.mock-hover,.hds-copy-snippet--color-primary:hover{color:var(--token-color-foreground-action-hover);background-color:var(--token-color-surface-interactive);border-color:var(--token-color-border-strong)}.hds-copy-snippet--color-primary.mock-active,.hds-copy-snippet--color-primary:active{color:var(--token-color-foreground-action-active);background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong)}.hds-copy-snippet--color-primary:focus{background-color:transparent}.hds-copy-snippet--color-secondary{color:var(--token-color-foreground-primary);background-color:transparent}.hds-copy-snippet--color-secondary.mock-hover,.hds-copy-snippet--color-secondary:hover{background-color:var(--token-color-surface-interactive);border-color:var(--token-color-border-strong)}.hds-copy-snippet--color-secondary.mock-active,.hds-copy-snippet--color-secondary:active{background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong)}.hds-copy-snippet--status-error,.hds-copy-snippet--status-success{background-color:var(--token-color-surface-interactive)}.hds-copy-snippet--color-secondary .hds-copy-snippet__icon{color:var(--token-color-foreground-action)}.hds-copy-snippet--color-secondary .hds-copy-snippet__icon:hover{color:var(--token-color-foreground-action-hover)}.hds-copy-snippet--color-secondary .hds-copy-snippet__icon:active{color:var(--token-color-foreground-action-active)}.hds-copy-snippet--color-secondary .hds-copy-snippet__icon:focus{color:var(--token-color-foreground-action)}.hds-copy-snippet--status-success .hds-copy-snippet__icon{color:var(--token-color-foreground-success)}.hds-copy-snippet--status-error .hds-copy-snippet__icon{color:var(--token-color-foreground-critical)}.hds-copy-snippet__icon{flex:none}.hds-copy-snippet--is-truncated .hds-copy-snippet__text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.hds-disclosure-primitive{position:relative}.hds-dismiss-button{flex:none;padding:0;color:var(--token-color-foreground-faint);background-color:transparent;border:none;cursor:pointer;position:relative;isolation:isolate}.hds-dismiss-button.mock-hover::before,.hds-dismiss-button:hover::before{background-color:rgba(222,223,227,.4)}.hds-dismiss-button::before{top:-4px;right:-4px;bottom:-4px;left:-4px;border-radius:5px}.hds-dismiss-button.mock-focus::before,.hds-dismiss-button:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-dismiss-button:focus:not(:focus-visible)::before{box-shadow:none}.hds-dismiss-button:focus-visible::before,.hds-dropdown-toggle-icon.mock-focus::before,.hds-dropdown-toggle-icon:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-dismiss-button.mock-focus.mock-active::before,.hds-dismiss-button:focus:active::before{box-shadow:none}.hds-dismiss-button.mock-active,.hds-dismiss-button:active{color:var(--token-color-foreground-secondary)}.hds-dismiss-button.mock-active::before,.hds-dismiss-button:active::before{background-color:rgba(222,223,227,.4);border:1px solid var(--token-color-border-strong)}.hds-dropdown--is-inline .hds-dropdown-toggle-button,.hds-dropdown--is-inline .hds-dropdown-toggle-icon{display:inline-flex}.hds-dropdown-toggle-icon{display:flex;gap:2px;align-items:center;justify-content:center;padding:1px;background-color:var(--token-color-surface-faint);border:1px solid var(--token-color-border-strong);border-radius:5px;position:relative;isolation:isolate}.hds-dropdown-toggle-button,.hds-link-standalone{gap:.375rem;font-family:var(--token-typography-font-stack-text);isolation:isolate}.hds-dropdown-toggle-icon.mock-hover,.hds-dropdown-toggle-icon:hover{background-color:var(--token-color-surface-interactive);cursor:pointer}.hds-dropdown-toggle-icon::before{position:absolute;top:-1px;right:-1px;bottom:-1px;left:-1px;z-index:-1;border-radius:5px;content:""}.hds-dropdown-toggle-icon:focus:not(:focus-visible)::before{box-shadow:none}.hds-dropdown-toggle-icon:focus-visible::before,.hds-link-standalone.mock-focus::before,.hds-link-standalone:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-dropdown-toggle-icon.mock-focus.mock-active::before,.hds-dropdown-toggle-icon:focus:active::before{box-shadow:none}.hds-dropdown-toggle-icon.mock-active,.hds-dropdown-toggle-icon:active{background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong)}.hds-dropdown-toggle-icon.mock-disabled,.hds-dropdown-toggle-icon:disabled{color:var(--token-color-foreground-disabled);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-primary);box-shadow:none;cursor:not-allowed}.hds-dropdown-toggle-icon.mock-disabled::before,.hds-dropdown-toggle-icon:disabled::before{border-color:transparent}.hds-dropdown-toggle-icon__wrapper{display:flex;align-items:center;justify-content:center;border-radius:3px}.hds-dropdown-toggle-icon__wrapper img{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;border-radius:inherit}.hds-dropdown-toggle-icon--size-small .hds-dropdown-toggle-icon__wrapper{width:24px;height:24px}.hds-dropdown-toggle-icon--size-medium .hds-dropdown-toggle-icon__wrapper{width:32px;height:32px}.hds-dropdown-toggle-button{position:relative;display:flex;align-items:center;justify-content:center;width:auto;text-decoration:none;border:1px solid transparent;border-radius:5px}.hds-dropdown-toggle-button.mock-focus,.hds-dropdown-toggle-button:focus{box-shadow:none}.hds-dropdown-toggle-button.mock-focus::before,.hds-dropdown-toggle-button:focus::before{position:absolute;top:-4px;right:-4px;bottom:-4px;left:-4px;z-index:-1;border:3px solid transparent;border-radius:8px;content:""}.hds-dropdown-toggle-button.mock-disabled,.hds-dropdown-toggle-button.mock-disabled:focus,.hds-dropdown-toggle-button.mock-disabled:hover,.hds-dropdown-toggle-button:disabled,.hds-dropdown-toggle-button:disabled:focus,.hds-dropdown-toggle-button:disabled:hover{color:var(--token-color-foreground-disabled);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-primary);box-shadow:none;cursor:not-allowed}.hds-dropdown-toggle-button.mock-disabled::before,.hds-dropdown-toggle-button.mock-disabled:focus::before,.hds-dropdown-toggle-button.mock-disabled:hover::before,.hds-dropdown-toggle-button:disabled::before,.hds-dropdown-toggle-button:disabled:focus::before,.hds-dropdown-toggle-button:disabled:hover::before{border-color:transparent}.hds-dropdown-toggle-button.mock-disabled .hds-dropdown-toggle-button__badge,.hds-dropdown-toggle-button.mock-disabled .hds-dropdown-toggle-button__count,.hds-dropdown-toggle-button.mock-disabled:focus .hds-dropdown-toggle-button__badge,.hds-dropdown-toggle-button.mock-disabled:focus .hds-dropdown-toggle-button__count,.hds-dropdown-toggle-button.mock-disabled:hover .hds-dropdown-toggle-button__badge,.hds-dropdown-toggle-button.mock-disabled:hover .hds-dropdown-toggle-button__count,.hds-dropdown-toggle-button:disabled .hds-dropdown-toggle-button__badge,.hds-dropdown-toggle-button:disabled .hds-dropdown-toggle-button__count,.hds-dropdown-toggle-button:disabled:focus .hds-dropdown-toggle-button__badge,.hds-dropdown-toggle-button:disabled:focus .hds-dropdown-toggle-button__count,.hds-dropdown-toggle-button:disabled:hover .hds-dropdown-toggle-button__badge,.hds-dropdown-toggle-button:disabled:hover .hds-dropdown-toggle-button__count{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-strong)}.hds-dropdown-toggle-button--size-small .hds-dropdown-toggle-button__icon{width:.75rem;height:.75rem}.hds-dropdown-toggle-button--size-small .hds-dropdown-toggle-button__text{font-size:.8125rem;line-height:.875rem}.hds-dropdown-toggle-button--size-small.hds-dropdown-toggle-button--is-icon-only{min-width:1.75rem;padding-right:.375rem;padding-left:.375rem}.hds-dropdown-toggle-button--size-medium{min-height:2.25rem;padding:.5625rem .9375rem}.hds-dropdown-toggle-button--size-medium .hds-dropdown-toggle-button__icon{width:1rem;height:1rem}.hds-dropdown-toggle-button--size-medium .hds-dropdown-toggle-button__text{font-size:.875rem;line-height:1rem}.hds-dropdown-toggle-button--size-medium.hds-dropdown-toggle-button--is-icon-only{min-width:2.25rem;padding-right:.5625rem;padding-left:.5625rem}.hds-dropdown-toggle-button--size-large{min-height:3rem;padding:.6875rem 1.1875rem}.hds-dropdown-toggle-button--size-large .hds-dropdown-toggle-button__icon{width:1.5rem;height:1.5rem}.hds-dropdown-toggle-button--size-large .hds-dropdown-toggle-button__text{font-size:1rem;line-height:1.5rem}.hds-dropdown-toggle-button--size-large.hds-dropdown-toggle-button--is-icon-only{min-width:3rem;padding-right:.6875rem;padding-left:.6875rem}.hds-dropdown-toggle-button--size-small{padding-right:.375rem}.hds-dropdown-toggle-button--size-medium{padding-right:.5625rem}.hds-dropdown-toggle-button--color-primary{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-blue-200);border-color:var(--token-color-palette-blue-300);box-shadow:var(--token-elevation-low-box-shadow)}.hds-dropdown-toggle-button--color-primary.mock-hover,.hds-dropdown-toggle-button--color-primary:hover{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-blue-300);border-color:var(--token-color-palette-blue-400);cursor:pointer}.hds-dropdown-toggle-button--color-primary.mock-focus,.hds-dropdown-toggle-button--color-primary:focus{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-blue-200);border-color:var(--token-color-focus-action-internal)}.hds-dropdown-toggle-button--color-primary.mock-focus::before,.hds-dropdown-toggle-button--color-primary:focus::before{top:-6px;right:-6px;bottom:-6px;left:-6px;border-color:var(--token-color-focus-action-external);border-radius:10px}.hds-dropdown-toggle-button--color-primary.mock-active,.hds-dropdown-toggle-button--color-primary:active{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-blue-400);border-color:var(--token-color-palette-blue-400);box-shadow:none}.hds-dropdown-toggle-button--color-primary.mock-active::before,.hds-dropdown-toggle-button--color-primary:active::before{border-color:transparent}.hds-dropdown-toggle-button--color-secondary{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-strong);box-shadow:var(--token-elevation-low-box-shadow)}.hds-dropdown-toggle-button--color-secondary.mock-hover,.hds-dropdown-toggle-button--color-secondary:hover{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-primary);border-color:var(--token-color-border-strong);cursor:pointer}.hds-dropdown-toggle-button--color-secondary.mock-focus,.hds-dropdown-toggle-button--color-secondary:focus{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint);border-color:var(--token-color-focus-action-internal)}.hds-dropdown-toggle-button--color-secondary.mock-focus::before,.hds-dropdown-toggle-button--color-secondary:focus::before{border-color:var(--token-color-focus-action-external)}.hds-dropdown-toggle-button--color-secondary.mock-active,.hds-dropdown-toggle-button--color-secondary:active{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong);box-shadow:none}.hds-dropdown-toggle-button--color-secondary.mock-active::before,.hds-dropdown-toggle-button--color-secondary:active::before{border-color:transparent}.hds-dropdown-list-item--variant-separator::before,.hds-dropdown__header--with-divider{border-bottom:1px solid var(--token-color-border-primary)}.hds-dropdown-toggle-button--width-full{justify-content:space-between}.hds-dropdown-toggle-button__text{text-align:left}.hds-dropdown-toggle-button__icon{flex:none}.hds-dropdown-toggle-button__badge,.hds-dropdown-toggle-button__count{margin:-3px 0}.hds-dropdown-toggle-chevron{margin-left:auto;padding-left:2px}@media (prefers-reduced-motion:no-preference){.hds-accordion-item__button .flight-icon-chevron-down,.hds-dropdown-toggle-chevron .flight-icon-chevron-down{transition:transform .3s}}.hds-dropdown-toggle-button--is-open .hds-dropdown-toggle-chevron .flight-icon-chevron-down,.hds-dropdown-toggle-icon--is-open .hds-dropdown-toggle-chevron .flight-icon-chevron-down{transform:rotate(-180deg)}.hds-dropdown__content{display:flex;flex-direction:column;width:-moz-max-content;width:max-content;min-width:200px;max-width:400px;background-color:var(--token-color-surface-primary);border-radius:6px;box-shadow:var(--token-surface-high-box-shadow)}.hds-dropdown__content--fixed-width{min-width:initial;max-width:initial}.hds-dropdown__content--position-bottom-right{position:absolute;top:calc(100% + 4px);right:0;z-index:2}.hds-dropdown__content--position-bottom-left{position:absolute;top:calc(100% + 4px);left:0;z-index:2}.hds-dropdown__content--position-top-right{position:absolute;right:0;bottom:calc(100% + 4px);z-index:2}.hds-dropdown__content--position-top-left{position:absolute;bottom:calc(100% + 4px);left:0;z-index:2}.hds-dropdown__list{flex:1 1 auto;margin:0;padding:4px 0;overflow-y:auto;list-style:none;overscroll-behavior:contain}.hds-dropdown__footer,.hds-dropdown__header{position:relative;flex:none;padding:0 8px}.hds-dropdown__footer>.hds-link-standalone,.hds-dropdown__header>.hds-link-standalone{width:initial;margin:4px 0;padding:7px 8px}.hds-dropdown__footer>.hds-link-standalone::before,.hds-dropdown__header>.hds-link-standalone::before{top:0;bottom:0}.hds-dropdown__footer>.hds-button,.hds-dropdown__footer>.hds-form-text-input,.hds-dropdown__header>.hds-button,.hds-dropdown__header>.hds-form-text-input{margin:8px 0}.hds-dropdown__footer>.hds-button-set,.hds-dropdown__header>.hds-button-set{gap:8px;margin:8px 0}.hds-dropdown__footer--with-divider{border-top:1px solid var(--token-color-border-primary)}.hds-dropdown-list-item__copy-item-title{padding:2px 0 4px;color:var(--token-color-foreground-faint)}.hds-dropdown-list-item--variant-copy-item{width:100%;padding:10px 16px 12px}.hds-dropdown-list-item--variant-description{padding:2px 16px 4px;color:var(--token-color-foreground-faint)}.hds-dropdown-list-item--variant-generic{padding-right:16px;padding-left:16px}.hds-dropdown-list-item--variant-checkmark,.hds-dropdown-list-item--variant-interactive{position:relative;min-height:36px;isolation:isolate}.hds-dropdown-list-item--variant-checkmark button,.hds-dropdown-list-item--variant-interactive button{width:100%;background-color:transparent}.hds-dropdown-list-item--variant-checkmark button:hover,.hds-dropdown-list-item--variant-interactive button:hover{cursor:pointer}.hds-dropdown-list-item--variant-checkmark a,.hds-dropdown-list-item--variant-checkmark button,.hds-dropdown-list-item--variant-interactive a,.hds-dropdown-list-item--variant-interactive button{display:flex;align-items:flex-start;padding:7px 9px 7px 15px;text-decoration:none;border:1px solid transparent;outline-style:solid;outline-color:transparent}.hds-dropdown-list-item--variant-checkmark a::before,.hds-dropdown-list-item--variant-checkmark button::before,.hds-dropdown-list-item--variant-interactive a::before,.hds-dropdown-list-item--variant-interactive button::before{position:absolute;top:6px;bottom:6px;left:4px;z-index:-1;width:2px;border-radius:1px;content:""}.hds-dropdown-list-item--variant-checkmark a::after,.hds-dropdown-list-item--variant-checkmark button::after,.hds-dropdown-list-item--variant-interactive a::after,.hds-dropdown-list-item--variant-interactive button::after{position:absolute;top:0;right:4px;bottom:0;left:10px;z-index:-1;border-radius:5px;content:""}.hds-dropdown-list-item--variant-checkmark a.mock-hover,.hds-dropdown-list-item--variant-checkmark a:hover,.hds-dropdown-list-item--variant-checkmark button.mock-hover,.hds-dropdown-list-item--variant-checkmark button:hover,.hds-dropdown-list-item--variant-interactive a.mock-hover,.hds-dropdown-list-item--variant-interactive a:hover,.hds-dropdown-list-item--variant-interactive button.mock-hover,.hds-dropdown-list-item--variant-interactive button:hover{color:var(--current-color-hover)}.hds-dropdown-list-item--variant-checkmark a.mock-focus,.hds-dropdown-list-item--variant-checkmark a:focus,.hds-dropdown-list-item--variant-checkmark a:focus-visible,.hds-dropdown-list-item--variant-checkmark button.mock-focus,.hds-dropdown-list-item--variant-checkmark button:focus,.hds-dropdown-list-item--variant-checkmark button:focus-visible,.hds-dropdown-list-item--variant-interactive a.mock-focus,.hds-dropdown-list-item--variant-interactive a:focus,.hds-dropdown-list-item--variant-interactive a:focus-visible,.hds-dropdown-list-item--variant-interactive button.mock-focus,.hds-dropdown-list-item--variant-interactive button:focus,.hds-dropdown-list-item--variant-interactive button:focus-visible{color:var(--current-color-focus)}.hds-dropdown-list-item--variant-checkmark a.mock-hover::before,.hds-dropdown-list-item--variant-checkmark a:hover::before,.hds-dropdown-list-item--variant-checkmark button.mock-hover::before,.hds-dropdown-list-item--variant-checkmark button:hover::before,.hds-dropdown-list-item--variant-interactive a.mock-hover::before,.hds-dropdown-list-item--variant-interactive a:hover::before,.hds-dropdown-list-item--variant-interactive button.mock-hover::before,.hds-dropdown-list-item--variant-interactive button:hover::before{background-color:currentColor}.hds-dropdown-list-item--variant-checkmark a.mock-focus::after,.hds-dropdown-list-item--variant-checkmark a:focus::after,.hds-dropdown-list-item--variant-checkmark button.mock-focus::after,.hds-dropdown-list-item--variant-checkmark button:focus::after,.hds-dropdown-list-item--variant-interactive a.mock-focus::after,.hds-dropdown-list-item--variant-interactive a:focus::after,.hds-dropdown-list-item--variant-interactive button.mock-focus::after,.hds-dropdown-list-item--variant-interactive button:focus::after{left:4px;box-shadow:var(--current-focus-ring-box-shadow)}.hds-dropdown-list-item--variant-checkmark a:focus:not(:focus-visible)::after,.hds-dropdown-list-item--variant-checkmark button:focus:not(:focus-visible)::after,.hds-dropdown-list-item--variant-interactive a:focus:not(:focus-visible)::after,.hds-dropdown-list-item--variant-interactive button:focus:not(:focus-visible)::after{background-color:transparent;box-shadow:none}.hds-dropdown-list-item--variant-checkmark a:focus-visible::after,.hds-dropdown-list-item--variant-checkmark button:focus-visible::after,.hds-dropdown-list-item--variant-interactive a:focus-visible::after,.hds-dropdown-list-item--variant-interactive button:focus-visible::after{left:4px;box-shadow:var(--current-focus-ring-box-shadow)}.hds-dropdown-list-item--variant-checkmark a.mock-focus.mock-active::after,.hds-dropdown-list-item--variant-checkmark a:focus-visible:active::after,.hds-dropdown-list-item--variant-checkmark a:focus:active::after,.hds-dropdown-list-item--variant-checkmark button.mock-focus.mock-active::after,.hds-dropdown-list-item--variant-checkmark button:focus-visible:active::after,.hds-dropdown-list-item--variant-checkmark button:focus:active::after,.hds-dropdown-list-item--variant-interactive a.mock-focus.mock-active::after,.hds-dropdown-list-item--variant-interactive a:focus-visible:active::after,.hds-dropdown-list-item--variant-interactive a:focus:active::after,.hds-dropdown-list-item--variant-interactive button.mock-focus.mock-active::after,.hds-dropdown-list-item--variant-interactive button:focus-visible:active::after,.hds-dropdown-list-item--variant-interactive button:focus:active::after{left:10px;background-color:var(--current-background-color);box-shadow:none}.hds-dropdown-list-item--variant-checkmark a.mock-active,.hds-dropdown-list-item--variant-checkmark a:active,.hds-dropdown-list-item--variant-checkmark button.mock-active,.hds-dropdown-list-item--variant-checkmark button:active,.hds-dropdown-list-item--variant-interactive a.mock-active,.hds-dropdown-list-item--variant-interactive a:active,.hds-dropdown-list-item--variant-interactive button.mock-active,.hds-dropdown-list-item--variant-interactive button:active{color:var(--current-color-active)}.hds-dropdown-list-item--variant-checkmark a.mock-active::before,.hds-dropdown-list-item--variant-checkmark a:active::before,.hds-dropdown-list-item--variant-checkmark button.mock-active::before,.hds-dropdown-list-item--variant-checkmark button:active::before,.hds-dropdown-list-item--variant-interactive a.mock-active::before,.hds-dropdown-list-item--variant-interactive a:active::before,.hds-dropdown-list-item--variant-interactive button.mock-active::before,.hds-dropdown-list-item--variant-interactive button:active::before{background-color:currentColor}.hds-dropdown-list-item__interactive-icon{margin-top:2px;margin-right:8px}.hds-dropdown-list-item__interactive-text{flex:1;text-align:left}.hds-dropdown-list-item--color-action a,.hds-dropdown-list-item--color-action button{color:var(--token-color-foreground-primary);--current-color-hover:var(--token-color-foreground-action-hover);--current-color-focus:var(--token-color-foreground-action-active);--current-color-active:var(--token-color-foreground-action-active)}.hds-dropdown-list-item--color-action a::after,.hds-dropdown-list-item--color-action button::after{--current-focus-ring-box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-dropdown-list-item--color-critical a,.hds-dropdown-list-item--color-critical button{color:var(--token-color-foreground-critical);--current-color-hover:var(--token-color-palette-red-300);--current-color-focus:var(--token-color-palette-red-400);--current-color-active:var(--token-color-palette-red-400)}.hds-dropdown-list-item--color-critical a::after,.hds-dropdown-list-item--color-critical button::after{--current-background-color:var(--token-color-surface-critical);--current-focus-ring-box-shadow:var(--token-focus-ring-critical-box-shadow)}.hds-dropdown-list-item__interactive-loading-wrapper{display:flex;align-items:center;padding:8px 10px 8px 16px}.hds-dropdown-list-item__interactive-loading-wrapper .hds-dropdown-list-item__interactive-text{color:var(--token-color-foreground-faint)}.hds-dropdown-list-item__interactive-loading-wrapper .hds-dropdown-list-item__interactive-icon{color:var(--token-color-foreground-primary)}.hds-dropdown-list-item--variant-separator{position:relative;width:100%;height:4px}.hds-dropdown-list-item--variant-separator::before{position:absolute;right:6px;bottom:0;left:6px;content:""}.hds-dropdown-list-item--variant-title{padding:10px 16px 4px;color:var(--token-color-foreground-strong)}.hds-dropdown-list-item--variant-checkmark-selected .hds-dropdown-list-item__interactive{color:var(--token-color-foreground-action)}.hds-dropdown-list-item__checkmark{display:flex;width:16px;height:20px;margin-left:8px}.hds-dropdown-list-item__checkmark-icon{align-self:center}.hds-dropdown-list-item__interactive[disabled],.hds-dropdown-list-item__interactive[disabled]:hover{color:var(--token-color-foreground-disabled);cursor:not-allowed}.hds-dropdown-list-item--variant-checkbox,.hds-dropdown-list-item--variant-radio{display:flex;align-items:self-start;padding:8px 16px}.hds-dropdown-list-item--variant-checkbox .hds-dropdown-list-item__control,.hds-dropdown-list-item--variant-radio .hds-dropdown-list-item__control{flex-shrink:0;margin-top:2px;margin-right:8px}.hds-dropdown-list-item--variant-checkbox .hds-dropdown-list-item__control[disabled]~.hds-dropdown-list-item__count,.hds-dropdown-list-item--variant-checkbox .hds-dropdown-list-item__control[disabled]~.hds-dropdown-list-item__icon,.hds-dropdown-list-item--variant-checkbox .hds-dropdown-list-item__control[disabled]~.hds-dropdown-list-item__text-content,.hds-dropdown-list-item--variant-radio .hds-dropdown-list-item__control[disabled]~.hds-dropdown-list-item__count,.hds-dropdown-list-item--variant-radio .hds-dropdown-list-item__control[disabled]~.hds-dropdown-list-item__icon,.hds-dropdown-list-item--variant-radio .hds-dropdown-list-item__control[disabled]~.hds-dropdown-list-item__text-content{color:var(--token-color-foreground-disabled)}.hds-dropdown-list-item--variant-checkbox .hds-dropdown-list-item__label,.hds-dropdown-list-item--variant-radio .hds-dropdown-list-item__label{display:flex;flex-grow:1;align-items:flex-start;color:var(--token-color-foreground-primary)}.hds-dropdown-list-item--variant-checkbox .hds-dropdown-list-item__icon,.hds-dropdown-list-item--variant-radio .hds-dropdown-list-item__icon{margin-top:2px;margin-right:4px}.hds-dropdown-list-item__count{margin-left:auto;padding-left:8px;color:var(--token-color-foreground-faint);line-height:20px}.hds-dropdown-list-item--variant-checkbox .hds-badge,.hds-dropdown-list-item--variant-checkmark .hds-badge,.hds-dropdown-list-item--variant-radio .hds-badge{vertical-align:bottom}.hds-flyout{z-index:49;flex-direction:column;height:100vh;max-height:100vh;margin:0;padding:0;background:var(--token-color-surface-primary);border:none;box-shadow:0 2px 3px 0 rgba(59,61,69,.2509803922),0 12px 24px 0 rgba(59,61,69,.3490196078)}.hds-flyout__footer .hds-button-set .hds-button--color-tertiary,.hds-modal__footer .hds-button-set .hds-button--color-tertiary{margin-left:auto}.hds-flyout__body,.hds-flyout__footer{border-top:1px solid var(--token-color-border-primary)}.hds-flyout[open]{position:fixed;display:flex}.hds-flyout::backdrop{display:none}.hds-flyout__overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:49;background:var(--token-color-palette-neutral-700);opacity:.5}.hds-form-masked-input__toggle-button,.hds-form-text-input__visibility-toggle{right:calc(var(--token-form-control-padding) - var(--token-form-control-border-width))}.hds-flyout__header{display:flex;flex:none;gap:16px;align-items:flex-start;padding:16px 24px;color:var(--token-color-foreground-strong)}.hds-flyout__icon{flex:none;align-self:center}.hds-flyout__title{flex-grow:1}.hds-flyout__tagline{margin-bottom:4px}.hds-flyout__dismiss{align-self:center}.hds-flyout__description{padding:0 24px 16px}.hds-flyout__body{flex:1 1 auto;padding:24px;overflow-y:auto;overscroll-behavior:contain}.hds-flyout__footer{flex:none;padding:16px 24px;background:var(--token-color-surface-faint)}.hds-flyout--size-medium{width:min(480px,100vw - 40px);max-width:calc(100vw - 40px)}.hds-flyout--size-medium[open]{margin-left:calc(100% - min(480px,100vw - 40px))}.hds-flyout--size-large{width:min(720px,100vw - 40px);max-width:calc(100vw - 40px)}.hds-flyout--size-large[open]{margin-left:calc(100% - min(720px,100vw - 40px))}.hds-form-label{display:block;width:-moz-max-content;width:max-content;max-width:100%;color:var(--token-form-label-color)}.hds-form-label .hds-badge{vertical-align:initial}.hds-form-helper-text{display:block;color:var(--token-form-helper-text-color)}.hds-form-error{display:flex;gap:8px;align-items:flex-start;color:var(--token-form-error-color)}.hds-form-error__icon{flex:none;width:var(--token-form-error-icon-size);height:var(--token-form-error-icon-size);margin:2px 0}.hds-form-error__content{flex:1 1 auto}.hds-form-error__message{margin:0}.hds-form-field--layout-vertical{display:grid;justify-items:start;width:100%}.hds-form-field--layout-vertical .hds-form-field__label{width:-moz-fit-content;width:fit-content}.hds-form-field--layout-vertical .hds-form-field__helper-text:not(:first-child){margin-top:4px}.hds-form-field--layout-vertical .hds-form-field__helper-text+.hds-form-helper-text{margin-top:2px}.hds-form-field--layout-vertical .hds-form-field__control{display:flex;justify-self:stretch}.hds-form-field--layout-vertical .hds-form-field__control:not(:first-child){margin-top:8px}.hds-form-field--layout-vertical .hds-form-field__control:not(:last-child){margin-bottom:8px}.hds-form-field--layout-flag{display:grid;grid-auto-flow:row;grid-template-areas:"control label" "control helper-text" "control error";grid-template-rows:auto auto auto;grid-template-columns:auto 1fr;justify-items:start}.hds-form-field--layout-flag .hds-form-field__label{grid-area:label;width:-moz-fit-content;width:fit-content}.hds-form-field--layout-flag .hds-form-field__helper-text{grid-area:helper-text;margin-top:4px}.hds-form-field--layout-flag .hds-form-field__control{display:flex;grid-area:control}.hds-form-field--layout-flag .hds-form-field__control:not(:only-child){margin-top:2px;margin-right:8px}.hds-form-field--layout-flag .hds-form-field__error{grid-area:error;margin-top:4px}.hds-form-file-input{margin:-4px 0 -4px -4px;padding:3px 0 3px 3px;color:var(--token-color-foreground-primary)}.hds-form-file-input:focus,.hds-form-file-input:focus-visible{outline:0}.hds-form-file-input::file-selector-button{min-height:36px;margin-right:16px;padding:7px 16px 7px 37px;color:var(--token-color-foreground-primary);font:inherit;background-color:var(--token-color-surface-faint);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' viewBox='0 0 16 16'%3E%3Cg fill='%233b3d45'%3E%3Cpath d='M4.24 5.8a.75.75 0 001.06-.04l1.95-2.1v6.59a.75.75 0 001.5 0V3.66l1.95 2.1a.75.75 0 101.1-1.02l-3.25-3.5a.75.75 0 00-1.101.001L4.2 4.74a.75.75 0 00.04 1.06z'/%3E%3Cpath d='M1.75 9a.75.75 0 01.75.75v3c0 .414.336.75.75.75h9.5a.75.75 0 00.75-.75v-3a.75.75 0 011.5 0v3A2.25 2.25 0 0112.75 15h-9.5A2.25 2.25 0 011 12.75v-3A.75.75 0 011.75 9z'/%3E%3C/g%3E%3C/svg%3E");background-repeat:no-repeat;background-position:15px 50%;background-size:var(--token-form-text-input-background-image-size);border:1px solid var(--token-color-border-strong);border-radius:5px;box-shadow:var(--token-elevation-low-box-shadow);cursor:pointer}.hds-form-group__legend~.hds-form-group__control-fields-wrapper .hds-form-label,.hds-link-standalone{font-weight:var(--token-typography-font-weight-regular)}.hds-form-file-input.mock-hover::file-selector-button,.hds-form-file-input::file-selector-button:hover{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-primary);border-color:var(--token-color-border-strong)}.hds-form-file-input.mock-focus::file-selector-button,.hds-form-file-input:focus-within::file-selector-button{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint);border-color:var(--token-color-focus-action-internal);outline:var(--token-color-focus-action-external) solid 3px}.hds-form-file-input:not(:focus,.mock-focus)::file-selector-button{border-color:var(--token-color-border-strong);outline:0}.hds-form-file-input.mock-active::file-selector-button,.hds-form-file-input::file-selector-button:active{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong);box-shadow:none}.hds-form-file-input.mock-disabled,.hds-form-file-input.mock-disabled:focus,.hds-form-file-input.mock-disabled:hover,.hds-form-file-input:disabled,.hds-form-file-input:disabled:focus,.hds-form-file-input:disabled:hover,.hds-form-file-input[disabled],.hds-form-file-input[disabled]:focus,.hds-form-file-input[disabled]:hover{color:var(--token-color-foreground-disabled)}.hds-form-file-input.mock-disabled::file-selector-button,.hds-form-file-input.mock-disabled:focus::file-selector-button,.hds-form-file-input.mock-disabled:hover::file-selector-button,.hds-form-file-input:disabled::file-selector-button,.hds-form-file-input:disabled:focus::file-selector-button,.hds-form-file-input:disabled:hover::file-selector-button,.hds-form-file-input[disabled]::file-selector-button,.hds-form-file-input[disabled]:focus::file-selector-button,.hds-form-file-input[disabled]:hover::file-selector-button{color:var(--token-color-foreground-disabled);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-primary);box-shadow:none;cursor:not-allowed;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' viewBox='0 0 16 16'%3E%3Cg fill='%238c909c'%3E%3Cpath d='M4.24 5.8a.75.75 0 001.06-.04l1.95-2.1v6.59a.75.75 0 001.5 0V3.66l1.95 2.1a.75.75 0 101.1-1.02l-3.25-3.5a.75.75 0 00-1.101.001L4.2 4.74a.75.75 0 00.04 1.06z'/%3E%3Cpath d='M1.75 9a.75.75 0 01.75.75v3c0 .414.336.75.75.75h9.5a.75.75 0 00.75-.75v-3a.75.75 0 011.5 0v3A2.25 2.25 0 0112.75 15h-9.5A2.25 2.25 0 011 12.75v-3A.75.75 0 011.75 9z'/%3E%3C/g%3E%3C/svg%3E")}.hds-form-file-input.mock-disabled::file-selector-button::before,.hds-form-file-input.mock-disabled:focus::file-selector-button::before,.hds-form-file-input.mock-disabled:hover::file-selector-button::before,.hds-form-file-input:disabled::file-selector-button::before,.hds-form-file-input:disabled:focus::file-selector-button::before,.hds-form-file-input:disabled:hover::file-selector-button::before,.hds-form-file-input[disabled]::file-selector-button::before,.hds-form-file-input[disabled]:focus::file-selector-button::before,.hds-form-file-input[disabled]:hover::file-selector-button::before{border-color:transparent}.hds-form-legend{display:block;color:var(--token-form-legend-color)}.hds-form-legend .hds-badge{vertical-align:initial}.hds-form-group{display:block;margin:0;padding:0;border:none}.hds-form-checkbox,.hds-form-radio{background-position:center center;border-style:solid;-moz-appearance:none}.hds-form-group__legend{margin:0 0 4px;padding:0}.hds-form-group--layout-vertical .hds-form-group__control-fields-wrapper{display:flex;flex-direction:column}.hds-form-group--layout-vertical .hds-form-group__control-field+.hds-form-group__control-field{margin-top:12px}.hds-form-group--layout-horizontal .hds-form-group__control-fields-wrapper{display:flex;flex-wrap:wrap;margin-bottom:-4px}.hds-form-group--layout-horizontal .hds-form-group__control-field{margin-right:16px;margin-bottom:4px}.hds-form-group__helper-text{margin-bottom:8px}.hds-form-group__error{margin-top:8px}.hds-form-indicator--optional{color:var(--token-form-indicator-optional-color)}.hds-form-checkbox{width:var(--token-form-checkbox-size);height:var(--token-form-checkbox-size);margin:0;padding:0;background-size:var(--token-form-checkbox-background-image-size) var(--token-form-checkbox-background-image-size);border-width:var(--token-form-checkbox-border-width);border-radius:var(--token-form-checkbox-border-radius);cursor:pointer;-webkit-appearance:none;appearance:none}.hds-form-checkbox:not(:checked,:indeterminate){background-color:var(--token-form-control-base-surface-color-default);border-color:var(--token-form-control-base-border-color-default)}.hds-form-checkbox:checked,.hds-form-checkbox:indeterminate{background-color:var(--token-form-control-checked-surface-color-default);border-color:var(--token-form-control-checked-border-color-default)}.hds-form-checkbox:checked{background-image:var(--token-form-checkbox-background-image-data-url)}.hds-form-checkbox:indeterminate{background-image:var(--token-form-checkbox-background-image-data-url-indeterminate)}.hds-form-checkbox.mock-hover:not(:checked,:indeterminate),.hds-form-checkbox:hover:not(:checked,:indeterminate){background-color:var(--token-form-control-base-surface-color-hover);border-color:var(--token-form-control-base-border-color-hover)}.hds-form-checkbox.mock-hover:checked,.hds-form-checkbox.mock-hover:indeterminate,.hds-form-checkbox:hover:checked,.hds-form-checkbox:hover:indeterminate{background-color:var(--token-form-control-checked-border-color-default);border-color:var(--token-form-control-checked-border-color-hover)}.hds-form-checkbox:disabled:checked,.hds-form-checkbox:disabled:indeterminate,.hds-form-checkbox:disabled:not(:checked,:indeterminate){background-color:var(--token-form-control-disabled-surface-color);border-color:var(--token-form-control-disabled-border-color);box-shadow:none;cursor:not-allowed}.hds-form-checkbox.mock-focus,.hds-form-checkbox:focus{outline:var(--token-color-focus-action-external) solid 3px;outline-offset:1px}.hds-form-checkbox:disabled:checked{background-image:var(--token-form-checkbox-background-image-data-url-disabled)}.hds-form-checkbox:disabled:indeterminate{background-image:var(--token-form-checkbox-background-image-data-url-indeterminate-disabled);background-repeat:no-repeat}.hds-form-masked-input{position:relative;display:grid;grid-template-areas:"input copy-button";grid-template-columns:1fr auto;width:100%}.hds-form-masked-input .hds-form-masked-input__control{grid-area:input;padding-right:calc(var(--token-form-control-padding) + 24px)}.hds-form-masked-input--is-masked .hds-form-masked-input__control{-webkit-text-security:disc}.hds-form-masked-input--is-not-masked .hds-form-masked-input__control{-webkit-text-security:none}.hds-form-masked-input__toggle-button{position:absolute;top:calc(var(--token-form-control-padding) - var(--token-form-control-border-width));grid-area:input}.hds-form-masked-input__copy-button{grid-area:copy-button;align-self:flex-start;margin-left:8px}.hds-form-radio{width:var(--token-form-radio-size);height:var(--token-form-radio-size);margin:0;padding:0;background-size:var(--token-form-radio-background-image-size) var(--token-form-radio-background-image-size);border-width:var(--token-form-radio-border-width);border-radius:50%;cursor:pointer;-webkit-appearance:none;appearance:none}.hds-form-radio:not(:checked){background-color:var(--token-form-control-base-surface-color-default);border-color:var(--token-form-control-base-border-color-default);box-shadow:var(--token-elevation-inset-box-shadow)}.hds-form-radio:checked{background-color:var(--token-form-control-checked-surface-color-default);background-image:var(--token-form-radio-background-image-data-url);border-color:var(--token-form-control-checked-border-color-default)}.hds-form-radio.mock-hover:not(:checked),.hds-form-radio:hover:not(:checked){background-color:var(--token-form-control-base-surface-color-hover);border-color:var(--token-form-control-base-border-color-hover)}.hds-form-radio.mock-hover:checked,.hds-form-radio:hover:checked{background-color:var(--token-form-control-checked-border-color-default);border-color:var(--token-form-control-checked-border-color-hover)}.hds-form-radio:disabled:checked,.hds-form-radio:disabled:not(:checked){background-color:var(--token-form-control-disabled-surface-color);border-color:var(--token-form-control-disabled-border-color);box-shadow:none;cursor:not-allowed}.hds-form-radio.mock-focus,.hds-form-radio:focus{outline:var(--token-color-focus-action-external) solid 3px;outline-offset:1px}.hds-form-radio:disabled:checked{background-image:var(--token-form-radio-background-image-data-url-disabled)}.hds-form-group--radio-cards .hds-form-group__control-fields-wrapper{margin:calc(-1 * var(--token-form-radiocard-group-gap)/ 2)}.hds-form-group--radio-cards .hds-form-group__legend{margin-bottom:12px}.hds-form-group--radio-cards .hds-form-radio-card{margin:calc(var(--token-form-radiocard-group-gap)/ 2)}.hds-form-group--radio-cards .hds-form-radio-card--has-fixed-width{flex:1 0 100%}.hds-form-radio-card{display:flex;flex-direction:column;background-color:var(--token-color-surface-primary);border:var(--token-form-radiocard-border-width) solid var(--token-color-border-primary);border-radius:var(--token-form-radiocard-border-radius);box-shadow:var(--token-elevation-mid-box-shadow);cursor:pointer}.hds-form-radio-card .hds-form-radio-card__control{outline-color:transparent}.hds-form-radio-card.mock-hover,.hds-form-radio-card:hover{box-shadow:var(--token-elevation-high-box-shadow);transition:var(--token-form-radiocard-transition-duration)}.hds-form-radio-card.mock-focus,.hds-form-radio-card:focus-within{border-color:var(--token-color-focus-action-internal);box-shadow:0 0 0 3px var(--token-color-focus-action-external)}.hds-form-radio-card--checked,.hds-form-radio-card.mock-checked{border-color:var(--token-color-focus-action-internal)}.hds-form-radio-card--checked .hds-form-radio-card__control-wrapper,.hds-form-radio-card.mock-checked .hds-form-radio-card__control-wrapper{background-color:var(--token-color-surface-action);border-color:var(--token-color-border-action)}.hds-form-radio-card--disabled,.hds-form-radio-card--disabled .hds-form-radio-card__control-wrapper,.hds-form-radio-card.mock-disabled,.hds-form-radio-card.mock-disabled .hds-form-radio-card__control-wrapper{background-color:var(--token-color-surface-interactive-disabled);border-color:var(--token-color-border-primary)}.hds-form-radio-card--disabled,.hds-form-radio-card.mock-disabled{box-shadow:none;cursor:not-allowed}.hds-form-radio-card--align-left{text-align:left}.hds-form-radio-card--align-center{text-align:center}.hds-form-radio-card--align-center .flight-icon{margin:auto}.hds-form-radio-card--control-bottom .hds-form-radio-card__control-wrapper{border-top-width:var(--token-form-radiocard-border-width);border-top-style:solid;border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.hds-form-radio-card--control-left{flex-direction:row-reverse}.hds-form-radio-card--control-left .hds-form-radio-card__control-wrapper{display:flex;align-items:center;border-right-width:var(--token-form-radiocard-border-width);border-right-style:solid;border-top-left-radius:inherit;border-bottom-left-radius:inherit}.hds-form-radio-card__content{flex:1;padding:var(--token-form-radiocard-content-padding)}.hds-form-radio-card__content .hds-badge{margin-bottom:12px}.hds-form-radio-card__label{display:block;margin:8px 0;color:var(--token-form-label-color);overflow-wrap:break-word}.hds-form-radio-card__label:first-child{margin-top:0}.hds-form-radio-card__description{display:block;color:var(--token-color-foreground-primary)}.hds-form-radio-card__control-wrapper{padding:var(--token-form-radiocard-control-padding);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-primary)}.hds-form-select,.hds-form-text-input{border:var(--token-form-control-border-width) solid var(--token-form-control-base-border-color-default)}.hds-form-radio-card__control{display:block;margin:auto}.hds-form-select{max-width:100%;padding:var(--token-form-control-padding);padding-right:calc(var(--token-form-control-padding) + 24px);color:var(--token-form-control-base-foreground-value-color);background-color:var(--token-form-control-base-surface-color-default);background-image:var(--token-form-select-background-image-data-url);background-repeat:no-repeat;background-position:right var(--token-form-select-background-image-position-right-x) top var(--token-form-select-background-image-position-top-y);background-size:var(--token-form-select-background-image-size) var(--token-form-select-background-image-size);border-radius:var(--token-form-control-border-radius);box-shadow:var(--token-elevation-low-box-shadow);-webkit-appearance:none;-moz-appearance:none;appearance:none}.hds-form-select.mock-hover,.hds-form-select:hover{border-color:var(--token-form-control-base-border-color-hover)}.hds-form-select.mock-focus,.hds-form-select:focus{border-color:var(--token-color-focus-action-internal);outline:var(--token-color-focus-action-external) solid 3px;outline-offset:0}.hds-form-select:disabled{color:var(--token-form-control-disabled-foreground-color);background-color:var(--token-form-control-disabled-surface-color);background-image:var(--token-form-select-background-image-data-url-disabled);border-color:var(--token-form-control-disabled-border-color);box-shadow:none;cursor:not-allowed}.hds-form-select.hds-form-select--is-invalid{border-color:var(--token-form-control-invalid-border-color-default)}.hds-form-select.hds-form-select--is-invalid.mock-hover,.hds-form-select.hds-form-select--is-invalid:hover{border-color:var(--token-form-control-invalid-border-color-hover)}.hds-form-select.hds-form-select--is-invalid.mock-focus,.hds-form-select.hds-form-select--is-invalid:focus{border-color:var(--token-color-focus-critical-internal);outline-color:var(--token-color-focus-critical-external)}.hds-form-select[multiple],.hds-form-select[size]{background:0 0}.hds-form-select[multiple] option,.hds-form-select[size] option{margin:2px auto;border-radius:3px}.hds-form-select[multiple] option:hover,.hds-form-select[size] option:hover{color:var(--token-color-foreground-action)}.hds-form-select[multiple] option:disabled,.hds-form-select[size] option:disabled{color:var(--token-color-foreground-disabled)}.hds-form-select[multiple] option:checked,.hds-form-select[size] option:checked{color:var(--token-color-foreground-high-contrast);background:var(--token-color-palette-blue-200)}.hds-form-text-input,.hds-form-textarea{background-color:var(--token-form-control-base-surface-color-default);max-width:100%}.hds-form-select[multiple] optgroup,.hds-form-select[size] optgroup{color:var(--token-color-foreground-strong);font-weight:var(--token-typography-font-weight-semibold);font-style:normal}.hds-form-text-input{width:100%;padding:var(--token-form-control-padding);color:var(--token-form-control-base-foreground-value-color);border-radius:var(--token-form-control-border-radius);box-shadow:var(--token-elevation-inset-box-shadow)}.hds-form-text-input ::-moz-placeholder{color:var(--token-form-control-base-foreground-placeholder-color)}.hds-form-text-input ::placeholder{color:var(--token-form-control-base-foreground-placeholder-color)}.hds-form-text-input.mock-hover,.hds-form-text-input:hover{border-color:var(--token-form-control-base-border-color-hover)}.hds-form-text-input.mock-focus,.hds-form-text-input:focus{border-color:var(--token-color-focus-action-internal);outline:var(--token-color-focus-action-external) solid 3px;outline-offset:0}.hds-form-text-input:-moz-read-only{color:var(--token-form-control-readonly-foreground-color);background-color:var(--token-form-control-readonly-surface-color);border-color:var(--token-form-control-readonly-border-color);box-shadow:none}.hds-form-text-input:read-only{color:var(--token-form-control-readonly-foreground-color);background-color:var(--token-form-control-readonly-surface-color);border-color:var(--token-form-control-readonly-border-color);box-shadow:none}.hds-form-text-input:disabled{color:var(--token-form-control-disabled-foreground-color);background-color:var(--token-form-control-disabled-surface-color);border-color:var(--token-form-control-disabled-border-color);box-shadow:none;cursor:not-allowed}.hds-form-text-input.hds-form-text-input--is-invalid{border-color:var(--token-form-control-invalid-border-color-default)}.hds-form-text-input.hds-form-text-input--is-invalid.mock-hover,.hds-form-text-input.hds-form-text-input--is-invalid:hover{border-color:var(--token-form-control-invalid-border-color-hover)}.hds-form-text-input.hds-form-text-input--is-invalid.mock-focus,.hds-form-text-input.hds-form-text-input--is-invalid:focus{border-color:var(--token-color-focus-critical-internal);outline-color:var(--token-color-focus-critical-external)}.hds-form-text-input__wrapper{position:relative;width:100%}.hds-form-text-input--has-visibility-toggle{padding-right:calc(var(--token-form-control-padding) + 24px)}.hds-form-text-input__visibility-toggle{position:absolute;top:calc(var(--token-form-control-padding) - var(--token-form-control-border-width))}.hds-form-text-input[type=date],.hds-form-text-input[type=datetime-local],.hds-form-text-input[type=time]{width:initial}.hds-form-text-input[type=date]:disabled::-webkit-calendar-picker-indicator,.hds-form-text-input[type=datetime-local]:disabled::-webkit-calendar-picker-indicator,.hds-form-text-input[type=time]:disabled::-webkit-calendar-picker-indicator{visibility:visible;opacity:.5}.hds-form-text-input[type=date][readonly]::-webkit-calendar-picker-indicator,.hds-form-text-input[type=datetime-local][readonly]::-webkit-calendar-picker-indicator,.hds-form-text-input[type=time][readonly]::-webkit-calendar-picker-indicator{visibility:visible}.hds-form-text-input[type=date]::-webkit-calendar-picker-indicator,.hds-form-text-input[type=datetime-local]::-webkit-calendar-picker-indicator{background-image:var(--token-form-text-input-background-image-data-url-date);background-position:center center;background-size:var(--token-form-text-input-background-image-size)}.hds-form-text-input[type=time]::-webkit-calendar-picker-indicator{background-image:var(--token-form-text-input-background-image-data-url-time);background-position:center center;background-size:var(--token-form-text-input-background-image-size)}.hds-form-text-input[type=search]{padding-left:calc(var(--token-form-control-padding) + 24px);background-image:var(--token-form-text-input-background-image-data-url-search);background-repeat:no-repeat;background-position:var(--token-form-text-input-background-image-position-x) 50%;background-size:var(--token-form-text-input-background-image-size)}.hds-form-text-input[type=search]::-webkit-search-cancel-button{width:var(--token-form-text-input-background-image-size);height:var(--token-form-text-input-background-image-size);background-image:var(--token-form-text-input-background-image-data-url-search-cancel);background-position:center center;background-size:var(--token-form-text-input-background-image-size);-webkit-appearance:none}.hds-form-text-input[type=search].hds-form-text-input--is-loading{background-image:var(--token-form-text-input-background-image-data-url-search-loading)}.hds-form-textarea{width:100%;min-height:36px;padding:var(--token-form-control-padding);color:var(--token-form-control-base-foreground-value-color);border:var(--token-form-control-border-width) solid var(--token-form-control-base-border-color-default);border-radius:var(--token-form-control-border-radius);box-shadow:var(--token-elevation-inset-box-shadow);resize:vertical}.hds-form-textarea ::-moz-placeholder{color:var(--token-form-control-base-foreground-placeholder-color)}.hds-form-textarea ::placeholder{color:var(--token-form-control-base-foreground-placeholder-color)}.hds-form-textarea.mock-hover,.hds-form-textarea:hover{border-color:var(--token-form-control-base-border-color-hover)}.hds-form-textarea.mock-focus,.hds-form-textarea:focus{border-color:var(--token-color-focus-action-internal);outline:var(--token-color-focus-action-external) solid 3px;outline-offset:0}.hds-form-textarea:-moz-read-only{color:var(--token-form-control-readonly-foreground-color);background-color:var(--token-form-control-readonly-surface-color);border-color:var(--token-form-control-readonly-border-color);box-shadow:none}.hds-form-textarea:read-only{color:var(--token-form-control-readonly-foreground-color);background-color:var(--token-form-control-readonly-surface-color);border-color:var(--token-form-control-readonly-border-color);box-shadow:none}.hds-form-textarea:disabled{color:var(--token-form-control-disabled-foreground-color);background-color:var(--token-form-control-disabled-surface-color);border-color:var(--token-form-control-disabled-border-color);box-shadow:none;cursor:not-allowed}.hds-form-textarea.hds-form-textarea--is-invalid{border-color:var(--token-form-control-invalid-border-color-default)}.hds-form-textarea.hds-form-textarea--is-invalid.mock-hover,.hds-form-textarea.hds-form-textarea--is-invalid:hover{border-color:var(--token-form-control-invalid-border-color-hover)}.hds-form-textarea.hds-form-textarea--is-invalid.mock-focus,.hds-form-textarea.hds-form-textarea--is-invalid:focus{border-color:var(--token-color-focus-critical-internal);outline-color:var(--token-color-focus-critical-external)}.hds-form-toggle{position:relative;isolation:isolate}.hds-form-toggle__control{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;display:block;height:100%;margin:0;padding:0;color:transparent;background-color:transparent;border:none;outline:0;cursor:pointer;opacity:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.hds-form-toggle__control:disabled{cursor:not-allowed}.hds-form-toggle__facade{position:relative;display:block;width:var(--token-form-toggle-width);height:var(--token-form-toggle-height);background-image:var(--token-form-toggle-background-image-data-url);background-repeat:no-repeat;background-position:var(--token-form-toggle-background-image-position-x) 50%;background-size:var(--token-form-toggle-background-image-size) var(--token-form-toggle-background-image-size);border:var(--token-form-radio-border-width) solid var(--border-color);border-radius:calc(var(--token-form-toggle-height)/ 2)}.hds-form-toggle__facade::after{position:absolute;top:calc(var(--token-form-radio-border-width) * -1);left:calc(var(--token-form-radio-border-width) * -1);width:var(--token-form-toggle-thumb-size);height:var(--token-form-toggle-thumb-size);background-color:var(--token-form-control-base-surface-color-default);border:var(--token-form-radio-border-width) solid var(--border-color);border-radius:50%;transform:translate3d(0,0,0);content:""}@media (prefers-reduced-motion:no-preference){.hds-form-toggle__facade,.hds-form-toggle__facade::after{transition-timing-function:var(--token-form-toggle-transition-timing-function);transition-duration:var(--token-form-toggle-transition-duration);transition-property:all}}.hds-form-toggle__facade::before{position:absolute;top:-5px;right:-5px;bottom:-5px;left:-5px;margin:auto;border-width:3px;border-radius:calc(var(--token-form-toggle-height)/ 2 + 3px + 1px);content:""}:not(:checked)+.hds-form-toggle__facade{--border-color:var(--token-form-control-base-border-color-default);background-color:var(--token-form-toggle-base-surface-color-default)}:checked+.hds-form-toggle__facade{--border-color:var(--token-form-control-checked-border-color-default);background-color:var(--token-form-control-checked-surface-color-default)}:checked+.hds-form-toggle__facade::after{transform:translate3d(calc(var(--token-form-toggle-width) - var(--token-form-toggle-thumb-size)),0,0)}.mock-hover:not(:checked)+.hds-form-toggle__facade,:hover:not(:checked)+.hds-form-toggle__facade{--border-color:var(--token-form-control-base-border-color-hover)}.mock-hover:checked+.hds-form-toggle__facade,:hover:checked+.hds-form-toggle__facade{--border-color:var(--token-form-control-checked-border-color-hover);background-color:var(--token-form-control-checked-border-color-default)}.mock-focus+.hds-form-toggle__facade::before,:focus+.hds-form-toggle__facade::before{border-color:var(--token-color-focus-action-external);border-style:solid}:disabled:checked+.hds-form-toggle__facade,:disabled:not(:checked)+.hds-form-toggle__facade{--border-color:var(--token-form-control-disabled-border-color);background-color:var(--token-form-control-disabled-surface-color);background-image:var(--token-form-toggle-background-image-data-url-disabled)}.hds-form-visibility-toggle{width:24px;height:24px;padding:2px;color:var(--token-color-foreground-primary);background-color:transparent;border-color:transparent;cursor:pointer}.hds-icon-tile--logo,.hds-icon-tile__extra{background-color:var(--token-color-surface-primary)}.hds-icon-tile{position:relative;display:flex;border:1px solid transparent;border-radius:4px;box-shadow:0 1px 1px rgba(101,106,118,.05)}.hds-icon-tile__icon,.hds-icon-tile__logo{display:flex;margin:auto}.hds-icon-tile__extra{position:absolute;right:-6px;bottom:-6px;display:flex;box-sizing:content-box;border:1px solid var(--token-color-border-primary);box-shadow:0 1px 1px rgba(101,106,118,.05)}.hds-icon-tile__extra-icon{display:flex;margin:auto;color:var(--token-color-foreground-strong)}.hds-icon-tile--size-small{width:1.75rem;height:1.75rem;border-radius:5px}.hds-icon-tile--size-small .hds-icon-tile__icon{width:1rem;height:1rem}.hds-icon-tile--size-small .hds-icon-tile__logo{width:1.125rem;height:1.125rem}.hds-icon-tile--size-small .hds-icon-tile__extra{width:1.125rem;height:1.125rem;border-radius:4px}.hds-icon-tile--size-small .hds-icon-tile__extra-icon{width:.75rem;height:.75rem}.hds-icon-tile--size-medium{width:2.5rem;height:2.5rem;border-radius:6px}.hds-icon-tile--size-medium .hds-icon-tile__icon{width:1.5rem;height:1.5rem}.hds-icon-tile--size-medium .hds-icon-tile__logo{width:1.75rem;height:1.75rem}.hds-icon-tile--size-medium .hds-icon-tile__extra{width:1.5rem;height:1.5rem;border-radius:5px}.hds-icon-tile--size-medium .hds-icon-tile__extra-icon{width:1rem;height:1rem}.hds-icon-tile--size-large{width:3rem;height:3rem;border-radius:6px}.hds-icon-tile--size-large .hds-icon-tile__icon{width:1.5rem;height:1.5rem}.hds-icon-tile--size-large .hds-icon-tile__logo{width:2rem;height:2rem}.hds-icon-tile--size-large .hds-icon-tile__extra{width:1.5rem;height:1.5rem;border-radius:5px}.hds-icon-tile--size-large .hds-icon-tile__extra-icon{width:1rem;height:1rem}.hds-icon-tile--logo{border-color:var(--token-color-border-primary)}.hds-icon-tile--icon.hds-icon-tile--color-neutral{color:var(--token-color-foreground-faint);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-primary)}.hds-icon-tile--icon.hds-icon-tile--color-boundary{color:var(--token-color-boundary-foreground);background:linear-gradient(135deg,var(--token-color-boundary-gradient-faint-start) 0,var(--token-color-boundary-gradient-faint-stop) 100%);border-color:var(--token-color-boundary-border)}.hds-icon-tile--icon.hds-icon-tile--color-consul{color:var(--token-color-consul-foreground);background:linear-gradient(135deg,var(--token-color-consul-gradient-faint-start) 0,var(--token-color-consul-gradient-faint-stop) 100%);border-color:var(--token-color-consul-border)}.hds-icon-tile--icon.hds-icon-tile--color-hcp{color:var(--token-color-palette-hcp-brand);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-primary)}.hds-icon-tile--icon.hds-icon-tile--color-nomad{color:var(--token-color-nomad-foreground);background:linear-gradient(135deg,var(--token-color-nomad-gradient-faint-start) 0,var(--token-color-nomad-gradient-faint-stop) 100%);border-color:var(--token-color-nomad-border)}.hds-icon-tile--icon.hds-icon-tile--color-packer{color:var(--token-color-packer-foreground);background:linear-gradient(135deg,var(--token-color-packer-gradient-faint-start) 0,var(--token-color-packer-gradient-faint-stop) 100%);border-color:var(--token-color-packer-border)}.hds-icon-tile--icon.hds-icon-tile--color-terraform{color:var(--token-color-terraform-foreground);background:linear-gradient(135deg,var(--token-color-terraform-gradient-faint-start) 0,var(--token-color-terraform-gradient-faint-stop) 100%);border-color:var(--token-color-terraform-border)}.hds-icon-tile--icon.hds-icon-tile--color-vagrant{color:var(--token-color-vagrant-foreground);background:linear-gradient(135deg,var(--token-color-vagrant-gradient-faint-start) 0,var(--token-color-vagrant-gradient-faint-stop) 100%);border-color:var(--token-color-vagrant-border)}.hds-icon-tile--icon.hds-icon-tile--color-vault{color:var(--token-color-vault-foreground);background:linear-gradient(135deg,var(--token-color-vault-gradient-faint-start) 0,var(--token-color-vault-gradient-faint-stop) 100%);border-color:var(--token-color-vault-border)}.hds-icon-tile--icon.hds-icon-tile--color-vault-secrets{color:var(--token-color-vault-secrets-foreground);background:linear-gradient(135deg,var(--token-color-vault-secrets-gradient-faint-start) 0,var(--token-color-vault-secrets-gradient-faint-stop) 100%);border-color:var(--token-color-vault-secrets-border)}.hds-icon-tile--icon.hds-icon-tile--color-waypoint{color:var(--token-color-waypoint-foreground);background:linear-gradient(135deg,var(--token-color-waypoint-gradient-faint-start) 0,var(--token-color-waypoint-gradient-faint-stop) 100%);border-color:var(--token-color-waypoint-border)}.hds-link-inline{border-radius:2px}.hds-link-inline.mock-focus,.hds-link-inline:focus,.hds-link-inline:focus-visible{text-decoration:none;outline:var(--token-color-focus-action-internal) solid 2px;outline-offset:1px}.hds-link-inline__icon{display:inline-block;width:1em;height:1em;vertical-align:text-bottom}.hds-link-inline--icon-leading>.hds-link-inline__icon{margin-right:.25em}.hds-link-inline--icon-trailing>.hds-link-inline__icon{margin-left:.25em}.hds-link-inline--color-primary{color:var(--token-color-foreground-action)}.hds-link-inline--color-primary.mock-hover,.hds-link-inline--color-primary:hover{color:var(--token-color-foreground-action-hover)}.hds-link-inline--color-primary.mock-active,.hds-link-inline--color-primary:active{color:var(--token-color-foreground-action-active)}.hds-link-inline--color-secondary{color:var(--token-color-foreground-strong)}.hds-link-inline--color-secondary.mock-hover,.hds-link-inline--color-secondary:hover{color:var(--token-color-foreground-primary)}.hds-link-inline--color-secondary.mock-active,.hds-link-inline--color-secondary:active{color:var(--token-color-foreground-faint)}.hds-link-standalone{display:flex;align-items:center;justify-content:center;width:-moz-fit-content;width:fit-content;padding-top:4px;padding-bottom:4px;background-color:transparent;border:1px solid transparent;text-decoration-color:transparent;position:relative;outline-style:solid;outline-color:transparent}.hds-link-standalone__text{flex:1 0 0;text-decoration:underline;text-decoration-color:transparent;transition:text-decoration-color .25s ease-in}#login-toggle+div footer button,.consul-intention-fieldsets .permissions>button,.empty-state>ul>li>*,.empty-state>ul>li>:active,.empty-state>ul>li>label>button,.empty-state>ul>li>label>button:active,.hds-pagination-nav__control,.hds-side-nav__list-item-link,.hds-tabs__tab,.modal-dialog [role=document] dd a,.modal-dialog [role=document] p a,.oidc-select button.reset,.search-bar-status .remove-all button,a,main dd a,main dd a:active,main p a,main p a:active{text-decoration:none}.hds-link-standalone--size-small .hds-link-standalone__icon{width:.75rem;height:.75rem}.hds-link-standalone--size-small .hds-link-standalone__text{font-size:.8125rem;line-height:1.231}.hds-link-standalone--size-medium .hds-link-standalone__icon{width:1rem;height:1rem}.hds-link-standalone--size-medium .hds-link-standalone__text{font-size:.875rem;line-height:1.143}.hds-link-standalone--size-large .hds-link-standalone__icon{width:1.5rem;height:1.5rem}.hds-link-standalone--size-large .hds-link-standalone__text{font-size:1rem;line-height:1.5}.hds-link-standalone--color-primary{color:var(--token-color-foreground-action)}.hds-link-standalone--color-primary.mock-hover,.hds-link-standalone--color-primary:hover{color:var(--token-color-foreground-action-hover)}.hds-link-standalone--color-primary.mock-hover .hds-link-standalone__text,.hds-link-standalone--color-primary:hover .hds-link-standalone__text{text-decoration-color:#4e81e8}.hds-link-standalone--color-primary.mock-active,.hds-link-standalone--color-primary:active{color:var(--token-color-foreground-action-active)}.hds-link-standalone--color-primary.mock-active .hds-link-standalone__text,.hds-link-standalone--color-primary:active .hds-link-standalone__text{text-decoration-color:#396ed6}.hds-link-standalone--color-primary.mock-active::before,.hds-link-standalone--color-primary:active::before{background-color:var(--token-color-surface-action)}.hds-link-standalone--color-secondary{color:var(--token-color-foreground-strong)}.hds-link-standalone--color-secondary.mock-hover .hds-link-standalone__text,.hds-link-standalone--color-secondary:hover .hds-link-standalone__text{text-decoration-color:#4d4d4f}.hds-link-standalone--color-secondary.mock-active,.hds-link-standalone--color-secondary:active{color:var(--token-color-foreground-primary)}.hds-link-standalone--color-secondary.mock-active .hds-link-standalone__text,.hds-link-standalone--color-secondary:active .hds-link-standalone__text{text-decoration-color:#6e7075}.hds-link-standalone--color-secondary.mock-active::before,.hds-link-standalone--color-secondary:active::before{background-color:var(--token-color-surface-interactive-active)}.hds-link-standalone::before{position:absolute;top:0;right:-5px;bottom:0;left:-5px;z-index:-1;border-radius:5px;content:""}.hds-link-standalone:focus:not(:focus-visible)::before{box-shadow:none}.hds-link-standalone:focus-visible::before,.hds-pagination-nav__control.mock-focus::before,.hds-pagination-nav__control:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-link-standalone.mock-focus.mock-active::before,.hds-link-standalone:focus:active::before{box-shadow:none}.hds-link-standalone.hds-link-standalone--icon-position-leading::before{right:-7px}.hds-link-standalone.hds-link-standalone--icon-position-trailing::before{left:-7px}.hds-menu-primitive{position:relative;width:-moz-fit-content;width:fit-content}.hds-modal{z-index:50;flex-direction:column;padding:0;background:var(--token-color-surface-primary);border:none;border-radius:8px;box-shadow:var(--token-surface-overlay-box-shadow)}.hds-modal[open]{position:fixed;display:flex}.hds-modal::backdrop{display:none}.hds-modal__overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;background:var(--token-color-palette-neutral-700);opacity:.5}.hds-modal__header{display:flex;flex:none;gap:16px;align-items:flex-start;padding:16px 24px;border-top-left-radius:inherit;border-top-right-radius:inherit}.hds-modal__icon{flex:none;align-self:center}.freetext-filter>label,.freetext-filter_input,.hds-modal__title{flex-grow:1}.hds-modal__tagline{margin-bottom:4px}.hds-modal__dismiss{align-self:center}.hds-modal__body{flex:1 1 auto;padding:24px;overflow-y:auto;overscroll-behavior:contain}.hds-modal__footer{flex:none;padding:16px 24px;background:var(--token-color-surface-faint);border-top:1px solid var(--token-color-border-primary);border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.hds-modal--size-small{width:min(400px,95vw)}.hds-modal--size-medium{width:min(600px,95vw)}.hds-modal--size-large{width:min(800px,95vw)}.hds-modal--color-neutral .hds-modal__header{color:var(--token-color-foreground-strong);background:var(--token-color-surface-faint);border-bottom:1px solid var(--token-color-border-primary)}.hds-modal--color-neutral .hds-modal__tagline{color:var(--token-color-foreground-faint)}.hds-modal--color-warning .hds-modal__header,.hds-modal--color-warning .hds-modal__tagline{color:var(--token-color-foreground-warning-on-surface)}.hds-modal--color-warning .hds-modal__header{background:var(--token-color-surface-warning);border-bottom:1px solid var(--token-color-border-warning)}.hds-modal--color-critical .hds-modal__header,.hds-modal--color-critical .hds-modal__tagline{color:var(--token-color-foreground-critical-on-surface)}.hds-modal--color-critical .hds-modal__header{background:var(--token-color-surface-critical);border-bottom:1px solid var(--token-color-border-critical)}.hds-page-header{position:relative;display:flex;flex-direction:column;gap:16px;container-type:inline-size}.hds-page-header__body{display:flex;flex-direction:column;gap:8px 16px}.hds-page-header__body .hds-icon-tile{flex-shrink:0}@container (min-width:400px){.hds-page-header__body{flex-direction:row}}.hds-page-header__main{display:flex;flex-direction:column;flex-grow:1;gap:16px;align-items:start;justify-content:start}@container (min-width:768px){.hds-page-header__main{flex-direction:row;justify-content:space-between;min-width:0}}.hds-page-header__content{display:flex;flex-direction:column;flex-grow:1;gap:8px;min-width:0;max-width:100%}.hds-page-header__title-wrapper{display:flex;flex-direction:row;flex-wrap:wrap;gap:8px 16px;align-items:center}.hds-page-header__title{max-width:100%;overflow-wrap:break-word}.hds-page-header__badges-wrapper{display:flex;flex-wrap:wrap;gap:8px}.hds-page-header__metadata{display:flex;flex-direction:column;gap:4px}.hds-page-header__description,.hds-page-header__subtitle{overflow-wrap:break-word}.hds-page-header__actions{display:flex;flex-direction:row;flex-shrink:0;flex-wrap:wrap;gap:16px;align-items:center}.hds-pagination{display:grid;grid-template-areas:"info nav selector";grid-template-rows:auto;grid-template-columns:1fr auto 1fr;align-items:center;margin:0 auto}@media screen and (max-width:1000px){.hds-pagination{display:flex;flex-wrap:wrap;justify-content:center}.hds-pagination .hds-pagination-info{margin-top:var(--token-pagination-child-spacing-vertical);margin-left:var(--token-pagination-child-spacing-horizontal)}}.hds-pagination .hds-pagination-info{grid-area:info;justify-self:flex-start;margin-right:var(--token-pagination-child-spacing-horizontal)}.hds-pagination .hds-pagination-nav{grid-area:nav}@media screen and (max-width:1000px){.hds-pagination .hds-pagination-nav{justify-content:center;order:-1;width:100%}.hds-pagination .hds-pagination-size-selector{margin-top:var(--token-pagination-child-spacing-vertical);margin-right:var(--token-pagination-child-spacing-horizontal)}}.hds-pagination .hds-pagination-size-selector{grid-area:selector;justify-self:flex-end;margin-left:var(--token-pagination-child-spacing-horizontal)}.hds-pagination-info{white-space:nowrap}.hds-pagination-nav{display:flex}.hds-pagination-nav__page-list{display:flex;margin:0;padding:0}.hds-pagination-nav__page-item{list-style-type:none}.hds-pagination-nav__control{display:flex;align-items:center;height:var(--token-pagination-nav-control-height);padding:0 calc(var(--token-pagination-nav-control-padding-horizontal) - 1px);color:var(--token-color-foreground-primary);background-color:transparent;border:1px solid transparent;position:relative;outline-style:solid;outline-color:transparent;isolation:isolate}.hds-pagination-nav__control::before{position:absolute;top:var(--token-pagination-nav-control-focus-inset);right:var(--token-pagination-nav-control-focus-inset);bottom:var(--token-pagination-nav-control-focus-inset);left:var(--token-pagination-nav-control-focus-inset);z-index:-1;border-radius:5px;content:""}.hds-pagination-nav__control:focus:not(:focus-visible)::before{box-shadow:none}.hds-pagination-nav__control:focus-visible::before,.hds-side-nav__home-link.mock-focus.mock-focus::before,.hds-side-nav__home-link.mock-focus:focus::before,.hds-side-nav__home-link:focus.mock-focus::before,.hds-side-nav__home-link:focus:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-pagination-nav__control.mock-focus.mock-active::before,.hds-pagination-nav__control:focus:active::before{box-shadow:none}.hds-pagination-nav__control.mock-hover,.hds-pagination-nav__control:hover{color:var(--token-color-foreground-action-hover)}.hds-pagination-nav__control.mock-active,.hds-pagination-nav__control:active{color:var(--token-color-foreground-action-active)}.hds-pagination-nav__arrow{gap:var(--token-pagination-nav-control-icon-spacing)}.hds-pagination-nav__arrow.mock-disabled,.hds-pagination-nav__arrow:disabled{color:var(--token-color-foreground-disabled);cursor:not-allowed}.hds-pagination-nav__arrow--direction-prev{flex-direction:row;justify-content:flex-start}.hds-pagination-nav__arrow--direction-next{flex-direction:row-reverse;justify-content:flex-end}.hds-pagination-nav__number--is-selected{position:relative;color:var(--token-color-foreground-action)}.hds-pagination-nav__number--is-selected:hover{color:var(--token-color-foreground-action-hover)}.hds-pagination-nav__number--is-selected:active{color:var(--token-color-foreground-action-active)}.hds-pagination-nav__number--is-selected::after{position:absolute;right:calc(var(--token-pagination-nav-indicator-spacing) - 1px);bottom:-1px;left:calc(var(--token-pagination-nav-indicator-spacing) - 1px);height:var(--token-pagination-nav-indicator-height);margin:0 auto;background-color:currentColor;border-radius:2px;content:""}.hds-pagination-nav__ellipsis{display:flex;align-items:center;height:var(--token-pagination-nav-control-height);padding:0 var(--token-pagination-nav-control-padding-horizontal);color:var(--token-color-foreground-faint)}.hds-pagination-size-selector{display:flex;align-items:center}.hds-pagination-size-selector>label{white-space:nowrap}.hds-pagination-size-selector>select{height:28px;margin-left:12px;padding:0 24px 0 8px;font-size:var(--token-typography-body-100-font-size);font-family:var(--token-typography-body-100-font-family);line-height:var(--token-typography-body-100-line-height);background-position:center right 5px}.hds-reveal{width:-moz-fit-content;width:fit-content}.hds-reveal__toggle-button{min-height:1.75rem;padding:.313rem .313rem .313rem .188rem}@media (prefers-reduced-motion:no-preference){.hds-reveal__toggle-button .flight-icon-chevron-down{transition:transform .3s}}.hds-reveal__toggle-button--is-open .flight-icon-chevron-down{transform:rotate(-180deg)}.hds-reveal__content{margin-top:4px}.hds-segmented-group{display:inline-flex}.hds-side-nav--is-desktop .hds-side-nav__overlay,.hds-side-nav__toggle-button.mock-focus::after,.hds-side-nav__toggle-button.mock-focus::before,.hds-side-nav__toggle-button:focus-visible::after,.hds-side-nav__toggle-button:focus-visible::before{display:none}.hds-segmented-group>.hds-button:first-child,.hds-segmented-group>.hds-dropdown:first-child,.hds-segmented-group>.hds-form-select:first-child,.hds-segmented-group>.hds-form-text-input:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.hds-segmented-group>.hds-button:first-child .hds-dropdown-toggle-button,.hds-segmented-group>.hds-button:first-child .hds-dropdown-toggle-button::before,.hds-segmented-group>.hds-button:first-child::before,.hds-segmented-group>.hds-dropdown:first-child .hds-dropdown-toggle-button,.hds-segmented-group>.hds-dropdown:first-child .hds-dropdown-toggle-button::before,.hds-segmented-group>.hds-dropdown:first-child::before,.hds-segmented-group>.hds-form-select:first-child .hds-dropdown-toggle-button,.hds-segmented-group>.hds-form-select:first-child .hds-dropdown-toggle-button::before,.hds-segmented-group>.hds-form-select:first-child::before,.hds-segmented-group>.hds-form-text-input:first-child .hds-dropdown-toggle-button,.hds-segmented-group>.hds-form-text-input:first-child .hds-dropdown-toggle-button::before,.hds-segmented-group>.hds-form-text-input:first-child::before{border-top-right-radius:inherit;border-bottom-right-radius:inherit}.hds-segmented-group>.hds-button:last-child,.hds-segmented-group>.hds-dropdown:last-child,.hds-segmented-group>.hds-form-select:last-child,.hds-segmented-group>.hds-form-text-input:last-child{margin-left:-1px;border-top-left-radius:0;border-bottom-left-radius:0}.hds-segmented-group>.hds-button:last-child .hds-dropdown-toggle-button,.hds-segmented-group>.hds-button:last-child .hds-dropdown-toggle-button::before,.hds-segmented-group>.hds-button:last-child::before,.hds-segmented-group>.hds-dropdown:last-child .hds-dropdown-toggle-button,.hds-segmented-group>.hds-dropdown:last-child .hds-dropdown-toggle-button::before,.hds-segmented-group>.hds-dropdown:last-child::before,.hds-segmented-group>.hds-form-select:last-child .hds-dropdown-toggle-button,.hds-segmented-group>.hds-form-select:last-child .hds-dropdown-toggle-button::before,.hds-segmented-group>.hds-form-select:last-child::before,.hds-segmented-group>.hds-form-text-input:last-child .hds-dropdown-toggle-button,.hds-segmented-group>.hds-form-text-input:last-child .hds-dropdown-toggle-button::before,.hds-segmented-group>.hds-form-text-input:last-child::before{border-top-left-radius:inherit;border-bottom-left-radius:inherit}.hds-segmented-group>.hds-button:not(:first-child,:last-child),.hds-segmented-group>.hds-dropdown:not(:first-child,:last-child),.hds-segmented-group>.hds-form-select:not(:first-child,:last-child),.hds-segmented-group>.hds-form-text-input:not(:first-child,:last-child){margin-left:-1px;border-radius:0}.hds-segmented-group>.hds-button:not(:first-child,:last-child) .hds-dropdown-toggle-button,.hds-segmented-group>.hds-button:not(:first-child,:last-child) .hds-dropdown-toggle-button::before,.hds-segmented-group>.hds-button:not(:first-child,:last-child)::before,.hds-segmented-group>.hds-dropdown:not(:first-child,:last-child) .hds-dropdown-toggle-button,.hds-segmented-group>.hds-dropdown:not(:first-child,:last-child) .hds-dropdown-toggle-button::before,.hds-segmented-group>.hds-dropdown:not(:first-child,:last-child)::before,.hds-segmented-group>.hds-form-select:not(:first-child,:last-child) .hds-dropdown-toggle-button,.hds-segmented-group>.hds-form-select:not(:first-child,:last-child) .hds-dropdown-toggle-button::before,.hds-segmented-group>.hds-form-select:not(:first-child,:last-child)::before,.hds-segmented-group>.hds-form-text-input:not(:first-child,:last-child) .hds-dropdown-toggle-button,.hds-segmented-group>.hds-form-text-input:not(:first-child,:last-child) .hds-dropdown-toggle-button::before,.hds-segmented-group>.hds-form-text-input:not(:first-child,:last-child)::before{border-radius:inherit}.hds-segmented-group>.hds-button .hds-dropdown-toggle-button:focus,.hds-segmented-group>.hds-button.mock-focus,.hds-segmented-group>.hds-button:focus,.hds-segmented-group>.hds-dropdown .hds-dropdown-toggle-button:focus,.hds-segmented-group>.hds-dropdown.mock-focus,.hds-segmented-group>.hds-dropdown:focus,.hds-segmented-group>.hds-form-select .hds-dropdown-toggle-button:focus,.hds-segmented-group>.hds-form-select.mock-focus,.hds-segmented-group>.hds-form-select:focus,.hds-segmented-group>.hds-form-text-input .hds-dropdown-toggle-button:focus,.hds-segmented-group>.hds-form-text-input.mock-focus,.hds-segmented-group>.hds-form-text-input:focus{z-index:1}.hds-separator{border:none;border-top:1px solid var(--token-color-border-primary)}.hds-separator--spacing-24{margin:24px 0}.hds-separator--spacing-0{margin:0}.hds-side-nav{top:0;z-index:20;width:var(--hds-app-sidenav-width-fixed);height:100vh;min-height:100vh;isolation:isolate}.hds-side-nav.hds-side-nav--is-responsive{transition:width var(--hds-app-sidenav-animation-duration) var(--hds-app-sidenav-animation-easing)}.hds-side-nav.hds-side-nav--is-mobile{width:var(--hds-app-sidenav-width-minimized)}.hds-side-nav.hds-side-nav--is-desktop.hds-side-nav--is-not-minimized{width:var(--hds-app-sidenav-width-expanded)}.hds-side-nav--is-minimized .hds-side-nav__wrapper,.hds-side-nav.hds-side-nav--is-desktop.hds-side-nav--is-minimized{width:var(--hds-app-sidenav-width-minimized)}.hds-side-nav__overlay{position:fixed;z-index:-1;inset:0;background-color:var(--token-color-palette-neutral-700);opacity:.2;transition:opacity var(--hds-app-sidenav-animation-duration) var(--hds-app-sidenav-animation-easing) var(--hds-app-sidenav-animation-delay)}.hds-side-nav--is-minimized .hds-side-nav__overlay{opacity:0;pointer-events:none}.hds-side-nav__wrapper{display:flex;flex-direction:column;height:100%;color:var(--token-side-nav-color-foreground-primary);background:var(--token-side-nav-color-surface-primary);border-right:var(--token-side-nav-wrapper-border-width) solid var(--token-side-nav-wrapper-border-color)}.hds-side-nav--is-responsive .hds-side-nav__wrapper{transition:width var(--hds-app-sidenav-animation-duration) var(--hds-app-sidenav-animation-easing)}.hds-side-nav--is-not-minimized .hds-side-nav__wrapper{width:var(--hds-app-sidenav-width-expanded)}.hds-side-nav__wrapper-header{padding-top:var(--token-side-nav-wrapper-padding-vertical);padding-right:var(--token-side-nav-wrapper-padding-horizontal);padding-bottom:8px;padding-left:var(--token-side-nav-wrapper-padding-horizontal);transition:padding var(--hds-app-sidenav-animation-duration) var(--hds-app-sidenav-animation-easing)}.hds-side-nav--is-minimized .hds-side-nav__wrapper-header{padding-top:var(--token-side-nav-wrapper-padding-vertical-minimized);padding-right:var(--token-side-nav-wrapper-padding-horizontal-minimized);padding-left:var(--token-side-nav-wrapper-padding-horizontal-minimized)}.hds-side-nav__wrapper-body,.hds-side-nav__wrapper-footer{padding:var(--token-side-nav-wrapper-padding-vertical) var(--token-side-nav-wrapper-padding-horizontal)}.hds-side-nav__wrapper-body{flex:1;overflow-x:hidden;overflow-y:auto}.hds-side-nav--is-minimized .hds-side-nav-hide-when-minimized{visibility:hidden!important;opacity:0;pointer-events:none}.hds-side-nav--is-not-minimized .hds-side-nav-hide-when-minimized{visibility:visible;opacity:1;transition:opacity var(--hds-app-sidenav-animation-duration) var(--hds-app-sidenav-animation-easing) var(--hds-app-sidenav-animation-delay)}.hds-side-nav--is-animating .hds-side-nav-hide-when-minimized{pointer-events:none}.hds-side-nav-header{display:flex;align-items:center;justify-content:space-between}.hds-side-nav-header__logo-container{display:flex;flex:none;align-items:center;justify-content:center;width:var(--token-side-nav-header-home-link-logo-size);height:var(--token-side-nav-header-home-link-logo-size);transition:width var(--hds-app-sidenav-animation-duration) var(--hds-app-sidenav-animation-easing),height var(--hds-app-sidenav-animation-duration) var(--hds-app-sidenav-animation-easing)}.hds-side-nav--is-minimized .hds-side-nav-header__logo-container{width:var(--token-side-nav-header-home-link-logo-size-minimized);height:var(--token-side-nav-header-home-link-logo-size-minimized)}.hds-side-nav__home-link{color:var(--token-side-nav-color-foreground-strong);background-color:transparent;border:1px solid transparent;border-radius:var(--token-side-nav-body-list-item-border-radius);cursor:pointer;display:block;width:100%;height:100%;padding:calc(var(--token-side-nav-header-home-link-padding) - 1px)}.hds-side-nav__home-link.mock-focus,.hds-side-nav__home-link:focus{position:relative;outline-style:solid;outline-color:transparent;isolation:isolate}.hds-side-nav__home-link.mock-focus::before,.hds-side-nav__home-link:focus::before{position:absolute;top:-1px;right:-1px;bottom:-1px;left:-1px;z-index:-1;border-radius:5px;content:""}.hds-side-nav__home-link.mock-focus:focus:not(:focus-visible)::before,.hds-side-nav__home-link:focus:focus:not(:focus-visible)::before{box-shadow:none}.hds-side-nav__home-link.mock-focus:focus-visible::before,.hds-side-nav__home-link:focus:focus-visible::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-side-nav__home-link.mock-focus.mock-focus.mock-active::before,.hds-side-nav__home-link.mock-focus:focus:active::before,.hds-side-nav__home-link:focus.mock-focus.mock-active::before,.hds-side-nav__home-link:focus:focus:active::before{box-shadow:none}.hds-side-nav__home-link.mock-hover,.hds-side-nav__home-link:hover{color:var(--token-side-nav-color-foreground-strong);background:var(--token-side-nav-color-surface-interactive-hover)}.hds-side-nav__home-link.mock-active,.hds-side-nav__home-link:active{color:var(--token-side-nav-color-foreground-strong);background:var(--token-side-nav-color-surface-interactive-active)}.hds-side-nav-header__actions-container{display:flex;gap:var(--token-side-nav-header-actions-spacing)}.hds-side-nav__dropdown .hds-dropdown-toggle-button,.hds-side-nav__dropdown .hds-dropdown-toggle-icon{color:var(--token-side-nav-color-foreground-strong);background-color:transparent;border:1px solid transparent;border-radius:var(--token-side-nav-body-list-item-border-radius);cursor:pointer;border-color:var(--token-color-palette-neutral-500)}.hds-side-nav__dropdown .hds-dropdown-toggle-button.mock-focus,.hds-side-nav__dropdown .hds-dropdown-toggle-button:focus,.hds-side-nav__dropdown .hds-dropdown-toggle-icon.mock-focus,.hds-side-nav__dropdown .hds-dropdown-toggle-icon:focus{position:relative;outline-style:solid;outline-color:transparent;isolation:isolate}.hds-side-nav__dropdown .hds-dropdown-toggle-button.mock-focus::before,.hds-side-nav__dropdown .hds-dropdown-toggle-button:focus::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon.mock-focus::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon:focus::before{position:absolute;top:-1px;right:-1px;bottom:-1px;left:-1px;z-index:-1;border-radius:5px;content:""}.hds-side-nav__dropdown .hds-dropdown-toggle-button.mock-focus.mock-focus::before,.hds-side-nav__dropdown .hds-dropdown-toggle-button.mock-focus:focus::before,.hds-side-nav__dropdown .hds-dropdown-toggle-button:focus.mock-focus::before,.hds-side-nav__dropdown .hds-dropdown-toggle-button:focus:focus::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon.mock-focus.mock-focus::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon.mock-focus:focus::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon:focus.mock-focus::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon:focus:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-side-nav__dropdown .hds-dropdown-toggle-button.mock-focus:focus:not(:focus-visible)::before,.hds-side-nav__dropdown .hds-dropdown-toggle-button:focus:focus:not(:focus-visible)::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon.mock-focus:focus:not(:focus-visible)::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon:focus:focus:not(:focus-visible)::before{box-shadow:none}.hds-side-nav__dropdown .hds-dropdown-toggle-button.mock-focus:focus-visible::before,.hds-side-nav__dropdown .hds-dropdown-toggle-button:focus:focus-visible::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon.mock-focus:focus-visible::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon:focus:focus-visible::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-side-nav__dropdown .hds-dropdown-toggle-button.mock-focus.mock-focus.mock-active::before,.hds-side-nav__dropdown .hds-dropdown-toggle-button.mock-focus:focus:active::before,.hds-side-nav__dropdown .hds-dropdown-toggle-button:focus.mock-focus.mock-active::before,.hds-side-nav__dropdown .hds-dropdown-toggle-button:focus:focus:active::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon.mock-focus.mock-focus.mock-active::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon.mock-focus:focus:active::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon:focus.mock-focus.mock-active::before,.hds-side-nav__dropdown .hds-dropdown-toggle-icon:focus:focus:active::before{box-shadow:none}.hds-side-nav__dropdown .hds-dropdown-toggle-button.mock-hover,.hds-side-nav__dropdown .hds-dropdown-toggle-button:hover,.hds-side-nav__dropdown .hds-dropdown-toggle-icon.mock-hover,.hds-side-nav__dropdown .hds-dropdown-toggle-icon:hover{color:var(--token-side-nav-color-foreground-strong);background:var(--token-side-nav-color-surface-interactive-hover)}.hds-side-nav__dropdown .hds-dropdown-toggle-button.mock-active,.hds-side-nav__dropdown .hds-dropdown-toggle-button:active,.hds-side-nav__dropdown .hds-dropdown-toggle-icon.mock-active,.hds-side-nav__dropdown .hds-dropdown-toggle-icon:active{color:var(--token-side-nav-color-foreground-strong);background:var(--token-side-nav-color-surface-interactive-active);border-color:var(--token-color-palette-neutral-400)}.hds-side-nav__icon-button{color:var(--token-side-nav-color-foreground-strong);background-color:transparent;border:1px solid transparent;border-radius:var(--token-side-nav-body-list-item-border-radius);cursor:pointer;border-color:var(--token-color-palette-neutral-500);display:flex;align-items:center;justify-content:center;width:36px;height:36px;padding:5px}.hds-side-nav__icon-button.mock-focus,.hds-side-nav__icon-button:focus{position:relative;outline-style:solid;outline-color:transparent;isolation:isolate}.hds-side-nav__icon-button.mock-focus::before,.hds-side-nav__icon-button:focus::before{position:absolute;top:-1px;right:-1px;bottom:-1px;left:-1px;z-index:-1;border-radius:5px;content:""}.hds-side-nav__icon-button.mock-focus.mock-focus::before,.hds-side-nav__icon-button.mock-focus:focus::before,.hds-side-nav__icon-button:focus.mock-focus::before,.hds-side-nav__icon-button:focus:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-side-nav__icon-button.mock-focus:focus:not(:focus-visible)::before,.hds-side-nav__icon-button:focus:focus:not(:focus-visible)::before{box-shadow:none}.hds-side-nav__icon-button.mock-focus:focus-visible::before,.hds-side-nav__icon-button:focus:focus-visible::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-side-nav__icon-button.mock-focus.mock-focus.mock-active::before,.hds-side-nav__icon-button.mock-focus:focus:active::before,.hds-side-nav__icon-button:focus.mock-focus.mock-active::before,.hds-side-nav__icon-button:focus:focus:active::before{box-shadow:none}.hds-side-nav__icon-button.mock-hover,.hds-side-nav__icon-button:hover{color:var(--token-side-nav-color-foreground-strong);background:var(--token-side-nav-color-surface-interactive-hover)}.hds-side-nav__icon-button.mock-active,.hds-side-nav__icon-button:active{color:var(--token-side-nav-color-foreground-strong);background:var(--token-side-nav-color-surface-interactive-active);border-color:var(--token-color-palette-neutral-400)}.hds-side-nav__content{margin:0 calc(var(--token-side-nav-wrapper-padding-horizontal) * -1)}.hds-side-nav__content-panels{display:grid;grid-template-columns:repeat(5,var(--hds-app-sidenav-width-expanded));width:100%}.hds-side-nav__content-panel{padding:0 var(--token-side-nav-wrapper-padding-horizontal)}.hds-side-nav__list-title{display:flex;align-items:center;min-height:var(--token-side-nav-body-list-item-height);margin-top:var(--token-side-nav-body-list-margin-vertical);padding:9px var(--token-side-nav-body-list-item-padding-horizontal);color:var(--token-side-nav-color-foreground-faint)}.hds-side-nav__list-wrapper:first-child .hds-side-nav__list-item:first-child>.hds-side-nav__list-title{margin-top:0}.hds-side-nav__list,.hds-side-nav__list-wrapper{margin:0;padding:0}.hds-side-nav__list-item{list-style-type:none}.hds-side-nav__list-item+.hds-side-nav__list-item{margin-top:var(--token-side-nav-body-list-item-spacing-vertical)}.hds-side-nav__list-item-link{display:flex;gap:var(--token-side-nav-body-list-item-content-spacing-horizontal);align-items:center;width:100%;min-height:var(--token-side-nav-body-list-item-height);padding:var(--token-side-nav-body-list-item-padding-vertical) var(--token-side-nav-body-list-item-padding-horizontal);color:var(--token-side-nav-color-foreground-primary);background:var(--token-side-nav-color-surface-primary);border-color:transparent;border-radius:var(--token-side-nav-body-list-item-border-radius)}.hds-side-nav__list-item-link.active .hds-side-nav__list-item-icon-leading,.hds-side-nav__list-item-link.active .hds-side-nav__list-item-icon-trailing,.hds-side-nav__list-item-link.active .hds-side-nav__list-item-text,.hds-side-nav__list-item-link.mock-active .hds-side-nav__list-item-icon-leading,.hds-side-nav__list-item-link.mock-active .hds-side-nav__list-item-icon-trailing,.hds-side-nav__list-item-link.mock-active .hds-side-nav__list-item-text,.hds-side-nav__list-item-link.mock-hover .hds-side-nav__list-item-icon-leading,.hds-side-nav__list-item-link.mock-hover .hds-side-nav__list-item-icon-trailing,.hds-side-nav__list-item-link.mock-hover .hds-side-nav__list-item-text,.hds-side-nav__list-item-link:active .hds-side-nav__list-item-icon-leading,.hds-side-nav__list-item-link:active .hds-side-nav__list-item-icon-trailing,.hds-side-nav__list-item-link:active .hds-side-nav__list-item-text,.hds-side-nav__list-item-link:hover .hds-side-nav__list-item-icon-leading,.hds-side-nav__list-item-link:hover .hds-side-nav__list-item-icon-trailing,.hds-side-nav__list-item-link:hover .hds-side-nav__list-item-text,.hds-side-nav__list-item-link:hover:focus .hds-side-nav__list-item-icon-leading,.hds-side-nav__list-item-link:hover:focus .hds-side-nav__list-item-icon-trailing,.hds-side-nav__list-item-link:hover:focus .hds-side-nav__list-item-text{color:var(--token-side-nav-color-foreground-strong)}.hds-side-nav__list-item-link.mock-focus,.hds-side-nav__list-item-link:focus{position:relative;outline-style:solid;outline-color:transparent;isolation:isolate}.hds-side-nav__list-item-link.mock-focus::before,.hds-side-nav__list-item-link:focus::before{position:absolute;top:0;right:0;bottom:0;left:0;z-index:-1;border-radius:5px;content:""}.hds-side-nav__list-item-link.mock-focus.mock-focus::before,.hds-side-nav__list-item-link.mock-focus:focus::before,.hds-side-nav__list-item-link:focus.mock-focus::before,.hds-side-nav__list-item-link:focus:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-side-nav__list-item-link.mock-focus:focus:not(:focus-visible)::before,.hds-side-nav__list-item-link:focus:focus:not(:focus-visible)::before{box-shadow:none}.hds-side-nav__list-item-link.mock-focus:focus-visible::before,.hds-side-nav__list-item-link:focus:focus-visible::before,.hds-table__th-sort button.mock-focus::before,.hds-table__th-sort button:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-side-nav__list-item-link.mock-focus.mock-focus.mock-active::before,.hds-side-nav__list-item-link.mock-focus:focus:active::before,.hds-side-nav__list-item-link:focus.mock-focus.mock-active::before,.hds-side-nav__list-item-link:focus:focus:active::before{box-shadow:none}.hds-side-nav__list-item-link.mock-hover,.hds-side-nav__list-item-link:hover{background:var(--token-side-nav-color-surface-interactive-hover);border-color:transparent}.hds-side-nav__list-item-link.active,.hds-side-nav__list-item-link.mock-active,.hds-side-nav__list-item-link:active,.hds-side-nav__list-item-link:hover:focus{background:var(--token-side-nav-color-surface-interactive-active)}.hds-side-nav__list-item-link.active .hds-badge,.hds-side-nav__list-item-link.active .hds-badge-count,.hds-side-nav__list-item-link.mock-active .hds-badge,.hds-side-nav__list-item-link.mock-active .hds-badge-count,.hds-side-nav__list-item-link:active .hds-badge,.hds-side-nav__list-item-link:active .hds-badge-count,.hds-side-nav__list-item-link:hover:focus .hds-badge,.hds-side-nav__list-item-link:hover:focus .hds-badge-count{color:var(--token-color-foreground-primary);background:var(--token-color-surface-strong)}.hds-side-nav__list-item-link--back-link.mock-active .hds-side-nav__list-item-icon-leading,.hds-side-nav__list-item-link--back-link.mock-active .hds-side-nav__list-item-icon-trailing,.hds-side-nav__list-item-link--back-link.mock-active .hds-side-nav__list-item-text,.hds-side-nav__list-item-link--back-link:active .hds-side-nav__list-item-icon-leading,.hds-side-nav__list-item-link--back-link:active .hds-side-nav__list-item-icon-trailing,.hds-side-nav__list-item-link--back-link:active .hds-side-nav__list-item-text,.hds-side-nav__list-item-text{color:var(--token-side-nav-color-foreground-primary)}.hds-side-nav__list-item-link--back-link.mock-active,.hds-side-nav__list-item-link--back-link:active{background:var(--token-side-nav-color-surface-primary)}.hds-side-nav__list-item-text{text-align:left}.hds-side-nav__list-item-icon-leading{flex:none}.hds-side-nav__list-item-icon-trailing{flex:none;margin-left:auto}.hds-side-nav__toggle-button{position:absolute;top:22px;left:calc(var(--token-side-nav-wrapper-border-width) * -1);z-index:1;display:flex;flex-direction:row-reverse;align-items:center;width:26px;height:36px;padding:0 4px;color:var(--token-color-foreground-high-contrast);background:0 0;background-color:var(--token-side-nav-color-surface-primary);border:var(--token-side-nav-wrapper-border-width) solid var(--token-side-nav-wrapper-border-color);border-left-color:transparent;border-top-right-radius:var(--token-side-nav-toggle-button-border-radius);border-bottom-right-radius:var(--token-side-nav-toggle-button-border-radius);transform:translateX(var(--hds-app-sidenav-width-expanded));cursor:pointer;transition:transform var(--hds-app-sidenav-animation-duration) var(--hds-app-sidenav-animation-easing),width var(--hds-app-sidenav-animation-duration) var(--hds-app-sidenav-animation-easing)}.hds-side-nav__toggle-button::after,.hds-side-nav__toggle-button::before{position:absolute;left:calc(var(--token-side-nav-wrapper-border-width) * -1);width:calc(var(--token-side-nav-toggle-button-border-radius) * 2);height:calc(var(--token-side-nav-toggle-button-border-radius) * 2);border-left:var(--token-side-nav-wrapper-border-width) solid var(--token-side-nav-wrapper-border-color);box-sizing:border-box;content:""}.hds-side-nav__toggle-button::before{top:calc(var(--token-side-nav-toggle-button-border-radius) * -2);border-bottom:var(--token-side-nav-wrapper-border-width) solid var(--token-side-nav-wrapper-border-color);border-bottom-left-radius:var(--token-side-nav-toggle-button-border-radius);box-shadow:0 var(--token-side-nav-toggle-button-border-radius) 0 var(--token-side-nav-color-surface-primary)}.hds-side-nav__toggle-button::after{bottom:calc(var(--token-side-nav-toggle-button-border-radius) * -2);border-top:var(--token-side-nav-wrapper-border-width) solid var(--token-side-nav-wrapper-border-color);border-top-left-radius:var(--token-side-nav-toggle-button-border-radius);box-shadow:0 calc(var(--token-side-nav-toggle-button-border-radius) * -1) 0 var(--token-side-nav-color-surface-primary)}.hds-side-nav__toggle-button.mock-hover,.hds-side-nav__toggle-button:hover{width:30px;background-color:var(--token-side-nav-color-surface-interactive-hover)}.hds-side-nav__toggle-button.mock-hover::before,.hds-side-nav__toggle-button:hover::before{box-shadow:0 var(--token-side-nav-toggle-button-border-radius) 0 var(--token-side-nav-color-surface-interactive-hover)}.hds-side-nav__toggle-button.mock-hover::after,.hds-side-nav__toggle-button:hover::after{box-shadow:0 calc(var(--token-side-nav-toggle-button-border-radius) * -1) 0 var(--token-side-nav-color-surface-interactive-hover)}.hds-side-nav__toggle-button.mock-active,.hds-side-nav__toggle-button:active{background-color:var(--token-side-nav-color-surface-interactive-active)}.hds-side-nav__toggle-button.mock-active::before,.hds-side-nav__toggle-button:active::before{box-shadow:0 var(--token-side-nav-toggle-button-border-radius) 0 var(--token-side-nav-color-surface-interactive-active)}.hds-side-nav__toggle-button.mock-active::after,.hds-side-nav__toggle-button:active::after{box-shadow:0 calc(var(--token-side-nav-toggle-button-border-radius) * -1) 0 var(--token-side-nav-color-surface-interactive-active)}.hds-side-nav__toggle-button.mock-focus,.hds-side-nav__toggle-button:focus-visible{border-color:var(--token-color-focus-action-internal);outline:var(--token-color-focus-action-external) solid 3px}.hds-table__th-sort button,.hds-tabs__tab-button,.hds-tooltip-button{outline-color:transparent;outline-style:solid}.hds-side-nav--is-minimized .hds-side-nav__toggle-button{transform:translateX(var(--hds-app-sidenav-width-minimized))}.hds-side-nav .ember-a11y-refocus-skip-link{top:10px;left:10px;z-index:20;width:-moz-max-content;width:max-content;padding:2px 10px 4px;color:var(--token-color-foreground-action);font-family:var(--token-typography-display-200-font-family);background-color:var(--token-color-surface-faint);border-radius:3px;transform:translateY(-200%);transition:.6s ease-in-out}.hds-side-nav .ember-a11y-refocus-skip-link:focus{transform:translateY(0)}.hds-stepper-indicator-step{position:relative;width:24px;height:24px}.hds-stepper-indicator-step__svg-hexagon{width:100%;height:100%;filter:drop-shadow(0 1px 1px rgba(101, 106, 118, .05))}.hds-stepper-indicator-step__status{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center}.hds-stepper-indicator-step__icon{width:12px;height:12px}.hds-stepper-indicator-step__text{width:20px;overflow:hidden;white-space:nowrap;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none}.hds-stepper-indicator-step--status-incomplete .hds-stepper-indicator-step__status{color:var(--token-color-foreground-strong)}.hds-stepper-indicator-step--status-complete .hds-stepper-indicator-step__status,.hds-stepper-indicator-step--status-processing .hds-stepper-indicator-step__status,.hds-stepper-indicator-step--status-progress .hds-stepper-indicator-step__status{color:var(--token-color-foreground-high-contrast)}.hds-stepper-indicator-step--status-incomplete .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-surface-faint);stroke:var(--token-color-foreground-strong)}.hds-stepper-indicator-step--status-complete .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--status-processing .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--status-progress .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-foreground-strong);stroke:var(--token-color-foreground-strong)}.hds-stepper-indicator-step--is-interactive{cursor:pointer}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-incomplete .hds-stepper-indicator-step__status{color:var(--token-color-foreground-primary)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-processing .hds-stepper-indicator-step__status,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-progress .hds-stepper-indicator-step__status{color:var(--token-color-foreground-high-contrast)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-incomplete .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-surface-interactive);stroke:var(--token-color-border-strong)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-incomplete.mock-hover .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-incomplete:hover .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-surface-interactive-hover)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-incomplete.mock-active .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-incomplete:active .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-surface-interactive-active)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-progress .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-200);stroke:var(--token-color-palette-blue-300)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-progress.mock-hover .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-progress:hover .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-300);stroke:var(--token-color-palette-blue-400)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-progress.mock-active .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-progress:active .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-400);stroke:var(--token-color-palette-blue-400)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-processing .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-200);stroke:var(--token-color-palette-blue-300)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-processing.mock-hover .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-processing:hover .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-300);stroke:var(--token-color-palette-blue-400)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-processing.mock-active .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-processing:active .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-400);stroke:var(--token-color-palette-blue-400)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete .hds-stepper-indicator-step__status{color:var(--token-color-palette-blue-200)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-50);stroke:var(--token-color-palette-blue-300)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete.mock-active .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete.mock-hover .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete:active .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete:hover .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-100);stroke:var(--token-color-palette-blue-400)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete.mock-hover .hds-stepper-indicator-step__status,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete:hover .hds-stepper-indicator-step__status{color:var(--token-color-palette-blue-300)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete.mock-active .hds-stepper-indicator-step__status,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete:active .hds-stepper-indicator-step__status{color:var(--token-color-palette-blue-400)}.hds-stepper-indicator-task{position:relative;display:flex;align-items:center;justify-content:center;width:16px;height:16px;color:var(--token-color-foreground-strong)}.hds-stepper-indicator-task__icon{width:12px;height:12px}.hds-stepper-indicator-task--is-interactive{cursor:pointer}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-incomplete{color:var(--token-color-palette-neutral-300)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-incomplete.mock-hover,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-incomplete:hover{color:var(--token-color-palette-blue-300)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-incomplete.mock-active,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-incomplete:active{color:var(--token-color-palette-blue-400)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-progress{color:var(--token-color-palette-blue-200)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-progress.mock-hover,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-progress:hover{color:var(--token-color-palette-blue-300)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-progress.mock-active,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-progress:active{color:var(--token-color-palette-blue-400)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-processing{color:var(--token-color-palette-blue-200)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-processing.mock-hover,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-processing:hover{color:var(--token-color-palette-blue-300)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-processing.mock-active,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-processing:active{color:var(--token-color-palette-blue-400)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-complete{color:var(--token-color-palette-green-200)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-complete.mock-hover,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-complete:hover{color:var(--token-color-palette-green-300)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-complete.mock-active,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-complete:active{color:var(--token-color-palette-green-400)}.hds-table{width:100%;border:1px solid var(--token-color-border-primary);border-radius:6px}.hds-table--layout-fixed{table-layout:fixed}.hds-table__thead .hds-table__tr{color:var(--token-color-foreground-strong);background-color:var(--token-color-surface-strong)}.hds-table__thead .hds-table__tr:first-of-type th:first-child{border-top-left-radius:5px}.hds-table__thead .hds-table__tr:first-of-type th:last-child{border-top-right-radius:5px}.hds-table__thead .hds-table__th,.hds-table__thead .hds-table__th-sort{min-height:48px}.hds-table__th,.hds-table__th-sort{text-align:left;border-top:none;border-right:none;border-bottom:1px solid var(--token-color-border-primary);border-left:none}.hds-table__th{padding:14px 16px 13px}.hds-table__th-sort{padding:0}.hds-table__th-sort button{width:100%;height:100%;min-height:48px;margin:0;padding:14px 16px 13px;text-align:inherit;background-color:transparent;border:1px solid transparent;border-radius:inherit;position:relative;isolation:isolate}.hds-table__th-sort button .hds-table__th-sort--button-content{display:flex;align-items:center}.hds-table__th-sort button .hds-table__th-sort--button-content .flight-icon{flex:none;margin-left:8px;color:var(--token-color-foreground-action)}.hds-table__th-sort button.mock-hover,.hds-table__th-sort button:hover{color:var(--token-color-foreground-strong);background-color:var(--token-color-palette-neutral-200);cursor:pointer}.hds-table__th-sort button::before{position:absolute;top:0;right:0;bottom:0;left:0;z-index:-1;border-radius:inherit;content:""}.hds-table__th-sort button:focus:not(:focus-visible)::before{box-shadow:none}.hds-table__th-sort button:focus-visible::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-table__th-sort button.mock-focus.mock-active::before,.hds-table__th-sort button:focus:active::before{box-shadow:none}.hds-table__th-sort button.mock-active,.hds-table__th-sort button:active{color:var(--token-color-foreground-strong);background-color:var(--token-color-palette-neutral-300)}.hds-table__tbody .hds-table__tr,.hds-tabs__tab,.hds-tag__dismiss-icon{color:var(--token-color-foreground-primary)}.hds-table--striped .hds-table__tbody .hds-table__tr:nth-child(even){background-color:var(--token-color-surface-faint)}.hds-table--density-short .hds-table__tbody td,.hds-table--density-short .hds-table__tbody th{padding:6px 16px 5px}.hds-table--density-medium .hds-table__tbody td,.hds-table--density-medium .hds-table__tbody th{padding:14px 16px 13px}.hds-table--density-tall .hds-table__tbody td,.hds-table--density-tall .hds-table__tbody th{padding:22px 16px 21px}.hds-table--valign-top .hds-table__tbody td,.hds-table--valign-top .hds-table__tbody th{vertical-align:top}.hds-table--valign-middle .hds-table__tbody td,.hds-table--valign-middle .hds-table__tbody th,.hds-tag{vertical-align:middle}.hds-table__td--text-right,.hds-table__th--text-right,.hds-table__th-sort--text-right{text-align:right}.hds-table__th-sort--text-right .hds-table__th-sort--button-content{justify-content:flex-end}.hds-table__td--text-center,.hds-table__th--text-center,.hds-table__th-sort--text-center{text-align:center}.hds-table__tbody .hds-table__tr{background-color:var(--token-color-surface-primary)}.hds-table__tbody .hds-table__tr td,.hds-table__tbody .hds-table__tr th{border-top:none;border-right:none;border-bottom:1px solid var(--token-color-border-primary);border-left:none}.hds-table__tbody .hds-table__tr:last-of-type td,.hds-table__tbody .hds-table__tr:last-of-type th{border-bottom:none}.hds-table__tbody .hds-table__tr:last-of-type td:first-child,.hds-table__tbody .hds-table__tr:last-of-type th:first-child{border-bottom-left-radius:5px}.hds-table__tbody .hds-table__tr:last-of-type td:last-child{border-bottom-right-radius:5px}.hds-tabs__tablist-wrapper{position:relative}.hds-tabs__tablist-wrapper::before{position:absolute;right:0;bottom:calc((var(--token-tabs-indicator-height) - var(--token-tabs-divider-height))/ 2);left:0;display:block;border-top:var(--token-tabs-divider-height) solid var(--token-color-border-primary);content:""}.hds-tabs__tablist{position:relative;display:flex;margin:0;padding:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.hds-tabs__tab{position:relative;display:flex;align-items:center;height:var(--token-tabs-tab-height);margin:0;padding:var(--token-tabs-tab-padding-vertical) var(--token-tabs-tab-padding-horizontal);white-space:nowrap;list-style:none}.hds-tabs__tab.hds-tabs__tab--is-selected,.hds-tabs__tab.mock-hover,.hds-tabs__tab:hover{color:var(--token-color-foreground-action)}.hds-tabs__tab.hds-tabs__tab--is-selected:hover{color:var(--token-color-foreground-action-hover)}.hds-tabs__tab.hds-tabs__tab--is-selected:hover~.hds-tabs__tab-indicator{background:var(--token-color-foreground-action-hover)}.hds-tabs__tab-button{isolation:isolate;position:static;display:flex;gap:var(--token-tabs-tab-gutter);align-items:center;padding:0;color:inherit;background-color:transparent;border:none;border-radius:var(--token-tabs-tab-border-radius);cursor:pointer}.hds-tabs__tab-button::before{position:absolute;top:var(--token-tabs-tab-focus-inset);right:var(--token-tabs-tab-focus-inset);bottom:var(--token-tabs-tab-focus-inset);left:var(--token-tabs-tab-focus-inset);z-index:-1;border-radius:5px;content:""}.hds-tabs__tab-button.mock-focus::before,.hds-tabs__tab-button:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-tabs__tab-button:focus:not(:focus-visible)::before{box-shadow:none}.hds-tabs__tab-button:focus-visible::before,.hds-tag__dismiss.mock-focus.mock-focus,.hds-tag__dismiss.mock-focus:focus,.hds-tag__dismiss:focus.mock-focus,.hds-tag__dismiss:focus:focus,.hds-tag__link.mock-focus.mock-focus,.hds-tag__link.mock-focus:focus,.hds-tag__link:focus.mock-focus,.hds-tag__link:focus:focus{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-tabs__tab-button.mock-focus.mock-active::before,.hds-tabs__tab-button:focus:active::before{box-shadow:none}.hds-tabs__tab-button::after{position:absolute;content:"";inset:0}.hds-tabs__tab-indicator{position:absolute;right:0;bottom:0;left:var(--indicator-left-pos);z-index:10;display:block;width:var(--indicator-width);height:var(--token-tabs-indicator-height);background-color:var(--token-color-foreground-action);border-radius:var(--token-tabs-indicator-height)}.hds-tabs__panel[hidden],.readonly-codemirror .CodeMirror-cursors{display:none}.hds-tag,.hds-tag__dismiss,.hds-tag__link{background-color:var(--token-color-surface-interactive)}@media screen and (prefers-reduced-motion:no-preference){.hds-tabs__tab-indicator{transition-timing-function:var(--token-tabs-indicator-transition-function);transition-duration:var(--token-tabs-indicator-transition-duration);transition-property:left,width}}.tippy-box,.tippy-box[data-theme~=hds]{transition-property:transform,visibility,opacity}.hds-tag,:where(.hds-tooltip-button--is-inline){display:inline-flex}.hds-tag{align-items:stretch;line-height:1rem;border:1px solid var(--token-color-border-strong);border-radius:50px}.hds-tag__dismiss{flex:0 0 auto;margin:0;padding:6px 4px 6px 8px;border:none;border-radius:inherit;border-top-right-radius:0;border-bottom-right-radius:0}.hds-tag__dismiss-icon{width:12px;height:12px}.hds-tag__link,.hds-tag__text{flex:1 0 0;padding:3px 10px 5px;border-radius:inherit}.hds-tag__dismiss~.hds-tag__link,.hds-tag__dismiss~.hds-tag__text{padding:3px 8px 5px 6px;border-top-left-radius:0;border-bottom-left-radius:0}.hds-tag__dismiss,.hds-tag__link{cursor:pointer}.hds-tag__dismiss.mock-hover,.hds-tag__dismiss:hover,.hds-tag__link.mock-hover,.hds-tag__link:hover{background-color:var(--token-color-surface-interactive-hover)}.hds-tag__dismiss.mock-active,.hds-tag__dismiss:active,.hds-tag__link.mock-active,.hds-tag__link:active{background-color:var(--token-color-surface-interactive-active)}.hds-tag__dismiss.mock-focus,.hds-tag__dismiss:focus,.hds-tag__link.mock-focus,.hds-tag__link:focus{outline-style:solid;outline-color:transparent;z-index:1}.hds-tag__dismiss.mock-focus:focus:not(:focus-visible),.hds-tag__dismiss:focus:focus:not(:focus-visible),.hds-tag__link.mock-focus:focus:not(:focus-visible),.hds-tag__link:focus:focus:not(:focus-visible){box-shadow:none}.hds-tag__dismiss.mock-focus:focus-visible,.hds-tag__dismiss:focus:focus-visible,.hds-tag__link.mock-focus:focus-visible,.hds-tag__link:focus:focus-visible{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-tag__dismiss.mock-focus.mock-focus.mock-active,.hds-tag__dismiss.mock-focus:focus:active,.hds-tag__dismiss:focus.mock-focus.mock-active,.hds-tag__dismiss:focus:focus:active,.hds-tag__link.mock-focus.mock-focus.mock-active,.hds-tag__link.mock-focus:focus:active,.hds-tag__link:focus.mock-focus.mock-active,.hds-tag__link:focus:focus:active{box-shadow:none}.hds-tag--color-primary .hds-tag__link{color:var(--token-color-foreground-action)}.hds-tag--color-primary .hds-tag__link.mock-hover,.hds-tag--color-primary .hds-tag__link:hover{color:var(--token-color-foreground-action-hover)}.hds-tag--color-primary .hds-tag__link.mock-active,.hds-tag--color-primary .hds-tag__link:active{color:var(--token-color-foreground-action-active)}.hds-tag--color-secondary .hds-tag__link{color:var(--token-color-foreground-strong)}.hds-text--align-left{text-align:left}.hds-text--align-center{text-align:center}.hds-text--align-right{text-align:right}.hds-toast{width:-moz-fit-content;width:fit-content;min-width:min(360px,80vw);max-width:min(500px,80vw);box-shadow:var(--token-elevation-higher-box-shadow)}.hds-tooltip-button{position:relative;isolation:isolate}.hds-tooltip-button::before{position:absolute;top:var(--token-tooltip-focus-offset);right:var(--token-tooltip-focus-offset);bottom:var(--token-tooltip-focus-offset);left:var(--token-tooltip-focus-offset);z-index:-1;border-radius:5px;content:""}.hds-tooltip-button.mock-focus::before,.hds-tooltip-button:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-tooltip-button:focus:not(:focus-visible)::before{box-shadow:none}.hds-tooltip-button:focus-visible::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-tooltip-button.mock-focus.mock-active::before,.hds-tooltip-button:focus:active::before{box-shadow:none}:where(.hds-tooltip-button){margin:0;padding:0;color:inherit;font:inherit;text-align:inherit;background-color:inherit;border:none}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li,.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.menu-panel>ul>[role=treeitem],.menu-panel>ul>li,.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.modal-dialog [role=document] table caption,.modal-dialog [role=document] table thead th,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li,.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],main table caption,main table thead th,table td,table th,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],td,th{text-align:left}:where(.hds-tooltip-button--is-block){display:flex}article,aside,figure,footer,header,hgroup,hr,section{display:block}.tippy-box[data-theme~=hds]{padding:var(--token-tooltip-padding-vertical) var(--token-tooltip-padding-horizontal);color:var(--token-tooltip-color-foreground-primary);font-weight:var(--token-typography-font-weight-regular);font-size:var(--token-typography-body-200-font-size);font-family:var(--token-typography-body-200-font-family);line-height:var(--token-typography-body-200-line-height);overflow-wrap:break-word;background-color:var(--token-tooltip-color-surface-primary);border-radius:var(--token-tooltip-border-radius);box-shadow:var(--token-elevation-higher-box-shadow)}.tippy-box[data-theme~=hds][data-animation=fade][data-state=hidden]{opacity:0}.tippy-box[data-theme~=hds][data-inertia][data-state=visible]{transition-timing-function:var(--token-tooltip-transition-function)}.tippy-box[data-theme~=hds] .tippy-content{position:relative;z-index:1;max-width:var(--token-tooltip-max-width);white-space:normal}.tippy-box[data-theme~=hds] .tippy-svg-arrow{fill:var(--token-tooltip-color-surface-primary)}.sr-only{position:absolute!important;width:1px!important;height:1px!important;margin:-1px!important;padding:0!important;overflow:hidden!important;white-space:nowrap!important;border:0!important;clip:rect(1px,1px,1px,1px)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important}fieldset,hr{border:none}blockquote,body,dd,dl,dt,fieldset,figure,hr,html,iframe,legend,li,ol,p,textarea,ul{margin:0;padding:0}ul{list-style:none}table td,table th{padding:0}audio,embed,img,object,video{height:auto;max-width:100%}.consul-intention-action-warn-modal button.dangerous,.copy-button button,.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.informed-action>ul>li>*,.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-select label>*,.topology-notices button,.type-sort.popover-select label>*,label span,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}a{color:var(--token-color-foreground-action)}span,strong,td,th{color:inherit}body{color:var(--token-color-foreground-strong)}html{background-color:var(--token-color-surface-primary);font-size:16px;text-rendering:optimizeLegibility;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;overflow-x:hidden;overflow-y:scroll;box-sizing:border-box;min-width:300px}hr{background-color:var(--token-color-surface-interactive-active);height:1px;margin:1.5rem 0}body,input,select,textarea{font-family:var(--token-typography-font-stack-text)}strong{font-style:inherit}code,pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}pre{-webkit-overflow-scrolling:touch;overflow-x:auto;white-space:pre;word-wrap:normal}*,::after,::before{box-sizing:inherit;animation-play-state:paused;animation-fill-mode:forwards}fieldset{width:100%}a,input[type=checkbox],input[type=radio]{cursor:pointer}td,th{vertical-align:top}button,input,select,textarea{margin:0}iframe{border:0}.consul-bucket-list .service,.consul-bucket-list:not([class]) dt:not([class]),.consul-exposed-path-list>ul>li>.detail dl:not([class]) dt:not([class]),.consul-instance-checks:not([class]) dt:not([class]),.consul-lock-session-list dl:not([class]) dt:not([class]),.consul-server-card dt:not(.name),.consul-upstream-instance-list dl.local-bind-address dt,.consul-upstream-instance-list dl.local-bind-socket-path dt,.consul-upstream-instance-list dl:not([class]) dt:not([class]),.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dt:not([class]),.route-title,.tag-list:not([class]) dt:not([class]),section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dt:not([class]),section[data-route="dc.show.license"] .validity dl .expired+dd,section[data-route="dc.show.license"] .validity dl:not([class]) dt:not([class]),td.tags:not([class]) dt:not([class]){position:absolute;overflow:hidden;clip:rect(0 0 0 0);width:1px;height:1px;margin:-1px;padding:0;border:0}.consul-upstream-instance-list dl.local-bind-socket-mode dt,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dt{position:static!important;clip:unset!important;overflow:visible!important;width:auto!important;height:auto!important;margin:0!important;padding:0!important}.animatable.tab-nav ul::after,.consul-auth-method-type,.consul-external-source,.consul-intention-action-warn-modal button.dangerous,.consul-intention-action-warn-modal button.dangerous:hover:active,.consul-intention-action-warn-modal button.dangerous:hover:not(:disabled):not(:active),.consul-intention-list td.intent- strong,.consul-intention-permission-form button.type-submit,.consul-intention-permission-form button.type-submit:disabled,.consul-intention-permission-form button.type-submit:focus:not(:disabled),.consul-intention-permission-form button.type-submit:hover:not(:disabled),.consul-intention-search-bar .value- span,.consul-kind,.consul-source,.consul-transparent-proxy,.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:first-child,.discovery-chain .route-card>header ul li,.informed-action>ul>.dangerous>*,.informed-action>ul>.dangerous>:focus,.informed-action>ul>.dangerous>:hover,.leader,.menu-panel>ul>li.dangerous>:first-child,.modal-dialog [role=document]>footer,.modal-dialog [role=document]>header,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:first-child,.tab-nav .selected>*,.topology-metrics-source-type,html[data-route^="dc.acls.index"] main td strong,span.policy-node-identity,span.policy-service-identity,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:first-child{border-style:solid}.ember-power-select-trigger,.ember-power-select-trigger--active,.ember-power-select-trigger:focus{border-top:1px solid #aaa;border-bottom:1px solid #aaa;border-right:1px solid #aaa;border-left:1px solid #aaa}.animatable.tab-nav ul::after,.app .notifications .app-notification,.tab-nav li>*{transition-duration:.15s;transition-timing-function:ease-out}html body>.brand-loader{transition-timing-function:cubic-bezier(.1,.1,.25,.9);transition-duration:.1s}html[data-state]:not(.ember-loading) body>.brand-loader{animation-timing-function:cubic-bezier(.1,.1,.25,.9);animation-duration:.1s;animation-name:remove-from-flow;animation-fill-mode:forwards}@keyframes remove-from-flow{100%{visibility:hidden;overflow:hidden;clip:rect(0 0 0 0)}}@keyframes typo-truncate{100%{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}}.CodeMirror-lint-tooltip,dd code,dd pre code{font-family:var(--token-typography-font-stack-code);font-size:var(--token-typography-code-100-font-size);line-height:var(--token-typography-code-100-line-height);font-weight:var(--token-typography-font-weight-regular)}.consul-health-check-list .health-check-output pre code,code,pre,pre code{font-family:var(--token-typography-font-stack-code);font-size:var(--token-typography-code-200-font-size);line-height:var(--token-typography-code-200-line-height);font-weight:var(--token-typography-font-weight-regular)}.informed-action header>*{font-size:inherit;font-weight:inherit;line-height:inherit;font-style:inherit}::after,::before{--tw-content:'';display:inline-block;vertical-align:text-top;background-repeat:no-repeat;background-position:center;mask-repeat:no-repeat;-webkit-mask-repeat:no-repeat;mask-position:center;-webkit-mask-position:center}::before{animation-name:var(--icon-name-start,var(--icon-name)),var(--icon-size-start,var(--icon-size,icon-000));background-color:var(--icon-color-start,var(--icon-color))}::after{animation-name:var(--icon-name-end,var(--icon-name)),var(--icon-size-end,var(--icon-size,icon-000));background-color:var(--icon-color-end,var(--icon-color))}[style*="--icon-color-start"]::before{color:var(--icon-color-start)}[style*="--icon-color-end"]::after{color:var(--icon-color-end)}[style*="--icon-name-start"]::before,[style*="--icon-name-end"]::after{content:""}@keyframes icon-000{100%{width:1.2em;height:1.2em}}@keyframes icon-100{100%{width:.625rem;height:.625rem}}@keyframes icon-200{100%{width:.75rem;height:.75rem}}@keyframes icon-300{100%{width:1rem;height:1rem}}@keyframes icon-400{100%{width:1.125rem;height:1.125rem}}@keyframes icon-500{100%{width:1.25rem;height:1.25rem}}@keyframes icon-600{100%{width:1.375rem;height:1.375rem}}@keyframes icon-700{100%{width:1.5rem;height:1.5rem}}@keyframes icon-800{100%{width:1.625rem;height:1.625rem}}@keyframes icon-900{100%{width:1.75rem;height:1.75rem}}@keyframes icon-999{100%{width:100%;height:100%}}.consul-intention-permission-header-list dt::before,.consul-intention-permission-list dt::before,.discovery-chain .resolver-card dt,.discovery-chain .route-card section header>::before{font-weight:var(--token-typography-font-weight-regular);background-color:var(--token-color-surface-strong);visibility:visible;padding:0 4px}#downstream-container .topology-metrics-card .details .group span::before,#downstream-container .topology-metrics-card div .critical::before,#downstream-container .topology-metrics-card div .empty::before,#downstream-container .topology-metrics-card div .health dt::before,#downstream-container .topology-metrics-card div .nspace dt::before,#downstream-container .topology-metrics-card div .partition dt::before,#downstream-container .topology-metrics-card div .passing::before,#downstream-container .topology-metrics-card div .warning::before,#downstream-container>div:first-child span::before,#login-toggle+div footer button::after,#metrics-container .link .config-link::before,#metrics-container .link .metrics-link::before,#metrics-container:hover .sparkline-key-link::before,#upstream-container .topology-metrics-card .details .group span::before,#upstream-container .topology-metrics-card div .critical::before,#upstream-container .topology-metrics-card div .empty::before,#upstream-container .topology-metrics-card div .health dt::before,#upstream-container .topology-metrics-card div .nspace dt::before,#upstream-container .topology-metrics-card div .partition dt::before,#upstream-container .topology-metrics-card div .passing::before,#upstream-container .topology-metrics-card div .warning::before,.animatable.tab-nav ul::after,.consul-auth-method-binding-list dl dt.type+dd span::before,.consul-auth-method-list ul .locality::before,.consul-auth-method-view dl dt.type+dd span::before,.consul-auth-method-view section dl dt.type+dd span::before,.consul-bucket-list .nspace::before,.consul-bucket-list .partition::before,.consul-bucket-list .peer::before,.consul-exposed-path-list>ul>li>.detail .policy-management::before,.consul-exposed-path-list>ul>li>.detail .policy::before,.consul-exposed-path-list>ul>li>.detail .role::before,.consul-exposed-path-list>ul>li>.detail dl.address dt::before,.consul-exposed-path-list>ul>li>.detail dl.behavior dt::before,.consul-exposed-path-list>ul>li>.detail dl.checks dt::before,.consul-exposed-path-list>ul>li>.detail dl.critical dt::before,.consul-exposed-path-list>ul>li>.detail dl.datacenter dt::before,.consul-exposed-path-list>ul>li>.detail dl.empty dt::before,.consul-exposed-path-list>ul>li>.detail dl.lock-delay dt::before,.consul-exposed-path-list>ul>li>.detail dl.mesh dt::before,.consul-exposed-path-list>ul>li>.detail dl.node dt::before,.consul-exposed-path-list>ul>li>.detail dl.nspace dt::before,.consul-exposed-path-list>ul>li>.detail dl.passing dt::before,.consul-exposed-path-list>ul>li>.detail dl.path dt::before,.consul-exposed-path-list>ul>li>.detail dl.port dt::before,.consul-exposed-path-list>ul>li>.detail dl.protocol dt::before,.consul-exposed-path-list>ul>li>.detail dl.socket dt::before,.consul-exposed-path-list>ul>li>.detail dl.ttl dt::before,.consul-exposed-path-list>ul>li>.detail dl.unknown dt::before,.consul-exposed-path-list>ul>li>.detail dl.warning dt::before,.consul-exposed-path-list>ul>li>.header .critical dd::before,.consul-exposed-path-list>ul>li>.header .empty dd::before,.consul-exposed-path-list>ul>li>.header .passing dd::before,.consul-exposed-path-list>ul>li>.header .policy-management dd::before,.consul-exposed-path-list>ul>li>.header .unknown dd::before,.consul-exposed-path-list>ul>li>.header .warning dd::before,.consul-exposed-path-list>ul>li>.header [rel=me] dd::before,.consul-external-source.jwt::before,.consul-external-source.oidc::before,.consul-health-check-list .health-check-output dd em.jwt::before,.consul-health-check-list .health-check-output dd em.oidc::before,.consul-health-check-list .health-check-output::before,.consul-instance-checks dt::before,.consul-intention-fieldsets .value->:last-child::before,.consul-intention-fieldsets .value-allow>:last-child::before,.consul-intention-fieldsets .value-deny>:last-child::before,.consul-intention-list em span::before,.consul-intention-list td strong.jwt::before,.consul-intention-list td strong.oidc::before,.consul-intention-list td.intent- strong::before,.consul-intention-list td.intent-allow strong::before,.consul-intention-list td.intent-deny strong::before,.consul-intention-permission-list .intent-allow::before,.consul-intention-permission-list .intent-deny::before,.consul-intention-permission-list strong.jwt::before,.consul-intention-permission-list strong.oidc::before,.consul-intention-search-bar .value- span::before,.consul-intention-search-bar .value-allow span::before,.consul-intention-search-bar .value-deny span::before,.consul-intention-search-bar li button span.jwt::before,.consul-intention-search-bar li button span.oidc::before,.consul-kind::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .policy-management::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .policy::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .role::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.address dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.behavior dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.checks dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.critical dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.datacenter dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.empty dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.lock-delay dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.mesh dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.node dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.nspace dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.passing dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.path dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.port dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.protocol dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.socket dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.ttl dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.unknown dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.warning dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .critical dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header .empty dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header .passing dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header .policy-management dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header .unknown dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header .warning dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header [rel=me] dd::before,.consul-peer-search-bar li button span.jwt::before,.consul-peer-search-bar li button span.oidc::before,.consul-server-card .health-status+dd.jwt::before,.consul-server-card .health-status+dd.oidc::before,.consul-upstream-instance-list dl.datacenter dt::before,.consul-upstream-instance-list dl.nspace dt::before,.consul-upstream-instance-list dl.partition dt::before,.consul-upstream-instance-list li>.detail .policy-management::before,.consul-upstream-instance-list li>.detail .policy::before,.consul-upstream-instance-list li>.detail .role::before,.consul-upstream-instance-list li>.detail dl.address dt::before,.consul-upstream-instance-list li>.detail dl.behavior dt::before,.consul-upstream-instance-list li>.detail dl.checks dt::before,.consul-upstream-instance-list li>.detail dl.critical dt::before,.consul-upstream-instance-list li>.detail dl.datacenter dt::before,.consul-upstream-instance-list li>.detail dl.empty dt::before,.consul-upstream-instance-list li>.detail dl.lock-delay dt::before,.consul-upstream-instance-list li>.detail dl.mesh dt::before,.consul-upstream-instance-list li>.detail dl.node dt::before,.consul-upstream-instance-list li>.detail dl.nspace dt::before,.consul-upstream-instance-list li>.detail dl.passing dt::before,.consul-upstream-instance-list li>.detail dl.path dt::before,.consul-upstream-instance-list li>.detail dl.port dt::before,.consul-upstream-instance-list li>.detail dl.protocol dt::before,.consul-upstream-instance-list li>.detail dl.socket dt::before,.consul-upstream-instance-list li>.detail dl.ttl dt::before,.consul-upstream-instance-list li>.detail dl.unknown dt::before,.consul-upstream-instance-list li>.detail dl.warning dt::before,.consul-upstream-instance-list li>.header .critical dd::before,.consul-upstream-instance-list li>.header .empty dd::before,.consul-upstream-instance-list li>.header .passing dd::before,.consul-upstream-instance-list li>.header .policy-management dd::before,.consul-upstream-instance-list li>.header .unknown dd::before,.consul-upstream-instance-list li>.header .warning dd::before,.consul-upstream-instance-list li>.header [rel=me] dd::before,.consul-upstream-list dl.partition dt::before,.copy-button button::before,.dangerous.informed-action header::before,.disclosure-menu [aria-expanded]~*>ul>li.is-active>::after,.disclosure-menu [aria-expanded]~*>ul>li[aria-checked]>::after,.disclosure-menu [aria-expanded]~*>ul>li[aria-current]>::after,.disclosure-menu [aria-expanded]~*>ul>li[aria-selected]>::after,.discovery-chain .resolvers>header span::after,.discovery-chain .route-card::before,.discovery-chain .route-card>header ul li.jwt::before,.discovery-chain .route-card>header ul li.oidc::before,.discovery-chain .routes>header span::after,.discovery-chain .splitter-card::before,.discovery-chain .splitters>header span::after,.empty-state li[class*=-link]>::after,.has-error>strong::before,.info.informed-action header::before,.jwt.consul-auth-method-type::before,.jwt.consul-external-source::before,.jwt.consul-kind::before,.jwt.consul-source::before,.jwt.consul-transparent-proxy::before,.jwt.leader::before,.jwt.topology-metrics-source-type::before,.leader::before,.list-collection>button::after,.list-collection>ul>li:not(:first-child)>.detail .policy-management::before,.list-collection>ul>li:not(:first-child)>.detail .policy::before,.list-collection>ul>li:not(:first-child)>.detail .role::before,.list-collection>ul>li:not(:first-child)>.detail dl.address dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.behavior dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.checks dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.critical dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.datacenter dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.empty dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.lock-delay dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.mesh dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.node dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.nspace dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.passing dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.path dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.port dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.protocol dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.socket dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.ttl dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.unknown dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.warning dt::before,.list-collection>ul>li:not(:first-child)>.header .critical dd::before,.list-collection>ul>li:not(:first-child)>.header .empty dd::before,.list-collection>ul>li:not(:first-child)>.header .passing dd::before,.list-collection>ul>li:not(:first-child)>.header .policy-management dd::before,.list-collection>ul>li:not(:first-child)>.header .unknown dd::before,.list-collection>ul>li:not(:first-child)>.header .warning dd::before,.list-collection>ul>li:not(:first-child)>.header [rel=me] dd::before,.menu-panel>ul>li.is-active>::after,.menu-panel>ul>li[aria-checked]>::after,.menu-panel>ul>li[aria-current]>::after,.menu-panel>ul>li[aria-selected]>::after,.modal-dialog [role=document] a[rel*=help]::after,.modal-dialog [role=document] table td.folder::before,.modal-dialog [role=document] table th span::after,.more-popover-menu>[type=checkbox]+label+div>ul>li.is-active>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li[aria-checked]>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li[aria-current]>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li[aria-selected]>::after,.more-popover-menu>[type=checkbox]+label>::after,.oidc-select .auth0-oidc-provider::before,.oidc-select .google-oidc-provider::before,.oidc-select .microsoft-oidc-provider::before,.oidc-select .okta-oidc-provider::before,.oidc.consul-auth-method-type::before,.oidc.consul-external-source::before,.oidc.consul-kind::before,.oidc.consul-source::before,.oidc.consul-transparent-proxy::before,.oidc.leader::before,.oidc.topology-metrics-source-type::before,.popover-menu>[type=checkbox]+label+div>ul>li.is-active>::after,.popover-menu>[type=checkbox]+label+div>ul>li[aria-checked]>::after,.popover-menu>[type=checkbox]+label+div>ul>li[aria-current]>::after,.popover-menu>[type=checkbox]+label+div>ul>li[aria-selected]>::after,.popover-menu>[type=checkbox]+label>::after,.popover-select .jwt button::before,.popover-select .oidc button::before,.popover-select .value-critical button::before,.popover-select .value-empty button::before,.popover-select .value-passing button::before,.popover-select .value-unknown button::before,.popover-select .value-warning button::before,.search-bar-status li.jwt:not(.remove-all)::before,.search-bar-status li.oidc:not(.remove-all)::before,.search-bar-status li:not(.remove-all) button::before,.sparkline-key h3::before,.tag-list dt::before,.tooltip-panel dd>div::before,.topology-metrics-popover.deny .tippy-arrow::after,.topology-metrics-popover.deny>button::before,.topology-metrics-popover.l7 .tippy-arrow::after,.topology-metrics-popover.l7>button::before,.topology-metrics-popover.not-defined .tippy-arrow::after,.topology-metrics-popover.not-defined>button::before,.topology-metrics-status-error span::before,.topology-metrics-status-loader span::before,.topology-notices button::before,.type-sort.popover-select label>::before,.type-source.popover-select li.partition button::before,.warning.informed-action header::before,.warning.modal-dialog header::before,[class*=status-].empty-state header::before,a[rel*=external]::after,html[data-route^="dc.acls.index"] main td strong.jwt::before,html[data-route^="dc.acls.index"] main td strong.oidc::before,main a[rel*=help]::after,main header nav:first-child ol li:first-child a::before,main table td.folder::before,main table th span::after,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl.jwt::before,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl.oidc::before,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em.jwt::before,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em.oidc::before,span.jwt.policy-node-identity::before,span.jwt.policy-service-identity::before,span.oidc.policy-node-identity::before,span.oidc.policy-service-identity::before,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.is-active>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li[aria-checked]>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li[aria-current]>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li[aria-selected]>::after,table.has-actions tr>.actions>[type=checkbox]+label>::after,table.with-details td:only-child>div>label::before,table.with-details td>label::before,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.is-active>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li[aria-checked]>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li[aria-current]>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li[aria-selected]>::after,table.with-details tr>.actions>[type=checkbox]+label>::after,td.tags dt::before{content:""}@keyframes icon-alert-circle-outline{100%{-webkit-mask-image:var(--icon-alert-circle-16);mask-image:var(--icon-alert-circle-16);background-color:var(--icon-color,var(--color-alert-circle-outline-500,currentColor))}}[class*=status-].empty-state header::before{--icon-name:icon-alert-circle-outline;content:""}@keyframes icon-alert-triangle{100%{-webkit-mask-image:var(--icon-alert-triangle-16);mask-image:var(--icon-alert-triangle-16);background-color:var(--icon-color,var(--color-alert-triangle-500,currentColor))}}#downstream-container .topology-metrics-card div .warning::before,#upstream-container .topology-metrics-card div .warning::before,.consul-exposed-path-list>ul>li>.detail dl.warning dt::before,.consul-exposed-path-list>ul>li>.header .warning dd::before,.consul-health-check-list .warning.health-check-output::before,.consul-instance-checks.warning dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.warning dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .warning dd::before,.consul-upstream-instance-list li>.detail dl.warning dt::before,.consul-upstream-instance-list li>.header .warning dd::before,.dangerous.informed-action header::before,.list-collection>ul>li:not(:first-child)>.detail dl.warning dt::before,.list-collection>ul>li:not(:first-child)>.header .warning dd::before,.popover-select .value-warning button::before,.topology-metrics-popover.not-defined .tippy-arrow::after,.topology-metrics-popover.not-defined>button::before,.warning.informed-action header::before,.warning.modal-dialog header::before{--icon-name:icon-alert-triangle;content:""}@keyframes icon-arrow-left{100%{-webkit-mask-image:var(--icon-arrow-left-16);mask-image:var(--icon-arrow-left-16);background-color:var(--icon-color,var(--color-arrow-left-500,currentColor))}}@keyframes icon-arrow-right{100%{-webkit-mask-image:var(--icon-arrow-right-16);mask-image:var(--icon-arrow-right-16);background-color:var(--icon-color,var(--color-arrow-right-500,currentColor))}}@keyframes icon-cancel-plain{100%{-webkit-mask-image:var(--icon-x-16);mask-image:var(--icon-x-16);background-color:var(--icon-color,var(--color-cancel-plain-500,currentColor))}}.search-bar-status li:not(.remove-all) button::before{--icon-name:icon-cancel-plain;content:""}@keyframes icon-cancel-square-fill{100%{-webkit-mask-image:var(--icon-x-square-fill-16);mask-image:var(--icon-x-square-fill-16);background-color:var(--icon-color,var(--color-cancel-square-fill-500,currentColor))}}#downstream-container .topology-metrics-card div .critical::before,#upstream-container .topology-metrics-card div .critical::before,.consul-exposed-path-list>ul>li>.detail dl.critical dt::before,.consul-exposed-path-list>ul>li>.header .critical dd::before,.consul-health-check-list .critical.health-check-output::before,.consul-instance-checks.critical dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.critical dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .critical dd::before,.consul-upstream-instance-list li>.detail dl.critical dt::before,.consul-upstream-instance-list li>.header .critical dd::before,.has-error>strong::before,.list-collection>ul>li:not(:first-child)>.detail dl.critical dt::before,.list-collection>ul>li:not(:first-child)>.header .critical dd::before,.popover-select .value-critical button::before,.topology-metrics-popover.deny .tippy-arrow::after,.topology-metrics-popover.deny>button::before{--icon-name:icon-cancel-square-fill;content:""}@keyframes icon-check-plain{100%{-webkit-mask-image:var(--icon-check-16);mask-image:var(--icon-check-16);background-color:var(--icon-color,var(--color-check-plain-500,currentColor))}}.disclosure-menu [aria-expanded]~*>ul>li.is-active>::after,.disclosure-menu [aria-expanded]~*>ul>li[aria-checked]>::after,.disclosure-menu [aria-expanded]~*>ul>li[aria-current]>::after,.disclosure-menu [aria-expanded]~*>ul>li[aria-selected]>::after,.menu-panel>ul>li.is-active>::after,.menu-panel>ul>li[aria-checked]>::after,.menu-panel>ul>li[aria-current]>::after,.menu-panel>ul>li[aria-selected]>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li.is-active>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li[aria-checked]>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li[aria-current]>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li[aria-selected]>::after,.popover-menu>[type=checkbox]+label+div>ul>li.is-active>::after,.popover-menu>[type=checkbox]+label+div>ul>li[aria-checked]>::after,.popover-menu>[type=checkbox]+label+div>ul>li[aria-current]>::after,.popover-menu>[type=checkbox]+label+div>ul>li[aria-selected]>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.is-active>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li[aria-checked]>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li[aria-current]>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li[aria-selected]>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.is-active>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li[aria-checked]>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li[aria-current]>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li[aria-selected]>::after{--icon-name:icon-check-plain;content:""}@keyframes icon-chevron-down{100%{-webkit-mask-image:var(--icon-chevron-down-16);mask-image:var(--icon-chevron-down-16);background-color:var(--icon-color,var(--color-chevron-down-500,currentColor))}}.list-collection>button.closed::after,.more-popover-menu>[type=checkbox]+label>::after,.popover-menu>[type=checkbox]+label>::after,.topology-notices button::before,table.has-actions tr>.actions>[type=checkbox]+label>::after,table.with-details td:only-child>div>label::before,table.with-details td>label::before,table.with-details tr>.actions>[type=checkbox]+label>::after{--icon-name:icon-chevron-down;content:""}@keyframes icon-copy-action{100%{-webkit-mask-image:var(--icon-clipboard-copy-16);mask-image:var(--icon-clipboard-copy-16);background-color:var(--icon-color,var(--color-copy-action-500,currentColor))}}.copy-button button::before{--icon-name:icon-copy-action;content:"";--icon-color:var(--token-color-foreground-faint)}@keyframes icon-deny-alt{100%{-webkit-mask-image:var(--icon-skip-16);mask-image:var(--icon-skip-16);background-color:var(--icon-color,var(--color-deny-alt-500,currentColor))}}@keyframes icon-deny-default{100%{-webkit-mask-image:var(--icon-skip-16);mask-image:var(--icon-skip-16);background-color:var(--icon-color,var(--color-deny-default-500,currentColor))}}@keyframes icon-disabled{100%{-webkit-mask-image:var(--icon-skip-16);mask-image:var(--icon-skip-16);background-color:var(--icon-color,var(--color-disabled-500,currentColor))}}.status-403.empty-state header::before{--icon-name:icon-disabled;content:""}@keyframes icon-docs{100%{-webkit-mask-image:var(--icon-docs-16);mask-image:var(--icon-docs-16);background-color:var(--icon-color,var(--color-docs-500,currentColor))}}#metrics-container .link .config-link::before,.empty-state .docs-link>::after{--icon-name:icon-docs;content:""}@keyframes icon-exit{100%{-webkit-mask-image:var(--icon-external-link-16);mask-image:var(--icon-external-link-16);background-color:var(--icon-color,var(--color-exit-500,currentColor))}}#metrics-container .link .metrics-link::before,a[rel*=external]::after{--icon-name:icon-exit;content:""}@keyframes icon-file-fill{100%{-webkit-mask-image:var(--icon-file-16);mask-image:var(--icon-file-16);background-color:var(--icon-color,var(--color-file-fill-500,currentColor))}}@keyframes icon-folder-outline{100%{-webkit-mask-image:var(--icon-folder-16);mask-image:var(--icon-folder-16);background-color:var(--icon-color,var(--color-folder-outline-500,currentColor))}}#downstream-container .topology-metrics-card div .nspace dt::before,#upstream-container .topology-metrics-card div .nspace dt::before,.consul-bucket-list .nspace::before,.consul-exposed-path-list>ul>li>.detail dl.nspace dt::before,.consul-intention-list span[class|=nspace]::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.nspace dt::before,.consul-upstream-instance-list dl.nspace dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.nspace dt::before,.modal-dialog [role=document] table td.folder::before,main table td.folder::before{--icon-name:icon-folder-outline;content:""}@keyframes icon-health{100%{-webkit-mask-image:var(--icon-activity-16);mask-image:var(--icon-activity-16);background-color:var(--icon-color,var(--color-health-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.checks dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.checks dt::before,.consul-upstream-instance-list li>.detail dl.checks dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.checks dt::before{--icon-name:icon-health;content:""}@keyframes icon-help-circle-outline{100%{-webkit-mask-image:var(--icon-help-16);mask-image:var(--icon-help-16);background-color:var(--icon-color,var(--color-help-circle-outline-500,currentColor))}}#downstream-container .topology-metrics-card div .health dt::before,#upstream-container .topology-metrics-card div .health dt::before,.consul-exposed-path-list>ul>li>.detail dl.unknown dt::before,.consul-exposed-path-list>ul>li>.header .unknown dd::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.unknown dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .unknown dd::before,.consul-upstream-instance-list li>.detail dl.unknown dt::before,.consul-upstream-instance-list li>.header .unknown dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.unknown dt::before,.list-collection>ul>li:not(:first-child)>.header .unknown dd::before,.popover-select .value-unknown button::before,.status-404.empty-state header::before{--icon-name:icon-help-circle-outline;content:""}@keyframes icon-info-circle-fill{100%{-webkit-mask-image:var(--icon-info-16);mask-image:var(--icon-info-16);background-color:var(--icon-color,var(--color-info-circle-fill-500,currentColor))}}#metrics-container:hover .sparkline-key-link::before,.info.informed-action header::before,.sparkline-key h3::before{--icon-name:icon-info-circle-fill;content:""}@keyframes icon-info-circle-outline{100%{-webkit-mask-image:var(--icon-info-16);mask-image:var(--icon-info-16);background-color:var(--icon-color,var(--color-info-circle-outline-500,currentColor))}}#downstream-container>div:first-child span::before,.consul-auth-method-binding-list dl dt.type+dd span::before,.consul-auth-method-view dl dt.type+dd span::before,.consul-exposed-path-list>ul>li>.detail dl.behavior dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.behavior dt::before,.consul-upstream-instance-list li>.detail dl.behavior dt::before,.discovery-chain .resolvers>header span::after,.discovery-chain .routes>header span::after,.discovery-chain .splitters>header span::after,.list-collection>ul>li:not(:first-child)>.detail dl.behavior dt::before,.modal-dialog [role=document] a[rel*=help]::after,.modal-dialog [role=document] table th span::after,.topology-metrics-status-error span::before,.topology-metrics-status-loader span::before,main a[rel*=help]::after,main table th span::after{--icon-name:icon-info-circle-outline;content:""}@keyframes icon-learn{100%{-webkit-mask-image:var(--icon-learn-16);mask-image:var(--icon-learn-16);background-color:var(--icon-color,var(--color-learn-500,currentColor))}}.empty-state .learn-link>::after{--icon-name:icon-learn;content:""}@keyframes icon-logo-github-monochrome{100%{-webkit-mask-image:var(--icon-github-color-16);mask-image:var(--icon-github-color-16);background-color:var(--icon-color,var(--color-logo-github-monochrome-500,currentColor))}}@keyframes icon-logo-google-color{100%{background-image:var(--icon-google-color-16)}}.oidc-select .google-oidc-provider::before{--icon-name:icon-logo-google-color;content:""}@keyframes icon-logo-kubernetes-color{100%{background-image:var(--icon-kubernetes-color-16)}}@keyframes icon-menu{100%{-webkit-mask-image:var(--icon-menu-16);mask-image:var(--icon-menu-16);background-color:var(--icon-color,var(--color-menu-500,currentColor))}}@keyframes icon-minus-square-fill{100%{-webkit-mask-image:var(--icon-minus-square-16);mask-image:var(--icon-minus-square-16);background-color:var(--icon-color,var(--color-minus-square-fill-500,currentColor))}}#downstream-container .topology-metrics-card div .empty::before,#upstream-container .topology-metrics-card div .empty::before,.consul-exposed-path-list>ul>li>.detail dl.empty dt::before,.consul-exposed-path-list>ul>li>.header .empty dd::before,.consul-instance-checks.empty dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.empty dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .empty dd::before,.consul-upstream-instance-list li>.detail dl.empty dt::before,.consul-upstream-instance-list li>.header .empty dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.empty dt::before,.list-collection>ul>li:not(:first-child)>.header .empty dd::before,.popover-select .value-empty button::before{--icon-name:icon-minus-square-fill;content:""}@keyframes icon-more-horizontal{100%{-webkit-mask-image:var(--icon-more-horizontal-16);mask-image:var(--icon-more-horizontal-16);background-color:var(--icon-color,var(--color-more-horizontal-500,currentColor))}}@keyframes icon-public-default{100%{-webkit-mask-image:var(--icon-globe-16);mask-image:var(--icon-globe-16);background-color:var(--icon-color,var(--color-public-default-500,currentColor))}}.consul-auth-method-list ul .locality::before,.consul-exposed-path-list>ul>li>.detail dl.address dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.address dt::before,.consul-upstream-instance-list li>.detail dl.address dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.address dt::before{--icon-name:icon-public-default;content:""}@keyframes icon-search{100%{-webkit-mask-image:var(--icon-search-16);mask-image:var(--icon-search-16);background-color:var(--icon-color,var(--color-search-500,currentColor))}}@keyframes icon-star-outline{100%{-webkit-mask-image:var(--icon-star-16);mask-image:var(--icon-star-16);background-color:var(--icon-color,var(--color-star-outline-500,currentColor))}}.leader::before{--icon-name:icon-star-outline;content:""}@keyframes icon-user-organization{100%{-webkit-mask-image:var(--icon-org-16);mask-image:var(--icon-org-16);background-color:var(--icon-color,var(--color-user-organization-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.datacenter dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.datacenter dt::before,.consul-upstream-instance-list dl.datacenter dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.datacenter dt::before{--icon-name:icon-user-organization;content:""}@keyframes icon-user-plain{100%{-webkit-mask-image:var(--icon-user-16);mask-image:var(--icon-user-16);background-color:var(--icon-color,var(--color-user-plain-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail .role::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .role::before,.consul-upstream-instance-list li>.detail .role::before,.list-collection>ul>li:not(:first-child)>.detail .role::before{--icon-name:icon-user-plain;content:""}@keyframes icon-user-team{100%{-webkit-mask-image:var(--icon-users-16);mask-image:var(--icon-users-16);background-color:var(--icon-color,var(--color-user-team-500,currentColor))}}#downstream-container .topology-metrics-card div .partition dt::before,#upstream-container .topology-metrics-card div .partition dt::before,.consul-bucket-list .partition::before,.consul-intention-list span[class|=partition]::before,.consul-upstream-instance-list dl.partition dt::before,.consul-upstream-list dl.partition dt::before,.type-source.popover-select li.partition button::before{--icon-name:icon-user-team;content:""}@keyframes icon-alert-circle{100%{-webkit-mask-image:var(--icon-alert-circle-16);mask-image:var(--icon-alert-circle-16);background-color:var(--icon-color,var(--color-alert-circle-500,currentColor))}}@keyframes icon-check{100%{-webkit-mask-image:var(--icon-check-16);mask-image:var(--icon-check-16);background-color:var(--icon-color,var(--color-check-500,currentColor))}}@keyframes icon-check-circle{100%{-webkit-mask-image:var(--icon-check-circle-16);mask-image:var(--icon-check-circle-16);background-color:var(--icon-color,var(--color-check-circle-500,currentColor))}}@keyframes icon-check-circle-fill{100%{-webkit-mask-image:var(--icon-check-circle-fill-16);mask-image:var(--icon-check-circle-fill-16);background-color:var(--icon-color,var(--color-check-circle-fill-500,currentColor))}}#downstream-container .topology-metrics-card div .passing::before,#upstream-container .topology-metrics-card div .passing::before,.consul-exposed-path-list>ul>li>.detail dl.passing dt::before,.consul-exposed-path-list>ul>li>.header .passing dd::before,.consul-exposed-path-list>ul>li>.header [rel=me] dd::before,.consul-health-check-list .passing.health-check-output::before,.consul-instance-checks.passing dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.passing dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .passing dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header [rel=me] dd::before,.consul-upstream-instance-list li>.detail dl.passing dt::before,.consul-upstream-instance-list li>.header .passing dd::before,.consul-upstream-instance-list li>.header [rel=me] dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.passing dt::before,.list-collection>ul>li:not(:first-child)>.header .passing dd::before,.list-collection>ul>li:not(:first-child)>.header [rel=me] dd::before,.popover-select .value-passing button::before{--icon-name:icon-check-circle-fill;content:""}@keyframes icon-chevron-left{100%{-webkit-mask-image:var(--icon-chevron-left-16);mask-image:var(--icon-chevron-left-16);background-color:var(--icon-color,var(--color-chevron-left-500,currentColor))}}.empty-state .back-link>::after,main header nav:first-child ol li:first-child a::before{--icon-name:icon-chevron-left;content:""}@keyframes icon-chevron-right{100%{-webkit-mask-image:var(--icon-chevron-right-16);mask-image:var(--icon-chevron-right-16);background-color:var(--icon-color,var(--color-chevron-right-500,currentColor))}}#login-toggle+div footer button::after{--icon-name:icon-chevron-right;content:""}@keyframes icon-chevron-up{100%{-webkit-mask-image:var(--icon-chevron-up-16);mask-image:var(--icon-chevron-up-16);background-color:var(--icon-color,var(--color-chevron-up-500,currentColor))}}.list-collection>button::after,.more-popover-menu>[type=checkbox]:checked+label>::after,.popover-menu>[type=checkbox]:checked+label>::after,.topology-notices button[aria-expanded=true]::before,table.has-actions tr>.actions>[type=checkbox]:checked+label>::after,table.with-details tr>.actions>[type=checkbox]:checked+label>::after{--icon-name:icon-chevron-up;content:""}@keyframes icon-delay{100%{-webkit-mask-image:var(--icon-delay-16);mask-image:var(--icon-delay-16);background-color:var(--icon-color,var(--color-delay-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.lock-delay dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.lock-delay dt::before,.consul-upstream-instance-list li>.detail dl.lock-delay dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.lock-delay dt::before{--icon-name:icon-delay;content:""}@keyframes icon-docs-link{100%{-webkit-mask-image:var(--icon-docs-link-16);mask-image:var(--icon-docs-link-16);background-color:var(--icon-color,var(--color-docs-link-500,currentColor))}}@keyframes icon-eye{100%{-webkit-mask-image:var(--icon-eye-16);mask-image:var(--icon-eye-16);background-color:var(--icon-color,var(--color-eye-500,currentColor))}}@keyframes icon-eye-off{100%{-webkit-mask-image:var(--icon-eye-off-16);mask-image:var(--icon-eye-off-16);background-color:var(--icon-color,var(--color-eye-off-500,currentColor))}}@keyframes icon-file-text{100%{-webkit-mask-image:var(--icon-file-text-16);mask-image:var(--icon-file-text-16);background-color:var(--icon-color,var(--color-file-text-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail .policy::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .policy::before,.consul-upstream-instance-list li>.detail .policy::before,.list-collection>ul>li:not(:first-child)>.detail .policy::before{--icon-name:icon-file-text;content:""}@keyframes icon-gateway{100%{-webkit-mask-image:var(--icon-gateway-16);mask-image:var(--icon-gateway-16);background-color:var(--icon-color,var(--color-gateway-500,currentColor))}}.consul-kind::before{--icon-name:icon-gateway;content:""}@keyframes icon-git-commit{100%{-webkit-mask-image:var(--icon-git-commit-16);mask-image:var(--icon-git-commit-16);background-color:var(--icon-color,var(--color-git-commit-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.node dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.node dt::before,.consul-upstream-instance-list li>.detail dl.node dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.node dt::before{--icon-name:icon-git-commit;content:""}@keyframes icon-hexagon{100%{-webkit-mask-image:var(--icon-hexagon-16);mask-image:var(--icon-hexagon-16);background-color:var(--icon-color,var(--color-hexagon-500,currentColor))}}@keyframes icon-history{100%{-webkit-mask-image:var(--icon-history-16);mask-image:var(--icon-history-16);background-color:var(--icon-color,var(--color-history-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.ttl dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.ttl dt::before,.consul-upstream-instance-list li>.detail dl.ttl dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.ttl dt::before{--icon-name:icon-history;content:""}@keyframes icon-info{100%{-webkit-mask-image:var(--icon-info-16);mask-image:var(--icon-info-16);background-color:var(--icon-color,var(--color-info-500,currentColor))}}@keyframes icon-layers{100%{-webkit-mask-image:var(--icon-layers-16);mask-image:var(--icon-layers-16);background-color:var(--icon-color,var(--color-layers-500,currentColor))}}.topology-metrics-popover.l7 .tippy-arrow::after,.topology-metrics-popover.l7>button::before{--icon-name:icon-layers;content:"";--icon-color:var(--token-color-palette-neutral-300)}@keyframes icon-loading{100%{-webkit-mask-image:var(--icon-loading-16);mask-image:var(--icon-loading-16);background-color:var(--icon-color,var(--color-loading-500,currentColor))}}@keyframes icon-network-alt{100%{-webkit-mask-image:var(--icon-network-alt-16);mask-image:var(--icon-network-alt-16);background-color:var(--icon-color,var(--color-network-alt-500,currentColor))}}.consul-bucket-list .peer::before{--icon-name:icon-network-alt;content:""}@keyframes icon-path{100%{-webkit-mask-image:var(--icon-path-16);mask-image:var(--icon-path-16);background-color:var(--icon-color,var(--color-path-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.path dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.path dt::before,.consul-upstream-instance-list li>.detail dl.path dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.path dt::before{--icon-name:icon-path;content:""}@keyframes icon-running{100%{-webkit-mask-image:var(--icon-running-16);mask-image:var(--icon-running-16);background-color:var(--icon-color,var(--color-running-500,currentColor))}}@keyframes icon-skip{100%{-webkit-mask-image:var(--icon-skip-16);mask-image:var(--icon-skip-16);background-color:var(--icon-color,var(--color-skip-500,currentColor))}}@keyframes icon-socket{100%{-webkit-mask-image:var(--icon-socket-16);mask-image:var(--icon-socket-16);background-color:var(--icon-color,var(--color-socket-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.socket dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.socket dt::before,.consul-upstream-instance-list li>.detail dl.socket dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.socket dt::before{--icon-name:icon-socket;content:""}@keyframes icon-star-circle{100%{-webkit-mask-image:var(--icon-star-circle-16);mask-image:var(--icon-star-circle-16);background-color:var(--icon-color,var(--color-star-circle-500,currentColor))}}@keyframes icon-star-fill{100%{-webkit-mask-image:var(--icon-star-fill-16);mask-image:var(--icon-star-fill-16);background-color:var(--icon-color,var(--color-star-fill-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail .policy-management::before,.consul-exposed-path-list>ul>li>.header .policy-management dd::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .policy-management::before,.consul-lock-session-list ul>li:not(:first-child)>.header .policy-management dd::before,.consul-upstream-instance-list li>.detail .policy-management::before,.consul-upstream-instance-list li>.header .policy-management dd::before,.list-collection>ul>li:not(:first-child)>.detail .policy-management::before,.list-collection>ul>li:not(:first-child)>.header .policy-management dd::before{--icon-name:icon-star-fill;content:"";--icon-color:var(--token-color-consul-brand)}@keyframes icon-tag{100%{-webkit-mask-image:var(--icon-tag-16);mask-image:var(--icon-tag-16);background-color:var(--icon-color,var(--color-tag-500,currentColor))}}.tag-list dt::before,td.tags dt::before{--icon-name:icon-tag;content:""}@keyframes icon-x{100%{-webkit-mask-image:var(--icon-x-16);mask-image:var(--icon-x-16);background-color:var(--icon-color,var(--color-x-500,currentColor))}}@keyframes icon-x-circle{100%{-webkit-mask-image:var(--icon-x-circle-16);mask-image:var(--icon-x-circle-16);background-color:var(--icon-color,var(--color-x-circle-500,currentColor))}}@keyframes icon-x-square{100%{-webkit-mask-image:var(--icon-x-square-16);mask-image:var(--icon-x-square-16);background-color:var(--icon-color,var(--color-x-square-500,currentColor))}}@keyframes icon-cloud-cross{100%{-webkit-mask-image:var(--icon-cloud-cross-16);mask-image:var(--icon-cloud-cross-16);background-color:var(--icon-color,var(--color-cloud-cross-500,currentColor))}}@keyframes icon-loading-motion{100%{-webkit-mask-image:var(--icon-loading-motion-16);mask-image:var(--icon-loading-motion-16);background-color:var(--icon-color,var(--color-loading-motion-500,currentColor))}}@keyframes icon-logo-auth0-color{100%{background-image:var(--icon-auth0-color-16)}}.oidc-select .auth0-oidc-provider::before{--icon-name:icon-logo-auth0-color;content:""}@keyframes icon-logo-ember-circle-color{100%{background-image:var(--icon-logo-ember-circle-color-16)}}@keyframes icon-logo-glimmer-color{100%{background-image:var(--icon-logo-glimmer-color-16)}}@keyframes icon-logo-jwt-color{100%{background-image:var(--icon-logo-jwt-color-16)}}.consul-external-source.jwt::before,.consul-health-check-list .health-check-output dd em.jwt::before,.consul-intention-list td strong.jwt::before,.consul-intention-permission-list strong.jwt::before,.consul-intention-search-bar li button span.jwt::before,.consul-peer-search-bar li button span.jwt::before,.consul-server-card .health-status+dd.jwt::before,.discovery-chain .route-card>header ul li.jwt::before,.jwt.consul-auth-method-type::before,.jwt.consul-kind::before,.jwt.consul-source::before,.jwt.consul-transparent-proxy::before,.jwt.leader::before,.jwt.topology-metrics-source-type::before,.popover-select .jwt button::before,.search-bar-status li.jwt:not(.remove-all)::before,html[data-route^="dc.acls.index"] main td strong.jwt::before,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl.jwt::before,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em.jwt::before,span.jwt.policy-node-identity::before,span.jwt.policy-service-identity::before{--icon-name:icon-logo-jwt-color;content:""}@keyframes icon-logo-microsoft-color{100%{background-image:var(--icon-microsoft-color-16)}}.oidc-select .microsoft-oidc-provider::before{--icon-name:icon-logo-microsoft-color;content:""}@keyframes icon-logo-oidc-color{100%{background-image:var(--icon-logo-oidc-color-16)}}.consul-external-source.oidc::before,.consul-health-check-list .health-check-output dd em.oidc::before,.consul-intention-list td strong.oidc::before,.consul-intention-permission-list strong.oidc::before,.consul-intention-search-bar li button span.oidc::before,.consul-peer-search-bar li button span.oidc::before,.consul-server-card .health-status+dd.oidc::before,.discovery-chain .route-card>header ul li.oidc::before,.oidc.consul-auth-method-type::before,.oidc.consul-kind::before,.oidc.consul-source::before,.oidc.consul-transparent-proxy::before,.oidc.leader::before,.oidc.topology-metrics-source-type::before,.popover-select .oidc button::before,.search-bar-status li.oidc:not(.remove-all)::before,html[data-route^="dc.acls.index"] main td strong.oidc::before,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl.oidc::before,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em.oidc::before,span.oidc.policy-node-identity::before,span.oidc.policy-service-identity::before{--icon-name:icon-logo-oidc-color;content:""}@keyframes icon-logo-okta-color{100%{background-image:var(--icon-okta-color-16)}}.oidc-select .okta-oidc-provider::before{--icon-name:icon-logo-okta-color;content:""}@keyframes icon-mesh{100%{-webkit-mask-image:var(--icon-mesh-16);mask-image:var(--icon-mesh-16);background-color:var(--icon-color,var(--color-mesh-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.mesh dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.mesh dt::before,.consul-upstream-instance-list li>.detail dl.mesh dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.mesh dt::before{--icon-name:icon-mesh;content:""}@keyframes icon-port{100%{-webkit-mask-image:var(--icon-port-16);mask-image:var(--icon-port-16);background-color:var(--icon-color,var(--color-port-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.port dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.port dt::before,.consul-upstream-instance-list li>.detail dl.port dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.port dt::before{--icon-name:icon-port;content:""}@keyframes icon-protocol{100%{-webkit-mask-image:var(--icon-protocol-16);mask-image:var(--icon-protocol-16);background-color:var(--icon-color,var(--color-protocol-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.protocol dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.protocol dt::before,.consul-upstream-instance-list li>.detail dl.protocol dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.protocol dt::before{--icon-name:icon-protocol;content:""}@keyframes icon-redirect{100%{-webkit-mask-image:var(--icon-redirect-16);mask-image:var(--icon-redirect-16);background-color:var(--icon-color,var(--color-redirect-500,currentColor))}}@keyframes icon-search-color{100%{background-image:var(--icon-search-color-16)}}[for=toolbar-toggle]{--icon-name:icon-search-color;content:""}@keyframes icon-sort{100%{-webkit-mask-image:var(--icon-sort-desc-16);mask-image:var(--icon-sort-desc-16);background-color:var(--icon-color,var(--color-sort-500,currentColor))}}.type-sort.popover-select label>::before{--icon-name:icon-sort;content:""}@keyframes icon-union{100%{-webkit-mask-image:var(--icon-union-16);mask-image:var(--icon-union-16);background-color:var(--icon-color,var(--color-union-500,currentColor))}}#downstream-container .topology-metrics-card .details .group span::before,#upstream-container .topology-metrics-card .details .group span::before{--icon-name:icon-union;content:""}.ember-basic-dropdown{position:relative}.ember-basic-dropdown,.ember-basic-dropdown-content,.ember-basic-dropdown-content *{box-sizing:border-box}.ember-basic-dropdown-content{position:absolute;width:auto;z-index:1000;background-color:#fff}.ember-basic-dropdown-content--left{left:0}.ember-basic-dropdown-content--right{right:0}.ember-basic-dropdown-overlay{position:fixed;background:rgba(0,0,0,.5);width:100%;height:100%;z-index:10;top:0;left:0;pointer-events:none}.ember-basic-dropdown-content-wormhole-origin{display:inline}.ember-power-select-dropdown *{box-sizing:border-box}.ember-power-select-trigger{position:relative;border-radius:4px;background-color:#fff;line-height:1.75;overflow-x:hidden;text-overflow:ellipsis;min-height:1.75em;-moz-user-select:none;user-select:none;-webkit-user-select:none;color:inherit}.ember-power-select-trigger:after{content:"";display:table;clear:both}.ember-power-select-trigger--active,.ember-power-select-trigger:focus{box-shadow:none}.ember-basic-dropdown-trigger--below.ember-power-select-trigger[aria-expanded=true],.ember-basic-dropdown-trigger--in-place.ember-power-select-trigger[aria-expanded=true]{border-bottom-left-radius:0;border-bottom-right-radius:0}.ember-basic-dropdown-trigger--above.ember-power-select-trigger[aria-expanded=true]{border-top-left-radius:0;border-top-right-radius:0}.ember-power-select-placeholder{color:#999;display:block;overflow-x:hidden;white-space:nowrap;text-overflow:ellipsis}.ember-power-select-status-icon{position:absolute;display:inline-block;width:0;height:0;top:0;bottom:0;margin:auto;border-style:solid;border-width:7px 4px 0;border-color:#aaa transparent transparent;right:5px}.ember-basic-dropdown-trigger[aria-expanded=true] .ember-power-select-status-icon{transform:rotate(180deg)}.ember-power-select-clear-btn{position:absolute;cursor:pointer;right:25px}.ember-power-select-trigger-multiple-input{font-family:inherit;font-size:inherit;border:none;display:inline-block;line-height:inherit;-webkit-appearance:none;outline:0;padding:0;float:left;background-color:transparent;text-indent:2px}.ember-power-select-trigger-multiple-input:disabled{background-color:#eee}.ember-power-select-trigger-multiple-input::placeholder{opacity:1;color:#999}.ember-power-select-trigger-multiple-input::-webkit-input-placeholder{opacity:1;color:#999}.ember-power-select-trigger-multiple-input::-moz-placeholder{opacity:1;color:#999}.ember-power-select-trigger-multiple-input::-ms-input-placeholder{opacity:1;color:#999}.active.discovery-chain [id*=":"],.discovery-chain path,.ember-power-select-multiple-remove-btn:not(:hover){opacity:.5}.ember-power-select-multiple-options{padding:0;margin:0}.ember-power-select-multiple-option{border:1px solid gray;border-radius:4px;color:#333;background-color:#e4e4e4;padding:0 4px;display:inline-block;line-height:1.45;float:left;margin:2px 0 2px 3px}.ember-power-select-multiple-remove-btn{cursor:pointer}.ember-power-select-search{padding:4px}.ember-power-select-search-input{border:1px solid #aaa;border-radius:0;width:100%;font-size:inherit;line-height:inherit;padding:0 5px}.ember-power-select-search-input:focus{border:1px solid #aaa;box-shadow:none}.ember-power-select-dropdown{border-left:1px solid #aaa;border-right:1px solid #aaa;line-height:1.75;border-radius:4px;box-shadow:none;overflow:hidden;color:inherit}.ember-power-select-dropdown.ember-basic-dropdown-content--above{border-top:1px solid #aaa;border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.ember-power-select-dropdown.ember-basic-dropdown-content--below,.ember-power-select-dropdown.ember-basic-dropdown-content--in-place{border-top:none;border-bottom:1px solid #aaa;border-top-left-radius:0;border-top-right-radius:0}.ember-power-select-dropdown.ember-basic-dropdown-content--in-place{width:100%}.ember-power-select-options{list-style:none;margin:0;padding:0;-moz-user-select:none;user-select:none;-webkit-user-select:none}.ember-power-select-placeholder,.ember-power-select-selected-item,a[rel*=external]::after{margin-left:8px}.ember-power-select-options[role=listbox]{overflow-y:auto;-webkit-overflow-scrolling:touch;max-height:12.25em}.ember-power-select-option{cursor:pointer;padding:0 8px}.ember-power-select-group[aria-disabled=true]{color:#999;cursor:not-allowed}.ember-power-select-group[aria-disabled=true] .ember-power-select-option,.ember-power-select-option[aria-disabled=true]{color:#999;pointer-events:none;cursor:not-allowed}.ember-power-select-option[aria-selected=true]{background-color:#ddd}.ember-power-select-option[aria-current=true]{background-color:#5897fb;color:#fff}.ember-power-select-group-name{cursor:default;font-weight:700}.ember-power-select-trigger[aria-disabled=true]{background-color:#eee}.ember-power-select-trigger{padding:0 16px 0 0}.ember-power-select-group .ember-power-select-group .ember-power-select-group-name{padding-left:24px}.ember-power-select-group .ember-power-select-group .ember-power-select-option{padding-left:40px}.ember-power-select-group .ember-power-select-option{padding-left:24px}.ember-power-select-group .ember-power-select-group-name{padding-left:8px}.ember-power-select-trigger[dir=rtl]{padding:0 0 0 16px}.ember-power-select-trigger[dir=rtl] .ember-power-select-placeholder,.ember-power-select-trigger[dir=rtl] .ember-power-select-selected-item{margin-right:8px}.ember-power-select-trigger[dir=rtl] .ember-power-select-multiple-option,.ember-power-select-trigger[dir=rtl] .ember-power-select-trigger-multiple-input{float:right}.ember-power-select-trigger[dir=rtl] .ember-power-select-status-icon{left:5px;right:initial}.ember-power-select-trigger[dir=rtl] .ember-power-select-clear-btn{left:25px;right:initial}.ember-power-select-dropdown[dir=rtl] .ember-power-select-group .ember-power-select-group .ember-power-select-group-name{padding-right:24px}.ember-power-select-dropdown[dir=rtl] .ember-power-select-group .ember-power-select-group .ember-power-select-option{padding-right:40px}.ember-power-select-dropdown[dir=rtl] .ember-power-select-group .ember-power-select-option{padding-right:24px}.ember-power-select-dropdown[dir=rtl] .ember-power-select-group .ember-power-select-group-name{padding-right:8px}#login-toggle+div footer button:focus,#login-toggle+div footer button:hover,.consul-intention-fieldsets .permissions>button:focus,.consul-intention-fieldsets .permissions>button:hover,.empty-state>ul>li>:focus,.empty-state>ul>li>:hover,.empty-state>ul>li>label>button:focus,.empty-state>ul>li>label>button:hover,.modal-dialog [role=document] dd a:focus,.modal-dialog [role=document] dd a:hover,.modal-dialog [role=document] p a:focus,.modal-dialog [role=document] p a:hover,.oidc-select button.reset:focus,.oidc-select button.reset:hover,.search-bar-status .remove-all button:focus,.search-bar-status .remove-all button:hover,main dd a:focus,main dd a:hover,main p a:focus,main p a:hover{text-decoration:underline}#login-toggle+div footer button,.consul-intention-fieldsets .permissions>button,.empty-state>ul>li>*,.empty-state>ul>li>:active,.empty-state>ul>li>:focus,.empty-state>ul>li>:hover,.empty-state>ul>li>label>button,.empty-state>ul>li>label>button:active,.empty-state>ul>li>label>button:focus,.empty-state>ul>li>label>button:hover,.modal-dialog [role=document] dd a,.modal-dialog [role=document] p a,.oidc-select button.reset,.search-bar-status .remove-all button,main dd a,main dd a:active,main dd a:focus,main dd a:hover,main p a,main p a:active,main p a:focus,main p a:hover{color:var(--token-color-foreground-action)}.modal-dialog [role=document] label a[rel*=help],div.with-confirmation p,main label a[rel*=help]{color:var(--token-color-foreground-disabled)}#login-toggle+div footer button,.consul-intention-fieldsets .permissions>button,.empty-state>ul>li>*,.empty-state>ul>li>label>button,.modal-dialog [role=document] dd a,.modal-dialog [role=document] p a,.oidc-select button.reset,.search-bar-status .remove-all button,main dd a,main p a{cursor:pointer;background-color:transparent}#login-toggle+div footer button:active,.consul-intention-fieldsets .permissions>button:active,.empty-state>ul>li>:active,.empty-state>ul>li>label>button:active,.modal-dialog [role=document] dd a:active,.modal-dialog [role=document] p a:active,.oidc-select button.reset:active,.search-bar-status .remove-all button:active,main dd a:active,main p a:active{outline:0}.modal-dialog [role=document] a[rel*=help]::after,main a[rel*=help]::after{opacity:.4}.modal-dialog [role=document] h2 a,main h2 a{color:var(--token-color-foreground-strong)}.auth-form em,.empty-state,main header nav:first-child ol li a,main header nav:first-child ol li:not(:first-child) a::before{color:var(--token-color-foreground-faint)}.modal-dialog [role=document] h2 a[rel*=help]::after,main h2 a[rel*=help]::after{font-size:.65em;margin-top:.2em;margin-left:.2em}.tab-section>p:only-child [rel*=help]::after{content:none}.auth-form{width:320px;margin:-20px 25px 0}.auth-form em{font-style:normal;display:inline-block;margin-top:1em}.auth-form .oidc-select,.auth-form form{padding-top:1em}.auth-form form{margin-bottom:0!important}.auth-form .ember-basic-dropdown-trigger,.auth-form button:not(.reset){width:100%}.auth-form .progress{margin:0 auto}#login-toggle+div footer button::after{font-size:120%;position:relative;top:-1px;left:-3px}#login-toggle+div footer{border-top:0;background-color:transparent;padding:10px 42px 20px}#login-toggle+div>div>div>div{padding-bottom:0}main header nav:first-child ol li a{text-decoration:none}main header nav:first-child ol li a:hover{color:var(--token-color-foreground-action);text-decoration:underline}main header nav:first-child ol li a::before{text-decoration:none}main header nav:first-child ol{display:grid;grid-auto-flow:column;white-space:nowrap;overflow:hidden}main header nav:first-child ol>li{list-style-type:none;display:inline-flex;overflow:hidden}main header nav:first-child ol li:first-child a::before{background-color:var(--token-color-foreground-faint);margin-right:4px;display:inline-block}main header nav:first-child ol li:not(:first-child) a{margin-left:6px;overflow:hidden;text-overflow:ellipsis}main header nav:first-child ol li:not(:first-child) a::before{content:"/";margin-right:8px;display:inline-block}main header nav:first-child{position:absolute;top:12px}.consul-intention-action-warn-modal button.dangerous,.copy-button button,.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.informed-action>ul>li>*,.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-select label>*,.topology-notices button,.type-sort.popover-select label>*,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{cursor:pointer;white-space:nowrap;text-decoration:none}.consul-intention-action-warn-modal button.dangerous:disabled,.copy-button button:disabled,.disclosure-menu [aria-expanded]~*>ul>[role=treeitem]:disabled,.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem]:disabled,.disclosure-menu [aria-expanded]~*>ul>li>[role=option]:disabled,.informed-action>ul>li>:disabled,.menu-panel>ul>[role=treeitem]:disabled,.menu-panel>ul>li>[role=menuitem]:disabled,.menu-panel>ul>li>[role=option]:disabled,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]:disabled,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]:disabled,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option]:disabled,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]:disabled,.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]:disabled,.popover-menu>[type=checkbox]+label+div>ul>li>[role=option]:disabled,.popover-select label>:disabled,.topology-notices button:disabled,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]:disabled,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]:disabled,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]:disabled,table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]:disabled,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]:disabled,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]:disabled{cursor:default;box-shadow:none}.checkbox-group label,.more-popover-menu>[type=checkbox]~label,.popover-menu>[type=checkbox]~label,html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label,table.has-actions tr>.actions>[type=checkbox]~label,table.with-details tr>.actions>[type=checkbox]~label{cursor:pointer}.consul-intention-action-warn-modal button.dangerous{border-width:1px;border-radius:var(--decor-radius-100);box-shadow:var(--token-elevation-high-box-shadow)}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.informed-action>ul>li>*,.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{color:var(--token-color-foreground-strong);background-color:var(--token-color-surface-primary)}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem]:focus,.disclosure-menu [aria-expanded]~*>ul>[role=treeitem]:hover,.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem]:focus,.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem]:hover,.disclosure-menu [aria-expanded]~*>ul>li>[role=option]:focus,.disclosure-menu [aria-expanded]~*>ul>li>[role=option]:hover,.informed-action>ul>li>:focus,.informed-action>ul>li>:hover,.menu-panel>ul>[role=treeitem]:focus,.menu-panel>ul>[role=treeitem]:hover,.menu-panel>ul>li>[role=menuitem]:focus,.menu-panel>ul>li>[role=menuitem]:hover,.menu-panel>ul>li>[role=option]:focus,.menu-panel>ul>li>[role=option]:hover,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]:focus,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]:hover,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]:focus,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]:hover,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option]:focus,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option]:hover,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]:focus,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]:hover,.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]:focus,.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]:hover,.popover-menu>[type=checkbox]+label+div>ul>li>[role=option]:focus,.popover-menu>[type=checkbox]+label+div>ul>li>[role=option]:hover,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]:focus,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]:hover,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]:focus,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]:hover,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]:focus,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]:hover,table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]:focus,table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]:hover,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]:focus,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]:hover,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]:focus,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]:hover{background-color:var(--token-color-surface-strong)}.type-sort.popover-select label>::before{position:relative;width:16px;height:16px}.type-sort.popover-select label>::after{top:0!important}.consul-intention-action-warn-modal button.dangerous,.copy-button button,.popover-select label>*,.topology-notices button,.type-sort.popover-select label>*{position:relative}.consul-intention-action-warn-modal button.dangerous .progress.indeterminate,.copy-button button .progress.indeterminate,.popover-select label>* .progress.indeterminate,.topology-notices button .progress.indeterminate{position:absolute;top:50%;left:50%;margin-left:-12px;margin-top:-12px}.consul-intention-action-warn-modal button.dangerous:disabled .progress+*,.copy-button button:disabled .progress+*,.popover-select label>:disabled .progress+*,.topology-notices button:disabled .progress+*{visibility:hidden}.consul-intention-action-warn-modal button.dangerous:empty,.copy-button button:empty,.popover-select label>:empty,.topology-notices button:empty{padding-right:0!important;padding-left:18px!important;margin-right:5px}.consul-intention-action-warn-modal button.dangerous:empty::before,.copy-button button:empty::before,.popover-select label>:empty::before,.topology-notices button:empty::before{left:1px}.consul-intention-action-warn-modal button.dangerous:not(:empty),.copy-button button:not(:empty),.popover-select label>:not(:empty),.topology-notices button:not(:empty){display:inline-flex;text-align:center;justify-content:center;align-items:center;padding:calc(.5em - 1px) calc(2.2em - 1px);min-width:100px}.consul-intention-action-warn-modal button.dangerous:not(:last-child),.copy-button button:not(:last-child),.popover-select label>:not(:last-child),.topology-notices button:not(:last-child){margin-right:8px}.app-view>header .actions a{padding-top:calc(.4em - 1px)!important;padding-bottom:calc(.4em - 1px)!important}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.informed-action>ul>li>*,.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{padding:.9em 1em;text-align:center;display:inline-block;box-sizing:border-box}.type-sort.popover-select label>*{height:35px!important}.discovery-chain .resolver-card,.discovery-chain .route-card,.discovery-chain .splitter-card{border:var(--decor-border-100);border-radius:var(--decor-radius-100);background-color:var(--token-color-surface-faint);display:block;position:relative}.discovery-chain .resolver-card>section,.discovery-chain .resolver-card>ul>li,.discovery-chain .route-card>section,.discovery-chain .route-card>ul>li,.discovery-chain .splitter-card>section,.discovery-chain .splitter-card>ul>li{border-top:var(--decor-border-100)}.discovery-chain .resolver-card,.discovery-chain .resolver-card>section,.discovery-chain .resolver-card>ul>li,.discovery-chain .route-card,.discovery-chain .route-card>section,.discovery-chain .route-card>ul>li,.discovery-chain .splitter-card,.discovery-chain .splitter-card>section,.discovery-chain .splitter-card>ul>li{border-color:var(--token-color-surface-interactive-active)}.discovery-chain .resolver-card:focus,.discovery-chain .resolver-card:hover,.discovery-chain .route-card:focus,.discovery-chain .route-card:hover,.discovery-chain .splitter-card:focus,.discovery-chain .splitter-card:hover{box-shadow:var(--token-surface-mid-box-shadow)}.discovery-chain .resolver-card>header,.discovery-chain .route-card>header,.discovery-chain .splitter-card>header{padding:10px}.discovery-chain .resolver-card>section,.discovery-chain .resolver-card>ul>li,.discovery-chain .route-card>section,.discovery-chain .route-card>ul>li,.discovery-chain .splitter-card>section,.discovery-chain .splitter-card>ul>li{padding:5px 10px}.discovery-chain .resolver-card ul,.discovery-chain .route-card ul,.discovery-chain .splitter-card ul{list-style-type:none;margin:0;padding:0}.checkbox-group label{margin-right:10px;white-space:nowrap}.checkbox-group span{display:inline-block;margin-left:10px;min-width:50px}.CodeMirror{max-width:1260px;min-height:300px;height:auto;padding-bottom:20px}.CodeMirror-scroll{overflow-x:hidden!important}.CodeMirror-lint-tooltip{background-color:#f9f9fa;border:1px solid var(--syntax-light-gray);border-radius:0;color:#212121;padding:7px 8px 9px}.cm-s-hashi.CodeMirror{width:100%;background-color:var(--token-color-hashicorp-brand)!important;color:#cfd2d1!important;border:none;font-family:var(--token-typography-font-stack-code);-webkit-font-smoothing:auto;line-height:1.4}.cm-s-hashi .CodeMirror-gutters{color:var(--syntax-dark-grey);background-color:var(--syntax-gutter-grey);border:none}.cm-s-hashi .CodeMirror-cursor{border-left:solid thin #f8f8f0}.cm-s-hashi .CodeMirror-linenumber{color:#6d8a88}.cm-s-hashi.CodeMirror-focused div.CodeMirror-selected{background:#214283}.cm-s-hashi .CodeMirror-line::selection,.cm-s-hashi .CodeMirror-line>span::selection,.cm-s-hashi .CodeMirror-line>span>span::selection{background:#214283}.cm-s-hashi .CodeMirror-line::-moz-selection,.cm-s-hashi .CodeMirror-line>span::-moz-selection,.cm-s-hashi .CodeMirror-line>span>span::-moz-selection{background:var(--token-color-surface-interactive)}.cm-s-hashi span.cm-comment{color:var(--syntax-light-grey)}.cm-s-hashi span.cm-string,.cm-s-hashi span.cm-string-2{color:var(--syntax-packer)}.cm-s-hashi span.cm-number{color:var(--syntax-serf)}.cm-s-hashi span.cm-variable,.cm-s-hashi span.cm-variable-2{color:#9e84c5}.cm-s-hashi span.cm-def{color:var(--syntax-packer)}.cm-s-hashi span.cm-operator{color:var(--syntax-gray)}.cm-s-hashi span.cm-keyword{color:var(--syntax-yellow)}.cm-s-hashi span.cm-atom{color:var(--syntax-serf)}.cm-s-hashi span.cm-meta,.cm-s-hashi span.cm-tag{color:var(--syntax-packer)}.cm-s-hashi span.cm-error{color:var(--syntax-red)}.cm-s-hashi span.cm-attribute,.cm-s-hashi span.cm-qualifier{color:#9fca56}.cm-s-hashi span.cm-property{color:#9e84c5}.cm-s-hashi span.cm-builtin,.cm-s-hashi span.cm-variable-3{color:#9fca56}.cm-s-hashi .CodeMirror-activeline-background{background:#101213}.cm-s-hashi .CodeMirror-matchingbracket{text-decoration:underline;color:var(--token-color-surface-primary)!important}.readonly-codemirror .cm-s-hashi span{color:var(--syntax-light-grey)}.readonly-codemirror .cm-s-hashi span.cm-string,.readonly-codemirror .cm-s-hashi span.cm-string-2{color:var(--syntax-faded-gray)}.readonly-codemirror .cm-s-hashi span.cm-number{color:#a3acbc}.readonly-codemirror .cm-s-hashi span.cm-property,.tippy-box[data-theme~=tooltip]{color:var(--token-color-surface-primary)}.readonly-codemirror .cm-s-hashi span.cm-variable-2{color:var(--syntax-light-grey-blue)}.code-editor .toolbar-container{background:var(--token-color-surface-strong);background:linear-gradient(180deg,var(--token-color-surface-strong) 50%,var(--token-color-surface-interactive-active) 100%);border:1px solid var(--token-color-surface-interactive-active);border-bottom-color:var(--token-color-foreground-faint);border-top-color:var(--token-color-foreground-disabled)}.code-editor .toolbar-container .toolbar .title{color:var(--token-color-foreground-strong);padding:0 8px}.code-editor .toolbar-container .toolbar .toolbar-separator{border-right:1px solid var(--token-color-palette-neutral-300)}.code-editor .toolbar-container .ember-power-select-trigger{background-color:var(--token-color-surface-primary);color:var(--token-color-hashicorp-brand);border-radius:var(--decor-radius-100);border:var(--decor-border-100);border-color:var(--token-color-foreground-faint)}.code-editor{display:block;border:10px;overflow:hidden;position:relative;clear:both}.code-editor::after{position:absolute;bottom:0;width:100%;height:25px;background-color:var(--token-color-hashicorp-brand);content:"";display:block}.code-editor>pre{display:none}.code-editor .toolbar-container,.code-editor .toolbar-container .toolbar{align-items:center;justify-content:space-between;display:flex}.code-editor .toolbar-container{position:relative;margin-top:4px;height:44px}.code-editor .toolbar-container .toolbar{flex:1;white-space:nowrap}.code-editor .toolbar-container .toolbar .toolbar-separator{height:32px;margin:0 4px;width:0}.code-editor .toolbar-container .toolbar .tools{display:flex;flex-direction:row;margin:0 10px;align-items:center}.code-editor .toolbar-container .toolbar .tools .copy-button{margin-left:10px}.code-editor .toolbar-container .ember-basic-dropdown-trigger{margin:0 8px;width:120px;height:32px;display:flex;align-items:center;flex-direction:row}.consul-exposed-path-list>ul>li,.consul-lock-session-list ul>li:not(:first-child),.consul-upstream-instance-list li,.list-collection>ul>li:not(:first-child){display:grid;grid-template-columns:1fr auto;grid-template-rows:50% 50%;grid-template-areas:"header actions" "detail actions"}.consul-exposed-path-list>ul>li>.header,.consul-lock-session-list ul>li:not(:first-child)>.header,.consul-upstream-instance-list li>.header,.list-collection>ul>li:not(:first-child)>.header{grid-area:header;align-self:start}.consul-exposed-path-list>ul>li>.detail,.consul-lock-session-list ul>li:not(:first-child)>.detail,.consul-upstream-instance-list li>.detail,.list-collection>ul>li:not(:first-child)>.detail{grid-area:detail;align-self:end}.consul-exposed-path-list>ul>li>.detail *,.consul-lock-session-list ul>li:not(:first-child)>.detail *,.consul-upstream-instance-list li>.detail *,.list-collection>ul>li:not(:first-child)>.detail *{flex-wrap:nowrap!important}.consul-exposed-path-list>ul>li>.actions,.consul-lock-session-list ul>li:not(:first-child)>.actions,.consul-upstream-instance-list li>.actions,.list-collection>ul>li:not(:first-child)>.actions{grid-area:actions;display:inline-flex}.consul-nspace-list>ul>li:not(:first-child) dt,.consul-policy-list>ul li:not(:first-child) dl:not(.datacenter) dt,.consul-role-list>ul>li:not(:first-child) dt,.consul-service-instance-list .port dt,.consul-service-instance-list .port dt::before,.consul-token-list>ul>li:not(:first-child) dt{display:none}.consul-exposed-path-list>ul>li>.header:nth-last-child(2),.consul-lock-session-list ul>li:not(:first-child)>.header:nth-last-child(2),.consul-upstream-instance-list li>.header:nth-last-child(2),.list-collection>ul>li:not(:first-child)>.header:nth-last-child(2){grid-column-start:header;grid-column-end:actions}.consul-exposed-path-list>ul>li>.detail:last-child,.consul-lock-session-list ul>li:not(:first-child)>.detail:last-child,.consul-upstream-instance-list li>.detail:last-child,.list-collection>ul>li:not(:first-child)>.detail:last-child{grid-column-start:detail;grid-column-end:actions}.consul-nspace-list>ul>li:not(:first-child) dt+dd,.consul-policy-list>ul li:not(:first-child) dl:not(.datacenter) dt+dd,.consul-role-list>ul>li:not(:first-child) dt+dd,.consul-token-list>ul>li:not(:first-child) dt+dd{margin-left:0!important}.consul-policy-list dl.datacenter dt,.consul-service-list li>div:first-child>dl:first-child dd{margin-top:1px}.consul-service-instance-list .detail,.consul-service-list .detail{overflow-x:visible!important}.consul-intention-permission-list>ul{border-top:1px solid var(--token-color-surface-interactive-active)}.consul-service-instance-list .port .copy-button{margin-right:0}.consul-exposed-path-list>ul>li .copy-button,.consul-lock-session-list ul>li:not(:first-child) .copy-button,.consul-upstream-instance-list li .copy-button,.list-collection>ul>li:not(:first-child) .copy-button{display:inline-flex}.consul-exposed-path-list>ul>li>.header .copy-button,.consul-lock-session-list ul>li:not(:first-child)>.header .copy-button,.consul-upstream-instance-list li>.header .copy-button,.list-collection>ul>li:not(:first-child)>.header .copy-button{margin-left:4px}.consul-exposed-path-list>ul>li>.detail .copy-button,.consul-lock-session-list ul>li:not(:first-child)>.detail .copy-button,.consul-upstream-instance-list li>.detail .copy-button,.list-collection>ul>li:not(:first-child)>.detail .copy-button{margin-top:2px}.consul-exposed-path-list>ul>li .copy-button button,.consul-lock-session-list ul>li:not(:first-child) .copy-button button,.consul-upstream-instance-list li .copy-button button,.list-collection>ul>li:not(:first-child) .copy-button button{padding:0!important;margin:0!important}.consul-exposed-path-list>ul>li>.header .copy-button button,.consul-lock-session-list ul>li:not(:first-child)>.header .copy-button button,.consul-upstream-instance-list li>.header .copy-button button,.list-collection>ul>li:not(:first-child)>.header .copy-button button{display:none}.consul-exposed-path-list>ul>li>.header:hover .copy-button button,.consul-lock-session-list ul>li:not(:first-child)>.header:hover .copy-button button,.consul-upstream-instance-list li>.header:hover .copy-button button,.list-collection>ul>li:not(:first-child)>.header:hover .copy-button button{display:block}.consul-exposed-path-list>ul>li .copy-button button:hover,.consul-lock-session-list ul>li:not(:first-child) .copy-button button:hover,.consul-upstream-instance-list li .copy-button button:hover,.list-collection>ul>li:not(:first-child) .copy-button button:hover{background-color:transparent!important}.consul-exposed-path-list>ul>li>.detail>.consul-external-source:first-child,.consul-exposed-path-list>ul>li>.detail>.consul-kind:first-child,.consul-lock-session-list ul>li:not(:first-child)>.detail>.consul-external-source:first-child,.consul-lock-session-list ul>li:not(:first-child)>.detail>.consul-kind:first-child,.consul-upstream-instance-list li>.detail>.consul-external-source:first-child,.consul-upstream-instance-list li>.detail>.consul-kind:first-child,.list-collection>ul>li:not(:first-child)>.detail>.consul-external-source:first-child,.list-collection>ul>li:not(:first-child)>.detail>.consul-kind:first-child{margin-left:-5px}.consul-exposed-path-list>ul>li>.detail .policy-management::before,.consul-exposed-path-list>ul>li>.detail .policy::before,.consul-exposed-path-list>ul>li>.detail .role::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .policy-management::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .policy::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .role::before,.consul-upstream-instance-list li>.detail .policy-management::before,.consul-upstream-instance-list li>.detail .policy::before,.consul-upstream-instance-list li>.detail .role::before,.list-collection>ul>li:not(:first-child)>.detail .policy-management::before,.list-collection>ul>li:not(:first-child)>.detail .policy::before,.list-collection>ul>li:not(:first-child)>.detail .role::before{margin-right:3px}table div.with-confirmation.confirming{background-color:var(--token-color-surface-primary)}div.with-confirmation p{margin-right:12px;padding-left:12px;margin-bottom:0!important}div.with-confirmation{justify-content:end;width:100%;display:flex;align-items:center}table td>div.with-confirmation.confirming{position:absolute;right:0}@media (max-width:420px){div.with-confirmation{float:none;margin-top:1em;display:block}div.with-confirmation p{margin-bottom:1em}}.copy-button button{color:var(--token-color-foreground-action);--icon-color:transparent;min-height:17px}.copy-button button::after{--icon-color:var(--token-color-surface-strong)}.copy-button button:focus,.copy-button button:hover:not(:disabled):not(:active){color:var(--token-color-foreground-action);--icon-color:var(--token-color-surface-strong)}.copy-button button:hover::before{--icon-color:var(--token-color-foreground-action)}.copy-button button:active{--icon-color:var(--token-color-surface-interactive-active)}.copy-button button:empty{padding:0!important;margin-right:0;top:-1px}.copy-button button:empty::after{content:"";display:none;position:absolute;top:-2px;left:-3px;width:20px;height:22px}.copy-button button:empty:hover::after{display:block}.copy-button button:empty::before{position:relative;z-index:1}.copy-button button:not(:empty)::before{margin-right:4px}.consul-bucket-list .copy-button,.consul-exposed-path-list>ul>li>.detail dl .copy-button,.consul-instance-checks .copy-button,.consul-lock-session-list dl .copy-button,.consul-lock-session-list ul>li:not(:first-child)>.detail dl .copy-button,.consul-upstream-instance-list dl .copy-button,.list-collection>ul>li:not(:first-child)>.detail dl .copy-button,.tag-list .copy-button,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .copy-button,section[data-route="dc.show.license"] .validity dl .copy-button,td.tags .copy-button{margin-top:0!important}.consul-bucket-list .copy-btn,.consul-exposed-path-list>ul>li>.detail dl .copy-btn,.consul-instance-checks .copy-btn,.consul-lock-session-list dl .copy-btn,.consul-lock-session-list ul>li:not(:first-child)>.detail dl .copy-btn,.consul-upstream-instance-list dl .copy-btn,.list-collection>ul>li:not(:first-child)>.detail dl .copy-btn,.tag-list .copy-btn,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .copy-btn,section[data-route="dc.show.license"] .validity dl .copy-btn,td.tags .copy-btn{top:0!important}.consul-bucket-list .copy-btn:empty::before,.consul-exposed-path-list>ul>li>.detail dl .copy-btn:empty::before,.consul-instance-checks .copy-btn:empty::before,.consul-lock-session-list dl .copy-btn:empty::before,.consul-upstream-instance-list dl .copy-btn:empty::before,.list-collection>ul>li:not(:first-child)>.detail dl .copy-btn:empty::before,.tag-list .copy-btn:empty::before,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .copy-btn:empty::before,section[data-route="dc.show.license"] .validity dl .copy-btn:empty::before,td.tags .copy-btn:empty::before{left:0!important}.definition-table>dl{display:grid;grid-template-columns:140px auto;grid-gap:.4em 20px;margin-bottom:1.4em}.disclosure-menu{position:relative}.disclosure-menu [aria-expanded]~*{overflow-y:auto!important;will-change:scrollPosition}.more-popover-menu>[type=checkbox],.more-popover-menu>[type=checkbox]~:not(.animating):not(label),.popover-menu>[type=checkbox],.popover-menu>[type=checkbox]~:not(.animating):not(label),table.has-actions tr>.actions>[type=checkbox],table.has-actions tr>.actions>[type=checkbox]~:not(.animating):not(label),table.with-details tr>.actions>[type=checkbox],table.with-details tr>.actions>[type=checkbox]~:not(.animating):not(label){display:none}.more-popover-menu>[type=checkbox]:checked~:not(label),.popover-menu>[type=checkbox]:checked~:not(label),table.has-actions tr>.actions>[type=checkbox]:checked~:not(label),table.with-details tr>.actions>[type=checkbox]:checked~:not(label){display:block}table.dom-recycling{position:relative}table.dom-recycling tr>*{overflow:hidden}.list-collection-scroll-virtual>ul,table.dom-recycling tbody{overflow-x:hidden!important}table.dom-recycling dd{flex-wrap:nowrap}table.dom-recycling dd>*{margin-bottom:0}.empty-state,.empty-state>div{display:flex;flex-direction:column}.empty-state header :first-child{padding:0;margin:0}.empty-state{margin-top:0!important;padding-bottom:2.8em;background-color:var(--token-color-surface-faint)}.empty-state>*{width:370px;margin:0 auto}.empty-state button{margin:0 auto;display:inline}.empty-state header :first-child{margin-bottom:-3px;border-bottom:none}.empty-state header{margin-top:1.8em;margin-bottom:.5em}.empty-state>ul{display:flex;justify-content:space-between;margin-top:1em}.empty-state>ul>li>*,.empty-state>ul>li>label>button{display:inline-flex;align-items:center}.empty-state>div:only-child{padding:50px 0 10px;text-align:center}.empty-state header::before{font-size:2.6em;position:relative;top:-3px;float:left;margin-right:10px}.oidc-select button.reset,.type-dialog{float:right}.empty-state>ul>li>::before,.empty-state>ul>li>label>button::before{margin-top:-1px;margin-right:.5em}.empty-state li[class*=-link]>::after{margin-left:5px}html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup]{border:var(--decor-border-100);border-color:var(--token-color-palette-neutral-300);border-radius:var(--decor-radius-100)}html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] input[type=radio]:checked+*,html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] input[type=radio]:focus+*,html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] input[type=radio]:hover+*{box-shadow:var(--token-elevation-high-box-shadow);background-color:var(--token-color-surface-primary)}@media (min-width:996px){html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup]{display:flex}html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label{flex-grow:1}}html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] input[type=radio]{display:none}.app-view>div form:not(.filter-bar) [role=radiogroup] label,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea,.app-view>div form:not(.filter-bar) [role=radiogroup] label>em,.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.modal-dialog [role=document] .type-password,.modal-dialog [role=document] .type-password textarea,.modal-dialog [role=document] .type-password>em,.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select,.modal-dialog [role=document] .type-select textarea,.modal-dialog [role=document] .type-select>em,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text,.modal-dialog [role=document] .type-text textarea,.modal-dialog [role=document] .type-text>em,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label,.modal-dialog [role=document] [role=radiogroup] label textarea,.modal-dialog [role=document] [role=radiogroup] label>em,.modal-dialog [role=document] [role=radiogroup] label>span,.modal-dialog [role=document] form button+em,.oidc-select label,.oidc-select label textarea,.oidc-select label>em,.oidc-select label>span,.type-toggle,.type-toggle textarea,.type-toggle>em,.type-toggle>span,html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label,html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label span,main .type-password,main .type-password textarea,main .type-password>em,main .type-password>span,main .type-select,main .type-select textarea,main .type-select>em,main .type-select>span,main .type-text,main .type-text textarea,main .type-text>em,main .type-text>span,main form button+em,span.label{display:block}html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup],html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label,html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label span{height:100%}html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label span{padding:5px 14px}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password],.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text],.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea,.modal-dialog [role=document] .type-password [type=password],.modal-dialog [role=document] .type-password [type=text],.modal-dialog [role=document] .type-password textarea,.modal-dialog [role=document] .type-select [type=password],.modal-dialog [role=document] .type-select [type=text],.modal-dialog [role=document] .type-select textarea,.modal-dialog [role=document] .type-text [type=password],.modal-dialog [role=document] .type-text [type=text],.modal-dialog [role=document] .type-text textarea,.modal-dialog [role=document] [role=radiogroup] label [type=password],.modal-dialog [role=document] [role=radiogroup] label [type=text],.modal-dialog [role=document] [role=radiogroup] label textarea,.oidc-select label [type=password],.oidc-select label [type=text],.oidc-select label textarea,.type-toggle [type=password],.type-toggle [type=text],.type-toggle textarea,main .type-password [type=password],main .type-password [type=text],main .type-password textarea,main .type-select [type=password],main .type-select [type=text],main .type-select textarea,main .type-text [type=password],main .type-text [type=text],main .type-text textarea{-moz-appearance:none;-webkit-appearance:none;box-shadow:var(--token-surface-inset-box-shadow);border-radius:var(--decor-radius-100);border:var(--decor-border-100);outline:0}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]:-moz-read-only,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]:-moz-read-only,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea:-moz-read-only,.modal-dialog [role=document] .type-password [type=password]:-moz-read-only,.modal-dialog [role=document] .type-password [type=text]:-moz-read-only,.modal-dialog [role=document] .type-password textarea:-moz-read-only,.modal-dialog [role=document] .type-select [type=password]:-moz-read-only,.modal-dialog [role=document] .type-select [type=text]:-moz-read-only,.modal-dialog [role=document] .type-select textarea:-moz-read-only,.modal-dialog [role=document] .type-text [type=password]:-moz-read-only,.modal-dialog [role=document] .type-text [type=text]:-moz-read-only,.modal-dialog [role=document] .type-text textarea:-moz-read-only,.modal-dialog [role=document] [role=radiogroup] label [type=password]:-moz-read-only,.modal-dialog [role=document] [role=radiogroup] label [type=text]:-moz-read-only,.modal-dialog [role=document] [role=radiogroup] label textarea:-moz-read-only,.oidc-select label [type=password]:-moz-read-only,.oidc-select label [type=text]:-moz-read-only,.oidc-select label textarea:-moz-read-only,.type-toggle [type=password]:-moz-read-only,.type-toggle [type=text]:-moz-read-only,.type-toggle textarea:-moz-read-only,main .type-password [type=password]:-moz-read-only,main .type-password [type=text]:-moz-read-only,main .type-password textarea:-moz-read-only,main .type-select [type=password]:-moz-read-only,main .type-select [type=text]:-moz-read-only,main .type-select textarea:-moz-read-only,main .type-text [type=password]:-moz-read-only,main .type-text [type=text]:-moz-read-only,main .type-text textarea:-moz-read-only{cursor:not-allowed}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]:disabled,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]:read-only,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]:disabled,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]:read-only,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea:disabled,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea:read-only,.modal-dialog [role=document] .type-password [type=password]:disabled,.modal-dialog [role=document] .type-password [type=password]:read-only,.modal-dialog [role=document] .type-password [type=text]:disabled,.modal-dialog [role=document] .type-password [type=text]:read-only,.modal-dialog [role=document] .type-password textarea:disabled,.modal-dialog [role=document] .type-password textarea:read-only,.modal-dialog [role=document] .type-select [type=password]:disabled,.modal-dialog [role=document] .type-select [type=password]:read-only,.modal-dialog [role=document] .type-select [type=text]:disabled,.modal-dialog [role=document] .type-select [type=text]:read-only,.modal-dialog [role=document] .type-select textarea:disabled,.modal-dialog [role=document] .type-select textarea:read-only,.modal-dialog [role=document] .type-text [type=password]:disabled,.modal-dialog [role=document] .type-text [type=password]:read-only,.modal-dialog [role=document] .type-text [type=text]:disabled,.modal-dialog [role=document] .type-text [type=text]:read-only,.modal-dialog [role=document] .type-text textarea:disabled,.modal-dialog [role=document] .type-text textarea:read-only,.modal-dialog [role=document] [role=radiogroup] label [type=password]:disabled,.modal-dialog [role=document] [role=radiogroup] label [type=password]:read-only,.modal-dialog [role=document] [role=radiogroup] label [type=text]:disabled,.modal-dialog [role=document] [role=radiogroup] label [type=text]:read-only,.modal-dialog [role=document] [role=radiogroup] label textarea:disabled,.modal-dialog [role=document] [role=radiogroup] label textarea:read-only,.oidc-select label [type=password]:disabled,.oidc-select label [type=password]:read-only,.oidc-select label [type=text]:disabled,.oidc-select label [type=text]:read-only,.oidc-select label textarea:disabled,.oidc-select label textarea:read-only,.type-toggle [type=password]:disabled,.type-toggle [type=password]:read-only,.type-toggle [type=text]:disabled,.type-toggle [type=text]:read-only,.type-toggle textarea:disabled,.type-toggle textarea:read-only,main .type-password [type=password]:disabled,main .type-password [type=password]:read-only,main .type-password [type=text]:disabled,main .type-password [type=text]:read-only,main .type-password textarea:disabled,main .type-password textarea:read-only,main .type-select [type=password]:disabled,main .type-select [type=password]:read-only,main .type-select [type=text]:disabled,main .type-select [type=text]:read-only,main .type-select textarea:disabled,main .type-select textarea:read-only,main .type-text [type=password]:disabled,main .type-text [type=password]:read-only,main .type-text [type=text]:disabled,main .type-text [type=text]:read-only,main .type-text textarea:disabled,main .type-text textarea:read-only,textarea:disabled+.CodeMirror{cursor:not-allowed}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]::-moz-placeholder,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]::-moz-placeholder,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea::-moz-placeholder,.modal-dialog [role=document] .type-password [type=password]::-moz-placeholder,.modal-dialog [role=document] .type-password [type=text]::-moz-placeholder,.modal-dialog [role=document] .type-password textarea::-moz-placeholder,.modal-dialog [role=document] .type-select [type=password]::-moz-placeholder,.modal-dialog [role=document] .type-select [type=text]::-moz-placeholder,.modal-dialog [role=document] .type-select textarea::-moz-placeholder,.modal-dialog [role=document] .type-text [type=password]::-moz-placeholder,.modal-dialog [role=document] .type-text [type=text]::-moz-placeholder,.modal-dialog [role=document] .type-text textarea::-moz-placeholder,.modal-dialog [role=document] [role=radiogroup] label [type=password]::-moz-placeholder,.modal-dialog [role=document] [role=radiogroup] label [type=text]::-moz-placeholder,.modal-dialog [role=document] [role=radiogroup] label textarea::-moz-placeholder,.oidc-select label [type=password]::-moz-placeholder,.oidc-select label [type=text]::-moz-placeholder,.oidc-select label textarea::-moz-placeholder,.type-toggle [type=password]::-moz-placeholder,.type-toggle [type=text]::-moz-placeholder,.type-toggle textarea::-moz-placeholder,main .type-password [type=password]::-moz-placeholder,main .type-password [type=text]::-moz-placeholder,main .type-password textarea::-moz-placeholder,main .type-select [type=password]::-moz-placeholder,main .type-select [type=text]::-moz-placeholder,main .type-select textarea::-moz-placeholder,main .type-text [type=password]::-moz-placeholder,main .type-text [type=text]::-moz-placeholder,main .type-text textarea::-moz-placeholder{color:var(--token-color-foreground-disabled)}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]::placeholder,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]::placeholder,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea::placeholder,.app-view>div form:not(.filter-bar) [role=radiogroup] label>em,.modal-dialog [role=document] .type-password [type=password]::placeholder,.modal-dialog [role=document] .type-password [type=text]::placeholder,.modal-dialog [role=document] .type-password textarea::placeholder,.modal-dialog [role=document] .type-password>em,.modal-dialog [role=document] .type-select [type=password]::placeholder,.modal-dialog [role=document] .type-select [type=text]::placeholder,.modal-dialog [role=document] .type-select textarea::placeholder,.modal-dialog [role=document] .type-select>em,.modal-dialog [role=document] .type-text [type=password]::placeholder,.modal-dialog [role=document] .type-text [type=text]::placeholder,.modal-dialog [role=document] .type-text textarea::placeholder,.modal-dialog [role=document] .type-text>em,.modal-dialog [role=document] [role=radiogroup] label [type=password]::placeholder,.modal-dialog [role=document] [role=radiogroup] label [type=text]::placeholder,.modal-dialog [role=document] [role=radiogroup] label textarea::placeholder,.modal-dialog [role=document] [role=radiogroup] label>em,.modal-dialog [role=document] form button+em,.modal-dialog [role=document] form fieldset>p,.oidc-select label [type=password]::placeholder,.oidc-select label [type=text]::placeholder,.oidc-select label textarea::placeholder,.oidc-select label>em,.type-toggle [type=password]::placeholder,.type-toggle [type=text]::placeholder,.type-toggle textarea::placeholder,.type-toggle>em,main .type-password [type=password]::placeholder,main .type-password [type=text]::placeholder,main .type-password textarea::placeholder,main .type-password>em,main .type-select [type=password]::placeholder,main .type-select [type=text]::placeholder,main .type-select textarea::placeholder,main .type-select>em,main .type-text [type=password]::placeholder,main .type-text [type=text]::placeholder,main .type-text textarea::placeholder,main .type-text>em,main form button+em,main form fieldset>p{color:var(--token-color-foreground-disabled)}.has-error>input,.has-error>textarea{border-color:var(--decor-error,var(--token-color-foreground-critical))!important}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password],.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text],.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea,.modal-dialog [role=document] .type-password [type=password],.modal-dialog [role=document] .type-password [type=text],.modal-dialog [role=document] .type-password textarea,.modal-dialog [role=document] .type-select [type=password],.modal-dialog [role=document] .type-select [type=text],.modal-dialog [role=document] .type-select textarea,.modal-dialog [role=document] .type-text [type=password],.modal-dialog [role=document] .type-text [type=text],.modal-dialog [role=document] .type-text textarea,.modal-dialog [role=document] [role=radiogroup] label [type=password],.modal-dialog [role=document] [role=radiogroup] label [type=text],.modal-dialog [role=document] [role=radiogroup] label textarea,.oidc-select label [type=password],.oidc-select label [type=text],.oidc-select label textarea,.type-toggle [type=password],.type-toggle [type=text],.type-toggle textarea,main .type-password [type=password],main .type-password [type=text],main .type-password textarea,main .type-select [type=password],main .type-select [type=text],main .type-select textarea,main .type-text [type=password],main .type-text [type=text],main .type-text textarea{color:var(--token-color-foreground-faint);border-color:var(--token-color-palette-neutral-300)}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]:hover,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]:hover,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea:hover,.modal-dialog [role=document] .type-password [type=password]:hover,.modal-dialog [role=document] .type-password [type=text]:hover,.modal-dialog [role=document] .type-password textarea:hover,.modal-dialog [role=document] .type-select [type=password]:hover,.modal-dialog [role=document] .type-select [type=text]:hover,.modal-dialog [role=document] .type-select textarea:hover,.modal-dialog [role=document] .type-text [type=password]:hover,.modal-dialog [role=document] .type-text [type=text]:hover,.modal-dialog [role=document] .type-text textarea:hover,.modal-dialog [role=document] [role=radiogroup] label [type=password]:hover,.modal-dialog [role=document] [role=radiogroup] label [type=text]:hover,.modal-dialog [role=document] [role=radiogroup] label textarea:hover,.oidc-select label [type=password]:hover,.oidc-select label [type=text]:hover,.oidc-select label textarea:hover,.type-toggle [type=password]:hover,.type-toggle [type=text]:hover,.type-toggle textarea:hover,main .type-password [type=password]:hover,main .type-password [type=text]:hover,main .type-password textarea:hover,main .type-select [type=password]:hover,main .type-select [type=text]:hover,main .type-select textarea:hover,main .type-text [type=password]:hover,main .type-text [type=text]:hover,main .type-text textarea:hover{border-color:var(--token-color-foreground-faint)}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]:focus,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]:focus,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea:focus,.modal-dialog [role=document] .type-password [type=password]:focus,.modal-dialog [role=document] .type-password [type=text]:focus,.modal-dialog [role=document] .type-password textarea:focus,.modal-dialog [role=document] .type-select [type=password]:focus,.modal-dialog [role=document] .type-select [type=text]:focus,.modal-dialog [role=document] .type-select textarea:focus,.modal-dialog [role=document] .type-text [type=password]:focus,.modal-dialog [role=document] .type-text [type=text]:focus,.modal-dialog [role=document] .type-text textarea:focus,.modal-dialog [role=document] [role=radiogroup] label [type=password]:focus,.modal-dialog [role=document] [role=radiogroup] label [type=text]:focus,.modal-dialog [role=document] [role=radiogroup] label textarea:focus,.oidc-select label [type=password]:focus,.oidc-select label [type=text]:focus,.oidc-select label textarea:focus,.type-toggle [type=password]:focus,.type-toggle [type=text]:focus,.type-toggle textarea:focus,main .type-password [type=password]:focus,main .type-password [type=text]:focus,main .type-password textarea:focus,main .type-select [type=password]:focus,main .type-select [type=text]:focus,main .type-select textarea:focus,main .type-text [type=password]:focus,main .type-text [type=text]:focus,main .type-text textarea:focus{border-color:var(--typo-action,var(--token-color-foreground-action))}.app-view>div form:not(.filter-bar) [role=radiogroup] label a,.modal-dialog [role=document] .type-password a,.modal-dialog [role=document] .type-select a,.modal-dialog [role=document] .type-text a,.modal-dialog [role=document] [role=radiogroup] label a,.oidc-select label a,.type-toggle a,main .type-password a,main .type-select a,main .type-text a{display:inline}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password],.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text],.modal-dialog [role=document] .type-password [type=password],.modal-dialog [role=document] .type-password [type=text],.modal-dialog [role=document] .type-select [type=password],.modal-dialog [role=document] .type-select [type=text],.modal-dialog [role=document] .type-text [type=password],.modal-dialog [role=document] .type-text [type=text],.modal-dialog [role=document] [role=radiogroup] label [type=password],.modal-dialog [role=document] [role=radiogroup] label [type=text],.oidc-select label [type=password],.oidc-select label [type=text],.type-toggle [type=password],.type-toggle [type=text],main .type-password [type=password],main .type-password [type=text],main .type-select [type=password],main .type-select [type=text],main .type-text [type=password],main .type-text [type=text]{display:inline-flex;justify-content:flex-start;max-width:100%;width:100%;height:0;padding:17px 13px}.consul-exposed-path-list>ul>li>.header dt,.consul-lock-session-list ul>li:not(:first-child)>.header dt,.consul-upstream-instance-list li>.header dt,.list-collection>ul>li:not(:first-child)>.header dt,.type-toggle input{display:none}.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea,.modal-dialog [role=document] .type-password textarea,.modal-dialog [role=document] .type-select textarea,.modal-dialog [role=document] .type-text textarea,.modal-dialog [role=document] [role=radiogroup] label textarea,.oidc-select label textarea,.type-toggle textarea,main .type-password textarea,main .type-select textarea,main .type-text textarea{resize:vertical;max-width:100%;min-width:100%;min-height:70px;padding:6px 13px}.app-view>div form:not(.filter-bar) [role=radiogroup],.app-view>div form:not(.filter-bar) [role=radiogroup] label,.checkbox-group,.modal-dialog [role=document] .type-password,.modal-dialog [role=document] .type-select,.modal-dialog [role=document] .type-text,.modal-dialog [role=document] [role=radiogroup],.modal-dialog [role=document] [role=radiogroup] label,.modal-dialog [role=document] form table,.oidc-select label,.type-toggle,main .type-password,main .type-select,main .type-text,main form table{margin-bottom:1.4em}.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label>span,.oidc-select label>span,.type-toggle>span,main .type-password>span,main .type-select>span,main .type-text>span,span.label{color:var(--typo-contrast,inherit);margin-bottom:.3em}.app-view>div form:not(.filter-bar) [role=radiogroup] label>em,.modal-dialog [role=document] .type-password>em,.modal-dialog [role=document] .type-select>em,.modal-dialog [role=document] .type-text>em,.modal-dialog [role=document] [role=radiogroup] label>em,.modal-dialog [role=document] form button+em,.oidc-select label>em,.type-toggle>em,main .type-password>em,main .type-select>em,main .type-text>em,main form button+em{margin-top:2px}.app-view>div form:not(.filter-bar) [role=radiogroup] label>span+em,.modal-dialog [role=document] .type-password>span+em,.modal-dialog [role=document] .type-select>span+em,.modal-dialog [role=document] .type-text>span+em,.modal-dialog [role=document] [role=radiogroup] label>span+em,.oidc-select label>span+em,.type-toggle>span+em,main .type-password>span+em,main .type-select>span+em,main .type-text>span+em,span.label+em{margin-top:-.5em;margin-bottom:.5em}.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] label.type-text>span,main .type-password>span,main .type-select>span,main label.type-text>span{line-height:2.2em}.type-toggle+.checkbox-group{margin-top:-1em}.consul-exposed-path-list>ul>li,.consul-intention-permission-header-list>ul>li,.consul-intention-permission-list>ul>li,.consul-lock-session-list ul>li:not(:first-child),.consul-upstream-instance-list li,.list-collection>ul>li:not(:first-child){list-style-type:none;border:var(--decor-border-100);border-top-color:transparent;border-bottom-color:var(--token-color-surface-interactive-active);border-right-color:transparent;border-left-color:transparent;--horizontal-padding:12px;--vertical-padding:10px;padding:var(--vertical-padding) 0;padding-left:var(--horizontal-padding)}.consul-auth-method-list>ul>li:active:not(:first-child),.consul-auth-method-list>ul>li:focus:not(:first-child),.consul-auth-method-list>ul>li:hover:not(:first-child),.consul-exposed-path-list>ul>li.linkable:active,.consul-exposed-path-list>ul>li.linkable:focus,.consul-exposed-path-list>ul>li.linkable:hover,.consul-intention-permission-list:not(.readonly)>ul>li:active,.consul-intention-permission-list:not(.readonly)>ul>li:focus,.consul-intention-permission-list:not(.readonly)>ul>li:hover,.consul-lock-session-list ul>li.linkable:active:not(:first-child),.consul-lock-session-list ul>li.linkable:focus:not(:first-child),.consul-lock-session-list ul>li.linkable:hover:not(:first-child),.consul-node-list>ul>li:active:not(:first-child),.consul-node-list>ul>li:focus:not(:first-child),.consul-node-list>ul>li:hover:not(:first-child),.consul-policy-list>ul>li:active:not(:first-child),.consul-policy-list>ul>li:focus:not(:first-child),.consul-policy-list>ul>li:hover:not(:first-child),.consul-role-list>ul>li:active:not(:first-child),.consul-role-list>ul>li:focus:not(:first-child),.consul-role-list>ul>li:hover:not(:first-child),.consul-service-instance-list>ul>li:active:not(:first-child),.consul-service-instance-list>ul>li:focus:not(:first-child),.consul-service-instance-list>ul>li:hover:not(:first-child),.consul-token-list>ul>li:active:not(:first-child),.consul-token-list>ul>li:focus:not(:first-child),.consul-token-list>ul>li:hover:not(:first-child),.consul-upstream-instance-list li.linkable:active,.consul-upstream-instance-list li.linkable:focus,.consul-upstream-instance-list li.linkable:hover,.list-collection>ul>li.linkable:active:not(:first-child),.list-collection>ul>li.linkable:focus:not(:first-child),.list-collection>ul>li.linkable:hover:not(:first-child){border-color:var(--token-color-surface-interactive-active);box-shadow:var(--token-elevation-high-box-shadow);border-top-color:transparent;cursor:pointer}.radio-card,.tippy-box{box-shadow:var(--token-surface-mid-box-shadow)}.consul-exposed-path-list>ul>li>.header,.consul-lock-session-list ul>li:not(:first-child)>.header,.consul-upstream-instance-list li>.header,.list-collection>ul>li:not(:first-child)>.header{color:var(--token-color-hashicorp-brand)}.consul-exposed-path-list>ul>li>.header *,.consul-lock-session-list ul>li:not(:first-child)>.header *,.consul-upstream-instance-list li>.header *,.list-collection>ul>li:not(:first-child)>.header *{color:inherit}.consul-exposed-path-list>ul>li>.detail,.consul-lock-session-list ul>li:not(:first-child)>.detail,.consul-upstream-instance-list li>.detail,.list-collection>ul>li:not(:first-child)>.detail,.radio-card{color:var(--token-color-foreground-faint)}.consul-exposed-path-list>ul>li>.detail a,.consul-lock-session-list ul>li:not(:first-child)>.detail a,.consul-upstream-instance-list li>.detail a,.list-collection>ul>li:not(:first-child)>.detail a{color:inherit}.consul-exposed-path-list>ul>li>.detail a:hover,.consul-lock-session-list ul>li:not(:first-child)>.detail a:hover,.consul-upstream-instance-list li>.detail a:hover,.list-collection>ul>li:not(:first-child)>.detail a:hover{color:var(--token-color-foreground-action);text-decoration:underline}.consul-exposed-path-list>ul>li>.detail,.consul-exposed-path-list>ul>li>.header>dl:first-child,.consul-lock-session-list ul>li:not(:first-child)>.detail,.consul-lock-session-list ul>li:not(:first-child)>.header>dl:first-child,.consul-upstream-instance-list li>.detail,.consul-upstream-instance-list li>.header>dl:first-child,.list-collection>ul>li:not(:first-child)>.detail,.list-collection>ul>li:not(:first-child)>.header>dl:first-child{margin-right:6px}.consul-exposed-path-list>ul>li>.header dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header dd::before,.consul-upstream-instance-list li>.header dd::before,.list-collection>ul>li:not(:first-child)>.header dd::before{font-size:.9em}.consul-exposed-path-list>ul>li>.detail,.consul-exposed-path-list>ul>li>.header,.consul-lock-session-list ul>li:not(:first-child)>.detail,.consul-lock-session-list ul>li:not(:first-child)>.header,.consul-upstream-instance-list li>.detail,.consul-upstream-instance-list li>.header,.list-collection>ul>li:not(:first-child)>.detail,.list-collection>ul>li:not(:first-child)>.header{display:flex;flex-wrap:nowrap;overflow-x:hidden}.consul-exposed-path-list>ul>li>.detail *,.consul-exposed-path-list>ul>li>.header *,.consul-lock-session-list ul>li:not(:first-child)>.detail *,.consul-lock-session-list ul>li:not(:first-child)>.header *,.consul-upstream-instance-list li>.detail *,.consul-upstream-instance-list li>.header *,.list-collection>ul>li:not(:first-child)>.detail *,.list-collection>ul>li:not(:first-child)>.header *{white-space:nowrap;flex-wrap:nowrap}.consul-exposed-path-list>ul>li>.detail>span,.consul-lock-session-list ul>li:not(:first-child)>.detail>span,.consul-upstream-instance-list li>.detail>span,.list-collection>ul>li:not(:first-child)>.detail>span{margin-right:18px}.consul-intention-permission-header-list>ul>li,.consul-intention-permission-list>ul>li{padding-top:0!important;padding-bottom:0!important}.consul-intention-permission-header-list>ul>li .detail,.consul-intention-permission-list>ul>li .detail{grid-row-start:header!important;grid-row-end:detail!important;align-self:center!important;padding:5px 0}.consul-intention-permission-header-list>ul>li .popover-menu>[type=checkbox]+label,.consul-intention-permission-list>ul>li .popover-menu>[type=checkbox]+label{padding:0}.consul-intention-permission-header-list>ul>li .popover-menu>[type=checkbox]+label+div:not(.above),.consul-intention-permission-list>ul>li .popover-menu>[type=checkbox]+label+div:not(.above){top:30px}.has-error>strong{font-style:normal;font-weight:var(--token-typography-font-weight-regular);color:inherit;color:var(--token-color-foreground-critical);position:relative;padding-left:20px}.has-error>strong::before{color:var(--token-color-foreground-critical);position:absolute;top:50%;left:0;margin-top:-8px}.more-popover-menu .popover-menu>[type=checkbox]+label,table.has-actions tr>.actions .popover-menu>[type=checkbox]+label,table.with-details tr>.actions .popover-menu>[type=checkbox]+label{padding:7px}.more-popover-menu .popover-menu>[type=checkbox]+label>*,table.has-actions tr>.actions .popover-menu>[type=checkbox]+label>*,table.with-details tr>.actions .popover-menu>[type=checkbox]+label>*{background-color:transparent;border-radius:var(--decor-radius-100);width:30px;height:30px;font-size:0}.more-popover-menu .popover-menu>[type=checkbox]+label>:active,.more-popover-menu .popover-menu>[type=checkbox]+label>:focus,.more-popover-menu .popover-menu>[type=checkbox]+label>:hover,.radio-card>:first-child,table.has-actions tr>.actions .popover-menu>[type=checkbox]+label>:active,table.has-actions tr>.actions .popover-menu>[type=checkbox]+label>:focus,table.has-actions tr>.actions .popover-menu>[type=checkbox]+label>:hover,table.with-details tr>.actions .popover-menu>[type=checkbox]+label>:active,table.with-details tr>.actions .popover-menu>[type=checkbox]+label>:focus,table.with-details tr>.actions .popover-menu>[type=checkbox]+label>:hover{background-color:var(--token-color-surface-strong)}.more-popover-menu .popover-menu>[type=checkbox]+label>::after,table.has-actions tr>.actions .popover-menu>[type=checkbox]+label>::after,table.with-details tr>.actions .popover-menu>[type=checkbox]+label>::after{--icon-name:icon-more-horizontal;--icon-color:var(--token-color-foreground-strong);--icon-size:icon-300;content:"";position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.oidc-select [class$=-oidc-provider]::before{width:22px;height:22px;flex:0 0 auto;margin-right:10px}.oidc-select .ember-power-select-trigger,.oidc-select li{margin-bottom:1em}.informed-action header,.radio-card header{margin-bottom:.5em}.oidc-select .ember-power-select-trigger{width:100%}.radio-card{border:var(--decor-border-100);border-radius:var(--decor-radius-100);border-color:var(--token-color-surface-interactive-active);cursor:pointer;float:none!important;margin-right:0!important;display:flex!important}.checked.radio-card{border-color:var(--token-color-foreground-action)}.checked.radio-card>:first-child{background-color:var(--token-color-surface-action)}.radio-card header{color:var(--token-color-hashicorp-brand)}.consul-intention-fieldsets .radio-card>:last-child{padding-left:47px;position:relative}.consul-intention-fieldsets .radio-card>:last-child::before{position:absolute;left:14px;font-size:1rem}.radio-card>:first-child{padding:10px;display:grid;align-items:center;justify-items:center}.radio-card>:last-child{padding:18px}.consul-server-card,.disclosure-menu [aria-expanded]~*,.menu-panel,.more-popover-menu>[type=checkbox]+label+div,.popover-menu>[type=checkbox]+label+div,section[data-route="dc.show.serverstatus"] .server-failure-tolerance,section[data-route="dc.show.license"] aside,table.has-actions tr>.actions>[type=checkbox]+label+div,table.with-details tr>.actions>[type=checkbox]+label+div{--tone-border:var(--token-color-palette-neutral-300);border:var(--decor-border-100);border-radius:var(--decor-radius-200);box-shadow:var(--token-surface-high-box-shadow);color:var(--token-color-foreground-strong);background-color:var(--token-color-surface-primary);--padding-x:14px;--padding-y:14px;position:relative}.disclosure-menu [aria-expanded]~* [role=separator],.menu-panel [role=separator],.more-popover-menu>[type=checkbox]+label+div [role=separator],.popover-menu>[type=checkbox]+label+div [role=separator],table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]{border-top:var(--decor-border-100);margin:0}.consul-server-card,.disclosure-menu [aria-expanded]~*,.disclosure-menu [aria-expanded]~* [role=separator],.menu-panel,.menu-panel [role=separator],.more-popover-menu>[type=checkbox]+label+div,.more-popover-menu>[type=checkbox]+label+div [role=separator],.popover-menu>[type=checkbox]+label+div,.popover-menu>[type=checkbox]+label+div [role=separator],section[data-route="dc.show.serverstatus"] .server-failure-tolerance,section[data-route="dc.show.license"] aside,table.has-actions tr>.actions>[type=checkbox]+label+div,table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],table.with-details tr>.actions>[type=checkbox]+label+div,table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]{border-color:var(--tone-border)}.paged-collection-scroll,[style*="--paged-row-height"]{overflow-y:auto!important;will-change:scrollPosition}[style*="--paged-start"]::before{content:"";display:block;height:var(--paged-start)}.consul-auth-method-type,.consul-external-source,.consul-health-check-list .health-check-output dd em,.consul-intention-list td strong,.consul-intention-permission-list strong,.consul-intention-search-bar li button span,.consul-kind,.consul-peer-search-bar li button span,.consul-server-card .health-status+dd,.consul-source,.consul-transparent-proxy,.discovery-chain .route-card>header ul li,.leader,.search-bar-status li:not(.remove-all),.topology-metrics-source-type,html[data-route^="dc.acls.index"] main td strong,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em,span.policy-node-identity,span.policy-service-identity{border-radius:var(--decor-radius-100);display:inline-flex;position:relative;align-items:center;white-space:nowrap}.consul-auth-method-type::before,.consul-external-source::before,.consul-health-check-list .health-check-output dd em::before,.consul-intention-list td strong::before,.consul-intention-permission-list strong::before,.consul-intention-search-bar li button span::before,.consul-kind::before,.consul-peer-search-bar li button span::before,.consul-server-card .health-status+dd::before,.consul-source::before,.consul-transparent-proxy::before,.discovery-chain .route-card>header ul li::before,.leader::before,.search-bar-status li:not(.remove-all)::before,.topology-metrics-source-type::before,html[data-route^="dc.acls.index"] main td strong::before,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl::before,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em::before,span.policy-node-identity::before,span.policy-service-identity::before{margin-right:4px;--icon-size:icon-300}.consul-auth-method-type,.consul-external-source,.consul-kind,.consul-server-card .health-status+dd,.consul-source,.consul-transparent-proxy,.leader,.search-bar-status li:not(.remove-all),.topology-metrics-source-type,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em,span.policy-node-identity,span.policy-service-identity{padding:0 8px;--icon-size:icon-200}.consul-intention-permission-list strong,.consul-peer-search-bar li button span,.discovery-chain .route-card>header ul li,html[data-route^="dc.acls.index"] main td strong,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl{padding:1px 5px}.consul-intention-list td strong,.consul-intention-search-bar li button span{padding:4px 8px}span.policy-node-identity::before,span.policy-service-identity::before{vertical-align:unset}span.policy-node-identity::before{content:"Node Identity: "}span.policy-service-identity::before{content:"Service Identity: "}.more-popover-menu>[type=checkbox]+label>*,.popover-menu>[type=checkbox]+label>*,table.has-actions tr>.actions>[type=checkbox]+label>*,table.with-details tr>.actions>[type=checkbox]+label>*{cursor:pointer}.more-popover-menu>[type=checkbox]+label>::after,.popover-menu>[type=checkbox]+label>::after,table.has-actions tr>.actions>[type=checkbox]+label>::after,table.with-details tr>.actions>[type=checkbox]+label>::after{width:16px;height:16px;position:relative}.more-popover-menu,.popover-menu,table.has-actions tr>.actions,table.with-details tr>.actions{position:relative}.more-popover-menu>[type=checkbox]+label,.popover-menu>[type=checkbox]+label,table.has-actions tr>.actions>[type=checkbox]+label,table.with-details tr>.actions>[type=checkbox]+label{display:block}.more-popover-menu>[type=checkbox]+label+div,.popover-menu>[type=checkbox]+label+div,table.has-actions tr>.actions>[type=checkbox]+label+div,table.with-details tr>.actions>[type=checkbox]+label+div{min-width:192px}.more-popover-menu>[type=checkbox]+label+div:not(.above),.popover-menu>[type=checkbox]+label+div:not(.above),table.has-actions tr>.actions>[type=checkbox]+label+div:not(.above),table.with-details tr>.actions>[type=checkbox]+label+div:not(.above){top:38px}.more-popover-menu>[type=checkbox]+label+div:not(.left),.popover-menu>[type=checkbox]+label+div:not(.left),table.has-actions tr>.actions>[type=checkbox]+label+div:not(.left),table.with-details tr>.actions>[type=checkbox]+label+div:not(.left){right:5px}.popover-menu .menu-panel{position:absolute!important}.popover-select label{height:100%}.popover-select label>*{padding:0 8px!important;height:100%!important;justify-content:space-between!important;min-width:auto!important}.popover-select label>::after{margin-left:6px}.popover-select button::before{margin-right:10px}.popover-select .value-passing button::before{color:var(--token-color-foreground-success)}.popover-select .value-warning button::before{color:var(--token-color-foreground-warning)}.popover-select .value-critical button::before{color:var(--token-color-foreground-critical)}.popover-select .value-empty button::before{color:var(--token-color-foreground-disabled)}.popover-select .value-unknown button::before,.type-source.popover-select li.partition button::before{color:var(--token-color-foreground-faint)}.type-source.popover-select li.aws button{text-transform:uppercase}.progress.indeterminate{width:100%;display:flex;align-items:center;justify-content:center;--icon-size:icon-700;--icon-name:var(--icon-loading);--icon-color:var(--token-color-foreground-faint)}.progress.indeterminate::before{content:""}.app-view>div form:not(.filter-bar) [role=radiogroup],.modal-dialog [role=document] [role=radiogroup]{overflow:hidden;padding-left:1px}.app-view>div form:not(.filter-bar) [role=radiogroup] label,.modal-dialog [role=document] [role=radiogroup] label{float:left}.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.modal-dialog [role=document] [role=radiogroup] label>span{float:right;margin-left:1em}.app-view>div form:not(.filter-bar) [role=radiogroup] label:not(:last-child),.modal-dialog [role=document] [role=radiogroup] label:not(:last-child){margin-right:25px}.app-view>div form:not(.filter-bar) [role=radiogroup] label,.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.modal-dialog [role=document] [role=radiogroup] label,.modal-dialog [role=document] [role=radiogroup] label>span{margin-bottom:0!important}.type-toggle label span{cursor:pointer}.type-toggle label span::after{border-radius:var(--decor-radius-full)}.type-toggle label span::before{border-radius:7px;left:0;width:24px;height:12px;margin-top:-5px}.type-negative.type-toggle{border:0}.app-view>header .title,.modal-dialog [role=document] table td,.modal-dialog [role=document] table th,main table td,main table th{border-bottom:var(--decor-border-100)}.type-toggle label span::after{background-color:var(--token-color-surface-primary);margin-top:-3px;width:8px;height:8px}.type-negative.type-toggle label input+span::before,.type-toggle label input:checked+span::before{background-color:var(--token-color-foreground-action)}.type-negative.type-toggle label input:checked+span::before,.type-toggle label span::before{background-color:var(--token-color-palette-neutral-300)}.type-toggle label{position:relative}.type-toggle label span{color:var(--token-color-foreground-strong);display:inline-block;padding-left:34px}.type-toggle label span::after,.type-toggle label span::before{position:absolute;display:block;content:"";top:50%}.type-negative.type-toggle label input+span::after,.type-toggle label input:checked+span::after{left:14px}.type-negative.type-toggle label input:checked+span::after,.type-toggle label span::after{left:2px}.consul-intention-list td.destination,.consul-intention-list td.source,.modal-dialog [role=document] table th,main table th{border-color:var(--token-color-palette-neutral-300)}.modal-dialog [role=document] table td,main table td{border-color:var(--token-color-palette-neutral-300);color:var(--token-color-foreground-faint);height:50px;vertical-align:middle}.modal-dialog [role=document] table td strong,.modal-dialog [role=document] table th,main table td strong,main table th{color:var(--token-color-foreground-faint)}.modal-dialog [role=document] table a,.tomography-graph .tick text,main table a{color:var(--token-color-foreground-strong)}.modal-dialog [role=document] table,main table{width:100%;border-collapse:collapse}table.dom-recycling tr{display:flex}table.dom-recycling tr>*{flex:1 1 auto;display:inline-flex;align-items:center}.modal-dialog [role=document] table th.actions input,main table th.actions input{display:none}.modal-dialog [role=document] table th.actions,main table th.actions{text-align:right}.modal-dialog [role=document] table td a,main table td a{display:block}.modal-dialog [role=document] table td.no-actions~.actions,main table td.no-actions~.actions{display:none}.modal-dialog [role=document] table td:not(.actions)>:only-child,main table td:not(.actions)>:only-child{overflow:hidden;text-overflow:ellipsis}.modal-dialog [role=document] table td:not(.actions)>*,main table td:not(.actions)>*{white-space:nowrap}.modal-dialog [role=document] table caption,main table caption{margin-bottom:.8em}.modal-dialog [role=document] table th,main table th{padding:.6em 0}.modal-dialog [role=document] table td a,.modal-dialog [role=document] table td:not(.actions),.modal-dialog [role=document] table th:not(.actions),main table td a,main table td:not(.actions),main table th:not(.actions){padding-right:.9em}.modal-dialog [role=document] table tbody td em,main table tbody td em{display:block;font-style:normal;font-weight:var(--token-typography-font-weight-regular);color:var(--token-color-foreground-faint)}table.has-actions tr>.actions,table.with-details tr>.actions{width:60px!important;overflow:visible}table.has-actions tr>.actions>[type=checkbox]+label,table.with-details tr>.actions>[type=checkbox]+label{position:absolute;right:5px}table.consul-metadata-list tbody tr{cursor:default}table.consul-metadata-list tbody tr:hover{box-shadow:none}.modal-dialog [role=document] table th span::after,main table th span::after{color:var(--token-color-foreground-faint);margin-left:4px}.modal-dialog [role=document] table tbody tr,main table tbody tr{cursor:pointer}.modal-dialog [role=document] table td:first-child,main table td:first-child{padding:0}.modal-dialog [role=document] table tbody tr:hover,main table tbody tr:hover{box-shadow:var(--token-elevation-high-box-shadow)}.modal-dialog [role=document] table td.folder::before,main table td.folder::before{background-color:var(--token-color-palette-neutral-300);margin-top:1px;margin-right:5px}@media (max-width:420px){.consul-intention-list tr>:nth-last-child(2),.modal-dialog [role=document] table tr>.actions,main table tr>.actions{display:none}}.voting-status-leader.consul-server-card .name{width:var(--tile-size,3rem);height:var(--tile-size,3rem)}.voting-status-leader.consul-server-card .name::before{display:block;content:"";width:100%;height:100%;border-radius:var(--decor-radius-250);border:var(--decor-border-100);background-image:linear-gradient(135deg,var(--token-color-consul-surface) 0,var(--token-color-consul-border) 100%);border-color:var(--token-color-border-faint)}.voting-status-leader.consul-server-card .name::after{content:"";position:absolute;top:calc(var(--tile-size,3rem)/ 4);left:calc(var(--tile-size,3rem)/ 4);--icon-name:icon-star-fill;--icon-size:icon-700;color:var(--token-color-consul-brand)}table.with-details td:only-child>div>label,table.with-details td>label{border-radius:var(--decor-radius-100);cursor:pointer;min-width:30px;min-height:30px;display:inline-flex;align-items:center;justify-content:center}table.with-details td:only-child>div>label:active,table.with-details td:only-child>div>label:focus,table.with-details td:only-child>div>label:hover,table.with-details td>label:active,table.with-details td>label:focus,table.with-details td>label:hover{background-color:var(--token-color-surface-strong)}table.dom-recycling tbody{top:33px!important;width:100%}table.dom-recycling caption~tbody{top:57px!important}table tr>:nth-last-child(2):first-child,table tr>:nth-last-child(2):first-child~*{width:50%}table tr>:nth-last-child(3):first-child,table tr>:nth-last-child(3):first-child~*{width:33.3333333333%}table tr>:nth-last-child(4):first-child,table tr>:nth-last-child(4):first-child~*{width:25%}table tr>:nth-last-child(5):first-child,table tr>:nth-last-child(5):first-child~*{width:20%}table.has-actions tr>:nth-last-child(2):first-child,table.has-actions tr>:nth-last-child(2):first-child~*{width:calc(100% - 60px)}table.has-actions tr>:nth-last-child(3):first-child,table.has-actions tr>:nth-last-child(3):first-child~*{width:calc(50% - 30px)}table.has-actions tr>:nth-last-child(4):first-child,table.has-actions tr>:nth-last-child(4):first-child~*{width:calc(33% - 20px)}table.has-actions tr>:nth-last-child(5):first-child,table.has-actions tr>:nth-last-child(5):first-child~*{width:calc(25% - 15px)}html[data-route^="dc.acls.policies"] [role=dialog] table tr>:not(last-child),html[data-route^="dc.acls.policies"] table tr>:not(last-child),html[data-route^="dc.acls.roles"] [role=dialog] table tr>:not(last-child),html[data-route^="dc.acls.roles"] main table.token-list tr>:not(last-child){width:120px}html[data-route^="dc.acls.policies"] table tr>:last-child,html[data-route^="dc.acls.roles"] [role=dialog] table tr>:last-child,html[data-route^="dc.acls.roles"] main table.token-list tr>:last-child{width:calc(100% - 240px)!important}table.with-details td:only-child{cursor:default;border:0}table.with-details td:only-child>div::before,table.with-details td:only-child>div>div,table.with-details td:only-child>div>label{background-color:var(--token-color-surface-primary)}table.with-details td:only-child>div>label::before{transform:rotate(180deg)}table.with-details td:only-child>div::before{background:var(--token-color-surface-interactive-active);content:"";display:block;height:1px;position:absolute;bottom:-20px;left:10px;width:calc(100% - 20px)}table.with-details tr>.actions{position:relative}table.with-details td:only-child>div>label,table.with-details td>label{pointer-events:auto;position:absolute;top:8px}table.with-details td:only-child>div>label span,table.with-details td>label span{display:none}table.with-details td>label{right:2px}table.with-details tr:nth-child(even) td{height:auto;position:relative;display:table-cell}table.with-details tr:nth-child(even) td>*{display:none}table.with-details td:only-child>div>label{right:11px}table.with-details tr:nth-child(even) td>input:checked+*{display:block}table.with-details td:only-child{overflow:visible;width:100%}table.with-details td:only-child>div{border:1px solid var(--token-color-palette-neutral-300);border-radius:var(--decor-radius-100);box-shadow:var(--token-surface-high-box-shadow);margin-bottom:20px;position:relative;left:-10px;right:-10px;width:calc(100% + 20px);margin-top:-51px;pointer-events:none;padding:10px}table.with-details td:only-child>div::after{content:"";display:block;clear:both}table.with-details td:only-child>div>div{pointer-events:auto;margin-top:36px}.consul-auth-method-binding-list dl,.consul-auth-method-view dl,.consul-auth-method-view section dl{display:flex;flex-wrap:wrap}.consul-auth-method-binding-list dl dd,.consul-auth-method-binding-list dl dt,.consul-auth-method-view dl dd,.consul-auth-method-view dl dt{padding:12px 0;margin:0;border-top:1px solid!important}.consul-auth-method-binding-list dl dt,.consul-auth-method-view dl dt{width:20%;font-weight:var(--token-typography-font-weight-bold)}.consul-auth-method-binding-list dl dd,.consul-auth-method-view dl dd{margin-left:auto;width:80%;display:flex}.consul-auth-method-binding-list dl dd>ul li,.consul-auth-method-view dl dd>ul li{display:flex}.consul-auth-method-binding-list dl dd>ul li:not(:last-of-type),.consul-auth-method-view dl dd>ul li:not(:last-of-type){padding-bottom:12px}.consul-auth-method-binding-list dl dt.check+dd,.consul-auth-method-view dl dt.check+dd{padding-top:16px}.consul-auth-method-binding-list dl>dd:last-of-type,.consul-auth-method-binding-list dl>dt:last-of-type,.consul-auth-method-view dl>dd:last-of-type,.consul-auth-method-view dl>dt:last-of-type{border-bottom:1px solid!important;border-color:var(--token-color-palette-neutral-300)!important}.consul-auth-method-binding-list dl dd,.consul-auth-method-binding-list dl dt,.consul-auth-method-view dl dd,.consul-auth-method-view dl dt{border-color:var(--token-color-palette-neutral-300)!important;color:var(--token-color-hashicorp-brand)!important}.consul-auth-method-binding-list dl dd .copy-button button::before,.consul-auth-method-view dl dd .copy-button button::before{background-color:var(--token-color-hashicorp-brand)}.consul-auth-method-binding-list dl dt.type+dd span::before,.consul-auth-method-view dl dt.type+dd span::before{margin-left:4px;background-color:var(--token-color-foreground-faint)}.tooltip-panel dt{cursor:pointer}.tooltip-panel dd>div::before{width:12px;height:12px;background-color:var(--token-color-surface-primary);border-top:1px solid var(--token-color-palette-neutral-300);border-right:1px solid var(--token-color-palette-neutral-300);transform:rotate(-45deg);position:absolute;left:16px;top:-7px}.tooltip-panel,.tooltip-panel dt{display:flex;flex-direction:column}.tooltip-panel dd>div.menu-panel{top:auto;overflow:visible}.tooltip-panel dd{display:none;position:relative;z-index:1;padding-top:10px;margin-bottom:-10px}.tooltip-panel:hover dd{display:block}.tooltip-panel dd>div{width:250px}.app-view>header .title{display:grid;grid-template-columns:1fr auto;grid-template-areas:"title actions";position:relative;z-index:5;padding-bottom:1.4em}.app-view>div form:not(.filter-bar) fieldset{border-bottom:var(--decor-border-200)}.app-view>header h1>em{color:var(--token-color-foreground-faint)}.app-view>header dd>a{color:var(--token-color-hashicorp-brand)}.app-view>div div>dl>dd{color:var(--token-color-foreground-disabled)}.app-view>div form:not(.filter-bar) fieldset,.app-view>header .title{border-color:var(--token-color-surface-interactive-active)}.app-view>header .title .title-left-container{grid-area:title;display:flex;flex-wrap:wrap;align-items:center;white-space:normal}.app-view>header .title .title-left-container>:first-child{flex-basis:100%}.app-view>header .title .title-left-container>:not(:first-child){margin-right:8px}.app-view>header .actions{grid-area:actions;align-self:end;display:flex;align-items:flex-start;margin-left:auto;margin-top:9px}.app-view>div form:not(.filter-bar) fieldset{padding-bottom:.3em;margin-bottom:2em}[for=toolbar-toggle]{background-position:0 4px;display:inline-block;width:26px;height:26px;cursor:pointer;color:var(--token-color-foreground-action)}#toolbar-toggle{display:none}@media (max-width:849px){.app-view>header .actions{margin-top:9px}}@media (min-width:996px){[for=toolbar-toggle]{display:none}}@media (max-width:995px){.app-view>header h1{display:inline-block}html[data-route$="dc.services.instance.show"] h1{display:block}#toolbar-toggle+*{display:none}#toolbar-toggle:checked+*{display:flex}}.brand-loader{position:absolute;top:50%;margin-top:-26px;left:50%}.app .notifications{position:fixed;z-index:100;bottom:2rem;left:1.5rem;pointer-events:none}.app .notifications .app-notification>*{min-width:400px}.app .notifications .app-notification{transition-property:opacity;width:-moz-fit-content;width:fit-content;max-width:80%;pointer-events:auto}.hashicorp-consul .consul-side-nav li.consul-disabled-nav{width:100%;min-height:var(--token-side-nav-body-list-item-height);padding:var(--token-side-nav-body-list-item-padding-vertical) var(--token-side-nav-body-list-item-padding-horizontal);color:var(--token-color-foreground-disabled)}.hashicorp-consul .consul-side-nav li.consul-side-nav__selector .consul-side-nav__selector-toggle{min-width:15.5rem}.hashicorp-consul .consul-side-nav li.consul-side-nav__selector .consul-side-nav__selector-toggle:disabled{color:var(--token-color-foreground-disabled);border-color:var(--token-color-border-primary)}.hashicorp-consul .consul-side-nav li.consul-side-nav__selector .consul-side-nav__selector-toggle:disabled:hover{background-color:transparent}.hashicorp-consul .consul-side-nav li.consul-side-nav__selector .hds-dropdown__content{min-width:15.5rem;max-height:500px}.hashicorp-consul .consul-side-nav .hds-side-nav__wrapper-body{overflow-y:unset;overflow-x:unset}.hashicorp-consul .consul-side-nav li.consul-side-nav__datacenter{display:flex;gap:.5rem;align-items:center;padding-left:.5rem}.hashicorp-consul .consul-side-nav .consul-side-nav__selector-group{margin-bottom:1.5rem}.hashicorp-consul .consul-side-nav .consul-datacenter-selector__dc-name{display:flex;align-items:center;gap:.5rem}.hashicorp-consul .consul-side-nav .consul-datacenter-selector__dc-name .consul-datacenter-selector__badges{display:flex;gap:.25rem}.hashicorp-consul .consul-side-nav .consul-side-nav__selector-title{margin-top:.5rem}.hashicorp-consul .consul-side-nav .consul-side-nav__selector-description{padding-top:.5rem}.disclosure-menu [aria-expanded]~*>div+ul,.menu-panel>div+ul,.more-popover-menu>[type=checkbox]+label+div>div+ul,.popover-menu>[type=checkbox]+label+div>div+ul,table.has-actions tr>.actions>[type=checkbox]+label+div>div+ul,table.with-details tr>.actions>[type=checkbox]+label+div>div+ul{border-top:var(--decor-border-100);border-color:var(--token-form--base-border-color-default)}.disclosure-menu [aria-expanded]~* [role=separator]:first-child:not(:empty),.menu-panel [role=separator]:first-child:not(:empty),.more-popover-menu>[type=checkbox]+label+div [role=separator]:first-child:not(:empty),.popover-menu>[type=checkbox]+label+div [role=separator]:first-child:not(:empty),table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator]:first-child:not(:empty),table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]:first-child:not(:empty){border:none}.disclosure-menu [aria-expanded]~*>ul>li,.menu-panel>ul>li,.more-popover-menu>[type=checkbox]+label+div>ul>li,.popover-menu>[type=checkbox]+label+div>ul>li,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li{list-style-type:none}.disclosure-menu [aria-expanded]~*>ul .informed-action,.menu-panel>ul .informed-action,.more-popover-menu>[type=checkbox]+label+div>ul .informed-action,.popover-menu>[type=checkbox]+label+div>ul .informed-action,table.has-actions tr>.actions>[type=checkbox]+label+div>ul .informed-action,table.with-details tr>.actions>[type=checkbox]+label+div>ul .informed-action{border:0!important}.disclosure-menu [aria-expanded]~*>div,.menu-panel>div,.more-popover-menu>[type=checkbox]+label+div>div,.popover-menu>[type=checkbox]+label+div>div,table.has-actions tr>.actions>[type=checkbox]+label+div>div,table.with-details tr>.actions>[type=checkbox]+label+div>div{padding:.625rem var(--padding-x);white-space:normal;max-width:-moz-fit-content;max-width:fit-content}@supports not ((max-width:-moz-fit-content) or (max-width:fit-content)){.disclosure-menu [aria-expanded]~*>div,.menu-panel>div,.more-popover-menu>[type=checkbox]+label+div>div,.popover-menu>[type=checkbox]+label+div>div,table.has-actions tr>.actions>[type=checkbox]+label+div>div,table.with-details tr>.actions>[type=checkbox]+label+div>div{max-width:200px}}.disclosure-menu [aria-expanded]~*>div::before,.menu-panel>div::before,.more-popover-menu>[type=checkbox]+label+div>div::before,.popover-menu>[type=checkbox]+label+div>div::before,table.has-actions tr>.actions>[type=checkbox]+label+div>div::before,table.with-details tr>.actions>[type=checkbox]+label+div>div::before{position:absolute;left:15px;top:calc(10px + .1em)}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem]+*,.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem]+*,.disclosure-menu [aria-expanded]~*>ul>li>[role=option]+*,.menu-panel-deprecated>ul>li>div[role=menu],.menu-panel>ul>[role=treeitem]+*,.menu-panel>ul>li>[role=menuitem]+*,.menu-panel>ul>li>[role=option]+*,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]+*,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]+*,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option]+*,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]+*,.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]+*,.popover-menu>[type=checkbox]+label+div>ul>li>[role=option]+*,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]+*,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]+*,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]+*,table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]+*,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]+*,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]+*{position:absolute;top:0;left:calc(100% + 10px)}.disclosure-menu [aria-expanded]~*>ul,.menu-panel>ul,.more-popover-menu>[type=checkbox]+label+div>ul,.popover-menu>[type=checkbox]+label+div>ul,table.has-actions tr>.actions>[type=checkbox]+label+div>ul,table.with-details tr>.actions>[type=checkbox]+label+div>ul{margin:0;padding:calc(var(--padding-y) - .625rem) 0;transition:transform 150ms}.disclosure-menu [aria-expanded]~*>ul,.disclosure-menu [aria-expanded]~*>ul>li,.disclosure-menu [aria-expanded]~*>ul>li>*,.menu-panel>ul,.menu-panel>ul>li,.menu-panel>ul>li>*,.more-popover-menu>[type=checkbox]+label+div>ul,.more-popover-menu>[type=checkbox]+label+div>ul>li,.more-popover-menu>[type=checkbox]+label+div>ul>li>*,.popover-menu>[type=checkbox]+label+div>ul,.popover-menu>[type=checkbox]+label+div>ul>li,.popover-menu>[type=checkbox]+label+div>ul>li>*,table.has-actions tr>.actions>[type=checkbox]+label+div>ul,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>*,table.with-details tr>.actions>[type=checkbox]+label+div>ul,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>*{width:100%}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{display:flex}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem]::after,.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem]::after,.disclosure-menu [aria-expanded]~*>ul>li>[role=option]::after,.menu-panel>ul>[role=treeitem]::after,.menu-panel>ul>li>[role=menuitem]::after,.menu-panel>ul>li>[role=option]::after,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]::after,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]::after,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option]::after,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]::after,.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]::after,.popover-menu>[type=checkbox]+label+div>ul>li>[role=option]::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]::after{margin-left:auto;padding-right:var(--padding-x);transform:translate(calc(var(--padding-x)/ 2),0)}.disclosure-menu [aria-expanded]~* [role=separator],.menu-panel [role=separator],.more-popover-menu>[type=checkbox]+label+div [role=separator],.popover-menu>[type=checkbox]+label+div [role=separator],table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]{text-transform:uppercase;color:var(--token-color-foreground-faint);padding-top:.375rem}.disclosure-menu [aria-expanded]~* [role=separator]:not(:first-child),.menu-panel [role=separator]:not(:first-child),.more-popover-menu>[type=checkbox]+label+div [role=separator]:not(:first-child),.popover-menu>[type=checkbox]+label+div [role=separator]:not(:first-child),table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator]:not(:first-child),table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]:not(:first-child){margin-top:.275rem}.disclosure-menu [aria-expanded]~* [role=separator]:not(:empty),.menu-panel [role=separator]:not(:empty),.more-popover-menu>[type=checkbox]+label+div [role=separator]:not(:empty),.popover-menu>[type=checkbox]+label+div [role=separator]:not(:empty),table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator]:not(:empty),table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]:not(:empty){padding-left:var(--padding-x);padding-right:var(--padding-x);padding-bottom:.125rem}.disclosure-menu [aria-expanded]~.menu-panel-confirming,.menu-panel-confirming.menu-panel,.more-popover-menu>[type=checkbox]+label+div.menu-panel-confirming,.popover-menu>[type=checkbox]+label+div.menu-panel-confirming,table.has-actions tr>.actions>[type=checkbox]+label+div.menu-panel-confirming,table.with-details tr>.actions>[type=checkbox]+label+div.menu-panel-confirming{overflow:hidden}.disclosure-menu [aria-expanded]~.menu-panel-confirming>ul,.menu-panel-confirming.menu-panel>ul,.more-popover-menu>[type=checkbox]+label+div.menu-panel-confirming>ul,.popover-menu>[type=checkbox]+label+div.menu-panel-confirming>ul,table.has-actions tr>.actions>[type=checkbox]+label+div.menu-panel-confirming>ul,table.with-details tr>.actions>[type=checkbox]+label+div.menu-panel-confirming>ul{transform:translateX(calc(-100% - 10px))}.disclosure-menu [aria-expanded]~*,.menu-panel,.more-popover-menu>[type=checkbox]+label+div,.popover-menu>[type=checkbox]+label+div,table.has-actions tr>.actions>[type=checkbox]+label+div,table.with-details tr>.actions>[type=checkbox]+label+div{overflow:hidden}.menu-panel-deprecated{position:absolute;transition:max-height 150ms;transition:min-height 150ms,max-height 150ms;min-height:0}.menu-panel-deprecated [type=checkbox]{display:none}.menu-panel-deprecated:not(.confirmation) [type=checkbox]~*{transition:transform 150ms}.confirmation.menu-panel-deprecated [role=menu]{min-height:205px!important}.menu-panel-deprecated [type=checkbox]:checked~*{transform:translateX(calc(-100% - 10px));min-height:143px;max-height:143px}.menu-panel-deprecated [id$="-"]:first-child:checked~ul label[for$="-"] * [role=menu],.menu-panel-deprecated [id$="-"]:first-child:checked~ul>li>[role=menu]{display:block}.menu-panel-deprecated>ul>li>:not(div[role=menu]),.tippy-box{position:relative}.menu-panel-deprecated:not(.left){right:0!important;left:auto!important}.left.menu-panel-deprecated{left:0}.menu-panel-deprecated:not(.above){top:28px}.above.menu-panel-deprecated{bottom:42px}.consul-upstream-instance-list dl.local-bind-socket-mode dt::after{display:inline;content:var(--horizontal-kv-list-key-separator)}.consul-bucket-list,.consul-exposed-path-list>ul>li>.detail dl,.consul-instance-checks,.consul-lock-session-list dl,.consul-lock-session-list ul>li:not(:first-child)>.detail dl,.consul-upstream-instance-list dl,.consul-upstream-instance-list li>.detail dl,.list-collection>ul>li:not(:first-child)>.detail dl,.tag-list,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl,section[data-route="dc.show.license"] .validity dl,td.tags{display:inline-flex;flex-wrap:nowrap;align-items:center}.consul-bucket-list:empty,.consul-exposed-path-list>ul>li>.detail dl:empty,.consul-instance-checks:empty,.consul-lock-session-list dl:empty,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:empty,.consul-upstream-instance-list dl:empty,.list-collection>ul>li:not(:first-child)>.detail dl:empty,.tag-list:empty,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:empty,section[data-route="dc.show.license"] .validity dl:empty,td.tags:empty{display:none}.consul-bucket-list>*>*,.consul-exposed-path-list>ul>li>.detail dl>*>*,.consul-instance-checks>*>*,.consul-lock-session-list dl>*>*,.consul-lock-session-list ul>li:not(:first-child)>.detail dl>*>*,.consul-upstream-instance-list dl>*>*,.consul-upstream-instance-list li>.detail dl>*>*,.list-collection>ul>li:not(:first-child)>.detail dl>*>*,.tag-list>*>*,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl>*>*,section[data-route="dc.show.license"] .validity dl>*>*,td.tags>*>*{display:inline-block}.consul-bucket-list>*,.consul-exposed-path-list>ul>li>.detail dl>*,.consul-instance-checks>*,.consul-lock-session-list dl>*,.consul-lock-session-list ul>li:not(:first-child)>.detail dl>*,.consul-upstream-instance-list dl>*,.consul-upstream-instance-list li>.detail dl>*,.list-collection>ul>li:not(:first-child)>.detail dl>*,.tag-list>*,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl>*,section[data-route="dc.show.license"] .validity dl>*,td.tags>*{white-space:nowrap}.consul-bucket-list>dd,.consul-exposed-path-list>ul>li>.detail dl>dd,.consul-instance-checks>dd,.consul-lock-session-list dl>dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl>dd,.consul-upstream-instance-list dl>dd,.consul-upstream-instance-list li>.detail dl>dd,.list-collection>ul>li:not(:first-child)>.detail dl>dd,.tag-list>dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl>dd,section[data-route="dc.show.license"] .validity dl>dd,td.tags>dd{flex-wrap:wrap}.consul-upstream-instance-list dl.local-bind-socket-mode dt{display:inline-flex;min-width:18px;overflow:hidden}.consul-lock-session-list .checks dd,.discovery-chain .resolver-card ol,.filter-bar,.filter-bar>div,.modal-dialog,.tag-list dd,td.tags dd{display:flex}.consul-bucket-list .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-bucket-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-bucket-list .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.consul-bucket-list .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.consul-bucket-list .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-bucket-list .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-bucket-list .tag-list:not([class]) dd+dt:not([class])+dd,.consul-bucket-list dd+dt,.consul-bucket-list td.tags:not([class]) dd+dt:not([class])+dd,.consul-bucket-list+.consul-bucket-list:not(:first-of-type),.consul-bucket-list+.consul-instance-checks:not(:first-of-type),.consul-bucket-list+.tag-list:not(:first-of-type),.consul-bucket-list+td.tags:not(:first-of-type),.consul-bucket-list:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,.consul-bucket-list:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-bucket-list:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,.consul-bucket-list:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-bucket-list:not([class]) .tag-list dd+dt:not([class])+dd,.consul-bucket-list:not([class]) dd+dt:not([class])+dd,.consul-bucket-list:not([class]) td.tags dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail .consul-bucket-list+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail .consul-instance-checks+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail .consul-lock-session-list dl+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail .consul-upstream-instance-list dl+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.consul-exposed-path-list>ul>li>.detail .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.consul-exposed-path-list>ul>li>.detail .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail .tag-list+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail dl .consul-bucket-list:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl .consul-instance-checks:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl .consul-lock-session-list dl:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl .consul-upstream-instance-list dl:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl .tag-list:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl dd+dt,.consul-exposed-path-list>ul>li>.detail dl section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl td.tags:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl+.consul-bucket-list:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail dl+.consul-instance-checks:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail dl+.tag-list:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail dl+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail dl+td.tags:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail dl:not([class]) .consul-bucket-list dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) .consul-instance-checks dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) .consul-lock-session-list dl dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) .consul-upstream-instance-list dl dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) .tag-list dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) section[data-route="dc.show.license"] .validity dl dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) td.tags dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail td.tags+dl:not(:first-of-type),.consul-instance-checks .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-instance-checks .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-instance-checks .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.consul-instance-checks .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.consul-instance-checks .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-instance-checks .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-instance-checks .tag-list:not([class]) dd+dt:not([class])+dd,.consul-instance-checks dd+dt,.consul-instance-checks td.tags:not([class]) dd+dt:not([class])+dd,.consul-instance-checks+.consul-bucket-list:not(:first-of-type),.consul-instance-checks+.consul-instance-checks:not(:first-of-type),.consul-instance-checks+.tag-list:not(:first-of-type),.consul-instance-checks+td.tags:not(:first-of-type),.consul-instance-checks:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,.consul-instance-checks:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-instance-checks:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,.consul-instance-checks:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-instance-checks:not([class]) .tag-list dd+dt:not([class])+dd,.consul-instance-checks:not([class]) dd+dt:not([class])+dd,.consul-instance-checks:not([class]) td.tags dd+dt:not([class])+dd,.consul-lock-session-list .consul-bucket-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-bucket-list+dl:not(:first-of-type),.consul-lock-session-list .consul-bucket-list:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list .consul-exposed-path-list>ul>li>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-exposed-path-list>ul>li>.detail dl+dl:not(:first-of-type),.consul-lock-session-list .consul-exposed-path-list>ul>li>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list .consul-instance-checks ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-instance-checks+dl:not(:first-of-type),.consul-lock-session-list .consul-instance-checks:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list dl li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list dl ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list dl+dl:not(:first-of-type),.consul-lock-session-list .consul-upstream-instance-list dl.local-bind-address dl dd+dt+dd,.consul-lock-session-list .consul-upstream-instance-list dl.local-bind-socket-path dl dd+dt+dd,.consul-lock-session-list .consul-upstream-instance-list dl:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list dl:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list li>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list li>.detail dl+dl:not(:first-of-type),.consul-lock-session-list .consul-upstream-instance-list li>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),.consul-lock-session-list .consul-upstream-instance-list ul>li:not(:first-child)>.detail dl.local-bind-address dd+dt+dd,.consul-lock-session-list .consul-upstream-instance-list ul>li:not(:first-child)>.detail dl.local-bind-socket-path dd+dt+dd,.consul-lock-session-list .consul-upstream-instance-list ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list .list-collection>ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .list-collection>ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),.consul-lock-session-list .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list .list-collection>ul>li:not(:first-child)>.detail ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .tag-list dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .tag-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .tag-list+dl:not(:first-of-type),.consul-lock-session-list .tag-list:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list .tag-list:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list dl .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.consul-lock-session-list dl .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.consul-lock-session-list dl .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl .tag-list:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl dd+dt,.consul-lock-session-list dl td.tags:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl+.consul-bucket-list:not(:first-of-type),.consul-lock-session-list dl+.consul-instance-checks:not(:first-of-type),.consul-lock-session-list dl+.tag-list:not(:first-of-type),.consul-lock-session-list dl+dl:not(:first-of-type),.consul-lock-session-list dl+td.tags:not(:first-of-type),.consul-lock-session-list dl:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) .tag-list dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) td.tags dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),.consul-lock-session-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list section[data-route="dc.show.license"] .validity dl ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),.consul-lock-session-list section[data-route="dc.show.license"] .validity dl:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list td.tags dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list td.tags ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list td.tags+dl:not(:first-of-type),.consul-lock-session-list td.tags:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list td.tags:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail .consul-bucket-list+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail .consul-instance-checks+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail .consul-upstream-instance-list dl+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail .tag-list+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail dl .consul-bucket-list:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl .consul-instance-checks:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl .consul-upstream-instance-list dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl .tag-list:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt,.consul-lock-session-list ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl td.tags:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl+.consul-bucket-list:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail dl+.consul-instance-checks:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail dl+.tag-list:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail dl+td.tags:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) .consul-bucket-list dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) .consul-instance-checks dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) .consul-upstream-instance-list dl dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) .tag-list dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) section[data-route="dc.show.license"] .validity dl dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) td.tags dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail td.tags+dl:not(:first-of-type),.consul-upstream-instance-list .consul-bucket-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-bucket-list+dl:not(:first-of-type),.consul-upstream-instance-list .consul-bucket-list:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-exposed-path-list>ul>li>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-exposed-path-list>ul>li>.detail dl+dl:not(:first-of-type),.consul-upstream-instance-list .consul-exposed-path-list>ul>li>.detail dl.local-bind-address dd+dt+dd,.consul-upstream-instance-list .consul-exposed-path-list>ul>li>.detail dl.local-bind-socket-path dd+dt+dd,.consul-upstream-instance-list .consul-exposed-path-list>ul>li>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-instance-checks li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-instance-checks+dl:not(:first-of-type),.consul-upstream-instance-list .consul-instance-checks:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-lock-session-list dl li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-lock-session-list dl+dl:not(:first-of-type),.consul-upstream-instance-list .consul-lock-session-list dl:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),.consul-upstream-instance-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl.local-bind-address dd+dt+dd,.consul-upstream-instance-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl.local-bind-socket-path dd+dt+dd,.consul-upstream-instance-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-upstream-instance-list .list-collection>ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .list-collection>ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),.consul-upstream-instance-list .list-collection>ul>li:not(:first-child)>.detail dl.local-bind-address dd+dt+dd,.consul-upstream-instance-list .list-collection>ul>li:not(:first-child)>.detail dl.local-bind-socket-path dd+dt+dd,.consul-upstream-instance-list .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-upstream-instance-list .list-collection>ul>li:not(:first-child)>.detail li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .tag-list dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .tag-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .tag-list+dl:not(:first-of-type),.consul-upstream-instance-list .tag-list:not([class]) dl dd+dt:not([class])+dd,.consul-upstream-instance-list .tag-list:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list dl .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl .tag-list:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl dd+dt,.consul-upstream-instance-list dl li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl td.tags:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl+.consul-bucket-list:not(:first-of-type),.consul-upstream-instance-list dl+.consul-instance-checks:not(:first-of-type),.consul-upstream-instance-list dl+.tag-list:not(:first-of-type),.consul-upstream-instance-list dl+dl:not(:first-of-type),.consul-upstream-instance-list dl+td.tags:not(:first-of-type),.consul-upstream-instance-list dl.local-bind-address .consul-bucket-list dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address .consul-instance-checks dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address .consul-lock-session-list dl dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address .tag-list dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address section[data-route="dc.show.license"] .validity dl dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address td.tags dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path .consul-bucket-list dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path .consul-instance-checks dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path .consul-lock-session-list dl dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path .tag-list dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path section[data-route="dc.show.license"] .validity dl dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path td.tags dd+dt+dd,.consul-upstream-instance-list dl:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) .tag-list dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) td.tags dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail .consul-bucket-list+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail .consul-instance-checks+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail .consul-lock-session-list dl+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail .tag-list+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail dl .consul-bucket-list:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl .consul-instance-checks:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl .consul-lock-session-list dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl .tag-list:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl dd+dt,.consul-upstream-instance-list li>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl td.tags:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl+.consul-bucket-list:not(:first-of-type),.consul-upstream-instance-list li>.detail dl+.consul-instance-checks:not(:first-of-type),.consul-upstream-instance-list li>.detail dl+.tag-list:not(:first-of-type),.consul-upstream-instance-list li>.detail dl+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail dl+td.tags:not(:first-of-type),.consul-upstream-instance-list li>.detail dl.local-bind-address dd+dt+dd,.consul-upstream-instance-list li>.detail dl.local-bind-socket-path dd+dt+dd,.consul-upstream-instance-list li>.detail dl:not([class]) .consul-bucket-list dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) .consul-instance-checks dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) .consul-lock-session-list dl dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) .tag-list dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) section[data-route="dc.show.license"] .validity dl dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) td.tags dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail td.tags+dl:not(:first-of-type),.consul-upstream-instance-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),.consul-upstream-instance-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list section[data-route="dc.show.license"] .validity dl li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),.consul-upstream-instance-list section[data-route="dc.show.license"] .validity dl:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list td.tags dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list td.tags li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list td.tags+dl:not(:first-of-type),.consul-upstream-instance-list td.tags:not([class]) dl dd+dt:not([class])+dd,.consul-upstream-instance-list td.tags:not([class]) li>.detail dl dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail .consul-bucket-list+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail .consul-instance-checks+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail .consul-lock-session-list dl+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail .consul-upstream-instance-list dl+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.list-collection>ul>li:not(:first-child)>.detail .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.list-collection>ul>li:not(:first-child)>.detail .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail .tag-list+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail dl .consul-bucket-list:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl .consul-instance-checks:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl .consul-lock-session-list dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl .consul-upstream-instance-list dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl .tag-list:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl dd+dt,.list-collection>ul>li:not(:first-child)>.detail dl section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl td.tags:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl+.consul-bucket-list:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail dl+.consul-instance-checks:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail dl+.tag-list:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail dl+td.tags:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) .consul-bucket-list dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) .consul-instance-checks dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) .consul-lock-session-list dl dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) .consul-upstream-instance-list dl dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) .tag-list dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) section[data-route="dc.show.license"] .validity dl dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) td.tags dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail td.tags+dl:not(:first-of-type),.tag-list .consul-bucket-list:not([class]) dd+dt:not([class])+dd,.tag-list .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.tag-list .consul-instance-checks:not([class]) dd+dt:not([class])+dd,.tag-list .consul-lock-session-list dl:not([class]) dd+dt:not([class])+dd,.tag-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.tag-list .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.tag-list .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.tag-list .consul-upstream-instance-list dl:not([class]) dd+dt:not([class])+dd,.tag-list .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.tag-list .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.tag-list dd+dt,.tag-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,.tag-list section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,.tag-list td.tags:not([class]) dd+dt:not([class])+dd,.tag-list+.consul-bucket-list:not(:first-of-type),.tag-list+.consul-instance-checks:not(:first-of-type),.tag-list+.tag-list:not(:first-of-type),.tag-list+td.tags:not(:first-of-type),.tag-list:not([class]) .consul-bucket-list dd+dt:not([class])+dd,.tag-list:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,.tag-list:not([class]) .consul-instance-checks dd+dt:not([class])+dd,.tag-list:not([class]) .consul-lock-session-list dl dd+dt:not([class])+dd,.tag-list:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.tag-list:not([class]) .consul-upstream-instance-list dl dd+dt:not([class])+dd,.tag-list:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,.tag-list:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.tag-list:not([class]) dd+dt:not([class])+dd,.tag-list:not([class]) section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt:not([class])+dd,.tag-list:not([class]) section[data-route="dc.show.license"] .validity dl dd+dt:not([class])+dd,.tag-list:not([class]) td.tags dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-bucket-list+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-exposed-path-list>ul>li>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-exposed-path-list>ul>li>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-exposed-path-list>ul>li>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-instance-checks+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-lock-session-list dl ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-lock-session-list dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-lock-session-list dl:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-lock-session-list ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-lock-session-list ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list dl li>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list dl.local-bind-address dl dd+dt+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list dl.local-bind-socket-path dl dd+dt+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list dl:not([class]) li>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list li>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list li>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list li>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .list-collection>ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .list-collection>ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .tag-list dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .tag-list+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .tag-list:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .tag-list:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl td.tags:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+.consul-bucket-list:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+.consul-instance-checks:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+.tag-list:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+td.tags:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) .tag-list dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) td.tags dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header td.tags dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header td.tags+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header td.tags:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section[data-route="dc.show.license"] .validity header dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section[data-route="dc.show.license"] header .validity dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-bucket-list+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-exposed-path-list>ul>li>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-exposed-path-list>ul>li>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-exposed-path-list>ul>li>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-instance-checks+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-lock-session-list dl ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-lock-session-list dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-lock-session-list dl:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-lock-session-list ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-lock-session-list ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-upstream-instance-list dl li>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-upstream-instance-list dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-upstream-instance-list dl.local-bind-address dl dd+dt+dd,section[data-route="dc.show.license"] .validity .consul-upstream-instance-list dl.local-bind-socket-path dl dd+dt+dd,section[data-route="dc.show.license"] .validity .consul-upstream-instance-list dl:not([class]) li>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-upstream-instance-list li>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-upstream-instance-list li>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-upstream-instance-list li>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .list-collection>ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .list-collection>ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .tag-list dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .tag-list+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .tag-list:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,section[data-route="dc.show.license"] .validity dl .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,section[data-route="dc.show.license"] .validity dl .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl .tag-list:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl dd+dt,section[data-route="dc.show.license"] .validity dl td.tags:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl+.consul-bucket-list:not(:first-of-type),section[data-route="dc.show.license"] .validity dl+.consul-instance-checks:not(:first-of-type),section[data-route="dc.show.license"] .validity dl+.tag-list:not(:first-of-type),section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity dl+td.tags:not(:first-of-type),section[data-route="dc.show.license"] .validity dl:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) .tag-list dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) td.tags dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity td.tags dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity td.tags+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity td.tags:not([class]) dl dd+dt:not([class])+dd,td.tags .consul-bucket-list:not([class]) dd+dt:not([class])+dd,td.tags .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,td.tags .consul-instance-checks:not([class]) dd+dt:not([class])+dd,td.tags .consul-lock-session-list dl:not([class]) dd+dt:not([class])+dd,td.tags .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,td.tags .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,td.tags .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,td.tags .consul-upstream-instance-list dl:not([class]) dd+dt:not([class])+dd,td.tags .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,td.tags .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,td.tags .tag-list:not([class]) dd+dt:not([class])+dd,td.tags dd+dt,td.tags section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,td.tags section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,td.tags+.consul-bucket-list:not(:first-of-type),td.tags+.consul-instance-checks:not(:first-of-type),td.tags+.tag-list:not(:first-of-type),td.tags+td.tags:not(:first-of-type),td.tags:not([class]) .consul-bucket-list dd+dt:not([class])+dd,td.tags:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,td.tags:not([class]) .consul-instance-checks dd+dt:not([class])+dd,td.tags:not([class]) .consul-lock-session-list dl dd+dt:not([class])+dd,td.tags:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,td.tags:not([class]) .consul-upstream-instance-list dl dd+dt:not([class])+dd,td.tags:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,td.tags:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,td.tags:not([class]) .tag-list dd+dt:not([class])+dd,td.tags:not([class]) dd+dt:not([class])+dd,td.tags:not([class]) section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt:not([class])+dd,td.tags:not([class]) section[data-route="dc.show.license"] .validity dl dd+dt:not([class])+dd{margin-left:var(--horizontal-kv-list-separator-width)}.consul-bucket-list dt+dd,.consul-exposed-path-list>ul>li>.detail dl dt+dd,.consul-instance-checks dt+dd,.consul-lock-session-list dl dt+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl dt+dd,.consul-upstream-instance-list dl dt+dd,.consul-upstream-instance-list li>.detail dl dt+dd,.list-collection>ul>li:not(:first-child)>.detail dl dt+dd,.tag-list dt+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dt+dd,section[data-route="dc.show.license"] .validity dl dt+dd,td.tags dt+dd{margin-left:4px}.consul-bucket-list:not([class]) dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) dt:not([class])+dd,.consul-instance-checks:not([class]) dt:not([class])+dd,.consul-lock-session-list dl:not([class]) dt:not([class])+dd,.consul-upstream-instance-list dl.local-bind-address dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path dt+dd,.consul-upstream-instance-list dl:not([class]) dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dt:not([class])+dd,.tag-list:not([class]) dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) dt:not([class])+dd,td.tags:not([class]) dt:not([class])+dd{margin-left:0!important}.consul-lock-session-list .checks dd>:not(:last-child)::after,.discovery-chain .resolver-card ol>:not(:last-child)::after,.tag-list dd>:not(:last-child)::after,td.tags dd>:not(:last-child)::after{display:inline;content:var(--csv-list-separator);vertical-align:initial;margin-right:.3em}.freetext-filter_label::after,.tippy-box .tippy-arrow::before{content:"";position:absolute}.tag-list dt::before,td.tags dt::before{color:inherit;color:var(--token-color-foreground-faint)}.consul-exposed-path-list>ul>li>.detail dl>dt>*,.consul-lock-session-list ul>li:not(:first-child)>.detail dl>dt>*,.consul-upstream-instance-list li>.detail dl>dt>*,.list-collection>ul>li:not(:first-child)>.detail dl>dt>*{display:none}.consul-exposed-path-list>ul>li>.detail dl.passing dt::before,.consul-exposed-path-list>ul>li>.header .passing dd::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.passing dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .passing dd::before,.consul-upstream-instance-list li>.detail dl.passing dt::before,.consul-upstream-instance-list li>.header .passing dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.passing dt::before,.list-collection>ul>li:not(:first-child)>.header .passing dd::before{color:var(--token-color-foreground-success)}.consul-exposed-path-list>ul>li>.detail dl.warning dt::before,.consul-exposed-path-list>ul>li>.header .warning dd::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.warning dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .warning dd::before,.consul-upstream-instance-list li>.detail dl.warning dt::before,.consul-upstream-instance-list li>.header .warning dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.warning dt::before,.list-collection>ul>li:not(:first-child)>.header .warning dd::before{color:var(--token-color-foreground-warning)}.consul-exposed-path-list>ul>li>.detail dl.critical dt::before,.consul-exposed-path-list>ul>li>.header .critical dd::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.critical dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .critical dd::before,.consul-upstream-instance-list li>.detail dl.critical dt::before,.consul-upstream-instance-list li>.header .critical dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.critical dt::before,.list-collection>ul>li:not(:first-child)>.header .critical dd::before{color:var(--token-color-foreground-critical)}.consul-exposed-path-list>ul>li>.detail dl.empty dt::before,.consul-exposed-path-list>ul>li>.detail dl.unknown dt::before,.consul-exposed-path-list>ul>li>.header .empty dd::before,.consul-exposed-path-list>ul>li>.header .unknown dd::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.empty dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.unknown dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .empty dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header .unknown dd::before,.consul-upstream-instance-list li>.detail dl.empty dt::before,.consul-upstream-instance-list li>.detail dl.unknown dt::before,.consul-upstream-instance-list li>.header .empty dd::before,.consul-upstream-instance-list li>.header .unknown dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.empty dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.unknown dt::before,.list-collection>ul>li:not(:first-child)>.header .empty dd::before,.list-collection>ul>li:not(:first-child)>.header .unknown dd::before{color:var(--token-color-foreground-faint)}.consul-exposed-path-list>ul>li>.header [rel=me] dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header [rel=me] dd::before,.consul-upstream-instance-list li>.header [rel=me] dd::before,.list-collection>ul>li:not(:first-child)>.header [rel=me] dd::before{color:var(--token-color-foreground-action)}.app-view>div form:not(.filter-bar) [role=radiogroup] label>em>code,.modal-dialog [role=document] .type-password>em>code,.modal-dialog [role=document] .type-select>em>code,.modal-dialog [role=document] .type-text>em>code,.modal-dialog [role=document] [role=radiogroup] label>em>code,.modal-dialog [role=document] form button+em>code,.modal-dialog [role=document] p code,.oidc-select label>em>code,.type-toggle>em>code,main .type-password>em>code,main .type-select>em>code,main .type-text>em>code,main form button+em>code,main p code{border:1px solid;color:var(--token-color-consul-brand);background-color:var(--token-color-surface-strong);border-color:var(--token-color-surface-interactive-active);display:inline-block;padding:0 4px}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{outline:0;background-color:var(--token-color-surface-primary);border-radius:var(--decor-radius-100)}[data-animation=fade][data-state=hidden].tippy-box{opacity:0}[data-inertia][data-state=visible].tippy-box{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-box .tippy-arrow{--size:5px}[data-placement^=top].tippy-box>.tippy-arrow{bottom:0}[data-placement^=top].tippy-box>.tippy-arrow::before{left:0;bottom:calc(0px - var(--size));transform-origin:center top}[data-placement^=bottom].tippy-box>.tippy-arrow{top:0}[data-placement^=bottom].tippy-box>.tippy-arrow::before{left:0;top:calc(0px - var(--size));transform-origin:center bottom}[data-placement^=left].tippy-box>.tippy-arrow{right:0}[data-placement^=left].tippy-box>.tippy-arrow::before{right:calc(0px - var(--size));transform-origin:center left}[data-placement^=right].tippy-box>.tippy-arrow{left:0}[data-placement^=right].tippy-box>.tippy-arrow::before{left:calc(0px - var(--size));transform-origin:center right}[data-theme~=square-tail] .tippy-arrow{--size:18px;left:calc(0px - var(--size)/ 2)!important}[data-theme~=square-tail] .tippy-arrow::before{background-color:var(--token-color-surface-primary);width:calc(1px + var(--size));height:calc(1px + var(--size));border:var(--decor-border-100);border-color:var(--token-color-palette-neutral-300)}[data-theme~=square-tail] .tippy-arrow::after{position:absolute;left:1px}[data-theme~=square-tail][data-placement^=top]{bottom:-10px}[data-theme~=square-tail][data-placement^=top] .informed-action{border-bottom-left-radius:0!important}[data-theme~=square-tail][data-placement^=top] .tippy-arrow::before{border-bottom-left-radius:var(--decor-radius-200);border-bottom-right-radius:var(--decor-radius-200);border-top:0!important}[data-theme~=square-tail][data-placement^=top] .tippy-arrow::after{bottom:calc(0px - var(--size))}[data-theme~=square-tail][data-placement^=bottom]{top:-10px}[data-theme~=square-tail][data-placement^=bottom] .informed-action{border-top-left-radius:0!important}[data-theme~=square-tail][data-placement^=bottom] .tippy-arrow::before{border-top-left-radius:var(--decor-radius-200);border-top-right-radius:var(--decor-radius-200);border-bottom:0!important}[data-theme~=square-tail][data-placement^=bottom] .tippy-arrow::after{top:calc(0px - var(--size))}.tippy-box[data-theme~=tooltip] .tippy-content{padding:12px;max-width:224px;position:relative;z-index:1}.tippy-box[data-theme~=tooltip]{background-color:var(--token-color-foreground-faint)}.tippy-box[data-theme~=tooltip] .tippy-arrow{--size:5px;color:var(--token-color-foreground-faint);width:calc(var(--size) * 2);height:calc(var(--size) * 2)}.tippy-box[data-theme~=tooltip] .tippy-arrow::before{border-color:transparent;border-style:solid}.tippy-box[data-theme~=tooltip][data-placement^=top]>.tippy-arrow::before{border-width:var(--size) var(--size) 0;border-top-color:initial}.tippy-box[data-theme~=tooltip][data-placement^=bottom]>.tippy-arrow::before{border-width:0 var(--size) var(--size);border-bottom-color:initial}.tippy-box[data-theme~=tooltip][data-placement^=left]>.tippy-arrow::before{border-width:var(--size) 0 var(--size) var(--size);border-left-color:initial}.tippy-box[data-theme~=tooltip][data-placement^=right]>.tippy-arrow::before{border-width:var(--size) var(--size) var(--size) 0;border-right-color:initial}.warning.modal-dialog header{background-color:var(--token-color-vault-gradient-faint-start);border-color:var(--token-color-vault-brand);color:var(--token-color-vault-foreground)}.warning.modal-dialog header::before{color:var(--token-color-vault-brand);float:left;margin-top:2px;margin-right:3px}.modal-dialog>div:first-child{background-color:var(--token-color-surface-interactive);opacity:.9}.modal-dialog [role=document]>footer,.modal-dialog [role=document]>header,.modal-dialog-body{border-color:var(--token-color-palette-neutral-300)}.modal-dialog-body{border-style:solid;border-left-width:1px;border-right-width:1px}.modal-layer{height:0}.modal-dialog [role=document] table{height:150px!important}.modal-dialog [role=document] tbody{max-height:100px}.modal-dialog table{min-height:149px}.modal-dialog,.modal-dialog>div:first-child{position:fixed;top:0;right:0;bottom:0;left:0}.modal-dialog{z-index:500;align-items:center;justify-content:center;height:100%}[aria-hidden=true].modal-dialog{display:none}.modal-dialog [role=document]{background-color:var(--token-color-surface-primary);margin:auto;z-index:2;max-width:855px;position:relative}.modal-dialog [role=document]>*{padding-left:15px;padding-right:15px}.modal-dialog [role=document]>div{overflow-y:auto;max-height:80vh;padding:20px 23px}.modal-dialog [role=document]>footer,.modal-dialog [role=document]>header{border-width:1px;padding-top:12px;padding-bottom:10px}.modal-dialog [role=document]>header{position:relative}.modal-dialog [role=document]>header button{float:right;margin-top:-3px}.list-collection>ul{border-top:1px solid;border-color:var(--token-color-surface-interactive-active)}.list-collection>button{cursor:pointer;background-color:var(--token-color-surface-strong);color:var(--token-color-foreground-action);width:100%;padding:15px}.list-collection-scroll-virtual,.list-collection>ul>li{position:relative}.list-collection-scroll-virtual{height:500px}.filter-bar{background-color:var(--token-color-foreground-high-contrast);border-bottom:var(--decor-border-100);border-color:var(--token-color-surface-interactive-active);padding:4px 8px}.filter-bar .filters .popover-menu>[type=checkbox]:checked+label button,.filter-bar .sort .popover-menu>[type=checkbox]:checked+label button{color:var(--token-color-foreground-action);background-color:var(--token-color-foreground-high-contrast)}.filter-bar .sort{margin-left:auto}.filter-bar .popover-select{position:relative;z-index:3}.filter-bar .popover-menu>[type=checkbox]+label button{padding-left:1.5rem!important;padding-right:1.5rem!important}.filter-bar .popover-menu [role=menuitem]{justify-content:normal!important}@media (max-width:1379px){.filter-bar,.filter-bar>div{flex-wrap:wrap}.filter-bar .search{position:relative;z-index:4;width:100%;margin-bottom:.3rem}}@media (max-width:995px){.filter-bar .filters,.filter-bar .sort{display:none}}html[data-route^="dc.acls.index"] .filter-bar{color:inherit}.freetext-filter{border:var(--decor-border-100);border-radius:var(--decor-radius-100);background-color:var(--token-color-surface-primary);border-color:var(--token-color-surface-interactive-active);color:var(--token-color-foreground-disabled)}.freetext-filter:hover,.freetext-filter:hover *{border-color:var(--token-color-foreground-disabled)}.freetext-filter_input::-moz-placeholder{cursor:inherit;color:inherit;border-color:inherit}.freetext-filter *,.freetext-filter_input::placeholder{cursor:inherit;color:inherit;border-color:inherit}.freetext-filter_input{-webkit-appearance:none;border:none}.freetext-filter_label::after{visibility:visible;--icon-name:icon-search;top:50%;left:50%;width:16px;height:16px;margin-left:-8px;margin-top:-8px}.freetext-filter .popover-menu{background-color:var(--token-color-surface-strong);color:var(--token-color-foreground-primary);border-left:1px solid;border-color:inherit}.freetext-filter .popover-menu>[type=checkbox]:checked+label button{background-color:var(--token-color-surface-interactive-active)}.freetext-filter{--height:2.2rem;display:flex;position:relative;height:var(--height);width:100%}.freetext-filter_input,.freetext-filter_label{height:100%}.freetext-filter_input{padding:8px 10px;padding-left:var(--height);min-width:12.7rem;width:100%}.freetext-filter_label{visibility:hidden;position:absolute;z-index:1;width:var(--height)}.informed-action{border-radius:var(--decor-radius-200);border:var(--decor-border-100);border-color:var(--token-color-palette-neutral-300);background-color:var(--token-color-surface-primary);min-width:190px}.informed-action>div{border-top-left-radius:var(--decor-radius-200);border-top-right-radius:var(--decor-radius-200);cursor:default;padding:1rem}.informed-action p{color:var(--token-color-hashicorp-brand)}.informed-action>ul>li>:focus,.informed-action>ul>li>:hover{background-color:var(--token-color-surface-strong)}.info.informed-action header{color:var(--token-color-foreground-action-active)}.info.informed-action header::before{background-color:var(--token-color-foreground-action);margin-right:5px}.info.informed-action>div{background-color:var(--token-color-surface-action)}.dangerous.informed-action header{color:var(--token-color-palette-red-400)}.dangerous.informed-action header::before{background-color:var(--token-color-foreground-critical)}.dangerous.informed-action>div{background-color:var(--token-color-surface-critical)}.warning.informed-action header{color:var(--token-color-foreground-warning-on-surface)}.warning.informed-action header::before{background-color:var(--token-color-vault-brand);margin-right:5px}.warning.informed-action>div{background-color:var(--token-color-vault-gradient-faint-start)}.copyable-code::after,.tab-nav li:not(.selected)>:active,.tab-nav li:not(.selected)>:focus,.tab-nav li:not(.selected)>:hover{background-color:var(--token-color-surface-strong)}.informed-action>ul>.action>*{color:var(--token-color-foreground-action)}.documentation.informed-action{min-width:270px}.informed-action header::before{float:left;margin-right:5px}.informed-action>ul{list-style:none;display:flex;margin:0;padding:4px}.informed-action>ul>li{width:50%}.informed-action>ul>li>*{width:100%}.tab-nav ul{list-style-type:none;display:inline-flex;align-items:center;position:relative;padding:0;margin:0}.tab-nav li>:not(:disabled){cursor:pointer}.tab-nav{border-bottom:var(--decor-border-100)}.animatable.tab-nav ul::after,.tab-nav li>*{border-bottom:var(--decor-border-300)}.tab-nav{border-color:var(--token-color-surface-interactive-active);clear:both;overflow:auto}.tab-nav li>*{white-space:nowrap;text-decoration:none;transition-property:background-color,border-color;border-color:transparent;color:var(--token-color-foreground-faint);display:inline-block;padding:16px 13px}.tab-nav li:not(.selected)>:focus,.tab-nav li:not(.selected)>:hover{border-color:var(--token-color-palette-neutral-300)}.animatable.tab-nav .selected a{border-color:transparent!important}.animatable.tab-nav ul::after{position:absolute;bottom:0;height:0;border-top:0;width:calc(var(--selected-width,0) * 1px);transform:translate(calc(var(--selected-left,0) * 1px),0);transition-property:transform,width}.search-bar-status{border-bottom:var(--decor-border-100);border-bottom-color:var(--token-color-surface-interactive-active);padding:.5rem 0 .5rem .5rem}.search-bar-status li:not(.remove-all) button::before{color:var(--token-color-foreground-faint);margin-top:1px;margin-right:.2rem}.search-bar-status dt::after{content:":";padding-right:.3rem}.search-bar-status>dl>dt{float:left}.search-bar-status dt{white-space:nowrap}.search-bar-status li{display:inline-flex}.search-bar-status li:not(:last-child){margin-right:.3rem;margin-bottom:.3rem}.search-bar-status li:not(.remove-all){border:var(--decor-border-100);border-color:var(--token-color-surface-interactive-active);color:var(--token-color-foreground-faint);padding:0 .2rem}.search-bar-status li:not(.remove-all) dl{display:flex}.search-bar-status li:not(.remove-all) button{cursor:pointer;padding:0}.copyable-code{display:flex;align-items:flex-start;position:relative;width:100%;padding:8px 14px 3px;border:var(--decor-border-100);border-color:var(--token-color-surface-interactive-active);border-radius:var(--decor-radius-200)}.copyable-code.obfuscated{padding-left:4px}.copyable-code::after{position:absolute;top:0;right:0;width:40px;height:100%;display:block;content:""}.copyable-code .copy-button{position:absolute;top:0;right:0;z-index:1}.copyable-code .copy-button button{width:40px;height:40px}.copyable-code .copy-button button:empty::after{display:none}.copyable-code button[aria-expanded]{margin-top:1px;margin-right:4px;cursor:pointer}.copyable-code button[aria-expanded]::before{content:"";--icon-size:icon-000;--icon-color:var(--token-color-foreground-faint)}.copyable-code button[aria-expanded=true]::before{--icon-name:icon-eye-off}.copyable-code button[aria-expanded=false]::before{--icon-name:icon-eye}.copyable-code pre{padding-right:30px}.copyable-code code{display:inline-block;overflow:hidden;text-overflow:ellipsis;width:100%}.copyable-code hr{width:calc(100% - 80px);margin:8px 0 13px;border:3px dashed var(--token-color-palette-neutral-300);background-color:var(--token-color-surface-primary)}.consul-loader circle{fill:var(--token-color-consul-gradient-faint-stop);animation:loader-animation 1.5s infinite ease-in-out;transform-origin:50% 50%}.consul-loader g:nth-last-child(2) circle{animation-delay:.2s}.consul-loader g:nth-last-child(3) circle{animation-delay:.3s}.consul-loader g:nth-last-child(4) circle{animation-delay:.4s}.consul-loader g:nth-last-child(5) circle{animation-delay:.5s}@keyframes loader-animation{0%,100%{transform:scale3D(1,1,1)}33%{transform:scale3D(0,0,1)}}.consul-loader{display:flex;align-items:center;justify-content:center;height:100%;position:absolute;width:100%;top:0;margin-top:0!important}.tomography-graph .background{fill:var(--token-color-surface-strong)}.tomography-graph .axis{fill:none;stroke:var(--token-color-palette-neutral-300);stroke-dasharray:4 4}.tomography-graph .border{fill:none;stroke:var(--token-color-palette-neutral-300)}.tomography-graph .point{stroke:var(--token-color-foreground-disabled);fill:var(--token-color-consul-foreground)}.tomography-graph .lines rect{fill:var(--token-color-consul-foreground);stroke:transparent;stroke-width:5px}.tomography-graph .lines rect:hover{fill:var(--token-color-palette-neutral-300);height:3px;y:-1px}.tomography-graph .tick line{stroke:var(--token-color-palette-neutral-300)}.tomography-graph .tick text{text-anchor:start}.discovery-chain .resolver-card,.discovery-chain .route-card,.discovery-chain .splitter-card,.discovery-chain path{transition-duration:.1s;transition-timing-function:linear;cursor:pointer}.discovery-chain path{transition-property:stroke;fill:none;stroke:var(--token-color-foreground-disabled);stroke-width:2;vector-effect:non-scaling-stroke}#downstream-lines svg circle,#upstream-lines svg circle,.discovery-chain circle{fill:var(--token-color-surface-primary)}.discovery-chain .resolver-card,.discovery-chain .resolver-card a,.discovery-chain .route-card,.discovery-chain .route-card a,.discovery-chain .splitter-card,.discovery-chain .splitter-card a{color:var(--token-color-foreground-strong)!important}.discovery-chain path:focus,.discovery-chain path:hover{stroke:var(--token-color-foreground-strong)}.discovery-chain .resolvers,.discovery-chain .routes,.discovery-chain .splitters{border-radius:var(--decor-radius-100);border:1px solid;border-color:var(--token-color-surface-interactive-active);background-color:var(--token-color-surface-strong);pointer-events:none}.discovery-chain .resolver-card,.discovery-chain .resolvers>header span,.discovery-chain .route-card,.discovery-chain .routes>header span,.discovery-chain .splitter-card,.discovery-chain .splitters>header span{pointer-events:all}.discovery-chain .resolvers>header>*,.discovery-chain .routes>header>*,.discovery-chain .splitters>header>*{text-transform:uppercase}.discovery-chain .resolvers>header span::after,.discovery-chain .routes>header span::after,.discovery-chain .splitters>header span::after{width:1.2em;height:1.2em;opacity:.6}.discovery-chain .resolver-card,.discovery-chain .route-card,.discovery-chain .splitter-card{transition-property:opacity background-color border-color;margin-top:0!important}.discovery-chain [id*=":"]:not(path):hover{opacity:1;background-color:var(--token-color-surface-primary);border-color:var(--token-color-foreground-faint)}.discovery-chain .route-card header:not(.short) dd{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.discovery-chain .route-card section header>*{visibility:hidden}.discovery-chain .route-card .match-headers header ::before{content:"H"}.discovery-chain .route-card .match-queryparams header>::before{content:"Q"}.discovery-chain .resolver-card dt::before{content:"";--icon-size:icon-999}.discovery-chain .resolver-card dl.failover dt::before{--icon-name:icon-cloud-cross}.discovery-chain .resolver-card dl.redirect dt::before{--icon-name:icon-redirect}.discovery-chain circle{stroke-width:2;stroke:var(--token-color-foreground-disabled)}.discovery-chain{position:relative;display:flex;justify-content:space-between}.discovery-chain svg{position:absolute}.discovery-chain .resolvers,.discovery-chain .routes,.discovery-chain .splitters{padding:10px 1%;width:32%}.discovery-chain .resolvers>header,.discovery-chain .routes>header,.discovery-chain .splitters>header{height:18px}.discovery-chain .resolvers>header span,.discovery-chain .routes>header span,.discovery-chain .splitters>header span{position:relative;z-index:1;margin-left:2px}.discovery-chain .resolvers [role=group],.discovery-chain .routes [role=group],.discovery-chain .splitters [role=group]{position:relative;z-index:1;display:flex;flex-direction:column;justify-content:space-around;height:100%}.discovery-chain .resolver-card dl,.discovery-chain .route-card dl,.discovery-chain .splitter-card dl{margin:0;float:none}.discovery-chain .resolver-card,.discovery-chain .route-card,.discovery-chain .splitter-card{margin-bottom:20px}.discovery-chain .route-card header.short dl{display:flex}.discovery-chain .route-card header.short dt::after{content:" ";display:inline-block}.discovery-chain .route-card>header ul{float:right;margin-top:-2px}.discovery-chain .route-card>header ul li{margin-left:5px}.discovery-chain .route-card section{display:flex}.discovery-chain .route-card section header{display:block;width:19px;margin-right:14px}.discovery-chain .resolver-card a{display:block}.discovery-chain .resolver-card dl{display:flex;flex-wrap:wrap;margin-top:5px}.discovery-chain .resolver-card dt{font-size:0;margin-right:6px;margin-top:1px;width:23px;height:20px}.discovery-chain .resolver-card ol{display:flex;flex-wrap:wrap;list-style-type:none}.discovery-chain .route-card,.discovery-chain .splitter-card{position:relative}.discovery-chain .route-card::before,.discovery-chain .splitter-card::before{background-color:var(--token-color-surface-primary);border-radius:var(--decor-radius-full);border:2px solid;border-color:var(--token-color-foreground-disabled);position:absolute;z-index:1;right:-5px;top:50%;margin-top:-5px;width:10px;height:10px}.discovery-chain .resolver-inlets,.discovery-chain .splitter-inlets{width:10px;height:100%;z-index:1}.discovery-chain .splitter-inlets{left:50%;margin-left:calc(-15% - 3px)}.discovery-chain .resolver-inlets{right:calc(31% - 7px)}.consul-bucket-list dd:not(:last-child)::after{display:inline-block;content:"/";margin:0 6px 0 3px}.consul-bucket-list .service+dd,.consul-bucket-list dd+dt{margin-left:0!important}.consul-upstream-instance-list dl.local-bind-socket-mode dt{text-transform:lowercase;font-weight:var(--token-typography-font-weight-semibold)}.consul-health-check-list .health-check-output::before{min-width:20px;min-height:20px;margin-right:15px}@media (max-width:650px){.consul-health-check-list .health-check-output::before{min-width:18px;min-height:18px;margin-right:8px}}.consul-health-check-list .health-check-output dd em{background-color:var(--token-color-surface-strong);cursor:default;font-style:normal;margin-top:-2px;margin-left:.5em}.consul-health-check-list .passing.health-check-output::before{color:var(--token-color-foreground-success)}.consul-health-check-list .warning.health-check-output::before{color:var(--token-color-foreground-warning)}.consul-health-check-list .critical.health-check-output::before{color:var(--token-color-foreground-critical)}.consul-health-check-list .health-check-output,.consul-health-check-list .health-check-output pre{border-radius:var(--decor-radius-100)}.consul-health-check-list .health-check-output dd:first-of-type{color:var(--token-color-foreground-disabled)}.consul-health-check-list .health-check-output pre{background-color:var(--token-color-surface-strong);color:var(--token-color-foreground-faint)}.consul-health-check-list .health-check-output{border-width:1px 1px 1px 4px;color:var(--token-color-foreground-strong);border-color:var(--token-color-surface-interactive-active);border-style:solid;display:flex;padding:20px 24px 20px 16px}.consul-health-check-list .passing.health-check-output{border-left-color:var(--token-color-foreground-success)}.consul-health-check-list .warning.health-check-output{border-left-color:var(--token-color-vault-brand)}.consul-health-check-list .critical.health-check-output{border-left-color:var(--token-color-foreground-critical)}.consul-health-check-list .health-check-output:not(:last-child){margin-bottom:24px}.consul-health-check-list .health-check-output dl:last-of-type,.consul-health-check-list .health-check-output header{width:100%}.consul-health-check-list .health-check-output header{margin-bottom:.9em}.consul-health-check-list .health-check-output>div{flex:1 1 auto;width:calc(100% - 26px);display:flex;flex-wrap:wrap;justify-content:space-between}.consul-health-check-list .health-check-output dl{min-width:110px}.consul-health-check-list .health-check-output dl>*{display:block;width:auto;position:static;padding-left:0}.consul-health-check-list .health-check-output dt{margin-bottom:0}.consul-health-check-list .health-check-output dd{position:relative}.consul-health-check-list .health-check-output dl:nth-last-of-type(2){width:50%}.consul-health-check-list .health-check-output dl:last-of-type{margin-top:1em;margin-bottom:0}.consul-health-check-list .health-check-output dl:last-of-type dt{margin-bottom:.3em}.consul-health-check-list .health-check-output pre{padding:12px 40px 12px 12px;white-space:pre-wrap;position:relative}.consul-health-check-list .health-check-output pre code{word-wrap:break-word}.consul-health-check-list .health-check-output .copy-button{position:absolute;right:.5em;top:.7em}@media (max-width:650px){.consul-health-check-list .health-check-output{padding:15px 19px 15px 14px}.consul-health-check-list .health-check-output::before{margin-right:8px}.consul-health-check-list .health-check-output dl:nth-last-of-type(2){width:100%}.consul-health-check-list .health-check-output dl:not(:last-of-type){margin-right:0}}.consul-instance-checks.passing dt::before{color:var(--token-color-foreground-success)}.consul-instance-checks.warning dt::before{color:var(--token-color-foreground-warning)}.consul-instance-checks.critical dt::before{color:var(--token-color-foreground-critical)}.consul-instance-checks.empty dt::before{color:var(--token-color-foreground-faint)}.consul-exposed-path-list>ul{border-top:1px solid var(--token-color-surface-interactive-active)}.consul-external-source::before,.consul-kind::before{--icon-size:icon-300}.consul-intention-list td.intent- strong::before,.consul-intention-list td.intent-allow strong::before,.consul-intention-list td.intent-deny strong::before,.consul-intention-permission-list .intent-allow::before,.consul-intention-permission-list .intent-deny::before,.consul-intention-search-bar .value- span::before,.consul-intention-search-bar .value-allow span::before,.consul-intention-search-bar .value-deny span::before{margin-right:5px}.consul-intention-list td.intent- strong,.consul-intention-list td.intent-allow strong,.consul-intention-list td.intent-deny strong,.consul-intention-permission-list .intent-allow,.consul-intention-permission-list .intent-deny,.consul-intention-search-bar .value- span,.consul-intention-search-bar .value-allow span,.consul-intention-search-bar .value-deny span{font-weight:var(--token-typography-font-weight-regular);font-size:var(--token-typography-body-200-font-size);display:inline-block}.consul-intention-list td.intent-allow strong,.consul-intention-permission-list .intent-allow,.consul-intention-search-bar .value-allow span{color:var(--token-color-foreground-success-on-surface);background-color:var(--token-color-border-success)}.consul-intention-list td.intent-deny strong,.consul-intention-permission-list .intent-deny,.consul-intention-search-bar .value-deny span{color:var(--token-color-foreground-critical-on-surface);background-color:var(--token-color-border-critical)}.consul-intention-list td.permissions{color:var(--token-color-foreground-action)}.consul-intention-list em{--word-spacing:0.25rem}.consul-intention-list em span::before,.consul-intention-list em span:first-child{margin-right:var(--word-spacing)}.consul-intention-list em span:last-child{margin-left:var(--word-spacing)}.consul-intention-list td{height:59px}.consul-intention-list tr>:nth-child(1){width:calc(30% - 50px)}.consul-intention-list tr>:nth-child(2){width:120px}.consul-intention-list tr>:nth-child(3){width:calc(30% - 50px)}.consul-intention-list tr>:nth-child(4){width:calc(40% - 240px)}.consul-intention-list tr>:nth-child(5){width:160px}.consul-intention-list tr>:last-child{width:60px}.consul-intention-list .menu-panel.confirmation{width:200px}@media (max-width:849px){.consul-intention-list tr>:not(.source):not(.destination):not(.intent){display:none}}.consul-intention-action-warn-modal .modal-dialog-window{max-width:450px}.consul-intention-fieldsets [role=radiogroup]{overflow:visible!important;display:grid;grid-gap:12px;grid-template-columns:repeat(auto-fit,minmax(270px,auto))}.consul-intention-fieldsets .radio-card header>*{display:inline}.consul-intention-fieldsets .permissions>button{float:right}.consul-intention-permission-modal [role=dialog]{width:100%}.consul-intention-permission-list dl.permission-methods dt::before{content:"M"}.consul-intention-permission-list dl.permission-path dt::before{content:"P"}.consul-intention-permission-header-list dt::before,.consul-intention-permission-list dl.permission-header dt::before{content:"H"}.consul-intention-permission-list .detail>div{display:flex;width:100%}.consul-intention-permission-list strong{margin-right:8px}.consul-intention-permission-form h2{border-top:1px solid var(--token-color-foreground-action);padding-top:1.4em;margin-top:.2em;margin-bottom:.6em}.consul-intention-permission-form .consul-intention-permission-header-form{margin-top:10px}.consul-intention-permission-form .consul-intention-permission-header-form fieldset>div,.consul-intention-permission-form fieldset:nth-child(2)>div{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));grid-gap:12px}.consul-intention-permission-form fieldset:nth-child(2)>div label:last-child{grid-column:span 2}.consul-intention-permission-form .ember-basic-dropdown-trigger{padding:5px}.consul-intention-permission-form .checkbox-group{flex-direction:column}.consul-intention-permission-header-list{max-height:200px;overflow:auto}.consul-lock-session-list button{margin-right:var(--horizontal-padding)}.consul-lock-session-form{overflow:hidden}.consul-server-list ul{display:grid;grid-template-columns:repeat(4,minmax(215px,25%));gap:12px}.consul-server-list a:hover div{--tone-border:var(--token-color-foreground-faint)}.consul-server-card .name+dd{color:var(--token-color-hashicorp-brand);animation-name:typo-truncate}.voting-status-non-voter.consul-server-card .health-status+dd{background-color:var(--token-color-surface-strong);color:var(--token-color-foreground-faint)}.consul-server-card:not(.voting-status-non-voter) .health-status.healthy+dd{background-color:var(--token-color-surface-success);color:var(--token-color-palette-green-400)}.consul-server-card:not(.voting-status-non-voter) .health-status:not(.healthy)+dd{background-color:var(--token-color-surface-critical);color:var(--token-color-foreground-critical)}.consul-server-card .health-status+dd::before{--icon-size:icon-000;content:""}.consul-server-card .health-status.healthy+dd::before{--icon-name:icon-check}.consul-server-card .health-status:not(.healthy)+dd::before{--icon-name:icon-x}.consul-server-card{position:relative;overflow:hidden;--padding-x:24px;--padding-y:24px;padding:var(--padding-y) var(--padding-x);--tile-size:3rem}.consul-auth-method-binding-list h2,.consul-auth-method-view section h2{padding-bottom:12px}.voting-status-leader.consul-server-card .name{position:absolute!important}.consul-server-card dd:not(:last-of-type){margin-bottom:calc(var(--padding-y)/ 2)}.voting-status-leader.consul-server-card dd{margin-left:calc(var(--tile-size) + 1rem)}.consul-auth-method-list ul .locality::before{margin-right:4px}.consul-auth-method-view{margin-bottom:32px}.consul-auth-method-view section{width:100%;position:relative;overflow-y:auto}.consul-auth-method-view section table thead td{color:var(--token-color-foreground-faint)}.consul-auth-method-view section table tbody td{color:var(--token-color-hashicorp-brand)}.consul-auth-method-view section table tbody tr{cursor:default}.consul-auth-method-view section table tbody tr:hover{box-shadow:none}.consul-auth-method-view section dt{width:30%}.consul-auth-method-view section dd{width:70%}.consul-auth-method-binding-list p{margin-bottom:4px!important}.consul-auth-method-binding-list code{background-color:var(--token-color-surface-strong);padding:0 12px}.consul-auth-method-nspace-list thead td{color:var(--token-color-foreground-faint)!important}.consul-auth-method-nspace-list tbody td{color:var(--token-color-hashicorp-brand)}.consul-auth-method-nspace-list tbody tr{cursor:default}.consul-auth-method-nspace-list tbody tr:hover{box-shadow:none}.role-selector [name="role[state]"],.role-selector [name="role[state]"]+*{display:none}.role-selector [name="role[state]"]:checked+*{display:block}.topology-notices button{color:var(--token-color-foreground-action);float:right;margin-top:16px;margin-bottom:32px}#metrics-container .link a,.topology-container{color:var(--token-color-foreground-faint)}#downstream-container .topology-metrics-card:not(:last-child),#upstream-column #upstream-container:not(:last-child),#upstream-container .topology-metrics-card:not(:last-child){margin-bottom:8px}#downstream-container,#metrics-container,#upstream-container{border-radius:var(--decor-radius-100);border:1px solid;border-color:var(--token-color-surface-interactive-active)}#downstream-container,#upstream-container{background-color:var(--token-color-surface-strong);padding:12px}#downstream-container>div:first-child{display:inline-flex}#downstream-container>div:first-child span::before{background-color:var(--token-color-foreground-faint)}#metrics-container div:first-child{background-color:var(--token-color-surface-primary);padding:12px;border:none}#metrics-container .link{background-color:var(--token-color-surface-strong);padding:18px}#metrics-container .link a:hover{color:var(--token-color-foreground-action)}#downstream-lines svg path,#upstream-lines svg path{fill:transparent}#downstream-lines svg .allow-arrow,#upstream-lines svg .allow-arrow{fill:var(--token-color-palette-neutral-300);stroke-linejoin:round}#downstream-lines svg .allow-arrow,#downstream-lines svg .allow-dot,#downstream-lines svg path,#upstream-lines svg .allow-arrow,#upstream-lines svg .allow-dot,#upstream-lines svg path{stroke:var(--token-color-palette-neutral-300);stroke-width:2}#downstream-lines svg path[data-permission=empty],#downstream-lines svg path[data-permission=not-defined],#upstream-lines svg path[data-permission=empty],#upstream-lines svg path[data-permission=not-defined]{stroke-dasharray:4}#downstream-lines svg path[data-permission=deny],#upstream-lines svg path[data-permission=deny]{stroke:var(--token-color-foreground-critical)}#downstream-lines svg .deny-dot,#upstream-lines svg .deny-dot{stroke:var(--token-color-foreground-critical);stroke-width:2}#downstream-lines svg .deny-arrow,#upstream-lines svg .deny-arrow{fill:var(--token-color-foreground-critical);stroke:var(--token-color-foreground-critical);stroke-linejoin:round}.topology-notices{display:flow-root}.topology-container{display:grid;height:100%;align-items:start;grid-template-columns:2fr 1fr 2fr 1fr 2fr;grid-template-rows:50px 1fr 50px;grid-template-areas:"down-cards down-lines . up-lines up-cards" "down-cards down-lines metrics up-lines up-cards" "down-cards down-lines . up-lines up-cards"}#downstream-container{grid-area:down-cards}#downstream-lines{grid-area:down-lines;margin-left:-20px}#upstream-lines{grid-area:up-lines;margin-right:-20px}#upstream-column{grid-area:up-cards}#downstream-lines,#upstream-lines{position:relative}#metrics-container{grid-area:metrics}#metrics-container .link a::before{background-color:var(--token-color-foreground-faint);margin-right:4px}#downstream-container .topology-metrics-card,#upstream-container .topology-metrics-card{display:block;color:var(--token-color-foreground-faint);overflow:hidden;background-color:var(--token-color-surface-primary);border-radius:var(--decor-radius-100);border:1px solid;border-color:var(--token-color-surface-interactive-active)}#downstream-container .topology-metrics-card p,#upstream-container .topology-metrics-card p{padding:12px 12px 0;margin-bottom:0!important}#downstream-container .topology-metrics-card p.empty,#upstream-container .topology-metrics-card p.empty{padding:12px!important}#downstream-container .topology-metrics-card div dl,#upstream-container .topology-metrics-card div dl{display:inline-flex;margin-right:8px}#downstream-container .topology-metrics-card div dd,#upstream-container .topology-metrics-card div dd{color:var(--token-color-foreground-faint)}#downstream-container .topology-metrics-card div span,#upstream-container .topology-metrics-card div span{margin-right:8px}#downstream-container .topology-metrics-card div dt::before,#downstream-container .topology-metrics-card div span::before,#upstream-container .topology-metrics-card div dt::before,#upstream-container .topology-metrics-card div span::before{margin-right:4px}#downstream-container .topology-metrics-card div .health dt::before,#downstream-container .topology-metrics-card div .nspace dt::before,#upstream-container .topology-metrics-card div .health dt::before,#upstream-container .topology-metrics-card div .nspace dt::before{margin-top:2px}#downstream-container .topology-metrics-card div .health dt::before,#downstream-container .topology-metrics-card div .nspace dt::before,#downstream-container .topology-metrics-card div .partition dt::before,#upstream-container .topology-metrics-card div .health dt::before,#upstream-container .topology-metrics-card div .nspace dt::before,#upstream-container .topology-metrics-card div .partition dt::before{--icon-color:var(--token-color-foreground-faint)}#downstream-container .topology-metrics-card div .passing::before,#upstream-container .topology-metrics-card div .passing::before{--icon-color:var(--token-color-foreground-success)}#downstream-container .topology-metrics-card div .warning::before,#upstream-container .topology-metrics-card div .warning::before{--icon-color:var(--token-color-foreground-warning)}#downstream-container .topology-metrics-card div .critical::before,#upstream-container .topology-metrics-card div .critical::before{--icon-color:var(--token-color-foreground-critical)}#downstream-container .topology-metrics-card div .empty::before,#upstream-container .topology-metrics-card div .empty::before{--icon-color:var(--token-color-foreground-faint)}#downstream-container .topology-metrics-card .details,#upstream-container .topology-metrics-card .details{padding:0 12px 12px}#downstream-container .topology-metrics-card .details>:not(:last-child),#upstream-container .topology-metrics-card .details>:not(:last-child){padding-bottom:6px}#downstream-container .topology-metrics-card .details .group,#upstream-container .topology-metrics-card .details .group{display:grid;grid-template-columns:20px 1fr;grid-template-rows:repeat(2,1fr);grid-template-areas:"partition partition" "union namespace"}#downstream-container .topology-metrics-card .details .group span,#upstream-container .topology-metrics-card .details .group span{display:inline-block;grid-area:union;padding-left:7px;margin-right:0}#downstream-container .topology-metrics-card .details .group span::before,#upstream-container .topology-metrics-card .details .group span::before{margin-right:0;--icon-color:var(--token-color-foreground-faint)}#downstream-container .topology-metrics-card .details .group dl:first-child,#upstream-container .topology-metrics-card .details .group dl:first-child{grid-area:partition;padding-bottom:6px}#downstream-container .topology-metrics-card .details .group dl:nth-child(2),#upstream-container .topology-metrics-card .details .group dl:nth-child(2){grid-area:namespace}.topology-metrics-source-type{margin:6px 0 6px 12px;display:table}.topology-metrics-popover>button{position:absolute;transform:translate(-50%,-50%);background-color:var(--token-color-surface-primary);padding:1px}.topology-metrics-popover>button:hover{cursor:pointer}.topology-metrics-popover>button:disabled,html[data-route^="dc.nodes.show.metadata"] table tr{cursor:default}.topology-metrics-popover>button:active,.topology-metrics-popover>button:focus{outline:0}.topology-metrics-popover.deny .informed-action header::before{display:none}.topology-metrics-popover.deny .tippy-arrow::after,.topology-metrics-popover.deny>button::before{--icon-color:var(--token-color-foreground-critical)}.topology-metrics-popover.not-defined .tippy-arrow::after,.topology-metrics-popover.not-defined>button::before{--icon-color:var(--token-color-vault-brand)}#metrics-container .sparkline-wrapper svg path{stroke-width:0}#metrics-container .sparkline-wrapper .tooltip{padding:0 0 10px;border:1px solid var(--token-color-palette-neutral-300);background:#fff;border-radius:2px;box-sizing:border-box;box-shadow:var(--token-elevation-higher-box-shadow)}#metrics-container .sparkline-wrapper .tooltip .sparkline-time{padding:8px 10px;color:#000;border-bottom:1px solid var(--token-color-surface-interactive-active);margin-bottom:4px;text-align:center}#metrics-container .sparkline-wrapper .tooltip .sparkline-tt-legend,#metrics-container .sparkline-wrapper .tooltip .sparkline-tt-sum{border:0;padding:3px 10px 0}#metrics-container .sparkline-wrapper .tooltip .sparkline-tt-sum{border-top:1px solid var(--token-color-surface-interactive-active);margin-top:4px;padding:8px 10px 0}#metrics-container .sparkline-wrapper .tooltip .sparkline-tt-legend-color{width:12px;height:12px;border-radius:2px;margin:0 5px 0 0;padding:0}#metrics-container .sparkline-wrapper .tooltip .sparkline-tt-legend-value,#metrics-container .sparkline-wrapper .tooltip .sparkline-tt-sum-value{float:right}#metrics-container .sparkline-wrapper div.tooltip:before{content:"";display:block;position:absolute;width:12px;height:12px;left:15px;bottom:-7px;border:1px solid var(--token-color-palette-neutral-300);border-top:0;border-left:0;background:#fff;transform:rotate(45deg)}.sparkline-key h3::before{margin:2px 3px 0 0;font-size:var(--token-typography-body-200-font-size)}.sparkline-key h3{color:var(--token-color-foreground-strong)}.sparkline-key .sparkline-key-content dd,.sparkline-key-link{color:var(--token-color-foreground-faint)}.sparkline-key-link:hover{color:var(--token-color-foreground-action)}#metrics-container:hover .sparkline-key-link::before{margin:1px 3px 0 0;font-size:12px}#metrics-container div .sparkline-wrapper,#metrics-container div .sparkline-wrapper svg.sparkline{width:100%;height:70px;padding:0;margin:0}#metrics-container div .sparkline-wrapper{position:relative}#metrics-container div .sparkline-wrapper .tooltip{visibility:hidden;position:absolute;z-index:10;bottom:78px;width:217px}#metrics-container div .sparkline-wrapper .sparkline-tt-legend-color{display:inline-block}#metrics-container div .sparkline-wrapper .topology-metrics-error,#metrics-container div .sparkline-wrapper .topology-metrics-loader{padding-top:15px}.sparkline-key .sparkline-key-content{width:500px;min-height:100px}.sparkline-key .sparkline-key-content dl{padding:10px 0 0}.sparkline-key .sparkline-key-content dt{font-weight:var(--token-typography-font-weight-semibold);width:125px;float:left}.sparkline-key .sparkline-key-content dd{margin:0 0 12px 135px}.sparkline-key-link{visibility:hidden;float:right;margin-top:-35px;margin-right:12px}#metrics-container:hover .sparkline-key-link{visibility:visible}.topology-metrics-stats{padding:12px 12px 0;display:flex;flex-flow:row wrap;justify-content:space-between;align-items:stretch;width:100%;border-top:1px solid var(--token-color-surface-interactive-active)}.topology-metrics-stats dl{display:flex;padding-bottom:12px}.topology-metrics-stats dt{margin-right:5px;line-height:1.5em!important}.topology-metrics-stats dd{color:var(--token-color-foreground-disabled)!important}.topology-metrics-stats span{padding-bottom:12px}.topology-metrics-status-error,.topology-metrics-status-loader{color:var(--token-color-foreground-faint);text-align:center;margin:0 auto!important;display:block}.topology-metrics-status-error span::before,.topology-metrics-status-loader span::before{background-color:var(--token-color-foreground-faint)}span.topology-metrics-status-loader::after{--icon-name:var(--icon-loading);content:"";margin-left:.5rem}.consul-node-peer-info .consul-node-peer-info__name,.consul-peer-info .consul-peer-info__description{margin-left:4px}.consul-intention-list-table__meta-info{display:flex}.consul-intention-list-table__meta-info .consul-intention-list-table__meta-info__peer{display:flex;align-items:center}.consul-node-peer-info,.peerings-badge{align-items:center;display:flex}.consul-peer-search-bar .value-active span::before,.consul-peer-search-bar .value-deleting span::before,.consul-peer-search-bar .value-establishing span::before,.consul-peer-search-bar .value-failing span::before,.consul-peer-search-bar .value-pending span::before,.consul-peer-search-bar .value-terminated span::before{--icon-size:icon-000;content:""}.consul-peer-search-bar .value-active span,.consul-peer-search-bar .value-deleting span,.consul-peer-search-bar .value-establishing span,.consul-peer-search-bar .value-failing span,.consul-peer-search-bar .value-pending span,.consul-peer-search-bar .value-terminated span{font-size:var(--token-typography-body-200-font-size)}.consul-peer-search-bar .value-pending span::before{--icon-name:icon-running;--icon-color:var(--token-color-palette-neutral-600)}.consul-peer-search-bar .value-pending span{background-color:var(--token-color-consul-surface);color:var(--token-color-consul-foreground)}.consul-peer-search-bar .value-establishing span::before{--icon-name:icon-running;--icon-color:var(--token-color-palette-neutral-600)}.consul-peer-search-bar .value-establishing span{background-color:var(--token-color-palette-blue-50);color:var(--token-color-palette-blue-200)}.consul-peer-search-bar .value-active span::before{--icon-name:icon-check;--icon-color:var(--token-color-palette-green-400)}.consul-peer-search-bar .value-active span{background-color:var(--token-color-palette-green-50);color:var(--token-color-palette-green-200)}.consul-peer-search-bar .value-failing span::before{--icon-name:icon-x;--icon-color:var(--token-color-palette-red-200)}.consul-peer-search-bar .value-failing span{background-color:var(--token-color-palette-red-50);color:var(--token-color-palette-red-200)}.consul-peer-search-bar .value-terminated span::before{--icon-name:icon-x-square;--icon-color:var(--token-color-palette-neutral-600)}.consul-peer-search-bar .value-terminated span{background-color:var(--token-color-palette-neutral-200);color:var(--token-color-palette-neutral-600)}.consul-peer-search-bar .value-deleting span::before{--icon-name:icon-loading;--icon-color:var(--token-color-foreground-warning-on-surface)}.consul-peer-search-bar .value-deleting span{background-color:var(--token-color-surface-warning);color:var(--token-color-foreground-warning-on-surface)}.peers__list__peer-detail{display:flex;align-content:center;gap:18px}.border-bottom-primary{border-bottom:1px solid var(--token-color-border-primary)}.peerings-badge{justify-content:center;padding:2px 8px;border-radius:5px;gap:4px}.peerings-badge.active{background:var(--token-color-surface-success);color:var(--token-color-foreground-success)}.peerings-badge.pending{background:var(--token-color-consul-surface);color:var(--token-color-consul-brand)}.peerings-badge.establishing{background:var(--token-color-surface-action);color:var(--token-color-foreground-action)}.peerings-badge.failing{background:var(--token-color-surface-critical);color:var(--token-color-foreground-critical)}.peerings-badge.deleting{background:var(--token-color-surface-warning);color:var(--token-color-foreground-warning-on-surface)}.peerings-badge.terminated,.peerings-badge.undefined{background:var(--token-color-surface-interactive-active);color:var(--token-color-foreground-primary)}.consul-peer-info,section[data-route="dc.show.serverstatus"] .server-failure-tolerance dt{color:var(--token-color-foreground-faint)}.consul-peer-info{background:var(--token-color-surface-faint);padding:0 8px;border-radius:2px;display:flex;align-items:center}.consul-peer-form{width:416px}.consul-peer-form nav{margin-bottom:20px}.consul-peer-form-generate{width:416px;min-height:200px}.consul-peer-form-generate ol{list-style-position:outside;list-style-type:none;counter-reset:hexagonal-counter;position:relative}.consul-peer-form-generate ol::before{content:"";border-left:var(--decor-border-100);border-color:var(--token-color-palette-neutral-300);height:100%;position:absolute;left:2rem}.consul-peer-form-generate li{counter-increment:hexagonal-counter;position:relative;margin-left:60px;margin-bottom:1rem}.consul-peer-form-generate li .copyable-code{margin-top:1rem}.consul-peer-form-generate li::before{--icon-name:icon-hexagon;--icon-size:icon-600;content:"";position:absolute;z-index:2}.consul-peer-form-generate li::after{content:counter(hexagonal-counter);position:absolute;top:0;background-color:var(--token-color-palette-neutral-0);z-index:1;text-align:center}.consul-peer-form-generate li::after,.consul-peer-form-generate li::before{left:-2.4rem;width:20px;height:20px}.agentless-node-notice .hds-alert__title{display:flex;justify-content:space-between}.definition-table dt{line-height:var(--token-typography-body-300-line-height)}.app-view>div form:not(.filter-bar) [role=radiogroup] label,.modal-dialog [role=document] [role=radiogroup] label{line-height:var(--token-typography-body-100-line-height)}.app-view h1 em,.app-view>div form:not(.filter-bar) [role=radiogroup] label>em,.consul-intention-list td.destination em,.consul-intention-list td.source em,.modal-dialog [role=document] .type-password>em,.modal-dialog [role=document] .type-select>em,.modal-dialog [role=document] .type-text>em,.modal-dialog [role=document] [role=radiogroup] label>em,.modal-dialog [role=document] form button+em,.modal-dialog [role=document] table th em,.oidc-select label>em,.type-toggle>em,main .type-password>em,main .type-select>em,main .type-text>em,main form button+em,main table th em{font-style:normal}.consul-exposed-path-list>ul>li>.header :not(button),.consul-lock-session-list ul>li:not(:first-child)>.header :not(button),.consul-upstream-instance-list li>.header :not(button),.list-collection>ul>li:not(:first-child)>.header :not(button){font-size:inherit;font-weight:inherit}@media (max-width:420px) and (-webkit-min-device-pixel-ratio:0){input{font-size:var(--token-typography-body-300-font-size)!important}}#wrapper,#wrapper>footer>*,.modal-dialog>*,main>*{box-sizing:border-box}html[data-route$=create] main,html[data-route$=edit] main{max-width:1260px}fieldset [role=group]{display:flex;flex-wrap:wrap;flex-direction:row}.outlet[data-state=loading],html.ember-loading .view-loader,html:not(.has-nspaces) [class*=nspace-],html:not(.has-partitions) [class*=partition-],html[data-state=idle] .view-loader{display:none}[role=group] fieldset{width:50%}[role=group] fieldset:not(:first-of-type){padding-left:20px;border-left:1px solid;border-left:var(--token-color-foreground-faint)}[role=group] fieldset:not(:last-of-type){padding-right:20px}.app-view{margin-top:50px}@media (max-width:849px){html:not(.with-breadcrumbs) .app-view{margin-top:10px}}html body>.brand-loader{transition-property:transform,opacity;transform:translate(0,0);opacity:1}html[data-state]:not(.ember-loading) body>.brand-loader{opacity:0}@media (min-width:900px){html[data-state] body>.brand-loader{transform:translate(calc(var(--chrome-width)/ 2),0)}}html[data-route$=create] .app-view>header+div>:first-child,html[data-route$=edit] .app-view>header+div>:first-child{margin-top:1.8em}.app-view>div .container,.app-view>div .tab-section .consul-health-check-list,.app-view>div .tab-section>.search-bar+p,.app-view>div .tab-section>:first-child:not(.filter-bar):not(table){margin-top:1.25em}.consul-upstream-instance-list,html[data-route^="dc.nodes.show.sessions"] .consul-lock-session-list{margin-top:0!important}.consul-auth-method-list ul,.consul-node-list ul,.consul-nspace-list ul,.consul-peer-list ul,.consul-policy-list ul,.consul-role-list ul,.consul-service-instance-list ul,.consul-token-list ul,html[data-route="dc.services.index"] .consul-service-list ul,html[data-route^="dc.nodes.show.sessions"] .consul-lock-session-list ul{border-top-width:0!important}#wrapper{display:flex;min-height:100vh}main{padding:0 48px;position:relative;flex:1}html:not([data-route$=index]):not([data-route$=instances]) main{margin-bottom:2em}@media (max-width:849px){.actions button.copy-btn{margin-top:-56px;padding:0}}.modal-dialog [role=document] p:not(:last-child),main p:not(:last-child){margin-bottom:1em}.modal-dialog [role=document] form+div .with-confirmation,.modal-dialog [role=document] form:not(.filter-bar),main form+div .with-confirmation,main form:not(.filter-bar){margin-bottom:2em}@media (max-width:420px){main form [type=reset]{float:right;margin-right:0!important}}html[data-route^="dc.services.show"] .app-view .actions .external-dashboard{position:absolute;top:50px;right:0}html[data-route^="dc.services.instance"] .app-view>header dl{float:left;margin-top:19px;margin-bottom:23px;margin-right:50px}html[data-route^="dc.services.instance"] .app-view>header dt{font-weight:var(--token-typography-font-weight-bold)}html[data-route^="dc.services.instance"] .tab-nav{border-top:var(--decor-border-100)}html[data-route^="dc.services.instance"] .tab-section section:not(:last-child){border-bottom:var(--decor-border-100);padding-bottom:24px}html[data-route^="dc.services.instance"] .tab-nav,html[data-route^="dc.services.instance"] .tab-section section:not(:last-child){border-color:var(--token-color-surface-interactive-active)}html[data-route^="dc.services.instance.metadata"] .tab-section section h2{margin:24px 0 12px}html[data-route^="dc.kv"] .type-toggle{float:right;margin-bottom:0!important}html[data-route^="dc.kv.edit"] h2{border-bottom:var(--decor-border-200);border-color:var(--token-color-surface-interactive-active);padding-bottom:.2em;margin-bottom:.5em}html[data-route^="dc.acls.index"] main td strong{margin-right:3px}@media (max-width:420px){html[data-route^="dc.acls.create"] main header .actions,html[data-route^="dc.acls.edit"] main header .actions{float:none;display:flex;justify-content:space-between;margin-bottom:1em}html[data-route^="dc.acls.create"] main header .actions .with-feedback,html[data-route^="dc.acls.edit"] main header .actions .with-feedback{position:absolute;right:0}html[data-route^="dc.acls.create"] main header .actions .with-confirmation,html[data-route^="dc.acls.edit"] main header .actions .with-confirmation{margin-top:0}}html[data-route^="dc.intentions.edit"] .definition-table{margin-bottom:1em}section[data-route="dc.show.serverstatus"] .server-failure-tolerance{box-shadow:none;padding:var(--padding-y) var(--padding-x);max-width:770px;display:flex;flex-wrap:wrap}section[data-route="dc.show.serverstatus"] .server-failure-tolerance>header{width:100%;display:flex;flex-direction:row;justify-content:space-between;align-items:center;padding-bottom:.5rem;margin-bottom:1rem;border-bottom:var(--decor-border-100);border-color:var(--tone-border)}section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em{background-color:var(--token-color-surface-interactive-active);text-transform:uppercase;font-style:normal}section[data-route="dc.show.serverstatus"] .server-failure-tolerance>section{width:50%}section[data-route="dc.show.serverstatus"] .server-failure-tolerance dl,section[data-route="dc.show.serverstatus"] .server-failure-tolerance>section{display:flex;flex-direction:column}section[data-route="dc.show.serverstatus"] .server-failure-tolerance dl{flex-grow:1;justify-content:space-between}section[data-route="dc.show.serverstatus"] .server-failure-tolerance dl.warning dd::before{--icon-name:icon-alert-circle;--icon-size:icon-800;--icon-color:var(--token-color-foreground-warning);content:"";margin-right:.5rem}section[data-route="dc.show.serverstatus"] .server-failure-tolerance section:first-of-type dl{padding-right:1.5rem}section[data-route="dc.show.serverstatus"] .server-failure-tolerance dd{display:flex;align-items:center;color:var(--token-color-hashicorp-brand)}section[data-route="dc.show.serverstatus"] .server-failure-tolerance header span::before{--icon-name:icon-info;--icon-size:icon-300;--icon-color:var(--token-color-foreground-faint);vertical-align:unset;content:""}section[data-route="dc.show.serverstatus"] section:not([class*=-tolerance]) h2{margin-top:1.5rem;margin-bottom:1.5rem}section[data-route="dc.show.serverstatus"] section:not([class*=-tolerance]) header{margin-top:18px;margin-bottom:18px}section[data-route="dc.show.serverstatus"] .redundancy-zones section header{display:flow-root}section[data-route="dc.show.serverstatus"] .redundancy-zones section header h3{float:left;margin-right:.5rem}section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not(.warning){background-color:var(--token-color-surface-strong)}section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl.warning{background-color:var(--token-color-border-warning);color:var(--token-color-palette-amber-400)}section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl.warning::before{--icon-name:icon-alert-circle;--icon-size:icon-000;margin-right:.312rem;content:""}section[data-route="dc.show.serverstatus"] .redundancy-zones section header dt::after{content:":";display:inline-block;vertical-align:revert;background-color:transparent}section[data-route="dc.show.license"] .validity p{color:var(--token-color-foreground-faint)}section[data-route="dc.show.license"] .validity dl dt::before{content:"";margin-right:.25rem}section[data-route="dc.show.license"] .validity dl .expired::before{--icon-name:icon-x-circle;--icon-color:var(--token-color-foreground-critical)}section[data-route="dc.show.license"] .validity dl .warning::before{--icon-name:icon-alert-circle;--icon-color:var(--token-color-foreground-warning)}section[data-route="dc.show.license"] .validity dl .valid:not(.warning)::before{--icon-name:icon-check-circle;--icon-color:var(--token-color-foreground-success)}section[data-route="dc.show.license"] aside{box-shadow:none;padding:var(--padding-y) var(--padding-x);width:40%;min-width:413px;margin-top:1rem}section[data-route="dc.show.license"] aside header{margin-bottom:1rem}.prefers-reduced-motion{--icon-loading:icon-loading}@media (prefers-reduced-motion){:root{--hds-app-sidenav-animation-duration:0;--icon-loading:icon-loading}}.consul-intention-fieldsets .value->:last-child::before,.consul-intention-fieldsets .value-allow>:last-child::before,.consul-intention-fieldsets .value-deny>:last-child::before{--icon-size:icon-500;--icon-resolution:0.5}.consul-intention-fieldsets .value-allow>:last-child::before,.consul-intention-list td.intent-allow strong::before,.consul-intention-permission-list .intent-allow::before,.consul-intention-search-bar .value-allow span::before{--icon-name:icon-arrow-right;--icon-color:var(--token-color-foreground-success-on-surface)}.consul-intention-fieldsets .value-deny>:last-child::before,.consul-intention-list td.intent-deny strong::before,.consul-intention-permission-list .intent-deny::before,.consul-intention-search-bar .value-deny span::before{--icon-name:icon-skip;--icon-color:var(--token-color-foreground-critical-on-surface)}.consul-intention-fieldsets .value->:last-child::before,.consul-intention-list td.intent- strong::before,.consul-intention-search-bar .value- span::before{--icon-name:icon-layers}*{border-width:0}.animatable.tab-nav ul::after,.consul-auth-method-type,.consul-external-source,.consul-intention-action-warn-modal button.dangerous,.consul-intention-action-warn-modal button.dangerous:disabled,.consul-intention-action-warn-modal button.dangerous:focus,.consul-intention-action-warn-modal button.dangerous:hover:active,.consul-intention-action-warn-modal button.dangerous:hover:not(:disabled):not(:active),.consul-intention-list td.intent- strong,.consul-intention-permission-form button.type-submit,.consul-intention-permission-form button.type-submit:disabled,.consul-intention-permission-form button.type-submit:focus:not(:disabled),.consul-intention-permission-form button.type-submit:hover:not(:disabled),.consul-intention-search-bar .value- span,.consul-kind,.consul-source,.consul-transparent-proxy,.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:first-child,.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:focus:first-child,.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:hover:first-child,.discovery-chain .route-card>header ul li,.informed-action>ul>.dangerous>*,.informed-action>ul>.dangerous>:focus,.informed-action>ul>.dangerous>:hover,.leader,.menu-panel>ul>li.dangerous>:first-child,.menu-panel>ul>li.dangerous>:focus:first-child,.menu-panel>ul>li.dangerous>:hover:first-child,.modal-dialog [role=document]>footer,.modal-dialog [role=document]>header,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:first-child,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child,.tab-nav .selected>*,.topology-metrics-source-type,html[data-route^="dc.acls.index"] main td strong,span.policy-node-identity,span.policy-service-identity,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:first-child,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child{border-style:solid}.consul-auth-method-type,.consul-external-source,.consul-kind,.consul-source,.consul-transparent-proxy,.leader,.topology-metrics-source-type,span.policy-node-identity,span.policy-service-identity{background-color:var(--token-color-surface-strong);border-color:var(--token-color-foreground-faint);color:var(--token-color-foreground-primary)}.consul-intention-list td.intent- strong,.consul-intention-search-bar .value- span,.discovery-chain .route-card>header ul li,.modal-dialog [role=document]>footer,.modal-dialog [role=document]>header,html[data-route^="dc.acls.index"] main td strong{background-color:var(--token-color-surface-strong);border-color:var(--token-color-palette-neutral-300);color:var(--token-color-foreground-strong)}.animatable.tab-nav ul::after,.consul-intention-permission-form button.type-submit,.consul-intention-permission-form button.type-submit:disabled,.tab-nav .selected>*{background-color:var(--token-color-surface-primary);border-color:var(--token-color-foreground-action);color:var(--token-color-foreground-action)}.consul-intention-permission-form button.type-submit:focus:not(:disabled),.consul-intention-permission-form button.type-submit:hover:not(:disabled){background-color:var(--token-color-surface-action);border-color:var(--token-color-foreground-action);color:var(--token-color-palette-blue-500)}.consul-intention-action-warn-modal button.dangerous,.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:first-child,.informed-action>ul>.dangerous>*,.menu-panel>ul>li.dangerous>:first-child,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:first-child,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:first-child{background-color:transparent;border-color:var(--token-color-foreground-critical);color:var(--token-color-foreground-critical)}.consul-intention-action-warn-modal button.dangerous:disabled{background-color:var(--token-color-border-critical);border-color:var(--token-color-foreground-disabled);color:var(--token-color-surface-primary)}.consul-intention-action-warn-modal button.dangerous:focus,.consul-intention-action-warn-modal button.dangerous:hover:not(:disabled):not(:active),.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:focus:first-child,.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:hover:first-child,.informed-action>ul>.dangerous>:focus,.informed-action>ul>.dangerous>:hover,.menu-panel>ul>li.dangerous>:focus:first-child,.menu-panel>ul>li.dangerous>:hover:first-child,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child{background-color:var(--token-color-foreground-critical);border-color:var(--token-color-foreground-critical-high-contrast);color:var(--token-color-surface-primary)}.consul-intention-action-warn-modal button.dangerous:hover:active{background-color:var(--token-color-palette-red-400);border-color:var(--token-color-foreground-critical-high-contrast);color:var(--token-color-surface-primary)}.hover\:scale-125:hover{--tw-scale-x:1.25;--tw-scale-y:1.25}.group:hover .group-hover\:opacity-100{opacity:1} \ No newline at end of file diff --git a/agent/uiserver/dist/assets/consul-ui-7444626e95c5ba30e9097f92995f0238.js b/agent/uiserver/dist/assets/consul-ui-7444626e95c5ba30e9097f92995f0238.js deleted file mode 100644 index f965f9a32133..000000000000 --- a/agent/uiserver/dist/assets/consul-ui-7444626e95c5ba30e9097f92995f0238.js +++ /dev/null @@ -1,3938 +0,0 @@ -"use strict" -define("consul-ui/abilities/acl",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i -function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"resource","acl"),o(this,"segmented",!1)}get canAccess(){return!this.env.var("CONSUL_ACLS_ENABLED")||this.canRead}get canRead(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canRead}get canDuplicate(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canWrite}get canDelete(){return this.env.var("CONSUL_ACLS_ENABLED")&&"anonymous"!==this.item.ID&&super.canWrite}get canUse(){return this.env.var("CONSUL_ACLS_ENABLED")}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/abilities/auth-method",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i -function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"resource","acl"),o(this,"segmented",!1)}get canRead(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canRead}get canCreate(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canCreate}get canDelete(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canDelete}get canUse(){return this.env.var("CONSUL_SSO_ENABLED")}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/abilities/base",["exports","@ember/service","@ember/object","ember-can"],(function(e,t,n,l){var r,i,o -function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.ACCESS_LIST=e.ACCESS_WRITE=e.ACCESS_READ=void 0 -const u="read" -e.ACCESS_READ=u -const s="write" -e.ACCESS_WRITE=s -const c="list" -e.ACCESS_LIST=c -let d=(r=(0,t.inject)("repository/permission"),i=class extends l.Ability{constructor(){var e,t,n,l -super(...arguments),e=this,t="permissions",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a(this,"resource",""),a(this,"segmented",!0)}generate(e){return this.permissions.generate(this.resource,e)}generateForSegment(e){return this.segmented?[this.permissions.generate(this.resource,u,e),this.permissions.generate(this.resource,s,e)]:[]}get isLinkable(){return!0}get isNew(){return this.item.isNew}get isPristine(){return this.item.isPristine}get canRead(){if(void 0!==this.item){const e=((0,n.get)(this,"item.Resources")||[]).find((e=>e.Access===u)) -if(e)return e.Allow}return this.permissions.has(this.generate(u))}get canList(){if(void 0!==this.item){const e=((0,n.get)(this,"item.Resources")||[]).find((e=>e.Access===c)) -if(e)return e.Allow}return this.permissions.has(this.generate(c))}get canWrite(){if(void 0!==this.item){const e=((0,n.get)(this,"item.Resources")||[]).find((e=>e.Access===s)) -if(e)return e.Allow}return this.permissions.has(this.generate(s))}get canCreate(){return this.canWrite}get canDelete(){return this.canWrite}get canUpdate(){return this.canWrite}},p=i.prototype,f="permissions",m=[r],h={configurable:!0,enumerable:!0,writable:!0,initializer:null},y={},Object.keys(h).forEach((function(e){y[e]=h[e]})),y.enumerable=!!y.enumerable,y.configurable=!!y.configurable,("value"in y||y.initializer)&&(y.writable=!0),y=m.slice().reverse().reduce((function(e,t){return t(p,f,e)||e}),y),b&&void 0!==y.initializer&&(y.value=y.initializer?y.initializer.call(b):void 0,y.initializer=void 0),void 0===y.initializer&&(Object.defineProperty(p,f,y),y=null),o=y,i) -var p,f,m,h,b,y -e.default=d})),define("consul-ui/abilities/intention",["exports","consul-ui/abilities/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{constructor(){var e,t,n -super(...arguments),n="intention",(t="resource")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}get canWrite(){return(void 0===this.item||void 0===this.item.SourcePeer)&&(super.canWrite&&(void 0===this.item||!this.canViewCRD))}get canViewCRD(){return void 0!==this.item&&this.item.IsManagedByCRD}}e.default=n})),define("consul-ui/abilities/kv",["exports","consul-ui/abilities/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{constructor(){var e,t,n -super(...arguments),n="key",(t="resource")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}generateForSegment(e){let n=super.generateForSegment(e) -return e.endsWith("/")&&(n=n.concat(this.permissions.generate(this.resource,t.ACCESS_LIST,e))),n}get canRead(){return!0}get canList(){return!0}get canWrite(){return!0}}e.default=n})),define("consul-ui/abilities/license",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i -function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),o(this,"resource","operator"),o(this,"segmented",!1),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}get canRead(){return this.env.var("CONSUL_NSPACES_ENABLED")&&super.canRead}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/abilities/node",["exports","consul-ui/abilities/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{constructor(){var e,t,n -super(...arguments),n="node",(t="resource")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}}e.default=n})),define("consul-ui/abilities/nspace",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i -function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"resource","operator"),o(this,"segmented",!1)}get isLinkable(){return!this.item.DeletedAt}get canManage(){return this.canCreate}get canDelete(){return"default"!==this.item.Name&&super.canDelete}get canChoose(){return this.canUse}get canUse(){return this.env.var("CONSUL_NSPACES_ENABLED")}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/abilities/overview",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i -function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"resource","operator"),o(this,"segmented",!1)}get canAccess(){return!this.env.var("CONSUL_HCP_ENABLED")&&this.canRead}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/abilities/partition",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i,o,a -function u(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let d=(l=(0,n.inject)("env"),r=(0,n.inject)("repository/dc"),i=class extends t.default{constructor(){super(...arguments),u(this,"env",o,this),u(this,"dcs",a,this),s(this,"resource","operator"),s(this,"segmented",!1)}get isLinkable(){return!this.item.DeletedAt}get canManage(){return this.canWrite}get canCreate(){return!(this.dcs.peekAll().length>1)&&super.canCreate}get canDelete(){return"default"!==this.item.Name&&super.canDelete}get canChoose(){return void 0!==this.dc&&(this.canUse&&this.dc.Primary)}get canUse(){return this.env.var("CONSUL_PARTITIONS_ENABLED")}},o=c(i.prototype,"env",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=c(i.prototype,"dcs",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) -e.default=d})),define("consul-ui/abilities/peer",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i -function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"resource","peering"),o(this,"segmented",!1)}get isLinkable(){return this.canDelete}get canDelete(){return!["DELETING"].includes(this.item.State)&&super.canDelete}get canUse(){return this.env.var("CONSUL_PEERINGS_ENABLED")}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/abilities/permission",["exports","consul-ui/abilities/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{get canRead(){return this.permissions.permissions.length>0}}e.default=n})),define("consul-ui/abilities/policy",["exports","consul-ui/abilities/base","@ember/service","consul-ui/helpers/policy/typeof"],(function(e,t,n,l){var r,i,o -function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let u=(r=(0,n.inject)("env"),i=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a(this,"resource","acl"),a(this,"segmented",!1)}get canRead(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canRead}get canWrite(){return this.env.var("CONSUL_ACLS_ENABLED")&&(void 0===this.item||"policy-management"!==(0,l.typeOf)([this.item]))&&super.canWrite}get canCreate(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canCreate}get canDelete(){return this.env.var("CONSUL_ACLS_ENABLED")&&(void 0===this.item||"policy-management"!==(0,l.typeOf)([this.item]))&&super.canDelete}},s=i.prototype,c="env",d=[r],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),o=m,i) -var s,c,d,p,f,m -e.default=u})),define("consul-ui/abilities/role",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i -function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"resource","acl"),o(this,"segmented",!1)}get canRead(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canRead}get canCreate(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canCreate}get canDelete(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canDelete}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/abilities/server",["exports","consul-ui/abilities/base"],(function(e,t){function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{constructor(){super(...arguments),n(this,"resource","operator"),n(this,"segmented",!1)}}e.default=l})),define("consul-ui/abilities/service-instance",["exports","consul-ui/abilities/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{constructor(){var e,t,n -super(...arguments),n="service",(t="resource")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}generateForSegment(e){return super.generateForSegment(...arguments).concat([this.permissions.generate("intention",t.ACCESS_READ,e),this.permissions.generate("intention",t.ACCESS_WRITE,e)])}}e.default=n})),define("consul-ui/abilities/session",["exports","consul-ui/abilities/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{constructor(){var e,t,n -super(...arguments),n="session",(t="resource")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}}e.default=n})),define("consul-ui/abilities/token",["exports","consul-ui/abilities/base","@ember/service","consul-ui/helpers/token/is-legacy","consul-ui/helpers/token/is-anonymous"],(function(e,t,n,l,r){var i,o,a -function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let s=(i=(0,n.inject)("env"),o=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),u(this,"resource","acl"),u(this,"segmented",!1)}get canRead(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canRead}get canCreate(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canCreate}get canDelete(){return this.env.var("CONSUL_ACLS_ENABLED")&&!(0,r.isAnonymous)([this.item])&&this.item.AccessorID!==this.token.AccessorID&&super.canDelete}get canDuplicate(){return this.env.var("CONSUL_ACLS_ENABLED")&&!(0,l.isLegacy)([this.item])&&super.canWrite}},c=o.prototype,d="env",p=[i],f={configurable:!0,enumerable:!0,writable:!0,initializer:null},h={},Object.keys(f).forEach((function(e){h[e]=f[e]})),h.enumerable=!!h.enumerable,h.configurable=!!h.configurable,("value"in h||h.initializer)&&(h.writable=!0),h=p.slice().reverse().reduce((function(e,t){return t(c,d,e)||e}),h),m&&void 0!==h.initializer&&(h.value=h.initializer?h.initializer.call(m):void 0,h.initializer=void 0),void 0===h.initializer&&(Object.defineProperty(c,d,h),h=null),a=h,o) -var c,d,p,f,m,h -e.default=s})),define("consul-ui/abilities/upstream",["exports","consul-ui/abilities/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{constructor(){var e,t,n -super(...arguments),n="upstream",(t="resource")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}get isLinkable(){return this.item.InstanceCount>0}}e.default=n})),define("consul-ui/abilities/zervice",["exports","consul-ui/abilities/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{constructor(){var e,t,n -super(...arguments),n="service",(t="resource")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}get isLinkable(){return this.item.InstanceCount>0}get canReadIntention(){if(void 0===this.item||void 0===this.item.Resources)return!1 -return void 0!==this.item.Resources.find((e=>"intention"===e.Resource&&"read"===e.Access&&!0===e.Allow))}get canWriteIntention(){if(void 0===this.item||void 0===this.item.Resources)return!1 -return void 0!==this.item.Resources.find((e=>"intention"===e.Resource&&"write"===e.Access&&!0===e.Allow))}get canCreateIntention(){return this.canWriteIntention}get canUpdateIntention(){return this.canWriteIntention}}e.default=n})),define("consul-ui/abilities/zone",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}get canRead(){return this.env.var("CONSUL_NSPACES_ENABLED")}},a=r.prototype,u="env",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/adapters/-json-api",["exports","@ember-data/adapter/json-api"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/adapters/application",["exports","consul-ui/adapters/http","@ember/service"],(function(e,t,n){var l,r,i,o,a -function u(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function s(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.NSPACE_QUERY_PARAM=e.DATACENTER_QUERY_PARAM=void 0 -e.DATACENTER_QUERY_PARAM="dc" -e.NSPACE_QUERY_PARAM="ns" -let c=(l=(0,n.inject)("client/http"),r=(0,n.inject)("env"),i=class extends t.default{constructor(){super(...arguments),u(this,"client",o,this),u(this,"env",a,this)}formatNspace(e){if(this.env.var("CONSUL_NSPACES_ENABLED"))return""!==e?{ns:e}:void 0}formatDatacenter(e){return{dc:e}}},o=s(i.prototype,"client",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=s(i.prototype,"env",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) -e.default=c})),define("consul-ui/adapters/auth-method",["exports","consul-ui/adapters/application"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{requestForQuery(e,t){let{dc:n,ns:l,partition:r,index:i,id:o}=t -return e` - GET /v1/acl/auth-methods?${{dc:n}} - - ${{ns:l,partition:r,index:i}} - `}requestForQueryRecord(e,t){let{dc:n,ns:l,partition:r,index:i,id:o}=t -if(void 0===o)throw new Error("You must specify an id") -return e` - GET /v1/acl/auth-method/${o}?${{dc:n}} - - ${{ns:l,partition:r,index:i}} - `}}e.default=n})),define("consul-ui/adapters/binding-rule",["exports","consul-ui/adapters/application"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{requestForQuery(e,t){let{dc:n,ns:l,partition:r,authmethod:i,index:o}=t -return e` - GET /v1/acl/binding-rules?${{dc:n,authmethod:i}} - - ${{ns:l,partition:r,index:o}} - `}}e.default=n})),define("consul-ui/adapters/coordinate",["exports","consul-ui/adapters/application"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{requestForQuery(e,t){let{dc:n,partition:l,index:r,uri:i}=t -return e` - GET /v1/coordinate/nodes?${{dc:n}} - X-Request-ID: ${i} - - ${{partition:l,index:r}} - `}}e.default=n})),define("consul-ui/adapters/discovery-chain",["exports","consul-ui/adapters/application"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{requestForQueryRecord(e,t){let{dc:n,ns:l,partition:r,index:i,id:o,uri:a}=t -if(void 0===o)throw new Error("You must specify an id") -return e` - GET /v1/discovery-chain/${o}?${{dc:n}} - X-Request-ID: ${a} - - ${{ns:l,partition:r,index:i}} - `}}e.default=n})),define("consul-ui/adapters/http",["exports","@ember/service","@ember-data/adapter","@ember-data/adapter/error"],(function(e,t,n,l){var r,i,o -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const a=function(e,t,n){let l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{} -return e.rpc((function(e){for(var t=arguments.length,l=new Array(t>1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;r=500?new l.ServerError(t,r):new l.default(t,r)}}catch(i){n=i}throw n}query(e,t,n){return a(this,t.modelName,"Query",n)}queryRecord(e,t,n){return a(this,t.modelName,"QueryRecord",n)}findAll(e,t){return a(this,t.modelName,"FindAll")}createRecord(e,t,n){return u(this,t.modelName,"CreateRecord",n)}updateRecord(e,t,n){return u(this,t.modelName,"UpdateRecord",n)}deleteRecord(e,t,n){return u(this,t.modelName,"DeleteRecord",n)}},c=i.prototype,d="client",p=[r],f={configurable:!0,enumerable:!0,writable:!0,initializer:null},h={},Object.keys(f).forEach((function(e){h[e]=f[e]})),h.enumerable=!!h.enumerable,h.configurable=!!h.configurable,("value"in h||h.initializer)&&(h.writable=!0),h=p.slice().reverse().reduce((function(e,t){return t(c,d,e)||e}),h),m&&void 0!==h.initializer&&(h.value=h.initializer?h.initializer.call(m):void 0,h.initializer=void 0),void 0===h.initializer&&(Object.defineProperty(c,d,h),h=null),o=h,i) -var c,d,p,f,m,h -e.default=s})),define("consul-ui/adapters/intention",["exports","consul-ui/adapters/application","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{requestForQuery(e,t){let{dc:n,ns:l,partition:r,filter:i,index:o,uri:a}=t -return e` - GET /v1/connect/intentions?${{dc:n}} - X-Request-ID: ${a}${void 0!==i?`\n X-Range: ${i}`:""} - - ${{partition:r,ns:"*",index:o,filter:i}} - `}requestForQueryRecord(e,t){let{dc:n,index:l,id:r}=t -if(void 0===r)throw new Error("You must specify an id") -if(r.match(/^peer:/)){const[t,i,o,a,u,s,c]=r.split(":").map(decodeURIComponent) -return e` - GET /v1/connect/intentions/exact?${{source:`${t}:${i}/${o}/${a}`,destination:`${u}/${s}/${c}`,dc:n}} - Cache-Control: no-store - - ${{index:l}} - `}{const[t,i,o,a,u,s]=r.split(":").map(decodeURIComponent) -return e` - GET /v1/connect/intentions/exact?${{source:`${t}/${i}/${o}`,destination:`${a}/${u}/${s}`,dc:n}} - Cache-Control: no-store - - ${{index:l}} - `}}requestForCreateRecord(e,t,l){const r={SourceName:t.SourceName,DestinationName:t.DestinationName,SourceNS:t.SourceNS,DestinationNS:t.DestinationNS,SourcePartition:t.SourcePartition,DestinationPartition:t.DestinationPartition,SourceType:t.SourceType,Meta:t.Meta,Description:t.Description} -return(0,n.get)(t,"Action.length")?r.Action=t.Action:t.Permissions&&(r.Permissions=t.Permissions),e` - PUT /v1/connect/intentions/exact?${{source:`${l.SourcePartition}/${l.SourceNS}/${l.SourceName}`,destination:`${l.DestinationPartition}/${l.DestinationNS}/${l.DestinationName}`,dc:l.Datacenter}} - - ${r} - `}requestForUpdateRecord(e,t,n){return delete t.DestinationName,delete t.DestinationNS,delete t.DestinationPartition,this.requestForCreateRecord(...arguments)}requestForDeleteRecord(e,t,n){return e` - DELETE /v1/connect/intentions/exact?${{source:`${n.SourcePartition}/${n.SourceNS}/${n.SourceName}`,destination:`${n.DestinationPartition}/${n.DestinationNS}/${n.DestinationName}`,dc:n.Datacenter}} - `}}e.default=l})),define("consul-ui/adapters/kv",["exports","consul-ui/adapters/application","consul-ui/utils/isFolder","consul-ui/utils/keyToArray","consul-ui/models/kv"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class i extends t.default{async requestForQuery(e,t){let{dc:n,ns:r,partition:i,index:o,id:a,separator:u}=t -if(void 0===a)throw new Error("You must specify an id") -const s=await(e` - GET /v1/kv/${(0,l.default)(a)}?${{keys:null,dc:n,separator:u}} - - ${{ns:r,partition:i,index:o}} - `) -return await s(((e,t)=>delete e["x-consul-index"])),s}async requestForQueryRecord(e,t){let{dc:n,ns:r,partition:i,index:o,id:a}=t -if(void 0===a)throw new Error("You must specify an id") -const u=await(e` - GET /v1/kv/${(0,l.default)(a)}?${{dc:n}} - - ${{ns:r,partition:i,index:o}} - `) -return await u(((e,t)=>delete e["x-consul-index"])),u}requestForCreateRecord(e,t,n){const i={dc:n.Datacenter,ns:n.Namespace,partition:n.Partition} -return e` - PUT /v1/kv/${(0,l.default)(n[r.SLUG_KEY])}?${i} - Content-Type: text/plain; charset=utf-8 - - ${t} - `}requestForUpdateRecord(e,t,n){const i={dc:n.Datacenter,ns:n.Namespace,partition:n.Partition,flags:n.Flags} -return e` - PUT /v1/kv/${(0,l.default)(n[r.SLUG_KEY])}?${i} - Content-Type: text/plain; charset=utf-8 - - ${t} - `}requestForDeleteRecord(e,t,i){let o;(0,n.default)(i[r.SLUG_KEY])&&(o=null) -const a={dc:i.Datacenter,ns:i.Namespace,partition:i.Partition,recurse:o} -return e` - DELETE /v1/kv/${(0,l.default)(i[r.SLUG_KEY])}?${a} - `}}e.default=i})) -define("consul-ui/adapters/node",["exports","consul-ui/adapters/application"],(function(e,t){function n(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function l(e){for(var t=1;t({ID:e.ID}))),RoleDefaults:t.ACLs.RoleDefaults.map((e=>({ID:e.ID})))}}} - `}requestForUpdateRecord(e,t,l){return e` - PUT /v1/namespace/${l[n.SLUG_KEY]}?${{dc:l.Datacenter,partition:l.Partition}} - - ${{Description:t.Description,ACLs:{PolicyDefaults:t.ACLs.PolicyDefaults.map((e=>({ID:e.ID}))),RoleDefaults:t.ACLs.RoleDefaults.map((e=>({ID:e.ID})))}}} - `}requestForDeleteRecord(e,t,l){return e` - DELETE /v1/namespace/${l[n.SLUG_KEY]}?${{dc:l.Datacenter,partition:l.Partition}} - `}}e.default=l})),define("consul-ui/adapters/oidc-provider",["exports","consul-ui/adapters/application","@ember/service"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}requestForQuery(e,t){let{dc:n,ns:l,partition:r,index:i,uri:o}=t -return e` - GET /v1/internal/ui/oidc-auth-methods?${{dc:n}} - X-Request-ID: ${o} - - ${{ns:l,partition:r,index:i}} - `}requestForQueryRecord(e,t){let{dc:n,ns:l,partition:r,id:i}=t -if(void 0===i)throw new Error("You must specify an id") -return e` - POST /v1/acl/oidc/auth-url?${{dc:n,ns:l,partition:r}} - Cache-Control: no-store - - ${{AuthMethod:i,RedirectURI:`${this.env.var("CONSUL_BASE_UI_URL")}/oidc/callback`}} - `}requestForAuthorize(e,t){let{dc:n,ns:l,partition:r,id:i,code:o,state:a}=t -if(void 0===i)throw new Error("You must specify an id") -if(void 0===o)throw new Error("You must specify an code") -if(void 0===a)throw new Error("You must specify an state") -return e` - POST /v1/acl/oidc/callback?${{dc:n,ns:l,partition:r}} - Cache-Control: no-store - - ${{AuthMethod:i,Code:o,State:a}} - `}requestForLogout(e,t){let{id:n}=t -if(void 0===n)throw new Error("You must specify an id") -return e` - POST /v1/acl/logout - Cache-Control: no-store - X-Consul-Token: ${n} - `}authorize(e,t,n,l){return this.rpc((function(e,t,n,l){return e.requestForAuthorize(t,n,l)}),(function(e,t,n,l){return e.respondForAuthorize(t,n,l)}),l,t.modelName)}logout(e,t,n,l){return this.rpc((function(e,t,n,l){return e.requestForLogout(t,n,l)}),(function(e,t,n,l){return{}}),l,t.modelName)}},a=r.prototype,u="env",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/adapters/partition",["exports","consul-ui/adapters/application","consul-ui/models/partition"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{async requestForQuery(e,t){let{ns:n,dc:l,index:r}=t -const i=await(e` - GET /v1/partitions?${{dc:l}} - - ${{index:r}} - `) -return await i(((e,t)=>delete e["x-consul-index"])),i}async requestForQueryRecord(e,t){let{ns:n,dc:l,index:r,id:i}=t -if(void 0===i)throw new Error("You must specify an id") -const o=await(e` - GET /v1/partition/${i}?${{dc:l}} - - ${{index:r}} - `) -return await o(((e,t)=>delete e["x-consul-index"])),o}async requestForCreateRecord(e,t,l){return e` - PUT /v1/partition/${l[n.SLUG_KEY]}?${{dc:l.Datacenter}} - - ${{Name:t.Name,Description:t.Description}} - `}async requestForUpdateRecord(e,t,l){return e` - PUT /v1/partition/${l[n.SLUG_KEY]}?${{dc:l.Datacenter}} - - ${{Description:t.Description}} - `}async requestForDeleteRecord(e,t,l){return e` - DELETE /v1/partition/${l[n.SLUG_KEY]}?${{dc:l.Datacenter}} - `}}e.default=l})),define("consul-ui/adapters/permission",["exports","consul-ui/adapters/application","@ember/service"],(function(e,t,n){var l,r,i,o,a -function u(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function s(e){for(var t=1;ts(s({},e),{},{Namespace:l})))),this.env.var("CONSUL_PARTITIONS_ENABLED")&&(i=i.map((e=>s(s({},e),{},{Partition:r})))),e` - POST /v1/internal/acl/authorize?${{dc:n}} - - ${i} - `}authorize(e,t,n,l){return this.rpc((async(e,t,n,l)=>{const r=this.env.var("CONSUL_NSPACES_ENABLED"),i=this.env.var("CONSUL_PARTITIONS_ENABLED") -if(r||i){const e=await this.settings.findBySlug("token") -r&&(void 0!==n.ns&&0!==n.ns.length||(n.ns=e.Namespace)),i&&(void 0!==n.partition&&0!==n.partition.length||(n.partition=e.Partition))}return e.requestForAuthorize(t,n)}),(function(e,t,n,l){return t((function(e,t){return t}))}),l,t.modelName)}},o=p(i.prototype,"env",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=p(i.prototype,"settings",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) -e.default=f})),define("consul-ui/adapters/policy",["exports","consul-ui/adapters/application","consul-ui/models/policy"],(function(e,t,n){function l(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function r(e){for(var t=1;tdelete e["x-consul-index"])),a}requestForCreateRecord(e,t,n){return e` - PUT /v1/acl/token?${u(u({},this.formatDatacenter(n.Datacenter)),{},{ns:n.Namespace,partition:n.Partition})} - - ${{Description:t.Description,Policies:t.Policies,Roles:t.Roles,ServiceIdentities:t.ServiceIdentities,NodeIdentities:t.NodeIdentities,Local:t.Local}} - `}requestForUpdateRecord(e,t,n){if(void 0!==n.Rules)return e` - PUT /v1/acl/update?${this.formatDatacenter(n.Datacenter)} - - ${t} - ` -const r=u(u({},this.formatDatacenter(n.Datacenter)),{},{ns:n.Namespace,partition:n.Partition}) -return e` - PUT /v1/acl/token/${n[l.SLUG_KEY]}?${r} - - ${{Description:t.Description,Policies:t.Policies,Roles:t.Roles,ServiceIdentities:t.ServiceIdentities,NodeIdentities:t.NodeIdentities,Local:t.Local}} - `}requestForDeleteRecord(e,t,n){const r={dc:n.Datacenter,ns:n.Namespace,partition:n.Partition} -return e` - DELETE /v1/acl/token/${n[l.SLUG_KEY]}?${r} - `}requestForSelf(e,t,n){let{dc:l,index:r,secret:i}=n -return e` - GET /v1/acl/token/self?${{dc:l}} - X-Consul-Token: ${i} - Cache-Control: no-store - - ${{index:r}} - `}requestForCloneRecord(e,t,n){const r=n[l.SLUG_KEY] -if(void 0===r)throw new Error("You must specify an id") -return e` - PUT /v1/acl/token/${r}/clone?${{dc:n.Datacenter,ns:n.Namespace,partition:n.Partition}} - `}self(e,t,n,l){return this.rpc((function(e,t,n,l){return e.requestForSelf(t,n,l)}),(function(e,t,n,l){return e.respondForSelf(t,n,l)}),l,t.modelName)}clone(e,t,n,l){return this.rpc((function(e,t,n,l){return e.requestForCloneRecord(t,n,l)}),((e,t,n,l)=>{const r={dc:l.Datacenter,ns:l.Namespace,partition:l.Partition} -return e.respondForQueryRecord(t,r)}),l,t.modelName)}},d=i.prototype,p="store",f=[r],m={configurable:!0,enumerable:!0,writable:!0,initializer:null},b={},Object.keys(m).forEach((function(e){b[e]=m[e]})),b.enumerable=!!b.enumerable,b.configurable=!!b.configurable,("value"in b||b.initializer)&&(b.writable=!0),b=f.slice().reverse().reduce((function(e,t){return t(d,p,e)||e}),b),h&&void 0!==b.initializer&&(b.value=b.initializer?b.initializer.call(h):void 0,b.initializer=void 0),void 0===b.initializer&&(Object.defineProperty(d,p,b),b=null),o=b,i) -var d,p,f,m,h,b -e.default=c})),define("consul-ui/adapters/topology",["exports","consul-ui/adapters/application"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{requestForQueryRecord(e,t){let{dc:n,ns:l,partition:r,kind:i,index:o,id:a,uri:u}=t -if(void 0===a)throw new Error("You must specify an id") -return e` - GET /v1/internal/ui/service-topology/${a}?${{dc:n,kind:i}} - X-Request-ID: ${u} - - ${{ns:l,partition:r,index:o}} - `}}e.default=n})),define("consul-ui/app",["exports","@ember/application","ember-resolver","ember-load-initializers","consul-ui/config/environment"],(function(e,t,n,l,r){function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class o extends t.default{constructor(){super(...arguments),i(this,"modulePrefix",r.default.modulePrefix),i(this,"podModulePrefix",r.default.podModulePrefix),i(this,"Resolver",n.default)}}e.default=o,(0,l.default)(o,r.default.modulePrefix)})),define("consul-ui/component-managers/glimmer",["exports","@glimmer/component/-private/ember-component-manager"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/-dynamic-element-alt",["exports","@ember/component"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=t.default.extend() -e.default=n})),define("consul-ui/components/-dynamic-element",["exports","@ember/component"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=t.default.extend() -e.default=n})),define("consul-ui/components/action/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"YwHFpVZ2",block:'[[[41,[30,1],[[[11,"label"],[16,"for",[30,1]],[17,2],[12],[18,8,null],[13]],[]],[[[41,[30,3],[[[41,[30,4],[[[11,3],[16,6,[30,3]],[24,"target","_blank"],[24,"rel","noopener noreferrer"],[17,2],[12],[18,8,null],[13]],[]],[[[11,3],[16,6,[30,3]],[17,2],[12],[18,8,null],[13]],[]]]],[]],[[[11,"button"],[16,4,[28,[37,2],[[30,5],"button"],null]],[16,"tabindex",[30,6]],[17,2],[4,[38,3],["click",[28,[37,4],[[30,7]],null]],null],[12],[18,8,null],[13]],[]]]],[]]]],["@for","&attrs","@href","@external","@type","@tabindex","@onclick","&default"],false,["if","yield","or","on","optional"]]',moduleName:"consul-ui/components/action/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/anonymous/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"RdtQ4WaT",block:'[[[18,1,null]],["&default"],false,["yield"]]',moduleName:"consul-ui/components/anonymous/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) -e.default=r})),define("consul-ui/components/app-error/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"4rDG/Mn1",block:'[[[8,[39,0],null,null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n Error "],[1,[30,1,["status"]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@error","@login"],[[30,1],[52,[28,[37,4],[[30,1,["status"]],"403"],null],[30,2]]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]]],[1,"\\n"]],["@error","@login"],false,["app-view","block-slot","error-state","if","eq"]]',moduleName:"consul-ui/components/app-error/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/app-view/index",["exports","@ember/component","@ember/template-factory","block-slots"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"JJpdEf6u",block:'[[[11,0],[24,0,"app-view"],[17,1],[12],[1,"\\n "],[18,2,null],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,"nav"],[14,"aria-label","Breadcrumb"],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],null,[["class"],["with-breadcrumbs"]]]],[1,"\\n "],[18,2,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"title"],[12],[1,"\\n "],[10,0],[14,0,"title-left-container"],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[18,2,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"actions"],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,3],null,[["@name"],["app-view-actions"]],null],[1,"\\n "],[18,2,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,1],null,[["@name"],["nav"]],[["default"],[[[[1,"\\n "],[18,2,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,1],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[18,2,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["content"]],[["default"],[[[[18,2,null]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs","&default"],false,["yield","yield-slot","document-attrs","portal-target"]]',moduleName:"consul-ui/components/app-view/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,t.default.extend(l.default,{tagName:""})) -e.default=i})),define("consul-ui/components/app/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/object"],(function(e,t,n,l,r,i){var o,a,u -function s(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const c=(0,n.createTemplateFactory)({id:"OX4Ky14Q",block:'[[[44,[[28,[37,1],null,[["main","Notification"],[[28,[37,2],[[33,3],"-main"],null],[50,"app/notification",0,null,null]]]]],[[[1,"\\n"],[11,0],[24,0,"app"],[17,2],[12],[1,"\\n\\n "],[11,0],[24,0,"skip-links"],[4,[38,5],["click",[30,0,["focus"]]],null],[12],[1,"\\n "],[8,[39,6],null,[["@name","@multiple"],["app-before-skip-links",true]],[["default"],[[[],[]]]]],[1,"\\n "],[10,3],[15,6,[28,[37,2],["#",[30,1,["main"]]],null]],[12],[1,[28,[35,7],["components.app.skip_to_content"],null]],[13],[1,"\\n"],[1," "],[8,[39,6],null,[["@name","@multiple"],["app-after-skip-links",true]],[["default"],[[[],[]]]]],[1,"\\n "],[13],[1,"\\n\\n "],[8,[39,8],null,null,null],[1,"\\n\\n "],[10,"input"],[15,1,[28,[37,2],[[33,3],"-main-nav-toggle"],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,"header"],[14,"role","banner"],[12],[1,"\\n "],[11,"label"],[24,"tabindex","0"],[16,"for",[28,[37,2],[[33,3],"-main-nav-toggle"],null]],[16,"aria-label",[28,[37,7],["components.app.toggle_menu"],null]],[4,[38,5],["keypress",[30,0,["keypressClick"]]],null],[4,[38,5],["mouseup",[30,0,["unfocus"]]],null],[12],[13],[1,"\\n "],[18,3,[[30,1]]],[1,"\\n "],[10,0],[12],[1,"\\n"],[1," "],[11,"nav"],[16,"aria-label",[28,[37,7],["components.app.main"],null]],[16,0,[52,[30,0,["navInViewport"]],"in-viewport"]],[4,[38,11],null,[["onEnter","onExit","viewportTolerance"],[[28,[37,12],[[30,0],"navInViewport",true],null],[28,[37,12],[[30,0],"navInViewport",false],null],[28,[37,1],null,[["top","bottom","left","right"],[-10,-10,-10,-10]]]]]],[12],[1,"\\n "],[18,4,[[30,1]]],[1,"\\n "],[13],[1,"\\n"],[1," "],[10,"nav"],[15,"aria-label",[28,[37,7],["components.app.complementary"],null]],[12],[1,"\\n "],[18,5,[[30,1]]],[1,"\\n "],[13],[1,"\\n\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"main"],[15,1,[28,[37,2],[[33,3],"-main"],null]],[12],[1,"\\n "],[10,0],[14,0,"notifications"],[12],[1,"\\n "],[18,6,[[30,1]]],[1,"\\n "],[8,[39,6],null,[["@name","@multiple"],["app-notifications",true]],[["default"],[[[],[]]]]],[1,"\\n "],[13],[1,"\\n "],[18,7,[[30,1]]],[1,"\\n "],[13],[1,"\\n "],[10,"footer"],[14,"role","contentinfo"],[12],[1,"\\n "],[18,8,[[30,1]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n\\n"]],[1]]]],["exported","&attrs","&home-nav","&main-nav","&complementary-nav","¬ifications","&main","&content-info"],false,["let","hash","concat","guid","component","on","portal-target","t","modal-layer","yield","if","in-viewport","set"]]',moduleName:"consul-ui/components/app/index.hbs",isStrictMode:!1}) -let d=(o=(0,r.inject)("dom"),a=class extends l.default{constructor(e,t){var n,l,r,i -super(...arguments),n=this,l="dom",i=this,(r=u)&&Object.defineProperty(n,l,{enumerable:r.enumerable,configurable:r.configurable,writable:r.writable,value:r.initializer?r.initializer.call(i):void 0}),this.guid=this.dom.guid(this)}keypressClick(e){e.target.dispatchEvent(new MouseEvent("click"))}focus(e){const t=e.target.getAttribute("href") -t.startsWith("#")&&(e.preventDefault(),this.dom.focus(t))}unfocus(e){e.target.blur()}},u=s(a.prototype,"dom",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s(a.prototype,"keypressClick",[i.action],Object.getOwnPropertyDescriptor(a.prototype,"keypressClick"),a.prototype),s(a.prototype,"focus",[i.action],Object.getOwnPropertyDescriptor(a.prototype,"focus"),a.prototype),s(a.prototype,"unfocus",[i.action],Object.getOwnPropertyDescriptor(a.prototype,"unfocus"),a.prototype),a) -e.default=d,(0,t.setComponentTemplate)(c,d)})),define("consul-ui/components/app/notification/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"OwV217Ed",block:'[[[11,0],[24,0,"app-notification"],[17,1],[4,[38,0],[[28,[37,1],[[28,[37,1],["opacity","1"],null],[28,[37,1],["transition-delay",[28,[37,2],[[30,2],"ms"],null]],null]],null]],null],[4,[38,0],[[28,[37,1],[[28,[37,1],["opacity",[52,[30,3],"1","0"]],null]],null]],[["delay"],[0]]],[12],[1,"\\n "],[18,4,null],[1,"\\n"],[13],[1,"\\n\\n"]],["&attrs","@delay","@sticky","&default"],false,["style","array","concat","if","yield"]]',moduleName:"consul-ui/components/app/notification/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/aria-menu/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object","@ember/runloop"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"W/2RN9qq",block:'[[[18,1,[[28,[37,1],[[30,0],"change"],null],[28,[37,1],[[30,0],"keypress"],null],[28,[37,1],[[30,0],"keypressClick"],null],[28,[37,2],null,[["labelledBy","controls","expanded"],[[28,[37,3],["component-aria-menu-trigger-",[33,4]],null],[28,[37,3],["component-aria-menu-menu-",[33,4]],null],[52,[33,6],"true",[27]]]]]]]],["&default"],false,["yield","action","hash","concat","guid","if","expanded"]]',moduleName:"consul-ui/components/aria-menu/index.hbs",isStrictMode:!1}),a=13,u=32,s=38,c=40,d={vertical:{[c]:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1 -return(t+1)%e.length},[s]:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0 -return 0===t?e.length-1:t-1},36:function(e,t){return 0},35:function(e,t){return e.length-1}},horizontal:{}},p='[role^="menuitem"]' -var f=(0,t.setComponentTemplate)(o,t.default.extend({tagName:"",dom:(0,l.inject)("dom"),guid:"",expanded:!1,orientation:"vertical",keyboardAccess:!0,init:function(){this._super(...arguments),(0,r.set)(this,"guid",this.dom.guid(this)),this._listeners=this.dom.listeners(),this._routelisteners=this.dom.listeners()},didInsertElement:function(){this.$menu=this.dom.element(`#component-aria-menu-menu-${this.guid}`) -const e=this.$menu.getAttribute("aria-labelledby") -this.$trigger=this.dom.element(`#${e}`)},willDestroyElement:function(){this._super(...arguments),this._listeners.remove(),this._routelisteners.remove()},actions:{keypressClick:function(e){e.target.dispatchEvent(new MouseEvent("click"))},keypress:function(e){if(![a,u,s,c].includes(e.keyCode))return -e.stopPropagation() -const t=[...this.dom.elements(p,this.$menu)] -if(e.keyCode===a||e.keyCode===u){let e=this.expanded?void 0:t[0];(0,i.next)((()=>{e=this.expanded?e:this.$trigger,void 0!==e&&e.focus()}))}if(void 0===d[this.orientation][e.keyCode])return -e.preventDefault() -const n=this.dom.element(`${p}:focus`,this.$menu) -let l -n&&(l=t.findIndex((function(e){return e===n}))) -t[d[this.orientation][e.keyCode](t,l)].focus()},change:function(e){e.target.checked?this.actions.open.apply(this,[e]):this.actions.close.apply(this,[e])},close:function(e){this._listeners.remove(),(0,r.set)(this,"expanded",!1),(0,i.next)((()=>{this.$trigger.removeAttribute("tabindex")}))},open:function(e){(0,r.set)(this,"expanded",!0) -0===[...this.dom.elements(p,this.$menu)].length&&this.dom.element('input[type="checkbox"]',this.$menu.parentElement).dispatchEvent(new MouseEvent("click")),this.$trigger.setAttribute("tabindex","-1"),this._listeners.add(this.dom.document(),{keydown:e=>{27===e.keyCode&&this.$trigger.focus(),9!==e.keyCode&&27!==e.keyCode?this.keyboardAccess&&this.actions.keypress.apply(this,[e]):this.$trigger.dispatchEvent(new MouseEvent("click"))}})}}})) -e.default=f})),define("consul-ui/components/auth-dialog/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={id:"auth-dialog",initial:"idle",on:{CHANGE:[{target:"authorized",cond:"hasToken",actions:["login"]},{target:"unauthorized",actions:["logout"]}]},states:{idle:{on:{CHANGE:[{target:"authorized",cond:"hasToken"},{target:"unauthorized"}]}},unauthorized:{},authorized:{}}}})),define("consul-ui/components/auth-dialog/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/object","consul-ui/components/auth-dialog/chart.xstate"],(function(e,t,n,l,r,i,o){var a,u,s -function c(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const d=(0,n.createTemplateFactory)({id:"Nh7efm+X",block:'[[[8,[39,0],null,[["@src"],[[99,1,["@src"]]]],[["default"],[[[[1,"\\n\\n "],[8,[30,2],null,[["@name","@cond"],["hasToken",[28,[37,2],[[30,0],"hasToken"],null]]],null],[1,"\\n "],[8,[30,3],null,[["@name","@exec"],["login",[28,[37,2],[[30,0],"login"],null]]],null],[1,"\\n "],[8,[30,3],null,[["@name","@exec"],["logout",[28,[37,2],[[30,0],"logout"],null]]],null],[1,"\\n\\n"],[1," "],[8,[39,3],null,[["@src","@onchange"],[[30,6],[28,[37,4],[[28,[37,2],[[30,0],[28,[37,5],[[33,6]],null]],[["value"],["data"]]],[28,[37,2],[[30,0],[30,4],"CHANGE"],null],[28,[37,2],[[30,0],[28,[37,5],[[33,7]],null]],[["value"],["data"]]]],null]]],null],[1,"\\n"],[1," "],[8,[39,8],null,[["@sink"],[[30,7]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,10],null,[["login","logout","token"],[[28,[37,2],[[30,0],[30,8,["open"]]],null],[28,[37,2],[[30,0],[30,8,["open"]],null],null],[33,6]]]]],[[[1,"\\n "],[8,[30,1],null,[["@matches"],["authorized"]],[["default"],[[[[1,"\\n "],[18,10,[[30,9]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["unauthorized"]],[["default"],[[[[1,"\\n "],[18,11,[[30,9]]],[1,"\\n "]],[]]]]],[1,"\\n\\n"]],[9]]],[1," "]],[8]]]]],[1,"\\n"]],[1,2,3,4,5]]]]],[1,"\\n"]],["State","Guard","Action","dispatch","state","@src","@sink","sink","api","&authorized","&unauthorized"],false,["state-chart","chart","action","data-source","queue","mut","token","previousToken","data-sink","let","hash","yield"]]',moduleName:"consul-ui/components/auth-dialog/index.hbs",isStrictMode:!1}) -let p=(a=(0,r.inject)("repository/oidc-provider"),u=class extends l.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="repo",l=this,(n=s)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),this.chart=o.default}hasToken(){return void 0!==this.token.AccessorID}login(){let e=(0,i.get)(this,"previousToken.AccessorID"),t=(0,i.get)(this,"token.AccessorID") -null===e&&(e=(0,i.get)(this,"previousToken.SecretID")),null===t&&(t=(0,i.get)(this,"token.SecretID")) -let n="authorize" -void 0!==e&&e!==t&&(n="use"),this.args.onchange({data:(0,i.get)(this,"token"),type:n})}logout(){void 0!==(0,i.get)(this,"previousToken.AuthMethod")&&this.repo.logout((0,i.get)(this,"previousToken.SecretID")),this.previousToken=null,this.args.onchange({data:null,type:"logout"})}},s=c(u.prototype,"repo",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c(u.prototype,"hasToken",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"hasToken"),u.prototype),c(u.prototype,"login",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"login"),u.prototype),c(u.prototype,"logout",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"logout"),u.prototype),u) -e.default=p,(0,t.setComponentTemplate)(d,p)})),define("consul-ui/components/auth-form/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={id:"auth-form",initial:"idle",on:{RESET:[{target:"idle"}],ERROR:[{target:"error"}]},states:{idle:{entry:["clearError"],on:{SUBMIT:[{target:"loading",cond:"hasValue"},{target:"error"}]}},loading:{},error:{exit:["clearError"],on:{TYPING:[{target:"idle"}],SUBMIT:[{target:"loading",cond:"hasValue"},{target:"error"}]}}}}})),define("consul-ui/components/auth-form/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","consul-ui/components/auth-form/chart.xstate","consul-ui/components/auth-form/tabs.xstate"],(function(e,t,n,l,r,i,o){var a -function u(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const s=(0,n.createTemplateFactory)({id:"35JQNcNu",block:'[[[8,[39,0],null,[["@src"],[[30,0,["chart"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,2],null,[["State","Guard","Action","dispatch","state"],[[30,1],[30,2],[30,3],[30,4],[30,5]]]]],[[[44,[[28,[37,2],null,[["reset","focus","disabled","error","submit"],[[28,[37,3],[[30,0],[30,4],"RESET"],null],[30,0,["focus"]],[28,[37,4],[[30,5],"loading"],null],[28,[37,5],[[28,[37,3],[[30,0],[30,4],"ERROR"],null],[28,[37,3],[[30,0],[28,[37,6],[[30,0,["error"]]],null]],[["value"],["error.errors.firstObject"]]]],null],[28,[37,5],[[28,[37,3],[[30,0],[28,[37,6],[[30,0,["value"]]],null]],null],[28,[37,3],[[30,0],[30,4],"SUBMIT"],null]],null]]]]],[[[1," "],[8,[30,2],null,[["@name","@cond"],["hasValue",[30,0,["hasValue"]]]],null],[1,"\\n"],[1," "],[8,[30,6,["Action"]],null,[["@name","@exec"],["clearError",[28,[37,5],[[28,[37,3],[[30,0],[28,[37,6],[[30,0,["error"]]],null],[27]],null],[28,[37,3],[[30,0],[28,[37,6],[[30,0,["secret"]]],null],[27]],null]],null]]],null],[1,"\\n "],[11,0],[24,0,"auth-form"],[17,8],[12],[1,"\\n "],[8,[39,0],null,[["@src"],[[30,0,["tabsChart"]]]],[["default"],[[[[1,"\\n"],[41,[28,[37,8],["use SSO"],null],[[[1," "],[8,[39,9],null,[["@items","@onclick"],[[28,[37,10],[[28,[37,2],null,[["label","selected"],["Token",[28,[37,4],[[30,13],"token"],null]]]],[28,[37,2],null,[["label","selected"],["SSO",[28,[37,4],[[30,13],"sso"],null]]]]],null],[28,[37,5],[[28,[37,3],[[30,0],[30,12]],null],[28,[37,3],[[30,0],[30,4],"RESET"],null]],null]]],null],[1,"\\n"]],[]],null],[1," "],[8,[30,1],null,[["@matches"],["error"]],[["default"],[[[[1,"\\n"],[41,[30,0,["error","status"]],[[[1," "],[8,[39,11],[[24,0,"mb-1 mt-2"]],[["@type","@color"],["inline","critical"]],[["default"],[[[[1,"\\n "],[8,[30,14,["Title"]],null,null,[["default"],[[[[1,"\\n"],[41,[30,0,["value","Name"]],[[[41,[28,[37,12],[[30,0,["error","status"]],"403"],null],[[[1," Consul login failed\\n"]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"401"],null],[[[1," Could not log in to provider\\n"]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"499"],null],[[[1," SSO log in window closed\\n"]],[]],[[[1," Error\\n "]],[]]]],[]]]],[]]]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"403"],null],[[[1," Invalid token\\n"]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"404"],null],[[[1," No providers\\n"]],[]],[[[1," Error\\n "]],[]]]],[]]]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[30,14,["Description"]],null,null,[["default"],[[[[1,"\\n"],[41,[30,0,["value","Name"]],[[[41,[28,[37,12],[[30,0,["error","status"]],"403"],null],[[[1," We received a token from your OIDC provider but could not log in to Consul\\n with it.\\n"]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"401"],null],[[[1," The OIDC provider has rejected this access token. Please have an\\n administrator check your auth method configuration.\\n"]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"499"],null],[[[1," The OIDC provider window was closed. Please try again.\\n"]],[]],[[[1," "],[1,[30,0,["error","detail"]]],[1,"\\n "]],[]]]],[]]]],[]]]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"403"],null],[[[1," The token entered does not exist. Please enter a valid token to log in.\\n"]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"404"],null],[[[1," No SSO providers are configured for that Partition.\\n"]],[]],[[[1," "],[1,[30,0,["error","detail"]]],[1,"\\n "]],[]]]],[]]]],[]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[30,9],null,[["@matches"],["token"]],[["default"],[[[[1,"\\n "],[10,"form"],[15,"onsubmit",[28,[37,3],[[30,0],[30,4],"SUBMIT"],null]],[12],[1,"\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"label"],[15,0,[28,[37,13],["type-password",[52,[28,[37,14],[[28,[37,4],[[30,5],"error"],null],[28,[37,15],[[30,0,["error","status"]]],null]],null]," has-error"]],null]],[12],[1,"\\n "],[10,1],[12],[1,"Log in with a token"],[13],[1,"\\n\\n"],[1," "],[11,"input"],[16,"disabled",[28,[37,4],[[30,5],"loading"],null]],[24,3,"auth[SecretID]"],[24,"placeholder","SecretID"],[16,2,[30,0,["secret"]]],[16,"oninput",[28,[37,5],[[28,[37,3],[[30,0],[28,[37,6],[[30,0,["secret"]]],null]],[["value"],["target.value"]]],[28,[37,3],[[30,0],[28,[37,6],[[30,0,["value"]]],null]],[["value"],["target.value"]]],[28,[37,3],[[30,0],[30,4],"TYPING"],null]],null]],[16,4,[52,[28,[37,12],[[28,[37,16],["environment"],null],"testing"],null],"text","password"]],[4,[38,17],[[28,[37,18],[[30,0],"input"],null]],null],[12],[13],[1,"\\n "],[8,[30,1],null,[["@matches"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,15],[[30,0,["error","status"]]],null],[[[1," "],[10,"strong"],[14,"role","alert"],[12],[1,"\\n Please enter your secret\\n "],[13],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,19],[[16,"disabled",[28,[37,4],[[30,5],"loading"],null]],[24,4,"submit"]],[["@text"],["Log in"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[18,19,[[28,[37,21],[[30,7],[28,[37,2],null,[["Method"],[[30,9]]]]],null]]],[1,"\\n\\n "],[10,"em"],[12],[1,"\\n Contact your administrator for login credentials.\\n "],[13],[1,"\\n "]],[9,10,11,12,13]]]]],[1,"\\n\\n "],[13],[1,"\\n "],[8,[30,1],null,[["@matches"],["loading"]],[["default"],[[[[1,"\\n "],[8,[39,22],null,[["@dc","@nspace","@partition","@type","@value","@onchange","@onerror"],[[30,15],[28,[37,23],[[30,0,["value","Namespace"]],[30,16]],null],[28,[37,23],[[30,0,["value","Partition"]],[30,17]],null],[52,[30,0,["value","Name"]],"oidc","secret"],[30,0,["value"]],[28,[37,5],[[28,[37,3],[[30,0],[30,4],"RESET"],null],[30,18]],null],[28,[37,5],[[28,[37,3],[[30,0],[28,[37,6],[[30,0,["error"]]],null]],[["value"],["error.errors.firstObject"]]],[28,[37,3],[[30,0],[30,4],"ERROR"],null]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[7]]]],[6]]]],[1,2,3,4,5]]]]],[1,"\\n"]],["State","Guard","ChartAction","dispatch","state","chart","exported","&attrs","TabState","IgnoredGuard","IgnoredAction","tabDispatch","tabState","A","@dc","@nspace","@partition","@onsubmit","&default"],false,["state-chart","let","hash","action","state-matches","queue","mut","if","can","tab-nav","array","hds/alert","eq","concat","and","not","env","did-insert","set","hds/button","yield","assign","token-source","or"]]',moduleName:"consul-ui/components/auth-form/index.hbs",isStrictMode:!1}) -let c=(a=class extends l.default{constructor(){super(...arguments),this.chart=i.default,this.tabsChart=o.default}hasValue(e,t,n){return""!==this.value&&void 0!==this.value}focus(){this.input.focus()}},u(a.prototype,"hasValue",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"hasValue"),a.prototype),u(a.prototype,"focus",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"focus"),a.prototype),a) -e.default=c,(0,t.setComponentTemplate)(s,c)})),define("consul-ui/components/auth-form/tabs.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={id:"auth-form-tabs",initial:"token",on:{TOKEN:[{target:"token"}],SSO:[{target:"sso"}]},states:{token:{},sso:{}}}})),define("consul-ui/components/auth-profile/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"FSF8r1GE",block:'[[[11,"dl"],[24,0,"auth-profile"],[17,1],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[10,1],[12],[1,"My ACL Token"],[13],[10,"br"],[12],[13],[1,"\\n AccessorID\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,0],[[30,2,["AccessorID"]],[28,[37,1],[[30,2,["AccessorID","length"]],8],null]],null]],[1,"\\n "],[13],[1,"\\n"],[13]],["&attrs","@item"],false,["string-substring","sub"]]',moduleName:"consul-ui/components/auth-profile/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})) -define("consul-ui/components/basic-dropdown-content",["exports","ember-basic-dropdown/components/basic-dropdown-content"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/basic-dropdown-optional-tag",["exports","ember-basic-dropdown/components/basic-dropdown-optional-tag"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/basic-dropdown-trigger",["exports","ember-basic-dropdown/components/basic-dropdown-trigger"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/basic-dropdown",["exports","ember-basic-dropdown/components/basic-dropdown"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/block-slot",["exports","block-slots/components/block-slot"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/brand-loader/enterprise",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"DW5EhD40",block:'[[[10,"path"],[14,"data-enterprise-logo",""],[14,"d","M322.099,18.0445001 C319.225,18.0223001 316.427,18.9609001 314.148,20.7112001 L314.016,20.8179001 L313.68,18.5368001 L310.332,18.5368001 L310.332,53.0000001 L314.312,52.4338001 L314.312,42.3164001 L314.435,42.3164001 C316.705,42.7693001 319.012,43.0165001 321.327,43.0549001 C326.554,43.0549001 329.098,40.5029001 329.098,35.2432001 L329.098,25.3802001 C329.073,20.4569001 326.809,18.0445001 322.099,18.0445001 Z M264.971,11.9722001 L260.991,12.5466001 L260.991,18.5284001 L256.708,18.5284001 L256.708,21.8106001 L260.991,21.8106001 L260.991,37.6883001 L260.99344,37.9365729 C261.066744,41.6122056 262.7975,43.1124033 266.915,43.1124033 C268.591,43.1170001 270.255,42.8396001 271.839,42.2915001 L271.363,39.1817001 L270.896229,39.3066643 C269.803094,39.5806719 268.682875,39.7315001 267.555,39.7560001 C265.526625,39.7560001 265.081547,38.9674128 264.991981,37.7056542 L264.97743,37.4176027 L264.97159,37.1147428 L264.971,21.8188001 L271.494,21.8188001 L271.83,18.5366001 L264.971,18.5366001 L264.971,11.9722001 Z M283.556,18.0770001 C277.312,18.0770001 274.144,21.0884001 274.144,27.0374001 L274.144,34.3075001 C274.144,40.3140001 277.164,43.1124894 283.655,43.1124894 C286.526,43.1192001 289.38,42.6620001 292.106,41.7581001 L291.589,38.6154001 C289.116,39.3030001 286.566,39.6779001 283.999,39.7314001 C279.785843,39.7314001 278.500803,38.4772648 278.201322,35.860808 L278.165734,35.4868687 L278.141767,35.0951811 C278.138675,35.0284172 278.136019,34.9609111 278.133774,34.8926614 L278.125037,34.474229 L278.124,32.0756001 L292.582,32.0756001 L292.582,27.1031001 C292.582,21.0064001 289.636,18.0770001 283.556,18.0770001 Z M384.631,18.0768001 C378.412,18.0440001 375.22,21.0554001 375.22,27.0208001 L375.22,34.2909001 C375.22,40.2973001 378.239,43.0955988 384.73,43.0955988 C387.599,43.1033001 390.45,42.6460001 393.173,41.7415001 L392.665,38.5988001 C390.188,39.2815001 387.635,39.6509001 385.066,39.6983001 C380.852843,39.6983001 379.567803,38.4442359 379.268322,35.8278014 L379.232734,35.4538649 L379.208767,35.0621794 C379.205675,34.9954158 379.203019,34.9279099 379.200774,34.8596604 L379.192037,34.4412289 L379.191,32.0754001 L393.657,32.0754001 L393.657,27.1029001 C393.657,21.0062001 390.712,18.0768001 384.631,18.0768001 Z M364.634,18.0441001 C363.881125,18.0441001 363.18736,18.0712813 362.54969,18.1279834 L362.016783,18.1838695 C357.948857,18.6791301 356.371,20.5353768 356.371,24.4608001 L356.371522,24.7155013 L356.376145,25.2052033 L356.386527,25.669464 L356.403852,26.1092746 C356.407384,26.1805939 356.411254,26.2509357 356.415488,26.3203208 L356.445451,26.7253144 L356.485319,27.1083357 C356.756619,29.3425283 357.626845,30.4437319 360.247859,31.3753061 L360.701103,31.529163 C360.779411,31.5545991 360.85912,31.5799457 360.940253,31.6052232 L361.444353,31.7562266 L361.983836,31.9065664 L362.55989,32.0572338 L363.430663,32.2724269 L364.440153,32.5299129 L364.884369,32.6506971 L365.29049,32.7679922 L365.660213,32.8831607 L365.99523,32.9975651 C367.26815,33.4554713 367.748817,33.9277406 367.925217,34.806783 L367.963261,35.0352452 C367.974017,35.1143754 367.982943,35.1965576 367.990321,35.2820187 L368.008092,35.5484662 L368.018269,35.8359502 L368.023,36.3096001 C368.023,36.3683432 368.022674,36.4261667 368.021989,36.4830819 L368.013333,36.8137655 C368.008847,36.9204214 368.002676,37.0235359 367.994568,37.1232009 L367.964177,37.4119383 C367.774513,38.8512264 367.058626,39.4837671 364.875404,39.6510671 L364.43427,39.67773 L363.954974,39.6933243 C363.78868,39.6967387 363.615773,39.6984001 363.436,39.6984001 C361.126,39.6638001 358.83,39.3385001 356.601,38.7302001 L356.051,41.7908001 L356.619468,41.9710684 C358.900888,42.6645722 361.270923,43.0269154 363.658,43.0463001 C369.59355,43.0463001 371.402903,41.3625861 371.812159,38.0405419 L371.854011,37.6421573 C371.859965,37.574501 371.865421,37.5062155 371.870401,37.4373012 L371.894725,37.0162715 L371.908596,36.5801656 C371.911587,36.4322862 371.913,36.2818967 371.913,36.1290001 L371.914417,35.5317322 C371.901583,33.4289389 371.677,32.2649251 370.797,31.3698001 C370.053077,30.6022731 368.787947,30.0494771 366.870096,29.4840145 L366.242608,29.3047611 C366.13436,29.2747269 366.024265,29.2445914 365.912304,29.2143213 L365.218,29.0308209 L364.216102,28.7784328 L363.495981,28.593015 L363.068145,28.4733265 L362.67987,28.3551624 C361.018765,27.8247783 360.501056,27.2986662 360.340522,26.2094051 L360.310407,25.9578465 C360.306262,25.9142982 360.302526,25.8699197 360.29916,25.8246823 L360.283089,25.5427193 L360.273984,25.2387571 L360.269927,24.911412 L360.270221,24.3885398 L360.280627,24.0635689 C360.366727,22.3885604 360.966747,21.6370879 363.248047,21.4645754 L363.695778,21.4389299 L364.184625,21.426349 L364.445,21.4248001 C366.684,21.4608001 368.916,21.6859001 371.117,22.0976001 L371.396,18.8646001 L370.730951,18.7059457 C368.73071,18.2553391 366.686,18.0331201 364.634,18.0441001 Z M351.301,18.5363001 L347.321,18.5363001 L347.321,42.6112001 L351.301,42.6112001 L351.301,18.5363001 Z M307.335,18.0850001 L306.70097,18.3638937 C304.598769,19.3169298 302.610091,20.5031364 300.771,21.9005001 L300.623,22.0236001 L300.369,18.5363001 L296.931,18.5363001 L296.931,42.6112001 L300.91,42.6112001 L300.91,25.9048001 L301.641825,25.3925123 C303.604371,24.0427531 305.654445,22.8240667 307.778,21.7446001 L307.335,18.0850001 Z M344.318,18.0850001 L343.683947,18.3638937 C341.581595,19.3169298 339.592091,20.5031364 337.753,21.9005001 L337.606,22.0236001 L337.351,18.5363001 L333.946,18.5363001 L333.946,42.6112001 L337.926,42.6112001 L337.926,25.9048001 L337.967,25.9048001 L338.701162,25.3884311 C340.669963,24.0279284 342.726556,22.7996223 344.859,21.7118001 L344.318,18.0850001 Z M230.384,9.62500005 L211.109,9.62500005 L211.109,42.6112001 L230.466,42.6112001 L230.466,38.9597001 L215.146,38.9597001 L215.146,27.4720001 L229.293,27.4720001 L229.293,23.8698001 L215.146,23.8698001 L215.146,13.2600001 L230.384,13.2600001 L230.384,9.62500005 Z M248.763,18.0441001 C245.899,18.0441001 241.706,19.3323001 239.047,20.6124001 L238.924,20.6698001 L238.522,18.5282001 L235.322,18.5282001 L235.322,42.5704001 L239.302,42.5704001 L239.302,24.2885001 L239.359,24.2885001 C241.919,22.9674001 245.661,21.8268001 247.524,21.8268001 C249.165,21.8268001 249.985,22.5735001 249.985,24.1736001 L249.985,42.5868001 L253.965,42.5868001 L253.965,24.1161001 C253.932,20.0380001 252.25,18.0523001 248.763,18.0441001 Z M321.229,21.5564001 C323.526,21.5564001 325.061,22.2046001 325.061,25.3966001 L325.094,35.2760001 C325.094,38.3121001 323.887,39.6085001 321.057,39.6085001 C318.81,39.5533001 316.572,39.3035001 314.369,38.8618001 L314.287,38.8618001 L314.287,24.4694001 C316.198,22.7311001 318.649,21.7027001 321.229,21.5564001 Z M283.581,21.3264001 C287.372,21.3264001 288.758,22.8855001 288.758,26.7010001 L288.758,28.7934001 L278.149,28.7934001 L278.149,26.7010001 C278.149,22.9839001 279.79,21.3264001 283.581,21.3264001 Z M384.648,21.3262001 C388.431,21.3262001 389.834,22.8852001 389.834,26.7008001 L389.834,28.7932001 L379.224,28.7932001 L379.224,26.7008001 C379.224,22.9837001 380.865,21.3262001 384.648,21.3262001 Z M351.301,8.63220005 L347.321,8.63220005 L347.321,14.4499001 L351.301,14.4499001 L351.301,8.63220005 Z"],[14,"fill-rule","nonzero"],[12],[13],[1,"\\n\\n"]],[],false,[]]',moduleName:"consul-ui/components/brand-loader/enterprise.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/brand-loader/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"yNoyAgqg",block:'[[[10,0],[14,0,"brand-loader"],[15,5,[29,["margin-left: calc(-",[30,1],"px / 2)"]]],[12],[1,"\\n"],[10,"svg"],[15,"width",[29,[[30,1]]]],[14,"height","53"],[14,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[15,"fill",[29,[[30,2]]]],[12],[1,"\\n "],[10,"path"],[14,"d","M32.7240001,0.866235051 C28.6239001,-0.218137949 24.3210001,-0.285465949 20.1890001,0.670096051 C16.0569001,1.62566005 12.2205001,3.57523005 9.01276015,6.34960005 C5.80499015,9.12397005 3.32280015,12.6393001 1.78161015,16.5905001 C0.240433148,20.5416001 -0.313157852,24.8092001 0.168892148,29.0228001 C0.650943148,33.2364001 2.15407015,37.2687001 4.54780015,40.7697001 C6.94153015,44.2707001 10.1535001,47.1346001 13.9050001,49.1128001 C17.6565001,51.0910001 21.8341001,52.1238001 26.0752001,52.1214409 C32.6125001,52.1281001 38.9121001,49.6698001 43.7170001,45.2370001 L37.5547001,38.7957001 C35.0952001,41.0133001 32.0454001,42.4701001 28.7748001,42.9898001 C25.5042001,43.5096001 22.1530001,43.0698001 19.1273001,41.7239001 C16.1015001,40.3779001 13.5308001,38.1835001 11.7267001,35.4064001 C9.92260015,32.6294001 8.96239015,29.3888001 8.96239015,26.0771001 C8.96239015,22.7655001 9.92260015,19.5249001 11.7267001,16.7478001 C13.5308001,13.9707001 16.1015001,11.7763001 19.1273001,10.4304001 C22.1530001,9.08444005 25.5042001,8.64470005 28.7748001,9.16441005 C32.0454001,9.68412005 35.0952001,11.1410001 37.5547001,13.3586001 L43.7170001,6.89263005 C40.5976001,4.01926005 36.8241001,1.95061005 32.7240001,0.866235051 Z M46.6320001,34.8572001 C46.2182001,34.9395001 45.8380001,35.1427001 45.5397001,35.4410001 C45.2413001,35.7394001 45.0381001,36.1195001 44.9558001,36.5334001 C44.8735001,36.9472001 44.9157001,37.3762001 45.0772001,37.7660001 C45.2387001,38.1559001 45.5121001,38.4891001 45.8630001,38.7235001 C46.2138001,38.9579001 46.6263001,39.0830001 47.0482001,39.0830001 C47.6141001,39.0830001 48.1567001,38.8583001 48.5568001,38.4582001 C48.9569001,38.0581001 49.1817001,37.5154001 49.1817001,36.9496001 C49.1817001,36.5276001 49.0565001,36.1152001 48.8221001,35.7643001 C48.5877001,35.4135001 48.2545001,35.1400001 47.8647001,34.9786001 C47.4748001,34.8171001 47.0459001,34.7748001 46.6320001,34.8572001 Z M49.0856001,27.5622001 C48.6718001,27.6446001 48.2916001,27.8477001 47.9933001,28.1461001 C47.6949001,28.4445001 47.4917001,28.8246001 47.4094001,29.2385001 C47.3271001,29.6523001 47.3693001,30.0813001 47.5308001,30.4711001 C47.6923001,30.8609001 47.9657001,31.1941001 48.3166001,31.4286001 C48.6674001,31.6630001 49.0799001,31.7881001 49.5018001,31.7881001 C50.0670001,31.7859001 50.6084001,31.5605001 51.0080001,31.1609001 C51.4076001,30.7612001 51.6331001,30.2198001 51.6353001,29.6547001 C51.6353001,29.2327001 51.5102001,28.8202001 51.2757001,28.4694001 C51.0413001,28.1186001 50.7081001,27.8451001 50.3183001,27.6836001 C49.9284001,27.5222001 49.4995001,27.4799001 49.0856001,27.5622001 Z M28.0728001,20.8457001 C27.0412001,20.4185001 25.9061001,20.3067001 24.8110001,20.5245001 C23.7159001,20.7423001 22.7100001,21.2800001 21.9205001,22.0695001 C21.1309001,22.8590001 20.5933001,23.8650001 20.3754001,24.9600001 C20.1576001,26.0551001 20.2694001,27.1902001 20.6967001,28.2218001 C21.1240001,29.2534001 21.8476001,30.1351001 22.7760001,30.7554001 C23.7043001,31.3757001 24.7958001,31.7068001 25.9124001,31.7068001 C27.4096001,31.7068001 28.8455001,31.1120001 29.9043001,30.0533001 C30.9630001,28.9946001 31.5578001,27.5587001 31.5578001,26.0614001 C31.5578001,24.9449001 31.2267001,23.8534001 30.6063001,22.9250001 C29.9860001,21.9966001 29.1043001,21.2730001 28.0728001,20.8457001 Z M43.9670001,27.4378001 C43.5772001,27.2763001 43.1482001,27.2341001 42.7344001,27.3164001 C42.3205001,27.3987001 41.9404001,27.6019001 41.6420001,27.9003001 C41.3437001,28.1986001 41.1405001,28.5788001 41.0581001,28.9926001 C40.9758001,29.4065001 41.0181001,29.8354001 41.1796001,30.2253001 C41.3410001,30.6151001 41.6145001,30.9483001 41.9653001,31.1827001 C42.3162001,31.4171001 42.7286001,31.5423001 43.1506001,31.5423001 C43.7164001,31.5423001 44.2591001,31.3175001 44.6592001,30.9174001 C45.0592001,30.5173001 45.2840001,29.9747001 45.2840001,29.4088001 C45.2840001,28.9869001 45.1589001,28.5744001 44.9245001,28.2236001 C44.6901001,27.8727001 44.3568001,27.5993001 43.9670001,27.4378001 Z M43.9670001,20.7503001 C43.5772001,20.5888001 43.1482001,20.5466001 42.7344001,20.6289001 C42.3205001,20.7112001 41.9404001,20.9144001 41.6420001,21.2128001 C41.3437001,21.5111001 41.1405001,21.8913001 41.0581001,22.3051001 C40.9758001,22.7190001 41.0181001,23.1479001 41.1796001,23.5378001 C41.3410001,23.9276001 41.6145001,24.2608001 41.9653001,24.4952001 C42.3162001,24.7296001 42.7286001,24.8548001 43.1506001,24.8548001 C43.7164001,24.8548001 44.2591001,24.6300001 44.6592001,24.2299001 C45.0592001,23.8298001 45.2840001,23.2871001 45.2840001,22.7213001 C45.2840001,22.2994001 45.1589001,21.8869001 44.9245001,21.5360001 C44.6901001,21.1852001 44.3568001,20.9118001 43.9670001,20.7503001 Z M49.0856001,20.3825001 C48.6718001,20.4649001 48.2916001,20.6681001 47.9933001,20.9664001 C47.6949001,21.2648001 47.4917001,21.6449001 47.4094001,22.0588001 C47.3271001,22.4726001 47.3693001,22.9016001 47.5308001,23.2914001 C47.6923001,23.6813001 47.9657001,24.0144001 48.3166001,24.2489001 C48.6674001,24.4833001 49.0799001,24.6084001 49.5018001,24.6084001 C50.0670001,24.6063001 50.6084001,24.3808001 51.0080001,23.9812001 C51.4076001,23.5815001 51.6331001,23.0401001 51.6353001,22.4750001 C51.6353001,22.0530001 51.5102001,21.6406001 51.2757001,21.2897001 C51.0413001,20.9389001 50.7081001,20.6654001 50.3183001,20.5040001 C49.9284001,20.3425001 49.4995001,20.3002001 49.0856001,20.3825001 Z M46.7554001,13.2026001 C46.3416001,13.2849001 45.9614001,13.4881001 45.6630001,13.7865001 C45.3647001,14.0849001 45.1615001,14.4650001 45.0792001,14.8788001 C44.9969001,15.2927001 45.0391001,15.7217001 45.2006001,16.1115001 C45.3621001,16.5013001 45.6355001,16.8345001 45.9863001,17.0689001 C46.3372001,17.3034001 46.7497001,17.4285001 47.1716001,17.4285001 C47.7374001,17.4285001 48.2801001,17.2037001 48.6802001,16.8036001 C49.0803001,16.4035001 49.3050001,15.8609001 49.3050001,15.2951001 C49.3050001,14.8731001 49.1799001,14.4606001 48.9455001,14.1098001 C48.7111001,13.7589001 48.3779001,13.4855001 47.9880001,13.3240001 C47.5982001,13.1625001 47.1692001,13.1203001 46.7554001,13.2026001 Z"],[14,"fill-rule","nonzero"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M83.5385001,9.02612084 C75.3002001,9.02612084 71.7718001,12.5545001 71.7718001,18.6102001 L71.7718001,33.5278001 L71.7744126,33.809806 C71.8842215,39.6928981 75.4612111,43.1118103 83.5385001,43.1118103 C86.5802001,43.1131001 89.6109001,42.7466001 92.5646001,42.0205001 L91.8671001,36.6049001 L90.9760579,36.7631811 C88.5964705,37.1629803 86.1899224,37.3844223 83.7765001,37.4254001 C79.4194001,37.4254001 78.0326001,35.9320001 78.0326001,32.4118001 L78.0326001,19.7261001 L78.0346281,19.4988781 C78.0956946,16.133828 79.5462067,14.7125001 83.7765001,14.7125001 C86.4916001,14.7587001 89.1980001,15.0332001 91.8671001,15.5331001 L92.5646001,10.1175001 L91.8246092,9.94345672 C89.1057071,9.33281156 86.3267251,9.02500229 83.5385001,9.02612084 Z M172.149,18.4131001 L166.094,18.4131001 L166.09588,36.2248122 C166.154955,40.3975255 167.61375,43.1117001 171.55,43.1117001 C174.919,42.9517001 178.218,42.0880001 181.233,40.5762001 L181.832,42.6112001 L186.443,42.6112001 L186.443,18.4131001 L180.388,18.4131001 L180.388,35.1934001 C178.188,36.3339001 175.481,37.2283001 174.086,37.2283001 C172.691,37.2283001 172.149,36.5801001 172.149,35.2918001 L172.149,18.4131001 Z M105.939,17.9127001 C98.2719471,17.9127001 95.7845671,21.8519543 95.4516942,26.3358062 L95.4257941,26.7784774 C95.4225999,26.8525088 95.4199581,26.9266566 95.4178553,27.0009059 L95.4116001,27.4475001 L95.4116001,33.5853001 L95.4178331,34.0318054 C95.5519456,38.7818866 97.886685,43.0872001 105.931,43.0872001 C113.716697,43.0872001 116.15821,39.0467642 116.432186,34.4757046 L116.45204,34.0318054 C116.456473,33.8833653 116.458758,33.734491 116.459,33.5853001 L116.459,27.4475001 L116.457455,27.2221358 C116.453317,26.9220505 116.440796,26.6236441 116.419035,26.3278463 L116.379357,25.8862225 C115.91894,21.5651129 113.355121,17.9127001 105.939,17.9127001 Z M154.345,17.8876515 C147.453,17.8876515 145.319,20.0214001 145.319,24.8873001 L145.319694,25.1343997 L145.325703,25.6107983 L145.338905,26.064173 C145.341773,26.1378641 145.344992,26.2106314 145.348588,26.2824927 L145.374889,26.7029295 C145.380095,26.7712375 145.385729,26.838675 145.391816,26.9052596 L145.433992,27.2946761 C145.714183,29.5082333 146.613236,30.7206123 149.232713,31.693068 L149.698825,31.8575665 C150.021076,31.9658547 150.36662,32.0715774 150.737101,32.1758709 L151.311731,32.3313812 C151.509646,32.3829554 151.714,32.4343143 151.925,32.4856001 L152.205551,32.5543061 L152.728976,32.6899356 L153.204098,32.8237311 L153.633238,32.9563441 C155.53221,33.5734587 156.004908,34.1732248 156.112605,35.0535762 L156.130482,35.2466262 L156.139507,35.448917 L156.142,35.6611001 L156.137247,35.9859786 L156.121298,36.2838969 C156.024263,37.5177444 155.540462,38.0172149 153.741624,38.1073495 L153.302742,38.1210314 L153.065,38.1227001 C150.631,38.0987001 148.21,37.7482001 145.869,37.0807001 L145.049,41.6922001 L145.672496,41.887484 C148.174444,42.639635 150.769923,43.0436231 153.385,43.0871001 C159.627887,43.0871001 161.583469,40.9824692 162.030289,37.4548504 L162.074576,37.049455 C162.087289,36.9123213 162.098004,36.7731979 162.106868,36.6321214 L162.128062,36.2030694 L162.139051,35.7625187 L162.141,35.5380001 C162.141,35.4566181 162.140828,35.3763299 162.14046,35.2971136 L162.131203,34.6125174 L162.117224,34.1865271 L162.095649,33.7836378 L162.065324,33.4027996 L162.025093,33.0429627 L161.973799,32.7030773 C161.659145,30.8866498 160.790109,29.9278873 158.501441,29.0408119 L158.069484,28.8801405 L157.605084,28.7199991 C157.524916,28.6932947 157.443348,28.6665687 157.360357,28.6397991 L156.845127,28.4784845 L156.294565,28.3150754 L155.707516,28.148522 L155.082823,27.9777746 L154.035614,27.7021396 L153.423677,27.5325226 L153.071612,27.4262327 C153.016479,27.4088193 152.963082,27.3915263 152.911366,27.3743086 L152.620815,27.2715428 C151.671458,26.912485 151.415595,26.5466416 151.348761,25.7543883 L151.334373,25.5160648 L151.327658,25.2523603 L151.327351,24.8244501 C151.355827,23.4390475 151.851313,22.8769001 154.403,22.8769001 C156.636,22.9360001 158.861,23.1692001 161.057,23.5744001 L161.591,18.7085001 L160.876597,18.5511522 C158.72872,18.1040608 156.5401,17.8816774 154.345,17.8876515 Z M197.71,7.71350005 L191.654,8.53405005 L191.654,42.6116001 L197.71,42.6116001 L197.71,7.71350005 Z M135.455,17.9211001 C132.086,18.0823001 128.788,18.9459001 125.772,20.4566001 L125.189,18.4135001 L120.57,18.4135001 L120.57,42.6115001 L126.625,42.6115001 L126.625,25.8066001 C128.833,24.6661001 131.549,23.7717001 132.936,23.7717001 C134.322,23.7717001 134.872,24.4199001 134.872,25.7082001 L134.872,42.6115001 L140.919,42.6115001 L140.919,25.0681001 C140.919,20.7520001 139.475,17.9211001 135.455,17.9211001 Z M105.931,23.0740001 C109.156,23.0740001 110.395,24.5592001 110.395,27.2506001 L110.395,33.7494001 L110.392134,33.9740961 C110.325067,36.5604698 109.074195,37.9178001 105.931,37.9178001 C102.698,37.9178001 101.459,36.4818001 101.459,33.7494001 L101.459,27.2506001 L101.461884,27.0258853 C101.529372,24.4390811 102.787806,23.0740001 105.931,23.0740001 Z"],[14,"fill-rule","nonzero"],[12],[13],[1,"\\n "],[1,[30,3]],[1,"\\n "],[18,4,null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n"]],["@width","@color","@subtitle","&default"],false,["yield"]]',moduleName:"consul-ui/components/brand-loader/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/child-selector/index",["exports","@ember/component","@ember/template-factory","@ember/object","@ember/object/computed","@ember/service","ember-concurrency","block-slots"],(function(e,t,n,l,r,i,o,a){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const u=(0,n.createTemplateFactory)({id:"rQwZ80hm",block:'[[[11,0],[16,0,[29,["child-selector ",[36,0],"-child-selector"]]],[17,1],[12],[1,"\\n"],[18,4,null],[1,"\\n"],[41,[28,[37,3],[[33,4]],null],[[[1," "],[8,[39,5],null,[["@name"],["create"]],[["default"],[[[[18,4,null]],[]]]]],[1,"\\n "],[10,"label"],[14,0,"type-text"],[12],[1,"\\n "],[10,1],[12],[8,[39,5],null,[["@name"],["label"]],[["default"],[[[[18,4,null]],[]]]]],[13],[1,"\\n"],[41,[33,6],[[[1," "],[8,[39,7],null,[["@src","@onchange"],[[28,[37,8],["/${partition}/${nspace}/${dc}/${type}",[28,[37,9],null,[["partition","nspace","dc","type"],[[33,10],[33,11],[33,12],[28,[37,13],[[33,0]],null]]]]],null],[28,[37,14],[[30,0],[28,[37,15],[[33,16]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,17],null,[["@type","@sort","@filters","@items"],[[99,0,["@type"]],"Name:asc",[28,[37,9],null,[["searchproperties"],[[28,[37,18],["Name"],null]]]],[99,19,["@items"]]]],[["default"],[[[[1,"\\n "],[8,[39,20],null,[["@searchEnabled","@search","@options","@loadingMessage","@searchMessage","@searchPlaceholder","@onOpen","@onClose","@onChange"],[true,[28,[37,14],[[30,0],[30,2,["search"]]],null],[28,[37,21],["Name:asc",[33,19]],null],"Loading...","No possible options",[99,22,["@searchPlaceholder"]],[28,[37,14],[[30,0],[28,[37,15],[[33,6]],null],true],null],[28,[37,14],[[30,0],[28,[37,15],[[33,6]],null],false],null],[28,[37,14],[[30,0],"change","items[]",[33,23]],null]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name","@params"],["option",[28,[37,24],[[30,3]],null]]],[["default"],[[[[18,4,null]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n "]],[2]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,25],[[33,23,["length"]],0],null],[[[1," "],[8,[39,5],null,[["@name"],["set"]],[["default"],[[[[18,4,null]],[]]]]],[1,"\\n"]],[]],[[[1,"\\n"]],[]]],[13]],["&attrs","collection","item","&default"],false,["type","yield","if","not","disabled","yield-slot","isOpen","data-source","uri","hash","partition","nspace","dc","pluralize","action","mut","allOptions","data-collection","array","options","power-select","sort-by","placeholder","items","block-params","gt"]]',moduleName:"consul-ui/components/child-selector/index.hbs",isStrictMode:!1}) -var s=(0,t.setComponentTemplate)(u,t.default.extend(a.default,{onchange:function(){},tagName:"",error:function(){},type:"",dom:(0,i.inject)("dom"),formContainer:(0,i.inject)("form"),item:(0,r.alias)("form.data"),selectedOptions:(0,r.alias)("items"),init:function(){this._super(...arguments),this._listeners=this.dom.listeners(),(0,l.set)(this,"form",this.formContainer.form(this.type)),this.form.clear({Datacenter:this.dc,Namespace:this.nspace})},willDestroyElement:function(){this._super(...arguments),this._listeners.remove()},options:(0,l.computed)("selectedOptions.[]","allOptions.[]",(function(){let e=this.allOptions||[] -const t=this.selectedOptions||[] -return(0,l.get)(t,"length")>0&&(e=e.filter((e=>!t.findBy("ID",(0,l.get)(e,"ID"))))),e})),save:(0,o.task)((function*(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){} -const l=this.repo -try{e=yield l.persist(e),this.actions.change.apply(this,[{target:{name:"items[]",value:t}},t,e]),n()}catch(r){this.error({error:r})}})),actions:{reset:function(){this.form.clear({Datacenter:this.dc,Namespace:this.nspace,Partition:this.partition})},remove:function(e,t){const n=this.repo.getSlugKey(),r=(0,l.get)(e,n),i=t.findIndex((function(e){return(0,l.get)(e,n)===r})) -if(-1!==i)return t.removeAt(i,1) -this.onchange({target:this})},change:function(e,t,n){const r=this.dom.normalizeEvent(...arguments),i=t -if("items[]"===r.target.name)(0,l.set)(n,"CreateTime",(new Date).getTime()),i.pushObject(n),this.onchange({target:this})}}})) -e.default=s})),define("consul-ui/components/code-editor/index",["exports","@ember/component","@ember/template-factory","@ember/object","@ember/service"],(function(e,t,n,l,r){function i(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function o(e){for(var t=1;t{let[t]=e -this.oninput((0,l.set)(this,"value",t.target.wholeText))})),this.observer.observe(e,{attributes:!1,subtree:!0,childList:!1,characterData:!0}),(0,l.set)(this,"value",e.firstChild.wholeText)),(0,l.set)(this,"editor",this.helper.getEditor(this.element)),this.settings.findBySlug("code-editor").then((e=>{const t=this.modes,n=this.syntax -n&&(e=t.find((function(e){return e.name.toLowerCase()==n.toLowerCase()}))),e=e||t[0],this.setMode(e)}))},didAppear:function(){this.editor.refresh()},actions:{change:function(e){this.settings.persist({"code-editor":e}),this.setMode(e)}}})) -e.default=c})),define("consul-ui/components/confirmation-alert/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"fpR2WXW3",block:'[[[18,5,null],[1,"\\n"],[8,[39,1],[[24,0,"confirmation-alert warning"],[17,1]],null,[["header","body","actions"],[[[[1,"\\n "],[8,[39,2],null,[["@name"],["header"]],[["default"],[[[[18,5,null]],[]]]]],[1,"\\n "]],[]],[[[1,"\\n "],[8,[39,2],null,[["@name"],["body"]],[["default"],[[[[18,5,null]],[]]]]],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,2,["Action"]],[[24,0,"dangerous"]],null,[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name","@params"],["confirm",[28,[37,3],[[50,"action",0,null,[["onclick","tabindex"],[[28,[37,5],[[30,0],[30,3]],null],"-1"]]]],null]]],[["default"],[[[[1,"\\n "],[18,5,null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,2,["Action"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@for"],[[30,4]]],[["default"],[[[[1,"\\n Cancel\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]]],["&attrs","Actions","@onclick","@name","&default"],false,["yield","informed-action","yield-slot","block-params","component","action"]]',moduleName:"consul-ui/components/confirmation-alert/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) -e.default=r})),define("consul-ui/components/confirmation-dialog/index",["exports","@ember/component","@ember/template-factory","block-slots","@ember/object"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i=(0,n.createTemplateFactory)({id:"JwnN2l0u",block:'[[[11,0],[16,0,[28,[37,0],["with-confirmation",[52,[33,2]," confirming",""]],null]],[17,1],[12],[1,"\\n"],[18,2,null],[1,"\\n"],[8,[39,4],null,[["@name","@params"],["action",[28,[37,5],[[28,[37,6],[[30,0],"confirm"],null],[28,[37,6],[[30,0],"cancel"],null]],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],[[33,8],[28,[37,9],[[33,2]],null]],null],[[[1," "],[18,2,null],[1,"\\n"]],[]],null]],[]]]]],[1,"\\n"],[8,[39,4],null,[["@name","@params"],["dialog",[28,[37,5],[[28,[37,6],[[30,0],"execute"],null],[28,[37,6],[[30,0],"cancel"],null],[33,10],[33,11]],null]]],[["default"],[[[[1,"\\n"],[41,[33,2],[[[1," "],[18,2,null],[1,"\\n"]],[]],null]],[]]]]],[1,"\\n"],[13]],["&attrs","&default"],false,["concat","if","confirming","yield","yield-slot","block-params","action","or","permanent","not","message","actionName"]]',moduleName:"consul-ui/components/confirmation-dialog/index.hbs",isStrictMode:!1}) -var o=(0,t.setComponentTemplate)(i,t.default.extend(l.default,{tagName:"",message:"Are you sure?",confirming:!1,permanent:!1,actions:{cancel:function(){(0,r.set)(this,"confirming",!1)},execute:function(){(0,r.set)(this,"confirming",!1),this.sendAction("actionName",...this.arguments)},confirm:function(){const[e,...t]=arguments;(0,r.set)(this,"actionName",e),(0,r.set)(this,"arguments",t),(0,r.set)(this,"confirming",!0)}}})) -e.default=o})),define("consul-ui/components/consul/acl/disabled/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"jFDvZrXB",block:'[[[8,[39,0],null,null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n Tokens\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,2],null,null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"Welcome to ACLs"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n ACLs are not enabled in this Consul cluster. We strongly encourage the use of ACLs in production environments for the best security practices.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,3],null,[["@text","@href","@icon","@iconPosition","@size"],["Read the documentation",[29,[[28,[37,4],["CONSUL_DOCS_URL"],null],"/acl/index.html"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,3],null,[["@text","@href","@icon","@iconPosition","@size"],["Follow the guide",[29,[[28,[37,4],["CONSUL_DOCS_LEARN_URL"],null],"/consul/security-networking/production-acls"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]]],[1,"\\n\\n"]],[],false,["app-view","block-slot","empty-state","hds/link/standalone","env"]]',moduleName:"consul-ui/components/consul/acl/disabled/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/acl/selector/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"uDHL3FS4",block:'[[[10,"li"],[14,0,"acls-separator"],[14,"role","separator"],[12],[1,"\\n Access Controls\\n"],[41,[28,[37,1],[[28,[37,2],["use acls"],null]],null],[[[1," "],[11,1],[4,[38,3],["ACLs are not currently enabled in this cluster"],null],[12],[13],[1,"\\n"]],[]],null],[13],[1,"\\n"],[10,"li"],[15,0,[52,[28,[37,4],["dc.acls.tokens",[30,1,["Name"]]],null],"is-active"]],[12],[1,"\\n "],[10,3],[15,6,[28,[37,5],["dc.acls.tokens",[30,1,["Name"]]],null]],[12],[1,"\\n Tokens\\n "],[13],[1,"\\n"],[13],[1,"\\n"],[41,[28,[37,2],["read acls"],null],[[[10,"li"],[15,0,[52,[28,[37,4],["dc.acls.policies",[30,1,["Name"]]],null],"is-active"]],[12],[1,"\\n "],[10,3],[15,6,[28,[37,5],["dc.acls.policies",[30,1,["Name"]]],null]],[12],[1,"\\n Policies\\n "],[13],[1,"\\n"],[13],[1,"\\n"],[10,"li"],[15,0,[52,[28,[37,4],["dc.acls.roles",[30,1,["Name"]]],null],"is-active"]],[12],[1,"\\n "],[10,3],[15,6,[28,[37,5],["dc.acls.roles",[30,1,["Name"]]],null]],[12],[1,"\\n Roles\\n "],[13],[1,"\\n"],[13],[1,"\\n"],[10,"li"],[15,0,[52,[28,[37,4],["dc.acls.auth-methods",[30,1,["Name"]]],null],"is-active"]],[12],[1,"\\n "],[10,3],[15,6,[28,[37,5],["dc.acls.auth-methods",[30,1,["Name"]]],null]],[12],[1,"\\n Auth Methods\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],[]],[[[41,[28,[37,1],[[28,[37,2],["use acls"],null]],null],[[[10,"li"],[15,0,[52,[28,[37,4],["dc.acls.policies",[30,1,["Name"]]],null],"is-active"]],[12],[1,"\\n "],[10,1],[12],[1,"\\n Policies\\n "],[13],[1,"\\n"],[13],[1,"\\n"],[10,"li"],[15,0,[52,[28,[37,4],["dc.acls.roles",[30,1,["Name"]]],null],"is-active"]],[12],[1,"\\n "],[10,1],[12],[1,"\\n Roles\\n "],[13],[1,"\\n"],[13],[1,"\\n"],[10,"li"],[15,0,[52,[28,[37,4],["dc.acls.auth-methods",[30,1,["Name"]]],null],"is-active"]],[12],[1,"\\n "],[10,1],[12],[1,"\\n Auth Methods\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null]],[]]],[1,"\\n"]],["@dc"],false,["if","not","can","tooltip","is-href","href-to"]]',moduleName:"consul-ui/components/consul/acl/selector/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/auth-method/binding-list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"tIxrxpUS",block:'[[[10,0],[14,0,"consul-auth-method-binding-list"],[12],[1,"\\n "],[10,"h2"],[12],[1,[30,1,["BindName"]]],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[14,0,"type"],[12],[1,[28,[35,0],["models.binding-rule.BindType"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,1,["BindType"]]],[1,"\\n "],[10,1],[12],[1,"\\n"],[41,[28,[37,2],[[30,1,["BindType"]],"service"],null],[[[1," "],[8,[39,3],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,0],["components.consul.auth-method.binding-list.bind-type.service"],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[41,[28,[37,2],[[30,1,["BindType"]],"node"],null],[[[1," "],[8,[39,3],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,0],["components.consul.auth-method.binding-list.bind-type.node"],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[41,[28,[37,2],[[30,1,["BindType"]],"role"],null],[[[1," "],[8,[39,3],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,0],["components.consul.auth-method.binding-list.bind-type.role"],null]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]],null]],[]]]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,[28,[35,0],["models.binding-rule.Selector"],null]],[13],[1,"\\n "],[10,"dd"],[12],[10,"code"],[12],[1,[30,1,["Selector"]]],[13],[13],[1,"\\n "],[10,"dt"],[12],[1,[28,[35,0],["models.binding-rule.Description"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,1,["Description"]]],[13],[1,"\\n "],[13],[1,"\\n"],[13]],["@item"],false,["t","if","eq","tooltip"]]',moduleName:"consul-ui/components/consul/auth-method/binding-list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/auth-method/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"klEqVgSZ",block:'[[[8,[39,0],[[24,0,"consul-auth-method-list"]],[["@items"],[[30,1]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],[[30,2,["DisplayName"]],""],null],[[[1," "],[10,3],[15,6,[28,[37,4],["dc.acls.auth-methods.show",[30,2,["Name"]]],null]],[12],[1,"\\n "],[1,[30,2,["DisplayName"]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,6,[28,[37,4],["dc.acls.auth-methods.show",[30,2,["Name"]]],null]],[12],[1,"\\n "],[1,[30,2,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@item"],[[30,2]]],null],[1,"\\n"],[41,[28,[37,3],[[30,2,["DisplayName"]],""],null],[[[1," "],[10,1],[12],[1,[30,2,["Name"]]],[13],[1,"\\n"]],[]],null],[41,[28,[37,6],[[30,2,["TokenLocality"]],"global"],null],[[[1," "],[10,1],[14,0,"locality"],[12],[1,"creates global tokens"],[13],[1,"\\n"]],[]],null],[41,[30,2,["MaxTokenTTL"]],[[[1," "],[10,"dl"],[14,0,"ttl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,7],null,null,[["default"],[[[[1,"\\n Maximum Time to Live: the maximum life of any token created by this auth method\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,2,["MaxTokenTTL"]]],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n"]],[2]]]]],[1,"\\n"]],["@items","item"],false,["list-collection","block-slot","if","not-eq","href-to","consul/auth-method/type","eq","tooltip"]]',moduleName:"consul-ui/components/consul/auth-method/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/auth-method/nspace-list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"IaUtLqXB",block:'[[[10,0],[14,0,"consul-auth-method-nspace-list"],[12],[1,"\\n "],[10,"table"],[12],[1,"\\n "],[10,"thead"],[12],[1,"\\n "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[12],[1,[28,[35,0],["models.auth-method.Selector"],null]],[13],[1,"\\n "],[10,"td"],[12],[1,[28,[35,0],["models.auth-method.BindNamespace"],null]],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"tbody"],[12],[1,"\\n"],[42,[28,[37,2],[[28,[37,2],[[30,1]],null]],null],null,[[[1," "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[12],[1,[30,2,["Selector"]]],[13],[1,"\\n "],[10,"td"],[12],[1,[30,2,["BindNamespace"]]],[13],[1,"\\n "],[13],[1,"\\n"]],[2]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n\\n"]],["@items","item"],false,["t","each","-track-array"]]',moduleName:"consul-ui/components/consul/auth-method/nspace-list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/auth-method/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"TX/eSrxH",block:'[[[8,[39,0],[[24,0,"consul-auth-method-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.auth-method.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.auth-method.search-bar.",[30,3,["status","key"]],".options.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-kind"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["kind","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.auth-method.search-bar.kind.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[1," "],[8,[30,16],null,[["@value","@selected"],["kubernetes",[28,[37,9],["kubernetes",[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,11],[[24,0,"mr-2.5"]],[["@name"],["kubernetes-color"]],null],[1,"\\n Kubernetes\\n "]],[]]]]],[1,"\\n "],[8,[30,16],[[24,0,"jwt"]],[["@value","@selected"],["jwt",[28,[37,9],["jwt",[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"JWT"]],[]]]]],[1,"\\n"],[41,[28,[37,13],["CONSUL_SSO_ENABLED"],null],[[[1," "],[8,[30,16],[[24,0,"oidc"]],[["@value","@selected"],["oidc",[28,[37,9],["oidc",[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"OIDC"]],[]]]]],[1,"\\n"]],[]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-locality"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["source","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.auth-method.search-bar.locality.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,17,["Optgroup"]],[30,17,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[28,[37,4],["local","global"],null]],null]],null],null,[[[1," "],[8,[30,19],[[16,0,[29,[[30,20]]]]],[["@value","@selected"],[[30,20],[28,[37,9],[[30,20],[30,2,["types"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.auth-method.search-bar.locality.options.",[30,20]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[20]],null]],[18,19]]],[1," "]],[]]]]],[1,"\\n "]],[17]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,21,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,22,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,14],[[28,[37,4],[[28,[37,4],["MethodName:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["MethodName:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["TokenTTL:desc",[28,[37,2],["common.sort.duration.asc"],null]],null],[28,[37,4],["TokenTTL:asc",[28,[37,2],["common.sort.duration.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,15],[[30,24],[30,22,["value"]]],null]],[1,"\\n"]],[24]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,23,["Optgroup"]],[30,23,["Option"]]],[[[1," "],[8,[30,25],null,[["@label"],[[28,[37,2],["common.ui.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,26],null,[["@value","@selected"],["MethodName:asc",[28,[37,16],["MethodName:asc",[30,22,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,26],null,[["@value","@selected"],["MethodName:desc",[28,[37,16],["MethodName:desc",[30,22,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,25],null,[["@label"],[[28,[37,2],["common.ui.maxttl"],null]]],[["default"],[[[[1,"\\n "],[8,[30,26],null,[["@value","@selected"],["TokenTTL:desc",[28,[37,16],["TokenTTL:desc",[30,22,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.duration.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,26],null,[["@value","@selected"],["TokenTTL:asc",[28,[37,16],["TokenTTL:asc",[30,22,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.duration.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[25,26]]],[1," "]],[]]]]],[1,"\\n "]],[23]]]]],[1,"\\n "]],[21]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","components","Optgroup","Option","option","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","flight-icon","if","env","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/auth-method/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/auth-method/type/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"KzIxa15o",block:'[[[44,[[28,[37,1],[[30,1,["Type"]]],null]],[[[1," "],[10,1],[15,0,[29,["consul-auth-method-type ",[52,[51,[30,2]],[30,1,["Type"]]]]]],[12],[1,"\\n"],[41,[30,2],[[[1," "],[8,[39,4],[[24,0,"mr-1.5 w-4 h-4"]],[["@name"],[[30,2]]],null],[1,"\\n"]],[]],null],[1," "],[1,[28,[35,5],[[28,[37,6],["common.brand.",[30,1,["Type"]]],null]],null]],[1,"\\n "],[13],[1,"\\n"]],[2]]]],["@item","flightIcon"],false,["let","icon-mapping","unless","if","flight-icon","t","concat"]]',moduleName:"consul-ui/components/consul/auth-method/type/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/auth-method/view/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"4cpKdVK+",block:'[[[1," "],[10,0],[14,0,"consul-auth-method-view"],[12],[1,"\\n"],[41,[28,[37,1],[[30,1,["Type"]],"kubernetes"],null],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Type"],null]],[13],[1,"\\n "],[10,"dd"],[12],[8,[39,3],null,[["@item"],[[30,1]]],null],[13],[1,"\\n\\n"],[42,[28,[37,5],[[28,[37,5],[[28,[37,6],["MaxTokenTTL","TokenLocality","DisplayName","Description"],null]],null]],null],null,[[[41,[28,[37,7],[[30,1],[30,2]],null],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],[[28,[37,8],["models.auth-method.",[30,2]],null]],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,7],[[30,1],[30,2]],null]],[13],[1,"\\n"]],[]],null]],[2]],null],[41,[30,1,["Config","Host"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.Host"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,1,["Config","Host"]],[28,[37,2],["models.auth-method.Config.Host"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","CACert"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.CACert"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@obfuscated","@value","@name"],[true,[30,1,["Config","CACert"]],[28,[37,2],["models.auth-method.Config.CACert"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","ServiceAccountJWT"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.ServiceAccountJWT"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,1,["Config","ServiceAccountJWT"]],[28,[37,2],["models.auth-method.Config.ServiceAccountJWT"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]],[[[1," "],[10,"section"],[14,0,"meta"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Type"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,3],null,[["@item"],[[30,1]]],null],[1,"\\n "],[13],[1,"\\n\\n"],[42,[28,[37,5],[[28,[37,5],[[28,[37,6],["MaxTokenTTL","TokenLocality","DisplayName","Description"],null]],null]],null],null,[[[41,[28,[37,7],[[30,1],[30,3]],null],[[[1,"\\n "],[10,"dt"],[12],[1,[28,[35,2],[[28,[37,8],["models.auth-method.",[30,3]],null]],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,7],[[30,1],[30,3]],null]],[13],[1,"\\n\\n"]],[]],null]],[3]],null],[1,"\\n"],[41,[28,[37,1],[[30,1,["Type"]],"aws-iam"],null],[[[1,"\\n"],[44,[[30,1,["Config"]]],[[[42,[28,[37,5],[[28,[37,5],[[28,[37,6],["BoundIAMPrincipalARNs","EnableIAMEntityDetails","IAMEntityTags","IAMEndpoint","MaxRetries","STSEndpoint","STSRegion","AllowedSTSHeaderValues","ServerIDHeaderValue"],null]],null]],null],null,[[[41,[28,[37,7],[[30,4],[30,5]],null],[[[1,"\\n "],[10,"dt"],[12],[1,[28,[35,2],[[28,[37,8],["models.auth-method.",[30,5]],null]],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[44,[[28,[37,7],[[30,4],[30,5]],null]],[[[41,[28,[37,11],[[30,6]],null],[[[1," "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,6]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,1],[12],[1,[30,7]],[13],[1,"\\n "],[13],[1,"\\n"]],[7]],null],[1," "],[13],[1,"\\n"]],[]],[[[1," "],[1,[30,6]],[1,"\\n"]],[]]]],[6]]],[1," "],[13],[1,"\\n\\n"]],[]],null]],[5]],null],[1,"\\n"]],[4]]],[1,"\\n"]],[]],[[[41,[28,[37,1],[[30,1,["Type"]],"jwt"],null],[[[41,[30,1,["Config","JWKSURL"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.JWKSURL"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,1,["Config","JWKSURL"]],[28,[37,2],["models.auth-method.Config.JWKSURL"],null]]],null],[1,"\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.JWKSCACert"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@obfuscated","@value","@name"],[true,[30,1,["Config","JWKSCACert"]],[28,[37,2],["models.auth-method.Config.JWKSCACert"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","JWTValidationPubKeys"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.JWTValidationPubKeys"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@obfuscated","@value","@name"],[true,[30,1,["Config","JWTValidationPubKeys"]],[28,[37,2],["models.auth-method.Config.JWTValidationPubKeys"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","OIDCDiscoveryURL"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.OIDCDiscoveryURL"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,1,["Config","OIDCDiscoveryURL"]],[28,[37,2],["models.auth-method.Config.OIDCDiscoveryURL"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","JWTSupportedAlgs"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.JWTSupportedAlgs"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,12],[", ",[30,1,["Config","JWTSupportedAlgs"]]],null]],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","BoundAudiences"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.BoundAudiences"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,1,["Config","BoundAudiences"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,1],[12],[1,[30,8]],[13],[1,"\\n "],[13],[1,"\\n"]],[8]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[42,[28,[37,5],[[28,[37,5],[[28,[37,6],["BoundIssuer","ExpirationLeeway","NotBeforeLeeway","ClockSkewLeeway"],null]],null]],null],null,[[[41,[28,[37,7],[[30,1,["Config"]],[30,9]],null],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],[[28,[37,8],["models.auth-method.Config.",[30,9]],null]],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,7],[[30,1,["Config"]],[30,9]],null]],[13],[1,"\\n"]],[]],null]],[9]],null]],[]],[[[41,[28,[37,1],[[30,1,["Type"]],"oidc"],null],[[[41,[30,1,["Config","OIDCDiscoveryURL"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.OIDCDiscoveryURL"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,1,["Config","OIDCDiscoveryURL"]],[28,[37,2],["models.auth-method.Config.OIDCDiscoveryURL"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","OIDCDiscoveryCACert"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.OIDCDiscoveryCACert"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@obfuscated","@value","@name"],[true,[30,1,["Config","OIDCDiscoveryCACert"]],[28,[37,2],["models.auth-method.Config.OIDCDiscoveryCACert"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","OIDCClientID"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.OIDCClientID"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,1,["Config","OIDCClientID"]]],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","OIDCClientSecret"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.OIDCClientSecret"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,1,["Config","OIDCClientSecret"]]],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","AllowedRedirectURIs"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.AllowedRedirectURIs"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,1,["Config","AllowedRedirectURIs"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,10],"Redirect URI"]],null],[1,"\\n "],[13],[1,"\\n"]],[10]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","BoundAudiences"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.BoundAudiences"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,1,["Config","BoundAudiences"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,1],[12],[1,[30,11]],[13],[1,"\\n "],[13],[1,"\\n"]],[11]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","OIDCScopes"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.OIDCScopes"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,1,["Config","OIDCScopes"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,1],[12],[1,[30,12]],[13],[1,"\\n "],[13],[1,"\\n"]],[12]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","JWTSupportedAlgs"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.JWTSupportedAlgs"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,12],[", ",[30,1,["Config","JWTSupportedAlgs"]]],null]],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","VerboseOIDCLogging"]],[[[1," "],[10,"dt"],[14,0,"check"],[12],[1,[28,[35,2],["models.auth-method.Config.VerboseOIDCLogging"],null]],[13],[1,"\\n "],[10,"dd"],[12],[10,"input"],[14,"disabled","disabled"],[15,"checked",[30,1,["Config","VerboseOIDCLogging"]]],[14,4,"checkbox"],[12],[13],[13],[1,"\\n"]],[]],null],[1," "]],[]],null]],[]]]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n\\n"],[41,[28,[37,13],[[28,[37,1],[[30,1,["Type"]],"aws-iam"],null]],null],[[[1," "],[10,"hr"],[12],[13],[1,"\\n\\n "],[10,"section"],[14,0,"claim-mappings"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Claim Mappings"],[13],[1,"\\n"],[41,[30,1,["Config","ClaimMappings"]],[[[1," "],[10,2],[12],[1,"Use this if the claim you are capturing is singular. When mapped, the values can be any of a number, string, or boolean and will all be stringified when returned."],[13],[1,"\\n "],[10,"table"],[12],[1,"\\n "],[10,"thead"],[12],[1,"\\n "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[12],[1,"Key"],[13],[1,"\\n "],[10,"td"],[12],[1,"Value"],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"tbody"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[28,[37,14],[[30,1,["Config","ClaimMappings"]]],null]],null]],null],null,[[[1," "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[12],[1,[28,[35,7],[[30,13],0],null]],[13],[1,"\\n "],[10,"td"],[12],[1,[28,[35,7],[[30,13],1],null]],[13],[1,"\\n "],[13],[1,"\\n"]],[13]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[8,[39,15],null,null,[["default"],[[[[1,"\\n "],[8,[39,16],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"No claim mappings"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,16],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"Use this if the claim you are capturing is singular. When mapped, the values can be any of a number, string, or boolean and will all be stringified when returned."],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,16],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"docs-link"],[12],[1,"\\n"],[41,[28,[37,1],[[30,1,["Type"]],"jwt"],null],[[[1," "],[10,3],[15,6,[29,[[28,[37,17],["CONSUL_DOCS_URL"],null],"/security/acl/auth-methods/jwt#claimmappings"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"Read the documentation"],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,6,[29,[[28,[37,17],["CONSUL_DOCS_URL"],null],"/security/acl/auth-methods/oidc#claimmappings"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"Read the documentation"],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n\\n "],[10,"hr"],[12],[13],[1,"\\n\\n "],[10,"section"],[14,0,"list-claim-mappings"],[12],[1,"\\n "],[10,"h2"],[12],[1,"List Claim Mappings"],[13],[1,"\\n"],[41,[30,1,["Config","ListClaimMappings"]],[[[1," "],[10,2],[12],[1,"Use this if the claim you are capturing is list-like (such as groups). When mapped, the values can be any of a number, string, or boolean and will all be stringified when returned."],[13],[1,"\\n "],[10,"table"],[12],[1,"\\n "],[10,"thead"],[12],[1,"\\n "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[12],[1,"Key"],[13],[1,"\\n "],[10,"td"],[12],[1,"Value"],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"tbody"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[28,[37,14],[[30,1,["Config","ListClaimMappings"]]],null]],null]],null],null,[[[1," "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[12],[1,[28,[35,7],[[30,14],0],null]],[13],[1,"\\n "],[10,"td"],[12],[1,[28,[35,7],[[30,14],1],null]],[13],[1,"\\n "],[13],[1,"\\n"]],[14]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[8,[39,15],null,null,[["default"],[[[[1,"\\n "],[8,[39,16],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"No list claim mappings"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,16],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"Use this if the claim you are capturing is list-like (such as groups). When mapped, the values can be any of a number, string, or boolean and will all be stringified when returned."],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,16],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"docs-link"],[12],[1,"\\n"],[41,[28,[37,1],[[30,1,["Type"]],"jwt"],null],[[[1," "],[10,3],[15,6,[29,[[28,[37,17],["CONSUL_DOCS_URL"],null],"/security/acl/auth-methods/jwt#listclaimmappings"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"Read the documentation"],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,6,[29,[[28,[37,17],["CONSUL_DOCS_URL"],null],"/security/acl/auth-methods/oidc#listclaimmappings"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"Read the documentation"],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[]],null]],[]]],[1," "],[13]],["@item","value","value","config","value","item","jtem","bond","value","uri","bond","scope","entry","entry"],false,["if","eq","t","consul/auth-method/type","each","-track-array","array","get","concat","copyable-code","let","array-is-array","join","not","entries","empty-state","block-slot","env"]]',moduleName:"consul-ui/components/consul/auth-method/view/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/bucket/list/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service"],(function(e,t,n,l,r){var i,o -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const a=(0,n.createTemplateFactory)({id:"Uns+fzyc",block:'[[[41,[30,0,["itemsToDisplay","length"]],[[[1," "],[10,"dl"],[14,0,"consul-bucket-list"],[12],[1,"\\n"],[42,[28,[37,2],[[28,[37,2],[[30,0,["itemsToDisplay"]]],null]],null],null,[[[1," "],[11,"dt"],[16,0,[30,1,["type"]]],[4,[38,3],null,null],[12],[1,"\\n "],[1,[30,1,["label"]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,1,["item"]]],[1,"\\n "],[13],[1,"\\n"]],[1]],null],[1," "],[13],[1,"\\n"]],[]],null]],["item"],false,["if","each","-track-array","tooltip"]]',moduleName:"consul-ui/components/consul/bucket/list/index.hbs",isStrictMode:!1}) -let u=(i=class extends l.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="abilities",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}get itemsToDisplay(){const{peerOrPartitionPart:e,namespacePart:t,servicePart:n}=this -return[...e,...t,...n]}get peerOrPartitionPart(){const{peerPart:e,partitionPart:t}=this -return e.length?e:t}get partitionPart(){const{item:e,partition:t}=this.args,{abilities:n}=this -return t&&n.can("use partitions")&&e.Partition!==t?[{type:"partition",label:"Admin Partition",item:e.Partition}]:[]}get peerPart(){const{item:e}=this.args -return e.PeerName?[{type:"peer",label:"Peer",item:e.PeerName}]:[]}get namespacePart(){const{item:e,nspace:t}=this.args,{abilities:n,partitionPart:l,peerPart:r}=this,i={type:"nspace",label:"Namespace",item:e.Namespace} -return l.length||r.length&&n.can("use nspaces")||t&&n.can("use nspaces")&&e.Namespace!==t?[i]:[]}get servicePart(){const{item:e,service:t}=this.args,{partitionPart:n,namespacePart:l}=this -return(n.length||l.length)&&e.Service&&t?[{type:"service",label:"Service",item:e.Service}]:[]}},s=i.prototype,c="abilities",d=[r.inject],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),o=m,i) -var s,c,d,p,f,m -e.default=u,(0,t.setComponentTemplate)(a,u)})),define("consul-ui/components/consul/datacenter/selector/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"b1hlblXc",block:'[[[10,"li"],[14,0,"dcs"],[12],[1,"\\n"],[41,[28,[37,1],[[30,1,["length"]],1],null],[[[1," "],[8,[39,2],[[24,"aria-label","Datacenter"]],[["@items"],[[28,[37,3],["Primary:desc","Local:desc","Name:asc",[30,1]],null]]],[["default"],[[[[1,"\\n "],[8,[30,2,["Action"]],[[4,[38,4],["click",[30,2,["toggle"]]],null]],null,[["default"],[[[[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,2,["Menu"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@src","@onchange"],[[28,[37,6],["/*/*/*/datacenters"],null],[28,[37,7],[[30,0],[28,[37,8],[[30,1]],null]],[["value"],["data"]]]]],null],[1,"\\n "],[10,2],[14,0,"dcs-message"],[12],[1,"\\n Datacenters shown in this dropdown are available through WAN Federation.\\n "],[13],[1,"\\n "],[8,[30,4,["Menu"]],null,null,[["default"],[[[[1,"\\n "],[8,[30,5,["Separator"]],null,null,[["default"],[[[[1,"\\n DATACENTERS\\n "]],[]]]]],[1,"\\n"],[42,[28,[37,10],[[28,[37,10],[[30,5,["items"]]],null]],null],null,[[[1," "],[8,[30,5,["Item"]],[[16,"aria-current",[52,[28,[37,11],[[30,3,["Name"]],[30,6,["Name"]]],null],"true"]],[16,0,[28,[37,12],[[28,[37,13],["is-local",[30,6,["Local"]]],null],[28,[37,13],["is-primary",[30,6,["Primary"]]],null]],null]]],null,[["default"],[[[[1,"\\n "],[8,[30,5,["Action"]],[[4,[38,4],["click",[30,2,["close"]]],null]],[["@href"],[[28,[37,14],["."],[["params"],[[28,[37,15],null,[["dc","partition","nspace"],[[30,6,["Name"]],[27],[52,[28,[37,1],[[30,7,["length"]],0],null],[30,7],[27]]]]]]]]]],[["default"],[[[[1,"\\n "],[1,[30,6,["Name"]]],[1,"\\n"],[41,[30,6,["Primary"]],[[[1," "],[10,1],[12],[1,"Primary"],[13],[1,"\\n"]],[]],null],[41,[30,6,["Local"]],[[[1," "],[10,1],[12],[1,"Local"],[13],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[6]],null],[1," "]],[5]]]]],[1,"\\n "]],[4]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[]],[[[1," "],[10,0],[14,0,"dc-name"],[12],[1,"\\n "],[1,[30,1,["firstObject","Name"]]],[1,"\\n"],[44,[[28,[37,17],["CONSUL_HCP_MANAGED_RUNTIME"],null]],[[[41,[30,8],[[[1," "],[10,1],[12],[1,[28,[35,18],[[30,8]],null]],[13],[1,"\\n"]],[]],null]],[8]]],[1," "],[13],[1,"\\n"]],[]]],[13]],["@dcs","disclosure","@dc","panel","menu","item","@nspace","managedRuntime"],false,["if","gt","disclosure-menu","sort-by","on","data-source","uri","action","mut","each","-track-array","eq","class-map","array","href-to","hash","let","env","capitalize"]]',moduleName:"consul-ui/components/consul/datacenter/selector/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/discovery-chain/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object","consul-ui/components/consul/discovery-chain/utils"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"gGEpz1eC",block:'[[[10,"style"],[12],[1,"\\n"],[41,[33,1,["nodes"]],[[[1," "],[1,[33,1,["nodes"]]],[1,"\\n { opacity: 1 !important; background-color: var(--token-color-surface-interactive); border:\\n var(--decor-border-100); border-radius: var(--decor-radius-200); border-color:\\n var(--token-color-foreground-faint); box-shadow: var(--token-surface-high-box-shadow); }\\n"]],[]],null],[41,[33,1,["edges"]],[[[1," "],[1,[33,1,["edges"]]],[1,"\\n { opacity: 1; }\\n"]],[]],null],[13],[1,"\\n\\n"],[10,0],[14,0,"routes"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[33,2,["ServiceName"]]],[1,"\\n Router\\n "],[11,1],[4,[38,3],["Use routers to intercept traffic using Layer 7 criteria such as path prefixes or http headers."],null],[12],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,"role","group"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[33,6]],null]],null],null,[[[1," "],[8,[39,7],[[4,[38,9],[[28,[37,10],[[28,[37,11],[[30,1],"rect"],null]],[["from"],[[30,0,["edges"]]]]]],null]],[["@item","@onclick"],[[30,1],[28,[37,8],[[30,0],"click"],null]]],null],[1,"\\n"]],[1]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n\\n"],[10,0],[14,0,"splitters"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n Splitters\\n "],[11,1],[4,[38,3],["Splitters are configured to split incoming requests across different services or subsets of a single service."],null],[12],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,"role","group"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[28,[37,12],["Name",[33,13]],null]],null]],null],null,[[[1," "],[8,[39,14],[[4,[38,9],[[28,[37,10],[[28,[37,11],[[30,2],"rect"],null]],[["from"],[[30,0,["edges"]]]]]],null]],[["@item","@onclick"],[[30,2],[28,[37,8],[[30,0],"click"],null]]],null],[1,"\\n"]],[2]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n\\n"],[10,0],[14,0,"resolvers"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n Resolvers\\n "],[11,1],[4,[38,3],["Resolvers are used to define which instances of a service should satisfy discovery requests."],null],[12],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,"role","group"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[28,[37,12],["Name",[33,15]],null]],null]],null],null,[[[1," "],[8,[39,16],[[4,[38,9],[[28,[37,10],[[28,[37,11],[[30,3],"rect"],null]],[["from"],[[30,0,["edges"]]]]]],null]],[["@item","@edges","@onclick"],[[30,3],[30,0,["edges"]],[28,[37,8],[[30,0],"click"],null]]],null],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n\\n"],[1,[34,17]],[1,"\\n\\n"],[11,"svg"],[24,0,"edges"],[24,"width","100%"],[24,"height","100%"],[24,"preserveAspectRatio","none"],[4,[38,18],[[28,[37,11],[[30,0],"edges"],null]],null],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[33,6]],null]],null],null,[[[41,[30,4,["rect"]],[[[44,[[30,4,["rect"]],[30,4,["NextItem","rect"]]],[[[44,[[28,[37,20],[[28,[37,21],null,[["x","y"],[[30,6,["x"]],[28,[37,22],[[30,6,["y"]],[28,[37,23],[[30,6,["height"]],2],null]],null]]]],[28,[37,24],[[30,4,["ID"]]],null]],null]],[[[1,"\\n "],[10,"path"],[15,1,[28,[37,24],[[30,4,["ID"]],">",[30,4,["NextNode"]]],null]],[15,"d",[28,[37,25],[[28,[37,21],null,[["x","y"],[[30,7,["x"]],[28,[37,26],[[30,7,["y"]],0],null]]]]],[["src"],[[28,[37,21],null,[["x","y"],[[30,5,["right"]],[28,[37,22],[[30,5,["y"]],[28,[37,23],[[30,5,["height"]],2],null]],null]]]]]]]],[12],[13],[1,"\\n\\n"]],[7]]]],[5,6]]]],[]],null]],[4]],null],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[33,13]],null]],null],null,[[[41,[30,8,["rect"]],[[[44,[[30,8,["rect"]]],[[[42,[28,[37,5],[[28,[37,5],[[30,8,["Splits"]]],null]],null],null,[[[44,[[30,10,["NextItem","rect"]]],[[[44,[[28,[37,20],[[28,[37,21],null,[["x","y"],[[30,12,["x"]],[28,[37,22],[[30,12,["y"]],[28,[37,23],[[30,12,["height"]],2],null]],null]]]],[28,[37,24],[[30,8,["ID"]],"-",[30,11]],null]],null]],[[[1,"\\n "],[11,"path"],[16,1,[28,[37,24],["splitter:",[30,8,["Name"]],">",[30,10,["NextNode"]]],null]],[24,0,"split"],[16,"d",[28,[37,25],[[28,[37,21],null,[["x","y"],[[30,13,["x"]],[30,13,["y"]]]]]],[["src"],[[28,[37,21],null,[["x","y"],[[30,9,["right"]],[28,[37,22],[[30,9,["y"]],[28,[37,23],[[30,9,["height"]],2],null]],null]]]]]]]],[4,[38,3],[[28,[37,24],[[28,[37,27],[[28,[37,28],[[30,10,["Weight"]],0],null]],[["decimals"],[2]]],"%"],null]],[["options"],[[28,[37,21],null,[["followCursor"],[true]]]]]],[12],[13],[1,"\\n\\n"]],[13]]]],[12]]]],[10,11]],null]],[9]]]],[]],null]],[8]],null],[1,"\\n"],[13],[1,"\\n\\n"],[10,"svg"],[14,0,"resolver-inlets"],[14,"height","100%"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[33,6]],null]],null],null,[[[41,[28,[37,29],[[30,14,["NextNode"]],"resolver:"],null],[[[44,[[28,[37,28],[[30,14,["NextItem","rect"]],[28,[37,21],null,[["y","height"],[0,0]]]],null]],[[[1," "],[10,"circle"],[14,"r","2.5"],[14,"cx","5"],[15,"cy",[28,[37,22],[[30,15,["y"]],[28,[37,23],[[30,15,["height"]],2],null]],null]],[12],[13],[1,"\\n"]],[15]]]],[]],null]],[14]],null],[42,[28,[37,5],[[28,[37,5],[[33,13]],null]],null],null,[[[42,[28,[37,5],[[28,[37,5],[[30,16,["Splits"]]],null]],null],null,[[[44,[[28,[37,28],[[30,17,["NextItem","rect"]],[28,[37,21],null,[["y","height"],[0,0]]]],null]],[[[1," "],[10,"circle"],[14,"r","2.5"],[14,"cx","5"],[15,"cy",[28,[37,22],[[30,18,["y"]],[28,[37,23],[[30,18,["height"]],2],null]],null]],[12],[13],[1,"\\n"]],[18]]]],[17]],null]],[16]],null],[13],[1,"\\n\\n"],[10,"svg"],[14,0,"splitter-inlets"],[14,"height","100%"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[33,6]],null]],null],null,[[[41,[28,[37,29],[[30,19,["NextNode"]],"splitter:"],null],[[[44,[[28,[37,28],[[30,19,["NextItem","rect"]],[28,[37,21],null,[["y","height"],[0,0]]]],null]],[[[1," "],[10,"circle"],[14,"r","2.5"],[14,"cx","5"],[15,"cy",[28,[37,22],[[30,20,["y"]],[28,[37,23],[[30,20,["height"]],2],null]],null]],[12],[13],[1,"\\n"]],[20]]]],[]],null]],[19]],null],[13],[1,"\\n"]],["item","item","item","item","src","destRect","dest","splitter","src","item","index","destRect","dest","item","dest","item","item","dest","item","dest"],false,["if","selected","chain","tooltip","each","-track-array","routes","consul/discovery-chain/route-card","action","on-resize","dom-position","set","sort-by","splitters","consul/discovery-chain/splitter-card","resolvers","consul/discovery-chain/resolver-card","nodes","did-insert","let","tween-to","hash","add","div","concat","svg-curve","sub","round","or","string-starts-with"]]',moduleName:"consul-ui/components/consul/discovery-chain/index.hbs",isStrictMode:!1}) -var a=(0,t.setComponentTemplate)(o,t.default.extend({dom:(0,l.inject)("dom"),ticker:(0,l.inject)("ticker"),dataStructs:(0,l.inject)("data-structs"),classNames:["discovery-chain"],classNameBindings:["active"],selectedId:"",init:function(){this._super(...arguments),this._listeners=this.dom.listeners()},didInsertElement:function(){this._listeners.add(this.dom.document(),{click:e=>{this.dom.closest('[class$="-card"]',e.target)||((0,r.set)(this,"active",!1),(0,r.set)(this,"selectedId",""))}})},willDestroyElement:function(){this._super(...arguments),this._listeners.remove(),this.ticker.destroy(this)},splitters:(0,r.computed)("chain.Nodes",(function(){return(0,i.getSplitters)((0,r.get)(this,"chain.Nodes"))})),routes:(0,r.computed)("chain.Nodes",(function(){const e=(0,i.getRoutes)((0,r.get)(this,"chain.Nodes"),this.dom.guid) -if(!e.find((e=>"/"===(0,r.get)(e,"Definition.Match.HTTP.PathPrefix")))&&!e.find((e=>void 0===e.Definition))){let t -const n=`resolver:${this.chain.ServiceName}.${this.chain.Namespace}.${this.chain.Partition}.${this.chain.Datacenter}`,l=`splitter:${this.chain.ServiceName}.${this.chain.Namespace}.${this.chain.Partition}` -if(void 0!==this.chain.Nodes[l]?t=l:void 0!==this.chain.Nodes[n]&&(t=n),void 0!==t){const n={Default:!0,ID:`route:${this.chain.ServiceName}`,Name:this.chain.ServiceName,Definition:{Match:{HTTP:{PathPrefix:"/"}}},NextNode:t} -e.push((0,i.createRoute)(n,this.chain.ServiceName,this.dom.guid))}}return e})),nodes:(0,r.computed)("routes","splitters","resolvers",(function(){let e=this.resolvers.reduce(((e,t)=>(e[`resolver:${t.ID}`]=t,t.Children.reduce(((e,t)=>(e[`resolver:${t.ID}`]=t,e)),e),e)),{}) -return e=this.splitters.reduce(((e,t)=>(e[t.ID]=t,e)),e),e=this.routes.reduce(((e,t)=>(e[t.ID]=t,e)),e),Object.entries(e).forEach((t=>{let[n,l]=t -void 0!==l.NextNode&&(l.NextItem=e[l.NextNode]),void 0!==l.Splits&&l.Splits.forEach((t=>{void 0!==t.NextNode&&(t.NextItem=e[t.NextNode])}))})),""})),resolvers:(0,r.computed)("chain.{Nodes,Targets}",(function(){return(0,i.getResolvers)(this.chain.Datacenter,this.chain.Partition,this.chain.Namespace,(0,r.get)(this,"chain.Targets"),(0,r.get)(this,"chain.Nodes"))})),graph:(0,r.computed)("splitters","routes.[]",(function(){const e=this.dataStructs.graph() -return this.splitters.forEach((t=>{t.Splits.forEach((n=>{e.addLink(t.ID,n.NextNode)}))})),this.routes.forEach(((t,n)=>{e.addLink(t.ID,t.NextNode)})),e})),selected:(0,r.computed)("selectedId","graph",(function(){if(""===this.selectedId||!this.dom.element(`#${this.selectedId}`))return{} -const e=this.selectedId,t=e.split(":").shift(),n=[e],l=[] -return this.graph.forEachLinkedNode(e,((e,r)=>{n.push(e.id),l.push(`${r.fromId}>${r.toId}`),this.graph.forEachLinkedNode(e.id,((e,r)=>{const i=e.id.split(":").shift() -t!==i&&"splitter"!==t&&"splitter"!==i&&(n.push(e.id),l.push(`${r.fromId}>${r.toId}`))}))})),{nodes:n.map((e=>`#${CSS.escape(e)}`)),edges:l.map((e=>`#${CSS.escape(e)}`))}})),actions:{click:function(e){const t=e.currentTarget.getAttribute("id") -t===this.selectedId?((0,r.set)(this,"active",!1),(0,r.set)(this,"selectedId","")):((0,r.set)(this,"active",!0),(0,r.set)(this,"selectedId",t))}}})) -e.default=a})),define("consul-ui/components/consul/discovery-chain/resolver-card/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"o/2vY0FQ",block:'[[[10,0],[14,0,"resolver-card"],[12],[1,"\\n "],[11,"header"],[17,1],[16,"onclick",[28,[37,0],[[30,2]],null]],[16,1,[28,[37,1],["resolver:",[30,3,["ID"]]],null]],[12],[1,"\\n "],[10,3],[14,3,""],[12],[1,"\\n "],[10,"h3"],[12],[1,[30,3,["Name"]]],[13],[1,"\\n"],[41,[30,3,["Failover"]],[[[1," "],[10,"dl"],[14,0,"failover"],[12],[1,"\\n "],[11,"dt"],[4,[38,3],[[28,[37,1],[[30,3,["Failover","Type"]]," failover"],null]],null],[12],[1,"\\n "],[1,[28,[35,1],[[30,3,["Failover","Type"]]," failover"],null]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ol"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,3,["Failover","Targets"]]],null]],null],null,[[[1," "],[10,"li"],[12],[10,1],[12],[1,[30,4]],[13],[13],[1,"\\n"]],[4]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,6],[[30,3,["Children","length"]],0],null],[[[1," "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,3,["Children"]]],null]],null],null,[[[1," "],[11,"li"],[16,"onclick",[28,[37,0],[[30,2]],null]],[16,1,[28,[37,1],["resolver:",[30,5,["ID"]]],null]],[4,[38,7],[[28,[37,8],[[28,[37,9],[[30,5],"rect"],null]],[["from"],[[30,6]]]]],null],[12],[1,"\\n "],[10,3],[14,3,""],[12],[1,"\\n"],[41,[30,5,["Redirect"]],[[[1," "],[10,"dl"],[14,0,"redirect"],[12],[1,"\\n "],[11,"dt"],[4,[38,3],[[28,[37,1],[[30,5,["Redirect"]]," redirect"],null]],null],[12],[1,"\\n "],[1,[30,5,["Redirect"]]],[1," redirect\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,5,["Name"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[30,5,["Failover"]],[[[1," "],[10,"dl"],[14,0,"failover"],[12],[1,"\\n "],[11,"dt"],[4,[38,3],[[28,[37,1],[[30,5,["Failover","Type"]]," failover"],null]],null],[12],[1,"\\n "],[1,[30,5,["Failover","Type"]]],[1," failover\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ol"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,5,["Failover","Targets"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,1],[12],[1,[30,7]],[13],[1,"\\n "],[13],[1,"\\n"]],[7]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[]],[[[41,[30,5,["Failover"]],[[[1," "],[1,[30,5,["Name"]]],[1,"\\n "],[10,"dl"],[14,0,"failover"],[12],[1,"\\n "],[11,"dt"],[4,[38,3],[[28,[37,1],[[30,5,["Failover","Type"]]," failover"],null]],null],[12],[1,"\\n "],[1,[28,[35,1],[[30,5,["Failover","Type"]]," failover"],null]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ol"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,5,["Failover","Targets"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,1],[12],[1,[30,8]],[13],[1,"\\n "],[13],[1,"\\n"]],[8]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[1,[30,5,["Name"]]],[1,"\\n "]],[]]]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[5]],null],[1," "],[13],[1,"\\n"]],[]],null],[13],[1,"\\n"]],["&attrs","@onclick","@item","item","child","@edges","target","target"],false,["optional","concat","if","tooltip","each","-track-array","gt","on-resize","dom-position","set"]]',moduleName:"consul-ui/components/consul/discovery-chain/resolver-card/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/discovery-chain/route-card/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i=(0,n.createTemplateFactory)({id:"fiqUKMeE",block:'[[[11,3],[24,0,"route-card"],[16,"onclick",[30,1]],[16,1,[30,2,["ID"]]],[17,3],[12],[1,"\\n "],[10,"header"],[15,0,[52,[28,[37,1],[[30,0,["path","value"]],"/"],null],"short"]],[12],[1,"\\n"],[41,[28,[37,2],[[30,2,["Definition","Match","HTTP","Methods","length"]],0],null],[[[1," "],[10,"ul"],[14,0,"match-methods"],[12],[1,"\\n"],[42,[28,[37,4],[[28,[37,4],[[30,2,["Definition","Match","HTTP","Methods"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,[30,4]],[13],[1,"\\n"]],[4]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[1,[30,0,["path","type"]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,0,["path","value"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,2],[[30,2,["Definition","Match","HTTP","Header","length"]],0],null],[[[1," "],[10,"section"],[14,0,"match-headers"],[12],[1,"\\n "],[11,"header"],[4,[38,5],["Header"],null],[12],[1,"\\n "],[10,"h4"],[12],[1,"Headers"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n"],[42,[28,[37,4],[[28,[37,4],[[30,2,["Definition","Match","HTTP","Header"]]],null]],null],null,[[[1," "],[10,"dt"],[12],[1,"\\n "],[1,[30,5,["Name"]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,6],[[30,5]],null]],[1,"\\n "],[13],[1,"\\n"]],[5]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,2],[[30,2,["Definition","Match","HTTP","QueryParam","length"]],0],null],[[[1," "],[10,"section"],[14,0,"match-queryparams"],[12],[1,"\\n "],[11,"header"],[4,[38,5],["Query Params"],null],[12],[1,"\\n "],[10,"h4"],[12],[1,"Query Params"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n"],[42,[28,[37,4],[[28,[37,4],[[30,2,["Definition","Match","HTTP","QueryParam"]]],null]],null],null,[[[1," "],[10,"dt"],[12],[1,"\\n "],[1,[30,6,["Name"]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,6],[[30,6]],null]],[1,"\\n "],[13],[1,"\\n"]],[6]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[13],[1,"\\n"]],["@onclick","@item","&attrs","item","item","item"],false,["if","eq","gt","each","-track-array","tooltip","route-match"]]',moduleName:"consul-ui/components/consul/discovery-chain/route-card/index.hbs",isStrictMode:!1}) -class o extends l.default{get path(){return Object.entries((0,r.get)(this.args.item,"Definition.Match.HTTP")||{}).reduce((function(e,t){let[n,l]=t -return n.toLowerCase().startsWith("path")?{type:n.replace("Path",""),value:l}:e}),{type:"Prefix",value:"/"})}}e.default=o,(0,t.setComponentTemplate)(i,o)})),define("consul-ui/components/consul/discovery-chain/splitter-card/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"RQh8TKeM",block:'[[[10,0],[12],[1,"\\n "],[11,3],[17,1],[16,1,[30,2,["ID"]]],[24,0,"splitter-card"],[16,"onclick",[28,[37,0],[[30,3]],null]],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h3"],[12],[1,[30,2,["Name"]]],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@item","@onclick"],false,["optional"]]',moduleName:"consul-ui/components/consul/discovery-chain/splitter-card/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/discovery-chain/utils",["exports"],(function(e){function t(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function n(e){for(var n=1;n0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1?arguments[1]:void 0 -return Object.values(e).filter((e=>e.Type===t))},i=function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"default",l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"default",r=arguments.length>4?arguments[4]:void 0 -return void 0===e[t]&&(e[t]={ID:`${t}.${n}.${l}.${r}`,Name:t,Children:[]}),e[t]},o=function(e,t){let n -const l=e.map((function(e){const[l,r]=[t,e].map((e=>e.split(".").reverse())),i=["Datacenter","Partition","Namespace","Service","Subset"] -return r.find((function(e,t){const r=e!==l[t] -return r&&(n=i[t]),r}))})) -return{Type:n,Targets:l}} -e.getAlternateServices=o -e.getSplitters=function(e){return r(e,"splitter").map((function(e){const t=e.Name.split(".") -return t.reverse(),t.shift(),t.shift(),t.reverse(),n(n({},e),{},{ID:`splitter:${e.Name}`,Name:t.join(".")})}))} -e.getRoutes=function(e,t){return r(e,"router").reduce((function(e,n){return e.concat(n.Routes.map((function(e,l){return a(e,n.Name,t)})))}),[])} -e.getResolvers=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"default",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"default",l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{} -const a={} -return Object.values(r).filter((e=>"resolver"===e.Type)).forEach((function(l){const r=l.Name.split(".") -let u -r.length>4&&(u=r.shift()),r.reverse(),r.shift(),r.shift(),r.shift(),r.reverse() -const s=r.join("."),c=i(a,s,n,t,e) -let d -if(void 0!==l.Resolver.Failover&&(d=o(l.Resolver.Failover.Targets,l.Name)),u){const e={Subset:!0,ID:l.Name,Name:u} -void 0!==d&&(e.Failover=d),c.Children.push(e)}else void 0!==d&&(c.Failover=d)})),Object.values(l).forEach((l=>{if(void 0!==r[`resolver:${l.ID}`]){const u=o([l.ID],`service.${n}.${t}.${e}`) -if("Service"!==u.Type){const s=i(a,l.Service,n,t,e),c={Redirect:u.Type,ID:l.ID,Name:l[u.Type]} -void 0!==r[`resolver:${l.ID}`].Resolver.Failover&&(c.Failover=o(r[`resolver:${l.ID}`].Resolver.Failover.Targets,l.ID)),s.Children.push(c)}}})),Object.values(a)} -const a=function(e,t,l){return n(n({},e),{},{Default:e.Default||void 0===e.Definition.Match,ID:`route:${t}-${l(e.Definition)}`})} -e.createRoute=a})),define("consul-ui/components/consul/exposed-path/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"gs8UZz5a",block:'[[[11,0],[24,0,"consul-exposed-path-list"],[17,1],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,1],[[28,[37,1],[[30,2]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,0],[14,0,"header"],[12],[1,"\\n"],[44,[[28,[37,3],[[30,4],":",[30,3,["ListenerPort"]],[30,3,["Path"]]],null]],[[[1," "],[10,2],[14,0,"combined-address"],[12],[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[30,5]],[1,"\\n "],[13],[1,"\\n "],[8,[39,4],null,[["@value","@name"],[[30,5],"Address"]],null],[1,"\\n "],[13],[1,"\\n"]],[5]]],[1," "],[13],[1,"\\n "],[10,0],[14,0,"detail"],[12],[1,"\\n"],[41,[30,3,["Protocol"]],[[[1," "],[10,"dl"],[14,0,"protocol"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,6],null,null,[["default"],[[[[1,"\\n Protocol\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Protocol"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,3,["ListenerPort"]],[[[1," "],[10,"dl"],[14,0,"port"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,6],null,null,[["default"],[[[[1,"\\n Listener Port\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n listening on :"],[1,[30,3,["ListenerPort"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,3,["LocalPathPort"]],[[[1," "],[10,"dl"],[14,0,"port"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,6],null,null,[["default"],[[[[1,"\\n Local Path Port\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n local port :"],[1,[30,3,["LocalPathPort"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,3,["Path"]],[[[1," "],[10,"dl"],[14,0,"path"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,6],null,null,[["default"],[[[[1,"\\n Path\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Path"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@items","path","@address","combinedAddress"],false,["each","-track-array","let","concat","copy-button","if","tooltip"]]',moduleName:"consul-ui/components/consul/exposed-path/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/external-source/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"qg6NqCwn",block:'[[[41,[30,1],[[[44,[[28,[37,2],[[30,1]],null]],[[[41,[28,[37,3],[[30,3],[28,[37,4],[[30,2],"consul-api-gateway"],null]],null],[[[1," "],[10,"dl"],[14,0,"tooltip-panel"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[11,1],[24,0,"consul-external-source"],[17,4],[12],[1,"\\n "],[8,[39,5],[[24,0,"mr-1.5 w-4 h-4"]],[["@name"],[[28,[37,6],[[30,2]],null]]],null],[1,"\\n Registered via "],[1,[28,[35,7],[[28,[37,8],["common.brand.",[30,2]],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@position","@menu"],["left",false]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@name"],["header"]],[["default"],[[[[1,"\\n API Gateways manage north-south traffic from external services to services in the Datacenter. For more information, read our documentation.\\n "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,"role","separator"],[12],[1,"\\n About "],[1,[28,[35,7],[[28,[37,8],["common.brand.",[30,2]],null]],null]],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[14,"role","none"],[14,0,"learn-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,8],[[28,[37,11],["CONSUL_DOCS_LEARN_URL"],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n Learn guides\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[41,[30,2],[[[1," "],[11,1],[24,0,"consul-external-source"],[17,4],[12],[1,"\\n "],[8,[39,5],[[24,0,"mr-1.5 h-4 w-4"]],[["@name","@color"],[[28,[37,6],[[30,2]],null],"var(--token-color-hashicorp-brand)"]],null],[1,"\\n"],[41,[30,5],[[[1," "],[1,[30,5]],[1,"\\n"]],[]],[[[1," Registered via "],[1,[28,[35,7],[[28,[37,8],["common.brand.",[30,2]],null]],null]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]],null]],[]]]],[2]]]],[]],null]],["@item","externalSource","@withInfo","&attrs","@label"],false,["if","let","service/external-source","and","eq","flight-icon","icon-mapping","t","concat","menu-panel","block-slot","env"]]',moduleName:"consul-ui/components/consul/external-source/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/hcp/home/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"0fh1ph90",block:'[[[11,0],[24,0,"consul-hcp-home"],[17,1],[12],[1,"\\n "],[10,3],[15,6,[28,[37,0],["CONSUL_HCP_URL"],null]],[14,"data-native-href","true"],[12],[1,"\\n Back to HCP\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs"],false,["env"]]',moduleName:"consul-ui/components/consul/hcp/home/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/health-check/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"L0W/wK5V",block:'[[[11,0],[24,0,"consul-health-check-list"],[17,1],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,1],[[28,[37,1],[[30,2]],null]],null],null,[[[1," "],[10,"li"],[15,0,[28,[37,2],["health-check-output ",[30,3,["Status"]]],null]],[12],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,[30,3,["Name"]]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n"],[41,[28,[37,4],[[30,3,["Kind"]],"node"],null],[[[1," "],[10,"dt"],[12],[1,"NodeName"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,3,["Node"]]],[13],[1,"\\n"]],[]],[[[1," "],[10,"dt"],[12],[1,"ServiceName"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,3,["ServiceName"]]],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"CheckID"],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,5],[[30,3,["CheckID"]],"-"],null]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Type"],[13],[1,"\\n "],[10,"dd"],[14,"data-health-check-type",""],[12],[1,"\\n "],[1,[30,3,["Type"]]],[1,"\\n"],[41,[30,3,["Exposed"]],[[[1," "],[11,"em"],[4,[38,6],["Expose.checks is set to true, so all registered HTTP and gRPC check paths are exposed through Envoy for the Consul agent."],null],[12],[1,"Exposed"],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Notes"],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,5],[[30,3,["Notes"]],"-"],null]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Output"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"pre"],[12],[10,"code"],[12],[1,[30,3,["Output"]]],[13],[13],[1,"\\n "],[8,[39,7],null,[["@value","@name"],[[30,3,["Output"]],"output"]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@items","item"],false,["each","-track-array","concat","if","eq","or","tooltip","copy-button"]]',moduleName:"consul-ui/components/consul/health-check/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})) -define("consul-ui/components/consul/health-check/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"UNgiEnUJ",block:'[[[8,[39,0],[[24,0,"consul-healthcheck-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.health-check.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.health-check.search-bar.",[30,3,["status","key"]],".options.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n"],[41,[30,2,["searchproperty"]],[[[1," "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,10],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,11],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-status"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["status","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.consul.status"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["passing","warning","critical","empty"],null]],null]],null],null,[[[1," "],[8,[30,16],[[16,0,[29,["value-",[30,17]]]]],[["@value","@selected"],[[30,17],[28,[37,10],[[30,17],[30,2,["status","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[30,17]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,17]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n"],[41,[30,2,["kind"]],[[[1," "],[8,[30,13,["Select"]],[[24,0,"type-kind"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["kind","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.health-check.search-bar.kind.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,18,["Optgroup"]],[30,18,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["service","node"],null]],null]],null],null,[[[1," "],[8,[30,20],null,[["@value","@selected"],[[30,21],[28,[37,10],[[30,21],[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.health-check.search-bar.kind.options.",[30,21]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,21]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[21]],null]],[19,20]]],[1," "]],[]]]]],[1,"\\n "]],[18]]]]],[1,"\\n"]],[]],null],[1," "],[8,[30,13,["Select"]],[[24,0,"type-check"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["check","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.health-check.search-bar.check.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,22,["Optgroup"]],[30,22,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["alias","docker","grpc","http","script","serf","tcp","ttl"],null]],null]],null],null,[[[1," "],[8,[30,24],null,[["@value","@selected"],[[30,25],[28,[37,10],[[30,25],[30,2,["check","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.health-check.search-bar.check.options.",[30,25]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,25]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[25]],null]],[23,24]]],[1," "]],[]]]]],[1,"\\n "]],[22]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,26,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,27,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,12],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["Status:asc",[28,[37,2],["common.sort.status.asc"],null]],null],[28,[37,4],["Status:desc",[28,[37,2],["common.sort.status.desc"],null]],null],[28,[37,4],["Kind:asc",[28,[37,2],["components.consul.health-check.search-bar.sort.kind.asc"],null]],null],[28,[37,4],["Kind:desc",[28,[37,2],["components.consul.health-check.search-bar.sort.kind.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,13],[[30,29],[30,27,["value"]]],null]],[1,"\\n"]],[29]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,28,["Optgroup"]],[30,28,["Option"]]],[[[1," "],[8,[30,30],null,[["@label"],[[28,[37,2],["common.consul.status"],null]]],[["default"],[[[[1,"\\n "],[8,[30,31],null,[["@value","@selected"],["Status:asc",[28,[37,14],["Status:asc",[30,27,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,31],null,[["@value","@selected"],["Status:desc",[28,[37,14],["Status:desc",[30,27,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,30],null,[["@label"],[[28,[37,2],["components.consul.health-check.search-bar.sort.name.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,31],null,[["@value","@selected"],["Name:asc",[28,[37,14],["Name:asc",[30,27,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,31],null,[["@value","@selected"],["Name:desc",[28,[37,14],["Name:desc",[30,27,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,30],null,[["@label"],[[28,[37,2],["components.consul.health-check.search-bar.sort.kind.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,31],null,[["@value","@selected"],["Kind:asc",[28,[37,14],["Kind:asc",[30,27]],null]]],[["default"],[[[[1,"Service to Node"]],[]]]]],[1,"\\n "],[8,[30,31],null,[["@value","@selected"],["Kind:desc",[28,[37,14],["Kind:desc",[30,27]],null]]],[["default"],[[[[1,"Node to Service"]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[30,31]]],[1," "]],[]]]]],[1,"\\n "]],[28]]]]],[1,"\\n "]],[26]]]]]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","state","components","Optgroup","Option","item","components","Optgroup","Option","item","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","if","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/health-check/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/instance-checks/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"ddRn9Bp0",block:'[[[44,[[28,[37,1],["Status",[28,[37,2],[[30,1],[28,[37,3],null,null]],null]],null]],[[[44,[[28,[37,2],[[52,[28,[37,5],[[30,2,["critical","length"]],0],null],[30,2,["critical"]]],[52,[28,[37,5],[[30,2,["warning","length"]],0],null],[30,2,["warning"]]],[52,[28,[37,5],[[30,2,["passing","length"]],0],null],[30,2,["passing"]]],[28,[37,3],null,null]],null]],[[[44,[[30,3,["firstObject","Status"]]],[[[1," "],[11,"dl"],[16,0,[28,[37,6],["consul-instance-checks",[28,[37,3],["empty",[28,[37,7],[[30,3,["length"]],0],null]],null],[28,[37,3],[[30,4],[28,[37,8],[[30,3,["length"]],0],null]],null]],null]],[17,5],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,9],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,10],[[30,6]],null]],[1," Checks\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[44,[[28,[37,2],[[52,[28,[37,7],[[30,4],"critical"],null],"failing"],[52,[28,[37,7],[[30,4],"warning"],null],"with a warning"],[30,4]],null]],[[[1," "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,2],[[52,[28,[37,7],[[30,3,["length"]],0],null],[28,[37,11],["No ",[30,6]," checks"],null]],[52,[28,[37,7],[[30,3,["length"]],[30,1,["length"]]],null],[28,[37,11],["All ",[30,6]," checks ",[30,7]],null]],[28,[37,11],[[30,3,["length"]],"/",[30,1,["length"]]," ",[30,6]," checks ",[30,7]],null]],null]],[1,"\\n "],[13],[1,"\\n"]],[7]]],[1," "],[13],[1,"\\n"]],[4]]]],[3]]]],[2]]]],["@items","grouped","checks","status","&attrs","@type","humanized"],false,["let","group-by","or","array","if","gt","class-map","eq","not-eq","tooltip","capitalize","concat"]]',moduleName:"consul-ui/components/consul/instance-checks/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/intention/form/fieldsets/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"fVbLeBz9",block:'[[[11,0],[17,1],[24,0,"consul-intention-fieldsets"],[12],[1,"\\n "],[10,"fieldset"],[15,"disabled",[36,0]],[12],[1,"\\n "],[10,0],[14,"role","group"],[12],[1,"\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Source"],[13],[1,"\\n "],[10,"label"],[15,0,[29,["type-select",[52,[33,2,["error","SourceName"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Source Service"],[13],[1,"\\n "],[8,[39,3],null,[["@disabled","@options","@searchField","@selected","@searchPlaceholder","@buildSuggestion","@showCreateWhen","@onCreate","@onChange"],[[28,[37,4],[[33,5]],null],[99,6,["@options"]],"Name",[99,7,["@selected"]],"Type service name",[28,[37,8],[[30,0],"createNewLabel","Use a Consul Service called \'{{term}}\'"],null],[28,[37,8],[[30,0],"isUnique",[33,6]],null],[28,[37,8],[[30,0],[33,9],"SourceName"],null],[28,[37,8],[[30,0],[33,9],"SourceName"],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],[[30,2,["Name"]],"*"],null],[[[1," * (All Services)\\n"]],[]],[[[1," "],[1,[30,2,["Name"]]],[1,"\\n"]],[]]],[1," "]],[2]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[10,"em"],[12],[1,"Search for an existing service, or enter any Service name."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"],[41,[28,[37,11],["choose nspaces"],null],[[[1," "],[10,"label"],[15,0,[29,["type-select",[52,[33,2,["error","SourceNS"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Source Namespace"],[13],[1,"\\n "],[8,[39,3],null,[["@disabled","@options","@selected","@searchPlaceholder","@buildSuggestion","@showCreateWhen","@onCreate","@onChange"],[[28,[37,4],[[33,5]],null],[99,12,["@options"]],[99,13,["@selected"]],"Type namespace name",[28,[37,8],[[30,0],"createNewLabel","Use a Consul Namespace called \'{{term}}\'"],null],[28,[37,8],[[30,0],"isUnique",[33,12]],null],[28,[37,8],[[30,0],[33,9],"SourceNS"],null],[28,[37,8],[[30,0],[33,9],"SourceNS"],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],[[30,3,["Name"]],"*"],null],[[[1," * (All Namespaces)\\n"]],[]],[[[1," "],[1,[30,3,["Name"]]],[1,"\\n"]],[]]],[1," "]],[3]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[10,"em"],[12],[1,"Search for an existing namespace, or enter any Namespace name."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]],null],[41,[28,[37,11],["choose partitions"],[["dc"],[[30,4]]]],[[[1," "],[10,"label"],[15,0,[29,["type-select",[52,[33,2,["error","SourcePartition"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Source Partition"],[13],[1,"\\n "],[8,[39,3],null,[["@disabled","@options","@selected","@searchPlaceholder","@buildSuggestion","@showCreateWhen","@onCreate","@onChange"],[[28,[37,4],[[33,5]],null],[99,14,["@options"]],[99,15,["@selected"]],"Type partition name",[28,[37,8],[[30,0],"createNewLabel","Use a Consul Partition called \'{{term}}\'"],null],[28,[37,8],[[30,0],"isUnique",[33,14]],null],[28,[37,8],[[30,0],[33,9],"SourcePartition"],null],[28,[37,8],[[30,0],[33,9],"SourcePartition"],null]]],[["default"],[[[[1,"\\n "],[1,[30,5,["Name"]]],[1,"\\n "]],[5]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[10,"em"],[12],[1,"Search for an existing partition, or enter any Partition name."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Destination"],[13],[1,"\\n "],[10,"label"],[15,0,[29,["type-select",[52,[33,2,["error","DestinationName"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Destination Service"],[13],[1,"\\n "],[8,[39,3],null,[["@disabled","@options","@searchField","@selected","@searchPlaceholder","@buildSuggestion","@showCreateWhen","@onCreate","@onChange"],[[28,[37,4],[[33,5]],null],[99,6,["@options"]],"Name",[99,16,["@selected"]],"Type service name",[28,[37,8],[[30,0],"createNewLabel","Use a Consul Service called \'{{term}}\'"],null],[28,[37,8],[[30,0],"isUnique",[33,6]],null],[28,[37,8],[[30,0],[33,9],"DestinationName"],null],[28,[37,8],[[30,0],[33,9],"DestinationName"],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],[[30,6,["Name"]],"*"],null],[[[1," * (All Services)\\n"]],[]],[[[1," "],[1,[30,6,["Name"]]],[1,"\\n"]],[]]],[1," "]],[6]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[10,"em"],[12],[1,"Search for an existing service, or enter any Service name."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"],[41,[28,[37,11],["choose nspaces"],null],[[[1," "],[10,"label"],[15,0,[29,["type-select",[52,[33,2,["error","DestinationNS"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Destination Namespace"],[13],[1,"\\n "],[8,[39,3],null,[["@disabled","@options","@searchField","@selected","@searchPlaceholder","@buildSuggestion","@showCreateWhen","@onCreate","@onChange"],[[28,[37,4],[[33,5]],null],[99,12,["@options"]],"Name",[99,17,["@selected"]],"Type namespace name",[28,[37,8],[[30,0],"createNewLabel","Use a future Consul Namespace called \'{{term}}\'"],null],[28,[37,8],[[30,0],"isUnique",[33,12]],null],[28,[37,8],[[30,0],[33,9],"DestinationNS"],null],[28,[37,8],[[30,0],[33,9],"DestinationNS"],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],[[30,7,["Name"]],"*"],null],[[[1," * (All Namespaces)\\n"]],[]],[[[1," "],[1,[30,7,["Name"]]],[1,"\\n"]],[]]],[1," "]],[7]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[10,"em"],[12],[1,"For the destination, you may choose any namespace for which you have access."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]],null],[41,[28,[37,11],["choose partitions"],[["dc"],[[30,4]]]],[[[1," "],[10,"label"],[15,0,[29,["type-select",[52,[33,2,["error","DestinationPartition"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Destination Partition"],[13],[1,"\\n "],[8,[39,3],null,[["@disabled","@options","@searchField","@selected","@searchPlaceholder","@buildSuggestion","@showCreateWhen","@onCreate","@onChange"],[[28,[37,4],[[33,5]],null],[99,14,["@options"]],"Name",[99,18,["@selected"]],"Type partition name",[28,[37,8],[[30,0],"createNewLabel","Use a future Consul Partition called \'{{term}}\'"],null],[28,[37,8],[[30,0],"isUnique",[33,14]],null],[28,[37,8],[[30,0],[33,9],"DestinationPartition"],null],[28,[37,8],[[30,0],[33,9],"DestinationPartition"],null]]],[["default"],[[[[1,"\\n "],[1,[30,8,["Name"]]],[1,"\\n "]],[8]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[10,"em"],[12],[1,"For the destination, you may choose any partition for which you have access."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"label"],[15,0,[29,["type-text",[52,[33,2,["error","Description"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Description (Optional)"],[13],[1,"\\n "],[10,"input"],[14,3,"Description"],[15,2,[33,2,["Description"]]],[14,"placeholder","Description (Optional)"],[15,"onchange",[28,[37,8],[[30,0],[33,9]],null]],[14,4,"text"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,1],[14,0,"label"],[12],[1,"Should this source connect to the destination?"],[13],[1,"\\n "],[10,0],[14,"role","radiogroup"],[15,0,[52,[33,2,["error","Action"]]," has-error"]],[12],[1,"\\n"],[42,[28,[37,20],[[28,[37,20],[[28,[37,21],[[28,[37,22],null,[["intent","header","body"],["allow","Allow","The source service will be allowed to connect to the destination."]]],[28,[37,22],null,[["intent","header","body"],["deny","Deny","The source service will not be allowed to connect to the destination."]]],[28,[37,22],null,[["intent","header","body"],["","Application Aware","The source service may or may not connect to the destination service via unique permissions based on Layer 7 criteria: path, header, or method."]]]],null]],null]],null],null,[[[1," "],[8,[39,23],[[16,0,[28,[37,24],["value-",[30,9,["intent"]]],null]]],[["@value","@checked","@onchange","@name"],[[30,9,["intent"]],[52,[28,[37,10],[[28,[37,25],[[33,2,["Action"]],""],null],[30,9,["intent"]]],null],"checked"],[28,[37,8],[[30,0],[33,9]],null],"Action"]],[["default"],[[[[1,"\\n "],[10,"header"],[12],[1,"\\n "],[1,[30,9,["header"]]],[1,"\\n "],[13],[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[30,9,["body"]]],[1,"\\n "],[13],[1,"\\n "]],[10]]]]],[1,"\\n"]],[9]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,10],[[28,[37,25],[[33,2,["Action"]],""],null],""],null],[[[1," "],[10,"fieldset"],[14,0,"permissions"],[12],[1,"\\n "],[8,[39,26],[[4,[38,27],["click",[28,[37,8],[[30,0],[30,0,["openModal"]]],null]],null]],[["@text","@size","@color","@icon"],["Add permission","small","tertiary","plus"]],null],[1,"\\n "],[10,"h2"],[12],[1,"Permissions"],[13],[1,"\\n"],[41,[28,[37,28],[[33,2,["Permissions","length"]],0],null],[[[1," "],[8,[39,29],null,null,null],[1,"\\n "],[8,[39,30],null,[["@items","@onclick","@ondelete"],[[33,2,["Permissions"]],[28,[37,31],[[28,[37,8],[[30,0],[28,[37,32],[[33,33]],null]],null],[28,[37,8],[[30,0],[30,0,["openModal"]]],null]],null],[28,[37,8],[[30,0],"delete","Permissions",[33,2]],null]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,34],null,null,[["default"],[[[[1,"\\n "],[8,[39,35],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h3"],[12],[1,"\\n No permissions yet\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,35],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Permissions intercept an Intention\'s traffic using Layer 7 criteria, such as path prefixes and http headers.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,35],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,36],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation",[29,[[28,[37,37],["CONSUL_DOCS_URL"],null],"/commands/intention"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,36],null,[["@text","@href","@icon","@iconPosition","@size"],["Read the guide",[29,[[28,[37,37],["CONSUL_DOCS_LEARN_URL"],null],"/consul/getting-started/connect"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,38],[[24,0,"consul-intention-permission-modal"]],[["@onclose","@aria"],[[28,[37,8],[[30,0],[28,[37,32],[[33,33]],null],[27]],null],[28,[37,22],null,[["label"],["Edit Permission"]]]]],[["default"],[[[[1,"\\n "],[8,[39,39],null,[["@target","@name","@value"],[[30,0],"modal",[30,11]]],null],[1,"\\n "],[8,[39,35],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h3"],[12],[1,"Edit Permission"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,35],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[8,[39,40],null,[["@item","@onsubmit"],[[99,33,["@item"]],[28,[37,8],[[30,0],"add","Permissions",[33,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,39],null,[["@target","@name","@value"],[[30,0],"permissionForm",[30,12]]],null],[1,"\\n "]],[12]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,35],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,41],null,null,[["default"],[[[[1,"\\n "],[8,[39,26],[[16,"disabled",[52,[28,[37,4],[[30,0,["permissionForm","isDirty"]]],null],"disabled"]],[16,"onclick",[28,[37,31],[[28,[37,8],[[30,0],[30,0,["permissionForm","submit"]]],null],[28,[37,8],[[30,0],[30,11,["close"]]],null]],null]]],[["@text","@color"],["Save","primary"]],null],[1,"\\n "],[8,[39,26],[[16,"onclick",[28,[37,31],[[28,[37,8],[[30,0],[30,0,["permissionForm","reset"]]],null],[28,[37,8],[[30,0],[30,11,["close"]]],null]],null]]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[11]]]]],[1,"\\n\\n"],[13]],["&attrs","service","nspace","@dc","partition","service","nspace","partition","_action","radio","modal","permissionForm"],false,["disabled","if","item","power-select-with-create","not","create","services","SourceName","action","onchange","eq","can","nspaces","SourceNS","partitions","SourcePartition","DestinationName","DestinationNS","DestinationPartition","each","-track-array","array","hash","radio-card","concat","or","hds/button","on","gt","consul/intention/notice/permissions","consul/intention/permission/list","queue","mut","permission","empty-state","block-slot","hds/link/standalone","env","modal-dialog","ref","consul/intention/permission/form","hds/button-set"]]',moduleName:"consul-ui/components/consul/intention/form/fieldsets/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:"",shouldShowPermissionForm:!1,openModal(){var e -null===(e=this.modal)||void 0===e||e.open()},actions:{createNewLabel:function(e,t){return e.replace(/{{term}}/g,t)},isUnique:function(e,t){return!e.findBy("Name",t)},add:function(e,t,n){!(t.get(e)||[]).includes(n)&&n.isNew&&(t.pushObject(e,n),t.validate())},delete:function(e,t,n){(t.get(e)||[]).includes(n)&&(t.removeObject(e,n),t.validate())}}})) -e.default=r})),define("consul-ui/components/consul/intention/form/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/object","@glimmer/tracking"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m,h,b,y,g,v -function O(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function P(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const x=(0,n.createTemplateFactory)({id:"8yZp6UDg",block:'[[[11,0],[24,0,"consul-intention"],[17,1],[12],[1,"\\n"],[8,[39,0],null,[["@type","@dc","@nspace","@partition","@autofill","@item","@src","@onchange","@onsubmit"],["intention",[30,2,["Name"]],[30,3],[30,4],[30,5],[30,6],[30,7],[28,[37,1],[[30,0],[30,0,["change"]]],null],[28,[37,1],[[30,0],[30,0,["onsubmit"]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,4],[[30,8,["error","detail"]],"duplicate intention found:"],null],[[[1," "],[8,[39,5],[[4,[38,6],null,[["after"],[[28,[37,1],[[30,0],[30,9]],null]]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,10,["Title"]],null,null,[["default"],[[[[1,"Intention exists!"]],[]]]]],[1,"\\n "],[8,[30,10,["Description"]],null,null,[["default"],[[[[1,"\\n An intention already exists for this Source-Destination pair. Please enter a different combination of Services, or search the intentions to edit an existing intention.\\n "]],[]]]]],[1,"\\n "]],[10]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,5],[[4,[38,6],null,[["after"],[[28,[37,1],[[30,0],[30,9]],null]]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,11,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,11,["Description"]],null,null,[["default"],[[[[1,"\\n There was an error saving your intention.\\n"],[41,[28,[37,7],[[30,8,["error","status"]],[30,8,["error","detail"]]],null],[[[1," "],[10,"br"],[12],[13],[1,[30,8,["error","status"]]],[1,": "],[1,[30,8,["error","detail"]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[11]]]]],[1,"\\n"]],[]]],[1," "]],[9]]]]],[1,"\\n\\n "],[8,[39,2],null,[["@name"],["form"]],[["default"],[[[[1,"\\n"],[44,[[30,8,["data"]],[28,[37,9],[[28,[37,10],["write intention"],[["item"],[[30,8,["data"]]]]]],null]],[[[41,[28,[37,9],[[30,13]],null],[[[1,"\\n"],[44,[[28,[37,11],[[30,12],"Action"],null]],[[[1," "],[8,[39,12],[[24,0,"consul-intention-action-warn-modal warning"]],[["@aria"],[[28,[37,13],null,[["label"],[[28,[37,14],["Set intention to ",[30,14]],null]]]]]],[["default"],[[[[1,"\\n "],[8,[39,15],null,[["@target","@name","@value"],[[30,0],"modal",[30,15]]],null],[1,"\\n "],[8,[39,2],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"Set intention to "],[1,[30,14]],[1,"?"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,2],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n When you change this Intention to "],[1,[30,14]],[1,", you will remove all the Layer 7 policy permissions currently saved to this Intention. Are you sure you want to set it to "],[1,[30,14]],[1,"?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,2],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n "],[8,[39,17],[[4,[38,19],["click",[30,8,["submit"]]],null]],[["@text","@color"],[[29,["Set to ",[28,[37,18],[[30,14]],null]]],"critical"]],null],[1,"\\n "],[8,[39,17],[[16,"onclick",[30,16]]],[["@text","@color"],["No, Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[16]]]]],[1,"\\n "]],[15]]]]],[1,"\\n"]],[14]]],[1,"\\n "],[8,[39,20],null,[["@src","@onchange"],[[28,[37,21],["/${partition}/*/${dc}/services",[28,[37,13],null,[["partition","dc"],[[30,4],[30,2,["Name"]]]]]],null],[28,[37,1],[[30,0],[30,0,["createServices"]],[30,12]],null]]],null],[1,"\\n\\n"],[41,[28,[37,10],["use nspaces"],null],[[[1," "],[8,[39,20],null,[["@src","@onchange"],[[28,[37,21],["/${partition}/*/${dc}/namespaces",[28,[37,13],null,[["partition","dc"],[[30,4],[30,2,["Name"]]]]]],null],[28,[37,1],[[30,0],[30,0,["createNspaces"]],[30,12]],null]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[41,[28,[37,10],["use partitions"],null],[[[1," "],[8,[39,20],null,[["@src","@onchange"],[[28,[37,21],["/*/*/${dc}/partitions",[28,[37,13],null,[["dc"],[[30,2,["Name"]]]]]],null],[28,[37,1],[[30,0],[30,0,["createPartitions"]],[30,12]],null]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[41,[30,8,["isCreate"]],[[[41,[28,[37,7],[[28,[37,10],["use partitions"],null],[28,[37,9],[[28,[37,10],["choose partitions"],[["dc"],[[30,2]]]]],null]],null],[[[1," "],[8,[39,22],[[24,0,"mb-3 mt-2"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,17,["Title"]],null,null,[["default"],[[[[1,"Cross-partition communication not supported"]],[]]]]],[1,"\\n "],[8,[30,17,["Description"]],null,null,[["default"],[[[[1,"Cross-partition communication is not supported outside of the primary datacenter. You will only be able to select namespaces for source and destination services."]],[]]]]],[1,"\\n "]],[17]]]]],[1,"\\n"]],[]],null],[41,[30,0,["isManagedByCRDs"]],[[[1," "],[8,[39,23],null,[["@type"],["warning"]],null],[1,"\\n"]],[]],null]],[]],null],[1," "],[11,"form"],[4,[38,19],["submit",[28,[37,24],[[30,0,["submit"]],[30,12],[30,8,["submit"]]],null]],null],[12],[1,"\\n "],[8,[39,25],null,[["@nspaces","@dc","@partitions","@services","@SourceName","@SourceNS","@SourcePartition","@DestinationName","@DestinationNS","@DestinationPartition","@item","@disabled","@create","@onchange"],[[30,0,["nspaces"]],[30,2],[30,0,["partitions"]],[30,0,["services"]],[30,0,["SourceName"]],[30,0,["SourceNS"]],[30,0,["SourcePartition"]],[30,0,["DestinationName"]],[30,0,["DestinationNS"]],[30,0,["DestinationPartition"]],[30,12],[30,8,["disabled"]],[30,8,["isCreate"]],[30,8,["change"]]]],null],[1,"\\n "],[10,0],[12],[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n "],[8,[39,17],[[16,"disabled",[28,[37,26],[[30,12,["isInvalid"]],[30,8,["disabled"]]],null]],[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n "],[8,[39,17],[[16,"disabled",[30,8,["disabled"]]],[24,4,"reset"],[4,[38,19],["click",[28,[37,24],[[30,0,["oncancel"]],[30,12]],null]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"],[41,[28,[37,9],[[30,8,["isCreate"]]],null],[[[41,[28,[37,27],[[30,12,["ID"]],"anonymous"],null],[[[1," "],[8,[39,28],null,[["@message"],["Are you sure you want to delete this Intention?"]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,17],[[16,"disabled",[30,8,["disabled"]]],[4,[38,19],["click",[28,[37,24],[[30,18],[30,8,["delete"]]],null]],null]],[["@text","@color"],["Delete","critical"]],null],[1,"\\n "]],[18]]]]],[1,"\\n "],[8,[39,2],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@message","@execute","@cancel"],[[30,21],[30,19],[30,20]]],null],[1,"\\n "]],[19,20,21]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1,"\\n"],[41,[30,12,["IsManagedByCRD"]],[[[1," "],[8,[39,22],[[24,0,"mb-3 mt-2"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,22,["Title"]],null,null,[["default"],[[[[1,"Intention Custom Resource"]],[]]]]],[1,"\\n "],[8,[30,22,["Description"]],null,null,[["default"],[[[[1,"This Intention is view only because it is managed through an Intention Custom Resource in your Kubernetes cluster."]],[]]]]],[1,"\\n "],[8,[30,22,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition"],["Learn more about CRDs",[29,[[28,[37,30],["CONSUL_DOCS_URL"],null],"/k8s/crds"]],"docs-link","trailing"]],null],[1,"\\n "]],[22]]]]],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,31],null,[["@item"],[[30,12]]],null],[1,"\\n"]],[]]]],[12,13]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[8]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@dc","@nspace","@partition","@autofill","@item","@src","api","after","T","T","item","readonly","newAction","modal","close","A","confirm","execute","cancel","message","A"],false,["data-form","action","block-slot","if","string-starts-with","hds/toast","notification","and","let","not","can","changeset-get","modal-dialog","hash","concat","ref","hds/button-set","hds/button","capitalize","on","data-source","uri","hds/alert","consul/intention/notice/custom-resource","fn","consul/intention/form/fieldsets","or","not-eq","confirmation-dialog","delete-confirmation","env","consul/intention/view"]]',moduleName:"consul-ui/components/consul/intention/form/index.hbs",isStrictMode:!1}) -let w=(a=(0,r.inject)("repository/intention"),u=class extends l.default{constructor(e,t){var n,l,r -super(...arguments),O(this,"services",s,this),O(this,"SourceName",c,this),O(this,"DestinationName",d,this),O(this,"nspaces",p,this),O(this,"SourceNS",f,this),O(this,"DestinationNS",m,this),O(this,"partitions",h,this),O(this,"SourcePartition",b,this),O(this,"DestinationPartition",y,this),O(this,"isManagedByCRDs",g,this),r=null,(l="modal")in(n=this)?Object.defineProperty(n,l,{value:r,enumerable:!0,configurable:!0,writable:!0}):n[l]=r,O(this,"repo",v,this),this.updateCRDManagement()}ondelete(){this.args.ondelete?this.args.ondelete(...arguments):this.onsubmit(...arguments)}oncancel(){this.args.oncancel?this.args.oncancel(...arguments):this.onsubmit(...arguments)}onsubmit(){this.args.onsubmit&&this.args.onsubmit(...arguments)}updateCRDManagement(){this.isManagedByCRDs=this.repo.isManagedByCRDs()}submit(e,t,n){n.preventDefault(),void 0!==e.change.Action&&void 0===e.data.Action?this.modal.open():t()}createServices(e,t){let n=t.data.uniqBy("Name").toArray().filter((e=>!["connect-proxy","mesh-gateway","terminating-gateway"].includes(e.Kind))).sort(((e,t)=>e.Name.localeCompare(t.Name))) -n=[{Name:"*"}].concat(n) -let l=n.findBy("Name",e.SourceName) -l||(l={Name:e.SourceName},n=[l].concat(n)) -let r=n.findBy("Name",e.DestinationName) -r||(r={Name:e.DestinationName},n=[r].concat(n)),this.services=n,this.SourceName=l,this.DestinationName=r}createNspaces(e,t){let n=t.data.toArray().sort(((e,t)=>e.Name.localeCompare(t.Name))) -n=[{Name:"*"}].concat(n) -let l=n.findBy("Name",e.SourceNS) -l||(l={Name:e.SourceNS},n=[l].concat(n)) -let r=n.findBy("Name",e.DestinationNS) -r||(r={Name:e.DestinationNS},n=[r].concat(n)),this.nspaces=n,this.SourceNS=l,this.DestinationNS=r}createPartitions(e,t){let n=t.data.toArray().sort(((e,t)=>e.Name.localeCompare(t.Name))),l=n.findBy("Name",e.SourcePartition) -l||(l={Name:e.SourcePartition},n=[l].concat(n)) -let r=n.findBy("Name",e.DestinationPartition) -r||(r={Name:e.DestinationPartition},n=[r].concat(n)),this.partitions=n,this.SourcePartition=l,this.DestinationPartition=r}change(e,t,n){const l=e.target -let r,i -switch(l.name){case"SourceName":case"DestinationName":case"SourceNS":case"DestinationNS":case"SourcePartition":case"DestinationPartition":switch(r=i=l.value,"string"!=typeof r&&(r=l.value.Name),l.value=r,l.name){case"SourceName":case"DestinationName":0===this.services.filterBy("Name",r).length&&(i={Name:r},this.services=[i].concat(this.services.toArray())) -break -case"SourceNS":case"DestinationNS":0===this.nspaces.filterBy("Name",r).length&&(i={Name:r},this.nspaces=[i].concat(this.nspaces.toArray())) -break -case"SourcePartition":case"DestinationPartition":0===this.partitions.filterBy("Name",r).length&&(i={Name:r},this.partitions=[i].concat(this.partitions.toArray()))}this[l.name]=i}t.handleEvent(e)}},s=P(u.prototype,"services",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=P(u.prototype,"SourceName",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=P(u.prototype,"DestinationName",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=P(u.prototype,"nspaces",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=P(u.prototype,"SourceNS",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=P(u.prototype,"DestinationNS",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=P(u.prototype,"partitions",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=P(u.prototype,"SourcePartition",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=P(u.prototype,"DestinationPartition",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=P(u.prototype,"isManagedByCRDs",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=P(u.prototype,"repo",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P(u.prototype,"ondelete",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"ondelete"),u.prototype),P(u.prototype,"oncancel",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"oncancel"),u.prototype),P(u.prototype,"onsubmit",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"onsubmit"),u.prototype),P(u.prototype,"updateCRDManagement",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"updateCRDManagement"),u.prototype),P(u.prototype,"submit",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"submit"),u.prototype),P(u.prototype,"createServices",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"createServices"),u.prototype),P(u.prototype,"createNspaces",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"createNspaces"),u.prototype),P(u.prototype,"createPartitions",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"createPartitions"),u.prototype),P(u.prototype,"change",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"change"),u.prototype),u) -e.default=w,(0,t.setComponentTemplate)(x,w)})),define("consul-ui/components/consul/intention/list/check/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"R9NJf0hk",block:'[[[44,[[28,[37,1],[[28,[37,2],[[28,[37,2],["allow","Allowed"],null],[28,[37,2],["deny","Denied"],null],[28,[37,2],["","Layer 7 Rules"],null]],null]],null]],[[[11,0],[16,0,[28,[37,3],["consul-intention-list-check ","notice ",[28,[37,4],[[30,2,["Action"]],"permissions"],null]],null]],[17,3],[12],[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,5],[[30,1],[28,[37,4],[[30,2,["Action"]],""],null]],null]],[1,"\\n "],[13],[1,"\\n "],[10,2],[12],[1,"\\n"],[41,[28,[37,7],[[30,2,["Action"]],"allow"],null],[[[1," Yes, "],[1,[33,8,["SourceName"]]],[1," is allowed to connect to "],[1,[30,2,["DestinationName"]]],[1," due to the highest precedence intention below:\\n"]],[]],[[[41,[28,[37,7],[[30,2,["Action"]],"deny"],null],[[[1," No, "],[1,[30,2,["SourceName"]]],[1," is not allowed to connect to "],[1,[30,2,["DestinationName"]]],[1," due to the highest precedence intention below:\\n"]],[]],[[[1," "],[1,[30,2,["SourceName"]]],[1," may or may not be allowed to connect with "],[1,[30,2,["DestinationName"]]],[1," through its Layer 7 rules.\\n "]],[]]]],[]]],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],[1]]]],["titles","@item","&attrs"],false,["let","from-entries","array","concat","or","get","if","eq","item"]]',moduleName:"consul-ui/components/consul/intention/list/check/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/intention/list/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/object","@glimmer/tracking"],(function(e,t,n,l,r,i,o){var a,u,s,c -function d(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function p(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const f=(0,n.createTemplateFactory)({id:"t3Jtqz1v",block:'[[[11,0],[24,0,"consul-intention-list"],[17,1],[4,[38,0],[[30,0,["updateCRDManagement"]],[30,2]],null],[12],[1,"\\n"],[18,4,[[28,[37,2],null,[["Table","CheckNotice","CustomResourceNotice"],[[50,"consul/intention/list/table",0,null,[["delete","items"],[[30,3],[30,0,["items"]]]]],[52,[30,0,["checkedItem"]],[50,"consul/intention/list/check",0,null,[["item"],[[30,0,["checkedItem"]]]]],""],[52,[30,0,["isManagedByCRDs"]],[50,"consul/intention/notice/custom-resource",0,null,null],""]]]]]],[1,"\\n"],[13]],["&attrs","@items","@delete","&default"],false,["did-update","yield","hash","component","if"]]',moduleName:"consul-ui/components/consul/intention/list/index.hbs",isStrictMode:!1}) -let m=(a=(0,r.inject)("repository/intention"),u=class extends l.default{constructor(e,t){super(...arguments),d(this,"repo",s,this),d(this,"isManagedByCRDs",c,this),this.updateCRDManagement(t.items)}get items(){return this.args.items||[]}get checkedItem(){return 1===this.items.length&&this.args.check&&this.items[0].SourceName===this.args.check?this.items[0]:null}updateCRDManagement(){this.isManagedByCRDs=this.repo.isManagedByCRDs()}},s=p(u.prototype,"repo",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=p(u.prototype,"isManagedByCRDs",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p(u.prototype,"updateCRDManagement",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"updateCRDManagement"),u.prototype),u) -e.default=m,(0,t.setComponentTemplate)(f,m)})),define("consul-ui/components/consul/intention/list/table/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"5xWkkvyi",block:'[[[8,[39,0],[[24,0,"consul-intention-list-table"],[17,1]],[["@items","@rowHeight"],[[30,2],59]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[14,0,"source"],[12],[1,"Source"],[13],[1,"\\n "],[10,"th"],[14,0,"intent"],[12],[1," "],[13],[1,"\\n "],[10,"th"],[14,0,"destination"],[12],[1,"Destination"],[13],[1,"\\n "],[10,"th"],[14,0,"permissions"],[12],[1,"\\n Permissions\\n "],[10,1],[12],[1,"\\n "],[8,[39,2],null,null,[["default"],[[[[1,"Permissions intercept an Intention\'s traffic using Layer 7 criteria, such as path\\n prefixes and http headers."]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"th"],[14,0,"meta"],[12],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["row"]],[["default"],[[[[1,"\\n "],[10,"td"],[14,0,"source"],[12],[1,"\\n "],[10,3],[15,6,[28,[37,3],[[28,[37,4],[[30,5],"dc.intentions.edit"],null],[30,3,["ID"]]],null]],[12],[1,"\\n"],[41,[28,[37,6],[[30,3,["SourceName"]],"*"],null],[[[1," All Services (*)\\n"]],[]],[[[1," "],[1,[30,3,["SourceName"]]],[1,"\\n"]],[]]],[1," "],[10,"em"],[14,0,"consul-intention-list-table__meta-info"],[12],[1,"\\n "],[8,[39,7],null,[["@item","@nspace","@partition"],[[28,[37,8],null,[["Namespace","Partition","PeerName"],[[30,3,["SourceNS"]],[30,3,["SourcePartition"]],[30,3,["SourcePeer"]]]]],"-","-"]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[15,0,[29,["intent intent-",[28,[37,9],[[30,3,["Action"]]],null]]]],[12],[1,"\\n "],[10,"strong"],[12],[1,[28,[35,10],[[28,[37,4],[[30,3,["Action"]],"App aware"],null]],null]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[14,0,"destination"],[12],[1,"\\n "],[10,1],[12],[1,"\\n"],[41,[28,[37,6],[[30,3,["DestinationName"]],"*"],null],[[[1," All Services (*)\\n"]],[]],[[[1," "],[1,[30,3,["DestinationName"]]],[1,"\\n"]],[]]],[41,[28,[37,4],[[28,[37,11],["use nspaces"],null],[28,[37,11],["use partitions"],null]],null],[[[1," "],[10,"em"],[12],[1,"\\n "],[10,1],[15,0,[28,[37,12],["partition-",[28,[37,4],[[30,3,["DestinationPartition"]],"default"],null]],null]],[12],[1,[28,[35,4],[[30,3,["DestinationPartition"]],"default"],null]],[13],[1,"\\n /\\n "],[10,1],[15,0,[28,[37,12],["nspace-",[28,[37,4],[[30,3,["DestinationNS"]],"default"],null]],null]],[12],[1,[28,[35,4],[[30,3,["DestinationNS"]],"default"],null]],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[14,0,"permissions"],[12],[1,"\\n"],[41,[28,[37,13],[[30,3,["Permissions","length"]],0],null],[[[1," "],[10,1],[12],[1,[28,[35,14],[[30,3,["Permissions","length"]],"Permission"],null]],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[10,"td"],[14,0,"meta"],[12],[1,"\\n"],[41,[30,3,["IsManagedByCRD"]],[[[1," "],[8,[39,15],null,[["@item","@label"],[[30,3],"Managed by CRD"]],null],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,16],null,[["@expanded","@onchange","@keyboardAccess"],[[52,[28,[37,6],[[30,8],[30,6]],null],true,false],[28,[37,17],[[30,0],[30,7],[30,6]],null],false]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n More\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n"],[41,[28,[37,11],["write intention"],[["item"],[[30,3]]]],[[[1," "],[10,"li"],[14,"role","none"],[12],[1,"\\n "],[10,3],[14,"role","menuitem"],[14,"tabindex","-1"],[15,6,[28,[37,3],[[28,[37,4],[[33,18],"dc.intentions.edit"],null],[30,3,["ID"]]],null]],[12],[1,"Edit"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[14,"role","none"],[14,0,"dangerous"],[12],[1,"\\n "],[10,"label"],[15,"for",[30,9]],[14,"role","menuitem"],[14,"tabindex","-1"],[15,"onkeypress",[30,11]],[12],[1,"Delete"],[13],[1,"\\n "],[10,0],[14,"role","menu"],[12],[1,"\\n "],[8,[39,19],[[24,0,"warning"]],null,[["header","body","actions"],[[[[1,"\\n Confirm Delete\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this intention?\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,13,["Action"]],[[24,0,"dangerous"]],null,[["default"],[[[[1,"\\n "],[8,[39,17],[[24,0,"type-delete"],[24,"tabindex","-1"],[4,[38,20],["click",[28,[37,21],[[28,[37,17],[[30,0],[30,12]],null],[28,[37,17],[[30,0],[30,14],[30,3]],null]],null]],null]],null,[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,13,["Action"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,17],null,[["@for"],[[30,9]]],[["default"],[[[[1,"\\n Cancel\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[13]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[41,[28,[37,11],["view CRD intention"],[["item"],[[30,3]]]],[[[1," "],[10,"li"],[14,"role","none"],[12],[1,"\\n "],[10,0],[14,"role","menu"],[12],[1,"\\n "],[8,[39,19],null,null,[["header","body","actions"],[[[[1,"\\n "],[10,1],[14,0,"flex flex-nowrap items-center"],[12],[1,"\\n "],[8,[39,22],[[24,0,"mr-1.5"]],[["@name"],["kubernetes-color"]],null],[1,"\\n Managed by CRD\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n This intention is being managed through an Intention Custom Resource in your\\n Kubernetes cluster. It is view only in the UI.\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,15,["Action"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,17],[[24,"tabindex","-1"],[24,0,"action"]],[["@href"],[[28,[37,3],[[28,[37,4],[[30,5],"dc.intentions.edit"],null],[30,3,["ID"]]],null]]],[["default"],[[[[1,"\\n View\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,15,["Action"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,17],null,[["@onclick"],[[28,[37,17],[[30,0],[30,12]],null]]],[["default"],[[[[1,"\\n Cancel\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[15]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,"li"],[14,"role","none"],[12],[1,"\\n "],[10,3],[14,"role","menuitem"],[14,"tabindex","-1"],[15,6,[28,[37,3],[[28,[37,4],[[33,18],"dc.intentions.edit"],null],[30,3,["ID"]]],null]],[12],[1,"\\n View\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]],[]]],[1," "]],[9,10,11,12]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6,7,8]]]]],[1,"\\n"]],[3,4]]]]],[1,"\\n"]],["&attrs","@items","item","index","@routeName","index","change","checked","confirm","send","keypressClick","change","Actions","@delete","Actions"],false,["tabular-collection","block-slot","tooltip","href-to","or","if","eq","consul/bucket/list","hash","slugify","capitalize","can","concat","gt","pluralize","consul/external-source","popover-menu","action","routeName","informed-action","on","queue","flight-icon"]]',moduleName:"consul-ui/components/consul/intention/list/table/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/intention/notice/custom-resource/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"6ZXsu8uh",block:'[[[8,[39,0],[[24,0,"mb-2 mt-2 consul-intention-notice-custom-resource"]],[["@type","@color"],["inline",[28,[37,1],[[30,1],"neutral"],null]]],[["default"],[[[[1,"\\n "],[8,[30,2,["Title"]],null,null,[["default"],[[[[1,"Intention Custom Resource"]],[]]]]],[1,"\\n "],[8,[30,2,["Description"]],null,null,[["default"],[[[[1,"Some of your intentions are being managed through an Intention Custom Resource in your Kubernetes cluster. Those managed intentions will be view only in the UI. Any intentions created in the UI will work but will not be synced to the Custom Resource Definition (CRD) datastore."]],[]]]]],[1,"\\n "],[8,[30,2,["Link::Standalone"]],null,[["@href","@text","@icon","@iconPosition","@size"],[[29,[[28,[37,2],["CONSUL_DOCS_URL"],null],"/k8s/crds"]],"Learn more about CRDs","docs-link","trailing","small"]],null],[1,"\\n"]],[2]]]]]],["@type","A"],false,["hds/alert","or","env"]]',moduleName:"consul-ui/components/consul/intention/notice/custom-resource/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/intention/notice/permissions/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"DK7vccyg",block:'[[[8,[39,0],[[24,0,"mb-3 mt-2"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,1,["Description"]],null,null,[["default"],[[[[1,[28,[35,1],["components.consul.intention.notice.permissions.body"],null]]],[]]]]],[1,"\\n "],[8,[30,1,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition","@size"],[[28,[37,1],["components.consul.intention.notice.permissions.footer"],null],[29,[[28,[37,2],["CONSUL_DOCS_URL"],null],"/connect/intentions"]],"docs-link","trailing","small"]],null],[1,"\\n"]],[1]]]]]],["A"],false,["hds/alert","t","env"]]',moduleName:"consul-ui/components/consul/intention/notice/permissions/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/intention/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"qH69B/hI",block:'[[[41,[28,[37,1],[[30,1],"create"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your intention has been added.\\n"]],[]],[[[1," There was an error adding your intention.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"update"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your intention has been saved.\\n"]],[]],[[[1," There was an error saving your intention.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"delete"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your intention was deleted.\\n"]],[]],[[[1," There was an error deleting your intention.\\n"]],[]]]],[]],null]],[]]]],[]]],[44,[[30,3,["errors","firstObject"]]],[[[41,[30,4,["detail"]],[[[1," "],[10,"br"],[12],[13],[1,[28,[35,3],["(",[52,[30,4,["status"]],[28,[37,3],[[30,4,["status"]],": "],null]],[30,4,["detail"]],")"],null]],[1,"\\n"]],[]],null]],[4]]]],["@type","@status","@error","error"],false,["if","eq","let","concat"]]',moduleName:"consul-ui/components/consul/intention/notifications/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/intention/permission/form/index",["exports","@ember/component","@ember/template-factory","@ember/object","@ember/object/computed","@ember/service"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"9N7+TvqA",block:'[[[11,0],[17,1],[24,0,"consul-intention-permission-form"],[12],[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[18,11,[[28,[37,3],null,[["submit","reset","isDirty","changeset"],[[28,[37,4],[[30,0],"submit",[33,5]],null],[28,[37,4],[[30,0],"reset",[33,5]],null],[28,[37,6],[[33,5,["isValid"]]],null],[33,5]]]]]],[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,0],[14,"data-property","action"],[12],[1,"\\n "],[10,1],[14,0,"label"],[12],[1,"\\n Should this permission allow the source connect to the destination?\\n "],[13],[1,"\\n "],[10,0],[14,"role","radiogroup"],[15,0,[52,[33,5,["error","Action"]]," has-error"]],[12],[1,"\\n"],[42,[28,[37,9],[[28,[37,9],[[33,10]],null]],null],null,[[[1," "],[10,"label"],[12],[1,"\\n "],[10,1],[12],[1,[28,[35,11],[[30,3]],null]],[13],[1,"\\n "],[10,"input"],[14,3,"Action"],[15,2,[30,3]],[15,"checked",[52,[28,[37,12],[[33,5,["Action"]],[30,3]],null],"checked"]],[15,"onchange",[28,[37,4],[[30,0],[28,[37,13],[[33,5],"Action"],null]],[["value"],["target.value"]]]],[14,4,"radio"],[12],[13],[1,"\\n "],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Path"],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[12],[1,"\\n "],[8,[30,2,["Element"]],null,[["@name","@type"],["PathType","select"]],[["default"],[[[[1,"\\n "],[8,[30,4,["Label"]],null,null,[["default"],[[[[1,"\\n Path type\\n "]],[]]]]],[1,"\\n "],[8,[39,14],null,[["@options","@selected","@onChange"],[[99,15,["@options"]],[99,16,["@selected"]],[28,[37,4],[[30,0],"change","HTTP.PathType",[33,5]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,17],[[33,18],[30,5]],null]],[1,"\\n "]],[5]]]]],[1,"\\n "]],[4]]]]],[1,"\\n\\n"],[41,[33,19],[[[1," "],[8,[30,2,["Element"]],null,[["@name","@error"],["Path",[28,[37,20],[[33,5],"error.HTTP.Path"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Label"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,17],[[33,18],[33,16]],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Text"]],[[16,"oninput",[28,[37,4],[[30,0],"change","HTTP.Path",[33,5]],null]]],[["@value"],[[28,[37,20],[[33,5],"HTTP.Path"],null]]],null],[1,"\\n "],[8,[39,21],null,[["@state","@matches"],[[30,6,["state"]],"error"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Error"]],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,12],[[28,[37,20],[[33,5],"HTTP.Path"],null],"Regex"],null],[[[1," Path Regex should not be blank\\n"]],[]],[[[1," Path should begin with a \'/\'\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Methods"],[13],[1,"\\n "],[10,0],[14,0,"type-toggle"],[12],[1,"\\n "],[10,1],[12],[1,"All methods are applied by default unless specified"],[13],[1,"\\n "],[8,[30,2,["Element"]],null,[["@name"],["allMethods"]],[["default"],[[[[1,"\\n "],[8,[30,7,["Checkbox"]],[[16,"checked",[52,[33,22],"checked"]],[16,"onchange",[28,[37,4],[[30,0],"change","allMethods",[33,5]],null]]],null,null],[1,"\\n "],[8,[30,7,["Label"]],null,null,[["default"],[[[[1,"\\n All Methods\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "],[13],[1,"\\n\\n"],[41,[33,23],[[[1," "],[10,0],[14,0,"checkbox-group"],[14,"role","group"],[12],[1,"\\n"],[42,[28,[37,9],[[28,[37,9],[[33,24]],null]],null],null,[[[1," "],[10,"label"],[14,0,"type-checkbox"],[12],[1,"\\n "],[10,"input"],[14,3,"method"],[15,2,[30,8]],[15,"checked",[52,[28,[37,25],[[30,8],[33,5,["HTTP","Methods"]]],null],"checked"]],[15,"onchange",[28,[37,4],[[30,0],"change","method",[33,5]],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,1],[12],[1,[30,8]],[13],[1,"\\n "],[13],[1,"\\n"]],[8]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Headers"],[13],[1,"\\n\\n "],[8,[39,26],null,[["@items","@ondelete"],[[28,[37,20],[[33,5],"HTTP.Header"],null],[28,[37,4],[[30,0],"delete","HTTP.Header",[33,5]],null]]],[["default"],[[[[1,"\\n\\n "]],[9]]]]],[1,"\\n\\n "],[8,[39,27],null,[["@onsubmit"],[[28,[37,4],[[30,0],"add","HTTP.Header",[33,5]],null]]],[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@target","@name","@value"],[[30,0],"headerForm",[30,10]]],null],[1,"\\n "]],[10]]]]],[1,"\\n\\n "],[8,[39,29],null,null,[["default"],[[[[1,"\\n "],[8,[39,30],[[16,"disabled",[52,[28,[37,31],[[30,0,["headerForm","isDirty"]]],null],"disabled"]],[16,"onclick",[28,[37,4],[[30,0],[30,0,["headerForm","submit"]]],null]]],[["@text","@color"],[[29,["Add",[52,[28,[37,32],[[28,[37,17],[[28,[37,20],[[33,5],"HTTP.Header"],null],"length"],null],0],null]," another",""]," header"]],"primary"]],null],[1,"\\n "],[8,[39,30],[[16,"onclick",[28,[37,4],[[30,0],[30,0,["headerForm","reset"]]],null]]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "]],[2]]]]],[1,"\\n"],[13]],["&attrs","group","intent","el","Type","el","el","method","headerList","headerForm","&default"],false,["form-group","name","yield","hash","action","changeset","and","if","each","-track-array","intents","capitalize","eq","changeset-set","power-select","pathTypes","pathType","get","pathLabels","shouldShowPathField","changeset-get","state","allMethods","shouldShowMethods","methods","includes","consul/intention/permission/header/list","consul/intention/permission/header/form","ref","hds/button-set","hds/button","not","gt"]]',moduleName:"consul-ui/components/consul/intention/permission/form/index.hbs",isStrictMode:!1}),a="intention-permission" -var u=(0,t.setComponentTemplate)(o,t.default.extend({tagName:"",name:a,schema:(0,i.inject)("schema"),change:(0,i.inject)("change"),repo:(0,i.inject)(`repository/${a}`),onsubmit:function(){},onreset:function(){},intents:(0,r.alias)(`schema.${a}.Action.allowedValues`),methods:(0,r.alias)(`schema.${a}-http.Methods.allowedValues`),pathProps:(0,r.alias)(`schema.${a}-http.PathType.allowedValues`),pathTypes:(0,l.computed)("pathProps",(function(){return["NoPath"].concat(this.pathProps)})),pathLabels:(0,l.computed)((function(){return{NoPath:"No Path",PathExact:"Exact",PathPrefix:"Prefixed by",PathRegex:"Regular Expression"}})),pathInputLabels:(0,l.computed)((function(){return{PathExact:"Exact Path",PathPrefix:"Path Prefix",PathRegex:"Path Regular Expression"}})),changeset:(0,l.computed)("item",(function(){const e=this.change.changesetFor(a,this.item||this.repo.create()) -return e.isNew&&e.validate(),e})),pathType:(0,l.computed)("changeset._changes.HTTP.PathType","pathTypes.firstObject",(function(){return this.changeset.HTTP.PathType||this.pathTypes.firstObject})),noPathType:(0,r.equal)("pathType","NoPath"),shouldShowPathField:(0,r.not)("noPathType"),allMethods:!1,shouldShowMethods:(0,r.not)("allMethods"),didReceiveAttrs:function(){(0,l.get)(this,"item.HTTP.Methods.length")||(0,l.set)(this,"allMethods",!0)},actions:{change:function(e,t,n){const r=void 0!==(0,l.get)(n,"target.value")?n.target.value:n -switch(e){case"allMethods":(0,l.set)(this,e,n.target.checked) -break -case"method":n.target.checked?this.actions.add.apply(this,["HTTP.Methods",t,r]):this.actions.delete.apply(this,["HTTP.Methods",t,r]) -break -default:t.set(e,r)}t.validate()},add:function(e,t,n){t.pushObject(e,n),t.validate()},delete:function(e,t,n){t.removeObject(e,n),t.validate()},submit:function(e,t){void 0!==e.changes.find((e=>{let{key:t,value:n}=e -return"HTTP.PathType"===t||"HTTP.Path"===t}))&&(this.pathProps.forEach((t=>{e.set(`HTTP.${t}`,void 0)})),"NoPath"!==e.HTTP.PathType&&e.set(`HTTP.${e.HTTP.PathType}`,e.HTTP.Path)),this.allMethods&&e.set("HTTP.Methods",null),delete e._changes.HTTP.PathType,delete e._changes.HTTP.Path,this.repo.persist(e),this.onsubmit(e.data)},reset:function(e,t){e.rollback(),this.onreset(e.data)}}})) -e.default=u})),define("consul-ui/components/consul/intention/permission/header/form/index",["exports","@ember/component","@ember/template-factory","@ember/object","@ember/object/computed","@ember/service"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"M/AqDx5C",block:'[[[11,0],[17,1],[24,0,"consul-intention-permission-header-form"],[12],[1,"\\n "],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[18,7,[[28,[37,3],null,[["submit","reset","isDirty","changeset"],[[28,[37,4],[[30,0],"submit",[33,5]],null],[28,[37,4],[[30,0],"reset",[33,5]],null],[28,[37,6],[[33,5,["isValid"]],[33,5,["isDirty"]]],null],[33,5]]]]]],[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,0],[12],[1,"\\n "],[8,[30,2,["Element"]],null,[["@name","@type"],["HeaderType","select"]],[["default"],[[[[1,"\\n "],[8,[30,3,["Label"]],null,null,[["default"],[[[[1,"Header type"]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@options","@selected","@onChange"],[[99,8,["@options"]],[99,9,["@selected"]],[28,[37,4],[[30,0],"change","HeaderType",[33,5]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,10],[[33,11],[30,4]],null]],[1,"\\n "]],[4]]]]],[1,"\\n "]],[3]]]]],[1,"\\n\\n\\n "],[8,[30,2,["Element"]],null,[["@name","@error"],["Name",[28,[37,12],[[33,5],"error.Name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,5,["Label"]],null,null,[["default"],[[[[1,"Header name"]],[]]]]],[1,"\\n "],[8,[30,5,["Text"]],[[16,"oninput",[28,[37,4],[[30,0],"change","Name",[33,5]],null]]],[["@value"],[[28,[37,12],[[33,5],"Name"],null]]],null],[1,"\\n "],[8,[39,13],null,[["@state","@matches"],[[30,5,["state"]],"error"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Error"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,12],[[33,5],"error.Name.validation"],null]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n\\n"],[41,[33,15],[[[1," "],[8,[30,2,["Element"]],null,[["@name","@error"],["Value",[28,[37,12],[[33,5],"error.Value"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Label"]],null,null,[["default"],[[[[1,"Header "],[1,[28,[35,16],[[28,[37,10],[[33,11],[33,9]],null]],null]]],[]]]]],[1,"\\n "],[8,[30,6,["Text"]],[[16,"oninput",[28,[37,4],[[30,0],"change","Value",[33,5]],null]]],[["@value"],[[28,[37,12],[[33,5],"Value"],null]]],null],[1,"\\n "],[8,[39,13],null,[["@state","@matches"],[[30,6,["state"]],"error"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Error"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,12],[[33,5],"error.Value.validation"],null]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[2]]]]],[1,"\\n"],[13]],["&attrs","group","el","Type","el","el","&default"],false,["form-group","name","yield","hash","action","changeset","and","power-select","headerTypes","headerType","get","headerLabels","changeset-get","state","if","shouldShowValueField","lowercase"]]',moduleName:"consul-ui/components/consul/intention/permission/header/form/index.hbs",isStrictMode:!1}),a="intention-permission-http-header" -var u=(0,t.setComponentTemplate)(o,t.default.extend({tagName:"",name:a,schema:(0,i.inject)("schema"),change:(0,i.inject)("change"),repo:(0,i.inject)(`repository/${a}`),onsubmit:function(){},onreset:function(){},changeset:(0,l.computed)("item",(function(){return this.change.changesetFor(a,this.item||this.repo.create({HeaderType:this.headerTypes.firstObject}))})),headerTypes:(0,r.alias)(`schema.${a}.HeaderType.allowedValues`),headerLabels:(0,l.computed)((function(){return{Exact:"Exactly Matching",Prefix:"Prefixed by",Suffix:"Suffixed by",Regex:"Regular Expression",Present:"Is present"}})),headerType:(0,l.computed)("changeset.HeaderType","headerTypes.firstObject",(function(){return this.changeset.HeaderType||this.headerTypes.firstObject})),headerTypeEqualsPresent:(0,r.equal)("headerType","Present"),shouldShowValueField:(0,r.not)("headerTypeEqualsPresent"),actions:{change:function(e,t,n){const r=void 0!==(0,l.get)(n,"target.value")?n.target.value:n -t.set(e,r),t.validate()},submit:function(e){this.headerTypes.forEach((t=>{e.set(t,void 0)})) -const t="Present"===e.HeaderType||e.Value -e.set(e.HeaderType,t),delete e._changes.HeaderType,delete e._changes.Value,this.repo.persist(e),this.onsubmit(e.data),(0,l.set)(this,"item",this.repo.create({HeaderType:this.headerType}))},reset:function(e,t){e.rollback()}}})) -e.default=u})),define("consul-ui/components/consul/intention/permission/header/list/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"3ZH2LwLz",block:'[[[41,[28,[37,1],[[33,2,["length"]],0],null],[[[8,[39,3],[[24,0,"consul-intention-permission-header-list"]],[["@items","@scroll","@cellHeight"],[[99,2,["@items"]],"native",42]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,5],null,null,[["default"],[[[[1,"\\n Header\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,1,["Name"]]],[1," "],[1,[28,[35,6],[[30,1]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[30,2],null,null,[["default"],[[[[1,"\\n "],[8,[30,3],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,7],[[30,0],[33,8],[30,1]],null]]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,4],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this header?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,5],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],[]],null]],["item","Actions","Action","Confirmation","Confirm"],false,["if","gt","items","list-collection","block-slot","tooltip","route-match","action","ondelete"]]',moduleName:"consul-ui/components/consul/intention/permission/header/list/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) -e.default=r})),define("consul-ui/components/consul/intention/permission/list/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"nRmkYMml",block:'[[[41,[28,[37,1],[[33,2,["length"]],0],null],[[[8,[39,3],[[16,0,[29,["consul-intention-permission-list",[52,[28,[37,4],[[33,5]],null]," readonly"]]]]],[["@scroll","@items","@partial"],["native",[99,2,["@items"]],5]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[10,0],[15,"onclick",[28,[37,7],[[30,0],[28,[37,8],[[33,5]],null],[30,1]],null]],[12],[1,"\\n "],[10,"strong"],[15,0,[28,[37,9],["intent-",[30,1,["Action"]]],null]],[12],[1,[28,[35,10],[[30,1,["Action"]]],null]],[13],[1,"\\n"],[41,[28,[37,1],[[30,1,["HTTP","Methods","length"]],0],null],[[[1," "],[10,"dl"],[14,0,"permission-methods"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,11],null,null,[["default"],[[[[1,"\\n Methods\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[42,[28,[37,13],[[28,[37,13],[[30,1,["HTTP","Methods"]]],null]],null],null,[[[1," "],[1,[30,2]],[1,"\\n"]],[2]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["HTTP","Path"]],[[[1," "],[10,"dl"],[14,0,"permission-path"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,11],null,null,[["default"],[[[[1,"\\n "],[1,[30,1,["HTTP","PathType"]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,1,["HTTP","Path"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[42,[28,[37,13],[[28,[37,13],[[30,1,["HTTP","Header"]]],null]],null],null,[[[1," "],[10,"dl"],[14,0,"permission-header"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,11],null,null,[["default"],[[[[1,"\\n Header\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Name"]]],[1," "],[1,[28,[35,14],[[30,3]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[8,[39,6],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[30,4],null,null,[["default"],[[[[1,"\\n "],[8,[30,5],null,[["@onclick","@close"],[[28,[37,7],[[30,0],[28,[37,8],[[33,5]],null],[30,1]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Edit\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,5],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,7],[[30,0],[33,15],[30,1]],null]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,6],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this permission?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,7],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[]],null]],[1]]]]],[1,"\\n"]],[]],null]],["item","item","item","Actions","Action","Confirmation","Confirm"],false,["if","gt","items","list-collection","not","onclick","block-slot","action","optional","concat","capitalize","tooltip","each","-track-array","route-match","ondelete"]]',moduleName:"consul-ui/components/consul/intention/permission/list/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) -e.default=r})),define("consul-ui/components/consul/intention/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"YTLr6u9H",block:'[[[8,[39,0],[[24,0,"consul-intention-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.intention.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.intention.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n"],[41,[30,2,["searchproperty"]],[[[1," "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,10],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,11],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-access"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["access","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.intention.search-bar.access.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["allow","deny",""],null]],null]],null],null,[[[1," "],[8,[30,16],[[16,0,[28,[37,3],["value-",[30,17]],null]]],[["@value","@selected"],[[28,[37,12],[[30,17],"app-aware"],null],[28,[37,10],[[28,[37,12],[[30,17],"app-aware"],null],[30,2,["access","value"]]],null]]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,[28,[35,2],[[28,[37,3],["components.consul.intention.search-bar.access.options.",[28,[37,12],[[30,17],"app-aware"],null]],null]],null]],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,18,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,19,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,13],[[28,[37,4],[[28,[37,4],["Action:asc",[28,[37,2],["components.consul.intention.search-bar.sort.access.asc"],null]],null],[28,[37,4],["Action:desc",[28,[37,2],["components.consul.intention.search-bar.sort.access.desc"],null]],null],[28,[37,4],["SourceName:asc",[28,[37,2],["components.consul.intention.search-bar.sort.source-name.asc"],null]],null],[28,[37,4],["SourceName:desc",[28,[37,2],["components.consul.intention.search-bar.sort.source-name.desc"],null]],null],[28,[37,4],["DestinationName:asc",[28,[37,2],["components.consul.intention.search-bar.sort.destination-name.asc"],null]],null],[28,[37,4],["DestinationName:desc",[28,[37,2],["components.consul.intention.search-bar.sort.destination-name.desc"],null]],null],[28,[37,4],["Precedence:asc",[28,[37,2],["common.sort.numeric.asc"],null]],null],[28,[37,4],["Precedence:desc",[28,[37,2],["common.sort.numeric.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,14],[[30,21],[30,19,["value"]]],null]],[1,"\\n"]],[21]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,20,["Optgroup"]],[30,20,["Option"]]],[[[1," "],[8,[30,22],null,[["@label"],[[28,[37,2],["components.consul.intention.search-bar.sort.access.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Action:asc",[28,[37,15],["Action:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["components.consul.intention.search-bar.sort.access.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Action:desc",[28,[37,15],["Action:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["components.consul.intention.search-bar.sort.access.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,22],null,[["@label"],[[28,[37,2],["components.consul.intention.search-bar.sort.source-name.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["SourceName:asc",[28,[37,15],["SourceName:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["SourceName:desc",[28,[37,15],["SourceName:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,22],null,[["@label"],[[28,[37,2],["components.consul.intention.search-bar.sort.destination-name.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["DestinationName:asc",[28,[37,15],["DestinationName:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["DestinationName:desc",[28,[37,15],["DestinationName:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,22],null,[["@label"],[[28,[37,2],["components.consul.intention.search-bar.sort.precedence.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Precedence:asc",[28,[37,15],["Precedence:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.numeric.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Precedence:desc",[28,[37,15],["Precedence:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.numeric.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22,23]]],[1," "]],[]]]]],[1,"\\n "]],[20]]]]],[1,"\\n "]],[18]]]]]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","item","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","if","block-slot","each","-track-array","includes","lowercase","or","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/intention/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/intention/view/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"+zan8Nkf",block:'[[[11,0],[24,0,"consul-intention-view"],[17,1],[12],[1,"\\n\\n "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Destination"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,0],null,[["@item","@nspace","@partition","@service"],[[28,[37,1],null,[["Namespace","Partition","Service"],[[33,2,["DestinationNS"]],[33,2,["DestinationPartition"]],[33,2,["DestinationName"]]]]],"-","-",true]],null],[1,"\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,"Source"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,0],null,[["@item","@nspace","@partition","@service"],[[28,[37,1],null,[["Namespace","Partition","Service","PeerName"],[[33,2,["SourceNS"]],[33,2,["SourcePartition"]],[33,2,["SourceName"]],[33,2,["SourcePeer"]]]]],"-","-",true]],null],[1,"\\n "],[13],[1,"\\n"],[41,[33,2,["Action"]],[[[1," "],[10,"dt"],[12],[1,"Action"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[33,2,["Action"]]],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,4],[[33,2,["Description"]],"N/A"],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n"],[41,[28,[37,5],[[33,2,["Permissions","length"]],0],null],[[[1," "],[10,"h2"],[12],[1,"Permissions"],[13],[1,"\\n "],[8,[39,6],null,null,null],[1,"\\n "],[8,[39,7],null,[["@items"],[[33,2,["Permissions"]]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[13],[1,"\\n"]],["&attrs"],false,["consul/bucket/list","hash","item","if","or","gt","consul/intention/notice/permissions","consul/intention/permission/list"]]',moduleName:"consul-ui/components/consul/intention/view/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) -e.default=r})),define("consul-ui/components/consul/kind/index",["exports","@ember/component","@ember/template-factory","@ember/object","ember-cli-string-helpers/helpers/titleize","ember-cli-string-helpers/helpers/humanize"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"uD6fm7hf",block:'[[[41,[33,1,["Kind"]],[[[41,[33,2],[[[1," "],[10,"dl"],[14,0,"tooltip-panel"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[10,1],[14,0,"consul-kind"],[12],[1,"\\n "],[1,[34,3]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,4],null,[["@position"],["left"]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,6],[[33,1,["Kind"]],"ingress-gateway"],null],[[[1," Ingress gateways enable ingress traffic from services outside the Consul service mesh to services inside the Consul service mesh.\\n"]],[]],[[[41,[28,[37,6],[[33,1,["Kind"]],"terminating-gateway"],null],[[[1," Terminating gateways allow connect-enabled services in Consul service mesh to communicate with services outside the service mesh.\\n"]],[]],[[[41,[28,[37,6],[[33,1,["Kind"]],"api-gateway"],null],[[[1," API gateways enable ingress traffic from services outside the Consul service mesh to services inside the Consul service mesh.\\n"]],[]],[[[1," Mesh gateways enable routing of Connect traffic between different Consul datacenters.\\n "]],[]]]],[]]]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,"role","separator"],[12],[1,"\\n"],[41,[28,[37,6],[[33,1,["Kind"]],"ingress-gateway"],null],[[[1," About Ingress gateways\\n"]],[]],[[[41,[28,[37,6],[[33,1,["Kind"]],"terminating-gateway"],null],[[[1," About Terminating gateways\\n"]],[]],[[[41,[28,[37,6],[[33,1,["Kind"]],"api-gateway"],null],[[[1," About API gateways\\n"]],[]],[[[1," About Mesh gateways\\n "]],[]]]],[]]]],[]]],[1," "],[13],[1,"\\n"],[44,[[28,[37,8],[[28,[37,9],[[28,[37,9],["ingress-gateway","/consul/developer-mesh/ingress-gateways"],null],[28,[37,9],["terminating-gateway","/consul/developer-mesh/understand-terminating-gateways"],null],[28,[37,9],["mesh-gateway","/consul/developer-mesh/connect-gateways"],null]],null]],null]],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"learn-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,10],[[28,[37,11],["CONSUL_DOCS_LEARN_URL"],null],[28,[37,12],[[30,1],[33,1,["Kind"]]],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n Learn guides\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[1]]],[44,[[28,[37,8],[[28,[37,9],[[28,[37,9],["ingress-gateway","/connect/gateways/ingress-gateway"],null],[28,[37,9],["terminating-gateway","/connect/gateways/terminating-gateway"],null],[28,[37,9],["api-gateway","/connect/gateways/api-gateway"],null],[28,[37,9],["mesh-gateway","/connect/gateways/mesh-gateway"],null]],null]],null]],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,10],[[28,[37,11],["CONSUL_DOCS_URL"],null],[28,[37,12],[[30,2],[33,1,["Kind"]]],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n Documentation\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[14,"role","separator"],[12],[1,"\\n Other gateway types\\n "],[13],[1,"\\n"],[41,[28,[37,13],[[33,1,["Kind"]],"mesh-gateway"],null],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,10],[[28,[37,11],["CONSUL_DOCS_URL"],null],[28,[37,12],[[30,2],"mesh-gateway"],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n Mesh gateways\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,13],[[33,1,["Kind"]],"terminating-gateway"],null],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,10],[[28,[37,11],["CONSUL_DOCS_URL"],null],[28,[37,12],[[30,2],"terminating-gateway"],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n Terminating gateways\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,13],[[33,1,["Kind"]],"ingress-gateway"],null],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,10],[[28,[37,11],["CONSUL_DOCS_URL"],null],[28,[37,12],[[30,2],"ingress-gateway"],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n Ingress gateways\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,13],[[33,1,["Kind"]],"api-gateway"],null],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,10],[[28,[37,11],["CONSUL_DOCS_URL"],null],[28,[37,12],[[30,2],"api-gateway"],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n API gateways\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[2]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,1],[14,0,"consul-kind"],[12],[1,"\\n "],[1,[34,3]],[1,"\\n "],[13],[1,"\\n"]],[]]]],[]],null]],["link","link"],false,["if","item","withInfo","Name","menu-panel","block-slot","eq","let","from-entries","array","concat","env","get","not-eq"]]',moduleName:"consul-ui/components/consul/kind/index.hbs",isStrictMode:!1}),a={"api-gateway":"API Gateway","mesh-gateway":"Mesh Gateway","ingress-gateway":"Ingress Gateway","terminating-gateway":"Terminating Gateway"} -var u=(0,t.setComponentTemplate)(o,t.default.extend({tagName:"",Name:(0,l.computed)("item.Kind",(function(){const e=a[this.item.Kind] -return e||(0,r.titleize)((0,i.humanize)(this.item.Kind))}))})) -e.default=u})),define("consul-ui/components/consul/kv/form/index",["exports","@ember/component","@ember/template-factory","@ember/object","@ember/service"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i=(0,n.createTemplateFactory)({id:"Wsyfh84D",block:'[[[8,[39,0],null,[["@dc","@nspace","@partition","@type","@label","@autofill","@item","@src","@onchange","@onsubmit"],[[99,1,["@dc"]],[99,2,["@nspace"]],[99,3,["@partition"]],"kv","key",[99,4,["@autofill"]],[99,5,["@item"]],[99,6,["@src"]],[28,[37,7],[[30,0],"change"],null],[28,[37,7],[[30,0],[33,8]],null]]],[["default"],[[[[1,"\\n "],[8,[39,9],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,11],["write kv"],[["item"],[[30,1,["data"]]]]]],[[[1," "],[10,"form"],[15,"onsubmit",[28,[37,7],[[30,0],[30,1,["submit"]]],null]],[12],[1,"\\n "],[11,"fieldset"],[4,[38,12],[[28,[37,13],[[30,2],[30,1,["disabled"]]],null]],null],[12],[1,"\\n"],[41,[30,1,["isCreate"]],[[[1," "],[10,"label"],[15,0,[29,["type-text",[52,[30,1,["data","error","Key"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Key or folder"],[13],[1,"\\n "],[10,"input"],[14,"autofocus","autofocus"],[15,2,[28,[37,15],[[30,1,["data","Key"]],[33,16]],null]],[14,3,"additional"],[15,"oninput",[28,[37,7],[[30,0],[30,1,["change"]]],null]],[14,"placeholder","Key or folder"],[14,4,"text"],[12],[13],[1,"\\n "],[10,"em"],[12],[1,"To create a folder, end a key with "],[10,"code"],[12],[1,"/"],[13],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,13],[[28,[37,17],[[28,[37,15],[[30,1,["data","Key"]],[33,16]],null],""],null],[28,[37,18],[[28,[37,19],[[30,1,["data","Key"]]],null],"/"],null]],null],[[[1," "],[10,0],[12],[1,"\\n "],[10,0],[14,0,"type-toggle"],[12],[1,"\\n "],[10,"label"],[12],[1,"\\n "],[11,"input"],[24,3,"json"],[16,"checked",[52,[33,20],"checked"]],[16,"onchange",[28,[37,7],[[30,0],[30,1,["change"]]],null]],[24,4,"checkbox"],[4,[38,12],[false],null],[12],[13],[1,"\\n "],[10,1],[12],[1,"Code"],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[10,"label"],[14,"for",""],[15,0,[29,["type-text",[52,[30,1,["data","error","Value"]]," has-error"]]]],[12],[1,"\\n"],[41,[33,20],[[[1," "],[8,[39,21],null,[["@name","@readonly","@value","@onkeyup"],["value",[28,[37,13],[[30,2],[30,1,["disabled"]]],null],[28,[37,22],[[30,1,["data","Value"]]],null],[28,[37,7],[[30,0],[30,1,["change"]],"value"],null]]],[["label"],[[[[1,"Value"]],[]]]]],[1,"\\n"]],[]],[[[1," "],[10,1],[12],[1,"Value"],[13],[1,"\\n "],[11,"textarea"],[16,"autofocus",[28,[37,23],[[30,1,["isCreate"]]],null]],[24,3,"value"],[16,"oninput",[28,[37,7],[[30,0],[30,1,["change"]]],null]],[4,[38,12],[[28,[37,13],[[30,2],[30,1,["disabled"]]],null]],null],[12],[1,[28,[35,22],[[30,1,["data","Value"]]],null]],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[8,[39,24],null,null,[["default"],[[[[1,"\\n"],[41,[30,1,["isCreate"]],[[[41,[28,[37,23],[[30,2]],null],[[[1," "],[8,[39,25],[[16,"disabled",[28,[37,13],[[30,1,["data","isPristine"]],[30,1,["data","isInvalid"]],[30,1,["disabled"]]],null]],[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,25],[[16,"disabled",[30,1,["disabled"]]],[16,"onclick",[28,[37,7],[[30,0],[33,26],[30,1,["data"]]],null]],[24,4,"reset"]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"]],[]],[[[41,[28,[37,23],[[30,2]],null],[[[1," "],[8,[39,25],[[16,"disabled",[28,[37,13],[[30,1,["data","isInvalid"]],[30,1,["disabled"]]],null]],[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,25],[[16,"disabled",[30,1,["disabled"]]],[16,"onclick",[28,[37,7],[[30,0],[33,26],[30,1,["data"]]],null]],[24,4,"reset"]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"],[41,[28,[37,23],[[30,2]],null],[[[1," "],[8,[39,27],null,[["@message"],["Are you sure you want to delete this key?"]],[["default"],[[[[1,"\\n "],[8,[39,9],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,25],[[16,"disabled",[30,1,["disabled"]]],[4,[38,28],["click",[28,[37,7],[[30,0],[30,3],[30,1,["delete"]]],null]],null]],[["@text","@color"],["Delete","critical"]],null],[1,"\\n "]],[3]]]]],[1,"\\n "],[8,[39,9],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@message","@execute","@cancel"],[[30,6],[30,4],[30,5]]],null],[1,"\\n "]],[4,5,6]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null]],[]]],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[2]]],[1," "]],[]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["api","disabld","confirm","execute","cancel","message"],false,["data-form","dc","nspace","partition","autofill","item","src","action","onsubmit","block-slot","let","cannot","disabled","or","if","left-trim","parent","eq","not-eq","last","json","code-editor","atob","not","hds/button-set","hds/button","oncancel","confirmation-dialog","on","delete-confirmation"]]',moduleName:"consul-ui/components/consul/kv/form/index.hbs",isStrictMode:!1}) -var o=(0,t.setComponentTemplate)(i,t.default.extend({tagName:"",encoder:(0,r.inject)("btoa"),json:!0,ondelete:function(){this.onsubmit(...arguments)},oncancel:function(){this.onsubmit(...arguments)},onsubmit:function(){},actions:{change:function(e,t){const n=t.getData() -try{t.handleEvent(e)}catch(r){const t=e.target -let i -switch(t.name){case"value":(0,l.set)(n,"Value",this.encoder.execute(t.value)) -break -case"additional":i=(0,l.get)(this,"parent"),(0,l.set)(n,"Key",`${"/"!==i?i:""}${t.value}`) -break -case"json":(0,l.set)(this,"json",!this.json) -break -default:throw r}}}}})) -e.default=o})),define("consul-ui/components/consul/kv/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"OYo2s3qR",block:'[[[8,[39,0],[[24,0,"consul-kv-list"],[17,1]],[["@items"],[[30,2]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[12],[1,"Name"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["row"]],[["default"],[[[[1,"\\n "],[10,"td"],[15,0,[52,[30,3,["isFolder"]],"folder","file"]],[12],[1,"\\n "],[10,3],[15,6,[28,[37,3],[[52,[30,3,["isFolder"]],"dc.kv.folder","dc.kv.edit"],[30,3,["Key"]]],null]],[12],[1,[28,[35,4],[[28,[37,5],[[30,3,["Key"]],[30,5,["Key"]]],null],"/"],null]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@expanded","@onchange","@keyboardAccess"],[[52,[28,[37,7],[[30,8],[30,6]],null],true,false],[28,[37,8],[[30,0],[30,7],[30,6]],null],false]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n More\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n"],[41,[28,[37,9],["write kv"],[["item"],[[30,3]]]],[[[1," "],[10,"li"],[14,"role","none"],[12],[1,"\\n "],[10,3],[14,"role","menuitem"],[14,"tabindex","-1"],[15,6,[28,[37,3],[[52,[30,3,["isFolder"]],"dc.kv.folder","dc.kv.edit"],[30,3,["Key"]]],null]],[12],[1,[52,[30,3,["isFolder"]],"View","Edit"]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[14,"role","none"],[14,0,"dangerous"],[12],[1,"\\n "],[10,"label"],[15,"for",[30,9]],[14,"role","menuitem"],[14,"tabindex","-1"],[15,"onkeypress",[30,11]],[12],[1,"Delete"],[13],[1,"\\n "],[10,0],[14,"role","menu"],[12],[1,"\\n "],[8,[39,10],[[24,0,"warning"]],null,[["header","body","actions"],[[[[1,"\\n Confirm Delete\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this KV entry?\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,12,["Action"]],[[24,0,"dangerous"]],null,[["default"],[[[[1,"\\n "],[8,[39,8],[[24,0,"type-delete"],[24,"tabindex","-1"],[4,[38,11],["click",[28,[37,12],[[28,[37,8],[[30,0],[30,7]],null],[28,[37,8],[[30,0],[30,13],[30,3]],null]],null]],null]],null,[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,12,["Action"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@for"],[[30,9]]],[["default"],[[[[1,"\\n Cancel\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[12]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,"li"],[14,"role","none"],[12],[1,"\\n "],[10,3],[14,"role","menuitem"],[14,"tabindex","-1"],[15,6,[28,[37,3],[[52,[30,3,["isFolder"]],"dc.kv.folder","dc.kv.edit"],[30,3,["Key"]]],null]],[12],[1,"View"],[13],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[9,10,11]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6,7,8]]]]],[1,"\\n"]],[3,4]]]]]],["&attrs","@items","item","index","@parent","index","change","checked","confirm","send","keypressClick","Actions","@delete"],false,["tabular-collection","block-slot","if","href-to","right-trim","left-trim","popover-menu","eq","action","can","informed-action","on","queue"]]',moduleName:"consul-ui/components/consul/kv/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/kv/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"sF1xY1/s",block:'[[[8,[39,0],[[24,0,"consul-kv-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.kv.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.kv.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n"],[41,[30,2,["searchproperty"]],[[[1," "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,10],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,11],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-kind"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["kind","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.kv.search-bar.kind.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["folder","key"],null]],null]],null],null,[[[1," "],[8,[30,16],[[24,0,"value-{item}}"]],[["@value","@selected"],[[30,17],[28,[37,10],[[30,17],[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.kv.search-bar.kind.options.",[30,17]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,18,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,19,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,12],[[28,[37,4],[[28,[37,4],["Key:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Key:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["Kind:asc",[28,[37,2],["components.consul.kv.search-bar.sort.kind.asc"],null]],null],[28,[37,4],["Kind:desc",[28,[37,2],["components.consul.kv.search-bar.sort.kind.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,13],[[30,21],[30,19,["value"]]],null]],[1,"\\n"]],[21]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,20,["Optgroup"]],[30,20,["Option"]]],[[[1," "],[8,[30,22],null,[["@label"],[[28,[37,2],["common.consul.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Key:asc",[28,[37,14],["Key:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Key:desc",[28,[37,14],["Key:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,22],null,[["@label"],[[28,[37,2],["components.consul.kv.search-bar.kind.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Kind:asc",[28,[37,14],["Kind:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["components.consul.kv.search-bar.sort.kind.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Kind:desc",[28,[37,14],["Kind:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["components.consul.kv.search-bar.sort.kind.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22,23]]],[1," "]],[]]]]],[1,"\\n "]],[20]]]]],[1,"\\n "]],[18]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","item","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","if","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/kv/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/loader/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"FSVimMul",block:'[[[11,0],[24,0,"consul-loader"],[17,1],[12],[1,"\\n "],[10,"svg"],[14,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[14,"xmlns:xlink","http://www.w3.org/1999/xlink","http://www.w3.org/2000/xmlns/"],[14,"width","44px"],[14,"height","44px"],[14,"viewBox","0 0 44 44"],[14,"version","1.1"],[12],[1,"\\n "],[10,"g"],[12],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","27"],[14,"cy","2"],[14,5,"transform-origin: 27px 2px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","17"],[14,"cy","2"],[14,5,"transform-origin: 17px 2px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","27"],[14,"cy","42"],[14,5,"transform-origin: 27px 42px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","17"],[14,"cy","42"],[14,5,"transform-origin: 17px 42px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","2"],[14,"cy","17"],[14,5,"transform-origin: 2px 17px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","2"],[14,"cy","27"],[14,5,"transform-origin: 2px 27px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","42"],[14,"cy","17"],[14,5,"transform-origin: 42px 17px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","42"],[14,"cy","27"],[14,5,"transform-origin: 42px 27px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","33"],[14,"cy","4"],[14,5,"transform-origin: 33px 4px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","11"],[14,"cy","4"],[14,5,"transform-origin: 11px 4px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","33"],[14,"cy","40"],[14,5,"transform-origin: 33px 40px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","11"],[14,"cy","40"],[14,5,"transform-origin: 11px 40px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","40"],[14,"cy","11"],[14,5,"transform-origin: 40px 11px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","4"],[14,"cy","33"],[14,5,"transform-origin: 4px 33px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","40"],[14,"cy","33"],[14,5,"transform-origin: 40px 33px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","4"],[14,"cy","11"],[14,5,"transform-origin: 4px 11px"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[12],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","22"],[14,"cy","4"],[14,5,"transform-origin: 22px 4px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","22"],[14,"cy","40"],[14,5,"transform-origin: 22px 40px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","4"],[14,"cy","22"],[14,5,"transform-origin: 4px 22px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","40"],[14,"cy","22"],[14,5,"transform-origin: 40px 22px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","9"],[14,"cy","9"],[14,5,"transform-origin: 9px 9px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","35"],[14,"cy","35"],[14,5,"transform-origin: 35px 35px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","35"],[14,"cy","9"],[14,5,"transform-origin: 35px 9px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","9"],[14,"cy","35"],[14,5,"transform-origin: 9px 35px"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[12],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","28"],[14,"cy","8"],[14,5,"transform-origin: 28px 8px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","16"],[14,"cy","8"],[14,5,"transform-origin: 16px 8px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","28"],[14,"cy","36"],[14,5,"transform-origin: 28px 36px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","16"],[14,"cy","36"],[14,5,"transform-origin: 16px 36px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","8"],[14,"cy","28"],[14,5,"transform-origin: 8px 28px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","8"],[14,"cy","16"],[14,5,"transform-origin: 8px 16px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","36"],[14,"cy","28"],[14,5,"transform-origin: 36px 28px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","36"],[14,"cy","16"],[14,5,"transform-origin: 36px 16px"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[12],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","22"],[14,"cy","12"],[14,5,"transform-origin: 22px 12px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","22"],[14,"cy","32"],[14,5,"transform-origin: 22px 32px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","12"],[14,"cy","22"],[14,5,"transform-origin: 12px 22px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","32"],[14,"cy","22"],[14,5,"transform-origin: 32px 22px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","15"],[14,"cy","15"],[14,5,"transform-origin: 15px 15px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","29"],[14,"cy","29"],[14,5,"transform-origin: 29px 29px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","29"],[14,"cy","15"],[14,5,"transform-origin: 29px 15px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","15"],[14,"cy","29"],[14,5,"transform-origin: 15px 29px"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[12],[1,"\\n "],[10,"circle"],[14,"r","9"],[14,"cx","22"],[14,"cy","22"],[14,5,"transform-origin: 22px 22px"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs"],false,[]]',moduleName:"consul-ui/components/consul/loader/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/lock-session/form/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"Hv2qW8N0",block:'[[[11,0],[24,0,"consul-lock-session-form"],[17,1],[12],[1,"\\n "],[8,[39,0],null,[["@sink","@type","@label","@ondelete","@onchange"],[[28,[37,1],["/${partition}/${nspace}/${dc}/session",[28,[37,2],null,[["partition","nspace","dc"],[[30,2,["Partition"]],[30,2,["Namespace"]],[30,2,["Datacenter"]]]]]],null],"session","Lock Session",[28,[37,3],[[52,[30,3],[30,3],[30,4]],[30,2]],null],[28,[37,3],[[28,[37,5],[[30,4]],null],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,7],[[4,[38,8],null,[["after"],[[28,[37,9],[[30,0],[30,6]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[6]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],[[4,[38,8],null,[["after"],[[28,[37,9],[[30,0],[30,7]],null]]]]],[["@type","@error"],["remove",[30,8]]],null],[1,"\\n "]],[7,8]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n"],[41,[30,2,["Name"]],[[[1," "],[10,"dt"],[12],[1,"Name"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,2,["Name"]]],[13],[1,"\\n"]],[]],null],[1," "],[10,"dt"],[12],[1,"ID"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,2,["ID"]]],[13],[1,"\\n "],[10,"dt"],[12],[1,"Node"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,10],null,[["@text","@icon","@href","@isHrefExternal","@size","@color"],[[30,2,["Node"]],"git-commit",[28,[37,11],["dc.nodes.show",[30,2,["Node"]]],null],false,"small","tertiary"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,"Delay"],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,12],[[30,2,["LockDelay"]]],null]],[13],[1,"\\n "],[10,"dt"],[12],[1,"TTL"],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,13],[[30,2,["TTL"]],"-"],null]],[13],[1,"\\n "],[10,"dt"],[12],[1,"Behavior"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,2,["Behavior"]]],[13],[1,"\\n"],[44,[[30,2,["checks"]]],[[[1," "],[10,"dt"],[12],[1,"Health Checks"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[41,[28,[37,15],[[30,9,["length"]],0],null],[[[1," "],[1,[28,[35,16],[", ",[30,9]],null]],[1,"\\n"]],[]],[[[1," -\\n"]],[]]],[1," "],[13],[1,"\\n"]],[9]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,17],["delete session"],[["item"],[[30,2]]]],[[[1," "],[8,[39,18],null,[["@message"],["Are you sure you want to invalidate this Lock Session?"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,10],[[4,[38,19],["click",[28,[37,3],[[30,10],[28,[37,3],[[30,5,["delete"]],[30,2]],null]],null]],null]],[["@text","@color"],["Invalidate Session","critical"]],null],[1,"\\n "]],[10]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[30,13]],[1,"\\n "],[13],[1,"\\n "],[8,[39,20],null,null,[["default"],[[[[1,"\\n "],[8,[39,10],[[4,[38,19],["click",[28,[37,3],[[30,11]],null]],null]],[["@text","@color"],["Confirm Invalidation","critical"]],null],[1,"\\n "],[8,[39,10],[[4,[38,19],["click",[28,[37,3],[[30,12]],null]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[11,12,13]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"],[13]],["&attrs","@item","@ondelete","@onsubmit","writer","after","after","error","checks","confirm","execute","cancel","message"],false,["data-writer","uri","hash","fn","if","optional","block-slot","consul/lock-session/notifications","notification","action","hds/button","href-to","duration-from","or","let","gt","join","can","confirmation-dialog","on","hds/button-set"]]',moduleName:"consul-ui/components/consul/lock-session/form/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/lock-session/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"f75K08ts",block:'[[[8,[39,0],[[24,0,"consul-lock-session-list"],[17,1]],[["@items"],[[30,2]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[30,3,["Name"]],[[[1," "],[10,1],[12],[1,[30,3,["Name"]]],[13],[1,"\\n"]],[]],[[[1," "],[10,1],[12],[1,"\\n "],[1,[30,3,["ID"]]],[1,"\\n "],[8,[39,3],null,[["@value","@name"],[[30,3,["ID"]],"ID"]],null],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n"],[41,[30,3,["Name"]],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n ID\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,3],null,[["@value","@name"],[[30,3,["ID"]],"ID"]],null],[1,"\\n "],[1,[30,3,["ID"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[10,"dl"],[14,0,"lock-delay"],[12],[1,"\\n "],[11,"dt"],[4,[38,4],null,null],[12],[1,"\\n Delay\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,5],[[30,3,["LockDelay"]]],null]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[14,0,"ttl"],[12],[1,"\\n "],[11,"dt"],[4,[38,4],null,null],[12],[1,"\\n TTL\\n "],[13],[1,"\\n"],[41,[28,[37,6],[[30,3,["TTL"]],""],null],[[[1," "],[10,"dd"],[12],[1,"-"],[13],[1,"\\n"]],[]],[[[1," "],[10,"dd"],[12],[1,[30,3,["TTL"]]],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[10,"dl"],[14,0,"behavior"],[12],[1,"\\n "],[11,"dt"],[4,[38,4],null,null],[12],[1,"\\n Behavior\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,3,["Behavior"]]],[13],[1,"\\n "],[13],[1,"\\n"],[44,[[28,[37,8],[[30,3,["NodeChecks"]],[30,3,["ServiceChecks"]]],null]],[[[1," "],[10,"dl"],[14,0,"checks"],[12],[1,"\\n "],[11,"dt"],[4,[38,4],null,null],[12],[1,"\\n Checks\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[41,[28,[37,9],[[30,5,["length"]],0],null],[[[42,[28,[37,11],[[28,[37,11],[[30,5]],null]],null],null,[[[1," "],[10,1],[12],[1,[30,6]],[13],[1,"\\n"]],[6]],null]],[]],[[[1," -\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[5]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@message"],["Are you sure you want to invalidate this session?"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,13],[[4,[38,14],["click",[28,[37,15],[[30,7],[28,[37,15],[[30,8],[30,3]],null]],null]],null]],[["@text","@color"],["Invalidate","critical"]],null],[1,"\\n "]],[7]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[30,11]],[1,"\\n "],[13],[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n "],[8,[39,13],[[4,[38,14],["click",[28,[37,15],[[30,9]],null]],null]],[["@text","@color"],["Confirm Invalidate","critical"]],null],[1,"\\n "],[8,[39,13],[[4,[38,14],["click",[28,[37,15],[[30,10]],null]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[9,10,11]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4]]]]]],["&attrs","@items","item","index","checks","item","confirm","@ondelete","execute","cancel","message"],false,["list-collection","block-slot","if","copy-button","tooltip","duration-from","eq","let","union","gt","each","-track-array","confirmation-dialog","hds/button","on","fn","hds/button-set"]]',moduleName:"consul-ui/components/consul/lock-session/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/lock-session/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"8UZIF1qV",block:'[[[41,[28,[37,1],[[30,1],"remove"],null],[[[41,[30,2],[[[1," "],[8,[39,2],[[17,3]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,4,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,4,["Description"]],null,null,[["default"],[[[[1,"\\n There was an error invalidating the Lock Session.\\n"],[41,[28,[37,3],[[30,2,["status"]],[30,2,["detail"]]],null],[[[1," "],[10,"br"],[12],[13],[1,[30,2,["status"]]],[1,": "],[1,[30,2,["detail"]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,2],[[17,3]],[["@color"],["success"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Success!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"\\n Your Lock Session has been invalidated.\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"kv"],null],[[[1," "],[8,[39,4],[[24,0,"mb-3"]],[["@type","@color"],["inline","warning"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Warning"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"This KV has a lock session. You can edit KV\'s with lock sessions, but we recommend doing so with care, or not doing so at all. It may negatively impact the active node it\'s associated with. See below for more details on the Lock Session."]],[]]]]],[1,"\\n "],[8,[30,6,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition"],["Learn more",[29,[[28,[37,5],["CONSUL_DOCS_URL"],null],"/internals/sessions.html"]],"docs-link","trailing"]],null],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],null]],[]]]],["@type","@error","&attrs","T","T","A"],false,["if","eq","hds/toast","and","hds/alert","env"]]',moduleName:"consul-ui/components/consul/lock-session/notifications/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/metadata/list/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"qvPSBKvv",block:'[[[8,[39,0],[[24,0,"consul-metadata-list"]],[["@items"],[[99,1,["@items"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[12],[1,"Key"],[13],[1,"\\n "],[10,"th"],[12],[1,"Value"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,2],null,[["@name"],["row"]],[["default"],[[[[1,"\\n "],[10,"td"],[12],[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,3],[0,[30,1]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[12],[1,"\\n "],[10,1],[12],[1,[28,[35,3],[1,[30,1]],null]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[1,2]]]]],[1,"\\n"]],["item","index"],false,["tabular-collection","items","block-slot","object-at"]]',moduleName:"consul-ui/components/consul/metadata/list/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) -e.default=r})),define("consul-ui/components/consul/node-identity/template/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"YflZV/pQ",block:'[[[41,[28,[37,1],["use partitions"],null],[[[1,"partition \\""],[1,[28,[35,2],[[30,1],"default"],null]],[1,"\\" {\\n"],[41,[28,[37,1],["use nspaces"],null],[[[1," namespace \\"default\\" {\\n node \\""],[1,[30,2]],[1,"\\" {\\n\\t policy = \\"write\\"\\n }\\n }\\n namespace_prefix \\"\\" {\\n service_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n }\\n"]],[]],[[[1," node \\""],[1,[30,2]],[1,"\\" {\\n\\t policy = \\"write\\"\\n }\\n service_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n"]],[]]],[1,"}"]],[]],[[[41,[28,[37,1],["use nspaces"],null],[[[1,"namespace \\"default\\" {\\n node \\""],[1,[30,2]],[1,"\\" {\\n\\t policy = \\"write\\"\\n }\\n}\\nnamespace_prefix \\"\\" {\\n service_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n}\\n"]],[]],[[[1,"node \\""],[1,[30,2]],[1,"\\" {\\n\\tpolicy = \\"write\\"\\n}\\nservice_prefix \\"\\" {\\n\\tpolicy = \\"read\\"\\n}"]],[]]]],[]]]],["@partition","@name"],false,["if","can","or"]]',moduleName:"consul-ui/components/consul/node-identity/template/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/node/agentless-notice/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","consul-ui/services/local-storage"],(function(e,t,n,l,r,i){var o,a,u -function s(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const c=(0,n.createTemplateFactory)({id:"639y+0v2",block:'[[[41,[33,1],[[[1," "],[8,[39,2],[[24,0,"mb-3 mt-2 agentless-node-notice"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,1,["Title"]],null,null,[["default"],[[[[1,"\\n "],[10,1],[12],[1,[28,[35,3],["routes.dc.nodes.index.agentless.notice.header"],null]],[13],[1,"\\n "],[8,[39,4],[[4,[38,5],["click",[30,0,["dismissAgentlessNotice"]]],null]],[["@color","@text","@icon","@size","@isIconOnly"],["secondary","Dismiss notice","x","small",true]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,1,["Description"]],null,null,[["default"],[[[[1,[28,[35,3],["routes.dc.nodes.index.agentless.notice.body"],null]]],[]]]]],[1,"\\n "],[8,[30,1,["Link::Standalone"]],null,[["@href","@text","@icon","@iconPosition"],[[29,[[28,[37,6],["CONSUL_DOCS_DEVELOPER_URL"],null],"/connect/dataplane"]],[28,[37,3],["routes.dc.nodes.index.agentless.notice.footer"],null],"docs-link","trailing"]],null],[1,"\\n "]],[1]]]]],[1,"\\n"]],[]],null]],["A"],false,["if","isVisible","hds/alert","t","hds/button","on","env"]]',moduleName:"consul-ui/components/consul/node/agentless-notice/index.hbs",isStrictMode:!1}) -let d=(o=(0,i.storageFor)("notices"),a=class extends l.default{constructor(){var e,t,n,l,r,i,o -super(...arguments),n="nodes-agentless-dismissed",(t="storageKey")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,l=this,r="notices",o=this,(i=u)&&Object.defineProperty(l,r,{enumerable:i.enumerable,configurable:i.configurable,writable:i.writable,value:i.initializer?i.initializer.call(o):void 0}),this.args.postfix&&(this.storageKey=`nodes-agentless-dismissed-${this.args.postfix}`)}get isVisible(){const{items:e,filteredItems:t}=this.args -return!this.notices.state.includes(this.storageKey)&&e.length>t.length}dismissAgentlessNotice(){this.notices.add(this.storageKey)}},u=s(a.prototype,"notices",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s(a.prototype,"dismissAgentlessNotice",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"dismissAgentlessNotice"),a.prototype),a) -e.default=d,(0,t.setComponentTemplate)(c,d)})),define("consul-ui/components/consul/node/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"UZddA6ka",block:'[[[8,[39,0],[[24,0,"consul-node-list"]],[["@items"],[[30,1]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"dl"],[15,0,[30,2,["Status"]]],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Health\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,2],null,[["@position"],["top-start"]],[["default"],[[[[1,"\\n"],[41,[28,[37,4],["critical",[30,2,["Status"]]],null],[[[1," At least one health check on this node is failing.\\n"]],[]],[[[41,[28,[37,4],["warning",[30,2,["Status"]]],null],[[[1," At least one health check on this node has a warning.\\n"]],[]],[[[41,[28,[37,4],["passing",[30,2,["Status"]]],null],[[[1," All health checks are passing.\\n"]],[]],[[[1," There are no health checks.\\n "]],[]]]],[]]]],[]]],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,3],[15,6,[28,[37,5],["dc.nodes.show",[30,2,["Node"]]],[["params"],[[28,[37,6],null,[["peer"],[[30,2,["PeerName"]]]]]]]]],[12],[1,"\\n "],[1,[30,2,["Node"]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@item"],[[30,2]]],null],[1,"\\n"],[41,[28,[37,4],[[30,2,["Address"]],[30,4,["Address"]]],null],[[[1," "],[10,1],[14,0,"leader"],[12],[1,"Leader"],[13],[1,"\\n"]],[]],null],[1," "],[10,1],[12],[1,"\\n "],[1,[28,[35,8],[[30,2,["MeshServiceInstances","length"]]],null]],[1," "],[1,[28,[35,9],[[30,2,["MeshServiceInstances","length"]],"Service"],[["without-count"],[true]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[10,1],[12],[1,"Address"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,10],null,[["@value","@name"],[[30,2,["Address"]],"Address"]],null],[1,"\\n "],[1,[30,2,["Address"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[2,3]]]]],[1,"\\n"]],["@items","item","index","@leader"],false,["list-collection","block-slot","tooltip","if","eq","href-to","hash","consul/node/peer-info","format-number","pluralize","copy-button"]]',moduleName:"consul-ui/components/consul/node/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/node/peer-info/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"7f6XDyqE",block:'[[[41,[30,1,["PeerName"]],[[[1," "],[10,1],[14,0,"consul-node-peer-info"],[12],[1,"\\n "],[11,"svg"],[24,"width","16"],[24,"height","16"],[24,"viewBox","0 0 16 16"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[4,[38,1],["Peer"],null],[12],[1,"\\n "],[10,"path"],[14,"d","M16 8C16 7.80109 15.921 7.61032 15.7803 7.46967L12.2803 3.96967C11.9874 3.67678 11.5126 3.67678 11.2197 3.96967C10.9268 4.26256 10.9268 4.73744 11.2197 5.03033L14.1893 8L11.2197 10.9697C10.9268 11.2626 10.9268 11.7374 11.2197 12.0303C11.5126 12.3232 11.9874 12.3232 12.2803 12.0303L15.7803 8.53033C15.921 8.38968 16 8.19891 16 8Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M0.21967 8.53033C-0.0732233 8.23744 -0.0732233 7.76256 0.21967 7.46967L3.71967 3.96967C4.01256 3.67678 4.48744 3.67678 4.78033 3.96967C5.07322 4.26256 5.07322 4.73744 4.78033 5.03033L1.81066 8L4.78033 10.9697C5.07322 11.2626 5.07322 11.7374 4.78033 12.0303C4.48744 12.3232 4.01256 12.3232 3.71967 12.0303L0.21967 8.53033Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M5 7C4.44772 7 4 7.44772 4 8C4 8.55229 4.44772 9 5 9H5.01C5.56228 9 6.01 8.55229 6.01 8C6.01 7.44772 5.56228 7 5.01 7H5Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M7 8C7 7.44772 7.44772 7 8 7H8.01C8.56228 7 9.01 7.44772 9.01 8C9.01 8.55229 8.56228 9 8.01 9H8C7.44772 9 7 8.55229 7 8Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M11 7C10.4477 7 10 7.44772 10 8C10 8.55229 10.4477 9 11 9H11.01C11.5623 9 12.01 8.55229 12.01 8C12.01 7.44772 11.5623 7 11.01 7H11Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,1],[14,0,"consul-node-peer-info__name"],[12],[1,[30,1,["PeerName"]]],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],["@item"],false,["if","tooltip"]]',moduleName:"consul-ui/components/consul/node/peer-info/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/node/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"u8IgeZRe",block:'[[[8,[39,0],[[24,0,"consul-node-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.node.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.node.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-status"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["status","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.consul.status"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[28,[37,4],["passing","warning","critical"],null]],null]],null],null,[[[1," "],[8,[30,16],[[16,0,[29,["value-",[30,17]]]]],[["@value","@selected"],[[30,17],[28,[37,9],[[30,17],[30,2,["status","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[30,17]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,17]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,18,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,19,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["Node:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Node:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["Status:asc",[28,[37,2],["common.sort.status.asc"],null]],null],[28,[37,4],["Status:desc",[28,[37,2],["common.sort.status.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,21],[30,19,["value"]]],null]],[1,"\\n"]],[21]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,20,["Optgroup"]],[30,20,["Option"]]],[[[1," "],[8,[30,22],null,[["@label"],[[28,[37,2],["common.consul.status"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Status:asc",[28,[37,13],["Status:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Status:desc",[28,[37,13],["Status:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,22],null,[["@label"],[[28,[37,2],["common.consul.node-name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Node:asc",[28,[37,13],["Node:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Node:desc",[28,[37,13],["Node:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22,23]]],[1," "]],[]]]]],[1,"\\n "]],[20]]]]],[1,"\\n "]],[18]]]]]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","state","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/node/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})) -define("consul-ui/components/consul/nspace/form/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object"],(function(e,t,n,l,r){var i -function o(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const a=(0,n.createTemplateFactory)({id:"rgTjBVSE",block:'[[[11,0],[24,0,"consul-nspace-form"],[17,1],[12],[1,"\\n "],[8,[39,0],null,[["@sink","@type","@label","@ondelete","@onchange"],[[28,[37,1],["/${partition}/${nspace}/${dc}/nspace",[28,[37,2],null,[["partition","nspace","dc"],["","",[30,2,["Datacenter"]]]]]],null],"nspace","Namespace",[28,[37,3],[[30,0,["onDelete"]],[30,2]],null],[28,[37,3],[[30,0,["onSubmit"]],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,5],[[4,[38,6],null,[["after"],[[28,[37,7],[[30,0],[30,4]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[4]]]]],[1,"\\n\\n "],[8,[39,4],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,9],[[28,[37,10],["write nspaces"],null]],null],[30,2],[28,[37,2],null,[["help","Name"],["Must be a valid DNS hostname. Must contain 1-64 characters (numbers, letters, and hyphens), and must begin with a letter. Once created, this cannot be changed.",[28,[37,11],[[28,[37,2],null,[["test","error"],["^[a-zA-Z0-9]([a-zA-Z0-9-]{0,62}[a-zA-Z0-9])?$","Name must be a valid DNS hostname."]]]],null]]]],[28,[37,2],null,[["Description"],[[28,[37,11],null,null]]]]],[[[1," "],[11,"form"],[4,[38,12],["submit",[28,[37,3],[[30,3,["persist"]],[30,6]],null]],null],[4,[38,13],[[30,5]],null],[12],[1,"\\n\\n "],[8,[39,14],null,[["@src"],[[28,[37,14],["validate"],null]]],[["default"],[[[[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n"],[41,[28,[37,16],["new nspace"],[["item"],[[30,6]]]],[[[1," "],[8,[39,17],null,[["@name","@placeholder","@item","@validations","@chart"],["Name","Name",[30,6],[30,7],[28,[37,2],null,[["state","dispatch"],[[30,13],[30,12]]]]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,17],null,[["@expanded","@name","@label","@item","@validations","@chart"],[true,"Description","Description (Optional)",[30,6],[30,8],[28,[37,2],null,[["state","dispatch"],[[30,13],[30,12]]]]]],null],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,10],["use acls"],null],[[[1," "],[10,"fieldset"],[14,1,"roles"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Roles"],[13],[1,"\\n "],[10,2],[12],[1,"\\n"],[41,[28,[37,10],["write nspace"],[["item"],[[30,6]]]],[[[1," By adding roles to this namespaces, you will apply them to\\n all tokens created within this namespace.\\n"]],[]],[[[1," The following roles are applied to all tokens created within\\n this namespace.\\n"]],[]]],[1," "],[13],[1,"\\n "],[8,[39,18],null,[["@dc","@nspace","@partition","@disabled","@items"],[[30,14],"default",[30,15],[30,5],[30,6,["ACLs","RoleDefaults"]]]],null],[1,"\\n "],[13],[1,"\\n "],[10,"fieldset"],[14,1,"policies"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Policies"],[13],[1,"\\n "],[10,2],[12],[1,"\\n"],[41,[28,[37,9],[[30,5]],null],[[[1," By adding policies to this namespace, you will apply them to\\n all tokens created within this namespace.\\n"]],[]],[[[1," The following policies are applied to all tokens created\\n within this namespace.\\n"]],[]]],[1," "],[13],[1,"\\n "],[8,[39,19],null,[["@dc","@nspace","@partition","@disabled","@allowIdentity","@items"],[[30,14],"default",[30,15],[30,5],false,[30,6,["ACLs","PolicyDefaults"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[10,0],[12],[1,"\\n "],[8,[39,20],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,21],[[28,[37,16],["new nspace"],[["item"],[[30,6]]]],[28,[37,10],["create nspaces"],null]],null],[[[1," "],[8,[39,22],[[16,"disabled",[28,[37,23],[[28,[37,16],["pristine nspace"],[["item"],[[30,6]]]],[28,[37,24],[[30,13],"error"],null]],null]],[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n"]],[]],[[[41,[28,[37,10],["write nspace"],[["item"],[[30,6]]]],[[[1," "],[8,[39,22],[[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n "]],[]],null]],[]]],[1,"\\n "],[8,[39,22],[[24,4,"reset"],[4,[38,12],["click",[28,[37,3],[[30,0,["onCancel"]],[30,6]],null]],null]],[["@color","@text"],["secondary","Cancel"]],null],[1,"\\n\\n"],[41,[28,[37,21],[[28,[37,9],[[28,[37,16],["new nspace"],[["item"],[[30,6]]]]],null],[28,[37,10],["delete nspace"],[["item"],[[30,6]]]]],null],[[[1," "],[8,[39,25],null,[["@message"],["Are you sure you want to delete this Namespace?"]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,22],[[4,[38,12],["click",[28,[37,3],[[30,16],[28,[37,3],[[30,3,["delete"]],[30,6]],null]],null]],null]],[["@color","@text"],["critical","Delete"]],null],[1,"\\n "]],[16]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@message","@execute","@cancel"],[[30,19],[30,17],[30,18]]],null],[1,"\\n "]],[17,18,19]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n "]],[9,10,11,12,13]]]]],[1,"\\n "],[13],[1,"\\n"]],[5,6,7,8]]],[1," "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n"],[13]],["&attrs","@item","writer","after","readOnly","item","Name","Description","State","Guard","ChartAction","dispatch","state","@dc","@partition","confirm","execute","cancel","message"],false,["data-writer","uri","hash","fn","block-slot","consul/nspace/notifications","notification","action","let","not","can","array","on","disabled","state-chart","if","is","text-input","role-selector","policy-selector","hds/button-set","and","hds/button","or","state-matches","confirmation-dialog","delete-confirmation"]]',moduleName:"consul-ui/components/consul/nspace/form/index.hbs",isStrictMode:!1}) -let u=(o((i=class extends l.default{onSubmit(e){const t=this.args.onsubmit -if(t)return t(e)}onDelete(e){const{onsubmit:t,ondelete:n}=this.args -return n?n(e):t?t(e):void 0}onCancel(e){const{oncancel:t,onsubmit:n}=this.args -return t?t(e):n?n(e):void 0}}).prototype,"onSubmit",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"onSubmit"),i.prototype),o(i.prototype,"onDelete",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"onDelete"),i.prototype),o(i.prototype,"onCancel",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"onCancel"),i.prototype),i) -e.default=u,(0,t.setComponentTemplate)(a,u)})),define("consul-ui/components/consul/nspace/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"HHDNRExj",block:'[[[8,[39,0],[[24,0,"consul-nspace-list"],[17,1]],[["@items","@linkable"],[[30,2],"linkable nspace"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[30,3,["DeletedAt"]],[[[1," "],[10,2],[12],[1,"\\n Deleting "],[1,[30,3,["Name"]]],[1,"...\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,6,[28,[37,3],["dc.nspaces.edit",[30,3,["Name"]]],null]],[12],[1,[30,3,["Name"]]],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n"],[41,[30,3,["Description"]],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Description"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,4],["CONSUL_ACLS_ENABLED"],null],[[[1," "],[8,[39,5],null,[["@item"],[[30,3]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,6],[[30,3,["DeletedAt"]]],null],[[[1," "],[8,[30,4],null,null,[["default"],[[[[1,"\\n "],[8,[30,5],null,[["@href"],[[28,[37,3],["dc.nspaces.edit",[30,3,["Name"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],["write nspace"],[["item"],[[30,3]]]],[[[1," Edit\\n"]],[]],[[[1," View\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,7],["delete nspace"],[["item"],[[30,3]]]],[[[1," "],[8,[30,5],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,8],[[30,0],[30,6],[30,3]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,7],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this namespace?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,8],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[5]]]]],[1,"\\n"]],[]],null],[1," "]],[4]]]]],[1,"\\n"]],[3]]]]]],["&attrs","@items","item","Actions","Action","@ondelete","Confirmation","Confirm"],false,["list-collection","block-slot","if","href-to","env","consul/token/ruleset/list","not","can","action"]]',moduleName:"consul-ui/components/consul/nspace/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/nspace/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"re+qR2Bv",block:'[[[41,[28,[37,1],[[30,1],"remove"],null],[[[1," "],[8,[39,2],[[17,2]],[["@color"],["success"]],[["default"],[[[[1,"\\n "],[8,[30,3,["Title"]],null,null,[["default"],[[[[1,"Success!"]],[]]]]],[1,"\\n "],[8,[30,3,["Description"]],null,null,[["default"],[[[[1,"Your Namespace has been marked for deletion."]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n"]],[]],null]],["@type","&attrs","T"],false,["if","eq","hds/toast"]]',moduleName:"consul-ui/components/consul/nspace/notifications/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/nspace/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"+U4p2s4N",block:'[[[8,[39,0],[[24,0,"consul-nspace-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.nspace.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.nspace.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,14,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,16],[30,14,["value"]]],null]],[1,"\\n"]],[16]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,15,["Optgroup"]],[30,15,["Option"]]],[[[1," "],[8,[30,17],null,[["@label"],[[28,[37,2],["common.consul.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["Name:asc",[28,[37,13],["Name:asc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["Name:desc",[28,[37,13],["Name:desc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17,18]]],[1," "]],[]]]]],[1,"\\n "]],[15]]]]],[1,"\\n "]],[13]]]]]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/nspace/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/nspace/selector/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"Sn707Mkm",block:'[[[41,[28,[37,1],["use nspaces"],null],[[[41,[28,[37,1],["choose nspaces"],null],[[[44,[[28,[37,3],[[30,1],"default"],null],[28,[37,4],["dc.nspaces",[30,2,["Name"]]],null]],[[[1," "],[10,"li"],[14,0,"nspaces"],[12],[1,"\\n "],[8,[39,5],[[24,"aria-label","Namespace"]],[["@items"],[[28,[37,6],[[28,[37,7],null,[["Name","href"],["Manage Namespaces",[28,[37,8],["dc.nspaces",[30,2,["Name"]]],null]]]],[28,[37,9],["DeletedAt",[30,5]],null]],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Action"]],[[4,[38,10],["click",[30,6,["toggle"]]],null]],null,[["default"],[[[[1,"\\n "],[1,[52,[30,4],"Manage Namespaces",[30,3]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Menu"]],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,11],[[30,5,["length"]],0],null],[[[1," "],[8,[39,12],null,[["@src","@onchange"],[[28,[37,13],["/${partition}/*/${dc}/namespaces",[28,[37,7],null,[["partition","dc"],[[30,8],[30,2,["Name"]]]]]],null],[28,[37,14],[[28,[37,15],[[30,9]],null]],null]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,12],null,[["@src","@onchange"],[[28,[37,13],["/${partition}/*/${dc}/namespaces",[28,[37,7],null,[["partition","dc"],[[30,8],[30,2,["Name"]]]]]],null],[28,[37,14],[[28,[37,15],[[30,9]],null]],null]]],null],[1,"\\n"]],[]]],[1," "],[8,[30,7,["Menu"]],null,null,[["default"],[[[[1,"\\n"],[42,[28,[37,17],[[28,[37,17],[[30,10,["items"]]],null]],null],null,[[[1,"\\n "],[8,[30,10,["Item"]],[[16,"aria-current",[52,[28,[37,3],[[28,[37,18],[[30,4],[30,11,["href"]]],null],[28,[37,18],[[28,[37,19],[[30,4]],null],[28,[37,20],[[30,3],[30,11,["Name"]]],null]],null]],null],"true"]]],null,[["default"],[[[[1,"\\n "],[8,[30,10,["Action"]],[[4,[38,10],["click",[30,6,["close"]]],null]],[["@href"],[[52,[30,11,["href"]],[30,11,["href"]],[52,[30,4],[28,[37,8],["dc.services.index"],[["params"],[[28,[37,7],null,[["partition","nspace","dc"],[[52,[28,[37,11],[[30,8,["length"]],0],null],[30,8],[27]],[30,11,["Name"]],[30,2,["Name"]]]]]]]],[28,[37,8],["."],[["params"],[[28,[37,7],null,[["partition","nspace"],[[52,[28,[37,11],[[30,8,["length"]],0],null],[30,8],[27]],[30,11,["Name"]]]]]]]]]]]],[["default"],[[[[1,"\\n "],[1,[30,11,["Name"]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[11]],null],[1," "]],[10]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "],[13],[1,"\\n"]],[3,4]]]],[]],null]],[]],null]],["@nspace","@dc","nspace","isManaging","@nspaces","disclosure","panel","@partition","@onchange","menu","item"],false,["if","can","let","or","is-href","disclosure-menu","append","hash","href-to","reject-by","on","gt","data-source","uri","fn","optional","each","-track-array","and","not","eq"]]',moduleName:"consul-ui/components/consul/nspace/selector/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/partition/form/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"+TwrfeYU",block:'[[[11,0],[24,0,"consul-partition-form"],[17,1],[12],[1,"\\n "],[8,[39,0],null,[["@sink","@type","@label","@ondelete","@onchange"],[[28,[37,1],["/${partition}/${nspace}/${dc}/partition",[28,[37,2],null,[["partition","nspace","dc"],["","",[30,2,["Datacenter"]]]]]],null],"partition","Partition",[28,[37,3],[[52,[30,3],[30,3],[30,4]],[30,2]],null],[28,[37,3],[[28,[37,5],[[30,4]],null],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,7],[[4,[38,8],null,[["after"],[[28,[37,9],[[30,0],[30,6]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[6]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,11],[[28,[37,12],["write partition"],null]],null],[30,2],[28,[37,2],null,[["help","Name"],["Must be a valid DNS hostname. Must contain 1-64 characters (numbers, letters, and hyphens), and must begin with a letter. Once created, this cannot be changed.",[28,[37,13],[[28,[37,2],null,[["test","error"],["^[a-zA-Z0-9]([a-zA-Z0-9-]{0,62}[a-zA-Z0-9])?$","Name must be a valid DNS hostname."]]]],null]]]],[28,[37,2],null,[["Description"],[[28,[37,13],null,null]]]]],[[[11,"form"],[4,[38,14],["submit",[28,[37,3],[[30,5,["persist"]],[30,8]],null]],null],[4,[38,15],[[30,7]],null],[12],[1,"\\n\\n"],[8,[39,16],null,[["@src"],[[28,[37,16],["validate"],null]]],[["default"],[[[[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n"],[41,[28,[37,17],["new partition"],[["item"],[[30,8]]]],[[[1," "],[8,[39,18],null,[["@name","@placeholder","@item","@validations","@chart"],["Name","Name",[30,8],[30,9],[28,[37,2],null,[["state","dispatch"],[[30,15],[30,14]]]]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,18],null,[["@expanded","@name","@label","@item","@validations","@chart"],[true,"Description","Description (Optional)",[30,8],[30,10],[28,[37,2],null,[["state","dispatch"],[[30,15],[30,14]]]]]],null],[1,"\\n "],[13],[1,"\\n\\n "],[10,0],[12],[1,"\\n "],[8,[39,19],null,null,[["default"],[[[[1,"\\n\\n\\n"],[41,[28,[37,20],[[28,[37,17],["new partition"],[["item"],[[30,8]]]],[28,[37,12],["create partitions"],null]],null],[[[1," "],[8,[39,21],[[16,"disabled",[28,[37,22],[[28,[37,17],["pristine partition"],[["item"],[[30,8]]]],[28,[37,23],[[30,15],"error"],null]],null]],[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n"]],[]],[[[41,[28,[37,11],[[30,7]],null],[[[1," "],[8,[39,21],[[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n"]],[]],null]],[]]],[1," "],[8,[39,21],[[24,4,"reset"],[4,[38,14],["click",[52,[30,16],[28,[37,3],[[28,[37,5],[[30,16],[30,8]],null]],null],[28,[37,3],[[28,[37,5],[[30,4],[30,8]],null]],null]]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n\\n"],[41,[28,[37,20],[[28,[37,11],[[28,[37,17],["new partition"],[["item"],[[30,8]]]]],null],[28,[37,12],["delete partition"],[["item"],[[30,8]]]]],null],[[[1," "],[8,[39,24],null,[["@message"],["Are you sure you want to delete this Partition?"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,21],[[4,[38,14],["click",[28,[37,3],[[30,17],[28,[37,3],[[30,5,["delete"]],[30,8]],null]],null]],null]],[["@text","@color"],["Delete","critical"]],null],[1,"\\n "]],[17]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@message","@execute","@cancel"],[[30,20],[30,18],[30,19]]],null],[1,"\\n "]],[18,19,20]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n\\n"]],[11,12,13,14,15]]]]],[1,"\\n"],[13],[1,"\\n\\n"]],[7,8,9,10]]],[1," "]],[]]]]],[1,"\\n"]],[5]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@item","@ondelete","@onsubmit","writer","after","readOnly","item","Name","Description","State","Guard","ChartAction","dispatch","state","@oncancel","confirm","execute","cancel","message"],false,["data-writer","uri","hash","fn","if","optional","block-slot","consul/partition/notifications","notification","action","let","not","can","array","on","disabled","state-chart","is","text-input","hds/button-set","and","hds/button","or","state-matches","confirmation-dialog","delete-confirmation"]]',moduleName:"consul-ui/components/consul/partition/form/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/partition/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"VkpAwQ51",block:'[[[8,[39,0],[[24,0,"consul-partition-list"],[17,1]],[["@items","@linkable"],[[30,2],"linkable partition"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[30,3,["DeletedAt"]],[[[1," "],[10,2],[12],[1,"\\n Deleting "],[1,[30,3,["Name"]]],[1,"...\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,6,[28,[37,3],["dc.partitions.edit",[30,3,["Name"]]],null]],[12],[1,[30,3,["Name"]]],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n"],[41,[30,3,["Description"]],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Description"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,4],[[30,3,["DeletedAt"]]],null],[[[1," "],[8,[30,4],null,null,[["default"],[[[[1,"\\n "],[8,[30,5],null,[["@href"],[[28,[37,3],["dc.partitions.edit",[30,3,["Name"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n"],[41,[28,[37,5],["write partition"],[["item"],[[30,3]]]],[[[1," Edit\\n"]],[]],[[[1," View\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,5],["delete partition"],[["item"],[[30,3]]]],[[[1," "],[8,[30,5],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,6],[[30,0],[30,6],[30,3]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,7],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this partition?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,8],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[5]]]]],[1,"\\n"]],[]],null],[1," "]],[4]]]]],[1,"\\n"]],[3]]]]],[1,"\\n"]],["&attrs","@items","item","Actions","Action","@ondelete","Confirmation","Confirm"],false,["list-collection","block-slot","if","href-to","not","can","action"]]',moduleName:"consul-ui/components/consul/partition/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/partition/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"Rj1t1uFE",block:'[[[41,[28,[37,1],[[30,1],"remove"],null],[[[1," "],[8,[39,2],[[17,2]],[["@color"],["success"]],[["default"],[[[[1,"\\n "],[8,[30,3,["Title"]],null,null,[["default"],[[[[1,"Success!"]],[]]]]],[1,"\\n "],[8,[30,3,["Description"]],null,null,[["default"],[[[[1,"\\n Your Partition has been marked for deletion.\\n "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n"]],[]],null]],["@type","&attrs","T"],false,["if","eq","hds/toast"]]',moduleName:"consul-ui/components/consul/partition/notifications/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/partition/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"zU7wyufj",block:'[[[8,[39,0],[[24,0,"consul-partition-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.nspace.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.nspace.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,14,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,16],[30,14,["value"]]],null]],[1,"\\n"]],[16]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,15,["Optgroup"]],[30,15,["Option"]]],[[[1," "],[8,[30,17],null,[["@label"],[[28,[37,2],["common.consul.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["Name:asc",[28,[37,13],["Name:asc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["Name:desc",[28,[37,13],["Name:desc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17,18]]],[1," "]],[]]]]],[1,"\\n "]],[15]]]]],[1,"\\n "]],[13]]]]]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/partition/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/partition/selector/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"GPyi0nAM",block:'[[[44,[[28,[37,1],[[30,1],"default"],null],[28,[37,2],["dc.partitions",[30,2,["Name"]]],null]],[[[41,[28,[37,4],["choose partitions"],[["dc"],[[30,2]]]],[[[1," "],[10,"li"],[14,0,"partitions"],[12],[1,"\\n "],[8,[39,5],[[24,"aria-label","Admin Partition"]],[["@items"],[[28,[37,6],[[28,[37,7],null,[["Name","href"],["Manage Partitions",[28,[37,8],["dc.partitions",[30,2,["Name"]]],null]]]],[28,[37,9],["DeletedAt",[30,5]],null]],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Action"]],[[4,[38,10],["click",[30,6,["toggle"]]],null]],null,[["default"],[[[[1,"\\n "],[1,[52,[30,4],"Manage Partition",[30,3]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Menu"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,11],null,[["@src","@onchange"],[[28,[37,12],["/*/*/${dc}/partitions",[28,[37,7],null,[["dc"],[[30,2,["Name"]]]]]],null],[28,[37,13],[[28,[37,14],[[30,8]],null]],null]]],null],[1,"\\n "],[8,[30,7,["Menu"]],null,null,[["default"],[[[[1,"\\n"],[42,[28,[37,16],[[28,[37,16],[[30,9,["items"]]],null]],null],null,[[[1," "],[8,[30,9,["Item"]],[[16,"aria-current",[52,[28,[37,1],[[28,[37,17],[[30,4],[30,10,["href"]]],null],[28,[37,17],[[28,[37,18],[[30,4]],null],[28,[37,19],[[30,3],[30,10,["Name"]]],null]],null]],null],"true"]]],null,[["default"],[[[[1,"\\n "],[8,[30,9,["Action"]],[[4,[38,10],["click",[30,6,["close"]]],null]],[["@href"],[[52,[30,10,["href"]],[30,10,["href"]],[52,[30,4],[28,[37,8],["dc.services.index"],[["params"],[[28,[37,7],null,[["partition","nspace","dc"],[[30,10,["Name"]],[27],[30,2,["Name"]]]]]]]],[28,[37,8],["."],[["params"],[[28,[37,7],null,[["partition","nspace"],[[30,10,["Name"]],[27]]]]]]]]]]],[["default"],[[[[1,"\\n "],[1,[30,10,["Name"]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[10]],null],[1," "]],[9]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,"li"],[14,0,"partition"],[14,"aria-label","Admin Partition"],[12],[1,"\\n "],[1,"default"],[1,"\\n "],[13],[1,"\\n"]],[]]]],[3,4]]]],["@partition","@dc","partition","isManaging","@partitions","disclosure","panel","@onchange","menu","item"],false,["let","or","is-href","if","can","disclosure-menu","append","hash","href-to","reject-by","on","data-source","uri","fn","optional","each","-track-array","and","not","eq"]]',moduleName:"consul-ui/components/consul/partition/selector/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/address/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"pSmtNtNJ",block:'[[[8,[39,0],null,null,[["default"],[[[[1,"\\n"],[41,[30,1,["data","height"]],[[[1," "],[10,0],[15,5,[30,1,["data","fillRemainingHeightStyle"]]],[14,0,"overflow-y-scroll"],[12],[1,"\\n "],[8,[39,2],null,[["@tagName","@estimateHeight","@items"],["ul",[30,1,["data","height"]],[30,2]]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"px-3 h-12 border-bottom-primary flex items-center justify-between group"],[12],[1,"\\n "],[10,0],[14,0,"hds-typography-display-300 text-hds-foreground-strong hds-font-weight-semibold"],[12],[1,[30,3]],[13],[1,"\\n "],[8,[39,3],[[24,0,"opacity-0 group-hover:opacity-100"]],[["@value","@name"],[[30,3],"Address"]],null],[1,"\\n "],[13],[1,"\\n "]],[3,4]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[1]]]]]],["p","@items","address","index"],false,["providers/dimension","if","vertical-collection","copy-button"]]',moduleName:"consul-ui/components/consul/peer/address/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/bento-box/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"H9CcvCNn",block:'[[[8,[39,0],[[24,0,"mt-6 mb-3"]],[["@level","@hasBorder"],["base",true]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"flex h-24 p-6 overflow-x-auto space-x-12"],[12],[1,"\\n "],[10,0],[14,0,"shrink-0"],[12],[1,"\\n "],[10,0],[14,0,"mb-2 hds-typography-body-200 hds-font-weight-semibold hds-foreground-primary"],[12],[1,"Status"],[13],[1,"\\n "],[10,0],[14,0,"flex items-center"],[12],[1,"\\n "],[8,[39,1],null,[["@peering"],[[30,1]]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"shrink-0"],[12],[1,"\\n "],[10,0],[14,0,"hds-typography-body-200 mb-2 hds-font-weight-semibold hds-foreground-primary"],[12],[1,"Latest heartbeat"],[13],[1,"\\n "],[10,0],[14,0,"flex items-center"],[12],[1,"\\n"],[41,[30,1,["LastHeartbeat"]],[[[44,[[28,[37,4],[[30,1,["LastHeartbeat"]]],null]],[[[1," "],[8,[39,5],[[24,0,"mr-0.5"]],[["@name","@color"],["activity","var(--token-color-foreground-faint)"]],null],[1,"\\n"],[41,[30,2,["isNearDate"]],[[[1," "],[11,1],[4,[38,6],[[30,2,["friendly"]]],null],[12],[1,[30,2,["relative"]]],[13],[1,"\\n"]],[]],[[[1," "],[10,1],[12],[1,[30,2,["friendly"]]],[13],[1,"\\n"]],[]]]],[2]]]],[]],[[[1," "],[10,1],[12],[1,"None yet"],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"shrink-0"],[12],[1,"\\n "],[10,0],[14,0,"mb-2 hds-typography-body-200 hds-font-weight-semibold hds-foreground-primary"],[12],[1,"Latest receipt"],[13],[1,"\\n "],[10,0],[14,0,"flex items-center"],[12],[1,"\\n"],[41,[30,1,["LastReceive"]],[[[44,[[28,[37,4],[[30,1,["LastReceive"]]],null]],[[[41,[30,3,["isNearDate"]],[[[1," "],[11,1],[4,[38,6],[[30,3,["friendly"]]],null],[12],[1,[30,3,["relative"]]],[13],[1,"\\n"]],[]],[[[1," "],[10,1],[12],[1,[30,3,["friendly"]]],[13],[1,"\\n"]],[]]]],[3]]]],[]],[[[1," "],[10,1],[12],[1,"None yet"],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"shrink-0"],[12],[1,"\\n "],[10,0],[14,0,"mb-2 hds-typography-body-200 hds-font-weight-semibold hds-foreground-primary"],[12],[1,"Latest send"],[13],[1,"\\n "],[10,0],[14,0,"flex items-center"],[12],[1,"\\n"],[41,[30,1,["LastSend"]],[[[44,[[28,[37,4],[[30,1,["LastSend"]]],null]],[[[41,[30,4,["isNearDate"]],[[[1," "],[11,1],[4,[38,6],[[30,4,["friendly"]]],null],[12],[1,[30,4,["relative"]]],[13],[1,"\\n"]],[]],[[[1," "],[10,1],[12],[1,[30,4,["friendly"]]],[13],[1,"\\n"]],[]]]],[4]]]],[]],[[[1," "],[10,1],[12],[1,"None yet"],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]]]]]],["@peering","smartDate","smartDate","smartDate"],false,["hds/card/container","peerings/badge","if","let","smart-date-format","flight-icon","tooltip"]]',moduleName:"consul-ui/components/consul/peer/bento-box/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/form/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={id:"consul-peer-form",initial:"generate",on:{INITIATE:[{target:"initiate"}],GENERATE:[{target:"generate"}]},states:{initiate:{},generate:{}}}})),define("consul-ui/components/consul/peer/form/generate/actions/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"3YYkPKep",block:'[[[8,[39,0],[[16,"form",[30,1]],[24,4,"submit"],[16,"disabled",[28,[37,1],[[28,[37,2],[[30,2,["Name","length"]],0],null]],null]],[17,3]],[["@text"],["Generate token"]],null]],["@id","@item","&attrs"],false,["hds/button","or","eq"]]',moduleName:"consul-ui/components/consul/peer/form/generate/actions/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/form/generate/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={id:"consul-peer-generate-form",initial:"idle",states:{idle:{on:{LOAD:{target:"loading"}}},loading:{on:{SUCCESS:{target:"success"},ERROR:{target:"error"}}},success:{on:{RESET:{target:"idle"}}},error:{}}}})),define("consul-ui/components/consul/peer/form/generate/fieldsets/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object"],(function(e,t,n,l,r){var i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"NcmZNT1t",block:'[[[11,0],[16,0,[28,[37,0],["consul-peer-form-generate-fieldsets"],null]],[17,1],[12],[1,"\\n "],[8,[39,1],null,[["@src"],[[28,[37,2],["/machines/validate.xstate"],[["from"],["/components/consul/peer/form/generate/fieldsets"]]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["help","Name"],[[28,[37,5],[[28,[37,6],["common.validations.dns-hostname.help"],null],[28,[37,6],["common.validations.immutable.help"],null]],null],[28,[37,7],[[28,[37,4],null,[["test","error"],[[28,[37,6],["common.validations.dns-hostname.test"],null],[28,[37,6],["common.validations.dns-hostname.error"],[["name"],["Name"]]]]]]],null]]]]],[[[1," "],[10,"fieldset"],[12],[1,"\\n "],[8,[39,8],null,[["@label","@name","@item","@validations","@chart","@oninput"],[[28,[37,6],["components.consul.peer.generate.name"],null],"Name",[30,4],[30,3],[30,2],[28,[37,9],["target.value",[28,[37,10],[[30,4],"Name"],null]],null]]],null],[1,"\\n "],[18,6,[[28,[37,4],null,[["valid"],[[28,[37,12],[[28,[37,13],[[30,2,["state"]],"error"],null]],null]]]]]],[1,"\\n "],[13],[1,"\\n\\n"]],[3]]],[1,"\\n"],[44,[[28,[37,4],null,[["help"],[[28,[37,6],["common.validations.server-external-addresses.help"],null]]]]],[[[1," "],[10,"fieldset"],[12],[1,"\\n "],[8,[39,8],null,[["@label","@name","@item","@chart","@validations","@oninput"],[[28,[37,6],["components.consul.peer.generate.addresses"],null],"ServerExternalAddresses",[30,4],[30,2],[30,5],[28,[37,9],["target.value",[30,0,["onInput"]]],null]]],null],[1,"\\n "],[18,6,[[28,[37,4],null,[["valid"],[[28,[37,12],[[28,[37,13],[[30,2,["state"]],"error"],null]],null]]]]]],[1,"\\n "],[13],[1,"\\n\\n"]],[5]]],[1," "]],[2]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","fsm","Name","@item","ServerExternalAddresses","&default"],false,["class-map","state-machine","require","let","hash","concat","t","array","text-input","pick","set","yield","not","state-matches"]]',moduleName:"consul-ui/components/consul/peer/form/generate/fieldsets/index.hbs",isStrictMode:!1}) -let a=(i=class extends l.default{onInput(e){e=e?e.split(",").map((e=>e.trim())):[],this.args.item.ServerExternalAddresses=e}},u=i.prototype,s="onInput",c=[r.action],d=Object.getOwnPropertyDescriptor(i.prototype,"onInput"),p=i.prototype,f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i) -var u,s,c,d,p,f -e.default=a,(0,t.setComponentTemplate)(o,a)})),define("consul-ui/components/consul/peer/form/generate/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"s3NJojfR",block:'[[[11,0],[16,0,[28,[37,0],["consul-peer-form-generate"],null]],[17,1],[12],[1,"\\n "],[8,[39,1],null,[["@src","@initial"],[[28,[37,2],["./chart.xstate"],[["from"],["/components/consul/peer/form/generate"]]],[52,[30,2],"loading","idle"]]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,5],null,null]],[[[1," "],[11,"form"],[16,1,[30,4]],[4,[38,6],["submit",[28,[37,7],[[30,3,["dispatch"]],"LOAD"],null]],null],[12],[1,"\\n\\n "],[8,[30,3,["State"]],null,[["@matches"],[[28,[37,8],["idle","error"],null]]],[["default"],[[[[1,"\\n "],[8,[30,3,["State"]],null,[["@matches"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,9],[[24,0,"mb-3 mt-2"]],[["@type"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Error"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,[30,3,["state","context","error","message"]]]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[18,9,[[28,[37,11],null,[["Fieldsets","Actions"],[[50,"consul/peer/form/generate/fieldsets",0,null,[["item"],[[30,7]]]],[50,"consul/peer/form/generate/actions",0,null,[["item","id"],[[30,7],[30,4]]]]]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,3,["State"]],null,[["@matches"],["loading"]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@src","@onchange","@onerror"],[[28,[37,14],["/${partition}/${nspace}/${dc}/peering/token-for/${name}/${externalAddresses}",[28,[37,11],null,[["partition","nspace","dc","name","externalAddresses"],[[30,7,["Partition"]],"",[30,7,["Datacenter"]],[30,7,["Name"]],[30,7,["ServerExternalAddresses"]]]]]],null],[28,[37,15],[[30,8],[28,[37,16],["data",[28,[37,7],[[30,3,["dispatch"]],"SUCCESS"],null]],null]],null],[28,[37,15],[[28,[37,7],[[30,3,["dispatch"]],"ERROR"],null]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,3,["State"]],null,[["@matches"],["success"]],[["default"],[[[[1,"\\n "],[18,9,[[28,[37,11],null,[["Fieldsets","Actions"],[[50,"consul/peer/form/token/fieldsets",0,null,[["item","token","regenerate","onclick"],[[30,7],[30,3,["state","context","PeeringToken"]],[30,2],[28,[37,15],[[28,[37,17],[[30,7],"Name",""],null],[28,[37,7],[[30,3,["dispatch"]],"RESET"],null]],null]]]],[50,"consul/peer/form/token/actions",0,null,[["token","item","id"],[[30,3,["state","context","PeeringToken"]],[30,7],[30,4]]]]]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[13],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@regenerate","fsm","id","reset","A","@item","@onchange","&default"],false,["class-map","state-machine","require","if","let","unique-id","on","fn","array","hds/alert","yield","hash","component","data-source","uri","queue","pick","set"]]',moduleName:"consul-ui/components/consul/peer/form/generate/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/form/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"5/r0PDQY",block:'[[[11,0],[16,0,[28,[37,0],["consul-peer-form"],null]],[17,1],[12],[1,"\\n "],[8,[39,1],null,[["@src"],[[28,[37,2],["./chart.xstate"],[["from"],["/components/consul/peer/form"]]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,3],null,[["@items","@onTabClicked"],[[28,[37,4],[[28,[37,5],null,[["label","selected","state"],[[28,[37,6],["components.consul.peer.form.generate-label"],null],[28,[37,7],[[30,2,["state"]],"generate"],null],"GENERATE"]]],[28,[37,5],null,[["label","selected","state"],[[28,[37,6],["components.consul.peer.form.establish-label"],null],[28,[37,7],[[30,2,["state"]],"initiate"],null],"INITIATE"]]]],null],[28,[37,8],["state",[30,2,["dispatch"]]],null]]],null],[1,"\\n\\n "],[8,[30,2,["State"]],null,[["@matches"],[[28,[37,4],["generate"],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,9],null,[["@src"],[[28,[37,10],["/${partition}/${nspace}/${dc}/peer-generate/",[30,3]],null]]],[["default"],[[[[1,"\\n "],[18,6,[[28,[37,5],null,[["Form"],[[50,"consul/peer/form/generate",0,null,[["item"],[[30,4,["data"]]]]]]]]]],[1,"\\n "]],[4]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,2,["State"]],null,[["@matches"],["initiate"]],[["default"],[[[[1,"\\n\\n "],[8,[39,9],null,[["@src"],[[28,[37,10],["/${partition}/${nspace}/${dc}/peer-initiate/",[30,3]],null]]],[["default"],[[[[1,"\\n "],[18,6,[[28,[37,5],null,[["Form"],[[50,"consul/peer/form/initiate",0,null,[["item"],[[30,5,["data"]]]]]]]]]],[1,"\\n "]],[5]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n\\n "]],[2]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","fsm","@params","source","source","&default"],false,["class-map","state-machine","require","tab-nav","array","hash","t","state-matches","pick","data-source","uri","yield","component"]]',moduleName:"consul-ui/components/consul/peer/form/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/form/initiate/actions/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"ShUcgNKi",block:'[[[8,[39,0],[[16,"form",[30,1]],[24,4,"submit"],[17,2]],[["@text"],["Add peer"]],null]],["@id","&attrs"],false,["hds/button"]]',moduleName:"consul-ui/components/consul/peer/form/initiate/actions/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/form/initiate/fieldsets/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"I08SZDBv",block:'[[[11,0],[16,0,[28,[37,0],["consul-peer-form-initiate-fieldsets"],null]],[17,1],[12],[1,"\\n"],[44,[[28,[37,2],null,[["help","Name"],["Enter a name to locally identify the new peer.",[28,[37,3],[[28,[37,2],null,[["test","error"],[[28,[37,4],["common.validations.dns-hostname.test"],null],[28,[37,4],["common.validations.dns-hostname.error"],[["name"],["Name"]]]]]]],null]]]],[28,[37,2],null,[["help","PeeringToken"],["Enter the token received from the operator of the desired peer.",[28,[37,3],null,null]]]]],[[[1," "],[10,2],[12],[1,"\\n Enter a token generated in the desired peer.\\n "],[13],[1,"\\n "],[8,[39,5],null,[["@src"],[[28,[37,6],["/machines/validate.xstate"],[["from"],["/components/consul/peer/form/generate/fieldsets"]]]]],[["default"],[[[[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n "],[8,[39,7],null,[["@name","@label","@item","@validations","@chart"],["Name","Name of peer",[30,5],[30,2],[30,4]]],null],[1,"\\n "],[8,[39,7],null,[["@expanded","@name","@item","@validations","@chart"],[true,"Token",[30,5],[30,3],[30,4]]],null],[1,"\\n "],[18,6,[[28,[37,2],null,[["valid"],[[28,[37,9],[[28,[37,10],[[30,4,["state"]],"error"],null]],null]]]]]],[1,"\\n "],[13],[1,"\\n\\n "]],[4]]]]],[1,"\\n"]],[2,3]]],[13],[1,"\\n"]],["&attrs","Name","PeeringToken","fsm","@item","&default"],false,["class-map","let","hash","array","t","state-machine","require","text-input","yield","not","state-matches"]]',moduleName:"consul-ui/components/consul/peer/form/initiate/fieldsets/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/form/initiate/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"xAGGr6Ec",block:'[[[11,0],[16,0,[28,[37,0],["consul-peer-form-initiate"],null]],[17,1],[12],[1,"\\n "],[8,[39,1],null,[["@sink","@type","@label","@onchange"],[[28,[37,2],["/${partition}/${nspace}/${dc}/peer",[28,[37,3],null,[["partition","nspace","dc"],[[28,[37,4],[[30,2,["Partition"]],""],null],[28,[37,4],[[30,2,["Namespace"]],""],null],[28,[37,4],[[30,2,["Datacenter"]],""],null]]]]],null],"peer","peer",[28,[37,5],[[28,[37,6],[[30,3]],null],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,8],[[24,0,"mb-3 mt-2"]],[["@type"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,7,["Title"]],null,null,[["default"],[[[[1,"Error"]],[]]]]],[1,"\\n "],[8,[30,7,["Description"]],null,null,[["default"],[[[[1,[30,6,["message"]]]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[5,6]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,10],null,null]],[[[1," "],[11,"form"],[16,1,[30,8]],[4,[38,11],["submit",[28,[37,5],[[30,4,["persist"]],[30,2]],null]],null],[12],[1,"\\n "],[18,9,[[28,[37,3],null,[["Fieldsets","Actions"],[[50,"consul/peer/form/initiate/fieldsets",0,null,[["item"],[[30,2]]]],[50,"consul/peer/form/initiate/actions",0,null,[["item","id"],[[30,2],[30,8]]]]]]]]],[1,"\\n "],[13],[1,"\\n"]],[8]]],[1," "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"],[13]],["&attrs","@item","@onsubmit","writer","after","error","A","id","&default"],false,["class-map","data-writer","uri","hash","or","fn","optional","block-slot","hds/alert","let","unique-id","on","yield","component"]]',moduleName:"consul-ui/components/consul/peer/form/initiate/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/form/token/actions/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"flM3VZCN",block:'[[[11,0],[17,1],[12],[1,"\\n "],[8,[39,0],null,null,[["default"],[[[[1,"\\n "],[8,[39,1],[[17,1],[4,[38,2],[[30,2]],null]],[["@text","@color"],["Copy token","primary"]],null],[1,"\\n "],[8,[39,1],[[24,4,"reset"],[4,[38,3],["click",[30,3]],null]],[["@text","@color"],["Close","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@token","@onclose"],false,["hds/button-set","hds/button","with-copyable","on"]]',moduleName:"consul-ui/components/consul/peer/form/token/actions/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/form/token/fieldsets/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"u1kd86tb",block:'[[[41,[30,1],[[[1," "],[10,2],[12],[1,"\\n Token regenerated! Here’s what’s next:\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,2],[12],[1,"\\n Token generated! Here’s what’s next:\\n "],[13],[1,"\\n"]],[]]],[1," "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[10,"strong"],[12],[1,"Copy the token"],[13],[10,"br"],[12],[13],[1,"\\n This token cannot be viewed again after creation.\\n "],[10,"br"],[12],[13],[1,"\\n "],[8,[39,1],null,[["@value","@name"],[[30,2],"Token"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[10,"strong"],[12],[1,"Switch to the peer"],[13],[10,"br"],[12],[13],[1,"\\n Someone on your team should log into the Datacenter (OSS) or Admin Partition (Enterprise) that you want this one to connect with.\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[10,"strong"],[12],[1,"Initiate the peering"],[13],[10,"br"],[12],[13],[1,"\\n From there, initiate a new peering, name it, and paste this token in.\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,2],[[30,1]],null],[[[1," "],[8,[39,3],[[24,4,"reset"],[4,[38,4],["click",[30,3]],null]],[["@text","@color"],["Generate another token","secondary"]],null],[1,"\\n"]],[]],null],[1,"\\n"]],["@regenerate","@token","@onclick"],false,["if","copyable-code","not","hds/button","on"]]',moduleName:"consul-ui/components/consul/peer/form/token/fieldsets/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/info/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"OgBqwHXm",block:'[[[41,[30,1,["PeerName"]],[[[1," "],[10,0],[14,0,"consul-peer-info"],[12],[1,"\\n\\n "],[11,"svg"],[24,"width","16"],[24,"height","16"],[24,"viewBox","0 0 16 16"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[4,[38,1],["Peer"],null],[12],[1,"\\n "],[10,"path"],[14,"d","M16 8C16 7.80109 15.921 7.61032 15.7803 7.46967L12.2803 3.96967C11.9874 3.67678 11.5126 3.67678 11.2197 3.96967C10.9268 4.26256 10.9268 4.73744 11.2197 5.03033L14.1893 8L11.2197 10.9697C10.9268 11.2626 10.9268 11.7374 11.2197 12.0303C11.5126 12.3232 11.9874 12.3232 12.2803 12.0303L15.7803 8.53033C15.921 8.38968 16 8.19891 16 8Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M0.21967 8.53033C-0.0732233 8.23744 -0.0732233 7.76256 0.21967 7.46967L3.71967 3.96967C4.01256 3.67678 4.48744 3.67678 4.78033 3.96967C5.07322 4.26256 5.07322 4.73744 4.78033 5.03033L1.81066 8L4.78033 10.9697C5.07322 11.2626 5.07322 11.7374 4.78033 12.0303C4.48744 12.3232 4.01256 12.3232 3.71967 12.0303L0.21967 8.53033Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M5 7C4.44772 7 4 7.44772 4 8C4 8.55229 4.44772 9 5 9H5.01C5.56228 9 6.01 8.55229 6.01 8C6.01 7.44772 5.56228 7 5.01 7H5Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M7 8C7 7.44772 7.44772 7 8 7H8.01C8.56228 7 9.01 7.44772 9.01 8C9.01 8.55229 8.56228 9 8.01 9H8C7.44772 9 7 8.55229 7 8Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M11 7C10.4477 7 10 7.44772 10 8C10 8.55229 10.4477 9 11 9H11.01C11.5623 9 12.01 8.55229 12.01 8C12.01 7.44772 11.5623 7 11.01 7H11Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,1],[14,0,"consul-peer-info__description"],[12],[1,"Imported from "],[10,1],[12],[1,[30,1,["PeerName"]]],[13],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],["@item"],false,["if","tooltip"]]',moduleName:"consul-ui/components/consul/peer/info/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"P8VyWcGf",block:'[[[8,[39,0],[[24,0,"consul-peer-list"],[17,1]],[["@items","@linkable"],[[30,2],"linkable peers"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],["delete peer"],[["item"],[[30,3]]]],[[[1," "],[10,3],[15,6,[28,[37,4],["dc.peers.show",[30,3,["Name"]]],null]],[12],[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,2],[12],[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"peers__list__peer-detail"],[12],[1,"\\n "],[8,[39,5],null,[["@peering"],[[30,3]]],null],[1,"\\n\\n "],[11,0],[4,[38,6],[[28,[37,7],["routes.dc.peers.index.detail.imported.tooltip"],[["name"],[[30,3,["Name"]]]]]],null],[12],[1,"\\n "],[1,[28,[35,7],["routes.dc.peers.index.detail.imported.count"],[["count"],[[28,[37,8],[[30,3,["ImportedServiceCount"]]],null]]]]],[1,"\\n "],[13],[1,"\\n\\n "],[11,0],[4,[38,6],[[28,[37,7],["routes.dc.peers.index.detail.exported.tooltip"],[["name"],[[30,3,["Name"]]]]]],null],[12],[1,"\\n "],[1,[28,[35,7],["routes.dc.peers.index.detail.exported.count"],[["count"],[[28,[37,8],[[30,3,["ExportedServiceCount"]]],null]]]]],[1,"\\n "],[13],[1,"\\n\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],["delete peer"],[["item"],[[30,3]]]],[[[1,"\\n "],[8,[30,5],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,9],[[28,[37,3],["write peer"],[["item"],[[30,3]]]],[30,3,["isDialer"]]],null],[[[1," "],[8,[30,6],[[4,[38,10],["click",[28,[37,11],[[30,7],[30,3]],null]],null]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Regenerate token\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "],[8,[30,6],null,[["@href"],[[28,[37,4],["dc.peers.show",[30,3,["Name"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n View\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,11],[[30,8],[30,3]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,9],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this peer?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,10],null,null,[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "]],[10]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],null],[1," "]],[5]]]]],[1,"\\n"]],[3,4]]]]]],["&attrs","@items","item","index","Actions","Action","@onedit","@ondelete","Confirmation","Confirm"],false,["list-collection","block-slot","if","can","href-to","peerings/badge","tooltip","t","format-number","and","on","fn"]]',moduleName:"consul-ui/components/consul/peer/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"OPH53/LC",block:'[[[41,[28,[37,1],[[30,1],"remove"],null],[[[1," "],[8,[39,2],[[17,2]],[["@color"],["success"]],[["default"],[[[[1,"\\n "],[8,[30,3,["Title"]],null,null,[["default"],[[[[1,"Success!"]],[]]]]],[1,"\\n "],[8,[30,3,["Description"]],null,null,[["default"],[[[[1,"\\n Your Peer has been marked for deletion.\\n "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n"]],[]],null]],["@type","&attrs","T"],false,["if","eq","hds/toast"]]',moduleName:"consul-ui/components/consul/peer/notifications/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"pkHcu+gS",block:'[[[8,[39,0],[[24,0,"consul-peer-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.peer.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.peer.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-state"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["state","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.peer.search-bar.state.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[28,[37,11],[[28,[37,12],["/models/peer"],[["export","from"],["schema","/components/consul/peer/search-bar"]]],"State.allowedValues"],null]],null]],null],null,[[[44,[[28,[37,13],[[30,17]],null]],[[[1," "],[8,[30,16],[[16,0,[29,["value-",[30,18]]]]],[["@value","@selected"],[[30,18],[28,[37,9],[[30,18],[30,2,["state","value"]]],null]]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.peer.search-bar.state.options.",[30,18]],null]],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[18]]]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,19,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,20,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,14],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["State:asc",[28,[37,2],["components.consul.peer.search-bar.sort.state.asc"],null]],null],[28,[37,4],["State:desc",[28,[37,2],["components.consul.peer.search-bar.sort.state.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,11],[[30,22],[30,20,["value"]]],null]],[1,"\\n"]],[22]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,21,["Optgroup"]],[30,21,["Option"]]],[[[1," "],[8,[30,23],null,[["@label"],[[28,[37,2],["components.consul.peer.search-bar.sort.state.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["State:asc",[28,[37,15],["State:asc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["components.consul.peer.search-bar.sort.state.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["State:desc",[28,[37,15],["State:desc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["components.consul.peer.search-bar.sort.state.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@label"],[[28,[37,2],["common.consul.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["Name:asc",[28,[37,15],["Name:asc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["Name:desc",[28,[37,15],["Name:desc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[23,24]]],[1," "]],[]]]]],[1,"\\n "]],[21]]]]],[1,"\\n "]],[19]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","upperState","state","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","get","require","string-to-lower-case","from-entries","eq"]]',moduleName:"consul-ui/components/consul/peer/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/peer/selector/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"kl+7MwvJ",block:'[[[11,"li"],[24,0,"peers-separator"],[24,"role","separator"],[17,1],[12],[1,"\\n Organization\\n"],[13],[1,"\\n"],[10,"li"],[15,0,[52,[28,[37,1],["dc.peers",[30,2,["Name"]]],null],"is-active"]],[12],[1,"\\n "],[10,3],[15,6,[28,[37,2],["dc.peers",[30,2,["Name"]]],[["params"],[[28,[37,3],null,[["peer"],[[27]]]]]]]],[12],[1,"\\n Peers\\n "],[13],[1,"\\n"],[13],[1,"\\n\\n"]],["&attrs","@dc"],false,["if","is-href","href-to","hash"]]',moduleName:"consul-ui/components/consul/peer/selector/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/policy/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"v5u90Yk1",block:'[[[8,[39,0],[[24,0,"consul-policy-list"]],[["@items"],[[30,1]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],[[28,[37,4],[[30,2]],null],"policy-management"],null],[[[1," "],[10,"dl"],[14,0,"policy-management"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Type"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,5],null,null,[["default"],[[[[1,"\\n Global Management Policy\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[10,3],[15,6,[28,[37,6],["dc.acls.policies.edit",[30,2,["ID"]]],null]],[15,0,[52,[28,[37,3],[[28,[37,4],[[30,2]],null],"policy-management"],null],"is-management"]],[12],[1,[30,2,["Name"]]],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[10,"dl"],[14,0,"datacenter"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,5],null,null,[["default"],[[[[1,"Datacenters"]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,7],[", ",[28,[37,8],[[30,2]],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[14,0,"description"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,2,["Description"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[30,3],null,null,[["default"],[[[[1,"\\n "],[8,[30,4],null,[["@href"],[[28,[37,6],["dc.acls.policies.edit",[30,2,["ID"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n"],[41,[28,[37,9],["write policy"],[["item"],[[30,2]]]],[[[1," Edit\\n"]],[]],[[[1," View\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,9],["delete policy"],[["item"],[[30,2]]]],[[[1," "],[8,[30,4],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,10],[[30,0],[30,5],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,6],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this policy?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,7],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[4]]]]],[1,"\\n "]],[3]]]]],[1,"\\n"]],[2]]]]]],["@items","item","Actions","Action","@ondelete","Confirmation","Confirm"],false,["list-collection","block-slot","if","eq","policy/typeof","tooltip","href-to","join","policy/datacenters","can","action"]]',moduleName:"consul-ui/components/consul/policy/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/policy/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"I7CTnbjl",block:'[[[41,[28,[37,1],[[30,1],"create"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your policy has been added.\\n"]],[]],[[[1," There was an error adding your policy.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"update"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your policy has been saved.\\n"]],[]],[[[1," There was an error saving your policy.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"delete"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your policy was deleted.\\n"]],[]],[[[1," There was an error deleting your policy.\\n"]],[]]]],[]],null]],[]]]],[]]],[44,[[30,3,["errors","firstObject"]]],[[[41,[30,4,["detail"]],[[[1," "],[10,"br"],[12],[13],[1,[28,[35,3],["(",[52,[30,4,["status"]],[28,[37,3],[[30,4,["status"]],": "],null]],[30,4,["detail"]],")"],null]],[1,"\\n"]],[]],null]],[4]]]],["@type","@status","@error","error"],false,["if","eq","let","concat"]]',moduleName:"consul-ui/components/consul/policy/notifications/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})) -define("consul-ui/components/consul/policy/search-bar/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"rNkB4Q1f",block:'[[[8,[39,0],[[24,0,"consul-policy-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.policy.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.policy.search-bar.",[30,3,["status","key"]],".options.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[52,[28,[37,6],[[30,3,["status","key"]],"datacenter"],null],[30,3,["status","value"]],[30,5]]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,7],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,7],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,10],[[28,[37,10],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,11],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,12],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-datacenter"]],[["@position","@onchange","@multiple"],["left",[28,[37,7],[[30,0],[30,2,["datacenter","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.consul.datacenter"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,10],[[28,[37,10],[[33,13]],null]],null],null,[[[1," "],[8,[30,16],null,[["@value","@selected"],[[30,17,["Name"]],[28,[37,11],[[30,17,["Name"]],[30,2,["datacenter","value"]]],null]]],[["default"],[[[[1,[30,17,["Name"]]]],[]]]]],[1,"\\n"]],[17]],null],[1," "],[8,[39,14],null,[["@src","@loading","@onchange"],[[28,[37,15],["/${partition}/*/*/datacenters",[28,[37,16],null,[["partition"],[[30,18]]]]],null],"lazy",[28,[37,7],[[30,0],[28,[37,17],[[30,0,["dcs"]]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-kind"]],[["@position","@onchange","@multiple"],["left",[28,[37,7],[[30,0],[30,2,["kind","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.policy.search-bar.kind.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,19,["Optgroup"]],[30,19,["Option"]]],[[[42,[28,[37,10],[[28,[37,10],[[28,[37,4],["global-management","standard"],null]],null]],null],null,[[[1," "],[8,[30,21],[[16,0,[29,["value-",[30,22]]]]],[["@value","@selected"],[[30,22],[28,[37,11],[[30,22],[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.policy.search-bar.kind.options.",[30,22]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,22]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22]],null]],[20,21]]],[1," "]],[]]]]],[1,"\\n "]],[19]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,23,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,7],[[30,0],[30,24,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,18],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,19],[[30,26],[30,24,["value"]]],null]],[1,"\\n"]],[26]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,25,["Optgroup"]],[30,25,["Option"]]],[[[1," "],[8,[30,27],null,[["@label"],[[28,[37,2],["common.ui.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,28],null,[["@value","@selected"],["Name:asc",[28,[37,6],["Name:asc",[30,24,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,28],null,[["@value","@selected"],["Name:desc",[28,[37,6],["Name:desc",[30,24,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[27,28]]],[1," "]],[]]]]],[1,"\\n "]],[25]]]]],[1,"\\n "]],[23]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","dc","@partition","components","Optgroup","Option","state","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","if","eq","action","block-slot","each","-track-array","includes","lowercase","dcs","data-source","uri","hash","mut","from-entries","get"]]',moduleName:"consul-ui/components/consul/policy/search-bar/index.hbs",isStrictMode:!1}) -class i extends l.default{}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/consul/role/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"+f+3clGw",block:'[[[8,[39,0],[[24,0,"consul-role-list"],[17,1]],[["@items"],[[30,2]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,3],[15,6,[28,[37,2],["dc.acls.roles.edit",[30,3,["ID"]]],null]],[12],[1,[30,3,["Name"]]],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[8,[39,3],null,[["@item"],[[30,3]]],null],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Description"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[30,4],null,null,[["default"],[[[[1,"\\n "],[8,[30,5],null,[["@href"],[[28,[37,2],["dc.acls.roles.edit",[30,3,["ID"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n"],[41,[28,[37,5],["write role"],[["item"],[[30,3]]]],[[[1," Edit\\n"]],[]],[[[1," View\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,5],["delete role"],[["item"],[[30,3]]]],[[[1," "],[8,[30,5],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,6],[[30,0],[30,6],[30,3]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,7],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this role?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,8],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[5]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[3]]]]]],["&attrs","@items","item","Actions","Action","@ondelete","Confirmation","Confirm"],false,["list-collection","block-slot","href-to","consul/token/ruleset/list","if","can","action"]]',moduleName:"consul-ui/components/consul/role/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/role/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"3IiB4HcR",block:'[[[41,[28,[37,1],[[30,1],"create"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your role has been added.\\n"]],[]],[[[1," There was an error adding your role.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"update"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your role has been saved.\\n"]],[]],[[[1," There was an error saving your role.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"delete"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your role was deleted.\\n"]],[]],[[[1," There was an error deleting your role.\\n"]],[]]]],[]],null]],[]]]],[]]],[44,[[30,3,["errors","firstObject"]]],[[[41,[30,4,["detail"]],[[[1," "],[10,"br"],[12],[13],[1,[28,[35,3],["(",[52,[30,4,["status"]],[28,[37,3],[[30,4,["status"]],": "],null]],[30,4,["detail"]],")"],null]],[1,"\\n"]],[]],null]],[4]]]],["@type","@status","@error","error"],false,["if","eq","let","concat"]]',moduleName:"consul-ui/components/consul/role/notifications/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/role/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"aNFJl995",block:'[[[8,[39,0],[[24,0,"consul-role-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.role.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.role.search-bar.",[30,3,["status","key"]],".options.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,14,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["CreateIndex:desc",[28,[37,2],["common.sort.age.desc"],null]],null],[28,[37,4],["CreateIndex:asc",[28,[37,2],["common.sort.age.asc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,16],[30,14,["value"]]],null]],[1,"\\n"]],[16]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,15,["Optgroup"]],[30,15,["Option"]]],[[[1," "],[8,[30,17],null,[["@label"],[[28,[37,2],["common.ui.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["Name:asc",[28,[37,13],["Name:asc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["Name:desc",[28,[37,13],["Name:desc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,17],null,[["@label"],[[28,[37,2],["common.ui.creation"],null]]],[["default"],[[[[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["CreateIndex:desc",[28,[37,13],["CreateIndex:desc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.age.desc"],null]]],[]]]]],[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["CreateIndex:asc",[28,[37,13],["CreateIndex:asc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.age.asc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17,18]]],[1," "]],[]]]]],[1,"\\n "]],[15]]]]],[1,"\\n "]],[13]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/role/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/server/card/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"3gOA2+ED",block:'[[[11,0],[16,0,[28,[37,0],["consul-server-card",[28,[37,1],["voting-status-leader",[28,[37,2],[[30,1,["Status"]],"leader"],null]],null],[28,[37,1],["voting-status-voter",[28,[37,3],[[28,[37,4],[[30,1,["ReadReplica"]]],null],[28,[37,2],[[30,1,["Status"]],"voter"],null]],null]],null],[28,[37,1],["voting-status-non-voter",[28,[37,5],[[30,1,["ReadReplica"]],[28,[37,6],[[30,1,["Status"]],[28,[37,1],["non-voter","staging"],null]],null]],null]],null]],null]],[17,2],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n\\n "],[11,"dt"],[24,0,"name"],[4,[38,7],["Leader"],null],[12],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,1,["Name"]]],[1,"\\n "],[13],[1,"\\n\\n "],[10,"dt"],[15,0,[28,[37,0],["health-status",[28,[37,1],["healthy",[30,1,["Healthy"]]],null]],null]],[12],[1,"\\n Status\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[52,[28,[37,6],[[30,1,["Status"]],[28,[37,1],["leader","voter"],null]],null],"Active voter","Backup voter"]],[1,"\\n "],[13],[1,"\\n\\n "],[13],[1,"\\n"],[13],[1,"\\n\\n"]],["@item","&attrs"],false,["class-map","array","eq","and","not","or","includes","tooltip","if"]]',moduleName:"consul-ui/components/consul/server/card/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/server/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"L4k4YQfd",block:'[[[11,0],[16,0,[28,[37,0],["consul-server-list"],null]],[17,1],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,2],[[28,[37,2],[[30,2]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,3],[15,6,[28,[37,3],["dc.nodes.show",[30,3,["Name"]]],null]],[12],[1,"\\n "],[8,[39,4],null,[["@item"],[[30,3]]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n\\n"]],["&attrs","@items","item"],false,["class-map","each","-track-array","href-to","consul/server/card"]]',moduleName:"consul-ui/components/consul/server/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/service-identity/template/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"/FDJj0m3",block:'[[[41,[28,[37,1],["use partitions"],null],[[[1,"partition \\""],[1,[28,[35,2],[[30,1],"default"],null]],[1,"\\" {\\n"],[41,[28,[37,1],["use nspaces"],null],[[[1," namespace \\""],[1,[28,[35,2],[[30,2],"default"],null]],[1,"\\" {\\n service \\""],[1,[30,3]],[1,"\\" {\\n\\t policy = \\"write\\"\\n }\\n service \\""],[1,[30,3]],[1,"-sidecar-proxy\\" {\\n\\t policy = \\"write\\"\\n }\\n service_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n node_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n }\\n"]],[]],[[[1," service \\""],[1,[30,3]],[1,"\\" {\\n\\t policy = \\"write\\"\\n }\\n service \\""],[1,[30,3]],[1,"-sidecar-proxy\\" {\\n\\t policy = \\"write\\"\\n }\\n service_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n node_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n"]],[]]],[1,"}\\n"]],[]],[[[41,[28,[37,1],["use nspaces"],null],[[[1,"namespace \\""],[1,[28,[35,2],[[30,2],"default"],null]],[1,"\\" {\\n service \\""],[1,[30,3]],[1,"\\" {\\n\\t policy = \\"write\\"\\n }\\n service \\""],[1,[30,3]],[1,"-sidecar-proxy\\" {\\n\\t policy = \\"write\\"\\n }\\n service_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n node_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n}\\n"]],[]],[[[1,"service \\""],[1,[30,3]],[1,"\\" {\\n\\tpolicy = \\"write\\"\\n}\\nservice \\""],[1,[30,3]],[1,"-sidecar-proxy\\" {\\n\\tpolicy = \\"write\\"\\n}\\nservice_prefix \\"\\" {\\n\\tpolicy = \\"read\\"\\n}\\nnode_prefix \\"\\" {\\n\\tpolicy = \\"read\\"\\n}\\n"]],[]]]],[]]]],["@partition","@nspace","@name"],false,["if","can","or"]]',moduleName:"consul-ui/components/consul/service-identity/template/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/service-instance/list/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"MaR0UaLj",block:'[[[44,[[28,[37,1],[[30,1],"Service.Proxy.DestinationServiceID"],null]],[[[8,[39,2],[[24,0,"consul-service-instance-list"],[17,3]],[["@items"],[[30,4]]],[["default"],[[[[1,"\\n "],[8,[39,3],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,5],[[30,7],"dc.services.show"],null],[[[1," "],[10,3],[15,6,[28,[37,6],[[30,7],[30,5,["Service","Service"]]],null]],[12],[1,"\\n "],[1,[30,5,["Service","ID"]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,6,[28,[37,6],[[30,7],[30,5,["Service","Service"]],[30,5,["Node","Node"]],[28,[37,7],[[30,5,["Service","ID"]],[30,5,["Service","Service"]]],null]],null]],[12],[1,"\\n "],[1,[30,5,["Service","ID"]]],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,3],null,[["@name"],["details"]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,8],[[30,2],[30,5,["Service","ID"]]],null]],[[[44,[[28,[37,9],[[28,[37,10],[[30,5,["Checks"]],[28,[37,7],[[30,8,["Checks"]],[28,[37,10],null,null]],null]],null]],null]],[[[1,"\\n"],[41,[30,10],[[[1," "],[8,[39,11],null,[["@item"],[[30,5,["Service"]]]],null],[1,"\\n "],[8,[39,12],null,[["@type","@items"],["service",[28,[37,13],["ServiceID","",[30,9]],null]]],null],[1,"\\n"]],[]],[[[41,[51,[30,0,["areAllExternalSourcesMatching"]]],[[[1," "],[8,[39,11],null,[["@item"],[[30,5,["Service"]]]],null],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,12],null,[["@type","@items"],["service",[28,[37,13],["ServiceID","",[30,9]],null]]],null],[1,"\\n\\n"],[41,[51,[30,5,["Node","Meta","synthetic-node"]]],[[[1," "],[8,[39,12],null,[["@type","@items"],["node",[28,[37,15],["ServiceID","",[30,9]],null]]],null],[1,"\\n"]],[]],null]],[]]],[41,[30,8],[[[1," "],[10,"dl"],[14,0,"mesh"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n This service uses a proxy for the Consul service mesh\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n in service mesh with proxy\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,17],[[28,[37,18],[[30,10]],null],[28,[37,18],[[30,5,["Node","Meta","synthetic-node"]]],null]],null],[[[1," "],[10,"dl"],[14,0,"node"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n Node\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,3],[15,6,[28,[37,6],["dc.nodes.show",[30,5,["Node","Node"]]],null]],[12],[1,[30,5,["Node","Node"]]],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,5,["Service","Port"]],[[[1," "],[10,"dl"],[14,0,"address"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n IP Address and Port\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[41,[28,[37,19],[[30,5,["Service","Address"]],""],null],[[[1," "],[1,[30,5,["Service","Address"]]],[1,":"],[1,[30,5,["Service","Port"]]],[1,"\\n"]],[]],[[[1," "],[1,[30,5,["Node","Address"]]],[1,":"],[1,[30,5,["Service","Port"]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[41,[30,5,["Service","SocketPath"]],[[[1," "],[10,"dl"],[14,0,"socket"],[12],[1,"\\n "],[11,"dt"],[4,[38,16],null,null],[12],[1,"\\n Socket Path\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,5,["Service","SocketPath"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[]]],[1," "],[8,[39,20],null,[["@item"],[[30,5,["Service"]]]],null],[1,"\\n\\n"]],[9]]]],[8]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[5,6]]]]],[1,"\\n"]],[2]]]],["@proxies","proxies","&attrs","@items","item","index","@routeName","proxy","checks","@node"],false,["let","to-hash","list-collection","block-slot","if","eq","href-to","or","get","merge-checks","array","consul/external-source","consul/instance-checks","filter-by","unless","reject-by","tooltip","and","not","not-eq","tag-list"]]',moduleName:"consul-ui/components/consul/service-instance/list/index.hbs",isStrictMode:!1}) -class i extends l.default{get areAllExternalSourcesMatching(){var e,t,n -const l=null===(e=this.args.items[0])||void 0===e||null===(t=e.Service)||void 0===t||null===(n=t.Meta)||void 0===n?void 0:n["external-source"] -return this.args.items.every((e=>{var t,n -return(null===(t=e.Service)||void 0===t||null===(n=t.Meta)||void 0===n?void 0:n["external-source"])===l}))}}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/consul/service-instance/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"sxcYe4gj",block:'[[[8,[39,0],[[24,0,"consul-service-instance-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.service-instance.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.service-instance.search-bar.",[30,3,["status","key"]],".options.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n"],[41,[30,2,["searchproperty"]],[[[1," "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,10],null,[["@value","@selected"],[[30,11],[28,[37,10],[[30,11],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,11],[[30,11]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[11]],null]],[10]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,12,["Select"]],[[24,0,"type-status"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["status","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.consul.status"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,13,["Optgroup"]],[30,13,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["passing","warning","critical","empty"],null]],null]],null],null,[[[1," "],[8,[30,15],[[16,0,[29,["value-",[30,16]]]]],[["@value","@selected"],[[30,16],[28,[37,10],[[30,16],[30,2,["status","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[30,16]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,16]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[16]],null]],[14,15]]],[1," "]],[]]]]],[1,"\\n "]],[13]]]]],[1,"\\n"],[41,[28,[37,12],[[30,17,["length"]],0],null],[[[1," "],[8,[30,12,["Select"]],[[24,0,"type-source"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["source","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@components","@filter","@sources"],[[30,18],[30,2],[30,17]]],null],[1,"\\n "]],[18]]]]],[1,"\\n"]],[]],null],[1," "]],[12]],[[[1,"\\n "],[8,[30,19,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,20,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,14],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["Status:asc",[28,[37,2],["common.sort.status.asc"],null]],null],[28,[37,4],["Status:desc",[28,[37,2],["common.sort.status.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,15],[[30,22],[30,20,["value"]]],null]],[1,"\\n"]],[22]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,21,["Optgroup"]],[30,21,["Option"]]],[[[1," "],[8,[30,23],null,[["@label"],[[28,[37,2],["common.consul.status"],null]]],[["default"],[[[[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["Status:asc",[28,[37,16],["Status:asc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["Status:desc",[28,[37,16],["Status:desc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@label"],[[28,[37,2],["components.consul.service-instance.search-bar.sort.name.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["Name:asc",[28,[37,16],["Name:asc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["Name:desc",[28,[37,16],["Name:desc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[23,24]]],[1," "]],[]]]]],[1,"\\n "]],[21]]]]],[1,"\\n "]],[19]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Option","prop","search","components","Optgroup","Option","state","@sources","components","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","if","block-slot","each","-track-array","includes","lowercase","gt","consul/sources-select","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/service-instance/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/service/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"SaF5GIVw",block:'[[[8,[39,0],[[24,0,"consul-service-list"],[17,1]],[["@items","@linkable"],[[30,2],"linkable service"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"dl"],[15,0,[30,3,["MeshStatus"]]],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Health\\n "],[13],[1,"\\n "],[11,"dd"],[4,[38,2],[[30,3,["healthTooltipText"]]],null],[12],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,4],[[30,3,["InstanceCount"]],0],null],[[[1," "],[10,3],[15,6,[28,[37,5],["dc.services.show.index",[30,3,["Name"]]],[["params"],[[52,[28,[37,6],[[30,3,["Partition"]],[30,5]],null],[28,[37,7],null,[["partition","nspace","peer"],[[30,3,["Partition"]],[30,3,["Namespace"]],[30,3,["PeerName"]]]]],[28,[37,7],null,[["peer"],[[30,3,["PeerName"]]]]]]]]]],[12],[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,2],[12],[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@item"],[[30,3]]],null],[1,"\\n "],[8,[39,9],null,[["@item"],[[30,3]]],null],[1,"\\n"],[41,[28,[37,10],[[28,[37,6],[[30,3,["InstanceCount"]],0],null],[28,[37,10],[[28,[37,6],[[30,3,["Kind"]],"terminating-gateway"],null],[28,[37,6],[[30,3,["Kind"]],"ingress-gateway"],null]],null]],null],[[[1," "],[10,1],[12],[1,"\\n "],[1,[28,[35,11],[[30,3,["InstanceCount"]]],null]],[1,"\\n "],[1,[28,[35,12],[[30,3,["InstanceCount"]],"instance"],[["without-count"],[true]]]],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[51,[30,6]],[[[1," "],[8,[39,14],null,[["@item","@nspace","@partition"],[[30,3],[30,7],[30,5]]],null],[1,"\\n"]],[]],null],[41,[28,[37,15],[[30,3,["Kind"]],"terminating-gateway"],null],[[[1," "],[10,1],[12],[1,"\\n "],[1,[28,[35,11],[[30,3,["GatewayConfig","AssociatedServiceCount"]]],null]],[1,"\\n "],[1,[28,[35,12],[[30,3,["GatewayConfig","AssociatedServiceCount"]],"linked service"],[["without-count"],[true]]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[41,[28,[37,15],[[30,3,["Kind"]],"ingress-gateway"],null],[[[1," "],[10,1],[12],[1,"\\n "],[1,[28,[35,11],[[30,3,["GatewayConfig","AssociatedServiceCount"]]],null]],[1,"\\n "],[1,[28,[35,12],[[30,3,["GatewayConfig","AssociatedServiceCount"]],"upstream"],[["without-count"],[true]]]],[1,"\\n "],[13],[1,"\\n "]],[]],null]],[]]],[41,[28,[37,16],[[30,3,["ConnectedWithGateway"]],[30,3,["ConnectedWithProxy"]]],null],[[[1," "],[10,"dl"],[14,0,"mesh"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,2],null,null,[["default"],[[[[1,"\\n This service uses a proxy for the Consul service mesh\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,10],[[30,3,["ConnectedWithGateway"]],[30,3,["ConnectedWithProxy"]]],null],[[[1," "],[10,"dd"],[12],[1,"\\n in service mesh with proxy and gateway\\n "],[13],[1,"\\n"]],[]],[[[41,[30,3,["ConnectedWithProxy"]],[[[1," "],[10,"dd"],[12],[1,"\\n in service mesh with proxy\\n "],[13],[1,"\\n"]],[]],[[[41,[30,3,["ConnectedWithGateway"]],[[[1," "],[10,"dd"],[12],[1,"\\n in service mesh with gateway\\n "],[13],[1,"\\n "]],[]],null]],[]]]],[]]],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[8,[39,17],null,[["@item"],[[30,3]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4]]]]],[1,"\\n"]],["&attrs","@items","item","index","@partition","@isPeerDetail","@nspace"],false,["list-collection","block-slot","tooltip","if","gt","href-to","not-eq","hash","consul/kind","consul/external-source","and","format-number","pluralize","unless","consul/bucket/list","eq","or","tag-list"]]',moduleName:"consul-ui/components/consul/service/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/service/search-bar/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"K9snRb1g",block:'[[[8,[39,0],[[24,0,"consul-service-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.service.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.service.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-status"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["status","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.consul.status"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,0,["healthStates"]]],null]],null],null,[[[1," "],[8,[30,16],[[16,0,[29,["value-",[30,17]]]]],[["@value","@selected"],[[30,17],[28,[37,9],[[30,17],[30,2,["status","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[30,17]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,17]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "],[8,[30,13,["Select"]],null,[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["kind","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.service.search-bar.kind"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,18,["Optgroup"]],[30,18,["Option"]]],[[[1," "],[8,[30,20],null,[["@value","@selected"],["service",[28,[37,9],["service",[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],["common.consul.service"],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,19],null,[["@label"],[[28,[37,2],["common.consul.gateway"],null]]],[["default"],[[[[1,"\\n"],[42,[28,[37,8],[[28,[37,8],[[28,[37,4],["api-gateway","ingress-gateway","terminating-gateway","mesh-gateway"],null]],null]],null],null,[[[1," "],[8,[30,20],null,[["@value","@selected"],[[30,21],[28,[37,9],[[30,21],[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[30,21]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[21]],null],[1," "]],[]]]]],[1,"\\n "],[8,[30,19],null,[["@label"],[[28,[37,2],["common.consul.mesh"],null]]],[["default"],[[[[1,"\\n"],[42,[28,[37,8],[[28,[37,8],[[28,[37,4],["in-mesh","not-in-mesh"],null]],null]],null],null,[[[1," "],[8,[30,20],null,[["@value","@selected"],[[30,22],[28,[37,9],[[30,22],[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.search.",[30,22]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22]],null],[1," "]],[]]]]],[1,"\\n"]],[19,20]]],[1," "]],[]]]]],[1,"\\n "]],[18]]]]],[1,"\\n"],[41,[28,[37,12],[[30,23,["length"]],0],null],[[[1," "],[8,[30,13,["Select"]],[[24,0,"type-source"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["source","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@components","@filter","@sources"],[[30,24],[30,2],[30,0,["sortedSources"]]]],null],[1,"\\n "]],[24]]]]],[1,"\\n"]],[]],null],[1," "]],[13]],[[[1,"\\n "],[8,[30,25,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,26,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,14],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["Status:asc",[28,[37,2],["common.sort.status.asc"],null]],null],[28,[37,4],["Status:desc",[28,[37,2],["common.sort.status.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,15],[[30,28],[30,26,["value"]]],null]],[1,"\\n"]],[28]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,27,["Optgroup"]],[30,27,["Option"]]],[[[1," "],[8,[30,29],null,[["@label"],[[28,[37,2],["common.consul.status"],null]]],[["default"],[[[[1,"\\n "],[8,[30,30],null,[["@value","@selected"],["Status:asc",[28,[37,16],["Status:asc",[30,26,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,30],null,[["@value","@selected"],["Status:desc",[28,[37,16],["Status:desc",[30,26,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,29],null,[["@label"],[[28,[37,2],["common.consul.service-name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,30],null,[["@value","@selected"],["Name:asc",[28,[37,16],["Name:asc",[30,26,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,30],null,[["@value","@selected"],["Name:desc",[28,[37,16],["Name:desc",[30,26,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[29,30]]],[1," "]],[]]]]],[1,"\\n "]],[27]]]]],[1,"\\n "]],[25]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","state","components","Optgroup","Option","kind","state","@sources","components","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","if","gt","consul/sources-select","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/service/search-bar/index.hbs",isStrictMode:!1}) -class i extends l.default{get healthStates(){return this.args.peer?["passing","warning","critical","unknown","empty"]:["passing","warning","critical","empty"]}get sortedSources(){const e=this.args.sources||[] -return e.unshift(["consul"]),e.includes("consul-api-gateway")?[...e.filter((e=>"consul-api-gateway"!==e)),"consul-api-gateway"]:e}}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/consul/source/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"7cN0Jpki",block:'[[[10,"dl"],[14,0,"tooltip-panel"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[10,1],[14,0,"consul-source"],[12],[1,"\\n "],[1,[30,1]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,0],null,[["@position"],["left"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],["components.consul.source.header"],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,"role","separator"],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.source.menu-title"],null]],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[14,"role","none"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[29,[[28,[37,3],["CONSUL_DOCS_URL"],null],"/connect/l7-traffic"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.source.links.documentation"],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n\\n"]],["@source"],false,["menu-panel","block-slot","t","env"]]',moduleName:"consul-ui/components/consul/source/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/sources-select/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"xQqOlkTv",block:'[[[41,[28,[37,1],[[30,1,["length"]],0],null],[[[1," "],[8,[39,2],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,3],["common.search.source"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,2],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["Option"]]],[[[42,[28,[37,6],[[28,[37,6],[[30,1]],null]],null],null,[[[44,[[28,[37,7],[[30,4]],null]],[[[1," "],[8,[30,3],[[16,0,[52,[51,[30,5]],[30,4]]]],[["@value","@selected"],[[30,4],[28,[37,9],[[30,4],[30,6,["source","value"]]],null]]],[["default"],[[[[1,"\\n"],[41,[30,5],[[[1," "],[8,[39,10],[[24,0,"mr-2.5"]],[["@name"],[[30,5]]],null],[1,"\\n"]],[]],null],[1," "],[1,[28,[35,3],[[28,[37,11],["common.brand.",[30,4]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[5]]]],[4]],null]],[3]]],[1," "]],[]]]]],[1,"\\n"]],[]],null]],["@sources","@components","Option","source","flightIcon","@filter"],false,["if","gt","block-slot","t","let","each","-track-array","icon-mapping","unless","includes","flight-icon","concat"]]',moduleName:"consul-ui/components/consul/sources-select/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/token/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"nhK5HxA8",block:'[[[8,[39,0],[[24,0,"consul-token-list"]],[["@items"],[[30,1]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],[[30,2,["AccessorID"]],[30,3,["AccessorID"]]],null],[[[1," "],[10,"dl"],[14,"rel","me"],[12],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,4],null,[["@position"],["top-start"]],[["default"],[[[[1,"\\n Your token\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[10,3],[15,6,[28,[37,5],["dc.acls.tokens.edit",[30,2,["AccessorID"]]],null]],[12],[1,[28,[35,6],[[30,2,["AccessorID"]],-8],null]],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Scope"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[52,[30,2,["Local"]],"local","global"]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,7],null,[["@item"],[[30,2]]],null],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,8],[[30,2,["Description"]],[30,2,["Name"]]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[30,2,["hasSecretID"]],[[[1," "],[8,[39,9],null,[["@value","@name"],[[30,2,["SecretID"]],[28,[37,10],["components.consul.token.secretID"],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,10],["components.consul.token.secretID"],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "],[8,[30,4],null,null,[["default"],[[[[1,"\\n "],[8,[30,5],null,[["@href"],[[28,[37,5],["dc.acls.tokens.edit",[30,2,["AccessorID"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n"],[41,[28,[37,11],["write token"],[["item"],[[30,2]]]],[[[1," Edit\\n"]],[]],[[[1," View\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,11],["duplicate token"],[["item"],[[30,2]]]],[[[1," "],[8,[30,5],null,[["@onclick"],[[28,[37,12],[[30,0],[30,6],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Duplicate\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1,"\\n"],[41,[28,[37,3],[[30,2,["AccessorID"]],[33,13,["AccessorID"]]],null],[[[1," "],[8,[30,5],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,12],[[30,0],[30,7],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Logout\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,8],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm logout\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to stop using this ACL token? This will log you out.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,9],null,null,[["default"],[[[[1,"Logout"]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[30,5],null,[["@onclick"],[[28,[37,12],[[30,0],[30,10],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Use\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,11],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm use\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to use this ACL token?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,12],null,null,[["default"],[[[[1,"Use"]],[]]]]],[1,"\\n "]],[12]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[11]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1,"\\n\\n"],[41,[28,[37,11],["delete token"],[["item","token"],[[30,2],[30,3]]]],[[[1," "],[8,[30,5],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,12],[[30,0],[30,13],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,14],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this token?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,15],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[15]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1,"\\n "]],[5]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[2]]]]]],["@items","item","@token","Actions","Action","@onclone","@onlogout","Confirmation","Confirm","@onuse","Confirmation","Confirm","@ondelete","Confirmation","Confirm"],false,["list-collection","block-slot","if","eq","tooltip","href-to","substr","consul/token/ruleset/list","or","copy-button","t","can","action","token"]]',moduleName:"consul-ui/components/consul/token/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/token/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"cW0yM/IH",block:'[[[41,[28,[37,1],[[30,1],"create"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," The token has been added.\\n"]],[]],[[[1," There was an error adding the token.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"update"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," The token has been saved.\\n"]],[]],[[[1," There was an error saving the token.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"delete"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," The token was deleted.\\n"]],[]],[[[1," There was an error deleting the token.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"clone"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," The token has been cloned as "],[1,[28,[35,2],[[30,3,["AccessorID"]],8,false],null]],[1,"\\n"]],[]],[[[1," There was an error cloning the token.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"use"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," You are now using the new ACL token\\n"]],[]],[[[1," There was an error using that ACL token.\\n"]],[]]]],[]],null]],[]]]],[]]]],[]]]],[]]],[44,[[30,4,["errors","firstObject"]]],[[[41,[30,5,["detail"]],[[[1," "],[10,"br"],[12],[13],[1,[28,[35,4],["(",[52,[30,5,["status"]],[28,[37,4],[[30,5,["status"]],": "],null]],[30,5,["detail"]],")"],null]],[1,"\\n"]],[]],null]],[5]]]],["@type","@status","@item","@error","error"],false,["if","eq","truncate","let","concat"]]',moduleName:"consul-ui/components/consul/token/notifications/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/token/ruleset/list/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"z6qiUtoK",block:'[[[44,[[28,[37,1],[[28,[37,2],[[33,3,["Policies"]],[33,3,["ACLs","PolicyDefaults"]],[28,[37,4],null,null]],null]],null]],[[[44,[[28,[37,5],[[30,1],"management"],null]],[[[41,[28,[37,7],[[30,2,["length"]],0],null],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Management\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[42,[28,[37,9],[[28,[37,9],[[28,[37,5],[[30,1],"management"],null]],null]],null],null,[[[1," "],[10,1],[15,0,[28,[37,10],[[30,3]],null]],[12],[1,[30,3,["Name"]]],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[2]]],[44,[[28,[37,5],[[30,1],"identities"],null]],[[[41,[28,[37,7],[[30,4,["length"]],0],null],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Identities"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[42,[28,[37,9],[[28,[37,9],[[30,4]],null]],null],null,[[[1," "],[10,1],[15,0,[28,[37,10],[[30,5]],null]],[12],[1,[30,5,["Name"]]],[13],[1,"\\n"]],[5]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[4]]],[41,[28,[37,11],[[33,3]],null],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Rules"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n Legacy tokens have embedded rules.\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[44,[[28,[37,12],[[28,[37,5],[[30,1],"policies"],null],[28,[37,2],[[33,3,["Roles"]],[33,3,["ACLs","RoleDefaults"]],[28,[37,4],null,null]],null]],null]],[[[41,[28,[37,7],[[30,6,["length"]],0],null],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Rules"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[42,[28,[37,9],[[28,[37,9],[[30,6]],null]],null],null,[[[1," "],[10,1],[15,0,[28,[37,10],[[30,7]],null]],[12],[1,[30,7,["Name"]]],[13],[1,"\\n"]],[7]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[6]]]],[]]]],[1]]]],["policies","management","item","identities","item","policies","item"],false,["let","policy/group","or","item","array","get","if","gt","each","-track-array","policy/typeof","token/is-legacy","append"]]',moduleName:"consul-ui/components/consul/token/ruleset/list/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) -e.default=r})),define("consul-ui/components/consul/token/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"81pOiVwr",block:'[[[8,[39,0],[[24,0,"consul-token-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.token.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.token.search-bar.",[30,3,["status","key"]],".options.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-status"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["kind","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.token.search-bar.kind.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[28,[37,4],["global-management","global","local"],null]],null]],null],null,[[[1," "],[8,[30,16],[[16,0,[29,["value-",[30,17]]]]],[["@value","@selected"],[[30,17],[28,[37,9],[[30,17],[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.token.search-bar.kind.options.",[30,17]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,17]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,18,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,19,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["CreateTime:desc",[28,[37,2],["common.sort.age.desc"],null]],null],[28,[37,4],["CreateTime:asc",[28,[37,2],["common.sort.age.asc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,21],[30,19,["value"]]],null]],[1,"\\n"]],[21]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,20,["Optgroup"]],[30,20,["Option"]]],[[[1," "],[8,[30,22],null,[["@label"],[[28,[37,2],["common.ui.creation"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["CreateTime:desc",[28,[37,13],["CreateTime:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.age.desc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["CreateTime:asc",[28,[37,13],["CreateTime:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.age.asc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22,23]]],[1," "]],[]]]]],[1,"\\n "]],[20]]]]],[1,"\\n "]],[18]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","state","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/token/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/token/selector/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object"],(function(e,t,n,l,r){var i -function o(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const a=(0,n.createTemplateFactory)({id:"TUgK5bUH",block:'[[[41,[28,[37,1],["use acls"],null],[[[1," "],[10,"li"],[12],[1,"\\n\\n "],[8,[39,2],null,[["@src","@sink","@onchange"],[[28,[37,3],["settings://consul:token"],null],[28,[37,3],["settings://consul:token"],null],[30,0,["reauthorize"]]]],[["unauthorized","authorized"],[[[[1,"\\n "],[8,[39,4],null,[["@target"],["app-before-skip-links"]],[["default"],[[[[1,"\\n "],[8,[39,5],[[4,[38,6],["click",[28,[37,7],[[30,0,["modal","open"]]],null]],null]],null,[["default"],[[[[1,"\\n Login\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],[[4,[38,6],["click",[28,[37,7],[[30,0,["modal","open"]]],null]],null]],null,[["default"],[[[[1,"\\n Log in\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name","@onclose","@onopen","@aria"],["login-toggle",[30,0,["close"]],[30,0,["open"]],[28,[37,9],null,[["label"],["Log in to Consul"]]]]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@target","@name","@value"],[[30,0],"modal",[30,2]]],null],[1,"\\n "],[8,[39,11],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n Log in to Consul\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,11],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@dc","@partition","@nspace","@onsubmit"],[[30,3,["Name"]],[30,4],[30,5],[28,[37,5],[[30,0],[30,1,["login"]]],[["value"],["data"]]]]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@target","@name","@value"],[[30,0],"authForm",[30,6]]],null],[1,"\\n"],[41,[28,[37,1],["use SSO"],null],[[[1," "],[8,[30,6,["Method"]],null,[["@matches"],["sso"]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@dc","@partition","@nspace","@disabled","@onchange","@onerror"],[[30,3,["Name"]],[30,4],[30,5],[30,6,["disabled"]],[30,6,["submit"]],[30,6,["error"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,11],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,14],[[4,[38,6],["click",[30,2,["close"]]],null]],[["@color","@text"],["secondary","Continue without logging in"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n "]],[1]],[[[1,"\\n "],[8,[39,8],null,[["@name","@onclose","@onopen","@aria"],["login-toggle",[30,0,["close"]],[30,0,["open"]],[28,[37,9],null,[["label"],["Log in with a different token"]]]]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@target","@name","@value"],[[30,0],"modal",[30,8]]],null],[1,"\\n "],[8,[39,11],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n Log in with a different token\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,11],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@dc","@nspace","@partition","@onsubmit"],[[30,3,["Name"]],[30,5],[30,4],[28,[37,5],[[30,0],[30,7,["login"]]],[["value"],["data"]]]]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@target","@name","@value"],[[30,0],"authForm",[30,9]]],null],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,11],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,14],[[4,[38,6],["click",[30,8,["close"]]],null]],[["@color","@text"],["secondary","Continue without logging in"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "],[8,[39,4],null,[["@target"],["app-before-skip-links"]],[["default"],[[[[1,"\\n "],[8,[39,5],[[4,[38,6],["click",[28,[37,7],[[30,7,["logout"]]],null]],null]],null,[["default"],[[[[1,"\\n Logout\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,15],null,null,[["default"],[[[[1,"\\n "],[8,[30,10,["Action"]],[[4,[38,6],["click",[30,10,["toggle"]]],null]],null,[["default"],[[[[1,"\\n Logout\\n "]],[]]]]],[1,"\\n "],[8,[30,10,["Menu"]],null,null,[["default"],[[[[1,"\\n"],[41,[30,7,["token","AccessorID"]],[[[1," "],[8,[39,16],null,[["@item"],[[30,7,["token"]]]],null],[1,"\\n"]],[]],null],[1," "],[8,[30,11,["Menu"]],null,null,[["default"],[[[[1,"\\n "],[8,[30,12,["Separator"]],null,null,null],[1,"\\n "],[8,[30,12,["Item"]],[[24,0,"dangerous"]],null,[["default"],[[[[1,"\\n "],[8,[30,12,["Action"]],[[4,[38,6],["click",[28,[37,7],[[30,7,["logout"]]],null]],null]],null,[["default"],[[[[1,"\\n Logout\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[12]]]]],[1,"\\n "]],[11]]]]],[1,"\\n "]],[10]]]]],[1,"\\n "]],[7]]]]],[1,"\\n\\n "],[13],[1,"\\n"],[18,13,[[28,[37,9],null,[["open","close"],[[30,0,["modal","open"]],[30,0,["model","close"]]]]]]],[1,"\\n"]],[]],null],[1,"\\n"]],["authDialog","modal","@dc","@partition","@nspace","authForm","authDialog","modal","authForm","disclosure","panel","menu","&default"],false,["if","can","auth-dialog","uri","portal","action","on","optional","modal-dialog","hash","ref","block-slot","auth-form","oidc-select","hds/button","disclosure-menu","auth-profile","yield"]]',moduleName:"consul-ui/components/consul/token/selector/index.hbs",isStrictMode:!1}) -let u=(o((i=class extends l.default{open(){this.authForm.focus()}close(){this.authForm.reset()}reauthorize(e){this.modal.close(),this.args.onchange(e)}}).prototype,"open",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"open"),i.prototype),o(i.prototype,"close",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"close"),i.prototype),o(i.prototype,"reauthorize",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"reauthorize"),i.prototype),i) -e.default=u,(0,t.setComponentTemplate)(a,u)})),define("consul-ui/components/consul/tomography/graph/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking"],(function(e,t,n,l,r){var i,o -function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const u=(0,n.createTemplateFactory)({id:"ZXa/jDY4",block:'[[[11,0],[24,0,"tomography-graph"],[17,1],[12],[1,"\\n "],[10,"svg"],[15,"width",[30,0,["size"]]],[15,"height",[30,0,["size"]]],[12],[1,"\\n "],[10,"g"],[15,"transform",[29,["translate(",[28,[37,0],[[30,0,["size"]],2],null],", ",[28,[37,0],[[30,0,["size"]],2],null],")"]]],[12],[1,"\\n "],[10,"g"],[12],[1,"\\n "],[10,"circle"],[14,0,"background"],[15,"r",[30,0,["circle","0"]]],[12],[13],[1,"\\n "],[10,"circle"],[14,0,"axis"],[15,"r",[30,0,["circle","1"]]],[12],[13],[1,"\\n "],[10,"circle"],[14,0,"axis"],[15,"r",[30,0,["circle","2"]]],[12],[13],[1,"\\n "],[10,"circle"],[14,0,"axis"],[15,"r",[30,0,["circle","3"]]],[12],[13],[1,"\\n "],[10,"circle"],[14,0,"border"],[15,"r",[30,0,["circle","4"]]],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[14,0,"lines"],[12],[1,"\\n"],[42,[28,[37,2],[[28,[37,2],[[30,0,["distances"]]],null]],null],null,[[[1," "],[11,"rect"],[16,"transform",[29,["rotate(",[30,2,["rotate"]],")"]]],[16,"width",[30,2,["y2"]]],[24,"height","1"],[4,[38,3],[[28,[37,4],[[30,2,["node"]]," - ",[28,[37,5],[[30,2,["distance"]]],[["maximumFractionDigits"],[2]]],"ms",[52,[30,2,["segment"]],[28,[37,4],["
      (Segment: ",[30,2,["segment"]],")"],null]]],null]],[["options"],[[28,[37,7],null,[["followCursor","allowHTML"],[true,true]]]]]],[12],[13],[1,"\\n"]],[2]],null],[1," "],[13],[1,"\\n "],[10,"g"],[14,0,"labels"],[12],[1,"\\n "],[10,"circle"],[14,0,"point"],[14,"r","5"],[12],[13],[1,"\\n "],[10,"g"],[14,0,"tick"],[15,"transform",[29,["translate(0, ",[30,0,["labels","0"]],")"]]],[12],[1,"\\n "],[10,"line"],[14,"x2","70"],[12],[13],[1,"\\n "],[10,"text"],[14,"x","75"],[14,"y","0"],[14,"dy",".32em"],[12],[1,[28,[35,5],[[30,0,["milliseconds","0"]]],[["maximumFractionDigits"],[2]]]],[1,"ms"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[14,0,"tick"],[15,"transform",[29,["translate(0, ",[30,0,["labels","1"]],")"]]],[12],[1,"\\n "],[10,"line"],[14,"x2","70"],[12],[13],[1,"\\n "],[10,"text"],[14,"x","75"],[14,"y","0"],[14,"dy",".32em"],[12],[1,[28,[35,5],[[30,0,["milliseconds","1"]]],[["maximumFractionDigits"],[2]]]],[1,"ms"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[14,0,"tick"],[15,"transform",[29,["translate(0, ",[30,0,["labels","2"]],")"]]],[12],[1,"\\n "],[10,"line"],[14,"x2","70"],[12],[13],[1,"\\n "],[10,"text"],[14,"x","75"],[14,"y","0"],[14,"dy",".32em"],[12],[1,[28,[35,5],[[30,0,["milliseconds","2"]]],[["maximumFractionDigits"],[2]]]],[1,"ms"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[14,0,"tick"],[15,"transform",[29,["translate(0, ",[30,0,["labels","3"]],")"]]],[12],[1,"\\n "],[10,"line"],[14,"x2","70"],[12],[13],[1,"\\n "],[10,"text"],[14,"x","75"],[14,"y","0"],[14,"dy",".32em"],[12],[1,[28,[35,5],[[30,0,["milliseconds","3"]]],[["maximumFractionDigits"],[2]]]],[1,"ms"],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs","item"],false,["div","each","-track-array","tooltip","concat","format-number","if","hash"]]',moduleName:"consul-ui/components/consul/tomography/graph/index.hbs",isStrictMode:!1}),s=function(e){return 160*e} -let c=(i=class extends l.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="max",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a(this,"size",336),a(this,"circle",[s(1),s(.25),s(.5),s(.75),s(1)]),a(this,"labels",[s(-.25),s(-.5),s(-.75),s(-1)])}get milliseconds(){const e=(this.args.distances||[]).reduce(((e,t)=>Math.max(e,t.distance)),this.max) -return[25,50,75,100].map((t=>function(e,t){return t>0?parseInt(t*e)/100:0}(t,e)))}get distances(){let e=this.args.distances||[] -const t=e.reduce(((e,t)=>Math.max(e,t.distance)),this.max),n=e.length -if(n>360){const t=360/n -e=e.filter((function(e,l){return 0==l||l==n-1||Math.random()({rotate:360*l/e.length,y2:n.distance/t*160,node:n.node,distance:n.distance,segment:n.segment})))}},d=i.prototype,p="max",f=[r.tracked],m={configurable:!0,enumerable:!0,writable:!0,initializer:function(){return-999999999}},b={},Object.keys(m).forEach((function(e){b[e]=m[e]})),b.enumerable=!!b.enumerable,b.configurable=!!b.configurable,("value"in b||b.initializer)&&(b.writable=!0),b=f.slice().reverse().reduce((function(e,t){return t(d,p,e)||e}),b),h&&void 0!==b.initializer&&(b.value=b.initializer?b.initializer.call(h):void 0,b.initializer=void 0),void 0===b.initializer&&(Object.defineProperty(d,p,b),b=null),o=b,i) -var d,p,f,m,h,b -e.default=c,(0,t.setComponentTemplate)(u,c)})),define("consul-ui/components/consul/transparent-proxy/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"UjBsOCBt",block:'[[[10,1],[14,0,"consul-transparent-proxy"],[12],[1,"\\n "],[1,[28,[35,0],["components.consul.transparent-proxy"],null]],[1,"\\n"],[13]],[],false,["t"]]',moduleName:"consul-ui/components/consul/transparent-proxy/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/upstream-instance/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"GEohwFqk",block:'[[[11,0],[24,0,"consul-upstream-instance-list"],[17,1],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,1],[[28,[37,1],[[30,2]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n\\n "],[10,0],[14,0,"header"],[12],[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[30,3,["DestinationName"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[10,0],[14,0,"detail"],[12],[1,"\\n\\n"],[41,[28,[37,3],[[30,3,["DestinationType"]],"prepared_query"],null],[[[1," "],[8,[39,4],null,[["@item","@partition","@nspace"],[[28,[37,5],null,[["Namespace","Partition"],[[28,[37,6],[[30,3,["DestinationNamespace"]],[30,4]],null],[28,[37,6],[[30,3,["DestinationPartition"]],[30,5]],null]]]],[30,5],[30,4]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[41,[28,[37,7],[[28,[37,3],[[30,3,["Datacenter"]],[30,6]],null],[28,[37,3],[[30,3,["Datacenter"]],""],null]],null],[[[1," "],[10,"dl"],[14,0,"datacenter"],[12],[1,"\\n "],[11,"dt"],[4,[38,8],null,null],[12],[1,"\\n Datacenter\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Datacenter"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1,"\\n"],[41,[30,3,["LocalBindSocketPath"]],[[[1," "],[10,"dl"],[14,0,"local-bind-socket-path"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Local bind socket path\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,3,["LocalBindSocketPath"]],"Local bind socket path"]],null],[1,"\\n "],[1,[30,3,["LocalBindSocketPath"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[14,0,"local-bind-socket-mode"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Mode\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,6],[[30,3,["LocalBindSocketMode"]],"-"],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1,"\\n"],[41,[28,[37,10],[[30,3,["LocalBindPort"]],0],null],[[[44,[[28,[37,12],[[28,[37,6],[[30,3,["LocalBindAddress"]],"127.0.0.1"],null],":",[30,3,["LocalBindPort"]]],null]],[[[1," "],[10,"dl"],[14,0,"local-bind-address"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Address\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,7],"Address"]],null],[1,"\\n "],[1,[30,7]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[7]]]],[]],null],[1,"\\n"]],[]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@items","item","@nspace","@partition","@dc","combinedAddress"],false,["each","-track-array","if","not-eq","consul/bucket/list","hash","or","and","tooltip","copy-button","gt","let","concat"]]',moduleName:"consul-ui/components/consul/upstream-instance/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/upstream-instance/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"wsZfd7L1",block:'[[[8,[39,0],[[24,0,"consul-upstream-instance-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.upstream-instance.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.upstream-instance.search-bar.",[30,3,["status","value"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,14,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["DestinationName:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["DestinationName:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,16],[30,14,["value"]]],null]],[1,"\\n"]],[16]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,15,["Optgroup"]],[30,15,["Option"]]],[[[1," "],[8,[30,18],null,[["@value","@selected"],["DestinationName:asc",[28,[37,13],["DestinationName:asc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["DestinationName:desc",[28,[37,13],["DestinationName:desc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n"]],[17,18]]],[1," "]],[]]]]],[1,"\\n "]],[15]]]]],[1,"\\n "]],[13]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/upstream-instance/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/upstream/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"eZNZsVXh",block:'[[[8,[39,0],[[24,0,"consul-upstream-list"],[17,1]],[["@items","@linkable"],[[30,2],"linkable upstream"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],[[30,3,["InstanceCount"]],0],null],[[[1," "],[10,"dl"],[15,0,[30,3,["MeshStatus"]]],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Health\\n "],[13],[1,"\\n "],[11,"dd"],[4,[38,4],null,null],[12],[1,"\\n"],[41,[28,[37,5],["critical",[30,3,["MeshStatus"]]],null],[[[1," At least one health check on one instance is failing.\\n"]],[]],[[[41,[28,[37,5],["warning",[30,3,["MeshStatus"]]],null],[[[1," At least one health check on one instance has a warning.\\n"]],[]],[[[41,[28,[37,5],["passing",[30,3,["MeshStatus"]]],null],[[[1," All health checks are passing.\\n"]],[]],[[[1," There are no health checks.\\n "]],[]]]],[]]]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,3],[15,6,[28,[37,6],["dc.services.show",[30,3,["Name"]]],[["params"],[[52,[28,[37,7],[[30,3,["Partition"]],[30,5]],null],[28,[37,8],null,[["partition","nspace"],[[30,3,["Partition"]],[30,3,["Namespace"]]]]],[52,[28,[37,7],[[30,3,["Namespace"]],[30,6]],null],[28,[37,8],null,[["nspace"],[[30,3,["Namespace"]]]]],[28,[37,8],null,null]]]]]]],[12],[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,2],[12],[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[8,[39,9],null,[["@item","@nspace","@partition"],[[30,3],[30,6],[30,5]]],null],[1,"\\n"],[42,[28,[37,11],[[28,[37,11],[[30,3,["GatewayConfig","Addresses"]]],null]],null],null,[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Address\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,12],null,[["@value","@name"],[[30,7],"Address"]],null],[1,"\\n "],[1,[30,7]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[7]],null],[1," "]],[]]]]],[1,"\\n"]],[3,4]]]]],[1,"\\n"]],["&attrs","@items","item","index","@partition","@nspace","address"],false,["list-collection","block-slot","if","gt","tooltip","eq","href-to","not-eq","hash","consul/bucket/list","each","-track-array","copy-button"]]',moduleName:"consul-ui/components/consul/upstream/list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/consul/upstream/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"t4tLfZqU",block:'[[[8,[39,0],[[24,0,"consul-upstream-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.upstream.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.upstream.search-bar.",[30,3,["status","value"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],null,[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["instance","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.upstream.search-bar.instance.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[28,[37,4],["registered","not-registered"],null]],null]],null],null,[[[1," "],[8,[30,16],null,[["@value","@selected"],[[30,17],[28,[37,9],[[30,17],[30,2,["instance","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[30,17]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,18,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,19,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["Status:asc",[28,[37,2],["common.sort.status.asc"],null]],null],[28,[37,4],["Status:desc",[28,[37,2],["common.sort.status.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,21],[30,19,["value"]]],null]],[1,"\\n"]],[21]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,20,["Optgroup"]],[30,20,["Option"]]],[[[1," "],[8,[30,22],null,[["@label"],[[28,[37,2],["common.consul.status"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Status:asc",[28,[37,13],["Status:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Status:desc",[28,[37,13],["Status:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,22],null,[["@label"],[[28,[37,2],["common.consul.service-name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Name:asc",[28,[37,13],["Name:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Name:desc",[28,[37,13],["Name:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22,23]]],[1," "]],[]]]]],[1,"\\n "]],[20]]]]],[1,"\\n "]],[18]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","item","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/upstream/search-bar/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/copy-button/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={id:"copy-button",initial:"idle",on:{RESET:[{target:"idle"}]},states:{idle:{on:{SUCCESS:[{target:"success"}],ERROR:[{target:"error"}]}},success:{},error:{}}}})),define("consul-ui/components/copy-button/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","consul-ui/components/copy-button/chart.xstate"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i=(0,n.createTemplateFactory)({id:"6RaQJr4m",block:'[[[8,[39,0],null,[["@src"],[[30,0,["chart"]]]],[["default"],[[[[1,"\\n "],[11,0],[24,0,"copy-button"],[17,6],[12],[1,"\\n"],[44,[[28,[37,2],[[30,4],"SUCCESS"],null],[28,[37,2],[[30,4],"ERROR"],null],[28,[37,2],[[30,4],"RESET"],null]],[[[1," "],[11,"button"],[16,"aria-label",[28,[37,3],["components.copy-button.title"],[["name"],[[30,10]]]]],[24,4,"button"],[24,0,"copy-btn"],[17,6],[4,[38,4],[[30,11]],[["success","error"],[[30,7],[30,8]]]],[4,[38,5],[[52,[28,[37,7],[[30,5],"success"],null],[28,[37,3],["components.copy-button.success"],[["name"],[[30,10]]]],[28,[37,3],["components.copy-button.error"],null]]],[["options"],[[28,[37,8],null,[["trigger","showOnCreate","delay","onHidden"],["manual",[28,[37,9],[[28,[37,7],[[30,5],"idle"],null]],null],[28,[37,10],[0,3000],null],[30,9]]]]]]],[12],[18,12,null],[13],[1,"\\n"]],[7,8,9]]],[1," "],[13],[1,"\\n"]],[1,2,3,4,5]]]]],[1,"\\n"]],["State","Guard","Action","dispatch","state","&attrs","success","error","reset","@name","@value","&default"],false,["state-chart","let","fn","t","with-copyable","tooltip","if","state-matches","hash","not","array","yield"]]',moduleName:"consul-ui/components/copy-button/index.hbs",isStrictMode:!1}) -class o extends l.default{constructor(){super(...arguments),this.chart=r.default}}e.default=o,(0,t.setComponentTemplate)(i,o)})),define("consul-ui/components/copyable-code/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"Q8iW7hMH",block:'[[[11,0],[16,0,[28,[37,0],["copyable-code",[28,[37,1],["obfuscated",[30,1]],null]],null]],[17,2],[12],[1,"\\n"],[41,[30,1],[[[1," "],[8,[39,3],null,null,[["default"],[[[[1,"\\n "],[8,[30,3,["Action"]],[[16,"aria-label",[52,[33,4,["expanded"]],"Hide","Show"]],[4,[38,5],["click",[30,3,["toggle"]]],null]],null,[["default"],[[[[1,"\\n\\n "]],[]]]]],[1,"\\n "],[8,[30,3,["Details"]],null,null,[["default"],[[[[1,"\\n "],[10,"pre"],[12],[10,"code"],[15,1,[30,4,["id"]]],[12],[1,[30,5]],[13],[13],[1,"\\n "]],[4]]]]],[1,"\\n "],[8,[30,3,["Details"]],null,[["@auto"],[false]],[["default"],[[[[1,"\\n"],[41,[28,[37,6],[[30,6,["expanded"]]],null],[[[1," "],[10,"hr"],[12],[13],[1,"\\n"]],[]],null],[1," "]],[6]]]]],[1,"\\n "]],[3]]]]],[1,"\\n\\n "],[8,[39,7],null,[["@value","@name"],[[30,5],[30,7]]],null],[1,"\\n\\n"]],[]],[[[1," "],[10,"pre"],[12],[10,"code"],[12],[1,[30,5]],[13],[13],[1,"\\n "],[8,[39,7],null,[["@value","@name"],[[30,5],[30,7]]],null],[1,"\\n"]],[]]],[1,"\\n"],[13]],["@obfuscated","&attrs","disclosure","details","@value","details","@name"],false,["class-map","array","if","disclosure","details","on","not","copy-button"]]',moduleName:"consul-ui/components/copyable-code/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/data-collection/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/object","@ember/object/computed","@glimmer/tracking"],(function(e,t,n,l,r,i,o,a){var u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j -function _(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function k(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const S=(0,n.createTemplateFactory)({id:"2flQHkul",block:'[[[1,[28,[35,0],[[28,[37,1],[[30,0],[28,[37,2],[[28,[37,3],[[30,0],"term"],null],""],null],[30,1]],null]],null]],[1,"\\n"],[18,2,[[28,[37,5],null,[["search","items","Collection","Empty"],[[28,[37,1],[[30,0],[30,0,["search"]]],null],[30,0,["items"]],[52,[28,[37,7],[[30,0,["items","length"]],0],null],[50,"anonymous",0,null,null],""],[52,[28,[37,9],[[30,0,["items","length"]],0],null],[50,"anonymous",0,null,null],""]]]]]],[1,"\\n"]],["@search","&default"],false,["did-update","action","fn","set","yield","hash","if","gt","component","eq"]]',moduleName:"consul-ui/components/data-collection/index.hbs",isStrictMode:!1}) -let N=(u=(0,r.inject)("filter"),s=(0,r.inject)("sort"),c=(0,r.inject)("search"),d=(0,o.alias)("searchService.searchables"),p=(0,i.computed)("term","args.search"),f=(0,i.computed)("type","searchMethod","filtered","args.filters"),m=(0,i.computed)("type","args.sort"),h=(0,i.computed)("comparator","searched"),b=(0,i.computed)("searchTerm","searchable","filtered"),y=(0,i.computed)("type","content","args.filters"),g=(0,i.computed)("args.{items.[],items.content.[]}"),v=class extends l.default{constructor(){super(...arguments),_(this,"filter",O,this),_(this,"sort",P,this),_(this,"searchService",x,this),_(this,"term",w,this),_(this,"searchableMap",j,this)}get type(){return this.args.type}get searchMethod(){return this.args.searchable||"exact"}get searchProperties(){return this.args.filters.searchproperties}get searchTerm(){return this.term||this.args.search||""}get searchable(){const e=(0,i.get)(this,"args.filters.searchproperty.value")||(0,i.get)(this,"args.filters.searchproperty") -return new("string"==typeof this.searchMethod?this.searchableMap[this.searchMethod]:this.args.searchable)(this.filtered,{finders:Object.fromEntries(Object.entries(this.searchService.predicate(this.type)).filter((t=>{let[n,l]=t -return void 0===e||e.includes(n)})))})}get comparator(){return void 0===this.args.sort?[]:this.sort.comparator(this.type)(this.args.sort)}get items(){let e="comparator" -return"function"==typeof this.comparator&&(e=this.comparator),(0,i.defineProperty)(this,"sorted",(0,o.sort)("searched",e)),this.sorted}get searched(){return""===this.searchTerm?this.filtered:this.searchable.search(this.searchTerm)}get filtered(){if(void 0===this.args.filters)return this.content.slice() -const e=this.filter.predicate(this.type) -if(void 0===e)return this.content.slice() -const t=Object.entries(this.args.filters).filter((e=>{let[t,n]=e -return Boolean(n)})).map((e=>{let[t,n]=e -return[t,"string"!=typeof n?n.value:n]})) -return this.content.filter(e(Object.fromEntries(t)))}get content(){const e=this.args.items||[] -return"function"==typeof e.dispatchEvent?e.content:e}search(e){return this.term=e,this.items}},O=k(v.prototype,"filter",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=k(v.prototype,"sort",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=k(v.prototype,"searchService",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=k(v.prototype,"term",[a.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return""}}),j=k(v.prototype,"searchableMap",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k(v.prototype,"searchTerm",[p],Object.getOwnPropertyDescriptor(v.prototype,"searchTerm"),v.prototype),k(v.prototype,"searchable",[f],Object.getOwnPropertyDescriptor(v.prototype,"searchable"),v.prototype),k(v.prototype,"comparator",[m],Object.getOwnPropertyDescriptor(v.prototype,"comparator"),v.prototype),k(v.prototype,"items",[h],Object.getOwnPropertyDescriptor(v.prototype,"items"),v.prototype),k(v.prototype,"searched",[b],Object.getOwnPropertyDescriptor(v.prototype,"searched"),v.prototype),k(v.prototype,"filtered",[y],Object.getOwnPropertyDescriptor(v.prototype,"filtered"),v.prototype),k(v.prototype,"content",[g],Object.getOwnPropertyDescriptor(v.prototype,"content"),v.prototype),k(v.prototype,"search",[i.action],Object.getOwnPropertyDescriptor(v.prototype,"search"),v.prototype),v) -e.default=N,(0,t.setComponentTemplate)(S,N)})),define("consul-ui/components/data-form/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object","block-slots","validated-changeset"],(function(e,t,n,l,r,i,o){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const a=(0,n.createTemplateFactory)({id:"IXfByXKe",block:'[[[8,[39,0],null,[["@items","@src","@onchange","@once"],[[99,1,["@items"]],[28,[37,2],["/${partition}/${nspace}/${dc}/${type}/${src}",[28,[37,3],null,[["partition","nspace","dc","type","src"],[[33,4],[33,5],[33,6],[33,7],[33,8]]]]],null],[28,[37,9],[[30,0],"setData"],null],true]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n\\n "],[8,[39,11],null,[["@sink","@type","@label","@ondelete","@onchange"],[[28,[37,2],["/${partition}/${nspace}/${dc}/${type}",[28,[37,3],null,[["partition","nspace","dc","type"],[[33,4],[33,5],[28,[37,12],[[33,13,["Datacenter"]],[33,6]],null],[33,7]]]]],null],[99,7,["@type"]],[99,14,["@label"]],[28,[37,9],[[30,0],[33,15]],null],[28,[37,9],[[30,0],[33,16]],null]]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,3],null,[["data","change","isCreate","error","disabled","submit","delete"],[[33,13],[28,[37,9],[[30,0],"change"],null],[33,18],[30,1,["error"]],[30,1,["inflight"]],[28,[37,9],[[30,0],[30,1,["persist"]],[33,13]],null],[28,[37,9],[[30,0],[30,1,["delete"]],[33,13]],null]]]]],[[[1,"\\n "],[18,3,[[30,2]]],[1,"\\n"],[41,[33,21],[[[1," "],[8,[39,10],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,22],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[18,3,[[30,2]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,10],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,22],null,[["@name"],["form"]],[["default"],[[[[1,"\\n "],[18,3,[[30,2]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n"]],[2]]],[1,"\\n "]],[1]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n"]],[]]]]]],["writer","api","&default"],false,["data-loader","item","uri","hash","partition","nspace","dc","type","src","action","block-slot","data-writer","or","data","label","ondelete","onsubmit","let","create","yield","if","hasError","yield-slot"]]',moduleName:"consul-ui/components/data-form/index.hbs",isStrictMode:!1}) -var u=(0,t.setComponentTemplate)(a,t.default.extend(i.default,{tagName:"",dom:(0,l.inject)("dom"),builder:(0,l.inject)("form"),create:!1,ondelete:function(){return this.onsubmit(...arguments)},oncancel:function(){return this.onsubmit(...arguments)},onsubmit:function(){},onchange:function(e,t){return t.handleEvent(e)},didReceiveAttrs:function(){this._super(...arguments) -try{this.form=this.builder.form(this.type)}catch(e){}},willRender:function(){this._super(...arguments),(0,r.set)(this,"hasError",this._isRegistered("error"))},willDestroyElement:function(){this._super(...arguments),(0,r.get)(this,"data.isNew")&&this.data.rollbackAttributes()},actions:{setData:function(e){let t=e -return(0,o.isChangeset)(e)||void 0===this.form||(t=this.form.setData(e).getData()),(0,r.get)(e,"isNew")&&((0,r.set)(this,"create",!0),t=Object.entries(this.autofill||{}).reduce((function(e,t){let[n,l]=t -return(0,r.set)(e,n,l),e}),t)),(0,r.set)(this,"data",t),this.data},change:function(e,t,n){this.onchange(this.dom.normalizeEvent(e,t),this.form,this.form.getData())}}})) -e.default=u})),define("consul-ui/components/data-loader/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={id:"data-loader",initial:"load",on:{OPEN:{target:"load"},ERROR:{target:"disconnected"},LOAD:[{target:"idle",cond:"loaded"},{target:"loading"}]},states:{load:{},loading:{on:{SUCCESS:{target:"idle"},ERROR:{target:"error"}}},idle:{},error:{on:{RETRY:{target:"load"}}},disconnected:{on:{RETRY:{target:"load"}}}}}})) -define("consul-ui/components/data-loader/index",["exports","@ember/component","@ember/template-factory","@ember/object","block-slots","consul-ui/components/data-loader/chart.xstate"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"0gYnIceV",block:'[[[18,9,null],[1,"\\n"],[8,[39,1],null,[["@src"],[[99,2,["@src"]]]],[["default"],[[[[1,"\\n "],[8,[39,3],null,[["@target","@name","@value"],[[30,0],"dispatch",[30,4]]],null],[1,"\\n "],[8,[30,2],null,[["@name","@cond"],["loaded",[28,[37,4],[[30,0],"isLoaded"],null]]],null],[1,"\\n\\n\\n"],[44,[[28,[37,6],null,[["data","error","invalidate","dispatchError"],[[33,7],[33,8],[30,0,["invalidate"]],[28,[37,9],[[28,[37,4],[[30,0],[28,[37,10],[[33,8]],null]],[["value"],["error.errors.firstObject"]]],[28,[37,4],[[30,0],[30,4],"ERROR"],null]],null]]]]],[[[1,"\\n"],[6,[39,11],null,[["name"],["data"]],[["default","else"],[[[[1," "],[18,9,[[30,6]]],[1,"\\n"]],[]],[[[41,[28,[37,13],[[33,14]],null],[[[1," "],[8,[30,1],null,[["@notMatches"],[[28,[37,15],["error","disconnected"],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,16],[[33,17],[28,[37,18],[[28,[37,13],[[33,19]],null],[28,[37,20],[[30,5],"loading"],null]],null]],null],[[[1," "],[8,[39,21],null,[["@open","@src","@onchange","@onerror"],[[99,22,["@open"]],[99,17,["@src"]],[28,[37,9],[[28,[37,4],[[30,0],"change"],[["value"],["data"]]],[28,[37,4],[[30,0],[30,4],"SUCCESS"],null]],null],[30,6,["dispatchError"]]]],[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,0],"invalidate",[30,7,["invalidate"]]],null]],null]],[1,"\\n "]],[7]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n"]],[]],null]],[]]]]],[1,"\\n "],[8,[30,1],null,[["@matches"],["loading"]],[["default"],[[[[1,"\\n"],[6,[39,11],null,[["name"],["loading"]],[["default","else"],[[[[1," "],[18,9,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,25],null,null,null],[1,"\\n"]],[]]]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["error"]],[["default"],[[[[1,"\\n"],[6,[39,11],null,[["name"],["error"]],[["default","else"],[[[[1," "],[18,9,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,26],null,[["@error"],[[99,8,["@error"]]]],null],[1,"\\n"]],[]]]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],[[28,[37,15],["idle","disconnected"],null]]],[["default"],[[[[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,13],[[28,[37,27],[[33,8,["status"]],"401"],null]],null],[[[6,[39,11],null,[["name","params"],["disconnected",[28,[37,28],[[28,[37,4],[[30,0],[30,4],"RESET"],null]],null]]],[["default","else"],[[[[1," "],[18,9,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,29],[[4,[38,30],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,8,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,8,["Description"]],null,null,[["default"],[[[[1,"An error was returned whilst loading this data, refresh to try again."]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n"]],[]]]]]],[]],null],[1," "]],[]]]]],[1,"\\n"],[41,[28,[37,27],[[33,8,["status"]],"403"],null],[[[6,[39,11],null,[["name"],["error"]],[["default","else"],[[[[1," "],[18,9,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,26],null,[["@error"],[[99,8,["@error"]]]],null],[1,"\\n"]],[]]]]]],[]],[[[1," "],[8,[39,11],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n "],[18,9,[[30,6]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1,"\\n "]],[]]]]],[1,"\\n\\n"]],[6]]],[1," "],[1,[28,[35,31],[[28,[37,32],[[30,4],"LOAD"],null]],[["src"],[[33,17]]]]],[1,"\\n"]],[1,2,3,4,5]]]]]],["State","Guard","Action","dispatch","state","api","source","T","&default"],false,["yield","state-chart","chart","ref","action","let","hash","data","error","queue","mut","yield-slot","if","not","items","array","and","src","or","once","state-matches","data-source","open","did-insert","set","consul/loader","error-state","eq","block-params","hds/toast","notification","did-update","fn"]]',moduleName:"consul-ui/components/data-loader/index.hbs",isStrictMode:!1}) -var a=(0,t.setComponentTemplate)(o,t.default.extend(r.default,{tagName:"",onchange:e=>e,init:function(){this._super(...arguments),this.chart=i.default},didReceiveAttrs:function(){this._super(...arguments),void 0!==this.items&&this.actions.change.apply(this,[this.items])},didInsertElement:function(){this._super(...arguments),this.dispatch("LOAD")},actions:{isLoaded:function(){return void 0!==this.items||void 0===this.src},change:function(e){(0,l.set)(this,"data",this.onchange(e))}}})) -e.default=a})),define("consul-ui/components/data-sink/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object","consul-ui/utils/dom/event-source"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"utpO3btI",block:'[[[18,1,[[28,[37,1],null,[["open","state"],[[28,[37,2],[[30,0],"open"],null],[33,3]]]]]],[1,"\\n"]],["&default"],false,["yield","hash","action","state"]]',moduleName:"consul-ui/components/data-sink/index.hbs",isStrictMode:!1}) -var a=(0,t.setComponentTemplate)(o,t.default.extend({tagName:"",service:(0,l.inject)("data-sink/service"),dom:(0,l.inject)("dom"),logger:(0,l.inject)("logger"),onchange:function(e){},onerror:function(e){},state:(0,r.computed)("instance","instance.{dirtyType,isSaving}",(function(){let e -const t=(0,r.get)(this,"instance.isSaving"),n=(0,r.get)(this,"instance.dirtyType") -if(void 0===t&&void 0===n)e="idle" -else{switch(n){case"created":e=t?"creating":"create" -break -case"updated":e=t?"updating":"update" -break -case"deleted":case void 0:e=t?"removing":"remove"}e=`active.${e}`}return{matches:t=>-1!==e.indexOf(t)}})),init:function(){this._super(...arguments),this._listeners=this.dom.listeners()},willDestroyElement:function(){this._super(...arguments),this._listeners.remove()},source:function(e){const t=(0,i.once)(e),n=e=>{(0,r.set)(this,"instance",void 0) -try{this.onerror(e),this.logger.execute(e)}catch(e){this.logger.execute(e)}} -return this._listeners.add(t,{message:e=>{try{(0,r.set)(this,"instance",void 0),this.onchange(e)}catch(t){n(t)}},error:e=>n(e)}),t},didInsertElement:function(){this._super(...arguments),void 0===this.data&&void 0===this.item||this.actions.open.apply(this,[this.data,this.item])},persist:function(e,t){void 0!==e?(0,r.set)(this,"instance",this.service.prepare(this.sink,e,t)):(0,r.set)(this,"instance",t),this.source((()=>this.service.persist(this.sink,this.instance)))},remove:function(e){(0,r.set)(this,"instance",e),this.source((()=>this.service.remove(this.sink,e)))},actions:{open:function(e,t){if(t instanceof Event&&(t=void 0),void 0===e&&void 0===t)throw new Error("You must specify data to save, or null to remove") -null===e||""===e?this.remove(t):this.persist(e,t)}}})) -e.default=a})),define("consul-ui/components/data-source/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@glimmer/tracking","@ember/object","@ember/runloop","@ember/debug"],(function(e,t,n,l,r,i,o,a,u){var s,c,d,p,f,m,h,b,y,g -function v(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function O(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const P=(0,n.createTemplateFactory)({id:"CRu7UTYr",block:'[[[41,[28,[37,1],[[30,0,["disabled"]]],null],[[[41,[28,[37,2],[[30,0,["loading"]],"lazy"],null],[[[1," "],[11,"data"],[24,"aria-hidden","true"],[24,5,"width: 0;height: 0;font-size: 0;padding: 0;margin: 0;"],[4,[38,3],[[30,0,["connect"]]],null],[12],[13],[1,"\\n"]],[]],[[[1," "],[1,[28,[35,3],[[30,0,["connect"]]],null]],[1,"\\n"]],[]]],[1," "],[1,[28,[35,4],[[30,0,["attributeChanged"]],"src",[30,1]],null]],[1,"\\n "],[1,[28,[35,4],[[30,0,["attributeChanged"]],"loading",[30,2]],null]],[1,"\\n "],[1,[28,[35,5],[[30,0,["disconnect"]]],null]],[1,"\\n"]],[]],null],[1,[28,[35,4],[[30,0,["attributeChanged"]],"disabled",[30,3]],null]],[1,"\\n"],[18,4,[[28,[37,7],null,[["data","error","invalidate","Source"],[[30,0,["data"]],[30,0,["error"]],[30,0,["invalidate"]],[52,[30,0,["data"]],[50,"data-source",0,null,[["disabled"],[[28,[37,1],[[28,[37,2],[[30,0,["error"]],[27]],null]],null]]]],""]]]]]],[1,"\\n"]],["@src","@loading","@disabled","&default"],false,["if","not","eq","did-insert","did-update","will-destroy","yield","hash","component"]]',moduleName:"consul-ui/components/data-source/index.hbs",isStrictMode:!1}),x=function(e,t,n){let l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null -return"function"==typeof e?e():null} -const r=e[t] -return r!==n&&l(r,n),e[t]=n},w=()=>{},j=e=>"function"==typeof e?e:w,_=["eager","lazy"] -let k=(s=(0,r.inject)("data-source/service"),c=(0,r.inject)("dom"),d=(0,r.inject)("logger"),p=class extends l.default{constructor(e,t){super(...arguments),v(this,"dataSource",f,this),v(this,"dom",m,this),v(this,"logger",h,this),v(this,"isIntersecting",b,this),v(this,"data",y,this),v(this,"error",g,this),this._listeners=this.dom.listeners(),this._lazyListeners=this.dom.listeners()}get loading(){return _.includes(this.args.loading)?this.args.loading:_[0]}get disabled(){return void 0!==this.args.disabled&&this.args.disabled}onchange(e){this.error=void 0,this.data=e.data,j(this.args.onchange)(e)}onerror(e){this.error=e.error||e,j(this.args.onerror)(e)}connect(e){Array.isArray(e)?(this._lazyListeners.remove(),this.open()):this._lazyListeners.add(this.dom.isInViewport(e,(e=>{this.isIntersecting=e,this.isIntersecting?this.open():this.close()})))}disconnect(){void 0!==this.data&&void 0===this.data.length&&"function"==typeof this.data.rollbackAttributes&&this.data.rollbackAttributes(),this.close(),this._listeners.remove(),this._lazyListeners.remove()}attributeChanged(e){let[t,n]=e -if("src"===t)("eager"===this.loading||this.isIntersecting)&&this.open()}open(){const e=this.args.src,t=x(this,"source",this.dataSource.open(e,this,this.open),((e,t)=>{this.dataSource.close(e,this)})),n=e=>{try{const t=(0,o.get)(e,"error.errors.firstObject")||{} -"429"!==(0,o.get)(t,"status")&&this.onerror(e),this.logger.execute(e)}catch(e){this.logger.execute(e)}},l=this._listeners.add(this.source,{message:e=>{try{this.onchange(e)}catch(t){n(t)}},error:e=>{n(e)}}) -if(x(this,"_remove",l),"function"==typeof t.getCurrentEvent){const e=t.getCurrentEvent() -if(e){let t -void 0!==e.error?(t="onerror",this.error=e.error):(this.error=void 0,this.data=e.data,t="onchange"),(0,a.schedule)("afterRender",(()=>{try{this[t](e)}catch(l){n(l)}}))}}}async invalidate(){this.source.readyState=2,this.disconnect(),(0,a.schedule)("afterRender",(()=>{(0,u.runInDebug)((e=>console.debug("Invalidation is only supported for non-lazy data sources. If you want to use this you should fixup support for lazy data sources"))),this.connect([])}))}close(){void 0!==this.source&&(this.dataSource.close(this.source,this),x(this,"_remove",void 0),this.source=void 0)}},f=O(p.prototype,"dataSource",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=O(p.prototype,"dom",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=O(p.prototype,"logger",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=O(p.prototype,"isIntersecting",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return!1}}),y=O(p.prototype,"data",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=O(p.prototype,"error",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O(p.prototype,"connect",[o.action],Object.getOwnPropertyDescriptor(p.prototype,"connect"),p.prototype),O(p.prototype,"disconnect",[o.action],Object.getOwnPropertyDescriptor(p.prototype,"disconnect"),p.prototype),O(p.prototype,"attributeChanged",[o.action],Object.getOwnPropertyDescriptor(p.prototype,"attributeChanged"),p.prototype),O(p.prototype,"open",[o.action],Object.getOwnPropertyDescriptor(p.prototype,"open"),p.prototype),O(p.prototype,"invalidate",[o.action],Object.getOwnPropertyDescriptor(p.prototype,"invalidate"),p.prototype),O(p.prototype,"close",[o.action],Object.getOwnPropertyDescriptor(p.prototype,"close"),p.prototype),p) -e.default=k,(0,t.setComponentTemplate)(P,k)})),define("consul-ui/components/data-writer/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={id:"data-writer",initial:"idle",states:{idle:{on:{PERSIST:{target:"persisting"},REMOVE:{target:"removing"}}},removing:{on:{SUCCESS:{target:"removed"},ERROR:{target:"error"}}},persisting:{on:{SUCCESS:{target:"persisted"},ERROR:{target:"error"}}},removed:{on:{RESET:{target:"idle"}}},persisted:{on:{RESET:{target:"idle"}}},error:{on:{RESET:{target:"idle"}}}}}})),define("consul-ui/components/data-writer/index",["exports","@ember/component","@ember/template-factory","@ember/object","block-slots","consul-ui/components/data-writer/chart.xstate"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"RH49dABa",block:'[[[8,[39,0],null,[["@src"],[[99,1,["@src"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@target","@name","@value"],[[30,0],"dispatch",[30,4]]],null],[1,"\\n\\n"],[44,[[28,[37,4],null,[["data","error","persist","delete","inflight","disabled"],[[33,5],[33,6],[28,[37,7],[[30,0],"persist"],null],[28,[37,8],[[28,[37,7],[[30,0],[28,[37,9],[[33,5]],null]],null],[28,[37,7],[[30,0],[30,4],"REMOVE"],null]],null],[28,[37,10],[[30,5],[28,[37,11],["persisting","removing"],null]],null],[28,[37,10],[[30,5],[28,[37,11],["persisting","removing"],null]],null]]]]],[[[1,"\\n "],[18,13,[[30,6]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["removing"]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@sink","@item","@data","@onchange","@onerror"],[[99,14,["@sink"]],[99,5,["@item"]],null,[28,[37,7],[[30,0],[30,4],"SUCCESS"],null],[28,[37,7],[[30,0],"error"],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["persisting"]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@sink","@item","@onchange","@onerror"],[[99,14,["@sink"]],[99,5,["@item"]],[28,[37,7],[[30,0],[30,4],"SUCCESS"],null],[28,[37,7],[[30,0],"error"],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["removed"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,8],[[28,[37,7],[[30,0],[30,4],"RESET"],null],[28,[37,7],[[30,0],[33,15]],null]],null]],[[[6,[39,16],null,[["name","params"],["removed",[28,[37,17],[[30,7]],null]]],[["default","else"],[[[[1," "],[18,13,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,18],[[4,[38,19],null,[["after"],[[28,[37,7],[[30,0],[30,7]],null]]]]],[["@color"],["success"]],[["default"],[[[[1,"\\n "],[8,[30,8,["Title"]],null,null,[["default"],[[[[1,"Success!"]],[]]]]],[1,"\\n "],[8,[30,8,["Description"]],null,null,[["default"],[[[[1,"Your "],[1,[28,[35,20],[[33,21],[33,22]],null]],[1," has been deleted."]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n"]],[]]]]]],[7]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["persisted"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,7],[[30,0],[33,23]],null]],[[[6,[39,16],null,[["name","params"],["persisted",[28,[37,17],[[30,9]],null]]],[["default","else"],[[[[1," "],[18,13,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,18],[[4,[38,19],null,[["after"],[[28,[37,7],[[30,0],[30,9]],null]]]]],[["@color"],["success"]],[["default"],[[[[1,"\\n "],[8,[30,10,["Title"]],null,null,[["default"],[[[[1,"Success!"]],[]]]]],[1,"\\n "],[8,[30,10,["Description"]],null,null,[["default"],[[[[1,"Your "],[1,[28,[35,20],[[33,21],[33,22]],null]],[1," has been saved."]],[]]]]],[1,"\\n "]],[10]]]]],[1,"\\n"]],[]]]]]],[9]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["error"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,7],[[30,0],[30,4],"RESET"],null]],[[[6,[39,16],null,[["name","params"],["error",[28,[37,17],[[30,11],[30,6,["error"]]],null]]],[["default","else"],[[[[1," "],[18,13,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,18],[[4,[38,19],null,[["after"],[[28,[37,7],[[30,0],[30,11]],null]]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,12,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,12,["Description"]],null,null,[["default"],[[[[1,"There was an error saving your "],[1,[28,[35,20],[[33,21],[33,22]],null]],[1,".\\n"],[41,[28,[37,25],[[30,6,["error","status"]],[30,6,["error","detail"]]],null],[[[1," "],[10,"br"],[12],[13],[1,[30,6,["error","status"]]],[1,": "],[1,[30,6,["error","detail"]]],[1,"\\n"]],[]],[[[41,[30,6,["error","message"]],[[[1," "],[10,"br"],[12],[13],[1,[30,6,["error","message"]]],[1,"\\n "]],[]],null]],[]]],[1," "]],[]]]]],[1,"\\n "]],[12]]]]],[1,"\\n"]],[]]]]]],[11]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,16],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[18,13,[[30,6]]],[1,"\\n "]],[]]]]],[1,"\\n\\n"]],[6]]]],[1,2,3,4,5]]]]]],["State","Guard","Action","dispatch","state","api","after","T","after","T","after","T","&default"],false,["state-chart","chart","ref","let","hash","data","error","action","queue","mut","state-matches","array","yield","data-sink","sink","ondelete","yield-slot","block-params","hds/toast","notification","or","label","type","onchange","if","and"]]',moduleName:"consul-ui/components/data-writer/index.hbs",isStrictMode:!1}) -var a=(0,t.setComponentTemplate)(o,t.default.extend(r.default,{tagName:"",ondelete:function(){return this.onchange(...arguments)},onchange:function(){},init:function(){this._super(...arguments),this.chart=i.default},actions:{persist:function(e,t){t&&"function"==typeof t.preventDefault&&t.preventDefault(),(0,l.set)(this,"data",e),this.dispatch("PERSIST")},error:function(e,t){t&&"function"==typeof t.preventDefault&&t.preventDefault(),(0,l.set)(this,"error",void 0!==e.error.errors?e.error.errors.firstObject:e.error),this.dispatch("ERROR")}}})) -e.default=a})),define("consul-ui/components/debug/navigation/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"gn00CoAo",block:"[[],[],false,[]]",moduleName:"consul-ui/components/debug/navigation/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/delete-confirmation/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"2MbSBAzB",block:'[[[10,2],[12],[1,"\\n "],[1,[34,0]],[1,"\\n"],[13],[1,"\\n"],[8,[39,1],null,null,[["default"],[[[[1,"\\n "],[8,[39,2],[[16,"onclick",[28,[37,3],[[30,0],[33,4]],null]]],[["@text","@color"],["Confirm Delete","critical"]],null],[1,"\\n "],[8,[39,2],[[16,"onclick",[28,[37,3],[[30,0],[33,5]],null]]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"]],[]]]]]],[],false,["message","hds/button-set","hds/button","action","execute","cancel"]]',moduleName:"consul-ui/components/delete-confirmation/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:"",execute:function(){},cancel:function(){}})) -e.default=r})),define("consul-ui/components/disclosure-menu/action/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"kVsFG9Z2",block:'[[[8,[30,1,["Action"]],[[24,"aria-haspopup","menu"],[17,2]],null,[["default"],[[[[1,"\\n "],[18,3,null],[1,"\\n"]],[]]]]],[1,"\\n"]],["@disclosure","&attrs","&default"],false,["yield"]]',moduleName:"consul-ui/components/disclosure-menu/action/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/disclosure-menu/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"fLNl+IoV",block:'[[[11,0],[16,0,[28,[37,0],["disclosure-menu"],null]],[17,1],[12],[1,"\\n "],[8,[39,1],null,[["@expanded"],[[30,2]]],[["default"],[[[[1,"\\n "],[18,6,[[28,[37,3],null,[["Action","Menu","disclosure","toggle","close","open","expanded"],[[50,"disclosure-menu/action",0,null,[["disclosure"],[[30,3]]]],[50,"disclosure-menu/menu",0,null,[["disclosure","items","rowHeight"],[[30,3],[30,4],[30,5]]]],[30,3],[30,3,["toggle"]],[30,3,["close"]],[30,3,["open"]],[30,3,["expanded"]]]]]]],[1,"\\n "]],[3]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@expanded","disclosure","@items","@rowHeight","&default"],false,["class-map","disclosure","yield","hash","component"]]',moduleName:"consul-ui/components/disclosure-menu/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/disclosure-menu/menu/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"ezjH7NRj",block:'[[[8,[30,1,["Details"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,0],null,[["@items"],[[28,[37,1],[[30,3],[28,[37,2],null,null]],null]]],[["default"],[[[[1,"\\n "],[11,0],[16,0,[28,[37,3],[[28,[37,2],["paged-collection-scroll",[28,[37,4],[[30,4,["type"]],[28,[37,2],["virtual-scroll","native-scroll"],null]],null]],null]],null]],[17,5],[4,[38,5],["click",[30,1,["close"]]],null],[4,[38,6],[[30,4,["viewport"]]],null],[4,[38,7],[[30,4,["resize"]]],null],[4,[38,8],["--paged-row-height"],[["returns"],[[30,4,["rowHeight"]]]]],[4,[38,8],["max-height"],[["returns"],[[30,4,["maxHeight"]]]]],[12],[1,"\\n "],[18,6,[[28,[37,10],null,[["Menu"],[[50,"menu",0,null,[["disclosure","pager"],[[30,1],[30,4]]]]]]]]],[1,"\\n "],[13],[1,"\\n "]],[4]]]]],[1,"\\n"]],[2]]]]],[1,"\\n\\n"]],["@disclosure","details","@items","pager","&attrs","&default"],false,["paged-collection","or","array","class-map","includes","on-outside","did-insert","on-resize","css-prop","yield","hash","component"]]',moduleName:"consul-ui/components/disclosure-menu/menu/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/disclosure/action/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"h7+iNKLY",block:'[[[8,[39,0],[[16,"aria-expanded",[52,[30,1,["expanded"]],"true","false"]],[16,"aria-controls",[30,1,["controls"]]],[17,2]],null,[["default"],[[[[1,"\\n "],[18,3,null],[1,"\\n"]],[]]]]],[1,"\\n"]],["@disclosure","&attrs","&default"],false,["action","if","yield"]]',moduleName:"consul-ui/components/disclosure/action/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/disclosure/details/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"VadZ+kad",block:'[[[44,[[28,[37,1],null,null]],[[[41,[28,[37,3],[[28,[37,4],[[28,[37,5],[[30,2],[27]],null],[30,3,["expanded"]]],null],[28,[37,4],[[28,[37,6],[[30,2],[27]],null],[28,[37,5],[[30,2],false],null]],null]],null],[[[18,4,[[28,[37,8],null,[["id","expanded"],[[30,1],[30,3,["expanded"]]]]]]],[1,"\\n"]],[]],null],[1,[28,[35,9],[[28,[37,10],[[30,3,["add"]],[30,1]],null]],null]],[1,"\\n"],[1,[28,[35,11],[[28,[37,10],[[30,3,["remove"]],[30,1]],null]],null]],[1,"\\n"]],[1]]]],["id","@auto","@disclosure","&default"],false,["let","unique-id","if","or","and","eq","not-eq","yield","hash","did-insert","fn","will-destroy"]]',moduleName:"consul-ui/components/disclosure/details/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/disclosure/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object","@ember/runloop"],(function(e,t,n,l,r,i,o){var a,u -function s(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const c=(0,n.createTemplateFactory)({id:"iAc3HX8Q",block:'[[[8,[39,0],null,[["@src","@initial"],[[28,[37,0],["boolean"],null],[52,[30,1],"true","false"]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],null,[["toggle","close","open","expanded","event","button","controls"],[[28,[37,4],[[30,5],"TOGGLE"],null],[28,[37,4],[[30,5],"FALSE"],null],[28,[37,4],[[30,5],"TRUE"],null],[28,[37,5],[[30,6],"true"],null],[30,6,["context"]],[28,[37,6],null,null],[30,0,["ids"]]]]]],[[[44,[[28,[37,7],[[30,7],[28,[37,3],null,[["Action","Details"],[[50,"disclosure/action",0,null,[["disclosure"],[[30,7]]]],[50,"disclosure/details",0,null,[["disclosure"],[[28,[37,3],null,[["add","remove","expanded"],[[30,0,["add"]],[30,0,["remove"]],[28,[37,5],[[30,6],"true"],null]]]]]]]]]]],null]],[[[1," "],[18,9,[[30,8]]],[1,"\\n"]],[8]]]],[7]]]],[2,3,4,5,6]]]]]],["@expanded","State","Guard","Action","dispatch","state","_api","api","&default"],false,["state-chart","if","let","hash","fn","state-matches","unique-id","assign","component","yield"]]',moduleName:"consul-ui/components/disclosure/index.hbs",isStrictMode:!1}) -let d=(a=class extends l.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="ids",l=this,(n=u)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}add(e){(0,o.schedule)("afterRender",(()=>{this.ids=`${this.ids}${this.ids.length>0?" ":""}${e}`}))}remove(e){this.ids=this.ids.split(" ").filter((t=>t!==e)).join(" ")}},u=s(a.prototype,"ids",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return""}}),s(a.prototype,"add",[i.action],Object.getOwnPropertyDescriptor(a.prototype,"add"),a.prototype),s(a.prototype,"remove",[i.action],Object.getOwnPropertyDescriptor(a.prototype,"remove"),a.prototype),a) -e.default=d,(0,t.setComponentTemplate)(c,d)})),define("consul-ui/components/ember-collection",["exports","ember-collection/components/ember-collection"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/ember-native-scrollable",["exports","ember-collection/components/ember-native-scrollable"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/empty-state/index",["exports","@ember/component","@ember/template-factory","@ember/object","block-slots"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i=(0,n.createTemplateFactory)({id:"MevuN2Uz",block:'[[[18,2,null],[1,"\\n"],[11,0],[24,0,"empty-state"],[17,1],[12],[1,"\\n"],[41,[33,2],[[[1," "],[10,"header"],[12],[1,"\\n"],[6,[39,3],null,[["name"],["header"]],[["default"],[[[[1," "],[18,2,null],[1,"\\n"]],[]]]]],[6,[39,3],null,[["name"],["subheader"]],[["default"],[[[[1," "],[18,2,null],[1,"\\n"]],[]]]]],[1," "],[13],[1,"\\n"]],[]],null],[6,[39,3],null,[["name"],["body"]],[["default"],[[[[1," "],[10,0],[12],[1,"\\n "],[18,2,null],[1,"\\n"],[41,[33,4],[[[1," "],[8,[39,5],[[4,[38,7],["click",[33,4]],null]],[["@color","@text"],["primary",[52,[33,6,["AccessorID"]],"Log in with a different token","Log in"]]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@src","@onchange"],[[28,[37,9],["settings://consul:token"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,6]],null]],[["value"],["data"]]]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]]]]],[6,[39,3],null,[["name"],["actions"]],[["default"],[[[[1," "],[10,"ul"],[12],[1,"\\n "],[18,2,null],[1,"\\n "],[13],[1,"\\n"]],[]]]]],[13]],["&attrs","&default"],false,["yield","if","hasHeader","yield-slot","login","hds/button","token","on","data-source","uri","action","mut"]]',moduleName:"consul-ui/components/empty-state/index.hbs",isStrictMode:!1}) -var o=(0,t.setComponentTemplate)(i,t.default.extend(r.default,{tagName:"",willRender:function(){this._super(...arguments),(0,l.set)(this,"hasHeader",this._isRegistered("header")||this._isRegistered("subheader"))}})) -e.default=o})),define("consul-ui/components/error-state/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"qh3oSZcW",block:'[[[41,[28,[37,1],[[30,1,["status"]],"403"],null],[[[1," "],[8,[39,2],[[16,0,[28,[37,3],["status-",[30,1,["status"]]],null]]],[["@login"],[[30,2]]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,5],[[30,1,["message"]],"Consul returned an error"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[30,1,["status"]],[[[1," "],[8,[39,4],null,[["@name"],["subheader"]],[["default"],[[[[1,"\\n "],[10,"h3"],[12],[1,"\\n Error "],[1,[30,1,["status"]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,4],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n"],[41,[30,1,["detail"]],[[[1," "],[1,[30,1,["detail"]]],[1,"\\n"]],[]],[[[1," You may have visited a URL that is loading an unknown resource, so you can try going back to the root or try re-submitting your ACL Token/SecretID by going back to ACLs.\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,6],null,[["@route","@text","@icon","@iconPosition","@size"],["index","Go back","chevron-left","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,6],null,[["@text","@href","@iconPosition","@icon","@size"],["Read the documentation",[29,[[28,[37,7],["CONSUL_DOCS_URL"],null]]],"trailing","docs-link","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,2],[[16,0,[28,[37,3],["status-",[30,1,["status"]]],null]]],[["@login"],[[30,2]]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n You are not authorized\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["subheader"]],[["default"],[[[[1,"\\n "],[10,"h3"],[12],[1,"\\n Error "],[1,[30,1,["status"]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n You must be granted permissions to view this data. Ask your administrator if you think you should have access.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,6],null,[["@text","@href","@icon","@iconPosition","@size"],["Read the documentation",[29,[[28,[37,7],["CONSUL_DOCS_URL"],null],"/acl/index.html"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,6],null,[["@text","@href","@icon","@iconPosition","@size"],["Follow the guide",[29,[[28,[37,7],["CONSUL_DOCS_LEARN_URL"],null],"/consul/security-networking/production-acls"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]],["@error","@login"],false,["if","not-eq","empty-state","concat","block-slot","or","hds/link/standalone","env"]]',moduleName:"consul-ui/components/error-state/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/event-source/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i=(0,n.createTemplateFactory)({id:"OA0g9tPL",block:'[[[18,1,[[28,[37,1],null,[["close"],[[28,[37,2],[[30,0],"close"],null]]]]]],[1,"\\n"]],["&default"],false,["yield","hash","action"]]',moduleName:"consul-ui/components/event-source/index.hbs",isStrictMode:!1}),o=function(e,t,n){let l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null -return"function"==typeof e?e():null} -const i=e[t] -return i!==n&&l(i,n),(0,r.set)(e,t,n)} -var a=(0,t.setComponentTemplate)(i,t.default.extend({tagName:"",dom:(0,l.inject)("dom"),logger:(0,l.inject)("logger"),data:(0,l.inject)("data-source/service"),closeOnDestroy:!0,onerror:function(e){this.logger.execute(e.error)},init:function(){this._super(...arguments),this._listeners=this.dom.listeners()},willDestroyElement:function(){this.closeOnDestroy&&this.actions.close.apply(this,[]),this._listeners.remove(),this._super(...arguments)},didReceiveAttrs:function(){this._super(...arguments),(0,r.get)(this,"src.configuration.uri")!==(0,r.get)(this,"source.configuration.uri")&&this.actions.open.apply(this,[])},actions:{open:function(){o(this,"source",this.data.open(this.src,this),((e,t)=>{void 0!==e&&this.data.close(e,this)})),o(this,"proxy",this.src,((e,t)=>{void 0!==e&&e.destroy()})) -const e=e=>{try{const t=(0,r.get)(e,"error.errors.firstObject") -"429"!==(0,r.get)(t||{},"status")&&this.onerror(e),this.logger.execute(e)}catch(e){this.logger.execute(e)}},t=this._listeners.add(this.source,{error:t=>{e(t)}}) -o(this,"_remove",t)},close:function(){void 0!==this.source&&(this.data.close(this.source,this),o(this,"_remove",void 0),(0,r.set)(this,"source",void 0)),void 0!==this.proxy&&this.proxy.destroy()}}})) -e.default=a})),define("consul-ui/components/flash-message",["exports","ember-cli-flash/components/flash-message"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/flight-icon",["exports","@hashicorp/ember-flight-icons/components/flight-icon"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/form-component/index",["exports","@ember/component","@ember/template-factory","block-slots","@ember/service","@ember/object/computed"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"etKAawDq",block:'[[[18,1,null]],["&default"],false,["yield"]]',moduleName:"consul-ui/components/form-component/index.hbs",isStrictMode:!1}),a=/([^[\]])+/g -var u=(0,t.setComponentTemplate)(o,t.default.extend(l.default,{tagName:"",onreset:function(){},onchange:function(){},onerror:function(){},onsuccess:function(){},data:(0,i.alias)("form.data"),item:(0,i.alias)("form.data"),dom:(0,r.inject)("dom"),container:(0,r.inject)("form"),actions:{change:function(e,t,n){let l=this.dom.normalizeEvent(e,t) -const r=[...l.target.name.matchAll(a)],i=r[r.length-1][0] -let o -o=-1===i.indexOf("[")?`${this.type}[${i}]`:i,this.form.handleEvent(l,o),this.onchange({target:this})}}})) -e.default=u})),define("consul-ui/components/form-group/element/checkbox/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"4jry83Gq",block:'[[[11,"input"],[24,4,"checkbox"],[16,3,[30,1]],[16,2,[30,2]],[17,3],[4,[38,0],[[28,[37,1],[[30,4]],null]],null],[4,[38,2],["change",[28,[37,1],[[30,5]],null]],null],[12],[13],[1,"\\n"]],["@name","@value","&attrs","@didinsert","@onchange"],false,["did-insert","optional","on"]]',moduleName:"consul-ui/components/form-group/element/checkbox/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/form-group/element/error/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"dGEGUftb",block:'[[[11,"strong"],[24,"role","alert"],[17,1],[12],[1,"\\n "],[18,2,null],[1,"\\n"],[13],[1,"\\n"]],["&attrs","&default"],false,["yield"]]',moduleName:"consul-ui/components/form-group/element/error/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/form-group/element/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object"],(function(e,t,n,l,r,i){var o,a,u -function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const d=(0,n.createTemplateFactory)({id:"Qn2u34/P",block:'[[[44,[[28,[37,1],null,[["Element","Text","Checkbox","Radio","Label","Error","state"],[[50,"form-group/element",0,null,[["group","name"],[[30,1],[30,2]]]],[50,"form-group/element/text",0,null,[["didinsert","name","oninput"],[[28,[37,3],[[30,0],[30,0,["connect"]]],null],[30,0,["name"]],[28,[37,3],[[30,0],[28,[37,4],[[30,0,["touched"]]],null],true],null]]]],[50,"form-group/element/checkbox",0,null,[["didinsert","name","onchange"],[[28,[37,3],[[30,0],[30,0,["connect"]]],null],[30,0,["name"]],[28,[37,3],[[30,0],[28,[37,4],[[30,0,["touched"]]],null],true],null]]]],[50,"form-group/element/radio",0,null,[["didinsert","name","onchange"],[[28,[37,3],[[30,0],[30,0,["connect"]]],null],[30,0,["name"]],[28,[37,3],[[30,0],[28,[37,4],[[30,0,["touched"]]],null],true],null]]]],[50,"form-group/element/label",0,null,null],[50,"form-group/element/error",0,null,null],[33,5]]]]],[[[41,[28,[37,7],[[30,0,["type"]],[28,[37,8],["radiogroup","checkbox-group","checkboxgroup"],null]],null],[[[1," "],[11,0],[16,"data-property",[30,0,["prop"]]],[16,0,[29,["type-",[30,0,["type"]],[52,[28,[37,9],[[33,5],"error"],null]," has-error"]]]],[17,4],[12],[1,"\\n "],[18,5,[[30,3]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[11,"label"],[16,"data-property",[30,0,["prop"]]],[16,0,[29,["type-",[30,0,["type"]],[52,[28,[37,9],[[33,5],"error"],null]," has-error"]]]],[17,4],[12],[1,"\\n "],[18,5,[[30,3]]],[1,"\\n "],[13],[1,"\\n"]],[]]]],[3]]]],["@group","@name","el","&attrs","&default"],false,["let","hash","component","action","mut","state","if","includes","array","state-matches","yield"]]',moduleName:"consul-ui/components/form-group/element/index.hbs",isStrictMode:!1}) -let p=(o=class extends l.default{constructor(){super(...arguments),s(this,"el",a,this),s(this,"touched",u,this)}get type(){return void 0!==this.el?this.el.dataset.type||this.el.getAttribute("type")||this.el.getAttribute("role"):this.args.type}get name(){return void 0!==this.args.group?`${this.args.group.name}[${this.args.name}]`:this.args.name}get prop(){return`${this.args.name.toLowerCase().split(".").join("-")}`}get state(){const e=this.touched&&this.args.error -return{matches:t=>"error"===t&&e}}connect(e){this.el=e}},a=c(o.prototype,"el",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(o.prototype,"touched",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return!1}}),c(o.prototype,"connect",[i.action],Object.getOwnPropertyDescriptor(o.prototype,"connect"),o.prototype),o) -e.default=p,(0,t.setComponentTemplate)(d,p)})),define("consul-ui/components/form-group/element/label/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"qfCtMXFx",block:'[[[11,1],[24,0,"form-elements-label label"],[17,1],[12],[1,"\\n "],[18,2,null],[1,"\\n"],[13],[1,"\\n"]],["&attrs","&default"],false,["yield"]]',moduleName:"consul-ui/components/form-group/element/label/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/form-group/element/radio/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"Ir+FjtQH",block:'[[[11,"input"],[24,4,"radio"],[16,3,[30,1]],[16,2,[30,2]],[17,3],[4,[38,0],[[28,[37,1],[[30,4]],null]],null],[4,[38,2],["change",[28,[37,1],[[30,5]],null]],null],[12],[13],[1,"\\n"]],["@name","@value","&attrs","@didinsert","@onchange"],false,["did-insert","optional","on"]]',moduleName:"consul-ui/components/form-group/element/radio/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/form-group/element/text/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"auOoQIU/",block:'[[[11,"input"],[24,4,"text"],[16,3,[30,1]],[16,2,[30,2]],[17,3],[4,[38,0],[[28,[37,1],[[30,4]],null]],null],[4,[38,2],["input",[28,[37,1],[[30,5]],null]],null],[12],[13],[1,"\\n"]],["@name","@value","&attrs","@didinsert","@oninput"],false,["did-insert","optional","on"]]',moduleName:"consul-ui/components/form-group/element/text/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/form-group/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"7XOStkey",block:'[[[18,1,[[28,[37,1],null,[["Element"],[[50,"form-group/element",0,null,[["group"],[[30,0]]]]]]]]],[1,"\\n"]],["&default"],false,["yield","hash","component"]]',moduleName:"consul-ui/components/form-group/index.hbs",isStrictMode:!1}) -class i extends l.default{get name(){return this.args.name}}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/form-input/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"m+IBH13K",block:'[[[11,"label"],[16,0,[28,[37,0],["form-input",[52,[28,[37,2],[[30,1,["state","context","errors"]],[30,2]],null]," has-error"]],null]],[17,3],[12],[1,"\\n "],[10,1],[12],[1,"\\n "],[18,7,null],[1,"\\n "],[13],[1,"\\n "],[18,8,null],[1,"\\n"],[44,[[28,[37,5],[[30,4,["help"]],[30,5]],null]],[[[41,[30,6],[[[1," "],[10,"em"],[12],[1,"\\n "],[1,[30,6]],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[6]]],[1," "],[8,[39,6],null,[["@state","@matches"],[[30,1,["state"]],"error"]],[["default"],[[[[1,"\\n"],[1," "],[10,"strong"],[14,"role","alert"],[12],[1,[28,[35,2],[[28,[37,2],[[30,1,["state","context","errors"]],[30,2]],null],"message"],null]],[13],[1,"\\n "]],[]]]]],[1,"\\n"],[13],[1,"\\n"]],["@chart","@name","&attrs","@validations","@help","help","&label","&input"],false,["concat","if","get","yield","let","or","state"]]',moduleName:"consul-ui/components/form-input/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/freetext-filter/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object"],(function(e,t,n,l,r){var i -function o(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const a=(0,n.createTemplateFactory)({id:"oIN1v5pq",block:'[[[11,0],[24,0,"freetext-filter"],[17,1],[12],[1,"\\n "],[10,"label"],[14,0,"type-search"],[12],[1,"\\n "],[10,1],[14,0,"freetext-filter_label"],[12],[1,"Search"],[13],[1,"\\n "],[10,"input"],[14,0,"freetext-filter_input"],[15,"onsearch",[28,[37,0],[[30,0],[30,0,["change"]]],null]],[15,"oninput",[28,[37,0],[[30,0],[30,0,["change"]]],null]],[15,"onkeydown",[28,[37,0],[[30,0],[30,0,["keydown"]]],null]],[14,3,"s"],[15,2,[30,2]],[15,"placeholder",[30,0,["placeholder"]]],[14,"autofocus","autofocus"],[14,4,"search"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[18,3,null],[1,"\\n"],[13]],["&attrs","@value","&default"],false,["action","yield"]]',moduleName:"consul-ui/components/freetext-filter/index.hbs",isStrictMode:!1}) -let u=(o((i=class extends l.default{get placeholder(){return this.args.placeholder||"Search"}get onsearch(){return this.args.onsearch||(()=>{})}change(e){this.onsearch(e)}keydown(e){13===e.keyCode&&e.preventDefault()}}).prototype,"change",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"change"),i.prototype),o(i.prototype,"keydown",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"keydown"),i.prototype),i) -e.default=u,(0,t.setComponentTemplate)(a,u)})) -define("consul-ui/components/hashicorp-consul/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service"],(function(e,t,n,l,r){var i,o,a -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const u=(0,n.createTemplateFactory)({id:"wUVRiBq4",block:'[[[8,[39,0],[[24,0,"hashicorp-consul"],[17,1]],null,[["notifications","home-nav","main-nav","complementary-nav","main","content-info"],[[[[1,"\\n"],[42,[28,[37,2],[[28,[37,2],[[33,3,["queue"]]],null]],null],null,[[[1," "],[8,[30,2,["Notification"]],null,[["@delay","@sticky"],[[28,[37,4],[[30,3,["timeout"]],[30,3,["extendedTimeout"]]],null],[30,3,["sticky"]]]],[["default"],[[[[1,"\\n"],[41,[30,3,["dom"]],[[[1," "],[2,[30,3,["dom"]]],[1,"\\n"]],[]],[[[44,[[28,[37,7],[[30,3,["type"]]],null],[28,[37,7],[[30,3,["action"]]],null]],[[[1," "],[8,[39,8],[[24,"data-notification",""]],[["@color"],[[52,[28,[37,9],[[30,4],"error"],null],"critical",[30,4]]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,[28,[35,10],[[30,4]],null]],[1,"!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,9],[[30,5],"logout"],null],[[[41,[28,[37,9],[[30,4],"success"],null],[[[1," You are now logged out.\\n"]],[]],[[[1," There was an error logging out.\\n"]],[]]]],[]],[[[41,[28,[37,9],[[30,5],"authorize"],null],[[[41,[28,[37,9],[[30,4],"success"],null],[[[1," You are now logged in.\\n"]],[]],[[[1," There was an error, please check your SecretID/Token\\n"]],[]]]],[]],[[[41,[28,[37,11],[[28,[37,9],[[30,5],"use"],null],[28,[37,9],[[30,3,["model"]],"token"],null]],null],[[[1," "],[8,[39,12],null,[["@type","@status","@item","@error"],[[30,5],[30,4],[30,3,["item"]],[30,3,["error"]]]],null],[1,"\\n"]],[]],[[[41,[28,[37,9],[[30,3,["model"]],"intention"],null],[[[1," "],[8,[39,13],null,[["@type","@status","@item","@error"],[[30,5],[30,4],[30,3,["item"]],[30,3,["error"]]]],null],[1,"\\n"]],[]],[[[41,[28,[37,9],[[30,3,["model"]],"role"],null],[[[1," "],[8,[39,14],null,[["@type","@status","@item","@error"],[[30,5],[30,4],[30,3,["item"]],[30,3,["error"]]]],null],[1,"\\n"]],[]],[[[41,[28,[37,9],[[30,3,["model"]],"policy"],null],[[[1," "],[8,[39,15],null,[["@type","@status","@item","@error"],[[30,5],[30,4],[30,3,["item"]],[30,3,["error"]]]],null],[1,"\\n "]],[]],null]],[]]]],[]]]],[]]],[1," "]],[]]]],[]]],[1," "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n\\n"]],[4,5]]]],[]]],[1," "]],[]]]]],[1,"\\n"]],[3]],null],[1,"\\n "]],[2]],[[[1,"\\n "],[10,3],[14,0,"w-8 h-8"],[15,6,[28,[37,16],["index"],[["params"],[[28,[37,17],null,[["peer"],[[27]]]]]]]],[12],[1,"\\n "],[8,[39,18],null,[["@size","@name","@stretched"],["24","consul-color",true]],null],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[39,19],null,null,null],[1,"\\n "],[10,"ul"],[12],[1,"\\n "],[8,[39,20],null,[["@dc","@partition","@nspace","@dcs"],[[30,7],[30,8],[30,9],[30,10]]],null],[1,"\\n "],[8,[39,21],null,[["@dc","@partition","@nspace","@partitions","@onchange"],[[30,7],[30,8],[30,9],[30,0,["partitions"]],[28,[37,22],[[30,0],[28,[37,23],[[30,0,["partitions"]]],null]],[["value"],["data"]]]]],null],[1,"\\n "],[8,[39,24],null,[["@dc","@partition","@nspace","@nspaces","@onchange"],[[30,7],[30,8],[30,9],[30,0,["nspaces"]],[28,[37,22],[[30,0],[28,[37,23],[[30,0,["nspaces"]]],null]],[["value"],["data"]]]]],null],[1,"\\n"],[41,[28,[37,25],["access overview"],null],[[[1," "],[10,"li"],[15,0,[28,[37,26],[[28,[37,27],["is-active",[28,[37,28],["dc.show",[30,7,["Name"]]],null]],null]],null]],[12],[1,"\\n "],[8,[39,22],null,[["@href"],[[28,[37,16],["dc.show",[30,7,["Name"]]],[["params"],[[28,[37,17],null,[["peer"],[[27]]]]]]]]],[["default"],[[[[1,"\\n Overview\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,25],["read services"],null],[[[1," "],[10,"li"],[15,0,[52,[28,[37,28],["dc.services",[30,7,["Name"]]],null],"is-active"]],[12],[1,"\\n "],[10,3],[15,6,[28,[37,16],["dc.services",[30,7,["Name"]]],[["params"],[[28,[37,17],null,[["peer"],[[27]]]]]]]],[12],[1,"Services"],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,25],["read nodes"],null],[[[1," "],[10,"li"],[15,0,[52,[28,[37,28],["dc.nodes",[30,7,["Name"]]],null],"is-active"]],[12],[1,"\\n "],[10,3],[15,6,[28,[37,16],["dc.nodes",[30,7,["Name"]]],[["params"],[[28,[37,17],null,[["peer"],[[27]]]]]]]],[12],[1,"Nodes"],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,25],["read kv"],null],[[[1," "],[10,"li"],[15,0,[52,[28,[37,28],["dc.kv",[30,7,["Name"]]],null],"is-active"]],[12],[1,"\\n "],[10,3],[15,6,[28,[37,16],["dc.kv",[30,7,["Name"]]],[["params"],[[28,[37,17],null,[["peer"],[[27]]]]]]]],[12],[1,"Key/Value"],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,25],["read intentions"],null],[[[1," "],[10,"li"],[15,0,[52,[28,[37,28],["dc.intentions",[30,7,["Name"]]],null],"is-active"]],[12],[1,"\\n "],[10,3],[15,6,[28,[37,16],["dc.intentions",[30,7,["Name"]]],[["params"],[[28,[37,17],null,[["peer"],[[27]]]]]]]],[12],[1,"Intentions"],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[8,[39,29],null,[["@dc","@partition","@nspace"],[[30,7],[30,8],[30,9]]],null],[1,"\\n "],[8,[39,30],null,[["@dc","@partition","@nspace"],[[30,7],[30,8],[30,9]]],null],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[10,"ul"],[12],[1,"\\n "],[8,[39,31],null,null,null],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,32],null,null,[["default"],[[[[1,"\\n "],[8,[30,11,["Action"]],[[4,[38,33],["click",[30,11,["toggle"]]],null]],null,[["default"],[[[[1,"\\n Help\\n "]],[]]]]],[1,"\\n "],[8,[30,11,["Menu"]],null,null,[["default"],[[[[1,"\\n "],[8,[30,12,["Menu"]],null,null,[["default"],[[[[1,"\\n "],[8,[30,13,["Separator"]],null,null,[["default"],[[[[1,"\\n Consul v"],[1,[28,[35,34],["CONSUL_VERSION"],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,13,["Item"]],[[24,0,"docs-link"]],null,[["default"],[[[[1,"\\n "],[8,[30,13,["Action"]],null,[["@href","@external"],[[28,[37,34],["CONSUL_DOCS_URL"],null],true]],[["default"],[[[[1,"\\n Documentation\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,13,["Item"]],[[24,0,"learn-link"]],null,[["default"],[[[[1,"\\n "],[8,[30,13,["Action"]],null,[["@href","@external"],[[28,[37,35],[[28,[37,34],["CONSUL_DOCS_LEARN_URL"],null],"/consul"],null],true]],[["default"],[[[[1,"\\n HashiCorp Learn\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,13,["Separator"]],null,null,null],[1,"\\n "],[8,[30,13,["Item"]],[[24,0,"feedback-link"]],null,[["default"],[[[[1,"\\n "],[8,[30,13,["Action"]],null,[["@href","@external"],[[28,[37,34],["CONSUL_REPO_ISSUES_URL"],null],true]],[["default"],[[[[1,"\\n Provide Feedback\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[13]]]]],[1,"\\n "]],[12]]]]],[1,"\\n "]],[11]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[15,0,[52,[28,[37,28],["settings"],null],"is-active"]],[12],[1,"\\n "],[10,3],[15,6,[28,[37,16],["settings"],[["params"],[[28,[37,17],null,[["nspace","partition"],[[27],[27]]]]]]]],[12],[1,"\\n Settings\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,36],null,[["@dc","@partition","@nspace","@onchange"],[[30,7],[30,8],[30,9],[30,14]]],[["default"],[[[[1,"\\n "],[8,[39,37],null,[["@target","@name","@value"],[[30,0],"tokenSelector",[30,15]]],null],[1,"\\n "]],[15]]]]],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[18,16,[[28,[37,17],null,[["login"],[[52,[30,0,["tokenSelector"]],[30,0,["tokenSelector"]],[28,[37,17],null,[["open","close"],[[27],[27]]]]]]]]]],[1,"\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n Consul v"],[1,[28,[35,34],["CONSUL_VERSION"],null]],[1,"\\n "],[13],[1,"\\n "],[2,[28,[37,35],["\x3c!-- ",[28,[37,34],["CONSUL_GIT_SHA"],null],"--\x3e"],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],["&attrs","app","flash","status","type","T","@dc","@partition","@nspace","@dcs","disclosure","panel","menu","@onchange","selector","&default"],false,["app","each","-track-array","flashMessages","sub","if","let","lowercase","hds/toast","eq","capitalize","or","consul/token/notifications","consul/intention/notifications","consul/role/notifications","consul/policy/notifications","href-to","hash","flight-icon","consul/hcp/home","consul/datacenter/selector","consul/partition/selector","action","mut","consul/nspace/selector","can","class-map","array","is-href","consul/acl/selector","consul/peer/selector","debug/navigation","disclosure-menu","on","env","concat","consul/token/selector","ref","yield"]]',moduleName:"consul-ui/components/hashicorp-consul/index.hbs",isStrictMode:!1}) -let s=(i=(0,r.inject)("flashMessages"),o=class extends l.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="flashMessages",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}},c=o.prototype,d="flashMessages",p=[i],f={configurable:!0,enumerable:!0,writable:!0,initializer:null},h={},Object.keys(f).forEach((function(e){h[e]=f[e]})),h.enumerable=!!h.enumerable,h.configurable=!!h.configurable,("value"in h||h.initializer)&&(h.writable=!0),h=p.slice().reverse().reduce((function(e,t){return t(c,d,e)||e}),h),m&&void 0!==h.initializer&&(h.value=h.initializer?h.initializer.call(m):void 0,h.initializer=void 0),void 0===h.initializer&&(Object.defineProperty(c,d,h),h=null),a=h,o) -var c,d,p,f,m,h -e.default=s,(0,t.setComponentTemplate)(u,s)})),define("consul-ui/components/hds/alert/description",["exports","@hashicorp/design-system-components/components/hds/alert/description"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/alert/index",["exports","@hashicorp/design-system-components/components/hds/alert/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/alert/title",["exports","@hashicorp/design-system-components/components/hds/alert/title"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/avatar/index",["exports","@hashicorp/design-system-components/components/hds/avatar/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/badge-count/index",["exports","@hashicorp/design-system-components/components/hds/badge-count/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/badge/index",["exports","@hashicorp/design-system-components/components/hds/badge/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/breadcrumb/index",["exports","@hashicorp/design-system-components/components/hds/breadcrumb/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/breadcrumb/item",["exports","@hashicorp/design-system-components/components/hds/breadcrumb/item"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/breadcrumb/truncation",["exports","@hashicorp/design-system-components/components/hds/breadcrumb/truncation"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/button-set/index",["exports","@hashicorp/design-system-components/components/hds/button-set/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/button/index",["exports","@hashicorp/design-system-components/components/hds/button/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/card/container",["exports","@hashicorp/design-system-components/components/hds/card/container"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/disclosure/index",["exports","@hashicorp/design-system-components/components/hds/disclosure/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dismiss-button/index",["exports","@hashicorp/design-system-components/components/hds/dismiss-button/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/index",["exports","@hashicorp/design-system-components/components/hds/dropdown/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/copy-item",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/copy-item"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/description",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/description"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/generic",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/generic"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/interactive",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/interactive"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/separator",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/separator"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/title",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/title"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/toggle/button",["exports","@hashicorp/design-system-components/components/hds/dropdown/toggle/button"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/toggle/icon",["exports","@hashicorp/design-system-components/components/hds/dropdown/toggle/icon"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/empty-state/body",["exports","@hashicorp/design-system-components/components/hds/empty-state/body"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/empty-state/footer",["exports","@hashicorp/design-system-components/components/hds/empty-state/footer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/empty-state/header",["exports","@hashicorp/design-system-components/components/hds/empty-state/header"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/empty-state/index",["exports","@hashicorp/design-system-components/components/hds/empty-state/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/flyout/body",["exports","@hashicorp/design-system-components/components/hds/flyout/body"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/flyout/description",["exports","@hashicorp/design-system-components/components/hds/flyout/description"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) -define("consul-ui/components/hds/flyout/header",["exports","@hashicorp/design-system-components/components/hds/flyout/header"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/flyout/index",["exports","@hashicorp/design-system-components/components/hds/flyout/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/checkbox/base",["exports","@hashicorp/design-system-components/components/hds/form/checkbox/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/checkbox/field",["exports","@hashicorp/design-system-components/components/hds/form/checkbox/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/checkbox/group",["exports","@hashicorp/design-system-components/components/hds/form/checkbox/group"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/error/index",["exports","@hashicorp/design-system-components/components/hds/form/error/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/error/message",["exports","@hashicorp/design-system-components/components/hds/form/error/message"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/field/index",["exports","@hashicorp/design-system-components/components/hds/form/field/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/fieldset/index",["exports","@hashicorp/design-system-components/components/hds/form/fieldset/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/helper-text/index",["exports","@hashicorp/design-system-components/components/hds/form/helper-text/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/indicator/index",["exports","@hashicorp/design-system-components/components/hds/form/indicator/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/label/index",["exports","@hashicorp/design-system-components/components/hds/form/label/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/legend/index",["exports","@hashicorp/design-system-components/components/hds/form/legend/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio-card/description",["exports","@hashicorp/design-system-components/components/hds/form/radio-card/description"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio-card/group",["exports","@hashicorp/design-system-components/components/hds/form/radio-card/group"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio-card/index",["exports","@hashicorp/design-system-components/components/hds/form/radio-card/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio-card/label",["exports","@hashicorp/design-system-components/components/hds/form/radio-card/label"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio/base",["exports","@hashicorp/design-system-components/components/hds/form/radio/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio/field",["exports","@hashicorp/design-system-components/components/hds/form/radio/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio/group",["exports","@hashicorp/design-system-components/components/hds/form/radio/group"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/select/base",["exports","@hashicorp/design-system-components/components/hds/form/select/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/select/field",["exports","@hashicorp/design-system-components/components/hds/form/select/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/text-input/base",["exports","@hashicorp/design-system-components/components/hds/form/text-input/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/text-input/field",["exports","@hashicorp/design-system-components/components/hds/form/text-input/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/textarea/base",["exports","@hashicorp/design-system-components/components/hds/form/textarea/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/textarea/field",["exports","@hashicorp/design-system-components/components/hds/form/textarea/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/toggle/base",["exports","@hashicorp/design-system-components/components/hds/form/toggle/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/toggle/field",["exports","@hashicorp/design-system-components/components/hds/form/toggle/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/toggle/group",["exports","@hashicorp/design-system-components/components/hds/form/toggle/group"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/icon-tile/index",["exports","@hashicorp/design-system-components/components/hds/icon-tile/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) -define("consul-ui/components/hds/interactive/index",["exports","@hashicorp/design-system-components/components/hds/interactive/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/link/inline",["exports","@hashicorp/design-system-components/components/hds/link/inline"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/link/standalone",["exports","@hashicorp/design-system-components/components/hds/link/standalone"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/modal/body",["exports","@hashicorp/design-system-components/components/hds/modal/body"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/modal/footer",["exports","@hashicorp/design-system-components/components/hds/modal/footer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/modal/header",["exports","@hashicorp/design-system-components/components/hds/modal/header"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/modal/index",["exports","@hashicorp/design-system-components/components/hds/modal/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/compact/index",["exports","@hashicorp/design-system-components/components/hds/pagination/compact/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/info",["exports","@hashicorp/design-system-components/components/hds/pagination/info"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/nav/arrow",["exports","@hashicorp/design-system-components/components/hds/pagination/nav/arrow"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/nav/ellipsis",["exports","@hashicorp/design-system-components/components/hds/pagination/nav/ellipsis"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/nav/number",["exports","@hashicorp/design-system-components/components/hds/pagination/nav/number"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/numbered/index",["exports","@hashicorp/design-system-components/components/hds/pagination/numbered/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/size-selector",["exports","@hashicorp/design-system-components/components/hds/pagination/size-selector"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/stepper/step/indicator",["exports","@hashicorp/design-system-components/components/hds/stepper/step/indicator"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/stepper/task/indicator",["exports","@hashicorp/design-system-components/components/hds/stepper/task/indicator"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/table/index",["exports","@hashicorp/design-system-components/components/hds/table/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/table/td",["exports","@hashicorp/design-system-components/components/hds/table/td"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/table/th-sort",["exports","@hashicorp/design-system-components/components/hds/table/th-sort"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/table/th",["exports","@hashicorp/design-system-components/components/hds/table/th"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/table/tr",["exports","@hashicorp/design-system-components/components/hds/table/tr"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/tabs/index",["exports","@hashicorp/design-system-components/components/hds/tabs/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/tabs/panel",["exports","@hashicorp/design-system-components/components/hds/tabs/panel"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/tabs/tab",["exports","@hashicorp/design-system-components/components/hds/tabs/tab"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/tag/index",["exports","@hashicorp/design-system-components/components/hds/tag/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/toast/index",["exports","@hashicorp/design-system-components/components/hds/toast/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/yield/index",["exports","@hashicorp/design-system-components/components/hds/yield/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/informed-action/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"NfQBR0Ol",block:'[[[11,0],[24,0,"informed-action"],[17,1],[12],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[18,2,null],[1,"\\n "],[13],[1,"\\n "],[18,3,null],[1,"\\n "],[13],[1,"\\n "],[10,"ul"],[12],[1,"\\n "],[18,4,[[28,[37,1],null,[["Action"],[[50,"anonymous",0,null,[["tagName"],["li"]]]]]]]],[1,"\\n "],[13],[1,"\\n"],[13]],["&attrs","&header","&body","&actions"],false,["yield","hash","component"]]',moduleName:"consul-ui/components/informed-action/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/ivy-codemirror",["exports","ivy-codemirror/components/ivy-codemirror"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/jwt-source/index",["exports","@glimmer/component","@ember/service","consul-ui/utils/dom/event-source"],(function(e,t,n,l){var r,i,o,a,u -function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let d=(r=(0,n.inject)("repository/oidc-provider"),i=(0,n.inject)("dom"),o=class extends t.default{constructor(){super(...arguments),s(this,"repo",a,this),s(this,"dom",u,this),this.source&&this.source.close(),this._listeners=this.dom.listeners(),this.source=(0,l.fromPromise)(this.repo.findCodeByURL(this.args.src)),this._listeners.add(this.source,{message:e=>this.onchange(e),error:e=>this.onerror(e)})}onchange(e){"function"==typeof this.args.onchange&&this.args.onchange(...arguments)}onerror(e){"function"==typeof this.args.onerror&&this.args.onerror(...arguments)}willDestroy(){super.willDestroy(...arguments),this.source&&this.source.close(),this.repo.close(),this._listeners.remove()}},a=c(o.prototype,"repo",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(o.prototype,"dom",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) -e.default=d})) -define("consul-ui/components/list-collection/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object","ember-collection/components/ember-collection","ember-collection/layouts/percentage-columns","block-slots"],(function(e,t,n,l,r,i,o,a){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const u=(0,n.createTemplateFactory)({id:"DfcTL8bI",block:'[[[11,0],[16,0,[29,["list-collection list-collection-scroll-",[36,0]]]],[23,5,[28,[37,1],["height:",[33,2,["height"]],"px"],null]],[16,1,[36,3]],[17,1],[12],[1,"\\n"],[18,7,null],[1,"\\n"],[41,[28,[37,6],[[33,0],"virtual"],null],[[[1," "],[1,[28,[35,7],["resize",[28,[37,8],[[30,0],"resize"],null]],null]],[1,"\\n "],[8,[39,9],null,[["@tagName","@content-size","@scroll-left","@scroll-top","@scrollChange","@clientSizeChange"],["ul",[99,10,["@content-size"]],[99,11,["@scroll-left"]],[99,12,["@scroll-top"]],[28,[37,8],[[30,0],"scrollChange"],null],[28,[37,8],[[30,0],"clientSizeChange"],null]]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[13],[42,[28,[37,14],[[28,[37,14],[[33,15]],null]],null],null,[[[10,"li"],[15,"onclick",[28,[37,8],[[30,0],"click"],null]],[22,5,[30,2,["style"]]],[15,0,[52,[33,16],[52,[28,[37,17],[[33,16]],[["item"],[[30,2,["item"]]]]],"linkable"]]],[12],[1,"\\n "],[8,[39,18],null,[["@name"],["header"]],[["default"],[[[[10,0],[14,0,"header"],[12],[18,7,[[30,2,["item"]],[30,2,["index"]]]],[13]],[]]]]],[1,"\\n "],[8,[39,18],null,[["@name"],["details"]],[["default"],[[[[10,0],[14,0,"detail"],[12],[18,7,[[30,2,["item"]],[30,2,["index"]]]],[13]],[]]]]],[1,"\\n "],[8,[39,18],null,[["@name","@params"],["actions",[28,[37,19],[[50,"more-popover-menu",0,null,[["expanded","onchange"],[[52,[28,[37,6],[[33,21],[30,2,["index"]]],null],true,false],[28,[37,8],[[30,0],"change",[30,2,["index"]]],null]]]]],null]]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"actions"],[12],[1,"\\n "],[18,7,[[30,2,["item"]],[30,2,["index"]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[13]],[2]],null]],[]]]]],[1,"\\n"]],[]],[[[44,[[52,[28,[37,23],[[33,24],[28,[37,25],[[30,0,["expand"]]],null]],null],[28,[37,26],[0,[33,24],[33,27]],null],[33,27]]],[[[1," "],[10,"ul"],[12],[1,"\\n "],[10,"li"],[14,5,"display: none;"],[12],[13],[42,[28,[37,14],[[28,[37,14],[[30,3]],null]],null],null,[[[10,"li"],[15,"onclick",[28,[37,8],[[30,0],"click"],null]],[15,0,[52,[28,[37,25],[[33,16]],null],"linkable",[52,[28,[37,17],[[33,16]],[["item"],[[33,28,["item"]]]]],"linkable"]]],[12],[1,"\\n "],[8,[39,18],null,[["@name"],["header"]],[["default"],[[[[10,0],[14,0,"header"],[12],[18,7,[[30,4],[30,5]]],[13]],[]]]]],[1,"\\n "],[8,[39,18],null,[["@name"],["details"]],[["default"],[[[[10,0],[14,0,"detail"],[12],[18,7,[[30,4],[30,5]]],[13]],[]]]]],[1,"\\n "],[8,[39,18],null,[["@name","@params"],["actions",[28,[37,19],[[50,"more-popover-menu",0,null,[["onchange"],[[28,[37,8],[[30,0],"change",[30,5]],null]]]]],null]]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"actions"],[12],[1,"\\n "],[18,7,[[30,4],[30,5]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[13]],[4,5]],null],[13],[1,"\\n"],[41,[28,[37,23],[[33,24],[28,[37,29],[[33,27,["length"]],[33,24]],null]],null],[[[44,[[28,[37,30],[[30,3,["length"]],[33,27,["length"]]],null]],[[[1," "],[10,"button"],[15,0,[52,[30,6],"closed"]],[15,"onclick",[28,[37,8],[[30,0],[28,[37,31],[[30,0,["expand"]]],null],[30,6]],null]],[14,4,"button"],[12],[1,"\\n"],[41,[30,6],[[[1," View "],[1,[28,[35,32],[[33,27,["length"]],[30,3,["length"]]],null]],[1," more\\n"]],[]],[[[1," View less\\n"]],[]]],[1," "],[13],[1,"\\n"]],[6]]]],[]],null]],[3]]],[1,"\\n"]],[]]],[13]],["&attrs","cell","slice","item","index","more","&default"],false,["scroll","concat","style","guid","yield","if","eq","on-window","action","ember-native-scrollable","_contentSize","_scrollLeft","_scrollTop","each","-track-array","_cells","linkable","is","yield-slot","block-params","component","checked","let","and","partial","not","slice","items","cell","gt","not-eq","mut","sub"]]',moduleName:"consul-ui/components/list-collection/index.hbs",isStrictMode:!1}),s=o.default.prototype.formatItemStyle -var c=(0,t.setComponentTemplate)(u,i.default.extend(a.default,{dom:(0,l.inject)("dom"),tagName:"",height:500,cellHeight:70,checked:null,scroll:"virtual",init:function(){this._super(...arguments),this.columns=[100],this.guid=this.dom.guid(this)},didInsertElement:function(){this._super(...arguments),this.$element=this.dom.element(`#${this.guid}`),"virtual"===this.scroll&&this.actions.resize.apply(this,[{target:this.dom.viewport()}])},didReceiveAttrs:function(){this._super(...arguments),this._cellLayout=this["cell-layout"]=new o.default((0,r.get)(this,"items.length"),(0,r.get)(this,"columns"),(0,r.get)(this,"cellHeight")) -const e=this -this["cell-layout"].formatItemStyle=function(t){let n=s.apply(this,arguments) -return e.checked===t&&(n=`${n};z-index: 1`),n}},style:(0,r.computed)("height",(function(){return"virtual"!==this.scroll?{}:{height:(0,r.get)(this,"height")}})),actions:{resize:function(e){const t=(0,r.get)(this,"dom").element('footer[role="contentinfo"]') -if(t){const n=1,l=this.$element.getBoundingClientRect().top+t.clientHeight+n,r=e.target.innerHeight-l -this.set("height",Math.max(0,r)),this.updateItems(),this.updateScrollPosition()}},click:function(e){return this.dom.clickFirstAnchor(e,".list-collection > ul > li")},change:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -if(t.target.checked&&e!==(0,r.get)(this,"checked")){(0,r.set)(this,"checked",parseInt(e)),this.$row=this.dom.closest("li",t.target),this.$row.style.zIndex=1 -const n=this.dom.sibling(t.target,"div") -n.getBoundingClientRect().top+n.clientHeight>this.dom.element('footer[role="contentinfo"]').getBoundingClientRect().top?n.classList.add("above"):n.classList.remove("above")}else{this.dom.sibling(t.target,"div").classList.remove("above"),(0,r.set)(this,"checked",null),this.$row.style.zIndex=null}}}})) -e.default=c})),define("consul-ui/components/maybe-in-element",["exports","ember-maybe-in-element/components/maybe-in-element"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/menu-panel/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/runloop","@ember/object","block-slots"],(function(e,t,n,l,r,i,o){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const a=(0,n.createTemplateFactory)({id:"wAfNxT0t",block:'[[[18,3,null],[1,"\\n"],[44,[[28,[37,2],null,[["change"],[[28,[37,3],[[30,0],"change"],null]]]]],[[[11,0],[16,0,[28,[37,4],[[28,[37,5],["menu-panel"],null],[28,[37,5],["menu-panel-deprecated"],null],[28,[37,5],[[33,6]],null],[28,[37,5],[[33,7],"confirmation"],null]],null]],[4,[38,8],[[28,[37,3],[[30,0],"connect"],null]],null],[12],[1,"\\n "],[8,[39,9],null,[["@name"],["controls"]],[["default"],[[[[1,"\\n "],[18,3,[[30,1]]],[1,"\\n "]],[]]]]],[1,"\\n"],[6,[39,9],null,[["name"],["header"]],[["default","else"],[[[[1," "],[10,0],[12],[1,"\\n "],[18,3,[[30,1]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[],[]]]]],[1," "],[11,"ul"],[24,"role","menu"],[17,2],[12],[1,"\\n "],[8,[39,9],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[18,3,[[30,1]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],[1]]]],["api","&attrs","&default"],false,["yield","let","hash","action","class-map","array","position","isConfirmation","did-insert","yield-slot"]]',moduleName:"consul-ui/components/menu-panel/index.hbs",isStrictMode:!1}) -var u=(0,t.setComponentTemplate)(a,t.default.extend(o.default,{tagName:"",dom:(0,l.inject)("dom"),isConfirmation:!1,actions:{connect:function(e){(0,r.next)((()=>{if(!this.isDestroyed){const t=this.dom.element('li:only-child > [role="menu"]:first-child',e);(0,i.set)(this,"isConfirmation",void 0!==t)}}))},change:function(e){const t=e.target.getAttribute("id"),n=this.dom.element(`[for='${t}']`),l=this.dom.element("[role=menu]",n.parentElement),r=this.dom.closest(".menu-panel",l) -if(e.target.checked){l.style.display="block" -const e=l.offsetHeight+2 -r.style.maxHeight=r.style.minHeight=`${e}px`}else l.style.display=null,r.style.maxHeight=null,r.style.minHeight="0"}}})) -e.default=u})),define("consul-ui/components/menu/action/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"tJ7CAUii",block:'[[[8,[39,0],[[24,"role","menuitem"],[17,1],[4,[38,1],["click",[52,[30,2],[30,4,["close"]],[28,[37,3],null,null]]],null]],[["@href","@external"],[[30,2],[30,3]]],[["default"],[[[[1,"\\n "],[18,5,null],[1,"\\n"]],[]]]]],[1,"\\n"]],["&attrs","@href","@external","@disclosure","&default"],false,["action","on","if","noop","yield"]]',moduleName:"consul-ui/components/menu/action/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/menu/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"6Fvyg+h9",block:'[[[11,"ul"],[24,"role","menu"],[23,5,[28,[37,0],[[28,[37,1],["height",[52,[28,[37,3],[[30,1],[28,[37,4],[[30,1,["type"]],"native-scroll"],null]],null],[30,1,["totalHeight"]]],"px"],null],[28,[37,1],["--paged-start",[52,[28,[37,3],[[30,1],[28,[37,4],[[30,1,["type"]],"native-scroll"],null]],null],[30,1,["startHeight"]]],"px"],null]],null]],[4,[38,5],[[28,[37,6],[[30,1,["pane"]]],null]],null],[4,[38,7],null,[["onclose","openEvent"],[[28,[37,8],[[30,2],[30,3,["close"]]],null],[28,[37,8],[[30,4],[30,3,["event"]]],null]]]],[12],[1,"\\n "],[18,5,[[28,[37,10],null,[["Action","Item","Separator","items"],[[50,"menu/action",0,null,[["disclosure"],[[30,3]]]],[50,"menu/item",0,null,null],[50,"menu/separator",0,null,null],[30,1,["items"]]]]]]],[1,"\\n"],[13]],["@pager","@onclose","@disclosure","@event","&default"],false,["style-map","array","if","and","not-eq","did-insert","optional","aria-menu","or","yield","hash","component"]]',moduleName:"consul-ui/components/menu/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/menu/item/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"xyqbyNJ6",block:'[[[11,"li"],[24,"role","none"],[17,1],[12],[1,"\\n "],[18,2,null],[1,"\\n"],[13],[1,"\\n\\n"]],["&attrs","&default"],false,["yield"]]',moduleName:"consul-ui/components/menu/item/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/menu/separator/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"5tMGOxru",block:'[[[11,"li"],[24,"role","separator"],[17,1],[12],[18,2,null],[13],[1,"\\n"]],["&attrs","&default"],false,["yield"]]',moduleName:"consul-ui/components/menu/separator/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/modal-dialog/index",["exports","@ember/component","@ember/template-factory","@ember/object","block-slots","a11y-dialog","@ember/runloop"],(function(e,t,n,l,r,i,o){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const a=(0,n.createTemplateFactory)({id:"LycjAwp+",block:'[[[44,[[28,[37,1],null,[["labelledby"],[[28,[37,2],null,null]]]]],[[[1," "],[8,[39,3],null,[["@target"],["modal"]],[["default"],[[[[1,"\\n "],[18,4,null],[1,"\\n "],[11,0],[24,0,"modal-dialog"],[24,"aria-hidden","true"],[17,2],[4,[38,5],[[28,[37,6],[[30,0],"connect"],null]],null],[4,[38,7],[[28,[37,6],[[30,0],"disconnect"],null]],null],[12],[1,"\\n "],[10,0],[14,"tabindex","-1"],[14,"data-a11y-dialog-hide",""],[12],[13],[1,"\\n "],[10,0],[14,0,"modal-dialog-modal"],[14,"role","dialog"],[15,"aria-label",[30,3,["label"]]],[12],[1,"\\n "],[10,0],[14,"role","document"],[12],[1,"\\n "],[10,"header"],[14,0,"modal-dialog-header"],[12],[1,"\\n "],[8,[39,8],[[24,"data-a11y-dialog-hide",""]],[["@text","@color","@icon","@size","@isIconOnly"],["Close dialog","secondary","x","small",true]],null],[1,"\\n "],[8,[39,9],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[18,4,[[28,[37,1],null,[["open","close","opened","aria"],[[28,[37,6],[[30,0],"open"],null],[28,[37,6],[[30,0],"close"],null],[30,0,["isOpen"]],[30,1]]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"modal-dialog-body"],[12],[1,"\\n "],[8,[39,9],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[18,4,[[28,[37,1],null,[["open","close","opened","aria"],[[28,[37,6],[[30,0],"open"],null],[28,[37,6],[[30,0],"close"],null],[30,0,["isOpen"]],[30,1]]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"footer"],[14,0,"modal-dialog-footer"],[12],[1,"\\n "],[8,[39,9],null,[["@name","@params"],["actions",[28,[37,10],[[28,[37,6],[[30,0],"close"],null]],null]]],[["default"],[[[[1,"\\n "],[18,4,[[28,[37,1],null,[["open","close","opened","aria"],[[28,[37,6],[[30,0],"open"],null],[28,[37,6],[[30,0],"close"],null],[30,0,["isOpen"]],[30,1]]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[1]]]],["aria","&attrs","@aria","&default"],false,["let","hash","unique-id","portal","yield","did-insert","action","will-destroy","hds/button","yield-slot","block-params"]]',moduleName:"consul-ui/components/modal-dialog/index.hbs",isStrictMode:!1}) -var u=(0,t.setComponentTemplate)(a,t.default.extend(r.default,{tagName:"",onclose:function(){},onopen:function(){},isOpen:!1,actions:{connect:function(e){this.dialog=new i.default(e),this.dialog.on("hide",(()=>{(0,o.schedule)("afterRender",(e=>(0,l.set)(this,"isOpen",!1))),this.onclose({target:e})})),this.dialog.on("show",(()=>{(0,l.set)(this,"isOpen",!0),this.onopen({target:e})})),this.open&&this.actions.open.apply(this,[])},disconnect:function(e){this.dialog.destroy()},open:function(){this.dialog.show()},close:function(){this.dialog.hide()}}})) -e.default=u})),define("consul-ui/components/modal-layer/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"6vWxczPc",block:'[[[11,0],[24,0,"modal-layer"],[17,1],[12],[1,"\\n "],[8,[39,0],null,[["@name","@multiple"],["modal",true]],null],[1,"\\n"],[13],[1,"\\n"]],["&attrs"],false,["portal-target"]]',moduleName:"consul-ui/components/modal-layer/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/more-popover-menu/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"9USQK1Le",block:'[[[11,0],[24,0,"more-popover-menu"],[17,1],[12],[1,"\\n "],[8,[39,0],null,[["@expanded","@onchange","@keyboardAccess"],[[99,1,["@expanded"]],[28,[37,2],[[30,0],[33,3]],null],false]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n More\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[18,4,[[30,2,["MenuItem"]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[2,3]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","components","api","&default"],false,["popover-menu","expanded","action","onchange","block-slot","yield"]]',moduleName:"consul-ui/components/more-popover-menu/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) -e.default=r})),define("consul-ui/components/oidc-select/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={id:"oidc-select",initial:"idle",on:{RESET:[{target:"idle"}]},states:{idle:{on:{LOAD:[{target:"loading"}]}},loaded:{},loading:{on:{SUCCESS:[{target:"loaded"}]}}}}})),define("consul-ui/components/oidc-select/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","consul-ui/components/oidc-select/chart.xstate"],(function(e,t,n,l,r,i){var o,a -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const u=(0,n.createTemplateFactory)({id:"1JjkWJfY",block:'[[[8,[39,0],null,[["@src"],[[99,1,["@src"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],null,[["State","Guard","Action","dispatch","state"],[[30,1],[30,2],[30,3],[30,4],[30,5]]]]],[[[1,"\\n "],[11,0],[24,0,"oidc-select"],[17,7],[12],[1,"\\n "],[8,[30,1],null,[["@notMatches"],["idle"]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@src","@onchange","@onerror"],[[28,[37,5],["/${partition}/${nspace}/${dc}/oidc/providers",[28,[37,3],null,[["partition","nspace","dc"],[[30,0,["partition"]],[30,8],[30,9]]]]],null],[28,[37,6],[[28,[37,7],[[30,0],[28,[37,8],[[30,0,["items"]]],null]],[["value"],["data"]]],[28,[37,9],[[30,4],"SUCCESS"],null]],null],[28,[37,6],[[28,[37,9],[[30,4],"RESET"],null],[30,10]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["loaded"]],[["default"],[[[[1,"\\n "],[8,[39,7],[[24,0,"reset"],[4,[38,10],["click",[28,[37,6],[[28,[37,11],[[30,0],"partition",""],null],[28,[37,9],[[30,4],"RESET"],null]],null]],null]],null,[["default"],[[[[1,"\\n Choose different Partition\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,0],null,[["@src"],[[28,[37,0],["validate"],null]]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@name","@label","@item","@validations","@placeholder","@oninput","@chart"],["partition","Admin Partition",[30,0],[28,[37,3],null,[["partition"],[[28,[37,13],[[28,[37,3],null,[["test","error"],["^[a-zA-Z0-9]([a-zA-Z0-9-]{0,62}[a-zA-Z0-9])?$","Name must be a valid DNS hostname."]]]],null]]]],"Enter your Partition",[28,[37,7],[[30,0],[28,[37,8],[[30,0,["partition"]]],null]],[["value"],["target.value"]]],[28,[37,3],null,[["state","dispatch"],[[30,15],[30,14]]]]]],null],[1,"\\n\\n"],[1," "],[8,[30,1],null,[["@matches"],["idle"]],[["default"],[[[[1,"\\n "],[8,[39,14],[[16,"disabled",[28,[37,15],[[28,[37,16],[[30,0,["partition","length"]],1],null],[28,[37,17],[[30,15],"error"],null]],null]],[24,4,"submit"],[4,[38,10],["click",[28,[37,9],[[30,4],"LOAD"],null]],null]],[["@text"],["Choose provider"]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "]],[11,12,13,14,15]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["loading"]],[["default"],[[[[1,"\\n "],[8,[39,18],[[24,"aria-label","Loading"]],null,null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["loaded"]],[["default"],[[[[1,"\\n"],[41,[28,[37,16],[[30,0,["items","length"]],3],null],[[[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,21],[[28,[37,21],[[30,0,["items"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[8,[39,7],[[16,0,[28,[37,22],[[30,16,["Kind"]],"-oidc-provider"],null]],[16,"disabled",[30,17]],[4,[38,10],["click",[28,[37,9],[[30,18],[30,16]],null]],null]],[["@type"],["button"]],[["default"],[[[[1,"\\n Continue with\\n "],[1,[28,[35,15],[[30,16,["DisplayName"]],[30,16,["Name"]]],null]],[41,[28,[37,23],[[30,16,["Namespace"]],"default"],null],[[[1,"\\n ("],[1,[30,16,["Namespace"]]],[1,")"]],[]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[16]],null],[1," "],[13],[1,"\\n\\n"]],[]],[[[1,"\\n"],[44,[[28,[37,15],[[30,0,["provider"]],[28,[37,24],[0,[30,0,["items"]]],null]],null]],[[[1,"\\n "],[8,[39,25],null,[["@label","@name","@item","@selected","@items","@onchange","@disabled"],["SSO Provider","provider",[30,0],[30,19],[30,0,["items"]],[28,[37,7],[[30,0],[28,[37,8],[[30,0,["provider"]]],null]],null],[30,17]]],[["option"],[[[[1,"\\n "],[10,1],[15,0,[28,[37,22],[[30,20,["item","Kind"]],"-oidc-provider"],null]],[12],[1,"\\n "],[1,[28,[35,15],[[30,20,["item","DisplayName"]],[30,20,["item","Name"]]],null]],[41,[28,[37,23],[[30,20,["item","Namespace"]],"default"],null],[[[1," ("],[1,[30,20,["item","Namespace"]]],[1,")"]],[]],null],[1,"\\n "],[13],[1,"\\n "]],[20]]]]],[1,"\\n\\n "],[8,[39,14],[[16,"disabled",[30,17]],[4,[38,10],["click",[28,[37,9],[[30,18],[30,19]],null]],null]],[["@color","@text"],["primary","Log in"]],null],[1,"\\n"]],[19]]]],[]]],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[6]]]],[1,2,3,4,5]]]]],[1,"\\n"]],["State","Guard","ChartAction","dispatch","state","chart","&attrs","@nspace","@dc","@onerror","ignoredState","ignoredGuard","ignoredAction","formDispatch","state","item","@disabled","@onchange","item","option"],false,["state-chart","chart","let","hash","data-source","uri","queue","action","mut","fn","on","set","text-input","array","hds/button","or","lt","state-matches","progress","if","each","-track-array","concat","not-eq","object-at","option-input"]]',moduleName:"consul-ui/components/oidc-select/index.hbs",isStrictMode:!1}) -let s=(o=class extends l.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="partition",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),this.chart=i.default,this.args.partition&&(this.partition=this.args.partition)}},c=o.prototype,d="partition",p=[r.tracked],f={configurable:!0,enumerable:!0,writable:!0,initializer:function(){return"default"}},h={},Object.keys(f).forEach((function(e){h[e]=f[e]})),h.enumerable=!!h.enumerable,h.configurable=!!h.configurable,("value"in h||h.initializer)&&(h.writable=!0),h=p.slice().reverse().reduce((function(e,t){return t(c,d,e)||e}),h),m&&void 0!==h.initializer&&(h.value=h.initializer?h.initializer.call(m):void 0,h.initializer=void 0),void 0===h.initializer&&(Object.defineProperty(c,d,h),h=null),a=h,o) -var c,d,p,f,m,h -e.default=s,(0,t.setComponentTemplate)(u,s)})),define("consul-ui/components/option-input/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"hk9fkczL",block:'[[[8,[39,0],[[24,0,"option-input type-select"],[17,1]],[["@item","@placeholder","@name","@label","@help","@validations","@chart"],[[30,2],[30,3],[30,4],[30,5],[30,6],[30,7],[30,8]]],[["label","input"],[[[[1,"\\n"],[1," "],[1,[28,[35,1],[[30,5],[30,4]],null]],[1,"\\n "]],[]],[[[1,"\\n"],[41,[30,9],[[[41,[30,10],[[],[]],[[],[]]]],[]],[[[1," "],[8,[39,3],null,[["@disabled","@onChange","@selected","@searchEnabled","@options"],[[30,11],[30,12],[30,13],false,[30,14]]],[["default"],[[[[1,"\\n "],[18,16,[[28,[37,5],null,[["item"],[[30,15]]]]]],[1,"\\n "]],[15]]]]],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n"]],["&attrs","@item","@placeholder","@name","@label","@help","@validations","@chart","@expanded","@multiple","@disabled","@onchange","@selected","@items","item","&option"],false,["form-input","or","if","power-select","yield","hash"]]',moduleName:"consul-ui/components/option-input/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/outlet/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object","@ember/service"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m,h,b,y -function g(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function v(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const O=(0,n.createTemplateFactory)({id:"X7pi+rvm",block:'[[[1,[28,[35,0],[[30,0,["connect"]]],null]],[1,"\\n"],[1,[28,[35,1],[[30,0,["disconnect"]]],null]],[1,"\\n"],[11,"section"],[24,0,"outlet"],[16,"data-outlet",[30,1]],[16,"data-route",[30,0,["routeName"]]],[16,"data-state",[30,0,["state","name"]]],[16,"data-transition",[28,[37,2],[[30,0,["previousState","name"]]," ",[30,0,["state","name"]]],null]],[4,[38,0],[[28,[37,3],[[30,0,["attributeChanged"]],"element"],null]],null],[4,[38,4],[[28,[37,3],[[30,0,["attributeChanged"]],"model",[30,2]],null]],null],[4,[38,5],["transitionend",[30,0,["transitionEnd"]]],null],[12],[1,"\\n "],[18,3,[[28,[37,7],null,[["state","previousState","route"],[[30,0,["state"]],[30,0,["previousState"]],[30,0,["route"]]]]]]],[1,"\\n"],[13]],["@name","@model","&default"],false,["did-insert","will-destroy","concat","fn","did-update","on","yield","hash"]]',moduleName:"consul-ui/components/outlet/index.hbs",isStrictMode:!1}) -class P{constructor(e){this.name=e}matches(e){return this.name===e}}let x=(a=(0,o.inject)("routlet"),u=(0,o.inject)("router"),s=class extends l.default{constructor(){super(...arguments),g(this,"routlet",c,this),g(this,"router",d,this),g(this,"element",p,this),g(this,"routeName",f,this),g(this,"state",m,this),g(this,"previousState",h,this),g(this,"endTransition",b,this),g(this,"route",y,this)}get model(){return this.args.model||{}}get name(){return this.args.name}setAppRoute(e){if("loading"!==e||"oidc-provider-debug"===e){const t=this.element.ownerDocument.documentElement -t.classList.contains("ember-loading")&&t.classList.remove("ember-loading"),t.dataset.route=e,this.setAppState("idle")}}setAppState(e){this.element.ownerDocument.documentElement.dataset.state=e}attributeChanged(e,t){switch(e){case"element":this.element=t,"application"===this.args.name&&(this.setAppState("loading"),this.setAppRoute(this.router.currentRouteName)) -break -case"model":void 0!==this.route&&(this.route._model=t)}}transitionEnd(e){"function"==typeof this.endTransition&&this.endTransition()}startLoad(e){const t=this.routlet.findOutlet(e.to.name)||"application" -if(this.args.name===t){let e -this.previousState=this.state,this.state=new P("loading"),this.endTransition=this.routlet.transition(),e=this.element?window.getComputedStyle(this.element).getPropertyValue("transition-duration"):0,0===parseFloat(e)&&this.endTransition()}"application"===this.args.name&&this.setAppState("loading")}endLoad(e){this.state.matches("loading")&&(this.previousState=this.state,this.state=new P("idle")),"application"===this.args.name&&this.setAppRoute(this.router.currentRouteName)}connect(){this.routlet.addOutlet(this.args.name,this),this.previousState=this.state=new P("idle"),this.router.on("routeWillChange",this.startLoad),this.router.on("routeDidChange",this.endLoad)}disconnect(){this.routlet.removeOutlet(this.args.name),this.router.off("routeWillChange",this.startLoad),this.router.off("routeDidChange",this.endLoad)}},c=v(s.prototype,"routlet",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=v(s.prototype,"router",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=v(s.prototype,"element",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=v(s.prototype,"routeName",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=v(s.prototype,"state",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=v(s.prototype,"previousState",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=v(s.prototype,"endTransition",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=v(s.prototype,"route",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v(s.prototype,"attributeChanged",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"attributeChanged"),s.prototype),v(s.prototype,"transitionEnd",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"transitionEnd"),s.prototype),v(s.prototype,"startLoad",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"startLoad"),s.prototype),v(s.prototype,"endLoad",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"endLoad"),s.prototype),v(s.prototype,"connect",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"connect"),s.prototype),v(s.prototype,"disconnect",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"disconnect"),s.prototype),s) -e.default=x,(0,t.setComponentTemplate)(O,x)})),define("consul-ui/components/paged-collection/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","@glimmer/tracking","@ember/runloop"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m -function h(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function b(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const y=(0,n.createTemplateFactory)({id:"4n2jhP/a",block:'[[[18,2,[[28,[37,1],null,[["items","page","pane","resize","viewport","rowHeight","maxHeight","startHeight","totalHeight","totalPages","Pager"],[[30,0,["items"]],[30,1],[28,[37,2],[[30,0,["setPane"]]],null],[28,[37,2],[[30,0,["resize"]]],null],[28,[37,2],[[30,0,["setViewport"]]],null],[28,[37,2],[[30,0,["setRowHeight"]]],null],[28,[37,2],[[30,0,["setMaxHeight"]]],null],[30,0,["startHeight"]],[30,0,["totalHeight"]],[30,0,["totalPages"]],[52,[28,[37,4],[[33,5],"index"],null],[50,"yield",0,null,null],""]]]]]],[1,"\\n\\n"],[1,[28,[35,7],[[30,0,["disconnect"]]],null]],[1,"\\n"]],["@page","&default"],false,["yield","hash","fn","if","eq","type","component","will-destroy"]]',moduleName:"consul-ui/components/paged-collection/index.hbs",isStrictMode:!1}) -let g=(a=class extends l.default{constructor(){super(...arguments),h(this,"$pane",u,this),h(this,"$viewport",s,this),h(this,"top",c,this),h(this,"visibleItems",d,this),h(this,"overflow",p,this),h(this,"_rowHeight",f,this),h(this,"_type",m,this)}get type(){return this.args.type||this._type}get items(){return this.args.items.slice(this.cursor,this.cursor+this.perPage)}get perPage(){switch(this.type){case"virtual-scroll":return this.visibleItems+2*this.overflow -case"index":return parseInt(this.args.perPage)}return this.total}get cursor(){switch(this.type){case"virtual-scroll":return this.itemsBefore -case"index":return(parseInt(this.args.page)-1)*this.perPage}return 0}get itemsBefore(){return void 0===this.$viewport?0:Math.max(0,Math.round(this.top/this.rowHeight)-this.overflow)}get rowHeight(){return parseFloat(this.args.rowHeight||this._rowHeight)}get startHeight(){switch(this.type){case"virtual-scroll":return Math.min(this.totalHeight,this.itemsBefore*this.rowHeight) -case"index":return 0}return 0}get totalHeight(){return this.total*this.rowHeight}get totalPages(){return Math.ceil(this.total/this.perPage)}get total(){return this.args.items.length}scroll(e){this.top=this.$viewport.scrollTop}resize(){this.$viewport.clientHeight>0&&this.rowHeight>0?this.visibleItems=Math.ceil(this.$viewport.clientHeight/this.rowHeight):this.visibleItems=0}setViewport(e){this.$viewport="html"===e?[...document.getElementsByTagName("html")][0]:e,this.$viewport.addEventListener("scroll",this.scroll),"html"===e&&this.$viewport.addEventListener("resize",this.resize),this.scroll(),this.resize()}setPane(e){this.$pane=e}setRowHeight(e){this._rowHeight=parseFloat(e)}setMaxHeight(e){(0,o.scheduleOnce)("actions",this,"_setMaxHeight")}_setMaxHeight(e){const t=parseFloat(e) -isNaN(t)||(this._type="virtual-scroll")}disconnect(){this.$viewport.removeEventListener("scroll",this.scroll),this.$viewport.removeEventListener("resize",this.resize)}},u=b(a.prototype,"$pane",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s=b(a.prototype,"$viewport",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=b(a.prototype,"top",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return 0}}),d=b(a.prototype,"visibleItems",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return 0}}),p=b(a.prototype,"overflow",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return 10}}),f=b(a.prototype,"_rowHeight",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return 0}}),m=b(a.prototype,"_type",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return"native-scroll"}}),b(a.prototype,"scroll",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"scroll"),a.prototype),b(a.prototype,"resize",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"resize"),a.prototype),b(a.prototype,"setViewport",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"setViewport"),a.prototype),b(a.prototype,"setPane",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"setPane"),a.prototype),b(a.prototype,"setRowHeight",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"setRowHeight"),a.prototype),b(a.prototype,"setMaxHeight",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"setMaxHeight"),a.prototype),b(a.prototype,"_setMaxHeight",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"_setMaxHeight"),a.prototype),b(a.prototype,"disconnect",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"disconnect"),a.prototype),a) -e.default=g,(0,t.setComponentTemplate)(y,g)})),define("consul-ui/components/panel/index.css",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>e` - .panel { - --padding-x: 14px; - --padding-y: 14px; - } - .panel { - position: relative; - } - .panel-separator { - margin: 0; - } - - .panel { - --tone-border: var(--token-color-palette-neutral-300); - border: var(--decor-border-100); - border-radius: var(--decor-radius-200); - box-shadow: var(--token-surface-high-box-shadow); - } - .panel-separator { - border: 0; - border-top: var(--decor-border-100); - } - .panel { - color: var(--token-color-foreground-strong); - background-color: var(--token-color-surface-primary); - } - .panel, - .panel-separator { - border-color: var(--tone-border); - } -`})),define("consul-ui/components/peerings/badge/icon/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"gV8UFvY5",block:'[[[41,[28,[37,1],[[28,[37,2],[[30,1],"PENDING"],null],[28,[37,2],[[30,1],"ESTABLISHING"],null]],null],[[[11,"svg"],[24,"width","16"],[24,"height","16"],[24,"viewBox","0 0 16 16"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[17,2],[12],[1,"\\n "],[10,"path"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M8 1.5C6.14798 1.5 4.47788 2.27358 3.29301 3.51732C3.0073 3.81723 2.53256 3.82874 2.23266 3.54303C1.93275 3.25732 1.92125 2.78258 2.20696 2.48268C3.66316 0.954124 5.72078 0 8 0C10.2792 0 12.3368 0.954124 13.793 2.48268C14.0788 2.78258 14.0672 3.25732 13.7673 3.54303C13.4674 3.82874 12.9927 3.81723 12.707 3.51732C11.5221 2.27358 9.85202 1.5 8 1.5ZM1.23586 5.27899C1.63407 5.39303 1.86443 5.80828 1.75039 6.20649C1.58749 6.7753 1.5 7.3768 1.5 8C1.5 11.0649 3.62199 13.636 6.47785 14.321C6.88064 14.4176 7.12885 14.8224 7.03225 15.2252C6.93565 15.628 6.53081 15.8762 6.12802 15.7796C2.61312 14.9366 0 11.7744 0 8C0 7.23572 0.107387 6.49527 0.30836 5.79351C0.422401 5.39531 0.837659 5.16494 1.23586 5.27899ZM14.7641 5.27899C15.1623 5.16494 15.5776 5.39531 15.6916 5.79351C15.8926 6.49527 16 7.23572 16 8C16 11.7744 13.3869 14.9366 9.87199 15.7796C9.4692 15.8762 9.06436 15.628 8.96775 15.2252C8.87115 14.8224 9.11936 14.4176 9.52215 14.321C12.378 13.636 14.5 11.0649 14.5 8C14.5 7.3768 14.4125 6.7753 14.2496 6.20649C14.1356 5.80828 14.3659 5.39303 14.7641 5.27899Z"],[14,"fill","#3B3D45"],[12],[13],[1,"\\n "],[10,"path"],[14,"opacity","0.2"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M8 4.5C6.067 4.5 4.5 6.067 4.5 8C4.5 9.933 6.067 11.5 8 11.5C9.933 11.5 11.5 9.933 11.5 8C11.5 6.067 9.933 4.5 8 4.5ZM3 8C3 5.23858 5.23858 3 8 3C10.7614 3 13 5.23858 13 8C13 10.7614 10.7614 13 8 13C5.23858 13 3 10.7614 3 8Z"],[14,"fill","#000001"],[12],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null],[41,[28,[37,2],[[30,1],"ACTIVE"],null],[[[11,"svg"],[24,"width","16"],[24,"height","16"],[24,"viewBox","0 0 16 16"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[17,2],[12],[1,"\\n "],[10,"path"],[14,"d","M14.7803 4.28033C15.0732 3.98744 15.0732 3.51256 14.7803 3.21967C14.4874 2.92678 14.0126 2.92678 13.7197 3.21967L5.75 11.1893L2.28033 7.71967C1.98744 7.42678 1.51256 7.42678 1.21967 7.71967C0.926777 8.01256 0.926777 8.48744 1.21967 8.78033L5.21967 12.7803C5.51256 13.0732 5.98744 13.0732 6.28033 12.7803L14.7803 4.28033Z"],[14,"fill","#00781E"],[12],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null],[41,[28,[37,2],[[30,1],"FAILING"],null],[[[11,"svg"],[24,"width","16"],[24,"height","16"],[24,"viewBox","0 0 16 16"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[17,2],[12],[1,"\\n "],[10,"path"],[14,"d","M12.7803 4.28033C13.0732 3.98744 13.0732 3.51256 12.7803 3.21967C12.4874 2.92678 12.0126 2.92678 11.7197 3.21967L8 6.93934L4.28033 3.21967C3.98744 2.92678 3.51256 2.92678 3.21967 3.21967C2.92678 3.51256 2.92678 3.98744 3.21967 4.28033L6.93934 8L3.21967 11.7197C2.92678 12.0126 2.92678 12.4874 3.21967 12.7803C3.51256 13.0732 3.98744 13.0732 4.28033 12.7803L8 9.06066L11.7197 12.7803C12.0126 13.0732 12.4874 13.0732 12.7803 12.7803C13.0732 12.4874 13.0732 12.0126 12.7803 11.7197L9.06066 8L12.7803 4.28033Z"],[14,"fill","#C00005"],[12],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null],[1,"\\n"],[41,[28,[37,2],[[30,1],"TERMINATED"],null],[[[11,"svg"],[24,"width","16"],[24,"height","17"],[24,"viewBox","0 0 16 17"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[17,2],[12],[1,"\\n "],[10,"path"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M3.13889 2.55566C2.78604 2.55566 2.5 2.8417 2.5 3.19455V12.9168C2.5 13.2696 2.78604 13.5557 3.13889 13.5557H12.8611C13.214 13.5557 13.5 13.2696 13.5 12.9168V3.19455C13.5 2.8417 13.214 2.55566 12.8611 2.55566H3.13889ZM1 3.19455C1 2.01328 1.95761 1.05566 3.13889 1.05566H12.8611C14.0424 1.05566 15 2.01328 15 3.19455V12.9168C15 14.0981 14.0424 15.0557 12.8611 15.0557H3.13889C1.95761 15.0557 1 14.0981 1 12.9168V3.19455ZM4.71967 4.77533C5.01256 4.48244 5.48744 4.48244 5.78033 4.77533L8 6.995L10.2197 4.77533C10.5126 4.48244 10.9874 4.48244 11.2803 4.77533C11.5732 5.06823 11.5732 5.5431 11.2803 5.83599L9.06066 8.05566L11.2803 10.2753C11.5732 10.5682 11.5732 11.0431 11.2803 11.336C10.9874 11.6289 10.5126 11.6289 10.2197 11.336L8 9.11632L5.78033 11.336C5.48744 11.6289 5.01256 11.6289 4.71967 11.336C4.42678 11.0431 4.42678 10.5682 4.71967 10.2753L6.93934 8.05566L4.71967 5.83599C4.42678 5.5431 4.42678 5.06823 4.71967 4.77533Z"],[14,"fill","#3B3D45"],[12],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null],[41,[28,[37,2],[[30,1],"UNDEFINED"],null],[[[11,"svg"],[24,"width","16"],[24,"height","16"],[24,"viewBox","0 0 16 16"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[17,2],[12],[1,"\\n"],[10,"path"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M8.1969 4.52275C7.83582 4.45975 7.46375 4.52849 7.14594 4.7185C6.82781 4.9087 6.58324 5.20915 6.45878 5.56907C6.32341 5.96054 5.89632 6.16815 5.50485 6.03278C5.11338 5.89741 4.90577 5.47032 5.04114 5.07886C5.27962 4.3892 5.75141 3.80461 6.37621 3.43106C7.00132 3.05732 7.73786 2.91999 8.45475 3.04508C9.17148 3.17015 9.81887 3.54878 10.2837 4.11048C10.7481 4.67171 11.0009 5.37994 11 6.10959C10.9999 6.59724 10.9078 7.01534 10.7254 7.37628C10.5432 7.73694 10.2936 7.9952 10.0464 8.19341C9.85239 8.34899 9.63602 8.48431 9.46464 8.59149C9.431 8.61253 9.39909 8.63248 9.36942 8.65129C9.16778 8.77916 9.02667 8.87887 8.91689 8.99055C8.81461 9.0946 8.77388 9.18682 8.75706 9.23816C8.74978 9.26038 8.74659 9.27628 8.74537 9.28347C8.72786 9.68216 8.3991 10 7.9961 10C7.58189 10 7.2461 9.66422 7.2461 9.25C7.24626 9.08689 7.28103 8.92552 7.33163 8.77109C7.41129 8.52797 7.56353 8.22758 7.84718 7.93902C8.0857 7.69637 8.35223 7.52016 8.56613 7.38452C8.61117 7.35596 8.65343 7.32942 8.69337 7.30434C8.8616 7.1987 8.98859 7.11896 9.10803 7.02318C9.24074 6.91676 9.32751 6.81683 9.38666 6.69978C9.44562 6.5831 9.49996 6.4041 9.49996 6.10918L9.49996 6.10808C9.50052 5.72536 9.36781 5.35654 9.12803 5.06677C8.88848 4.77728 8.55813 4.58578 8.1969 4.52275Z"],[14,"fill","#3B3D45"],[12],[13],[1,"\\n"],[10,"path"],[14,"d","M8 11C7.44772 11 7 11.4477 7 12C7 12.5523 7.44772 13 8 13H8.00667C8.55895 13 9.00667 12.5523 9.00667 12C9.00667 11.4477 8.55895 11 8.00667 11H8Z"],[14,"fill","#3B3D45"],[12],[13],[1,"\\n"],[10,"path"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8ZM8 1.5C4.41015 1.5 1.5 4.41015 1.5 8C1.5 11.5899 4.41015 14.5 8 14.5C11.5899 14.5 14.5 11.5899 14.5 8C14.5 4.41015 11.5899 1.5 8 1.5Z"],[14,"fill","#3B3D45"],[12],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null],[1,"\\n"],[41,[28,[37,2],[[30,1],"DELETING"],null],[[[10,"svg"],[14,"width","16"],[14,"height","16"],[14,"viewBox","0 0 16 16"],[14,"fill","none"],[14,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[12],[1,"\\n"],[10,"path"],[14,"opacity","0.2"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M8 1.5C4.41015 1.5 1.5 4.41015 1.5 8C1.5 11.5899 4.41015 14.5 8 14.5C11.5899 14.5 14.5 11.5899 14.5 8C14.5 4.41015 11.5899 1.5 8 1.5ZM0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8Z"],[14,"fill","#000001"],[12],[13],[1,"\\n"],[10,"path"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M7.25 0.75C7.25 0.335786 7.58579 0 8 0C12.4183 0 16 3.58172 16 8C16 8.41421 15.6642 8.75 15.25 8.75C14.8358 8.75 14.5 8.41421 14.5 8C14.5 4.41015 11.5899 1.5 8 1.5C7.58579 1.5 7.25 1.16421 7.25 0.75Z"],[14,"fill","#3B3D45"],[12],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null]],["@state","&attrs"],false,["if","or","eq"]]',moduleName:"consul-ui/components/peerings/badge/icon/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/peerings/badge/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"Fxysa+1X",block:'[[[41,[30,1,["State"]],[[[1," "],[11,0],[16,0,[29,["peerings-badge ",[28,[37,1],[[30,1,["State"]]],null]]]],[4,[38,2],[[30,0,["tooltip"]]],null],[12],[1,"\\n "],[8,[39,3],null,[["@state"],[[29,[[30,1,["State"]]]]]],null],[1,"\\n "],[10,1],[14,0,"peerings-badge__text"],[12],[1,[28,[35,4],[[28,[37,1],[[30,1,["State"]]],null]],null]],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],["@peering"],false,["if","lowercase","tooltip","peerings/badge/icon","capitalize"]]',moduleName:"consul-ui/components/peerings/badge/index.hbs",isStrictMode:!1}),i={ACTIVE:{tooltip:"This peer connection is currently active."},PENDING:{tooltip:"This peering connection has not been established yet."},ESTABLISHING:{tooltip:"This peering connection is in the process of being established."},FAILING:{tooltip:"This peering connection has some intermittent errors (usually network related). It will continue to retry. "},DELETING:{tooltip:"This peer is in the process of being deleted."},TERMINATED:{tooltip:"Someone in the other peer may have deleted this peering connection."},UNDEFINED:{tooltip:""}} -class o extends l.default{get styles(){const{peering:{State:e}}=this.args -return i[e]}get tooltip(){return this.styles.tooltip}}e.default=o,(0,t.setComponentTemplate)(r,o)})),define("consul-ui/components/peerings/provider/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/application","consul-ui/components/tab-nav"],(function(e,t,n,l,r,i,o){var a,u,s -function c(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function d(e){for(var t=1;tnew o.Tab(d(d({},e),{},{currentRouteName:t.currentRouteName,owner:n}))))}},u=m(a.prototype,"router",[r.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s=m(a.prototype,"intl",[r.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a) -e.default=b,(0,t.setComponentTemplate)(h,b)})),define("consul-ui/components/policy-form/index",["exports","@ember/component","@ember/template-factory","consul-ui/components/form-component/index","@ember/object"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i=(0,n.createTemplateFactory)({id:"N+FAvdR9",block:'[[[18,6,null],[1,"\\n"],[11,"fieldset"],[24,0,"policy-form"],[16,"disabled",[52,[28,[37,2],[[28,[37,3],["write policy"],[["item"],[[33,4]]]]],null],"disabled"]],[17,1],[12],[1,"\\n"],[6,[39,5],null,[["name"],["template"]],[["default","else"],[[[],[]],[[[1," "],[10,"header"],[12],[1,"\\n Policy"],[1,[52,[33,6]," or identity?",""]],[1,"\\n "],[13],[1,"\\n"],[41,[33,6],[[[1," "],[10,2],[12],[1,"\\n Identities are default policies with configurable names. They save you some time and effort you\'re using Consul for Connect features.\\n "],[13],[1,"\\n"],[1," "],[10,0],[14,"role","radiogroup"],[15,0,[52,[33,4,["error","Type"]]," has-error"]],[12],[1,"\\n"],[42,[28,[37,8],[[28,[37,8],[[33,9]],null]],null],null,[[[1," "],[10,"label"],[12],[1,"\\n "],[10,1],[12],[1,[30,2,["name"]]],[13],[1,"\\n "],[10,"input"],[15,3,[28,[37,10],[[33,11],"[template]"],null]],[15,2,[30,2,["template"]]],[15,"checked",[28,[37,12],[[33,4,["template"]],[30,2,["template"]]],null]],[15,"onchange",[28,[37,13],[[30,0],[28,[37,14],[[28,[37,15],[[33,4],"template"],null]],null]],[["value"],["target.value"]]]],[14,4,"radio"],[12],[13],[1,"\\n "],[13],[1,"\\n"]],[2]],null],[1," "],[13],[1,"\\n"]],[]],[[[1," "],[10,"input"],[15,3,[28,[37,10],[[33,11],"[template]"],null]],[14,2,""],[14,4,"hidden"],[12],[13],[1,"\\n"]],[]]]],[]]]]],[1," "],[10,"label"],[15,0,[29,["type-text",[52,[28,[37,16],[[33,4,["error","Name"]],[28,[37,2],[[33,4,["isPristine"]]],null]],null]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Name"],[13],[1,"\\n "],[10,"input"],[15,2,[33,4,["Name"]]],[15,3,[29,[[36,11],"[Name]"]]],[14,"autofocus","autofocus"],[15,"oninput",[28,[37,13],[[30,0],"change"],null]],[14,4,"text"],[12],[13],[1,"\\n "],[10,"em"],[12],[1,"\\n Maximum 128 characters. May only include letters (uppercase and/or lowercase) and/or numbers. Must be unique.\\n "],[13],[1,"\\n"],[41,[28,[37,16],[[33,4,["error","Name"]],[28,[37,2],[[33,4,["isPristine"]]],null]],null],[[[1," "],[10,"strong"],[12],[1,[33,4,["error","Name","validation"]]],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[10,"label"],[14,"for",""],[14,0,"type-text"],[12],[1,"\\n"],[41,[28,[37,12],[[33,4,["template"]],"service-identity"],null],[[[1," "],[8,[39,17],null,[["@readonly","@name","@syntax","@oninput"],[true,[28,[37,10],[[33,11],"[Rules]"],null],"hcl",[28,[37,13],[[30,0],"change",[28,[37,10],[[33,11],"[Rules]"],null]],null]]],[["label","content"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,18],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]],[[[8,[39,19],null,[["@nspace","@partition","@name"],[[99,20,["@nspace"]],[99,21,["@partition"]],[33,4,["Name"]]]],null]],[]]]]],[1,"\\n"]],[]],[[[41,[28,[37,12],[[33,4,["template"]],"node-identity"],null],[[[1," "],[8,[39,17],null,[["@readonly","@name","@syntax","@oninput"],[true,[28,[37,10],[[33,11],"[Rules]"],null],"hcl",[28,[37,13],[[30,0],"change",[28,[37,10],[[33,11],"[Rules]"],null]],null]]],[["label","content"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,18],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]],[[[8,[39,22],null,[["@name","@partition"],[[33,4,["Name"]],[99,21,["@partition"]]]],null]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,17],null,[["@syntax","@class","@name","@value","@onkeyup"],["hcl",[52,[33,4,["error","Rules"]],"error"],[28,[37,10],[[33,11],"[Rules]"],null],[33,4,["Rules"]],[28,[37,13],[[30,0],"change",[28,[37,10],[[33,11],"[Rules]"],null]],null]]],[["label"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,18],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[33,4,["error","Rules"]],[[[1," "],[10,"strong"],[12],[1,[33,4,["error","Rules","validation"]]],[13],[1,"\\n"]],[]],null]],[]]]],[]]],[1," "],[13],[1,"\\n"],[41,[28,[37,12],[[33,4,["template"]],"node-identity"],null],[[[1,"\\n "],[8,[39,23],null,[["@src","@onchange"],[[28,[37,24],["/*/*/*/datacenters"],null],[28,[37,13],[[30,0],[28,[37,25],[[33,26]],null]],[["value"],["data"]]]]],null],[1,"\\n "],[10,"label"],[14,0,"type-select"],[12],[1,"\\n "],[10,1],[12],[1,"Datacenter"],[13],[1,"\\n "],[8,[39,27],null,[["@options","@searchField","@selected","@searchPlaceholder","@onChange"],[[28,[37,28],["Name",[33,26]],null],"Name",[28,[37,29],[[33,4,["Datacenter"]],[33,30]],null],"Type a datacenter name",[28,[37,13],[[30,0],"change","Datacenter"],null]]],[["default"],[[[[1,"\\n "],[1,[30,3]],[1,"\\n "]],[3]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[41,[28,[37,12],[[28,[37,29],[[33,21],"default"],null],"default"],null],[[[1," "],[10,0],[14,0,"type-toggle"],[12],[1,"\\n "],[10,1],[12],[1,"Valid datacenters"],[13],[1,"\\n "],[10,"label"],[12],[1,"\\n "],[10,"input"],[15,3,[29,[[36,11],"[isScoped]"]]],[15,"checked",[52,[28,[37,2],[[33,31]],null],"checked"]],[15,"onchange",[28,[37,13],[[30,0],"change"],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,1],[12],[1,"All"],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[33,31],[[[1," "],[8,[39,23],null,[["@src","@onchange"],[[28,[37,24],["/*/*/*/datacenters"],null],[28,[37,13],[[30,0],[28,[37,25],[[33,26]],null]],[["value"],["data"]]]]],null],[1,"\\n\\n "],[10,0],[14,0,"checkbox-group"],[14,"role","group"],[12],[1,"\\n"],[42,[28,[37,8],[[28,[37,8],[[33,26]],null]],null],null,[[[1," "],[10,"label"],[14,0,"type-checkbox"],[12],[1,"\\n "],[10,"input"],[15,3,[29,[[36,11],"[Datacenters]"]]],[15,2,[30,4,["Name"]]],[15,"checked",[52,[28,[37,32],[[30,4,["Name"]],[33,4,["Datacenters"]]],null],"checked"]],[15,"onchange",[28,[37,13],[[30,0],"change"],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,1],[12],[1,[30,4,["Name"]]],[13],[1,"\\n "],[13],[1,"\\n"]],[4]],null],[42,[28,[37,8],[[28,[37,8],[[33,4,["Datacenters"]]],null]],null],null,[[[41,[28,[37,2],[[28,[37,33],["Name",[30,5],[33,26]],null]],null],[[[1," "],[10,"label"],[14,0,"type-checkbox"],[12],[1,"\\n "],[10,"input"],[15,3,[29,[[36,11],"[Datacenters]"]]],[15,2,[30,5]],[14,"checked","checked"],[15,"onchange",[28,[37,13],[[30,0],"change"],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,1],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[5]],null],[1," "],[13],[1,"\\n\\n\\n"]],[]],null]],[]]],[41,[28,[37,12],[[33,4,["template"]],""],null],[[[1," "],[10,"label"],[14,0,"type-text"],[12],[1,"\\n "],[10,1],[12],[1,"Description (Optional)"],[13],[1,"\\n "],[10,"textarea"],[15,3,[29,[[36,11],"[Description]"]]],[15,2,[33,4,["Description"]]],[15,"oninput",[28,[37,13],[[30,0],"change"],null]],[12],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[13],[1,"\\n\\n"]],["&attrs","template","Name","dc","dc","&default"],false,["yield","if","not","can","item","yield-slot","allowIdentity","each","-track-array","templates","concat","name","eq","action","optional","changeset-set","and","code-editor","env","consul/service-identity/template","nspace","partition","consul/node-identity/template","data-source","uri","mut","datacenters","power-select","map-by","or","dc","isScoped","includes","find-by"]]',moduleName:"consul-ui/components/policy-form/index.hbs",isStrictMode:!1}) -var o=(0,t.setComponentTemplate)(i,l.default.extend({type:"policy",name:"policy",allowIdentity:!0,classNames:["policy-form"],isScoped:!1,init:function(){this._super(...arguments),(0,r.set)(this,"isScoped",(0,r.get)(this,"item.Datacenters.length")>0),this.templates=[{name:"Policy",template:""},{name:"Service Identity",template:"service-identity"},{name:"Node Identity",template:"node-identity"}]},actions:{change:function(e){try{this._super(...arguments)}catch(t){const e=this.isScoped -if("policy[isScoped]"===t.target.name)e?((0,r.set)(this,"previousDatacenters",(0,r.get)(this.item,"Datacenters")),(0,r.set)(this.item,"Datacenters",null)):((0,r.set)(this.item,"Datacenters",this.previousDatacenters),(0,r.set)(this,"previousDatacenters",null)),(0,r.set)(this,"isScoped",!e) -else this.onerror(t) -this.onchange({target:this.form})}}}})) -e.default=o})),define("consul-ui/components/policy-selector/index",["exports","@ember/component","@ember/template-factory","consul-ui/components/child-selector/index","@ember/object","@ember/service"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"7xWCYtBV",block:'[[[8,[39,0],[[17,1]],[["@disabled","@repo","@dc","@partition","@nspace","@type","@placeholder","@items"],[[99,1,["@disabled"]],[99,2,["@repo"]],[99,3,["@dc"]],[99,4,["@partition"]],[99,5,["@nspace"]],"policy","Search for policy",[99,6,["@items"]]]],[["default"],[[[[1,"\\n "],[18,11,null],[1,"\\n "],[8,[39,8],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Apply an existing policy\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["create"]],[["default"],[[[[1,"\\n"],[6,[39,9],null,[["name"],["trigger"]],[["default","else"],[[[[1," "],[18,11,null],[1,"\\n"]],[]],[[[1," "],[8,[39,10],[[24,0,"type-dialog"],[4,[38,11],["click",[28,[37,12],[[30,0],[30,0,["openModal"]]],null]],null]],[["@text","@size","@color","@icon"],["Create new policy","small","tertiary","plus"]],null],[1,"\\n"],[1," "],[8,[39,13],[[24,1,"new-policy"]],[["@onopen","@aria"],[[28,[37,12],[[30,0],"open"],null],[28,[37,14],null,[["label"],["New Policy"]]]]],[["default"],[[[[1,"\\n "],[8,[39,15],null,[["@target","@name","@value"],[[30,0],"modal",[30,2]]],null],[1,"\\n "],[8,[39,8],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"New Policy"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[8,[39,16],null,[["@form","@nspace","@partition","@dc","@allowServiceIdentity"],[[99,17,["@form"]],[99,5,["@nspace"]],[99,4,["@partition"]],[99,3,["@dc"]],[99,18,["@allowServiceIdentity"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,19],null,null,[["default"],[[[[1,"\\n "],[8,[39,10],[[16,"onclick",[28,[37,20],[[30,0,["save"]],[33,21],[33,6],[28,[37,22],[[28,[37,12],[[30,0],[30,3]],null],[28,[37,12],[[30,0],"reset"],null]],null]],null]],[16,"disabled",[52,[28,[37,24],[[33,21,["isSaving"]],[33,21,["isPristine"]],[33,21,["isInvalid"]]],null],"disabled"]],[24,4,"submit"]],[["@isLoading","@text"],[[33,21,["isSaving"]],"Create and apply"]],null],[1,"\\n "],[8,[39,10],[[16,"disabled",[52,[33,21,["isSaving"]],"disabled"]],[24,4,"reset"],[4,[38,11],["click",[28,[37,12],[[30,0],[28,[37,22],[[28,[37,12],[[30,0],[30,3]],null],[28,[37,12],[[30,0],"reset"],null]],null]],null]],null]],[["@color","@text"],["secondary","Cancel"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[]]]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["option"]],[["default"],[[[[1,"\\n "],[1,[30,4,["Name"]]],[1,"\\n "]],[4]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["set"]],[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@onchange","@items"],[[28,[37,12],[[30,0],"open"],null],[28,[37,26],["CreateTime:desc","Name:asc",[33,6]],null]]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[12],[1,"Name"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["row"]],[["default"],[[[[1,"\\n "],[10,"td"],[15,0,[28,[37,27],[[30,5]],null]],[12],[1,"\\n"],[41,[30,5,["ID"]],[[[1," "],[10,3],[15,6,[28,[37,28],["dc.acls.policies.edit",[30,5,["ID"]]],null]],[12],[1,[30,5,["Name"]]],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,3,[30,5,["Name"]]],[12],[1,[30,5,["Name"]]],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["details"]],[["default"],[[[[1,"\\n"],[41,[28,[37,29],[[30,5,["template"]],""],null],[[[1," "],[8,[39,30],null,[["@src","@onchange","@loading"],[[28,[37,31],["/${partition}/${nspace}/${dc}/policy/${id}",[28,[37,14],null,[["partition","nspace","dc","id"],[[33,4],[33,5],[33,3],[30,5,["ID"]]]]]],null],[28,[37,12],[[30,0],[28,[37,32],[[33,33]],null]],[["value"],["data"]]],"lazy"]],null],[1,"\\n"]],[]],null],[41,[28,[37,29],[[30,5,["template"]],"node-identity"],null],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Datacenter:"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,5,["Datacenter"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Datacenters:"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,34],[", ",[28,[37,35],[[28,[37,24],[[33,33],[30,5]],null]],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "],[10,"label"],[14,0,"type-text"],[12],[1,"\\n"],[41,[28,[37,29],[[30,5,["template"]],"service-identity"],null],[[[1," "],[8,[39,36],null,[["@syntax","@readonly"],["hcl",true]],[["label","content"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,37],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[39,38],null,[["@nspace","@partition","@name"],[[99,5,["@nspace"]],[99,4,["@partition"]],[30,5,["Name"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[41,[28,[37,29],[[30,5,["template"]],"node-identity"],null],[[[1," "],[8,[39,36],null,[["@syntax","@readonly"],["hcl",true]],[["label","content"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,37],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[39,39],null,[["@name","@partition"],[[30,5,["Name"]],[99,4,["@partition"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,36],null,[["@syntax","@readonly","@value"],["hcl",true,[28,[37,24],[[33,33,["Rules"]],[30,5,["Rules"]]],null]]],[["label"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,37],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]],[]]],[1," "],[13],[1,"\\n"],[41,[28,[37,40],[[33,1]],null],[[[1," "],[10,0],[12],[1,"\\n "],[8,[39,41],null,[["@message"],["Are you sure you want to remove this policy from this token?"]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,10],[[4,[38,12],[[30,0],[30,7],"remove",[30,5],[33,6]],null]],[["@text","@color","@size"],["Remove","critical","small"]],null],[1,"\\n "]],[7]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[30,10]],[1,"\\n "],[13],[1,"\\n "],[8,[39,19],null,null,[["default"],[[[[1,"\\n "],[8,[39,10],[[4,[38,12],[[30,0],[30,8]],null]],[["@text","@color","@size"],["Confirm remove","critical","small"]],null],[1,"\\n "],[8,[39,10],[[4,[38,12],[[30,0],[30,9]],null]],[["@text","@color","@size"],["Cancel","secondary","small"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[8,9,10]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[5,6]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n"]],[]]]]],[1,"\\n"]],["&attrs","modal","close","option","item","index","confirm","execute","cancel","message","&default"],false,["child-selector","disabled","repo","dc","partition","nspace","items","yield","block-slot","yield-slot","hds/button","on","action","modal-dialog","hash","ref","policy-form","form","allowServiceIdentity","hds/button-set","perform","item","queue","if","or","tabular-details","sort-by","policy/typeof","href-to","eq","data-source","uri","mut","loadedItem","join","policy/datacenters","code-editor","env","consul/service-identity/template","consul/node-identity/template","not","confirmation-dialog"]]',moduleName:"consul-ui/components/policy-selector/index.hbs",isStrictMode:!1}),a="Invalid Policy: A Policy with Name" -var u=(0,t.setComponentTemplate)(o,l.default.extend({repo:(0,i.inject)("repository/policy"),name:"policy",type:"policy",allowIdentity:!0,classNames:["policy-selector"],init:function(){this._super(...arguments) -const e=this.source -e&&this._listeners.add(e,{save:e=>{this.save.perform(...e.data)}})},reset:function(e){this._super(...arguments),(0,r.set)(this,"isScoped",!1)},refreshCodeEditor:function(e,t){this.dom.component(".code-editor",t).didAppear()},error:function(e){const t=this.item,n=e.error -if(void 0===n.errors)throw n -{const e=n.errors[0] -let l="Rules",r=e.detail -switch(!0){case 0===r.indexOf("Failed to parse ACL rules"):case 0===r.indexOf("Invalid service policy"):l="Rules",r=e.detail -break -case 0===r.indexOf(a):l="Name",r=r.substr(a.indexOf(":")+1)}l&&t.addError(l,r)}},openModal:function(){const{modal:e}=this -e&&e.open()},actions:{open:function(e){this.refreshCodeEditor(e,e.target.parentElement)}}})) -e.default=u})),define("consul-ui/components/popover-menu/index",["exports","@ember/component","@ember/template-factory","@ember/service","block-slots","@ember/object"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"yEAcBvbt",block:'[[[18,11,null],[1,"\\n"],[11,0],[24,0,"popover-menu"],[17,1],[12],[1,"\\n "],[8,[39,1],null,[["@keyboardAccess"],[[99,2,["@keyboardAccess"]]]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,4],null,[["MenuItem","MenuSeparator"],[[50,"popover-menu/menu-item",0,null,[["menu"],[[28,[37,4],null,[["addSubmenu","removeSubmenu","confirm","clickTrigger","keypressClick"],[[28,[37,6],[[30,0],"addSubmenu"],null],[28,[37,6],[[30,0],"removeSubmenu"],null],[28,[37,7],["popover-menu-",[33,8],"-"],null],[30,0,["toggle","click"]],[30,4]]]]]]],[50,"popover-menu/menu-separator",0,null,null]]]]],[[[44,[[28,[37,4],null,[["toggle"],[[30,0,["toggle","click"]]]]]],[[[1,"\\n "],[8,[39,9],null,[["@checked","@onchange"],[[52,[33,2],[30,5,["expanded"]],[33,11]],[28,[37,12],[[30,2],[28,[37,6],[[30,0],"change"],null]],null]]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@target","@name","@value"],[[30,0],"toggle",[30,8]]],null],[1,"\\n "],[10,"button"],[14,"aria-haspopup","menu"],[15,"onkeydown",[30,3]],[15,"onclick",[30,0,["toggle","click"]]],[15,1,[30,5,["labelledBy"]]],[15,"aria-controls",[30,5,["controls"]]],[14,4,"button"],[12],[1,"\\n "],[8,[39,14],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n "],[18,11,[[30,6],[30,7]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "]],[8]]]]],[1,"\\n\\n "],[8,[39,15],[[16,1,[30,5,["controls"]]],[16,"aria-labelledby",[30,5,["labelledBy"]]],[16,"aria-expanded",[30,5,["expanded"]]]],[["@position"],[[99,16,["@position"]]]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@target","@name","@value"],[[30,0],"menu",[30,9]]],null],[1,"\\n "],[8,[39,17],null,[["@name"],["controls"]],[["default"],[[[[1,"\\n "],[10,"input"],[15,1,[28,[37,7],["popover-menu-",[33,8],"-"],null]],[14,4,"checkbox"],[12],[13],[1,"\\n"],[42,[28,[37,19],[[28,[37,19],[[33,20]],null]],null],null,[[[1," "],[10,"input"],[15,1,[28,[37,7],["popover-menu-",[33,8],"-",[30,10]],null]],[15,"onchange",[30,9,["change"]]],[14,4,"checkbox"],[12],[13],[1,"\\n"]],[10]],null],[1," "]],[]]]]],[1,"\\n"],[41,[33,21],[[[1," "],[8,[39,17],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[18,11,[[30,6],[30,7]]],[1,"\\n "],[6,[39,14],null,[["name"],["header"]],[["default","else"],[[[],[]],[[],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,17],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[8,[39,14],null,[["@name","@params"],["menu",[28,[37,22],[[28,[37,7],["popover-menu-",[33,8],"-"],null],[33,23],[30,4],[30,0,["toggle","click"]]],null]]],[["default"],[[[[1,"\\n "],[18,11,[[30,6],[30,7]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n\\n"]],[7]]]],[6]]],[1,"\\n "]],[2,3,4,5]]]]],[1,"\\n"],[13]],["&attrs","change","keypress","keypressClick","aria","components","api","toggle","menu","sub","&default"],false,["yield","aria-menu","keyboardAccess","let","hash","component","action","concat","guid","toggle-button","if","expanded","queue","ref","yield-slot","menu-panel","position","block-slot","each","-track-array","submenus","hasHeader","block-params","send"]]',moduleName:"consul-ui/components/popover-menu/index.hbs",isStrictMode:!1}) -var a=(0,t.setComponentTemplate)(o,t.default.extend(r.default,{tagName:"",dom:(0,l.inject)("dom"),expanded:!1,keyboardAccess:!0,onchange:function(){},position:"",init:function(){this._super(...arguments),this.guid=this.dom.guid(this),this.submenus=[]},willRender:function(){(0,i.set)(this,"hasHeader",this._isRegistered("header"))},actions:{addSubmenu:function(e){(0,i.set)(this,"submenus",this.submenus.concat(e))},removeSubmenu:function(e){const t=this.submenus.indexOf(e);-1!==t&&(this.submenus.splice(t,1),(0,i.set)(this,"submenus",this.submenus))},change:function(e){e.target.checked||[...this.dom.elements(`[id^=popover-menu-${this.guid}]`)].forEach((function(e){e.checked=!1})),this.onchange(e)},send:function(){this.sendAction(...arguments)}}})) -e.default=a})),define("consul-ui/components/popover-menu/menu-item/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object","block-slots"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=(0,n.createTemplateFactory)({id:"2GW+NBsb",block:'[[[18,3,null],[1,"\\n"],[11,"li"],[24,"role","none"],[17,1],[12],[1,"\\n"],[41,[33,2],[[[1," "],[10,"label"],[15,"for",[28,[37,3],[[33,4,["confirm"]],[33,5]],null]],[14,"role","menuitem"],[14,"tabindex","-1"],[15,"onkeypress",[33,4,["keypressClick"]]],[12],[1,"\\n "],[8,[39,6],null,[["@name"],["label"]],[["default"],[[[[18,3,null]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,"role","menu"],[12],[1,"\\n "],[8,[39,6],null,[["@name","@params"],["confirmation",[28,[37,7],[[50,"confirmation-alert",0,null,[["onclick","name"],[[28,[37,9],[[28,[37,10],[[30,0],[33,4,["clickTrigger"]]],null],[28,[37,10],[[30,0],[33,11]],null]],null],[28,[37,3],[[33,4,["confirm"]],[33,5]],null]]]]],null]]],[["default"],[[[[18,3,null]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[41,[33,12],[[[44,[[28,[37,14],[[33,12],"://"],null]],[[[1," "],[10,3],[14,"role","menuitem"],[14,"tabindex","-1"],[15,"onclick",[28,[37,10],[[30,0],[33,4,["clickTrigger"]]],null]],[15,6,[36,12]],[15,"target",[52,[30,2],"_blank"]],[15,"rel",[52,[30,2],"noopener noreferrer"]],[12],[1,"\\n "],[8,[39,6],null,[["@name"],["label"]],[["default"],[[[[1,"\\n "],[18,3,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[2]]]],[]],[[[10,"button"],[14,"role","menuitem"],[15,"aria-selected",[52,[33,15],"true"]],[14,"tabindex","-1"],[15,"onclick",[28,[37,9],[[28,[37,10],[[30,0],[28,[37,16],[[30,0,["onclick"]],[28,[37,17],null,null]],null]],null],[28,[37,10],[[30,0],[52,[30,0,["close"]],[33,4,["clickTrigger"]],[28,[37,17],null,null]]],null]],null]],[14,4,"button"],[12],[1,"\\n "],[8,[39,6],null,[["@name"],["label"]],[["default"],[[[[1,"\\n "],[18,3,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[]]]],[]]],[13],[1,"\\n\\n"]],["&attrs","external","&default"],false,["yield","if","hasConfirmation","concat","menu","guid","yield-slot","block-params","component","queue","action","onclick","href","let","string-includes","selected","or","noop"]]',moduleName:"consul-ui/components/popover-menu/menu-item/index.hbs",isStrictMode:!1}) -var a=(0,t.setComponentTemplate)(o,t.default.extend(i.default,{tagName:"",dom:(0,l.inject)("dom"),init:function(){this._super(...arguments),this.guid=this.dom.guid(this)},didInsertElement:function(){this._super(...arguments),this.menu.addSubmenu(this.guid)},didDestroyElement:function(){this._super(...arguments),this.menu.removeSubmenu(this.guid)},willRender:function(){this._super(...arguments),(0,r.set)(this,"hasConfirmation",this._isRegistered("confirmation"))}})) -e.default=a})),define("consul-ui/components/popover-menu/menu-separator/index",["exports","@ember/component","@ember/template-factory","block-slots"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"n5s/eW+J",block:'[[[18,1,null],[1,"\\n"],[10,"li"],[14,"role","separator"],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[18,1,null]],[]]]]],[1,"\\n"],[13],[1,"\\n"]],["&default"],false,["yield","yield-slot"]]',moduleName:"consul-ui/components/popover-menu/menu-separator/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,t.default.extend(l.default,{tagName:""})) -e.default=i})),define("consul-ui/components/popover-select/index",["exports","@ember/component","@ember/template-factory","@ember/service","block-slots"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i=(0,n.createTemplateFactory)({id:"MCbyGl1m",block:'[[[8,[39,0],[[24,0,"popover-select"],[17,1]],[["@position"],[[28,[37,1],[[33,2],"left"],null]]],[["default"],[[[[1,"\\n "],[18,6,null],[1,"\\n"],[44,[[50,"popover-select/optgroup",0,null,[["components"],[[30,2]]]],[50,"popover-select/option",0,null,[["select","components","onclick"],[[30,0],[30,2],[28,[37,6],[[28,[37,7],[[30,0],"click"],null],[52,[33,9],[28,[37,10],null,null],[30,3,["toggle"]]]],null]]]]],[[[1," "],[8,[39,11],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[18,6,[[28,[37,13],null,[["Optgroup","Option"],[[30,4],[30,5]]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,11],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@name"],["options"]],[["default"],[[[[1,"\\n "],[18,6,[[28,[37,13],null,[["Optgroup","Option"],[[30,4],[30,5]]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]]],[2,3]]]]],[1,"\\n"]],["&attrs","components","menu","Optgroup","Option","&default"],false,["popover-menu","or","position","yield","let","component","pipe","action","if","multiple","noop","block-slot","yield-slot","hash"]]',moduleName:"consul-ui/components/popover-select/index.hbs",isStrictMode:!1}) -var o=(0,t.setComponentTemplate)(i,t.default.extend(r.default,{tagName:"",dom:(0,l.inject)("dom"),multiple:!1,required:!1,onchange:function(){},addOption:function(e){void 0===this._options&&(this._options=new Set),this._options.add(e)},removeOption:function(e){this._options.delete(e)},actions:{click:function(e,t){if(this.multiple){if(e.selected&&this.required){if(![...this._options].find((t=>t!==e&&t.selected)))return t}}else{if(e.selected&&this.required)return t;[...this._options].filter((t=>t!==e)).forEach((e=>{e.selected=!1}))}return e.selected=!e.selected,this.onchange(this.dom.setEventTargetProperties(t,{selected:t=>e.args.value,selectedItems:e=>[...this._options].filter((e=>e.selected)).map((e=>e.args.value)).join(",")})),t}}})) -e.default=o})),define("consul-ui/components/popover-select/optgroup/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"GuHT6dz2",block:'[[[44,[[30,1,["MenuSeparator"]]],[[[8,[30,2],null,null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n "],[1,[30,3]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]]],[1,"\\n"],[18,4,null],[1,"\\n"]],[2]]]],["@components","MenuSeparator","@label","&default"],false,["let","block-slot","yield"]]',moduleName:"consul-ui/components/popover-select/optgroup/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/popover-select/option/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object"],(function(e,t,n,l,r,i){var o,a -function u(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const s=(0,n.createTemplateFactory)({id:"gE0Zhut+",block:'[[[44,[[30,1,["MenuItem"]]],[[[1," "],[8,[30,2],[[16,0,[52,[30,0,["selected"]],"is-active"]],[17,3],[4,[38,3],[[30,0,["connect"]]],null],[4,[38,3],[[28,[37,4],[[30,0],"selected",[30,5]],null]],null],[4,[38,5],[[28,[37,4],[[30,0],"selected",[30,5]],null]],null],[4,[38,6],[[30,0,["disconnect"]]],null]],[["@onclick","@selected"],[[28,[37,2],[[30,0],[30,4],[30,0]],null],[30,0,["selected"]]]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["label"]],[["default"],[[[[1,"\\n "],[18,6,null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[2]]]],["@components","MenuItem","&attrs","@onclick","@selected","&default"],false,["let","if","action","did-insert","set","did-update","will-destroy","block-slot","yield"]]',moduleName:"consul-ui/components/popover-select/option/index.hbs",isStrictMode:!1}) -let c=(o=class extends l.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="selected",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}connect(){this.args.select.addOption(this)}disconnect(){this.args.select.removeOption(this)}},a=u(o.prototype,"selected",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u(o.prototype,"connect",[i.action],Object.getOwnPropertyDescriptor(o.prototype,"connect"),o.prototype),u(o.prototype,"disconnect",[i.action],Object.getOwnPropertyDescriptor(o.prototype,"disconnect"),o.prototype),o) -e.default=c,(0,t.setComponentTemplate)(s,c)})),define("consul-ui/components/portal-target",["exports","ember-stargate/components/portal-target"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/portal",["exports","ember-stargate/components/portal"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select-multiple-with-create",["exports","ember-power-select-with-create/components/power-select-multiple-with-create"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) -define("consul-ui/components/power-select-multiple",["exports","ember-power-select/components/power-select-multiple"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select-multiple/trigger",["exports","ember-power-select/components/power-select-multiple/trigger"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select-with-create",["exports","ember-power-select-with-create/components/power-select-with-create"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select-with-create/suggested-option",["exports","ember-power-select-with-create/components/power-select-with-create/suggested-option"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select",["exports","ember-power-select/components/power-select"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/before-options",["exports","ember-power-select/components/power-select/before-options"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/no-matches-message",["exports","ember-power-select/components/power-select/no-matches-message"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/options",["exports","ember-power-select/components/power-select/options"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/placeholder",["exports","ember-power-select/components/power-select/placeholder"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/power-select-group",["exports","ember-power-select/components/power-select/power-select-group"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/search-message",["exports","ember-power-select/components/power-select/search-message"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/trigger",["exports","ember-power-select/components/power-select/trigger"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/progress/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"0deDvA3Z",block:'[[[11,0],[24,0,"progress indeterminate"],[24,"role","progressbar"],[17,1],[12],[13],[1,"\\n"]],["&attrs"],false,[]]',moduleName:"consul-ui/components/progress/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/providers/dimension/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object","ember-ref-bucket","@ember/template"],(function(e,t,n,l,r,i,o,a){var u,s,c,d -function p(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function f(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const m=(0,n.createTemplateFactory)({id:"BXV/pZSO",block:'[[[11,0],[4,[38,0],["element"],[["debugName","bucket"],["create-ref",[30,0]]]],[4,[38,1],[[30,0,["measureDimensions"]]],null],[12],[1,"\\n "],[1,[28,[35,2],["resize",[30,0,["handleWindowResize"]]],null]],[1,"\\n "],[18,1,[[28,[37,4],null,[["data"],[[30,0,["data"]]]]]]],[1,"\\n"],[13]],["&default"],false,["create-ref","did-insert","on-window","yield","hash"]]',moduleName:"consul-ui/components/providers/dimension/index.hbs",isStrictMode:!1}) -let h=(u=(0,o.ref)("element"),s=class extends l.default{constructor(){super(...arguments),p(this,"element",c,this),p(this,"height",d,this)}get data(){const{height:e,fillRemainingHeightStyle:t}=this -return{height:e,fillRemainingHeightStyle:t}}get fillRemainingHeightStyle(){return(0,a.htmlSafe)(`height: ${this.height}px;`)}get bottomBoundary(){return document.querySelector(this.args.bottomBoundary)||this.footer}get footer(){return document.querySelector('footer[role="contentinfo"]')}measureDimensions(e){const t=this.bottomBoundary.getBoundingClientRect(),n=e.getBoundingClientRect() -this.height=t.top+t.height-n.top}handleWindowResize(){const{element:e}=this -this.measureDimensions(e)}},c=f(s.prototype,"element",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=f(s.prototype,"height",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f(s.prototype,"measureDimensions",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"measureDimensions"),s.prototype),f(s.prototype,"handleWindowResize",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"handleWindowResize"),s.prototype),s) -e.default=h,(0,t.setComponentTemplate)(m,h)})),define("consul-ui/components/providers/search/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"nGR80lz+",block:'[[[18,1,[[28,[37,1],null,[["data"],[[30,0,["data"]]]]]]]],["&default"],false,["yield","hash"]]',moduleName:"consul-ui/components/providers/search/index.hbs",isStrictMode:!1}) -class i extends l.default{get _search(){return this.args.search||""}get items(){const{items:e,searchProperties:t}=this.args,{_search:n}=this -return n.length>0?e.filter((e=>t.reduce(((t,l)=>{const r=-1!==e[l].indexOf(n) -return r?[...t,r]:t}),[]).length>0)):e}get data(){const{items:e}=this -return{items:e}}}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/radio-card/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"o/1nwT6X",block:'[[[11,"label"],[17,1],[16,0,[29,["radio-card",[52,[33,1]," checked"]]]],[12],[1,"\\n "],[10,0],[12],[1,"\\n"],[41,[28,[37,2],[[33,3,["length"]],0],null],[[[1," "],[10,"input"],[15,3,[36,4]],[15,2,[36,3]],[15,"checked",[36,1]],[15,"onchange",[28,[37,5],[[30,0],[33,6]],null]],[14,4,"radio"],[12],[13],[1,"\\n"]],[]],[[[1," "],[10,"input"],[15,3,[36,4]],[14,2,""],[15,"checked",[36,1]],[15,"onchange",[28,[37,5],[[30,0],[33,6]],null]],[14,4,"radio"],[12],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[10,0],[12],[1,"\\n "],[18,2,null],[1,"\\n "],[13],[1,"\\n"],[13]],["&attrs","&default"],false,["if","checked","gt","value","name","action","onchange","yield"]]',moduleName:"consul-ui/components/radio-card/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) -e.default=r})),define("consul-ui/components/radio-group/index",["exports","@ember/component","@ember/template-factory","@ember/service"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"Ud+ETI/C",block:'[[[10,"fieldset"],[12],[1,"\\n "],[10,0],[14,"role","radiogroup"],[15,1,[29,["radiogroup_",[36,0]]]],[12],[1,"\\n"],[42,[28,[37,2],[[28,[37,2],[[33,3]],null]],null],null,[[[44,[[52,[28,[37,6],[[30,1,["key"]],[27]],null],[30,1,["key"]],[30,1,["value"]]],[28,[37,7],[[30,1,["label"]],[30,1,["value"]]],null]],[[[1," "],[10,"label"],[15,"tabindex",[52,[33,8],"0"]],[15,"onkeydown",[52,[33,8],[28,[37,9],[[30,0],"keydown"],null]]],[15,0,[29,["type-radio value-",[30,2]]]],[12],[1," "],[1,"\\n "],[10,"input"],[15,3,[36,0]],[15,2,[30,2]],[15,"checked",[52,[28,[37,10],[[28,[37,11],[[33,12]],null],[30,2]],null],"checked"]],[15,"onchange",[28,[37,9],[[30,0],"change"],null]],[14,4,"radio"],[12],[13],[1,"\\n "],[10,1],[12],[1,[30,3]],[13],[1,"\\n "],[13],[1,"\\n"]],[2,3]]]],[1]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],["item","_key","_value"],false,["name","each","-track-array","items","let","if","not-eq","or","keyboardAccess","action","eq","concat","value"]]',moduleName:"consul-ui/components/radio-group/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,t.default.extend({tagName:"",keyboardAccess:!1,dom:(0,l.inject)("dom"),init:function(){this._super(...arguments),this.name=this.dom.guid(this)},actions:{keydown:function(e){13===e.keyCode&&e.target.dispatchEvent(new MouseEvent("click"))},change:function(e){this.onchange(this.dom.setEventTargetProperty(e,"value",(e=>""===e?void 0:e)))}}})) -e.default=i})),define("consul-ui/components/ref/index",["exports","@ember/component","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l=t.default.extend({tagName:"",didReceiveAttrs:function(){(0,n.set)(this.target,this.name,this.value)}}) -e.default=l})),define("consul-ui/components/role-form/index",["exports","@ember/component","@ember/template-factory","consul-ui/components/form-component/index"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"0/f8kKT6",block:'[[[18,2,null],[1,"\\n"],[11,"fieldset"],[24,0,"role-form"],[16,"disabled",[52,[28,[37,2],[[28,[37,3],["write role"],[["item"],[[33,4]]]]],null],"disabled"]],[17,1],[12],[1,"\\n "],[10,"label"],[15,0,[29,["type-text",[52,[33,4,["error","Name"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Name"],[13],[1,"\\n "],[10,"input"],[15,2,[33,4,["Name"]]],[14,3,"role[Name]"],[14,"autofocus","autofocus"],[15,"oninput",[28,[37,5],[[30,0],"change"],null]],[14,4,"text"],[12],[13],[1,"\\n "],[10,"em"],[12],[1,"\\n Maximum 256 characters. May only include letters (uppercase and/or lowercase) and/or numbers. Must be unique.\\n "],[13],[1,"\\n"],[41,[33,4,["error","Name"]],[[[1," "],[10,"strong"],[12],[1,[33,4,["error","Name","validation"]]],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[10,"label"],[14,0,"type-text"],[12],[1,"\\n "],[10,1],[12],[1,"Description (Optional)"],[13],[1,"\\n "],[10,"textarea"],[14,3,"role[Description]"],[15,2,[33,4,["Description"]]],[15,"oninput",[28,[37,5],[[30,0],"change"],null]],[12],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"],[10,"fieldset"],[14,1,"policies"],[14,0,"policies"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Policies"],[13],[1,"\\n"],[6,[39,6],null,[["name","params"],["policy",[28,[37,7],[[33,4]],null]]],[["default","else"],[[[[1," "],[18,2,null],[1,"\\n"]],[]],[[[1," "],[8,[39,8],null,[["@disabled","@dc","@partition","@nspace","@items"],[[28,[37,2],[[28,[37,3],["write role"],[["item"],[[33,4]]]]],null],[99,9,["@dc"]],[99,10,["@partition"]],[99,11,["@nspace"]],[33,4,["Policies"]]]],null],[1,"\\n"]],[]]]]],[13],[1,"\\n"]],["&attrs","&default"],false,["yield","if","not","can","item","action","yield-slot","block-params","policy-selector","dc","partition","nspace"]]',moduleName:"consul-ui/components/role-form/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,l.default.extend({type:"role",name:"role",classNames:["role-form"]})) -e.default=i})),define("consul-ui/components/role-selector/index",["exports","@ember/component","@ember/template-factory","consul-ui/components/child-selector/index","@ember/service","@ember/object","@ember/object/computed","consul-ui/utils/dom/event-source"],(function(e,t,n,l,r,i,o,a){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const u=(0,n.createTemplateFactory)({id:"6ZRIYR2n",block:'[[[8,[39,0],[[24,0,"role-selector"],[24,1,"new-role"]],[["@onclose","@aria"],[[28,[37,1],[[30,0],[28,[37,2],[[33,3]],null],"role"],null],[28,[37,4],null,[["label"],[[52,[28,[37,6],[[33,3],"role"],null],"New Role","New Policy"]]]]]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@target","@name","@value"],[[30,0],"modal",[30,1]]],null],[1,"\\n "],[8,[39,8],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,6],[[33,3],"role"],null],[[[1," "],[10,"h2"],[12],[1,"New Role"],[13],[1,"\\n"]],[]],[[[1," "],[10,"h2"],[12],[1,"New Policy"],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["body"]],[["default"],[[[[1,"\\n\\n "],[10,"input"],[15,1,[29,[[36,9],"_state_role"]]],[15,3,[29,[[36,9],"[state]"]]],[14,2,"role"],[15,"checked",[52,[28,[37,6],[[33,3],"role"],null],"checked"]],[15,"onchange",[28,[37,1],[[30,0],"change"],null]],[14,4,"radio"],[12],[13],[1,"\\n "],[8,[39,10],null,[["@form","@dc","@nspace","@partition"],[[99,11,["@form"]],[99,12,["@dc"]],[99,13,["@nspace"]],[99,14,["@partition"]]]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["policy"]],[["default"],[[[[1,"\\n\\n "],[8,[39,15],null,[["@source","@dc","@partition","@nspace","@items"],[[99,16,["@source"]],[99,12,["@dc"]],[99,14,["@partition"]],[99,13,["@nspace"]],[33,17,["Policies"]]]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n "],[8,[39,18],[[24,0,"type-dialog"],[4,[38,1],[[30,0],"triggerStateCheckboxChange"],null]],[["@text","@size","@color","@icon"],["Create new policy","small","tertiary","plus"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[10,"input"],[15,1,[29,[[36,9],"_state_policy"]]],[15,3,[29,[[36,9],"[state]"]]],[14,2,"policy"],[15,"checked",[52,[28,[37,6],[[33,3],"policy"],null],"checked"]],[15,"onchange",[28,[37,1],[[30,0],"change"],null]],[14,4,"radio"],[12],[13],[1,"\\n "],[8,[39,19],null,[["@name","@form","@dc","@nspace","@partition"],["role[policy]",[99,20,["@form"]],[99,12,["@dc"]],[99,13,["@nspace"]],[99,14,["@partition"]]]],null],[1,"\\n\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n\\n "],[8,[39,21],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,6],[[33,3],"role"],null],[[[1," "],[8,[39,18],[[16,"onclick",[28,[37,22],[[30,0,["save"]],[33,17],[33,23],[28,[37,24],[[28,[37,1],[[30,0],[30,2]],null],[28,[37,1],[[30,0],"reset"],null]],null]],null]],[16,"disabled",[52,[28,[37,25],[[33,17,["isSaving"]],[33,17,["isPristine"]],[33,17,["isInvalid"]]],null],"disabled"]],[24,4,"submit"]],[["@text","@isLoading"],["Create and apply",[33,17,["isSaving"]]]],null],[1,"\\n "],[8,[39,18],[[16,"disabled",[52,[33,17,["isSaving"]],"disabled"]],[24,4,"reset"],[4,[38,26],["click",[28,[37,1],[[30,0],[28,[37,24],[[28,[37,1],[[30,0],[30,2]],null],[28,[37,1],[[30,0],"reset"],null]],null]],null]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n\\n"]],[]],[[[1," "],[8,[39,18],[[16,"disabled",[52,[28,[37,25],[[33,27,["isSaving"]],[33,27,["isPristine"]],[33,27,["isInvalid"]]],null],"disabled"]],[24,4,"submit"],[4,[38,1],[[30,0],"dispatch","save",[28,[37,28],[[33,27],[33,17,["Policies"]],[28,[37,1],[[30,0],[28,[37,2],[[33,3]],null],"role"],null]],null]],null]],[["@text","@isLoading"],["Create and apply",[33,27,["isSaving"]]]],null],[1,"\\n "],[8,[39,18],[[16,"disabled",[52,[33,27,["isSaving"]],"disabled"]],[24,4,"reset"],[4,[38,26],["click",[28,[37,1],[[30,0],[28,[37,2],[[33,3]],null],"role"],null]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n\\n"],[8,[39,29],null,[["@disabled","@repo","@dc","@partition","@nspace","@type","@placeholder","@items"],[[99,30,["@disabled"]],[99,31,["@repo"]],[99,12,["@dc"]],[99,14,["@partition"]],[99,13,["@nspace"]],"role","Search for role",[99,23,["@items"]]]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Apply an existing role\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["create"]],[["default"],[[[[1,"\\n "],[8,[39,18],[[24,0,"type-dialog"],[4,[38,26],["click",[28,[37,32],[[30,0,["modal","open"]]],null]],null]],[["@text","@size","@color","@icon"],["Create new role","small","tertiary","plus"]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["option"]],[["default"],[[[[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "]],[3]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["set"]],[["default"],[[[[1,"\\n "],[8,[39,33],null,[["@rows","@items"],[5,[28,[37,34],["CreateTime:desc","Name:asc",[33,23]],null]]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[12],[1,"Name"],[13],[1,"\\n "],[10,"th"],[12],[1,"Description"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["row"]],[["default"],[[[[1,"\\n "],[10,"td"],[12],[1,"\\n "],[10,3],[15,6,[28,[37,35],["dc.acls.roles.edit",[30,4,["ID"]]],null]],[12],[1,[30,4,["Name"]]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[12],[1,"\\n "],[1,[30,4,["Description"]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,36],null,[["@expanded","@onchange","@keyboardAccess"],[[52,[28,[37,6],[[30,8],[30,6]],null],true,false],[28,[37,1],[[30,0],[30,7],[30,6]],null],false]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n More\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,"role","none"],[12],[1,"\\n "],[10,3],[14,"role","menuitem"],[14,"tabindex","-1"],[15,6,[28,[37,35],["dc.acls.roles.edit",[30,4,["ID"]]],null]],[12],[1,"\\n"],[41,[28,[37,37],["edit role"],[["item"],[[30,4]]]],[[[1," Edit\\n"]],[]],[[[1," View\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,38],[[33,30]],null],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"dangerous"],[12],[1,"\\n "],[10,"label"],[15,"for",[30,9]],[14,"role","menuitem"],[14,"tabindex","-1"],[15,"onkeypress",[30,11]],[12],[1,"Remove"],[13],[1,"\\n "],[10,0],[14,"role","menu"],[12],[1,"\\n "],[8,[39,39],[[24,0,"warning"]],null,[["header","body","actions"],[[[[1,"\\n Confirm Remove\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to remove this role?\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,12,["Action"]],[[24,0,"dangerous"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],[[24,"tabindex","-1"],[4,[38,26],["click",[28,[37,1],[[30,0],[30,10],"remove",[30,4],[33,23]],null]],null]],null,[["default"],[[[[1,"\\n Remove\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,12,["Action"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@for"],[[30,9]]],[["default"],[[[[1,"\\n Cancel\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[12]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "]],[9,10,11]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6,7,8]]]]],[1,"\\n "]],[4,5]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]]],[1,"\\n"]],["modal","close","option","item","index","index","change","checked","confirm","send","keypressClick","Actions"],false,["modal-dialog","action","mut","state","hash","if","eq","ref","block-slot","name","role-form","form","dc","nspace","partition","policy-selector","source","item","hds/button","policy-form","policyForm","hds/button-set","perform","items","queue","or","on","policy","array","child-selector","disabled","repo","optional","tabular-collection","sort-by","href-to","popover-menu","can","not","informed-action"]]',moduleName:"consul-ui/components/role-selector/index.hbs",isStrictMode:!1}) -var s=(0,t.setComponentTemplate)(u,l.default.extend({repo:(0,r.inject)("repository/role"),dom:(0,r.inject)("dom"),name:"role",type:"role",classNames:["role-selector"],state:"role",policy:(0,o.alias)("policyForm.data"),init:function(){this._super(...arguments),(0,i.set)(this,"policyForm",this.formContainer.form("policy")),this.source=new a.CallableEventSource},actions:{reset:function(e){this._super(...arguments),this.policyForm.clear({Datacenter:this.dc})},dispatch:function(e,t){this.source.dispatchEvent({type:e,data:t})},change:function(){const e=this.dom.normalizeEvent(...arguments),t=e.target -if("role[state]"===t.name)(0,i.set)(this,"state",t.value),"policy"===t.value&&this.dom.component(".code-editor",t.nextElementSibling).didAppear() -else this._super(...arguments)},triggerStateCheckboxChange(){let e=document.getElementById(`${this.name}_state_policy`) -e&&e.dispatchEvent(new Event("change"))}}})) -e.default=s})),define("consul-ui/components/route/announcer/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"othmimN0",block:'[[[1,[28,[35,0],[[30,1]],[["separator"],[[28,[37,1],[[30,2]," - "],null]]]]],[1,"\\n"],[8,[39,2],null,[["@name"],["route-announcer"]],null],[1,"\\n\\n"]],["@title","@separator"],false,["page-title","or","portal-target"]]',moduleName:"consul-ui/components/route/announcer/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/route/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/object","@glimmer/tracking"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m,h,b -function y(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function g(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const v=(0,n.createTemplateFactory)({id:"aUe64HGf",block:'[[[1,[28,[35,0],[[30,0,["connect"]]],null]],[1,"\\n"],[1,[28,[35,1],[[30,0,["disconnect"]]],null]],[1,"\\n"],[18,1,[[28,[37,3],null,[["model","params","currentName","refresh","t","exists","Title","Announcer"],[[30,0,["model"]],[30,0,["params"]],[30,0,["router","currentRoute","name"]],[30,0,["refresh"]],[30,0,["t"]],[30,0,["exists"]],[50,"route/title",0,null,null],[50,"route/announcer",0,null,null]]]]]]],["&default"],false,["did-insert","will-destroy","yield","hash","component"]]',moduleName:"consul-ui/components/route/index.hbs",isStrictMode:!1}),O=/\${([A-Za-z.0-9_-]+)}/g -let P=(a=(0,r.inject)("routlet"),u=(0,r.inject)("router"),s=(0,r.inject)("intl"),c=(0,r.inject)("encoder"),d=class extends l.default{constructor(){super(...arguments),y(this,"routlet",p,this),y(this,"router",f,this),y(this,"intl",m,this),y(this,"encoder",h,this),y(this,"_model",b,this),this.intlKey=this.encoder.createRegExpEncoder(O,(e=>e))}get params(){return this.routlet.paramsFor(this.args.name)}get model(){if(this._model)return this._model -if(this.args.name){const e=this.routlet.outletFor(this.args.name) -if(e)return this.routlet.modelFor(e.name)}}exists(e){return this.routlet.exists(`${this.args.name}.${e}`)}t(e,t){return e.includes("${")&&(e=this.intlKey(e,t)),this.intl.t(`routes.${this.args.name}.${e}`,t)}connect(){this.routlet.addRoute(this.args.name,this)}disconnect(){this.routlet.removeRoute(this.args.name,this)}},p=g(d.prototype,"routlet",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=g(d.prototype,"router",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=g(d.prototype,"intl",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=g(d.prototype,"encoder",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=g(d.prototype,"_model",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g(d.prototype,"exists",[i.action],Object.getOwnPropertyDescriptor(d.prototype,"exists"),d.prototype),g(d.prototype,"t",[i.action],Object.getOwnPropertyDescriptor(d.prototype,"t"),d.prototype),g(d.prototype,"connect",[i.action],Object.getOwnPropertyDescriptor(d.prototype,"connect"),d.prototype),g(d.prototype,"disconnect",[i.action],Object.getOwnPropertyDescriptor(d.prototype,"disconnect"),d.prototype),d) -e.default=P,(0,t.setComponentTemplate)(v,P)})),define("consul-ui/components/route/title/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"SU19CA8/",block:'[[[1,[28,[35,0],[[30,1]],[["separator"],[[30,2]]]]],[1,"\\n"],[41,[28,[37,2],[[30,3],false],null],[[[1,[30,1]],[1,"\\n"]],[]],null],[8,[39,3],null,[["@target"],["route-announcer"]],[["default"],[[[[1,"\\n"],[11,0],[24,0,"route-title"],[17,4],[24,"aria-live","assertive"],[24,"aria-atomic","true"],[12],[1,"\\n"],[1," "],[1,[28,[35,4],["Navigated to ",[30,1]],null]],[1,"\\n"],[13],[1,"\\n"]],[]]]]],[1,"\\n"]],["@title","@separator","@render","&attrs"],false,["page-title","if","not-eq","portal","concat"]]',moduleName:"consul-ui/components/route/title/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/search-bar/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","consul-ui/components/search-bar/utils"],(function(e,t,n,l,r,i){var o -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const a=(0,n.createTemplateFactory)({id:"ltULr+gR",block:'[[[11,0],[24,0,"search-bar"],[17,1],[12],[1,"\\n "],[10,"form"],[14,0,"filter-bar"],[12],[1,"\\n "],[10,0],[14,0,"search"],[12],[1,"\\n "],[18,4,[[28,[37,1],null,[["Search","Select"],[[50,"freetext-filter",0,null,null],[50,"popover-select",0,null,null]]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"filters"],[12],[1,"\\n "],[18,5,[[28,[37,1],null,[["Search","Select"],[[50,"freetext-filter",0,null,null],[50,"popover-select",0,null,null]]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"sort"],[12],[1,"\\n "],[18,6,[[28,[37,1],null,[["Search","Select"],[[50,"freetext-filter",0,null,null],[50,"popover-select",0,null,null]]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[30,0,["isFiltered"]],[[[1," "],[10,0],[14,0,"search-bar-status"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[28,[35,4],[[28,[37,5],["component.search-bar.header"],[["default","item"],["common.ui.filtered-by",""]]]],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,7],[[28,[37,7],[[30,0,["filters"]]],null]],null],null,[[[1," "],[18,7,[[28,[37,1],null,[["RemoveFilter","status"],[[50,"search-bar/remove-filter",0,null,[["onclick"],[[28,[37,8],[[30,0],[28,[37,9],[[28,[37,9],[[30,3],[30,2,["key"]]],null],"change"],null],[28,[37,1],null,[["target"],[[28,[37,1],null,[["selectedItems"],[[28,[37,10],[[30,2,["selected"]],","],null]]]]]]]],null]]]],[28,[37,1],null,[["key","value"],[[30,2,["key"]],[28,[37,11],[[30,2,["value"]]],null]]]]]]]]],[1,"\\n"]],[2]],null],[1," "],[10,"li"],[14,0,"remove-all"],[12],[1,"\\n "],[8,[39,8],[[4,[38,12],["click",[30,0,["removeAllFilters"]]],null]],null,[["default"],[[[[1,"\\n Remove filters\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[13],[1,"\\n"]],["&attrs","filter","@filter","&search","&filter","&sort","&status"],false,["yield","hash","component","if","string-trim","t","each","-track-array","action","get","join","lowercase","on"]]',moduleName:"consul-ui/components/search-bar/index.hbs",isStrictMode:!1}) -let u=(o=class extends l.default{get isFiltered(){const e=this.args.filter.searchproperty||{default:[],value:[]} -return(0,i.diff)(e.default,e.value).length>0||Object.entries(this.args.filter).some((e=>{let[t,n]=e -return"searchproperty"!==t&&void 0!==n.value}))}get filters(){return(0,i.filters)(this.args.filter)}removeAllFilters(){Object.values(this.args.filter).forEach(((e,t)=>{setTimeout((()=>e.change(e.default||[])),1*t)}))}},s=o.prototype,c="removeAllFilters",d=[r.action],p=Object.getOwnPropertyDescriptor(o.prototype,"removeAllFilters"),f=o.prototype,m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),o) -var s,c,d,p,f,m -e.default=u,(0,t.setComponentTemplate)(a,u)})),define("consul-ui/components/search-bar/remove-filter/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"euFx6j52",block:'[[[10,"li"],[12],[1,"\\n "],[8,[39,0],[[17,1],[4,[38,1],["click",[30,2]],null]],null,null],[1,"\\n "],[18,3,null],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@onclick","&default"],false,["action","on","yield"]]',moduleName:"consul-ui/components/search-bar/remove-filter/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/search-bar/utils",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.filters=e.diff=void 0 -const t=(e,t)=>e.filter((e=>!t.includes(e))) -e.diff=t -e.filters=e=>Object.entries(e).filter((e=>{let[n,l]=e -return"searchproperty"===n?t(l.default,l.value).length>0:(l.value||[]).length>0})).reduce(((e,n)=>{let[l,r]=n -return e.concat(r.value.map((e=>{const n={key:l,value:e} -return n.selected="searchproperty"!==l?t(r.value,[e]):1===r.value.length?r.default:t(r.value,[e]),n})))}),[])})),define("consul-ui/components/state-chart/action/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"ryQhDcxm",block:'[[[18,1,null]],["&default"],false,["yield"]]',moduleName:"consul-ui/components/state-chart/action/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:"",didInsertElement:function(){this._super(...arguments),this.chart.addAction(this.name,((e,t)=>this.exec(e,t)))},willDestroy:function(){this._super(...arguments),this.chart.removeAction(this.type)}})) -e.default=r})),define("consul-ui/components/state-chart/guard/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const l=(0,n.createTemplateFactory)({id:"nyWRsZoG",block:'[[[18,1,null]],["&default"],false,["yield"]]',moduleName:"consul-ui/components/state-chart/guard/index.hbs",isStrictMode:!1}) -var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:"",didInsertElement:function(){this._super(...arguments) -const e=this -this.chart.addGuard(this.name,(function(){return"function"==typeof e.cond?e.cond(...arguments):e.cond}))},willDestroyElement:function(){this._super(...arguments),this.chart.removeGuard(this.name)}})) -e.default=r})),define("consul-ui/components/state-chart/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i=(0,n.createTemplateFactory)({id:"4gS2sdh2",block:'[[[18,1,[[50,"state",0,null,[["state"],[[33,2]]]],[50,"state-chart/guard",0,null,[["chart"],[[30,0]]]],[50,"state-chart/action",0,null,[["chart"],[[30,0]]]],[28,[37,3],[[30,0],"dispatch"],null],[33,2]]]],["&default"],false,["yield","component","state","action"]]',moduleName:"consul-ui/components/state-chart/index.hbs",isStrictMode:!1}) -var o=(0,t.setComponentTemplate)(i,t.default.extend({chart:(0,l.inject)("state"),tagName:"",ontransition:function(e){},init:function(){this._super(...arguments),this._actions={},this._guards={}},didReceiveAttrs:function(){var e=this -void 0!==this.machine&&this.machine.stop(),void 0!==this.initial&&(this.src.initial=this.initial),this.machine=this.chart.interpret(this.src,{onTransition:e=>{const t=new CustomEvent("transition",{detail:e}) -this.ontransition(t),t.defaultPrevented||e.actions.forEach((t=>{"function"==typeof this._actions[t.type]&&this._actions[t.type](t.type,e.context,e.event)})),(0,r.set)(this,"state",e)},onGuard:function(t){for(var n=arguments.length,l=new Array(n>1?n-1:0),r=1;r1&&void 0!==arguments[1]?arguments[1]:{} -if(this.$tr&&(this.$tr.style.zIndex=null),t.target&&t.target.checked&&e!==(0,r.get)(this,"checked")){(0,r.set)(this,"checked",parseInt(e)) -const n=t.target,l=this.dom.closest("tr",n),i=this.dom.sibling(n,"div") -i.getBoundingClientRect().top+i.clientHeight>this.dom.element('footer[role="contentinfo"]').getBoundingClientRect().top?i.classList.add("above"):i.classList.remove("above"),l.style.zIndex=1,this.$tr=l}else(0,r.set)(this,"checked",null)}}})) -e.default=d})),define("consul-ui/components/tabular-details/index",["exports","@ember/component","@ember/template-factory","@ember/service","block-slots"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i=(0,n.createTemplateFactory)({id:"+Q2oF2tj",block:'[[[18,4,null],[1,"\\n"],[10,"table"],[14,0,"with-details has-actions"],[12],[1,"\\n "],[10,"thead"],[12],[1,"\\n "],[10,"tr"],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[18,4,null]],[]]]]],[1,"\\n "],[10,"th"],[14,0,"actions"],[12],[1,"Actions"],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"tbody"],[12],[1,"\\n"],[44,[[28,[37,3],["tabular-details-",[33,4],"-toggle-",[33,5],"_"],null]],[[[42,[28,[37,7],[[28,[37,7],[[33,8]],null]],null],null,[[[1," "],[10,"tr"],[15,"onclick",[28,[37,9],[[30,0],"click"],null]],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["row"]],[["default"],[[[[18,4,[[30,2],[30,3]]]],[]]]]],[1,"\\n "],[10,"td"],[14,0,"actions"],[12],[1,"\\n "],[10,"label"],[15,"for",[28,[37,3],[[30,1],[30,3]],null]],[12],[10,1],[12],[1,"Show details"],[13],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[14,"colspan","3"],[12],[1,"\\n "],[10,"input"],[15,"checked",[28,[37,10],[[28,[37,11],[[30,2,["closed"]]],null]],null]],[15,2,[30,3]],[15,3,[36,4]],[15,1,[28,[37,3],[[30,1],[30,3]],null]],[15,"onchange",[28,[37,9],[[30,0],"change",[30,2],[33,8]],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,"label"],[15,"for",[28,[37,3],[[30,1],[30,3]],null]],[12],[10,1],[12],[1,"Hide details"],[13],[13],[1,"\\n "],[10,0],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[18,4,[[30,2],[30,3]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[2,3]],null]],[1]]],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],["inputId","item","index","&default"],false,["yield","yield-slot","let","concat","name","guid","each","-track-array","items","action","not","is-empty"]]',moduleName:"consul-ui/components/tabular-details/index.hbs",isStrictMode:!1}) -var o=(0,t.setComponentTemplate)(i,t.default.extend(r.default,{dom:(0,l.inject)("dom"),onchange:function(){},init:function(){this._super(...arguments),this.guid=this.dom.guid(this)},actions:{click:function(e){this.dom.clickFirstAnchor(e)},change:function(e,t,n){this.onchange(n,e,t)}}})) -e.default=o})),define("consul-ui/components/tag-list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"6itZIEFp",block:'[[[44,[[28,[37,1],[[28,[37,2],[[30,1,["Tags"]],[28,[37,3],null,null]],null],[28,[37,2],[[30,2],[28,[37,3],null,null]],null]],null]],[[[41,[28,[37,5],[[30,3,["length"]],0],null],[[[41,[48,[30,6]],[[[1," "],[18,6,[[50,"tag-list",0,null,[["item"],[[30,1]]]]]],[1,"\\n"]],[]],[[[11,"dl"],[24,0,"tag-list"],[17,4],[12],[1,"\\n "],[11,"dt"],[4,[38,9],null,null],[12],[1,"\\n "],[1,[28,[35,10],["components.tag-list.title"],[["default"],[[28,[37,3],["common.consul.tags"],null]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[42,[28,[37,12],[[28,[37,12],[[30,3]],null]],null],null,[[[1," "],[10,1],[12],[1,[30,5]],[13],[1,"\\n"]],[5]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],[]]]],[]],null]],[3]]]],["@item","@tags","tags","&attrs","item","&default"],false,["let","union","or","array","if","gt","has-block","yield","component","tooltip","t","each","-track-array"]]',moduleName:"consul-ui/components/tag-list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/text-input/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"CVQgbzbo",block:'[[[8,[39,0],[[16,0,[28,[37,1],["text-input"," type-text"],null]],[17,1]],[["@item","@placeholder","@name","@label","@help","@validations","@chart"],[[30,2],[30,3],[30,4],[30,5],[30,6],[30,7],[30,8]]],[["label","input"],[[[[1,"\\n"],[1," "],[1,[28,[35,2],[[30,5],[30,4]],null]],[1,"\\n "]],[]],[[[1,"\\n"],[41,[30,9],[[[1," "],[11,"textarea"],[16,3,[30,4]],[4,[38,4],[[30,2]],[["validations","chart"],[[30,7],[30,8]]]],[4,[38,5],["input",[28,[37,6],[[30,10]],null]],null],[12],[1,[28,[35,2],[[30,11],[28,[37,7],[[30,2],[30,4]],null]],null]],[13],[1,"\\n"]],[]],[[[1," "],[11,"input"],[16,2,[28,[37,2],[[30,11],[28,[37,7],[[30,2],[30,4]],null]],null]],[16,3,[30,4]],[16,"placeholder",[28,[37,2],[[30,3]],null]],[24,4,"text"],[4,[38,4],[[30,2]],[["validations","chart"],[[30,7],[30,8]]]],[4,[38,5],["input",[28,[37,6],[[30,10]],null]],null],[12],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n"]],["&attrs","@item","@placeholder","@name","@label","@help","@validations","@chart","@expanded","@oninput","@value"],false,["form-input","concat","or","if","validate","on","optional","get"]]',moduleName:"consul-ui/components/text-input/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/toggle-button/index",["exports","@ember/component","@ember/template-factory","@ember/service"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"DglTzUFT",block:'[[[11,"input"],[17,1],[24,4,"checkbox"],[16,"checked",[52,[33,1],"checked",[27]]],[16,1,[28,[37,2],["toggle-button-",[33,3]],null]],[16,"onchange",[28,[37,4],[[30,0],"change"],null]],[4,[38,5],[[28,[37,6],[[30,0],"input"],null]],null],[12],[13],[1,"\\n"],[11,"label"],[16,"for",[28,[37,2],["toggle-button-",[33,3]],null]],[4,[38,5],[[28,[37,6],[[30,0],"label"],null]],null],[12],[1,"\\n "],[18,2,[[28,[37,8],null,[["click"],[[28,[37,4],[[30,0],"click"],null]]]]]],[1,"\\n"],[13]],["&attrs","&default"],false,["if","checked","concat","guid","action","did-insert","set","yield","hash"]]',moduleName:"consul-ui/components/toggle-button/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,t.default.extend({dom:(0,l.inject)("dom"),tagName:"",checked:!1,onchange:function(){},onblur:function(){},init:function(){this._super(...arguments),this.guid=this.dom.guid(this),this._listeners=this.dom.listeners()},willDestroyElement:function(){this._super(...arguments),this._listeners.remove()},didReceiveAttrs:function(){this._super(...arguments),this.checked?this.addClickOutsideListener():this._listeners.remove()},addClickOutsideListener:function(){this._listeners.remove(),this._listeners.add(this.dom.document(),"click",(e=>{this.dom.isOutside(this.label,e.target)&&this.dom.isOutside(this.label.nextElementSibling,e.target)&&(this.input.checked&&(this.input.checked=!1,this.onchange({target:this.input})),this._listeners.remove())}))},actions:{click:function(e){-1===(e.target.rel||"").indexOf("noopener")&&e.preventDefault(),this.input.checked=!this.input.checked,0!==e.detail&&e.target.blur(),this.actions.change.apply(this,[e])},change:function(e){this.input.checked&&this.addClickOutsideListener(),this.onchange({target:this.input})}}})) -e.default=i})),define("consul-ui/components/token-list/index",["exports","@ember/component","@ember/template-factory","block-slots"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"YY0PAiL0",block:'[[[18,3,null],[1,"\\n"],[41,[28,[37,2],[[33,3,["length"]],0],null],[[[1," "],[8,[39,4],[[24,0,"token-list"]],[["@rows","@items"],[5,[28,[37,5],["AccessorID:asc",[33,3]],null]]],[["default"],[[[[1,"\\n"],[41,[33,6],[[[1," "],[8,[39,7],null,[["@name"],["caption"]],[["default"],[[[[1,[34,6]]],[]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,7],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[12],[1,"AccessorID"],[13],[1,"\\n "],[10,"th"],[12],[1,"Scope"],[13],[1,"\\n "],[10,"th"],[12],[1,"Description"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["row"]],[["default"],[[[[1,"\\n "],[10,"td"],[12],[1,"\\n "],[10,3],[15,6,[28,[37,8],["dc.acls.tokens.edit",[30,1,["AccessorID"]]],null]],[15,"target",[28,[37,9],[[33,10],""],null]],[12],[1,[28,[35,11],[[30,1,["AccessorID"]],8,false],null]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[12],[1,"\\n "],[1,[52,[30,1,["Local"]],"local","global"]],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[12],[1,"\\n "],[10,2],[12],[1,[30,1,["Description"]]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[1,2]]]]],[1,"\\n"]],[]],null]],["item","index","&default"],false,["yield","if","gt","items","tabular-collection","sort-by","caption","block-slot","href-to","or","target","truncate"]]',moduleName:"consul-ui/components/token-list/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,t.default.extend(l.default,{tagName:""})) -e.default=i})),define("consul-ui/components/token-source/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={id:"token-source",initial:"idle",on:{RESTART:[{target:"secret",cond:"isSecret"},{target:"provider"}]},states:{idle:{},secret:{},provider:{on:{SUCCESS:"jwt"}},jwt:{on:{SUCCESS:"token"}},token:{}}}})),define("consul-ui/components/token-source/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","@glimmer/tracking","consul-ui/components/token-source/chart.xstate"],(function(e,t,n,l,r,i,o){var a,u,s -function c(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function d(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function p(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function f(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const m=(0,n.createTemplateFactory)({id:"49zN7wYk",block:'[[[8,[39,0],null,[["@src","@initial"],[[30,0,["chart"]],[52,[28,[37,2],[[30,1],"oidc"],null],"provider","secret"]]],[["default"],[[[[1,"\\n "],[8,[30,3],null,[["@name","@cond"],["isSecret",[30,0,["isSecret"]]]],null],[1,"\\n"],[44,[[28,[37,4],["/${partition}/${nspace}/${dc}",[28,[37,5],null,[["partition","nspace","dc"],[[28,[37,6],[[30,7,["Partition"]],[30,8]],null],[28,[37,6],[[30,7,["Namespace"]],[30,9]],null],[30,10]]]]],null]],[[[1," "],[8,[30,2],null,[["@matches"],["secret"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@src","@onchange","@onerror"],[[28,[37,4],[[28,[37,8],[[30,11],"/token/self/${value}"],null],[28,[37,5],null,[["value"],[[30,7]]]]],null],[30,0,["change"]],[30,12]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,2],null,[["@matches"],["provider"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@src","@onchange","@onerror"],[[28,[37,4],[[28,[37,8],[[30,11],"/oidc/provider/${value}"],null],[28,[37,5],null,[["value"],[[30,7,["Name"]]]]]],null],[28,[37,9],[[28,[37,10],[[30,0],[28,[37,11],[[30,0,["provider"]]],null]],[["value"],["data"]]],[28,[37,10],[[30,0],[30,5],"SUCCESS"],null]],null],[30,12]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,2],null,[["@matches"],["jwt"]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@src","@onchange","@onerror"],[[30,0,["provider","AuthURL"]],[28,[37,9],[[28,[37,10],[[30,0],[28,[37,11],[[30,0,["jwt"]]],null]],[["value"],["data"]]],[28,[37,10],[[30,0],[30,5],"SUCCESS"],null]],null],[30,12]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,2],null,[["@matches"],["token"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@src","@onchange","@onerror"],[[28,[37,4],[[28,[37,8],[[30,11],"/oidc/authorize/${provider}/${code}/${state}"],null],[28,[37,5],null,[["provider","code","state"],[[30,0,["provider","Name"]],[30,0,["jwt","authorizationCode"]],[28,[37,6],[[30,0,["jwt","authorizationState"]],""],null]]]]],null],[30,0,["change"]],[30,12]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[11]]]],[2,3,4,5,6]]]]]],["@type","State","Guard","Action","dispatch","state","@value","@partition","@nspace","@dc","path","@onerror"],false,["state-chart","if","eq","let","uri","hash","or","data-source","concat","queue","action","mut","jwt-source"]]',moduleName:"consul-ui/components/token-source/index.hbs",isStrictMode:!1}) -let h=(a=class extends l.default{constructor(){super(...arguments),d(this,"provider",u,this),d(this,"jwt",s,this),this.chart=o.default}isSecret(){return"secret"===this.args.type}change(e){e.data.toJSON=function(){return function(e){for(var t=1;t{const n=parseFloat(t.getTotalLength()),l=t.getPointAtLength(Math.ceil(n/3)) -return{id:t.id,x:Math.round(l.x-e.x),y:Math.round(l.y-e.y)}}))}},s=p(u.prototype,"iconPositions",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=p(u.prototype,"dom",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p(u.prototype,"getIconPositions",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"getIconPositions"),u.prototype),u) -e.default=m,(0,t.setComponentTemplate)(f,m)})),define("consul-ui/components/topology-metrics/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object","@ember/service"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m,h,b,y -function g(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function v(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const O=(0,n.createTemplateFactory)({id:"/n9s2uNC",block:'[[[11,0],[24,0,"topology-container consul-topology-metrics"],[4,[38,0],[[30,0,["calculate"]]],null],[12],[1,"\\n"],[41,[28,[37,2],[[30,0,["downstreams","length"]],0],null],[[[1," "],[11,0],[24,1,"downstream-container"],[4,[38,3],[[30,0,["setHeight"]],"downstream-lines"],null],[4,[38,4],[[30,0,["setHeight"]],"downstream-lines",[30,0,["downstreams"]]],null],[12],[1,"\\n"],[41,[28,[37,5],[[30,0,["emptyColumn"]]],null],[[[1," "],[10,0],[12],[1,"\\n "],[10,2],[12],[1,[30,1,["Name"]]],[13],[1,"\\n "],[10,1],[12],[1,"\\n "],[8,[39,6],null,null,[["default"],[[[[1,"\\n Only showing downstreams within the current datacenter for "],[1,[30,2,["Service","Service"]]],[1,".\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[42,[28,[37,8],[[28,[37,8],[[30,0,["downstreams"]]],null]],null],null,[[[1," "],[8,[39,9],null,[["@nspace","@dc","@service","@item","@hasMetricsProvider","@noMetricsReason"],[[30,4],[30,1,["Name"]],[30,2,["Service"]],[30,3],[30,5],[30,0,["noMetricsReason"]]]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],[[30,5],[30,0,["mainNotIngressService"]],[28,[37,11],[[30,3,["Kind"]],"ingress-gateway"],null]],null],[[[1," "],[8,[39,12],null,[["@nspace","@partition","@dc","@endpoint","@service","@item","@noMetricsReason"],[[28,[37,13],[[30,3,["Namespace"]],"default"],null],[28,[37,13],[[30,3,["Partition"]],"default"],null],[30,3,["Datacenter"]],"downstream-summary-for-service",[30,2,["Service","Service"]],[30,3,["Name"]],[30,0,["noMetricsReason"]]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[10,0],[14,1,"metrics-container"],[12],[1,"\\n "],[10,0],[14,0,"metrics-header"],[12],[1,"\\n "],[1,[30,2,["Service","Service"]]],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,11],[[30,2,["Service","Meta","external-source"]],"consul-api-gateway"],null],[[[41,[30,5],[[[1," "],[8,[39,14],null,[["@nspace","@partition","@dc","@service","@protocol","@noMetricsReason"],[[28,[37,13],[[30,2,["Service","Namespace"]],"default"],null],[28,[37,13],[[33,15,["Service","Partition"]],"default"],null],[30,1,["Name"]],[30,2,["Service","Service"]],[30,6,["Protocol"]],[30,0,["noMetricsReason"]]]],null],[1,"\\n"],[41,[30,0,["mainNotIngressService"]],[[[1," "],[8,[39,12],null,[["@nspace","@partition","@dc","@endpoint","@service","@protocol","@noMetricsReason"],[[28,[37,13],[[30,2,["Service","Namespace"]],"default"],null],[28,[37,13],[[33,15,["Service","Partition"]],"default"],null],[30,1,["Name"]],"summary-for-service",[30,2,["Service","Service"]],[30,6,["Protocol"]],[30,0,["noMetricsReason"]]]],null],[1,"\\n"]],[]],null]],[]],null],[1," "],[10,0],[14,0,"link"],[12],[1,"\\n"],[41,[30,7],[[[1," "],[10,3],[14,0,"metrics-link"],[15,6,[30,7]],[14,"target","_blank"],[14,"rel","noopener noreferrer"],[12],[1,"Open dashboard"],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[14,0,"config-link"],[15,6,[29,[[28,[37,16],["CONSUL_DOCS_URL"],null],"/connect/observability/ui-visualization"]]],[14,"target","_blank"],[14,"rel","noopener noreferrer"],[12],[1,"Configure dashboard"],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[10,0],[14,1,"downstream-lines"],[12],[1,"\\n "],[8,[39,17],null,[["@type","@service","@view","@center","@lines","@items","@oncreate"],["downstream",[30,2],[30,0,["downView"]],[30,0,["centerDimensions"]],[30,0,["downLines"]],[30,0,["downstreams"]],[28,[37,18],[[30,0],[30,8]],null]]],null],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,2],[[30,0,["upstreams","length"]],0],null],[[[1," "],[10,0],[14,1,"upstream-column"],[12],[1,"\\n"],[42,[28,[37,19],[[28,[37,20],["PeerOrDatacenter",[30,0,["upstreams"]]],null]],null],null,[[[1," "],[11,0],[24,1,"upstream-container"],[4,[38,3],[[30,0,["setHeight"]],"upstream-lines"],null],[4,[38,4],[[30,0,["setHeight"]],"upstream-lines",[30,0,["upstreams"]]],null],[12],[1,"\\n"],[41,[30,10],[[[1," "],[10,2],[12],[1,[30,10]],[13],[1,"\\n"]],[]],null],[42,[28,[37,8],[[28,[37,8],[[30,9]],null]],null],null,[[[1," "],[8,[39,9],null,[["@dc","@item","@service"],[[30,1,["Name"]],[30,11],[30,2,["Service"]]]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],[[30,5],[30,0,["mainNotIngressService"]],[28,[37,11],[[30,11,["Kind"]],"ingress-gateway"],null]],null],[[[1," "],[8,[39,12],null,[["@nspace","@partition","@dc","@endpoint","@service","@item","@noMetricsReason"],[[28,[37,13],[[30,11,["Namespace"]],"default"],null],[28,[37,13],[[30,11,["Partition"]],"default"],null],[30,11,["Datacenter"]],"upstream-summary-for-service",[30,2,["Service","Service"]],[30,11,["Name"]],[30,0,["noMetricsReason"]]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n"]],[11]],null],[1," "],[13],[1,"\\n"]],[9,10]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[10,0],[14,1,"upstream-lines"],[12],[1,"\\n "],[8,[39,21],null,[["@type","@service","@view","@center","@lines","@items","@oncreate"],["upstream",[30,2],[30,0,["upView"]],[30,0,["centerDimensions"]],[30,0,["upLines"]],[30,0,["upstreams"]],[28,[37,18],[[30,0],[30,8]],null]]],null],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["@dc","@service","item","@nspace","@hasMetricsProvider","@topology","@metricsHref","@oncreate","upstreams","dc","item"],false,["on-resize","if","gt","did-insert","did-update","not","tooltip","each","-track-array","topology-metrics/card","and","not-eq","topology-metrics/stats","or","topology-metrics/series","service","env","topology-metrics/down-lines","action","-each-in","group-by","topology-metrics/up-lines"]]',moduleName:"consul-ui/components/topology-metrics/index.hbs",isStrictMode:!1}) -let P=(a=(0,o.inject)("env"),u=(0,o.inject)(),s=class extends l.default{constructor(){super(...arguments),g(this,"env",c,this),g(this,"abilities",d,this),g(this,"centerDimensions",p,this),g(this,"downView",f,this),g(this,"downLines",m,this),g(this,"upView",h,this),g(this,"upLines",b,this),g(this,"noMetricsReason",y,this)}drawDownLines(e){const t=["allow","deny"],n={x:this.centerDimensions.x-7,y:this.centerDimensions.y+this.centerDimensions.height/2} -return e.map((e=>{const t=e.getBoundingClientRect(),l={x:t.x+t.width,y:t.y+t.height/2} -return{id:e.id,permission:e.getAttribute("data-permission"),dest:n,src:l}})).sort(((e,n)=>t.indexOf(e.permission)-t.indexOf(n.permission)))}drawUpLines(e){const t=["allow","deny"],n={x:this.centerDimensions.x+5.5,y:this.centerDimensions.y+this.centerDimensions.height/2} -return e.map((e=>{const t=e.getBoundingClientRect(),l={x:t.x-t.width-25,y:t.y+t.height/2} -return{id:e.id,permission:e.getAttribute("data-permission"),dest:l,src:n}})).sort(((e,n)=>t.indexOf(e.permission)-t.indexOf(n.permission)))}emptyColumn(){const e=(0,i.get)(this.args.topology,"noDependencies") -return!this.env.var("CONSUL_ACLS_ENABLED")||e}get downstreams(){const e=(0,i.get)(this.args.topology,"Downstreams")||[],t=[...e],n=(0,i.get)(this.args.topology,"noDependencies") -if(!this.env.var("CONSUL_ACLS_ENABLED")&&n)t.push({Name:"Downstreams unknown.",Empty:!0,Datacenter:"",Namespace:""}) -else if(0===e.length){const e=this.abilities.can("use peers") -t.push({Name:e?"No downstreams, or the downstreams are imported services.":"No downstreams.",Datacenter:"",Namespace:""})}return t}get upstreams(){const e=(0,i.get)(this.args.topology,"Upstreams")||[] -e.forEach((e=>{e.PeerOrDatacenter=e.PeerName||e.Datacenter})) -const t=[...e],n=(0,i.get)(this.args.dc,"DefaultACLPolicy"),l=(0,i.get)(this.args.topology,"wildcardIntention"),r=(0,i.get)(this.args.topology,"noDependencies") -return!this.env.var("CONSUL_ACLS_ENABLED")&&r?t.push({Name:"Upstreams unknown.",Datacenter:"",PeerOrDatacenter:"",Namespace:""}):"allow"===n||l?t.push({Name:"* (All Services)",Datacenter:"",PeerOrDatacenter:"",Namespace:""}):0===e.length&&t.push({Name:"No upstreams.",Datacenter:"",PeerOrDatacenter:"",Namespace:""}),t}get mainNotIngressService(){return"ingress-gateway"!==((0,i.get)(this.args.service.Service,"Kind")||"")}setHeight(e,t){if(e){const n=e.getBoundingClientRect() -document.getElementById(`${t[0]}`).setAttribute("style",`height:${n.height}px`)}this.calculate()}calculate(){this.args.isRemoteDC?this.noMetricsReason="remote-dc":"ingress-gateway"===this.args.service.Service.Kind?this.noMetricsReason="ingress-gateway":this.noMetricsReason=null -const e=document.getElementById("downstream-lines").getBoundingClientRect(),t=document.getElementById("upstream-lines").getBoundingClientRect(),n=document.getElementById("upstream-column") -this.emptyColumn?this.downView={x:e.x,y:e.y,width:e.width,height:e.height+10}:this.downView=e,n&&(this.upView={x:t.x,y:t.y,width:t.width,height:n.getBoundingClientRect().height+10}) -const l=[...document.querySelectorAll("#downstream-container .topology-metrics-card")],r=document.querySelector(".metrics-header"),i=[...document.querySelectorAll("#upstream-column .topology-metrics-card")] -this.centerDimensions=r.getBoundingClientRect(),this.downLines=this.drawDownLines(l),this.upLines=this.drawUpLines(i)}},c=v(s.prototype,"env",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=v(s.prototype,"abilities",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=v(s.prototype,"centerDimensions",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=v(s.prototype,"downView",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=v(s.prototype,"downLines",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return[]}}),h=v(s.prototype,"upView",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=v(s.prototype,"upLines",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return[]}}),y=v(s.prototype,"noMetricsReason",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v(s.prototype,"setHeight",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"setHeight"),s.prototype),v(s.prototype,"calculate",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"calculate"),s.prototype),s) -e.default=P,(0,t.setComponentTemplate)(O,P)})),define("consul-ui/components/topology-metrics/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"PrGtFY8+",block:'[[[41,[28,[37,1],[[30,1],"create"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your intention has been added.\\n"]],[]],[[[1," There was an error adding your intention.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"update"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your intention has been saved.\\n"]],[]],[[[1," There was an error saving your intention.\\n"]],[]]]],[]],null]],[]]],[44,[[30,3,["errors","firstObject"]]],[[[41,[30,4,["detail"]],[[[1," "],[10,"br"],[12],[13],[1,[28,[35,3],["(",[52,[30,4,["status"]],[28,[37,3],[[30,4,["status"]],": "],null]],[30,4,["detail"]],")"],null]],[1,"\\n"]],[]],null]],[4]]],[1,"\\n"]],["@type","@status","@error","error"],false,["if","eq","let","concat"]]',moduleName:"consul-ui/components/topology-metrics/notifications/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/topology-metrics/popover/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"2ZmfKieE",block:'[[[11,0],[16,0,[29,["topology-metrics-popover ",[30,1]]]],[17,2],[12],[1,"\\n"],[44,[[28,[37,1],["top:",[30,3,["y"]],"px;left:",[30,3,["x"]],"px;"],null],[52,[28,[37,3],[[30,1],"deny"],null],"Add intention","View intention"]],[[[41,[28,[37,4],[[30,6]],null],[[[41,[28,[37,3],[[30,1],"deny"],null],[[[1," "],[8,[39,5],[[24,0,"dangerous"],[4,[38,6],[[28,[37,7],[[30,0],"popover"],null]],null]],null,[["header","body","actions"],[[[[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.deny.header"],null]],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n"],[41,[30,7,["Intention","HasExact"]],[[[1," "],[1,[28,[35,8],["components.consul.topology-metrics.popover.deny.body.isExact"],null]],[1,"\\n"]],[]],[[[1," "],[1,[28,[35,8],["components.consul.topology-metrics.popover.deny.body.notExact"],null]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,8,["Action"]],[[24,0,"action"]],null,[["default"],[[[[1,"\\n "],[11,"button"],[24,4,"button"],[4,[38,9],["click",[30,9]],null],[12],[1,"\\n"],[41,[30,7,["Intention","HasExact"]],[[[1," "],[1,[28,[35,8],["components.consul.topology-metrics.popover.deny.action.isExact"],null]],[1,"\\n"]],[]],[[[1," "],[1,[28,[35,8],["components.consul.topology-metrics.popover.deny.action.notExact"],null]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,8,["Action"]],null,null,[["default"],[[[[1,"\\n "],[11,"button"],[24,0,"cancel"],[24,4,"button"],[4,[38,9],["click",[28,[37,10],[[28,[37,11],[[30,0,["popoverController","hide"]]],null]],null]],null],[12],[1,"\\n Cancel\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n"]],[]],[[[41,[28,[37,3],[[30,1],"not-defined"],null],[[[1," "],[8,[39,5],[[24,0,"warning documentation"],[4,[38,6],[[28,[37,7],[[30,0],"popover"],null]],null]],null,[["header","body","actions"],[[[[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.not-defined.header"],null]],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.not-defined.body"],[["downstream","upstream"],[[30,7,["Name"]],[30,10,["Name"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,11,["Action"]],[[24,0,"action"]],null,[["default"],[[[[1,"\\n "],[10,3],[15,6,[29,[[28,[37,12],["CONSUL_DOCS_URL"],null],"/connect/registration/service-registration#upstreams"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.not-defined.action"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,11,["Action"]],null,null,[["default"],[[[[1,"\\n "],[11,"button"],[24,0,"cancel"],[24,4,"button"],[4,[38,9],["click",[28,[37,10],[[28,[37,11],[[30,0,["popoverController","hide"]]],null]],null]],null],[12],[1,"\\n Close\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[11]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,5],[[24,0,"info"],[4,[38,6],[[28,[37,7],[[30,0],"popover"],null]],null]],null,[["header","body","actions"],[[[[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.l7.header"],null]],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.l7.body"],null]],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,12,["Action"]],[[24,0,"action"]],null,[["default"],[[[[1,"\\n "],[10,3],[15,6,[28,[37,13],["dc.services.show.intentions.edit",[28,[37,1],[[30,7,["Intention","ID"]]],null]],null]],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.l7.action"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,12,["Action"]],null,null,[["default"],[[[[1,"\\n "],[11,"button"],[24,0,"cancel"],[24,4,"button"],[4,[38,9],["click",[28,[37,10],[[28,[37,11],[[30,0,["popoverController","hide"]]],null]],null]],null],[12],[1,"\\n Close\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[12]]]]],[1,"\\n "]],[]]]],[]]],[1," "],[11,"button"],[23,5,[30,4]],[16,"aria-label",[30,5]],[24,4,"button"],[4,[38,14],[[30,0,["popover"]]],[["options","returns"],[[28,[37,15],null,[["theme","placement"],["square-tail","bottom-start"]]],[28,[37,7],[[30,0],"popoverController"],null]]]],[4,[38,9],["click",[28,[37,10],[[28,[37,11],[[30,0,["popoverController","show"]]],null]],null]],null],[12],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[11,"button"],[23,5,[30,4]],[16,"aria-label",[30,5]],[24,4,"button"],[4,[38,16],[true],null],[12],[1,"\\n "],[13],[1,"\\n"]],[]]]],[4,5]]],[13],[1,"\\n"]],["@type","&attrs","@position","style","label","@disabled","@item","Actions","@oncreate","@service","Actions","Actions"],false,["let","concat","if","eq","not","informed-action","did-insert","set","t","on","fn","optional","env","href-to","with-overlay","hash","disabled"]]',moduleName:"consul-ui/components/topology-metrics/popover/index.hbs",isStrictMode:!1}) -class i extends l.default{}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/topology-metrics/series/index",["exports","@ember/component","@ember/template-factory","dayjs","dayjs/plugin/calendar","d3-selection","d3-scale","d3-scale-chromatic","d3-shape","d3-array","@ember/object"],(function(e,t,n,l,r,i,o,a,u,s,c){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const d=(0,n.createTemplateFactory)({id:"AXSuGOoT",block:'[[[41,[28,[37,1],[[30,1]],null],[[[1," "],[8,[39,2],null,[["@src","@onchange","@onerror"],[[28,[37,3],["/${partition}/${nspace}/${dc}/metrics/summary-for-service/${service}/${protocol}",[28,[37,4],null,[["nspace","partition","dc","service","protocol"],[[30,2],[30,3],[30,4],[30,5],[30,6]]]]],null],[28,[37,5],[[30,0],"change"],null],[28,[37,5],[[30,0],[28,[37,6],[[33,7]],null]],[["value"],["error"]]]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[1,[28,[35,8],["resize",[28,[37,5],[[30,0],"redraw"],null]],null]],[1,"\\n"],[1,[28,[35,9],[[28,[37,5],[[30,0],"redraw"],null]],null]],[1,"\\n\\n"],[41,[28,[37,1],[[33,10]],null],[[[41,[33,11,["labels"]],[[[1," "],[11,3],[24,0,"sparkline-key-link"],[4,[38,12],["click",[28,[37,13],[[30,0,["modal","open"]]],null]],null],[12],[1,"\\n Key\\n "],[13],[1,"\\n"]],[]],null]],[]],null],[1,"\\n"],[10,0],[14,0,"sparkline-wrapper"],[12],[1,"\\n "],[10,0],[14,0,"tooltip"],[12],[1,"\\n "],[10,0],[14,0,"sparkline-time"],[12],[1,"Timestamp"],[13],[1,"\\n "],[13],[1,"\\n"],[41,[33,10],[[[1," "],[8,[39,14],null,[["@noMetricsReason","@error"],[[30,1],[99,7,["@error"]]]],null],[1,"\\n"]],[]],null],[1," "],[10,"svg"],[14,0,"sparkline"],[12],[13],[1,"\\n"],[13],[1,"\\n\\n"],[8,[39,15],[[24,0,"sparkline-key"]],[["@aria"],[[28,[37,4],null,[["label"],["Metrics Key"]]]]],[["default"],[[[[1,"\\n "],[8,[39,16],null,[["@target","@name","@value"],[[30,0],"modal",[30,7]]],null],[1,"\\n "],[8,[39,17],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h3"],[12],[1,"Metrics Key"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,17],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"sparkline-key-content"],[12],[1,"\\n "],[10,2],[12],[1,"This key describes the metrics corresponding to the graph tooltip labels in more detail."],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n"],[42,[28,[37,19],[[33,11,["labels"]]],null],null,[[[1," "],[10,"dt"],[12],[1,[30,9]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,8]],[13],[1,"\\n"]],[8,9]],null],[1," "],[13],[1,"\\n"],[41,[51,[33,11,["labels"]]],[[[1," "],[10,1],[14,0,"no-data"],[12],[1,"No metrics loaded."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,17],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"button"],[14,0,"type-cancel"],[15,"onclick",[28,[37,5],[[30,0],[30,7,["close"]]],null]],[14,4,"button"],[12],[1,"\\n Close\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[7]]]]]],["@noMetricsReason","@nspace","@partition","@dc","@service","@protocol","modal","desc","label"],false,["if","not","data-source","uri","hash","action","mut","error","on-window","did-insert","empty","data","on","optional","topology-metrics/status","modal-dialog","ref","block-slot","each","-each-in","unless"]]',moduleName:"consul-ui/components/topology-metrics/series/index.hbs",isStrictMode:!1}) -l.default.extend(r.default) -var p=(0,t.setComponentTemplate)(d,t.default.extend({data:null,empty:!1,actions:{redraw:function(e){this.drawGraphs()},change:function(e){this.set("data",e.data.series),this.drawGraphs(),this.rerender()}},drawGraphs:function(){if(!this.data)return void(0,c.set)(this,"empty",!0) -let e=this.svg=(0,i.select)(this.element.querySelector("svg.sparkline")) -e.on("mouseover mousemove mouseout",null),e.selectAll("path").remove(),e.selectAll("rect").remove() -let t=e.node().getBoundingClientRect(),n=t.width,l=t.height,r=this.data||{},d=r.data||[],p=r.labels||{},f=r.unitSuffix||"",m=Object.keys(p).filter((e=>"Total"!=e)) -if(0==d.length||0==m.length)return void(0,c.set)(this,"empty",!0);(0,c.set)(this,"empty",!1) -let h=(0,u.stack)().keys(m).order(u.stackOrderReverse)(d),b=d.map((e=>{let t=0 -return m.forEach((n=>{t+=e[n]})),t})),y=(0,o.scaleTime)().domain((0,s.extent)(d,(e=>e.time))).range([0,n]),g=(0,o.scaleLinear)().domain([0,(0,s.max)(b)]).range([l,0]),v=(0,u.area)().x((e=>y(e.data.time))).y1((e=>g(e[0]))).y0((e=>g(e[1]))),O=["#DCE0E6","#C73445"].concat(a.schemeTableau10) -m.includes("Outbound")&&(O=["#DCE0E6","#0E40A3"].concat(a.schemeTableau10)) -let P=(0,o.scaleOrdinal)(O).domain(m) -e.selectAll("path").data(h).join("path").attr("fill",(e=>{let{key:t}=e -return P(t)})).attr("stroke",(e=>{let{key:t}=e -return P(t)})).attr("d",v) -let x=e.append("rect").attr("class","cursor").style("visibility","hidden").attr("width",1).attr("height",l).attr("x",0).attr("y",0),w=(0,i.select)(this.element.querySelector(".tooltip")) -for(var j of(w.selectAll(".sparkline-tt-legend").remove(),w.selectAll(".sparkline-tt-sum").remove(),m)){let e=w.append("div").attr("class","sparkline-tt-legend") -e.append("div").attr("class","sparkline-tt-legend-color").style("background-color",P(j)),e.append("span").text(j).append("span").attr("class","sparkline-tt-legend-value")}let _=w.selectAll(".sparkline-tt-legend-value") -m.length>1&&w.append("div").attr("class","sparkline-tt-sum").append("span").text("Total").append("span").attr("class","sparkline-tt-sum-value") -let k=this -e.on("mouseover",(function(e){w.style("visibility","visible"),x.style("visibility","visible"),k.updateTooltip(e,d,h,b,f,y,w,_,x)})).on("mousemove",(function(e){k.updateTooltip(e,d,h,b,f,y,w,_,x)})).on("mouseout",(function(e){w.style("visibility","hidden"),x.style("visibility","hidden")}))},willDestroyElement:function(){this._super(...arguments),void 0!==this.svg&&this.svg.on("mouseover mousemove mouseout",null)},updateTooltip:function(e,t,n,r,o,a,u,c,d){let[p]=(0,i.pointer)(e) -d.attr("x",p) -let m=a.invert(p) -var h=(0,s.bisector)((function(e){return e.time})).left -let b=h(t,m) -var y -u.style("left",p-22+"px").select(".sparkline-time").text((y=m,(0,l.default)(y).calendar(null,{sameDay:"[Today at] h:mm:ss A",lastDay:"[Yesterday at] h:mm:ss A",lastWeek:"[Last] dddd at h:mm:ss A",sameElse:"MMM DD at h:mm:ss A"}))),u.select(".sparkline-tt-sum-value").text(`${f(r[b])}${o}`),c.nodes().forEach(((e,t)=>{let l=n[t][b][1]-n[t][b][0];(0,i.select)(e).text(`${f(l)}${o}`)})),d.attr("x",p)}})) -function f(e){return e<1e3?Number.isInteger(e)?""+e:Number(e>=100?e.toPrecision(3):e<1?e.toFixed(2):e.toPrecision(2)):e>=1e3&&e<1e6?+(e/1e3).toPrecision(3)+"k":e>=1e6&&e<1e9?+(e/1e6).toPrecision(3)+"m":e>=1e9&&e<1e12?+(e/1e9).toPrecision(3)+"g":e>=1e12?+(e/1e12).toFixed(0)+"t":void 0}e.default=p})),define("consul-ui/components/topology-metrics/source-type/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"wl8kyvfj",block:'[[[11,1],[24,0,"topology-metrics-source-type"],[4,[38,0],[[28,[37,1],[[28,[37,2],["components.consul.topology-metrics.source-type.",[30,1],".tooltip"],null]],null]],null],[12],[1,"\\n "],[1,[28,[35,1],[[28,[37,2],["components.consul.topology-metrics.source-type.",[30,1],".text"],null]],null]],[1,"\\n"],[13]],["@source"],false,["tooltip","t","concat"]]',moduleName:"consul-ui/components/topology-metrics/source-type/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/topology-metrics/stats/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object"],(function(e,t,n,l,r,i){var o,a,u -function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const d=(0,n.createTemplateFactory)({id:"OvZgaKFU",block:'[[[41,[28,[37,1],[[30,1]],null],[[[1," "],[8,[39,2],null,[["@src","@onchange","@onerror"],[[28,[37,3],["/${partition}/${nspace}/${dc}/metrics/${endpoint}/${service}/${protocol}",[28,[37,4],null,[["nspace","partition","dc","endpoint","service","protocol"],[[30,2],[30,3],[30,4],[30,5],[30,6],[28,[37,5],[[30,7],""],null]]]]],null],[28,[37,6],[[30,0],"statsUpdate"],null],[28,[37,6],[[30,0],[28,[37,7],[[33,8]],null]],[["value"],["error"]]]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[11,0],[17,8],[24,0,"topology-metrics-stats"],[12],[1,"\\n"],[41,[33,9],[[[42,[28,[37,11],[[28,[37,11],[[33,12]],null]],null],null,[[[1," "],[11,"dl"],[4,[38,13],[[30,9,["desc"]]],[["options"],[[28,[37,4],null,[["allowHTML"],[true]]]]]],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[1,[30,9,["value"]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,9,["label"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[9]],[[[1," "],[10,1],[12],[1,"No Metrics Available"],[13],[1,"\\n"]],[]]]],[]],[[[1," "],[8,[39,14],null,[["@noMetricsReason","@error"],[[30,1],[99,8,["@error"]]]],null],[1,"\\n"]],[]]],[13]],["@noMetricsReason","@nspace","@partition","@dc","@endpoint","@service","@protocol","&attrs","stat"],false,["if","not","data-source","uri","hash","or","action","mut","error","hasLoaded","each","-track-array","stats","tooltip","topology-metrics/status"]]',moduleName:"consul-ui/components/topology-metrics/stats/index.hbs",isStrictMode:!1}) -let p=(o=class extends l.default{constructor(){super(...arguments),s(this,"stats",a,this),s(this,"hasLoaded",u,this)}statsUpdate(e){if("summary-for-service"==this.args.endpoint)this.stats=e.data.stats -else{let t=this.args.nspace||"" -0===t.length&&(t="default") -let n=`${this.args.item}.${t}.${this.args.dc}` -this.stats=e.data.stats[n]}this.stats=(this.stats||[]).slice(0,4),this.hasLoaded=!0}},a=c(o.prototype,"stats",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return null}}),u=c(o.prototype,"hasLoaded",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return!1}}),c(o.prototype,"statsUpdate",[i.action],Object.getOwnPropertyDescriptor(o.prototype,"statsUpdate"),o.prototype),o) -e.default=p,(0,t.setComponentTemplate)(d,p)})),define("consul-ui/components/topology-metrics/status/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"weO6aWlc",block:'[[[41,[28,[37,1],[[30,1],[30,2]],null],[[[1," "],[10,1],[14,0,"topology-metrics-status-error"],[12],[1,"\\n"],[41,[28,[37,2],[[30,1],"ingress-gateway"],null],[[[1," "],[1,[28,[35,3],["components.consul.topology-metrics.status.ingress-gateway"],null]],[1,"\\n"]],[]],[[[41,[28,[37,2],[[30,1],"remote-dc"],null],[[[1," "],[1,[28,[35,3],["components.consul.topology-metrics.status.error"],null]],[1,"\\n "],[11,1],[4,[38,4],[[28,[37,3],["components.consul.topology-metrics.status.remote-dc"],null]],null],[12],[13],[1,"\\n"]],[]],[[[41,[30,2],[[[1," "],[1,[28,[35,3],["components.consul.topology-metrics.status.error"],null]],[1,"\\n "]],[]],null]],[]]]],[]]],[1," "],[13],[1,"\\n"]],[]],[[[1," "],[10,1],[14,0,"topology-metrics-status-loader"],[12],[1,[28,[35,3],["components.consul.topology-metrics.status.loading"],null]],[13],[1,"\\n"]],[]]]],["@noMetricsReason","@error"],false,["if","or","eq","t","tooltip"]]',moduleName:"consul-ui/components/topology-metrics/status/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/components/topology-metrics/up-lines/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object","@ember/service"],(function(e,t,n,l,r,i,o){var a,u,s,c -function d(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function p(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const f=(0,n.createTemplateFactory)({id:"MfMA5Fce",block:'[[[41,[28,[37,1],[[30,1,["length"]],0],null],[[[1," "],[11,"svg"],[16,"viewBox",[28,[37,2],[[30,2,["x"]]," ",[30,3,["y"]]," ",[30,3,["width"]]," ",[30,3,["height"]]],null]],[24,"preserveAspectRatio","none"],[4,[38,3],[[30,0,["getIconPositions"]]],null],[4,[38,4],[[30,0,["getIconPositions"]],[30,1]],null],[12],[1,"\\n "],[10,"defs"],[12],[1,"\\n "],[10,"marker"],[15,1,[28,[37,2],[[30,0,["guid"]],"-allow-dot"],null]],[14,0,"allow-dot"],[14,"viewBox","-2 -2 15 15"],[14,"refX","6"],[14,"refY","6"],[14,"markerWidth","6"],[14,"markerHeight","6"],[12],[1,"\\n "],[10,"circle"],[14,"cx","6"],[14,"cy","6"],[14,"r","6"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"marker"],[15,1,[28,[37,2],[[30,0,["guid"]],"-allow-arrow"],null]],[14,0,"allow-arrow"],[14,"viewBox","-1 -1 12 12"],[14,"refX","5"],[14,"refY","5"],[14,"markerWidth","6"],[14,"markerHeight","6"],[14,"orient","auto-start-reverse"],[12],[1,"\\n "],[10,"polygon"],[14,"points","0 0 10 5 0 10"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"marker"],[15,1,[28,[37,2],[[30,0,["guid"]],"-deny-dot"],null]],[14,0,"deny-dot"],[14,"viewBox","-2 -2 15 15"],[14,"refX","6"],[14,"refY","6"],[14,"markerWidth","6"],[14,"markerHeight","6"],[12],[1,"\\n "],[10,"circle"],[14,"cx","6"],[14,"cy","6"],[14,"r","6"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"marker"],[15,1,[28,[37,2],[[30,0,["guid"]],"-deny-arrow"],null]],[14,0,"deny-arrow"],[14,"viewBox","-1 -1 12 12"],[14,"refX","5"],[14,"refY","5"],[14,"markerWidth","6"],[14,"markerHeight","6"],[14,"orient","auto-start-reverse"],[12],[1,"\\n "],[10,"polygon"],[14,"points","0 0 10 5 0 10"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[42,[28,[37,6],[[28,[37,6],[[30,1]],null]],null],null,[[[41,[28,[37,7],[[30,4,["permission"]],"deny"],null],[[[1," "],[10,"path"],[15,1,[28,[37,2],[[30,0,["guid"]],[30,4,["id"]]],null]],[15,"d",[28,[37,8],[[30,4,["dest"]]],[["src"],[[30,4,["src"]]]]]],[15,"marker-start",[28,[37,2],["url(#",[30,0,["guid"]],"-deny-dot)"],null]],[15,"marker-end",[28,[37,2],["url(#",[30,0,["guid"]],"-deny-arrow)"],null]],[15,"data-permission",[30,4,["permission"]]],[12],[13],[1,"\\n"]],[]],[[[1," "],[10,"path"],[15,1,[28,[37,2],[[30,0,["guid"]],[30,4,["id"]]],null]],[15,"d",[28,[37,8],[[30,4,["dest"]]],[["src"],[[30,4,["src"]]]]]],[15,"marker-start",[28,[37,2],["url(#",[30,0,["guid"]],"-allow-dot)"],null]],[15,"marker-end",[28,[37,2],["url(#",[30,0,["guid"]],"-allow-arrow)"],null]],[15,"data-permission",[30,4,["permission"]]],[12],[13],[1,"\\n"]],[]]]],[4]],null],[1," "],[13],[1,"\\n"]],[]],null],[42,[28,[37,6],[[28,[37,6],[[30,5]],null]],null],null,[[[41,[28,[37,9],[[28,[37,10],[[30,6,["Datacenter"]],""],null],[28,[37,11],[[28,[37,12],[[30,6,["Intention","Allowed"]]],null],[30,6,["Intention","HasPermissions"]]],null]],null],[[[1," "],[8,[39,13],null,[["@type","@position","@item","@disabled","@oncreate"],[[52,[30,6,["Intention","HasPermissions"]],"l7","deny"],[28,[37,14],["id",[28,[37,2],[[30,0,["guid"]],[30,6,["Namespace"]],[30,6,["Name"]]],null],[30,0,["iconPositions"]]],null],[30,6],false,[28,[37,15],[[30,0],[30,7],[30,8],[30,6]],null]]],null],[1,"\\n"]],[]],null]],[6]],null]],["@lines","@center","@view","line","@items","item","@oncreate","@service"],false,["if","gt","concat","did-insert","did-update","each","-track-array","eq","svg-curve","and","not-eq","or","not","topology-metrics/popover","find-by","action"]]',moduleName:"consul-ui/components/topology-metrics/up-lines/index.hbs",isStrictMode:!1}) -let m=(a=(0,o.inject)("dom"),u=class extends l.default{constructor(){super(...arguments),d(this,"iconPositions",s,this),d(this,"dom",c,this)}get guid(){return this.dom.guid(this)}getIconPositions(){const e=this.args.center,t=this.args.view,n=[...document.querySelectorAll("#upstream-lines path")] -this.iconPositions=n.map((n=>{const l=parseFloat(n.getTotalLength()),r=n.getPointAtLength(Math.ceil(.666*l)) -return{id:n.id,x:Math.round(r.x-e.x),y:Math.round(r.y-t.y)}}))}},s=p(u.prototype,"iconPositions",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=p(u.prototype,"dom",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p(u.prototype,"getIconPositions",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"getIconPositions"),u.prototype),u) -e.default=m,(0,t.setComponentTemplate)(f,m)})),define("consul-ui/components/torii-iframe-placeholder",["exports","torii/components/torii-iframe-placeholder"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=t.default -e.default=n})),define("consul-ui/components/vertical-collection",["exports","@html-next/vertical-collection/components/vertical-collection/component"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/watcher/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","@glimmer/tracking","@ember/runloop","@ember/service"],(function(e,t,n,l,r,i,o,a){var u,s,c,d -function p(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function f(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const m=(0,n.createTemplateFactory)({id:"WK8VbrJT",block:'[[[18,1,[[28,[37,1],null,[["fns"],[[28,[37,1],null,[["start","stop"],[[30,0,["start"]],[30,0,["stop"]]]]]]]]]],[1,"\\n"]],["&default"],false,["yield","hash"]]',moduleName:"consul-ui/components/watcher/index.hbs",isStrictMode:!1}) -let h=(u=class extends l.default{constructor(){super(...arguments),p(this,"env",s,this),p(this,"_isPolling",c,this),p(this,"cancel",d,this)}get timeout(){return this.isTesting?300:this.args.timeout||1e4}get isTesting(){return"testing"===this.env.var("environment")}get isPolling(){const{isTesting:e,_isPolling:t}=this -return!e&&t}start(){this._isPolling=!0,this.watchTask()}stop(){this._isPolling=!1,(0,o.cancel)(this.cancel)}watchTask(){const e=(0,o.later)(this,(()=>{var e,t -null===(e=(t=this.args).watch)||void 0===e||e.call(t),this.isPolling&&this.watchTask()}),this.timeout) -this.cancel=e}},s=f(u.prototype,"env",[a.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=f(u.prototype,"_isPolling",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return!1}}),d=f(u.prototype,"cancel",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return null}}),f(u.prototype,"start",[r.action],Object.getOwnPropertyDescriptor(u.prototype,"start"),u.prototype),f(u.prototype,"stop",[r.action],Object.getOwnPropertyDescriptor(u.prototype,"stop"),u.prototype),u) -e.default=h,(0,t.setComponentTemplate)(m,h)})),define("consul-ui/components/yield-slot",["exports","block-slots/components/yield-slot"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/yield/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.createTemplateFactory)({id:"uvrXCen3",block:'[[[18,1,null],[1,"\\n"]],["&default"],false,["yield"]]',moduleName:"consul-ui/components/yield/index.hbs",isStrictMode:!1}) -var i=(0,t.setComponentTemplate)(r,(0,l.default)()) -e.default=i})),define("consul-ui/controllers/_peered-resource",["exports","@ember/controller","@ember/service"],(function(e,t,n){var l,r -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let i=(l=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="abilities",l=this,(n=r)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}get _searchProperties(){const{searchProperties:e}=this -return this.abilities.can("use peers")?e:e.filter((e=>"PeerName"!==e))}},o=l.prototype,a="abilities",u=[n.inject],s={configurable:!0,enumerable:!0,writable:!0,initializer:null},d={},Object.keys(s).forEach((function(e){d[e]=s[e]})),d.enumerable=!!d.enumerable,d.configurable=!!d.configurable,("value"in d||d.initializer)&&(d.writable=!0),d=u.slice().reverse().reduce((function(e,t){return t(o,a,e)||e}),d),c&&void 0!==d.initializer&&(d.value=d.initializer?d.initializer.call(c):void 0,d.initializer=void 0),void 0===d.initializer&&(Object.defineProperty(o,a,d),d=null),r=d,l) -var o,a,u,s,c,d -e.default=i})),define("consul-ui/controllers/application",["exports","@ember/service","@ember/controller","@ember/application","@ember/object","consul-ui/utils/routing/transitionable"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p -function f(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function m(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let h=(o=(0,t.inject)("router"),a=(0,t.inject)("store"),u=(0,t.inject)("feedback"),s=class extends n.default{constructor(){super(...arguments),f(this,"router",c,this),f(this,"store",d,this),f(this,"feedback",p,this)}reauthorize(e){this.feedback.execute((()=>{this.store.invalidate() -const t={} -if(e.data){const n=e.data -if(void 0!==this.nspace){const e=(0,r.get)(n,"Namespace")||this.nspace.Name -e!==this.nspace.Name&&(t.nspace=`${e}`)}}const n=(0,l.getOwner)(this),o=this.router.currentRoute.name,a=n.lookup(`route:${o}`) -return n.lookup("route:application").refresh().promise.catch((function(e){})).then((e=>o!==this.router.currentRouteName||void 0!==t.nspace?a.transitionTo(...(0,i.default)(this.router.currentRoute,t,n)):e))}),e.type,(function(e,t){return e}),{})}},c=m(s.prototype,"router",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=m(s.prototype,"store",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=m(s.prototype,"feedback",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m(s.prototype,"reauthorize",[r.action],Object.getOwnPropertyDescriptor(s.prototype,"reauthorize"),s.prototype),s) -e.default=h})),define("consul-ui/controllers/dc/acls/policies/create",["exports","consul-ui/controllers/dc/acls/policies/edit"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{}e.default=n})),define("consul-ui/controllers/dc/acls/policies/edit",["exports","@ember/service","@ember/controller"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,t.inject)("form"),r=class extends n.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="builder",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}init(){super.init(...arguments),this.form=this.builder.form("policy")}setProperties(e){super.setProperties(Object.keys(e).reduce(((e,t,n)=>{if("item"===t)e[t]=this.form.setData(e[t]).getData() -return e}),e))}},a=r.prototype,u="builder",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})) -define("consul-ui/controllers/dc/acls/roles/create",["exports","consul-ui/controllers/dc/acls/roles/edit"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{}e.default=n})),define("consul-ui/controllers/dc/acls/roles/edit",["exports","@ember/service","@ember/controller"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,t.inject)("form"),r=class extends n.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="builder",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}init(){super.init(...arguments),this.form=this.builder.form("role")}setProperties(e){super.setProperties(Object.keys(e).reduce(((e,t,n)=>{if("item"===t)e[t]=this.form.setData(e[t]).getData() -return e}),e))}},a=r.prototype,u="builder",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/controllers/dc/acls/tokens/create",["exports","consul-ui/controllers/dc/acls/tokens/edit"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{}e.default=n})),define("consul-ui/controllers/dc/acls/tokens/edit",["exports","@ember/controller","@ember/service"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l=t.default.extend({dom:(0,n.inject)("dom"),builder:(0,n.inject)("form"),isScoped:!1,init:function(){this._super(...arguments),this.form=this.builder.form("token")},setProperties:function(e){this._super(Object.keys(e).reduce(((e,t,n)=>{if("item"===t)e[t]=this.form.setData(e[t]).getData() -return e}),e))},actions:{change:function(e,t,n){const l=this.dom.normalizeEvent(e,t),r=this.form -try{r.handleEvent(l)}catch(i){throw l.target.name,i}}}}) -e.default=l})),define("consul-ui/controllers/dc/nodes/index",["exports","consul-ui/controllers/_peered-resource"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{}e.default=n})),define("consul-ui/controllers/dc/peers/index",["exports","@ember/controller","@ember/service"],(function(e,t,n){var l,r -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let i=(l=class extends t.default{constructor(){var e,t,n,l,i,o,a -super(...arguments),e=this,t="router",l=this,(n=r)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a=(e,t)=>{null==e||e(),this.router.transitionTo("dc.peers.show",t.Name)},(o="redirectToPeerShow")in(i=this)?Object.defineProperty(i,o,{value:a,enumerable:!0,configurable:!0,writable:!0}):i[o]=a}},o=l.prototype,a="router",u=[n.inject],s={configurable:!0,enumerable:!0,writable:!0,initializer:null},d={},Object.keys(s).forEach((function(e){d[e]=s[e]})),d.enumerable=!!d.enumerable,d.configurable=!!d.configurable,("value"in d||d.initializer)&&(d.writable=!0),d=u.slice().reverse().reduce((function(e,t){return t(o,a,e)||e}),d),c&&void 0!==d.initializer&&(d.value=d.initializer?d.initializer.call(c):void 0,d.initializer=void 0),void 0===d.initializer&&(Object.defineProperty(o,a,d),d=null),r=d,l) -var o,a,u,s,c,d -e.default=i})),define("consul-ui/controllers/dc/peers/show/exported",["exports","@ember/controller","@glimmer/tracking","@ember/object"],(function(e,t,n,l){var r,i -function o(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(r=class extends t.default{constructor(){var e,t,n,l,r,o,a -super(...arguments),n={search:{as:"filter"}},(t="queryParams")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,l=this,r="search",a=this,(o=i)&&Object.defineProperty(l,r,{enumerable:o.enumerable,configurable:o.configurable,writable:o.writable,value:o.initializer?o.initializer.call(a):void 0})}updateSearch(e){this.search=e}},i=o(r.prototype,"search",[n.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return""}}),o(r.prototype,"updateSearch",[l.action],Object.getOwnPropertyDescriptor(r.prototype,"updateSearch"),r.prototype),r) -e.default=a})),define("consul-ui/controllers/dc/peers/show/index",["exports","@ember/controller","@ember/service","@ember/object"],(function(e,t,n,l){var r,i -function o(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="router",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}transitionToImported(){this.router.replaceWith("dc.peers.show.imported")}},i=o(r.prototype,"router",[n.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o(r.prototype,"transitionToImported",[l.action],Object.getOwnPropertyDescriptor(r.prototype,"transitionToImported"),r.prototype),r) -e.default=a})),define("consul-ui/controllers/dc/services/index",["exports","consul-ui/controllers/_peered-resource"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{}e.default=n})),define("consul-ui/controllers/dc/services/instance/healthchecks",["exports","@ember/controller","@ember/object"],(function(e,t,n){var l -function r(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let i=(r((l=class extends t.default{syntheticNodeSearchPropertyFilter(e,t){var n -return!(null!==(n=e.Node.Meta)&&void 0!==n&&n["synthetic-node"]&&"Node"===t)}syntheticNodeHealthCheckFilter(e,t,n,l){var r -return!(null!==(r=e.Node.Meta)&&void 0!==r&&r["synthetic-node"]&&"node"===(null==t?void 0:t.Kind))}}).prototype,"syntheticNodeSearchPropertyFilter",[n.action],Object.getOwnPropertyDescriptor(l.prototype,"syntheticNodeSearchPropertyFilter"),l.prototype),r(l.prototype,"syntheticNodeHealthCheckFilter",[n.action],Object.getOwnPropertyDescriptor(l.prototype,"syntheticNodeHealthCheckFilter"),l.prototype),l) -e.default=i})),define("consul-ui/data-adapter",["exports","@ember-data/debug"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/decorators/data-source",["exports","@ember/debug","wayfarer"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.match=e.default=void 0 -const l=(0,n.default)(),r={} -e.default=e=>(n,i,o)=>((0,t.runInDebug)((()=>{r[e]={cls:n,method:i}})),l.on(e,(function(e,t,l){const r=t.lookup("service:container").get(n) -return t=>o.value.apply(r,[e,t,l])})),o) -e.match=e=>l.match(e),(0,t.runInDebug)((()=>{window.DataSourceRoutes=()=>{const e=window.ConsulUi.__container__.lookup("service:container"),t=window.open("","_blank") -t.document.write(`\n\n
      \n${Object.entries(r).map((t=>{let[n,l]=t,r=e.keyForClass(l.cls).split("/").pop()
      -return r=r.split("-").map((e=>`${e[0].toUpperCase()}${e.substr(1)}`)).join(""),`${n}\n      ${r}Repository.${l.method}(params)\n\n`})).join("")}\n  
      \n\n `),t.focus()}}))})),define("consul-ui/decorators/replace",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.nullValue=e.replace=void 0 -const t=(e,t)=>(n,l,r)=>({get:function(){const n=r.get.apply(this,arguments) -return n===e?t:n},set:function(){return r.set.apply(this,arguments)}}) -e.replace=t -e.nullValue=function(e){return t(null,e)} -var n=t -e.default=n})),define("consul-ui/env",["exports","consul-ui/config/environment","consul-ui/utils/get-environment"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.env=void 0 -const l=(0,n.default)(t.default,window,document) -e.env=l})),define("consul-ui/filter/predicates/auth-method",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={kind:{kubernetes:(e,t)=>e.Type===t,jwt:(e,t)=>e.Type===t,oidc:(e,t)=>e.Type===t},source:{local:(e,t)=>e.TokenLocality===t,global:(e,t)=>e.TokenLocality===t}}})),define("consul-ui/filter/predicates/health-check",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={status:{passing:(e,t)=>e.Status===t,warning:(e,t)=>e.Status===t,critical:(e,t)=>e.Status===t},kind:{service:(e,t)=>e.Kind===t,node:(e,t)=>e.Kind===t},check:{serf:(e,t)=>e.Type===t,script:(e,t)=>e.Type===t,http:(e,t)=>e.Type===t,tcp:(e,t)=>e.Type===t,ttl:(e,t)=>e.Type===t,docker:(e,t)=>e.Type===t,grpc:(e,t)=>e.Type===t,alias:(e,t)=>e.Type===t}}})),define("consul-ui/filter/predicates/intention",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={access:{allow:(e,t)=>e.Action===t,deny:(e,t)=>e.Action===t,"app-aware":(e,t)=>void 0===e.Action}}})),define("consul-ui/filter/predicates/kv",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={kind:{folder:(e,t)=>e.isFolder,key:(e,t)=>!e.isFolder}}})),define("consul-ui/filter/predicates/node",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={status:{passing:(e,t)=>e.Status===t,warning:(e,t)=>e.Status===t,critical:(e,t)=>e.Status===t}}})),define("consul-ui/filter/predicates/peer",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={state:{pending:(e,t)=>e.State.toLowerCase()===t,establishing:(e,t)=>e.State.toLowerCase()===t,active:(e,t)=>e.State.toLowerCase()===t,failing:(e,t)=>e.State.toLowerCase()===t,terminated:(e,t)=>e.State.toLowerCase()===t,deleting:(e,t)=>e.State.toLowerCase()===t}}})),define("consul-ui/filter/predicates/policy",["exports","mnemonist/set"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n={kind:{"global-management":(e,t)=>e.isGlobalManagement,standard:(e,t)=>!e.isGlobalManagement},datacenter:(e,n)=>void 0===e.Datacenters||t.default.intersectionSize(n,new Set(e.Datacenters))>0} -e.default=n})),define("consul-ui/filter/predicates/service-instance",["exports","mnemonist/set"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n={status:{passing:(e,t)=>e.Status===t,warning:(e,t)=>e.Status===t,critical:(e,t)=>e.Status===t,empty:(e,t)=>0===e.ServiceChecks.length},source:(e,n)=>0!==t.default.intersectionSize(n,new Set(e.ExternalSources||[]))} -e.default=n})),define("consul-ui/filter/predicates/service",["exports","mnemonist/set"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n={kind:{"api-gateway":(e,t)=>e.Kind===t,"ingress-gateway":(e,t)=>e.Kind===t,"terminating-gateway":(e,t)=>e.Kind===t,"mesh-gateway":(e,t)=>e.Kind===t,service:(e,t)=>!e.Kind,"in-mesh":(e,t)=>e.InMesh,"not-in-mesh":(e,t)=>!e.InMesh},status:{passing:(e,t)=>e.MeshStatus===t,warning:(e,t)=>e.MeshStatus===t,critical:(e,t)=>e.MeshStatus===t,empty:(e,t)=>0===e.MeshChecksTotal,unknown:e=>e.peerIsFailing||e.isZeroCountButPeered},instance:{registered:(e,t)=>e.InstanceCount>0,"not-registered":(e,t)=>0===e.InstanceCount},source:(e,n)=>{let l=!1 -return n.includes("consul")&&(l=!e.ExternalSources||0===e.ExternalSources.length||1===e.ExternalSources.length&&""===e.ExternalSources[0]||e.PeerName),0!==t.default.intersectionSize(n,new Set(e.ExternalSources||[]))||n.includes(e.Partition)||l}} -e.default=n})),define("consul-ui/filter/predicates/token",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={kind:{"global-management":(e,t)=>e.isGlobalManagement,global:(e,t)=>!e.Local,local:(e,t)=>e.Local}}})),define("consul-ui/flash/object",["exports","ember-cli-flash/flash/object"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/formats",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={time:{hhmmss:{hour:"numeric",minute:"numeric",second:"numeric"}},date:{hhmmss:{hour:"numeric",minute:"numeric",second:"numeric"}},number:{compact:{notation:"compact"},EUR:{style:"currency",currency:"EUR",minimumFractionDigits:2,maximumFractionDigits:2},USD:{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}}}})),define("consul-ui/forms/intention",["exports","consul-ui/validations/intention","consul-ui/utils/form/builder"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.default,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:l -return i(n,{}).setValidators(r)} -const l=(0,n.default)()})),define("consul-ui/forms/kv",["exports","consul-ui/validations/kv","consul-ui/utils/form/builder"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.default,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:l -return i(n,{}).setValidators(r)} -const l=(0,n.default)()})),define("consul-ui/forms/policy",["exports","consul-ui/validations/policy","consul-ui/utils/form/builder"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"policy",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.default,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:l -return i(n,{Datacenters:{type:"array"}}).setValidators(r)} -const l=(0,n.default)()})),define("consul-ui/forms/role",["exports","consul-ui/validations/role","consul-ui/utils/form/builder"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"role",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.default,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:l -return i(n,{}).setValidators(r).add(e.form("policy"))} -const l=(0,n.default)()})) -define("consul-ui/forms/token",["exports","consul-ui/validations/token","consul-ui/utils/form/builder"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.default,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:l -return i(n,{}).setValidators(r).add(e.form("policy")).add(e.form("role"))} -const l=(0,n.default)()})),define("consul-ui/helpers/-element",["exports","ember-element-helper/helpers/-element"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/abs",["exports","ember-math-helpers/helpers/abs"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"abs",{enumerable:!0,get:function(){return t.abs}})})),define("consul-ui/helpers/acos",["exports","ember-math-helpers/helpers/acos"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"acos",{enumerable:!0,get:function(){return t.acos}})})),define("consul-ui/helpers/acosh",["exports","ember-math-helpers/helpers/acosh"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"acosh",{enumerable:!0,get:function(){return t.acosh}})})),define("consul-ui/helpers/add",["exports","ember-math-helpers/helpers/add"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"add",{enumerable:!0,get:function(){return t.add}})})),define("consul-ui/helpers/adopt-styles",["exports","@ember/component/helper","@ember/debug","@lit/reactive-element"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class r extends t.default{compute(e,t){let[n,r]=e -Array.isArray(r)||(r=[r]),(0,l.adoptStyles)(n,r)}}e.default=r})),define("consul-ui/helpers/and",["exports","ember-truth-helpers/helpers/and"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"and",{enumerable:!0,get:function(){return t.and}})})),define("consul-ui/helpers/app-version",["exports","@ember/component/helper","consul-ui/config/environment","ember-cli-app-version/utils/regexp"],(function(e,t,n,l){function r(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -const r=n.default.APP.version -let i=t.versionOnly||t.hideSha,o=t.shaOnly||t.hideVersion,a=null -return i&&(t.showExtended&&(a=r.match(l.versionExtendedRegExp)),a||(a=r.match(l.versionRegExp))),o&&(a=r.match(l.shaRegExp)),a?a[0]:r}Object.defineProperty(e,"__esModule",{value:!0}),e.appVersion=r,e.default=void 0 -var i=(0,t.helper)(r) -e.default=i})),define("consul-ui/helpers/append",["exports","ember-composable-helpers/helpers/append"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"append",{enumerable:!0,get:function(){return t.append}})})),define("consul-ui/helpers/array-concat",["exports","ember-array-fns/helpers/array-concat"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayConcat",{enumerable:!0,get:function(){return t.arrayConcat}})})),define("consul-ui/helpers/array-every",["exports","ember-array-fns/helpers/array-every"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayEvery",{enumerable:!0,get:function(){return t.arrayEvery}})})),define("consul-ui/helpers/array-filter",["exports","ember-array-fns/helpers/array-filter"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayFilter",{enumerable:!0,get:function(){return t.arrayFilter}})})),define("consul-ui/helpers/array-find-index",["exports","ember-array-fns/helpers/array-find-index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayFindIndex",{enumerable:!0,get:function(){return t.arrayFindIndex}})})),define("consul-ui/helpers/array-find",["exports","ember-array-fns/helpers/array-find"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayFind",{enumerable:!0,get:function(){return t.arrayFind}})})),define("consul-ui/helpers/array-includes",["exports","ember-array-fns/helpers/array-includes"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayIncludes",{enumerable:!0,get:function(){return t.arrayIncludes}})})),define("consul-ui/helpers/array-index-of",["exports","ember-array-fns/helpers/array-index-of"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayIndexOf",{enumerable:!0,get:function(){return t.arrayIndexOf}})})),define("consul-ui/helpers/array-is-array",["exports","ember-array-fns/helpers/array-is-array"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayIsArray",{enumerable:!0,get:function(){return t.arrayIsArray}})})),define("consul-ui/helpers/array-is-first-element",["exports","ember-array-fns/helpers/array-is-first-element"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayIsFirstElement",{enumerable:!0,get:function(){return t.arrayIsFirstElement}})})),define("consul-ui/helpers/array-is-last-element",["exports","ember-array-fns/helpers/array-is-last-element"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayIsLastElement",{enumerable:!0,get:function(){return t.arrayIsLastElement}})})),define("consul-ui/helpers/array-join",["exports","ember-array-fns/helpers/array-join"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayJoin",{enumerable:!0,get:function(){return t.arrayJoin}})})),define("consul-ui/helpers/array-last-index-of",["exports","ember-array-fns/helpers/array-last-index-of"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayLastIndexOf",{enumerable:!0,get:function(){return t.arrayLastIndexOf}})})),define("consul-ui/helpers/array-map",["exports","ember-array-fns/helpers/array-map"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayMap",{enumerable:!0,get:function(){return t.arrayMap}})})),define("consul-ui/helpers/array-reduce",["exports","ember-array-fns/helpers/array-reduce"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayReduce",{enumerable:!0,get:function(){return t.arrayReduce}})})),define("consul-ui/helpers/array-reverse",["exports","ember-array-fns/helpers/array-reverse"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arrayReverse",{enumerable:!0,get:function(){return t.arrayReverse}})})),define("consul-ui/helpers/array-slice",["exports","ember-array-fns/helpers/array-slice"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arraySlice",{enumerable:!0,get:function(){return t.arraySlice}})})),define("consul-ui/helpers/array-some",["exports","ember-array-fns/helpers/array-some"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arraySome",{enumerable:!0,get:function(){return t.arraySome}})})),define("consul-ui/helpers/array-sort",["exports","ember-array-fns/helpers/array-sort"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arraySort",{enumerable:!0,get:function(){return t.arraySort}})})),define("consul-ui/helpers/array-splice",["exports","ember-array-fns/helpers/array-splice"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"arraySplice",{enumerable:!0,get:function(){return t.arraySplice}})})),define("consul-ui/helpers/asin",["exports","ember-math-helpers/helpers/asin"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"asin",{enumerable:!0,get:function(){return t.asin}})})) -define("consul-ui/helpers/asinh",["exports","ember-math-helpers/helpers/asinh"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"asinh",{enumerable:!0,get:function(){return t.asinh}})})),define("consul-ui/helpers/assign",["exports","ember-assign-helper/helpers/assign"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"assign",{enumerable:!0,get:function(){return t.assign}})})),define("consul-ui/helpers/atan",["exports","ember-math-helpers/helpers/atan"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"atan",{enumerable:!0,get:function(){return t.atan}})})),define("consul-ui/helpers/atan2",["exports","ember-math-helpers/helpers/atan2"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"atan2",{enumerable:!0,get:function(){return t.atan2}})})),define("consul-ui/helpers/atanh",["exports","ember-math-helpers/helpers/atanh"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"atanh",{enumerable:!0,get:function(){return t.atanh}})})),define("consul-ui/helpers/atob",["exports","@ember/component/helper","consul-ui/utils/atob"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l=(0,t.helper)((function(e){let[t=""]=e -return(0,n.default)(t)})) -e.default=l})),define("consul-ui/helpers/block-params",["exports","block-slots/helpers/block-params"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/cached-model",["exports","@ember/component/helper","@ember/application"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{compute(e,t){let[l,r]=e -return(0,n.getOwner)(this).lookup(`service:repository/${l}`).cached(r)}}e.default=l})),define("consul-ui/helpers/call",["exports","ember-composable-helpers/helpers/call"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"call",{enumerable:!0,get:function(){return t.call}})})),define("consul-ui/helpers/can",["exports","ember-can/helpers/can"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/cancel-all",["exports","ember-concurrency/helpers/cancel-all"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/cannot",["exports","ember-can/helpers/cannot"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/capitalize",["exports","ember-cli-string-helpers/helpers/capitalize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"capitalize",{enumerable:!0,get:function(){return t.capitalize}})})),define("consul-ui/helpers/cbrt",["exports","ember-math-helpers/helpers/cbrt"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"cbrt",{enumerable:!0,get:function(){return t.cbrt}})})),define("consul-ui/helpers/ceil",["exports","ember-math-helpers/helpers/ceil"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"ceil",{enumerable:!0,get:function(){return t.ceil}})})),define("consul-ui/helpers/changeset-get",["exports","ember-changeset/helpers/changeset-get"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/changeset-set",["exports","ember-changeset/helpers/changeset-set"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"changesetSet",{enumerable:!0,get:function(){return t.changesetSet}})})),define("consul-ui/helpers/changeset",["exports","ember-changeset-validations/helpers/changeset"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"changeset",{enumerable:!0,get:function(){return t.changeset}})})),define("consul-ui/helpers/chunk",["exports","ember-composable-helpers/helpers/chunk"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"chunk",{enumerable:!0,get:function(){return t.chunk}})})),define("consul-ui/helpers/class-map",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.helper)((e=>{const t=e.filter(Boolean).filter((e=>"string"==typeof e||e[e.length-1])).map((e=>"string"==typeof e?e:e[0])).join(" ") -return t.length>0?t:void 0})) -e.default=n})),define("consul-ui/helpers/classify",["exports","ember-cli-string-helpers/helpers/classify"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"classify",{enumerable:!0,get:function(){return t.classify}})})),define("consul-ui/helpers/clz32",["exports","ember-math-helpers/helpers/clz32"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"clz32",{enumerable:!0,get:function(){return t.clz32}})})),define("consul-ui/helpers/collection",["exports","@ember/component/helper","@ember/object","consul-ui/models/service","consul-ui/models/service-instance"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i={service:l.Collection,"service-instance":r.Collection} -class o{}class a extends t.default{compute(e,t){let[l,r]=e -if(l.length>0){const e=(0,n.get)(l,"firstObject")._internalModel.modelName -return new(0,i[e])(l)}return new o}}e.default=a})),define("consul-ui/helpers/compact",["exports","ember-composable-helpers/helpers/compact"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/compute",["exports","ember-composable-helpers/helpers/compute"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"compute",{enumerable:!0,get:function(){return t.compute}})})),define("consul-ui/helpers/contains",["exports","ember-composable-helpers/helpers/contains"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"contains",{enumerable:!0,get:function(){return t.contains}})})),define("consul-ui/helpers/cos",["exports","ember-math-helpers/helpers/cos"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"cos",{enumerable:!0,get:function(){return t.cos}})})),define("consul-ui/helpers/cosh",["exports","ember-math-helpers/helpers/cosh"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"cosh",{enumerable:!0,get:function(){return t.cosh}})})),define("consul-ui/helpers/css-map",["exports","@ember/component/helper","@lit/reactive-element"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l=(0,t.helper)((e=>e.filter((e=>e instanceof n.CSSResult||e[e.length-1])).map((e=>e instanceof n.CSSResult?e:e[0])))) -e.default=l})),define("consul-ui/helpers/css",["exports","@ember/component/helper","@lit/reactive-element"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{compute(e,t){let[l]=e -return(0,n.css)([l])}}e.default=l})) -define("consul-ui/helpers/dec",["exports","ember-composable-helpers/helpers/dec"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"dec",{enumerable:!0,get:function(){return t.dec}})})),define("consul-ui/helpers/did-insert",["exports","ember-render-helpers/helpers/did-insert"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/did-update",["exports","ember-render-helpers/helpers/did-update"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/div",["exports","ember-math-helpers/helpers/div"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"div",{enumerable:!0,get:function(){return t.div}})})),define("consul-ui/helpers/document-attrs",["exports","@ember/component/helper","@ember/service","@ember/debug","mnemonist/multi-map"],(function(e,t,n,l,r){var i,o,a -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const u=new Map,s=new WeakMap -let c=(i=(0,n.inject)("-document"),o=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="document",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){this.synchronize(this.document.documentElement,t)}willDestroy(){this.synchronize(this.document.documentElement),s.delete(this)}synchronize(e,t){const n=s.get(this) -return n&&Object.entries(n).forEach((e=>{let[t,n]=e,l=u.get(t) -void 0!==l&&[...new Set(n.split(" "))].map((e=>l.remove(e,this)))})),t&&(s.set(this,t),[...Object.entries(t)].forEach((e=>{let[t,n]=e,l=u.get(t) -void 0===l&&(l=new r.default(Set),u.set(t,l)),[...new Set(n.split(" "))].map((e=>{0===l.count(e)&&l.set(e,null),l.set(e,this)}))}))),[...u.entries()].forEach((t=>{let[n,r]=t,i="attr" -"class"===n?i=n:n.startsWith("data-")&&(i="data"),[...r.keys()].forEach((t=>{if(1===r.count(t)){if("class"===i)e.classList.remove(t) -else(0,l.runInDebug)((()=>{throw new Error(`${i} is not implemented yet`)})) -r.delete(t),0===r.size&&u.delete(n)}else if("class"===i)e.classList.add(t) -else(0,l.runInDebug)((()=>{throw new Error(`${i} is not implemented yet`)}))}))})),u}},d=o.prototype,p="document",f=[i],m={configurable:!0,enumerable:!0,writable:!0,initializer:null},b={},Object.keys(m).forEach((function(e){b[e]=m[e]})),b.enumerable=!!b.enumerable,b.configurable=!!b.configurable,("value"in b||b.initializer)&&(b.writable=!0),b=f.slice().reverse().reduce((function(e,t){return t(d,p,e)||e}),b),h&&void 0!==b.initializer&&(b.value=b.initializer?b.initializer.call(h):void 0,b.initializer=void 0),void 0===b.initializer&&(Object.defineProperty(d,p,b),b=null),a=b,o) -var d,p,f,m,h,b -e.default=c})),define("consul-ui/helpers/dom-position",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{compute(e,t){let[n]=e,{from:l,offset:r=!1}=t -return e=>{if("function"==typeof n){let t,i -if(r)i=e.currentTarget,t={width:i.offsetWidth,left:i.offsetLeft,height:i.offsetHeight,top:i.offsetTop} -else if(i=e.target,t=i.getBoundingClientRect(),void 0!==l){const e=l.getBoundingClientRect() -t.x=t.x-e.x,t.y=t.y-e.y}return n(t)}{const t=e.target,l=t.getBoundingClientRect() -n.forEach((e=>{let[n,r]=e -t.style[r]=`${l[n]}px`}))}}}}e.default=n})),define("consul-ui/helpers/drop",["exports","ember-composable-helpers/helpers/drop"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/duration-from",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,n.inject)("temporal"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="temporal",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){let[n]=e -return this.temporal.durationFrom(n)}},a=r.prototype,u="temporal",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/helpers/element",["exports","ember-element-helper/helpers/element"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/ember-power-select-is-group",["exports","ember-power-select/helpers/ember-power-select-is-group"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"emberPowerSelectIsGroup",{enumerable:!0,get:function(){return t.emberPowerSelectIsGroup}})})),define("consul-ui/helpers/ember-power-select-is-selected",["exports","ember-power-select/helpers/ember-power-select-is-selected"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"emberPowerSelectIsSelected",{enumerable:!0,get:function(){return t.emberPowerSelectIsSelected}})})),define("consul-ui/helpers/ensure-safe-component",["exports","@embroider/util"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.EnsureSafeComponentHelper}})})),define("consul-ui/helpers/entries",["exports","ember-composable-helpers/helpers/entries"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"entries",{enumerable:!0,get:function(){return t.entries}})})),define("consul-ui/helpers/env",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){let[n,l=""]=e -const r=this.env.var(n) -return null!=r?r:l}},a=r.prototype,u="env",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/helpers/eq",["exports","ember-truth-helpers/helpers/equal"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"equal",{enumerable:!0,get:function(){return t.equal}})})),define("consul-ui/helpers/exp",["exports","ember-math-helpers/helpers/exp"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"exp",{enumerable:!0,get:function(){return t.exp}})})),define("consul-ui/helpers/expm1",["exports","ember-math-helpers/helpers/expm1"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"expm1",{enumerable:!0,get:function(){return t.expm1}})})),define("consul-ui/helpers/filter-by",["exports","ember-composable-helpers/helpers/filter-by"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/filter",["exports","ember-composable-helpers/helpers/filter"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/find-by",["exports","ember-composable-helpers/helpers/find-by"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/fixed-grid-layout",["exports","@ember/component/helper","ember-collection/layouts/grid"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l=(0,t.helper)((function(e){return new n.default(e[0],e[1])})) -e.default=l})),define("consul-ui/helpers/flatten-property",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.helper)((function e(t,n){let[l,r]=t -const i=n.pages||[] -return i.push(...l.pages),l.children.forEach((t=>e([t],{pages:i}))),i})) -e.default=n})),define("consul-ui/helpers/flatten",["exports","ember-composable-helpers/helpers/flatten"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"flatten",{enumerable:!0,get:function(){return t.flatten}})})),define("consul-ui/helpers/floor",["exports","ember-math-helpers/helpers/floor"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"floor",{enumerable:!0,get:function(){return t.floor}})})),define("consul-ui/helpers/format-date",["exports","ember-intl/helpers/format-date"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/format-message",["exports","ember-intl/helpers/format-message"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/format-number",["exports","ember-intl/helpers/format-number"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/format-relative",["exports","ember-intl/helpers/format-relative"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/format-short-time",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.helper)((function(e,t){let n,l,r,i,[o]=e -i=Math.floor(o/1e3),r=Math.floor(i/60),i%=60,l=Math.floor(r/60),r%=60,n=Math.floor(l/24),l%=24 -const a=n,u=l,s=r,c=i -switch(!0){case 0!==a:return a+"d" -case 0!==u:return u+"h" -case 0!==s:return s+"m" -default:return c+"s"}})) -e.default=n})),define("consul-ui/helpers/format-time",["exports","ember-intl/helpers/format-time"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) -define("consul-ui/helpers/from-entries",["exports","ember-composable-helpers/helpers/from-entries"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"fromEntries",{enumerable:!0,get:function(){return t.fromEntries}})})),define("consul-ui/helpers/fround",["exports","ember-math-helpers/helpers/fround"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"fround",{enumerable:!0,get:function(){return t.fround}})})),define("consul-ui/helpers/gcd",["exports","ember-math-helpers/helpers/gcd"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"gcd",{enumerable:!0,get:function(){return t.gcd}})})),define("consul-ui/helpers/group-by",["exports","ember-composable-helpers/helpers/group-by"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/gt",["exports","ember-truth-helpers/helpers/gt"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"gt",{enumerable:!0,get:function(){return t.gt}})})),define("consul-ui/helpers/gte",["exports","ember-truth-helpers/helpers/gte"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"gte",{enumerable:!0,get:function(){return t.gte}})})),define("consul-ui/helpers/has-next",["exports","ember-composable-helpers/helpers/has-next"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"hasNext",{enumerable:!0,get:function(){return t.hasNext}})})),define("consul-ui/helpers/has-previous",["exports","ember-composable-helpers/helpers/has-previous"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"hasPrevious",{enumerable:!0,get:function(){return t.hasPrevious}})})),define("consul-ui/helpers/hds-link-to-models",["exports","@hashicorp/design-system-components/helpers/hds-link-to-models"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/hds-link-to-query",["exports","@hashicorp/design-system-components/helpers/hds-link-to-query"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/href-to",["exports","@ember/component/helper","@ember/service","@ember/object","@ember/application","consul-ui/utils/routing/transitionable","consul-ui/utils/routing/wildcard","consul-ui/router"],(function(e,t,n,l,r,i,o,a){var u,s,c -function d(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.hrefTo=void 0 -const p=(0,o.default)(a.routes),f=function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{} -const l=e.lookup("router:main").location,r=e.lookup("service:router") -let o=t.slice(0),a=o.shift(),u=n.params||{} -"."===a&&(o=(0,i.default)(r.currentRoute,u,e),a=o.shift()) -try{return p(a)&&(o=o.map(((e,t)=>e.split("/").map(encodeURIComponent).join("/")))),l.hrefTo(a,o,u)}catch(s){throw s.constructor===Error&&(s.message=`${s.message} For "${t[0]}:${JSON.stringify(t.slice(1))}"`),s}} -e.hrefTo=f -let m=(u=(0,n.inject)("router"),s=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="router",l=this,(n=c)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}init(){super.init(...arguments),this.router.on("routeWillChange",this.routeWillChange)}compute(e,t){return f((0,r.getOwner)(this),e,t)}routeWillChange(e){this.recompute()}willDestroy(){this.router.off("routeWillChange",this.routeWillChange),super.willDestroy()}},c=d(s.prototype,"router",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d(s.prototype,"routeWillChange",[l.action],Object.getOwnPropertyDescriptor(s.prototype,"routeWillChange"),s.prototype),s) -e.default=m})),define("consul-ui/helpers/humanize",["exports","ember-cli-string-helpers/helpers/humanize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"humanize",{enumerable:!0,get:function(){return t.humanize}})})),define("consul-ui/helpers/hypot",["exports","ember-math-helpers/helpers/hypot"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"hypot",{enumerable:!0,get:function(){return t.hypot}})})),define("consul-ui/helpers/icon-mapping",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const n={kubernetes:"kubernetes-color",terraform:"terraform-color",nomad:"nomad-color",consul:"consul-color","consul-api-gateway":"consul-color",vault:"vault",aws:"aws-color","aws-iam":"aws-color",lambda:"aws-lambda-color"} -var l=(0,t.helper)((function(e){let[t]=e -return n[t]})) -e.default=l})),define("consul-ui/helpers/if-key",["exports","ember-keyboard/helpers/if-key.js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/imul",["exports","ember-math-helpers/helpers/imul"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"imul",{enumerable:!0,get:function(){return t.imul}})})),define("consul-ui/helpers/inc",["exports","ember-composable-helpers/helpers/inc"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"inc",{enumerable:!0,get:function(){return t.inc}})})),define("consul-ui/helpers/includes",["exports","ember-composable-helpers/helpers/includes"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"includes",{enumerable:!0,get:function(){return t.includes}})})),define("consul-ui/helpers/intersect",["exports","ember-composable-helpers/helpers/intersect"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/invoke",["exports","ember-composable-helpers/helpers/invoke"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"invoke",{enumerable:!0,get:function(){return t.invoke}})})),define("consul-ui/helpers/is-active",["exports","ember-router-helpers/helpers/is-active"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"isActive",{enumerable:!0,get:function(){return t.isActive}})})),define("consul-ui/helpers/is-array",["exports","ember-truth-helpers/helpers/is-array"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"isArray",{enumerable:!0,get:function(){return t.isArray}})})),define("consul-ui/helpers/is-empty",["exports","ember-truth-helpers/helpers/is-empty"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/is-equal",["exports","ember-truth-helpers/helpers/is-equal"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"isEqual",{enumerable:!0,get:function(){return t.isEqual}})})),define("consul-ui/helpers/is-href",["exports","@ember/component/helper","@ember/service","@ember/object"],(function(e,t,n,l){var r,i,o -function a(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let u=(r=(0,n.inject)("router"),i=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="router",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}init(){super.init(...arguments),this.router.on("routeWillChange",this.routeWillChange)}compute(e){let[t,...n]=e -return this.router.currentRouteName.startsWith("nspace.")&&t.startsWith("dc.")&&(t=`nspace.${t}`),void 0!==this.next&&"loading"!==this.next?this.next.startsWith(t):this.router.isActive(t,...n)}routeWillChange(e){this.next=e.to.name.replace(".index",""),this.recompute()}willDestroy(){this.router.off("routeWillChange",this.routeWillChange),super.willDestroy()}},o=a(i.prototype,"router",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a(i.prototype,"routeWillChange",[l.action],Object.getOwnPropertyDescriptor(i.prototype,"routeWillChange"),i.prototype),i) -e.default=u})),define("consul-ui/helpers/is",["exports","ember-can/helpers/can","@ember/object","@ember/string"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.is=void 0 -const r=(e,t,r)=>{let[i,o]=t,{abilityName:a,propertyName:u}=e.abilities.parse(i),s=e.abilities.abilityFor(a,o,r) -return u="function"==typeof s.getCharacteristicProperty?s.getCharacteristicProperty(u):(0,l.camelize)(`is-${u}`),(0,n.get)(s,u)} -e.is=r -class i extends t.default{compute(e,t){let[n,l]=e -return r(this,[n,l],t)}}e.default=i})),define("consul-ui/helpers/join",["exports","ember-composable-helpers/helpers/join"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/json-stringify",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.helper)((function(e,t){try{return JSON.stringify(...e)}catch(n){return e[0].map((t=>JSON.stringify(t,e[1],e[2])))}})) -e.default=n})),define("consul-ui/helpers/keys",["exports","ember-composable-helpers/helpers/keys"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"keys",{enumerable:!0,get:function(){return t.keys}})})),define("consul-ui/helpers/last",["exports","@ember/component/helper"],(function(e,t){function n(e,t){let[n=""]=e -if(!0==("string"==typeof n))return n.substr(-1)}Object.defineProperty(e,"__esModule",{value:!0}),e.last=n,e.default=void 0 -var l=(0,t.helper)(n) -e.default=l})) -define("consul-ui/helpers/lcm",["exports","ember-math-helpers/helpers/lcm"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"lcm",{enumerable:!0,get:function(){return t.lcm}})})),define("consul-ui/helpers/left-trim",["exports","@ember/component/helper","consul-ui/utils/left-trim"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l=(0,t.helper)((function(e,t){let[l="",r=""]=e -return(0,n.default)(l,r)})) -e.default=l})),define("consul-ui/helpers/loc",["exports","@ember/string/helpers/loc"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"loc",{enumerable:!0,get:function(){return t.loc}})})),define("consul-ui/helpers/log-e",["exports","ember-math-helpers/helpers/log-e"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"logE",{enumerable:!0,get:function(){return t.logE}})})),define("consul-ui/helpers/log10",["exports","ember-math-helpers/helpers/log10"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"log10",{enumerable:!0,get:function(){return t.log10}})})),define("consul-ui/helpers/log1p",["exports","ember-math-helpers/helpers/log1p"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"log1p",{enumerable:!0,get:function(){return t.log1p}})})),define("consul-ui/helpers/log2",["exports","ember-math-helpers/helpers/log2"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"log2",{enumerable:!0,get:function(){return t.log2}})})),define("consul-ui/helpers/lowercase",["exports","ember-cli-string-helpers/helpers/lowercase"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"lowercase",{enumerable:!0,get:function(){return t.lowercase}})})),define("consul-ui/helpers/lt",["exports","ember-truth-helpers/helpers/lt"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"lt",{enumerable:!0,get:function(){return t.lt}})})),define("consul-ui/helpers/lte",["exports","ember-truth-helpers/helpers/lte"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"lte",{enumerable:!0,get:function(){return t.lte}})})),define("consul-ui/helpers/map-by",["exports","ember-composable-helpers/helpers/map-by"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/map",["exports","ember-composable-helpers/helpers/map"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/max",["exports","ember-math-helpers/helpers/max"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"max",{enumerable:!0,get:function(){return t.max}})})),define("consul-ui/helpers/merge-checks",["exports","@ember/component/helper","consul-ui/utils/merge-checks"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l=(0,t.helper)((function(e,t){let[l,r]=e -return(0,n.default)(l,r)})) -e.default=l})),define("consul-ui/helpers/min",["exports","ember-math-helpers/helpers/min"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"min",{enumerable:!0,get:function(){return t.min}})})),define("consul-ui/helpers/mixed-grid-layout",["exports","@ember/component/helper","ember-collection/layouts/mixed-grid"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l=(0,t.helper)((function(e){return new n.default(e[0])})) -e.default=l})),define("consul-ui/helpers/mod",["exports","ember-math-helpers/helpers/mod"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"mod",{enumerable:!0,get:function(){return t.mod}})})),define("consul-ui/helpers/mult",["exports","ember-math-helpers/helpers/mult"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"mult",{enumerable:!0,get:function(){return t.mult}})})),define("consul-ui/helpers/next",["exports","ember-composable-helpers/helpers/next"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"next",{enumerable:!0,get:function(){return t.next}})})),define("consul-ui/helpers/noop",["exports","ember-composable-helpers/helpers/noop"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"noop",{enumerable:!0,get:function(){return t.noop}})})),define("consul-ui/helpers/not-eq",["exports","ember-truth-helpers/helpers/not-equal"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"notEqualHelper",{enumerable:!0,get:function(){return t.notEqualHelper}})})),define("consul-ui/helpers/not",["exports","ember-truth-helpers/helpers/not"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"not",{enumerable:!0,get:function(){return t.not}})})),define("consul-ui/helpers/object-at",["exports","ember-composable-helpers/helpers/object-at"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"objectAt",{enumerable:!0,get:function(){return t.objectAt}})})),define("consul-ui/helpers/on-document",["exports","ember-on-helper/helpers/on-document"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/on-key",["exports","ember-keyboard/helpers/on-key.js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/on-window",["exports","ember-on-helper/helpers/on-window"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/on",["exports","ember-on-helper/helpers/on"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/optional",["exports","ember-composable-helpers/helpers/optional"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"optional",{enumerable:!0,get:function(){return t.optional}})})),define("consul-ui/helpers/or",["exports","ember-truth-helpers/helpers/or"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"or",{enumerable:!0,get:function(){return t.or}})})),define("consul-ui/helpers/page-title",["exports","ember-page-title/helpers/page-title"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=t.default -e.default=n})) -define("consul-ui/helpers/percentage-columns-layout",["exports","@ember/component/helper","ember-collection/layouts/percentage-columns"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l=(0,t.helper)((function(e){return new n.default(e[0],e[1],e[2])})) -e.default=l})),define("consul-ui/helpers/percentage-of",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.helper)((function(e,t){let[n,l]=e -const r=n/l*100 -return isNaN(r)?0:r.toFixed(2)})) -e.default=n})),define("consul-ui/helpers/perform",["exports","ember-concurrency/helpers/perform"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/pick",["exports","ember-composable-helpers/helpers/pick"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"pick",{enumerable:!0,get:function(){return t.pick}})})),define("consul-ui/helpers/pipe-action",["exports","ember-composable-helpers/helpers/pipe-action"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/pipe",["exports","ember-composable-helpers/helpers/pipe"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"pipe",{enumerable:!0,get:function(){return t.pipe}})})),define("consul-ui/helpers/pluralize",["exports","ember-inflector/lib/helpers/pluralize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=t.default -e.default=n})),define("consul-ui/helpers/policy/datacenters",["exports","@ember/component/helper","@ember/object"],(function(e,t,n){function l(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -const l=(0,n.get)(e[0],"Datacenters") -return Array.isArray(l)&&0!==l.length?(0,n.get)(e[0],"Datacenters"):[t.global||"All"]}Object.defineProperty(e,"__esModule",{value:!0}),e.datacenters=l,e.default=void 0 -var r=(0,t.helper)(l) -e.default=r})),define("consul-ui/helpers/policy/group",["exports","@ember/component/helper","@ember/object","consul-ui/models/policy"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var r=(0,t.helper)((function(e){let[t]=e -return t.reduce((function(e,t){let r -switch(!0){case(0,n.get)(t,"ID")===l.MANAGEMENT_ID:r="management" -break -case""!==(0,n.get)(t,"template"):r="identities" -break -default:r="policies"}return e[r].push(t),e}),{management:[],identities:[],policies:[]})})) -e.default=r})),define("consul-ui/helpers/policy/typeof",["exports","@ember/component/helper","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.typeOf=l,e.default=void 0 -function l(e,t){const l=e[0],r=(0,n.get)(l,"template") -switch(!0){case void 0===r:return"role" -case"service-identity"===r:return"policy-service-identity" -case"node-identity"===r:return"policy-node-identity" -case"00000000-0000-0000-0000-000000000001"===(0,n.get)(l,"ID"):return"policy-management" -default:return"policy"}}var r=(0,t.helper)(l) -e.default=r})),define("consul-ui/helpers/pow",["exports","ember-math-helpers/helpers/pow"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"pow",{enumerable:!0,get:function(){return t.pow}})})),define("consul-ui/helpers/previous",["exports","ember-composable-helpers/helpers/previous"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"previous",{enumerable:!0,get:function(){return t.previous}})})),define("consul-ui/helpers/queue",["exports","ember-composable-helpers/helpers/queue"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"queue",{enumerable:!0,get:function(){return t.queue}})})),define("consul-ui/helpers/random",["exports","ember-math-helpers/helpers/random"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"random",{enumerable:!0,get:function(){return t.random}})})),define("consul-ui/helpers/range",["exports","ember-composable-helpers/helpers/range"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"range",{enumerable:!0,get:function(){return t.range}})})),define("consul-ui/helpers/reduce",["exports","ember-composable-helpers/helpers/reduce"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/ref-to",["exports","ember-ref-bucket/helpers/ref-to"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"refTo",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/refresh-route",["exports","@ember/component/helper","@ember/service","@ember/application"],(function(e,t,n,l){var r,i,o -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(r=(0,n.inject)("router"),i=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="router",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){return()=>{const e=(0,l.getOwner)(this),t=this.router.currentRoute.name -return e.lookup(`route:${t}`).refresh()}}},u=i.prototype,s="router",c=[r],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),o=f,i) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/helpers/reject-by",["exports","ember-composable-helpers/helpers/reject-by"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/render-template",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=/{{([A-Za-z.0-9_-]+)}}/g -let a,u=(l=(0,n.inject)("encoder"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="encoder",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),"function"!=typeof a&&(a=this.encoder.createRegExpEncoder(o,encodeURIComponent,!1))}compute(e){let[t,n]=e -return a(t,n)}},s=r.prototype,c="encoder",d=[l],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),i=m,r) -var s,c,d,p,f,m -e.default=u})),define("consul-ui/helpers/repeat",["exports","ember-composable-helpers/helpers/repeat"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"repeat",{enumerable:!0,get:function(){return t.repeat}})})),define("consul-ui/helpers/require",["exports","@ember/component/helper","require","@lit/reactive-element","consul-ui/utils/path/resolve"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i=new Map -var o=(0,t.helper)(((e,t)=>{let o,[a=""]=e,u=(0,r.default)(`consul-ui${t.from}`,a) -if("/"===a.charAt(0)&&(u=`consul-ui${u}`),!n.default.has(u))throw new Error(`Unable to resolve '${u}' does the file exist?`) -switch(o=(0,n.default)(u)[t.export||"default"],!0){case u.endsWith(".css"):return o(l.css) -case u.endsWith(".xstate"):return o -case u.endsWith(".element"):{if(i.has(u))return i.get(u) -const e=o(HTMLElement) -return i.set(u,e),e}default:return o}})) -e.default=o})),define("consul-ui/helpers/reverse",["exports","ember-composable-helpers/helpers/reverse"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/right-trim",["exports","@ember/component/helper","consul-ui/utils/right-trim"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l=(0,t.helper)((function(e,t){let[l="",r=""]=e -return(0,n.default)(l,r)})) -e.default=l})),define("consul-ui/helpers/root-url",["exports","ember-router-helpers/helpers/root-url"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"rootUrl",{enumerable:!0,get:function(){return t.rootUrl}})})),define("consul-ui/helpers/round",["exports","ember-math-helpers/helpers/round"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"round",{enumerable:!0,get:function(){return t.round}})})),define("consul-ui/helpers/route-action",["exports","ember-route-action-helper/helpers/route-action"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/route-match",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.helper)((function(e,t){let[n]=e -switch(["Present","Exact","Prefix","Suffix","Regex"].find((e=>void 0!==n[e]))){case"Present":return(n.Invert?"NOT ":"")+"present" -case"Exact":return`${n.Invert?"NOT ":""}exactly matching "${n.Exact}"` -case"Prefix":return`${n.Invert?"NOT ":""}prefixed by "${n.Prefix}"` -case"Suffix":return`${n.Invert?"NOT ":""}suffixed by "${n.Suffix}"` -case"Regex":return`${n.Invert?"NOT ":""}matching the regex "${n.Regex}"`}return""})) -e.default=n})),define("consul-ui/helpers/route-params",["exports","ember-router-helpers/helpers/route-params"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"routeParams",{enumerable:!0,get:function(){return t.routeParams}})})),define("consul-ui/helpers/service/card-permissions",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.helper)((function(e){let[t]=e -if(""===t.Datacenter)return"empty" -{const e=t.Intention.HasPermissions,n=t.Intention.Allowed,l="specific-intention"===t.Source&&!t.TransparentProxy -switch(!0){case e:return"allow" -case!n&&!e:return"deny" -case n&&l:return"not-defined" -default:return"allow"}}})) -e.default=n})) -define("consul-ui/helpers/service/external-source",["exports","@ember/component/helper","@ember/object"],(function(e,t,n){function l(e,t){let l=(0,n.get)(e[0],"ExternalSources.firstObject") -l||(l=(0,n.get)(e[0],"Meta.external-source")) -const r=void 0===t.prefix?"":t.prefix -if(l&&["consul-api-gateway","vault","kubernetes","terraform","nomad","consul","aws","lambda"].includes(l))return`${r}${l}`}Object.defineProperty(e,"__esModule",{value:!0}),e.serviceExternalSource=l,e.default=void 0 -var r=(0,t.helper)(l) -e.default=r})),define("consul-ui/helpers/service/health-percentage",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.helper)((function(e){let[t]=e -const n=t.ChecksCritical+t.ChecksPassing+t.ChecksWarning -return 0===n?"":{passing:Math.round(t.ChecksPassing/n*100),warning:Math.round(t.ChecksWarning/n*100),critical:Math.round(t.ChecksCritical/n*100)}})) -e.default=n})),define("consul-ui/helpers/set",["exports","ember-set-helper/helpers/set"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/shuffle",["exports","ember-composable-helpers/helpers/shuffle"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"shuffle",{enumerable:!0,get:function(){return t.shuffle}})})),define("consul-ui/helpers/sign",["exports","ember-math-helpers/helpers/sign"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"sign",{enumerable:!0,get:function(){return t.sign}})})),define("consul-ui/helpers/sin",["exports","ember-math-helpers/helpers/sin"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"sin",{enumerable:!0,get:function(){return t.sin}})})),define("consul-ui/helpers/singularize",["exports","ember-inflector/lib/helpers/singularize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=t.default -e.default=n})),define("consul-ui/helpers/slice",["exports","ember-composable-helpers/helpers/slice"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/slugify",["exports","@ember/component/helper"],(function(e,t){function n(e,t){let[n=""]=e -return n.replace(/ /g,"-").toLowerCase()}Object.defineProperty(e,"__esModule",{value:!0}),e.slugify=n,e.default=void 0 -var l=(0,t.helper)(n) -e.default=l})),define("consul-ui/helpers/smart-date-format",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i -function o(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function a(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const u=6048e5 -function s(e){const t=new Date -return e>=+t-u&&e<=+t+u}let c=(l=class extends t.default{constructor(){super(...arguments),o(this,"temporal",r,this),o(this,"intl",i,this)}compute(e,t){let[n]=e -return{isNearDate:s(n),relative:`${this.temporal.format(n)} ago`,friendly:this.intl.formatTime(n,{month:"short",day:"numeric",year:"numeric",hour:"numeric",minute:"numeric",second:"numeric",hourCycle:"h24"})}}},r=a(l.prototype,"temporal",[n.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i=a(l.prototype,"intl",[n.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),l) -e.default=c})),define("consul-ui/helpers/sort-by",["exports","ember-composable-helpers/helpers/sort-by"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/split",["exports","@ember/component/helper"],(function(e,t){function n(e,t){let[n="",l=","]=e -return n.split(l)}Object.defineProperty(e,"__esModule",{value:!0}),e.split=n,e.default=void 0 -var l=(0,t.helper)(n) -e.default=l})),define("consul-ui/helpers/sqrt",["exports","ember-math-helpers/helpers/sqrt"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"sqrt",{enumerable:!0,get:function(){return t.sqrt}})})),define("consul-ui/helpers/state-chart",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,n.inject)("state"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="state",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){let[n]=e -return this.state.stateChart(n)}},a=r.prototype,u="state",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/helpers/state-matches",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,n.inject)("state"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="state",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){let[n,l]=e -return this.state.matches(n,l)}},a=r.prototype,u="state",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/helpers/string-char-at",["exports","ember-string-fns/helpers/string-char-at"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringCharAt",{enumerable:!0,get:function(){return t.stringCharAt}})})),define("consul-ui/helpers/string-char-code-at",["exports","ember-string-fns/helpers/string-char-code-at"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringCharCodeAt",{enumerable:!0,get:function(){return t.stringCharCodeAt}})})),define("consul-ui/helpers/string-code-point-at",["exports","ember-string-fns/helpers/string-code-point-at"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringCodePointAt",{enumerable:!0,get:function(){return t.stringCodePointAt}})})),define("consul-ui/helpers/string-concat",["exports","ember-string-fns/helpers/string-concat"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringConcat",{enumerable:!0,get:function(){return t.stringConcat}})})),define("consul-ui/helpers/string-ends-with",["exports","ember-string-fns/helpers/string-ends-with"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringEndsWith",{enumerable:!0,get:function(){return t.stringEndsWith}})})),define("consul-ui/helpers/string-equals",["exports","ember-string-fns/helpers/string-equals"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringEquals",{enumerable:!0,get:function(){return t.stringEquals}})})),define("consul-ui/helpers/string-from-char-code",["exports","ember-string-fns/helpers/string-from-char-code"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringFromCharCode",{enumerable:!0,get:function(){return t.stringFromCharCode}})})),define("consul-ui/helpers/string-from-code-point",["exports","ember-string-fns/helpers/string-from-code-point"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringFromCodePoint",{enumerable:!0,get:function(){return t.stringFromCodePoint}})})),define("consul-ui/helpers/string-html-safe",["exports","@ember/component/helper","@ember/string"],(function(e,t,n){function l(e){let[t=""]=e -return(0,n.htmlSafe)(t)}Object.defineProperty(e,"__esModule",{value:!0}),e.stringHtmlSafe=l,e.default=void 0 -var r=(0,t.helper)(l) -e.default=r})),define("consul-ui/helpers/string-includes",["exports","ember-string-fns/helpers/string-includes"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringIncludes",{enumerable:!0,get:function(){return t.stringIncludes}})})),define("consul-ui/helpers/string-index-of",["exports","ember-string-fns/helpers/string-index-of"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringIndexOf",{enumerable:!0,get:function(){return t.stringIndexOf}})})),define("consul-ui/helpers/string-last-index-of",["exports","ember-string-fns/helpers/string-last-index-of"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringLastIndexOf",{enumerable:!0,get:function(){return t.stringLastIndexOf}})})),define("consul-ui/helpers/string-not-equals",["exports","ember-string-fns/helpers/string-not-equals"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringNotEquals",{enumerable:!0,get:function(){return t.stringNotEquals}})})),define("consul-ui/helpers/string-pad-end",["exports","ember-string-fns/helpers/string-pad-end"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringPadEnd",{enumerable:!0,get:function(){return t.stringPadEnd}})})),define("consul-ui/helpers/string-pad-start",["exports","ember-string-fns/helpers/string-pad-start"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringPadStart",{enumerable:!0,get:function(){return t.stringPadStart}})})) -define("consul-ui/helpers/string-repeat",["exports","ember-string-fns/helpers/string-repeat"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringRepeat",{enumerable:!0,get:function(){return t.stringRepeat}})})),define("consul-ui/helpers/string-replace-all",["exports","ember-string-fns/helpers/string-replace-all"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringReplaceAll",{enumerable:!0,get:function(){return t.stringReplaceAll}})})),define("consul-ui/helpers/string-replace",["exports","ember-string-fns/helpers/string-replace"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringReplace",{enumerable:!0,get:function(){return t.stringReplace}})})),define("consul-ui/helpers/string-slice",["exports","ember-string-fns/helpers/string-slice"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringSlice",{enumerable:!0,get:function(){return t.stringSlice}})})),define("consul-ui/helpers/string-split",["exports","ember-string-fns/helpers/string-split"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringSplit",{enumerable:!0,get:function(){return t.stringSplit}})})),define("consul-ui/helpers/string-starts-with",["exports","ember-string-fns/helpers/string-starts-with"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringStartsWith",{enumerable:!0,get:function(){return t.stringStartsWith}})})),define("consul-ui/helpers/string-substring",["exports","ember-string-fns/helpers/string-substring"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringSubstring",{enumerable:!0,get:function(){return t.stringSubstring}})})),define("consul-ui/helpers/string-to-camel-case",["exports","ember-string-fns/helpers/string-to-camel-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToCamelCase",{enumerable:!0,get:function(){return t.stringToCamelCase}})})),define("consul-ui/helpers/string-to-kebab-case",["exports","ember-string-fns/helpers/string-to-kebab-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToKebabCase",{enumerable:!0,get:function(){return t.stringToKebabCase}})})),define("consul-ui/helpers/string-to-lower-case",["exports","ember-string-fns/helpers/string-to-lower-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToLowerCase",{enumerable:!0,get:function(){return t.stringToLowerCase}})})),define("consul-ui/helpers/string-to-pascal-case",["exports","ember-string-fns/helpers/string-to-pascal-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToPascalCase",{enumerable:!0,get:function(){return t.stringToPascalCase}})})),define("consul-ui/helpers/string-to-sentence-case",["exports","ember-string-fns/helpers/string-to-sentence-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToSentenceCase",{enumerable:!0,get:function(){return t.stringToSentenceCase}})})),define("consul-ui/helpers/string-to-snake-case",["exports","ember-string-fns/helpers/string-to-snake-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToSnakeCase",{enumerable:!0,get:function(){return t.stringToSnakeCase}})})),define("consul-ui/helpers/string-to-title-case",["exports","ember-string-fns/helpers/string-to-title-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToTitleCase",{enumerable:!0,get:function(){return t.stringToTitleCase}})})),define("consul-ui/helpers/string-to-upper-case",["exports","ember-string-fns/helpers/string-to-upper-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToUpperCase",{enumerable:!0,get:function(){return t.stringToUpperCase}})})),define("consul-ui/helpers/string-trim-end",["exports","ember-string-fns/helpers/string-trim-end"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringTrimEnd",{enumerable:!0,get:function(){return t.stringTrimEnd}})})),define("consul-ui/helpers/string-trim-start",["exports","ember-string-fns/helpers/string-trim-start"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringTrimStart",{enumerable:!0,get:function(){return t.stringTrimStart}})})),define("consul-ui/helpers/string-trim",["exports","ember-string-fns/helpers/string-trim"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringTrim",{enumerable:!0,get:function(){return t.stringTrim}})})),define("consul-ui/helpers/style-map",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.helper)((function(e){const t=e.reduce(((e,t)=>{let[n,l,r=""]=t -return null==l?e:`${e}${n}:${l.toString()}${r};`}),"") -return t.length>0?t:void 0})) -e.default=n})),define("consul-ui/helpers/sub",["exports","ember-math-helpers/helpers/sub"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"sub",{enumerable:!0,get:function(){return t.sub}})})),define("consul-ui/helpers/substr",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.helper)((function(e,t){let[n="",l=0,r]=e -return n.substr(l,r)})) -e.default=n})),define("consul-ui/helpers/svg-curve",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.helper)((function(e,t){let[n]=e -const l=t.src||{x:0,y:0},r=t.type||"cubic" -let i=[n,{x:(l.x+n.x)/2,y:l.y}] -return"cubic"===r&&i.push({x:i[1].x,y:n.y}),`${o=l,`\n M ${o.x} ${o.y}\n `}${function(){const e=[...arguments] -return`${arguments.length>2?"C":"Q"} ${e.concat(e.shift()).map((e=>Object.values(e).join(" "))).join(",")}`}(...i)}` -var o})) -e.default=n})),define("consul-ui/helpers/t",["exports","ember-intl/helpers/t"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/take",["exports","ember-composable-helpers/helpers/take"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/tan",["exports","ember-math-helpers/helpers/tan"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"tan",{enumerable:!0,get:function(){return t.tan}})})),define("consul-ui/helpers/tanh",["exports","ember-math-helpers/helpers/tanh"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"tanh",{enumerable:!0,get:function(){return t.tanh}})})),define("consul-ui/helpers/task",["exports","ember-concurrency/helpers/task"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/temporal-format",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,n.inject)("temporal"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="temporal",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){let[n]=e -return this.temporal.format(n,t)}},a=r.prototype,u="temporal",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/helpers/temporal-within",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,n.inject)("temporal"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="temporal",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){return this.temporal.within(e,t)}},a=r.prototype,u="temporal",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/helpers/test",["exports","consul-ui/helpers/can","consul-ui/helpers/is"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{compute(e,t){let[l,r]=e -switch(!0){case l.startsWith("can "):return super.compute([l.substr(4),r],t) -case l.startsWith("is "):return(0,n.is)(this,[l.substr(3),r],t)}throw new Error(`${l} is not supported by the 'test' helper.`)}}e.default=l})) -define("consul-ui/helpers/titleize",["exports","ember-cli-string-helpers/helpers/titleize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"titleize",{enumerable:!0,get:function(){return t.titleize}})})),define("consul-ui/helpers/to-hash",["exports","@ember/component/helper","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l=(0,t.helper)(((e,t)=>{let[l=[],r]=e -return Array.isArray(l)||(l=l.toArray()),l.reduce(((e,t,l)=>(e[(0,n.get)(t,r)]=t,e)),{})})) -e.default=l})),define("consul-ui/helpers/to-route",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i,o,a -function u(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function s(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let c=(l=(0,n.inject)("router"),r=(0,n.inject)("env"),i=class extends t.default{constructor(){super(...arguments),u(this,"router",o,this),u(this,"env",a,this)}compute(e){let[t]=e -return this.router.recognize(`${this.env.var("rootURL")}${t}`).name}},o=s(i.prototype,"router",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=s(i.prototype,"env",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) -e.default=c})),define("consul-ui/helpers/toggle-action",["exports","ember-composable-helpers/helpers/toggle-action"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/toggle",["exports","ember-composable-helpers/helpers/toggle"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"toggle",{enumerable:!0,get:function(){return t.toggle}})})),define("consul-ui/helpers/token/is-anonymous",["exports","@ember/component/helper","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.isAnonymous=l,e.default=void 0 -function l(e,t){return"00000000-0000-0000-0000-000000000002"===(0,n.get)(e[0],"AccessorID")}var r=(0,t.helper)(l) -e.default=r})),define("consul-ui/helpers/token/is-legacy",["exports","@ember/component/helper","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.isLegacy=r,e.default=void 0 -const l=function(e){const t=(0,n.get)(e,"Rules") -if(null!=t)return""!==t.trim() -const l=(0,n.get)(e,"Legacy") -return void 0!==l&&l} -function r(e,t){const n=e[0] -return void 0!==n.length?n.find((function(e){return l(e)})):l(n)}var i=(0,t.helper)(r) -e.default=i})),define("consul-ui/helpers/transition-to",["exports","ember-router-helpers/helpers/transition-to"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"transitionTo",{enumerable:!0,get:function(){return t.transitionTo}})})),define("consul-ui/helpers/trunc",["exports","ember-math-helpers/helpers/trunc"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"trunc",{enumerable:!0,get:function(){return t.trunc}})})),define("consul-ui/helpers/truncate",["exports","ember-cli-string-helpers/helpers/truncate"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"truncate",{enumerable:!0,get:function(){return t.truncate}})})),define("consul-ui/helpers/tween-to",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,n.inject)("ticker"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="ticker",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){let[n,l]=e -return this.ticker.tweenTo(n,l)}},a=r.prototype,u="ticker",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/helpers/union",["exports","ember-composable-helpers/helpers/union"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/uniq-by",["exports","@ember/component/helper","@ember/utils","@ember/array"],(function(e,t,n,l){function r(e){let[t,r]=e -return(0,n.isEmpty)(t)?[]:(0,l.A)(r).uniqBy(t)}Object.defineProperty(e,"__esModule",{value:!0}),e.uniqBy=r,e.default=void 0 -var i=(0,t.helper)(r) -e.default=i})),define("consul-ui/helpers/unique-id",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,n.inject)("dom"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="dom",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){return this.dom.guid({})}},a=r.prototype,u="dom",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/helpers/uppercase",["exports","ember-cli-string-helpers/helpers/uppercase"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"uppercase",{enumerable:!0,get:function(){return t.uppercase}})})),define("consul-ui/helpers/uri",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i,o,a -function u(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function s(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const c=/\${([A-Za-z.0-9_-]+)}/g -let d,p=(l=(0,n.inject)("encoder"),r=(0,n.inject)("data-source/service"),i=class extends t.default{constructor(){super(...arguments),u(this,"encoder",o,this),u(this,"data",a,this),"function"!=typeof d&&(d=this.encoder.createRegExpEncoder(c,encodeURIComponent))}compute(e){let[t,n]=e -return this.data.uri(d(t,n))}},o=s(i.prototype,"encoder",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=s(i.prototype,"data",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) -e.default=p})),define("consul-ui/helpers/url-for",["exports","ember-router-helpers/helpers/url-for"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"urlFor",{enumerable:!0,get:function(){return t.urlFor}})})),define("consul-ui/helpers/values",["exports","ember-composable-helpers/helpers/values"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"values",{enumerable:!0,get:function(){return t.values}})})),define("consul-ui/helpers/will-destroy",["exports","ember-render-helpers/helpers/will-destroy"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/without",["exports","ember-composable-helpers/helpers/without"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"without",{enumerable:!0,get:function(){return t.without}})})),define("consul-ui/helpers/xor",["exports","ember-truth-helpers/helpers/xor"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"xor",{enumerable:!0,get:function(){return t.xor}})})),define("consul-ui/initializers/app-version",["exports","ember-cli-app-version/initializer-factory","consul-ui/config/environment"],(function(e,t,n){let l,r -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,n.default.APP&&(l=n.default.APP.name,r=n.default.APP.version) -var i={name:"App Version",initialize:(0,t.default)(l,r)} -e.default=i})),define("consul-ui/initializers/container-debug-adapter",["exports","ember-resolver/resolvers/classic/container-debug-adapter"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n={name:"container-debug-adapter",initialize(){(arguments[1]||arguments[0]).register("container-debug-adapter:main",t.default)}} -e.default=n})),define("consul-ui/initializers/ember-data-data-adapter",["exports","@ember-data/debug/setup"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/initializers/ember-data",["exports","ember-data","ember-data/setup-container"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l={name:"ember-data",initialize:n.default} -e.default=l})),define("consul-ui/initializers/export-application-global",["exports","ember","consul-ui/config/environment"],(function(e,t,n){function l(){var e=arguments[1]||arguments[0] -if(!1!==n.default.exportApplicationGlobal){var l -if("undefined"!=typeof window)l=window -else if("undefined"!=typeof global)l=global -else{if("undefined"==typeof self)return -l=self}var r,i=n.default.exportApplicationGlobal -r="string"==typeof i?i:t.default.String.classify(n.default.modulePrefix),l[r]||(l[r]=e,e.reopen({willDestroy:function(){this._super.apply(this,arguments),delete l[r]}}))}}Object.defineProperty(e,"__esModule",{value:!0}),e.initialize=l,e.default=void 0 -var r={name:"export-application-global",initialize:l} -e.default=r})),define("consul-ui/initializers/flash-messages",["exports","consul-ui/config/environment","@ember/application/deprecations","ember-cli-flash/utils/flash-message-options"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.initialize=r,e.default=void 0 -function r(){const e=arguments[1]||arguments[0],{flashMessageDefaults:n}=t.default||{},{injectionFactories:r}=n||[],i=(0,l.default)(n) -r&&r.length -i.injectionFactories.forEach((t=>{e.inject(t,"flashMessages","service:flash-messages")}))}var i={name:"flash-messages",initialize:r} -e.default=i})),define("consul-ui/initializers/initialize-torii-callback",["exports","consul-ui/config/environment","torii/redirect-handler"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l={name:"torii-callback",before:"torii",initialize(e){arguments[1]&&(e=arguments[1]),t.default.torii&&t.default.torii.disableRedirectInitializer||(e.deferReadiness(),n.default.handle(window).catch((function(){e.advanceReadiness()})))}} -e.default=l})),define("consul-ui/initializers/initialize-torii-session",["exports","torii/bootstrap/session","torii/configuration"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l={name:"torii-session",after:"torii",initialize(e){arguments[1]&&(e=arguments[1]) -const l=(0,n.getConfiguration)() -l.sessionServiceName&&(0,t.default)(e,l.sessionServiceName)}} -e.default=l})),define("consul-ui/initializers/initialize-torii",["exports","torii/bootstrap/torii","torii/configuration","consul-ui/config/environment"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var r={name:"torii",initialize(e){arguments[1]&&(e=arguments[1]),(0,n.configure)(l.default.torii||{}),(0,t.default)(e)}},i=r -e.default=i})) -define("consul-ui/initializers/model-fragments",["exports","ember-data-model-fragments","ember-data-model-fragments/ext"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l={name:"fragmentTransform",after:"ember-data",initialize(){}} -e.default=l})),define("consul-ui/initializers/setup-ember-can",["exports","ember-can/initializers/setup-ember-can"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"initialize",{enumerable:!0,get:function(){return t.initialize}})})),define("consul-ui/initializers/viewport-config",["exports","ember-in-viewport/initializers/viewport-config"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"initialize",{enumerable:!0,get:function(){return t.initialize}})})),define("consul-ui/instance-initializers/container",["exports","@ember/debug","require","deepmerge"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.services=void 0 -const r=document,i=l.default.all([...r.querySelectorAll("script[data-services]")].map((e=>JSON.parse(e.dataset.services)))) -e.services=i -var o={name:"container",initialize(e){(function(e,t){Object.entries(t).forEach((t=>{let[l,r]=t -if(1==("string"==typeof r.class)){if(!n.default.has(r.class))throw new Error(`Unable to locate '${r.class}'`) -e.register(l.replace("auth-provider:","torii-provider:"),(0,n.default)(r.class).default)}}))})(e,i) -const l=e.lookup("service:container") -let r=l.get("container-debug-adapter:main").catalogEntriesByType("service").filter((e=>e.startsWith("repository/")||"ui-config"===e));(0,t.runInDebug)((()=>r=r.filter((e=>!e.endsWith("-test"))))),r.push("repository/service"),r.forEach((e=>{const t=`service:${e}` -l.set(t,l.resolveRegistration(t))}))}} -e.default=o})),define("consul-ui/instance-initializers/ember-data",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var t={name:"ember-data",initialize(){}} -e.default=t})),define("consul-ui/instance-initializers/href-to",["exports","@ember/routing/link-component"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.HrefTo=void 0 -class n{constructor(e,t){this.applicationInstance=e,this.target=t -const n=this.target.attributes.href -this.url=n&&n.value}handle(e){this.shouldHandle(e)&&(e.preventDefault(),this.applicationInstance.lookup("router:main").location.transitionTo(this.url))}shouldHandle(e){return this.isUnmodifiedLeftClick(e)&&!this.isIgnored(this.target)&&!this.isExternal(this.target)&&!this.hasActionHelper(this.target)&&!this.hasDownload(this.target)&&!this.isLinkComponent(this.target)}isUnmodifiedLeftClick(e){return!(void 0!==e.which&&1!==e.which||e.ctrlKey||e.metaKey)}isExternal(e){return"_blank"===e.getAttribute("target")}isIgnored(e){return e.dataset.nativeHref}hasActionHelper(e){return e.dataset.emberAction}hasDownload(e){return e.hasAttribute("download")}isLinkComponent(e){let n=!1 -const l=e.id -if(l){const e=this.applicationInstance.lookup("-view-registry:main")[l] -n=e&&e instanceof t.default}return n}recognizeUrl(e){let t=!1 -if(e){const n=this._getRouter(),l=this._getRootUrl(),r=0===e.indexOf(l),i=this.getUrlWithoutRoot(),o=n._router._routerMicrolib||n._router.router -t=r&&o.recognizer.recognize(i)}return t}getUrlWithoutRoot(){const e=this.applicationInstance.lookup("router:main").location -let t=e.getURL.apply({getHash:()=>"",location:{pathname:this.url},baseURL:e.baseURL,rootURL:e.rootURL,env:e.env},[]) -const n=t.indexOf("?") -return-1!==n&&(t=t.substr(0,n-1)),t}_getRouter(){return this.applicationInstance.lookup("service:router")}_getRootUrl(){let e=this._getRouter().get("rootURL") -return"/"!==e.charAt(e.length-1)&&(e+="/"),e}}e.HrefTo=n -var l={name:"href-to",initialize(e){if("undefined"==typeof FastBoot){const t=e.lookup("service:dom").document(),l=t=>{const l="A"===t.target.tagName?t.target:function(e){if(e.closest)return e.closest("a") -for(e=e.parentElement;e&&"A"!==e.tagName;)e=e.parentElement -return e}(t.target) -if(l){new n(e,l).handle(t)}} -t.body.addEventListener("click",l),e.reopen({willDestroy(){return t.body.removeEventListener("click",l),this._super(...arguments)}})}}} -e.default=l})),define("consul-ui/instance-initializers/ivy-codemirror",["exports"],(function(e){function t(e){const t=e.application.name,n=e.lookup("service:-document"),l=new Map(Object.entries(JSON.parse(n.querySelector(`[data-${t}-fs]`).textContent))) -CodeMirror.modeURL={replace:function(e,t){switch(t.trim()){case"javascript":return l.get(["codemirror","mode","javascript","javascript.js"].join("/")) -case"ruby":return l.get(["codemirror","mode","ruby","ruby.js"].join("/")) -case"yaml":return l.get(["codemirror","mode","yaml","yaml.js"].join("/")) -case"xml":return l.get(["codemirror","mode","xml","xml.js"].join("/"))}}} -e.resolveRegistration("component:ivy-codemirror").reopen({attributeBindings:["name"]})}Object.defineProperty(e,"__esModule",{value:!0}),e.initialize=t,e.default=void 0 -var n={initialize:t} -e.default=n})),define("consul-ui/instance-initializers/selection",["exports","consul-ui/env"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n={name:"selection",initialize(e){if((0,t.env)("CONSUL_UI_DISABLE_ANCHOR_SELECTION"))return -const n=e.lookup("service:dom"),l=n.document(),r=l.getElementsByTagName("html")[0],i=function(e){return"A"===e.tagName?e:n.closest("a",e)},o=function(e){if(r.classList.contains("is-debug"))return -const t=i(e.target) -if(t){if(void 0!==e.button&&2===e.button){const e=t.dataset.href -return void(e&&t.setAttribute("href",e))}const n=t.getAttribute("href") -n&&(t.dataset.href=n,t.removeAttribute("href"))}},a=function(e){if(r.classList.contains("is-debug"))return -const t=i(e.target) -if(t){const n=t.dataset.href -!function(){const t=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:window).getSelection() -let n=!1 -try{n="isCollapsed"in t&&!t.isCollapsed&&t.toString().length>1}catch(e){}return n}()&&n&&t.setAttribute("href",n)}} -l.body.addEventListener("mousedown",o),l.body.addEventListener("mouseup",a),e.reopen({willDestroy:function(){return l.body.removeEventListener("mousedown",o),l.body.removeEventListener("mouseup",a),this._super(...arguments)}})}} -e.default=n})),define("consul-ui/instance-initializers/setup-routes",["exports","ember","torii/bootstrap/routing","torii/configuration","torii/compat/get-router-instance","torii/compat/get-router-lib","torii/router-dsl-ext"],(function(e,t,n,l,r,i,o){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var a={name:"torii-setup-routes",initialize(e){if(!(0,l.getConfiguration)().sessionServiceName)return -let o=(0,r.default)(e) -const a=e.lookup("service:router") -var u=function(){var l=(0,i.default)(o).authenticatedRoutes -!t.default.isEmpty(l)&&(0,n.default)(e,l),a.off("routeWillChange",u)} -a.on("routeWillChange",u)}} -e.default=a})),define("consul-ui/instance-initializers/walk-providers",["exports","torii/lib/container-utils","torii/configuration"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l={name:"torii-walk-providers",initialize(e){let l=(0,n.getConfiguration)() -for(var r in l.providers)l.providers.hasOwnProperty(r)&&(0,t.lookup)(e,"torii-provider:"+r)}} -e.default=l})),define("consul-ui/locations/fsm-with-optional-test",["exports","consul-ui/locations/fsm-with-optional","consul-ui/locations/fsm","@ember/test-helpers"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class r extends t.default{static create(){return new this(...arguments)}constructor(){var e,t,l -super(...arguments),l="fsm-with-optional-test",(t="implementation")in(e=this)?Object.defineProperty(e,t,{value:l,enumerable:!0,configurable:!0,writable:!0}):e[t]=l,this.location=new n.Location,this.machine=new n.FSM(this.location),this.doc={defaultView:{addEventListener:(e,t)=>{this.machine=new n.FSM(this.location,t)},removeEventListener:(e,t)=>{this.machine=new n.FSM}}}}visit(e){const t=this.container,n=this.container.lookup("router:main"),r=async e=>(await(0,l.settled)(),new Promise((e=>setTimeout(e(t),0)))),i=e=>{if(e.error)throw e.error -if("TransitionAborted"===e.name&&n._routerMicrolib.activeTransition)return n._routerMicrolib.activeTransition.then(r,i) -throw"TransitionAborted"===e.name?new Error(e.message):e} -return""===this.location.pathname?(this.rootURL=n.rootURL.replace(/\/$/,""),this.machine.state.path=this.location.pathname=`${this.rootURL}${e}`,this.path=this.getURL(),t.handleURL(`${this.path}`).then(r,i)):this.transitionTo(e).then(r,i)}}e.default=r})),define("consul-ui/locations/fsm-with-optional",["exports","consul-ui/env"],(function(e,t){function n(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function l(e){for(var t=1;t{if(t<3){let t=!1 -return Object.entries(i).reduce(((n,l)=>{let[r,i]=l -const o=i.exec(e) -return null!==o&&(n[r]={value:e,match:o[1]},t=!0),n}),this.optional),!t}return!0})).join("/")}optionalParams(){let e=this.optional||{} -return["partition","nspace","peer"].reduce(((t,n)=>{let l="" -return void 0!==e[n]&&(l=e[n].match),t[n]=l,t}),{})}visit(){return this.transitionTo(...arguments)}hrefTo(e,n,r){const i=l({},r) -void 0!==i.dc&&delete i.dc,void 0!==i.nspace&&(i.nspace=`~${i.nspace}`),void 0!==i.partition&&(i.partition=`_${i.partition}`),void 0!==i.peer&&(i.peer=`:${i.peer}`),void 0===this.router&&(this.router=this.container.lookup("router:main")) -let o=!0 -switch(!0){case"settings"===e:case e.startsWith("docs."):o=!1}if(this.router.currentRouteName.startsWith("docs.")&&(n.unshift((0,t.env)("CONSUL_DATACENTER_PRIMARY")),e.startsWith("dc")))return`console://${e} <= ${JSON.stringify(n)}` -const a=this.router._routerMicrolib -let u -try{u=a.generate(e,...n,{queryParams:{}})}catch(s){n=Object.values(a.oldState.params).reduce(((e,t)=>e.concat(Object.keys(t).length>0?t:[])),[]),u=a.generate(e,...n)}return this.formatURL(u,i,o)}transitionTo(e){if(this.router.currentRouteName.startsWith("docs")&&e.startsWith("console://"))return console.info(`location.transitionTo: ${e.substr(10)}`),!0 -const t=Object.entries(this.optionalParams()),n=this.getURLForTransition(e) -if(this._previousURL===n)return this.dispatch("push",e),Promise.resolve() -{const l=this.optionalParams() -return t.some((e=>{let[t,n]=e -return l[t]!==n}))&&this.dispatch("push",e),this.container.lookup("router:main").transitionTo(n)}}getURL(){const e=this.location.search||"" -let t="" -void 0!==this.location.hash&&(t=this.location.hash.substr(0)) -return`${this.getURLForTransition(this.location.pathname)}${e}${t}`}formatURL(e,t){let n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2] -if(""!==e?(this.rootURL=this.rootURL.replace(o,""),this.baseURL=this.baseURL.replace(o,"")):"/"===this.baseURL[0]&&"/"===this.rootURL[0]&&(this.baseURL=this.baseURL.replace(o,"")),n){const n=e.split("/") -t=l(l({},this.optional),t||{}),t=Object.values(t).filter((e=>Boolean(e))).map((e=>e.value||e),[]),n.splice(...[1,0].concat(t)),e=n.join("/")}return`${this.baseURL}${this.rootURL}${e}`}changeURL(e,t){this.path=t -const n=this.machine.state -t=this.formatURL(t),n&&n.path===t||this.dispatch(e,t)}setURL(e){this.changeURL("push",e)}replaceURL(e){this.changeURL("replace",e)}onUpdateURL(e){this.callback=e}dispatch(e,t){const n={path:t,uuid:"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0 -return("x"===e?t:3&t|8).toString(16)}))} -this.machine[`${e}State`](n,null,t),this.route({state:n})}willDestroy(){this.doc.defaultView.removeEventListener("popstate",this.route)}}})),define("consul-ui/locations/fsm",["exports"],(function(e){function t(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.Location=e.FSM=void 0 -e.FSM=class{constructor(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:()=>{} -t(this,"state",{}),this.listener=n,this.location=e}pushState(e,t,n){this.state=e,this.location.pathname=n,this.listener({state:this.state})}replaceState(){return this.pushState(...arguments)}} -e.Location=class{constructor(){t(this,"pathname",""),t(this,"search",""),t(this,"hash","")}} -e.default=class{static create(){return new this(...arguments)}constructor(e){t(this,"implementation","fsm"),this.container=Object.entries(e)[0][1]}visit(){return this.transitionTo(...arguments)}hrefTo(){}transitionTo(){}}})),define("consul-ui/machines/boolean.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={id:"boolean",initial:"false",states:{true:{on:{TOGGLE:[{target:"false"}],FALSE:[{target:"false"}]}},false:{on:{TOGGLE:[{target:"true"}],TRUE:[{target:"true"}]}}}}})),define("consul-ui/machines/validate.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={id:"form",initial:"idle",on:{RESET:[{target:"idle"}]},states:{idle:{on:{SUCCESS:[{target:"success"}],ERROR:[{target:"error"}]}},success:{},error:{}}}})),define("consul-ui/mixins/policy/as-many",["exports","@ember/object/mixin","@ember/object","consul-ui/utils/minimizeModel"],(function(e,t,n,l){function r(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=function(e,t,n,l){return(e||[]).map((function(e){const r={template:t,Name:e[n]} -return void 0!==e[l]&&(r[l]=e[l]),r}))},a=function(e){return(e||[]).map((function(e){return function(e){for(var t=1;t(n.Policies=a(n.Policies).concat(o(n.ServiceIdentities,"service-identity","ServiceName","Datacenters")).concat(o(n.NodeIdentities,"node-identity","NodeName","Datacenter")),t(e,n))))}),t)},respondForQuery:function(e,t){return this._super((function(t){return e((function(e,n){return t(e,n.map((function(e){return e.Policies=a(e.Policies).concat(o(e.ServiceIdentities,"service-identity","ServiceName","Datacenters")).concat(o(e.NodeIdentities,"node-identity","NodeName","Datacenter")),e})))}))}),t)},serialize:function(e,t){const n=this._super(...arguments) -return n.ServiceIdentities=u(n.Policies,"service-identity","ServiceName","Datacenters"),n.NodeIdentities=u(n.Policies,"node-identity","NodeName","Datacenter"),n.Policies=(0,l.default)(s(n.Policies)),n}}) -e.default=c})),define("consul-ui/mixins/role/as-many",["exports","@ember/object/mixin","consul-ui/utils/minimizeModel"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l=t.default.create({respondForQueryRecord:function(e,t){return this._super((function(t){return e(((e,n)=>(n.Roles=void 0===n.Roles||null===n.Roles?[]:n.Roles,t(e,n))))}),t)},respondForQuery:function(e,t){return this._super((function(t){return e((function(e,n){return t(e,n.map((function(e){return e.Roles=void 0===e.Roles||null===e.Roles?[]:e.Roles,e})))}))}),t)},serialize:function(e,t){const l=this._super(...arguments) -return l.Roles=(0,n.default)(l.Roles),l}}) -e.default=l})),define("consul-ui/mixins/slots",["exports","block-slots/mixins/slots"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/mixins/with-blocking-actions",["exports","@ember/object/mixin","@ember/service","@ember/object","ember-inflector"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var i=t.default.create({_feedback:(0,n.inject)("feedback"),settings:(0,n.inject)("settings"),init:function(){this._super(...arguments) -const e=this._feedback,t=this;(0,l.set)(this,"feedback",{execute:function(n,l,i){const o=t.routeName.split(".") -o.pop() -const a=(0,r.singularize)(o.pop()) -return e.execute(n,l,i,a)}})},afterCreate:function(e){return this.afterUpdate(...arguments)},afterUpdate:function(e){const t=this.routeName.split(".") -return t.pop(),this.transitionTo(t.join("."))},afterDelete:function(e){const t=this.routeName.split(".") -return"index"===t.pop()?this.refresh():this.transitionTo(t.join("."))},errorCreate:function(e,t){return e},errorUpdate:function(e,t){return e},errorDelete:function(e,t){return e},actions:{cancel:function(){return this.afterUpdate(...arguments)},create:function(e,t){return t.preventDefault(),this.feedback.execute((()=>this.repo.persist(e).then((e=>this.afterCreate(...arguments)))),"create",((e,t)=>this.errorCreate(e,t)))},update:function(e,t){return t.preventDefault(),this.feedback.execute((()=>this.repo.persist(e).then((()=>this.afterUpdate(...arguments)))),"update",((e,t)=>this.errorUpdate(e,t)))},delete:function(e){return this.feedback.execute((()=>this.repo.remove(e).then((()=>this.afterDelete(...arguments)))),"delete",((e,t)=>this.errorDelete(e,t)))},use:function(e){return this.repo.findBySlug({dc:(0,l.get)(e,"Datacenter"),ns:(0,l.get)(e,"Namespace"),partition:(0,l.get)(e,"Partition"),id:(0,l.get)(e,"AccessorID")}).then((e=>this.settings.persist({token:{AccessorID:(0,l.get)(e,"AccessorID"),SecretID:(0,l.get)(e,"SecretID"),Namespace:(0,l.get)(e,"Namespace"),Partition:(0,l.get)(e,"Partition")}})))},logout:function(e){return this.settings.delete("token")},clone:function(e){let t -return this.feedback.execute((()=>this.repo.clone(e).then((e=>(t=e,this.afterDelete(...arguments)))).then((function(){return t}))),"clone")}}}) -e.default=i})),define("consul-ui/models/auth-method",["exports","@ember-data/model","@ember/object/computed","parse-duration","@ember/object"],(function(e,t,n,l,r){var i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D,T,E,L,A,R,I,$,F -function U(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function B(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="Name" -let q=(i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string",{defaultValue:()=>""}),d=(0,t.attr)("string",{defaultValue:()=>""}),p=(0,t.attr)("string",{defaultValue:()=>"local"}),f=(0,t.attr)("string"),m=(0,t.attr)(),h=(0,n.or)("DisplayName","Name"),b=(0,t.attr)(),y=(0,t.attr)("string"),g=(0,t.attr)("number"),v=(0,t.attr)("number"),O=(0,t.attr)(),P=(0,t.attr)(),x=(0,r.computed)("MaxTokenTTL"),w=class extends t.default{constructor(){super(...arguments),U(this,"uid",j,this),U(this,"Name",_,this),U(this,"Datacenter",k,this),U(this,"Namespace",S,this),U(this,"Partition",N,this),U(this,"Description",C,this),U(this,"DisplayName",z,this),U(this,"TokenLocality",M,this),U(this,"Type",D,this),U(this,"NamespaceRules",T,this),U(this,"MethodName",E,this),U(this,"Config",L,this),U(this,"MaxTokenTTL",A,this),U(this,"CreateIndex",R,this),U(this,"ModifyIndex",I,this),U(this,"Datacenters",$,this),U(this,"meta",F,this)}get TokenTTL(){return(0,l.default)(this.MaxTokenTTL)}},j=B(w.prototype,"uid",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=B(w.prototype,"Name",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=B(w.prototype,"Datacenter",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=B(w.prototype,"Namespace",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=B(w.prototype,"Partition",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=B(w.prototype,"Description",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=B(w.prototype,"DisplayName",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=B(w.prototype,"TokenLocality",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=B(w.prototype,"Type",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=B(w.prototype,"NamespaceRules",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=B(w.prototype,"MethodName",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=B(w.prototype,"Config",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=B(w.prototype,"MaxTokenTTL",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R=B(w.prototype,"CreateIndex",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=B(w.prototype,"ModifyIndex",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),$=B(w.prototype,"Datacenters",[O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),F=B(w.prototype,"meta",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),B(w.prototype,"TokenTTL",[x],Object.getOwnPropertyDescriptor(w.prototype,"TokenTTL"),w.prototype),w) -e.default=q})),define("consul-ui/models/binding-rule",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k -function S(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function N(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="ID" -let C=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string",{defaultValue:()=>""}),u=(0,t.attr)("string"),s=(0,t.attr)("string",{defaultValue:()=>""}),c=(0,t.attr)("string"),d=(0,t.attr)("string"),p=(0,t.attr)("number"),f=(0,t.attr)("number"),m=class extends t.default{constructor(){super(...arguments),S(this,"uid",h,this),S(this,"ID",b,this),S(this,"Datacenter",y,this),S(this,"Namespace",g,this),S(this,"Partition",v,this),S(this,"Description",O,this),S(this,"AuthMethod",P,this),S(this,"Selector",x,this),S(this,"BindType",w,this),S(this,"BindName",j,this),S(this,"CreateIndex",_,this),S(this,"ModifyIndex",k,this)}},h=N(m.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=N(m.prototype,"ID",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=N(m.prototype,"Datacenter",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=N(m.prototype,"Namespace",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=N(m.prototype,"Partition",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=N(m.prototype,"Description",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=N(m.prototype,"AuthMethod",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=N(m.prototype,"Selector",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=N(m.prototype,"BindType",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=N(m.prototype,"BindName",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=N(m.prototype,"CreateIndex",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=N(m.prototype,"ModifyIndex",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m) -e.default=C})),define("consul-ui/models/coordinate",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b -function y(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function g(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="Node" -let v=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)(),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("number"),s=class extends t.default{constructor(){super(...arguments),y(this,"uid",c,this),y(this,"Node",d,this),y(this,"Coord",p,this),y(this,"Segment",f,this),y(this,"Datacenter",m,this),y(this,"Partition",h,this),y(this,"SyncTime",b,this)}},c=g(s.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=g(s.prototype,"Node",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=g(s.prototype,"Coord",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=g(s.prototype,"Segment",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=g(s.prototype,"Datacenter",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=g(s.prototype,"Partition",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=g(s.prototype,"SyncTime",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s) -e.default=v})),define("consul-ui/models/dc",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D -function T(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function E(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.FOREIGN_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.FOREIGN_KEY="Datacenter" -e.SLUG_KEY="Name" -let L=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("boolean"),i=(0,t.attr)("number"),o=(0,t.attr)("number"),a=(0,t.attr)("string"),u=(0,t.attr)(),s=(0,t.attr)(),c=(0,t.attr)(),d=(0,t.attr)(),p=(0,t.attr)(),f=(0,t.attr)("boolean"),m=(0,t.attr)("boolean"),h=(0,t.attr)("string"),b=(0,t.attr)("boolean",{defaultValue:()=>!0}),y=class extends t.default{constructor(){super(...arguments),T(this,"uri",g,this),T(this,"Name",v,this),T(this,"Healthy",O,this),T(this,"FailureTolerance",P,this),T(this,"OptimisticFailureTolerance",x,this),T(this,"Leader",w,this),T(this,"Voters",j,this),T(this,"Servers",_,this),T(this,"RedundancyZones",k,this),T(this,"Default",S,this),T(this,"ReadReplicas",N,this),T(this,"Local",C,this),T(this,"Primary",z,this),T(this,"DefaultACLPolicy",M,this),T(this,"MeshEnabled",D,this)}},g=E(y.prototype,"uri",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=E(y.prototype,"Name",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=E(y.prototype,"Healthy",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=E(y.prototype,"FailureTolerance",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=E(y.prototype,"OptimisticFailureTolerance",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=E(y.prototype,"Leader",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=E(y.prototype,"Voters",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=E(y.prototype,"Servers",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=E(y.prototype,"RedundancyZones",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=E(y.prototype,"Default",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=E(y.prototype,"ReadReplicas",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=E(y.prototype,"Local",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=E(y.prototype,"Primary",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=E(y.prototype,"DefaultACLPolicy",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=E(y.prototype,"MeshEnabled",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y) -e.default=L})),define("consul-ui/models/discovery-chain",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b -function y(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function g(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="ServiceName" -let v=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)(),u=(0,t.attr)(),s=class extends t.default{constructor(){super(...arguments),y(this,"uid",c,this),y(this,"ServiceName",d,this),y(this,"Datacenter",p,this),y(this,"Partition",f,this),y(this,"Namespace",m,this),y(this,"Chain",h,this),y(this,"meta",b,this)}},c=g(s.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=g(s.prototype,"ServiceName",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=g(s.prototype,"Datacenter",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=g(s.prototype,"Partition",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=g(s.prototype,"Namespace",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=g(s.prototype,"Chain",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=g(s.prototype,"meta",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s) -e.default=v})),define("consul-ui/models/gateway-config",["exports","ember-data-model-fragments/fragment","ember-data-model-fragments/attributes","@ember-data/model"],(function(e,t,n,l){var r,i,o,a,u -function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let d=(r=(0,l.attr)("number",{defaultValue:()=>0}),i=(0,n.array)("string",{defaultValue:()=>[]}),o=class extends t.default{constructor(){super(...arguments),s(this,"AssociatedServiceCount",a,this),s(this,"Addresses",u,this)}},a=c(o.prototype,"AssociatedServiceCount",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(o.prototype,"Addresses",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) -e.default=d})),define("consul-ui/models/health-check",["exports","ember-data-model-fragments/fragment","ember-data-model-fragments/attributes","@ember-data/model","@ember/object","consul-ui/decorators/replace"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D,T,E -function L(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function A(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.schema=void 0 -e.schema={Status:{allowedValues:["passing","warning","critical"]},Type:{allowedValues:["serf","script","http","tcp","ttl","docker","grpc","alias"]}} -let R=(o=(0,l.attr)("string"),a=(0,l.attr)("string"),u=(0,i.replace)("","serf"),s=(0,l.attr)("string"),c=(0,l.attr)("string"),d=(0,l.attr)("string"),p=(0,l.attr)("string"),f=(0,l.attr)("string"),m=(0,l.attr)("string"),h=(0,l.attr)("string"),b=(0,i.nullValue)([]),y=(0,n.array)("string"),g=(0,l.attr)(),v=(0,l.attr)("boolean"),O=(0,r.computed)("ServiceID"),P=(0,r.computed)("Type"),x=class extends t.default{constructor(){super(...arguments),L(this,"Name",w,this),L(this,"CheckID",j,this),L(this,"Type",_,this),L(this,"Status",k,this),L(this,"Notes",S,this),L(this,"Output",N,this),L(this,"ServiceName",C,this),L(this,"ServiceID",z,this),L(this,"Node",M,this),L(this,"ServiceTags",D,this),L(this,"Definition",T,this),L(this,"Exposed",E,this)}get Kind(){return""===this.ServiceID?"node":"service"}get Exposable(){return["http","grpc"].includes(this.Type)}},w=A(x.prototype,"Name",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=A(x.prototype,"CheckID",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=A(x.prototype,"Type",[u,s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=A(x.prototype,"Status",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=A(x.prototype,"Notes",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=A(x.prototype,"Output",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=A(x.prototype,"ServiceName",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=A(x.prototype,"ServiceID",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=A(x.prototype,"Node",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=A(x.prototype,"ServiceTags",[b,y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=A(x.prototype,"Definition",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=A(x.prototype,"Exposed",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A(x.prototype,"Kind",[O],Object.getOwnPropertyDescriptor(x.prototype,"Kind"),x.prototype),A(x.prototype,"Exposable",[P],Object.getOwnPropertyDescriptor(x.prototype,"Exposable"),x.prototype),x) -e.default=R})),define("consul-ui/models/intention-permission-http-header",["exports","ember-data-model-fragments/fragment","@ember-data/model","@ember/object","@ember/object/computed"],(function(e,t,n,l,r){var i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O -function P(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function x(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.schema=void 0 -const w={Name:{required:!0},HeaderType:{allowedValues:["Exact","Prefix","Suffix","Regex","Present"]}} -e.schema=w -let j=(i=(0,n.attr)("string"),o=(0,n.attr)("string"),a=(0,n.attr)("string"),u=(0,n.attr)("string"),s=(0,n.attr)("string"),c=(0,n.attr)(),d=(0,r.or)(...w.HeaderType.allowedValues),p=(0,l.computed)(...w.HeaderType.allowedValues),f=class extends t.default{constructor(){super(...arguments),P(this,"Name",m,this),P(this,"Exact",h,this),P(this,"Prefix",b,this),P(this,"Suffix",y,this),P(this,"Regex",g,this),P(this,"Present",v,this),P(this,"Value",O,this)}get HeaderType(){return w.HeaderType.allowedValues.find((e=>void 0!==this[e]))}},m=x(f.prototype,"Name",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=x(f.prototype,"Exact",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=x(f.prototype,"Prefix",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=x(f.prototype,"Suffix",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=x(f.prototype,"Regex",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=x(f.prototype,"Present",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=x(f.prototype,"Value",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x(f.prototype,"HeaderType",[p],Object.getOwnPropertyDescriptor(f.prototype,"HeaderType"),f.prototype),f) -e.default=j})),define("consul-ui/models/intention-permission-http",["exports","ember-data-model-fragments/fragment","ember-data-model-fragments/attributes","@ember-data/model","@ember/object","@ember/object/computed"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m,h,b,y,g,v -function O(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function P(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.schema=void 0 -const x={PathType:{allowedValues:["PathPrefix","PathExact","PathRegex"]},Methods:{allowedValues:["GET","HEAD","POST","PUT","DELETE","CONNECT","OPTIONS","TRACE","PATCH"]}} -e.schema=x -let w=(o=(0,l.attr)("string"),a=(0,l.attr)("string"),u=(0,l.attr)("string"),s=(0,n.fragmentArray)("intention-permission-http-header"),c=(0,n.array)("string"),d=(0,i.or)(...x.PathType.allowedValues),p=(0,r.computed)(...x.PathType.allowedValues),f=class extends t.default{constructor(){super(...arguments),O(this,"PathExact",m,this),O(this,"PathPrefix",h,this),O(this,"PathRegex",b,this),O(this,"Header",y,this),O(this,"Methods",g,this),O(this,"Path",v,this)}get PathType(){return x.PathType.allowedValues.find((e=>"string"==typeof this[e]))}},m=P(f.prototype,"PathExact",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=P(f.prototype,"PathPrefix",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=P(f.prototype,"PathRegex",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=P(f.prototype,"Header",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=P(f.prototype,"Methods",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=P(f.prototype,"Path",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P(f.prototype,"PathType",[p],Object.getOwnPropertyDescriptor(f.prototype,"PathType"),f.prototype),f) -e.default=w})),define("consul-ui/models/intention-permission",["exports","ember-data-model-fragments/fragment","ember-data-model-fragments/attributes","@ember-data/model"],(function(e,t,n,l){var r,i,o,a,u -function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.schema=void 0 -const d={Action:{defaultValue:"allow",allowedValues:["allow","deny"]}} -e.schema=d -let p=(r=(0,l.attr)("string",{defaultValue:()=>d.Action.defaultValue}),i=(0,n.fragment)("intention-permission-http"),o=class extends t.default{constructor(){super(...arguments),s(this,"Action",a,this),s(this,"HTTP",u,this)}},a=c(o.prototype,"Action",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(o.prototype,"HTTP",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) -e.default=p})),define("consul-ui/models/intention",["exports","@ember-data/model","@ember/object","ember-data-model-fragments/attributes","consul-ui/decorators/replace"],(function(e,t,n,l,r){var i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D,T,E,L,A,R,I,$,F,U,B,q,K,H,Y,G,V,W,Z,Q,J,X,ee,te,ne -function le(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function re(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="ID" -let ie=(i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,r.default)("",void 0),c=(0,t.attr)("string"),d=(0,t.attr)("string",{defaultValue:()=>"*"}),p=(0,t.attr)("string",{defaultValue:()=>"*"}),f=(0,t.attr)("string",{defaultValue:()=>"default"}),m=(0,t.attr)("string",{defaultValue:()=>"default"}),h=(0,t.attr)("string",{defaultValue:()=>"default"}),b=(0,t.attr)("string",{defaultValue:()=>"default"}),y=(0,t.attr)("number"),g=(0,t.attr)("string",{defaultValue:()=>"consul"}),v=(0,r.nullValue)(void 0),O=(0,t.attr)("string"),P=(0,t.attr)("string"),x=(0,t.attr)("boolean",{defaultValue:()=>!0}),w=(0,t.attr)("number"),j=(0,t.attr)("date"),_=(0,t.attr)("date"),k=(0,t.attr)("number"),S=(0,t.attr)("number"),N=(0,t.attr)(),C=(0,t.attr)({defaultValue:()=>[]}),z=(0,l.fragmentArray)("intention-permission"),M=(0,n.computed)("Meta"),D=class extends t.default{constructor(){super(...arguments),le(this,"uid",T,this),le(this,"ID",E,this),le(this,"Datacenter",L,this),le(this,"Description",A,this),le(this,"SourcePeer",R,this),le(this,"SourceName",I,this),le(this,"DestinationName",$,this),le(this,"SourceNS",F,this),le(this,"DestinationNS",U,this),le(this,"SourcePartition",B,this),le(this,"DestinationPartition",q,this),le(this,"Precedence",K,this),le(this,"SourceType",H,this),le(this,"Action",Y,this),le(this,"LegacyID",G,this),le(this,"Legacy",V,this),le(this,"SyncTime",W,this),le(this,"CreatedAt",Z,this),le(this,"UpdatedAt",Q,this),le(this,"CreateIndex",J,this),le(this,"ModifyIndex",X,this),le(this,"Meta",ee,this),le(this,"Resources",te,this),le(this,"Permissions",ne,this)}get IsManagedByCRD(){return void 0!==Object.entries(this.Meta||{}).find((e=>{let[t,n]=e -return"external-source"===t&&"kubernetes"===n}))}},T=re(D.prototype,"uid",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=re(D.prototype,"ID",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=re(D.prototype,"Datacenter",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=re(D.prototype,"Description",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R=re(D.prototype,"SourcePeer",[s,c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=re(D.prototype,"SourceName",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),$=re(D.prototype,"DestinationName",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),F=re(D.prototype,"SourceNS",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),U=re(D.prototype,"DestinationNS",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),B=re(D.prototype,"SourcePartition",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),q=re(D.prototype,"DestinationPartition",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),K=re(D.prototype,"Precedence",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),H=re(D.prototype,"SourceType",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Y=re(D.prototype,"Action",[v,O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),G=re(D.prototype,"LegacyID",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),V=re(D.prototype,"Legacy",[x],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),W=re(D.prototype,"SyncTime",[w],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Z=re(D.prototype,"CreatedAt",[j],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Q=re(D.prototype,"UpdatedAt",[_],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),J=re(D.prototype,"CreateIndex",[k],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),X=re(D.prototype,"ModifyIndex",[S],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ee=re(D.prototype,"Meta",[N],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),te=re(D.prototype,"Resources",[C],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ne=re(D.prototype,"Permissions",[z],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),re(D.prototype,"IsManagedByCRD",[M],Object.getOwnPropertyDescriptor(D.prototype,"IsManagedByCRD"),D.prototype),D) -e.default=ie})) -define("consul-ui/models/kv",["exports","@ember-data/model","@ember/object","consul-ui/utils/isFolder","consul-ui/decorators/replace"],(function(e,t,n,l,r){var i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D,T,E,L,A -function R(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function I(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="Key" -let $=(i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("number"),u=(0,t.attr)(),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,t.attr)("string"),p=(0,t.attr)("number"),f=(0,t.attr)("number"),m=(0,r.nullValue)(void 0),h=(0,t.attr)("string"),b=(0,t.attr)("number"),y=(0,t.attr)("number"),g=(0,t.attr)("string"),v=(0,t.attr)({defaultValue:()=>[]}),O=(0,n.computed)("isFolder"),P=(0,n.computed)("Key"),x=class extends t.default{constructor(){super(...arguments),R(this,"uid",w,this),R(this,"Key",j,this),R(this,"SyncTime",_,this),R(this,"meta",k,this),R(this,"Datacenter",S,this),R(this,"Namespace",N,this),R(this,"Partition",C,this),R(this,"LockIndex",z,this),R(this,"Flags",M,this),R(this,"Value",D,this),R(this,"CreateIndex",T,this),R(this,"ModifyIndex",E,this),R(this,"Session",L,this),R(this,"Resources",A,this)}get Kind(){return this.isFolder?"folder":"key"}get isFolder(){return(0,l.default)(this.Key||"")}},w=I(x.prototype,"uid",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=I(x.prototype,"Key",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=I(x.prototype,"SyncTime",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=I(x.prototype,"meta",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=I(x.prototype,"Datacenter",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=I(x.prototype,"Namespace",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=I(x.prototype,"Partition",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=I(x.prototype,"LockIndex",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=I(x.prototype,"Flags",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=I(x.prototype,"Value",[m,h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=I(x.prototype,"CreateIndex",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=I(x.prototype,"ModifyIndex",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=I(x.prototype,"Session",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=I(x.prototype,"Resources",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I(x.prototype,"Kind",[O],Object.getOwnPropertyDescriptor(x.prototype,"Kind"),x.prototype),I(x.prototype,"isFolder",[P],Object.getOwnPropertyDescriptor(x.prototype,"isFolder"),x.prototype),x) -e.default=$})),define("consul-ui/models/license",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,g -function v(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function O(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uri" -let P=(n=(0,t.attr)("string"),l=(0,t.attr)("boolean"),r=(0,t.attr)("number"),i=(0,t.attr)(),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)(),c=class extends t.default{constructor(){super(...arguments),v(this,"uri",d,this),v(this,"Valid",p,this),v(this,"SyncTime",f,this),v(this,"meta",m,this),v(this,"Datacenter",h,this),v(this,"Namespace",b,this),v(this,"Partition",y,this),v(this,"License",g,this)}},d=O(c.prototype,"uri",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=O(c.prototype,"Valid",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=O(c.prototype,"SyncTime",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=O(c.prototype,"meta",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=O(c.prototype,"Datacenter",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=O(c.prototype,"Namespace",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=O(c.prototype,"Partition",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=O(c.prototype,"License",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c) -e.default=P})),define("consul-ui/models/node",["exports","@ember-data/model","@ember/object","@ember/object/computed","ember-data-model-fragments/attributes"],(function(e,t,n,l,r){var i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D,T,E,L,A,R,I,$,F,U,B,q,K,H,Y,G -function V(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function W(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="ID" -let Z=(i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,t.attr)("string"),p=(0,t.attr)("number"),f=(0,t.attr)("number"),m=(0,t.attr)("number"),h=(0,t.attr)(),b=(0,t.attr)(),y=(0,t.attr)(),g=(0,t.attr)({defaultValue:()=>[]}),v=(0,t.hasMany)("service-instance"),O=(0,r.fragmentArray)("health-check"),P=(0,l.filter)("Services",(e=>"connect-proxy"!==e.Service.Kind)),x=(0,l.filter)("Services",(e=>"connect-proxy"===e.Service.Kind)),w=(0,l.filter)("Checks",(e=>""===e.ServiceID)),j=(0,n.computed)("ChecksCritical","ChecksPassing","ChecksWarning"),_=(0,n.computed)("NodeChecks.[]"),k=(0,n.computed)("NodeChecks.[]"),S=(0,n.computed)("NodeChecks.[]"),N=class extends t.default{constructor(){super(...arguments),V(this,"uid",C,this),V(this,"ID",z,this),V(this,"Datacenter",M,this),V(this,"PeerName",D,this),V(this,"Partition",T,this),V(this,"Address",E,this),V(this,"Node",L,this),V(this,"SyncTime",A,this),V(this,"CreateIndex",R,this),V(this,"ModifyIndex",I,this),V(this,"meta",$,this),V(this,"Meta",F,this),V(this,"TaggedAddresses",U,this),V(this,"Resources",B,this),V(this,"Services",q,this),V(this,"Checks",K,this),V(this,"MeshServiceInstances",H,this),V(this,"ProxyServiceInstances",Y,this),V(this,"NodeChecks",G,this)}get Status(){switch(!0){case 0!==this.ChecksCritical:return"critical" -case 0!==this.ChecksWarning:return"warning" -case 0!==this.ChecksPassing:return"passing" -default:return"empty"}}get ChecksCritical(){return this.NodeChecks.filter((e=>"critical"===e.Status)).length}get ChecksPassing(){return this.NodeChecks.filter((e=>"passing"===e.Status)).length}get ChecksWarning(){return this.NodeChecks.filter((e=>"warning"===e.Status)).length}},C=W(N.prototype,"uid",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=W(N.prototype,"ID",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=W(N.prototype,"Datacenter",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=W(N.prototype,"PeerName",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=W(N.prototype,"Partition",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=W(N.prototype,"Address",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=W(N.prototype,"Node",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=W(N.prototype,"SyncTime",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R=W(N.prototype,"CreateIndex",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=W(N.prototype,"ModifyIndex",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),$=W(N.prototype,"meta",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),F=W(N.prototype,"Meta",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),U=W(N.prototype,"TaggedAddresses",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),B=W(N.prototype,"Resources",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),q=W(N.prototype,"Services",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),K=W(N.prototype,"Checks",[O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),H=W(N.prototype,"MeshServiceInstances",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Y=W(N.prototype,"ProxyServiceInstances",[x],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),G=W(N.prototype,"NodeChecks",[w],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),W(N.prototype,"Status",[j],Object.getOwnPropertyDescriptor(N.prototype,"Status"),N.prototype),W(N.prototype,"ChecksCritical",[_],Object.getOwnPropertyDescriptor(N.prototype,"ChecksCritical"),N.prototype),W(N.prototype,"ChecksPassing",[k],Object.getOwnPropertyDescriptor(N.prototype,"ChecksPassing"),N.prototype),W(N.prototype,"ChecksWarning",[S],Object.getOwnPropertyDescriptor(N.prototype,"ChecksWarning"),N.prototype),N) -e.default=Z})),define("consul-ui/models/nspace",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x -function w(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function j(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.NSPACE_KEY=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="Name" -e.NSPACE_KEY="Namespace" -let _=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("number"),u=(0,t.attr)("string",{defaultValue:()=>""}),s=(0,t.attr)({defaultValue:()=>[]}),c=(0,t.attr)("string"),d=(0,t.attr)({defaultValue:()=>({PolicyDefaults:[],RoleDefaults:[]})}),p=class extends t.default{constructor(){super(...arguments),w(this,"uid",f,this),w(this,"Name",m,this),w(this,"Datacenter",h,this),w(this,"Partition",b,this),w(this,"Namespace",y,this),w(this,"SyncTime",g,this),w(this,"Description",v,this),w(this,"Resources",O,this),w(this,"DeletedAt",P,this),w(this,"ACLs",x,this)}},f=j(p.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=j(p.prototype,"Name",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=j(p.prototype,"Datacenter",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=j(p.prototype,"Partition",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=j(p.prototype,"Namespace",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=j(p.prototype,"SyncTime",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=j(p.prototype,"Description",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=j(p.prototype,"Resources",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=j(p.prototype,"DeletedAt",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=j(p.prototype,"ACLs",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p) -e.default=_})),define("consul-ui/models/oidc-provider",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O -function P(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function x(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="Name" -let w=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)(),d=class extends t.default{constructor(){super(...arguments),P(this,"uid",p,this),P(this,"Name",f,this),P(this,"Datacenter",m,this),P(this,"Namespace",h,this),P(this,"Partition",b,this),P(this,"Kind",y,this),P(this,"AuthURL",g,this),P(this,"DisplayName",v,this),P(this,"meta",O,this)}},p=x(d.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=x(d.prototype,"Name",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=x(d.prototype,"Datacenter",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=x(d.prototype,"Namespace",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=x(d.prototype,"Partition",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=x(d.prototype,"Kind",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=x(d.prototype,"AuthURL",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=x(d.prototype,"DisplayName",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=x(d.prototype,"meta",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d) -e.default=w})),define("consul-ui/models/partition",["exports","ember-data/model","ember-data/attr"],(function(e,t,n){var l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P -function x(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function w(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.PARTITION_KEY=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="Name" -e.PARTITION_KEY="Partition" -let j=(l=(0,n.default)("string"),r=(0,n.default)("string"),i=(0,n.default)("string"),o=(0,n.default)("string"),a=(0,n.default)("string"),u=(0,n.default)("string"),s=(0,n.default)("string"),c=(0,n.default)("number"),d=(0,n.default)(),p=class extends t.default{constructor(){super(...arguments),x(this,"uid",f,this),x(this,"Name",m,this),x(this,"Description",h,this),x(this,"DeletedAt",b,this),x(this,"Datacenter",y,this),x(this,"Namespace",g,this),x(this,"Partition",v,this),x(this,"SyncTime",O,this),x(this,"meta",P,this)}},f=w(p.prototype,"uid",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=w(p.prototype,"Name",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=w(p.prototype,"Description",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=w(p.prototype,"DeletedAt",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=w(p.prototype,"Datacenter",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=w(p.prototype,"Namespace",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=w(p.prototype,"Partition",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=w(p.prototype,"SyncTime",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=w(p.prototype,"meta",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p) -e.default=j})),define("consul-ui/models/peer",["exports","@ember-data/model","consul-ui/decorators/replace"],(function(e,t,n){var l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D,T,E,L,A,R,I -function $(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function F(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.schema=void 0 -e.schema={State:{defaultValue:"PENDING",allowedValues:["PENDING","ESTABLISHING","ACTIVE","FAILING","TERMINATED","DELETING"]}} -let U=(l=(0,t.attr)("string"),r=(0,t.attr)(),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,n.nullValue)([]),p=(0,t.attr)(),f=(0,t.attr)("string"),m=(0,t.attr)(),h=(0,n.nullValue)([]),b=(0,t.attr)(),y=(0,n.nullValue)([]),g=(0,t.attr)(),v=(0,t.attr)("date"),O=(0,t.attr)("date"),P=(0,t.attr)("date"),x=class extends t.default{constructor(){super(...arguments),$(this,"uri",w,this),$(this,"meta",j,this),$(this,"Datacenter",_,this),$(this,"Partition",k,this),$(this,"Name",S,this),$(this,"State",N,this),$(this,"ID",C,this),$(this,"ServerExternalAddresses",z,this),$(this,"ServerExternalAddresses",M,this),$(this,"PeerID",D,this),$(this,"PeerServerAddresses",T,this),$(this,"ImportedServices",E,this),$(this,"ExportedServices",L,this),$(this,"LastHeartbeat",A,this),$(this,"LastReceive",R,this),$(this,"LastSend",I,this)}get ImportedServiceCount(){return this.ImportedServices.length}get ExportedServiceCount(){return this.ExportedServices.length}get isReceiver(){return this.PeerID}get isDialer(){return!this.isReceiver}},w=F(x.prototype,"uri",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=F(x.prototype,"meta",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=F(x.prototype,"Datacenter",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=F(x.prototype,"Partition",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=F(x.prototype,"Name",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=F(x.prototype,"State",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=F(x.prototype,"ID",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=F(x.prototype,"ServerExternalAddresses",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=F(x.prototype,"ServerExternalAddresses",[d,p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=F(x.prototype,"PeerID",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=F(x.prototype,"PeerServerAddresses",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=F(x.prototype,"ImportedServices",[h,b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=F(x.prototype,"ExportedServices",[y,g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=F(x.prototype,"LastHeartbeat",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R=F(x.prototype,"LastReceive",[O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=F(x.prototype,"LastSend",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x) -e.default=U})),define("consul-ui/models/permission",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c -function d(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function p(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let f=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("boolean"),o=class extends t.default{constructor(){super(...arguments),d(this,"Resource",a,this),d(this,"Segment",u,this),d(this,"Access",s,this),d(this,"Allow",c,this)}},a=p(o.prototype,"Resource",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=p(o.prototype,"Segment",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s=p(o.prototype,"Access",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=p(o.prototype,"Allow",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) -e.default=f})),define("consul-ui/models/policy",["exports","@ember-data/model","@ember/object"],(function(e,t,n){var l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D,T,E -function L(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function A(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=e.MANAGEMENT_ID=void 0 -const R="00000000-0000-0000-0000-000000000001" -e.MANAGEMENT_ID=R -e.PRIMARY_KEY="uid" -e.SLUG_KEY="ID" -let I=(l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string",{defaultValue:()=>""}),s=(0,t.attr)("string",{defaultValue:()=>""}),c=(0,t.attr)("string",{defaultValue:()=>""}),d=(0,t.attr)("number"),p=(0,t.attr)("number"),f=(0,t.attr)("number"),m=(0,t.attr)(),h=(0,t.attr)(),b=(0,t.attr)("string",{defaultValue:()=>""}),y=(0,t.attr)("number",{defaultValue:()=>(new Date).getTime()}),g=(0,n.computed)("ID"),v=class extends t.default{constructor(){super(...arguments),L(this,"uid",O,this),L(this,"ID",P,this),L(this,"Datacenter",x,this),L(this,"Namespace",w,this),L(this,"Partition",j,this),L(this,"Name",_,this),L(this,"Description",k,this),L(this,"Rules",S,this),L(this,"SyncTime",N,this),L(this,"CreateIndex",C,this),L(this,"ModifyIndex",z,this),L(this,"Datacenters",M,this),L(this,"meta",D,this),L(this,"template",T,this),L(this,"CreateTime",E,this)}get isGlobalManagement(){return this.ID===R}},O=A(v.prototype,"uid",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=A(v.prototype,"ID",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=A(v.prototype,"Datacenter",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=A(v.prototype,"Namespace",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=A(v.prototype,"Partition",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=A(v.prototype,"Name",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=A(v.prototype,"Description",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=A(v.prototype,"Rules",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=A(v.prototype,"SyncTime",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=A(v.prototype,"CreateIndex",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=A(v.prototype,"ModifyIndex",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=A(v.prototype,"Datacenters",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=A(v.prototype,"meta",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=A(v.prototype,"template",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=A(v.prototype,"CreateTime",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A(v.prototype,"isGlobalManagement",[g],Object.getOwnPropertyDescriptor(v.prototype,"isGlobalManagement"),v.prototype),v) -e.default=I})),define("consul-ui/models/proxy",["exports","@ember-data/model","consul-ui/models/service-instance"],(function(e,t,n){var l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w -function j(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function _(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="Node,ServiceID" -let k=(l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,t.attr)("number"),p=(0,t.attr)(),f=class extends n.default{constructor(){super(...arguments),j(this,"uid",m,this),j(this,"ID",h,this),j(this,"Datacenter",b,this),j(this,"Namespace",y,this),j(this,"Partition",g,this),j(this,"ServiceName",v,this),j(this,"ServiceID",O,this),j(this,"NodeName",P,this),j(this,"SyncTime",x,this),j(this,"ServiceProxy",w,this)}},m=_(f.prototype,"uid",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=_(f.prototype,"ID",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=_(f.prototype,"Datacenter",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=_(f.prototype,"Namespace",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=_(f.prototype,"Partition",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=_(f.prototype,"ServiceName",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=_(f.prototype,"ServiceID",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=_(f.prototype,"NodeName",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=_(f.prototype,"SyncTime",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=_(f.prototype,"ServiceProxy",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f) -e.default=k})),define("consul-ui/models/role",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D,T,E -function L(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function A(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="ID" -let R=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string",{defaultValue:()=>""}),u=(0,t.attr)("string",{defaultValue:()=>""}),s=(0,t.attr)({defaultValue:()=>[]}),c=(0,t.attr)({defaultValue:()=>[]}),d=(0,t.attr)({defaultValue:()=>[]}),p=(0,t.attr)("number"),f=(0,t.attr)("number"),m=(0,t.attr)("number"),h=(0,t.attr)("number"),b=(0,t.attr)(),y=(0,t.attr)("string"),g=class extends t.default{constructor(){super(...arguments),L(this,"uid",v,this),L(this,"ID",O,this),L(this,"Datacenter",P,this),L(this,"Namespace",x,this),L(this,"Partition",w,this),L(this,"Name",j,this),L(this,"Description",_,this),L(this,"Policies",k,this),L(this,"ServiceIdentities",S,this),L(this,"NodeIdentities",N,this),L(this,"SyncTime",C,this),L(this,"CreateIndex",z,this),L(this,"ModifyIndex",M,this),L(this,"CreateTime",D,this),L(this,"Datacenters",T,this),L(this,"Hash",E,this)}},v=A(g.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=A(g.prototype,"ID",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=A(g.prototype,"Datacenter",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=A(g.prototype,"Namespace",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=A(g.prototype,"Partition",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=A(g.prototype,"Name",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=A(g.prototype,"Description",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=A(g.prototype,"Policies",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=A(g.prototype,"ServiceIdentities",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=A(g.prototype,"NodeIdentities",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=A(g.prototype,"SyncTime",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=A(g.prototype,"CreateIndex",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=A(g.prototype,"ModifyIndex",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=A(g.prototype,"CreateTime",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=A(g.prototype,"Datacenters",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=A(g.prototype,"Hash",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g) -e.default=R})),define("consul-ui/models/service-instance",["exports","@ember-data/model","ember-data-model-fragments/attributes","@ember/object","@ember/object/computed","@glimmer/tracking"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D,T,E,L,A,R,I,$,F,U,B,q,K,H,Y,G,V,W,Z,Q,J,X,ee,te,ne,le -function re(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function ie(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.Collection=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="Node.Node,Service.ID" -const oe=(a=ie((o=class{constructor(e){re(this,"items",a,this),this.items=e}get ExternalSources(){const e=this.items.reduce((function(e,t){return e.concat(t.ExternalSources||[])}),[]) -return[...new Set(e)].filter(Boolean).sort()}}).prototype,"items",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) -e.Collection=oe -let ae=(u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)(),d=(0,t.attr)(),p=(0,t.attr)(),f=(0,n.fragmentArray)("health-check"),m=(0,t.attr)("number"),h=(0,t.attr)(),b=(0,t.attr)({defaultValue:()=>[]}),y=(0,r.alias)("Service.Service"),g=(0,r.or)("Service.{ID,Service}"),v=(0,r.or)("Service.Address","Node.Service"),O=(0,t.attr)("string"),P=(0,r.alias)("Service.Tags"),x=(0,r.alias)("Service.Meta"),w=(0,r.alias)("Service.Namespace"),j=(0,r.alias)("Service.Partition"),_=(0,r.filter)("Checks.@each.Kind",((e,t,n)=>"service"===e.Kind)),k=(0,r.filter)("Checks.@each.Kind",((e,t,n)=>"node"===e.Kind)),S=(0,l.computed)("Service.Meta"),N=(0,l.computed)("Service.Kind"),C=(0,l.computed)("Service.Kind"),z=(0,l.computed)("IsOrigin"),M=(0,l.computed)("ChecksPassing","ChecksWarning","ChecksCritical"),D=(0,l.computed)("Checks.[]"),T=(0,l.computed)("Checks.[]"),E=(0,l.computed)("Checks.[]"),L=(0,l.computed)("Checks.[]","ChecksPassing"),A=(0,l.computed)("Checks.[]","ChecksWarning"),R=(0,l.computed)("Checks.[]","ChecksCritical"),I=class extends t.default{constructor(){super(...arguments),re(this,"uid",$,this),re(this,"Datacenter",F,this),re(this,"Proxy",U,this),re(this,"Node",B,this),re(this,"Service",q,this),re(this,"Checks",K,this),re(this,"SyncTime",H,this),re(this,"meta",Y,this),re(this,"Resources",G,this),re(this,"Name",V,this),re(this,"ID",W,this),re(this,"Address",Z,this),re(this,"SocketPath",Q,this),re(this,"Tags",J,this),re(this,"Meta",X,this),re(this,"Namespace",ee,this),re(this,"Partition",te,this),re(this,"ServiceChecks",ne,this),re(this,"NodeChecks",le,this)}get ExternalSources(){const e=Object.entries(this.Service.Meta||{}).filter((e=>{let[t,n]=e -return"external-source"===t})).map((e=>{let[t,n]=e -return n})) -return[...new Set(e)]}get IsProxy(){return["connect-proxy","mesh-gateway","ingress-gateway","terminating-gateway","api-gateway"].includes(this.Service.Kind)}get IsOrigin(){return!["connect-proxy","mesh-gateway"].includes(this.Service.Kind)}get IsMeshOrigin(){return this.IsOrigin&&!["terminating-gateway"].includes(this.Service.Kind)}get Status(){switch(!0){case 0!==this.ChecksCritical.length:return"critical" -case 0!==this.ChecksWarning.length:return"warning" -case 0!==this.ChecksPassing.length:return"passing" -default:return"empty"}}get ChecksPassing(){return this.Checks.filter((e=>"passing"===e.Status))}get ChecksWarning(){return this.Checks.filter((e=>"warning"===e.Status))}get ChecksCritical(){return this.Checks.filter((e=>"critical"===e.Status))}get PercentageChecksPassing(){return this.ChecksPassing.length/this.Checks.length*100}get PercentageChecksWarning(){return this.ChecksWarning.length/this.Checks.length*100}get PercentageChecksCritical(){return this.ChecksCritical.length/this.Checks.length*100}},$=ie(I.prototype,"uid",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),F=ie(I.prototype,"Datacenter",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),U=ie(I.prototype,"Proxy",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),B=ie(I.prototype,"Node",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),q=ie(I.prototype,"Service",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),K=ie(I.prototype,"Checks",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),H=ie(I.prototype,"SyncTime",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Y=ie(I.prototype,"meta",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),G=ie(I.prototype,"Resources",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),V=ie(I.prototype,"Name",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),W=ie(I.prototype,"ID",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Z=ie(I.prototype,"Address",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Q=ie(I.prototype,"SocketPath",[O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),J=ie(I.prototype,"Tags",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),X=ie(I.prototype,"Meta",[x],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ee=ie(I.prototype,"Namespace",[w],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),te=ie(I.prototype,"Partition",[j],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ne=ie(I.prototype,"ServiceChecks",[_],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),le=ie(I.prototype,"NodeChecks",[k],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ie(I.prototype,"ExternalSources",[S],Object.getOwnPropertyDescriptor(I.prototype,"ExternalSources"),I.prototype),ie(I.prototype,"IsProxy",[N],Object.getOwnPropertyDescriptor(I.prototype,"IsProxy"),I.prototype),ie(I.prototype,"IsOrigin",[C],Object.getOwnPropertyDescriptor(I.prototype,"IsOrigin"),I.prototype),ie(I.prototype,"IsMeshOrigin",[z],Object.getOwnPropertyDescriptor(I.prototype,"IsMeshOrigin"),I.prototype),ie(I.prototype,"Status",[M],Object.getOwnPropertyDescriptor(I.prototype,"Status"),I.prototype),ie(I.prototype,"ChecksPassing",[D],Object.getOwnPropertyDescriptor(I.prototype,"ChecksPassing"),I.prototype),ie(I.prototype,"ChecksWarning",[T],Object.getOwnPropertyDescriptor(I.prototype,"ChecksWarning"),I.prototype),ie(I.prototype,"ChecksCritical",[E],Object.getOwnPropertyDescriptor(I.prototype,"ChecksCritical"),I.prototype),ie(I.prototype,"PercentageChecksPassing",[L],Object.getOwnPropertyDescriptor(I.prototype,"PercentageChecksPassing"),I.prototype),ie(I.prototype,"PercentageChecksWarning",[A],Object.getOwnPropertyDescriptor(I.prototype,"PercentageChecksWarning"),I.prototype),ie(I.prototype,"PercentageChecksCritical",[R],Object.getOwnPropertyDescriptor(I.prototype,"PercentageChecksCritical"),I.prototype),I) -e.default=ae})),define("consul-ui/models/service",["exports","@ember-data/model","@ember/object","@glimmer/tracking","ember-data-model-fragments/attributes","consul-ui/decorators/replace"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D,T,E,L,A,R,I,$,F,U,B,q,K,H,Y,G,V,W,Z,Q,J,X,ee,te,ne,le,re,ie,oe,ae,ue,se,ce,de,pe,fe,me,he,be,ye,ge -function ve(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function Oe(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.Collection=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="Name,PeerName" -const Pe=(a=Oe((o=class{constructor(e){ve(this,"items",a,this),this.items=e}get ExternalSources(){const e=this.items.reduce((function(e,t){return e.concat(t.ExternalSources||[])}),[]) -return[...new Set(e)].filter(Boolean).sort()}get Partitions(){return[...new Set(this.items.map((e=>e.Partition)))].sort()}}).prototype,"items",[l.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) -e.Collection=Pe -let xe=(u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,t.attr)("string"),p=(0,t.attr)("string"),f=(0,t.attr)("string"),m=(0,i.default)("",void 0),h=(0,t.attr)("string"),b=(0,t.attr)("number"),y=(0,t.attr)("number"),g=(0,t.attr)("number"),v=(0,t.attr)("number"),O=(0,t.attr)("boolean"),P=(0,t.attr)("boolean"),x=(0,t.attr)({defaultValue:()=>[]}),w=(0,t.attr)("number"),j=(0,t.attr)("number"),_=(0,t.attr)("number"),k=(0,i.nullValue)([]),S=(0,t.attr)({defaultValue:()=>[]}),N=(0,t.attr)(),C=(0,t.attr)(),z=(0,r.fragment)("gateway-config"),M=(0,i.nullValue)([]),D=(0,t.attr)(),T=(0,t.attr)(),E=(0,t.attr)(),L=(0,t.belongsTo)({async:!1}),A=(0,n.computed)("peer","InstanceCount"),R=(0,n.computed)("peer.State"),I=(0,n.computed)("ChecksPassing","ChecksWarning","ChecksCritical"),$=(0,n.computed)("MeshChecksPassing","MeshChecksWarning","MeshChecksCritical"),F=(0,n.computed)("ConnectedWithProxy","ConnectedWithGateway"),U=(0,n.computed)("MeshEnabled","Kind"),B=(0,n.computed)("MeshChecksPassing","MeshChecksWarning","MeshChecksCritical","isZeroCountButPeered","peerIsFailing"),q=(0,n.computed)("isZeroCountButPeered","peerIsFailing","MeshStatus"),K=(0,n.computed)("ChecksPassing","Proxy.ChecksPassing"),H=(0,n.computed)("ChecksWarning","Proxy.ChecksWarning"),Y=(0,n.computed)("ChecksCritical","Proxy.ChecksCritical"),G=class extends t.default{constructor(){super(...arguments),ve(this,"uid",V,this),ve(this,"Name",W,this),ve(this,"Datacenter",Z,this),ve(this,"Namespace",Q,this),ve(this,"Partition",J,this),ve(this,"Kind",X,this),ve(this,"PeerName",ee,this),ve(this,"ChecksPassing",te,this),ve(this,"ChecksCritical",ne,this),ve(this,"ChecksWarning",le,this),ve(this,"InstanceCount",re,this),ve(this,"ConnectedWithGateway",ie,this),ve(this,"ConnectedWithProxy",oe,this),ve(this,"Resources",ae,this),ve(this,"SyncTime",ue,this),ve(this,"CreateIndex",se,this),ve(this,"ModifyIndex",ce,this),ve(this,"Tags",de,this),ve(this,"Nodes",pe,this),ve(this,"Proxy",fe,this),ve(this,"GatewayConfig",me,this),ve(this,"ExternalSources",he,this),ve(this,"Meta",be,this),ve(this,"meta",ye,this),ve(this,"peer",ge,this)}get isZeroCountButPeered(){return this.peer&&0===this.InstanceCount}get peerIsFailing(){return this.peer&&"FAILING"===this.peer.State}get ChecksTotal(){return this.ChecksPassing+this.ChecksWarning+this.ChecksCritical}get MeshChecksTotal(){return this.MeshChecksPassing+this.MeshChecksWarning+this.MeshChecksCritical}get MeshEnabled(){return this.ConnectedWithProxy||this.ConnectedWithGateway}get InMesh(){return this.MeshEnabled||(this.Kind||"").length>0}get MeshStatus(){switch(!0){case this.isZeroCountButPeered:case this.peerIsFailing:return"unknown" -case 0!==this.MeshChecksCritical:return"critical" -case 0!==this.MeshChecksWarning:return"warning" -case 0!==this.MeshChecksPassing:return"passing" -default:return"empty"}}get healthTooltipText(){const{MeshStatus:e,isZeroCountButPeered:t,peerIsFailing:n}=this -return t?"This service currently has 0 instances. Check with the operator of its peer to make sure this is expected behavior.":n?"This peer is out of sync, so the current health statuses of its services are unknown.":"critical"===e?"At least one health check on one instance is failing.":"warning"===e?"At least one health check on one instance has a warning.":"passing"==e?"All health checks are passing.":"There are no health checks"}get MeshChecksPassing(){let e=0 -return void 0!==this.Proxy&&(e=this.Proxy.ChecksPassing),this.ChecksPassing+e}get MeshChecksWarning(){let e=0 -return void 0!==this.Proxy&&(e=this.Proxy.ChecksWarning),this.ChecksWarning+e}get MeshChecksCritical(){let e=0 -return void 0!==this.Proxy&&(e=this.Proxy.ChecksCritical),this.ChecksCritical+e}},V=Oe(G.prototype,"uid",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),W=Oe(G.prototype,"Name",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Z=Oe(G.prototype,"Datacenter",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Q=Oe(G.prototype,"Namespace",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),J=Oe(G.prototype,"Partition",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),X=Oe(G.prototype,"Kind",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ee=Oe(G.prototype,"PeerName",[m,h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),te=Oe(G.prototype,"ChecksPassing",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ne=Oe(G.prototype,"ChecksCritical",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),le=Oe(G.prototype,"ChecksWarning",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),re=Oe(G.prototype,"InstanceCount",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ie=Oe(G.prototype,"ConnectedWithGateway",[O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),oe=Oe(G.prototype,"ConnectedWithProxy",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ae=Oe(G.prototype,"Resources",[x],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ue=Oe(G.prototype,"SyncTime",[w],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),se=Oe(G.prototype,"CreateIndex",[j],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ce=Oe(G.prototype,"ModifyIndex",[_],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),de=Oe(G.prototype,"Tags",[k,S],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),pe=Oe(G.prototype,"Nodes",[N],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),fe=Oe(G.prototype,"Proxy",[C],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),me=Oe(G.prototype,"GatewayConfig",[z],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),he=Oe(G.prototype,"ExternalSources",[M,D],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),be=Oe(G.prototype,"Meta",[T],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ye=Oe(G.prototype,"meta",[E],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ge=Oe(G.prototype,"peer",[L],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Oe(G.prototype,"isZeroCountButPeered",[A],Object.getOwnPropertyDescriptor(G.prototype,"isZeroCountButPeered"),G.prototype),Oe(G.prototype,"peerIsFailing",[R],Object.getOwnPropertyDescriptor(G.prototype,"peerIsFailing"),G.prototype),Oe(G.prototype,"ChecksTotal",[I],Object.getOwnPropertyDescriptor(G.prototype,"ChecksTotal"),G.prototype),Oe(G.prototype,"MeshChecksTotal",[$],Object.getOwnPropertyDescriptor(G.prototype,"MeshChecksTotal"),G.prototype),Oe(G.prototype,"MeshEnabled",[F],Object.getOwnPropertyDescriptor(G.prototype,"MeshEnabled"),G.prototype),Oe(G.prototype,"InMesh",[U],Object.getOwnPropertyDescriptor(G.prototype,"InMesh"),G.prototype),Oe(G.prototype,"MeshStatus",[B],Object.getOwnPropertyDescriptor(G.prototype,"MeshStatus"),G.prototype),Oe(G.prototype,"healthTooltipText",[q],Object.getOwnPropertyDescriptor(G.prototype,"healthTooltipText"),G.prototype),Oe(G.prototype,"MeshChecksPassing",[K],Object.getOwnPropertyDescriptor(G.prototype,"MeshChecksPassing"),G.prototype),Oe(G.prototype,"MeshChecksWarning",[H],Object.getOwnPropertyDescriptor(G.prototype,"MeshChecksWarning"),G.prototype),Oe(G.prototype,"MeshChecksCritical",[Y],Object.getOwnPropertyDescriptor(G.prototype,"MeshChecksCritical"),G.prototype),G) -e.default=xe})),define("consul-ui/models/session",["exports","@ember-data/model","@ember/object","consul-ui/decorators/replace"],(function(e,t,n,l){var r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D,T,E,L,A,R,I,$ -function F(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function U(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="ID" -let B=(r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,t.attr)("string"),p=(0,t.attr)("string"),f=(0,t.attr)("number"),m=(0,t.attr)("number"),h=(0,t.attr)("number"),b=(0,t.attr)("number"),y=(0,l.nullValue)([]),g=(0,t.attr)({defaultValue:()=>[]}),v=(0,l.nullValue)([]),O=(0,t.attr)({defaultValue:()=>[]}),P=(0,t.attr)({defaultValue:()=>[]}),x=(0,n.computed)("NodeChecks","ServiceChecks"),w=class extends t.default{constructor(){super(...arguments),F(this,"uid",j,this),F(this,"ID",_,this),F(this,"Name",k,this),F(this,"Datacenter",S,this),F(this,"Namespace",N,this),F(this,"Partition",C,this),F(this,"Node",z,this),F(this,"Behavior",M,this),F(this,"TTL",D,this),F(this,"LockDelay",T,this),F(this,"SyncTime",E,this),F(this,"CreateIndex",L,this),F(this,"ModifyIndex",A,this),F(this,"NodeChecks",R,this),F(this,"ServiceChecks",I,this),F(this,"Resources",$,this)}get checks(){return[...this.NodeChecks,...this.ServiceChecks.map((e=>{let{ID:t}=e -return t}))]}},j=U(w.prototype,"uid",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=U(w.prototype,"ID",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=U(w.prototype,"Name",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=U(w.prototype,"Datacenter",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=U(w.prototype,"Namespace",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=U(w.prototype,"Partition",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=U(w.prototype,"Node",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=U(w.prototype,"Behavior",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=U(w.prototype,"TTL",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=U(w.prototype,"LockDelay",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=U(w.prototype,"SyncTime",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=U(w.prototype,"CreateIndex",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=U(w.prototype,"ModifyIndex",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R=U(w.prototype,"NodeChecks",[y,g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=U(w.prototype,"ServiceChecks",[v,O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),$=U(w.prototype,"Resources",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),U(w.prototype,"checks",[x],Object.getOwnPropertyDescriptor(w.prototype,"checks"),w.prototype),w) -e.default=B})),define("consul-ui/models/token",["exports","@ember-data/model","@ember/object","consul-ui/models/policy"],(function(e,t,n,l){var r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z,M,D,T,E,L,A,R,I,$,F,U,B,q,K,H,Y,G,V,W,Z -function Q(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function J(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="AccessorID" -let X=(r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,t.attr)("boolean"),p=(0,t.attr)("boolean"),f=(0,t.attr)("string",{defaultValue:()=>""}),m=(0,t.attr)(),h=(0,t.attr)({defaultValue:()=>[]}),b=(0,t.attr)({defaultValue:()=>[]}),y=(0,t.attr)({defaultValue:()=>[]}),g=(0,t.attr)({defaultValue:()=>[]}),v=(0,t.attr)("date"),O=(0,t.attr)("string"),P=(0,t.attr)("number"),x=(0,t.attr)("number"),w=(0,t.attr)("string"),j=(0,t.attr)("string",{defaultValue:()=>""}),_=(0,t.attr)("string"),k=(0,n.computed)("Policies.[]"),S=(0,n.computed)("SecretID"),N=class extends t.default{constructor(){super(...arguments),Q(this,"uid",C,this),Q(this,"AccessorID",z,this),Q(this,"Datacenter",M,this),Q(this,"Namespace",D,this),Q(this,"Partition",T,this),Q(this,"IDPName",E,this),Q(this,"SecretID",L,this),Q(this,"Legacy",A,this),Q(this,"Local",R,this),Q(this,"Description",I,this),Q(this,"meta",$,this),Q(this,"Policies",F,this),Q(this,"Roles",U,this),Q(this,"ServiceIdentities",B,this),Q(this,"NodeIdentities",q,this),Q(this,"CreateTime",K,this),Q(this,"Hash",H,this),Q(this,"CreateIndex",Y,this),Q(this,"ModifyIndex",G,this),Q(this,"Type",V,this),Q(this,"Name",W,this),Q(this,"Rules",Z,this)}get isGlobalManagement(){return(this.Policies||[]).find((e=>e.ID===l.MANAGEMENT_ID))}get hasSecretID(){return""!==this.SecretID&&""!==this.SecretID}},C=J(N.prototype,"uid",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=J(N.prototype,"AccessorID",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=J(N.prototype,"Datacenter",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=J(N.prototype,"Namespace",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=J(N.prototype,"Partition",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=J(N.prototype,"IDPName",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=J(N.prototype,"SecretID",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=J(N.prototype,"Legacy",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R=J(N.prototype,"Local",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=J(N.prototype,"Description",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),$=J(N.prototype,"meta",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),F=J(N.prototype,"Policies",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),U=J(N.prototype,"Roles",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),B=J(N.prototype,"ServiceIdentities",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),q=J(N.prototype,"NodeIdentities",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),K=J(N.prototype,"CreateTime",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),H=J(N.prototype,"Hash",[O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Y=J(N.prototype,"CreateIndex",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),G=J(N.prototype,"ModifyIndex",[x],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),V=J(N.prototype,"Type",[w],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),W=J(N.prototype,"Name",[j],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Z=J(N.prototype,"Rules",[_],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),J(N.prototype,"isGlobalManagement",[k],Object.getOwnPropertyDescriptor(N.prototype,"isGlobalManagement"),N.prototype),J(N.prototype,"hasSecretID",[S],Object.getOwnPropertyDescriptor(N.prototype,"hasSecretID"),N.prototype),N) -e.default=X})),define("consul-ui/models/topology",["exports","@ember-data/model","@ember/object"],(function(e,t,n){var l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v,O,P,x,w,j,_,k,S,N,C,z -function M(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function D(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 -e.PRIMARY_KEY="uid" -e.SLUG_KEY="ServiceName" -let T=(l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("boolean"),c=(0,t.attr)("boolean"),d=(0,t.attr)("boolean"),p=(0,t.attr)(),f=(0,t.attr)(),m=(0,t.attr)(),h=(0,n.computed)("Downstreams"),b=(0,n.computed)("Downstreams","Upstreams"),y=(0,n.computed)("Downstreams","Upstreams"),g=class extends t.default{constructor(){super(...arguments),M(this,"uid",v,this),M(this,"ServiceName",O,this),M(this,"Datacenter",P,this),M(this,"Namespace",x,this),M(this,"Partition",w,this),M(this,"Protocol",j,this),M(this,"FilteredByACLs",_,this),M(this,"TransparentProxy",k,this),M(this,"ConnectNative",S,this),M(this,"Upstreams",N,this),M(this,"Downstreams",C,this),M(this,"meta",z,this)}get notDefinedIntention(){let e=!1 -return e=0!==this.Downstreams.filter((e=>"specific-intention"===e.Source&&!e.TransparentProxy&&!e.ConnectNative&&e.Intention.Allowed)).length,e}get wildcardIntention(){const e=0!==this.Downstreams.filter((e=>!e.Intention.HasExact&&e.Intention.Allowed)).length,t=0!==this.Upstreams.filter((e=>!e.Intention.HasExact&&e.Intention.Allowed)).length -return e||t}get noDependencies(){return 0===this.Upstreams.length&&0===this.Downstreams.length}},v=D(g.prototype,"uid",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=D(g.prototype,"ServiceName",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=D(g.prototype,"Datacenter",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=D(g.prototype,"Namespace",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=D(g.prototype,"Partition",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=D(g.prototype,"Protocol",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=D(g.prototype,"FilteredByACLs",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=D(g.prototype,"TransparentProxy",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=D(g.prototype,"ConnectNative",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=D(g.prototype,"Upstreams",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=D(g.prototype,"Downstreams",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=D(g.prototype,"meta",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D(g.prototype,"notDefinedIntention",[h],Object.getOwnPropertyDescriptor(g.prototype,"notDefinedIntention"),g.prototype),D(g.prototype,"wildcardIntention",[b],Object.getOwnPropertyDescriptor(g.prototype,"wildcardIntention"),g.prototype),D(g.prototype,"noDependencies",[y],Object.getOwnPropertyDescriptor(g.prototype,"noDependencies"),g.prototype),g) -e.default=T})),define("consul-ui/modifiers/aria-menu",["exports","ember-modifier","@ember/service","@ember/object"],(function(e,t,n,l){var r,i,o -function a(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const u={vertical:{40:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1 -return(t+1)%e.length},38:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0 -return 0===t?e.length-1:t-1},36:(e,t)=>0,35:(e,t)=>e.length-1},horizontal:{}} -let s=(r=(0,n.inject)("-document"),i=class extends t.default{constructor(){var e,t,n,l,r,i,a -super(...arguments),e=this,t="doc",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a="vertical",(i="orientation")in(r=this)?Object.defineProperty(r,i,{value:a,enumerable:!0,configurable:!0,writable:!0}):r[i]=a}async keydown(e){if(27===e.keyCode)return this.options.onclose(e),void this.$trigger.focus() -const t=[...this.element.querySelectorAll('[role^="menuitem"]')],n=t.findIndex((e=>e===this.doc.activeElement)) -9!==e.keyCode?void 0!==u[this.orientation][e.keyCode]&&(t[u[this.orientation][e.keyCode](t,n)].focus(),e.stopPropagation(),e.preventDefault()):e.shiftKey?0===n&&(this.options.onclose(e),this.$trigger.focus()):n===t.length-1&&(await new Promise((e=>setTimeout(e,0))),this.options.onclose(e))}async focus(e){""===e.pointerType&&(await Promise.resolve(),this.keydown({keyCode:36,stopPropagation:()=>{},preventDefault:()=>{}}))}connect(e,t){this.$trigger=this.doc.getElementById(this.element.getAttribute("aria-labelledby")),void 0!==t.openEvent&&this.focus(t.openEvent),this.doc.addEventListener("keydown",this.keydown)}disconnect(){this.doc.removeEventListener("keydown",this.keydown)}didReceiveArguments(){this.params=this.args.positional,this.options=this.args.named}didInstall(){this.connect(this.args.positional,this.args.named)}willRemove(){this.disconnect()}},o=a(i.prototype,"doc",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a(i.prototype,"keydown",[l.action],Object.getOwnPropertyDescriptor(i.prototype,"keydown"),i.prototype),a(i.prototype,"focus",[l.action],Object.getOwnPropertyDescriptor(i.prototype,"focus"),i.prototype),i) -e.default=s})),define("consul-ui/modifiers/create-ref",["exports","ember-ref-bucket/modifiers/create-ref"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/css-prop",["exports","ember-modifier","@ember/service"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,n.inject)("-document"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="doc",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}didReceiveArguments(){const e=this.args.positional,t=this.args.named;(e[1]||t.returns)(this.doc.defaultView.getComputedStyle(this.element).getPropertyValue(e[0]))}},a=r.prototype,u="doc",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/modifiers/css-props",["exports","ember-modifier"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const n=Object.fromEntries([...document.styleSheets].reduce(((e,t)=>e.concat([...t.cssRules].filter((e=>1===e.type)).reduce(((e,t)=>[...e,...[...t.style].filter((e=>e.startsWith("--"))).map((e=>[e.trim(),t.style.getPropertyValue(e).trim()]))]),[]))),[])) -var l=(0,t.modifier)((function(e,t,l){let[r]=t -const i=new RegExp(`^--${l.prefix||"."}${l.group||""}+`),o={} -Object.entries(n).forEach((e=>{let[t,n]=e -const r=t.match(i) -if(r){let e=r[0] -"-"===e.charAt(e.length-1)&&(e=e.substr(0,e.length-1)),l.group?(void 0===o[e]&&(o[e]={}),o[e][t]=n):o[t]=n}})),r(o)})) -e.default=l})),define("consul-ui/modifiers/did-insert",["exports","@ember/render-modifiers/modifiers/did-insert"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/did-update",["exports","@ember/render-modifiers/modifiers/did-update"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/did-upsert",["exports","@ember/modifier"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const n=e=>({target:e.element,currentTarget:e.element}) -var l=(0,t.setModifierManager)((()=>({capabilities:(0,t.capabilities)("3.22",{disableAutoTracking:!0}),createModifier:()=>({element:null}),installModifier(e,t,l){e.element=t,l.positional.forEach((()=>{})),l.named&&Object.values(l.named) -const[r,...i]=l.positional -r(n(e),i,l.named)},updateModifier(e,t){t.positional.forEach((()=>{})),t.named&&Object.values(t.named) -const[l,...r]=t.positional -l(n(e),r,t.named)},destroyModifier(){}})),class{}) -e.default=l})),define("consul-ui/modifiers/disabled",["exports","ember-modifier"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.modifier)((function(e,t,n){let[l=!0]=t -if(["input","textarea","select","button"].includes(e.nodeName.toLowerCase()))l?(e.setAttribute("disabled",l),e.setAttribute("aria-disabled",l)):(e.dataset.disabled=!1,e.removeAttribute("disabled"),e.removeAttribute("aria-disabled")) -else for(const r of e.querySelectorAll("input,textarea,button"))l&&"false"!==r.dataset.disabled?(e.setAttribute("disabled",l),e.setAttribute("aria-disabled",l)):(e.removeAttribute("disabled"),e.removeAttribute("aria-disabled"))})) -e.default=n})),define("consul-ui/modifiers/focus-trap",["exports","ember-focus-trap/modifiers/focus-trap.js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/in-viewport",["exports","ember-in-viewport/modifiers/in-viewport"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/notification",["exports","ember-modifier","@ember/service"],(function(e,t,n){var l,r,i -function o(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let u=(l=(0,n.inject)("flashMessages"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="notify",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}didInstall(){this.element.setAttribute("role","alert"),this.element.dataset.notification=null -const e=function(e){for(var t=1;te.after())).catch((e=>{if("TransitionAborted"!==e.name)throw e})).then((t=>{this.notify.add(e)})):this.notify.add(e)}willDestroy(){this.args.named.sticky&&this.notify.clearMessages()}},s=r.prototype,c="notify",d=[l],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),i=m,r) -var s,c,d,p,f,m -e.default=u})),define("consul-ui/modifiers/on-key",["exports","ember-keyboard/modifiers/on-key.js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/on-outside",["exports","ember-modifier","@ember/object","@ember/service"],(function(e,t,n,l){var r,i,o -function a(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let u=(r=(0,l.inject)("dom"),i=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="dom",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),this.doc=this.dom.document()}async connect(e,t){await new Promise((e=>setTimeout(e,0))) -try{this.doc.addEventListener(e[0],this.listen)}catch(n){}}listen(e){if(this.dom.isOutside(this.element,e.target)){("function"==typeof this.params[1]?this.params[1]:e=>{}).apply(this.element,[e])}}disconnect(){this.doc.removeEventListener("click",this.listen)}didReceiveArguments(){this.params=this.args.positional,this.options=this.args.named}didInstall(){this.connect(this.args.positional,this.args.named)}willRemove(){this.disconnect()}},o=a(i.prototype,"dom",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a(i.prototype,"listen",[n.action],Object.getOwnPropertyDescriptor(i.prototype,"listen"),i.prototype),i) -e.default=u})),define("consul-ui/modifiers/on-resize",["exports","ember-on-resize-modifier/modifiers/on-resize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) -define("consul-ui/modifiers/style",["exports","ember-modifier","@ember/debug"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{setStyles(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[] -const t=this._oldStyles||new Set -Array.isArray(e)||(e=Object.entries(e)),e.forEach((e=>{let[n,l]=e,r="" -l.length>0&&l.includes("!important")&&(r="important",l=l.replace("!important","")),this.element.style.setProperty(n,l,r),t.delete(n)})),t.forEach((e=>this.element.style.removeProperty(e))),this._oldStyles=new Set(e.map((e=>e[0])))}didReceiveArguments(){void 0!==this.args.named.delay?setTimeout((e=>{typeof this!==this.args.positional[0]&&this.setStyles(this.args.positional[0])}),this.args.named.delay):this.setStyles(this.args.positional[0])}}e.default=l})),define("consul-ui/modifiers/tooltip",["exports","ember-modifier","tippy.js"],(function(e,t,n){function l(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function r(e){for(var t=1;t2&&void 0!==arguments[2]?arguments[2]:{} -if("string"==typeof l&&""===l.trim())return -const o=i.options||{} -let a,u=e -if("string"==typeof o.triggerTarget){const e=u -if("parentNode"===o.triggerTarget)u=u.parentNode -else u=u.querySelectorAll(o.triggerTarget) -l=u.cloneNode(!0),e.remove(),i.options.triggerTarget=void 0}if(void 0===l&&(l=u.innerHTML,u.innerHTML=""),"manual"===o.trigger){const e=o.delay||[] -void 0!==e[1]&&(i.options.onShown=t=>{clearInterval(a),a=setTimeout((()=>{t.hide()}),e[1])})}let s=u,c=!1 -s.hasAttribute("tabindex")||(c=!0,s.setAttribute("tabindex","0")) -const d=(0,n.default)(u,r({theme:"tooltip",triggerTarget:s,content:e=>l,plugins:[void 0!==o.followCursor?n.followCursor:void 0].filter((e=>Boolean(e)))},i.options)) -return()=>{c&&s.removeAttribute("tabindex"),clearInterval(a),d.destroy()}})) -e.default=o})),define("consul-ui/modifiers/validate",["exports","ember-modifier","@ember/object"],(function(e,t,n){var l -function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class o extends Error{}let a=(l=class extends t.default{constructor(){super(...arguments),r(this,"item",null),r(this,"hash",null)}validate(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -if(0===Object.keys(t).length)return -const n={} -Object.entries(this.hash.validations).filter((e=>{let[t,n]=e -return"string"!=typeof n})).forEach((t=>{let[l,r]=t -this.item&&(this.item[l]=e),(r||[]).forEach((t=>{new RegExp(t.test).test(e)||(n[l]=new o(t.error))}))})) -const l=this.hash.chart.state||{} -null==l.context&&(l.context={}),Object.keys(n).length>0?(l.context.errors=n,this.hash.chart.dispatch("ERROR",l.context)):(l.context.errors=null,this.hash.chart.dispatch("RESET",l.context))}reset(e){if(0===e.target.value.length){const e=this.hash.chart.state -e.context||(e.context={}),e.context.errors||(e.context.errors={}),Object.entries(this.hash.validations).filter((e=>{let[t,n]=e -return"string"!=typeof n})).forEach((t=>{let[n,l]=t -void 0!==e.context.errors[n]&&delete e.context.errors[n]})),0===Object.keys(e.context.errors).length&&(e.context.errors=null,this.hash.chart.dispatch("RESET",e.context))}}async connect(e,t){let[n]=e -this.element.addEventListener("input",this.listen),this.element.addEventListener("blur",this.reset),this.element.value.length>0&&(await Promise.resolve(),this&&this.element&&this.validate(this.element.value,this.hash.validations))}listen(e){this.validate(e.target.value,this.hash.validations)}disconnect(){this.item=null,this.hash=null,this.element.removeEventListener("input",this.listen),this.element.removeEventListener("blur",this.reset)}didReceiveArguments(){const[e]=this.args.positional,t=this.args.named -this.item=e,this.hash=t,void 0===t.chart&&(this.hash.chart={state:{context:{}},dispatch:e=>{switch(e){case"ERROR":t.onchange(this.hash.chart.state.context.errors) -break -case"RESET":t.onchange()}}})}didInstall(){this.connect(this.args.positional,this.args.named)}willRemove(){this.disconnect()}},i(l.prototype,"reset",[n.action],Object.getOwnPropertyDescriptor(l.prototype,"reset"),l.prototype),i(l.prototype,"listen",[n.action],Object.getOwnPropertyDescriptor(l.prototype,"listen"),l.prototype),l) -e.default=a})),define("consul-ui/modifiers/will-destroy",["exports","@ember/render-modifiers/modifiers/will-destroy"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/with-copyable",["exports","ember-modifier","@ember/service","@ember/debug"],(function(e,t,n,l){var r,i,o -function a(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const s=(e,t,n)=>typeof t===e?t:n -let c=(r=(0,n.inject)("clipboard/os"),i=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="clipboard",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),u(this,"hash",null),u(this,"source",null)}connect(e,t){let[n]=e -n=s("string",n,this.element.innerText) -const r={success:e=>((0,l.runInDebug)((e=>console.info(`with-copyable: Copied \`${n}\``))),s("function",t.success,(()=>{}))(e)),error:e=>((0,l.runInDebug)((e=>console.info(`with-copyable: Error copying \`${n}\``))),s("function",t.error,(()=>{}))(e))} -this.source=this.clipboard.execute(this.element,function(e){for(var t=1;tn},r.options)).on("success",r.success).on("error",r.error),this.hash=r}disconnect(){this.source&&this.hash&&(this.source.off("success",this.hash.success).off("error",this.hash.error),this.source.destroy(),this.hash=null,this.source=null)}didReceiveArguments(){this.disconnect(),this.connect(this.args.positional,this.args.named)}willRemove(){this.disconnect()}},d=i.prototype,p="clipboard",f=[r],m={configurable:!0,enumerable:!0,writable:!0,initializer:null},b={},Object.keys(m).forEach((function(e){b[e]=m[e]})),b.enumerable=!!b.enumerable,b.configurable=!!b.configurable,("value"in b||b.initializer)&&(b.writable=!0),b=f.slice().reverse().reduce((function(e,t){return t(d,p,e)||e}),b),h&&void 0!==b.initializer&&(b.value=b.initializer?b.initializer.call(h):void 0,b.initializer=void 0),void 0===b.initializer&&(Object.defineProperty(d,p,b),b=null),o=b,i) -var d,p,f,m,h,b -e.default=c})),define("consul-ui/modifiers/with-overlay",["exports","ember-modifier","tippy.js"],(function(e,t,n){function l(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function r(e){for(var t=1;t2&&void 0!==arguments[2]?arguments[2]:{} -const o=i.options||{} -let a,u=e -if("string"==typeof o.triggerTarget){const e=u -if("parentNode"===o.triggerTarget)u=u.parentNode -else u=u.querySelectorAll(o.triggerTarget) -l=u.cloneNode(!0),e.remove(),i.options.triggerTarget=void 0}if(void 0===l&&(l=u.innerHTML,u.innerHTML=""),i.returns&&(o.trigger="manual"),"manual"===o.trigger){const e=o.delay||[] -void 0!==e[1]&&(o.onShown=t=>{clearInterval(a),a=setTimeout((()=>{t.hide()}),e[1])})}let s=u -const c=(0,n.default)(u,r({triggerTarget:s,content:e=>l,interactive:!0,plugins:[void 0!==o.followCursor?n.followCursor:void 0].filter((e=>Boolean(e)))},o)) -return i.returns&&i.returns(c),()=>{clearInterval(a),c.destroy()}})) -e.default=o})),define("consul-ui/router",["exports","@ember/routing/router","consul-ui/config/environment","@ember/debug","deepmerge","consul-ui/env","consul-ui/utils/routing/walk"],(function(e,t,n,l,r,i,o){function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.routes=void 0 -const u=document,s=n.default.modulePrefix,c=r.default.all([...u.querySelectorAll("script[data-routes]")].map((e=>JSON.parse(e.dataset.routes)))) -e.routes=c,(0,l.runInDebug)((()=>{const e=requirejs.entries[`${s}/docfy-output`] -if(void 0!==e){const t={} -e.callback(t),function e(t,n){"/"!==n.name&&(t=t[n.name]={_options:{path:n.name}}),n.pages.forEach((e=>{const n=e.relativeUrl -"string"==typeof n&&""!==n&&(t[n]={_options:{path:n}})})),n.children.forEach((n=>{e(t,n)}))}(c,t.default.nested)}})),(0,l.runInDebug)((()=>{window.Routes=function(){let e,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:(0,i.env)("DEBUG_ROUTES_ENDPOINT") -t||(t="data:,%s") -const n=(0,o.dump)(c) -t.startsWith("data:,")?(e=window.open("","_blank"),e.document.write(`
      ${n}
      `)):e=window.open(t.replace("%s",encodeURIComponent(n)),"_blank"),e.focus()}})) -class d extends t.default{constructor(){super(...arguments),a(this,"location",(0,i.env)("locationType")),a(this,"rootURL",(0,i.env)("rootURL"))}}e.default=d,d.map((0,o.default)(c))})),define("consul-ui/routes/application",["exports","consul-ui/routing/route","@ember/object","@ember/service","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l,r){var i,o,a,u,s,c,d -function p(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function f(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let m=(i=(0,l.inject)("client/http"),o=(0,l.inject)("env"),a=(0,l.inject)(),u=class extends(t.default.extend(r.default)){constructor(){var e,t,n -super(...arguments),p(this,"client",s,this),p(this,"env",c,this),p(this,"hcp",d,this),n=void 0,(t="data")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}async model(){return this.env.var("CONSUL_ACLS_ENABLED")&&await this.hcp.updateTokenIfNecessary(this.env.var("CONSUL_HTTP_TOKEN")),{}}onClientChanged(e){let t=e.data -""===t&&(t={blocking:!0}),void 0!==this.data?(!0===this.data.blocking&&!1===t.blocking&&this.client.abort(),this.data=Object.assign({},t)):this.data=Object.assign({},t)}error(e,t){let n={status:e.code||e.statusCode||"",message:e.message||e.detail||"Error"} -return e.errors&&e.errors[0]&&(n=e.errors[0],n.message=n.message||n.title||n.detail||"Error"),""===n.status&&(n.message="Error"),this.controllerFor("application").setProperties({error:n}),!0}},s=f(u.prototype,"client",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=f(u.prototype,"env",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=f(u.prototype,"hcp",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f(u.prototype,"onClientChanged",[n.action],Object.getOwnPropertyDescriptor(u.prototype,"onClientChanged"),u.prototype),f(u.prototype,"error",[n.action],Object.getOwnPropertyDescriptor(u.prototype,"error"),u.prototype),u) -e.default=m})),define("consul-ui/routes/dc",["exports","@ember/service","consul-ui/routing/route"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,t.inject)("repository/permission"),r=class extends n.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="permissionsRepo",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}async model(e){const t=await this.permissionsRepo.findAll({dc:e.dc,ns:this.optionalParams().nspace,partition:this.optionalParams().partition}) -return this.controllerFor("application").setProperties({permissions:t}),{permissions:t}}},a=r.prototype,u="permissionsRepo",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/routes/dc/acls/auth-methods/index",["exports","consul-ui/routing/route"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{constructor(){var e,t,n -super(...arguments),n={sortBy:"sort",source:"source",kind:"kind",searchproperty:{as:"searchproperty",empty:[["Name","DisplayName"]]},search:{as:"filter",replace:!0}},(t="queryParams")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}}e.default=n})),define("consul-ui/routes/dc/acls/auth-methods/show/index",["exports","consul-ui/routing/route","consul-ui/utils/routing/redirect-to"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{constructor(){var e,t,l -super(...arguments),e=this,t="redirect",l=(0,n.default)("auth-method"),t in e?Object.defineProperty(e,t,{value:l,enumerable:!0,configurable:!0,writable:!0}):e[t]=l}}e.default=l})),define("consul-ui/routes/dc/acls/policies/create",["exports","consul-ui/routes/dc/acls/policies/edit"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{constructor(){var e,t,n -super(...arguments),n="dc/acls/policies/edit",(t="templateName")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}}e.default=n})),define("consul-ui/routes/dc/acls/policies/edit",["exports","@ember/service","consul-ui/routing/route","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l){var r,i,o -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(r=(0,t.inject)("repository/policy"),i=class extends(n.default.extend(l.default)){constructor(){var e,t,n,l -super(...arguments),e=this,t="repo",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}},u=i.prototype,s="repo",c=[r],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),o=f,i) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/routes/dc/acls/policies/index",["exports","consul-ui/routing/route","@ember/service","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l){var r,i,o -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(r=(0,n.inject)("repository/policy"),i=class extends(t.default.extend(l.default)){constructor(){var e,t,n,l,r,i,a -super(...arguments),e=this,t="repo",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a={sortBy:"sort",datacenter:{as:"dc"},kind:"kind",searchproperty:{as:"searchproperty",empty:[["Name","Description"]]},search:{as:"filter",replace:!0}},(i="queryParams")in(r=this)?Object.defineProperty(r,i,{value:a,enumerable:!0,configurable:!0,writable:!0}):r[i]=a}},u=i.prototype,s="repo",c=[r],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),o=f,i) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/routes/dc/acls/roles/create",["exports","consul-ui/routes/dc/acls/roles/edit"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{constructor(){var e,t,n -super(...arguments),n="dc/acls/roles/edit",(t="templateName")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}}e.default=n})),define("consul-ui/routes/dc/acls/roles/edit",["exports","@ember/service","consul-ui/routing/route","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l){var r,i,o -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(r=(0,t.inject)("repository/role"),i=class extends(n.default.extend(l.default)){constructor(){var e,t,n,l -super(...arguments),e=this,t="repo",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}},u=i.prototype,s="repo",c=[r],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),o=f,i) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/routes/dc/acls/roles/index",["exports","consul-ui/routing/route","@ember/service","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l){var r,i,o -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(r=(0,n.inject)("repository/role"),i=class extends(t.default.extend(l.default)){constructor(){var e,t,n,l,r,i,a -super(...arguments),e=this,t="repo",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a={sortBy:"sort",searchproperty:{as:"searchproperty",empty:[["Name","Description","Policy"]]},search:{as:"filter",replace:!0}},(i="queryParams")in(r=this)?Object.defineProperty(r,i,{value:a,enumerable:!0,configurable:!0,writable:!0}):r[i]=a}},u=i.prototype,s="repo",c=[r],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),o=f,i) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/routes/dc/acls/tokens/create",["exports","consul-ui/routes/dc/acls/tokens/edit"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{constructor(){var e,t,n -super(...arguments),n="dc/acls/tokens/edit",(t="templateName")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}}e.default=n})),define("consul-ui/routes/dc/acls/tokens/edit",["exports","@ember/service","consul-ui/routing/route","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l){var r,i,o,a,u -function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let d=(r=(0,t.inject)("repository/token"),i=(0,t.inject)("settings"),o=class extends(n.default.extend(l.default)){constructor(){super(...arguments),s(this,"repo",a,this),s(this,"settings",u,this)}async model(e,t){return{token:await this.settings.findBySlug("token")}}},a=c(o.prototype,"repo",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(o.prototype,"settings",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) -e.default=d})),define("consul-ui/routes/dc/acls/tokens/index",["exports","consul-ui/routing/route","@ember/service","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l){var r,i,o -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let a=(r=(0,n.inject)("repository/token"),i=class extends(t.default.extend(l.default)){constructor(){var e,t,n,l,r,i,a -super(...arguments),e=this,t="repo",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a={sortBy:"sort",kind:"kind",searchproperty:{as:"searchproperty",empty:[["AccessorID","Description","Role","Policy"]]},search:{as:"filter",replace:!0}},(i="queryParams")in(r=this)?Object.defineProperty(r,i,{value:a,enumerable:!0,configurable:!0,writable:!0}):r[i]=a}},u=i.prototype,s="repo",c=[r],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),o=f,i) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/routes/dc/kv/folder",["exports","consul-ui/routes/dc/kv/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{beforeModel(e){super.beforeModel(...arguments) -const t=this.paramsFor("dc.kv.folder") -if("/"===t.key||null==t.key)return this.transitionTo("dc.kv.index")}}e.default=n})),define("consul-ui/routes/dc/kv/index",["exports","consul-ui/routing/route","@ember/object","consul-ui/utils/isFolder"],(function(e,t,n,l){var r -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let i=(r=class extends t.default{beforeModel(){const e=this.paramsFor(this.routeName).key||"/" -if(!(0,l.default)(e))return this.replaceWith(this.routeName,e+"/")}error(e){return!e.errors||!e.errors[0]||"404"!=e.errors[0].status||this.transitionTo("dc.kv.index")}},o=r.prototype,a="error",u=[n.action],s=Object.getOwnPropertyDescriptor(r.prototype,"error"),c=r.prototype,d={},Object.keys(s).forEach((function(e){d[e]=s[e]})),d.enumerable=!!d.enumerable,d.configurable=!!d.configurable,("value"in d||d.initializer)&&(d.writable=!0),d=u.slice().reverse().reduce((function(e,t){return t(o,a,e)||e}),d),c&&void 0!==d.initializer&&(d.value=d.initializer?d.initializer.call(c):void 0,d.initializer=void 0),void 0===d.initializer&&(Object.defineProperty(o,a,d),d=null),r) -var o,a,u,s,c,d -e.default=i})),define("consul-ui/routes/dc/services/notfound",["exports","consul-ui/routing/route"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{redirect(e,t){this.replaceWith("dc.services.instance",e.name,e.node,e.id)}}e.default=n})),define("consul-ui/routes/dc/services/show/topology",["exports","consul-ui/routing/route","@ember/service","@ember/object"],(function(e,t,n,l){var r,i,o,a,u,s,c -function d(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function p(e){for(var t=1;tn.Datacenter===e.Datacenter&&n.SourceName===e.Name&&n.SourceNS===e.Namespace&&n.SourcePartition===e.Partition&&n.DestinationName===t.Name&&n.DestinationNS===t.Namespace&&n.DestinationPartition===t.Partition)) -void 0===r?r=this.repo.create({Datacenter:e.Datacenter,SourceName:e.Name,SourceNS:e.Namespace||"default",SourcePartition:e.Partition||"default",DestinationName:t.Name,DestinationNS:t.Namespace||"default",DestinationPartition:t.Partition||"default"}):n=this.feedback.notification("update","intention"),(0,l.set)(r,"Action","allow"),await this.repo.persist(r),n.success(r)}catch(r){n.error(r)}this.refresh()}afterModel(e,t){const n=p(p(p({},this.optionalParams()),this.paramsFor("dc")),this.paramsFor("dc.services.show")) -this.intentions=this.data.source((e=>e`/${n.partition}/${n.nspace}/${n.dc}/intentions/for-service/${n.name}`))}async deactivate(e){(await this.intentions).destroy()}},u=h(a.prototype,"data",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s=h(a.prototype,"repo",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=h(a.prototype,"feedback",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h(a.prototype,"createIntention",[l.action],Object.getOwnPropertyDescriptor(a.prototype,"createIntention"),a.prototype),a) -e.default=b})),define("consul-ui/routing/route",["exports","@ember/routing/route","@ember/object","@ember/service","consul-ui/utils/path/resolve","consul-ui/router"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m,h,b -function y(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function g(e){for(var t=1;t!n.includes(e))).length&&(e=void 0)}}return e}model(){const e={} -return void 0!==this.queryParams&&void 0!==this.queryParams.searchproperty&&(e.searchProperties=this.queryParams.searchproperty.empty[0]),e}setupController(e,t){(0,n.setProperties)(e,g(g({},t),{},{routeName:this.routeName})),super.setupController(...arguments)}optionalParams(){return this.container.get(`location:${this.env.var("locationType")}`).optionalParams()}paramsFor(e){return this.routlet.normalizeParamsFor(this.routeName,super.paramsFor(...arguments))}async replaceWith(e,t){await Promise.resolve() -let n=[] -return"string"==typeof t&&(n=[t]),void 0===t||Array.isArray(t)||"string"==typeof t||(n=Object.values(t)),super.replaceWith(e,...n)}async transitionTo(e,t){await Promise.resolve() -let n=[] -return"string"==typeof t&&(n=[t]),void 0===t||Array.isArray(t)||"string"==typeof t||(n=Object.values(t)),super.transitionTo(e,...n)}},p=P(d.prototype,"container",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=P(d.prototype,"env",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=P(d.prototype,"permissions",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=P(d.prototype,"router",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=P(d.prototype,"routlet",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P(d.prototype,"replaceWith",[n.action],Object.getOwnPropertyDescriptor(d.prototype,"replaceWith"),d.prototype),P(d.prototype,"transitionTo",[n.action],Object.getOwnPropertyDescriptor(d.prototype,"transitionTo"),d.prototype),d) -e.default=x})),define("consul-ui/routing/single",["exports","consul-ui/routing/route","@ember/debug","rsvp"],(function(e,t,n,l){function r(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function i(e){for(var t=1;te.ID,Name:e=>e.Name}})),define("consul-ui/search/predicates/auth-method",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={Name:e=>e.Name,DisplayName:e=>e.DisplayName}})),define("consul-ui/search/predicates/health-check",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var t={Name:e=>e.Name,Node:e=>e.Node,Service:e=>e.ServiceName,CheckID:e=>e.CheckID||"",ID:e=>e.Service.ID||"",Notes:e=>e.Notes,Output:e=>e.Output,ServiceTags:e=>{return t=e.ServiceTags,Array.isArray(t)?t:t.toArray() -var t}} -e.default=t})),define("consul-ui/search/predicates/intention",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const t="All Services (*)" -var n={SourceName:e=>[e.SourceName,"*"===e.SourceName?t:void 0].filter(Boolean),DestinationName:e=>[e.DestinationName,"*"===e.DestinationName?t:void 0].filter(Boolean)} -e.default=n})) -define("consul-ui/search/predicates/kv",["exports","consul-ui/utils/right-trim"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n={Key:e=>(0,t.default)(e.Key.toLowerCase()).split("/").filter((e=>Boolean(e))).pop()} -e.default=n})),define("consul-ui/search/predicates/node",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var t={Node:e=>e.Node,Address:e=>e.Address,PeerName:e=>e.PeerName,Meta:e=>Object.entries(e.Meta||{}).reduce(((e,t)=>e.concat(t)),[])} -e.default=t})),define("consul-ui/search/predicates/nspace",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={Name:e=>e.Name,Description:e=>e.Description,Role:e=>((e.ACLs||{}).RoleDefaults||[]).map((e=>e.Name)),Policy:e=>((e.ACLs||{}).PolicyDefaults||[]).map((e=>e.Name))}})),define("consul-ui/search/predicates/peer",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={Name:e=>e.Name,ID:e=>e.ID}})),define("consul-ui/search/predicates/policy",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={Name:e=>e.Name,Description:e=>e.Description}})),define("consul-ui/search/predicates/role",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={Name:e=>e.Name,Description:e=>e.Description,Policy:e=>(e.Policies||[]).map((e=>e.Name)).concat((e.ServiceIdentities||[]).map((e=>e.ServiceName))).concat((e.NodeIdentities||[]).map((e=>e.NodeName)))}})),define("consul-ui/search/predicates/service-instance",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var t={Name:e=>e.Name,Node:e=>e.Node.Node,Tags:e=>e.Service.Tags||[],ID:e=>e.Service.ID||"",Address:e=>e.Address||"",Port:e=>(e.Service.Port||"").toString(),"Service.Meta":e=>Object.entries(e.Service.Meta||{}).reduce(((e,t)=>e.concat(t)),[]),"Node.Meta":e=>Object.entries(e.Node.Meta||{}).reduce(((e,t)=>e.concat(t)),[])} -e.default=t})),define("consul-ui/search/predicates/service",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={Name:e=>e.Name,Tags:e=>e.Tags||[],PeerName:e=>e.PeerName,Partition:e=>e.Partition}})),define("consul-ui/search/predicates/token",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={Name:e=>e.Name,Description:e=>e.Description,AccessorID:e=>e.AccessorID,Role:e=>(e.Roles||[]).map((e=>e.Name)),Policy:e=>(e.Policies||[]).map((e=>e.Name)).concat((e.ServiceIdentities||[]).map((e=>e.ServiceName))).concat((e.NodeIdentities||[]).map((e=>e.NodeName)))}})),define("consul-ui/search/predicates/upstream-instance",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={DestinationName:(e,t)=>e.DestinationName,LocalBindAddress:(e,t)=>e.LocalBindAddress,LocalBindPort:(e,t)=>e.LocalBindPort.toString()}})),define("consul-ui/serializers/-default",["exports","@ember-data/serializer/json"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/serializers/-json-api",["exports","@ember-data/serializer/json-api"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/serializers/-rest",["exports","@ember-data/serializer/rest"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/serializers/application",["exports","consul-ui/serializers/http","@ember/object","consul-ui/utils/http/consul","consul-ui/utils/http/headers","consul-ui/models/dc","consul-ui/models/nspace","consul-ui/models/partition","consul-ui/utils/create-fingerprinter"],(function(e,t,n,l,r,i,o,a,u){function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const c=function(e,t){const n={} -return Object.keys(e).forEach((function(t){n[t.toLowerCase()]=e[t]})),t[l.HEADERS_SYMBOL]=n,t} -class d extends t.default{constructor(){super(...arguments),s(this,"attachHeaders",c),s(this,"fingerprint",(0,u.default)(i.FOREIGN_KEY,o.NSPACE_KEY,a.PARTITION_KEY))}respondForQuery(e,t){return e(((e,n)=>{return c(e,(r=n,i=this.fingerprint(this.primaryKey,this.slugKey,t.dc,e[l.HEADERS_NAMESPACE],e[l.HEADERS_PARTITION]),Array.isArray(r)?r.map(i):[r].map(i)[0]),t) -var r,i}))}respondForQueryRecord(e,t){return e(((e,n)=>c(e,this.fingerprint(this.primaryKey,this.slugKey,t.dc,e[l.HEADERS_NAMESPACE],e[l.HEADERS_PARTITION])(n),t)))}respondForCreateRecord(e,t,n){const r=this.slugKey,o=this.primaryKey -return e(((e,t)=>(!0===t&&(t=n),this.fingerprint(o,r,n[i.FOREIGN_KEY],e[l.HEADERS_NAMESPACE],n.Partition)(t))))}respondForUpdateRecord(e,t,n){const r=this.slugKey,o=this.primaryKey -return e(((e,t)=>(!0===t&&(t=n),this.fingerprint(o,r,n[i.FOREIGN_KEY],e[l.HEADERS_NAMESPACE],e[l.HEADERS_PARTITION])(t))))}respondForDeleteRecord(e,t,n){const r=this.slugKey,u=this.primaryKey -return e(((e,t)=>({[u]:this.fingerprint(u,r,n[i.FOREIGN_KEY],e[l.HEADERS_NAMESPACE],e[l.HEADERS_PARTITION])({[r]:n[r],[o.NSPACE_KEY]:n[o.NSPACE_KEY],[a.PARTITION_KEY]:n[a.PARTITION_KEY]})[u]})))}normalizeResponse(e,t,n,l,r){const i=this.normalizePayload(n,l,r),o=this.normalizeMeta(e,t,i,l,r) -"query"!==r&&(i.meta=o) -const a=super.normalizeResponse(e,t,{meta:o,[t.modelName]:i},l,r) -return void 0===a?n:a}timestamp(){return(new Date).getTime()}normalizeMeta(e,t,i,o,a){const u=i[l.HEADERS_SYMBOL]||{} -delete i[l.HEADERS_SYMBOL] -const s={cacheControl:u[r.CACHE_CONTROL.toLowerCase()],cursor:u[l.HEADERS_INDEX.toLowerCase()],dc:u[l.HEADERS_DATACENTER.toLowerCase()],nspace:u[l.HEADERS_NAMESPACE.toLowerCase()],partition:u[l.HEADERS_PARTITION.toLowerCase()]} -return void 0!==u["x-range"]&&(s.range=u["x-range"]),void 0!==u.refresh&&(s.interval=1e3*u.refresh),"query"===a&&(s.date=this.timestamp(),i.forEach((function(e){(0,n.set)(e,"SyncTime",s.date)}))),s}normalizePayload(e,t,n){return e}}e.default=d})),define("consul-ui/serializers/auth-method",["exports","consul-ui/serializers/application","consul-ui/models/auth-method"],(function(e,t,n){function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class r extends t.default{constructor(){super(...arguments),l(this,"primaryKey",n.PRIMARY_KEY),l(this,"slugKey",n.SLUG_KEY)}}e.default=r})),define("consul-ui/serializers/binding-rule",["exports","consul-ui/serializers/application","consul-ui/models/binding-rule"],(function(e,t,n){function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class r extends t.default{constructor(){super(...arguments),l(this,"primaryKey",n.PRIMARY_KEY),l(this,"slugKey",n.SLUG_KEY)}}e.default=r})),define("consul-ui/serializers/coordinate",["exports","consul-ui/serializers/application","consul-ui/models/coordinate"],(function(e,t,n){function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class r extends t.default{constructor(){super(...arguments),l(this,"primaryKey",n.PRIMARY_KEY),l(this,"slugKey",n.SLUG_KEY)}}e.default=r})),define("consul-ui/serializers/discovery-chain",["exports","consul-ui/serializers/application","consul-ui/models/discovery-chain"],(function(e,t,n){function l(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function r(e){for(var t=1;tt))}respondForQueryRecord(e,t){return e(((e,t)=>t))}respondForFindAll(e,t){return e(((e,t)=>t))}respondForCreateRecord(e,t){return e(((e,t)=>t))}respondForUpdateRecord(e,t){return e(((e,t)=>t))}respondForDeleteRecord(e,t){return e(((e,t)=>t))}}e.default=n})),define("consul-ui/serializers/intention",["exports","consul-ui/serializers/application","@ember/service","@ember/object","consul-ui/models/intention"],(function(e,t,n,l,r){var i,o,a -function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let s=(i=(0,n.inject)("encoder"),o=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="encoder",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),u(this,"primaryKey",r.PRIMARY_KEY),u(this,"slugKey",r.SLUG_KEY)}init(){super.init(...arguments),this.uri=this.encoder.uriTag()}ensureID(e){return(0,l.get)(e,"ID.length")?(e.Legacy=!0,e.LegacyID=e.ID):e.Legacy=!1,e.SourcePeer?e.ID=this.uri`peer:${e.SourcePeer}:${e.SourceNS}:${e.SourceName}:${e.DestinationPartition}:${e.DestinationNS}:${e.DestinationName}`:e.ID=this.uri`${e.SourcePartition}:${e.SourceNS}:${e.SourceName}:${e.DestinationPartition}:${e.DestinationNS}:${e.DestinationName}`,e}respondForQuery(e,t){return super.respondForQuery((t=>e(((e,n)=>t(e,n.map((e=>this.ensureID(e))))))),t)}respondForQueryRecord(e,t){return super.respondForQueryRecord((t=>e(((e,n)=>(n=this.ensureID(n),t(e,n))))),t)}respondForCreateRecord(e,t,n){const l=this.slugKey,r=this.primaryKey -return e(((e,i)=>((i=n).ID=this.uri`${t.SourcePartition}:${t.SourceNS}:${t.SourceName}:${t.DestinationPartition}:${t.DestinationNS}:${t.DestinationName}`,this.fingerprint(r,l,i.Datacenter)(i))))}respondForUpdateRecord(e,t,n){const l=this.slugKey,r=this.primaryKey -return e(((e,i)=>((i=n).LegacyID=i.ID,i.ID=t.ID,this.fingerprint(r,l,i.Datacenter)(i))))}},c=o.prototype,d="encoder",p=[i],f={configurable:!0,enumerable:!0,writable:!0,initializer:null},h={},Object.keys(f).forEach((function(e){h[e]=f[e]})),h.enumerable=!!h.enumerable,h.configurable=!!h.configurable,("value"in h||h.initializer)&&(h.writable=!0),h=p.slice().reverse().reduce((function(e,t){return t(c,d,e)||e}),h),m&&void 0!==h.initializer&&(h.value=h.initializer?h.initializer.call(m):void 0,h.initializer=void 0),void 0===h.initializer&&(Object.defineProperty(c,d,h),h=null),a=h,o) -var c,d,p,f,m,h -e.default=s})),define("consul-ui/serializers/kv",["exports","consul-ui/serializers/application","@ember/service","consul-ui/models/kv"],(function(e,t,n,l){var r,i,o -function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let u=(r=(0,n.inject)("atob"),i=class extends t.default{constructor(){var e,t,n,r -super(...arguments),e=this,t="decoder",r=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(r):void 0}),a(this,"primaryKey",l.PRIMARY_KEY),a(this,"slugKey",l.SLUG_KEY)}serialize(e,t){const n=e.attr("Value") -return"string"==typeof n?this.decoder.execute(n):null}respondForQueryRecord(e,t){return super.respondForQueryRecord((t=>e(((e,n)=>(void 0===n[0].Session&&(n[0].Session=""),t(e,n[0]))))),t)}respondForQuery(e,t){return super.respondForQuery((t=>e(((e,n)=>t(e,n.map((e=>({[this.slugKey]:e}))))))),t)}},s=i.prototype,c="decoder",d=[r],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),o=m,i) -var s,c,d,p,f,m -e.default=u})),define("consul-ui/serializers/node",["exports","consul-ui/serializers/application","@ember-data/serializer/rest","consul-ui/models/node","@ember/string"],(function(e,t,n,l,r){function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=function(e){return""===e[l.SLUG_KEY]&&(e[l.SLUG_KEY]=e.Node),e} -class a extends(t.default.extend(n.EmbeddedRecordsMixin)){constructor(){super(...arguments),i(this,"primaryKey",l.PRIMARY_KEY),i(this,"slugKey",l.SLUG_KEY),i(this,"attrs",{Services:{embedded:"always"}})}transformHasManyResponse(e,t,n){let l,r={} -return"Services"===t.key?((n.Checks||[]).filter((e=>""!==e.ServiceID)).forEach((e=>{void 0===r[e.ServiceID]&&(r[e.ServiceID]=[]),r[e.ServiceID].push(e)})),""===n.PeerName&&(n.PeerName=void 0),l=this.store.serializerFor(t.type),n.Services=n.Services.map((e=>l.transformHasManyResponseFromNode(n,e,r))),n):super.transformHasManyResponse(...arguments)}respondForQuery(e,t,n,l){const i=super.respondForQuery((t=>e(((e,n)=>t(e,n.map(o))))),t) -return l.eachRelationship(((e,t)=>{i.forEach((e=>this[`transform${(0,r.classify)(t.kind)}Response`](this.store,t,e,i)))})),i}respondForQueryRecord(e,t,n,l){const i=super.respondForQueryRecord((t=>e(((e,n)=>t(e,o(n))))),t) -return l.eachRelationship(((e,t)=>{this[`transform${(0,r.classify)(t.kind)}Response`](this.store,t,i)})),i}respondForQueryLeader(e,t){return e(((e,n)=>{const l=n.split(":"),r=l.pop(),i=l.join(":") -return this.attachHeaders(e,{Address:i,Port:r},t)}))}}e.default=a})),define("consul-ui/serializers/nspace",["exports","consul-ui/serializers/application","@ember/object","consul-ui/models/nspace"],(function(e,t,n,l){function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const i=e=>((0,n.get)(e,"ACLs.PolicyDefaults")&&(e.ACLs.PolicyDefaults=e.ACLs.PolicyDefaults.map((function(e){return void 0===e.template&&(e.template=""),e}))),["PolicyDefaults","RoleDefaults"].forEach((function(t){void 0===e.ACLs&&(e.ACLs=[]),void 0===e.ACLs[t]&&(e.ACLs[t]=[])})),e) -class o extends t.default{constructor(){super(...arguments),r(this,"primaryKey",l.PRIMARY_KEY),r(this,"slugKey",l.SLUG_KEY)}respondForQuery(e,t,n,l){return super.respondForQuery((n=>e(((e,l)=>n(e,l.map((function(e){return e.Namespace="*",e.Datacenter=t.dc,i(e)})))))),t)}respondForQueryRecord(e,t,n){return super.respondForQuery((n=>e(((e,l)=>(l.Datacenter=t.dc,l.Namespace="*",n(e,i(l)))))),t,n)}respondForCreateRecord(e,t,n){return super.respondForCreateRecord((n=>e(((e,l)=>(l.Datacenter=t.dc,l.Namespace="*",n(e,i(l)))))),t,n)}respondForUpdateRecord(e,t,n){return e(((e,t)=>i(t)))}}e.default=o})),define("consul-ui/serializers/oidc-provider",["exports","consul-ui/serializers/application","consul-ui/models/oidc-provider"],(function(e,t,n){function l(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class i extends t.default{constructor(){super(...arguments),r(this,"primaryKey",n.PRIMARY_KEY),r(this,"slugKey",n.SLUG_KEY)}respondForAuthorize(e,t,n){return e(((e,t)=>this.attachHeaders(e,t,n)))}respondForQueryRecord(e,t){return super.respondForQueryRecord((n=>e(((e,i)=>n(e,function(e){for(var t=1;te(((e,n)=>t(e,n.map((e=>(e.Partition="*",e.Namespace="*",e))))))),t)}}e.default=r})),define("consul-ui/serializers/permission",["exports","consul-ui/serializers/application"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{}e.default=n})),define("consul-ui/serializers/policy",["exports","consul-ui/serializers/application","consul-ui/models/policy"],(function(e,t,n){function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class r extends t.default{constructor(){super(...arguments),l(this,"primaryKey",n.PRIMARY_KEY),l(this,"slugKey",n.SLUG_KEY)}}e.default=r})),define("consul-ui/serializers/proxy",["exports","consul-ui/serializers/application","consul-ui/models/proxy"],(function(e,t,n){function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class r extends t.default{constructor(){super(...arguments),l(this,"primaryKey",n.PRIMARY_KEY),l(this,"slugKey",n.SLUG_KEY),l(this,"attrs",{NodeName:"Node"})}}e.default=r})),define("consul-ui/serializers/role",["exports","consul-ui/serializers/application","consul-ui/models/role","consul-ui/mixins/policy/as-many"],(function(e,t,n,l){function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class i extends(t.default.extend(l.default)){constructor(){super(...arguments),r(this,"primaryKey",n.PRIMARY_KEY),r(this,"slugKey",n.SLUG_KEY)}}e.default=i})),define("consul-ui/serializers/service-instance",["exports","consul-ui/serializers/application","consul-ui/models/service-instance"],(function(e,t,n){function l(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function r(e){for(var t=1;t{switch(t.Status){case"passing":e.ChecksPassing.push(t) -break -case"warning":e.ChecksWarning.push(t) -break -case"critical":e.ChecksCritical.push(t)}return e}),{ChecksPassing:[],ChecksWarning:[],ChecksCritical:[]}),o=r(r({},i),{},{Service:t,Checks:l,Node:{Datacenter:e.Datacenter,Namespace:e.Namespace,Partition:e.Partition,ID:e.ID,Node:e.Node,Address:e.Address,TaggedAddresses:e.TaggedAddresses,Meta:e.Meta}}) -return o.uid=this.extractUid(o),o}respondForQuery(e,t){return super.respondForQuery((n=>e(((e,l)=>{if(0===l.length){const e=new Error -throw e.errors=[{status:"404",title:"Not found"}],e}return l.forEach((e=>{e.Datacenter=t.dc,e.Namespace=t.ns||"default",e.Partition=t.partition||"default",e.uid=this.extractUid(e)})),n(e,l)}))),t)}respondForQueryRecord(e,t){return super.respondForQueryRecord((n=>e(((e,l)=>{if(l.forEach((e=>{e.Datacenter=t.dc,e.Namespace=t.ns||"default",e.Partition=t.partition||"default",e.uid=this.extractUid(e)})),void 0===(l=l.find((function(e){return e.Node.Node===t.node&&e.Service.ID===t.serviceId})))){const e=new Error -throw e.errors=[{status:"404",title:"Not found"}],e}return l.Namespace=l.Service.Namespace,l.Partition=l.Service.Partition,n(e,l)}))),t)}}e.default=o})) -define("consul-ui/serializers/service",["exports","consul-ui/serializers/application","consul-ui/models/service","@ember/object","consul-ui/utils/http/consul"],(function(e,t,n,l,r){function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class o extends t.default{constructor(){super(...arguments),i(this,"primaryKey",n.PRIMARY_KEY),i(this,"slugKey",n.SLUG_KEY)}respondForQuery(e,t){return super.respondForQuery((t=>e(((e,n)=>t(e,this._transformServicesPayload(n))))),t)}respondForQueryRecord(e,t){return super.respondForQueryRecord((n=>e(((e,r)=>n(e,{Name:t.id,Namespace:(0,l.get)(r,"firstObject.Service.Namespace"),Nodes:r})))),t)}createJSONApiDocumentFromServicesPayload(e,t,n){const{primaryKey:l,slugKey:i,fingerprint:o}=this -return{data:this._transformServicesPayload(t).map(o(l,i,n,e[r.HEADERS_NAMESPACE],e[r.HEADERS_PARTITION])).map((e=>({id:e.uid,type:"service",attributes:e})))}}_transformServicesPayload(e){const t={} -return e.filter((function(e){return"connect-proxy"!==e.Kind})).forEach((e=>{t[e.Name]=e})),e.filter((function(e){return"connect-proxy"===e.Kind})).forEach((e=>{e.ProxyFor&&e.ProxyFor.forEach((n=>{void 0!==t[n]&&(t[n].Proxy=e)}))})),e}}e.default=o})),define("consul-ui/serializers/session",["exports","consul-ui/serializers/application","consul-ui/models/session"],(function(e,t,n){function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class r extends t.default{constructor(){super(...arguments),l(this,"primaryKey",n.PRIMARY_KEY),l(this,"slugKey",n.SLUG_KEY)}respondForQueryRecord(e,t){return super.respondForQueryRecord((t=>e(((e,n)=>{if(0===n.length){const e=new Error -throw e.errors=[{status:"404",title:"Not found"}],e}return t(e,n[0])}))),t)}}e.default=r})),define("consul-ui/serializers/token",["exports","consul-ui/serializers/application","@ember/object","consul-ui/models/token","consul-ui/mixins/policy/as-many","consul-ui/mixins/role/as-many"],(function(e,t,n,l,r,i){function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class a extends(t.default.extend(r.default,i.default)){constructor(){super(...arguments),o(this,"primaryKey",l.PRIMARY_KEY),o(this,"slugKey",l.SLUG_KEY)}serialize(e,t){let n=super.serialize(...arguments) -return null!==n.Rules&&(n={ID:n.SecretID,Name:n.Description,Type:n.Type,Rules:n.Rules}),n&&delete n.SecretID,n}respondForSelf(e,t){return this.respondForQueryRecord(e,t)}respondForUpdateRecord(e,t,l){return super.respondForUpdateRecord((t=>e(((e,l)=>{if(void 0!==l.Policies&&null!==l.Policies||(l.Policies=[]),void 0!==l.ID){const e=this.store.peekAll("token").findBy("SecretID",l.ID) -e&&(l.SecretID=l.ID,l.AccessorID=(0,n.get)(e,"AccessorID"))}return t(e,l)}))),t,l)}}e.default=a})),define("consul-ui/serializers/topology",["exports","consul-ui/serializers/application","consul-ui/models/topology","@ember/service"],(function(e,t,n,l){var r,i,o -function a(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function u(e){for(var t=1;t{e.Intention.SourceName=e.Name,e.Intention.SourceNS=e.Namespace,e.Intention.DestinationName=t.id,e.Intention.DestinationNS=t.ns||"default",l.ensureID(e.Intention)})),i.Upstreams.forEach((e=>{e.Intention.SourceName=t.id,e.Intention.SourceNS=t.ns||"default",e.Intention.DestinationName=e.Name,e.Intention.DestinationNS=e.Namespace,l.ensureID(e.Intention)})),r(e,u(u({},i),{},{[n.SLUG_KEY]:t.id}))}))}),t)}},d=i.prototype,p="store",f=[r],m={configurable:!0,enumerable:!0,writable:!0,initializer:null},b={},Object.keys(m).forEach((function(e){b[e]=m[e]})),b.enumerable=!!b.enumerable,b.configurable=!!b.configurable,("value"in b||b.initializer)&&(b.writable=!0),b=f.slice().reverse().reduce((function(e,t){return t(d,p,e)||e}),b),h&&void 0!==b.initializer&&(b.value=b.initializer?b.initializer.call(h):void 0,b.initializer=void 0),void 0===b.initializer&&(Object.defineProperty(d,p,b),b=null),o=b,i) -var d,p,f,m,h,b -e.default=c})),define("consul-ui/services/-ensure-registered",["exports","@embroider/util/services/ensure-registered"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/-portal",["exports","ember-stargate/services/-portal"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/abilities",["exports","ember-can/services/can"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{parse(e){return super.parse(e.replace("use SSO","use authMethods").replace("service","zervice"))}}e.default=n})),define("consul-ui/services/atob",["exports","@ember/service","consul-ui/utils/atob"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{execute(){return(0,n.default)(...arguments)}}e.default=l})),define("consul-ui/services/auth-providers/oauth2-code-with-url-provider",["exports","torii/providers/oauth2-code","@ember/debug"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{constructor(){var e,t,n -super(...arguments),n="oidc-with-url",(t="name")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}buildUrl(){return this.baseUrl}open(e){const t=this.get("name"),l=this.buildUrl() -return this.get("popup").open(l,["state","code"],e).then((function(e){const l={authorizationState:e.state,authorizationCode:decodeURIComponent(e.code),provider:t} -return(0,n.runInDebug)((e=>console.info("Retrieved the following creds from the OAuth Provider",l))),l}))}close(){const e=this.get("popup.remote")||{} -if("function"==typeof e.close)return e.close()}}e.default=l})),define("consul-ui/services/btoa",["exports","@ember/service","consul-ui/utils/btoa"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{execute(){return(0,n.default)(...arguments)}}e.default=l})),define("consul-ui/services/can",["exports","ember-can/services/abilities"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/change",["exports","@ember/service","ember-changeset-validations","ember-changeset","consul-ui/utils/form/changeset","consul-ui/validations/intention-permission","consul-ui/validations/intention-permission-http-header"],(function(e,t,n,l,r,i,o){var a,u,s -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const c={"intention-permission":i.default,"intention-permission-http-header":o.default} -let d=(a=(0,t.inject)("schema"),u=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="schema",l=this,(n=s)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}init(){super.init(...arguments),this._validators=new Map}willDestroy(){this._validators=null}changesetFor(e,t){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{} -const o=this.validatorFor(e,i) -let a -if(o){let e=o -"function"!=typeof o&&(e=(0,n.default)(o)),a=(0,l.Changeset)(t,e,o,{changeset:r.default})}else a=(0,l.Changeset)(t) -return a}validatorFor(e){if(!this._validators.has(e)){const t=c[e] -let n -void 0!==t&&(n=t(this.schema)),this._validators.set(e,n)}return this._validators.get(e)}},p=u.prototype,f="schema",m=[a],h={configurable:!0,enumerable:!0,writable:!0,initializer:null},y={},Object.keys(h).forEach((function(e){y[e]=h[e]})),y.enumerable=!!y.enumerable,y.configurable=!!y.configurable,("value"in y||y.initializer)&&(y.writable=!0),y=m.slice().reverse().reduce((function(e,t){return t(p,f,e)||e}),y),b&&void 0!==y.initializer&&(y.value=y.initializer?y.initializer.call(b):void 0,y.initializer=void 0),void 0===y.initializer&&(Object.defineProperty(p,f,y),y=null),s=y,u) -var p,f,m,h,b,y -e.default=d})),define("consul-ui/services/client/connections",["exports","@ember/service"],(function(e,t){var n,l,r,i,o,a,u -function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let d=(n=(0,t.inject)("dom"),l=(0,t.inject)("env"),r=(0,t.inject)("data-source/service"),i=class extends t.default{constructor(){super(...arguments),s(this,"dom",o,this),s(this,"env",a,this),s(this,"data",u,this)}init(){super.init(...arguments),this._listeners=this.dom.listeners(),this.connections=new Set,this.addVisibilityChange()}willDestroy(){this._listeners.remove(),this.purge(),super.willDestroy(...arguments)}addVisibilityChange(){this._listeners.add(this.dom.document(),{visibilitychange:e=>{e.target.hidden&&this.purge(-1)}})}whenAvailable(e){const t=this.dom.document() -return t.hidden?new Promise((n=>{const l=this._listeners.add(t,{visibilitychange:function(t){l(),n(e)}})})):Promise.resolve(e)}purge(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;[...this.connections].forEach((function(t){t.abort(e)})),this.connections=new Set}acquire(e){if(this.connections.size>=this.env.var("CONSUL_HTTP_MAX_CONNECTIONS")){const t=this.data.closed() -let n=[...this.connections].find((e=>!!e.headers()["x-request-id"]&&t.includes(e.headers()["x-request-id"]))) -void 0===n&&"text/event-stream"===e.headers()["content-type"]&&(n=this.connections.values().next().value),void 0!==n&&(this.release(n),n.abort(429))}this.connections.add(e)}release(e){this.connections.delete(e)}},o=c(i.prototype,"dom",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=c(i.prototype,"env",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(i.prototype,"data",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) -e.default=d})),define("consul-ui/services/client/http",["exports","@ember/service","@ember/object","@ember/runloop","consul-ui/utils/http/headers","consul-ui/utils/http/consul","consul-ui/utils/http/create-url","consul-ui/utils/http/create-headers","consul-ui/utils/http/create-query-params"],(function(e,t,n,l,r,i,o,a,u){var s,c,d,p,f,m,h,b,y,g,v,O,P,x,w -function j(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function _(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}function k(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function S(e){for(var t=1;tC.stringify(this.sanitize(e)))) -const e=this.encoder.uriTag() -this.cache=(t,n)=>(t.uri=n(e),t.SyncTime=(new Date).getTime(),this.store.push({data:{id:t.uri,type:new URL(t.uri).protocol.slice(0,-1),attributes:t}}))}sanitize(e){return this.env.var("CONSUL_NSPACES_ENABLED")&&void 0!==e.ns&&null!==e.ns&&""!==e.ns||delete e.ns,this.env.var("CONSUL_PARTITIONS_ENABLED")&&void 0!==e.partition&&null!==e.partition&&""!==e.partition||delete e.partition,e}willDestroy(){this._listeners.remove(),super.willDestroy(...arguments)}url(){return this.parseURL(...arguments)}body(){const e=function(e){let t={} -const n=e.reduce((function(e,t,n){return-1!==(t=t.split("\n").map((e=>e.trim())).join("\n")).indexOf("\n\n")?n:e}),-1) -for(var l=arguments.length,r=new Array(l>1?l-1:0),i=1;i1?t-1:0),l=1;l0||Object.keys(d.data).length>0)&&(d.body=d.data) -else{const e=C.stringify(d.data) -e.length>0&&(-1!==d.url.indexOf("?")?d.url=`${d.url}&${e}`:d.url=`${d.url}?${e}`)}return d.headers[r.CONTENT_TYPE]="application/json; charset=utf-8",d.url=`${this.env.var("CONSUL_API_PREFIX")}${d.url}`,d}fetchWithToken(e,t){return this.settings.findBySlug("token").then((n=>fetch(`${this.env.var("CONSUL_API_PREFIX")}${e}`,S(S({},t),{},{credentials:"include",headers:S({"X-Consul-Token":void 0===n.SecretID?"":n.SecretID},t.headers)}))))}request(e){const t=this,n=this.cache -return e((function(e){for(var r=arguments.length,o=new Array(r>1?r-1:0),a=1;a{const r=S(S({},u),{},{headers:S({[i.HEADERS_TOKEN]:void 0===e.SecretID?"":e.SecretID},u.headers)}),o=t.transport.request(r) -return new Promise(((r,a)=>{const s=t._listeners.add(o,{open:e=>{t.acquire(e.target)},message:t=>{const o=S(S(S({},Object.entries(t.data.headers).reduce((function(e,t,n){let[l,r]=t -return M.includes(l)||(e[l]=r),e}),{})),u.clientHeaders),{},{[i.HEADERS_DATACENTER]:u.data.dc,[i.HEADERS_NAMESPACE]:u.data.ns||e.Namespace||"default",[i.HEADERS_PARTITION]:u.data.partition||e.Partition||"default"}),a=function(e){let l=e(o,t.data.response,n) -const r=l.meta||{} -return 2===r.version&&(Array.isArray(l.body)?l=new Proxy(l.body,{get:(e,t)=>"meta"===t?r:e[t]}):(l=l.body,l.meta=r)),l};(0,l.next)((()=>r(a)))},error:e=>{(0,l.next)((()=>a(e.error)))},close:e=>{t.release(e.target),s()}}) -o.fetch()}))}))}))}whenAvailable(e){return this.connections.whenAvailable(e)}abort(){return this.connections.purge(...arguments)}acquire(){return this.connections.acquire(...arguments)}release(){return this.connections.release(...arguments)}},y=_(b.prototype,"dom",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=_(b.prototype,"env",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=_(b.prototype,"connections",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=_(b.prototype,"transport",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=_(b.prototype,"settings",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=_(b.prototype,"encoder",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=_(b.prototype,"store",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b) -e.default=D})),define("consul-ui/services/client/transports/xhr",["exports","@ember/service","consul-ui/utils/http/create-headers","consul-ui/utils/http/xhr","consul-ui/utils/http/request","consul-ui/utils/http/error"],(function(e,t,n,l,r,i){function o(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function a(e){for(var t=1;t(this.xhr(n),t),t}}e.default=c})),define("consul-ui/services/clipboard/local-storage",["exports","@ember/service","clipboard"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class o extends n.default{constructor(e,t,n){super(e,t),this._cb=n}onClick(e){this._cb(this.text(e.delegateTarget||e.currentTarget)),this.emit("success",{})}}let a=(l=(0,t.inject)("-document"),r=class extends t.default{constructor(){var e,t,n,l,r,o,a -super(...arguments),e=this,t="doc",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a="clipboard",(o="key")in(r=this)?Object.defineProperty(r,o,{value:a,enumerable:!0,configurable:!0,writable:!0}):r[o]=a}execute(e,t){return new o(e,t,(e=>{this.doc.defaultView.localStorage.setItem(this.key,e)}))}},u=r.prototype,s="doc",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/services/clipboard/os",["exports","@ember/service","clipboard"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{execute(){return new n.default(...arguments)}}e.default=l})),define("consul-ui/services/code-mirror",["exports","ivy-codemirror/services/code-mirror"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/code-mirror/linter",["exports","@ember/service","consul-ui/utils/editor/lint"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const o=[{name:"JSON",mime:"application/json",mode:"javascript",ext:["json","map"],alias:["json5"]},{name:"HCL",mime:"text/x-ruby",mode:"ruby",ext:["rb"],alias:["jruby","macruby","rake","rb","rbx"]},{name:"YAML",mime:"text/x-yaml",mode:"yaml",ext:["yaml","yml"],alias:["yml"]},{name:"XML",mime:"application/xml",mode:"xml",htmlMode:!1,matchClosing:!0,alignCDATA:!1,ext:["xml"],alias:["xml"]}] -let a=(l=(0,t.inject)("dom"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="dom",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}modes(){return o}lint(){return(0,n.default)(...arguments)}getEditor(e){return this.dom.element("textarea + div",e).CodeMirror}},u=r.prototype,s="dom",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) -var u,s,c,d,p,f -e.default=a})),define("consul-ui/services/container",["exports","@ember/service"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{constructor(e){super(...arguments),this._owner=e,this._wm=new WeakMap}set(e,t){this._wm.set(t,e)}keyForClass(e){return this._wm.get(e)}get(e){return"string"!=typeof e&&(e=this.keyForClass(e)),this.lookup(e)}lookup(e){return this._owner.lookup(e)}resolveRegistration(e){return this._owner.resolveRegistration(e).prototype}}e.default=n})),define("consul-ui/services/data-sink/protocols/http",["exports","@ember/service","@ember/object"],(function(e,t,n){var l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,g,v -function O(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function P(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let x=(l=(0,t.inject)("client/http"),r=(0,t.inject)("settings"),i=(0,t.inject)("repository/intention"),o=(0,t.inject)("repository/kv"),a=(0,t.inject)("repository/nspace"),u=(0,t.inject)("repository/partition"),s=(0,t.inject)("repository/peer"),c=(0,t.inject)("repository/session"),d=class extends t.default{constructor(){super(...arguments),O(this,"client",p,this),O(this,"settings",f,this),O(this,"intention",m,this),O(this,"kv",h,this),O(this,"nspace",b,this),O(this,"partition",y,this),O(this,"peer",g,this),O(this,"session",v,this)}prepare(e,t,l){return(0,n.setProperties)(l,t)}persist(e,t){const[,,,,n]=e.split("/"),l=this[n] -return this.client.request((e=>l.persist(t,e)))}remove(e,t){const[,,,,n]=e.split("/"),l=this[n] -return this.client.request((e=>l.remove(t,e)))}},p=P(d.prototype,"client",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=P(d.prototype,"settings",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=P(d.prototype,"intention",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=P(d.prototype,"kv",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=P(d.prototype,"nspace",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=P(d.prototype,"partition",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=P(d.prototype,"peer",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=P(d.prototype,"session",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d) -e.default=x})),define("consul-ui/services/data-sink/protocols/local-storage",["exports","@ember/service","@ember/object"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,t.inject)("settings"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="settings",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}prepare(e,t){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{} -return null===t||""===t?l:(0,n.setProperties)(l,t)}persist(e,t){const n=e.split(":").pop() -return this.settings.persist({[n]:t})}remove(e,t){const n=e.split(":").pop() -return this.settings.delete(n)}},a=r.prototype,u="settings",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/services/data-sink/service",["exports","@ember/service"],(function(e,t){var n,l,r,i,o -function a(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function u(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const s=function(e){return-1===(e=e.toString()).indexOf("://")&&(e=`consul://${e}`),e.split("://")} -let c=(n=(0,t.inject)("data-sink/protocols/http"),l=(0,t.inject)("data-sink/protocols/local-storage"),r=class extends t.default{constructor(){super(...arguments),a(this,"consul",i,this),a(this,"settings",o,this)}prepare(e,t,n){const[l,r]=s(e) -return this[l].prepare(r,t,n)}persist(e,t){const[n,l]=s(e) -return this[n].persist(l,t)}remove(e,t){const[n,l]=s(e) -return this[n].remove(l,t)}},i=u(r.prototype,"consul",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o=u(r.prototype,"settings",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),r) -e.default=c})),define("consul-ui/services/data-source/protocols/http",["exports","@ember/service","@ember/application","consul-ui/decorators/data-source"],(function(e,t,n,l){var r,i,o,a,u -function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let d=(r=(0,t.inject)("client/http"),i=(0,t.inject)("data-source/protocols/http/blocking"),o=class extends t.default{constructor(){super(...arguments),s(this,"client",a,this),s(this,"type",u,this)}source(e,t){const r=(0,l.match)(e) -let i -return this.client.request((e=>{i=r.cb(r.params,(0,n.getOwner)(this),e)})),this.type.source(i,t)}},a=c(o.prototype,"client",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(o.prototype,"type",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) -e.default=d})),define("consul-ui/services/data-source/protocols/http/blocking",["exports","@ember/service","@ember/object","consul-ui/utils/dom/event-source","consul-ui/services/settings","consul-ui/services/client/http","consul-ui/utils/maybe-call"],(function(e,t,n,l,r,i,o){var a,u,s,c,d -function p(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function f(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let m=(a=(0,t.inject)("client/http"),u=(0,t.inject)("settings"),s=class extends t.default{constructor(){super(...arguments),p(this,"client",c,this),p(this,"settings",d,this)}source(e,t){return new l.BlockingEventSource(((t,l)=>{const a=l.close.bind(l) -return(0,o.default)((()=>t.cursor=void 0),(0,r.ifNotBlocking)(this.settings))().then((()=>e(t).then((0,o.default)(a,(0,r.ifNotBlocking)(this.settings))).then((function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{} -const t=(0,n.get)(e,"meta")||{} -return void 0===t.cursor&&void 0===t.interval&&a(),e})).catch((0,i.restartWhenAvailable)(this.client))))}),t)}},c=f(s.prototype,"client",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=f(s.prototype,"settings",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s) -e.default=m})),define("consul-ui/services/data-source/protocols/http/promise",["exports","@ember/service","consul-ui/utils/dom/event-source"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{source(e,t){return(0,n.once)(e,t)}}e.default=l})),define("consul-ui/services/data-source/protocols/local-storage",["exports","@ember/service","consul-ui/utils/dom/event-source"],(function(e,t,n){var l,r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(l=(0,t.inject)("settings"),r=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="repo",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}source(e,t){const l=e.split(":").pop() -return new n.StorageEventSource((e=>this.repo.findBySlug(l)),{key:e,uri:t.uri})}},a=r.prototype,u="repo",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/services/data-source/service",["exports","@ember/service","@ember/debug","consul-ui/utils/dom/event-source","@ember/runloop","mnemonist/multi-map"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m -function h(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function b(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let y=null,g=null,v=null -class O{constructor(e){this.uri=e}toString(){return this.uri}}let P=(o=(0,t.inject)("dom"),a=(0,t.inject)("encoder"),u=(0,t.inject)("data-source/protocols/http"),s=(0,t.inject)("data-source/protocols/local-storage"),c=class extends t.default{constructor(){super(...arguments),h(this,"dom",d,this),h(this,"encoder",p,this),h(this,"consul",f,this),h(this,"settings",m,this)}init(){super.init(...arguments),y=new Map,g=new Map,v=new i.default(Set),this._listeners=this.dom.listeners()}resetCache(){y=new Map}willDestroy(){(0,r.schedule)("afterRender",(()=>{this._listeners.remove(),g.forEach((function(e){e.close()})),y=null,g=null,v.clear(),v=null}))}source(e,t){const n=e(this.encoder.uriTag()) -return new Promise(((e,t)=>{const r={},i=this.open(n,r,!0) -i.configuration.ref=r -const o=this._listeners.add(i,{message:t=>{o(),e((0,l.proxy)(t.target,t.data))},error:e=>{o(),this.close(i,r),t(e.error)}}) -void 0!==i.getCurrentEvent()&&i.dispatchEvent(i.getCurrentEvent())}))}unwrap(e,t){const n=e._source -return v.set(n,t),v.remove(n,n.configuration.ref),delete n.configuration.ref,n}uri(e){return new O(e)}open(e,t){let l,r=arguments.length>2&&void 0!==arguments[2]&&arguments[2] -if(!(e instanceof O)&&"string"!=typeof e)return this.unwrap(e,t);(0,n.runInDebug)((t=>{e instanceof O||console.error(new Error(`DataSource '${e}' does not use the uri helper. Please ensure you use the uri helper to ensure correct encoding`))})),-1===(e=e.toString()).indexOf("://")&&(e=`consul://${e}`) -let[i,o]=e.split("://") -const a=this[i] -if(g.has(e))l=g.get(e),g.delete(e),g.set(e,l) -else{let t={} -y.has(e)&&(t=y.get(e)),t.uri=e,l=a.source(o,t) -const n=this._listeners.add(l,{close:t=>{const l=t.target,r=l.getCurrentEvent(),i=l.configuration.cursor -void 0!==r&&void 0!==i&&t.errors&&"401"!==t.errors[0].status&&y.set(e,{currentEvent:r,cursor:i}),v.has(l)||g.delete(e),n()}}) -g.set(e,l)}return(!v.has(l)||l.readyState>1||r)&&l.open(),v.set(l,t),l}close(e,t){e&&(v.remove(e,t),v.has(e)||(e.close(),2===e.readyState&&g.delete(e.configuration.uri)))}closed(){return[...g.entries()].filter((e=>{let[t,n]=e -return n.readyState>1})).map((e=>e[0]))}},d=b(c.prototype,"dom",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=b(c.prototype,"encoder",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=b(c.prototype,"consul",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=b(c.prototype,"settings",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c) -e.default=P})),define("consul-ui/services/data-structs",["exports","@ember/service","ngraph.graph"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{graph(){return(0,n.default)()}}e.default=l})),define("consul-ui/services/dom",["exports","@ember/service","@ember/object/internals","consul-ui/utils/dom/qsa-factory","consul-ui/utils/dom/sibling","consul-ui/utils/dom/closest","consul-ui/utils/dom/is-outside","consul-ui/utils/dom/get-component-factory","consul-ui/utils/dom/normalize-event","consul-ui/utils/dom/create-listeners","consul-ui/utils/dom/click-first-anchor"],(function(e,t,n,l,r,i,o,a,u,s,c){var d,p,f -function m(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const h=(0,l.default)() -let b,y -const g=(0,c.default)(i.default) -let v=(d=(0,t.inject)("-document"),p=class extends t.default{constructor(e){var t,n,l,c -super(...arguments),t=this,n="doc",c=this,(l=f)&&Object.defineProperty(t,n,{enumerable:l.enumerable,configurable:l.configurable,writable:l.writable,value:l.initializer?l.initializer.call(c):void 0}),m(this,"clickFirstAnchor",g),m(this,"closest",i.default),m(this,"sibling",r.default),m(this,"isOutside",o.default),m(this,"normalizeEvent",u.default),m(this,"listeners",s.default),y=new WeakMap,b=(0,a.default)(e)}willDestroy(){super.willDestroy(...arguments),y=null,b=null}document(){return this.doc}viewport(){return this.doc.defaultView}guid(e){return(0,n.guidFor)(e)}focus(e){if("string"==typeof e&&(e=this.element(e)),void 0!==e){let t=e.getAttribute("tabindex") -e.setAttribute("tabindex","0"),e.focus(),null===t?e.removeAttribute("tabindex"):e.setAttribute("tabindex",t)}}setEventTargetProperty(e,t,n){const l=e.target -return new Proxy(e,{get:function(r,i,o){return"target"===i?new Proxy(l,{get:function(r,i,o){return i===t?n(e.target[t]):l[i]}}):Reflect.get(...arguments)}})}setEventTargetProperties(e,t){const n=e.target -return new Proxy(e,{get:function(l,r,i){return"target"===r?new Proxy(n,{get:function(l,r,i){return void 0!==t[r]?t[r](e.target):n[r]}}):Reflect.get(...arguments)}})}root(){return this.doc.documentElement}elementById(e){return this.doc.getElementById(e)}elementsByTagName(e,t){return(t=void 0===t?this.doc:t).getElementsByTagName(e)}elements(e,t){return h(e,t)}element(e,t){return"#"===e.substr(0,1)?this.elementById(e.substr(1)):[...h(e,t)][0]}component(e,t){return b("string"!=typeof e?e:this.element(e,t))}components(e,t){return[...this.elements(e,t)].map((function(e){return b(e)})).filter((function(e){return null!=e}))}isInViewport(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0 -y.set(e,t) -let l=new IntersectionObserver(((e,t)=>{e.map((e=>{const t=y.get(e.target) -"function"==typeof t&&t(e.isIntersecting)}))}),{rootMargin:"0px",threshold:n}) -return l.observe(e),()=>{l.unobserve(e),y&&y.delete(e),l.disconnect(),l=null}}},O=p.prototype,P="doc",x=[d],w={configurable:!0,enumerable:!0,writable:!0,initializer:null},_={},Object.keys(w).forEach((function(e){_[e]=w[e]})),_.enumerable=!!_.enumerable,_.configurable=!!_.configurable,("value"in _||_.initializer)&&(_.writable=!0),_=x.slice().reverse().reduce((function(e,t){return t(O,P,e)||e}),_),j&&void 0!==_.initializer&&(_.value=_.initializer?_.initializer.call(j):void 0,_.initializer=void 0),void 0===_.initializer&&(Object.defineProperty(O,P,_),_=null),f=_,p) -var O,P,x,w,j,_ -e.default=v})) -define("consul-ui/services/encoder",["exports","@ember/service","@ember/object","@ember/debug","consul-ui/utils/atob","consul-ui/utils/btoa"],(function(e,t,n,l,r,i){function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class a extends t.default{constructor(){super(...arguments),o(this,"uriComponent",encodeURIComponent),o(this,"joiner",(function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"" -return(l,r)=>(r||Array(l.length).fill(t)).reduce(((t,r,i)=>`${t}${r}${e(l[i]||n)}`),"")}))}createRegExpEncoder(e,t){return function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:e=>e,r=!(arguments.length>2&&void 0!==arguments[2])||arguments[2] -return function(){let i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return""!==i?i.replace(e,((e,a)=>{const u=(0,n.get)(o,a) -return(0,l.runInDebug)((()=>{r&&void 0===u&&console.error(new Error(`${a} is undefined in ${i}`))})),t(u||"")})):""}}(e,t)}atob(){return(0,r.default)(...arguments)}btoa(){return(0,i.default)(...arguments)}uriJoin(){return this.joiner(this.uriComponent,"/","")(...arguments)}uriTag(){return this.tag(this.uriJoin.bind(this))}tag(e){return function(t){for(var n=arguments.length,l=new Array(n>1?n-1:0),r=1;rthis.success(n,e,void 0,t),error:n=>this.error(n,e,void 0,t)}}success(e,t){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:m,r=arguments.length>3?arguments[3]:void 0 -const i=(0,n.default)(t),o=(0,n.default)(l) -!1!==e&&(this.notify.clearMessages(),this.notify.add(s(s({},{timeout:6e3,extendedTimeout:300,destroyOnClick:!0}),{},{type:o(f),action:i(),item:e,model:r})))}error(e,t){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:m,r=arguments.length>3?arguments[3]:void 0 -const i=(0,n.default)(t),o=(0,n.default)(l) -this.notify.clearMessages(),this.logger.execute(e),"TransitionAborted"===e.name?this.notify.add(s(s({},{timeout:6e3,extendedTimeout:300,destroyOnClick:!0}),{},{type:o(f),action:i(),model:r})):this.notify.add(s(s({},{timeout:6e3,extendedTimeout:300,destroyOnClick:!0}),{},{type:o("error",e),action:i(),error:e,model:r}))}async execute(e,t,n,l){let r -try{r=await e(),this.success(r,t,n,l)}catch(i){this.error(i,t,n,l)}}},o=p(i.prototype,"notify",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=p(i.prototype,"logger",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) -e.default=h})),define("consul-ui/services/filter",["exports","@ember/service","consul-ui/utils/filter","consul-ui/filter/predicates/service","consul-ui/filter/predicates/service-instance","consul-ui/filter/predicates/health-check","consul-ui/filter/predicates/node","consul-ui/filter/predicates/kv","consul-ui/filter/predicates/intention","consul-ui/filter/predicates/token","consul-ui/filter/predicates/policy","consul-ui/filter/predicates/auth-method","consul-ui/filter/predicates/peer"],(function(e,t,n,l,r,i,o,a,u,s,c,d,p){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const f={service:(0,n.andOr)(l.default),"service-instance":(0,n.andOr)(r.default),"health-check":(0,n.andOr)(i.default),"auth-method":(0,n.andOr)(d.default),node:(0,n.andOr)(o.default),kv:(0,n.andOr)(a.default),intention:(0,n.andOr)(u.default),token:(0,n.andOr)(s.default),policy:(0,n.andOr)(c.default),peer:(0,n.andOr)(p.default)} -class m extends t.default{predicate(e){return f[e]}}e.default=m})),define("consul-ui/services/flash-messages",["exports","ember-cli-flash/services/flash-messages"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/form",["exports","@ember/service","consul-ui/utils/form/builder","consul-ui/forms/kv","consul-ui/forms/token","consul-ui/forms/policy","consul-ui/forms/role","consul-ui/forms/intention"],(function(e,t,n,l,r,i,o,a){var u,s,c,d,p -function f(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function m(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const h=(0,n.default)(),b={kv:l.default,token:r.default,policy:i.default,role:o.default,intention:a.default} -let y=(u=(0,t.inject)("repository/role"),s=(0,t.inject)("repository/policy"),c=class extends t.default{constructor(){var e,t,n -super(...arguments),f(this,"role",d,this),f(this,"policy",p,this),n=[],(t="forms")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}build(e,t){return h(...arguments)}form(e){let t=this.forms[e] -if(void 0===t&&(t=this.forms[e]=b[e](this),"role"===e||"policy"===e)){const n=this[e] -t.clear((function(e){return n.create(e)})),t.submit((function(e){return n.persist(e)}))}return t}},d=m(c.prototype,"role",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=m(c.prototype,"policy",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c) -e.default=y})),define("consul-ui/services/hcp",["exports","@ember/service","@ember/debug"],(function(e,t,n){var l,r,i,o,a,u,s -function c(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function d(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let p=(l=(0,t.inject)("env"),r=(0,t.inject)("repository/token"),i=(0,t.inject)("settings"),o=class extends t.default{constructor(){super(...arguments),c(this,"env",a,this),c(this,"tokenRepo",u,this),c(this,"settings",s,this)}async updateTokenIfNecessary(e){if(e){const l=await this.settings.findBySlug("token") -if(e&&e!==l.SecretID)try{const t=await this.tokenRepo.self({secret:e,dc:this.env.var("CONSUL_DATACENTER_LOCAL")}) -await this.settings.persist({token:{AccessorID:t.AccessorID,SecretID:t.SecretID,Namespace:t.Namespace,Partition:t.Partition}})}catch(t){(0,n.runInDebug)((e=>console.error(t)))}}}},a=d(o.prototype,"env",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=d(o.prototype,"tokenRepo",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s=d(o.prototype,"settings",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) -e.default=p})),define("consul-ui/services/i18n",["exports","ember-intl/services/intl","@ember/service"],(function(e,t,n){var l,r,i -function o(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function a(e){for(var t=1;t(e[t]=this.env.var(t),e)),{}) -return a(a({},e),t)}},d=r.prototype,p="env",f=[l],m={configurable:!0,enumerable:!0,writable:!0,initializer:null},b={},Object.keys(m).forEach((function(e){b[e]=m[e]})),b.enumerable=!!b.enumerable,b.configurable=!!b.configurable,("value"in b||b.initializer)&&(b.writable=!0),b=f.slice().reverse().reduce((function(e,t){return t(d,p,e)||e}),b),h&&void 0!==b.initializer&&(b.value=b.initializer?b.initializer.call(h):void 0,b.initializer=void 0),void 0===b.initializer&&(Object.defineProperty(d,p,b),b=null),i=b,r) -var d,p,f,m,h,b -e.default=c})),define("consul-ui/services/in-viewport",["exports","ember-in-viewport/services/in-viewport"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/intl",["exports","ember-intl/services/intl"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/keyboard",["exports","ember-keyboard/services/keyboard.js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/local-storage",["exports","@ember/service","@ember/application","consul-ui/config/environment"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.storageFor=function(e){return function(){return{get(){return(0,n.getOwner)(this).lookup("service:localStorage").getBucket(e)}}}},e.default=void 0 -class r{constructor(){this.data=new Map}getItem(e){return this.data.get(e)}setItem(e,t){return this.data.set(e,t.toString())}seed(e){const t=new Map -Object.keys(e).forEach((n=>{t.set(n,e[n].toString())})),this.data=t}}class i extends t.default{constructor(){super(...arguments),this.storage="test"===l.default.environment?new r:window.localStorage,this.buckets=new Map}getBucket(e){const t=this.buckets.get(e) -return t||this._setupBucket(e)}_setupBucket(e){const t=new(0,(0,n.getOwner)(this).factoryFor(`storage:${e}`).class)(e,this.storage) -return this.buckets.set(e,t),t}}e.default=i})),define("consul-ui/services/logger",["exports","@ember/service","@ember/debug"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends t.default{execute(e){(0,n.runInDebug)((()=>{(e=void 0!==e.error?e.error:e)instanceof Error?console.error(e):console.log(e)}))}}e.default=l})),define("consul-ui/services/page-title-list",["exports","ember-page-title/services/page-title-list"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/page-title",["exports","ember-page-title/services/page-title"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/popup",["exports","torii/services/popup"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/repository",["exports","@ember/service","@ember/debug","@ember/utils","@ember/object","validated-changeset","consul-ui/utils/http/error","consul-ui/abilities/base"],(function(e,t,n,l,r,i,o,a){var u,s,c,d,p,f,m -function h(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function b(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.softDelete=void 0 -e.softDelete=(e,t)=>e.store.adapterFor(e.getModelName()).rpc(((e,t,n,l)=>e.requestForDeleteRecord(t,n,l)),((e,n,l,r)=>t),t,e.getModelName()) -let y=(u=(0,t.inject)("store"),s=(0,t.inject)("env"),c=(0,t.inject)("repository/permission"),d=class extends t.default{constructor(){super(...arguments),h(this,"store",p,this),h(this,"env",f,this),h(this,"permissions",m,this)}getModelName(){}getPrimaryKey(){}getSlugKey(){}async authorizeBySlug(e,t,n){return n.resources=await this.permissions.findBySlug(n,this.getModelName()),this.validatePermissions(e,t,n)}async authorizeByPermissions(e,t,n){return n.resources=await this.permissions.authorize(n),this.validatePermissions(e,t,n)}async validatePermissions(e,t,n){if(n.resources.length>0){const e=n.resources.find((e=>e.Access===t)) -if(e&&!1===e.Allow){const e=new o.default(403) -throw e.errors=[{status:"403"}],e}}const l=await e(n.resources) -return(0,r.get)(l,"Resources")&&(0,r.set)(l,"Resources",n.resources),l}shouldReconcile(e,t){if((0,r.get)(e,"Datacenter")!==t.dc)return!1 -if(this.env.var("CONSUL_NSPACES_ENABLED")){const n=(0,r.get)(e,"Namespace") -if(void 0!==n&&n!==t.ns)return!1}if(this.env.var("CONSUL_PARTITIONS_ENABLED")){const n=(0,r.get)(e,"Partition") -if(void 0!==n&&n!==t.partition)return!1}return!0}reconcile(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -void 0!==e.date&&this.store.peekAll(this.getModelName()).forEach((n=>{const l=(0,r.get)(n,"SyncTime") -!n.isDeleted&&void 0!==l&&l!=e.date&&this.shouldReconcile(n,t)&&this.store.unloadRecord(n)}))}peekOne(e){return this.store.peekRecord(this.getModelName(),e)}peekAll(){return this.store.peekAll(this.getModelName())}cached(e){const t=Object.entries(e) -return this.store.peekAll(this.getModelName()).filter((e=>t.every((t=>{let[n,l]=t -return e[n]===l}))))}async findAllByDatacenter(e){return this.findAll(...arguments)}async findAll(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.query(e)}async query(){let e,t,n,l=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -try{n=await this.store.query(this.getModelName(),l),t=n.meta}catch(o){switch((0,r.get)(o,"errors.firstObject.status")){case"404":case"403":t={date:Number.POSITIVE_INFINITY},e=o -break -default:throw o}}if(void 0!==t&&this.reconcile(t,l,i),void 0!==e)throw e -return n}async findBySlug(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return""===e.id?this.create({Datacenter:e.dc,Namespace:e.ns,Partition:e.partition}):(void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.authorizeBySlug((()=>this.store.queryRecord(this.getModelName(),e)),a.ACCESS_READ,e))}create(e){return this.store.createRecord(this.getModelName(),e)}persist(e){return(0,i.isChangeset)(e)&&(e.execute(),e=e.data),(0,r.set)(e,"SyncTime",void 0),e.save()}remove(e){let t=e -return void 0===e.destroyRecord&&(t=e.get("data")),"object"===(0,l.typeOf)(t)&&(t=this.store.peekRecord(this.getModelName(),t[this.getPrimaryKey()])),t.destroyRecord().then((e=>this.store.unloadRecord(e)))}invalidate(){this.store.unloadAll(this.getModelName())}},p=b(d.prototype,"store",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=b(d.prototype,"env",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=b(d.prototype,"permissions",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d) -e.default=y})),define("consul-ui/services/repository/auth-method",["exports","consul-ui/services/repository","consul-ui/models/auth-method","consul-ui/decorators/data-source"],(function(e,t,n,l){var r,i,o -function a(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let u=(r=(0,l.default)("/:partition/:ns/:dc/auth-methods"),i=(0,l.default)("/:partition/:ns/:dc/auth-method/:id"),o=class extends t.default{getModelName(){return"auth-method"}getPrimaryKey(){return n.PRIMARY_KEY}getSlugKey(){return n.SLUG_KEY}async findAllByDatacenter(){return super.findAllByDatacenter(...arguments)}async findBySlug(){return super.findBySlug(...arguments)}},a(o.prototype,"findAllByDatacenter",[r],Object.getOwnPropertyDescriptor(o.prototype,"findAllByDatacenter"),o.prototype),a(o.prototype,"findBySlug",[i],Object.getOwnPropertyDescriptor(o.prototype,"findBySlug"),o.prototype),o) -e.default=u})),define("consul-ui/services/repository/binding-rule",["exports","consul-ui/services/repository","consul-ui/models/binding-rule","consul-ui/decorators/data-source"],(function(e,t,n,l){var r,i -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let o=(r=(0,l.default)("/:partition/:ns/:dc/binding-rules/for-auth-method/:authmethod"),i=class extends t.default{getModelName(){return"binding-rule"}getPrimaryKey(){return n.PRIMARY_KEY}getSlugKey(){return n.SLUG_KEY}async findAllByAuthMethod(){return super.findAll(...arguments)}},a=i.prototype,u="findAllByAuthMethod",s=[r],c=Object.getOwnPropertyDescriptor(i.prototype,"findAllByAuthMethod"),d=i.prototype,p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i) -var a,u,s,c,d,p -e.default=o})),define("consul-ui/services/repository/coordinate",["exports","consul-ui/services/repository","consul-ui/decorators/data-source","consul-ui/utils/tomography","consul-ui/utils/distance"],(function(e,t,n,l,r){var i,o,a -function u(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const s=(0,l.default)(r.default) -let c=(i=(0,n.default)("/:partition/:ns/:dc/coordinates"),o=(0,n.default)("/:partition/:ns/:dc/coordinates/for-node/:id"),a=class extends t.default{getModelName(){return"coordinate"}async findAllByDatacenter(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.store.query(this.getModelName(),e)}async findAllByNode(e,t){const n=await this.findAllByDatacenter(e,t) -let l={} -return n.length>1&&(l=s(e.id,n)),l.meta=n.meta,l}},u(a.prototype,"findAllByDatacenter",[i],Object.getOwnPropertyDescriptor(a.prototype,"findAllByDatacenter"),a.prototype),u(a.prototype,"findAllByNode",[o],Object.getOwnPropertyDescriptor(a.prototype,"findAllByNode"),a.prototype),a) -e.default=c})),define("consul-ui/services/repository/dc",["exports","@ember/error","@ember/service","consul-ui/services/repository","consul-ui/decorators/data-source","consul-ui/utils/http/consul"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p -function f(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}function m(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function h(e){for(var t=1;t{const l=Object.entries(e).find((e=>{let[t,n]=e -return t.toLowerCase()===i.HEADERS_DEFAULT_ACL_POLICY.toLowerCase()}))[1]||"allow" -return{meta:{version:2,uri:a},body:t.map((e=>n({Name:e,Datacenter:"",Local:e===u,Primary:e===s,DefaultACLPolicy:l},(t=>t`${y}:///${""}/${""}/${e}/datacenter`))))}}))}async fetch(e,t,n){let{partition:l,ns:r,dc:i}=e,{uri:o}=t -return(await(n` - GET /v1/operator/autopilot/state?${{dc:i}} - X-Request-ID: ${o} - `))(((e,t,n)=>{const l=Object.values(t.Servers),r=[] -return{meta:{version:2,uri:o},body:n(h(h({},t),{},{Servers:l,RedundancyZones:Object.entries(t.RedundancyZones||{}).map((e=>{let[n,l]=e -return h(h({},l),{},{Name:n,Healthy:!0,Servers:l.Servers.reduce(((e,n)=>{const l=t.Servers[n] -return r.push(l.ID),e.push(l),e}),[])})})),ReadReplicas:(t.ReadReplicas||[]).map((e=>(r.push(e),t.Servers[e]))),Default:{Servers:l.filter((e=>!r.includes(e.ID)))}}),(e=>e`${y}:///${""}/${""}/${i}/datacenter`))}}))}async fetchCatalogHealth(e,t,n){let{partition:l,ns:r,dc:i}=e,{uri:o}=t -return(await(n` - GET /v1/internal/ui/catalog-overview?${{dc:i,stale:null}} - X-Request-ID: ${o} - `))(((e,t,n)=>{const l=["Nodes","Services","Checks"].reduce(((e,n)=>((e,t,n)=>t[n].reduce(((e,t)=>(["Partition","Namespace"].forEach((l=>{let r=e[l][t[l]] -void 0===r&&(r=e[l][t[l]]={Name:t[l]}),void 0===r[n]&&(r[n]=h({},g)),r[n].Total+=t.Total,r[n].Passing+=t.Passing,r[n].Warning+=t.Warning,r[n].Critical+=t.Critical})),e.Datacenter[n].Total+=t.Total,e.Datacenter[n].Passing+=t.Passing,e.Datacenter[n].Warning+=t.Warning,e.Datacenter[n].Critical+=t.Critical,e)),e))(e,t,n)),{Datacenter:{Name:i,Nodes:h({},g),Services:h({},g),Checks:h({},g)},Partition:{},Namespace:{}}) -return{meta:{version:2,uri:o,interval:3e4},body:h({Datacenter:l.Datacenter,Partitions:Object.values(l.Partition),Namespaces:Object.values(l.Namespace)},t)}}))}async find(e){const n=this.store.peekAll("dc").findBy("Name",e.name) -if(void 0===n){const e=new t.default("Page not found") -throw e.status="404",{errors:[e]}}return n}},p=f(d.prototype,"env",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f(d.prototype,"fetchAll",[a],Object.getOwnPropertyDescriptor(d.prototype,"fetchAll"),d.prototype),f(d.prototype,"fetch",[u],Object.getOwnPropertyDescriptor(d.prototype,"fetch"),d.prototype),f(d.prototype,"fetchCatalogHealth",[s],Object.getOwnPropertyDescriptor(d.prototype,"fetchCatalogHealth"),d.prototype),f(d.prototype,"find",[c],Object.getOwnPropertyDescriptor(d.prototype,"find"),d.prototype),d) -e.default=v})),define("consul-ui/services/repository/discovery-chain",["exports","@ember/service","@ember/object","consul-ui/services/repository","consul-ui/decorators/data-source"],(function(e,t,n,l,r){var i,o,a,u -function s(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let c=(i=(0,t.inject)("repository/dc"),o=(0,r.default)("/:partition/:ns/:dc/discovery-chain/:id"),a=class extends l.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="dcs",l=this,(n=u)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"discovery-chain"}findBySlug(e){const t=this.dcs.peekAll().findBy("Name",e.dc) -return void 0===t||(0,n.get)(t,"MeshEnabled")?super.findBySlug(...arguments).catch((e=>{const l=(0,n.get)(e,"errors.firstObject.status"),r=((0,n.get)(e,"errors.firstObject.detail")||"").trim() -if("500"!==l)throw e -void 0!==t&&r.endsWith("Connect must be enabled in order to use this endpoint")&&(0,n.set)(t,"MeshEnabled",!1)})):Promise.resolve()}},u=s(a.prototype,"dcs",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s(a.prototype,"findBySlug",[o],Object.getOwnPropertyDescriptor(a.prototype,"findBySlug"),a.prototype),a) -e.default=c})),define("consul-ui/services/repository/intention-permission-http-header",["exports","consul-ui/services/repository"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{getModelName(){return"intention-permission-http-header"}create(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{} -return this.store.createFragment(this.getModelName(),e)}persist(e){return e.execute()}}e.default=n})),define("consul-ui/services/repository/intention-permission",["exports","consul-ui/services/repository"],(function(e,t){function n(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function l(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:{} -return this.store.createFragment(this.getModelName(),l(l({},e),{},{HTTP:this.store.createFragment("intention-permission-http",e.HTTP||{})}))}persist(e){return e.execute()}}e.default=i})),define("consul-ui/services/repository/intention",["exports","@ember/object","@ember/service","consul-ui/services/repository","consul-ui/models/intention","consul-ui/decorators/data-source"],(function(e,t,n,l,r,i){var o,a,u,s,c,d -function p(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function f(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function m(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let h=(o=(0,n.inject)("env"),a=(0,i.default)("/:partition/:ns/:dc/intentions"),u=(0,i.default)("/:partition/:ns/:dc/intention/:id"),s=(0,i.default)("/:partition/:ns/:dc/intentions/for-service/:id"),c=class extends l.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=d)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),f(this,"managedByCRDs",!1)}getModelName(){return"intention"}getPrimaryKey(){return r.PRIMARY_KEY}create(e){return delete e.Namespace,super.create(function(e){for(var t=1;te.IsManagedByCRD))),this.managedByCRDs}async authorizeBySlug(e,t,n){const[,l,,r]=n.id.split(":"),i=this.permissions.abilityFor(this.getModelName()) -return n.resources=i.generateForSegment(l).concat(i.generateForSegment(r)),this.authorizeByPermissions(e,t,n)}async persist(e){const n=await super.persist(...arguments) -return(0,t.get)(n,"Action.length")&&(0,t.set)(n,"Permissions",[]),n}async findAll(){return super.findAll(...arguments)}async findBySlug(e){let t -if(""===e.id){const n=this.env.var("CONSUL_NSPACES_ENABLED")?"*":"default",l="default" -t=await this.create({SourceNS:e.nspace||n,DestinationNS:e.nspace||n,SourcePartition:e.partition||l,DestinationPartition:e.partition||l,Datacenter:e.dc,Partition:e.partition})}else t=super.findBySlug(...arguments) -return t}async findByService(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -const n={dc:e.dc,nspace:e.nspace,filter:`SourceName == "${e.id}" or DestinationName == "${e.id}" or SourceName == "*" or DestinationName == "*"`} -return void 0!==t.cursor&&(n.index=t.cursor,n.uri=t.uri),this.store.query(this.getModelName(),n)}},d=m(c.prototype,"env",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m(c.prototype,"findAll",[a],Object.getOwnPropertyDescriptor(c.prototype,"findAll"),c.prototype),m(c.prototype,"findBySlug",[u],Object.getOwnPropertyDescriptor(c.prototype,"findBySlug"),c.prototype),m(c.prototype,"findByService",[s],Object.getOwnPropertyDescriptor(c.prototype,"findByService"),c.prototype),c) -e.default=h})),define("consul-ui/services/repository/kv",["exports","consul-ui/services/repository","consul-ui/utils/isFolder","@ember/object","consul-ui/models/kv","consul-ui/decorators/data-source"],(function(e,t,n,l,r,i){var o,a,u -function s(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let c=(o=(0,i.default)("/:partition/:ns/:dc/kv/:id"),a=(0,i.default)("/:partition/:ns/:dc/kvs/:id"),u=class extends t.default{getModelName(){return"kv"}getPrimaryKey(){return r.PRIMARY_KEY}shouldReconcile(e,t){return super.shouldReconcile(...arguments)&&e.Key.startsWith(t.id)}async findBySlug(e){let t -if((0,n.default)(e.id)){const n=JSON.stringify([e.partition,e.ns,e.dc,e.id]) -t=this.store.peekRecord(this.getModelName(),n),t||(t=await this.create({Key:e.id,Datacenter:e.dc,Namespace:e.ns,Partition:e.partition}))}else t=""===e.id?await this.create({Datacenter:e.dc,Namespace:e.ns,Partition:e.partition}):await super.findBySlug(...arguments) -return t}async findAllBySlug(e){e.separator="/","/"===e.id&&(e.id="") -let t=await this.findAll(...arguments) -const n=t.meta -return t=t.filter((t=>e.id!==(0,l.get)(t,"Key"))),t.meta=n,t}},s(u.prototype,"findBySlug",[o],Object.getOwnPropertyDescriptor(u.prototype,"findBySlug"),u.prototype),s(u.prototype,"findAllBySlug",[a],Object.getOwnPropertyDescriptor(u.prototype,"findAllBySlug"),u.prototype),u) -e.default=c})),define("consul-ui/services/repository/license",["exports","consul-ui/services/repository","consul-ui/decorators/data-source"],(function(e,t,n){var l,r -function i(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function o(e){for(var t=1;t({meta:{version:2,uri:o,interval:3e4},body:n(u(t,{dc:i}),(e=>e`${"license"}:///${l}/${r}/${i}/license/${t.License.license_id}`))})))}},c=r.prototype,d="find",p=[l],f=Object.getOwnPropertyDescriptor(r.prototype,"find"),m=r.prototype,h={},Object.keys(f).forEach((function(e){h[e]=f[e]})),h.enumerable=!!h.enumerable,h.configurable=!!h.configurable,("value"in h||h.initializer)&&(h.writable=!0),h=p.slice().reverse().reduce((function(e,t){return t(c,d,e)||e}),h),m&&void 0!==h.initializer&&(h.value=h.initializer?h.initializer.call(m):void 0,h.initializer=void 0),void 0===h.initializer&&(Object.defineProperty(c,d,h),h=null),r) -var c,d,p,f,m,h -e.default=s})),define("consul-ui/services/repository/metrics",["exports","@ember/service","consul-ui/services/repository","consul-ui/decorators/data-source"],(function(e,t,n,l){var r,i,o,a,u,s,c,d,p,f -function m(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function h(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let b=(r=(0,t.inject)("ui-config"),i=(0,t.inject)("env"),o=(0,t.inject)("client/http"),a=(0,l.default)("/:partition/:ns/:dc/metrics/summary-for-service/:slug/:protocol"),u=(0,l.default)("/:partition/:ns/:dc/metrics/upstream-summary-for-service/:slug/:protocol"),s=(0,l.default)("/:partition/:ns/:dc/metrics/downstream-summary-for-service/:slug/:protocol"),c=class extends n.default{constructor(){var e,t,n -super(...arguments),m(this,"config",d,this),m(this,"env",p,this),m(this,"client",f,this),n=null,(t="error")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}getModelName(){return"metrics"}init(){super.init(...arguments) -const e=this.config.getSync(),t=e.metrics_provider_options||{} -t.metrics_proxy_enabled=e.metrics_proxy_enabled -const n=e.metrics_provider||"prometheus" -t.fetch=(e,t)=>this.client.fetchWithToken(`/v1/internal/ui/metrics-proxy${e}`,t) -try{this.provider=window.consul.getMetricsProvider(n,t)}catch(l){this.error=new Error(`metrics provider not initialized: ${l}`),console.error(this.error)}}findServiceSummary(e){if(this.error)return Promise.reject(this.error) -const t=[this.provider.serviceRecentSummarySeries(e.slug,e.dc,e.ns,e.protocol,{}),this.provider.serviceRecentSummaryStats(e.slug,e.dc,e.ns,e.protocol,{})] -return Promise.all(t).then((e=>({meta:{interval:this.env.var("CONSUL_METRICS_POLL_INTERVAL")||1e4},series:e[0],stats:e[1].stats})))}findUpstreamSummary(e){return this.error?Promise.reject(this.error):this.provider.upstreamRecentSummaryStats(e.slug,e.dc,e.ns,{}).then((e=>(e.meta={interval:this.env.var("CONSUL_METRICS_POLL_INTERVAL")||1e4},e)))}findDownstreamSummary(e){return this.error?Promise.reject(this.error):this.provider.downstreamRecentSummaryStats(e.slug,e.dc,e.ns,{}).then((e=>(e.meta={interval:this.env.var("CONSUL_METRICS_POLL_INTERVAL")||1e4},e)))}},d=h(c.prototype,"config",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=h(c.prototype,"env",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=h(c.prototype,"client",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h(c.prototype,"findServiceSummary",[a],Object.getOwnPropertyDescriptor(c.prototype,"findServiceSummary"),c.prototype),h(c.prototype,"findUpstreamSummary",[u],Object.getOwnPropertyDescriptor(c.prototype,"findUpstreamSummary"),c.prototype),h(c.prototype,"findDownstreamSummary",[s],Object.getOwnPropertyDescriptor(c.prototype,"findDownstreamSummary"),c.prototype),c) -e.default=b})),define("consul-ui/services/repository/node",["exports","consul-ui/services/repository","consul-ui/decorators/data-source"],(function(e,t,n){var l,r,i,o -function a(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let u=(l=(0,n.default)("/:partition/:ns/:dc/nodes"),r=(0,n.default)("/:partition/:ns/:dc/node/:id/:peer"),i=(0,n.default)("/:partition/:ns/:dc/leader"),o=class extends t.default{getModelName(){return"node"}async findAllByDatacenter(){return super.findAllByDatacenter(...arguments)}async findBySlug(){return super.findBySlug(...arguments)}findLeader(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return void 0!==t.refresh&&(e.uri=t.uri),this.store.queryLeader(this.getModelName(),e)}},a(o.prototype,"findAllByDatacenter",[l],Object.getOwnPropertyDescriptor(o.prototype,"findAllByDatacenter"),o.prototype),a(o.prototype,"findBySlug",[r],Object.getOwnPropertyDescriptor(o.prototype,"findBySlug"),o.prototype),a(o.prototype,"findLeader",[i],Object.getOwnPropertyDescriptor(o.prototype,"findLeader"),o.prototype),o) -e.default=u})),define("consul-ui/services/repository/nspace",["exports","@ember/service","@ember/debug","consul-ui/services/repository","consul-ui/models/nspace","consul-ui/decorators/data-source","consul-ui/utils/form/builder"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m,h,b,y,g,v,O,P -function x(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function w(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let j=(a=(0,t.inject)("router"),u=(0,t.inject)("container"),s=(0,t.inject)("env"),c=(0,t.inject)("form"),d=(0,t.inject)("settings"),p=(0,t.inject)("repository/permission"),f=(0,i.default)("/:partition/:ns/:dc/namespaces"),m=(0,i.default)("/:partition/:ns/:dc/namespace/:id"),h=class extends l.default{constructor(){super(...arguments),x(this,"router",b,this),x(this,"container",y,this),x(this,"env",g,this),x(this,"form",v,this),x(this,"settings",O,this),x(this,"permissions",P,this)}getPrimaryKey(){return r.PRIMARY_KEY}getSlugKey(){return r.SLUG_KEY}getModelName(){return"nspace"}async findAll(){return this.permissions.can("use nspaces")?super.findAll(...arguments).catch((()=>[])):[]}async findBySlug(e){let t -return t=""===e.id?await this.create({Datacenter:e.dc,Partition:e.partition,ACLs:{PolicyDefaults:[],RoleDefaults:[]}}):await super.findBySlug(...arguments),(0,o.defaultChangeset)(t)}remove(e){return(0,l.softDelete)(this,e)}authorize(e,t){return this.env.var("CONSUL_ACLS_ENABLED")?this.store.authorize(this.getModelName(),{dc:e,ns:t}).catch((function(e){return[]})):Promise.resolve([{Resource:"operator",Access:"write",Allow:!0}])}async getActive(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"" -if(this.permissions.can("use nspaces"))return{Name:"default"} -const t=this.store.peekAll("nspace").toArray() -if(0===e.length){e=(await this.settings.findBySlug("token")).Namespace||"default"}return 1===t.length?t[0]:function(e,t){let l=e.find((function(e){return e.Name===t.Name})) -return void 0===l&&((0,n.runInDebug)((n=>console.info(`${t.Name} not found in [${e.map((e=>e.Name)).join(", ")}]`))),l=e.find((function(e){return"default"===e.Name})),void 0===l&&(l=e[0])),l}(t,{Name:e})}},b=w(h.prototype,"router",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=w(h.prototype,"container",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=w(h.prototype,"env",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=w(h.prototype,"form",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=w(h.prototype,"settings",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=w(h.prototype,"permissions",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w(h.prototype,"findAll",[f],Object.getOwnPropertyDescriptor(h.prototype,"findAll"),h.prototype),w(h.prototype,"findBySlug",[m],Object.getOwnPropertyDescriptor(h.prototype,"findBySlug"),h.prototype),h) -e.default=j})) -define("consul-ui/services/repository/oidc-provider",["exports","@ember/service","consul-ui/services/repository","@ember/application","@ember/object","consul-ui/decorators/data-source"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f -function m(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function h(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const b="oidc-with-url" -let y=(o=(0,t.inject)("torii"),a=(0,t.inject)("settings"),u=(0,i.default)("/:partition/:ns/:dc/oidc/providers"),s=(0,i.default)("/:partition/:ns/:dc/oidc/provider/:id"),c=(0,i.default)("/:partition/:ns/:dc/oidc/authorize/:id/:code/:state"),d=class extends n.default{constructor(){super(...arguments),m(this,"manager",p,this),m(this,"settings",f,this)}init(){super.init(...arguments),this.provider=(0,l.getOwner)(this).lookup("torii-provider:oidc-with-url")}getModelName(){return"oidc-provider"}async findAllByDatacenter(){const e=await super.findAllByDatacenter(...arguments) -if(0===e.length){const e=new Error("Not found") -return e.statusCode=404,void this.store.adapterFor(this.getModelName()).error(e)}return e}async findBySlug(e){const t=await this.settings.findBySlug("token")||{} -return super.findBySlug({ns:e.ns||t.Namespace||"default",partition:e.partition||t.Partition||"default",dc:e.dc,id:e.id})}authorize(e){return this.store.authorize(this.getModelName(),e)}logout(e,t,n,l,r){const i={id:e} -return this.store.logout(this.getModelName(),i)}close(){this.manager.close(b)}findCodeByURL(e){return(0,r.set)(this.provider,"baseUrl",e),this.manager.open(b,{}).catch((e=>{let t -if(!0===e.message.startsWith("remote was closed"))t=new Error("Remote was closed"),t.statusCode=499 -else t=new Error(e.message),t.statusCode=500 -this.store.adapterFor(this.getModelName()).error(t)}))}},p=h(d.prototype,"manager",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=h(d.prototype,"settings",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h(d.prototype,"findAllByDatacenter",[u],Object.getOwnPropertyDescriptor(d.prototype,"findAllByDatacenter"),d.prototype),h(d.prototype,"findBySlug",[s],Object.getOwnPropertyDescriptor(d.prototype,"findBySlug"),d.prototype),h(d.prototype,"authorize",[c],Object.getOwnPropertyDescriptor(d.prototype,"authorize"),d.prototype),d) -e.default=y})),define("consul-ui/services/repository/partition",["exports","@ember/service","@ember/debug","consul-ui/services/repository","consul-ui/models/partition","consul-ui/decorators/data-source","consul-ui/utils/form/builder"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m,h -function b(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function y(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let g=(a=(0,t.inject)("settings"),u=(0,t.inject)("form"),s=(0,t.inject)("repository/permission"),c=(0,i.default)("/:partition/:ns/:dc/partitions"),d=(0,i.default)("/:partition/:ns/:dc/partition/:id"),p=class extends l.default{constructor(){super(...arguments),b(this,"settings",f,this),b(this,"form",m,this),b(this,"permissions",h,this)}getModelName(){return"partition"}getPrimaryKey(){return r.PRIMARY_KEY}getSlugKey(){return r.SLUG_KEY}async findAll(){return this.permissions.can("use partitions")?super.findAll(...arguments).catch((()=>[])):[]}async findBySlug(e){let t -return t=""===e.id?await this.create({Datacenter:e.dc,Partition:""}):await super.findBySlug(...arguments),(0,o.defaultChangeset)(t)}remove(e){return(0,l.softDelete)(this,e)}async getActive(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"" -const t=this.store.peekAll("partition").toArray() -if(0===e.length){e=(await this.settings.findBySlug("token")).Partition||"default"}return 1===t.length?t[0]:function(e,t){let l=e.find((function(e){return e.Name===t.Name})) -return void 0===l&&((0,n.runInDebug)((n=>console.info(`${t.Name} not found in [${e.map((e=>e.Name)).join(", ")}]`))),l=e.find((function(e){return"default"===e.Name})),void 0===l&&(l=e[0])),l}(t,{Name:e})}},f=y(p.prototype,"settings",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=y(p.prototype,"form",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=y(p.prototype,"permissions",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y(p.prototype,"findAll",[c],Object.getOwnPropertyDescriptor(p.prototype,"findAll"),p.prototype),y(p.prototype,"findBySlug",[d],Object.getOwnPropertyDescriptor(p.prototype,"findBySlug"),p.prototype),p) -e.default=g})),define("consul-ui/services/repository/peer",["exports","consul-ui/services/repository","consul-ui/decorators/data-source","@ember/service"],(function(e,t,n,l){var r,i,o,a,u,s,c,d -function p(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}function f(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function m(e){for(var t=1;t{const r=this.store.serializerFor("service") -return this.store.push(r.createJSONApiDocumentFromServicesPayload(e,t,l))}))}async fetchToken(e,t,n){let{dc:l,ns:r,partition:i,name:o,externalAddresses:a}=e -const u=(null==a?void 0:a.length)>0?a.split(","):[] -return(await(n` - POST /v1/peering/token - - ${{PeerName:o,Partition:i||void 0,ServerExternalAddresses:u}} - `))(((e,t,n)=>t))}async fetchAll(e,t,n){let{dc:l,ns:r,partition:i}=e,{uri:o}=t -return(await(n` - GET /v1/peerings - - ${{partition:i}} - `))(((e,t,n)=>({meta:{version:2,interval:1e4,uri:o},body:t.map((e=>n(b(e,l,i),(t=>t`peer:///${i}/${r}/${l}/peer/${e.Name}`))))})))}async fetchOne(e,t,n){let{partition:l,ns:r,dc:i,name:o}=e,{uri:a}=t -if(void 0===o||""===o){const e=this.create({Datacenter:i,Namespace:"",Partition:l}) -return e.meta={cacheControl:"no-store"},e}return(await(n` - GET /v1/peering/${o} - - ${{partition:l}} - `))(((e,t,n)=>{const{StreamStatus:o}=t -return o&&(o.LastHeartbeat&&(o.LastHeartbeat=new Date(o.LastHeartbeat)),o.LastReceive&&(o.LastReceive=new Date(o.LastReceive)),o.LastSend&&(o.LastSend=new Date(o.LastSend))),{meta:{version:2,interval:1e4,uri:a},body:n(b(t,i,l),(e=>e`peer:///${l}/${r}/${i}/peer/${t.Name}`))}}))}async persist(e,t){return(await(t` - POST /v1/peering/establish - - ${{PeerName:e.Name,PeeringToken:e.PeeringToken,Partition:e.Partition||void 0}} - `))(((t,n,l)=>{const r=e.Partition,i=e.Namespace,o=e.Datacenter -return{meta:{version:2},body:l(m(m({},e),{},{State:"ESTABLISHING"}),(t=>t`peer:///${r}/${i}/${o}/peer/${e.Name}`))}}))}async remove(e,t){return(await(t` - DELETE /v1/peering/${e.Name} - `))(((t,n,l)=>{const r=e.Partition,i=e.Namespace,o=e.Datacenter -return{meta:{version:2},body:l(m(m({},e),{},{State:"DELETING"}),(t=>t`peer:///${r}/${i}/${o}/peer/${e.Name}`))}}))}},d=p(c.prototype,"store",[l.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p(c.prototype,"fetchExportedServices",[r],Object.getOwnPropertyDescriptor(c.prototype,"fetchExportedServices"),c.prototype),p(c.prototype,"fetchToken",[i],Object.getOwnPropertyDescriptor(c.prototype,"fetchToken"),c.prototype),p(c.prototype,"fetchAll",[o],Object.getOwnPropertyDescriptor(c.prototype,"fetchAll"),c.prototype),p(c.prototype,"fetchOne",[a,u,s],Object.getOwnPropertyDescriptor(c.prototype,"fetchOne"),c.prototype),c) -e.default=y})),define("consul-ui/services/repository/permission",["exports","consul-ui/services/repository","@ember/service","@glimmer/tracking","@ember/debug","consul-ui/decorators/data-source"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p -function f(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function m(e){for(var t=1;tt.every((t=>n[t]===e[t]))&&!0===n.Allow))}can(e){return this._can.can(e)}abilityFor(e){return this._can.abilityFor(e)}generate(e,t,n){const l={Resource:e,Access:t} -return void 0!==n&&(l.Segment=n),l}async authorize(e){if(this.env.var("CONSUL_ACLS_ENABLED")){let n=[] -try{n=await this.store.authorize("permission",e)}catch(t){(0,r.runInDebug)((()=>console.error(t)))}return n}return e.resources.map((e=>m(m({},e),{},{Allow:!0})))}async findBySlug(e,t){let n -try{n=this._can.abilityFor(t)}catch(r){return[]}const l=n.generateForSegment(e.id.toString()) -return 0===l.length?[]:(e.resources=l,this.authorize(e))}async findByPermissions(e){return this.authorize(e)}async findAll(e){return e.resources=this.permissionsToRequest,this.permissions=await this.findByPermissions(e),this.permissions.forEach((e=>{["key","node","service","intention","session"].includes(e.Resource)&&(e.Allow=!0)})),this.permissions}get permissionsToRequest(){return this._can.can("use peers")?[...g,...v]:g}},c=y(s.prototype,"env",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=y(s.prototype,"_can",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=y(s.prototype,"permissions",[l.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return[]}}),y(s.prototype,"findAll",[u],Object.getOwnPropertyDescriptor(s.prototype,"findAll"),s.prototype),s) -e.default=O})),define("consul-ui/services/repository/policy",["exports","consul-ui/services/repository","@ember/object","@ember/service","consul-ui/models/policy","consul-ui/decorators/data-source"],(function(e,t,n,l,r,i){var o,a,u,s,c -function d(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let p=(o=(0,l.inject)("form"),a=(0,i.default)("/:partition/:ns/:dc/policies"),u=(0,i.default)("/:partition/:ns/:dc/policy/:id"),s=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="form",l=this,(n=c)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"policy"}getPrimaryKey(){return r.PRIMARY_KEY}getSlugKey(){return r.SLUG_KEY}async findAllByDatacenter(){return super.findAllByDatacenter(...arguments)}async findBySlug(e){let t -return t=""===e.id?await this.create({Datacenter:e.dc,Partition:e.partition,Namespace:e.ns}):await super.findBySlug(...arguments),this.form.form(this.getModelName()).setData(t).getData()}persist(e){return""===(0,n.get)(e,"template")?e.save():Promise.resolve(e)}translate(e){return this.store.translate("policy",(0,n.get)(e,"Rules"))}},c=d(s.prototype,"form",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d(s.prototype,"findAllByDatacenter",[a],Object.getOwnPropertyDescriptor(s.prototype,"findAllByDatacenter"),s.prototype),d(s.prototype,"findBySlug",[u],Object.getOwnPropertyDescriptor(s.prototype,"findBySlug"),s.prototype),s) -e.default=p})),define("consul-ui/services/repository/proxy",["exports","consul-ui/services/repository","consul-ui/models/proxy","@ember/object","consul-ui/decorators/data-source"],(function(e,t,n,l,r){var i,o,a -function u(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let s=(i=(0,r.default)("/:partition/:ns/:dc/proxies/for-service/:id"),o=(0,r.default)("/:partition/:ns/:dc/proxy-instance/:serviceId/:node/:id"),a=class extends t.default{getModelName(){return"proxy"}getPrimaryKey(){return n.PRIMARY_KEY}findAllBySlug(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.store.query(this.getModelName(),e).then((e=>(e.forEach((e=>{const t=JSON.parse(e.uid) -t.pop(),t.push(e.ServiceProxy.DestinationServiceID) -const n=this.store.peekRecord("service-instance",JSON.stringify(t)) -n&&(0,l.set)(n,"ProxyInstance",e)})),e)))}async findInstanceBySlug(e,t){const n=await this.findAllBySlug(e,t) -let r={} -if((0,l.get)(n,"length")>0){let t=n.filterBy("ServiceProxy.DestinationServiceID",e.serviceId).findBy("NodeName",e.node) -t?r=t:(t=n.findBy("ServiceProxy.DestinationServiceName",e.id),t&&(r=t))}return(0,l.set)(r,"meta",(0,l.get)(n,"meta")),r}},u(a.prototype,"findAllBySlug",[i],Object.getOwnPropertyDescriptor(a.prototype,"findAllBySlug"),a.prototype),u(a.prototype,"findInstanceBySlug",[o],Object.getOwnPropertyDescriptor(a.prototype,"findInstanceBySlug"),a.prototype),a) -e.default=s})),define("consul-ui/services/repository/role",["exports","consul-ui/services/repository","@ember/service","consul-ui/models/role","consul-ui/decorators/data-source"],(function(e,t,n,l,r){var i,o,a,u,s -function c(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let d=(i=(0,n.inject)("form"),o=(0,r.default)("/:partition/:ns/:dc/roles"),a=(0,r.default)("/:partition/:ns/:dc/role/:id"),u=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="form",l=this,(n=s)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"role"}getPrimaryKey(){return l.PRIMARY_KEY}getSlugKey(){return l.SLUG_KEY}async findAll(){return super.findAll(...arguments)}async findBySlug(e){let t -return t=""===e.id?await this.create({Datacenter:e.dc,Partition:e.partition,Namespace:e.ns}):await super.findBySlug(...arguments),this.form.form(this.getModelName()).setData(t).getData()}},s=c(u.prototype,"form",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c(u.prototype,"findAll",[o],Object.getOwnPropertyDescriptor(u.prototype,"findAll"),u.prototype),c(u.prototype,"findBySlug",[a],Object.getOwnPropertyDescriptor(u.prototype,"findBySlug"),u.prototype),u) -e.default=d})),define("consul-ui/services/repository/service-instance",["exports","consul-ui/services/repository","@ember/object","consul-ui/abilities/base","consul-ui/decorators/data-source"],(function(e,t,n,l,r){var i,o,a -function u(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let s=(i=(0,r.default)("/:partition/:ns/:dc/service-instances/for-service/:id/:peer"),o=(0,r.default)("/:partition/:ns/:dc/service-instance/:serviceId/:node/:id/:peer"),a=class extends t.default{getModelName(){return"service-instance"}shouldReconcile(e,t){return super.shouldReconcile(...arguments)&&e.Service.Service===t.id}async findByService(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.authorizeBySlug((async t=>{const l=await this.query(e) -return(0,n.set)(l,"firstObject.Service.Resources",t),l}),l.ACCESS_READ,e)}async findBySlug(e){return super.findBySlug(...arguments)}},u(a.prototype,"findByService",[i],Object.getOwnPropertyDescriptor(a.prototype,"findByService"),a.prototype),u(a.prototype,"findBySlug",[o],Object.getOwnPropertyDescriptor(a.prototype,"findBySlug"),a.prototype),a) -e.default=s})),define("consul-ui/services/repository/service",["exports","consul-ui/services/repository","consul-ui/decorators/data-source","@ember/service"],(function(e,t,n,l){var r,i,o,a,u -function s(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let c=(r=(0,n.default)("/:partition/:ns/:dc/services"),i=(0,n.default)("/:partition/:ns/:dc/services/:peer/:peerId"),o=(0,n.default)("/:partition/:ns/:dc/gateways/for-service/:gateway"),a=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="store",l=this,(n=u)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"service"}async findAllByDatacenter(){return super.findAll(...arguments)}async findAllImportedServices(e,t){const{peerId:n}=e -return delete e.peerId,super.findAll(e,t).then((e=>{const t=this.store.peekRecord("peer",n) -return e.forEach((e=>e.peer=t)),e}))}findGatewayBySlug(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.store.query(this.getModelName(),e)}},u=s(a.prototype,"store",[l.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s(a.prototype,"findAllByDatacenter",[r],Object.getOwnPropertyDescriptor(a.prototype,"findAllByDatacenter"),a.prototype),s(a.prototype,"findAllImportedServices",[i],Object.getOwnPropertyDescriptor(a.prototype,"findAllImportedServices"),a.prototype),s(a.prototype,"findGatewayBySlug",[o],Object.getOwnPropertyDescriptor(a.prototype,"findGatewayBySlug"),a.prototype),a) -e.default=c})),define("consul-ui/services/repository/session",["exports","@ember/service","consul-ui/services/repository","consul-ui/decorators/data-source"],(function(e,t,n,l){var r,i,o,a,u -function s(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let c=(r=(0,t.inject)("store"),i=(0,l.default)("/:partition/:ns/:dc/sessions/for-node/:id"),o=(0,l.default)("/:partition/:ns/:dc/sessions/for-key/:id"),a=class extends n.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="store",l=this,(n=u)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"session"}findByNode(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.store.query(this.getModelName(),e)}findByKey(e){return this.findBySlug(...arguments)}},u=s(a.prototype,"store",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s(a.prototype,"findByNode",[i],Object.getOwnPropertyDescriptor(a.prototype,"findByNode"),a.prototype),s(a.prototype,"findByKey",[o],Object.getOwnPropertyDescriptor(a.prototype,"findByKey"),a.prototype),a) -e.default=c})),define("consul-ui/services/repository/token",["exports","consul-ui/services/repository","@ember/object","@ember/service","consul-ui/models/token","consul-ui/decorators/data-source"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f -function m(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let h=(o=(0,l.inject)("form"),a=(0,i.default)("/:partition/:ns/:dc/tokens"),u=(0,i.default)("/:partition/:ns/:dc/token/:id"),s=(0,i.default)("/:partition/:ns/:dc/token/self/:secret"),c=(0,i.default)("/:partition/:ns/:dc/tokens/for-policy/:policy"),d=(0,i.default)("/:partition/:ns/:dc/tokens/for-role/:role"),p=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="form",l=this,(n=f)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"token"}getPrimaryKey(){return r.PRIMARY_KEY}getSlugKey(){return r.SLUG_KEY}async findAll(){return super.findAll(...arguments)}async findBySlug(e){let t -return t=""===e.id?await this.create({Datacenter:e.dc,Partition:e.partition,Namespace:e.ns}):await super.findBySlug(...arguments),this.form.form(this.getModelName()).setData(t).getData()}self(e){return this.store.self(this.getModelName(),{secret:e.secret,dc:e.dc}).catch((e=>Promise.reject(e)))}clone(e){return this.store.clone(this.getModelName(),(0,n.get)(e,r.PRIMARY_KEY))}findByPolicy(e){return this.findAll(...arguments)}findByRole(){return this.findAll(...arguments)}},f=m(p.prototype,"form",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m(p.prototype,"findAll",[a],Object.getOwnPropertyDescriptor(p.prototype,"findAll"),p.prototype),m(p.prototype,"findBySlug",[u],Object.getOwnPropertyDescriptor(p.prototype,"findBySlug"),p.prototype),m(p.prototype,"self",[s],Object.getOwnPropertyDescriptor(p.prototype,"self"),p.prototype),m(p.prototype,"findByPolicy",[c],Object.getOwnPropertyDescriptor(p.prototype,"findByPolicy"),p.prototype),m(p.prototype,"findByRole",[d],Object.getOwnPropertyDescriptor(p.prototype,"findByRole"),p.prototype),p) -e.default=h})),define("consul-ui/services/repository/topology",["exports","@ember/service","consul-ui/services/repository","@ember/object","consul-ui/decorators/data-source"],(function(e,t,n,l,r){var i,o,a,u -function s(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let c=(i=(0,t.inject)("repository/dc"),o=(0,r.default)("/:partition/:ns/:dc/topology/:id/:kind"),a=class extends n.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="dcs",l=this,(n=u)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"topology"}findBySlug(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -const n=this.dcs.peekOne(e.dc) -return null===n||(0,l.get)(n,"MeshEnabled")?(void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.store.queryRecord(this.getModelName(),e).catch((e=>{const t=(0,l.get)(e,"errors.firstObject.status"),r=((0,l.get)(e,"errors.firstObject.detail")||"").trim() -if("500"!==t)throw e -null!==n&&r.endsWith("Connect must be enabled in order to use this endpoint")&&(0,l.set)(n,"MeshEnabled",!1)}))):Promise.resolve()}},u=s(a.prototype,"dcs",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s(a.prototype,"findBySlug",[o],Object.getOwnPropertyDescriptor(a.prototype,"findBySlug"),a.prototype),a) -e.default=c})),define("consul-ui/services/resize-observer",["exports","ember-resize-observer-service/services/resize-observer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/routlet",["exports","@ember/service","@ember/runloop","@ember/object","consul-ui/utils/routing/wildcard","consul-ui/router"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m -function h(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function b(e){for(var t=1;t{if("application"===e)return 1 -if("application"===t)return-1 -const n=e.split(".").length,l=t.split(".").length -switch(!0){case n>l:return-1 -case n0&&!t.every((e=>this.permissions.can(e))))}transition(){let e -return this._transition=new Promise((t=>{e=t})),e}findOutlet(e){return[...P.keys()].find((t=>-1!==e.indexOf(t)))}outletFor(e){const t=[...P.keys()],n=t.indexOf(e)+1 -return P.get(t[n])}normalizeParamsFor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return O(e)?Object.keys(t).reduce((function(e,n){return void 0!==t[n]?e[n]=decodeURIComponent(t[n]):e[n]=t[n],e}),{}):t}paramsFor(e){let t={} -const n=P.get(e) -void 0!==n&&void 0!==n.args.params&&(t=n.args.params) -let l=this.router.currentRoute -null===l&&(l=this.container.lookup("route:application")) -let r,i=l,o=this.normalizeParamsFor(e,i.params) -for(;r=i.parent;)o=b(b({},this.normalizeParamsFor(r.name,r.params)),o),i=r -return b(b(b({},this.container.get(`location:${this.env.var("locationType")}`).optionalParams()),o),t)}modelFor(e){const t=P.get(e) -if(void 0!==t)return t.model}addRoute(e,t){const l=this.outletFor(e) -void 0!==l&&(l.route=t,(0,n.schedule)("afterRender",(()=>{l.routeName=e})))}removeRoute(e,t){const l=this.outletFor(e) -t._model=void 0,void 0!==l&&(0,n.schedule)("afterRender",(()=>{l.route=void 0}))}addOutlet(e,t){P.set(e,t)}removeOutlet(e){(0,n.schedule)("afterRender",(()=>{P.delete(e)}))}},d=v(c.prototype,"container",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=v(c.prototype,"env",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=v(c.prototype,"router",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=v(c.prototype,"permissions",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c) -e.default=x})),define("consul-ui/services/schema",["exports","@ember/service","consul-ui/models/intention-permission","consul-ui/models/intention-permission-http","consul-ui/models/intention-permission-http-header"],(function(e,t,n,l,r){function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class o extends t.default{constructor(){super(...arguments),i(this,"intention-permission",n.schema),i(this,"intention-permission-http",l.schema),i(this,"intention-permission-http-header",r.schema)}}e.default=o})),define("consul-ui/services/search",["exports","@ember/service","consul-ui/utils/search/exact","consul-ui/search/predicates/intention","consul-ui/search/predicates/upstream-instance","consul-ui/search/predicates/service-instance","consul-ui/search/predicates/health-check","consul-ui/search/predicates/acl","consul-ui/search/predicates/service","consul-ui/search/predicates/node","consul-ui/search/predicates/kv","consul-ui/search/predicates/token","consul-ui/search/predicates/role","consul-ui/search/predicates/policy","consul-ui/search/predicates/auth-method","consul-ui/search/predicates/nspace","consul-ui/search/predicates/peer"],(function(e,t,n,l,r,i,o,a,u,s,c,d,p,f,m,h,b){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const y={intention:l.default,service:u.default,"service-instance":i.default,"upstream-instance":r.default,"health-check":o.default,"auth-method":m.default,node:s.default,kv:c.default,acl:a.default,token:d.default,role:p.default,policy:f.default,nspace:h.default,peer:b.default} -class g extends t.default{constructor(){var e,t,l -super(...arguments),e=this,t="searchables",l={exact:n.default},t in e?Object.defineProperty(e,t,{value:l,enumerable:!0,configurable:!0,writable:!0}):e[t]=l}predicate(e){return y[e]}}e.default=g})),define("consul-ui/services/settings",["exports","@ember/service","consul-ui/utils/storage/local-storage"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.ifNotBlocking=void 0 -const l=(0,n.default)("consul") -e.ifNotBlocking=function(e){return e.findBySlug("client").then((function(e){return void 0!==e.blocking&&!e.blocking}))} -class r extends t.default{constructor(){var e,t,n -super(...arguments),n=l,(t="storage")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}findAll(e){return Promise.resolve(this.storage.all())}findBySlug(e){return Promise.resolve(this.storage.getValue(e))}persist(e){const t=this.storage -return Object.keys(e).forEach(((n,l)=>{t.setValue(n,e[n])})),Promise.resolve(e)}delete(e){Array.isArray(e)||(e=[e]) -const t=this.storage,n=e.reduce((function(e,n,l,r){return t.removeValue(n),e}),{}) -return Promise.resolve(n)}}e.default=r})),define("consul-ui/services/sort",["exports","@ember/service","consul-ui/sort/comparators/service","consul-ui/sort/comparators/service-instance","consul-ui/sort/comparators/upstream-instance","consul-ui/sort/comparators/kv","consul-ui/sort/comparators/health-check","consul-ui/sort/comparators/intention","consul-ui/sort/comparators/token","consul-ui/sort/comparators/role","consul-ui/sort/comparators/policy","consul-ui/sort/comparators/auth-method","consul-ui/sort/comparators/nspace","consul-ui/sort/comparators/peer","consul-ui/sort/comparators/node"],(function(e,t,n,l,r,i,o,a,u,s,c,d,p,f,m){Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.properties=void 0 -const h=e=>e.reduce(((e,t)=>e.concat([`${t}:asc`,`${t}:desc`])),[]),b=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[] -return t=>{const n=h(e) -return[n.find((e=>e===t))||n[0]]}} -e.properties=b -const y={properties:b,directionify:h},g={service:(0,n.default)(y),"service-instance":(0,l.default)(y),"upstream-instance":(0,r.default)(y),"health-check":(0,o.default)(y),"auth-method":(0,d.default)(y),kv:(0,i.default)(y),intention:(0,a.default)(y),token:(0,u.default)(y),role:(0,s.default)(y),policy:(0,c.default)(y),nspace:(0,p.default)(y),peer:(0,f.default)(y),node:(0,m.default)(y)} -class v extends t.default{comparator(e){return g[e]}}e.default=v})),define("consul-ui/services/state-with-charts",["exports","consul-ui/services/state","consul-ui/machines/validate.xstate","consul-ui/machines/boolean.xstate"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class r extends t.default{constructor(){var e,t,r -super(...arguments),e=this,t="stateCharts",r={validate:n.default,boolean:l.default},t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r}}e.default=r})),define("consul-ui/services/state",["exports","@ember/service","@ember/object","flat","@xstate/fsm"],(function(e,t,n,l,r){var i,o,a -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let u=(i=(0,t.inject)("logger"),o=class extends t.default{constructor(){var e,t,n,l,r,i,o -super(...arguments),n={},(t="stateCharts")in(e=this)?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,l=this,r="logger",o=this,(i=a)&&Object.defineProperty(l,r,{enumerable:i.enumerable,configurable:i.configurable,writable:i.writable,value:i.initializer?i.initializer.call(o):void 0})}log(e,t){}stateChart(e){return this.stateCharts[e]}addGuards(e,t){return this.guards(e).forEach((function(l){let[r,i]=l;(0,n.set)(e,r,(function(){return!!t.onGuard(i,...arguments)}))})),[e,t]}machine(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return(0,r.createMachine)(...this.addGuards(e,t))}prepareChart(e){return void 0!==(e=JSON.parse(JSON.stringify(e))).on&&Object.values(e.states).forEach((function(t){void 0===t.on?t.on=e.on:Object.keys(e.on).forEach((function(n){void 0===t.on[n]&&(t.on[n]=e.on[n])}))})),e}matches(e,t){if(void 0===e)return!1 -return(Array.isArray(t)?t:[t]).some((t=>e.matches(t)))}state(e){return{matches:e}}interpret(e,t){e=this.prepareChart(e) -const n=(0,r.interpret)(this.machine(e,t)) -return n.subscribe((n=>{n.changed&&(this.log(e,n),t.onTransition(n))})),n}guards(e){return Object.entries((0,l.default)(e)).filter((e=>{let[t]=e -return t.endsWith(".cond")}))}},s=o.prototype,c="logger",d=[i],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),a=m,o) -var s,c,d,p,f,m -e.default=u})),define("consul-ui/services/store",["exports","@ember/service","@ember-data/store"],(function(e,t,n){var l,r,i,o,a -function u(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function s(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let c=(l=(0,t.inject)("data-source/service"),r=(0,t.inject)("client/http"),i=class extends n.default{constructor(){super(...arguments),u(this,"dataSource",o,this),u(this,"client",a,this)}invalidate(){this.client.abort(401),this.dataSource.resetCache(),this.init()}clear(){this.invalidate(0)}clone(e,t){return this.adapterFor(e).clone(this,{modelName:e},t,this._internalModelForId(e,t).createSnapshot({}))}self(e,t){const n=this.adapterFor(e),l=this.serializerFor(e),r={modelName:e} -return n.self(this,r,t.secret,t).then((e=>l.normalizeResponse(this,r,e,t,"self")))}queryLeader(e,t){const n=this.adapterFor(e),l=this.serializerFor(e),r={modelName:e} -return n.queryLeader(this,r,null,t).then((e=>(e.meta=l.normalizeMeta(this,r,e,null,"leader"),e)))}authorize(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -const n=this.adapterFor(e),l=this.serializerFor(e),r={modelName:e} -return n.authorize(this,r,null,t).then((e=>l.normalizeResponse(this,r,e,void 0,"authorize")))}logout(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -const n={modelName:e} -return this.adapterFor(e).logout(this,n,t.id,t)}},o=s(i.prototype,"dataSource",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=s(i.prototype,"client",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) -e.default=c})),define("consul-ui/services/temporal",["exports","pretty-ms","parse-duration","@ember/debug","dayjs","dayjs/plugin/relativeTime","@ember/service"],(function(e,t,n,l,r,i,o){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,r.default.extend(i.default) -class a extends o.default{format(e,t){const n=(0,r.default)(e) -return(0,r.default)().isBefore(n)?(0,r.default)().to(n,!0):(0,r.default)().from(n,!0)}within(e,t){let[n,l]=e -return(0,r.default)(n).isBefore((0,r.default)().add(l,"ms"))}parse(e,t){return(0,n.default)(e)}durationFrom(e){return!0==("number"==typeof e)?0===e?"0":(0,t.default)(e/1e6,{formatSubMilliseconds:!0}).split(" ").join(""):e}}e.default=a})),define("consul-ui/services/text-measurer",["exports","ember-text-measurer/services/text-measurer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/ticker",["exports","@ember/service","consul-ui/utils/ticker"],(function(e,t,n){let l -Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class r extends t.default{init(){super.init(...arguments),this.reset()}tweenTo(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",r=arguments.length>2?arguments[2]:void 0,i=arguments.length>3?arguments[3]:void 0 -const o=t -return l.has(o)?(t=l.get(o),t instanceof n.Tween&&(t=t.stop().getTarget()),l.set(o,n.Tween.to(t,e,r,i)),t):(l.set(o,e),e)}destroy(e){return this.reset(),n.Tween.destroy()}reset(){l=new Map}}e.default=r})),define("consul-ui/services/timeout",["exports","@ember/service","consul-ui/utils/promisedTimeout","@ember/runloop"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -const r=(0,n.default)(Promise) -class i extends t.default{execute(e,t){return r(e,t)}tick(){return new Promise((function(e,t){(0,l.next)(e)}))}}e.default=i})),define("consul-ui/services/torii-session",["exports","torii/services/torii-session"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/torii",["exports","torii/services/torii"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/ui-config",["exports","@ember/service","@ember/object","consul-ui/decorators/data-source"],(function(e,t,n,l){var r,i,o,a,u,s -function c(e,t,n,l,r){var i={} -return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -let d=(r=(0,t.inject)("env"),i=(0,l.default)("/:partition/:nspace/:dc/ui-config/:path"),o=(0,l.default)("/:partition/:nspace/:dc/notfound/:path"),a=(0,l.default)("/:partition/:nspace/:dc/ui-config"),u=class extends t.default{constructor(){var e,t,n,l -super(...arguments),e=this,t="env",l=this,(n=s)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}async findByPath(e){return(0,n.get)(this.get(),e.path)}async parsePath(e){return e.path.split("/").reduce(((e,t,n)=>{switch(!0){case t.startsWith("~"):e.nspace=t.substr(1) -break -case t.startsWith("_"):e.partition=t.substr(1) -break -case void 0===e.dc:e.dc=t}return e}),{})}async get(){return this.env.var("CONSUL_UI_CONFIG")}getSync(){return this.env.var("CONSUL_UI_CONFIG")}},s=c(u.prototype,"env",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c(u.prototype,"findByPath",[i],Object.getOwnPropertyDescriptor(u.prototype,"findByPath"),u.prototype),c(u.prototype,"parsePath",[o],Object.getOwnPropertyDescriptor(u.prototype,"parsePath"),u.prototype),c(u.prototype,"get",[a],Object.getOwnPropertyDescriptor(u.prototype,"get"),u.prototype),u) -e.default=d})),define("consul-ui/sort/comparators/auth-method",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:t}=e -return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"MethodName:asc" -return t(["MethodName","TokenTTL"])(e)}}})),define("consul-ui/sort/comparators/health-check",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:t}=e -return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"Status:asc" -return e.startsWith("Status:")?function(t,n){const[,l]=e.split(":") -let r,i -"asc"===l?(r=t,i=n):(i=t,r=n) -const o=r.Status,a=i.Status -switch(o){case"passing":return"passing"===a?0:1 -case"critical":return"critical"===a?0:-1 -case"warning":switch(a){case"passing":return-1 -case"critical":return 1 -default:return 0}}return 0}:t(["Name","Kind"])(e)}}})) -define("consul-ui/sort/comparators/intention",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=()=>e=>[e]})),define("consul-ui/sort/comparators/kv",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:t}=e -return e=>t(["Key","Kind"])(e)}})),define("consul-ui/sort/comparators/node",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:t}=e -return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"Name:asc" -return e.startsWith("Status:")?function(t,n){const[,l]=e.split(":") -let r,i -switch("asc"===l?(i=t,r=n):(r=t,i=n),!0){case r.ChecksCritical>i.ChecksCritical:return 1 -case r.ChecksCriticali.ChecksWarning:return 1 -case r.ChecksWarningi.ChecksPassing:return-1}}return 0}}:t(["Node"])(e)}}})),define("consul-ui/sort/comparators/nspace",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:t}=e -return e=>t(["Name"])(e)}})),define("consul-ui/sort/comparators/partition",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:t}=e -return e=>t(["Name"])(e)}})),define("consul-ui/sort/comparators/peer",["exports","consul-ui/models/peer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:n}=e -return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"State:asc" -return e.startsWith("State:")?function(n,l){const[,r]=e.split(":") -let i,o -switch("asc"===r?(o=n,i=l):(i=n,o=l),!0){case t.schema.State.allowedValues.indexOf(i.State)t.schema.State.allowedValues.indexOf(o.State):return-1 -case t.schema.State.allowedValues.indexOf(i.State)===t.schema.State.allowedValues.indexOf(o.State):return 0}}:n(["Name"])(e)}}})),define("consul-ui/sort/comparators/policy",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:t}=e -return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"Name:asc" -return t(["Name"])(e)}}})),define("consul-ui/sort/comparators/role",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:t}=e -return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"Name:asc" -return t(["Name","CreateIndex"])(e)}}})),define("consul-ui/sort/comparators/service-instance",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:t}=e -return e=>{if(e.startsWith("Status:")){const[,t]=e.split(":"),n=["PercentageChecksPassing","PercentageChecksWarning","PercentageChecksCritical"] -return"asc"===t&&n.reverse(),function(e,t){for(let l in n){let r=n[l] -if(e[r]!==t[r])return e[r]>t[r]?-1:1}}}return t(["Name"])(e)}}})),define("consul-ui/sort/comparators/service",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:t}=e -return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"Status:asc" -return e.startsWith("Status:")?function(t,n){const[,l]=e.split(":") -let r,i -switch("asc"===l?(i=t,r=n):(r=t,i=n),!0){case r.MeshChecksCritical>i.MeshChecksCritical:return 1 -case r.MeshChecksCriticali.MeshChecksWarning:return 1 -case r.MeshChecksWarningi.MeshChecksPassing:return-1}}return 0}}:t(["Name"])(e)}}})),define("consul-ui/sort/comparators/token",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:t}=e -return e=>t(["CreateTime"])(e)}})),define("consul-ui/sort/comparators/upstream-instance",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>{let{properties:t}=e -return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"DestinationName:asc" -return t(["DestinationName"])(e)}}})),define("consul-ui/storages/base",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=class{constructor(e,t){this.key=e,this.storage=t,this.state=this.initState(this.key,this.storage)}initState(){const{key:e,storage:t}=this -return t.getItem(e)}}})),define("consul-ui/storages/notices",["exports","tracked-built-ins","consul-ui/storages/base"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends n.default{initState(){const{key:e,storage:n}=this,l=n.getItem(e) -return l?new t.TrackedArray(l.split(",")):new t.TrackedArray}add(e){const{key:t,storage:n,state:l}=this -l.push(e),n.setItem(t,[...l])}}e.default=l})),define("consul-ui/styles/base/decoration/visually-hidden.css",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>e` - @keyframes visually-hidden { - 100% { - position: absolute; - overflow: hidden; - clip: rect(0 0 0 0); - width: 1px; - height: 1px; - margin: -1px; - padding: 0; - border: 0; - } - } - `})),define("consul-ui/styles/base/icons/base-keyframes.css",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>e` - *::before, - *::after { - display: inline-block; - animation-play-state: paused; - animation-fill-mode: forwards; - animation-iteration-count: var(--icon-resolution, 1); - vertical-align: text-top; - } - *::before { - animation-name: var(--icon-name-start, var(--icon-name)), - var(--icon-size-start, var(--icon-size, icon-000)); - background-color: var(--icon-color-start, var(--icon-color)); - } - *::after { - animation-name: var(--icon-name-end, var(--icon-name)), - var(--icon-size-end, var(--icon-size, icon-000)); - background-color: var(--icon-color-end, var(--icon-color)); - } - - [style*='--icon-color-start']::before { - color: var(--icon-color-start); - } - [style*='--icon-color-end']::after { - color: var(--icon-color-end); - } - [style*='--icon-name-start']::before, - [style*='--icon-name-end']::after { - content: ''; - } - - @keyframes icon-000 { - 100% { - width: 1.2em; - height: 1.2em; - } - } - @keyframes icon-100 { - 100% { - width: 0.625rem; /* 10px */ - height: 0.625rem; /* 10px */ - } - } - @keyframes icon-200 { - 100% { - width: 0.75rem; /* 12px */ - height: 0.75rem; /* 12px */ - } - } - @keyframes icon-300 { - 100% { - width: 1rem; /* 16px */ - height: 1rem; /* 16px */ - } - } - @keyframes icon-400 { - 100% { - width: 1.125rem; /* 18px */ - height: 1.125rem; /* 18px */ - } - } - @keyframes icon-500 { - 100% { - width: 1.25rem; /* 20px */ - height: 1.25rem; /* 20px */ - } - } - @keyframes icon-600 { - 100% { - width: 1.375rem; /* 22px */ - height: 1.375rem; /* 22px */ - } - } - @keyframes icon-700 { - 100% { - width: 1.5rem; /* 24px */ - height: 1.5rem; /* 24px */ - } - } - @keyframes icon-800 { - 100% { - width: 1.625rem; /* 26px */ - height: 1.625rem; /* 26px */ - } - } - @keyframes icon-900 { - 100% { - width: 1.75rem; /* 28px */ - height: 1.75rem; /* 28px */ - } - } -`})),define("consul-ui/templates/application",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"JXqlDmpZ",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n"],[1," "],[8,[30,1,["Announcer"]],null,[["@title"],["Consul"]],null],[1,"\\n"],[41,[28,[37,3],["use acls"],null],[[[1," "],[1,[28,[35,4],null,[["class"],["has-acls"]]]],[1,"\\n"]],[]],null],[41,[28,[37,3],["use nspaces"],null],[[[1," "],[1,[28,[35,4],null,[["class"],["has-nspaces"]]]],[1,"\\n"]],[]],null],[41,[28,[37,3],["use partitions"],null],[[[1," "],[1,[28,[35,4],null,[["class"],["has-partitions"]]]],[1,"\\n"]],[]],null],[1,"\\n"],[1," "],[8,[39,5],null,[["@src","@onchange"],[[28,[37,6],["settings://consul:client"],null],[28,[37,7],["onClientChanged"],null]]],null],[1,"\\n\\n"],[1," "],[8,[39,5],null,[["@src"],[[28,[37,6],["settings://consul:theme"],null]]],[["default"],[[[[1,"\\n"],[42,[28,[37,9],[[30,2,["data"]]],null],null,[[[41,[28,[37,10],[[30,3],[28,[37,11],[[30,4],[28,[37,12],["color-scheme","contrast"],null]],null]],null],[[[1," "],[1,[28,[35,4],null,[["class"],[[28,[37,13],["prefers-",[30,4],"-",[30,3]],null]]]]],[1,"\\n"]],[]],null]],[3,4]],null],[1," "]],[2]]]]],[1,"\\n\\n"],[41,[28,[37,3],["use acls"],null],[[[1," "],[8,[39,5],null,[["@src","@onchange"],[[28,[37,6],["settings://consul:token"],null],[28,[37,14],[[30,0],[28,[37,15],[[33,16]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[41,[28,[37,17],[[30,1,["currentName"]],"oauth-provider-debug"],null],[[[1,"\\n"],[41,[28,[37,18],[[30,1,["currentName"]],"index"],null],[[[1,"\\n"],[1," "],[1,[28,[35,19],[[28,[37,7],["replaceWith","dc.services.index",[28,[37,20],null,[["dc"],[[28,[37,21],["CONSUL_DATACENTER_LOCAL"],null]]]]],null]],null]],[1,"\\n"]],[]],[[[41,[28,[37,18],[[30,1,["currentName"]],"notfound"],null],[[[1," "],[8,[39,5],null,[["@src","@onchange"],[[28,[37,6],["/*/*/*/notfound/${path}",[28,[37,20],null,[["path"],[[30,1,["params","notfound"]]]]]],null],[28,[37,14],[[30,0],[28,[37,15],[[33,22]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[44,[[52,[28,[37,3],["use partitions"],null],[28,[37,24],[[30,1,["params","partition"]],[33,22,["partition"]],[33,16,["Partition"]],""],null],""],[52,[28,[37,3],["use nspaces"],null],[28,[37,24],[[30,1,["params","nspace"]],[33,22,["nspace"]],[33,16,["Namespace"]],""],null],""]],[[[1,"\\n"],[1," "],[8,[39,5],null,[["@src"],[[28,[37,6],["/*/*/*/datacenters"],null]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,24],[[52,[33,25,["dc"]],[28,[37,26],[0,[28,[37,27],["dc",[28,[37,20],null,[["Name"],[[33,22,["dc"]]]]]],null]],null]],[28,[37,26],[0,[28,[37,27],["dc",[28,[37,20],null,[["Name"],[[30,1,["params","dc"]]]]]],null]],null],[28,[37,20],null,[["Name"],[[28,[37,21],["CONSUL_DATACENTER_LOCAL"],null]]]]],null],[30,7,["data"]]],[[[41,[28,[37,10],[[28,[37,28],[[30,8,["Name","length"]],0],null],[30,9]],null],[[[1,"\\n"],[1," "],[8,[39,5],null,[["@src"],[[28,[37,6],["/${partition}/*/${dc}/datacenter-cache/${name}",[28,[37,20],null,[["dc","partition","name"],[[30,8,["Name"]],[30,5],[30,8,["Name"]]]]]],null]]],[["default"],[[[[1,"\\n"],[41,[30,10,["data"]],[[[1," "],[8,[39,29],[[24,1,"wrapper"]],[["@dcs","@dc","@partition","@nspace","@user","@onchange"],[[30,9],[30,10,["data"]],[30,5],[30,6],[28,[37,20],null,[["token"],[[33,16]]]],[28,[37,14],[[30,0],"reauthorize"],null]]],[["default"],[[[[1,"\\n\\n"],[41,[33,30],[[[1," "],[8,[39,31],null,[["@error","@login"],[[99,30,["@error"]],[30,11,["login","open"]]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,32],null,[["@name","@model"],["application",[28,[37,20],null,[["app","user","dc","dcs"],[[30,11],[28,[37,20],null,[["token"],[[33,16]]]],[30,10,["data"]],[30,9]]]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,34],null,null],null,null,null],[1,"\\n "]],[12]]]]],[1,"\\n\\n"],[1," "],[8,[39,35],[[24,0,"view-loader"]],null,null],[1,"\\n"]],[]]],[1,"\\n "]],[11]]]]],[1,"\\n"]],[]],null],[1," "]],[10]]]]],[1,"\\n"]],[]],null]],[8,9]]],[1," "]],[7]]]]],[1,"\\n"]],[5,6]]]],[]]]],[]],[[[1," "],[8,[39,32],null,[["@name","@model"],["application",[28,[37,20],null,[["user"],[[28,[37,20],null,[["token"],[[33,16]]]]]]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,34],null,null],null,null,null],[1,"\\n "]],[13]]]]],[1,"\\n"]],[]]]],[1]]]]],[1,"\\n"]],["route","source","value","key","partition","nspace","dcs","dc","dcs","dc","consul","o","o"],false,["route","routeName","if","can","document-attrs","data-source","uri","route-action","each","-each-in","and","includes","array","concat","action","mut","token","not-eq","eq","did-insert","hash","env","notfound","let","or","nofound","object-at","cached-model","gt","hashicorp-consul","error","app-error","outlet","component","-outlet","consul/loader"]]',moduleName:"consul-ui/templates/application.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/components/basic-dropdown-content",["exports","ember-basic-dropdown/templates/components/basic-dropdown-content"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/templates/components/basic-dropdown-optional-tag",["exports","ember-basic-dropdown/templates/components/basic-dropdown-optional-tag"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/templates/components/basic-dropdown-trigger",["exports","ember-basic-dropdown/templates/components/basic-dropdown-trigger"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/templates/components/basic-dropdown",["exports","ember-basic-dropdown/templates/components/basic-dropdown"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/templates/dc",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"zSQnZ2jK",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name","@model"],[[99,1,["@name"]],[30,1,["model"]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,4],null,null],null,null,null],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","o"],false,["route","routeName","outlet","component","-outlet"]]',moduleName:"consul-ui/templates/dc.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"U8Va7GUq",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name","@model"],[[99,1,["@name"]],[30,1,["model"]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,4],null,null],null,null,null],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","o"],false,["route","routeName","outlet","component","-outlet"]]',moduleName:"consul-ui/templates/dc/acls.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/auth-methods/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"RVzHvzAb",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/auth-methods",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,8],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,9],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,11],[[33,12],"MethodName:asc"],null],[28,[37,13],[[30,0],[28,[37,14],[[33,12]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["kind","source","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,15],[28,[37,16],[[33,15],","],null],[27]],[28,[37,13],[[30,0],[28,[37,14],[[33,15]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change"],[[52,[33,17],[28,[37,16],[[33,17],","],null],[27]],[28,[37,13],[[30,0],[28,[37,14],[[33,17]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,18],[[33,19],[27]],null],[28,[37,16],[[33,19],","],null],[33,20]],[28,[37,13],[[30,0],[28,[37,14],[[33,19]],null]],[["value"],["target.selectedItems"]]],[33,20]]]]]]],[30,2,["data"]]],[[[1,"\\n\\n "],[8,[39,21],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Auth Methods"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,22],[[30,5,["length"]],0],null],[[[1," "],[8,[39,23],null,[["@search","@onsearch","@sort","@filter"],[[99,24,["@search"]],[28,[37,13],[[30,0],[28,[37,14],[[33,24]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@type","@sort","@filters","@search","@items"],["auth-method",[30,3,["value"]],[30,4],[99,24,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@items"],[[30,6,["items"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,28],["routes.dc.acls.auth-methods.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,28],["routes.dc.acls.auth-methods.index.empty.body"],[["items","htmlSafe"],[[30,5,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,29],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on auth methods",[29,[[28,[37,30],["CONSUL_DOCS_URL"],null],"/security/acl/auth-methods"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,29],null,[["@text","@href","@icon","@iconPosition","@size"],["Read the API Docs",[29,[[28,[37,30],["CONSUL_DOCS_API_URL"],null],"/acl/auth-methods.html"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","sort","filters","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","if","eq","consul/acl/disabled","app-error","let","or","sortBy","action","mut","kind","split","source","not-eq","searchproperty","searchProperties","app-view","gt","consul/auth-method/search-bar","search","data-collection","consul/auth-method/list","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/acls/auth-methods/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/auth-methods/show",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"HUExCiVZ",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/auth-method/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","id"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,8],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,9],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]]],[[[1," "],[8,[39,11],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,12],["dc.acls.auth-methods"],null]],[12],[1,"All Auth Methods"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[30,3,["Name"]]]],null],[1,"\\n "],[13],[1,"\\n "],[8,[39,13],null,[["@item"],[[30,3]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["nav"]],[["default"],[[[[1,"\\n "],[8,[39,14],null,[["@items"],[[28,[37,15],[[28,[37,16],[[28,[37,4],null,[["label","href","selected"],["General info",[28,[37,12],["dc.acls.auth-methods.show.auth-method"],null],[28,[37,17],["dc.acls.auth-methods.show.auth-method"],null]]]],[52,[28,[37,18],["use nspaces"],null],[28,[37,4],null,[["label","href","selected"],["Namespace rules",[28,[37,12],["dc.acls.auth-methods.show.nspace-rules"],null],[28,[37,17],["dc.acls.auth-methods.show.nspace-rules"],null]]]],""],[28,[37,4],null,[["label","href","selected"],["Binding rules",[28,[37,12],["dc.acls.auth-methods.show.binding-rules"],null],[28,[37,17],["dc.acls.auth-methods.show.binding-rules"],null]]]]],null]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,19],null,[["@name","@model"],[[99,1,["@name"]],[28,[37,4],null,[["item"],[[30,3]]]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,21],null,null],null,null,null],[1,"\\n "]],[4]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","item","o"],false,["route","routeName","data-loader","uri","hash","block-slot","if","eq","consul/acl/disabled","app-error","let","app-view","href-to","consul/auth-method/type","tab-nav","compact","array","is-href","can","outlet","component","-outlet"]]',moduleName:"consul-ui/templates/dc/acls/auth-methods/show.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/auth-methods/show/auth-method",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"eqP++7Wz",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n "],[8,[39,2],null,[["@item"],[[30,1,["model","item"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route"],false,["route","routeName","consul/auth-method/view"]]',moduleName:"consul-ui/templates/dc/acls/auth-methods/show/auth-method.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/auth-methods/show/binding-rules",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"P/K1HFfv",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/binding-rules/for-auth-method/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","id"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]]],[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,9],[[30,3,["length"]],0],null],[[[1," "],[10,2],[12],[1,"\\n Binding rules allow an operator to express a systematic way of automatically linking roles and service identities to newly created tokens without operator intervention.\\n "],[13],[1,"\\n "],[10,2],[12],[1,"\\n Successful authentication with an auth method returns a set of trusted identity attributes corresponding to the authenticated identity. Those attributes are matched against all configured binding rules for that auth method to determine what privileges to grant the Consul ACL token it will ultimately create.\\n "],[13],[1,"\\n "],[10,"hr"],[12],[13],[1,"\\n"],[42,[28,[37,11],[[28,[37,11],[[30,3]],null]],null],null,[[[1," "],[8,[39,12],null,[["@item"],[[30,4]]],null],[1,"\\n "],[10,"hr"],[12],[13],[1,"\\n"]],[4]],null]],[]],[[[1," "],[8,[39,13],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,14],["routes.dc.acls.auth-methods.show.binding-rules.index.empty.header"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,14],["routes.dc.acls.auth-methods.show.binding-rules.index.empty.body"],[["htmlSafe"],[true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[15,6,[29,[[28,[37,15],["CONSUL_DOCS_API_URL"],null],"/acl/binding-rules"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"Read the documentation"],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[3]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","items","item"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","if","gt","each","-track-array","consul/auth-method/binding-list","empty-state","t","env"]]',moduleName:"consul-ui/templates/dc/acls/auth-methods/show/binding-rules.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/auth-methods/show/nspace-rules",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"L5CJq4k2",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[30,1,["model","item"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,4],[[30,2,["NamespaceRules","length"]],0],null],[[[1," "],[10,2],[12],[1,"\\n A set of rules that can control which namespace tokens created via this auth method will be created within. Unlike binding rules, the first matching namespace rule wins.\\n "],[13],[1,"\\n "],[8,[39,5],null,[["@items"],[[30,2,["NamespaceRules"]]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,6],null,null,[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,8],[[28,[37,9],[[30,1,["t"]],"empty.header"],null]],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,8],[[28,[37,9],[[30,1,["t"]],"empty.body",[28,[37,10],null,[["htmlSafe"],[true]]]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[15,6,[29,[[28,[37,11],["CONSUL_DOCS_API_URL"],null],"/acl/auth-methods#namespacerules"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"Read the documentation"],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[2]]]],[1]]]]],[1,"\\n"]],["route","item"],false,["route","routeName","let","if","gt","consul/auth-method/nspace-list","empty-state","block-slot","compute","fn","hash","env"]]',moduleName:"consul-ui/templates/dc/acls/auth-methods/show/nspace-rules.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"kWA9U8QS",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["replaceWith","dc.acls.tokens"],null]],null]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route"],false,["route","routeName","did-insert","route-action"]]',moduleName:"consul-ui/templates/dc/acls/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/policies/-form",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"k8B3pmJI",block:'[[[10,"form"],[12],[1,"\\n "],[8,[39,0],null,[["@form","@partition","@nspace","@item"],[[99,1,["@form"]],[99,2,["@partition"]],[99,3,["@nspace"]],[99,4,["@item"]]]],[["default"],[[[[1,"\\n"],[1," "],[8,[39,5],null,[["@name"],["template"]],null],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,7],[[33,8]],null],[[[1," "],[8,[39,9],null,[["@src","@onchange"],[[28,[37,10],["/${partition}/${nspace}/${dc}/tokens/for-policy/${id}",[28,[37,11],null,[["partition","nspace","dc","id"],[[33,2],[33,3],[33,12],[28,[37,13],[[33,14],""],null]]]]],null],[28,[37,15],[[30,0],[28,[37,16],[[33,17]],null]],[["value"],["data"]]]]],null],[1,"\\n"],[41,[28,[37,18],[[33,17,["length"]],0],null],[[[1," "],[8,[39,19],null,[["@caption","@items"],["Applied to the following tokens:",[99,17,["@items"]]]],null],[1,"\\n"]],[]],null]],[]],null],[1," "],[10,0],[12],[1,"\\n "],[8,[39,20],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,21],[[33,8],[28,[37,22],["create tokens"],null]],null],[[[1," "],[8,[39,23],[[16,"disabled",[52,[28,[37,13],[[33,4,["isPristine"]],[33,4,["isInvalid"]],[28,[37,24],[[33,4,["Name"]],""],null]],null],"disabled"]],[24,4,"submit"],[4,[38,25],["click",[28,[37,26],["create",[33,4]],null]],null]],[["@text"],["Save"]],null],[1,"\\n"]],[]],[[[41,[28,[37,22],["write policy"],[["item"],[[33,4]]]],[[[1," "],[8,[39,23],[[16,"disabled",[52,[33,4,["isInvalid"]],"disabled"]],[24,4,"submit"],[4,[38,25],["click",[28,[37,26],["update",[33,4]],null]],null]],[["@text"],["Save"]],null],[1,"\\n"]],[]],null]],[]]],[1," "],[8,[39,23],[[24,4,"reset"],[4,[38,15],[[30,0],"cancel",[33,4]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"],[41,[28,[37,21],[[28,[37,7],[[33,8]],null],[28,[37,22],["delete policy"],[["item"],[[33,4]]]]],null],[[[1," "],[8,[39,27],null,[["@message"],["Are you sure you want to delete this Policy?"]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,23],[[4,[38,15],[[30,0],[30,1],"delete",[33,4]],null]],[["@text","@color"],["Delete","critical"]],null],[1,"\\n "]],[1]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n"],[41,[28,[37,18],[[33,17,["length"]],0],null],[[[1," "],[8,[39,28],null,[["@onclose","@open","@aria"],[[28,[37,15],[[30,0],[30,3]],null],true,[28,[37,11],null,[["label"],["Policy in Use"]]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"Policy in Use"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n This Policy is currently in use. If you choose to delete this Policy, it will be removed from the\\n following "],[10,"strong"],[12],[1,[33,17,["length"]]],[1," Tokens"],[13],[1,":\\n "],[13],[1,"\\n "],[8,[39,19],null,[["@items","@target"],[[99,17,["@items"]],"_blank"]],null],[1,"\\n "],[10,2],[12],[1,"\\n This action cannot be undone. "],[1,[30,4]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,20],null,null,[["default"],[[[[1,"\\n "],[8,[39,23],[[4,[38,15],[[30,0],[30,2]],null]],[["@text","@color"],["Yes, Delete","critical"]],null],[1,"\\n "],[8,[39,23],[[4,[38,15],[[30,0],[30,5]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,29],null,[["@message","@execute","@cancel"],[[30,4],[30,2],[30,3]]],null],[1,"\\n"]],[]]],[1," "]],[2,3,4]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["confirm","execute","cancel","message","close"],false,["policy-form","form","partition","nspace","item","block-slot","if","not","create","data-source","uri","hash","dc","or","id","action","mut","items","gt","token-list","hds/button-set","and","can","hds/button","eq","on","route-action","confirmation-dialog","modal-dialog","delete-confirmation"]]',moduleName:"consul-ui/templates/dc/acls/policies/-form.hbs",isStrictMode:!1}) -e.default=n})) -define("consul-ui/templates/dc/acls/policies/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"zMcjLQlh",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/policy/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","id"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,8],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,9],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,10],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[28,[37,5],[[30,1,["params","id"]],""],null],[30,2,["data"]],[30,2,["data","isNew"]]],[[[1," "],[8,[39,12],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,13],["dc.acls.policies"],null]],[12],[1,"All Policies"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n"],[41,[30,8],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["New Policy"]],null],[1,"\\n"]],[]],[[[41,[28,[37,14],["write policy"],[["item"],[[30,7]]]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["Edit Policy"]],null],[1,"\\n"]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["View Policy"]],null],[1,"\\n"]],[]]]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[41,[28,[37,15],[[30,8]],null],[[[1," "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Policy ID"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,16],null,[["@value","@name"],[[30,7,["ID"]],"Policy ID"]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,8],[[28,[37,17],[[30,7]],null],"policy-management"],null],[[[1," "],[8,[39,18],[[24,0,"mb-3 mt-2"]],[["@type","@icon"],["inline","star-fill"]],[["default"],[[[[1,"\\n "],[8,[30,9,["Title"]],null,null,[["default"],[[[[1,"Management"]],[]]]]],[1,"\\n "],[8,[30,9,["Description"]],null,null,[["default"],[[[[1,"This global-management token is built into Consul\'s policy system. You can apply this special policy to tokens for full access. This policy is not editable or removeable, but can be ignored by not applying it to any tokens."]],[]]]]],[1,"\\n "],[8,[30,9,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition"],["Learn more",[29,[[28,[37,19],["CONSUL_DOCS_URL"],null],"/guides/acl.html#builtin-policies"]],"docs-link","trailing"]],null],[1,"\\n "]],[9]]]]],[1,"\\n "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Name"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,7,["Name"]]],[13],[1,"\\n "],[10,"dt"],[12],[1,"Valid Datacenters"],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,20],[", ",[28,[37,21],[[30,7]],null]],null]],[13],[1,"\\n "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,7,["Description"]]],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,22],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/tokens/for-policy/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,4],[30,5],[30,3],[30,6]]]]],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,23],[[30,10,["data","length"]],0],null],[[[1," "],[8,[39,24],null,[["@caption","@items"],["Applied to the following tokens:",[30,10,["data"]]]],null],[1,"\\n"]],[]],null],[1," "]],[10]]]]],[1,"\\n"]],[]],[[[1," "],[19,"dc/acls/policies/form",[1,2,3,4,5,6,7,8]],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5,6,7,8]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","dc","partition","nspace","id","item","create","A","loader"],true,["route","routeName","data-loader","uri","hash","or","block-slot","if","eq","consul/acl/disabled","app-error","let","app-view","href-to","can","not","copyable-code","policy/typeof","hds/alert","env","join","policy/datacenters","data-source","gt","token-list","partial"]]',moduleName:"consul-ui/templates/dc/acls/policies/edit.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/policies/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"gfKx11yz",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/policies",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,8],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,9],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,11],[[33,12],"Name:asc"],null],[28,[37,13],[[30,0],[28,[37,14],[[33,12]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["kind","datacenter","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,15],[28,[37,16],[[33,15],","],null],[27]],[28,[37,13],[[30,0],[28,[37,14],[[33,15]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change"],[[52,[33,17],[28,[37,16],[[33,17],","],null],[27]],[28,[37,13],[[30,0],[28,[37,14],[[33,17]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,18],[[33,19],[27]],null],[28,[37,16],[[33,19],","],null],[33,20]],[28,[37,13],[[30,0],[28,[37,14],[[33,19]],null]],[["value"],["target.selectedItems"]]],[33,20]]]]]]],[30,2,["data"]]],[[[1," "],[8,[39,21],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Policies"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,22],["create policies"],null],[[[1," "],[8,[39,23],null,[["@text","@route"],["Create","dc.acls.policies.create"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,24],[[30,5,["length"]],0],null],[[[1," "],[8,[39,25],null,[["@partition","@search","@onsearch","@sort","@filter"],[[30,1,["params","partition"]],[99,26,["@search"]],[28,[37,13],[[30,0],[28,[37,14],[[33,26]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@type","@sort","@filters","@search","@items"],["policy",[30,3,["value"]],[30,4],[99,26,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@items","@ondelete"],[[30,6,["items"]],[28,[37,29],["delete"],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,30],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,31],["routes.dc.acls.policies.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,31],["routes.dc.acls.policies.index.empty.body"],[["items","htmlSafe"],[[30,5,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,32],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on policies",[29,[[28,[37,33],["CONSUL_DOCS_URL"],null],"/commands/acl/policy"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,32],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,33],["CONSUL_LEARN_URL"],null],"/consul/security-networking/managing-acl-policies"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","sort","filters","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","if","eq","consul/acl/disabled","app-error","let","or","sortBy","action","mut","kind","split","datacenter","not-eq","searchproperty","searchProperties","app-view","can","hds/button","gt","consul/policy/search-bar","search","data-collection","consul/policy/list","route-action","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/acls/policies/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/roles/-form",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"V+NwcqN9",block:'[[[10,"form"],[12],[1,"\\n "],[8,[39,0],null,[["@form","@item","@dc","@nspace","@partition"],[[99,1,["@form"]],[99,2,["@item"]],[99,3,["@dc"]],[99,4,["@nspace"]],[99,5,["@partition"]]]],null],[1,"\\n"],[41,[28,[37,7],[[33,8]],null],[[[1," "],[8,[39,9],null,[["@src"],[[28,[37,10],["/${partition}/${nspace}/${dc}/tokens/for-role/${id}",[28,[37,11],null,[["partition","nspace","dc","id"],[[33,5],[33,4],[33,3],[28,[37,12],[[33,13],""],null]]]]],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,14],[[30,1,["data","length"]],0],null],[[[1," "],[10,"h2"],[12],[1,"Where is this role used?"],[13],[1,"\\n "],[10,2],[12],[1,"\\n We\'re only able to show information for the primary datacenter and the current datacenter. This list may not\\n show every case where this role is applied.\\n "],[13],[1,"\\n "],[8,[39,15],null,[["@caption","@items"],["Tokens",[30,1,["data"]]]],null],[1,"\\n"]],[]],null],[1," "]],[1]]]]],[1,"\\n"]],[]],null],[1," "],[10,0],[12],[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,17],[[33,8],[28,[37,18],["create roles"],null]],null],[[[1," "],[8,[39,19],[[16,"disabled",[28,[37,12],[[33,2,["isPristine"]],[33,2,["isInvalid"]],[28,[37,20],[[33,2,["Name"]],""],null]],null]],[24,4,"submit"],[4,[38,21],["click",[28,[37,22],["create",[33,2]],null]],null]],[["@text"],["Save"]],null],[1,"\\n"]],[]],[[[41,[28,[37,18],["write role"],[["item"],[[33,2]]]],[[[1," "],[8,[39,19],[[16,"disabled",[33,2,["isInvalid"]]],[24,4,"submit"],[4,[38,21],["click",[28,[37,22],["update",[33,2]],null]],null]],[["@text"],["Save"]],null],[1,"\\n"]],[]],null]],[]]],[1," "],[8,[39,19],[[24,4,"reset"],[4,[38,23],[[30,0],"cancel",[33,2]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n\\n"],[41,[28,[37,17],[[28,[37,7],[[33,8]],null],[28,[37,18],["delete role"],[["item"],[[33,2]]]]],null],[[[1," "],[8,[39,24],null,[["@message"],["Are you sure you want to delete this Role?"]],[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,19],[[4,[38,23],[[30,0],[30,2],"delete",[33,2]],null]],[["@text","@color"],["Delete","critical"]],null],[1,"\\n "]],[2]]]]],[1,"\\n "],[8,[39,25],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n"],[41,[28,[37,14],[[33,26,["length"]],0],null],[[[1," "],[8,[39,27],null,[["@onclose","@aria"],[[28,[37,23],[[30,0],[30,4]],null],[28,[37,11],null,[["label"],["Role in Use"]]]]],[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"Role in Use"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,25],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n This Role is currently in use. If you choose to delete this Role, it will be removed from the\\n following "],[10,"strong"],[12],[1,[33,26,["length"]]],[1," Tokens"],[13],[1,":\\n "],[13],[1,"\\n "],[8,[39,15],null,[["@items","@target"],[[99,26,["@items"]],"_blank"]],null],[1,"\\n "],[10,2],[12],[1,"\\n This action cannot be undone. "],[1,[30,5]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,25],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n "],[8,[39,19],[[4,[38,23],[[30,0],[30,3]],null]],[["@text","@color"],["Yes, Delete","critical"]],null],[1,"\\n "],[8,[39,19],[[4,[38,23],[[30,0],[30,6]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,28],null,[["@message","@execute","@cancel"],[[30,5],[30,3],[30,4]]],null],[1,"\\n"]],[]]],[1," "]],[3,4,5]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["loader","confirm","execute","cancel","message","close"],false,["role-form","form","item","dc","nspace","partition","if","not","create","data-source","uri","hash","or","id","gt","token-list","hds/button-set","and","can","hds/button","eq","on","route-action","action","confirmation-dialog","block-slot","items","modal-dialog","delete-confirmation"]]',moduleName:"consul-ui/templates/dc/acls/roles/-form.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/roles/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"J3r9dfLo",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/role/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","id"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,8],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,9],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,10],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,2,["data"]],[30,2,["data","isNew"]]],[[[1," "],[8,[39,12],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,13],["dc.acls.roles"],null]],[12],[1,"All Roles"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n"],[41,[30,7],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["New Role"]],null],[1,"\\n"]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["Edit Role"]],null],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[41,[28,[37,14],[[30,7]],null],[[[1," "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Role ID"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,15],null,[["@value","@name"],[[30,6,["ID"]],"Role ID"]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[19,"dc/acls/roles/form",[1,2,3,4,5,6,7]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5,6,7]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","dc","partition","nspace","item","create"],true,["route","routeName","data-loader","uri","hash","or","block-slot","if","eq","consul/acl/disabled","app-error","let","app-view","href-to","not","copyable-code","partial"]]',moduleName:"consul-ui/templates/dc/acls/roles/edit.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/roles/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"nMIoNCst",block:'[[[8,[39,0],null,[["@name","@title"],[[99,1,["@name"]],"Roles"]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/roles",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,8],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,9],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,11],[[33,12],"Name:asc"],null],[28,[37,13],[[30,0],[28,[37,14],[[33,12]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["searchproperty"],[[28,[37,4],null,[["value","change","default"],[[52,[28,[37,15],[[33,16],[27]],null],[28,[37,17],[[33,16],","],null],[33,18]],[28,[37,13],[[30,0],[28,[37,14],[[33,16]],null]],[["value"],["target.selectedItems"]]],[33,18]]]]]]],[30,2,["data"]]],[[[1,"\\n "],[8,[39,19],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Roles"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,20],["create roles"],null],[[[1," "],[8,[39,21],null,[["@text","@route"],["Create","dc.acls.roles.create"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,22],[[30,5,["length"]],0],null],[[[1," "],[8,[39,23],null,[["@search","@onsearch","@sort","@filter"],[[99,24,["@search"]],[28,[37,13],[[30,0],[28,[37,14],[[33,24]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@type","@sort","@filters","@search","@items"],["role",[30,3,["value"]],[30,4],[99,24,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@items","@ondelete"],[[30,6,["items"]],[28,[37,27],["delete"],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,29],["routes.dc.acls.roles.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,29],["routes.dc.acls.roles.index.empty.body"],[["items","htmlSafe"],[[30,5,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,30],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on roles",[29,[[28,[37,31],["CONSUL_DOCS_URL"],null],"/commands/acl/role"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,30],null,[["@text","@href","@icon","@iconPosition","@size"],["Read the API Docs",[29,[[28,[37,31],["CONSUL_DOCS_API_URL"],null],"/acl/roles.html"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","sort","filters","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","if","eq","consul/acl/disabled","app-error","let","or","sortBy","action","mut","not-eq","searchproperty","split","searchProperties","app-view","can","hds/button","gt","consul/role/search-bar","search","data-collection","consul/role/list","route-action","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/acls/roles/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/tokens/-fieldsets-legacy",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"igHmo1ap",block:'[[[1," "],[10,"fieldset"],[15,"disabled",[52,[28,[37,1],[[28,[37,2],["write token"],[["item"],[[33,3]]]]],null],"disabled"]],[12],[1,"\\n "],[10,"label"],[15,0,[29,["type-text",[52,[33,3,["error","Name"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Name"],[13],[1,"\\n "],[8,[39,4],null,[["@value","@name","@autofocus"],[[33,3,["Description"]],"name","autofocus"]],null],[1,"\\n "],[13],[1,"\\n"],[41,false,[[[1," "],[10,0],[14,"role","radiogroup"],[15,0,[52,[33,3,["error","Type"]]," has-error"]],[12],[1,"\\n"],[42,[28,[37,6],[[28,[37,6],[[28,[37,7],["management","client"],null]],null]],null],null,[[[1," "],[10,"label"],[12],[1,"\\n "],[10,1],[12],[1,[28,[35,8],[[30,1]],null]],[13],[1,"\\n "],[10,"input"],[14,3,"Type"],[15,2,[29,[[30,1]]]],[15,"checked",[52,[28,[37,9],[[33,3,["Type"]],[30,1]],null],"checked"]],[15,"onchange",[28,[37,10],[[30,0],"change"],null]],[14,4,"radio"],[12],[13],[1,"\\n "],[13],[1,"\\n"]],[1]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[10,"label"],[14,0,"type-text"],[12],[1,"\\n "],[8,[39,11],null,[["@class","@name","@syntax","@value","@onkeyup"],[[52,[33,3,["error","Rules"]],"error"],"Rules","hcl",[33,3,["Rules"]],[28,[37,10],[[30,0],"change","Rules"],null]]],[["label"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,12],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[41,[33,13],[[[1," "],[10,"label"],[14,0,"type-text"],[12],[1,"\\n "],[10,1],[12],[1,"ID"],[13],[1,"\\n "],[8,[39,4],null,[["@value"],[[33,3,["ID"]]]],null],[1,"\\n "],[10,"em"],[12],[1,"We\'ll generate a UUID if this field is left empty."],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n\\n"]],["type"],false,["if","not","can","item","input","each","-track-array","array","capitalize","eq","action","code-editor","env","create"]]',moduleName:"consul-ui/templates/dc/acls/tokens/-fieldsets-legacy.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/tokens/-fieldsets",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"DwYj+qxa",block:'[[[10,"fieldset"],[15,"disabled",[52,[28,[37,1],[[28,[37,2],["write token"],[["item"],[[33,3]]]]],null],"disabled"]],[12],[1,"\\n"],[41,[33,4],[[[1," "],[10,0],[14,0,"type-toggle"],[12],[1,"\\n "],[10,"label"],[12],[1,"\\n "],[10,"input"],[14,3,"Local"],[15,"checked",[52,[33,5],"checked"]],[15,"onchange",[28,[37,6],[[30,0],"change"],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,1],[12],[1,"Restrict this token to a local datacenter?"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"em"],[12],[1,"Local tokens get set in the Raft store of the local DC and do not ever get transmitted to the primary DC or replicated to any other DC."],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[10,"label"],[14,0,"type-text validate-optional"],[12],[1,"\\n "],[10,1],[12],[1,"Description (Optional)"],[13],[1,"\\n "],[10,"textarea"],[14,3,"Description"],[15,"oninput",[28,[37,6],[[30,0],"change"],null]],[12],[1,[33,3,["Description"]]],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"],[10,"fieldset"],[14,1,"roles"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Roles"],[13],[1,"\\n "],[8,[39,7],null,[["@disabled","@dc","@partition","@nspace","@items"],[[28,[37,1],[[28,[37,2],["write token"],[["item"],[[33,3]]]]],null],[99,8,["@dc"]],[99,9,["@partition"]],[99,10,["@nspace"]],[33,3,["Roles"]]]],null],[1,"\\n"],[13],[1,"\\n"],[10,"fieldset"],[14,1,"policies"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Policies"],[13],[1,"\\n "],[8,[39,11],null,[["@disabled","@dc","@partition","@nspace","@items"],[[28,[37,1],[[28,[37,2],["write token"],[["item"],[[33,3]]]]],null],[99,8,["@dc"]],[99,9,["@partition"]],[99,10,["@nspace"]],[33,3,["Policies"]]]],null],[1,"\\n"],[13],[1,"\\n"]],[],false,["if","not","can","item","create","Local","action","role-selector","dc","partition","nspace","policy-selector"]]',moduleName:"consul-ui/templates/dc/acls/tokens/-fieldsets.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/tokens/-form",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"3VM7Ab9v",block:'[[[10,"form"],[12],[1,"\\n"],[41,[28,[37,1],[[28,[37,2],[[33,3]],null]],null],[[[1," "],[19,"dc/acls/tokens/fieldsets",[]],[1,"\\n"]],[]],[[[1," "],[19,"dc/acls/tokens/fieldsets-legacy",[]],[1,"\\n"]],[]]],[1," "],[10,0],[12],[1,"\\n "],[8,[39,5],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,6],[[33,7],[28,[37,8],["create tokens"],null]],null],[[[1," "],[8,[39,9],[[16,"disabled",[52,[28,[37,10],[[28,[37,6],[[28,[37,2],[[33,3]],null],[33,3,["isPristine"]]],null],[33,3,["isInvalid"]]],null],"disabled"]],[24,4,"submit"],[4,[38,11],["click",[28,[37,12],["create",[33,3]],null]],null]],[["@text"],["Save"]],null],[1,"\\n"]],[]],[[[41,[28,[37,8],["write token"],[["item"],[[33,3]]]],[[[1," "],[8,[39,9],[[16,"disabled",[52,[33,3,["isInvalid"]],"disabled"]],[24,4,"submit"],[4,[38,11],["click",[28,[37,12],["update",[33,3]],null]],null]],[["@text"],["Save"]],null],[1,"\\n"]],[]],null]],[]]],[1," "],[8,[39,9],[[24,4,"reset"],[4,[38,13],[[30,0],"cancel",[33,3]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"],[41,[28,[37,6],[[28,[37,1],[[33,7]],null],[28,[37,8],["delete token"],[["item","token"],[[33,3],[33,14]]]]],null],[[[1," "],[8,[39,15],null,[["@message"],["Are you sure you want to delete this Token?"]],[["default"],[[[[1,"\\n "],[8,[39,16],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,9],[[4,[38,13],[[30,0],[30,1],"delete",[33,3]],null]],[["@text","@color"],["Delete","critical"]],null],[1,"\\n "]],[1]]]]],[1,"\\n "],[8,[39,16],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[8,[39,17],null,[["@message","@execute","@cancel"],[[30,4],[30,2],[30,3]]],null],[1,"\\n "]],[2,3,4]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["confirm","execute","cancel","message"],true,["if","not","token/is-legacy","item","partial","hds/button-set","and","create","can","hds/button","or","on","route-action","action","token","confirmation-dialog","block-slot","delete-confirmation"]]',moduleName:"consul-ui/templates/dc/acls/tokens/-form.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/tokens/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"VqbRsph6",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/token/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","id"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,8],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,9],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,10],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,2,["data"]],[30,2,["data","isNew"]]],[[[1," "],[8,[39,12],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,13],["dc.acls.tokens"],null]],[12],[1,"All Tokens"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n"],[41,[30,7],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["New Token"]],null],[1,"\\n"]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["Edit Token"]],null],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,14],[[30,7]],null],[[[1," "],[8,[39,15],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,16],[[30,6,["AccessorID"]],[33,17,["AccessorID"]]],null],[[[1," "],[8,[39,18],null,[["@message"],["Are you sure you want to use this ACL token?"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,19],[[4,[38,20],[[30,0],[30,8],"use",[30,6]],null]],[["@text","@color"],["Use","secondary"]],null],[1,"\\n "]],[8]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[30,11]],[1,"\\n "],[13],[1,"\\n "],[8,[39,15],null,null,[["default"],[[[[1,"\\n "],[8,[39,19],[[4,[38,20],[[30,0],[30,9]],null]],[["@text","@color"],["Confirm Use","critical"]],null],[1,"\\n "],[8,[39,19],[[4,[38,20],[[30,0],[30,10]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[9,10,11]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[41,[28,[37,21],["duplicate token"],[["item"],[[30,6]]]],[[[1," "],[8,[39,19],[[4,[38,20],[[30,0],"clone",[30,6]],null]],[["@text","@color"],["Duplicate","secondary"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[41,[28,[37,22],[[30,6]],null],[[[1," "],[8,[39,23],[[24,0,"mb-6"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,12,["Title"]],null,null,[["default"],[[[[1,"Update"]],[]]]]],[1,"\\n "],[8,[30,12,["Description"]],null,null,[["default"],[[[[1,"We have upgraded our ACL system by allowing you to create reusable policies which you can then apply to tokens. Don\'t worry, even though this token was written in the old style, it is still valid. However, we do recommend upgrading your old tokens to the new style."]],[]]]]],[1,"\\n "],[8,[30,12,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition"],["Learn more",[29,[[28,[37,24],["CONSUL_DOCS_URL"],null],"/guides/acl-migrate-tokens.html"]],"docs-link","trailing"]],null],[1,"\\n "]],[12]]]]],[1,"\\n"]],[]],null],[41,[28,[37,14],[[30,7]],null],[[[1," "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"AccessorID"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,25],null,[["@value","@name"],[[30,6,["AccessorID"]],"AccessorID"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,"Token"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,25],null,[["@obfuscated","@value","@name"],[true,[30,6,["SecretID"]],"Token"]],null],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,26],[[28,[37,14],[[28,[37,22],[[30,6]],null]],null],[28,[37,14],[[30,7]],null]],null],[[[1," "],[10,"dt"],[12],[1,"Scope"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[52,[30,6,["Local"]],"local","global"]],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[19,"dc/acls/tokens/form",[1,2,3,4,5,6,7]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5,6,7]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","dc","partition","nspace","item","create","confirm","execute","cancel","message","A"],true,["route","routeName","data-loader","uri","hash","or","block-slot","if","eq","consul/acl/disabled","app-error","let","app-view","href-to","not","hds/button-set","not-eq","token","confirmation-dialog","hds/button","action","can","token/is-legacy","hds/alert","env","copyable-code","and","partial"]]',moduleName:"consul-ui/templates/dc/acls/tokens/edit.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/acls/tokens/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"vndZHRNu",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/tokens",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,8],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,9],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,11],[[33,12],"CreateTime:desc"],null],[28,[37,13],[[30,0],[28,[37,14],[[33,12]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["kind","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,15],[28,[37,16],[[33,15],","],null],[27]],[28,[37,13],[[30,0],[28,[37,14],[[33,15]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,17],[[33,18],[27]],null],[28,[37,16],[[33,18],","],null],[33,19]],[28,[37,13],[[30,0],[28,[37,14],[[33,18]],null]],[["value"],["target.selectedItems"]]],[33,19]]]]]]],[30,2,["data"]]],[[[1,"\\n "],[8,[39,20],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Tokens"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,21],["create tokens"],null],[[[1," "],[8,[39,22],null,[["@text","@route"],["Create","dc.acls.tokens.create"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,23],[[30,5,["length"]],0],null],[[[1," "],[8,[39,24],null,[["@search","@onsearch","@sort","@filter"],[[99,25,["@search"]],[28,[37,13],[[30,0],[28,[37,14],[[33,25]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[41,[28,[37,26],[[30,5]],null],[[[1," "],[8,[39,27],[[24,0,"mb-3 mt-3"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Update"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"We have upgraded our ACL System to allow the creation of reusable policies that can be applied to tokens. Read more about the changes and how to upgrade legacy tokens."]],[]]]]],[1,"\\n "],[8,[30,6,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition"],["Learn more",[29,[[28,[37,28],["CONSUL_DOCS_URL"],null],"/guides/acl-migrate-tokens.html"]],"docs-link","trailing"]],null],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,29],null,[["@type","@sort","@filters","@search","@items"],["token",[30,3,["value"]],[30,4],[99,25,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,7,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,30],null,[["@items","@token","@onuse","@ondelete","@onlogout","@onclone"],[[30,7,["items"]],[30,1,["model","user","token"]],[28,[37,31],["use"],null],[28,[37,31],["delete"],null],[28,[37,31],["logout"],null],[28,[37,31],["clone"],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,7,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,32],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,33],["routes.dc.acls.tokens.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,33],["routes.dc.acls.tokens.index.empty.body"],[["items","htmlSafe"],[[30,5,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","sort","filters","items","A","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","if","eq","consul/acl/disabled","app-error","let","or","sortBy","action","mut","kind","split","not-eq","searchproperty","searchProperties","app-view","can","hds/button","gt","consul/token/search-bar","search","token/is-legacy","hds/alert","env","data-collection","consul/token/list","route-action","empty-state","t"]]',moduleName:"consul-ui/templates/dc/acls/tokens/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/intentions/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"APCDJQ0j",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/intention/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","intention_id"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]],[28,[37,9],[[28,[37,10],["write intention"],[["item"],[[30,2,["data"]]]]]],null]],[[[1," "],[8,[39,11],null,null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,12],["dc.intentions"],null]],[12],[1,"All Intentions"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n"],[41,[28,[37,9],[[30,4]],null],[[[41,[30,3,["ID"]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["Edit Intention"]],null],[1,"\\n"]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["New Intention"]],null],[1,"\\n"]],[]]]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["View Intention"]],null],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,14],null,[["@readonly","@item","@dc","@nspace","@partition","@onsubmit"],[[30,4],[30,3],[30,1,["model","dc"]],[30,1,["params","nspace"]],[30,1,["params","partition"]],[28,[37,15],["transitionTo","dc.intentions.index",[28,[37,4],null,[["dc"],[[30,1,["params","dc"]]]]]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4]]],[1," "]],[]]]]],[1,"\\n"]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","item","readOnly"],false,["route","routeName","data-loader","uri","hash","or","block-slot","app-error","let","not","can","app-view","href-to","if","consul/intention/form","route-action"]]',moduleName:"consul-ui/templates/dc/intentions/edit.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/intentions/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"MRCKg8a1",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/intentions",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Action:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["access","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,15],[[33,16],[27]],null],[28,[37,14],[[33,16],","],null],[33,17]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]],[33,17]]]]]]],[30,2,["data"]]],[[[1,"\\n "],[8,[39,18],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Intentions"]],null],[1," "],[10,"em"],[12],[1,[28,[35,19],[[30,5,["length"]]],null]],[1," total"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"label"],[14,"for","toolbar-toggle"],[12],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,20],["create intentions"],null],[[[1," "],[8,[39,21],null,[["@text","@route"],["Create","dc.intentions.create"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n\\n"],[41,[28,[37,22],[[30,5,["length"]],0],null],[[[1," "],[8,[39,23],null,[["@search","@onsearch","@sort","@filter"],[[99,24,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,24]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@sink","@type","@ondelete"],[[28,[37,3],["/${partition}/${dc}/${nspace}/intention/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"intention",[99,26,["@ondelete"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@type","@sort","@filters","@search","@items"],["intention",[30,3,["value"]],[30,4],[99,24,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,7,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@items","@delete"],[[30,7,["items"]],[30,6,["delete"]]]],[["default"],[[[[1,"\\n "],[8,[30,8,["CustomResourceNotice"]],null,null,null],[1,"\\n "],[8,[30,8,["Table"]],null,null,null],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,7,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,30],["routes.dc.intentions.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,30],["routes.dc.intentions.index.empty.body"],[["items","canUseACLs","htmlSafe"],[[30,5,["length"]],[28,[37,20],["use acls"],null],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,31],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on intentions",[29,[[28,[37,32],["CONSUL_DOCS_URL"],null],"/commands/intention"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,31],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,32],["CONSUL_DOCS_LEARN_URL"],null],"/consul/getting-started/connect"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","api","sort","filters","items","writer","collection","list"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","access","split","not-eq","searchproperty","searchProperties","app-view","format-number","can","hds/button","gt","consul/intention/search-bar","search","data-writer","refresh-route","data-collection","consul/intention/list","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/intentions/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/kv/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"OKjbKUH/",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n"],[44,["/"],[[[1,"\\n"],[44,[[28,[37,3],[[28,[37,4],[[30,2],[28,[37,5],[0,-1,[28,[37,6],[[30,1,["params","key"]],[30,2]],null]],null]],null],[30,2]],null]],[[[1,"\\n "],[8,[39,7],null,[["@src"],[[28,[37,8],["/${partition}/${nspace}/${dc}/kv/${key}",[28,[37,9],null,[["partition","nspace","dc","key"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[52,[28,[37,11],[[33,1],"create"],null],"",[30,1,["params","key"]]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,12],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@error","@login"],[[30,4,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,12],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,4,["data"]]],[[[1,"\\n "],[8,[39,14],null,null,[["default"],[[[[1,"\\n\\n "],[8,[39,12],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,15],null,[["@href"],[[28,[37,16],["dc.kv.index"],null]]],[["default"],[[[[1,"\\n Key / Values\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,17],[[30,3],[30,2]],null],[[[1,"\\n"],[44,[[28,[37,6],[[30,3],[30,2]],null]],[[[1,"\\n"],[42,[28,[37,19],[[28,[37,19],[[30,9]],null]],null],null,[[[41,[28,[37,20],[[30,10,["length"]],0],null],[[[1," "],[10,"li"],[12],[1,"\\n "],[8,[39,15],[[4,[38,15],[[30,0],[30,10]],null]],[["@href"],[[28,[37,16],["dc.kv.folder",[28,[37,4],["/",[28,[37,21],[[28,[37,5],[0,[28,[37,22],[[30,11],1],null],[30,9]],null],""],null]],null]],null]]],[["default"],[[[[1,"\\n "],[1,[30,10]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[10,11]],null]],[9]]],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,12],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n"],[41,[28,[37,23],[[30,8,["Key"]],[28,[37,17],[[30,8,["Key"]],[30,3]],null]],null],[[[1," "],[8,[30,1,["Title"]],null,[["@title","@render"],["Edit Key / Value",false]],null],[1,"\\n "],[1,[28,[35,24],[[30,8,["Key"]],[30,3]],null]],[1,"\\n"]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title","@render"],["New Key / Value",true]],null],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,12],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n"],[41,[30,8,["Session"]],[[[1," "],[8,[39,25],null,[["@type"],["kv"]],null],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,26],null,[["@item","@dc","@nspace","@partition","@onsubmit","@parent"],[[30,8],[30,1,["params","dc"]],[30,1,["params","nspace"]],[30,1,["params","partition"]],[52,[28,[37,27],[[30,3],[30,2]],null],[28,[37,28],["dc.kv.index"],null],[28,[37,28],["dc.kv.folder",[30,3]],null]],[30,3]]],null],[1,"\\n\\n\\n"],[41,[28,[37,23],[[30,8,["Session"]]],null],[[[1," "],[8,[39,29],null,[["@src","@onchange"],[[28,[37,8],["/${partition}/${nspace}/${dc}/sessions/for-key/${id}",[28,[37,9],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,8,["Session"]]]]]],null],[28,[37,15],[[30,0],[28,[37,30],[[33,31]],null]],[["value"],["data"]]]]],null],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[8,[39,15],[[24,"rel","help"]],[["@href","@external"],[[28,[37,3],[[28,[37,32],["CONSUL_DOCS_URL"],null],"/internals/sessions.html#session-design"],null],true]],[["default"],[[[[1,"\\n Lock Session\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[41,[33,31,["ID"]],[[[1," "],[8,[39,33],null,[["@item","@ondelete"],[[99,31,["@item"]],[30,4,["invalidate"]]]],null],[1,"\\n"]],[]],null]],[]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[5,6,7,8]]],[1," "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[3]]]],[2]]]],[1]]]]],[1,"\\n"]],["route","separator","parentKey","loader","dc","partition","nspace","item","parts","breadcrumb","index"],false,["route","routeName","let","concat","join","slice","split","data-loader","uri","hash","if","string-ends-with","block-slot","app-error","app-view","action","href-to","not-eq","each","-track-array","gt","append","add","and","left-trim","consul/lock-session/notifications","consul/kv/form","eq","transition-to","data-source","mut","session","env","consul/lock-session/form"]]',moduleName:"consul-ui/templates/dc/kv/edit.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/kv/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"Vj7yxEy8",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src","@onchange"],[[28,[37,3],["/${partition}/${nspace}/${dc}/kv/${key}",[28,[37,4],null,[["partition","nspace","dc","key"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","key"]],"/"],null]]]]],null],[28,[37,6],[[30,0],[28,[37,7],[[33,8]],null]],[["value"],["data"]]]]],null],[1,"\\n "],[8,[39,9],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/kvs/${key}",[28,[37,4],null,[["partition","nspace","dc","key"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","key"]],"/"],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,10],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,11],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,13],[[30,2,["error","status"]],"404"],null],[[[1," "],[8,[39,14],[[4,[38,15],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,4,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,4,["Description"]],null,null,[["default"],[[[[1,"\\n This KV or parent of this KV was deleted.\\n "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[]],[[[41,[28,[37,13],[[30,2,["error","status"]],"403"],null],[[[1," "],[8,[39,14],[[4,[38,15],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"\\n You no longer have access to this KV.\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,14],[[4,[38,15],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"\\n An error was returned whilst loading this data, refresh to try again.\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]],[]]],[1," "]],[3]]]]],[1,"\\n\\n "],[8,[39,10],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,5],[[33,17],"Kind:asc"],null],[28,[37,6],[[30,0],[28,[37,7],[[33,17]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["kind"],[[28,[37,4],null,[["value","change"],[[52,[33,18],[28,[37,19],[[33,18],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,18]],null]],[["value"],["target.selectedItems"]]]]]]]]],[33,8],[30,2,["data"]]],[[[1," "],[8,[39,20],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,21],[[30,9,["Key"]],"/"],null],[[[1," "],[8,[39,10],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,22],["dc.kv"],null]],[12],[1,"Key / Values"],[13],[13],[1,"\\n"],[42,[28,[37,24],[[28,[37,24],[[28,[37,25],[0,-2,[28,[37,19],[[30,9,["Key"]],"/"],null]],null]],null]],null],null,[[[1," "],[10,"li"],[12],[11,3],[16,6,[28,[37,22],["dc.kv.folder",[28,[37,26],["/",[28,[37,27],[[28,[37,25],[0,[28,[37,28],[[30,12],1],null],[28,[37,19],[[30,9,["Key"]],"/"],null]],null],""],null]],null]],null]],[4,[38,29],[[30,11]],null],[12],[1,[30,11]],[13],[13],[1,"\\n"]],[11,12]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,10],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n"],[41,[28,[37,13],[[30,9,["Key"]],"/"],null],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["Key / Value"]],null],[1,"\\n"]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],[[28,[37,30],[1,[28,[37,31],[1,[28,[37,32],[[28,[37,19],[[30,9,["Key"]],"/"],null]],null]],null]],null]]],null],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[10,"label"],[14,"for","toolbar-toggle"],[12],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,33],[[30,10,["length"]],0],null],[[[1," "],[8,[39,34],null,[["@search","@onsearch","@sort","@filter"],[[99,35,["@search"]],[28,[37,6],[[30,0],[28,[37,7],[[33,35]],null]],[["value"],["target.value"]]],[30,7],[30,8]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,36],["create kvs"],null],[[[41,[28,[37,37],[[30,9,["Key"]],[28,[37,21],[[30,9,["Key"]],"/"],null]],null],[[[1," "],[8,[39,38],null,[["@text","@isHrefExternal","@href"],["Create",false,[29,[[28,[37,22],["dc.kv.create",[30,9,["Key"]]],null]]]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,38],null,[["@text","@route"],["Create","dc.kv.root-create"]],null],[1,"\\n"]],[]]]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,39],null,[["@sink","@type","@label","@ondelete"],[[28,[37,3],["/${partition}/${nspace}/${dc}/kv/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"kv","key",[99,40,["@ondelete"]]]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,41],null,[["@type","@sort","@filters","@search","@items"],["kv",[30,7,["value"]],[30,8],[99,35,["@search"]],[30,10]]],[["default"],[[[[1,"\\n "],[8,[30,14,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,42],null,[["@items","@parent","@delete"],[[30,14,["items"]],[30,9],[30,13,["delete"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,14,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,43],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,44],["routes.dc.kv.index.empty.header"],[["items"],[[30,10,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,44],["routes.dc.kv.index.empty.body"],[["items","canUseACLs","htmlSafe"],[[30,10,["length"]],[28,[37,36],["use acls"],null],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,45],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on K/V",[29,[[28,[37,46],["CONSUL_DOCS_URL"],null],"/agent/kv"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,45],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,46],["CONSUL_DOCS_LEARN_URL"],null],"/consul/getting-started/kv"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[13]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[7,8,9,10]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","after","T","T","T","sort","filters","parent","items","breadcrumb","index","writer","collection"],false,["route","routeName","data-source","uri","hash","or","action","mut","parent","data-loader","block-slot","app-error","if","eq","hds/toast","notification","let","sortBy","kind","split","app-view","not-eq","href-to","each","-track-array","slice","join","append","add","tooltip","take","drop","reverse","gt","consul/kv/search-bar","search","can","and","hds/button","data-writer","refresh-route","data-collection","consul/kv/list","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/kv/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/nodes/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"vxNtRU5K",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/leader",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/nodes",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,3,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,9],[[33,10],"Status:asc"],null],[28,[37,11],[[30,0],[28,[37,12],[[33,10]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["status","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,14],[28,[37,15],[[33,14],","],null],[27]],[28,[37,11],[[30,0],[28,[37,12],[[33,14]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,16],[[33,17],[27]],null],[28,[37,15],[[33,17],","],null],[30,0,["_searchProperties"]]],[28,[37,11],[[30,0],[28,[37,12],[[33,17]],null]],[["value"],["target.selectedItems"]]],[30,0,["_searchProperties"]]]]]]]],[30,3,["data"]],[30,2,["data"]]],[[[44,[[28,[37,18],["Meta.synthetic-node",[30,6]],null]],[[[1," "],[8,[39,19],null,null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Nodes"]],null],[1,"\\n "],[10,"em"],[12],[1,[28,[35,20],[[30,6,["length"]]],null]],[1," total"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"label"],[14,"for","toolbar-toggle"],[12],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,21],[[30,8,["length"]],0],null],[[[1," "],[8,[39,22],null,[["@search","@onsearch","@sort","@filter"],[[99,23,["@search"]],[28,[37,11],[[30,0],[28,[37,12],[[33,23]],null]],[["value"],["target.value"]]],[30,4],[30,5]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,24],null,[["@items","@filteredItems","@postfix"],[[30,6],[30,8],[28,[37,25],[[30,1,["params","partition"]],[30,1,["params","dc"]]],null]]],null],[1,"\\n "],[8,[39,26],null,[["@type","@sort","@filters","@search","@items"],["node",[30,4,["value"]],[30,5],[99,23,["@search"]],[30,8]]],[["default"],[[[[1,"\\n "],[8,[30,9,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@items","@leader"],[[30,9,["items"]],[30,7]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,9,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,29],["routes.dc.nodes.index.empty.header"],[["items"],[[30,6,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,29],["routes.dc.nodes.index.empty.body"],[["items","canUseACLs","htmlSafe"],[[30,6,["length"]],[28,[37,30],["use acls"],null],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,31],null,[["@text","@href","@color","@icon","@iconPosition","@size"],[[28,[37,29],["routes.dc.nodes.index.empty.documentation"],null],[29,[[28,[37,32],["CONSUL_DOCS_DEVELOPER_URL"],null],"/agent"]],"tertiary","docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,31],null,[["@text","@href","@color","@icon","@iconPosition","@size"],[[28,[37,29],["routes.dc.nodes.index.empty.learn"],null],[29,[[28,[37,32],["CONSUL_DOCS_LEARN_URL"],null],"/tutorials/consul/deployment-guide?in=consul/production-deploy#configure-consul-agents"]],"tertiary","learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[8]]]],[4,5,6,7]]],[1," "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","leader","api","sort","filters","items","leader","filtered","collection"],false,["route","routeName","data-source","uri","hash","data-loader","block-slot","app-error","let","or","sortBy","action","mut","if","status","split","not-eq","searchproperty","reject-by","app-view","format-number","gt","consul/node/search-bar","search","consul/node/agentless-notice","concat","data-collection","consul/node/list","empty-state","t","can","hds/button","env"]]',moduleName:"consul-ui/templates/dc/nodes/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/nodes/show",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"14xgVgV5",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/coordinates/for-node/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/node/${name}/${peer}",[28,[37,4],null,[["partition","nspace","dc","name","peer"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]],[30,1,["params","peer"]]]]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,3,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,9],[[30,3,["error","status"]],"404"],null],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"This node no longer exists in the catalog."]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[41,[28,[37,9],[[30,3,["error","status"]],"403"],null],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"You no longer have access to this node."]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,7,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,7,["Description"]],null,null,[["default"],[[[[1,"An error was returned whilst loading this data, refresh to try again."]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]],[]]],[1," "]],[4]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,3,["data"]],[30,2,["data"]]],[[[1," "],[8,[39,13],null,null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["notification"]],[["default"],[[[[1,"\\n "],[8,[39,14],null,[["@type","@status"],[[30,11],[30,10]]],null],[1,"\\n "]],[10,11]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,15],["dc.nodes"],[["params"],[[28,[37,4],null,[["peer"],[[27]]]]]]]],[12],[1,"All Nodes"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[30,8,["Node"]]]],null],[1,"\\n "],[13],[1,"\\n "],[10,"label"],[14,"for","toolbar-toggle"],[12],[13],[1,"\\n "],[8,[39,16],null,[["@item"],[[30,8]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["nav"]],[["default"],[[[[1,"\\n "],[8,[39,17],null,[["@items"],[[28,[37,18],[[28,[37,19],[[28,[37,4],null,[["label","href","selected"],[[28,[37,20],["routes.dc.nodes.show.healthchecks.title"],null],[28,[37,15],["dc.nodes.show.healthchecks"],null],[28,[37,21],["dc.nodes.show.healthchecks"],null]]]],[28,[37,4],null,[["label","href","selected"],[[28,[37,20],["routes.dc.nodes.show.services.title"],null],[28,[37,15],["dc.nodes.show.services"],null],[28,[37,21],["dc.nodes.show.services"],null]]]],[52,[30,9,["distances"]],[28,[37,4],null,[["label","href","selected"],[[28,[37,20],["routes.dc.nodes.show.rtt.title"],null],[28,[37,15],["dc.nodes.show.rtt"],null],[28,[37,21],["dc.nodes.show.rtt"],null]]]],""],[52,[28,[37,22],["read sessions"],null],[28,[37,4],null,[["label","href","selected"],[[28,[37,20],["routes.dc.nodes.show.sessions.title"],null],[28,[37,15],["dc.nodes.show.sessions"],null],[28,[37,21],["dc.nodes.show.sessions"],null]]]],""],[28,[37,4],null,[["label","href","selected"],[[28,[37,20],["routes.dc.nodes.show.metadata.title"],null],[28,[37,15],["dc.nodes.show.metadata"],null],[28,[37,21],["dc.nodes.show.metadata"],null]]]]],null]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,23],null,[["@value","@name"],[[30,8,["Address"]],"Address"]],[["default"],[[[[1,[30,8,["Address"]]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,24],null,[["@name","@model"],[[99,1,["@name"]],[28,[37,25],[[28,[37,4],null,[["item","tomography"],[[30,8],[30,9]]]],[30,1,["model"]]],null]]],[["default"],[[[[1,"\\n "],[46,[28,[37,27],null,null],null,null,null],[1,"\\n "]],[12]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[8,9]]],[1," "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","tomography","loader","after","T","T","T","item","tomography","status","type","o"],false,["route","routeName","data-source","uri","hash","data-loader","block-slot","app-error","if","eq","hds/toast","notification","let","app-view","consul/lock-session/notifications","href-to","consul/peer/info","tab-nav","compact","array","t","is-href","can","copy-button","outlet","assign","component","-outlet"]]',moduleName:"consul-ui/templates/dc/nodes/show.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/nodes/show/healthchecks",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"i+D+Qmra",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],null,[["value","change"],[[28,[37,4],[[33,5],"Status:asc"],null],[28,[37,6],[[30,0],[28,[37,7],[[33,5]],null]],[["value"],["target.selected"]]]]]],[28,[37,3],null,[["status","kind","check","searchproperty"],[[28,[37,3],null,[["value","change"],[[52,[33,9],[28,[37,10],[[33,9],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,9]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change"],[[52,[33,11],[28,[37,10],[[33,11],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,11]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change"],[[52,[33,12],[28,[37,10],[[33,12],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,12]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change","default"],[[52,[28,[37,13],[[33,14],[27]],null],[28,[37,10],[[33,14],","],null],[33,15]],[28,[37,6],[[30,0],[28,[37,7],[[33,14]],null]],[["value"],["target.selectedItems"]]],[33,15]]]]]]],[30,1,["model","item","Checks"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,16],[[30,4,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,17],null,[["@search","@onsearch","@sort","@filter"],[[99,18,["@search"]],[28,[37,6],[[30,0],[28,[37,7],[[33,18]],null]],[["value"],["target.value"]]],[30,2],[30,3]]],null],[1,"\\n"]],[]],null],[44,[[28,[37,19],["Type","serf",[30,4]],null]],[[[41,[28,[37,20],[[30,5],[28,[37,21],[[30,5,["Status"]],"critical"],null]],null],[[[1," "],[8,[39,22],[[24,0,"mb-3 mt-2"]],[["@type","@color"],["inline","warning"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,[28,[35,23],["routes.dc.nodes.show.healthchecks.critical-serf-notice.header"],null]]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,[28,[35,23],["routes.dc.nodes.show.healthchecks.critical-serf-notice.body"],null]]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],null]],[5]]],[1," "],[8,[39,24],null,[["@type","@sort","@filters","@search","@items"],["health-check",[30,2,["value"]],[30,3],[99,18,["@search"]],[30,4]]],[["default"],[[[[1,"\\n "],[8,[30,7,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@items"],[[30,7,["items"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,7,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,26],null,null,[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,23],["routes.dc.nodes.show.healthchecks.empty"],[["items","htmlSafe"],[[30,4,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "],[13],[1,"\\n"]],[2,3,4]]]],[1]]]]]],["route","sort","filters","items","serf","A","collection"],false,["route","routeName","let","hash","or","sortBy","action","mut","if","status","split","kind","check","not-eq","searchproperty","searchProperties","gt","consul/health-check/search-bar","search","find-by","and","eq","hds/alert","t","data-collection","consul/health-check/list","empty-state","block-slot"]]',moduleName:"consul-ui/templates/dc/nodes/show/healthchecks.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/nodes/show/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"qL7XyD9+",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],[[30,1,["model","item","Checks","length"]],0],null],[[[1," "],[1,[28,[35,4],[[28,[37,5],["replaceWith","dc.nodes.show.services"],null]],null]],[1,"\\n"]],[]],[[[1," "],[1,[28,[35,4],[[28,[37,5],["replaceWith","dc.nodes.show.healthchecks"],null]],null]],[1,"\\n"]],[]]]],[1]]]]],[1,"\\n"]],["route"],false,["route","routeName","if","eq","did-insert","route-action"]]',moduleName:"consul-ui/templates/dc/nodes/show/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/nodes/show/metadata",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"II5xvxvi",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[30,1,["model","item","Meta"]],[[[1," "],[8,[39,3],null,[["@items"],[[28,[37,4],[[30,1,["model","item","Meta"]]],null]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,5],null,null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n This node has no metadata.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route"],false,["route","routeName","if","consul/metadata/list","entries","empty-state","block-slot"]]',moduleName:"consul-ui/templates/dc/nodes/show/metadata.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/nodes/show/rtt",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"dQ8VTTOG",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[30,1,["model","tomography"]]],[[[41,[28,[37,4],[[30,2,["distances"]]],null],[[[1," "],[1,[28,[35,5],[[28,[37,6],["replaceWith","dc.nodes.show"],null]],null]],[1,"\\n"]],[]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Minimum\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,7],[[30,2,["min"]]],[["maximumFractionDigits"],[2]]]],[1,"ms\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,"\\n Median\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,7],[[30,2,["median"]]],[["maximumFractionDigits"],[2]]]],[1,"ms\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,"\\n Maximum\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,7],[[30,2,["max"]]],[["maximumFractionDigits"],[2]]]],[1,"ms\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,8],null,[["@distances"],[[30,2,["distances"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[]]]],[2]]]],[1]]]]],[1,"\\n"]],["route","tomography"],false,["route","routeName","let","if","not","did-insert","route-action","format-number","consul/tomography/graph"]]',moduleName:"consul-ui/templates/dc/nodes/show/rtt.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/nodes/show/services",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"3xjsHJKx",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],null,[["value","change"],[[28,[37,4],[[33,5],"Status:asc"],null],[28,[37,6],[[30,0],[28,[37,7],[[33,5]],null]],[["value"],["target.selected"]]]]]],[28,[37,3],null,[["status","source","searchproperty"],[[28,[37,3],null,[["value","change"],[[52,[33,9],[28,[37,10],[[33,9],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,9]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change"],[[52,[33,11],[28,[37,10],[[33,11],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,11]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change","default"],[[52,[28,[37,12],[[33,13],[27]],null],[28,[37,10],[[33,13],","],null],[33,14]],[28,[37,6],[[30,0],[28,[37,7],[[33,13]],null]],[["value"],["target.selectedItems"]]],[33,14]]]]]]],[30,1,["model","item","MeshServiceInstances"]],[30,1,["model","item","ProxyServiceInstances"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,15],[[30,4,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,16],null,[["@sources","@search","@onsearch","@searchproperties","@sort","@filter"],[[28,[37,17],[[28,[37,18],[[30,4]],null],"ExternalSources"],null],[99,19,["@search"]],[28,[37,6],[[30,0],[28,[37,7],[[33,19]],null]],[["value"],["target.value"]]],[99,14,["@searchproperties"]],[30,2],[30,3]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,20],null,[["@type","@sort","@filters","@search","@items"],["service-instance",[30,2,["value"]],[30,3],[99,19,["@search"]],[30,4]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,21],null,[["@node","@routeName","@items","@proxies"],[[30,1,["model","item"]],"dc.services.show",[30,6,["items"]],[30,5]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,22],null,null,[["default"],[[[[1,"\\n "],[8,[39,23],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,24],["routes.dc.nodes.show.services.empty"],[["items","htmlSafe"],[[30,4,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "],[13],[1,"\\n"]],[2,3,4,5]]]],[1]]]]]],["route","sort","filters","items","proxies","collection"],false,["route","routeName","let","hash","or","sortBy","action","mut","if","status","split","source","not-eq","searchproperty","searchProperties","gt","consul/service-instance/search-bar","get","collection","search","data-collection","consul/service-instance/list","empty-state","block-slot","t"]]',moduleName:"consul-ui/templates/dc/nodes/show/services.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/nodes/show/sessions",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"sY17bdHd",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/sessions/for-node/${node}",[28,[37,4],null,[["partition","nspace","dc","node"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n "],[8,[39,8],null,[["@sink","@type","@label","@ondelete"],[[28,[37,3],["/${partition}/${dc}/${nspace}/session/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"session","Lock Session",[99,9,["@ondelete"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,10],[[4,[38,11],null,[["after"],[[28,[37,12],[[30,0],[30,5]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[5]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,10],[[4,[38,11],null,[["after"],[[28,[37,12],[[30,0],[30,6]],null]]]]],[["@type","@error"],["remove",[30,7]]],null],[1,"\\n "]],[6,7]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n "],[8,[39,13],null,[["@type","@items"],["session",[30,3]]],[["default"],[[[[1,"\\n\\n "],[8,[30,8,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,14],null,[["@items","@ondelete"],[[30,8,["items"]],[30,4,["delete"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,8,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,15],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,16],["routes.dc.nodes.show.sessions.empty.header"],[["items"],[[30,3,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,16],["routes.dc.nodes.show.sessions.empty.body"],[["canUseACLs","htmlSafe"],[[28,[37,17],["use acls"],null],true]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,18],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on Lock Sessions",[29,[[28,[37,19],["CONSUL_DOCS_URL"],null],"/internals/sessions.html"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,18],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,19],["CONSUL_DOCS_LEARN_URL"],null],"/tutorials/consul/distributed-semaphore"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "]],[8]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n "],[13],[1,"\\n"]],[3]]],[1," "]],[]]]]],[1,"\\n"]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","api","items","writer","after","after","error","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","data-writer","refresh-route","consul/lock-session/notifications","notification","action","data-collection","consul/lock-session/list","empty-state","t","can","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/nodes/show/sessions.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/nspaces/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"kT+yvkgU",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/namespace/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","name"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,2,["data"]],[30,2,["data","isNew"]]],[[[1," "],[8,[39,9],null,null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,10],["dc.nspaces"],null]],[12],[1,"All Namespaces"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[52,[30,7],"New Namespace",[28,[37,12],["Edit ",[30,6,["Name"]]],null]]]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@item","@dc","@nspace","@partition","@onsubmit"],[[30,6],[30,1,["params","dc"]],[30,1,["params","nspace"]],[30,1,["params","partition"]],[28,[37,14],["dc.nspaces.index"],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5,6,7]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","dc","partition","nspace","item","create"],false,["route","routeName","data-loader","uri","hash","or","block-slot","app-error","let","app-view","href-to","if","concat","consul/nspace/form","transition-to"]]',moduleName:"consul-ui/templates/dc/nspaces/edit.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/nspaces/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"sVU/Q7Zh",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/namespaces",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Name:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["searchproperty"],[[28,[37,4],null,[["value","change","default"],[[52,[28,[37,13],[[33,14],[27]],null],[28,[37,15],[[33,14],","],null],[33,16]],[28,[37,10],[[30,0],[28,[37,11],[[33,14]],null]],[["value"],["target.selectedItems"]]],[33,16]]]]]]],[30,2,["data"]]],[[[1,"\\n "],[8,[39,17],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Namespaces"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,18],["create nspaces"],null],[[[1," "],[8,[39,19],null,[["@text","@route"],["Create","dc.nspaces.create"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,20],[[30,5,["length"]],0],null],[[[1," "],[8,[39,21],null,[["@search","@onsearch","@sort","@filter"],[[99,22,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,22]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,23],null,[["@sink","@type","@label","@ondelete"],[[28,[37,3],["/${partition}/${dc}/${nspace}/nspace/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"nspace","Namespace",[99,24,["@ondelete"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,25],[[4,[38,26],null,[["after"],[[28,[37,10],[[30,0],[30,7]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[7]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@type","@sort","@filters","@search","@items"],["nspace",[30,3,["value"]],[30,4],[99,22,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,8,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@items","@ondelete"],[[30,8,["items"]],[30,6,["delete"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,8,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,30],["routes.dc.namespaces.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[28,[35,30],["routes.dc.namespaces.index.empty.body"],[["items","canUseACLs"],[[30,5,["length"]],[28,[37,18],["use acls"],null]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,31],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on namespaces",[29,[[28,[37,32],["CONSUL_DOCS_URL"],null],"/commands/namespace"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,31],null,[["@text","@href","@icon","@iconPosition","@size"],["Read the guide",[29,[[28,[37,32],["CONSUL_DOCS_LEARN_URL"],null],"/consul/namespaces/secure-namespaces"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","sort","filters","items","writer","after","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","not-eq","searchproperty","split","searchProperties","app-view","can","hds/button","gt","consul/nspace/search-bar","search","data-writer","refresh-route","consul/nspace/notifications","notification","data-collection","consul/nspace/list","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/nspaces/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/partitions/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"4dMfLoFT",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/partition/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","name"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,2,["data"]]],[[[1," "],[8,[39,9],null,null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,10],["dc.partitions"],null]],[12],[1,"All Admin Partitions"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[52,[28,[37,12],["new partition"],[["item"],[[30,6]]]],"New Partition",[28,[37,13],["Edit ",[30,6,["Name"]]],null]]]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n "],[8,[39,14],null,[["@item","@dc","@nspace","@partition","@onsubmit"],[[30,6],[30,1,["params","dc"]],[30,1,["params","nspace"]],[30,1,["params","partition"]],[28,[37,15],["dc.partitions.index"],null]]],null],[1,"\\n\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5,6]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","dc","partition","nspace","item"],false,["route","routeName","data-loader","uri","hash","or","block-slot","app-error","let","app-view","href-to","if","is","concat","consul/partition/form","transition-to"]]',moduleName:"consul-ui/templates/dc/partitions/edit.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/partitions/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"h9pu8svr",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/partitions",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Name:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["searchproperty"],[[28,[37,4],null,[["value","change","default"],[[52,[28,[37,13],[[33,14],[27]],null],[28,[37,15],[[33,14],","],null],[33,16]],[28,[37,10],[[30,0],[28,[37,11],[[33,14]],null]],[["value"],["target.selectedItems"]]],[33,16]]]]]]],[30,2,["data"]]],[[[1,"\\n "],[8,[39,17],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Admin Partitions"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,18],["create partitions"],null],[[[1," "],[8,[39,19],null,[["@text","@route"],["Create","dc.partitions.create"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,20],[[30,5,["length"]],0],null],[[[1," "],[8,[39,21],null,[["@search","@onsearch","@sort","@filter"],[[99,22,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,22]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,23],null,[["@sink","@type","@label","@ondelete"],[[28,[37,3],["/${partition}/${dc}/${nspace}/partition/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"partition","Partition",[99,24,["@ondelete"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,25],[[4,[38,26],null,[["after"],[[28,[37,10],[[30,0],[30,7]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[7]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@type","@sort","@filters","@search","@items"],["nspace",[30,3,["value"]],[30,4],[99,22,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,8,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@items","@ondelete"],[[30,8,["items"]],[30,6,["delete"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,8,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,30],["routes.dc.partitions.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[28,[35,30],["routes.dc.partitions.index.empty.body"],[["items","canUseACLs"],[[30,5,["length"]],[28,[37,18],["use acls"],null]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"docs-link"],[12],[1,"\\n "],[8,[39,10],null,[["@href","@external"],[[29,[[28,[37,31],["CONSUL_DOCS_URL"],null],"/enterprise/admin-partitions"]],true]],[["default"],[[[[1,"\\n Documentation on Admin Partitions\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","sort","filters","items","writer","after","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","not-eq","searchproperty","split","searchProperties","app-view","can","hds/button","gt","consul/partition/search-bar","search","data-writer","refresh-route","consul/partition/notifications","notification","data-collection","consul/partition/list","empty-state","t","env"]]',moduleName:"consul-ui/templates/dc/partitions/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/peers/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"mLlJfy/N",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/peers",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"State:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["state","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,15],[[33,16],[27]],null],[28,[37,14],[[33,16],","],null],[33,17]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]],[33,17]]]]]]],[30,2,["data"]]],[[[1," "],[8,[39,18],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Peers"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n\\n"],[41,[28,[37,19],[[30,5,["length"]],0],null],[[[1," "],[8,[39,20],null,[["@search","@onsearch","@sort","@filter"],[[99,21,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,21]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n\\n "],[8,[39,22],[[24,0,"peer-create-modal"]],[["@aria"],[[28,[37,4],null,[["label"],["Add peer connection"]]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,0],"create",[30,6]],null]],null]],[1,"\\n "],[10,"h2"],[12],[1,"\\n Add peer connection\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n\\n"],[41,[30,6,["opened"]],[[[1," "],[8,[39,25],null,[["@params"],[[30,1,["params"]]]],[["default"],[[[[1,"\\n "],[8,[30,7,["Form"]],null,[["@onchange","@onsubmit"],[[30,2,["invalidate"]],[28,[37,26],[[30,0,["redirectToPeerShow"]],[30,6,["close"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,0],"form",[30,8]],null]],null]],[1,"\\n "],[8,[30,8,["Fieldsets"]],null,null,null],[1,"\\n "]],[8]]]]],[1,"\\n "]],[7]]]]],[1,"\\n"]],[]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[30,0,["form","Actions"]],null,[["@onclose"],[[30,0,["create","close"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "],[8,[39,27],[[4,[38,28],["click",[28,[37,29],[[30,0,["create","open"]]],null]],null]],[["@color","@text"],["primary","Add peer connection"]],null],[1,"\\n\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n "],[8,[39,30],null,[["@sink","@type","@label"],[[28,[37,3],["/${partition}/${dc}/${nspace}/peer/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"peer","Peer"]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,31],[[4,[38,32],null,[["after"],[[28,[37,10],[[30,0],[30,10]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[10]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n "],[8,[39,22],null,[["@aria","@onclose"],[[28,[37,4],null,[["label"],["Regenerate token"]]],[28,[37,24],[[30,0],"item",[27]],null]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,0],"regenerate",[30,11]],null]],null]],[1,"\\n "],[10,"h2"],[12],[1,"\\n Regenerate token\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n"],[41,[30,0,["item"]],[[[1," "],[8,[39,33],null,[["@item","@onchange","@regenerate"],[[30,0,["item"]],[30,2,["invalidate"]],true]],[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,0],"regenerateForm",[30,12]],null]],null]],[1,"\\n "],[8,[30,12,["Fieldsets"]],null,null,null],[1,"\\n "]],[12]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[30,0,["regenerateForm","Actions"]],null,[["@onclose"],[[30,0,["regenerate","close"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[11]]]]],[1,"\\n\\n "],[8,[39,34],null,[["@type","@sort","@filters","@search","@items"],["peer",[30,3,["value"]],[30,4],[99,21,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,13,["Collection"]],null,null,[["default"],[[[[1,"\\n\\n "],[8,[39,35],null,[["@items","@onedit","@ondelete"],[[30,13,["items"]],[28,[37,36],[[28,[37,24],[[30,0],"item"],null],[30,0,["regenerate","open"]]],null],[30,9,["delete"]]]],null],[1,"\\n\\n "]],[]]]]],[1,"\\n "],[8,[30,13,["Empty"]],null,null,[["default"],[[[[1,"\\n"],[1," "],[8,[39,37],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,38],["routes.dc.peers.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[28,[35,38],["routes.dc.peers.index.empty.body"],[["items","canUsePartitions","canUseACLs","htmlSafe"],[[30,5,["length"]],[28,[37,39],["use partitions"],null],[28,[37,39],["use acls"],null],true]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n"],[1," "],[8,[39,40],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on Peers",[29,[[28,[37,41],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,40],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,41],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering/create-manage-peering"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[13]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","sort","filters","items","modal","form","form","writer","after","modal","form","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","state","split","not-eq","searchproperty","searchProperties","app-view","gt","consul/peer/search-bar","search","modal-dialog","did-insert","set","consul/peer/form","fn","hds/button","on","optional","data-writer","consul/peer/notifications","notification","consul/peer/form/generate","data-collection","consul/peer/list","queue","empty-state","t","can","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/peers/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/peers/show",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"Omb1G6/B",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/peer/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,2,["data"]]],[[[1," "],[8,[39,8],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,9],["dc.peers"],null]],[12],[1,"All Peers"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[30,6,["Name"]]]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@peering"],[[30,6]]],null],[1,"\\n "],[8,[39,11],null,[["@peer"],[[30,6]]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@items"],[[30,7,["data","tabs"]]]],null],[1,"\\n\\n "]],[7]]]]],[1,"\\n "],[8,[39,13],null,[["@name","@model"],[[99,1,["@name"]],[28,[37,14],[[28,[37,4],null,[["items","peer"],[[30,6,["PeerServerAddresses"]],[30,6]]]],[30,1,["model"]]],null]]],[["default"],[[[[1,"\\n "],[46,[28,[37,16],null,null],null,null,null],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5,6]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","dc","partition","nspace","item","peering","o"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","app-view","href-to","consul/peer/bento-box","peerings/provider","tab-nav","outlet","assign","component","-outlet"]]',moduleName:"consul-ui/templates/dc/peers/show.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/peers/show/addresses",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"An6ASLD6",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],[[30,1,["model","items","length"]],0],null],[[[1," "],[8,[39,4],null,[["@items"],[[30,1,["model","items"]]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,5],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,7],["routes.dc.peers.show.addresses.empty.header"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,7],["routes.dc.peers.show.addresses.empty.body"],[["htmlSafe"],[true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,8],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on Peers",[29,[[28,[37,9],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,8],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,9],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering/create-manage-peering"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]],[1]]]]]],["route"],false,["route","routeName","if","gt","consul/peer/address/list","empty-state","block-slot","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/peers/show/addresses.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/peers/show/exported",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"nW3ZeYXo",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/exported-services/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["model","peer","Name"]]]]]],null]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,6],[[30,1,["params","partition"]],[30,1,["model","user","token","Partition"]],"default"],null],[30,2,["data"]]],[[[1,"\\n "],[8,[39,7],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,7],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[41,[30,4,["length"]],[[[1," "],[10,0],[14,0,"search-bar"],[12],[1,"\\n "],[10,"form"],[14,0,"filter-bar"],[12],[1,"\\n "],[8,[39,10],[[24,0,"!w-80"]],[["@onsearch","@value","@placeholder"],[[28,[37,11],["target.value",[30,0,["updateSearch"]]],null],[30,0,["search"]],"Search"]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[8,[39,12],null,[["@items","@search","@searchProperties"],[[30,4],[30,0,["search"]],[28,[37,13],["Name"],null]]],[["default"],[[[[1,"\\n "],[8,[39,14],null,null,[["default"],[[[[1,"\\n"],[41,[30,6,["data","height"]],[[[1," "],[10,0],[15,5,[30,6,["data","fillRemainingHeightStyle"]]],[14,0,"overflow-y-scroll"],[12],[1,"\\n"],[41,[30,5,["data","items","length"]],[[[1," "],[8,[39,15],null,[["@tagName","@estimateHeight","@items"],["ul",[30,6,["data","height"]],[30,5,["data","items"]]]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"px-3 h-12 border-bottom-primary"],[12],[1,"\\n "],[10,3],[14,0,"hds-typography-display-300 hds-foreground-strong hds-font-weight-semibold h-full w-full flex items-center"],[15,6,[28,[37,16],["dc.services.show.index",[30,7,["Name"]]],[["params"],[[52,[28,[37,17],[[30,7,["Partition"]],[30,3]],null],[28,[37,4],null,[["partition","nspace","peer"],[[30,7,["Partition"]],[30,7,["Namespace"]],[30,7,["PeerName"]]]]],[28,[37,4],null,[["peer"],[[30,7,["PeerName"]]]]]]]]]],[12],[1,"\\n "],[1,[30,7,["Name"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[7,8]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,18],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,19],["routes.dc.peers.show.exported.empty.header"],[["name"],[[30,1,["model","peer","Name"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,19],["routes.dc.peers.show.exported.empty.body"],[["items","name","htmlSafe"],[[30,4,["length"]],[30,1,["model","peer","Name"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,20],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on Peers",[29,[[28,[37,21],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,20],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,21],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering/create-manage-peering"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[]],null],[1," "]],[6]]]]],[1,"\\n\\n "]],[5]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4]]],[1," "]],[2]]]]],[1,"\\n\\n"]],[1]]]]]],["route","api","partition","items","search","p","service","index"],false,["route","routeName","data-loader","uri","hash","let","or","block-slot","app-error","if","freetext-filter","pick","providers/search","array","providers/dimension","vertical-collection","href-to","not-eq","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/peers/show/exported.hbs",isStrictMode:!1}) -e.default=n})) -define("consul-ui/templates/dc/peers/show/imported",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"LzFp9Hrp",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/services/${peer}/${peerId}",[28,[37,4],null,[["partition","nspace","dc","peer","peerId"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["model","peer","Name"]],[30,1,["model","peer","id"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Status:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["status","kind","source","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change"],[[52,[33,15],[28,[37,14],[[33,15],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,15]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change"],[[52,[33,16],[28,[37,14],[[33,16],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,17],[[33,18],[27]],null],[28,[37,14],[[33,18],","],null],[30,0,["searchProperties"]]],[28,[37,10],[[30,0],[28,[37,11],[[33,18]],null]],[["value"],["target.selectedItems"]]],[30,0,["searchProperties"]]]]]]]],[28,[37,19],["Kind","connect-proxy",[30,2,["data"]]],null],[28,[37,8],[[30,1,["params","partition"]],[30,1,["model","user","token","Partition"]],"default"],null],[28,[37,8],[[30,1,["params","nspace"]],[30,1,["model","user","token","Namespace"]],"default"],null]],[[[1,"\\n"],[41,[28,[37,20],[[30,5,["length"]],0],null],[[[44,[[28,[37,21],[[30,5]],null]],[[[1," "],[8,[39,22],null,[["@sources","@partitions","@partition","@search","@onsearch","@sort","@filter","@peer"],[[28,[37,23],[[30,8],"ExternalSources"],null],[28,[37,23],[[30,8],"Partitions"],null],[30,6],[99,24,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,24]],null]],[["value"],["target.value"]]],[30,3],[30,4],[30,1,["model","peer"]]]],null],[1,"\\n"]],[8]]]],[]],null],[1," "],[8,[39,25],null,[["@type","@sort","@filters","@search","@items"],["service",[30,3,["value"]],[30,4],[99,24,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,9,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@items","@partition","@isPeerDetail"],[[30,9,["items"]],[30,6],true]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,9,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,28],["routes.dc.peers.show.imported.empty.header"],[["name"],[[30,1,["model","peer","Name"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,28],["routes.dc.peers.show.imported.empty.body"],[["items","name","htmlSafe"],[[30,5,["length"]],[30,1,["model","peer","Name"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n"],[1," "],[8,[39,29],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on Peers",[29,[[28,[37,30],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,29],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,30],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering/create-manage-peering"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n"]],[3,4,5,6,7]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","api","sort","filters","items","partition","nspace","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","status","split","kind","source","not-eq","searchproperty","reject-by","gt","collection","consul/service/search-bar","get","search","data-collection","consul/service/list","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/peers/show/imported.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/peers/show/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"gn6gS8WU",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[30,0,["transitionToImported"]]],null]],[1,"\\n"]],[1]]]]]],["route"],false,["route","routeName","did-insert"]]',moduleName:"consul-ui/templates/dc/peers/show/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/routing-config",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"wffPe0l/",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/discovery-chain/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]]],[[[8,[39,8],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,9],["dc.services"],null]],[12],[1,"All Services"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[30,3,["Chain","ServiceName"]]]],null],[1,"\\n "],[13],[1,"\\n "],[8,[39,10],null,[["@source","@withInfo"],[[28,[37,11],["routes.dc.routing-config.source"],null],true]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"container"],[12],[1,"\\n "],[8,[39,12],null,[["@chain"],[[30,3,["Chain"]]]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]]],[1,"\\n"]],[3]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","item"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","app-view","href-to","consul/source","t","consul/discovery-chain"]]',moduleName:"consul-ui/templates/dc/routing-config.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"ixFFtisJ",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/services",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Status:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["status","kind","source","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change"],[[52,[33,15],[28,[37,14],[[33,15],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,15]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change"],[[52,[33,16],[28,[37,14],[[33,16],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,17],[[33,18],[27]],null],[28,[37,14],[[33,18],","],null],[30,0,["_searchProperties"]]],[28,[37,10],[[30,0],[28,[37,11],[[33,18]],null]],[["value"],["target.selectedItems"]]],[30,0,["_searchProperties"]]]]]]]],[28,[37,19],["Kind","connect-proxy",[30,2,["data"]]],null],[28,[37,8],[[30,1,["params","partition"]],[30,1,["model","user","token","Partition"]],"default"],null],[28,[37,8],[[30,1,["params","nspace"]],[30,1,["model","user","token","Namespace"]],"default"],null]],[[[1,"\\n "],[8,[39,20],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Services"]],null],[1," "],[10,"em"],[12],[1,[28,[35,21],[[30,5,["length"]]],null]],[1," total"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"label"],[14,"for","toolbar-toggle"],[12],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,22],[[30,5,["length"]],0],null],[[[44,[[28,[37,23],[[30,5]],null]],[[[1," "],[8,[39,24],null,[["@sources","@partitions","@partition","@search","@onsearch","@sort","@filter"],[[28,[37,25],[[30,8],"ExternalSources"],null],[28,[37,25],[[30,8],"Partitions"],null],[30,6],[99,26,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,26]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[8]]]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@type","@sort","@filters","@search","@items"],["service",[30,3,["value"]],[30,4],[99,26,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,9,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@items","@partition"],[[30,9,["items"]],[30,6]]],[["default"],[[[[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,9,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,30],["routes.dc.services.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,30],["routes.dc.services.index.empty.body"],[["items","canUseACLs","htmlSafe"],[[30,5,["length"]],[28,[37,31],["use acls"],null],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,32],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on Services",[29,[[28,[37,33],["CONSUL_DOCS_URL"],null],"/commands/services"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,32],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,33],["CONSUL_DOCS_LEARN_URL"],null],"/consul/getting-started/services"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n\\n"]],[3,4,5,6,7]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","api","sort","filters","items","partition","nspace","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","status","split","kind","source","not-eq","searchproperty","reject-by","app-view","format-number","gt","collection","consul/service/search-bar","get","search","data-collection","consul/service/list","empty-state","t","can","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/services/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/instance",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"qYqPny+P",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/service-instance/${id}/${node}/${name}/${peer}",[28,[37,4],null,[["partition","nspace","dc","id","node","name","peer"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","id"]],[30,1,["params","node"]],[30,1,["params","name"]],[30,1,["params","peer"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,8],[[30,2,["error","status"]],"404"],null],[[[1," "],[8,[39,9],[[4,[38,10],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,4,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,4,["Description"]],null,null,[["default"],[[[[1,"\\n This service has been deregistered and no longer exists in the catalog.\\n "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[]],[[[41,[28,[37,8],[[30,2,["error","status"]],"403"],null],[[[1," "],[8,[39,9],[[4,[38,10],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"\\n You no longer have access to this service.\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,9],[[4,[38,10],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"\\n An error was returned whilst loading this data, refresh to try again.\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]],[]]],[1," "]],[3]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]]],[[[41,[30,7,["IsOrigin"]],[[[1," "],[8,[39,12],null,[["@src","@onchange"],[[28,[37,3],["/${partition}/${nspace}/${dc}/proxy-instance/${id}/${node}/${name}",[28,[37,4],null,[["partition","nspace","dc","id","node","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","id"]],[30,1,["params","node"]],[30,1,["params","name"]]]]]],null],[28,[37,13],[[30,0],[28,[37,14],[[33,15]],null]],[["value"],["data"]]]]],[["default"],[[[[1,"\\n"],[41,[30,8,["data","ServiceID"]],[[[1," "],[8,[39,12],null,[["@src","@onchange"],[[28,[37,3],["/${partition}/${nspace}/${dc}/service-instance/${id}/${node}/${name}/${peer}",[28,[37,4],null,[["partition","nspace","dc","id","node","name","peer"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,8,["data","ServiceID"]],[30,8,["data","NodeName"]],[30,8,["data","ServiceName"]],[30,1,["params","peer"]]]]]],null],[28,[37,13],[[30,0],[28,[37,14],[[33,16]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[]],null],[1," "]],[8]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,17],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,18],["dc.services"],[["params"],[[28,[37,4],null,[["peer"],[[27]]]]]]]],[12],[1,"All Services"],[13],[13],[1,"\\n "],[10,"li"],[12],[11,3],[16,6,[28,[37,18],["dc.services.show"],null]],[4,[38,19],[[28,[37,20],["Service (",[30,7,["Service","Service"]],")"],null]],null],[12],[1,"\\n Service ("],[1,[30,7,["Service","Service"]]],[1,")\\n "],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[30,7,["Service","ID"]]]],null],[1,"\\n "],[13],[1,"\\n "],[8,[39,21],null,[["@item","@withInfo"],[[30,7],true]],null],[1,"\\n "],[8,[39,22],null,[["@item","@withInfo"],[[30,7],true]],null],[1,"\\n"],[41,[28,[37,8],[[33,15,["ServiceProxy","Mode"]],"transparent"],null],[[[1," "],[8,[39,23],null,null,null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["nav"]],[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Service Name"],[13],[1,"\\n "],[10,"dd"],[12],[10,3],[15,6,[29,[[28,[37,18],["dc.services.show",[30,7,["Service","Service"]]],null]]]],[12],[1,[30,7,["Service","Service"]]],[13],[13],[1,"\\n "],[13],[1,"\\n"],[41,[51,[30,7,["Node","Meta","synthetic-node"]]],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Node Name"],[13],[1,"\\n "],[10,"dd"],[12],[10,3],[15,6,[29,[[28,[37,18],["dc.nodes.show",[30,7,["Node","Node"]]],null]]]],[12],[1,[30,7,["Node","Node"]]],[13],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,7,["Service","PeerName"]],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Peer Name"],[13],[1,"\\n "],[10,"dd"],[12],[10,3],[15,6,[28,[37,18],["dc.peers.show",[30,7,["Service","PeerName"]]],[["params"],[[28,[37,4],null,[["peer"],[[27]]]]]]]],[12],[1,[30,7,["Service","PeerName"]]],[13],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,25],[[30,7,["Service","Address"]],[30,7,["Node","Address"]]],null]],[[[1," "],[8,[39,26],null,[["@value","@name"],[[30,9],"Address"]],[["default"],[[[[1,[30,9]]],[]]]]],[1,"\\n"]],[9]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@items"],[[28,[37,28],[[28,[37,29],[[28,[37,4],null,[["label","href","selected"],["Health Checks",[28,[37,18],["dc.services.instance.healthchecks"],null],[28,[37,30],["dc.services.instance.healthchecks"],null]]]],[52,[28,[37,8],[[30,7,["Service","Kind"]],"mesh-gateway"],null],[28,[37,4],null,[["label","href","selected"],["Addresses",[28,[37,18],["dc.services.instance.addresses"],null],[28,[37,30],["dc.services.instance.addresses"],null]]]]],[52,[33,16],[28,[37,4],null,[["label","href","selected"],["Upstreams",[28,[37,18],["dc.services.instance.upstreams"],null],[28,[37,30],["dc.services.instance.upstreams"],null]]]]],[52,[33,16],[28,[37,4],null,[["label","href","selected"],["Exposed Paths",[28,[37,18],["dc.services.instance.exposedpaths"],null],[28,[37,30],["dc.services.instance.exposedpaths"],null]]]]],[28,[37,4],null,[["label","href","selected"],["Tags & Meta",[28,[37,18],["dc.services.instance.metadata"],null],[28,[37,30],["dc.services.instance.metadata"],null]]]]],null]],null]]],null],[1,"\\n "],[8,[39,31],null,[["@name","@model"],[[99,1,["@name"]],[28,[37,32],[[28,[37,4],null,[["proxy","meta","item"],[[33,16],[33,15],[30,7]]]],[30,1,["model"]]],null]]],[["default"],[[[[1,"\\n "],[46,[28,[37,34],null,null],null,null,null],[1,"\\n "]],[10]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[7]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","after","T","T","T","item","meta","address","o"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","if","eq","hds/toast","notification","let","data-source","action","mut","meta","proxy","app-view","href-to","tooltip","concat","consul/external-source","consul/kind","consul/transparent-proxy","unless","or","copy-button","tab-nav","compact","array","is-href","outlet","assign","component","-outlet"]]',moduleName:"consul-ui/templates/dc/services/instance.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/instance/addresses",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"OEv9mr5t",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],[[30,1,["model","item","Service","TaggedAddresses"]]],null]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,5],[[30,2,["length"]],0],null],[[[1," "],[8,[39,6],[[24,0,"consul-tagged-addresses"]],[["@items"],[[30,2]]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[12],[1,"Tag"],[13],[1,"\\n "],[10,"th"],[12],[1,"Address"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["row"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,8],[1,[30,3]],null]],[[[41,[30,5],[[[1," "],[10,"td"],[12],[1,"\\n "],[1,[28,[35,8],[0,[30,3]],null]],[41,[28,[37,9],[[28,[37,10],[[30,5,["Address"]],[33,11,["Address"]]],null],[28,[37,10],[[30,5,["Port"]],[33,11,["Port"]]],null]],null],[[[1," "],[10,"em"],[12],[1,"(default)"],[13]],[]],null],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[12],[1,"\\n "],[1,[30,5,["Address"]]],[1,":"],[1,[30,5,["Port"]]],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[5]]],[1," "]],[]]]]],[1,"\\n "]],[3,4]]]]],[1,"\\n"]],[]],[[[1," "],[10,2],[12],[1,"\\n There are no additional addresses.\\n "],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[2]]]],[1]]]]],[1,"\\n"]],["route","items","taggedAddress","index","address"],false,["route","routeName","let","entries","if","gt","tabular-collection","block-slot","object-at","and","eq","item"]]',moduleName:"consul-ui/templates/dc/services/instance/addresses.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/instance/exposedpaths",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"bKwLyBQ8",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[30,1,["model","proxy"]],[30,1,["model","meta"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,4],[[30,3,["ServiceProxy","Expose","Paths","length"]],0],null],[[[1," "],[1,[28,[35,5],["routes.dc.services.instance.exposedpaths.intro"],[["htmlSafe"],[true]]]],[1,"\\n "],[8,[39,6],null,[["@items","@address"],[[30,3,["ServiceProxy","Expose","Paths"]],[28,[37,7],[[30,2,["Service","Address"]],[30,2,["Node","Address"]]],null]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,8],null,null,[["default"],[[[[1,"\\n "],[8,[39,9],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,5],["routes.dc.services.instance.exposedpaths.empty.body"],[["htmlSafe"],[true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[2,3]]]],[1]]]]]],["route","item","proxy"],false,["route","routeName","let","if","gt","t","consul/exposed-path/list","or","empty-state","block-slot"]]',moduleName:"consul-ui/templates/dc/services/instance/exposedpaths.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/instance/healthchecks",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"c8iqBcKE",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],[[28,[37,4],[[30,0],"syntheticNodeSearchPropertyFilter",[30,1,["model","item"]]],null],[33,5]],null]],[[[44,[[28,[37,6],null,[["value","change"],[[28,[37,7],[[33,8],"Status:asc"],null],[28,[37,4],[[30,0],[28,[37,9],[[33,8]],null]],[["value"],["target.selected"]]]]]],[28,[37,6],null,[["status","check","searchproperty"],[[28,[37,6],null,[["value","change"],[[52,[33,11],[28,[37,12],[[33,11],","],null],[27]],[28,[37,4],[[30,0],[28,[37,9],[[33,11]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,6],null,[["value","change"],[[52,[33,13],[28,[37,12],[[33,13],","],null],[27]],[28,[37,4],[[30,0],[28,[37,9],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,6],null,[["value","change","default"],[[52,[28,[37,14],[[33,15],[27]],null],[28,[37,12],[[33,15],","],null],[30,2]],[28,[37,4],[[30,0],[28,[37,9],[[33,15]],null]],[["value"],["target.selectedItems"]]],[30,2]]]]]]],[28,[37,3],[[28,[37,4],[[30,0],"syntheticNodeHealthCheckFilter",[30,1,["model","item"]]],null],[28,[37,16],[[28,[37,17],[[30,1,["model","item","Checks"]],[30,1,["model","proxy","Checks"]]],null],[30,1,["model","proxy","ServiceProxy","Expose","Checks"]]],null]],null]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n\\n"],[41,[28,[37,18],[[30,5,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,19],null,[["@search","@onsearch","@sort","@filter"],[[99,20,["@search"]],[28,[37,4],[[30,0],[28,[37,9],[[33,20]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[44,[[28,[37,21],["Type","serf",[30,5]],null]],[[[41,[28,[37,22],[[30,6],[28,[37,23],[[30,6,["Status"]],"critical"],null]],null],[[[1," "],[8,[39,24],[[24,0,"mb-3 mt-2"]],[["@type","@color"],["inline","warning"]],[["default"],[[[[1,"\\n "],[8,[30,7,["Title"]],null,null,[["default"],[[[[1,[28,[35,25],["routes.dc.services.instance.healthchecks.critical-serf-notice.header"],null]]],[]]]]],[1,"\\n "],[8,[30,7,["Description"]],null,null,[["default"],[[[[1,[28,[35,25],["routes.dc.services.instance.healthchecks.critical-serf-notice.body"],[["htmlSafe"],[true]]]]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n"]],[]],null]],[6]]],[1," "],[8,[39,26],null,[["@type","@sort","@filters","@search","@items"],["health-check",[30,3,["value"]],[30,4],[99,20,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,8,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@items"],[[30,8,["items"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,8,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,null,[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,25],["routes.dc.services.instance.healthchecks.empty"],[["items","htmlSafe"],[[30,5,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n\\n "],[13],[1,"\\n"]],[3,4,5]]]],[2]]]],[1]]]]],[1,"\\n"]],["route","filteredSearchProperties","sort","filters","items","serf","A","collection"],false,["route","routeName","let","filter","action","searchProperties","hash","or","sortBy","mut","if","status","split","check","not-eq","searchproperty","merge-checks","array","gt","consul/health-check/search-bar","search","find-by","and","eq","hds/alert","t","data-collection","consul/health-check/list","empty-state","block-slot"]]',moduleName:"consul-ui/templates/dc/services/instance/healthchecks.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/instance/metadata",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"TS1cbRDj",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[30,1,["model","item"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n "],[10,"section"],[14,0,"tags"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Tags"],[13],[1,"\\n"],[41,[28,[37,4],[[30,2,["Tags","length"]],0],null],[[[1," "],[8,[39,5],null,[["@item"],[[30,2]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,6],null,null,[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n There are no tags.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[10,"section"],[14,0,"metadata"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Meta"],[13],[1,"\\n"],[41,[30,2,["Meta"]],[[[1," "],[8,[39,8],null,[["@items"],[[28,[37,9],[[30,2,["Meta"]]],null]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,6],null,null,[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n This instance has no metadata.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[2]]]],[1]]]]],[1,"\\n"]],["route","item"],false,["route","routeName","let","if","gt","tag-list","empty-state","block-slot","consul/metadata/list","entries"]]',moduleName:"consul-ui/templates/dc/services/instance/metadata.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/instance/upstreams",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"2fQZNDmw",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[44,[[28,[37,3],null,[["value","change"],[[28,[37,4],[[33,5],"DestinationName:asc"],null],[28,[37,6],[[30,0],[28,[37,7],[[33,5]],null]],[["value"],["target.selected"]]]]]],[28,[37,3],null,[["searchproperty"],[[28,[37,3],null,[["value","change","default"],[[52,[28,[37,9],[[33,10],[27]],null],[28,[37,11],[[33,10],","],null],[33,12]],[28,[37,6],[[30,0],[28,[37,7],[[33,10]],null]],[["value"],["target.selectedItems"]]],[33,12]]]]]]],[28,[37,4],[[30,1,["params","partition"]],[30,1,["model","user","token","Partition"]],"default"],null],[28,[37,4],[[30,1,["params","nspace"]],[30,1,["model","user","token","Namespace"]],"default"],null],[30,1,["params","dc"]],[30,1,["model","proxy"]],[30,1,["model","meta"]],[30,1,["model","proxy","Service","Proxy","Upstreams"]]],[[[41,[28,[37,13],[[30,9,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,14],null,[["@search","@onsearch","@searchproperties","@sort","@filter"],[[99,15,["@search"]],[28,[37,6],[[30,0],[28,[37,7],[[33,15]],null]],[["value"],["target.value"]]],[99,12,["@searchproperties"]],[30,2],[30,3]]],null],[1,"\\n"]],[]],null],[41,[28,[37,16],[[30,8,["ServiceProxy","Mode"]],"transparent"],null],[[[1," "],[8,[39,17],[[24,0,"mb-3 mt-2"]],[["@type","@color"],["inline","warning"]],[["default"],[[[[1,"\\n "],[8,[30,10,["Title"]],null,null,[["default"],[[[[1,[28,[35,18],["routes.dc.services.instance.upstreams.tproxy-mode.header"],null]]],[]]]]],[1,"\\n "],[8,[30,10,["Description"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,18],["routes.dc.services.instance.upstreams.tproxy-mode.body"],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,10,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition","@size"],[[28,[37,18],["routes.dc.services.instance.upstreams.tproxy-mode.footer.text"],null],[29,[[28,[37,19],[[28,[37,20],["CONSUL_DOCS_URL"],null],[28,[37,18],["routes.dc.services.instance.upstreams.tproxy-mode.footer.link"],null]],null]]],"docs-link","trailing","small"]],null],[1,"\\n "]],[10]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,21],null,[["@type","@sort","@filters","@search","@items"],["upstream-instance",[30,2,["value"]],[30,3],[99,15,["@search"]],[30,9]]],[["default"],[[[[1,"\\n "],[8,[30,11,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,22],null,[["@items","@dc","@nspace","@partition"],[[30,11,["items"]],[30,6],[30,5],[30,4]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,11,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,23],null,null,[["default"],[[[[1,"\\n "],[8,[39,24],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,18],["routes.dc.services.instance.upstreams.empty"],[["items","htmlSafe"],[[30,9,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[11]]]]],[1,"\\n"]],[2,3,4,5,6,7,8,9]]],[1," "],[13],[1,"\\n"]],[1]]]]]],["route","sort","filters","partition","nspace","dc","proxy","meta","items","A","collection"],false,["route","routeName","let","hash","or","sortBy","action","mut","if","not-eq","searchproperty","split","searchProperties","gt","consul/upstream-instance/search-bar","search","eq","hds/alert","t","concat","env","data-collection","consul/upstream-instance/list","empty-state","block-slot"]]',moduleName:"consul-ui/templates/dc/services/instance/upstreams.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/show",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"ep8WMqyL",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/service-instances/for-service/${name}/${peer}",[28,[37,4],null,[["partition","nspace","dc","name","peer"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]],[30,1,["params","peer"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,8],[[30,2,["error","status"]],"404"],null],[[[1," "],[8,[39,9],[[4,[38,10],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,4,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,4,["Description"]],null,null,[["default"],[[[[1,"This service has been deregistered and no longer exists in the catalog."]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[]],[[[41,[28,[37,8],[[30,2,["error","status"]],"403"],null],[[[1," "],[8,[39,9],[[4,[38,10],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"You no longer have access to this service."]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,9],[[4,[38,10],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"An error was returned whilst loading this data, refresh to try again."]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]],[]]],[1," "]],[3]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]],[30,2,["data","firstObject"]],[30,1,["model","dc"]]],[[[1,"\\n"],[41,[30,8,["IsOrigin"]],[[[1," "],[8,[39,12],null,[["@src","@onchange"],[[28,[37,3],["/${partition}/${nspace}/${dc}/proxies/for-service/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null],[28,[37,13],[[30,0],[28,[37,14],[[33,15]],null]],[["value"],["data"]]]]],null],[1,"\\n"],[41,[28,[37,16],[[33,17]],null],[[[1," "],[8,[39,12],null,[["@src","@onchange"],[[28,[37,3],["/${partition}/${nspace}/${dc}/discovery-chain/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null],[28,[37,13],[[30,0],[28,[37,14],[[33,17]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[]],null],[1," "],[1,[28,[35,18],[[28,[37,19],[[30,0],"chain",[27]],null],[30,1,["params","dc"]]],null]],[1,"\\n"]],[]],null],[44,[[28,[37,4],null,[["topology","services","upstreams","instances","intentions","routing","tags"],[[28,[37,20],[[30,9,["MeshEnabled"]],[30,8,["IsMeshOrigin"]],[28,[37,21],[[28,[37,22],[[33,15,["length"]],0],null],[28,[37,8],[[30,8,["Service","Kind"]],"ingress-gateway"],null]],null],[28,[37,16],[[30,8,["Service","PeerName"]]],null]],null],[28,[37,20],[[28,[37,8],[[30,8,["Service","Kind"]],"terminating-gateway"],null],[28,[37,16],[[30,8,["Service","PeerName"]]],null]],null],[28,[37,20],[[28,[37,8],[[30,8,["Service","Kind"]],"ingress-gateway"],null],[28,[37,16],[[30,8,["Service","PeerName"]]],null]],null],true,[28,[37,20],[[28,[37,23],[[30,8,["Service","Kind"]],"terminating-gateway"],null],[28,[37,24],["read intention for service"],[["item"],[[30,8,["Service"]]]]],[28,[37,16],[[30,8,["Service","PeerName"]]],null]],null],[28,[37,20],[[30,9,["MeshEnabled"]],[30,8,["IsOrigin"]],[28,[37,16],[[30,8,["Service","PeerName"]]],null]],null],true]]]],[[[1," "],[8,[39,25],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["notification"]],[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@type","@status","@error"],[[30,12],[30,11],[30,14]]],null],[1,"\\n "]],[11,12,13,14]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,27],["dc.services"],[["params"],[[28,[37,4],null,[["peer"],[[27]]]]]]]],[12],[1,"All Services"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[30,8,["Service","Service"]]]],null],[1,"\\n "],[13],[1,"\\n "],[8,[39,28],null,[["@item","@withInfo"],[[30,8,["Service"]],true]],null],[1,"\\n "],[8,[39,29],null,[["@item","@withInfo"],[[30,8,["Service"]],true]],null],[1,"\\n "],[8,[39,30],null,[["@item"],[[30,8,["Service"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["nav"]],[["default"],[[[[1,"\\n"],[41,[28,[37,23],[[30,8,["Service","Kind"]],"mesh-gateway"],null],[[[1," "],[8,[39,31],null,[["@items"],[[28,[37,32],[[28,[37,33],[[52,[30,10,["topology"]],[28,[37,4],null,[["label","href","selected"],["Topology",[28,[37,27],["dc.services.show.topology"],null],[28,[37,34],["dc.services.show.topology"],null]]]],""],[52,[30,10,["services"]],[28,[37,4],null,[["label","href","selected"],["Linked Services",[28,[37,27],["dc.services.show.services"],null],[28,[37,34],["dc.services.show.services"],null]]]],""],[52,[30,10,["upstreams"]],[28,[37,4],null,[["label","href","selected"],["Upstreams",[28,[37,27],["dc.services.show.upstreams"],null],[28,[37,34],["dc.services.show.upstreams"],null]]]],""],[52,[30,10,["instances"]],[28,[37,4],null,[["label","href","selected"],["Instances",[28,[37,27],["dc.services.show.instances"],null],[28,[37,34],["dc.services.show.instances"],null]]]],""],[52,[30,10,["intentions"]],[28,[37,4],null,[["label","href","selected"],["Intentions",[28,[37,27],["dc.services.show.intentions"],null],[28,[37,34],["dc.services.show.intentions"],null]]]],""],[52,[30,10,["routing"]],[28,[37,4],null,[["label","href","selected"],["Routing",[28,[37,27],["dc.services.show.routing"],null],[28,[37,34],["dc.services.show.routing"],null]]]],""],[52,[30,10,["tags"]],[28,[37,4],null,[["label","href","selected"],["Tags",[28,[37,27],["dc.services.show.tags"],null],[28,[37,34],["dc.services.show.tags"],null]]]],""]],null]],null]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/ui-config",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n"],[41,[30,15,["data","dashboard_url_templates","service"]],[[[1," "],[8,[39,13],[[24,0,"external-dashboard"]],[["@href","@external"],[[28,[37,35],[[30,15,["data","dashboard_url_templates","service"]],[28,[37,4],null,[["Datacenter","Service"],[[30,9,["Name"]],[28,[37,4],null,[["Name","Namespace","Partition"],[[30,8,["Service","Service"]],[28,[37,21],[[30,8,["Service","Namespace"]],""],null],[28,[37,21],[[30,8,["Service","Partition"]],""],null]]]]]]]],null],true]],[["default"],[[[[1,"\\n Open dashboard\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[15]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[41,[28,[37,21],[[28,[37,16],[[30,8,["IsOrigin"]]],null],[33,17]],null],[[[1," "],[8,[39,36],null,[["@name","@model"],[[99,1,["@name"]],[28,[37,37],[[28,[37,4],null,[["items","proxies","item","tabs"],[[30,7],[33,15],[30,8],[30,10]]]],[30,1,["model"]]],null]]],[["default"],[[[[1,"\\n "],[46,[28,[37,39],null,null],null,null,null],[1,"\\n "]],[16]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[10]]]],[7,8,9]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","after","T","T","T","items","item","dc","tabs","status","type","item","error","config","o"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","if","eq","hds/toast","notification","let","data-source","action","mut","proxies","not","chain","did-insert","set","and","or","gt","not-eq","can","app-view","topology-metrics/notifications","href-to","consul/external-source","consul/kind","consul/peer/info","tab-nav","compact","array","is-href","render-template","outlet","assign","component","-outlet"]]',moduleName:"consul-ui/templates/dc/services/show.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/show/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"och8aDuk",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[41,[30,1,["model","tabs","topology"]],[[[1," "],[1,[28,[35,3],[[28,[37,4],["replaceWith","dc.services.show.topology"],null]],null]],[1,"\\n"]],[]],[[[41,[30,1,["model","tabs","upstreams"]],[[[1," "],[1,[28,[35,3],[[28,[37,4],["replaceWith","dc.services.show.upstreams"],null]],null]],[1,"\\n"]],[]],[[[41,[30,1,["model","tabs","services"]],[[[1," "],[1,[28,[35,3],[[28,[37,4],["replaceWith","dc.services.show.services"],null]],null]],[1,"\\n"]],[]],[[[1," "],[1,[28,[35,3],[[28,[37,4],["replaceWith","dc.services.show.instances"],null]],null]],[1,"\\n"]],[]]]],[]]]],[]]]],[1]]]]],[1,"\\n"]],["route"],false,["route","routeName","if","did-insert","route-action"]]',moduleName:"consul-ui/templates/dc/services/show/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/show/instances",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"QmKK5Mhb",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[44,[[28,[37,3],null,[["value","change"],[[28,[37,4],[[33,5],"Status:asc"],null],[28,[37,6],[[30,0],[28,[37,7],[[33,5]],null]],[["value"],["target.selected"]]]]]],[28,[37,3],null,[["status","source","searchproperty"],[[28,[37,3],null,[["value","change"],[[52,[33,9],[28,[37,10],[[33,9],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,9]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change"],[[52,[33,11],[28,[37,10],[[33,11],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,11]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change","default"],[[52,[28,[37,12],[[33,13],[27]],null],[28,[37,10],[[33,13],","],null],[33,14]],[28,[37,6],[[30,0],[28,[37,7],[[33,13]],null]],[["value"],["target.selectedItems"]]],[33,14]]]]]]],[30,1,["model","items"]],[30,1,["model","proxies","firstObject"]]],[[[41,[28,[37,15],[[30,4,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,16],null,[["@sources","@search","@onsearch","@sort","@filter"],[[28,[37,17],[[28,[37,18],[[30,4]],null],"ExternalSources"],null],[99,19,["@search"]],[28,[37,6],[[30,0],[28,[37,7],[[33,19]],null]],[["value"],["target.value"]]],[30,2],[30,3]]],null],[1,"\\n"]],[]],null],[41,[30,5,["ServiceName"]],[[[1," "],[8,[39,20],null,[["@src","@onchange"],[[28,[37,21],["/${partition}/${nspace}/${dc}/service-instances/for-service/${name}/${peer}",[28,[37,3],null,[["partition","nspace","dc","name","peer"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,5,["ServiceName"]],[30,1,["params","peer"]]]]]],null],[28,[37,6],[[30,0],[28,[37,7],[[33,22]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,23],null,[["@type","@sort","@filters","@search","@items"],["service-instance",[30,2,["value"]],[30,3],[99,19,["@search"]],[30,4]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,24],null,[["@routeName","@items","@proxies"],["dc.services.instance",[30,6,["items"]],[99,22,["@proxies"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,25],null,null,[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,27],["routes.dc.services.show.instances.empty"],[["items","htmlSafe"],[[30,4,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[2,3,4,5]]],[13],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","sort","filters","items","proxyMeta","collection"],false,["route","routeName","let","hash","or","sortBy","action","mut","if","status","split","source","not-eq","searchproperty","searchProperties","gt","consul/service-instance/search-bar","get","collection","search","data-source","uri","proxies","data-collection","consul/service-instance/list","empty-state","block-slot","t"]]',moduleName:"consul-ui/templates/dc/services/show/instances.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/show/intentions",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"sF5zClCb",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name","@model"],[[99,1,["@name"]],[30,1,["model"]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,4],null,null],null,null,null],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","o"],false,["route","routeName","outlet","component","-outlet"]]',moduleName:"consul-ui/templates/dc/services/show/intentions.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/show/intentions/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"FjErs42E",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],[[28,[37,4],["write intention for service"],[["item"],[[33,5,["Service"]]]]]],null]],[[[1," "],[8,[39,6],null,[["@src"],[[28,[37,7],["/${partition}/${nspace}/${dc}/intention/${id}",[28,[37,8],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,9],[[30,1,["params","intention_id"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,10],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,11],null,[["@error","@login"],[[30,3,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,10],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,3,["data"]]],[[[1," "],[8,[39,12],null,[["@readonly","@item","@dc","@nspace","@partition","@autofill","@onsubmit"],[[30,2],[30,4],[30,1,["model","dc"]],[30,1,["params","nspace"]],[30,1,["params","partition"]],[28,[37,8],null,[["DestinationName"],[[30,1,["params","name"]]]]],[28,[37,13],["dc.services.show.intentions.index"],null]]],null],[1,"\\n"]],[4]]],[1," "]],[]]]]],[1,"\\n"]],[3]]]]],[1,"\\n"]],[2]]]],[1]]]]],[1,"\\n"]],["route","readOnly","loader","item"],false,["route","routeName","let","not","can","item","data-loader","uri","hash","or","block-slot","error-state","consul/intention/form","transition-to"]]',moduleName:"consul-ui/templates/dc/services/show/intentions/edit.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/show/intentions/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"R5ukfGXO",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/intentions/for-service/${slug}",[28,[37,4],null,[["partition","nspace","dc","slug"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error"],[[30,2,["error"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Action:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["access","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,15],[[33,16],[27]],null],[28,[37,14],[[33,16],","],null],[33,17]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]],[33,17]]]]]]],[30,2,["data"]],[30,1,["model","item"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,18],["create intention for service"],[["item"],[[30,6,["Service"]]]]],[[[1," "],[8,[39,19],null,[["@target"],["app-view-actions"]],[["default"],[[[[1,"\\n "],[8,[39,20],null,[["@text","@route"],["Create","dc.services.show.intentions.create"]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[41,[28,[37,21],[[30,5,["length"]],0],null],[[[1," "],[8,[39,22],null,[["@search","@onsearch","@sort","@filter"],[[99,23,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,23]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,24],null,[["@sink","@type","@ondelete"],[[28,[37,3],["/${partition}/${dc}/${nspace}/intention/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"intention",[99,25,["@ondelete"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@type","@sort","@filters","@search","@items"],["intention",[30,3,["value"]],[30,4],[99,23,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,8,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@items","@check","@delete"],[[30,8,["items"]],[99,23,["@check"]],[30,7,["delete"]]]],[["default"],[[[[1,"\\n "],[8,[30,9,["CustomResourceNotice"]],null,null,null],[1,"\\n "],[8,[30,9,["CheckNotice"]],null,null,null],[1,"\\n "],[8,[30,9,["Table"]],null,[["@routeName"],["dc.services.show.intentions.edit"]],null],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,8,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,29],["routes.dc.services.show.intentions.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,29],["routes.dc.services.show.intentions.index.empty.body"],[["items","canUseACLs","htmlSafe"],[[30,5,["length"]],[28,[37,18],["use acls"],null],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,30],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on intentions",[29,[[28,[37,31],["CONSUL_DOCS_URL"],null],"/commands/intention"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,30],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,31],["CONSUL_DOCS_LEARN_URL"],null],"/consul/getting-started/connect"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "],[13],[1,"\\n"]],[3,4,5,6]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","api","sort","filters","items","item","writer","collection","list"],false,["route","routeName","data-loader","uri","hash","block-slot","error-state","let","or","sortBy","action","mut","if","access","split","not-eq","searchproperty","searchProperties","can","portal","hds/button","gt","consul/intention/search-bar","search","data-writer","refresh-route","data-collection","consul/intention/list","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/services/show/intentions/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/show/routing",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"LPaSV3FN",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/discovery-chain/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n "],[8,[39,7],null,[["@chain"],[[30,2,["data","Chain"]]]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","consul/discovery-chain"]]',moduleName:"consul-ui/templates/dc/services/show/routing.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/show/services",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"9lMQo36C",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/gateways/for-service/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Status:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["instance","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,15],[[33,16],[27]],null],[28,[37,14],[[33,16],","],null],[33,17]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]],[33,17]]]]]]],[30,2,["data"]]],[[[41,[28,[37,18],[[30,5,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,19],null,[["@search","@onsearch","@sort","@filter"],[[99,20,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,20]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,21],null,[["@type","@sort","@filters","@search","@items"],["service",[30,3,["value"]],[30,4],[99,20,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,22],["routes.dc.services.show.services.intro"],[["htmlSafe"],[true]]]],[1,"\\n "],[8,[39,23],null,[["@nspace","@partition","@items"],[[28,[37,8],[[30,1,["params","nspace"]],[30,1,["model","user","token","Namespace"]],"default"],null],[28,[37,8],[[30,1,["params","partition"]],[30,1,["model","user","token","Partition"]],"default"],null],[30,6,["items"]]]],[["default"],[[[[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,24],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,22],["routes.dc.services.show.services.empty"],[["items","htmlSafe"],[[30,5,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[3,4,5]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","sort","filters","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","instance","split","not-eq","searchproperty","searchProperties","gt","consul/upstream/search-bar","search","data-collection","t","consul/service/list","empty-state"]]',moduleName:"consul-ui/templates/dc/services/show/services.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/show/tags",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"QPrKCkNR",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[44,[[28,[37,3],[[28,[37,4],["Tags",[30,1,["model","items"]]],null]],null]],[[[41,[28,[37,6],[[30,2,["length"]],0],null],[[[1," "],[8,[39,7],null,[["@item"],[[28,[37,8],null,[["Tags"],[[30,2]]]]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,9],null,null,[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,11],["routes.dc.services.show.tags.empty.header"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,11],["routes.dc.services.show.tags.empty.body"],[["htmlSafe"],[true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]],[2]]],[1," "],[13],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","tags"],false,["route","routeName","let","flatten","map-by","if","gt","tag-list","hash","empty-state","block-slot","t"]]',moduleName:"consul-ui/templates/dc/services/show/tags.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/show/topology",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"ZLtuX5vP",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/topology/${name}/${kind}",[28,[37,4],null,[["partition","nspace","dc","name","kind"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]],[28,[37,5],[[30,1,["model","items","firstObject","Service","Kind"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","nspace"]],[30,1,["model","dc"]],[30,1,["model","items"]],[30,2,["data"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n\\n "],[10,0],[14,0,"topology-notices"],[12],[1,"\\n "],[8,[39,9],null,[["@expanded"],[true]],[["default"],[[[[1,"\\n"],[44,[[28,[37,10],[[28,[37,11],[[28,[37,11],["filtered-by-acls",[28,[37,5],[false,[30,6,["FilteredByACLs"]]],null]],null],[28,[37,11],["default-allow",[28,[37,5],[false,[28,[37,12],[[30,4,["DefaultACLPolicy"]],"allow"],null]],null]],null],[28,[37,11],["wildcard-intention",[28,[37,5],[false,[30,6,["wildcardIntention"]]],null]],null],[28,[37,11],["not-defined-intention",[28,[37,5],[false,[30,6,["notDefinedIntention"]]],null]],null],[28,[37,11],["no-dependencies",[28,[37,5],[false,[28,[37,13],[[30,6,["noDependencies"]],[28,[37,14],["use acls"],null]],null]],null]],null],[28,[37,11],["acls-disabled",[28,[37,5],[false,[28,[37,13],[[30,6,["noDependencies"]],[28,[37,15],[[28,[37,14],["use acls"],null]],null]],null]],null]],null]],null]],null]],[[[1,"\\n"],[44,[[28,[37,16],[false,[28,[37,17],[[30,8]],null]],null]],[[[1,"\\n"],[42,[28,[37,19],[[30,8]],null],null,[[[41,[30,10],[[[1," "],[8,[30,7,["Details"]],null,[["@auto"],[false]],[["default"],[[[[1,"\\n "],[8,[39,21],[[16,1,[30,12,["id"]]],[24,0,"mb-3 mt-2 topology-metrics-notice"]],[["@type","@color"],["inline",[52,[28,[37,22],[[30,11],[28,[37,11],["filtered-by-acls","no-dependencies"],null]],null],"neutral","warning"]]],[["default"],[[[[1,"\\n "],[8,[30,13,["Title"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,1,["t"]],"notice.${prop}.header",[28,[37,4],null,[["prop"],[[30,11]]]]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[30,7,["expanded"]],[[[1," "],[8,[30,13,["Description"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,1,["t"]],"notice.${prop}.body",[28,[37,4],null,[["prop"],[[30,11]]]]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[41,[28,[37,13],[[30,7,["expanded"]],[28,[37,25],[[30,11],"filtered-by-acls"],null]],null],[[[41,[28,[37,22],[[30,11],[28,[37,11],["wildcard-intention","default-allow","no-intentions"],null]],null],[[[1," "],[8,[30,13,["Button"]],null,[["@color","@size","@route","@text","@icon"],["secondary","small","dc.services.show.intentions",[28,[37,23],[[28,[37,24],[[30,1,["t"]],"notice.${prop}.footer.link-text",[28,[37,4],null,[["prop"],[[30,11]]]]],null]],null],[28,[37,23],[[28,[37,24],[[30,1,["t"]],"notice.${prop}.footer.icon",[28,[37,4],null,[["prop"],[[30,11]]]]],null]],null]]],null],[1,"\\n"]],[]],[[[1," "],[8,[30,13,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition"],[[28,[37,23],[[28,[37,24],[[30,1,["t"]],"notice.${prop}.footer.link-text",[28,[37,4],null,[["prop"],[[30,11]]]]],null]],null],[28,[37,23],[[28,[37,24],[[30,1,["t"]],"notice.${prop}.footer.link",[28,[37,4],null,[["prop"],[[30,11]]]]],null]],null],"docs-link","trailing"]],null],[1,"\\n"]],[]]]],[]],null],[1," "]],[13]]]]],[1,"\\n "]],[12]]]]],[1,"\\n"]],[]],null]],[10,11]],null],[1,"\\n"],[41,[28,[37,26],[[30,9,["length"]],2],null],[[[1," "],[8,[30,7,["Action"]],[[4,[38,27],["click",[30,7,["toggle"]]],null]],null,[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,1,["t"]],"notices.${expanded}",[28,[37,4],null,[["expanded"],[[52,[30,7,["expanded"]],"close","open"]]]]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1,"\\n"]],[9]]]],[8]]],[1," "]],[7]]]]],[1,"\\n\\n "],[13],[1,"\\n\\n\\n "],[8,[39,28],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/ui-config",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n"],[41,[30,14,["data"]],[[[1,"\\n "],[8,[39,29],null,[["@nspace","@dc","@service","@topology","@metricsHref","@isRemoteDC","@hasMetricsProvider","@oncreate"],[[30,3],[30,4],[30,5,["firstObject"]],[30,6],[28,[37,30],[[30,14,["data","dashboard_url_templates","service"]],[28,[37,4],null,[["Datacenter","Service"],[[30,4,["Name"]],[28,[37,4],null,[["Name","Namespace","Partition"],[[30,5,["firstObject","Name"]],[28,[37,5],[[30,5,["firstObject","Namespace"]],""],null],[28,[37,5],[[30,5,["firstObject","Partition"]],""],null]]]]]]]],null],[28,[37,15],[[30,4,["Local"]]],null],[28,[37,26],[[30,14,["data","metrics_provider","length"]],0],null],[28,[37,31],["createIntention"],null]]],null],[1,"\\n\\n"]],[]],null],[1," "]],[14]]]]],[1,"\\n "],[13],[1,"\\n"]],[3,4,5,6]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","nspace","dc","items","topology","disclosure","notices","noticesEnabled","enabled","prop","details","A","config"],false,["route","routeName","data-loader","uri","hash","or","block-slot","app-error","let","disclosure","from-entries","array","eq","and","can","not","without","values","each","-each-in","if","hds/alert","includes","compute","fn","not-eq","gt","on","data-source","topology-metrics","render-template","route-action"]]',moduleName:"consul-ui/templates/dc/services/show/topology.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/services/show/upstreams",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"edRsEgtL",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/gateways/for-service/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Status:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["instance","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,15],[[33,16],[27]],null],[28,[37,14],[[33,16],","],null],[33,17]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]],[33,17]]]]]]],[28,[37,8],[[30,1,["params","partition"]],[30,1,["model","user","token","Partition"]],"default"],null],[28,[37,8],[[30,1,["params","nspace"]],[30,1,["model","user","token","Namespace"]],"default"],null],[30,1,["params","dc"]],[30,2,["data"]]],[[[41,[28,[37,18],[[30,8,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,19],null,[["@search","@onsearch","@sort","@filter"],[[99,20,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,20]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "],[1,[28,[35,21],["routes.dc.services.show.upstreams.intro"],[["htmlSafe"],[true]]]],[1,"\\n "],[8,[39,22],null,[["@type","@sort","@filters","@search","@items"],["service",[30,3,["value"]],[30,4],[99,20,["@search"]],[30,8]]],[["default"],[[[[1,"\\n "],[8,[30,9,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,23],null,[["@items","@dc","@nspace","@partition"],[[30,9,["items"]],[30,7],[30,6],[30,5]]],[["default"],[[[[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,9,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,24],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,21],["routes.dc.services.show.upstreams.empty"],[["items","htmlSafe"],[[30,8,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n"]],[3,4,5,6,7,8]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","sort","filters","partition","nspace","dc","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","instance","split","not-eq","searchproperty","searchProperties","gt","consul/upstream/search-bar","search","t","data-collection","consul/upstream/list","empty-state"]]',moduleName:"consul-ui/templates/dc/services/show/upstreams.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/show",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"FQ+sKuK+",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,null,[["default"],[[[[1,"\\n "],[8,[39,3],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[28,[37,4],[[28,[37,5],[[30,1,["t"]],"title"],null]],null]]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,3],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,3],null,[["@name"],["nav"]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,7],[[28,[37,8],[[28,[37,8],["serverstatus",[28,[37,4],[[28,[37,5],[[30,1,["exists"]],"serverstatus"],null]],null]],null],[28,[37,8],["cataloghealth",false],null],[28,[37,8],["license",[28,[37,4],[[28,[37,5],[[30,1,["exists"]],"license"],null]],null]],null]],null]],null]],[[[1,"\\n"],[44,[[28,[37,9],[false,[28,[37,10],[[30,2]],null]],null]],[[[1,"\\n"],[41,[28,[37,12],[[30,3,["length"]],1],null],[[[1," "],[8,[39,13],null,[["@items"],[[28,[37,14],[[28,[37,8],[[52,[30,2,["serverstatus"]],[28,[37,15],null,[["label","href","selected"],[[28,[37,4],[[28,[37,5],[[30,1,["t"]],"serverstatus.title"],null]],null],[28,[37,16],["dc.show.serverstatus"],null],[28,[37,17],["dc.show.serverstatus"],null]]]],""],[52,[30,2,["cataloghealth"]],[28,[37,15],null,[["label","href","selected"],[[28,[37,4],[[28,[37,5],[[30,1,["t"]],"cataloghealth.title"],null]],null],[28,[37,16],["dc.show.cataloghealth"],null],[28,[37,17],["dc.show.cataloghealth"],null]]]],""],[52,[30,2,["license"]],[28,[37,15],null,[["label","href","selected"],[[28,[37,4],[[28,[37,5],[[30,1,["t"]],"license.title"],null]],null],[28,[37,16],["dc.show.license"],null],[28,[37,17],["dc.show.license"],null]]]]],""],null]],null]]],null],[1,"\\n"]],[]],null],[1,"\\n"]],[3]]]],[2]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,3],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,18],null,[["@name","@model"],[[99,1,["@name"]],[30,1,["model"]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,20],null,null],null,null,null],[1,"\\n "]],[4]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","tabs","tabsEnabled","o"],false,["route","routeName","app-view","block-slot","compute","fn","let","from-entries","array","without","values","if","gt","tab-nav","compact","hash","href-to","is-href","outlet","component","-outlet"]]',moduleName:"consul-ui/templates/dc/show.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/show/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"ZLphbwyJ",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["replaceWith",[52,[28,[37,5],["access overview"],null],"dc.show.serverstatus","dc.services.index"]],null]],null]],[1,"\\n"]],[1]]]]],[1,"\\n\\n"]],["route"],false,["route","routeName","did-insert","route-action","if","can"]]',moduleName:"consul-ui/templates/dc/show/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/show/license",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"NAOKWgT+",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/license",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n"],[44,[[30,2,["data"]]],[[[1," "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,9],[[30,2,["error","status"]],"404"],null],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"This service has been deregistered and no longer exists in the catalog."]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[41,[28,[37,9],[[30,2,["error","status"]],"403"],null],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"You no longer have access to this service."]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,7,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,7,["Description"]],null,null,[["default"],[[[[1,"An error was returned whilst loading this data, refresh to try again."]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]],[]]],[1," "]],[4]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n "],[10,"section"],[15,0,[28,[37,12],["validity",[28,[37,13],["valid",[30,3,["Valid"]]],null]],null]],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,14],[[28,[37,15],[[30,1,["t"]],"expiry.header"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[10,2],[12],[1,"\\n "],[1,[28,[35,14],[[28,[37,15],[[30,1,["t"]],"expiry.${type}.body",[28,[37,4],null,[["type","date","time","htmlSafe"],[[52,[30,3,["Valid"]],"valid","expired"],[28,[37,16],[[30,3,["License","expiration_time"]]],[["year","month","day"],["numeric","long","numeric"]]],[28,[37,16],[[30,3,["License","expiration_time"]]],[["hour12","hour","hourCycle","minute","second","timeZoneName"],[true,"numeric","h12","numeric","numeric","short"]]],true]]]],null]],null]],[1,"\\n "],[13],[1,"\\n\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[15,0,[28,[37,12],[[28,[37,13],["valid",[30,3,["Valid"]]],null],[28,[37,13],["expired",[28,[37,17],[[30,3,["Valid"]]],null]],null],[28,[37,13],["warning",[28,[37,18],[[30,3,["License","expiration_time"]],2629800000],null]],null]],null]],[12],[1,"\\n "],[1,[28,[35,14],[[28,[37,15],[[30,1,["t"]],"expiry.${type}.header",[28,[37,4],null,[["type"],[[52,[30,3,["Valid"]],"valid","expired"]]]]],null]],null]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,19],[[30,3,["License","expiration_time"]]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[10,"aside"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,14],[[28,[37,15],[[30,1,["t"]],"documentation.title"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"flex gap-1.5 flex-col"],[12],[1,"\\n "],[8,[39,20],null,[["@text","@href","@icon"],[[28,[37,14],[[28,[37,15],[[30,1,["t"]],"documentation.links.license-expiration.text"],null]],null],[29,[[28,[37,21],[[28,[37,22],["CONSUL_DOCS_URL"],null],[28,[37,14],[[28,[37,15],[[30,1,["t"]],"documentation.links.license-expiration.link"],null]],null]],null]]],"docs-link"]],null],[1,"\\n "],[8,[39,20],null,[["@text","@href","@icon"],[[28,[37,14],[[28,[37,15],[[30,1,["t"]],"documentation.links.renewing-license.text"],null]],null],[29,[[28,[37,21],[[28,[37,22],["CONSUL_DOCS_URL"],null],[28,[37,14],[[28,[37,15],[[30,1,["t"]],"documentation.links.renewing-license.link"],null]],null]],null]]],"docs-link"]],null],[1,"\\n "],[8,[39,20],null,[["@text","@href","@icon"],[[28,[37,14],[[28,[37,15],[[30,1,["t"]],"documentation.links.applying-new-license.text"],null]],null],[29,[[28,[37,21],[[28,[37,22],["CONSUL_DOCS_URL"],null],[28,[37,14],[[28,[37,15],[[30,1,["t"]],"documentation.links.applying-new-license.link"],null]],null]],null]]],"docs-link"]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[3]]],[1," "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n\\n"]],["route","loader","item","after","T","T","T"],false,["route","routeName","data-loader","uri","hash","let","block-slot","error-state","if","eq","hds/toast","notification","class-map","array","compute","fn","format-time","not","temporal-within","temporal-format","hds/link/standalone","concat","env"]]',moduleName:"consul-ui/templates/dc/show/license.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/dc/show/serverstatus",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"UCwnBDmO",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/datacenter",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n"],[44,[[30,2,["data"]]],[[[1," "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,9],[[30,2,["error","status"]],"404"],null],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"This service has been deregistered and no longer exists in the catalog."]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[41,[28,[37,9],[[30,2,["error","status"]],"403"],null],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"You no longer have access to this service."]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,7,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,7,["Description"]],null,null,[["default"],[[[[1,"An error was returned whilst loading this data, refresh to try again."]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]],[]]],[1," "]],[4]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n\\n "],[10,"section"],[15,0,[28,[37,12],["server-failure-tolerance"],null]],[12],[1,"\\n\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"tolerance.header"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[8,[39,15],null,[["@icon","@iconPosition","@text","@href"],["docs-link","trailing",[28,[37,13],[[28,[37,14],[[30,1,["t"]],"tolerance.link-text"],null]],null],[29,[[28,[37,16],[[28,[37,17],["CONSUL_DOCS_URL"],null],[28,[37,13],[[28,[37,14],[[30,1,["t"]],"tolerance.link"],null]],null]],null]]]]],null],[1,"\\n "],[13],[1,"\\n\\n "],[10,"section"],[15,0,[28,[37,12],[[28,[37,18],["immediate-tolerance"],null]],null]],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"tolerance.immediate.header"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[15,0,[28,[37,12],[[28,[37,18],["warning",[28,[37,19],[[28,[37,9],[[30,3,["FailureTolerance"]],0],null],[28,[37,9],[[30,3,["OptimisticFailureTolerance"]],0],null]],null]],null]],null]],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"tolerance.immediate.body"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["FailureTolerance"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n"],[41,[28,[37,20],["read zones"],null],[[[1," "],[10,"section"],[15,0,[28,[37,12],[[28,[37,18],["optimistic-tolerance"],null]],null]],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"tolerance.optimistic.header"],null]],null]],[1,"\\n "],[11,1],[4,[38,21],["With > 30 seconds between server failures, Consul can restore the Immediate Fault Tolerance by replacing failed active voters with healthy back-up voters when using redundancy zones."],null],[12],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[15,0,[28,[37,12],[[28,[37,18],["warning",[28,[37,9],[[30,3,["OptimisticFailureTolerance"]],0],null]],null]],null]],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"tolerance.optimistic.body"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["OptimisticFailureTolerance"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n\\n"],[41,[28,[37,22],[[30,3,["RedundancyZones","length"]],0],null],[[[1," "],[10,"section"],[15,0,[28,[37,12],["redundancy-zones"],null]],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,23],[[28,[37,24],["common.consul.redundancyzone"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n"],[42,[28,[37,26],[[28,[37,26],[[30,3,["RedundancyZones"]]],null]],null],null,[[[41,[28,[37,22],[[30,8,["Servers","length"]],0],null],[[[1," "],[10,"section"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[30,8,["Name"]]],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[15,0,[28,[37,12],[[28,[37,18],["warning",[28,[37,9],[[30,8,["FailureTolerance"]],0],null]],null]],null]],[12],[1,"\\n "],[10,"dt"],[12],[1,[28,[35,24],["common.consul.failuretolerance"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,8,["FailureTolerance"]]],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,27],null,[["@items"],[[30,8,["Servers"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[8]],null],[1,"\\n"],[41,[28,[37,22],[[30,3,["Default","Servers","length"]],0],null],[[[1," "],[10,"section"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"unassigned"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,27],null,[["@items"],[[30,3,["Default","Servers"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,"section"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"servers"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,27],null,[["@items"],[[30,3,["Default","Servers"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[]]],[1,"\\n"],[41,[28,[37,22],[[30,3,["ReadReplicas","length"]],0],null],[[[1," "],[10,"section"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,23],[[28,[37,24],["common.consul.readreplica"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[8,[39,27],null,[["@items"],[[30,3,["ReadReplicas"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[3]]],[1," "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n\\n"]],["route","loader","item","after","T","T","T","item"],false,["route","routeName","data-loader","uri","hash","let","block-slot","error-state","if","eq","hds/toast","notification","class-map","compute","fn","hds/link/standalone","concat","env","array","and","can","tooltip","gt","pluralize","t","each","-track-array","consul/server/list"]]',moduleName:"consul-ui/templates/dc/show/serverstatus.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/error",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"fBHiRsbk",block:'[[[41,[33,1],[[[8,[39,2],null,[["@error"],[[99,1,["@error"]]]],null],[1,"\\n"]],[]],null]],[],false,["if","error","app-error"]]',moduleName:"consul-ui/templates/error.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"GYFZBIFL",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name","@model"],[[99,1,["@name"]],[30,1,["model"]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,4],null,null],null,null,null],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","o"],false,["route","routeName","outlet","component","-outlet"]]',moduleName:"consul-ui/templates/index.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/loading",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"bxrEoh3x",block:"[[],[],false,[]]",moduleName:"consul-ui/templates/loading.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/notfound",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"3oarGPY0",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@login","@error"],[[30,1,["model","app","login","open"]],[28,[37,3],null,[["status","message"],[404,"Unable to find that page"]]]]],null],[1,"\\n"]],[1]]]]],[1,"\\n\\n"]],["route"],false,["route","routeName","app-error","hash"]]',moduleName:"consul-ui/templates/notfound.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/templates/oauth-provider-debug",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"8VyAGRf6",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[10,0],[14,5,"width: 50%;margin: 0 auto;"],[12],[1,"\\n "],[10,"h1"],[12],[8,[30,1,["Title"]],null,[["@title"],["Mock OAuth Provider"]],null],[13],[1,"\\n "],[10,"main"],[12],[1,"\\n "],[10,"form"],[14,"method","GET"],[15,"action",[36,2]],[12],[1,"\\n"],[44,[[28,[37,4],null,[["state","code"],["state-123456789/abcdefghijklmnopqrstuvwxyz","code-abcdefghijklmnopqrstuvwxyz/123456789"]]]],[[[1," "],[8,[39,5],null,[["@name","@label","@item","@help"],["state","State",[30,2],"The OIDC state value that will get passed through to Consul"]],null],[1,"\\n "],[8,[39,5],null,[["@name","@label","@item","@help"],["code","Code",[30,2],"The OIDC code value that will get passed through to Consul"]],null],[1,"\\n"]],[2]]],[1," "],[8,[39,6],null,[["@type"],["submit"]],[["default"],[[[[1,"\\n Login\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","item"],false,["route","routeName","redirect_uri","let","hash","text-input","action"]]',moduleName:"consul-ui/templates/oauth-provider-debug.hbs",isStrictMode:!1}) -e.default=n})) -define("consul-ui/templates/settings",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=(0,t.createTemplateFactory)({id:"cNZzwPnu",block:'[[[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["settings://consul:client"],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,4],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,4],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,7],[[30,2,["data"]],[28,[37,8],null,[["blocking"],[true]]]],null]],[[[1," "],[8,[39,9],null,null,[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Settings"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,10],[[24,0,"mb-3 mt-2"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,4,["Title"]],null,null,[["default"],[[[[1,"Local Storage"]],[]]]]],[1,"\\n "],[8,[30,4,["Description"]],null,null,[["default"],[[[[1,"These settings are immediately saved to local storage and persisted through browser usage."]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n "],[10,"form"],[12],[1,"\\n"],[41,[28,[37,12],[[28,[37,13],["CONSUL_UI_DISABLE_REALTIME"],null]],null],[[[1," "],[8,[39,14],null,null,[["default"],[[[[1,"\\n "],[8,[30,5,["Details"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,15],null,[["@data","@sink","@onchange"],[[30,3],"settings://consul:client",[28,[37,16],[[30,0],[28,[37,17],[[30,5,["close"]]],null]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Blocking Queries"],[13],[1,"\\n "],[10,2],[12],[1,"Keep catalog info up-to-date without refreshing the page. Any changes made to services, nodes and intentions would be reflected in real time."],[13],[1,"\\n "],[10,0],[14,0,"type-toggle"],[12],[1,"\\n "],[10,"label"],[12],[1,"\\n "],[11,"input"],[24,3,"client[blocking]"],[16,"checked",[52,[30,3,["blocking"]],"checked"]],[24,4,"checkbox"],[4,[38,18],["change",[28,[37,19],[[28,[37,20],[[30,3],"blocking",[28,[37,12],[[30,3,["blocking"]]],null]],null],[28,[37,17],[[30,5,["open"]]],null]],null]],null],[12],[13],[1,"\\n "],[10,1],[12],[1,[52,[30,3,["blocking"]],"On","Off"]],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3]]],[1," "]],[]]]]],[1,"\\n"]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","item","A","disclosure"],false,["route","routeName","data-loader","uri","block-slot","app-error","let","or","hash","app-view","hds/alert","if","not","env","disclosure","data-sink","action","fn","on","queue","set"]]',moduleName:"consul-ui/templates/settings.hbs",isStrictMode:!1}) -e.default=n})),define("consul-ui/transforms/array",["exports","ember-data-model-fragments/transforms/array"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=t.default -e.default=n})),define("consul-ui/transforms/boolean",["exports","@ember-data/serializer/-private"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.BooleanTransform}})})),define("consul-ui/transforms/date",["exports","@ember-data/serializer/-private"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.DateTransform}})})),define("consul-ui/transforms/fragment-array",["exports","ember-data-model-fragments/transforms/fragment-array"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=t.default -e.default=n})),define("consul-ui/transforms/fragment",["exports","ember-data-model-fragments/transforms/fragment"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n=t.default -e.default=n})),define("consul-ui/transforms/number",["exports","@ember-data/serializer/-private"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.NumberTransform}})})),define("consul-ui/transforms/string",["exports","@ember-data/serializer/-private"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.StringTransform}})})),define("consul-ui/utils/ascend",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){const n=e.split("/") -return n.length>t?n.slice(0,-t).concat("").join("/"):""}})),define("consul-ui/utils/atob",["exports","base64-js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"utf-8" -const l=t.default.toByteArray(e) -return new TextDecoder(n).decode(l)}})),define("consul-ui/utils/btoa",["exports","base64-js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){const n=(new TextEncoder).encode(e) -return t.default.fromByteArray(n)}})),define("consul-ui/utils/calculate-position",["exports","ember-basic-dropdown/utils/calculate-position"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/utils/callable-type",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return"function"!=typeof e?function(){return e}:e}})),define("consul-ui/utils/create-fingerprinter",["exports","@ember/object","@ember/utils"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,l,r){let i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:JSON.stringify -return function(o,a,u,s,c){return function(d){if(null==(u=null==u?d[e]:u))throw new Error(`Unable to create fingerprint, missing foreignKey value. Looking for value in \`${e}\` got \`${u}\``) -const p=a.split(",").map((function(e){const l=(0,t.get)(d,e) -if((0,n.isEmpty)(l)){if("PeerName"===e)return -throw new Error(`Unable to create fingerprint, missing slug. Looking for value in \`${e}\` got \`${l}\``)}return l})).compact() -return void 0===d[l]&&("*"===s&&(s="default"),d[l]=s),void 0===d[r]&&("*"===c&&(c="default"),d[r]=c),void 0===d[e]&&(d[e]=u),void 0===d[o]&&(d[o]=i([d[r],d[l],u].concat(p))),d}}}})),define("consul-ui/utils/distance",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){e=e.Coord,t=t.Coord -let n=0 -for(let o=0;o0&&(r=i) -return Math.round(1e5*r)/100}})),define("consul-ui/utils/dom/click-first-anchor",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t -return function(t){let l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"tr" -const r=t.target.nodeName.toLowerCase() -switch(r){case"input":case"label":case"a":case"button":return}const i=e(l,t.target).querySelector("a") -i&&n(i)}} -const t=function(e){["mousedown","mouseup","click"].map((function(e){return new MouseEvent(e,{bubbles:!0,cancelable:!0,view:window})})).forEach((function(t){e.dispatchEvent(t)}))}})),define("consul-ui/utils/dom/closest",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){try{return t.closest(e)}catch(n){return}}})),define("consul-ui/utils/dom/create-listeners",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[] -return new t(e)} -class t{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[] -this.listeners=e}add(e,n,l){let r -if("function"==typeof e)r=e -else if(e instanceof t)r=e.remove.bind(e) -else{let t="addEventListener",i="removeEventListener" -void 0===e[t]&&(t="on",i="off") -let o=n -"string"==typeof o&&(o={[n]:l}) -const a=Object.keys(o).map((function(n){return function(n,l){return e[t](n,l),function(){return e[i](n,l),l}}(n,o[n])})) -r=()=>a.map((e=>e()))}return this.listeners.push(r),()=>{const e=this.listeners.findIndex((function(e){return e===r})) -return this.listeners.splice(e,1)[0]()}}remove(){const e=this.listeners.map((e=>e())) -return this.listeners.splice(0,this.listeners.length),e}}})),define("consul-ui/utils/dom/event-source/blocking",["exports","@ember/object"],(function(e,t){function n(e,t){if(null==e)return{} -var n,l,r=function(e,t){if(null==e)return{} -var n,l,r={},i=Object.keys(e) -for(l=0;l=0||(r[n]=e[n]) -return r}(e,t) -if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e) -for(l=0;l=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:l() -const u=function(l){let u=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -const{currentEvent:s}=u,c=n(u,["currentEvent"]) -e.apply(this,[e=>{const{createEvent:u}=e,s=n(e,["createEvent"]) -return l.apply(this,[s,this]).catch(a).then((n=>{if(n instanceof Error)return n -let l=("function"==typeof u?u:o)(n,e) -l.type||(l={type:"message",data:l}) -const a=(0,t.get)(l.data||{},"meta") -a&&(e.cursor=r(a.cursor,e.cursor),e.cacheControl=a.cacheControl,e.interval=a.interval),-1===(e.cacheControl||"").indexOf("no-store")&&(this.currentEvent=l),this.dispatchEvent(l) -const s=i(e,l,this.previousEvent) -return this.previousEvent=this.currentEvent,s(n)}))},c]),void 0!==s&&(this.currentEvent=s),this.addEventListener("open",(e=>{const t=e.target.getCurrentEvent() -void 0!==t&&this.dispatchEvent(t)}))} -return u.prototype=Object.assign(Object.create(e.prototype,{constructor:{value:e,configurable:!0,writable:!0}}),{getCurrentEvent:function(){return this.currentEvent},getPreviousEvent:function(){return this.previousEvent}}),u},e.validateCursor=e.createErrorBackoff=void 0 -const l=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:3e3,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Promise,l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:setTimeout -return function(r){let i=(0,t.get)(r,"errors.firstObject.status")||(0,t.get)(r,"statusCode") -if(void 0!==i)switch(i=i.toString(),!0){case 0===i.indexOf("5")&&3===i.length&&"500"!==i:case"0"===i:return new n((function(t){l((function(){t(r)}),e)}))}throw r}} -e.createErrorBackoff=l -const r=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=parseInt(e) -if(!isNaN(n))return null!==t&&n2&&void 0!==arguments[2]?arguments[2]:Promise -return function(l){return function(r,i){const o=i.key -if(void 0!==l[o]&&i.settings.enabled)return void 0===l[o].configuration&&(l[o].configuration={}),l[o].configuration.settings=i.settings,e(l[o]) -{const a=i.type||t,u=l[o]=new a(r,i) -return e(u).catch((function(e){return delete l[o],n.reject(e)})).then((function(e){return void 0===e.configuration.cursor&&(e.close(),delete l[o]),e}))}}}}})),define("consul-ui/utils/dom/event-source/callable",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Promise,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:n -const a=function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -e.call(this),this.readyState=2,this.source="function"!=typeof t?function(e,t){return this.close(),r.resolve()}:t,this.readyState=0,r.resolve().then((()=>{if(!(this.readyState>1))return this.readyState=1,this.dispatchEvent({type:"open"}),i(this,n,l)})).catch((e=>{this.dispatchEvent(o(e)),this.readyState=2,this.dispatchEvent({type:"close",error:e})})).then((()=>{this.readyState=2}))} -return a.prototype=Object.assign(Object.create(e.prototype,{constructor:{value:a,configurable:!0,writable:!0}}),{close:function(){switch(this.readyState){case 0:case 2:this.readyState=2 -break -default:this.readyState=3}return this}}),a},e.defaultRunner=void 0 -const t=function(e,n,l){if(!l(e))return e.source.bind(e)(n,e).then((function(r){return t(e,n,l)})) -e.dispatchEvent({type:"close"})} -e.defaultRunner=t -const n=function(e){return new ErrorEvent("error",{error:e,message:e.message})},l=function(e){switch(e.readyState){case 2:case 3:return!0}return!1}})),define("consul-ui/utils/dom/event-source/index",["exports","@ember/object/proxy","@ember/array/proxy","consul-ui/utils/dom/create-listeners","consul-ui/utils/dom/event-target/rsvp","consul-ui/utils/dom/event-source/cache","consul-ui/utils/dom/event-source/proxy","consul-ui/utils/dom/event-source/resolver","consul-ui/utils/dom/event-source/callable","consul-ui/utils/dom/event-source/openable","consul-ui/utils/dom/event-source/blocking","consul-ui/utils/dom/event-source/storage","@ember/object","ember-concurrency","consul-ui/env"],(function(e,t,n,l,r,i,o,a,u,s,c,d,p,f,m){let h -switch(Object.defineProperty(e,"__esModule",{value:!0}),e.once=e.toPromise=e.fromPromise=e.cache=e.source=e.resolve=e.proxy=e.StorageEventSource=e.BlockingEventSource=e.OpenableEventSource=e.CallableEventSource=void 0,(0,m.env)("CONSUL_UI_REALTIME_RUNNER")){case"ec":h=function(e,t,n){return p.default.extend({task:(0,f.task)((function*(){for(;!n(e);)yield e.source.bind(e)(t)}))}).create().get("task").perform()} -break -case"generator":h=async function(e,t,n){const l=function*(){for(;!n(e);)yield e.source.bind(e)(t)} -let r,i=l().next() -for(;!i.done;)r=await i.value,i=l().next() -return r} -break -case"async":h=async function(e,t,n){let l -for(;!n(e);)l=await e.source.bind(e)(t) -return l}}const b=(0,u.default)(r.default,Promise,h) -e.CallableEventSource=b -const y=(0,s.default)(b) -e.OpenableEventSource=y -const g=(0,c.default)(y) -e.BlockingEventSource=g -const v=(0,d.default)(r.default,Promise) -e.StorageEventSource=v -const O=(0,o.default)(t.default,n.default,l.default) -e.proxy=O -const P=(0,a.default)(Promise) -e.resolve=P -const x=function(e){return P(e,(0,l.default)()).then((function(t){return O(e,t)}))} -e.source=x -const w=(0,i.default)(x,g,Promise) -e.cache=w -e.fromPromise=function(e){return new b((function(t){const n=this.dispatchEvent.bind(this),l=()=>{this.close()} -return e.then((function(e){l(),n({type:"message",data:e})})).catch((function(e){l(),n(function(e){return new ErrorEvent("error",{error:e,message:e.message})}(e))}))}))} -e.toPromise=function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"message",l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"error" -return new Promise((function(r,i){const o=function(e){r(e.data)},a=function(e){i(e.error)} -e.addEventListener(n,o),e.addEventListener(l,a),t((function(){"function"==typeof e.close&&e.close(),e.removeEventListener(n,o),e.removeEventListener(l,a)}))}))} -e.once=function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:y -return new n((function(t,n){return e(t,n).then((function(e){n.dispatchEvent({type:"message",data:e}),n.close()})).catch((function(e){n.dispatchEvent({type:"error",error:e}),n.close()}))}),t)}})),define("consul-ui/utils/dom/event-source/openable",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:EventSource -const t=function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -e.apply(this,arguments),this.configuration=n} -return t.prototype=Object.assign(Object.create(e.prototype,{constructor:{value:t,configurable:!0,writable:!0}}),{open:function(){switch(this.readyState){case 3:this.readyState=1 -break -case 2:e.apply(this,[this.source,this.configuration])}return this}}),t}})),define("consul-ui/utils/dom/event-source/proxy",["exports","@ember/object"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,l,r){return function(i){let o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],a=e,u="object" -return"string"!=typeof o&&void 0!==(0,t.get)(o,"length")&&(a=l,u="array",o=o.filter((function(e){return!(0,t.get)(e,"isDestroyed")&&!(0,t.get)(e,"isDeleted")&&(0,t.get)(e,"isLoaded")}))),void 0===n[u]&&(n[u]=a.extend({init:function(){this.listeners=r(),this.listeners.add(this._source,"message",(e=>(0,t.set)(this,"content",e.data))),this._super(...arguments)},addEventListener:function(e,t){this.listeners.add(this._source,e,t)},getCurrentEvent:function(){return this._source.getCurrentEvent(...arguments)},removeEventListener:function(){return this._source.removeEventListener(...arguments)},dispatchEvent:function(){return this._source.dispatchEvent(...arguments)},close:function(){return this._source.close(...arguments)},open:function(){return this._source.open(...arguments)},willDestroy:function(){this._super(...arguments),this.close(),this.listeners.remove()}})),n[u].create({content:o,_source:i,configuration:i.configuration})}} -const n={}})),define("consul-ui/utils/dom/event-source/resolver",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Promise -return function(t,n){let l -return"function"==typeof t.getCurrentEvent&&(l=t.getCurrentEvent()),null!=l?e.resolve(l.data).then((function(e){return t.open(),e})):new e((function(e,l){n.add(t,"error",(function(e){n.remove(),e.target.close(),l(e.error)})),n.add(t,"message",(function(t){n.remove(),e(t.data)}))}))}}})),define("consul-ui/utils/dom/event-source/storage",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Promise -const n=function(e){if((void 0===e||e.key===this.configuration.key)&&1===this.readyState){const e=this.source(this.configuration) -t.resolve(e).then((e=>{this.configuration.cursor++,this._currentEvent={type:"message",data:e},this.dispatchEvent({type:"message",data:e})}))}} -return class extends e{constructor(e,t){super(...arguments),this.readyState=2,this.target=t.target||window,this.name="storage",this.source=e,this.handler=n.bind(this),this.configuration=t,this.configuration.cursor=1,this.open()}dispatchEvent(){if(1===this.readyState)return super.dispatchEvent(...arguments)}close(){this.target.removeEventListener(this.name,this.handler),this.readyState=2}getCurrentEvent(){return this._currentEvent}open(){const e=this.readyState -this.readyState=1,1!==e&&(this.target.addEventListener(this.name,this.handler),this.handler())}}}})),define("consul-ui/utils/dom/event-target/event-target-shim/event",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.wrapEvent=function(e,t){return new(u(Object.getPrototypeOf(t)))(e,t)},e.isStopped=function(e){return l(e).immediateStopped},e.setEventPhase=function(e,t){l(e).eventPhase=t},e.setCurrentTarget=function(e,t){l(e).currentTarget=t},e.setPassiveListener=function(e,t){l(e).passiveListener=t} -const t=new WeakMap,n=new WeakMap -function l(e){const n=t.get(e) -return console.assert(null!=n,"'this' is expected an Event object, but got",e),n}function r(e){null==e.passiveListener?e.event.cancelable&&(e.canceled=!0,"function"==typeof e.event.preventDefault&&e.event.preventDefault()):"undefined"!=typeof console&&"function"==typeof console.error&&console.error("Unable to preventDefault inside passive event listener invocation.",e.passiveListener)}function i(e,n){t.set(this,{eventTarget:e,event:n,eventPhase:2,currentTarget:e,canceled:!1,stopped:!1,immediateStopped:!1,passiveListener:null,timeStamp:n.timeStamp||Date.now()}),Object.defineProperty(this,"isTrusted",{value:!1,enumerable:!0}) -const l=Object.keys(n) -for(let t=0;t1&&void 0!==arguments[1]?arguments[1]:"-view-registry:main" -const n=e.lookup(t) -return function(e){const t=e.getAttribute("id") -if(t)return n[t]}}})),define("consul-ui/utils/dom/is-outside",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:document -if(e){const l=!t||!n.contains(t),r=e===t||e.contains(t) -return!l&&!r}return!1}})) -define("consul-ui/utils/dom/normalize-event",["exports"],(function(e){function t(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function n(e){for(var n=1;n2&&void 0!==arguments[2]?arguments[2]:{} -if(void 0!==e.target)return e -return{target:n(n({},l),{name:e,value:t})}}})),define("consul-ui/utils/dom/qsa-factory",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:document -return function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:e -return n.querySelectorAll(t)}}})),define("consul-ui/utils/dom/sibling",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){let n=e -for(;n=n.nextSibling;)if(1===n.nodeType&&n.nodeName.toLowerCase()===t)return n}})),define("consul-ui/utils/editor/lint",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){n(e,t,(function(){e.getValue().trim().length&&e.performLint()}))},e.createLoader=void 0 -const t=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:document.getElementsByTagName.bind(document),t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:CodeMirror -return t.registerHelper("lint","ruby",(function(e){return[]})),function(n,l,r){let i=[...e("script")] -const o=i.find((function(e){return-1!==e.src.indexOf(`/codemirror/mode/${l}/${l}.js`)})) -t.autoLoadMode(n,l),o?r():(i=[...e("script")],t.on(i[0],"load",(function(){r()})))}} -e.createLoader=t -const n=t()})),define("consul-ui/utils/filter/index",["exports","mnemonist/set"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.andOr=void 0 -e.andOr=e=>{const n=function(e){return Object.entries(e).reduce(((e,t)=>{let[n,l]=t -return e[n]="function"!=typeof l?new Set(Object.keys(l)):null,e}),{})}(e) -return l=>(l=function(e,n){return Object.keys(n).reduce(((l,r)=>{const i=void 0===e[r]?[]:e[r] -return i.length>0&&(null!==n[r]?l[r]=[...t.default.intersection(n[r],new Set(i))]:l[r]=[...new Set(i)]),l}),{})}(l,n),t=>function(e,t,n){return Object.entries(t).every((t=>{let[l,r]=t,i=n[l] -return"function"==typeof i?i(e,r):r.some((t=>i[t](e,t)))}))}(t,l,e))}})),define("consul-ui/utils/form/builder",["exports","@ember/object","ember-changeset","consul-ui/utils/form/changeset","ember-changeset-validations","consul-ui/utils/get-form-name-property"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:o,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.default -return function(){let l=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -const i={} -let o=null -const a={data:null,name:l,getName:function(){return this.name},setData:function(n){return o&&!Array.isArray(n)&&(n=e(n,o)),(0,t.set)(this,"data",n),this},getData:function(){return this.data},add:function(e){return i[e.getName()]=e,this},handleEvent:function(e,l){const i=e.target,o=n(l||i.name),a=o[0],u=o[1] -let s=r -if(a!==this.getName()){if(this.has(a))return this.form(a).handleEvent(e) -s=s[a]}const c=this.getData(),d="function"==typeof c.toJSON?c.toJSON():(0,t.get)(c,"data").toJSON() -if(!Object.keys(d).includes(u)){const e=new Error(`${u} property doesn't exist`) -throw e.target=i,e}let p=(0,t.get)(c,u) -if(Array.isArray(p)||void 0!==s[u]&&"string"==typeof s[u].type&&"array"===s[u].type.toLowerCase()){null==p&&(p=[]) -p[i.checked?"pushObject":"removeObject"](i.value),(0,t.set)(c,u,p)}else void 0===i.checked||"on"!==i.value.toLowerCase()&&"off"!==i.value.toLowerCase()?(0,t.set)(c,u,i.value):(0,t.set)(c,u,i.checked) -return this.validate()},reset:function(){return"function"==typeof this.getData().rollbackAttributes&&this.getData().rollbackAttributes(),this},clear:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{} -return"function"==typeof e?this.clearer=e:this.setData(this.clearer(e)).getData()},submit:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{} -if("function"==typeof e)return this.submitter=e -this.submitter(this.getData())},setValidators:function(e){return o=e,this},validate:function(){const e=this.getData() -return"function"==typeof e.validate&&e.validate(),this},addError:function(e,t){const n=this.getData() -"function"==typeof n.addError&&n.addError(...arguments)},form:function(e){return null==e?this:i[e]},has:function(e){return void 0!==i[e]}} -return a.submit=a.submit.bind(a),a.reset=a.reset.bind(a),a}},e.defaultChangeset=void 0 -const o=function(e,t){return(0,n.Changeset)(e,(0,r.default)(t),t,{changeset:l.default})} -e.defaultChangeset=o})),define("consul-ui/utils/form/changeset",["exports","@ember/object","ember-changeset"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class l extends n.EmberChangeset{pushObject(e,n){let l -void 0===(0,t.get)(this,`_changes.${e}`)?(l=(0,t.get)(this,`data.${e}`),l=l?l.toArray():[]):l=this.get(e).slice(0),l.push(n),this.set(`${e}`,l)}removeObject(e,n){let l -void 0===(0,t.get)(this,`_changes.${e}`)?(l=(0,t.get)(this,`data.${e}`),l=void 0===l?[]:l.toArray()):l=this.get(e).slice(0) -const r=l.indexOf(n);-1!==r&&l.splice(r,1),this.set(`${e}`,l)}}e.default=l})),define("consul-ui/utils/get-environment",["exports","@ember/debug"],(function(e,t){function n(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function l(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:{},n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:window,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:document;(0,t.runInDebug)((()=>{const e=function(e){return e.split(";").map((e=>e.trim())).filter((e=>""!==e)).filter((e=>e.split("=").shift().startsWith("CONSUL_")))} -n.Scenario=function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"" -if(t.length>0)e(t).forEach((e=>{if(e.startsWith("CONSUL_COLOR_SCHEME=")){const[,l]=e.split("=") -let r -try{r=JSON.parse(n.localStorage.getItem("consul:theme"))}catch(t){r={"color-scheme":"light"}}n.localStorage.setItem("consul:theme",`{"color-scheme": "${"!"===l?"light"===r["color-scheme"]?"dark":"light":l}"}`)}else r.cookie=`${e};Path=/`})),n.location.hash="",location.reload() -else{t=e(r.cookie).join(";") -n.open("","_blank").document.write(`
      ${location.href}#${t}

      Scenario`)}},void 0!==n.location&&"string"==typeof n.location.hash&&n.location.hash.length>0&&n.Scenario(n.location.hash.substr(1))})) -const i=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:r.cookie -return e.split(";").filter((e=>""!==e)).map((e=>{const[t,...n]=e.trim().split("=") -return[t,n.join("=")]}))},o=function(e){const t=n.localStorage.getItem(e) -return null===t?void 0:t},a=function(e){try{return n.performance.getEntriesByType("resource").find((t=>"script"===t.initiatorType&&e===t.name))||{}}catch(t){return{}}},u=l(l({},e.operatorConfig),JSON.parse(r.querySelector(`[data-${e.modulePrefix}-config]`).textContent)),s=u.UIConfig||{},c=r.getElementsByTagName("script"),d=c[c.length-1].src -let p -const f=function(e,t){let n,l,r,i -switch(e){case"CONSUL_NSPACES_ENABLED":return void 0!==u.NamespacesEnabled&&u.NamespacesEnabled -case"CONSUL_SSO_ENABLED":return void 0!==u.SSOEnabled&&u.SSOEnabled -case"CONSUL_ACLS_ENABLED":return void 0!==u.ACLsEnabled&&u.ACLsEnabled -case"CONSUL_PARTITIONS_ENABLED":return void 0!==u.PartitionsEnabled&&u.PartitionsEnabled -case"CONSUL_PEERINGS_ENABLED":return void 0!==u.PeeringEnabled&&u.PeeringEnabled -case"CONSUL_HCP_ENABLED":return void 0!==u.HCPEnabled&&u.HCPEnabled -case"CONSUL_DATACENTER_LOCAL":return u.LocalDatacenter -case"CONSUL_DATACENTER_PRIMARY":return u.PrimaryDatacenter -case"CONSUL_HCP_MANAGED_RUNTIME":return u.HCPManagedRuntime -case"CONSUL_API_PREFIX":return u.APIPrefix -case"CONSUL_HCP_URL":return u.HCPURL -case"CONSUL_UI_CONFIG":return l={service:void 0},r=t("CONSUL_METRICS_PROVIDER"),i=t("CONSUL_METRICS_PROXY_ENABLED"),l.service=t("CONSUL_SERVICE_DASHBOARD_URL"),r&&(s.metrics_provider=r),i&&(s.metrics_proxy_enabled=i),l.service&&(s.dashboard_url_templates=l),s -case"CONSUL_BASE_UI_URL":return d.split("/").slice(0,-2).join("/") -case"CONSUL_HTTP_PROTOCOL":return void 0===p&&(p=a(d)),p.nextHopProtocol||"http/1.1" -case"CONSUL_HTTP_MAX_CONNECTIONS":switch(n=t("CONSUL_HTTP_PROTOCOL"),!0){case 0===n.indexOf("h2"):case 0===n.indexOf("hq"):case 0===n.indexOf("spdy"):return -default:return 5}}},m=function(t){let n={} -switch(e.environment){case"development":case"staging":case"coverage":case"test":n=i().reduce((function(e,t){let[n,l]=t -switch(n){case"CONSUL_INTL_LOCALE":e.CONSUL_INTL_LOCALE=String(l).toLowerCase() -break -case"CONSUL_INTL_DEBUG":e.CONSUL_INTL_DEBUG=!!JSON.parse(String(l).toLowerCase()) -break -case"CONSUL_ACLS_ENABLE":e.CONSUL_ACLS_ENABLED=!!JSON.parse(String(l).toLowerCase()) -break -case"CONSUL_AGENTLESS_ENABLE":e.CONSUL_AGENTLESS_ENABLED=!!JSON.parse(String(l).toLowerCase()) -break -case"CONSUL_NSPACES_ENABLE":e.CONSUL_NSPACES_ENABLED=!!JSON.parse(String(l).toLowerCase()) -break -case"CONSUL_SSO_ENABLE":e.CONSUL_SSO_ENABLED=!!JSON.parse(String(l).toLowerCase()) -break -case"CONSUL_PARTITIONS_ENABLE":e.CONSUL_PARTITIONS_ENABLED=!!JSON.parse(String(l).toLowerCase()) -break -case"CONSUL_METRICS_PROXY_ENABLE":e.CONSUL_METRICS_PROXY_ENABLED=!!JSON.parse(String(l).toLowerCase()) -break -case"CONSUL_PEERINGS_ENABLE":e.CONSUL_PEERINGS_ENABLED=!!JSON.parse(String(l).toLowerCase()) -break -case"CONSUL_HCP_ENABLE":e.CONSUL_HCP_ENABLED=!!JSON.parse(String(l).toLowerCase()) -break -case"CONSUL_UI_CONFIG":e.CONSUL_UI_CONFIG=JSON.parse(l) -break -case"TokenSecretID":e.CONSUL_HTTP_TOKEN=l -break -default:e[n]=l}return e}),{}) -break -case"production":n=i().reduce((function(e,t){let[n,l]=t -if("TokenSecretID"===n)e.CONSUL_HTTP_TOKEN=l -return e}),{})}return void 0!==n[t]?n[t]:e[t]} -return function e(t){switch(t){case"CONSUL_UI_DISABLE_REALTIME":case"CONSUL_UI_DISABLE_ANCHOR_SELECTION":return!!JSON.parse(String(o(t)||0).toLowerCase())||m(t) -case"CONSUL_UI_REALTIME_RUNNER":return o(t)||m(t) -case"CONSUL_UI_CONFIG":case"CONSUL_DATACENTER_LOCAL":case"CONSUL_DATACENTER_PRIMARY":case"CONSUL_HCP_MANAGED_RUNTIME":case"CONSUL_API_PREFIX":case"CONSUL_HCP_URL":case"CONSUL_ACLS_ENABLED":case"CONSUL_NSPACES_ENABLED":case"CONSUL_PEERINGS_ENABLED":case"CONSUL_AGENTLESS_ENABLED":case"CONSUL_HCP_ENABLED":case"CONSUL_SSO_ENABLED":case"CONSUL_PARTITIONS_ENABLED":case"CONSUL_METRICS_PROVIDER":case"CONSUL_METRICS_PROXY_ENABLE":case"CONSUL_SERVICE_DASHBOARD_URL":case"CONSUL_BASE_UI_URL":case"CONSUL_HTTP_PROTOCOL":case"CONSUL_HTTP_MAX_CONNECTIONS":{const n=m(t) -return void 0!==n?n:f(t,e)}default:return m(t)}}}})),define("consul-ui/utils/get-form-name-property",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){if(-1!==e.indexOf("["))return e.match(/(.*)\[(.*)\]/).slice(1) -return["",e]}})),define("consul-ui/utils/helpers/call-if-type",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return function(t){return function(n){let l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return typeof n[0]!==e?n[0]:t(n[0],l)}}}})),define("consul-ui/utils/http/consul",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.HEADERS_SYMBOL=e.HEADERS_DIGEST=e.HEADERS_TOKEN=e.HEADERS_INDEX=e.HEADERS_DEFAULT_ACL_POLICY=e.HEADERS_DATACENTER=e.HEADERS_NAMESPACE=e.HEADERS_PARTITION=void 0 -e.HEADERS_PARTITION="X-Consul-Partition" -e.HEADERS_NAMESPACE="X-Consul-Namespace" -e.HEADERS_DATACENTER="X-Consul-Datacenter" -e.HEADERS_DEFAULT_ACL_POLICY="X-Consul-Default-Acl-Policy" -e.HEADERS_INDEX="X-Consul-Index" -e.HEADERS_TOKEN="X-Consul-Token" -e.HEADERS_DIGEST="X-Consul-ContentHash" -e.HEADERS_SYMBOL="__consul_ui_http_headers__"})),define("consul-ui/utils/http/create-headers",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){return function(e){return e.reduce((function(e,t){const[n,...l]=t.split(":") -return l.length>0&&(e[n.trim()]=l.join(":").trim()),e}),{})}}})),define("consul-ui/utils/http/create-query-params",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:encodeURIComponent -return function t(n,l){return Object.entries(n).reduce((function(n,r,i){let[o,a]=r -if(void 0===a)return n -let u=e(o) -return void 0!==l&&(u=`${l}[${u}]`),null===a?n.concat(u):"object"==typeof a?n.concat(t(a,u)):n.concat(`${u}=${e(a)}`)}),[]).join("&")}}})),define("consul-ui/utils/http/create-url",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){return function(n){for(var l=arguments.length,r=new Array(l>1?l-1:0),i=1;i0&&void 0!==arguments[0]?arguments[0]:0 -if("text/event-stream"===this.headers()["content-type"]){this.statusCode=e -const t=this.connection() -if(t.readyState)switch(t.readyState){case 0:case 1:t.abort()}}}}e.default=i})),define("consul-ui/utils/http/status",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.INTERNAL_SERVER_ERROR=e.FORBIDDEN=e.UNAUTHORIZED=e.OK=void 0 -e.OK=200 -e.UNAUTHORIZED=401 -e.FORBIDDEN=403 -e.INTERNAL_SERVER_ERROR=500})),define("consul-ui/utils/http/xhr",["exports"],(function(e){function t(e,t){var n=Object.keys(e) -if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) -t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function n(e){for(var n=1;n=200&&this.status<400){const e=l.converters["text json"](this.response) -l.success(t,e,this.status,this.statusText)}else l.error(t,this.responseText,this.status,this.statusText,this.error) -l.complete(this.status)}} -let i=l.url -i.endsWith("?")&&(i=i.substr(0,i.length-1)),r.open(l.method,i,!0),void 0===l.headers&&(l.headers={}) -const o=n(n({},l.headers),{},{"X-Requested-With":"XMLHttpRequest"}) -return Object.entries(o).forEach((e=>{let[t,n]=e -return r.setRequestHeader(t,n)})),l.beforeSend(r),r.withCredentials=!0,r.send(l.body),r}}})),define("consul-ui/utils/intl/missing-message",["exports","@ember/debug"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,n){(0,t.runInDebug)((t=>console.debug(`Translation key not found: ${e}`))) -const l=e.split(".").pop().split("-").join(" ") -return`${l.substr(0,1).toUpperCase()}${l.substr(1)}`}})),define("consul-ui/utils/isFolder",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"" -return"/"===e.slice(-1)}})),define("consul-ui/utils/keyToArray",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"/" -return(e===t?"":e).split(t)}})),define("consul-ui/utils/left-trim",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"" -return 0===e.indexOf(t)?e.substr(t.length):e}})),define("consul-ui/utils/maybe-call",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){return function(n){return t.then((function(t){return t&&e(),n}))}}})),define("consul-ui/utils/merge-checks",["exports","@ember/object","mnemonist/multi-map"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],l=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:n.default -const i=new r,o=e.shift(),a=o.map((e=>(""===e.ServiceName&&i.set(e.Node,e.CheckID),e))).concat(e.reduce(((e,t)=>void 0===t?e:e.concat(t.reduce(((e,t)=>{if(""===t.ServiceName){if((i.get(t.Node)||[]).includes(t.CheckID))return e -i.set(t.Node,t.CheckID)}return e.push(t),e}),[]))),[])) -return l&&a.filter((e=>(0,t.get)(e,"Exposable"))).forEach((e=>{(0,t.set)(e,"Exposed",l)})),a}})),define("consul-ui/utils/minimizeModel",["exports","@ember/object"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){if(Array.isArray(e))return e.filter((function(e){return!(0,t.get)(e,"isNew")})).map((function(e){return{ID:(0,t.get)(e,"ID"),Name:(0,t.get)(e,"Name")}}))}})),define("consul-ui/utils/non-empty-set",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return function(t){return null==t||""===t?{}:{[e]:t}}}})),define("consul-ui/utils/path/resolve",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=(e,t)=>0===t.indexOf("/")?t:t.split("/").reduce(((e,t,n,l)=>("."!==t&&(".."===t?e.pop():""===t&&n!==l.length-1||e.push(t)),e)),e.split("/")).join("/")})),define("consul-ui/utils/promisedTimeout",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Promise,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:setTimeout -return function(n){let l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(){} -return new e(((e,r)=>{l(t((function(){e(n)}),n))}))}}})) -define("consul-ui/utils/right-trim",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"" -const n=e.length-t.length -if(n>=0)return e.lastIndexOf(t)===n?e.substr(0,n):e -return e}})),define("consul-ui/utils/routing/redirect-to",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){return function(t,n){const l=this.routeName.split(".").slice(0,-1).join(".") -this.replaceWith(`${l}.${e}`,t)}}})),define("consul-ui/utils/routing/transitionable",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2?arguments[2]:void 0 -null===e&&(e=r.lookup("route:application")) -let i,o=n(e,l),a=e -for(;i=a.parent;)o=o.concat(n(i,l)),a=i -return o.reverse(),t(e.name||"application",o,l)} -const t=function(e,t,n){return[e,...t]},n=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} -return(e.paramNames||[]).map((function(n){return void 0!==t[n]?t[n]:e.params[n]})).reverse()}})),define("consul-ui/utils/routing/walk",["exports","@ember/debug"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return function(){n.apply(this,[e])}},e.dump=e.walk=void 0 -const n=function(e){Object.keys(e).forEach(((t,l)=>{if("_options"===t)return -if(null===e[t])return -const r=e[t]._options -let i -Object.keys(e[t]).length>1&&(i=function(){n.apply(this,[e[t]])}),this.route(t,r,i)})),void 0===e.index&&(e.index={_options:{path:""}})} -e.walk=n -let l=e=>{} -e.dump=l,(0,t.runInDebug)((()=>{const t=function(e){return Array(e).fill(" ",0,e).join("")} -e.dump=l=function(e){let l=2 -const r={out:"",route:function(e,n,r){this.out+=`${t(l)}this.route('${e}', ${JSON.stringify(n)}`,r?(l++,this.out+=", function() {\n",r.apply(this,[]),l--,this.out+=`${t(l)}});\n`):this.out+=");",this.out+="\n"}} -return n.apply(r,[e]),`Router.map(\n function() {\n${r.out}\n }\n);`}}))})),define("consul-ui/utils/routing/wildcard",["exports","@ember/object"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return function(n){let l=!1 -try{l=-1!==(0,t.get)(e,n)._options.path.indexOf("*")}catch(r){}return l}}})),define("consul-ui/utils/search/exact",["exports","consul-ui/utils/search/predicate"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{predicate(e){return e=e.toLowerCase(),function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"" -return-1!==t.toString().toLowerCase().indexOf(e)}}}e.default=n})),define("consul-ui/utils/search/fuzzy",["exports","fuse.js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=class{constructor(e,n){this.fuse=new t.default(e,{includeMatches:!0,shouldSort:!1,threshold:.4,keys:Object.keys(n.finders)||[],getFn:(e,t)=>(n.finders[t[0]](e)||[]).toString()})}search(e){return this.fuse.search(e).map((e=>e.item))}}})),define("consul-ui/utils/search/predicate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=class{constructor(e,t){this.items=e,this.options=t}search(e){const t=this.predicate(e) -return this.items.filter((e=>Object.entries(this.options.finders).some((n=>{let[l,r]=n -const i=r(e) -return Array.isArray(i)?i.some(t):t(i)}))))}}})),define("consul-ui/utils/search/regexp",["exports","consul-ui/utils/search/predicate"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -class n extends t.default{predicate(e){let t -try{t=new RegExp(e,"i")}catch(n){return()=>!1}return e=>t.test(e)}}e.default=n})),define("consul-ui/utils/storage/local-storage",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:window.localStorage,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:JSON.stringify,l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:JSON.parse,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:function(e){window.dispatchEvent(new StorageEvent("storage",{key:e}))} -const i=`${e}:` -return{getValue:function(e){let n=t.getItem(`${i}${e}`) -"string"!=typeof n&&(n='""') -try{n=l(n)}catch(r){n=""}return n},setValue:function(e,l){if(null===l)return this.removeValue(e) -try{l=n(l)}catch(a){l='""'}const o=t.setItem(`${i}${e}`,l) -return r(`${i}${e}`),o},removeValue:function(e){const n=t.removeItem(`${i}${e}`) -return r(`${i}${e}`),n},all:function(){return Object.keys(t).reduce(((e,t,n,l)=>{if(0===t.indexOf(`${i}`)){const n=t.substr(i.length) -e[n]=this.getValue(n)}return e}),{})}}}})),define("consul-ui/utils/templatize",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[] -return e.map((e=>`template-${e}`))}})),define("consul-ui/utils/ticker/index",["exports","consul-ui/utils/dom/event-target/rsvp","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.Tween=e.Ticker=void 0 -const l=class extends t.default{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1e3/60 -super(),this.setRate(e)}tick(){this.dispatchEvent({type:"tick",target:this})}setRate(e){clearInterval(this._interval),this._interval=setInterval((()=>this.tick()),e)}destroy(){clearInterval(this._interval)}},r=class extends t.default{static destroy(){void 0!==r.defaultTickerGroup&&(r.defaultTickerGroup.destroy(),delete r.defaultTickerGroup)}constructor(e){super(),this.setTickable(e)}tick(){this._tickable.tick()}setTickable(e){this._tickable=e,void 0===this._tickable.getTicker&&(this._tickable.getTicker=()=>this),this.tick=this._tickable.tick.bind(this._tickable)}getTickable(){return this._tickable}isAlive(){return this._isAlive}start(){this._isAlive=!0,this.getTickerGroup().addEventListener("tick",this.tick),this.dispatchEvent({type:"start",target:this})}stop(){this._isAlive=!1,this.getTickerGroup().removeEventListener("tick",this.tick),this.dispatchEvent({type:"stop",target:this})}activeCount(){return this.getTickerGroup().activeCount()}setTickerGroup(e){this._group=e}getTickerGroup(){return void 0===this._group&&(void 0===r.defaultTickerGroup&&(r.defaultTickerGroup=new o),this._group=r.defaultTickerGroup),this._group}} -e.Ticker=r -const i={easeOut:function(e,t,n,l){return e/=l,n*(--e*e*e+1)+t}},o=l,a=class extends class{constructor(){this._currentframe=1,this.setIncrement(1)}isAtStart(){return this._currentframe<=1}isAtEnd(){return this._currentframe>=this._totalframes}addEventListener(){return this.getTicker().addEventListener(...arguments)}removeEventListener(){return this.getTicker().removeEventListener(...arguments)}stop(){return this.gotoAndStop(this._currentframe)}play(){return this.gotoAndPlay(this._currentframe)}start(){return this.gotoAndPlay(this._currentframe)}gotoAndStop(e){this._currentframe=e -const t=this.getTicker() -return t.isAlive()&&t.stop(),this}gotoAndPlay(e){this._currentframe=e -const t=this.getTicker() -return t.isAlive()||t.start(),this}getTicker(){return void 0===this._ticker&&(this._ticker=new r(this)),this._ticker}setFrames(e){return this._totalframes=e,this}setIncrement(e){return this._increment=e,this}}{static destroy(){r.destroy()}static to(e,t,n,l){return Object.keys(t).forEach((function(n){t[n]-=e[n]})),new a(e,t,n,l).play()}constructor(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:12,l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:i.easeOut -super(),this.setMethod(l),this.setProps(t),this.setTarget(e),this.setFrames(n),this.tick=this.forwards}_process(){Object.keys(this._props).forEach((e=>{const t=this._method(this._currentframe,this._initialstate[e],this._props[e],this._totalframes);(0,n.set)(this._target,e,t)}))}forwards(){this._currentframe<=this._totalframes?(this._process(),this._currentframe+=this._increment):(this._currentframe=this._totalframes,this.getTicker().stop())}backwards(){this._currentframe-=this._increment,this._currentframe>=0?this._process():(this.run=this.forwards,this._currentframe=1,this.getTicker().stop())}gotoAndPlay(){return void 0===this._initialstate&&(this._initialstate={},Object.keys(this._props).forEach((e=>{this._initialstate[e]=this._target[e]}))),super.gotoAndPlay(...arguments)}setTarget(e){this._target=e}getTarget(e){return this._target}setProps(e){return this._props=e,this}setMethod(e){this._method=e}} -e.Tween=a})),define("consul-ui/utils/titleize",["exports","ember-cli-string-helpers/utils/titleize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/utils/tomography",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return function(t,n){var l=999999999,r=-999999999,i=[] -n.forEach((function(o){if(t==o.Node){var a=o.Segment -n.forEach((function(t){if(o.Node!=t.Node&&t.Segment==a){var n=e(o,t) -i.push({node:t.Node,distance:n,segment:a}),nr&&(r=n)}})),i.sort((function(e,t){return e.distance-t.distance}))}})) -var o,a=i.length,u=Math.floor(a/2) -return a>0?o=a%2?i[u].distance:(i[u-1].distance+i[u].distance)/2:(o=0,l=0,r=0),{distances:i,min:Math.trunc(100*l)/100,median:Math.trunc(100*o)/100,max:Math.trunc(100*r)/100}}}})),define("consul-ui/utils/ucfirst",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return`${e.substr(0,1).toUpperCase()}${e.substr(1)}`}})),define("consul-ui/utils/update-array-object",["exports","@ember/object","@ember/object/proxy"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,l,r,i){i=void 0===i?(0,t.get)(l,r):i -const o=e.findIndex((function(e){return(0,t.get)(e,r)===i}));-1!==o&&(l instanceof n.default&&(0,t.set)(l,"content",e.objectAt(o)),e.replace(o,1,[l])) -return l}})),define("consul-ui/validations/intention-permission-http-header",["exports","ember-changeset-validations/validators","consul-ui/validations/sometimes"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>({Name:[(0,t.validatePresence)(!0)],Value:[(0,n.default)((0,t.validatePresence)(!0),(function(){return"Present"!==this.get("HeaderType")}))]})})),define("consul-ui/validations/intention-permission",["exports","ember-changeset-validations/validators","consul-ui/validations/sometimes"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default=e=>({"*":[(0,n.default)((0,t.validatePresence)(!0),(function(){const e=this.get("HTTP.Methods")||[],t=this.get("HTTP.Header")||[],n=this.get("HTTP.PathType")||"NoPath",l=this.get("HTTP.Path")||"" -return![0!==e.length,0!==t.length,"NoPath"!==n&&""!==l].includes(!0)}))],Action:[(0,t.validateInclusion)({in:e["intention-permission"].Action.allowedValues})],HTTP:{Path:[(0,n.default)((0,t.validateFormat)({regex:/^\//}),(function(){const e=this.get("HTTP.PathType") -return void 0!==e&&"NoPath"!==e}))]}})})),define("consul-ui/validations/intention",["exports","ember-changeset-validations/validators","consul-ui/validations/sometimes"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var l={"*":[(0,n.default)((0,t.validatePresence)(!0),(function(){const e=this.get("Action")||"",t=this.get("Permissions")||[] -return""===e&&0===t.length}))],SourceName:[(0,t.validatePresence)(!0),(0,t.validateLength)({min:1})],DestinationName:[(0,t.validatePresence)(!0),(0,t.validateLength)({min:1})],Permissions:[(0,n.default)((0,t.validateLength)({min:1}),(function(e,t){return!this.get("Action")}))]} -e.default=l})),define("consul-ui/validations/kv",["exports","ember-changeset-validations/validators"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n={Key:[(0,t.validatePresence)(!0),(0,t.validateLength)({min:1})]} -e.default=n})),define("consul-ui/validations/policy",["exports","ember-changeset-validations/validators"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n={Name:(0,t.validateFormat)({regex:/^[A-Za-z0-9\-_]{1,128}$/})} -e.default=n})),define("consul-ui/validations/role",["exports","ember-changeset-validations/validators"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -var n={Name:(0,t.validateFormat)({regex:/^[A-Za-z0-9\-_]{1,256}$/})} -e.default=n})),define("consul-ui/validations/sometimes",["exports","@ember/object"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,n){return function(e){return function(l,r,i,o,a){let u={get(e){if(e.includes(".")){let n=(0,t.get)(o,e) -if(void 0!==n)return n -let l=e.split("."),r=l.pop(),i=l.join("."),u=(0,t.get)(o,i) -return u&&u.hasOwnProperty&&u.hasOwnProperty(r)?n:(0,t.get)(a,e)}return o.hasOwnProperty(e)?(0,t.get)(o,e):(0,t.get)(a,e)}} -return!n.call(u,o,a)||e(l,r,i,o,a)}}(e)}})),define("consul-ui/validations/token",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 -e.default={}})),define("consul-ui/config/environment",[],(function(){try{var e="consul-ui/config/environment",t=document.querySelector('meta[name="'+e+'"]').getAttribute("content"),n={default:JSON.parse(decodeURIComponent(t))} -return Object.defineProperty(n,"__esModule",{value:!0}),n}catch(l){throw new Error('Could not read config from meta tag with name "'+e+'".')}})),runningTests||require("consul-ui/app").default.create({name:"consul-ui",version:"2.2.0+63204b51"}) diff --git a/agent/uiserver/dist/assets/consul-ui-a3d723b2486613aa25201645e617bbf2.js b/agent/uiserver/dist/assets/consul-ui-a3d723b2486613aa25201645e617bbf2.js new file mode 100644 index 000000000000..0a6ee6ad762f --- /dev/null +++ b/agent/uiserver/dist/assets/consul-ui-a3d723b2486613aa25201645e617bbf2.js @@ -0,0 +1,4483 @@ +"use strict" +define("consul-ui/abilities/acl",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i +function o(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"resource","acl"),o(this,"segmented",!1)}get canAccess(){return!this.env.var("CONSUL_ACLS_ENABLED")||this.canRead}get canRead(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canRead}get canDuplicate(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canWrite}get canDelete(){return this.env.var("CONSUL_ACLS_ENABLED")&&"anonymous"!==this.item.ID&&super.canWrite}get canUse(){return this.env.var("CONSUL_ACLS_ENABLED")}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) +var u,s,c,d,p,f +e.default=a})),define("consul-ui/abilities/auth-method",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i +function o(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"resource","acl"),o(this,"segmented",!1)}get canRead(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canRead}get canCreate(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canCreate}get canDelete(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canDelete}get canUse(){return this.env.var("CONSUL_SSO_ENABLED")}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) +var u,s,c,d,p,f +e.default=a})),define("consul-ui/abilities/base",["exports","@ember/service","@ember/object","ember-can"],(function(e,t,n,l){var r,i,o +function a(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.ACCESS_WRITE=e.ACCESS_READ=e.ACCESS_LIST=void 0 +const u="read" +e.ACCESS_READ=u +const s="write" +e.ACCESS_WRITE=s +const c="list" +e.ACCESS_LIST=c +let d=(r=(0,t.inject)("repository/permission"),i=class extends l.Ability{constructor(){var e,t,n,l +super(...arguments),e=this,t="permissions",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a(this,"resource",""),a(this,"segmented",!0)}generate(e){return this.permissions.generate(this.resource,e)}generateForSegment(e){return this.segmented?[this.permissions.generate(this.resource,u,e),this.permissions.generate(this.resource,s,e)]:[]}get isLinkable(){return!0}get isNew(){return this.item.isNew}get isPristine(){return this.item.isPristine}get canRead(){if(void 0!==this.item){const e=((0,n.get)(this,"item.Resources")||[]).find((e=>e.Access===u)) +if(e)return e.Allow}return this.permissions.has(this.generate(u))}get canList(){if(void 0!==this.item){const e=((0,n.get)(this,"item.Resources")||[]).find((e=>e.Access===c)) +if(e)return e.Allow}return this.permissions.has(this.generate(c))}get canWrite(){if(void 0!==this.item){const e=((0,n.get)(this,"item.Resources")||[]).find((e=>e.Access===s)) +if(e)return e.Allow}return this.permissions.has(this.generate(s))}get canCreate(){return this.canWrite}get canDelete(){return this.canWrite}get canUpdate(){return this.canWrite}},p=i.prototype,f="permissions",m=[r],h={configurable:!0,enumerable:!0,writable:!0,initializer:null},y={},Object.keys(h).forEach((function(e){y[e]=h[e]})),y.enumerable=!!y.enumerable,y.configurable=!!y.configurable,("value"in y||y.initializer)&&(y.writable=!0),y=m.slice().reverse().reduce((function(e,t){return t(p,f,e)||e}),y),b&&void 0!==y.initializer&&(y.value=y.initializer?y.initializer.call(b):void 0,y.initializer=void 0),void 0===y.initializer&&(Object.defineProperty(p,f,y),y=null),o=y,i) +var p,f,m,h,b,y +e.default=d})),define("consul-ui/abilities/intention",["exports","consul-ui/abilities/base"],(function(e,t){function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{constructor(){super(...arguments),n(this,"resource","intention")}get canWrite(){return(void 0===this.item||void 0===this.item.SourcePeer)&&(super.canWrite&&(void 0===this.item||!this.canViewCRD))}get canViewCRD(){return void 0!==this.item&&this.item.IsManagedByCRD}}e.default=l})),define("consul-ui/abilities/kv",["exports","consul-ui/abilities/base"],(function(e,t){function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{constructor(){super(...arguments),n(this,"resource","key")}generateForSegment(e){let n=super.generateForSegment(e) +return e.endsWith("/")&&(n=n.concat(this.permissions.generate(this.resource,t.ACCESS_LIST,e))),n}get canRead(){return!0}get canList(){return!0}get canWrite(){return!0}}e.default=l})),define("consul-ui/abilities/license",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i +function o(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),o(this,"resource","operator"),o(this,"segmented",!1),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}get canRead(){return this.env.var("CONSUL_NSPACES_ENABLED")&&super.canRead}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) +var u,s,c,d,p,f +e.default=a})),define("consul-ui/abilities/node",["exports","consul-ui/abilities/base"],(function(e,t){function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{constructor(){super(...arguments),n(this,"resource","node")}}e.default=l})),define("consul-ui/abilities/nspace",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i +function o(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"resource","operator"),o(this,"segmented",!1)}get isLinkable(){return!this.item.DeletedAt}get canManage(){return this.canCreate}get canDelete(){return"default"!==this.item.Name&&super.canDelete}get canChoose(){return this.canUse}get canUse(){return this.env.var("CONSUL_NSPACES_ENABLED")}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) +var u,s,c,d,p,f +e.default=a})),define("consul-ui/abilities/overview",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i +function o(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"resource","operator"),o(this,"segmented",!1)}get canAccess(){return!this.env.var("CONSUL_HCP_ENABLED")&&this.canRead}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) +var u,s,c,d,p,f +e.default=a})),define("consul-ui/abilities/partition",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i,o,a +function u(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function s(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let d=(l=(0,n.inject)("env"),r=(0,n.inject)("repository/dc"),i=class extends t.default{constructor(){super(...arguments),u(this,"env",o,this),u(this,"dcs",a,this),s(this,"resource","operator"),s(this,"segmented",!1)}get isLinkable(){return!this.item.DeletedAt}get canManage(){return this.canWrite}get canCreate(){return!(this.dcs.peekAll().length>1)&&super.canCreate}get canDelete(){return"default"!==this.item.Name&&super.canDelete}get canChoose(){return void 0!==this.dc&&(this.canUse&&this.dc.Primary)}get canUse(){return this.env.var("CONSUL_PARTITIONS_ENABLED")}},o=c(i.prototype,"env",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=c(i.prototype,"dcs",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) +e.default=d})),define("consul-ui/abilities/peer",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i +function o(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"resource","peering"),o(this,"segmented",!1)}get isLinkable(){return this.canDelete}get canDelete(){return!["DELETING"].includes(this.item.State)&&super.canDelete}get canUse(){return this.env.var("CONSUL_PEERINGS_ENABLED")}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) +var u,s,c,d,p,f +e.default=a})),define("consul-ui/abilities/permission",["exports","consul-ui/abilities/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{get canRead(){return this.permissions.permissions.length>0}}e.default=n})),define("consul-ui/abilities/policy",["exports","consul-ui/abilities/base","@ember/service","consul-ui/helpers/policy/typeof"],(function(e,t,n,l){var r,i,o +function a(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let u=(r=(0,n.inject)("env"),i=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a(this,"resource","acl"),a(this,"segmented",!1)}get canRead(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canRead}get canWrite(){return this.env.var("CONSUL_ACLS_ENABLED")&&(void 0===this.item||!["policy-management","read-only"].includes((0,l.typeOf)([this.item])))&&super.canWrite}get canCreate(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canCreate}get canDelete(){return this.env.var("CONSUL_ACLS_ENABLED")&&(void 0===this.item||"policy-management"!==(0,l.typeOf)([this.item]))&&super.canDelete}},s=i.prototype,c="env",d=[r],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),o=m,i) +var s,c,d,p,f,m +e.default=u})),define("consul-ui/abilities/role",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i +function o(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let a=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"resource","acl"),o(this,"segmented",!1)}get canRead(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canRead}get canCreate(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canCreate}get canDelete(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canDelete}},u=r.prototype,s="env",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) +var u,s,c,d,p,f +e.default=a})),define("consul-ui/abilities/server",["exports","consul-ui/abilities/base"],(function(e,t){function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{constructor(){super(...arguments),n(this,"resource","operator"),n(this,"segmented",!1)}}e.default=l})),define("consul-ui/abilities/service-instance",["exports","consul-ui/abilities/base"],(function(e,t){function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{constructor(){super(...arguments),n(this,"resource","service")}generateForSegment(e){return super.generateForSegment(...arguments).concat([this.permissions.generate("intention",t.ACCESS_READ,e),this.permissions.generate("intention",t.ACCESS_WRITE,e)])}}e.default=l})),define("consul-ui/abilities/session",["exports","consul-ui/abilities/base"],(function(e,t){function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{constructor(){super(...arguments),n(this,"resource","session")}}e.default=l})),define("consul-ui/abilities/token",["exports","consul-ui/abilities/base","@ember/service","consul-ui/helpers/token/is-legacy","consul-ui/helpers/token/is-anonymous"],(function(e,t,n,l,r){var i,o,a +function u(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let s=(i=(0,n.inject)("env"),o=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),u(this,"resource","acl"),u(this,"segmented",!1)}get canRead(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canRead}get canCreate(){return this.env.var("CONSUL_ACLS_ENABLED")&&super.canCreate}get canDelete(){return this.env.var("CONSUL_ACLS_ENABLED")&&!(0,r.isAnonymous)([this.item])&&this.item.AccessorID!==this.token.AccessorID&&super.canDelete}get canDuplicate(){return this.env.var("CONSUL_ACLS_ENABLED")&&!(0,l.isLegacy)([this.item])&&super.canWrite}},c=o.prototype,d="env",p=[i],f={configurable:!0,enumerable:!0,writable:!0,initializer:null},h={},Object.keys(f).forEach((function(e){h[e]=f[e]})),h.enumerable=!!h.enumerable,h.configurable=!!h.configurable,("value"in h||h.initializer)&&(h.writable=!0),h=p.slice().reverse().reduce((function(e,t){return t(c,d,e)||e}),h),m&&void 0!==h.initializer&&(h.value=h.initializer?h.initializer.call(m):void 0,h.initializer=void 0),void 0===h.initializer&&(Object.defineProperty(c,d,h),h=null),a=h,o) +var c,d,p,f,m,h +e.default=s})),define("consul-ui/abilities/upstream",["exports","consul-ui/abilities/base"],(function(e,t){function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{constructor(){super(...arguments),n(this,"resource","upstream")}get isLinkable(){return this.item.InstanceCount>0}}e.default=l})),define("consul-ui/abilities/zervice",["exports","consul-ui/abilities/base"],(function(e,t){function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{constructor(){super(...arguments),n(this,"resource","service")}get isLinkable(){return this.item.InstanceCount>0}get canReadIntention(){if(void 0===this.item||void 0===this.item.Resources)return!1 +return void 0!==this.item.Resources.find((e=>"intention"===e.Resource&&"read"===e.Access&&!0===e.Allow))}get canWriteIntention(){if(void 0===this.item||void 0===this.item.Resources)return!1 +return void 0!==this.item.Resources.find((e=>"intention"===e.Resource&&"write"===e.Access&&!0===e.Allow))}get canCreateIntention(){return this.canWriteIntention}get canUpdateIntention(){return this.canWriteIntention}}e.default=l})),define("consul-ui/abilities/zone",["exports","consul-ui/abilities/base","@ember/service"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}get canRead(){return this.env.var("CONSUL_NSPACES_ENABLED")}},a=r.prototype,u="env",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/adapters/-json-api",["exports","@ember-data/adapter/json-api"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/adapters/application",["exports","consul-ui/adapters/http","@ember/service"],(function(e,t,n){var l,r,i,o,a +function u(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.NSPACE_QUERY_PARAM=e.DATACENTER_QUERY_PARAM=void 0 +e.DATACENTER_QUERY_PARAM="dc" +e.NSPACE_QUERY_PARAM="ns" +let c=(l=(0,n.inject)("client/http"),r=(0,n.inject)("env"),i=class extends t.default{constructor(){super(...arguments),u(this,"client",o,this),u(this,"env",a,this)}formatNspace(e){if(this.env.var("CONSUL_NSPACES_ENABLED"))return""!==e?{ns:e}:void 0}formatDatacenter(e){return{dc:e}}},o=s(i.prototype,"client",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=s(i.prototype,"env",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) +e.default=c})),define("consul-ui/adapters/auth-method",["exports","consul-ui/adapters/application"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{requestForQuery(e,t){let{dc:n,ns:l,partition:r,index:i,id:o}=t +return e` + GET /v1/acl/auth-methods?${{dc:n}} + + ${{ns:l,partition:r,index:i}} + `}requestForQueryRecord(e,t){let{dc:n,ns:l,partition:r,index:i,id:o}=t +if(void 0===o)throw new Error("You must specify an id") +return e` + GET /v1/acl/auth-method/${o}?${{dc:n}} + + ${{ns:l,partition:r,index:i}} + `}}e.default=n})),define("consul-ui/adapters/binding-rule",["exports","consul-ui/adapters/application"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{requestForQuery(e,t){let{dc:n,ns:l,partition:r,authmethod:i,index:o}=t +return e` + GET /v1/acl/binding-rules?${{dc:n,authmethod:i}} + + ${{ns:l,partition:r,index:o}} + `}}e.default=n})),define("consul-ui/adapters/coordinate",["exports","consul-ui/adapters/application"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{requestForQuery(e,t){let{dc:n,partition:l,index:r,uri:i}=t +return e` + GET /v1/coordinate/nodes?${{dc:n}} + X-Request-ID: ${i} + + ${{partition:l,index:r}} + `}}e.default=n})),define("consul-ui/adapters/discovery-chain",["exports","consul-ui/adapters/application"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{requestForQueryRecord(e,t){let{dc:n,ns:l,partition:r,index:i,id:o,uri:a}=t +if(void 0===o)throw new Error("You must specify an id") +return e` + GET /v1/discovery-chain/${o}?${{dc:n}} + X-Request-ID: ${a} + + ${{ns:l,partition:r,index:i}} + `}}e.default=n})),define("consul-ui/adapters/http",["exports","@ember/service","@ember-data/adapter","@ember-data/adapter/error"],(function(e,t,n,l){var r,i,o +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const a=function(e,t,n){let l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{} +return e.rpc((function(e){for(var t=arguments.length,l=new Array(t>1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;r=500?new l.ServerError(t,r):new l.default(t,r)}}catch(i){n=i}throw n}query(e,t,n){return a(this,t.modelName,"Query",n)}queryRecord(e,t,n){return a(this,t.modelName,"QueryRecord",n)}findAll(e,t){return a(this,t.modelName,"FindAll")}createRecord(e,t,n){return u(this,t.modelName,"CreateRecord",n)}updateRecord(e,t,n){return u(this,t.modelName,"UpdateRecord",n)}deleteRecord(e,t,n){return u(this,t.modelName,"DeleteRecord",n)}},c=i.prototype,d="client",p=[r],f={configurable:!0,enumerable:!0,writable:!0,initializer:null},h={},Object.keys(f).forEach((function(e){h[e]=f[e]})),h.enumerable=!!h.enumerable,h.configurable=!!h.configurable,("value"in h||h.initializer)&&(h.writable=!0),h=p.slice().reverse().reduce((function(e,t){return t(c,d,e)||e}),h),m&&void 0!==h.initializer&&(h.value=h.initializer?h.initializer.call(m):void 0,h.initializer=void 0),void 0===h.initializer&&(Object.defineProperty(c,d,h),h=null),o=h,i) +var c,d,p,f,m,h +e.default=s})),define("consul-ui/adapters/intention",["exports","consul-ui/adapters/application","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{requestForQuery(e,t){let{dc:n,ns:l,partition:r,filter:i,index:o,uri:a}=t +return e` + GET /v1/connect/intentions?${{dc:n}} + X-Request-ID: ${a}${void 0!==i?`\n X-Range: ${i}`:""} + + ${{partition:r,ns:"*",index:o,filter:i}} + `}requestForQueryRecord(e,t){let{dc:n,index:l,id:r}=t +if(void 0===r)throw new Error("You must specify an id") +if(r.match(/^peer:/)){const[t,i,o,a,u,s,c]=r.split(":").map(decodeURIComponent) +return e` + GET /v1/connect/intentions/exact?${{source:`${t}:${i}/${o}/${a}`,destination:`${u}/${s}/${c}`,dc:n}} + Cache-Control: no-store + + ${{index:l}} + `}{const[t,i,o,a,u,s]=r.split(":").map(decodeURIComponent) +return e` + GET /v1/connect/intentions/exact?${{source:`${t}/${i}/${o}`,destination:`${a}/${u}/${s}`,dc:n}} + Cache-Control: no-store + + ${{index:l}} + `}}requestForCreateRecord(e,t,l){const r={SourceName:t.SourceName,DestinationName:t.DestinationName,SourceNS:t.SourceNS,DestinationNS:t.DestinationNS,SourcePartition:t.SourcePartition,DestinationPartition:t.DestinationPartition,SourceType:t.SourceType,Meta:t.Meta,Description:t.Description} +return(0,n.get)(t,"Action.length")?r.Action=t.Action:t.Permissions&&(r.Permissions=t.Permissions),e` + PUT /v1/connect/intentions/exact?${{source:`${l.SourcePartition}/${l.SourceNS}/${l.SourceName}`,destination:`${l.DestinationPartition}/${l.DestinationNS}/${l.DestinationName}`,dc:l.Datacenter}} + + ${r} + `}requestForUpdateRecord(e,t,n){return delete t.DestinationName,delete t.DestinationNS,delete t.DestinationPartition,this.requestForCreateRecord(...arguments)}requestForDeleteRecord(e,t,n){return e` + DELETE /v1/connect/intentions/exact?${{source:`${n.SourcePartition}/${n.SourceNS}/${n.SourceName}`,destination:`${n.DestinationPartition}/${n.DestinationNS}/${n.DestinationName}`,dc:n.Datacenter}} + `}}e.default=l})),define("consul-ui/adapters/kv",["exports","consul-ui/adapters/application","consul-ui/utils/isFolder","consul-ui/utils/keyToArray","consul-ui/models/kv"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class i extends t.default{async requestForQuery(e,t){let{dc:n,ns:r,partition:i,index:o,id:a,separator:u}=t +if(void 0===a)throw new Error("You must specify an id") +const s=await(e` + GET /v1/kv/${(0,l.default)(a)}?${{keys:null,dc:n,separator:u}} + + ${{ns:r,partition:i,index:o}} + `) +return await s(((e,t)=>delete e["x-consul-index"])),s}async requestForQueryRecord(e,t){let{dc:n,ns:r,partition:i,index:o,id:a}=t +if(void 0===a)throw new Error("You must specify an id") +const u=await(e` + GET /v1/kv/${(0,l.default)(a)}?${{dc:n}} + + ${{ns:r,partition:i,index:o}} + `) +return await u(((e,t)=>delete e["x-consul-index"])),u}requestForCreateRecord(e,t,n){const i={dc:n.Datacenter,ns:n.Namespace,partition:n.Partition} +return e` + PUT /v1/kv/${(0,l.default)(n[r.SLUG_KEY])}?${i} + Content-Type: text/plain; charset=utf-8 + + ${t} + `}requestForUpdateRecord(e,t,n){const i={dc:n.Datacenter,ns:n.Namespace,partition:n.Partition,flags:n.Flags} +return e` + PUT /v1/kv/${(0,l.default)(n[r.SLUG_KEY])}?${i} + Content-Type: text/plain; charset=utf-8 + + ${t} + `}requestForDeleteRecord(e,t,i){let o;(0,n.default)(i[r.SLUG_KEY])&&(o=null) +const a={dc:i.Datacenter,ns:i.Namespace,partition:i.Partition,recurse:o} +return e` + DELETE /v1/kv/${(0,l.default)(i[r.SLUG_KEY])}?${a} + `}}e.default=i})) +define("consul-ui/adapters/node",["exports","consul-ui/adapters/application"],(function(e,t){function n(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function l(e){for(var t=1;t({ID:e.ID}))),RoleDefaults:t.ACLs.RoleDefaults.map((e=>({ID:e.ID})))}}} + `}requestForUpdateRecord(e,t,l){return e` + PUT /v1/namespace/${l[n.SLUG_KEY]}?${{dc:l.Datacenter,partition:l.Partition}} + + ${{Description:t.Description,ACLs:{PolicyDefaults:t.ACLs.PolicyDefaults.map((e=>({ID:e.ID}))),RoleDefaults:t.ACLs.RoleDefaults.map((e=>({ID:e.ID})))}}} + `}requestForDeleteRecord(e,t,l){return e` + DELETE /v1/namespace/${l[n.SLUG_KEY]}?${{dc:l.Datacenter,partition:l.Partition}} + `}}e.default=l})),define("consul-ui/adapters/oidc-provider",["exports","consul-ui/adapters/application","@ember/service"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}requestForQuery(e,t){let{dc:n,ns:l,partition:r,index:i,uri:o}=t +return e` + GET /v1/internal/ui/oidc-auth-methods?${{dc:n}} + X-Request-ID: ${o} + + ${{ns:l,partition:r,index:i}} + `}requestForQueryRecord(e,t){let{dc:n,ns:l,partition:r,id:i}=t +if(void 0===i)throw new Error("You must specify an id") +return e` + POST /v1/acl/oidc/auth-url?${{dc:n,ns:l,partition:r}} + Cache-Control: no-store + + ${{AuthMethod:i,RedirectURI:`${this.env.var("CONSUL_BASE_UI_URL")}/oidc/callback`}} + `}requestForAuthorize(e,t){let{dc:n,ns:l,partition:r,id:i,code:o,state:a}=t +if(void 0===i)throw new Error("You must specify an id") +if(void 0===o)throw new Error("You must specify an code") +if(void 0===a)throw new Error("You must specify an state") +return e` + POST /v1/acl/oidc/callback?${{dc:n,ns:l,partition:r}} + Cache-Control: no-store + + ${{AuthMethod:i,Code:o,State:a}} + `}requestForLogout(e,t){let{id:n}=t +if(void 0===n)throw new Error("You must specify an id") +return e` + POST /v1/acl/logout + Cache-Control: no-store + X-Consul-Token: ${n} + `}authorize(e,t,n,l){return this.rpc((function(e,t,n,l){return e.requestForAuthorize(t,n,l)}),(function(e,t,n,l){return e.respondForAuthorize(t,n,l)}),l,t.modelName)}logout(e,t,n,l){return this.rpc((function(e,t,n,l){return e.requestForLogout(t,n,l)}),(function(e,t,n,l){return{}}),l,t.modelName)}},a=r.prototype,u="env",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/adapters/partition",["exports","consul-ui/adapters/application","consul-ui/models/partition"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{async requestForQuery(e,t){let{ns:n,dc:l,index:r}=t +const i=await(e` + GET /v1/partitions?${{dc:l}} + + ${{index:r}} + `) +return await i(((e,t)=>delete e["x-consul-index"])),i}async requestForQueryRecord(e,t){let{ns:n,dc:l,index:r,id:i}=t +if(void 0===i)throw new Error("You must specify an id") +const o=await(e` + GET /v1/partition/${i}?${{dc:l}} + + ${{index:r}} + `) +return await o(((e,t)=>delete e["x-consul-index"])),o}async requestForCreateRecord(e,t,l){return e` + PUT /v1/partition/${l[n.SLUG_KEY]}?${{dc:l.Datacenter}} + + ${{Name:t.Name,Description:t.Description}} + `}async requestForUpdateRecord(e,t,l){return e` + PUT /v1/partition/${l[n.SLUG_KEY]}?${{dc:l.Datacenter}} + + ${{Description:t.Description}} + `}async requestForDeleteRecord(e,t,l){return e` + DELETE /v1/partition/${l[n.SLUG_KEY]}?${{dc:l.Datacenter}} + `}}e.default=l})),define("consul-ui/adapters/permission",["exports","consul-ui/adapters/application","@ember/service"],(function(e,t,n){var l,r,i,o,a +function u(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function s(e){for(var t=1;ts(s({},e),{},{Namespace:l})))),this.env.var("CONSUL_PARTITIONS_ENABLED")&&(i=i.map((e=>s(s({},e),{},{Partition:r})))),e` + POST /v1/internal/acl/authorize?${{dc:n}} + + ${i} + `}authorize(e,t,n,l){return this.rpc((async(e,t,n,l)=>{const r=this.env.var("CONSUL_NSPACES_ENABLED"),i=this.env.var("CONSUL_PARTITIONS_ENABLED") +if(r||i){const e=await this.settings.findBySlug("token") +r&&(void 0!==n.ns&&0!==n.ns.length||(n.ns=e.Namespace)),i&&(void 0!==n.partition&&0!==n.partition.length||(n.partition=e.Partition))}return e.requestForAuthorize(t,n)}),(function(e,t,n,l){return t((function(e,t){return t}))}),l,t.modelName)}},o=p(i.prototype,"env",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=p(i.prototype,"settings",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) +e.default=f})),define("consul-ui/adapters/policy",["exports","consul-ui/adapters/application","consul-ui/models/policy"],(function(e,t,n){function l(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function r(e){for(var t=1;tdelete e["x-consul-index"])),a}requestForCreateRecord(e,t,n){return e` + PUT /v1/acl/token?${u(u({},this.formatDatacenter(n.Datacenter)),{},{ns:n.Namespace,partition:n.Partition})} + + ${{Description:t.Description,Policies:t.Policies,Roles:t.Roles,ServiceIdentities:t.ServiceIdentities,NodeIdentities:t.NodeIdentities,Local:t.Local}} + `}requestForUpdateRecord(e,t,n){if(void 0!==n.Rules)return e` + PUT /v1/acl/update?${this.formatDatacenter(n.Datacenter)} + + ${t} + ` +const r=u(u({},this.formatDatacenter(n.Datacenter)),{},{ns:n.Namespace,partition:n.Partition}) +return e` + PUT /v1/acl/token/${n[l.SLUG_KEY]}?${r} + + ${{Description:t.Description,AccessorID:t.AccessorID,Policies:t.Policies,Roles:t.Roles,ServiceIdentities:t.ServiceIdentities,NodeIdentities:t.NodeIdentities,Local:t.Local}} + `}requestForDeleteRecord(e,t,n){const r={dc:n.Datacenter,ns:n.Namespace,partition:n.Partition} +return e` + DELETE /v1/acl/token/${n[l.SLUG_KEY]}?${r} + `}requestForSelf(e,t,n){let{dc:l,index:r,secret:i}=n +return e` + GET /v1/acl/token/self?${{dc:l}} + X-Consul-Token: ${i} + Cache-Control: no-store + + ${{index:r}} + `}requestForCloneRecord(e,t,n){const r=n[l.SLUG_KEY] +if(void 0===r)throw new Error("You must specify an id") +return e` + PUT /v1/acl/token/${r}/clone?${{dc:n.Datacenter,ns:n.Namespace,partition:n.Partition}} + `}self(e,t,n,l){return this.rpc((function(e,t,n,l){return e.requestForSelf(t,n,l)}),(function(e,t,n,l){return e.respondForSelf(t,n,l)}),l,t.modelName)}clone(e,t,n,l){return this.rpc((function(e,t,n,l){return e.requestForCloneRecord(t,n,l)}),((e,t,n,l)=>{const r={dc:l.Datacenter,ns:l.Namespace,partition:l.Partition} +return e.respondForQueryRecord(t,r)}),l,t.modelName)}},d=i.prototype,p="store",f=[r],m={configurable:!0,enumerable:!0,writable:!0,initializer:null},b={},Object.keys(m).forEach((function(e){b[e]=m[e]})),b.enumerable=!!b.enumerable,b.configurable=!!b.configurable,("value"in b||b.initializer)&&(b.writable=!0),b=f.slice().reverse().reduce((function(e,t){return t(d,p,e)||e}),b),h&&void 0!==b.initializer&&(b.value=b.initializer?b.initializer.call(h):void 0,b.initializer=void 0),void 0===b.initializer&&(Object.defineProperty(d,p,b),b=null),o=b,i) +var d,p,f,m,h,b +e.default=c})),define("consul-ui/adapters/topology",["exports","consul-ui/adapters/application"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{requestForQueryRecord(e,t){let{dc:n,ns:l,partition:r,kind:i,index:o,id:a,uri:u}=t +if(void 0===a)throw new Error("You must specify an id") +return e` + GET /v1/internal/ui/service-topology/${a}?${{dc:n,kind:i}} + X-Request-ID: ${u} + + ${{ns:l,partition:r,index:o}} + `}}e.default=n})),define("consul-ui/app",["exports","@ember/application","ember-resolver","ember-load-initializers","consul-ui/config/environment"],(function(e,t,n,l,r){function i(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class o extends t.default{constructor(){super(...arguments),i(this,"modulePrefix",r.default.modulePrefix),i(this,"podModulePrefix",r.default.podModulePrefix),i(this,"Resolver",n.default)}}e.default=o,(0,l.default)(o,r.default.modulePrefix)})),define("consul-ui/component-managers/glimmer",["exports","@glimmer/component/-private/ember-component-manager"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/-dynamic-element-alt",["exports","@glimmer/component"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{}e.default=n})),define("consul-ui/components/-dynamic-element",["exports","@glimmer/component"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{}e.default=n})),define("consul-ui/components/action/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"KpdZ2T3D",block:'[[[1,"\\n"],[41,[30,1],[[[11,"label"],[16,"for",[30,1]],[17,2],[12],[18,8,null],[13]],[]],[[[41,[30,3],[[[41,[30,4],[[[11,3],[16,6,[30,3]],[24,"target","_blank"],[24,"rel","noopener noreferrer"],[17,2],[12],[18,8,null],[13]],[]],[[[11,3],[16,6,[30,3]],[17,2],[12],[18,8,null],[13]],[]]]],[]],[[[11,"button"],[16,4,[28,[37,2],[[30,5],"button"],null]],[16,"tabindex",[30,6]],[17,2],[4,[38,3],["click",[28,[37,4],[[30,7]],null]],null],[12],[18,8,null],[13]],[]]]],[]]]],["@for","&attrs","@href","@external","@type","@tabindex","@onclick","&default"],false,["if","yield","or","on","optional"]]',moduleName:"consul-ui/components/action/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/anonymous/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"MXp+ENoB",block:'[[[1,"\\n"],[18,1,null]],["&default"],false,["yield"]]',moduleName:"consul-ui/components/anonymous/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) +e.default=r})),define("consul-ui/components/app-error/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"staay0IG",block:'[[[1,"\\n"],[8,[39,0],null,null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n Error "],[1,[30,1,["status"]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@error","@login"],[[30,1],[52,[28,[37,4],[[30,1,["status"]],"403"],null],[30,2]]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]]],[1,"\\n"]],["@error","@login"],false,["app-view","block-slot","error-state","if","eq"]]',moduleName:"consul-ui/components/app-error/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/app-view/index",["exports","@ember/component","@ember/template-factory","block-slots"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"oa2Rdx8I",block:'[[[1,"\\n"],[11,0],[24,0,"app-view"],[17,1],[12],[1,"\\n "],[18,2,null],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,"nav"],[14,"aria-label","Breadcrumb"],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],null,[["class"],["with-breadcrumbs"]]]],[1,"\\n "],[18,2,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"title"],[12],[1,"\\n "],[10,0],[14,0,"title-left-container"],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[18,2,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"actions"],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,3],null,[["@name"],["app-view-actions"]],null],[1,"\\n "],[18,2,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,1],null,[["@name"],["nav"]],[["default"],[[[[1,"\\n "],[18,2,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,1],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[18,2,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["content"]],[["default"],[[[[18,2,null]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs","&default"],false,["yield","yield-slot","document-attrs","portal-target"]]',moduleName:"consul-ui/components/app-view/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,t.default.extend(l.default,{tagName:""})) +e.default=i})),define("consul-ui/components/app/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/object"],(function(e,t,n,l,r,i){var o,a,u +function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const c=(0,n.createTemplateFactory)({id:"bKitd39l",block:'[[[1,"\\n"],[44,[[28,[37,1],null,[["main","Notification"],[[28,[37,2],[[33,3],"-main"],null],[50,"app/notification",0,null,null]]]]],[[[1,"\\n "],[11,0],[24,0,"app"],[17,2],[12],[1,"\\n "],[8,[39,5],null,null,null],[1,"\\n\\n "],[18,3,[[30,1]]],[1,"\\n "],[10,"main"],[15,1,[28,[37,2],[[33,3],"-main"],null]],[12],[1,"\\n "],[10,0],[14,0,"notifications"],[12],[1,"\\n "],[18,4,[[30,1]]],[1,"\\n "],[8,[39,7],null,[["@name","@multiple"],["app-notifications",true]],null],[1,"\\n "],[13],[1,"\\n "],[18,5,[[30,1]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n"]],[1]]]],["exported","&attrs","&side-nav","¬ifications","&main"],false,["let","hash","concat","guid","component","modal-layer","yield","portal-target"]]',moduleName:"consul-ui/components/app/index.hbs",isStrictMode:!1}) +let d=(o=(0,r.inject)("dom"),a=class extends l.default{constructor(e,t){var n,l,r,i +super(...arguments),n=this,l="dom",i=this,(r=u)&&Object.defineProperty(n,l,{enumerable:r.enumerable,configurable:r.configurable,writable:r.writable,value:r.initializer?r.initializer.call(i):void 0}),this.guid=this.dom.guid(this)}keypressClick(e){e.target.dispatchEvent(new MouseEvent("click"))}focus(e){const t=e.target.getAttribute("href") +t.startsWith("#")&&(e.preventDefault(),this.dom.focus(t))}unfocus(e){e.target.blur()}},u=s(a.prototype,"dom",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s(a.prototype,"keypressClick",[i.action],Object.getOwnPropertyDescriptor(a.prototype,"keypressClick"),a.prototype),s(a.prototype,"focus",[i.action],Object.getOwnPropertyDescriptor(a.prototype,"focus"),a.prototype),s(a.prototype,"unfocus",[i.action],Object.getOwnPropertyDescriptor(a.prototype,"unfocus"),a.prototype),a) +e.default=d,(0,t.setComponentTemplate)(c,d)})),define("consul-ui/components/app/notification/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"CpdPnT0l",block:'[[[1,"\\n"],[11,0],[24,0,"app-notification"],[17,1],[4,[38,0],[[28,[37,1],[[28,[37,1],["opacity","1"],null],[28,[37,1],["transition-delay",[28,[37,2],[[30,2],"ms"],null]],null]],null]],null],[4,[38,0],[[28,[37,1],[[28,[37,1],["opacity",[52,[30,3],"1","0"]],null]],null]],[["delay"],[0]]],[12],[1,"\\n "],[18,4,null],[1,"\\n"],[13],[1,"\\n\\n"]],["&attrs","@delay","@sticky","&default"],false,["style","array","concat","if","yield"]]',moduleName:"consul-ui/components/app/notification/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/aria-menu/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object","@ember/runloop"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"XFAq3WQx",block:'[[[1,"\\n"],[18,1,[[28,[37,1],[[30,0],"change"],null],[28,[37,1],[[30,0],"keypress"],null],[28,[37,1],[[30,0],"keypressClick"],null],[28,[37,2],null,[["labelledBy","controls","expanded"],[[28,[37,3],["component-aria-menu-trigger-",[33,4]],null],[28,[37,3],["component-aria-menu-menu-",[33,4]],null],[52,[33,6],"true",[27]]]]]]]],["&default"],false,["yield","action","hash","concat","guid","if","expanded"]]',moduleName:"consul-ui/components/aria-menu/index.hbs",isStrictMode:!1}),a=13,u=32,s=38,c=40,d={vertical:{[c]:function(e){return((arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1)+1)%e.length},[s]:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0 +return 0===t?e.length-1:t-1},36:function(e,t){return 0},35:function(e,t){return e.length-1}},horizontal:{}},p='[role^="menuitem"]' +var f=(0,t.setComponentTemplate)(o,t.default.extend({tagName:"",dom:(0,l.inject)("dom"),guid:"",expanded:!1,orientation:"vertical",keyboardAccess:!0,init:function(){this._super(...arguments),(0,r.set)(this,"guid",this.dom.guid(this)),this._listeners=this.dom.listeners(),this._routelisteners=this.dom.listeners()},didInsertElement:function(){this.$menu=this.dom.element(`#component-aria-menu-menu-${this.guid}`) +const e=this.$menu.getAttribute("aria-labelledby") +this.$trigger=this.dom.element(`#${e}`)},willDestroyElement:function(){this._super(...arguments),this._listeners.remove(),this._routelisteners.remove()},actions:{keypressClick:function(e){e.target.dispatchEvent(new MouseEvent("click"))},keypress:function(e){if(![a,u,s,c].includes(e.keyCode))return +e.stopPropagation() +const t=[...this.dom.elements(p,this.$menu)] +if(e.keyCode===a||e.keyCode===u){let e=this.expanded?void 0:t[0];(0,i.next)((()=>{e=this.expanded?e:this.$trigger,void 0!==e&&e.focus()}))}if(void 0===d[this.orientation][e.keyCode])return +e.preventDefault() +const n=this.dom.element(`${p}:focus`,this.$menu) +let l +n&&(l=t.findIndex((function(e){return e===n}))) +t[d[this.orientation][e.keyCode](t,l)].focus()},change:function(e){e.target.checked?this.actions.open.apply(this,[e]):this.actions.close.apply(this,[e])},close:function(e){this._listeners.remove(),(0,r.set)(this,"expanded",!1),(0,i.next)((()=>{this.$trigger.removeAttribute("tabindex")}))},open:function(e){(0,r.set)(this,"expanded",!0) +0===[...this.dom.elements(p,this.$menu)].length&&this.dom.element('input[type="checkbox"]',this.$menu.parentElement).dispatchEvent(new MouseEvent("click")),this.$trigger.setAttribute("tabindex","-1"),this._listeners.add(this.dom.document(),{keydown:e=>{27===e.keyCode&&this.$trigger.focus(),9!==e.keyCode&&27!==e.keyCode?this.keyboardAccess&&this.actions.keypress.apply(this,[e]):this.$trigger.dispatchEvent(new MouseEvent("click"))}})}}})) +e.default=f})),define("consul-ui/components/auth-dialog/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={id:"auth-dialog",initial:"idle",on:{CHANGE:[{target:"authorized",cond:"hasToken",actions:["login"]},{target:"unauthorized",actions:["logout"]}]},states:{idle:{on:{CHANGE:[{target:"authorized",cond:"hasToken"},{target:"unauthorized"}]}},unauthorized:{},authorized:{}}}})),define("consul-ui/components/auth-dialog/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/object","consul-ui/components/auth-dialog/chart.xstate"],(function(e,t,n,l,r,i,o){var a,u,s +function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const d=(0,n.createTemplateFactory)({id:"dtpP8wDK",block:'[[[1,"\\n"],[8,[39,0],null,[["@src"],[[99,1,["@src"]]]],[["default"],[[[[1,"\\n\\n "],[8,[30,2],null,[["@name","@cond"],["hasToken",[28,[37,2],[[30,0],"hasToken"],null]]],null],[1,"\\n "],[8,[30,3],null,[["@name","@exec"],["login",[28,[37,2],[[30,0],"login"],null]]],null],[1,"\\n "],[8,[30,3],null,[["@name","@exec"],["logout",[28,[37,2],[[30,0],"logout"],null]]],null],[1,"\\n\\n"],[1," "],[8,[39,3],null,[["@src","@onchange"],[[30,6],[28,[37,4],[[28,[37,2],[[30,0],[28,[37,5],[[33,6]],null]],[["value"],["data"]]],[28,[37,2],[[30,0],[30,4],"CHANGE"],null],[28,[37,2],[[30,0],[28,[37,5],[[33,7]],null]],[["value"],["data"]]]],null]]],null],[1,"\\n"],[1," "],[8,[39,8],null,[["@sink"],[[30,7]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,10],null,[["login","logout","token"],[[28,[37,2],[[30,0],[30,8,["open"]]],null],[28,[37,2],[[30,0],[30,8,["open"]],null],null],[33,6]]]]],[[[1,"\\n "],[8,[30,1],null,[["@matches"],["authorized"]],[["default"],[[[[1,"\\n "],[18,10,[[30,9]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["unauthorized"]],[["default"],[[[[1,"\\n "],[18,11,[[30,9]]],[1,"\\n "]],[]]]]],[1,"\\n\\n"]],[9]]],[1," "]],[8]]]]],[1,"\\n"]],[1,2,3,4,5]]]]],[1,"\\n"]],["State","Guard","Action","dispatch","state","@src","@sink","sink","api","&authorized","&unauthorized"],false,["state-chart","chart","action","data-source","queue","mut","token","previousToken","data-sink","let","hash","yield"]]',moduleName:"consul-ui/components/auth-dialog/index.hbs",isStrictMode:!1}) +let p=(a=(0,r.inject)("repository/oidc-provider"),u=class extends l.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="repo",l=this,(n=s)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),this.chart=o.default}hasToken(){return void 0!==this.token.AccessorID}login(){let e=(0,i.get)(this,"previousToken.AccessorID"),t=(0,i.get)(this,"token.AccessorID") +null===e&&(e=(0,i.get)(this,"previousToken.SecretID")),null===t&&(t=(0,i.get)(this,"token.SecretID")) +let n="authorize" +void 0!==e&&e!==t&&(n="use"),this.args.onchange({data:this.token,type:n})}logout(){void 0!==(0,i.get)(this,"previousToken.AuthMethod")&&this.repo.logout((0,i.get)(this,"previousToken.SecretID")),this.previousToken=null,this.args.onchange({data:null,type:"logout"})}},s=c(u.prototype,"repo",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c(u.prototype,"hasToken",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"hasToken"),u.prototype),c(u.prototype,"login",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"login"),u.prototype),c(u.prototype,"logout",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"logout"),u.prototype),u) +e.default=p,(0,t.setComponentTemplate)(d,p)})),define("consul-ui/components/auth-form/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={id:"auth-form",initial:"idle",on:{RESET:[{target:"idle"}],ERROR:[{target:"error"}]},states:{idle:{entry:["clearError"],on:{SUBMIT:[{target:"loading",cond:"hasValue"},{target:"error"}]}},loading:{},error:{exit:["clearError"],on:{TYPING:[{target:"idle"}],SUBMIT:[{target:"loading",cond:"hasValue"},{target:"error"}]}}}}})),define("consul-ui/components/auth-form/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","consul-ui/components/auth-form/chart.xstate","consul-ui/components/auth-form/tabs.xstate"],(function(e,t,n,l,r,i,o){var a +function u(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const s=(0,n.createTemplateFactory)({id:"BOj7IYa9",block:'[[[1,"\\n"],[8,[39,0],null,[["@src"],[[30,0,["chart"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,2],null,[["State","Guard","Action","dispatch","state"],[[30,1],[30,2],[30,3],[30,4],[30,5]]]]],[[[44,[[28,[37,2],null,[["reset","focus","disabled","error","submit"],[[28,[37,3],[[30,0],[30,4],"RESET"],null],[30,0,["focus"]],[28,[37,4],[[30,5],"loading"],null],[28,[37,5],[[28,[37,3],[[30,0],[30,4],"ERROR"],null],[28,[37,3],[[30,0],[28,[37,6],[[30,0,["error"]]],null]],[["value"],["error.errors.firstObject"]]]],null],[28,[37,5],[[28,[37,3],[[30,0],[28,[37,6],[[30,0,["value"]]],null]],null],[28,[37,3],[[30,0],[30,4],"SUBMIT"],null]],null]]]]],[[[1," "],[8,[30,2],null,[["@name","@cond"],["hasValue",[30,0,["hasValue"]]]],null],[1,"\\n"],[1," "],[8,[30,6,["Action"]],null,[["@name","@exec"],["clearError",[28,[37,5],[[28,[37,3],[[30,0],[28,[37,6],[[30,0,["error"]]],null],[27]],null],[28,[37,3],[[30,0],[28,[37,6],[[30,0,["secret"]]],null],[27]],null]],null]]],null],[1,"\\n "],[11,0],[24,0,"auth-form"],[17,8],[12],[1,"\\n "],[8,[39,0],null,[["@src"],[[30,0,["tabsChart"]]]],[["default"],[[[[1,"\\n"],[41,[28,[37,8],["use SSO"],null],[[[1," "],[8,[39,9],null,[["@items","@onclick"],[[28,[37,10],[[28,[37,2],null,[["label","selected"],["Token",[28,[37,4],[[30,13],"token"],null]]]],[28,[37,2],null,[["label","selected"],["SSO",[28,[37,4],[[30,13],"sso"],null]]]]],null],[28,[37,5],[[28,[37,3],[[30,0],[30,12]],null],[28,[37,3],[[30,0],[30,4],"RESET"],null]],null]]],null],[1,"\\n"]],[]],null],[1," "],[8,[30,1],null,[["@matches"],["error"]],[["default"],[[[[1,"\\n"],[41,[30,0,["error","status"]],[[[1," "],[8,[39,11],[[24,0,"mb-1 mt-2"]],[["@type","@color"],["inline","critical"]],[["default"],[[[[1,"\\n "],[8,[30,14,["Title"]],null,null,[["default"],[[[[1,"\\n"],[41,[30,0,["value","Name"]],[[[41,[28,[37,12],[[30,0,["error","status"]],"403"],null],[[[1," Consul login failed\\n"]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"401"],null],[[[1," Could not log in to provider\\n"]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"499"],null],[[[1," SSO log in window closed\\n"]],[]],[[[1," Error\\n "]],[]]]],[]]]],[]]]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"403"],null],[[[1," Invalid token\\n"]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"404"],null],[[[1," No providers\\n"]],[]],[[[1," Error\\n "]],[]]]],[]]]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[30,14,["Description"]],null,null,[["default"],[[[[1,"\\n"],[41,[30,0,["value","Name"]],[[[41,[28,[37,12],[[30,0,["error","status"]],"403"],null],[[[1," We received a token from your OIDC provider but could not log in to Consul\\n with it.\\n"]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"401"],null],[[[1," The OIDC provider has rejected this access token. Please have an\\n administrator check your auth method configuration.\\n"]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"499"],null],[[[1," The OIDC provider window was closed. Please try again.\\n"]],[]],[[[1," "],[1,[30,0,["error","detail"]]],[1,"\\n "]],[]]]],[]]]],[]]]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"403"],null],[[[1," The token entered does not exist. Please enter a valid token to log in.\\n"]],[]],[[[41,[28,[37,12],[[30,0,["error","status"]],"404"],null],[[[1," No SSO providers are configured for that Partition.\\n"]],[]],[[[1," "],[1,[30,0,["error","detail"]]],[1,"\\n "]],[]]]],[]]]],[]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[30,9],null,[["@matches"],["token"]],[["default"],[[[[1,"\\n "],[10,"form"],[15,"onsubmit",[28,[37,3],[[30,0],[30,4],"SUBMIT"],null]],[12],[1,"\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"label"],[15,0,[28,[37,13],["type-password",[52,[28,[37,14],[[28,[37,4],[[30,5],"error"],null],[28,[37,15],[[30,0,["error","status"]]],null]],null]," has-error"]],null]],[12],[1,"\\n "],[10,1],[12],[1,"Log in with a token"],[13],[1,"\\n\\n"],[1," "],[11,"input"],[16,"disabled",[28,[37,4],[[30,5],"loading"],null]],[24,3,"auth[SecretID]"],[24,"placeholder","SecretID"],[16,2,[30,0,["secret"]]],[16,"oninput",[28,[37,5],[[28,[37,3],[[30,0],[28,[37,6],[[30,0,["secret"]]],null]],[["value"],["target.value"]]],[28,[37,3],[[30,0],[28,[37,6],[[30,0,["value"]]],null]],[["value"],["target.value"]]],[28,[37,3],[[30,0],[30,4],"TYPING"],null]],null]],[16,4,[52,[28,[37,12],[[28,[37,16],["environment"],null],"testing"],null],"text","password"]],[4,[38,17],[[28,[37,18],[[30,0],"input"],null]],null],[12],[13],[1,"\\n "],[8,[30,1],null,[["@matches"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,15],[[30,0,["error","status"]]],null],[[[1," "],[10,"strong"],[14,"role","alert"],[12],[1,"\\n Please enter your secret\\n "],[13],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,19],[[16,"disabled",[28,[37,4],[[30,5],"loading"],null]],[24,4,"submit"]],[["@text"],["Log in"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[18,19,[[28,[37,21],[[30,7],[28,[37,2],null,[["Method"],[[30,9]]]]],null]]],[1,"\\n\\n "],[10,"em"],[12],[1,"\\n Contact your administrator for login credentials.\\n "],[13],[1,"\\n "]],[9,10,11,12,13]]]]],[1,"\\n\\n "],[13],[1,"\\n "],[8,[30,1],null,[["@matches"],["loading"]],[["default"],[[[[1,"\\n "],[8,[39,22],null,[["@dc","@nspace","@partition","@type","@value","@onchange","@onerror"],[[30,15],[28,[37,23],[[30,0,["value","Namespace"]],[30,16]],null],[28,[37,23],[[30,0,["value","Partition"]],[30,17]],null],[52,[30,0,["value","Name"]],"oidc","secret"],[30,0,["value"]],[28,[37,5],[[28,[37,3],[[30,0],[30,4],"RESET"],null],[30,18]],null],[28,[37,5],[[28,[37,3],[[30,0],[28,[37,6],[[30,0,["error"]]],null]],[["value"],["error.errors.firstObject"]]],[28,[37,3],[[30,0],[30,4],"ERROR"],null]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[7]]]],[6]]]],[1,2,3,4,5]]]]],[1,"\\n"]],["State","Guard","ChartAction","dispatch","state","chart","exported","&attrs","TabState","IgnoredGuard","IgnoredAction","tabDispatch","tabState","A","@dc","@nspace","@partition","@onsubmit","&default"],false,["state-chart","let","hash","action","state-matches","queue","mut","if","can","tab-nav","array","hds/alert","eq","concat","and","not","env","did-insert","set","hds/button","yield","assign","token-source","or"]]',moduleName:"consul-ui/components/auth-form/index.hbs",isStrictMode:!1}) +let c=(a=class extends l.default{constructor(){super(...arguments),this.chart=i.default,this.tabsChart=o.default}hasValue(e,t,n){return""!==this.value&&void 0!==this.value}focus(){this.input.focus()}},u(a.prototype,"hasValue",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"hasValue"),a.prototype),u(a.prototype,"focus",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"focus"),a.prototype),a) +e.default=c,(0,t.setComponentTemplate)(s,c)})),define("consul-ui/components/auth-form/tabs.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={id:"auth-form-tabs",initial:"token",on:{TOKEN:[{target:"token"}],SSO:[{target:"sso"}]},states:{token:{},sso:{}}}})),define("consul-ui/components/basic-dropdown-content",["exports","ember-basic-dropdown/components/basic-dropdown-content"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) +define("consul-ui/components/basic-dropdown-optional-tag",["exports","ember-basic-dropdown/components/basic-dropdown-optional-tag"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/basic-dropdown-trigger",["exports","ember-basic-dropdown/components/basic-dropdown-trigger"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/basic-dropdown",["exports","ember-basic-dropdown/components/basic-dropdown"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/block-slot",["exports","block-slots/components/block-slot"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/brand-loader/enterprise",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"DW5EhD40",block:'[[[10,"path"],[14,"data-enterprise-logo",""],[14,"d","M322.099,18.0445001 C319.225,18.0223001 316.427,18.9609001 314.148,20.7112001 L314.016,20.8179001 L313.68,18.5368001 L310.332,18.5368001 L310.332,53.0000001 L314.312,52.4338001 L314.312,42.3164001 L314.435,42.3164001 C316.705,42.7693001 319.012,43.0165001 321.327,43.0549001 C326.554,43.0549001 329.098,40.5029001 329.098,35.2432001 L329.098,25.3802001 C329.073,20.4569001 326.809,18.0445001 322.099,18.0445001 Z M264.971,11.9722001 L260.991,12.5466001 L260.991,18.5284001 L256.708,18.5284001 L256.708,21.8106001 L260.991,21.8106001 L260.991,37.6883001 L260.99344,37.9365729 C261.066744,41.6122056 262.7975,43.1124033 266.915,43.1124033 C268.591,43.1170001 270.255,42.8396001 271.839,42.2915001 L271.363,39.1817001 L270.896229,39.3066643 C269.803094,39.5806719 268.682875,39.7315001 267.555,39.7560001 C265.526625,39.7560001 265.081547,38.9674128 264.991981,37.7056542 L264.97743,37.4176027 L264.97159,37.1147428 L264.971,21.8188001 L271.494,21.8188001 L271.83,18.5366001 L264.971,18.5366001 L264.971,11.9722001 Z M283.556,18.0770001 C277.312,18.0770001 274.144,21.0884001 274.144,27.0374001 L274.144,34.3075001 C274.144,40.3140001 277.164,43.1124894 283.655,43.1124894 C286.526,43.1192001 289.38,42.6620001 292.106,41.7581001 L291.589,38.6154001 C289.116,39.3030001 286.566,39.6779001 283.999,39.7314001 C279.785843,39.7314001 278.500803,38.4772648 278.201322,35.860808 L278.165734,35.4868687 L278.141767,35.0951811 C278.138675,35.0284172 278.136019,34.9609111 278.133774,34.8926614 L278.125037,34.474229 L278.124,32.0756001 L292.582,32.0756001 L292.582,27.1031001 C292.582,21.0064001 289.636,18.0770001 283.556,18.0770001 Z M384.631,18.0768001 C378.412,18.0440001 375.22,21.0554001 375.22,27.0208001 L375.22,34.2909001 C375.22,40.2973001 378.239,43.0955988 384.73,43.0955988 C387.599,43.1033001 390.45,42.6460001 393.173,41.7415001 L392.665,38.5988001 C390.188,39.2815001 387.635,39.6509001 385.066,39.6983001 C380.852843,39.6983001 379.567803,38.4442359 379.268322,35.8278014 L379.232734,35.4538649 L379.208767,35.0621794 C379.205675,34.9954158 379.203019,34.9279099 379.200774,34.8596604 L379.192037,34.4412289 L379.191,32.0754001 L393.657,32.0754001 L393.657,27.1029001 C393.657,21.0062001 390.712,18.0768001 384.631,18.0768001 Z M364.634,18.0441001 C363.881125,18.0441001 363.18736,18.0712813 362.54969,18.1279834 L362.016783,18.1838695 C357.948857,18.6791301 356.371,20.5353768 356.371,24.4608001 L356.371522,24.7155013 L356.376145,25.2052033 L356.386527,25.669464 L356.403852,26.1092746 C356.407384,26.1805939 356.411254,26.2509357 356.415488,26.3203208 L356.445451,26.7253144 L356.485319,27.1083357 C356.756619,29.3425283 357.626845,30.4437319 360.247859,31.3753061 L360.701103,31.529163 C360.779411,31.5545991 360.85912,31.5799457 360.940253,31.6052232 L361.444353,31.7562266 L361.983836,31.9065664 L362.55989,32.0572338 L363.430663,32.2724269 L364.440153,32.5299129 L364.884369,32.6506971 L365.29049,32.7679922 L365.660213,32.8831607 L365.99523,32.9975651 C367.26815,33.4554713 367.748817,33.9277406 367.925217,34.806783 L367.963261,35.0352452 C367.974017,35.1143754 367.982943,35.1965576 367.990321,35.2820187 L368.008092,35.5484662 L368.018269,35.8359502 L368.023,36.3096001 C368.023,36.3683432 368.022674,36.4261667 368.021989,36.4830819 L368.013333,36.8137655 C368.008847,36.9204214 368.002676,37.0235359 367.994568,37.1232009 L367.964177,37.4119383 C367.774513,38.8512264 367.058626,39.4837671 364.875404,39.6510671 L364.43427,39.67773 L363.954974,39.6933243 C363.78868,39.6967387 363.615773,39.6984001 363.436,39.6984001 C361.126,39.6638001 358.83,39.3385001 356.601,38.7302001 L356.051,41.7908001 L356.619468,41.9710684 C358.900888,42.6645722 361.270923,43.0269154 363.658,43.0463001 C369.59355,43.0463001 371.402903,41.3625861 371.812159,38.0405419 L371.854011,37.6421573 C371.859965,37.574501 371.865421,37.5062155 371.870401,37.4373012 L371.894725,37.0162715 L371.908596,36.5801656 C371.911587,36.4322862 371.913,36.2818967 371.913,36.1290001 L371.914417,35.5317322 C371.901583,33.4289389 371.677,32.2649251 370.797,31.3698001 C370.053077,30.6022731 368.787947,30.0494771 366.870096,29.4840145 L366.242608,29.3047611 C366.13436,29.2747269 366.024265,29.2445914 365.912304,29.2143213 L365.218,29.0308209 L364.216102,28.7784328 L363.495981,28.593015 L363.068145,28.4733265 L362.67987,28.3551624 C361.018765,27.8247783 360.501056,27.2986662 360.340522,26.2094051 L360.310407,25.9578465 C360.306262,25.9142982 360.302526,25.8699197 360.29916,25.8246823 L360.283089,25.5427193 L360.273984,25.2387571 L360.269927,24.911412 L360.270221,24.3885398 L360.280627,24.0635689 C360.366727,22.3885604 360.966747,21.6370879 363.248047,21.4645754 L363.695778,21.4389299 L364.184625,21.426349 L364.445,21.4248001 C366.684,21.4608001 368.916,21.6859001 371.117,22.0976001 L371.396,18.8646001 L370.730951,18.7059457 C368.73071,18.2553391 366.686,18.0331201 364.634,18.0441001 Z M351.301,18.5363001 L347.321,18.5363001 L347.321,42.6112001 L351.301,42.6112001 L351.301,18.5363001 Z M307.335,18.0850001 L306.70097,18.3638937 C304.598769,19.3169298 302.610091,20.5031364 300.771,21.9005001 L300.623,22.0236001 L300.369,18.5363001 L296.931,18.5363001 L296.931,42.6112001 L300.91,42.6112001 L300.91,25.9048001 L301.641825,25.3925123 C303.604371,24.0427531 305.654445,22.8240667 307.778,21.7446001 L307.335,18.0850001 Z M344.318,18.0850001 L343.683947,18.3638937 C341.581595,19.3169298 339.592091,20.5031364 337.753,21.9005001 L337.606,22.0236001 L337.351,18.5363001 L333.946,18.5363001 L333.946,42.6112001 L337.926,42.6112001 L337.926,25.9048001 L337.967,25.9048001 L338.701162,25.3884311 C340.669963,24.0279284 342.726556,22.7996223 344.859,21.7118001 L344.318,18.0850001 Z M230.384,9.62500005 L211.109,9.62500005 L211.109,42.6112001 L230.466,42.6112001 L230.466,38.9597001 L215.146,38.9597001 L215.146,27.4720001 L229.293,27.4720001 L229.293,23.8698001 L215.146,23.8698001 L215.146,13.2600001 L230.384,13.2600001 L230.384,9.62500005 Z M248.763,18.0441001 C245.899,18.0441001 241.706,19.3323001 239.047,20.6124001 L238.924,20.6698001 L238.522,18.5282001 L235.322,18.5282001 L235.322,42.5704001 L239.302,42.5704001 L239.302,24.2885001 L239.359,24.2885001 C241.919,22.9674001 245.661,21.8268001 247.524,21.8268001 C249.165,21.8268001 249.985,22.5735001 249.985,24.1736001 L249.985,42.5868001 L253.965,42.5868001 L253.965,24.1161001 C253.932,20.0380001 252.25,18.0523001 248.763,18.0441001 Z M321.229,21.5564001 C323.526,21.5564001 325.061,22.2046001 325.061,25.3966001 L325.094,35.2760001 C325.094,38.3121001 323.887,39.6085001 321.057,39.6085001 C318.81,39.5533001 316.572,39.3035001 314.369,38.8618001 L314.287,38.8618001 L314.287,24.4694001 C316.198,22.7311001 318.649,21.7027001 321.229,21.5564001 Z M283.581,21.3264001 C287.372,21.3264001 288.758,22.8855001 288.758,26.7010001 L288.758,28.7934001 L278.149,28.7934001 L278.149,26.7010001 C278.149,22.9839001 279.79,21.3264001 283.581,21.3264001 Z M384.648,21.3262001 C388.431,21.3262001 389.834,22.8852001 389.834,26.7008001 L389.834,28.7932001 L379.224,28.7932001 L379.224,26.7008001 C379.224,22.9837001 380.865,21.3262001 384.648,21.3262001 Z M351.301,8.63220005 L347.321,8.63220005 L347.321,14.4499001 L351.301,14.4499001 L351.301,8.63220005 Z"],[14,"fill-rule","nonzero"],[12],[13],[1,"\\n\\n"]],[],false,[]]',moduleName:"consul-ui/components/brand-loader/enterprise.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/brand-loader/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"yNoyAgqg",block:'[[[10,0],[14,0,"brand-loader"],[15,5,[29,["margin-left: calc(-",[30,1],"px / 2)"]]],[12],[1,"\\n"],[10,"svg"],[15,"width",[29,[[30,1]]]],[14,"height","53"],[14,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[15,"fill",[29,[[30,2]]]],[12],[1,"\\n "],[10,"path"],[14,"d","M32.7240001,0.866235051 C28.6239001,-0.218137949 24.3210001,-0.285465949 20.1890001,0.670096051 C16.0569001,1.62566005 12.2205001,3.57523005 9.01276015,6.34960005 C5.80499015,9.12397005 3.32280015,12.6393001 1.78161015,16.5905001 C0.240433148,20.5416001 -0.313157852,24.8092001 0.168892148,29.0228001 C0.650943148,33.2364001 2.15407015,37.2687001 4.54780015,40.7697001 C6.94153015,44.2707001 10.1535001,47.1346001 13.9050001,49.1128001 C17.6565001,51.0910001 21.8341001,52.1238001 26.0752001,52.1214409 C32.6125001,52.1281001 38.9121001,49.6698001 43.7170001,45.2370001 L37.5547001,38.7957001 C35.0952001,41.0133001 32.0454001,42.4701001 28.7748001,42.9898001 C25.5042001,43.5096001 22.1530001,43.0698001 19.1273001,41.7239001 C16.1015001,40.3779001 13.5308001,38.1835001 11.7267001,35.4064001 C9.92260015,32.6294001 8.96239015,29.3888001 8.96239015,26.0771001 C8.96239015,22.7655001 9.92260015,19.5249001 11.7267001,16.7478001 C13.5308001,13.9707001 16.1015001,11.7763001 19.1273001,10.4304001 C22.1530001,9.08444005 25.5042001,8.64470005 28.7748001,9.16441005 C32.0454001,9.68412005 35.0952001,11.1410001 37.5547001,13.3586001 L43.7170001,6.89263005 C40.5976001,4.01926005 36.8241001,1.95061005 32.7240001,0.866235051 Z M46.6320001,34.8572001 C46.2182001,34.9395001 45.8380001,35.1427001 45.5397001,35.4410001 C45.2413001,35.7394001 45.0381001,36.1195001 44.9558001,36.5334001 C44.8735001,36.9472001 44.9157001,37.3762001 45.0772001,37.7660001 C45.2387001,38.1559001 45.5121001,38.4891001 45.8630001,38.7235001 C46.2138001,38.9579001 46.6263001,39.0830001 47.0482001,39.0830001 C47.6141001,39.0830001 48.1567001,38.8583001 48.5568001,38.4582001 C48.9569001,38.0581001 49.1817001,37.5154001 49.1817001,36.9496001 C49.1817001,36.5276001 49.0565001,36.1152001 48.8221001,35.7643001 C48.5877001,35.4135001 48.2545001,35.1400001 47.8647001,34.9786001 C47.4748001,34.8171001 47.0459001,34.7748001 46.6320001,34.8572001 Z M49.0856001,27.5622001 C48.6718001,27.6446001 48.2916001,27.8477001 47.9933001,28.1461001 C47.6949001,28.4445001 47.4917001,28.8246001 47.4094001,29.2385001 C47.3271001,29.6523001 47.3693001,30.0813001 47.5308001,30.4711001 C47.6923001,30.8609001 47.9657001,31.1941001 48.3166001,31.4286001 C48.6674001,31.6630001 49.0799001,31.7881001 49.5018001,31.7881001 C50.0670001,31.7859001 50.6084001,31.5605001 51.0080001,31.1609001 C51.4076001,30.7612001 51.6331001,30.2198001 51.6353001,29.6547001 C51.6353001,29.2327001 51.5102001,28.8202001 51.2757001,28.4694001 C51.0413001,28.1186001 50.7081001,27.8451001 50.3183001,27.6836001 C49.9284001,27.5222001 49.4995001,27.4799001 49.0856001,27.5622001 Z M28.0728001,20.8457001 C27.0412001,20.4185001 25.9061001,20.3067001 24.8110001,20.5245001 C23.7159001,20.7423001 22.7100001,21.2800001 21.9205001,22.0695001 C21.1309001,22.8590001 20.5933001,23.8650001 20.3754001,24.9600001 C20.1576001,26.0551001 20.2694001,27.1902001 20.6967001,28.2218001 C21.1240001,29.2534001 21.8476001,30.1351001 22.7760001,30.7554001 C23.7043001,31.3757001 24.7958001,31.7068001 25.9124001,31.7068001 C27.4096001,31.7068001 28.8455001,31.1120001 29.9043001,30.0533001 C30.9630001,28.9946001 31.5578001,27.5587001 31.5578001,26.0614001 C31.5578001,24.9449001 31.2267001,23.8534001 30.6063001,22.9250001 C29.9860001,21.9966001 29.1043001,21.2730001 28.0728001,20.8457001 Z M43.9670001,27.4378001 C43.5772001,27.2763001 43.1482001,27.2341001 42.7344001,27.3164001 C42.3205001,27.3987001 41.9404001,27.6019001 41.6420001,27.9003001 C41.3437001,28.1986001 41.1405001,28.5788001 41.0581001,28.9926001 C40.9758001,29.4065001 41.0181001,29.8354001 41.1796001,30.2253001 C41.3410001,30.6151001 41.6145001,30.9483001 41.9653001,31.1827001 C42.3162001,31.4171001 42.7286001,31.5423001 43.1506001,31.5423001 C43.7164001,31.5423001 44.2591001,31.3175001 44.6592001,30.9174001 C45.0592001,30.5173001 45.2840001,29.9747001 45.2840001,29.4088001 C45.2840001,28.9869001 45.1589001,28.5744001 44.9245001,28.2236001 C44.6901001,27.8727001 44.3568001,27.5993001 43.9670001,27.4378001 Z M43.9670001,20.7503001 C43.5772001,20.5888001 43.1482001,20.5466001 42.7344001,20.6289001 C42.3205001,20.7112001 41.9404001,20.9144001 41.6420001,21.2128001 C41.3437001,21.5111001 41.1405001,21.8913001 41.0581001,22.3051001 C40.9758001,22.7190001 41.0181001,23.1479001 41.1796001,23.5378001 C41.3410001,23.9276001 41.6145001,24.2608001 41.9653001,24.4952001 C42.3162001,24.7296001 42.7286001,24.8548001 43.1506001,24.8548001 C43.7164001,24.8548001 44.2591001,24.6300001 44.6592001,24.2299001 C45.0592001,23.8298001 45.2840001,23.2871001 45.2840001,22.7213001 C45.2840001,22.2994001 45.1589001,21.8869001 44.9245001,21.5360001 C44.6901001,21.1852001 44.3568001,20.9118001 43.9670001,20.7503001 Z M49.0856001,20.3825001 C48.6718001,20.4649001 48.2916001,20.6681001 47.9933001,20.9664001 C47.6949001,21.2648001 47.4917001,21.6449001 47.4094001,22.0588001 C47.3271001,22.4726001 47.3693001,22.9016001 47.5308001,23.2914001 C47.6923001,23.6813001 47.9657001,24.0144001 48.3166001,24.2489001 C48.6674001,24.4833001 49.0799001,24.6084001 49.5018001,24.6084001 C50.0670001,24.6063001 50.6084001,24.3808001 51.0080001,23.9812001 C51.4076001,23.5815001 51.6331001,23.0401001 51.6353001,22.4750001 C51.6353001,22.0530001 51.5102001,21.6406001 51.2757001,21.2897001 C51.0413001,20.9389001 50.7081001,20.6654001 50.3183001,20.5040001 C49.9284001,20.3425001 49.4995001,20.3002001 49.0856001,20.3825001 Z M46.7554001,13.2026001 C46.3416001,13.2849001 45.9614001,13.4881001 45.6630001,13.7865001 C45.3647001,14.0849001 45.1615001,14.4650001 45.0792001,14.8788001 C44.9969001,15.2927001 45.0391001,15.7217001 45.2006001,16.1115001 C45.3621001,16.5013001 45.6355001,16.8345001 45.9863001,17.0689001 C46.3372001,17.3034001 46.7497001,17.4285001 47.1716001,17.4285001 C47.7374001,17.4285001 48.2801001,17.2037001 48.6802001,16.8036001 C49.0803001,16.4035001 49.3050001,15.8609001 49.3050001,15.2951001 C49.3050001,14.8731001 49.1799001,14.4606001 48.9455001,14.1098001 C48.7111001,13.7589001 48.3779001,13.4855001 47.9880001,13.3240001 C47.5982001,13.1625001 47.1692001,13.1203001 46.7554001,13.2026001 Z"],[14,"fill-rule","nonzero"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M83.5385001,9.02612084 C75.3002001,9.02612084 71.7718001,12.5545001 71.7718001,18.6102001 L71.7718001,33.5278001 L71.7744126,33.809806 C71.8842215,39.6928981 75.4612111,43.1118103 83.5385001,43.1118103 C86.5802001,43.1131001 89.6109001,42.7466001 92.5646001,42.0205001 L91.8671001,36.6049001 L90.9760579,36.7631811 C88.5964705,37.1629803 86.1899224,37.3844223 83.7765001,37.4254001 C79.4194001,37.4254001 78.0326001,35.9320001 78.0326001,32.4118001 L78.0326001,19.7261001 L78.0346281,19.4988781 C78.0956946,16.133828 79.5462067,14.7125001 83.7765001,14.7125001 C86.4916001,14.7587001 89.1980001,15.0332001 91.8671001,15.5331001 L92.5646001,10.1175001 L91.8246092,9.94345672 C89.1057071,9.33281156 86.3267251,9.02500229 83.5385001,9.02612084 Z M172.149,18.4131001 L166.094,18.4131001 L166.09588,36.2248122 C166.154955,40.3975255 167.61375,43.1117001 171.55,43.1117001 C174.919,42.9517001 178.218,42.0880001 181.233,40.5762001 L181.832,42.6112001 L186.443,42.6112001 L186.443,18.4131001 L180.388,18.4131001 L180.388,35.1934001 C178.188,36.3339001 175.481,37.2283001 174.086,37.2283001 C172.691,37.2283001 172.149,36.5801001 172.149,35.2918001 L172.149,18.4131001 Z M105.939,17.9127001 C98.2719471,17.9127001 95.7845671,21.8519543 95.4516942,26.3358062 L95.4257941,26.7784774 C95.4225999,26.8525088 95.4199581,26.9266566 95.4178553,27.0009059 L95.4116001,27.4475001 L95.4116001,33.5853001 L95.4178331,34.0318054 C95.5519456,38.7818866 97.886685,43.0872001 105.931,43.0872001 C113.716697,43.0872001 116.15821,39.0467642 116.432186,34.4757046 L116.45204,34.0318054 C116.456473,33.8833653 116.458758,33.734491 116.459,33.5853001 L116.459,27.4475001 L116.457455,27.2221358 C116.453317,26.9220505 116.440796,26.6236441 116.419035,26.3278463 L116.379357,25.8862225 C115.91894,21.5651129 113.355121,17.9127001 105.939,17.9127001 Z M154.345,17.8876515 C147.453,17.8876515 145.319,20.0214001 145.319,24.8873001 L145.319694,25.1343997 L145.325703,25.6107983 L145.338905,26.064173 C145.341773,26.1378641 145.344992,26.2106314 145.348588,26.2824927 L145.374889,26.7029295 C145.380095,26.7712375 145.385729,26.838675 145.391816,26.9052596 L145.433992,27.2946761 C145.714183,29.5082333 146.613236,30.7206123 149.232713,31.693068 L149.698825,31.8575665 C150.021076,31.9658547 150.36662,32.0715774 150.737101,32.1758709 L151.311731,32.3313812 C151.509646,32.3829554 151.714,32.4343143 151.925,32.4856001 L152.205551,32.5543061 L152.728976,32.6899356 L153.204098,32.8237311 L153.633238,32.9563441 C155.53221,33.5734587 156.004908,34.1732248 156.112605,35.0535762 L156.130482,35.2466262 L156.139507,35.448917 L156.142,35.6611001 L156.137247,35.9859786 L156.121298,36.2838969 C156.024263,37.5177444 155.540462,38.0172149 153.741624,38.1073495 L153.302742,38.1210314 L153.065,38.1227001 C150.631,38.0987001 148.21,37.7482001 145.869,37.0807001 L145.049,41.6922001 L145.672496,41.887484 C148.174444,42.639635 150.769923,43.0436231 153.385,43.0871001 C159.627887,43.0871001 161.583469,40.9824692 162.030289,37.4548504 L162.074576,37.049455 C162.087289,36.9123213 162.098004,36.7731979 162.106868,36.6321214 L162.128062,36.2030694 L162.139051,35.7625187 L162.141,35.5380001 C162.141,35.4566181 162.140828,35.3763299 162.14046,35.2971136 L162.131203,34.6125174 L162.117224,34.1865271 L162.095649,33.7836378 L162.065324,33.4027996 L162.025093,33.0429627 L161.973799,32.7030773 C161.659145,30.8866498 160.790109,29.9278873 158.501441,29.0408119 L158.069484,28.8801405 L157.605084,28.7199991 C157.524916,28.6932947 157.443348,28.6665687 157.360357,28.6397991 L156.845127,28.4784845 L156.294565,28.3150754 L155.707516,28.148522 L155.082823,27.9777746 L154.035614,27.7021396 L153.423677,27.5325226 L153.071612,27.4262327 C153.016479,27.4088193 152.963082,27.3915263 152.911366,27.3743086 L152.620815,27.2715428 C151.671458,26.912485 151.415595,26.5466416 151.348761,25.7543883 L151.334373,25.5160648 L151.327658,25.2523603 L151.327351,24.8244501 C151.355827,23.4390475 151.851313,22.8769001 154.403,22.8769001 C156.636,22.9360001 158.861,23.1692001 161.057,23.5744001 L161.591,18.7085001 L160.876597,18.5511522 C158.72872,18.1040608 156.5401,17.8816774 154.345,17.8876515 Z M197.71,7.71350005 L191.654,8.53405005 L191.654,42.6116001 L197.71,42.6116001 L197.71,7.71350005 Z M135.455,17.9211001 C132.086,18.0823001 128.788,18.9459001 125.772,20.4566001 L125.189,18.4135001 L120.57,18.4135001 L120.57,42.6115001 L126.625,42.6115001 L126.625,25.8066001 C128.833,24.6661001 131.549,23.7717001 132.936,23.7717001 C134.322,23.7717001 134.872,24.4199001 134.872,25.7082001 L134.872,42.6115001 L140.919,42.6115001 L140.919,25.0681001 C140.919,20.7520001 139.475,17.9211001 135.455,17.9211001 Z M105.931,23.0740001 C109.156,23.0740001 110.395,24.5592001 110.395,27.2506001 L110.395,33.7494001 L110.392134,33.9740961 C110.325067,36.5604698 109.074195,37.9178001 105.931,37.9178001 C102.698,37.9178001 101.459,36.4818001 101.459,33.7494001 L101.459,27.2506001 L101.461884,27.0258853 C101.529372,24.4390811 102.787806,23.0740001 105.931,23.0740001 Z"],[14,"fill-rule","nonzero"],[12],[13],[1,"\\n "],[1,[30,3]],[1,"\\n "],[18,4,null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n"]],["@width","@color","@subtitle","&default"],false,["yield"]]',moduleName:"consul-ui/components/brand-loader/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/child-selector/index",["exports","@ember/component","@ember/template-factory","@ember/object","@ember/object/computed","@ember/service","ember-concurrency","block-slots"],(function(e,t,n,l,r,i,o,a){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const u=(0,n.createTemplateFactory)({id:"MfLIFek0",block:'[[[1,"\\n"],[11,0],[16,0,[29,["child-selector ",[36,0],"-child-selector"]]],[17,1],[12],[1,"\\n"],[18,4,null],[1,"\\n"],[41,[28,[37,3],[[33,4]],null],[[[1," "],[8,[39,5],null,[["@name"],["create"]],[["default"],[[[[18,4,null]],[]]]]],[1,"\\n "],[10,"label"],[14,0,"type-text"],[12],[1,"\\n "],[10,1],[12],[8,[39,5],null,[["@name"],["label"]],[["default"],[[[[18,4,null]],[]]]]],[13],[1,"\\n"],[41,[33,6],[[[1," "],[8,[39,7],null,[["@src","@onchange"],[[28,[37,8],["/${partition}/${nspace}/${dc}/${type}",[28,[37,9],null,[["partition","nspace","dc","type"],[[33,10],[33,11],[33,12],[28,[37,13],[[33,0]],null]]]]],null],[28,[37,14],[[30,0],[28,[37,15],[[33,16]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,17],null,[["@type","@sort","@filters","@items"],[[99,0,["@type"]],"Name:asc",[28,[37,9],null,[["searchproperties"],[[28,[37,18],["Name"],null]]]],[99,19,["@items"]]]],[["default"],[[[[1,"\\n "],[8,[39,20],null,[["@searchEnabled","@search","@options","@loadingMessage","@searchMessage","@searchPlaceholder","@onOpen","@onClose","@onChange"],[true,[28,[37,14],[[30,0],[30,2,["search"]]],null],[28,[37,21],["Name:asc",[33,19]],null],"Loading...","No possible options",[99,22,["@searchPlaceholder"]],[28,[37,14],[[30,0],[28,[37,15],[[33,6]],null],true],null],[28,[37,14],[[30,0],[28,[37,15],[[33,6]],null],false],null],[28,[37,14],[[30,0],"change","items[]",[33,23]],null]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name","@params"],["option",[28,[37,24],[[30,3]],null]]],[["default"],[[[[18,4,null]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n "]],[2]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,25],[[33,23,["length"]],0],null],[[[1," "],[8,[39,5],null,[["@name"],["set"]],[["default"],[[[[18,4,null]],[]]]]],[1,"\\n"]],[]],[[[1,"\\n"]],[]]],[13]],["&attrs","collection","item","&default"],false,["type","yield","if","not","disabled","yield-slot","isOpen","data-source","uri","hash","partition","nspace","dc","pluralize","action","mut","allOptions","data-collection","array","options","power-select","sort-by","placeholder","items","block-params","gt"]]',moduleName:"consul-ui/components/child-selector/index.hbs",isStrictMode:!1}) +var s=(0,t.setComponentTemplate)(u,t.default.extend(a.default,{onchange:function(){},tagName:"",error:function(){},type:"",dom:(0,i.inject)("dom"),formContainer:(0,i.inject)("form"),item:(0,r.alias)("form.data"),selectedOptions:(0,r.alias)("items"),init:function(){this._super(...arguments),this._listeners=this.dom.listeners(),(0,l.set)(this,"form",this.formContainer.form(this.type)),this.form.clear({Datacenter:this.dc,Namespace:this.nspace})},willDestroyElement:function(){this._super(...arguments),this._listeners.remove()},options:(0,l.computed)("selectedOptions.[]","allOptions.[]",(function(){let e=this.allOptions||[] +const t=this.selectedOptions||[] +return(0,l.get)(t,"length")>0&&(e=e.filter((e=>!t.findBy("ID",(0,l.get)(e,"ID"))))),e})),save:(0,o.task)((function(e,t){var n=this +let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){} +return function*(){const r=n.repo +try{e=yield r.persist(e),n.actions.change.apply(n,[{target:{name:"items[]",value:t}},t,e]),l()}catch(i){n.error({error:i})}}()})),actions:{reset:function(){this.form.clear({Datacenter:this.dc,Namespace:this.nspace,Partition:this.partition})},remove:function(e,t){const n=this.repo.getSlugKey(),r=(0,l.get)(e,n),i=t.findIndex((function(e){return(0,l.get)(e,n)===r})) +if(-1!==i)return t.removeAt(i,1) +this.onchange({target:this})},change:function(e,t,n){const r=t +if("items[]"===this.dom.normalizeEvent(...arguments).target.name)(0,l.set)(n,"CreateTime",(new Date).getTime()),r.pushObject(n),this.onchange({target:this})}}})) +e.default=s})),define("consul-ui/components/code-editor/index",["exports","@ember/component","@ember/template-factory","@ember/object","@ember/service"],(function(e,t,n,l,r){function i(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function o(e){for(var t=1;t{let[t]=e +this.oninput((0,l.set)(this,"value",t.target.wholeText))})),this.observer.observe(e,{attributes:!1,subtree:!0,childList:!1,characterData:!0}),(0,l.set)(this,"value",e.firstChild.wholeText)),(0,l.set)(this,"editor",this.helper.getEditor(this.element)),this.settings.findBySlug("code-editor").then((e=>{const t=this.modes,n=this.syntax +n&&(e=t.find((function(e){return e.name.toLowerCase()==n.toLowerCase()}))),e=e||t[0],this.setMode(e)}))},didAppear:function(){this.editor.refresh()},actions:{change:function(e){this.settings.persist({"code-editor":e}),this.setMode(e)}}})) +e.default=c})),define("consul-ui/components/confirmation-alert/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"4XrJqbun",block:'[[[1,"\\n"],[18,5,null],[1,"\\n"],[8,[39,1],[[24,0,"confirmation-alert warning"],[17,1]],null,[["header","body","actions"],[[[[1,"\\n "],[8,[39,2],null,[["@name"],["header"]],[["default"],[[[[18,5,null]],[]]]]],[1,"\\n "]],[]],[[[1,"\\n "],[8,[39,2],null,[["@name"],["body"]],[["default"],[[[[18,5,null]],[]]]]],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,2,["Action"]],[[24,0,"dangerous"]],null,[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name","@params"],["confirm",[28,[37,3],[[50,"action",0,null,[["onclick","tabindex"],[[28,[37,5],[[30,0],[30,3]],null],"-1"]]]],null]]],[["default"],[[[[1,"\\n "],[18,5,null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,2,["Action"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@for"],[[30,4]]],[["default"],[[[[1,"\\n Cancel\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]]],["&attrs","Actions","@onclick","@name","&default"],false,["yield","informed-action","yield-slot","block-params","component","action"]]',moduleName:"consul-ui/components/confirmation-alert/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) +e.default=r})),define("consul-ui/components/confirmation-dialog/index",["exports","@ember/component","@ember/template-factory","block-slots","@ember/object"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i=(0,n.createTemplateFactory)({id:"BPY22wiu",block:'[[[1,"\\n"],[11,0],[16,0,[28,[37,0],["with-confirmation",[52,[33,2]," confirming",""]],null]],[17,1],[12],[1,"\\n"],[18,2,null],[1,"\\n"],[8,[39,4],null,[["@name","@params"],["action",[28,[37,5],[[28,[37,6],[[30,0],"confirm"],null],[28,[37,6],[[30,0],"cancel"],null]],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],[[33,8],[28,[37,9],[[33,2]],null]],null],[[[1," "],[18,2,null],[1,"\\n"]],[]],null]],[]]]]],[1,"\\n"],[8,[39,4],null,[["@name","@params"],["dialog",[28,[37,5],[[28,[37,6],[[30,0],"execute"],null],[28,[37,6],[[30,0],"cancel"],null],[33,10],[33,11]],null]]],[["default"],[[[[1,"\\n"],[41,[33,2],[[[1," "],[18,2,null],[1,"\\n"]],[]],null]],[]]]]],[1,"\\n"],[13]],["&attrs","&default"],false,["concat","if","confirming","yield","yield-slot","block-params","action","or","permanent","not","message","actionName"]]',moduleName:"consul-ui/components/confirmation-dialog/index.hbs",isStrictMode:!1}) +var o=(0,t.setComponentTemplate)(i,t.default.extend(l.default,{tagName:"",message:"Are you sure?",confirming:!1,permanent:!1,actions:{cancel:function(){(0,r.set)(this,"confirming",!1)},execute:function(){(0,r.set)(this,"confirming",!1),this.sendAction("actionName",...this.arguments)},confirm:function(){const[e,...t]=arguments;(0,r.set)(this,"actionName",e),(0,r.set)(this,"arguments",t),(0,r.set)(this,"confirming",!0)}}})) +e.default=o})),define("consul-ui/components/consul-copy-button/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={id:"copy-button",initial:"idle",on:{RESET:[{target:"idle"}]},states:{idle:{on:{SUCCESS:[{target:"success"}],ERROR:[{target:"error"}]}},success:{},error:{}}}})),define("consul-ui/components/consul-copy-button/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","consul-ui/components/consul-copy-button/chart.xstate"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i=(0,n.createTemplateFactory)({id:"WfykRiNj",block:'[[[1,"\\n"],[8,[39,0],null,[["@src"],[[30,0,["chart"]]]],[["default"],[[[[1,"\\n "],[11,0],[24,0,"copy-button"],[17,6],[12],[1,"\\n"],[44,[[28,[37,2],[[30,4],"SUCCESS"],null],[28,[37,2],[[30,4],"ERROR"],null],[28,[37,2],[[30,4],"RESET"],null]],[[[1," "],[11,"button"],[16,"aria-label",[28,[37,3],["components.consul-copy-button.title"],[["name"],[[30,10]]]]],[24,4,"button"],[24,0,"copy-btn"],[17,6],[4,[38,4],[[30,11]],[["success","error"],[[30,7],[30,8]]]],[4,[38,5],[[52,[28,[37,7],[[30,5],"success"],null],[28,[37,3],["components.consul-copy-button.success"],[["name"],[[30,10]]]],[28,[37,3],["components.consul-copy-button.error"],null]]],[["options"],[[28,[37,8],null,[["trigger","showOnCreate","delay","onHidden"],["manual",[28,[37,9],[[28,[37,7],[[30,5],"idle"],null]],null],[28,[37,10],[0,3000],null],[30,9]]]]]]],[12],[18,12,null],[13],[1,"\\n"]],[7,8,9]]],[1," "],[13],[1,"\\n"]],[1,2,3,4,5]]]]],[1,"\\n"]],["State","Guard","Action","dispatch","state","&attrs","success","error","reset","@name","@value","&default"],false,["state-chart","let","fn","t","with-copyable","tooltip","if","state-matches","hash","not","array","yield"]]',moduleName:"consul-ui/components/consul-copy-button/index.hbs",isStrictMode:!1}) +class o extends l.default{constructor(){super(...arguments),this.chart=r.default}}e.default=o,(0,t.setComponentTemplate)(i,o)})),define("consul-ui/components/consul/acl/disabled/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"JlSTtuNT",block:'[[[1,"\\n"],[8,[39,0],null,null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n Tokens\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,2],null,null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"Welcome to ACLs"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n ACLs are not enabled in this Consul cluster. We strongly encourage the use of ACLs in production environments for the best security practices.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,3],null,[["@text","@href","@icon","@iconPosition","@size"],["Read the documentation",[29,[[28,[37,4],["CONSUL_DOCS_URL"],null],"/acl/index.html"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,3],null,[["@text","@href","@icon","@iconPosition","@size"],["Follow the guide",[29,[[28,[37,4],["CONSUL_DOCS_LEARN_URL"],null],"/consul/security-networking/production-acls"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]]],[1,"\\n\\n"]],[],false,["app-view","block-slot","empty-state","hds/link/standalone","env"]]',moduleName:"consul-ui/components/consul/acl/disabled/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/acl/selector/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"S5plMqyM",block:'[[[1,"\\n"],[44,[[30,1]],[[[41,[28,[37,2],["use acls"],null],[[[1," "],[8,[30,2,["Title"]],null,null,[["default"],[[[[1,[28,[35,3],["components.hashicorp-consul.side-nav.acls.title"],null]]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[30,2,["Title"]],[[4,[38,4],[[28,[37,3],["components.hashicorp-consul.side-nav.acls.tooltip"],null]],null]],null,[["default"],[[[[1,"\\n "],[1,[28,[35,3],["components.hashicorp-consul.side-nav.acls.title"],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1,"\\n "],[8,[30,2,["Link"]],null,[["@text","@href","@isHrefExternal","@isActive"],[[28,[37,3],["components.hashicorp-consul.side-nav.acls.tokens"],null],[28,[37,5],["dc.acls.tokens",[30,3,["Name"]]],null],false,[28,[37,6],["dc.acls.tokens",[30,3,["Name"]]],null]]],null],[1,"\\n\\n"],[41,[28,[37,2],["read acls"],null],[[[1," "],[8,[30,2,["Link"]],null,[["@text","@href","@isHrefExternal","@isActive"],[[28,[37,3],["components.hashicorp-consul.side-nav.acls.policies"],null],[28,[37,5],["dc.acls.policies",[30,3,["Name"]]],null],false,[28,[37,6],["dc.acls.policies",[30,3,["Name"]]],null]]],null],[1,"\\n "],[8,[30,2,["Link"]],null,[["@text","@href","@isHrefExternal","@isActive"],[[28,[37,3],["components.hashicorp-consul.side-nav.acls.roles"],null],[28,[37,5],["dc.acls.roles",[30,3,["Name"]]],null],false,[28,[37,6],["dc.acls.roles",[30,3,["Name"]]],null]]],null],[1,"\\n "],[8,[30,2,["Link"]],null,[["@text","@href","@isHrefExternal","@isActive"],[[28,[37,3],["components.hashicorp-consul.side-nav.acls.auth-methods"],null],[28,[37,5],["dc.acls.auth-methods",[30,3,["Name"]]],null],false,[28,[37,6],["dc.acls.auth-methods",[30,3,["Name"]]],null]]],null],[1,"\\n"]],[]],[[[41,[28,[37,7],[[28,[37,2],["use acls"],null]],null],[[[1," "],[8,[30,2,["Item"]],[[24,0,"consul-disabled-nav"]],null,[["default"],[[[[1,"\\n "],[1,[28,[35,3],["components.hashicorp-consul.side-nav.acls.policies"],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,2,["Item"]],[[24,0,"consul-disabled-nav"]],null,[["default"],[[[[1,"\\n "],[1,[28,[35,3],["components.hashicorp-consul.side-nav.acls.roles"],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,2,["Item"]],[[24,0,"consul-disabled-nav"]],null,[["default"],[[[[1,"\\n "],[1,[28,[35,3],["components.hashicorp-consul.side-nav.acls.auth-methods"],null]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]],null]],[]]]],[2]]]],["@list","SNL","@dc"],false,["let","if","can","t","tooltip","href-to","is-href","not"]]',moduleName:"consul-ui/components/consul/acl/selector/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/auth-method/binding-list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"qC1cSJjc",block:'[[[1,"\\n"],[10,0],[14,0,"consul-auth-method-binding-list"],[12],[1,"\\n "],[10,"h2"],[12],[1,[30,1,["BindName"]]],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[14,0,"type"],[12],[1,[28,[35,0],["models.binding-rule.BindType"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,1,["BindType"]]],[1,"\\n "],[10,1],[12],[1,"\\n"],[41,[28,[37,2],[[30,1,["BindType"]],"service"],null],[[[1," "],[8,[39,3],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,0],["components.consul.auth-method.binding-list.bind-type.service"],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[41,[28,[37,2],[[30,1,["BindType"]],"node"],null],[[[1," "],[8,[39,3],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,0],["components.consul.auth-method.binding-list.bind-type.node"],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[41,[28,[37,2],[[30,1,["BindType"]],"role"],null],[[[1," "],[8,[39,3],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,0],["components.consul.auth-method.binding-list.bind-type.role"],null]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]],null]],[]]]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,[28,[35,0],["models.binding-rule.Selector"],null]],[13],[1,"\\n "],[10,"dd"],[12],[10,"code"],[12],[1,[30,1,["Selector"]]],[13],[13],[1,"\\n "],[10,"dt"],[12],[1,[28,[35,0],["models.binding-rule.Description"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,1,["Description"]]],[13],[1,"\\n "],[13],[1,"\\n"],[13]],["@item"],false,["t","if","eq","tooltip"]]',moduleName:"consul-ui/components/consul/auth-method/binding-list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/auth-method/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"d2xDNEp2",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-auth-method-list"]],[["@items"],[[30,1]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],[[30,2,["DisplayName"]],""],null],[[[1," "],[10,3],[15,6,[28,[37,4],["dc.acls.auth-methods.show",[30,2,["Name"]]],null]],[12],[1,"\\n "],[1,[30,2,["DisplayName"]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,6,[28,[37,4],["dc.acls.auth-methods.show",[30,2,["Name"]]],null]],[12],[1,"\\n "],[1,[30,2,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@item"],[[30,2]]],null],[1,"\\n"],[41,[28,[37,3],[[30,2,["DisplayName"]],""],null],[[[1," "],[10,1],[12],[1,[30,2,["Name"]]],[13],[1,"\\n"]],[]],null],[41,[28,[37,6],[[30,2,["TokenLocality"]],"global"],null],[[[1," "],[10,1],[14,0,"locality"],[12],[1,"creates global tokens"],[13],[1,"\\n"]],[]],null],[41,[30,2,["MaxTokenTTL"]],[[[1," "],[10,"dl"],[14,0,"ttl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,7],null,null,[["default"],[[[[1,"\\n Maximum Time to Live: the maximum life of any token created by this auth method\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,2,["MaxTokenTTL"]]],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n"]],[2]]]]],[1,"\\n"]],["@items","item"],false,["list-collection","block-slot","if","not-eq","href-to","consul/auth-method/type","eq","tooltip"]]',moduleName:"consul-ui/components/consul/auth-method/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/auth-method/nspace-list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"5QjjBDlL",block:'[[[1,"\\n"],[10,0],[14,0,"consul-auth-method-nspace-list"],[12],[1,"\\n "],[10,"table"],[12],[1,"\\n "],[10,"thead"],[12],[1,"\\n "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[12],[1,[28,[35,0],["models.auth-method.Selector"],null]],[13],[1,"\\n "],[10,"td"],[12],[1,[28,[35,0],["models.auth-method.BindNamespace"],null]],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"tbody"],[12],[1,"\\n"],[42,[28,[37,2],[[28,[37,2],[[30,1]],null]],null],null,[[[1," "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[12],[1,[30,2,["Selector"]]],[13],[1,"\\n "],[10,"td"],[12],[1,[30,2,["BindNamespace"]]],[13],[1,"\\n "],[13],[1,"\\n"]],[2]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n\\n"]],["@items","item"],false,["t","each","-track-array"]]',moduleName:"consul-ui/components/consul/auth-method/nspace-list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/auth-method/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"Ka2pQgPL",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-auth-method-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.auth-method.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.auth-method.search-bar.",[30,3,["status","key"]],".options.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-kind"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["kind","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.auth-method.search-bar.kind.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[1," "],[8,[30,16],null,[["@value","@selected"],["kubernetes",[28,[37,9],["kubernetes",[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,11],[[24,0,"mr-2.5"]],[["@name"],["kubernetes-color"]],null],[1,"\\n Kubernetes\\n "]],[]]]]],[1,"\\n "],[8,[30,16],[[24,0,"jwt"]],[["@value","@selected"],["jwt",[28,[37,9],["jwt",[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"JWT"]],[]]]]],[1,"\\n"],[41,[28,[37,13],["CONSUL_SSO_ENABLED"],null],[[[1," "],[8,[30,16],[[24,0,"oidc"]],[["@value","@selected"],["oidc",[28,[37,9],["oidc",[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"OIDC"]],[]]]]],[1,"\\n"]],[]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-locality"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["source","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.auth-method.search-bar.locality.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,17,["Optgroup"]],[30,17,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[28,[37,4],["local","global"],null]],null]],null],null,[[[1," "],[8,[30,19],[[16,0,[29,[[30,20]]]]],[["@value","@selected"],[[30,20],[28,[37,9],[[30,20],[30,2,["types"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.auth-method.search-bar.locality.options.",[30,20]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[20]],null]],[18,19]]],[1," "]],[]]]]],[1,"\\n "]],[17]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,21,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,22,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,14],[[28,[37,4],[[28,[37,4],["MethodName:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["MethodName:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["TokenTTL:desc",[28,[37,2],["common.sort.duration.asc"],null]],null],[28,[37,4],["TokenTTL:asc",[28,[37,2],["common.sort.duration.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,15],[[30,24],[30,22,["value"]]],null]],[1,"\\n"]],[24]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,23,["Optgroup"]],[30,23,["Option"]]],[[[1," "],[8,[30,25],null,[["@label"],[[28,[37,2],["common.ui.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,26],null,[["@value","@selected"],["MethodName:asc",[28,[37,16],["MethodName:asc",[30,22,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,26],null,[["@value","@selected"],["MethodName:desc",[28,[37,16],["MethodName:desc",[30,22,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,25],null,[["@label"],[[28,[37,2],["common.ui.maxttl"],null]]],[["default"],[[[[1,"\\n "],[8,[30,26],null,[["@value","@selected"],["TokenTTL:desc",[28,[37,16],["TokenTTL:desc",[30,22,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.duration.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,26],null,[["@value","@selected"],["TokenTTL:asc",[28,[37,16],["TokenTTL:asc",[30,22,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.duration.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[25,26]]],[1," "]],[]]]]],[1,"\\n "]],[23]]]]],[1,"\\n "]],[21]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","components","Optgroup","Option","option","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","flight-icon","if","env","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/auth-method/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/auth-method/type/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"bY+aGPOK",block:'[[[1,"\\n"],[44,[[28,[37,1],[[30,1,["Type"]]],null]],[[[1," "],[10,1],[15,0,[29,["consul-auth-method-type ",[52,[51,[30,2]],[30,1,["Type"]]]]]],[12],[1,"\\n"],[41,[30,2],[[[1," "],[8,[39,4],[[24,0,"mr-1.5 w-4 h-4"]],[["@name"],[[30,2]]],null],[1,"\\n"]],[]],null],[1," "],[1,[28,[35,5],[[28,[37,6],["common.brand.",[30,1,["Type"]]],null]],null]],[1,"\\n "],[13],[1,"\\n"]],[2]]]],["@item","flightIcon"],false,["let","icon-mapping","unless","if","flight-icon","t","concat"]]',moduleName:"consul-ui/components/consul/auth-method/type/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/auth-method/view/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"kcVi1X7l",block:'[[[1,"\\n "],[10,0],[14,0,"consul-auth-method-view"],[12],[1,"\\n"],[41,[28,[37,1],[[30,1,["Type"]],"kubernetes"],null],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Type"],null]],[13],[1,"\\n "],[10,"dd"],[12],[8,[39,3],null,[["@item"],[[30,1]]],null],[13],[1,"\\n\\n"],[42,[28,[37,5],[[28,[37,5],[[28,[37,6],["MaxTokenTTL","TokenLocality","DisplayName","Description"],null]],null]],null],null,[[[41,[28,[37,7],[[30,1],[30,2]],null],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],[[28,[37,8],["models.auth-method.",[30,2]],null]],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,7],[[30,1],[30,2]],null]],[13],[1,"\\n"]],[]],null]],[2]],null],[41,[30,1,["Config","Host"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.Host"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,1,["Config","Host"]],[28,[37,2],["models.auth-method.Config.Host"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","CACert"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.CACert"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@obfuscated","@value","@name"],[true,[30,1,["Config","CACert"]],[28,[37,2],["models.auth-method.Config.CACert"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","ServiceAccountJWT"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.ServiceAccountJWT"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,1,["Config","ServiceAccountJWT"]],[28,[37,2],["models.auth-method.Config.ServiceAccountJWT"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]],[[[1," "],[10,"section"],[14,0,"meta"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Type"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,3],null,[["@item"],[[30,1]]],null],[1,"\\n "],[13],[1,"\\n\\n"],[42,[28,[37,5],[[28,[37,5],[[28,[37,6],["MaxTokenTTL","TokenLocality","DisplayName","Description"],null]],null]],null],null,[[[41,[28,[37,7],[[30,1],[30,3]],null],[[[1,"\\n "],[10,"dt"],[12],[1,[28,[35,2],[[28,[37,8],["models.auth-method.",[30,3]],null]],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,7],[[30,1],[30,3]],null]],[13],[1,"\\n\\n"]],[]],null]],[3]],null],[1,"\\n"],[41,[28,[37,1],[[30,1,["Type"]],"aws-iam"],null],[[[1,"\\n"],[44,[[30,1,["Config"]]],[[[42,[28,[37,5],[[28,[37,5],[[28,[37,6],["BoundIAMPrincipalARNs","EnableIAMEntityDetails","IAMEntityTags","IAMEndpoint","MaxRetries","STSEndpoint","STSRegion","AllowedSTSHeaderValues","ServerIDHeaderValue"],null]],null]],null],null,[[[41,[28,[37,7],[[30,4],[30,5]],null],[[[1,"\\n "],[10,"dt"],[12],[1,[28,[35,2],[[28,[37,8],["models.auth-method.",[30,5]],null]],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[44,[[28,[37,7],[[30,4],[30,5]],null]],[[[41,[28,[37,11],[[30,6]],null],[[[1," "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,6]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,1],[12],[1,[30,7]],[13],[1,"\\n "],[13],[1,"\\n"]],[7]],null],[1," "],[13],[1,"\\n"]],[]],[[[1," "],[1,[30,6]],[1,"\\n"]],[]]]],[6]]],[1," "],[13],[1,"\\n\\n"]],[]],null]],[5]],null],[1,"\\n"]],[4]]],[1,"\\n"]],[]],[[[41,[28,[37,1],[[30,1,["Type"]],"jwt"],null],[[[41,[30,1,["Config","JWKSURL"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.JWKSURL"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,1,["Config","JWKSURL"]],[28,[37,2],["models.auth-method.Config.JWKSURL"],null]]],null],[1,"\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.JWKSCACert"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@obfuscated","@value","@name"],[true,[30,1,["Config","JWKSCACert"]],[28,[37,2],["models.auth-method.Config.JWKSCACert"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","JWTValidationPubKeys"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.JWTValidationPubKeys"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@obfuscated","@value","@name"],[true,[30,1,["Config","JWTValidationPubKeys"]],[28,[37,2],["models.auth-method.Config.JWTValidationPubKeys"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","OIDCDiscoveryURL"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.OIDCDiscoveryURL"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,1,["Config","OIDCDiscoveryURL"]],[28,[37,2],["models.auth-method.Config.OIDCDiscoveryURL"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","JWTSupportedAlgs"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.JWTSupportedAlgs"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,12],[", ",[30,1,["Config","JWTSupportedAlgs"]]],null]],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","BoundAudiences"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.BoundAudiences"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,1,["Config","BoundAudiences"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,1],[12],[1,[30,8]],[13],[1,"\\n "],[13],[1,"\\n"]],[8]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[42,[28,[37,5],[[28,[37,5],[[28,[37,6],["BoundIssuer","ExpirationLeeway","NotBeforeLeeway","ClockSkewLeeway"],null]],null]],null],null,[[[41,[28,[37,7],[[30,1,["Config"]],[30,9]],null],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],[[28,[37,8],["models.auth-method.Config.",[30,9]],null]],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,7],[[30,1,["Config"]],[30,9]],null]],[13],[1,"\\n"]],[]],null]],[9]],null]],[]],[[[41,[28,[37,1],[[30,1,["Type"]],"oidc"],null],[[[41,[30,1,["Config","OIDCDiscoveryURL"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.OIDCDiscoveryURL"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,1,["Config","OIDCDiscoveryURL"]],[28,[37,2],["models.auth-method.Config.OIDCDiscoveryURL"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","OIDCDiscoveryCACert"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.OIDCDiscoveryCACert"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@obfuscated","@value","@name"],[true,[30,1,["Config","OIDCDiscoveryCACert"]],[28,[37,2],["models.auth-method.Config.OIDCDiscoveryCACert"],null]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","OIDCClientID"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.OIDCClientID"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,1,["Config","OIDCClientID"]]],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","OIDCClientSecret"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.OIDCClientSecret"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,1,["Config","OIDCClientSecret"]]],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","AllowedRedirectURIs"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.AllowedRedirectURIs"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,1,["Config","AllowedRedirectURIs"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,10],"Redirect URI"]],null],[1,"\\n "],[13],[1,"\\n"]],[10]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","BoundAudiences"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.BoundAudiences"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,1,["Config","BoundAudiences"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,1],[12],[1,[30,11]],[13],[1,"\\n "],[13],[1,"\\n"]],[11]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","OIDCScopes"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.OIDCScopes"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,1,["Config","OIDCScopes"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,1],[12],[1,[30,12]],[13],[1,"\\n "],[13],[1,"\\n"]],[12]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","JWTSupportedAlgs"]],[[[1," "],[10,"dt"],[12],[1,[28,[35,2],["models.auth-method.Config.JWTSupportedAlgs"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,12],[", ",[30,1,["Config","JWTSupportedAlgs"]]],null]],[13],[1,"\\n"]],[]],null],[41,[30,1,["Config","VerboseOIDCLogging"]],[[[1," "],[10,"dt"],[14,0,"check"],[12],[1,[28,[35,2],["models.auth-method.Config.VerboseOIDCLogging"],null]],[13],[1,"\\n "],[10,"dd"],[12],[10,"input"],[14,"disabled","disabled"],[15,"checked",[30,1,["Config","VerboseOIDCLogging"]]],[14,4,"checkbox"],[12],[13],[13],[1,"\\n"]],[]],null],[1," "]],[]],null]],[]]]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n\\n"],[41,[28,[37,13],[[28,[37,1],[[30,1,["Type"]],"aws-iam"],null]],null],[[[1," "],[10,"hr"],[12],[13],[1,"\\n\\n "],[10,"section"],[14,0,"claim-mappings"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Claim Mappings"],[13],[1,"\\n"],[41,[30,1,["Config","ClaimMappings"]],[[[1," "],[10,2],[12],[1,"Use this if the claim you are capturing is singular. When mapped, the values can be any of a number, string, or boolean and will all be stringified when returned."],[13],[1,"\\n "],[10,"table"],[12],[1,"\\n "],[10,"thead"],[12],[1,"\\n "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[12],[1,"Key"],[13],[1,"\\n "],[10,"td"],[12],[1,"Value"],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"tbody"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[28,[37,14],[[30,1,["Config","ClaimMappings"]]],null]],null]],null],null,[[[1," "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[12],[1,[28,[35,7],[[30,13],0],null]],[13],[1,"\\n "],[10,"td"],[12],[1,[28,[35,7],[[30,13],1],null]],[13],[1,"\\n "],[13],[1,"\\n"]],[13]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[8,[39,15],null,null,[["default"],[[[[1,"\\n "],[8,[39,16],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"No claim mappings"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,16],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"Use this if the claim you are capturing is singular. When mapped, the values can be any of a number, string, or boolean and will all be stringified when returned."],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,16],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"docs-link"],[12],[1,"\\n"],[41,[28,[37,1],[[30,1,["Type"]],"jwt"],null],[[[1," "],[10,3],[15,6,[29,[[28,[37,17],["CONSUL_DOCS_URL"],null],"/security/acl/auth-methods/jwt#claimmappings"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"Read the documentation"],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,6,[29,[[28,[37,17],["CONSUL_DOCS_URL"],null],"/security/acl/auth-methods/oidc#claimmappings"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"Read the documentation"],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n\\n "],[10,"hr"],[12],[13],[1,"\\n\\n "],[10,"section"],[14,0,"list-claim-mappings"],[12],[1,"\\n "],[10,"h2"],[12],[1,"List Claim Mappings"],[13],[1,"\\n"],[41,[30,1,["Config","ListClaimMappings"]],[[[1," "],[10,2],[12],[1,"Use this if the claim you are capturing is list-like (such as groups). When mapped, the values can be any of a number, string, or boolean and will all be stringified when returned."],[13],[1,"\\n "],[10,"table"],[12],[1,"\\n "],[10,"thead"],[12],[1,"\\n "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[12],[1,"Key"],[13],[1,"\\n "],[10,"td"],[12],[1,"Value"],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"tbody"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[28,[37,14],[[30,1,["Config","ListClaimMappings"]]],null]],null]],null],null,[[[1," "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[12],[1,[28,[35,7],[[30,14],0],null]],[13],[1,"\\n "],[10,"td"],[12],[1,[28,[35,7],[[30,14],1],null]],[13],[1,"\\n "],[13],[1,"\\n"]],[14]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[8,[39,15],null,null,[["default"],[[[[1,"\\n "],[8,[39,16],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"No list claim mappings"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,16],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"Use this if the claim you are capturing is list-like (such as groups). When mapped, the values can be any of a number, string, or boolean and will all be stringified when returned."],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,16],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"docs-link"],[12],[1,"\\n"],[41,[28,[37,1],[[30,1,["Type"]],"jwt"],null],[[[1," "],[10,3],[15,6,[29,[[28,[37,17],["CONSUL_DOCS_URL"],null],"/security/acl/auth-methods/jwt#listclaimmappings"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"Read the documentation"],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,6,[29,[[28,[37,17],["CONSUL_DOCS_URL"],null],"/security/acl/auth-methods/oidc#listclaimmappings"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"Read the documentation"],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[]],null]],[]]],[1," "],[13]],["@item","value","value","config","value","item","jtem","bond","value","uri","bond","scope","entry","entry"],false,["if","eq","t","consul/auth-method/type","each","-track-array","array","get","concat","copyable-code","let","array-is-array","join","not","entries","empty-state","block-slot","env"]]',moduleName:"consul-ui/components/consul/auth-method/view/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/bucket/list/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service"],(function(e,t,n,l,r){var i,o +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const a=(0,n.createTemplateFactory)({id:"r6O724Xz",block:'[[[1,"\\n"],[41,[30,0,["itemsToDisplay","length"]],[[[1," "],[10,"dl"],[14,0,"consul-bucket-list"],[12],[1,"\\n"],[42,[28,[37,2],[[28,[37,2],[[30,0,["itemsToDisplay"]]],null]],null],null,[[[1," "],[11,"dt"],[16,0,[30,1,["type"]]],[4,[38,3],null,null],[12],[1,"\\n "],[1,[30,1,["label"]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,1,["item"]]],[1,"\\n "],[13],[1,"\\n"]],[1]],null],[1," "],[13],[1,"\\n"]],[]],null]],["item"],false,["if","each","-track-array","tooltip"]]',moduleName:"consul-ui/components/consul/bucket/list/index.hbs",isStrictMode:!1}) +let u=(i=class extends l.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="abilities",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}get itemsToDisplay(){const{peerOrPartitionPart:e,namespacePart:t,servicePart:n}=this +return[...e,...t,...n]}get peerOrPartitionPart(){const{peerPart:e,partitionPart:t}=this +return e.length?e:t}get partitionPart(){const{item:e,partition:t}=this.args,{abilities:n}=this +return t&&n.can("use partitions")&&e.Partition!==t?[{type:"partition",label:"Admin Partition",item:e.Partition}]:[]}get peerPart(){const{item:e}=this.args +return e.PeerName?[{type:"peer",label:"Peer",item:e.PeerName}]:[]}get namespacePart(){const{item:e,nspace:t}=this.args,{abilities:n,partitionPart:l,peerPart:r}=this,i={type:"nspace",label:"Namespace",item:e.Namespace} +return l.length||r.length&&n.can("use nspaces")||t&&n.can("use nspaces")&&e.Namespace!==t?[i]:[]}get servicePart(){const{item:e,service:t}=this.args,{partitionPart:n,namespacePart:l}=this +return(n.length||l.length)&&e.Service&&t?[{type:"service",label:"Service",item:e.Service}]:[]}},s=i.prototype,c="abilities",d=[r.inject],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),o=m,i) +var s,c,d,p,f,m +e.default=u,(0,t.setComponentTemplate)(a,u)})),define("consul-ui/components/consul/datacenter/selector/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","@glimmer/tracking"],(function(e,t,n,l,r,i){var o,a +function u(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const s=(0,n.createTemplateFactory)({id:"xS/PrPr6",block:'[[[1,"\\n"],[44,[[30,1]],[[[41,[28,[37,2],[[30,3,["length"]],1],null],[[[1," "],[8,[30,2,["Title"]],[[24,0,"consul-side-nav__selector-title"]],null,[["default"],[[[[1,[28,[35,3],["components.hashicorp-consul.side-nav.datacenters.title"],null]]],[]]]]],[1,"\\n "],[8,[39,4],[[24,0,"consul-datacenter-selector"]],[["@list","@items","@item","@key","@icon","@placeholder","@description"],[[30,2],[28,[37,5],["Primary:desc","Local:desc","Name:asc",[30,3]],null],[30,4],"Name","server-cluster",[28,[37,3],["components.hashicorp-consul.side-nav.datacenters.placeholder"],null],[28,[37,3],["components.hashicorp-consul.side-nav.datacenters.description"],null]]],[["default"],[[[[1,"\\n "],[8,[30,5,["Dropdown","Checkmark"]],[[24,0,"consul-datacenter-selector__item"]],[["@selected","@href","@isHrefExternal"],[[28,[37,6],[[30,4,["Name"]],[30,5,["item","Name"]]],null],[28,[37,7],["."],[["params"],[[28,[37,8],null,[["dc","partition","nspace"],[[30,5,["item","Name"]],[27],[52,[28,[37,2],[[30,6,["length"]],0],null],[30,6],[27]]]]]]]],false]],[["default"],[[[[1,"\\n "],[10,1],[14,0,"consul-datacenter-selector__dc-name"],[12],[1,"\\n "],[1,[30,5,["item","Name"]]],[1,"\\n\\n"],[41,[28,[37,9],[[30,5,["item","Local"]],[30,5,["item","Primary"]]],null],[[[1," "],[10,1],[14,0,"consul-datacenter-selector__badges"],[12],[1,"\\n"],[41,[30,5,["item","Primary"]],[[[1," "],[8,[39,10],null,[["@text"],["Primary"]],null],[1,"\\n"]],[]],null],[41,[30,5,["item","Local"]],[[[1," "],[8,[39,10],null,[["@text"],["Local"]],null],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[1," "],[8,[30,2,["Item"]],[[24,0,"consul-side-nav__datacenter"]],null,[["default"],[[[[1,"\\n "],[8,[39,11],null,[["@name","@color"],["server-cluster","var(--token-form-control-disabled-foreground-color)"]],null],[1,"\\n "],[8,[39,12],null,[["@size","@color"],["200","disabled"]],[["default"],[[[[1,[30,4,["Name"]]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]],[2]]]],["@list","SNL","@dcs","@dc","Selector","@nspace"],false,["let","if","gt","t","nav-selector","sort-by","eq","href-to","hash","or","hds/badge","flight-icon","hds/text/display"]]',moduleName:"consul-ui/components/consul/datacenter/selector/index.hbs",isStrictMode:!1}) +let c=(o=class extends l.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="search",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}get filteredItems(){const e=this.search.toLowerCase() +return this.args.dcs.filter((t=>t.Name.toLowerCase().includes(e)))}onSearchInput(e){this.search=e.target.value}},a=u(o.prototype,"search",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return""}}),u(o.prototype,"onSearchInput",[r.action],Object.getOwnPropertyDescriptor(o.prototype,"onSearchInput"),o.prototype),o) +e.default=c,(0,t.setComponentTemplate)(s,c)})),define("consul-ui/components/consul/discovery-chain/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object","consul-ui/components/consul/discovery-chain/utils"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"G/NfZcWn",block:'[[[1,"\\n"],[10,"style"],[12],[1,"\\n"],[41,[33,1,["nodes"]],[[[1," "],[1,[33,1,["nodes"]]],[1,"\\n { opacity: 1 !important; background-color: var(--token-color-surface-interactive); border:\\n var(--decor-border-100); border-radius: var(--decor-radius-200); border-color:\\n var(--token-color-foreground-faint); box-shadow: var(--token-surface-high-box-shadow); }\\n"]],[]],null],[41,[33,1,["edges"]],[[[1," "],[1,[33,1,["edges"]]],[1,"\\n { opacity: 1; }\\n"]],[]],null],[13],[1,"\\n\\n"],[10,0],[14,0,"routes"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[33,2,["ServiceName"]]],[1,"\\n Router\\n "],[11,1],[4,[38,3],["Use routers to intercept traffic using Layer 7 criteria such as path prefixes or http headers."],null],[12],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,"role","group"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[33,6]],null]],null],null,[[[1," "],[8,[39,7],[[4,[38,9],[[28,[37,10],[[28,[37,11],[[30,1],"rect"],null]],[["from"],[[30,0,["edges"]]]]]],null]],[["@item","@onclick"],[[30,1],[28,[37,8],[[30,0],"click"],null]]],null],[1,"\\n"]],[1]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n\\n"],[10,0],[14,0,"splitters"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n Splitters\\n "],[11,1],[4,[38,3],["Splitters are configured to split incoming requests across different services or subsets of a single service."],null],[12],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,"role","group"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[28,[37,12],["Name",[33,13]],null]],null]],null],null,[[[1," "],[8,[39,14],[[4,[38,9],[[28,[37,10],[[28,[37,11],[[30,2],"rect"],null]],[["from"],[[30,0,["edges"]]]]]],null]],[["@item","@onclick"],[[30,2],[28,[37,8],[[30,0],"click"],null]]],null],[1,"\\n"]],[2]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n\\n"],[10,0],[14,0,"resolvers"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n Resolvers\\n "],[11,1],[4,[38,3],["Resolvers are used to define which instances of a service should satisfy discovery requests."],null],[12],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,"role","group"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[28,[37,12],["Name",[33,15]],null]],null]],null],null,[[[1," "],[8,[39,16],[[4,[38,9],[[28,[37,10],[[28,[37,11],[[30,3],"rect"],null]],[["from"],[[30,0,["edges"]]]]]],null]],[["@item","@edges","@onclick"],[[30,3],[30,0,["edges"]],[28,[37,8],[[30,0],"click"],null]]],null],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n\\n"],[1,[34,17]],[1,"\\n\\n"],[11,"svg"],[24,0,"edges"],[24,"width","100%"],[24,"height","100%"],[24,"preserveAspectRatio","none"],[4,[38,18],[[28,[37,11],[[30,0],"edges"],null]],null],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[33,6]],null]],null],null,[[[41,[30,4,["rect"]],[[[44,[[30,4,["rect"]],[30,4,["NextItem","rect"]]],[[[44,[[28,[37,20],[[28,[37,21],null,[["x","y"],[[30,6,["x"]],[28,[37,22],[[30,6,["y"]],[28,[37,23],[[30,6,["height"]],2],null]],null]]]],[28,[37,24],[[30,4,["ID"]]],null]],null]],[[[1,"\\n "],[10,"path"],[15,1,[28,[37,24],[[30,4,["ID"]],">",[30,4,["NextNode"]]],null]],[15,"d",[28,[37,25],[[28,[37,21],null,[["x","y"],[[30,7,["x"]],[28,[37,26],[[30,7,["y"]],0],null]]]]],[["src"],[[28,[37,21],null,[["x","y"],[[30,5,["right"]],[28,[37,22],[[30,5,["y"]],[28,[37,23],[[30,5,["height"]],2],null]],null]]]]]]]],[12],[13],[1,"\\n\\n"]],[7]]]],[5,6]]]],[]],null]],[4]],null],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[33,13]],null]],null],null,[[[41,[30,8,["rect"]],[[[44,[[30,8,["rect"]]],[[[42,[28,[37,5],[[28,[37,5],[[30,8,["Splits"]]],null]],null],null,[[[44,[[30,10,["NextItem","rect"]]],[[[44,[[28,[37,20],[[28,[37,21],null,[["x","y"],[[30,12,["x"]],[28,[37,22],[[30,12,["y"]],[28,[37,23],[[30,12,["height"]],2],null]],null]]]],[28,[37,24],[[30,8,["ID"]],"-",[30,11]],null]],null]],[[[1,"\\n "],[11,"path"],[16,1,[28,[37,24],["splitter:",[30,8,["Name"]],">",[30,10,["NextNode"]]],null]],[24,0,"split"],[16,"d",[28,[37,25],[[28,[37,21],null,[["x","y"],[[30,13,["x"]],[30,13,["y"]]]]]],[["src"],[[28,[37,21],null,[["x","y"],[[30,9,["right"]],[28,[37,22],[[30,9,["y"]],[28,[37,23],[[30,9,["height"]],2],null]],null]]]]]]]],[4,[38,3],[[28,[37,24],[[28,[37,27],[[28,[37,28],[[30,10,["Weight"]],0],null]],[["decimals"],[2]]],"%"],null]],[["options"],[[28,[37,21],null,[["followCursor"],[true]]]]]],[12],[13],[1,"\\n\\n"]],[13]]]],[12]]]],[10,11]],null]],[9]]]],[]],null]],[8]],null],[1,"\\n"],[13],[1,"\\n\\n"],[10,"svg"],[14,0,"resolver-inlets"],[14,"height","100%"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[33,6]],null]],null],null,[[[41,[28,[37,29],[[30,14,["NextNode"]],"resolver:"],null],[[[44,[[28,[37,28],[[30,14,["NextItem","rect"]],[28,[37,21],null,[["y","height"],[0,0]]]],null]],[[[1," "],[10,"circle"],[14,"r","2.5"],[14,"cx","5"],[15,"cy",[28,[37,22],[[30,15,["y"]],[28,[37,23],[[30,15,["height"]],2],null]],null]],[12],[13],[1,"\\n"]],[15]]]],[]],null]],[14]],null],[42,[28,[37,5],[[28,[37,5],[[33,13]],null]],null],null,[[[42,[28,[37,5],[[28,[37,5],[[30,16,["Splits"]]],null]],null],null,[[[44,[[28,[37,28],[[30,17,["NextItem","rect"]],[28,[37,21],null,[["y","height"],[0,0]]]],null]],[[[1," "],[10,"circle"],[14,"r","2.5"],[14,"cx","5"],[15,"cy",[28,[37,22],[[30,18,["y"]],[28,[37,23],[[30,18,["height"]],2],null]],null]],[12],[13],[1,"\\n"]],[18]]]],[17]],null]],[16]],null],[13],[1,"\\n\\n"],[10,"svg"],[14,0,"splitter-inlets"],[14,"height","100%"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[33,6]],null]],null],null,[[[41,[28,[37,29],[[30,19,["NextNode"]],"splitter:"],null],[[[44,[[28,[37,28],[[30,19,["NextItem","rect"]],[28,[37,21],null,[["y","height"],[0,0]]]],null]],[[[1," "],[10,"circle"],[14,"r","2.5"],[14,"cx","5"],[15,"cy",[28,[37,22],[[30,20,["y"]],[28,[37,23],[[30,20,["height"]],2],null]],null]],[12],[13],[1,"\\n"]],[20]]]],[]],null]],[19]],null],[13],[1,"\\n"]],["item","item","item","item","src","destRect","dest","splitter","src","item","index","destRect","dest","item","dest","item","item","dest","item","dest"],false,["if","selected","chain","tooltip","each","-track-array","routes","consul/discovery-chain/route-card","action","on-resize","dom-position","set","sort-by","splitters","consul/discovery-chain/splitter-card","resolvers","consul/discovery-chain/resolver-card","nodes","did-insert","let","tween-to","hash","add","div","concat","svg-curve","sub","round","or","string-starts-with"]]',moduleName:"consul-ui/components/consul/discovery-chain/index.hbs",isStrictMode:!1}) +var a=(0,t.setComponentTemplate)(o,t.default.extend({dom:(0,l.inject)("dom"),ticker:(0,l.inject)("ticker"),dataStructs:(0,l.inject)("data-structs"),classNames:["discovery-chain"],classNameBindings:["active"],selectedId:"",init:function(){this._super(...arguments),this._listeners=this.dom.listeners()},didInsertElement:function(){this._listeners.add(this.dom.document(),{click:e=>{this.dom.closest('[class$="-card"]',e.target)||((0,r.set)(this,"active",!1),(0,r.set)(this,"selectedId",""))}})},willDestroyElement:function(){this._super(...arguments),this._listeners.remove(),this.ticker.destroy(this)},splitters:(0,r.computed)("chain.Nodes",(function(){return(0,i.getSplitters)((0,r.get)(this,"chain.Nodes"))})),routes:(0,r.computed)("chain.Nodes",(function(){const e=(0,i.getRoutes)((0,r.get)(this,"chain.Nodes"),this.dom.guid) +if(!e.find((e=>"/"===(0,r.get)(e,"Definition.Match.HTTP.PathPrefix")))&&!e.find((e=>void 0===e.Definition))){let t +const n=`resolver:${this.chain.ServiceName}.${this.chain.Namespace}.${this.chain.Partition}.${this.chain.Datacenter}`,l=`splitter:${this.chain.ServiceName}.${this.chain.Namespace}.${this.chain.Partition}` +if(void 0!==this.chain.Nodes[l]?t=l:void 0!==this.chain.Nodes[n]&&(t=n),void 0!==t){const n={Default:!0,ID:`route:${this.chain.ServiceName}`,Name:this.chain.ServiceName,Definition:{Match:{HTTP:{PathPrefix:"/"}}},NextNode:t} +e.push((0,i.createRoute)(n,this.chain.ServiceName,this.dom.guid))}}return e})),nodes:(0,r.computed)("routes","splitters","resolvers",(function(){let e=this.resolvers.reduce(((e,t)=>(e[`resolver:${t.ID}`]=t,t.Children.reduce(((e,t)=>(e[`resolver:${t.ID}`]=t,e)),e),e)),{}) +return e=this.splitters.reduce(((e,t)=>(e[t.ID]=t,e)),e),e=this.routes.reduce(((e,t)=>(e[t.ID]=t,e)),e),Object.entries(e).forEach((t=>{let[n,l]=t +void 0!==l.NextNode&&(l.NextItem=e[l.NextNode]),void 0!==l.Splits&&l.Splits.forEach((t=>{void 0!==t.NextNode&&(t.NextItem=e[t.NextNode])}))})),""})),resolvers:(0,r.computed)("chain.{Nodes,Targets}",(function(){return(0,i.getResolvers)(this.chain.Datacenter,this.chain.Partition,this.chain.Namespace,(0,r.get)(this,"chain.Targets"),(0,r.get)(this,"chain.Nodes"))})),graph:(0,r.computed)("splitters","routes.[]",(function(){const e=this.dataStructs.graph() +return this.splitters.forEach((t=>{t.Splits.forEach((n=>{e.addLink(t.ID,n.NextNode)}))})),this.routes.forEach(((t,n)=>{e.addLink(t.ID,t.NextNode)})),e})),selected:(0,r.computed)("selectedId","graph",(function(){if(""===this.selectedId||!this.dom.element(`#${this.selectedId}`))return{} +const e=this.selectedId,t=e.split(":").shift(),n=[e],l=[] +return this.graph.forEachLinkedNode(e,((e,r)=>{n.push(e.id),l.push(`${r.fromId}>${r.toId}`),this.graph.forEachLinkedNode(e.id,((e,r)=>{const i=e.id.split(":").shift() +t!==i&&"splitter"!==t&&"splitter"!==i&&(n.push(e.id),l.push(`${r.fromId}>${r.toId}`))}))})),{nodes:n.map((e=>`#${CSS.escape(e)}`)),edges:l.map((e=>`#${CSS.escape(e)}`))}})),actions:{click:function(e){const t=e.currentTarget.getAttribute("id") +t===this.selectedId?((0,r.set)(this,"active",!1),(0,r.set)(this,"selectedId","")):((0,r.set)(this,"active",!0),(0,r.set)(this,"selectedId",t))}}})) +e.default=a})),define("consul-ui/components/consul/discovery-chain/resolver-card/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"15kmIv+F",block:'[[[1,"\\n"],[10,0],[14,0,"resolver-card"],[12],[1,"\\n "],[11,"header"],[17,1],[16,"onclick",[28,[37,0],[[30,2]],null]],[16,1,[28,[37,1],["resolver:",[30,3,["ID"]]],null]],[12],[1,"\\n "],[10,3],[14,3,""],[12],[1,"\\n "],[10,"h3"],[12],[1,[30,3,["Name"]]],[13],[1,"\\n"],[41,[30,3,["Failover"]],[[[1," "],[10,"dl"],[14,0,"failover"],[12],[1,"\\n "],[11,"dt"],[4,[38,3],[[28,[37,1],[[30,3,["Failover","Type"]]," failover"],null]],null],[12],[1,"\\n "],[1,[28,[35,1],[[30,3,["Failover","Type"]]," failover"],null]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ol"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,3,["Failover","Targets"]]],null]],null],null,[[[1," "],[10,"li"],[12],[10,1],[12],[1,[30,4]],[13],[13],[1,"\\n"]],[4]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,6],[[30,3,["Children","length"]],0],null],[[[1," "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,3,["Children"]]],null]],null],null,[[[1," "],[11,"li"],[16,"onclick",[28,[37,0],[[30,2]],null]],[16,1,[28,[37,1],["resolver:",[30,5,["ID"]]],null]],[4,[38,7],[[28,[37,8],[[28,[37,9],[[30,5],"rect"],null]],[["from"],[[30,6]]]]],null],[12],[1,"\\n "],[10,3],[14,3,""],[12],[1,"\\n"],[41,[30,5,["Redirect"]],[[[1," "],[10,"dl"],[14,0,"redirect"],[12],[1,"\\n "],[11,"dt"],[4,[38,3],[[28,[37,1],[[30,5,["Redirect"]]," redirect"],null]],null],[12],[1,"\\n "],[1,[30,5,["Redirect"]]],[1," redirect\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,5,["Name"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[30,5,["Failover"]],[[[1," "],[10,"dl"],[14,0,"failover"],[12],[1,"\\n "],[11,"dt"],[4,[38,3],[[28,[37,1],[[30,5,["Failover","Type"]]," failover"],null]],null],[12],[1,"\\n "],[1,[30,5,["Failover","Type"]]],[1," failover\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ol"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,5,["Failover","Targets"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,1],[12],[1,[30,7]],[13],[1,"\\n "],[13],[1,"\\n"]],[7]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[]],[[[41,[30,5,["Failover"]],[[[1," "],[1,[30,5,["Name"]]],[1,"\\n "],[10,"dl"],[14,0,"failover"],[12],[1,"\\n "],[11,"dt"],[4,[38,3],[[28,[37,1],[[30,5,["Failover","Type"]]," failover"],null]],null],[12],[1,"\\n "],[1,[28,[35,1],[[30,5,["Failover","Type"]]," failover"],null]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ol"],[12],[1,"\\n"],[42,[28,[37,5],[[28,[37,5],[[30,5,["Failover","Targets"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,1],[12],[1,[30,8]],[13],[1,"\\n "],[13],[1,"\\n"]],[8]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[1,[30,5,["Name"]]],[1,"\\n "]],[]]]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[5]],null],[1," "],[13],[1,"\\n"]],[]],null],[13],[1,"\\n"]],["&attrs","@onclick","@item","item","child","@edges","target","target"],false,["optional","concat","if","tooltip","each","-track-array","gt","on-resize","dom-position","set"]]',moduleName:"consul-ui/components/consul/discovery-chain/resolver-card/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/discovery-chain/route-card/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i=(0,n.createTemplateFactory)({id:"gPMB5AI2",block:'[[[1,"\\n"],[11,3],[24,0,"route-card"],[16,"onclick",[30,1]],[16,1,[30,2,["ID"]]],[17,3],[12],[1,"\\n "],[10,"header"],[15,0,[52,[28,[37,1],[[30,0,["path","value"]],"/"],null],"short"]],[12],[1,"\\n"],[41,[28,[37,2],[[30,2,["Definition","Match","HTTP","Methods","length"]],0],null],[[[1," "],[10,"ul"],[14,0,"match-methods"],[12],[1,"\\n"],[42,[28,[37,4],[[28,[37,4],[[30,2,["Definition","Match","HTTP","Methods"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,[30,4]],[13],[1,"\\n"]],[4]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[1,[30,0,["path","type"]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,0,["path","value"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,2],[[30,2,["Definition","Match","HTTP","Header","length"]],0],null],[[[1," "],[10,"section"],[14,0,"match-headers"],[12],[1,"\\n "],[11,"header"],[4,[38,5],["Header"],null],[12],[1,"\\n "],[10,"h4"],[12],[1,"Headers"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n"],[42,[28,[37,4],[[28,[37,4],[[30,2,["Definition","Match","HTTP","Header"]]],null]],null],null,[[[1," "],[10,"dt"],[12],[1,"\\n "],[1,[30,5,["Name"]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,6],[[30,5]],null]],[1,"\\n "],[13],[1,"\\n"]],[5]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,2],[[30,2,["Definition","Match","HTTP","QueryParam","length"]],0],null],[[[1," "],[10,"section"],[14,0,"match-queryparams"],[12],[1,"\\n "],[11,"header"],[4,[38,5],["Query Params"],null],[12],[1,"\\n "],[10,"h4"],[12],[1,"Query Params"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n"],[42,[28,[37,4],[[28,[37,4],[[30,2,["Definition","Match","HTTP","QueryParam"]]],null]],null],null,[[[1," "],[10,"dt"],[12],[1,"\\n "],[1,[30,6,["Name"]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,6],[[30,6]],null]],[1,"\\n "],[13],[1,"\\n"]],[6]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[13],[1,"\\n"]],["@onclick","@item","&attrs","item","item","item"],false,["if","eq","gt","each","-track-array","tooltip","route-match"]]',moduleName:"consul-ui/components/consul/discovery-chain/route-card/index.hbs",isStrictMode:!1}) +class o extends l.default{get path(){return Object.entries((0,r.get)(this.args.item,"Definition.Match.HTTP")||{}).reduce((function(e,t){let[n,l]=t +return n.toLowerCase().startsWith("path")?{type:n.replace("Path",""),value:l}:e}),{type:"Prefix",value:"/"})}}e.default=o,(0,t.setComponentTemplate)(i,o)})),define("consul-ui/components/consul/discovery-chain/splitter-card/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"JSAcFDJZ",block:'[[[1,"\\n"],[10,0],[12],[1,"\\n "],[11,3],[17,1],[16,1,[30,2,["ID"]]],[24,0,"splitter-card"],[16,"onclick",[28,[37,0],[[30,3]],null]],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h3"],[12],[1,[30,2,["Name"]]],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@item","@onclick"],false,["optional"]]',moduleName:"consul-ui/components/consul/discovery-chain/splitter-card/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/discovery-chain/utils",["exports"],(function(e){function t(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function n(e){for(var n=1;n0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1?arguments[1]:void 0 +return Object.values(e).filter((e=>e.Type===t))},i=function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"default",l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"default",r=arguments.length>4?arguments[4]:void 0 +return void 0===e[t]&&(e[t]={ID:`${t}.${n}.${l}.${r}`,Name:t,Children:[]}),e[t]},o=function(e,t){let n +const l=e.map((function(e){const[l,r]=[t,e].map((e=>e.split(".").reverse())),i=["Datacenter","Partition","Namespace","Service","Subset"] +return r.find((function(e,t){const r=e!==l[t] +return r&&(n=i[t]),r}))})) +return{Type:n,Targets:l}} +e.getAlternateServices=o +e.getSplitters=function(e){return r(e,"splitter").map((function(e){const t=e.Name.split(".") +return t.reverse(),t.shift(),t.shift(),t.reverse(),n(n({},e),{},{ID:`splitter:${e.Name}`,Name:t.join(".")})}))} +e.getRoutes=function(e,t){return r(e,"router").reduce((function(e,n){return e.concat(n.Routes.map((function(e,l){return a(e,n.Name,t)})))}),[])} +e.getResolvers=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"default",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"default",l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{} +const a={} +return Object.values(r).filter((e=>"resolver"===e.Type)).forEach((function(l){const r=l.Name.split(".") +let u +r.length>4&&(u=r.shift()),r.reverse(),r.shift(),r.shift(),r.shift(),r.reverse() +const s=r.join("."),c=i(a,s,n,t,e) +let d +if(void 0!==l.Resolver.Failover&&(d=o(l.Resolver.Failover.Targets,l.Name)),u){const e={Subset:!0,ID:l.Name,Name:u} +void 0!==d&&(e.Failover=d),c.Children.push(e)}else void 0!==d&&(c.Failover=d)})),Object.values(l).forEach((l=>{if(void 0!==r[`resolver:${l.ID}`]){const u=o([l.ID],`service.${n}.${t}.${e}`) +if("Service"!==u.Type){const s=i(a,l.Service,n,t,e),c={Redirect:u.Type,ID:l.ID,Name:l[u.Type]} +void 0!==r[`resolver:${l.ID}`].Resolver.Failover&&(c.Failover=o(r[`resolver:${l.ID}`].Resolver.Failover.Targets,l.ID)),s.Children.push(c)}}})),Object.values(a)} +const a=function(e,t,l){return n(n({},e),{},{Default:e.Default||void 0===e.Definition.Match,ID:`route:${t}-${l(e.Definition)}`})} +e.createRoute=a})),define("consul-ui/components/consul/exposed-path/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"vg28qIfG",block:'[[[1,"\\n"],[11,0],[24,0,"consul-exposed-path-list"],[17,1],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,1],[[28,[37,1],[[30,2]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,0],[14,0,"header"],[12],[1,"\\n"],[44,[[28,[37,3],[[30,4],":",[30,3,["ListenerPort"]],[30,3,["Path"]]],null]],[[[1," "],[10,2],[14,0,"combined-address"],[12],[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[30,5]],[1,"\\n "],[13],[1,"\\n "],[8,[39,4],null,[["@value","@name"],[[30,5],"Address"]],null],[1,"\\n "],[13],[1,"\\n"]],[5]]],[1," "],[13],[1,"\\n "],[10,0],[14,0,"detail"],[12],[1,"\\n"],[41,[30,3,["Protocol"]],[[[1," "],[10,"dl"],[14,0,"protocol"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,6],null,null,[["default"],[[[[1,"\\n Protocol\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Protocol"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,3,["ListenerPort"]],[[[1," "],[10,"dl"],[14,0,"port"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,6],null,null,[["default"],[[[[1,"\\n Listener Port\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n listening on :"],[1,[30,3,["ListenerPort"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,3,["LocalPathPort"]],[[[1," "],[10,"dl"],[14,0,"port"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,6],null,null,[["default"],[[[[1,"\\n Local Path Port\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n local port :"],[1,[30,3,["LocalPathPort"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,3,["Path"]],[[[1," "],[10,"dl"],[14,0,"path"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,6],null,null,[["default"],[[[[1,"\\n Path\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Path"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@items","path","@address","combinedAddress"],false,["each","-track-array","let","concat","consul-copy-button","if","tooltip"]]',moduleName:"consul-ui/components/consul/exposed-path/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/external-source/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"uG5lBIhe",block:'[[[1,"\\n"],[41,[30,1],[[[44,[[28,[37,2],[[30,1]],null]],[[[41,[28,[37,3],[[30,3],[28,[37,4],[[30,2],"consul-api-gateway"],null]],null],[[[1," "],[10,"dl"],[14,0,"tooltip-panel"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[11,1],[24,0,"consul-external-source"],[17,4],[12],[1,"\\n "],[8,[39,5],[[24,0,"mr-1.5 w-4 h-4"]],[["@name"],[[28,[37,6],[[30,2]],null]]],null],[1,"\\n Registered via "],[1,[28,[35,7],[[28,[37,8],["common.brand.",[30,2]],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@position","@menu"],["left",false]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@name"],["header"]],[["default"],[[[[1,"\\n API Gateways manage north-south traffic from external services to services in the Datacenter. For more information, read our documentation.\\n "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,"role","separator"],[12],[1,"\\n About "],[1,[28,[35,7],[[28,[37,8],["common.brand.",[30,2]],null]],null]],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[14,"role","none"],[14,0,"learn-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,8],[[28,[37,11],["CONSUL_DOCS_LEARN_URL"],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n Learn guides\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[41,[30,2],[[[1," "],[11,1],[24,0,"consul-external-source"],[17,4],[12],[1,"\\n "],[8,[39,5],[[24,0,"mr-1.5 h-4 w-4"]],[["@name","@color"],[[28,[37,6],[[30,2]],null],"var(--token-color-hashicorp-brand)"]],null],[1,"\\n"],[41,[30,5],[[[1," "],[1,[30,5]],[1,"\\n"]],[]],[[[1," Registered via "],[1,[28,[35,7],[[28,[37,8],["common.brand.",[30,2]],null]],null]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]],null]],[]]]],[2]]]],[]],null]],["@item","externalSource","@withInfo","&attrs","@label"],false,["if","let","service/external-source","and","eq","flight-icon","icon-mapping","t","concat","menu-panel","block-slot","env"]]',moduleName:"consul-ui/components/consul/external-source/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/health-check/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"1WWZf50M",block:'[[[1,"\\n"],[11,0],[24,0,"consul-health-check-list"],[17,1],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,1],[[28,[37,1],[[30,2]],null]],null],null,[[[1," "],[10,"li"],[15,0,[28,[37,2],["health-check-output ",[30,3,["Status"]]],null]],[12],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,[30,3,["Name"]]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n"],[41,[28,[37,4],[[30,3,["Kind"]],"node"],null],[[[1," "],[10,"dt"],[12],[1,"NodeName"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,3,["Node"]]],[13],[1,"\\n"]],[]],[[[1," "],[10,"dt"],[12],[1,"ServiceName"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,3,["ServiceName"]]],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"CheckID"],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,5],[[30,3,["CheckID"]],"-"],null]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Type"],[13],[1,"\\n "],[10,"dd"],[14,"data-health-check-type",""],[12],[1,"\\n "],[1,[30,3,["Type"]]],[1,"\\n"],[41,[30,3,["Exposed"]],[[[1," "],[11,"em"],[4,[38,6],["Expose.checks is set to true, so all registered HTTP and gRPC check paths are exposed through Envoy for the Consul agent."],null],[12],[1,"Exposed"],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Notes"],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,5],[[30,3,["Notes"]],"-"],null]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Output"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"pre"],[12],[10,"code"],[12],[1,[30,3,["Output"]]],[13],[13],[1,"\\n "],[8,[39,7],null,[["@value","@name"],[[30,3,["Output"]],"output"]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@items","item"],false,["each","-track-array","concat","if","eq","or","tooltip","consul-copy-button"]]',moduleName:"consul-ui/components/consul/health-check/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})) +define("consul-ui/components/consul/health-check/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"vj3AOTz9",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-healthcheck-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.health-check.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.health-check.search-bar.",[30,3,["status","key"]],".options.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n"],[41,[30,2,["searchproperty"]],[[[1," "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,10],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,11],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-status"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["status","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.consul.status"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["passing","warning","critical","empty"],null]],null]],null],null,[[[1," "],[8,[30,16],[[16,0,[29,["value-",[30,17]]]]],[["@value","@selected"],[[30,17],[28,[37,10],[[30,17],[30,2,["status","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[30,17]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,17]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n"],[41,[30,2,["kind"]],[[[1," "],[8,[30,13,["Select"]],[[24,0,"type-kind"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["kind","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.health-check.search-bar.kind.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,18,["Optgroup"]],[30,18,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["service","node"],null]],null]],null],null,[[[1," "],[8,[30,20],null,[["@value","@selected"],[[30,21],[28,[37,10],[[30,21],[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.health-check.search-bar.kind.options.",[30,21]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,21]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[21]],null]],[19,20]]],[1," "]],[]]]]],[1,"\\n "]],[18]]]]],[1,"\\n"]],[]],null],[1," "],[8,[30,13,["Select"]],[[24,0,"type-check"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["check","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.health-check.search-bar.check.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,22,["Optgroup"]],[30,22,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["alias","docker","grpc","http","script","serf","tcp","ttl"],null]],null]],null],null,[[[1," "],[8,[30,24],null,[["@value","@selected"],[[30,25],[28,[37,10],[[30,25],[30,2,["check","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.health-check.search-bar.check.options.",[30,25]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,25]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[25]],null]],[23,24]]],[1," "]],[]]]]],[1,"\\n "]],[22]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,26,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,27,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,12],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["Status:asc",[28,[37,2],["common.sort.status.asc"],null]],null],[28,[37,4],["Status:desc",[28,[37,2],["common.sort.status.desc"],null]],null],[28,[37,4],["Kind:asc",[28,[37,2],["components.consul.health-check.search-bar.sort.kind.asc"],null]],null],[28,[37,4],["Kind:desc",[28,[37,2],["components.consul.health-check.search-bar.sort.kind.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,13],[[30,29],[30,27,["value"]]],null]],[1,"\\n"]],[29]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,28,["Optgroup"]],[30,28,["Option"]]],[[[1," "],[8,[30,30],null,[["@label"],[[28,[37,2],["common.consul.status"],null]]],[["default"],[[[[1,"\\n "],[8,[30,31],null,[["@value","@selected"],["Status:asc",[28,[37,14],["Status:asc",[30,27,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,31],null,[["@value","@selected"],["Status:desc",[28,[37,14],["Status:desc",[30,27,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,30],null,[["@label"],[[28,[37,2],["components.consul.health-check.search-bar.sort.name.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,31],null,[["@value","@selected"],["Name:asc",[28,[37,14],["Name:asc",[30,27,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,31],null,[["@value","@selected"],["Name:desc",[28,[37,14],["Name:desc",[30,27,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,30],null,[["@label"],[[28,[37,2],["components.consul.health-check.search-bar.sort.kind.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,31],null,[["@value","@selected"],["Kind:asc",[28,[37,14],["Kind:asc",[30,27]],null]]],[["default"],[[[[1,"Service to Node"]],[]]]]],[1,"\\n "],[8,[30,31],null,[["@value","@selected"],["Kind:desc",[28,[37,14],["Kind:desc",[30,27]],null]]],[["default"],[[[[1,"Node to Service"]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[30,31]]],[1," "]],[]]]]],[1,"\\n "]],[28]]]]],[1,"\\n "]],[26]]]]]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","state","components","Optgroup","Option","item","components","Optgroup","Option","item","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","if","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/health-check/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/instance-checks/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"AKBTKkHH",block:'[[[1,"\\n"],[44,[[28,[37,1],["Status",[28,[37,2],[[30,1],[28,[37,3],null,null]],null]],null]],[[[44,[[28,[37,2],[[52,[28,[37,5],[[30,2,["critical","length"]],0],null],[30,2,["critical"]]],[52,[28,[37,5],[[30,2,["warning","length"]],0],null],[30,2,["warning"]]],[52,[28,[37,5],[[30,2,["passing","length"]],0],null],[30,2,["passing"]]],[28,[37,3],null,null]],null]],[[[44,[[30,3,["firstObject","Status"]]],[[[1," "],[11,"dl"],[16,0,[28,[37,6],["consul-instance-checks",[28,[37,3],["empty",[28,[37,7],[[30,3,["length"]],0],null]],null],[28,[37,3],[[30,4],[28,[37,8],[[30,3,["length"]],0],null]],null]],null]],[17,5],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,9],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,10],[[30,6]],null]],[1," Checks\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[44,[[28,[37,2],[[52,[28,[37,7],[[30,4],"critical"],null],"failing"],[52,[28,[37,7],[[30,4],"warning"],null],"with a warning"],[30,4]],null]],[[[1," "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,2],[[52,[28,[37,7],[[30,3,["length"]],0],null],[28,[37,11],["No ",[30,6]," checks"],null]],[52,[28,[37,7],[[30,3,["length"]],[30,1,["length"]]],null],[28,[37,11],["All ",[30,6]," checks ",[30,7]],null]],[28,[37,11],[[30,3,["length"]],"/",[30,1,["length"]]," ",[30,6]," checks ",[30,7]],null]],null]],[1,"\\n "],[13],[1,"\\n"]],[7]]],[1," "],[13],[1,"\\n"]],[4]]]],[3]]]],[2]]]],["@items","grouped","checks","status","&attrs","@type","humanized"],false,["let","group-by","or","array","if","gt","class-map","eq","not-eq","tooltip","capitalize","concat"]]',moduleName:"consul-ui/components/consul/instance-checks/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/intention/form/fieldsets/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"8Nb+ToX7",block:'[[[1,"\\n"],[11,0],[17,1],[24,0,"consul-intention-fieldsets"],[12],[1,"\\n "],[10,"fieldset"],[15,"disabled",[36,0]],[12],[1,"\\n "],[10,0],[14,"role","group"],[12],[1,"\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Source"],[13],[1,"\\n "],[10,"label"],[15,0,[29,["type-select",[52,[33,2,["error","SourceName"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Source Service"],[13],[1,"\\n "],[8,[39,3],null,[["@disabled","@options","@searchField","@selected","@searchPlaceholder","@buildSuggestion","@showCreateWhen","@onCreate","@onChange"],[[28,[37,4],[[33,5]],null],[99,6,["@options"]],"Name",[99,7,["@selected"]],"Type service name",[28,[37,8],[[30,0],"createNewLabel","Use a Consul Service called \'{{term}}\'"],null],[28,[37,8],[[30,0],"isUnique",[33,6]],null],[28,[37,8],[[30,0],[33,9],"SourceName"],null],[28,[37,8],[[30,0],[33,9],"SourceName"],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],[[30,2,["Name"]],"*"],null],[[[1," * (All Services)\\n"]],[]],[[[1," "],[1,[30,2,["Name"]]],[1,"\\n"]],[]]],[1," "]],[2]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[10,"em"],[12],[1,"Search for an existing service, or enter any Service name."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"],[41,[28,[37,11],["choose nspaces"],null],[[[1," "],[10,"label"],[15,0,[29,["type-select",[52,[33,2,["error","SourceNS"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Source Namespace"],[13],[1,"\\n "],[8,[39,3],null,[["@disabled","@options","@selected","@searchPlaceholder","@buildSuggestion","@showCreateWhen","@onCreate","@onChange"],[[28,[37,4],[[33,5]],null],[99,12,["@options"]],[99,13,["@selected"]],"Type namespace name",[28,[37,8],[[30,0],"createNewLabel","Use a Consul Namespace called \'{{term}}\'"],null],[28,[37,8],[[30,0],"isUnique",[33,12]],null],[28,[37,8],[[30,0],[33,9],"SourceNS"],null],[28,[37,8],[[30,0],[33,9],"SourceNS"],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],[[30,3,["Name"]],"*"],null],[[[1," * (All Namespaces)\\n"]],[]],[[[1," "],[1,[30,3,["Name"]]],[1,"\\n"]],[]]],[1," "]],[3]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[10,"em"],[12],[1,"Search for an existing namespace, or enter any Namespace name."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]],null],[41,[28,[37,11],["choose partitions"],[["dc"],[[30,4]]]],[[[1," "],[10,"label"],[15,0,[29,["type-select",[52,[33,2,["error","SourcePartition"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Source Partition"],[13],[1,"\\n "],[8,[39,3],null,[["@disabled","@options","@selected","@searchPlaceholder","@buildSuggestion","@showCreateWhen","@onCreate","@onChange"],[[28,[37,4],[[33,5]],null],[99,14,["@options"]],[99,15,["@selected"]],"Type partition name",[28,[37,8],[[30,0],"createNewLabel","Use a Consul Partition called \'{{term}}\'"],null],[28,[37,8],[[30,0],"isUnique",[33,14]],null],[28,[37,8],[[30,0],[33,9],"SourcePartition"],null],[28,[37,8],[[30,0],[33,9],"SourcePartition"],null]]],[["default"],[[[[1,"\\n "],[1,[30,5,["Name"]]],[1,"\\n "]],[5]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[10,"em"],[12],[1,"Search for an existing partition, or enter any Partition name."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Destination"],[13],[1,"\\n "],[10,"label"],[15,0,[29,["type-select",[52,[33,2,["error","DestinationName"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Destination Service"],[13],[1,"\\n "],[8,[39,3],null,[["@disabled","@options","@searchField","@selected","@searchPlaceholder","@buildSuggestion","@showCreateWhen","@onCreate","@onChange"],[[28,[37,4],[[33,5]],null],[99,6,["@options"]],"Name",[99,16,["@selected"]],"Type service name",[28,[37,8],[[30,0],"createNewLabel","Use a Consul Service called \'{{term}}\'"],null],[28,[37,8],[[30,0],"isUnique",[33,6]],null],[28,[37,8],[[30,0],[33,9],"DestinationName"],null],[28,[37,8],[[30,0],[33,9],"DestinationName"],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],[[30,6,["Name"]],"*"],null],[[[1," * (All Services)\\n"]],[]],[[[1," "],[1,[30,6,["Name"]]],[1,"\\n"]],[]]],[1," "]],[6]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[10,"em"],[12],[1,"Search for an existing service, or enter any Service name."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"],[41,[28,[37,11],["choose nspaces"],null],[[[1," "],[10,"label"],[15,0,[29,["type-select",[52,[33,2,["error","DestinationNS"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Destination Namespace"],[13],[1,"\\n "],[8,[39,3],null,[["@disabled","@options","@searchField","@selected","@searchPlaceholder","@buildSuggestion","@showCreateWhen","@onCreate","@onChange"],[[28,[37,4],[[33,5]],null],[99,12,["@options"]],"Name",[99,17,["@selected"]],"Type namespace name",[28,[37,8],[[30,0],"createNewLabel","Use a future Consul Namespace called \'{{term}}\'"],null],[28,[37,8],[[30,0],"isUnique",[33,12]],null],[28,[37,8],[[30,0],[33,9],"DestinationNS"],null],[28,[37,8],[[30,0],[33,9],"DestinationNS"],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],[[30,7,["Name"]],"*"],null],[[[1," * (All Namespaces)\\n"]],[]],[[[1," "],[1,[30,7,["Name"]]],[1,"\\n"]],[]]],[1," "]],[7]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[10,"em"],[12],[1,"For the destination, you may choose any namespace for which you have access."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]],null],[41,[28,[37,11],["choose partitions"],[["dc"],[[30,4]]]],[[[1," "],[10,"label"],[15,0,[29,["type-select",[52,[33,2,["error","DestinationPartition"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Destination Partition"],[13],[1,"\\n "],[8,[39,3],null,[["@disabled","@options","@searchField","@selected","@searchPlaceholder","@buildSuggestion","@showCreateWhen","@onCreate","@onChange"],[[28,[37,4],[[33,5]],null],[99,14,["@options"]],"Name",[99,18,["@selected"]],"Type partition name",[28,[37,8],[[30,0],"createNewLabel","Use a future Consul Partition called \'{{term}}\'"],null],[28,[37,8],[[30,0],"isUnique",[33,14]],null],[28,[37,8],[[30,0],[33,9],"DestinationPartition"],null],[28,[37,8],[[30,0],[33,9],"DestinationPartition"],null]]],[["default"],[[[[1,"\\n "],[1,[30,8,["Name"]]],[1,"\\n "]],[8]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[10,"em"],[12],[1,"For the destination, you may choose any partition for which you have access."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"label"],[15,0,[29,["type-text",[52,[33,2,["error","Description"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Description (Optional)"],[13],[1,"\\n "],[10,"input"],[14,3,"Description"],[15,2,[33,2,["Description"]]],[14,"placeholder","Description (Optional)"],[15,"onchange",[28,[37,8],[[30,0],[33,9]],null]],[14,4,"text"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,1],[14,0,"label"],[12],[1,"Should this source connect to the destination?"],[13],[1,"\\n "],[10,0],[14,"role","radiogroup"],[15,0,[52,[33,2,["error","Action"]]," has-error"]],[12],[1,"\\n"],[42,[28,[37,20],[[28,[37,20],[[28,[37,21],[[28,[37,22],null,[["intent","header","body"],["allow","Allow","The source service will be allowed to connect to the destination."]]],[28,[37,22],null,[["intent","header","body"],["deny","Deny","The source service will not be allowed to connect to the destination."]]],[28,[37,22],null,[["intent","header","body"],["","Application Aware","The source service may or may not connect to the destination service via unique permissions based on Layer 7 criteria: path, header, or method."]]]],null]],null]],null],null,[[[1," "],[8,[39,23],[[16,0,[28,[37,24],["value-",[30,9,["intent"]]],null]]],[["@value","@checked","@onchange","@name"],[[30,9,["intent"]],[52,[28,[37,10],[[28,[37,25],[[33,2,["Action"]],""],null],[30,9,["intent"]]],null],"checked"],[28,[37,8],[[30,0],[33,9]],null],"Action"]],[["default"],[[[[1,"\\n "],[10,"header"],[12],[1,"\\n "],[1,[30,9,["header"]]],[1,"\\n "],[13],[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[30,9,["body"]]],[1,"\\n "],[13],[1,"\\n "]],[10]]]]],[1,"\\n"]],[9]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,10],[[28,[37,25],[[33,2,["Action"]],""],null],""],null],[[[1," "],[10,"fieldset"],[14,0,"permissions"],[12],[1,"\\n "],[8,[39,26],[[4,[38,27],["click",[28,[37,8],[[30,0],[30,0,["openModal"]]],null]],null]],[["@text","@size","@color","@icon"],["Add permission","small","tertiary","plus"]],null],[1,"\\n "],[10,"h2"],[12],[1,"Permissions"],[13],[1,"\\n"],[41,[28,[37,28],[[33,2,["Permissions","length"]],0],null],[[[1," "],[8,[39,29],null,null,null],[1,"\\n "],[8,[39,30],null,[["@items","@onclick","@ondelete"],[[33,2,["Permissions"]],[28,[37,31],[[28,[37,8],[[30,0],[28,[37,32],[[33,33]],null]],null],[28,[37,8],[[30,0],[30,0,["openModal"]]],null]],null],[28,[37,8],[[30,0],"delete","Permissions",[33,2]],null]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,34],null,null,[["default"],[[[[1,"\\n "],[8,[39,35],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h3"],[12],[1,"\\n No permissions yet\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,35],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Permissions intercept an Intention\'s traffic using Layer 7 criteria, such as path prefixes and http headers.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,35],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,36],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation",[29,[[28,[37,37],["CONSUL_DOCS_URL"],null],"/commands/intention"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,36],null,[["@text","@href","@icon","@iconPosition","@size"],["Read the guide",[29,[[28,[37,37],["CONSUL_DOCS_LEARN_URL"],null],"/consul/getting-started/connect"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,38],[[24,0,"consul-intention-permission-modal"]],[["@onclose","@aria"],[[28,[37,8],[[30,0],[28,[37,32],[[33,33]],null],[27]],null],[28,[37,22],null,[["label"],["Edit Permission"]]]]],[["default"],[[[[1,"\\n "],[8,[39,39],null,[["@target","@name","@value"],[[30,0],"modal",[30,11]]],null],[1,"\\n "],[8,[39,35],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h3"],[12],[1,"Edit Permission"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,35],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[8,[39,40],null,[["@item","@onsubmit"],[[99,33,["@item"]],[28,[37,8],[[30,0],"add","Permissions",[33,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,39],null,[["@target","@name","@value"],[[30,0],"permissionForm",[30,12]]],null],[1,"\\n "]],[12]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,35],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,41],null,null,[["default"],[[[[1,"\\n "],[8,[39,26],[[16,"disabled",[52,[28,[37,4],[[30,0,["permissionForm","isDirty"]]],null],"disabled"]],[16,"onclick",[28,[37,31],[[28,[37,8],[[30,0],[30,0,["permissionForm","submit"]]],null],[28,[37,8],[[30,0],[30,11,["close"]]],null]],null]]],[["@text","@color"],["Save","primary"]],null],[1,"\\n "],[8,[39,26],[[16,"onclick",[28,[37,31],[[28,[37,8],[[30,0],[30,0,["permissionForm","reset"]]],null],[28,[37,8],[[30,0],[30,11,["close"]]],null]],null]]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[11]]]]],[1,"\\n\\n"],[13]],["&attrs","service","nspace","@dc","partition","service","nspace","partition","_action","radio","modal","permissionForm"],false,["disabled","if","item","power-select-with-create","not","create","services","SourceName","action","onchange","eq","can","nspaces","SourceNS","partitions","SourcePartition","DestinationName","DestinationNS","DestinationPartition","each","-track-array","array","hash","radio-card","concat","or","hds/button","on","gt","consul/intention/notice/permissions","consul/intention/permission/list","queue","mut","permission","empty-state","block-slot","hds/link/standalone","env","modal-dialog","ref","consul/intention/permission/form","hds/button-set"]]',moduleName:"consul-ui/components/consul/intention/form/fieldsets/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:"",shouldShowPermissionForm:!1,openModal(){var e +null===(e=this.modal)||void 0===e||e.open()},actions:{createNewLabel:function(e,t){return e.replace(/{{term}}/g,t)},isUnique:function(e,t){return!e.findBy("Name",t)},add:function(e,t,n){(t.get(e)||[]).includes(n)||(t.pushObject(e,n),t.validate())},delete:function(e,t,n){(t.get(e)||[]).includes(n)&&(t.removeObject(e,n),t.validate())}}})) +e.default=r})),define("consul-ui/components/consul/intention/form/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/object","@glimmer/tracking"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m,h,b,y,v,g +function O(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function P(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function w(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const x=(0,n.createTemplateFactory)({id:"f3I3843H",block:'[[[1,"\\n"],[11,0],[24,0,"consul-intention"],[17,1],[12],[1,"\\n"],[8,[39,0],null,[["@type","@dc","@nspace","@partition","@autofill","@item","@src","@onchange","@onsubmit"],["intention",[30,2,["Name"]],[30,3],[30,4],[30,5],[30,6],[30,7],[28,[37,1],[[30,0],[30,0,["change"]]],null],[28,[37,1],[[30,0],[30,0,["onsubmit"]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,4],[[30,8,["error","detail"]],"duplicate intention found:"],null],[[[1," "],[8,[39,5],[[4,[38,6],null,[["after"],[[28,[37,1],[[30,0],[30,9]],null]]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,10,["Title"]],null,null,[["default"],[[[[1,"Intention exists!"]],[]]]]],[1,"\\n "],[8,[30,10,["Description"]],null,null,[["default"],[[[[1,"\\n An intention already exists for this Source-Destination pair. Please enter a different combination of Services, or search the intentions to edit an existing intention.\\n "]],[]]]]],[1,"\\n "]],[10]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,5],[[4,[38,6],null,[["after"],[[28,[37,1],[[30,0],[30,9]],null]]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,11,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,11,["Description"]],null,null,[["default"],[[[[1,"\\n There was an error saving your intention.\\n"],[41,[28,[37,7],[[30,8,["error","status"]],[30,8,["error","detail"]]],null],[[[1," "],[10,"br"],[12],[13],[1,[30,8,["error","status"]]],[1,": "],[1,[30,8,["error","detail"]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[11]]]]],[1,"\\n"]],[]]],[1," "]],[9]]]]],[1,"\\n\\n "],[8,[39,2],null,[["@name"],["form"]],[["default"],[[[[1,"\\n"],[44,[[30,8,["data"]],[28,[37,9],[[28,[37,10],["write intention"],[["item"],[[30,8,["data"]]]]]],null]],[[[41,[28,[37,9],[[30,13]],null],[[[1,"\\n"],[44,[[28,[37,11],[[30,12],"Action"],null]],[[[1," "],[8,[39,12],[[24,0,"consul-intention-action-warn-modal warning"]],[["@aria"],[[28,[37,13],null,[["label"],[[28,[37,14],["Set intention to ",[30,14]],null]]]]]],[["default"],[[[[1,"\\n "],[8,[39,15],null,[["@target","@name","@value"],[[30,0],"modal",[30,15]]],null],[1,"\\n "],[8,[39,2],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"Set intention to "],[1,[30,14]],[1,"?"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,2],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n When you change this Intention to "],[1,[30,14]],[1,", you will remove all the Layer 7 policy permissions currently saved to this Intention. Are you sure you want to set it to "],[1,[30,14]],[1,"?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,2],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n "],[8,[39,17],[[4,[38,19],["click",[30,8,["submit"]]],null]],[["@text","@color"],[[29,["Set to ",[28,[37,18],[[30,14]],null]]],"critical"]],null],[1,"\\n "],[8,[39,17],[[16,"onclick",[30,16]]],[["@text","@color"],["No, Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[16]]]]],[1,"\\n "]],[15]]]]],[1,"\\n"]],[14]]],[1,"\\n "],[8,[39,20],null,[["@src","@onchange"],[[28,[37,21],["/${partition}/*/${dc}/services",[28,[37,13],null,[["partition","dc"],[[30,4],[30,2,["Name"]]]]]],null],[28,[37,1],[[30,0],[30,0,["createServices"]],[30,12]],null]]],null],[1,"\\n\\n"],[41,[28,[37,10],["use nspaces"],null],[[[1," "],[8,[39,20],null,[["@src","@onchange"],[[28,[37,21],["/${partition}/*/${dc}/namespaces",[28,[37,13],null,[["partition","dc"],[[30,4],[30,2,["Name"]]]]]],null],[28,[37,1],[[30,0],[30,0,["createNspaces"]],[30,12]],null]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[41,[28,[37,10],["use partitions"],null],[[[1," "],[8,[39,20],null,[["@src","@onchange"],[[28,[37,21],["/*/*/${dc}/partitions",[28,[37,13],null,[["dc"],[[30,2,["Name"]]]]]],null],[28,[37,1],[[30,0],[30,0,["createPartitions"]],[30,12]],null]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[41,[30,8,["isCreate"]],[[[41,[28,[37,7],[[28,[37,10],["use partitions"],null],[28,[37,9],[[28,[37,10],["choose partitions"],[["dc"],[[30,2]]]]],null]],null],[[[1," "],[8,[39,22],[[24,0,"mb-3 mt-2"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,17,["Title"]],null,null,[["default"],[[[[1,"Cross-partition communication not supported"]],[]]]]],[1,"\\n "],[8,[30,17,["Description"]],null,null,[["default"],[[[[1,"Cross-partition communication is not supported outside of the primary datacenter. You will only be able to select namespaces for source and destination services."]],[]]]]],[1,"\\n "]],[17]]]]],[1,"\\n"]],[]],null],[41,[30,0,["isManagedByCRDs"]],[[[1," "],[8,[39,23],null,[["@type"],["warning"]],null],[1,"\\n"]],[]],null]],[]],null],[1," "],[11,"form"],[4,[38,19],["submit",[28,[37,24],[[30,0,["submit"]],[30,12],[30,8,["submit"]]],null]],null],[12],[1,"\\n "],[8,[39,25],null,[["@nspaces","@dc","@partitions","@services","@SourceName","@SourceNS","@SourcePartition","@DestinationName","@DestinationNS","@DestinationPartition","@item","@disabled","@create","@onchange"],[[30,0,["nspaces"]],[30,2],[30,0,["partitions"]],[30,0,["services"]],[30,0,["SourceName"]],[30,0,["SourceNS"]],[30,0,["SourcePartition"]],[30,0,["DestinationName"]],[30,0,["DestinationNS"]],[30,0,["DestinationPartition"]],[30,12],[30,8,["disabled"]],[30,8,["isCreate"]],[30,8,["change"]]]],null],[1,"\\n "],[10,0],[12],[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n "],[8,[39,17],[[16,"disabled",[28,[37,26],[[30,12,["isInvalid"]],[30,8,["disabled"]]],null]],[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n "],[8,[39,17],[[16,"disabled",[30,8,["disabled"]]],[24,4,"reset"],[4,[38,19],["click",[28,[37,24],[[30,0,["oncancel"]],[30,12]],null]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"],[41,[28,[37,9],[[30,8,["isCreate"]]],null],[[[41,[28,[37,27],[[30,12,["ID"]],"anonymous"],null],[[[1," "],[8,[39,28],null,[["@message"],["Are you sure you want to delete this Intention?"]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,17],[[16,"disabled",[30,8,["disabled"]]],[4,[38,19],["click",[28,[37,24],[[30,18],[30,8,["delete"]]],null]],null]],[["@text","@color"],["Delete","critical"]],null],[1,"\\n "]],[18]]]]],[1,"\\n "],[8,[39,2],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@message","@execute","@cancel"],[[30,21],[30,19],[30,20]]],null],[1,"\\n "]],[19,20,21]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1,"\\n"],[41,[30,12,["IsManagedByCRD"]],[[[1," "],[8,[39,22],[[24,0,"mb-3 mt-2"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,22,["Title"]],null,null,[["default"],[[[[1,"Intention Custom Resource"]],[]]]]],[1,"\\n "],[8,[30,22,["Description"]],null,null,[["default"],[[[[1,"This Intention is view only because it is managed through an Intention Custom Resource in your Kubernetes cluster."]],[]]]]],[1,"\\n "],[8,[30,22,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition"],["Learn more about CRDs",[29,[[28,[37,30],["CONSUL_DOCS_URL"],null],"/k8s/crds"]],"docs-link","trailing"]],null],[1,"\\n "]],[22]]]]],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,31],null,[["@item"],[[30,12]]],null],[1,"\\n"]],[]]]],[12,13]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[8]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@dc","@nspace","@partition","@autofill","@item","@src","api","after","T","T","item","readonly","newAction","modal","close","A","confirm","execute","cancel","message","A"],false,["data-form","action","block-slot","if","string-starts-with","hds/toast","notification","and","let","not","can","changeset-get","modal-dialog","hash","concat","ref","hds/button-set","hds/button","capitalize","on","data-source","uri","hds/alert","consul/intention/notice/custom-resource","fn","consul/intention/form/fieldsets","or","not-eq","confirmation-dialog","delete-confirmation","env","consul/intention/view"]]',moduleName:"consul-ui/components/consul/intention/form/index.hbs",isStrictMode:!1}) +let j=(a=(0,r.inject)("repository/intention"),u=class extends l.default{constructor(e,t){super(...arguments),O(this,"services",s,this),O(this,"SourceName",c,this),O(this,"DestinationName",d,this),O(this,"nspaces",p,this),O(this,"SourceNS",f,this),O(this,"DestinationNS",m,this),O(this,"partitions",h,this),O(this,"SourcePartition",b,this),O(this,"DestinationPartition",y,this),O(this,"isManagedByCRDs",v,this),P(this,"modal",null),O(this,"repo",g,this),this.updateCRDManagement()}ondelete(){this.args.ondelete?this.args.ondelete(...arguments):this.onsubmit(...arguments)}oncancel(){this.args.oncancel?this.args.oncancel(...arguments):this.onsubmit(...arguments)}onsubmit(){this.args.onsubmit&&this.args.onsubmit(...arguments)}updateCRDManagement(){this.isManagedByCRDs=this.repo.isManagedByCRDs()}submit(e,t,n){n.preventDefault(),void 0!==e.change.Action&&void 0===e.data.Action?this.modal.open():t()}createServices(e,t){let n=t.data.uniqBy("Name").toArray().filter((e=>!["connect-proxy","mesh-gateway","terminating-gateway"].includes(e.Kind))).sort(((e,t)=>e.Name.localeCompare(t.Name))) +n=[{Name:"*"}].concat(n) +let l=n.findBy("Name",e.SourceName) +l||(l={Name:e.SourceName},n=[l].concat(n)) +let r=n.findBy("Name",e.DestinationName) +r||(r={Name:e.DestinationName},n=[r].concat(n)),this.services=n,this.SourceName=l,this.DestinationName=r}createNspaces(e,t){let n=t.data.toArray().sort(((e,t)=>e.Name.localeCompare(t.Name))) +n=[{Name:"*"}].concat(n) +let l=n.findBy("Name",e.SourceNS) +l||(l={Name:e.SourceNS},n=[l].concat(n)) +let r=n.findBy("Name",e.DestinationNS) +r||(r={Name:e.DestinationNS},n=[r].concat(n)),this.nspaces=n,this.SourceNS=l,this.DestinationNS=r}createPartitions(e,t){let n=t.data.toArray().sort(((e,t)=>e.Name.localeCompare(t.Name))),l=n.findBy("Name",e.SourcePartition) +l||(l={Name:e.SourcePartition},n=[l].concat(n)) +let r=n.findBy("Name",e.DestinationPartition) +r||(r={Name:e.DestinationPartition},n=[r].concat(n)),this.partitions=n,this.SourcePartition=l,this.DestinationPartition=r}change(e,t,n){const l=e.target +let r,i +switch(l.name){case"SourceName":case"DestinationName":case"SourceNS":case"DestinationNS":case"SourcePartition":case"DestinationPartition":switch(r=i=l.value,"string"!=typeof r&&(r=l.value.Name),l.value=r,l.name){case"SourceName":case"DestinationName":0===this.services.filterBy("Name",r).length&&(i={Name:r},this.services=[i].concat(this.services.toArray())) +break +case"SourceNS":case"DestinationNS":0===this.nspaces.filterBy("Name",r).length&&(i={Name:r},this.nspaces=[i].concat(this.nspaces.toArray())) +break +case"SourcePartition":case"DestinationPartition":0===this.partitions.filterBy("Name",r).length&&(i={Name:r},this.partitions=[i].concat(this.partitions.toArray()))}this[l.name]=i}t.handleEvent(e)}},s=w(u.prototype,"services",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=w(u.prototype,"SourceName",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=w(u.prototype,"DestinationName",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=w(u.prototype,"nspaces",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=w(u.prototype,"SourceNS",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=w(u.prototype,"DestinationNS",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=w(u.prototype,"partitions",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=w(u.prototype,"SourcePartition",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=w(u.prototype,"DestinationPartition",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=w(u.prototype,"isManagedByCRDs",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=w(u.prototype,"repo",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w(u.prototype,"ondelete",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"ondelete"),u.prototype),w(u.prototype,"oncancel",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"oncancel"),u.prototype),w(u.prototype,"onsubmit",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"onsubmit"),u.prototype),w(u.prototype,"updateCRDManagement",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"updateCRDManagement"),u.prototype),w(u.prototype,"submit",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"submit"),u.prototype),w(u.prototype,"createServices",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"createServices"),u.prototype),w(u.prototype,"createNspaces",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"createNspaces"),u.prototype),w(u.prototype,"createPartitions",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"createPartitions"),u.prototype),w(u.prototype,"change",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"change"),u.prototype),u) +e.default=j,(0,t.setComponentTemplate)(x,j)})),define("consul-ui/components/consul/intention/list/check/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"A/kl6rVt",block:'[[[1,"\\n"],[44,[[28,[37,1],[[28,[37,2],[[28,[37,2],["allow","Allowed"],null],[28,[37,2],["deny","Denied"],null],[28,[37,2],["","Layer 7 Rules"],null]],null]],null]],[[[11,0],[16,0,[28,[37,3],["consul-intention-list-check ","notice ",[28,[37,4],[[30,2,["Action"]],"permissions"],null]],null]],[17,3],[12],[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,5],[[30,1],[28,[37,4],[[30,2,["Action"]],""],null]],null]],[1,"\\n "],[13],[1,"\\n "],[10,2],[12],[1,"\\n"],[41,[28,[37,7],[[30,2,["Action"]],"allow"],null],[[[1," Yes, "],[1,[33,8,["SourceName"]]],[1," is allowed to connect to "],[1,[30,2,["DestinationName"]]],[1," due to the highest precedence intention below:\\n"]],[]],[[[41,[28,[37,7],[[30,2,["Action"]],"deny"],null],[[[1," No, "],[1,[30,2,["SourceName"]]],[1," is not allowed to connect to "],[1,[30,2,["DestinationName"]]],[1," due to the highest precedence intention below:\\n"]],[]],[[[1," "],[1,[30,2,["SourceName"]]],[1," may or may not be allowed to connect with "],[1,[30,2,["DestinationName"]]],[1," through its Layer 7 rules.\\n "]],[]]]],[]]],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],[1]]]],["titles","@item","&attrs"],false,["let","from-entries","array","concat","or","get","if","eq","item"]]',moduleName:"consul-ui/components/consul/intention/list/check/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/intention/list/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/object","@glimmer/tracking"],(function(e,t,n,l,r,i,o){var a,u,s,c +function d(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function p(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const f=(0,n.createTemplateFactory)({id:"1D6EKD3D",block:'[[[1,"\\n"],[11,0],[24,0,"consul-intention-list"],[17,1],[4,[38,0],[[30,0,["updateCRDManagement"]],[30,2]],null],[12],[1,"\\n"],[18,4,[[28,[37,2],null,[["Table","CheckNotice","CustomResourceNotice"],[[50,"consul/intention/list/table",0,null,[["delete","items"],[[30,3],[30,0,["items"]]]]],[52,[30,0,["checkedItem"]],[50,"consul/intention/list/check",0,null,[["item"],[[30,0,["checkedItem"]]]]],""],[52,[30,0,["isManagedByCRDs"]],[50,"consul/intention/notice/custom-resource",0,null,null],""]]]]]],[1,"\\n"],[13]],["&attrs","@items","@delete","&default"],false,["did-update","yield","hash","component","if"]]',moduleName:"consul-ui/components/consul/intention/list/index.hbs",isStrictMode:!1}) +let m=(a=(0,r.inject)("repository/intention"),u=class extends l.default{constructor(e,t){super(...arguments),d(this,"repo",s,this),d(this,"isManagedByCRDs",c,this),this.updateCRDManagement(t.items)}get items(){return this.args.items||[]}get checkedItem(){return 1===this.items.length&&this.args.check&&this.items[0].SourceName===this.args.check?this.items[0]:null}updateCRDManagement(){this.isManagedByCRDs=this.repo.isManagedByCRDs()}},s=p(u.prototype,"repo",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=p(u.prototype,"isManagedByCRDs",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p(u.prototype,"updateCRDManagement",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"updateCRDManagement"),u.prototype),u) +e.default=m,(0,t.setComponentTemplate)(f,m)})),define("consul-ui/components/consul/intention/list/table/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"0tpkzdWh",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-intention-list-table"],[17,1]],[["@items","@rowHeight"],[[30,2],59]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[14,0,"source"],[12],[1,"Source"],[13],[1,"\\n "],[10,"th"],[14,0,"intent"],[12],[1," "],[13],[1,"\\n "],[10,"th"],[14,0,"destination"],[12],[1,"Destination"],[13],[1,"\\n "],[10,"th"],[14,0,"permissions"],[12],[1,"\\n Permissions\\n "],[10,1],[12],[1,"\\n "],[8,[39,2],null,null,[["default"],[[[[1,"Permissions intercept an Intention\'s traffic using Layer 7 criteria, such as path\\n prefixes and http headers."]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"th"],[14,0,"meta"],[12],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["row"]],[["default"],[[[[1,"\\n "],[10,"td"],[14,0,"source"],[12],[1,"\\n "],[10,3],[15,6,[28,[37,3],[[28,[37,4],[[30,5],"dc.intentions.edit"],null],[30,3,["ID"]]],null]],[12],[1,"\\n"],[41,[28,[37,6],[[30,3,["SourceName"]],"*"],null],[[[1," All Services (*)\\n"]],[]],[[[1," "],[1,[30,3,["SourceName"]]],[1,"\\n"]],[]]],[1," "],[10,"em"],[14,0,"consul-intention-list-table__meta-info"],[12],[1,"\\n "],[8,[39,7],null,[["@item","@nspace","@partition"],[[28,[37,8],null,[["Namespace","Partition","PeerName"],[[30,3,["SourceNS"]],[30,3,["SourcePartition"]],[30,3,["SourcePeer"]]]]],"-","-"]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[15,0,[29,["intent intent-",[28,[37,9],[[30,3,["Action"]]],null]]]],[12],[1,"\\n "],[10,"strong"],[12],[1,[28,[35,10],[[28,[37,4],[[30,3,["Action"]],"App aware"],null]],null]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[14,0,"destination"],[12],[1,"\\n "],[10,1],[12],[1,"\\n"],[41,[28,[37,6],[[30,3,["DestinationName"]],"*"],null],[[[1," All Services (*)\\n"]],[]],[[[1," "],[1,[30,3,["DestinationName"]]],[1,"\\n"]],[]]],[41,[28,[37,4],[[28,[37,11],["use nspaces"],null],[28,[37,11],["use partitions"],null]],null],[[[1," "],[10,"em"],[12],[1,"\\n "],[10,1],[15,0,[28,[37,12],["partition-",[28,[37,4],[[30,3,["DestinationPartition"]],"default"],null]],null]],[12],[1,[28,[35,4],[[30,3,["DestinationPartition"]],"default"],null]],[13],[1,"\\n /\\n "],[10,1],[15,0,[28,[37,12],["nspace-",[28,[37,4],[[30,3,["DestinationNS"]],"default"],null]],null]],[12],[1,[28,[35,4],[[30,3,["DestinationNS"]],"default"],null]],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[14,0,"permissions"],[12],[1,"\\n"],[41,[28,[37,13],[[30,3,["Permissions","length"]],0],null],[[[1," "],[10,1],[12],[1,[28,[35,14],[[30,3,["Permissions","length"]],"Permission"],null]],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[10,"td"],[14,0,"meta"],[12],[1,"\\n"],[41,[30,3,["IsManagedByCRD"]],[[[1," "],[8,[39,15],null,[["@item","@label"],[[30,3],"Managed by CRD"]],null],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,16],null,[["@expanded","@onchange","@keyboardAccess"],[[52,[28,[37,6],[[30,8],[30,6]],null],true,false],[28,[37,17],[[30,0],[30,7],[30,6]],null],false]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n More\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n"],[41,[28,[37,11],["write intention"],[["item"],[[30,3]]]],[[[1," "],[10,"li"],[14,"role","none"],[12],[1,"\\n "],[10,3],[14,"role","menuitem"],[14,"tabindex","-1"],[15,6,[28,[37,3],[[28,[37,4],[[33,18],"dc.intentions.edit"],null],[30,3,["ID"]]],null]],[12],[1,"Edit"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[14,"role","none"],[14,0,"dangerous"],[12],[1,"\\n "],[10,"label"],[15,"for",[30,9]],[14,"role","menuitem"],[14,"tabindex","-1"],[15,"onkeypress",[30,11]],[12],[1,"Delete"],[13],[1,"\\n "],[10,0],[14,"role","menu"],[12],[1,"\\n "],[8,[39,19],[[24,0,"warning"]],null,[["header","body","actions"],[[[[1,"\\n Confirm Delete\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this intention?\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,13,["Action"]],[[24,0,"dangerous"]],null,[["default"],[[[[1,"\\n "],[8,[39,17],[[24,0,"type-delete"],[24,"tabindex","-1"],[4,[38,20],["click",[28,[37,21],[[28,[37,17],[[30,0],[30,12]],null],[28,[37,17],[[30,0],[30,14],[30,3]],null]],null]],null]],null,[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,13,["Action"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,17],null,[["@for"],[[30,9]]],[["default"],[[[[1,"\\n Cancel\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[13]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[41,[28,[37,11],["view CRD intention"],[["item"],[[30,3]]]],[[[1," "],[10,"li"],[14,"role","none"],[12],[1,"\\n "],[10,0],[14,"role","menu"],[12],[1,"\\n "],[8,[39,19],null,null,[["header","body","actions"],[[[[1,"\\n "],[10,1],[14,0,"flex flex-nowrap items-center"],[12],[1,"\\n "],[8,[39,22],[[24,0,"mr-1.5"]],[["@name"],["kubernetes-color"]],null],[1,"\\n Managed by CRD\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n This intention is being managed through an Intention Custom Resource in your\\n Kubernetes cluster. It is view only in the UI.\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,15,["Action"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,17],[[24,"tabindex","-1"],[24,0,"action"]],[["@href"],[[28,[37,3],[[28,[37,4],[[30,5],"dc.intentions.edit"],null],[30,3,["ID"]]],null]]],[["default"],[[[[1,"\\n View\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,15,["Action"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,17],null,[["@onclick"],[[28,[37,17],[[30,0],[30,12]],null]]],[["default"],[[[[1,"\\n Cancel\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[15]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,"li"],[14,"role","none"],[12],[1,"\\n "],[10,3],[14,"role","menuitem"],[14,"tabindex","-1"],[15,6,[28,[37,3],[[28,[37,4],[[33,18],"dc.intentions.edit"],null],[30,3,["ID"]]],null]],[12],[1,"\\n View\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]],[]]],[1," "]],[9,10,11,12]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6,7,8]]]]],[1,"\\n"]],[3,4]]]]],[1,"\\n"]],["&attrs","@items","item","index","@routeName","index","change","checked","confirm","send","keypressClick","change","Actions","@delete","Actions"],false,["tabular-collection","block-slot","tooltip","href-to","or","if","eq","consul/bucket/list","hash","slugify","capitalize","can","concat","gt","pluralize","consul/external-source","popover-menu","action","routeName","informed-action","on","queue","flight-icon"]]',moduleName:"consul-ui/components/consul/intention/list/table/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/intention/notice/custom-resource/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"bdXNglRL",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"mb-2 mt-2 consul-intention-notice-custom-resource"]],[["@type","@color"],["inline",[28,[37,1],[[30,1],"neutral"],null]]],[["default"],[[[[1,"\\n "],[8,[30,2,["Title"]],null,null,[["default"],[[[[1,"Intention Custom Resource"]],[]]]]],[1,"\\n "],[8,[30,2,["Description"]],null,null,[["default"],[[[[1,"Some of your intentions are being managed through an Intention Custom Resource in your Kubernetes cluster. Those managed intentions will be view only in the UI. Any intentions created in the UI will work but will not be synced to the Custom Resource Definition (CRD) datastore."]],[]]]]],[1,"\\n "],[8,[30,2,["Link::Standalone"]],null,[["@href","@text","@icon","@iconPosition","@size"],[[29,[[28,[37,2],["CONSUL_DOCS_URL"],null],"/k8s/crds"]],"Learn more about CRDs","docs-link","trailing","small"]],null],[1,"\\n"]],[2]]]]]],["@type","A"],false,["hds/alert","or","env"]]',moduleName:"consul-ui/components/consul/intention/notice/custom-resource/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/intention/notice/permissions/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"vs+EKtgU",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"mb-3 mt-2"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,1,["Description"]],null,null,[["default"],[[[[1,[28,[35,1],["components.consul.intention.notice.permissions.body"],null]]],[]]]]],[1,"\\n "],[8,[30,1,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition","@size"],[[28,[37,1],["components.consul.intention.notice.permissions.footer"],null],[29,[[28,[37,2],["CONSUL_DOCS_URL"],null],"/connect/intentions"]],"docs-link","trailing","small"]],null],[1,"\\n"]],[1]]]]]],["A"],false,["hds/alert","t","env"]]',moduleName:"consul-ui/components/consul/intention/notice/permissions/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/intention/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"WszqZIrE",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1],"create"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your intention has been added.\\n"]],[]],[[[1," There was an error adding your intention.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"update"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your intention has been saved.\\n"]],[]],[[[1," There was an error saving your intention.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"delete"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your intention was deleted.\\n"]],[]],[[[1," There was an error deleting your intention.\\n"]],[]]]],[]],null]],[]]]],[]]],[44,[[30,3,["errors","firstObject"]]],[[[41,[30,4,["detail"]],[[[1," "],[10,"br"],[12],[13],[1,[28,[35,3],["(",[52,[30,4,["status"]],[28,[37,3],[[30,4,["status"]],": "],null]],[30,4,["detail"]],")"],null]],[1,"\\n"]],[]],null]],[4]]]],["@type","@status","@error","error"],false,["if","eq","let","concat"]]',moduleName:"consul-ui/components/consul/intention/notifications/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/intention/permission/form/index",["exports","@ember/component","@ember/template-factory","@ember/object","@ember/object/computed","@ember/service"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"CUvwsNTr",block:'[[[1,"\\n"],[11,0],[17,1],[24,0,"consul-intention-permission-form"],[12],[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[18,11,[[28,[37,3],null,[["submit","reset","isDirty","changeset"],[[28,[37,4],[[30,0],"submit",[33,5]],null],[28,[37,4],[[30,0],"reset",[33,5]],null],[28,[37,6],[[33,5,["isValid"]]],null],[33,5]]]]]],[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,0],[14,"data-property","action"],[12],[1,"\\n "],[10,1],[14,0,"label"],[12],[1,"\\n Should this permission allow the source connect to the destination?\\n "],[13],[1,"\\n "],[10,0],[14,"role","radiogroup"],[15,0,[52,[33,5,["error","Action"]]," has-error"]],[12],[1,"\\n"],[42,[28,[37,9],[[28,[37,9],[[33,10]],null]],null],null,[[[1," "],[10,"label"],[12],[1,"\\n "],[10,1],[12],[1,[28,[35,11],[[30,3]],null]],[13],[1,"\\n "],[10,"input"],[14,3,"Action"],[15,2,[30,3]],[15,"checked",[52,[28,[37,12],[[33,5,["Action"]],[30,3]],null],"checked"]],[15,"onchange",[28,[37,4],[[30,0],[28,[37,13],[[33,5],"Action"],null]],[["value"],["target.value"]]]],[14,4,"radio"],[12],[13],[1,"\\n "],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Path"],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[12],[1,"\\n "],[8,[30,2,["Element"]],null,[["@name","@type"],["PathType","select"]],[["default"],[[[[1,"\\n "],[8,[30,4,["Label"]],null,null,[["default"],[[[[1,"\\n Path type\\n "]],[]]]]],[1,"\\n "],[8,[39,14],null,[["@options","@selected","@onChange"],[[99,15,["@options"]],[99,16,["@selected"]],[28,[37,4],[[30,0],"change","HTTP.PathType",[33,5]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,17],[[33,18],[30,5]],null]],[1,"\\n "]],[5]]]]],[1,"\\n "]],[4]]]]],[1,"\\n\\n"],[41,[33,19],[[[1," "],[8,[30,2,["Element"]],null,[["@name","@error"],["Path",[28,[37,20],[[33,5],"error.HTTP.Path"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Label"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,17],[[33,18],[33,16]],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Text"]],[[16,"oninput",[28,[37,4],[[30,0],"change","HTTP.Path",[33,5]],null]]],[["@value"],[[28,[37,20],[[33,5],"HTTP.Path"],null]]],null],[1,"\\n "],[8,[39,21],null,[["@state","@matches"],[[30,6,["state"]],"error"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Error"]],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,12],[[28,[37,20],[[33,5],"HTTP.Path"],null],"Regex"],null],[[[1," Path Regex should not be blank\\n"]],[]],[[[1," Path should begin with a \'/\'\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Methods"],[13],[1,"\\n "],[10,0],[14,0,"type-toggle"],[12],[1,"\\n "],[10,1],[12],[1,"All methods are applied by default unless specified"],[13],[1,"\\n "],[8,[30,2,["Element"]],null,[["@name"],["allMethods"]],[["default"],[[[[1,"\\n "],[8,[30,7,["Checkbox"]],[[16,"checked",[52,[33,22],"checked"]],[16,"onchange",[28,[37,4],[[30,0],"change","allMethods",[33,5]],null]]],null,null],[1,"\\n "],[8,[30,7,["Label"]],null,null,[["default"],[[[[1,"\\n All Methods\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "],[13],[1,"\\n\\n"],[41,[33,23],[[[1," "],[10,0],[14,0,"checkbox-group"],[14,"role","group"],[12],[1,"\\n"],[42,[28,[37,9],[[28,[37,9],[[33,24]],null]],null],null,[[[1," "],[10,"label"],[14,0,"type-checkbox"],[12],[1,"\\n "],[10,"input"],[14,3,"method"],[15,2,[30,8]],[15,"checked",[52,[28,[37,25],[[30,8],[33,5,["HTTP","Methods"]]],null],"checked"]],[15,"onchange",[28,[37,4],[[30,0],"change","method",[33,5]],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,1],[12],[1,[30,8]],[13],[1,"\\n "],[13],[1,"\\n"]],[8]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Headers"],[13],[1,"\\n\\n "],[8,[39,26],null,[["@items","@ondelete"],[[28,[37,20],[[33,5],"HTTP.Header"],null],[28,[37,4],[[30,0],"delete","HTTP.Header",[33,5]],null]]],[["default"],[[[[1,"\\n\\n "]],[9]]]]],[1,"\\n\\n "],[8,[39,27],null,[["@onsubmit"],[[28,[37,4],[[30,0],"add","HTTP.Header",[33,5]],null]]],[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@target","@name","@value"],[[30,0],"headerForm",[30,10]]],null],[1,"\\n "]],[10]]]]],[1,"\\n\\n "],[8,[39,29],null,null,[["default"],[[[[1,"\\n "],[8,[39,30],[[16,"disabled",[52,[28,[37,31],[[30,0,["headerForm","isDirty"]]],null],"disabled"]],[16,"onclick",[28,[37,4],[[30,0],[30,0,["headerForm","submit"]]],null]]],[["@text","@color"],[[29,["Add",[52,[28,[37,32],[[28,[37,17],[[28,[37,20],[[33,5],"HTTP.Header"],null],"length"],null],0],null]," another",""]," header"]],"primary"]],null],[1,"\\n "],[8,[39,30],[[16,"onclick",[28,[37,4],[[30,0],[30,0,["headerForm","reset"]]],null]]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "]],[2]]]]],[1,"\\n"],[13]],["&attrs","group","intent","el","Type","el","el","method","headerList","headerForm","&default"],false,["form-group","name","yield","hash","action","changeset","and","if","each","-track-array","intents","capitalize","eq","changeset-set","power-select","pathTypes","pathType","get","pathLabels","shouldShowPathField","changeset-get","state","allMethods","shouldShowMethods","methods","includes","consul/intention/permission/header/list","consul/intention/permission/header/form","ref","hds/button-set","hds/button","not","gt"]]',moduleName:"consul-ui/components/consul/intention/permission/form/index.hbs",isStrictMode:!1}),a="intention-permission" +var u=(0,t.setComponentTemplate)(o,t.default.extend({tagName:"",name:a,schema:(0,i.inject)("schema"),change:(0,i.inject)("change"),repo:(0,i.inject)(`repository/${a}`),onsubmit:function(){},onreset:function(){},intents:(0,r.alias)(`schema.${a}.Action.allowedValues`),methods:(0,r.alias)(`schema.${a}-http.Methods.allowedValues`),pathProps:(0,r.alias)(`schema.${a}-http.PathType.allowedValues`),pathTypes:(0,l.computed)("pathProps",(function(){return["NoPath"].concat(this.pathProps)})),pathLabels:(0,l.computed)((function(){return{NoPath:"No Path",PathExact:"Exact",PathPrefix:"Prefixed by",PathRegex:"Regular Expression"}})),pathInputLabels:(0,l.computed)((function(){return{PathExact:"Exact Path",PathPrefix:"Path Prefix",PathRegex:"Path Regular Expression"}})),changeset:(0,l.computed)("item",(function(){const e=this.change.changesetFor(a,this.item||this.repo.create()) +return e.isPristine&&e.validate(),e})),pathType:(0,l.computed)("changeset._changes.HTTP.PathType","pathTypes.firstObject",(function(){return this.changeset.HTTP.PathType||this.pathTypes.firstObject})),noPathType:(0,r.equal)("pathType","NoPath"),shouldShowPathField:(0,r.not)("noPathType"),allMethods:!1,shouldShowMethods:(0,r.not)("allMethods"),didReceiveAttrs:function(){(0,l.get)(this,"item.HTTP.Methods.length")||(0,l.set)(this,"allMethods",!0)},actions:{change:function(e,t,n){const r=void 0!==(0,l.get)(n,"target.value")?n.target.value:n +switch(e){case"allMethods":(0,l.set)(this,e,n.target.checked) +break +case"method":n.target.checked?this.actions.add.apply(this,["HTTP.Methods",t,r]):this.actions.delete.apply(this,["HTTP.Methods",t,r]) +break +default:t.set(e,r)}t.validate()},add:function(e,t,n){t.pushObject(e,n),t.validate()},delete:function(e,t,n){t.removeObject(e,n),t.validate()},submit:function(e,t){void 0!==e.changes.find((e=>{let{key:t,value:n}=e +return"HTTP.PathType"===t||"HTTP.Path"===t}))&&(this.pathProps.forEach((t=>{e.set(`HTTP.${t}`,void 0)})),"NoPath"!==e.HTTP.PathType&&e.set(`HTTP.${e.HTTP.PathType}`,e.HTTP.Path)),this.allMethods&&e.set("HTTP.Methods",null),delete e._changes.HTTP.PathType,delete e._changes.HTTP.Path,this.repo.persist(e),this.onsubmit(e.data)},reset:function(e,t){e.rollback(),this.onreset(e.data)}}})) +e.default=u})),define("consul-ui/components/consul/intention/permission/header/form/index",["exports","@ember/component","@ember/template-factory","@ember/object","@ember/object/computed","@ember/service"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"2cihjQ3k",block:'[[[1,"\\n"],[11,0],[17,1],[24,0,"consul-intention-permission-header-form"],[12],[1,"\\n "],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[18,7,[[28,[37,3],null,[["submit","reset","isDirty","changeset"],[[28,[37,4],[[30,0],"submit",[33,5]],null],[28,[37,4],[[30,0],"reset",[33,5]],null],[28,[37,6],[[33,5,["isValid"]],[33,5,["isDirty"]]],null],[33,5]]]]]],[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,0],[12],[1,"\\n "],[8,[30,2,["Element"]],null,[["@name","@type"],["HeaderType","select"]],[["default"],[[[[1,"\\n "],[8,[30,3,["Label"]],null,null,[["default"],[[[[1,"Header type"]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@options","@selected","@onChange"],[[99,8,["@options"]],[99,9,["@selected"]],[28,[37,4],[[30,0],"change","HeaderType",[33,5]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,10],[[33,11],[30,4]],null]],[1,"\\n "]],[4]]]]],[1,"\\n "]],[3]]]]],[1,"\\n\\n\\n "],[8,[30,2,["Element"]],null,[["@name","@error"],["Name",[28,[37,12],[[33,5],"error.Name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,5,["Label"]],null,null,[["default"],[[[[1,"Header name"]],[]]]]],[1,"\\n "],[8,[30,5,["Text"]],[[16,"oninput",[28,[37,4],[[30,0],"change","Name",[33,5]],null]]],[["@value"],[[28,[37,12],[[33,5],"Name"],null]]],null],[1,"\\n "],[8,[39,13],null,[["@state","@matches"],[[30,5,["state"]],"error"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Error"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,12],[[33,5],"error.Name.validation"],null]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n\\n"],[41,[33,15],[[[1," "],[8,[30,2,["Element"]],null,[["@name","@error"],["Value",[28,[37,12],[[33,5],"error.Value"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Label"]],null,null,[["default"],[[[[1,"Header "],[1,[28,[35,16],[[28,[37,10],[[33,11],[33,9]],null]],null]]],[]]]]],[1,"\\n "],[8,[30,6,["Text"]],[[16,"oninput",[28,[37,4],[[30,0],"change","Value",[33,5]],null]]],[["@value"],[[28,[37,12],[[33,5],"Value"],null]]],null],[1,"\\n "],[8,[39,13],null,[["@state","@matches"],[[30,6,["state"]],"error"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Error"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,12],[[33,5],"error.Value.validation"],null]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[2]]]]],[1,"\\n"],[13]],["&attrs","group","el","Type","el","el","&default"],false,["form-group","name","yield","hash","action","changeset","and","power-select","headerTypes","headerType","get","headerLabels","changeset-get","state","if","shouldShowValueField","lowercase"]]',moduleName:"consul-ui/components/consul/intention/permission/header/form/index.hbs",isStrictMode:!1}),a="intention-permission-http-header" +var u=(0,t.setComponentTemplate)(o,t.default.extend({tagName:"",name:a,schema:(0,i.inject)("schema"),change:(0,i.inject)("change"),repo:(0,i.inject)(`repository/${a}`),onsubmit:function(){},onreset:function(){},changeset:(0,l.computed)("item",(function(){return this.change.changesetFor(a,this.item||this.repo.create({HeaderType:this.headerTypes.firstObject}))})),headerTypes:(0,r.alias)(`schema.${a}.HeaderType.allowedValues`),headerLabels:(0,l.computed)((function(){return{Exact:"Exactly Matching",Prefix:"Prefixed by",Suffix:"Suffixed by",Regex:"Regular Expression",Present:"Is present"}})),headerType:(0,l.computed)("changeset.HeaderType","headerTypes.firstObject",(function(){return this.changeset.HeaderType||this.headerTypes.firstObject})),headerTypeEqualsPresent:(0,r.equal)("headerType","Present"),shouldShowValueField:(0,r.not)("headerTypeEqualsPresent"),actions:{change:function(e,t,n){const r=void 0!==(0,l.get)(n,"target.value")?n.target.value:n +t.set(e,r),t.validate()},submit:function(e){this.headerTypes.forEach((t=>{e.set(t,void 0)})) +const t="Present"===e.HeaderType||e.Value +e.set(e.HeaderType,t),delete e._changes.HeaderType,delete e._changes.Value,this.repo.persist(e),this.onsubmit(e.data),(0,l.set)(this,"item",this.repo.create({HeaderType:this.headerType}))},reset:function(e,t){e.rollback()}}})) +e.default=u})),define("consul-ui/components/consul/intention/permission/header/list/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"YQICAE68",block:'[[[1,"\\n"],[41,[28,[37,1],[[33,2,["length"]],0],null],[[[8,[39,3],[[24,0,"consul-intention-permission-header-list"]],[["@items","@scroll","@cellHeight"],[[99,2,["@items"]],"native",42]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,5],null,null,[["default"],[[[[1,"\\n Header\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,1,["Name"]]],[1," "],[1,[28,[35,6],[[30,1]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[30,2],null,null,[["default"],[[[[1,"\\n "],[8,[30,3],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,7],[[30,0],[33,8],[30,1]],null]]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,4],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this header?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,5],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],[]],null]],["item","Actions","Action","Confirmation","Confirm"],false,["if","gt","items","list-collection","block-slot","tooltip","route-match","action","ondelete"]]',moduleName:"consul-ui/components/consul/intention/permission/header/list/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) +e.default=r})),define("consul-ui/components/consul/intention/permission/list/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"eQ5zYOJl",block:'[[[1,"\\n"],[41,[28,[37,1],[[33,2,["length"]],0],null],[[[8,[39,3],[[16,0,[29,["consul-intention-permission-list",[52,[28,[37,4],[[33,5]],null]," readonly"]]]]],[["@scroll","@items","@partial"],["native",[99,2,["@items"]],5]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[10,0],[15,"onclick",[28,[37,7],[[30,0],[28,[37,8],[[33,5]],null],[30,1]],null]],[12],[1,"\\n "],[10,"strong"],[15,0,[28,[37,9],["intent-",[30,1,["Action"]]],null]],[12],[1,[28,[35,10],[[30,1,["Action"]]],null]],[13],[1,"\\n"],[41,[28,[37,1],[[30,1,["HTTP","Methods","length"]],0],null],[[[1," "],[10,"dl"],[14,0,"permission-methods"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,11],null,null,[["default"],[[[[1,"\\n Methods\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[42,[28,[37,13],[[28,[37,13],[[30,1,["HTTP","Methods"]]],null]],null],null,[[[1," "],[1,[30,2]],[1,"\\n"]],[2]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,1,["HTTP","Path"]],[[[1," "],[10,"dl"],[14,0,"permission-path"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,11],null,null,[["default"],[[[[1,"\\n "],[1,[30,1,["HTTP","PathType"]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,1,["HTTP","Path"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[42,[28,[37,13],[[28,[37,13],[[30,1,["HTTP","Header"]]],null]],null],null,[[[1," "],[10,"dl"],[14,0,"permission-header"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,11],null,null,[["default"],[[[[1,"\\n Header\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Name"]]],[1," "],[1,[28,[35,14],[[30,3]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[33,5],[[[1," "],[8,[39,6],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[30,4],null,null,[["default"],[[[[1,"\\n "],[8,[30,5],null,[["@onclick","@close"],[[28,[37,7],[[30,0],[28,[37,8],[[33,5]],null],[30,1]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Edit\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,5],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,7],[[30,0],[33,15],[30,1]],null]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,6],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this permission?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,7],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[]],null]],[1]]]]],[1,"\\n"]],[]],null]],["item","item","item","Actions","Action","Confirmation","Confirm"],false,["if","gt","items","list-collection","not","onclick","block-slot","action","optional","concat","capitalize","tooltip","each","-track-array","route-match","ondelete"]]',moduleName:"consul-ui/components/consul/intention/permission/list/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) +e.default=r})),define("consul-ui/components/consul/intention/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"TGY4oICb",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-intention-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.intention.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.intention.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n"],[41,[30,2,["searchproperty"]],[[[1," "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,10],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,11],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-access"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["access","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.intention.search-bar.access.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["allow","deny",""],null]],null]],null],null,[[[1," "],[8,[30,16],[[16,0,[28,[37,3],["value-",[30,17]],null]]],[["@value","@selected"],[[28,[37,12],[[30,17],"app-aware"],null],[28,[37,10],[[28,[37,12],[[30,17],"app-aware"],null],[30,2,["access","value"]]],null]]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,[28,[35,2],[[28,[37,3],["components.consul.intention.search-bar.access.options.",[28,[37,12],[[30,17],"app-aware"],null]],null]],null]],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,18,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,19,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,13],[[28,[37,4],[[28,[37,4],["Action:asc",[28,[37,2],["components.consul.intention.search-bar.sort.access.asc"],null]],null],[28,[37,4],["Action:desc",[28,[37,2],["components.consul.intention.search-bar.sort.access.desc"],null]],null],[28,[37,4],["SourceName:asc",[28,[37,2],["components.consul.intention.search-bar.sort.source-name.asc"],null]],null],[28,[37,4],["SourceName:desc",[28,[37,2],["components.consul.intention.search-bar.sort.source-name.desc"],null]],null],[28,[37,4],["DestinationName:asc",[28,[37,2],["components.consul.intention.search-bar.sort.destination-name.asc"],null]],null],[28,[37,4],["DestinationName:desc",[28,[37,2],["components.consul.intention.search-bar.sort.destination-name.desc"],null]],null],[28,[37,4],["Precedence:asc",[28,[37,2],["common.sort.numeric.asc"],null]],null],[28,[37,4],["Precedence:desc",[28,[37,2],["common.sort.numeric.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,14],[[30,21],[30,19,["value"]]],null]],[1,"\\n"]],[21]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,20,["Optgroup"]],[30,20,["Option"]]],[[[1," "],[8,[30,22],null,[["@label"],[[28,[37,2],["components.consul.intention.search-bar.sort.access.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Action:asc",[28,[37,15],["Action:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["components.consul.intention.search-bar.sort.access.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Action:desc",[28,[37,15],["Action:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["components.consul.intention.search-bar.sort.access.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,22],null,[["@label"],[[28,[37,2],["components.consul.intention.search-bar.sort.source-name.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["SourceName:asc",[28,[37,15],["SourceName:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["SourceName:desc",[28,[37,15],["SourceName:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,22],null,[["@label"],[[28,[37,2],["components.consul.intention.search-bar.sort.destination-name.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["DestinationName:asc",[28,[37,15],["DestinationName:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["DestinationName:desc",[28,[37,15],["DestinationName:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,22],null,[["@label"],[[28,[37,2],["components.consul.intention.search-bar.sort.precedence.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Precedence:asc",[28,[37,15],["Precedence:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.numeric.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Precedence:desc",[28,[37,15],["Precedence:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.numeric.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22,23]]],[1," "]],[]]]]],[1,"\\n "]],[20]]]]],[1,"\\n "]],[18]]]]]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","item","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","if","block-slot","each","-track-array","includes","lowercase","or","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/intention/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/intention/view/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"2U6CYW9B",block:'[[[1,"\\n"],[11,0],[24,0,"consul-intention-view"],[17,1],[12],[1,"\\n\\n "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Destination"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,0],null,[["@item","@nspace","@partition","@service"],[[28,[37,1],null,[["Namespace","Partition","Service"],[[33,2,["DestinationNS"]],[33,2,["DestinationPartition"]],[33,2,["DestinationName"]]]]],"-","-",true]],null],[1,"\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,"Source"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,0],null,[["@item","@nspace","@partition","@service"],[[28,[37,1],null,[["Namespace","Partition","Service","PeerName"],[[33,2,["SourceNS"]],[33,2,["SourcePartition"]],[33,2,["SourceName"]],[33,2,["SourcePeer"]]]]],"-","-",true]],null],[1,"\\n "],[13],[1,"\\n"],[41,[33,2,["Action"]],[[[1," "],[10,"dt"],[12],[1,"Action"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[33,2,["Action"]]],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,4],[[33,2,["Description"]],"N/A"],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n"],[41,[28,[37,5],[[33,2,["Permissions","length"]],0],null],[[[1," "],[10,"h2"],[12],[1,"Permissions"],[13],[1,"\\n "],[8,[39,6],null,null,null],[1,"\\n "],[8,[39,7],null,[["@items"],[[33,2,["Permissions"]]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[13],[1,"\\n"]],["&attrs"],false,["consul/bucket/list","hash","item","if","or","gt","consul/intention/notice/permissions","consul/intention/permission/list"]]',moduleName:"consul-ui/components/consul/intention/view/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) +e.default=r})),define("consul-ui/components/consul/kind/index",["exports","@ember/component","@ember/template-factory","@ember/object","ember-cli-string-helpers/helpers/titleize","ember-cli-string-helpers/helpers/humanize"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"w6CpoygV",block:'[[[1,"\\n"],[41,[33,1,["Kind"]],[[[41,[33,2],[[[1," "],[10,"dl"],[14,0,"tooltip-panel"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[10,1],[14,0,"consul-kind"],[12],[1,"\\n "],[1,[34,3]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,4],null,[["@position"],["left"]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,6],[[33,1,["Kind"]],"ingress-gateway"],null],[[[1," Ingress gateways enable ingress traffic from services outside the Consul service mesh to services inside the Consul service mesh.\\n"]],[]],[[[41,[28,[37,6],[[33,1,["Kind"]],"terminating-gateway"],null],[[[1," Terminating gateways allow connect-enabled services in Consul service mesh to communicate with services outside the service mesh.\\n"]],[]],[[[41,[28,[37,6],[[33,1,["Kind"]],"api-gateway"],null],[[[1," API gateways enable ingress traffic from services outside the Consul service mesh to services inside the Consul service mesh.\\n"]],[]],[[[1," Mesh gateways enable routing of Connect traffic between different Consul datacenters.\\n "]],[]]]],[]]]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,"role","separator"],[12],[1,"\\n"],[41,[28,[37,6],[[33,1,["Kind"]],"ingress-gateway"],null],[[[1," About Ingress gateways\\n"]],[]],[[[41,[28,[37,6],[[33,1,["Kind"]],"terminating-gateway"],null],[[[1," About Terminating gateways\\n"]],[]],[[[41,[28,[37,6],[[33,1,["Kind"]],"api-gateway"],null],[[[1," About API gateways\\n"]],[]],[[[1," About Mesh gateways\\n "]],[]]]],[]]]],[]]],[1," "],[13],[1,"\\n"],[44,[[28,[37,8],[[28,[37,9],[[28,[37,9],["ingress-gateway","/consul/developer-mesh/ingress-gateways"],null],[28,[37,9],["terminating-gateway","/consul/developer-mesh/understand-terminating-gateways"],null],[28,[37,9],["mesh-gateway","/consul/developer-mesh/connect-gateways"],null]],null]],null]],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"learn-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,10],[[28,[37,11],["CONSUL_DOCS_LEARN_URL"],null],[28,[37,12],[[30,1],[33,1,["Kind"]]],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n Learn guides\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[1]]],[44,[[28,[37,8],[[28,[37,9],[[28,[37,9],["ingress-gateway","/connect/gateways/ingress-gateway"],null],[28,[37,9],["terminating-gateway","/connect/gateways/terminating-gateway"],null],[28,[37,9],["api-gateway","/connect/gateways/api-gateway"],null],[28,[37,9],["mesh-gateway","/connect/gateways/mesh-gateway"],null]],null]],null]],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,10],[[28,[37,11],["CONSUL_DOCS_URL"],null],[28,[37,12],[[30,2],[33,1,["Kind"]]],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n Documentation\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[14,"role","separator"],[12],[1,"\\n Other gateway types\\n "],[13],[1,"\\n"],[41,[28,[37,13],[[33,1,["Kind"]],"mesh-gateway"],null],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,10],[[28,[37,11],["CONSUL_DOCS_URL"],null],[28,[37,12],[[30,2],"mesh-gateway"],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n Mesh gateways\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,13],[[33,1,["Kind"]],"terminating-gateway"],null],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,10],[[28,[37,11],["CONSUL_DOCS_URL"],null],[28,[37,12],[[30,2],"terminating-gateway"],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n Terminating gateways\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,13],[[33,1,["Kind"]],"ingress-gateway"],null],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,10],[[28,[37,11],["CONSUL_DOCS_URL"],null],[28,[37,12],[[30,2],"ingress-gateway"],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n Ingress gateways\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,13],[[33,1,["Kind"]],"api-gateway"],null],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[28,[37,10],[[28,[37,11],["CONSUL_DOCS_URL"],null],[28,[37,12],[[30,2],"api-gateway"],null]],null]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n API gateways\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[2]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,1],[14,0,"consul-kind"],[12],[1,"\\n "],[1,[34,3]],[1,"\\n "],[13],[1,"\\n"]],[]]]],[]],null]],["link","link"],false,["if","item","withInfo","Name","menu-panel","block-slot","eq","let","from-entries","array","concat","env","get","not-eq"]]',moduleName:"consul-ui/components/consul/kind/index.hbs",isStrictMode:!1}),a={"api-gateway":"API Gateway","mesh-gateway":"Mesh Gateway","ingress-gateway":"Ingress Gateway","terminating-gateway":"Terminating Gateway"} +var u=(0,t.setComponentTemplate)(o,t.default.extend({tagName:"",Name:(0,l.computed)("item.Kind",(function(){const e=a[this.item.Kind] +return e||(0,r.titleize)((0,i.humanize)(this.item.Kind))}))})) +e.default=u})),define("consul-ui/components/consul/kv/form/index",["exports","@ember/component","@ember/template-factory","@ember/object","@ember/service"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i=(0,n.createTemplateFactory)({id:"CDb8CUMa",block:'[[[1,"\\n"],[8,[39,0],null,[["@dc","@nspace","@partition","@type","@label","@autofill","@item","@src","@onchange","@onsubmit"],[[99,1,["@dc"]],[99,2,["@nspace"]],[99,3,["@partition"]],"kv","key",[99,4,["@autofill"]],[99,5,["@item"]],[99,6,["@src"]],[28,[37,7],[[30,0],"change"],null],[28,[37,7],[[30,0],[33,8]],null]]],[["default"],[[[[1,"\\n "],[8,[39,9],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,11],["write kv"],[["item"],[[30,1,["data"]]]]]],[[[1," "],[10,"form"],[15,"onsubmit",[28,[37,7],[[30,0],[30,1,["submit"]]],null]],[12],[1,"\\n "],[11,"fieldset"],[4,[38,12],[[28,[37,13],[[30,2],[30,1,["disabled"]]],null]],null],[12],[1,"\\n"],[41,[30,1,["isCreate"]],[[[1," "],[10,"label"],[15,0,[29,["type-text",[52,[30,1,["data","error","Key"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Key or folder"],[13],[1,"\\n "],[10,"input"],[14,"autofocus","autofocus"],[15,2,[28,[37,15],[[30,1,["data","Key"]],[33,16]],null]],[14,3,"additional"],[15,"oninput",[28,[37,7],[[30,0],[30,1,["change"]]],null]],[14,"placeholder","Key or folder"],[14,4,"text"],[12],[13],[1,"\\n "],[10,"em"],[12],[1,"To create a folder, end a key with "],[10,"code"],[12],[1,"/"],[13],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,13],[[28,[37,17],[[28,[37,15],[[30,1,["data","Key"]],[33,16]],null],""],null],[28,[37,18],[[28,[37,19],[[30,1,["data","Key"]]],null],"/"],null]],null],[[[1," "],[10,0],[12],[1,"\\n "],[10,0],[14,0,"type-toggle"],[12],[1,"\\n "],[10,"label"],[12],[1,"\\n "],[11,"input"],[24,3,"json"],[16,"checked",[52,[33,20],"checked"]],[16,"onchange",[28,[37,7],[[30,0],[30,1,["change"]]],null]],[24,4,"checkbox"],[4,[38,12],[false],null],[12],[13],[1,"\\n "],[10,1],[12],[1,"Code"],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[10,"label"],[14,"for",""],[15,0,[29,["type-text",[52,[30,1,["data","error","Value"]]," has-error"]]]],[12],[1,"\\n"],[41,[33,20],[[[1," "],[8,[39,21],null,[["@name","@readonly","@value","@onkeyup"],["value",[28,[37,13],[[30,2],[30,1,["disabled"]]],null],[28,[37,22],[[30,1,["data","Value"]]],null],[28,[37,7],[[30,0],[30,1,["change"]],"value"],null]]],[["label"],[[[[1,"Value"]],[]]]]],[1,"\\n"]],[]],[[[1," "],[10,1],[12],[1,"Value"],[13],[1,"\\n "],[11,"textarea"],[16,"autofocus",[28,[37,23],[[30,1,["isCreate"]]],null]],[24,3,"value"],[16,"oninput",[28,[37,7],[[30,0],[30,1,["change"]]],null]],[4,[38,12],[[28,[37,13],[[30,2],[30,1,["disabled"]]],null]],null],[12],[1,[28,[35,22],[[30,1,["data","Value"]]],null]],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[8,[39,24],null,null,[["default"],[[[[1,"\\n"],[41,[30,1,["isCreate"]],[[[41,[28,[37,23],[[30,2]],null],[[[1," "],[8,[39,25],[[16,"disabled",[28,[37,13],[[30,1,["data","isPristine"]],[30,1,["data","isInvalid"]],[30,1,["disabled"]]],null]],[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,25],[[16,"disabled",[30,1,["disabled"]]],[16,"onclick",[28,[37,7],[[30,0],[33,26],[30,1,["data"]]],null]],[24,4,"reset"]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"]],[]],[[[41,[28,[37,23],[[30,2]],null],[[[1," "],[8,[39,25],[[16,"disabled",[28,[37,13],[[30,1,["data","isInvalid"]],[30,1,["disabled"]]],null]],[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,25],[[16,"disabled",[30,1,["disabled"]]],[16,"onclick",[28,[37,7],[[30,0],[33,26],[30,1,["data"]]],null]],[24,4,"reset"]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"],[41,[28,[37,23],[[30,2]],null],[[[1," "],[8,[39,27],null,[["@message"],["Are you sure you want to delete this key?"]],[["default"],[[[[1,"\\n "],[8,[39,9],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,25],[[16,"disabled",[30,1,["disabled"]]],[4,[38,28],["click",[28,[37,7],[[30,0],[30,3],[30,1,["delete"]]],null]],null]],[["@text","@color"],["Delete","critical"]],null],[1,"\\n "]],[3]]]]],[1,"\\n "],[8,[39,9],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@message","@execute","@cancel"],[[30,6],[30,4],[30,5]]],null],[1,"\\n "]],[4,5,6]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null]],[]]],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[2]]],[1," "]],[]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["api","disabld","confirm","execute","cancel","message"],false,["data-form","dc","nspace","partition","autofill","item","src","action","onsubmit","block-slot","let","cannot","disabled","or","if","left-trim","parent","eq","not-eq","last","json","code-editor","atob","not","hds/button-set","hds/button","oncancel","confirmation-dialog","on","delete-confirmation"]]',moduleName:"consul-ui/components/consul/kv/form/index.hbs",isStrictMode:!1}) +var o=(0,t.setComponentTemplate)(i,t.default.extend({tagName:"",encoder:(0,r.inject)("btoa"),json:!0,ondelete:function(){this.onsubmit(...arguments)},oncancel:function(){this.onsubmit(...arguments)},onsubmit:function(){},actions:{change:function(e,t){const n=t.getData() +try{t.handleEvent(e)}catch(r){const t=e.target +let i +switch(t.name){case"value":(0,l.set)(n,"Value",this.encoder.execute(t.value)) +break +case"additional":i=this.parent,(0,l.set)(n,"Key",`${"/"!==i?i:""}${t.value}`) +break +case"json":(0,l.set)(this,"json",!this.json) +break +default:throw r}}}}})) +e.default=o})),define("consul-ui/components/consul/kv/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"sbZrWnGU",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-kv-list"],[17,1]],[["@items"],[[30,2]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[12],[1,"Name"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["row"]],[["default"],[[[[1,"\\n "],[10,"td"],[15,0,[52,[30,3,["isFolder"]],"folder","file"]],[12],[1,"\\n "],[10,3],[15,6,[28,[37,3],[[52,[30,3,["isFolder"]],"dc.kv.folder","dc.kv.edit"],[30,3,["Key"]]],null]],[12],[1,[28,[35,4],[[28,[37,5],[[30,3,["Key"]],[30,5,["Key"]]],null],"/"],null]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@expanded","@onchange","@keyboardAccess"],[[52,[28,[37,7],[[30,8],[30,6]],null],true,false],[28,[37,8],[[30,0],[30,7],[30,6]],null],false]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n More\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n"],[41,[28,[37,9],["write kv"],[["item"],[[30,3]]]],[[[1," "],[10,"li"],[14,"role","none"],[12],[1,"\\n "],[10,3],[14,"role","menuitem"],[14,"tabindex","-1"],[15,6,[28,[37,3],[[52,[30,3,["isFolder"]],"dc.kv.folder","dc.kv.edit"],[30,3,["Key"]]],null]],[12],[1,[52,[30,3,["isFolder"]],"View","Edit"]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[14,"role","none"],[14,0,"dangerous"],[12],[1,"\\n "],[10,"label"],[15,"for",[30,9]],[14,"role","menuitem"],[14,"tabindex","-1"],[15,"onkeypress",[30,11]],[12],[1,"Delete"],[13],[1,"\\n "],[10,0],[14,"role","menu"],[12],[1,"\\n "],[8,[39,10],[[24,0,"warning"]],null,[["header","body","actions"],[[[[1,"\\n Confirm Delete\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this KV entry?\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,12,["Action"]],[[24,0,"dangerous"]],null,[["default"],[[[[1,"\\n "],[8,[39,8],[[24,0,"type-delete"],[24,"tabindex","-1"],[4,[38,11],["click",[28,[37,12],[[28,[37,8],[[30,0],[30,7]],null],[28,[37,8],[[30,0],[30,13],[30,3]],null]],null]],null]],null,[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,12,["Action"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@for"],[[30,9]]],[["default"],[[[[1,"\\n Cancel\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[12]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,"li"],[14,"role","none"],[12],[1,"\\n "],[10,3],[14,"role","menuitem"],[14,"tabindex","-1"],[15,6,[28,[37,3],[[52,[30,3,["isFolder"]],"dc.kv.folder","dc.kv.edit"],[30,3,["Key"]]],null]],[12],[1,"View"],[13],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[9,10,11]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6,7,8]]]]],[1,"\\n"]],[3,4]]]]]],["&attrs","@items","item","index","@parent","index","change","checked","confirm","send","keypressClick","Actions","@delete"],false,["tabular-collection","block-slot","if","href-to","right-trim","left-trim","popover-menu","eq","action","can","informed-action","on","queue"]]',moduleName:"consul-ui/components/consul/kv/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/kv/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"zAAbqFtP",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-kv-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.kv.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.kv.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n"],[41,[30,2,["searchproperty"]],[[[1," "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,10],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,11],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-kind"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["kind","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.kv.search-bar.kind.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["folder","key"],null]],null]],null],null,[[[1," "],[8,[30,16],[[24,0,"value-{item}}"]],[["@value","@selected"],[[30,17],[28,[37,10],[[30,17],[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.kv.search-bar.kind.options.",[30,17]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,18,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,19,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,12],[[28,[37,4],[[28,[37,4],["Key:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Key:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["Kind:asc",[28,[37,2],["components.consul.kv.search-bar.sort.kind.asc"],null]],null],[28,[37,4],["Kind:desc",[28,[37,2],["components.consul.kv.search-bar.sort.kind.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,13],[[30,21],[30,19,["value"]]],null]],[1,"\\n"]],[21]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,20,["Optgroup"]],[30,20,["Option"]]],[[[1," "],[8,[30,22],null,[["@label"],[[28,[37,2],["common.consul.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Key:asc",[28,[37,14],["Key:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Key:desc",[28,[37,14],["Key:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,22],null,[["@label"],[[28,[37,2],["components.consul.kv.search-bar.kind.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Kind:asc",[28,[37,14],["Kind:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["components.consul.kv.search-bar.sort.kind.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Kind:desc",[28,[37,14],["Kind:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["components.consul.kv.search-bar.sort.kind.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22,23]]],[1," "]],[]]]]],[1,"\\n "]],[20]]]]],[1,"\\n "]],[18]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","item","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","if","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/kv/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/loader/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"FplgL0cl",block:'[[[1,"\\n"],[11,0],[24,0,"consul-loader"],[17,1],[12],[1,"\\n "],[10,"svg"],[14,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[14,"xmlns:xlink","http://www.w3.org/1999/xlink","http://www.w3.org/2000/xmlns/"],[14,"width","44px"],[14,"height","44px"],[14,"viewBox","0 0 44 44"],[14,"version","1.1"],[12],[1,"\\n "],[10,"g"],[12],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","27"],[14,"cy","2"],[14,5,"transform-origin: 27px 2px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","17"],[14,"cy","2"],[14,5,"transform-origin: 17px 2px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","27"],[14,"cy","42"],[14,5,"transform-origin: 27px 42px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","17"],[14,"cy","42"],[14,5,"transform-origin: 17px 42px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","2"],[14,"cy","17"],[14,5,"transform-origin: 2px 17px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","2"],[14,"cy","27"],[14,5,"transform-origin: 2px 27px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","42"],[14,"cy","17"],[14,5,"transform-origin: 42px 17px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","42"],[14,"cy","27"],[14,5,"transform-origin: 42px 27px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","33"],[14,"cy","4"],[14,5,"transform-origin: 33px 4px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","11"],[14,"cy","4"],[14,5,"transform-origin: 11px 4px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","33"],[14,"cy","40"],[14,5,"transform-origin: 33px 40px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","11"],[14,"cy","40"],[14,5,"transform-origin: 11px 40px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","40"],[14,"cy","11"],[14,5,"transform-origin: 40px 11px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","4"],[14,"cy","33"],[14,5,"transform-origin: 4px 33px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","40"],[14,"cy","33"],[14,5,"transform-origin: 40px 33px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","1"],[14,"cx","4"],[14,"cy","11"],[14,5,"transform-origin: 4px 11px"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[12],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","22"],[14,"cy","4"],[14,5,"transform-origin: 22px 4px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","22"],[14,"cy","40"],[14,5,"transform-origin: 22px 40px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","4"],[14,"cy","22"],[14,5,"transform-origin: 4px 22px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","40"],[14,"cy","22"],[14,5,"transform-origin: 40px 22px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","9"],[14,"cy","9"],[14,5,"transform-origin: 9px 9px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","35"],[14,"cy","35"],[14,5,"transform-origin: 35px 35px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","35"],[14,"cy","9"],[14,5,"transform-origin: 35px 9px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","9"],[14,"cy","35"],[14,5,"transform-origin: 9px 35px"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[12],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","28"],[14,"cy","8"],[14,5,"transform-origin: 28px 8px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","16"],[14,"cy","8"],[14,5,"transform-origin: 16px 8px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","28"],[14,"cy","36"],[14,5,"transform-origin: 28px 36px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","16"],[14,"cy","36"],[14,5,"transform-origin: 16px 36px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","8"],[14,"cy","28"],[14,5,"transform-origin: 8px 28px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","8"],[14,"cy","16"],[14,5,"transform-origin: 8px 16px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","36"],[14,"cy","28"],[14,5,"transform-origin: 36px 28px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","2"],[14,"cx","36"],[14,"cy","16"],[14,5,"transform-origin: 36px 16px"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[12],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","22"],[14,"cy","12"],[14,5,"transform-origin: 22px 12px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","22"],[14,"cy","32"],[14,5,"transform-origin: 22px 32px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","12"],[14,"cy","22"],[14,5,"transform-origin: 12px 22px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","32"],[14,"cy","22"],[14,5,"transform-origin: 32px 22px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","15"],[14,"cy","15"],[14,5,"transform-origin: 15px 15px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","29"],[14,"cy","29"],[14,5,"transform-origin: 29px 29px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","29"],[14,"cy","15"],[14,5,"transform-origin: 29px 15px"],[12],[13],[1,"\\n "],[10,"circle"],[14,"r","5"],[14,"cx","15"],[14,"cy","29"],[14,5,"transform-origin: 15px 29px"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[12],[1,"\\n "],[10,"circle"],[14,"r","9"],[14,"cx","22"],[14,"cy","22"],[14,5,"transform-origin: 22px 22px"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs"],false,[]]',moduleName:"consul-ui/components/consul/loader/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/lock-session/form/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"siqBOmFq",block:'[[[1,"\\n"],[11,0],[24,0,"consul-lock-session-form"],[17,1],[12],[1,"\\n "],[8,[39,0],null,[["@sink","@type","@label","@ondelete","@onchange"],[[28,[37,1],["/${partition}/${nspace}/${dc}/session",[28,[37,2],null,[["partition","nspace","dc"],[[30,2,["Partition"]],[30,2,["Namespace"]],[30,2,["Datacenter"]]]]]],null],"session","Lock Session",[28,[37,3],[[52,[30,3],[30,3],[30,4]],[30,2]],null],[28,[37,3],[[28,[37,5],[[30,4]],null],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,7],[[4,[38,8],null,[["after"],[[28,[37,9],[[30,0],[30,6]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[6]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],[[4,[38,8],null,[["after"],[[28,[37,9],[[30,0],[30,7]],null]]]]],[["@type","@error"],["remove",[30,8]]],null],[1,"\\n "]],[7,8]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n"],[41,[30,2,["Name"]],[[[1," "],[10,"dt"],[12],[1,"Name"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,2,["Name"]]],[13],[1,"\\n"]],[]],null],[1," "],[10,"dt"],[12],[1,"ID"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,2,["ID"]]],[13],[1,"\\n "],[10,"dt"],[12],[1,"Node"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,10],null,[["@text","@icon","@href","@isHrefExternal","@size","@color"],[[30,2,["Node"]],"git-commit",[28,[37,11],["dc.nodes.show",[30,2,["Node"]]],null],false,"small","tertiary"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,"Delay"],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,12],[[30,2,["LockDelay"]]],null]],[13],[1,"\\n "],[10,"dt"],[12],[1,"TTL"],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,13],[[30,2,["TTL"]],"-"],null]],[13],[1,"\\n "],[10,"dt"],[12],[1,"Behavior"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,2,["Behavior"]]],[13],[1,"\\n"],[44,[[30,2,["checks"]]],[[[1," "],[10,"dt"],[12],[1,"Health Checks"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[41,[28,[37,15],[[30,9,["length"]],0],null],[[[1," "],[1,[28,[35,16],[", ",[30,9]],null]],[1,"\\n"]],[]],[[[1," -\\n"]],[]]],[1," "],[13],[1,"\\n"]],[9]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,17],["delete session"],[["item"],[[30,2]]]],[[[1," "],[8,[39,18],null,[["@message"],["Are you sure you want to invalidate this Lock Session?"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,10],[[4,[38,19],["click",[28,[37,3],[[30,10],[28,[37,3],[[30,5,["delete"]],[30,2]],null]],null]],null]],[["@text","@color"],["Invalidate Session","critical"]],null],[1,"\\n "]],[10]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[30,13]],[1,"\\n "],[13],[1,"\\n "],[8,[39,20],null,null,[["default"],[[[[1,"\\n "],[8,[39,10],[[4,[38,19],["click",[28,[37,3],[[30,11]],null]],null]],[["@text","@color"],["Confirm Invalidation","critical"]],null],[1,"\\n "],[8,[39,10],[[4,[38,19],["click",[28,[37,3],[[30,12]],null]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[11,12,13]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"],[13]],["&attrs","@item","@ondelete","@onsubmit","writer","after","after","error","checks","confirm","execute","cancel","message"],false,["data-writer","uri","hash","fn","if","optional","block-slot","consul/lock-session/notifications","notification","action","hds/button","href-to","duration-from","or","let","gt","join","can","confirmation-dialog","on","hds/button-set"]]',moduleName:"consul-ui/components/consul/lock-session/form/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/lock-session/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"W2kUeHox",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-lock-session-list"],[17,1]],[["@items"],[[30,2]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[30,3,["Name"]],[[[1," "],[10,1],[12],[1,[30,3,["Name"]]],[13],[1,"\\n"]],[]],[[[1," "],[10,1],[12],[1,"\\n "],[1,[30,3,["ID"]]],[1,"\\n "],[8,[39,3],null,[["@value","@name"],[[30,3,["ID"]],"ID"]],null],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n"],[41,[30,3,["Name"]],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n ID\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,3],null,[["@value","@name"],[[30,3,["ID"]],"ID"]],null],[1,"\\n "],[1,[30,3,["ID"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[10,"dl"],[14,0,"lock-delay"],[12],[1,"\\n "],[11,"dt"],[4,[38,4],null,null],[12],[1,"\\n Delay\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,5],[[30,3,["LockDelay"]]],null]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[14,0,"ttl"],[12],[1,"\\n "],[11,"dt"],[4,[38,4],null,null],[12],[1,"\\n TTL\\n "],[13],[1,"\\n"],[41,[28,[37,6],[[30,3,["TTL"]],""],null],[[[1," "],[10,"dd"],[12],[1,"-"],[13],[1,"\\n"]],[]],[[[1," "],[10,"dd"],[12],[1,[30,3,["TTL"]]],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[10,"dl"],[14,0,"behavior"],[12],[1,"\\n "],[11,"dt"],[4,[38,4],null,null],[12],[1,"\\n Behavior\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,3,["Behavior"]]],[13],[1,"\\n "],[13],[1,"\\n"],[44,[[28,[37,8],[[30,3,["NodeChecks"]],[30,3,["ServiceChecks"]]],null]],[[[1," "],[10,"dl"],[14,0,"checks"],[12],[1,"\\n "],[11,"dt"],[4,[38,4],null,null],[12],[1,"\\n Checks\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[41,[28,[37,9],[[30,5,["length"]],0],null],[[[42,[28,[37,11],[[28,[37,11],[[30,5]],null]],null],null,[[[1," "],[10,1],[12],[1,[30,6]],[13],[1,"\\n"]],[6]],null]],[]],[[[1," -\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[5]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@message"],["Are you sure you want to invalidate this session?"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,13],[[4,[38,14],["click",[28,[37,15],[[30,7],[28,[37,15],[[30,8],[30,3]],null]],null]],null]],[["@text","@color"],["Invalidate","critical"]],null],[1,"\\n "]],[7]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[30,11]],[1,"\\n "],[13],[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n "],[8,[39,13],[[4,[38,14],["click",[28,[37,15],[[30,9]],null]],null]],[["@text","@color"],["Confirm Invalidate","critical"]],null],[1,"\\n "],[8,[39,13],[[4,[38,14],["click",[28,[37,15],[[30,10]],null]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[9,10,11]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4]]]]]],["&attrs","@items","item","index","checks","item","confirm","@ondelete","execute","cancel","message"],false,["list-collection","block-slot","if","consul-copy-button","tooltip","duration-from","eq","let","union","gt","each","-track-array","confirmation-dialog","hds/button","on","fn","hds/button-set"]]',moduleName:"consul-ui/components/consul/lock-session/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/lock-session/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"31+K+XMy",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1],"remove"],null],[[[41,[30,2],[[[1," "],[8,[39,2],[[17,3]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,4,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,4,["Description"]],null,null,[["default"],[[[[1,"\\n There was an error invalidating the Lock Session.\\n"],[41,[28,[37,3],[[30,2,["status"]],[30,2,["detail"]]],null],[[[1," "],[10,"br"],[12],[13],[1,[30,2,["status"]]],[1,": "],[1,[30,2,["detail"]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,2],[[17,3]],[["@color"],["success"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Success!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"\\n Your Lock Session has been invalidated.\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"kv"],null],[[[1," "],[8,[39,4],[[24,0,"mb-3"]],[["@type","@color"],["inline","warning"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Warning"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"This KV has a lock session. You can edit KV\'s with lock sessions, but we recommend doing so with care, or not doing so at all. It may negatively impact the active node it\'s associated with. See below for more details on the Lock Session."]],[]]]]],[1,"\\n "],[8,[30,6,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition"],["Learn more",[29,[[28,[37,5],["CONSUL_DOCS_URL"],null],"/internals/sessions.html"]],"docs-link","trailing"]],null],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],null]],[]]]],["@type","@error","&attrs","T","T","A"],false,["if","eq","hds/toast","and","hds/alert","env"]]',moduleName:"consul-ui/components/consul/lock-session/notifications/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/metadata/list/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"8Eqo0Hvc",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-metadata-list"]],[["@items"],[[99,1,["@items"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[12],[1,"Key"],[13],[1,"\\n "],[10,"th"],[12],[1,"Value"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,2],null,[["@name"],["row"]],[["default"],[[[[1,"\\n "],[10,"td"],[12],[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,3],[0,[30,1]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[12],[1,"\\n "],[10,1],[12],[1,[28,[35,3],[1,[30,1]],null]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[1,2]]]]],[1,"\\n"]],["item","index"],false,["tabular-collection","items","block-slot","object-at"]]',moduleName:"consul-ui/components/consul/metadata/list/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) +e.default=r})),define("consul-ui/components/consul/node-identity/template/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"FtkBULd3",block:'[[[1,"\\n"],[41,[28,[37,1],["use partitions"],null],[[[1,"partition \\""],[1,[28,[35,2],[[30,1],"default"],null]],[1,"\\" {\\n"],[41,[28,[37,1],["use nspaces"],null],[[[1," namespace \\"default\\" {\\n node \\""],[1,[30,2]],[1,"\\" {\\n\\t policy = \\"write\\"\\n }\\n }\\n namespace_prefix \\"\\" {\\n service_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n }\\n"]],[]],[[[1," node \\""],[1,[30,2]],[1,"\\" {\\n\\t policy = \\"write\\"\\n }\\n service_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n"]],[]]],[1,"}"]],[]],[[[41,[28,[37,1],["use nspaces"],null],[[[1,"namespace \\"default\\" {\\n node \\""],[1,[30,2]],[1,"\\" {\\n\\t policy = \\"write\\"\\n }\\n}\\nnamespace_prefix \\"\\" {\\n service_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n}\\n"]],[]],[[[1,"node \\""],[1,[30,2]],[1,"\\" {\\n\\tpolicy = \\"write\\"\\n}\\nservice_prefix \\"\\" {\\n\\tpolicy = \\"read\\"\\n}"]],[]]]],[]]]],["@partition","@name"],false,["if","can","or"]]',moduleName:"consul-ui/components/consul/node-identity/template/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/node/agentless-notice/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","consul-ui/services/local-storage"],(function(e,t,n,l,r,i){var o,a,u +function s(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const d=(0,n.createTemplateFactory)({id:"gCCXUOqK",block:'[[[1,"\\n"],[41,[33,1],[[[1," "],[8,[39,2],[[24,0,"mb-3 mt-2 agentless-node-notice"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,1,["Title"]],null,null,[["default"],[[[[1,"\\n "],[10,1],[12],[1,[28,[35,3],["routes.dc.nodes.index.agentless.notice.header"],null]],[13],[1,"\\n "],[8,[39,4],[[4,[38,5],["click",[30,0,["dismissAgentlessNotice"]]],null]],[["@color","@text","@icon","@size","@isIconOnly"],["secondary","Dismiss notice","x","small",true]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,1,["Description"]],null,null,[["default"],[[[[1,[28,[35,3],["routes.dc.nodes.index.agentless.notice.body"],null]]],[]]]]],[1,"\\n "],[8,[30,1,["Link::Standalone"]],null,[["@href","@text","@icon","@iconPosition"],[[29,[[28,[37,6],["CONSUL_DOCS_DEVELOPER_URL"],null],"/connect/dataplane"]],[28,[37,3],["routes.dc.nodes.index.agentless.notice.footer"],null],"docs-link","trailing"]],null],[1,"\\n "]],[1]]]]],[1,"\\n"]],[]],null]],["A"],false,["if","isVisible","hds/alert","t","hds/button","on","env"]]',moduleName:"consul-ui/components/consul/node/agentless-notice/index.hbs",isStrictMode:!1}) +let p=(o=(0,i.storageFor)("notices"),a=class extends l.default{constructor(){var e,t,n,l +super(...arguments),s(this,"storageKey","nodes-agentless-dismissed"),e=this,t="notices",l=this,(n=u)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),this.args.postfix&&(this.storageKey=`nodes-agentless-dismissed-${this.args.postfix}`)}get isVisible(){const{items:e,filteredItems:t}=this.args +return!this.notices.state.includes(this.storageKey)&&e.length>t.length}dismissAgentlessNotice(){this.notices.add(this.storageKey)}},u=c(a.prototype,"notices",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c(a.prototype,"dismissAgentlessNotice",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"dismissAgentlessNotice"),a.prototype),a) +e.default=p,(0,t.setComponentTemplate)(d,p)})),define("consul-ui/components/consul/node/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"+A6LiBf2",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-node-list"]],[["@items"],[[30,1]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"dl"],[15,0,[30,2,["Status"]]],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Health\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,2],null,[["@position"],["top-start"]],[["default"],[[[[1,"\\n"],[41,[28,[37,4],["critical",[30,2,["Status"]]],null],[[[1," At least one health check on this node is failing.\\n"]],[]],[[[41,[28,[37,4],["warning",[30,2,["Status"]]],null],[[[1," At least one health check on this node has a warning.\\n"]],[]],[[[41,[28,[37,4],["passing",[30,2,["Status"]]],null],[[[1," All health checks are passing.\\n"]],[]],[[[1," There are no health checks.\\n "]],[]]]],[]]]],[]]],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,3],[15,6,[28,[37,5],["dc.nodes.show",[30,2,["Node"]]],[["params"],[[28,[37,6],null,[["peer"],[[30,2,["PeerName"]]]]]]]]],[12],[1,"\\n "],[1,[30,2,["Node"]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@item"],[[30,2]]],null],[1,"\\n"],[41,[28,[37,4],[[30,2,["Address"]],[30,4,["Address"]]],null],[[[1," "],[10,1],[14,0,"leader"],[12],[1,"Leader"],[13],[1,"\\n"]],[]],null],[1," "],[10,1],[12],[1,"\\n "],[1,[28,[35,8],[[30,2,["MeshServiceInstances","length"]]],null]],[1," "],[1,[28,[35,9],[[30,2,["MeshServiceInstances","length"]],"Service"],[["without-count"],[true]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[10,1],[12],[1,"Address"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,10],null,[["@value","@name"],[[30,2,["Address"]],"Address"]],null],[1,"\\n "],[1,[30,2,["Address"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[10,1],[12],[1,"ConsulVersion"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[41,[30,2,["Meta","consul-version"]],[[[1," "],[8,[39,11],[[24,0,"w-4 h-4"]],[["@size","@name","@stretched"],["24","consul-color",true]],null],[1,"\\n "],[10,1],[12],[1,"v"],[1,[30,2,["Meta","consul-version"]]],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[2,3]]]]],[1,"\\n"]],["@items","item","index","@leader"],false,["list-collection","block-slot","tooltip","if","eq","href-to","hash","consul/node/peer-info","format-number","pluralize","consul-copy-button","flight-icon"]]',moduleName:"consul-ui/components/consul/node/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/node/peer-info/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"ufFBkLZx",block:'[[[1,"\\n"],[41,[30,1,["PeerName"]],[[[1," "],[10,1],[14,0,"consul-node-peer-info"],[12],[1,"\\n "],[11,"svg"],[24,"width","16"],[24,"height","16"],[24,"viewBox","0 0 16 16"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[4,[38,1],["Peer"],null],[12],[1,"\\n "],[10,"path"],[14,"d","M16 8C16 7.80109 15.921 7.61032 15.7803 7.46967L12.2803 3.96967C11.9874 3.67678 11.5126 3.67678 11.2197 3.96967C10.9268 4.26256 10.9268 4.73744 11.2197 5.03033L14.1893 8L11.2197 10.9697C10.9268 11.2626 10.9268 11.7374 11.2197 12.0303C11.5126 12.3232 11.9874 12.3232 12.2803 12.0303L15.7803 8.53033C15.921 8.38968 16 8.19891 16 8Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M0.21967 8.53033C-0.0732233 8.23744 -0.0732233 7.76256 0.21967 7.46967L3.71967 3.96967C4.01256 3.67678 4.48744 3.67678 4.78033 3.96967C5.07322 4.26256 5.07322 4.73744 4.78033 5.03033L1.81066 8L4.78033 10.9697C5.07322 11.2626 5.07322 11.7374 4.78033 12.0303C4.48744 12.3232 4.01256 12.3232 3.71967 12.0303L0.21967 8.53033Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M5 7C4.44772 7 4 7.44772 4 8C4 8.55229 4.44772 9 5 9H5.01C5.56228 9 6.01 8.55229 6.01 8C6.01 7.44772 5.56228 7 5.01 7H5Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M7 8C7 7.44772 7.44772 7 8 7H8.01C8.56228 7 9.01 7.44772 9.01 8C9.01 8.55229 8.56228 9 8.01 9H8C7.44772 9 7 8.55229 7 8Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M11 7C10.4477 7 10 7.44772 10 8C10 8.55229 10.4477 9 11 9H11.01C11.5623 9 12.01 8.55229 12.01 8C12.01 7.44772 11.5623 7 11.01 7H11Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,1],[14,0,"consul-node-peer-info__name"],[12],[1,[30,1,["PeerName"]]],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],["@item"],false,["if","tooltip"]]',moduleName:"consul-ui/components/consul/node/peer-info/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/node/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"XAC5AQJw",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-node-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.node.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[52,[30,3,["status","value"]],[30,3,["status","value"]],[28,[37,2],[[28,[37,3],["components.consul.node.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,6],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,6],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,10],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,11],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-status"]],[["@position","@onchange","@multiple"],["left",[28,[37,6],[[30,0],[30,2,["status","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.consul.status"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["passing","warning","critical"],null]],null]],null],null,[[[1," "],[8,[30,16],[[16,0,[29,["value-",[30,17]]]]],[["@value","@selected"],[[30,17],[28,[37,10],[[30,17],[30,2,["status","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[30,17]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,17]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-version"]],[["@position","@onchange","@multiple"],["left",[28,[37,6],[[30,0],[30,2,["version","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.consul.version"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,18,["Optgroup"]],[30,18,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[30,21]],null]],null],null,[[[1," "],[8,[30,20],null,[["@value","@selected"],[[30,22],[28,[37,10],[[30,22],[30,2,["version","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,3],[[30,22],".x"],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22]],null]],[19,20]]],[1," "]],[]]]]],[1,"\\n "]],[18]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,23,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,6],[[30,0],[30,24,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,12],[[28,[37,4],[[28,[37,4],["Node:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Node:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["Status:asc",[28,[37,2],["common.sort.status.asc"],null]],null],[28,[37,4],["Status:desc",[28,[37,2],["common.sort.status.desc"],null]],null],[28,[37,4],["Version:asc",[28,[37,2],["common.sort.version.asc"],null]],null],[28,[37,4],["Version:desc",[28,[37,2],["common.sort.version.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,13],[[30,26],[30,24,["value"]]],null]],[1,"\\n"]],[26]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,25,["Optgroup"]],[30,25,["Option"]]],[[[1," "],[8,[30,27],null,[["@label"],[[28,[37,2],["common.consul.status"],null]]],[["default"],[[[[1,"\\n "],[8,[30,28],null,[["@value","@selected"],["Status:asc",[28,[37,14],["Status:asc",[30,24,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,28],null,[["@value","@selected"],["Status:desc",[28,[37,14],["Status:desc",[30,24,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,27],null,[["@label"],[[28,[37,2],["common.consul.node-name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,28],null,[["@value","@selected"],["Node:asc",[28,[37,14],["Node:asc",[30,24,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,28],null,[["@value","@selected"],["Node:desc",[28,[37,14],["Node:desc",[30,24,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,27],null,[["@label"],[[28,[37,2],["common.consul.version"],null]]],[["default"],[[[[1,"\\n "],[8,[30,28],null,[["@value","@selected"],["Version:asc",[28,[37,14],["Version:asc",[30,24,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.version.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,28],null,[["@value","@selected"],["Version:desc",[28,[37,14],["Version:desc",[30,24,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.version.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[27,28]]],[1," "]],[]]]]],[1,"\\n "]],[25]]]]],[1,"\\n "]],[23]]]]]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","state","components","Optgroup","Option","@versions","version","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","if","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/node/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})) +define("consul-ui/components/consul/nspace/form/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object"],(function(e,t,n,l,r){var i +function o(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const a=(0,n.createTemplateFactory)({id:"0A+rYSOU",block:'[[[1,"\\n"],[11,0],[24,0,"consul-nspace-form"],[17,1],[12],[1,"\\n "],[8,[39,0],null,[["@sink","@type","@label","@ondelete","@onchange"],[[28,[37,1],["/${partition}/${nspace}/${dc}/nspace",[28,[37,2],null,[["partition","nspace","dc"],["","",[30,2,["Datacenter"]]]]]],null],"nspace","Namespace",[28,[37,3],[[30,0,["onDelete"]],[30,2]],null],[28,[37,3],[[30,0,["onSubmit"]],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,5],[[4,[38,6],null,[["after"],[[28,[37,7],[[30,0],[30,4]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[4]]]]],[1,"\\n\\n "],[8,[39,4],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,9],[[28,[37,10],["write nspaces"],null]],null],[30,2],[28,[37,2],null,[["help","Name"],["Must be a valid DNS hostname. Must contain 1-64 characters (numbers, letters, and hyphens), and must begin with a letter. Once created, this cannot be changed.",[28,[37,11],[[28,[37,2],null,[["test","error"],["^[a-zA-Z0-9]([a-zA-Z0-9-]{0,62}[a-zA-Z0-9])?$","Name must be a valid DNS hostname."]]]],null]]]],[28,[37,2],null,[["Description"],[[28,[37,11],null,null]]]]],[[[1," "],[11,"form"],[4,[38,12],["submit",[28,[37,3],[[30,3,["persist"]],[30,6]],null]],null],[4,[38,13],[[30,5]],null],[12],[1,"\\n\\n "],[8,[39,14],null,[["@src"],[[28,[37,14],["validate"],null]]],[["default"],[[[[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n"],[41,[28,[37,16],["new nspace"],[["item"],[[30,6]]]],[[[1," "],[8,[39,17],null,[["@name","@placeholder","@item","@validations","@chart"],["Name","Name",[30,6],[30,7],[28,[37,2],null,[["state","dispatch"],[[30,13],[30,12]]]]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,17],null,[["@expanded","@name","@label","@item","@validations","@chart"],[true,"Description","Description (Optional)",[30,6],[30,8],[28,[37,2],null,[["state","dispatch"],[[30,13],[30,12]]]]]],null],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,10],["use acls"],null],[[[1," "],[10,"fieldset"],[14,1,"roles"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Roles"],[13],[1,"\\n "],[10,2],[12],[1,"\\n"],[41,[28,[37,10],["write nspace"],[["item"],[[30,6]]]],[[[1," By adding roles to this namespaces, you will apply them to\\n all tokens created within this namespace.\\n"]],[]],[[[1," The following roles are applied to all tokens created within\\n this namespace.\\n"]],[]]],[1," "],[13],[1,"\\n "],[8,[39,18],null,[["@dc","@nspace","@partition","@disabled","@items"],[[30,14],"default",[30,15],[30,5],[30,6,["ACLs","RoleDefaults"]]]],null],[1,"\\n "],[13],[1,"\\n "],[10,"fieldset"],[14,1,"policies"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Policies"],[13],[1,"\\n "],[10,2],[12],[1,"\\n"],[41,[28,[37,9],[[30,5]],null],[[[1," By adding policies to this namespace, you will apply them to\\n all tokens created within this namespace.\\n"]],[]],[[[1," The following policies are applied to all tokens created\\n within this namespace.\\n"]],[]]],[1," "],[13],[1,"\\n "],[8,[39,19],null,[["@dc","@nspace","@partition","@disabled","@allowIdentity","@items"],[[30,14],"default",[30,15],[30,5],false,[30,6,["ACLs","PolicyDefaults"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[10,0],[12],[1,"\\n "],[8,[39,20],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,21],[[28,[37,16],["new nspace"],[["item"],[[30,6]]]],[28,[37,10],["create nspaces"],null]],null],[[[1," "],[8,[39,22],[[16,"disabled",[28,[37,23],[[28,[37,16],["pristine nspace"],[["item"],[[30,6]]]],[28,[37,24],[[30,13],"error"],null]],null]],[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n"]],[]],[[[41,[28,[37,10],["write nspace"],[["item"],[[30,6]]]],[[[1," "],[8,[39,22],[[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n "]],[]],null]],[]]],[1,"\\n "],[8,[39,22],[[24,4,"reset"],[4,[38,12],["click",[28,[37,3],[[30,0,["onCancel"]],[30,6]],null]],null]],[["@color","@text"],["secondary","Cancel"]],null],[1,"\\n\\n"],[41,[28,[37,21],[[28,[37,9],[[28,[37,16],["new nspace"],[["item"],[[30,6]]]]],null],[28,[37,10],["delete nspace"],[["item"],[[30,6]]]]],null],[[[1," "],[8,[39,25],null,[["@message"],["Are you sure you want to delete this Namespace?"]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,22],[[4,[38,12],["click",[28,[37,3],[[30,16],[28,[37,3],[[30,3,["delete"]],[30,6]],null]],null]],null]],[["@color","@text"],["critical","Delete"]],null],[1,"\\n "]],[16]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@message","@execute","@cancel"],[[30,19],[30,17],[30,18]]],null],[1,"\\n "]],[17,18,19]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n "]],[9,10,11,12,13]]]]],[1,"\\n "],[13],[1,"\\n"]],[5,6,7,8]]],[1," "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n"],[13]],["&attrs","@item","writer","after","readOnly","item","Name","Description","State","Guard","ChartAction","dispatch","state","@dc","@partition","confirm","execute","cancel","message"],false,["data-writer","uri","hash","fn","block-slot","consul/nspace/notifications","notification","action","let","not","can","array","on","disabled","state-chart","if","is","text-input","role-selector","policy-selector","hds/button-set","and","hds/button","or","state-matches","confirmation-dialog","delete-confirmation"]]',moduleName:"consul-ui/components/consul/nspace/form/index.hbs",isStrictMode:!1}) +let u=(o((i=class extends l.default{onSubmit(e){const t=this.args.onsubmit +if(t)return t(e)}onDelete(e){const{onsubmit:t,ondelete:n}=this.args +return n?n(e):t?t(e):void 0}onCancel(e){const{oncancel:t,onsubmit:n}=this.args +return t?t(e):n?n(e):void 0}}).prototype,"onSubmit",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"onSubmit"),i.prototype),o(i.prototype,"onDelete",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"onDelete"),i.prototype),o(i.prototype,"onCancel",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"onCancel"),i.prototype),i) +e.default=u,(0,t.setComponentTemplate)(a,u)})),define("consul-ui/components/consul/nspace/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"5DLhAB/n",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-nspace-list"],[17,1]],[["@items","@linkable"],[[30,2],"linkable nspace"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[30,3,["DeletedAt"]],[[[1," "],[10,2],[12],[1,"\\n Deleting "],[1,[30,3,["Name"]]],[1,"...\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,6,[28,[37,3],["dc.nspaces.edit",[30,3,["Name"]]],null]],[12],[1,[30,3,["Name"]]],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n"],[41,[30,3,["Description"]],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Description"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,4],["CONSUL_ACLS_ENABLED"],null],[[[1," "],[8,[39,5],null,[["@item"],[[30,3]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,6],[[30,3,["DeletedAt"]]],null],[[[1," "],[8,[30,4],null,null,[["default"],[[[[1,"\\n "],[8,[30,5],null,[["@href"],[[28,[37,3],["dc.nspaces.edit",[30,3,["Name"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],["write nspace"],[["item"],[[30,3]]]],[[[1," Edit\\n"]],[]],[[[1," View\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,7],["delete nspace"],[["item"],[[30,3]]]],[[[1," "],[8,[30,5],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,8],[[30,0],[30,6],[30,3]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,7],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this namespace?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,8],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[5]]]]],[1,"\\n"]],[]],null],[1," "]],[4]]]]],[1,"\\n"]],[3]]]]]],["&attrs","@items","item","Actions","Action","@ondelete","Confirmation","Confirm"],false,["list-collection","block-slot","if","href-to","env","consul/token/ruleset/list","not","can","action"]]',moduleName:"consul-ui/components/consul/nspace/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/nspace/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"F/gWWJYk",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1],"remove"],null],[[[1," "],[8,[39,2],[[17,2]],[["@color"],["success"]],[["default"],[[[[1,"\\n "],[8,[30,3,["Title"]],null,null,[["default"],[[[[1,"Success!"]],[]]]]],[1,"\\n "],[8,[30,3,["Description"]],null,null,[["default"],[[[[1,"Your Namespace has been marked for deletion."]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n"]],[]],null]],["@type","&attrs","T"],false,["if","eq","hds/toast"]]',moduleName:"consul-ui/components/consul/nspace/notifications/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/nspace/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"DelkwCZ4",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-nspace-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.nspace.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.nspace.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,14,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,16],[30,14,["value"]]],null]],[1,"\\n"]],[16]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,15,["Optgroup"]],[30,15,["Option"]]],[[[1," "],[8,[30,17],null,[["@label"],[[28,[37,2],["common.consul.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["Name:asc",[28,[37,13],["Name:asc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["Name:desc",[28,[37,13],["Name:desc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17,18]]],[1," "]],[]]]]],[1,"\\n "]],[15]]]]],[1,"\\n "]],[13]]]]]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/nspace/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/nspace/selector/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"ZHMEj55d",block:'[[[1,"\\n"],[41,[28,[37,1],[[28,[37,2],["use nspaces"],null],[28,[37,2],["choose nspaces"],null]],null],[[[44,[[30,1],[52,[30,2],[28,[37,4],null,[["Name"],[[30,2]]]],[28,[37,4],null,[["Name"],["default"]]]],[28,[37,5],["dc.nspaces",[30,3,["Name"]]],null]],[[[1," "],[8,[30,4,["Title"]],[[24,0,"consul-side-nav__selector-title"]],null,[["default"],[[[[1,[28,[35,6],["components.hashicorp-consul.side-nav.nspaces.title"],null]]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@list","@items","@item","@key","@icon","@placeholder","@footerLink","@footerLinkText"],[[30,1],[28,[37,8],["Name:asc",[28,[37,9],["DeletedAt",[30,7]],null]],null],[30,5],"Name","folder",[28,[37,6],["components.hashicorp-consul.side-nav.nspaces.placeholder"],null],[28,[37,10],["dc.nspaces",[30,3,["Name"]]],null],[28,[37,6],["components.hashicorp-consul.side-nav.nspaces.footer"],null]]],[["default"],[[[[1,"\\n "],[8,[30,8,["Data"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,11],null,[["@src","@loading","@onchange"],[[28,[37,12],["/${partition}/*/${dc}/namespaces",[28,[37,4],null,[["partition","dc"],[[30,9],[30,3,["Name"]]]]]],null],"lazy",[28,[37,13],[[28,[37,14],[[30,10]],null]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,8,["Dropdown","Checkmark"]],null,[["@selected","@href","@isHrefExternal"],[[28,[37,15],[[30,5,["Name"]],[30,8,["item","Name"]]],null],[28,[37,10],["dc.services.index"],[["params"],[[28,[37,4],null,[["partition","nspace","peer","dc"],[[52,[28,[37,16],[[30,9,["length"]],0],null],[30,9],[27]],[30,8,["item","Name"]],[27],[30,3,["Name"]]]]]]]],false]],[["default"],[[[[1,"\\n "],[1,[30,8,["item","Name"]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n"]],[4,5,6]]]],[]],null]],["@list","@nspace","@dc","SNL","nspace","isManaging","@nspaces","Selector","@partition","@onchange"],false,["if","and","can","let","hash","is-href","t","nav-selector","sort-by","reject-by","href-to","data-source","uri","fn","optional","eq","gt"]]',moduleName:"consul-ui/components/consul/nspace/selector/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/partition/form/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"IFfwt6JG",block:'[[[1,"\\n"],[11,0],[24,0,"consul-partition-form"],[17,1],[12],[1,"\\n "],[8,[39,0],null,[["@sink","@type","@label","@ondelete","@onchange"],[[28,[37,1],["/${partition}/${nspace}/${dc}/partition",[28,[37,2],null,[["partition","nspace","dc"],["","",[30,2,["Datacenter"]]]]]],null],"partition","Partition",[28,[37,3],[[52,[30,3],[30,3],[30,4]],[30,2]],null],[28,[37,3],[[28,[37,5],[[30,4]],null],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,7],[[4,[38,8],null,[["after"],[[28,[37,9],[[30,0],[30,6]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[6]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,11],[[28,[37,12],["write partition"],null]],null],[30,2],[28,[37,2],null,[["help","Name"],["Must be a valid DNS hostname. Must contain 1-64 characters (numbers, letters, and hyphens), and must begin with a letter. Once created, this cannot be changed.",[28,[37,13],[[28,[37,2],null,[["test","error"],["^[a-zA-Z0-9]([a-zA-Z0-9-]{0,62}[a-zA-Z0-9])?$","Name must be a valid DNS hostname."]]]],null]]]],[28,[37,2],null,[["Description"],[[28,[37,13],null,null]]]]],[[[11,"form"],[4,[38,14],["submit",[28,[37,3],[[30,5,["persist"]],[30,8]],null]],null],[4,[38,15],[[30,7]],null],[12],[1,"\\n\\n"],[8,[39,16],null,[["@src"],[[28,[37,16],["validate"],null]]],[["default"],[[[[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n"],[41,[28,[37,17],["new partition"],[["item"],[[30,8]]]],[[[1," "],[8,[39,18],null,[["@name","@placeholder","@item","@validations","@chart"],["Name","Name",[30,8],[30,9],[28,[37,2],null,[["state","dispatch"],[[30,15],[30,14]]]]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,18],null,[["@expanded","@name","@label","@item","@validations","@chart"],[true,"Description","Description (Optional)",[30,8],[30,10],[28,[37,2],null,[["state","dispatch"],[[30,15],[30,14]]]]]],null],[1,"\\n "],[13],[1,"\\n\\n "],[10,0],[12],[1,"\\n "],[8,[39,19],null,null,[["default"],[[[[1,"\\n\\n\\n"],[41,[28,[37,20],[[28,[37,17],["new partition"],[["item"],[[30,8]]]],[28,[37,12],["create partitions"],null]],null],[[[1," "],[8,[39,21],[[16,"disabled",[28,[37,22],[[28,[37,17],["pristine partition"],[["item"],[[30,8]]]],[28,[37,23],[[30,15],"error"],null]],null]],[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n"]],[]],[[[41,[28,[37,11],[[30,7]],null],[[[1," "],[8,[39,21],[[24,4,"submit"]],[["@text"],["Save"]],null],[1,"\\n"]],[]],null]],[]]],[1," "],[8,[39,21],[[24,4,"reset"],[4,[38,14],["click",[52,[30,16],[28,[37,3],[[28,[37,5],[[30,16],[30,8]],null]],null],[28,[37,3],[[28,[37,5],[[30,4],[30,8]],null]],null]]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n\\n"],[41,[28,[37,20],[[28,[37,11],[[28,[37,17],["new partition"],[["item"],[[30,8]]]]],null],[28,[37,12],["delete partition"],[["item"],[[30,8]]]]],null],[[[1," "],[8,[39,24],null,[["@message"],["Are you sure you want to delete this Partition?"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,21],[[4,[38,14],["click",[28,[37,3],[[30,17],[28,[37,3],[[30,5,["delete"]],[30,8]],null]],null]],null]],[["@text","@color"],["Delete","critical"]],null],[1,"\\n "]],[17]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@message","@execute","@cancel"],[[30,20],[30,18],[30,19]]],null],[1,"\\n "]],[18,19,20]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n\\n"]],[11,12,13,14,15]]]]],[1,"\\n"],[13],[1,"\\n\\n"]],[7,8,9,10]]],[1," "]],[]]]]],[1,"\\n"]],[5]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@item","@ondelete","@onsubmit","writer","after","readOnly","item","Name","Description","State","Guard","ChartAction","dispatch","state","@oncancel","confirm","execute","cancel","message"],false,["data-writer","uri","hash","fn","if","optional","block-slot","consul/partition/notifications","notification","action","let","not","can","array","on","disabled","state-chart","is","text-input","hds/button-set","and","hds/button","or","state-matches","confirmation-dialog","delete-confirmation"]]',moduleName:"consul-ui/components/consul/partition/form/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/partition/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"x4HKpDnG",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-partition-list"],[17,1]],[["@items","@linkable"],[[30,2],"linkable partition"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[30,3,["DeletedAt"]],[[[1," "],[10,2],[12],[1,"\\n Deleting "],[1,[30,3,["Name"]]],[1,"...\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,6,[28,[37,3],["dc.partitions.edit",[30,3,["Name"]]],null]],[12],[1,[30,3,["Name"]]],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n"],[41,[30,3,["Description"]],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Description"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,4],[[30,3,["DeletedAt"]]],null],[[[1," "],[8,[30,4],null,null,[["default"],[[[[1,"\\n "],[8,[30,5],null,[["@href"],[[28,[37,3],["dc.partitions.edit",[30,3,["Name"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n"],[41,[28,[37,5],["write partition"],[["item"],[[30,3]]]],[[[1," Edit\\n"]],[]],[[[1," View\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,5],["delete partition"],[["item"],[[30,3]]]],[[[1," "],[8,[30,5],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,6],[[30,0],[30,6],[30,3]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,7],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this partition?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,8],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[5]]]]],[1,"\\n"]],[]],null],[1," "]],[4]]]]],[1,"\\n"]],[3]]]]],[1,"\\n"]],["&attrs","@items","item","Actions","Action","@ondelete","Confirmation","Confirm"],false,["list-collection","block-slot","if","href-to","not","can","action"]]',moduleName:"consul-ui/components/consul/partition/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/partition/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"PTUeou9E",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1],"remove"],null],[[[1," "],[8,[39,2],[[17,2]],[["@color"],["success"]],[["default"],[[[[1,"\\n "],[8,[30,3,["Title"]],null,null,[["default"],[[[[1,"Success!"]],[]]]]],[1,"\\n "],[8,[30,3,["Description"]],null,null,[["default"],[[[[1,"\\n Your Partition has been marked for deletion.\\n "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n"]],[]],null]],["@type","&attrs","T"],false,["if","eq","hds/toast"]]',moduleName:"consul-ui/components/consul/partition/notifications/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/partition/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"IuHkFeus",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-partition-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.nspace.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.nspace.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,14,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,16],[30,14,["value"]]],null]],[1,"\\n"]],[16]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,15,["Optgroup"]],[30,15,["Option"]]],[[[1," "],[8,[30,17],null,[["@label"],[[28,[37,2],["common.consul.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["Name:asc",[28,[37,13],["Name:asc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["Name:desc",[28,[37,13],["Name:desc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17,18]]],[1," "]],[]]]]],[1,"\\n "]],[15]]]]],[1,"\\n "]],[13]]]]]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/partition/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/partition/selector/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"kdZOlgGd",block:'[[[1,"\\n"],[44,[[30,1],[52,[30,2],[28,[37,2],null,[["Name"],[[30,2]]]],[28,[37,2],null,[["Name"],["default"]]]],[28,[37,3],["dc.partitions",[30,3,["Name"]]],null],[28,[37,4],["choose partitions"],[["dc"],[[30,3]]]]],[[[1," "],[8,[30,4,["Title"]],[[24,0,"consul-side-nav__selector-title"]],null,[["default"],[[[[1,[28,[35,5],["components.hashicorp-consul.side-nav.partitions.title"],null]]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@list","@items","@item","@key","@icon","@placeholder","@footerLink","@footerLinkText","@disabled"],[[30,1],[28,[37,7],["Name:asc",[28,[37,8],["DeletedAt",[30,8]],null]],null],[30,5],"Name","users",[28,[37,5],["components.hashicorp-consul.side-nav.partitions.placeholder"],null],[28,[37,9],["dc.partitions",[30,3,["Name"]]],null],[28,[37,5],["components.hashicorp-consul.side-nav.partitions.footer"],null],[28,[37,10],[[30,7]],null]]],[["default"],[[[[1,"\\n "],[8,[30,9,["Data"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,11],null,[["@src","@loading","@onchange"],[[28,[37,12],["/*/*/${dc}/partitions",[28,[37,2],null,[["dc"],[[30,3,["Name"]]]]]],null],"lazy",[28,[37,13],[[28,[37,14],[[30,10]],null]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[30,7],[[[1," "],[8,[30,9,["Dropdown","Checkmark"]],null,[["@selected","@href","@isHrefExternal"],[[28,[37,15],[[30,5,["Name"]],[30,9,["item","Name"]]],null],[52,[30,9,["item","href"]],[30,9,["item","href"]],[28,[37,9],["dc.services.index"],[["params"],[[28,[37,2],null,[["partition","nspace","peer","dc"],[[30,9,["item","Name"]],[27],[27],[30,3,["Name"]]]]]]]]],false]],[["default"],[[[[1,"\\n "],[1,[30,9,["item","Name"]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[9]]]]],[1,"\\n"]],[4,5,6,7]]]],["@list","@partition","@dc","SNL","partition","isManaging","canChoose","@partitions","Selector","@onchange"],false,["let","if","hash","is-href","can","t","nav-selector","sort-by","reject-by","href-to","not","data-source","uri","fn","optional","eq"]]',moduleName:"consul-ui/components/consul/partition/selector/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/address/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"TNoxeoLi",block:'[[[1,"\\n"],[8,[39,0],null,null,[["default"],[[[[1,"\\n"],[41,[30,1,["data","height"]],[[[1," "],[10,0],[15,5,[30,1,["data","fillRemainingHeightStyle"]]],[14,0,"overflow-y-scroll"],[12],[1,"\\n "],[8,[39,2],null,[["@tagName","@estimateHeight","@items"],["ul",[30,1,["data","height"]],[30,2]]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"px-3 h-12 border-bottom-primary flex items-center justify-between group"],[12],[1,"\\n "],[10,0],[14,0,"hds-typography-display-300 text-hds-foreground-strong hds-font-weight-semibold"],[12],[1,[30,3]],[13],[1,"\\n "],[8,[39,3],[[24,0,"opacity-0 group-hover:opacity-100"]],[["@value","@name"],[[30,3],"Address"]],null],[1,"\\n "],[13],[1,"\\n "]],[3,4]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[1]]]]]],["p","@items","address","index"],false,["providers/dimension","if","vertical-collection","consul-copy-button"]]',moduleName:"consul-ui/components/consul/peer/address/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/bento-box/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"3LY0GCin",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"mt-6 mb-3"]],[["@level","@hasBorder"],["base",true]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"flex h-24 p-6 overflow-x-auto space-x-12"],[12],[1,"\\n "],[10,0],[14,0,"shrink-0"],[12],[1,"\\n "],[10,0],[14,0,"mb-2 hds-typography-body-200 hds-font-weight-semibold hds-foreground-primary"],[12],[1,"Status"],[13],[1,"\\n "],[10,0],[14,0,"flex items-center"],[12],[1,"\\n "],[8,[39,1],null,[["@peering"],[[30,1]]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"shrink-0"],[12],[1,"\\n "],[10,0],[14,0,"hds-typography-body-200 mb-2 hds-font-weight-semibold hds-foreground-primary"],[12],[1,"Latest heartbeat"],[13],[1,"\\n "],[10,0],[14,0,"flex items-center"],[12],[1,"\\n"],[41,[30,1,["LastHeartbeat"]],[[[44,[[28,[37,4],[[30,1,["LastHeartbeat"]]],null]],[[[1," "],[8,[39,5],[[24,0,"mr-0.5"]],[["@name","@color"],["activity","var(--token-color-foreground-faint)"]],null],[1,"\\n"],[41,[30,2,["isNearDate"]],[[[1," "],[11,1],[4,[38,6],[[30,2,["friendly"]]],null],[12],[1,[30,2,["relative"]]],[13],[1,"\\n"]],[]],[[[1," "],[10,1],[12],[1,[30,2,["friendly"]]],[13],[1,"\\n"]],[]]]],[2]]]],[]],[[[1," "],[10,1],[12],[1,"None yet"],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"shrink-0"],[12],[1,"\\n "],[10,0],[14,0,"mb-2 hds-typography-body-200 hds-font-weight-semibold hds-foreground-primary"],[12],[1,"Latest receipt"],[13],[1,"\\n "],[10,0],[14,0,"flex items-center"],[12],[1,"\\n"],[41,[30,1,["LastReceive"]],[[[44,[[28,[37,4],[[30,1,["LastReceive"]]],null]],[[[41,[30,3,["isNearDate"]],[[[1," "],[11,1],[4,[38,6],[[30,3,["friendly"]]],null],[12],[1,[30,3,["relative"]]],[13],[1,"\\n"]],[]],[[[1," "],[10,1],[12],[1,[30,3,["friendly"]]],[13],[1,"\\n"]],[]]]],[3]]]],[]],[[[1," "],[10,1],[12],[1,"None yet"],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"shrink-0"],[12],[1,"\\n "],[10,0],[14,0,"mb-2 hds-typography-body-200 hds-font-weight-semibold hds-foreground-primary"],[12],[1,"Latest send"],[13],[1,"\\n "],[10,0],[14,0,"flex items-center"],[12],[1,"\\n"],[41,[30,1,["LastSend"]],[[[44,[[28,[37,4],[[30,1,["LastSend"]]],null]],[[[41,[30,4,["isNearDate"]],[[[1," "],[11,1],[4,[38,6],[[30,4,["friendly"]]],null],[12],[1,[30,4,["relative"]]],[13],[1,"\\n"]],[]],[[[1," "],[10,1],[12],[1,[30,4,["friendly"]]],[13],[1,"\\n"]],[]]]],[4]]]],[]],[[[1," "],[10,1],[12],[1,"None yet"],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]]]]]],["@peering","smartDate","smartDate","smartDate"],false,["hds/card/container","peerings/badge","if","let","smart-date-format","flight-icon","tooltip"]]',moduleName:"consul-ui/components/consul/peer/bento-box/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/form/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={id:"consul-peer-form",initial:"generate",on:{INITIATE:[{target:"initiate"}],GENERATE:[{target:"generate"}]},states:{initiate:{},generate:{}}}})),define("consul-ui/components/consul/peer/form/generate/actions/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"Agkp8hSw",block:'[[[1,"\\n"],[8,[39,0],[[16,"form",[30,1]],[24,4,"submit"],[16,"disabled",[28,[37,1],[[28,[37,2],[[30,2,["Name","length"]],0],null]],null]],[17,3]],[["@text"],["Generate token"]],null]],["@id","@item","&attrs"],false,["hds/button","or","eq"]]',moduleName:"consul-ui/components/consul/peer/form/generate/actions/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/form/generate/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={id:"consul-peer-generate-form",initial:"idle",states:{idle:{on:{LOAD:{target:"loading"}}},loading:{on:{SUCCESS:{target:"success"},ERROR:{target:"error"}}},success:{on:{RESET:{target:"idle"}}},error:{}}}})),define("consul-ui/components/consul/peer/form/generate/fieldsets/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object"],(function(e,t,n,l,r){var i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"sFxHhDSu",block:'[[[1,"\\n"],[11,0],[16,0,[28,[37,0],["consul-peer-form-generate-fieldsets"],null]],[17,1],[12],[1,"\\n "],[8,[39,1],null,[["@src"],[[28,[37,2],["/machines/validate.xstate"],[["from"],["/components/consul/peer/form/generate/fieldsets"]]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["help","Name"],[[28,[37,5],[[28,[37,6],["common.validations.dns-hostname.help"],null],[28,[37,6],["common.validations.immutable.help"],null]],null],[28,[37,7],[[28,[37,4],null,[["test","error"],[[28,[37,6],["common.validations.dns-hostname.test"],null],[28,[37,6],["common.validations.dns-hostname.error"],[["name"],["Name"]]]]]]],null]]]]],[[[1," "],[10,"fieldset"],[12],[1,"\\n "],[8,[39,8],null,[["@label","@name","@item","@validations","@chart","@oninput"],[[28,[37,6],["components.consul.peer.generate.name"],null],"Name",[30,4],[30,3],[30,2],[28,[37,9],["target.value",[28,[37,10],[[30,4],"Name"],null]],null]]],null],[1,"\\n "],[18,6,[[28,[37,4],null,[["valid"],[[28,[37,12],[[28,[37,13],[[30,2,["state"]],"error"],null]],null]]]]]],[1,"\\n "],[13],[1,"\\n\\n"]],[3]]],[1,"\\n"],[44,[[28,[37,4],null,[["help"],[[28,[37,6],["common.validations.server-external-addresses.help"],null]]]]],[[[1," "],[10,"fieldset"],[12],[1,"\\n "],[8,[39,8],null,[["@label","@name","@item","@chart","@validations","@oninput"],[[28,[37,6],["components.consul.peer.generate.addresses"],null],"ServerExternalAddresses",[30,4],[30,2],[30,5],[28,[37,9],["target.value",[30,0,["onInput"]]],null]]],null],[1,"\\n "],[18,6,[[28,[37,4],null,[["valid"],[[28,[37,12],[[28,[37,13],[[30,2,["state"]],"error"],null]],null]]]]]],[1,"\\n "],[13],[1,"\\n\\n"]],[5]]],[1," "]],[2]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","fsm","Name","@item","ServerExternalAddresses","&default"],false,["class-map","state-machine","require","let","hash","concat","t","array","text-input","pick","set","yield","not","state-matches"]]',moduleName:"consul-ui/components/consul/peer/form/generate/fieldsets/index.hbs",isStrictMode:!1}) +let a=(i=class extends l.default{onInput(e){e=e?e.split(",").map((e=>e.trim())):[],this.args.item.ServerExternalAddresses=e}},u=i.prototype,s="onInput",c=[r.action],d=Object.getOwnPropertyDescriptor(i.prototype,"onInput"),p=i.prototype,f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i) +var u,s,c,d,p,f +e.default=a,(0,t.setComponentTemplate)(o,a)})),define("consul-ui/components/consul/peer/form/generate/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"w1v/7n9u",block:'[[[1,"\\n"],[11,0],[16,0,[28,[37,0],["consul-peer-form-generate"],null]],[17,1],[12],[1,"\\n "],[8,[39,1],null,[["@src","@initial"],[[28,[37,2],["./chart.xstate"],[["from"],["/components/consul/peer/form/generate"]]],[52,[30,2],"loading","idle"]]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,5],null,null]],[[[1," "],[11,"form"],[16,1,[30,4]],[4,[38,6],["submit",[28,[37,7],[[30,3,["dispatch"]],"LOAD"],null]],null],[12],[1,"\\n\\n "],[8,[30,3,["State"]],null,[["@matches"],[[28,[37,8],["idle","error"],null]]],[["default"],[[[[1,"\\n "],[8,[30,3,["State"]],null,[["@matches"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,9],[[24,0,"mb-3 mt-2"]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Error"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,[30,3,["state","context","error","message"]]]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[18,9,[[28,[37,11],null,[["Fieldsets","Actions"],[[50,"consul/peer/form/generate/fieldsets",0,null,[["item"],[[30,7]]]],[50,"consul/peer/form/generate/actions",0,null,[["item","id"],[[30,7],[30,4]]]]]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,3,["State"]],null,[["@matches"],["loading"]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@src","@onchange","@onerror"],[[28,[37,14],["/${partition}/${nspace}/${dc}/peering/token-for/${name}/${externalAddresses}",[28,[37,11],null,[["partition","nspace","dc","name","externalAddresses"],[[30,7,["Partition"]],"",[30,7,["Datacenter"]],[30,7,["Name"]],[30,7,["ServerExternalAddresses"]]]]]],null],[28,[37,15],[[30,8],[28,[37,16],["data",[28,[37,7],[[30,3,["dispatch"]],"SUCCESS"],null]],null]],null],[28,[37,15],[[28,[37,7],[[30,3,["dispatch"]],"ERROR"],null]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,3,["State"]],null,[["@matches"],["success"]],[["default"],[[[[1,"\\n "],[18,9,[[28,[37,11],null,[["Fieldsets","Actions"],[[50,"consul/peer/form/token/fieldsets",0,null,[["item","token","regenerate","onclick"],[[30,7],[30,3,["state","context","PeeringToken"]],[30,2],[28,[37,15],[[28,[37,17],[[30,7],"Name",""],null],[28,[37,7],[[30,3,["dispatch"]],"RESET"],null]],null]]]],[50,"consul/peer/form/token/actions",0,null,[["token","item","id"],[[30,3,["state","context","PeeringToken"]],[30,7],[30,4]]]]]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[13],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@regenerate","fsm","id","reset","A","@item","@onchange","&default"],false,["class-map","state-machine","require","if","let","unique-id","on","fn","array","hds/alert","yield","hash","component","data-source","uri","queue","pick","set"]]',moduleName:"consul-ui/components/consul/peer/form/generate/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/form/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"/fuosMgw",block:'[[[1,"\\n"],[11,0],[16,0,[28,[37,0],["consul-peer-form"],null]],[17,1],[12],[1,"\\n "],[8,[39,1],null,[["@src"],[[28,[37,2],["./chart.xstate"],[["from"],["/components/consul/peer/form"]]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,3],null,[["@items","@onTabClicked"],[[28,[37,4],[[28,[37,5],null,[["label","selected","state"],[[28,[37,6],["components.consul.peer.form.generate-label"],null],[28,[37,7],[[30,2,["state"]],"generate"],null],"GENERATE"]]],[28,[37,5],null,[["label","selected","state"],[[28,[37,6],["components.consul.peer.form.establish-label"],null],[28,[37,7],[[30,2,["state"]],"initiate"],null],"INITIATE"]]]],null],[28,[37,8],["state",[30,2,["dispatch"]]],null]]],null],[1,"\\n\\n "],[8,[30,2,["State"]],null,[["@matches"],[[28,[37,4],["generate"],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,9],null,[["@src"],[[28,[37,10],["/${partition}/${nspace}/${dc}/peer-generate/",[30,3]],null]]],[["default"],[[[[1,"\\n "],[18,6,[[28,[37,5],null,[["Form"],[[50,"consul/peer/form/generate",0,null,[["item"],[[30,4,["data"]]]]]]]]]],[1,"\\n "]],[4]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,2,["State"]],null,[["@matches"],["initiate"]],[["default"],[[[[1,"\\n\\n "],[8,[39,9],null,[["@src"],[[28,[37,10],["/${partition}/${nspace}/${dc}/peer-initiate/",[30,3]],null]]],[["default"],[[[[1,"\\n "],[18,6,[[28,[37,5],null,[["Form"],[[50,"consul/peer/form/initiate",0,null,[["item"],[[30,5,["data"]]]]]]]]]],[1,"\\n "]],[5]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n\\n "]],[2]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","fsm","@params","source","source","&default"],false,["class-map","state-machine","require","tab-nav","array","hash","t","state-matches","pick","data-source","uri","yield","component"]]',moduleName:"consul-ui/components/consul/peer/form/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/form/initiate/actions/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"rVLddbat",block:'[[[1,"\\n"],[8,[39,0],[[16,"form",[30,1]],[24,4,"submit"],[17,2]],[["@text"],["Add peer"]],null]],["@id","&attrs"],false,["hds/button"]]',moduleName:"consul-ui/components/consul/peer/form/initiate/actions/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/form/initiate/fieldsets/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"q1ndxYMU",block:'[[[1,"\\n"],[11,0],[16,0,[28,[37,0],["consul-peer-form-initiate-fieldsets"],null]],[17,1],[12],[1,"\\n"],[44,[[28,[37,2],null,[["help","Name"],["Enter a name to locally identify the new peer.",[28,[37,3],[[28,[37,2],null,[["test","error"],[[28,[37,4],["common.validations.dns-hostname.test"],null],[28,[37,4],["common.validations.dns-hostname.error"],[["name"],["Name"]]]]]]],null]]]],[28,[37,2],null,[["help","PeeringToken"],["Enter the token received from the operator of the desired peer.",[28,[37,3],null,null]]]]],[[[1," "],[10,2],[12],[1,"\\n Enter a token generated in the desired peer.\\n "],[13],[1,"\\n "],[8,[39,5],null,[["@src"],[[28,[37,6],["/machines/validate.xstate"],[["from"],["/components/consul/peer/form/generate/fieldsets"]]]]],[["default"],[[[[1,"\\n\\n "],[10,"fieldset"],[12],[1,"\\n "],[8,[39,7],null,[["@name","@label","@item","@validations","@chart"],["Name","Name of peer",[30,5],[30,2],[30,4]]],null],[1,"\\n "],[8,[39,7],null,[["@expanded","@name","@item","@validations","@chart"],[true,"Token",[30,5],[30,3],[30,4]]],null],[1,"\\n "],[18,6,[[28,[37,2],null,[["valid"],[[28,[37,9],[[28,[37,10],[[30,4,["state"]],"error"],null]],null]]]]]],[1,"\\n "],[13],[1,"\\n\\n "]],[4]]]]],[1,"\\n"]],[2,3]]],[13],[1,"\\n"]],["&attrs","Name","PeeringToken","fsm","@item","&default"],false,["class-map","let","hash","array","t","state-machine","require","text-input","yield","not","state-matches"]]',moduleName:"consul-ui/components/consul/peer/form/initiate/fieldsets/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/form/initiate/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"DWuLBe0N",block:'[[[1,"\\n"],[11,0],[16,0,[28,[37,0],["consul-peer-form-initiate"],null]],[17,1],[12],[1,"\\n "],[8,[39,1],null,[["@sink","@type","@label","@onchange"],[[28,[37,2],["/${partition}/${nspace}/${dc}/peer",[28,[37,3],null,[["partition","nspace","dc"],[[28,[37,4],[[30,2,["Partition"]],""],null],[28,[37,4],[[30,2,["Namespace"]],""],null],[28,[37,4],[[30,2,["Datacenter"]],""],null]]]]],null],"peer","peer",[28,[37,5],[[28,[37,6],[[30,3]],null],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,8],[[24,0,"mb-3 mt-2"]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,7,["Title"]],null,null,[["default"],[[[[1,"Error"]],[]]]]],[1,"\\n "],[8,[30,7,["Description"]],null,null,[["default"],[[[[1,[30,6,["message"]]]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[5,6]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,10],null,null]],[[[1," "],[11,"form"],[16,1,[30,8]],[4,[38,11],["submit",[28,[37,5],[[30,4,["persist"]],[30,2]],null]],null],[12],[1,"\\n "],[18,9,[[28,[37,3],null,[["Fieldsets","Actions"],[[50,"consul/peer/form/initiate/fieldsets",0,null,[["item"],[[30,2]]]],[50,"consul/peer/form/initiate/actions",0,null,[["item","id"],[[30,2],[30,8]]]]]]]]],[1,"\\n "],[13],[1,"\\n"]],[8]]],[1," "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"],[13]],["&attrs","@item","@onsubmit","writer","after","error","A","id","&default"],false,["class-map","data-writer","uri","hash","or","fn","optional","block-slot","hds/alert","let","unique-id","on","yield","component"]]',moduleName:"consul-ui/components/consul/peer/form/initiate/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/form/token/actions/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"Om/MyDR4",block:'[[[1,"\\n"],[11,0],[17,1],[12],[1,"\\n "],[8,[39,0],null,null,[["default"],[[[[1,"\\n "],[8,[39,1],[[17,1],[4,[38,2],[[30,2]],null]],[["@text","@color"],["Copy token","primary"]],null],[1,"\\n "],[8,[39,1],[[24,4,"reset"],[4,[38,3],["click",[30,3]],null]],[["@text","@color"],["Close","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@token","@onclose"],false,["hds/button-set","hds/button","with-copyable","on"]]',moduleName:"consul-ui/components/consul/peer/form/token/actions/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/form/token/fieldsets/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"IOG4Ffy9",block:'[[[1,"\\n"],[41,[30,1],[[[1," "],[10,2],[12],[1,"\\n Token regenerated! Here’s what’s next:\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,2],[12],[1,"\\n Token generated! Here’s what’s next:\\n "],[13],[1,"\\n"]],[]]],[1," "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[10,"strong"],[12],[1,"Copy the token"],[13],[10,"br"],[12],[13],[1,"\\n This token cannot be viewed again after creation.\\n "],[10,"br"],[12],[13],[1,"\\n "],[8,[39,1],null,[["@value","@name"],[[30,2],"Token"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[10,"strong"],[12],[1,"Switch to the peer"],[13],[10,"br"],[12],[13],[1,"\\n Someone on your team should log into the Datacenter (Community) or Admin Partition (Enterprise) that you want this one to connect with.\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[10,"strong"],[12],[1,"Initiate the peering"],[13],[10,"br"],[12],[13],[1,"\\n From there, initiate a new peering, name it, and paste this token in.\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,2],[[30,1]],null],[[[1," "],[8,[39,3],[[24,4,"reset"],[4,[38,4],["click",[30,3]],null]],[["@text","@color"],["Generate another token","secondary"]],null],[1,"\\n"]],[]],null],[1,"\\n"]],["@regenerate","@token","@onclick"],false,["if","copyable-code","not","hds/button","on"]]',moduleName:"consul-ui/components/consul/peer/form/token/fieldsets/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/info/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"Fvjn0Yfe",block:'[[[1,"\\n"],[41,[30,1,["PeerName"]],[[[1," "],[10,0],[14,0,"consul-peer-info"],[12],[1,"\\n\\n "],[11,"svg"],[24,"width","16"],[24,"height","16"],[24,"viewBox","0 0 16 16"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[4,[38,1],["Peer"],null],[12],[1,"\\n "],[10,"path"],[14,"d","M16 8C16 7.80109 15.921 7.61032 15.7803 7.46967L12.2803 3.96967C11.9874 3.67678 11.5126 3.67678 11.2197 3.96967C10.9268 4.26256 10.9268 4.73744 11.2197 5.03033L14.1893 8L11.2197 10.9697C10.9268 11.2626 10.9268 11.7374 11.2197 12.0303C11.5126 12.3232 11.9874 12.3232 12.2803 12.0303L15.7803 8.53033C15.921 8.38968 16 8.19891 16 8Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M0.21967 8.53033C-0.0732233 8.23744 -0.0732233 7.76256 0.21967 7.46967L3.71967 3.96967C4.01256 3.67678 4.48744 3.67678 4.78033 3.96967C5.07322 4.26256 5.07322 4.73744 4.78033 5.03033L1.81066 8L4.78033 10.9697C5.07322 11.2626 5.07322 11.7374 4.78033 12.0303C4.48744 12.3232 4.01256 12.3232 3.71967 12.0303L0.21967 8.53033Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M5 7C4.44772 7 4 7.44772 4 8C4 8.55229 4.44772 9 5 9H5.01C5.56228 9 6.01 8.55229 6.01 8C6.01 7.44772 5.56228 7 5.01 7H5Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M7 8C7 7.44772 7.44772 7 8 7H8.01C8.56228 7 9.01 7.44772 9.01 8C9.01 8.55229 8.56228 9 8.01 9H8C7.44772 9 7 8.55229 7 8Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M11 7C10.4477 7 10 7.44772 10 8C10 8.55229 10.4477 9 11 9H11.01C11.5623 9 12.01 8.55229 12.01 8C12.01 7.44772 11.5623 7 11.01 7H11Z"],[14,"fill","#77838A"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,1],[14,0,"consul-peer-info__description"],[12],[1,"Imported from "],[10,1],[12],[1,[30,1,["PeerName"]]],[13],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],["@item"],false,["if","tooltip"]]',moduleName:"consul-ui/components/consul/peer/info/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"fnAtXcEa",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-peer-list"],[17,1]],[["@items","@linkable"],[[30,2],"linkable peers"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],["delete peer"],[["item"],[[30,3]]]],[[[1," "],[10,3],[15,6,[28,[37,4],["dc.peers.show",[30,3,["Name"]]],null]],[12],[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,2],[12],[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"peers__list__peer-detail"],[12],[1,"\\n "],[8,[39,5],null,[["@peering"],[[30,3]]],null],[1,"\\n\\n "],[11,0],[4,[38,6],[[28,[37,7],["routes.dc.peers.index.detail.imported.tooltip"],[["name"],[[30,3,["Name"]]]]]],null],[12],[1,"\\n "],[1,[28,[35,7],["routes.dc.peers.index.detail.imported.count"],[["count"],[[28,[37,8],[[30,3,["ImportedServiceCount"]]],null]]]]],[1,"\\n "],[13],[1,"\\n\\n "],[11,0],[4,[38,6],[[28,[37,7],["routes.dc.peers.index.detail.exported.tooltip"],[["name"],[[30,3,["Name"]]]]]],null],[12],[1,"\\n "],[1,[28,[35,7],["routes.dc.peers.index.detail.exported.count"],[["count"],[[28,[37,8],[[30,3,["ExportedServiceCount"]]],null]]]]],[1,"\\n "],[13],[1,"\\n\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],["delete peer"],[["item"],[[30,3]]]],[[[1,"\\n "],[8,[30,5],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,9],[[28,[37,3],["write peer"],[["item"],[[30,3]]]],[30,3,["isDialer"]]],null],[[[1," "],[8,[30,6],[[4,[38,10],["click",[28,[37,11],[[30,7],[30,3]],null]],null]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Regenerate token\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "],[8,[30,6],null,[["@href"],[[28,[37,4],["dc.peers.show",[30,3,["Name"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n View\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,11],[[30,8],[30,3]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,9],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this peer?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,10],null,null,[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "]],[10]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],null],[1," "]],[5]]]]],[1,"\\n"]],[3,4]]]]]],["&attrs","@items","item","index","Actions","Action","@onedit","@ondelete","Confirmation","Confirm"],false,["list-collection","block-slot","if","can","href-to","peerings/badge","tooltip","t","format-number","and","on","fn"]]',moduleName:"consul-ui/components/consul/peer/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"X9zOi0Cb",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1],"remove"],null],[[[1," "],[8,[39,2],[[17,2]],[["@color"],["success"]],[["default"],[[[[1,"\\n "],[8,[30,3,["Title"]],null,null,[["default"],[[[[1,"Success!"]],[]]]]],[1,"\\n "],[8,[30,3,["Description"]],null,null,[["default"],[[[[1,"\\n Your Peer has been marked for deletion.\\n "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n"]],[]],null]],["@type","&attrs","T"],false,["if","eq","hds/toast"]]',moduleName:"consul-ui/components/consul/peer/notifications/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"fwTgzNL7",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-peer-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.peer.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.peer.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-state"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["state","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.peer.search-bar.state.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[28,[37,11],[[28,[37,12],["/models/peer"],[["export","from"],["schema","/components/consul/peer/search-bar"]]],"State.allowedValues"],null]],null]],null],null,[[[44,[[28,[37,13],[[30,17]],null]],[[[1," "],[8,[30,16],[[16,0,[29,["value-",[30,18]]]]],[["@value","@selected"],[[30,18],[28,[37,9],[[30,18],[30,2,["state","value"]]],null]]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.peer.search-bar.state.options.",[30,18]],null]],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[18]]]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,19,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,20,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,14],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["State:asc",[28,[37,2],["components.consul.peer.search-bar.sort.state.asc"],null]],null],[28,[37,4],["State:desc",[28,[37,2],["components.consul.peer.search-bar.sort.state.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,11],[[30,22],[30,20,["value"]]],null]],[1,"\\n"]],[22]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,21,["Optgroup"]],[30,21,["Option"]]],[[[1," "],[8,[30,23],null,[["@label"],[[28,[37,2],["components.consul.peer.search-bar.sort.state.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["State:asc",[28,[37,15],["State:asc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["components.consul.peer.search-bar.sort.state.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["State:desc",[28,[37,15],["State:desc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["components.consul.peer.search-bar.sort.state.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@label"],[[28,[37,2],["common.consul.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["Name:asc",[28,[37,15],["Name:asc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["Name:desc",[28,[37,15],["Name:desc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[23,24]]],[1," "]],[]]]]],[1,"\\n "]],[21]]]]],[1,"\\n "]],[19]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","upperState","state","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","get","require","string-to-lower-case","from-entries","eq"]]',moduleName:"consul-ui/components/consul/peer/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/peer/selector/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"bN0o4zNN",block:'[[[1,"\\n"],[44,[[30,1]],[[[1," "],[8,[30,2,["Title"]],[[17,3]],null,[["default"],[[[[1,[28,[35,1],["components.hashicorp-consul.side-nav.organization.title"],null]]],[]]]]],[1,"\\n "],[8,[30,2,["Link"]],null,[["@text","@route","@models","@query","@isActive"],[[28,[37,1],["components.hashicorp-consul.side-nav.organization.peers"],null],"dc.peers",[28,[37,2],[[30,4,["Name"]]],null],[28,[37,3],null,[["peer"],[[27]]]],[28,[37,4],["dc.peers",[30,4,["Name"]]],null]]],null],[1,"\\n"]],[2]]]],["@list","SNL","&attrs","@dc"],false,["let","t","array","hash","is-href"]]',moduleName:"consul-ui/components/consul/peer/selector/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/policy/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"62bUfTFp",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-policy-list"]],[["@items"],[[30,1]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],[[28,[37,4],[[28,[37,5],[[30,2]],null],"policy-management"],null],[28,[37,4],[[28,[37,5],[[30,2]],null],"read-only"],null]],null],[[[1," "],[10,"dl"],[14,0,"policy-management"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Type"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[41,[28,[37,4],[[28,[37,5],[[30,2]],null],"policy-management"],null],[[[1," "],[8,[39,6],null,null,[["default"],[[[[1,"\\n Global Management Policy\\n "]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,6],null,null,[["default"],[[[[1,"\\n Global Read-only Policy\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[10,3],[15,6,[28,[37,7],["dc.acls.policies.edit",[30,2,["ID"]]],null]],[15,0,[52,[28,[37,4],[[28,[37,5],[[30,2]],null],"policy-management"],null],"is-management"]],[12],[1,[30,2,["Name"]]],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[10,"dl"],[14,0,"datacenter"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,6],null,null,[["default"],[[[[1,"Datacenters"]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,8],[", ",[28,[37,9],[[30,2]],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[14,0,"description"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,2,["Description"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[30,3],null,null,[["default"],[[[[1,"\\n "],[8,[30,4],null,[["@href"],[[28,[37,7],["dc.acls.policies.edit",[30,2,["ID"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],["write policy"],[["item"],[[30,2]]]],[[[1," Edit\\n"]],[]],[[[1," View\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,10],["delete policy"],[["item"],[[30,2]]]],[[[1," "],[8,[30,4],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,11],[[30,0],[30,5],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,6],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this policy?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,7],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[4]]]]],[1,"\\n "]],[3]]]]],[1,"\\n"]],[2]]]]]],["@items","item","Actions","Action","@ondelete","Confirmation","Confirm"],false,["list-collection","block-slot","if","or","eq","policy/typeof","tooltip","href-to","join","policy/datacenters","can","action"]]',moduleName:"consul-ui/components/consul/policy/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/policy/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"sUAOpVES",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1],"create"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your policy has been added.\\n"]],[]],[[[1," There was an error adding your policy.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"update"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your policy has been saved.\\n"]],[]],[[[1," There was an error saving your policy.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"delete"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your policy was deleted.\\n"]],[]],[[[1," There was an error deleting your policy.\\n"]],[]]]],[]],null]],[]]]],[]]],[44,[[30,3,["errors","firstObject"]]],[[[41,[30,4,["detail"]],[[[1," "],[10,"br"],[12],[13],[1,[28,[35,3],["(",[52,[30,4,["status"]],[28,[37,3],[[30,4,["status"]],": "],null]],[30,4,["detail"]],")"],null]],[1,"\\n"]],[]],null]],[4]]]],["@type","@status","@error","error"],false,["if","eq","let","concat"]]',moduleName:"consul-ui/components/consul/policy/notifications/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})) +define("consul-ui/components/consul/policy/search-bar/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"Idci/62E",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-policy-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.policy.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.policy.search-bar.",[30,3,["status","key"]],".options.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[52,[28,[37,6],[[30,3,["status","key"]],"datacenter"],null],[30,3,["status","value"]],[30,5]]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,7],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,7],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,10],[[28,[37,10],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,11],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,12],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-datacenter"]],[["@position","@onchange","@multiple"],["left",[28,[37,7],[[30,0],[30,2,["datacenter","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.consul.datacenter"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,10],[[28,[37,10],[[33,13]],null]],null],null,[[[1," "],[8,[30,16],null,[["@value","@selected"],[[30,17,["Name"]],[28,[37,11],[[30,17,["Name"]],[30,2,["datacenter","value"]]],null]]],[["default"],[[[[1,[30,17,["Name"]]]],[]]]]],[1,"\\n"]],[17]],null],[1," "],[8,[39,14],null,[["@src","@loading","@onchange"],[[28,[37,15],["/${partition}/*/*/datacenters",[28,[37,16],null,[["partition"],[[30,18]]]]],null],"lazy",[28,[37,7],[[30,0],[28,[37,17],[[30,0,["dcs"]]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-kind"]],[["@position","@onchange","@multiple"],["left",[28,[37,7],[[30,0],[30,2,["kind","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.policy.search-bar.kind.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,19,["Optgroup"]],[30,19,["Option"]]],[[[42,[28,[37,10],[[28,[37,10],[[28,[37,4],["global-management","standard"],null]],null]],null],null,[[[1," "],[8,[30,21],[[16,0,[29,["value-",[30,22]]]]],[["@value","@selected"],[[30,22],[28,[37,11],[[30,22],[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.policy.search-bar.kind.options.",[30,22]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,22]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22]],null]],[20,21]]],[1," "]],[]]]]],[1,"\\n "]],[19]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,23,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,7],[[30,0],[30,24,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,18],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,19],[[30,26],[30,24,["value"]]],null]],[1,"\\n"]],[26]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,25,["Optgroup"]],[30,25,["Option"]]],[[[1," "],[8,[30,27],null,[["@label"],[[28,[37,2],["common.ui.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,28],null,[["@value","@selected"],["Name:asc",[28,[37,6],["Name:asc",[30,24,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,28],null,[["@value","@selected"],["Name:desc",[28,[37,6],["Name:desc",[30,24,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[27,28]]],[1," "]],[]]]]],[1,"\\n "]],[25]]]]],[1,"\\n "]],[23]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","dc","@partition","components","Optgroup","Option","state","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","if","eq","action","block-slot","each","-track-array","includes","lowercase","dcs","data-source","uri","hash","mut","from-entries","get"]]',moduleName:"consul-ui/components/consul/policy/search-bar/index.hbs",isStrictMode:!1}) +class i extends l.default{}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/consul/role/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"B3WXmBeq",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-role-list"],[17,1]],[["@items"],[[30,2]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,3],[15,6,[28,[37,2],["dc.acls.roles.edit",[30,3,["ID"]]],null]],[12],[1,[30,3,["Name"]]],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[8,[39,3],null,[["@item"],[[30,3]]],null],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Description"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[30,4],null,null,[["default"],[[[[1,"\\n "],[8,[30,5],null,[["@href"],[[28,[37,2],["dc.acls.roles.edit",[30,3,["ID"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n"],[41,[28,[37,5],["write role"],[["item"],[[30,3]]]],[[[1," Edit\\n"]],[]],[[[1," View\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,5],["delete role"],[["item"],[[30,3]]]],[[[1," "],[8,[30,5],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,6],[[30,0],[30,6],[30,3]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,7],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this role?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,8],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[5]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[3]]]]]],["&attrs","@items","item","Actions","Action","@ondelete","Confirmation","Confirm"],false,["list-collection","block-slot","href-to","consul/token/ruleset/list","if","can","action"]]',moduleName:"consul-ui/components/consul/role/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/role/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"gE+Sp3ez",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1],"create"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your role has been added.\\n"]],[]],[[[1," There was an error adding your role.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"update"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your role has been saved.\\n"]],[]],[[[1," There was an error saving your role.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"delete"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your role was deleted.\\n"]],[]],[[[1," There was an error deleting your role.\\n"]],[]]]],[]],null]],[]]]],[]]],[44,[[30,3,["errors","firstObject"]]],[[[41,[30,4,["detail"]],[[[1," "],[10,"br"],[12],[13],[1,[28,[35,3],["(",[52,[30,4,["status"]],[28,[37,3],[[30,4,["status"]],": "],null]],[30,4,["detail"]],")"],null]],[1,"\\n"]],[]],null]],[4]]]],["@type","@status","@error","error"],false,["if","eq","let","concat"]]',moduleName:"consul-ui/components/consul/role/notifications/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/role/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"OtMY+FfU",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-role-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.role.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.role.search-bar.",[30,3,["status","key"]],".options.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,14,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["CreateIndex:desc",[28,[37,2],["common.sort.age.desc"],null]],null],[28,[37,4],["CreateIndex:asc",[28,[37,2],["common.sort.age.asc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,16],[30,14,["value"]]],null]],[1,"\\n"]],[16]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,15,["Optgroup"]],[30,15,["Option"]]],[[[1," "],[8,[30,17],null,[["@label"],[[28,[37,2],["common.ui.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["Name:asc",[28,[37,13],["Name:asc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["Name:desc",[28,[37,13],["Name:desc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,17],null,[["@label"],[[28,[37,2],["common.ui.creation"],null]]],[["default"],[[[[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["CreateIndex:desc",[28,[37,13],["CreateIndex:desc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.age.desc"],null]]],[]]]]],[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["CreateIndex:asc",[28,[37,13],["CreateIndex:asc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.age.asc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17,18]]],[1," "]],[]]]]],[1,"\\n "]],[15]]]]],[1,"\\n "]],[13]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/role/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/server/card/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"Mtow1lYR",block:'[[[1,"\\n"],[11,0],[16,0,[28,[37,0],["consul-server-card",[28,[37,1],["voting-status-leader",[28,[37,2],[[30,1,["Status"]],"leader"],null]],null],[28,[37,1],["voting-status-voter",[28,[37,3],[[28,[37,4],[[30,1,["ReadReplica"]]],null],[28,[37,2],[[30,1,["Status"]],"voter"],null]],null]],null],[28,[37,1],["voting-status-non-voter",[28,[37,5],[[30,1,["ReadReplica"]],[28,[37,6],[[30,1,["Status"]],[28,[37,1],["non-voter","staging"],null]],null]],null]],null]],null]],[17,2],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n\\n "],[11,"dt"],[24,0,"name"],[4,[38,7],["Leader"],null],[12],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,1,["Name"]]],[1,"\\n "],[13],[1,"\\n\\n "],[10,"dt"],[15,0,[28,[37,0],["health-status",[28,[37,1],["healthy",[30,1,["Healthy"]]],null]],null]],[12],[1,"\\n Status\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[52,[28,[37,6],[[30,1,["Status"]],[28,[37,1],["leader","voter"],null]],null],"Active voter","Backup voter"]],[1,"\\n "],[13],[1,"\\n\\n "],[13],[1,"\\n"],[13],[1,"\\n\\n"]],["@item","&attrs"],false,["class-map","array","eq","and","not","or","includes","tooltip","if"]]',moduleName:"consul-ui/components/consul/server/card/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/server/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"Npo4ZrBj",block:'[[[1,"\\n"],[11,0],[16,0,[28,[37,0],["consul-server-list"],null]],[17,1],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,2],[[28,[37,2],[[30,2]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[10,3],[15,6,[28,[37,3],["dc.nodes.show",[30,3,["Name"]]],null]],[12],[1,"\\n "],[8,[39,4],null,[["@item"],[[30,3]]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n\\n"]],["&attrs","@items","item"],false,["class-map","each","-track-array","href-to","consul/server/card"]]',moduleName:"consul-ui/components/consul/server/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/service-identity/template/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"ocpFRqFf",block:'[[[1,"\\n"],[41,[28,[37,1],["use partitions"],null],[[[1,"partition \\""],[1,[28,[35,2],[[30,1],"default"],null]],[1,"\\" {\\n"],[41,[28,[37,1],["use nspaces"],null],[[[1," namespace \\""],[1,[28,[35,2],[[30,2],"default"],null]],[1,"\\" {\\n service \\""],[1,[30,3]],[1,"\\" {\\n\\t policy = \\"write\\"\\n }\\n service \\""],[1,[30,3]],[1,"-sidecar-proxy\\" {\\n\\t policy = \\"write\\"\\n }\\n service_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n node_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n }\\n"]],[]],[[[1," service \\""],[1,[30,3]],[1,"\\" {\\n\\t policy = \\"write\\"\\n }\\n service \\""],[1,[30,3]],[1,"-sidecar-proxy\\" {\\n\\t policy = \\"write\\"\\n }\\n service_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n node_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n"]],[]]],[1,"}\\n"]],[]],[[[41,[28,[37,1],["use nspaces"],null],[[[1,"namespace \\""],[1,[28,[35,2],[[30,2],"default"],null]],[1,"\\" {\\n service \\""],[1,[30,3]],[1,"\\" {\\n\\t policy = \\"write\\"\\n }\\n service \\""],[1,[30,3]],[1,"-sidecar-proxy\\" {\\n\\t policy = \\"write\\"\\n }\\n service_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n node_prefix \\"\\" {\\n\\t policy = \\"read\\"\\n }\\n}\\n"]],[]],[[[1,"service \\""],[1,[30,3]],[1,"\\" {\\n\\tpolicy = \\"write\\"\\n}\\nservice \\""],[1,[30,3]],[1,"-sidecar-proxy\\" {\\n\\tpolicy = \\"write\\"\\n}\\nservice_prefix \\"\\" {\\n\\tpolicy = \\"read\\"\\n}\\nnode_prefix \\"\\" {\\n\\tpolicy = \\"read\\"\\n}\\n"]],[]]]],[]]]],["@partition","@nspace","@name"],false,["if","can","or"]]',moduleName:"consul-ui/components/consul/service-identity/template/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/service-instance/list/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"UrXEnr5R",block:'[[[1,"\\n"],[44,[[28,[37,1],[[30,1],"Service.Proxy.DestinationServiceID"],null]],[[[8,[39,2],[[24,0,"consul-service-instance-list"],[17,3]],[["@items"],[[30,4]]],[["default"],[[[[1,"\\n "],[8,[39,3],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,5],[[30,7],"dc.services.show"],null],[[[1," "],[10,3],[15,6,[28,[37,6],[[30,7],[30,5,["Service","Service"]]],null]],[12],[1,"\\n "],[1,[30,5,["Service","ID"]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,6,[28,[37,6],[[30,7],[30,5,["Service","Service"]],[30,5,["Node","Node"]],[28,[37,7],[[30,5,["Service","ID"]],[30,5,["Service","Service"]]],null]],null]],[12],[1,"\\n "],[1,[30,5,["Service","ID"]]],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,3],null,[["@name"],["details"]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,8],[[30,2],[30,5,["Service","ID"]]],null]],[[[44,[[28,[37,9],[[28,[37,10],[[30,5,["Checks"]],[28,[37,7],[[30,8,["Checks"]],[28,[37,10],null,null]],null]],null]],null]],[[[1,"\\n"],[41,[30,10],[[[1," "],[8,[39,11],null,[["@item"],[[30,5,["Service"]]]],null],[1,"\\n "],[8,[39,12],null,[["@type","@items"],["service",[28,[37,13],["ServiceID","",[30,9]],null]]],null],[1,"\\n"]],[]],[[[41,[51,[30,0,["areAllExternalSourcesMatching"]]],[[[1," "],[8,[39,11],null,[["@item"],[[30,5,["Service"]]]],null],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,12],null,[["@type","@items"],["service",[28,[37,13],["ServiceID","",[30,9]],null]]],null],[1,"\\n\\n"],[41,[51,[30,5,["Node","Meta","synthetic-node"]]],[[[1," "],[8,[39,12],null,[["@type","@items"],["node",[28,[37,15],["ServiceID","",[30,9]],null]]],null],[1,"\\n"]],[]],null]],[]]],[41,[30,8],[[[1," "],[10,"dl"],[14,0,"mesh"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n This service uses a proxy for the Consul service mesh\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n in service mesh with proxy\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,17],[[28,[37,18],[[30,10]],null],[28,[37,18],[[30,5,["Node","Meta","synthetic-node"]]],null]],null],[[[1," "],[10,"dl"],[14,0,"node"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n Node\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,3],[15,6,[28,[37,6],["dc.nodes.show",[30,5,["Node","Node"]]],null]],[12],[1,[30,5,["Node","Node"]]],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,5,["Service","Port"]],[[[1," "],[10,"dl"],[14,0,"address"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,16],null,null,[["default"],[[[[1,"\\n IP Address and Port\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[41,[28,[37,19],[[30,5,["Service","Address"]],""],null],[[[1," "],[1,[30,5,["Service","Address"]]],[1,":"],[1,[30,5,["Service","Port"]]],[1,"\\n"]],[]],[[[1," "],[1,[30,5,["Node","Address"]]],[1,":"],[1,[30,5,["Service","Port"]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[41,[30,5,["Service","SocketPath"]],[[[1," "],[10,"dl"],[14,0,"socket"],[12],[1,"\\n "],[11,"dt"],[4,[38,16],null,null],[12],[1,"\\n Socket Path\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,5,["Service","SocketPath"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[]]],[1," "],[8,[39,20],null,[["@item"],[[30,5,["Service"]]]],null],[1,"\\n\\n"]],[9]]]],[8]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[5,6]]]]],[1,"\\n"]],[2]]]],["@proxies","proxies","&attrs","@items","item","index","@routeName","proxy","checks","@node"],false,["let","to-hash","list-collection","block-slot","if","eq","href-to","or","get","merge-checks","array","consul/external-source","consul/instance-checks","filter-by","unless","reject-by","tooltip","and","not","not-eq","tag-list"]]',moduleName:"consul-ui/components/consul/service-instance/list/index.hbs",isStrictMode:!1}) +class i extends l.default{get areAllExternalSourcesMatching(){var e,t,n +const l=null===(e=this.args.items[0])||void 0===e||null===(t=e.Service)||void 0===t||null===(n=t.Meta)||void 0===n?void 0:n["external-source"] +return this.args.items.every((e=>{var t,n +return(null===(t=e.Service)||void 0===t||null===(n=t.Meta)||void 0===n?void 0:n["external-source"])===l}))}}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/consul/service-instance/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"VjdzBiZi",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-service-instance-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.service-instance.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.service-instance.search-bar.",[30,3,["status","key"]],".options.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n"],[41,[30,2,["searchproperty"]],[[[1," "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,10],null,[["@value","@selected"],[[30,11],[28,[37,10],[[30,11],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,11],[[30,11]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[11]],null]],[10]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,12,["Select"]],[[24,0,"type-status"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["status","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.consul.status"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,13,["Optgroup"]],[30,13,["Option"]]],[[[42,[28,[37,9],[[28,[37,9],[[28,[37,4],["passing","warning","critical","empty"],null]],null]],null],null,[[[1," "],[8,[30,15],[[16,0,[29,["value-",[30,16]]]]],[["@value","@selected"],[[30,16],[28,[37,10],[[30,16],[30,2,["status","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[30,16]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,16]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[16]],null]],[14,15]]],[1," "]],[]]]]],[1,"\\n "]],[13]]]]],[1,"\\n"],[41,[28,[37,12],[[30,17,["length"]],0],null],[[[1," "],[8,[30,12,["Select"]],[[24,0,"type-source"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["source","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@components","@filter","@sources"],[[30,18],[30,2],[30,17]]],null],[1,"\\n "]],[18]]]]],[1,"\\n"]],[]],null],[1," "]],[12]],[[[1,"\\n "],[8,[30,19,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,20,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,14],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["Status:asc",[28,[37,2],["common.sort.status.asc"],null]],null],[28,[37,4],["Status:desc",[28,[37,2],["common.sort.status.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,15],[[30,22],[30,20,["value"]]],null]],[1,"\\n"]],[22]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,21,["Optgroup"]],[30,21,["Option"]]],[[[1," "],[8,[30,23],null,[["@label"],[[28,[37,2],["common.consul.status"],null]]],[["default"],[[[[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["Status:asc",[28,[37,16],["Status:asc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["Status:desc",[28,[37,16],["Status:desc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@label"],[[28,[37,2],["components.consul.service-instance.search-bar.sort.name.name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["Name:asc",[28,[37,16],["Name:asc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,24],null,[["@value","@selected"],["Name:desc",[28,[37,16],["Name:desc",[30,20,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[23,24]]],[1," "]],[]]]]],[1,"\\n "]],[21]]]]],[1,"\\n "]],[19]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Option","prop","search","components","Optgroup","Option","state","@sources","components","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","if","block-slot","each","-track-array","includes","lowercase","gt","consul/sources-select","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/service-instance/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/service/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"xPCwneUJ",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-service-list"],[17,1]],[["@items","@linkable"],[[30,2],"linkable service"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@item","@partition","@nspace"],[[30,3],[30,5],[30,6]]],null],[1,"\\n"]],[3,4]]]]],[1,"\\n"]],["&attrs","@items","item","index","@partition","@nspace"],false,["list-collection","consul/service/list/item"]]',moduleName:"consul-ui/components/consul/service/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/service/list/item/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"cAe7geUl",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"dl"],[15,0,[30,1,["MeshStatus"]]],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Health\\n "],[13],[1,"\\n "],[11,"dd"],[4,[38,1],[[30,1,["healthTooltipText"]]],null],[12],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,3],[[30,1,["InstanceCount"]],0],null],[[[1," "],[10,3],[15,6,[28,[37,4],["dc.services.show.index",[30,1,["Name"]]],[["params"],[[30,0,["linkParams"]]]]]],[12],[1,"\\n "],[1,[30,1,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,2],[12],[1,"\\n "],[1,[30,1,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]]]],[]]]]],[1,"\\n"],[8,[39,0],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@item"],[[30,1]]],null],[1,"\\n "],[8,[39,6],null,[["@item"],[[30,1]]],null],[1,"\\n"],[41,[28,[37,7],[[28,[37,8],[[30,1,["InstanceCount"]],0],null],[28,[37,7],[[28,[37,8],[[30,1,["Kind"]],"terminating-gateway"],null],[28,[37,8],[[30,1,["Kind"]],"ingress-gateway"],null]],null]],null],[[[1," "],[10,1],[12],[1,"\\n "],[1,[28,[35,9],[[30,1,["InstanceCount"]]],null]],[1,"\\n "],[1,[28,[35,10],[[30,1,["InstanceCount"]],"instance"],[["without-count"],[true]]]],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[51,[30,2]],[[[1," "],[8,[39,12],null,[["@item","@nspace","@partition"],[[30,1],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[41,[28,[37,13],[[30,1,["Kind"]],"terminating-gateway"],null],[[[1," "],[10,1],[12],[1,"\\n "],[1,[28,[35,9],[[30,1,["GatewayConfig","AssociatedServiceCount"]]],null]],[1,"\\n "],[1,[28,[35,10],[[30,1,["GatewayConfig","AssociatedServiceCount"]],"linked service"],[["without-count"],[true]]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[41,[28,[37,13],[[30,1,["Kind"]],"ingress-gateway"],null],[[[1," "],[10,1],[12],[1,"\\n "],[1,[28,[35,9],[[30,1,["GatewayConfig","AssociatedServiceCount"]]],null]],[1,"\\n "],[1,[28,[35,10],[[30,1,["GatewayConfig","AssociatedServiceCount"]],"upstream"],[["without-count"],[true]]]],[1,"\\n "],[13],[1,"\\n "]],[]],null]],[]]],[41,[28,[37,14],[[30,1,["ConnectedWithGateway"]],[30,1,["ConnectedWithProxy"]]],null],[[[1," "],[10,"dl"],[14,0,"mesh"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[8,[39,1],null,null,[["default"],[[[[1,"\\n This service uses a proxy for the Consul service mesh\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,7],[[30,1,["ConnectedWithGateway"]],[30,1,["ConnectedWithProxy"]]],null],[[[1," "],[10,"dd"],[12],[1,"\\n in service mesh with proxy and gateway\\n "],[13],[1,"\\n"]],[]],[[[41,[30,1,["ConnectedWithProxy"]],[[[1," "],[10,"dd"],[12],[1,"\\n in service mesh with proxy\\n "],[13],[1,"\\n"]],[]],[[[41,[30,1,["ConnectedWithGateway"]],[[[1," "],[10,"dd"],[12],[1,"\\n in service mesh with gateway\\n "],[13],[1,"\\n "]],[]],null]],[]]]],[]]],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[8,[39,15],null,[["@item"],[[30,1]]],null],[1,"\\n"]],[]]]]]],["@item","@isPeerDetail","@nspace","@partition"],false,["block-slot","tooltip","if","gt","href-to","consul/kind","consul/external-source","and","not-eq","format-number","pluralize","unless","consul/bucket/list","eq","or","tag-list"]]',moduleName:"consul-ui/components/consul/service/list/item/index.hbs",isStrictMode:!1}) +class i extends l.default{get linkParams(){const e={} +return this.args.item.Partition&&this.args.partition!==this.args.item.Partition?(e.partition=this.args.item.Partition,e.nspace=this.args.Namespace):this.args.item.Namespace&&this.args.nspace!==this.args.item.Namespace&&(e.nspace=this.args.item.Namespace),this.args.item.PeerName&&(e.peer=this.args.item.PeerName),e}}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/consul/service/search-bar/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"4sJ6oMs1",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-service-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.service.search-bar.",[30,3,["status","key"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.service.search-bar.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-status"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["status","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.consul.status"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,0,["healthStates"]]],null]],null],null,[[[1," "],[8,[30,16],[[16,0,[29,["value-",[30,17]]]]],[["@value","@selected"],[[30,17],[28,[37,9],[[30,17],[30,2,["status","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[30,17]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,17]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "],[8,[30,13,["Select"]],null,[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["kind","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.service.search-bar.kind"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,18,["Optgroup"]],[30,18,["Option"]]],[[[1," "],[8,[30,20],null,[["@value","@selected"],["service",[28,[37,9],["service",[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],["common.consul.service"],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,19],null,[["@label"],[[28,[37,2],["common.consul.gateway"],null]]],[["default"],[[[[1,"\\n"],[42,[28,[37,8],[[28,[37,8],[[28,[37,4],["api-gateway","ingress-gateway","terminating-gateway","mesh-gateway"],null]],null]],null],null,[[[1," "],[8,[30,20],null,[["@value","@selected"],[[30,21],[28,[37,9],[[30,21],[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[30,21]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[21]],null],[1," "]],[]]]]],[1,"\\n "],[8,[30,19],null,[["@label"],[[28,[37,2],["common.consul.mesh"],null]]],[["default"],[[[[1,"\\n"],[42,[28,[37,8],[[28,[37,8],[[28,[37,4],["in-mesh","not-in-mesh"],null]],null]],null],null,[[[1," "],[8,[30,20],null,[["@value","@selected"],[[30,22],[28,[37,9],[[30,22],[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.search.",[30,22]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22]],null],[1," "]],[]]]]],[1,"\\n"]],[19,20]]],[1," "]],[]]]]],[1,"\\n "]],[18]]]]],[1,"\\n"],[41,[28,[37,12],[[30,23,["length"]],0],null],[[[1," "],[8,[30,13,["Select"]],[[24,0,"type-source"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["source","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@components","@filter","@sources"],[[30,24],[30,2],[30,0,["sortedSources"]]]],null],[1,"\\n "]],[24]]]]],[1,"\\n"]],[]],null],[1," "]],[13]],[[[1,"\\n "],[8,[30,25,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,26,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,14],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["Status:asc",[28,[37,2],["common.sort.status.asc"],null]],null],[28,[37,4],["Status:desc",[28,[37,2],["common.sort.status.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,15],[[30,28],[30,26,["value"]]],null]],[1,"\\n"]],[28]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,27,["Optgroup"]],[30,27,["Option"]]],[[[1," "],[8,[30,29],null,[["@label"],[[28,[37,2],["common.consul.status"],null]]],[["default"],[[[[1,"\\n "],[8,[30,30],null,[["@value","@selected"],["Status:asc",[28,[37,16],["Status:asc",[30,26,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,30],null,[["@value","@selected"],["Status:desc",[28,[37,16],["Status:desc",[30,26,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,29],null,[["@label"],[[28,[37,2],["common.consul.service-name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,30],null,[["@value","@selected"],["Name:asc",[28,[37,16],["Name:asc",[30,26,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,30],null,[["@value","@selected"],["Name:desc",[28,[37,16],["Name:desc",[30,26,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[29,30]]],[1," "]],[]]]]],[1,"\\n "]],[27]]]]],[1,"\\n "]],[25]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","state","components","Optgroup","Option","kind","state","@sources","components","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","if","gt","consul/sources-select","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/service/search-bar/index.hbs",isStrictMode:!1}) +class i extends l.default{get healthStates(){return this.args.peer?["passing","warning","critical","unknown","empty"]:["passing","warning","critical","empty"]}get sortedSources(){const e=this.args.sources||[] +return e.unshift(["consul"]),e.includes("consul-api-gateway")?[...e.filter((e=>"consul-api-gateway"!==e)),"consul-api-gateway"]:e}}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/consul/source/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"94oD1HbB",block:'[[[1,"\\n"],[10,"dl"],[14,0,"tooltip-panel"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[10,1],[14,0,"consul-source"],[12],[1,"\\n "],[1,[30,1]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,0],null,[["@position"],["left"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],["components.consul.source.header"],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,"role","separator"],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.source.menu-title"],null]],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[14,"role","none"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[14,"tabindex","-1"],[14,"role","menuitem"],[15,6,[29,[[28,[37,3],["CONSUL_DOCS_URL"],null],"/connect/l7-traffic"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.source.links.documentation"],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n\\n"]],["@source"],false,["menu-panel","block-slot","t","env"]]',moduleName:"consul-ui/components/consul/source/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/sources-select/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"FlZT/Gne",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1,["length"]],0],null],[[[1," "],[8,[39,2],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,3],["common.search.source"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,2],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["Option"]]],[[[42,[28,[37,6],[[28,[37,6],[[30,1]],null]],null],null,[[[44,[[28,[37,7],[[30,4]],null]],[[[1," "],[8,[30,3],[[16,0,[52,[51,[30,5]],[30,4]]]],[["@value","@selected"],[[30,4],[28,[37,9],[[30,4],[30,6,["source","value"]]],null]]],[["default"],[[[[1,"\\n"],[41,[30,5],[[[1," "],[8,[39,10],[[24,0,"mr-2.5"]],[["@name"],[[30,5]]],null],[1,"\\n"]],[]],null],[1," "],[1,[28,[35,3],[[28,[37,11],["common.brand.",[30,4]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[5]]]],[4]],null]],[3]]],[1," "]],[]]]]],[1,"\\n"]],[]],null]],["@sources","@components","Option","source","flightIcon","@filter"],false,["if","gt","block-slot","t","let","each","-track-array","icon-mapping","unless","includes","flight-icon","concat"]]',moduleName:"consul-ui/components/consul/sources-select/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/token/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"0BngM4XH",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-token-list"]],[["@items"],[[30,1]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],[[30,2,["AccessorID"]],[30,3,["AccessorID"]]],null],[[[1," "],[10,"dl"],[14,"rel","me"],[12],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,4],null,[["@position"],["top-start"]],[["default"],[[[[1,"\\n Your token\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[10,3],[15,6,[28,[37,5],["dc.acls.tokens.edit",[30,2,["AccessorID"]]],null]],[12],[1,[28,[35,6],[[30,2,["AccessorID"]],-8],null]],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Scope"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[52,[30,2,["Local"]],"local","global"]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,7],null,[["@item"],[[30,2]]],null],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,8],[[30,2,["Description"]],[30,2,["Name"]]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[30,2,["hasSecretID"]],[[[1," "],[8,[39,9],null,[["@value","@name"],[[30,2,["SecretID"]],[28,[37,10],["components.consul.token.secretID"],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,10],["components.consul.token.secretID"],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "],[8,[30,4],null,null,[["default"],[[[[1,"\\n "],[8,[30,5],null,[["@href"],[[28,[37,5],["dc.acls.tokens.edit",[30,2,["AccessorID"]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n"],[41,[28,[37,11],["write token"],[["item"],[[30,2]]]],[[[1," Edit\\n"]],[]],[[[1," View\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,11],["duplicate token"],[["item"],[[30,2]]]],[[[1," "],[8,[30,5],null,[["@onclick"],[[28,[37,12],[[30,0],[30,6],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Duplicate\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1,"\\n"],[41,[28,[37,3],[[30,2,["AccessorID"]],[33,13,["AccessorID"]]],null],[[[1," "],[8,[30,5],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,12],[[30,0],[30,7],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Logout\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,8],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm logout\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to stop using this ACL token? This will log you out.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,9],null,null,[["default"],[[[[1,"Logout"]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[30,5],null,[["@onclick"],[[28,[37,12],[[30,0],[30,10],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Use\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,11],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm use\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to use this ACL token?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,12],null,null,[["default"],[[[[1,"Use"]],[]]]]],[1,"\\n "]],[12]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[11]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1,"\\n\\n"],[41,[28,[37,11],["delete token"],[["item","token"],[[30,2],[30,3]]]],[[[1," "],[8,[30,5],[[24,0,"dangerous"]],[["@onclick"],[[28,[37,12],[[30,0],[30,13],[30,2]],null]]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirmation"]],[["default"],[[[[1,"\\n "],[8,[30,14],[[24,0,"warning"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n Confirm delete\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to delete this token?\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["confirm"]],[["default"],[[[[1,"\\n "],[8,[30,15],null,null,[["default"],[[[[1,"Delete"]],[]]]]],[1,"\\n "]],[15]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1,"\\n "]],[5]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[2]]]]]],["@items","item","@token","Actions","Action","@onclone","@onlogout","Confirmation","Confirm","@onuse","Confirmation","Confirm","@ondelete","Confirmation","Confirm"],false,["list-collection","block-slot","if","eq","tooltip","href-to","substr","consul/token/ruleset/list","or","consul-copy-button","t","can","action","token"]]',moduleName:"consul-ui/components/consul/token/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/token/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"dh/3vHST",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1],"create"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," The token has been added.\\n"]],[]],[[[1," There was an error adding the token.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"update"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," The token has been saved.\\n"]],[]],[[[1," There was an error saving the token.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"delete"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," The token was deleted.\\n"]],[]],[[[1," There was an error deleting the token.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"clone"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," The token has been cloned as "],[1,[28,[35,2],[[30,3,["AccessorID"]],8,false],null]],[1,"\\n"]],[]],[[[1," There was an error cloning the token.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"use"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," You are now using the new ACL token\\n"]],[]],[[[1," There was an error using that ACL token.\\n"]],[]]]],[]],null]],[]]]],[]]]],[]]]],[]]],[44,[[30,4,["errors","firstObject"]]],[[[41,[30,5,["detail"]],[[[1," "],[10,"br"],[12],[13],[1,[28,[35,4],["(",[52,[30,5,["status"]],[28,[37,4],[[30,5,["status"]],": "],null]],[30,5,["detail"]],")"],null]],[1,"\\n"]],[]],null]],[5]]]],["@type","@status","@item","@error","error"],false,["if","eq","truncate","let","concat"]]',moduleName:"consul-ui/components/consul/token/notifications/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/token/ruleset/list/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"K4Pw6G3b",block:'[[[1,"\\n"],[44,[[28,[37,1],[[28,[37,2],[[33,3,["Policies"]],[33,3,["ACLs","PolicyDefaults"]],[28,[37,4],null,null]],null]],null]],[[[44,[[28,[37,5],[[30,1],"management"],null]],[[[41,[28,[37,7],[[30,2,["length"]],0],null],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Management\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[42,[28,[37,9],[[28,[37,9],[[28,[37,5],[[30,1],"management"],null]],null]],null],null,[[[1," "],[10,1],[15,0,[28,[37,10],[[30,3]],null]],[12],[1,[30,3,["Name"]]],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[2]]],[44,[[28,[37,5],[[30,1],"identities"],null]],[[[41,[28,[37,7],[[30,4,["length"]],0],null],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Identities"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[42,[28,[37,9],[[28,[37,9],[[30,4]],null]],null],null,[[[1," "],[10,1],[15,0,[28,[37,10],[[30,5]],null]],[12],[1,[30,5,["Name"]]],[13],[1,"\\n"]],[5]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[4]]],[41,[28,[37,11],[[33,3]],null],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Rules"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n Legacy tokens have embedded rules.\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[44,[[28,[37,12],[[28,[37,5],[[30,1],"policies"],null],[28,[37,2],[[33,3,["Roles"]],[33,3,["ACLs","RoleDefaults"]],[28,[37,4],null,null]],null]],null]],[[[41,[28,[37,7],[[30,6,["length"]],0],null],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Rules"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[42,[28,[37,9],[[28,[37,9],[[30,6]],null]],null],null,[[[1," "],[10,1],[15,0,[28,[37,10],[[30,7]],null]],[12],[1,[30,7,["Name"]]],[13],[1,"\\n"]],[7]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[6]]]],[]]]],[1]]]],["policies","management","item","identities","item","policies","item"],false,["let","policy/group","or","item","array","get","if","gt","each","-track-array","policy/typeof","token/is-legacy","append"]]',moduleName:"consul-ui/components/consul/token/ruleset/list/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) +e.default=r})),define("consul-ui/components/consul/token/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"bjhw2BTT",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-token-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.token.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.token.search-bar.",[30,3,["status","key"]],".options.",[30,3,["status","value"]]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-status"]],[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["kind","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.token.search-bar.kind.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[28,[37,4],["global-management","global","local"],null]],null]],null],null,[[[1," "],[8,[30,16],[[16,0,[29,["value-",[30,17]]]]],[["@value","@selected"],[[30,17],[28,[37,9],[[30,17],[30,2,["kind","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["components.consul.token.search-bar.kind.options.",[30,17]],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,17]],null]],null]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,18,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,19,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["CreateTime:desc",[28,[37,2],["common.sort.age.desc"],null]],null],[28,[37,4],["CreateTime:asc",[28,[37,2],["common.sort.age.asc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,21],[30,19,["value"]]],null]],[1,"\\n"]],[21]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,20,["Optgroup"]],[30,20,["Option"]]],[[[1," "],[8,[30,22],null,[["@label"],[[28,[37,2],["common.ui.creation"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["CreateTime:desc",[28,[37,13],["CreateTime:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.age.desc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["CreateTime:asc",[28,[37,13],["CreateTime:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.age.asc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22,23]]],[1," "]],[]]]]],[1,"\\n "]],[20]]]]],[1,"\\n "]],[18]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","state","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/token/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/token/selector/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object"],(function(e,t,n,l,r){var i +function o(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const a=(0,n.createTemplateFactory)({id:"IGuw4tq5",block:'[[[1,"\\n"],[41,[28,[37,1],["use acls"],null],[[[1," "],[8,[39,2],null,[["@src","@sink","@onchange"],[[28,[37,3],["settings://consul:token"],null],[28,[37,3],["settings://consul:token"],null],[30,0,["reauthorize"]]]],[["unauthorized","authorized"],[[[[1,"\\n\\n "],[8,[39,4],null,[["@name","@onclose","@onopen","@aria"],["login-toggle",[30,0,["close"]],[30,0,["open"]],[28,[37,5],null,[["label"],["Log in to Consul"]]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@target","@name","@value"],[[30,0],"modal",[30,2]]],null],[1,"\\n "],[8,[39,7],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n Log in to Consul\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@dc","@partition","@nspace","@onsubmit"],[[30,3,["Name"]],[30,4],[30,5],[28,[37,9],[[30,0],[30,1,["login"]]],[["value"],["data"]]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@target","@name","@value"],[[30,0],"authForm",[30,6]]],null],[1,"\\n"],[41,[28,[37,1],["use SSO"],null],[[[1," "],[8,[30,6,["Method"]],null,[["@matches"],["sso"]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@dc","@partition","@nspace","@disabled","@onchange","@onerror"],[[30,3,["Name"]],[30,4],[30,5],[30,6,["disabled"]],[30,6,["submit"]],[30,6,["error"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,11],[[4,[38,12],["click",[30,2,["close"]]],null]],[["@color","@text"],["secondary","Continue without logging in"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n\\n "],[8,[39,13],[[24,0,"hds-side-nav__dropdown"]],[["@listPosition"],["bottom-left"]],[["default"],[[[[1,"\\n\\n "],[8,[30,7,["ToggleIcon"]],null,[["@icon","@text"],["user","Auth menu"]],null],[1,"\\n "],[8,[30,7,["Interactive"]],null,[["@href","@text","@isHrefExternal"],[[28,[37,14],["settings"],[["params"],[[28,[37,5],null,[["nspace","partition"],[[27],[27]]]]]]],[28,[37,15],["components.hashicorp-consul.side-nav.user-menu.settings"],null],false]],null],[1,"\\n "],[8,[30,7,["Interactive"]],[[4,[38,12],["click",[28,[37,16],[[30,0,["modal","open"]]],null]],null]],[["@text"],[[28,[37,15],["components.hashicorp-consul.side-nav.user-menu.log-in"],null]]],null],[1,"\\n "]],[7]]]]],[1,"\\n "]],[1]],[[[1,"\\n\\n "],[8,[39,4],null,[["@name","@onclose","@onopen","@aria"],["login-toggle",[30,0,["close"]],[30,0,["open"]],[28,[37,5],null,[["label"],["Log in with a different token"]]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@target","@name","@value"],[[30,0],"modal",[30,9]]],null],[1,"\\n "],[8,[39,7],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n Log in with a different token\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@dc","@nspace","@partition","@onsubmit"],[[30,3,["Name"]],[30,5],[30,4],[28,[37,9],[[30,0],[30,8,["login"]]],[["value"],["data"]]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@target","@name","@value"],[[30,0],"authForm",[30,10]]],null],[1,"\\n "]],[10]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,11],[[4,[38,12],["click",[30,9,["close"]]],null]],[["@color","@text"],["secondary","Continue without logging in"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n\\n "],[8,[39,13],[[24,0,"hds-side-nav__dropdown"]],[["@listPosition"],["bottom-left"]],[["default"],[[[[1,"\\n "],[8,[30,11,["ToggleIcon"]],null,[["@icon","@text"],["user","Auth menu"]],null],[1,"\\n"],[41,[30,8,["token","AccessorID"]],[[[1," "],[8,[30,11,["Description"]],null,[["@text"],[[28,[37,15],["components.consul.token.selector.logged-in"],[["token","htmlSafe"],[[28,[37,17],[[30,8,["token","AccessorID"]],[28,[37,18],[[30,8,["token","AccessorID","length"]],8],null]],null],true]]]]],null],[1,"\\n"]],[]],null],[1," "],[8,[30,11,["Separator"]],null,null,null],[1,"\\n "],[8,[30,11,["Interactive"]],null,[["@href","@text","@isHrefExternal"],[[28,[37,14],["settings"],[["params"],[[28,[37,5],null,[["nspace","partition"],[[27],[27]]]]]]],[28,[37,15],["components.hashicorp-consul.side-nav.user-menu.settings"],null],false]],null],[1,"\\n "],[8,[30,11,["Interactive"]],[[4,[38,12],["click",[28,[37,16],[[30,8,["logout"]]],null]],null]],[["@text"],[[28,[37,15],["components.hashicorp-consul.side-nav.user-menu.log-out"],null]]],null],[1,"\\n "]],[11]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "],[18,13,[[28,[37,5],null,[["open","close"],[[30,0,["modal","open"]],[30,0,["model","close"]]]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,13],[[24,0,"hds-side-nav__dropdown"]],[["@listPosition"],["bottom-left"]],[["default"],[[[[1,"\\n "],[8,[30,12,["ToggleIcon"]],null,[["@icon","@text"],["user","Auth menu"]],null],[1,"\\n "],[8,[30,12,["Interactive"]],null,[["@href","@text","@isHrefExternal"],[[28,[37,14],["settings"],[["params"],[[28,[37,5],null,[["nspace","partition"],[[27],[27]]]]]]],[28,[37,15],["components.hashicorp-consul.side-nav.user-menu.settings"],null],false]],null],[1,"\\n "]],[12]]]]],[1,"\\n"]],[]]]],["authDialog","modal","@dc","@partition","@nspace","authForm","dd","authDialog","modal","authForm","dd","dd","&default"],false,["if","can","auth-dialog","uri","modal-dialog","hash","ref","block-slot","auth-form","action","oidc-select","hds/button","on","hds/dropdown","href-to","t","optional","string-substring","sub","yield"]]',moduleName:"consul-ui/components/consul/token/selector/index.hbs",isStrictMode:!1}) +let u=(o((i=class extends l.default{open(){this.authForm.focus()}close(){this.authForm.reset()}reauthorize(e){this.modal.close(),this.args.onchange(e)}}).prototype,"open",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"open"),i.prototype),o(i.prototype,"close",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"close"),i.prototype),o(i.prototype,"reauthorize",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"reauthorize"),i.prototype),i) +e.default=u,(0,t.setComponentTemplate)(a,u)})),define("consul-ui/components/consul/tomography/graph/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking"],(function(e,t,n,l,r){var i,o +function a(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const u=(0,n.createTemplateFactory)({id:"NUlnPif0",block:'[[[1,"\\n"],[11,0],[24,0,"tomography-graph"],[17,1],[12],[1,"\\n "],[10,"svg"],[15,"width",[30,0,["size"]]],[15,"height",[30,0,["size"]]],[12],[1,"\\n "],[10,"g"],[15,"transform",[29,["translate(",[28,[37,0],[[30,0,["size"]],2],null],", ",[28,[37,0],[[30,0,["size"]],2],null],")"]]],[12],[1,"\\n "],[10,"g"],[12],[1,"\\n "],[10,"circle"],[14,0,"background"],[15,"r",[30,0,["circle","0"]]],[12],[13],[1,"\\n "],[10,"circle"],[14,0,"axis"],[15,"r",[30,0,["circle","1"]]],[12],[13],[1,"\\n "],[10,"circle"],[14,0,"axis"],[15,"r",[30,0,["circle","2"]]],[12],[13],[1,"\\n "],[10,"circle"],[14,0,"axis"],[15,"r",[30,0,["circle","3"]]],[12],[13],[1,"\\n "],[10,"circle"],[14,0,"border"],[15,"r",[30,0,["circle","4"]]],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[14,0,"lines"],[12],[1,"\\n"],[42,[28,[37,2],[[28,[37,2],[[30,0,["distances"]]],null]],null],null,[[[1," "],[11,"rect"],[16,"transform",[29,["rotate(",[30,2,["rotate"]],")"]]],[16,"width",[30,2,["y2"]]],[24,"height","1"],[4,[38,3],[[28,[37,4],[[30,2,["node"]]," - ",[28,[37,5],[[30,2,["distance"]]],[["maximumFractionDigits"],[2]]],"ms",[52,[30,2,["segment"]],[28,[37,4],["
      (Segment: ",[30,2,["segment"]],")"],null]]],null]],[["options"],[[28,[37,7],null,[["followCursor","allowHTML"],[true,true]]]]]],[12],[13],[1,"\\n"]],[2]],null],[1," "],[13],[1,"\\n "],[10,"g"],[14,0,"labels"],[12],[1,"\\n "],[10,"circle"],[14,0,"point"],[14,"r","5"],[12],[13],[1,"\\n "],[10,"g"],[14,0,"tick"],[15,"transform",[29,["translate(0, ",[30,0,["labels","0"]],")"]]],[12],[1,"\\n "],[10,"line"],[14,"x2","70"],[12],[13],[1,"\\n "],[10,"text"],[14,"x","75"],[14,"y","0"],[14,"dy",".32em"],[12],[1,[28,[35,5],[[30,0,["milliseconds","0"]]],[["maximumFractionDigits"],[2]]]],[1,"ms"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[14,0,"tick"],[15,"transform",[29,["translate(0, ",[30,0,["labels","1"]],")"]]],[12],[1,"\\n "],[10,"line"],[14,"x2","70"],[12],[13],[1,"\\n "],[10,"text"],[14,"x","75"],[14,"y","0"],[14,"dy",".32em"],[12],[1,[28,[35,5],[[30,0,["milliseconds","1"]]],[["maximumFractionDigits"],[2]]]],[1,"ms"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[14,0,"tick"],[15,"transform",[29,["translate(0, ",[30,0,["labels","2"]],")"]]],[12],[1,"\\n "],[10,"line"],[14,"x2","70"],[12],[13],[1,"\\n "],[10,"text"],[14,"x","75"],[14,"y","0"],[14,"dy",".32em"],[12],[1,[28,[35,5],[[30,0,["milliseconds","2"]]],[["maximumFractionDigits"],[2]]]],[1,"ms"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"g"],[14,0,"tick"],[15,"transform",[29,["translate(0, ",[30,0,["labels","3"]],")"]]],[12],[1,"\\n "],[10,"line"],[14,"x2","70"],[12],[13],[1,"\\n "],[10,"text"],[14,"x","75"],[14,"y","0"],[14,"dy",".32em"],[12],[1,[28,[35,5],[[30,0,["milliseconds","3"]]],[["maximumFractionDigits"],[2]]]],[1,"ms"],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs","item"],false,["div","each","-track-array","tooltip","concat","format-number","if","hash"]]',moduleName:"consul-ui/components/consul/tomography/graph/index.hbs",isStrictMode:!1}),s=function(e){return 160*e} +let c=(i=class extends l.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="max",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a(this,"size",336),a(this,"circle",[s(1),s(.25),s(.5),s(.75),s(1)]),a(this,"labels",[s(-.25),s(-.5),s(-.75),s(-1)])}get milliseconds(){const e=(this.args.distances||[]).reduce(((e,t)=>Math.max(e,t.distance)),this.max) +return[25,50,75,100].map((t=>function(e,t){return t>0?parseInt(t*e)/100:0}(t,e)))}get distances(){let e=this.args.distances||[] +const t=e.reduce(((e,t)=>Math.max(e,t.distance)),this.max),n=e.length +if(n>360){const t=360/n +e=e.filter((function(e,l){return 0==l||l==n-1||Math.random()({rotate:360*l/e.length,y2:n.distance/t*160,node:n.node,distance:n.distance,segment:n.segment})))}},d=i.prototype,p="max",f=[r.tracked],m={configurable:!0,enumerable:!0,writable:!0,initializer:function(){return-999999999}},b={},Object.keys(m).forEach((function(e){b[e]=m[e]})),b.enumerable=!!b.enumerable,b.configurable=!!b.configurable,("value"in b||b.initializer)&&(b.writable=!0),b=f.slice().reverse().reduce((function(e,t){return t(d,p,e)||e}),b),h&&void 0!==b.initializer&&(b.value=b.initializer?b.initializer.call(h):void 0,b.initializer=void 0),void 0===b.initializer&&(Object.defineProperty(d,p,b),b=null),o=b,i) +var d,p,f,m,h,b +e.default=c,(0,t.setComponentTemplate)(u,c)})),define("consul-ui/components/consul/transparent-proxy/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"QQRh7noe",block:'[[[1,"\\n"],[10,1],[14,0,"consul-transparent-proxy"],[12],[1,"\\n "],[1,[28,[35,0],["components.consul.transparent-proxy"],null]],[1,"\\n"],[13]],[],false,["t"]]',moduleName:"consul-ui/components/consul/transparent-proxy/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/upstream-instance/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"o/cQrCOP",block:'[[[1,"\\n"],[11,0],[24,0,"consul-upstream-instance-list"],[17,1],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,1],[[28,[37,1],[[30,2]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n\\n "],[10,0],[14,0,"header"],[12],[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[30,3,["DestinationName"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[10,0],[14,0,"detail"],[12],[1,"\\n\\n"],[41,[28,[37,3],[[30,3,["DestinationType"]],"prepared_query"],null],[[[1," "],[8,[39,4],null,[["@item","@partition","@nspace"],[[28,[37,5],null,[["Namespace","Partition"],[[28,[37,6],[[30,3,["DestinationNamespace"]],[30,4]],null],[28,[37,6],[[30,3,["DestinationPartition"]],[30,5]],null]]]],[30,5],[30,4]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[41,[28,[37,7],[[28,[37,3],[[30,3,["Datacenter"]],[30,6]],null],[28,[37,3],[[30,3,["Datacenter"]],""],null]],null],[[[1," "],[10,"dl"],[14,0,"datacenter"],[12],[1,"\\n "],[11,"dt"],[4,[38,8],null,null],[12],[1,"\\n Datacenter\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["Datacenter"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1,"\\n"],[41,[30,3,["LocalBindSocketPath"]],[[[1," "],[10,"dl"],[14,0,"local-bind-socket-path"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Local bind socket path\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,3,["LocalBindSocketPath"]],"Local bind socket path"]],null],[1,"\\n "],[1,[30,3,["LocalBindSocketPath"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[14,0,"local-bind-socket-mode"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Mode\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,6],[[30,3,["LocalBindSocketMode"]],"-"],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1,"\\n"],[41,[28,[37,10],[[30,3,["LocalBindPort"]],0],null],[[[44,[[28,[37,12],[[28,[37,6],[[30,3,["LocalBindAddress"]],"127.0.0.1"],null],":",[30,3,["LocalBindPort"]]],null]],[[[1," "],[10,"dl"],[14,0,"local-bind-address"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Address\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,9],null,[["@value","@name"],[[30,7],"Address"]],null],[1,"\\n "],[1,[30,7]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[7]]]],[]],null],[1,"\\n"]],[]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@items","item","@nspace","@partition","@dc","combinedAddress"],false,["each","-track-array","if","not-eq","consul/bucket/list","hash","or","and","tooltip","consul-copy-button","gt","let","concat"]]',moduleName:"consul-ui/components/consul/upstream-instance/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/upstream-instance/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"7/RrQEaf",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-upstream-instance-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.upstream-instance.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.upstream-instance.search-bar.",[30,3,["status","value"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,14,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["DestinationName:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["DestinationName:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,16],[30,14,["value"]]],null]],[1,"\\n"]],[16]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,15,["Optgroup"]],[30,15,["Option"]]],[[[1," "],[8,[30,18],null,[["@value","@selected"],["DestinationName:asc",[28,[37,13],["DestinationName:asc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,18],null,[["@value","@selected"],["DestinationName:desc",[28,[37,13],["DestinationName:desc",[30,14,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n"]],[17,18]]],[1," "]],[]]]]],[1,"\\n "]],[15]]]]],[1,"\\n "]],[13]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/upstream-instance/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/upstream/list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"IiJIFQhR",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-upstream-list"],[17,1]],[["@items","@linkable"],[[30,2],"linkable upstream"]],[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],[[30,3,["InstanceCount"]],0],null],[[[1," "],[10,"dl"],[15,0,[30,3,["MeshStatus"]]],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Health\\n "],[13],[1,"\\n "],[11,"dd"],[4,[38,4],null,null],[12],[1,"\\n"],[41,[28,[37,5],["critical",[30,3,["MeshStatus"]]],null],[[[1," At least one health check on one instance is failing.\\n"]],[]],[[[41,[28,[37,5],["warning",[30,3,["MeshStatus"]]],null],[[[1," At least one health check on one instance has a warning.\\n"]],[]],[[[41,[28,[37,5],["passing",[30,3,["MeshStatus"]]],null],[[[1," All health checks are passing.\\n"]],[]],[[[1," There are no health checks.\\n "]],[]]]],[]]]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n "],[10,3],[15,6,[28,[37,6],["dc.services.show",[30,3,["Name"]]],[["params"],[[52,[28,[37,7],[[30,3,["Partition"]],[30,5]],null],[28,[37,8],null,[["partition","nspace"],[[30,3,["Partition"]],[30,3,["Namespace"]]]]],[52,[28,[37,7],[[30,3,["Namespace"]],[30,6]],null],[28,[37,8],null,[["nspace"],[[30,3,["Namespace"]]]]],[28,[37,8],null,null]]]]]]],[12],[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,2],[12],[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[8,[39,9],null,[["@item","@nspace","@partition"],[[30,3],[30,6],[30,5]]],null],[1,"\\n"],[42,[28,[37,11],[[28,[37,11],[[30,3,["GatewayConfig","Addresses"]]],null]],null],null,[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Address\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,12],null,[["@value","@name"],[[30,7],"Address"]],null],[1,"\\n "],[1,[30,7]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[7]],null],[1," "]],[]]]]],[1,"\\n"]],[3,4]]]]],[1,"\\n"]],["&attrs","@items","item","index","@partition","@nspace","address"],false,["list-collection","block-slot","if","gt","tooltip","eq","href-to","not-eq","hash","consul/bucket/list","each","-track-array","consul-copy-button"]]',moduleName:"consul-ui/components/consul/upstream/list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/consul/upstream/search-bar/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"CcoH46GJ",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"consul-upstream-search-bar"],[17,1]],[["@filter"],[[30,2]]],[["status","search","filter","sort"],[[[[1,"\\n\\n"],[44,[[28,[37,2],[[28,[37,3],["components.consul.upstream.search-bar.",[30,3,["status","key"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","key"]]],null],[28,[37,3],["common.consul.",[30,3,["status","key"]]],null]],null]]]],[28,[37,2],[[28,[37,3],["components.consul.upstream.search-bar.",[30,3,["status","value"]],".name"],null]],[["default"],[[28,[37,4],[[28,[37,3],["common.search.",[30,3,["status","value"]]],null],[28,[37,3],["common.consul.",[30,3,["status","value"]]],null],[28,[37,3],["common.brand.",[30,3,["status","value"]]],null]],null]]]]],[[[1," "],[8,[30,3,["RemoveFilter"]],[[16,"aria-label",[28,[37,2],["common.ui.remove"],[["item"],[[28,[37,3],[[30,4]," ",[30,5]],null]]]]]],null,[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[30,4]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]],[1,"\\n "]],[3]],[[[1,"\\n "],[8,[30,6,["Search"]],null,[["@onsearch","@value","@placeholder"],[[28,[37,5],[[30,0],[30,7]],null],[30,8],[28,[37,2],["common.search.search"],null]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Select"]],[[24,0,"type-search-properties"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,2,["searchproperty","change"]]],null],true,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["common.search.searchproperty"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,9,["Optgroup"]],[30,9,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[30,2,["searchproperty","default"]]],null]],null],null,[[[1," "],[8,[30,11],null,[["@value","@selected"],[[30,12],[28,[37,9],[[30,12],[30,2,["searchproperty","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[28,[37,10],[[30,12]],null]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[12]],null]],[10,11]]],[1," "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]],[[[1,"\\n "],[8,[30,13,["Select"]],null,[["@position","@onchange","@multiple"],["left",[28,[37,5],[[30,0],[30,2,["instance","change"]]],null],true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n "],[1,[28,[35,2],["components.consul.upstream.search-bar.instance.name"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,14,["Optgroup"]],[30,14,["Option"]]],[[[42,[28,[37,8],[[28,[37,8],[[28,[37,4],["registered","not-registered"],null]],null]],null],null,[[[1," "],[8,[30,16],null,[["@value","@selected"],[[30,17],[28,[37,9],[[30,17],[30,2,["instance","value"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["common.consul.",[30,17]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[17]],null]],[15,16]]],[1," "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[13]],[[[1,"\\n "],[8,[30,18,["Select"]],[[24,0,"type-sort"]],[["@position","@onchange","@multiple","@required"],["right",[28,[37,5],[[30,0],[30,19,["change"]]],null],false,true]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[10,1],[12],[1,"\\n"],[44,[[28,[37,11],[[28,[37,4],[[28,[37,4],["Name:asc",[28,[37,2],["common.sort.alpha.asc"],null]],null],[28,[37,4],["Name:desc",[28,[37,2],["common.sort.alpha.desc"],null]],null],[28,[37,4],["Status:asc",[28,[37,2],["common.sort.status.asc"],null]],null],[28,[37,4],["Status:desc",[28,[37,2],["common.sort.status.desc"],null]],null]],null]],null]],[[[1," "],[1,[28,[35,12],[[30,21],[30,19,["value"]]],null]],[1,"\\n"]],[21]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["options"]],[["default"],[[[[1,"\\n"],[44,[[30,20,["Optgroup"]],[30,20,["Option"]]],[[[1," "],[8,[30,22],null,[["@label"],[[28,[37,2],["common.consul.status"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Status:asc",[28,[37,13],["Status:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Status:desc",[28,[37,13],["Status:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.status.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,22],null,[["@label"],[[28,[37,2],["common.consul.service-name"],null]]],[["default"],[[[[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Name:asc",[28,[37,13],["Name:asc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.asc"],null]]],[]]]]],[1,"\\n "],[8,[30,23],null,[["@value","@selected"],["Name:desc",[28,[37,13],["Name:desc",[30,19,["value"]]],null]]],[["default"],[[[[1,[28,[35,2],["common.sort.alpha.desc"],null]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[22,23]]],[1," "]],[]]]]],[1,"\\n "]],[20]]]]],[1,"\\n "]],[18]]]]],[1,"\\n"]],["&attrs","@filter","search","key","value","search","@onsearch","@search","components","Optgroup","Option","prop","search","components","Optgroup","Option","item","search","@sort","components","selectable","Optgroup","Option"],false,["search-bar","let","t","concat","array","action","block-slot","each","-track-array","includes","lowercase","from-entries","get","eq"]]',moduleName:"consul-ui/components/consul/upstream/search-bar/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/copyable-code/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"KbYc4t+4",block:'[[[1,"\\n"],[11,0],[16,0,[28,[37,0],["copyable-code",[28,[37,1],["obfuscated",[30,1]],null]],null]],[17,2],[12],[1,"\\n"],[41,[30,1],[[[1," "],[8,[39,3],null,null,[["default"],[[[[1,"\\n "],[8,[30,3,["Action"]],[[16,"aria-label",[52,[33,4,["expanded"]],"Hide","Show"]],[4,[38,5],["click",[30,3,["toggle"]]],null]],null,[["default"],[[[[1,"\\n\\n "]],[]]]]],[1,"\\n "],[8,[30,3,["Details"]],null,null,[["default"],[[[[1,"\\n "],[10,"pre"],[12],[10,"code"],[15,1,[30,4,["id"]]],[12],[1,[30,5]],[13],[13],[1,"\\n "]],[4]]]]],[1,"\\n "],[8,[30,3,["Details"]],null,[["@auto"],[false]],[["default"],[[[[1,"\\n"],[41,[28,[37,6],[[30,6,["expanded"]]],null],[[[1," "],[10,"hr"],[12],[13],[1,"\\n"]],[]],null],[1," "]],[6]]]]],[1,"\\n "]],[3]]]]],[1,"\\n\\n "],[8,[39,7],null,[["@value","@name"],[[30,5],[30,7]]],null],[1,"\\n\\n"]],[]],[[[1," "],[10,"pre"],[12],[10,"code"],[12],[1,[30,5]],[13],[13],[1,"\\n "],[8,[39,7],null,[["@value","@name"],[[30,5],[30,7]]],null],[1,"\\n"]],[]]],[1,"\\n"],[13]],["@obfuscated","&attrs","disclosure","details","@value","details","@name"],false,["class-map","array","if","disclosure","details","on","not","consul-copy-button"]]',moduleName:"consul-ui/components/copyable-code/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/data-collection/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/object","@ember/object/computed","@glimmer/tracking"],(function(e,t,n,l,r,i,o,a){var u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j +function _(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function S(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const k=(0,n.createTemplateFactory)({id:"2sUjfsVP",block:'[[[1,"\\n"],[1,[28,[35,0],[[28,[37,1],[[30,0],[28,[37,2],[[28,[37,3],[[30,0],"term"],null],""],null],[30,1]],null]],null]],[1,"\\n"],[18,2,[[28,[37,5],null,[["search","items","Collection","Empty"],[[28,[37,1],[[30,0],[30,0,["search"]]],null],[30,0,["items"]],[52,[28,[37,7],[[30,0,["items","length"]],0],null],[50,"anonymous",0,null,null],""],[52,[28,[37,9],[[30,0,["items","length"]],0],null],[50,"anonymous",0,null,null],""]]]]]],[1,"\\n"]],["@search","&default"],false,["did-update","action","fn","set","yield","hash","if","gt","component","eq"]]',moduleName:"consul-ui/components/data-collection/index.hbs",isStrictMode:!1}) +let N=(u=(0,r.inject)("filter"),s=(0,r.inject)("sort"),c=(0,r.inject)("search"),d=(0,o.alias)("searchService.searchables"),p=(0,i.computed)("term","args.search"),f=(0,i.computed)("type","searchMethod","filtered","args.filters"),m=(0,i.computed)("type","args.sort"),h=(0,i.computed)("comparator","searched"),b=(0,i.computed)("searchTerm","searchable","filtered"),y=(0,i.computed)("type","content","args.filters"),v=(0,i.computed)("args.{items.[],items.content.[]}"),g=class extends l.default{constructor(){super(...arguments),_(this,"filter",O,this),_(this,"sort",P,this),_(this,"searchService",w,this),_(this,"term",x,this),_(this,"searchableMap",j,this)}get type(){return this.args.type}get searchMethod(){return this.args.searchable||"exact"}get searchProperties(){return this.args.filters.searchproperties}get searchTerm(){return this.term||this.args.search||""}get searchable(){const e=(0,i.get)(this,"args.filters.searchproperty.value")||(0,i.get)(this,"args.filters.searchproperty") +return new("string"==typeof this.searchMethod?this.searchableMap[this.searchMethod]:this.args.searchable)(this.filtered,{finders:Object.fromEntries(Object.entries(this.searchService.predicate(this.type)).filter((t=>{let[n,l]=t +return void 0===e||e.includes(n)})))})}get comparator(){return void 0===this.args.sort?[]:this.sort.comparator(this.type)(this.args.sort)}get items(){let e="comparator" +return"function"==typeof this.comparator&&(e=this.comparator),(0,i.defineProperty)(this,"sorted",(0,o.sort)("searched",e)),this.sorted}get searched(){return""===this.searchTerm?this.filtered:this.searchable.search(this.searchTerm)}get filtered(){if(void 0===this.args.filters)return this.content.slice() +const e=this.filter.predicate(this.type) +if(void 0===e)return this.content.slice() +const t=Object.entries(this.args.filters).filter((e=>{let[t,n]=e +return Boolean(n)})).map((e=>{let[t,n]=e +return[t,"string"!=typeof n?n.value:n]})) +return this.content.filter(e(Object.fromEntries(t)))}get content(){const e=this.args.items||[] +return"function"==typeof e.dispatchEvent?e.content:e}search(e){return this.term=e,this.items}},O=S(g.prototype,"filter",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=S(g.prototype,"sort",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=S(g.prototype,"searchService",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=S(g.prototype,"term",[a.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return""}}),j=S(g.prototype,"searchableMap",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S(g.prototype,"searchTerm",[p],Object.getOwnPropertyDescriptor(g.prototype,"searchTerm"),g.prototype),S(g.prototype,"searchable",[f],Object.getOwnPropertyDescriptor(g.prototype,"searchable"),g.prototype),S(g.prototype,"comparator",[m],Object.getOwnPropertyDescriptor(g.prototype,"comparator"),g.prototype),S(g.prototype,"items",[h],Object.getOwnPropertyDescriptor(g.prototype,"items"),g.prototype),S(g.prototype,"searched",[b],Object.getOwnPropertyDescriptor(g.prototype,"searched"),g.prototype),S(g.prototype,"filtered",[y],Object.getOwnPropertyDescriptor(g.prototype,"filtered"),g.prototype),S(g.prototype,"content",[v],Object.getOwnPropertyDescriptor(g.prototype,"content"),g.prototype),S(g.prototype,"search",[i.action],Object.getOwnPropertyDescriptor(g.prototype,"search"),g.prototype),g) +e.default=N,(0,t.setComponentTemplate)(k,N)})),define("consul-ui/components/data-form/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object","block-slots","validated-changeset"],(function(e,t,n,l,r,i,o){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const a=(0,n.createTemplateFactory)({id:"jFu0ODbk",block:'[[[1,"\\n"],[8,[39,0],null,[["@items","@src","@onchange","@once"],[[99,1,["@items"]],[28,[37,2],["/${partition}/${nspace}/${dc}/${type}/${src}",[28,[37,3],null,[["partition","nspace","dc","type","src"],[[33,4],[33,5],[33,6],[33,7],[33,8]]]]],null],[28,[37,9],[[30,0],"setData"],null],true]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n\\n "],[8,[39,11],null,[["@sink","@type","@label","@ondelete","@onchange"],[[28,[37,2],["/${partition}/${nspace}/${dc}/${type}",[28,[37,3],null,[["partition","nspace","dc","type"],[[33,4],[33,5],[28,[37,12],[[33,13,["Datacenter"]],[33,6]],null],[33,7]]]]],null],[99,7,["@type"]],[99,14,["@label"]],[28,[37,9],[[30,0],[33,15]],null],[28,[37,9],[[30,0],[33,16]],null]]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,3],null,[["data","change","isCreate","error","disabled","submit","delete"],[[33,13],[28,[37,9],[[30,0],"change"],null],[33,18],[30,1,["error"]],[30,1,["inflight"]],[28,[37,9],[[30,0],[30,1,["persist"]],[33,13]],null],[28,[37,9],[[30,0],[30,1,["delete"]],[33,13]],null]]]]],[[[1,"\\n "],[18,3,[[30,2]]],[1,"\\n"],[41,[33,21],[[[1," "],[8,[39,10],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,22],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[18,3,[[30,2]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,10],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,22],null,[["@name"],["form"]],[["default"],[[[[1,"\\n "],[18,3,[[30,2]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n"]],[2]]],[1,"\\n "]],[1]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n"]],[]]]]]],["writer","api","&default"],false,["data-loader","item","uri","hash","partition","nspace","dc","type","src","action","block-slot","data-writer","or","data","label","ondelete","onsubmit","let","create","yield","if","hasError","yield-slot"]]',moduleName:"consul-ui/components/data-form/index.hbs",isStrictMode:!1}) +var u=(0,t.setComponentTemplate)(a,t.default.extend(i.default,{tagName:"",dom:(0,l.inject)("dom"),builder:(0,l.inject)("form"),create:!1,ondelete:function(){return this.onsubmit(...arguments)},oncancel:function(){return this.onsubmit(...arguments)},onsubmit:function(){},onchange:function(e,t){return t.handleEvent(e)},didReceiveAttrs:function(){this._super(...arguments) +try{this.form=this.builder.form(this.type)}catch(e){}},willRender:function(){this._super(...arguments),(0,r.set)(this,"hasError",this._isRegistered("error"))},actions:{setData:function(e){let t=e +return(0,o.isChangeset)(e)||void 0===this.form||(t=this.form.setData(e).getData()),(0,r.get)(e,"isNew")&&((0,r.set)(this,"create",!0),t=Object.entries(this.autofill||{}).reduce((function(e,t){let[n,l]=t +return(0,r.set)(e,n,l),e}),t)),(0,r.set)(this,"data",t),this.data},change:function(e,t,n){this.onchange(this.dom.normalizeEvent(e,t),this.form,this.form.getData())}}})) +e.default=u})),define("consul-ui/components/data-loader/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={id:"data-loader",initial:"load",on:{OPEN:{target:"load"},ERROR:{target:"disconnected"},LOAD:[{target:"idle",cond:"loaded"},{target:"loading"}]},states:{load:{},loading:{on:{SUCCESS:{target:"idle"},ERROR:{target:"error"}}},idle:{},error:{on:{RETRY:{target:"load"}}},disconnected:{on:{RETRY:{target:"load"}}}}}})),define("consul-ui/components/data-loader/index",["exports","@ember/component","@ember/template-factory","@ember/object","block-slots","consul-ui/components/data-loader/chart.xstate"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"FfdegZAa",block:'[[[1,"\\n"],[18,9,null],[1,"\\n"],[8,[39,1],null,[["@src"],[[99,2,["@src"]]]],[["default"],[[[[1,"\\n "],[8,[39,3],null,[["@target","@name","@value"],[[30,0],"dispatch",[30,4]]],null],[1,"\\n "],[8,[30,2],null,[["@name","@cond"],["loaded",[28,[37,4],[[30,0],"isLoaded"],null]]],null],[1,"\\n\\n\\n"],[44,[[28,[37,6],null,[["data","error","invalidate","dispatchError"],[[33,7],[33,8],[30,0,["invalidate"]],[28,[37,9],[[28,[37,4],[[30,0],[28,[37,10],[[33,8]],null]],[["value"],["error.errors.firstObject"]]],[28,[37,4],[[30,0],[30,4],"ERROR"],null]],null]]]]],[[[1,"\\n"],[6,[39,11],null,[["name"],["data"]],[["default","else"],[[[[1," "],[18,9,[[30,6]]],[1,"\\n"]],[]],[[[41,[28,[37,13],[[33,14]],null],[[[1," "],[8,[30,1],null,[["@notMatches"],[[28,[37,15],["error","disconnected"],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,16],[[33,17],[28,[37,18],[[28,[37,13],[[33,19]],null],[28,[37,20],[[30,5],"loading"],null]],null]],null],[[[1," "],[8,[39,21],null,[["@open","@src","@onchange","@onerror"],[[99,22,["@open"]],[99,17,["@src"]],[28,[37,9],[[28,[37,4],[[30,0],"change"],[["value"],["data"]]],[28,[37,4],[[30,0],[30,4],"SUCCESS"],null]],null],[30,6,["dispatchError"]]]],[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,0],"invalidate",[30,7,["invalidate"]]],null]],null]],[1,"\\n "]],[7]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n"]],[]],null]],[]]]]],[1,"\\n "],[8,[30,1],null,[["@matches"],["loading"]],[["default"],[[[[1,"\\n"],[6,[39,11],null,[["name"],["loading"]],[["default","else"],[[[[1," "],[18,9,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,25],null,null,null],[1,"\\n"]],[]]]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["error"]],[["default"],[[[[1,"\\n"],[6,[39,11],null,[["name"],["error"]],[["default","else"],[[[[1," "],[18,9,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,26],null,[["@error"],[[99,8,["@error"]]]],null],[1,"\\n"]],[]]]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],[[28,[37,15],["idle","disconnected"],null]]],[["default"],[[[[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,13],[[28,[37,27],[[33,8,["status"]],"401"],null]],null],[[[6,[39,11],null,[["name","params"],["disconnected",[28,[37,28],[[28,[37,4],[[30,0],[30,4],"RESET"],null]],null]]],[["default","else"],[[[[1," "],[18,9,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,29],[[4,[38,30],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,8,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,8,["Description"]],null,null,[["default"],[[[[1,"An error was returned whilst loading this data, refresh to try again."]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n"]],[]]]]]],[]],null],[1," "]],[]]]]],[1,"\\n"],[41,[28,[37,27],[[33,8,["status"]],"403"],null],[[[6,[39,11],null,[["name"],["error"]],[["default","else"],[[[[1," "],[18,9,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,26],null,[["@error"],[[99,8,["@error"]]]],null],[1,"\\n"]],[]]]]]],[]],[[[1," "],[8,[39,11],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n "],[18,9,[[30,6]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1,"\\n "]],[]]]]],[1,"\\n\\n"]],[6]]],[1," "],[1,[28,[35,31],[[28,[37,32],[[30,4],"LOAD"],null]],[["src"],[[33,17]]]]],[1,"\\n"]],[1,2,3,4,5]]]]]],["State","Guard","Action","dispatch","state","api","source","T","&default"],false,["yield","state-chart","chart","ref","action","let","hash","data","error","queue","mut","yield-slot","if","not","items","array","and","src","or","once","state-matches","data-source","open","did-insert","set","consul/loader","error-state","eq","block-params","hds/toast","notification","did-update","fn"]]',moduleName:"consul-ui/components/data-loader/index.hbs",isStrictMode:!1}) +var a=(0,t.setComponentTemplate)(o,t.default.extend(r.default,{tagName:"",onchange:e=>e,init:function(){this._super(...arguments),this.chart=i.default},didReceiveAttrs:function(){this._super(...arguments),void 0!==this.items&&this.send("change",this.items)},didInsertElement:function(){this._super(...arguments),this.dispatch("LOAD")},actions:{isLoaded:function(){return void 0!==this.items||void 0===this.src},change:function(e){(0,l.set)(this,"data",this.onchange(e))}}})) +e.default=a})) +define("consul-ui/components/data-sink/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object","consul-ui/utils/dom/event-source"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"hxJqQ0VJ",block:'[[[1,"\\n"],[18,1,[[28,[37,1],null,[["open","state"],[[28,[37,2],[[30,0],"open"],null],[33,3]]]]]],[1,"\\n"]],["&default"],false,["yield","hash","action","state"]]',moduleName:"consul-ui/components/data-sink/index.hbs",isStrictMode:!1}) +var a=(0,t.setComponentTemplate)(o,t.default.extend({tagName:"",service:(0,l.inject)("data-sink/service"),dom:(0,l.inject)("dom"),logger:(0,l.inject)("logger"),onchange:function(e){},onerror:function(e){},state:(0,r.computed)("instance","instance.{dirtyType,isSaving}",(function(){let e +const t=(0,r.get)(this,"instance.isSaving"),n=(0,r.get)(this,"instance.dirtyType") +if(void 0===t&&void 0===n)e="idle" +else{switch(n){case"created":e=t?"creating":"create" +break +case"updated":e=t?"updating":"update" +break +case"deleted":case void 0:e=t?"removing":"remove"}e=`active.${e}`}return{matches:t=>-1!==e.indexOf(t)}})),init:function(){this._super(...arguments),this._listeners=this.dom.listeners()},willDestroyElement:function(){this._super(...arguments),this._listeners.remove()},source:function(e){const t=(0,i.once)(e),n=e=>{(0,r.set)(this,"instance",void 0) +try{this.onerror(e),this.logger.execute(e)}catch(e){this.logger.execute(e)}} +return this._listeners.add(t,{message:e=>{try{(0,r.set)(this,"instance",void 0),this.onchange(e)}catch(t){n(t)}},error:e=>n(e)}),t},didInsertElement:function(){this._super(...arguments),void 0===this.data&&void 0===this.item||this.actions.open.apply(this,[this.data,this.item])},persist:function(e,t){void 0!==e?(0,r.set)(this,"instance",this.service.prepare(this.sink,e,t)):(0,r.set)(this,"instance",t),this.source((()=>this.service.persist(this.sink,this.instance)))},remove:function(e){(0,r.set)(this,"instance",e),this.source((()=>this.service.remove(this.sink,e)))},actions:{open:function(e,t){if(t instanceof Event&&(t=void 0),void 0===e&&void 0===t)throw new Error("You must specify data to save, or null to remove") +null===e||""===e?this.remove(t):this.persist(e,t)}}})) +e.default=a})),define("consul-ui/components/data-source/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@glimmer/tracking","@ember/object","@ember/runloop","@ember/debug"],(function(e,t,n,l,r,i,o,a,u){var s,c,d,p,f,m,h,b,y,v +function g(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function O(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const P=(0,n.createTemplateFactory)({id:"W/NppIUM",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,0,["disabled"]]],null],[[[41,[28,[37,2],[[30,0,["loading"]],"lazy"],null],[[[1," "],[11,"data"],[24,"aria-hidden","true"],[24,5,"width: 0;height: 0;font-size: 0;padding: 0;margin: 0;"],[4,[38,3],[[30,0,["connect"]]],null],[12],[13],[1,"\\n"]],[]],[[[1," "],[1,[28,[35,3],[[30,0,["connect"]]],null]],[1,"\\n"]],[]]],[1," "],[1,[28,[35,4],[[30,0,["attributeChanged"]],"src",[30,1]],null]],[1,"\\n "],[1,[28,[35,4],[[30,0,["attributeChanged"]],"loading",[30,2]],null]],[1,"\\n "],[1,[28,[35,5],[[30,0,["disconnect"]]],null]],[1,"\\n"]],[]],null],[1,[28,[35,4],[[30,0,["attributeChanged"]],"disabled",[30,3]],null]],[1,"\\n"],[18,4,[[28,[37,7],null,[["data","error","invalidate","Source"],[[30,0,["data"]],[30,0,["error"]],[30,0,["invalidate"]],[52,[30,0,["data"]],[50,"data-source",0,null,[["disabled"],[[28,[37,1],[[28,[37,2],[[30,0,["error"]],[27]],null]],null]]]],""]]]]]],[1,"\\n"]],["@src","@loading","@disabled","&default"],false,["if","not","eq","did-insert","did-update","will-destroy","yield","hash","component"]]',moduleName:"consul-ui/components/data-source/index.hbs",isStrictMode:!1}),w=function(e,t,n){let l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null +return"function"==typeof e?e():null} +const r=e[t] +return r!==n&&l(r,n),e[t]=n},x=()=>{},j=e=>"function"==typeof e?e:x,_=["eager","lazy"] +let S=(s=(0,r.inject)("data-source/service"),c=(0,r.inject)("dom"),d=(0,r.inject)("logger"),p=class extends l.default{constructor(e,t){super(...arguments),g(this,"dataSource",f,this),g(this,"dom",m,this),g(this,"logger",h,this),g(this,"isIntersecting",b,this),g(this,"data",y,this),g(this,"error",v,this),this._listeners=this.dom.listeners(),this._lazyListeners=this.dom.listeners()}get loading(){return _.includes(this.args.loading)?this.args.loading:_[0]}get disabled(){return void 0!==this.args.disabled&&this.args.disabled}onchange(e){this.error=void 0,this.data=e.data,j(this.args.onchange)(e)}onerror(e){this.error=e.error||e,j(this.args.onerror)(e)}connect(e){Array.isArray(e)?(this._lazyListeners.remove(),this.open()):this._lazyListeners.add(this.dom.isInViewport(e,(e=>{this.isIntersecting=e,this.isIntersecting?this.open():this.close()})))}disconnect(){void 0!==this.data&&void 0===this.data.length&&"function"==typeof this.data.rollbackAttributes&&this.data.rollbackAttributes(),this.close(),this._listeners.remove(),this._lazyListeners.remove()}attributeChanged(e){let[t,n]=e +if("src"===t)("eager"===this.loading||this.isIntersecting)&&this.open()}open(){const e=this.args.src,t=w(this,"source",this.dataSource.open(e,this,this.open),((e,t)=>{this.dataSource.close(e,this)})),n=e=>{try{const t=(0,o.get)(e,"error.errors.firstObject")||{} +"429"!==(0,o.get)(t,"status")&&this.onerror(e),this.logger.execute(e)}catch(e){this.logger.execute(e)}},l=this._listeners.add(this.source,{message:e=>{try{this.onchange(e)}catch(t){n(t)}},error:e=>{n(e)}}) +if(w(this,"_remove",l),"function"==typeof t.getCurrentEvent){const e=t.getCurrentEvent() +if(e){let t +void 0!==e.error?(t="onerror",this.error=e.error):(this.error=void 0,this.data=e.data,t="onchange"),(0,a.schedule)("afterRender",(()=>{try{this[t](e)}catch(l){n(l)}}))}}}async invalidate(){this.source.readyState=2,this.disconnect(),(0,a.schedule)("afterRender",(()=>{(0,u.runInDebug)((e=>console.debug("Invalidation is only supported for non-lazy data sources. If you want to use this you should fixup support for lazy data sources"))),this.connect([])}))}close(){void 0!==this.source&&(this.dataSource.close(this.source,this),w(this,"_remove",void 0),this.source=void 0)}},f=O(p.prototype,"dataSource",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=O(p.prototype,"dom",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=O(p.prototype,"logger",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=O(p.prototype,"isIntersecting",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return!1}}),y=O(p.prototype,"data",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=O(p.prototype,"error",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O(p.prototype,"connect",[o.action],Object.getOwnPropertyDescriptor(p.prototype,"connect"),p.prototype),O(p.prototype,"disconnect",[o.action],Object.getOwnPropertyDescriptor(p.prototype,"disconnect"),p.prototype),O(p.prototype,"attributeChanged",[o.action],Object.getOwnPropertyDescriptor(p.prototype,"attributeChanged"),p.prototype),O(p.prototype,"open",[o.action],Object.getOwnPropertyDescriptor(p.prototype,"open"),p.prototype),O(p.prototype,"invalidate",[o.action],Object.getOwnPropertyDescriptor(p.prototype,"invalidate"),p.prototype),O(p.prototype,"close",[o.action],Object.getOwnPropertyDescriptor(p.prototype,"close"),p.prototype),p) +e.default=S,(0,t.setComponentTemplate)(P,S)})),define("consul-ui/components/data-writer/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={id:"data-writer",initial:"idle",states:{idle:{on:{PERSIST:{target:"persisting"},REMOVE:{target:"removing"}}},removing:{on:{SUCCESS:{target:"removed"},ERROR:{target:"error"}}},persisting:{on:{SUCCESS:{target:"persisted"},ERROR:{target:"error"}}},removed:{on:{RESET:{target:"idle"}}},persisted:{on:{RESET:{target:"idle"}}},error:{on:{RESET:{target:"idle"}}}}}})),define("consul-ui/components/data-writer/index",["exports","@ember/component","@ember/template-factory","@ember/object","block-slots","consul-ui/components/data-writer/chart.xstate"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"2KEWIUOo",block:'[[[1,"\\n"],[8,[39,0],null,[["@src"],[[99,1,["@src"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@target","@name","@value"],[[30,0],"dispatch",[30,4]]],null],[1,"\\n\\n"],[44,[[28,[37,4],null,[["data","error","persist","delete","inflight","disabled"],[[33,5],[33,6],[28,[37,7],[[30,0],"persist"],null],[28,[37,8],[[28,[37,7],[[30,0],[28,[37,9],[[33,5]],null]],null],[28,[37,7],[[30,0],[30,4],"REMOVE"],null]],null],[28,[37,10],[[30,5],[28,[37,11],["persisting","removing"],null]],null],[28,[37,10],[[30,5],[28,[37,11],["persisting","removing"],null]],null]]]]],[[[1,"\\n "],[18,13,[[30,6]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["removing"]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@sink","@item","@data","@onchange","@onerror"],[[99,14,["@sink"]],[99,5,["@item"]],null,[28,[37,7],[[30,0],[30,4],"SUCCESS"],null],[28,[37,7],[[30,0],"error"],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["persisting"]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@sink","@item","@onchange","@onerror"],[[99,14,["@sink"]],[99,5,["@item"]],[28,[37,7],[[30,0],[30,4],"SUCCESS"],null],[28,[37,7],[[30,0],"error"],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["removed"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,8],[[28,[37,7],[[30,0],[30,4],"RESET"],null],[28,[37,7],[[30,0],[33,15]],null]],null]],[[[6,[39,16],null,[["name","params"],["removed",[28,[37,17],[[30,7]],null]]],[["default","else"],[[[[1," "],[18,13,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,18],[[4,[38,19],null,[["after"],[[28,[37,7],[[30,0],[30,7]],null]]]]],[["@color"],["success"]],[["default"],[[[[1,"\\n "],[8,[30,8,["Title"]],null,null,[["default"],[[[[1,"Success!"]],[]]]]],[1,"\\n "],[8,[30,8,["Description"]],null,null,[["default"],[[[[1,"Your "],[1,[28,[35,20],[[33,21],[33,22]],null]],[1," has been deleted."]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n"]],[]]]]]],[7]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["persisted"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,7],[[30,0],[33,23]],null]],[[[6,[39,16],null,[["name","params"],["persisted",[28,[37,17],[[30,9]],null]]],[["default","else"],[[[[1," "],[18,13,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,18],[[4,[38,19],null,[["after"],[[28,[37,7],[[30,0],[30,9]],null]]]]],[["@color"],["success"]],[["default"],[[[[1,"\\n "],[8,[30,10,["Title"]],null,null,[["default"],[[[[1,"Success!"]],[]]]]],[1,"\\n "],[8,[30,10,["Description"]],null,null,[["default"],[[[[1,"Your "],[1,[28,[35,20],[[33,21],[33,22]],null]],[1," has been saved."]],[]]]]],[1,"\\n "]],[10]]]]],[1,"\\n"]],[]]]]]],[9]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["error"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,7],[[30,0],[30,4],"RESET"],null]],[[[6,[39,16],null,[["name","params"],["error",[28,[37,17],[[30,11],[30,6,["error"]]],null]]],[["default","else"],[[[[1," "],[18,13,[[30,6]]],[1,"\\n"]],[]],[[[1," "],[8,[39,18],[[4,[38,19],null,[["after"],[[28,[37,7],[[30,0],[30,11]],null]]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,12,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,12,["Description"]],null,null,[["default"],[[[[1,"There was an error saving your "],[1,[28,[35,20],[[33,21],[33,22]],null]],[1,".\\n"],[41,[28,[37,25],[[30,6,["error","status"]],[30,6,["error","detail"]]],null],[[[1," "],[10,"br"],[12],[13],[1,[30,6,["error","status"]]],[1,": "],[1,[30,6,["error","detail"]]],[1,"\\n"]],[]],[[[41,[30,6,["error","message"]],[[[1," "],[10,"br"],[12],[13],[1,[30,6,["error","message"]]],[1,"\\n "]],[]],null]],[]]],[1," "]],[]]]]],[1,"\\n "]],[12]]]]],[1,"\\n"]],[]]]]]],[11]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,16],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[18,13,[[30,6]]],[1,"\\n "]],[]]]]],[1,"\\n\\n"]],[6]]]],[1,2,3,4,5]]]]]],["State","Guard","Action","dispatch","state","api","after","T","after","T","after","T","&default"],false,["state-chart","chart","ref","let","hash","data","error","action","queue","mut","state-matches","array","yield","data-sink","sink","ondelete","yield-slot","block-params","hds/toast","notification","or","label","type","onchange","if","and"]]',moduleName:"consul-ui/components/data-writer/index.hbs",isStrictMode:!1}) +var a=(0,t.setComponentTemplate)(o,t.default.extend(r.default,{tagName:"",ondelete:function(){return this.onchange(...arguments)},onchange:function(){},init:function(){this._super(...arguments),this.chart=i.default},actions:{persist:function(e,t){t&&"function"==typeof t.preventDefault&&t.preventDefault(),(0,l.set)(this,"data",e),this.dispatch("PERSIST")},error:function(e,t){t&&"function"==typeof t.preventDefault&&t.preventDefault(),(0,l.set)(this,"error",void 0!==e.error.errors?e.error.errors.firstObject:e.error),this.dispatch("ERROR")}}})) +e.default=a})),define("consul-ui/components/debug/navigation/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"gn00CoAo",block:"[[],[],false,[]]",moduleName:"consul-ui/components/debug/navigation/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/delete-confirmation/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"wrK95/Xv",block:'[[[1,"\\n"],[10,2],[12],[1,"\\n "],[1,[34,0]],[1,"\\n"],[13],[1,"\\n"],[8,[39,1],null,null,[["default"],[[[[1,"\\n "],[8,[39,2],[[16,"onclick",[28,[37,3],[[30,0],[33,4]],null]]],[["@text","@color"],["Confirm Delete","critical"]],null],[1,"\\n "],[8,[39,2],[[16,"onclick",[28,[37,3],[[30,0],[33,5]],null]]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"]],[]]]]]],[],false,["message","hds/button-set","hds/button","action","execute","cancel"]]',moduleName:"consul-ui/components/delete-confirmation/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:"",execute:function(){},cancel:function(){}})) +e.default=r})),define("consul-ui/components/disclosure-menu/action/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"5sPiH/Fc",block:'[[[1,"\\n"],[8,[30,1,["Action"]],[[24,"aria-haspopup","menu"],[17,2]],null,[["default"],[[[[1,"\\n "],[18,3,null],[1,"\\n"]],[]]]]],[1,"\\n"]],["@disclosure","&attrs","&default"],false,["yield"]]',moduleName:"consul-ui/components/disclosure-menu/action/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/disclosure-menu/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"xJDSwfnA",block:'[[[1,"\\n"],[11,0],[16,0,[28,[37,0],["disclosure-menu"],null]],[17,1],[12],[1,"\\n "],[8,[39,1],null,[["@expanded"],[[30,2]]],[["default"],[[[[1,"\\n "],[18,6,[[28,[37,3],null,[["Action","Menu","disclosure","toggle","close","open","expanded"],[[50,"disclosure-menu/action",0,null,[["disclosure"],[[30,3]]]],[50,"disclosure-menu/menu",0,null,[["disclosure","items","rowHeight"],[[30,3],[30,4],[30,5]]]],[30,3],[30,3,["toggle"]],[30,3,["close"]],[30,3,["open"]],[30,3,["expanded"]]]]]]],[1,"\\n "]],[3]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@expanded","disclosure","@items","@rowHeight","&default"],false,["class-map","disclosure","yield","hash","component"]]',moduleName:"consul-ui/components/disclosure-menu/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/disclosure-menu/menu/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"Q113CWhh",block:'[[[1,"\\n"],[8,[30,1,["Details"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,0],null,[["@items"],[[28,[37,1],[[30,3],[28,[37,2],null,null]],null]]],[["default"],[[[[1,"\\n "],[11,0],[16,0,[28,[37,3],[[28,[37,2],["paged-collection-scroll",[28,[37,4],[[30,4,["type"]],[28,[37,2],["virtual-scroll","native-scroll"],null]],null]],null]],null]],[17,5],[4,[38,5],["click",[30,1,["close"]]],null],[4,[38,6],[[30,4,["viewport"]]],null],[4,[38,7],[[30,4,["resize"]]],null],[4,[38,8],["--paged-row-height"],[["returns"],[[30,4,["rowHeight"]]]]],[4,[38,8],["max-height"],[["returns"],[[30,4,["maxHeight"]]]]],[12],[1,"\\n "],[18,6,[[28,[37,10],null,[["Menu"],[[50,"menu",0,null,[["disclosure","pager"],[[30,1],[30,4]]]]]]]]],[1,"\\n "],[13],[1,"\\n "]],[4]]]]],[1,"\\n"]],[2]]]]]],["@disclosure","details","@items","pager","&attrs","&default"],false,["paged-collection","or","array","class-map","includes","on-outside","did-insert","on-resize","css-prop","yield","hash","component"]]',moduleName:"consul-ui/components/disclosure-menu/menu/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/disclosure/action/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"L9cY7BZT",block:'[[[1,"\\n"],[8,[39,0],[[16,"aria-expanded",[52,[30,1,["expanded"]],"true","false"]],[16,"aria-controls",[30,1,["controls"]]],[17,2]],null,[["default"],[[[[1,"\\n "],[18,3,null],[1,"\\n"]],[]]]]],[1,"\\n"]],["@disclosure","&attrs","&default"],false,["action","if","yield"]]',moduleName:"consul-ui/components/disclosure/action/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/disclosure/details/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"2QtyQRCK",block:'[[[1,"\\n"],[44,[[28,[37,1],null,null]],[[[41,[28,[37,3],[[28,[37,4],[[28,[37,5],[[30,2],[27]],null],[30,3,["expanded"]]],null],[28,[37,4],[[28,[37,6],[[30,2],[27]],null],[28,[37,5],[[30,2],false],null]],null]],null],[[[18,4,[[28,[37,8],null,[["id","expanded"],[[30,1],[30,3,["expanded"]]]]]]],[1,"\\n"]],[]],null],[1,[28,[35,9],[[28,[37,10],[[30,3,["add"]],[30,1]],null]],null]],[1,"\\n"],[1,[28,[35,11],[[28,[37,10],[[30,3,["remove"]],[30,1]],null]],null]],[1,"\\n"]],[1]]]],["id","@auto","@disclosure","&default"],false,["let","unique-id","if","or","and","eq","not-eq","yield","hash","did-insert","fn","will-destroy"]]',moduleName:"consul-ui/components/disclosure/details/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/disclosure/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object","@ember/runloop"],(function(e,t,n,l,r,i,o){var a,u +function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const c=(0,n.createTemplateFactory)({id:"ATdkf5j+",block:'[[[1,"\\n"],[8,[39,0],null,[["@src","@initial"],[[28,[37,0],["boolean"],null],[52,[30,1],"true","false"]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],null,[["toggle","close","open","expanded","event","button","controls"],[[28,[37,4],[[30,5],"TOGGLE"],null],[28,[37,4],[[30,5],"FALSE"],null],[28,[37,4],[[30,5],"TRUE"],null],[28,[37,5],[[30,6],"true"],null],[30,6,["context"]],[28,[37,6],null,null],[30,0,["ids"]]]]]],[[[44,[[28,[37,7],[[30,7],[28,[37,3],null,[["Action","Details"],[[50,"disclosure/action",0,null,[["disclosure"],[[30,7]]]],[50,"disclosure/details",0,null,[["disclosure"],[[28,[37,3],null,[["add","remove","expanded"],[[30,0,["add"]],[30,0,["remove"]],[28,[37,5],[[30,6],"true"],null]]]]]]]]]]],null]],[[[1," "],[18,9,[[30,8]]],[1,"\\n"]],[8]]]],[7]]]],[2,3,4,5,6]]]]]],["@expanded","State","Guard","Action","dispatch","state","_api","api","&default"],false,["state-chart","if","let","hash","fn","state-matches","unique-id","assign","component","yield"]]',moduleName:"consul-ui/components/disclosure/index.hbs",isStrictMode:!1}) +let d=(a=class extends l.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="ids",l=this,(n=u)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}add(e){(0,o.schedule)("afterRender",(()=>{this.ids=`${this.ids}${this.ids.length>0?" ":""}${e}`}))}remove(e){this.ids=this.ids.split(" ").filter((t=>t!==e)).join(" ")}},u=s(a.prototype,"ids",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return""}}),s(a.prototype,"add",[i.action],Object.getOwnPropertyDescriptor(a.prototype,"add"),a.prototype),s(a.prototype,"remove",[i.action],Object.getOwnPropertyDescriptor(a.prototype,"remove"),a.prototype),a) +e.default=d,(0,t.setComponentTemplate)(c,d)})),define("consul-ui/components/ember-collection",["exports","ember-collection/components/ember-collection"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/ember-native-scrollable",["exports","ember-collection/components/ember-native-scrollable"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/empty-state/index",["exports","@ember/component","@ember/template-factory","@ember/object","block-slots"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i=(0,n.createTemplateFactory)({id:"Hzp776M1",block:'[[[1,"\\n"],[18,2,null],[1,"\\n"],[11,0],[24,0,"empty-state"],[17,1],[12],[1,"\\n"],[41,[33,2],[[[1," "],[10,"header"],[12],[1,"\\n"],[6,[39,3],null,[["name"],["header"]],[["default"],[[[[1," "],[18,2,null],[1,"\\n"]],[]]]]],[6,[39,3],null,[["name"],["subheader"]],[["default"],[[[[1," "],[18,2,null],[1,"\\n"]],[]]]]],[1," "],[13],[1,"\\n"]],[]],null],[6,[39,3],null,[["name"],["body"]],[["default"],[[[[1," "],[10,0],[12],[1,"\\n "],[18,2,null],[1,"\\n"],[41,[33,4],[[[1," "],[8,[39,5],[[4,[38,7],["click",[33,4]],null]],[["@color","@text"],["primary",[52,[33,6,["AccessorID"]],"Log in with a different token","Log in"]]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@src","@onchange"],[[28,[37,9],["settings://consul:token"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,6]],null]],[["value"],["data"]]]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n"]],[]]]]],[6,[39,3],null,[["name"],["actions"]],[["default"],[[[[1," "],[10,"ul"],[12],[1,"\\n "],[18,2,null],[1,"\\n "],[13],[1,"\\n"]],[]]]]],[13]],["&attrs","&default"],false,["yield","if","hasHeader","yield-slot","login","hds/button","token","on","data-source","uri","action","mut"]]',moduleName:"consul-ui/components/empty-state/index.hbs",isStrictMode:!1}) +var o=(0,t.setComponentTemplate)(i,t.default.extend(r.default,{tagName:"",willRender:function(){this._super(...arguments),(0,l.set)(this,"hasHeader",this._isRegistered("header")||this._isRegistered("subheader"))}})) +e.default=o})),define("consul-ui/components/error-state/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"Zz5ttQNZ",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1,["status"]],"403"],null],[[[1," "],[8,[39,2],[[16,0,[28,[37,3],["status-",[30,1,["status"]]],null]]],[["@login"],[[30,2]]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,5],[[30,1,["message"]],"Consul returned an error"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[30,1,["status"]],[[[1," "],[8,[39,4],null,[["@name"],["subheader"]],[["default"],[[[[1,"\\n "],[10,"h3"],[12],[1,"\\n Error "],[1,[30,1,["status"]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,4],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n"],[41,[30,1,["detail"]],[[[1," "],[1,[30,1,["detail"]]],[1,"\\n"]],[]],[[[1," You may have visited a URL that is loading an unknown resource, so you can try going back to the root or try re-submitting your ACL Token/SecretID by going back to ACLs.\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,6],null,[["@route","@text","@icon","@iconPosition","@size"],["index","Go back","chevron-left","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,6],null,[["@text","@href","@iconPosition","@icon","@size"],["Read the documentation",[29,[[28,[37,7],["CONSUL_DOCS_URL"],null]]],"trailing","docs-link","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,2],[[16,0,[28,[37,3],["status-",[30,1,["status"]]],null]]],[["@login"],[[30,2]]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n You are not authorized\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["subheader"]],[["default"],[[[[1,"\\n "],[10,"h3"],[12],[1,"\\n Error "],[1,[30,1,["status"]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n You must be granted permissions to view this data. Ask your administrator if you think you should have access.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,6],null,[["@text","@href","@icon","@iconPosition","@size"],["Read the documentation",[29,[[28,[37,7],["CONSUL_DOCS_URL"],null],"/acl/index.html"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,6],null,[["@text","@href","@icon","@iconPosition","@size"],["Follow the guide",[29,[[28,[37,7],["CONSUL_DOCS_LEARN_URL"],null],"/consul/security-networking/production-acls"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]],["@error","@login"],false,["if","not-eq","empty-state","concat","block-slot","or","hds/link/standalone","env"]]',moduleName:"consul-ui/components/error-state/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/event-source/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i=(0,n.createTemplateFactory)({id:"CYkx/ZA5",block:'[[[1,"\\n"],[18,1,[[28,[37,1],null,[["close"],[[28,[37,2],[[30,0],"close"],null]]]]]],[1,"\\n"]],["&default"],false,["yield","hash","action"]]',moduleName:"consul-ui/components/event-source/index.hbs",isStrictMode:!1}),o=function(e,t,n){let l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null +return"function"==typeof e?e():null} +const i=e[t] +return i!==n&&l(i,n),(0,r.set)(e,t,n)} +var a=(0,t.setComponentTemplate)(i,t.default.extend({tagName:"",dom:(0,l.inject)("dom"),logger:(0,l.inject)("logger"),data:(0,l.inject)("data-source/service"),closeOnDestroy:!0,onerror:function(e){this.logger.execute(e.error)},init:function(){this._super(...arguments),this._listeners=this.dom.listeners()},willDestroyElement:function(){this.closeOnDestroy&&this.actions.close.apply(this,[]),this._listeners.remove(),this._super(...arguments)},didReceiveAttrs:function(){this._super(...arguments),(0,r.get)(this,"src.configuration.uri")!==(0,r.get)(this,"source.configuration.uri")&&this.actions.open.apply(this,[])},actions:{open:function(){o(this,"source",this.data.open(this.src,this),((e,t)=>{void 0!==e&&this.data.close(e,this)})),o(this,"proxy",this.src,((e,t)=>{void 0!==e&&e.destroy()})) +const e=e=>{try{const t=(0,r.get)(e,"error.errors.firstObject") +"429"!==(0,r.get)(t||{},"status")&&this.onerror(e),this.logger.execute(e)}catch(e){this.logger.execute(e)}},t=this._listeners.add(this.source,{error:t=>{e(t)}}) +o(this,"_remove",t)},close:function(){void 0!==this.source&&(this.data.close(this.source,this),o(this,"_remove",void 0),(0,r.set)(this,"source",void 0)),void 0!==this.proxy&&this.proxy.destroy()}}})) +e.default=a})),define("consul-ui/components/flash-message",["exports","ember-cli-flash/components/flash-message"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/flight-icon",["exports","@hashicorp/ember-flight-icons/components/flight-icon"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/form-component/index",["exports","@ember/component","@ember/template-factory","block-slots","@ember/service","@ember/object/computed"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"Zu8CcSUV",block:'[[[1,"\\n"],[18,1,null]],["&default"],false,["yield"]]',moduleName:"consul-ui/components/form-component/index.hbs",isStrictMode:!1}),a=/([^[\]])+/g +var u=(0,t.setComponentTemplate)(o,t.default.extend(l.default,{tagName:"",onreset:function(){},onchange:function(){},onerror:function(){},onsuccess:function(){},data:(0,i.alias)("form.data"),item:(0,i.alias)("form.data"),dom:(0,r.inject)("dom"),container:(0,r.inject)("form"),actions:{change:function(e,t,n){let l=this.dom.normalizeEvent(e,t) +const r=[...l.target.name.matchAll(a)],i=r[r.length-1][0] +let o +o=-1===i.indexOf("[")?`${this.type}[${i}]`:i,this.form.handleEvent(l,o),this.onchange({target:this})}}})) +e.default=u})),define("consul-ui/components/form-group/element/checkbox/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"aTpxDLx0",block:'[[[1,"\\n"],[11,"input"],[24,4,"checkbox"],[16,3,[30,1]],[16,2,[30,2]],[17,3],[4,[38,0],[[28,[37,1],[[30,4]],null]],null],[4,[38,2],["change",[28,[37,1],[[30,5]],null]],null],[12],[13],[1,"\\n"]],["@name","@value","&attrs","@didinsert","@onchange"],false,["did-insert","optional","on"]]',moduleName:"consul-ui/components/form-group/element/checkbox/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/form-group/element/error/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"GMa+YgFr",block:'[[[1,"\\n"],[11,"strong"],[24,"role","alert"],[17,1],[12],[1,"\\n "],[18,2,null],[1,"\\n"],[13],[1,"\\n"]],["&attrs","&default"],false,["yield"]]',moduleName:"consul-ui/components/form-group/element/error/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/form-group/element/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object"],(function(e,t,n,l,r,i){var o,a,u +function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const d=(0,n.createTemplateFactory)({id:"LYBie/vO",block:'[[[1,"\\n"],[44,[[28,[37,1],null,[["Element","Text","Checkbox","Radio","Label","Error","state"],[[50,"form-group/element",0,null,[["group","name"],[[30,1],[30,2]]]],[50,"form-group/element/text",0,null,[["didinsert","name","oninput"],[[28,[37,3],[[30,0],[30,0,["connect"]]],null],[30,0,["name"]],[28,[37,3],[[30,0],[28,[37,4],[[30,0,["touched"]]],null],true],null]]]],[50,"form-group/element/checkbox",0,null,[["didinsert","name","onchange"],[[28,[37,3],[[30,0],[30,0,["connect"]]],null],[30,0,["name"]],[28,[37,3],[[30,0],[28,[37,4],[[30,0,["touched"]]],null],true],null]]]],[50,"form-group/element/radio",0,null,[["didinsert","name","onchange"],[[28,[37,3],[[30,0],[30,0,["connect"]]],null],[30,0,["name"]],[28,[37,3],[[30,0],[28,[37,4],[[30,0,["touched"]]],null],true],null]]]],[50,"form-group/element/label",0,null,null],[50,"form-group/element/error",0,null,null],[33,5]]]]],[[[41,[28,[37,7],[[30,0,["type"]],[28,[37,8],["radiogroup","checkbox-group","checkboxgroup"],null]],null],[[[1," "],[11,0],[16,"data-property",[30,0,["prop"]]],[16,0,[29,["type-",[30,0,["type"]],[52,[28,[37,9],[[33,5],"error"],null]," has-error"]]]],[17,4],[12],[1,"\\n "],[18,5,[[30,3]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[11,"label"],[16,"data-property",[30,0,["prop"]]],[16,0,[29,["type-",[30,0,["type"]],[52,[28,[37,9],[[33,5],"error"],null]," has-error"]]]],[17,4],[12],[1,"\\n "],[18,5,[[30,3]]],[1,"\\n "],[13],[1,"\\n"]],[]]]],[3]]]],["@group","@name","el","&attrs","&default"],false,["let","hash","component","action","mut","state","if","includes","array","state-matches","yield"]]',moduleName:"consul-ui/components/form-group/element/index.hbs",isStrictMode:!1}) +let p=(o=class extends l.default{constructor(){super(...arguments),s(this,"el",a,this),s(this,"touched",u,this)}get type(){return void 0!==this.el?this.el.dataset.type||this.el.getAttribute("type")||this.el.getAttribute("role"):this.args.type}get name(){return void 0!==this.args.group?`${this.args.group.name}[${this.args.name}]`:this.args.name}get prop(){return`${this.args.name.toLowerCase().split(".").join("-")}`}get state(){const e=this.touched&&this.args.error +return{matches:t=>"error"===t&&e}}connect(e){this.el=e}},a=c(o.prototype,"el",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(o.prototype,"touched",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return!1}}),c(o.prototype,"connect",[i.action],Object.getOwnPropertyDescriptor(o.prototype,"connect"),o.prototype),o) +e.default=p,(0,t.setComponentTemplate)(d,p)})),define("consul-ui/components/form-group/element/label/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"f3iRrlW/",block:'[[[1,"\\n"],[11,1],[24,0,"form-elements-label label"],[17,1],[12],[1,"\\n "],[18,2,null],[1,"\\n"],[13],[1,"\\n"]],["&attrs","&default"],false,["yield"]]',moduleName:"consul-ui/components/form-group/element/label/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/form-group/element/radio/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"/22Fhuo5",block:'[[[1,"\\n"],[11,"input"],[24,4,"radio"],[16,3,[30,1]],[16,2,[30,2]],[17,3],[4,[38,0],[[28,[37,1],[[30,4]],null]],null],[4,[38,2],["change",[28,[37,1],[[30,5]],null]],null],[12],[13],[1,"\\n"]],["@name","@value","&attrs","@didinsert","@onchange"],false,["did-insert","optional","on"]]',moduleName:"consul-ui/components/form-group/element/radio/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/form-group/element/text/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"VMeFItBq",block:'[[[1,"\\n"],[11,"input"],[24,4,"text"],[16,3,[30,1]],[16,2,[30,2]],[17,3],[4,[38,0],[[28,[37,1],[[30,4]],null]],null],[4,[38,2],["input",[28,[37,1],[[30,5]],null]],null],[12],[13],[1,"\\n"]],["@name","@value","&attrs","@didinsert","@oninput"],false,["did-insert","optional","on"]]',moduleName:"consul-ui/components/form-group/element/text/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/form-group/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"LaNs6VhD",block:'[[[1,"\\n"],[18,1,[[28,[37,1],null,[["Element"],[[50,"form-group/element",0,null,[["group"],[[30,0]]]]]]]]],[1,"\\n"]],["&default"],false,["yield","hash","component"]]',moduleName:"consul-ui/components/form-group/index.hbs",isStrictMode:!1}) +class i extends l.default{get name(){return this.args.name}}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/form-input/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"s7KSGcTe",block:'[[[1,"\\n"],[11,"label"],[16,0,[28,[37,0],["form-input",[52,[28,[37,2],[[30,1,["state","context","errors"]],[30,2]],null]," has-error"]],null]],[17,3],[12],[1,"\\n "],[10,1],[12],[1,"\\n "],[18,7,null],[1,"\\n "],[13],[1,"\\n "],[18,8,null],[1,"\\n"],[44,[[28,[37,5],[[30,4,["help"]],[30,5]],null]],[[[41,[30,6],[[[1," "],[10,"em"],[12],[1,"\\n "],[1,[30,6]],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[6]]],[1," "],[8,[39,6],null,[["@state","@matches"],[[30,1,["state"]],"error"]],[["default"],[[[[1,"\\n"],[1," "],[10,"strong"],[14,"role","alert"],[12],[1,[28,[35,2],[[28,[37,2],[[30,1,["state","context","errors"]],[30,2]],null],"message"],null]],[13],[1,"\\n "]],[]]]]],[1,"\\n"],[13],[1,"\\n"]],["@chart","@name","&attrs","@validations","@help","help","&label","&input"],false,["concat","if","get","yield","let","or","state"]]',moduleName:"consul-ui/components/form-input/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/freetext-filter/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object"],(function(e,t,n,l,r){var i +function o(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const a=(0,n.createTemplateFactory)({id:"QsBvWU14",block:'[[[1,"\\n"],[11,0],[24,0,"freetext-filter"],[17,1],[12],[1,"\\n "],[10,"label"],[14,0,"type-search"],[12],[1,"\\n "],[10,1],[14,0,"freetext-filter_label"],[12],[1,"Search"],[13],[1,"\\n "],[10,"input"],[14,0,"freetext-filter_input"],[15,"onsearch",[28,[37,0],[[30,0],[30,0,["change"]]],null]],[15,"oninput",[28,[37,0],[[30,0],[30,0,["change"]]],null]],[15,"onkeydown",[28,[37,0],[[30,0],[30,0,["keydown"]]],null]],[14,3,"s"],[15,2,[30,2]],[15,"placeholder",[30,0,["placeholder"]]],[14,"autofocus","autofocus"],[14,4,"search"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[18,3,null],[1,"\\n"],[13]],["&attrs","@value","&default"],false,["action","yield"]]',moduleName:"consul-ui/components/freetext-filter/index.hbs",isStrictMode:!1}) +let u=(o((i=class extends l.default{get placeholder(){return this.args.placeholder||"Search"}get onsearch(){return this.args.onsearch||(()=>{})}change(e){this.onsearch(e)}keydown(e){13===e.keyCode&&e.preventDefault()}}).prototype,"change",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"change"),i.prototype),o(i.prototype,"keydown",[r.action],Object.getOwnPropertyDescriptor(i.prototype,"keydown"),i.prototype),i) +e.default=u,(0,t.setComponentTemplate)(a,u)})),define("consul-ui/components/hashicorp-consul/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service"],(function(e,t,n,l,r){var i,o,a,u,s +function c(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function d(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const p=(0,n.createTemplateFactory)({id:"dpUxCs9Y",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"hashicorp-consul"],[17,1]],null,[["notifications","side-nav","main"],[[[[1,"\\n"],[42,[28,[37,2],[[28,[37,2],[[33,3,["queue"]]],null]],null],null,[[[1," "],[8,[30,2,["Notification"]],null,[["@delay","@sticky"],[[28,[37,4],[[30,3,["timeout"]],[30,3,["extendedTimeout"]]],null],[30,3,["sticky"]]]],[["default"],[[[[1,"\\n"],[41,[30,3,["dom"]],[[[1," "],[2,[30,3,["dom"]]],[1,"\\n"]],[]],[[[44,[[28,[37,7],[[30,3,["type"]]],null],[28,[37,7],[[30,3,["action"]]],null]],[[[1," "],[8,[39,8],[[24,"data-notification",""]],[["@color"],[[52,[28,[37,9],[[30,4],"error"],null],"critical",[30,4]]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,[28,[35,10],[[30,4]],null]],[1,"!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,9],[[30,5],"logout"],null],[[[41,[28,[37,9],[[30,4],"success"],null],[[[1," "],[1,[28,[35,11],["components.hashicorp-consul.notifications.logged-out"],null]],[1,"\\n"]],[]],[[[1," "],[1,[28,[35,11],["components.hashicorp-consul.notifications.logged-out-error"],null]],[1,"\\n"]],[]]]],[]],[[[41,[28,[37,9],[[30,5],"authorize"],null],[[[41,[28,[37,9],[[30,4],"success"],null],[[[1," "],[1,[28,[35,11],["components.hashicorp-consul.notifications.logged-in"],null]],[1,"\\n"]],[]],[[[1," "],[1,[28,[35,11],["components.hashicorp-consul.notifications.logged-in-error"],null]],[1,"\\n"]],[]]]],[]],[[[41,[28,[37,12],[[28,[37,9],[[30,5],"use"],null],[28,[37,9],[[30,3,["model"]],"token"],null]],null],[[[1," "],[8,[39,13],null,[["@type","@status","@item","@error"],[[30,5],[30,4],[30,3,["item"]],[30,3,["error"]]]],null],[1,"\\n"]],[]],[[[41,[28,[37,9],[[30,3,["model"]],"intention"],null],[[[1," "],[8,[39,14],null,[["@type","@status","@item","@error"],[[30,5],[30,4],[30,3,["item"]],[30,3,["error"]]]],null],[1,"\\n"]],[]],[[[41,[28,[37,9],[[30,3,["model"]],"role"],null],[[[1," "],[8,[39,15],null,[["@type","@status","@item","@error"],[[30,5],[30,4],[30,3,["item"]],[30,3,["error"]]]],null],[1,"\\n"]],[]],[[[41,[28,[37,9],[[30,3,["model"]],"policy"],null],[[[1," "],[8,[39,16],null,[["@type","@status","@item","@error"],[[30,5],[30,4],[30,3,["item"]],[30,3,["error"]]]],null],[1,"\\n "]],[]],null]],[]]]],[]]]],[]]],[1," "]],[]]]],[]]],[1," "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n\\n"]],[4,5]]]],[]]],[1," "]],[]]]]],[1,"\\n"]],[3]],null],[1,"\\n "]],[2]],[[[1,"\\n "],[8,[39,17],[[24,0,"consul-side-nav"]],[["@hasA11yRefocus","@isResponsive"],[false,false]],[["header","body","footer"],[[[[1,"\\n "],[8,[39,18],null,null,[["logo","actions"],[[[[1,"\\n "],[8,[39,19],null,[["@icon","@ariaLabel","@href","@isHrefExternal"],["consul-color","Consul",[28,[37,20],["index"],[["params"],[[28,[37,21],null,[["peer"],[[27]]]]]]],false]],null],[1,"\\n "]],[]],[[[1,"\\n "],[8,[39,22],[[24,0,"hds-side-nav__dropdown"]],[["@listPosition"],["bottom-left"]],[["default"],[[[[1,"\\n "],[8,[30,7,["ToggleIcon"]],null,[["@icon","@text"],["help","Help & Support menu"]],null],[1,"\\n "],[8,[39,23],null,[["@dropdown"],[[30,7]]],null],[1,"\\n "],[8,[30,7,["Interactive"]],null,[["@href","@isHrefExternal","@text"],[[28,[37,24],["CONSUL_DOCS_URL"],null],true,[28,[37,11],["components.hashicorp-consul.side-nav.support-menu.docs"],null]]],null],[1,"\\n "],[8,[30,7,["Interactive"]],null,[["@href","@isHrefExternal","@text"],[[28,[37,25],[[28,[37,24],["CONSUL_DOCS_LEARN_URL"],null],"/consul"],null],true,[28,[37,11],["components.hashicorp-consul.side-nav.support-menu.tutorials"],null]]],null],[1,"\\n "],[8,[30,7,["Interactive"]],null,[["@href","@isHrefExternal","@text"],[[28,[37,24],["CONSUL_REPO_ISSUES_URL"],null],true,[28,[37,11],["components.hashicorp-consul.side-nav.support-menu.feedback"],null]]],null],[1,"\\n "]],[7]]]]],[1,"\\n\\n "],[8,[39,26],null,[["@dc","@partition","@nspace","@onchange"],[[30,8],[30,9],[30,10],[30,11]]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@target","@name","@value"],[[30,0],"tokenSelector",[30,12]]],null],[1,"\\n "]],[12]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]],[[[1,"\\n "],[8,[39,28],[[24,0,"hds-side-nav-hide-when-minimized consul-side-nav__selector-group"]],null,[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@list"],[[30,13]]],null],[1,"\\n "],[8,[39,30],null,[["@list","@dc","@partition","@nspace","@dcs"],[[30,13],[30,8],[30,9],[30,10],[30,14]]],null],[1,"\\n\\n "],[8,[39,31],null,[["@dc","@partition","@nspace","@partitions","@list","@onchange"],[[30,8],[30,9],[30,10],[30,0,["partitions"]],[30,13],[28,[37,32],[[30,0],[28,[37,33],[[30,0,["partitions"]]],null]],[["value"],["data"]]]]],null],[1,"\\n "],[8,[39,34],null,[["@list","@dc","@partition","@nspace","@nspaces","@onchange"],[[30,13],[30,8],[30,9],[30,10],[30,0,["nspaces"]],[28,[37,32],[[30,0],[28,[37,33],[[30,0,["nspaces"]]],null]],[["value"],["data"]]]]],null],[1,"\\n "]],[13]]]]],[1,"\\n "],[8,[39,28],[[24,0,"hds-side-nav-hide-when-minimized"]],null,[["default"],[[[[1,"\\n"],[41,[28,[37,35],["access overview"],null],[[[1," "],[8,[30,15,["Link"]],null,[["@text","@route","@models","@query","@isActive"],[[28,[37,11],["components.hashicorp-consul.side-nav.overview"],null],"dc.show",[28,[37,36],[[30,8,["Name"]]],null],[28,[37,21],null,[["peer"],[[27]]]],[28,[37,37],["dc.show",[30,8,["Name"]]],null]]],null],[1,"\\n"]],[]],null],[41,[28,[37,35],["read services"],null],[[[1," "],[8,[30,15,["Link"]],null,[["@text","@href","@isHrefExternal","@isActive"],[[28,[37,11],["components.hashicorp-consul.side-nav.services"],null],[28,[37,20],["dc.services",[30,8,["Name"]]],[["params"],[[28,[37,21],null,[["peer"],[[27]]]]]]],false,[28,[37,37],["dc.services",[30,8,["Name"]]],null]]],null],[1,"\\n"]],[]],null],[41,[28,[37,35],["read nodes"],null],[[[1," "],[8,[30,15,["Link"]],null,[["@text","@href","@isHrefExternal","@isActive"],[[28,[37,11],["components.hashicorp-consul.side-nav.nodes"],null],[28,[37,20],["dc.nodes",[30,8,["Name"]]],[["params"],[[28,[37,21],null,[["peer"],[[27]]]]]]],false,[28,[37,37],["dc.nodes",[30,8,["Name"]]],null]]],null],[1,"\\n"]],[]],null],[41,[28,[37,35],["read kv"],null],[[[1," "],[8,[30,15,["Link"]],null,[["@text","@href","@isHrefExternal","@isActive"],[[28,[37,11],["components.hashicorp-consul.side-nav.kv"],null],[28,[37,20],["dc.kv",[30,8,["Name"]]],[["params"],[[28,[37,21],null,[["peer"],[[27]]]]]]],false,[28,[37,37],["dc.kv",[30,8,["Name"]]],null]]],null],[1,"\\n"]],[]],null],[41,[28,[37,35],["read intentions"],null],[[[1," "],[8,[30,15,["Link"]],null,[["@text","@href","@isHrefExternal","@isActive"],[[28,[37,11],["components.hashicorp-consul.side-nav.intentions"],null],[28,[37,20],["dc.intentions",[30,8,["Name"]]],[["params"],[[28,[37,21],null,[["peer"],[[27]]]]]]],false,[28,[37,37],["dc.intentions",[30,8,["Name"]]],null]]],null],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,38],null,[["@dc","@partition","@nspace","@list"],[[30,8],[30,9],[30,10],[30,15]]],null],[1,"\\n "],[8,[39,39],null,[["@dc","@partition","@nspace","@list"],[[30,8],[30,9],[30,10],[30,15]]],null],[1,"\\n "]],[15]]]]],[1,"\\n "]],[]],[[[1,"\\n "],[10,"footer"],[14,"role","contentinfo"],[12],[1,"\\n "],[8,[39,40],[[24,0,"hds-side-nav-hide-when-minimized"]],[["@size","@color"],["100","disabled"]],[["default"],[[[[1,"\\n "],[1,[28,[35,11],["components.hashicorp-consul.side-nav.footer"],[["version"],[[30,0,["consulVersion"]]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[2,[28,[37,25],["\x3c!-- ",[28,[37,24],["CONSUL_GIT_SHA"],null],"--\x3e"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]],[[[1,"\\n "],[18,16,[[28,[37,21],null,[["login"],[[52,[30,0,["tokenSelector"]],[30,0,["tokenSelector"]],[28,[37,21],null,[["open","close"],[[27],[27]]]]]]]]]],[1,"\\n "]],[]]]]]],["&attrs","app","flash","status","type","T","dd","@dc","@partition","@nspace","@onchange","selector","SNL","@dcs","SNL","&default"],false,["app","each","-track-array","flashMessages","sub","if","let","lowercase","hds/toast","eq","capitalize","t","or","consul/token/notifications","consul/intention/notifications","consul/role/notifications","consul/policy/notifications","hds/side-nav","hds/side-nav/header","hds/side-nav/header/home-link","href-to","hash","hds/dropdown","debug/navigation","env","concat","consul/token/selector","ref","hds/side-nav/list","hcp-nav-item","consul/datacenter/selector","consul/partition/selector","action","mut","consul/nspace/selector","can","array","is-href","consul/acl/selector","consul/peer/selector","hds/text/display","yield"]]',moduleName:"consul-ui/components/hashicorp-consul/index.hbs",isStrictMode:!1}) +let f=(i=(0,r.inject)("flashMessages"),o=(0,r.inject)("env"),a=class extends l.default{constructor(){super(...arguments),c(this,"flashMessages",u,this),c(this,"env",s,this)}get consulVersion(){const e=["","oss"].includes(this.env.var("CONSUL_BINARY_TYPE"))?"":"+ent" +return`${this.env.var("CONSUL_VERSION")}${e}`}},u=d(a.prototype,"flashMessages",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s=d(a.prototype,"env",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a) +e.default=f,(0,t.setComponentTemplate)(p,f)})) +define("consul-ui/components/hcp-nav-item/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service"],(function(e,t,n,l,r){var i,o +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const a=(0,n.createTemplateFactory)({id:"l8c9YROO",block:'[[[1,"\\n"],[44,[[30,1],[28,[37,1],["CONSUL_HCP_URL"],null]],[[[41,[30,0,["shouldShowBackToHcpItem"]],[[[1," "],[8,[30,2,["BackLink"]],null,[["@text","@href","@isHrefExternal"],[[28,[37,3],["components.hashicorp-consul.side-nav.hcp"],null],[30,3],true]],null],[1,"\\n"]],[]],null]],[2,3]]]],["@list","SNL","hcpUrl"],false,["let","env","if","t"]]',moduleName:"consul-ui/components/hcp-nav-item/index.hbs",isStrictMode:!1}) +let u=(i=class extends l.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}get shouldShowBackToHcpItem(){const e=!!this.env.var("CONSUL_HCP_URL") +return!!this.env.var("CONSUL_HCP_ENABLED")&&e}},s=i.prototype,c="env",d=[r.inject],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),o=m,i) +var s,c,d,p,f,m +e.default=u,(0,t.setComponentTemplate)(a,u)})),define("consul-ui/components/hds/accordion/index",["exports","@hashicorp/design-system-components/components/hds/accordion/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/accordion/item/button",["exports","@hashicorp/design-system-components/components/hds/accordion/item/button"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/accordion/item/index",["exports","@hashicorp/design-system-components/components/hds/accordion/item/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/alert/description",["exports","@hashicorp/design-system-components/components/hds/alert/description"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/alert/index",["exports","@hashicorp/design-system-components/components/hds/alert/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/alert/title",["exports","@hashicorp/design-system-components/components/hds/alert/title"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/app-footer/copyright",["exports","@hashicorp/design-system-components/components/hds/app-footer/copyright"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/app-footer/index",["exports","@hashicorp/design-system-components/components/hds/app-footer/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/app-footer/item",["exports","@hashicorp/design-system-components/components/hds/app-footer/item"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/app-footer/legal-links",["exports","@hashicorp/design-system-components/components/hds/app-footer/legal-links"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/app-footer/link",["exports","@hashicorp/design-system-components/components/hds/app-footer/link"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/app-footer/status-link",["exports","@hashicorp/design-system-components/components/hds/app-footer/status-link"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/app-frame/index",["exports","@hashicorp/design-system-components/components/hds/app-frame/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/app-frame/parts/footer",["exports","@hashicorp/design-system-components/components/hds/app-frame/parts/footer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/app-frame/parts/header",["exports","@hashicorp/design-system-components/components/hds/app-frame/parts/header"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/app-frame/parts/main",["exports","@hashicorp/design-system-components/components/hds/app-frame/parts/main"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/app-frame/parts/modals",["exports","@hashicorp/design-system-components/components/hds/app-frame/parts/modals"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/app-frame/parts/sidebar",["exports","@hashicorp/design-system-components/components/hds/app-frame/parts/sidebar"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/application-state/body",["exports","@hashicorp/design-system-components/components/hds/application-state/body"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/application-state/footer",["exports","@hashicorp/design-system-components/components/hds/application-state/footer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/application-state/header",["exports","@hashicorp/design-system-components/components/hds/application-state/header"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/application-state/index",["exports","@hashicorp/design-system-components/components/hds/application-state/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/avatar/index",["exports","@hashicorp/design-system-components/components/hds/avatar/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/badge-count/index",["exports","@hashicorp/design-system-components/components/hds/badge-count/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/badge/index",["exports","@hashicorp/design-system-components/components/hds/badge/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/breadcrumb/index",["exports","@hashicorp/design-system-components/components/hds/breadcrumb/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/breadcrumb/item",["exports","@hashicorp/design-system-components/components/hds/breadcrumb/item"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/breadcrumb/truncation",["exports","@hashicorp/design-system-components/components/hds/breadcrumb/truncation"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/button-set/index",["exports","@hashicorp/design-system-components/components/hds/button-set/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) +define("consul-ui/components/hds/button/index",["exports","@hashicorp/design-system-components/components/hds/button/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/card/container",["exports","@hashicorp/design-system-components/components/hds/card/container"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/copy/button/index",["exports","@hashicorp/design-system-components/components/hds/copy/button/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/copy/snippet/index",["exports","@hashicorp/design-system-components/components/hds/copy/snippet/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/disclosure-primitive/index",["exports","@hashicorp/design-system-components/components/hds/disclosure-primitive/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dismiss-button/index",["exports","@hashicorp/design-system-components/components/hds/dismiss-button/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/footer",["exports","@hashicorp/design-system-components/components/hds/dropdown/footer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/header",["exports","@hashicorp/design-system-components/components/hds/dropdown/header"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/index",["exports","@hashicorp/design-system-components/components/hds/dropdown/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/checkbox",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/checkbox"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/checkmark",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/checkmark"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/copy-item",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/copy-item"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/description",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/description"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/generic",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/generic"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/interactive",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/interactive"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/radio",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/radio"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/separator",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/separator"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/list-item/title",["exports","@hashicorp/design-system-components/components/hds/dropdown/list-item/title"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/toggle/button",["exports","@hashicorp/design-system-components/components/hds/dropdown/toggle/button"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/toggle/chevron",["exports","@hashicorp/design-system-components/components/hds/dropdown/toggle/chevron"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/dropdown/toggle/icon",["exports","@hashicorp/design-system-components/components/hds/dropdown/toggle/icon"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/flyout/body",["exports","@hashicorp/design-system-components/components/hds/flyout/body"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/flyout/description",["exports","@hashicorp/design-system-components/components/hds/flyout/description"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/flyout/footer",["exports","@hashicorp/design-system-components/components/hds/flyout/footer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/flyout/header",["exports","@hashicorp/design-system-components/components/hds/flyout/header"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/flyout/index",["exports","@hashicorp/design-system-components/components/hds/flyout/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/checkbox/base",["exports","@hashicorp/design-system-components/components/hds/form/checkbox/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/checkbox/field",["exports","@hashicorp/design-system-components/components/hds/form/checkbox/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/checkbox/group",["exports","@hashicorp/design-system-components/components/hds/form/checkbox/group"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/error/index",["exports","@hashicorp/design-system-components/components/hds/form/error/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) +define("consul-ui/components/hds/form/error/message",["exports","@hashicorp/design-system-components/components/hds/form/error/message"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/field/index",["exports","@hashicorp/design-system-components/components/hds/form/field/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/fieldset/index",["exports","@hashicorp/design-system-components/components/hds/form/fieldset/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/file-input/base",["exports","@hashicorp/design-system-components/components/hds/form/file-input/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/file-input/field",["exports","@hashicorp/design-system-components/components/hds/form/file-input/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/helper-text/index",["exports","@hashicorp/design-system-components/components/hds/form/helper-text/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/indicator/index",["exports","@hashicorp/design-system-components/components/hds/form/indicator/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/label/index",["exports","@hashicorp/design-system-components/components/hds/form/label/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/legend/index",["exports","@hashicorp/design-system-components/components/hds/form/legend/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/masked-input/base",["exports","@hashicorp/design-system-components/components/hds/form/masked-input/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/masked-input/field",["exports","@hashicorp/design-system-components/components/hds/form/masked-input/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio-card/description",["exports","@hashicorp/design-system-components/components/hds/form/radio-card/description"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio-card/group",["exports","@hashicorp/design-system-components/components/hds/form/radio-card/group"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio-card/index",["exports","@hashicorp/design-system-components/components/hds/form/radio-card/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio-card/label",["exports","@hashicorp/design-system-components/components/hds/form/radio-card/label"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio/base",["exports","@hashicorp/design-system-components/components/hds/form/radio/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio/field",["exports","@hashicorp/design-system-components/components/hds/form/radio/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/radio/group",["exports","@hashicorp/design-system-components/components/hds/form/radio/group"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/select/base",["exports","@hashicorp/design-system-components/components/hds/form/select/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/select/field",["exports","@hashicorp/design-system-components/components/hds/form/select/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/text-input/base",["exports","@hashicorp/design-system-components/components/hds/form/text-input/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/text-input/field",["exports","@hashicorp/design-system-components/components/hds/form/text-input/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/textarea/base",["exports","@hashicorp/design-system-components/components/hds/form/textarea/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/textarea/field",["exports","@hashicorp/design-system-components/components/hds/form/textarea/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/toggle/base",["exports","@hashicorp/design-system-components/components/hds/form/toggle/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/toggle/field",["exports","@hashicorp/design-system-components/components/hds/form/toggle/field"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/toggle/group",["exports","@hashicorp/design-system-components/components/hds/form/toggle/group"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/form/visibility-toggle/index",["exports","@hashicorp/design-system-components/components/hds/form/visibility-toggle/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/icon-tile/index",["exports","@hashicorp/design-system-components/components/hds/icon-tile/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/interactive/index",["exports","@hashicorp/design-system-components/components/hds/interactive/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) +define("consul-ui/components/hds/link/inline",["exports","@hashicorp/design-system-components/components/hds/link/inline"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/link/standalone",["exports","@hashicorp/design-system-components/components/hds/link/standalone"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/menu-primitive/index",["exports","@hashicorp/design-system-components/components/hds/menu-primitive/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/modal/body",["exports","@hashicorp/design-system-components/components/hds/modal/body"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/modal/footer",["exports","@hashicorp/design-system-components/components/hds/modal/footer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/modal/header",["exports","@hashicorp/design-system-components/components/hds/modal/header"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/modal/index",["exports","@hashicorp/design-system-components/components/hds/modal/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/page-header/actions",["exports","@hashicorp/design-system-components/components/hds/page-header/actions"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/page-header/badges",["exports","@hashicorp/design-system-components/components/hds/page-header/badges"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/page-header/description",["exports","@hashicorp/design-system-components/components/hds/page-header/description"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/page-header/index",["exports","@hashicorp/design-system-components/components/hds/page-header/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/page-header/subtitle",["exports","@hashicorp/design-system-components/components/hds/page-header/subtitle"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/page-header/title",["exports","@hashicorp/design-system-components/components/hds/page-header/title"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/compact/index",["exports","@hashicorp/design-system-components/components/hds/pagination/compact/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/info",["exports","@hashicorp/design-system-components/components/hds/pagination/info"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/nav/arrow",["exports","@hashicorp/design-system-components/components/hds/pagination/nav/arrow"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/nav/ellipsis",["exports","@hashicorp/design-system-components/components/hds/pagination/nav/ellipsis"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/nav/number",["exports","@hashicorp/design-system-components/components/hds/pagination/nav/number"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/numbered/index",["exports","@hashicorp/design-system-components/components/hds/pagination/numbered/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/pagination/size-selector",["exports","@hashicorp/design-system-components/components/hds/pagination/size-selector"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/reveal/index",["exports","@hashicorp/design-system-components/components/hds/reveal/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/reveal/toggle/button",["exports","@hashicorp/design-system-components/components/hds/reveal/toggle/button"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/segmented-group/index",["exports","@hashicorp/design-system-components/components/hds/segmented-group/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/separator/index",["exports","@hashicorp/design-system-components/components/hds/separator/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/side-nav/base",["exports","@hashicorp/design-system-components/components/hds/side-nav/base"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/side-nav/header/home-link",["exports","@hashicorp/design-system-components/components/hds/side-nav/header/home-link"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/side-nav/header/icon-button",["exports","@hashicorp/design-system-components/components/hds/side-nav/header/icon-button"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/side-nav/header/index",["exports","@hashicorp/design-system-components/components/hds/side-nav/header"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/side-nav/index",["exports","@hashicorp/design-system-components/components/hds/side-nav/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/side-nav/list/back-link",["exports","@hashicorp/design-system-components/components/hds/side-nav/list/back-link"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) +define("consul-ui/components/hds/side-nav/list/index",["exports","@hashicorp/design-system-components/components/hds/side-nav/list/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/side-nav/list/item",["exports","@hashicorp/design-system-components/components/hds/side-nav/list/item"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/side-nav/list/link",["exports","@hashicorp/design-system-components/components/hds/side-nav/list/link"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/side-nav/list/title",["exports","@hashicorp/design-system-components/components/hds/side-nav/list/title"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/side-nav/portal/index",["exports","@hashicorp/design-system-components/components/hds/side-nav/portal/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/side-nav/portal/target",["exports","@hashicorp/design-system-components/components/hds/side-nav/portal/target"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/side-nav/toggle-button",["exports","@hashicorp/design-system-components/components/hds/side-nav/toggle-button"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/stepper/step/indicator",["exports","@hashicorp/design-system-components/components/hds/stepper/step/indicator"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/stepper/task/indicator",["exports","@hashicorp/design-system-components/components/hds/stepper/task/indicator"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/table/index",["exports","@hashicorp/design-system-components/components/hds/table/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/table/td",["exports","@hashicorp/design-system-components/components/hds/table/td"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/table/th-sort",["exports","@hashicorp/design-system-components/components/hds/table/th-sort"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/table/th",["exports","@hashicorp/design-system-components/components/hds/table/th"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/table/tr",["exports","@hashicorp/design-system-components/components/hds/table/tr"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/tabs/index",["exports","@hashicorp/design-system-components/components/hds/tabs/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/tabs/panel",["exports","@hashicorp/design-system-components/components/hds/tabs/panel"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/tabs/tab",["exports","@hashicorp/design-system-components/components/hds/tabs/tab"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/tag/index",["exports","@hashicorp/design-system-components/components/hds/tag/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/text/body",["exports","@hashicorp/design-system-components/components/hds/text/body"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/text/code",["exports","@hashicorp/design-system-components/components/hds/text/code"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/text/display",["exports","@hashicorp/design-system-components/components/hds/text/display"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/text/index",["exports","@hashicorp/design-system-components/components/hds/text/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/toast/index",["exports","@hashicorp/design-system-components/components/hds/toast/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/tooltip-button/index",["exports","@hashicorp/design-system-components/components/hds/tooltip-button/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/hds/yield/index",["exports","@hashicorp/design-system-components/components/hds/yield/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/informed-action/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"OpUoOs2J",block:'[[[1,"\\n"],[11,0],[24,0,"informed-action"],[17,1],[12],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[18,2,null],[1,"\\n "],[13],[1,"\\n "],[18,3,null],[1,"\\n "],[13],[1,"\\n "],[10,"ul"],[12],[1,"\\n "],[18,4,[[28,[37,1],null,[["Action"],[[50,"anonymous",0,null,[["tagName"],["li"]]]]]]]],[1,"\\n "],[13],[1,"\\n"],[13]],["&attrs","&header","&body","&actions"],false,["yield","hash","component"]]',moduleName:"consul-ui/components/informed-action/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/ivy-codemirror",["exports","ivy-codemirror/components/ivy-codemirror"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/jwt-source/index",["exports","@glimmer/component","@ember/service","consul-ui/utils/dom/event-source"],(function(e,t,n,l){var r,i,o,a,u +function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let d=(r=(0,n.inject)("repository/oidc-provider"),i=(0,n.inject)("dom"),o=class extends t.default{constructor(){super(...arguments),s(this,"repo",a,this),s(this,"dom",u,this),this.source&&this.source.close(),this._listeners=this.dom.listeners(),this.source=(0,l.fromPromise)(this.repo.findCodeByURL(this.args.src)),this._listeners.add(this.source,{message:e=>this.onchange(e),error:e=>this.onerror(e)})}onchange(e){"function"==typeof this.args.onchange&&this.args.onchange(...arguments)}onerror(e){"function"==typeof this.args.onerror&&this.args.onerror(...arguments)}willDestroy(){super.willDestroy(...arguments),this.source&&this.source.close(),this.repo.close(),this._listeners.remove()}},a=c(o.prototype,"repo",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(o.prototype,"dom",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) +e.default=d})),define("consul-ui/components/list-collection/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object","ember-collection/components/ember-collection","ember-collection/layouts/percentage-columns","block-slots"],(function(e,t,n,l,r,i,o,a){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const u=(0,n.createTemplateFactory)({id:"c8hhQNDG",block:'[[[1,"\\n"],[11,0],[16,0,[29,["list-collection list-collection-scroll-",[36,0]]]],[23,5,[28,[37,1],["height:",[33,2,["height"]],"px"],null]],[16,1,[36,3]],[17,1],[12],[1,"\\n"],[18,7,null],[1,"\\n"],[41,[28,[37,6],[[33,0],"virtual"],null],[[[1," "],[1,[28,[35,7],["resize",[28,[37,8],[[30,0],"resize"],null]],null]],[1,"\\n "],[8,[39,9],null,[["@tagName","@content-size","@scroll-left","@scroll-top","@scrollChange","@clientSizeChange"],["ul",[99,10,["@content-size"]],[99,11,["@scroll-left"]],[99,12,["@scroll-top"]],[28,[37,8],[[30,0],"scrollChange"],null],[28,[37,8],[[30,0],"clientSizeChange"],null]]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[13],[42,[28,[37,14],[[28,[37,14],[[33,15]],null]],null],null,[[[10,"li"],[15,"onclick",[28,[37,8],[[30,0],"click"],null]],[22,5,[30,2,["style"]]],[15,0,[52,[33,16],[52,[28,[37,17],[[33,16]],[["item"],[[30,2,["item"]]]]],"linkable"]]],[12],[1,"\\n "],[8,[39,18],null,[["@name"],["header"]],[["default"],[[[[10,0],[14,0,"header"],[12],[18,7,[[30,2,["item"]],[30,2,["index"]]]],[13]],[]]]]],[1,"\\n "],[8,[39,18],null,[["@name"],["details"]],[["default"],[[[[10,0],[14,0,"detail"],[12],[18,7,[[30,2,["item"]],[30,2,["index"]]]],[13]],[]]]]],[1,"\\n "],[8,[39,18],null,[["@name","@params"],["actions",[28,[37,19],[[50,"more-popover-menu",0,null,[["expanded","onchange"],[[52,[28,[37,6],[[33,21],[30,2,["index"]]],null],true,false],[28,[37,8],[[30,0],"change",[30,2,["index"]]],null]]]]],null]]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"actions"],[12],[1,"\\n "],[18,7,[[30,2,["item"]],[30,2,["index"]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[13]],[2]],null]],[]]]]],[1,"\\n"]],[]],[[[44,[[52,[28,[37,23],[[33,24],[28,[37,25],[[30,0,["expand"]]],null]],null],[28,[37,26],[0,[33,24],[33,27]],null],[33,27]]],[[[1," "],[10,"ul"],[12],[1,"\\n "],[10,"li"],[14,5,"display: none;"],[12],[13],[42,[28,[37,14],[[28,[37,14],[[30,3]],null]],null],null,[[[10,"li"],[15,"onclick",[28,[37,8],[[30,0],"click"],null]],[15,0,[52,[28,[37,25],[[33,16]],null],"linkable",[52,[28,[37,17],[[33,16]],[["item"],[[33,28,["item"]]]]],"linkable"]]],[12],[1,"\\n "],[8,[39,18],null,[["@name"],["header"]],[["default"],[[[[10,0],[14,0,"header"],[12],[18,7,[[30,4],[30,5]]],[13]],[]]]]],[1,"\\n "],[8,[39,18],null,[["@name"],["details"]],[["default"],[[[[10,0],[14,0,"detail"],[12],[18,7,[[30,4],[30,5]]],[13]],[]]]]],[1,"\\n "],[8,[39,18],null,[["@name","@params"],["actions",[28,[37,19],[[50,"more-popover-menu",0,null,[["onchange"],[[28,[37,8],[[30,0],"change",[30,5]],null]]]]],null]]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"actions"],[12],[1,"\\n "],[18,7,[[30,4],[30,5]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[13]],[4,5]],null],[13],[1,"\\n"],[41,[28,[37,23],[[33,24],[28,[37,29],[[33,27,["length"]],[33,24]],null]],null],[[[44,[[28,[37,30],[[30,3,["length"]],[33,27,["length"]]],null]],[[[1," "],[10,"button"],[15,0,[52,[30,6],"closed"]],[15,"onclick",[28,[37,8],[[30,0],[28,[37,31],[[30,0,["expand"]]],null],[30,6]],null]],[14,4,"button"],[12],[1,"\\n"],[41,[30,6],[[[1," View "],[1,[28,[35,32],[[33,27,["length"]],[30,3,["length"]]],null]],[1," more\\n"]],[]],[[[1," View less\\n"]],[]]],[1," "],[13],[1,"\\n"]],[6]]]],[]],null]],[3]]],[1,"\\n"]],[]]],[13]],["&attrs","cell","slice","item","index","more","&default"],false,["scroll","concat","style","guid","yield","if","eq","on-window","action","ember-native-scrollable","_contentSize","_scrollLeft","_scrollTop","each","-track-array","_cells","linkable","is","yield-slot","block-params","component","checked","let","and","partial","not","slice","items","cell","gt","not-eq","mut","sub"]]',moduleName:"consul-ui/components/list-collection/index.hbs",isStrictMode:!1}),s=o.default.prototype.formatItemStyle +var c=(0,t.setComponentTemplate)(u,i.default.extend(a.default,{dom:(0,l.inject)("dom"),tagName:"",height:500,cellHeight:70,checked:null,scroll:"virtual",init:function(){this._super(...arguments),this.columns=[100],this.guid=this.dom.guid(this)},didInsertElement:function(){this._super(...arguments),this.$element=this.dom.element(`#${this.guid}`),"virtual"===this.scroll&&this.actions.resize.apply(this,[{target:this.dom.viewport()}])},didReceiveAttrs:function(){this._super(...arguments),this._cellLayout=this["cell-layout"]=new o.default((0,r.get)(this,"items.length"),this.columns,this.cellHeight) +const e=this +this["cell-layout"].formatItemStyle=function(t){let n=s.apply(this,arguments) +return e.checked===t&&(n=`${n};z-index: 1`),n}},style:(0,r.computed)("height",(function(){return"virtual"!==this.scroll?{}:{height:this.height}})),actions:{resize:function(e){const t=this.dom.element('footer[role="contentinfo"]') +if(t){const n=1,l=this.$element.getBoundingClientRect().top+t.clientHeight+n,r=e.target.innerHeight-l +this.set("height",Math.max(0,r)),this.updateItems(),this.updateScrollPosition()}},click:function(e){return this.dom.clickFirstAnchor(e,".list-collection > ul > li")},change:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +if(t.target.checked&&e!==this.checked){(0,r.set)(this,"checked",parseInt(e)),this.$row=this.dom.closest("li",t.target),this.$row.style.zIndex=1 +const n=this.dom.sibling(t.target,"div") +n.getBoundingClientRect().top+n.clientHeight>this.dom.element('footer[role="contentinfo"]').getBoundingClientRect().top?n.classList.add("above"):n.classList.remove("above")}else{this.dom.sibling(t.target,"div").classList.remove("above"),(0,r.set)(this,"checked",null),this.$row.style.zIndex=null}}}})) +e.default=c})),define("consul-ui/components/maybe-in-element",["exports","ember-maybe-in-element/components/maybe-in-element"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) +define("consul-ui/components/menu-panel/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/runloop","@ember/object","block-slots"],(function(e,t,n,l,r,i,o){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const a=(0,n.createTemplateFactory)({id:"AUkkhvKM",block:'[[[1,"\\n"],[18,3,null],[1,"\\n"],[44,[[28,[37,2],null,[["change"],[[28,[37,3],[[30,0],"change"],null]]]]],[[[11,0],[16,0,[28,[37,4],[[28,[37,5],["menu-panel"],null],[28,[37,5],["menu-panel-deprecated"],null],[28,[37,5],[[33,6]],null],[28,[37,5],[[33,7],"confirmation"],null]],null]],[4,[38,8],[[28,[37,3],[[30,0],"connect"],null]],null],[12],[1,"\\n "],[8,[39,9],null,[["@name"],["controls"]],[["default"],[[[[1,"\\n "],[18,3,[[30,1]]],[1,"\\n "]],[]]]]],[1,"\\n"],[6,[39,9],null,[["name"],["header"]],[["default","else"],[[[[1," "],[10,0],[12],[1,"\\n "],[18,3,[[30,1]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[],[]]]]],[1," "],[11,"ul"],[24,"role","menu"],[17,2],[12],[1,"\\n "],[8,[39,9],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[18,3,[[30,1]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],[1]]]],["api","&attrs","&default"],false,["yield","let","hash","action","class-map","array","position","isConfirmation","did-insert","yield-slot"]]',moduleName:"consul-ui/components/menu-panel/index.hbs",isStrictMode:!1}) +var u=(0,t.setComponentTemplate)(a,t.default.extend(o.default,{tagName:"",dom:(0,l.inject)("dom"),isConfirmation:!1,actions:{connect:function(e){(0,r.next)((()=>{if(!this.isDestroyed){const t=this.dom.element('li:only-child > [role="menu"]:first-child',e);(0,i.set)(this,"isConfirmation",void 0!==t)}}))},change:function(e){const t=e.target.getAttribute("id"),n=this.dom.element(`[for='${t}']`),l=this.dom.element("[role=menu]",n.parentElement),r=this.dom.closest(".menu-panel",l) +if(e.target.checked){l.style.display="block" +const e=l.offsetHeight+2 +r.style.maxHeight=r.style.minHeight=`${e}px`}else l.style.display=null,r.style.maxHeight=null,r.style.minHeight="0"}}})) +e.default=u})),define("consul-ui/components/menu/action/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"JOnhu+Ze",block:'[[[1,"\\n"],[8,[39,0],[[24,"role","menuitem"],[17,1],[4,[38,1],["click",[52,[30,2],[30,4,["close"]],[28,[37,3],null,null]]],null]],[["@href","@external"],[[30,2],[30,3]]],[["default"],[[[[1,"\\n "],[18,5,null],[1,"\\n"]],[]]]]],[1,"\\n"]],["&attrs","@href","@external","@disclosure","&default"],false,["action","on","if","noop","yield"]]',moduleName:"consul-ui/components/menu/action/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/menu/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"u8Z6a2DI",block:'[[[1,"\\n"],[11,"ul"],[24,"role","menu"],[23,5,[28,[37,0],[[28,[37,1],["height",[52,[28,[37,3],[[30,1],[28,[37,4],[[30,1,["type"]],"native-scroll"],null]],null],[30,1,["totalHeight"]]],"px"],null],[28,[37,1],["--paged-start",[52,[28,[37,3],[[30,1],[28,[37,4],[[30,1,["type"]],"native-scroll"],null]],null],[30,1,["startHeight"]]],"px"],null]],null]],[4,[38,5],[[28,[37,6],[[30,1,["pane"]]],null]],null],[4,[38,7],null,[["onclose","openEvent"],[[28,[37,8],[[30,2],[30,3,["close"]]],null],[28,[37,8],[[30,4],[30,3,["event"]]],null]]]],[12],[1,"\\n "],[18,5,[[28,[37,10],null,[["Action","Item","Separator","items"],[[50,"menu/action",0,null,[["disclosure"],[[30,3]]]],[50,"menu/item",0,null,null],[50,"menu/separator",0,null,null],[30,1,["items"]]]]]]],[1,"\\n"],[13]],["@pager","@onclose","@disclosure","@event","&default"],false,["style-map","array","if","and","not-eq","did-insert","optional","aria-menu","or","yield","hash","component"]]',moduleName:"consul-ui/components/menu/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/menu/item/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"5LgsA0nf",block:'[[[1,"\\n"],[11,"li"],[24,"role","none"],[17,1],[12],[1,"\\n "],[18,2,null],[1,"\\n"],[13],[1,"\\n\\n"]],["&attrs","&default"],false,["yield"]]',moduleName:"consul-ui/components/menu/item/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/menu/separator/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"yTrI1HMJ",block:'[[[1,"\\n"],[11,"li"],[24,"role","separator"],[17,1],[12],[18,2,null],[13],[1,"\\n"]],["&attrs","&default"],false,["yield"]]',moduleName:"consul-ui/components/menu/separator/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/modal-dialog/index",["exports","@ember/component","@ember/template-factory","@ember/object","block-slots","a11y-dialog","@ember/runloop"],(function(e,t,n,l,r,i,o){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const a=(0,n.createTemplateFactory)({id:"OjyTBU44",block:'[[[1,"\\n"],[44,[[28,[37,1],null,[["labelledby"],[[28,[37,2],null,null]]]]],[[[1," "],[8,[39,3],null,[["@target"],["modal"]],[["default"],[[[[1,"\\n "],[18,4,null],[1,"\\n "],[11,0],[24,0,"modal-dialog"],[24,"aria-hidden","true"],[17,2],[4,[38,5],[[28,[37,6],[[30,0],"connect"],null]],null],[4,[38,7],[[28,[37,6],[[30,0],"disconnect"],null]],null],[12],[1,"\\n "],[10,0],[14,"tabindex","-1"],[14,"data-a11y-dialog-hide",""],[12],[13],[1,"\\n "],[10,0],[14,0,"modal-dialog-modal"],[14,"role","dialog"],[15,"aria-label",[30,3,["label"]]],[12],[1,"\\n "],[10,0],[14,"role","document"],[12],[1,"\\n "],[10,"header"],[14,0,"modal-dialog-header"],[12],[1,"\\n "],[8,[39,8],[[24,"data-a11y-dialog-hide",""]],[["@text","@color","@icon","@size","@isIconOnly"],["Close dialog","secondary","x","small",true]],null],[1,"\\n "],[8,[39,9],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[18,4,[[28,[37,1],null,[["open","close","opened","aria"],[[28,[37,6],[[30,0],"open"],null],[28,[37,6],[[30,0],"close"],null],[30,0,["isOpen"]],[30,1]]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"modal-dialog-body"],[12],[1,"\\n "],[8,[39,9],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[18,4,[[28,[37,1],null,[["open","close","opened","aria"],[[28,[37,6],[[30,0],"open"],null],[28,[37,6],[[30,0],"close"],null],[30,0,["isOpen"]],[30,1]]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"footer"],[14,0,"modal-dialog-footer"],[12],[1,"\\n "],[8,[39,9],null,[["@name","@params"],["actions",[28,[37,10],[[28,[37,6],[[30,0],"close"],null]],null]]],[["default"],[[[[1,"\\n "],[18,4,[[28,[37,1],null,[["open","close","opened","aria"],[[28,[37,6],[[30,0],"open"],null],[28,[37,6],[[30,0],"close"],null],[30,0,["isOpen"]],[30,1]]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[1]]]],["aria","&attrs","@aria","&default"],false,["let","hash","unique-id","portal","yield","did-insert","action","will-destroy","hds/button","yield-slot","block-params"]]',moduleName:"consul-ui/components/modal-dialog/index.hbs",isStrictMode:!1}) +var u=(0,t.setComponentTemplate)(a,t.default.extend(r.default,{tagName:"",onclose:function(){},onopen:function(){},isOpen:!1,actions:{connect:function(e){this.dialog=new i.default(e),this.dialog.on("hide",(()=>{(0,o.schedule)("afterRender",(e=>(0,l.set)(this,"isOpen",!1))),this.onclose({target:e})})),this.dialog.on("show",(()=>{(0,l.set)(this,"isOpen",!0),this.onopen({target:e})})),this.open&&this.actions.open.apply(this,[])},disconnect:function(e){this.dialog.destroy()},open:function(){this.dialog.show()},close:function(){this.dialog.hide()}}})) +e.default=u})),define("consul-ui/components/modal-layer/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"zyQSzvZS",block:'[[[1,"\\n"],[11,0],[24,0,"modal-layer"],[17,1],[12],[1,"\\n "],[8,[39,0],null,[["@name","@multiple"],["modal",true]],null],[1,"\\n"],[13],[1,"\\n"]],["&attrs"],false,["portal-target"]]',moduleName:"consul-ui/components/modal-layer/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/more-popover-menu/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"aLK3TSIx",block:'[[[1,"\\n"],[11,0],[24,0,"more-popover-menu"],[17,1],[12],[1,"\\n "],[8,[39,0],null,[["@expanded","@onchange","@keyboardAccess"],[[99,1,["@expanded"]],[28,[37,2],[[30,0],[33,3]],null],false]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n More\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[18,4,[[30,2,["MenuItem"]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[2,3]]]]],[1,"\\n"],[13],[1,"\\n"]],["&attrs","components","api","&default"],false,["popover-menu","expanded","action","onchange","block-slot","yield"]]',moduleName:"consul-ui/components/more-popover-menu/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) +e.default=r})),define("consul-ui/components/nav-selector/generic",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"J8OHquCr",block:'[[[1,"\\n"],[18,1,null]],["&default"],false,["yield"]]',moduleName:"consul-ui/components/nav-selector/generic.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/nav-selector/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","@glimmer/tracking"],(function(e,t,n,l,r,i){var o,a +function u(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const s=(0,n.createTemplateFactory)({id:"JCYQiQJP",block:'[[[1,"\\n"],[44,[[30,1]],[[[1," "],[8,[30,2,["Item"]],[[24,0,"consul-side-nav__selector"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],[[24,0,"hds-side-nav__dropdown"],[17,3]],[["@listPosition","@width","@isInline"],["bottom-left","15.5rem",true]],[["default"],[[[[1,"\\n "],[8,[30,4,["ToggleButton"]],[[24,0,"consul-side-nav__selector-toggle"],[16,"disabled",[28,[37,2],[[30,5],true],null]]],[["@icon","@text"],[[30,6],[28,[37,3],[[30,7],[30,8]],null]]],null],[1,"\\n "],[8,[30,4,["Header"]],null,[["@hasDivider"],[true]],[["default"],[[[[1,"\\n "],[18,14,[[28,[37,5],null,[["Data"],[[50,"nav-selector/generic",0,null,null]]]]]],[1,"\\n"],[41,[30,9],[[[1," "],[10,0],[14,0,"consul-side-nav__selector-description"],[12],[1,"\\n "],[8,[39,8],null,[["@size","@color"],["100","faint"]],[["default"],[[[[1,[30,9]]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[8,[39,9],[[16,"placeholder",[30,10]],[16,"aria-label",[30,10]],[4,[38,10],["input",[30,0,["onSearchInput"]]],null]],[["@type","@value"],["search",[30,0,["search"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,2],[[30,0,["filteredItems","length"]],0],null],[[[1," "],[8,[30,4,["Description"]],null,[["@text"],["No results"]],null],[1,"\\n"]],[]],[[[42,[28,[37,12],[[28,[37,12],[[30,0,["filteredItems"]]],null]],null],null,[[[1," "],[18,14,[[28,[37,5],null,[["Dropdown","item"],[[30,4],[30,11]]]]]],[1,"\\n"]],[11]],null]],[]]],[41,[30,12],[[[1," "],[8,[30,4,["Footer"]],null,[["@hasDivider"],[true]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@href","@isHrefExternal","@text","@iconPosition","@icon","@color"],[[30,12],false,[30,13],"trailing","arrow-right","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[4]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[2]]]],["@list","SNL","&attrs","DD","@disabled","@icon","@item","@key","@description","@placeholder","item","@footerLink","@footerLinkText","&default"],false,["let","hds/dropdown","eq","get","yield","hash","component","if","hds/text/body","hds/form/text-input/base","on","each","-track-array","hds/link/standalone"]]',moduleName:"consul-ui/components/nav-selector/index.hbs",isStrictMode:!1}) +let c=(o=class extends l.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="search",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}get filteredItems(){const e=this.search.toLowerCase() +return e?this.args.items.filter((t=>t[this.args.key].toLowerCase().includes(e))):this.args.items}onSearchInput(e){this.search=e.target.value}},a=u(o.prototype,"search",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return""}}),u(o.prototype,"onSearchInput",[r.action],Object.getOwnPropertyDescriptor(o.prototype,"onSearchInput"),o.prototype),o) +e.default=c,(0,t.setComponentTemplate)(s,c)})),define("consul-ui/components/navigation-narrator",["exports","ember-a11y-refocus/components/navigation-narrator"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/oidc-select/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={id:"oidc-select",initial:"idle",on:{RESET:[{target:"idle"}]},states:{idle:{on:{LOAD:[{target:"loading"}]}},loaded:{},loading:{on:{SUCCESS:[{target:"loaded"}]}}}}})),define("consul-ui/components/oidc-select/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","consul-ui/components/oidc-select/chart.xstate"],(function(e,t,n,l,r,i){var o,a +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const u=(0,n.createTemplateFactory)({id:"cSKoM+S3",block:'[[[1,"\\n"],[8,[39,0],null,[["@src"],[[99,1,["@src"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],null,[["State","Guard","Action","dispatch","state"],[[30,1],[30,2],[30,3],[30,4],[30,5]]]]],[[[1,"\\n "],[11,0],[24,0,"oidc-select"],[17,7],[12],[1,"\\n "],[8,[30,1],null,[["@notMatches"],["idle"]],[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@src","@onchange","@onerror"],[[28,[37,5],["/${partition}/${nspace}/${dc}/oidc/providers",[28,[37,3],null,[["partition","nspace","dc"],[[30,0,["partition"]],[30,8],[30,9]]]]],null],[28,[37,6],[[28,[37,7],[[30,0],[28,[37,8],[[30,0,["items"]]],null]],[["value"],["data"]]],[28,[37,9],[[30,4],"SUCCESS"],null]],null],[28,[37,6],[[28,[37,9],[[30,4],"RESET"],null],[30,10]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["loaded"]],[["default"],[[[[1,"\\n "],[8,[39,7],[[24,0,"reset"],[4,[38,10],["click",[28,[37,6],[[28,[37,11],[[30,0],"partition",""],null],[28,[37,9],[[30,4],"RESET"],null]],null]],null]],null,[["default"],[[[[1,"\\n Choose different Partition\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,0],null,[["@src"],[[28,[37,0],["validate"],null]]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@name","@label","@item","@validations","@placeholder","@oninput","@chart"],["partition","Admin Partition",[30,0],[28,[37,3],null,[["partition"],[[28,[37,13],[[28,[37,3],null,[["test","error"],["^[a-zA-Z0-9]([a-zA-Z0-9-]{0,62}[a-zA-Z0-9])?$","Name must be a valid DNS hostname."]]]],null]]]],"Enter your Partition",[28,[37,7],[[30,0],[28,[37,8],[[30,0,["partition"]]],null]],[["value"],["target.value"]]],[28,[37,3],null,[["state","dispatch"],[[30,15],[30,14]]]]]],null],[1,"\\n\\n"],[1," "],[8,[30,1],null,[["@matches"],["idle"]],[["default"],[[[[1,"\\n "],[8,[39,14],[[16,"disabled",[28,[37,15],[[28,[37,16],[[30,0,["partition","length"]],1],null],[28,[37,17],[[30,15],"error"],null]],null]],[24,4,"submit"],[4,[38,10],["click",[28,[37,9],[[30,4],"LOAD"],null]],null]],[["@text"],["Choose provider"]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "]],[11,12,13,14,15]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["loading"]],[["default"],[[[[1,"\\n "],[8,[39,18],[[24,"aria-label","Loading"]],null,null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,1],null,[["@matches"],["loaded"]],[["default"],[[[[1,"\\n"],[41,[28,[37,16],[[30,0,["items","length"]],3],null],[[[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,21],[[28,[37,21],[[30,0,["items"]]],null]],null],null,[[[1," "],[10,"li"],[12],[1,"\\n "],[8,[39,7],[[16,0,[28,[37,22],[[30,16,["Kind"]],"-oidc-provider"],null]],[16,"disabled",[30,17]],[4,[38,10],["click",[28,[37,9],[[30,18],[30,16]],null]],null]],[["@type"],["button"]],[["default"],[[[[1,"\\n Continue with\\n "],[1,[28,[35,15],[[30,16,["DisplayName"]],[30,16,["Name"]]],null]],[41,[28,[37,23],[[30,16,["Namespace"]],"default"],null],[[[1,"\\n ("],[1,[30,16,["Namespace"]]],[1,")"]],[]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[16]],null],[1," "],[13],[1,"\\n\\n"]],[]],[[[1,"\\n"],[44,[[28,[37,15],[[30,0,["provider"]],[28,[37,24],[0,[30,0,["items"]]],null]],null]],[[[1,"\\n "],[8,[39,25],null,[["@label","@name","@item","@selected","@items","@onchange","@disabled"],["SSO Provider","provider",[30,0],[30,19],[30,0,["items"]],[28,[37,7],[[30,0],[28,[37,8],[[30,0,["provider"]]],null]],null],[30,17]]],[["option"],[[[[1,"\\n "],[10,1],[15,0,[28,[37,22],[[30,20,["item","Kind"]],"-oidc-provider"],null]],[12],[1,"\\n "],[1,[28,[35,15],[[30,20,["item","DisplayName"]],[30,20,["item","Name"]]],null]],[41,[28,[37,23],[[30,20,["item","Namespace"]],"default"],null],[[[1," ("],[1,[30,20,["item","Namespace"]]],[1,")"]],[]],null],[1,"\\n "],[13],[1,"\\n "]],[20]]]]],[1,"\\n\\n "],[8,[39,14],[[16,"disabled",[30,17]],[4,[38,10],["click",[28,[37,9],[[30,18],[30,19]],null]],null]],[["@color","@text"],["primary","Log in"]],null],[1,"\\n"]],[19]]]],[]]],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[6]]]],[1,2,3,4,5]]]]],[1,"\\n"]],["State","Guard","ChartAction","dispatch","state","chart","&attrs","@nspace","@dc","@onerror","ignoredState","ignoredGuard","ignoredAction","formDispatch","state","item","@disabled","@onchange","item","option"],false,["state-chart","chart","let","hash","data-source","uri","queue","action","mut","fn","on","set","text-input","array","hds/button","or","lt","state-matches","progress","if","each","-track-array","concat","not-eq","object-at","option-input"]]',moduleName:"consul-ui/components/oidc-select/index.hbs",isStrictMode:!1}) +let s=(o=class extends l.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="partition",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),this.chart=i.default,this.args.partition&&(this.partition=this.args.partition)}},c=o.prototype,d="partition",p=[r.tracked],f={configurable:!0,enumerable:!0,writable:!0,initializer:function(){return"default"}},h={},Object.keys(f).forEach((function(e){h[e]=f[e]})),h.enumerable=!!h.enumerable,h.configurable=!!h.configurable,("value"in h||h.initializer)&&(h.writable=!0),h=p.slice().reverse().reduce((function(e,t){return t(c,d,e)||e}),h),m&&void 0!==h.initializer&&(h.value=h.initializer?h.initializer.call(m):void 0,h.initializer=void 0),void 0===h.initializer&&(Object.defineProperty(c,d,h),h=null),a=h,o) +var c,d,p,f,m,h +e.default=s,(0,t.setComponentTemplate)(u,s)})),define("consul-ui/components/option-input/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"HSNBl7Zm",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"option-input type-select"],[17,1]],[["@item","@placeholder","@name","@label","@help","@validations","@chart"],[[30,2],[30,3],[30,4],[30,5],[30,6],[30,7],[30,8]]],[["label","input"],[[[[1,"\\n"],[1," "],[1,[28,[35,1],[[30,5],[30,4]],null]],[1,"\\n "]],[]],[[[1,"\\n"],[41,[30,9],[[[41,[30,10],[[],[]],[[],[]]]],[]],[[[1," "],[8,[39,3],null,[["@disabled","@onChange","@selected","@searchEnabled","@options"],[[30,11],[30,12],[30,13],false,[30,14]]],[["default"],[[[[1,"\\n "],[18,16,[[28,[37,5],null,[["item"],[[30,15]]]]]],[1,"\\n "]],[15]]]]],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n"]],["&attrs","@item","@placeholder","@name","@label","@help","@validations","@chart","@expanded","@multiple","@disabled","@onchange","@selected","@items","item","&option"],false,["form-input","or","if","power-select","yield","hash"]]',moduleName:"consul-ui/components/option-input/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/outlet/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object","@ember/service"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m,h,b,y +function v(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function g(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const O=(0,n.createTemplateFactory)({id:"rWvBYpZT",block:'[[[1,"\\n"],[1,[28,[35,0],[[30,0,["connect"]]],null]],[1,"\\n"],[1,[28,[35,1],[[30,0,["disconnect"]]],null]],[1,"\\n"],[11,"section"],[24,0,"outlet"],[16,"data-outlet",[30,1]],[16,"data-route",[30,0,["routeName"]]],[16,"data-state",[30,0,["state","name"]]],[16,"data-transition",[28,[37,2],[[30,0,["previousState","name"]]," ",[30,0,["state","name"]]],null]],[4,[38,0],[[28,[37,3],[[30,0,["attributeChanged"]],"element"],null]],null],[4,[38,4],[[28,[37,3],[[30,0,["attributeChanged"]],"model",[30,2]],null]],null],[4,[38,5],["transitionend",[30,0,["transitionEnd"]]],null],[12],[1,"\\n "],[18,3,[[28,[37,7],null,[["state","previousState","route"],[[30,0,["state"]],[30,0,["previousState"]],[30,0,["route"]]]]]]],[1,"\\n"],[13]],["@name","@model","&default"],false,["did-insert","will-destroy","concat","fn","did-update","on","yield","hash"]]',moduleName:"consul-ui/components/outlet/index.hbs",isStrictMode:!1}) +class P{constructor(e){this.name=e}matches(e){return this.name===e}}let w=(a=(0,o.inject)("routlet"),u=(0,o.inject)("router"),s=class extends l.default{constructor(){super(...arguments),v(this,"routlet",c,this),v(this,"router",d,this),v(this,"element",p,this),v(this,"routeName",f,this),v(this,"state",m,this),v(this,"previousState",h,this),v(this,"endTransition",b,this),v(this,"route",y,this)}get model(){return this.args.model||{}}get name(){return this.args.name}setAppRoute(e){if("loading"!==e||"oidc-provider-debug"===e){const t=this.element.ownerDocument.documentElement +t.classList.contains("ember-loading")&&t.classList.remove("ember-loading"),t.dataset.route=e,this.setAppState("idle")}}setAppState(e){this.element.ownerDocument.documentElement.dataset.state=e}attributeChanged(e,t){switch(e){case"element":this.element=t,"application"===this.args.name&&(this.setAppState("loading"),this.setAppRoute(this.router.currentRouteName)) +break +case"model":void 0!==this.route&&(this.route._model=t)}}transitionEnd(e){"function"==typeof this.endTransition&&this.endTransition()}startLoad(e){const t=this.routlet.findOutlet(e.to.name)||"application" +if(this.args.name===t){let e +this.previousState=this.state,this.state=new P("loading"),this.endTransition=this.routlet.transition(),e=this.element?window.getComputedStyle(this.element).getPropertyValue("transition-duration"):0,0===parseFloat(e)&&this.endTransition()}"application"===this.args.name&&this.setAppState("loading")}endLoad(e){this.state.matches("loading")&&(this.previousState=this.state,this.state=new P("idle")),"application"===this.args.name&&this.setAppRoute(this.router.currentRouteName)}connect(){this.routlet.addOutlet(this.args.name,this),this.previousState=this.state=new P("idle"),this.router.on("routeWillChange",this.startLoad),this.router.on("routeDidChange",this.endLoad)}disconnect(){this.routlet.removeOutlet(this.args.name),this.router.off("routeWillChange",this.startLoad),this.router.off("routeDidChange",this.endLoad)}},c=g(s.prototype,"routlet",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=g(s.prototype,"router",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=g(s.prototype,"element",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=g(s.prototype,"routeName",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=g(s.prototype,"state",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=g(s.prototype,"previousState",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=g(s.prototype,"endTransition",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=g(s.prototype,"route",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g(s.prototype,"attributeChanged",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"attributeChanged"),s.prototype),g(s.prototype,"transitionEnd",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"transitionEnd"),s.prototype),g(s.prototype,"startLoad",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"startLoad"),s.prototype),g(s.prototype,"endLoad",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"endLoad"),s.prototype),g(s.prototype,"connect",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"connect"),s.prototype),g(s.prototype,"disconnect",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"disconnect"),s.prototype),s) +e.default=w,(0,t.setComponentTemplate)(O,w)})),define("consul-ui/components/paged-collection/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","@glimmer/tracking","@ember/runloop"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m +function h(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function b(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const y=(0,n.createTemplateFactory)({id:"aR3XrTzu",block:'[[[1,"\\n"],[18,2,[[28,[37,1],null,[["items","page","pane","resize","viewport","rowHeight","maxHeight","startHeight","totalHeight","totalPages","Pager"],[[30,0,["items"]],[30,1],[28,[37,2],[[30,0,["setPane"]]],null],[28,[37,2],[[30,0,["resize"]]],null],[28,[37,2],[[30,0,["setViewport"]]],null],[28,[37,2],[[30,0,["setRowHeight"]]],null],[28,[37,2],[[30,0,["setMaxHeight"]]],null],[30,0,["startHeight"]],[30,0,["totalHeight"]],[30,0,["totalPages"]],[52,[28,[37,4],[[33,5],"index"],null],[50,"yield",0,null,null],""]]]]]],[1,"\\n\\n"],[1,[28,[35,7],[[30,0,["disconnect"]]],null]],[1,"\\n"]],["@page","&default"],false,["yield","hash","fn","if","eq","type","component","will-destroy"]]',moduleName:"consul-ui/components/paged-collection/index.hbs",isStrictMode:!1}) +let v=(a=class extends l.default{constructor(){super(...arguments),h(this,"$pane",u,this),h(this,"$viewport",s,this),h(this,"top",c,this),h(this,"visibleItems",d,this),h(this,"overflow",p,this),h(this,"_rowHeight",f,this),h(this,"_type",m,this)}get type(){return this.args.type||this._type}get items(){return this.args.items.slice(this.cursor,this.cursor+this.perPage)}get perPage(){switch(this.type){case"virtual-scroll":return this.visibleItems+2*this.overflow +case"index":return parseInt(this.args.perPage)}return this.total}get cursor(){switch(this.type){case"virtual-scroll":return this.itemsBefore +case"index":return(parseInt(this.args.page)-1)*this.perPage}return 0}get itemsBefore(){return void 0===this.$viewport?0:Math.max(0,Math.round(this.top/this.rowHeight)-this.overflow)}get rowHeight(){return parseFloat(this.args.rowHeight||this._rowHeight)}get startHeight(){switch(this.type){case"virtual-scroll":return Math.min(this.totalHeight,this.itemsBefore*this.rowHeight) +case"index":return 0}return 0}get totalHeight(){return this.total*this.rowHeight}get totalPages(){return Math.ceil(this.total/this.perPage)}get total(){return this.args.items.length}scroll(e){this.top=this.$viewport.scrollTop}resize(){this.$viewport.clientHeight>0&&this.rowHeight>0?this.visibleItems=Math.ceil(this.$viewport.clientHeight/this.rowHeight):this.visibleItems=0}setViewport(e){this.$viewport="html"===e?[...document.getElementsByTagName("html")][0]:e,this.$viewport.addEventListener("scroll",this.scroll),"html"===e&&this.$viewport.addEventListener("resize",this.resize),this.scroll(),this.resize()}setPane(e){this.$pane=e}setRowHeight(e){this._rowHeight=parseFloat(e)}setMaxHeight(e){(0,o.scheduleOnce)("actions",this,"_setMaxHeight")}_setMaxHeight(e){const t=parseFloat(e) +isNaN(t)||(this._type="virtual-scroll")}disconnect(){this.$viewport.removeEventListener("scroll",this.scroll),this.$viewport.removeEventListener("resize",this.resize)}},u=b(a.prototype,"$pane",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s=b(a.prototype,"$viewport",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=b(a.prototype,"top",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return 0}}),d=b(a.prototype,"visibleItems",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return 0}}),p=b(a.prototype,"overflow",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return 10}}),f=b(a.prototype,"_rowHeight",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return 0}}),m=b(a.prototype,"_type",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return"native-scroll"}}),b(a.prototype,"scroll",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"scroll"),a.prototype),b(a.prototype,"resize",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"resize"),a.prototype),b(a.prototype,"setViewport",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"setViewport"),a.prototype),b(a.prototype,"setPane",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"setPane"),a.prototype),b(a.prototype,"setRowHeight",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"setRowHeight"),a.prototype),b(a.prototype,"setMaxHeight",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"setMaxHeight"),a.prototype),b(a.prototype,"_setMaxHeight",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"_setMaxHeight"),a.prototype),b(a.prototype,"disconnect",[r.action],Object.getOwnPropertyDescriptor(a.prototype,"disconnect"),a.prototype),a) +e.default=v,(0,t.setComponentTemplate)(y,v)})),define("consul-ui/components/panel/index.css",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>e` + .panel { + --padding-x: 14px; + --padding-y: 14px; + } + .panel { + position: relative; + } + .panel-separator { + margin: 0; + } + + .panel { + --tone-border: var(--token-color-palette-neutral-300); + border: var(--decor-border-100); + border-radius: var(--decor-radius-200); + box-shadow: var(--token-surface-high-box-shadow); + } + .panel-separator { + border: 0; + border-top: var(--decor-border-100); + } + .panel { + color: var(--token-color-foreground-strong); + background-color: var(--token-color-surface-primary); + } + .panel, + .panel-separator { + border-color: var(--tone-border); + } +`})),define("consul-ui/components/peerings/badge/icon/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"KlZK7YBq",block:'[[[1,"\\n"],[41,[28,[37,1],[[28,[37,2],[[30,1],"PENDING"],null],[28,[37,2],[[30,1],"ESTABLISHING"],null]],null],[[[11,"svg"],[24,"width","16"],[24,"height","16"],[24,"viewBox","0 0 16 16"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[17,2],[12],[1,"\\n "],[10,"path"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M8 1.5C6.14798 1.5 4.47788 2.27358 3.29301 3.51732C3.0073 3.81723 2.53256 3.82874 2.23266 3.54303C1.93275 3.25732 1.92125 2.78258 2.20696 2.48268C3.66316 0.954124 5.72078 0 8 0C10.2792 0 12.3368 0.954124 13.793 2.48268C14.0788 2.78258 14.0672 3.25732 13.7673 3.54303C13.4674 3.82874 12.9927 3.81723 12.707 3.51732C11.5221 2.27358 9.85202 1.5 8 1.5ZM1.23586 5.27899C1.63407 5.39303 1.86443 5.80828 1.75039 6.20649C1.58749 6.7753 1.5 7.3768 1.5 8C1.5 11.0649 3.62199 13.636 6.47785 14.321C6.88064 14.4176 7.12885 14.8224 7.03225 15.2252C6.93565 15.628 6.53081 15.8762 6.12802 15.7796C2.61312 14.9366 0 11.7744 0 8C0 7.23572 0.107387 6.49527 0.30836 5.79351C0.422401 5.39531 0.837659 5.16494 1.23586 5.27899ZM14.7641 5.27899C15.1623 5.16494 15.5776 5.39531 15.6916 5.79351C15.8926 6.49527 16 7.23572 16 8C16 11.7744 13.3869 14.9366 9.87199 15.7796C9.4692 15.8762 9.06436 15.628 8.96775 15.2252C8.87115 14.8224 9.11936 14.4176 9.52215 14.321C12.378 13.636 14.5 11.0649 14.5 8C14.5 7.3768 14.4125 6.7753 14.2496 6.20649C14.1356 5.80828 14.3659 5.39303 14.7641 5.27899Z"],[14,"fill","#3B3D45"],[12],[13],[1,"\\n "],[10,"path"],[14,"opacity","0.2"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M8 4.5C6.067 4.5 4.5 6.067 4.5 8C4.5 9.933 6.067 11.5 8 11.5C9.933 11.5 11.5 9.933 11.5 8C11.5 6.067 9.933 4.5 8 4.5ZM3 8C3 5.23858 5.23858 3 8 3C10.7614 3 13 5.23858 13 8C13 10.7614 10.7614 13 8 13C5.23858 13 3 10.7614 3 8Z"],[14,"fill","#000001"],[12],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null],[41,[28,[37,2],[[30,1],"ACTIVE"],null],[[[11,"svg"],[24,"width","16"],[24,"height","16"],[24,"viewBox","0 0 16 16"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[17,2],[12],[1,"\\n "],[10,"path"],[14,"d","M14.7803 4.28033C15.0732 3.98744 15.0732 3.51256 14.7803 3.21967C14.4874 2.92678 14.0126 2.92678 13.7197 3.21967L5.75 11.1893L2.28033 7.71967C1.98744 7.42678 1.51256 7.42678 1.21967 7.71967C0.926777 8.01256 0.926777 8.48744 1.21967 8.78033L5.21967 12.7803C5.51256 13.0732 5.98744 13.0732 6.28033 12.7803L14.7803 4.28033Z"],[14,"fill","#00781E"],[12],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null],[41,[28,[37,2],[[30,1],"FAILING"],null],[[[11,"svg"],[24,"width","16"],[24,"height","16"],[24,"viewBox","0 0 16 16"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[17,2],[12],[1,"\\n "],[10,"path"],[14,"d","M12.7803 4.28033C13.0732 3.98744 13.0732 3.51256 12.7803 3.21967C12.4874 2.92678 12.0126 2.92678 11.7197 3.21967L8 6.93934L4.28033 3.21967C3.98744 2.92678 3.51256 2.92678 3.21967 3.21967C2.92678 3.51256 2.92678 3.98744 3.21967 4.28033L6.93934 8L3.21967 11.7197C2.92678 12.0126 2.92678 12.4874 3.21967 12.7803C3.51256 13.0732 3.98744 13.0732 4.28033 12.7803L8 9.06066L11.7197 12.7803C12.0126 13.0732 12.4874 13.0732 12.7803 12.7803C13.0732 12.4874 13.0732 12.0126 12.7803 11.7197L9.06066 8L12.7803 4.28033Z"],[14,"fill","#C00005"],[12],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null],[1,"\\n"],[41,[28,[37,2],[[30,1],"TERMINATED"],null],[[[11,"svg"],[24,"width","16"],[24,"height","17"],[24,"viewBox","0 0 16 17"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[17,2],[12],[1,"\\n "],[10,"path"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M3.13889 2.55566C2.78604 2.55566 2.5 2.8417 2.5 3.19455V12.9168C2.5 13.2696 2.78604 13.5557 3.13889 13.5557H12.8611C13.214 13.5557 13.5 13.2696 13.5 12.9168V3.19455C13.5 2.8417 13.214 2.55566 12.8611 2.55566H3.13889ZM1 3.19455C1 2.01328 1.95761 1.05566 3.13889 1.05566H12.8611C14.0424 1.05566 15 2.01328 15 3.19455V12.9168C15 14.0981 14.0424 15.0557 12.8611 15.0557H3.13889C1.95761 15.0557 1 14.0981 1 12.9168V3.19455ZM4.71967 4.77533C5.01256 4.48244 5.48744 4.48244 5.78033 4.77533L8 6.995L10.2197 4.77533C10.5126 4.48244 10.9874 4.48244 11.2803 4.77533C11.5732 5.06823 11.5732 5.5431 11.2803 5.83599L9.06066 8.05566L11.2803 10.2753C11.5732 10.5682 11.5732 11.0431 11.2803 11.336C10.9874 11.6289 10.5126 11.6289 10.2197 11.336L8 9.11632L5.78033 11.336C5.48744 11.6289 5.01256 11.6289 4.71967 11.336C4.42678 11.0431 4.42678 10.5682 4.71967 10.2753L6.93934 8.05566L4.71967 5.83599C4.42678 5.5431 4.42678 5.06823 4.71967 4.77533Z"],[14,"fill","#3B3D45"],[12],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null],[41,[28,[37,2],[[30,1],"UNDEFINED"],null],[[[11,"svg"],[24,"width","16"],[24,"height","16"],[24,"viewBox","0 0 16 16"],[24,"fill","none"],[24,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[17,2],[12],[1,"\\n"],[10,"path"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M8.1969 4.52275C7.83582 4.45975 7.46375 4.52849 7.14594 4.7185C6.82781 4.9087 6.58324 5.20915 6.45878 5.56907C6.32341 5.96054 5.89632 6.16815 5.50485 6.03278C5.11338 5.89741 4.90577 5.47032 5.04114 5.07886C5.27962 4.3892 5.75141 3.80461 6.37621 3.43106C7.00132 3.05732 7.73786 2.91999 8.45475 3.04508C9.17148 3.17015 9.81887 3.54878 10.2837 4.11048C10.7481 4.67171 11.0009 5.37994 11 6.10959C10.9999 6.59724 10.9078 7.01534 10.7254 7.37628C10.5432 7.73694 10.2936 7.9952 10.0464 8.19341C9.85239 8.34899 9.63602 8.48431 9.46464 8.59149C9.431 8.61253 9.39909 8.63248 9.36942 8.65129C9.16778 8.77916 9.02667 8.87887 8.91689 8.99055C8.81461 9.0946 8.77388 9.18682 8.75706 9.23816C8.74978 9.26038 8.74659 9.27628 8.74537 9.28347C8.72786 9.68216 8.3991 10 7.9961 10C7.58189 10 7.2461 9.66422 7.2461 9.25C7.24626 9.08689 7.28103 8.92552 7.33163 8.77109C7.41129 8.52797 7.56353 8.22758 7.84718 7.93902C8.0857 7.69637 8.35223 7.52016 8.56613 7.38452C8.61117 7.35596 8.65343 7.32942 8.69337 7.30434C8.8616 7.1987 8.98859 7.11896 9.10803 7.02318C9.24074 6.91676 9.32751 6.81683 9.38666 6.69978C9.44562 6.5831 9.49996 6.4041 9.49996 6.10918L9.49996 6.10808C9.50052 5.72536 9.36781 5.35654 9.12803 5.06677C8.88848 4.77728 8.55813 4.58578 8.1969 4.52275Z"],[14,"fill","#3B3D45"],[12],[13],[1,"\\n"],[10,"path"],[14,"d","M8 11C7.44772 11 7 11.4477 7 12C7 12.5523 7.44772 13 8 13H8.00667C8.55895 13 9.00667 12.5523 9.00667 12C9.00667 11.4477 8.55895 11 8.00667 11H8Z"],[14,"fill","#3B3D45"],[12],[13],[1,"\\n"],[10,"path"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8ZM8 1.5C4.41015 1.5 1.5 4.41015 1.5 8C1.5 11.5899 4.41015 14.5 8 14.5C11.5899 14.5 14.5 11.5899 14.5 8C14.5 4.41015 11.5899 1.5 8 1.5Z"],[14,"fill","#3B3D45"],[12],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null],[1,"\\n"],[41,[28,[37,2],[[30,1],"DELETING"],null],[[[10,"svg"],[14,"width","16"],[14,"height","16"],[14,"viewBox","0 0 16 16"],[14,"fill","none"],[14,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[12],[1,"\\n"],[10,"path"],[14,"opacity","0.2"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M8 1.5C4.41015 1.5 1.5 4.41015 1.5 8C1.5 11.5899 4.41015 14.5 8 14.5C11.5899 14.5 14.5 11.5899 14.5 8C14.5 4.41015 11.5899 1.5 8 1.5ZM0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8Z"],[14,"fill","#000001"],[12],[13],[1,"\\n"],[10,"path"],[14,"fill-rule","evenodd"],[14,"clip-rule","evenodd"],[14,"d","M7.25 0.75C7.25 0.335786 7.58579 0 8 0C12.4183 0 16 3.58172 16 8C16 8.41421 15.6642 8.75 15.25 8.75C14.8358 8.75 14.5 8.41421 14.5 8C14.5 4.41015 11.5899 1.5 8 1.5C7.58579 1.5 7.25 1.16421 7.25 0.75Z"],[14,"fill","#3B3D45"],[12],[13],[1,"\\n"],[13],[1,"\\n"]],[]],null]],["@state","&attrs"],false,["if","or","eq"]]',moduleName:"consul-ui/components/peerings/badge/icon/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/peerings/badge/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"9gyI6t3m",block:'[[[1,"\\n"],[41,[30,1,["State"]],[[[1," "],[11,0],[16,0,[29,["peerings-badge ",[28,[37,1],[[30,1,["State"]]],null]]]],[4,[38,2],[[30,0,["tooltip"]]],null],[12],[1,"\\n "],[8,[39,3],null,[["@state"],[[29,[[30,1,["State"]]]]]],null],[1,"\\n "],[10,1],[14,0,"peerings-badge__text"],[12],[1,[28,[35,4],[[28,[37,1],[[30,1,["State"]]],null]],null]],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],["@peering"],false,["if","lowercase","tooltip","peerings/badge/icon","capitalize"]]',moduleName:"consul-ui/components/peerings/badge/index.hbs",isStrictMode:!1}),i={ACTIVE:{tooltip:"This peer connection is currently active."},PENDING:{tooltip:"This peering connection has not been established yet."},ESTABLISHING:{tooltip:"This peering connection is in the process of being established."},FAILING:{tooltip:"This peering connection has some intermittent errors (usually network related). It will continue to retry. "},DELETING:{tooltip:"This peer is in the process of being deleted."},TERMINATED:{tooltip:"Someone in the other peer may have deleted this peering connection."},UNDEFINED:{tooltip:""}} +class o extends l.default{get styles(){const{peering:{State:e}}=this.args +return i[e]}get tooltip(){return this.styles.tooltip}}e.default=o,(0,t.setComponentTemplate)(r,o)})),define("consul-ui/components/peerings/provider/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/application","consul-ui/components/tab-nav"],(function(e,t,n,l,r,i,o){var a,u,s +function c(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function d(e){for(var t=1;tnew o.Tab(d(d({},e),{},{currentRouteName:t.currentRouteName,owner:n}))))}},u=m(a.prototype,"router",[r.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s=m(a.prototype,"intl",[r.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a) +e.default=b,(0,t.setComponentTemplate)(h,b)})),define("consul-ui/components/policy-form/index",["exports","@ember/component","@ember/template-factory","consul-ui/components/form-component/index","@ember/object"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i=(0,n.createTemplateFactory)({id:"Hx5i6L86",block:'[[[1,"\\n"],[18,6,null],[1,"\\n"],[11,"fieldset"],[24,0,"policy-form"],[16,"disabled",[52,[28,[37,2],[[28,[37,3],["write policy"],[["item"],[[33,4]]]]],null],"disabled"]],[17,1],[12],[1,"\\n"],[6,[39,5],null,[["name"],["template"]],[["default","else"],[[[],[]],[[[1," "],[10,"header"],[12],[1,"\\n Policy"],[1,[52,[33,6]," or identity?",""]],[1,"\\n "],[13],[1,"\\n"],[41,[33,6],[[[1," "],[10,2],[12],[1,"\\n Identities are default policies with configurable names. They save you some time and effort you\'re using Consul for Connect features.\\n "],[13],[1,"\\n"],[1," "],[10,0],[14,"role","radiogroup"],[15,0,[52,[33,4,["error","Type"]]," has-error"]],[12],[1,"\\n"],[42,[28,[37,8],[[28,[37,8],[[33,9]],null]],null],null,[[[1," "],[10,"label"],[12],[1,"\\n "],[10,1],[12],[1,[30,2,["name"]]],[13],[1,"\\n "],[10,"input"],[15,3,[28,[37,10],[[33,11],"[template]"],null]],[15,2,[30,2,["template"]]],[15,"checked",[28,[37,12],[[33,4,["template"]],[30,2,["template"]]],null]],[15,"onchange",[28,[37,13],[[30,0],[28,[37,14],[[28,[37,15],[[33,4],"template"],null]],null]],[["value"],["target.value"]]]],[14,4,"radio"],[12],[13],[1,"\\n "],[13],[1,"\\n"]],[2]],null],[1," "],[13],[1,"\\n"]],[]],[[[1," "],[10,"input"],[15,3,[28,[37,10],[[33,11],"[template]"],null]],[14,2,""],[14,4,"hidden"],[12],[13],[1,"\\n"]],[]]]],[]]]]],[1," "],[10,"label"],[15,0,[29,["type-text",[52,[28,[37,16],[[33,4,["error","Name"]],[28,[37,2],[[33,4,["isPristine"]]],null]],null]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Name"],[13],[1,"\\n "],[10,"input"],[15,2,[33,4,["Name"]]],[15,3,[29,[[36,11],"[Name]"]]],[14,"autofocus","autofocus"],[15,"oninput",[28,[37,13],[[30,0],"change"],null]],[14,4,"text"],[12],[13],[1,"\\n "],[10,"em"],[12],[1,"\\n Maximum 128 characters. May only include letters (uppercase and/or lowercase) and/or numbers. Must be unique.\\n "],[13],[1,"\\n"],[41,[28,[37,16],[[33,4,["error","Name"]],[28,[37,2],[[33,4,["isPristine"]]],null]],null],[[[1," "],[10,"strong"],[12],[1,[33,4,["error","Name","validation"]]],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[10,"label"],[14,"for",""],[14,0,"type-text"],[12],[1,"\\n"],[41,[28,[37,12],[[33,4,["template"]],"service-identity"],null],[[[1," "],[8,[39,17],null,[["@readonly","@name","@syntax","@oninput"],[true,[28,[37,10],[[33,11],"[Rules]"],null],"hcl",[28,[37,13],[[30,0],"change",[28,[37,10],[[33,11],"[Rules]"],null]],null]]],[["label","content"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,18],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]],[[[8,[39,19],null,[["@nspace","@partition","@name"],[[99,20,["@nspace"]],[99,21,["@partition"]],[33,4,["Name"]]]],null]],[]]]]],[1,"\\n"]],[]],[[[41,[28,[37,12],[[33,4,["template"]],"node-identity"],null],[[[1," "],[8,[39,17],null,[["@readonly","@name","@syntax","@oninput"],[true,[28,[37,10],[[33,11],"[Rules]"],null],"hcl",[28,[37,13],[[30,0],"change",[28,[37,10],[[33,11],"[Rules]"],null]],null]]],[["label","content"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,18],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]],[[[8,[39,22],null,[["@name","@partition"],[[33,4,["Name"]],[99,21,["@partition"]]]],null]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,17],null,[["@syntax","@class","@name","@value","@onkeyup"],["hcl",[52,[33,4,["error","Rules"]],"error"],[28,[37,10],[[33,11],"[Rules]"],null],[33,4,["Rules"]],[28,[37,13],[[30,0],"change",[28,[37,10],[[33,11],"[Rules]"],null]],null]]],[["label"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,18],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[33,4,["error","Rules"]],[[[1," "],[10,"strong"],[12],[1,[33,4,["error","Rules","validation"]]],[13],[1,"\\n"]],[]],null]],[]]]],[]]],[1," "],[13],[1,"\\n"],[41,[28,[37,12],[[33,4,["template"]],"node-identity"],null],[[[1,"\\n "],[8,[39,23],null,[["@src","@onchange"],[[28,[37,24],["/*/*/*/datacenters"],null],[28,[37,13],[[30,0],[28,[37,25],[[33,26]],null]],[["value"],["data"]]]]],null],[1,"\\n "],[10,"label"],[14,0,"type-select"],[12],[1,"\\n "],[10,1],[12],[1,"Datacenter"],[13],[1,"\\n "],[8,[39,27],null,[["@options","@searchField","@selected","@searchPlaceholder","@onChange"],[[28,[37,28],["Name",[33,26]],null],"Name",[28,[37,29],[[33,4,["Datacenter"]],[33,30]],null],"Type a datacenter name",[28,[37,13],[[30,0],"change","Datacenter"],null]]],[["default"],[[[[1,"\\n "],[1,[30,3]],[1,"\\n "]],[3]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[41,[28,[37,12],[[28,[37,29],[[33,21],"default"],null],"default"],null],[[[1," "],[10,0],[14,0,"type-toggle"],[12],[1,"\\n "],[10,1],[12],[1,"Valid datacenters"],[13],[1,"\\n "],[10,"label"],[12],[1,"\\n "],[10,"input"],[15,3,[29,[[36,11],"[isScoped]"]]],[15,"checked",[52,[28,[37,2],[[33,31]],null],"checked"]],[15,"onchange",[28,[37,13],[[30,0],"change"],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,1],[12],[1,"All"],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[33,31],[[[1," "],[8,[39,23],null,[["@src","@onchange"],[[28,[37,24],["/*/*/*/datacenters"],null],[28,[37,13],[[30,0],[28,[37,25],[[33,26]],null]],[["value"],["data"]]]]],null],[1,"\\n\\n "],[10,0],[14,0,"checkbox-group"],[14,"role","group"],[12],[1,"\\n"],[42,[28,[37,8],[[28,[37,8],[[33,26]],null]],null],null,[[[1," "],[10,"label"],[14,0,"type-checkbox"],[12],[1,"\\n "],[10,"input"],[15,3,[29,[[36,11],"[Datacenters]"]]],[15,2,[30,4,["Name"]]],[15,"checked",[52,[28,[37,32],[[30,4,["Name"]],[33,4,["Datacenters"]]],null],"checked"]],[15,"onchange",[28,[37,13],[[30,0],"change"],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,1],[12],[1,[30,4,["Name"]]],[13],[1,"\\n "],[13],[1,"\\n"]],[4]],null],[42,[28,[37,8],[[28,[37,8],[[33,4,["Datacenters"]]],null]],null],null,[[[41,[28,[37,2],[[28,[37,33],["Name",[30,5],[33,26]],null]],null],[[[1," "],[10,"label"],[14,0,"type-checkbox"],[12],[1,"\\n "],[10,"input"],[15,3,[29,[[36,11],"[Datacenters]"]]],[15,2,[30,5]],[14,"checked","checked"],[15,"onchange",[28,[37,13],[[30,0],"change"],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,1],[12],[1,[30,5]],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[5]],null],[1," "],[13],[1,"\\n\\n\\n"]],[]],null]],[]]],[41,[28,[37,12],[[33,4,["template"]],""],null],[[[1," "],[10,"label"],[14,0,"type-text"],[12],[1,"\\n "],[10,1],[12],[1,"Description (Optional)"],[13],[1,"\\n "],[10,"textarea"],[15,3,[29,[[36,11],"[Description]"]]],[15,2,[33,4,["Description"]]],[15,"oninput",[28,[37,13],[[30,0],"change"],null]],[12],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[13],[1,"\\n\\n"]],["&attrs","template","Name","dc","dc","&default"],false,["yield","if","not","can","item","yield-slot","allowIdentity","each","-track-array","templates","concat","name","eq","action","optional","changeset-set","and","code-editor","env","consul/service-identity/template","nspace","partition","consul/node-identity/template","data-source","uri","mut","datacenters","power-select","map-by","or","dc","isScoped","includes","find-by"]]',moduleName:"consul-ui/components/policy-form/index.hbs",isStrictMode:!1}) +var o=(0,t.setComponentTemplate)(i,l.default.extend({type:"policy",name:"policy",allowIdentity:!0,classNames:["policy-form"],isScoped:!1,init:function(){this._super(...arguments),(0,r.set)(this,"isScoped",(0,r.get)(this,"item.Datacenters.length")>0),this.templates=[{name:"Policy",template:""},{name:"Service Identity",template:"service-identity"},{name:"Node Identity",template:"node-identity"}]},actions:{change:function(e){try{this._super(...arguments)}catch(t){const e=this.isScoped +if("policy[isScoped]"===t.target.name)e?((0,r.set)(this,"previousDatacenters",(0,r.get)(this.item,"Datacenters")),(0,r.set)(this.item,"Datacenters",null)):((0,r.set)(this.item,"Datacenters",this.previousDatacenters),(0,r.set)(this,"previousDatacenters",null)),(0,r.set)(this,"isScoped",!e) +else this.onerror(t) +this.onchange({target:this.form})}}}})) +e.default=o})),define("consul-ui/components/policy-selector/index",["exports","@ember/component","@ember/template-factory","consul-ui/components/child-selector/index","@ember/object","@ember/service"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"Cn++QMVx",block:'[[[1,"\\n"],[8,[39,0],[[17,1]],[["@disabled","@repo","@dc","@partition","@nspace","@type","@placeholder","@items"],[[99,1,["@disabled"]],[99,2,["@repo"]],[99,3,["@dc"]],[99,4,["@partition"]],[99,5,["@nspace"]],"policy","Search for policy",[99,6,["@items"]]]],[["default"],[[[[1,"\\n "],[18,11,null],[1,"\\n "],[8,[39,8],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Apply an existing policy\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["create"]],[["default"],[[[[1,"\\n"],[6,[39,9],null,[["name"],["trigger"]],[["default","else"],[[[[1," "],[18,11,null],[1,"\\n"]],[]],[[[1," "],[8,[39,10],[[24,0,"type-dialog"],[4,[38,11],["click",[28,[37,12],[[30,0],[30,0,["openModal"]]],null]],null]],[["@text","@size","@color","@icon"],["Create new policy","small","tertiary","plus"]],null],[1,"\\n"],[1," "],[8,[39,13],[[24,1,"new-policy"]],[["@onopen","@aria"],[[28,[37,12],[[30,0],"open"],null],[28,[37,14],null,[["label"],["New Policy"]]]]],[["default"],[[[[1,"\\n "],[8,[39,15],null,[["@target","@name","@value"],[[30,0],"modal",[30,2]]],null],[1,"\\n "],[8,[39,8],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"New Policy"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[8,[39,16],null,[["@form","@nspace","@partition","@dc","@allowServiceIdentity"],[[99,17,["@form"]],[99,5,["@nspace"]],[99,4,["@partition"]],[99,3,["@dc"]],[99,18,["@allowServiceIdentity"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,19],null,null,[["default"],[[[[1,"\\n "],[8,[39,10],[[16,"onclick",[28,[37,20],[[30,0,["save"]],[33,21],[33,6],[28,[37,22],[[28,[37,12],[[30,0],[30,3]],null],[28,[37,12],[[30,0],"reset"],null]],null]],null]],[16,"disabled",[52,[28,[37,24],[[33,21,["isSaving"]],[33,21,["isPristine"]],[33,21,["isInvalid"]]],null],"disabled"]],[24,4,"submit"]],[["@isLoading","@text"],[[33,21,["isSaving"]],"Create and apply"]],null],[1,"\\n "],[8,[39,10],[[16,"disabled",[52,[33,21,["isSaving"]],"disabled"]],[24,4,"reset"],[4,[38,11],["click",[28,[37,12],[[30,0],[28,[37,22],[[28,[37,12],[[30,0],[30,3]],null],[28,[37,12],[[30,0],"reset"],null]],null]],null]],null]],[["@color","@text"],["secondary","Cancel"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[]]]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["option"]],[["default"],[[[[1,"\\n "],[1,[30,4,["Name"]]],[1,"\\n "]],[4]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["set"]],[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@onchange","@items"],[[28,[37,12],[[30,0],"open"],null],[28,[37,26],["CreateTime:desc","Name:asc",[33,6]],null]]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[12],[1,"Name"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["row"]],[["default"],[[[[1,"\\n "],[10,"td"],[15,0,[28,[37,27],[[30,5]],null]],[12],[1,"\\n"],[41,[30,5,["ID"]],[[[1," "],[10,3],[15,6,[28,[37,28],["dc.acls.policies.edit",[30,5,["ID"]]],null]],[12],[1,[30,5,["Name"]]],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[15,3,[30,5,["Name"]]],[12],[1,[30,5,["Name"]]],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["details"]],[["default"],[[[[1,"\\n"],[41,[28,[37,29],[[30,5,["template"]],""],null],[[[1," "],[8,[39,30],null,[["@src","@onchange","@loading"],[[28,[37,31],["/${partition}/${nspace}/${dc}/policy/${id}",[28,[37,14],null,[["partition","nspace","dc","id"],[[33,4],[33,5],[33,3],[30,5,["ID"]]]]]],null],[28,[37,12],[[30,0],[28,[37,32],[[33,33]],null]],[["value"],["data"]]],"lazy"]],null],[1,"\\n"]],[]],null],[41,[28,[37,29],[[30,5,["template"]],"node-identity"],null],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Datacenter:"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,5,["Datacenter"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Datacenters:"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,34],[", ",[28,[37,35],[[28,[37,24],[[33,33],[30,5]],null]],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]]],[1," "],[10,"label"],[14,0,"type-text"],[12],[1,"\\n"],[41,[28,[37,29],[[30,5,["template"]],"service-identity"],null],[[[1," "],[8,[39,36],null,[["@syntax","@readonly"],["hcl",true]],[["label","content"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,37],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[39,38],null,[["@nspace","@partition","@name"],[[99,5,["@nspace"]],[99,4,["@partition"]],[30,5,["Name"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[41,[28,[37,29],[[30,5,["template"]],"node-identity"],null],[[[1," "],[8,[39,36],null,[["@syntax","@readonly"],["hcl",true]],[["label","content"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,37],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[39,39],null,[["@name","@partition"],[[30,5,["Name"]],[99,4,["@partition"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,36],null,[["@syntax","@readonly","@value"],["hcl",true,[28,[37,24],[[33,33,["Rules"]],[30,5,["Rules"]]],null]]],[["label"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,37],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]],[]]],[1," "],[13],[1,"\\n"],[41,[28,[37,40],[[33,1]],null],[[[1," "],[10,0],[12],[1,"\\n "],[8,[39,41],null,[["@message"],["Are you sure you want to remove this policy from this token?"]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,10],[[4,[38,12],[[30,0],[30,7],"remove",[30,5],[33,6]],null]],[["@text","@color","@size"],["Remove","critical","small"]],null],[1,"\\n "]],[7]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[30,10]],[1,"\\n "],[13],[1,"\\n "],[8,[39,19],null,null,[["default"],[[[[1,"\\n "],[8,[39,10],[[4,[38,12],[[30,0],[30,8]],null]],[["@text","@color","@size"],["Confirm remove","critical","small"]],null],[1,"\\n "],[8,[39,10],[[4,[38,12],[[30,0],[30,9]],null]],[["@text","@color","@size"],["Cancel","secondary","small"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[8,9,10]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[5,6]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n"]],[]]]]],[1,"\\n"]],["&attrs","modal","close","option","item","index","confirm","execute","cancel","message","&default"],false,["child-selector","disabled","repo","dc","partition","nspace","items","yield","block-slot","yield-slot","hds/button","on","action","modal-dialog","hash","ref","policy-form","form","allowServiceIdentity","hds/button-set","perform","item","queue","if","or","tabular-details","sort-by","policy/typeof","href-to","eq","data-source","uri","mut","loadedItem","join","policy/datacenters","code-editor","env","consul/service-identity/template","consul/node-identity/template","not","confirmation-dialog"]]',moduleName:"consul-ui/components/policy-selector/index.hbs",isStrictMode:!1}),a="Invalid Policy: A Policy with Name" +var u=(0,t.setComponentTemplate)(o,l.default.extend({repo:(0,i.inject)("repository/policy"),name:"policy",type:"policy",allowIdentity:!0,classNames:["policy-selector"],init:function(){this._super(...arguments) +const e=this.source +e&&this._listeners.add(e,{save:e=>{this.save.perform(...e.data)}})},reset:function(e){this._super(...arguments),(0,r.set)(this,"isScoped",!1)},refreshCodeEditor:function(e,t){this.dom.component(".code-editor",t).didAppear()},error:function(e){const t=this.item,n=e.error +if(void 0===n.errors)throw n +{const e=n.errors[0] +let l="Rules",r=e.detail +switch(!0){case 0===r.indexOf("Failed to parse ACL rules"):case 0===r.indexOf("Invalid service policy"):l="Rules",r=e.detail +break +case 0===r.indexOf(a):l="Name",r=r.substr(a.indexOf(":")+1)}l&&t.addError(l,r)}},openModal:function(){const{modal:e}=this +e&&e.open()},actions:{open:function(e){this.refreshCodeEditor(e,e.target.parentElement)}}})) +e.default=u})),define("consul-ui/components/popover-menu/index",["exports","@ember/component","@ember/template-factory","@ember/service","block-slots","@ember/object"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"gOcgCjMn",block:'[[[1,"\\n"],[18,11,null],[1,"\\n"],[11,0],[24,0,"popover-menu"],[17,1],[12],[1,"\\n "],[8,[39,1],null,[["@keyboardAccess"],[[99,2,["@keyboardAccess"]]]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,4],null,[["MenuItem","MenuSeparator"],[[50,"popover-menu/menu-item",0,null,[["menu"],[[28,[37,4],null,[["addSubmenu","removeSubmenu","confirm","clickTrigger","keypressClick"],[[28,[37,6],[[30,0],"addSubmenu"],null],[28,[37,6],[[30,0],"removeSubmenu"],null],[28,[37,7],["popover-menu-",[33,8],"-"],null],[30,0,["toggle","click"]],[30,4]]]]]]],[50,"popover-menu/menu-separator",0,null,null]]]]],[[[44,[[28,[37,4],null,[["toggle"],[[30,0,["toggle","click"]]]]]],[[[1,"\\n "],[8,[39,9],null,[["@checked","@onchange"],[[52,[33,2],[30,5,["expanded"]],[33,11]],[28,[37,12],[[30,2],[28,[37,6],[[30,0],"change"],null]],null]]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@target","@name","@value"],[[30,0],"toggle",[30,8]]],null],[1,"\\n "],[10,"button"],[14,"aria-haspopup","menu"],[15,"onkeydown",[30,3]],[15,"onclick",[30,0,["toggle","click"]]],[15,1,[30,5,["labelledBy"]]],[15,"aria-controls",[30,5,["controls"]]],[14,4,"button"],[12],[1,"\\n "],[8,[39,14],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n "],[18,11,[[30,6],[30,7]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "]],[8]]]]],[1,"\\n\\n "],[8,[39,15],[[16,1,[30,5,["controls"]]],[16,"aria-labelledby",[30,5,["labelledBy"]]],[16,"aria-expanded",[30,5,["expanded"]]]],[["@position"],[[99,16,["@position"]]]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@target","@name","@value"],[[30,0],"menu",[30,9]]],null],[1,"\\n "],[8,[39,17],null,[["@name"],["controls"]],[["default"],[[[[1,"\\n "],[10,"input"],[15,1,[28,[37,7],["popover-menu-",[33,8],"-"],null]],[14,4,"checkbox"],[12],[13],[1,"\\n"],[42,[28,[37,19],[[28,[37,19],[[33,20]],null]],null],null,[[[1," "],[10,"input"],[15,1,[28,[37,7],["popover-menu-",[33,8],"-",[30,10]],null]],[15,"onchange",[30,9,["change"]]],[14,4,"checkbox"],[12],[13],[1,"\\n"]],[10]],null],[1," "]],[]]]]],[1,"\\n"],[41,[33,21],[[[1," "],[8,[39,17],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[18,11,[[30,6],[30,7]]],[1,"\\n "],[6,[39,14],null,[["name"],["header"]],[["default","else"],[[[],[]],[[],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,17],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[8,[39,14],null,[["@name","@params"],["menu",[28,[37,22],[[28,[37,7],["popover-menu-",[33,8],"-"],null],[33,23],[30,4],[30,0,["toggle","click"]]],null]]],[["default"],[[[[1,"\\n "],[18,11,[[30,6],[30,7]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n\\n"]],[7]]]],[6]]],[1,"\\n "]],[2,3,4,5]]]]],[1,"\\n"],[13]],["&attrs","change","keypress","keypressClick","aria","components","api","toggle","menu","sub","&default"],false,["yield","aria-menu","keyboardAccess","let","hash","component","action","concat","guid","toggle-button","if","expanded","queue","ref","yield-slot","menu-panel","position","block-slot","each","-track-array","submenus","hasHeader","block-params","send"]]',moduleName:"consul-ui/components/popover-menu/index.hbs",isStrictMode:!1}) +var a=(0,t.setComponentTemplate)(o,t.default.extend(r.default,{tagName:"",dom:(0,l.inject)("dom"),expanded:!1,keyboardAccess:!0,onchange:function(){},position:"",init:function(){this._super(...arguments),this.guid=this.dom.guid(this),this.submenus=[]},willRender:function(){(0,i.set)(this,"hasHeader",this._isRegistered("header"))},actions:{addSubmenu:function(e){(0,i.set)(this,"submenus",this.submenus.concat(e))},removeSubmenu:function(e){const t=this.submenus.indexOf(e);-1!==t&&(this.submenus.splice(t,1),(0,i.set)(this,"submenus",this.submenus))},change:function(e){e.target.checked||[...this.dom.elements(`[id^=popover-menu-${this.guid}]`)].forEach((function(e){e.checked=!1})),this.onchange(e)},send:function(){this.sendAction(...arguments)}}})) +e.default=a})),define("consul-ui/components/popover-menu/menu-item/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object","block-slots"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=(0,n.createTemplateFactory)({id:"9sIg+bnI",block:'[[[1,"\\n"],[18,3,null],[1,"\\n"],[11,"li"],[24,"role","none"],[17,1],[12],[1,"\\n"],[41,[33,2],[[[1," "],[10,"label"],[15,"for",[28,[37,3],[[33,4,["confirm"]],[33,5]],null]],[14,"role","menuitem"],[14,"tabindex","-1"],[15,"onkeypress",[33,4,["keypressClick"]]],[12],[1,"\\n "],[8,[39,6],null,[["@name"],["label"]],[["default"],[[[[18,3,null]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,"role","menu"],[12],[1,"\\n "],[8,[39,6],null,[["@name","@params"],["confirmation",[28,[37,7],[[50,"confirmation-alert",0,null,[["onclick","name"],[[28,[37,9],[[28,[37,10],[[30,0],[33,4,["clickTrigger"]]],null],[28,[37,10],[[30,0],[33,11]],null]],null],[28,[37,3],[[33,4,["confirm"]],[33,5]],null]]]]],null]]],[["default"],[[[[18,3,null]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],[[[41,[33,12],[[[44,[[28,[37,14],[[33,12],"://"],null]],[[[1," "],[10,3],[14,"role","menuitem"],[14,"tabindex","-1"],[15,"onclick",[28,[37,10],[[30,0],[33,4,["clickTrigger"]]],null]],[15,6,[36,12]],[15,"target",[52,[30,2],"_blank"]],[15,"rel",[52,[30,2],"noopener noreferrer"]],[12],[1,"\\n "],[8,[39,6],null,[["@name"],["label"]],[["default"],[[[[1,"\\n "],[18,3,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[2]]]],[]],[[[10,"button"],[14,"role","menuitem"],[15,"aria-selected",[52,[33,15],"true"]],[14,"tabindex","-1"],[15,"onclick",[28,[37,9],[[28,[37,10],[[30,0],[28,[37,16],[[30,0,["onclick"]],[28,[37,17],null,null]],null]],null],[28,[37,10],[[30,0],[52,[30,0,["close"]],[33,4,["clickTrigger"]],[28,[37,17],null,null]]],null]],null]],[14,4,"button"],[12],[1,"\\n "],[8,[39,6],null,[["@name"],["label"]],[["default"],[[[[1,"\\n "],[18,3,null],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[]]]],[]]],[13],[1,"\\n\\n"]],["&attrs","external","&default"],false,["yield","if","hasConfirmation","concat","menu","guid","yield-slot","block-params","component","queue","action","onclick","href","let","string-includes","selected","or","noop"]]',moduleName:"consul-ui/components/popover-menu/menu-item/index.hbs",isStrictMode:!1}) +var a=(0,t.setComponentTemplate)(o,t.default.extend(i.default,{tagName:"",dom:(0,l.inject)("dom"),init:function(){this._super(...arguments),this.guid=this.dom.guid(this)},didInsertElement:function(){this._super(...arguments),this.menu.addSubmenu(this.guid)},didDestroyElement:function(){this._super(...arguments),this.menu.removeSubmenu(this.guid)},willRender:function(){this._super(...arguments),(0,r.set)(this,"hasConfirmation",this._isRegistered("confirmation"))}})) +e.default=a})),define("consul-ui/components/popover-menu/menu-separator/index",["exports","@ember/component","@ember/template-factory","block-slots"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"Mhlwh5rK",block:'[[[1,"\\n"],[18,1,null],[1,"\\n"],[10,"li"],[14,"role","separator"],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[18,1,null]],[]]]]],[1,"\\n"],[13],[1,"\\n"]],["&default"],false,["yield","yield-slot"]]',moduleName:"consul-ui/components/popover-menu/menu-separator/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,t.default.extend(l.default,{tagName:""})) +e.default=i})),define("consul-ui/components/popover-select/index",["exports","@ember/component","@ember/template-factory","@ember/service","block-slots"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i=(0,n.createTemplateFactory)({id:"JjNimTr5",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"popover-select"],[17,1]],[["@position"],[[28,[37,1],[[33,2],"left"],null]]],[["default"],[[[[1,"\\n "],[18,6,null],[1,"\\n"],[44,[[50,"popover-select/optgroup",0,null,[["components"],[[30,2]]]],[50,"popover-select/option",0,null,[["select","components","onclick"],[[30,0],[30,2],[28,[37,6],[[28,[37,7],[[30,0],"click"],null],[52,[33,9],[28,[37,10],null,null],[30,3,["toggle"]]]],null]]]]],[[[1," "],[8,[39,11],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@name"],["selected"]],[["default"],[[[[1,"\\n "],[18,6,[[28,[37,13],null,[["Optgroup","Option"],[[30,4],[30,5]]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,11],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@name"],["options"]],[["default"],[[[[1,"\\n "],[18,6,[[28,[37,13],null,[["Optgroup","Option"],[[30,4],[30,5]]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[4,5]]]],[2,3]]]]],[1,"\\n"]],["&attrs","components","menu","Optgroup","Option","&default"],false,["popover-menu","or","position","yield","let","component","pipe","action","if","multiple","noop","block-slot","yield-slot","hash"]]',moduleName:"consul-ui/components/popover-select/index.hbs",isStrictMode:!1}) +var o=(0,t.setComponentTemplate)(i,t.default.extend(r.default,{tagName:"",dom:(0,l.inject)("dom"),multiple:!1,required:!1,onchange:function(){},addOption:function(e){void 0===this._options&&(this._options=new Set),this._options.add(e)},removeOption:function(e){this._options.delete(e)},actions:{click:function(e,t){if(this.multiple){if(e.selected&&this.required){if(![...this._options].find((t=>t!==e&&t.selected)))return t}}else{if(e.selected&&this.required)return t;[...this._options].filter((t=>t!==e)).forEach((e=>{e.selected=!1}))}return e.selected=!e.selected,this.onchange(this.dom.setEventTargetProperties(t,{selected:t=>e.args.value,selectedItems:e=>[...this._options].filter((e=>e.selected)).map((e=>e.args.value)).join(",")})),t}}})) +e.default=o})),define("consul-ui/components/popover-select/optgroup/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"ErzD41Of",block:'[[[1,"\\n"],[44,[[30,1,["MenuSeparator"]]],[[[8,[30,2],null,null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@name"],["label"]],[["default"],[[[[1,"\\n "],[1,[30,3]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]]],[1,"\\n"],[18,4,null],[1,"\\n"]],[2]]]],["@components","MenuSeparator","@label","&default"],false,["let","block-slot","yield"]]',moduleName:"consul-ui/components/popover-select/optgroup/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/popover-select/option/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object"],(function(e,t,n,l,r,i){var o,a +function u(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const s=(0,n.createTemplateFactory)({id:"SC5oIKM/",block:'[[[1,"\\n"],[44,[[30,1,["MenuItem"]]],[[[1," "],[8,[30,2],[[16,0,[52,[30,0,["selected"]],"is-active"]],[17,3],[4,[38,3],[[30,0,["connect"]]],null],[4,[38,3],[[28,[37,4],[[30,0],"selected",[30,5]],null]],null],[4,[38,5],[[28,[37,4],[[30,0],"selected",[30,5]],null]],null],[4,[38,6],[[30,0,["disconnect"]]],null]],[["@onclick","@selected"],[[28,[37,2],[[30,0],[30,4],[30,0]],null],[30,0,["selected"]]]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["label"]],[["default"],[[[[1,"\\n "],[18,6,null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[2]]]],["@components","MenuItem","&attrs","@onclick","@selected","&default"],false,["let","if","action","did-insert","set","did-update","will-destroy","block-slot","yield"]]',moduleName:"consul-ui/components/popover-select/option/index.hbs",isStrictMode:!1}) +let c=(o=class extends l.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="selected",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}connect(){this.args.select.addOption(this)}disconnect(){this.args.select.removeOption(this)}},a=u(o.prototype,"selected",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u(o.prototype,"connect",[i.action],Object.getOwnPropertyDescriptor(o.prototype,"connect"),o.prototype),u(o.prototype,"disconnect",[i.action],Object.getOwnPropertyDescriptor(o.prototype,"disconnect"),o.prototype),o) +e.default=c,(0,t.setComponentTemplate)(s,c)})),define("consul-ui/components/portal-target",["exports","ember-stargate/components/portal-target"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/portal",["exports","ember-stargate/components/portal"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) +define("consul-ui/components/power-select-multiple-with-create",["exports","ember-power-select-with-create/components/power-select-multiple-with-create"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select-multiple",["exports","ember-power-select/components/power-select-multiple"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select-multiple/trigger",["exports","ember-power-select/components/power-select-multiple/trigger"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select-with-create",["exports","ember-power-select-with-create/components/power-select-with-create"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select-with-create/suggested-option",["exports","ember-power-select-with-create/components/power-select-with-create/suggested-option"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select",["exports","ember-power-select/components/power-select"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/before-options",["exports","ember-power-select/components/power-select/before-options"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/no-matches-message",["exports","ember-power-select/components/power-select/no-matches-message"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/options",["exports","ember-power-select/components/power-select/options"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/placeholder",["exports","ember-power-select/components/power-select/placeholder"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/power-select-group",["exports","ember-power-select/components/power-select/power-select-group"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/search-message",["exports","ember-power-select/components/power-select/search-message"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/power-select/trigger",["exports","ember-power-select/components/power-select/trigger"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/progress/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"v8Ti52Dh",block:'[[[1,"\\n"],[11,0],[24,0,"progress indeterminate"],[24,"role","progressbar"],[17,1],[12],[13],[1,"\\n"]],["&attrs"],false,[]]',moduleName:"consul-ui/components/progress/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/providers/dimension/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object","ember-ref-bucket","@ember/template"],(function(e,t,n,l,r,i,o,a){var u,s,c,d +function p(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function f(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const m=(0,n.createTemplateFactory)({id:"F2wGehPq",block:'[[[1,"\\n"],[11,0],[4,[38,0],["element"],[["debugName","bucket"],["create-ref",[30,0]]]],[4,[38,1],[[30,0,["measureDimensions"]]],null],[12],[1,"\\n "],[1,[28,[35,2],["resize",[30,0,["handleWindowResize"]]],null]],[1,"\\n "],[18,1,[[28,[37,4],null,[["data"],[[30,0,["data"]]]]]]],[1,"\\n"],[13]],["&default"],false,["create-ref","did-insert","on-window","yield","hash"]]',moduleName:"consul-ui/components/providers/dimension/index.hbs",isStrictMode:!1}) +let h=(u=(0,o.ref)("element"),s=class extends l.default{constructor(){super(...arguments),p(this,"element",c,this),p(this,"height",d,this)}get data(){const{height:e,fillRemainingHeightStyle:t}=this +return{height:e,fillRemainingHeightStyle:t}}get fillRemainingHeightStyle(){return(0,a.htmlSafe)(`height: ${this.height}px;`)}get bottomBoundary(){return document.querySelector(this.args.bottomBoundary)||this.footer}get footer(){return document.querySelector('footer[role="contentinfo"]')}measureDimensions(e){const t=this.bottomBoundary.getBoundingClientRect(),n=e.getBoundingClientRect() +this.height=t.top+t.height-n.top}handleWindowResize(){const{element:e}=this +this.measureDimensions(e)}},c=f(s.prototype,"element",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=f(s.prototype,"height",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f(s.prototype,"measureDimensions",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"measureDimensions"),s.prototype),f(s.prototype,"handleWindowResize",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"handleWindowResize"),s.prototype),s) +e.default=h,(0,t.setComponentTemplate)(m,h)})),define("consul-ui/components/providers/search/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"TiH81o1A",block:'[[[1,"\\n"],[18,1,[[28,[37,1],null,[["data"],[[30,0,["data"]]]]]]]],["&default"],false,["yield","hash"]]',moduleName:"consul-ui/components/providers/search/index.hbs",isStrictMode:!1}) +class i extends l.default{get _search(){return this.args.search||""}get items(){const{items:e,searchProperties:t}=this.args,{_search:n}=this +return n.length>0?e.filter((e=>t.reduce(((t,l)=>{const r=-1!==e[l].indexOf(n) +return r?[...t,r]:t}),[]).length>0)):e}get data(){const{items:e}=this +return{items:e}}}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/radio-card/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"UokgMRSB",block:'[[[1,"\\n"],[11,"label"],[17,1],[16,0,[29,["radio-card",[52,[33,1]," checked"]]]],[12],[1,"\\n "],[10,0],[12],[1,"\\n"],[41,[28,[37,2],[[33,3,["length"]],0],null],[[[1," "],[10,"input"],[15,3,[36,4]],[15,2,[36,3]],[15,"checked",[36,1]],[15,"onchange",[28,[37,5],[[30,0],[33,6]],null]],[14,4,"radio"],[12],[13],[1,"\\n"]],[]],[[[1," "],[10,"input"],[15,3,[36,4]],[14,2,""],[15,"checked",[36,1]],[15,"onchange",[28,[37,5],[[30,0],[33,6]],null]],[14,4,"radio"],[12],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[10,0],[12],[1,"\\n "],[18,2,null],[1,"\\n "],[13],[1,"\\n"],[13]],["&attrs","&default"],false,["if","checked","gt","value","name","action","onchange","yield"]]',moduleName:"consul-ui/components/radio-card/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:""})) +e.default=r})),define("consul-ui/components/radio-group/index",["exports","@ember/component","@ember/template-factory","@ember/service"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"wT+5/I+/",block:'[[[1,"\\n"],[10,"fieldset"],[12],[1,"\\n "],[10,0],[14,"role","radiogroup"],[15,1,[29,["radiogroup_",[36,0]]]],[12],[1,"\\n"],[42,[28,[37,2],[[28,[37,2],[[33,3]],null]],null],null,[[[44,[[52,[28,[37,6],[[30,1,["key"]],[27]],null],[30,1,["key"]],[30,1,["value"]]],[28,[37,7],[[30,1,["label"]],[30,1,["value"]]],null]],[[[1," "],[10,"label"],[15,"tabindex",[52,[33,8],"0"]],[15,"onkeydown",[52,[33,8],[28,[37,9],[[30,0],"keydown"],null]]],[15,0,[29,["type-radio value-",[30,2]]]],[12],[1," "],[1,"\\n "],[10,"input"],[15,3,[36,0]],[15,2,[30,2]],[15,"checked",[52,[28,[37,10],[[28,[37,11],[[33,12]],null],[30,2]],null],"checked"]],[15,"onchange",[28,[37,9],[[30,0],"change"],null]],[14,4,"radio"],[12],[13],[1,"\\n "],[10,1],[12],[1,[30,3]],[13],[1,"\\n "],[13],[1,"\\n"]],[2,3]]]],[1]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],["item","_key","_value"],false,["name","each","-track-array","items","let","if","not-eq","or","keyboardAccess","action","eq","concat","value"]]',moduleName:"consul-ui/components/radio-group/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,t.default.extend({tagName:"",keyboardAccess:!1,dom:(0,l.inject)("dom"),init:function(){this._super(...arguments),this.name=this.dom.guid(this)},actions:{keydown:function(e){13===e.keyCode&&e.target.dispatchEvent(new MouseEvent("click"))},change:function(e){this.onchange(this.dom.setEventTargetProperty(e,"value",(e=>""===e?void 0:e)))}}})) +e.default=i})),define("consul-ui/components/ref/index",["exports","@ember/component","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l=t.default.extend({tagName:"",didReceiveAttrs:function(){(0,n.set)(this.target,this.name,this.value)}}) +e.default=l})),define("consul-ui/components/role-form/index",["exports","@ember/component","@ember/template-factory","consul-ui/components/form-component/index"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"c7JRCIgS",block:'[[[1,"\\n"],[18,2,null],[1,"\\n"],[11,"fieldset"],[24,0,"role-form"],[16,"disabled",[52,[28,[37,2],[[28,[37,3],["write role"],[["item"],[[33,4]]]]],null],"disabled"]],[17,1],[12],[1,"\\n "],[10,"label"],[15,0,[29,["type-text",[52,[33,4,["error","Name"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Name"],[13],[1,"\\n "],[10,"input"],[15,2,[33,4,["Name"]]],[14,3,"role[Name]"],[14,"autofocus","autofocus"],[15,"oninput",[28,[37,5],[[30,0],"change"],null]],[14,4,"text"],[12],[13],[1,"\\n "],[10,"em"],[12],[1,"\\n Maximum 256 characters. May only include letters (uppercase and/or lowercase) and/or numbers. Must be unique.\\n "],[13],[1,"\\n"],[41,[33,4,["error","Name"]],[[[1," "],[10,"strong"],[12],[1,[33,4,["error","Name","validation"]]],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[10,"label"],[14,0,"type-text"],[12],[1,"\\n "],[10,1],[12],[1,"Description (Optional)"],[13],[1,"\\n "],[10,"textarea"],[14,3,"role[Description]"],[15,2,[33,4,["Description"]]],[15,"oninput",[28,[37,5],[[30,0],"change"],null]],[12],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"],[10,"fieldset"],[14,1,"policies"],[14,0,"policies"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Policies"],[13],[1,"\\n"],[6,[39,6],null,[["name","params"],["policy",[28,[37,7],[[33,4]],null]]],[["default","else"],[[[[1," "],[18,2,null],[1,"\\n"]],[]],[[[1," "],[8,[39,8],null,[["@disabled","@dc","@partition","@nspace","@items"],[[28,[37,2],[[28,[37,3],["write role"],[["item"],[[33,4]]]]],null],[99,9,["@dc"]],[99,10,["@partition"]],[99,11,["@nspace"]],[33,4,["Policies"]]]],null],[1,"\\n"]],[]]]]],[13],[1,"\\n"]],["&attrs","&default"],false,["yield","if","not","can","item","action","yield-slot","block-params","policy-selector","dc","partition","nspace"]]',moduleName:"consul-ui/components/role-form/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,l.default.extend({type:"role",name:"role",classNames:["role-form"]})) +e.default=i})),define("consul-ui/components/role-selector/index",["exports","@ember/component","@ember/template-factory","consul-ui/components/child-selector/index","@ember/service","@ember/object","@ember/object/computed","consul-ui/utils/dom/event-source"],(function(e,t,n,l,r,i,o,a){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const u=(0,n.createTemplateFactory)({id:"6DJSWWjY",block:'[[[1,"\\n"],[8,[39,0],[[24,0,"role-selector"],[24,1,"new-role"]],[["@onclose","@aria"],[[28,[37,1],[[30,0],[28,[37,2],[[33,3]],null],"role"],null],[28,[37,4],null,[["label"],[[52,[28,[37,6],[[33,3],"role"],null],"New Role","New Policy"]]]]]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@target","@name","@value"],[[30,0],"modal",[30,1]]],null],[1,"\\n "],[8,[39,8],null,[["@name"],["header"]],[["default"],[[[[1,"\\n"],[41,[28,[37,6],[[33,3],"role"],null],[[[1," "],[10,"h2"],[12],[1,"New Role"],[13],[1,"\\n"]],[]],[[[1," "],[10,"h2"],[12],[1,"New Policy"],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["body"]],[["default"],[[[[1,"\\n\\n "],[10,"input"],[15,1,[29,[[36,9],"_state_role"]]],[15,3,[29,[[36,9],"[state]"]]],[14,2,"role"],[15,"checked",[52,[28,[37,6],[[33,3],"role"],null],"checked"]],[15,"onchange",[28,[37,1],[[30,0],"change"],null]],[14,4,"radio"],[12],[13],[1,"\\n "],[8,[39,10],null,[["@form","@dc","@nspace","@partition"],[[99,11,["@form"]],[99,12,["@dc"]],[99,13,["@nspace"]],[99,14,["@partition"]]]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["policy"]],[["default"],[[[[1,"\\n\\n "],[8,[39,15],null,[["@source","@dc","@partition","@nspace","@items"],[[99,16,["@source"]],[99,12,["@dc"]],[99,14,["@partition"]],[99,13,["@nspace"]],[33,17,["Policies"]]]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n "],[8,[39,18],[[24,0,"type-dialog"],[4,[38,1],[[30,0],"triggerStateCheckboxChange"],null]],[["@text","@size","@color","@icon"],["Create new policy","small","tertiary","plus"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[10,"input"],[15,1,[29,[[36,9],"_state_policy"]]],[15,3,[29,[[36,9],"[state]"]]],[14,2,"policy"],[15,"checked",[52,[28,[37,6],[[33,3],"policy"],null],"checked"]],[15,"onchange",[28,[37,1],[[30,0],"change"],null]],[14,4,"radio"],[12],[13],[1,"\\n "],[8,[39,19],null,[["@name","@form","@dc","@nspace","@partition"],["role[policy]",[99,20,["@form"]],[99,12,["@dc"]],[99,13,["@nspace"]],[99,14,["@partition"]]]],null],[1,"\\n\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n\\n "],[8,[39,21],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,6],[[33,3],"role"],null],[[[1," "],[8,[39,18],[[16,"onclick",[28,[37,22],[[30,0,["save"]],[33,17],[33,23],[28,[37,24],[[28,[37,1],[[30,0],[30,2]],null],[28,[37,1],[[30,0],"reset"],null]],null]],null]],[16,"disabled",[52,[28,[37,25],[[33,17,["isSaving"]],[33,17,["isPristine"]],[33,17,["isInvalid"]]],null],"disabled"]],[24,4,"submit"]],[["@text","@isLoading"],["Create and apply",[33,17,["isSaving"]]]],null],[1,"\\n "],[8,[39,18],[[16,"disabled",[52,[33,17,["isSaving"]],"disabled"]],[24,4,"reset"],[4,[38,26],["click",[28,[37,1],[[30,0],[28,[37,24],[[28,[37,1],[[30,0],[30,2]],null],[28,[37,1],[[30,0],"reset"],null]],null]],null]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n\\n"]],[]],[[[1," "],[8,[39,18],[[16,"disabled",[52,[28,[37,25],[[33,27,["isSaving"]],[33,27,["isPristine"]],[33,27,["isInvalid"]]],null],"disabled"]],[24,4,"submit"],[4,[38,1],[[30,0],"dispatch","save",[28,[37,28],[[33,27],[33,17,["Policies"]],[28,[37,1],[[30,0],[28,[37,2],[[33,3]],null],"role"],null]],null]],null]],[["@text","@isLoading"],["Create and apply",[33,27,["isSaving"]]]],null],[1,"\\n "],[8,[39,18],[[16,"disabled",[52,[33,27,["isSaving"]],"disabled"]],[24,4,"reset"],[4,[38,26],["click",[28,[37,1],[[30,0],[28,[37,2],[[33,3]],null],"role"],null]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n\\n"],[8,[39,29],null,[["@disabled","@repo","@dc","@partition","@nspace","@type","@placeholder","@items"],[[99,30,["@disabled"]],[99,31,["@repo"]],[99,12,["@dc"]],[99,14,["@partition"]],[99,13,["@nspace"]],"role","Search for role",[99,23,["@items"]]]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["label"]],[["default"],[[[[1,"\\n Apply an existing role\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["create"]],[["default"],[[[[1,"\\n "],[8,[39,18],[[24,0,"type-dialog"],[4,[38,26],["click",[28,[37,32],[[30,0,["modal","open"]]],null]],null]],[["@text","@size","@color","@icon"],["Create new role","small","tertiary","plus"]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["option"]],[["default"],[[[[1,"\\n "],[1,[30,3,["Name"]]],[1,"\\n "]],[3]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["set"]],[["default"],[[[[1,"\\n "],[8,[39,33],null,[["@rows","@items"],[5,[28,[37,34],["CreateTime:desc","Name:asc",[33,23]],null]]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[12],[1,"Name"],[13],[1,"\\n "],[10,"th"],[12],[1,"Description"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["row"]],[["default"],[[[[1,"\\n "],[10,"td"],[12],[1,"\\n "],[10,3],[15,6,[28,[37,35],["dc.acls.roles.edit",[30,4,["ID"]]],null]],[12],[1,[30,4,["Name"]]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[12],[1,"\\n "],[1,[30,4,["Description"]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,36],null,[["@expanded","@onchange","@keyboardAccess"],[[52,[28,[37,6],[[30,8],[30,6]],null],true,false],[28,[37,1],[[30,0],[30,7],[30,6]],null],false]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@name"],["trigger"]],[["default"],[[[[1,"\\n More\\n "]],[]]]]],[1,"\\n "],[8,[39,8],null,[["@name"],["menu"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,"role","none"],[12],[1,"\\n "],[10,3],[14,"role","menuitem"],[14,"tabindex","-1"],[15,6,[28,[37,35],["dc.acls.roles.edit",[30,4,["ID"]]],null]],[12],[1,"\\n"],[41,[28,[37,37],["edit role"],[["item"],[[30,4]]]],[[[1," Edit\\n"]],[]],[[[1," View\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,38],[[33,30]],null],[[[1," "],[10,"li"],[14,"role","none"],[14,0,"dangerous"],[12],[1,"\\n "],[10,"label"],[15,"for",[30,9]],[14,"role","menuitem"],[14,"tabindex","-1"],[15,"onkeypress",[30,11]],[12],[1,"Remove"],[13],[1,"\\n "],[10,0],[14,"role","menu"],[12],[1,"\\n "],[8,[39,39],[[24,0,"warning"]],null,[["header","body","actions"],[[[[1,"\\n Confirm Remove\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n Are you sure you want to remove this role?\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,12,["Action"]],[[24,0,"dangerous"]],null,[["default"],[[[[1,"\\n "],[8,[39,1],[[24,"tabindex","-1"],[4,[38,26],["click",[28,[37,1],[[30,0],[30,10],"remove",[30,4],[33,23]],null]],null]],null,[["default"],[[[[1,"\\n Remove\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,12,["Action"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,1],null,[["@for"],[[30,9]]],[["default"],[[[[1,"\\n Cancel\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[12]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "]],[9,10,11]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6,7,8]]]]],[1,"\\n "]],[4,5]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]]],[1,"\\n"]],["modal","close","option","item","index","index","change","checked","confirm","send","keypressClick","Actions"],false,["modal-dialog","action","mut","state","hash","if","eq","ref","block-slot","name","role-form","form","dc","nspace","partition","policy-selector","source","item","hds/button","policy-form","policyForm","hds/button-set","perform","items","queue","or","on","policy","array","child-selector","disabled","repo","optional","tabular-collection","sort-by","href-to","popover-menu","can","not","informed-action"]]',moduleName:"consul-ui/components/role-selector/index.hbs",isStrictMode:!1}) +var s=(0,t.setComponentTemplate)(u,l.default.extend({repo:(0,r.inject)("repository/role"),dom:(0,r.inject)("dom"),name:"role",type:"role",classNames:["role-selector"],state:"role",policy:(0,o.alias)("policyForm.data"),init:function(){this._super(...arguments),(0,i.set)(this,"policyForm",this.formContainer.form("policy")),this.source=new a.CallableEventSource},actions:{reset:function(e){this._super(...arguments),this.policyForm.clear({Datacenter:this.dc})},dispatch:function(e,t){this.source.dispatchEvent({type:e,data:t})},change:function(){const e=this.dom.normalizeEvent(...arguments).target +if("role[state]"===e.name)(0,i.set)(this,"state",e.value),"policy"===e.value&&this.dom.component(".code-editor",e.nextElementSibling).didAppear() +else this._super(...arguments)},triggerStateCheckboxChange(){let e=document.getElementById(`${this.name}_state_policy`) +e&&e.dispatchEvent(new Event("change"))}}})) +e.default=s})),define("consul-ui/components/route/announcer/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"vLxKAafQ",block:'[[[1,"\\n"],[1,[28,[35,0],[[30,1]],[["separator"],[[28,[37,1],[[30,2]," - "],null]]]]],[1,"\\n"],[8,[39,2],null,[["@name"],["route-announcer"]],null],[1,"\\n\\n"]],["@title","@separator"],false,["page-title","or","portal-target"]]',moduleName:"consul-ui/components/route/announcer/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/route/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/service","@ember/object","@glimmer/tracking"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m,h,b +function y(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function v(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const g=(0,n.createTemplateFactory)({id:"LX/9AVV9",block:'[[[1,"\\n"],[1,[28,[35,0],[[30,0,["connect"]]],null]],[1,"\\n"],[1,[28,[35,1],[[30,0,["disconnect"]]],null]],[1,"\\n"],[18,1,[[28,[37,3],null,[["model","params","currentName","refresh","t","exists","Title","Announcer"],[[30,0,["model"]],[30,0,["params"]],[30,0,["router","currentRoute","name"]],[30,0,["refresh"]],[30,0,["t"]],[30,0,["exists"]],[50,"route/title",0,null,null],[50,"route/announcer",0,null,null]]]]]]],["&default"],false,["did-insert","will-destroy","yield","hash","component"]]',moduleName:"consul-ui/components/route/index.hbs",isStrictMode:!1}),O=/\${([A-Za-z.0-9_-]+)}/g +let P=(a=(0,r.inject)("routlet"),u=(0,r.inject)("router"),s=(0,r.inject)("intl"),c=(0,r.inject)("encoder"),d=class extends l.default{constructor(){super(...arguments),y(this,"routlet",p,this),y(this,"router",f,this),y(this,"intl",m,this),y(this,"encoder",h,this),y(this,"_model",b,this),this.intlKey=this.encoder.createRegExpEncoder(O,(e=>e))}get params(){return this.routlet.paramsFor(this.args.name)}get model(){if(this._model)return this._model +if(this.args.name){const e=this.routlet.outletFor(this.args.name) +if(e)return this.routlet.modelFor(e.name)}}exists(e){return this.routlet.exists(`${this.args.name}.${e}`)}t(e,t){return e.includes("${")&&(e=this.intlKey(e,t)),this.intl.t(`routes.${this.args.name}.${e}`,t)}connect(){this.routlet.addRoute(this.args.name,this)}disconnect(){this.routlet.removeRoute(this.args.name,this)}},p=v(d.prototype,"routlet",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=v(d.prototype,"router",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=v(d.prototype,"intl",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=v(d.prototype,"encoder",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=v(d.prototype,"_model",[o.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v(d.prototype,"exists",[i.action],Object.getOwnPropertyDescriptor(d.prototype,"exists"),d.prototype),v(d.prototype,"t",[i.action],Object.getOwnPropertyDescriptor(d.prototype,"t"),d.prototype),v(d.prototype,"connect",[i.action],Object.getOwnPropertyDescriptor(d.prototype,"connect"),d.prototype),v(d.prototype,"disconnect",[i.action],Object.getOwnPropertyDescriptor(d.prototype,"disconnect"),d.prototype),d) +e.default=P,(0,t.setComponentTemplate)(g,P)})),define("consul-ui/components/route/title/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"6zw7iO0V",block:'[[[1,"\\n"],[1,[28,[35,0],[[30,1]],[["separator"],[[30,2]]]]],[1,"\\n"],[41,[28,[37,2],[[30,3],false],null],[[[1,[30,1]],[1,"\\n"]],[]],null],[8,[39,3],null,[["@target"],["route-announcer"]],[["default"],[[[[1,"\\n"],[11,0],[24,0,"route-title"],[17,4],[24,"aria-live","assertive"],[24,"aria-atomic","true"],[12],[1,"\\n"],[1," "],[1,[28,[35,4],["Navigated to ",[30,1]],null]],[1,"\\n"],[13],[1,"\\n"]],[]]]]],[1,"\\n"]],["@title","@separator","@render","&attrs"],false,["page-title","if","not-eq","portal","concat"]]',moduleName:"consul-ui/components/route/title/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/search-bar/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","consul-ui/components/search-bar/utils"],(function(e,t,n,l,r,i){var o +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const a=(0,n.createTemplateFactory)({id:"ZUmE45ig",block:'[[[1,"\\n"],[11,0],[24,0,"search-bar"],[17,1],[12],[1,"\\n "],[10,"form"],[14,0,"filter-bar"],[12],[1,"\\n "],[10,0],[14,0,"search"],[12],[1,"\\n "],[18,4,[[28,[37,1],null,[["Search","Select"],[[50,"freetext-filter",0,null,null],[50,"popover-select",0,null,null]]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"filters"],[12],[1,"\\n "],[18,5,[[28,[37,1],null,[["Search","Select"],[[50,"freetext-filter",0,null,null],[50,"popover-select",0,null,null]]]]]],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"sort"],[12],[1,"\\n "],[18,6,[[28,[37,1],null,[["Search","Select"],[[50,"freetext-filter",0,null,null],[50,"popover-select",0,null,null]]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[41,[30,0,["isFiltered"]],[[[1," "],[10,0],[14,0,"search-bar-status"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,[28,[35,4],[[28,[37,5],["component.search-bar.header"],[["default","item"],["common.ui.filtered-by",""]]]],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[10,"ul"],[12],[1,"\\n"],[42,[28,[37,7],[[28,[37,7],[[30,0,["filters"]]],null]],null],null,[[[1," "],[18,7,[[28,[37,1],null,[["RemoveFilter","status"],[[50,"search-bar/remove-filter",0,null,[["onclick"],[[28,[37,8],[[30,0],[28,[37,9],[[28,[37,9],[[30,3],[30,2,["key"]]],null],"change"],null],[28,[37,1],null,[["target"],[[28,[37,1],null,[["selectedItems"],[[28,[37,10],[[30,2,["selected"]],","],null]]]]]]]],null]]]],[28,[37,1],null,[["key","value"],[[30,2,["key"]],[28,[37,11],[[30,2,["value"]]],null]]]]]]]]],[1,"\\n"]],[2]],null],[1," "],[10,"li"],[14,0,"remove-all"],[12],[1,"\\n "],[8,[39,8],[[4,[38,12],["click",[30,0,["removeAllFilters"]]],null]],null,[["default"],[[[[1,"\\n Remove filters\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[13],[1,"\\n"]],["&attrs","filter","@filter","&search","&filter","&sort","&status"],false,["yield","hash","component","if","string-trim","t","each","-track-array","action","get","join","lowercase","on"]]',moduleName:"consul-ui/components/search-bar/index.hbs",isStrictMode:!1}) +let u=(o=class extends l.default{get isFiltered(){const e=this.args.filter.searchproperty||{default:[],value:[]} +return(0,i.diff)(e.default,e.value).length>0||Object.entries(this.args.filter).some((e=>{let[t,n]=e +return"searchproperty"!==t&&void 0!==n.value}))}get filters(){return(0,i.filters)(this.args.filter)}removeAllFilters(){Object.values(this.args.filter).forEach(((e,t)=>{setTimeout((()=>e.change(e.default||[])),1*t)}))}},s=o.prototype,c="removeAllFilters",d=[r.action],p=Object.getOwnPropertyDescriptor(o.prototype,"removeAllFilters"),f=o.prototype,m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),o) +var s,c,d,p,f,m +e.default=u,(0,t.setComponentTemplate)(a,u)})),define("consul-ui/components/search-bar/remove-filter/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"cLgM374P",block:'[[[1,"\\n"],[10,"li"],[12],[1,"\\n "],[8,[39,0],[[17,1],[4,[38,1],["click",[30,2]],null]],null,null],[1,"\\n "],[18,3,null],[1,"\\n"],[13],[1,"\\n"]],["&attrs","@onclick","&default"],false,["action","on","yield"]]',moduleName:"consul-ui/components/search-bar/remove-filter/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/search-bar/utils",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.filters=e.diff=void 0 +const t=(e,t)=>e.filter((e=>!t.includes(e))) +e.diff=t +e.filters=e=>Object.entries(e).filter((e=>{let[n,l]=e +return"searchproperty"===n?t(l.default,l.value).length>0:(l.value||[]).length>0})).reduce(((e,n)=>{let[l,r]=n +return e.concat(r.value.map((e=>{const n={key:l,value:e} +return n.selected="searchproperty"!==l?t(r.value,[e]):1===r.value.length?r.default:t(r.value,[e]),n})))}),[])})),define("consul-ui/components/state-chart/action/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"T5GYB6QS",block:'[[[1,"\\n"],[18,1,null]],["&default"],false,["yield"]]',moduleName:"consul-ui/components/state-chart/action/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:"",didInsertElement:function(){this._super(...arguments),this.chart.addAction(this.name,((e,t)=>this.exec(e,t)))},willDestroy:function(){this._super(...arguments),this.chart.removeAction(this.type)}})) +e.default=r})),define("consul-ui/components/state-chart/guard/index",["exports","@ember/component","@ember/template-factory"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l=(0,n.createTemplateFactory)({id:"yKKkKZDK",block:'[[[1,"\\n"],[18,1,null]],["&default"],false,["yield"]]',moduleName:"consul-ui/components/state-chart/guard/index.hbs",isStrictMode:!1}) +var r=(0,t.setComponentTemplate)(l,t.default.extend({tagName:"",didInsertElement:function(){this._super(...arguments) +const e=this +this.chart.addGuard(this.name,(function(){return"function"==typeof e.cond?e.cond(...arguments):e.cond}))},willDestroyElement:function(){this._super(...arguments),this.chart.removeGuard(this.name)}})) +e.default=r})),define("consul-ui/components/state-chart/index",["exports","@ember/component","@ember/template-factory","@ember/service","@ember/object"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i=(0,n.createTemplateFactory)({id:"Vs0Hi4qP",block:'[[[1,"\\n"],[18,1,[[50,"state",0,null,[["state"],[[33,2]]]],[50,"state-chart/guard",0,null,[["chart"],[[30,0]]]],[50,"state-chart/action",0,null,[["chart"],[[30,0]]]],[28,[37,3],[[30,0],"dispatch"],null],[33,2]]]],["&default"],false,["yield","component","state","action"]]',moduleName:"consul-ui/components/state-chart/index.hbs",isStrictMode:!1}) +var o=(0,t.setComponentTemplate)(i,t.default.extend({chart:(0,l.inject)("state"),tagName:"",ontransition:function(e){},init:function(){this._super(...arguments),this._actions={},this._guards={}},didReceiveAttrs:function(){var e=this +void 0!==this.machine&&this.machine.stop(),void 0!==this.initial&&(this.src.initial=this.initial),this.machine=this.chart.interpret(this.src,{onTransition:e=>{const t=new CustomEvent("transition",{detail:e}) +this.ontransition(t),t.defaultPrevented||e.actions.forEach((t=>{"function"==typeof this._actions[t.type]&&this._actions[t.type](t.type,e.context,e.event)})),(0,r.set)(this,"state",e)},onGuard:function(t){for(var n=arguments.length,l=new Array(n>1?n-1:0),r=1;r1&&void 0!==arguments[1]?arguments[1]:{} +if(this.$tr&&(this.$tr.style.zIndex=null),t.target&&t.target.checked&&e!==this.checked){(0,r.set)(this,"checked",parseInt(e)) +const n=t.target,l=this.dom.closest("tr",n),i=this.dom.sibling(n,"div") +i.getBoundingClientRect().top+i.clientHeight>this.dom.element('footer[role="contentinfo"]').getBoundingClientRect().top?i.classList.add("above"):i.classList.remove("above"),l.style.zIndex=1,this.$tr=l}else(0,r.set)(this,"checked",null)}}})) +e.default=d})),define("consul-ui/components/tabular-details/index",["exports","@ember/component","@ember/template-factory","@ember/service","block-slots"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i=(0,n.createTemplateFactory)({id:"rfQqVmFw",block:'[[[1,"\\n"],[18,4,null],[1,"\\n"],[10,"table"],[14,0,"with-details has-actions"],[12],[1,"\\n "],[10,"thead"],[12],[1,"\\n "],[10,"tr"],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["header"]],[["default"],[[[[18,4,null]],[]]]]],[1,"\\n "],[10,"th"],[14,0,"actions"],[12],[1,"Actions"],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"tbody"],[12],[1,"\\n"],[44,[[28,[37,3],["tabular-details-",[33,4],"-toggle-",[33,5],"_"],null]],[[[42,[28,[37,7],[[28,[37,7],[[33,8]],null]],null],null,[[[1," "],[10,"tr"],[15,"onclick",[28,[37,9],[[30,0],"click"],null]],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["row"]],[["default"],[[[[18,4,[[30,2],[30,3]]]],[]]]]],[1,"\\n "],[10,"td"],[14,0,"actions"],[12],[1,"\\n "],[10,"label"],[15,"for",[28,[37,3],[[30,1],[30,3]],null]],[12],[10,1],[12],[1,"Show details"],[13],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"tr"],[12],[1,"\\n "],[10,"td"],[14,"colspan","3"],[12],[1,"\\n "],[10,"input"],[15,"checked",[28,[37,10],[[28,[37,11],[[30,2,["closed"]]],null]],null]],[15,2,[30,3]],[15,3,[36,4]],[15,1,[28,[37,3],[[30,1],[30,3]],null]],[15,"onchange",[28,[37,9],[[30,0],"change",[30,2],[33,8]],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,"label"],[15,"for",[28,[37,3],[[30,1],[30,3]],null]],[12],[10,1],[12],[1,"Hide details"],[13],[13],[1,"\\n "],[10,0],[12],[1,"\\n "],[8,[39,1],null,[["@name"],["details"]],[["default"],[[[[1,"\\n "],[18,4,[[30,2],[30,3]]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[2,3]],null]],[1]]],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],["inputId","item","index","&default"],false,["yield","yield-slot","let","concat","name","guid","each","-track-array","items","action","not","is-empty"]]',moduleName:"consul-ui/components/tabular-details/index.hbs",isStrictMode:!1}) +var o=(0,t.setComponentTemplate)(i,t.default.extend(r.default,{dom:(0,l.inject)("dom"),onchange:function(){},init:function(){this._super(...arguments),this.guid=this.dom.guid(this)},actions:{click:function(e){this.dom.clickFirstAnchor(e)},change:function(e,t,n){this.onchange(n,e,t)}}})) +e.default=o})),define("consul-ui/components/tag-list/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"w4UdhAwF",block:'[[[1,"\\n"],[44,[[28,[37,1],[[28,[37,2],[[30,1,["Tags"]],[28,[37,3],null,null]],null],[28,[37,2],[[30,2],[28,[37,3],null,null]],null]],null]],[[[41,[28,[37,5],[[30,3,["length"]],0],null],[[[41,[48,[30,6]],[[[1," "],[18,6,[[50,"tag-list",0,null,[["item"],[[30,1]]]]]],[1,"\\n"]],[]],[[[11,"dl"],[24,0,"tag-list"],[17,4],[12],[1,"\\n "],[11,"dt"],[4,[38,9],null,null],[12],[1,"\\n "],[1,[28,[35,10],["components.tag-list.title"],[["default"],[[28,[37,3],["common.consul.tags"],null]]]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n"],[42,[28,[37,12],[[28,[37,12],[[30,3]],null]],null],null,[[[1," "],[10,1],[12],[1,[30,5]],[13],[1,"\\n"]],[5]],null],[1," "],[13],[1,"\\n"],[13],[1,"\\n"]],[]]]],[]],null]],[3]]]],["@item","@tags","tags","&attrs","item","&default"],false,["let","union","or","array","if","gt","has-block","yield","component","tooltip","t","each","-track-array"]]',moduleName:"consul-ui/components/tag-list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/text-input/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"/IacsejQ",block:'[[[1,"\\n"],[8,[39,0],[[16,0,[28,[37,1],["text-input"," type-text"],null]],[17,1]],[["@item","@placeholder","@name","@label","@help","@validations","@chart"],[[30,2],[30,3],[30,4],[30,5],[30,6],[30,7],[30,8]]],[["label","input"],[[[[1,"\\n"],[1," "],[1,[28,[35,2],[[30,5],[30,4]],null]],[1,"\\n "]],[]],[[[1,"\\n"],[41,[30,9],[[[1," "],[11,"textarea"],[16,3,[30,4]],[4,[38,4],[[30,2]],[["validations","chart"],[[30,7],[30,8]]]],[4,[38,5],["input",[28,[37,6],[[30,10]],null]],null],[12],[1,[28,[35,2],[[30,11],[28,[37,7],[[30,2],[30,4]],null]],null]],[13],[1,"\\n"]],[]],[[[1," "],[11,"input"],[16,2,[28,[37,2],[[30,11],[28,[37,7],[[30,2],[30,4]],null]],null]],[16,3,[30,4]],[16,"placeholder",[28,[37,2],[[30,3]],null]],[24,4,"text"],[4,[38,4],[[30,2]],[["validations","chart"],[[30,7],[30,8]]]],[4,[38,5],["input",[28,[37,6],[[30,10]],null]],null],[12],[13],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n"]],["&attrs","@item","@placeholder","@name","@label","@help","@validations","@chart","@expanded","@oninput","@value"],false,["form-input","concat","or","if","validate","on","optional","get"]]',moduleName:"consul-ui/components/text-input/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/toggle-button/index",["exports","@ember/component","@ember/template-factory","@ember/service"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"aP5ecOU9",block:'[[[1,"\\n"],[11,"input"],[17,1],[24,4,"checkbox"],[16,"checked",[52,[33,1],"checked",[27]]],[16,1,[28,[37,2],["toggle-button-",[33,3]],null]],[16,"onchange",[28,[37,4],[[30,0],"change"],null]],[4,[38,5],[[28,[37,6],[[30,0],"input"],null]],null],[12],[13],[1,"\\n"],[11,"label"],[16,"for",[28,[37,2],["toggle-button-",[33,3]],null]],[4,[38,5],[[28,[37,6],[[30,0],"label"],null]],null],[12],[1,"\\n "],[18,2,[[28,[37,8],null,[["click"],[[28,[37,4],[[30,0],"click"],null]]]]]],[1,"\\n"],[13]],["&attrs","&default"],false,["if","checked","concat","guid","action","did-insert","set","yield","hash"]]',moduleName:"consul-ui/components/toggle-button/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,t.default.extend({dom:(0,l.inject)("dom"),tagName:"",checked:!1,onchange:function(){},onblur:function(){},init:function(){this._super(...arguments),this.guid=this.dom.guid(this),this._listeners=this.dom.listeners()},willDestroyElement:function(){this._super(...arguments),this._listeners.remove()},didReceiveAttrs:function(){this._super(...arguments),this.checked?this.addClickOutsideListener():this._listeners.remove()},addClickOutsideListener:function(){this._listeners.remove(),this._listeners.add(this.dom.document(),"click",(e=>{this.dom.isOutside(this.label,e.target)&&this.dom.isOutside(this.label.nextElementSibling,e.target)&&(this.input.checked&&(this.input.checked=!1,this.onchange({target:this.input})),this._listeners.remove())}))},actions:{click:function(e){-1===(e.target.rel||"").indexOf("noopener")&&e.preventDefault(),this.input.checked=!this.input.checked,0!==e.detail&&e.target.blur(),this.actions.change.apply(this,[e])},change:function(e){this.input.checked&&this.addClickOutsideListener(),this.onchange({target:this.input})}}})) +e.default=i})),define("consul-ui/components/token-list/index",["exports","@ember/component","@ember/template-factory","block-slots"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"Y0O5hDWb",block:'[[[1,"\\n"],[18,3,null],[1,"\\n"],[41,[28,[37,2],[[33,3,["length"]],0],null],[[[1," "],[8,[39,4],[[24,0,"token-list"]],[["@rows","@items"],[5,[28,[37,5],["AccessorID:asc",[33,3]],null]]],[["default"],[[[[1,"\\n"],[41,[33,6],[[[1," "],[8,[39,7],null,[["@name"],["caption"]],[["default"],[[[[1,[34,6]]],[]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,7],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[12],[1,"AccessorID"],[13],[1,"\\n "],[10,"th"],[12],[1,"Scope"],[13],[1,"\\n "],[10,"th"],[12],[1,"Description"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["row"]],[["default"],[[[[1,"\\n "],[10,"td"],[12],[1,"\\n "],[10,3],[15,6,[28,[37,8],["dc.acls.tokens.edit",[30,1,["AccessorID"]]],null]],[15,"target",[28,[37,9],[[33,10],""],null]],[12],[1,[28,[35,11],[[30,1,["AccessorID"]],8,false],null]],[13],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[12],[1,"\\n "],[1,[52,[30,1,["Local"]],"local","global"]],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[12],[1,"\\n "],[10,2],[12],[1,[30,1,["Description"]]],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[1,2]]]]],[1,"\\n"]],[]],null]],["item","index","&default"],false,["yield","if","gt","items","tabular-collection","sort-by","caption","block-slot","href-to","or","target","truncate"]]',moduleName:"consul-ui/components/token-list/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,t.default.extend(l.default,{tagName:""})) +e.default=i})),define("consul-ui/components/token-source/chart.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={id:"token-source",initial:"idle",on:{RESTART:[{target:"secret",cond:"isSecret"},{target:"provider"}]},states:{idle:{},secret:{},provider:{on:{SUCCESS:"jwt"}},jwt:{on:{SUCCESS:"token"}},token:{}}}})),define("consul-ui/components/token-source/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","@glimmer/tracking","consul-ui/components/token-source/chart.xstate"],(function(e,t,n,l,r,i,o){var a,u,s +function c(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function d(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function p(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function f(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const m=(0,n.createTemplateFactory)({id:"4D3syB2X",block:'[[[1,"\\n"],[8,[39,0],null,[["@src","@initial"],[[30,0,["chart"]],[52,[28,[37,2],[[30,1],"oidc"],null],"provider","secret"]]],[["default"],[[[[1,"\\n "],[8,[30,3],null,[["@name","@cond"],["isSecret",[30,0,["isSecret"]]]],null],[1,"\\n"],[44,[[28,[37,4],["/${partition}/${nspace}/${dc}",[28,[37,5],null,[["partition","nspace","dc"],[[28,[37,6],[[30,7,["Partition"]],[30,8]],null],[28,[37,6],[[30,7,["Namespace"]],[30,9]],null],[30,10]]]]],null]],[[[1," "],[8,[30,2],null,[["@matches"],["secret"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@src","@onchange","@onerror"],[[28,[37,4],[[28,[37,8],[[30,11],"/token/self/${value}"],null],[28,[37,5],null,[["value"],[[30,7]]]]],null],[30,0,["change"]],[30,12]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,2],null,[["@matches"],["provider"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@src","@onchange","@onerror"],[[28,[37,4],[[28,[37,8],[[30,11],"/oidc/provider/${value}"],null],[28,[37,5],null,[["value"],[[30,7,["Name"]]]]]],null],[28,[37,9],[[28,[37,10],[[30,0],[28,[37,11],[[30,0,["provider"]]],null]],[["value"],["data"]]],[28,[37,10],[[30,0],[30,5],"SUCCESS"],null]],null],[30,12]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,2],null,[["@matches"],["jwt"]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@src","@onchange","@onerror"],[[30,0,["provider","AuthURL"]],[28,[37,9],[[28,[37,10],[[30,0],[28,[37,11],[[30,0,["jwt"]]],null]],[["value"],["data"]]],[28,[37,10],[[30,0],[30,5],"SUCCESS"],null]],null],[30,12]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,2],null,[["@matches"],["token"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@src","@onchange","@onerror"],[[28,[37,4],[[28,[37,8],[[30,11],"/oidc/authorize/${provider}/${code}/${state}"],null],[28,[37,5],null,[["provider","code","state"],[[30,0,["provider","Name"]],[30,0,["jwt","authorizationCode"]],[28,[37,6],[[30,0,["jwt","authorizationState"]],""],null]]]]],null],[30,0,["change"]],[30,12]]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[11]]]],[2,3,4,5,6]]]]]],["@type","State","Guard","Action","dispatch","state","@value","@partition","@nspace","@dc","path","@onerror"],false,["state-chart","if","eq","let","uri","hash","or","data-source","concat","queue","action","mut","jwt-source"]]',moduleName:"consul-ui/components/token-source/index.hbs",isStrictMode:!1}) +let h=(a=class extends l.default{constructor(){super(...arguments),d(this,"provider",u,this),d(this,"jwt",s,this),this.chart=o.default}isSecret(){return"secret"===this.args.type}change(e){e.data.toJSON=function(){return function(e){for(var t=1;t{const n=parseFloat(t.getTotalLength()),l=t.getPointAtLength(Math.ceil(n/3)) +return{id:t.id,x:Math.round(l.x-e.x),y:Math.round(l.y-e.y)}}))}},s=p(u.prototype,"iconPositions",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=p(u.prototype,"dom",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p(u.prototype,"getIconPositions",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"getIconPositions"),u.prototype),u) +e.default=m,(0,t.setComponentTemplate)(f,m)})),define("consul-ui/components/topology-metrics/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object","@ember/service"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m,h,b,y +function v(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function g(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const O=(0,n.createTemplateFactory)({id:"iumWc6H2",block:'[[[1,"\\n"],[11,0],[24,0,"topology-container consul-topology-metrics"],[4,[38,0],[[30,0,["calculate"]]],null],[12],[1,"\\n"],[41,[28,[37,2],[[30,0,["downstreams","length"]],0],null],[[[1," "],[11,0],[24,1,"downstream-container"],[4,[38,3],[[30,0,["setHeight"]],"downstream-lines"],null],[4,[38,4],[[30,0,["setHeight"]],"downstream-lines",[30,0,["downstreams"]]],null],[12],[1,"\\n"],[41,[28,[37,5],[[30,0,["emptyColumn"]]],null],[[[1," "],[10,0],[12],[1,"\\n "],[10,2],[12],[1,[30,1,["Name"]]],[13],[1,"\\n "],[10,1],[12],[1,"\\n "],[8,[39,6],null,null,[["default"],[[[[1,"\\n Only showing downstreams within the current datacenter for "],[1,[30,2,["Service","Service"]]],[1,".\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[42,[28,[37,8],[[28,[37,8],[[30,0,["downstreams"]]],null]],null],null,[[[1," "],[8,[39,9],null,[["@nspace","@dc","@service","@item","@hasMetricsProvider","@noMetricsReason"],[[30,4],[30,1,["Name"]],[30,2,["Service"]],[30,3],[30,5],[30,0,["noMetricsReason"]]]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],[[30,5],[30,0,["mainNotIngressService"]],[28,[37,11],[[30,3,["Kind"]],"ingress-gateway"],null],[30,0,["mainNotAPIGatewayService"]],[28,[37,11],[[30,3,["Kind"]],"api-gateway"],null]],null],[[[1," "],[8,[39,12],null,[["@nspace","@partition","@dc","@endpoint","@service","@item","@noMetricsReason"],[[28,[37,13],[[30,3,["Namespace"]],"default"],null],[28,[37,13],[[30,3,["Partition"]],"default"],null],[30,3,["Datacenter"]],"downstream-summary-for-service",[30,2,["Service","Service"]],[30,3,["Name"]],[30,0,["noMetricsReason"]]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n"]],[3]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[10,0],[14,1,"metrics-container"],[12],[1,"\\n "],[10,0],[14,0,"metrics-header"],[12],[1,"\\n "],[1,[30,2,["Service","Service"]]],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,5],[[28,[37,10],[[28,[37,14],[[30,2,["Service","Meta","external-source"]],"consul-api-gateway"],null],[28,[37,14],[[30,2,["Service","Kind"]],"ingress-gateway"],null]],null]],null],[[[41,[30,5],[[[1," "],[8,[39,15],null,[["@nspace","@partition","@dc","@service","@protocol","@noMetricsReason"],[[28,[37,13],[[30,2,["Service","Namespace"]],"default"],null],[28,[37,13],[[33,16,["Service","Partition"]],"default"],null],[30,1,["Name"]],[30,2,["Service","Service"]],[30,6,["Protocol"]],[30,0,["noMetricsReason"]]]],null],[1,"\\n"],[41,[28,[37,13],[[28,[30,0,["mainNotIngressService"]],null,null],[28,[30,0,["mainNotAPIGatewayService"]],null,null]],null],[[[1," "],[8,[39,12],null,[["@nspace","@partition","@dc","@endpoint","@service","@protocol","@noMetricsReason"],[[28,[37,13],[[30,2,["Service","Namespace"]],"default"],null],[28,[37,13],[[33,16,["Service","Partition"]],"default"],null],[30,1,["Name"]],"summary-for-service",[30,2,["Service","Service"]],[30,6,["Protocol"]],[30,0,["noMetricsReason"]]]],null],[1,"\\n"]],[]],null]],[]],null],[1," "],[10,0],[14,0,"link"],[12],[1,"\\n"],[41,[30,7],[[[1," "],[10,3],[14,0,"metrics-link"],[15,6,[30,7]],[14,"target","_blank"],[14,"rel","noopener noreferrer"],[12],[1,"Open dashboard"],[13],[1,"\\n"]],[]],[[[1," "],[10,3],[14,0,"config-link"],[15,6,[29,[[28,[37,17],["CONSUL_DOCS_URL"],null],"/connect/observability/ui-visualization"]]],[14,"target","_blank"],[14,"rel","noopener noreferrer"],[12],[1,"Configure dashboard"],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[10,0],[14,1,"downstream-lines"],[12],[1,"\\n "],[8,[39,18],null,[["@type","@service","@view","@center","@lines","@items","@oncreate"],["downstream",[30,2],[30,0,["downView"]],[30,0,["centerDimensions"]],[30,0,["downLines"]],[30,0,["downstreams"]],[28,[37,19],[[30,0],[30,8]],null]]],null],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,2],[[30,0,["upstreams","length"]],0],null],[[[1," "],[10,0],[14,1,"upstream-column"],[12],[1,"\\n"],[42,[28,[37,20],[[28,[37,21],["PeerOrDatacenter",[30,0,["upstreams"]]],null]],null],null,[[[1," "],[11,0],[24,1,"upstream-container"],[4,[38,3],[[30,0,["setHeight"]],"upstream-lines"],null],[4,[38,4],[[30,0,["setHeight"]],"upstream-lines",[30,0,["upstreams"]]],null],[12],[1,"\\n"],[41,[30,10],[[[1," "],[10,2],[12],[1,[30,10]],[13],[1,"\\n"]],[]],null],[42,[28,[37,8],[[28,[37,8],[[30,9]],null]],null],null,[[[1," "],[8,[39,9],null,[["@dc","@item","@service"],[[30,1,["Name"]],[30,11],[30,2,["Service"]]]],[["default"],[[[[1,"\\n"],[41,[28,[37,10],[[30,5],[30,0,["mainNotIngressService"]],[28,[37,11],[[30,11,["Kind"]],"ingress-gateway"],null]],null],[[[1," "],[8,[39,12],null,[["@nspace","@partition","@dc","@endpoint","@service","@item","@noMetricsReason"],[[28,[37,13],[[30,11,["Namespace"]],"default"],null],[28,[37,13],[[30,11,["Partition"]],"default"],null],[30,11,["Datacenter"]],"upstream-summary-for-service",[30,2,["Service","Service"]],[30,11,["Name"]],[30,0,["noMetricsReason"]]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n"]],[11]],null],[1," "],[13],[1,"\\n"]],[9,10]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[10,0],[14,1,"upstream-lines"],[12],[1,"\\n "],[8,[39,22],null,[["@type","@service","@view","@center","@lines","@items","@oncreate"],["upstream",[30,2],[30,0,["upView"]],[30,0,["centerDimensions"]],[30,0,["upLines"]],[30,0,["upstreams"]],[28,[37,19],[[30,0],[30,8]],null]]],null],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["@dc","@service","item","@nspace","@hasMetricsProvider","@topology","@metricsHref","@oncreate","upstreams","dc","item"],false,["on-resize","if","gt","did-insert","did-update","not","tooltip","each","-track-array","topology-metrics/card","and","not-eq","topology-metrics/stats","or","eq","topology-metrics/series","service","env","topology-metrics/down-lines","action","-each-in","group-by","topology-metrics/up-lines"]]',moduleName:"consul-ui/components/topology-metrics/index.hbs",isStrictMode:!1}) +let P=(a=(0,o.inject)("env"),u=(0,o.inject)(),s=class extends l.default{constructor(){super(...arguments),v(this,"env",c,this),v(this,"abilities",d,this),v(this,"centerDimensions",p,this),v(this,"downView",f,this),v(this,"downLines",m,this),v(this,"upView",h,this),v(this,"upLines",b,this),v(this,"noMetricsReason",y,this)}drawDownLines(e){const t=["allow","deny"],n={x:this.centerDimensions.x-7,y:this.centerDimensions.y+this.centerDimensions.height/2} +return e.map((e=>{const t=e.getBoundingClientRect(),l={x:t.x+t.width,y:t.y+t.height/2} +return{id:e.id,permission:e.getAttribute("data-permission"),dest:n,src:l}})).sort(((e,n)=>t.indexOf(e.permission)-t.indexOf(n.permission)))}drawUpLines(e){const t=["allow","deny"],n={x:this.centerDimensions.x+5.5,y:this.centerDimensions.y+this.centerDimensions.height/2} +return e.map((e=>{const t=e.getBoundingClientRect(),l={x:t.x-t.width-25,y:t.y+t.height/2} +return{id:e.id,permission:e.getAttribute("data-permission"),dest:l,src:n}})).sort(((e,n)=>t.indexOf(e.permission)-t.indexOf(n.permission)))}emptyColumn(){const e=(0,i.get)(this.args.topology,"noDependencies") +return!this.env.var("CONSUL_ACLS_ENABLED")||e}get downstreams(){const e=(0,i.get)(this.args.topology,"Downstreams")||[],t=[...e],n=(0,i.get)(this.args.topology,"noDependencies") +if(!this.env.var("CONSUL_ACLS_ENABLED")&&n)t.push({Name:"Downstreams unknown.",Empty:!0,Datacenter:"",Namespace:""}) +else if(0===e.length){const e=this.abilities.can("use peers") +t.push({Name:e?"No downstreams, or the downstreams are imported services.":"No downstreams.",Datacenter:"",Namespace:""})}return t}get upstreams(){const e=(0,i.get)(this.args.topology,"Upstreams")||[] +e.forEach((e=>{e.PeerOrDatacenter=e.PeerName||e.Datacenter})) +const t=[...e],n=(0,i.get)(this.args.dc,"DefaultACLPolicy"),l=(0,i.get)(this.args.topology,"wildcardIntention"),r=(0,i.get)(this.args.topology,"noDependencies") +return!this.env.var("CONSUL_ACLS_ENABLED")&&r?t.push({Name:"Upstreams unknown.",Datacenter:"",PeerOrDatacenter:"",Namespace:""}):"allow"===n||l?t.push({Name:"* (All Services)",Datacenter:"",PeerOrDatacenter:"",Namespace:""}):0===e.length&&t.push({Name:"No upstreams.",Datacenter:"",PeerOrDatacenter:"",Namespace:""}),t}get mainNotIngressService(){return"ingress-gateway"!==((0,i.get)(this.args.service.Service,"Kind")||"")}get mainNotAPIGatewayService(){return"api-gateway"!==((0,i.get)(this.args.service.Service,"Kind")||"")}setHeight(e,t){if(e){const n=e.getBoundingClientRect() +document.getElementById(`${t[0]}`).setAttribute("style",`height:${n.height}px`)}this.calculate()}calculate(){this.args.isRemoteDC?this.noMetricsReason="remote-dc":"ingress-gateway"===this.args.service.Service.Kind?this.noMetricsReason="ingress-gateway":this.noMetricsReason=null +const e=document.getElementById("downstream-lines").getBoundingClientRect(),t=document.getElementById("upstream-lines").getBoundingClientRect(),n=document.getElementById("upstream-column") +this.emptyColumn?this.downView={x:e.x,y:e.y,width:e.width,height:e.height+10}:this.downView=e,n&&(this.upView={x:t.x,y:t.y,width:t.width,height:n.getBoundingClientRect().height+10}) +const l=[...document.querySelectorAll("#downstream-container .topology-metrics-card")],r=document.querySelector(".metrics-header"),i=[...document.querySelectorAll("#upstream-column .topology-metrics-card")] +this.centerDimensions=r.getBoundingClientRect(),this.downLines=this.drawDownLines(l),this.upLines=this.drawUpLines(i)}},c=g(s.prototype,"env",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=g(s.prototype,"abilities",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=g(s.prototype,"centerDimensions",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=g(s.prototype,"downView",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=g(s.prototype,"downLines",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return[]}}),h=g(s.prototype,"upView",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=g(s.prototype,"upLines",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return[]}}),y=g(s.prototype,"noMetricsReason",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g(s.prototype,"setHeight",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"setHeight"),s.prototype),g(s.prototype,"calculate",[i.action],Object.getOwnPropertyDescriptor(s.prototype,"calculate"),s.prototype),s) +e.default=P,(0,t.setComponentTemplate)(O,P)})),define("consul-ui/components/topology-metrics/notifications/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"Qfu6ZA1U",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1],"create"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your intention has been added.\\n"]],[]],[[[1," There was an error adding your intention.\\n"]],[]]]],[]],[[[41,[28,[37,1],[[30,1],"update"],null],[[[41,[28,[37,1],[[30,2],"success"],null],[[[1," Your intention has been saved.\\n"]],[]],[[[1," There was an error saving your intention.\\n"]],[]]]],[]],null]],[]]],[44,[[30,3,["errors","firstObject"]]],[[[41,[30,4,["detail"]],[[[1," "],[10,"br"],[12],[13],[1,[28,[35,3],["(",[52,[30,4,["status"]],[28,[37,3],[[30,4,["status"]],": "],null]],[30,4,["detail"]],")"],null]],[1,"\\n"]],[]],null]],[4]]],[1,"\\n"]],["@type","@status","@error","error"],false,["if","eq","let","concat"]]',moduleName:"consul-ui/components/topology-metrics/notifications/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/topology-metrics/popover/index",["exports","@ember/component","@ember/template-factory","@glimmer/component"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"IUnHpfA3",block:'[[[1,"\\n"],[11,0],[16,0,[29,["topology-metrics-popover ",[30,1]]]],[17,2],[12],[1,"\\n"],[44,[[28,[37,1],["top:",[30,3,["y"]],"px;left:",[30,3,["x"]],"px;"],null],[52,[28,[37,3],[[30,1],"deny"],null],"Add intention","View intention"]],[[[41,[28,[37,4],[[30,6]],null],[[[41,[28,[37,3],[[30,1],"deny"],null],[[[1," "],[8,[39,5],[[24,0,"dangerous"],[4,[38,6],[[28,[37,7],[[30,0],"popover"],null]],null]],null,[["header","body","actions"],[[[[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.deny.header"],null]],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n"],[41,[30,7,["Intention","HasExact"]],[[[1," "],[1,[28,[35,8],["components.consul.topology-metrics.popover.deny.body.isExact"],null]],[1,"\\n"]],[]],[[[1," "],[1,[28,[35,8],["components.consul.topology-metrics.popover.deny.body.notExact"],null]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,8,["Action"]],[[24,0,"action"]],null,[["default"],[[[[1,"\\n "],[11,"button"],[24,4,"button"],[4,[38,9],["click",[30,9]],null],[12],[1,"\\n"],[41,[30,7,["Intention","HasExact"]],[[[1," "],[1,[28,[35,8],["components.consul.topology-metrics.popover.deny.action.isExact"],null]],[1,"\\n"]],[]],[[[1," "],[1,[28,[35,8],["components.consul.topology-metrics.popover.deny.action.notExact"],null]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,8,["Action"]],null,null,[["default"],[[[[1,"\\n "],[11,"button"],[24,0,"cancel"],[24,4,"button"],[4,[38,9],["click",[28,[37,10],[[28,[37,11],[[30,0,["popoverController","hide"]]],null]],null]],null],[12],[1,"\\n Cancel\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n"]],[]],[[[41,[28,[37,3],[[30,1],"not-defined"],null],[[[1," "],[8,[39,5],[[24,0,"warning documentation"],[4,[38,6],[[28,[37,7],[[30,0],"popover"],null]],null]],null,[["header","body","actions"],[[[[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.not-defined.header"],null]],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.not-defined.body"],[["downstream","upstream"],[[30,7,["Name"]],[30,10,["Name"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,11,["Action"]],[[24,0,"action"]],null,[["default"],[[[[1,"\\n "],[10,3],[15,6,[29,[[28,[37,12],["CONSUL_DOCS_URL"],null],"/connect/registration/service-registration#upstreams"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.not-defined.action"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,11,["Action"]],null,null,[["default"],[[[[1,"\\n "],[11,"button"],[24,0,"cancel"],[24,4,"button"],[4,[38,9],["click",[28,[37,10],[[28,[37,11],[[30,0,["popoverController","hide"]]],null]],null]],null],[12],[1,"\\n Close\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[11]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,5],[[24,0,"info"],[4,[38,6],[[28,[37,7],[[30,0],"popover"],null]],null]],null,[["header","body","actions"],[[[[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.l7.header"],null]],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.l7.body"],null]],[1,"\\n "],[13],[1,"\\n "]],[]],[[[1,"\\n "],[8,[30,12,["Action"]],[[24,0,"action"]],null,[["default"],[[[[1,"\\n "],[10,3],[15,6,[28,[37,13],["dc.services.show.intentions.edit",[28,[37,1],[[30,7,["Intention","ID"]]],null]],null]],[12],[1,"\\n "],[1,[28,[35,8],["components.consul.topology-metrics.popover.l7.action"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,12,["Action"]],null,null,[["default"],[[[[1,"\\n "],[11,"button"],[24,0,"cancel"],[24,4,"button"],[4,[38,9],["click",[28,[37,10],[[28,[37,11],[[30,0,["popoverController","hide"]]],null]],null]],null],[12],[1,"\\n Close\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[12]]]]],[1,"\\n "]],[]]]],[]]],[1," "],[11,"button"],[23,5,[30,4]],[16,"aria-label",[30,5]],[24,4,"button"],[4,[38,14],[[30,0,["popover"]]],[["options","returns"],[[28,[37,15],null,[["theme","placement"],["square-tail","bottom-start"]]],[28,[37,7],[[30,0],"popoverController"],null]]]],[4,[38,9],["click",[28,[37,10],[[28,[37,11],[[30,0,["popoverController","show"]]],null]],null]],null],[12],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[11,"button"],[23,5,[30,4]],[16,"aria-label",[30,5]],[24,4,"button"],[4,[38,16],[true],null],[12],[1,"\\n "],[13],[1,"\\n"]],[]]]],[4,5]]],[13],[1,"\\n"]],["@type","&attrs","@position","style","label","@disabled","@item","Actions","@oncreate","@service","Actions","Actions"],false,["let","concat","if","eq","not","informed-action","did-insert","set","t","on","fn","optional","env","href-to","with-overlay","hash","disabled"]]',moduleName:"consul-ui/components/topology-metrics/popover/index.hbs",isStrictMode:!1}) +class i extends l.default{}e.default=i,(0,t.setComponentTemplate)(r,i)})),define("consul-ui/components/topology-metrics/series/index",["exports","@ember/component","@ember/template-factory","dayjs","dayjs/plugin/calendar","d3-selection","d3-scale","d3-scale-chromatic","d3-shape","d3-array","@ember/object"],(function(e,t,n,l,r,i,o,a,u,s,c){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const d=(0,n.createTemplateFactory)({id:"ICVZQmrA",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1]],null],[[[1," "],[8,[39,2],null,[["@src","@onchange","@onerror"],[[28,[37,3],["/${partition}/${nspace}/${dc}/metrics/summary-for-service/${service}/${protocol}",[28,[37,4],null,[["nspace","partition","dc","service","protocol"],[[30,2],[30,3],[30,4],[30,5],[30,6]]]]],null],[28,[37,5],[[30,0],"change"],null],[28,[37,5],[[30,0],[28,[37,6],[[33,7]],null]],[["value"],["error"]]]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[1,[28,[35,8],["resize",[28,[37,5],[[30,0],"redraw"],null]],null]],[1,"\\n"],[1,[28,[35,9],[[28,[37,5],[[30,0],"redraw"],null]],null]],[1,"\\n\\n"],[41,[28,[37,1],[[33,10]],null],[[[41,[33,11,["labels"]],[[[1," "],[11,3],[24,0,"sparkline-key-link"],[4,[38,12],["click",[28,[37,13],[[30,0,["modal","open"]]],null]],null],[12],[1,"\\n Key\\n "],[13],[1,"\\n"]],[]],null]],[]],null],[1,"\\n"],[10,0],[14,0,"sparkline-wrapper"],[12],[1,"\\n "],[10,0],[14,0,"tooltip"],[12],[1,"\\n "],[10,0],[14,0,"sparkline-time"],[12],[1,"Timestamp"],[13],[1,"\\n "],[13],[1,"\\n"],[41,[33,10],[[[1," "],[8,[39,14],null,[["@noMetricsReason","@error"],[[30,1],[99,7,["@error"]]]],null],[1,"\\n"]],[]],null],[1," "],[10,"svg"],[14,0,"sparkline"],[12],[13],[1,"\\n"],[13],[1,"\\n\\n"],[8,[39,15],[[24,0,"sparkline-key"]],[["@aria"],[[28,[37,4],null,[["label"],["Metrics Key"]]]]],[["default"],[[[[1,"\\n "],[8,[39,16],null,[["@target","@name","@value"],[[30,0],"modal",[30,7]]],null],[1,"\\n "],[8,[39,17],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h3"],[12],[1,"Metrics Key"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,17],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"sparkline-key-content"],[12],[1,"\\n "],[10,2],[12],[1,"This key describes the metrics corresponding to the graph tooltip labels in more detail."],[13],[1,"\\n "],[10,"dl"],[12],[1,"\\n"],[42,[28,[37,19],[[33,11,["labels"]]],null],null,[[[1," "],[10,"dt"],[12],[1,[30,9]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,8]],[13],[1,"\\n"]],[8,9]],null],[1," "],[13],[1,"\\n"],[41,[51,[33,11,["labels"]]],[[[1," "],[10,1],[14,0,"no-data"],[12],[1,"No metrics loaded."],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,17],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"button"],[14,0,"type-cancel"],[15,"onclick",[28,[37,5],[[30,0],[30,7,["close"]]],null]],[14,4,"button"],[12],[1,"\\n Close\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[7]]]]]],["@noMetricsReason","@nspace","@partition","@dc","@service","@protocol","modal","desc","label"],false,["if","not","data-source","uri","hash","action","mut","error","on-window","did-insert","empty","data","on","optional","topology-metrics/status","modal-dialog","ref","block-slot","each","-each-in","unless"]]',moduleName:"consul-ui/components/topology-metrics/series/index.hbs",isStrictMode:!1}) +l.default.extend(r.default) +var p=(0,t.setComponentTemplate)(d,t.default.extend({data:null,empty:!1,actions:{redraw:function(e){this.drawGraphs()},change:function(e){this.set("data",e.data.series),this.drawGraphs(),this.rerender()}},drawGraphs:function(){if(!this.data)return void(0,c.set)(this,"empty",!0) +let e=this.svg=(0,i.select)(this.element.querySelector("svg.sparkline")) +e.on("mouseover mousemove mouseout",null),e.selectAll("path").remove(),e.selectAll("rect").remove() +let t=e.node().getBoundingClientRect(),n=t.width,l=t.height,r=this.data||{},d=r.data||[],p=r.labels||{},f=r.unitSuffix||"",m=Object.keys(p).filter((e=>"Total"!=e)) +if(0==d.length||0==m.length)return void(0,c.set)(this,"empty",!0);(0,c.set)(this,"empty",!1) +let h=(0,u.stack)().keys(m).order(u.stackOrderReverse)(d),b=d.map((e=>{let t=0 +return m.forEach((n=>{t+=e[n]})),t})),y=(0,o.scaleTime)().domain((0,s.extent)(d,(e=>e.time))).range([0,n]),v=(0,o.scaleLinear)().domain([0,(0,s.max)(b)]).range([l,0]),g=(0,u.area)().x((e=>y(e.data.time))).y1((e=>v(e[0]))).y0((e=>v(e[1]))),O=["#DCE0E6","#C73445"].concat(a.schemeTableau10) +m.includes("Outbound")&&(O=["#DCE0E6","#0E40A3"].concat(a.schemeTableau10)) +let P=(0,o.scaleOrdinal)(O).domain(m) +e.selectAll("path").data(h).join("path").attr("fill",(e=>{let{key:t}=e +return P(t)})).attr("stroke",(e=>{let{key:t}=e +return P(t)})).attr("d",g) +let w=e.append("rect").attr("class","cursor").style("visibility","hidden").attr("width",1).attr("height",l).attr("x",0).attr("y",0),x=(0,i.select)(this.element.querySelector(".tooltip")) +for(var j of(x.selectAll(".sparkline-tt-legend").remove(),x.selectAll(".sparkline-tt-sum").remove(),m)){let e=x.append("div").attr("class","sparkline-tt-legend") +e.append("div").attr("class","sparkline-tt-legend-color").style("background-color",P(j)),e.append("span").text(j).append("span").attr("class","sparkline-tt-legend-value")}let _=x.selectAll(".sparkline-tt-legend-value") +m.length>1&&x.append("div").attr("class","sparkline-tt-sum").append("span").text("Total").append("span").attr("class","sparkline-tt-sum-value") +let S=this +e.on("mouseover",(function(e){x.style("visibility","visible"),w.style("visibility","visible"),S.updateTooltip(e,d,h,b,f,y,x,_,w)})).on("mousemove",(function(e){S.updateTooltip(e,d,h,b,f,y,x,_,w)})).on("mouseout",(function(e){x.style("visibility","hidden"),w.style("visibility","hidden")}))},willDestroyElement:function(){this._super(...arguments),void 0!==this.svg&&this.svg.on("mouseover mousemove mouseout",null)},updateTooltip:function(e,t,n,r,o,a,u,c,d){let[p]=(0,i.pointer)(e) +d.attr("x",p) +let m=a.invert(p) +var h=(0,s.bisector)((function(e){return e.time})).left +let b=h(t,m) +var y +u.style("left",p-22+"px").select(".sparkline-time").text((y=m,(0,l.default)(y).calendar(null,{sameDay:"[Today at] h:mm:ss A",lastDay:"[Yesterday at] h:mm:ss A",lastWeek:"[Last] dddd at h:mm:ss A",sameElse:"MMM DD at h:mm:ss A"}))),u.select(".sparkline-tt-sum-value").text(`${f(r[b])}${o}`),c.nodes().forEach(((e,t)=>{let l=n[t][b][1]-n[t][b][0];(0,i.select)(e).text(`${f(l)}${o}`)})),d.attr("x",p)}})) +function f(e){return e<1e3?Number.isInteger(e)?""+e:Number(e>=100?e.toPrecision(3):e<1?e.toFixed(2):e.toPrecision(2)):e>=1e3&&e<1e6?+(e/1e3).toPrecision(3)+"k":e>=1e6&&e<1e9?+(e/1e6).toPrecision(3)+"m":e>=1e9&&e<1e12?+(e/1e9).toPrecision(3)+"g":e>=1e12?+(e/1e12).toFixed(0)+"t":void 0}e.default=p})),define("consul-ui/components/topology-metrics/source-type/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"gRMRAVqf",block:'[[[1,"\\n"],[11,1],[24,0,"topology-metrics-source-type"],[4,[38,0],[[28,[37,1],[[28,[37,2],["components.consul.topology-metrics.source-type.",[30,1],".tooltip"],null]],null]],null],[12],[1,"\\n "],[1,[28,[35,1],[[28,[37,2],["components.consul.topology-metrics.source-type.",[30,1],".text"],null]],null]],[1,"\\n"],[13]],["@source"],false,["tooltip","t","concat"]]',moduleName:"consul-ui/components/topology-metrics/source-type/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/topology-metrics/stats/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object"],(function(e,t,n,l,r,i){var o,a,u +function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const d=(0,n.createTemplateFactory)({id:"hkoroSIm",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1]],null],[[[1," "],[8,[39,2],null,[["@src","@onchange","@onerror"],[[28,[37,3],["/${partition}/${nspace}/${dc}/metrics/${endpoint}/${service}/${protocol}",[28,[37,4],null,[["nspace","partition","dc","endpoint","service","protocol"],[[30,2],[30,3],[30,4],[30,5],[30,6],[28,[37,5],[[30,7],""],null]]]]],null],[28,[37,6],[[30,0],"statsUpdate"],null],[28,[37,6],[[30,0],[28,[37,7],[[33,8]],null]],[["value"],["error"]]]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[11,0],[17,8],[24,0,"topology-metrics-stats"],[12],[1,"\\n"],[41,[33,9],[[[42,[28,[37,11],[[28,[37,11],[[33,12]],null]],null],null,[[[1," "],[11,"dl"],[4,[38,13],[[30,9,["desc"]]],[["options"],[[28,[37,4],null,[["allowHTML"],[true]]]]]],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[1,[30,9,["value"]]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,9,["label"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[9]],[[[1," "],[10,1],[12],[1,"No Metrics Available"],[13],[1,"\\n"]],[]]]],[]],[[[1," "],[8,[39,14],null,[["@noMetricsReason","@error"],[[30,1],[99,8,["@error"]]]],null],[1,"\\n"]],[]]],[13]],["@noMetricsReason","@nspace","@partition","@dc","@endpoint","@service","@protocol","&attrs","stat"],false,["if","not","data-source","uri","hash","or","action","mut","error","hasLoaded","each","-track-array","stats","tooltip","topology-metrics/status"]]',moduleName:"consul-ui/components/topology-metrics/stats/index.hbs",isStrictMode:!1}) +let p=(o=class extends l.default{constructor(){super(...arguments),s(this,"stats",a,this),s(this,"hasLoaded",u,this)}statsUpdate(e){if("summary-for-service"==this.args.endpoint)this.stats=e.data.stats +else{let t=this.args.nspace||"" +0===t.length&&(t="default") +let n=`${this.args.item}.${t}.${this.args.dc}` +this.stats=e.data.stats[n]}this.stats=(this.stats||[]).slice(0,4),this.hasLoaded=!0}},a=c(o.prototype,"stats",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return null}}),u=c(o.prototype,"hasLoaded",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return!1}}),c(o.prototype,"statsUpdate",[i.action],Object.getOwnPropertyDescriptor(o.prototype,"statsUpdate"),o.prototype),o) +e.default=p,(0,t.setComponentTemplate)(d,p)})),define("consul-ui/components/topology-metrics/status/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"sKBKTTRI",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1],[30,2]],null],[[[1," "],[10,1],[14,0,"topology-metrics-status-error"],[12],[1,"\\n"],[41,[28,[37,2],[[30,1],"ingress-gateway"],null],[[[1," "],[1,[28,[35,3],["components.consul.topology-metrics.status.ingress-gateway"],null]],[1,"\\n"]],[]],[[[41,[28,[37,2],[[30,1],"remote-dc"],null],[[[1," "],[1,[28,[35,3],["components.consul.topology-metrics.status.error"],null]],[1,"\\n "],[11,1],[4,[38,4],[[28,[37,3],["components.consul.topology-metrics.status.remote-dc"],null]],null],[12],[13],[1,"\\n"]],[]],[[[41,[30,2],[[[1," "],[1,[28,[35,3],["components.consul.topology-metrics.status.error"],null]],[1,"\\n "]],[]],null]],[]]]],[]]],[1," "],[13],[1,"\\n"]],[]],[[[1," "],[10,1],[14,0,"topology-metrics-status-loader"],[12],[1,[28,[35,3],["components.consul.topology-metrics.status.loading"],null]],[13],[1,"\\n"]],[]]]],["@noMetricsReason","@error"],false,["if","or","eq","t","tooltip"]]',moduleName:"consul-ui/components/topology-metrics/status/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/components/topology-metrics/up-lines/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@glimmer/tracking","@ember/object","@ember/service"],(function(e,t,n,l,r,i,o){var a,u,s,c +function d(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function p(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const f=(0,n.createTemplateFactory)({id:"F6bhXeuI",block:'[[[1,"\\n"],[41,[28,[37,1],[[30,1,["length"]],0],null],[[[1," "],[11,"svg"],[16,"viewBox",[28,[37,2],[[30,2,["x"]]," ",[30,3,["y"]]," ",[30,3,["width"]]," ",[30,3,["height"]]],null]],[24,"preserveAspectRatio","none"],[4,[38,3],[[30,0,["getIconPositions"]]],null],[4,[38,4],[[30,0,["getIconPositions"]],[30,1]],null],[12],[1,"\\n "],[10,"defs"],[12],[1,"\\n "],[10,"marker"],[15,1,[28,[37,2],[[30,0,["guid"]],"-allow-dot"],null]],[14,0,"allow-dot"],[14,"viewBox","-2 -2 15 15"],[14,"refX","6"],[14,"refY","6"],[14,"markerWidth","6"],[14,"markerHeight","6"],[12],[1,"\\n "],[10,"circle"],[14,"cx","6"],[14,"cy","6"],[14,"r","6"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"marker"],[15,1,[28,[37,2],[[30,0,["guid"]],"-allow-arrow"],null]],[14,0,"allow-arrow"],[14,"viewBox","-1 -1 12 12"],[14,"refX","5"],[14,"refY","5"],[14,"markerWidth","6"],[14,"markerHeight","6"],[14,"orient","auto-start-reverse"],[12],[1,"\\n "],[10,"polygon"],[14,"points","0 0 10 5 0 10"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"marker"],[15,1,[28,[37,2],[[30,0,["guid"]],"-deny-dot"],null]],[14,0,"deny-dot"],[14,"viewBox","-2 -2 15 15"],[14,"refX","6"],[14,"refY","6"],[14,"markerWidth","6"],[14,"markerHeight","6"],[12],[1,"\\n "],[10,"circle"],[14,"cx","6"],[14,"cy","6"],[14,"r","6"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"marker"],[15,1,[28,[37,2],[[30,0,["guid"]],"-deny-arrow"],null]],[14,0,"deny-arrow"],[14,"viewBox","-1 -1 12 12"],[14,"refX","5"],[14,"refY","5"],[14,"markerWidth","6"],[14,"markerHeight","6"],[14,"orient","auto-start-reverse"],[12],[1,"\\n "],[10,"polygon"],[14,"points","0 0 10 5 0 10"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[42,[28,[37,6],[[28,[37,6],[[30,1]],null]],null],null,[[[41,[28,[37,7],[[30,4,["permission"]],"deny"],null],[[[1," "],[10,"path"],[15,1,[28,[37,2],[[30,0,["guid"]],[30,4,["id"]]],null]],[15,"d",[28,[37,8],[[30,4,["dest"]]],[["src"],[[30,4,["src"]]]]]],[15,"marker-start",[28,[37,2],["url(#",[30,0,["guid"]],"-deny-dot)"],null]],[15,"marker-end",[28,[37,2],["url(#",[30,0,["guid"]],"-deny-arrow)"],null]],[15,"data-permission",[30,4,["permission"]]],[12],[13],[1,"\\n"]],[]],[[[1," "],[10,"path"],[15,1,[28,[37,2],[[30,0,["guid"]],[30,4,["id"]]],null]],[15,"d",[28,[37,8],[[30,4,["dest"]]],[["src"],[[30,4,["src"]]]]]],[15,"marker-start",[28,[37,2],["url(#",[30,0,["guid"]],"-allow-dot)"],null]],[15,"marker-end",[28,[37,2],["url(#",[30,0,["guid"]],"-allow-arrow)"],null]],[15,"data-permission",[30,4,["permission"]]],[12],[13],[1,"\\n"]],[]]]],[4]],null],[1," "],[13],[1,"\\n"]],[]],null],[42,[28,[37,6],[[28,[37,6],[[30,5]],null]],null],null,[[[41,[28,[37,9],[[28,[37,10],[[30,6,["Datacenter"]],""],null],[28,[37,11],[[28,[37,12],[[30,6,["Intention","Allowed"]]],null],[30,6,["Intention","HasPermissions"]]],null]],null],[[[1," "],[8,[39,13],null,[["@type","@position","@item","@disabled","@oncreate"],[[52,[30,6,["Intention","HasPermissions"]],"l7","deny"],[28,[37,14],["id",[28,[37,2],[[30,0,["guid"]],[30,6,["Namespace"]],[30,6,["Name"]]],null],[30,0,["iconPositions"]]],null],[30,6],false,[28,[37,15],[[30,0],[30,7],[30,8],[30,6]],null]]],null],[1,"\\n"]],[]],null]],[6]],null]],["@lines","@center","@view","line","@items","item","@oncreate","@service"],false,["if","gt","concat","did-insert","did-update","each","-track-array","eq","svg-curve","and","not-eq","or","not","topology-metrics/popover","find-by","action"]]',moduleName:"consul-ui/components/topology-metrics/up-lines/index.hbs",isStrictMode:!1}) +let m=(a=(0,o.inject)("dom"),u=class extends l.default{constructor(){super(...arguments),d(this,"iconPositions",s,this),d(this,"dom",c,this)}get guid(){return this.dom.guid(this)}getIconPositions(){const e=this.args.center,t=this.args.view,n=[...document.querySelectorAll("#upstream-lines path")] +this.iconPositions=n.map((n=>{const l=parseFloat(n.getTotalLength()),r=n.getPointAtLength(Math.ceil(.666*l)) +return{id:n.id,x:Math.round(r.x-e.x),y:Math.round(r.y-t.y)}}))}},s=p(u.prototype,"iconPositions",[r.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=p(u.prototype,"dom",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p(u.prototype,"getIconPositions",[i.action],Object.getOwnPropertyDescriptor(u.prototype,"getIconPositions"),u.prototype),u) +e.default=m,(0,t.setComponentTemplate)(f,m)})),define("consul-ui/components/torii-iframe-placeholder",["exports","torii/components/torii-iframe-placeholder"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=t.default +e.default=n})),define("consul-ui/components/vertical-collection",["exports","@html-next/vertical-collection/components/vertical-collection/component"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/watcher/index",["exports","@ember/component","@ember/template-factory","@glimmer/component","@ember/object","@glimmer/tracking","@ember/runloop","@ember/service"],(function(e,t,n,l,r,i,o,a){var u,s,c,d +function p(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function f(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const m=(0,n.createTemplateFactory)({id:"jSQtkZfW",block:'[[[1,"\\n"],[18,1,[[28,[37,1],null,[["fns"],[[28,[37,1],null,[["start","stop"],[[30,0,["start"]],[30,0,["stop"]]]]]]]]]],[1,"\\n"]],["&default"],false,["yield","hash"]]',moduleName:"consul-ui/components/watcher/index.hbs",isStrictMode:!1}) +let h=(u=class extends l.default{constructor(){super(...arguments),p(this,"env",s,this),p(this,"_isPolling",c,this),p(this,"cancel",d,this)}get timeout(){return this.isTesting?300:this.args.timeout||1e4}get isTesting(){return"testing"===this.env.var("environment")}get isPolling(){const{isTesting:e,_isPolling:t}=this +return!e&&t}start(){this._isPolling=!0,this.watchTask()}stop(){this._isPolling=!1,(0,o.cancel)(this.cancel)}watchTask(){const e=(0,o.later)(this,(()=>{var e,t +null===(e=(t=this.args).watch)||void 0===e||e.call(t),this.isPolling&&this.watchTask()}),this.timeout) +this.cancel=e}},s=f(u.prototype,"env",[a.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=f(u.prototype,"_isPolling",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return!1}}),d=f(u.prototype,"cancel",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return null}}),f(u.prototype,"start",[r.action],Object.getOwnPropertyDescriptor(u.prototype,"start"),u.prototype),f(u.prototype,"stop",[r.action],Object.getOwnPropertyDescriptor(u.prototype,"stop"),u.prototype),u) +e.default=h,(0,t.setComponentTemplate)(m,h)})),define("consul-ui/components/yield-slot",["exports","block-slots/components/yield-slot"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/components/yield/index",["exports","@ember/component","@ember/template-factory","@ember/component/template-only"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.createTemplateFactory)({id:"OlSTyydz",block:'[[[1,"\\n"],[18,1,null],[1,"\\n"]],["&default"],false,["yield"]]',moduleName:"consul-ui/components/yield/index.hbs",isStrictMode:!1}) +var i=(0,t.setComponentTemplate)(r,(0,l.default)()) +e.default=i})),define("consul-ui/controllers/_peered-resource",["exports","@ember/controller","@ember/service"],(function(e,t,n){var l,r +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let i=(l=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="abilities",l=this,(n=r)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}get _searchProperties(){const{searchProperties:e}=this +return this.abilities.can("use peers")?e:e.filter((e=>"PeerName"!==e))}},o=l.prototype,a="abilities",u=[n.inject],s={configurable:!0,enumerable:!0,writable:!0,initializer:null},d={},Object.keys(s).forEach((function(e){d[e]=s[e]})),d.enumerable=!!d.enumerable,d.configurable=!!d.configurable,("value"in d||d.initializer)&&(d.writable=!0),d=u.slice().reverse().reduce((function(e,t){return t(o,a,e)||e}),d),c&&void 0!==d.initializer&&(d.value=d.initializer?d.initializer.call(c):void 0,d.initializer=void 0),void 0===d.initializer&&(Object.defineProperty(o,a,d),d=null),r=d,l) +var o,a,u,s,c,d +e.default=i})),define("consul-ui/controllers/application",["exports","@ember/service","@ember/controller","@ember/application","@ember/object","consul-ui/utils/routing/transitionable"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p +function f(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function m(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let h=(o=(0,t.inject)("router"),a=(0,t.inject)("store"),u=(0,t.inject)("feedback"),s=class extends n.default{constructor(){super(...arguments),f(this,"router",c,this),f(this,"store",d,this),f(this,"feedback",p,this)}reauthorize(e){this.feedback.execute((()=>{this.store.invalidate() +const t={} +if(e.data){const n=e.data +if(void 0!==this.nspace){const e=(0,r.get)(n,"Namespace")||this.nspace.Name +e!==this.nspace.Name&&(t.nspace=`${e}`)}}const n=(0,l.getOwner)(this),o=this.router.currentRoute.name,a=n.lookup(`route:${o}`) +return n.lookup("route:application").refresh().promise.catch((function(e){})).then((e=>o!==this.router.currentRouteName||void 0!==t.nspace?a.transitionTo(...(0,i.default)(this.router.currentRoute,t,n)):e))}),e.type,(function(e,t){return e}),{})}},c=m(s.prototype,"router",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=m(s.prototype,"store",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=m(s.prototype,"feedback",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m(s.prototype,"reauthorize",[r.action],Object.getOwnPropertyDescriptor(s.prototype,"reauthorize"),s.prototype),s) +e.default=h})),define("consul-ui/controllers/dc/acls/policies/create",["exports","consul-ui/controllers/dc/acls/policies/edit"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{}e.default=n})) +define("consul-ui/controllers/dc/acls/policies/edit",["exports","@ember/service","@ember/controller"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,t.inject)("form"),r=class extends n.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="builder",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}init(){super.init(...arguments),this.form=this.builder.form("policy")}setProperties(e){super.setProperties(Object.keys(e).reduce(((e,t,n)=>{if("item"===t)e[t]=this.form.setData(e[t]).getData() +return e}),e))}},a=r.prototype,u="builder",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/controllers/dc/acls/roles/create",["exports","consul-ui/controllers/dc/acls/roles/edit"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{}e.default=n})),define("consul-ui/controllers/dc/acls/roles/edit",["exports","@ember/service","@ember/controller"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,t.inject)("form"),r=class extends n.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="builder",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}init(){super.init(...arguments),this.form=this.builder.form("role")}setProperties(e){super.setProperties(Object.keys(e).reduce(((e,t,n)=>{if("item"===t)e[t]=this.form.setData(e[t]).getData() +return e}),e))}},a=r.prototype,u="builder",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/controllers/dc/acls/tokens/create",["exports","consul-ui/controllers/dc/acls/tokens/edit"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{}e.default=n})),define("consul-ui/controllers/dc/acls/tokens/edit",["exports","@ember/controller","@ember/service"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l=t.default.extend({dom:(0,n.inject)("dom"),builder:(0,n.inject)("form"),isScoped:!1,init:function(){this._super(...arguments),this.form=this.builder.form("token")},setProperties:function(e){this._super(Object.keys(e).reduce(((e,t,n)=>{if("item"===t)e[t]=this.form.setData(e[t]).getData() +return e}),e))},actions:{change:function(e,t,n){const l=this.dom.normalizeEvent(e,t),r=this.form +try{r.handleEvent(l)}catch(i){throw l.target.name,i}}}}) +e.default=l})),define("consul-ui/controllers/dc/nodes/index",["exports","consul-ui/controllers/_peered-resource"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{}e.default=n})),define("consul-ui/controllers/dc/peers/index",["exports","@ember/controller","@ember/service"],(function(e,t,n){var l,r +function i(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="router",l=this,(n=r)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),i(this,"redirectToPeerShow",((e,t)=>{null==e||e(),this.router.transitionTo("dc.peers.show",t.Name)}))}},a=l.prototype,u="router",s=[n.inject],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),r=p,l) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/controllers/dc/peers/show/exported",["exports","@ember/controller","@glimmer/tracking","@ember/object"],(function(e,t,n,l){var r,i +function o(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let u=(r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),o(this,"queryParams",{search:{as:"filter"}}),e=this,t="search",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}updateSearch(e){this.search=e}},i=a(r.prototype,"search",[n.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return""}}),a(r.prototype,"updateSearch",[l.action],Object.getOwnPropertyDescriptor(r.prototype,"updateSearch"),r.prototype),r) +e.default=u})),define("consul-ui/controllers/dc/peers/show/index",["exports","@ember/controller","@ember/service","@ember/object"],(function(e,t,n,l){var r,i +function o(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let a=(r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="router",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}transitionToImported(){this.router.replaceWith("dc.peers.show.imported")}},i=o(r.prototype,"router",[n.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o(r.prototype,"transitionToImported",[l.action],Object.getOwnPropertyDescriptor(r.prototype,"transitionToImported"),r.prototype),r) +e.default=a})),define("consul-ui/controllers/dc/services/index",["exports","consul-ui/controllers/_peered-resource"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{}e.default=n})),define("consul-ui/controllers/dc/services/instance/healthchecks",["exports","@ember/controller","@ember/object"],(function(e,t,n){var l +function r(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let i=(r((l=class extends t.default{syntheticNodeSearchPropertyFilter(e,t){var n +return!(null!==(n=e.Node.Meta)&&void 0!==n&&n["synthetic-node"]&&"Node"===t)}syntheticNodeHealthCheckFilter(e,t,n,l){var r +return!(null!==(r=e.Node.Meta)&&void 0!==r&&r["synthetic-node"]&&"node"===(null==t?void 0:t.Kind))}}).prototype,"syntheticNodeSearchPropertyFilter",[n.action],Object.getOwnPropertyDescriptor(l.prototype,"syntheticNodeSearchPropertyFilter"),l.prototype),r(l.prototype,"syntheticNodeHealthCheckFilter",[n.action],Object.getOwnPropertyDescriptor(l.prototype,"syntheticNodeHealthCheckFilter"),l.prototype),l) +e.default=i})),define("consul-ui/data-adapter",["exports","@ember-data/debug"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/decorators/data-source",["exports","@ember/debug","wayfarer"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.match=e.default=void 0 +const l=(0,n.default)(),r={} +e.default=e=>(n,i,o)=>((0,t.runInDebug)((()=>{r[e]={cls:n,method:i}})),l.on(e,(function(e,t,l){const r=t.lookup("service:container").get(n) +return t=>o.value.apply(r,[e,t,l])})),o) +e.match=e=>l.match(e),(0,t.runInDebug)((()=>{window.DataSourceRoutes=()=>{const e=window.ConsulUi.__container__.lookup("service:container"),t=window.open("","_blank") +t.document.write(`\n\n
      \n${Object.entries(r).map((t=>{let[n,l]=t,r=e.keyForClass(l.cls).split("/").pop()
      +return r=r.split("-").map((e=>`${e[0].toUpperCase()}${e.substr(1)}`)).join(""),`${n}\n      ${r}Repository.${l.method}(params)\n\n`})).join("")}\n  
      \n\n `),t.focus()}}))})),define("consul-ui/decorators/replace",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.replace=e.nullValue=e.default=void 0 +const t=(e,t)=>(n,l,r)=>({get:function(){const n=r.get.apply(this,arguments) +return n===e?t:n},set:function(){return r.set.apply(this,arguments)}}) +e.replace=t +e.nullValue=function(e){return t(null,e)} +var n=t +e.default=n})),define("consul-ui/env",["exports","consul-ui/config/environment","consul-ui/utils/get-environment"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.env=void 0 +const l=(0,n.default)(t.default,window,document) +e.env=l})),define("consul-ui/filter/predicates/auth-method",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={kind:{kubernetes:(e,t)=>e.Type===t,jwt:(e,t)=>e.Type===t,oidc:(e,t)=>e.Type===t},source:{local:(e,t)=>e.TokenLocality===t,global:(e,t)=>e.TokenLocality===t}}})),define("consul-ui/filter/predicates/health-check",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={status:{passing:(e,t)=>e.Status===t,warning:(e,t)=>e.Status===t,critical:(e,t)=>e.Status===t},kind:{service:(e,t)=>e.Kind===t,node:(e,t)=>e.Kind===t},check:{serf:(e,t)=>e.Type===t,script:(e,t)=>e.Type===t,http:(e,t)=>e.Type===t,tcp:(e,t)=>e.Type===t,ttl:(e,t)=>e.Type===t,docker:(e,t)=>e.Type===t,grpc:(e,t)=>e.Type===t,alias:(e,t)=>e.Type===t}}})),define("consul-ui/filter/predicates/intention",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={access:{allow:(e,t)=>e.Action===t,deny:(e,t)=>e.Action===t,"app-aware":(e,t)=>void 0===e.Action}}})),define("consul-ui/filter/predicates/kv",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={kind:{folder:(e,t)=>e.isFolder,key:(e,t)=>!e.isFolder}}})),define("consul-ui/filter/predicates/node",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={status:{passing:(e,t)=>e.Status===t,warning:(e,t)=>e.Status===t,critical:(e,t)=>e.Status===t},version:(e,t)=>{for(const n of t)if(e.Version.includes(n+"."))return!0 +return!1}}})),define("consul-ui/filter/predicates/peer",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={state:{pending:(e,t)=>e.State.toLowerCase()===t,establishing:(e,t)=>e.State.toLowerCase()===t,active:(e,t)=>e.State.toLowerCase()===t,failing:(e,t)=>e.State.toLowerCase()===t,terminated:(e,t)=>e.State.toLowerCase()===t,deleting:(e,t)=>e.State.toLowerCase()===t}}})),define("consul-ui/filter/predicates/policy",["exports","mnemonist/set"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n={kind:{"global-management":(e,t)=>e.isGlobalManagement,standard:(e,t)=>!e.isGlobalManagement},datacenter:(e,n)=>void 0===e.Datacenters||t.default.intersectionSize(n,new Set(e.Datacenters))>0} +e.default=n})),define("consul-ui/filter/predicates/service-instance",["exports","mnemonist/set"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n={status:{passing:(e,t)=>e.Status===t,warning:(e,t)=>e.Status===t,critical:(e,t)=>e.Status===t,empty:(e,t)=>0===e.ServiceChecks.length},source:(e,n)=>0!==t.default.intersectionSize(n,new Set(e.ExternalSources||[]))} +e.default=n})),define("consul-ui/filter/predicates/service",["exports","mnemonist/set"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n={kind:{"api-gateway":(e,t)=>e.Kind===t,"ingress-gateway":(e,t)=>e.Kind===t,"terminating-gateway":(e,t)=>e.Kind===t,"mesh-gateway":(e,t)=>e.Kind===t,service:(e,t)=>!e.Kind,"in-mesh":(e,t)=>e.InMesh,"not-in-mesh":(e,t)=>!e.InMesh},status:{passing:(e,t)=>e.MeshStatus===t,warning:(e,t)=>e.MeshStatus===t,critical:(e,t)=>e.MeshStatus===t,empty:(e,t)=>0===e.MeshChecksTotal,unknown:e=>e.peerIsFailing||e.isZeroCountButPeered},instance:{registered:(e,t)=>e.InstanceCount>0,"not-registered":(e,t)=>0===e.InstanceCount},source:(e,n)=>{let l=!1 +return n.includes("consul")&&(l=!e.ExternalSources||0===e.ExternalSources.length||1===e.ExternalSources.length&&""===e.ExternalSources[0]||e.PeerName),0!==t.default.intersectionSize(n,new Set(e.ExternalSources||[]))||n.includes(e.Partition)||l}} +e.default=n})),define("consul-ui/filter/predicates/token",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={kind:{"global-management":(e,t)=>e.isGlobalManagement,global:(e,t)=>!e.Local,local:(e,t)=>e.Local}}})),define("consul-ui/flash/object",["exports","ember-cli-flash/flash/object"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/formats",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={time:{hhmmss:{hour:"numeric",minute:"numeric",second:"numeric"}},date:{hhmmss:{hour:"numeric",minute:"numeric",second:"numeric"}},number:{compact:{notation:"compact"},EUR:{style:"currency",currency:"EUR",minimumFractionDigits:2,maximumFractionDigits:2},USD:{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}}}})),define("consul-ui/forms/intention",["exports","consul-ui/validations/intention","consul-ui/utils/form/builder"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.default,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:l +return i(n,{}).setValidators(r)} +const l=(0,n.default)()})),define("consul-ui/forms/kv",["exports","consul-ui/validations/kv","consul-ui/utils/form/builder"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.default,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:l +return i(n,{}).setValidators(r)} +const l=(0,n.default)()})),define("consul-ui/forms/policy",["exports","consul-ui/validations/policy","consul-ui/utils/form/builder"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"policy",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.default,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:l +return i(n,{Datacenters:{type:"array"}}).setValidators(r)} +const l=(0,n.default)()})) +define("consul-ui/forms/role",["exports","consul-ui/validations/role","consul-ui/utils/form/builder"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"role",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.default,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:l +return i(n,{}).setValidators(r).add(e.form("policy"))} +const l=(0,n.default)()})),define("consul-ui/forms/token",["exports","consul-ui/validations/token","consul-ui/utils/form/builder"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.default,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:l +return i(n,{}).setValidators(r).add(e.form("policy")).add(e.form("role"))} +const l=(0,n.default)()})),define("consul-ui/helpers/-element",["exports","ember-element-helper/helpers/-element"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/abs",["exports","ember-math-helpers/helpers/abs"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"abs",{enumerable:!0,get:function(){return t.abs}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/acos",["exports","ember-math-helpers/helpers/acos"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"acos",{enumerable:!0,get:function(){return t.acos}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/acosh",["exports","ember-math-helpers/helpers/acosh"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"acosh",{enumerable:!0,get:function(){return t.acosh}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/add",["exports","ember-math-helpers/helpers/add"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"add",{enumerable:!0,get:function(){return t.add}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/adopt-styles",["exports","@ember/component/helper","@ember/debug","@lit/reactive-element"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class r extends t.default{compute(e,t){let[n,r]=e +Array.isArray(r)||(r=[r]),(0,l.adoptStyles)(n,r)}}e.default=r})),define("consul-ui/helpers/and",["exports","ember-truth-helpers/helpers/and"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"and",{enumerable:!0,get:function(){return t.and}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/app-version",["exports","@ember/component/helper","consul-ui/config/environment","ember-cli-app-version/utils/regexp"],(function(e,t,n,l){function r(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +const r=n.default.APP.version +let i=t.versionOnly||t.hideSha,o=t.shaOnly||t.hideVersion,a=null +return i&&(t.showExtended&&(a=r.match(l.versionExtendedRegExp)),a||(a=r.match(l.versionRegExp))),o&&(a=r.match(l.shaRegExp)),a?a[0]:r}Object.defineProperty(e,"__esModule",{value:!0}),e.appVersion=r,e.default=void 0 +var i=(0,t.helper)(r) +e.default=i})),define("consul-ui/helpers/append",["exports","ember-composable-helpers/helpers/append"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"append",{enumerable:!0,get:function(){return t.append}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-concat",["exports","ember-array-fns/helpers/array-concat"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayConcat",{enumerable:!0,get:function(){return t.arrayConcat}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-every",["exports","ember-array-fns/helpers/array-every"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayEvery",{enumerable:!0,get:function(){return t.arrayEvery}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-filter",["exports","ember-array-fns/helpers/array-filter"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayFilter",{enumerable:!0,get:function(){return t.arrayFilter}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-find-index",["exports","ember-array-fns/helpers/array-find-index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayFindIndex",{enumerable:!0,get:function(){return t.arrayFindIndex}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-find",["exports","ember-array-fns/helpers/array-find"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayFind",{enumerable:!0,get:function(){return t.arrayFind}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-includes",["exports","ember-array-fns/helpers/array-includes"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayIncludes",{enumerable:!0,get:function(){return t.arrayIncludes}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-index-of",["exports","ember-array-fns/helpers/array-index-of"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayIndexOf",{enumerable:!0,get:function(){return t.arrayIndexOf}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-is-array",["exports","ember-array-fns/helpers/array-is-array"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayIsArray",{enumerable:!0,get:function(){return t.arrayIsArray}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-is-first-element",["exports","ember-array-fns/helpers/array-is-first-element"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayIsFirstElement",{enumerable:!0,get:function(){return t.arrayIsFirstElement}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-is-last-element",["exports","ember-array-fns/helpers/array-is-last-element"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayIsLastElement",{enumerable:!0,get:function(){return t.arrayIsLastElement}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-join",["exports","ember-array-fns/helpers/array-join"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayJoin",{enumerable:!0,get:function(){return t.arrayJoin}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-last-index-of",["exports","ember-array-fns/helpers/array-last-index-of"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayLastIndexOf",{enumerable:!0,get:function(){return t.arrayLastIndexOf}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-map",["exports","ember-array-fns/helpers/array-map"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayMap",{enumerable:!0,get:function(){return t.arrayMap}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-reduce",["exports","ember-array-fns/helpers/array-reduce"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayReduce",{enumerable:!0,get:function(){return t.arrayReduce}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-reverse",["exports","ember-array-fns/helpers/array-reverse"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arrayReverse",{enumerable:!0,get:function(){return t.arrayReverse}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-slice",["exports","ember-array-fns/helpers/array-slice"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arraySlice",{enumerable:!0,get:function(){return t.arraySlice}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-some",["exports","ember-array-fns/helpers/array-some"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arraySome",{enumerable:!0,get:function(){return t.arraySome}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-sort",["exports","ember-array-fns/helpers/array-sort"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arraySort",{enumerable:!0,get:function(){return t.arraySort}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/array-splice",["exports","ember-array-fns/helpers/array-splice"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"arraySplice",{enumerable:!0,get:function(){return t.arraySplice}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) +define("consul-ui/helpers/asin",["exports","ember-math-helpers/helpers/asin"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"asin",{enumerable:!0,get:function(){return t.asin}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/asinh",["exports","ember-math-helpers/helpers/asinh"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"asinh",{enumerable:!0,get:function(){return t.asinh}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/assign",["exports","ember-assign-helper/helpers/assign"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"assign",{enumerable:!0,get:function(){return t.assign}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/atan",["exports","ember-math-helpers/helpers/atan"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"atan",{enumerable:!0,get:function(){return t.atan}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/atan2",["exports","ember-math-helpers/helpers/atan2"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"atan2",{enumerable:!0,get:function(){return t.atan2}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/atanh",["exports","ember-math-helpers/helpers/atanh"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"atanh",{enumerable:!0,get:function(){return t.atanh}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/atob",["exports","@ember/component/helper","consul-ui/utils/atob"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l=(0,t.helper)((function(e){let[t=""]=e +return(0,n.default)(t)})) +e.default=l})),define("consul-ui/helpers/block-params",["exports","block-slots/helpers/block-params"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/cached-model",["exports","@ember/component/helper","@ember/application"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{compute(e,t){let[l,r]=e +return(0,n.getOwner)(this).lookup(`service:repository/${l}`).cached(r)}}e.default=l})),define("consul-ui/helpers/call",["exports","ember-composable-helpers/helpers/call"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"call",{enumerable:!0,get:function(){return t.call}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/can",["exports","ember-can/helpers/can"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/cancel-all",["exports","ember-concurrency/helpers/cancel-all"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/cannot",["exports","ember-can/helpers/cannot"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/capitalize",["exports","ember-cli-string-helpers/helpers/capitalize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"capitalize",{enumerable:!0,get:function(){return t.capitalize}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/cbrt",["exports","ember-math-helpers/helpers/cbrt"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"cbrt",{enumerable:!0,get:function(){return t.cbrt}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/ceil",["exports","ember-math-helpers/helpers/ceil"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"ceil",{enumerable:!0,get:function(){return t.ceil}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/changeset-get",["exports","ember-changeset/helpers/changeset-get"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/changeset-set",["exports","ember-changeset/helpers/changeset-set"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"changesetSet",{enumerable:!0,get:function(){return t.changesetSet}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/changeset",["exports","ember-changeset-validations/helpers/changeset"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"changeset",{enumerable:!0,get:function(){return t.changeset}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/chunk",["exports","ember-composable-helpers/helpers/chunk"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"chunk",{enumerable:!0,get:function(){return t.chunk}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/class-map",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.helper)((e=>{const t=e.filter(Boolean).filter((e=>"string"==typeof e||e[e.length-1])).map((e=>"string"==typeof e?e:e[0])).join(" ") +return t.length>0?t:void 0})) +e.default=n})),define("consul-ui/helpers/classify",["exports","ember-cli-string-helpers/helpers/classify"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"classify",{enumerable:!0,get:function(){return t.classify}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/clz32",["exports","ember-math-helpers/helpers/clz32"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"clz32",{enumerable:!0,get:function(){return t.clz32}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/collection",["exports","@ember/component/helper","@ember/object","consul-ui/models/service","consul-ui/models/service-instance"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i={service:l.Collection,"service-instance":r.Collection} +class o{}class a extends t.default{compute(e,t){let[l,r]=e +if(l.length>0){const e=(0,n.get)(l,"firstObject")._internalModel.modelName +return new(0,i[e])(l)}return new o}}e.default=a})),define("consul-ui/helpers/compact",["exports","ember-composable-helpers/helpers/compact"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/compute",["exports","ember-composable-helpers/helpers/compute"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"compute",{enumerable:!0,get:function(){return t.compute}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/contains",["exports","ember-composable-helpers/helpers/contains"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"contains",{enumerable:!0,get:function(){return t.contains}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/cos",["exports","ember-math-helpers/helpers/cos"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"cos",{enumerable:!0,get:function(){return t.cos}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/cosh",["exports","ember-math-helpers/helpers/cosh"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"cosh",{enumerable:!0,get:function(){return t.cosh}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/css-map",["exports","@ember/component/helper","@lit/reactive-element"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l=(0,t.helper)((e=>e.filter((e=>e instanceof n.CSSResult||e[e.length-1])).map((e=>e instanceof n.CSSResult?e:e[0])))) +e.default=l})) +define("consul-ui/helpers/css",["exports","@ember/component/helper","@lit/reactive-element"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{compute(e,t){let[l]=e +return(0,n.css)([l])}}e.default=l})),define("consul-ui/helpers/dec",["exports","ember-composable-helpers/helpers/dec"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"dec",{enumerable:!0,get:function(){return t.dec}}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/did-insert",["exports","ember-render-helpers/helpers/did-insert"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/did-update",["exports","ember-render-helpers/helpers/did-update"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/div",["exports","ember-math-helpers/helpers/div"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"div",{enumerable:!0,get:function(){return t.div}})})),define("consul-ui/helpers/document-attrs",["exports","@ember/component/helper","@ember/service","@ember/debug","mnemonist/multi-map"],(function(e,t,n,l,r){var i,o,a +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const u=new Map,s=new WeakMap +let c=(i=(0,n.inject)("-document"),o=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="document",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){this.synchronize(this.document.documentElement,t)}willDestroy(){this.synchronize(this.document.documentElement),s.delete(this)}synchronize(e,t){const n=s.get(this) +return n&&Object.entries(n).forEach((e=>{let[t,n]=e,l=u.get(t) +void 0!==l&&[...new Set(n.split(" "))].map((e=>l.remove(e,this)))})),t&&(s.set(this,t),[...Object.entries(t)].forEach((e=>{let[t,n]=e,l=u.get(t) +void 0===l&&(l=new r.default(Set),u.set(t,l)),[...new Set(n.split(" "))].map((e=>{0===l.count(e)&&l.set(e,null),l.set(e,this)}))}))),[...u.entries()].forEach((t=>{let[n,r]=t,i="attr" +"class"===n?i=n:n.startsWith("data-")&&(i="data"),[...r.keys()].forEach((t=>{if(1===r.count(t)){if("class"===i)e.classList.remove(t) +else(0,l.runInDebug)((()=>{throw new Error(`${i} is not implemented yet`)})) +r.delete(t),0===r.size&&u.delete(n)}else if("class"===i)e.classList.add(t) +else(0,l.runInDebug)((()=>{throw new Error(`${i} is not implemented yet`)}))}))})),u}},d=o.prototype,p="document",f=[i],m={configurable:!0,enumerable:!0,writable:!0,initializer:null},b={},Object.keys(m).forEach((function(e){b[e]=m[e]})),b.enumerable=!!b.enumerable,b.configurable=!!b.configurable,("value"in b||b.initializer)&&(b.writable=!0),b=f.slice().reverse().reduce((function(e,t){return t(d,p,e)||e}),b),h&&void 0!==b.initializer&&(b.value=b.initializer?b.initializer.call(h):void 0,b.initializer=void 0),void 0===b.initializer&&(Object.defineProperty(d,p,b),b=null),a=b,o) +var d,p,f,m,h,b +e.default=c})),define("consul-ui/helpers/dom-position",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{compute(e,t){let[n]=e,{from:l,offset:r=!1}=t +return e=>{if("function"==typeof n){let t,i +if(r)i=e.currentTarget,t={width:i.offsetWidth,left:i.offsetLeft,height:i.offsetHeight,top:i.offsetTop} +else if(i=e.target,t=i.getBoundingClientRect(),void 0!==l){const e=l.getBoundingClientRect() +t.x=t.x-e.x,t.y=t.y-e.y}return n(t)}{const t=e.target,l=t.getBoundingClientRect() +n.forEach((e=>{let[n,r]=e +t.style[r]=`${l[n]}px`}))}}}}e.default=n})),define("consul-ui/helpers/drop",["exports","ember-composable-helpers/helpers/drop"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/duration-from",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,n.inject)("temporal"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="temporal",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){let[n]=e +return this.temporal.durationFrom(n)}},a=r.prototype,u="temporal",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/helpers/element",["exports","ember-element-helper/helpers/element"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/ember-power-select-is-group",["exports","ember-power-select/helpers/ember-power-select-is-group"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"emberPowerSelectIsGroup",{enumerable:!0,get:function(){return t.emberPowerSelectIsGroup}})})),define("consul-ui/helpers/ember-power-select-is-selected",["exports","ember-power-select/helpers/ember-power-select-is-selected"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"emberPowerSelectIsSelected",{enumerable:!0,get:function(){return t.emberPowerSelectIsSelected}})})),define("consul-ui/helpers/ensure-safe-component",["exports","@embroider/util"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.EnsureSafeComponentHelper}})})),define("consul-ui/helpers/entries",["exports","ember-composable-helpers/helpers/entries"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"entries",{enumerable:!0,get:function(){return t.entries}})})),define("consul-ui/helpers/env",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,n.inject)("env"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){let[n,l=""]=e +const r=this.env.var(n) +return null!=r?r:l}},a=r.prototype,u="env",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/helpers/eq",["exports","ember-truth-helpers/helpers/eq"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"equal",{enumerable:!0,get:function(){return t.equal}})})),define("consul-ui/helpers/exp",["exports","ember-math-helpers/helpers/exp"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"exp",{enumerable:!0,get:function(){return t.exp}})})),define("consul-ui/helpers/expm1",["exports","ember-math-helpers/helpers/expm1"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"expm1",{enumerable:!0,get:function(){return t.expm1}})})),define("consul-ui/helpers/filter-by",["exports","ember-composable-helpers/helpers/filter-by"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/filter",["exports","ember-composable-helpers/helpers/filter"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/find-by",["exports","ember-composable-helpers/helpers/find-by"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/fixed-grid-layout",["exports","@ember/component/helper","ember-collection/layouts/grid"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l=(0,t.helper)((function(e){return new n.default(e[0],e[1])})) +e.default=l})),define("consul-ui/helpers/flatten-property",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.helper)((function e(t,n){let[l,r]=t +const i=n.pages||[] +return i.push(...l.pages),l.children.forEach((t=>e([t],{pages:i}))),i})) +e.default=n})),define("consul-ui/helpers/flatten",["exports","ember-composable-helpers/helpers/flatten"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"flatten",{enumerable:!0,get:function(){return t.flatten}})})),define("consul-ui/helpers/floor",["exports","ember-math-helpers/helpers/floor"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"floor",{enumerable:!0,get:function(){return t.floor}})})),define("consul-ui/helpers/format-date",["exports","ember-intl/helpers/format-date"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/format-message",["exports","ember-intl/helpers/format-message"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/format-number",["exports","ember-intl/helpers/format-number"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/format-relative",["exports","ember-intl/helpers/format-relative"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/format-short-time",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.helper)((function(e,t){let n,l,r,i,[o]=e +i=Math.floor(o/1e3),r=Math.floor(i/60),i%=60,l=Math.floor(r/60),r%=60,n=Math.floor(l/24),l%=24 +const a=n,u=l,s=r,c=i +switch(!0){case 0!==a:return a+"d" +case 0!==u:return u+"h" +case 0!==s:return s+"m" +default:return c+"s"}})) +e.default=n})) +define("consul-ui/helpers/format-time",["exports","ember-intl/helpers/format-time"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/from-entries",["exports","ember-composable-helpers/helpers/from-entries"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"fromEntries",{enumerable:!0,get:function(){return t.fromEntries}})})),define("consul-ui/helpers/fround",["exports","ember-math-helpers/helpers/fround"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"fround",{enumerable:!0,get:function(){return t.fround}})})),define("consul-ui/helpers/gcd",["exports","ember-math-helpers/helpers/gcd"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"gcd",{enumerable:!0,get:function(){return t.gcd}})})),define("consul-ui/helpers/group-by",["exports","ember-composable-helpers/helpers/group-by"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/gt",["exports","ember-truth-helpers/helpers/gt"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"gt",{enumerable:!0,get:function(){return t.gt}})})),define("consul-ui/helpers/gte",["exports","ember-truth-helpers/helpers/gte"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"gte",{enumerable:!0,get:function(){return t.gte}})})),define("consul-ui/helpers/has-next",["exports","ember-composable-helpers/helpers/has-next"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"hasNext",{enumerable:!0,get:function(){return t.hasNext}})})),define("consul-ui/helpers/has-previous",["exports","ember-composable-helpers/helpers/has-previous"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"hasPrevious",{enumerable:!0,get:function(){return t.hasPrevious}})})),define("consul-ui/helpers/hds-link-to-models",["exports","@hashicorp/design-system-components/helpers/hds-link-to-models"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/hds-link-to-query",["exports","@hashicorp/design-system-components/helpers/hds-link-to-query"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/href-to",["exports","@ember/component/helper","@ember/service","@ember/object","@ember/application","consul-ui/utils/routing/transitionable","consul-ui/utils/routing/wildcard","consul-ui/router"],(function(e,t,n,l,r,i,o,a){var u,s,c +function d(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.hrefTo=e.default=void 0 +const p=(0,o.default)(a.routes),f=function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{} +const l=e.lookup("router:main").location,r=e.lookup("service:router") +let o=t.slice(0),a=o.shift(),u=n.params||{} +"."===a&&(o=(0,i.default)(r.currentRoute,u,e),a=o.shift()) +try{return p(a)&&(o=o.map(((e,t)=>e.split("/").map(encodeURIComponent).join("/")))),l.hrefTo(a,o,u)}catch(s){throw s.constructor===Error&&(s.message=`${s.message} For "${t[0]}:${JSON.stringify(t.slice(1))}"`),s}} +e.hrefTo=f +let m=(u=(0,n.inject)("router"),s=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="router",l=this,(n=c)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}init(){super.init(...arguments),this.router.on("routeWillChange",this.routeWillChange)}compute(e,t){return f((0,r.getOwner)(this),e,t)}routeWillChange(e){this.recompute()}willDestroy(){this.router.off("routeWillChange",this.routeWillChange),super.willDestroy()}},c=d(s.prototype,"router",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d(s.prototype,"routeWillChange",[l.action],Object.getOwnPropertyDescriptor(s.prototype,"routeWillChange"),s.prototype),s) +e.default=m})),define("consul-ui/helpers/humanize",["exports","ember-cli-string-helpers/helpers/humanize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"humanize",{enumerable:!0,get:function(){return t.humanize}})})),define("consul-ui/helpers/hypot",["exports","ember-math-helpers/helpers/hypot"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"hypot",{enumerable:!0,get:function(){return t.hypot}})})),define("consul-ui/helpers/icon-mapping",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const n={kubernetes:"kubernetes-color",terraform:"terraform-color",nomad:"nomad-color",consul:"consul-color","consul-api-gateway":"consul-color",vault:"vault",aws:"aws-color","aws-iam":"aws-color",lambda:"aws-lambda-color"} +var l=(0,t.helper)((function(e){let[t]=e +return n[t]})) +e.default=l})),define("consul-ui/helpers/if-key",["exports","ember-keyboard/helpers/if-key.js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/imul",["exports","ember-math-helpers/helpers/imul"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"imul",{enumerable:!0,get:function(){return t.imul}})})),define("consul-ui/helpers/inc",["exports","ember-composable-helpers/helpers/inc"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"inc",{enumerable:!0,get:function(){return t.inc}})})),define("consul-ui/helpers/includes",["exports","ember-composable-helpers/helpers/includes"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"includes",{enumerable:!0,get:function(){return t.includes}})})),define("consul-ui/helpers/intersect",["exports","ember-composable-helpers/helpers/intersect"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/invoke",["exports","ember-composable-helpers/helpers/invoke"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"invoke",{enumerable:!0,get:function(){return t.invoke}})})),define("consul-ui/helpers/is-active",["exports","ember-router-helpers/helpers/is-active"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"isActive",{enumerable:!0,get:function(){return t.isActive}})})),define("consul-ui/helpers/is-array",["exports","ember-truth-helpers/helpers/is-array"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"isArray",{enumerable:!0,get:function(){return t.isArray}})})),define("consul-ui/helpers/is-empty",["exports","ember-truth-helpers/helpers/is-empty"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/is-equal",["exports","ember-truth-helpers/helpers/is-equal"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"isEqual",{enumerable:!0,get:function(){return t.isEqual}})})),define("consul-ui/helpers/is-href",["exports","@ember/component/helper","@ember/service","@ember/object"],(function(e,t,n,l){var r,i,o +function a(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let u=(r=(0,n.inject)("router"),i=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="router",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}init(){super.init(...arguments),this.router.on("routeWillChange",this.routeWillChange)}compute(e){let[t,...n]=e +return this.router.currentRouteName.startsWith("nspace.")&&t.startsWith("dc.")&&(t=`nspace.${t}`),void 0!==this.next&&"loading"!==this.next?this.next.startsWith(t):this.router.isActive(t,...n)}routeWillChange(e){this.next=e.to.name.replace(".index",""),this.recompute()}willDestroy(){this.router.off("routeWillChange",this.routeWillChange),super.willDestroy()}},o=a(i.prototype,"router",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a(i.prototype,"routeWillChange",[l.action],Object.getOwnPropertyDescriptor(i.prototype,"routeWillChange"),i.prototype),i) +e.default=u})),define("consul-ui/helpers/is",["exports","ember-can/helpers/can","@ember/object","@ember/string"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.is=e.default=void 0 +const r=(e,t,r)=>{let[i,o]=t,{abilityName:a,propertyName:u}=e.abilities.parse(i),s=e.abilities.abilityFor(a,o,r) +return u="function"==typeof s.getCharacteristicProperty?s.getCharacteristicProperty(u):(0,l.camelize)(`is-${u}`),(0,n.get)(s,u)} +e.is=r +class i extends t.default{compute(e,t){let[n,l]=e +return r(this,[n,l],t)}}e.default=i})),define("consul-ui/helpers/join",["exports","ember-composable-helpers/helpers/join"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/json-stringify",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.helper)((function(e,t){try{return JSON.stringify(...e)}catch(n){return e[0].map((t=>JSON.stringify(t,e[1],e[2])))}})) +e.default=n})),define("consul-ui/helpers/keys",["exports","ember-composable-helpers/helpers/keys"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"keys",{enumerable:!0,get:function(){return t.keys}})})) +define("consul-ui/helpers/last",["exports","@ember/component/helper"],(function(e,t){function n(e,t){let[n=""]=e +if(!0==("string"==typeof n))return n.substr(-1)}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.last=n +var l=(0,t.helper)(n) +e.default=l})),define("consul-ui/helpers/lcm",["exports","ember-math-helpers/helpers/lcm"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"lcm",{enumerable:!0,get:function(){return t.lcm}})})),define("consul-ui/helpers/left-trim",["exports","@ember/component/helper","consul-ui/utils/left-trim"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l=(0,t.helper)((function(e,t){let[l="",r=""]=e +return(0,n.default)(l,r)})) +e.default=l})),define("consul-ui/helpers/log-e",["exports","ember-math-helpers/helpers/log-e"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"logE",{enumerable:!0,get:function(){return t.logE}})})),define("consul-ui/helpers/log10",["exports","ember-math-helpers/helpers/log10"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"log10",{enumerable:!0,get:function(){return t.log10}})})),define("consul-ui/helpers/log1p",["exports","ember-math-helpers/helpers/log1p"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"log1p",{enumerable:!0,get:function(){return t.log1p}})})),define("consul-ui/helpers/log2",["exports","ember-math-helpers/helpers/log2"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"log2",{enumerable:!0,get:function(){return t.log2}})})),define("consul-ui/helpers/lowercase",["exports","ember-cli-string-helpers/helpers/lowercase"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"lowercase",{enumerable:!0,get:function(){return t.lowercase}})})),define("consul-ui/helpers/lt",["exports","ember-truth-helpers/helpers/lt"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"lt",{enumerable:!0,get:function(){return t.lt}})})),define("consul-ui/helpers/lte",["exports","ember-truth-helpers/helpers/lte"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"lte",{enumerable:!0,get:function(){return t.lte}})})),define("consul-ui/helpers/map-by",["exports","ember-composable-helpers/helpers/map-by"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/map",["exports","ember-composable-helpers/helpers/map"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/max",["exports","ember-math-helpers/helpers/max"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"max",{enumerable:!0,get:function(){return t.max}})})),define("consul-ui/helpers/merge-checks",["exports","@ember/component/helper","consul-ui/utils/merge-checks"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l=(0,t.helper)((function(e,t){let[l,r]=e +return(0,n.default)(l,r)})) +e.default=l})),define("consul-ui/helpers/min",["exports","ember-math-helpers/helpers/min"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"min",{enumerable:!0,get:function(){return t.min}})})),define("consul-ui/helpers/mixed-grid-layout",["exports","@ember/component/helper","ember-collection/layouts/mixed-grid"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l=(0,t.helper)((function(e){return new n.default(e[0])})) +e.default=l})),define("consul-ui/helpers/mod",["exports","ember-math-helpers/helpers/mod"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"mod",{enumerable:!0,get:function(){return t.mod}})})),define("consul-ui/helpers/mult",["exports","ember-math-helpers/helpers/mult"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"mult",{enumerable:!0,get:function(){return t.mult}})})),define("consul-ui/helpers/next",["exports","ember-composable-helpers/helpers/next"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"next",{enumerable:!0,get:function(){return t.next}})})),define("consul-ui/helpers/noop",["exports","ember-composable-helpers/helpers/noop"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"noop",{enumerable:!0,get:function(){return t.noop}})})),define("consul-ui/helpers/not-eq",["exports","ember-truth-helpers/helpers/not-eq"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"notEqualHelper",{enumerable:!0,get:function(){return t.notEqualHelper}})})),define("consul-ui/helpers/not",["exports","ember-truth-helpers/helpers/not"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"not",{enumerable:!0,get:function(){return t.not}})})),define("consul-ui/helpers/object-at",["exports","ember-composable-helpers/helpers/object-at"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"objectAt",{enumerable:!0,get:function(){return t.objectAt}})})),define("consul-ui/helpers/on-document",["exports","ember-on-helper/helpers/on-document"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/on-key",["exports","ember-keyboard/helpers/on-key.js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/on-window",["exports","ember-on-helper/helpers/on-window"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/on",["exports","ember-on-helper/helpers/on"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/optional",["exports","ember-composable-helpers/helpers/optional"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"optional",{enumerable:!0,get:function(){return t.optional}})})),define("consul-ui/helpers/or",["exports","ember-truth-helpers/helpers/or"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"or",{enumerable:!0,get:function(){return t.or}})})),define("consul-ui/helpers/page-title",["exports","ember-page-title/helpers/page-title"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=t.default +e.default=n})) +define("consul-ui/helpers/percentage-columns-layout",["exports","@ember/component/helper","ember-collection/layouts/percentage-columns"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l=(0,t.helper)((function(e){return new n.default(e[0],e[1],e[2])})) +e.default=l})),define("consul-ui/helpers/percentage-of",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.helper)((function(e,t){let[n,l]=e +const r=n/l*100 +return isNaN(r)?0:r.toFixed(2)})) +e.default=n})),define("consul-ui/helpers/perform",["exports","ember-concurrency/helpers/perform"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/pick",["exports","ember-composable-helpers/helpers/pick"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"pick",{enumerable:!0,get:function(){return t.pick}})})),define("consul-ui/helpers/pipe-action",["exports","ember-composable-helpers/helpers/pipe-action"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/pipe",["exports","ember-composable-helpers/helpers/pipe"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"pipe",{enumerable:!0,get:function(){return t.pipe}})})),define("consul-ui/helpers/pluralize",["exports","ember-inflector/lib/helpers/pluralize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=t.default +e.default=n})),define("consul-ui/helpers/policy/datacenters",["exports","@ember/component/helper","@ember/object"],(function(e,t,n){function l(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +const l=(0,n.get)(e[0],"Datacenters") +return Array.isArray(l)&&0!==l.length?(0,n.get)(e[0],"Datacenters"):[t.global||"All"]}Object.defineProperty(e,"__esModule",{value:!0}),e.datacenters=l,e.default=void 0 +var r=(0,t.helper)(l) +e.default=r})),define("consul-ui/helpers/policy/group",["exports","@ember/component/helper","@ember/object","consul-ui/models/policy"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var r=(0,t.helper)((function(e){let[t]=e +return t.reduce((function(e,t){let r +switch(!0){case(0,n.get)(t,"ID")===l.MANAGEMENT_ID:r="management" +break +case""!==(0,n.get)(t,"template"):r="identities" +break +default:r="policies"}return e[r].push(t),e}),{management:[],identities:[],policies:[]})})) +e.default=r})),define("consul-ui/helpers/policy/typeof",["exports","@ember/component/helper","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.typeOf=i +const l="00000000-0000-0000-0000-000000000001",r="00000000-0000-0000-0000-000000000002" +function i(e,t){const i=e[0],o=(0,n.get)(i,"template") +switch(!0){case void 0===o:return"role" +case"service-identity"===o:return"policy-service-identity" +case"node-identity"===o:return"policy-node-identity" +case(0,n.get)(i,"ID")===l:return"policy-management" +case(0,n.get)(i,"ID")===r:return"read-only" +default:return"policy"}}var o=(0,t.helper)(i) +e.default=o})),define("consul-ui/helpers/pow",["exports","ember-math-helpers/helpers/pow"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"pow",{enumerable:!0,get:function(){return t.pow}})})),define("consul-ui/helpers/previous",["exports","ember-composable-helpers/helpers/previous"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"previous",{enumerable:!0,get:function(){return t.previous}})})),define("consul-ui/helpers/queue",["exports","ember-composable-helpers/helpers/queue"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"queue",{enumerable:!0,get:function(){return t.queue}})})),define("consul-ui/helpers/random",["exports","ember-math-helpers/helpers/random"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"random",{enumerable:!0,get:function(){return t.random}})})),define("consul-ui/helpers/range",["exports","ember-composable-helpers/helpers/range"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"range",{enumerable:!0,get:function(){return t.range}})})),define("consul-ui/helpers/reduce",["exports","ember-composable-helpers/helpers/reduce"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/ref-to",["exports","ember-ref-bucket/helpers/ref-to"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"refTo",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/refresh-route",["exports","@ember/component/helper","@ember/service","@ember/application"],(function(e,t,n,l){var r,i,o +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let a=(r=(0,n.inject)("router"),i=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="router",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){return()=>{const e=(0,l.getOwner)(this),t=this.router.currentRoute.name +return e.lookup(`route:${t}`).refresh()}}},u=i.prototype,s="router",c=[r],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),o=f,i) +var u,s,c,d,p,f +e.default=a})),define("consul-ui/helpers/reject-by",["exports","ember-composable-helpers/helpers/reject-by"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/render-template",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=/{{([A-Za-z.0-9_-]+)}}/g +let a,u=(l=(0,n.inject)("encoder"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="encoder",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),"function"!=typeof a&&(a=this.encoder.createRegExpEncoder(o,encodeURIComponent,!1))}compute(e){let[t,n]=e +return a(t,n)}},s=r.prototype,c="encoder",d=[l],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),i=m,r) +var s,c,d,p,f,m +e.default=u})),define("consul-ui/helpers/repeat",["exports","ember-composable-helpers/helpers/repeat"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"repeat",{enumerable:!0,get:function(){return t.repeat}})})),define("consul-ui/helpers/require",["exports","@ember/component/helper","require","@lit/reactive-element","consul-ui/utils/path/resolve"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i="consul-ui",o=new Map +var a=(0,t.helper)(((e,t)=>{let a,[u=""]=e,s=(0,r.default)(`${i}${t.from}`,u) +if("/"===u.charAt(0)&&(s=`${i}${s}`),!n.default.has(s))throw new Error(`Unable to resolve '${s}' does the file exist?`) +switch(a=(0,n.default)(s)[t.export||"default"],!0){case s.endsWith(".css"):return a(l.css) +case s.endsWith(".xstate"):return a +case s.endsWith(".element"):{if(o.has(s))return o.get(s) +const e=a(HTMLElement) +return o.set(s,e),e}default:return a}})) +e.default=a})),define("consul-ui/helpers/reverse",["exports","ember-composable-helpers/helpers/reverse"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/right-trim",["exports","@ember/component/helper","consul-ui/utils/right-trim"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l=(0,t.helper)((function(e,t){let[l="",r=""]=e +return(0,n.default)(l,r)})) +e.default=l})),define("consul-ui/helpers/root-url",["exports","ember-router-helpers/helpers/root-url"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"rootUrl",{enumerable:!0,get:function(){return t.rootUrl}})})),define("consul-ui/helpers/round",["exports","ember-math-helpers/helpers/round"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"round",{enumerable:!0,get:function(){return t.round}})})),define("consul-ui/helpers/route-action",["exports","ember-route-action-helper/helpers/route-action"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/route-match",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.helper)((function(e,t){let[n]=e +switch(["Present","Exact","Prefix","Suffix","Regex"].find((e=>void 0!==n[e]))){case"Present":return(n.Invert?"NOT ":"")+"present" +case"Exact":return`${n.Invert?"NOT ":""}exactly matching "${n.Exact}"` +case"Prefix":return`${n.Invert?"NOT ":""}prefixed by "${n.Prefix}"` +case"Suffix":return`${n.Invert?"NOT ":""}suffixed by "${n.Suffix}"` +case"Regex":return`${n.Invert?"NOT ":""}matching the regex "${n.Regex}"`}return""})) +e.default=n})),define("consul-ui/helpers/route-params",["exports","ember-router-helpers/helpers/route-params"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"routeParams",{enumerable:!0,get:function(){return t.routeParams}})})),define("consul-ui/helpers/service/card-permissions",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.helper)((function(e){let[t]=e +if(""===t.Datacenter)return"empty" +{const e=t.Intention.HasPermissions,n=t.Intention.Allowed,l="specific-intention"===t.Source&&!t.TransparentProxy +switch(!0){case e:return"allow" +case!n&&!e:return"deny" +case n&&l:return"not-defined" +default:return"allow"}}})) +e.default=n})) +define("consul-ui/helpers/service/external-source",["exports","@ember/component/helper","@ember/object"],(function(e,t,n){function l(e,t){let l=(0,n.get)(e[0],"ExternalSources.firstObject") +l||(l=(0,n.get)(e[0],"Meta.external-source")) +const r=void 0===t.prefix?"":t.prefix +if(l&&["consul-api-gateway","vault","kubernetes","terraform","nomad","consul","aws","lambda"].includes(l))return`${r}${l}`}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.serviceExternalSource=l +var r=(0,t.helper)(l) +e.default=r})),define("consul-ui/helpers/service/health-percentage",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.helper)((function(e){let[t]=e +const n=t.ChecksCritical+t.ChecksPassing+t.ChecksWarning +return 0===n?"":{passing:Math.round(t.ChecksPassing/n*100),warning:Math.round(t.ChecksWarning/n*100),critical:Math.round(t.ChecksCritical/n*100)}})) +e.default=n})),define("consul-ui/helpers/set",["exports","ember-set-helper/helpers/set"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/shuffle",["exports","ember-composable-helpers/helpers/shuffle"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"shuffle",{enumerable:!0,get:function(){return t.shuffle}})})),define("consul-ui/helpers/sign",["exports","ember-math-helpers/helpers/sign"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"sign",{enumerable:!0,get:function(){return t.sign}})})),define("consul-ui/helpers/sin",["exports","ember-math-helpers/helpers/sin"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"sin",{enumerable:!0,get:function(){return t.sin}})})),define("consul-ui/helpers/singularize",["exports","ember-inflector/lib/helpers/singularize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=t.default +e.default=n})),define("consul-ui/helpers/slice",["exports","ember-composable-helpers/helpers/slice"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/slugify",["exports","@ember/component/helper"],(function(e,t){function n(e,t){let[n=""]=e +return n.replace(/ /g,"-").toLowerCase()}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.slugify=n +var l=(0,t.helper)(n) +e.default=l})),define("consul-ui/helpers/smart-date-format",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i +function o(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function a(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const u=6048e5 +function s(e){const t=new Date +return e>=+t-u&&e<=+t+u}let c=(l=class extends t.default{constructor(){super(...arguments),o(this,"temporal",r,this),o(this,"intl",i,this)}compute(e,t){let[n]=e +return{isNearDate:s(n),relative:`${this.temporal.format(n)} ago`,friendly:this.intl.formatTime(n,{month:"short",day:"numeric",year:"numeric",hour:"numeric",minute:"numeric",second:"numeric",hourCycle:"h24"})}}},r=a(l.prototype,"temporal",[n.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i=a(l.prototype,"intl",[n.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),l) +e.default=c})),define("consul-ui/helpers/sort-by",["exports","ember-composable-helpers/helpers/sort-by"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/split",["exports","@ember/component/helper"],(function(e,t){function n(e,t){let[n="",l=","]=e +return n.split(l)}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.split=n +var l=(0,t.helper)(n) +e.default=l})),define("consul-ui/helpers/sqrt",["exports","ember-math-helpers/helpers/sqrt"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"sqrt",{enumerable:!0,get:function(){return t.sqrt}})})),define("consul-ui/helpers/state-chart",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,n.inject)("state"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="state",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){let[n]=e +return this.state.stateChart(n)}},a=r.prototype,u="state",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/helpers/state-matches",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,n.inject)("state"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="state",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){let[n,l]=e +return this.state.matches(n,l)}},a=r.prototype,u="state",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/helpers/string-char-at",["exports","ember-string-fns/helpers/string-char-at"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringCharAt",{enumerable:!0,get:function(){return t.stringCharAt}})})),define("consul-ui/helpers/string-char-code-at",["exports","ember-string-fns/helpers/string-char-code-at"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringCharCodeAt",{enumerable:!0,get:function(){return t.stringCharCodeAt}})})),define("consul-ui/helpers/string-code-point-at",["exports","ember-string-fns/helpers/string-code-point-at"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringCodePointAt",{enumerable:!0,get:function(){return t.stringCodePointAt}})})),define("consul-ui/helpers/string-concat",["exports","ember-string-fns/helpers/string-concat"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringConcat",{enumerable:!0,get:function(){return t.stringConcat}})})),define("consul-ui/helpers/string-ends-with",["exports","ember-string-fns/helpers/string-ends-with"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringEndsWith",{enumerable:!0,get:function(){return t.stringEndsWith}})})),define("consul-ui/helpers/string-equals",["exports","ember-string-fns/helpers/string-equals"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringEquals",{enumerable:!0,get:function(){return t.stringEquals}})})),define("consul-ui/helpers/string-from-char-code",["exports","ember-string-fns/helpers/string-from-char-code"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringFromCharCode",{enumerable:!0,get:function(){return t.stringFromCharCode}})})),define("consul-ui/helpers/string-from-code-point",["exports","ember-string-fns/helpers/string-from-code-point"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringFromCodePoint",{enumerable:!0,get:function(){return t.stringFromCodePoint}})})),define("consul-ui/helpers/string-html-safe",["exports","@ember/component/helper","@ember/string"],(function(e,t,n){function l(e){let[t=""]=e +return(0,n.htmlSafe)(t)}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.stringHtmlSafe=l +var r=(0,t.helper)(l) +e.default=r})),define("consul-ui/helpers/string-includes",["exports","ember-string-fns/helpers/string-includes"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringIncludes",{enumerable:!0,get:function(){return t.stringIncludes}})})),define("consul-ui/helpers/string-index-of",["exports","ember-string-fns/helpers/string-index-of"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringIndexOf",{enumerable:!0,get:function(){return t.stringIndexOf}})})),define("consul-ui/helpers/string-last-index-of",["exports","ember-string-fns/helpers/string-last-index-of"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringLastIndexOf",{enumerable:!0,get:function(){return t.stringLastIndexOf}})})),define("consul-ui/helpers/string-not-equals",["exports","ember-string-fns/helpers/string-not-equals"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringNotEquals",{enumerable:!0,get:function(){return t.stringNotEquals}})})),define("consul-ui/helpers/string-pad-end",["exports","ember-string-fns/helpers/string-pad-end"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringPadEnd",{enumerable:!0,get:function(){return t.stringPadEnd}})})),define("consul-ui/helpers/string-pad-start",["exports","ember-string-fns/helpers/string-pad-start"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringPadStart",{enumerable:!0,get:function(){return t.stringPadStart}})})) +define("consul-ui/helpers/string-repeat",["exports","ember-string-fns/helpers/string-repeat"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringRepeat",{enumerable:!0,get:function(){return t.stringRepeat}})})),define("consul-ui/helpers/string-replace-all",["exports","ember-string-fns/helpers/string-replace-all"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringReplaceAll",{enumerable:!0,get:function(){return t.stringReplaceAll}})})),define("consul-ui/helpers/string-replace",["exports","ember-string-fns/helpers/string-replace"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringReplace",{enumerable:!0,get:function(){return t.stringReplace}})})),define("consul-ui/helpers/string-slice",["exports","ember-string-fns/helpers/string-slice"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringSlice",{enumerable:!0,get:function(){return t.stringSlice}})})),define("consul-ui/helpers/string-split",["exports","ember-string-fns/helpers/string-split"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringSplit",{enumerable:!0,get:function(){return t.stringSplit}})})),define("consul-ui/helpers/string-starts-with",["exports","ember-string-fns/helpers/string-starts-with"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringStartsWith",{enumerable:!0,get:function(){return t.stringStartsWith}})})),define("consul-ui/helpers/string-substring",["exports","ember-string-fns/helpers/string-substring"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringSubstring",{enumerable:!0,get:function(){return t.stringSubstring}})})),define("consul-ui/helpers/string-to-camel-case",["exports","ember-string-fns/helpers/string-to-camel-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToCamelCase",{enumerable:!0,get:function(){return t.stringToCamelCase}})})),define("consul-ui/helpers/string-to-kebab-case",["exports","ember-string-fns/helpers/string-to-kebab-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToKebabCase",{enumerable:!0,get:function(){return t.stringToKebabCase}})})),define("consul-ui/helpers/string-to-lower-case",["exports","ember-string-fns/helpers/string-to-lower-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToLowerCase",{enumerable:!0,get:function(){return t.stringToLowerCase}})})),define("consul-ui/helpers/string-to-pascal-case",["exports","ember-string-fns/helpers/string-to-pascal-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToPascalCase",{enumerable:!0,get:function(){return t.stringToPascalCase}})})),define("consul-ui/helpers/string-to-sentence-case",["exports","ember-string-fns/helpers/string-to-sentence-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToSentenceCase",{enumerable:!0,get:function(){return t.stringToSentenceCase}})})),define("consul-ui/helpers/string-to-snake-case",["exports","ember-string-fns/helpers/string-to-snake-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToSnakeCase",{enumerable:!0,get:function(){return t.stringToSnakeCase}})})),define("consul-ui/helpers/string-to-title-case",["exports","ember-string-fns/helpers/string-to-title-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToTitleCase",{enumerable:!0,get:function(){return t.stringToTitleCase}})})),define("consul-ui/helpers/string-to-upper-case",["exports","ember-string-fns/helpers/string-to-upper-case"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringToUpperCase",{enumerable:!0,get:function(){return t.stringToUpperCase}})})),define("consul-ui/helpers/string-trim-end",["exports","ember-string-fns/helpers/string-trim-end"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringTrimEnd",{enumerable:!0,get:function(){return t.stringTrimEnd}})})),define("consul-ui/helpers/string-trim-start",["exports","ember-string-fns/helpers/string-trim-start"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringTrimStart",{enumerable:!0,get:function(){return t.stringTrimStart}})})),define("consul-ui/helpers/string-trim",["exports","ember-string-fns/helpers/string-trim"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"stringTrim",{enumerable:!0,get:function(){return t.stringTrim}})})),define("consul-ui/helpers/style-map",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.helper)((function(e){const t=e.reduce(((e,t)=>{let[n,l,r=""]=t +return null==l?e:`${e}${n}:${l.toString()}${r};`}),"") +return t.length>0?t:void 0})) +e.default=n})),define("consul-ui/helpers/sub",["exports","ember-math-helpers/helpers/sub"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"sub",{enumerable:!0,get:function(){return t.sub}})})),define("consul-ui/helpers/substr",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.helper)((function(e,t){let[n="",l=0,r]=e +return n.substr(l,r)})) +e.default=n})),define("consul-ui/helpers/sum",["exports","ember-math-helpers/helpers/sum"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"sum",{enumerable:!0,get:function(){return t.sum}})})),define("consul-ui/helpers/svg-curve",["exports","@ember/component/helper"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.helper)((function(e,t){let[n]=e +const l=t.src||{x:0,y:0},r=t.type||"cubic" +let i=[n,{x:(l.x+n.x)/2,y:l.y}] +return"cubic"===r&&i.push({x:i[1].x,y:n.y}),`${o=l,`\n M ${o.x} ${o.y}\n `}${function(){const e=[...arguments] +return`${arguments.length>2?"C":"Q"} ${e.concat(e.shift()).map((e=>Object.values(e).join(" "))).join(",")}`}(...i)}` +var o})) +e.default=n})),define("consul-ui/helpers/t",["exports","ember-intl/helpers/t"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/take",["exports","ember-composable-helpers/helpers/take"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/tan",["exports","ember-math-helpers/helpers/tan"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"tan",{enumerable:!0,get:function(){return t.tan}})})),define("consul-ui/helpers/tanh",["exports","ember-math-helpers/helpers/tanh"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"tanh",{enumerable:!0,get:function(){return t.tanh}})})),define("consul-ui/helpers/task",["exports","ember-concurrency/helpers/task"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/temporal-format",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,n.inject)("temporal"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="temporal",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){let[n]=e +return this.temporal.format(n,t)}},a=r.prototype,u="temporal",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/helpers/temporal-within",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,n.inject)("temporal"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="temporal",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){return this.temporal.within(e,t)}},a=r.prototype,u="temporal",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})) +define("consul-ui/helpers/test",["exports","consul-ui/helpers/can","consul-ui/helpers/is"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{compute(e,t){let[l,r]=e +switch(!0){case l.startsWith("can "):return super.compute([l.substr(4),r],t) +case l.startsWith("is "):return(0,n.is)(this,[l.substr(3),r],t)}throw new Error(`${l} is not supported by the 'test' helper.`)}}e.default=l})),define("consul-ui/helpers/titleize",["exports","ember-cli-string-helpers/helpers/titleize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"titleize",{enumerable:!0,get:function(){return t.titleize}})})),define("consul-ui/helpers/to-hash",["exports","@ember/component/helper","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l=(0,t.helper)(((e,t)=>{let[l=[],r]=e +return Array.isArray(l)||(l=l.toArray()),l.reduce(((e,t,l)=>(e[(0,n.get)(t,r)]=t,e)),{})})) +e.default=l})),define("consul-ui/helpers/to-route",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i,o,a +function u(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let c=(l=(0,n.inject)("router"),r=(0,n.inject)("env"),i=class extends t.default{constructor(){super(...arguments),u(this,"router",o,this),u(this,"env",a,this)}compute(e){let[t]=e +return this.router.recognize(`${this.env.var("rootURL")}${t}`).name}},o=s(i.prototype,"router",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=s(i.prototype,"env",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) +e.default=c})),define("consul-ui/helpers/toggle-action",["exports","ember-composable-helpers/helpers/toggle-action"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/toggle",["exports","ember-composable-helpers/helpers/toggle"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"toggle",{enumerable:!0,get:function(){return t.toggle}})})),define("consul-ui/helpers/token/is-anonymous",["exports","@ember/component/helper","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.isAnonymous=r +const l="00000000-0000-0000-0000-000000000002" +function r(e,t){return(0,n.get)(e[0],"AccessorID")===l}var i=(0,t.helper)(r) +e.default=i})),define("consul-ui/helpers/token/is-legacy",["exports","@ember/component/helper","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.isLegacy=r +const l=function(e){const t=(0,n.get)(e,"Rules") +if(null!=t)return""!==t.trim() +const l=(0,n.get)(e,"Legacy") +return void 0!==l&&l} +function r(e,t){const n=e[0] +return void 0!==n.length?n.find((function(e){return l(e)})):l(n)}var i=(0,t.helper)(r) +e.default=i})),define("consul-ui/helpers/transition-to",["exports","ember-router-helpers/helpers/transition-to"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"transitionTo",{enumerable:!0,get:function(){return t.transitionTo}})})),define("consul-ui/helpers/trunc",["exports","ember-math-helpers/helpers/trunc"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"trunc",{enumerable:!0,get:function(){return t.trunc}})})),define("consul-ui/helpers/truncate",["exports","ember-cli-string-helpers/helpers/truncate"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"truncate",{enumerable:!0,get:function(){return t.truncate}})})),define("consul-ui/helpers/tween-to",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,n.inject)("ticker"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="ticker",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){let[n,l]=e +return this.ticker.tweenTo(n,l)}},a=r.prototype,u="ticker",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/helpers/union",["exports","ember-composable-helpers/helpers/union"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/uniq-by",["exports","@ember/component/helper","@ember/utils","@ember/array"],(function(e,t,n,l){function r(e){let[t,r]=e +return(0,n.isEmpty)(t)?[]:(0,l.A)(r).uniqBy(t)}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.uniqBy=r +var i=(0,t.helper)(r) +e.default=i})),define("consul-ui/helpers/unique-id",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,n.inject)("dom"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="dom",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}compute(e,t){return this.dom.guid({})}},a=r.prototype,u="dom",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/helpers/uppercase",["exports","ember-cli-string-helpers/helpers/uppercase"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"uppercase",{enumerable:!0,get:function(){return t.uppercase}})})),define("consul-ui/helpers/uri",["exports","@ember/component/helper","@ember/service"],(function(e,t,n){var l,r,i,o,a +function u(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const c=/\${([A-Za-z.0-9_-]+)}/g +let d,p=(l=(0,n.inject)("encoder"),r=(0,n.inject)("data-source/service"),i=class extends t.default{constructor(){super(...arguments),u(this,"encoder",o,this),u(this,"data",a,this),"function"!=typeof d&&(d=this.encoder.createRegExpEncoder(c,encodeURIComponent))}compute(e){let[t,n]=e +return this.data.uri(d(t,n))}},o=s(i.prototype,"encoder",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=s(i.prototype,"data",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) +e.default=p})),define("consul-ui/helpers/url-for",["exports","ember-router-helpers/helpers/url-for"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"urlFor",{enumerable:!0,get:function(){return t.urlFor}})})),define("consul-ui/helpers/values",["exports","ember-composable-helpers/helpers/values"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"values",{enumerable:!0,get:function(){return t.values}})})),define("consul-ui/helpers/will-destroy",["exports","ember-render-helpers/helpers/will-destroy"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/helpers/without",["exports","ember-composable-helpers/helpers/without"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"without",{enumerable:!0,get:function(){return t.without}})})),define("consul-ui/helpers/xor",["exports","ember-truth-helpers/helpers/xor"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"xor",{enumerable:!0,get:function(){return t.xor}})})),define("consul-ui/initializers/app-version",["exports","ember-cli-app-version/initializer-factory","consul-ui/config/environment"],(function(e,t,n){let l,r +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,n.default.APP&&(l=n.default.APP.name,r=n.default.APP.version) +var i={name:"App Version",initialize:(0,t.default)(l,r)} +e.default=i})),define("consul-ui/initializers/container-debug-adapter",["exports","ember-resolver/resolvers/classic/container-debug-adapter"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n={name:"container-debug-adapter",initialize(){(arguments[1]||arguments[0]).register("container-debug-adapter:main",t.default)}} +e.default=n})),define("consul-ui/initializers/ember-data-data-adapter",["exports","@ember-data/debug/setup"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/initializers/ember-data",["exports","ember-data","ember-data/setup-container"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l={name:"ember-data",initialize:n.default} +e.default=l})),define("consul-ui/initializers/export-application-global",["exports","ember","consul-ui/config/environment"],(function(e,t,n){function l(){var e=arguments[1]||arguments[0] +if(!1!==n.default.exportApplicationGlobal){var l +if("undefined"!=typeof window)l=window +else if("undefined"!=typeof global)l=global +else{if("undefined"==typeof self)return +l=self}var r,i=n.default.exportApplicationGlobal +r="string"==typeof i?i:t.default.String.classify(n.default.modulePrefix),l[r]||(l[r]=e,e.reopen({willDestroy:function(){this._super.apply(this,arguments),delete l[r]}}))}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.initialize=l +var r={name:"export-application-global",initialize:l} +e.default=r})),define("consul-ui/initializers/flash-messages",["exports","consul-ui/config/environment","@ember/debug","ember-cli-flash/utils/flash-message-options"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.initialize=r +function r(){const e=arguments[1]||arguments[0],{flashMessageDefaults:n}=t.default||{},{injectionFactories:r}=n||[],i=(0,l.default)(n) +r&&r.length +i.injectionFactories.forEach((t=>{e.inject(t,"flashMessages","service:flash-messages")}))}var i={name:"flash-messages",initialize:r} +e.default=i})),define("consul-ui/initializers/initialize-torii-callback",["exports","consul-ui/config/environment","torii/redirect-handler"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l={name:"torii-callback",before:"torii",initialize(e){arguments[1]&&(e=arguments[1]),t.default.torii&&t.default.torii.disableRedirectInitializer||(e.deferReadiness(),n.default.handle(window).catch((function(){e.advanceReadiness()})))}} +e.default=l})),define("consul-ui/initializers/initialize-torii-session",["exports","torii/bootstrap/session","torii/configuration"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l={name:"torii-session",after:"torii",initialize(e){arguments[1]&&(e=arguments[1]) +const l=(0,n.getConfiguration)() +l.sessionServiceName&&(0,t.default)(e,l.sessionServiceName)}} +e.default=l})) +define("consul-ui/initializers/initialize-torii",["exports","torii/bootstrap/torii","torii/configuration","consul-ui/config/environment"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var r={name:"torii",initialize(e){arguments[1]&&(e=arguments[1]),(0,n.configure)(l.default.torii||{}),(0,t.default)(e)}},i=r +e.default=i})),define("consul-ui/initializers/model-fragments",["exports","ember-data-model-fragments","ember-data-model-fragments/ext"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l={name:"fragmentTransform",after:"ember-data",initialize(){}} +e.default=l})),define("consul-ui/initializers/setup-ember-can",["exports","ember-can/initializers/setup-ember-can"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"initialize",{enumerable:!0,get:function(){return t.initialize}})})),define("consul-ui/instance-initializers/container",["exports","@ember/debug","require","deepmerge"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.services=e.default=void 0 +const r=document,i=l.default.all([...r.querySelectorAll("script[data-services]")].map((e=>JSON.parse(e.dataset.services)))) +e.services=i +var o={name:"container",initialize(e){(function(e,t){Object.entries(t).forEach((t=>{let[l,r]=t +if(1==("string"==typeof r.class)){if(!n.default.has(r.class))throw new Error(`Unable to locate '${r.class}'`) +e.register(l.replace("auth-provider:","torii-provider:"),(0,n.default)(r.class).default)}}))})(e,i) +const l=e.lookup("service:container") +let r=l.get("container-debug-adapter:main").catalogEntriesByType("service").filter((e=>e.startsWith("repository/")||"ui-config"===e));(0,t.runInDebug)((()=>r=r.filter((e=>!e.endsWith("-test"))))),r.push("repository/service"),r.forEach((e=>{const t=`service:${e}` +l.set(t,l.resolveRegistration(t))}))}} +e.default=o})),define("consul-ui/instance-initializers/ember-data",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var t={name:"ember-data",initialize(){}} +e.default=t})),define("consul-ui/instance-initializers/href-to",["exports","@ember/routing/link-component"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.HrefTo=void 0 +class n{constructor(e,t){this.applicationInstance=e,this.target=t +const n=this.target.attributes.href +this.url=n&&n.value}handle(e){this.shouldHandle(e)&&(e.preventDefault(),this.applicationInstance.lookup("router:main").location.transitionTo(this.url))}shouldHandle(e){return this.isUnmodifiedLeftClick(e)&&!this.isIgnored(this.target)&&!this.isExternal(this.target)&&!this.hasActionHelper(this.target)&&!this.hasDownload(this.target)&&!this.isLinkComponent(this.target)}isUnmodifiedLeftClick(e){return!(void 0!==e.which&&1!==e.which||e.ctrlKey||e.metaKey)}isExternal(e){return"_blank"===e.getAttribute("target")}isIgnored(e){return e.dataset.nativeHref}hasActionHelper(e){return e.dataset.emberAction}hasDownload(e){return e.hasAttribute("download")}isLinkComponent(e){let n=!1 +const l=e.id +if(l){const e=this.applicationInstance.lookup("-view-registry:main")[l] +n=e&&e instanceof t.default}return n}recognizeUrl(e){let t=!1 +if(e){const n=this._getRouter(),l=this._getRootUrl(),r=0===e.indexOf(l),i=this.getUrlWithoutRoot(),o=n._router._routerMicrolib||n._router.router +t=r&&o.recognizer.recognize(i)}return t}getUrlWithoutRoot(){const e=this.applicationInstance.lookup("router:main").location +let t=e.getURL.apply({getHash:()=>"",location:{pathname:this.url},baseURL:e.baseURL,rootURL:e.rootURL,env:e.env},[]) +const n=t.indexOf("?") +return-1!==n&&(t=t.substr(0,n-1)),t}_getRouter(){return this.applicationInstance.lookup("service:router")}_getRootUrl(){let e=this._getRouter().get("rootURL") +return"/"!==e.charAt(e.length-1)&&(e+="/"),e}}e.HrefTo=n +var l={name:"href-to",initialize(e){if("undefined"==typeof FastBoot){const t=e.lookup("service:dom").document(),l=t=>{const l="A"===t.target.tagName?t.target:function(e){if(e.closest)return e.closest("a") +for(e=e.parentElement;e&&"A"!==e.tagName;)e=e.parentElement +return e}(t.target) +if(l){new n(e,l).handle(t)}} +t.body.addEventListener("click",l),e.reopen({willDestroy(){return t.body.removeEventListener("click",l),this._super(...arguments)}})}}} +e.default=l})),define("consul-ui/instance-initializers/ivy-codemirror",["exports"],(function(e){function t(e){const t=e.application.name,n=e.lookup("service:-document"),l=new Map(Object.entries(JSON.parse(n.querySelector(`[data-${t}-fs]`).textContent))) +CodeMirror.modeURL={replace:function(e,t){switch(t.trim()){case"javascript":return l.get(["codemirror","mode","javascript","javascript.js"].join("/")) +case"ruby":return l.get(["codemirror","mode","ruby","ruby.js"].join("/")) +case"yaml":return l.get(["codemirror","mode","yaml","yaml.js"].join("/")) +case"xml":return l.get(["codemirror","mode","xml","xml.js"].join("/"))}}} +e.resolveRegistration("component:ivy-codemirror").reopen({attributeBindings:["name"]})}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.initialize=t +var n={initialize:t} +e.default=n})),define("consul-ui/instance-initializers/load-sprite",["exports","@hashicorp/ember-flight-icons/instance-initializers/load-sprite"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(e,"initialize",{enumerable:!0,get:function(){return t.initialize}})})),define("consul-ui/instance-initializers/selection",["exports","consul-ui/env"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n={name:"selection",initialize(e){if((0,t.env)("CONSUL_UI_DISABLE_ANCHOR_SELECTION"))return +const n=e.lookup("service:dom"),l=n.document(),r=l.getElementsByTagName("html")[0],i=function(e){return"A"===e.tagName?e:n.closest("a",e)},o=function(e){if(r.classList.contains("is-debug"))return +const t=i(e.target) +if(t){if(void 0!==e.button&&2===e.button){const e=t.dataset.href +return void(e&&t.setAttribute("href",e))}const n=t.getAttribute("href") +n&&(t.dataset.href=n,t.removeAttribute("href"))}},a=function(e){if(r.classList.contains("is-debug"))return +const t=i(e.target) +if(t){const n=t.dataset.href +!function(){const t=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:window).getSelection() +let n=!1 +try{n="isCollapsed"in t&&!t.isCollapsed&&t.toString().length>1}catch(e){}return n}()&&n&&t.setAttribute("href",n)}} +l.body.addEventListener("mousedown",o),l.body.addEventListener("mouseup",a),e.reopen({willDestroy:function(){return l.body.removeEventListener("mousedown",o),l.body.removeEventListener("mouseup",a),this._super(...arguments)}})}} +e.default=n})),define("consul-ui/instance-initializers/setup-routes",["exports","ember","torii/bootstrap/routing","torii/configuration","torii/compat/get-router-instance","torii/compat/get-router-lib","torii/router-dsl-ext"],(function(e,t,n,l,r,i,o){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var a={name:"torii-setup-routes",initialize(e){if(!(0,l.getConfiguration)().sessionServiceName)return +let o=(0,r.default)(e) +const a=e.lookup("service:router") +var u=function(){var l=(0,i.default)(o).authenticatedRoutes +!t.default.isEmpty(l)&&(0,n.default)(e,l),a.off("routeWillChange",u)} +a.on("routeWillChange",u)}} +e.default=a})),define("consul-ui/instance-initializers/walk-providers",["exports","torii/lib/container-utils","torii/configuration"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l={name:"torii-walk-providers",initialize(e){let l=(0,n.getConfiguration)() +for(var r in l.providers)l.providers.hasOwnProperty(r)&&(0,t.lookup)(e,"torii-provider:"+r)}} +e.default=l})),define("consul-ui/locations/fsm-with-optional-test",["exports","consul-ui/locations/fsm-with-optional","consul-ui/locations/fsm","@ember/test-helpers"],(function(e,t,n,l){function r(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class i extends t.default{static create(){return new this(...arguments)}constructor(){super(...arguments),r(this,"implementation","fsm-with-optional-test"),this.location=new n.Location,this.machine=new n.FSM(this.location),this.doc={defaultView:{addEventListener:(e,t)=>{this.machine=new n.FSM(this.location,t)},removeEventListener:(e,t)=>{this.machine=new n.FSM}}}}visit(e){const t=this.container,n=this.container.lookup("router:main"),r=async e=>(await(0,l.settled)(),new Promise((e=>setTimeout(e(t),0)))),i=e=>{if(e.error)throw e.error +if("TransitionAborted"===e.name&&n._routerMicrolib.activeTransition)return n._routerMicrolib.activeTransition.then(r,i) +throw"TransitionAborted"===e.name?new Error(e.message):e} +return""===this.location.pathname?(this.rootURL=n.rootURL.replace(/\/$/,""),this.machine.state.path=this.location.pathname=`${this.rootURL}${e}`,this.path=this.getURL(),t.handleURL(`${this.path}`).then(r,i)):this.transitionTo(e).then(r,i)}}e.default=i})),define("consul-ui/locations/fsm-with-optional",["exports","consul-ui/env"],(function(e,t){function n(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function l(e){for(var t=1;t{if(t<4){let t=!1 +return Object.entries(i).reduce(((n,l)=>{let[r,i]=l +const o=i.exec(e) +return null!==o&&(n[r]={value:e,match:o[1]},t=!0),n}),this.optional),!t}return!0})).join("/")}optionalParams(){let e=this.optional||{} +return["partition","nspace","peer"].reduce(((t,n)=>{let l="" +return void 0!==e[n]&&(l=e[n].match),t[n]=l,t}),{})}visit(){return this.transitionTo(...arguments)}hrefTo(e,n,r){const i=l({},r) +void 0!==i.dc&&delete i.dc,void 0!==i.nspace&&(i.nspace=`~${i.nspace}`),void 0!==i.partition&&(i.partition=`_${i.partition}`),void 0!==i.peer&&(i.peer=`:${i.peer}`),void 0===this.router&&(this.router=this.container.lookup("router:main")) +let o=!0 +switch(!0){case"settings"===e:case e.startsWith("docs."):o=!1}if(this.router.currentRouteName.startsWith("docs.")&&(n.unshift((0,t.env)("CONSUL_DATACENTER_PRIMARY")),e.startsWith("dc")))return`console://${e} <= ${JSON.stringify(n)}` +const a=this.router._routerMicrolib +let u +try{u=a.generate(e,...n,{queryParams:{}})}catch(s){n=Object.values(a.oldState.params).reduce(((e,t)=>e.concat(Object.keys(t).length>0?t:[])),[]),u=a.generate(e,...n)}return this.formatURL(u,i,o)}transitionTo(e){if(void 0===this.router&&(this.router=this.container.lookup("router:main")),this.router.currentRouteName.startsWith("docs")&&e.startsWith("console://"))return console.info(`location.transitionTo: ${e.substr(10)}`),!0 +const t=Object.entries(this.optionalParams()),n=this.getURLForTransition(e) +if(this._previousURL===n)return this.dispatch("push",e),Promise.resolve() +{const l=this.optionalParams() +return t.some((e=>{let[t,n]=e +return l[t]!==n}))&&this.dispatch("push",e),this.container.lookup("router:main").transitionTo(n)}}getURL(){const e=this.location.search||"" +let t="" +void 0!==this.location.hash&&(t=this.location.hash.substr(0)) +return`${this.getURLForTransition(this.location.pathname)}${e}${t}`}formatURL(e,t){let n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2] +if(""!==e?(this.rootURL=this.rootURL.replace(o,""),this.baseURL=this.baseURL.replace(o,"")):"/"===this.baseURL[0]&&"/"===this.rootURL[0]&&(this.baseURL=this.baseURL.replace(o,"")),n){const n=e.split("/") +t=l(l({},this.optional),t||{}),t=Object.values(t).filter((e=>Boolean(e))).map((e=>e.value||e),[]),n.splice(...[1,0].concat(t)),e=n.join("/")}return`${this.baseURL}${this.rootURL}${e}`}changeURL(e,t){this.path=t +const n=this.machine.state +t=this.formatURL(t),n&&n.path===t||this.dispatch(e,t)}setURL(e){this.changeURL("push",e)}replaceURL(e){this.changeURL("replace",e)}onUpdateURL(e){this.callback=e}dispatch(e,t){const n={path:t,uuid:"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0 +return("x"===e?t:3&t|8).toString(16)}))} +this.machine[`${e}State`](n,null,t),this.route({state:n})}willDestroy(){this.doc.defaultView.removeEventListener("popstate",this.route)}}})),define("consul-ui/locations/fsm",["exports"],(function(e){function t(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.Location=e.FSM=void 0 +e.FSM=class{constructor(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:()=>{} +t(this,"state",{}),this.listener=n,this.location=e}pushState(e,t,n){this.state=e,this.location.pathname=n,this.listener({state:this.state})}replaceState(){return this.pushState(...arguments)}} +e.Location=class{constructor(){t(this,"pathname",""),t(this,"search",""),t(this,"hash","")}} +e.default=class{static create(){return new this(...arguments)}constructor(e){t(this,"implementation","fsm"),this.container=Object.entries(e)[0][1]}visit(){return this.transitionTo(...arguments)}hrefTo(){}transitionTo(){}}})),define("consul-ui/machines/boolean.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={id:"boolean",initial:"false",states:{true:{on:{TOGGLE:[{target:"false"}],FALSE:[{target:"false"}]}},false:{on:{TOGGLE:[{target:"true"}],TRUE:[{target:"true"}]}}}}})),define("consul-ui/machines/validate.xstate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={id:"form",initial:"idle",on:{RESET:[{target:"idle"}]},states:{idle:{on:{SUCCESS:[{target:"success"}],ERROR:[{target:"error"}]}},success:{},error:{}}}})),define("consul-ui/mixins/policy/as-many",["exports","@ember/object/mixin","@ember/object","consul-ui/utils/minimizeModel"],(function(e,t,n,l){function r(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function i(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=function(e,t,n,l){return(e||[]).map((function(e){const r={template:t,Name:e[n]} +return void 0!==e[l]&&(r[l]=e[l]),r}))},a=function(e){return(e||[]).map((function(e){return function(e){for(var t=1;t(n.Policies=a(n.Policies).concat(o(n.ServiceIdentities,"service-identity","ServiceName","Datacenters")).concat(o(n.NodeIdentities,"node-identity","NodeName","Datacenter")),t(e,n))))}),t)},respondForQuery:function(e,t){return this._super((function(t){return e((function(e,n){return t(e,n.map((function(e){return e.Policies=a(e.Policies).concat(o(e.ServiceIdentities,"service-identity","ServiceName","Datacenters")).concat(o(e.NodeIdentities,"node-identity","NodeName","Datacenter")),e})))}))}),t)},serialize:function(e,t){const r=this._super(...arguments) +return r.ServiceIdentities=u(r.Policies,"service-identity","ServiceName","Datacenters"),r.NodeIdentities=u(r.Policies,"node-identity","NodeName","Datacenter"),r.Policies=(0,l.default)(r.Policies.filter((function(e){return""===(0,n.get)(e,"template")}))),r}}) +e.default=s})),define("consul-ui/mixins/role/as-many",["exports","@ember/object/mixin","consul-ui/utils/minimizeModel"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l=t.default.create({respondForQueryRecord:function(e,t){return this._super((function(t){return e(((e,n)=>(n.Roles=void 0===n.Roles||null===n.Roles?[]:n.Roles,t(e,n))))}),t)},respondForQuery:function(e,t){return this._super((function(t){return e((function(e,n){return t(e,n.map((function(e){return e.Roles=void 0===e.Roles||null===e.Roles?[]:e.Roles,e})))}))}),t)},serialize:function(e,t){const l=this._super(...arguments) +return l.Roles=(0,n.default)(l.Roles),l}}) +e.default=l})),define("consul-ui/mixins/slots",["exports","block-slots/mixins/slots"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/mixins/with-blocking-actions",["exports","@ember/object/mixin","@ember/service","@ember/object","ember-inflector"],(function(e,t,n,l,r){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var i=t.default.create({_feedback:(0,n.inject)("feedback"),settings:(0,n.inject)("settings"),init:function(){this._super(...arguments) +const e=this._feedback,t=this;(0,l.set)(this,"feedback",{execute:function(n,l,i){const o=t.routeName.split(".") +o.pop() +const a=(0,r.singularize)(o.pop()) +return e.execute(n,l,i,a)}})},afterCreate:function(e){return this.afterUpdate(...arguments)},afterUpdate:function(e){const t=this.routeName.split(".") +return t.pop(),this.transitionTo(t.join("."))},afterDelete:function(e){const t=this.routeName.split(".") +return"index"===t.pop()?this.refresh():this.transitionTo(t.join("."))},errorCreate:function(e,t){return e},errorUpdate:function(e,t){return e},errorDelete:function(e,t){return e},actions:{cancel:function(){return this.afterUpdate(...arguments)},create:function(e,t){return t.preventDefault(),this.feedback.execute((()=>this.repo.persist(e).then((e=>this.afterCreate(...arguments)))),"create",((e,t)=>this.errorCreate(e,t)))},update:function(e,t){return t.preventDefault(),this.feedback.execute((()=>this.repo.persist(e).then((()=>this.afterUpdate(...arguments)))),"update",((e,t)=>this.errorUpdate(e,t)))},delete:function(e){return this.feedback.execute((()=>this.repo.remove(e).then((()=>this.afterDelete(...arguments)))),"delete",((e,t)=>this.errorDelete(e,t)))},use:function(e){return this.repo.findBySlug({dc:(0,l.get)(e,"Datacenter"),ns:(0,l.get)(e,"Namespace"),partition:(0,l.get)(e,"Partition"),id:(0,l.get)(e,"AccessorID")}).then((e=>this.settings.persist({token:{AccessorID:(0,l.get)(e,"AccessorID"),SecretID:(0,l.get)(e,"SecretID"),Namespace:(0,l.get)(e,"Namespace"),Partition:(0,l.get)(e,"Partition")}})))},logout:function(e){return this.settings.delete("token")},clone:function(e){let t +return this.feedback.execute((()=>this.repo.clone(e).then((e=>(t=e,this.afterDelete(...arguments)))).then((function(){return t}))),"clone")}}}) +e.default=i})),define("consul-ui/models/auth-method",["exports","@ember-data/model","@ember/object/computed","parse-duration","@ember/object"],(function(e,t,n,l,r){var i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D,T,E,L,A,R,I,$,F +function U(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function B(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="Name" +let q=(i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string",{defaultValue:()=>""}),d=(0,t.attr)("string",{defaultValue:()=>""}),p=(0,t.attr)("string",{defaultValue:()=>"local"}),f=(0,t.attr)("string"),m=(0,t.attr)(),h=(0,n.or)("DisplayName","Name"),b=(0,t.attr)(),y=(0,t.attr)("string"),v=(0,t.attr)("number"),g=(0,t.attr)("number"),O=(0,t.attr)(),P=(0,t.attr)(),w=(0,r.computed)("MaxTokenTTL"),x=class extends t.default{constructor(){super(...arguments),U(this,"uid",j,this),U(this,"Name",_,this),U(this,"Datacenter",S,this),U(this,"Namespace",k,this),U(this,"Partition",N,this),U(this,"Description",C,this),U(this,"DisplayName",z,this),U(this,"TokenLocality",M,this),U(this,"Type",D,this),U(this,"NamespaceRules",T,this),U(this,"MethodName",E,this),U(this,"Config",L,this),U(this,"MaxTokenTTL",A,this),U(this,"CreateIndex",R,this),U(this,"ModifyIndex",I,this),U(this,"Datacenters",$,this),U(this,"meta",F,this)}get TokenTTL(){return(0,l.default)(this.MaxTokenTTL)}},j=B(x.prototype,"uid",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=B(x.prototype,"Name",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=B(x.prototype,"Datacenter",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=B(x.prototype,"Namespace",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=B(x.prototype,"Partition",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=B(x.prototype,"Description",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=B(x.prototype,"DisplayName",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=B(x.prototype,"TokenLocality",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=B(x.prototype,"Type",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=B(x.prototype,"NamespaceRules",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=B(x.prototype,"MethodName",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=B(x.prototype,"Config",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=B(x.prototype,"MaxTokenTTL",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R=B(x.prototype,"CreateIndex",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=B(x.prototype,"ModifyIndex",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),$=B(x.prototype,"Datacenters",[O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),F=B(x.prototype,"meta",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),B(x.prototype,"TokenTTL",[w],Object.getOwnPropertyDescriptor(x.prototype,"TokenTTL"),x.prototype),x) +e.default=q})),define("consul-ui/models/binding-rule",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S +function k(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function N(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="ID" +let C=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string",{defaultValue:()=>""}),u=(0,t.attr)("string"),s=(0,t.attr)("string",{defaultValue:()=>""}),c=(0,t.attr)("string"),d=(0,t.attr)("string"),p=(0,t.attr)("number"),f=(0,t.attr)("number"),m=class extends t.default{constructor(){super(...arguments),k(this,"uid",h,this),k(this,"ID",b,this),k(this,"Datacenter",y,this),k(this,"Namespace",v,this),k(this,"Partition",g,this),k(this,"Description",O,this),k(this,"AuthMethod",P,this),k(this,"Selector",w,this),k(this,"BindType",x,this),k(this,"BindName",j,this),k(this,"CreateIndex",_,this),k(this,"ModifyIndex",S,this)}},h=N(m.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=N(m.prototype,"ID",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=N(m.prototype,"Datacenter",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=N(m.prototype,"Namespace",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=N(m.prototype,"Partition",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=N(m.prototype,"Description",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=N(m.prototype,"AuthMethod",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=N(m.prototype,"Selector",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=N(m.prototype,"BindType",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=N(m.prototype,"BindName",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=N(m.prototype,"CreateIndex",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=N(m.prototype,"ModifyIndex",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m) +e.default=C})),define("consul-ui/models/coordinate",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b +function y(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function v(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="Node" +let g=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)(),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("number"),s=class extends t.default{constructor(){super(...arguments),y(this,"uid",c,this),y(this,"Node",d,this),y(this,"Coord",p,this),y(this,"Segment",f,this),y(this,"Datacenter",m,this),y(this,"Partition",h,this),y(this,"SyncTime",b,this)}},c=v(s.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=v(s.prototype,"Node",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=v(s.prototype,"Coord",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=v(s.prototype,"Segment",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=v(s.prototype,"Datacenter",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=v(s.prototype,"Partition",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=v(s.prototype,"SyncTime",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s) +e.default=g})),define("consul-ui/models/dc",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D +function T(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function E(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=e.FOREIGN_KEY=void 0 +e.PRIMARY_KEY="uid" +e.FOREIGN_KEY="Datacenter" +e.SLUG_KEY="Name" +let L=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("boolean"),i=(0,t.attr)("number"),o=(0,t.attr)("number"),a=(0,t.attr)("string"),u=(0,t.attr)(),s=(0,t.attr)(),c=(0,t.attr)(),d=(0,t.attr)(),p=(0,t.attr)(),f=(0,t.attr)("boolean"),m=(0,t.attr)("boolean"),h=(0,t.attr)("string"),b=(0,t.attr)("boolean",{defaultValue:()=>!0}),y=class extends t.default{constructor(){super(...arguments),T(this,"uri",v,this),T(this,"Name",g,this),T(this,"Healthy",O,this),T(this,"FailureTolerance",P,this),T(this,"OptimisticFailureTolerance",w,this),T(this,"Leader",x,this),T(this,"Voters",j,this),T(this,"Servers",_,this),T(this,"RedundancyZones",S,this),T(this,"Default",k,this),T(this,"ReadReplicas",N,this),T(this,"Local",C,this),T(this,"Primary",z,this),T(this,"DefaultACLPolicy",M,this),T(this,"MeshEnabled",D,this)}},v=E(y.prototype,"uri",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=E(y.prototype,"Name",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=E(y.prototype,"Healthy",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=E(y.prototype,"FailureTolerance",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=E(y.prototype,"OptimisticFailureTolerance",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=E(y.prototype,"Leader",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=E(y.prototype,"Voters",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=E(y.prototype,"Servers",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=E(y.prototype,"RedundancyZones",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=E(y.prototype,"Default",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=E(y.prototype,"ReadReplicas",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=E(y.prototype,"Local",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=E(y.prototype,"Primary",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=E(y.prototype,"DefaultACLPolicy",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=E(y.prototype,"MeshEnabled",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y) +e.default=L})),define("consul-ui/models/discovery-chain",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b +function y(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function v(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="ServiceName" +let g=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)(),u=(0,t.attr)(),s=class extends t.default{constructor(){super(...arguments),y(this,"uid",c,this),y(this,"ServiceName",d,this),y(this,"Datacenter",p,this),y(this,"Partition",f,this),y(this,"Namespace",m,this),y(this,"Chain",h,this),y(this,"meta",b,this)}},c=v(s.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=v(s.prototype,"ServiceName",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=v(s.prototype,"Datacenter",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=v(s.prototype,"Partition",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=v(s.prototype,"Namespace",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=v(s.prototype,"Chain",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=v(s.prototype,"meta",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s) +e.default=g})),define("consul-ui/models/gateway-config",["exports","ember-data-model-fragments/fragment","ember-data-model-fragments/attributes","@ember-data/model"],(function(e,t,n,l){var r,i,o,a,u +function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let d=(r=(0,l.attr)("number",{defaultValue:()=>0}),i=(0,n.array)("string",{defaultValue:()=>[]}),o=class extends t.default{constructor(){super(...arguments),s(this,"AssociatedServiceCount",a,this),s(this,"Addresses",u,this)}},a=c(o.prototype,"AssociatedServiceCount",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(o.prototype,"Addresses",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) +e.default=d})),define("consul-ui/models/health-check",["exports","ember-data-model-fragments/fragment","ember-data-model-fragments/attributes","@ember-data/model","@ember/object","consul-ui/decorators/replace"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D,T,E +function L(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function A(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.schema=e.default=void 0 +e.schema={Status:{allowedValues:["passing","warning","critical"]},Type:{allowedValues:["serf","script","http","tcp","ttl","docker","grpc","alias"]}} +let R=(o=(0,l.attr)("string"),a=(0,l.attr)("string"),u=(0,i.replace)("","serf"),s=(0,l.attr)("string"),c=(0,l.attr)("string"),d=(0,l.attr)("string"),p=(0,l.attr)("string"),f=(0,l.attr)("string"),m=(0,l.attr)("string"),h=(0,l.attr)("string"),b=(0,i.nullValue)([]),y=(0,n.array)("string"),v=(0,l.attr)(),g=(0,l.attr)("boolean"),O=(0,r.computed)("ServiceID"),P=(0,r.computed)("Type"),w=class extends t.default{constructor(){super(...arguments),L(this,"Name",x,this),L(this,"CheckID",j,this),L(this,"Type",_,this),L(this,"Status",S,this),L(this,"Notes",k,this),L(this,"Output",N,this),L(this,"ServiceName",C,this),L(this,"ServiceID",z,this),L(this,"Node",M,this),L(this,"ServiceTags",D,this),L(this,"Definition",T,this),L(this,"Exposed",E,this)}get Kind(){return""===this.ServiceID?"node":"service"}get Exposable(){return["http","grpc"].includes(this.Type)}},x=A(w.prototype,"Name",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=A(w.prototype,"CheckID",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=A(w.prototype,"Type",[u,s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=A(w.prototype,"Status",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=A(w.prototype,"Notes",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=A(w.prototype,"Output",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=A(w.prototype,"ServiceName",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=A(w.prototype,"ServiceID",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=A(w.prototype,"Node",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=A(w.prototype,"ServiceTags",[b,y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=A(w.prototype,"Definition",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=A(w.prototype,"Exposed",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A(w.prototype,"Kind",[O],Object.getOwnPropertyDescriptor(w.prototype,"Kind"),w.prototype),A(w.prototype,"Exposable",[P],Object.getOwnPropertyDescriptor(w.prototype,"Exposable"),w.prototype),w) +e.default=R})),define("consul-ui/models/intention-permission-http-header",["exports","ember-data-model-fragments/fragment","@ember-data/model","@ember/object","@ember/object/computed"],(function(e,t,n,l,r){var i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O +function P(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function w(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.schema=e.default=void 0 +const x={Name:{required:!0},HeaderType:{allowedValues:["Exact","Prefix","Suffix","Regex","Present"]}} +e.schema=x +let j=(i=(0,n.attr)("string"),o=(0,n.attr)("string"),a=(0,n.attr)("string"),u=(0,n.attr)("string"),s=(0,n.attr)("string"),c=(0,n.attr)(),d=(0,r.or)(...x.HeaderType.allowedValues),p=(0,l.computed)(...x.HeaderType.allowedValues),f=class extends t.default{constructor(){super(...arguments),P(this,"Name",m,this),P(this,"Exact",h,this),P(this,"Prefix",b,this),P(this,"Suffix",y,this),P(this,"Regex",v,this),P(this,"Present",g,this),P(this,"Value",O,this)}get HeaderType(){return x.HeaderType.allowedValues.find((e=>void 0!==this[e]))}},m=w(f.prototype,"Name",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=w(f.prototype,"Exact",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=w(f.prototype,"Prefix",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=w(f.prototype,"Suffix",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=w(f.prototype,"Regex",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=w(f.prototype,"Present",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=w(f.prototype,"Value",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w(f.prototype,"HeaderType",[p],Object.getOwnPropertyDescriptor(f.prototype,"HeaderType"),f.prototype),f) +e.default=j})),define("consul-ui/models/intention-permission-http",["exports","ember-data-model-fragments/fragment","ember-data-model-fragments/attributes","@ember-data/model","@ember/object","@ember/object/computed"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m,h,b,y,v,g +function O(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function P(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.schema=e.default=void 0 +const w={PathType:{allowedValues:["PathPrefix","PathExact","PathRegex"]},Methods:{allowedValues:["GET","HEAD","POST","PUT","DELETE","CONNECT","OPTIONS","TRACE","PATCH"]}} +e.schema=w +let x=(o=(0,l.attr)("string"),a=(0,l.attr)("string"),u=(0,l.attr)("string"),s=(0,n.fragmentArray)("intention-permission-http-header"),c=(0,n.array)("string"),d=(0,i.or)(...w.PathType.allowedValues),p=(0,r.computed)(...w.PathType.allowedValues),f=class extends t.default{constructor(){super(...arguments),O(this,"PathExact",m,this),O(this,"PathPrefix",h,this),O(this,"PathRegex",b,this),O(this,"Header",y,this),O(this,"Methods",v,this),O(this,"Path",g,this)}get PathType(){return w.PathType.allowedValues.find((e=>"string"==typeof this[e]))}},m=P(f.prototype,"PathExact",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=P(f.prototype,"PathPrefix",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=P(f.prototype,"PathRegex",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=P(f.prototype,"Header",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=P(f.prototype,"Methods",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=P(f.prototype,"Path",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P(f.prototype,"PathType",[p],Object.getOwnPropertyDescriptor(f.prototype,"PathType"),f.prototype),f) +e.default=x})),define("consul-ui/models/intention-permission",["exports","ember-data-model-fragments/fragment","ember-data-model-fragments/attributes","@ember-data/model"],(function(e,t,n,l){var r,i,o,a,u +function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.schema=e.default=void 0 +const d={Action:{defaultValue:"allow",allowedValues:["allow","deny"]}} +e.schema=d +let p=(r=(0,l.attr)("string",{defaultValue:()=>d.Action.defaultValue}),i=(0,n.fragment)("intention-permission-http"),o=class extends t.default{constructor(){super(...arguments),s(this,"Action",a,this),s(this,"HTTP",u,this)}},a=c(o.prototype,"Action",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(o.prototype,"HTTP",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) +e.default=p})) +define("consul-ui/models/intention",["exports","@ember-data/model","@ember/object","ember-data-model-fragments/attributes","consul-ui/decorators/replace"],(function(e,t,n,l,r){var i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D,T,E,L,A,R,I,$,F,U,B,q,K,H,Y,G,V,W,Z,Q,J,X,ee,te,ne +function le(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function re(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="ID" +let ie=(i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,r.default)("",void 0),c=(0,t.attr)("string"),d=(0,t.attr)("string",{defaultValue:()=>"*"}),p=(0,t.attr)("string",{defaultValue:()=>"*"}),f=(0,t.attr)("string",{defaultValue:()=>"default"}),m=(0,t.attr)("string",{defaultValue:()=>"default"}),h=(0,t.attr)("string",{defaultValue:()=>"default"}),b=(0,t.attr)("string",{defaultValue:()=>"default"}),y=(0,t.attr)("number"),v=(0,t.attr)("string",{defaultValue:()=>"consul"}),g=(0,r.nullValue)(void 0),O=(0,t.attr)("string"),P=(0,t.attr)("string"),w=(0,t.attr)("boolean",{defaultValue:()=>!0}),x=(0,t.attr)("number"),j=(0,t.attr)("date"),_=(0,t.attr)("date"),S=(0,t.attr)("number"),k=(0,t.attr)("number"),N=(0,t.attr)(),C=(0,t.attr)({defaultValue:()=>[]}),z=(0,l.fragmentArray)("intention-permission"),M=(0,n.computed)("Meta"),D=class extends t.default{constructor(){super(...arguments),le(this,"uid",T,this),le(this,"ID",E,this),le(this,"Datacenter",L,this),le(this,"Description",A,this),le(this,"SourcePeer",R,this),le(this,"SourceName",I,this),le(this,"DestinationName",$,this),le(this,"SourceNS",F,this),le(this,"DestinationNS",U,this),le(this,"SourcePartition",B,this),le(this,"DestinationPartition",q,this),le(this,"Precedence",K,this),le(this,"SourceType",H,this),le(this,"Action",Y,this),le(this,"LegacyID",G,this),le(this,"Legacy",V,this),le(this,"SyncTime",W,this),le(this,"CreatedAt",Z,this),le(this,"UpdatedAt",Q,this),le(this,"CreateIndex",J,this),le(this,"ModifyIndex",X,this),le(this,"Meta",ee,this),le(this,"Resources",te,this),le(this,"Permissions",ne,this)}get IsManagedByCRD(){return void 0!==Object.entries(this.Meta||{}).find((e=>{let[t,n]=e +return"external-source"===t&&"kubernetes"===n}))}},T=re(D.prototype,"uid",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=re(D.prototype,"ID",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=re(D.prototype,"Datacenter",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=re(D.prototype,"Description",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R=re(D.prototype,"SourcePeer",[s,c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=re(D.prototype,"SourceName",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),$=re(D.prototype,"DestinationName",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),F=re(D.prototype,"SourceNS",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),U=re(D.prototype,"DestinationNS",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),B=re(D.prototype,"SourcePartition",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),q=re(D.prototype,"DestinationPartition",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),K=re(D.prototype,"Precedence",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),H=re(D.prototype,"SourceType",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Y=re(D.prototype,"Action",[g,O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),G=re(D.prototype,"LegacyID",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),V=re(D.prototype,"Legacy",[w],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),W=re(D.prototype,"SyncTime",[x],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Z=re(D.prototype,"CreatedAt",[j],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Q=re(D.prototype,"UpdatedAt",[_],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),J=re(D.prototype,"CreateIndex",[S],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),X=re(D.prototype,"ModifyIndex",[k],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ee=re(D.prototype,"Meta",[N],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),te=re(D.prototype,"Resources",[C],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ne=re(D.prototype,"Permissions",[z],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),re(D.prototype,"IsManagedByCRD",[M],Object.getOwnPropertyDescriptor(D.prototype,"IsManagedByCRD"),D.prototype),D) +e.default=ie})),define("consul-ui/models/kv",["exports","@ember-data/model","@ember/object","consul-ui/utils/isFolder","consul-ui/decorators/replace"],(function(e,t,n,l,r){var i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D,T,E,L,A +function R(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function I(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="Key" +let $=(i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("number"),u=(0,t.attr)(),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,t.attr)("string"),p=(0,t.attr)("number"),f=(0,t.attr)("number"),m=(0,r.nullValue)(void 0),h=(0,t.attr)("string"),b=(0,t.attr)("number"),y=(0,t.attr)("number"),v=(0,t.attr)("string"),g=(0,t.attr)({defaultValue:()=>[]}),O=(0,n.computed)("isFolder"),P=(0,n.computed)("Key"),w=class extends t.default{constructor(){super(...arguments),R(this,"uid",x,this),R(this,"Key",j,this),R(this,"SyncTime",_,this),R(this,"meta",S,this),R(this,"Datacenter",k,this),R(this,"Namespace",N,this),R(this,"Partition",C,this),R(this,"LockIndex",z,this),R(this,"Flags",M,this),R(this,"Value",D,this),R(this,"CreateIndex",T,this),R(this,"ModifyIndex",E,this),R(this,"Session",L,this),R(this,"Resources",A,this)}get Kind(){return this.isFolder?"folder":"key"}get isFolder(){return(0,l.default)(this.Key||"")}},x=I(w.prototype,"uid",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=I(w.prototype,"Key",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=I(w.prototype,"SyncTime",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=I(w.prototype,"meta",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=I(w.prototype,"Datacenter",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=I(w.prototype,"Namespace",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=I(w.prototype,"Partition",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=I(w.prototype,"LockIndex",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=I(w.prototype,"Flags",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=I(w.prototype,"Value",[m,h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=I(w.prototype,"CreateIndex",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=I(w.prototype,"ModifyIndex",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=I(w.prototype,"Session",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=I(w.prototype,"Resources",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I(w.prototype,"Kind",[O],Object.getOwnPropertyDescriptor(w.prototype,"Kind"),w.prototype),I(w.prototype,"isFolder",[P],Object.getOwnPropertyDescriptor(w.prototype,"isFolder"),w.prototype),w) +e.default=$})),define("consul-ui/models/license",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,v +function g(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function O(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uri" +let P=(n=(0,t.attr)("string"),l=(0,t.attr)("boolean"),r=(0,t.attr)("number"),i=(0,t.attr)(),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)(),c=class extends t.default{constructor(){super(...arguments),g(this,"uri",d,this),g(this,"Valid",p,this),g(this,"SyncTime",f,this),g(this,"meta",m,this),g(this,"Datacenter",h,this),g(this,"Namespace",b,this),g(this,"Partition",y,this),g(this,"License",v,this)}},d=O(c.prototype,"uri",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=O(c.prototype,"Valid",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=O(c.prototype,"SyncTime",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=O(c.prototype,"meta",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=O(c.prototype,"Datacenter",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=O(c.prototype,"Namespace",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=O(c.prototype,"Partition",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=O(c.prototype,"License",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c) +e.default=P})),define("consul-ui/models/node",["exports","@ember-data/model","@ember/object","@ember/object/computed","ember-data-model-fragments/attributes"],(function(e,t,n,l,r){var i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D,T,E,L,A,R,I,$,F,U,B,q,K,H,Y,G,V +function W(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function Z(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="ID" +let Q=(i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,t.attr)("string"),p=(0,t.attr)("number"),f=(0,t.attr)("number"),m=(0,t.attr)("number"),h=(0,t.attr)(),b=(0,t.attr)(),y=(0,t.attr)(),v=(0,t.attr)({defaultValue:()=>[]}),g=(0,t.hasMany)("service-instance"),O=(0,r.fragmentArray)("health-check"),P=(0,l.filter)("Services",(e=>"connect-proxy"!==e.Service.Kind)),w=(0,l.filter)("Services",(e=>"connect-proxy"===e.Service.Kind)),x=(0,l.filter)("Checks",(e=>""===e.ServiceID)),j=(0,n.computed)("ChecksCritical","ChecksPassing","ChecksWarning"),_=(0,n.computed)("NodeChecks.[]"),S=(0,n.computed)("NodeChecks.[]"),k=(0,n.computed)("NodeChecks.[]"),N=(0,n.computed)("Meta"),C=class extends t.default{constructor(){super(...arguments),W(this,"uid",z,this),W(this,"ID",M,this),W(this,"Datacenter",D,this),W(this,"PeerName",T,this),W(this,"Partition",E,this),W(this,"Address",L,this),W(this,"Node",A,this),W(this,"SyncTime",R,this),W(this,"CreateIndex",I,this),W(this,"ModifyIndex",$,this),W(this,"meta",F,this),W(this,"Meta",U,this),W(this,"TaggedAddresses",B,this),W(this,"Resources",q,this),W(this,"Services",K,this),W(this,"Checks",H,this),W(this,"MeshServiceInstances",Y,this),W(this,"ProxyServiceInstances",G,this),W(this,"NodeChecks",V,this)}get Status(){switch(!0){case 0!==this.ChecksCritical:return"critical" +case 0!==this.ChecksWarning:return"warning" +case 0!==this.ChecksPassing:return"passing" +default:return"empty"}}get ChecksCritical(){return this.NodeChecks.filter((e=>"critical"===e.Status)).length}get ChecksPassing(){return this.NodeChecks.filter((e=>"passing"===e.Status)).length}get ChecksWarning(){return this.NodeChecks.filter((e=>"warning"===e.Status)).length}get Version(){var e,t +return null!==(e=null===(t=this.Meta)||void 0===t?void 0:t["consul-version"])&&void 0!==e?e:""}},z=Z(C.prototype,"uid",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=Z(C.prototype,"ID",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=Z(C.prototype,"Datacenter",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=Z(C.prototype,"PeerName",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=Z(C.prototype,"Partition",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=Z(C.prototype,"Address",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=Z(C.prototype,"Node",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R=Z(C.prototype,"SyncTime",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=Z(C.prototype,"CreateIndex",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),$=Z(C.prototype,"ModifyIndex",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),F=Z(C.prototype,"meta",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),U=Z(C.prototype,"Meta",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),B=Z(C.prototype,"TaggedAddresses",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),q=Z(C.prototype,"Resources",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),K=Z(C.prototype,"Services",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),H=Z(C.prototype,"Checks",[O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Y=Z(C.prototype,"MeshServiceInstances",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),G=Z(C.prototype,"ProxyServiceInstances",[w],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),V=Z(C.prototype,"NodeChecks",[x],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Z(C.prototype,"Status",[j],Object.getOwnPropertyDescriptor(C.prototype,"Status"),C.prototype),Z(C.prototype,"ChecksCritical",[_],Object.getOwnPropertyDescriptor(C.prototype,"ChecksCritical"),C.prototype),Z(C.prototype,"ChecksPassing",[S],Object.getOwnPropertyDescriptor(C.prototype,"ChecksPassing"),C.prototype),Z(C.prototype,"ChecksWarning",[k],Object.getOwnPropertyDescriptor(C.prototype,"ChecksWarning"),C.prototype),Z(C.prototype,"Version",[N],Object.getOwnPropertyDescriptor(C.prototype,"Version"),C.prototype),C) +e.default=Q})),define("consul-ui/models/nspace",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w +function x(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function j(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=e.NSPACE_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="Name" +e.NSPACE_KEY="Namespace" +let _=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("number"),u=(0,t.attr)("string",{defaultValue:()=>""}),s=(0,t.attr)({defaultValue:()=>[]}),c=(0,t.attr)("string"),d=(0,t.attr)({defaultValue:()=>({PolicyDefaults:[],RoleDefaults:[]})}),p=class extends t.default{constructor(){super(...arguments),x(this,"uid",f,this),x(this,"Name",m,this),x(this,"Datacenter",h,this),x(this,"Partition",b,this),x(this,"Namespace",y,this),x(this,"SyncTime",v,this),x(this,"Description",g,this),x(this,"Resources",O,this),x(this,"DeletedAt",P,this),x(this,"ACLs",w,this)}},f=j(p.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=j(p.prototype,"Name",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=j(p.prototype,"Datacenter",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=j(p.prototype,"Partition",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=j(p.prototype,"Namespace",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=j(p.prototype,"SyncTime",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=j(p.prototype,"Description",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=j(p.prototype,"Resources",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=j(p.prototype,"DeletedAt",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=j(p.prototype,"ACLs",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p) +e.default=_})),define("consul-ui/models/oidc-provider",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O +function P(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function w(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="Name" +let x=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)(),d=class extends t.default{constructor(){super(...arguments),P(this,"uid",p,this),P(this,"Name",f,this),P(this,"Datacenter",m,this),P(this,"Namespace",h,this),P(this,"Partition",b,this),P(this,"Kind",y,this),P(this,"AuthURL",v,this),P(this,"DisplayName",g,this),P(this,"meta",O,this)}},p=w(d.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=w(d.prototype,"Name",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=w(d.prototype,"Datacenter",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=w(d.prototype,"Namespace",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=w(d.prototype,"Partition",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=w(d.prototype,"Kind",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=w(d.prototype,"AuthURL",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=w(d.prototype,"DisplayName",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=w(d.prototype,"meta",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d) +e.default=x})),define("consul-ui/models/partition",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O +function P(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function w(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=e.PARTITION_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="Name" +e.PARTITION_KEY="Partition" +let x=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("number"),c=(0,t.attr)(),d=class extends t.default{constructor(){super(...arguments),P(this,"uid",p,this),P(this,"Name",f,this),P(this,"Description",m,this),P(this,"DeletedAt",h,this),P(this,"Datacenter",b,this),P(this,"Namespace",y,this),P(this,"Partition",v,this),P(this,"SyncTime",g,this),P(this,"meta",O,this)}},p=w(d.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=w(d.prototype,"Name",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=w(d.prototype,"Description",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=w(d.prototype,"DeletedAt",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=w(d.prototype,"Datacenter",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=w(d.prototype,"Namespace",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=w(d.prototype,"Partition",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=w(d.prototype,"SyncTime",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=w(d.prototype,"meta",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d) +e.default=x})),define("consul-ui/models/peer",["exports","@ember-data/model","consul-ui/decorators/replace"],(function(e,t,n){var l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D,T,E,L,A,R,I +function $(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function F(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.schema=e.default=void 0 +e.schema={State:{defaultValue:"PENDING",allowedValues:["PENDING","ESTABLISHING","ACTIVE","FAILING","TERMINATED","DELETING"]}} +let U=(l=(0,t.attr)("string"),r=(0,t.attr)(),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,n.nullValue)([]),p=(0,t.attr)(),f=(0,t.attr)("string"),m=(0,t.attr)(),h=(0,n.nullValue)([]),b=(0,t.attr)(),y=(0,n.nullValue)([]),v=(0,t.attr)(),g=(0,t.attr)("date"),O=(0,t.attr)("date"),P=(0,t.attr)("date"),w=class extends t.default{constructor(){super(...arguments),$(this,"uri",x,this),$(this,"meta",j,this),$(this,"Datacenter",_,this),$(this,"Partition",S,this),$(this,"Name",k,this),$(this,"State",N,this),$(this,"ID",C,this),$(this,"ServerExternalAddresses",z,this),$(this,"ServerExternalAddresses",M,this),$(this,"PeerID",D,this),$(this,"PeerServerAddresses",T,this),$(this,"ImportedServices",E,this),$(this,"ExportedServices",L,this),$(this,"LastHeartbeat",A,this),$(this,"LastReceive",R,this),$(this,"LastSend",I,this)}get ImportedServiceCount(){return this.ImportedServices.length}get ExportedServiceCount(){return this.ExportedServices.length}get isReceiver(){return this.PeerID}get isDialer(){return!this.isReceiver}},x=F(w.prototype,"uri",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=F(w.prototype,"meta",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=F(w.prototype,"Datacenter",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=F(w.prototype,"Partition",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=F(w.prototype,"Name",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=F(w.prototype,"State",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=F(w.prototype,"ID",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=F(w.prototype,"ServerExternalAddresses",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=F(w.prototype,"ServerExternalAddresses",[d,p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=F(w.prototype,"PeerID",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=F(w.prototype,"PeerServerAddresses",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=F(w.prototype,"ImportedServices",[h,b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=F(w.prototype,"ExportedServices",[y,v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=F(w.prototype,"LastHeartbeat",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R=F(w.prototype,"LastReceive",[O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=F(w.prototype,"LastSend",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w) +e.default=U})),define("consul-ui/models/permission",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c +function d(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function p(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let f=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("boolean"),o=class extends t.default{constructor(){super(...arguments),d(this,"Resource",a,this),d(this,"Segment",u,this),d(this,"Access",s,this),d(this,"Allow",c,this)}},a=p(o.prototype,"Resource",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=p(o.prototype,"Segment",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s=p(o.prototype,"Access",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=p(o.prototype,"Allow",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) +e.default=f})),define("consul-ui/models/policy",["exports","@ember-data/model","@ember/object"],(function(e,t,n){var l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D,T,E +function L(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function A(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=e.MANAGEMENT_ID=void 0 +const R="00000000-0000-0000-0000-000000000001" +e.MANAGEMENT_ID=R +e.PRIMARY_KEY="uid" +e.SLUG_KEY="ID" +let I=(l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string",{defaultValue:()=>""}),s=(0,t.attr)("string",{defaultValue:()=>""}),c=(0,t.attr)("string",{defaultValue:()=>""}),d=(0,t.attr)("number"),p=(0,t.attr)("number"),f=(0,t.attr)("number"),m=(0,t.attr)(),h=(0,t.attr)(),b=(0,t.attr)("string",{defaultValue:()=>""}),y=(0,t.attr)("number",{defaultValue:()=>(new Date).getTime()}),v=(0,n.computed)("ID"),g=class extends t.default{constructor(){super(...arguments),L(this,"uid",O,this),L(this,"ID",P,this),L(this,"Datacenter",w,this),L(this,"Namespace",x,this),L(this,"Partition",j,this),L(this,"Name",_,this),L(this,"Description",S,this),L(this,"Rules",k,this),L(this,"SyncTime",N,this),L(this,"CreateIndex",C,this),L(this,"ModifyIndex",z,this),L(this,"Datacenters",M,this),L(this,"meta",D,this),L(this,"template",T,this),L(this,"CreateTime",E,this)}get isGlobalManagement(){return this.ID===R}},O=A(g.prototype,"uid",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=A(g.prototype,"ID",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=A(g.prototype,"Datacenter",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=A(g.prototype,"Namespace",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=A(g.prototype,"Partition",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=A(g.prototype,"Name",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=A(g.prototype,"Description",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=A(g.prototype,"Rules",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=A(g.prototype,"SyncTime",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=A(g.prototype,"CreateIndex",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=A(g.prototype,"ModifyIndex",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=A(g.prototype,"Datacenters",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=A(g.prototype,"meta",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=A(g.prototype,"template",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=A(g.prototype,"CreateTime",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A(g.prototype,"isGlobalManagement",[v],Object.getOwnPropertyDescriptor(g.prototype,"isGlobalManagement"),g.prototype),g) +e.default=I})),define("consul-ui/models/proxy",["exports","@ember-data/model","consul-ui/models/service-instance"],(function(e,t,n){var l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x +function j(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function _(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="Node,ServiceID" +let S=(l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,t.attr)("number"),p=(0,t.attr)(),f=class extends n.default{constructor(){super(...arguments),j(this,"uid",m,this),j(this,"ID",h,this),j(this,"Datacenter",b,this),j(this,"Namespace",y,this),j(this,"Partition",v,this),j(this,"ServiceName",g,this),j(this,"ServiceID",O,this),j(this,"NodeName",P,this),j(this,"SyncTime",w,this),j(this,"ServiceProxy",x,this)}},m=_(f.prototype,"uid",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=_(f.prototype,"ID",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=_(f.prototype,"Datacenter",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=_(f.prototype,"Namespace",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=_(f.prototype,"Partition",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=_(f.prototype,"ServiceName",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=_(f.prototype,"ServiceID",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=_(f.prototype,"NodeName",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=_(f.prototype,"SyncTime",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=_(f.prototype,"ServiceProxy",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f) +e.default=S})),define("consul-ui/models/role",["exports","@ember-data/model"],(function(e,t){var n,l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D,T,E +function L(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function A(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="ID" +let R=(n=(0,t.attr)("string"),l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string",{defaultValue:()=>""}),u=(0,t.attr)("string",{defaultValue:()=>""}),s=(0,t.attr)({defaultValue:()=>[]}),c=(0,t.attr)({defaultValue:()=>[]}),d=(0,t.attr)({defaultValue:()=>[]}),p=(0,t.attr)("number"),f=(0,t.attr)("number"),m=(0,t.attr)("number"),h=(0,t.attr)("number"),b=(0,t.attr)(),y=(0,t.attr)("string"),v=class extends t.default{constructor(){super(...arguments),L(this,"uid",g,this),L(this,"ID",O,this),L(this,"Datacenter",P,this),L(this,"Namespace",w,this),L(this,"Partition",x,this),L(this,"Name",j,this),L(this,"Description",_,this),L(this,"Policies",S,this),L(this,"ServiceIdentities",k,this),L(this,"NodeIdentities",N,this),L(this,"SyncTime",C,this),L(this,"CreateIndex",z,this),L(this,"ModifyIndex",M,this),L(this,"CreateTime",D,this),L(this,"Datacenters",T,this),L(this,"Hash",E,this)}},g=A(v.prototype,"uid",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=A(v.prototype,"ID",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=A(v.prototype,"Datacenter",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=A(v.prototype,"Namespace",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=A(v.prototype,"Partition",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=A(v.prototype,"Name",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=A(v.prototype,"Description",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=A(v.prototype,"Policies",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=A(v.prototype,"ServiceIdentities",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=A(v.prototype,"NodeIdentities",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=A(v.prototype,"SyncTime",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=A(v.prototype,"CreateIndex",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=A(v.prototype,"ModifyIndex",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=A(v.prototype,"CreateTime",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=A(v.prototype,"Datacenters",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=A(v.prototype,"Hash",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v) +e.default=R})),define("consul-ui/models/service-instance",["exports","@ember-data/model","ember-data-model-fragments/attributes","@ember/object","@ember/object/computed","@glimmer/tracking"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D,T,E,L,A,R,I,$,F,U,B,q,K,H,Y,G,V,W,Z,Q,J,X,ee,te,ne,le +function re(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function ie(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=e.Collection=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="Node.Node,Service.ID" +const oe=(a=ie((o=class{constructor(e){re(this,"items",a,this),this.items=e}get ExternalSources(){const e=this.items.reduce((function(e,t){return e.concat(t.ExternalSources||[])}),[]) +return[...new Set(e)].filter(Boolean).sort()}}).prototype,"items",[i.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) +e.Collection=oe +let ae=(u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)(),d=(0,t.attr)(),p=(0,t.attr)(),f=(0,n.fragmentArray)("health-check"),m=(0,t.attr)("number"),h=(0,t.attr)(),b=(0,t.attr)({defaultValue:()=>[]}),y=(0,r.alias)("Service.Service"),v=(0,r.or)("Service.{ID,Service}"),g=(0,r.or)("Service.Address","Node.Service"),O=(0,t.attr)("string"),P=(0,r.alias)("Service.Tags"),w=(0,r.alias)("Service.Meta"),x=(0,r.alias)("Service.Namespace"),j=(0,r.alias)("Service.Partition"),_=(0,r.filter)("Checks.@each.Kind",((e,t,n)=>"service"===e.Kind)),S=(0,r.filter)("Checks.@each.Kind",((e,t,n)=>"node"===e.Kind)),k=(0,l.computed)("Service.Meta"),N=(0,l.computed)("Service.Kind"),C=(0,l.computed)("Service.Kind"),z=(0,l.computed)("IsOrigin"),M=(0,l.computed)("ChecksPassing","ChecksWarning","ChecksCritical"),D=(0,l.computed)("Checks.[]"),T=(0,l.computed)("Checks.[]"),E=(0,l.computed)("Checks.[]"),L=(0,l.computed)("Checks.[]","ChecksPassing"),A=(0,l.computed)("Checks.[]","ChecksWarning"),R=(0,l.computed)("Checks.[]","ChecksCritical"),I=class extends t.default{constructor(){super(...arguments),re(this,"uid",$,this),re(this,"Datacenter",F,this),re(this,"Proxy",U,this),re(this,"Node",B,this),re(this,"Service",q,this),re(this,"Checks",K,this),re(this,"SyncTime",H,this),re(this,"meta",Y,this),re(this,"Resources",G,this),re(this,"Name",V,this),re(this,"ID",W,this),re(this,"Address",Z,this),re(this,"SocketPath",Q,this),re(this,"Tags",J,this),re(this,"Meta",X,this),re(this,"Namespace",ee,this),re(this,"Partition",te,this),re(this,"ServiceChecks",ne,this),re(this,"NodeChecks",le,this)}get ExternalSources(){const e=Object.entries(this.Service.Meta||{}).filter((e=>{let[t,n]=e +return"external-source"===t})).map((e=>{let[t,n]=e +return n})) +return[...new Set(e)]}get IsProxy(){return["connect-proxy","mesh-gateway","ingress-gateway","terminating-gateway","api-gateway"].includes(this.Service.Kind)}get IsOrigin(){return!["connect-proxy","mesh-gateway"].includes(this.Service.Kind)}get IsMeshOrigin(){return this.IsOrigin&&!["terminating-gateway"].includes(this.Service.Kind)}get Status(){switch(!0){case 0!==this.ChecksCritical.length:return"critical" +case 0!==this.ChecksWarning.length:return"warning" +case 0!==this.ChecksPassing.length:return"passing" +default:return"empty"}}get ChecksPassing(){return this.Checks.filter((e=>"passing"===e.Status))}get ChecksWarning(){return this.Checks.filter((e=>"warning"===e.Status))}get ChecksCritical(){return this.Checks.filter((e=>"critical"===e.Status))}get PercentageChecksPassing(){return this.ChecksPassing.length/this.Checks.length*100}get PercentageChecksWarning(){return this.ChecksWarning.length/this.Checks.length*100}get PercentageChecksCritical(){return this.ChecksCritical.length/this.Checks.length*100}},$=ie(I.prototype,"uid",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),F=ie(I.prototype,"Datacenter",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),U=ie(I.prototype,"Proxy",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),B=ie(I.prototype,"Node",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),q=ie(I.prototype,"Service",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),K=ie(I.prototype,"Checks",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),H=ie(I.prototype,"SyncTime",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Y=ie(I.prototype,"meta",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),G=ie(I.prototype,"Resources",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),V=ie(I.prototype,"Name",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),W=ie(I.prototype,"ID",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Z=ie(I.prototype,"Address",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Q=ie(I.prototype,"SocketPath",[O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),J=ie(I.prototype,"Tags",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),X=ie(I.prototype,"Meta",[w],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ee=ie(I.prototype,"Namespace",[x],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),te=ie(I.prototype,"Partition",[j],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ne=ie(I.prototype,"ServiceChecks",[_],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),le=ie(I.prototype,"NodeChecks",[S],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ie(I.prototype,"ExternalSources",[k],Object.getOwnPropertyDescriptor(I.prototype,"ExternalSources"),I.prototype),ie(I.prototype,"IsProxy",[N],Object.getOwnPropertyDescriptor(I.prototype,"IsProxy"),I.prototype),ie(I.prototype,"IsOrigin",[C],Object.getOwnPropertyDescriptor(I.prototype,"IsOrigin"),I.prototype),ie(I.prototype,"IsMeshOrigin",[z],Object.getOwnPropertyDescriptor(I.prototype,"IsMeshOrigin"),I.prototype),ie(I.prototype,"Status",[M],Object.getOwnPropertyDescriptor(I.prototype,"Status"),I.prototype),ie(I.prototype,"ChecksPassing",[D],Object.getOwnPropertyDescriptor(I.prototype,"ChecksPassing"),I.prototype),ie(I.prototype,"ChecksWarning",[T],Object.getOwnPropertyDescriptor(I.prototype,"ChecksWarning"),I.prototype),ie(I.prototype,"ChecksCritical",[E],Object.getOwnPropertyDescriptor(I.prototype,"ChecksCritical"),I.prototype),ie(I.prototype,"PercentageChecksPassing",[L],Object.getOwnPropertyDescriptor(I.prototype,"PercentageChecksPassing"),I.prototype),ie(I.prototype,"PercentageChecksWarning",[A],Object.getOwnPropertyDescriptor(I.prototype,"PercentageChecksWarning"),I.prototype),ie(I.prototype,"PercentageChecksCritical",[R],Object.getOwnPropertyDescriptor(I.prototype,"PercentageChecksCritical"),I.prototype),I) +e.default=ae})),define("consul-ui/models/service",["exports","@ember-data/model","@ember/object","@glimmer/tracking","ember-data-model-fragments/attributes","consul-ui/decorators/replace"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D,T,E,L,A,R,I,$,F,U,B,q,K,H,Y,G,V,W,Z,Q,J,X,ee,te,ne,le,re,ie,oe,ae,ue,se,ce,de,pe,fe,me,he,be,ye,ve +function ge(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function Oe(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=e.Collection=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="Name,PeerName" +const Pe=(a=Oe((o=class{constructor(e){ge(this,"items",a,this),this.items=e}get ExternalSources(){const e=this.items.reduce((function(e,t){return e.concat(t.ExternalSources||[])}),[]) +return[...new Set(e)].filter(Boolean).sort()}get Partitions(){return[...new Set(this.items.map((e=>e.Partition)))].sort()}}).prototype,"items",[l.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) +e.Collection=Pe +let we=(u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,t.attr)("string"),p=(0,t.attr)("string"),f=(0,t.attr)("string"),m=(0,i.default)("",void 0),h=(0,t.attr)("string"),b=(0,t.attr)("number"),y=(0,t.attr)("number"),v=(0,t.attr)("number"),g=(0,t.attr)("number"),O=(0,t.attr)("boolean"),P=(0,t.attr)("boolean"),w=(0,t.attr)({defaultValue:()=>[]}),x=(0,t.attr)("number"),j=(0,t.attr)("number"),_=(0,t.attr)("number"),S=(0,i.nullValue)([]),k=(0,t.attr)({defaultValue:()=>[]}),N=(0,t.attr)(),C=(0,t.attr)(),z=(0,r.fragment)("gateway-config"),M=(0,i.nullValue)([]),D=(0,t.attr)(),T=(0,t.attr)(),E=(0,t.attr)(),L=(0,t.belongsTo)({async:!1}),A=(0,n.computed)("peer","InstanceCount"),R=(0,n.computed)("peer.State"),I=(0,n.computed)("ChecksPassing","ChecksWarning","ChecksCritical"),$=(0,n.computed)("MeshChecksPassing","MeshChecksWarning","MeshChecksCritical"),F=(0,n.computed)("ConnectedWithProxy","ConnectedWithGateway"),U=(0,n.computed)("MeshEnabled","Kind"),B=(0,n.computed)("MeshChecksPassing","MeshChecksWarning","MeshChecksCritical","isZeroCountButPeered","peerIsFailing"),q=(0,n.computed)("isZeroCountButPeered","peerIsFailing","MeshStatus"),K=(0,n.computed)("ChecksPassing","Proxy.ChecksPassing"),H=(0,n.computed)("ChecksWarning","Proxy.ChecksWarning"),Y=(0,n.computed)("ChecksCritical","Proxy.ChecksCritical"),G=class extends t.default{constructor(){super(...arguments),ge(this,"uid",V,this),ge(this,"Name",W,this),ge(this,"Datacenter",Z,this),ge(this,"Namespace",Q,this),ge(this,"Partition",J,this),ge(this,"Kind",X,this),ge(this,"PeerName",ee,this),ge(this,"ChecksPassing",te,this),ge(this,"ChecksCritical",ne,this),ge(this,"ChecksWarning",le,this),ge(this,"InstanceCount",re,this),ge(this,"ConnectedWithGateway",ie,this),ge(this,"ConnectedWithProxy",oe,this),ge(this,"Resources",ae,this),ge(this,"SyncTime",ue,this),ge(this,"CreateIndex",se,this),ge(this,"ModifyIndex",ce,this),ge(this,"Tags",de,this),ge(this,"Nodes",pe,this),ge(this,"Proxy",fe,this),ge(this,"GatewayConfig",me,this),ge(this,"ExternalSources",he,this),ge(this,"Meta",be,this),ge(this,"meta",ye,this),ge(this,"peer",ve,this)}get isZeroCountButPeered(){return this.peer&&0===this.InstanceCount}get peerIsFailing(){return this.peer&&"FAILING"===this.peer.State}get ChecksTotal(){return this.ChecksPassing+this.ChecksWarning+this.ChecksCritical}get MeshChecksTotal(){return this.MeshChecksPassing+this.MeshChecksWarning+this.MeshChecksCritical}get MeshEnabled(){return this.ConnectedWithProxy||this.ConnectedWithGateway}get InMesh(){return this.MeshEnabled||(this.Kind||"").length>0}get MeshStatus(){switch(!0){case this.isZeroCountButPeered:case this.peerIsFailing:return"unknown" +case 0!==this.MeshChecksCritical:return"critical" +case 0!==this.MeshChecksWarning:return"warning" +case 0!==this.MeshChecksPassing:return"passing" +default:return"empty"}}get healthTooltipText(){const{MeshStatus:e,isZeroCountButPeered:t,peerIsFailing:n}=this +return t?"This service currently has 0 instances. Check with the operator of its peer to make sure this is expected behavior.":n?"This peer is out of sync, so the current health statuses of its services are unknown.":"critical"===e?"At least one health check on one instance is failing.":"warning"===e?"At least one health check on one instance has a warning.":"passing"==e?"All health checks are passing.":"There are no health checks"}get MeshChecksPassing(){let e=0 +return void 0!==this.Proxy&&(e=this.Proxy.ChecksPassing),this.ChecksPassing+e}get MeshChecksWarning(){let e=0 +return void 0!==this.Proxy&&(e=this.Proxy.ChecksWarning),this.ChecksWarning+e}get MeshChecksCritical(){let e=0 +return void 0!==this.Proxy&&(e=this.Proxy.ChecksCritical),this.ChecksCritical+e}},V=Oe(G.prototype,"uid",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),W=Oe(G.prototype,"Name",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Z=Oe(G.prototype,"Datacenter",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Q=Oe(G.prototype,"Namespace",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),J=Oe(G.prototype,"Partition",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),X=Oe(G.prototype,"Kind",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ee=Oe(G.prototype,"PeerName",[m,h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),te=Oe(G.prototype,"ChecksPassing",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ne=Oe(G.prototype,"ChecksCritical",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),le=Oe(G.prototype,"ChecksWarning",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),re=Oe(G.prototype,"InstanceCount",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ie=Oe(G.prototype,"ConnectedWithGateway",[O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),oe=Oe(G.prototype,"ConnectedWithProxy",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ae=Oe(G.prototype,"Resources",[w],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ue=Oe(G.prototype,"SyncTime",[x],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),se=Oe(G.prototype,"CreateIndex",[j],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ce=Oe(G.prototype,"ModifyIndex",[_],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),de=Oe(G.prototype,"Tags",[S,k],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),pe=Oe(G.prototype,"Nodes",[N],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),fe=Oe(G.prototype,"Proxy",[C],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),me=Oe(G.prototype,"GatewayConfig",[z],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),he=Oe(G.prototype,"ExternalSources",[M,D],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),be=Oe(G.prototype,"Meta",[T],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ye=Oe(G.prototype,"meta",[E],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),ve=Oe(G.prototype,"peer",[L],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Oe(G.prototype,"isZeroCountButPeered",[A],Object.getOwnPropertyDescriptor(G.prototype,"isZeroCountButPeered"),G.prototype),Oe(G.prototype,"peerIsFailing",[R],Object.getOwnPropertyDescriptor(G.prototype,"peerIsFailing"),G.prototype),Oe(G.prototype,"ChecksTotal",[I],Object.getOwnPropertyDescriptor(G.prototype,"ChecksTotal"),G.prototype),Oe(G.prototype,"MeshChecksTotal",[$],Object.getOwnPropertyDescriptor(G.prototype,"MeshChecksTotal"),G.prototype),Oe(G.prototype,"MeshEnabled",[F],Object.getOwnPropertyDescriptor(G.prototype,"MeshEnabled"),G.prototype),Oe(G.prototype,"InMesh",[U],Object.getOwnPropertyDescriptor(G.prototype,"InMesh"),G.prototype),Oe(G.prototype,"MeshStatus",[B],Object.getOwnPropertyDescriptor(G.prototype,"MeshStatus"),G.prototype),Oe(G.prototype,"healthTooltipText",[q],Object.getOwnPropertyDescriptor(G.prototype,"healthTooltipText"),G.prototype),Oe(G.prototype,"MeshChecksPassing",[K],Object.getOwnPropertyDescriptor(G.prototype,"MeshChecksPassing"),G.prototype),Oe(G.prototype,"MeshChecksWarning",[H],Object.getOwnPropertyDescriptor(G.prototype,"MeshChecksWarning"),G.prototype),Oe(G.prototype,"MeshChecksCritical",[Y],Object.getOwnPropertyDescriptor(G.prototype,"MeshChecksCritical"),G.prototype),G) +e.default=we})),define("consul-ui/models/session",["exports","@ember-data/model","@ember/object","consul-ui/decorators/replace"],(function(e,t,n,l){var r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D,T,E,L,A,R,I,$ +function F(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function U(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="ID" +let B=(r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,t.attr)("string"),p=(0,t.attr)("string"),f=(0,t.attr)("number"),m=(0,t.attr)("number"),h=(0,t.attr)("number"),b=(0,t.attr)("number"),y=(0,l.nullValue)([]),v=(0,t.attr)({defaultValue:()=>[]}),g=(0,l.nullValue)([]),O=(0,t.attr)({defaultValue:()=>[]}),P=(0,t.attr)({defaultValue:()=>[]}),w=(0,n.computed)("NodeChecks","ServiceChecks"),x=class extends t.default{constructor(){super(...arguments),F(this,"uid",j,this),F(this,"ID",_,this),F(this,"Name",S,this),F(this,"Datacenter",k,this),F(this,"Namespace",N,this),F(this,"Partition",C,this),F(this,"Node",z,this),F(this,"Behavior",M,this),F(this,"TTL",D,this),F(this,"LockDelay",T,this),F(this,"SyncTime",E,this),F(this,"CreateIndex",L,this),F(this,"ModifyIndex",A,this),F(this,"NodeChecks",R,this),F(this,"ServiceChecks",I,this),F(this,"Resources",$,this)}get checks(){return[...this.NodeChecks,...this.ServiceChecks.map((e=>{let{ID:t}=e +return t}))]}},j=U(x.prototype,"uid",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=U(x.prototype,"ID",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=U(x.prototype,"Name",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=U(x.prototype,"Datacenter",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=U(x.prototype,"Namespace",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=U(x.prototype,"Partition",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=U(x.prototype,"Node",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=U(x.prototype,"Behavior",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=U(x.prototype,"TTL",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=U(x.prototype,"LockDelay",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=U(x.prototype,"SyncTime",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=U(x.prototype,"CreateIndex",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=U(x.prototype,"ModifyIndex",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R=U(x.prototype,"NodeChecks",[y,v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=U(x.prototype,"ServiceChecks",[g,O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),$=U(x.prototype,"Resources",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),U(x.prototype,"checks",[w],Object.getOwnPropertyDescriptor(x.prototype,"checks"),x.prototype),x) +e.default=B})),define("consul-ui/models/token",["exports","@ember-data/model","@ember/object","consul-ui/models/policy"],(function(e,t,n,l){var r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z,M,D,T,E,L,A,R,I,$,F,U,B,q,K,H,Y,G,V,W,Z +function Q(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function J(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="AccessorID" +let X=(r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("string"),c=(0,t.attr)("string"),d=(0,t.attr)("boolean"),p=(0,t.attr)("boolean"),f=(0,t.attr)("string",{defaultValue:()=>""}),m=(0,t.attr)(),h=(0,t.attr)({defaultValue:()=>[]}),b=(0,t.attr)({defaultValue:()=>[]}),y=(0,t.attr)({defaultValue:()=>[]}),v=(0,t.attr)({defaultValue:()=>[]}),g=(0,t.attr)("date"),O=(0,t.attr)("string"),P=(0,t.attr)("number"),w=(0,t.attr)("number"),x=(0,t.attr)("string"),j=(0,t.attr)("string",{defaultValue:()=>""}),_=(0,t.attr)("string"),S=(0,n.computed)("Policies.[]"),k=(0,n.computed)("SecretID"),N=class extends t.default{constructor(){super(...arguments),Q(this,"uid",C,this),Q(this,"AccessorID",z,this),Q(this,"Datacenter",M,this),Q(this,"Namespace",D,this),Q(this,"Partition",T,this),Q(this,"IDPName",E,this),Q(this,"SecretID",L,this),Q(this,"Legacy",A,this),Q(this,"Local",R,this),Q(this,"Description",I,this),Q(this,"meta",$,this),Q(this,"Policies",F,this),Q(this,"Roles",U,this),Q(this,"ServiceIdentities",B,this),Q(this,"NodeIdentities",q,this),Q(this,"CreateTime",K,this),Q(this,"Hash",H,this),Q(this,"CreateIndex",Y,this),Q(this,"ModifyIndex",G,this),Q(this,"Type",V,this),Q(this,"Name",W,this),Q(this,"Rules",Z,this)}get isGlobalManagement(){return(this.Policies||[]).find((e=>e.ID===l.MANAGEMENT_ID))}get hasSecretID(){return""!==this.SecretID&&""!==this.SecretID}},C=J(N.prototype,"uid",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=J(N.prototype,"AccessorID",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),M=J(N.prototype,"Datacenter",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D=J(N.prototype,"Namespace",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=J(N.prototype,"Partition",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E=J(N.prototype,"IDPName",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=J(N.prototype,"SecretID",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),A=J(N.prototype,"Legacy",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R=J(N.prototype,"Local",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=J(N.prototype,"Description",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),$=J(N.prototype,"meta",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),F=J(N.prototype,"Policies",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),U=J(N.prototype,"Roles",[b],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),B=J(N.prototype,"ServiceIdentities",[y],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),q=J(N.prototype,"NodeIdentities",[v],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),K=J(N.prototype,"CreateTime",[g],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),H=J(N.prototype,"Hash",[O],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Y=J(N.prototype,"CreateIndex",[P],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),G=J(N.prototype,"ModifyIndex",[w],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),V=J(N.prototype,"Type",[x],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),W=J(N.prototype,"Name",[j],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),Z=J(N.prototype,"Rules",[_],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),J(N.prototype,"isGlobalManagement",[S],Object.getOwnPropertyDescriptor(N.prototype,"isGlobalManagement"),N.prototype),J(N.prototype,"hasSecretID",[k],Object.getOwnPropertyDescriptor(N.prototype,"hasSecretID"),N.prototype),N) +e.default=X})),define("consul-ui/models/topology",["exports","@ember-data/model","@ember/object"],(function(e,t,n){var l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g,O,P,w,x,j,_,S,k,N,C,z +function M(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function D(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=e.SLUG_KEY=e.PRIMARY_KEY=void 0 +e.PRIMARY_KEY="uid" +e.SLUG_KEY="ServiceName" +let T=(l=(0,t.attr)("string"),r=(0,t.attr)("string"),i=(0,t.attr)("string"),o=(0,t.attr)("string"),a=(0,t.attr)("string"),u=(0,t.attr)("string"),s=(0,t.attr)("boolean"),c=(0,t.attr)("boolean"),d=(0,t.attr)("boolean"),p=(0,t.attr)(),f=(0,t.attr)(),m=(0,t.attr)(),h=(0,n.computed)("Downstreams"),b=(0,n.computed)("Downstreams","Upstreams"),y=(0,n.computed)("Downstreams","Upstreams"),v=class extends t.default{constructor(){super(...arguments),M(this,"uid",g,this),M(this,"ServiceName",O,this),M(this,"Datacenter",P,this),M(this,"Namespace",w,this),M(this,"Partition",x,this),M(this,"Protocol",j,this),M(this,"FilteredByACLs",_,this),M(this,"TransparentProxy",S,this),M(this,"ConnectNative",k,this),M(this,"Upstreams",N,this),M(this,"Downstreams",C,this),M(this,"meta",z,this)}get notDefinedIntention(){let e=!1 +return e=0!==this.Downstreams.filter((e=>"specific-intention"===e.Source&&!e.TransparentProxy&&!e.ConnectNative&&e.Intention.Allowed)).length,e}get wildcardIntention(){const e=0!==this.Downstreams.filter((e=>!e.Intention.HasExact&&e.Intention.Allowed)).length,t=0!==this.Upstreams.filter((e=>!e.Intention.HasExact&&e.Intention.Allowed)).length +return e||t}get noDependencies(){return 0===this.Upstreams.length&&0===this.Downstreams.length}},g=D(v.prototype,"uid",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=D(v.prototype,"ServiceName",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=D(v.prototype,"Datacenter",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=D(v.prototype,"Namespace",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=D(v.prototype,"Partition",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),j=D(v.prototype,"Protocol",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),_=D(v.prototype,"FilteredByACLs",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=D(v.prototype,"TransparentProxy",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),k=D(v.prototype,"ConnectNative",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=D(v.prototype,"Upstreams",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=D(v.prototype,"Downstreams",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=D(v.prototype,"meta",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),D(v.prototype,"notDefinedIntention",[h],Object.getOwnPropertyDescriptor(v.prototype,"notDefinedIntention"),v.prototype),D(v.prototype,"wildcardIntention",[b],Object.getOwnPropertyDescriptor(v.prototype,"wildcardIntention"),v.prototype),D(v.prototype,"noDependencies",[y],Object.getOwnPropertyDescriptor(v.prototype,"noDependencies"),v.prototype),v) +e.default=T})),define("consul-ui/modifiers/aria-menu",["exports","ember-modifier","@ember/service","@ember/object","@ember/destroyable"],(function(e,t,n,l,r){var i,o,a +function u(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const c={vertical:{40:function(e){return((arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1)+1)%e.length},38:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0 +return 0===t?e.length-1:t-1},36:(e,t)=>0,35:(e,t)=>e.length-1},horizontal:{}} +function d(e){var t +e&&(null==e||null===(t=e.doc)||void 0===t||t.removeEventListener("keydown",null==e?void 0:e.keydown))}let p=(i=(0,n.inject)("-document"),o=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="doc",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),u(this,"orientation","vertical")}async keydown(e){var t,n +if(27===e.keyCode)return this.options.onclose(e),void(null===(n=this.$trigger)||void 0===n||n.focus()) +const l=[...this.element.querySelectorAll('[role^="menuitem"]')],r=l.findIndex((e=>e===this.doc.activeElement)) +var i +9!==e.keyCode?void 0!==c[this.orientation][e.keyCode]&&(null===(t=l[c[this.orientation][e.keyCode](l,r)])||void 0===t||t.focus(),e.stopPropagation(),e.preventDefault()):e.shiftKey?0===r&&(this.options.onclose(e),null===(i=this.$trigger)||void 0===i||i.focus()):r===l.length-1&&(await new Promise((e=>setTimeout(e,0))),this.options.onclose(e))}async focus(e){""===e.pointerType&&(await Promise.resolve(),this.keydown({keyCode:36,stopPropagation:()=>{},preventDefault:()=>{}}))}modify(e,t,n){this.params=t,this.options=n,this.$trigger||(this.element=e,this.$trigger=this.doc.getElementById(e.getAttribute("aria-labelledby")),void 0!==n.openEvent&&this.focus(n.openEvent),this.doc.addEventListener("keydown",this.keydown)),(0,r.registerDestructor)(this,d)}},a=s(o.prototype,"doc",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s(o.prototype,"keydown",[l.action],Object.getOwnPropertyDescriptor(o.prototype,"keydown"),o.prototype),s(o.prototype,"focus",[l.action],Object.getOwnPropertyDescriptor(o.prototype,"focus"),o.prototype),o) +e.default=p})),define("consul-ui/modifiers/create-ref",["exports","ember-ref-bucket/modifiers/create-ref"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/css-prop",["exports","ember-modifier","@ember/service"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,n.inject)("-document"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="doc",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}modify(e,t,n){(t[1]||(null==n?void 0:n.returns))(this.doc.defaultView.getComputedStyle(e).getPropertyValue(t[0]))}},a=r.prototype,u="doc",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/modifiers/css-props",["exports","ember-modifier"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const n=Object.fromEntries([...document.styleSheets].reduce(((e,t)=>e.concat([...t.cssRules].filter((e=>1===e.type)).reduce(((e,t)=>[...e,...[...t.style].filter((e=>e.startsWith("--"))).map((e=>[e.trim(),t.style.getPropertyValue(e).trim()]))]),[]))),[])) +var l=(0,t.modifier)((function(e,t,l){let[r]=t +const i=new RegExp(`^--${l.prefix||"."}${l.group||""}+`),o={} +Object.entries(n).forEach((e=>{let[t,n]=e +const r=t.match(i) +if(r){let e=r[0] +"-"===e.charAt(e.length-1)&&(e=e.substr(0,e.length-1)),l.group?(void 0===o[e]&&(o[e]={}),o[e][t]=n):o[t]=n}})),r(o)})) +e.default=l})),define("consul-ui/modifiers/did-insert",["exports","@ember/render-modifiers/modifiers/did-insert"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/did-update",["exports","@ember/render-modifiers/modifiers/did-update"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/did-upsert",["exports","ember-modifier"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{modify(e,t,n){this.element=e +const[l,...r]=t +var i +l({target:(i=this).element,currentTarget:i.element},r,n)}}e.default=n})),define("consul-ui/modifiers/disabled",["exports","ember-modifier"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.modifier)((function(e,t,n){let[l=!0]=t +if(["input","textarea","select","button"].includes(e.nodeName.toLowerCase()))l?(e.setAttribute("disabled",l),e.setAttribute("aria-disabled",l)):(e.dataset.disabled=!1,e.removeAttribute("disabled"),e.removeAttribute("aria-disabled")) +else for(const r of e.querySelectorAll("input,textarea,button"))l&&"false"!==r.dataset.disabled?(e.setAttribute("disabled",l),e.setAttribute("aria-disabled",l)):(e.removeAttribute("disabled"),e.removeAttribute("aria-disabled"))})) +e.default=n})),define("consul-ui/modifiers/focus-trap",["exports","ember-focus-trap/modifiers/focus-trap.js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/hds-clipboard",["exports","@hashicorp/design-system-components/modifiers/hds-clipboard"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/hds-tooltip",["exports","@hashicorp/design-system-components/modifiers/hds-tooltip"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/notification",["exports","ember-modifier","@ember/service","@ember/destroyable"],(function(e,t,n,l){var r,i,o +function a(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function u(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e){var t,n +e&&null!=e&&null!==(t=e.named)&&void 0!==t&&t.sticky&&(null===(n=e.notify)||void 0===n||n.clearMessages())}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let c=(r=(0,n.inject)("flashMessages"),i=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="notify",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}modify(e,t,n){this.named=n,e.setAttribute("role","alert"),e.dataset.notification=null +const r=function(e){for(var t=1;tr.after())).catch((e=>{if("TransitionAborted"!==e.name)throw e})).then((e=>{this.notify.add(r)})):this.notify.add(r),(0,l.registerDestructor)(this,s)}},d=i.prototype,p="notify",f=[r],m={configurable:!0,enumerable:!0,writable:!0,initializer:null},b={},Object.keys(m).forEach((function(e){b[e]=m[e]})),b.enumerable=!!b.enumerable,b.configurable=!!b.configurable,("value"in b||b.initializer)&&(b.writable=!0),b=f.slice().reverse().reduce((function(e,t){return t(d,p,e)||e}),b),h&&void 0!==b.initializer&&(b.value=b.initializer?b.initializer.call(h):void 0,b.initializer=void 0),void 0===b.initializer&&(Object.defineProperty(d,p,b),b=null),o=b,i) +var d,p,f,m,h,b +e.default=c})),define("consul-ui/modifiers/on-key",["exports","ember-keyboard/modifiers/on-key.js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})) +define("consul-ui/modifiers/on-outside",["exports","ember-modifier","@ember/object","@ember/service","@ember/destroyable"],(function(e,t,n,l,r){var i,o,a +function u(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}function s(e){var t +e&&(null===(t=e.doc)||void 0===t||t.removeEventListener("click",e.listen))}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let c=(i=(0,l.inject)("dom"),o=class extends t.default{constructor(e,t){var n,l,i,o +super(e,t),n=this,l="dom",o=this,(i=a)&&Object.defineProperty(n,l,{enumerable:i.enumerable,configurable:i.configurable,writable:i.writable,value:i.initializer?i.initializer.call(o):void 0}),this.doc=this.dom.document(),(0,r.registerDestructor)(this,s)}async modify(e,t,n){s.call(this),this.params=t,this.options=n,this.element=e,await new Promise((e=>setTimeout(e,0))) +try{this.doc.addEventListener(t[0],this.listen)}catch(l){}}listen(e){if(this.element&&this.dom.isOutside(this.element,e.target)){("function"==typeof this.params[1]?this.params[1]:e=>{}).apply(this.element,[e])}}},a=u(o.prototype,"dom",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u(o.prototype,"listen",[n.action],Object.getOwnPropertyDescriptor(o.prototype,"listen"),o.prototype),o) +e.default=c})),define("consul-ui/modifiers/on-resize",["exports","ember-on-resize-modifier/modifiers/on-resize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/style",["exports","ember-modifier","@ember/debug"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{setStyles(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[] +const t=this._oldStyles||new Set +Array.isArray(e)||(e=Object.entries(e)),e.forEach((e=>{let[n,l]=e,r="" +l.length>0&&l.includes("!important")&&(r="important",l=l.replace("!important","")),this.element.style.setProperty(n,l,r),t.delete(n)})),t.forEach((e=>this.element.style.removeProperty(e))),this._oldStyles=new Set(e.map((e=>e[0])))}modify(e,t,n){this.element=e,void 0!==n.delay?setTimeout((e=>{typeof this!==t[0]&&this.setStyles(t[0])}),null==n?void 0:n.delay):this.setStyles(t[0])}}e.default=l})),define("consul-ui/modifiers/tooltip",["exports","ember-modifier","tippy.js"],(function(e,t,n){function l(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function r(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var i=(0,t.modifier)((function(e,t){let[i]=t,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{} +if("string"==typeof i&&""===i.trim())return +const a=o.options||{} +let u,s=e +if("string"==typeof a.triggerTarget){const e=s +if("parentNode"===a.triggerTarget)s=s.parentNode +else s=s.querySelectorAll(a.triggerTarget) +i=s.cloneNode(!0),e.remove(),o.options.triggerTarget=void 0}if(void 0===i&&(i=s.innerHTML,s.innerHTML=""),"manual"===a.trigger){const e=a.delay||[] +void 0!==e[1]&&(o.options.onShown=t=>{clearInterval(u),u=setTimeout((()=>{t.hide()}),e[1])})}let c=s,d=!1 +c.hasAttribute("tabindex")||(d=!0,c.setAttribute("tabindex","0")) +const p=(0,n.default)(s,function(e){for(var t=1;ti,plugins:[void 0!==a.followCursor?n.followCursor:void 0].filter((e=>Boolean(e)))},o.options)) +return()=>{d&&c.removeAttribute("tabindex"),clearInterval(u),p.destroy()}})) +e.default=i})),define("consul-ui/modifiers/validate",["exports","ember-modifier","@ember/object","@ember/destroyable"],(function(e,t,n,l){var r +function i(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class a extends Error{}function u(e){var t,n +e&&null!=e&&e.element&&(null==e||null===(t=e.element)||void 0===t||t.removeEventListener("input",null==e?void 0:e.listen),null==e||null===(n=e.element)||void 0===n||n.removeEventListener("blur",null==e?void 0:e.reset))}let s=(r=class extends t.default{validate(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +if(0===Object.keys(t).length)return +const n={} +Object.entries(this.hash.validations).filter((e=>{let[t,n]=e +return"string"!=typeof n})).forEach((t=>{let[l,r]=t +this.item&&(this.item[l]=e),(r||[]).forEach((t=>{new RegExp(t.test).test(e)||(n[l]=new a(t.error))}))})) +const l=this.hash.chart.state||{} +null==l.context&&(l.context={}),Object.keys(n).length>0?(l.context.errors=n,this.hash.chart.dispatch("ERROR",l.context)):(l.context.errors=null,this.hash.chart.dispatch("RESET",l.context))}reset(e){if(0===e.target.value.length){const e=this.hash.chart.state +e.context||(e.context={}),e.context.errors||(e.context.errors={}),Object.entries(this.hash.validations).filter((e=>{let[t,n]=e +return"string"!=typeof n})).forEach((t=>{let[n,l]=t +void 0!==e.context.errors[n]&&delete e.context.errors[n]})),0===Object.keys(e.context.errors).length&&(e.context.errors=null,this.hash.chart.dispatch("RESET",e.context))}}listen(e){this.validate(e.target.value,this.hash.validations)}constructor(e,t){super(e,t),i(this,"item",null),i(this,"hash",null),(0,l.registerDestructor)(this,u)}async modify(e,t,n){u.call(this),this.element=e,this.hash=n,this.item=t[0],void 0===this.hash.chart&&(this.hash.chart={state:{context:{}},dispatch:e=>{switch(e){case"ERROR":this.hash.onchange(this.hash.chart.state.context.errors) +break +case"RESET":this.hash.onchange()}}}),this.element.addEventListener("input",this.listen),this.element.addEventListener("blur",this.reset),this.element.value.length>0&&(await Promise.resolve(),this&&this.element&&this.validate(this.element.value,this.hash.validations))}},o(r.prototype,"reset",[n.action],Object.getOwnPropertyDescriptor(r.prototype,"reset"),r.prototype),o(r.prototype,"listen",[n.action],Object.getOwnPropertyDescriptor(r.prototype,"listen"),r.prototype),r) +e.default=s})),define("consul-ui/modifiers/will-destroy",["exports","@ember/render-modifiers/modifiers/will-destroy"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/modifiers/with-copyable",["exports","ember-modifier","@ember/service","@ember/debug","@ember/destroyable"],(function(e,t,n,l,r){var i,o,a +function u(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function s(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const c=(e,t,n)=>typeof t===e?t:n +function d(e){var t,n,l +e&&null!=e&&e.source&&null!=e&&e.hash&&(null===(t=e.source)||void 0===t||null===(n=t.off("success",e.hash.success))||void 0===n||n.off("error",e.hash.error),null===(l=e.source)||void 0===l||l.destroy(),e.hash=null,e.source=null)}let p=(i=(0,n.inject)("clipboard/os"),o=class extends t.default{connect(e,t){let[n]=e +n=c("string",n,this.element.innerText) +const r={success:e=>((0,l.runInDebug)((e=>console.info(`with-copyable: Copied \`${n}\``))),c("function",t.success,(()=>{}))(e)),error:e=>((0,l.runInDebug)((e=>console.info(`with-copyable: Error copying \`${n}\``))),c("function",t.error,(()=>{}))(e))} +this.source=this.clipboard.execute(this.element,function(e){for(var t=1;tn,container:this.element},r.options)).on("success",r.success).on("error",r.error),this.hash=r}constructor(){var e,t,n,l +super(...arguments),e=this,t="clipboard",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),s(this,"hash",null),s(this,"source",null),(0,r.registerDestructor)(this,d)}modify(e,t,n){this.element=e,this.disconnect(),this.connect(t,n)}disconnect(){d.call(this)}},f=o.prototype,m="clipboard",h=[i],b={configurable:!0,enumerable:!0,writable:!0,initializer:null},v={},Object.keys(b).forEach((function(e){v[e]=b[e]})),v.enumerable=!!v.enumerable,v.configurable=!!v.configurable,("value"in v||v.initializer)&&(v.writable=!0),v=h.slice().reverse().reduce((function(e,t){return t(f,m,e)||e}),v),y&&void 0!==v.initializer&&(v.value=v.initializer?v.initializer.call(y):void 0,v.initializer=void 0),void 0===v.initializer&&(Object.defineProperty(f,m,v),v=null),a=v,o) +var f,m,h,b,y,v +e.default=p})),define("consul-ui/modifiers/with-overlay",["exports","ember-modifier","tippy.js"],(function(e,t,n){function l(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function r(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var i=(0,t.modifier)((function(e,t){let[i]=t,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{} +const a=o.options||{} +let u,s=e +if("string"==typeof a.triggerTarget){const e=s +if("parentNode"===a.triggerTarget)s=s.parentNode +else s=s.querySelectorAll(a.triggerTarget) +i=s.cloneNode(!0),e.remove(),o.options.triggerTarget=void 0}if(void 0===i&&(i=s.innerHTML,s.innerHTML=""),o.returns&&(a.trigger="manual"),"manual"===a.trigger){const e=a.delay||[] +void 0!==e[1]&&(a.onShown=t=>{clearInterval(u),u=setTimeout((()=>{t.hide()}),e[1])})}let c=s +const d=(0,n.default)(s,function(e){for(var t=1;ti,interactive:!0,plugins:[void 0!==a.followCursor?n.followCursor:void 0].filter((e=>Boolean(e)))},a)) +return o.returns&&o.returns(d),()=>{clearInterval(u),d.destroy()}})) +e.default=i})),define("consul-ui/router",["exports","@ember/routing/router","consul-ui/config/environment","@ember/debug","deepmerge","consul-ui/env","consul-ui/utils/routing/walk"],(function(e,t,n,l,r,i,o){function a(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.routes=e.default=void 0 +const u=document,s=n.default.modulePrefix,c=r.default.all([...u.querySelectorAll("script[data-routes]")].map((e=>JSON.parse(e.dataset.routes)))) +e.routes=c,(0,l.runInDebug)((()=>{const e=requirejs.entries[`${s}/docfy-output`] +if(void 0!==e){const t={} +e.callback(t),function e(t,n){"/"!==n.name&&(t=t[n.name]={_options:{path:n.name}}),n.pages.forEach((e=>{const n=e.relativeUrl +"string"==typeof n&&""!==n&&(t[n]={_options:{path:n}})})),n.children.forEach((n=>{e(t,n)}))}(c,t.default.nested)}})),(0,l.runInDebug)((()=>{window.Routes=function(){let e,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:(0,i.env)("DEBUG_ROUTES_ENDPOINT") +t||(t="data:,%s") +const n=(0,o.dump)(c) +t.startsWith("data:,")?(e=window.open("","_blank"),e.document.write(`
      ${n}
      `)):e=window.open(t.replace("%s",encodeURIComponent(n)),"_blank"),e.focus()}})) +class d extends t.default{constructor(){super(...arguments),a(this,"location",(0,i.env)("locationType")),a(this,"rootURL",(0,i.env)("rootURL"))}}e.default=d,d.map((0,o.default)(c))})),define("consul-ui/routes/application",["exports","consul-ui/routing/route","@ember/object","@ember/service","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l,r){var i,o,a,u,s,c,d,p,f +function m(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function h(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function b(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let y=(i=(0,l.inject)("client/http"),o=(0,l.inject)("env"),a=(0,l.inject)(),u=(0,l.inject)(),s=class extends(t.default.extend(r.default)){constructor(){super(...arguments),m(this,"client",c,this),m(this,"env",d,this),m(this,"hcp",p,this),m(this,"router",f,this),h(this,"data",void 0)}beforeModel(){this.env.var("CONSUL_V2_CATALOG_ENABLED")&&this.router.replaceWith("unavailable")}async model(){return this.env.var("CONSUL_ACLS_ENABLED")&&await this.hcp.updateTokenIfNecessary(this.env.var("CONSUL_HTTP_TOKEN")),{}}onClientChanged(e){let t=e.data +""===t&&(t={blocking:!0}),void 0!==this.data?(!0===this.data.blocking&&!1===t.blocking&&this.client.abort(),this.data=Object.assign({},t)):this.data=Object.assign({},t)}error(e,t){let n={status:e.code||e.statusCode||"",message:e.message||e.detail||"Error"} +return e.errors&&e.errors[0]&&(n=e.errors[0],n.message=n.message||n.title||n.detail||"Error"),""===n.status&&(n.message="Error"),this.controllerFor("application").setProperties({error:n}),!0}},c=b(s.prototype,"client",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=b(s.prototype,"env",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=b(s.prototype,"hcp",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=b(s.prototype,"router",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b(s.prototype,"onClientChanged",[n.action],Object.getOwnPropertyDescriptor(s.prototype,"onClientChanged"),s.prototype),b(s.prototype,"error",[n.action],Object.getOwnPropertyDescriptor(s.prototype,"error"),s.prototype),s) +e.default=y})),define("consul-ui/routes/dc",["exports","@ember/service","consul-ui/routing/route"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,t.inject)("repository/permission"),r=class extends n.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="permissionsRepo",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}async model(e){const t=await this.permissionsRepo.findAll({dc:e.dc,ns:this.optionalParams().nspace,partition:this.optionalParams().partition}) +return this.controllerFor("application").setProperties({permissions:t}),{permissions:t}}},a=r.prototype,u="permissionsRepo",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/routes/dc/acls/auth-methods/index",["exports","consul-ui/routing/route"],(function(e,t){function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{constructor(){super(...arguments),n(this,"queryParams",{sortBy:"sort",source:"source",kind:"kind",searchproperty:{as:"searchproperty",empty:[["Name","DisplayName"]]},search:{as:"filter",replace:!0}})}}e.default=l})),define("consul-ui/routes/dc/acls/auth-methods/show/index",["exports","consul-ui/routing/route","consul-ui/utils/routing/redirect-to"],(function(e,t,n){function l(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class r extends t.default{constructor(){super(...arguments),l(this,"redirect",(0,n.default)("auth-method"))}}e.default=r})),define("consul-ui/routes/dc/acls/policies/create",["exports","consul-ui/routes/dc/acls/policies/edit"],(function(e,t){function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{constructor(){super(...arguments),n(this,"templateName","dc/acls/policies/edit")}}e.default=l})),define("consul-ui/routes/dc/acls/policies/edit",["exports","@ember/service","consul-ui/routing/route","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l){var r,i,o +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let a=(r=(0,t.inject)("repository/policy"),i=class extends(n.default.extend(l.default)){constructor(){var e,t,n,l +super(...arguments),e=this,t="repo",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}},u=i.prototype,s="repo",c=[r],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),o=f,i) +var u,s,c,d,p,f +e.default=a})),define("consul-ui/routes/dc/acls/policies/index",["exports","consul-ui/routing/route","@ember/service","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l){var r,i,o +function a(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let u=(r=(0,n.inject)("repository/policy"),i=class extends(t.default.extend(l.default)){constructor(){var e,t,n,l +super(...arguments),e=this,t="repo",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a(this,"queryParams",{sortBy:"sort",datacenter:{as:"dc"},kind:"kind",searchproperty:{as:"searchproperty",empty:[["Name","Description"]]},search:{as:"filter",replace:!0}})}},s=i.prototype,c="repo",d=[r],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),o=m,i) +var s,c,d,p,f,m +e.default=u})),define("consul-ui/routes/dc/acls/roles/create",["exports","consul-ui/routes/dc/acls/roles/edit"],(function(e,t){function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{constructor(){super(...arguments),n(this,"templateName","dc/acls/roles/edit")}}e.default=l})),define("consul-ui/routes/dc/acls/roles/edit",["exports","@ember/service","consul-ui/routing/route","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l){var r,i,o +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let a=(r=(0,t.inject)("repository/role"),i=class extends(n.default.extend(l.default)){constructor(){var e,t,n,l +super(...arguments),e=this,t="repo",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}},u=i.prototype,s="repo",c=[r],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),o=f,i) +var u,s,c,d,p,f +e.default=a})),define("consul-ui/routes/dc/acls/roles/index",["exports","consul-ui/routing/route","@ember/service","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l){var r,i,o +function a(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let u=(r=(0,n.inject)("repository/role"),i=class extends(t.default.extend(l.default)){constructor(){var e,t,n,l +super(...arguments),e=this,t="repo",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a(this,"queryParams",{sortBy:"sort",searchproperty:{as:"searchproperty",empty:[["Name","Description","Policy"]]},search:{as:"filter",replace:!0}})}},s=i.prototype,c="repo",d=[r],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),o=m,i) +var s,c,d,p,f,m +e.default=u})),define("consul-ui/routes/dc/acls/tokens/create",["exports","consul-ui/routes/dc/acls/tokens/edit"],(function(e,t){function n(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{constructor(){super(...arguments),n(this,"templateName","dc/acls/tokens/edit")}}e.default=l})),define("consul-ui/routes/dc/acls/tokens/edit",["exports","@ember/service","consul-ui/routing/route","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l){var r,i,o,a,u +function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let d=(r=(0,t.inject)("repository/token"),i=(0,t.inject)("settings"),o=class extends(n.default.extend(l.default)){constructor(){super(...arguments),s(this,"repo",a,this),s(this,"settings",u,this)}async model(e,t){return{token:await this.settings.findBySlug("token")}}},a=c(o.prototype,"repo",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(o.prototype,"settings",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) +e.default=d})),define("consul-ui/routes/dc/acls/tokens/index",["exports","consul-ui/routing/route","@ember/service","consul-ui/mixins/with-blocking-actions"],(function(e,t,n,l){var r,i,o +function a(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let u=(r=(0,n.inject)("repository/token"),i=class extends(t.default.extend(l.default)){constructor(){var e,t,n,l +super(...arguments),e=this,t="repo",l=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),a(this,"queryParams",{sortBy:"sort",kind:"kind",searchproperty:{as:"searchproperty",empty:[["AccessorID","Description","Role","Policy"]]},search:{as:"filter",replace:!0}})}},s=i.prototype,c="repo",d=[r],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),o=m,i) +var s,c,d,p,f,m +e.default=u})),define("consul-ui/routes/dc/kv/folder",["exports","consul-ui/routes/dc/kv/index"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{beforeModel(e){super.beforeModel(...arguments) +const t=this.paramsFor("dc.kv.folder") +if("/"===t.key||null==t.key)return this.transitionTo("dc.kv.index")}}e.default=n})),define("consul-ui/routes/dc/kv/index",["exports","consul-ui/routing/route","@ember/object","consul-ui/utils/isFolder"],(function(e,t,n,l){var r +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let i=(r=class extends t.default{beforeModel(){const e=this.paramsFor(this.routeName).key||"/" +if(!(0,l.default)(e))return this.replaceWith(this.routeName,e+"/")}error(e){return!e.errors||!e.errors[0]||"404"!=e.errors[0].status||this.transitionTo("dc.kv.index")}},o=r.prototype,a="error",u=[n.action],s=Object.getOwnPropertyDescriptor(r.prototype,"error"),c=r.prototype,d={},Object.keys(s).forEach((function(e){d[e]=s[e]})),d.enumerable=!!d.enumerable,d.configurable=!!d.configurable,("value"in d||d.initializer)&&(d.writable=!0),d=u.slice().reverse().reduce((function(e,t){return t(o,a,e)||e}),d),c&&void 0!==d.initializer&&(d.value=d.initializer?d.initializer.call(c):void 0,d.initializer=void 0),void 0===d.initializer&&(Object.defineProperty(o,a,d),d=null),r) +var o,a,u,s,c,d +e.default=i})),define("consul-ui/routes/dc/services/notfound",["exports","consul-ui/routing/route"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{redirect(e,t){this.replaceWith("dc.services.instance",e.name,e.node,e.id)}}e.default=n})),define("consul-ui/routes/dc/services/show/topology",["exports","consul-ui/routing/route","@ember/service","@ember/object"],(function(e,t,n,l){var r,i,o,a,u,s,c +function d(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function p(e){for(var t=1;tn.Datacenter===e.Datacenter&&n.SourceName===e.Name&&n.SourceNS===e.Namespace&&n.SourcePartition===e.Partition&&n.DestinationName===t.Name&&n.DestinationNS===t.Namespace&&n.DestinationPartition===t.Partition)) +void 0===r?r=this.repo.create({Datacenter:e.Datacenter,SourceName:e.Name,SourceNS:e.Namespace||"default",SourcePartition:e.Partition||"default",DestinationName:t.Name,DestinationNS:t.Namespace||"default",DestinationPartition:t.Partition||"default"}):n=this.feedback.notification("update","intention"),(0,l.set)(r,"Action","allow"),await this.repo.persist(r),n.success(r)}catch(r){n.error(r)}this.refresh()}afterModel(e,t){const n=p(p(p({},this.optionalParams()),this.paramsFor("dc")),this.paramsFor("dc.services.show")) +this.intentions=this.data.source((e=>e`/${n.partition}/${n.nspace}/${n.dc}/intentions/for-service/${n.name}`))}async deactivate(e){(await this.intentions).destroy()}},u=h(a.prototype,"data",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s=h(a.prototype,"repo",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c=h(a.prototype,"feedback",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h(a.prototype,"createIntention",[l.action],Object.getOwnPropertyDescriptor(a.prototype,"createIntention"),a.prototype),a) +e.default=b})),define("consul-ui/routes/unavailable",["exports","consul-ui/routing/route","@ember/service"],(function(e,t,n){var l,r,i,o,a +function u(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let c=(l=(0,n.inject)("env"),r=(0,n.inject)(),i=class extends t.default{constructor(){super(...arguments),u(this,"env",o,this),u(this,"router",a,this)}beforeModel(){this.env.var("CONSUL_V2_CATALOG_ENABLED")||this.router.replaceWith("index")}},o=s(i.prototype,"env",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=s(i.prototype,"router",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) +e.default=c})),define("consul-ui/routing/route",["exports","@ember/routing/route","@ember/object","@ember/service","consul-ui/utils/path/resolve","consul-ui/router"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m,h,b +function y(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function v(e){for(var t=1;t!n.includes(e))).length&&(e=void 0)}}return e}model(){const e={} +return void 0!==this.queryParams&&void 0!==this.queryParams.searchproperty&&(e.searchProperties=this.queryParams.searchproperty.empty[0]),e}setupController(e,t){(0,n.setProperties)(e,v(v({},t),{},{routeName:this.routeName})),super.setupController(...arguments)}optionalParams(){return this.container.get(`location:${this.env.var("locationType")}`).optionalParams()}paramsFor(e){return this.routlet.normalizeParamsFor(this.routeName,super.paramsFor(...arguments))}async replaceWith(e,t){await Promise.resolve() +let n=[] +return"string"==typeof t&&(n=[t]),void 0===t||Array.isArray(t)||"string"==typeof t||(n=Object.values(t)),super.replaceWith(e,...n)}async transitionTo(e,t){await Promise.resolve() +let n=[] +return"string"==typeof t&&(n=[t]),void 0===t||Array.isArray(t)||"string"==typeof t||(n=Object.values(t)),this.router.transitionTo(e,...n)}},p=P(d.prototype,"container",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=P(d.prototype,"env",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=P(d.prototype,"permissions",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=P(d.prototype,"router",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=P(d.prototype,"routlet",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P(d.prototype,"replaceWith",[n.action],Object.getOwnPropertyDescriptor(d.prototype,"replaceWith"),d.prototype),P(d.prototype,"transitionTo",[n.action],Object.getOwnPropertyDescriptor(d.prototype,"transitionTo"),d.prototype),d) +e.default=w})),define("consul-ui/routing/single",["exports","consul-ui/routing/route","@ember/debug","rsvp"],(function(e,t,n,l){function r(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function i(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var o=t.default.extend({isCreate:function(e,t){return"create"===t.targetName.split(".").pop()},model:function(e,t){const n=this.repo,o=this.modelFor("dc").dc.Name,a=this.optionalParams().nspace,u=this.optionalParams().partition,s=this.isCreate(...arguments) +return(0,l.hash)(function(e){for(var t=1;te.ID,Name:e=>e.Name}})) +define("consul-ui/search/predicates/auth-method",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={Name:e=>e.Name,DisplayName:e=>e.DisplayName}})),define("consul-ui/search/predicates/health-check",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var t={Name:e=>e.Name,Node:e=>e.Node,Service:e=>e.ServiceName,CheckID:e=>e.CheckID||"",ID:e=>e.Service.ID||"",Notes:e=>e.Notes,Output:e=>e.Output,ServiceTags:e=>{return t=e.ServiceTags,Array.isArray(t)?t:t.toArray() +var t}} +e.default=t})),define("consul-ui/search/predicates/intention",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const t="All Services (*)" +var n={SourceName:e=>[e.SourceName,"*"===e.SourceName?t:void 0].filter(Boolean),DestinationName:e=>[e.DestinationName,"*"===e.DestinationName?t:void 0].filter(Boolean)} +e.default=n})),define("consul-ui/search/predicates/kv",["exports","consul-ui/utils/right-trim"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n={Key:e=>(0,t.default)(e.Key.toLowerCase()).split("/").filter((e=>Boolean(e))).pop()} +e.default=n})),define("consul-ui/search/predicates/node",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var t={Node:e=>e.Node,Address:e=>e.Address,PeerName:e=>e.PeerName,Meta:e=>Object.entries(e.Meta||{}).reduce(((e,t)=>e.concat(t)),[])} +e.default=t})),define("consul-ui/search/predicates/nspace",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={Name:e=>e.Name,Description:e=>e.Description,Role:e=>((e.ACLs||{}).RoleDefaults||[]).map((e=>e.Name)),Policy:e=>((e.ACLs||{}).PolicyDefaults||[]).map((e=>e.Name))}})),define("consul-ui/search/predicates/peer",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={Name:e=>e.Name,ID:e=>e.ID}})),define("consul-ui/search/predicates/policy",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={Name:e=>e.Name,Description:e=>e.Description}})),define("consul-ui/search/predicates/role",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={Name:e=>e.Name,Description:e=>e.Description,Policy:e=>(e.Policies||[]).map((e=>e.Name)).concat((e.ServiceIdentities||[]).map((e=>e.ServiceName))).concat((e.NodeIdentities||[]).map((e=>e.NodeName)))}})),define("consul-ui/search/predicates/service-instance",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var t={Name:e=>e.Name,Node:e=>e.Node.Node,Tags:e=>e.Service.Tags||[],ID:e=>e.Service.ID||"",Address:e=>e.Address||"",Port:e=>(e.Service.Port||"").toString(),"Service.Meta":e=>Object.entries(e.Service.Meta||{}).reduce(((e,t)=>e.concat(t)),[]),"Node.Meta":e=>Object.entries(e.Node.Meta||{}).reduce(((e,t)=>e.concat(t)),[])} +e.default=t})),define("consul-ui/search/predicates/service",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={Name:e=>e.Name,Tags:e=>e.Tags||[],PeerName:e=>e.PeerName,Partition:e=>e.Partition}})),define("consul-ui/search/predicates/token",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={Name:e=>e.Name,Description:e=>e.Description,AccessorID:e=>e.AccessorID,Role:e=>(e.Roles||[]).map((e=>e.Name)),Policy:e=>(e.Policies||[]).map((e=>e.Name)).concat((e.ServiceIdentities||[]).map((e=>e.ServiceName))).concat((e.NodeIdentities||[]).map((e=>e.NodeName)))}})),define("consul-ui/search/predicates/upstream-instance",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={DestinationName:(e,t)=>e.DestinationName,LocalBindAddress:(e,t)=>e.LocalBindAddress,LocalBindPort:(e,t)=>e.LocalBindPort.toString()}})),define("consul-ui/serializers/-default",["exports","@ember-data/serializer/json"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/serializers/-json-api",["exports","@ember-data/serializer/json-api"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/serializers/-rest",["exports","@ember-data/serializer/rest"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/serializers/application",["exports","consul-ui/serializers/http","@ember/object","consul-ui/utils/http/consul","consul-ui/utils/http/headers","consul-ui/models/dc","consul-ui/models/nspace","consul-ui/models/partition","consul-ui/utils/create-fingerprinter"],(function(e,t,n,l,r,i,o,a,u){function s(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const c=function(e,t){const n={} +return Object.keys(e).forEach((function(t){n[t.toLowerCase()]=e[t]})),t[l.HEADERS_SYMBOL]=n,t} +class d extends t.default{constructor(){super(...arguments),s(this,"attachHeaders",c),s(this,"fingerprint",(0,u.default)(i.FOREIGN_KEY,o.NSPACE_KEY,a.PARTITION_KEY))}respondForQuery(e,t){return e(((e,n)=>{return c(e,(r=n,i=this.fingerprint(this.primaryKey,this.slugKey,t.dc,e[l.HEADERS_NAMESPACE],e[l.HEADERS_PARTITION]),Array.isArray(r)?r.map(i):[r].map(i)[0]),t) +var r,i}))}respondForQueryRecord(e,t){return e(((e,n)=>c(e,this.fingerprint(this.primaryKey,this.slugKey,t.dc,e[l.HEADERS_NAMESPACE],e[l.HEADERS_PARTITION])(n),t)))}respondForCreateRecord(e,t,n){const r=this.slugKey,o=this.primaryKey +return e(((e,t)=>(!0===t&&(t=n),this.fingerprint(o,r,n[i.FOREIGN_KEY],e[l.HEADERS_NAMESPACE],n.Partition)(t))))}respondForUpdateRecord(e,t,n){const r=this.slugKey,o=this.primaryKey +return e(((e,t)=>(!0===t&&(t=n),this.fingerprint(o,r,n[i.FOREIGN_KEY],e[l.HEADERS_NAMESPACE],e[l.HEADERS_PARTITION])(t))))}respondForDeleteRecord(e,t,n){const r=this.slugKey,u=this.primaryKey +return e(((e,t)=>({[u]:this.fingerprint(u,r,n[i.FOREIGN_KEY],e[l.HEADERS_NAMESPACE],e[l.HEADERS_PARTITION])({[r]:n[r],[o.NSPACE_KEY]:n[o.NSPACE_KEY],[a.PARTITION_KEY]:n[a.PARTITION_KEY]})[u]})))}normalizeResponse(e,t,n,l,r){const i=this.normalizePayload(n,l,r),o=this.normalizeMeta(e,t,i,l,r) +"node"===t.modelName&&"query"===r&&(o.versions=this.getDistinctConsulVersions(i)),"query"!==r&&(i.meta=o) +const a=super.normalizeResponse(e,t,{meta:o,[t.modelName]:i},l,r) +return void 0===a?n:a}timestamp(){return(new Date).getTime()}normalizeMeta(e,t,i,o,a){const u=i[l.HEADERS_SYMBOL]||{} +delete i[l.HEADERS_SYMBOL] +const s={cacheControl:u[r.CACHE_CONTROL.toLowerCase()],cursor:u[l.HEADERS_INDEX.toLowerCase()],dc:u[l.HEADERS_DATACENTER.toLowerCase()],nspace:u[l.HEADERS_NAMESPACE.toLowerCase()],partition:u[l.HEADERS_PARTITION.toLowerCase()]} +return void 0!==u["x-range"]&&(s.range=u["x-range"]),void 0!==u.refresh&&(s.interval=1e3*u.refresh),"query"===a&&(s.date=this.timestamp(),i.forEach((function(e){(0,n.set)(e,"SyncTime",s.date)}))),s}normalizePayload(e,t,n){return e}getDistinctConsulVersions(e){let t=new Set +e.forEach((function(e){if(e.Meta&&e.Meta["consul-version"]){const n=e.Meta["consul-version"].split(".") +t.add(n[0]+"."+n[1])}})) +const n=Array.from(t) +return n.sort(((e,t)=>{const n=e.split(".").map((e=>{const t=Number(e) +return isNaN(t)?0:t})),l=t.split(".").map((e=>{const t=Number(e) +return isNaN(t)?0:t})),r=Math.min(n.length,l.length) +for(let i=0;it))}respondForQueryRecord(e,t){return e(((e,t)=>t))}respondForFindAll(e,t){return e(((e,t)=>t))}respondForCreateRecord(e,t){return e(((e,t)=>t))}respondForUpdateRecord(e,t){return e(((e,t)=>t))}respondForDeleteRecord(e,t){return e(((e,t)=>t))}}e.default=n})),define("consul-ui/serializers/intention",["exports","consul-ui/serializers/application","@ember/service","@ember/object","consul-ui/models/intention"],(function(e,t,n,l,r){var i,o,a +function u(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let s=(i=(0,n.inject)("encoder"),o=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="encoder",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),u(this,"primaryKey",r.PRIMARY_KEY),u(this,"slugKey",r.SLUG_KEY)}init(){super.init(...arguments),this.uri=this.encoder.uriTag()}ensureID(e){return(0,l.get)(e,"ID.length")?(e.Legacy=!0,e.LegacyID=e.ID):e.Legacy=!1,e.SourcePeer?e.ID=this.uri`peer:${e.SourcePeer}:${e.SourceNS}:${e.SourceName}:${e.DestinationPartition}:${e.DestinationNS}:${e.DestinationName}`:e.ID=this.uri`${e.SourcePartition}:${e.SourceNS}:${e.SourceName}:${e.DestinationPartition}:${e.DestinationNS}:${e.DestinationName}`,e}respondForQuery(e,t){return super.respondForQuery((t=>e(((e,n)=>t(e,n.map((e=>this.ensureID(e))))))),t)}respondForQueryRecord(e,t){return super.respondForQueryRecord((t=>e(((e,n)=>(n=this.ensureID(n),t(e,n))))),t)}respondForCreateRecord(e,t,n){const l=this.slugKey,r=this.primaryKey +return e(((e,i)=>((i=n).ID=this.uri`${t.SourcePartition}:${t.SourceNS}:${t.SourceName}:${t.DestinationPartition}:${t.DestinationNS}:${t.DestinationName}`,this.fingerprint(r,l,i.Datacenter)(i))))}respondForUpdateRecord(e,t,n){const l=this.slugKey,r=this.primaryKey +return e(((e,i)=>((i=n).LegacyID=i.ID,i.ID=t.ID,this.fingerprint(r,l,i.Datacenter)(i))))}},c=o.prototype,d="encoder",p=[i],f={configurable:!0,enumerable:!0,writable:!0,initializer:null},h={},Object.keys(f).forEach((function(e){h[e]=f[e]})),h.enumerable=!!h.enumerable,h.configurable=!!h.configurable,("value"in h||h.initializer)&&(h.writable=!0),h=p.slice().reverse().reduce((function(e,t){return t(c,d,e)||e}),h),m&&void 0!==h.initializer&&(h.value=h.initializer?h.initializer.call(m):void 0,h.initializer=void 0),void 0===h.initializer&&(Object.defineProperty(c,d,h),h=null),a=h,o) +var c,d,p,f,m,h +e.default=s})),define("consul-ui/serializers/kv",["exports","consul-ui/serializers/application","@ember/service","consul-ui/models/kv"],(function(e,t,n,l){var r,i,o +function a(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let u=(r=(0,n.inject)("atob"),i=class extends t.default{constructor(){var e,t,n,r +super(...arguments),e=this,t="decoder",r=this,(n=o)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(r):void 0}),a(this,"primaryKey",l.PRIMARY_KEY),a(this,"slugKey",l.SLUG_KEY)}serialize(e,t){const n=e.attr("Value") +return"string"==typeof n?this.decoder.execute(n):null}respondForQueryRecord(e,t){return super.respondForQueryRecord((t=>e(((e,n)=>(void 0===n[0].Session&&(n[0].Session=""),t(e,n[0]))))),t)}respondForQuery(e,t){return super.respondForQuery((t=>e(((e,n)=>t(e,n.map((e=>({[this.slugKey]:e}))))))),t)}},s=i.prototype,c="decoder",d=[r],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),o=m,i) +var s,c,d,p,f,m +e.default=u})),define("consul-ui/serializers/node",["exports","consul-ui/serializers/application","@ember-data/serializer/rest","consul-ui/models/node","@ember/string"],(function(e,t,n,l,r){function i(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=function(e){return""===e[l.SLUG_KEY]&&(e[l.SLUG_KEY]=e.Node),e} +class a extends(t.default.extend(n.EmbeddedRecordsMixin)){constructor(){super(...arguments),i(this,"primaryKey",l.PRIMARY_KEY),i(this,"slugKey",l.SLUG_KEY),i(this,"attrs",{Services:{embedded:"always"}})}transformHasManyResponse(e,t,n){let l,r={} +return"Services"===t.key?((n.Checks||[]).filter((e=>""!==e.ServiceID)).forEach((e=>{void 0===r[e.ServiceID]&&(r[e.ServiceID]=[]),r[e.ServiceID].push(e)})),""===n.PeerName&&(n.PeerName=void 0),l=this.store.serializerFor(t.type),n.Services=n.Services.map((e=>l.transformHasManyResponseFromNode(n,e,r))),n):super.transformHasManyResponse(...arguments)}respondForQuery(e,t,n,l){const i=super.respondForQuery((t=>e(((e,n)=>t(e,n.map(o))))),t) +return l.eachRelationship(((e,t)=>{i.forEach((e=>this[`transform${(0,r.classify)(t.kind)}Response`](this.store,t,e,i)))})),i}respondForQueryRecord(e,t,n,l){const i=super.respondForQueryRecord((t=>e(((e,n)=>t(e,o(n))))),t) +return l.eachRelationship(((e,t)=>{this[`transform${(0,r.classify)(t.kind)}Response`](this.store,t,i)})),i}respondForQueryLeader(e,t){return e(((e,n)=>{const l=n.split(":"),r=l.pop(),i=l.join(":") +return this.attachHeaders(e,{Address:i,Port:r},t)}))}}e.default=a})),define("consul-ui/serializers/nspace",["exports","consul-ui/serializers/application","@ember/object","consul-ui/models/nspace"],(function(e,t,n,l){function r(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const i=e=>((0,n.get)(e,"ACLs.PolicyDefaults")&&(e.ACLs.PolicyDefaults=e.ACLs.PolicyDefaults.map((function(e){return void 0===e.template&&(e.template=""),e}))),["PolicyDefaults","RoleDefaults"].forEach((function(t){void 0===e.ACLs&&(e.ACLs=[]),void 0===e.ACLs[t]&&(e.ACLs[t]=[])})),e) +class o extends t.default{constructor(){super(...arguments),r(this,"primaryKey",l.PRIMARY_KEY),r(this,"slugKey",l.SLUG_KEY)}respondForQuery(e,t,n,l){return super.respondForQuery((n=>e(((e,l)=>n(e,l.map((function(e){return e.Namespace="*",e.Datacenter=t.dc,i(e)})))))),t)}respondForQueryRecord(e,t,n){return super.respondForQuery((n=>e(((e,l)=>(l.Datacenter=t.dc,l.Namespace="*",n(e,i(l)))))),t,n)}respondForCreateRecord(e,t,n){return super.respondForCreateRecord((n=>e(((e,l)=>(l.Datacenter=t.dc,l.Namespace="*",n(e,i(l)))))),t,n)}respondForUpdateRecord(e,t,n){return e(((e,t)=>i(t)))}}e.default=o})),define("consul-ui/serializers/oidc-provider",["exports","consul-ui/serializers/application","consul-ui/models/oidc-provider"],(function(e,t,n){function l(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function r(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class i extends t.default{constructor(){super(...arguments),r(this,"primaryKey",n.PRIMARY_KEY),r(this,"slugKey",n.SLUG_KEY)}respondForAuthorize(e,t,n){return e(((e,t)=>this.attachHeaders(e,t,n)))}respondForQueryRecord(e,t){return super.respondForQueryRecord((n=>e(((e,i)=>n(e,function(e){for(var t=1;te(((e,n)=>t(e,n.map((e=>(e.Partition="*",e.Namespace="*",e))))))),t)}}e.default=r})),define("consul-ui/serializers/permission",["exports","consul-ui/serializers/application"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{}e.default=n})),define("consul-ui/serializers/policy",["exports","consul-ui/serializers/application","consul-ui/models/policy"],(function(e,t,n){function l(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class r extends t.default{constructor(){super(...arguments),l(this,"primaryKey",n.PRIMARY_KEY),l(this,"slugKey",n.SLUG_KEY)}}e.default=r})) +define("consul-ui/serializers/proxy",["exports","consul-ui/serializers/application","consul-ui/models/proxy"],(function(e,t,n){function l(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class r extends t.default{constructor(){super(...arguments),l(this,"primaryKey",n.PRIMARY_KEY),l(this,"slugKey",n.SLUG_KEY),l(this,"attrs",{NodeName:"Node"})}}e.default=r})),define("consul-ui/serializers/role",["exports","consul-ui/serializers/application","consul-ui/models/role","consul-ui/mixins/policy/as-many"],(function(e,t,n,l){function r(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class i extends(t.default.extend(l.default)){constructor(){super(...arguments),r(this,"primaryKey",n.PRIMARY_KEY),r(this,"slugKey",n.SLUG_KEY)}}e.default=i})),define("consul-ui/serializers/service-instance",["exports","consul-ui/serializers/application","consul-ui/models/service-instance"],(function(e,t,n){function l(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function r(e){for(var t=1;t{switch(t.Status){case"passing":e.ChecksPassing.push(t) +break +case"warning":e.ChecksWarning.push(t) +break +case"critical":e.ChecksCritical.push(t)}return e}),{ChecksPassing:[],ChecksWarning:[],ChecksCritical:[]}),o=r(r({},i),{},{Service:t,Checks:l,Node:{Datacenter:e.Datacenter,Namespace:e.Namespace,Partition:e.Partition,ID:e.ID,Node:e.Node,Address:e.Address,TaggedAddresses:e.TaggedAddresses,Meta:e.Meta}}) +return o.uid=this.extractUid(o),o}respondForQuery(e,t){return super.respondForQuery((n=>e(((e,l)=>{if(0===l.length){const e=new Error +throw e.errors=[{status:"404",title:"Not found"}],e}return l.forEach((e=>{e.Datacenter=t.dc,e.Namespace=t.ns||"default",e.Partition=t.partition||"default",e.uid=this.extractUid(e)})),n(e,l)}))),t)}respondForQueryRecord(e,t){return super.respondForQueryRecord((n=>e(((e,l)=>{if(l.forEach((e=>{e.Datacenter=t.dc,e.Namespace=t.ns||"default",e.Partition=t.partition||"default",e.uid=this.extractUid(e)})),void 0===(l=l.find((function(e){return e.Node.Node===t.node&&e.Service.ID===t.serviceId})))){const e=new Error +throw e.errors=[{status:"404",title:"Not found"}],e}return l.Namespace=l.Service.Namespace,l.Partition=l.Service.Partition,n(e,l)}))),t)}}e.default=o})),define("consul-ui/serializers/service",["exports","consul-ui/serializers/application","consul-ui/models/service","@ember/object","consul-ui/utils/http/consul"],(function(e,t,n,l,r){function i(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class o extends t.default{constructor(){super(...arguments),i(this,"primaryKey",n.PRIMARY_KEY),i(this,"slugKey",n.SLUG_KEY)}respondForQuery(e,t){return super.respondForQuery((t=>e(((e,n)=>t(e,this._transformServicesPayload(n))))),t)}respondForQueryRecord(e,t){return super.respondForQueryRecord((n=>e(((e,r)=>n(e,{Name:t.id,Namespace:(0,l.get)(r,"firstObject.Service.Namespace"),Nodes:r})))),t)}createJSONApiDocumentFromServicesPayload(e,t,n){const{primaryKey:l,slugKey:i,fingerprint:o}=this +return{data:this._transformServicesPayload(t).map(o(l,i,n,e[r.HEADERS_NAMESPACE],e[r.HEADERS_PARTITION])).map((e=>({id:e.uid,type:"service",attributes:e})))}}_transformServicesPayload(e){const t={} +return e.filter((function(e){return"connect-proxy"!==e.Kind})).forEach((e=>{t[e.Name]=e})),e.filter((function(e){return"connect-proxy"===e.Kind})).forEach((e=>{e.ProxyFor&&e.ProxyFor.forEach((n=>{void 0!==t[n]&&(t[n].Proxy=e)}))})),e}}e.default=o})),define("consul-ui/serializers/session",["exports","consul-ui/serializers/application","consul-ui/models/session"],(function(e,t,n){function l(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class r extends t.default{constructor(){super(...arguments),l(this,"primaryKey",n.PRIMARY_KEY),l(this,"slugKey",n.SLUG_KEY)}respondForQueryRecord(e,t){return super.respondForQueryRecord((t=>e(((e,n)=>{if(0===n.length){const e=new Error +throw e.errors=[{status:"404",title:"Not found"}],e}return t(e,n[0])}))),t)}}e.default=r})),define("consul-ui/serializers/token",["exports","consul-ui/serializers/application","@ember/object","consul-ui/models/token","consul-ui/mixins/policy/as-many","consul-ui/mixins/role/as-many"],(function(e,t,n,l,r,i){function o(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class a extends(t.default.extend(r.default,i.default)){constructor(){super(...arguments),o(this,"primaryKey",l.PRIMARY_KEY),o(this,"slugKey",l.SLUG_KEY)}serialize(e,t){let n=super.serialize(...arguments) +return null!==n.Rules&&(n={ID:n.SecretID,Name:n.Description,Type:n.Type,Rules:n.Rules}),n&&delete n.SecretID,n}respondForSelf(e,t){return this.respondForQueryRecord(e,t)}respondForUpdateRecord(e,t,l){return super.respondForUpdateRecord((t=>e(((e,l)=>{if(void 0!==l.Policies&&null!==l.Policies||(l.Policies=[]),void 0!==l.ID){const e=this.store.peekAll("token").findBy("SecretID",l.ID) +e&&(l.SecretID=l.ID,l.AccessorID=(0,n.get)(e,"AccessorID"))}return t(e,l)}))),t,l)}}e.default=a})),define("consul-ui/serializers/topology",["exports","consul-ui/serializers/application","consul-ui/models/topology","@ember/service"],(function(e,t,n,l){var r,i,o +function a(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function u(e){for(var t=1;t{e.Intention.SourceName=e.Name,e.Intention.SourceNS=e.Namespace,e.Intention.DestinationName=t.id,e.Intention.DestinationNS=t.ns||"default",l.ensureID(e.Intention)})),i.Upstreams.forEach((e=>{e.Intention.SourceName=t.id,e.Intention.SourceNS=t.ns||"default",e.Intention.DestinationName=e.Name,e.Intention.DestinationNS=e.Namespace,l.ensureID(e.Intention)})),r(e,u(u({},i),{},{[n.SLUG_KEY]:t.id}))}))}),t)}},d=i.prototype,p="store",f=[r],m={configurable:!0,enumerable:!0,writable:!0,initializer:null},b={},Object.keys(m).forEach((function(e){b[e]=m[e]})),b.enumerable=!!b.enumerable,b.configurable=!!b.configurable,("value"in b||b.initializer)&&(b.writable=!0),b=f.slice().reverse().reduce((function(e,t){return t(d,p,e)||e}),b),h&&void 0!==b.initializer&&(b.value=b.initializer?b.initializer.call(h):void 0,b.initializer=void 0),void 0===b.initializer&&(Object.defineProperty(d,p,b),b=null),o=b,i) +var d,p,f,m,h,b +e.default=c})),define("consul-ui/services/-ensure-registered",["exports","@embroider/util/services/ensure-registered"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/-portal",["exports","ember-stargate/services/-portal"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/abilities",["exports","ember-can/services/can"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{parse(e){return super.parse(e.replace("use SSO","use authMethods").replace("service","zervice"))}}e.default=n})),define("consul-ui/services/atob",["exports","@ember/service","consul-ui/utils/atob"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{execute(){return(0,n.default)(...arguments)}}e.default=l})),define("consul-ui/services/auth-providers/oauth2-code-with-url-provider",["exports","torii/providers/oauth2-code","@ember/debug"],(function(e,t,n){function l(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class r extends t.default{constructor(){super(...arguments),l(this,"name","oidc-with-url")}buildUrl(){return this.baseUrl}open(e){const t=this.name,l=this.buildUrl() +return this.popup.open(l,["state","code"],e).then((function(e){const l={authorizationState:e.state,authorizationCode:decodeURIComponent(e.code),provider:t} +return(0,n.runInDebug)((e=>console.info("Retrieved the following creds from the OAuth Provider",l))),l}))}close(){const e=this.get("popup.remote")||{} +if("function"==typeof e.close)return e.close()}}e.default=r})),define("consul-ui/services/btoa",["exports","@ember/service","consul-ui/utils/btoa"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{execute(){return(0,n.default)(...arguments)}}e.default=l})),define("consul-ui/services/can",["exports","ember-can/services/abilities"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/change",["exports","@ember/service","ember-changeset-validations","ember-changeset","consul-ui/utils/form/changeset","consul-ui/validations/intention-permission","consul-ui/validations/intention-permission-http-header"],(function(e,t,n,l,r,i,o){var a,u,s +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const c={"intention-permission":i.default,"intention-permission-http-header":o.default} +let d=(a=(0,t.inject)("schema"),u=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="schema",l=this,(n=s)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}init(){super.init(...arguments),this._validators=new Map}willDestroy(){this._validators=null}changesetFor(e,t){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{} +const o=this.validatorFor(e,i) +let a +if(o){let e=o +"function"!=typeof o&&(e=(0,n.default)(o)),a=(0,l.Changeset)(t,e,o,{changeset:r.default})}else a=(0,l.Changeset)(t) +return a}validatorFor(e){if(!this._validators.has(e)){const t=c[e] +let n +void 0!==t&&(n=t(this.schema)),this._validators.set(e,n)}return this._validators.get(e)}},p=u.prototype,f="schema",m=[a],h={configurable:!0,enumerable:!0,writable:!0,initializer:null},y={},Object.keys(h).forEach((function(e){y[e]=h[e]})),y.enumerable=!!y.enumerable,y.configurable=!!y.configurable,("value"in y||y.initializer)&&(y.writable=!0),y=m.slice().reverse().reduce((function(e,t){return t(p,f,e)||e}),y),b&&void 0!==y.initializer&&(y.value=y.initializer?y.initializer.call(b):void 0,y.initializer=void 0),void 0===y.initializer&&(Object.defineProperty(p,f,y),y=null),s=y,u) +var p,f,m,h,b,y +e.default=d})),define("consul-ui/services/client/connections",["exports","@ember/service"],(function(e,t){var n,l,r,i,o,a,u +function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let d=(n=(0,t.inject)("dom"),l=(0,t.inject)("env"),r=(0,t.inject)("data-source/service"),i=class extends t.default{constructor(){super(...arguments),s(this,"dom",o,this),s(this,"env",a,this),s(this,"data",u,this)}init(){super.init(...arguments),this._listeners=this.dom.listeners(),this.connections=new Set,this.addVisibilityChange()}willDestroy(){this._listeners.remove(),this.purge(),super.willDestroy(...arguments)}addVisibilityChange(){this._listeners.add(this.dom.document(),{visibilitychange:e=>{e.target.hidden&&this.purge(-1)}})}whenAvailable(e){const t=this.dom.document() +return t.hidden?new Promise((n=>{const l=this._listeners.add(t,{visibilitychange:function(t){l(),n(e)}})})):Promise.resolve(e)}purge(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;[...this.connections].forEach((function(t){t.abort(e)})),this.connections=new Set}acquire(e){if(this.connections.size>=this.env.var("CONSUL_HTTP_MAX_CONNECTIONS")){const t=this.data.closed() +let n=[...this.connections].find((e=>!!e.headers()["x-request-id"]&&t.includes(e.headers()["x-request-id"]))) +void 0===n&&"text/event-stream"===e.headers()["content-type"]&&(n=this.connections.values().next().value),void 0!==n&&(this.release(n),n.abort(429))}this.connections.add(e)}release(e){this.connections.delete(e)}},o=c(i.prototype,"dom",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=c(i.prototype,"env",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(i.prototype,"data",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) +e.default=d})),define("consul-ui/services/client/http",["exports","@ember/service","@ember/object","@ember/runloop","consul-ui/utils/http/headers","consul-ui/utils/http/consul","consul-ui/utils/http/create-url","consul-ui/utils/http/create-headers","consul-ui/utils/http/create-query-params"],(function(e,t,n,l,r,i,o,a,u){var s,c,d,p,f,m,h,b,y,v,g,O,P,w,x +function j(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function _(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}function S(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function k(e){for(var t=1;tC.stringify(this.sanitize(e)))) +const e=this.encoder.uriTag() +this.cache=(t,n)=>(t.uri=n(e),t.SyncTime=(new Date).getTime(),this.store.push({data:{id:t.uri,type:new URL(t.uri).protocol.slice(0,-1),attributes:t}}))}sanitize(e){return this.env.var("CONSUL_NSPACES_ENABLED")&&void 0!==e.ns&&null!==e.ns&&""!==e.ns||delete e.ns,this.env.var("CONSUL_PARTITIONS_ENABLED")&&void 0!==e.partition&&null!==e.partition&&""!==e.partition||delete e.partition,e}willDestroy(){this._listeners.remove(),super.willDestroy(...arguments)}url(){return this.parseURL(...arguments)}body(){const e=function(e){let t={} +const n=e.reduce((function(e,t,n){return-1!==(t=t.split("\n").map((e=>e.trim())).join("\n")).indexOf("\n\n")?n:e}),-1) +for(var l=arguments.length,r=new Array(l>1?l-1:0),i=1;i1?t-1:0),l=1;l0||Object.keys(d.data).length>0)&&(d.body=d.data) +else{const e=C.stringify(d.data) +e.length>0&&(-1!==d.url.indexOf("?")?d.url=`${d.url}&${e}`:d.url=`${d.url}?${e}`)}return d.headers[r.CONTENT_TYPE]="application/json; charset=utf-8",d.url=`${this.env.var("CONSUL_API_PREFIX")}${d.url}`,d}fetchWithToken(e,t){return this.settings.findBySlug("token").then((n=>fetch(`${this.env.var("CONSUL_API_PREFIX")}${e}`,k(k({},t),{},{credentials:"include",headers:k({"X-Consul-Token":void 0===n.SecretID?"":n.SecretID},t.headers)}))))}request(e){const t=this,n=this.cache +return e((function(e){for(var r=arguments.length,o=new Array(r>1?r-1:0),a=1;a{const r=k(k({},u),{},{headers:k({[i.HEADERS_TOKEN]:void 0===e.SecretID?"":e.SecretID},u.headers)}),o=t.transport.request(r) +return new Promise(((r,a)=>{const s=t._listeners.add(o,{open:e=>{t.acquire(e.target)},message:t=>{const o=k(k(k({},Object.entries(t.data.headers).reduce((function(e,t,n){let[l,r]=t +return M.includes(l)||(e[l]=r),e}),{})),u.clientHeaders),{},{[i.HEADERS_DATACENTER]:u.data.dc,[i.HEADERS_NAMESPACE]:u.data.ns||e.Namespace||"default",[i.HEADERS_PARTITION]:u.data.partition||e.Partition||"default"}),a=function(e){let l=e(o,t.data.response,n) +const r=l.meta||{} +return 2===r.version&&(Array.isArray(l.body)?l=new Proxy(l.body,{get:(e,t)=>"meta"===t?r:e[t]}):(l=l.body,l.meta=r)),l};(0,l.next)((()=>r(a)))},error:e=>{(0,l.next)((()=>a(e.error)))},close:e=>{t.release(e.target),s()}}) +o.fetch()}))}))}))}whenAvailable(e){return this.connections.whenAvailable(e)}abort(){return this.connections.purge(...arguments)}acquire(){return this.connections.acquire(...arguments)}release(){return this.connections.release(...arguments)}},y=_(b.prototype,"dom",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=_(b.prototype,"env",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=_(b.prototype,"connections",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=_(b.prototype,"transport",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=_(b.prototype,"settings",[f],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),w=_(b.prototype,"encoder",[m],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x=_(b.prototype,"store",[h],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b) +e.default=D})),define("consul-ui/services/client/transports/xhr",["exports","@ember/service","consul-ui/utils/http/create-headers","consul-ui/utils/http/xhr","consul-ui/utils/http/request","consul-ui/utils/http/error"],(function(e,t,n,l,r,i){function o(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function a(e){for(var t=1;t(this.xhr(n),t),t}}e.default=c})),define("consul-ui/services/clipboard/local-storage",["exports","@ember/service","clipboard"],(function(e,t,n){var l,r,i +function o(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class a extends n.default{constructor(e,t,n){super(e,t),this._cb=n}onClick(e){this._cb(this.text(e.delegateTarget||e.currentTarget)),this.emit("success",{})}}let u=(l=(0,t.inject)("-document"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="doc",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),o(this,"key","clipboard")}execute(e,t){return new a(e,t,(e=>{this.doc.defaultView.localStorage.setItem(this.key,e)}))}},s=r.prototype,c="doc",d=[l],p={configurable:!0,enumerable:!0,writable:!0,initializer:null},m={},Object.keys(p).forEach((function(e){m[e]=p[e]})),m.enumerable=!!m.enumerable,m.configurable=!!m.configurable,("value"in m||m.initializer)&&(m.writable=!0),m=d.slice().reverse().reduce((function(e,t){return t(s,c,e)||e}),m),f&&void 0!==m.initializer&&(m.value=m.initializer?m.initializer.call(f):void 0,m.initializer=void 0),void 0===m.initializer&&(Object.defineProperty(s,c,m),m=null),i=m,r) +var s,c,d,p,f,m +e.default=u})),define("consul-ui/services/clipboard/os",["exports","@ember/service","clipboard"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{execute(){return new n.default(...arguments)}}e.default=l})),define("consul-ui/services/code-mirror",["exports","ivy-codemirror/services/code-mirror"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/code-mirror/linter",["exports","@ember/service","consul-ui/utils/editor/lint"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const o=[{name:"JSON",mime:"application/json",mode:"javascript",ext:["json","map"],alias:["json5"]},{name:"HCL",mime:"text/x-ruby",mode:"ruby",ext:["rb"],alias:["jruby","macruby","rake","rb","rbx"]},{name:"YAML",mime:"text/x-yaml",mode:"yaml",ext:["yaml","yml"],alias:["yml"]},{name:"XML",mime:"application/xml",mode:"xml",htmlMode:!1,matchClosing:!0,alignCDATA:!1,ext:["xml"],alias:["xml"]}] +let a=(l=(0,t.inject)("dom"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="dom",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}modes(){return o}lint(){return(0,n.default)(...arguments)}getEditor(e){return this.dom.element("textarea + div",e).CodeMirror}},u=r.prototype,s="dom",c=[l],d={configurable:!0,enumerable:!0,writable:!0,initializer:null},f={},Object.keys(d).forEach((function(e){f[e]=d[e]})),f.enumerable=!!f.enumerable,f.configurable=!!f.configurable,("value"in f||f.initializer)&&(f.writable=!0),f=c.slice().reverse().reduce((function(e,t){return t(u,s,e)||e}),f),p&&void 0!==f.initializer&&(f.value=f.initializer?f.initializer.call(p):void 0,f.initializer=void 0),void 0===f.initializer&&(Object.defineProperty(u,s,f),f=null),i=f,r) +var u,s,c,d,p,f +e.default=a})),define("consul-ui/services/container",["exports","@ember/service"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{constructor(e){super(...arguments),this._owner=e,this._wm=new WeakMap}set(e,t){this._wm.set(t,e)}keyForClass(e){return this._wm.get(e)}get(e){return"string"!=typeof e&&(e=this.keyForClass(e)),this.lookup(e)}lookup(e){return this._owner.lookup(e)}resolveRegistration(e){return this._owner.resolveRegistration(e).prototype}}e.default=n})),define("consul-ui/services/data-sink/protocols/http",["exports","@ember/service","@ember/object"],(function(e,t,n){var l,r,i,o,a,u,s,c,d,p,f,m,h,b,y,v,g +function O(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function P(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let w=(l=(0,t.inject)("client/http"),r=(0,t.inject)("settings"),i=(0,t.inject)("repository/intention"),o=(0,t.inject)("repository/kv"),a=(0,t.inject)("repository/nspace"),u=(0,t.inject)("repository/partition"),s=(0,t.inject)("repository/peer"),c=(0,t.inject)("repository/session"),d=class extends t.default{constructor(){super(...arguments),O(this,"client",p,this),O(this,"settings",f,this),O(this,"intention",m,this),O(this,"kv",h,this),O(this,"nspace",b,this),O(this,"partition",y,this),O(this,"peer",v,this),O(this,"session",g,this)}prepare(e,t,l){return(0,n.setProperties)(l,t)}persist(e,t){const[,,,,n]=e.split("/"),l=this[n] +return this.client.request((e=>l.persist(t,e)))}remove(e,t){const[,,,,n]=e.split("/"),l=this[n] +return this.client.request((e=>l.remove(t,e)))}},p=P(d.prototype,"client",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=P(d.prototype,"settings",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=P(d.prototype,"intention",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=P(d.prototype,"kv",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b=P(d.prototype,"nspace",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=P(d.prototype,"partition",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=P(d.prototype,"peer",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=P(d.prototype,"session",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d) +e.default=w})),define("consul-ui/services/data-sink/protocols/local-storage",["exports","@ember/service","@ember/object"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,t.inject)("settings"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="settings",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}prepare(e,t){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{} +return null===t||""===t?l:(0,n.setProperties)(l,t)}persist(e,t){const n=e.split(":").pop() +return this.settings.persist({[n]:t})}remove(e,t){const n=e.split(":").pop() +return this.settings.delete(n)}},a=r.prototype,u="settings",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/services/data-sink/service",["exports","@ember/service"],(function(e,t){var n,l,r,i,o +function a(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function u(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const s=function(e){return-1===(e=e.toString()).indexOf("://")&&(e=`consul://${e}`),e.split("://")} +let c=(n=(0,t.inject)("data-sink/protocols/http"),l=(0,t.inject)("data-sink/protocols/local-storage"),r=class extends t.default{constructor(){super(...arguments),a(this,"consul",i,this),a(this,"settings",o,this)}prepare(e,t,n){const[l,r]=s(e) +return this[l].prepare(r,t,n)}persist(e,t){const[n,l]=s(e) +return this[n].persist(l,t)}remove(e,t){const[n,l]=s(e) +return this[n].remove(l,t)}},i=u(r.prototype,"consul",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o=u(r.prototype,"settings",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),r) +e.default=c})),define("consul-ui/services/data-source/protocols/http",["exports","@ember/service","@ember/application","consul-ui/decorators/data-source"],(function(e,t,n,l){var r,i,o,a,u +function s(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let d=(r=(0,t.inject)("client/http"),i=(0,t.inject)("data-source/protocols/http/blocking"),o=class extends t.default{constructor(){super(...arguments),s(this,"client",a,this),s(this,"type",u,this)}source(e,t){const r=(0,l.match)(e) +let i +return this.client.request((e=>{i=r.cb(r.params,(0,n.getOwner)(this),e)})),this.type.source(i,t)}},a=c(o.prototype,"client",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=c(o.prototype,"type",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) +e.default=d})),define("consul-ui/services/data-source/protocols/http/blocking",["exports","@ember/service","@ember/object","consul-ui/utils/dom/event-source","consul-ui/services/settings","consul-ui/services/client/http","consul-ui/utils/maybe-call"],(function(e,t,n,l,r,i,o){var a,u,s,c,d +function p(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function f(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let m=(a=(0,t.inject)("client/http"),u=(0,t.inject)("settings"),s=class extends t.default{constructor(){super(...arguments),p(this,"client",c,this),p(this,"settings",d,this)}source(e,t){return new l.BlockingEventSource(((t,l)=>{const a=l.close.bind(l) +return(0,o.default)((()=>t.cursor=void 0),(0,r.ifNotBlocking)(this.settings))().then((()=>e(t).then((0,o.default)(a,(0,r.ifNotBlocking)(this.settings))).then((function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{} +const t=(0,n.get)(e,"meta")||{} +return void 0===t.cursor&&void 0===t.interval&&a(),e})).catch((0,i.restartWhenAvailable)(this.client))))}),t)}},c=f(s.prototype,"client",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=f(s.prototype,"settings",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s) +e.default=m})),define("consul-ui/services/data-source/protocols/http/promise",["exports","@ember/service","consul-ui/utils/dom/event-source"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{source(e,t){return(0,n.once)(e,t)}}e.default=l})),define("consul-ui/services/data-source/protocols/local-storage",["exports","@ember/service","consul-ui/utils/dom/event-source"],(function(e,t,n){var l,r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(l=(0,t.inject)("settings"),r=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="repo",l=this,(n=i)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}source(e,t){const l=e.split(":").pop() +return new n.StorageEventSource((e=>this.repo.findBySlug(l)),{key:e,uri:t.uri})}},a=r.prototype,u="repo",s=[l],c={configurable:!0,enumerable:!0,writable:!0,initializer:null},p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i=p,r) +var a,u,s,c,d,p +e.default=o})) +define("consul-ui/services/data-source/service",["exports","@ember/service","@ember/debug","consul-ui/utils/dom/event-source","@ember/runloop","mnemonist/multi-map"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m +function h(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function b(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let y=null,v=null,g=null +class O{constructor(e){this.uri=e}toString(){return this.uri}}let P=(o=(0,t.inject)("dom"),a=(0,t.inject)("encoder"),u=(0,t.inject)("data-source/protocols/http"),s=(0,t.inject)("data-source/protocols/local-storage"),c=class extends t.default{constructor(){super(...arguments),h(this,"dom",d,this),h(this,"encoder",p,this),h(this,"consul",f,this),h(this,"settings",m,this)}init(){super.init(...arguments),y=new Map,v=new Map,g=new i.default(Set),this._listeners=this.dom.listeners()}resetCache(){y=new Map}willDestroy(){(0,r.schedule)("afterRender",(()=>{this._listeners.remove(),v.forEach((function(e){e.close()})),y=null,v=null,g.clear(),g=null}))}source(e,t){const n=e(this.encoder.uriTag()) +return new Promise(((e,t)=>{const r={},i=this.open(n,r,!0) +i.configuration.ref=r +const o=this._listeners.add(i,{message:t=>{o(),e((0,l.proxy)(t.target,t.data))},error:e=>{o(),this.close(i,r),t(e.error)}}) +void 0!==i.getCurrentEvent()&&i.dispatchEvent(i.getCurrentEvent())}))}unwrap(e,t){const n=e._source +return g.set(n,t),g.remove(n,n.configuration.ref),delete n.configuration.ref,n}uri(e){return new O(e)}open(e,t){let l,r=arguments.length>2&&void 0!==arguments[2]&&arguments[2] +if(!(e instanceof O)&&"string"!=typeof e)return this.unwrap(e,t);(0,n.runInDebug)((t=>{e instanceof O||console.error(new Error(`DataSource '${e}' does not use the uri helper. Please ensure you use the uri helper to ensure correct encoding`))})),-1===(e=e.toString()).indexOf("://")&&(e=`consul://${e}`) +let[i,o]=e.split("://") +const a=this[i] +if(v.has(e))l=v.get(e),v.delete(e),v.set(e,l) +else{let t={} +y.has(e)&&(t=y.get(e)),t.uri=e,l=a.source(o,t) +const n=this._listeners.add(l,{close:t=>{const l=t.target,r=l.getCurrentEvent(),i=l.configuration.cursor +void 0!==r&&void 0!==i&&t.errors&&"401"!==t.errors[0].status&&y.set(e,{currentEvent:r,cursor:i}),g.has(l)||v.delete(e),n()}}) +v.set(e,l)}return(!g.has(l)||l.readyState>1||r)&&l.open(),g.set(l,t),l}close(e,t){e&&(g.remove(e,t),g.has(e)||(e.close(),2===e.readyState&&v.delete(e.configuration.uri)))}closed(){return[...v.entries()].filter((e=>{let[t,n]=e +return n.readyState>1})).map((e=>e[0]))}},d=b(c.prototype,"dom",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=b(c.prototype,"encoder",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=b(c.prototype,"consul",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=b(c.prototype,"settings",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c) +e.default=P})),define("consul-ui/services/data-structs",["exports","@ember/service","ngraph.graph"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{graph(){return(0,n.default)()}}e.default=l})),define("consul-ui/services/dom",["exports","@ember/service","@ember/object/internals","consul-ui/utils/dom/qsa-factory","consul-ui/utils/dom/sibling","consul-ui/utils/dom/closest","consul-ui/utils/dom/is-outside","consul-ui/utils/dom/get-component-factory","consul-ui/utils/dom/normalize-event","consul-ui/utils/dom/create-listeners","consul-ui/utils/dom/click-first-anchor"],(function(e,t,n,l,r,i,o,a,u,s,c){var d,p,f +function m(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const h=(0,l.default)() +let b,y +const v=(0,c.default)(i.default) +let g=(d=(0,t.inject)("-document"),p=class extends t.default{constructor(e){var t,n,l,c +super(...arguments),t=this,n="doc",c=this,(l=f)&&Object.defineProperty(t,n,{enumerable:l.enumerable,configurable:l.configurable,writable:l.writable,value:l.initializer?l.initializer.call(c):void 0}),m(this,"clickFirstAnchor",v),m(this,"closest",i.default),m(this,"sibling",r.default),m(this,"isOutside",o.default),m(this,"normalizeEvent",u.default),m(this,"listeners",s.default),y=new WeakMap,b=(0,a.default)(e)}willDestroy(){super.willDestroy(...arguments),y=null,b=null}document(){return this.doc}viewport(){return this.doc.defaultView}guid(e){return(0,n.guidFor)(e)}focus(e){if("string"==typeof e&&(e=this.element(e)),void 0!==e){let t=e.getAttribute("tabindex") +e.setAttribute("tabindex","0"),e.focus(),null===t?e.removeAttribute("tabindex"):e.setAttribute("tabindex",t)}}setEventTargetProperty(e,t,n){const l=e.target +return new Proxy(e,{get:function(r,i,o){return"target"===i?new Proxy(l,{get:function(r,i,o){return i===t?n(e.target[t]):l[i]}}):Reflect.get(...arguments)}})}setEventTargetProperties(e,t){const n=e.target +return new Proxy(e,{get:function(l,r,i){return"target"===r?new Proxy(n,{get:function(l,r,i){return void 0!==t[r]?t[r](e.target):n[r]}}):Reflect.get(...arguments)}})}root(){return this.doc.documentElement}elementById(e){return this.doc.getElementById(e)}elementsByTagName(e,t){return(t=void 0===t?this.doc:t).getElementsByTagName(e)}elements(e,t){return h(e,t)}element(e,t){return"#"===e.substr(0,1)?this.elementById(e.substr(1)):[...h(e,t)][0]}component(e,t){return b("string"!=typeof e?e:this.element(e,t))}components(e,t){return[...this.elements(e,t)].map((function(e){return b(e)})).filter((function(e){return null!=e}))}isInViewport(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0 +y.set(e,t) +let l=new IntersectionObserver(((e,t)=>{e.map((e=>{const t=y.get(e.target) +"function"==typeof t&&t(e.isIntersecting)}))}),{rootMargin:"0px",threshold:n}) +return l.observe(e),()=>{l.unobserve(e),y&&y.delete(e),l.disconnect(),l=null}}},O=p.prototype,P="doc",w=[d],x={configurable:!0,enumerable:!0,writable:!0,initializer:null},_={},Object.keys(x).forEach((function(e){_[e]=x[e]})),_.enumerable=!!_.enumerable,_.configurable=!!_.configurable,("value"in _||_.initializer)&&(_.writable=!0),_=w.slice().reverse().reduce((function(e,t){return t(O,P,e)||e}),_),j&&void 0!==_.initializer&&(_.value=_.initializer?_.initializer.call(j):void 0,_.initializer=void 0),void 0===_.initializer&&(Object.defineProperty(O,P,_),_=null),f=_,p) +var O,P,w,x,j,_ +e.default=g})),define("consul-ui/services/encoder",["exports","@ember/service","@ember/object","@ember/debug","consul-ui/utils/atob","consul-ui/utils/btoa"],(function(e,t,n,l,r,i){function o(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class a extends t.default{constructor(){super(...arguments),o(this,"uriComponent",encodeURIComponent),o(this,"joiner",(function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"" +return(l,r)=>(r||Array(l.length).fill(t)).reduce(((t,r,i)=>`${t}${r}${e(l[i]||n)}`),"")}))}createRegExpEncoder(e,t){return function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:e=>e,r=!(arguments.length>2&&void 0!==arguments[2])||arguments[2] +return function(){let i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return""!==i?i.replace(e,((e,a)=>{const u=(0,n.get)(o,a) +return(0,l.runInDebug)((()=>{r&&void 0===u&&console.error(new Error(`${a} is undefined in ${i}`))})),t(u||"")})):""}}(e,t)}atob(){return(0,r.default)(...arguments)}btoa(){return(0,i.default)(...arguments)}uriJoin(){return this.joiner(this.uriComponent,"/","")(...arguments)}uriTag(){return this.tag(this.uriJoin.bind(this))}tag(e){return function(t){for(var n=arguments.length,l=new Array(n>1?n-1:0),r=1;rthis.success(n,e,void 0,t),error:n=>this.error(n,e,void 0,t)}}success(e,t){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:m,r=arguments.length>3?arguments[3]:void 0 +const i=(0,n.default)(t),o=(0,n.default)(l) +!1!==e&&(this.notify.clearMessages(),this.notify.add(s(s({},{timeout:6e3,extendedTimeout:300,destroyOnClick:!0}),{},{type:o(f),action:i(),item:e,model:r})))}error(e,t){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:m,r=arguments.length>3?arguments[3]:void 0 +const i=(0,n.default)(t),o=(0,n.default)(l) +this.notify.clearMessages(),this.logger.execute(e),"TransitionAborted"===e.name?this.notify.add(s(s({},{timeout:6e3,extendedTimeout:300,destroyOnClick:!0}),{},{type:o(f),action:i(),model:r})):this.notify.add(s(s({},{timeout:6e3,extendedTimeout:300,destroyOnClick:!0}),{},{type:o("error",e),action:i(),error:e,model:r}))}async execute(e,t,n,l){let r +try{r=await e(),this.success(r,t,n,l)}catch(i){this.error(i,t,n,l)}}},o=p(i.prototype,"notify",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=p(i.prototype,"logger",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) +e.default=h})),define("consul-ui/services/filter",["exports","@ember/service","consul-ui/utils/filter","consul-ui/filter/predicates/service","consul-ui/filter/predicates/service-instance","consul-ui/filter/predicates/health-check","consul-ui/filter/predicates/node","consul-ui/filter/predicates/kv","consul-ui/filter/predicates/intention","consul-ui/filter/predicates/token","consul-ui/filter/predicates/policy","consul-ui/filter/predicates/auth-method","consul-ui/filter/predicates/peer"],(function(e,t,n,l,r,i,o,a,u,s,c,d,p){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const f={service:(0,n.andOr)(l.default),"service-instance":(0,n.andOr)(r.default),"health-check":(0,n.andOr)(i.default),"auth-method":(0,n.andOr)(d.default),node:(0,n.andOr)(o.default),kv:(0,n.andOr)(a.default),intention:(0,n.andOr)(u.default),token:(0,n.andOr)(s.default),policy:(0,n.andOr)(c.default),peer:(0,n.andOr)(p.default)} +class m extends t.default{predicate(e){return f[e]}}e.default=m})),define("consul-ui/services/flash-messages",["exports","ember-cli-flash/services/flash-messages"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/form",["exports","@ember/service","consul-ui/utils/form/builder","consul-ui/forms/kv","consul-ui/forms/token","consul-ui/forms/policy","consul-ui/forms/role","consul-ui/forms/intention"],(function(e,t,n,l,r,i,o,a){var u,s,c,d,p +function f(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function m(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function h(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const b=(0,n.default)(),y={kv:l.default,token:r.default,policy:i.default,role:o.default,intention:a.default} +let v=(u=(0,t.inject)("repository/role"),s=(0,t.inject)("repository/policy"),c=class extends t.default{constructor(){super(...arguments),f(this,"role",d,this),f(this,"policy",p,this),m(this,"forms",[])}build(e,t){return b(...arguments)}form(e){let t=this.forms[e] +if(void 0===t&&(t=this.forms[e]=y[e](this),"role"===e||"policy"===e)){const n=this[e] +t.clear((function(e){return n.create(e)})),t.submit((function(e){return n.persist(e)}))}return t}},d=h(c.prototype,"role",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=h(c.prototype,"policy",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c) +e.default=v})),define("consul-ui/services/hcp",["exports","@ember/service","@ember/debug"],(function(e,t,n){var l,r,i,o,a,u,s +function c(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function d(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let p=(l=(0,t.inject)("env"),r=(0,t.inject)("repository/token"),i=(0,t.inject)("settings"),o=class extends t.default{constructor(){super(...arguments),c(this,"env",a,this),c(this,"tokenRepo",u,this),c(this,"settings",s,this)}async updateTokenIfNecessary(e){if(e){const l=await this.settings.findBySlug("token") +if(e&&e!==l.SecretID)try{const t=await this.tokenRepo.self({secret:e,dc:this.env.var("CONSUL_DATACENTER_LOCAL")}) +await this.settings.persist({token:{AccessorID:t.AccessorID,SecretID:t.SecretID,Namespace:t.Namespace,Partition:t.Partition}})}catch(t){(0,n.runInDebug)((e=>console.error(t)))}}}},a=d(o.prototype,"env",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),u=d(o.prototype,"tokenRepo",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s=d(o.prototype,"settings",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),o) +e.default=p})),define("consul-ui/services/i18n",["exports","ember-intl/services/intl","@ember/service"],(function(e,t,n){var l,r,i +function o(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function a(e){for(var t=1;t(e[t]=this.env.var(t),e)),{}) +return a(a({},e),t)}},d=r.prototype,p="env",f=[l],m={configurable:!0,enumerable:!0,writable:!0,initializer:null},b={},Object.keys(m).forEach((function(e){b[e]=m[e]})),b.enumerable=!!b.enumerable,b.configurable=!!b.configurable,("value"in b||b.initializer)&&(b.writable=!0),b=f.slice().reverse().reduce((function(e,t){return t(d,p,e)||e}),b),h&&void 0!==b.initializer&&(b.value=b.initializer?b.initializer.call(h):void 0,b.initializer=void 0),void 0===b.initializer&&(Object.defineProperty(d,p,b),b=null),i=b,r) +var d,p,f,m,h,b +e.default=c})),define("consul-ui/services/intl",["exports","ember-intl/services/intl"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/keyboard",["exports","ember-keyboard/services/keyboard.js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/local-storage",["exports","@ember/service","@ember/application","consul-ui/config/environment"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.storageFor=function(e){return function(){return{get(){return(0,n.getOwner)(this).lookup("service:localStorage").getBucket(e)}}}} +class r{constructor(){this.data=new Map}getItem(e){return this.data.get(e)}setItem(e,t){return this.data.set(e,t.toString())}seed(e){const t=new Map +Object.keys(e).forEach((n=>{t.set(n,e[n].toString())})),this.data=t}}class i extends t.default{constructor(){super(...arguments),this.storage="test"===l.default.environment?new r:window.localStorage,this.buckets=new Map}getBucket(e){const t=this.buckets.get(e) +return t||this._setupBucket(e)}_setupBucket(e){const t=new(0,(0,n.getOwner)(this).factoryFor(`storage:${e}`).class)(e,this.storage) +return this.buckets.set(e,t),t}}e.default=i})),define("consul-ui/services/logger",["exports","@ember/service","@ember/debug"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends t.default{execute(e){(0,n.runInDebug)((()=>{(e=void 0!==e.error?e.error:e)instanceof Error?console.error(e):console.log(e)}))}}e.default=l})),define("consul-ui/services/page-title-list",["exports","ember-page-title/services/page-title-list"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/page-title",["exports","ember-page-title/services/page-title"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/popup",["exports","torii/services/popup"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/repository",["exports","@ember/service","@ember/debug","@ember/utils","@ember/object","validated-changeset","consul-ui/utils/http/error","consul-ui/abilities/base"],(function(e,t,n,l,r,i,o,a){var u,s,c,d,p,f,m +function h(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function b(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.softDelete=e.default=void 0 +e.softDelete=(e,t)=>e.store.adapterFor(e.getModelName()).rpc(((e,t,n,l)=>e.requestForDeleteRecord(t,n,l)),((e,n,l,r)=>t),t,e.getModelName()) +let y=(u=(0,t.inject)("store"),s=(0,t.inject)("env"),c=(0,t.inject)("repository/permission"),d=class extends t.default{constructor(){super(...arguments),h(this,"store",p,this),h(this,"env",f,this),h(this,"permissions",m,this)}getModelName(){}getPrimaryKey(){}getSlugKey(){}async authorizeBySlug(e,t,n){return n.resources=await this.permissions.findBySlug(n,this.getModelName()),this.validatePermissions(e,t,n)}async authorizeByPermissions(e,t,n){return n.resources=await this.permissions.authorize(n),this.validatePermissions(e,t,n)}async validatePermissions(e,t,n){if(n.resources.length>0){const e=n.resources.find((e=>e.Access===t)) +if(e&&!1===e.Allow){const e=new o.default(403) +throw e.errors=[{status:"403"}],e}}const l=await e(n.resources) +return(0,r.get)(l,"Resources")&&(0,r.set)(l,"Resources",n.resources),l}shouldReconcile(e,t){if((0,r.get)(e,"Datacenter")!==t.dc)return!1 +if(this.env.var("CONSUL_NSPACES_ENABLED")){const n=(0,r.get)(e,"Namespace") +if(void 0!==n&&n!==t.ns)return!1}if(this.env.var("CONSUL_PARTITIONS_ENABLED")){const n=(0,r.get)(e,"Partition") +if(void 0!==n&&n!==t.partition)return!1}return!this.env.var("CONSUL_PEERINGS_ENABLED")||"service"!==this.getModelName()}reconcile(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +void 0!==e.date&&this.store.peekAll(this.getModelName()).forEach((n=>{const l=(0,r.get)(n,"SyncTime") +!n.isDeleted&&void 0!==l&&l!=e.date&&this.shouldReconcile(n,t)&&this.store.unloadRecord(n)}))}peekOne(e){return this.store.peekRecord(this.getModelName(),e)}peekAll(){return this.store.peekAll(this.getModelName())}cached(e){const t=Object.entries(e) +return this.store.peekAll(this.getModelName()).filter((e=>t.every((t=>{let[n,l]=t +return e[n]===l}))))}async findAllByDatacenter(e){return this.findAll(...arguments)}async findAll(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.query(e)}async query(){let e,t,n,l=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +try{n=await this.store.query(this.getModelName(),l),t=n.meta}catch(o){switch((0,r.get)(o,"errors.firstObject.status")){case"404":case"403":t={date:Number.POSITIVE_INFINITY},e=o +break +default:throw o}}if(void 0!==t&&this.reconcile(t,l,i),void 0!==e)throw e +return n}async findBySlug(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return""===e.id?this.create({Datacenter:e.dc,Namespace:e.ns,Partition:e.partition}):(void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.authorizeBySlug((()=>this.store.queryRecord(this.getModelName(),e)),a.ACCESS_READ,e))}create(e){return this.store.createRecord(this.getModelName(),e)}persist(e){return(0,i.isChangeset)(e)&&(e.execute(),e=e.data),(0,r.set)(e,"SyncTime",void 0),e.save()}remove(e){let t=e +return void 0===e.destroyRecord&&(t=e.get("data")),"object"===(0,l.typeOf)(t)&&(t=this.store.peekRecord(this.getModelName(),t[this.getPrimaryKey()])),t.destroyRecord().then((e=>this.store.unloadRecord(e)))}invalidate(){this.store.unloadAll(this.getModelName())}},p=b(d.prototype,"store",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=b(d.prototype,"env",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=b(d.prototype,"permissions",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d) +e.default=y})),define("consul-ui/services/repository/auth-method",["exports","consul-ui/services/repository","consul-ui/models/auth-method","consul-ui/decorators/data-source"],(function(e,t,n,l){var r,i,o +function a(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let u=(r=(0,l.default)("/:partition/:ns/:dc/auth-methods"),i=(0,l.default)("/:partition/:ns/:dc/auth-method/:id"),o=class extends t.default{getModelName(){return"auth-method"}getPrimaryKey(){return n.PRIMARY_KEY}getSlugKey(){return n.SLUG_KEY}async findAllByDatacenter(){return super.findAllByDatacenter(...arguments)}async findBySlug(){return super.findBySlug(...arguments)}},a(o.prototype,"findAllByDatacenter",[r],Object.getOwnPropertyDescriptor(o.prototype,"findAllByDatacenter"),o.prototype),a(o.prototype,"findBySlug",[i],Object.getOwnPropertyDescriptor(o.prototype,"findBySlug"),o.prototype),o) +e.default=u})),define("consul-ui/services/repository/binding-rule",["exports","consul-ui/services/repository","consul-ui/models/binding-rule","consul-ui/decorators/data-source"],(function(e,t,n,l){var r,i +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let o=(r=(0,l.default)("/:partition/:ns/:dc/binding-rules/for-auth-method/:authmethod"),i=class extends t.default{getModelName(){return"binding-rule"}getPrimaryKey(){return n.PRIMARY_KEY}getSlugKey(){return n.SLUG_KEY}async findAllByAuthMethod(){return super.findAll(...arguments)}},a=i.prototype,u="findAllByAuthMethod",s=[r],c=Object.getOwnPropertyDescriptor(i.prototype,"findAllByAuthMethod"),d=i.prototype,p={},Object.keys(c).forEach((function(e){p[e]=c[e]})),p.enumerable=!!p.enumerable,p.configurable=!!p.configurable,("value"in p||p.initializer)&&(p.writable=!0),p=s.slice().reverse().reduce((function(e,t){return t(a,u,e)||e}),p),d&&void 0!==p.initializer&&(p.value=p.initializer?p.initializer.call(d):void 0,p.initializer=void 0),void 0===p.initializer&&(Object.defineProperty(a,u,p),p=null),i) +var a,u,s,c,d,p +e.default=o})),define("consul-ui/services/repository/coordinate",["exports","consul-ui/services/repository","consul-ui/decorators/data-source","consul-ui/utils/tomography","consul-ui/utils/distance"],(function(e,t,n,l,r){var i,o,a +function u(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const s=(0,l.default)(r.default) +let c=(i=(0,n.default)("/:partition/:ns/:dc/coordinates"),o=(0,n.default)("/:partition/:ns/:dc/coordinates/for-node/:id"),a=class extends t.default{getModelName(){return"coordinate"}async findAllByDatacenter(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.store.query(this.getModelName(),e)}async findAllByNode(e,t){const n=await this.findAllByDatacenter(e,t) +let l={} +return n.length>1&&(l=s(e.id,n)),l.meta=n.meta,l}},u(a.prototype,"findAllByDatacenter",[i],Object.getOwnPropertyDescriptor(a.prototype,"findAllByDatacenter"),a.prototype),u(a.prototype,"findAllByNode",[o],Object.getOwnPropertyDescriptor(a.prototype,"findAllByNode"),a.prototype),a) +e.default=c})),define("consul-ui/services/repository/dc",["exports","@ember/error","@ember/service","consul-ui/services/repository","consul-ui/decorators/data-source","consul-ui/utils/http/consul"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p +function f(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}function m(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function h(e){for(var t=1;t{const l=Object.entries(e).find((e=>{let[t,n]=e +return t.toLowerCase()===i.HEADERS_DEFAULT_ACL_POLICY.toLowerCase()}))[1]||"allow" +return{meta:{version:2,uri:a},body:t.map((e=>n({Name:e,Datacenter:"",Local:e===u,Primary:e===s,DefaultACLPolicy:l},(t=>t`${y}:///${""}/${""}/${e}/datacenter`))))}}))}async fetch(e,t,n){let{partition:l,ns:r,dc:i}=e,{uri:o}=t +return(await(n` + GET /v1/operator/autopilot/state?${{dc:i}} + X-Request-ID: ${o} + `))(((e,t,n)=>{const l=Object.values(t.Servers),r=[] +return{meta:{version:2,uri:o},body:n(h(h({},t),{},{Servers:l,RedundancyZones:Object.entries(t.RedundancyZones||{}).map((e=>{let[n,l]=e +return h(h({},l),{},{Name:n,Healthy:!0,Servers:l.Servers.reduce(((e,n)=>{const l=t.Servers[n] +return r.push(l.ID),e.push(l),e}),[])})})),ReadReplicas:(t.ReadReplicas||[]).map((e=>(r.push(e),t.Servers[e]))),Default:{Servers:l.filter((e=>!r.includes(e.ID)))}}),(e=>e`${y}:///${""}/${""}/${i}/datacenter`))}}))}async fetchCatalogHealth(e,t,n){let{partition:l,ns:r,dc:i}=e,{uri:o}=t +return(await(n` + GET /v1/internal/ui/catalog-overview?${{dc:i,stale:null}} + X-Request-ID: ${o} + `))(((e,t,n)=>{const l=["Nodes","Services","Checks"].reduce(((e,n)=>((e,t,n)=>t[n].reduce(((e,t)=>(["Partition","Namespace"].forEach((l=>{let r=e[l][t[l]] +void 0===r&&(r=e[l][t[l]]={Name:t[l]}),void 0===r[n]&&(r[n]=h({},v)),r[n].Total+=t.Total,r[n].Passing+=t.Passing,r[n].Warning+=t.Warning,r[n].Critical+=t.Critical})),e.Datacenter[n].Total+=t.Total,e.Datacenter[n].Passing+=t.Passing,e.Datacenter[n].Warning+=t.Warning,e.Datacenter[n].Critical+=t.Critical,e)),e))(e,t,n)),{Datacenter:{Name:i,Nodes:h({},v),Services:h({},v),Checks:h({},v)},Partition:{},Namespace:{}}) +return{meta:{version:2,uri:o,interval:3e4},body:h({Datacenter:l.Datacenter,Partitions:Object.values(l.Partition),Namespaces:Object.values(l.Namespace)},t)}}))}async find(e){const n=this.store.peekAll("dc").findBy("Name",e.name) +if(void 0===n){const e=new t.default("Page not found") +throw e.status="404",{errors:[e]}}return n}},p=f(d.prototype,"env",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f(d.prototype,"fetchAll",[a],Object.getOwnPropertyDescriptor(d.prototype,"fetchAll"),d.prototype),f(d.prototype,"fetch",[u],Object.getOwnPropertyDescriptor(d.prototype,"fetch"),d.prototype),f(d.prototype,"fetchCatalogHealth",[s],Object.getOwnPropertyDescriptor(d.prototype,"fetchCatalogHealth"),d.prototype),f(d.prototype,"find",[c],Object.getOwnPropertyDescriptor(d.prototype,"find"),d.prototype),d) +e.default=g})),define("consul-ui/services/repository/discovery-chain",["exports","@ember/service","@ember/object","consul-ui/services/repository","consul-ui/decorators/data-source"],(function(e,t,n,l,r){var i,o,a,u +function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let c=(i=(0,t.inject)("repository/dc"),o=(0,r.default)("/:partition/:ns/:dc/discovery-chain/:id"),a=class extends l.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="dcs",l=this,(n=u)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"discovery-chain"}findBySlug(e){const t=this.dcs.peekAll().findBy("Name",e.dc) +return void 0===t||(0,n.get)(t,"MeshEnabled")?super.findBySlug(...arguments).catch((e=>{const l=(0,n.get)(e,"errors.firstObject.status"),r=((0,n.get)(e,"errors.firstObject.detail")||"").trim() +if("500"!==l)throw e +void 0!==t&&r.endsWith("Connect must be enabled in order to use this endpoint")&&(0,n.set)(t,"MeshEnabled",!1)})):Promise.resolve()}},u=s(a.prototype,"dcs",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s(a.prototype,"findBySlug",[o],Object.getOwnPropertyDescriptor(a.prototype,"findBySlug"),a.prototype),a) +e.default=c})),define("consul-ui/services/repository/intention-permission-http-header",["exports","consul-ui/services/repository"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{getModelName(){return"intention-permission-http-header"}create(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{} +return this.store.createFragment(this.getModelName(),e)}persist(e){return e.execute()}}e.default=n})),define("consul-ui/services/repository/intention-permission",["exports","consul-ui/services/repository"],(function(e,t){function n(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function l(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:{} +return this.store.createFragment(this.getModelName(),l(l({},e),{},{HTTP:this.store.createFragment("intention-permission-http",e.HTTP||{})}))}persist(e){return e.execute()}}e.default=i})),define("consul-ui/services/repository/intention",["exports","@ember/object","@ember/service","consul-ui/services/repository","consul-ui/models/intention","consul-ui/decorators/data-source"],(function(e,t,n,l,r,i){var o,a,u,s,c,d +function p(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function f(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function m(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let h=(o=(0,n.inject)("env"),a=(0,i.default)("/:partition/:ns/:dc/intentions"),u=(0,i.default)("/:partition/:ns/:dc/intention/:id"),s=(0,i.default)("/:partition/:ns/:dc/intentions/for-service/:id"),c=class extends l.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=d)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0}),f(this,"managedByCRDs",!1)}getModelName(){return"intention"}getPrimaryKey(){return r.PRIMARY_KEY}create(e){return delete e.Namespace,super.create(function(e){for(var t=1;te.IsManagedByCRD))),this.managedByCRDs}async authorizeBySlug(e,t,n){const[,l,,r]=n.id.split(":"),i=this.permissions.abilityFor(this.getModelName()) +return n.resources=i.generateForSegment(l).concat(i.generateForSegment(r)),this.authorizeByPermissions(e,t,n)}async persist(e){const n=await super.persist(...arguments) +return(0,t.get)(n,"Action.length")&&(0,t.set)(n,"Permissions",[]),n}async findAll(){return super.findAll(...arguments)}async findBySlug(e){let t +if(""===e.id){const n=this.env.var("CONSUL_NSPACES_ENABLED")?"*":"default",l="default" +t=await this.create({SourceNS:e.nspace||n,DestinationNS:e.nspace||n,SourcePartition:e.partition||l,DestinationPartition:e.partition||l,Datacenter:e.dc,Partition:e.partition})}else t=super.findBySlug(...arguments) +return t}async findByService(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +const n={dc:e.dc,nspace:e.nspace,filter:`SourceName == "${e.id}" or DestinationName == "${e.id}" or SourceName == "*" or DestinationName == "*"`} +return void 0!==t.cursor&&(n.index=t.cursor,n.uri=t.uri),this.store.query(this.getModelName(),n)}},d=m(c.prototype,"env",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m(c.prototype,"findAll",[a],Object.getOwnPropertyDescriptor(c.prototype,"findAll"),c.prototype),m(c.prototype,"findBySlug",[u],Object.getOwnPropertyDescriptor(c.prototype,"findBySlug"),c.prototype),m(c.prototype,"findByService",[s],Object.getOwnPropertyDescriptor(c.prototype,"findByService"),c.prototype),c) +e.default=h})),define("consul-ui/services/repository/kv",["exports","consul-ui/services/repository","consul-ui/utils/isFolder","@ember/object","consul-ui/models/kv","consul-ui/decorators/data-source"],(function(e,t,n,l,r,i){var o,a,u +function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let c=(o=(0,i.default)("/:partition/:ns/:dc/kv/:id"),a=(0,i.default)("/:partition/:ns/:dc/kvs/:id"),u=class extends t.default{getModelName(){return"kv"}getPrimaryKey(){return r.PRIMARY_KEY}shouldReconcile(e,t){return super.shouldReconcile(...arguments)&&e.Key.startsWith(t.id)}async findBySlug(e){let t +if((0,n.default)(e.id)){const n=JSON.stringify([e.partition,e.ns,e.dc,e.id]) +t=this.store.peekRecord(this.getModelName(),n),t||(t=await this.create({Key:e.id,Datacenter:e.dc,Namespace:e.ns,Partition:e.partition}))}else t=""===e.id?await this.create({Datacenter:e.dc,Namespace:e.ns,Partition:e.partition}):await super.findBySlug(...arguments) +return t}async findAllBySlug(e){e.separator="/","/"===e.id&&(e.id="") +let t=await this.findAll(...arguments) +const n=t.meta +return t=t.filter((t=>e.id!==(0,l.get)(t,"Key"))),t.meta=n,t}},s(u.prototype,"findBySlug",[o],Object.getOwnPropertyDescriptor(u.prototype,"findBySlug"),u.prototype),s(u.prototype,"findAllBySlug",[a],Object.getOwnPropertyDescriptor(u.prototype,"findAllBySlug"),u.prototype),u) +e.default=c})),define("consul-ui/services/repository/license",["exports","consul-ui/services/repository","consul-ui/decorators/data-source"],(function(e,t,n){var l,r +function i(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function o(e){for(var t=1;t({meta:{version:2,uri:o,interval:3e4},body:n(u(t,{dc:i}),(e=>e`${"license"}:///${l}/${r}/${i}/license/${t.License.license_id}`))})))}},c=r.prototype,d="find",p=[l],f=Object.getOwnPropertyDescriptor(r.prototype,"find"),m=r.prototype,h={},Object.keys(f).forEach((function(e){h[e]=f[e]})),h.enumerable=!!h.enumerable,h.configurable=!!h.configurable,("value"in h||h.initializer)&&(h.writable=!0),h=p.slice().reverse().reduce((function(e,t){return t(c,d,e)||e}),h),m&&void 0!==h.initializer&&(h.value=h.initializer?h.initializer.call(m):void 0,h.initializer=void 0),void 0===h.initializer&&(Object.defineProperty(c,d,h),h=null),r) +var c,d,p,f,m,h +e.default=s})),define("consul-ui/services/repository/metrics",["exports","@ember/service","consul-ui/services/repository","consul-ui/decorators/data-source"],(function(e,t,n,l){var r,i,o,a,u,s,c,d,p,f +function m(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function h(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function b(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let y=(r=(0,t.inject)("ui-config"),i=(0,t.inject)("env"),o=(0,t.inject)("client/http"),a=(0,l.default)("/:partition/:ns/:dc/metrics/summary-for-service/:slug/:protocol"),u=(0,l.default)("/:partition/:ns/:dc/metrics/upstream-summary-for-service/:slug/:protocol"),s=(0,l.default)("/:partition/:ns/:dc/metrics/downstream-summary-for-service/:slug/:protocol"),c=class extends n.default{constructor(){super(...arguments),m(this,"config",d,this),m(this,"env",p,this),m(this,"client",f,this),h(this,"error",null)}getModelName(){return"metrics"}init(){super.init(...arguments) +const e=this.config.getSync(),t=e.metrics_provider_options||{} +t.metrics_proxy_enabled=e.metrics_proxy_enabled +const n=e.metrics_provider||"prometheus" +t.fetch=(e,t)=>this.client.fetchWithToken(`/v1/internal/ui/metrics-proxy${e}`,t) +try{this.provider=window.consul.getMetricsProvider(n,t)}catch(l){this.error=new Error(`metrics provider not initialized: ${l}`),console.error(this.error)}}findServiceSummary(e){if(this.error)return Promise.reject(this.error) +const t=[this.provider.serviceRecentSummarySeries(e.slug,e.dc,e.ns,e.protocol,{}),this.provider.serviceRecentSummaryStats(e.slug,e.dc,e.ns,e.protocol,{})] +return Promise.all(t).then((e=>({meta:{interval:this.env.var("CONSUL_METRICS_POLL_INTERVAL")||1e4},series:e[0],stats:e[1].stats})))}findUpstreamSummary(e){return this.error?Promise.reject(this.error):this.provider.upstreamRecentSummaryStats(e.slug,e.dc,e.ns,{}).then((e=>(e.meta={interval:this.env.var("CONSUL_METRICS_POLL_INTERVAL")||1e4},e)))}findDownstreamSummary(e){return this.error?Promise.reject(this.error):this.provider.downstreamRecentSummaryStats(e.slug,e.dc,e.ns,{}).then((e=>(e.meta={interval:this.env.var("CONSUL_METRICS_POLL_INTERVAL")||1e4},e)))}},d=b(c.prototype,"config",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=b(c.prototype,"env",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=b(c.prototype,"client",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),b(c.prototype,"findServiceSummary",[a],Object.getOwnPropertyDescriptor(c.prototype,"findServiceSummary"),c.prototype),b(c.prototype,"findUpstreamSummary",[u],Object.getOwnPropertyDescriptor(c.prototype,"findUpstreamSummary"),c.prototype),b(c.prototype,"findDownstreamSummary",[s],Object.getOwnPropertyDescriptor(c.prototype,"findDownstreamSummary"),c.prototype),c) +e.default=y})) +define("consul-ui/services/repository/node",["exports","consul-ui/services/repository","consul-ui/decorators/data-source"],(function(e,t,n){var l,r,i,o +function a(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let u=(l=(0,n.default)("/:partition/:ns/:dc/nodes"),r=(0,n.default)("/:partition/:ns/:dc/node/:id/:peer"),i=(0,n.default)("/:partition/:ns/:dc/leader"),o=class extends t.default{getModelName(){return"node"}async findAllByDatacenter(){return super.findAllByDatacenter(...arguments)}async findBySlug(){return super.findBySlug(...arguments)}findLeader(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return void 0!==t.refresh&&(e.uri=t.uri),this.store.queryLeader(this.getModelName(),e)}},a(o.prototype,"findAllByDatacenter",[l],Object.getOwnPropertyDescriptor(o.prototype,"findAllByDatacenter"),o.prototype),a(o.prototype,"findBySlug",[r],Object.getOwnPropertyDescriptor(o.prototype,"findBySlug"),o.prototype),a(o.prototype,"findLeader",[i],Object.getOwnPropertyDescriptor(o.prototype,"findLeader"),o.prototype),o) +e.default=u})),define("consul-ui/services/repository/nspace",["exports","@ember/service","@ember/debug","consul-ui/services/repository","consul-ui/models/nspace","consul-ui/decorators/data-source","consul-ui/utils/form/builder"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m,h,b,y,v,g,O,P +function w(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function x(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let j=(a=(0,t.inject)("router"),u=(0,t.inject)("container"),s=(0,t.inject)("env"),c=(0,t.inject)("form"),d=(0,t.inject)("settings"),p=(0,t.inject)("repository/permission"),f=(0,i.default)("/:partition/:ns/:dc/namespaces"),m=(0,i.default)("/:partition/:ns/:dc/namespace/:id"),h=class extends l.default{constructor(){super(...arguments),w(this,"router",b,this),w(this,"container",y,this),w(this,"env",v,this),w(this,"form",g,this),w(this,"settings",O,this),w(this,"permissions",P,this)}getPrimaryKey(){return r.PRIMARY_KEY}getSlugKey(){return r.SLUG_KEY}getModelName(){return"nspace"}async findAll(){return this.permissions.can("use nspaces")?super.findAll(...arguments).catch((()=>[])):[]}async findBySlug(e){let t +return t=""===e.id?await this.create({Datacenter:e.dc,Partition:e.partition,ACLs:{PolicyDefaults:[],RoleDefaults:[]}}):await super.findBySlug(...arguments),(0,o.defaultChangeset)(t)}remove(e){return(0,l.softDelete)(this,e)}authorize(e,t){return this.env.var("CONSUL_ACLS_ENABLED")?this.store.authorize(this.getModelName(),{dc:e,ns:t}).catch((function(e){return[]})):Promise.resolve([{Resource:"operator",Access:"write",Allow:!0}])}async getActive(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"" +if(this.permissions.can("use nspaces"))return{Name:"default"} +const t=this.store.peekAll("nspace").toArray() +if(0===e.length){e=(await this.settings.findBySlug("token")).Namespace||"default"}return 1===t.length?t[0]:function(e,t){let l=e.find((function(e){return e.Name===t.Name})) +return void 0===l&&((0,n.runInDebug)((n=>console.info(`${t.Name} not found in [${e.map((e=>e.Name)).join(", ")}]`))),l=e.find((function(e){return"default"===e.Name})),void 0===l&&(l=e[0])),l}(t,{Name:e})}},b=x(h.prototype,"router",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y=x(h.prototype,"container",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),v=x(h.prototype,"env",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),g=x(h.prototype,"form",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),O=x(h.prototype,"settings",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=x(h.prototype,"permissions",[p],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),x(h.prototype,"findAll",[f],Object.getOwnPropertyDescriptor(h.prototype,"findAll"),h.prototype),x(h.prototype,"findBySlug",[m],Object.getOwnPropertyDescriptor(h.prototype,"findBySlug"),h.prototype),h) +e.default=j})),define("consul-ui/services/repository/oidc-provider",["exports","@ember/service","consul-ui/services/repository","@ember/application","@ember/object","consul-ui/decorators/data-source"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f +function m(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function h(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const b="oidc-with-url" +let y=(o=(0,t.inject)("torii"),a=(0,t.inject)("settings"),u=(0,i.default)("/:partition/:ns/:dc/oidc/providers"),s=(0,i.default)("/:partition/:ns/:dc/oidc/provider/:id"),c=(0,i.default)("/:partition/:ns/:dc/oidc/authorize/:id/:code/:state"),d=class extends n.default{constructor(){super(...arguments),m(this,"manager",p,this),m(this,"settings",f,this)}init(){super.init(...arguments),this.provider=(0,l.getOwner)(this).lookup(`torii-provider:${b}`)}getModelName(){return"oidc-provider"}async findAllByDatacenter(){const e=await super.findAllByDatacenter(...arguments) +if(0===e.length){const e=new Error("Not found") +return e.statusCode=404,void this.store.adapterFor(this.getModelName()).error(e)}return e}async findBySlug(e){const t=await this.settings.findBySlug("token")||{} +return super.findBySlug({ns:e.ns||t.Namespace||"default",partition:e.partition||t.Partition||"default",dc:e.dc,id:e.id})}authorize(e){return this.store.authorize(this.getModelName(),e)}logout(e,t,n,l,r){const i={id:e} +return this.store.logout(this.getModelName(),i)}close(){this.manager.close(b)}findCodeByURL(e){return(0,r.set)(this.provider,"baseUrl",e),this.manager.open(b,{}).catch((e=>{let t +if(!0===e.message.startsWith("remote was closed"))t=new Error("Remote was closed"),t.statusCode=499 +else t=new Error(e.message),t.statusCode=500 +this.store.adapterFor(this.getModelName()).error(t)}))}},p=h(d.prototype,"manager",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=h(d.prototype,"settings",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h(d.prototype,"findAllByDatacenter",[u],Object.getOwnPropertyDescriptor(d.prototype,"findAllByDatacenter"),d.prototype),h(d.prototype,"findBySlug",[s],Object.getOwnPropertyDescriptor(d.prototype,"findBySlug"),d.prototype),h(d.prototype,"authorize",[c],Object.getOwnPropertyDescriptor(d.prototype,"authorize"),d.prototype),d) +e.default=y})),define("consul-ui/services/repository/partition",["exports","@ember/service","@ember/debug","consul-ui/services/repository","consul-ui/models/partition","consul-ui/decorators/data-source","consul-ui/utils/form/builder"],(function(e,t,n,l,r,i,o){var a,u,s,c,d,p,f,m,h +function b(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function y(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let v=(a=(0,t.inject)("settings"),u=(0,t.inject)("form"),s=(0,t.inject)("repository/permission"),c=(0,i.default)("/:partition/:ns/:dc/partitions"),d=(0,i.default)("/:partition/:ns/:dc/partition/:id"),p=class extends l.default{constructor(){super(...arguments),b(this,"settings",f,this),b(this,"form",m,this),b(this,"permissions",h,this)}getModelName(){return"partition"}getPrimaryKey(){return r.PRIMARY_KEY}getSlugKey(){return r.SLUG_KEY}async findAll(){return this.permissions.can("use partitions")?super.findAll(...arguments).catch((()=>[])):[]}async findBySlug(e){let t +return t=""===e.id?await this.create({Datacenter:e.dc,Partition:""}):await super.findBySlug(...arguments),(0,o.defaultChangeset)(t)}remove(e){return(0,l.softDelete)(this,e)}async getActive(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"" +const t=this.store.peekAll("partition").toArray() +if(0===e.length){e=(await this.settings.findBySlug("token")).Partition||"default"}return 1===t.length?t[0]:function(e,t){let l=e.find((function(e){return e.Name===t.Name})) +return void 0===l&&((0,n.runInDebug)((n=>console.info(`${t.Name} not found in [${e.map((e=>e.Name)).join(", ")}]`))),l=e.find((function(e){return"default"===e.Name})),void 0===l&&(l=e[0])),l}(t,{Name:e})}},f=y(p.prototype,"settings",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=y(p.prototype,"form",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),h=y(p.prototype,"permissions",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),y(p.prototype,"findAll",[c],Object.getOwnPropertyDescriptor(p.prototype,"findAll"),p.prototype),y(p.prototype,"findBySlug",[d],Object.getOwnPropertyDescriptor(p.prototype,"findBySlug"),p.prototype),p) +e.default=v})),define("consul-ui/services/repository/peer",["exports","consul-ui/services/repository","consul-ui/decorators/data-source","@ember/service"],(function(e,t,n,l){var r,i,o,a,u,s,c,d +function p(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}function f(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function m(e){for(var t=1;t{const r=this.store.serializerFor("service") +return this.store.push(r.createJSONApiDocumentFromServicesPayload(e,t,l))}))}async fetchToken(e,t,n){let{dc:l,ns:r,partition:i,name:o,externalAddresses:a}=e +const u=(null==a?void 0:a.length)>0?a.split(","):[] +return(await(n` + POST /v1/peering/token + + ${{PeerName:o,Partition:i||void 0,ServerExternalAddresses:u}} + `))(((e,t,n)=>t))}async fetchAll(e,t,n){let{dc:l,ns:r,partition:i}=e,{uri:o}=t +return(await(n` + GET /v1/peerings + + ${{partition:i}} + `))(((e,t,n)=>({meta:{version:2,interval:1e4,uri:o},body:t.map((e=>n(b(e,l,i),(t=>t`peer:///${i}/${r}/${l}/peer/${e.Name}`))))})))}async fetchOne(e,t,n){let{partition:l,ns:r,dc:i,name:o}=e,{uri:a}=t +if(void 0===o||""===o){const e=this.create({Datacenter:i,Namespace:"",Partition:l}) +return e.meta={cacheControl:"no-store"},e}return(await(n` + GET /v1/peering/${o} + + ${{partition:l}} + `))(((e,t,n)=>{const{StreamStatus:o}=t +return o&&(o.LastHeartbeat&&(o.LastHeartbeat=new Date(o.LastHeartbeat)),o.LastReceive&&(o.LastReceive=new Date(o.LastReceive)),o.LastSend&&(o.LastSend=new Date(o.LastSend))),{meta:{version:2,interval:1e4,uri:a},body:n(b(t,i,l),(e=>e`peer:///${l}/${r}/${i}/peer/${t.Name}`))}}))}async persist(e,t){return(await(t` + POST /v1/peering/establish + + ${{PeerName:e.Name,PeeringToken:e.PeeringToken,Partition:e.Partition||void 0}} + `))(((t,n,l)=>{const r=e.Partition,i=e.Namespace,o=e.Datacenter +return{meta:{version:2},body:l(m(m({},e),{},{State:"ESTABLISHING"}),(t=>t`peer:///${r}/${i}/${o}/peer/${e.Name}`))}}))}async remove(e,t){return(await(t` + DELETE /v1/peering/${e.Name} + `))(((t,n,l)=>{const r=e.Partition,i=e.Namespace,o=e.Datacenter +return{meta:{version:2},body:l(m(m({},e),{},{State:"DELETING"}),(t=>t`peer:///${r}/${i}/${o}/peer/${e.Name}`))}}))}},d=p(c.prototype,"store",[l.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p(c.prototype,"fetchExportedServices",[r],Object.getOwnPropertyDescriptor(c.prototype,"fetchExportedServices"),c.prototype),p(c.prototype,"fetchToken",[i],Object.getOwnPropertyDescriptor(c.prototype,"fetchToken"),c.prototype),p(c.prototype,"fetchAll",[o],Object.getOwnPropertyDescriptor(c.prototype,"fetchAll"),c.prototype),p(c.prototype,"fetchOne",[a,u,s],Object.getOwnPropertyDescriptor(c.prototype,"fetchOne"),c.prototype),c) +e.default=y})),define("consul-ui/services/repository/permission",["exports","consul-ui/services/repository","@ember/service","@glimmer/tracking","@ember/debug","consul-ui/decorators/data-source"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p +function f(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function m(e){for(var t=1;tt.every((t=>n[t]===e[t]))&&!0===n.Allow))}can(e){return this._can.can(e)}abilityFor(e){return this._can.abilityFor(e)}generate(e,t,n){const l={Resource:e,Access:t} +return void 0!==n&&(l.Segment=n),l}async authorize(e){if(this.env.var("CONSUL_ACLS_ENABLED")){let n=[] +try{n=await this.store.authorize("permission",e)}catch(t){(0,r.runInDebug)((()=>console.error(t)))}return n}return e.resources.map((e=>m(m({},e),{},{Allow:!0})))}async findBySlug(e,t){let n +try{n=this._can.abilityFor(t)}catch(r){return[]}const l=n.generateForSegment(e.id.toString()) +return 0===l.length?[]:(e.resources=l,this.authorize(e))}async findByPermissions(e){return this.authorize(e)}async findAll(e){return e.resources=this.permissionsToRequest,this.permissions=await this.findByPermissions(e),this.permissions.forEach((e=>{["key","node","service","intention","session"].includes(e.Resource)&&(e.Allow=!0)})),this.permissions}get permissionsToRequest(){return this._can.can("use peers")?[...v,...g]:v}},c=y(s.prototype,"env",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d=y(s.prototype,"_can",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=y(s.prototype,"permissions",[l.tracked],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return[]}}),y(s.prototype,"findAll",[u],Object.getOwnPropertyDescriptor(s.prototype,"findAll"),s.prototype),s) +e.default=O})),define("consul-ui/services/repository/policy",["exports","consul-ui/services/repository","@ember/object","@ember/service","consul-ui/models/policy","consul-ui/decorators/data-source"],(function(e,t,n,l,r,i){var o,a,u,s,c +function d(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let p=(o=(0,l.inject)("form"),a=(0,i.default)("/:partition/:ns/:dc/policies"),u=(0,i.default)("/:partition/:ns/:dc/policy/:id"),s=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="form",l=this,(n=c)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"policy"}getPrimaryKey(){return r.PRIMARY_KEY}getSlugKey(){return r.SLUG_KEY}async findAllByDatacenter(){return super.findAllByDatacenter(...arguments)}async findBySlug(e){let t +return t=""===e.id?await this.create({Datacenter:e.dc,Partition:e.partition,Namespace:e.ns}):await super.findBySlug(...arguments),this.form.form(this.getModelName()).setData(t).getData()}persist(e){return""===(0,n.get)(e,"template")?e.save():Promise.resolve(e)}translate(e){return this.store.translate("policy",(0,n.get)(e,"Rules"))}},c=d(s.prototype,"form",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),d(s.prototype,"findAllByDatacenter",[a],Object.getOwnPropertyDescriptor(s.prototype,"findAllByDatacenter"),s.prototype),d(s.prototype,"findBySlug",[u],Object.getOwnPropertyDescriptor(s.prototype,"findBySlug"),s.prototype),s) +e.default=p})),define("consul-ui/services/repository/proxy",["exports","consul-ui/services/repository","consul-ui/models/proxy","@ember/object","consul-ui/decorators/data-source"],(function(e,t,n,l,r){var i,o,a +function u(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let s=(i=(0,r.default)("/:partition/:ns/:dc/proxies/for-service/:id"),o=(0,r.default)("/:partition/:ns/:dc/proxy-instance/:serviceId/:node/:id"),a=class extends t.default{getModelName(){return"proxy"}getPrimaryKey(){return n.PRIMARY_KEY}findAllBySlug(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.store.query(this.getModelName(),e).then((e=>(e.forEach((e=>{const t=JSON.parse(e.uid) +t.pop(),t.push(e.ServiceProxy.DestinationServiceID) +const n=this.store.peekRecord("service-instance",JSON.stringify(t)) +n&&(0,l.set)(n,"ProxyInstance",e)})),e)))}async findInstanceBySlug(e,t){const n=await this.findAllBySlug(e,t) +let r={} +if((0,l.get)(n,"length")>0){let t=n.filterBy("ServiceProxy.DestinationServiceID",e.serviceId).findBy("NodeName",e.node) +t?r=t:(t=n.findBy("ServiceProxy.DestinationServiceName",e.id),t&&(r=t))}return(0,l.set)(r,"meta",(0,l.get)(n,"meta")),r}},u(a.prototype,"findAllBySlug",[i],Object.getOwnPropertyDescriptor(a.prototype,"findAllBySlug"),a.prototype),u(a.prototype,"findInstanceBySlug",[o],Object.getOwnPropertyDescriptor(a.prototype,"findInstanceBySlug"),a.prototype),a) +e.default=s})),define("consul-ui/services/repository/role",["exports","consul-ui/services/repository","@ember/service","consul-ui/models/role","consul-ui/decorators/data-source"],(function(e,t,n,l,r){var i,o,a,u,s +function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let d=(i=(0,n.inject)("form"),o=(0,r.default)("/:partition/:ns/:dc/roles"),a=(0,r.default)("/:partition/:ns/:dc/role/:id"),u=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="form",l=this,(n=s)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"role"}getPrimaryKey(){return l.PRIMARY_KEY}getSlugKey(){return l.SLUG_KEY}async findAll(){return super.findAll(...arguments)}async findBySlug(e){let t +return t=""===e.id?await this.create({Datacenter:e.dc,Partition:e.partition,Namespace:e.ns}):await super.findBySlug(...arguments),this.form.form(this.getModelName()).setData(t).getData()}},s=c(u.prototype,"form",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c(u.prototype,"findAll",[o],Object.getOwnPropertyDescriptor(u.prototype,"findAll"),u.prototype),c(u.prototype,"findBySlug",[a],Object.getOwnPropertyDescriptor(u.prototype,"findBySlug"),u.prototype),u) +e.default=d})),define("consul-ui/services/repository/service-instance",["exports","consul-ui/services/repository","@ember/object","consul-ui/abilities/base","consul-ui/decorators/data-source"],(function(e,t,n,l,r){var i,o,a +function u(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let s=(i=(0,r.default)("/:partition/:ns/:dc/service-instances/for-service/:id/:peer"),o=(0,r.default)("/:partition/:ns/:dc/service-instance/:serviceId/:node/:id/:peer"),a=class extends t.default{getModelName(){return"service-instance"}shouldReconcile(e,t){return super.shouldReconcile(...arguments)&&e.Service.Service===t.id}async findByService(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.authorizeBySlug((async t=>{const l=await this.query(e) +return(0,n.set)(l,"firstObject.Service.Resources",t),l}),l.ACCESS_READ,e)}async findBySlug(e){return super.findBySlug(...arguments)}},u(a.prototype,"findByService",[i],Object.getOwnPropertyDescriptor(a.prototype,"findByService"),a.prototype),u(a.prototype,"findBySlug",[o],Object.getOwnPropertyDescriptor(a.prototype,"findBySlug"),a.prototype),a) +e.default=s})),define("consul-ui/services/repository/service",["exports","consul-ui/services/repository","consul-ui/decorators/data-source","@ember/service"],(function(e,t,n,l){var r,i,o,a,u +function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let c=(r=(0,n.default)("/:partition/:ns/:dc/services"),i=(0,n.default)("/:partition/:ns/:dc/services/:peer/:peerId"),o=(0,n.default)("/:partition/:ns/:dc/gateways/for-service/:gateway"),a=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="store",l=this,(n=u)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"service"}async findAllByDatacenter(){return super.findAll(...arguments)}async findAllImportedServices(e,t){const{peerId:n}=e +return delete e.peerId,super.findAll(e,t).then((e=>{const t=this.store.peekRecord("peer",n) +return e.forEach((e=>e.peer=t)),e}))}findGatewayBySlug(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.store.query(this.getModelName(),e)}},u=s(a.prototype,"store",[l.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s(a.prototype,"findAllByDatacenter",[r],Object.getOwnPropertyDescriptor(a.prototype,"findAllByDatacenter"),a.prototype),s(a.prototype,"findAllImportedServices",[i],Object.getOwnPropertyDescriptor(a.prototype,"findAllImportedServices"),a.prototype),s(a.prototype,"findGatewayBySlug",[o],Object.getOwnPropertyDescriptor(a.prototype,"findGatewayBySlug"),a.prototype),a) +e.default=c})),define("consul-ui/services/repository/session",["exports","@ember/service","consul-ui/services/repository","consul-ui/decorators/data-source"],(function(e,t,n,l){var r,i,o,a,u +function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let c=(r=(0,t.inject)("store"),i=(0,l.default)("/:partition/:ns/:dc/sessions/for-node/:id"),o=(0,l.default)("/:partition/:ns/:dc/sessions/for-key/:id"),a=class extends n.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="store",l=this,(n=u)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"session"}findByNode(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.store.query(this.getModelName(),e)}findByKey(e){return this.findBySlug(...arguments)}},u=s(a.prototype,"store",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s(a.prototype,"findByNode",[i],Object.getOwnPropertyDescriptor(a.prototype,"findByNode"),a.prototype),s(a.prototype,"findByKey",[o],Object.getOwnPropertyDescriptor(a.prototype,"findByKey"),a.prototype),a) +e.default=c})),define("consul-ui/services/repository/token",["exports","consul-ui/services/repository","@ember/object","@ember/service","consul-ui/models/token","consul-ui/decorators/data-source"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f +function m(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let h=(o=(0,l.inject)("form"),a=(0,i.default)("/:partition/:ns/:dc/tokens"),u=(0,i.default)("/:partition/:ns/:dc/token/:id"),s=(0,i.default)("/:partition/:ns/:dc/token/self/:secret"),c=(0,i.default)("/:partition/:ns/:dc/tokens/for-policy/:policy"),d=(0,i.default)("/:partition/:ns/:dc/tokens/for-role/:role"),p=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="form",l=this,(n=f)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"token"}getPrimaryKey(){return r.PRIMARY_KEY}getSlugKey(){return r.SLUG_KEY}async findAll(){return super.findAll(...arguments)}async findBySlug(e){let t +return t=""===e.id?await this.create({Datacenter:e.dc,Partition:e.partition,Namespace:e.ns}):await super.findBySlug(...arguments),this.form.form(this.getModelName()).setData(t).getData()}self(e){return this.store.self(this.getModelName(),{secret:e.secret,dc:e.dc}).catch((e=>Promise.reject(e)))}clone(e){return this.store.clone(this.getModelName(),(0,n.get)(e,r.PRIMARY_KEY))}findByPolicy(e){return this.findAll(...arguments)}findByRole(){return this.findAll(...arguments)}},f=m(p.prototype,"form",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m(p.prototype,"findAll",[a],Object.getOwnPropertyDescriptor(p.prototype,"findAll"),p.prototype),m(p.prototype,"findBySlug",[u],Object.getOwnPropertyDescriptor(p.prototype,"findBySlug"),p.prototype),m(p.prototype,"self",[s],Object.getOwnPropertyDescriptor(p.prototype,"self"),p.prototype),m(p.prototype,"findByPolicy",[c],Object.getOwnPropertyDescriptor(p.prototype,"findByPolicy"),p.prototype),m(p.prototype,"findByRole",[d],Object.getOwnPropertyDescriptor(p.prototype,"findByRole"),p.prototype),p) +e.default=h})),define("consul-ui/services/repository/topology",["exports","@ember/service","consul-ui/services/repository","@ember/object","consul-ui/decorators/data-source"],(function(e,t,n,l,r){var i,o,a,u +function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let c=(i=(0,t.inject)("repository/dc"),o=(0,r.default)("/:partition/:ns/:dc/topology/:id/:kind"),a=class extends n.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="dcs",l=this,(n=u)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}getModelName(){return"topology"}findBySlug(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +const n=this.dcs.peekOne(e.dc) +return null===n||(0,l.get)(n,"MeshEnabled")?(void 0!==t.cursor&&(e.index=t.cursor,e.uri=t.uri),this.store.queryRecord(this.getModelName(),e).catch((e=>{const t=(0,l.get)(e,"errors.firstObject.status"),r=((0,l.get)(e,"errors.firstObject.detail")||"").trim() +if("500"!==t)throw e +null!==n&&r.endsWith("Connect must be enabled in order to use this endpoint")&&(0,l.set)(n,"MeshEnabled",!1)}))):Promise.resolve()}},u=s(a.prototype,"dcs",[i],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),s(a.prototype,"findBySlug",[o],Object.getOwnPropertyDescriptor(a.prototype,"findBySlug"),a.prototype),a) +e.default=c})),define("consul-ui/services/resize-observer",["exports","ember-resize-observer-service/services/resize-observer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/routlet",["exports","@ember/service","@ember/runloop","@ember/object","consul-ui/utils/routing/wildcard","consul-ui/router"],(function(e,t,n,l,r,i){var o,a,u,s,c,d,p,f,m +function h(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function b(e){for(var t=1;t{if("application"===e)return 1 +if("application"===t)return-1 +const n=e.split(".").length,l=t.split(".").length +switch(!0){case n>l:return-1 +case n0&&!t.every((e=>this.permissions.can(e))))}transition(){let e +return this._transition=new Promise((t=>{e=t})),e}findOutlet(e){return[...P.keys()].find((t=>-1!==e.indexOf(t)))}outletFor(e){const t=[...P.keys()],n=t.indexOf(e)+1 +return P.get(t[n])}normalizeParamsFor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return O(e)?Object.keys(t).reduce((function(e,n){return void 0!==t[n]?e[n]=decodeURIComponent(t[n]):e[n]=t[n],e}),{}):t}paramsFor(e){let t={} +const n=P.get(e) +void 0!==n&&void 0!==n.args.params&&(t=n.args.params) +let l=this.router.currentRoute +null===l&&(l=this.container.lookup("route:application")) +let r,i=l,o=this.normalizeParamsFor(e,i.params) +for(;r=i.parent;)o=b(b({},this.normalizeParamsFor(r.name,r.params)),o),i=r +return b(b(b({},this.container.get(`location:${this.env.var("locationType")}`).optionalParams()),o),t)}modelFor(e){const t=P.get(e) +if(void 0!==t)return t.model}addRoute(e,t){const l=this.outletFor(e) +void 0!==l&&(l.route=t,(0,n.schedule)("afterRender",(()=>{l.routeName=e})))}removeRoute(e,t){const l=this.outletFor(e) +t._model=void 0,void 0!==l&&(0,n.schedule)("afterRender",(()=>{l.route=void 0}))}addOutlet(e,t){P.set(e,t)}removeOutlet(e){(0,n.schedule)("afterRender",(()=>{P.delete(e)}))}},d=g(c.prototype,"container",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),p=g(c.prototype,"env",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),f=g(c.prototype,"router",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),m=g(c.prototype,"permissions",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c) +e.default=w})),define("consul-ui/services/schema",["exports","@ember/service","consul-ui/models/intention-permission","consul-ui/models/intention-permission-http","consul-ui/models/intention-permission-http-header"],(function(e,t,n,l,r){function i(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class o extends t.default{constructor(){super(...arguments),i(this,"intention-permission",n.schema),i(this,"intention-permission-http",l.schema),i(this,"intention-permission-http-header",r.schema)}}e.default=o})),define("consul-ui/services/search",["exports","@ember/service","consul-ui/utils/search/exact","consul-ui/search/predicates/intention","consul-ui/search/predicates/upstream-instance","consul-ui/search/predicates/service-instance","consul-ui/search/predicates/health-check","consul-ui/search/predicates/acl","consul-ui/search/predicates/service","consul-ui/search/predicates/node","consul-ui/search/predicates/kv","consul-ui/search/predicates/token","consul-ui/search/predicates/role","consul-ui/search/predicates/policy","consul-ui/search/predicates/auth-method","consul-ui/search/predicates/nspace","consul-ui/search/predicates/peer"],(function(e,t,n,l,r,i,o,a,u,s,c,d,p,f,m,h,b){function y(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const v={intention:l.default,service:u.default,"service-instance":i.default,"upstream-instance":r.default,"health-check":o.default,"auth-method":m.default,node:s.default,kv:c.default,acl:a.default,token:d.default,role:p.default,policy:f.default,nspace:h.default,peer:b.default} +class g extends t.default{constructor(){super(...arguments),y(this,"searchables",{exact:n.default})}predicate(e){return v[e]}}e.default=g})),define("consul-ui/services/settings",["exports","@ember/service","consul-ui/utils/storage/local-storage"],(function(e,t,n){function l(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.ifNotBlocking=e.default=void 0 +const r=(0,n.default)("consul") +e.ifNotBlocking=function(e){return e.findBySlug("client").then((function(e){return void 0!==e.blocking&&!e.blocking}))} +class i extends t.default{constructor(){super(...arguments),l(this,"storage",r)}findAll(e){return Promise.resolve(this.storage.all())}findBySlug(e){return Promise.resolve(this.storage.getValue(e))}persist(e){const t=this.storage +return Object.keys(e).forEach(((n,l)=>{t.setValue(n,e[n])})),Promise.resolve(e)}delete(e){Array.isArray(e)||(e=[e]) +const t=this.storage,n=e.reduce((function(e,n,l,r){return t.removeValue(n),e}),{}) +return Promise.resolve(n)}}e.default=i})),define("consul-ui/services/sort",["exports","@ember/service","consul-ui/sort/comparators/service","consul-ui/sort/comparators/service-instance","consul-ui/sort/comparators/upstream-instance","consul-ui/sort/comparators/kv","consul-ui/sort/comparators/health-check","consul-ui/sort/comparators/intention","consul-ui/sort/comparators/token","consul-ui/sort/comparators/role","consul-ui/sort/comparators/policy","consul-ui/sort/comparators/auth-method","consul-ui/sort/comparators/nspace","consul-ui/sort/comparators/peer","consul-ui/sort/comparators/node"],(function(e,t,n,l,r,i,o,a,u,s,c,d,p,f,m){Object.defineProperty(e,"__esModule",{value:!0}),e.properties=e.default=void 0 +const h=e=>e.reduce(((e,t)=>e.concat([`${t}:asc`,`${t}:desc`])),[]),b=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[] +return t=>{const n=h(e) +return[n.find((e=>e===t))||n[0]]}} +e.properties=b +const y={properties:b,directionify:h},v={service:(0,n.default)(y),"service-instance":(0,l.default)(y),"upstream-instance":(0,r.default)(y),"health-check":(0,o.default)(y),"auth-method":(0,d.default)(y),kv:(0,i.default)(y),intention:(0,a.default)(y),token:(0,u.default)(y),role:(0,s.default)(y),policy:(0,c.default)(y),nspace:(0,p.default)(y),peer:(0,f.default)(y),node:(0,m.default)(y)} +class g extends t.default{comparator(e){return v[e]}}e.default=g})),define("consul-ui/services/state-with-charts",["exports","consul-ui/services/state","consul-ui/machines/validate.xstate","consul-ui/machines/boolean.xstate"],(function(e,t,n,l){function r(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class i extends t.default{constructor(){super(...arguments),r(this,"stateCharts",{validate:n.default,boolean:l.default})}}e.default=i})),define("consul-ui/services/state",["exports","@ember/service","@ember/object","flat","@xstate/fsm"],(function(e,t,n,l,r){var i,o,a +function u(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e +var n=e[Symbol.toPrimitive] +if(void 0!==n){var l=n.call(e,t||"default") +if("object"!=typeof l)return l +throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string") +return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let s=(i=(0,t.inject)("logger"),o=class extends t.default{constructor(){var e,t,n,l +super(...arguments),u(this,"stateCharts",{}),e=this,t="logger",l=this,(n=a)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}log(e,t){}stateChart(e){return this.stateCharts[e]}addGuards(e,t){return this.guards(e).forEach((function(l){let[r,i]=l;(0,n.set)(e,r,(function(){return!!t.onGuard(i,...arguments)}))})),[e,t]}machine(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return(0,r.createMachine)(...this.addGuards(e,t))}prepareChart(e){return void 0!==(e=JSON.parse(JSON.stringify(e))).on&&Object.values(e.states).forEach((function(t){void 0===t.on?t.on=e.on:Object.keys(e.on).forEach((function(n){void 0===t.on[n]&&(t.on[n]=e.on[n])}))})),e}matches(e,t){if(void 0===e)return!1 +return(Array.isArray(t)?t:[t]).some((t=>e.matches(t)))}state(e){return{matches:e}}interpret(e,t){e=this.prepareChart(e) +const n=(0,r.interpret)(this.machine(e,t)) +return n.subscribe((n=>{n.changed&&(this.log(e,n),t.onTransition(n))})),n}guards(e){return Object.entries((0,l.default)(e)).filter((e=>{let[t]=e +return t.endsWith(".cond")}))}},c=o.prototype,d="logger",p=[i],f={configurable:!0,enumerable:!0,writable:!0,initializer:null},h={},Object.keys(f).forEach((function(e){h[e]=f[e]})),h.enumerable=!!h.enumerable,h.configurable=!!h.configurable,("value"in h||h.initializer)&&(h.writable=!0),h=p.slice().reverse().reduce((function(e,t){return t(c,d,e)||e}),h),m&&void 0!==h.initializer&&(h.value=h.initializer?h.initializer.call(m):void 0,h.initializer=void 0),void 0===h.initializer&&(Object.defineProperty(c,d,h),h=null),a=h,o) +var c,d,p,f,m,h +e.default=s})),define("consul-ui/services/store",["exports","@ember/service","@ember-data/store"],(function(e,t,n){var l,r,i,o,a +function u(e,t,n,l){n&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}function s(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let c=(l=(0,t.inject)("data-source/service"),r=(0,t.inject)("client/http"),i=class extends n.default{constructor(){super(...arguments),u(this,"dataSource",o,this),u(this,"client",a,this)}invalidate(){this.client.abort(401),this.dataSource.resetCache(),this.init()}clear(){this.invalidate(0)}clone(e,t){return this.adapterFor(e).clone(this,{modelName:e},t,this._internalModelForId(e,t).createSnapshot({}))}self(e,t){const n=this.adapterFor(e),l=this.serializerFor(e),r={modelName:e} +return n.self(this,r,t.secret,t).then((e=>l.normalizeResponse(this,r,e,t,"self")))}queryLeader(e,t){const n=this.adapterFor(e),l=this.serializerFor(e),r={modelName:e} +return n.queryLeader(this,r,null,t).then((e=>(e.meta=l.normalizeMeta(this,r,e,null,"leader"),e)))}authorize(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +const n=this.adapterFor(e),l=this.serializerFor(e),r={modelName:e} +return n.authorize(this,r,null,t).then((e=>l.normalizeResponse(this,r,e,void 0,"authorize")))}logout(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +const n={modelName:e} +return this.adapterFor(e).logout(this,n,t.id,t)}},o=s(i.prototype,"dataSource",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),a=s(i.prototype,"client",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),i) +e.default=c})),define("consul-ui/services/temporal",["exports","pretty-ms","parse-duration","@ember/debug","dayjs","dayjs/plugin/relativeTime","@ember/service"],(function(e,t,n,l,r,i,o){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,r.default.extend(i.default) +class a extends o.default{format(e,t){const n=(0,r.default)(e) +return(0,r.default)().isBefore(n)?(0,r.default)().to(n,!0):(0,r.default)().from(n,!0)}within(e,t){let[n,l]=e +return(0,r.default)(n).isBefore((0,r.default)().add(l,"ms"))}parse(e,t){return(0,n.default)(e)}durationFrom(e){return!0==("number"==typeof e)?0===e?"0":(0,t.default)(e/1e6,{formatSubMilliseconds:!0}).split(" ").join(""):e}}e.default=a})),define("consul-ui/services/text-measurer",["exports","ember-text-measurer/services/text-measurer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/ticker",["exports","@ember/service","consul-ui/utils/ticker"],(function(e,t,n){let l +Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class r extends t.default{init(){super.init(...arguments),this.reset()}tweenTo(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",r=arguments.length>2?arguments[2]:void 0,i=arguments.length>3?arguments[3]:void 0 +const o=t +return l.has(o)?(t=l.get(o),t instanceof n.Tween&&(t=t.stop().getTarget()),l.set(o,n.Tween.to(t,e,r,i)),t):(l.set(o,e),e)}destroy(e){return this.reset(),n.Tween.destroy()}reset(){l=new Map}}e.default=r})),define("consul-ui/services/timeout",["exports","@ember/service","consul-ui/utils/promisedTimeout","@ember/runloop"],(function(e,t,n,l){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const r=(0,n.default)(Promise) +class i extends t.default{execute(e,t){return r(e,t)}tick(){return new Promise((function(e,t){(0,l.next)(e)}))}}e.default=i})),define("consul-ui/services/torii-session",["exports","torii/services/torii-session"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/torii",["exports","torii/services/torii"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/services/ui-config",["exports","@ember/service","@ember/object","consul-ui/decorators/data-source"],(function(e,t,n,l){var r,i,o,a,u,s +function c(e,t,n,l,r){var i={} +return Object.keys(l).forEach((function(e){i[e]=l[e]})),i.enumerable=!!i.enumerable,i.configurable=!!i.configurable,("value"in i||i.initializer)&&(i.writable=!0),i=n.slice().reverse().reduce((function(n,l){return l(e,t,n)||n}),i),r&&void 0!==i.initializer&&(i.value=i.initializer?i.initializer.call(r):void 0,i.initializer=void 0),void 0===i.initializer&&(Object.defineProperty(e,t,i),i=null),i}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +let d=(r=(0,t.inject)("env"),i=(0,l.default)("/:partition/:nspace/:dc/ui-config/:path"),o=(0,l.default)("/:partition/:nspace/:dc/notfound/:path"),a=(0,l.default)("/:partition/:nspace/:dc/ui-config"),u=class extends t.default{constructor(){var e,t,n,l +super(...arguments),e=this,t="env",l=this,(n=s)&&Object.defineProperty(e,t,{enumerable:n.enumerable,configurable:n.configurable,writable:n.writable,value:n.initializer?n.initializer.call(l):void 0})}async findByPath(e){return(0,n.get)(this.get(),e.path)}async parsePath(e){return e.path.split("/").reduce(((e,t,n)=>{switch(!0){case t.startsWith("~"):e.nspace=t.substr(1) +break +case t.startsWith("_"):e.partition=t.substr(1) +break +case void 0===e.dc:e.dc=t}return e}),{})}async get(){return this.env.var("CONSUL_UI_CONFIG")}getSync(){return this.env.var("CONSUL_UI_CONFIG")}},s=c(u.prototype,"env",[r],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),c(u.prototype,"findByPath",[i],Object.getOwnPropertyDescriptor(u.prototype,"findByPath"),u.prototype),c(u.prototype,"parsePath",[o],Object.getOwnPropertyDescriptor(u.prototype,"parsePath"),u.prototype),c(u.prototype,"get",[a],Object.getOwnPropertyDescriptor(u.prototype,"get"),u.prototype),u) +e.default=d})) +define("consul-ui/sort/comparators/auth-method",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:t}=e +return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"MethodName:asc" +return t(["MethodName","TokenTTL"])(e)}}})),define("consul-ui/sort/comparators/health-check",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:t}=e +return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"Status:asc" +return e.startsWith("Status:")?function(t,n){const[,l]=e.split(":") +let r,i +"asc"===l?(r=t,i=n):(i=t,r=n) +const o=r.Status,a=i.Status +switch(o){case"passing":return"passing"===a?0:1 +case"critical":return"critical"===a?0:-1 +case"warning":switch(a){case"passing":return-1 +case"critical":return 1 +default:return 0}}return 0}:t(["Name","Kind"])(e)}}})),define("consul-ui/sort/comparators/intention",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=()=>e=>[e]})),define("consul-ui/sort/comparators/kv",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:t}=e +return e=>t(["Key","Kind"])(e)}})),define("consul-ui/sort/comparators/node",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:t}=e +return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"Name:asc" +return e.startsWith("Status:")?function(t,n){const[,l]=e.split(":") +let r,i +switch("asc"===l?(i=t,r=n):(r=t,i=n),!0){case r.ChecksCritical>i.ChecksCritical:return 1 +case r.ChecksCriticali.ChecksWarning:return 1 +case r.ChecksWarningi.ChecksPassing:return-1}}return 0}}:e.startsWith("Version:")?function(t,n){const[,l]=e.split(":") +let r,i +"asc"===l?(r=t,i=n):(i=t,r=n) +const o=r.Version.split(".").map((e=>{const t=Number(e) +return isNaN(t)?0:t})),a=i.Version.split(".").map((e=>{const t=Number(e) +return isNaN(t)?0:t})),u=Math.min(o.length,a.length) +for(let e=0;e0:return 1 +case t<0:return-1}}return o.length-a.length}:t(["Node"])(e)}}})),define("consul-ui/sort/comparators/nspace",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:t}=e +return e=>t(["Name"])(e)}})),define("consul-ui/sort/comparators/partition",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:t}=e +return e=>t(["Name"])(e)}})),define("consul-ui/sort/comparators/peer",["exports","consul-ui/models/peer"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:n}=e +return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"State:asc" +return e.startsWith("State:")?function(n,l){const[,r]=e.split(":") +let i,o +switch("asc"===r?(o=n,i=l):(i=n,o=l),!0){case t.schema.State.allowedValues.indexOf(i.State)t.schema.State.allowedValues.indexOf(o.State):return-1 +case t.schema.State.allowedValues.indexOf(i.State)===t.schema.State.allowedValues.indexOf(o.State):return 0}}:n(["Name"])(e)}}})),define("consul-ui/sort/comparators/policy",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:t}=e +return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"Name:asc" +return t(["Name"])(e)}}})),define("consul-ui/sort/comparators/role",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:t}=e +return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"Name:asc" +return t(["Name","CreateIndex"])(e)}}})),define("consul-ui/sort/comparators/service-instance",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:t}=e +return e=>{if(e.startsWith("Status:")){const[,t]=e.split(":"),n=["PercentageChecksPassing","PercentageChecksWarning","PercentageChecksCritical"] +return"asc"===t&&n.reverse(),function(e,t){for(let l in n){let r=n[l] +if(e[r]!==t[r])return e[r]>t[r]?-1:1}}}return t(["Name"])(e)}}})),define("consul-ui/sort/comparators/service",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:t}=e +return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"Status:asc" +return e.startsWith("Status:")?function(t,n){const[,l]=e.split(":") +let r,i +switch("asc"===l?(i=t,r=n):(r=t,i=n),!0){case r.MeshChecksCritical>i.MeshChecksCritical:return 1 +case r.MeshChecksCriticali.MeshChecksWarning:return 1 +case r.MeshChecksWarningi.MeshChecksPassing:return-1}}return 0}}:t(["Name"])(e)}}})),define("consul-ui/sort/comparators/token",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:t}=e +return e=>t(["CreateTime"])(e)}})),define("consul-ui/sort/comparators/upstream-instance",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>{let{properties:t}=e +return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"DestinationName:asc" +return t(["DestinationName"])(e)}}})),define("consul-ui/storages/base",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=class{constructor(e,t){this.key=e,this.storage=t,this.state=this.initState(this.key,this.storage)}initState(){const{key:e,storage:t}=this +return t.getItem(e)}}})),define("consul-ui/storages/notices",["exports","tracked-built-ins","consul-ui/storages/base"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class l extends n.default{initState(){const{key:e,storage:n}=this,l=n.getItem(e) +return l?new t.TrackedArray(l.split(",")):new t.TrackedArray}add(e){const{key:t,storage:n,state:l}=this +l.push(e),n.setItem(t,[...l])}}e.default=l})),define("consul-ui/styles/base/decoration/visually-hidden.css",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>e` + @keyframes visually-hidden { + 100% { + position: absolute; + overflow: hidden; + clip: rect(0 0 0 0); + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + border: 0; + } + } + `})),define("consul-ui/styles/base/icons/base-keyframes.css",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>e` + *::before, + *::after { + display: inline-block; + animation-play-state: paused; + animation-fill-mode: forwards; + animation-iteration-count: var(--icon-resolution, 1); + vertical-align: text-top; + } + *::before { + animation-name: var(--icon-name-start, var(--icon-name)), + var(--icon-size-start, var(--icon-size, icon-000)); + background-color: var(--icon-color-start, var(--icon-color)); + } + *::after { + animation-name: var(--icon-name-end, var(--icon-name)), + var(--icon-size-end, var(--icon-size, icon-000)); + background-color: var(--icon-color-end, var(--icon-color)); + } + + [style*='--icon-color-start']::before { + color: var(--icon-color-start); + } + [style*='--icon-color-end']::after { + color: var(--icon-color-end); + } + [style*='--icon-name-start']::before, + [style*='--icon-name-end']::after { + content: ''; + } + + @keyframes icon-000 { + 100% { + width: 1.2em; + height: 1.2em; + } + } + @keyframes icon-100 { + 100% { + width: 0.625rem; /* 10px */ + height: 0.625rem; /* 10px */ + } + } + @keyframes icon-200 { + 100% { + width: 0.75rem; /* 12px */ + height: 0.75rem; /* 12px */ + } + } + @keyframes icon-300 { + 100% { + width: 1rem; /* 16px */ + height: 1rem; /* 16px */ + } + } + @keyframes icon-400 { + 100% { + width: 1.125rem; /* 18px */ + height: 1.125rem; /* 18px */ + } + } + @keyframes icon-500 { + 100% { + width: 1.25rem; /* 20px */ + height: 1.25rem; /* 20px */ + } + } + @keyframes icon-600 { + 100% { + width: 1.375rem; /* 22px */ + height: 1.375rem; /* 22px */ + } + } + @keyframes icon-700 { + 100% { + width: 1.5rem; /* 24px */ + height: 1.5rem; /* 24px */ + } + } + @keyframes icon-800 { + 100% { + width: 1.625rem; /* 26px */ + height: 1.625rem; /* 26px */ + } + } + @keyframes icon-900 { + 100% { + width: 1.75rem; /* 28px */ + height: 1.75rem; /* 28px */ + } + } +`})),define("consul-ui/templates/application",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"Srw5qTey",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n"],[1," "],[8,[30,1,["Announcer"]],null,[["@title"],["Consul"]],null],[1,"\\n\\n"],[41,[51,[28,[37,3],["CONSUL_V2_CATALOG_ENABLED"],null]],[[[41,[28,[37,5],["use acls"],null],[[[1," "],[1,[28,[35,6],null,[["class"],["has-acls"]]]],[1,"\\n"]],[]],null],[41,[28,[37,5],["use nspaces"],null],[[[1," "],[1,[28,[35,6],null,[["class"],["has-nspaces"]]]],[1,"\\n"]],[]],null],[41,[28,[37,5],["use partitions"],null],[[[1," "],[1,[28,[35,6],null,[["class"],["has-partitions"]]]],[1,"\\n"]],[]],null],[1,"\\n"],[1," "],[8,[39,7],null,[["@src","@onchange"],[[28,[37,8],["settings://consul:client"],null],[28,[37,9],["onClientChanged"],null]]],null],[1,"\\n\\n"],[1," "],[8,[39,7],null,[["@src"],[[28,[37,8],["settings://consul:theme"],null]]],[["default"],[[[[1,"\\n"],[42,[28,[37,11],[[30,2,["data"]]],null],null,[[[41,[28,[37,12],[[30,3],[28,[37,13],[[30,4],[28,[37,14],["color-scheme","contrast"],null]],null]],null],[[[1," "],[1,[28,[35,6],null,[["class"],[[28,[37,15],["prefers-",[30,4],"-",[30,3]],null]]]]],[1,"\\n"]],[]],null]],[3,4]],null],[1," "]],[2]]]]],[1,"\\n\\n"],[41,[28,[37,5],["use acls"],null],[[[1," "],[8,[39,7],null,[["@src","@onchange"],[[28,[37,8],["settings://consul:token"],null],[28,[37,16],[[30,0],[28,[37,17],[[33,18]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[]],null]],[]],null],[1,"\\n"],[41,[28,[37,12],[[28,[37,19],[[28,[37,3],["CONSUL_V2_CATALOG_ENABLED"],null]],null],[28,[37,20],[[30,1,["currentName"]],"oauth-provider-debug"],null]],null],[[[1,"\\n"],[41,[28,[37,21],[[30,1,["currentName"]],"index"],null],[[[1,"\\n"],[1," "],[1,[28,[35,22],[[28,[37,9],["replaceWith","dc.services.index",[28,[37,23],null,[["dc"],[[28,[37,3],["CONSUL_DATACENTER_LOCAL"],null]]]]],null]],null]],[1,"\\n"]],[]],[[[41,[28,[37,21],[[30,1,["currentName"]],"notfound"],null],[[[1," "],[8,[39,7],null,[["@src","@onchange"],[[28,[37,8],["/*/*/*/notfound/${path}",[28,[37,23],null,[["path"],[[30,1,["params","notfound"]]]]]],null],[28,[37,16],[[30,0],[28,[37,17],[[33,24]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[44,[[52,[28,[37,5],["use partitions"],null],[28,[37,26],[[30,1,["params","partition"]],[33,24,["partition"]],[33,18,["Partition"]],""],null],""],[52,[28,[37,5],["use nspaces"],null],[28,[37,26],[[30,1,["params","nspace"]],[33,24,["nspace"]],[33,18,["Namespace"]],""],null],""]],[[[1,"\\n"],[1," "],[8,[39,7],null,[["@src"],[[28,[37,8],["/*/*/*/datacenters"],null]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,26],[[52,[33,27,["dc"]],[28,[37,28],[0,[28,[37,29],["dc",[28,[37,23],null,[["Name"],[[33,24,["dc"]]]]]],null]],null]],[28,[37,28],[0,[28,[37,29],["dc",[28,[37,23],null,[["Name"],[[30,1,["params","dc"]]]]]],null]],null],[28,[37,23],null,[["Name"],[[28,[37,3],["CONSUL_DATACENTER_LOCAL"],null]]]]],null],[30,7,["data"]]],[[[41,[28,[37,12],[[28,[37,30],[[30,8,["Name","length"]],0],null],[30,9]],null],[[[1,"\\n"],[1," "],[8,[39,7],null,[["@src"],[[28,[37,8],["/${partition}/*/${dc}/datacenter-cache/${name}",[28,[37,23],null,[["dc","partition","name"],[[30,8,["Name"]],[30,5],[30,8,["Name"]]]]]],null]]],[["default"],[[[[1,"\\n"],[41,[30,10,["data"]],[[[1," "],[8,[39,31],[[24,1,"wrapper"]],[["@dcs","@dc","@partition","@nspace","@user","@onchange"],[[30,9],[30,10,["data"]],[30,5],[30,6],[28,[37,23],null,[["token"],[[33,18]]]],[28,[37,16],[[30,0],"reauthorize"],null]]],[["default"],[[[[1,"\\n\\n"],[41,[33,32],[[[1," "],[8,[39,33],null,[["@error","@login"],[[99,32,["@error"]],[30,11,["login","open"]]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,34],null,[["@name","@model"],["application",[28,[37,23],null,[["app","user","dc","dcs"],[[30,11],[28,[37,23],null,[["token"],[[33,18]]]],[30,10,["data"]],[30,9]]]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,36],null,null],null,null,null],[1,"\\n "]],[12]]]]],[1,"\\n\\n"],[1," "],[8,[39,37],[[24,0,"view-loader"]],null,null],[1,"\\n"]],[]]],[1,"\\n "]],[11]]]]],[1,"\\n"]],[]],null],[1," "]],[10]]]]],[1,"\\n"]],[]],null]],[8,9]]],[1," "]],[7]]]]],[1,"\\n"]],[5,6]]]],[]]]],[]],[[[1," "],[8,[39,34],null,[["@name","@model"],["application",[28,[37,23],null,[["user"],[[28,[37,23],null,[["token"],[[33,18]]]]]]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,36],null,null],null,null,null],[1,"\\n "]],[13]]]]],[1,"\\n"]],[]]]],[1]]]]]],["route","source","value","key","partition","nspace","dcs","dc","dcs","dc","consul","o","o"],false,["route","routeName","unless","env","if","can","document-attrs","data-source","uri","route-action","each","-each-in","and","includes","array","concat","action","mut","token","not","not-eq","eq","did-insert","hash","notfound","let","or","nofound","object-at","cached-model","gt","hashicorp-consul","error","app-error","outlet","component","-outlet","consul/loader"]]',moduleName:"consul-ui/templates/application.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/components/basic-dropdown-content",["exports","ember-basic-dropdown/templates/components/basic-dropdown-content"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/templates/components/basic-dropdown-optional-tag",["exports","ember-basic-dropdown/templates/components/basic-dropdown-optional-tag"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/templates/components/basic-dropdown-trigger",["exports","ember-basic-dropdown/templates/components/basic-dropdown-trigger"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/templates/components/basic-dropdown",["exports","ember-basic-dropdown/templates/components/basic-dropdown"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/templates/dc",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"ex21k2WB",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name","@model"],[[99,1,["@name"]],[30,1,["model"]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,4],null,null],null,null,null],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","o"],false,["route","routeName","outlet","component","-outlet"]]',moduleName:"consul-ui/templates/dc.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"QsSsujkj",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name","@model"],[[99,1,["@name"]],[30,1,["model"]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,4],null,null],null,null,null],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","o"],false,["route","routeName","outlet","component","-outlet"]]',moduleName:"consul-ui/templates/dc/acls.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/auth-methods/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"G0S4rRqt",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/auth-methods",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,8],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,9],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,11],[[33,12],"MethodName:asc"],null],[28,[37,13],[[30,0],[28,[37,14],[[33,12]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["kind","source","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,15],[28,[37,16],[[33,15],","],null],[27]],[28,[37,13],[[30,0],[28,[37,14],[[33,15]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change"],[[52,[33,17],[28,[37,16],[[33,17],","],null],[27]],[28,[37,13],[[30,0],[28,[37,14],[[33,17]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,18],[[33,19],[27]],null],[28,[37,16],[[33,19],","],null],[33,20]],[28,[37,13],[[30,0],[28,[37,14],[[33,19]],null]],[["value"],["target.selectedItems"]]],[33,20]]]]]]],[30,2,["data"]]],[[[1,"\\n\\n "],[8,[39,21],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Auth Methods"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,22],[[30,5,["length"]],0],null],[[[1," "],[8,[39,23],null,[["@search","@onsearch","@sort","@filter"],[[99,24,["@search"]],[28,[37,13],[[30,0],[28,[37,14],[[33,24]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@type","@sort","@filters","@search","@items"],["auth-method",[30,3,["value"]],[30,4],[99,24,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@items"],[[30,6,["items"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,28],["routes.dc.acls.auth-methods.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,28],["routes.dc.acls.auth-methods.index.empty.body"],[["items","htmlSafe"],[[30,5,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,29],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on auth methods",[29,[[28,[37,30],["CONSUL_DOCS_URL"],null],"/security/acl/auth-methods"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,29],null,[["@text","@href","@icon","@iconPosition","@size"],["Read the API Docs",[29,[[28,[37,30],["CONSUL_DOCS_API_URL"],null],"/acl/auth-methods.html"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","sort","filters","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","if","eq","consul/acl/disabled","app-error","let","or","sortBy","action","mut","kind","split","source","not-eq","searchproperty","searchProperties","app-view","gt","consul/auth-method/search-bar","search","data-collection","consul/auth-method/list","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/acls/auth-methods/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/auth-methods/show",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"wumVrj9i",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/auth-method/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","id"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,8],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,9],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]]],[[[1," "],[8,[39,11],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,12],["dc.acls.auth-methods"],null]],[12],[1,"All Auth Methods"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[30,3,["Name"]]]],null],[1,"\\n "],[13],[1,"\\n "],[8,[39,13],null,[["@item"],[[30,3]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["nav"]],[["default"],[[[[1,"\\n "],[8,[39,14],null,[["@items"],[[28,[37,15],[[28,[37,16],[[28,[37,4],null,[["label","href","selected"],["General info",[28,[37,12],["dc.acls.auth-methods.show.auth-method"],null],[28,[37,17],["dc.acls.auth-methods.show.auth-method"],null]]]],[52,[28,[37,18],["use nspaces"],null],[28,[37,4],null,[["label","href","selected"],["Namespace rules",[28,[37,12],["dc.acls.auth-methods.show.nspace-rules"],null],[28,[37,17],["dc.acls.auth-methods.show.nspace-rules"],null]]]],""],[28,[37,4],null,[["label","href","selected"],["Binding rules",[28,[37,12],["dc.acls.auth-methods.show.binding-rules"],null],[28,[37,17],["dc.acls.auth-methods.show.binding-rules"],null]]]]],null]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,19],null,[["@name","@model"],[[99,1,["@name"]],[28,[37,4],null,[["item"],[[30,3]]]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,21],null,null],null,null,null],[1,"\\n "]],[4]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","item","o"],false,["route","routeName","data-loader","uri","hash","block-slot","if","eq","consul/acl/disabled","app-error","let","app-view","href-to","consul/auth-method/type","tab-nav","compact","array","is-href","can","outlet","component","-outlet"]]',moduleName:"consul-ui/templates/dc/acls/auth-methods/show.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/auth-methods/show/auth-method",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"AwEeTFr9",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n "],[8,[39,2],null,[["@item"],[[30,1,["model","item"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route"],false,["route","routeName","consul/auth-method/view"]]',moduleName:"consul-ui/templates/dc/acls/auth-methods/show/auth-method.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/auth-methods/show/binding-rules",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"lp1F+P1r",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/binding-rules/for-auth-method/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","id"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]]],[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,9],[[30,3,["length"]],0],null],[[[1," "],[10,2],[12],[1,"\\n Binding rules allow an operator to express a systematic way of automatically linking roles and service identities to newly created tokens without operator intervention.\\n "],[13],[1,"\\n "],[10,2],[12],[1,"\\n Successful authentication with an auth method returns a set of trusted identity attributes corresponding to the authenticated identity. Those attributes are matched against all configured binding rules for that auth method to determine what privileges to grant the Consul ACL token it will ultimately create.\\n "],[13],[1,"\\n "],[10,"hr"],[12],[13],[1,"\\n"],[42,[28,[37,11],[[28,[37,11],[[30,3]],null]],null],null,[[[1," "],[8,[39,12],null,[["@item"],[[30,4]]],null],[1,"\\n "],[10,"hr"],[12],[13],[1,"\\n"]],[4]],null]],[]],[[[1," "],[8,[39,13],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,14],["routes.dc.acls.auth-methods.show.binding-rules.index.empty.header"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,14],["routes.dc.acls.auth-methods.show.binding-rules.index.empty.body"],[["htmlSafe"],[true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[15,6,[29,[[28,[37,15],["CONSUL_DOCS_API_URL"],null],"/acl/binding-rules"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"Read the documentation"],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[3]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","items","item"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","if","gt","each","-track-array","consul/auth-method/binding-list","empty-state","t","env"]]',moduleName:"consul-ui/templates/dc/acls/auth-methods/show/binding-rules.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/auth-methods/show/nspace-rules",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"B9VyTw0K",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[30,1,["model","item"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,4],[[30,2,["NamespaceRules","length"]],0],null],[[[1," "],[10,2],[12],[1,"\\n A set of rules that can control which namespace tokens created via this auth method will be created within. Unlike binding rules, the first matching namespace rule wins.\\n "],[13],[1,"\\n "],[8,[39,5],null,[["@items"],[[30,2,["NamespaceRules"]]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,6],null,null,[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,8],[[28,[37,9],[[30,1,["t"]],"empty.header"],null]],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,8],[[28,[37,9],[[30,1,["t"]],"empty.body",[28,[37,10],null,[["htmlSafe"],[true]]]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"docs-link"],[12],[1,"\\n "],[10,3],[15,6,[29,[[28,[37,11],["CONSUL_DOCS_API_URL"],null],"/acl/auth-methods#namespacerules"]]],[14,"rel","noopener noreferrer"],[14,"target","_blank"],[12],[1,"Read the documentation"],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[2]]]],[1]]]]],[1,"\\n"]],["route","item"],false,["route","routeName","let","if","gt","consul/auth-method/nspace-list","empty-state","block-slot","compute","fn","hash","env"]]',moduleName:"consul-ui/templates/dc/acls/auth-methods/show/nspace-rules.hbs",isStrictMode:!1}) +e.default=n})) +define("consul-ui/templates/dc/acls/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"u49Giiy6",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["replaceWith","dc.acls.tokens"],null]],null]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route"],false,["route","routeName","did-insert","route-action"]]',moduleName:"consul-ui/templates/dc/acls/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/policies/-form",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"HeHpiPG6",block:'[[[1,"\\n"],[10,"form"],[12],[1,"\\n "],[8,[39,0],null,[["@form","@partition","@nspace","@item"],[[99,1,["@form"]],[99,2,["@partition"]],[99,3,["@nspace"]],[99,4,["@item"]]]],[["default"],[[[[1,"\\n"],[1," "],[8,[39,5],null,[["@name"],["template"]],null],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[28,[37,7],[[33,8]],null],[[[1," "],[8,[39,9],null,[["@src","@onchange"],[[28,[37,10],["/${partition}/${nspace}/${dc}/tokens/for-policy/${id}",[28,[37,11],null,[["partition","nspace","dc","id"],[[33,2],[33,3],[33,12],[28,[37,13],[[33,14],""],null]]]]],null],[28,[37,15],[[30,0],[28,[37,16],[[33,17]],null]],[["value"],["data"]]]]],null],[1,"\\n"],[41,[28,[37,18],[[33,17,["length"]],0],null],[[[1," "],[8,[39,19],null,[["@caption","@items"],["Applied to the following tokens:",[99,17,["@items"]]]],null],[1,"\\n"]],[]],null]],[]],null],[1," "],[10,0],[12],[1,"\\n "],[8,[39,20],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,21],[[33,8],[28,[37,22],["create tokens"],null]],null],[[[1," "],[8,[39,23],[[16,"disabled",[52,[28,[37,13],[[33,4,["isPristine"]],[33,4,["isInvalid"]],[28,[37,24],[[33,4,["Name"]],""],null]],null],"disabled"]],[24,4,"submit"],[4,[38,25],["click",[28,[37,26],["create",[33,4]],null]],null]],[["@text"],["Save"]],null],[1,"\\n"]],[]],[[[41,[28,[37,22],["write policy"],[["item"],[[33,4]]]],[[[1," "],[8,[39,23],[[16,"disabled",[52,[33,4,["isInvalid"]],"disabled"]],[24,4,"submit"],[4,[38,25],["click",[28,[37,26],["update",[33,4]],null]],null]],[["@text"],["Save"]],null],[1,"\\n"]],[]],null]],[]]],[1," "],[8,[39,23],[[24,4,"reset"],[4,[38,15],[[30,0],"cancel",[33,4]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"],[41,[28,[37,21],[[28,[37,7],[[33,8]],null],[28,[37,22],["delete policy"],[["item"],[[33,4]]]]],null],[[[1," "],[8,[39,27],null,[["@message"],["Are you sure you want to delete this Policy?"]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,23],[[4,[38,15],[[30,0],[30,1],"delete",[33,4]],null]],[["@text","@color"],["Delete","critical"]],null],[1,"\\n "]],[1]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n"],[41,[28,[37,18],[[33,17,["length"]],0],null],[[[1," "],[8,[39,28],null,[["@onclose","@open","@aria"],[[28,[37,15],[[30,0],[30,3]],null],true,[28,[37,11],null,[["label"],["Policy in Use"]]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"Policy in Use"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n This Policy is currently in use. If you choose to delete this Policy, it will be removed from the\\n following "],[10,"strong"],[12],[1,[33,17,["length"]]],[1," Tokens"],[13],[1,":\\n "],[13],[1,"\\n "],[8,[39,19],null,[["@items","@target"],[[99,17,["@items"]],"_blank"]],null],[1,"\\n "],[10,2],[12],[1,"\\n This action cannot be undone. "],[1,[30,4]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,20],null,null,[["default"],[[[[1,"\\n "],[8,[39,23],[[4,[38,15],[[30,0],[30,2]],null]],[["@text","@color"],["Yes, Delete","critical"]],null],[1,"\\n "],[8,[39,23],[[4,[38,15],[[30,0],[30,5]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,29],null,[["@message","@execute","@cancel"],[[30,4],[30,2],[30,3]]],null],[1,"\\n"]],[]]],[1," "]],[2,3,4]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["confirm","execute","cancel","message","close"],false,["policy-form","form","partition","nspace","item","block-slot","if","not","create","data-source","uri","hash","dc","or","id","action","mut","items","gt","token-list","hds/button-set","and","can","hds/button","eq","on","route-action","confirmation-dialog","modal-dialog","delete-confirmation"]]',moduleName:"consul-ui/templates/dc/acls/policies/-form.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/policies/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"ZeBYu7Wq",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/policy/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","id"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,8],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,9],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,10],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[28,[37,5],[[30,1,["params","id"]],""],null],[30,2,["data"]],[30,2,["data","isNew"]]],[[[1," "],[8,[39,12],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,13],["dc.acls.policies"],null]],[12],[1,"All Policies"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n"],[41,[30,8],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["New Policy"]],null],[1,"\\n"]],[]],[[[41,[28,[37,14],["write policy"],[["item"],[[30,7]]]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["Edit Policy"]],null],[1,"\\n"]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["View Policy"]],null],[1,"\\n"]],[]]]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[41,[28,[37,15],[[30,8]],null],[[[1," "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Policy ID"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,16],null,[["@value","@name"],[[30,7,["ID"]],"Policy ID"]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[28,[37,5],[[28,[37,8],[[28,[37,17],[[30,7]],null],"policy-management"],null],[28,[37,8],[[28,[37,17],[[30,7]],null],"read-only"],null]],null],[[[1," "],[8,[39,18],[[24,0,"mb-3 mt-2"]],[["@type","@icon"],["inline","star-fill"]],[["default"],[[[[1,"\\n "],[8,[30,9,["Title"]],null,null,[["default"],[[[[1,"Built-in policy"]],[]]]]],[1,"\\n "],[8,[30,9,["Description"]],null,null,[["default"],[[[[1,"This policy is built into Consul\'s ACL system. You can use this special policy by adding it to a token. This policy is not editable or removable, but can be ignored by not applying it to any tokens.\\n "]],[]]]]],[1,"\\n "],[8,[30,9,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition"],["Learn more",[29,[[28,[37,19],["CONSUL_DOCS_URL"],null],"/guides/acl.html#builtin-policies"]],"docs-link","trailing"]],null],[1,"\\n "]],[9]]]]],[1,"\\n "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Name"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,7,["Name"]]],[13],[1,"\\n "],[10,"dt"],[12],[1,"Valid Datacenters"],[13],[1,"\\n "],[10,"dd"],[12],[1,[28,[35,20],[", ",[28,[37,21],[[30,7]],null]],null]],[13],[1,"\\n "],[10,"dt"],[12],[1,"Description"],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,7,["Description"]]],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,22],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/tokens/for-policy/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,4],[30,5],[30,3],[30,6]]]]],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,23],[[30,10,["data","length"]],0],null],[[[1," "],[8,[39,24],null,[["@caption","@items"],["Applied to the following tokens:",[30,10,["data"]]]],null],[1,"\\n"]],[]],null],[1," "]],[10]]]]],[1,"\\n"]],[]],[[[1," "],[19,"dc/acls/policies/form",[1,2,3,4,5,6,7,8]],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5,6,7,8]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","dc","partition","nspace","id","item","create","A","loader"],true,["route","routeName","data-loader","uri","hash","or","block-slot","if","eq","consul/acl/disabled","app-error","let","app-view","href-to","can","not","copyable-code","policy/typeof","hds/alert","env","join","policy/datacenters","data-source","gt","token-list","partial"]]',moduleName:"consul-ui/templates/dc/acls/policies/edit.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/policies/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"fHN/RQtj",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/policies",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,8],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,9],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,11],[[33,12],"Name:asc"],null],[28,[37,13],[[30,0],[28,[37,14],[[33,12]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["kind","datacenter","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,15],[28,[37,16],[[33,15],","],null],[27]],[28,[37,13],[[30,0],[28,[37,14],[[33,15]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change"],[[52,[33,17],[28,[37,16],[[33,17],","],null],[27]],[28,[37,13],[[30,0],[28,[37,14],[[33,17]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,18],[[33,19],[27]],null],[28,[37,16],[[33,19],","],null],[33,20]],[28,[37,13],[[30,0],[28,[37,14],[[33,19]],null]],[["value"],["target.selectedItems"]]],[33,20]]]]]]],[30,2,["data"]]],[[[1," "],[8,[39,21],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Policies"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,22],["create policies"],null],[[[1," "],[8,[39,23],null,[["@text","@route"],["Create","dc.acls.policies.create"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,24],[[30,5,["length"]],0],null],[[[1," "],[8,[39,25],null,[["@partition","@search","@onsearch","@sort","@filter"],[[30,1,["params","partition"]],[99,26,["@search"]],[28,[37,13],[[30,0],[28,[37,14],[[33,26]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@type","@sort","@filters","@search","@items"],["policy",[30,3,["value"]],[30,4],[99,26,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@items","@ondelete"],[[30,6,["items"]],[28,[37,29],["delete"],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,30],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,31],["routes.dc.acls.policies.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,31],["routes.dc.acls.policies.index.empty.body"],[["items","htmlSafe"],[[30,5,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,32],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on policies",[29,[[28,[37,33],["CONSUL_DOCS_URL"],null],"/commands/acl/policy"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,32],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,33],["CONSUL_LEARN_URL"],null],"/consul/security-networking/managing-acl-policies"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","sort","filters","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","if","eq","consul/acl/disabled","app-error","let","or","sortBy","action","mut","kind","split","datacenter","not-eq","searchproperty","searchProperties","app-view","can","hds/button","gt","consul/policy/search-bar","search","data-collection","consul/policy/list","route-action","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/acls/policies/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/roles/-form",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"6qtq9TRB",block:'[[[1,"\\n"],[10,"form"],[12],[1,"\\n "],[8,[39,0],null,[["@form","@item","@dc","@nspace","@partition"],[[99,1,["@form"]],[99,2,["@item"]],[99,3,["@dc"]],[99,4,["@nspace"]],[99,5,["@partition"]]]],null],[1,"\\n"],[41,[28,[37,7],[[33,8]],null],[[[1," "],[8,[39,9],null,[["@src"],[[28,[37,10],["/${partition}/${nspace}/${dc}/tokens/for-role/${id}",[28,[37,11],null,[["partition","nspace","dc","id"],[[33,5],[33,4],[33,3],[52,[33,2],[33,2,["ID"]],""]]]]],null]]],[["default"],[[[[1,"\\n"],[41,[28,[37,12],[[30,1,["data","length"]],0],null],[[[1," "],[10,"h2"],[12],[1,"Where is this role used?"],[13],[1,"\\n "],[10,2],[12],[1,"\\n We\'re only able to show information for the primary datacenter and the current datacenter. This list may not\\n show every case where this role is applied.\\n "],[13],[1,"\\n "],[8,[39,13],null,[["@caption","@items"],["Tokens",[30,1,["data"]]]],null],[1,"\\n"]],[]],null],[1," "]],[1]]]]],[1,"\\n"]],[]],null],[1," "],[10,0],[12],[1,"\\n "],[8,[39,14],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,15],[[33,8],[28,[37,16],["create roles"],null]],null],[[[1," "],[8,[39,17],[[16,"disabled",[28,[37,18],[[33,2,["isPristine"]],[33,2,["isInvalid"]],[28,[37,19],[[33,2,["Name"]],""],null]],null]],[24,4,"submit"],[4,[38,20],["click",[28,[37,21],["create",[33,2]],null]],null]],[["@text"],["Save"]],null],[1,"\\n"]],[]],[[[41,[28,[37,16],["write role"],[["item"],[[33,2]]]],[[[1," "],[8,[39,17],[[16,"disabled",[33,2,["isInvalid"]]],[24,4,"submit"],[4,[38,20],["click",[28,[37,21],["update",[33,2]],null]],null]],[["@text"],["Save"]],null],[1,"\\n"]],[]],null]],[]]],[1," "],[8,[39,17],[[24,4,"reset"],[4,[38,22],[[30,0],"cancel",[33,2]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n\\n"],[41,[28,[37,15],[[28,[37,7],[[33,8]],null],[28,[37,16],["delete role"],[["item"],[[33,2]]]]],null],[[[1," "],[8,[39,23],null,[["@message"],["Are you sure you want to delete this Role?"]],[["default"],[[[[1,"\\n "],[8,[39,24],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,17],[[4,[38,22],[[30,0],[30,2],"delete",[33,2]],null]],[["@text","@color"],["Delete","critical"]],null],[1,"\\n "]],[2]]]]],[1,"\\n "],[8,[39,24],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n"],[41,[28,[37,12],[[33,25,["length"]],0],null],[[[1," "],[8,[39,26],null,[["@onclose","@aria"],[[28,[37,22],[[30,0],[30,4]],null],[28,[37,11],null,[["label"],["Role in Use"]]]]],[["default"],[[[[1,"\\n "],[8,[39,24],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"Role in Use"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,24],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n This Role is currently in use. If you choose to delete this Role, it will be removed from the\\n following "],[10,"strong"],[12],[1,[33,25,["length"]]],[1," Tokens"],[13],[1,":\\n "],[13],[1,"\\n "],[8,[39,13],null,[["@items","@target"],[[99,25,["@items"]],"_blank"]],null],[1,"\\n "],[10,2],[12],[1,"\\n This action cannot be undone. "],[1,[30,5]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,24],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,14],null,null,[["default"],[[[[1,"\\n "],[8,[39,17],[[4,[38,22],[[30,0],[30,3]],null]],[["@text","@color"],["Yes, Delete","critical"]],null],[1,"\\n "],[8,[39,17],[[4,[38,22],[[30,0],[30,6]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,27],null,[["@message","@execute","@cancel"],[[30,5],[30,3],[30,4]]],null],[1,"\\n"]],[]]],[1," "]],[3,4,5]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["loader","confirm","execute","cancel","message","close"],false,["role-form","form","item","dc","nspace","partition","if","not","create","data-source","uri","hash","gt","token-list","hds/button-set","and","can","hds/button","or","eq","on","route-action","action","confirmation-dialog","block-slot","items","modal-dialog","delete-confirmation"]]',moduleName:"consul-ui/templates/dc/acls/roles/-form.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/roles/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"B1T3t9iM",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/role/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","id"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,8],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,9],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,10],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,2,["data"]],[30,2,["data","isNew"]]],[[[1," "],[8,[39,12],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,13],["dc.acls.roles"],null]],[12],[1,"All Roles"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n"],[41,[30,7],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["New Role"]],null],[1,"\\n"]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["Edit Role"]],null],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[41,[28,[37,14],[[30,7]],null],[[[1," "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Role ID"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,15],null,[["@value","@name"],[[30,6,["ID"]],"Role ID"]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[19,"dc/acls/roles/form",[1,2,3,4,5,6,7]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5,6,7]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","dc","partition","nspace","item","create"],true,["route","routeName","data-loader","uri","hash","or","block-slot","if","eq","consul/acl/disabled","app-error","let","app-view","href-to","not","copyable-code","partial"]]',moduleName:"consul-ui/templates/dc/acls/roles/edit.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/roles/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"viN7dfZy",block:'[[[1,"\\n"],[8,[39,0],null,[["@name","@title"],[[99,1,["@name"]],"Roles"]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/roles",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,8],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,9],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,11],[[33,12],"Name:asc"],null],[28,[37,13],[[30,0],[28,[37,14],[[33,12]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["searchproperty"],[[28,[37,4],null,[["value","change","default"],[[52,[28,[37,15],[[33,16],[27]],null],[28,[37,17],[[33,16],","],null],[33,18]],[28,[37,13],[[30,0],[28,[37,14],[[33,16]],null]],[["value"],["target.selectedItems"]]],[33,18]]]]]]],[30,2,["data"]]],[[[1,"\\n "],[8,[39,19],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Roles"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,20],["create roles"],null],[[[1," "],[8,[39,21],null,[["@text","@route"],["Create","dc.acls.roles.create"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,22],[[30,5,["length"]],0],null],[[[1," "],[8,[39,23],null,[["@search","@onsearch","@sort","@filter"],[[99,24,["@search"]],[28,[37,13],[[30,0],[28,[37,14],[[33,24]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@type","@sort","@filters","@search","@items"],["role",[30,3,["value"]],[30,4],[99,24,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@items","@ondelete"],[[30,6,["items"]],[28,[37,27],["delete"],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,29],["routes.dc.acls.roles.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,29],["routes.dc.acls.roles.index.empty.body"],[["items","htmlSafe"],[[30,5,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,30],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on roles",[29,[[28,[37,31],["CONSUL_DOCS_URL"],null],"/commands/acl/role"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,30],null,[["@text","@href","@icon","@iconPosition","@size"],["Read the API Docs",[29,[[28,[37,31],["CONSUL_DOCS_API_URL"],null],"/acl/roles.html"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","sort","filters","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","if","eq","consul/acl/disabled","app-error","let","or","sortBy","action","mut","not-eq","searchproperty","split","searchProperties","app-view","can","hds/button","gt","consul/role/search-bar","search","data-collection","consul/role/list","route-action","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/acls/roles/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/tokens/-fieldsets-legacy",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"YGXEadog",block:'[[[1,"\\n "],[10,"fieldset"],[15,"disabled",[52,[28,[37,1],[[28,[37,2],["write token"],[["item"],[[33,3]]]]],null],"disabled"]],[12],[1,"\\n "],[10,"label"],[15,0,[29,["type-text",[52,[33,3,["error","Name"]]," has-error"]]]],[12],[1,"\\n "],[10,1],[12],[1,"Name"],[13],[1,"\\n "],[8,[39,4],null,[["@value","@name","@autofocus"],[[33,3,["Description"]],"name","autofocus"]],null],[1,"\\n "],[13],[1,"\\n"],[41,false,[[[1," "],[10,0],[14,"role","radiogroup"],[15,0,[52,[33,3,["error","Type"]]," has-error"]],[12],[1,"\\n"],[42,[28,[37,6],[[28,[37,6],[[28,[37,7],["management","client"],null]],null]],null],null,[[[1," "],[10,"label"],[12],[1,"\\n "],[10,1],[12],[1,[28,[35,8],[[30,1]],null]],[13],[1,"\\n "],[10,"input"],[14,3,"Type"],[15,2,[29,[[30,1]]]],[15,"checked",[52,[28,[37,9],[[33,3,["Type"]],[30,1]],null],"checked"]],[15,"onchange",[28,[37,10],[[30,0],"change"],null]],[14,4,"radio"],[12],[13],[1,"\\n "],[13],[1,"\\n"]],[1]],null],[1," "],[13],[1,"\\n"]],[]],null],[1," "],[10,"label"],[14,0,"type-text"],[12],[1,"\\n "],[8,[39,11],null,[["@class","@name","@syntax","@value","@onkeyup"],[[52,[33,3,["error","Rules"]],"error"],"Rules","hcl",[33,3,["Rules"]],[28,[37,10],[[30,0],"change","Rules"],null]]],[["label"],[[[[1,"\\n Rules "],[10,3],[15,6,[29,[[28,[37,12],["CONSUL_DOCS_URL"],null],"/guides/acl.html#rule-specification"]]],[14,"rel","help noopener noreferrer"],[14,"target","_blank"],[12],[1,"(HCL Format)"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[41,[33,13],[[[1," "],[10,"label"],[14,0,"type-text"],[12],[1,"\\n "],[10,1],[12],[1,"ID"],[13],[1,"\\n "],[8,[39,4],null,[["@value"],[[33,3,["ID"]]]],null],[1,"\\n "],[10,"em"],[12],[1,"We\'ll generate a UUID if this field is left empty."],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n\\n"]],["type"],false,["if","not","can","item","input","each","-track-array","array","capitalize","eq","action","code-editor","env","create"]]',moduleName:"consul-ui/templates/dc/acls/tokens/-fieldsets-legacy.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/tokens/-fieldsets",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"MnuX4JE7",block:'[[[1,"\\n"],[10,"fieldset"],[15,"disabled",[52,[28,[37,1],[[28,[37,2],["write token"],[["item"],[[33,3]]]]],null],"disabled"]],[12],[1,"\\n"],[41,[33,4],[[[1," "],[10,0],[14,0,"type-toggle"],[12],[1,"\\n "],[10,"label"],[12],[1,"\\n "],[10,"input"],[14,3,"Local"],[15,"checked",[52,[33,5],"checked"]],[15,"onchange",[28,[37,6],[[30,0],"change"],null]],[14,4,"checkbox"],[12],[13],[1,"\\n "],[10,1],[12],[1,"Restrict this token to a local datacenter?"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"em"],[12],[1,"Local tokens get set in the Raft store of the local DC and do not ever get transmitted to the primary DC or replicated to any other DC."],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[10,"label"],[14,0,"type-text validate-optional"],[12],[1,"\\n "],[10,1],[12],[1,"Description (Optional)"],[13],[1,"\\n "],[10,"textarea"],[14,3,"Description"],[15,"oninput",[28,[37,6],[[30,0],"change"],null]],[12],[1,[33,3,["Description"]]],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"],[10,"fieldset"],[14,1,"roles"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Roles"],[13],[1,"\\n "],[8,[39,7],null,[["@disabled","@dc","@partition","@nspace","@items"],[[28,[37,1],[[28,[37,2],["write token"],[["item"],[[33,3]]]]],null],[99,8,["@dc"]],[99,9,["@partition"]],[99,10,["@nspace"]],[33,3,["Roles"]]]],null],[1,"\\n"],[13],[1,"\\n"],[10,"fieldset"],[14,1,"policies"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Policies"],[13],[1,"\\n "],[8,[39,11],null,[["@disabled","@dc","@partition","@nspace","@items"],[[28,[37,1],[[28,[37,2],["write token"],[["item"],[[33,3]]]]],null],[99,8,["@dc"]],[99,9,["@partition"]],[99,10,["@nspace"]],[33,3,["Policies"]]]],null],[1,"\\n"],[13],[1,"\\n"]],[],false,["if","not","can","item","create","Local","action","role-selector","dc","partition","nspace","policy-selector"]]',moduleName:"consul-ui/templates/dc/acls/tokens/-fieldsets.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/tokens/-form",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"m4QMWXr7",block:'[[[1,"\\n"],[10,"form"],[12],[1,"\\n"],[41,[28,[37,1],[[28,[37,2],[[33,3]],null]],null],[[[1," "],[19,"dc/acls/tokens/fieldsets",[]],[1,"\\n"]],[]],[[[1," "],[19,"dc/acls/tokens/fieldsets-legacy",[]],[1,"\\n"]],[]]],[1," "],[10,0],[12],[1,"\\n "],[8,[39,5],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,6],[[33,7],[28,[37,8],["create tokens"],null]],null],[[[1," "],[8,[39,9],[[16,"disabled",[52,[28,[37,10],[[28,[37,6],[[28,[37,2],[[33,3]],null],[33,3,["isPristine"]]],null],[33,3,["isInvalid"]]],null],"disabled"]],[24,4,"submit"],[4,[38,11],["click",[28,[37,12],["create",[33,3]],null]],null]],[["@text"],["Save"]],null],[1,"\\n"]],[]],[[[41,[28,[37,8],["write token"],[["item"],[[33,3]]]],[[[1," "],[8,[39,9],[[16,"disabled",[52,[33,3,["isInvalid"]],"disabled"]],[24,4,"submit"],[4,[38,11],["click",[28,[37,12],["update",[33,3]],null]],null]],[["@text"],["Save"]],null],[1,"\\n"]],[]],null]],[]]],[1," "],[8,[39,9],[[24,4,"reset"],[4,[38,13],[[30,0],"cancel",[33,3]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n"],[41,[28,[37,6],[[28,[37,1],[[33,7]],null],[28,[37,8],["delete token"],[["item","token"],[[33,3],[33,14]]]]],null],[[[1," "],[8,[39,15],null,[["@message"],["Are you sure you want to delete this Token?"]],[["default"],[[[[1,"\\n "],[8,[39,16],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,9],[[4,[38,13],[[30,0],[30,1],"delete",[33,3]],null]],[["@text","@color"],["Delete","critical"]],null],[1,"\\n "]],[1]]]]],[1,"\\n "],[8,[39,16],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[8,[39,17],null,[["@message","@execute","@cancel"],[[30,4],[30,2],[30,3]]],null],[1,"\\n "]],[2,3,4]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],["confirm","execute","cancel","message"],true,["if","not","token/is-legacy","item","partial","hds/button-set","and","create","can","hds/button","or","on","route-action","action","token","confirmation-dialog","block-slot","delete-confirmation"]]',moduleName:"consul-ui/templates/dc/acls/tokens/-form.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/tokens/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"YoJWnwjp",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/token/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","id"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,8],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,9],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,10],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,2,["data"]],[30,2,["data","isNew"]]],[[[1," "],[8,[39,12],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,13],["dc.acls.tokens"],null]],[12],[1,"All Tokens"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n"],[41,[30,7],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["New Token"]],null],[1,"\\n"]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["Edit Token"]],null],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,14],[[30,7]],null],[[[1," "],[8,[39,15],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,16],[[30,6,["AccessorID"]],[33,17,["AccessorID"]]],null],[[[1," "],[8,[39,18],null,[["@message"],["Are you sure you want to use this ACL token?"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["action"]],[["default"],[[[[1,"\\n "],[8,[39,19],[[4,[38,20],[[30,0],[30,8],"use",[30,6]],null]],[["@text","@color"],["Use","secondary"]],null],[1,"\\n "]],[8]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["dialog"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[30,11]],[1,"\\n "],[13],[1,"\\n "],[8,[39,15],null,null,[["default"],[[[[1,"\\n "],[8,[39,19],[[4,[38,20],[[30,0],[30,9]],null]],[["@text","@color"],["Confirm Use","critical"]],null],[1,"\\n "],[8,[39,19],[[4,[38,20],[[30,0],[30,10]],null]],[["@text","@color"],["Cancel","secondary"]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[9,10,11]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[41,[28,[37,21],["duplicate token"],[["item"],[[30,6]]]],[[[1," "],[8,[39,19],[[4,[38,20],[[30,0],"clone",[30,6]],null]],[["@text","@color"],["Duplicate","secondary"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[41,[28,[37,22],[[30,6]],null],[[[1," "],[8,[39,23],[[24,0,"mb-6"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,12,["Title"]],null,null,[["default"],[[[[1,"Update"]],[]]]]],[1,"\\n "],[8,[30,12,["Description"]],null,null,[["default"],[[[[1,"We have upgraded our ACL system by allowing you to create reusable policies which you can then apply to tokens. Don\'t worry, even though this token was written in the old style, it is still valid. However, we do recommend upgrading your old tokens to the new style."]],[]]]]],[1,"\\n "],[8,[30,12,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition"],["Learn more",[29,[[28,[37,24],["CONSUL_DOCS_URL"],null],"/guides/acl-migrate-tokens.html"]],"docs-link","trailing"]],null],[1,"\\n "]],[12]]]]],[1,"\\n"]],[]],null],[41,[28,[37,14],[[30,7]],null],[[[1," "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"AccessorID"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,25],null,[["@value","@name"],[[30,6,["AccessorID"]],"AccessorID"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,"Token"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[8,[39,25],null,[["@obfuscated","@value","@name"],[true,[30,6,["SecretID"]],"Token"]],null],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,26],[[28,[37,14],[[28,[37,22],[[30,6]],null]],null],[28,[37,14],[[30,7]],null]],null],[[[1," "],[10,"dt"],[12],[1,"Scope"],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[52,[30,6,["Local"]],"local","global"]],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[19,"dc/acls/tokens/form",[1,2,3,4,5,6,7]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5,6,7]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","dc","partition","nspace","item","create","confirm","execute","cancel","message","A"],true,["route","routeName","data-loader","uri","hash","or","block-slot","if","eq","consul/acl/disabled","app-error","let","app-view","href-to","not","hds/button-set","not-eq","token","confirmation-dialog","hds/button","action","can","token/is-legacy","hds/alert","env","copyable-code","and","partial"]]',moduleName:"consul-ui/templates/dc/acls/tokens/edit.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/acls/tokens/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"nM/xLeTH",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/tokens",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n"],[41,[28,[37,7],[[30,2,["error","status"]],"401"],null],[[[1," "],[8,[39,8],null,null,null],[1,"\\n"]],[]],[[[1," "],[8,[39,9],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n"]],[]]],[1," "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,11],[[33,12],"CreateTime:desc"],null],[28,[37,13],[[30,0],[28,[37,14],[[33,12]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["kind","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,15],[28,[37,16],[[33,15],","],null],[27]],[28,[37,13],[[30,0],[28,[37,14],[[33,15]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,17],[[33,18],[27]],null],[28,[37,16],[[33,18],","],null],[33,19]],[28,[37,13],[[30,0],[28,[37,14],[[33,18]],null]],[["value"],["target.selectedItems"]]],[33,19]]]]]]],[30,2,["data"]]],[[[1,"\\n "],[8,[39,20],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Tokens"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,21],["create tokens"],null],[[[1," "],[8,[39,22],null,[["@text","@route"],["Create","dc.acls.tokens.create"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,23],[[30,5,["length"]],0],null],[[[1," "],[8,[39,24],null,[["@search","@onsearch","@sort","@filter"],[[99,25,["@search"]],[28,[37,13],[[30,0],[28,[37,14],[[33,25]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[41,[28,[37,26],[[30,5]],null],[[[1," "],[8,[39,27],[[24,0,"mb-3 mt-3"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Update"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"We have upgraded our ACL System to allow the creation of reusable policies that can be applied to tokens. Read more about the changes and how to upgrade legacy tokens."]],[]]]]],[1,"\\n "],[8,[30,6,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition"],["Learn more",[29,[[28,[37,28],["CONSUL_DOCS_URL"],null],"/guides/acl-migrate-tokens.html"]],"docs-link","trailing"]],null],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,29],null,[["@type","@sort","@filters","@search","@items"],["token",[30,3,["value"]],[30,4],[99,25,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,7,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,30],null,[["@items","@token","@onuse","@ondelete","@onlogout","@onclone"],[[30,7,["items"]],[30,1,["model","user","token"]],[28,[37,31],["use"],null],[28,[37,31],["delete"],null],[28,[37,31],["logout"],null],[28,[37,31],["clone"],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,7,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,32],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,33],["routes.dc.acls.tokens.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,33],["routes.dc.acls.tokens.index.empty.body"],[["items","htmlSafe"],[[30,5,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","sort","filters","items","A","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","if","eq","consul/acl/disabled","app-error","let","or","sortBy","action","mut","kind","split","not-eq","searchproperty","searchProperties","app-view","can","hds/button","gt","consul/token/search-bar","search","token/is-legacy","hds/alert","env","data-collection","consul/token/list","route-action","empty-state","t"]]',moduleName:"consul-ui/templates/dc/acls/tokens/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/intentions/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"eGHzHT1F",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/intention/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","intention_id"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]],[28,[37,9],[[28,[37,10],["write intention"],[["item"],[[30,2,["data"]]]]]],null]],[[[1," "],[8,[39,11],null,null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,12],["dc.intentions"],null]],[12],[1,"All Intentions"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n"],[41,[28,[37,9],[[30,4]],null],[[[41,[30,3,["ID"]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["Edit Intention"]],null],[1,"\\n"]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["New Intention"]],null],[1,"\\n"]],[]]]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["View Intention"]],null],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,14],null,[["@readonly","@item","@dc","@nspace","@partition","@onsubmit"],[[30,4],[30,3],[30,1,["model","dc"]],[30,1,["params","nspace"]],[30,1,["params","partition"]],[28,[37,15],["transitionTo","dc.intentions.index",[28,[37,4],null,[["dc"],[[30,1,["params","dc"]]]]]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4]]],[1," "]],[]]]]],[1,"\\n"]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","item","readOnly"],false,["route","routeName","data-loader","uri","hash","or","block-slot","app-error","let","not","can","app-view","href-to","if","consul/intention/form","route-action"]]',moduleName:"consul-ui/templates/dc/intentions/edit.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/intentions/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"uhPF61cB",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/intentions",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Action:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["access","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,15],[[33,16],[27]],null],[28,[37,14],[[33,16],","],null],[33,17]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]],[33,17]]]]]]],[30,2,["data"]]],[[[1,"\\n "],[8,[39,18],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Intentions"]],null],[1," "],[10,"em"],[12],[1,[28,[35,19],[[30,5,["length"]]],null]],[1," total"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"label"],[14,"for","toolbar-toggle"],[12],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,20],["create intentions"],null],[[[1," "],[8,[39,21],null,[["@text","@route"],["Create","dc.intentions.create"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n\\n"],[41,[28,[37,22],[[30,5,["length"]],0],null],[[[1," "],[8,[39,23],null,[["@search","@onsearch","@sort","@filter"],[[99,24,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,24]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@sink","@type","@ondelete"],[[28,[37,3],["/${partition}/${dc}/${nspace}/intention/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"intention",[99,26,["@ondelete"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@type","@sort","@filters","@search","@items"],["intention",[30,3,["value"]],[30,4],[99,24,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,7,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@items","@delete"],[[30,7,["items"]],[30,6,["delete"]]]],[["default"],[[[[1,"\\n "],[8,[30,8,["CustomResourceNotice"]],null,null,null],[1,"\\n "],[8,[30,8,["Table"]],null,null,null],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,7,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,30],["routes.dc.intentions.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,30],["routes.dc.intentions.index.empty.body"],[["items","canUseACLs","htmlSafe"],[[30,5,["length"]],[28,[37,20],["use acls"],null],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,31],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on intentions",[29,[[28,[37,32],["CONSUL_DOCS_URL"],null],"/commands/intention"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,31],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,32],["CONSUL_DOCS_LEARN_URL"],null],"/consul/getting-started/connect"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","api","sort","filters","items","writer","collection","list"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","access","split","not-eq","searchproperty","searchProperties","app-view","format-number","can","hds/button","gt","consul/intention/search-bar","search","data-writer","refresh-route","data-collection","consul/intention/list","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/intentions/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/kv/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"gAVZYavj",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n"],[44,["/"],[[[1,"\\n"],[44,[[28,[37,3],[[28,[37,4],[[30,2],[28,[37,5],[0,-1,[28,[37,6],[[30,1,["params","key"]],[30,2]],null]],null]],null],[30,2]],null]],[[[1,"\\n "],[8,[39,7],null,[["@src"],[[28,[37,8],["/${partition}/${nspace}/${dc}/kv/${key}",[28,[37,9],null,[["partition","nspace","dc","key"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[52,[28,[37,11],[[33,1],"create"],null],"",[30,1,["params","key"]]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,12],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@error","@login"],[[30,4,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,12],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,4,["data"]]],[[[1,"\\n "],[8,[39,14],null,null,[["default"],[[[[1,"\\n\\n "],[8,[39,12],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,15],null,[["@href"],[[28,[37,16],["dc.kv.index"],null]]],[["default"],[[[[1,"\\n Key / Values\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[41,[28,[37,17],[[30,3],[30,2]],null],[[[1,"\\n"],[44,[[28,[37,6],[[30,3],[30,2]],null]],[[[1,"\\n"],[42,[28,[37,19],[[28,[37,19],[[30,9]],null]],null],null,[[[41,[28,[37,20],[[30,10,["length"]],0],null],[[[1," "],[10,"li"],[12],[1,"\\n "],[8,[39,15],[[4,[38,15],[[30,0],[30,10]],null]],[["@href"],[[28,[37,16],["dc.kv.folder",[28,[37,4],["/",[28,[37,21],[[28,[37,5],[0,[28,[37,22],[[30,11],1],null],[30,9]],null],""],null]],null]],null]]],[["default"],[[[[1,"\\n "],[1,[30,10]],[1,"\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[10,11]],null]],[9]]],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,12],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n"],[41,[28,[37,23],[[30,8,["Key"]],[28,[37,17],[[30,8,["Key"]],[30,3]],null]],null],[[[1," "],[8,[30,1,["Title"]],null,[["@title","@render"],["Edit Key / Value",false]],null],[1,"\\n "],[1,[28,[35,24],[[30,8,["Key"]],[30,3]],null]],[1,"\\n"]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title","@render"],["New Key / Value",true]],null],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,12],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n"],[41,[30,8,["Session"]],[[[1," "],[8,[39,25],null,[["@type"],["kv"]],null],[1,"\\n"]],[]],null],[1,"\\n "],[8,[39,26],null,[["@item","@dc","@nspace","@partition","@onsubmit","@parent"],[[30,8],[30,1,["params","dc"]],[30,1,["params","nspace"]],[30,1,["params","partition"]],[52,[28,[37,27],[[30,3],[30,2]],null],[28,[37,28],["dc.kv.index"],null],[28,[37,28],["dc.kv.folder",[30,3]],null]],[30,3]]],null],[1,"\\n\\n\\n"],[41,[28,[37,23],[[30,8,["Session"]]],null],[[[1," "],[8,[39,29],null,[["@src","@onchange"],[[28,[37,8],["/${partition}/${nspace}/${dc}/sessions/for-key/${id}",[28,[37,9],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,8,["Session"]]]]]],null],[28,[37,15],[[30,0],[28,[37,30],[[33,31]],null]],[["value"],["data"]]]]],null],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[8,[39,15],[[24,"rel","help"]],[["@href","@external"],[[28,[37,3],[[28,[37,32],["CONSUL_DOCS_URL"],null],"/internals/sessions.html#session-design"],null],true]],[["default"],[[[[1,"\\n Lock Session\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n"],[41,[33,31,["ID"]],[[[1," "],[8,[39,33],null,[["@item","@ondelete"],[[99,31,["@item"]],[30,4,["invalidate"]]]],null],[1,"\\n"]],[]],null]],[]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[5,6,7,8]]],[1," "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[3]]]],[2]]]],[1]]]]],[1,"\\n"]],["route","separator","parentKey","loader","dc","partition","nspace","item","parts","breadcrumb","index"],false,["route","routeName","let","concat","join","slice","split","data-loader","uri","hash","if","string-ends-with","block-slot","app-error","app-view","action","href-to","not-eq","each","-track-array","gt","append","add","and","left-trim","consul/lock-session/notifications","consul/kv/form","eq","transition-to","data-source","mut","session","env","consul/lock-session/form"]]',moduleName:"consul-ui/templates/dc/kv/edit.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/kv/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"EqbwXwSB",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src","@onchange"],[[28,[37,3],["/${partition}/${nspace}/${dc}/kv/${key}",[28,[37,4],null,[["partition","nspace","dc","key"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","key"]],"/"],null]]]]],null],[28,[37,6],[[30,0],[28,[37,7],[[33,8]],null]],[["value"],["data"]]]]],null],[1,"\\n "],[8,[39,9],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/kvs/${key}",[28,[37,4],null,[["partition","nspace","dc","key"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","key"]],"/"],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,10],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,11],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,13],[[30,2,["error","status"]],"404"],null],[[[1," "],[8,[39,14],[[4,[38,15],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,4,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,4,["Description"]],null,null,[["default"],[[[[1,"\\n This KV or parent of this KV was deleted.\\n "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[]],[[[41,[28,[37,13],[[30,2,["error","status"]],"403"],null],[[[1," "],[8,[39,14],[[4,[38,15],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"\\n You no longer have access to this KV.\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,14],[[4,[38,15],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"\\n An error was returned whilst loading this data, refresh to try again.\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]],[]]],[1," "]],[3]]]]],[1,"\\n\\n "],[8,[39,10],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,5],[[33,17],"Kind:asc"],null],[28,[37,6],[[30,0],[28,[37,7],[[33,17]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["kind"],[[28,[37,4],null,[["value","change"],[[52,[33,18],[28,[37,19],[[33,18],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,18]],null]],[["value"],["target.selectedItems"]]]]]]]]],[33,8],[30,2,["data"]]],[[[1," "],[8,[39,20],null,null,[["default"],[[[[1,"\\n"],[41,[28,[37,21],[[30,9,["Key"]],"/"],null],[[[1," "],[8,[39,10],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,22],["dc.kv"],null]],[12],[1,"Key / Values"],[13],[13],[1,"\\n"],[42,[28,[37,24],[[28,[37,24],[[28,[37,25],[0,-2,[28,[37,19],[[30,9,["Key"]],"/"],null]],null]],null]],null],null,[[[1," "],[10,"li"],[12],[11,3],[16,6,[28,[37,22],["dc.kv.folder",[28,[37,26],["/",[28,[37,27],[[28,[37,25],[0,[28,[37,28],[[30,12],1],null],[28,[37,19],[[30,9,["Key"]],"/"],null]],null],""],null]],null]],null]],[4,[38,29],[[30,11]],null],[12],[1,[30,11]],[13],[13],[1,"\\n"]],[11,12]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,10],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n"],[41,[28,[37,13],[[30,9,["Key"]],"/"],null],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],["Key / Value"]],null],[1,"\\n"]],[]],[[[1," "],[8,[30,1,["Title"]],null,[["@title"],[[28,[37,30],[1,[28,[37,31],[1,[28,[37,32],[[28,[37,19],[[30,9,["Key"]],"/"],null]],null]],null]],null]]],null],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[10,"label"],[14,"for","toolbar-toggle"],[12],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,33],[[30,10,["length"]],0],null],[[[1," "],[8,[39,34],null,[["@search","@onsearch","@sort","@filter"],[[99,35,["@search"]],[28,[37,6],[[30,0],[28,[37,7],[[33,35]],null]],[["value"],["target.value"]]],[30,7],[30,8]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,36],["create kvs"],null],[[[41,[28,[37,37],[[30,9,["Key"]],[28,[37,21],[[30,9,["Key"]],"/"],null]],null],[[[1," "],[8,[39,38],null,[["@text","@isHrefExternal","@href"],["Create",false,[29,[[28,[37,22],["dc.kv.create",[30,9,["Key"]]],null]]]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,38],null,[["@text","@route"],["Create","dc.kv.root-create"]],null],[1,"\\n"]],[]]]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,39],null,[["@sink","@type","@label","@ondelete"],[[28,[37,3],["/${partition}/${nspace}/${dc}/kv/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"kv","key",[99,40,["@ondelete"]]]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,41],null,[["@type","@sort","@filters","@search","@items"],["kv",[30,7,["value"]],[30,8],[99,35,["@search"]],[30,10]]],[["default"],[[[[1,"\\n "],[8,[30,14,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,42],null,[["@items","@parent","@delete"],[[30,14,["items"]],[30,9],[30,13,["delete"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,14,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,43],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,44],["routes.dc.kv.index.empty.header"],[["items"],[[30,10,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,44],["routes.dc.kv.index.empty.body"],[["items","canUseACLs","htmlSafe"],[[30,10,["length"]],[28,[37,36],["use acls"],null],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,45],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on K/V",[29,[[28,[37,46],["CONSUL_DOCS_URL"],null],"/agent/kv"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,45],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,46],["CONSUL_DOCS_LEARN_URL"],null],"/consul/getting-started/kv"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[14]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[13]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[7,8,9,10]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","after","T","T","T","sort","filters","parent","items","breadcrumb","index","writer","collection"],false,["route","routeName","data-source","uri","hash","or","action","mut","parent","data-loader","block-slot","app-error","if","eq","hds/toast","notification","let","sortBy","kind","split","app-view","not-eq","href-to","each","-track-array","slice","join","append","add","tooltip","take","drop","reverse","gt","consul/kv/search-bar","search","can","and","hds/button","data-writer","refresh-route","data-collection","consul/kv/list","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/kv/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/nodes/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"M0ePlJBh",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/leader",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/nodes",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,3,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,9],[[33,10],"Status:asc"],null],[28,[37,11],[[30,0],[28,[37,12],[[33,10]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["status","searchproperty","version"],[[28,[37,4],null,[["value","change"],[[52,[33,14],[28,[37,15],[[33,14],","],null],[27]],[28,[37,11],[[30,0],[28,[37,12],[[33,14]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,16],[[33,17],[27]],null],[28,[37,15],[[33,17],","],null],[30,0,["_searchProperties"]]],[28,[37,11],[[30,0],[28,[37,12],[[33,17]],null]],[["value"],["target.selectedItems"]]],[30,0,["_searchProperties"]]]]],[28,[37,4],null,[["value","change"],[[52,[30,0,["version"]],[28,[37,15],[[30,0,["version"]],","],null],[27]],[28,[37,11],[[30,0],[28,[37,12],[[30,0,["version"]]],null]],[["value"],["target.selectedItems"]]]]]]]]],[30,3,["data"]],[30,2,["data"]],[30,3,["data","meta","versions"]]],[[[44,[[28,[37,18],["Meta.synthetic-node",[30,6]],null]],[[[1," "],[8,[39,19],null,null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Nodes"]],null],[1,"\\n "],[10,"em"],[12],[1,[28,[35,20],[[30,6,["length"]]],null]],[1," total"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"label"],[14,"for","toolbar-toggle"],[12],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,21],[[30,9,["length"]],0],null],[[[1," "],[8,[39,22],null,[["@search","@onsearch","@sort","@filter","@versions"],[[99,23,["@search"]],[28,[37,11],[[30,0],[28,[37,12],[[33,23]],null]],[["value"],["target.value"]]],[30,4],[30,5],[30,8]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,24],null,[["@items","@filteredItems","@postfix"],[[30,6],[30,9],[28,[37,25],[[30,1,["params","partition"]],[30,1,["params","dc"]]],null]]],null],[1,"\\n "],[8,[39,26],null,[["@type","@sort","@filters","@search","@items"],["node",[30,4,["value"]],[30,5],[99,23,["@search"]],[30,9]]],[["default"],[[[[1,"\\n "],[8,[30,10,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@items","@leader"],[[30,10,["items"]],[30,7]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,10,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,29],["routes.dc.nodes.index.empty.header"],[["items"],[[30,6,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,29],["routes.dc.nodes.index.empty.body"],[["items","canUseACLs","htmlSafe"],[[30,6,["length"]],[28,[37,30],["use acls"],null],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,31],null,[["@text","@href","@color","@icon","@iconPosition","@size"],[[28,[37,29],["routes.dc.nodes.index.empty.documentation"],null],[29,[[28,[37,32],["CONSUL_DOCS_DEVELOPER_URL"],null],"/agent"]],"tertiary","docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,31],null,[["@text","@href","@color","@icon","@iconPosition","@size"],[[28,[37,29],["routes.dc.nodes.index.empty.learn"],null],[29,[[28,[37,32],["CONSUL_DOCS_LEARN_URL"],null],"/tutorials/consul/deployment-guide?in=consul/production-deploy#configure-consul-agents"]],"tertiary","learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[10]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[9]]]],[4,5,6,7,8]]],[1," "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","leader","api","sort","filters","items","leader","versions","filtered","collection"],false,["route","routeName","data-source","uri","hash","data-loader","block-slot","app-error","let","or","sortBy","action","mut","if","status","split","not-eq","searchproperty","reject-by","app-view","format-number","gt","consul/node/search-bar","search","consul/node/agentless-notice","concat","data-collection","consul/node/list","empty-state","t","can","hds/button","env"]]',moduleName:"consul-ui/templates/dc/nodes/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/nodes/show",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"h4OruvTV",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/coordinates/for-node/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/node/${name}/${peer}",[28,[37,4],null,[["partition","nspace","dc","name","peer"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]],[30,1,["params","peer"]]]]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,3,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,9],[[30,3,["error","status"]],"404"],null],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"This node no longer exists in the catalog."]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[41,[28,[37,9],[[30,3,["error","status"]],"403"],null],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"You no longer have access to this node."]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,7,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,7,["Description"]],null,null,[["default"],[[[[1,"An error was returned whilst loading this data, refresh to try again."]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]],[]]],[1," "]],[4]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,3,["data"]],[30,2,["data"]]],[[[1," "],[8,[39,13],null,null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["notification"]],[["default"],[[[[1,"\\n "],[8,[39,14],null,[["@type","@status"],[[30,11],[30,10]]],null],[1,"\\n "]],[10,11]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,15],["dc.nodes"],[["params"],[[28,[37,4],null,[["peer"],[[27]]]]]]]],[12],[1,"All Nodes"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[30,8,["Node"]]]],null],[1,"\\n "],[13],[1,"\\n "],[10,"label"],[14,"for","toolbar-toggle"],[12],[13],[1,"\\n "],[8,[39,16],null,[["@item"],[[30,8]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["nav"]],[["default"],[[[[1,"\\n "],[8,[39,17],null,[["@items"],[[28,[37,18],[[28,[37,19],[[28,[37,4],null,[["label","href","selected"],[[28,[37,20],["routes.dc.nodes.show.healthchecks.title"],null],[28,[37,15],["dc.nodes.show.healthchecks"],null],[28,[37,21],["dc.nodes.show.healthchecks"],null]]]],[28,[37,4],null,[["label","href","selected"],[[28,[37,20],["routes.dc.nodes.show.services.title"],null],[28,[37,15],["dc.nodes.show.services"],null],[28,[37,21],["dc.nodes.show.services"],null]]]],[52,[30,9,["distances"]],[28,[37,4],null,[["label","href","selected"],[[28,[37,20],["routes.dc.nodes.show.rtt.title"],null],[28,[37,15],["dc.nodes.show.rtt"],null],[28,[37,21],["dc.nodes.show.rtt"],null]]]],""],[52,[28,[37,22],["read sessions"],null],[28,[37,4],null,[["label","href","selected"],[[28,[37,20],["routes.dc.nodes.show.sessions.title"],null],[28,[37,15],["dc.nodes.show.sessions"],null],[28,[37,21],["dc.nodes.show.sessions"],null]]]],""],[28,[37,4],null,[["label","href","selected"],[[28,[37,20],["routes.dc.nodes.show.metadata.title"],null],[28,[37,15],["dc.nodes.show.metadata"],null],[28,[37,21],["dc.nodes.show.metadata"],null]]]]],null]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,23],null,[["@value","@name"],[[30,8,["Address"]],"Address"]],[["default"],[[[[1,[30,8,["Address"]]]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,24],null,[["@name","@model"],[[99,1,["@name"]],[28,[37,25],[[28,[37,4],null,[["item","tomography"],[[30,8],[30,9]]]],[30,1,["model"]]],null]]],[["default"],[[[[1,"\\n "],[46,[28,[37,27],null,null],null,null,null],[1,"\\n "]],[12]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[8,9]]],[1," "]],[]]]]],[1,"\\n "]],[3]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","tomography","loader","after","T","T","T","item","tomography","status","type","o"],false,["route","routeName","data-source","uri","hash","data-loader","block-slot","app-error","if","eq","hds/toast","notification","let","app-view","consul/lock-session/notifications","href-to","consul/peer/info","tab-nav","compact","array","t","is-href","can","consul-copy-button","outlet","assign","component","-outlet"]]',moduleName:"consul-ui/templates/dc/nodes/show.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/nodes/show/healthchecks",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"Pjg8DJiZ",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],null,[["value","change"],[[28,[37,4],[[33,5],"Status:asc"],null],[28,[37,6],[[30,0],[28,[37,7],[[33,5]],null]],[["value"],["target.selected"]]]]]],[28,[37,3],null,[["status","kind","check","searchproperty"],[[28,[37,3],null,[["value","change"],[[52,[33,9],[28,[37,10],[[33,9],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,9]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change"],[[52,[33,11],[28,[37,10],[[33,11],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,11]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change"],[[52,[33,12],[28,[37,10],[[33,12],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,12]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change","default"],[[52,[28,[37,13],[[33,14],[27]],null],[28,[37,10],[[33,14],","],null],[33,15]],[28,[37,6],[[30,0],[28,[37,7],[[33,14]],null]],[["value"],["target.selectedItems"]]],[33,15]]]]]]],[30,1,["model","item","Checks"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,16],[[30,4,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,17],null,[["@search","@onsearch","@sort","@filter"],[[99,18,["@search"]],[28,[37,6],[[30,0],[28,[37,7],[[33,18]],null]],[["value"],["target.value"]]],[30,2],[30,3]]],null],[1,"\\n"]],[]],null],[44,[[28,[37,19],["Type","serf",[30,4]],null]],[[[41,[28,[37,20],[[30,5],[28,[37,21],[[30,5,["Status"]],"critical"],null]],null],[[[1," "],[8,[39,22],[[24,0,"mb-3 mt-2"]],[["@type","@color"],["inline","warning"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,[28,[35,23],["routes.dc.nodes.show.healthchecks.critical-serf-notice.header"],null]]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,[28,[35,23],["routes.dc.nodes.show.healthchecks.critical-serf-notice.body"],null]]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],null]],[5]]],[1," "],[8,[39,24],null,[["@type","@sort","@filters","@search","@items"],["health-check",[30,2,["value"]],[30,3],[99,18,["@search"]],[30,4]]],[["default"],[[[[1,"\\n "],[8,[30,7,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,25],null,[["@items"],[[30,7,["items"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,7,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,26],null,null,[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,23],["routes.dc.nodes.show.healthchecks.empty"],[["items","htmlSafe"],[[30,4,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "],[13],[1,"\\n"]],[2,3,4]]]],[1]]]]]],["route","sort","filters","items","serf","A","collection"],false,["route","routeName","let","hash","or","sortBy","action","mut","if","status","split","kind","check","not-eq","searchproperty","searchProperties","gt","consul/health-check/search-bar","search","find-by","and","eq","hds/alert","t","data-collection","consul/health-check/list","empty-state","block-slot"]]',moduleName:"consul-ui/templates/dc/nodes/show/healthchecks.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/nodes/show/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"D2F2tcWD",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],[[30,1,["model","item","Checks","length"]],0],null],[[[1," "],[1,[28,[35,4],[[28,[37,5],["replaceWith","dc.nodes.show.services"],null]],null]],[1,"\\n"]],[]],[[[1," "],[1,[28,[35,4],[[28,[37,5],["replaceWith","dc.nodes.show.healthchecks"],null]],null]],[1,"\\n"]],[]]]],[1]]]]],[1,"\\n"]],["route"],false,["route","routeName","if","eq","did-insert","route-action"]]',moduleName:"consul-ui/templates/dc/nodes/show/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/nodes/show/metadata",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"ywB5UQap",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[30,1,["model","item","Meta"]],[[[1," "],[8,[39,3],null,[["@items"],[[28,[37,4],[[30,1,["model","item","Meta"]]],null]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,5],null,null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n This node has no metadata.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route"],false,["route","routeName","if","consul/metadata/list","entries","empty-state","block-slot"]]',moduleName:"consul-ui/templates/dc/nodes/show/metadata.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/nodes/show/rtt",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"NmAMHd68",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[30,1,["model","tomography"]]],[[[41,[28,[37,4],[[30,2,["distances"]]],null],[[[1," "],[1,[28,[35,5],[[28,[37,6],["replaceWith","dc.nodes.show"],null]],null]],[1,"\\n"]],[]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n "],[10,0],[14,0,"definition-table"],[12],[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n Minimum\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,7],[[30,2,["min"]]],[["maximumFractionDigits"],[2]]]],[1,"ms\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,"\\n Median\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,7],[[30,2,["median"]]],[["maximumFractionDigits"],[2]]]],[1,"ms\\n "],[13],[1,"\\n "],[10,"dt"],[12],[1,"\\n Maximum\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,7],[[30,2,["max"]]],[["maximumFractionDigits"],[2]]]],[1,"ms\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,8],null,[["@distances"],[[30,2,["distances"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[]]]],[2]]]],[1]]]]],[1,"\\n"]],["route","tomography"],false,["route","routeName","let","if","not","did-insert","route-action","format-number","consul/tomography/graph"]]',moduleName:"consul-ui/templates/dc/nodes/show/rtt.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/nodes/show/services",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"uy3XQkE0",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],null,[["value","change"],[[28,[37,4],[[33,5],"Status:asc"],null],[28,[37,6],[[30,0],[28,[37,7],[[33,5]],null]],[["value"],["target.selected"]]]]]],[28,[37,3],null,[["status","source","searchproperty"],[[28,[37,3],null,[["value","change"],[[52,[33,9],[28,[37,10],[[33,9],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,9]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change"],[[52,[33,11],[28,[37,10],[[33,11],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,11]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change","default"],[[52,[28,[37,12],[[33,13],[27]],null],[28,[37,10],[[33,13],","],null],[33,14]],[28,[37,6],[[30,0],[28,[37,7],[[33,13]],null]],[["value"],["target.selectedItems"]]],[33,14]]]]]]],[30,1,["model","item","MeshServiceInstances"]],[30,1,["model","item","ProxyServiceInstances"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,15],[[30,4,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,16],null,[["@sources","@search","@onsearch","@searchproperties","@sort","@filter"],[[28,[37,17],[[28,[37,18],[[30,4]],null],"ExternalSources"],null],[99,19,["@search"]],[28,[37,6],[[30,0],[28,[37,7],[[33,19]],null]],[["value"],["target.value"]]],[99,14,["@searchproperties"]],[30,2],[30,3]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,20],null,[["@type","@sort","@filters","@search","@items"],["service-instance",[30,2,["value"]],[30,3],[99,19,["@search"]],[30,4]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,21],null,[["@node","@routeName","@items","@proxies"],[[30,1,["model","item"]],"dc.services.show",[30,6,["items"]],[30,5]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,22],null,null,[["default"],[[[[1,"\\n "],[8,[39,23],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,24],["routes.dc.nodes.show.services.empty"],[["items","htmlSafe"],[[30,4,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "],[13],[1,"\\n"]],[2,3,4,5]]]],[1]]]]]],["route","sort","filters","items","proxies","collection"],false,["route","routeName","let","hash","or","sortBy","action","mut","if","status","split","source","not-eq","searchproperty","searchProperties","gt","consul/service-instance/search-bar","get","collection","search","data-collection","consul/service-instance/list","empty-state","block-slot","t"]]',moduleName:"consul-ui/templates/dc/nodes/show/services.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/nodes/show/sessions",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"ZmABt/J1",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/sessions/for-node/${node}",[28,[37,4],null,[["partition","nspace","dc","node"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n "],[8,[39,8],null,[["@sink","@type","@label","@ondelete"],[[28,[37,3],["/${partition}/${dc}/${nspace}/session/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"session","Lock Session",[99,9,["@ondelete"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,10],[[4,[38,11],null,[["after"],[[28,[37,12],[[30,0],[30,5]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[5]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,10],[[4,[38,11],null,[["after"],[[28,[37,12],[[30,0],[30,6]],null]]]]],[["@type","@error"],["remove",[30,7]]],null],[1,"\\n "]],[6,7]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n "],[8,[39,13],null,[["@type","@items"],["session",[30,3]]],[["default"],[[[[1,"\\n\\n "],[8,[30,8,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,14],null,[["@items","@ondelete"],[[30,8,["items"]],[30,4,["delete"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[30,8,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,15],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,16],["routes.dc.nodes.show.sessions.empty.header"],[["items"],[[30,3,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,16],["routes.dc.nodes.show.sessions.empty.body"],[["canUseACLs","htmlSafe"],[[28,[37,17],["use acls"],null],true]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,18],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on Lock Sessions",[29,[[28,[37,19],["CONSUL_DOCS_URL"],null],"/internals/sessions.html"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,18],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,19],["CONSUL_DOCS_LEARN_URL"],null],"/tutorials/consul/distributed-semaphore"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "]],[8]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n "],[13],[1,"\\n"]],[3]]],[1," "]],[]]]]],[1,"\\n"]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","api","items","writer","after","after","error","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","data-writer","refresh-route","consul/lock-session/notifications","notification","action","data-collection","consul/lock-session/list","empty-state","t","can","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/nodes/show/sessions.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/nspaces/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"1lxBXjI3",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/namespace/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","name"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,2,["data"]],[30,2,["data","isNew"]]],[[[1," "],[8,[39,9],null,null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,10],["dc.nspaces"],null]],[12],[1,"All Namespaces"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[52,[30,7],"New Namespace",[28,[37,12],["Edit ",[30,6,["Name"]]],null]]]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,13],null,[["@item","@dc","@nspace","@partition","@onsubmit"],[[30,6],[30,1,["params","dc"]],[30,1,["params","nspace"]],[30,1,["params","partition"]],[28,[37,14],["dc.nspaces.index"],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5,6,7]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","dc","partition","nspace","item","create"],false,["route","routeName","data-loader","uri","hash","or","block-slot","app-error","let","app-view","href-to","if","concat","consul/nspace/form","transition-to"]]',moduleName:"consul-ui/templates/dc/nspaces/edit.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/nspaces/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"+WFNzwTw",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/namespaces",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Name:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["searchproperty"],[[28,[37,4],null,[["value","change","default"],[[52,[28,[37,13],[[33,14],[27]],null],[28,[37,15],[[33,14],","],null],[33,16]],[28,[37,10],[[30,0],[28,[37,11],[[33,14]],null]],[["value"],["target.selectedItems"]]],[33,16]]]]]]],[30,2,["data"]]],[[[1,"\\n "],[8,[39,17],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Namespaces"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,18],["create nspaces"],null],[[[1," "],[8,[39,19],null,[["@text","@route"],["Create","dc.nspaces.create"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,20],[[30,5,["length"]],0],null],[[[1," "],[8,[39,21],null,[["@search","@onsearch","@sort","@filter"],[[99,22,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,22]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,23],null,[["@sink","@type","@label","@ondelete"],[[28,[37,3],["/${partition}/${dc}/${nspace}/nspace/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"nspace","Namespace",[99,24,["@ondelete"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,25],[[4,[38,26],null,[["after"],[[28,[37,10],[[30,0],[30,7]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[7]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@type","@sort","@filters","@search","@items"],["nspace",[30,3,["value"]],[30,4],[99,22,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,8,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@items","@ondelete"],[[30,8,["items"]],[30,6,["delete"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,8,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,30],["routes.dc.namespaces.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[28,[35,30],["routes.dc.namespaces.index.empty.body"],[["items","canUseACLs"],[[30,5,["length"]],[28,[37,18],["use acls"],null]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,31],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on namespaces",[29,[[28,[37,32],["CONSUL_DOCS_URL"],null],"/commands/namespace"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,31],null,[["@text","@href","@icon","@iconPosition","@size"],["Read the guide",[29,[[28,[37,32],["CONSUL_DOCS_LEARN_URL"],null],"/consul/namespaces/secure-namespaces"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","sort","filters","items","writer","after","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","not-eq","searchproperty","split","searchProperties","app-view","can","hds/button","gt","consul/nspace/search-bar","search","data-writer","refresh-route","consul/nspace/notifications","notification","data-collection","consul/nspace/list","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/nspaces/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/partitions/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"jnt72m+Q",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/partition/${id}",[28,[37,4],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,5],[[30,1,["params","name"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,2,["data"]]],[[[1," "],[8,[39,9],null,null,[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,10],["dc.partitions"],null]],[12],[1,"All Admin Partitions"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[52,[28,[37,12],["new partition"],[["item"],[[30,6]]]],"New Partition",[28,[37,13],["Edit ",[30,6,["Name"]]],null]]]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n "],[8,[39,14],null,[["@item","@dc","@nspace","@partition","@onsubmit"],[[30,6],[30,1,["params","dc"]],[30,1,["params","nspace"]],[30,1,["params","partition"]],[28,[37,15],["dc.partitions.index"],null]]],null],[1,"\\n\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5,6]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","dc","partition","nspace","item"],false,["route","routeName","data-loader","uri","hash","or","block-slot","app-error","let","app-view","href-to","if","is","concat","consul/partition/form","transition-to"]]',moduleName:"consul-ui/templates/dc/partitions/edit.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/partitions/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"OueAvJB/",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/partitions",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Name:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["searchproperty"],[[28,[37,4],null,[["value","change","default"],[[52,[28,[37,13],[[33,14],[27]],null],[28,[37,15],[[33,14],","],null],[33,16]],[28,[37,10],[[30,0],[28,[37,11],[[33,14]],null]],[["value"],["target.selectedItems"]]],[33,16]]]]]]],[30,2,["data"]]],[[[1,"\\n "],[8,[39,17],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Admin Partitions"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[41,[28,[37,18],["create partitions"],null],[[[1," "],[8,[39,19],null,[["@text","@route"],["Create","dc.partitions.create"]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,20],[[30,5,["length"]],0],null],[[[1," "],[8,[39,21],null,[["@search","@onsearch","@sort","@filter"],[[99,22,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,22]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,23],null,[["@sink","@type","@label","@ondelete"],[[28,[37,3],["/${partition}/${dc}/${nspace}/partition/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"partition","Partition",[99,24,["@ondelete"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,25],[[4,[38,26],null,[["after"],[[28,[37,10],[[30,0],[30,7]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[7]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@type","@sort","@filters","@search","@items"],["nspace",[30,3,["value"]],[30,4],[99,22,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,8,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@items","@ondelete"],[[30,8,["items"]],[30,6,["delete"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,8,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,30],["routes.dc.partitions.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[28,[35,30],["routes.dc.partitions.index.empty.body"],[["items","canUseACLs"],[[30,5,["length"]],[28,[37,18],["use acls"],null]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"docs-link"],[12],[1,"\\n "],[8,[39,10],null,[["@href","@external"],[[29,[[28,[37,31],["CONSUL_DOCS_URL"],null],"/enterprise/admin-partitions"]],true]],[["default"],[[[[1,"\\n Documentation on Admin Partitions\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","sort","filters","items","writer","after","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","not-eq","searchproperty","split","searchProperties","app-view","can","hds/button","gt","consul/partition/search-bar","search","data-writer","refresh-route","consul/partition/notifications","notification","data-collection","consul/partition/list","empty-state","t","env"]]',moduleName:"consul-ui/templates/dc/partitions/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/peers/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"uPTWAtBk",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/peers",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"State:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["state","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,15],[[33,16],[27]],null],[28,[37,14],[[33,16],","],null],[33,17]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]],[33,17]]]]]]],[30,2,["data"]]],[[[1," "],[8,[39,18],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Peers"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n\\n"],[41,[28,[37,19],[[30,5,["length"]],0],null],[[[1," "],[8,[39,20],null,[["@search","@onsearch","@sort","@filter"],[[99,21,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,21]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n\\n "],[8,[39,22],[[24,0,"peer-create-modal"]],[["@aria"],[[28,[37,4],null,[["label"],["Add peer connection"]]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,0],"create",[30,6]],null]],null]],[1,"\\n "],[10,"h2"],[12],[1,"\\n Add peer connection\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n\\n"],[41,[30,6,["opened"]],[[[1," "],[8,[39,25],null,[["@params"],[[30,1,["params"]]]],[["default"],[[[[1,"\\n "],[8,[30,7,["Form"]],null,[["@onchange","@onsubmit"],[[30,2,["invalidate"]],[28,[37,26],[[30,0,["redirectToPeerShow"]],[30,6,["close"]]],null]]],[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,0],"form",[30,8]],null]],null]],[1,"\\n "],[8,[30,8,["Fieldsets"]],null,null,null],[1,"\\n "]],[8]]]]],[1,"\\n "]],[7]]]]],[1,"\\n"]],[]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[30,0,["form","Actions"]],null,[["@onclose"],[[30,0,["create","close"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "],[8,[39,27],[[4,[38,28],["click",[28,[37,29],[[30,0,["create","open"]]],null]],null]],[["@color","@text"],["primary","Add peer connection"]],null],[1,"\\n\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n "],[8,[39,30],null,[["@sink","@type","@label"],[[28,[37,3],["/${partition}/${dc}/${nspace}/peer/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"peer","Peer"]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["removed"]],[["default"],[[[[1,"\\n "],[8,[39,31],[[4,[38,32],null,[["after"],[[28,[37,10],[[30,0],[30,10]],null]]]]],[["@type"],["remove"]],null],[1,"\\n "]],[10]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n\\n "],[8,[39,22],null,[["@aria","@onclose"],[[28,[37,4],null,[["label"],["Regenerate token"]]],[28,[37,24],[[30,0],"item",[27]],null]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,0],"regenerate",[30,11]],null]],null]],[1,"\\n "],[10,"h2"],[12],[1,"\\n Regenerate token\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n"],[41,[30,0,["item"]],[[[1," "],[8,[39,33],null,[["@item","@onchange","@regenerate"],[[30,0,["item"]],[30,2,["invalidate"]],true]],[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,0],"regenerateForm",[30,12]],null]],null]],[1,"\\n "],[8,[30,12,["Fieldsets"]],null,null,null],[1,"\\n "]],[12]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[30,0,["regenerateForm","Actions"]],null,[["@onclose"],[[30,0,["regenerate","close"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "]],[11]]]]],[1,"\\n\\n "],[8,[39,34],null,[["@type","@sort","@filters","@search","@items"],["peer",[30,3,["value"]],[30,4],[99,21,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,13,["Collection"]],null,null,[["default"],[[[[1,"\\n\\n "],[8,[39,35],null,[["@items","@onedit","@ondelete"],[[30,13,["items"]],[28,[37,36],[[28,[37,24],[[30,0],"item"],null],[30,0,["regenerate","open"]]],null],[30,9,["delete"]]]],null],[1,"\\n\\n "]],[]]]]],[1,"\\n "],[8,[30,13,["Empty"]],null,null,[["default"],[[[[1,"\\n"],[1," "],[8,[39,37],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,38],["routes.dc.peers.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n "],[1,[28,[35,38],["routes.dc.peers.index.empty.body"],[["items","canUsePartitions","canUseACLs","htmlSafe"],[[30,5,["length"]],[28,[37,39],["use partitions"],null],[28,[37,39],["use acls"],null],true]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n"],[1," "],[8,[39,40],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on Peers",[29,[[28,[37,41],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,40],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,41],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering/create-manage-peering"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[13]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","sort","filters","items","modal","form","form","writer","after","modal","form","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","state","split","not-eq","searchproperty","searchProperties","app-view","gt","consul/peer/search-bar","search","modal-dialog","did-insert","set","consul/peer/form","fn","hds/button","on","optional","data-writer","consul/peer/notifications","notification","consul/peer/form/generate","data-collection","consul/peer/list","queue","empty-state","t","can","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/peers/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/peers/show",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"AvoaCEAO",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/peer/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","dc"]],[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,2,["data"]]],[[[1," "],[8,[39,8],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,9],["dc.peers"],null]],[12],[1,"All Peers"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[30,6,["Name"]]]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@peering"],[[30,6]]],null],[1,"\\n "],[8,[39,11],null,[["@peer"],[[30,6]]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@items"],[[30,7,["data","tabs"]]]],null],[1,"\\n\\n "]],[7]]]]],[1,"\\n "],[8,[39,13],null,[["@name","@model"],[[99,1,["@name"]],[28,[37,14],[[28,[37,4],null,[["items","peer"],[[30,6,["PeerServerAddresses"]],[30,6]]]],[30,1,["model"]]],null]]],[["default"],[[[[1,"\\n "],[46,[28,[37,16],null,null],null,null,null],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4,5,6]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","dc","partition","nspace","item","peering","o"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","app-view","href-to","consul/peer/bento-box","peerings/provider","tab-nav","outlet","assign","component","-outlet"]]',moduleName:"consul-ui/templates/dc/peers/show.hbs",isStrictMode:!1}) +e.default=n})) +define("consul-ui/templates/dc/peers/show/addresses",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"3k5sOecZ",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],[[30,1,["model","items","length"]],0],null],[[[1," "],[8,[39,4],null,[["@items"],[[30,1,["model","items"]]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,5],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,7],["routes.dc.peers.show.addresses.empty.header"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,7],["routes.dc.peers.show.addresses.empty.body"],[["htmlSafe"],[true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,6],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,8],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on Peers",[29,[[28,[37,9],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,8],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,9],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering/create-manage-peering"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]],[1]]]]]],["route"],false,["route","routeName","if","gt","consul/peer/address/list","empty-state","block-slot","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/peers/show/addresses.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/peers/show/exported",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"Z0gVGZWd",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/exported-services/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["model","peer","Name"]]]]]],null]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,6],[[30,1,["params","partition"]],[30,1,["model","user","token","Partition"]],"default"],null],[30,2,["data"]]],[[[1,"\\n "],[8,[39,7],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,8],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,7],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[41,[30,4,["length"]],[[[1," "],[10,0],[14,0,"search-bar"],[12],[1,"\\n "],[10,"form"],[14,0,"filter-bar"],[12],[1,"\\n "],[8,[39,10],[[24,0,"!w-80"]],[["@onsearch","@value","@placeholder"],[[28,[37,11],["target.value",[30,0,["updateSearch"]]],null],[30,0,["search"]],"Search"]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "],[8,[39,12],null,[["@items","@search","@searchProperties"],[[30,4],[30,0,["search"]],[28,[37,13],["Name"],null]]],[["default"],[[[[1,"\\n "],[8,[39,14],null,null,[["default"],[[[[1,"\\n"],[41,[30,6,["data","height"]],[[[1," "],[10,0],[15,5,[30,6,["data","fillRemainingHeightStyle"]]],[14,0,"overflow-y-scroll"],[12],[1,"\\n"],[41,[30,5,["data","items","length"]],[[[1," "],[8,[39,15],null,[["@tagName","@estimateHeight","@items"],["ul",[30,6,["data","height"]],[30,5,["data","items"]]]],[["default"],[[[[1,"\\n "],[10,"li"],[14,0,"px-3 h-12 border-bottom-primary"],[12],[1,"\\n "],[10,3],[14,0,"hds-typography-display-300 hds-foreground-strong hds-font-weight-semibold h-full w-full flex items-center"],[15,6,[28,[37,16],["dc.services.show.index",[30,7,["Name"]]],[["params"],[[52,[28,[37,17],[[30,7,["Partition"]],[30,3]],null],[28,[37,4],null,[["partition","nspace","peer"],[[30,7,["Partition"]],[30,7,["Namespace"]],[30,7,["PeerName"]]]]],[28,[37,4],null,[["peer"],[[30,7,["PeerName"]]]]]]]]]],[12],[1,"\\n "],[1,[30,7,["Name"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[7,8]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,18],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,19],["routes.dc.peers.show.exported.empty.header"],[["name"],[[30,1,["model","peer","Name"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,19],["routes.dc.peers.show.exported.empty.body"],[["items","name","htmlSafe"],[[30,4,["length"]],[30,1,["model","peer","Name"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,20],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on Peers",[29,[[28,[37,21],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,20],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,21],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering/create-manage-peering"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[]],null],[1," "]],[6]]]]],[1,"\\n\\n "]],[5]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3,4]]],[1," "]],[2]]]]],[1,"\\n\\n"]],[1]]]]]],["route","api","partition","items","search","p","service","index"],false,["route","routeName","data-loader","uri","hash","let","or","block-slot","app-error","if","freetext-filter","pick","providers/search","array","providers/dimension","vertical-collection","href-to","not-eq","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/peers/show/exported.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/peers/show/imported",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"Ioh7AUof",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/services/${peer}/${peerId}",[28,[37,4],null,[["partition","nspace","dc","peer","peerId"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["model","peer","Name"]],[30,1,["model","peer","id"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Status:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["status","kind","source","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change"],[[52,[33,15],[28,[37,14],[[33,15],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,15]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change"],[[52,[33,16],[28,[37,14],[[33,16],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,17],[[33,18],[27]],null],[28,[37,14],[[33,18],","],null],[30,0,["searchProperties"]]],[28,[37,10],[[30,0],[28,[37,11],[[33,18]],null]],[["value"],["target.selectedItems"]]],[30,0,["searchProperties"]]]]]]]],[28,[37,19],["Kind","connect-proxy",[30,2,["data"]]],null],[28,[37,8],[[30,1,["params","partition"]],[30,1,["model","user","token","Partition"]],"default"],null],[28,[37,8],[[30,1,["params","nspace"]],[30,1,["model","user","token","Namespace"]],"default"],null]],[[[1,"\\n"],[41,[28,[37,20],[[30,5,["length"]],0],null],[[[44,[[28,[37,21],[[30,5]],null]],[[[1," "],[8,[39,22],null,[["@sources","@partitions","@partition","@search","@onsearch","@sort","@filter","@peer"],[[28,[37,23],[[30,8],"ExternalSources"],null],[28,[37,23],[[30,8],"Partitions"],null],[30,6],[99,24,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,24]],null]],[["value"],["target.value"]]],[30,3],[30,4],[30,1,["model","peer"]]]],null],[1,"\\n"]],[8]]]],[]],null],[1," "],[8,[39,25],null,[["@type","@sort","@filters","@search","@items"],["service",[30,3,["value"]],[30,4],[99,24,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,9,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@items","@partition","@nspace","@isPeerDetail"],[[30,9,["items"]],[30,6],[30,7],true]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,9,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,28],["routes.dc.peers.show.imported.empty.header"],[["name"],[[30,1,["model","peer","Name"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,28],["routes.dc.peers.show.imported.empty.body"],[["items","name","htmlSafe"],[[30,5,["length"]],[30,1,["model","peer","Name"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n"],[1," "],[8,[39,29],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on Peers",[29,[[28,[37,30],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,29],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,30],["CONSUL_DOCS_URL"],null],"/connect/cluster-peering/create-manage-peering"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n"]],[3,4,5,6,7]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","api","sort","filters","items","partition","nspace","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","status","split","kind","source","not-eq","searchproperty","reject-by","gt","collection","consul/service/search-bar","get","search","data-collection","consul/service/list","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/peers/show/imported.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/peers/show/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"IJMk41B8",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[30,0,["transitionToImported"]]],null]],[1,"\\n"]],[1]]]]]],["route"],false,["route","routeName","did-insert"]]',moduleName:"consul-ui/templates/dc/peers/show/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/routing-config",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"ag2giQ2I",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/discovery-chain/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]]],[[[8,[39,8],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,9],["dc.services"],null]],[12],[1,"All Services"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[30,3,["Chain","ServiceName"]]]],null],[1,"\\n "],[13],[1,"\\n "],[8,[39,10],null,[["@source","@withInfo"],[[28,[37,11],["routes.dc.routing-config.source"],null],true]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"container"],[12],[1,"\\n "],[8,[39,12],null,[["@chain"],[[30,3,["Chain"]]]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]]],[1,"\\n"]],[3]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","item"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","app-view","href-to","consul/source","t","consul/discovery-chain"]]',moduleName:"consul-ui/templates/dc/routing-config.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"k/tlhz7S",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/services",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Status:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["status","kind","source","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change"],[[52,[33,15],[28,[37,14],[[33,15],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,15]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change"],[[52,[33,16],[28,[37,14],[[33,16],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,17],[[33,18],[27]],null],[28,[37,14],[[33,18],","],null],[30,0,["_searchProperties"]]],[28,[37,10],[[30,0],[28,[37,11],[[33,18]],null]],[["value"],["target.selectedItems"]]],[30,0,["_searchProperties"]]]]]]]],[28,[37,19],["Kind","connect-proxy",[30,2,["data"]]],null],[28,[37,8],[[30,1,["params","partition"]],[30,1,["model","user","token","Partition"]],"default"],null],[28,[37,8],[[30,1,["params","nspace"]],[30,1,["model","user","token","Namespace"]],"default"],null]],[[[1,"\\n "],[8,[39,20],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Services"]],null],[1," "],[10,"em"],[12],[1,[28,[35,21],[[30,5,["length"]]],null]],[1," total"],[13],[1,"\\n "],[13],[1,"\\n "],[10,"label"],[14,"for","toolbar-toggle"],[12],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n"],[41,[28,[37,22],[[30,5,["length"]],0],null],[[[44,[[28,[37,23],[[30,5]],null]],[[[1," "],[8,[39,24],null,[["@sources","@partitions","@partition","@search","@onsearch","@sort","@filter"],[[28,[37,25],[[30,8],"ExternalSources"],null],[28,[37,25],[[30,8],"Partitions"],null],[30,6],[99,26,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,26]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[8]]]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@type","@sort","@filters","@search","@items"],["service",[30,3,["value"]],[30,4],[99,26,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,9,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@items","@partition","@nspace"],[[30,9,["items"]],[30,6],[30,7]]],[["default"],[[[[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,9,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,30],["routes.dc.services.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,30],["routes.dc.services.index.empty.body"],[["items","canUseACLs","htmlSafe"],[[30,5,["length"]],[28,[37,31],["use acls"],null],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,32],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on Services",[29,[[28,[37,33],["CONSUL_DOCS_URL"],null],"/commands/services"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,32],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,33],["CONSUL_DOCS_LEARN_URL"],null],"/consul/getting-started/services"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n\\n"]],[3,4,5,6,7]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","api","sort","filters","items","partition","nspace","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","status","split","kind","source","not-eq","searchproperty","reject-by","app-view","format-number","gt","collection","consul/service/search-bar","get","search","data-collection","consul/service/list","empty-state","t","can","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/services/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/instance",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"UwadJzgF",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/service-instance/${id}/${node}/${name}/${peer}",[28,[37,4],null,[["partition","nspace","dc","id","node","name","peer"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","id"]],[30,1,["params","node"]],[30,1,["params","name"]],[30,1,["params","peer"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,8],[[30,2,["error","status"]],"404"],null],[[[1," "],[8,[39,9],[[4,[38,10],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,4,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,4,["Description"]],null,null,[["default"],[[[[1,"\\n This service has been deregistered and no longer exists in the catalog.\\n "]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[]],[[[41,[28,[37,8],[[30,2,["error","status"]],"403"],null],[[[1," "],[8,[39,9],[[4,[38,10],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"\\n You no longer have access to this service.\\n "]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,9],[[4,[38,10],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"\\n An error was returned whilst loading this data, refresh to try again.\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]],[]]],[1," "]],[3]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]]],[[[41,[30,7,["IsOrigin"]],[[[1," "],[8,[39,12],null,[["@src","@onchange"],[[28,[37,3],["/${partition}/${nspace}/${dc}/proxy-instance/${id}/${node}/${name}",[28,[37,4],null,[["partition","nspace","dc","id","node","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","id"]],[30,1,["params","node"]],[30,1,["params","name"]]]]]],null],[28,[37,13],[[30,0],[28,[37,14],[[33,15]],null]],[["value"],["data"]]]]],[["default"],[[[[1,"\\n"],[41,[30,8,["data","ServiceID"]],[[[1," "],[8,[39,12],null,[["@src","@onchange"],[[28,[37,3],["/${partition}/${nspace}/${dc}/service-instance/${id}/${node}/${name}/${peer}",[28,[37,4],null,[["partition","nspace","dc","id","node","name","peer"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,8,["data","ServiceID"]],[30,8,["data","NodeName"]],[30,8,["data","ServiceName"]],[30,1,["params","peer"]]]]]],null],[28,[37,13],[[30,0],[28,[37,14],[[33,16]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[]],null],[1," "]],[8]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,17],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,18],["dc.services"],[["params"],[[28,[37,4],null,[["peer"],[[27]]]]]]]],[12],[1,"All Services"],[13],[13],[1,"\\n "],[10,"li"],[12],[11,3],[16,6,[28,[37,18],["dc.services.show"],null]],[4,[38,19],[[28,[37,20],["Service (",[30,7,["Service","Service"]],")"],null]],null],[12],[1,"\\n Service ("],[1,[30,7,["Service","Service"]]],[1,")\\n "],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[30,7,["Service","ID"]]]],null],[1,"\\n "],[13],[1,"\\n "],[8,[39,21],null,[["@item","@withInfo"],[[30,7],true]],null],[1,"\\n "],[8,[39,22],null,[["@item","@withInfo"],[[30,7],true]],null],[1,"\\n"],[41,[28,[37,8],[[33,15,["ServiceProxy","Mode"]],"transparent"],null],[[[1," "],[8,[39,23],null,null,null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["nav"]],[["default"],[[[[1,"\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Service Name"],[13],[1,"\\n "],[10,"dd"],[12],[10,3],[15,6,[29,[[28,[37,18],["dc.services.show",[30,7,["Service","Service"]]],null]]]],[12],[1,[30,7,["Service","Service"]]],[13],[13],[1,"\\n "],[13],[1,"\\n"],[41,[51,[30,7,["Node","Meta","synthetic-node"]]],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Node Name"],[13],[1,"\\n "],[10,"dd"],[12],[10,3],[15,6,[29,[[28,[37,18],["dc.nodes.show",[30,7,["Node","Node"]]],null]]]],[12],[1,[30,7,["Node","Node"]]],[13],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[41,[30,7,["Service","PeerName"]],[[[1," "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[12],[1,"Peer Name"],[13],[1,"\\n "],[10,"dd"],[12],[10,3],[15,6,[28,[37,18],["dc.peers.show",[30,7,["Service","PeerName"]]],[["params"],[[28,[37,4],null,[["peer"],[[27]]]]]]]],[12],[1,[30,7,["Service","PeerName"]]],[13],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,25],[[30,7,["Service","Address"]],[30,7,["Node","Address"]]],null]],[[[1," "],[8,[39,26],null,[["@value","@name"],[[30,9],"Address"]],[["default"],[[[[1,[30,9]]],[]]]]],[1,"\\n"]],[9]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@items"],[[28,[37,28],[[28,[37,29],[[28,[37,4],null,[["label","href","selected"],["Health Checks",[28,[37,18],["dc.services.instance.healthchecks"],null],[28,[37,30],["dc.services.instance.healthchecks"],null]]]],[52,[28,[37,8],[[30,7,["Service","Kind"]],"mesh-gateway"],null],[28,[37,4],null,[["label","href","selected"],["Addresses",[28,[37,18],["dc.services.instance.addresses"],null],[28,[37,30],["dc.services.instance.addresses"],null]]]]],[52,[33,16],[28,[37,4],null,[["label","href","selected"],["Upstreams",[28,[37,18],["dc.services.instance.upstreams"],null],[28,[37,30],["dc.services.instance.upstreams"],null]]]]],[52,[33,16],[28,[37,4],null,[["label","href","selected"],["Exposed Paths",[28,[37,18],["dc.services.instance.exposedpaths"],null],[28,[37,30],["dc.services.instance.exposedpaths"],null]]]]],[28,[37,4],null,[["label","href","selected"],["Tags & Meta",[28,[37,18],["dc.services.instance.metadata"],null],[28,[37,30],["dc.services.instance.metadata"],null]]]]],null]],null]]],null],[1,"\\n "],[8,[39,31],null,[["@name","@model"],[[99,1,["@name"]],[28,[37,32],[[28,[37,4],null,[["proxy","meta","item"],[[33,16],[33,15],[30,7]]]],[30,1,["model"]]],null]]],[["default"],[[[[1,"\\n "],[46,[28,[37,34],null,null],null,null,null],[1,"\\n "]],[10]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[7]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","after","T","T","T","item","meta","address","o"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","if","eq","hds/toast","notification","let","data-source","action","mut","meta","proxy","app-view","href-to","tooltip","concat","consul/external-source","consul/kind","consul/transparent-proxy","unless","or","consul-copy-button","tab-nav","compact","array","is-href","outlet","assign","component","-outlet"]]',moduleName:"consul-ui/templates/dc/services/instance.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/instance/addresses",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"Uyz1biFQ",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],[[30,1,["model","item","Service","TaggedAddresses"]]],null]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,5],[[30,2,["length"]],0],null],[[[1," "],[8,[39,6],[[24,0,"consul-tagged-addresses"]],[["@items"],[[30,2]]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"th"],[12],[1,"Tag"],[13],[1,"\\n "],[10,"th"],[12],[1,"Address"],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,7],null,[["@name"],["row"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,8],[1,[30,3]],null]],[[[41,[30,5],[[[1," "],[10,"td"],[12],[1,"\\n "],[1,[28,[35,8],[0,[30,3]],null]],[41,[28,[37,9],[[28,[37,10],[[30,5,["Address"]],[33,11,["Address"]]],null],[28,[37,10],[[30,5,["Port"]],[33,11,["Port"]]],null]],null],[[[1," "],[10,"em"],[12],[1,"(default)"],[13]],[]],null],[1,"\\n "],[13],[1,"\\n "],[10,"td"],[12],[1,"\\n "],[1,[30,5,["Address"]]],[1,":"],[1,[30,5,["Port"]]],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[5]]],[1," "]],[]]]]],[1,"\\n "]],[3,4]]]]],[1,"\\n"]],[]],[[[1," "],[10,2],[12],[1,"\\n There are no additional addresses.\\n "],[13],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[2]]]],[1]]]]],[1,"\\n"]],["route","items","taggedAddress","index","address"],false,["route","routeName","let","entries","if","gt","tabular-collection","block-slot","object-at","and","eq","item"]]',moduleName:"consul-ui/templates/dc/services/instance/addresses.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/instance/exposedpaths",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"2ZHEMt/5",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[30,1,["model","proxy"]],[30,1,["model","meta"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,4],[[30,3,["ServiceProxy","Expose","Paths","length"]],0],null],[[[1," "],[1,[28,[35,5],["routes.dc.services.instance.exposedpaths.intro"],[["htmlSafe"],[true]]]],[1,"\\n "],[8,[39,6],null,[["@items","@address"],[[30,3,["ServiceProxy","Expose","Paths"]],[28,[37,7],[[30,2,["Service","Address"]],[30,2,["Node","Address"]]],null]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,8],null,null,[["default"],[[[[1,"\\n "],[8,[39,9],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,5],["routes.dc.services.instance.exposedpaths.empty.body"],[["htmlSafe"],[true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n"]],[2,3]]]],[1]]]]]],["route","item","proxy"],false,["route","routeName","let","if","gt","t","consul/exposed-path/list","or","empty-state","block-slot"]]',moduleName:"consul-ui/templates/dc/services/instance/exposedpaths.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/instance/healthchecks",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"VEYB4gr9",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],[[28,[37,4],[[30,0],"syntheticNodeSearchPropertyFilter",[30,1,["model","item"]]],null],[33,5]],null]],[[[44,[[28,[37,6],null,[["value","change"],[[28,[37,7],[[33,8],"Status:asc"],null],[28,[37,4],[[30,0],[28,[37,9],[[33,8]],null]],[["value"],["target.selected"]]]]]],[28,[37,6],null,[["status","check","searchproperty"],[[28,[37,6],null,[["value","change"],[[52,[33,11],[28,[37,12],[[33,11],","],null],[27]],[28,[37,4],[[30,0],[28,[37,9],[[33,11]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,6],null,[["value","change"],[[52,[33,13],[28,[37,12],[[33,13],","],null],[27]],[28,[37,4],[[30,0],[28,[37,9],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,6],null,[["value","change","default"],[[52,[28,[37,14],[[33,15],[27]],null],[28,[37,12],[[33,15],","],null],[30,2]],[28,[37,4],[[30,0],[28,[37,9],[[33,15]],null]],[["value"],["target.selectedItems"]]],[30,2]]]]]]],[28,[37,3],[[28,[37,4],[[30,0],"syntheticNodeHealthCheckFilter",[30,1,["model","item"]]],null],[28,[37,16],[[28,[37,17],[[30,1,["model","item","Checks"]],[30,1,["model","proxy","Checks"]]],null],[30,1,["model","proxy","ServiceProxy","Expose","Checks"]]],null]],null]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n\\n"],[41,[28,[37,18],[[30,5,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,19],null,[["@search","@onsearch","@sort","@filter"],[[99,20,["@search"]],[28,[37,4],[[30,0],[28,[37,9],[[33,20]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1,"\\n"],[44,[[28,[37,21],["Type","serf",[30,5]],null]],[[[41,[28,[37,22],[[30,6],[28,[37,23],[[30,6,["Status"]],"critical"],null]],null],[[[1," "],[8,[39,24],[[24,0,"mb-3 mt-2"]],[["@type","@color"],["inline","warning"]],[["default"],[[[[1,"\\n "],[8,[30,7,["Title"]],null,null,[["default"],[[[[1,[28,[35,25],["routes.dc.services.instance.healthchecks.critical-serf-notice.header"],null]]],[]]]]],[1,"\\n "],[8,[30,7,["Description"]],null,null,[["default"],[[[[1,[28,[35,25],["routes.dc.services.instance.healthchecks.critical-serf-notice.body"],[["htmlSafe"],[true]]]]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n"]],[]],null]],[6]]],[1," "],[8,[39,26],null,[["@type","@sort","@filters","@search","@items"],["health-check",[30,3,["value"]],[30,4],[99,20,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,8,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@items"],[[30,8,["items"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,8,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,null,[["default"],[[[[1,"\\n "],[8,[39,29],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,25],["routes.dc.services.instance.healthchecks.empty"],[["items","htmlSafe"],[[30,5,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n\\n "],[13],[1,"\\n"]],[3,4,5]]]],[2]]]],[1]]]]],[1,"\\n"]],["route","filteredSearchProperties","sort","filters","items","serf","A","collection"],false,["route","routeName","let","filter","action","searchProperties","hash","or","sortBy","mut","if","status","split","check","not-eq","searchproperty","merge-checks","array","gt","consul/health-check/search-bar","search","find-by","and","eq","hds/alert","t","data-collection","consul/health-check/list","empty-state","block-slot"]]',moduleName:"consul-ui/templates/dc/services/instance/healthchecks.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/instance/metadata",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"TXVP9+3G",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[30,1,["model","item"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n "],[10,"section"],[14,0,"tags"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Tags"],[13],[1,"\\n"],[41,[28,[37,4],[[30,2,["Tags","length"]],0],null],[[[1," "],[8,[39,5],null,[["@item"],[[30,2]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,6],null,null,[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n There are no tags.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[10,"section"],[14,0,"metadata"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Meta"],[13],[1,"\\n"],[41,[30,2,["Meta"]],[[[1," "],[8,[39,8],null,[["@items"],[[28,[37,9],[[30,2,["Meta"]]],null]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,6],null,null,[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[10,2],[12],[1,"\\n This instance has no metadata.\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]],[1," "],[13],[1,"\\n "],[13],[1,"\\n"]],[2]]]],[1]]]]],[1,"\\n"]],["route","item"],false,["route","routeName","let","if","gt","tag-list","empty-state","block-slot","consul/metadata/list","entries"]]',moduleName:"consul-ui/templates/dc/services/instance/metadata.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/instance/upstreams",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"uuOJKl7x",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[44,[[28,[37,3],null,[["value","change"],[[28,[37,4],[[33,5],"DestinationName:asc"],null],[28,[37,6],[[30,0],[28,[37,7],[[33,5]],null]],[["value"],["target.selected"]]]]]],[28,[37,3],null,[["searchproperty"],[[28,[37,3],null,[["value","change","default"],[[52,[28,[37,9],[[33,10],[27]],null],[28,[37,11],[[33,10],","],null],[33,12]],[28,[37,6],[[30,0],[28,[37,7],[[33,10]],null]],[["value"],["target.selectedItems"]]],[33,12]]]]]]],[28,[37,4],[[30,1,["params","partition"]],[30,1,["model","user","token","Partition"]],"default"],null],[28,[37,4],[[30,1,["params","nspace"]],[30,1,["model","user","token","Namespace"]],"default"],null],[30,1,["params","dc"]],[30,1,["model","proxy"]],[30,1,["model","meta"]],[30,1,["model","proxy","Service","Proxy","Upstreams"]]],[[[41,[28,[37,13],[[30,9,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,14],null,[["@search","@onsearch","@searchproperties","@sort","@filter"],[[99,15,["@search"]],[28,[37,6],[[30,0],[28,[37,7],[[33,15]],null]],[["value"],["target.value"]]],[99,12,["@searchproperties"]],[30,2],[30,3]]],null],[1,"\\n"]],[]],null],[41,[28,[37,16],[[30,8,["ServiceProxy","Mode"]],"transparent"],null],[[[1," "],[8,[39,17],[[24,0,"mb-3 mt-2"]],[["@type","@color"],["inline","warning"]],[["default"],[[[[1,"\\n "],[8,[30,10,["Title"]],null,null,[["default"],[[[[1,[28,[35,18],["routes.dc.services.instance.upstreams.tproxy-mode.header"],null]]],[]]]]],[1,"\\n "],[8,[30,10,["Description"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,18],["routes.dc.services.instance.upstreams.tproxy-mode.body"],null]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,10,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition","@size"],[[28,[37,18],["routes.dc.services.instance.upstreams.tproxy-mode.footer.text"],null],[29,[[28,[37,19],[[28,[37,20],["CONSUL_DOCS_URL"],null],[28,[37,18],["routes.dc.services.instance.upstreams.tproxy-mode.footer.link"],null]],null]]],"docs-link","trailing","small"]],null],[1,"\\n "]],[10]]]]],[1,"\\n"]],[]],null],[1," "],[8,[39,21],null,[["@type","@sort","@filters","@search","@items"],["upstream-instance",[30,2,["value"]],[30,3],[99,15,["@search"]],[30,9]]],[["default"],[[[[1,"\\n "],[8,[30,11,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,22],null,[["@items","@dc","@nspace","@partition"],[[30,11,["items"]],[30,6],[30,5],[30,4]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,11,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,23],null,null,[["default"],[[[[1,"\\n "],[8,[39,24],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,18],["routes.dc.services.instance.upstreams.empty"],[["items","htmlSafe"],[[30,9,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[11]]]]],[1,"\\n"]],[2,3,4,5,6,7,8,9]]],[1," "],[13],[1,"\\n"]],[1]]]]]],["route","sort","filters","partition","nspace","dc","proxy","meta","items","A","collection"],false,["route","routeName","let","hash","or","sortBy","action","mut","if","not-eq","searchproperty","split","searchProperties","gt","consul/upstream-instance/search-bar","search","eq","hds/alert","t","concat","env","data-collection","consul/upstream-instance/list","empty-state","block-slot"]]',moduleName:"consul-ui/templates/dc/services/instance/upstreams.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/show",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"Y0GMHKaI",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/service-instances/for-service/${name}/${peer}",[28,[37,4],null,[["partition","nspace","dc","name","peer"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]],[30,1,["params","peer"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,8],[[30,2,["error","status"]],"404"],null],[[[1," "],[8,[39,9],[[4,[38,10],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,4,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,4,["Description"]],null,null,[["default"],[[[[1,"This service has been deregistered and no longer exists in the catalog."]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n"]],[]],[[[41,[28,[37,8],[[30,2,["error","status"]],"403"],null],[[[1," "],[8,[39,9],[[4,[38,10],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"You no longer have access to this service."]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,9],[[4,[38,10],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"An error was returned whilst loading this data, refresh to try again."]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n "]],[]]]],[]]],[1," "]],[3]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,2,["data"]],[30,2,["data","firstObject"]],[30,1,["model","dc"]]],[[[1,"\\n"],[41,[30,8,["IsOrigin"]],[[[1," "],[8,[39,12],null,[["@src","@onchange"],[[28,[37,3],["/${partition}/${nspace}/${dc}/proxies/for-service/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null],[28,[37,13],[[30,0],[28,[37,14],[[33,15]],null]],[["value"],["data"]]]]],null],[1,"\\n"],[41,[28,[37,16],[[33,17]],null],[[[1," "],[8,[39,12],null,[["@src","@onchange"],[[28,[37,3],["/${partition}/${nspace}/${dc}/discovery-chain/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null],[28,[37,13],[[30,0],[28,[37,14],[[33,17]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[]],null],[1," "],[1,[28,[35,18],[[28,[37,19],[[30,0],"chain",[27]],null],[30,1,["params","dc"]]],null]],[1,"\\n"]],[]],null],[44,[[28,[37,4],null,[["topology","services","upstreams","instances","intentions","routing","tags"],[[28,[37,20],[[30,9,["MeshEnabled"]],[30,8,["IsMeshOrigin"]],[28,[37,21],[[28,[37,22],[[33,15,["length"]],0],null],[28,[37,8],[[30,8,["Service","Kind"]],"ingress-gateway"],null],[28,[37,8],[[30,8,["Service","Kind"]],"api-gateway"],null]],null],[28,[37,16],[[30,8,["Service","PeerName"]]],null]],null],[28,[37,20],[[28,[37,8],[[30,8,["Service","Kind"]],"terminating-gateway"],null],[28,[37,16],[[30,8,["Service","PeerName"]]],null]],null],[28,[37,20],[[28,[37,8],[[30,8,["Service","Kind"]],"ingress-gateway"],null],[28,[37,16],[[30,8,["Service","PeerName"]]],null]],null],true,[28,[37,20],[[28,[37,23],[[30,8,["Service","Kind"]],"terminating-gateway"],null],[28,[37,24],["read intention for service"],[["item"],[[30,8,["Service"]]]]],[28,[37,16],[[30,8,["Service","PeerName"]]],null]],null],[28,[37,20],[[30,9,["MeshEnabled"]],[30,8,["IsOrigin"]],[28,[37,16],[[30,8,["Service","PeerName"]]],null]],null],true]]]],[[[1," "],[8,[39,25],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["notification"]],[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@type","@status","@error"],[[30,12],[30,11],[30,14]]],null],[1,"\\n "]],[11,12,13,14]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["breadcrumbs"]],[["default"],[[[[1,"\\n "],[10,"ol"],[12],[1,"\\n "],[10,"li"],[12],[10,3],[15,6,[28,[37,27],["dc.services"],[["params"],[[28,[37,4],null,[["peer"],[[27]]]]]]]],[12],[1,"All Services"],[13],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[30,8,["Service","Service"]]]],null],[1,"\\n "],[13],[1,"\\n "],[8,[39,28],null,[["@item","@withInfo"],[[30,8,["Service"]],true]],null],[1,"\\n "],[8,[39,29],null,[["@item","@withInfo"],[[30,8,["Service"]],true]],null],[1,"\\n "],[8,[39,30],null,[["@item"],[[30,8,["Service"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["nav"]],[["default"],[[[[1,"\\n"],[41,[28,[37,23],[[30,8,["Service","Kind"]],"mesh-gateway"],null],[[[1," "],[8,[39,31],null,[["@items"],[[28,[37,32],[[28,[37,33],[[52,[30,10,["topology"]],[28,[37,4],null,[["label","href","selected"],["Topology",[28,[37,27],["dc.services.show.topology"],null],[28,[37,34],["dc.services.show.topology"],null]]]],""],[52,[30,10,["services"]],[28,[37,4],null,[["label","href","selected"],["Linked Services",[28,[37,27],["dc.services.show.services"],null],[28,[37,34],["dc.services.show.services"],null]]]],""],[52,[30,10,["upstreams"]],[28,[37,4],null,[["label","href","selected"],["Upstreams",[28,[37,27],["dc.services.show.upstreams"],null],[28,[37,34],["dc.services.show.upstreams"],null]]]],""],[52,[30,10,["instances"]],[28,[37,4],null,[["label","href","selected"],["Instances",[28,[37,27],["dc.services.show.instances"],null],[28,[37,34],["dc.services.show.instances"],null]]]],""],[52,[30,10,["intentions"]],[28,[37,4],null,[["label","href","selected"],["Intentions",[28,[37,27],["dc.services.show.intentions"],null],[28,[37,34],["dc.services.show.intentions"],null]]]],""],[52,[30,10,["routing"]],[28,[37,4],null,[["label","href","selected"],["Routing",[28,[37,27],["dc.services.show.routing"],null],[28,[37,34],["dc.services.show.routing"],null]]]],""],[52,[30,10,["tags"]],[28,[37,4],null,[["label","href","selected"],["Tags",[28,[37,27],["dc.services.show.tags"],null],[28,[37,34],["dc.services.show.tags"],null]]]],""]],null]],null]]],null],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[8,[39,12],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/ui-config",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n"],[41,[30,15,["data","dashboard_url_templates","service"]],[[[1," "],[8,[39,13],[[24,0,"external-dashboard"]],[["@href","@external"],[[28,[37,35],[[30,15,["data","dashboard_url_templates","service"]],[28,[37,4],null,[["Datacenter","Service"],[[30,9,["Name"]],[28,[37,4],null,[["Name","Namespace","Partition"],[[30,8,["Service","Service"]],[28,[37,21],[[30,8,["Service","Namespace"]],""],null],[28,[37,21],[[30,8,["Service","Partition"]],""],null]]]]]]]],null],true]],[["default"],[[[[1,"\\n Open dashboard\\n "]],[]]]]],[1,"\\n"]],[]],null],[1," "]],[15]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n"],[41,[28,[37,21],[[28,[37,16],[[30,8,["IsOrigin"]]],null],[33,17]],null],[[[1," "],[8,[39,36],null,[["@name","@model"],[[99,1,["@name"]],[28,[37,37],[[28,[37,4],null,[["items","proxies","item","tabs"],[[30,7],[33,15],[30,8],[30,10]]]],[30,1,["model"]]],null]]],[["default"],[[[[1,"\\n "],[46,[28,[37,39],null,null],null,null,null],[1,"\\n "]],[16]]]]],[1,"\\n"]],[]],null],[1," "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[10]]]],[7,8,9]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]]],["route","loader","after","T","T","T","items","item","dc","tabs","status","type","item","error","config","o"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","if","eq","hds/toast","notification","let","data-source","action","mut","proxies","not","chain","did-insert","set","and","or","gt","not-eq","can","app-view","topology-metrics/notifications","href-to","consul/external-source","consul/kind","consul/peer/info","tab-nav","compact","array","is-href","render-template","outlet","assign","component","-outlet"]]',moduleName:"consul-ui/templates/dc/services/show.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/show/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"eJ7jOopO",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[41,[30,1,["model","tabs","topology"]],[[[1," "],[1,[28,[35,3],[[28,[37,4],["replaceWith","dc.services.show.topology"],null]],null]],[1,"\\n"]],[]],[[[41,[30,1,["model","tabs","upstreams"]],[[[1," "],[1,[28,[35,3],[[28,[37,4],["replaceWith","dc.services.show.upstreams"],null]],null]],[1,"\\n"]],[]],[[[41,[30,1,["model","tabs","services"]],[[[1," "],[1,[28,[35,3],[[28,[37,4],["replaceWith","dc.services.show.services"],null]],null]],[1,"\\n"]],[]],[[[1," "],[1,[28,[35,3],[[28,[37,4],["replaceWith","dc.services.show.instances"],null]],null]],[1,"\\n"]],[]]]],[]]]],[]]]],[1]]]]],[1,"\\n"]],["route"],false,["route","routeName","if","did-insert","route-action"]]',moduleName:"consul-ui/templates/dc/services/show/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/show/instances",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"MHlhY9We",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[44,[[28,[37,3],null,[["value","change"],[[28,[37,4],[[33,5],"Status:asc"],null],[28,[37,6],[[30,0],[28,[37,7],[[33,5]],null]],[["value"],["target.selected"]]]]]],[28,[37,3],null,[["status","source","searchproperty"],[[28,[37,3],null,[["value","change"],[[52,[33,9],[28,[37,10],[[33,9],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,9]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change"],[[52,[33,11],[28,[37,10],[[33,11],","],null],[27]],[28,[37,6],[[30,0],[28,[37,7],[[33,11]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,3],null,[["value","change","default"],[[52,[28,[37,12],[[33,13],[27]],null],[28,[37,10],[[33,13],","],null],[33,14]],[28,[37,6],[[30,0],[28,[37,7],[[33,13]],null]],[["value"],["target.selectedItems"]]],[33,14]]]]]]],[30,1,["model","items"]],[30,1,["model","proxies","firstObject"]]],[[[41,[28,[37,15],[[30,4,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,16],null,[["@sources","@search","@onsearch","@sort","@filter"],[[28,[37,17],[[28,[37,18],[[30,4]],null],"ExternalSources"],null],[99,19,["@search"]],[28,[37,6],[[30,0],[28,[37,7],[[33,19]],null]],[["value"],["target.value"]]],[30,2],[30,3]]],null],[1,"\\n"]],[]],null],[41,[30,5,["ServiceName"]],[[[1," "],[8,[39,20],null,[["@src","@onchange"],[[28,[37,21],["/${partition}/${nspace}/${dc}/service-instances/for-service/${name}/${peer}",[28,[37,3],null,[["partition","nspace","dc","name","peer"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,5,["ServiceName"]],[30,1,["params","peer"]]]]]],null],[28,[37,6],[[30,0],[28,[37,7],[[33,22]],null]],[["value"],["data"]]]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,23],null,[["@type","@sort","@filters","@search","@items"],["service-instance",[30,2,["value"]],[30,3],[99,19,["@search"]],[30,4]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,24],null,[["@routeName","@items","@proxies"],["dc.services.instance",[30,6,["items"]],[99,22,["@proxies"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,25],null,null,[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,27],["routes.dc.services.show.instances.empty"],[["items","htmlSafe"],[[30,4,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[2,3,4,5]]],[13],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","sort","filters","items","proxyMeta","collection"],false,["route","routeName","let","hash","or","sortBy","action","mut","if","status","split","source","not-eq","searchproperty","searchProperties","gt","consul/service-instance/search-bar","get","collection","search","data-source","uri","proxies","data-collection","consul/service-instance/list","empty-state","block-slot","t"]]',moduleName:"consul-ui/templates/dc/services/show/instances.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/show/intentions",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"NPdMmDjz",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name","@model"],[[99,1,["@name"]],[30,1,["model"]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,4],null,null],null,null,null],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","o"],false,["route","routeName","outlet","component","-outlet"]]',moduleName:"consul-ui/templates/dc/services/show/intentions.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/show/intentions/edit",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"p1PxhBqH",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[44,[[28,[37,3],[[28,[37,4],["write intention for service"],[["item"],[[33,5,["Service"]]]]]],null]],[[[1," "],[8,[39,6],null,[["@src"],[[28,[37,7],["/${partition}/${nspace}/${dc}/intention/${id}",[28,[37,8],null,[["partition","nspace","dc","id"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[28,[37,9],[[30,1,["params","intention_id"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,10],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,11],null,[["@error","@login"],[[30,3,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,10],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,3,["data"]]],[[[1," "],[8,[39,12],null,[["@readonly","@item","@dc","@nspace","@partition","@autofill","@onsubmit"],[[30,2],[30,4],[30,1,["model","dc"]],[30,1,["params","nspace"]],[30,1,["params","partition"]],[28,[37,8],null,[["DestinationName"],[[30,1,["params","name"]]]]],[28,[37,13],["dc.services.show.intentions.index"],null]]],null],[1,"\\n"]],[4]]],[1," "]],[]]]]],[1,"\\n"]],[3]]]]],[1,"\\n"]],[2]]]],[1]]]]],[1,"\\n"]],["route","readOnly","loader","item"],false,["route","routeName","let","not","can","item","data-loader","uri","hash","or","block-slot","error-state","consul/intention/form","transition-to"]]',moduleName:"consul-ui/templates/dc/services/show/intentions/edit.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/show/intentions/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"wTdxLnel",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/intentions/for-service/${slug}",[28,[37,4],null,[["partition","nspace","dc","slug"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error"],[[30,2,["error"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Action:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["access","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,15],[[33,16],[27]],null],[28,[37,14],[[33,16],","],null],[33,17]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]],[33,17]]]]]]],[30,2,["data"]],[30,1,["model","item"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[41,[28,[37,18],["create intention for service"],[["item"],[[30,6,["Service"]]]]],[[[1," "],[8,[39,19],null,[["@target"],["app-view-actions"]],[["default"],[[[[1,"\\n "],[8,[39,20],null,[["@text","@route"],["Create","dc.services.show.intentions.create"]],null],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[41,[28,[37,21],[[30,5,["length"]],0],null],[[[1," "],[8,[39,22],null,[["@search","@onsearch","@sort","@filter"],[[99,23,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,23]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,24],null,[["@sink","@type","@ondelete"],[[28,[37,3],["/${partition}/${dc}/${nspace}/intention/",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null],"intention",[99,25,["@ondelete"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,26],null,[["@type","@sort","@filters","@search","@items"],["intention",[30,3,["value"]],[30,4],[99,23,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,8,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,27],null,[["@items","@check","@delete"],[[30,8,["items"]],[99,23,["@check"]],[30,7,["delete"]]]],[["default"],[[[[1,"\\n "],[8,[30,9,["CustomResourceNotice"]],null,null,null],[1,"\\n "],[8,[30,9,["CheckNotice"]],null,null,null],[1,"\\n "],[8,[30,9,["Table"]],null,[["@routeName"],["dc.services.show.intentions.edit"]],null],[1,"\\n "]],[9]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,8,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,28],null,[["@login"],[[30,1,["model","app","login","open"]]]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,29],["routes.dc.services.show.intentions.index.empty.header"],[["items"],[[30,5,["length"]]]]]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,29],["routes.dc.services.show.intentions.index.empty.body"],[["items","canUseACLs","htmlSafe"],[[30,5,["length"]],[28,[37,18],["use acls"],null],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,5],null,[["@name"],["actions"]],[["default"],[[[[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,30],null,[["@text","@href","@icon","@iconPosition","@size"],["Documentation on intentions",[29,[[28,[37,31],["CONSUL_DOCS_URL"],null],"/commands/intention"]],"docs-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "],[10,"li"],[12],[1,"\\n "],[8,[39,30],null,[["@text","@href","@icon","@iconPosition","@size"],["Take the tutorial",[29,[[28,[37,31],["CONSUL_DOCS_LEARN_URL"],null],"/consul/getting-started/connect"]],"learn-link","trailing","small"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[8]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "],[13],[1,"\\n"]],[3,4,5,6]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","api","sort","filters","items","item","writer","collection","list"],false,["route","routeName","data-loader","uri","hash","block-slot","error-state","let","or","sortBy","action","mut","if","access","split","not-eq","searchproperty","searchProperties","can","portal","hds/button","gt","consul/intention/search-bar","search","data-writer","refresh-route","data-collection","consul/intention/list","empty-state","t","hds/link/standalone","env"]]',moduleName:"consul-ui/templates/dc/services/show/intentions/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/show/routing",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"l1rtBpJx",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/discovery-chain/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n "],[8,[39,7],null,[["@chain"],[[30,2,["data","Chain"]]]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","consul/discovery-chain"]]',moduleName:"consul-ui/templates/dc/services/show/routing.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/show/services",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"dmCrfo63",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/gateways/for-service/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Status:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["instance","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,15],[[33,16],[27]],null],[28,[37,14],[[33,16],","],null],[33,17]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]],[33,17]]]]]]],[30,2,["data"]]],[[[41,[28,[37,18],[[30,5,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,19],null,[["@search","@onsearch","@sort","@filter"],[[99,20,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,20]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "],[8,[39,21],null,[["@type","@sort","@filters","@search","@items"],["service",[30,3,["value"]],[30,4],[99,20,["@search"]],[30,5]]],[["default"],[[[[1,"\\n "],[8,[30,6,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,22],["routes.dc.services.show.services.intro"],[["htmlSafe"],[true]]]],[1,"\\n "],[8,[39,23],null,[["@nspace","@partition","@items"],[[28,[37,8],[[30,1,["params","nspace"]],[30,1,["model","user","token","Namespace"]],"default"],null],[28,[37,8],[[30,1,["params","partition"]],[30,1,["model","user","token","Partition"]],"default"],null],[30,6,["items"]]]],[["default"],[[[[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,6,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,24],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,22],["routes.dc.services.show.services.empty"],[["items","htmlSafe"],[[30,5,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[3,4,5]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","sort","filters","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","instance","split","not-eq","searchproperty","searchProperties","gt","consul/upstream/search-bar","search","data-collection","t","consul/service/list","empty-state"]]',moduleName:"consul-ui/templates/dc/services/show/services.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/show/tags",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"dY7xSJxb",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[44,[[28,[37,3],[[28,[37,4],["Tags",[30,1,["model","items"]]],null]],null]],[[[41,[28,[37,6],[[30,2,["length"]],0],null],[[[1," "],[8,[39,7],null,[["@item"],[[28,[37,8],null,[["Tags"],[[30,2]]]]]],null],[1,"\\n"]],[]],[[[1," "],[8,[39,9],null,null,[["default"],[[[[1,"\\n "],[8,[39,10],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,11],["routes.dc.services.show.tags.empty.header"],null]],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,10],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,11],["routes.dc.services.show.tags.empty.body"],[["htmlSafe"],[true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]]]],[2]]],[1," "],[13],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","tags"],false,["route","routeName","let","flatten","map-by","if","gt","tag-list","hash","empty-state","block-slot","t"]]',moduleName:"consul-ui/templates/dc/services/show/tags.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/show/topology",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"ezCjemo1",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/topology/${name}/${kind}",[28,[37,4],null,[["partition","nspace","dc","name","kind"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]],[28,[37,5],[[30,1,["model","items","firstObject","Service","Kind"]],""],null]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[30,1,["params","nspace"]],[30,1,["model","dc"]],[30,1,["model","items"]],[30,2,["data"]]],[[[1," "],[10,0],[14,0,"tab-section"],[12],[1,"\\n\\n "],[10,0],[14,0,"topology-notices"],[12],[1,"\\n "],[8,[39,9],null,[["@expanded"],[true]],[["default"],[[[[1,"\\n"],[44,[[28,[37,10],[[28,[37,11],[[28,[37,11],["filtered-by-acls",[28,[37,5],[false,[30,6,["FilteredByACLs"]]],null]],null],[28,[37,11],["default-allow",[28,[37,5],[false,[28,[37,12],[[30,4,["DefaultACLPolicy"]],"allow"],null]],null]],null],[28,[37,11],["wildcard-intention",[28,[37,5],[false,[30,6,["wildcardIntention"]]],null]],null],[28,[37,11],["not-defined-intention",[28,[37,5],[false,[30,6,["notDefinedIntention"]]],null]],null],[28,[37,11],["no-dependencies",[28,[37,5],[false,[28,[37,13],[[30,6,["noDependencies"]],[28,[37,14],["use acls"],null]],null]],null]],null],[28,[37,11],["acls-disabled",[28,[37,5],[false,[28,[37,13],[[30,6,["noDependencies"]],[28,[37,15],[[28,[37,14],["use acls"],null]],null]],null]],null]],null]],null]],null]],[[[1,"\\n"],[44,[[28,[37,16],[false,[28,[37,17],[[30,8]],null]],null]],[[[1,"\\n"],[42,[28,[37,19],[[30,8]],null],null,[[[41,[30,10],[[[1," "],[8,[30,7,["Details"]],null,[["@auto"],[false]],[["default"],[[[[1,"\\n "],[8,[39,21],[[16,1,[30,12,["id"]]],[24,0,"mb-3 mt-2 topology-metrics-notice"]],[["@type","@color"],["inline",[52,[28,[37,22],[[30,11],[28,[37,11],["filtered-by-acls","no-dependencies"],null]],null],"neutral","warning"]]],[["default"],[[[[1,"\\n "],[8,[30,13,["Title"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,1,["t"]],"notice.${prop}.header",[28,[37,4],null,[["prop"],[[30,11]]]]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"],[41,[30,7,["expanded"]],[[[1," "],[8,[30,13,["Description"]],null,null,[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,1,["t"]],"notice.${prop}.body",[28,[37,4],null,[["prop"],[[30,11]]]]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[41,[28,[37,13],[[30,7,["expanded"]],[28,[37,25],[[30,11],"filtered-by-acls"],null]],null],[[[41,[28,[37,22],[[30,11],[28,[37,11],["wildcard-intention","default-allow","no-intentions"],null]],null],[[[1," "],[8,[30,13,["Button"]],null,[["@color","@size","@route","@text","@icon"],["secondary","small","dc.services.show.intentions",[28,[37,23],[[28,[37,24],[[30,1,["t"]],"notice.${prop}.footer.link-text",[28,[37,4],null,[["prop"],[[30,11]]]]],null]],null],[28,[37,23],[[28,[37,24],[[30,1,["t"]],"notice.${prop}.footer.icon",[28,[37,4],null,[["prop"],[[30,11]]]]],null]],null]]],null],[1,"\\n"]],[]],[[[1," "],[8,[30,13,["Link::Standalone"]],null,[["@text","@href","@icon","@iconPosition"],[[28,[37,23],[[28,[37,24],[[30,1,["t"]],"notice.${prop}.footer.link-text",[28,[37,4],null,[["prop"],[[30,11]]]]],null]],null],[28,[37,23],[[28,[37,24],[[30,1,["t"]],"notice.${prop}.footer.link",[28,[37,4],null,[["prop"],[[30,11]]]]],null]],null],"docs-link","trailing"]],null],[1,"\\n"]],[]]]],[]],null],[1," "]],[13]]]]],[1,"\\n "]],[12]]]]],[1,"\\n"]],[]],null]],[10,11]],null],[1,"\\n"],[41,[28,[37,26],[[30,9,["length"]],2],null],[[[1," "],[8,[30,7,["Action"]],[[4,[38,27],["click",[30,7,["toggle"]]],null]],null,[["default"],[[[[1,"\\n "],[1,[28,[35,23],[[28,[37,24],[[30,1,["t"]],"notices.${expanded}",[28,[37,4],null,[["expanded"],[[52,[30,7,["expanded"]],"close","open"]]]]],null]],null]],[1,"\\n "]],[]]]]],[1,"\\n"]],[]],null],[1,"\\n"]],[9]]]],[8]]],[1," "]],[7]]]]],[1,"\\n\\n "],[13],[1,"\\n\\n\\n "],[8,[39,28],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/ui-config",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n"],[41,[30,14,["data"]],[[[1,"\\n "],[8,[39,29],null,[["@nspace","@dc","@service","@topology","@metricsHref","@isRemoteDC","@hasMetricsProvider","@oncreate"],[[30,3],[30,4],[30,5,["firstObject"]],[30,6],[28,[37,30],[[30,14,["data","dashboard_url_templates","service"]],[28,[37,4],null,[["Datacenter","Service"],[[30,4,["Name"]],[28,[37,4],null,[["Name","Namespace","Partition"],[[30,5,["firstObject","Name"]],[28,[37,5],[[30,5,["firstObject","Namespace"]],""],null],[28,[37,5],[[30,5,["firstObject","Partition"]],""],null]]]]]]]],null],[28,[37,15],[[30,4,["Local"]]],null],[28,[37,26],[[30,14,["data","metrics_provider","length"]],0],null],[28,[37,31],["createIntention"],null]]],null],[1,"\\n\\n"]],[]],null],[1," "]],[14]]]]],[1,"\\n "],[13],[1,"\\n"]],[3,4,5,6]]],[1," "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","nspace","dc","items","topology","disclosure","notices","noticesEnabled","enabled","prop","details","A","config"],false,["route","routeName","data-loader","uri","hash","or","block-slot","app-error","let","disclosure","from-entries","array","eq","and","can","not","without","values","each","-each-in","if","hds/alert","includes","compute","fn","not-eq","gt","on","data-source","topology-metrics","render-template","route-action"]]',moduleName:"consul-ui/templates/dc/services/show/topology.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/services/show/upstreams",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"Mpl+Le50",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/gateways/for-service/${name}",[28,[37,4],null,[["partition","nspace","dc","name"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]],[30,1,["params","name"]]]]]],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,5],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,6],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,5],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n"],[44,[[28,[37,4],null,[["value","change"],[[28,[37,8],[[33,9],"Status:asc"],null],[28,[37,10],[[30,0],[28,[37,11],[[33,9]],null]],[["value"],["target.selected"]]]]]],[28,[37,4],null,[["instance","searchproperty"],[[28,[37,4],null,[["value","change"],[[52,[33,13],[28,[37,14],[[33,13],","],null],[27]],[28,[37,10],[[30,0],[28,[37,11],[[33,13]],null]],[["value"],["target.selectedItems"]]]]]],[28,[37,4],null,[["value","change","default"],[[52,[28,[37,15],[[33,16],[27]],null],[28,[37,14],[[33,16],","],null],[33,17]],[28,[37,10],[[30,0],[28,[37,11],[[33,16]],null]],[["value"],["target.selectedItems"]]],[33,17]]]]]]],[28,[37,8],[[30,1,["params","partition"]],[30,1,["model","user","token","Partition"]],"default"],null],[28,[37,8],[[30,1,["params","nspace"]],[30,1,["model","user","token","Namespace"]],"default"],null],[30,1,["params","dc"]],[30,2,["data"]]],[[[41,[28,[37,18],[[30,8,["length"]],0],null],[[[1," "],[10,"input"],[14,1,"toolbar-toggle"],[14,4,"checkbox"],[12],[13],[1,"\\n "],[8,[39,19],null,[["@search","@onsearch","@sort","@filter"],[[99,20,["@search"]],[28,[37,10],[[30,0],[28,[37,11],[[33,20]],null]],[["value"],["target.value"]]],[30,3],[30,4]]],null],[1,"\\n"]],[]],null],[1," "],[1,[28,[35,21],["routes.dc.services.show.upstreams.intro"],[["htmlSafe"],[true]]]],[1,"\\n "],[8,[39,22],null,[["@type","@sort","@filters","@search","@items"],["service",[30,3,["value"]],[30,4],[99,20,["@search"]],[30,8]]],[["default"],[[[[1,"\\n "],[8,[30,9,["Collection"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,23],null,[["@items","@dc","@nspace","@partition"],[[30,9,["items"]],[30,7],[30,6],[30,5]]],[["default"],[[[[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[30,9,["Empty"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,24],null,null,[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@name"],["body"]],[["default"],[[[[1,"\\n "],[1,[28,[35,21],["routes.dc.services.show.upstreams.empty"],[["items","htmlSafe"],[[30,8,["length"]],true]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n "]],[9]]]]],[1,"\\n"]],[3,4,5,6,7,8]]],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","sort","filters","partition","nspace","dc","items","collection"],false,["route","routeName","data-loader","uri","hash","block-slot","app-error","let","or","sortBy","action","mut","if","instance","split","not-eq","searchproperty","searchProperties","gt","consul/upstream/search-bar","search","t","data-collection","consul/upstream/list","empty-state"]]',moduleName:"consul-ui/templates/dc/services/show/upstreams.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/show",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"cTe8wXVf",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,null,[["default"],[[[[1,"\\n "],[8,[39,3],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],[[28,[37,4],[[28,[37,5],[[30,1,["t"]],"title"],null]],null]]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,3],null,[["@name"],["toolbar"]],[["default"],[[[[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,3],null,[["@name"],["nav"]],[["default"],[[[[1,"\\n\\n"],[44,[[28,[37,7],[[28,[37,8],[[28,[37,8],["serverstatus",[28,[37,4],[[28,[37,5],[[30,1,["exists"]],"serverstatus"],null]],null]],null],[28,[37,8],["cataloghealth",false],null],[28,[37,8],["license",[28,[37,4],[[28,[37,5],[[30,1,["exists"]],"license"],null]],null]],null]],null]],null]],[[[1,"\\n"],[44,[[28,[37,9],[false,[28,[37,10],[[30,2]],null]],null]],[[[1,"\\n"],[41,[28,[37,12],[[30,3,["length"]],1],null],[[[1," "],[8,[39,13],null,[["@items"],[[28,[37,14],[[28,[37,8],[[52,[30,2,["serverstatus"]],[28,[37,15],null,[["label","href","selected"],[[28,[37,4],[[28,[37,5],[[30,1,["t"]],"serverstatus.title"],null]],null],[28,[37,16],["dc.show.serverstatus"],null],[28,[37,17],["dc.show.serverstatus"],null]]]],""],[52,[30,2,["cataloghealth"]],[28,[37,15],null,[["label","href","selected"],[[28,[37,4],[[28,[37,5],[[30,1,["t"]],"cataloghealth.title"],null]],null],[28,[37,16],["dc.show.cataloghealth"],null],[28,[37,17],["dc.show.cataloghealth"],null]]]],""],[52,[30,2,["license"]],[28,[37,15],null,[["label","href","selected"],[[28,[37,4],[[28,[37,5],[[30,1,["t"]],"license.title"],null]],null],[28,[37,16],["dc.show.license"],null],[28,[37,17],["dc.show.license"],null]]]]],""],null]],null]]],null],[1,"\\n"]],[]],null],[1,"\\n"]],[3]]]],[2]]],[1," "]],[]]]]],[1,"\\n "],[8,[39,3],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,18],null,[["@name","@model"],[[99,1,["@name"]],[30,1,["model"]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,20],null,null],null,null,null],[1,"\\n "]],[4]]]]],[1,"\\n "]],[]]]]],[1,"\\n\\n "]],[]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","tabs","tabsEnabled","o"],false,["route","routeName","app-view","block-slot","compute","fn","let","from-entries","array","without","values","if","gt","tab-nav","compact","hash","href-to","is-href","outlet","component","-outlet"]]',moduleName:"consul-ui/templates/dc/show.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/show/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"vE8aBvmc",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[1,[28,[35,2],[[28,[37,3],["replaceWith",[52,[28,[37,5],["access overview"],null],"dc.show.serverstatus","dc.services.index"]],null]],null]],[1,"\\n"]],[1]]]]],[1,"\\n\\n"]],["route"],false,["route","routeName","did-insert","route-action","if","can"]]',moduleName:"consul-ui/templates/dc/show/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/show/license",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"IQuLUg96",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/license",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n"],[44,[[30,2,["data"]]],[[[1," "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,9],[[30,2,["error","status"]],"404"],null],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"This service has been deregistered and no longer exists in the catalog."]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[41,[28,[37,9],[[30,2,["error","status"]],"403"],null],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"You no longer have access to this service."]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,7,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,7,["Description"]],null,null,[["default"],[[[[1,"An error was returned whilst loading this data, refresh to try again."]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]],[]]],[1," "]],[4]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n "],[10,"section"],[15,0,[28,[37,12],["validity",[28,[37,13],["valid",[30,3,["Valid"]]],null]],null]],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,14],[[28,[37,15],[[30,1,["t"]],"expiry.header"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[10,2],[12],[1,"\\n "],[1,[28,[35,14],[[28,[37,15],[[30,1,["t"]],"expiry.${type}.body",[28,[37,4],null,[["type","date","time","htmlSafe"],[[52,[30,3,["Valid"]],"valid","expired"],[28,[37,16],[[30,3,["License","expiration_time"]]],[["year","month","day"],["numeric","long","numeric"]]],[28,[37,16],[[30,3,["License","expiration_time"]]],[["hour12","hour","hourCycle","minute","second","timeZoneName"],[true,"numeric","h12","numeric","numeric","short"]]],true]]]],null]],null]],[1,"\\n "],[13],[1,"\\n\\n "],[10,"dl"],[12],[1,"\\n "],[10,"dt"],[15,0,[28,[37,12],[[28,[37,13],["valid",[30,3,["Valid"]]],null],[28,[37,13],["expired",[28,[37,17],[[30,3,["Valid"]]],null]],null],[28,[37,13],["warning",[28,[37,18],[[30,3,["License","expiration_time"]],2629800000],null]],null]],null]],[12],[1,"\\n "],[1,[28,[35,14],[[28,[37,15],[[30,1,["t"]],"expiry.${type}.header",[28,[37,4],null,[["type"],[[52,[30,3,["Valid"]],"valid","expired"]]]]],null]],null]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[28,[35,19],[[30,3,["License","expiration_time"]]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[10,"aside"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,14],[[28,[37,15],[[30,1,["t"]],"documentation.title"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,0],[14,0,"flex gap-1.5 flex-col"],[12],[1,"\\n "],[8,[39,20],null,[["@text","@href","@icon","@iconPosition"],[[28,[37,14],[[28,[37,15],[[30,1,["t"]],"documentation.links.license-expiration.text"],null]],null],[29,[[28,[37,21],[[28,[37,22],["CONSUL_DOCS_URL"],null],[28,[37,14],[[28,[37,15],[[30,1,["t"]],"documentation.links.license-expiration.link"],null]],null]],null]]],"docs-link","trailing"]],null],[1,"\\n "],[8,[39,20],null,[["@text","@href","@icon","@iconPosition"],[[28,[37,14],[[28,[37,15],[[30,1,["t"]],"documentation.links.renewing-license.text"],null]],null],[29,[[28,[37,21],[[28,[37,22],["CONSUL_DOCS_URL"],null],[28,[37,14],[[28,[37,15],[[30,1,["t"]],"documentation.links.renewing-license.link"],null]],null]],null]]],"docs-link","trailing"]],null],[1,"\\n "],[8,[39,20],null,[["@text","@href","@icon","@iconPosition"],[[28,[37,14],[[28,[37,15],[[30,1,["t"]],"documentation.links.applying-new-license.text"],null]],null],[29,[[28,[37,21],[[28,[37,22],["CONSUL_DOCS_URL"],null],[28,[37,14],[[28,[37,15],[[30,1,["t"]],"documentation.links.applying-new-license.link"],null]],null]],null]]],"docs-link","trailing"]],null],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[3]]],[1," "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n\\n"]],["route","loader","item","after","T","T","T"],false,["route","routeName","data-loader","uri","hash","let","block-slot","error-state","if","eq","hds/toast","notification","class-map","array","compute","fn","format-time","not","temporal-within","temporal-format","hds/link/standalone","concat","env"]]',moduleName:"consul-ui/templates/dc/show/license.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/dc/show/serverstatus",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"eg4Biu8u",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["/${partition}/${nspace}/${dc}/datacenter",[28,[37,4],null,[["partition","nspace","dc"],[[30,1,["params","partition"]],[30,1,["params","nspace"]],[30,1,["params","dc"]]]]]],null]]],[["default"],[[[[1,"\\n\\n"],[44,[[30,2,["data"]]],[[[1," "],[8,[39,6],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,7],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["disconnected"]],[["default"],[[[[1,"\\n"],[41,[28,[37,9],[[30,2,["error","status"]],"404"],null],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,5,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,5,["Description"]],null,null,[["default"],[[[[1,"This service has been deregistered and no longer exists in the catalog."]],[]]]]],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],[[[41,[28,[37,9],[[30,2,["error","status"]],"403"],null],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["critical"]],[["default"],[[[[1,"\\n "],[8,[30,6,["Title"]],null,null,[["default"],[[[[1,"Error!"]],[]]]]],[1,"\\n "],[8,[30,6,["Description"]],null,null,[["default"],[[[[1,"You no longer have access to this service."]],[]]]]],[1,"\\n "]],[6]]]]],[1,"\\n"]],[]],[[[1," "],[8,[39,10],[[4,[38,11],null,[["sticky"],[true]]]],[["@color"],["warning"]],[["default"],[[[[1,"\\n "],[8,[30,7,["Title"]],null,null,[["default"],[[[[1,"Warning!"]],[]]]]],[1,"\\n "],[8,[30,7,["Description"]],null,null,[["default"],[[[[1,"An error was returned whilst loading this data, refresh to try again."]],[]]]]],[1,"\\n "]],[7]]]]],[1,"\\n "]],[]]]],[]]],[1," "]],[4]]]]],[1,"\\n\\n "],[8,[39,6],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n "],[10,0],[14,0,"tab-section"],[12],[1,"\\n\\n "],[10,"section"],[15,0,[28,[37,12],["server-failure-tolerance"],null]],[12],[1,"\\n\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"tolerance.header"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[8,[39,15],null,[["@icon","@iconPosition","@text","@href"],["docs-link","trailing",[28,[37,13],[[28,[37,14],[[30,1,["t"]],"tolerance.link-text"],null]],null],[29,[[28,[37,16],[[28,[37,17],["CONSUL_DOCS_URL"],null],[28,[37,13],[[28,[37,14],[[30,1,["t"]],"tolerance.link"],null]],null]],null]]]]],null],[1,"\\n "],[13],[1,"\\n\\n "],[10,"section"],[15,0,[28,[37,12],[[28,[37,18],["immediate-tolerance"],null]],null]],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"tolerance.immediate.header"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[15,0,[28,[37,12],[[28,[37,18],["warning",[28,[37,19],[[28,[37,9],[[30,3,["FailureTolerance"]],0],null],[28,[37,9],[[30,3,["OptimisticFailureTolerance"]],0],null]],null]],null]],null]],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"tolerance.immediate.body"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["FailureTolerance"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n"],[41,[28,[37,20],["read zones"],null],[[[1," "],[10,"section"],[15,0,[28,[37,12],[[28,[37,18],["optimistic-tolerance"],null]],null]],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"tolerance.optimistic.header"],null]],null]],[1,"\\n "],[11,1],[4,[38,21],["With > 30 seconds between server failures, Consul can restore the Immediate Fault Tolerance by replacing failed active voters with healthy back-up voters when using redundancy zones."],null],[12],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[15,0,[28,[37,12],[[28,[37,18],["warning",[28,[37,9],[[30,3,["OptimisticFailureTolerance"]],0],null]],null]],null]],[12],[1,"\\n "],[10,"dt"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"tolerance.optimistic.body"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[10,"dd"],[12],[1,"\\n "],[1,[30,3,["OptimisticFailureTolerance"]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[13],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n\\n"],[41,[28,[37,22],[[30,3,["RedundancyZones","length"]],0],null],[[[1," "],[10,"section"],[15,0,[28,[37,12],["redundancy-zones"],null]],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,23],[[28,[37,24],["common.consul.redundancyzone"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n"],[42,[28,[37,26],[[28,[37,26],[[30,3,["RedundancyZones"]]],null]],null],null,[[[41,[28,[37,22],[[30,8,["Servers","length"]],0],null],[[[1," "],[10,"section"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[30,8,["Name"]]],[1,"\\n "],[13],[1,"\\n "],[10,"dl"],[15,0,[28,[37,12],[[28,[37,18],["warning",[28,[37,9],[[30,8,["FailureTolerance"]],0],null]],null]],null]],[12],[1,"\\n "],[10,"dt"],[12],[1,[28,[35,24],["common.consul.failuretolerance"],null]],[13],[1,"\\n "],[10,"dd"],[12],[1,[30,8,["FailureTolerance"]]],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,27],null,[["@items"],[[30,8,["Servers"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[8]],null],[1,"\\n"],[41,[28,[37,22],[[30,3,["Default","Servers","length"]],0],null],[[[1," "],[10,"section"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h3"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"unassigned"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,27],null,[["@items"],[[30,3,["Default","Servers"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1,"\\n "],[13],[1,"\\n"]],[]],[[[1," "],[10,"section"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,13],[[28,[37,14],[[30,1,["t"]],"servers"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[8,[39,27],null,[["@items"],[[30,3,["Default","Servers"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[]]],[1,"\\n"],[41,[28,[37,22],[[30,3,["ReadReplicas","length"]],0],null],[[[1," "],[10,"section"],[12],[1,"\\n "],[10,"header"],[12],[1,"\\n "],[10,"h2"],[12],[1,"\\n "],[1,[28,[35,23],[[28,[37,24],["common.consul.readreplica"],null]],null]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[8,[39,27],null,[["@items"],[[30,3,["ReadReplicas"]]]],null],[1,"\\n "],[13],[1,"\\n"]],[]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n"]],[3]]],[1," "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n\\n"]],["route","loader","item","after","T","T","T","item"],false,["route","routeName","data-loader","uri","hash","let","block-slot","error-state","if","eq","hds/toast","notification","class-map","compute","fn","hds/link/standalone","concat","env","array","and","can","tooltip","gt","pluralize","t","each","-track-array","consul/server/list"]]',moduleName:"consul-ui/templates/dc/show/serverstatus.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/error",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"bZdlAt9b",block:'[[[1,"\\n"],[41,[33,1],[[[8,[39,2],null,[["@error"],[[99,1,["@error"]]]],null],[1,"\\n"]],[]],null]],[],false,["if","error","app-error"]]',moduleName:"consul-ui/templates/error.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/index",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"CJ8DiXUS",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@name","@model"],[[99,1,["@name"]],[30,1,["model"]]]],[["default"],[[[[1,"\\n "],[46,[28,[37,4],null,null],null,null,null],[1,"\\n "]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","o"],false,["route","routeName","outlet","component","-outlet"]]',moduleName:"consul-ui/templates/index.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/loading",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"5kbK/dah",block:'[[[1,"\\n"]],[],false,[]]',moduleName:"consul-ui/templates/loading.hbs",isStrictMode:!1}) +e.default=n})) +define("consul-ui/templates/notfound",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"qt+16XBx",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@login","@error"],[[30,1,["model","app","login","open"]],[28,[37,3],null,[["status","message"],[404,"Unable to find that page"]]]]],null],[1,"\\n"]],[1]]]]],[1,"\\n\\n"]],["route"],false,["route","routeName","app-error","hash"]]',moduleName:"consul-ui/templates/notfound.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/oauth-provider-debug",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"Lxy3wDlI",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[10,0],[14,5,"width: 50%;margin: 0 auto;"],[12],[1,"\\n "],[10,"h1"],[12],[8,[30,1,["Title"]],null,[["@title"],["Mock OAuth Provider"]],null],[13],[1,"\\n "],[10,"main"],[12],[1,"\\n "],[10,"form"],[14,"method","GET"],[15,"action",[36,2]],[12],[1,"\\n"],[44,[[28,[37,4],null,[["state","code"],["state-123456789/abcdefghijklmnopqrstuvwxyz","code-abcdefghijklmnopqrstuvwxyz/123456789"]]]],[[[1," "],[8,[39,5],null,[["@name","@label","@item","@help"],["state","State",[30,2],"The OIDC state value that will get passed through to Consul"]],null],[1,"\\n "],[8,[39,5],null,[["@name","@label","@item","@help"],["code","Code",[30,2],"The OIDC code value that will get passed through to Consul"]],null],[1,"\\n"]],[2]]],[1," "],[8,[39,6],null,[["@type"],["submit"]],[["default"],[[[[1,"\\n Login\\n "]],[]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"],[13],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","item"],false,["route","routeName","redirect_uri","let","hash","text-input","action"]]',moduleName:"consul-ui/templates/oauth-provider-debug.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/settings",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"GXqC0vCH",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n "],[8,[39,2],null,[["@src"],[[28,[37,3],["settings://consul:client"],null]]],[["default"],[[[[1,"\\n\\n "],[8,[39,4],null,[["@name"],["error"]],[["default"],[[[[1,"\\n "],[8,[39,5],null,[["@error","@login"],[[30,2,["error"]],[30,1,["model","app","login","open"]]]],null],[1,"\\n "]],[]]]]],[1,"\\n\\n "],[8,[39,4],null,[["@name"],["loaded"]],[["default"],[[[[1,"\\n"],[44,[[28,[37,7],[[30,2,["data"]],[28,[37,8],null,[["blocking"],[true]]]],null]],[[[1," "],[8,[39,9],null,null,[["default"],[[[[1,"\\n "],[8,[39,4],null,[["@name"],["header"]],[["default"],[[[[1,"\\n "],[10,"h1"],[12],[1,"\\n "],[8,[30,1,["Title"]],null,[["@title"],["Settings"]],null],[1,"\\n "],[13],[1,"\\n "]],[]]]]],[1,"\\n "],[8,[39,4],null,[["@name"],["content"]],[["default"],[[[[1,"\\n "],[8,[39,10],[[24,0,"mb-3 mt-2"]],[["@type"],["inline"]],[["default"],[[[[1,"\\n "],[8,[30,4,["Title"]],null,null,[["default"],[[[[1,"Local Storage"]],[]]]]],[1,"\\n "],[8,[30,4,["Description"]],null,null,[["default"],[[[[1,"These settings are immediately saved to local storage and persisted through browser usage."]],[]]]]],[1,"\\n "]],[4]]]]],[1,"\\n "],[10,"form"],[12],[1,"\\n"],[41,[28,[37,12],[[28,[37,13],["CONSUL_UI_DISABLE_REALTIME"],null]],null],[[[1," "],[8,[39,14],null,null,[["default"],[[[[1,"\\n "],[8,[30,5,["Details"]],null,null,[["default"],[[[[1,"\\n "],[8,[39,15],null,[["@data","@sink","@onchange"],[[30,3],"settings://consul:client",[28,[37,16],[[30,0],[28,[37,17],[[30,5,["close"]]],null]],null]]],null],[1,"\\n "]],[]]]]],[1,"\\n "],[10,"fieldset"],[12],[1,"\\n "],[10,"h2"],[12],[1,"Blocking Queries"],[13],[1,"\\n "],[10,2],[12],[1,"Keep catalog info up-to-date without refreshing the page. Any changes made to services, nodes and intentions would be reflected in real time."],[13],[1,"\\n "],[10,0],[14,0,"type-toggle"],[12],[1,"\\n "],[10,"label"],[12],[1,"\\n "],[11,"input"],[24,3,"client[blocking]"],[16,"checked",[52,[30,3,["blocking"]],"checked"]],[24,4,"checkbox"],[4,[38,18],["change",[28,[37,19],[[28,[37,20],[[30,3],"blocking",[28,[37,12],[[30,3,["blocking"]]],null]],null],[28,[37,17],[[30,5,["open"]]],null]],null]],null],[12],[13],[1,"\\n "],[10,1],[12],[1,[52,[30,3,["blocking"]],"On","Off"]],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "]],[5]]]]],[1,"\\n"]],[]],null],[1," "],[13],[1,"\\n "]],[]]]]],[1,"\\n "]],[]]]]],[1,"\\n"]],[3]]],[1," "]],[]]]]],[1,"\\n"]],[2]]]]],[1,"\\n"]],[1]]]]],[1,"\\n"]],["route","loader","item","A","disclosure"],false,["route","routeName","data-loader","uri","block-slot","app-error","let","or","hash","app-view","hds/alert","if","not","env","disclosure","data-sink","action","fn","on","queue","set"]]',moduleName:"consul-ui/templates/settings.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/templates/unavailable",["exports","@ember/template-factory"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=(0,t.createTemplateFactory)({id:"hP024biE",block:'[[[1,"\\n"],[8,[39,0],null,[["@name"],[[99,1,["@name"]]]],[["default"],[[[[1,"\\n"],[41,[28,[37,3],["CONSUL_V2_CATALOG_ENABLED"],null],[[[1," "],[10,0],[14,0,"h-screen w-full flex flex-col justify-center items-center"],[12],[1,"\\n "],[10,0],[12],[1,"\\n "],[10,"svg"],[14,"width","149"],[14,"height","39"],[14,"viewBox","0 0 149 39"],[14,"fill","none"],[14,"xmlns","http://www.w3.org/2000/svg","http://www.w3.org/2000/xmlns/"],[14,0,"mb-8"],[12],[1,"\\n "],[10,"g"],[14,"clip-path","url(#clip0_2336_115454)"],[12],[1,"\\n "],[10,"path"],[14,"d","M54.6631 13.8631C54.6631 9.36592 57.3284 6.74561 63.5515 6.74561C65.8492 6.7447 68.1385 7.01683 70.3697 7.55608L69.8428 11.578C67.8266 11.2067 65.7822 11.0028 63.7313 10.9686C60.4647 10.9686 59.3924 12.0715 59.3924 14.6919V24.1128C59.3924 26.727 60.4399 27.8361 63.7313 27.8361C65.7822 27.8018 67.8266 27.598 69.8428 27.2267L70.3697 31.2486C68.1385 31.7878 65.8492 32.06 63.5515 32.059C57.3532 32.059 54.6631 29.4387 54.6631 24.9415V13.8631Z"],[14,"fill","black"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M80.4668 32.0408C74.2003 32.0408 72.5205 28.6405 72.5205 24.9843V20.4262C72.5205 16.7394 74.2065 13.3452 80.473 13.3452C86.7395 13.3452 88.4193 16.7394 88.4193 20.4262V24.9843C88.4131 28.6405 86.7271 32.0408 80.4668 32.0408ZM80.4668 17.1782C78.0246 17.1782 77.0887 18.2507 77.0887 20.2799V25.1061C77.0887 27.1354 78.0246 28.2018 80.4668 28.2018C82.9089 28.2018 83.8387 27.1354 83.8387 25.1061V20.2799C83.8387 18.2812 82.9027 17.1782 80.4668 17.1782Z"],[14,"fill","black"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M102.328 31.6877V19.1345C102.328 18.1778 101.913 17.6964 100.865 17.6964C99.8178 17.6964 97.7661 18.3606 96.0988 19.2077V31.6877H91.5244V13.7172H95.0141L95.4542 15.2345C97.7321 14.1126 100.223 13.4712 102.768 13.3516C105.805 13.3516 106.896 15.4539 106.896 18.6592V31.6877H102.328Z"],[14,"fill","black"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M116.312 32.0412C114.172 32.0062 112.05 31.657 110.015 31.0052L110.634 27.5805C112.403 28.0763 114.231 28.3366 116.07 28.3544C118.097 28.3544 118.395 27.9096 118.395 26.5263C118.395 25.4233 118.172 24.8688 115.209 24.168C110.746 23.1016 110.219 21.9926 110.219 18.5252C110.219 14.9116 111.831 13.3272 117.037 13.3272C118.88 13.3221 120.716 13.5265 122.511 13.9366L122.108 17.5502C120.448 17.2493 118.768 17.0762 117.081 17.0322C115.091 17.0322 114.756 17.4771 114.756 18.5801C114.756 20.0182 114.868 20.1279 117.347 20.7555C122.442 22.084 122.926 22.7482 122.926 26.4349C122.913 29.9022 121.829 32.0412 116.312 32.0412Z"],[14,"fill","black"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M130.487 13.7168V26.2516C130.487 27.2084 130.897 27.6898 131.95 27.6898C133.004 27.6898 135.049 27.0255 136.711 26.1785V13.7168H141.285V31.6873H137.802L137.349 30.176C135.071 31.2988 132.58 31.9402 130.035 32.059C126.998 32.059 125.913 29.9566 125.913 26.7452V13.7168H130.487Z"],[14,"fill","black"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M145.221 31.6877V6.38037L149.795 5.771V31.6877H145.221Z"],[14,"fill","black"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M20.1451 38.75C16.9414 38.7517 13.7857 37.9848 10.9519 36.5157C8.1181 35.0466 5.69179 32.9197 3.88359 30.3197C2.0754 27.7198 0.939957 24.7252 0.575821 21.596C0.211686 18.4668 0.629862 15.2975 1.79405 12.3632C2.95824 9.42894 4.83326 6.81831 7.25637 4.75795C9.67949 2.69759 12.5775 1.24976 15.6988 0.540121C18.8201 -0.169518 22.0704 -0.119518 25.1675 0.685782C28.2647 1.49108 31.1152 3.02734 33.4716 5.16123L28.8166 9.9631C26.9587 8.31623 24.655 7.2343 22.1844 6.84834C19.7138 6.46239 17.1824 6.78896 14.8967 7.78851C12.6111 8.78806 10.6693 10.4177 9.30646 12.4801C7.94365 14.5424 7.21832 16.9491 7.21832 19.4084C7.21832 21.8678 7.94365 24.2744 9.30646 26.3367C10.6693 28.3991 12.6111 30.0288 14.8967 31.0283C17.1824 32.0279 19.7138 32.3544 22.1844 31.9685C24.655 31.5825 26.9587 30.5006 28.8166 28.8537L33.4716 33.6373C29.842 36.9293 25.0834 38.7549 20.1451 38.75Z"],[14,"fill","#E03875"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M35.9875 29.0672C35.6688 29.0672 35.3572 28.9743 35.0922 28.8002C34.8272 28.6261 34.6206 28.3786 34.4987 28.0891C34.3767 27.7996 34.3448 27.4811 34.4069 27.1737C34.4691 26.8664 34.6226 26.5841 34.848 26.3625C35.0734 26.1409 35.3605 25.99 35.6731 25.9289C35.9858 25.8677 36.3098 25.8991 36.6043 26.019C36.8987 26.139 37.1504 26.342 37.3275 26.6026C37.5046 26.8631 37.5991 27.1695 37.5991 27.4828C37.5991 27.903 37.4293 28.306 37.1271 28.6031C36.8249 28.9003 36.415 29.0672 35.9875 29.0672Z"],[14,"fill","#E03875"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M20.0203 23.5891C19.1769 23.5891 18.3524 23.3432 17.6511 22.8825C16.9498 22.4219 16.4032 21.7671 16.0805 21.001C15.7577 20.2349 15.6733 19.392 15.8378 18.5787C16.0023 17.7654 16.4085 17.0184 17.0049 16.4321C17.6013 15.8457 18.3611 15.4464 19.1884 15.2847C20.0156 15.1229 20.873 15.2059 21.6523 15.5232C22.4315 15.8406 23.0975 16.3779 23.5661 17.0674C24.0347 17.7568 24.2848 18.5674 24.2848 19.3966C24.2848 20.5085 23.8355 21.5749 23.0358 22.3611C22.236 23.1474 21.1513 23.5891 20.0203 23.5891Z"],[14,"fill","#E03875"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M37.8411 23.6497C37.5223 23.6497 37.2107 23.5568 36.9457 23.3827C36.6807 23.2086 36.4741 22.9612 36.3522 22.6716C36.2302 22.3821 36.1983 22.0636 36.2605 21.7562C36.3226 21.4489 36.4761 21.1666 36.7015 20.945C36.9269 20.7234 37.214 20.5725 37.5267 20.5114C37.8393 20.4503 38.1633 20.4816 38.4578 20.6016C38.7523 20.7215 39.004 20.9246 39.181 21.1851C39.3581 21.4457 39.4526 21.752 39.4526 22.0653C39.451 22.485 39.2807 22.8871 38.9788 23.1839C38.6769 23.4807 38.268 23.6481 37.8411 23.6497Z"],[14,"fill","#E03875"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M33.0432 23.4671C32.7245 23.4671 32.4129 23.3742 32.1479 23.2001C31.8828 23.026 31.6763 22.7785 31.5543 22.489C31.4323 22.1995 31.4004 21.881 31.4626 21.5736C31.5248 21.2663 31.6783 20.984 31.9037 20.7624C32.129 20.5408 32.4162 20.3899 32.7288 20.3288C33.0414 20.2677 33.3655 20.299 33.6599 20.4189C33.9544 20.5389 34.2061 20.7419 34.3832 21.0025C34.5603 21.263 34.6548 21.5694 34.6548 21.8827C34.6548 22.3029 34.485 22.7059 34.1828 23.003C33.8805 23.3002 33.4706 23.4671 33.0432 23.4671Z"],[14,"fill","#E03875"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M37.8411 18.3177C37.5223 18.3177 37.2107 18.2248 36.9457 18.0507C36.6807 17.8766 36.4741 17.6291 36.3522 17.3396C36.2302 17.0501 36.1983 16.7315 36.2605 16.4242C36.3226 16.1169 36.4761 15.8346 36.7015 15.613C36.9269 15.3914 37.214 15.2405 37.5267 15.1794C37.8393 15.1182 38.1633 15.1496 38.4578 15.2695C38.7523 15.3894 39.004 15.5925 39.181 15.8531C39.3581 16.1136 39.4526 16.4199 39.4526 16.7333C39.451 17.153 39.2807 17.5551 38.9788 17.8518C38.6769 18.1486 38.268 18.3161 37.8411 18.3177Z"],[14,"fill","#E03875"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M33.0432 18.5008C32.7245 18.5008 32.4129 18.4079 32.1479 18.2338C31.8828 18.0597 31.6763 17.8122 31.5543 17.5227C31.4323 17.2332 31.4004 16.9146 31.4626 16.6073C31.5248 16.3 31.6783 16.0177 31.9037 15.7961C32.129 15.5745 32.4162 15.4236 32.7288 15.3625C33.0414 15.3013 33.3655 15.3327 33.6599 15.4526C33.9544 15.5726 34.2061 15.7756 34.3832 16.0362C34.5603 16.2967 34.6548 16.603 34.6548 16.9164C34.6548 17.3366 34.485 17.7396 34.1828 18.0367C33.8805 18.3339 33.4706 18.5008 33.0432 18.5008Z"],[14,"fill","#E03875"],[12],[13],[1,"\\n "],[10,"path"],[14,"d","M36.0803 12.9856C35.7616 12.9856 35.45 12.8927 35.185 12.7186C34.92 12.5445 34.7134 12.2971 34.5914 12.0076C34.4694 11.7181 34.4375 11.3995 34.4997 11.0922C34.5619 10.7848 34.7154 10.5025 34.9408 10.2809C35.1662 10.0594 35.4533 9.90847 35.7659 9.84734C36.0785 9.7862 36.4026 9.81758 36.697 9.9375C36.9915 10.0574 37.2432 10.2605 37.4203 10.521C37.5974 10.7816 37.6919 11.0879 37.6919 11.4013C37.6919 11.8215 37.5221 12.2245 37.2199 12.5216C36.9176 12.8187 36.5077 12.9856 36.0803 12.9856Z"],[14,"fill","#E03875"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[10,"defs"],[12],[1,"\\n "],[10,"clipPath"],[14,1,"clip0_2336_115454"],[12],[1,"\\n "],[10,"rect"],[14,"width","150"],[14,"height","39"],[14,"fill","white"],[12],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n\\n "],[8,[39,4],null,null,[["default"],[[[[1,"\\n "],[8,[30,2,["Header"]],null,[["@title"],["User Interface Unavailable"]],null],[1,"\\n "],[8,[30,2,["Body"]],null,[["@text"],["The Consul v2 catalog API (beta) is enabled, and is not yet compatible with the Consul UI."]],null],[1,"\\n "],[8,[30,2,["Footer"]],null,[["@hasDivider"],[true]],[["default"],[[[[1,"\\n "],[8,[30,3,["Link::Standalone"]],null,[["@icon","@iconPosition","@isHrefExternal","@text","@href"],["docs-link","trailing",true,"Learn more","https://developer.hashicorp.com/consul/docs/architecture/catalog/v2#constraints-and-limitations"]],null],[1,"\\n "],[8,[30,3,["Link::Standalone"]],null,[["@icon","@iconPosition","@isHrefExternal","@text","@href"],["external-link","trailing",true,"Provide feedback","https://hashicorp.sjc1.qualtrics.com/jfe/form/SV_cHDaObigIBbQneC"]],null],[1,"\\n "]],[3]]]]],[1,"\\n "]],[2]]]]],[1,"\\n "],[13],[1,"\\n "],[13],[1,"\\n"]],[]],null]],[1]]]]]],["route","A","F"],false,["route","routeName","if","env","hds/application-state"]]',moduleName:"consul-ui/templates/unavailable.hbs",isStrictMode:!1}) +e.default=n})),define("consul-ui/transforms/array",["exports","ember-data-model-fragments/transforms/array"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=t.default +e.default=n})),define("consul-ui/transforms/boolean",["exports","@ember-data/serializer/-private"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.BooleanTransform}})})),define("consul-ui/transforms/date",["exports","@ember-data/serializer/-private"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.DateTransform}})})),define("consul-ui/transforms/fragment-array",["exports","ember-data-model-fragments/transforms/fragment-array"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=t.default +e.default=n})),define("consul-ui/transforms/fragment",["exports","ember-data-model-fragments/transforms/fragment"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n=t.default +e.default=n})),define("consul-ui/transforms/number",["exports","@ember-data/serializer/-private"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.NumberTransform}})})),define("consul-ui/transforms/string",["exports","@ember-data/serializer/-private"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.StringTransform}})})),define("consul-ui/utils/ascend",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){const n=e.split("/") +return n.length>t?n.slice(0,-t).concat("").join("/"):""}})),define("consul-ui/utils/atob",["exports","base64-js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"utf-8" +const l=t.default.toByteArray(e) +return new TextDecoder(n).decode(l)}})),define("consul-ui/utils/btoa",["exports","base64-js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){const n=(new TextEncoder).encode(e) +return t.default.fromByteArray(n)}})),define("consul-ui/utils/calculate-position",["exports","ember-basic-dropdown/utils/calculate-position"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/utils/callable-type",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return"function"!=typeof e?function(){return e}:e}})),define("consul-ui/utils/create-fingerprinter",["exports","@ember/object","@ember/utils"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,l,r){let i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:JSON.stringify +return function(o,a,u,s,c){return function(d){if(null==(u=null==u?d[e]:u))throw new Error(`Unable to create fingerprint, missing foreignKey value. Looking for value in \`${e}\` got \`${u}\``) +const p=a.split(",").map((function(e){const l=(0,t.get)(d,e) +if((0,n.isEmpty)(l)){if("PeerName"===e)return +throw new Error(`Unable to create fingerprint, missing slug. Looking for value in \`${e}\` got \`${l}\``)}return l})).compact() +return void 0===d[l]&&("*"===s&&(s="default"),d[l]=s),void 0===d[r]&&("*"===c&&(c="default"),d[r]=c),void 0===d[e]&&(d[e]=u),void 0===d[o]&&(d[o]=i([d[r],d[l],u].concat(p))),d}}}})),define("consul-ui/utils/distance",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){e=e.Coord,t=t.Coord +let n=0 +for(let o=0;o0&&(r=i) +return Math.round(1e5*r)/100}})),define("consul-ui/utils/dom/click-first-anchor",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t +return function(t){let l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"tr" +switch(t.target.nodeName.toLowerCase()){case"input":case"label":case"a":case"button":return}const r=e(l,t.target).querySelector("a") +r&&n(r)}} +const t=function(e){["mousedown","mouseup","click"].map((function(e){return new MouseEvent(e,{bubbles:!0,cancelable:!0,view:window})})).forEach((function(t){e.dispatchEvent(t)}))}})),define("consul-ui/utils/dom/closest",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){try{return t.closest(e)}catch(n){return}}})),define("consul-ui/utils/dom/create-listeners",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[] +return new t(e)} +class t{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[] +this.listeners=e}add(e,n,l){let r +if("function"==typeof e)r=e +else if(e instanceof t)r=e.remove.bind(e) +else{let t="addEventListener",i="removeEventListener" +void 0===e[t]&&(t="on",i="off") +let o=n +"string"==typeof o&&(o={[n]:l}) +const a=Object.keys(o).map((function(n){return function(n,l){return e[t](n,l),function(){return e[i](n,l),l}}(n,o[n])})) +r=()=>a.map((e=>e()))}return this.listeners.push(r),()=>{const e=this.listeners.findIndex((function(e){return e===r})) +return this.listeners.splice(e,1)[0]()}}remove(){const e=this.listeners.map((e=>e())) +return this.listeners.splice(0,this.listeners.length),e}}})),define("consul-ui/utils/dom/event-source/blocking",["exports","@ember/object"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.createErrorBackoff=void 0,e.default=function(e){let s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i() +const c=function(i){let c=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +const{currentEvent:d}=c,p=r(c,n) +e.apply(this,[e=>{const{createEvent:n}=e,c=r(e,l) +return i.apply(this,[c,this]).catch(s).then((l=>{if(l instanceof Error)return l +let r=("function"==typeof n?n:u)(l,e) +r.type||(r={type:"message",data:r}) +const i=(0,t.get)(r.data||{},"meta") +i&&(e.cursor=o(i.cursor,e.cursor),e.cacheControl=i.cacheControl,e.interval=i.interval),-1===(e.cacheControl||"").indexOf("no-store")&&(this.currentEvent=r),this.dispatchEvent(r) +const s=a(e,r,this.previousEvent) +return this.previousEvent=this.currentEvent,s(l)}))},p]),void 0!==d&&(this.currentEvent=d),this.addEventListener("open",(e=>{const t=e.target.getCurrentEvent() +void 0!==t&&this.dispatchEvent(t)}))} +return c.prototype=Object.assign(Object.create(e.prototype,{constructor:{value:e,configurable:!0,writable:!0}}),{getCurrentEvent:function(){return this.currentEvent},getPreviousEvent:function(){return this.previousEvent}}),c},e.validateCursor=void 0 +const n=["currentEvent"],l=["createEvent"] +function r(e,t){if(null==e)return{} +var n,l,r=function(e,t){if(null==e)return{} +var n,l,r={},i=Object.keys(e) +for(l=0;l=0||(r[n]=e[n]) +return r}(e,t) +if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e) +for(l=0;l=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}const i=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:3e3,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Promise,l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:setTimeout +return function(r){let i=(0,t.get)(r,"errors.firstObject.status")||(0,t.get)(r,"statusCode") +if(void 0!==i)switch(i=i.toString(),!0){case 0===i.indexOf("5")&&3===i.length&&"500"!==i:case"0"===i:return new n((function(t){l((function(){t(r)}),e)}))}throw r}} +e.createErrorBackoff=i +const o=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=parseInt(e) +if(!isNaN(n))return null!==t&&n2&&void 0!==arguments[2]?arguments[2]:Promise +return function(l){return function(r,i){const o=i.key +if(void 0!==l[o]&&i.settings.enabled)return void 0===l[o].configuration&&(l[o].configuration={}),l[o].configuration.settings=i.settings,e(l[o]) +{const a=i.type||t,u=l[o]=new a(r,i) +return e(u).catch((function(e){return delete l[o],n.reject(e)})).then((function(e){return void 0===e.configuration.cursor&&(e.close(),delete l[o]),e}))}}}}})),define("consul-ui/utils/dom/event-source/callable",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Promise,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:n +const a=function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +e.call(this),this.readyState=2,this.source="function"!=typeof t?function(e,t){return this.close(),r.resolve()}:t,this.readyState=0,r.resolve().then((()=>{if(!(this.readyState>1))return this.readyState=1,this.dispatchEvent({type:"open"}),i(this,n,l)})).catch((e=>{this.dispatchEvent(o(e)),this.readyState=2,this.dispatchEvent({type:"close",error:e})})).then((()=>{this.readyState=2}))} +return a.prototype=Object.assign(Object.create(e.prototype,{constructor:{value:a,configurable:!0,writable:!0}}),{close:function(){switch(this.readyState){case 0:case 2:this.readyState=2 +break +default:this.readyState=3}return this}}),a},e.defaultRunner=void 0 +const t=function(e,n,l){if(!l(e))return e.source.bind(e)(n,e).then((function(r){return t(e,n,l)})) +e.dispatchEvent({type:"close"})} +e.defaultRunner=t +const n=function(e){return new ErrorEvent("error",{error:e,message:e.message})},l=function(e){switch(e.readyState){case 2:case 3:return!0}return!1}})),define("consul-ui/utils/dom/event-source/index",["exports","@ember/object/proxy","@ember/array/proxy","consul-ui/utils/dom/create-listeners","consul-ui/utils/dom/event-target/rsvp","consul-ui/utils/dom/event-source/cache","consul-ui/utils/dom/event-source/proxy","consul-ui/utils/dom/event-source/resolver","consul-ui/utils/dom/event-source/callable","consul-ui/utils/dom/event-source/openable","consul-ui/utils/dom/event-source/blocking","consul-ui/utils/dom/event-source/storage","@ember/object","ember-concurrency","consul-ui/env"],(function(e,t,n,l,r,i,o,a,u,s,c,d,p,f,m){let h +switch(Object.defineProperty(e,"__esModule",{value:!0}),e.toPromise=e.source=e.resolve=e.proxy=e.once=e.fromPromise=e.cache=e.StorageEventSource=e.OpenableEventSource=e.CallableEventSource=e.BlockingEventSource=void 0,(0,m.env)("CONSUL_UI_REALTIME_RUNNER")){case"ec":h=function(e,t,n){return p.default.extend({task:(0,f.task)((function*(){for(;!n(e);)yield e.source.bind(e)(t)}))}).create().get("task").perform()} +break +case"generator":h=async function(e,t,n){const l=function*(){for(;!n(e);)yield e.source.bind(e)(t)} +let r,i=l().next() +for(;!i.done;)r=await i.value,i=l().next() +return r} +break +case"async":h=async function(e,t,n){let l +for(;!n(e);)l=await e.source.bind(e)(t) +return l}}const b=(0,u.default)(r.default,Promise,h) +e.CallableEventSource=b +const y=(0,s.default)(b) +e.OpenableEventSource=y +const v=(0,c.default)(y) +e.BlockingEventSource=v +const g=(0,d.default)(r.default,Promise) +e.StorageEventSource=g +const O=(0,o.default)(t.default,n.default,l.default) +e.proxy=O +const P=(0,a.default)(Promise) +e.resolve=P +const w=function(e){return P(e,(0,l.default)()).then((function(t){return O(e,t)}))} +e.source=w +const x=(0,i.default)(w,v,Promise) +e.cache=x +e.fromPromise=function(e){return new b((function(t){const n=this.dispatchEvent.bind(this),l=()=>{this.close()} +return e.then((function(e){l(),n({type:"message",data:e})})).catch((function(e){l(),n(function(e){return new ErrorEvent("error",{error:e,message:e.message})}(e))}))}))} +e.toPromise=function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"message",l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"error" +return new Promise((function(r,i){const o=function(e){r(e.data)},a=function(e){i(e.error)} +e.addEventListener(n,o),e.addEventListener(l,a),t((function(){"function"==typeof e.close&&e.close(),e.removeEventListener(n,o),e.removeEventListener(l,a)}))}))} +e.once=function(e,t){return new(arguments.length>2&&void 0!==arguments[2]?arguments[2]:y)((function(t,n){return e(t,n).then((function(e){n.dispatchEvent({type:"message",data:e}),n.close()})).catch((function(e){n.dispatchEvent({type:"error",error:e}),n.close()}))}),t)}})),define("consul-ui/utils/dom/event-source/openable",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:EventSource +const t=function(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +e.apply(this,arguments),this.configuration=n} +return t.prototype=Object.assign(Object.create(e.prototype,{constructor:{value:t,configurable:!0,writable:!0}}),{open:function(){switch(this.readyState){case 3:this.readyState=1 +break +case 2:e.apply(this,[this.source,this.configuration])}return this}}),t}})),define("consul-ui/utils/dom/event-source/proxy",["exports","@ember/object"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,l,r){return function(i){let o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],a=e,u="object" +return"string"!=typeof o&&void 0!==(0,t.get)(o,"length")&&(a=l,u="array",o=o.filter((function(e){return!(0,t.get)(e,"isDestroyed")&&!(0,t.get)(e,"isDeleted")&&(0,t.get)(e,"isLoaded")}))),void 0===n[u]&&(n[u]=a.extend({init:function(){this.listeners=r(),this.listeners.add(this._source,"message",(e=>(0,t.set)(this,"content",e.data))),this._super(...arguments)},addEventListener:function(e,t){this.listeners.add(this._source,e,t)},getCurrentEvent:function(){return this._source.getCurrentEvent(...arguments)},removeEventListener:function(){return this._source.removeEventListener(...arguments)},dispatchEvent:function(){return this._source.dispatchEvent(...arguments)},close:function(){return this._source.close(...arguments)},open:function(){return this._source.open(...arguments)},willDestroy:function(){this._super(...arguments),this.close(),this.listeners.remove()}})),n[u].create({content:o,_source:i,configuration:i.configuration})}} +const n={}})),define("consul-ui/utils/dom/event-source/resolver",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Promise +return function(t,n){let l +return"function"==typeof t.getCurrentEvent&&(l=t.getCurrentEvent()),null!=l?e.resolve(l.data).then((function(e){return t.open(),e})):new e((function(e,l){n.add(t,"error",(function(e){n.remove(),e.target.close(),l(e.error)})),n.add(t,"message",(function(t){n.remove(),e(t.data)}))}))}}})),define("consul-ui/utils/dom/event-source/storage",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Promise +const n=function(e){if((void 0===e||e.key===this.configuration.key)&&1===this.readyState){const e=this.source(this.configuration) +t.resolve(e).then((e=>{this.configuration.cursor++,this._currentEvent={type:"message",data:e},this.dispatchEvent({type:"message",data:e})}))}} +return class extends e{constructor(e,t){super(...arguments),this.readyState=2,this.target=t.target||window,this.name="storage",this.source=e,this.handler=n.bind(this),this.configuration=t,this.configuration.cursor=1,this.open()}dispatchEvent(){if(1===this.readyState)return super.dispatchEvent(...arguments)}close(){this.target.removeEventListener(this.name,this.handler),this.readyState=2}getCurrentEvent(){return this._currentEvent}open(){const e=this.readyState +this.readyState=1,1!==e&&(this.target.addEventListener(this.name,this.handler),this.handler())}}}})),define("consul-ui/utils/dom/event-target/event-target-shim/event",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isStopped=function(e){return l(e).immediateStopped},e.setCurrentTarget=function(e,t){l(e).currentTarget=t},e.setEventPhase=function(e,t){l(e).eventPhase=t},e.setPassiveListener=function(e,t){l(e).passiveListener=t},e.wrapEvent=function(e,t){return new(u(Object.getPrototypeOf(t)))(e,t)} +const t=new WeakMap,n=new WeakMap +function l(e){const n=t.get(e) +return console.assert(null!=n,"'this' is expected an Event object, but got",e),n}function r(e){null==e.passiveListener?e.event.cancelable&&(e.canceled=!0,"function"==typeof e.event.preventDefault&&e.event.preventDefault()):"undefined"!=typeof console&&"function"==typeof console.error&&console.error("Unable to preventDefault inside passive event listener invocation.",e.passiveListener)}function i(e,n){t.set(this,{eventTarget:e,event:n,eventPhase:2,currentTarget:e,canceled:!1,stopped:!1,immediateStopped:!1,passiveListener:null,timeStamp:n.timeStamp||Date.now()}),Object.defineProperty(this,"isTrusted",{value:!1,enumerable:!0}) +const l=Object.keys(n) +for(let t=0;t1&&void 0!==arguments[1]?arguments[1]:"-view-registry:main" +const n=e.lookup(t) +return function(e){const t=e.getAttribute("id") +if(t)return n[t]}}})),define("consul-ui/utils/dom/is-outside",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:document +if(e){const l=!t||!n.contains(t),r=e===t||e.contains(t) +return!l&&!r}return!1}})),define("consul-ui/utils/dom/normalize-event",["exports"],(function(e){function t(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function n(e){for(var n=1;n2&&void 0!==arguments[2]?arguments[2]:{} +if(void 0!==e.target)return e +return{target:n(n({},l),{name:e,value:t})}}})),define("consul-ui/utils/dom/qsa-factory",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:document +return function(t){return(arguments.length>1&&void 0!==arguments[1]?arguments[1]:e).querySelectorAll(t)}}})),define("consul-ui/utils/dom/sibling",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){let n=e +for(;n=n.nextSibling;)if(1===n.nodeType&&n.nodeName.toLowerCase()===t)return n}})),define("consul-ui/utils/editor/lint",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.createLoader=void 0,e.default=function(e,t){n(e,t,(function(){e.getValue().trim().length&&e.performLint()}))} +const t=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:document.getElementsByTagName.bind(document),t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:CodeMirror +return t.registerHelper("lint","ruby",(function(e){return[]})),function(n,l,r){let i=[...e("script")] +const o=i.find((function(e){return-1!==e.src.indexOf(`/codemirror/mode/${l}/${l}.js`)})) +t.autoLoadMode(n,l),o?r():(i=[...e("script")],t.on(i[0],"load",(function(){r()})))}} +e.createLoader=t +const n=t()})),define("consul-ui/utils/filter/index",["exports","mnemonist/set"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.andOr=void 0 +e.andOr=e=>{const n=function(e){return Object.entries(e).reduce(((e,t)=>{let[n,l]=t +return e[n]="function"!=typeof l?new Set(Object.keys(l)):null,e}),{})}(e) +return l=>(l=function(e,n){return Object.keys(n).reduce(((l,r)=>{const i=void 0===e[r]?[]:e[r] +return i.length>0&&(null!==n[r]?l[r]=[...t.default.intersection(n[r],new Set(i))]:l[r]=[...new Set(i)]),l}),{})}(l,n),t=>function(e,t,n){return Object.entries(t).every((t=>{let[l,r]=t,i=n[l] +return"function"==typeof i?i(e,r):r.some((t=>i[t](e,t)))}))}(t,l,e))}})),define("consul-ui/utils/form/builder",["exports","@ember/object","ember-changeset","consul-ui/utils/form/changeset","ember-changeset-validations","consul-ui/utils/get-form-name-property"],(function(e,t,n,l,r,i){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:o,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.default +return function(){let l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +const r={} +let i=null +const o={data:null,name:arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",getName:function(){return this.name},setData:function(n){return i&&!Array.isArray(n)&&(n=e(n,i)),(0,t.set)(this,"data",n),this},getData:function(){return this.data},add:function(e){return r[e.getName()]=e,this},handleEvent:function(e,r){const i=e.target,o=n(r||i.name),a=o[0],u=o[1] +let s=l +if(a!==this.getName()){if(this.has(a))return this.form(a).handleEvent(e) +s=s[a]}const c=this.getData(),d="function"==typeof c.toJSON?c.toJSON():(0,t.get)(c,"data").toJSON() +if(!Object.keys(d).includes(u)){const e=new Error(`${u} property doesn't exist`) +throw e.target=i,e}let p=(0,t.get)(c,u) +if(Array.isArray(p)||void 0!==s[u]&&"string"==typeof s[u].type&&"array"===s[u].type.toLowerCase()){null==p&&(p=[]) +p[i.checked?"pushObject":"removeObject"](i.value),(0,t.set)(c,u,p)}else void 0===i.checked||"on"!==i.value.toLowerCase()&&"off"!==i.value.toLowerCase()?(0,t.set)(c,u,i.value):(0,t.set)(c,u,i.checked) +return this.validate()},reset:function(){return"function"==typeof this.getData().rollbackAttributes&&this.getData().rollbackAttributes(),this},clear:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{} +return"function"==typeof e?this.clearer=e:this.setData(this.clearer(e)).getData()},submit:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{} +if("function"==typeof e)return this.submitter=e +this.submitter(this.getData())},setValidators:function(e){return i=e,this},validate:function(){const e=this.getData() +return"function"==typeof e.validate&&e.validate(),this},addError:function(e,t){const n=this.getData() +"function"==typeof n.addError&&n.addError(...arguments)},form:function(e){return null==e?this:r[e]},has:function(e){return void 0!==r[e]}} +return o.submit=o.submit.bind(o),o.reset=o.reset.bind(o),o}},e.defaultChangeset=void 0 +const o=function(e,t){return(0,n.Changeset)(e,(0,r.default)(t),t,{changeset:l.default})} +e.defaultChangeset=o})),define("consul-ui/utils/form/changeset",["exports","@ember/object","ember-changeset"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +const l="_changes" +class r extends n.EmberChangeset{pushObject(e,n){let r +void 0===(0,t.get)(this,`${l}.${e}`)?(r=(0,t.get)(this,`data.${e}`),r=r?r.toArray():[]):r=this.get(e).slice(0),r.push(n),this.set(`${e}`,r)}removeObject(e,n){let r +void 0===(0,t.get)(this,`${l}.${e}`)?(r=(0,t.get)(this,`data.${e}`),r=void 0===r?[]:r.toArray()):r=this.get(e).slice(0) +const i=r.indexOf(n);-1!==i&&r.splice(i,1),this.set(`${e}`,r)}}e.default=r})),define("consul-ui/utils/get-environment",["exports","@ember/debug"],(function(e,t){function n(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function l(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:{},n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:window,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:document;(0,t.runInDebug)((()=>{const e=function(e){return e.split(";").map((e=>e.trim())).filter((e=>""!==e)).filter((e=>e.split("=").shift().startsWith("CONSUL_")))} +n.Scenario=function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"" +if(t.length>0)e(t).forEach((e=>{if(e.startsWith("CONSUL_COLOR_SCHEME=")){const[,l]=e.split("=") +let r +try{r=JSON.parse(n.localStorage.getItem("consul:theme"))}catch(t){r={"color-scheme":"light"}}n.localStorage.setItem("consul:theme",`{"color-scheme": "${"!"===l?"light"===r["color-scheme"]?"dark":"light":l}"}`)}else r.cookie=`${e};Path=/`})),n.location.hash="",location.reload() +else{t=e(r.cookie).join(";") +n.open("","_blank").document.write(`
      ${location.href}#${t}

      Scenario`)}},void 0!==n.location&&"string"==typeof n.location.hash&&n.location.hash.length>0&&n.Scenario(n.location.hash.substr(1))})) +const i=function(){return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:r.cookie).split(";").filter((e=>""!==e)).map((e=>{const[t,...n]=e.trim().split("=") +return[t,n.join("=")]}))},o=function(e){const t=n.localStorage.getItem(e) +return null===t?void 0:t},a=l(l({},e.operatorConfig),JSON.parse(r.querySelector(`[data-${e.modulePrefix}-config]`).textContent)),u=a.UIConfig||{},s=r.getElementsByTagName("script"),c=s[s.length-1].src +let d +const p=function(e,t){let l,r,i,o +switch(e){case"CONSUL_NSPACES_ENABLED":return void 0!==a.NamespacesEnabled&&a.NamespacesEnabled +case"CONSUL_SSO_ENABLED":return void 0!==a.SSOEnabled&&a.SSOEnabled +case"CONSUL_ACLS_ENABLED":return void 0!==a.ACLsEnabled&&a.ACLsEnabled +case"CONSUL_PARTITIONS_ENABLED":return void 0!==a.PartitionsEnabled&&a.PartitionsEnabled +case"CONSUL_PEERINGS_ENABLED":return void 0!==a.PeeringEnabled&&a.PeeringEnabled +case"CONSUL_HCP_ENABLED":return void 0!==a.HCPEnabled&&a.HCPEnabled +case"CONSUL_DATACENTER_LOCAL":return a.LocalDatacenter +case"CONSUL_DATACENTER_PRIMARY":return a.PrimaryDatacenter +case"CONSUL_HCP_MANAGED_RUNTIME":return a.HCPManagedRuntime +case"CONSUL_API_PREFIX":return a.APIPrefix +case"CONSUL_HCP_URL":return a.HCPURL +case"CONSUL_UI_CONFIG":return r={service:void 0},i=t("CONSUL_METRICS_PROVIDER"),o=t("CONSUL_METRICS_PROXY_ENABLED"),r.service=t("CONSUL_SERVICE_DASHBOARD_URL"),i&&(u.metrics_provider=i),o&&(u.metrics_proxy_enabled=o),r.service&&(u.dashboard_url_templates=r),u +case"CONSUL_BASE_UI_URL":return c.split("/").slice(0,-2).join("/") +case"CONSUL_HTTP_PROTOCOL":return void 0===d&&(d=function(e){try{return n.performance.getEntriesByType("resource").find((t=>"script"===t.initiatorType&&e===t.name))||{}}catch(t){return{}}}(c)),d.nextHopProtocol||"http/1.1" +case"CONSUL_HTTP_MAX_CONNECTIONS":switch(l=t("CONSUL_HTTP_PROTOCOL"),!0){case 0===l.indexOf("h2"):case 0===l.indexOf("hq"):case 0===l.indexOf("spdy"):return +default:return 5}case"CONSUL_V2_CATALOG_ENABLED":return"undefined"!==a.V2CatalogEnabled&&a.V2CatalogEnabled}},f=function(t){let n={} +switch(e.environment){case"development":case"staging":case"coverage":case"test":n=i().reduce((function(e,t){let[n,l]=t +switch(n){case"CONSUL_INTL_LOCALE":e.CONSUL_INTL_LOCALE=String(l).toLowerCase() +break +case"CONSUL_INTL_DEBUG":e.CONSUL_INTL_DEBUG=!!JSON.parse(String(l).toLowerCase()) +break +case"CONSUL_ACLS_ENABLE":e.CONSUL_ACLS_ENABLED=!!JSON.parse(String(l).toLowerCase()) +break +case"CONSUL_AGENTLESS_ENABLE":e.CONSUL_AGENTLESS_ENABLED=!!JSON.parse(String(l).toLowerCase()) +break +case"CONSUL_NSPACES_ENABLE":e.CONSUL_NSPACES_ENABLED=!!JSON.parse(String(l).toLowerCase()) +break +case"CONSUL_SSO_ENABLE":e.CONSUL_SSO_ENABLED=!!JSON.parse(String(l).toLowerCase()) +break +case"CONSUL_PARTITIONS_ENABLE":e.CONSUL_PARTITIONS_ENABLED=!!JSON.parse(String(l).toLowerCase()) +break +case"CONSUL_METRICS_PROXY_ENABLE":e.CONSUL_METRICS_PROXY_ENABLED=!!JSON.parse(String(l).toLowerCase()) +break +case"CONSUL_PEERINGS_ENABLE":e.CONSUL_PEERINGS_ENABLED=!!JSON.parse(String(l).toLowerCase()) +break +case"CONSUL_HCP_ENABLE":e.CONSUL_HCP_ENABLED=!!JSON.parse(String(l).toLowerCase()) +break +case"CONSUL_UI_CONFIG":e.CONSUL_UI_CONFIG=JSON.parse(l) +break +case"TokenSecretID":e.CONSUL_HTTP_TOKEN=l +break +case"CONSUL_V2_CATALOG_ENABLE":e.CONSUL_V2_CATALOG_ENABLED=JSON.parse(l) +break +default:e[n]=l}return e}),{}) +break +case"production":n=i().reduce((function(e,t){let[n,l]=t +if("TokenSecretID"===n)e.CONSUL_HTTP_TOKEN=l +return e}),{})}return void 0!==n[t]?n[t]:e[t]} +return function e(t){switch(t){case"CONSUL_UI_DISABLE_REALTIME":case"CONSUL_UI_DISABLE_ANCHOR_SELECTION":return!!JSON.parse(String(o(t)||0).toLowerCase())||f(t) +case"CONSUL_UI_REALTIME_RUNNER":return o(t)||f(t) +case"CONSUL_UI_CONFIG":case"CONSUL_DATACENTER_LOCAL":case"CONSUL_DATACENTER_PRIMARY":case"CONSUL_HCP_MANAGED_RUNTIME":case"CONSUL_API_PREFIX":case"CONSUL_HCP_URL":case"CONSUL_ACLS_ENABLED":case"CONSUL_NSPACES_ENABLED":case"CONSUL_PEERINGS_ENABLED":case"CONSUL_AGENTLESS_ENABLED":case"CONSUL_HCP_ENABLED":case"CONSUL_SSO_ENABLED":case"CONSUL_PARTITIONS_ENABLED":case"CONSUL_METRICS_PROVIDER":case"CONSUL_METRICS_PROXY_ENABLE":case"CONSUL_SERVICE_DASHBOARD_URL":case"CONSUL_BASE_UI_URL":case"CONSUL_V2_CATALOG_ENABLED":case"CONSUL_HTTP_PROTOCOL":case"CONSUL_HTTP_MAX_CONNECTIONS":{const n=f(t) +return void 0!==n?n:p(t,e)}default:return f(t)}}}})),define("consul-ui/utils/get-form-name-property",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){if(-1!==e.indexOf("["))return e.match(/(.*)\[(.*)\]/).slice(1) +return["",e]}})),define("consul-ui/utils/helpers/call-if-type",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return function(t){return function(n){let l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return typeof n[0]!==e?n[0]:t(n[0],l)}}}})),define("consul-ui/utils/http/consul",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.HEADERS_TOKEN=e.HEADERS_SYMBOL=e.HEADERS_PARTITION=e.HEADERS_NAMESPACE=e.HEADERS_INDEX=e.HEADERS_DIGEST=e.HEADERS_DEFAULT_ACL_POLICY=e.HEADERS_DATACENTER=void 0 +e.HEADERS_PARTITION="X-Consul-Partition" +e.HEADERS_NAMESPACE="X-Consul-Namespace" +e.HEADERS_DATACENTER="X-Consul-Datacenter" +e.HEADERS_DEFAULT_ACL_POLICY="X-Consul-Default-Acl-Policy" +e.HEADERS_INDEX="X-Consul-Index" +e.HEADERS_TOKEN="X-Consul-Token" +e.HEADERS_DIGEST="X-Consul-ContentHash" +e.HEADERS_SYMBOL="__consul_ui_http_headers__"})),define("consul-ui/utils/http/create-headers",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){return function(e){return e.reduce((function(e,t){const[n,...l]=t.split(":") +return l.length>0&&(e[n.trim()]=l.join(":").trim()),e}),{})}}})),define("consul-ui/utils/http/create-query-params",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:encodeURIComponent +return function t(n,l){return Object.entries(n).reduce((function(n,r,i){let[o,a]=r +if(void 0===a)return n +let u=e(o) +return void 0!==l&&(u=`${l}[${u}]`),null===a?n.concat(u):"object"==typeof a?n.concat(t(a,u)):n.concat(`${u}=${e(a)}`)}),[]).join("&")}}})),define("consul-ui/utils/http/create-url",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,i){return function(o){for(var a=arguments.length,u=new Array(a>1?a-1:0),s=1;s0&&void 0!==arguments[0]?arguments[0]:0 +if("text/event-stream"===this.headers()["content-type"]){this.statusCode=e +const t=this.connection() +if(t.readyState)switch(t.readyState){case 0:case 1:t.abort()}}}}e.default=i})),define("consul-ui/utils/http/status",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.UNAUTHORIZED=e.OK=e.INTERNAL_SERVER_ERROR=e.FORBIDDEN=void 0 +e.OK=200 +e.UNAUTHORIZED=401 +e.FORBIDDEN=403 +e.INTERNAL_SERVER_ERROR=500})),define("consul-ui/utils/http/xhr",["exports"],(function(e){function t(e,t){var n=Object.keys(e) +if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e) +t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function n(e){for(var n=1;n=200&&this.status<400){const e=l.converters["text json"](this.response) +l.success(t,e,this.status,this.statusText)}else l.error(t,this.responseText,this.status,this.statusText,this.error) +l.complete(this.status)}} +let i=l.url +i.endsWith("?")&&(i=i.substr(0,i.length-1)),r.open(l.method,i,!0),void 0===l.headers&&(l.headers={}) +const o=n(n({},l.headers),{},{"X-Requested-With":"XMLHttpRequest"}) +return Object.entries(o).forEach((e=>{let[t,n]=e +return r.setRequestHeader(t,n)})),l.beforeSend(r),r.withCredentials=!0,r.send(l.body),r}}})),define("consul-ui/utils/intl/missing-message",["exports","@ember/debug"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,n){(0,t.runInDebug)((t=>console.debug(`Translation key not found: ${e}`))) +const l=e.split(".").pop().split("-").join(" ") +return`${l.substr(0,1).toUpperCase()}${l.substr(1)}`}})),define("consul-ui/utils/isFolder",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"" +return"/"===e.slice(-1)}})),define("consul-ui/utils/keyToArray",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"/" +return(e===t?"":e).split(t)}})),define("consul-ui/utils/left-trim",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"" +return 0===e.indexOf(t)?e.substr(t.length):e}})),define("consul-ui/utils/maybe-call",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){return function(n){return t.then((function(t){return t&&e(),n}))}}})),define("consul-ui/utils/merge-checks",["exports","@ember/object","mnemonist/multi-map"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],l=arguments.length>1&&void 0!==arguments[1]&&arguments[1] +const r=new(arguments.length>2&&void 0!==arguments[2]?arguments[2]:n.default),i=e.shift().map((e=>(""===e.ServiceName&&r.set(e.Node,e.CheckID),e))).concat(e.reduce(((e,t)=>void 0===t?e:e.concat(t.reduce(((e,t)=>{if(""===t.ServiceName){if((r.get(t.Node)||[]).includes(t.CheckID))return e +r.set(t.Node,t.CheckID)}return e.push(t),e}),[]))),[])) +return l&&i.filter((e=>(0,t.get)(e,"Exposable"))).forEach((e=>{(0,t.set)(e,"Exposed",l)})),i}})),define("consul-ui/utils/minimizeModel",["exports","@ember/object"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){if(Array.isArray(e))return e.filter((function(e){return!(0,t.get)(e,"isNew")})).map((function(e){return{ID:(0,t.get)(e,"ID"),Name:(0,t.get)(e,"Name")}}))}})) +define("consul-ui/utils/non-empty-set",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return function(t){return null==t||""===t?{}:{[e]:t}}}})),define("consul-ui/utils/path/resolve",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=(e,t)=>0===t.indexOf("/")?t:t.split("/").reduce(((e,t,n,l)=>("."!==t&&(".."===t?e.pop():""===t&&n!==l.length-1||e.push(t)),e)),e.split("/")).join("/")})),define("consul-ui/utils/promisedTimeout",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Promise,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:setTimeout +return function(n){let l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(){} +return new e(((e,r)=>{l(t((function(){e(n)}),n))}))}}})),define("consul-ui/utils/right-trim",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"" +const n=e.length-t.length +if(n>=0)return e.lastIndexOf(t)===n?e.substr(0,n):e +return e}})),define("consul-ui/utils/routing/redirect-to",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,t){return function(t,n){const l=this.routeName.split(".").slice(0,-1).join(".") +this.replaceWith(`${l}.${e}`,t)}}})),define("consul-ui/utils/routing/transitionable",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){let l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2?arguments[2]:void 0 +null===e&&(e=r.lookup("route:application")) +let i,o=n(e,l),a=e +for(;i=a.parent;)o=o.concat(n(i,l)),a=i +return o.reverse(),t(e.name||"application",o,l)} +const t=function(e,t,n){return[e,...t]},n=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{} +return(e.paramNames||[]).map((function(n){return void 0!==t[n]?t[n]:e.params[n]})).reverse()}})),define("consul-ui/utils/routing/walk",["exports","@ember/debug"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return function(){n.apply(this,[e])}},e.walk=e.dump=void 0 +const n=function(e){Object.keys(e).forEach(((t,l)=>{if("_options"===t)return +if(null===e[t])return +const r=e[t]._options +let i +Object.keys(e[t]).length>1&&(i=function(){n.apply(this,[e[t]])}),this.route(t,r,i)})),void 0===e.index&&(e.index={_options:{path:""}})} +e.walk=n +let l=e=>{} +e.dump=l,(0,t.runInDebug)((()=>{const t=function(e){return Array(e).fill(" ",0,e).join("")} +e.dump=l=function(e){let l=2 +const r={out:"",route:function(e,n,r){this.out+=`${t(l)}this.route('${e}', ${JSON.stringify(n)}`,r?(l++,this.out+=", function() {\n",r.apply(this,[]),l--,this.out+=`${t(l)}});\n`):this.out+=");",this.out+="\n"}} +return n.apply(r,[e]),`Router.map(\n function() {\n${r.out}\n }\n);`}}))})),define("consul-ui/utils/routing/wildcard",["exports","@ember/object"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return function(n){let l=!1 +try{l=-1!==(0,t.get)(e,n)._options.path.indexOf("*")}catch(r){}return l}}})),define("consul-ui/utils/search/exact",["exports","consul-ui/utils/search/predicate"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{predicate(e){return e=e.toLowerCase(),function(){return-1!==(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").toString().toLowerCase().indexOf(e)}}}e.default=n})),define("consul-ui/utils/search/fuzzy",["exports","fuse.js"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=class{constructor(e,n){this.fuse=new t.default(e,{includeMatches:!0,shouldSort:!1,threshold:.4,keys:Object.keys(n.finders)||[],getFn:(e,t)=>(n.finders[t[0]](e)||[]).toString()})}search(e){return this.fuse.search(e).map((e=>e.item))}}})),define("consul-ui/utils/search/predicate",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=class{constructor(e,t){this.items=e,this.options=t}search(e){const t=this.predicate(e) +return this.items.filter((e=>Object.entries(this.options.finders).some((n=>{let[l,r]=n +const i=r(e) +return Array.isArray(i)?i.some(t):t(i)}))))}}})),define("consul-ui/utils/search/regexp",["exports","consul-ui/utils/search/predicate"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +class n extends t.default{predicate(e){let t +try{t=new RegExp(e,"i")}catch(n){return()=>!1}return e=>t.test(e)}}e.default=n})),define("consul-ui/utils/storage/local-storage",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:window.localStorage,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:JSON.stringify,l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:JSON.parse,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:function(e){window.dispatchEvent(new StorageEvent("storage",{key:e}))} +const i=`${e}:` +return{getValue:function(e){let n=t.getItem(`${i}${e}`) +"string"!=typeof n&&(n='""') +try{n=l(n)}catch(r){n=""}return n},setValue:function(e,l){if(null===l)return this.removeValue(e) +try{l=n(l)}catch(a){l='""'}const o=t.setItem(`${i}${e}`,l) +return r(`${i}${e}`),o},removeValue:function(e){const n=t.removeItem(`${i}${e}`) +return r(`${i}${e}`),n},all:function(){return Object.keys(t).reduce(((e,t,n,l)=>{if(0===t.indexOf(`${i}`)){const n=t.substr(i.length) +e[n]=this.getValue(n)}return e}),{})}}}})),define("consul-ui/utils/templatize",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[] +return e.map((e=>`template-${e}`))}})),define("consul-ui/utils/ticker/index",["exports","consul-ui/utils/dom/event-target/rsvp","@ember/object"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.Tween=e.Ticker=void 0 +const l=class extends t.default{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1e3/60 +super(),this.setRate(e)}tick(){this.dispatchEvent({type:"tick",target:this})}setRate(e){clearInterval(this._interval),this._interval=setInterval((()=>this.tick()),e)}destroy(){clearInterval(this._interval)}},r=class extends t.default{static destroy(){void 0!==r.defaultTickerGroup&&(r.defaultTickerGroup.destroy(),delete r.defaultTickerGroup)}constructor(e){super(),this.setTickable(e)}tick(){this._tickable.tick()}setTickable(e){this._tickable=e,void 0===this._tickable.getTicker&&(this._tickable.getTicker=()=>this),this.tick=this._tickable.tick.bind(this._tickable)}getTickable(){return this._tickable}isAlive(){return this._isAlive}start(){this._isAlive=!0,this.getTickerGroup().addEventListener("tick",this.tick),this.dispatchEvent({type:"start",target:this})}stop(){this._isAlive=!1,this.getTickerGroup().removeEventListener("tick",this.tick),this.dispatchEvent({type:"stop",target:this})}activeCount(){return this.getTickerGroup().activeCount()}setTickerGroup(e){this._group=e}getTickerGroup(){return void 0===this._group&&(void 0===r.defaultTickerGroup&&(r.defaultTickerGroup=new a),this._group=r.defaultTickerGroup),this._group}} +e.Ticker=r +const i=class{constructor(){this._currentframe=1,this.setIncrement(1)}isAtStart(){return this._currentframe<=1}isAtEnd(){return this._currentframe>=this._totalframes}addEventListener(){return this.getTicker().addEventListener(...arguments)}removeEventListener(){return this.getTicker().removeEventListener(...arguments)}stop(){return this.gotoAndStop(this._currentframe)}play(){return this.gotoAndPlay(this._currentframe)}start(){return this.gotoAndPlay(this._currentframe)}gotoAndStop(e){this._currentframe=e +const t=this.getTicker() +return t.isAlive()&&t.stop(),this}gotoAndPlay(e){this._currentframe=e +const t=this.getTicker() +return t.isAlive()||t.start(),this}getTicker(){return void 0===this._ticker&&(this._ticker=new r(this)),this._ticker}setFrames(e){return this._totalframes=e,this}setIncrement(e){return this._increment=e,this}},o={easeOut:function(e,t,n,l){return e/=l,n*(--e*e*e+1)+t}},a=l,u=class extends i{static destroy(){r.destroy()}static to(e,t,n,l){return Object.keys(t).forEach((function(n){t[n]-=e[n]})),new u(e,t,n,l).play()}constructor(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:12,l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:o.easeOut +super(),this.setMethod(l),this.setProps(t),this.setTarget(e),this.setFrames(n),this.tick=this.forwards}_process(){Object.keys(this._props).forEach((e=>{const t=this._method(this._currentframe,this._initialstate[e],this._props[e],this._totalframes);(0,n.set)(this._target,e,t)}))}forwards(){this._currentframe<=this._totalframes?(this._process(),this._currentframe+=this._increment):(this._currentframe=this._totalframes,this.getTicker().stop())}backwards(){this._currentframe-=this._increment,this._currentframe>=0?this._process():(this.run=this.forwards,this._currentframe=1,this.getTicker().stop())}gotoAndPlay(){return void 0===this._initialstate&&(this._initialstate={},Object.keys(this._props).forEach((e=>{this._initialstate[e]=this._target[e]}))),super.gotoAndPlay(...arguments)}setTarget(e){this._target=e}getTarget(e){return this._target}setProps(e){return this._props=e,this}setMethod(e){this._method=e}} +e.Tween=u})),define("consul-ui/utils/titleize",["exports","ember-cli-string-helpers/utils/titleize"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})})),define("consul-ui/utils/tomography",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return function(t,n){var l=999999999,r=-999999999,i=[] +n.forEach((function(o){if(t==o.Node){var a=o.Segment +n.forEach((function(t){if(o.Node!=t.Node&&t.Segment==a){var n=e(o,t) +i.push({node:t.Node,distance:n,segment:a}),nr&&(r=n)}})),i.sort((function(e,t){return e.distance-t.distance}))}})) +var o,a=i.length,u=Math.floor(a/2) +return a>0?o=a%2?i[u].distance:(i[u-1].distance+i[u].distance)/2:(o=0,l=0,r=0),{distances:i,min:Math.trunc(100*l)/100,median:Math.trunc(100*o)/100,max:Math.trunc(100*r)/100}}}})),define("consul-ui/utils/ucfirst",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e){return`${e.substr(0,1).toUpperCase()}${e.substr(1)}`}})),define("consul-ui/utils/update-array-object",["exports","@ember/object","@ember/object/proxy"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,l,r,i){i=void 0===i?(0,t.get)(l,r):i +const o=e.findIndex((function(e){return(0,t.get)(e,r)===i}));-1!==o&&(l instanceof n.default&&(0,t.set)(l,"content",e.objectAt(o)),e.replace(o,1,[l])) +return l}})),define("consul-ui/validations/intention-permission-http-header",["exports","ember-changeset-validations/validators","consul-ui/validations/sometimes"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>({Name:[(0,t.validatePresence)(!0)],Value:[(0,n.default)((0,t.validatePresence)(!0),(function(){return"Present"!==this.get("HeaderType")}))]})})),define("consul-ui/validations/intention-permission",["exports","ember-changeset-validations/validators","consul-ui/validations/sometimes"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default=e=>({"*":[(0,n.default)((0,t.validatePresence)(!0),(function(){const e=this.get("HTTP.Methods")||[],t=this.get("HTTP.Header")||[],n=this.get("HTTP.PathType")||"NoPath",l=this.get("HTTP.Path")||"" +return![0!==e.length,0!==t.length,"NoPath"!==n&&""!==l].includes(!0)}))],Action:[(0,t.validateInclusion)({in:e["intention-permission"].Action.allowedValues})],HTTP:{Path:[(0,n.default)((0,t.validateFormat)({regex:/^\//}),(function(){const e=this.get("HTTP.PathType") +return void 0!==e&&"NoPath"!==e}))]}})})),define("consul-ui/validations/intention",["exports","ember-changeset-validations/validators","consul-ui/validations/sometimes"],(function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var l={"*":[(0,n.default)((0,t.validatePresence)(!0),(function(){const e=this.get("Action")||"",t=this.get("Permissions")||[] +return""===e&&0===t.length}))],SourceName:[(0,t.validatePresence)(!0),(0,t.validateLength)({min:1})],DestinationName:[(0,t.validatePresence)(!0),(0,t.validateLength)({min:1})],Permissions:[(0,n.default)((0,t.validateLength)({min:1}),(function(e,t){return!this.get("Action")}))]} +e.default=l})),define("consul-ui/validations/kv",["exports","ember-changeset-validations/validators"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n={Key:[(0,t.validatePresence)(!0),(0,t.validateLength)({min:1})]} +e.default=n})),define("consul-ui/validations/policy",["exports","ember-changeset-validations/validators"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n={Name:(0,t.validateFormat)({regex:/^[A-Za-z0-9\-_]{1,128}$/})} +e.default=n})),define("consul-ui/validations/role",["exports","ember-changeset-validations/validators"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +var n={Name:(0,t.validateFormat)({regex:/^[A-Za-z0-9\-_]{1,256}$/})} +e.default=n})),define("consul-ui/validations/sometimes",["exports","@ember/object"],(function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(e,n){return function(e){return function(l,r,i,o,a){let u={get(e){if(e.includes(".")){let n=(0,t.get)(o,e) +if(void 0!==n)return n +let l=e.split("."),r=l.pop(),i=l.join("."),u=(0,t.get)(o,i) +return u&&u.hasOwnProperty&&u.hasOwnProperty(r)?n:(0,t.get)(a,e)}return o.hasOwnProperty(e)?(0,t.get)(o,e):(0,t.get)(a,e)}} +return!n.call(u,o,a)||e(l,r,i,o,a)}}(e)}})),define("consul-ui/validations/token",["exports"],(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0 +e.default={}})),define("consul-ui/config/environment",[],(function(){try{var e="consul-ui/config/environment",t=document.querySelector('meta[name="'+e+'"]').getAttribute("content"),n={default:JSON.parse(decodeURIComponent(t))} +return Object.defineProperty(n,"__esModule",{value:!0}),n}catch(l){throw new Error('Could not read config from meta tag with name "'+e+'".')}})),runningTests||require("consul-ui/app").default.create({name:"consul-ui",version:"2.2.0+3c24c491"}) diff --git a/agent/uiserver/dist/assets/consul-ui-f5d0ec3be8cca14adb133c8e2f488419.css b/agent/uiserver/dist/assets/consul-ui-f5d0ec3be8cca14adb133c8e2f488419.css deleted file mode 100644 index f09dcd203cfe..000000000000 --- a/agent/uiserver/dist/assets/consul-ui-f5d0ec3be8cca14adb133c8e2f488419.css +++ /dev/null @@ -1 +0,0 @@ -@charset "UTF-8";.hds-table,table{border-spacing:0}progress,sub,sup{vertical-align:baseline}.container,.w-full{width:100%}.hover\:scale-125:hover,.scale-100,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.ease-in-out,.transition{transition-timing-function:cubic-bezier(.4,0,.2,1)}*,::after,::before{border-width:0;border-style:solid;border-color:currentColor}html{line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"}a,hr{color:inherit}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto}::-webkit-backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scroll-snap-strictness:proximity;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000}::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scroll-snap-strictness:proximity;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.hds-breadcrumb,.hds-breadcrumb__item,.relative{position:relative}.sticky{position:-webkit-sticky;position:sticky}.bottom-0{bottom:0}.isolate{isolation:isolate}.ml-4{margin-left:1rem}.mb-3{margin-bottom:.75rem}.mt-2{margin-top:.5rem}.mb-1{margin-bottom:.25rem}.mr-1\.5{margin-right:.375rem}.mr-1{margin-right:.25rem}.mr-2\.5{margin-right:.625rem}.mr-2{margin-right:.5rem}.mt-6{margin-top:1.5rem}.mb-2{margin-bottom:.5rem}.mr-0\.5{margin-right:.125rem}.mr-0{margin-right:0}.mb-6{margin-bottom:1.5rem}.mt-3{margin-top:.75rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.contents{display:contents}.hidden{display:none}.h-16{height:4rem}.h-8{height:2rem}.h-4{height:1rem}.h-48{height:12rem}.h-full{height:100%}.h-12{height:3rem}.h-24{height:6rem}.w-8{width:2rem}.w-4{width:1rem}.w-24{width:6rem}.\!w-80{width:20rem!important}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.scale-100{--tw-scale-x:1;--tw-scale-y:1}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-col{flex-direction:column}.flex-nowrap{flex-wrap:nowrap}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1\.5{gap:.375rem}.gap-1{gap:.25rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-12>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(3rem * var(--tw-space-x-reverse));margin-left:calc(3rem * calc(1 - var(--tw-space-x-reverse)))}.overflow-x-auto{overflow-x:auto}.overflow-y-scroll{overflow-y:scroll}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded{border-radius:.25rem}.border{border-width:1px}.p-6{padding:1.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-3{padding-left:.75rem;padding-right:.75rem}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize,.type-source.popover-select li:not(.partition) button{text-transform:capitalize}.underline{-webkit-text-decoration-line:underline;text-decoration-line:underline}.opacity-0{opacity:0}.shadow{--tw-shadow:0 1px 3px 0 rgb(0 0 0 / 0.1),0 1px 2px -1px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-text-decoration-color,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-text-decoration-color,-webkit-backdrop-filter;transition-duration:150ms}.consul-surface-nav{background:var(--token-color-palette-neutral-700)}:root{--token-color-palette-blue-500:#1c345f;--token-color-palette-blue-400:#0046d1;--token-color-palette-blue-300:#0c56e9;--token-color-palette-blue-200:#1060ff;--token-color-palette-blue-100:#cce3fe;--token-color-palette-blue-50:#f2f8ff;--token-color-palette-purple-500:#42215b;--token-color-palette-purple-400:#7b00db;--token-color-palette-purple-300:#911ced;--token-color-palette-purple-200:#a737ff;--token-color-palette-purple-100:#ead2fe;--token-color-palette-purple-50:#f9f2ff;--token-color-palette-green-500:#054220;--token-color-palette-green-400:#006619;--token-color-palette-green-300:#00781e;--token-color-palette-green-200:#008a22;--token-color-palette-green-100:#cceeda;--token-color-palette-green-50:#f2fbf6;--token-color-palette-amber-500:#542800;--token-color-palette-amber-400:#803d00;--token-color-palette-amber-300:#9e4b00;--token-color-palette-amber-200:#bb5a00;--token-color-palette-amber-100:#fbeabf;--token-color-palette-amber-50:#fff9e8;--token-color-palette-red-500:#51130a;--token-color-palette-red-400:#940004;--token-color-palette-red-300:#c00005;--token-color-palette-red-200:#e52228;--token-color-palette-red-100:#fbd4d4;--token-color-palette-red-50:#fff5f5;--token-color-palette-neutral-700:#0c0c0e;--token-color-palette-neutral-600:#3b3d45;--token-color-palette-neutral-500:#656a76;--token-color-palette-neutral-400:#8c909c;--token-color-palette-neutral-300:#c2c5cb;--token-color-palette-neutral-200:#dedfe3;--token-color-palette-neutral-100:#f1f2f3;--token-color-palette-neutral-50:#fafafa;--token-color-palette-neutral-0:#ffffff;--token-color-palette-alpha-300:#3b3d4566;--token-color-palette-alpha-200:#656a7633;--token-color-palette-alpha-100:#656a761a;--token-color-border-primary:#656a7633;--token-color-border-faint:#656a761a;--token-color-border-strong:#3b3d4566;--token-color-border-action:#cce3fe;--token-color-border-highlight:#ead2fe;--token-color-border-success:#cceeda;--token-color-border-warning:#fbeabf;--token-color-border-critical:#fbd4d4;--token-color-focus-action-internal:#0c56e9;--token-color-focus-action-external:#5990ff;--token-color-focus-critical-internal:#c00005;--token-color-focus-critical-external:#dd7578;--token-color-foreground-strong:#0c0c0e;--token-color-foreground-primary:#3b3d45;--token-color-foreground-faint:#656a76;--token-color-foreground-high-contrast:#ffffff;--token-color-foreground-disabled:#8c909c;--token-color-foreground-action:#1060ff;--token-color-foreground-action-hover:#0c56e9;--token-color-foreground-action-active:#0046d1;--token-color-foreground-highlight:#a737ff;--token-color-foreground-highlight-on-surface:#911ced;--token-color-foreground-highlight-high-contrast:#42215b;--token-color-foreground-success:#008a22;--token-color-foreground-success-on-surface:#00781e;--token-color-foreground-success-high-contrast:#054220;--token-color-foreground-warning:#bb5a00;--token-color-foreground-warning-on-surface:#9e4b00;--token-color-foreground-warning-high-contrast:#542800;--token-color-foreground-critical:#e52228;--token-color-foreground-critical-on-surface:#c00005;--token-color-foreground-critical-high-contrast:#51130a;--token-color-page-primary:#ffffff;--token-color-page-faint:#fafafa;--token-color-surface-primary:#ffffff;--token-color-surface-faint:#fafafa;--token-color-surface-strong:#f1f2f3;--token-color-surface-interactive:#ffffff;--token-color-surface-interactive-hover:#f1f2f3;--token-color-surface-interactive-active:#dedfe3;--token-color-surface-interactive-disabled:#fafafa;--token-color-surface-action:#f2f8ff;--token-color-surface-highlight:#f9f2ff;--token-color-surface-success:#f2fbf6;--token-color-surface-warning:#fff9e8;--token-color-surface-critical:#fff5f5;--token-color-hashicorp-brand:#000000;--token-color-boundary-brand:#f24c53;--token-color-boundary-foreground:#cf2d32;--token-color-boundary-surface:#ffecec;--token-color-boundary-border:#fbd7d8;--token-color-boundary-gradient-primary-start:#f97076;--token-color-boundary-gradient-primary-stop:#db363b;--token-color-boundary-gradient-faint-start:#fffafa;--token-color-boundary-gradient-faint-stop:#ffecec;--token-color-consul-brand:#e03875;--token-color-consul-foreground:#d01c5b;--token-color-consul-surface:#ffe9f1;--token-color-consul-border:#ffcede;--token-color-consul-gradient-primary-start:#ff99be;--token-color-consul-gradient-primary-stop:#da306e;--token-color-consul-gradient-faint-start:#fff9fb;--token-color-consul-gradient-faint-stop:#ffe9f1;--token-color-hcp-brand:#000000;--token-color-nomad-brand:#06d092;--token-color-nomad-foreground:#008661;--token-color-nomad-surface:#d3fdeb;--token-color-nomad-border:#bff3dd;--token-color-nomad-gradient-primary-start:#bff3dd;--token-color-nomad-gradient-primary-stop:#60dea9;--token-color-nomad-gradient-faint-start:#f3fff9;--token-color-nomad-gradient-faint-stop:#d3fdeb;--token-color-packer-brand:#02a8ef;--token-color-packer-foreground:#007eb4;--token-color-packer-surface:#d4f2ff;--token-color-packer-border:#b4e4ff;--token-color-packer-gradient-primary-start:#b4e4ff;--token-color-packer-gradient-primary-stop:#63d0ff;--token-color-packer-gradient-faint-start:#f3fcff;--token-color-packer-gradient-faint-stop:#d4f2ff;--token-color-terraform-brand:#7b42bc;--token-color-terraform-foreground:#773cb4;--token-color-terraform-surface:#f4ecff;--token-color-terraform-border:#ebdbfc;--token-color-terraform-gradient-primary-start:#bb8deb;--token-color-terraform-gradient-primary-stop:#844fba;--token-color-terraform-gradient-faint-start:#fcfaff;--token-color-terraform-gradient-faint-stop:#f4ecff;--token-color-vagrant-brand:#1868f2;--token-color-vagrant-foreground:#1c61d8;--token-color-vagrant-surface:#d6ebff;--token-color-vagrant-border:#c7dbfc;--token-color-vagrant-gradient-primary-start:#c7dbfc;--token-color-vagrant-gradient-primary-stop:#7dadff;--token-color-vagrant-gradient-faint-start:#f4faff;--token-color-vagrant-gradient-faint-stop:#d6ebff;--token-color-vault-brand:#ffd814;--token-color-vault-brand-alt:#000000;--token-color-vault-foreground:#9a6f00;--token-color-vault-surface:#fff9cf;--token-color-vault-border:#feec7b;--token-color-vault-gradient-primary-start:#feec7b;--token-color-vault-gradient-primary-stop:#ffe543;--token-color-vault-gradient-faint-start:#fffdf2;--token-color-vault-gradient-faint-stop:#fff9cf;--token-color-waypoint-brand:#14c6cb;--token-color-waypoint-foreground:#008196;--token-color-waypoint-surface:#e0fcff;--token-color-waypoint-border:#cbf1f3;--token-color-waypoint-gradient-primary-start:#cbf1f3;--token-color-waypoint-gradient-primary-stop:#62d4dc;--token-color-waypoint-gradient-faint-start:#f6feff;--token-color-waypoint-gradient-faint-stop:#e0fcff;--token-elevation-inset-box-shadow:inset 0px 1px 2px 1px #656a761a;--token-elevation-low-box-shadow:0px 1px 1px 0px #656a760d,0px 2px 2px 0px #656a760d;--token-elevation-mid-box-shadow:0px 2px 3px 0px #656a761a,0px 8px 16px -10px #656a7633;--token-elevation-high-box-shadow:0px 2px 3px 0px #656a7626,0px 16px 16px -10px #656a7633;--token-elevation-higher-box-shadow:0px 2px 3px 0px #656a761a,0px 12px 28px 0px #656a7640;--token-elevation-overlay-box-shadow:0px 2px 3px 0px #3b3d4580,0px 12px 24px 0px #3b3d4599;--token-surface-inset-box-shadow:inset 0 0 0 1px #656a764d,inset 0px 1px 2px 1px #656a761a;--token-surface-base-box-shadow:0 0 0 1px #656a7633;--token-surface-low-box-shadow:0 0 0 1px #656a7626,0px 1px 1px 0px #656a760d,0px 2px 2px 0px #656a760d;--token-surface-mid-box-shadow:0 0 0 1px #656a7626,0px 2px 3px 0px #656a761a,0px 8px 16px -10px #656a7633;--token-surface-high-box-shadow:0 0 0 1px #656a7640,0px 2px 3px 0px #656a7626,0px 16px 16px -10px #656a7633;--token-surface-higher-box-shadow:0 0 0 1px #656a7633,0px 2px 3px 0px #656a761a,0px 12px 28px 0px #656a7640;--token-surface-overlay-box-shadow:0 0 0 1px #3b3d4566,0px 2px 3px 0px #3b3d4580,0px 12px 24px 0px #3b3d4599;--token-focus-ring-action-box-shadow:inset 0 0 0 1px #0c56e9,0 0 0 3px #5990ff;--token-focus-ring-critical-box-shadow:inset 0 0 0 1px #c00005,0 0 0 3px #dd7578;--token-form-label-color:#0c0c0e;--token-form-legend-color:#0c0c0e;--token-form-helper-text-color:#656a76;--token-form-indicator-optional-color:#656a76;--token-form-error-color:#c00005;--token-form-error-icon-size:14px;--token-form-checkbox-size:16px;--token-form-checkbox-border-radius:3px;--token-form-checkbox-border-width:1px;--token-form-checkbox-background-image-size:12px;--token-form-checkbox-background-image-data-url:url("data:image/svg+xml,%3csvg viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M9.78033 3.21967C10.0732 3.51256 10.0732 3.98744 9.78033 4.28033L5.28033 8.78033C4.98744 9.07322 4.51256 9.07322 4.21967 8.78033L2.21967 6.78033C1.92678 6.48744 1.92678 6.01256 2.21967 5.71967C2.51256 5.42678 2.98744 5.42678 3.28033 5.71967L4.75 7.18934L8.71967 3.21967C9.01256 2.92678 9.48744 2.92678 9.78033 3.21967Z' fill='%23FFF'/%3e%3c/svg%3e");--token-form-checkbox-background-image-data-url-disabled:url("data:image/svg+xml,%3csvg viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M9.78033 3.21967C10.0732 3.51256 10.0732 3.98744 9.78033 4.28033L5.28033 8.78033C4.98744 9.07322 4.51256 9.07322 4.21967 8.78033L2.21967 6.78033C1.92678 6.48744 1.92678 6.01256 2.21967 5.71967C2.51256 5.42678 2.98744 5.42678 3.28033 5.71967L4.75 7.18934L8.71967 3.21967C9.01256 2.92678 9.48744 2.92678 9.78033 3.21967Z' fill='%238C909C'/%3e%3c/svg%3e");--token-form-control-base-foreground-value-color:#0c0c0e;--token-form-control-base-foreground-placeholder-color:#656a76;--token-form-control-base-surface-color-default:#ffffff;--token-form-control-base-surface-color-hover:#f1f2f3;--token-form-control-base-border-color-default:#8c909c;--token-form-control-base-border-color-hover:#656a76;--token-form-control-checked-foreground-color:#ffffff;--token-form-control-checked-surface-color-default:#1060ff;--token-form-control-checked-surface-color-hover:#0c56e9;--token-form-control-checked-border-color-default:#0c56e9;--token-form-control-checked-border-color-hover:#0046d1;--token-form-control-invalid-border-color-default:#c00005;--token-form-control-invalid-border-color-hover:#940004;--token-form-control-readonly-foreground-color:#3b3d45;--token-form-control-readonly-surface-color:#f1f2f3;--token-form-control-readonly-border-color:#656a761a;--token-form-control-disabled-foreground-color:#8c909c;--token-form-control-disabled-surface-color:#fafafa;--token-form-control-disabled-border-color:#656a7633;--token-form-control-padding:7px;--token-form-control-border-radius:5px;--token-form-control-border-width:1px;--token-form-radio-size:16px;--token-form-radio-border-width:1px;--token-form-radio-background-image-size:12px;--token-form-radio-background-image-data-url:url("data:image/svg+xml,%3csvg width='12' height='12' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='6' cy='6' r='2.5' fill='%23ffffff'/%3e%3c/svg%3e");--token-form-radio-background-image-data-url-disabled:url("data:image/svg+xml,%3csvg width='12' height='12' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='6' cy='6' r='2.5' fill='%238C909C'/%3e%3c/svg%3e");--token-form-select-background-image-size:16px;--token-form-select-background-image-position-right-x:7px;--token-form-select-background-image-position-top-y:9px;--token-form-select-background-image-data-url:url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.55 2.24a.75.75 0 0 0-1.1 0L4.2 5.74a.75.75 0 1 0 1.1 1.02L8 3.852l2.7 2.908a.75.75 0 1 0 1.1-1.02l-3.25-3.5Zm-1.1 11.52a.75.75 0 0 0 1.1 0l3.25-3.5a.75.75 0 1 0-1.1-1.02L8 12.148 5.3 9.24a.75.75 0 0 0-1.1 1.02l3.25 3.5Z' fill='%23656A76'/%3E%3C/svg%3E");--token-form-select-background-image-data-url-disabled:url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.55 2.24a.75.75 0 0 0-1.1 0L4.2 5.74a.75.75 0 1 0 1.1 1.02L8 3.852l2.7 2.908a.75.75 0 1 0 1.1-1.02l-3.25-3.5Zm-1.1 11.52a.75.75 0 0 0 1.1 0l3.25-3.5a.75.75 0 1 0-1.1-1.02L8 12.148 5.3 9.24a.75.75 0 0 0-1.1 1.02l3.25 3.5Z' fill='%238C909C'/%3E%3C/svg%3E");--token-form-text-input-background-image-size:16px;--token-form-text-input-background-image-position-x:7px;--token-form-text-input-background-image-data-url-date:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M11.5.75a.75.75 0 00-1.5 0V1H6V.75a.75.75 0 00-1.5 0V1H3.25A2.25 2.25 0 001 3.25v9.5A2.25 2.25 0 003.25 15h9.5A2.25 2.25 0 0015 12.75v-9.5A2.25 2.25 0 0012.75 1H11.5V.75zm-7 2.5V2.5H3.25a.75.75 0 00-.75.75V5h11V3.25a.75.75 0 00-.75-.75H11.5v.75a.75.75 0 01-1.5 0V2.5H6v.75a.75.75 0 01-1.5 0zm9 3.25h-11v6.25c0 .414.336.75.75.75h9.5a.75.75 0 00.75-.75V6.5z' fill-rule='evenodd' clip-rule='evenodd' fill='%233B3D45'/%3e%3c/svg%3e");--token-form-text-input-background-image-data-url-time:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3e%3cg fill='%233B3D45'%3e%3cpath d='M8.5 3.75a.75.75 0 00-1.5 0V8c0 .284.16.544.415.67l2.5 1.25a.75.75 0 10.67-1.34L8.5 7.535V3.75z'/%3e%3cpath d='M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z' fill-rule='evenodd' clip-rule='evenodd'/%3e%3c/g%3e%3c/svg%3e");--token-form-text-input-background-image-data-url-search:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3e%3cg fill='%23656A76'%3e%3cpath d='M7.25 2a5.25 5.25 0 103.144 9.455l2.326 2.325a.75.75 0 101.06-1.06l-2.325-2.326A5.25 5.25 0 007.25 2zM3.5 7.25a3.75 3.75 0 117.5 0 3.75 3.75 0 01-7.5 0z' fill-rule='evenodd' clip-rule='evenodd'/%3e%3c/g%3e%3c/svg%3e");--token-form-text-input-background-image-data-url-search-cancel:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.78 4.28a.75.75 0 00-1.06-1.06L8 6.94 4.28 3.22a.75.75 0 00-1.06 1.06L6.94 8l-3.72 3.72a.75.75 0 101.06 1.06L8 9.06l3.72 3.72a.75.75 0 101.06-1.06L9.06 8l3.72-3.72z'/%3e%3c/svg%3e");--token-form-toggle-width:32px;--token-form-toggle-height:16px;--token-form-toggle-base-surface-color-default:#f1f2f3;--token-form-toggle-border-radius:3px;--token-form-toggle-border-width:1px;--token-form-toggle-background-image-size:12px;--token-form-toggle-background-image-position-x:2px;--token-form-toggle-background-image-data-url:url("data:image/svg+xml,%3csvg viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M9.78033 3.21967C10.0732 3.51256 10.0732 3.98744 9.78033 4.28033L5.28033 8.78033C4.98744 9.07322 4.51256 9.07322 4.21967 8.78033L2.21967 6.78033C1.92678 6.48744 1.92678 6.01256 2.21967 5.71967C2.51256 5.42678 2.98744 5.42678 3.28033 5.71967L4.75 7.18934L8.71967 3.21967C9.01256 2.92678 9.48744 2.92678 9.78033 3.21967Z' fill='%23FFF'/%3e%3c/svg%3e");--token-form-toggle-background-image-data-url-disabled:url("data:image/svg+xml,%3csvg viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M9.78033 3.21967C10.0732 3.51256 10.0732 3.98744 9.78033 4.28033L5.28033 8.78033C4.98744 9.07322 4.51256 9.07322 4.21967 8.78033L2.21967 6.78033C1.92678 6.48744 1.92678 6.01256 2.21967 5.71967C2.51256 5.42678 2.98744 5.42678 3.28033 5.71967L4.75 7.18934L8.71967 3.21967C9.01256 2.92678 9.48744 2.92678 9.78033 3.21967Z' fill='%238C909C'/%3e%3c/svg%3e");--token-form-toggle-transition-duration:0.2s;--token-form-toggle-transition-timing-function:cubic-bezier(0.68, -0.2, 0.265, 1.15);--token-form-toggle-thumb-size:16px;--token-typography-font-stack-display:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-font-stack-text:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-font-stack-code:ui-monospace,Menlo,Consolas,monospace;--token-typography-font-weight-regular:400;--token-typography-font-weight-medium:500;--token-typography-font-weight-semibold:600;--token-typography-font-weight-bold:700;--token-typography-display-500-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-display-500-font-size:1.875rem;--token-typography-display-500-line-height:1.2666;--token-typography-display-400-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-display-400-font-size:1.5rem;--token-typography-display-400-line-height:1.3333;--token-typography-display-300-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-display-300-font-size:1.125rem;--token-typography-display-300-line-height:1.3333;--token-typography-display-300-letter-spacing:-0.5px;--token-typography-display-200-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-display-200-font-size:1rem;--token-typography-display-200-line-height:1.5;--token-typography-display-200-letter-spacing:-0.5px;--token-typography-display-100-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-display-100-font-size:0.8125rem;--token-typography-display-100-line-height:1.3846;--token-typography-body-300-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-body-300-font-size:1rem;--token-typography-body-300-line-height:1.5;--token-typography-body-200-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-body-200-font-size:0.875rem;--token-typography-body-200-line-height:1.4286;--token-typography-body-100-font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;--token-typography-body-100-font-size:0.8125rem;--token-typography-body-100-line-height:1.3846;--token-typography-code-100-font-family:ui-monospace,Menlo,Consolas,monospace;--token-typography-code-100-font-size:0.8125rem;--token-typography-code-100-line-height:1.23;--decor-radius-000:0;--decor-radius-100:2px;--decor-radius-200:4px;--decor-radius-250:6px;--decor-radius-300:7px;--decor-radius-999:9999px;--decor-radius-full:100%;--decor-border-000:none;--decor-border-100:1px solid;--decor-border-200:2px solid;--decor-border-300:3px solid;--decor-border-400:4px solid;--color-info:var(--token-color-foreground-action);--color-alert:var(--token-color-palette-amber-200);--typo-family-sans:BlinkMacSystemFont,-apple-system,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue","Helvetica","Arial",sans-serif;--typo-family-mono:monospace;--typo-size-000:16px;--typo-size-100:3.5rem;--typo-size-200:1.8rem;--typo-size-250:1.750rem;--typo-size-300:1.3rem;--typo-size-400:1.2rem;--typo-size-450:1.125rem;--typo-size-500:1rem;--typo-size-600:0.875rem;--typo-size-700:0.8125rem;--typo-size-800:0.75rem;--typo-weight-light:300;--typo-weight-normal:400;--typo-weight-medium:500;--typo-weight-semibold:600;--typo-weight-bold:700;--typo-lead-000:0;--typo-lead-050:1;--typo-lead-100:1.2;--typo-lead-200:1.25;--typo-lead-300:1.28;--typo-lead-500:1.33;--typo-lead-600:1.4;--typo-lead-700:1.5;--typo-lead-800:1.7;--icon-alert-triangle-16:url('data:image/svg+xml;charset=UTF-8,');--icon-alert-triangle-24:url('data:image/svg+xml;charset=UTF-8,');--icon-arrow-left-16:url('data:image/svg+xml;charset=UTF-8,');--icon-arrow-left-24:url('data:image/svg+xml;charset=UTF-8,');--icon-arrow-right-16:url('data:image/svg+xml;charset=UTF-8,');--icon-arrow-right-24:url('data:image/svg+xml;charset=UTF-8,');--icon-x-square-fill-16:url('data:image/svg+xml;charset=UTF-8,');--icon-x-square-fill-24:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-down-16:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-down-24:url('data:image/svg+xml;charset=UTF-8,');--icon-clipboard-copy-16:url('data:image/svg+xml;charset=UTF-8,');--icon-clipboard-copy-24:url('data:image/svg+xml;charset=UTF-8,');--icon-docs-16:url('data:image/svg+xml;charset=UTF-8,');--icon-docs-24:url('data:image/svg+xml;charset=UTF-8,');--icon-external-link-16:url('data:image/svg+xml;charset=UTF-8,');--icon-external-link-24:url('data:image/svg+xml;charset=UTF-8,');--icon-file-16:url('data:image/svg+xml;charset=UTF-8,');--icon-file-24:url('data:image/svg+xml;charset=UTF-8,');--icon-folder-16:url('data:image/svg+xml;charset=UTF-8,');--icon-folder-24:url('data:image/svg+xml;charset=UTF-8,');--icon-activity-16:url('data:image/svg+xml;charset=UTF-8,');--icon-activity-24:url('data:image/svg+xml;charset=UTF-8,');--icon-help-16:url('data:image/svg+xml;charset=UTF-8,');--icon-help-24:url('data:image/svg+xml;charset=UTF-8,');--icon-learn-16:url('data:image/svg+xml;charset=UTF-8,');--icon-learn-24:url('data:image/svg+xml;charset=UTF-8,');--icon-github-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-github-color-24:url('data:image/svg+xml;charset=UTF-8,');--icon-google-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-google-color-24:url('data:image/svg+xml;charset=UTF-8,');--icon-kubernetes-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-kubernetes-color-24:url('data:image/svg+xml;charset=UTF-8,');--icon-menu-16:url('data:image/svg+xml;charset=UTF-8,');--icon-menu-24:url('data:image/svg+xml;charset=UTF-8,');--icon-minus-square-16:url('data:image/svg+xml;charset=UTF-8,');--icon-minus-square-24:url('data:image/svg+xml;charset=UTF-8,');--icon-more-horizontal-16:url('data:image/svg+xml;charset=UTF-8,');--icon-more-horizontal-24:url('data:image/svg+xml;charset=UTF-8,');--icon-globe-16:url('data:image/svg+xml;charset=UTF-8,');--icon-globe-24:url('data:image/svg+xml;charset=UTF-8,');--icon-search-16:url('data:image/svg+xml;charset=UTF-8,');--icon-search-24:url('data:image/svg+xml;charset=UTF-8,');--icon-star-16:url('data:image/svg+xml;charset=UTF-8,');--icon-star-24:url('data:image/svg+xml;charset=UTF-8,');--icon-org-16:url('data:image/svg+xml;charset=UTF-8,');--icon-org-24:url('data:image/svg+xml;charset=UTF-8,');--icon-user-16:url('data:image/svg+xml;charset=UTF-8,');--icon-user-24:url('data:image/svg+xml;charset=UTF-8,');--icon-users-16:url('data:image/svg+xml;charset=UTF-8,');--icon-users-24:url('data:image/svg+xml;charset=UTF-8,');--icon-alert-circle-16:url('data:image/svg+xml;charset=UTF-8,');--icon-alert-circle-24:url('data:image/svg+xml;charset=UTF-8,');--icon-check-16:url('data:image/svg+xml;charset=UTF-8,');--icon-check-24:url('data:image/svg+xml;charset=UTF-8,');--icon-check-circle-16:url('data:image/svg+xml;charset=UTF-8,');--icon-check-circle-24:url('data:image/svg+xml;charset=UTF-8,');--icon-check-circle-fill-16:url('data:image/svg+xml;charset=UTF-8,');--icon-check-circle-fill-24:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-left-16:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-left-24:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-right-16:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-right-24:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-up-16:url('data:image/svg+xml;charset=UTF-8,');--icon-chevron-up-24:url('data:image/svg+xml;charset=UTF-8,');--icon-delay-16:url('data:image/svg+xml;charset=UTF-8,');--icon-delay-24:url('data:image/svg+xml;charset=UTF-8,');--icon-docs-link-16:url('data:image/svg+xml;charset=UTF-8,');--icon-docs-link-24:url('data:image/svg+xml;charset=UTF-8,');--icon-eye-16:url('data:image/svg+xml;charset=UTF-8,');--icon-eye-24:url('data:image/svg+xml;charset=UTF-8,');--icon-eye-off-16:url('data:image/svg+xml;charset=UTF-8,');--icon-eye-off-24:url('data:image/svg+xml;charset=UTF-8,');--icon-file-text-16:url('data:image/svg+xml;charset=UTF-8,');--icon-file-text-24:url('data:image/svg+xml;charset=UTF-8,');--icon-gateway-16:url('data:image/svg+xml;charset=UTF-8,');--icon-gateway-24:url('data:image/svg+xml;charset=UTF-8,');--icon-git-commit-16:url('data:image/svg+xml;charset=UTF-8,');--icon-git-commit-24:url('data:image/svg+xml;charset=UTF-8,');--icon-hexagon-16:url('data:image/svg+xml;charset=UTF-8,');--icon-hexagon-24:url('data:image/svg+xml;charset=UTF-8,');--icon-history-16:url('data:image/svg+xml;charset=UTF-8,');--icon-history-24:url('data:image/svg+xml;charset=UTF-8,');--icon-info-16:url('data:image/svg+xml;charset=UTF-8,');--icon-info-24:url('data:image/svg+xml;charset=UTF-8,');--icon-layers-16:url('data:image/svg+xml;charset=UTF-8,');--icon-layers-24:url('data:image/svg+xml;charset=UTF-8,');--icon-loading-16:url('data:image/svg+xml;charset=UTF-8,');--icon-loading-24:url('data:image/svg+xml;charset=UTF-8,');--icon-network-alt-16:url('data:image/svg+xml;charset=UTF-8,');--icon-network-alt-24:url('data:image/svg+xml;charset=UTF-8,');--icon-path-16:url('data:image/svg+xml;charset=UTF-8,');--icon-path-24:url('data:image/svg+xml;charset=UTF-8,');--icon-running-16:url('data:image/svg+xml;charset=UTF-8,');--icon-running-24:url('data:image/svg+xml;charset=UTF-8,');--icon-skip-16:url('data:image/svg+xml;charset=UTF-8,');--icon-skip-24:url('data:image/svg+xml;charset=UTF-8,');--icon-socket-16:url('data:image/svg+xml;charset=UTF-8,');--icon-socket-24:url('data:image/svg+xml;charset=UTF-8,');--icon-star-circle-16:url('data:image/svg+xml;charset=UTF-8,');--icon-star-circle-24:url('data:image/svg+xml;charset=UTF-8,');--icon-star-fill-16:url('data:image/svg+xml;charset=UTF-8,');--icon-star-fill-24:url('data:image/svg+xml;charset=UTF-8,');--icon-tag-16:url('data:image/svg+xml;charset=UTF-8,');--icon-tag-24:url('data:image/svg+xml;charset=UTF-8,');--icon-x-16:url('data:image/svg+xml;charset=UTF-8,');--icon-x-24:url('data:image/svg+xml;charset=UTF-8,');--icon-x-circle-16:url('data:image/svg+xml;charset=UTF-8,');--icon-x-circle-24:url('data:image/svg+xml;charset=UTF-8,');--icon-x-square-16:url('data:image/svg+xml;charset=UTF-8,');--icon-x-square-24:url('data:image/svg+xml;charset=UTF-8,');--icon-cloud-cross-16:url('data:image/svg+xml;charset=UTF-8,');--icon-loading-motion-16:url('data:image/svg+xml;charset=UTF-8,');--icon-auth0-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-auth0-color-24:url('data:image/svg+xml;charset=UTF-8,');--icon-logo-ember-circle-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-logo-glimmer-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-logo-jwt-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-microsoft-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-microsoft-color-24:url('data:image/svg+xml;charset=UTF-8,');--icon-logo-oidc-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-okta-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-okta-color-24:url('data:image/svg+xml;charset=UTF-8,');--icon-mesh-16:url('data:image/svg+xml;charset=UTF-8,');--icon-mesh-24:url('data:image/svg+xml;charset=UTF-8,');--icon-port-16:url('data:image/svg+xml;charset=UTF-8,');--icon-protocol-16:url('data:image/svg+xml;charset=UTF-8,');--icon-redirect-16:url('data:image/svg+xml;charset=UTF-8,');--icon-redirect-24:url('data:image/svg+xml;charset=UTF-8,');--icon-search-color-16:url('data:image/svg+xml;charset=UTF-8,');--icon-sort-desc-16:url('data:image/svg+xml;charset=UTF-8,');--icon-sort-desc-24:url('data:image/svg+xml;charset=UTF-8,');--icon-union-16:url('data:image/svg+xml;charset=UTF-8,');--chrome-width:280px;--chrome-height:64px;--typo-action:var(--token-color-foreground-action);--decor-error:var(--token-color-foreground-critical);--typo-contrast:var(--token-color-hashicorp-brand);--syntax-light-grey:#dde3e7;--syntax-light-gray:#a4a4a4;--syntax-light-grey-blue:#6c7b81;--syntax-dark-grey:#788290;--syntax-faded-gray:#eaeaea;--syntax-atlas:#127eff;--syntax-vagrant:#2f88f7;--syntax-consul:#69499a;--syntax-terraform:#822ff7;--syntax-serf:#dd4e58;--syntax-packer:#1ddba3;--syntax-gray:lighten(#000, 89%);--syntax-red:#ff3d3d;--syntax-green:#39b54a;--syntax-dark-gray:#535f73;--syntax-gutter-grey:#2a2f36;--syntax-yellow:var(--token-color-vault-brand);--horizontal-kv-list-separator-width:18px;--horizontal-kv-list-key-separator:":";--horizontal-kv-list-key-wrapper-start:"(";--horizontal-kv-list-key-wrapper-end:")";--csv-list-separator:",";--icon-loading:icon-loading-motion}.hds-border-primary{border:1px solid var(--token-color-border-primary)}.hds-border-faint{border:1px solid var(--token-color-border-faint)}.hds-border-strong{border:1px solid var(--token-color-border-strong)}.hds-border-action{border:1px solid var(--token-color-border-action)}.hds-border-highlight{border:1px solid var(--token-color-border-highlight)}.hds-border-success{border:1px solid var(--token-color-border-success)}.hds-border-warning{border:1px solid var(--token-color-border-warning)}.hds-border-critical{border:1px solid var(--token-color-border-critical)}.hds-foreground-strong{color:var(--token-color-foreground-strong)}.hds-foreground-primary{color:var(--token-color-foreground-primary)}.hds-foreground-faint{color:var(--token-color-foreground-faint)}.hds-foreground-high-contrast{color:var(--token-color-foreground-high-contrast)}.hds-foreground-disabled{color:var(--token-color-foreground-disabled)}.hds-foreground-action{color:var(--token-color-foreground-action)}.hds-foreground-action-hover{color:var(--token-color-foreground-action-hover)}.hds-foreground-action-active{color:var(--token-color-foreground-action-active)}.hds-foreground-highlight{color:var(--token-color-foreground-highlight)}.hds-foreground-highlight-on-surface{color:var(--token-color-foreground-highlight-on-surface)}.hds-foreground-highlight-high-contrast{color:var(--token-color-foreground-highlight-high-contrast)}.hds-foreground-success{color:var(--token-color-foreground-success)}.hds-foreground-success-on-surface{color:var(--token-color-foreground-success-on-surface)}.hds-foreground-success-high-contrast{color:var(--token-color-foreground-success-high-contrast)}.hds-foreground-warning{color:var(--token-color-foreground-warning)}.hds-alert__text,.hds-foreground-warning-on-surface{color:var(--token-color-foreground-warning-on-surface)}.hds-foreground-warning-high-contrast{color:var(--token-color-foreground-warning-high-contrast)}.hds-foreground-critical{color:var(--token-color-foreground-critical)}.hds-foreground-critical-on-surface{color:var(--token-color-foreground-critical-on-surface)}.hds-foreground-critical-high-contrast{color:var(--token-color-foreground-critical-high-contrast)}.hds-page-primary{background-color:var(--token-color-page-primary)}.hds-page-faint{background-color:var(--token-color-page-faint)}.hds-surface-primary{background-color:var(--token-color-surface-primary)}.hds-surface-faint{background-color:var(--token-color-surface-faint)}.hds-surface-strong{background-color:var(--token-color-surface-strong)}.hds-surface-interactive{background-color:var(--token-color-surface-interactive)}.hds-surface-interactive-hover{background-color:var(--token-color-surface-interactive-hover)}.hds-surface-interactive-active{background-color:var(--token-color-surface-interactive-active)}.hds-surface-interactive-disabled{background-color:var(--token-color-surface-interactive-disabled)}.hds-surface-action{background-color:var(--token-color-surface-action)}.hds-surface-highlight{background-color:var(--token-color-surface-highlight)}.hds-surface-success{background-color:var(--token-color-surface-success)}.hds-surface-warning{background-color:var(--token-color-surface-warning)}.hds-surface-critical{background-color:var(--token-color-surface-critical)}.hds-elevation-inset{box-shadow:var(--token-elevation-inset-box-shadow)}.hds-elevation-low{box-shadow:var(--token-elevation-low-box-shadow)}.hds-elevation-mid{box-shadow:var(--token-elevation-mid-box-shadow)}.hds-elevation-high{box-shadow:var(--token-elevation-high-box-shadow)}.hds-elevation-higher{box-shadow:var(--token-elevation-higher-box-shadow)}.hds-elevation-overlay{box-shadow:var(--token-elevation-overlay-box-shadow)}.hds-surface-inset{box-shadow:var(--token-surface-inset-box-shadow)}.hds-surface-base{box-shadow:var(--token-surface-base-box-shadow)}.hds-surface-low{box-shadow:var(--token-surface-low-box-shadow)}.hds-surface-mid{box-shadow:var(--token-surface-mid-box-shadow)}.hds-surface-high{box-shadow:var(--token-surface-high-box-shadow)}.hds-surface-higher{box-shadow:var(--token-surface-higher-box-shadow)}.hds-surface-overlay{box-shadow:var(--token-surface-overlay-box-shadow)}.hds-breadcrumb__link.mock-focus,.hds-breadcrumb__link:focus,.hds-focus-ring-action-box-shadow{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-focus-ring-critical-box-shadow{box-shadow:var(--token-focus-ring-critical-box-shadow)}.hds-font-family-sans-display{font-family:var(--token-typography-font-stack-display)}.hds-font-family-sans-text{font-family:var(--token-typography-font-stack-text)}.hds-font-family-mono-code{font-family:var(--token-typography-font-stack-code)}.hds-font-weight-regular{font-weight:400}.hds-font-weight-medium{font-weight:500}.hds-font-weight-semibold{font-weight:600}.hds-font-weight-bold{font-weight:700}.hds-typography-display-500{font-family:var(--token-typography-display-500-font-family);font-size:var(--token-typography-display-500-font-size);line-height:var(--token-typography-display-500-line-height);margin:0;padding:0}.hds-typography-display-400{font-family:var(--token-typography-display-400-font-family);font-size:var(--token-typography-display-400-font-size);line-height:var(--token-typography-display-400-line-height);margin:0;padding:0}.hds-typography-display-300{font-family:var(--token-typography-display-300-font-family);font-size:var(--token-typography-display-300-font-size);line-height:var(--token-typography-display-300-line-height);margin:0;padding:0}.hds-typography-display-200{font-family:var(--token-typography-display-200-font-family);font-size:var(--token-typography-display-200-font-size);line-height:var(--token-typography-display-200-line-height);margin:0;padding:0}.hds-typography-display-100{font-family:var(--token-typography-display-100-font-family);font-size:var(--token-typography-display-100-font-size);line-height:var(--token-typography-display-100-line-height);margin:0;padding:0}.hds-typography-body-300{font-family:var(--token-typography-body-300-font-family);font-size:var(--token-typography-body-300-font-size);line-height:var(--token-typography-body-300-line-height);margin:0;padding:0}.hds-typography-body-200{font-family:var(--token-typography-body-200-font-family);font-size:var(--token-typography-body-200-font-size);line-height:var(--token-typography-body-200-line-height);margin:0;padding:0}.hds-typography-body-100{font-family:var(--token-typography-body-100-font-family);font-size:var(--token-typography-body-100-font-size);line-height:var(--token-typography-body-100-line-height);margin:0;padding:0}.hds-typography-code-100{font-family:var(--token-typography-code-100-font-family);font-size:var(--token-typography-code-100-font-size);line-height:var(--token-typography-code-100-line-height);margin:0;padding:0}.hds-alert{display:flex;align-items:flex-start}.hds-alert__icon{flex:none;width:20px;height:20px;margin-right:12px}.hds-alert__content{flex:1 1 auto}.hds-alert__text{display:flex;flex-direction:column;justify-content:center;font-size:var(--token-typography-body-200-font-size);font-family:var(--token-typography-body-200-font-family);line-height:var(--token-typography-body-200-line-height)}.hds-alert--type-compact .hds-alert__text,.hds-pagination-size-selector>select{font-size:var(--token-typography-body-100-font-size);font-family:var(--token-typography-body-100-font-family);line-height:var(--token-typography-body-100-line-height)}.hds-alert__title{font-weight:var(--token-typography-font-weight-semibold)}.hds-alert__description{color:var(--token-color-foreground-primary);font-weight:var(--token-typography-font-weight-regular);word-break:break-word}.hds-alert__title+.hds-alert__description{margin-top:4px}.hds-alert__description strong{font-weight:var(--token-typography-font-weight-semibold)}.hds-badge-count,.hds-badge__text,.hds-link-standalone{font-weight:var(--token-typography-font-weight-medium)}.hds-alert__description code,.hds-alert__description pre{display:inline;padding:1px 5px;font-size:.9em;font-family:var(--token-typography-code-100-font-family);line-height:1em;background-color:var(--token-color-surface-primary);border:1px solid var(--token-color-palette-neutral-200);border-radius:5px}.hds-badge-count,.hds-badge__text,.hds-breadcrumb__text,.hds-button,.hds-link-standalone,.hds-stepper-indicator-step__text,.hds-tag{font-family:var(--token-typography-font-stack-text)}.hds-alert__description a{color:var(--token-color-foreground-action)}.hds-alert__description a:focus,.hds-alert__description a:focus-visible{text-decoration:none;outline:var(--token-color-focus-action-internal) solid 2px;outline-offset:1px}.hds-alert__description a:hover{color:var(--token-color-foreground-action-hover)}.hds-alert__description a:active{color:var(--token-color-foreground-action-active)}.hds-alert__actions{display:flex;align-items:center}.hds-alert--type-compact .hds-alert__title,button.hds-button[href] .hds-button__text,button.hds-button[href]::before{display:none}.hds-alert__actions>*{margin-top:16px}.hds-alert__actions>*+*{margin-left:8px}.hds-alert__dismiss{margin-top:2px;margin-left:16px}.hds-alert--type-compact .hds-alert__dismiss{margin-top:1px}.hds-alert--type-page{padding:16px 48px}.hds-alert--type-inline{padding:16px;border-style:solid;border-width:1px;border-radius:6px}.hds-alert--type-compact .hds-alert__icon{width:14px;height:14px;margin-top:2px;margin-right:8px}.hds-alert--type-compact .hds-alert__title+.hds-alert__description{margin-top:0}.hds-alert--color-neutral.hds-alert--type-page{background-color:var(--token-color-surface-faint);box-shadow:0 1px 0 0 var(--token-color-palette-alpha-300)}.hds-alert--color-neutral.hds-alert--type-inline{background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-strong)}.hds-alert--color-neutral .hds-alert__icon{color:var(--token-color-foreground-faint)}.hds-alert--color-neutral .hds-alert__title{color:var(--token-color-foreground-primary)}.hds-alert--color-highlight.hds-alert--type-page{background-color:var(--token-color-surface-highlight);box-shadow:0 1px 0 0 var(--token-color-border-highlight)}.hds-alert--color-highlight.hds-alert--type-inline{background-color:var(--token-color-surface-highlight);border-color:var(--token-color-border-highlight)}.hds-alert--color-highlight .hds-alert__icon,.hds-alert--color-highlight .hds-alert__title{color:var(--token-color-foreground-highlight-on-surface)}.hds-alert--color-success.hds-alert--type-page{background-color:var(--token-color-surface-success);box-shadow:0 1px 0 0 var(--token-color-border-success)}.hds-alert--color-success.hds-alert--type-inline{background-color:var(--token-color-surface-success);border-color:var(--token-color-border-success)}.hds-alert--color-success .hds-alert__icon,.hds-alert--color-success .hds-alert__title{color:var(--token-color-foreground-success-on-surface)}.hds-alert--color-warning.hds-alert--type-page{background-color:var(--token-color-surface-warning);box-shadow:0 1px 0 0 var(--token-color-border-warning)}.hds-alert--color-warning.hds-alert--type-inline{background-color:var(--token-color-surface-warning);border-color:var(--token-color-border-warning)}.hds-alert--color-warning .hds-alert__icon,.hds-alert--color-warning .hds-alert__title{color:var(--token-color-foreground-warning-on-surface)}.hds-alert--color-critical.hds-alert--type-page{background-color:var(--token-color-surface-critical);box-shadow:0 1px 0 0 var(--token-color-border-critical)}.hds-alert--color-critical.hds-alert--type-inline{background-color:var(--token-color-surface-critical);border-color:var(--token-color-border-critical)}.hds-alert--color-critical .hds-alert__icon,.hds-alert--color-critical .hds-alert__title{color:var(--token-color-foreground-critical-on-surface)}.hds-avatar{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:32px;height:32px}.hds-avatar svg,.hds-form-toggle{display:inline-block}.hds-avatar img{width:inherit;height:inherit;border-radius:2px}.hds-badge{display:inline-flex;align-items:center;max-width:100%;vertical-align:middle;border:1px solid transparent;border-radius:5px}.hds-badge__icon{display:block;flex:0 0 auto}.hds-badge__text{flex:1 0 0}.hds-badge--size-small{min-height:1.25rem;padding:calc(.125rem - 1px) calc(.375rem - 1px)}.hds-badge--size-small .hds-badge__icon{width:.75rem;height:.75rem}.hds-badge--size-large .hds-badge__icon,.hds-badge--size-medium .hds-badge__icon{width:1rem;height:1rem}.hds-badge--size-small .hds-badge__text{font-size:.8125rem;line-height:1.2308}.hds-badge--size-small .hds-badge__icon+.hds-badge__text{-webkit-margin-start:.25rem;margin-inline-start:.25rem}.hds-badge--size-medium{min-height:1.5rem;padding:calc(.25rem - 1px) calc(.5rem - 1px)}.hds-badge--size-medium .hds-badge__text{font-size:.8125rem;line-height:1.2308}.hds-badge--size-medium .hds-badge__icon+.hds-badge__text{-webkit-margin-start:.25rem;margin-inline-start:.25rem}.hds-badge--size-large{min-height:2rem;padding:calc(.25rem - 1px) calc(.5rem - 1px)}.hds-badge--size-large .hds-badge__text{font-size:1rem;line-height:1.5}.hds-badge--size-large .hds-badge__icon+.hds-badge__text{-webkit-margin-start:.375rem;margin-inline-start:.375rem}.hds-badge--color-neutral.hds-badge--type-filled{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-strong)}.hds-badge--color-neutral.hds-badge--type-inverted{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-faint)}.hds-badge--color-neutral.hds-badge--type-outlined{color:var(--token-color-foreground-primary);background-color:transparent;border-color:var(--token-color-foreground-faint)}.hds-badge--color-neutral-dark-mode.hds-badge--type-filled{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-faint)}.hds-badge--color-neutral-dark-mode.hds-badge--type-inverted{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint)}.hds-badge--color-neutral-dark-mode.hds-badge--type-outlined{color:var(--token-color-foreground-high-contrast);background-color:transparent;border-color:var(--token-color-palette-neutral-100)}.hds-badge--color-highlight.hds-badge--type-filled{color:var(--token-color-foreground-highlight-on-surface);background-color:var(--token-color-surface-highlight)}.hds-badge--color-highlight.hds-badge--type-inverted{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-highlight)}.hds-badge--color-highlight.hds-badge--type-outlined{color:var(--token-color-foreground-highlight);background-color:transparent;border-color:currentColor}.hds-badge--color-success.hds-badge--type-filled{color:var(--token-color-foreground-success-on-surface);background-color:var(--token-color-surface-success)}.hds-badge--color-success.hds-badge--type-inverted{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-success)}.hds-badge--color-success.hds-badge--type-outlined{color:var(--token-color-foreground-success);background-color:transparent;border-color:currentColor}.hds-badge--color-warning.hds-badge--type-filled{color:var(--token-color-foreground-warning-on-surface);background-color:var(--token-color-surface-warning)}.hds-badge--color-warning.hds-badge--type-inverted{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-warning)}.hds-badge--color-warning.hds-badge--type-outlined{color:var(--token-color-foreground-warning);background-color:transparent;border-color:currentColor}.hds-badge--color-critical.hds-badge--type-filled{color:var(--token-color-foreground-critical-on-surface);background-color:var(--token-color-surface-critical)}.hds-badge--color-critical.hds-badge--type-inverted{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-critical)}.hds-badge--color-critical.hds-badge--type-outlined{color:var(--token-color-foreground-critical);background-color:transparent;border-color:currentColor}.hds-badge-count{display:inline-flex;align-items:center;max-width:100%;border:1px solid transparent}.hds-badge-count--size-small{min-height:1.25rem;padding:calc(.125rem - 1px) calc(.5rem - 1px);font-size:.8125rem;line-height:1.2308;border-radius:.625rem}.hds-badge-count--size-medium{min-height:1.5rem;padding:calc(.25rem - 1px) calc(.75rem - 1px);font-size:.8125rem;line-height:1.2308;border-radius:.75rem}.hds-badge-count--size-large{min-height:2rem;padding:calc(.25rem - 1px) calc(.875rem - 1px);font-size:1rem;line-height:1.5;border-radius:1rem}.hds-breadcrumb__list,.hds-breadcrumb__sublist{margin:0;padding:0;list-style:none}.hds-badge-count--color-neutral.hds-badge-count--type-filled{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-strong)}.hds-badge-count--color-neutral.hds-badge-count--type-inverted{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-faint)}.hds-badge-count--color-neutral.hds-badge-count--type-outlined{color:var(--token-color-foreground-primary);background-color:transparent;border-color:var(--token-color-foreground-faint)}.hds-badge-count--color-neutral-dark-mode.hds-badge-count--type-filled{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-foreground-faint)}.hds-badge-count--color-neutral-dark-mode.hds-badge-count--type-inverted{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint)}.hds-badge-count--color-neutral-dark-mode.hds-badge-count--type-outlined{color:var(--token-color-foreground-high-contrast);background-color:transparent;border-color:var(--token-color-palette-neutral-100)}.hds-breadcrumb__list{display:flex}.hds-breadcrumb--items-can-wrap .hds-breadcrumb__list{flex-wrap:wrap}.hds-breadcrumb__item{display:flex;flex-direction:row;align-items:center;min-width:0}.hds-breadcrumb__list>.hds-breadcrumb__item:not(:last-child)::after{padding:0 8px;color:var(--token-color-palette-neutral-300);content:"/"}.hds-breadcrumb__sublist>.hds-breadcrumb__item+.hds-breadcrumb__item{margin-top:4px}.hds-breadcrumb__item--is-truncation{flex:none}.hds-breadcrumb__link{display:flex;flex-direction:row;align-items:center;min-width:0;margin:0 -4px;padding:0 4px;color:var(--token-color-foreground-faint);border-radius:5px;-webkit-text-decoration-color:transparent;text-decoration-color:transparent;outline-style:solid;outline-color:transparent}.hds-breadcrumb__link.mock-active>.hds-breadcrumb__text,.hds-breadcrumb__link.mock-hover>.hds-breadcrumb__text,.hds-breadcrumb__link:active>.hds-breadcrumb__text,.hds-breadcrumb__link:hover>.hds-breadcrumb__text{-webkit-text-decoration-color:currentColor;text-decoration-color:currentColor}.hds-breadcrumb__link.mock-hover,.hds-breadcrumb__link:hover{color:var(--token-color-palette-neutral-600)}.hds-breadcrumb__link:focus:not(:focus-visible){box-shadow:none}.hds-breadcrumb__link:focus-visible{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-breadcrumb__link.mock-focus.mock-active,.hds-breadcrumb__link:focus:active{box-shadow:none}.hds-breadcrumb__link.mock-active,.hds-breadcrumb__link:active{color:var(--token-color-foreground-secondary)}.hds-breadcrumb__text,.hds-link-standalone,.hds-link-standalone__text{-webkit-text-decoration-color:transparent;text-decoration-color:transparent}.hds-breadcrumb__current{display:flex;flex-direction:row;align-items:center;min-width:0;margin:0 -4px;padding:0 4px;color:var(--token-color-foreground-strong)}.consul-exposed-path-list>ul>li>.detail,.consul-exposed-path-list>ul>li>.header>dl:first-child,.consul-lock-session-list ul>li:not(:first-child)>.detail,.consul-lock-session-list ul>li:not(:first-child)>.header>dl:first-child,.consul-upstream-instance-list li>.detail,.consul-upstream-instance-list li>.header>dl:first-child,.hds-breadcrumb__icon,.hds-pagination-nav__arrow--direction-next .hds-pagination-nav__arrow-label,.list-collection>ul>li:not(:first-child)>.detail,.list-collection>ul>li:not(:first-child)>.header>dl:first-child{margin-right:6px}.hds-breadcrumb__icon{flex:none;width:13px;height:13px}.hds-breadcrumb__text{padding:calc((28px - 1rem)/ 2) 0;overflow:hidden;font-size:.8125rem;line-height:1rem;white-space:nowrap;text-decoration:underline;text-overflow:ellipsis}.hds-breadcrumb__sublist .hds-breadcrumb__text{white-space:normal}.hds-breadcrumb__truncation-toggle{display:flex;flex:none;align-items:center;justify-content:center;width:28px;height:28px;margin:0 -4px;padding:0;color:var(--token-color-foreground-faint);background-color:transparent;border:1px solid transparent;border-radius:5px;outline:transparent solid 0;cursor:pointer}.hds-button,.hds-dismiss-button,.hds-dropdown-list-item--copy-item button,.hds-dropdown-list-item--interactive a,.hds-dropdown-list-item--interactive button,.hds-dropdown-toggle-icon{outline-style:solid;outline-color:transparent}.hds-breadcrumb__truncation-toggle.mock-hover,.hds-breadcrumb__truncation-toggle:hover{color:var(--token-color-foreground-faint);border-color:var(--token-color-border-strong)}.hds-breadcrumb__truncation-toggle.mock-focus,.hds-breadcrumb__truncation-toggle:focus{box-shadow:var(--token-focus-ring-action-box-shadow);background-color:transparent;border:none}.hds-breadcrumb__truncation-toggle:focus:not(:focus-visible){box-shadow:none}.hds-breadcrumb__truncation-toggle:focus-visible,.hds-dismiss-button.mock-focus::before,.hds-dismiss-button:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-breadcrumb__truncation-toggle.mock-focus.mock-active,.hds-breadcrumb__truncation-toggle:focus:active{box-shadow:none}.hds-breadcrumb__truncation-toggle.mock-active,.hds-breadcrumb__truncation-toggle:active{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong)}.hds-breadcrumb__truncation-content{position:absolute;top:100%;left:-4px;z-index:300;width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:200px;margin-top:4px;padding:6px 12px;background-color:var(--token-color-surface-primary);border-radius:6px;box-shadow:var(--token-surface-high-box-shadow)}.hds-button{position:relative;display:flex;align-items:center;justify-content:center;width:auto;text-decoration:none;border:1px solid transparent;border-radius:5px;isolation:isolate}.hds-disclosure,.hds-form-field--layout-vertical .hds-form-field__label,a.hds-button{width:-webkit-fit-content;width:-moz-fit-content}a.hds-button{width:fit-content}a.hds-button.mock-active,a.hds-button.mock-focus,a.hds-button.mock-hover,a.hds-button:active,a.hds-button:focus,a.hds-button:hover{text-decoration:underline}.hds-button.mock-disabled,.hds-button.mock-disabled:focus,.hds-button.mock-disabled:hover,.hds-button:disabled,.hds-button:disabled:focus,.hds-button:disabled:hover,.hds-button[disabled],.hds-button[disabled]:focus,.hds-button[disabled]:hover{color:var(--token-color-foreground-disabled);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-primary);box-shadow:none;cursor:not-allowed}.hds-button.mock-disabled::before,.hds-button.mock-disabled:focus::before,.hds-button.mock-disabled:hover::before,.hds-button:disabled::before,.hds-button:disabled:focus::before,.hds-button:disabled:hover::before,.hds-button[disabled]::before,.hds-button[disabled]:focus::before,.hds-button[disabled]:hover::before{border-color:transparent}.hds-button.hds-button--width-full{width:100%;max-width:100%}.hds-button.hds-button--width-full .hds-button__text{flex:0 0 auto}.hds-button__text,.hds-form-group--radio-cards .hds-form-radio-card--layout-fluid{flex:1 0 0}.hds-button.mock-focus,.hds-button:focus{box-shadow:none}.hds-button.mock-focus::before,.hds-button:focus::before{position:absolute;top:-4px;right:-4px;bottom:-4px;left:-4px;z-index:-1;border:3px solid transparent;border-radius:8px;content:""}.hds-button__icon+.hds-button__text,.hds-button__text+.hds-button__icon{margin-left:.375rem}.hds-button--size-small{min-height:1.75rem;padding:.375rem .6875rem}.hds-button--size-small .hds-button__icon{width:.75rem;height:.75rem}.hds-button--size-small .hds-button__text{font-size:.8125rem;line-height:.875rem}.hds-button--size-medium{min-height:2.25rem;padding:.5625rem .9375rem}.hds-button--size-medium .hds-button__icon{width:1rem;height:1rem}.hds-button--size-medium .hds-button__text{font-size:.875rem;line-height:1rem}.hds-button--size-large{min-height:3rem;padding:.6875rem 1.1875rem}.hds-button--size-large .hds-button__icon{width:1.5rem;height:1.5rem}.hds-button--size-large .hds-button__text{font-size:1rem;line-height:1.5rem}.hds-button--color-primary{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-blue-200);border-color:var(--token-color-palette-blue-300);box-shadow:var(--token-elevation-low-box-shadow)}.hds-button--color-primary.mock-hover,.hds-button--color-primary:hover{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-blue-300);border-color:var(--token-color-palette-blue-400);cursor:pointer}.hds-button--color-primary.mock-focus,.hds-button--color-primary:focus{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-blue-200);border-color:var(--token-color-focus-action-internal)}.hds-button--color-primary.mock-focus::before,.hds-button--color-primary:focus::before{top:-6px;right:-6px;bottom:-6px;left:-6px;border-color:var(--token-color-focus-action-external);border-radius:10px}.hds-button--color-primary.mock-active,.hds-button--color-primary:active{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-blue-400);border-color:var(--token-color-palette-blue-400);box-shadow:none}.hds-button--color-primary.mock-active::before,.hds-button--color-primary:active::before{border-color:transparent}.hds-button--color-secondary{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-strong);box-shadow:var(--token-elevation-low-box-shadow)}.hds-button--color-secondary.mock-hover,.hds-button--color-secondary:hover{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-primary);border-color:var(--token-color-border-strong);cursor:pointer}.hds-button--color-secondary.mock-focus,.hds-button--color-secondary:focus{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-faint);border-color:var(--token-color-focus-action-internal)}.hds-button--color-secondary.mock-focus::before,.hds-button--color-secondary:focus::before{border-color:var(--token-color-focus-action-external)}.hds-button--color-secondary.mock-active,.hds-button--color-secondary:active{color:var(--token-color-foreground-primary);background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong);box-shadow:none}.hds-button--color-secondary.mock-active::before,.hds-button--color-secondary:active::before{border-color:transparent}.hds-button--color-tertiary{color:var(--token-color-foreground-action);background-color:transparent;border-color:transparent}.hds-button--color-tertiary.mock-hover,.hds-button--color-tertiary:hover{color:var(--token-color-foreground-action-hover);background-color:var(--token-color-surface-primary);border-color:var(--token-color-border-strong);cursor:pointer}.hds-button--color-tertiary.mock-focus,.hds-button--color-tertiary:focus{color:var(--token-color-foreground-action);border-color:var(--token-color-focus-action-internal)}.hds-button--color-tertiary.mock-focus::before,.hds-button--color-tertiary:focus::before{border-color:var(--token-color-focus-action-external)}.hds-button--color-tertiary.mock-active,.hds-button--color-tertiary:active{color:var(--token-color-foreground-action-active);background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong);box-shadow:none}.hds-button--color-tertiary.mock-active::before,.hds-button--color-tertiary:active::before{border-color:transparent}.hds-button--color-tertiary.mock-disabled,.hds-button--color-tertiary.mock-disabled:focus,.hds-button--color-tertiary.mock-disabled:hover,.hds-button--color-tertiary:disabled,.hds-button--color-tertiary:disabled:focus,.hds-button--color-tertiary:disabled:hover,.hds-button--color-tertiary[disabled],.hds-button--color-tertiary[disabled]:focus,.hds-button--color-tertiary[disabled]:hover{background-color:transparent;border-color:transparent}.hds-button--color-tertiary.mock-disabled::before,.hds-button--color-tertiary.mock-disabled:focus::before,.hds-button--color-tertiary.mock-disabled:hover::before,.hds-button--color-tertiary:disabled::before,.hds-button--color-tertiary:disabled:focus::before,.hds-button--color-tertiary:disabled:hover::before,.hds-button--color-tertiary[disabled]::before,.hds-button--color-tertiary[disabled]:focus::before,.hds-button--color-tertiary[disabled]:hover::before{border-color:transparent}.hds-button--color-critical{color:var(--token-color-foreground-critical-on-surface);background-color:var(--token-color-surface-critical);border-color:var(--token-color-foreground-critical-on-surface);box-shadow:var(--token-elevation-low-box-shadow)}.hds-button--color-critical.mock-hover,.hds-button--color-critical:hover{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-red-300);border-color:var(--token-color-palette-red-400);cursor:pointer}.hds-button--color-critical.mock-focus,.hds-button--color-critical:focus{color:var(--token-color-foreground-critical-on-surface);background-color:var(--token-color-surface-critical);border-color:var(--token-color-focus-critical-internal)}.hds-button--color-critical.mock-focus::before,.hds-button--color-critical:focus::before{border-color:var(--token-color-focus-critical-external)}.hds-button--color-critical.mock-active,.hds-button--color-critical:active{color:var(--token-color-foreground-high-contrast);background-color:var(--token-color-palette-red-400);border-color:var(--token-color-palette-red-400);box-shadow:none}.hds-button--color-critical.mock-active::before,.hds-button--color-critical:active::before{border-color:transparent}button.hds-button[href]{color:#fff!important;background-color:red!important;border:none}button.hds-button[href]::after{content:' Attention: you’re passing a "href" attribute to the "Hds::Button" component, you should use an "@href" argument.'}.hds-button-set{display:flex}.hds-button-set>*+*{margin-left:16px}.hds-card__container{position:relative;background-color:#fff;border-radius:6px}.hds-card__container--level-surface-base{box-shadow:var(--token-surface-base-box-shadow)}.hds-card__container--level-surface-mid{box-shadow:var(--token-surface-mid-box-shadow)}.hds-card__container--level-surface-high{box-shadow:var(--token-surface-high-box-shadow)}.hds-card__container--hover-level-surface-base.mock-hover,.hds-card__container--hover-level-surface-base:hover{box-shadow:var(--token-surface-base-box-shadow)}.hds-card__container--hover-level-surface-mid.mock-hover,.hds-card__container--hover-level-surface-mid:hover{box-shadow:var(--token-surface-mid-box-shadow)}.hds-card__container--hover-level-surface-high.mock-hover,.hds-card__container--hover-level-surface-high:hover{box-shadow:var(--token-surface-high-box-shadow)}.hds-card__container--active-level-surface-base.mock-active,.hds-card__container--active-level-surface-base:active{box-shadow:var(--token-surface-base-box-shadow)}.hds-card__container--active-level-surface-mid.mock-active,.hds-card__container--active-level-surface-mid:active{box-shadow:var(--token-surface-mid-box-shadow)}.hds-card__container--active-level-surface-high.mock-active,.hds-card__container--active-level-surface-high:active{box-shadow:var(--token-surface-high-box-shadow)}.hds-card__container--level-elevation-base{box-shadow:var(--token-elevation-base-box-shadow)}.hds-card__container--level-elevation-mid{box-shadow:var(--token-elevation-mid-box-shadow)}.hds-card__container--level-elevation-high{box-shadow:var(--token-elevation-high-box-shadow)}.hds-card__container--hover-level-elevation-base.mock-hover,.hds-card__container--hover-level-elevation-base:hover{box-shadow:var(--token-elevation-base-box-shadow)}.hds-card__container--hover-level-elevation-mid.mock-hover,.hds-card__container--hover-level-elevation-mid:hover{box-shadow:var(--token-elevation-mid-box-shadow)}.hds-card__container--hover-level-elevation-high.mock-hover,.hds-card__container--hover-level-elevation-high:hover{box-shadow:var(--token-elevation-high-box-shadow)}.hds-card__container--active-level-elevation-base.mock-active,.hds-card__container--active-level-elevation-base:active{box-shadow:var(--token-elevation-base-box-shadow)}.hds-card__container--active-level-elevation-mid.mock-active,.hds-card__container--active-level-elevation-mid:active{box-shadow:var(--token-elevation-mid-box-shadow)}.hds-card__container--active-level-elevation-high.mock-active,.hds-card__container--active-level-elevation-high:active{box-shadow:var(--token-elevation-high-box-shadow)}.hds-card__container--background-neutral-primary{background-color:var(--token-color-surface-primary)}.hds-card__container--background-neutral-secondary{background-color:var(--token-color-surface-faint)}.hds-card__container--overflow-hidden{overflow:hidden}.hds-card__container--overflow-visible{overflow:visible}.hds-disclosure{position:relative;width:fit-content}.hds-dismiss-button{flex:none;padding:0;color:var(--token-color-foreground-faint);background-color:transparent;border:none;cursor:pointer;position:relative;isolation:isolate}.hds-dismiss-button.mock-hover::before,.hds-dismiss-button:hover::before{background-color:rgba(222,223,227,.4)}.hds-dismiss-button::before{position:absolute;top:-4px;right:-4px;bottom:-4px;left:-4px;z-index:-1;border-radius:5px;content:""}.hds-dismiss-button:focus:not(:focus-visible)::before{box-shadow:none}.hds-dismiss-button:focus-visible::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-dismiss-button.mock-focus.mock-active::before,.hds-dismiss-button:focus:active::before{box-shadow:none}.hds-dismiss-button.mock-active,.hds-dismiss-button:active{color:var(--token-color-foreground-secondary)}.hds-dismiss-button.mock-active::before,.hds-dismiss-button:active::before{background-color:rgba(222,223,227,.4);border:1px solid var(--token-color-border-strong)}.hds-dropdown-toggle-icon{display:flex;align-items:center;justify-content:center;min-width:36px;height:36px;padding:1px;background-color:transparent;border:1px solid transparent;border-radius:5px;position:relative;isolation:isolate}.hds-dropdown-toggle-icon.mock-hover,.hds-dropdown-toggle-icon:hover{background-color:var(--token-color-surface-interactive);border-color:var(--token-color-border-strong);cursor:pointer}.hds-dropdown-toggle-icon::before{position:absolute;top:-1px;right:-1px;bottom:-1px;left:-1px;z-index:-1;border-radius:5px;content:""}.hds-dropdown-toggle-icon.mock-focus::before,.hds-dropdown-toggle-icon:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-dropdown-toggle-icon:focus:not(:focus-visible)::before{box-shadow:none}.hds-dropdown-toggle-icon:focus-visible::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-dropdown-toggle-button,.hds-dropdown-toggle-icon.mock-focus.mock-active::before,.hds-dropdown-toggle-icon:focus:active::before{box-shadow:none}.hds-dropdown-toggle-icon.mock-active,.hds-dropdown-toggle-icon:active{background-color:var(--token-color-surface-interactive-active);border-color:var(--token-color-border-strong)}.hds-dropdown-toggle-icon__wrapper{display:flex;align-items:center;justify-content:center;width:32px;height:32px;padding:1px;border-radius:3px}.hds-dropdown-toggle-icon__wrapper img{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;border-radius:inherit}.hds-dropdown-toggle-icon__chevron{margin-left:4px}.hds-dropdown-toggle-icon--is-open .hds-dropdown-toggle-icon__chevron{transform:rotate(-180deg)}.hds-dropdown-toggle-button .hds-button__icon{margin-right:-6px;margin-left:8px}@media (prefers-reduced-motion:no-preference){.hds-dropdown-toggle-button .hds-button__icon,.hds-dropdown-toggle-icon__chevron{transition:transform .3s}}.hds-dropdown-toggle-button--is-open .hds-button__icon{transform:rotate(-180deg)}.hds-dropdown-list{width:-webkit-max-content;width:-moz-max-content;width:max-content;min-width:200px;max-width:400px;margin:0;padding:4px 0;list-style:none;background-color:var(--token-color-surface-primary);border-radius:6px;box-shadow:var(--token-surface-high-box-shadow)}.hds-dropdown-list--fixed-width{min-width:initial;max-width:initial}.hds-dropdown-list--position-right{position:absolute;top:calc(100% + 4px);right:0;z-index:2}.hds-dropdown-list--position-left{position:absolute;top:calc(100% + 4px);left:0;z-index:2}.hds-dropdown-list-item__copy-item-title{padding:2px 0 4px;color:var(--token-color-foreground-faint)}.hds-dropdown-list-item--copy-item{width:100%;padding:10px 16px 12px}.hds-dropdown-list-item--copy-item button{display:flex;justify-content:space-between;width:100%;padding:12px 8px;color:var(--token-color-foreground-primary);background-color:transparent;border:1px solid var(--token-color-border-primary);border-radius:5px}.hds-dropdown-list-item--copy-item button.mock-hover,.hds-dropdown-list-item--copy-item button:hover{background-color:var(--token-color-surface-interactive-hover);cursor:pointer}.hds-dropdown-list-item--copy-item button.mock-focus,.hds-dropdown-list-item--copy-item button:focus{box-shadow:var(--token-focus-ring-action-box-shadow);background-color:var(--token-color-surface-action);border-color:var(--token-color-focus-action-internal)}.hds-dropdown-list-item--copy-item button:focus:not(:focus-visible){box-shadow:none}.hds-dropdown-list-item--copy-item button:focus-visible{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-dropdown-list-item--copy-item button.mock-focus.mock-active,.hds-dropdown-list-item--copy-item button:focus:active{box-shadow:none}.hds-dropdown-list-item--copy-item button.mock-active,.hds-dropdown-list-item--copy-item button:active{background-color:var(--token-color-surface-interactive-active)}.hds-dropdown-list-item--copy-item button.is-success{background-color:var(--token-color-surface-success);border-color:var(--token-color-border-success)}.hds-dropdown-list-item--copy-item button.is-success .hds-dropdown-list-item__copy-item-icon{color:var(--token-color-foreground-success)}.hds-dropdown-list-item__copy-item-text{overflow:hidden;white-space:nowrap;text-align:left;text-overflow:ellipsis}.hds-dropdown-list-item__copy-item-icon{flex:none;margin-left:8px;color:var(--token-color-foreground-action)}.hds-dropdown-list-item--description{padding:2px 16px 4px;color:var(--token-color-foreground-faint)}.hds-dropdown-list-item--generic{padding-right:16px;padding-left:16px}.hds-dropdown-list-item--interactive{position:relative;min-height:36px;isolation:isolate}.hds-dropdown-list-item--interactive button{width:100%;background-color:transparent}.hds-dropdown-list-item--interactive button:hover{cursor:pointer}.hds-dropdown-list-item--interactive a,.hds-dropdown-list-item--interactive button{display:flex;align-items:center;padding:7px 9px 7px 15px;text-decoration:none;border:1px solid transparent}.hds-dropdown-list-item--interactive a::before,.hds-dropdown-list-item--interactive button::before{position:absolute;top:6px;bottom:6px;left:4px;z-index:-1;width:2px;border-radius:1px;content:""}.hds-dropdown-list-item--interactive a::after,.hds-dropdown-list-item--interactive button::after{position:absolute;top:0;right:4px;bottom:0;left:10px;z-index:-1;border-radius:5px;content:""}.hds-dropdown-list-item--interactive a.mock-hover,.hds-dropdown-list-item--interactive a:hover,.hds-dropdown-list-item--interactive button.mock-hover,.hds-dropdown-list-item--interactive button:hover{color:var(--current-color-hover)}.hds-dropdown-list-item--interactive a.mock-focus,.hds-dropdown-list-item--interactive a:focus,.hds-dropdown-list-item--interactive a:focus-visible,.hds-dropdown-list-item--interactive button.mock-focus,.hds-dropdown-list-item--interactive button:focus,.hds-dropdown-list-item--interactive button:focus-visible{color:var(--current-color-focus)}.hds-dropdown-list-item--interactive a.mock-hover::before,.hds-dropdown-list-item--interactive a:hover::before,.hds-dropdown-list-item--interactive button.mock-hover::before,.hds-dropdown-list-item--interactive button:hover::before{background-color:currentColor}.hds-dropdown-list-item--interactive a.mock-focus::after,.hds-dropdown-list-item--interactive a:focus::after,.hds-dropdown-list-item--interactive button.mock-focus::after,.hds-dropdown-list-item--interactive button:focus::after{left:4px;background-color:var(--current-background-color);box-shadow:var(--current-focus-ring-box-shadow)}.hds-dropdown-list-item--interactive a:focus:not(:focus-visible)::after,.hds-dropdown-list-item--interactive button:focus:not(:focus-visible)::after{background-color:transparent;box-shadow:none}.hds-dropdown-list-item--interactive a:focus-visible::after,.hds-dropdown-list-item--interactive button:focus-visible::after{left:4px;background-color:var(--current-background-color);box-shadow:var(--current-focus-ring-box-shadow)}.hds-dropdown-list-item--interactive a.mock-focus.mock-active::after,.hds-dropdown-list-item--interactive a:focus-visible:active::after,.hds-dropdown-list-item--interactive a:focus:active::after,.hds-dropdown-list-item--interactive button.mock-focus.mock-active::after,.hds-dropdown-list-item--interactive button:focus-visible:active::after,.hds-dropdown-list-item--interactive button:focus:active::after{left:10px;background-color:var(--current-background-color);box-shadow:none}.hds-dropdown-list-item--interactive a.mock-active,.hds-dropdown-list-item--interactive a:active,.hds-dropdown-list-item--interactive button.mock-active,.hds-dropdown-list-item--interactive button:active{color:var(--current-color-active)}.hds-dropdown-list-item--interactive a.mock-active::before,.hds-dropdown-list-item--interactive a:active::before,.hds-dropdown-list-item--interactive button.mock-active::before,.hds-dropdown-list-item--interactive button:active::before{background-color:currentColor}.hds-dropdown-list-item--interactive a.mock-active::after,.hds-dropdown-list-item--interactive a:active::after,.hds-dropdown-list-item--interactive button.mock-active::after,.hds-dropdown-list-item--interactive button:active::after{background-color:var(--current-background-color)}.hds-dropdown-list-item__interactive-icon{margin-right:8px}.hds-dropdown-list-item__interactive-text{text-align:left}.hds-dropdown-list-item--color-action a,.hds-dropdown-list-item--color-action button{color:var(--token-color-foreground-primary);--current-color-hover:var(--token-color-foreground-action-hover);--current-color-focus:var(--token-color-foreground-action-active);--current-color-active:var(--token-color-foreground-action-active)}.hds-dropdown-list-item--color-action a::after,.hds-dropdown-list-item--color-action button::after{--current-background-color:var(--token-color-surface-action);--current-focus-ring-box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-dropdown-list-item--color-critical a,.hds-dropdown-list-item--color-critical button{color:var(--token-color-foreground-critical);--current-color-hover:var(--token-color-palette-red-300);--current-color-focus:var(--token-color-palette-red-400);--current-color-active:var(--token-color-palette-red-400)}.hds-dropdown-list-item--color-critical a::after,.hds-dropdown-list-item--color-critical button::after{--current-background-color:var(--token-color-surface-critical);--current-focus-ring-box-shadow:var(--token-focus-ring-critical-box-shadow)}.hds-dropdown-list-item__interactive-loading-wrapper{display:flex;align-items:center;padding:8px 10px 8px 16px}.hds-dropdown-list-item__interactive-loading-wrapper .hds-dropdown-list-item__interactive-text{color:var(--token-color-foreground-faint)}.hds-dropdown-list-item__interactive-loading-wrapper .hds-dropdown-list-item__interactive-icon{color:var(--token-color-foreground-primary)}.hds-dropdown-list-item--separator{position:relative;width:100%;height:4px}.hds-dropdown-list-item--separator::before{position:absolute;right:6px;bottom:0;left:6px;border-bottom:1px solid var(--token-color-border-primary);content:""}.hds-dropdown-list-item--title{padding:10px 16px 4px;color:var(--token-color-foreground-strong)}.hds-empty-state{display:block;max-width:40ch;margin:0 auto;padding:0;color:var(--token-color-foreground-faint)}.hds-empty-state>*{margin:0;padding:0}.hds-empty-state__body{font-weight:400;font-size:1rem;line-height:1.5}.hds-empty-state__body+*{-webkit-margin-before:1rem;margin-block-start:1rem}.hds-empty-state__header{font-weight:700;font-size:1.25rem;line-height:1.2}.hds-flyout{z-index:49;flex-direction:column;height:100vh;max-height:100vh;margin:0;padding:0;background:var(--token-color-surface-primary);border:none;box-shadow:0 2px 3px 0 rgba(59,61,69,.2509803922),0 12px 24px 0 rgba(59,61,69,.3490196078)}.hds-flyout[open]{position:fixed;display:flex}.hds-flyout::-webkit-backdrop{display:none}.hds-flyout::backdrop{display:none}.hds-flyout__overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;background:var(--token-color-palette-neutral-700);opacity:.5}.hds-flyout__header{display:flex;flex:none;align-items:flex-start;padding:16px 24px;color:var(--token-color-foreground-strong)}.hds-flyout__icon{flex:none;align-self:center;margin-right:16px}.hds-flyout__title{flex-grow:1}.hds-flyout__tagline{margin-bottom:4px;color:var(--token-color-foreground-faint)}.hds-flyout__dismiss{align-self:center;margin-left:16px}.hds-flyout__description{padding:0 24px 16px;color:var(--token-color-foreground-primary)}.hds-flyout__body{flex:1 1 auto;padding:24px;overflow-y:auto;overscroll-behavior:contain;border-top:1px solid var(--token-color-border-primary)}.hds-flyout--size-medium{width:min(480px,100vw - 40px);max-width:calc(100vw - 40px)}.hds-flyout--size-medium[open]{margin-left:calc(100% - min(480px,100vw - 40px))}.hds-flyout--size-large{width:min(720px,100vw - 40px);max-width:calc(100vw - 40px)}.hds-flyout--size-large[open]{margin-left:calc(100% - min(720px,100vw - 40px))}.hds-form-label{display:block;width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:100%;color:var(--token-form-label-color)}.hds-form-label .hds-badge{vertical-align:initial}.hds-form-helper-text{display:block;color:var(--token-form-helper-text-color)}.hds-form-error{display:flex;align-items:flex-start;color:var(--token-form-error-color)}.hds-form-error__icon{flex:none;width:var(--token-form-error-icon-size);height:var(--token-form-error-icon-size);margin:2px 8px 2px 0}.hds-form-error__content{flex:1 1 auto}.hds-form-error__message{margin:0}.hds-form-field--layout-vertical{display:grid;justify-items:start;width:100%}.hds-form-field--layout-vertical .hds-form-field__label{width:fit-content}.hds-form-field--layout-vertical .hds-form-field__helper-text:not(:first-child){margin-top:4px}.hds-form-field--layout-vertical .hds-form-field__helper-text+.hds-form-helper-text{margin-top:2px}.hds-form-field--layout-vertical .hds-form-field__control:not(:first-child){margin-top:8px}.hds-form-field--layout-vertical .hds-form-field__control:not(:last-child){margin-bottom:8px}.hds-form-field--layout-flag{display:grid;grid-auto-flow:row;grid-template-areas:"control label" "control helper-text" "control error";grid-template-rows:auto auto auto;grid-template-columns:auto 1fr;justify-items:start}.hds-form-field--layout-flag .hds-form-field__label{grid-area:label;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.hds-form-field--layout-flag .hds-form-field__helper-text{grid-area:helper-text;margin-top:4px}.hds-form-field--layout-flag .hds-form-field__control{grid-area:control}.hds-form-field--layout-flag .hds-form-field__control:not(:only-child){margin-top:2px;margin-right:8px}.hds-form-field--layout-flag .hds-form-field__error{grid-area:error;margin-top:4px}.hds-form-legend{display:block;color:var(--token-form-legend-color)}.hds-form-legend .hds-badge{vertical-align:initial}.hds-form-group{display:block;margin:0;padding:0;border:none}.hds-form-checkbox,.hds-form-radio{padding:0;background-position:center center;border-style:solid}.hds-form-group__legend{margin:0 0 4px;padding:0}.hds-form-group__legend~.hds-form-group__control-fields-wrapper .hds-form-label{font-weight:var(--token-typography-font-weight-regular)}.hds-form-group--layout-vertical .hds-form-group__control-field+.hds-form-group__control-field{margin-top:12px}.hds-form-group--layout-horizontal .hds-form-group__control-fields-wrapper{display:flex;flex-wrap:wrap;margin-bottom:-4px}.hds-form-group--layout-horizontal .hds-form-group__control-field{margin-right:16px;margin-bottom:4px}.hds-form-group__helper-text{margin-bottom:8px}.hds-form-group__error{margin-top:8px}.hds-form-indicator--optional{color:var(--token-form-indicator-optional-color)}.hds-form-checkbox{width:var(--token-form-checkbox-size);height:var(--token-form-checkbox-size);margin:0;background-size:var(--token-form-checkbox-background-image-size) var(--token-form-checkbox-background-image-size);border-width:var(--token-form-checkbox-border-width);border-radius:var(--token-form-checkbox-border-radius);cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none}.hds-form-radio,.hds-form-select{-webkit-appearance:none;-moz-appearance:none}.hds-form-checkbox:not(:checked,:indeterminate){background-color:var(--token-form-control-base-surface-color-default);border-color:var(--token-form-control-base-border-color-default);box-shadow:var(--hds-elevation-inset-box-shadow)}.hds-form-checkbox:checked,.hds-form-checkbox:indeterminate{background-color:var(--token-form-control-checked-surface-color-default);border-color:var(--token-form-control-checked-border-color-default)}.hds-form-checkbox:checked{background-image:var(--token-form-checkbox-background-image-data-url)}.hds-form-checkbox:indeterminate{background-image:var(--token-form-checkbox-background-image-data-url-indeterminate)}.hds-form-checkbox.mock-hover:not(:checked,:indeterminate),.hds-form-checkbox:hover:not(:checked,:indeterminate){background-color:var(--token-form-control-base-surface-color-hover);border-color:var(--token-form-control-base-border-color-hover)}.hds-form-checkbox.mock-hover:checked,.hds-form-checkbox.mock-hover:indeterminate,.hds-form-checkbox:hover:checked,.hds-form-checkbox:hover:indeterminate{background-color:var(--token-form-control-checked-border-color-default);border-color:var(--token-form-control-checked-border-color-hover)}.hds-form-checkbox:disabled:checked,.hds-form-checkbox:disabled:indeterminate,.hds-form-checkbox:disabled:not(:checked,:indeterminate){background-color:var(--token-form-control-disabled-surface-color);border-color:var(--token-form-control-disabled-border-color);box-shadow:none;cursor:not-allowed}.hds-form-checkbox.mock-focus,.hds-form-checkbox:focus{outline:var(--token-color-focus-action-external) solid 3px;outline-offset:1px}.hds-form-checkbox:disabled:checked{background-image:var(--token-form-checkbox-background-image-data-url-disabled)}.hds-form-checkbox:disabled:indeterminate{background-image:var(--token-form-checkbox-background-image-data-url-indeterminate-disabled);background-repeat:no-repeat}.hds-form-radio{width:var(--token-form-radio-size);height:var(--token-form-radio-size);margin:0;background-size:var(--token-form-radio-background-image-size) var(--token-form-radio-background-image-size);border-width:var(--token-form-radio-border-width);border-radius:50%;cursor:pointer;appearance:none}.hds-form-radio:not(:checked){background-color:var(--token-form-control-base-surface-color-default);border-color:var(--token-form-control-base-border-color-default);box-shadow:var(--hds-elevation-inset-box-shadow)}.hds-form-radio:checked{background-color:var(--token-form-control-checked-surface-color-default);background-image:var(--token-form-radio-background-image-data-url);border-color:var(--token-form-control-checked-border-color-default)}.hds-form-radio.mock-hover:not(:checked),.hds-form-radio:hover:not(:checked){background-color:var(--token-form-control-base-surface-color-hover);border-color:var(--token-form-control-base-border-color-hover)}.hds-form-radio.mock-hover:checked,.hds-form-radio:hover:checked{background-color:var(--token-form-control-checked-border-color-default);border-color:var(--token-form-control-checked-border-color-hover)}.hds-form-radio:disabled:checked,.hds-form-radio:disabled:not(:checked){background-color:var(--token-form-control-disabled-surface-color);border-color:var(--token-form-control-disabled-border-color);box-shadow:none;cursor:not-allowed}.hds-form-radio.mock-focus,.hds-form-radio:focus{outline:var(--token-color-focus-action-external) solid 3px;outline-offset:1px}.hds-form-radio:disabled:checked{background-image:var(--token-form-radio-background-image-data-url-disabled)}.hds-form-group--radio-cards .hds-form-group__control-fields-wrapper{margin:calc(-1 * var(--token-form-radiocard-group-gap)/ 2)}.hds-form-group--radio-cards .hds-form-group__legend{margin-bottom:12px}.hds-form-group--radio-cards .hds-form-radio-card{margin:calc(var(--token-form-radiocard-group-gap)/ 2)}.hds-form-group--radio-cards .hds-form-radio-card--layout-fixed{flex:1 0 100%}.hds-form-radio-card{display:flex;flex-direction:column;background-color:var(--token-color-surface-primary);border:var(--token-form-radiocard-border-width) solid var(--token-color-border-primary);border-radius:var(--token-form-radiocard-border-radius);box-shadow:var(--token-elevation-mid-box-shadow);cursor:pointer}.hds-form-radio-card .hds-form-radio-card__control{outline-color:transparent}.hds-form-radio-card.mock-hover,.hds-form-radio-card:hover{box-shadow:var(--token-elevation-high-box-shadow);transition:var(--token-form-radiocard-transition-duration)}.hds-form-radio-card.mock-focus,.hds-form-radio-card:focus-within{border-color:var(--token-color-focus-action-internal);box-shadow:0 0 0 3px var(--token-color-focus-action-external)}.hds-form-radio-card--checked,.hds-form-radio-card.mock-checked{border-color:var(--token-color-focus-action-internal)}.hds-form-radio-card--checked .hds-form-radio-card__control-wrapper,.hds-form-radio-card.mock-checked .hds-form-radio-card__control-wrapper{background-color:var(--token-color-surface-action);border-color:var(--token-color-border-action)}.hds-form-radio-card--disabled,.hds-form-radio-card--disabled .hds-form-radio-card__control-wrapper,.hds-form-radio-card.mock-disabled,.hds-form-radio-card.mock-disabled .hds-form-radio-card__control-wrapper{background-color:var(--token-color-surface-interactive-disabled);border-color:var(--token-color-border-primary)}.hds-form-radio-card--disabled,.hds-form-radio-card.mock-disabled{box-shadow:none;cursor:not-allowed}.hds-form-radio-card--align-left{text-align:left}.hds-form-radio-card--align-center{text-align:center}.hds-form-radio-card--align-center .flight-icon{margin:auto}.hds-form-radio-card--control-bottom .hds-form-radio-card__control-wrapper{border-top-width:var(--token-form-radiocard-border-width);border-top-style:solid;border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.hds-form-radio-card--control-left{flex-direction:row-reverse}.hds-form-radio-card--control-left .hds-form-radio-card__control-wrapper{display:flex;align-items:center;border-right-width:var(--token-form-radiocard-border-width);border-right-style:solid;border-top-left-radius:inherit;border-bottom-left-radius:inherit}.hds-form-radio-card__content{flex:1;padding:var(--token-form-radiocard-content-padding)}.hds-form-radio-card__content .hds-badge{margin-bottom:12px}.hds-form-radio-card__label{display:block;margin:8px 0;color:var(--token-form-label-color)}.hds-form-radio-card__label:first-child{margin-top:0}.hds-form-radio-card__description{display:block;color:var(--token-color-foreground-primary)}.hds-form-radio-card__control-wrapper{padding:var(--token-form-radiocard-control-padding);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-primary)}.hds-form-radio-card__control{display:block;margin:auto}.hds-form-select{max-width:100%;padding:var(--token-form-control-padding);padding-right:calc(var(--token-form-control-padding) + 24px);color:var(--token-form-control-base-foreground-value-color);background-color:var(--token-form-control-base-surface-color-default);background-image:var(--token-form-select-background-image-data-url);background-repeat:no-repeat;background-position:right var(--token-form-select-background-image-position-right-x) top var(--token-form-select-background-image-position-top-y);background-size:var(--token-form-select-background-image-size) var(--token-form-select-background-image-size);border:var(--token-form-control-border-width) solid var(--token-form-control-base-border-color-default);border-radius:var(--token-form-control-border-radius);box-shadow:var(--token-elevation-low-box-shadow);appearance:none}.hds-form-select.mock-hover,.hds-form-select:hover{border-color:var(--token-form-control-base-border-color-hover)}.hds-form-select.mock-focus,.hds-form-select:focus{border-color:var(--token-color-focus-action-internal);outline:var(--token-color-focus-action-external) solid 3px;outline-offset:0}.hds-form-select:disabled{color:var(--token-form-control-disabled-foreground-color);background-color:var(--token-form-control-disabled-surface-color);background-image:var(--token-form-select-background-image-data-url-disabled);border-color:var(--token-form-control-disabled-border-color);box-shadow:none;cursor:not-allowed}.hds-form-select.hds-form-select--is-invalid{border-color:var(--token-form-control-invalid-border-color-default)}.hds-form-select.hds-form-select--is-invalid.mock-hover,.hds-form-select.hds-form-select--is-invalid:hover{border-color:var(--token-form-control-invalid-border-color-hover)}.hds-form-select.hds-form-select--is-invalid.mock-focus,.hds-form-select.hds-form-select--is-invalid:focus{border-color:var(--token-color-focus-critical-internal);outline-color:var(--token-color-focus-critical-external)}.hds-form-select[multiple],.hds-form-select[size]{background:0 0}.hds-form-select[multiple] option,.hds-form-select[size] option{margin:2px auto;border-radius:3px}.hds-form-select[multiple] option:hover,.hds-form-select[size] option:hover{color:var(--token-color-foreground-action)}.hds-form-select[multiple] option:disabled,.hds-form-select[size] option:disabled{color:var(--token-color-foreground-disabled)}.hds-form-select[multiple] option:checked,.hds-form-select[size] option:checked{color:var(--token-color-foreground-high-contrast);background:var(--token-color-palette-blue-200)}.hds-form-text-input,.hds-form-textarea{max-width:100%;background-color:var(--token-form-control-base-surface-color-default)}.hds-form-select[multiple] optgroup,.hds-form-select[size] optgroup{color:var(--token-color-foreground-strong);font-weight:var(--token-typography-font-weight-semibold);font-style:normal}.hds-form-text-input{width:100%;padding:var(--token-form-control-padding);color:var(--token-form-control-base-foreground-value-color);border:var(--token-form-control-border-width) solid var(--token-form-control-base-border-color-default);border-radius:var(--token-form-control-border-radius);box-shadow:var(--hds-elevation-inset-box-shadow)}.hds-form-text-input ::-moz-placeholder{color:var(--token-form-control-base-foreground-placeholder-color)}.hds-form-text-input ::placeholder{color:var(--token-form-control-base-foreground-placeholder-color)}.hds-form-text-input.mock-hover,.hds-form-text-input:hover{border-color:var(--token-form-control-base-border-color-hover)}.hds-form-text-input.mock-focus,.hds-form-text-input:focus{border-color:var(--token-color-focus-action-internal);outline:var(--token-color-focus-action-external) solid 3px;outline-offset:0}.hds-form-text-input:-moz-read-only{color:var(--token-form-control-readonly-foreground-color);background-color:var(--token-form-control-readonly-surface-color);border-color:var(--token-form-control-readonly-border-color);box-shadow:none}.hds-form-text-input:read-only{color:var(--token-form-control-readonly-foreground-color);background-color:var(--token-form-control-readonly-surface-color);border-color:var(--token-form-control-readonly-border-color);box-shadow:none}.hds-form-text-input:disabled{color:var(--token-form-control-disabled-foreground-color);background-color:var(--token-form-control-disabled-surface-color);border-color:var(--token-form-control-disabled-border-color);box-shadow:none;cursor:not-allowed}.hds-form-text-input.hds-form-text-input--is-invalid{border-color:var(--token-form-control-invalid-border-color-default)}.hds-form-text-input.hds-form-text-input--is-invalid.mock-hover,.hds-form-text-input.hds-form-text-input--is-invalid:hover{border-color:var(--token-form-control-invalid-border-color-hover)}.hds-form-text-input.hds-form-text-input--is-invalid.mock-focus,.hds-form-text-input.hds-form-text-input--is-invalid:focus{border-color:var(--token-color-focus-critical-internal);outline-color:var(--token-color-focus-critical-external)}.hds-form-text-input[type=date],.hds-form-text-input[type=time]{width:initial}.hds-form-text-input[type=date]:disabled::-webkit-calendar-picker-indicator,.hds-form-text-input[type=time]:disabled::-webkit-calendar-picker-indicator{visibility:visible;opacity:.5}.hds-form-text-input[type=date][readonly]::-webkit-calendar-picker-indicator,.hds-form-text-input[type=time][readonly]::-webkit-calendar-picker-indicator{visibility:visible}.hds-form-text-input[type=date]::-webkit-calendar-picker-indicator{background-image:var(--token-form-text-input-background-image-data-url-date);background-position:center center;background-size:var(--token-form-text-input-background-image-size)}.hds-form-text-input[type=time]::-webkit-calendar-picker-indicator{background-image:var(--token-form-text-input-background-image-data-url-time);background-position:center center;background-size:var(--token-form-text-input-background-image-size)}.hds-form-text-input[type=search]{padding-left:calc(var(--token-form-control-padding) + 24px);background-image:var(--token-form-text-input-background-image-data-url-search);background-repeat:no-repeat;background-position:var(--token-form-text-input-background-image-position-x) 50%;background-size:var(--token-form-text-input-background-image-size)}.hds-form-text-input[type=search]::-webkit-search-cancel-button{width:var(--token-form-text-input-background-image-size);height:var(--token-form-text-input-background-image-size);background-image:var(--token-form-text-input-background-image-data-url-search-cancel);background-position:center center;background-size:var(--token-form-text-input-background-image-size);-webkit-appearance:none}.hds-form-textarea{width:100%;padding:var(--token-form-control-padding);color:var(--token-form-control-base-foreground-value-color);border:var(--token-form-control-border-width) solid var(--token-form-control-base-border-color-default);border-radius:var(--token-form-control-border-radius);box-shadow:var(--hds-elevation-inset-box-shadow);resize:vertical}.hds-form-textarea ::-moz-placeholder{color:var(--token-form-control-base-foreground-placeholder-color)}.hds-form-textarea ::placeholder{color:var(--token-form-control-base-foreground-placeholder-color)}.hds-form-textarea.mock-hover,.hds-form-textarea:hover{border-color:var(--token-form-control-base-border-color-hover)}.hds-form-textarea.mock-focus,.hds-form-textarea:focus{border-color:var(--token-color-focus-action-internal);outline:var(--token-color-focus-action-external) solid 3px;outline-offset:0}.hds-form-textarea:-moz-read-only{color:var(--token-form-control-disabled-foreground-color);background-color:var(--token-form-control-readonly-surface-color);border-color:var(--token-form-control-disabled-border-color);box-shadow:none}.hds-form-textarea:read-only{color:var(--token-form-control-disabled-foreground-color);background-color:var(--token-form-control-readonly-surface-color);border-color:var(--token-form-control-disabled-border-color);box-shadow:none}.hds-form-textarea:disabled{color:var(--token-form-control-disabled-foreground-color);background-color:var(--token-form-control-disabled-surface-color);border-color:var(--token-form-control-disabled-border-color);box-shadow:none;cursor:not-allowed}.hds-form-textarea.hds-form-textarea--is-invalid{border-color:var(--token-form-control-invalid-border-color-default)}.hds-form-textarea.hds-form-textarea--is-invalid.mock-hover,.hds-form-textarea.hds-form-textarea--is-invalid:hover{border-color:var(--token-form-control-invalid-border-color-hover)}.hds-form-textarea.hds-form-textarea--is-invalid.mock-focus,.hds-form-textarea.hds-form-textarea--is-invalid:focus{border-color:var(--token-color-focus-critical-internal);outline-color:var(--token-color-focus-critical-external)}.hds-form-toggle{position:relative;isolation:isolate}.hds-form-toggle__control{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;display:block;height:100%;margin:0;padding:0;color:transparent;background-color:transparent;border:none;outline:0;cursor:pointer;opacity:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.hds-form-toggle__control:disabled{cursor:not-allowed}.hds-form-toggle__facade{position:relative;display:block;width:var(--token-form-toggle-width);height:var(--token-form-toggle-height);background-image:var(--token-form-toggle-background-image-data-url);background-repeat:no-repeat;background-position:var(--token-form-toggle-background-image-position-x) 50%;background-size:var(--token-form-toggle-background-image-size) var(--token-form-toggle-background-image-size);border:var(--token-form-radio-border-width) solid var(--border-color);border-radius:calc(var(--token-form-toggle-height)/ 2)}.hds-form-toggle__facade::after{position:absolute;top:calc(var(--token-form-radio-border-width) * -1);left:calc(var(--token-form-radio-border-width) * -1);width:var(--token-form-toggle-thumb-size);height:var(--token-form-toggle-thumb-size);background-color:var(--token-form-control-base-surface-color-default);border:var(--token-form-radio-border-width) solid var(--border-color);border-radius:50%;transform:translate3d(0,0,0);content:""}@media (prefers-reduced-motion:no-preference){.hds-form-toggle__facade,.hds-form-toggle__facade::after{transition-timing-function:var(--token-form-toggle-transition-timing-function);transition-duration:var(--token-form-toggle-transition-duration);transition-property:all}}.hds-form-toggle__facade::before{position:absolute;top:-5px;right:-5px;bottom:-5px;left:-5px;margin:auto;border-width:3px;border-radius:calc(var(--token-form-toggle-height)/ 2 + 3px + 1px);content:""}:not(:checked)+.hds-form-toggle__facade{--border-color:var(--token-form-control-base-border-color-default);background-color:var(--token-form-toggle-base-surface-color-default)}:checked+.hds-form-toggle__facade{--border-color:var(--token-form-control-checked-border-color-default);background-color:var(--token-form-control-checked-surface-color-default)}:checked+.hds-form-toggle__facade::after{transform:translate3d(calc(var(--token-form-toggle-width) - var(--token-form-toggle-thumb-size)),0,0)}.mock-hover:not(:checked)+.hds-form-toggle__facade,:hover:not(:checked)+.hds-form-toggle__facade{--border-color:var(--token-form-control-base-border-color-hover)}.mock-hover:checked+.hds-form-toggle__facade,:hover:checked+.hds-form-toggle__facade{--border-color:var(--token-form-control-checked-border-color-hover);background-color:var(--token-form-control-checked-border-color-default)}.mock-focus+.hds-form-toggle__facade::before,:focus+.hds-form-toggle__facade::before{border-color:var(--token-color-focus-action-external);border-style:solid}:disabled:checked+.hds-form-toggle__facade,:disabled:not(:checked)+.hds-form-toggle__facade{--border-color:var(--token-form-control-disabled-border-color);background-color:var(--token-form-control-disabled-surface-color);background-image:var(--token-form-toggle-background-image-data-url-disabled)}.hds-icon-tile--logo,.hds-icon-tile__extra{background-color:var(--token-color-surface-primary)}.hds-icon-tile{position:relative;display:flex;border:1px solid transparent;border-radius:4px;box-shadow:0 1px 1px rgba(101,106,118,.05)}.hds-icon-tile__icon,.hds-icon-tile__logo{display:flex;margin:auto}.hds-icon-tile__extra{position:absolute;right:-6px;bottom:-6px;display:flex;box-sizing:content-box;border:1px solid var(--token-color-border-primary);box-shadow:0 1px 1px rgba(101,106,118,.05)}.hds-icon-tile__extra-icon{display:flex;margin:auto;color:var(--token-color-foreground-strong)}.hds-icon-tile--size-small{width:1.75rem;height:1.75rem;border-radius:5px}.hds-icon-tile--size-small .hds-icon-tile__icon{width:1rem;height:1rem}.hds-icon-tile--size-small .hds-icon-tile__logo{width:1.125rem;height:1.125rem}.hds-icon-tile--size-small .hds-icon-tile__extra{width:1.125rem;height:1.125rem;border-radius:4px}.hds-icon-tile--size-small .hds-icon-tile__extra-icon{width:.75rem;height:.75rem}.hds-icon-tile--size-medium{width:2.5rem;height:2.5rem;border-radius:6px}.hds-icon-tile--size-medium .hds-icon-tile__icon{width:1.5rem;height:1.5rem}.hds-icon-tile--size-medium .hds-icon-tile__logo{width:1.75rem;height:1.75rem}.hds-icon-tile--size-medium .hds-icon-tile__extra{width:1.5rem;height:1.5rem;border-radius:5px}.hds-icon-tile--size-medium .hds-icon-tile__extra-icon{width:1rem;height:1rem}.hds-icon-tile--size-large{width:3rem;height:3rem;border-radius:6px}.hds-icon-tile--size-large .hds-icon-tile__icon{width:1.5rem;height:1.5rem}.hds-icon-tile--size-large .hds-icon-tile__logo{width:2rem;height:2rem}.hds-icon-tile--size-large .hds-icon-tile__extra{width:1.5rem;height:1.5rem;border-radius:5px}.hds-icon-tile--size-large .hds-icon-tile__extra-icon{width:1rem;height:1rem}.hds-icon-tile--logo{border-color:var(--token-color-border-primary)}.hds-icon-tile--icon.hds-icon-tile--color-neutral{color:var(--token-color-foreground-faint);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-primary)}.hds-icon-tile--icon.hds-icon-tile--color-boundary{color:var(--token-color-boundary-foreground);background:linear-gradient(135deg,var(--token-color-boundary-gradient-faint-start) 0,var(--token-color-boundary-gradient-faint-stop) 100%);border-color:var(--token-color-boundary-border)}.hds-icon-tile--icon.hds-icon-tile--color-consul{color:var(--token-color-consul-foreground);background:linear-gradient(135deg,var(--token-color-consul-gradient-faint-start) 0,var(--token-color-consul-gradient-faint-stop) 100%);border-color:var(--token-color-consul-border)}.hds-icon-tile--icon.hds-icon-tile--color-hcp{color:var(--token-color-palette-hcp-brand);background-color:var(--token-color-surface-faint);border-color:var(--token-color-border-primary)}.hds-icon-tile--icon.hds-icon-tile--color-nomad{color:var(--token-color-nomad-foreground);background:linear-gradient(135deg,var(--token-color-nomad-gradient-faint-start) 0,var(--token-color-nomad-gradient-faint-stop) 100%);border-color:var(--token-color-nomad-border)}.hds-icon-tile--icon.hds-icon-tile--color-packer{color:var(--token-color-packer-foreground);background:linear-gradient(135deg,var(--token-color-packer-gradient-faint-start) 0,var(--token-color-packer-gradient-faint-stop) 100%);border-color:var(--token-color-packer-border)}.hds-icon-tile--icon.hds-icon-tile--color-terraform{color:var(--token-color-terraform-foreground);background:linear-gradient(135deg,var(--token-color-terraform-gradient-faint-start) 0,var(--token-color-terraform-gradient-faint-stop) 100%);border-color:var(--token-color-terraform-border)}.hds-icon-tile--icon.hds-icon-tile--color-vagrant{color:var(--token-color-vagrant-foreground);background:linear-gradient(135deg,var(--token-color-vagrant-gradient-faint-start) 0,var(--token-color-vagrant-gradient-faint-stop) 100%);border-color:var(--token-color-vagrant-border)}.hds-icon-tile--icon.hds-icon-tile--color-vault{color:var(--token-color-vault-foreground);background:linear-gradient(135deg,var(--token-color-vault-gradient-faint-start) 0,var(--token-color-vault-gradient-faint-stop) 100%);border-color:var(--token-color-vault-border)}.hds-icon-tile--icon.hds-icon-tile--color-waypoint{color:var(--token-color-waypoint-foreground);background:linear-gradient(135deg,var(--token-color-waypoint-gradient-faint-start) 0,var(--token-color-waypoint-gradient-faint-stop) 100%);border-color:var(--token-color-waypoint-border)}.hds-link-inline--color-primary,.hds-link-standalone--color-primary{color:var(--token-color-foreground-action)}.hds-link-inline{border-radius:2px}.hds-link-inline.mock-focus,.hds-link-inline:focus,.hds-link-inline:focus-visible{text-decoration:none;outline:var(--token-color-focus-action-internal) solid 2px;outline-offset:1px}.hds-link-standalone,.hds-pagination-nav__control,.hds-table__th-sort button,.hds-tabs__tab-button{outline-style:solid;outline-color:transparent}.hds-link-inline__icon{display:inline-block;width:1em;height:1em;vertical-align:text-bottom}.hds-link-inline--icon-leading>.hds-link-inline__icon{margin-right:.25em}.hds-link-inline--icon-trailing>.hds-link-inline__icon{margin-left:.25em}.hds-link-inline--color-primary.mock-hover,.hds-link-inline--color-primary:hover{color:var(--token-color-foreground-action-hover)}.hds-link-inline--color-primary.mock-active,.hds-link-inline--color-primary:active{color:var(--token-color-foreground-action-active)}.hds-link-inline--color-secondary{color:var(--token-color-foreground-strong)}.hds-link-inline--color-secondary.mock-hover,.hds-link-inline--color-secondary:hover{color:var(--token-color-foreground-primary)}.hds-link-inline--color-secondary.mock-active,.hds-link-inline--color-secondary:active{color:var(--token-color-foreground-faint)}.hds-link-standalone{display:flex;align-items:center;justify-content:center;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;background-color:transparent;border:1px solid transparent;position:relative;isolation:isolate}.hds-link-standalone--size-medium .hds-link-standalone__icon,.hds-link-standalone--size-small .hds-link-standalone__icon{width:1rem;height:1rem}.hds-link-standalone__text{flex:1 0 0;text-decoration:underline;transition:-webkit-text-decoration-color .25s ease-in;transition:text-decoration-color .25s ease-in;transition:text-decoration-color .25s ease-in,-webkit-text-decoration-color .25s ease-in}#login-toggle+div footer button,.consul-intention-fieldsets .permissions>button,.empty-state>ul>li>*,.empty-state>ul>li>:active,.empty-state>ul>li>label>button,.empty-state>ul>li>label>button:active,.hds-pagination-nav__control,.hds-tabs__tab,.modal-dialog [role=document] dd a,.modal-dialog [role=document] p a,.oidc-select button.reset,.search-bar-status .remove-all button,a,main dd a,main dd a:active,main p a,main p a:active{text-decoration:none}.hds-link-standalone__icon+.hds-link-standalone__text,.hds-link-standalone__text+.hds-link-standalone__icon{margin-left:.375rem}.hds-link-standalone--size-small .hds-link-standalone__text{font-size:.8125rem;line-height:1.231}.hds-link-standalone--size-medium .hds-link-standalone__text{font-size:.875rem;line-height:1.143}.hds-link-standalone--size-large .hds-link-standalone__icon{width:1.5rem;height:1.5rem}.hds-link-standalone--size-large .hds-link-standalone__text{font-size:1rem;line-height:1.5}.hds-link-standalone--color-primary.mock-hover,.hds-link-standalone--color-primary:hover{color:var(--token-color-foreground-action-hover)}.hds-link-standalone--color-primary.mock-hover .hds-link-standalone__text,.hds-link-standalone--color-primary:hover .hds-link-standalone__text{-webkit-text-decoration-color:#4e81e8;text-decoration-color:#4e81e8}.hds-link-standalone--color-primary.mock-active,.hds-link-standalone--color-primary:active{color:var(--token-color-foreground-action-active)}.hds-link-standalone--color-primary.mock-active .hds-link-standalone__text,.hds-link-standalone--color-primary:active .hds-link-standalone__text{-webkit-text-decoration-color:#396ed6;text-decoration-color:#396ed6}.hds-link-standalone--color-primary.mock-active::before,.hds-link-standalone--color-primary:active::before{background-color:var(--token-color-surface-action)}.hds-link-standalone--color-secondary{color:var(--token-color-foreground-strong)}.hds-link-standalone--color-secondary.mock-hover .hds-link-standalone__text,.hds-link-standalone--color-secondary:hover .hds-link-standalone__text{-webkit-text-decoration-color:#4d4d4f;text-decoration-color:#4d4d4f}.hds-link-standalone--color-secondary.mock-active,.hds-link-standalone--color-secondary:active{color:var(--token-color-foreground-primary)}.hds-link-standalone--color-secondary.mock-active .hds-link-standalone__text,.hds-link-standalone--color-secondary:active .hds-link-standalone__text{-webkit-text-decoration-color:#6e7075;text-decoration-color:#6e7075}.hds-link-standalone--color-secondary.mock-active::before,.hds-link-standalone--color-secondary:active::before{background-color:var(--token-color-surface-interactive-active)}.hds-link-standalone::before{position:absolute;top:-5px;right:-5px;bottom:-5px;left:-5px;z-index:-1;border-radius:5px;content:""}.hds-link-standalone.mock-focus::before,.hds-link-standalone:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-link-standalone:focus:not(:focus-visible)::before{box-shadow:none}.hds-link-standalone:focus-visible::before,.hds-pagination-nav__control.mock-focus::before,.hds-pagination-nav__control:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-link-standalone.mock-focus.mock-active::before,.hds-link-standalone:focus:active::before{box-shadow:none}.hds-link-standalone.hds-link-standalone--icon-position-leading::before{right:-7px}.hds-link-standalone.hds-link-standalone--icon-position-trailing::before{left:-7px}.hds-modal{z-index:50;flex-direction:column;padding:0;background:var(--token-color-surface-primary);border:none;border-radius:8px;box-shadow:var(--token-surface-overlay-box-shadow)}.hds-modal[open]{position:fixed;display:flex}.hds-modal::backdrop,.readonly-codemirror .CodeMirror-cursors{display:none}.hds-modal::-webkit-backdrop{display:none}.hds-modal__overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;background:var(--token-color-palette-neutral-700);opacity:.5}.hds-modal__header{display:flex;flex:none;align-items:flex-start;padding:16px 24px;border-top-left-radius:inherit;border-top-right-radius:inherit}.hds-modal__icon{flex:none;align-self:center;margin-right:16px}.freetext-filter>label,.freetext-filter_input,.hds-modal__title{flex-grow:1}.hds-modal__tagline{margin-bottom:4px}.hds-modal__dismiss{align-self:center;margin-left:16px}.hds-modal__body{flex:1 1 auto;padding:24px;overflow-y:auto;overscroll-behavior:contain}.hds-modal__footer{flex:none;padding:16px 24px;background:var(--token-color-surface-faint);border-top:1px solid var(--token-color-border-primary);border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.hds-modal__footer .hds-button-set .hds-button--color-tertiary{margin-left:auto}.hds-modal--size-small{width:min(400px,95vw)}.hds-modal--size-medium{width:min(600px,95vw)}.hds-modal--size-large{width:min(800px,95vw)}.hds-modal--color-neutral .hds-modal__header{color:var(--token-color-foreground-strong);background:var(--token-color-surface-faint);border-bottom:1px solid var(--token-color-border-primary)}.hds-modal--color-neutral .hds-modal__tagline{color:var(--token-color-foreground-faint)}.hds-modal--color-warning .hds-modal__header,.hds-modal--color-warning .hds-modal__tagline{color:var(--token-color-foreground-warning-on-surface)}.hds-modal--color-warning .hds-modal__header{background:var(--token-color-surface-warning);border-bottom:1px solid var(--token-color-border-warning)}.hds-modal--color-critical .hds-modal__header,.hds-modal--color-critical .hds-modal__tagline{color:var(--token-color-foreground-critical-on-surface)}.hds-modal--color-critical .hds-modal__header{background:var(--token-color-surface-critical);border-bottom:1px solid var(--token-color-border-critical)}.hds-pagination{display:grid;grid-template-areas:"info nav selector";grid-template-rows:auto;grid-template-columns:1fr auto 1fr;align-items:center;margin:0 auto}@media screen and (max-width:1000px){.hds-pagination{display:flex;flex-wrap:wrap;justify-content:center}.hds-pagination-info{margin-top:var(--token-pagination-child-spacing-vertical);margin-left:var(--token-pagination-child-spacing-horizontal)}}.hds-pagination-info{grid-area:info;justify-self:flex-start;margin-right:var(--token-pagination-child-spacing-horizontal);white-space:nowrap}.hds-pagination-nav{display:flex;grid-area:nav}@media screen and (max-width:1000px){.hds-pagination-nav{justify-content:center;order:-1;width:100%}}.hds-pagination-nav__page-list{display:flex;margin:0;padding:0}.hds-pagination-nav__page-item{list-style-type:none}.hds-pagination-nav__control{display:flex;align-items:center;height:var(--token-pagination-nav-control-height);padding:0 calc(var(--token-pagination-nav-control-padding-horizontal) - 1px);color:var(--token-color-foreground-primary);background-color:transparent;border:1px solid transparent;position:relative;isolation:isolate}.hds-pagination-nav__control::before{position:absolute;top:var(--token-pagination-nav-control-focus-inset);right:var(--token-pagination-nav-control-focus-inset);bottom:var(--token-pagination-nav-control-focus-inset);left:var(--token-pagination-nav-control-focus-inset);z-index:-1;border-radius:5px;content:""}.hds-pagination-nav__control:focus:not(:focus-visible)::before{box-shadow:none}.hds-pagination-nav__control:focus-visible::before,.hds-table__th-sort button.mock-focus::before,.hds-table__th-sort button:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-pagination-nav__control.mock-focus.mock-active::before,.hds-pagination-nav__control:focus:active::before{box-shadow:none}.hds-pagination-nav__control.mock-hover,.hds-pagination-nav__control:hover{color:var(--token-color-foreground-action-hover)}.hds-pagination-nav__control.mock-active,.hds-pagination-nav__control:active{color:var(--token-color-foreground-action-active)}.hds-pagination-nav__arrow.mock-disabled,.hds-pagination-nav__arrow:disabled{color:var(--token-color-foreground-disabled);cursor:not-allowed}.hds-pagination-nav__arrow--direction-prev{flex-direction:row;justify-content:flex-start}.hds-pagination-nav__arrow--direction-prev .hds-pagination-nav__arrow-label{margin-left:var(--token-pagination-nav-control-icon-spacing)}.hds-pagination-nav__arrow--direction-next{flex-direction:row-reverse;justify-content:flex-end}.hds-pagination-nav__number--is-selected{position:relative;color:var(--token-color-foreground-action)}.hds-pagination-nav__number--is-selected:hover{color:var(--token-color-foreground-action-hover)}.hds-pagination-nav__number--is-selected:active{color:var(--token-color-foreground-action-active)}.hds-pagination-nav__number--is-selected::after{position:absolute;right:calc(var(--token-pagination-nav-indicator-spacing) - 1px);bottom:-1px;left:calc(var(--token-pagination-nav-indicator-spacing) - 1px);height:var(--token-pagination-nav-indicator-height);margin:0 auto;background-color:currentColor;border-radius:2px;content:""}.hds-pagination-nav__ellipsis{display:flex;align-items:center;height:var(--token-pagination-nav-control-height);padding:0 var(--token-pagination-nav-control-padding-horizontal);color:var(--token-color-foreground-faint)}.hds-pagination-size-selector{display:flex;grid-area:selector;align-items:center;justify-self:flex-end;margin-left:var(--token-pagination-child-spacing-horizontal)}@media screen and (max-width:1000px){.hds-pagination-size-selector{margin-top:var(--token-pagination-child-spacing-vertical);margin-right:var(--token-pagination-child-spacing-horizontal)}}.hds-pagination-size-selector>label{white-space:nowrap}.hds-pagination-size-selector>select{height:28px;margin-left:12px;padding:0 24px 0 8px;background-position:center right 5px}.hds-stepper-indicator-step__text,.hds-tag{font-weight:var(--token-typography-font-weight-medium);font-size:.8125rem}.hds-stepper-indicator-step{position:relative;width:24px;height:24px}.hds-stepper-indicator-step__svg-hexagon{width:100%;height:100%;filter:drop-shadow(0 1px 1px rgba(101, 106, 118, .05))}.hds-stepper-indicator-step__svg-hexagon path{fill:--status-fill-color;stroke:--status-stroke-color}.hds-stepper-indicator-step__status{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center}.hds-stepper-indicator-step__icon{width:12px;height:12px;color:--status-text-color}.hds-stepper-indicator-step__text{width:20px;overflow:hidden;color:--status-text-color;white-space:nowrap;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none}.hds-stepper-indicator-step--status-incomplete .hds-stepper-indicator-step__status{color:var(--token-color-foreground-strong)}.hds-stepper-indicator-step--status-complete .hds-stepper-indicator-step__status,.hds-stepper-indicator-step--status-processing .hds-stepper-indicator-step__status,.hds-stepper-indicator-step--status-progress .hds-stepper-indicator-step__status{color:var(--token-color-foreground-high-contrast)}.hds-stepper-indicator-step--status-incomplete .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-surface-faint);stroke:var(--token-color-foreground-strong)}.hds-stepper-indicator-step--status-complete .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--status-processing .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--status-progress .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-foreground-strong);stroke:var(--token-color-foreground-strong)}.hds-stepper-indicator-step--is-interactive{cursor:pointer}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-incomplete .hds-stepper-indicator-step__status{color:var(--token-color-foreground-primary)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-processing .hds-stepper-indicator-step__status,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-progress .hds-stepper-indicator-step__status{color:var(--token-color-foreground-high-contrast)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-incomplete .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-surface-interactive);stroke:var(--token-color-border-strong)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-incomplete.mock-hover .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-incomplete:hover .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-surface-interactive-hover)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-incomplete.mock-active .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-incomplete:active .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-surface-interactive-active)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-progress .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-200);stroke:var(--token-color-palette-blue-300)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-progress.mock-hover .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-progress:hover .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-300);stroke:var(--token-color-palette-blue-400)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-progress.mock-active .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-progress:active .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-400);stroke:var(--token-color-palette-blue-400)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-processing .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-200);stroke:var(--token-color-palette-blue-300)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-processing.mock-hover .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-processing:hover .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-300);stroke:var(--token-color-palette-blue-400)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-processing.mock-active .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-processing:active .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-400);stroke:var(--token-color-palette-blue-400)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete .hds-stepper-indicator-step__status{color:var(--token-color-palette-blue-200)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-50);stroke:var(--token-color-palette-blue-300)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete.mock-active .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete.mock-hover .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete:active .hds-stepper-indicator-step__svg-hexagon path,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete:hover .hds-stepper-indicator-step__svg-hexagon path{fill:var(--token-color-palette-blue-100);stroke:var(--token-color-palette-blue-400)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete.mock-hover .hds-stepper-indicator-step__status,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete:hover .hds-stepper-indicator-step__status{color:var(--token-color-palette-blue-300)}.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete.mock-active .hds-stepper-indicator-step__status,.hds-stepper-indicator-step--is-interactive.hds-stepper-indicator-step--status-complete:active .hds-stepper-indicator-step__status{color:var(--token-color-palette-blue-400)}.hds-stepper-indicator-task{position:relative;display:flex;align-items:center;justify-content:center;width:16px;height:16px;color:var(--token-color-foreground-strong)}.hds-stepper-indicator-task__icon{width:12px;height:12px}.hds-stepper-indicator-task--is-interactive{cursor:pointer}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-incomplete{color:var(--token-color-palette-neutral-300)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-incomplete.mock-hover,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-incomplete:hover{color:var(--token-color-palette-blue-300)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-incomplete.mock-active,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-incomplete:active{color:var(--token-color-palette-blue-400)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-progress{color:var(--token-color-palette-blue-200)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-progress.mock-hover,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-progress:hover{color:var(--token-color-palette-blue-300)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-progress.mock-active,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-progress:active{color:var(--token-color-palette-blue-400)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-processing{color:var(--token-color-palette-blue-200)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-processing.mock-hover,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-processing:hover{color:var(--token-color-palette-blue-300)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-processing.mock-active,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-processing:active{color:var(--token-color-palette-blue-400)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-complete{color:var(--token-color-palette-green-200)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-complete.mock-hover,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-complete:hover{color:var(--token-color-palette-green-300)}.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-complete.mock-active,.hds-stepper-indicator-task--is-interactive.hds-stepper-indicator-task--status-complete:active{color:var(--token-color-palette-green-400)}.hds-table{width:100%;border:1px solid var(--token-color-border-primary);border-radius:6px}.hds-table--layout-fixed{table-layout:fixed}.hds-table__thead .hds-table__tr{color:var(--token-color-foreground-strong);background-color:var(--token-color-surface-strong)}.hds-table__thead .hds-table__tr:first-of-type th:first-child{border-top-left-radius:5px}.hds-table__thead .hds-table__tr:first-of-type th:last-child{border-top-right-radius:5px}.hds-table__th,.hds-table__th-sort{height:48px;text-align:left;border-top:none;border-right:none;border-bottom:1px solid var(--token-color-border-primary);border-left:none}.hds-table__th{padding:12px 16px}.hds-table__th-sort{padding:0}.hds-table__th-sort button{width:100%;height:100%;min-height:48px;margin:0;padding:12px 16px;text-align:inherit;background-color:transparent;border:1px solid transparent;border-radius:inherit;position:relative;isolation:isolate}.hds-table__th-sort button .hds-table__th-sort--button-content{display:flex;align-items:center}.hds-table__th-sort button .hds-table__th-sort--button-content .flight-icon{flex:none;margin-left:8px;color:var(--token-color-foreground-action)}.hds-tabs__tab,.hds-tabs__tablist{margin:0;position:relative;display:flex}.hds-table__th-sort button.mock-hover,.hds-table__th-sort button:hover{color:var(--token-color-foreground-strong);background-color:var(--token-color-palette-neutral-200);cursor:pointer}.hds-table__th-sort button::before{position:absolute;top:0;right:0;bottom:0;left:0;z-index:-1;border-radius:inherit;content:""}.hds-table__th-sort button:focus:not(:focus-visible)::before{box-shadow:none}.hds-table__th-sort button:focus-visible::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-table__th-sort button.mock-focus.mock-active::before,.hds-table__th-sort button:focus:active::before{box-shadow:none}.hds-table__th-sort button.mock-active,.hds-table__th-sort button:active{color:var(--token-color-foreground-strong);background-color:var(--token-color-palette-neutral-300)}.hds-table__tbody .hds-table__tr,.hds-tabs__tab,.hds-tag,.hds-tag__dismiss-icon{color:var(--token-color-foreground-primary)}.hds-table--striped .hds-table__tbody .hds-table__tr:nth-child(even){background-color:var(--token-color-surface-faint)}.hds-table--density-short .hds-table__tbody td{padding:4px 16px}.hds-table--density-medium .hds-table__tbody td{padding:12px 16px}.hds-table--density-tall .hds-table__tbody td{padding:20px 16px}.hds-table--valign-top .hds-table__tbody td{vertical-align:top}.hds-table--valign-middle .hds-table__tbody td,.hds-tag{vertical-align:middle}.hds-table__td--text-right,.hds-table__th--text-right,.hds-table__th-sort--text-right{text-align:right}.hds-table__td--text-center,.hds-table__th--text-center,.hds-table__th-sort--text-center{text-align:center}.hds-table__tbody .hds-table__tr{background-color:var(--token-color-surface-primary)}.hds-table__tbody .hds-table__tr td{border-top:none;border-right:none;border-bottom:1px solid var(--token-color-border-primary);border-left:none}.hds-table__tbody .hds-table__tr:last-of-type td{border-bottom:none}.hds-table__tbody .hds-table__tr:last-of-type td:first-child{border-bottom-left-radius:5px}.hds-table__tbody .hds-table__tr:last-of-type td:last-child{border-bottom-right-radius:5px}.hds-tabs__tablist-wrapper{position:relative}.hds-tabs__tablist-wrapper::before{position:absolute;right:0;bottom:calc((var(--token-tabs-indicator-height) - var(--token-tabs-divider-height))/ 2);left:0;display:block;border-top:var(--token-tabs-divider-height) solid var(--token-color-border-primary);content:""}.hds-tabs__tablist{padding:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.hds-tabs__tab{align-items:center;height:var(--token-tabs-tab-height);padding:var(--token-tabs-tab-padding-vertical) var(--token-tabs-tab-padding-horizontal);white-space:nowrap;list-style:none}.hds-tabs__tab.hds-tabs__tab--is-selected,.hds-tabs__tab.mock-hover,.hds-tabs__tab:hover{color:var(--token-color-foreground-action)}.hds-tabs__tab.hds-tabs__tab--is-selected:hover{color:var(--token-color-foreground-action-hover)}.hds-tabs__tab.hds-tabs__tab--is-selected:hover~.hds-tabs__tab-indicator{background:var(--token-color-foreground-action-hover)}.hds-tabs__tab-button{isolation:isolate;position:static;display:flex;align-items:center;padding:0;color:inherit;background-color:transparent;border:none;border-radius:var(--token-tabs-tab-border-radius);cursor:pointer}.hds-tabs__tab-button::before{position:absolute;top:var(--token-tabs-tab-focus-inset);right:var(--token-tabs-tab-focus-inset);bottom:var(--token-tabs-tab-focus-inset);left:var(--token-tabs-tab-focus-inset);z-index:-1;border-radius:5px;content:""}.hds-tabs__tab-button.mock-focus::before,.hds-tabs__tab-button:focus::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-tabs__tab-button:focus:not(:focus-visible)::before{box-shadow:none}.hds-tabs__tab-button:focus-visible::before{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-tabs__tab-button.mock-focus.mock-active::before,.hds-tabs__tab-button:focus:active::before{box-shadow:none}.hds-tabs__tab-button::after{position:absolute;content:"";inset:0}.hds-tabs__tab-icon{margin-right:var(--token-tabs-tab-gutter)}.hds-tabs__tab-count{margin-left:var(--token-tabs-tab-gutter)}.hds-tabs__tab-indicator{position:absolute;right:0;bottom:0;left:var(--indicator-left-pos);z-index:10;display:block;width:var(--indicator-width);height:var(--token-tabs-indicator-height);background-color:var(--token-color-foreground-action);border-radius:var(--token-tabs-indicator-height)}.hds-tag,.hds-tag__dismiss,.hds-tag__link{background-color:var(--token-color-surface-interactive)}@media screen and (prefers-reduced-motion:no-preference){.hds-tabs__tab-indicator{transition-timing-function:var(--token-tabs-indicator-transition-function);transition-duration:var(--token-tabs-indicator-transition-duration);transition-property:left,width}}.hds-tag{display:inline-flex;align-items:stretch;line-height:1rem;border:1px solid var(--token-color-border-strong);border-radius:50px}article,aside,figure,footer,header,hgroup,hr,section{display:block}.hds-tag__dismiss{flex:0 0 auto;margin:0;padding:6px 2px 6px 8px;border:none;border-radius:inherit;border-top-right-radius:0;border-bottom-right-radius:0}.hds-tag__dismiss-icon{width:12px;height:12px}.hds-tag__link,.hds-tag__text{flex:1 0 0;padding:3px 10px 5px;border-radius:inherit}.hds-tag__dismiss~.hds-tag__link,.hds-tag__dismiss~.hds-tag__text{padding:3px 8px 5px 6px;border-top-left-radius:0;border-bottom-left-radius:0}.hds-tag__dismiss,.hds-tag__link{cursor:pointer}.hds-tag__dismiss.mock-hover,.hds-tag__dismiss:hover,.hds-tag__link.mock-hover,.hds-tag__link:hover{background-color:var(--token-color-surface-interactive-hover)}.hds-tag__dismiss.mock-active,.hds-tag__dismiss:active,.hds-tag__link.mock-active,.hds-tag__link:active,hr{background-color:var(--token-color-surface-interactive-active)}.hds-tag__dismiss.mock-focus,.hds-tag__dismiss:focus,.hds-tag__link.mock-focus,.hds-tag__link:focus{outline-style:solid;outline-color:transparent;z-index:1}.hds-tag__dismiss.mock-focus.mock-focus,.hds-tag__dismiss.mock-focus:focus,.hds-tag__dismiss:focus.mock-focus,.hds-tag__dismiss:focus:focus,.hds-tag__link.mock-focus.mock-focus,.hds-tag__link.mock-focus:focus,.hds-tag__link:focus.mock-focus,.hds-tag__link:focus:focus{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-tag__dismiss.mock-focus:focus:not(:focus-visible),.hds-tag__dismiss:focus:focus:not(:focus-visible),.hds-tag__link.mock-focus:focus:not(:focus-visible),.hds-tag__link:focus:focus:not(:focus-visible){box-shadow:none}.hds-tag__dismiss.mock-focus:focus-visible,.hds-tag__dismiss:focus:focus-visible,.hds-tag__link.mock-focus:focus-visible,.hds-tag__link:focus:focus-visible{box-shadow:var(--token-focus-ring-action-box-shadow)}.hds-tag__dismiss.mock-focus.mock-focus.mock-active,.hds-tag__dismiss.mock-focus:focus:active,.hds-tag__dismiss:focus.mock-focus.mock-active,.hds-tag__dismiss:focus:focus:active,.hds-tag__link.mock-focus.mock-focus.mock-active,.hds-tag__link.mock-focus:focus:active,.hds-tag__link:focus.mock-focus.mock-active,.hds-tag__link:focus:focus:active{box-shadow:none}.hds-tag--color-primary .hds-tag__link{color:var(--token-color-foreground-action)}.hds-tag--color-primary .hds-tag__link.mock-hover,.hds-tag--color-primary .hds-tag__link:hover{color:var(--token-color-foreground-action-hover)}.hds-tag--color-primary .hds-tag__link.mock-active,.hds-tag--color-primary .hds-tag__link:active{color:var(--token-color-foreground-action-active)}.hds-tag--color-secondary .hds-tag__link,body{color:var(--token-color-foreground-strong)}.hds-toast{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;min-width:min(360px,80vw);max-width:min(500px,80vw);box-shadow:var(--token-elevation-higher-box-shadow)}.sr-only{position:absolute!important;width:1px!important;height:1px!important;margin:-1px!important;padding:0!important;overflow:hidden!important;white-space:nowrap!important;border:0!important;clip:rect(1px,1px,1px,1px)!important;-webkit-clip-path:inset(50%)!important;clip-path:inset(50%)!important}fieldset,hr{border:none}blockquote,body,dd,dl,dt,fieldset,figure,h1,h2,h3,h4,h5,h6,hr,html,iframe,legend,li,ol,p,pre,textarea,ul{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:400}ul{list-style:none}table td,table th{padding:0;text-align:left}audio,embed,img,object,video{height:auto;max-width:100%}.consul-intention-action-warn-modal button.dangerous,.copy-button button,.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.hashicorp-consul nav li.nspaces .disclosure-menu>button,.hashicorp-consul nav li.partitions .disclosure-menu>button,.informed-action>ul>li>*,.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-select label>*,.topology-notices button,.type-sort.popover-select label>*,label span,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}a{color:var(--token-color-foreground-action)}span,strong,td,th{color:inherit}html{background-color:var(--token-color-surface-primary);font-size:var(--typo-size-000);text-rendering:optimizeLegibility;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;overflow-x:hidden;overflow-y:scroll;box-sizing:border-box;min-width:300px}hr{height:1px;margin:1.5rem 0}body,input,select,textarea{font-family:var(--typo-family-sans)}.CodeMirror-lint-tooltip,.cm-s-hashi.CodeMirror,code,pre{font-family:var(--typo-family-mono)}strong{font-style:inherit;font-weight:var(--typo-weight-bold)}code,pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}pre{-webkit-overflow-scrolling:touch;overflow-x:auto;white-space:pre;word-wrap:normal}*,::after,::before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scroll-snap-strictness:proximity;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-sizing:inherit;-webkit-animation-play-state:paused;animation-play-state:paused;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}fieldset{width:100%}a,input[type=checkbox],input[type=radio]{cursor:pointer}input[type=checkbox],input[type=radio]{vertical-align:baseline}td,th{text-align:left;vertical-align:top}button,input,select,textarea{margin:0}iframe{border:0}.consul-bucket-list .service,.consul-bucket-list:not([class]) dt:not([class]),.consul-exposed-path-list>ul>li>.detail dl:not([class]) dt:not([class]),.consul-instance-checks:not([class]) dt:not([class]),.consul-lock-session-list dl:not([class]) dt:not([class]),.consul-server-card dt:not(.name),.consul-upstream-instance-list dl.local-bind-address dt,.consul-upstream-instance-list dl.local-bind-socket-path dt,.consul-upstream-instance-list dl:not([class]) dt:not([class]),.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dt:not([class]),.route-title,.tag-list:not([class]) dt:not([class]),section[data-route="dc.show.license"] .validity dl .expired+dd,section[data-route="dc.show.license"] .validity dl:not([class]) dt:not([class]),section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dt:not([class]),td.tags:not([class]) dt:not([class]){position:absolute;overflow:hidden;clip:rect(0 0 0 0);width:1px;height:1px;margin:-1px;padding:0;border:0}.consul-upstream-instance-list dl.local-bind-socket-mode dt,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dt{position:static!important;clip:unset!important;overflow:visible!important;width:auto!important;height:auto!important;margin:0!important;padding:0!important}.animatable.tab-nav ul::after,.consul-auth-method-type,.consul-external-source,.consul-intention-action-warn-modal button.dangerous,.consul-intention-action-warn-modal button.dangerous:hover:active,.consul-intention-action-warn-modal button.dangerous:hover:not(:disabled):not(:active),.consul-intention-list td.intent- strong,.consul-intention-permission-form button.type-submit,.consul-intention-permission-form button.type-submit:disabled,.consul-intention-permission-form button.type-submit:focus:not(:disabled),.consul-intention-permission-form button.type-submit:hover:not(:disabled),.consul-intention-search-bar .value- span,.consul-kind,.consul-source,.consul-transparent-proxy,.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:first-child,.discovery-chain .route-card>header ul li,.informed-action>ul>.dangerous>*,.informed-action>ul>.dangerous>:focus,.informed-action>ul>.dangerous>:hover,.leader,.menu-panel>ul>li.dangerous>:first-child,.modal-dialog [role=document]>footer,.modal-dialog [role=document]>header,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:first-child,.tab-nav .selected>*,.topology-metrics-source-type,html[data-route^="dc.acls.index"] main td strong,span.policy-node-identity,span.policy-service-identity,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:first-child{border-style:solid}.animatable.tab-nav ul::after,.app .notifications .app-notification,.tab-nav li>*{transition-duration:.15s;transition-timing-function:ease-out}[role=banner] nav:first-of-type,[role=contentinfo],html body>.brand-loader,main{transition-timing-function:cubic-bezier(.1,.1,.25,.9);transition-duration:.1s}html[data-state]:not(.ember-loading) body>.brand-loader{-webkit-animation-timing-function:cubic-bezier(.1,.1,.25,.9);animation-timing-function:cubic-bezier(.1,.1,.25,.9);-webkit-animation-duration:.1s;animation-duration:.1s;-webkit-animation-name:remove-from-flow;animation-name:remove-from-flow;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@-webkit-keyframes remove-from-flow{100%{visibility:hidden;overflow:hidden;clip:rect(0 0 0 0)}}@keyframes remove-from-flow{100%{visibility:hidden;overflow:hidden;clip:rect(0 0 0 0)}}@-webkit-keyframes typo-truncate{100%{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}}@keyframes typo-truncate{100%{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}}.informed-action header>*{font-size:inherit;font-weight:inherit;line-height:inherit;font-style:inherit}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password],.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text],.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea,.modal-dialog [role=document] .type-password [type=password],.modal-dialog [role=document] .type-password [type=text],.modal-dialog [role=document] .type-password textarea,.modal-dialog [role=document] .type-select [type=password],.modal-dialog [role=document] .type-select [type=text],.modal-dialog [role=document] .type-select textarea,.modal-dialog [role=document] .type-text [type=password],.modal-dialog [role=document] .type-text [type=text],.modal-dialog [role=document] .type-text textarea,.modal-dialog [role=document] [role=radiogroup] label [type=password],.modal-dialog [role=document] [role=radiogroup] label [type=text],.modal-dialog [role=document] [role=radiogroup] label textarea,.oidc-select label [type=password],.oidc-select label [type=text],.oidc-select label textarea,.type-toggle [type=password],.type-toggle [type=text],.type-toggle textarea,body,main .type-password [type=password],main .type-password [type=text],main .type-password textarea,main .type-select [type=password],main .type-select [type=text],main .type-select textarea,main .type-text [type=password],main .type-text [type=text],main .type-text textarea{font-size:var(--typo-size-600);font-family:var(--typo-family-sans);line-height:var(--typo-lead-700)}.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.app-view>header .title .title-left-container>:first-child,.consul-auth-method-binding-list h2,.consul-auth-method-view section h2,.consul-health-check-list .health-check-output dt,.consul-health-check-list .health-check-output header>*,.consul-intention-list td.destination,.consul-intention-list td.source,.consul-intention-permission-form h2,.consul-intention-view h2,.consul-server-card .name+dd,.definition-table dt,.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.empty-state header :first-child,.hashicorp-consul nav .dcs [aria-expanded],.hashicorp-consul nav li.nspaces .disclosure-menu>button,.hashicorp-consul nav li.partitions .disclosure-menu>button,.informed-action header,.informed-action>ul>li>*,.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label>span,.modal-dialog [role=document] form h2,.modal-dialog [role=document] table caption,.modal-dialog [role=document] table td strong,.modal-dialog [role=document] table td:first-child,.modal-dialog [role=document] table th,.modal-dialog [role=document]>header>:not(button),.modal-dialog-body h2,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.oidc-select label>span,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.radio-card header,.tab-nav,.type-toggle label span,.type-toggle>span,[role=banner] nav:last-of-type [aria-expanded],[role=banner] nav:last-of-type>ul>li>.popover-menu>label>button,[role=banner] nav:last-of-type>ul>li>a,[role=banner] nav:last-of-type>ul>li>button,[role=banner] nav:last-of-type>ul>li>span,fieldset>header,html[data-route^="dc.kv.edit"] h2,html[data-route^="dc.services.instance.metadata"] .tab-section section h2,main .type-password>span,main .type-select>span,main .type-text>span,main form h2,main header nav:first-child ol li>*,main table caption,main table td strong,main table td:first-child,main table th,section[data-route="dc.show.license"] aside header>:first-child,section[data-route="dc.show.license"] h2,section[data-route="dc.show.serverstatus"] .redundancy-zones h3,section[data-route="dc.show.serverstatus"] h2,section[data-route="dc.show.serverstatus"] h3,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{line-height:var(--typo-lead-200)}.app-view>header .title .title-left-container>:first-child{font-weight:var(--typo-weight-bold);font-size:var(--typo-size-200)}.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.consul-auth-method-binding-list h2,.consul-auth-method-view section h2,.consul-health-check-list .health-check-output header>*,.consul-intention-list td.destination,.consul-intention-list td.source,.consul-intention-permission-form h2,.consul-intention-view h2,.consul-server-card .name+dd,.definition-table dt,.empty-state header :first-child,.hashicorp-consul nav .dcs [aria-expanded],.informed-action header,.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label>span,.modal-dialog [role=document] form h2,.modal-dialog [role=document] table caption,.modal-dialog [role=document] table td:first-child,.modal-dialog [role=document]>header>:not(button),.modal-dialog-body h2,.oidc-select label>span,.radio-card header,.type-toggle>span,[role=banner] nav:last-of-type [aria-expanded],[role=banner] nav:last-of-type>ul>li>.popover-menu>label>button,[role=banner] nav:last-of-type>ul>li>a,[role=banner] nav:last-of-type>ul>li>button,[role=banner] nav:last-of-type>ul>li>span,fieldset>header,html[data-route^="dc.kv.edit"] h2,html[data-route^="dc.services.instance.metadata"] .tab-section section h2,main .type-password>span,main .type-select>span,main .type-text>span,main form h2,main table caption,main table td:first-child,section[data-route="dc.show.license"] aside header>:first-child,section[data-route="dc.show.license"] h2,section[data-route="dc.show.serverstatus"] .redundancy-zones h3,section[data-route="dc.show.serverstatus"] h2,section[data-route="dc.show.serverstatus"] h3{font-weight:var(--typo-weight-semibold)}.consul-health-check-list .health-check-output dt,.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.hashicorp-consul nav li.nspaces .disclosure-menu>button,.hashicorp-consul nav li.partitions .disclosure-menu>button,.informed-action>ul>li>*,.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.modal-dialog [role=document] table td strong,.modal-dialog [role=document] table th,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.tab-nav,.type-toggle label span,main header nav:first-child ol li>*,main table td strong,main table th,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{font-weight:var(--typo-weight-medium)}.consul-auth-method-binding-list h2,.consul-auth-method-view section h2,.consul-intention-permission-form h2,.consul-intention-view h2,.empty-state header :first-child,.modal-dialog [role=document] form h2,.modal-dialog [role=document]>header>:not(button),.modal-dialog-body h2,html[data-route^="dc.kv.edit"] h2,main form h2,section[data-route="dc.show.license"] h2,section[data-route="dc.show.serverstatus"] h2,section[data-route="dc.show.serverstatus"] h3{font-size:var(--typo-size-300)}.consul-health-check-list .health-check-output header>*,.consul-server-card .name+dd,html[data-route^="dc.services.instance.metadata"] .tab-section section h2,section[data-route="dc.show.license"] aside header>:first-child,section[data-route="dc.show.serverstatus"] .redundancy-zones h3{font-size:var(--typo-size-500)}.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.consul-intention-list td.destination,.consul-intention-list td.source,.definition-table dt,.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.hashicorp-consul nav .dcs [aria-expanded],.hashicorp-consul nav li.nspaces .disclosure-menu>button,.hashicorp-consul nav li.partitions .disclosure-menu>button,.informed-action header,.informed-action>ul>li>*,.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label>span,.modal-dialog [role=document] table caption,.modal-dialog [role=document] table td:first-child,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.oidc-select label>span,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.radio-card header,.tab-nav,.type-toggle>span,[role=banner] nav:last-of-type [aria-expanded],[role=banner] nav:last-of-type>ul>li>.popover-menu>label>button,[role=banner] nav:last-of-type>ul>li>a,[role=banner] nav:last-of-type>ul>li>button,[role=banner] nav:last-of-type>ul>li>span,fieldset>header,main .type-password>span,main .type-select>span,main .type-text>span,main header nav:first-child ol li>*,main table caption,main table td:first-child,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{font-size:var(--typo-size-600)}.consul-health-check-list .health-check-output dt,.modal-dialog [role=document] table td strong,.modal-dialog [role=document] table th,.type-toggle label span,main table td strong,main table th{font-size:var(--typo-size-700)}.app-view h1 span.kind-proxy,.app-view>div form:not(.filter-bar) [role=radiogroup] label>em,.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.auth-form em,.auth-profile,.consul-auth-method-view section,.consul-external-source,.consul-health-check-list .health-check-output dl>dd,.consul-intention-action-warn-modal button.dangerous,.consul-intention-fieldsets .permissions>button,.consul-intention-permission-header-list>ul>li dd,.consul-intention-permission-list>ul>li dd,.consul-kind,.consul-source,.copy-button button,.disclosure-menu [aria-expanded]~* [role=separator],.disclosure-menu [aria-expanded]~*>div,.discovery-chain .resolvers>header>*,.discovery-chain .routes>header>*,.discovery-chain .splitters>header>*,.empty-state header :nth-child(2),.empty-state p,.empty-state>ul>li>*,.empty-state>ul>li>label>button,.has-error>strong,.informed-action p,.menu-panel [role=separator],.menu-panel>div,.modal-dialog [role=document] .type-password>em,.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>em,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text>em,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label>em,.modal-dialog [role=document] [role=radiogroup] label>span,.modal-dialog [role=document] form button+em,.modal-dialog [role=document] p,.modal-dialog [role=document] table td,.modal-dialog [role=document] table td p,.more-popover-menu>[type=checkbox]+label+div [role=separator],.more-popover-menu>[type=checkbox]+label+div>div,.oidc-select button.reset,.oidc-select label>em,.oidc-select label>span,.popover-menu>[type=checkbox]+label+div [role=separator],.popover-menu>[type=checkbox]+label+div>div,.popover-select label>*,.tippy-box[data-theme~=tooltip] .tippy-content,.topology-notices button,.type-sort.popover-select label>*,.type-toggle>em,.type-toggle>span,[role=banner] nav:first-of-type [role=separator],[role=banner] nav:first-of-type a,[role=banner] nav:first-of-type>ul>li>label,[role=contentinfo],main .type-password>em,main .type-password>span,main .type-select>em,main .type-select>span,main .type-text>em,main .type-text>span,main form button+em,main p,main table td,main table td p,pre code,section[data-route="dc.show.serverstatus"] .server-failure-tolerance dt,span.label,table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],table.has-actions tr>.actions>[type=checkbox]+label+div>div,table.with-details tr>.actions>[type=checkbox]+label+div [role=separator],table.with-details tr>.actions>[type=checkbox]+label+div>div{line-height:inherit;font-size:inherit}.consul-auth-method-view section,.consul-external-source,.consul-kind,.consul-source,[role=banner] nav:first-of-type a,[role=banner] nav:first-of-type>ul>li>label,pre code{font-size:var(--typo-size-600)}.app-view h1 span.kind-proxy,.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.auth-profile,.consul-health-check-list .health-check-output dl>dd,.consul-intention-fieldsets .permissions>button,.consul-intention-permission-header-list>ul>li dd,.consul-intention-permission-list>ul>li dd,.disclosure-menu [aria-expanded]~*>div,.empty-state>ul>li>*,.empty-state>ul>li>label>button,.informed-action p,.menu-panel>div,.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label>span,.modal-dialog [role=document] table td,.modal-dialog [role=document] table td p,.more-popover-menu>[type=checkbox]+label+div>div,.oidc-select label>span,.popover-menu>[type=checkbox]+label+div>div,.type-toggle>span,[role=contentinfo],main .type-password>span,main .type-select>span,main .type-text>span,main table td,main table td p,section[data-route="dc.show.serverstatus"] .server-failure-tolerance dt,span.label,table.has-actions tr>.actions>[type=checkbox]+label+div>div,table.with-details tr>.actions>[type=checkbox]+label+div>div{font-size:var(--typo-size-700)}.app-view>div form:not(.filter-bar) [role=radiogroup] label>em,.auth-form em,.consul-intention-action-warn-modal button.dangerous,.copy-button button,.disclosure-menu [aria-expanded]~* [role=separator],.discovery-chain .resolvers>header>*,.discovery-chain .routes>header>*,.discovery-chain .splitters>header>*,.empty-state header :nth-child(2),.empty-state p,.has-error>strong,.menu-panel [role=separator],.modal-dialog [role=document] .type-password>em,.modal-dialog [role=document] .type-select>em,.modal-dialog [role=document] .type-text>em,.modal-dialog [role=document] [role=radiogroup] label>em,.modal-dialog [role=document] form button+em,.modal-dialog [role=document] p,.more-popover-menu>[type=checkbox]+label+div [role=separator],.oidc-select button.reset,.oidc-select label>em,.popover-menu>[type=checkbox]+label+div [role=separator],.popover-select label>*,.tippy-box[data-theme~=tooltip] .tippy-content,.topology-notices button,.type-sort.popover-select label>*,.type-toggle>em,[role=banner] nav:first-of-type [role=separator],[role=contentinfo],main .type-password>em,main .type-select>em,main .type-text>em,main form button+em,main p,table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]{font-size:var(--typo-size-800)}::after,::before{--tw-content:'';display:inline-block;vertical-align:text-top;background-repeat:no-repeat;background-position:center;mask-repeat:no-repeat;-webkit-mask-repeat:no-repeat;mask-position:center;-webkit-mask-position:center}::before{-webkit-animation-name:var(--icon-name-start,var(--icon-name)),var(--icon-size-start,var(--icon-size,icon-000));animation-name:var(--icon-name-start,var(--icon-name)),var(--icon-size-start,var(--icon-size,icon-000));background-color:var(--icon-color-start,var(--icon-color))}::after{-webkit-animation-name:var(--icon-name-end,var(--icon-name)),var(--icon-size-end,var(--icon-size,icon-000));animation-name:var(--icon-name-end,var(--icon-name)),var(--icon-size-end,var(--icon-size,icon-000));background-color:var(--icon-color-end,var(--icon-color))}[style*="--icon-color-start"]::before{color:var(--icon-color-start)}[style*="--icon-color-end"]::after{color:var(--icon-color-end)}[style*="--icon-name-start"]::before,[style*="--icon-name-end"]::after{content:""}@-webkit-keyframes icon-000{100%{width:1.2em;height:1.2em}}@keyframes icon-000{100%{width:1.2em;height:1.2em}}@-webkit-keyframes icon-100{100%{width:.625rem;height:.625rem}}@keyframes icon-100{100%{width:.625rem;height:.625rem}}@-webkit-keyframes icon-200{100%{width:.75rem;height:.75rem}}@keyframes icon-200{100%{width:.75rem;height:.75rem}}@-webkit-keyframes icon-300{100%{width:1rem;height:1rem}}@keyframes icon-300{100%{width:1rem;height:1rem}}@-webkit-keyframes icon-400{100%{width:1.125rem;height:1.125rem}}@keyframes icon-400{100%{width:1.125rem;height:1.125rem}}@-webkit-keyframes icon-500{100%{width:1.25rem;height:1.25rem}}@keyframes icon-500{100%{width:1.25rem;height:1.25rem}}@-webkit-keyframes icon-600{100%{width:1.375rem;height:1.375rem}}@keyframes icon-600{100%{width:1.375rem;height:1.375rem}}@-webkit-keyframes icon-700{100%{width:1.5rem;height:1.5rem}}@keyframes icon-700{100%{width:1.5rem;height:1.5rem}}@-webkit-keyframes icon-800{100%{width:1.625rem;height:1.625rem}}@keyframes icon-800{100%{width:1.625rem;height:1.625rem}}@-webkit-keyframes icon-900{100%{width:1.75rem;height:1.75rem}}@keyframes icon-900{100%{width:1.75rem;height:1.75rem}}@-webkit-keyframes icon-999{100%{width:100%;height:100%}}@keyframes icon-999{100%{width:100%;height:100%}}.consul-intention-permission-header-list dt::before,.consul-intention-permission-list dt::before,.discovery-chain .resolver-card dt,.discovery-chain .route-card section header>::before{font-weight:var(--typo-weight-normal);background-color:var(--token-color-surface-strong);visibility:visible;padding:0 4px}.consul-intention-action-warn-modal button.dangerous:disabled .progress+*,.copy-button button:disabled .progress+*,.popover-select label>:disabled .progress+*,.topology-notices button:disabled .progress+*,[role=banner] nav:not(.in-viewport):first-of-type{visibility:hidden}#downstream-container .topology-metrics-card .details .group span::before,#downstream-container .topology-metrics-card div .critical::before,#downstream-container .topology-metrics-card div .empty::before,#downstream-container .topology-metrics-card div .health dt::before,#downstream-container .topology-metrics-card div .nspace dt::before,#downstream-container .topology-metrics-card div .partition dt::before,#downstream-container .topology-metrics-card div .passing::before,#downstream-container .topology-metrics-card div .warning::before,#downstream-container>div:first-child span::before,#login-toggle+div footer button::after,#metrics-container .link .config-link::before,#metrics-container .link .metrics-link::before,#metrics-container:hover .sparkline-key-link::before,#upstream-container .topology-metrics-card .details .group span::before,#upstream-container .topology-metrics-card div .critical::before,#upstream-container .topology-metrics-card div .empty::before,#upstream-container .topology-metrics-card div .health dt::before,#upstream-container .topology-metrics-card div .nspace dt::before,#upstream-container .topology-metrics-card div .partition dt::before,#upstream-container .topology-metrics-card div .passing::before,#upstream-container .topology-metrics-card div .warning::before,.animatable.tab-nav ul::after,.consul-auth-method-binding-list dl dt.type+dd span::before,.consul-auth-method-list ul .locality::before,.consul-auth-method-view dl dt.type+dd span::before,.consul-auth-method-view section dl dt.type+dd span::before,.consul-bucket-list .nspace::before,.consul-bucket-list .partition::before,.consul-bucket-list .peer::before,.consul-exposed-path-list>ul>li>.detail .policy-management::before,.consul-exposed-path-list>ul>li>.detail .policy::before,.consul-exposed-path-list>ul>li>.detail .role::before,.consul-exposed-path-list>ul>li>.detail dl.address dt::before,.consul-exposed-path-list>ul>li>.detail dl.behavior dt::before,.consul-exposed-path-list>ul>li>.detail dl.checks dt::before,.consul-exposed-path-list>ul>li>.detail dl.critical dt::before,.consul-exposed-path-list>ul>li>.detail dl.datacenter dt::before,.consul-exposed-path-list>ul>li>.detail dl.empty dt::before,.consul-exposed-path-list>ul>li>.detail dl.lock-delay dt::before,.consul-exposed-path-list>ul>li>.detail dl.mesh dt::before,.consul-exposed-path-list>ul>li>.detail dl.node dt::before,.consul-exposed-path-list>ul>li>.detail dl.nspace dt::before,.consul-exposed-path-list>ul>li>.detail dl.passing dt::before,.consul-exposed-path-list>ul>li>.detail dl.path dt::before,.consul-exposed-path-list>ul>li>.detail dl.port dt::before,.consul-exposed-path-list>ul>li>.detail dl.protocol dt::before,.consul-exposed-path-list>ul>li>.detail dl.socket dt::before,.consul-exposed-path-list>ul>li>.detail dl.ttl dt::before,.consul-exposed-path-list>ul>li>.detail dl.unknown dt::before,.consul-exposed-path-list>ul>li>.detail dl.warning dt::before,.consul-exposed-path-list>ul>li>.header .critical dd::before,.consul-exposed-path-list>ul>li>.header .empty dd::before,.consul-exposed-path-list>ul>li>.header .passing dd::before,.consul-exposed-path-list>ul>li>.header .policy-management dd::before,.consul-exposed-path-list>ul>li>.header .unknown dd::before,.consul-exposed-path-list>ul>li>.header .warning dd::before,.consul-exposed-path-list>ul>li>.header [rel=me] dd::before,.consul-external-source.jwt::before,.consul-external-source.oidc::before,.consul-health-check-list .health-check-output dd em.jwt::before,.consul-health-check-list .health-check-output dd em.oidc::before,.consul-health-check-list .health-check-output::before,.consul-instance-checks dt::before,.consul-intention-fieldsets .value->:last-child::before,.consul-intention-fieldsets .value-allow>:last-child::before,.consul-intention-fieldsets .value-deny>:last-child::before,.consul-intention-list em span::before,.consul-intention-list td strong.jwt::before,.consul-intention-list td strong.oidc::before,.consul-intention-list td.intent- strong::before,.consul-intention-list td.intent-allow strong::before,.consul-intention-list td.intent-deny strong::before,.consul-intention-permission-list .intent-allow::before,.consul-intention-permission-list .intent-deny::before,.consul-intention-permission-list strong.jwt::before,.consul-intention-permission-list strong.oidc::before,.consul-intention-search-bar .value- span::before,.consul-intention-search-bar .value-allow span::before,.consul-intention-search-bar .value-deny span::before,.consul-intention-search-bar li button span.jwt::before,.consul-intention-search-bar li button span.oidc::before,.consul-kind::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .policy-management::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .policy::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .role::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.address dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.behavior dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.checks dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.critical dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.datacenter dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.empty dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.lock-delay dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.mesh dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.node dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.nspace dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.passing dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.path dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.port dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.protocol dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.socket dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.ttl dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.unknown dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.warning dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .critical dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header .empty dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header .passing dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header .policy-management dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header .unknown dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header .warning dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header [rel=me] dd::before,.consul-peer-search-bar li button span.jwt::before,.consul-peer-search-bar li button span.oidc::before,.consul-server-card .health-status+dd.jwt::before,.consul-server-card .health-status+dd.oidc::before,.consul-upstream-instance-list dl.datacenter dt::before,.consul-upstream-instance-list dl.nspace dt::before,.consul-upstream-instance-list dl.partition dt::before,.consul-upstream-instance-list li>.detail .policy-management::before,.consul-upstream-instance-list li>.detail .policy::before,.consul-upstream-instance-list li>.detail .role::before,.consul-upstream-instance-list li>.detail dl.address dt::before,.consul-upstream-instance-list li>.detail dl.behavior dt::before,.consul-upstream-instance-list li>.detail dl.checks dt::before,.consul-upstream-instance-list li>.detail dl.critical dt::before,.consul-upstream-instance-list li>.detail dl.datacenter dt::before,.consul-upstream-instance-list li>.detail dl.empty dt::before,.consul-upstream-instance-list li>.detail dl.lock-delay dt::before,.consul-upstream-instance-list li>.detail dl.mesh dt::before,.consul-upstream-instance-list li>.detail dl.node dt::before,.consul-upstream-instance-list li>.detail dl.nspace dt::before,.consul-upstream-instance-list li>.detail dl.passing dt::before,.consul-upstream-instance-list li>.detail dl.path dt::before,.consul-upstream-instance-list li>.detail dl.port dt::before,.consul-upstream-instance-list li>.detail dl.protocol dt::before,.consul-upstream-instance-list li>.detail dl.socket dt::before,.consul-upstream-instance-list li>.detail dl.ttl dt::before,.consul-upstream-instance-list li>.detail dl.unknown dt::before,.consul-upstream-instance-list li>.detail dl.warning dt::before,.consul-upstream-instance-list li>.header .critical dd::before,.consul-upstream-instance-list li>.header .empty dd::before,.consul-upstream-instance-list li>.header .passing dd::before,.consul-upstream-instance-list li>.header .policy-management dd::before,.consul-upstream-instance-list li>.header .unknown dd::before,.consul-upstream-instance-list li>.header .warning dd::before,.consul-upstream-instance-list li>.header [rel=me] dd::before,.consul-upstream-list dl.partition dt::before,.copy-button button::before,.dangerous.informed-action header::before,.disclosure-menu [aria-expanded]~*>ul>li.is-active>::after,.disclosure-menu [aria-expanded]~*>ul>li[aria-checked]>::after,.disclosure-menu [aria-expanded]~*>ul>li[aria-current]>::after,.disclosure-menu [aria-expanded]~*>ul>li[aria-selected]>::after,.discovery-chain .resolvers>header span::after,.discovery-chain .route-card::before,.discovery-chain .route-card>header ul li.jwt::before,.discovery-chain .route-card>header ul li.oidc::before,.discovery-chain .routes>header span::after,.discovery-chain .splitter-card::before,.discovery-chain .splitters>header span::after,.empty-state li[class*=-link]>::after,.has-error>strong::before,.hashicorp-consul .docs-link a::after,.hashicorp-consul .feedback-link a::after,.hashicorp-consul .learn-link a::after,.hashicorp-consul nav .dcs .dc-name span.jwt::before,.hashicorp-consul nav .dcs .dc-name span.oidc::before,.hashicorp-consul nav .dcs li.is-local span.jwt::before,.hashicorp-consul nav .dcs li.is-local span.oidc::before,.hashicorp-consul nav .dcs li.is-primary span.jwt::before,.hashicorp-consul nav .dcs li.is-primary span.oidc::before,.hashicorp-consul nav li.nspaces .disclosure-menu>button::after,.hashicorp-consul nav li.partitions .disclosure-menu>button::after,.info.informed-action header::before,.jwt.consul-auth-method-type::before,.jwt.consul-external-source::before,.jwt.consul-kind::before,.jwt.consul-source::before,.jwt.consul-transparent-proxy::before,.jwt.leader::before,.jwt.topology-metrics-source-type::before,.leader::before,.list-collection>button::after,.list-collection>ul>li:not(:first-child)>.detail .policy-management::before,.list-collection>ul>li:not(:first-child)>.detail .policy::before,.list-collection>ul>li:not(:first-child)>.detail .role::before,.list-collection>ul>li:not(:first-child)>.detail dl.address dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.behavior dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.checks dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.critical dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.datacenter dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.empty dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.lock-delay dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.mesh dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.node dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.nspace dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.passing dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.path dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.port dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.protocol dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.socket dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.ttl dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.unknown dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.warning dt::before,.list-collection>ul>li:not(:first-child)>.header .critical dd::before,.list-collection>ul>li:not(:first-child)>.header .empty dd::before,.list-collection>ul>li:not(:first-child)>.header .passing dd::before,.list-collection>ul>li:not(:first-child)>.header .policy-management dd::before,.list-collection>ul>li:not(:first-child)>.header .unknown dd::before,.list-collection>ul>li:not(:first-child)>.header .warning dd::before,.list-collection>ul>li:not(:first-child)>.header [rel=me] dd::before,.menu-panel>ul>li.is-active>::after,.menu-panel>ul>li[aria-checked]>::after,.menu-panel>ul>li[aria-current]>::after,.menu-panel>ul>li[aria-selected]>::after,.modal-dialog [role=document] a[rel*=help]::after,.modal-dialog [role=document] table td.folder::before,.modal-dialog [role=document] table th span::after,.more-popover-menu>[type=checkbox]+label+div>ul>li.is-active>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li[aria-checked]>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li[aria-current]>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li[aria-selected]>::after,.more-popover-menu>[type=checkbox]+label>::after,.oidc-select .auth0-oidc-provider::before,.oidc-select .google-oidc-provider::before,.oidc-select .microsoft-oidc-provider::before,.oidc-select .okta-oidc-provider::before,.oidc.consul-auth-method-type::before,.oidc.consul-external-source::before,.oidc.consul-kind::before,.oidc.consul-source::before,.oidc.consul-transparent-proxy::before,.oidc.leader::before,.oidc.topology-metrics-source-type::before,.popover-menu>[type=checkbox]+label+div>ul>li.is-active>::after,.popover-menu>[type=checkbox]+label+div>ul>li[aria-checked]>::after,.popover-menu>[type=checkbox]+label+div>ul>li[aria-current]>::after,.popover-menu>[type=checkbox]+label+div>ul>li[aria-selected]>::after,.popover-menu>[type=checkbox]+label>::after,.popover-select .jwt button::before,.popover-select .oidc button::before,.popover-select .value-critical button::before,.popover-select .value-empty button::before,.popover-select .value-passing button::before,.popover-select .value-unknown button::before,.popover-select .value-warning button::before,.search-bar-status li.jwt:not(.remove-all)::before,.search-bar-status li.oidc:not(.remove-all)::before,.search-bar-status li:not(.remove-all) button::before,.sparkline-key h3::before,.tag-list dt::before,.tooltip-panel dd>div::before,.topology-metrics-popover.deny .tippy-arrow::after,.topology-metrics-popover.deny>button::before,.topology-metrics-popover.l7 .tippy-arrow::after,.topology-metrics-popover.l7>button::before,.topology-metrics-popover.not-defined .tippy-arrow::after,.topology-metrics-popover.not-defined>button::before,.topology-metrics-status-error span::before,.topology-metrics-status-loader span::before,.topology-notices button::before,.type-sort.popover-select label>::before,.type-source.popover-select li.partition button::before,.warning.informed-action header::before,.warning.modal-dialog header::before,[class*=status-].empty-state header::before,a[rel*=external]::after,html[data-route^="dc.acls.index"] main td strong.jwt::before,html[data-route^="dc.acls.index"] main td strong.oidc::before,main a[rel*=help]::after,main header nav:first-child ol li:first-child a::before,main table td.folder::before,main table th span::after,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl.jwt::before,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl.oidc::before,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em.jwt::before,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em.oidc::before,span.jwt.policy-node-identity::before,span.jwt.policy-service-identity::before,span.oidc.policy-node-identity::before,span.oidc.policy-service-identity::before,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.is-active>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li[aria-checked]>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li[aria-current]>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li[aria-selected]>::after,table.has-actions tr>.actions>[type=checkbox]+label>::after,table.with-details td:only-child>div>label::before,table.with-details td>label::before,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.is-active>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li[aria-checked]>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li[aria-current]>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li[aria-selected]>::after,table.with-details tr>.actions>[type=checkbox]+label>::after,td.tags dt::before{content:""}.hashicorp-consul .acls-separator span{box-sizing:border-box;width:12px;height:12px}.hashicorp-consul .acls-separator span::after,.hashicorp-consul .acls-separator span::before{content:"";display:block;width:100%;height:100%;border-radius:100%}.hashicorp-consul .acls-separator span::before{border:1px solid currentColor;opacity:.5}.ember-power-select-trigger,.ember-power-select-trigger--active,.ember-power-select-trigger:focus{border-top:1px solid #aaa;border-bottom:1px solid #aaa;border-right:1px solid #aaa;border-left:1px solid #aaa}.hashicorp-consul .acls-separator span::after{position:absolute;top:2px;left:2px;width:calc(100% - 4px);height:calc(100% - 4px);background-color:currentColor}@-webkit-keyframes icon-alert-circle-outline{100%{-webkit-mask-image:var(--icon-alert-circle-16);mask-image:var(--icon-alert-circle-16);background-color:var(--icon-color,var(--color-alert-circle-outline-500,currentColor))}}@keyframes icon-alert-circle-outline{100%{-webkit-mask-image:var(--icon-alert-circle-16);mask-image:var(--icon-alert-circle-16);background-color:var(--icon-color,var(--color-alert-circle-outline-500,currentColor))}}[class*=status-].empty-state header::before{--icon-name:icon-alert-circle-outline;content:""}@-webkit-keyframes icon-alert-triangle{100%{-webkit-mask-image:var(--icon-alert-triangle-16);mask-image:var(--icon-alert-triangle-16);background-color:var(--icon-color,var(--color-alert-triangle-500,currentColor))}}@keyframes icon-alert-triangle{100%{-webkit-mask-image:var(--icon-alert-triangle-16);mask-image:var(--icon-alert-triangle-16);background-color:var(--icon-color,var(--color-alert-triangle-500,currentColor))}}#downstream-container .topology-metrics-card div .warning::before,#upstream-container .topology-metrics-card div .warning::before,.consul-exposed-path-list>ul>li>.detail dl.warning dt::before,.consul-exposed-path-list>ul>li>.header .warning dd::before,.consul-health-check-list .warning.health-check-output::before,.consul-instance-checks.warning dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.warning dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .warning dd::before,.consul-upstream-instance-list li>.detail dl.warning dt::before,.consul-upstream-instance-list li>.header .warning dd::before,.dangerous.informed-action header::before,.list-collection>ul>li:not(:first-child)>.detail dl.warning dt::before,.list-collection>ul>li:not(:first-child)>.header .warning dd::before,.popover-select .value-warning button::before,.topology-metrics-popover.not-defined .tippy-arrow::after,.topology-metrics-popover.not-defined>button::before,.warning.informed-action header::before,.warning.modal-dialog header::before{--icon-name:icon-alert-triangle;content:""}@-webkit-keyframes icon-arrow-left{100%{-webkit-mask-image:var(--icon-arrow-left-16);mask-image:var(--icon-arrow-left-16);background-color:var(--icon-color,var(--color-arrow-left-500,currentColor))}}@keyframes icon-arrow-left{100%{-webkit-mask-image:var(--icon-arrow-left-16);mask-image:var(--icon-arrow-left-16);background-color:var(--icon-color,var(--color-arrow-left-500,currentColor))}}@-webkit-keyframes icon-arrow-right{100%{-webkit-mask-image:var(--icon-arrow-right-16);mask-image:var(--icon-arrow-right-16);background-color:var(--icon-color,var(--color-arrow-right-500,currentColor))}}@keyframes icon-arrow-right{100%{-webkit-mask-image:var(--icon-arrow-right-16);mask-image:var(--icon-arrow-right-16);background-color:var(--icon-color,var(--color-arrow-right-500,currentColor))}}@-webkit-keyframes icon-cancel-plain{100%{-webkit-mask-image:var(--icon-x-16);mask-image:var(--icon-x-16);background-color:var(--icon-color,var(--color-cancel-plain-500,currentColor))}}@keyframes icon-cancel-plain{100%{-webkit-mask-image:var(--icon-x-16);mask-image:var(--icon-x-16);background-color:var(--icon-color,var(--color-cancel-plain-500,currentColor))}}.search-bar-status li:not(.remove-all) button::before{--icon-name:icon-cancel-plain;content:""}@-webkit-keyframes icon-cancel-square-fill{100%{-webkit-mask-image:var(--icon-x-square-fill-16);mask-image:var(--icon-x-square-fill-16);background-color:var(--icon-color,var(--color-cancel-square-fill-500,currentColor))}}@keyframes icon-cancel-square-fill{100%{-webkit-mask-image:var(--icon-x-square-fill-16);mask-image:var(--icon-x-square-fill-16);background-color:var(--icon-color,var(--color-cancel-square-fill-500,currentColor))}}#downstream-container .topology-metrics-card div .critical::before,#upstream-container .topology-metrics-card div .critical::before,.consul-exposed-path-list>ul>li>.detail dl.critical dt::before,.consul-exposed-path-list>ul>li>.header .critical dd::before,.consul-health-check-list .critical.health-check-output::before,.consul-instance-checks.critical dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.critical dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .critical dd::before,.consul-upstream-instance-list li>.detail dl.critical dt::before,.consul-upstream-instance-list li>.header .critical dd::before,.has-error>strong::before,.list-collection>ul>li:not(:first-child)>.detail dl.critical dt::before,.list-collection>ul>li:not(:first-child)>.header .critical dd::before,.popover-select .value-critical button::before,.topology-metrics-popover.deny .tippy-arrow::after,.topology-metrics-popover.deny>button::before{--icon-name:icon-cancel-square-fill;content:""}@-webkit-keyframes icon-check-plain{100%{-webkit-mask-image:var(--icon-check-16);mask-image:var(--icon-check-16);background-color:var(--icon-color,var(--color-check-plain-500,currentColor))}}@keyframes icon-check-plain{100%{-webkit-mask-image:var(--icon-check-16);mask-image:var(--icon-check-16);background-color:var(--icon-color,var(--color-check-plain-500,currentColor))}}.disclosure-menu [aria-expanded]~*>ul>li.is-active>::after,.disclosure-menu [aria-expanded]~*>ul>li[aria-checked]>::after,.disclosure-menu [aria-expanded]~*>ul>li[aria-current]>::after,.disclosure-menu [aria-expanded]~*>ul>li[aria-selected]>::after,.menu-panel>ul>li.is-active>::after,.menu-panel>ul>li[aria-checked]>::after,.menu-panel>ul>li[aria-current]>::after,.menu-panel>ul>li[aria-selected]>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li.is-active>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li[aria-checked]>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li[aria-current]>::after,.more-popover-menu>[type=checkbox]+label+div>ul>li[aria-selected]>::after,.popover-menu>[type=checkbox]+label+div>ul>li.is-active>::after,.popover-menu>[type=checkbox]+label+div>ul>li[aria-checked]>::after,.popover-menu>[type=checkbox]+label+div>ul>li[aria-current]>::after,.popover-menu>[type=checkbox]+label+div>ul>li[aria-selected]>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.is-active>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li[aria-checked]>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li[aria-current]>::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li[aria-selected]>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.is-active>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li[aria-checked]>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li[aria-current]>::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li[aria-selected]>::after{--icon-name:icon-check-plain;content:""}@-webkit-keyframes icon-chevron-down{100%{-webkit-mask-image:var(--icon-chevron-down-16);mask-image:var(--icon-chevron-down-16);background-color:var(--icon-color,var(--color-chevron-down-500,currentColor))}}@keyframes icon-chevron-down{100%{-webkit-mask-image:var(--icon-chevron-down-16);mask-image:var(--icon-chevron-down-16);background-color:var(--icon-color,var(--color-chevron-down-500,currentColor))}}.hashicorp-consul nav li.nspaces .disclosure-menu>button::after,.hashicorp-consul nav li.partitions .disclosure-menu>button::after,.list-collection>button.closed::after,.more-popover-menu>[type=checkbox]+label>::after,.popover-menu>[type=checkbox]+label>::after,.topology-notices button::before,table.has-actions tr>.actions>[type=checkbox]+label>::after,table.with-details td:only-child>div>label::before,table.with-details td>label::before,table.with-details tr>.actions>[type=checkbox]+label>::after{--icon-name:icon-chevron-down;content:""}@-webkit-keyframes icon-copy-action{100%{-webkit-mask-image:var(--icon-clipboard-copy-16);mask-image:var(--icon-clipboard-copy-16);background-color:var(--icon-color,var(--color-copy-action-500,currentColor))}}@keyframes icon-copy-action{100%{-webkit-mask-image:var(--icon-clipboard-copy-16);mask-image:var(--icon-clipboard-copy-16);background-color:var(--icon-color,var(--color-copy-action-500,currentColor))}}.copy-button button::before{--icon-name:icon-copy-action;content:"";--icon-color:var(--token-color-foreground-faint)}@-webkit-keyframes icon-deny-alt{100%{-webkit-mask-image:var(--icon-skip-16);mask-image:var(--icon-skip-16);background-color:var(--icon-color,var(--color-deny-alt-500,currentColor))}}@keyframes icon-deny-alt{100%{-webkit-mask-image:var(--icon-skip-16);mask-image:var(--icon-skip-16);background-color:var(--icon-color,var(--color-deny-alt-500,currentColor))}}@-webkit-keyframes icon-deny-default{100%{-webkit-mask-image:var(--icon-skip-16);mask-image:var(--icon-skip-16);background-color:var(--icon-color,var(--color-deny-default-500,currentColor))}}@keyframes icon-deny-default{100%{-webkit-mask-image:var(--icon-skip-16);mask-image:var(--icon-skip-16);background-color:var(--icon-color,var(--color-deny-default-500,currentColor))}}@-webkit-keyframes icon-disabled{100%{-webkit-mask-image:var(--icon-skip-16);mask-image:var(--icon-skip-16);background-color:var(--icon-color,var(--color-disabled-500,currentColor))}}@keyframes icon-disabled{100%{-webkit-mask-image:var(--icon-skip-16);mask-image:var(--icon-skip-16);background-color:var(--icon-color,var(--color-disabled-500,currentColor))}}.status-403.empty-state header::before{--icon-name:icon-disabled;content:""}@-webkit-keyframes icon-docs{100%{-webkit-mask-image:var(--icon-docs-16);mask-image:var(--icon-docs-16);background-color:var(--icon-color,var(--color-docs-500,currentColor))}}@keyframes icon-docs{100%{-webkit-mask-image:var(--icon-docs-16);mask-image:var(--icon-docs-16);background-color:var(--icon-color,var(--color-docs-500,currentColor))}}#metrics-container .link .config-link::before,.empty-state .docs-link>::after,.hashicorp-consul .docs-link a::after{--icon-name:icon-docs;content:""}@-webkit-keyframes icon-exit{100%{-webkit-mask-image:var(--icon-external-link-16);mask-image:var(--icon-external-link-16);background-color:var(--icon-color,var(--color-exit-500,currentColor))}}@keyframes icon-exit{100%{-webkit-mask-image:var(--icon-external-link-16);mask-image:var(--icon-external-link-16);background-color:var(--icon-color,var(--color-exit-500,currentColor))}}#metrics-container .link .metrics-link::before,a[rel*=external]::after{--icon-name:icon-exit;content:""}@-webkit-keyframes icon-file-fill{100%{-webkit-mask-image:var(--icon-file-16);mask-image:var(--icon-file-16);background-color:var(--icon-color,var(--color-file-fill-500,currentColor))}}@keyframes icon-file-fill{100%{-webkit-mask-image:var(--icon-file-16);mask-image:var(--icon-file-16);background-color:var(--icon-color,var(--color-file-fill-500,currentColor))}}@-webkit-keyframes icon-folder-outline{100%{-webkit-mask-image:var(--icon-folder-16);mask-image:var(--icon-folder-16);background-color:var(--icon-color,var(--color-folder-outline-500,currentColor))}}@keyframes icon-folder-outline{100%{-webkit-mask-image:var(--icon-folder-16);mask-image:var(--icon-folder-16);background-color:var(--icon-color,var(--color-folder-outline-500,currentColor))}}#downstream-container .topology-metrics-card div .nspace dt::before,#upstream-container .topology-metrics-card div .nspace dt::before,.consul-bucket-list .nspace::before,.consul-exposed-path-list>ul>li>.detail dl.nspace dt::before,.consul-intention-list span[class|=nspace]::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.nspace dt::before,.consul-upstream-instance-list dl.nspace dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.nspace dt::before,.modal-dialog [role=document] table td.folder::before,main table td.folder::before{--icon-name:icon-folder-outline;content:""}@-webkit-keyframes icon-health{100%{-webkit-mask-image:var(--icon-activity-16);mask-image:var(--icon-activity-16);background-color:var(--icon-color,var(--color-health-500,currentColor))}}@keyframes icon-health{100%{-webkit-mask-image:var(--icon-activity-16);mask-image:var(--icon-activity-16);background-color:var(--icon-color,var(--color-health-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.checks dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.checks dt::before,.consul-upstream-instance-list li>.detail dl.checks dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.checks dt::before{--icon-name:icon-health;content:""}@-webkit-keyframes icon-help-circle-outline{100%{-webkit-mask-image:var(--icon-help-16);mask-image:var(--icon-help-16);background-color:var(--icon-color,var(--color-help-circle-outline-500,currentColor))}}@keyframes icon-help-circle-outline{100%{-webkit-mask-image:var(--icon-help-16);mask-image:var(--icon-help-16);background-color:var(--icon-color,var(--color-help-circle-outline-500,currentColor))}}#downstream-container .topology-metrics-card div .health dt::before,#upstream-container .topology-metrics-card div .health dt::before,.consul-exposed-path-list>ul>li>.detail dl.unknown dt::before,.consul-exposed-path-list>ul>li>.header .unknown dd::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.unknown dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .unknown dd::before,.consul-upstream-instance-list li>.detail dl.unknown dt::before,.consul-upstream-instance-list li>.header .unknown dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.unknown dt::before,.list-collection>ul>li:not(:first-child)>.header .unknown dd::before,.popover-select .value-unknown button::before,.status-404.empty-state header::before{--icon-name:icon-help-circle-outline;content:""}@-webkit-keyframes icon-info-circle-fill{100%{-webkit-mask-image:var(--icon-info-16);mask-image:var(--icon-info-16);background-color:var(--icon-color,var(--color-info-circle-fill-500,currentColor))}}@keyframes icon-info-circle-fill{100%{-webkit-mask-image:var(--icon-info-16);mask-image:var(--icon-info-16);background-color:var(--icon-color,var(--color-info-circle-fill-500,currentColor))}}#metrics-container:hover .sparkline-key-link::before,.info.informed-action header::before,.sparkline-key h3::before{--icon-name:icon-info-circle-fill;content:""}@-webkit-keyframes icon-info-circle-outline{100%{-webkit-mask-image:var(--icon-info-16);mask-image:var(--icon-info-16);background-color:var(--icon-color,var(--color-info-circle-outline-500,currentColor))}}@keyframes icon-info-circle-outline{100%{-webkit-mask-image:var(--icon-info-16);mask-image:var(--icon-info-16);background-color:var(--icon-color,var(--color-info-circle-outline-500,currentColor))}}#downstream-container>div:first-child span::before,.consul-auth-method-binding-list dl dt.type+dd span::before,.consul-auth-method-view dl dt.type+dd span::before,.consul-exposed-path-list>ul>li>.detail dl.behavior dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.behavior dt::before,.consul-upstream-instance-list li>.detail dl.behavior dt::before,.discovery-chain .resolvers>header span::after,.discovery-chain .routes>header span::after,.discovery-chain .splitters>header span::after,.list-collection>ul>li:not(:first-child)>.detail dl.behavior dt::before,.modal-dialog [role=document] a[rel*=help]::after,.modal-dialog [role=document] table th span::after,.topology-metrics-status-error span::before,.topology-metrics-status-loader span::before,main a[rel*=help]::after,main table th span::after{--icon-name:icon-info-circle-outline;content:""}@-webkit-keyframes icon-learn{100%{-webkit-mask-image:var(--icon-learn-16);mask-image:var(--icon-learn-16);background-color:var(--icon-color,var(--color-learn-500,currentColor))}}@keyframes icon-learn{100%{-webkit-mask-image:var(--icon-learn-16);mask-image:var(--icon-learn-16);background-color:var(--icon-color,var(--color-learn-500,currentColor))}}.empty-state .learn-link>::after,.hashicorp-consul .learn-link a::after{--icon-name:icon-learn;content:""}@-webkit-keyframes icon-loading{100%{-webkit-mask-image:var(--icon-loading-16);mask-image:var(--icon-loading-16);background-color:var(--icon-color,var(--color-loading-500,currentColor))}}@-webkit-keyframes icon-logo-github-monochrome{100%{-webkit-mask-image:var(--icon-github-color-16);mask-image:var(--icon-github-color-16);background-color:var(--icon-color,var(--color-logo-github-monochrome-500,currentColor))}}@keyframes icon-logo-github-monochrome{100%{-webkit-mask-image:var(--icon-github-color-16);mask-image:var(--icon-github-color-16);background-color:var(--icon-color,var(--color-logo-github-monochrome-500,currentColor))}}.hashicorp-consul .feedback-link a::after{--icon-name:icon-logo-github-monochrome;content:""}@-webkit-keyframes icon-logo-google-color{100%{background-image:var(--icon-google-color-16)}}@keyframes icon-logo-google-color{100%{background-image:var(--icon-google-color-16)}}.oidc-select .google-oidc-provider::before{--icon-name:icon-logo-google-color;content:""}@-webkit-keyframes icon-logo-kubernetes-color{100%{background-image:var(--icon-kubernetes-color-16)}}@keyframes icon-logo-kubernetes-color{100%{background-image:var(--icon-kubernetes-color-16)}}@-webkit-keyframes icon-menu{100%{-webkit-mask-image:var(--icon-menu-16);mask-image:var(--icon-menu-16);background-color:var(--icon-color,var(--color-menu-500,currentColor))}}@keyframes icon-menu{100%{-webkit-mask-image:var(--icon-menu-16);mask-image:var(--icon-menu-16);background-color:var(--icon-color,var(--color-menu-500,currentColor))}}@-webkit-keyframes icon-minus-square-fill{100%{-webkit-mask-image:var(--icon-minus-square-16);mask-image:var(--icon-minus-square-16);background-color:var(--icon-color,var(--color-minus-square-fill-500,currentColor))}}@keyframes icon-minus-square-fill{100%{-webkit-mask-image:var(--icon-minus-square-16);mask-image:var(--icon-minus-square-16);background-color:var(--icon-color,var(--color-minus-square-fill-500,currentColor))}}#downstream-container .topology-metrics-card div .empty::before,#upstream-container .topology-metrics-card div .empty::before,.consul-exposed-path-list>ul>li>.detail dl.empty dt::before,.consul-exposed-path-list>ul>li>.header .empty dd::before,.consul-instance-checks.empty dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.empty dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .empty dd::before,.consul-upstream-instance-list li>.detail dl.empty dt::before,.consul-upstream-instance-list li>.header .empty dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.empty dt::before,.list-collection>ul>li:not(:first-child)>.header .empty dd::before,.popover-select .value-empty button::before{--icon-name:icon-minus-square-fill;content:""}@-webkit-keyframes icon-more-horizontal{100%{-webkit-mask-image:var(--icon-more-horizontal-16);mask-image:var(--icon-more-horizontal-16);background-color:var(--icon-color,var(--color-more-horizontal-500,currentColor))}}@keyframes icon-more-horizontal{100%{-webkit-mask-image:var(--icon-more-horizontal-16);mask-image:var(--icon-more-horizontal-16);background-color:var(--icon-color,var(--color-more-horizontal-500,currentColor))}}@-webkit-keyframes icon-public-default{100%{-webkit-mask-image:var(--icon-globe-16);mask-image:var(--icon-globe-16);background-color:var(--icon-color,var(--color-public-default-500,currentColor))}}@keyframes icon-public-default{100%{-webkit-mask-image:var(--icon-globe-16);mask-image:var(--icon-globe-16);background-color:var(--icon-color,var(--color-public-default-500,currentColor))}}.consul-auth-method-list ul .locality::before,.consul-exposed-path-list>ul>li>.detail dl.address dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.address dt::before,.consul-upstream-instance-list li>.detail dl.address dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.address dt::before{--icon-name:icon-public-default;content:""}@-webkit-keyframes icon-search{100%{-webkit-mask-image:var(--icon-search-16);mask-image:var(--icon-search-16);background-color:var(--icon-color,var(--color-search-500,currentColor))}}@keyframes icon-search{100%{-webkit-mask-image:var(--icon-search-16);mask-image:var(--icon-search-16);background-color:var(--icon-color,var(--color-search-500,currentColor))}}@-webkit-keyframes icon-star-outline{100%{-webkit-mask-image:var(--icon-star-16);mask-image:var(--icon-star-16);background-color:var(--icon-color,var(--color-star-outline-500,currentColor))}}@keyframes icon-star-outline{100%{-webkit-mask-image:var(--icon-star-16);mask-image:var(--icon-star-16);background-color:var(--icon-color,var(--color-star-outline-500,currentColor))}}.leader::before{--icon-name:icon-star-outline;content:""}@-webkit-keyframes icon-user-organization{100%{-webkit-mask-image:var(--icon-org-16);mask-image:var(--icon-org-16);background-color:var(--icon-color,var(--color-user-organization-500,currentColor))}}@keyframes icon-user-organization{100%{-webkit-mask-image:var(--icon-org-16);mask-image:var(--icon-org-16);background-color:var(--icon-color,var(--color-user-organization-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.datacenter dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.datacenter dt::before,.consul-upstream-instance-list dl.datacenter dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.datacenter dt::before{--icon-name:icon-user-organization;content:""}@-webkit-keyframes icon-user-plain{100%{-webkit-mask-image:var(--icon-user-16);mask-image:var(--icon-user-16);background-color:var(--icon-color,var(--color-user-plain-500,currentColor))}}@keyframes icon-user-plain{100%{-webkit-mask-image:var(--icon-user-16);mask-image:var(--icon-user-16);background-color:var(--icon-color,var(--color-user-plain-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail .role::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .role::before,.consul-upstream-instance-list li>.detail .role::before,.list-collection>ul>li:not(:first-child)>.detail .role::before{--icon-name:icon-user-plain;content:""}@-webkit-keyframes icon-user-team{100%{-webkit-mask-image:var(--icon-users-16);mask-image:var(--icon-users-16);background-color:var(--icon-color,var(--color-user-team-500,currentColor))}}@keyframes icon-user-team{100%{-webkit-mask-image:var(--icon-users-16);mask-image:var(--icon-users-16);background-color:var(--icon-color,var(--color-user-team-500,currentColor))}}#downstream-container .topology-metrics-card div .partition dt::before,#upstream-container .topology-metrics-card div .partition dt::before,.consul-bucket-list .partition::before,.consul-intention-list span[class|=partition]::before,.consul-upstream-instance-list dl.partition dt::before,.consul-upstream-list dl.partition dt::before,.type-source.popover-select li.partition button::before{--icon-name:icon-user-team;content:""}@-webkit-keyframes icon-alert-circle{100%{-webkit-mask-image:var(--icon-alert-circle-16);mask-image:var(--icon-alert-circle-16);background-color:var(--icon-color,var(--color-alert-circle-500,currentColor))}}@keyframes icon-alert-circle{100%{-webkit-mask-image:var(--icon-alert-circle-16);mask-image:var(--icon-alert-circle-16);background-color:var(--icon-color,var(--color-alert-circle-500,currentColor))}}@-webkit-keyframes icon-check{100%{-webkit-mask-image:var(--icon-check-16);mask-image:var(--icon-check-16);background-color:var(--icon-color,var(--color-check-500,currentColor))}}@keyframes icon-check{100%{-webkit-mask-image:var(--icon-check-16);mask-image:var(--icon-check-16);background-color:var(--icon-color,var(--color-check-500,currentColor))}}@-webkit-keyframes icon-check-circle{100%{-webkit-mask-image:var(--icon-check-circle-16);mask-image:var(--icon-check-circle-16);background-color:var(--icon-color,var(--color-check-circle-500,currentColor))}}@keyframes icon-check-circle{100%{-webkit-mask-image:var(--icon-check-circle-16);mask-image:var(--icon-check-circle-16);background-color:var(--icon-color,var(--color-check-circle-500,currentColor))}}@-webkit-keyframes icon-check-circle-fill{100%{-webkit-mask-image:var(--icon-check-circle-fill-16);mask-image:var(--icon-check-circle-fill-16);background-color:var(--icon-color,var(--color-check-circle-fill-500,currentColor))}}@keyframes icon-check-circle-fill{100%{-webkit-mask-image:var(--icon-check-circle-fill-16);mask-image:var(--icon-check-circle-fill-16);background-color:var(--icon-color,var(--color-check-circle-fill-500,currentColor))}}#downstream-container .topology-metrics-card div .passing::before,#upstream-container .topology-metrics-card div .passing::before,.consul-exposed-path-list>ul>li>.detail dl.passing dt::before,.consul-exposed-path-list>ul>li>.header .passing dd::before,.consul-exposed-path-list>ul>li>.header [rel=me] dd::before,.consul-health-check-list .passing.health-check-output::before,.consul-instance-checks.passing dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.passing dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .passing dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header [rel=me] dd::before,.consul-upstream-instance-list li>.detail dl.passing dt::before,.consul-upstream-instance-list li>.header .passing dd::before,.consul-upstream-instance-list li>.header [rel=me] dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.passing dt::before,.list-collection>ul>li:not(:first-child)>.header .passing dd::before,.list-collection>ul>li:not(:first-child)>.header [rel=me] dd::before,.popover-select .value-passing button::before{--icon-name:icon-check-circle-fill;content:""}@-webkit-keyframes icon-chevron-left{100%{-webkit-mask-image:var(--icon-chevron-left-16);mask-image:var(--icon-chevron-left-16);background-color:var(--icon-color,var(--color-chevron-left-500,currentColor))}}@keyframes icon-chevron-left{100%{-webkit-mask-image:var(--icon-chevron-left-16);mask-image:var(--icon-chevron-left-16);background-color:var(--icon-color,var(--color-chevron-left-500,currentColor))}}.empty-state .back-link>::after,main header nav:first-child ol li:first-child a::before{--icon-name:icon-chevron-left;content:""}@-webkit-keyframes icon-chevron-right{100%{-webkit-mask-image:var(--icon-chevron-right-16);mask-image:var(--icon-chevron-right-16);background-color:var(--icon-color,var(--color-chevron-right-500,currentColor))}}@keyframes icon-chevron-right{100%{-webkit-mask-image:var(--icon-chevron-right-16);mask-image:var(--icon-chevron-right-16);background-color:var(--icon-color,var(--color-chevron-right-500,currentColor))}}#login-toggle+div footer button::after{--icon-name:icon-chevron-right;content:""}@-webkit-keyframes icon-chevron-up{100%{-webkit-mask-image:var(--icon-chevron-up-16);mask-image:var(--icon-chevron-up-16);background-color:var(--icon-color,var(--color-chevron-up-500,currentColor))}}@keyframes icon-chevron-up{100%{-webkit-mask-image:var(--icon-chevron-up-16);mask-image:var(--icon-chevron-up-16);background-color:var(--icon-color,var(--color-chevron-up-500,currentColor))}}.hashicorp-consul nav li.nspaces .disclosure-menu>button[aria-expanded=true]::after,.hashicorp-consul nav li.partitions .disclosure-menu>button[aria-expanded=true]::after,.list-collection>button::after,.more-popover-menu>[type=checkbox]:checked+label>::after,.popover-menu>[type=checkbox]:checked+label>::after,.topology-notices button[aria-expanded=true]::before,table.has-actions tr>.actions>[type=checkbox]:checked+label>::after,table.with-details tr>.actions>[type=checkbox]:checked+label>::after{--icon-name:icon-chevron-up;content:""}@-webkit-keyframes icon-delay{100%{-webkit-mask-image:var(--icon-delay-16);mask-image:var(--icon-delay-16);background-color:var(--icon-color,var(--color-delay-500,currentColor))}}@keyframes icon-delay{100%{-webkit-mask-image:var(--icon-delay-16);mask-image:var(--icon-delay-16);background-color:var(--icon-color,var(--color-delay-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.lock-delay dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.lock-delay dt::before,.consul-upstream-instance-list li>.detail dl.lock-delay dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.lock-delay dt::before{--icon-name:icon-delay;content:""}@-webkit-keyframes icon-docs-link{100%{-webkit-mask-image:var(--icon-docs-link-16);mask-image:var(--icon-docs-link-16);background-color:var(--icon-color,var(--color-docs-link-500,currentColor))}}@keyframes icon-docs-link{100%{-webkit-mask-image:var(--icon-docs-link-16);mask-image:var(--icon-docs-link-16);background-color:var(--icon-color,var(--color-docs-link-500,currentColor))}}@-webkit-keyframes icon-eye{100%{-webkit-mask-image:var(--icon-eye-16);mask-image:var(--icon-eye-16);background-color:var(--icon-color,var(--color-eye-500,currentColor))}}@keyframes icon-eye{100%{-webkit-mask-image:var(--icon-eye-16);mask-image:var(--icon-eye-16);background-color:var(--icon-color,var(--color-eye-500,currentColor))}}@-webkit-keyframes icon-eye-off{100%{-webkit-mask-image:var(--icon-eye-off-16);mask-image:var(--icon-eye-off-16);background-color:var(--icon-color,var(--color-eye-off-500,currentColor))}}@keyframes icon-eye-off{100%{-webkit-mask-image:var(--icon-eye-off-16);mask-image:var(--icon-eye-off-16);background-color:var(--icon-color,var(--color-eye-off-500,currentColor))}}@-webkit-keyframes icon-file-text{100%{-webkit-mask-image:var(--icon-file-text-16);mask-image:var(--icon-file-text-16);background-color:var(--icon-color,var(--color-file-text-500,currentColor))}}@keyframes icon-file-text{100%{-webkit-mask-image:var(--icon-file-text-16);mask-image:var(--icon-file-text-16);background-color:var(--icon-color,var(--color-file-text-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail .policy::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .policy::before,.consul-upstream-instance-list li>.detail .policy::before,.list-collection>ul>li:not(:first-child)>.detail .policy::before{--icon-name:icon-file-text;content:""}@-webkit-keyframes icon-gateway{100%{-webkit-mask-image:var(--icon-gateway-16);mask-image:var(--icon-gateway-16);background-color:var(--icon-color,var(--color-gateway-500,currentColor))}}@keyframes icon-gateway{100%{-webkit-mask-image:var(--icon-gateway-16);mask-image:var(--icon-gateway-16);background-color:var(--icon-color,var(--color-gateway-500,currentColor))}}.consul-kind::before{--icon-name:icon-gateway;content:""}@-webkit-keyframes icon-git-commit{100%{-webkit-mask-image:var(--icon-git-commit-16);mask-image:var(--icon-git-commit-16);background-color:var(--icon-color,var(--color-git-commit-500,currentColor))}}@keyframes icon-git-commit{100%{-webkit-mask-image:var(--icon-git-commit-16);mask-image:var(--icon-git-commit-16);background-color:var(--icon-color,var(--color-git-commit-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.node dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.node dt::before,.consul-upstream-instance-list li>.detail dl.node dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.node dt::before{--icon-name:icon-git-commit;content:""}@-webkit-keyframes icon-hexagon{100%{-webkit-mask-image:var(--icon-hexagon-16);mask-image:var(--icon-hexagon-16);background-color:var(--icon-color,var(--color-hexagon-500,currentColor))}}@keyframes icon-hexagon{100%{-webkit-mask-image:var(--icon-hexagon-16);mask-image:var(--icon-hexagon-16);background-color:var(--icon-color,var(--color-hexagon-500,currentColor))}}@-webkit-keyframes icon-history{100%{-webkit-mask-image:var(--icon-history-16);mask-image:var(--icon-history-16);background-color:var(--icon-color,var(--color-history-500,currentColor))}}@keyframes icon-history{100%{-webkit-mask-image:var(--icon-history-16);mask-image:var(--icon-history-16);background-color:var(--icon-color,var(--color-history-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.ttl dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.ttl dt::before,.consul-upstream-instance-list li>.detail dl.ttl dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.ttl dt::before{--icon-name:icon-history;content:""}@-webkit-keyframes icon-info{100%{-webkit-mask-image:var(--icon-info-16);mask-image:var(--icon-info-16);background-color:var(--icon-color,var(--color-info-500,currentColor))}}@keyframes icon-info{100%{-webkit-mask-image:var(--icon-info-16);mask-image:var(--icon-info-16);background-color:var(--icon-color,var(--color-info-500,currentColor))}}@-webkit-keyframes icon-layers{100%{-webkit-mask-image:var(--icon-layers-16);mask-image:var(--icon-layers-16);background-color:var(--icon-color,var(--color-layers-500,currentColor))}}@keyframes icon-layers{100%{-webkit-mask-image:var(--icon-layers-16);mask-image:var(--icon-layers-16);background-color:var(--icon-color,var(--color-layers-500,currentColor))}}.topology-metrics-popover.l7 .tippy-arrow::after,.topology-metrics-popover.l7>button::before{--icon-name:icon-layers;content:"";--icon-color:var(--token-color-palette-neutral-300)}@keyframes icon-loading{100%{-webkit-mask-image:var(--icon-loading-16);mask-image:var(--icon-loading-16);background-color:var(--icon-color,var(--color-loading-500,currentColor))}}@-webkit-keyframes icon-network-alt{100%{-webkit-mask-image:var(--icon-network-alt-16);mask-image:var(--icon-network-alt-16);background-color:var(--icon-color,var(--color-network-alt-500,currentColor))}}@keyframes icon-network-alt{100%{-webkit-mask-image:var(--icon-network-alt-16);mask-image:var(--icon-network-alt-16);background-color:var(--icon-color,var(--color-network-alt-500,currentColor))}}.consul-bucket-list .peer::before{--icon-name:icon-network-alt;content:""}@-webkit-keyframes icon-path{100%{-webkit-mask-image:var(--icon-path-16);mask-image:var(--icon-path-16);background-color:var(--icon-color,var(--color-path-500,currentColor))}}@keyframes icon-path{100%{-webkit-mask-image:var(--icon-path-16);mask-image:var(--icon-path-16);background-color:var(--icon-color,var(--color-path-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.path dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.path dt::before,.consul-upstream-instance-list li>.detail dl.path dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.path dt::before{--icon-name:icon-path;content:""}@-webkit-keyframes icon-running{100%{-webkit-mask-image:var(--icon-running-16);mask-image:var(--icon-running-16);background-color:var(--icon-color,var(--color-running-500,currentColor))}}@keyframes icon-running{100%{-webkit-mask-image:var(--icon-running-16);mask-image:var(--icon-running-16);background-color:var(--icon-color,var(--color-running-500,currentColor))}}@-webkit-keyframes icon-skip{100%{-webkit-mask-image:var(--icon-skip-16);mask-image:var(--icon-skip-16);background-color:var(--icon-color,var(--color-skip-500,currentColor))}}@keyframes icon-skip{100%{-webkit-mask-image:var(--icon-skip-16);mask-image:var(--icon-skip-16);background-color:var(--icon-color,var(--color-skip-500,currentColor))}}@-webkit-keyframes icon-socket{100%{-webkit-mask-image:var(--icon-socket-16);mask-image:var(--icon-socket-16);background-color:var(--icon-color,var(--color-socket-500,currentColor))}}@keyframes icon-socket{100%{-webkit-mask-image:var(--icon-socket-16);mask-image:var(--icon-socket-16);background-color:var(--icon-color,var(--color-socket-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.socket dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.socket dt::before,.consul-upstream-instance-list li>.detail dl.socket dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.socket dt::before{--icon-name:icon-socket;content:""}@-webkit-keyframes icon-star-circle{100%{-webkit-mask-image:var(--icon-star-circle-16);mask-image:var(--icon-star-circle-16);background-color:var(--icon-color,var(--color-star-circle-500,currentColor))}}@keyframes icon-star-circle{100%{-webkit-mask-image:var(--icon-star-circle-16);mask-image:var(--icon-star-circle-16);background-color:var(--icon-color,var(--color-star-circle-500,currentColor))}}@-webkit-keyframes icon-star-fill{100%{-webkit-mask-image:var(--icon-star-fill-16);mask-image:var(--icon-star-fill-16);background-color:var(--icon-color,var(--color-star-fill-500,currentColor))}}@keyframes icon-star-fill{100%{-webkit-mask-image:var(--icon-star-fill-16);mask-image:var(--icon-star-fill-16);background-color:var(--icon-color,var(--color-star-fill-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail .policy-management::before,.consul-exposed-path-list>ul>li>.header .policy-management dd::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .policy-management::before,.consul-lock-session-list ul>li:not(:first-child)>.header .policy-management dd::before,.consul-upstream-instance-list li>.detail .policy-management::before,.consul-upstream-instance-list li>.header .policy-management dd::before,.list-collection>ul>li:not(:first-child)>.detail .policy-management::before,.list-collection>ul>li:not(:first-child)>.header .policy-management dd::before{--icon-name:icon-star-fill;content:"";--icon-color:var(--token-color-consul-brand)}@-webkit-keyframes icon-tag{100%{-webkit-mask-image:var(--icon-tag-16);mask-image:var(--icon-tag-16);background-color:var(--icon-color,var(--color-tag-500,currentColor))}}@keyframes icon-tag{100%{-webkit-mask-image:var(--icon-tag-16);mask-image:var(--icon-tag-16);background-color:var(--icon-color,var(--color-tag-500,currentColor))}}.tag-list dt::before,td.tags dt::before{--icon-name:icon-tag;content:""}@-webkit-keyframes icon-x{100%{-webkit-mask-image:var(--icon-x-16);mask-image:var(--icon-x-16);background-color:var(--icon-color,var(--color-x-500,currentColor))}}@keyframes icon-x{100%{-webkit-mask-image:var(--icon-x-16);mask-image:var(--icon-x-16);background-color:var(--icon-color,var(--color-x-500,currentColor))}}@-webkit-keyframes icon-x-circle{100%{-webkit-mask-image:var(--icon-x-circle-16);mask-image:var(--icon-x-circle-16);background-color:var(--icon-color,var(--color-x-circle-500,currentColor))}}@keyframes icon-x-circle{100%{-webkit-mask-image:var(--icon-x-circle-16);mask-image:var(--icon-x-circle-16);background-color:var(--icon-color,var(--color-x-circle-500,currentColor))}}@-webkit-keyframes icon-x-square{100%{-webkit-mask-image:var(--icon-x-square-16);mask-image:var(--icon-x-square-16);background-color:var(--icon-color,var(--color-x-square-500,currentColor))}}@keyframes icon-x-square{100%{-webkit-mask-image:var(--icon-x-square-16);mask-image:var(--icon-x-square-16);background-color:var(--icon-color,var(--color-x-square-500,currentColor))}}@-webkit-keyframes icon-cloud-cross{100%{-webkit-mask-image:var(--icon-cloud-cross-16);mask-image:var(--icon-cloud-cross-16);background-color:var(--icon-color,var(--color-cloud-cross-500,currentColor))}}@keyframes icon-cloud-cross{100%{-webkit-mask-image:var(--icon-cloud-cross-16);mask-image:var(--icon-cloud-cross-16);background-color:var(--icon-color,var(--color-cloud-cross-500,currentColor))}}@-webkit-keyframes icon-loading-motion{100%{-webkit-mask-image:var(--icon-loading-motion-16);mask-image:var(--icon-loading-motion-16);background-color:var(--icon-color,var(--color-loading-motion-500,currentColor))}}@keyframes icon-loading-motion{100%{-webkit-mask-image:var(--icon-loading-motion-16);mask-image:var(--icon-loading-motion-16);background-color:var(--icon-color,var(--color-loading-motion-500,currentColor))}}@-webkit-keyframes icon-logo-auth0-color{100%{background-image:var(--icon-auth0-color-16)}}@keyframes icon-logo-auth0-color{100%{background-image:var(--icon-auth0-color-16)}}.oidc-select .auth0-oidc-provider::before{--icon-name:icon-logo-auth0-color;content:""}@-webkit-keyframes icon-logo-ember-circle-color{100%{background-image:var(--icon-logo-ember-circle-color-16)}}@keyframes icon-logo-ember-circle-color{100%{background-image:var(--icon-logo-ember-circle-color-16)}}@-webkit-keyframes icon-logo-glimmer-color{100%{background-image:var(--icon-logo-glimmer-color-16)}}@keyframes icon-logo-glimmer-color{100%{background-image:var(--icon-logo-glimmer-color-16)}}@-webkit-keyframes icon-logo-jwt-color{100%{background-image:var(--icon-logo-jwt-color-16)}}@keyframes icon-logo-jwt-color{100%{background-image:var(--icon-logo-jwt-color-16)}}.consul-external-source.jwt::before,.consul-health-check-list .health-check-output dd em.jwt::before,.consul-intention-list td strong.jwt::before,.consul-intention-permission-list strong.jwt::before,.consul-intention-search-bar li button span.jwt::before,.consul-peer-search-bar li button span.jwt::before,.consul-server-card .health-status+dd.jwt::before,.discovery-chain .route-card>header ul li.jwt::before,.hashicorp-consul nav .dcs .dc-name span.jwt::before,.hashicorp-consul nav .dcs li.is-local span.jwt::before,.hashicorp-consul nav .dcs li.is-primary span.jwt::before,.jwt.consul-auth-method-type::before,.jwt.consul-kind::before,.jwt.consul-source::before,.jwt.consul-transparent-proxy::before,.jwt.leader::before,.jwt.topology-metrics-source-type::before,.popover-select .jwt button::before,.search-bar-status li.jwt:not(.remove-all)::before,html[data-route^="dc.acls.index"] main td strong.jwt::before,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl.jwt::before,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em.jwt::before,span.jwt.policy-node-identity::before,span.jwt.policy-service-identity::before{--icon-name:icon-logo-jwt-color;content:""}@-webkit-keyframes icon-logo-microsoft-color{100%{background-image:var(--icon-microsoft-color-16)}}@keyframes icon-logo-microsoft-color{100%{background-image:var(--icon-microsoft-color-16)}}.oidc-select .microsoft-oidc-provider::before{--icon-name:icon-logo-microsoft-color;content:""}@-webkit-keyframes icon-logo-oidc-color{100%{background-image:var(--icon-logo-oidc-color-16)}}@keyframes icon-logo-oidc-color{100%{background-image:var(--icon-logo-oidc-color-16)}}.consul-external-source.oidc::before,.consul-health-check-list .health-check-output dd em.oidc::before,.consul-intention-list td strong.oidc::before,.consul-intention-permission-list strong.oidc::before,.consul-intention-search-bar li button span.oidc::before,.consul-peer-search-bar li button span.oidc::before,.consul-server-card .health-status+dd.oidc::before,.discovery-chain .route-card>header ul li.oidc::before,.hashicorp-consul nav .dcs .dc-name span.oidc::before,.hashicorp-consul nav .dcs li.is-local span.oidc::before,.hashicorp-consul nav .dcs li.is-primary span.oidc::before,.oidc.consul-auth-method-type::before,.oidc.consul-kind::before,.oidc.consul-source::before,.oidc.consul-transparent-proxy::before,.oidc.leader::before,.oidc.topology-metrics-source-type::before,.popover-select .oidc button::before,.search-bar-status li.oidc:not(.remove-all)::before,html[data-route^="dc.acls.index"] main td strong.oidc::before,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl.oidc::before,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em.oidc::before,span.oidc.policy-node-identity::before,span.oidc.policy-service-identity::before{--icon-name:icon-logo-oidc-color;content:""}@-webkit-keyframes icon-logo-okta-color{100%{background-image:var(--icon-okta-color-16)}}@keyframes icon-logo-okta-color{100%{background-image:var(--icon-okta-color-16)}}.oidc-select .okta-oidc-provider::before{--icon-name:icon-logo-okta-color;content:""}@-webkit-keyframes icon-mesh{100%{-webkit-mask-image:var(--icon-mesh-16);mask-image:var(--icon-mesh-16);background-color:var(--icon-color,var(--color-mesh-500,currentColor))}}@keyframes icon-mesh{100%{-webkit-mask-image:var(--icon-mesh-16);mask-image:var(--icon-mesh-16);background-color:var(--icon-color,var(--color-mesh-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.mesh dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.mesh dt::before,.consul-upstream-instance-list li>.detail dl.mesh dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.mesh dt::before{--icon-name:icon-mesh;content:""}@-webkit-keyframes icon-port{100%{-webkit-mask-image:var(--icon-port-16);mask-image:var(--icon-port-16);background-color:var(--icon-color,var(--color-port-500,currentColor))}}@keyframes icon-port{100%{-webkit-mask-image:var(--icon-port-16);mask-image:var(--icon-port-16);background-color:var(--icon-color,var(--color-port-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.port dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.port dt::before,.consul-upstream-instance-list li>.detail dl.port dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.port dt::before{--icon-name:icon-port;content:""}@-webkit-keyframes icon-protocol{100%{-webkit-mask-image:var(--icon-protocol-16);mask-image:var(--icon-protocol-16);background-color:var(--icon-color,var(--color-protocol-500,currentColor))}}@keyframes icon-protocol{100%{-webkit-mask-image:var(--icon-protocol-16);mask-image:var(--icon-protocol-16);background-color:var(--icon-color,var(--color-protocol-500,currentColor))}}.consul-exposed-path-list>ul>li>.detail dl.protocol dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.protocol dt::before,.consul-upstream-instance-list li>.detail dl.protocol dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.protocol dt::before{--icon-name:icon-protocol;content:""}@-webkit-keyframes icon-redirect{100%{-webkit-mask-image:var(--icon-redirect-16);mask-image:var(--icon-redirect-16);background-color:var(--icon-color,var(--color-redirect-500,currentColor))}}@keyframes icon-redirect{100%{-webkit-mask-image:var(--icon-redirect-16);mask-image:var(--icon-redirect-16);background-color:var(--icon-color,var(--color-redirect-500,currentColor))}}@-webkit-keyframes icon-search-color{100%{background-image:var(--icon-search-color-16)}}@keyframes icon-search-color{100%{background-image:var(--icon-search-color-16)}}[for=toolbar-toggle]{--icon-name:icon-search-color;content:""}@-webkit-keyframes icon-sort{100%{-webkit-mask-image:var(--icon-sort-desc-16);mask-image:var(--icon-sort-desc-16);background-color:var(--icon-color,var(--color-sort-500,currentColor))}}@keyframes icon-sort{100%{-webkit-mask-image:var(--icon-sort-desc-16);mask-image:var(--icon-sort-desc-16);background-color:var(--icon-color,var(--color-sort-500,currentColor))}}.type-sort.popover-select label>::before{--icon-name:icon-sort;content:""}@-webkit-keyframes icon-union{100%{-webkit-mask-image:var(--icon-union-16);mask-image:var(--icon-union-16);background-color:var(--icon-color,var(--color-union-500,currentColor))}}@keyframes icon-union{100%{-webkit-mask-image:var(--icon-union-16);mask-image:var(--icon-union-16);background-color:var(--icon-color,var(--color-union-500,currentColor))}}#downstream-container .topology-metrics-card .details .group span::before,#upstream-container .topology-metrics-card .details .group span::before{--icon-name:icon-union;content:""}.ember-basic-dropdown{position:relative}.ember-basic-dropdown,.ember-basic-dropdown-content,.ember-basic-dropdown-content *{box-sizing:border-box}.ember-basic-dropdown-content{position:absolute;width:auto;z-index:1000;background-color:#fff}.ember-basic-dropdown-content--left{left:0}.ember-basic-dropdown-content--right{right:0}.ember-basic-dropdown-overlay{position:fixed;background:rgba(0,0,0,.5);width:100%;height:100%;z-index:10;top:0;left:0;pointer-events:none}.ember-basic-dropdown-content-wormhole-origin{display:inline}.ember-power-select-dropdown *{box-sizing:border-box}.ember-power-select-trigger{position:relative;border-radius:4px;background-color:#fff;line-height:1.75;overflow-x:hidden;text-overflow:ellipsis;min-height:1.75em;-moz-user-select:none;user-select:none;-webkit-user-select:none;color:inherit}.ember-power-select-trigger:after{content:"";display:table;clear:both}.ember-power-select-trigger--active,.ember-power-select-trigger:focus{box-shadow:none}.ember-basic-dropdown-trigger--below.ember-power-select-trigger[aria-expanded=true],.ember-basic-dropdown-trigger--in-place.ember-power-select-trigger[aria-expanded=true]{border-bottom-left-radius:0;border-bottom-right-radius:0}.ember-basic-dropdown-trigger--above.ember-power-select-trigger[aria-expanded=true]{border-top-left-radius:0;border-top-right-radius:0}.ember-power-select-placeholder{color:#999;display:block;overflow-x:hidden;white-space:nowrap;text-overflow:ellipsis}.ember-power-select-status-icon{position:absolute;display:inline-block;width:0;height:0;top:0;bottom:0;margin:auto;border-style:solid;border-width:7px 4px 0;border-color:#aaa transparent transparent;right:5px}.ember-basic-dropdown-trigger[aria-expanded=true] .ember-power-select-status-icon{transform:rotate(180deg)}.ember-power-select-clear-btn{position:absolute;cursor:pointer;right:25px}.ember-power-select-trigger-multiple-input{font-family:inherit;font-size:inherit;border:none;display:inline-block;line-height:inherit;-webkit-appearance:none;outline:0;padding:0;float:left;background-color:transparent;text-indent:2px}.ember-power-select-trigger-multiple-input:disabled{background-color:#eee}.ember-power-select-trigger-multiple-input::placeholder{opacity:1;color:#999}.ember-power-select-trigger-multiple-input::-webkit-input-placeholder{opacity:1;color:#999}.ember-power-select-trigger-multiple-input::-moz-placeholder{opacity:1;color:#999}.ember-power-select-trigger-multiple-input::-ms-input-placeholder{opacity:1;color:#999}.active.discovery-chain [id*=":"],.discovery-chain path,.ember-power-select-multiple-remove-btn:not(:hover){opacity:.5}.ember-power-select-multiple-options{padding:0;margin:0}.ember-power-select-multiple-option{border:1px solid gray;border-radius:4px;color:#333;background-color:#e4e4e4;padding:0 4px;display:inline-block;line-height:1.45;float:left;margin:2px 0 2px 3px}.ember-power-select-multiple-remove-btn{cursor:pointer}.ember-power-select-search{padding:4px}.ember-power-select-search-input{border:1px solid #aaa;border-radius:0;width:100%;font-size:inherit;line-height:inherit;padding:0 5px}.ember-power-select-search-input:focus{border:1px solid #aaa;box-shadow:none}.ember-power-select-dropdown{border-left:1px solid #aaa;border-right:1px solid #aaa;line-height:1.75;border-radius:4px;box-shadow:none;overflow:hidden;color:inherit}.ember-power-select-dropdown.ember-basic-dropdown-content--above{border-top:1px solid #aaa;border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.ember-power-select-dropdown.ember-basic-dropdown-content--below,.ember-power-select-dropdown.ember-basic-dropdown-content--in-place{border-top:none;border-bottom:1px solid #aaa;border-top-left-radius:0;border-top-right-radius:0}.ember-power-select-dropdown.ember-basic-dropdown-content--in-place{width:100%}.ember-power-select-options{list-style:none;margin:0;padding:0;-moz-user-select:none;user-select:none;-webkit-user-select:none}.ember-power-select-placeholder,.ember-power-select-selected-item,a[rel*=external]::after{margin-left:8px}.ember-power-select-options[role=listbox]{overflow-y:auto;-webkit-overflow-scrolling:touch;max-height:12.25em}.ember-power-select-option{cursor:pointer;padding:0 8px}.ember-power-select-group[aria-disabled=true]{color:#999;cursor:not-allowed}.ember-power-select-group[aria-disabled=true] .ember-power-select-option,.ember-power-select-option[aria-disabled=true]{color:#999;pointer-events:none;cursor:not-allowed}.ember-power-select-option[aria-selected=true]{background-color:#ddd}.ember-power-select-option[aria-current=true]{background-color:#5897fb;color:#fff}.ember-power-select-group-name{cursor:default;font-weight:700}.ember-power-select-trigger[aria-disabled=true]{background-color:#eee}.ember-power-select-trigger{padding:0 16px 0 0}.ember-power-select-group .ember-power-select-group .ember-power-select-group-name{padding-left:24px}.ember-power-select-group .ember-power-select-group .ember-power-select-option{padding-left:40px}.ember-power-select-group .ember-power-select-option{padding-left:24px}.ember-power-select-group .ember-power-select-group-name{padding-left:8px}.ember-power-select-trigger[dir=rtl]{padding:0 0 0 16px}.ember-power-select-trigger[dir=rtl] .ember-power-select-placeholder,.ember-power-select-trigger[dir=rtl] .ember-power-select-selected-item{margin-right:8px}.ember-power-select-trigger[dir=rtl] .ember-power-select-multiple-option,.ember-power-select-trigger[dir=rtl] .ember-power-select-trigger-multiple-input{float:right}.ember-power-select-trigger[dir=rtl] .ember-power-select-status-icon{left:5px;right:initial}.ember-power-select-trigger[dir=rtl] .ember-power-select-clear-btn{left:25px;right:initial}.ember-power-select-dropdown[dir=rtl] .ember-power-select-group .ember-power-select-group .ember-power-select-group-name{padding-right:24px}.ember-power-select-dropdown[dir=rtl] .ember-power-select-group .ember-power-select-group .ember-power-select-option{padding-right:40px}.ember-power-select-dropdown[dir=rtl] .ember-power-select-group .ember-power-select-option{padding-right:24px}.ember-power-select-dropdown[dir=rtl] .ember-power-select-group .ember-power-select-group-name{padding-right:8px}#login-toggle+div footer button:focus,#login-toggle+div footer button:hover,.consul-intention-fieldsets .permissions>button:focus,.consul-intention-fieldsets .permissions>button:hover,.empty-state>ul>li>:focus,.empty-state>ul>li>:hover,.empty-state>ul>li>label>button:focus,.empty-state>ul>li>label>button:hover,.modal-dialog [role=document] dd a:focus,.modal-dialog [role=document] dd a:hover,.modal-dialog [role=document] p a:focus,.modal-dialog [role=document] p a:hover,.oidc-select button.reset:focus,.oidc-select button.reset:hover,.search-bar-status .remove-all button:focus,.search-bar-status .remove-all button:hover,main dd a:focus,main dd a:hover,main p a:focus,main p a:hover{text-decoration:underline}#login-toggle+div footer button,.consul-intention-fieldsets .permissions>button,.empty-state>ul>li>*,.empty-state>ul>li>:active,.empty-state>ul>li>:focus,.empty-state>ul>li>:hover,.empty-state>ul>li>label>button,.empty-state>ul>li>label>button:active,.empty-state>ul>li>label>button:focus,.empty-state>ul>li>label>button:hover,.modal-dialog [role=document] dd a,.modal-dialog [role=document] p a,.oidc-select button.reset,.search-bar-status .remove-all button,main dd a,main dd a:active,main dd a:focus,main dd a:hover,main p a,main p a:active,main p a:focus,main p a:hover{color:var(--token-color-foreground-action)}.modal-dialog [role=document] label a[rel*=help],div.with-confirmation p,main label a[rel*=help]{color:var(--token-color-foreground-disabled)}#login-toggle+div footer button,.consul-intention-fieldsets .permissions>button,.empty-state>ul>li>*,.empty-state>ul>li>label>button,.modal-dialog [role=document] dd a,.modal-dialog [role=document] p a,.oidc-select button.reset,.search-bar-status .remove-all button,main dd a,main p a{cursor:pointer;background-color:transparent}#login-toggle+div footer button:active,.consul-intention-fieldsets .permissions>button:active,.empty-state>ul>li>:active,.empty-state>ul>li>label>button:active,.modal-dialog [role=document] dd a:active,.modal-dialog [role=document] p a:active,.oidc-select button.reset:active,.search-bar-status .remove-all button:active,main dd a:active,main p a:active{outline:0}.modal-dialog [role=document] a[rel*=help]::after,main a[rel*=help]::after{opacity:.4}.modal-dialog [role=document] h2 a,main h2 a{color:var(--token-color-foreground-strong)}.modal-dialog [role=document] h2 a[rel*=help]::after,main h2 a[rel*=help]::after{font-size:.65em;margin-top:.2em;margin-left:.2em}.tab-section>p:only-child [rel*=help]::after{content:none}.auth-form{width:320px;margin:-20px 25px 0}.auth-form em{color:var(--token-color-foreground-faint);font-style:normal;display:inline-block;margin-top:1em}.auth-form .oidc-select,.auth-form form{padding-top:1em}.auth-form form{margin-bottom:0!important}.auth-form .ember-basic-dropdown-trigger,.auth-form button:not(.reset){width:100%}.auth-form .progress{margin:0 auto}#login-toggle+div footer button::after{font-size:120%;position:relative;top:-1px;left:-3px}#login-toggle+div footer{border-top:0;background-color:transparent;padding:10px 42px 20px}#login-toggle+div>div>div>div{padding-bottom:0}.auth-profile{padding:.9em 1em}.auth-profile dt span{font-weight:var(--typo-weight-normal)}.auth-profile dt{font-weight:var(--typo-weight-bold)}.auth-profile dd,.auth-profile dt{color:var(--token-color-paletter-neutral-300)}.auth-profile dt span,.empty-state,main header nav:first-child ol li a,main header nav:first-child ol li:not(:first-child) a::before{color:var(--token-color-foreground-faint)}main header nav:first-child ol li a{text-decoration:none}main header nav:first-child ol li a:hover{color:var(--token-color-foreground-action);text-decoration:underline}main header nav:first-child ol li a::before{text-decoration:none}main header nav:first-child ol{display:grid;grid-auto-flow:column;white-space:nowrap;overflow:hidden}main header nav:first-child ol>li{list-style-type:none;display:inline-flex;overflow:hidden}main header nav:first-child ol li:first-child a::before{background-color:var(--token-color-foreground-faint);margin-right:4px;display:inline-block}main header nav:first-child ol li:not(:first-child) a{margin-left:6px;overflow:hidden;text-overflow:ellipsis}main header nav:first-child ol li:not(:first-child) a::before{content:"/";margin-right:8px;display:inline-block}main header nav:first-child{position:absolute;top:12px}.consul-intention-action-warn-modal button.dangerous,.copy-button button,.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.hashicorp-consul nav li.nspaces .disclosure-menu>button,.hashicorp-consul nav li.partitions .disclosure-menu>button,.informed-action>ul>li>*,.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-select label>*,.topology-notices button,.type-sort.popover-select label>*,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{cursor:pointer;white-space:nowrap;text-decoration:none}.consul-intention-action-warn-modal button.dangerous:disabled,.copy-button button:disabled,.disclosure-menu [aria-expanded]~*>ul>[role=treeitem]:disabled,.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem]:disabled,.disclosure-menu [aria-expanded]~*>ul>li>[role=option]:disabled,.hashicorp-consul nav li.nspaces .disclosure-menu>button:disabled,.hashicorp-consul nav li.partitions .disclosure-menu>button:disabled,.informed-action>ul>li>:disabled,.menu-panel>ul>[role=treeitem]:disabled,.menu-panel>ul>li>[role=menuitem]:disabled,.menu-panel>ul>li>[role=option]:disabled,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]:disabled,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]:disabled,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option]:disabled,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]:disabled,.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]:disabled,.popover-menu>[type=checkbox]+label+div>ul>li>[role=option]:disabled,.popover-select label>:disabled,.topology-notices button:disabled,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]:disabled,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]:disabled,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]:disabled,table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]:disabled,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]:disabled,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]:disabled{cursor:default;box-shadow:none}.checkbox-group label,.more-popover-menu>[type=checkbox]~label,.popover-menu>[type=checkbox]~label,html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label,table.has-actions tr>.actions>[type=checkbox]~label,table.with-details tr>.actions>[type=checkbox]~label{cursor:pointer}.consul-intention-action-warn-modal button.dangerous{border-width:1px;border-radius:var(--decor-radius-100);box-shadow:var(--token-elevation-high-box-shadow)}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.hashicorp-consul nav li.nspaces .disclosure-menu>button,.hashicorp-consul nav li.partitions .disclosure-menu>button,.informed-action>ul>li>*,.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{color:var(--token-color-foreground-strong);background-color:var(--token-color-surface-primary)}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem]:focus,.disclosure-menu [aria-expanded]~*>ul>[role=treeitem]:hover,.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem]:focus,.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem]:hover,.disclosure-menu [aria-expanded]~*>ul>li>[role=option]:focus,.disclosure-menu [aria-expanded]~*>ul>li>[role=option]:hover,.hashicorp-consul nav li.nspaces .disclosure-menu>button:focus,.hashicorp-consul nav li.nspaces .disclosure-menu>button:hover,.hashicorp-consul nav li.partitions .disclosure-menu>button:focus,.hashicorp-consul nav li.partitions .disclosure-menu>button:hover,.informed-action>ul>li>:focus,.informed-action>ul>li>:hover,.menu-panel>ul>[role=treeitem]:focus,.menu-panel>ul>[role=treeitem]:hover,.menu-panel>ul>li>[role=menuitem]:focus,.menu-panel>ul>li>[role=menuitem]:hover,.menu-panel>ul>li>[role=option]:focus,.menu-panel>ul>li>[role=option]:hover,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]:focus,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]:hover,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]:focus,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]:hover,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option]:focus,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option]:hover,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]:focus,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]:hover,.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]:focus,.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]:hover,.popover-menu>[type=checkbox]+label+div>ul>li>[role=option]:focus,.popover-menu>[type=checkbox]+label+div>ul>li>[role=option]:hover,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]:focus,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]:hover,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]:focus,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]:hover,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]:focus,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]:hover,table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]:focus,table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]:hover,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]:focus,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]:hover,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]:focus,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]:hover{background-color:var(--token-color-surface-strong)}.type-sort.popover-select label>::before{position:relative;width:16px;height:16px}.type-sort.popover-select label>::after{top:0!important}.consul-intention-action-warn-modal button.dangerous,.copy-button button,.popover-select label>*,.topology-notices button,.type-sort.popover-select label>*{position:relative}.consul-intention-action-warn-modal button.dangerous .progress.indeterminate,.copy-button button .progress.indeterminate,.popover-select label>* .progress.indeterminate,.topology-notices button .progress.indeterminate{position:absolute;top:50%;left:50%;margin-left:-12px;margin-top:-12px}.consul-intention-action-warn-modal button.dangerous:empty,.copy-button button:empty,.popover-select label>:empty,.topology-notices button:empty{padding-right:0!important;padding-left:18px!important;margin-right:5px}.consul-intention-action-warn-modal button.dangerous:empty::before,.copy-button button:empty::before,.popover-select label>:empty::before,.topology-notices button:empty::before{left:1px}.consul-intention-action-warn-modal button.dangerous:not(:empty),.copy-button button:not(:empty),.popover-select label>:not(:empty),.topology-notices button:not(:empty){display:inline-flex;text-align:center;justify-content:center;align-items:center;padding:calc(.5em - 1px) calc(2.2em - 1px);min-width:100px}.consul-intention-action-warn-modal button.dangerous:not(:last-child),.copy-button button:not(:last-child),.popover-select label>:not(:last-child),.topology-notices button:not(:last-child){margin-right:8px}.app-view>header .actions a{padding-top:calc(.4em - 1px)!important;padding-bottom:calc(.4em - 1px)!important}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.hashicorp-consul nav li.nspaces .disclosure-menu>button,.hashicorp-consul nav li.partitions .disclosure-menu>button,.informed-action>ul>li>*,.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{padding:.9em 1em;text-align:center;display:inline-block;box-sizing:border-box}.type-sort.popover-select label>*{height:35px!important}.discovery-chain .resolver-card,.discovery-chain .route-card,.discovery-chain .splitter-card{border:var(--decor-border-100);border-radius:var(--decor-radius-100);background-color:var(--token-color-surface-faint);display:block;position:relative}.discovery-chain .resolver-card>section,.discovery-chain .resolver-card>ul>li,.discovery-chain .route-card>section,.discovery-chain .route-card>ul>li,.discovery-chain .splitter-card>section,.discovery-chain .splitter-card>ul>li{border-top:var(--decor-border-100)}.discovery-chain .resolver-card,.discovery-chain .resolver-card>section,.discovery-chain .resolver-card>ul>li,.discovery-chain .route-card,.discovery-chain .route-card>section,.discovery-chain .route-card>ul>li,.discovery-chain .splitter-card,.discovery-chain .splitter-card>section,.discovery-chain .splitter-card>ul>li{border-color:var(--token-color-surface-interactive-active)}.discovery-chain .resolver-card:focus,.discovery-chain .resolver-card:hover,.discovery-chain .route-card:focus,.discovery-chain .route-card:hover,.discovery-chain .splitter-card:focus,.discovery-chain .splitter-card:hover{box-shadow:var(--token-surface-mid-box-shadow)}.discovery-chain .resolver-card>header,.discovery-chain .route-card>header,.discovery-chain .splitter-card>header{padding:10px}.discovery-chain .resolver-card>section,.discovery-chain .resolver-card>ul>li,.discovery-chain .route-card>section,.discovery-chain .route-card>ul>li,.discovery-chain .splitter-card>section,.discovery-chain .splitter-card>ul>li{padding:5px 10px}.discovery-chain .resolver-card ul,.discovery-chain .route-card ul,.discovery-chain .splitter-card ul{list-style-type:none;margin:0;padding:0}.checkbox-group label{margin-right:10px;white-space:nowrap}.checkbox-group span{display:inline-block;margin-left:10px;min-width:50px}.CodeMirror{max-width:1260px;min-height:300px;height:auto;padding-bottom:20px}.CodeMirror-scroll{overflow-x:hidden!important}.CodeMirror-lint-tooltip{background-color:#f9f9fa;border:1px solid var(--syntax-light-gray);border-radius:0;color:#212121;font-size:13px;padding:7px 8px 9px}.cm-s-hashi.CodeMirror{width:100%;background-color:var(--token-color-hashicorp-brand)!important;color:#cfd2d1!important;border:none;-webkit-font-smoothing:auto;line-height:1.4}.cm-s-hashi .CodeMirror-gutters{color:var(--syntax-dark-grey);background-color:var(--syntax-gutter-grey);border:none}.cm-s-hashi .CodeMirror-cursor{border-left:solid thin #f8f8f0}.cm-s-hashi .CodeMirror-linenumber{color:#6d8a88}.cm-s-hashi.CodeMirror-focused div.CodeMirror-selected{background:#214283}.cm-s-hashi .CodeMirror-line::selection,.cm-s-hashi .CodeMirror-line>span::selection,.cm-s-hashi .CodeMirror-line>span>span::selection{background:#214283}.cm-s-hashi .CodeMirror-line::-moz-selection,.cm-s-hashi .CodeMirror-line>span::-moz-selection,.cm-s-hashi .CodeMirror-line>span>span::-moz-selection{background:var(--token-color-surface-interactive)}.cm-s-hashi span.cm-comment{color:var(--syntax-light-grey)}.cm-s-hashi span.cm-string,.cm-s-hashi span.cm-string-2{color:var(--syntax-packer)}.cm-s-hashi span.cm-number{color:var(--syntax-serf)}.cm-s-hashi span.cm-variable,.cm-s-hashi span.cm-variable-2{color:#9e84c5}.cm-s-hashi span.cm-def{color:var(--syntax-packer)}.cm-s-hashi span.cm-operator{color:var(--syntax-gray)}.cm-s-hashi span.cm-keyword{color:var(--syntax-yellow)}.cm-s-hashi span.cm-atom{color:var(--syntax-serf)}.cm-s-hashi span.cm-meta,.cm-s-hashi span.cm-tag{color:var(--syntax-packer)}.cm-s-hashi span.cm-error{color:var(--syntax-red)}.cm-s-hashi span.cm-attribute,.cm-s-hashi span.cm-qualifier{color:#9fca56}.cm-s-hashi span.cm-property{color:#9e84c5}.cm-s-hashi span.cm-builtin,.cm-s-hashi span.cm-variable-3{color:#9fca56}.cm-s-hashi .CodeMirror-activeline-background{background:#101213}.cm-s-hashi .CodeMirror-matchingbracket{text-decoration:underline;color:var(--token-color-surface-primary)!important}.readonly-codemirror .cm-s-hashi span{color:var(--syntax-light-grey)}.readonly-codemirror .cm-s-hashi span.cm-string,.readonly-codemirror .cm-s-hashi span.cm-string-2{color:var(--syntax-faded-gray)}.readonly-codemirror .cm-s-hashi span.cm-number{color:#a3acbc}.readonly-codemirror .cm-s-hashi span.cm-property{color:var(--token-color-surface-primary)}.readonly-codemirror .cm-s-hashi span.cm-variable-2{color:var(--syntax-light-grey-blue)}.code-editor .toolbar-container{background:var(--token-color-surface-strong);background:linear-gradient(180deg,var(--token-color-surface-strong) 50%,var(--token-color-surface-interactive-active) 100%);border:1px solid var(--token-color-surface-interactive-active);border-bottom-color:var(--token-color-foreground-faint);border-top-color:var(--token-color-foreground-disabled)}.code-editor .toolbar-container .toolbar .title{color:var(--token-color-foreground-strong);font-size:14px;font-weight:700;padding:0 8px}.code-editor .toolbar-container .toolbar .toolbar-separator{border-right:1px solid var(--token-color-palette-neutral-300)}.code-editor .toolbar-container .ember-power-select-trigger{background-color:var(--token-color-surface-primary);color:var(--token-color-hashicorp-brand);border-radius:var(--decor-radius-100);border:var(--decor-border-100);border-color:var(--token-color-foreground-faint)}.code-editor{display:block;border:10px;overflow:hidden;position:relative;clear:both}.code-editor::after{position:absolute;bottom:0;width:100%;height:25px;background-color:var(--token-color-hashicorp-brand);content:"";display:block}.code-editor>pre{display:none}.code-editor .toolbar-container,.code-editor .toolbar-container .toolbar{align-items:center;justify-content:space-between;display:flex}.code-editor .toolbar-container{position:relative;margin-top:4px;height:44px}.code-editor .toolbar-container .toolbar{flex:1;white-space:nowrap}.code-editor .toolbar-container .toolbar .toolbar-separator{height:32px;margin:0 4px;width:0}.code-editor .toolbar-container .toolbar .tools{display:flex;flex-direction:row;margin:0 10px;align-items:center}.code-editor .toolbar-container .toolbar .tools .copy-button{margin-left:10px}.code-editor .toolbar-container .ember-basic-dropdown-trigger{margin:0 8px;width:120px;height:32px;display:flex;align-items:center;flex-direction:row}.consul-exposed-path-list>ul>li,.consul-lock-session-list ul>li:not(:first-child),.consul-upstream-instance-list li,.list-collection>ul>li:not(:first-child){display:grid;grid-template-columns:1fr auto;grid-template-rows:50% 50%;grid-template-areas:"header actions" "detail actions"}.consul-exposed-path-list>ul>li>.header,.consul-lock-session-list ul>li:not(:first-child)>.header,.consul-upstream-instance-list li>.header,.list-collection>ul>li:not(:first-child)>.header{grid-area:header;align-self:start}.consul-exposed-path-list>ul>li>.detail,.consul-lock-session-list ul>li:not(:first-child)>.detail,.consul-upstream-instance-list li>.detail,.list-collection>ul>li:not(:first-child)>.detail{grid-area:detail;align-self:end}.consul-exposed-path-list>ul>li>.detail *,.consul-lock-session-list ul>li:not(:first-child)>.detail *,.consul-upstream-instance-list li>.detail *,.list-collection>ul>li:not(:first-child)>.detail *{flex-wrap:nowrap!important}.consul-exposed-path-list>ul>li>.actions,.consul-lock-session-list ul>li:not(:first-child)>.actions,.consul-upstream-instance-list li>.actions,.list-collection>ul>li:not(:first-child)>.actions{grid-area:actions;display:inline-flex}.consul-nspace-list>ul>li:not(:first-child) dt,.consul-policy-list>ul li:not(:first-child) dl:not(.datacenter) dt,.consul-role-list>ul>li:not(:first-child) dt,.consul-service-instance-list .port dt,.consul-service-instance-list .port dt::before,.consul-token-list>ul>li:not(:first-child) dt{display:none}.consul-exposed-path-list>ul>li>.header:nth-last-child(2),.consul-lock-session-list ul>li:not(:first-child)>.header:nth-last-child(2),.consul-upstream-instance-list li>.header:nth-last-child(2),.list-collection>ul>li:not(:first-child)>.header:nth-last-child(2){grid-column-start:header;grid-column-end:actions}.consul-exposed-path-list>ul>li>.detail:last-child,.consul-lock-session-list ul>li:not(:first-child)>.detail:last-child,.consul-upstream-instance-list li>.detail:last-child,.list-collection>ul>li:not(:first-child)>.detail:last-child{grid-column-start:detail;grid-column-end:actions}.consul-nspace-list>ul>li:not(:first-child) dt+dd,.consul-policy-list>ul li:not(:first-child) dl:not(.datacenter) dt+dd,.consul-role-list>ul>li:not(:first-child) dt+dd,.consul-token-list>ul>li:not(:first-child) dt+dd{margin-left:0!important}.consul-policy-list dl.datacenter dt,.consul-service-list li>div:first-child>dl:first-child dd{margin-top:1px}.consul-service-instance-list .detail,.consul-service-list .detail{overflow-x:visible!important}.consul-intention-permission-list>ul{border-top:1px solid var(--token-color-surface-interactive-active)}.consul-service-instance-list .port .copy-button{margin-right:0}.consul-exposed-path-list>ul>li .copy-button,.consul-lock-session-list ul>li:not(:first-child) .copy-button,.consul-upstream-instance-list li .copy-button,.list-collection>ul>li:not(:first-child) .copy-button{display:inline-flex}.consul-exposed-path-list>ul>li>.header .copy-button,.consul-lock-session-list ul>li:not(:first-child)>.header .copy-button,.consul-upstream-instance-list li>.header .copy-button,.list-collection>ul>li:not(:first-child)>.header .copy-button{margin-left:4px}.consul-exposed-path-list>ul>li>.detail .copy-button,.consul-lock-session-list ul>li:not(:first-child)>.detail .copy-button,.consul-upstream-instance-list li>.detail .copy-button,.list-collection>ul>li:not(:first-child)>.detail .copy-button{margin-top:2px}.consul-exposed-path-list>ul>li .copy-button button,.consul-lock-session-list ul>li:not(:first-child) .copy-button button,.consul-upstream-instance-list li .copy-button button,.list-collection>ul>li:not(:first-child) .copy-button button{padding:0!important;margin:0!important}.consul-exposed-path-list>ul>li>.header .copy-button button,.consul-lock-session-list ul>li:not(:first-child)>.header .copy-button button,.consul-upstream-instance-list li>.header .copy-button button,.list-collection>ul>li:not(:first-child)>.header .copy-button button{display:none}.consul-exposed-path-list>ul>li>.header:hover .copy-button button,.consul-lock-session-list ul>li:not(:first-child)>.header:hover .copy-button button,.consul-upstream-instance-list li>.header:hover .copy-button button,.list-collection>ul>li:not(:first-child)>.header:hover .copy-button button{display:block}.consul-exposed-path-list>ul>li .copy-button button:hover,.consul-lock-session-list ul>li:not(:first-child) .copy-button button:hover,.consul-upstream-instance-list li .copy-button button:hover,.list-collection>ul>li:not(:first-child) .copy-button button:hover{background-color:transparent!important}.consul-exposed-path-list>ul>li>.detail>.consul-external-source:first-child,.consul-exposed-path-list>ul>li>.detail>.consul-kind:first-child,.consul-lock-session-list ul>li:not(:first-child)>.detail>.consul-external-source:first-child,.consul-lock-session-list ul>li:not(:first-child)>.detail>.consul-kind:first-child,.consul-upstream-instance-list li>.detail>.consul-external-source:first-child,.consul-upstream-instance-list li>.detail>.consul-kind:first-child,.list-collection>ul>li:not(:first-child)>.detail>.consul-external-source:first-child,.list-collection>ul>li:not(:first-child)>.detail>.consul-kind:first-child{margin-left:-5px}.consul-exposed-path-list>ul>li>.detail .policy-management::before,.consul-exposed-path-list>ul>li>.detail .policy::before,.consul-exposed-path-list>ul>li>.detail .role::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .policy-management::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .policy::before,.consul-lock-session-list ul>li:not(:first-child)>.detail .role::before,.consul-upstream-instance-list li>.detail .policy-management::before,.consul-upstream-instance-list li>.detail .policy::before,.consul-upstream-instance-list li>.detail .role::before,.list-collection>ul>li:not(:first-child)>.detail .policy-management::before,.list-collection>ul>li:not(:first-child)>.detail .policy::before,.list-collection>ul>li:not(:first-child)>.detail .role::before{margin-right:3px}table div.with-confirmation.confirming{background-color:var(--token-color-surface-primary)}div.with-confirmation p{margin-right:12px;padding-left:12px;margin-bottom:0!important}div.with-confirmation{justify-content:end;width:100%;display:flex;align-items:center}table td>div.with-confirmation.confirming{position:absolute;right:0}@media (max-width:420px){div.with-confirmation{float:none;margin-top:1em;display:block}div.with-confirmation p{margin-bottom:1em}}.copy-button button{color:var(--token-color-foreground-action);--icon-color:transparent;min-height:17px}.copy-button button::after{--icon-color:var(--token-color-surface-strong)}.copy-button button:focus,.copy-button button:hover:not(:disabled):not(:active){color:var(--token-color-foreground-action);--icon-color:var(--token-color-surface-strong)}.copy-button button:hover::before{--icon-color:var(--token-color-foreground-action)}.copy-button button:active{--icon-color:var(--token-color-surface-interactive-active)}.copy-button button:empty{padding:0!important;margin-right:0;top:-1px}.copy-button button:empty::after{content:"";display:none;position:absolute;top:-2px;left:-3px;width:20px;height:22px}.copy-button button:empty:hover::after{display:block}.copy-button button:empty::before{position:relative;z-index:1}.copy-button button:not(:empty)::before{margin-right:4px}.consul-bucket-list .copy-button,.consul-exposed-path-list>ul>li>.detail dl .copy-button,.consul-instance-checks .copy-button,.consul-lock-session-list dl .copy-button,.consul-lock-session-list ul>li:not(:first-child)>.detail dl .copy-button,.consul-upstream-instance-list dl .copy-button,.list-collection>ul>li:not(:first-child)>.detail dl .copy-button,.tag-list .copy-button,section[data-route="dc.show.license"] .validity dl .copy-button,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .copy-button,td.tags .copy-button{margin-top:0!important}.consul-bucket-list .copy-btn,.consul-exposed-path-list>ul>li>.detail dl .copy-btn,.consul-instance-checks .copy-btn,.consul-lock-session-list dl .copy-btn,.consul-lock-session-list ul>li:not(:first-child)>.detail dl .copy-btn,.consul-upstream-instance-list dl .copy-btn,.list-collection>ul>li:not(:first-child)>.detail dl .copy-btn,.tag-list .copy-btn,section[data-route="dc.show.license"] .validity dl .copy-btn,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .copy-btn,td.tags .copy-btn{top:0!important}.consul-bucket-list .copy-btn:empty::before,.consul-exposed-path-list>ul>li>.detail dl .copy-btn:empty::before,.consul-instance-checks .copy-btn:empty::before,.consul-lock-session-list dl .copy-btn:empty::before,.consul-upstream-instance-list dl .copy-btn:empty::before,.list-collection>ul>li:not(:first-child)>.detail dl .copy-btn:empty::before,.tag-list .copy-btn:empty::before,section[data-route="dc.show.license"] .validity dl .copy-btn:empty::before,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .copy-btn:empty::before,td.tags .copy-btn:empty::before{left:0!important}.definition-table>dl{display:grid;grid-template-columns:140px auto;grid-gap:.4em 20px;margin-bottom:1.4em}.disclosure-menu{position:relative}.disclosure-menu [aria-expanded]~*{overflow-y:auto!important;will-change:scrollPosition}.more-popover-menu>[type=checkbox],.more-popover-menu>[type=checkbox]~:not(.animating):not(label),.popover-menu>[type=checkbox],.popover-menu>[type=checkbox]~:not(.animating):not(label),table.has-actions tr>.actions>[type=checkbox],table.has-actions tr>.actions>[type=checkbox]~:not(.animating):not(label),table.with-details tr>.actions>[type=checkbox],table.with-details tr>.actions>[type=checkbox]~:not(.animating):not(label){display:none}.more-popover-menu>[type=checkbox]:checked~:not(label),.popover-menu>[type=checkbox]:checked~:not(label),table.has-actions tr>.actions>[type=checkbox]:checked~:not(label),table.with-details tr>.actions>[type=checkbox]:checked~:not(label){display:block}table.dom-recycling{position:relative}table.dom-recycling tr>*{overflow:hidden}.list-collection-scroll-virtual>ul,table.dom-recycling tbody{overflow-x:hidden!important}table.dom-recycling dd{flex-wrap:nowrap}table.dom-recycling dd>*{margin-bottom:0}.empty-state,.empty-state>div{display:flex;flex-direction:column}.empty-state header :first-child{padding:0;margin:0}.empty-state{margin-top:0!important;padding-bottom:2.8em;background-color:var(--token-color-surface-faint)}.empty-state>*{width:370px;margin:0 auto}.empty-state button{margin:0 auto;display:inline}.empty-state header :first-child{margin-bottom:-3px;border-bottom:none}.empty-state header{margin-top:1.8em;margin-bottom:.5em}.empty-state>ul{display:flex;justify-content:space-between;margin-top:1em}.empty-state>ul>li>*,.empty-state>ul>li>label>button{display:inline-flex;align-items:center}.empty-state>div:only-child{padding:50px 0 10px;text-align:center}.empty-state header::before{font-size:2.6em;position:relative;top:-3px;float:left;margin-right:10px}.oidc-select button.reset,.type-dialog{float:right}.empty-state>ul>li>::before,.empty-state>ul>li>label>button::before{margin-top:-1px;margin-right:.5em;font-size:.9em}.empty-state li[class*=-link]>::after{margin-left:5px}html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup]{border:var(--decor-border-100);border-color:var(--token-color-palette-neutral-300);border-radius:var(--decor-radius-100)}html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] input[type=radio]:checked+*,html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] input[type=radio]:focus+*,html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] input[type=radio]:hover+*{box-shadow:var(--token-elevation-high-box-shadow);background-color:var(--token-color-surface-primary)}@media (min-width:996px){html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup]{display:flex}html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label{flex-grow:1}}html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] input[type=radio]{display:none}.app-view>div form:not(.filter-bar) [role=radiogroup] label,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea,.app-view>div form:not(.filter-bar) [role=radiogroup] label>em,.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.modal-dialog [role=document] .type-password,.modal-dialog [role=document] .type-password textarea,.modal-dialog [role=document] .type-password>em,.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select,.modal-dialog [role=document] .type-select textarea,.modal-dialog [role=document] .type-select>em,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text,.modal-dialog [role=document] .type-text textarea,.modal-dialog [role=document] .type-text>em,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label,.modal-dialog [role=document] [role=radiogroup] label textarea,.modal-dialog [role=document] [role=radiogroup] label>em,.modal-dialog [role=document] [role=radiogroup] label>span,.modal-dialog [role=document] form button+em,.oidc-select label,.oidc-select label textarea,.oidc-select label>em,.oidc-select label>span,.type-toggle,.type-toggle textarea,.type-toggle>em,.type-toggle>span,html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label,html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label span,main .type-password,main .type-password textarea,main .type-password>em,main .type-password>span,main .type-select,main .type-select textarea,main .type-select>em,main .type-select>span,main .type-text,main .type-text textarea,main .type-text>em,main .type-text>span,main form button+em,span.label{display:block}html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup],html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label,html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label span{height:100%}html[data-route^="dc.acls.index"] .filter-bar [role=radiogroup] label span{padding:5px 14px}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password],.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text],.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea,.modal-dialog [role=document] .type-password [type=password],.modal-dialog [role=document] .type-password [type=text],.modal-dialog [role=document] .type-password textarea,.modal-dialog [role=document] .type-select [type=password],.modal-dialog [role=document] .type-select [type=text],.modal-dialog [role=document] .type-select textarea,.modal-dialog [role=document] .type-text [type=password],.modal-dialog [role=document] .type-text [type=text],.modal-dialog [role=document] .type-text textarea,.modal-dialog [role=document] [role=radiogroup] label [type=password],.modal-dialog [role=document] [role=radiogroup] label [type=text],.modal-dialog [role=document] [role=radiogroup] label textarea,.oidc-select label [type=password],.oidc-select label [type=text],.oidc-select label textarea,.type-toggle [type=password],.type-toggle [type=text],.type-toggle textarea,main .type-password [type=password],main .type-password [type=text],main .type-password textarea,main .type-select [type=password],main .type-select [type=text],main .type-select textarea,main .type-text [type=password],main .type-text [type=text],main .type-text textarea{-moz-appearance:none;-webkit-appearance:none;box-shadow:var(--token-surface-inset-box-shadow);border-radius:var(--decor-radius-100);border:var(--decor-border-100);outline:0}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]:-moz-read-only,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]:-moz-read-only,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea:-moz-read-only,.modal-dialog [role=document] .type-password [type=password]:-moz-read-only,.modal-dialog [role=document] .type-password [type=text]:-moz-read-only,.modal-dialog [role=document] .type-password textarea:-moz-read-only,.modal-dialog [role=document] .type-select [type=password]:-moz-read-only,.modal-dialog [role=document] .type-select [type=text]:-moz-read-only,.modal-dialog [role=document] .type-select textarea:-moz-read-only,.modal-dialog [role=document] .type-text [type=password]:-moz-read-only,.modal-dialog [role=document] .type-text [type=text]:-moz-read-only,.modal-dialog [role=document] .type-text textarea:-moz-read-only,.modal-dialog [role=document] [role=radiogroup] label [type=password]:-moz-read-only,.modal-dialog [role=document] [role=radiogroup] label [type=text]:-moz-read-only,.modal-dialog [role=document] [role=radiogroup] label textarea:-moz-read-only,.oidc-select label [type=password]:-moz-read-only,.oidc-select label [type=text]:-moz-read-only,.oidc-select label textarea:-moz-read-only,.type-toggle [type=password]:-moz-read-only,.type-toggle [type=text]:-moz-read-only,.type-toggle textarea:-moz-read-only,main .type-password [type=password]:-moz-read-only,main .type-password [type=text]:-moz-read-only,main .type-password textarea:-moz-read-only,main .type-select [type=password]:-moz-read-only,main .type-select [type=text]:-moz-read-only,main .type-select textarea:-moz-read-only,main .type-text [type=password]:-moz-read-only,main .type-text [type=text]:-moz-read-only,main .type-text textarea:-moz-read-only{cursor:not-allowed}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]:disabled,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]:read-only,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]:disabled,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]:read-only,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea:disabled,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea:read-only,.modal-dialog [role=document] .type-password [type=password]:disabled,.modal-dialog [role=document] .type-password [type=password]:read-only,.modal-dialog [role=document] .type-password [type=text]:disabled,.modal-dialog [role=document] .type-password [type=text]:read-only,.modal-dialog [role=document] .type-password textarea:disabled,.modal-dialog [role=document] .type-password textarea:read-only,.modal-dialog [role=document] .type-select [type=password]:disabled,.modal-dialog [role=document] .type-select [type=password]:read-only,.modal-dialog [role=document] .type-select [type=text]:disabled,.modal-dialog [role=document] .type-select [type=text]:read-only,.modal-dialog [role=document] .type-select textarea:disabled,.modal-dialog [role=document] .type-select textarea:read-only,.modal-dialog [role=document] .type-text [type=password]:disabled,.modal-dialog [role=document] .type-text [type=password]:read-only,.modal-dialog [role=document] .type-text [type=text]:disabled,.modal-dialog [role=document] .type-text [type=text]:read-only,.modal-dialog [role=document] .type-text textarea:disabled,.modal-dialog [role=document] .type-text textarea:read-only,.modal-dialog [role=document] [role=radiogroup] label [type=password]:disabled,.modal-dialog [role=document] [role=radiogroup] label [type=password]:read-only,.modal-dialog [role=document] [role=radiogroup] label [type=text]:disabled,.modal-dialog [role=document] [role=radiogroup] label [type=text]:read-only,.modal-dialog [role=document] [role=radiogroup] label textarea:disabled,.modal-dialog [role=document] [role=radiogroup] label textarea:read-only,.oidc-select label [type=password]:disabled,.oidc-select label [type=password]:read-only,.oidc-select label [type=text]:disabled,.oidc-select label [type=text]:read-only,.oidc-select label textarea:disabled,.oidc-select label textarea:read-only,.type-toggle [type=password]:disabled,.type-toggle [type=password]:read-only,.type-toggle [type=text]:disabled,.type-toggle [type=text]:read-only,.type-toggle textarea:disabled,.type-toggle textarea:read-only,main .type-password [type=password]:disabled,main .type-password [type=password]:read-only,main .type-password [type=text]:disabled,main .type-password [type=text]:read-only,main .type-password textarea:disabled,main .type-password textarea:read-only,main .type-select [type=password]:disabled,main .type-select [type=password]:read-only,main .type-select [type=text]:disabled,main .type-select [type=text]:read-only,main .type-select textarea:disabled,main .type-select textarea:read-only,main .type-text [type=password]:disabled,main .type-text [type=password]:read-only,main .type-text [type=text]:disabled,main .type-text [type=text]:read-only,main .type-text textarea:disabled,main .type-text textarea:read-only,textarea:disabled+.CodeMirror{cursor:not-allowed}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]::-moz-placeholder,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]::-moz-placeholder,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea::-moz-placeholder,.modal-dialog [role=document] .type-password [type=password]::-moz-placeholder,.modal-dialog [role=document] .type-password [type=text]::-moz-placeholder,.modal-dialog [role=document] .type-password textarea::-moz-placeholder,.modal-dialog [role=document] .type-select [type=password]::-moz-placeholder,.modal-dialog [role=document] .type-select [type=text]::-moz-placeholder,.modal-dialog [role=document] .type-select textarea::-moz-placeholder,.modal-dialog [role=document] .type-text [type=password]::-moz-placeholder,.modal-dialog [role=document] .type-text [type=text]::-moz-placeholder,.modal-dialog [role=document] .type-text textarea::-moz-placeholder,.modal-dialog [role=document] [role=radiogroup] label [type=password]::-moz-placeholder,.modal-dialog [role=document] [role=radiogroup] label [type=text]::-moz-placeholder,.modal-dialog [role=document] [role=radiogroup] label textarea::-moz-placeholder,.oidc-select label [type=password]::-moz-placeholder,.oidc-select label [type=text]::-moz-placeholder,.oidc-select label textarea::-moz-placeholder,.type-toggle [type=password]::-moz-placeholder,.type-toggle [type=text]::-moz-placeholder,.type-toggle textarea::-moz-placeholder,main .type-password [type=password]::-moz-placeholder,main .type-password [type=text]::-moz-placeholder,main .type-password textarea::-moz-placeholder,main .type-select [type=password]::-moz-placeholder,main .type-select [type=text]::-moz-placeholder,main .type-select textarea::-moz-placeholder,main .type-text [type=password]::-moz-placeholder,main .type-text [type=text]::-moz-placeholder,main .type-text textarea::-moz-placeholder{color:var(--token-color-foreground-disabled)}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]::placeholder,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]::placeholder,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea::placeholder,.app-view>div form:not(.filter-bar) [role=radiogroup] label>em,.modal-dialog [role=document] .type-password [type=password]::placeholder,.modal-dialog [role=document] .type-password [type=text]::placeholder,.modal-dialog [role=document] .type-password textarea::placeholder,.modal-dialog [role=document] .type-password>em,.modal-dialog [role=document] .type-select [type=password]::placeholder,.modal-dialog [role=document] .type-select [type=text]::placeholder,.modal-dialog [role=document] .type-select textarea::placeholder,.modal-dialog [role=document] .type-select>em,.modal-dialog [role=document] .type-text [type=password]::placeholder,.modal-dialog [role=document] .type-text [type=text]::placeholder,.modal-dialog [role=document] .type-text textarea::placeholder,.modal-dialog [role=document] .type-text>em,.modal-dialog [role=document] [role=radiogroup] label [type=password]::placeholder,.modal-dialog [role=document] [role=radiogroup] label [type=text]::placeholder,.modal-dialog [role=document] [role=radiogroup] label textarea::placeholder,.modal-dialog [role=document] [role=radiogroup] label>em,.modal-dialog [role=document] form button+em,.modal-dialog [role=document] form fieldset>p,.oidc-select label [type=password]::placeholder,.oidc-select label [type=text]::placeholder,.oidc-select label textarea::placeholder,.oidc-select label>em,.type-toggle [type=password]::placeholder,.type-toggle [type=text]::placeholder,.type-toggle textarea::placeholder,.type-toggle>em,main .type-password [type=password]::placeholder,main .type-password [type=text]::placeholder,main .type-password textarea::placeholder,main .type-password>em,main .type-select [type=password]::placeholder,main .type-select [type=text]::placeholder,main .type-select textarea::placeholder,main .type-select>em,main .type-text [type=password]::placeholder,main .type-text [type=text]::placeholder,main .type-text textarea::placeholder,main .type-text>em,main form button+em,main form fieldset>p{color:var(--token-color-foreground-disabled)}.has-error>input,.has-error>textarea{border-color:var(--decor-error,var(--token-color-foreground-critical))!important}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password],.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text],.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea,.modal-dialog [role=document] .type-password [type=password],.modal-dialog [role=document] .type-password [type=text],.modal-dialog [role=document] .type-password textarea,.modal-dialog [role=document] .type-select [type=password],.modal-dialog [role=document] .type-select [type=text],.modal-dialog [role=document] .type-select textarea,.modal-dialog [role=document] .type-text [type=password],.modal-dialog [role=document] .type-text [type=text],.modal-dialog [role=document] .type-text textarea,.modal-dialog [role=document] [role=radiogroup] label [type=password],.modal-dialog [role=document] [role=radiogroup] label [type=text],.modal-dialog [role=document] [role=radiogroup] label textarea,.oidc-select label [type=password],.oidc-select label [type=text],.oidc-select label textarea,.type-toggle [type=password],.type-toggle [type=text],.type-toggle textarea,main .type-password [type=password],main .type-password [type=text],main .type-password textarea,main .type-select [type=password],main .type-select [type=text],main .type-select textarea,main .type-text [type=password],main .type-text [type=text],main .type-text textarea{color:var(--token-color-foreground-faint);border-color:var(--token-color-palette-neutral-300)}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]:hover,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]:hover,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea:hover,.modal-dialog [role=document] .type-password [type=password]:hover,.modal-dialog [role=document] .type-password [type=text]:hover,.modal-dialog [role=document] .type-password textarea:hover,.modal-dialog [role=document] .type-select [type=password]:hover,.modal-dialog [role=document] .type-select [type=text]:hover,.modal-dialog [role=document] .type-select textarea:hover,.modal-dialog [role=document] .type-text [type=password]:hover,.modal-dialog [role=document] .type-text [type=text]:hover,.modal-dialog [role=document] .type-text textarea:hover,.modal-dialog [role=document] [role=radiogroup] label [type=password]:hover,.modal-dialog [role=document] [role=radiogroup] label [type=text]:hover,.modal-dialog [role=document] [role=radiogroup] label textarea:hover,.oidc-select label [type=password]:hover,.oidc-select label [type=text]:hover,.oidc-select label textarea:hover,.type-toggle [type=password]:hover,.type-toggle [type=text]:hover,.type-toggle textarea:hover,main .type-password [type=password]:hover,main .type-password [type=text]:hover,main .type-password textarea:hover,main .type-select [type=password]:hover,main .type-select [type=text]:hover,main .type-select textarea:hover,main .type-text [type=password]:hover,main .type-text [type=text]:hover,main .type-text textarea:hover{border-color:var(--token-color-foreground-faint)}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password]:focus,.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text]:focus,.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea:focus,.modal-dialog [role=document] .type-password [type=password]:focus,.modal-dialog [role=document] .type-password [type=text]:focus,.modal-dialog [role=document] .type-password textarea:focus,.modal-dialog [role=document] .type-select [type=password]:focus,.modal-dialog [role=document] .type-select [type=text]:focus,.modal-dialog [role=document] .type-select textarea:focus,.modal-dialog [role=document] .type-text [type=password]:focus,.modal-dialog [role=document] .type-text [type=text]:focus,.modal-dialog [role=document] .type-text textarea:focus,.modal-dialog [role=document] [role=radiogroup] label [type=password]:focus,.modal-dialog [role=document] [role=radiogroup] label [type=text]:focus,.modal-dialog [role=document] [role=radiogroup] label textarea:focus,.oidc-select label [type=password]:focus,.oidc-select label [type=text]:focus,.oidc-select label textarea:focus,.type-toggle [type=password]:focus,.type-toggle [type=text]:focus,.type-toggle textarea:focus,main .type-password [type=password]:focus,main .type-password [type=text]:focus,main .type-password textarea:focus,main .type-select [type=password]:focus,main .type-select [type=text]:focus,main .type-select textarea:focus,main .type-text [type=password]:focus,main .type-text [type=text]:focus,main .type-text textarea:focus{border-color:var(--typo-action,var(--token-color-foreground-action))}.app-view>div form:not(.filter-bar) [role=radiogroup] label a,.modal-dialog [role=document] .type-password a,.modal-dialog [role=document] .type-select a,.modal-dialog [role=document] .type-text a,.modal-dialog [role=document] [role=radiogroup] label a,.oidc-select label a,.type-toggle a,main .type-password a,main .type-select a,main .type-text a{display:inline}.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=password],.app-view>div form:not(.filter-bar) [role=radiogroup] label [type=text],.modal-dialog [role=document] .type-password [type=password],.modal-dialog [role=document] .type-password [type=text],.modal-dialog [role=document] .type-select [type=password],.modal-dialog [role=document] .type-select [type=text],.modal-dialog [role=document] .type-text [type=password],.modal-dialog [role=document] .type-text [type=text],.modal-dialog [role=document] [role=radiogroup] label [type=password],.modal-dialog [role=document] [role=radiogroup] label [type=text],.oidc-select label [type=password],.oidc-select label [type=text],.type-toggle [type=password],.type-toggle [type=text],main .type-password [type=password],main .type-password [type=text],main .type-select [type=password],main .type-select [type=text],main .type-text [type=password],main .type-text [type=text]{display:inline-flex;justify-content:flex-start;max-width:100%;width:100%;height:0;padding:17px 13px}.app-view>div form:not(.filter-bar) [role=radiogroup] label textarea,.modal-dialog [role=document] .type-password textarea,.modal-dialog [role=document] .type-select textarea,.modal-dialog [role=document] .type-text textarea,.modal-dialog [role=document] [role=radiogroup] label textarea,.oidc-select label textarea,.type-toggle textarea,main .type-password textarea,main .type-select textarea,main .type-text textarea{resize:vertical;max-width:100%;min-width:100%;min-height:70px;padding:6px 13px}.app-view>div form:not(.filter-bar) [role=radiogroup],.app-view>div form:not(.filter-bar) [role=radiogroup] label,.checkbox-group,.modal-dialog [role=document] .type-password,.modal-dialog [role=document] .type-select,.modal-dialog [role=document] .type-text,.modal-dialog [role=document] [role=radiogroup],.modal-dialog [role=document] [role=radiogroup] label,.modal-dialog [role=document] form table,.oidc-select label,.type-toggle,main .type-password,main .type-select,main .type-text,main form table{margin-bottom:1.4em}.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label>span,.oidc-select label>span,.type-toggle>span,main .type-password>span,main .type-select>span,main .type-text>span,span.label{color:var(--typo-contrast,inherit);margin-bottom:.3em}.app-view>div form:not(.filter-bar) [role=radiogroup] label>em,.modal-dialog [role=document] .type-password>em,.modal-dialog [role=document] .type-select>em,.modal-dialog [role=document] .type-text>em,.modal-dialog [role=document] [role=radiogroup] label>em,.modal-dialog [role=document] form button+em,.oidc-select label>em,.type-toggle>em,main .type-password>em,main .type-select>em,main .type-text>em,main form button+em{margin-top:2px}.app-view>div form:not(.filter-bar) [role=radiogroup] label>span+em,.modal-dialog [role=document] .type-password>span+em,.modal-dialog [role=document] .type-select>span+em,.modal-dialog [role=document] .type-text>span+em,.modal-dialog [role=document] [role=radiogroup] label>span+em,.oidc-select label>span+em,.type-toggle>span+em,main .type-password>span+em,main .type-select>span+em,main .type-text>span+em,span.label+em{margin-top:-.5em;margin-bottom:.5em}.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] label.type-text>span,main .type-password>span,main .type-select>span,main label.type-text>span{line-height:2.2em}.type-toggle+.checkbox-group{margin-top:-1em}.consul-exposed-path-list>ul>li,.consul-intention-permission-header-list>ul>li,.consul-intention-permission-list>ul>li,.consul-lock-session-list ul>li:not(:first-child),.consul-upstream-instance-list li,.list-collection>ul>li:not(:first-child){list-style-type:none;border:var(--decor-border-100);border-top-color:transparent;border-bottom-color:var(--token-color-surface-interactive-active);border-right-color:transparent;border-left-color:transparent;--horizontal-padding:12px;--vertical-padding:10px;padding:var(--vertical-padding) 0;padding-left:var(--horizontal-padding)}.consul-auth-method-list>ul>li:active:not(:first-child),.consul-auth-method-list>ul>li:focus:not(:first-child),.consul-auth-method-list>ul>li:hover:not(:first-child),.consul-exposed-path-list>ul>li.linkable:active,.consul-exposed-path-list>ul>li.linkable:focus,.consul-exposed-path-list>ul>li.linkable:hover,.consul-intention-permission-list:not(.readonly)>ul>li:active,.consul-intention-permission-list:not(.readonly)>ul>li:focus,.consul-intention-permission-list:not(.readonly)>ul>li:hover,.consul-lock-session-list ul>li.linkable:active:not(:first-child),.consul-lock-session-list ul>li.linkable:focus:not(:first-child),.consul-lock-session-list ul>li.linkable:hover:not(:first-child),.consul-node-list>ul>li:active:not(:first-child),.consul-node-list>ul>li:focus:not(:first-child),.consul-node-list>ul>li:hover:not(:first-child),.consul-policy-list>ul>li:active:not(:first-child),.consul-policy-list>ul>li:focus:not(:first-child),.consul-policy-list>ul>li:hover:not(:first-child),.consul-role-list>ul>li:active:not(:first-child),.consul-role-list>ul>li:focus:not(:first-child),.consul-role-list>ul>li:hover:not(:first-child),.consul-service-instance-list>ul>li:active:not(:first-child),.consul-service-instance-list>ul>li:focus:not(:first-child),.consul-service-instance-list>ul>li:hover:not(:first-child),.consul-token-list>ul>li:active:not(:first-child),.consul-token-list>ul>li:focus:not(:first-child),.consul-token-list>ul>li:hover:not(:first-child),.consul-upstream-instance-list li.linkable:active,.consul-upstream-instance-list li.linkable:focus,.consul-upstream-instance-list li.linkable:hover,.list-collection>ul>li.linkable:active:not(:first-child),.list-collection>ul>li.linkable:focus:not(:first-child),.list-collection>ul>li.linkable:hover:not(:first-child){border-color:var(--token-color-surface-interactive-active);box-shadow:var(--token-elevation-high-box-shadow);border-top-color:transparent;cursor:pointer}.radio-card,.tippy-box{box-shadow:var(--token-surface-mid-box-shadow)}.consul-exposed-path-list>ul>li>.header,.consul-lock-session-list ul>li:not(:first-child)>.header,.consul-upstream-instance-list li>.header,.list-collection>ul>li:not(:first-child)>.header{color:var(--token-color-hashicorp-brand)}.consul-exposed-path-list>ul>li>.header *,.consul-lock-session-list ul>li:not(:first-child)>.header *,.consul-upstream-instance-list li>.header *,.list-collection>ul>li:not(:first-child)>.header *{color:inherit}.consul-exposed-path-list>ul>li>.detail,.consul-lock-session-list ul>li:not(:first-child)>.detail,.consul-upstream-instance-list li>.detail,.list-collection>ul>li:not(:first-child)>.detail,.radio-card{color:var(--token-color-foreground-faint)}.consul-exposed-path-list>ul>li>.detail a,.consul-lock-session-list ul>li:not(:first-child)>.detail a,.consul-upstream-instance-list li>.detail a,.list-collection>ul>li:not(:first-child)>.detail a{color:inherit}.consul-exposed-path-list>ul>li>.detail a:hover,.consul-lock-session-list ul>li:not(:first-child)>.detail a:hover,.consul-upstream-instance-list li>.detail a:hover,.list-collection>ul>li:not(:first-child)>.detail a:hover{color:var(--token-color-foreground-action);text-decoration:underline}.consul-exposed-path-list>ul>li>.header dt,.consul-lock-session-list ul>li:not(:first-child)>.header dt,.consul-upstream-instance-list li>.header dt,.list-collection>ul>li:not(:first-child)>.header dt{display:none}.consul-exposed-path-list>ul>li>.header dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header dd::before,.consul-upstream-instance-list li>.header dd::before,.list-collection>ul>li:not(:first-child)>.header dd::before{font-size:.9em}.consul-exposed-path-list>ul>li>.detail,.consul-exposed-path-list>ul>li>.header,.consul-lock-session-list ul>li:not(:first-child)>.detail,.consul-lock-session-list ul>li:not(:first-child)>.header,.consul-upstream-instance-list li>.detail,.consul-upstream-instance-list li>.header,.list-collection>ul>li:not(:first-child)>.detail,.list-collection>ul>li:not(:first-child)>.header{display:flex;flex-wrap:nowrap;overflow-x:hidden}.consul-exposed-path-list>ul>li>.detail *,.consul-exposed-path-list>ul>li>.header *,.consul-lock-session-list ul>li:not(:first-child)>.detail *,.consul-lock-session-list ul>li:not(:first-child)>.header *,.consul-upstream-instance-list li>.detail *,.consul-upstream-instance-list li>.header *,.list-collection>ul>li:not(:first-child)>.detail *,.list-collection>ul>li:not(:first-child)>.header *{white-space:nowrap;flex-wrap:nowrap}.consul-exposed-path-list>ul>li>.detail>span,.consul-lock-session-list ul>li:not(:first-child)>.detail>span,.consul-upstream-instance-list li>.detail>span,.list-collection>ul>li:not(:first-child)>.detail>span{margin-right:18px}.consul-intention-permission-header-list>ul>li,.consul-intention-permission-list>ul>li{padding-top:0!important;padding-bottom:0!important}.consul-intention-permission-header-list>ul>li .detail,.consul-intention-permission-list>ul>li .detail{grid-row-start:header!important;grid-row-end:detail!important;align-self:center!important;padding:5px 0}.consul-intention-permission-header-list>ul>li .popover-menu>[type=checkbox]+label,.consul-intention-permission-list>ul>li .popover-menu>[type=checkbox]+label{padding:0}.consul-intention-permission-header-list>ul>li .popover-menu>[type=checkbox]+label+div:not(.above),.consul-intention-permission-list>ul>li .popover-menu>[type=checkbox]+label+div:not(.above){top:30px}.has-error>strong{font-style:normal;font-weight:400;color:inherit;color:var(--token-color-foreground-critical);position:relative;padding-left:20px}.has-error>strong::before{font-size:14px;color:var(--token-color-foreground-critical);position:absolute;top:50%;left:0;margin-top:-8px}.more-popover-menu .popover-menu>[type=checkbox]+label,table.has-actions tr>.actions .popover-menu>[type=checkbox]+label,table.with-details tr>.actions .popover-menu>[type=checkbox]+label{padding:7px}.more-popover-menu .popover-menu>[type=checkbox]+label>*,table.has-actions tr>.actions .popover-menu>[type=checkbox]+label>*,table.with-details tr>.actions .popover-menu>[type=checkbox]+label>*{background-color:transparent;border-radius:var(--decor-radius-100);width:30px;height:30px;font-size:0}.more-popover-menu .popover-menu>[type=checkbox]+label>:active,.more-popover-menu .popover-menu>[type=checkbox]+label>:focus,.more-popover-menu .popover-menu>[type=checkbox]+label>:hover,.radio-card>:first-child,table.has-actions tr>.actions .popover-menu>[type=checkbox]+label>:active,table.has-actions tr>.actions .popover-menu>[type=checkbox]+label>:focus,table.has-actions tr>.actions .popover-menu>[type=checkbox]+label>:hover,table.with-details td:only-child>div>label:active,table.with-details td:only-child>div>label:focus,table.with-details td:only-child>div>label:hover,table.with-details td>label:active,table.with-details td>label:focus,table.with-details td>label:hover,table.with-details tr>.actions .popover-menu>[type=checkbox]+label>:active,table.with-details tr>.actions .popover-menu>[type=checkbox]+label>:focus,table.with-details tr>.actions .popover-menu>[type=checkbox]+label>:hover{background-color:var(--token-color-surface-strong)}.more-popover-menu .popover-menu>[type=checkbox]+label>::after,table.has-actions tr>.actions .popover-menu>[type=checkbox]+label>::after,table.with-details tr>.actions .popover-menu>[type=checkbox]+label>::after{--icon-name:icon-more-horizontal;--icon-color:var(--token-color-foreground-strong);--icon-size:icon-300;content:"";position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.oidc-select [class$=-oidc-provider]::before{width:22px;height:22px;flex:0 0 auto;margin-right:10px}.oidc-select .ember-power-select-trigger,.oidc-select li{margin-bottom:1em}.informed-action header,.radio-card header{margin-bottom:.5em}.oidc-select .ember-power-select-trigger{width:100%}.radio-card{border:var(--decor-border-100);border-radius:var(--decor-radius-100);border-color:var(--token-color-surface-interactive-active);cursor:pointer;float:none!important;margin-right:0!important;display:flex!important}.checked.radio-card{border-color:var(--token-color-foreground-action)}.checked.radio-card>:first-child{background-color:var(--token-color-surface-action)}.radio-card header{color:var(--token-color-hashicorp-brand)}.consul-intention-fieldsets .radio-card>:last-child{padding-left:47px;position:relative}.consul-intention-fieldsets .radio-card>:last-child::before{position:absolute;left:14px;font-size:1rem}.radio-card>:first-child{padding:10px;display:grid;align-items:center;justify-items:center}.radio-card>:last-child{padding:18px}.consul-server-card,.disclosure-menu [aria-expanded]~*,.menu-panel,.more-popover-menu>[type=checkbox]+label+div,.popover-menu>[type=checkbox]+label+div,section[data-route="dc.show.license"] aside,section[data-route="dc.show.serverstatus"] .server-failure-tolerance,table.has-actions tr>.actions>[type=checkbox]+label+div,table.with-details tr>.actions>[type=checkbox]+label+div{--tone-border:var(--token-color-palette-neutral-300);border:var(--decor-border-100);border-radius:var(--decor-radius-200);box-shadow:var(--token-surface-high-box-shadow);color:var(--token-color-foreground-strong);background-color:var(--token-color-surface-primary);--padding-x:14px;--padding-y:14px;position:relative}.disclosure-menu [aria-expanded]~* [role=separator],.menu-panel [role=separator],.more-popover-menu>[type=checkbox]+label+div [role=separator],.popover-menu>[type=checkbox]+label+div [role=separator],table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]{border-top:var(--decor-border-100);margin:0}.consul-server-card,.disclosure-menu [aria-expanded]~*,.disclosure-menu [aria-expanded]~* [role=separator],.menu-panel,.menu-panel [role=separator],.more-popover-menu>[type=checkbox]+label+div,.more-popover-menu>[type=checkbox]+label+div [role=separator],.popover-menu>[type=checkbox]+label+div,.popover-menu>[type=checkbox]+label+div [role=separator],section[data-route="dc.show.license"] aside,section[data-route="dc.show.serverstatus"] .server-failure-tolerance,table.has-actions tr>.actions>[type=checkbox]+label+div,table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],table.with-details tr>.actions>[type=checkbox]+label+div,table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]{border-color:var(--tone-border)}.paged-collection-scroll,[style*="--paged-row-height"]{overflow-y:auto!important;will-change:scrollPosition}[style*="--paged-start"]::before{content:"";display:block;height:var(--paged-start)}.consul-auth-method-type,.consul-external-source,.consul-health-check-list .health-check-output dd em,.consul-intention-list td strong,.consul-intention-permission-list strong,.consul-intention-search-bar li button span,.consul-kind,.consul-peer-search-bar li button span,.consul-server-card .health-status+dd,.consul-source,.consul-transparent-proxy,.discovery-chain .route-card>header ul li,.hashicorp-consul nav .dcs .dc-name span,.hashicorp-consul nav .dcs li.is-local span,.hashicorp-consul nav .dcs li.is-primary span,.leader,.search-bar-status li:not(.remove-all),.topology-metrics-source-type,html[data-route^="dc.acls.index"] main td strong,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em,span.policy-node-identity,span.policy-service-identity{border-radius:var(--decor-radius-100);display:inline-flex;position:relative;align-items:center;white-space:nowrap}.consul-auth-method-type::before,.consul-external-source::before,.consul-health-check-list .health-check-output dd em::before,.consul-intention-list td strong::before,.consul-intention-permission-list strong::before,.consul-intention-search-bar li button span::before,.consul-kind::before,.consul-peer-search-bar li button span::before,.consul-server-card .health-status+dd::before,.consul-source::before,.consul-transparent-proxy::before,.discovery-chain .route-card>header ul li::before,.hashicorp-consul nav .dcs .dc-name span::before,.hashicorp-consul nav .dcs li.is-local span::before,.hashicorp-consul nav .dcs li.is-primary span::before,.leader::before,.search-bar-status li:not(.remove-all)::before,.topology-metrics-source-type::before,html[data-route^="dc.acls.index"] main td strong::before,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl::before,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em::before,span.policy-node-identity::before,span.policy-service-identity::before{margin-right:4px;--icon-size:icon-300}.consul-auth-method-type,.consul-external-source,.consul-kind,.consul-server-card .health-status+dd,.consul-source,.consul-transparent-proxy,.hashicorp-consul nav .dcs .dc-name span,.leader,.search-bar-status li:not(.remove-all),.topology-metrics-source-type,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em,span.policy-node-identity,span.policy-service-identity{padding:0 8px;--icon-size:icon-200}.consul-intention-permission-list strong,.consul-peer-search-bar li button span,.discovery-chain .route-card>header ul li,html[data-route^="dc.acls.index"] main td strong,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl{padding:1px 5px}.consul-intention-list td strong,.consul-intention-search-bar li button span{padding:4px 8px}span.policy-node-identity::before,span.policy-service-identity::before{vertical-align:unset}span.policy-node-identity::before{content:"Node Identity: "}span.policy-service-identity::before{content:"Service Identity: "}.more-popover-menu>[type=checkbox]+label>*,.popover-menu>[type=checkbox]+label>*,table.has-actions tr>.actions>[type=checkbox]+label>*,table.with-details tr>.actions>[type=checkbox]+label>*{cursor:pointer}.more-popover-menu>[type=checkbox]+label>::after,.popover-menu>[type=checkbox]+label>::after,table.has-actions tr>.actions>[type=checkbox]+label>::after,table.with-details tr>.actions>[type=checkbox]+label>::after{width:16px;height:16px;position:relative}.more-popover-menu,.popover-menu,table.has-actions tr>.actions,table.with-details tr>.actions{position:relative}.more-popover-menu>[type=checkbox]+label,.popover-menu>[type=checkbox]+label,table.has-actions tr>.actions>[type=checkbox]+label,table.with-details tr>.actions>[type=checkbox]+label{display:block}.more-popover-menu>[type=checkbox]+label+div,.popover-menu>[type=checkbox]+label+div,table.has-actions tr>.actions>[type=checkbox]+label+div,table.with-details tr>.actions>[type=checkbox]+label+div{min-width:192px}.more-popover-menu>[type=checkbox]+label+div:not(.above),.popover-menu>[type=checkbox]+label+div:not(.above),table.has-actions tr>.actions>[type=checkbox]+label+div:not(.above),table.with-details tr>.actions>[type=checkbox]+label+div:not(.above){top:38px}.more-popover-menu>[type=checkbox]+label+div:not(.left),.popover-menu>[type=checkbox]+label+div:not(.left),table.has-actions tr>.actions>[type=checkbox]+label+div:not(.left),table.with-details tr>.actions>[type=checkbox]+label+div:not(.left){right:5px}.popover-menu .menu-panel{position:absolute!important}.popover-select label{height:100%}.popover-select label>*{padding:0 8px!important;height:100%!important;justify-content:space-between!important;min-width:auto!important}.popover-select label>::after{margin-left:6px}.popover-select button::before{margin-right:10px}.popover-select .value-passing button::before{color:var(--token-color-foreground-success)}.popover-select .value-warning button::before{color:var(--token-color-foreground-warning)}.popover-select .value-critical button::before{color:var(--token-color-foreground-critical)}.popover-select .value-empty button::before{color:var(--token-color-foreground-disabled)}.popover-select .value-unknown button::before,.type-source.popover-select li.partition button::before{color:var(--token-color-foreground-faint)}.type-source.popover-select li.aws button{text-transform:uppercase}.progress.indeterminate{width:100%;display:flex;align-items:center;justify-content:center;--icon-size:icon-700;--icon-name:var(--icon-loading);--icon-color:var(--token-color-foreground-faint)}.progress.indeterminate::before{content:""}.app-view>div form:not(.filter-bar) [role=radiogroup],.modal-dialog [role=document] [role=radiogroup]{overflow:hidden;padding-left:1px}.app-view>div form:not(.filter-bar) [role=radiogroup] label,.modal-dialog [role=document] [role=radiogroup] label{float:left}.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.modal-dialog [role=document] [role=radiogroup] label>span{float:right;margin-left:1em}.app-view>div form:not(.filter-bar) [role=radiogroup] label:not(:last-child),.modal-dialog [role=document] [role=radiogroup] label:not(:last-child){margin-right:25px}.app-view>div form:not(.filter-bar) [role=radiogroup] label,.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.modal-dialog [role=document] [role=radiogroup] label,.modal-dialog [role=document] [role=radiogroup] label>span{margin-bottom:0!important}.type-toggle label span{cursor:pointer}.type-toggle label span::after{border-radius:var(--decor-radius-full)}.type-toggle label span::before{border-radius:7px;left:0;width:24px;height:12px;margin-top:-5px}.type-negative.type-toggle{border:0}.app-view>header .title,.modal-dialog [role=document] table td,.modal-dialog [role=document] table th,main table td,main table th{border-bottom:var(--decor-border-100)}.type-toggle label span::after{background-color:var(--token-color-surface-primary);margin-top:-3px;width:8px;height:8px}.app .skip-links,.type-negative.type-toggle label input+span::before,.type-toggle label input:checked+span::before{background-color:var(--token-color-foreground-action)}.type-negative.type-toggle label input:checked+span::before,.type-toggle label span::before{background-color:var(--token-color-palette-neutral-300)}.type-toggle label{position:relative}.type-toggle input{display:none}.type-toggle label span{color:var(--token-color-foreground-strong);display:inline-block;padding-left:34px}.type-toggle label span::after,.type-toggle label span::before{position:absolute;display:block;content:"";top:50%}.type-negative.type-toggle label input+span::after,.type-toggle label input:checked+span::after{left:14px}.type-negative.type-toggle label input:checked+span::after,.type-toggle label span::after{left:2px}.modal-dialog [role=document] table th,main table th{border-color:var(--token-color-palette-neutral-300);padding:.6em 0}.modal-dialog [role=document] table td,main table td{border-color:var(--token-color-surface-interactive-active);color:var(--token-color-foreground-faint);height:50px;vertical-align:middle}.modal-dialog [role=document] table td strong,.modal-dialog [role=document] table th,main table td strong,main table th{color:var(--token-color-foreground-faint)}.consul-intention-list td.destination,.consul-intention-list td.source,.modal-dialog [role=document] table a,.modal-dialog [role=document] table td:first-child,.tomography-graph .tick text,main table a,main table td:first-child{color:var(--token-color-foreground-strong)}.modal-dialog [role=document] table,main table{width:100%;border-collapse:collapse}table.dom-recycling tr{display:flex}table.dom-recycling tr>*{flex:1 1 auto;display:inline-flex;align-items:center}.modal-dialog [role=document] table caption,.modal-dialog [role=document] table thead th,main table caption,main table thead th{text-align:left}.modal-dialog [role=document] table th.actions input,main table th.actions input{display:none}.modal-dialog [role=document] table th.actions,main table th.actions{text-align:right}.modal-dialog [role=document] table td a,main table td a{display:block}.modal-dialog [role=document] table td.no-actions~.actions,main table td.no-actions~.actions{display:none}.modal-dialog [role=document] table td:not(.actions)>:only-child,main table td:not(.actions)>:only-child{overflow:hidden;text-overflow:ellipsis}.modal-dialog [role=document] table td:not(.actions)>*,main table td:not(.actions)>*{white-space:nowrap}.modal-dialog [role=document] table caption,main table caption{margin-bottom:.8em}.modal-dialog [role=document] table td a,.modal-dialog [role=document] table td:not(.actions),.modal-dialog [role=document] table th:not(.actions),main table td a,main table td:not(.actions),main table th:not(.actions){padding-right:.9em}.modal-dialog [role=document] table tbody td em,main table tbody td em{display:block;font-style:normal;font-weight:400;color:var(--token-color-foreground-faint)}table.has-actions tr>.actions,table.with-details tr>.actions{width:60px!important;overflow:visible}table.has-actions tr>.actions>[type=checkbox]+label,table.with-details tr>.actions>[type=checkbox]+label{position:absolute;right:5px}table.consul-metadata-list tbody tr{cursor:default}table.consul-metadata-list tbody tr:hover{box-shadow:none}.modal-dialog [role=document] table th span::after,main table th span::after{color:var(--token-color-foreground-faint);margin-left:4px}.modal-dialog [role=document] table tbody tr,main table tbody tr{cursor:pointer}.modal-dialog [role=document] table td:first-child,main table td:first-child{padding:0}.modal-dialog [role=document] table tbody tr:hover,main table tbody tr:hover{box-shadow:var(--token-elevation-high-box-shadow)}.modal-dialog [role=document] table td.folder::before,main table td.folder::before{background-color:var(--token-color-palette-neutral-300);margin-top:1px;margin-right:5px}@media (max-width:420px){.consul-intention-list tr>:nth-last-child(2),.modal-dialog [role=document] table tr>.actions,main table tr>.actions{display:none}}.voting-status-leader.consul-server-card .name{width:var(--tile-size,3rem);height:var(--tile-size,3rem)}.voting-status-leader.consul-server-card .name::before{display:block;content:"";width:100%;height:100%;border-radius:var(--decor-radius-250);border:var(--decor-border-100);background-image:linear-gradient(135deg,var(--token-color-consul-surface) 0,var(--token-color-consul-border) 100%);border-color:var(--token-color-border-faint)}.voting-status-leader.consul-server-card .name::after{content:"";position:absolute;top:calc(var(--tile-size,3rem)/ 4);left:calc(var(--tile-size,3rem)/ 4);--icon-name:icon-star-fill;--icon-size:icon-700;color:var(--token-color-consul-brand)}table.with-details td:only-child>div>label,table.with-details td>label{border-radius:var(--decor-radius-100);cursor:pointer;min-width:30px;min-height:30px;display:inline-flex;align-items:center;justify-content:center}table.dom-recycling tbody{top:33px!important;width:100%}table.dom-recycling caption~tbody{top:57px!important}table tr>:nth-last-child(2):first-child,table tr>:nth-last-child(2):first-child~*{width:50%}table tr>:nth-last-child(3):first-child,table tr>:nth-last-child(3):first-child~*{width:33.3333333333%}table tr>:nth-last-child(4):first-child,table tr>:nth-last-child(4):first-child~*{width:25%}table tr>:nth-last-child(5):first-child,table tr>:nth-last-child(5):first-child~*{width:20%}table.has-actions tr>:nth-last-child(2):first-child,table.has-actions tr>:nth-last-child(2):first-child~*{width:calc(100% - 60px)}table.has-actions tr>:nth-last-child(3):first-child,table.has-actions tr>:nth-last-child(3):first-child~*{width:calc(50% - 30px)}table.has-actions tr>:nth-last-child(4):first-child,table.has-actions tr>:nth-last-child(4):first-child~*{width:calc(33% - 20px)}table.has-actions tr>:nth-last-child(5):first-child,table.has-actions tr>:nth-last-child(5):first-child~*{width:calc(25% - 15px)}html[data-route^="dc.acls.policies"] [role=dialog] table tr>:not(last-child),html[data-route^="dc.acls.policies"] table tr>:not(last-child),html[data-route^="dc.acls.roles"] [role=dialog] table tr>:not(last-child),html[data-route^="dc.acls.roles"] main table.token-list tr>:not(last-child){width:120px}html[data-route^="dc.acls.policies"] table tr>:last-child,html[data-route^="dc.acls.roles"] [role=dialog] table tr>:last-child,html[data-route^="dc.acls.roles"] main table.token-list tr>:last-child{width:calc(100% - 240px)!important}table.with-details td:only-child{cursor:default;border:0}table.with-details td:only-child>div::before,table.with-details td:only-child>div>div,table.with-details td:only-child>div>label{background-color:var(--token-color-surface-primary)}table.with-details td:only-child>div>label::before{transform:rotate(180deg)}table.with-details td:only-child>div::before{background:var(--token-color-surface-interactive-active);content:"";display:block;height:1px;position:absolute;bottom:-20px;left:10px;width:calc(100% - 20px)}table.with-details tr>.actions{position:relative}table.with-details td:only-child>div>label,table.with-details td>label{pointer-events:auto;position:absolute;top:8px}table.with-details td:only-child>div>label span,table.with-details td>label span{display:none}table.with-details td>label{right:2px}table.with-details tr:nth-child(even) td{height:auto;position:relative;display:table-cell}table.with-details tr:nth-child(even) td>*{display:none}table.with-details td:only-child>div>label{right:11px}table.with-details tr:nth-child(even) td>input:checked+*{display:block}table.with-details td:only-child{overflow:visible;width:100%}table.with-details td:only-child>div{border:1px solid var(--token-color-palette-neutral-300);border-radius:var(--decor-radius-100);box-shadow:var(--token-surface-high-box-shadow);margin-bottom:20px;position:relative;left:-10px;right:-10px;width:calc(100% + 20px);margin-top:-51px;pointer-events:none;padding:10px}table.with-details td:only-child>div::after{content:"";display:block;clear:both}table.with-details td:only-child>div>div{pointer-events:auto;margin-top:36px}.consul-auth-method-binding-list dl,.consul-auth-method-view dl,.consul-auth-method-view section dl{display:flex;flex-wrap:wrap}.consul-auth-method-binding-list dl dd,.consul-auth-method-binding-list dl dt,.consul-auth-method-view dl dd,.consul-auth-method-view dl dt{padding:12px 0;margin:0;border-top:1px solid!important}.consul-auth-method-binding-list dl dt,.consul-auth-method-view dl dt{width:20%;font-weight:var(--typo-weight-bold)}.consul-auth-method-binding-list dl dd,.consul-auth-method-view dl dd{margin-left:auto;width:80%;display:flex}.consul-auth-method-binding-list dl dd>ul li,.consul-auth-method-view dl dd>ul li{display:flex}.consul-auth-method-binding-list dl dd>ul li:not(:last-of-type),.consul-auth-method-view dl dd>ul li:not(:last-of-type){padding-bottom:12px}.consul-auth-method-binding-list dl dt.check+dd,.consul-auth-method-view dl dt.check+dd{padding-top:16px}.consul-auth-method-binding-list dl>dd:last-of-type,.consul-auth-method-binding-list dl>dt:last-of-type,.consul-auth-method-view dl>dd:last-of-type,.consul-auth-method-view dl>dt:last-of-type{border-bottom:1px solid!important;border-color:var(--token-color-palette-neutral-300)!important}.consul-auth-method-binding-list dl dd,.consul-auth-method-binding-list dl dt,.consul-auth-method-view dl dd,.consul-auth-method-view dl dt{border-color:var(--token-color-palette-neutral-300)!important;color:var(--token-color-hashicorp-brand)!important}.consul-auth-method-binding-list dl dd .copy-button button::before,.consul-auth-method-view dl dd .copy-button button::before{background-color:var(--token-color-hashicorp-brand)}.consul-auth-method-binding-list dl dt.type+dd span::before,.consul-auth-method-view dl dt.type+dd span::before{margin-left:4px;background-color:var(--token-color-foreground-faint)}.tooltip-panel dt{cursor:pointer}.tooltip-panel dd>div::before{width:12px;height:12px;background-color:var(--token-color-surface-primary);border-top:1px solid var(--token-color-palette-neutral-300);border-right:1px solid var(--token-color-palette-neutral-300);transform:rotate(-45deg);position:absolute;left:16px;top:-7px}.tooltip-panel,.tooltip-panel dt{display:flex;flex-direction:column}.tooltip-panel dd>div.menu-panel{top:auto;overflow:visible}.tooltip-panel dd{display:none;position:relative;z-index:1;padding-top:10px;margin-bottom:-10px}.tooltip-panel:hover dd{display:block}.tooltip-panel dd>div{width:250px}.app-view>header .title{display:grid;grid-template-columns:1fr auto;grid-template-areas:"title actions";position:relative;z-index:5;padding-bottom:1.4em}.app-view>div form:not(.filter-bar) fieldset{border-bottom:var(--decor-border-200)}.app-view>header h1>em{color:var(--token-color-foreground-faint)}.app-view>header dd>a{color:var(--token-color-hashicorp-brand)}.app-view>div div>dl>dd,[role=contentinfo]{color:var(--token-color-foreground-disabled)}.app-view>div form:not(.filter-bar) fieldset,.app-view>header .title{border-color:var(--token-color-surface-interactive-active)}.app-view>header .title .title-left-container{grid-area:title;display:flex;flex-wrap:wrap;align-items:center;white-space:normal}.app-view>header .title .title-left-container>:first-child{flex-basis:100%}.app-view>header .title .title-left-container>:not(:first-child){margin-right:8px}.app-view>header .actions{grid-area:actions;align-self:end;display:flex;align-items:flex-start;margin-left:auto;margin-top:9px}.app-view>div form:not(.filter-bar) fieldset{padding-bottom:.3em;margin-bottom:2em}[for=toolbar-toggle]{background-position:0 4px;display:inline-block;width:26px;height:26px;cursor:pointer;color:var(--token-color-foreground-action)}#toolbar-toggle{display:none}@media (max-width:849px){.app-view>header .actions{margin-top:9px}}@media (min-width:996px){[for=toolbar-toggle]{display:none}}@media (max-width:995px){.app-view>header h1{display:inline-block}html[data-route$="dc.services.instance.show"] h1{display:block}#toolbar-toggle+*{display:none}#toolbar-toggle:checked+*{display:flex}}.brand-loader{position:absolute;top:50%;margin-top:-26px;left:50%}.app .skip-links{outline:solid var(--token-color-surface-primary);color:var(--token-color-surface-primary);display:flex;flex-direction:column;position:absolute;z-index:10;left:50%;padding:20px;top:-100px;transform:translateX(-50%)}.app .skip-links a,.app .skip-links button{color:inherit}.app .skip-links a,.app .skip-links button,.app .skip-links div{display:block;width:100%;text-align:center;box-sizing:border-box}.app .skip-links:focus-within{top:0}.app .notifications{position:fixed;z-index:100;bottom:2rem;left:1.5rem;pointer-events:none}.app .notifications .app-notification>*{min-width:400px}.app .notifications .app-notification{transition-property:opacity;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;max-width:80%;pointer-events:auto}[role=banner] nav:last-of-type{margin-left:auto}.hashicorp-consul nav .dcs{top:18px}.hashicorp-consul nav .dcs [aria-label]::before{display:none!important}[role=banner] nav:last-of-type [aria-haspopup=menu]~*{position:absolute;right:0;min-width:192px}[role=contentinfo]{position:fixed;z-index:50;width:250px;padding-left:25px;top:calc(100vh - 42px);top:calc(max(100vh,460px) - 42px)}html.has-partitions.has-nspaces .app [role=contentinfo]{top:calc(100vh - 42px);top:calc(max(100vh,640px) - 42px)}[role=banner] nav:first-of-type{z-index:10}[role=banner] nav:first-of-type,[role=contentinfo]{transition-property:left}.app .notifications,main{margin-top:var(--chrome-height,64px);transition-property:margin-left}.app .notifications{transition-property:margin-left,width}@media (min-width:900px){.app>input[id]~main .notifications{width:calc(100% - var(--chrome-width))}.app>input[id]:checked~main .notifications{width:100%}.app>input[id]+header>div>nav:first-of-type,.app>input[id]~footer{left:0}.app>input[id]:checked+header>div>nav:first-of-type,.app>input[id]:checked~footer{left:calc(var(--chrome-width,280px) * -1)}.app>input[id]~main{margin-left:var(--chrome-width,280px)}.app>input[id]:checked~main,.app>input[id]:checked~main .notifications{margin-left:0}}@media (max-width:899px){.app>input[id]~main .notifications{width:100%}.app>input[id]:checked+header>div>nav:first-of-type,.app>input[id]:checked~footer{left:0}.app>input[id]+header>div>nav:first-of-type,.app>input[id]~footer{left:calc(var(--chrome-width,280px) * -1)}.app>input[id]~main,.app>input[id]~main .notifications{margin-left:0}}[role=banner]::before{background-color:var(--token-color-hashicorp-brand);content:"";position:absolute;z-index:-1;left:0;width:100vw}[role=banner]{display:flex;position:fixed;z-index:50;left:0;padding:0 25px;width:calc(100% - 50px);align-items:center}[role=banner],[role=banner]::before{height:var(--chrome-height)}[role=banner]>a{display:block;line-height:0;font-size:0}.hashicorp-consul nav .dcs [aria-expanded]>a,[role=banner] nav:last-of-type [aria-expanded]>a,[role=banner] nav:last-of-type>ul>li>a>a,[role=banner] nav:last-of-type>ul>li>button>a,[role=banner] nav:last-of-type>ul>li>span>a{color:inherit}.hashicorp-consul nav .dcs [aria-expanded]::after,[role=banner] nav:last-of-type [aria-expanded]::after{--icon-name:icon-chevron-down;content:""}.hashicorp-consul nav .dcs [aria-expanded=true][aria-expanded]::after,[role=banner] nav:last-of-type [aria-expanded=true][aria-expanded]::after{transform:scaleY(-100%)}[role=banner] nav:last-of-type .disclosure-menu button+*,[role=banner] nav:last-of-type .disclosure-menu button+*>ul[role=menu],[role=banner] nav:last-of-type .disclosure-menu button+*>ul[role=menu]>li>[role=menuitem]{background-color:var(--token-color-hashicorp-brand);color:var(--token-color-palette-neutral-300)}[role=banner] nav:last-of-type .disclosure-menu button+*>ul[role=menu]>li>[role=menuitem]:hover{background-color:var(--token-color-palette-neutral-600)}.app>input[id]{display:none}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.menu-panel>ul>[role=treeitem],.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],[role=banner] nav:last-of-type>ul,[role=banner]>div,[role=banner]>label,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{display:flex}[role=banner]>label::before{--icon-name:icon-menu;--icon-color:var(--token-color-palette-neutral-300);content:"";cursor:pointer}.hashicorp-consul nav .dcs [aria-expanded],[role=banner] nav:last-of-type .popover-menu [type=checkbox]:checked+label>*,[role=banner] nav:last-of-type [aria-expanded],[role=banner] nav:last-of-type>ul>li>.popover-menu>label>button,[role=banner] nav:last-of-type>ul>li>a,[role=banner] nav:last-of-type>ul>li>button,[role=banner] nav:last-of-type>ul>li>span{color:var(--token-color-palette-neutral-300)}[role=banner]>label{align-items:center;height:100%;padding:0 1rem 0 5px}[role=banner]>div{justify-content:space-between;flex-grow:1}[role=banner] nav:last-of-type .disclosure-menu button+*{z-index:400;top:28px!important}.hashicorp-consul nav .dcs [aria-expanded],[role=banner] nav:last-of-type [aria-expanded],[role=banner] nav:last-of-type>ul>li>.popover-menu>label>button,[role=banner] nav:last-of-type>ul>li>a,[role=banner] nav:last-of-type>ul>li>button,[role=banner] nav:last-of-type>ul>li>span{border-radius:var(--decor-radius-200);cursor:pointer;display:block;padding:5px 12px;white-space:nowrap}[role=banner] nav:last-of-type .popover-menu>label{padding-right:5px}[role=banner] nav:last-of-type .popover-menu>label>*{padding-right:4px!important}[role=banner] nav:last-of-type .popover-menu>label>button::after{top:2px}[role=banner] nav:last-of-type>ul>li>span{cursor:default}[role=banner] nav:first-of-type a>a,[role=banner] nav:first-of-type>ul>li>label>a{color:inherit;font-size:inherit}[role=banner] nav:first-of-type [role=separator]{text-transform:uppercase;font-weight:var(--typo-weight-medium)}[role=banner] nav:first-of-type a:focus,[role=banner] nav:first-of-type a:hover,[role=banner] nav:first-of-type>ul>li>label:focus,[role=banner] nav:first-of-type>ul>li>label:hover{text-decoration:underline}.tab-nav li>*,[role=banner] nav:first-of-type>ul>li.is-active>a:focus:not(:active),[role=banner] nav:first-of-type>ul>li.is-active>a:hover:not(:active){text-decoration:none}[role=banner] nav:first-of-type{background-color:var(--token-color-foreground-strong);color:var(--token-color-foreground-faint)}[role=banner] nav:first-of-type li:not([role=separator])>span{color:var(--token-color-palette-neutral-300)}.hashicorp-consul nav .dcs [role=separator],[role=banner] nav:first-of-type [role=separator]{color:var(--token-color-palette-neutral-400);background-color:var(--token-color-foreground-strong)}[role=banner] nav:first-of-type a,[role=banner] nav:first-of-type>ul>li>label{cursor:pointer;border-right:var(--decor-border-400);border-color:transparent;color:var(--token-color-palette-neutral-300)}[role=banner] nav:first-of-type a:focus,[role=banner] nav:first-of-type a:hover,[role=banner] nav:first-of-type>ul>li.is-active>a,[role=banner] nav:first-of-type>ul>li>label:focus,[role=banner] nav:first-of-type>ul>li>label:hover,[role=banner] nav:first-of-type>ul>li[aria-label]{color:var(--token-color-palette-neutral-0)}[role=banner] nav:first-of-type>ul>li.is-active>a{background-color:var(--token-color-palette-neutral-500);border-color:var(--token-color-palette-neutral-0)}[role=banner] nav:first-of-type [aria-label]::before{color:var(--token-color-palette-neutral-400);content:attr(aria-label);display:block;margin-top:-.5rem;margin-bottom:.5rem}.hashicorp-consul nav li.nspaces .disclosure-menu>button,.hashicorp-consul nav li.partitions .disclosure-menu>button{border:var(--decor-border-100);border-color:var(--token-color-foreground-faint);border-radius:var(--decor-radius-100);font-weight:inherit;background-color:var(--token-color-foreground-strong);color:var(--token-color-palette-neutral-200)}.hashicorp-consul nav li.nspaces .disclosure-menu>button:focus,.hashicorp-consul nav li.nspaces .disclosure-menu>button:hover,.hashicorp-consul nav li.partitions .disclosure-menu>button:focus,.hashicorp-consul nav li.partitions .disclosure-menu>button:hover,[role=banner] nav:first-of-type ul[role=menu] li a[role=menuitem]{color:var(--token-color-palette-neutral-300);background-color:var(--token-color-foreground-strong)}[role=banner] nav:first-of-type ul[role=menu] li a[role=menuitem]:hover{background-color:var(--token-color-palette-neutral-600)}.hashicorp-consul nav li.nspaces .disclosure-menu>button[aria-expanded=true],.hashicorp-consul nav li.partitions .disclosure-menu>button[aria-expanded=true]{border-bottom-left-radius:var(--decor-radius-000);border-bottom-right-radius:var(--decor-radius-000)}.disclosure-menu [aria-expanded]~* [role=banner] nav:first-of-type [role=separator],.disclosure-menu [aria-expanded]~* [role=banner] nav:last-of-type [role=separator],.disclosure-menu [role=banner] nav:first-of-type [aria-expanded]~*,.disclosure-menu [role=banner] nav:last-of-type [aria-expanded]~*,.menu-panel [role=banner] nav:first-of-type [role=separator],.menu-panel [role=banner] nav:last-of-type [role=separator],.more-popover-menu>[type=checkbox]+label+div [role=banner] nav:first-of-type [role=separator],.more-popover-menu>[type=checkbox]+label+div [role=banner] nav:last-of-type [role=separator],.popover-menu>[type=checkbox]+label+div [role=banner] nav:first-of-type [role=separator],.popover-menu>[type=checkbox]+label+div [role=banner] nav:last-of-type [role=separator],[role=banner] nav:first-of-type .consul-server-card,[role=banner] nav:first-of-type .disclosure-menu [aria-expanded]~*,[role=banner] nav:first-of-type .disclosure-menu [aria-expanded]~* [role=separator],[role=banner] nav:first-of-type .menu-panel,[role=banner] nav:first-of-type .menu-panel [role=separator],[role=banner] nav:first-of-type .more-popover-menu>[type=checkbox]+label+div,[role=banner] nav:first-of-type .more-popover-menu>[type=checkbox]+label+div [role=separator],[role=banner] nav:first-of-type .popover-menu>[type=checkbox]+label+div,[role=banner] nav:first-of-type .popover-menu>[type=checkbox]+label+div [role=separator],[role=banner] nav:first-of-type section[data-route="dc.show.license"] aside,[role=banner] nav:first-of-type section[data-route="dc.show.serverstatus"] .server-failure-tolerance,[role=banner] nav:first-of-type table.has-actions tr>.actions>[type=checkbox]+label+div,[role=banner] nav:first-of-type table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],[role=banner] nav:first-of-type table.with-details tr>.actions>[type=checkbox]+label+div,[role=banner] nav:first-of-type table.with-details tr>.actions>[type=checkbox]+label+div [role=separator],[role=banner] nav:last-of-type .consul-server-card,[role=banner] nav:last-of-type .disclosure-menu [aria-expanded]~*,[role=banner] nav:last-of-type .disclosure-menu [aria-expanded]~* [role=separator],[role=banner] nav:last-of-type .menu-panel,[role=banner] nav:last-of-type .menu-panel [role=separator],[role=banner] nav:last-of-type .more-popover-menu>[type=checkbox]+label+div,[role=banner] nav:last-of-type .more-popover-menu>[type=checkbox]+label+div [role=separator],[role=banner] nav:last-of-type .popover-menu>[type=checkbox]+label+div,[role=banner] nav:last-of-type .popover-menu>[type=checkbox]+label+div [role=separator],[role=banner] nav:last-of-type section[data-route="dc.show.license"] aside,[role=banner] nav:last-of-type section[data-route="dc.show.serverstatus"] .server-failure-tolerance,[role=banner] nav:last-of-type table.has-actions tr>.actions>[type=checkbox]+label+div,[role=banner] nav:last-of-type table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],[role=banner] nav:last-of-type table.with-details tr>.actions>[type=checkbox]+label+div,[role=banner] nav:last-of-type table.with-details tr>.actions>[type=checkbox]+label+div [role=separator],section[data-route="dc.show.license"] [role=banner] nav:first-of-type aside,section[data-route="dc.show.license"] [role=banner] nav:last-of-type aside,section[data-route="dc.show.serverstatus"] [role=banner] nav:first-of-type .server-failure-tolerance,section[data-route="dc.show.serverstatus"] [role=banner] nav:last-of-type .server-failure-tolerance,table.has-actions [role=banner] nav:first-of-type tr>.actions>[type=checkbox]+label+div,table.has-actions [role=banner] nav:last-of-type tr>.actions>[type=checkbox]+label+div,table.has-actions tr>.actions>[type=checkbox]+label+div [role=banner] nav:first-of-type [role=separator],table.has-actions tr>.actions>[type=checkbox]+label+div [role=banner] nav:last-of-type [role=separator],table.with-details [role=banner] nav:first-of-type tr>.actions>[type=checkbox]+label+div,table.with-details [role=banner] nav:last-of-type tr>.actions>[type=checkbox]+label+div,table.with-details tr>.actions>[type=checkbox]+label+div [role=banner] nav:first-of-type [role=separator],table.with-details tr>.actions>[type=checkbox]+label+div [role=banner] nav:last-of-type [role=separator]{border-color:var(--token-color-foreground-faint)}.hashicorp-consul nav li.nspaces .disclosure-menu>button::after,.hashicorp-consul nav li.partitions .disclosure-menu>button::after{width:16px;height:16px;position:relative;float:right}.hashicorp-consul nav li.nspaces .disclosure-menu button+*,.hashicorp-consul nav li.partitions .disclosure-menu button+*{border-top-left-radius:var(--decor-radius-000);border-top-right-radius:var(--decor-radius-000);border-top:var(--decor-border-000);color:var(--token-color-palette-neutral-300);background-color:var(--token-color-foreground-strong)}.hashicorp-consul nav .dcs .dcs-message,.hashicorp-consul nav .dcs ul[role=menu]{background-color:var(--token-color-hashicorp-brand)}[role=banner] nav:first-of-type{position:absolute;left:0;top:var(--chrome-height,47px);width:var(--chrome-width,280px);height:calc(100vh - var(--chrome-height,47px) - 35px);padding-top:35px;overflow:auto}[role=banner] nav:first-of-type li.nspaces,[role=banner] nav:first-of-type li.partition,[role=banner] nav:first-of-type li.partitions{margin-bottom:25px;padding:0 26px}[role=banner] nav:first-of-type li.dcs{padding:0 18px}[role=banner] nav:first-of-type [role=menuitem]{justify-content:flex-start!important}[role=banner] nav:first-of-type [role=menuitem] span{margin-left:.5rem}[role=banner] nav:first-of-type [role=separator],[role=banner] nav:first-of-type a,[role=banner] nav:first-of-type li:not([role=separator])>span,[role=banner] nav:first-of-type>ul>li>label{display:block;padding:7px 25px}[role=banner] nav:first-of-type>ul>[role=separator]{margin-top:.7rem;padding-bottom:0}.hashicorp-consul nav li.nspaces .disclosure,.hashicorp-consul nav li.partitions .disclosure{position:relative}.hashicorp-consul nav li.nspaces .disclosure-menu>button,.hashicorp-consul nav li.partitions .disclosure-menu>button{width:100%;text-align:left;padding:10px}.hashicorp-consul nav li.nspaces .disclosure-menu button+*,.hashicorp-consul nav li.partitions .disclosure-menu button+*{position:absolute;z-index:1;width:calc(100% - 2px)}.hashicorp-consul nav .dcs{visibility:visible;position:fixed;z-index:10;left:100px}.hashicorp-consul nav .dcs .dcs-message{padding:8px 12px;border-bottom:1px solid var(--token-color-foreground-disabled);max-width:-webkit-fit-content;max-width:-moz-fit-content;max-width:fit-content;color:var(--token-color-palette-neutral-300)}.hashicorp-consul nav .dcs .dc-name{color:var(--token-color-foreground-faint);padding:3.25px 0;font-weight:var(--typo-weight-semibold)}.hashicorp-consul nav .dcs .dc-name span{margin-left:1rem;background-color:var(--token-color-palette-neutral-300);color:var(--token-color-hashicorp-brand)}.hashicorp-consul nav li.dcs [aria-expanded]~*{min-width:250px;max-height:560px;--paged-row-height:43px}.hashicorp-consul nav li.nspaces [aria-expanded]~*,.hashicorp-consul nav li.partitions [aria-expanded]~*{max-height:360px;--paged-row-height:43px}.hashicorp-consul [role=banner] a svg{fill:var(--token-color-consul-brand)}.hashicorp-consul .acls-separator span{color:var(--token-color-foreground-critical);display:inline-block;position:relative;top:2px;margin-left:2px}.disclosure-menu [aria-expanded]~*>div+ul,.menu-panel>div+ul,.more-popover-menu>[type=checkbox]+label+div>div+ul,.popover-menu>[type=checkbox]+label+div>div+ul,table.has-actions tr>.actions>[type=checkbox]+label+div>div+ul,table.with-details tr>.actions>[type=checkbox]+label+div>div+ul{border-top:var(--decor-border-100);border-color:var(--token-form--base-border-color-default)}.disclosure-menu [aria-expanded]~* [role=separator]:first-child:not(:empty),.menu-panel [role=separator]:first-child:not(:empty),.more-popover-menu>[type=checkbox]+label+div [role=separator]:first-child:not(:empty),.popover-menu>[type=checkbox]+label+div [role=separator]:first-child:not(:empty),table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator]:first-child:not(:empty),table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]:first-child:not(:empty){border:none}.disclosure-menu [aria-expanded]~* [role=separator],.menu-panel [role=separator],.more-popover-menu>[type=checkbox]+label+div [role=separator],.popover-menu>[type=checkbox]+label+div [role=separator],table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]{text-transform:uppercase;font-weight:var(--typo-weight-medium);color:var(--token-color-foreground-faint)}.disclosure-menu [aria-expanded]~*>ul>li,.menu-panel>ul>li,.more-popover-menu>[type=checkbox]+label+div>ul>li,.popover-menu>[type=checkbox]+label+div>ul>li,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li{list-style-type:none}.disclosure-menu [aria-expanded]~*>ul .informed-action,.menu-panel>ul .informed-action,.more-popover-menu>[type=checkbox]+label+div>ul .informed-action,.popover-menu>[type=checkbox]+label+div>ul .informed-action,table.has-actions tr>.actions>[type=checkbox]+label+div>ul .informed-action,table.with-details tr>.actions>[type=checkbox]+label+div>ul .informed-action{border:0!important}.disclosure-menu [aria-expanded]~*>div,.menu-panel>div,.more-popover-menu>[type=checkbox]+label+div>div,.popover-menu>[type=checkbox]+label+div>div,table.has-actions tr>.actions>[type=checkbox]+label+div>div,table.with-details tr>.actions>[type=checkbox]+label+div>div{padding:.625rem var(--padding-x);white-space:normal;max-width:-webkit-fit-content;max-width:-moz-fit-content;max-width:fit-content}@supports not ((max-width:-webkit-fit-content) or (max-width:-moz-fit-content) or (max-width:fit-content)){.disclosure-menu [aria-expanded]~*>div,.menu-panel>div,.more-popover-menu>[type=checkbox]+label+div>div,.popover-menu>[type=checkbox]+label+div>div,table.has-actions tr>.actions>[type=checkbox]+label+div>div,table.with-details tr>.actions>[type=checkbox]+label+div>div{max-width:200px}}.disclosure-menu [aria-expanded]~*>div::before,.menu-panel>div::before,.more-popover-menu>[type=checkbox]+label+div>div::before,.popover-menu>[type=checkbox]+label+div>div::before,table.has-actions tr>.actions>[type=checkbox]+label+div>div::before,table.with-details tr>.actions>[type=checkbox]+label+div>div::before{position:absolute;left:15px;top:calc(10px + .1em)}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem]+*,.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem]+*,.disclosure-menu [aria-expanded]~*>ul>li>[role=option]+*,.menu-panel-deprecated>ul>li>div[role=menu],.menu-panel>ul>[role=treeitem]+*,.menu-panel>ul>li>[role=menuitem]+*,.menu-panel>ul>li>[role=option]+*,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]+*,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]+*,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option]+*,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]+*,.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]+*,.popover-menu>[type=checkbox]+label+div>ul>li>[role=option]+*,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]+*,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]+*,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]+*,table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]+*,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]+*,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]+*{position:absolute;top:0;left:calc(100% + 10px)}.disclosure-menu [aria-expanded]~*>ul,.menu-panel>ul,.more-popover-menu>[type=checkbox]+label+div>ul,.popover-menu>[type=checkbox]+label+div>ul,table.has-actions tr>.actions>[type=checkbox]+label+div>ul,table.with-details tr>.actions>[type=checkbox]+label+div>ul{margin:0;padding:calc(var(--padding-y) - .625rem) 0;transition:transform 150ms}.disclosure-menu [aria-expanded]~*>ul,.disclosure-menu [aria-expanded]~*>ul>li,.disclosure-menu [aria-expanded]~*>ul>li>*,.menu-panel>ul,.menu-panel>ul>li,.menu-panel>ul>li>*,.more-popover-menu>[type=checkbox]+label+div>ul,.more-popover-menu>[type=checkbox]+label+div>ul>li,.more-popover-menu>[type=checkbox]+label+div>ul>li>*,.popover-menu>[type=checkbox]+label+div>ul,.popover-menu>[type=checkbox]+label+div>ul>li,.popover-menu>[type=checkbox]+label+div>ul>li>*,table.has-actions tr>.actions>[type=checkbox]+label+div>ul,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>*,table.with-details tr>.actions>[type=checkbox]+label+div>ul,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>*{width:100%}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem],.disclosure-menu [aria-expanded]~*>ul>li,.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem],.disclosure-menu [aria-expanded]~*>ul>li>[role=option],.menu-panel>ul>[role=treeitem],.menu-panel>ul>li,.menu-panel>ul>li>[role=menuitem],.menu-panel>ul>li>[role=option],.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.more-popover-menu>[type=checkbox]+label+div>ul>li,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option],.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem],.popover-menu>[type=checkbox]+label+div>ul>li,.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem],.popover-menu>[type=checkbox]+label+div>ul>li>[role=option],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option],table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem],table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]{text-align:left}.hashicorp-consul nav .dcs li.is-local span,.hashicorp-consul nav .dcs li.is-primary span{color:var(--token-color-surface-primary);background-color:var(--token-color-foreground-faint);padding:0 8px;margin-left:.5rem}.disclosure-menu [aria-expanded]~*>ul>[role=treeitem]::after,.disclosure-menu [aria-expanded]~*>ul>li>[role=menuitem]::after,.disclosure-menu [aria-expanded]~*>ul>li>[role=option]::after,.menu-panel>ul>[role=treeitem]::after,.menu-panel>ul>li>[role=menuitem]::after,.menu-panel>ul>li>[role=option]::after,.more-popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]::after,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]::after,.more-popover-menu>[type=checkbox]+label+div>ul>li>[role=option]::after,.popover-menu>[type=checkbox]+label+div>ul>[role=treeitem]::after,.popover-menu>[type=checkbox]+label+div>ul>li>[role=menuitem]::after,.popover-menu>[type=checkbox]+label+div>ul>li>[role=option]::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]::after,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>[role=treeitem]::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=menuitem]::after,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li>[role=option]::after{margin-left:auto;padding-right:var(--padding-x);transform:translate(calc(var(--padding-x)/ 2),0)}.disclosure-menu [aria-expanded]~* [role=separator],.menu-panel [role=separator],.more-popover-menu>[type=checkbox]+label+div [role=separator],.popover-menu>[type=checkbox]+label+div [role=separator],table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator],table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]{padding-top:.375rem}.disclosure-menu [aria-expanded]~* [role=separator]:not(:first-child),.menu-panel [role=separator]:not(:first-child),.more-popover-menu>[type=checkbox]+label+div [role=separator]:not(:first-child),.popover-menu>[type=checkbox]+label+div [role=separator]:not(:first-child),table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator]:not(:first-child),table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]:not(:first-child){margin-top:.275rem}.disclosure-menu [aria-expanded]~* [role=separator]:not(:empty),.menu-panel [role=separator]:not(:empty),.more-popover-menu>[type=checkbox]+label+div [role=separator]:not(:empty),.popover-menu>[type=checkbox]+label+div [role=separator]:not(:empty),table.has-actions tr>.actions>[type=checkbox]+label+div [role=separator]:not(:empty),table.with-details tr>.actions>[type=checkbox]+label+div [role=separator]:not(:empty){padding-left:var(--padding-x);padding-right:var(--padding-x);padding-bottom:.125rem}.disclosure-menu [aria-expanded]~.menu-panel-confirming,.menu-panel-confirming.menu-panel,.more-popover-menu>[type=checkbox]+label+div.menu-panel-confirming,.popover-menu>[type=checkbox]+label+div.menu-panel-confirming,table.has-actions tr>.actions>[type=checkbox]+label+div.menu-panel-confirming,table.with-details tr>.actions>[type=checkbox]+label+div.menu-panel-confirming{overflow:hidden}.disclosure-menu [aria-expanded]~.menu-panel-confirming>ul,.menu-panel-confirming.menu-panel>ul,.more-popover-menu>[type=checkbox]+label+div.menu-panel-confirming>ul,.popover-menu>[type=checkbox]+label+div.menu-panel-confirming>ul,table.has-actions tr>.actions>[type=checkbox]+label+div.menu-panel-confirming>ul,table.with-details tr>.actions>[type=checkbox]+label+div.menu-panel-confirming>ul{transform:translateX(calc(-100% - 10px))}.disclosure-menu [aria-expanded]~*,.menu-panel,.more-popover-menu>[type=checkbox]+label+div,.popover-menu>[type=checkbox]+label+div,table.has-actions tr>.actions>[type=checkbox]+label+div,table.with-details tr>.actions>[type=checkbox]+label+div{overflow:hidden}.menu-panel-deprecated{position:absolute;transition:max-height 150ms;transition:min-height 150ms,max-height 150ms;min-height:0}.menu-panel-deprecated [type=checkbox]{display:none}.menu-panel-deprecated:not(.confirmation) [type=checkbox]~*{transition:transform 150ms}.confirmation.menu-panel-deprecated [role=menu]{min-height:205px!important}.menu-panel-deprecated [type=checkbox]:checked~*{transform:translateX(calc(-100% - 10px));min-height:143px;max-height:143px}.menu-panel-deprecated [id$="-"]:first-child:checked~ul label[for$="-"] * [role=menu],.menu-panel-deprecated [id$="-"]:first-child:checked~ul>li>[role=menu]{display:block}.menu-panel-deprecated>ul>li>:not(div[role=menu]),.tippy-box{position:relative}.menu-panel-deprecated:not(.left){right:0!important;left:auto!important}.left.menu-panel-deprecated{left:0}.menu-panel-deprecated:not(.above){top:28px}.above.menu-panel-deprecated{bottom:42px}.consul-upstream-instance-list dl.local-bind-socket-mode dt::after{display:inline;content:var(--horizontal-kv-list-key-separator)}.consul-bucket-list,.consul-exposed-path-list>ul>li>.detail dl,.consul-instance-checks,.consul-lock-session-list dl,.consul-lock-session-list ul>li:not(:first-child)>.detail dl,.consul-upstream-instance-list dl,.consul-upstream-instance-list li>.detail dl,.list-collection>ul>li:not(:first-child)>.detail dl,.tag-list,section[data-route="dc.show.license"] .validity dl,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl,td.tags{display:inline-flex;flex-wrap:nowrap;align-items:center}.consul-bucket-list:empty,.consul-exposed-path-list>ul>li>.detail dl:empty,.consul-instance-checks:empty,.consul-lock-session-list dl:empty,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:empty,.consul-upstream-instance-list dl:empty,.list-collection>ul>li:not(:first-child)>.detail dl:empty,.tag-list:empty,section[data-route="dc.show.license"] .validity dl:empty,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:empty,td.tags:empty{display:none}.consul-bucket-list>*>*,.consul-exposed-path-list>ul>li>.detail dl>*>*,.consul-instance-checks>*>*,.consul-lock-session-list dl>*>*,.consul-lock-session-list ul>li:not(:first-child)>.detail dl>*>*,.consul-upstream-instance-list dl>*>*,.consul-upstream-instance-list li>.detail dl>*>*,.list-collection>ul>li:not(:first-child)>.detail dl>*>*,.tag-list>*>*,section[data-route="dc.show.license"] .validity dl>*>*,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl>*>*,td.tags>*>*{display:inline-block}.consul-bucket-list>*,.consul-exposed-path-list>ul>li>.detail dl>*,.consul-instance-checks>*,.consul-lock-session-list dl>*,.consul-lock-session-list ul>li:not(:first-child)>.detail dl>*,.consul-upstream-instance-list dl>*,.consul-upstream-instance-list li>.detail dl>*,.list-collection>ul>li:not(:first-child)>.detail dl>*,.tag-list>*,section[data-route="dc.show.license"] .validity dl>*,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl>*,td.tags>*{white-space:nowrap}.consul-bucket-list>dd,.consul-exposed-path-list>ul>li>.detail dl>dd,.consul-instance-checks>dd,.consul-lock-session-list dl>dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl>dd,.consul-upstream-instance-list dl>dd,.consul-upstream-instance-list li>.detail dl>dd,.list-collection>ul>li:not(:first-child)>.detail dl>dd,.tag-list>dd,section[data-route="dc.show.license"] .validity dl>dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl>dd,td.tags>dd{flex-wrap:wrap}.consul-upstream-instance-list dl.local-bind-socket-mode dt{display:inline-flex;min-width:18px;overflow:hidden}.consul-lock-session-list .checks dd,.discovery-chain .resolver-card ol,.filter-bar,.filter-bar>div,.modal-dialog,.tag-list dd,td.tags dd{display:flex}.consul-bucket-list .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-bucket-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-bucket-list .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.consul-bucket-list .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.consul-bucket-list .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-bucket-list .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-bucket-list .tag-list:not([class]) dd+dt:not([class])+dd,.consul-bucket-list dd+dt,.consul-bucket-list td.tags:not([class]) dd+dt:not([class])+dd,.consul-bucket-list+.consul-bucket-list:not(:first-of-type),.consul-bucket-list+.consul-instance-checks:not(:first-of-type),.consul-bucket-list+.tag-list:not(:first-of-type),.consul-bucket-list+td.tags:not(:first-of-type),.consul-bucket-list:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,.consul-bucket-list:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-bucket-list:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,.consul-bucket-list:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-bucket-list:not([class]) .tag-list dd+dt:not([class])+dd,.consul-bucket-list:not([class]) dd+dt:not([class])+dd,.consul-bucket-list:not([class]) td.tags dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail .consul-bucket-list+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail .consul-instance-checks+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail .consul-lock-session-list dl+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail .consul-upstream-instance-list dl+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.consul-exposed-path-list>ul>li>.detail .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.consul-exposed-path-list>ul>li>.detail .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail .tag-list+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail dl .consul-bucket-list:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl .consul-instance-checks:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl .consul-lock-session-list dl:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl .consul-upstream-instance-list dl:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl .tag-list:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl dd+dt,.consul-exposed-path-list>ul>li>.detail dl section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl td.tags:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl+.consul-bucket-list:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail dl+.consul-instance-checks:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail dl+.tag-list:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail dl+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail dl+td.tags:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail dl:not([class]) .consul-bucket-list dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) .consul-instance-checks dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) .consul-lock-session-list dl dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) .consul-upstream-instance-list dl dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) .tag-list dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) section[data-route="dc.show.license"] .validity dl dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) td.tags dd+dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),.consul-exposed-path-list>ul>li>.detail td.tags+dl:not(:first-of-type),.consul-instance-checks .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-instance-checks .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-instance-checks .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.consul-instance-checks .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.consul-instance-checks .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-instance-checks .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-instance-checks .tag-list:not([class]) dd+dt:not([class])+dd,.consul-instance-checks dd+dt,.consul-instance-checks td.tags:not([class]) dd+dt:not([class])+dd,.consul-instance-checks+.consul-bucket-list:not(:first-of-type),.consul-instance-checks+.consul-instance-checks:not(:first-of-type),.consul-instance-checks+.tag-list:not(:first-of-type),.consul-instance-checks+td.tags:not(:first-of-type),.consul-instance-checks:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,.consul-instance-checks:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-instance-checks:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,.consul-instance-checks:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-instance-checks:not([class]) .tag-list dd+dt:not([class])+dd,.consul-instance-checks:not([class]) dd+dt:not([class])+dd,.consul-instance-checks:not([class]) td.tags dd+dt:not([class])+dd,.consul-lock-session-list .consul-bucket-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-bucket-list+dl:not(:first-of-type),.consul-lock-session-list .consul-bucket-list:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list .consul-exposed-path-list>ul>li>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-exposed-path-list>ul>li>.detail dl+dl:not(:first-of-type),.consul-lock-session-list .consul-exposed-path-list>ul>li>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list .consul-instance-checks ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-instance-checks+dl:not(:first-of-type),.consul-lock-session-list .consul-instance-checks:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list dl li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list dl ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list dl+dl:not(:first-of-type),.consul-lock-session-list .consul-upstream-instance-list dl.local-bind-address dl dd+dt+dd,.consul-lock-session-list .consul-upstream-instance-list dl.local-bind-socket-path dl dd+dt+dd,.consul-lock-session-list .consul-upstream-instance-list dl:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list dl:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list li>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list li>.detail dl+dl:not(:first-of-type),.consul-lock-session-list .consul-upstream-instance-list li>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .consul-upstream-instance-list ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),.consul-lock-session-list .consul-upstream-instance-list ul>li:not(:first-child)>.detail dl.local-bind-address dd+dt+dd,.consul-lock-session-list .consul-upstream-instance-list ul>li:not(:first-child)>.detail dl.local-bind-socket-path dd+dt+dd,.consul-lock-session-list .consul-upstream-instance-list ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list .list-collection>ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .list-collection>ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),.consul-lock-session-list .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list .list-collection>ul>li:not(:first-child)>.detail ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .tag-list dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .tag-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list .tag-list+dl:not(:first-of-type),.consul-lock-session-list .tag-list:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list .tag-list:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list dl .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.consul-lock-session-list dl .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.consul-lock-session-list dl .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl .tag-list:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl dd+dt,.consul-lock-session-list dl td.tags:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl+.consul-bucket-list:not(:first-of-type),.consul-lock-session-list dl+.consul-instance-checks:not(:first-of-type),.consul-lock-session-list dl+.tag-list:not(:first-of-type),.consul-lock-session-list dl+dl:not(:first-of-type),.consul-lock-session-list dl+td.tags:not(:first-of-type),.consul-lock-session-list dl:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) .tag-list dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) td.tags dd+dt:not([class])+dd,.consul-lock-session-list dl:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list section[data-route="dc.show.license"] .validity dl ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),.consul-lock-session-list section[data-route="dc.show.license"] .validity dl:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),.consul-lock-session-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list td.tags dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list td.tags ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list td.tags+dl:not(:first-of-type),.consul-lock-session-list td.tags:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list td.tags:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail .consul-bucket-list+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail .consul-instance-checks+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail .consul-upstream-instance-list dl+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail .tag-list+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail dl .consul-bucket-list:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl .consul-instance-checks:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl .consul-upstream-instance-list dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl .tag-list:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt,.consul-lock-session-list ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl td.tags:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl+.consul-bucket-list:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail dl+.consul-instance-checks:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail dl+.tag-list:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail dl+td.tags:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) .consul-bucket-list dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) .consul-instance-checks dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) .consul-upstream-instance-list dl dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) .tag-list dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) section[data-route="dc.show.license"] .validity dl dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) td.tags dd+dt:not([class])+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),.consul-lock-session-list ul>li:not(:first-child)>.detail td.tags+dl:not(:first-of-type),.consul-upstream-instance-list .consul-bucket-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-bucket-list+dl:not(:first-of-type),.consul-upstream-instance-list .consul-bucket-list:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-exposed-path-list>ul>li>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-exposed-path-list>ul>li>.detail dl+dl:not(:first-of-type),.consul-upstream-instance-list .consul-exposed-path-list>ul>li>.detail dl.local-bind-address dd+dt+dd,.consul-upstream-instance-list .consul-exposed-path-list>ul>li>.detail dl.local-bind-socket-path dd+dt+dd,.consul-upstream-instance-list .consul-exposed-path-list>ul>li>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-instance-checks li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-instance-checks+dl:not(:first-of-type),.consul-upstream-instance-list .consul-instance-checks:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-lock-session-list dl li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-lock-session-list dl+dl:not(:first-of-type),.consul-upstream-instance-list .consul-lock-session-list dl:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),.consul-upstream-instance-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl.local-bind-address dd+dt+dd,.consul-upstream-instance-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl.local-bind-socket-path dd+dt+dd,.consul-upstream-instance-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-upstream-instance-list .list-collection>ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .list-collection>ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),.consul-upstream-instance-list .list-collection>ul>li:not(:first-child)>.detail dl.local-bind-address dd+dt+dd,.consul-upstream-instance-list .list-collection>ul>li:not(:first-child)>.detail dl.local-bind-socket-path dd+dt+dd,.consul-upstream-instance-list .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-upstream-instance-list .list-collection>ul>li:not(:first-child)>.detail li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .tag-list dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .tag-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list .tag-list+dl:not(:first-of-type),.consul-upstream-instance-list .tag-list:not([class]) dl dd+dt:not([class])+dd,.consul-upstream-instance-list .tag-list:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list dl .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl .tag-list:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl dd+dt,.consul-upstream-instance-list dl li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl td.tags:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl+.consul-bucket-list:not(:first-of-type),.consul-upstream-instance-list dl+.consul-instance-checks:not(:first-of-type),.consul-upstream-instance-list dl+.tag-list:not(:first-of-type),.consul-upstream-instance-list dl+dl:not(:first-of-type),.consul-upstream-instance-list dl+td.tags:not(:first-of-type),.consul-upstream-instance-list dl.local-bind-address .consul-bucket-list dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address .consul-instance-checks dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address .consul-lock-session-list dl dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address .tag-list dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address section[data-route="dc.show.license"] .validity dl dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt+dd,.consul-upstream-instance-list dl.local-bind-address td.tags dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path .consul-bucket-list dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path .consul-instance-checks dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path .consul-lock-session-list dl dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path .tag-list dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path section[data-route="dc.show.license"] .validity dl dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path td.tags dd+dt+dd,.consul-upstream-instance-list dl:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) .tag-list dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list dl:not([class]) td.tags dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail .consul-bucket-list+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail .consul-instance-checks+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail .consul-lock-session-list dl+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail .tag-list+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail dl .consul-bucket-list:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl .consul-instance-checks:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl .consul-lock-session-list dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl .tag-list:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl dd+dt,.consul-upstream-instance-list li>.detail dl dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl td.tags:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl+.consul-bucket-list:not(:first-of-type),.consul-upstream-instance-list li>.detail dl+.consul-instance-checks:not(:first-of-type),.consul-upstream-instance-list li>.detail dl+.tag-list:not(:first-of-type),.consul-upstream-instance-list li>.detail dl+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail dl+td.tags:not(:first-of-type),.consul-upstream-instance-list li>.detail dl.local-bind-address dd+dt+dd,.consul-upstream-instance-list li>.detail dl.local-bind-socket-path dd+dt+dd,.consul-upstream-instance-list li>.detail dl:not([class]) .consul-bucket-list dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) .consul-instance-checks dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) .consul-lock-session-list dl dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) .tag-list dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) dl dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) section[data-route="dc.show.license"] .validity dl dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail dl:not([class]) td.tags dd+dt:not([class])+dd,.consul-upstream-instance-list li>.detail section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),.consul-upstream-instance-list li>.detail td.tags+dl:not(:first-of-type),.consul-upstream-instance-list section[data-route="dc.show.license"] .validity dl li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),.consul-upstream-instance-list section[data-route="dc.show.license"] .validity dl:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),.consul-upstream-instance-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) li>.detail dl dd+dt:not([class])+dd,.consul-upstream-instance-list td.tags dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list td.tags li>.detail dl:not([class]) dd+dt:not([class])+dd,.consul-upstream-instance-list td.tags+dl:not(:first-of-type),.consul-upstream-instance-list td.tags:not([class]) dl dd+dt:not([class])+dd,.consul-upstream-instance-list td.tags:not([class]) li>.detail dl dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail .consul-bucket-list+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail .consul-instance-checks+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail .consul-lock-session-list dl+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail .consul-upstream-instance-list dl+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.list-collection>ul>li:not(:first-child)>.detail .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.list-collection>ul>li:not(:first-child)>.detail .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail .tag-list+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail dl .consul-bucket-list:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl .consul-instance-checks:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl .consul-lock-session-list dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl .consul-upstream-instance-list dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl .tag-list:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl dd+dt,.list-collection>ul>li:not(:first-child)>.detail dl section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl td.tags:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl+.consul-bucket-list:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail dl+.consul-instance-checks:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail dl+.tag-list:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail dl+td.tags:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) .consul-bucket-list dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) .consul-instance-checks dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) .consul-lock-session-list dl dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) .consul-upstream-instance-list dl dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) .tag-list dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) section[data-route="dc.show.license"] .validity dl dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) td.tags dd+dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),.list-collection>ul>li:not(:first-child)>.detail td.tags+dl:not(:first-of-type),.tag-list .consul-bucket-list:not([class]) dd+dt:not([class])+dd,.tag-list .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,.tag-list .consul-instance-checks:not([class]) dd+dt:not([class])+dd,.tag-list .consul-lock-session-list dl:not([class]) dd+dt:not([class])+dd,.tag-list .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.tag-list .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,.tag-list .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,.tag-list .consul-upstream-instance-list dl:not([class]) dd+dt:not([class])+dd,.tag-list .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,.tag-list .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,.tag-list dd+dt,.tag-list section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,.tag-list section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,.tag-list td.tags:not([class]) dd+dt:not([class])+dd,.tag-list+.consul-bucket-list:not(:first-of-type),.tag-list+.consul-instance-checks:not(:first-of-type),.tag-list+.tag-list:not(:first-of-type),.tag-list+td.tags:not(:first-of-type),.tag-list:not([class]) .consul-bucket-list dd+dt:not([class])+dd,.tag-list:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,.tag-list:not([class]) .consul-instance-checks dd+dt:not([class])+dd,.tag-list:not([class]) .consul-lock-session-list dl dd+dt:not([class])+dd,.tag-list:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.tag-list:not([class]) .consul-upstream-instance-list dl dd+dt:not([class])+dd,.tag-list:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,.tag-list:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,.tag-list:not([class]) dd+dt:not([class])+dd,.tag-list:not([class]) section[data-route="dc.show.license"] .validity dl dd+dt:not([class])+dd,.tag-list:not([class]) section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt:not([class])+dd,.tag-list:not([class]) td.tags dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-bucket-list+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-exposed-path-list>ul>li>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-exposed-path-list>ul>li>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-exposed-path-list>ul>li>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-instance-checks+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-lock-session-list dl ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-lock-session-list dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-lock-session-list dl:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-lock-session-list ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-lock-session-list ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-upstream-instance-list dl li>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-upstream-instance-list dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-upstream-instance-list dl.local-bind-address dl dd+dt+dd,section[data-route="dc.show.license"] .validity .consul-upstream-instance-list dl.local-bind-socket-path dl dd+dt+dd,section[data-route="dc.show.license"] .validity .consul-upstream-instance-list dl:not([class]) li>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-upstream-instance-list li>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .consul-upstream-instance-list li>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .consul-upstream-instance-list li>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .list-collection>ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .list-collection>ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .tag-list dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity .tag-list+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity .tag-list:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,section[data-route="dc.show.license"] .validity dl .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,section[data-route="dc.show.license"] .validity dl .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl .tag-list:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl dd+dt,section[data-route="dc.show.license"] .validity dl td.tags:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl+.consul-bucket-list:not(:first-of-type),section[data-route="dc.show.license"] .validity dl+.consul-instance-checks:not(:first-of-type),section[data-route="dc.show.license"] .validity dl+.tag-list:not(:first-of-type),section[data-route="dc.show.license"] .validity dl+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity dl+td.tags:not(:first-of-type),section[data-route="dc.show.license"] .validity dl:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) .tag-list dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) td.tags dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity td.tags dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.license"] .validity td.tags+dl:not(:first-of-type),section[data-route="dc.show.license"] .validity td.tags:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-bucket-list+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-exposed-path-list>ul>li>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-exposed-path-list>ul>li>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-exposed-path-list>ul>li>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-instance-checks+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-lock-session-list dl ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-lock-session-list dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-lock-session-list dl:not([class]) ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-lock-session-list ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-lock-session-list ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list dl li>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list dl.local-bind-address dl dd+dt+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list dl.local-bind-socket-path dl dd+dt+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list dl:not([class]) li>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list li>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list li>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .consul-upstream-instance-list li>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .list-collection>ul>li:not(:first-child)>.detail dl dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .list-collection>ul>li:not(:first-child)>.detail dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .tag-list dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header .tag-list+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header .tag-list:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl .tag-list:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl td.tags:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+.consul-bucket-list:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+.consul-instance-checks:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+.tag-list:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl+td.tags:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) .tag-list dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) td.tags dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header td.tags dl:not([class]) dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header td.tags+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section header td.tags:not([class]) dl dd+dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section[data-route="dc.show.license"] .validity header dl+dl:not(:first-of-type),section[data-route="dc.show.serverstatus"] .redundancy-zones section[data-route="dc.show.license"] header .validity dl+dl:not(:first-of-type),td.tags .consul-bucket-list:not([class]) dd+dt:not([class])+dd,td.tags .consul-exposed-path-list>ul>li>.detail dl:not([class]) dd+dt:not([class])+dd,td.tags .consul-instance-checks:not([class]) dd+dt:not([class])+dd,td.tags .consul-lock-session-list dl:not([class]) dd+dt:not([class])+dd,td.tags .consul-lock-session-list ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,td.tags .consul-upstream-instance-list dl.local-bind-address dd+dt+dd,td.tags .consul-upstream-instance-list dl.local-bind-socket-path dd+dt+dd,td.tags .consul-upstream-instance-list dl:not([class]) dd+dt:not([class])+dd,td.tags .consul-upstream-instance-list li>.detail dl:not([class]) dd+dt:not([class])+dd,td.tags .list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dd+dt:not([class])+dd,td.tags .tag-list:not([class]) dd+dt:not([class])+dd,td.tags dd+dt,td.tags section[data-route="dc.show.license"] .validity dl:not([class]) dd+dt:not([class])+dd,td.tags section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dd+dt:not([class])+dd,td.tags+.consul-bucket-list:not(:first-of-type),td.tags+.consul-instance-checks:not(:first-of-type),td.tags+.tag-list:not(:first-of-type),td.tags+td.tags:not(:first-of-type),td.tags:not([class]) .consul-bucket-list dd+dt:not([class])+dd,td.tags:not([class]) .consul-exposed-path-list>ul>li>.detail dl dd+dt:not([class])+dd,td.tags:not([class]) .consul-instance-checks dd+dt:not([class])+dd,td.tags:not([class]) .consul-lock-session-list dl dd+dt:not([class])+dd,td.tags:not([class]) .consul-lock-session-list ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,td.tags:not([class]) .consul-upstream-instance-list dl dd+dt:not([class])+dd,td.tags:not([class]) .consul-upstream-instance-list li>.detail dl dd+dt:not([class])+dd,td.tags:not([class]) .list-collection>ul>li:not(:first-child)>.detail dl dd+dt:not([class])+dd,td.tags:not([class]) .tag-list dd+dt:not([class])+dd,td.tags:not([class]) dd+dt:not([class])+dd,td.tags:not([class]) section[data-route="dc.show.license"] .validity dl dd+dt:not([class])+dd,td.tags:not([class]) section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dd+dt:not([class])+dd{margin-left:var(--horizontal-kv-list-separator-width)}.consul-bucket-list dt+dd,.consul-exposed-path-list>ul>li>.detail dl dt+dd,.consul-instance-checks dt+dd,.consul-lock-session-list dl dt+dd,.consul-lock-session-list ul>li:not(:first-child)>.detail dl dt+dd,.consul-upstream-instance-list dl dt+dd,.consul-upstream-instance-list li>.detail dl dt+dd,.list-collection>ul>li:not(:first-child)>.detail dl dt+dd,.tag-list dt+dd,section[data-route="dc.show.license"] .validity dl dt+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl dt+dd,td.tags dt+dd{margin-left:4px}.consul-bucket-list:not([class]) dt:not([class])+dd,.consul-exposed-path-list>ul>li>.detail dl:not([class]) dt:not([class])+dd,.consul-instance-checks:not([class]) dt:not([class])+dd,.consul-lock-session-list dl:not([class]) dt:not([class])+dd,.consul-upstream-instance-list dl.local-bind-address dt+dd,.consul-upstream-instance-list dl.local-bind-socket-path dt+dd,.consul-upstream-instance-list dl:not([class]) dt:not([class])+dd,.list-collection>ul>li:not(:first-child)>.detail dl:not([class]) dt:not([class])+dd,.tag-list:not([class]) dt:not([class])+dd,section[data-route="dc.show.license"] .validity dl:not([class]) dt:not([class])+dd,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not([class]) dt:not([class])+dd,td.tags:not([class]) dt:not([class])+dd{margin-left:0!important}.consul-lock-session-list .checks dd>:not(:last-child)::after,.discovery-chain .resolver-card ol>:not(:last-child)::after,.tag-list dd>:not(:last-child)::after,td.tags dd>:not(:last-child)::after{display:inline;content:var(--csv-list-separator);vertical-align:initial;margin-right:.3em}.tag-list dt::before,td.tags dt::before{color:inherit;color:var(--token-color-foreground-faint)}.consul-exposed-path-list>ul>li>.detail dl>dt>*,.consul-lock-session-list ul>li:not(:first-child)>.detail dl>dt>*,.consul-upstream-instance-list li>.detail dl>dt>*,.list-collection>ul>li:not(:first-child)>.detail dl>dt>*{display:none}.consul-exposed-path-list>ul>li>.detail dl.passing dt::before,.consul-exposed-path-list>ul>li>.header .passing dd::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.passing dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .passing dd::before,.consul-upstream-instance-list li>.detail dl.passing dt::before,.consul-upstream-instance-list li>.header .passing dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.passing dt::before,.list-collection>ul>li:not(:first-child)>.header .passing dd::before{color:var(--token-color-foreground-success)}.consul-exposed-path-list>ul>li>.detail dl.warning dt::before,.consul-exposed-path-list>ul>li>.header .warning dd::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.warning dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .warning dd::before,.consul-upstream-instance-list li>.detail dl.warning dt::before,.consul-upstream-instance-list li>.header .warning dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.warning dt::before,.list-collection>ul>li:not(:first-child)>.header .warning dd::before{color:var(--token-color-foreground-warning)}.consul-exposed-path-list>ul>li>.detail dl.critical dt::before,.consul-exposed-path-list>ul>li>.header .critical dd::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.critical dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .critical dd::before,.consul-upstream-instance-list li>.detail dl.critical dt::before,.consul-upstream-instance-list li>.header .critical dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.critical dt::before,.list-collection>ul>li:not(:first-child)>.header .critical dd::before{color:var(--token-color-foreground-critical)}.consul-exposed-path-list>ul>li>.detail dl.empty dt::before,.consul-exposed-path-list>ul>li>.detail dl.unknown dt::before,.consul-exposed-path-list>ul>li>.header .empty dd::before,.consul-exposed-path-list>ul>li>.header .unknown dd::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.empty dt::before,.consul-lock-session-list ul>li:not(:first-child)>.detail dl.unknown dt::before,.consul-lock-session-list ul>li:not(:first-child)>.header .empty dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header .unknown dd::before,.consul-upstream-instance-list li>.detail dl.empty dt::before,.consul-upstream-instance-list li>.detail dl.unknown dt::before,.consul-upstream-instance-list li>.header .empty dd::before,.consul-upstream-instance-list li>.header .unknown dd::before,.list-collection>ul>li:not(:first-child)>.detail dl.empty dt::before,.list-collection>ul>li:not(:first-child)>.detail dl.unknown dt::before,.list-collection>ul>li:not(:first-child)>.header .empty dd::before,.list-collection>ul>li:not(:first-child)>.header .unknown dd::before{color:var(--token-color-foreground-faint)}.consul-exposed-path-list>ul>li>.header [rel=me] dd::before,.consul-lock-session-list ul>li:not(:first-child)>.header [rel=me] dd::before,.consul-upstream-instance-list li>.header [rel=me] dd::before,.list-collection>ul>li:not(:first-child)>.header [rel=me] dd::before{color:var(--token-color-foreground-action)}.app-view>div form:not(.filter-bar) [role=radiogroup] label>em>code,.modal-dialog [role=document] .type-password>em>code,.modal-dialog [role=document] .type-select>em>code,.modal-dialog [role=document] .type-text>em>code,.modal-dialog [role=document] [role=radiogroup] label>em>code,.modal-dialog [role=document] form button+em>code,.modal-dialog [role=document] p code,.oidc-select label>em>code,.type-toggle>em>code,main .type-password>em>code,main .type-select>em>code,main .type-text>em>code,main form button+em>code,main p code{border:1px solid;color:var(--token-color-consul-brand);background-color:var(--token-color-surface-strong);border-color:var(--token-color-surface-interactive-active);display:inline-block;padding:0 4px}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{outline:0;transition-property:transform,visibility,opacity;background-color:var(--token-color-surface-primary);border-radius:var(--decor-radius-100)}[data-animation=fade][data-state=hidden].tippy-box{opacity:0}[data-inertia][data-state=visible].tippy-box{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-box .tippy-arrow{--size:5px}.tippy-box .tippy-arrow::before{content:"";position:absolute}[data-placement^=top].tippy-box>.tippy-arrow{bottom:0}[data-placement^=top].tippy-box>.tippy-arrow::before{left:0;bottom:calc(0px - var(--size));transform-origin:center top}[data-placement^=bottom].tippy-box>.tippy-arrow{top:0}[data-placement^=bottom].tippy-box>.tippy-arrow::before{left:0;top:calc(0px - var(--size));transform-origin:center bottom}[data-placement^=left].tippy-box>.tippy-arrow{right:0}[data-placement^=left].tippy-box>.tippy-arrow::before{right:calc(0px - var(--size));transform-origin:center left}[data-placement^=right].tippy-box>.tippy-arrow{left:0}[data-placement^=right].tippy-box>.tippy-arrow::before{left:calc(0px - var(--size));transform-origin:center right}[data-theme~=square-tail] .tippy-arrow{--size:18px;left:calc(0px - var(--size)/ 2)!important}[data-theme~=square-tail] .tippy-arrow::before{background-color:var(--token-color-surface-primary);width:calc(1px + var(--size));height:calc(1px + var(--size));border:var(--decor-border-100);border-color:var(--token-color-palette-neutral-300)}[data-theme~=square-tail] .tippy-arrow::after{position:absolute;left:1px}[data-theme~=square-tail][data-placement^=top]{bottom:-10px}[data-theme~=square-tail][data-placement^=top] .informed-action{border-bottom-left-radius:0!important}[data-theme~=square-tail][data-placement^=top] .tippy-arrow::before{border-bottom-left-radius:var(--decor-radius-200);border-bottom-right-radius:var(--decor-radius-200);border-top:0!important}[data-theme~=square-tail][data-placement^=top] .tippy-arrow::after{bottom:calc(0px - var(--size))}[data-theme~=square-tail][data-placement^=bottom]{top:-10px}[data-theme~=square-tail][data-placement^=bottom] .informed-action{border-top-left-radius:0!important}[data-theme~=square-tail][data-placement^=bottom] .tippy-arrow::before{border-top-left-radius:var(--decor-radius-200);border-top-right-radius:var(--decor-radius-200);border-bottom:0!important}[data-theme~=square-tail][data-placement^=bottom] .tippy-arrow::after{top:calc(0px - var(--size))}.tippy-box[data-theme~=tooltip] .tippy-content{padding:12px;max-width:224px;position:relative;z-index:1}.tippy-box[data-theme~=tooltip]{background-color:var(--token-color-foreground-faint);color:var(--token-color-surface-primary)}.tippy-box[data-theme~=tooltip] .tippy-arrow{--size:5px;color:var(--token-color-foreground-faint);width:calc(var(--size) * 2);height:calc(var(--size) * 2)}.tippy-box[data-theme~=tooltip] .tippy-arrow::before{border-color:transparent;border-style:solid}.tippy-box[data-theme~=tooltip][data-placement^=top]>.tippy-arrow::before{border-width:var(--size) var(--size) 0;border-top-color:initial}.tippy-box[data-theme~=tooltip][data-placement^=bottom]>.tippy-arrow::before{border-width:0 var(--size) var(--size);border-bottom-color:initial}.tippy-box[data-theme~=tooltip][data-placement^=left]>.tippy-arrow::before{border-width:var(--size) 0 var(--size) var(--size);border-left-color:initial}.tippy-box[data-theme~=tooltip][data-placement^=right]>.tippy-arrow::before{border-width:var(--size) var(--size) var(--size) 0;border-right-color:initial}.warning.modal-dialog header{background-color:var(--token-color-vault-gradient-faint-start);border-color:var(--token-color-vault-brand);color:var(--token-color-vault-foreground)}.warning.modal-dialog header>:not(label){font-size:var(--typo-size-500);font-weight:var(--typo-weight-semibold)}.warning.modal-dialog header::before{color:var(--token-color-vault-brand);float:left;margin-top:2px;margin-right:3px}.modal-dialog>div:first-child{background-color:var(--token-color-surface-interactive);opacity:.9}.modal-dialog [role=document]>footer,.modal-dialog [role=document]>header,.modal-dialog-body{border-color:var(--token-color-palette-neutral-300)}.modal-dialog-body{border-style:solid;border-left-width:1px;border-right-width:1px}.modal-layer{height:0}.modal-dialog [role=document] table{height:150px!important}.modal-dialog [role=document] tbody{max-height:100px}.modal-dialog table{min-height:149px}.modal-dialog,.modal-dialog>div:first-child{position:fixed;top:0;right:0;bottom:0;left:0}.modal-dialog{z-index:500;align-items:center;justify-content:center;height:100%}[aria-hidden=true].modal-dialog{display:none}.modal-dialog [role=document]{box-shadow:var(--token-elevation-overlay-box-shadow);background-color:var(--token-color-surface-primary);margin:auto;z-index:2;max-width:855px;position:relative}.modal-dialog [role=document]>*{padding-left:15px;padding-right:15px}.modal-dialog [role=document]>div{overflow-y:auto;max-height:80vh;padding:20px 23px}.modal-dialog [role=document]>footer,.modal-dialog [role=document]>header{border-width:1px;padding-top:12px;padding-bottom:10px}.modal-dialog [role=document]>header{position:relative}.modal-dialog [role=document]>header button{float:right;margin-top:-3px}.list-collection>ul{border-top:1px solid;border-color:var(--token-color-surface-interactive-active)}.list-collection>button{cursor:pointer;background-color:var(--token-color-surface-strong);color:var(--token-color-foreground-action);width:100%;padding:15px}.list-collection-scroll-virtual,.list-collection>ul>li{position:relative}.list-collection-scroll-virtual{height:500px}.filter-bar{background-color:var(--token-color-foreground-high-contrast);border-bottom:var(--decor-border-100);border-color:var(--token-color-surface-interactive-active);padding:4px 8px}.filter-bar .filters .popover-menu>[type=checkbox]:checked+label button,.filter-bar .sort .popover-menu>[type=checkbox]:checked+label button{color:var(--token-color-foreground-action);background-color:var(--token-color-foreground-high-contrast)}.filter-bar .sort{margin-left:auto}.filter-bar .popover-select{position:relative;z-index:3}.filter-bar .popover-menu>[type=checkbox]+label button{padding-left:1.5rem!important;padding-right:1.5rem!important}.filter-bar .popover-menu [role=menuitem]{justify-content:normal!important}@media (max-width:1379px){.filter-bar,.filter-bar>div{flex-wrap:wrap}.filter-bar .search{position:relative;z-index:4;width:100%;margin-bottom:.3rem}}@media (max-width:995px){.filter-bar .filters,.filter-bar .sort{display:none}}html[data-route^="dc.acls.index"] .filter-bar{color:inherit}.freetext-filter{border:var(--decor-border-100);border-radius:var(--decor-radius-100);background-color:var(--token-color-surface-primary);border-color:var(--token-color-surface-interactive-active);color:var(--token-color-foreground-disabled)}.freetext-filter:hover,.freetext-filter:hover *{border-color:var(--token-color-foreground-disabled)}.freetext-filter_input::-moz-placeholder{cursor:inherit;color:inherit;border-color:inherit}.freetext-filter *,.freetext-filter_input::placeholder{cursor:inherit;color:inherit;border-color:inherit}.freetext-filter_input{-webkit-appearance:none;border:none}.freetext-filter_label::after{visibility:visible;--icon-name:icon-search;content:"";position:absolute;top:50%;left:50%;width:16px;height:16px;margin-left:-8px;margin-top:-8px}.freetext-filter .popover-menu{background-color:var(--token-color-surface-strong);color:var(--token-color-foreground-primary);border-left:1px solid;border-color:inherit}.freetext-filter .popover-menu>[type=checkbox]:checked+label button{background-color:var(--token-color-surface-interactive-active)}.freetext-filter{--height:2.2rem;display:flex;position:relative;height:var(--height);width:100%}.freetext-filter_input,.freetext-filter_label{height:100%}.freetext-filter_input{padding:8px 10px;padding-left:var(--height);min-width:12.7rem;width:100%}.freetext-filter_label{visibility:hidden;position:absolute;z-index:1;width:var(--height)}.informed-action{border-radius:var(--decor-radius-200);border:var(--decor-border-100);border-color:var(--token-color-palette-neutral-300);background-color:var(--token-color-surface-primary);min-width:190px}.informed-action>div{border-top-left-radius:var(--decor-radius-200);border-top-right-radius:var(--decor-radius-200);cursor:default;padding:1rem}.informed-action p{color:var(--token-color-hashicorp-brand)}.informed-action>ul>li>:focus,.informed-action>ul>li>:hover{background-color:var(--token-color-surface-strong)}.info.informed-action header{color:var(--token-color-foreground-action-active)}.info.informed-action header::before{background-color:var(--token-color-foreground-action);margin-right:5px}.info.informed-action>div{background-color:var(--token-color-surface-action)}.dangerous.informed-action header{color:var(--token-color-palette-red-400)}.dangerous.informed-action header::before{background-color:var(--token-color-foreground-critical)}.dangerous.informed-action>div{background-color:var(--token-color-surface-critical)}.warning.informed-action header{color:var(--token-color-foreground-warning-on-surface)}.warning.informed-action header::before{background-color:var(--token-color-vault-brand);margin-right:5px}.warning.informed-action>div{background-color:var(--token-color-vault-gradient-faint-start)}.copyable-code::after,.tab-nav li:not(.selected)>:active,.tab-nav li:not(.selected)>:focus,.tab-nav li:not(.selected)>:hover{background-color:var(--token-color-surface-strong)}.informed-action>ul>.action>*{color:var(--token-color-foreground-action)}.documentation.informed-action{min-width:270px}.informed-action header::before{float:left;margin-right:5px}.informed-action>ul{list-style:none;display:flex;margin:0;padding:4px}.informed-action>ul>li{width:50%}.informed-action>ul>li>*{width:100%}.tab-nav ul{list-style-type:none;display:inline-flex;align-items:center;position:relative;padding:0;margin:0}.tab-nav li>:not(:disabled){cursor:pointer}.tab-nav{border-bottom:var(--decor-border-100)}.animatable.tab-nav ul::after,.tab-nav li>*{border-bottom:var(--decor-border-300)}.tab-nav{border-color:var(--token-color-surface-interactive-active);clear:both;overflow:auto;letter-spacing:.03em}.tab-nav li>*{white-space:nowrap;transition-property:background-color,border-color;border-color:transparent;color:var(--token-color-foreground-faint);display:inline-block;padding:16px 13px}.tab-nav li:not(.selected)>:focus,.tab-nav li:not(.selected)>:hover{border-color:var(--token-color-palette-neutral-300)}.animatable.tab-nav .selected a{border-color:transparent!important}.animatable.tab-nav ul::after{position:absolute;bottom:0;height:0;border-top:0;width:calc(var(--selected-width,0) * 1px);transform:translate(calc(var(--selected-left,0) * 1px),0);transition-property:transform,width}.search-bar-status{border-bottom:var(--decor-border-100);border-bottom-color:var(--token-color-surface-interactive-active);padding:.5rem 0 .5rem .5rem}.search-bar-status li:not(.remove-all) button::before{color:var(--token-color-foreground-faint);margin-top:1px;margin-right:.2rem}.search-bar-status dt::after{content:":";padding-right:.3rem}.search-bar-status>dl>dt{float:left}.search-bar-status dt{white-space:nowrap}.search-bar-status li{display:inline-flex}.search-bar-status li:not(:last-child){margin-right:.3rem;margin-bottom:.3rem}.search-bar-status li:not(.remove-all){border:var(--decor-border-100);border-color:var(--token-color-surface-interactive-active);color:var(--token-color-foreground-faint);padding:0 .2rem}.search-bar-status li:not(.remove-all) dl{display:flex}.search-bar-status li:not(.remove-all) button{cursor:pointer;padding:0}.copyable-code{display:flex;align-items:flex-start;position:relative;width:100%;padding:8px 14px 3px;border:var(--decor-border-100);border-color:var(--token-color-surface-interactive-active);border-radius:var(--decor-radius-200)}.copyable-code.obfuscated{padding-left:4px}.copyable-code::after{position:absolute;top:0;right:0;width:40px;height:100%;display:block;content:""}.copyable-code .copy-button{position:absolute;top:0;right:0;z-index:1}.copyable-code .copy-button button{width:40px;height:40px}.copyable-code .copy-button button:empty::after{display:none}.copyable-code button[aria-expanded]{margin-top:1px;margin-right:4px;cursor:pointer}.copyable-code button[aria-expanded]::before{content:"";--icon-size:icon-000;--icon-color:var(--token-color-foreground-faint)}.copyable-code button[aria-expanded=true]::before{--icon-name:icon-eye-off}.copyable-code button[aria-expanded=false]::before{--icon-name:icon-eye}.copyable-code pre{padding-right:30px}.copyable-code code{display:inline-block;overflow:hidden;text-overflow:ellipsis;width:100%}.copyable-code hr{width:calc(100% - 80px);margin:8px 0 13px;border:3px dashed var(--token-color-palette-neutral-300);background-color:var(--token-color-surface-primary)}.consul-loader circle{fill:var(--token-color-consul-gradient-faint-stop);-webkit-animation:loader-animation 1.5s infinite ease-in-out;animation:loader-animation 1.5s infinite ease-in-out;transform-origin:50% 50%}.consul-loader g:nth-last-child(2) circle{-webkit-animation-delay:.2s;animation-delay:.2s}.consul-loader g:nth-last-child(3) circle{-webkit-animation-delay:.3s;animation-delay:.3s}.consul-loader g:nth-last-child(4) circle{-webkit-animation-delay:.4s;animation-delay:.4s}.consul-loader g:nth-last-child(5) circle{-webkit-animation-delay:.5s;animation-delay:.5s}@-webkit-keyframes loader-animation{0%,100%{transform:scale3D(1,1,1)}33%{transform:scale3D(0,0,1)}}@keyframes loader-animation{0%,100%{transform:scale3D(1,1,1)}33%{transform:scale3D(0,0,1)}}.consul-loader{display:flex;align-items:center;justify-content:center;height:100%;position:absolute;width:100%;top:0;margin-top:0!important}.tomography-graph .background{fill:var(--token-color-surface-strong)}.tomography-graph .axis{fill:none;stroke:var(--token-color-palette-neutral-300);stroke-dasharray:4 4}.tomography-graph .border{fill:none;stroke:var(--token-color-palette-neutral-300)}.tomography-graph .point{stroke:var(--token-color-foreground-disabled);fill:var(--token-color-consul-foreground)}.tomography-graph .lines rect{fill:var(--token-color-consul-foreground);stroke:transparent;stroke-width:5px}.tomography-graph .lines rect:hover{fill:var(--token-color-palette-neutral-300);height:3px;y:-1px}.tomography-graph .tick line{stroke:var(--token-color-palette-neutral-300)}.tomography-graph .tick text{font-size:var(--typo-size-600);text-anchor:start}.discovery-chain .resolver-card,.discovery-chain .route-card,.discovery-chain .splitter-card,.discovery-chain path{transition-duration:.1s;transition-timing-function:linear;cursor:pointer}.discovery-chain path{transition-property:stroke;fill:none;stroke:var(--token-color-foreground-disabled);stroke-width:2;vector-effect:non-scaling-stroke}#downstream-lines svg circle,#upstream-lines svg circle,.discovery-chain circle{fill:var(--token-color-surface-primary)}.discovery-chain .resolver-card,.discovery-chain .resolver-card a,.discovery-chain .route-card,.discovery-chain .route-card a,.discovery-chain .splitter-card,.discovery-chain .splitter-card a{color:var(--token-color-foreground-strong)!important}.discovery-chain path:focus,.discovery-chain path:hover{stroke:var(--token-color-foreground-strong)}.discovery-chain .resolvers,.discovery-chain .routes,.discovery-chain .splitters{border-radius:var(--decor-radius-100);border:1px solid;border-color:var(--token-color-surface-interactive-active);background-color:var(--token-color-surface-strong);pointer-events:none}.discovery-chain .resolver-card,.discovery-chain .resolvers>header span,.discovery-chain .route-card,.discovery-chain .routes>header span,.discovery-chain .splitter-card,.discovery-chain .splitters>header span{pointer-events:all}.discovery-chain .resolvers>header>*,.discovery-chain .routes>header>*,.discovery-chain .splitters>header>*{text-transform:uppercase}.discovery-chain .resolvers>header span::after,.discovery-chain .routes>header span::after,.discovery-chain .splitters>header span::after{width:1.2em;height:1.2em;opacity:.6}.discovery-chain .resolver-card,.discovery-chain .route-card,.discovery-chain .splitter-card{transition-property:opacity background-color border-color;margin-top:0!important}.discovery-chain [id*=":"]:not(path):hover{opacity:1;background-color:var(--token-color-surface-primary);border-color:var(--token-color-foreground-faint)}.discovery-chain .route-card header:not(.short) dd{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.discovery-chain .route-card section header>*{visibility:hidden}.discovery-chain .route-card .match-headers header ::before{content:"H"}.discovery-chain .route-card .match-queryparams header>::before{content:"Q"}.discovery-chain .resolver-card dt::before{content:"";--icon-size:icon-999}.discovery-chain .resolver-card dl.failover dt::before{--icon-name:icon-cloud-cross}.discovery-chain .resolver-card dl.redirect dt::before{--icon-name:icon-redirect}.discovery-chain circle{stroke-width:2;stroke:var(--token-color-foreground-disabled)}.discovery-chain{position:relative;display:flex;justify-content:space-between}.discovery-chain svg{position:absolute}.discovery-chain .resolvers,.discovery-chain .routes,.discovery-chain .splitters{padding:10px 1%;width:32%}.discovery-chain .resolvers>header,.discovery-chain .routes>header,.discovery-chain .splitters>header{height:18px}.discovery-chain .resolvers>header span,.discovery-chain .routes>header span,.discovery-chain .splitters>header span{position:relative;z-index:1;margin-left:2px}.discovery-chain .resolvers [role=group],.discovery-chain .routes [role=group],.discovery-chain .splitters [role=group]{position:relative;z-index:1;display:flex;flex-direction:column;justify-content:space-around;height:100%}.discovery-chain .resolver-card dl,.discovery-chain .route-card dl,.discovery-chain .splitter-card dl{margin:0;float:none}.discovery-chain .resolver-card,.discovery-chain .route-card,.discovery-chain .splitter-card{margin-bottom:20px}.discovery-chain .route-card header.short dl{display:flex}.discovery-chain .route-card header.short dt::after{content:" ";display:inline-block}.discovery-chain .route-card>header ul{float:right;margin-top:-2px}.discovery-chain .route-card>header ul li{margin-left:5px}.discovery-chain .route-card section{display:flex}.discovery-chain .route-card section header{display:block;width:19px;margin-right:14px}.discovery-chain .resolver-card a{display:block}.discovery-chain .resolver-card dl{display:flex;flex-wrap:wrap;margin-top:5px}.discovery-chain .resolver-card dt{font-size:0;margin-right:6px;margin-top:1px;width:23px;height:20px}.discovery-chain .resolver-card ol{display:flex;flex-wrap:wrap;list-style-type:none}.discovery-chain .route-card,.discovery-chain .splitter-card{position:relative}.discovery-chain .route-card::before,.discovery-chain .splitter-card::before{background-color:var(--token-color-surface-primary);border-radius:var(--decor-radius-full);border:2px solid;border-color:var(--token-color-foreground-disabled);position:absolute;z-index:1;right:-5px;top:50%;margin-top:-5px;width:10px;height:10px}.discovery-chain .resolver-inlets,.discovery-chain .splitter-inlets{width:10px;height:100%;z-index:1}.discovery-chain .splitter-inlets{left:50%;margin-left:calc(-15% - 3px)}.discovery-chain .resolver-inlets{right:calc(31% - 7px)}.consul-bucket-list .service+dd{font-weight:var(--typo-weight-semibold)}.consul-bucket-list dd:not(:last-child)::after{display:inline-block;content:"/";margin:0 6px 0 3px}.consul-bucket-list .service+dd,.consul-bucket-list dd+dt{margin-left:0!important}.consul-upstream-instance-list dl.local-bind-socket-mode dt{text-transform:lowercase;font-weight:var(--typo-weight-semibold)}.consul-health-check-list .health-check-output::before{min-width:20px;min-height:20px;margin-right:15px}@media (max-width:650px){.consul-health-check-list .health-check-output::before{min-width:18px;min-height:18px;margin-right:8px}}.consul-health-check-list .health-check-output dd em{background-color:var(--token-color-surface-strong);cursor:default;font-style:normal;margin-top:-2px;margin-left:.5em}.consul-health-check-list .passing.health-check-output::before{color:var(--token-color-foreground-success)}.consul-health-check-list .warning.health-check-output::before{color:var(--token-color-foreground-warning)}.consul-health-check-list .critical.health-check-output::before{color:var(--token-color-foreground-critical)}.consul-health-check-list .health-check-output,.consul-health-check-list .health-check-output pre{border-radius:var(--decor-radius-100)}.consul-health-check-list .health-check-output dd:first-of-type{color:var(--token-color-foreground-disabled)}.consul-health-check-list .health-check-output pre{background-color:var(--token-color-surface-strong);color:var(--token-color-foreground-faint)}.consul-health-check-list .health-check-output{border-width:1px 1px 1px 4px;color:var(--token-color-foreground-strong);border-color:var(--token-color-surface-interactive-active);border-style:solid;display:flex;padding:20px 24px 20px 16px}.consul-health-check-list .passing.health-check-output{border-left-color:var(--token-color-foreground-success)}.consul-health-check-list .warning.health-check-output{border-left-color:var(--token-color-vault-brand)}.consul-health-check-list .critical.health-check-output{border-left-color:var(--token-color-foreground-critical)}.consul-health-check-list .health-check-output:not(:last-child){margin-bottom:24px}.consul-health-check-list .health-check-output dl:last-of-type,.consul-health-check-list .health-check-output header{width:100%}.consul-health-check-list .health-check-output header{margin-bottom:.9em}.consul-health-check-list .health-check-output>div{flex:1 1 auto;width:calc(100% - 26px);display:flex;flex-wrap:wrap;justify-content:space-between}.consul-health-check-list .health-check-output dl{min-width:110px}.consul-health-check-list .health-check-output dl>*{display:block;width:auto;position:static;padding-left:0}.consul-health-check-list .health-check-output dt{margin-bottom:0}.consul-health-check-list .health-check-output dd{position:relative}.consul-health-check-list .health-check-output dl:nth-last-of-type(2){width:50%}.consul-health-check-list .health-check-output dl:last-of-type{margin-top:1em;margin-bottom:0}.consul-health-check-list .health-check-output dl:last-of-type dt{margin-bottom:.3em}.consul-health-check-list .health-check-output pre{padding:12px 40px 12px 12px;white-space:pre-wrap;position:relative}.consul-health-check-list .health-check-output pre code{word-wrap:break-word}.consul-health-check-list .health-check-output .copy-button{position:absolute;right:.5em;top:.7em}@media (max-width:650px){.consul-health-check-list .health-check-output{padding:15px 19px 15px 14px}.consul-health-check-list .health-check-output::before{margin-right:8px}.consul-health-check-list .health-check-output dl:nth-last-of-type(2){width:100%}.consul-health-check-list .health-check-output dl:not(:last-of-type){margin-right:0}}.consul-instance-checks.passing dt::before{color:var(--token-color-foreground-success)}.consul-instance-checks.warning dt::before{color:var(--token-color-foreground-warning)}.consul-instance-checks.critical dt::before{color:var(--token-color-foreground-critical)}.consul-instance-checks.empty dt::before{color:var(--token-color-foreground-faint)}.consul-exposed-path-list>ul{border-top:1px solid var(--token-color-surface-interactive-active)}.consul-external-source::before,.consul-kind::before{--icon-size:icon-300}.consul-intention-list td.intent- strong::before,.consul-intention-list td.intent-allow strong::before,.consul-intention-list td.intent-deny strong::before,.consul-intention-permission-list .intent-allow::before,.consul-intention-permission-list .intent-deny::before,.consul-intention-search-bar .value- span::before,.consul-intention-search-bar .value-allow span::before,.consul-intention-search-bar .value-deny span::before{margin-right:5px}.consul-intention-list td.intent- strong,.consul-intention-list td.intent-allow strong,.consul-intention-list td.intent-deny strong,.consul-intention-permission-list .intent-allow,.consul-intention-permission-list .intent-deny,.consul-intention-search-bar .value- span,.consul-intention-search-bar .value-allow span,.consul-intention-search-bar .value-deny span{display:inline-block;font-weight:var(--typo-weight-normal);font-size:var(--typo-size-600)}.consul-intention-list td.intent-allow strong,.consul-intention-permission-list .intent-allow,.consul-intention-search-bar .value-allow span{color:var(--token-color-foreground-success-on-surface);background-color:var(--token-color-border-success)}.consul-intention-list td.intent-deny strong,.consul-intention-permission-list .intent-deny,.consul-intention-search-bar .value-deny span{color:var(--token-color-foreground-critical-on-surface);background-color:var(--token-color-border-critical)}.consul-intention-list td.permissions{color:var(--token-color-foreground-action)}.consul-intention-list em{--word-spacing:0.25rem}.consul-intention-list em span::before,.consul-intention-list em span:first-child{margin-right:var(--word-spacing)}.consul-intention-list em span:last-child{margin-left:var(--word-spacing)}.consul-intention-list td{height:59px}.consul-intention-list tr>:nth-child(1){width:calc(30% - 50px)}.consul-intention-list tr>:nth-child(2){width:120px}.consul-intention-list tr>:nth-child(3){width:calc(30% - 50px)}.consul-intention-list tr>:nth-child(4){width:calc(40% - 240px)}.consul-intention-list tr>:nth-child(5){width:160px}.consul-intention-list tr>:last-child{width:60px}.consul-intention-list .menu-panel.confirmation{width:200px}@media (max-width:849px){.consul-intention-list tr>:not(.source):not(.destination):not(.intent){display:none}}.consul-intention-action-warn-modal .modal-dialog-window{max-width:450px}.consul-intention-action-warn-modal .modal-dialog-body p{font-size:var(--typo-size-600)}.consul-intention-fieldsets [role=radiogroup]{overflow:visible!important;display:grid;grid-gap:12px;grid-template-columns:repeat(auto-fit,minmax(270px,auto))}.consul-intention-fieldsets .radio-card header>*{display:inline}.consul-intention-fieldsets .permissions>button{float:right}.consul-intention-permission-modal [role=dialog]{width:100%}.consul-intention-permission-list dl.permission-methods dt::before{content:"M"}.consul-intention-permission-list dl.permission-path dt::before{content:"P"}.consul-intention-permission-header-list dt::before,.consul-intention-permission-list dl.permission-header dt::before{content:"H"}.consul-intention-permission-list .detail>div{display:flex;width:100%}.consul-intention-permission-list strong{margin-right:8px}.consul-intention-permission-form h2{border-top:1px solid var(--token-color-foreground-action);padding-top:1.4em;margin-top:.2em;margin-bottom:.6em}.consul-intention-permission-form .consul-intention-permission-header-form{margin-top:10px}.consul-intention-permission-form .consul-intention-permission-header-form fieldset>div,.consul-intention-permission-form fieldset:nth-child(2)>div{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));grid-gap:12px}.consul-intention-permission-form fieldset:nth-child(2)>div label:last-child{grid-column:span 2}.consul-intention-permission-form .ember-basic-dropdown-trigger{padding:5px}.consul-intention-permission-form .checkbox-group{flex-direction:column}.consul-intention-permission-header-list{max-height:200px;overflow:auto}.consul-lock-session-list button{margin-right:var(--horizontal-padding)}.consul-lock-session-form{overflow:hidden}.consul-server-list ul{display:grid;grid-template-columns:repeat(4,minmax(215px,25%));gap:12px}.consul-server-list a:hover div{box-shadow:var(--token-elevation-overlay-box-shadow);--tone-border:var(--token-color-foreground-faint)}.consul-server-card .name+dd{color:var(--token-color-hashicorp-brand);-webkit-animation-name:typo-truncate;animation-name:typo-truncate}.consul-server-card .health-status+dd{font-size:var(--typo-size-700)}.voting-status-non-voter.consul-server-card .health-status+dd{background-color:var(--token-color-surface-strong);color:var(--token-color-foreground-faint)}.consul-server-card:not(.voting-status-non-voter) .health-status.healthy+dd{background-color:var(--token-color-surface-success);color:var(--token-color-palette-green-400)}.consul-server-card:not(.voting-status-non-voter) .health-status:not(.healthy)+dd{background-color:var(--token-color-surface-critical);color:var(--token-color-foreground-critical)}.consul-server-card .health-status+dd::before{--icon-size:icon-000;content:""}.consul-server-card .health-status.healthy+dd::before{--icon-name:icon-check}.consul-server-card .health-status:not(.healthy)+dd::before{--icon-name:icon-x}.consul-server-card{position:relative;overflow:hidden;--padding-x:24px;--padding-y:24px;padding:var(--padding-y) var(--padding-x);--tile-size:3rem}.consul-auth-method-binding-list h2,.consul-auth-method-view section h2{padding-bottom:12px}.voting-status-leader.consul-server-card .name{position:absolute!important}.consul-server-card dd:not(:last-of-type){margin-bottom:calc(var(--padding-y)/ 2)}.voting-status-leader.consul-server-card dd{margin-left:calc(var(--tile-size) + 1rem)}.consul-auth-method-list ul .locality::before{margin-right:4px}.consul-auth-method-view{margin-bottom:32px}.consul-auth-method-view section{width:100%;position:relative;overflow-y:auto}.consul-auth-method-view section table thead td{color:var(--token-color-foreground-faint);font-weight:var(--typo-weight-semibold);font-size:var(--typo-size-700)}.consul-auth-method-view section table tbody td{font-size:var(--typo-size-600);color:var(--token-color-hashicorp-brand)}.consul-auth-method-view section table tbody tr{cursor:default}.consul-auth-method-view section table tbody tr:hover{box-shadow:none}.consul-auth-method-view section dt{width:30%}.consul-auth-method-view section dd{width:70%}.consul-auth-method-binding-list p{margin-bottom:4px!important}.consul-auth-method-binding-list code{background-color:var(--token-color-surface-strong);padding:0 12px}.consul-auth-method-nspace-list thead td{color:var(--token-color-foreground-faint)!important;font-weight:var(--typo-weight-semibold)!important;font-size:var(--typo-size-700)!important}.consul-auth-method-nspace-list tbody td{font-size:var(--typo-size-600);color:var(--token-color-hashicorp-brand)}.consul-auth-method-nspace-list tbody tr{cursor:default}.consul-auth-method-nspace-list tbody tr:hover{box-shadow:none}.role-selector [name="role[state]"],.role-selector [name="role[state]"]+*{display:none}.role-selector [name="role[state]"]:checked+*{display:block}.topology-notices button{color:var(--token-color-foreground-action);float:right;margin-top:16px;margin-bottom:32px}#metrics-container .link a,.topology-container{color:var(--token-color-foreground-faint)}#downstream-container .topology-metrics-card:not(:last-child),#upstream-column #upstream-container:not(:last-child),#upstream-container .topology-metrics-card:not(:last-child){margin-bottom:8px}#downstream-container,#metrics-container,#upstream-container{border-radius:var(--decor-radius-100);border:1px solid;border-color:var(--token-color-surface-interactive-active)}#downstream-container,#upstream-container{background-color:var(--token-color-surface-strong);padding:12px}#downstream-container>div:first-child{display:inline-flex}#downstream-container>div:first-child span::before{background-color:var(--token-color-foreground-faint)}#metrics-container div:first-child{background-color:var(--token-color-surface-primary);padding:12px;border:none;font-size:16px;font-weight:700}#metrics-container .link{background-color:var(--token-color-surface-strong);padding:18px}#metrics-container .link a:hover{color:var(--token-color-foreground-action)}#downstream-lines svg path,#upstream-lines svg path{fill:transparent}#downstream-lines svg .allow-arrow,#upstream-lines svg .allow-arrow{fill:var(--token-color-palette-neutral-300);stroke-linejoin:round}#downstream-lines svg .allow-arrow,#downstream-lines svg .allow-dot,#downstream-lines svg path,#upstream-lines svg .allow-arrow,#upstream-lines svg .allow-dot,#upstream-lines svg path{stroke:var(--token-color-palette-neutral-300);stroke-width:2}#downstream-lines svg path[data-permission=empty],#downstream-lines svg path[data-permission=not-defined],#upstream-lines svg path[data-permission=empty],#upstream-lines svg path[data-permission=not-defined]{stroke-dasharray:4}#downstream-lines svg path[data-permission=deny],#upstream-lines svg path[data-permission=deny]{stroke:var(--token-color-foreground-critical)}#downstream-lines svg .deny-dot,#upstream-lines svg .deny-dot{stroke:var(--token-color-foreground-critical);stroke-width:2}#downstream-lines svg .deny-arrow,#upstream-lines svg .deny-arrow{fill:var(--token-color-foreground-critical);stroke:var(--token-color-foreground-critical);stroke-linejoin:round}.topology-notices{display:flow-root}.topology-container{display:grid;height:100%;align-items:start;grid-template-columns:2fr 1fr 2fr 1fr 2fr;grid-template-rows:50px 1fr 50px;grid-template-areas:"down-cards down-lines . up-lines up-cards" "down-cards down-lines metrics up-lines up-cards" "down-cards down-lines . up-lines up-cards"}#downstream-container{grid-area:down-cards}#downstream-lines{grid-area:down-lines;margin-left:-20px}#upstream-lines{grid-area:up-lines;margin-right:-20px}#upstream-column{grid-area:up-cards}#downstream-lines,#upstream-lines{position:relative}#metrics-container{grid-area:metrics}#metrics-container .link a::before{background-color:var(--token-color-foreground-faint);margin-right:4px}#downstream-container .topology-metrics-card,#upstream-container .topology-metrics-card{display:block;color:var(--token-color-foreground-faint);overflow:hidden;background-color:var(--token-color-surface-primary);border-radius:var(--decor-radius-100);border:1px solid;border-color:var(--token-color-surface-interactive-active)}#downstream-container .topology-metrics-card p,#upstream-container .topology-metrics-card p{padding:12px 12px 0;font-size:var(--typo-size-500);font-weight:var(--typo-weight-semibold);margin-bottom:0!important}#downstream-container .topology-metrics-card p.empty,#upstream-container .topology-metrics-card p.empty{padding:12px!important}#downstream-container .topology-metrics-card div dl,#upstream-container .topology-metrics-card div dl{display:inline-flex;margin-right:8px}#downstream-container .topology-metrics-card div dd,#upstream-container .topology-metrics-card div dd{color:var(--token-color-foreground-faint)}#downstream-container .topology-metrics-card div span,#upstream-container .topology-metrics-card div span{margin-right:8px}#downstream-container .topology-metrics-card div dt::before,#downstream-container .topology-metrics-card div span::before,#upstream-container .topology-metrics-card div dt::before,#upstream-container .topology-metrics-card div span::before{margin-right:4px}#downstream-container .topology-metrics-card div .health dt::before,#downstream-container .topology-metrics-card div .nspace dt::before,#upstream-container .topology-metrics-card div .health dt::before,#upstream-container .topology-metrics-card div .nspace dt::before{margin-top:2px}#downstream-container .topology-metrics-card div .health dt::before,#downstream-container .topology-metrics-card div .nspace dt::before,#downstream-container .topology-metrics-card div .partition dt::before,#upstream-container .topology-metrics-card div .health dt::before,#upstream-container .topology-metrics-card div .nspace dt::before,#upstream-container .topology-metrics-card div .partition dt::before{--icon-color:var(--token-color-foreground-faint)}#downstream-container .topology-metrics-card div .passing::before,#upstream-container .topology-metrics-card div .passing::before{--icon-color:var(--token-color-foreground-success)}#downstream-container .topology-metrics-card div .warning::before,#upstream-container .topology-metrics-card div .warning::before{--icon-color:var(--token-color-foreground-warning)}#downstream-container .topology-metrics-card div .critical::before,#upstream-container .topology-metrics-card div .critical::before{--icon-color:var(--token-color-foreground-critical)}#downstream-container .topology-metrics-card div .empty::before,#upstream-container .topology-metrics-card div .empty::before{--icon-color:var(--token-color-foreground-faint)}#downstream-container .topology-metrics-card .details,#upstream-container .topology-metrics-card .details{padding:0 12px 12px}#downstream-container .topology-metrics-card .details>:not(:last-child),#upstream-container .topology-metrics-card .details>:not(:last-child){padding-bottom:6px}#downstream-container .topology-metrics-card .details .group,#upstream-container .topology-metrics-card .details .group{display:grid;grid-template-columns:20px 1fr;grid-template-rows:repeat(2,1fr);grid-template-areas:"partition partition" "union namespace"}#downstream-container .topology-metrics-card .details .group span,#upstream-container .topology-metrics-card .details .group span{display:inline-block;grid-area:union;padding-left:7px;margin-right:0}#downstream-container .topology-metrics-card .details .group span::before,#upstream-container .topology-metrics-card .details .group span::before{margin-right:0;--icon-color:var(--token-color-foreground-faint)}#downstream-container .topology-metrics-card .details .group dl:first-child,#upstream-container .topology-metrics-card .details .group dl:first-child{grid-area:partition;padding-bottom:6px}#downstream-container .topology-metrics-card .details .group dl:nth-child(2),#upstream-container .topology-metrics-card .details .group dl:nth-child(2){grid-area:namespace}.topology-metrics-source-type{margin:6px 0 6px 12px;display:table}.topology-metrics-popover>button{position:absolute;transform:translate(-50%,-50%);background-color:var(--token-color-surface-primary);padding:1px}.topology-metrics-popover>button:hover{cursor:pointer}.topology-metrics-popover>button:disabled,html[data-route^="dc.nodes.show.metadata"] table tr{cursor:default}.topology-metrics-popover>button:active,.topology-metrics-popover>button:focus{outline:0}.topology-metrics-popover.deny .informed-action header::before{display:none}.topology-metrics-popover.deny .tippy-arrow::after,.topology-metrics-popover.deny>button::before{--icon-color:var(--token-color-foreground-critical)}.topology-metrics-popover.not-defined .tippy-arrow::after,.topology-metrics-popover.not-defined>button::before{--icon-color:var(--token-color-vault-brand)}#metrics-container .sparkline-wrapper svg path{stroke-width:0}#metrics-container .sparkline-wrapper .tooltip{padding:0 0 10px;font-size:.875em;line-height:1.5em;font-weight:400;border:1px solid var(--token-color-palette-neutral-300);background:#fff;border-radius:2px;box-sizing:border-box;box-shadow:var(--token-elevation-higher-box-shadow)}#metrics-container .sparkline-wrapper .tooltip .sparkline-time{padding:8px 10px;font-weight:700;font-size:14px;color:#000;border-bottom:1px solid var(--token-color-surface-interactive-active);margin-bottom:4px;text-align:center}#metrics-container .sparkline-wrapper .tooltip .sparkline-tt-legend,#metrics-container .sparkline-wrapper .tooltip .sparkline-tt-sum{border:0;padding:3px 10px 0}#metrics-container .sparkline-wrapper .tooltip .sparkline-tt-sum{border-top:1px solid var(--token-color-surface-interactive-active);margin-top:4px;padding:8px 10px 0}#metrics-container .sparkline-wrapper .tooltip .sparkline-tt-legend-color{width:12px;height:12px;border-radius:2px;margin:0 5px 0 0;padding:0}#metrics-container .sparkline-wrapper .tooltip .sparkline-tt-legend-value,#metrics-container .sparkline-wrapper .tooltip .sparkline-tt-sum-value{float:right}#metrics-container .sparkline-wrapper div.tooltip:before{content:"";display:block;position:absolute;width:12px;height:12px;left:15px;bottom:-7px;border:1px solid var(--token-color-palette-neutral-300);border-top:0;border-left:0;background:#fff;transform:rotate(45deg)}.sparkline-key h3::before{margin:2px 3px 0 0;font-size:14px}.sparkline-key h3{color:var(--token-color-foreground-strong);font-size:16px}.sparkline-key .sparkline-key-content dd,.sparkline-key-link{color:var(--token-color-foreground-faint)}.sparkline-key-link:hover{color:var(--token-color-foreground-action)}#metrics-container:hover .sparkline-key-link::before{margin:1px 3px 0 0;font-size:12px}#metrics-container div .sparkline-wrapper,#metrics-container div .sparkline-wrapper svg.sparkline{width:100%;height:70px;padding:0;margin:0}#metrics-container div .sparkline-wrapper{position:relative}#metrics-container div .sparkline-wrapper .tooltip{visibility:hidden;position:absolute;z-index:10;bottom:78px;width:217px}#metrics-container div .sparkline-wrapper .sparkline-tt-legend-color{display:inline-block}#metrics-container div .sparkline-wrapper .topology-metrics-error,#metrics-container div .sparkline-wrapper .topology-metrics-loader{padding-top:15px}.sparkline-key .sparkline-key-content{width:500px;min-height:100px}.sparkline-key .sparkline-key-content dl{padding:10px 0 0}.sparkline-key .sparkline-key-content dt{font-weight:600;width:125px;float:left}.sparkline-key .sparkline-key-content dd{margin:0 0 12px 135px}.sparkline-key-link{visibility:hidden;float:right;margin-top:-35px;margin-right:12px}#metrics-container:hover .sparkline-key-link{visibility:visible}.topology-metrics-stats{padding:12px 12px 0;display:flex;flex-flow:row wrap;justify-content:space-between;align-items:stretch;width:100%;border-top:1px solid var(--token-color-surface-interactive-active)}.topology-metrics-stats dl{display:flex;padding-bottom:12px}.topology-metrics-stats dt{margin-right:5px;line-height:1.5em!important}.topology-metrics-stats dd{color:var(--token-color-foreground-disabled)!important}.topology-metrics-stats span{padding-bottom:12px}.topology-metrics-status-error,.topology-metrics-status-loader{font-weight:400;font-size:.875rem;color:var(--token-color-foreground-faint);text-align:center;margin:0 auto!important;display:block}.topology-metrics-status-error span::before,.topology-metrics-status-loader span::before{background-color:var(--token-color-foreground-faint)}span.topology-metrics-status-loader::after{--icon-name:var(--icon-loading);content:"";margin-left:.5rem}.consul-node-peer-info .consul-node-peer-info__name,.consul-peer-info .consul-peer-info__description{margin-left:4px}.consul-intention-list-table__meta-info{display:flex}.consul-intention-list-table__meta-info .consul-intention-list-table__meta-info__peer{display:flex;align-items:center}.consul-node-peer-info,.peerings-badge{align-items:center;display:flex}.consul-peer-search-bar .value-active span::before,.consul-peer-search-bar .value-deleting span::before,.consul-peer-search-bar .value-establishing span::before,.consul-peer-search-bar .value-failing span::before,.consul-peer-search-bar .value-pending span::before,.consul-peer-search-bar .value-terminated span::before{--icon-size:icon-000;content:""}.consul-peer-search-bar .value-active span,.consul-peer-search-bar .value-deleting span,.consul-peer-search-bar .value-establishing span,.consul-peer-search-bar .value-failing span,.consul-peer-search-bar .value-pending span,.consul-peer-search-bar .value-terminated span{font-weight:var(--typo-weight-medium);font-size:var(--typo-size-700)}.consul-peer-search-bar .value-pending span::before{--icon-name:icon-running;--icon-color:var(--token-color-palette-neutral-600)}.consul-peer-search-bar .value-pending span{background-color:var(--token-color-consul-surface);color:var(--token-color-consul-foreground)}.consul-peer-search-bar .value-establishing span::before{--icon-name:icon-running;--icon-color:var(--token-color-palette-neutral-600)}.consul-peer-search-bar .value-establishing span{background-color:var(--token-color-palette-blue-50);color:var(--token-color-palette-blue-200)}.consul-peer-search-bar .value-active span::before{--icon-name:icon-check;--icon-color:var(--token-color-palette-green-400)}.consul-peer-search-bar .value-active span{background-color:var(--token-color-palette-green-50);color:var(--token-color-palette-green-200)}.consul-peer-search-bar .value-failing span::before{--icon-name:icon-x;--icon-color:var(--token-color-palette-red-200)}.consul-peer-search-bar .value-failing span{background-color:var(--token-color-palette-red-50);color:var(--token-color-palette-red-200)}.consul-peer-search-bar .value-terminated span::before{--icon-name:icon-x-square;--icon-color:var(--token-color-palette-neutral-600)}.consul-peer-search-bar .value-terminated span{background-color:var(--token-color-palette-neutral-200);color:var(--token-color-palette-neutral-600)}.consul-peer-search-bar .value-deleting span::before{--icon-name:icon-loading;--icon-color:var(--token-color-foreground-warning-on-surface)}.consul-peer-search-bar .value-deleting span{background-color:var(--token-color-surface-warning);color:var(--token-color-foreground-warning-on-surface)}.peers__list__peer-detail{display:flex;align-content:center;gap:18px}.border-bottom-primary{border-bottom:1px solid var(--token-color-border-primary)}.peerings-badge{justify-content:center;padding:2px 8px;border-radius:5px;gap:4px}.peerings-badge.active{background:var(--token-color-surface-success);color:var(--token-color-foreground-success)}.peerings-badge.pending{background:var(--token-color-consul-surface);color:var(--token-color-consul-brand)}.peerings-badge.establishing{background:var(--token-color-surface-action);color:var(--token-color-foreground-action)}.peerings-badge.failing{background:var(--token-color-surface-critical);color:var(--token-color-foreground-critical)}.peerings-badge.deleting{background:var(--token-color-surface-warning);color:var(--token-color-foreground-warning-on-surface)}.peerings-badge.terminated,.peerings-badge.undefined{background:var(--token-color-surface-interactive-active);color:var(--token-color-foreground-primary)}.consul-peer-info,section[data-route="dc.show.serverstatus"] .server-failure-tolerance dt{color:var(--token-color-foreground-faint)}.peerings-badge .peerings-badge__text{font-weight:500;font-size:13px}.consul-peer-info{background:var(--token-color-surface-faint);padding:0 8px;border-radius:2px;display:flex;align-items:center}.consul-peer-form{width:416px}.consul-peer-form nav{margin-bottom:20px}.consul-peer-form-generate{width:416px;min-height:200px}.consul-peer-form-generate ol{list-style-position:outside;list-style-type:none;counter-reset:hexagonal-counter;position:relative}.consul-peer-form-generate ol::before{content:"";border-left:var(--decor-border-100);border-color:var(--token-color-palette-neutral-300);height:100%;position:absolute;left:2rem}.consul-peer-form-generate li{counter-increment:hexagonal-counter;position:relative;margin-left:60px;margin-bottom:1rem}.consul-peer-form-generate li .copyable-code{margin-top:1rem}.consul-peer-form-generate li::before{--icon-name:icon-hexagon;--icon-size:icon-600;content:"";position:absolute;z-index:2}.consul-peer-form-generate li::after{content:counter(hexagonal-counter);position:absolute;top:0;font-size:14px;font-weight:var(--typo-weight-bold);background-color:var(--token-color-palette-neutral-0);z-index:1;text-align:center}.consul-peer-form-generate li::after,.consul-peer-form-generate li::before{left:-2.4rem;width:20px;height:20px}.consul-hcp-home{position:relative;top:-22px}.consul-hcp-home a::before{content:"";--icon-name:icon-arrow-left;--icon-size:icon-300;margin-right:8px}.agentless-node-notice .hds-alert__title{display:flex;justify-content:space-between}.definition-table dt{line-height:var(--typo-lead-700)}.app-view>div form:not(.filter-bar) [role=radiogroup] label,.modal-dialog [role=document] [role=radiogroup] label{line-height:var(--typo-lead-200)}.app-view>div form:not(.filter-bar) [role=radiogroup] label>span,.consul-intention-action-warn-modal button.dangerous,.copy-button button,.modal-dialog [role=document] .type-password>span,.modal-dialog [role=document] .type-select>span,.modal-dialog [role=document] .type-text>span,.modal-dialog [role=document] [role=radiogroup] label>span,.oidc-select label>span,.popover-select label>*,.topology-notices button,.type-sort.popover-select label>*,.type-toggle>span,main .type-password>span,main .type-select>span,main .type-text>span,span.label{font-weight:var(--typo-weight-semibold)}.discovery-chain .route-card header:not(.short) dd,.discovery-chain .route-card section dt,.discovery-chain .splitter-card>header{font-weight:var(--typo-weight-bold)}.app-view h1 em,.app-view>div form:not(.filter-bar) [role=radiogroup] label>strong,.consul-auth-method-type,.consul-external-source,.consul-health-check-list .health-check-output dd em,.consul-intention-list td strong,.consul-intention-list td.destination em,.consul-intention-list td.source em,.consul-intention-permission-list strong,.consul-intention-search-bar li button span,.consul-kind,.consul-peer-search-bar li button span,.consul-server-card .health-status+dd,.consul-source,.consul-transparent-proxy,.discovery-chain .route-card header dt,.discovery-chain .route-card>header ul li,.empty-state header :nth-child(2),.hashicorp-consul nav .dcs .dc-name span,.hashicorp-consul nav .dcs li.is-local span,.hashicorp-consul nav .dcs li.is-primary span,.leader,.modal-dialog [role=document] .type-password>strong,.modal-dialog [role=document] .type-select>strong,.modal-dialog [role=document] .type-text>strong,.modal-dialog [role=document] [role=radiogroup] label>strong,.modal-dialog [role=document] label a[rel*=help],.modal-dialog [role=document] table td:first-child em,.oidc-select label>strong,.search-bar-status li:not(.remove-all),.topology-metrics-source-type,.type-toggle>strong,html[data-route^="dc.acls.index"] main td strong,main .type-password>strong,main .type-select>strong,main .type-text>strong,main label a[rel*=help],main table td:first-child em,section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl,section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em,span.policy-node-identity,span.policy-service-identity{font-weight:var(--typo-weight-normal)}.app-view h1 em,.app-view>div form:not(.filter-bar) [role=radiogroup] label>em,.consul-intention-list td.destination em,.consul-intention-list td.source em,.modal-dialog [role=document] .type-password>em,.modal-dialog [role=document] .type-select>em,.modal-dialog [role=document] .type-text>em,.modal-dialog [role=document] [role=radiogroup] label>em,.modal-dialog [role=document] form button+em,.modal-dialog [role=document] table td:first-child em,.oidc-select label>em,.type-toggle>em,main .type-password>em,main .type-select>em,main .type-text>em,main form button+em,main table td:first-child em{font-style:normal}.consul-exposed-path-list>ul>li>.header,.consul-lock-session-list ul>li:not(:first-child)>.header,.consul-upstream-instance-list li>.header,.list-collection>ul>li:not(:first-child)>.header{font-size:var(--typo-size-450);font-weight:var(--typo-weight-medium)}.consul-exposed-path-list>ul>li>.header :not(button),.consul-lock-session-list ul>li:not(:first-child)>.header :not(button),.consul-upstream-instance-list li>.header :not(button),.list-collection>ul>li:not(:first-child)>.header :not(button){font-size:inherit;font-weight:inherit}.app-view h1 em{font-size:var(--typo-size-500)}@media (max-width:420px) and (-webkit-min-device-pixel-ratio:0){input{font-size:16px!important}}#wrapper{box-sizing:content-box}#wrapper>footer>*,.modal-dialog>*,main>*{box-sizing:border-box}html[data-route$=create] main,html[data-route$=edit] main{max-width:1260px}fieldset [role=group]{display:flex;flex-wrap:wrap;flex-direction:row}.outlet[data-state=loading],html.ember-loading .view-loader,html:not(.has-nspaces) [class*=nspace-],html:not(.has-partitions) [class*=partition-],html[data-state=idle] .view-loader{display:none}[role=group] fieldset{width:50%}[role=group] fieldset:not(:first-of-type){padding-left:20px;border-left:1px solid;border-left:var(--token-color-foreground-faint)}[role=group] fieldset:not(:last-of-type){padding-right:20px}.app-view{margin-top:50px}@media (max-width:849px){html:not(.with-breadcrumbs) .app-view{margin-top:10px}}html body>.brand-loader{transition-property:transform,opacity;transform:translate(0,0);opacity:1}html[data-state]:not(.ember-loading) body>.brand-loader{opacity:0}@media (min-width:900px){html[data-state] body>.brand-loader{transform:translate(calc(var(--chrome-width)/ 2),0)}}html[data-route$=create] .app-view>header+div>:first-child,html[data-route$=edit] .app-view>header+div>:first-child{margin-top:1.8em}.app-view>div .container,.app-view>div .tab-section .consul-health-check-list,.app-view>div .tab-section>.search-bar+p,.app-view>div .tab-section>:first-child:not(.filter-bar):not(table){margin-top:1.25em}.consul-upstream-instance-list,html[data-route^="dc.nodes.show.sessions"] .consul-lock-session-list{margin-top:0!important}.consul-auth-method-list ul,.consul-node-list ul,.consul-nspace-list ul,.consul-peer-list ul,.consul-policy-list ul,.consul-role-list ul,.consul-service-instance-list ul,.consul-token-list ul,html[data-route="dc.services.index"] .consul-service-list ul,html[data-route^="dc.nodes.show.sessions"] .consul-lock-session-list ul{border-top-width:0!important}#wrapper{padding-left:48px;padding-right:48px;display:flex;min-height:100vh;flex-direction:column}main{position:relative;flex:1}html:not([data-route$=index]):not([data-route$=instances]) main{margin-bottom:2em}@media (max-width:849px){.actions button.copy-btn{margin-top:-56px;padding:0}}.modal-dialog [role=document] p:not(:last-child),main p:not(:last-child){margin-bottom:1em}.modal-dialog [role=document] form+div .with-confirmation,.modal-dialog [role=document] form:not(.filter-bar),main form+div .with-confirmation,main form:not(.filter-bar){margin-bottom:2em}@media (max-width:420px){main form [type=reset]{float:right;margin-right:0!important}}html[data-route^="dc.services.show"] .app-view .actions .external-dashboard{position:absolute;top:50px;right:0}html[data-route^="dc.services.instance"] .app-view>header dl{float:left;margin-top:19px;margin-bottom:23px;margin-right:50px}html[data-route^="dc.services.instance"] .app-view>header dt{font-weight:var(--typo-weight-bold)}html[data-route^="dc.services.instance"] .tab-nav{border-top:var(--decor-border-100)}html[data-route^="dc.services.instance"] .tab-section section:not(:last-child){border-bottom:var(--decor-border-100);padding-bottom:24px}html[data-route^="dc.services.instance"] .tab-nav,html[data-route^="dc.services.instance"] .tab-section section:not(:last-child){border-color:var(--token-color-surface-interactive-active)}html[data-route^="dc.services.instance.metadata"] .tab-section section h2{margin:24px 0 12px}html[data-route^="dc.kv"] .type-toggle{float:right;margin-bottom:0!important}html[data-route^="dc.kv.edit"] h2{border-bottom:var(--decor-border-200);border-color:var(--token-color-surface-interactive-active);padding-bottom:.2em;margin-bottom:.5em}html[data-route^="dc.acls.index"] main td strong{margin-right:3px}@media (max-width:420px){html[data-route^="dc.acls.create"] main header .actions,html[data-route^="dc.acls.edit"] main header .actions{float:none;display:flex;justify-content:space-between;margin-bottom:1em}html[data-route^="dc.acls.create"] main header .actions .with-feedback,html[data-route^="dc.acls.edit"] main header .actions .with-feedback{position:absolute;right:0}html[data-route^="dc.acls.create"] main header .actions .with-confirmation,html[data-route^="dc.acls.edit"] main header .actions .with-confirmation{margin-top:0}}html[data-route^="dc.intentions.edit"] .definition-table{margin-bottom:1em}section[data-route="dc.show.serverstatus"] .server-failure-tolerance{box-shadow:none;padding:var(--padding-y) var(--padding-x);max-width:770px;display:flex;flex-wrap:wrap}section[data-route="dc.show.serverstatus"] .server-failure-tolerance>header{width:100%;display:flex;flex-direction:row;justify-content:space-between;align-items:center;padding-bottom:.5rem;margin-bottom:1rem;border-bottom:var(--decor-border-100);border-color:var(--tone-border)}section[data-route="dc.show.serverstatus"] .server-failure-tolerance header em{font-size:.812rem;background-color:var(--token-color-surface-interactive-active);text-transform:uppercase;font-style:normal}section[data-route="dc.show.serverstatus"] .server-failure-tolerance>section{width:50%}section[data-route="dc.show.serverstatus"] .server-failure-tolerance dl,section[data-route="dc.show.serverstatus"] .server-failure-tolerance>section{display:flex;flex-direction:column}section[data-route="dc.show.serverstatus"] .server-failure-tolerance dl{flex-grow:1;justify-content:space-between}section[data-route="dc.show.serverstatus"] .server-failure-tolerance dl.warning dd::before{--icon-name:icon-alert-circle;--icon-size:icon-800;--icon-color:var(--token-color-foreground-warning);content:"";margin-right:.5rem}section[data-route="dc.show.serverstatus"] .server-failure-tolerance section:first-of-type dl{padding-right:1.5rem}section[data-route="dc.show.serverstatus"] .server-failure-tolerance dd{display:flex;align-items:center;font-size:var(--typo-size-250);color:var(--token-color-hashicorp-brand)}section[data-route="dc.show.serverstatus"] .server-failure-tolerance header span::before{--icon-name:icon-info;--icon-size:icon-300;--icon-color:var(--token-color-foreground-faint);vertical-align:unset;content:""}section[data-route="dc.show.serverstatus"] section:not([class*=-tolerance]) h2{margin-top:1.5rem;margin-bottom:1.5rem}section[data-route="dc.show.serverstatus"] section:not([class*=-tolerance]) header{margin-top:18px;margin-bottom:18px}section[data-route="dc.show.serverstatus"] .redundancy-zones section header{display:flow-root}section[data-route="dc.show.serverstatus"] .redundancy-zones section header h3{float:left;margin-right:.5rem}section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl:not(.warning){background-color:var(--token-color-surface-strong)}section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl.warning{background-color:var(--token-color-border-warning);color:var(--token-color-palette-amber-400)}section[data-route="dc.show.serverstatus"] .redundancy-zones section header dl.warning::before{--icon-name:icon-alert-circle;--icon-size:icon-000;margin-right:.312rem;content:""}section[data-route="dc.show.serverstatus"] .redundancy-zones section header dt::after{content:":";display:inline-block;vertical-align:revert;background-color:transparent}section[data-route="dc.show.license"] .validity p{color:var(--token-color-foreground-faint)}section[data-route="dc.show.license"] .validity dl{font-size:var(--typo-size-400)}section[data-route="dc.show.license"] .validity dl dt::before{content:"";margin-right:.25rem}section[data-route="dc.show.license"] .validity dl .expired::before{--icon-name:icon-x-circle;--icon-color:var(--token-color-foreground-critical)}section[data-route="dc.show.license"] .validity dl .warning::before{--icon-name:icon-alert-circle;--icon-color:var(--token-color-foreground-warning)}section[data-route="dc.show.license"] .validity dl .valid:not(.warning)::before{--icon-name:icon-check-circle;--icon-color:var(--token-color-foreground-success)}section[data-route="dc.show.license"] aside{box-shadow:none;padding:var(--padding-y) var(--padding-x);width:40%;min-width:413px;margin-top:1rem}section[data-route="dc.show.license"] aside header{margin-bottom:1rem}.prefers-reduced-motion{--icon-loading:icon-loading}@media (prefers-reduced-motion){:root{--icon-loading:icon-loading}}.consul-intention-fieldsets .value->:last-child::before,.consul-intention-fieldsets .value-allow>:last-child::before,.consul-intention-fieldsets .value-deny>:last-child::before{--icon-size:icon-500;--icon-resolution:0.5}.consul-intention-fieldsets .value-allow>:last-child::before,.consul-intention-list td.intent-allow strong::before,.consul-intention-permission-list .intent-allow::before,.consul-intention-search-bar .value-allow span::before{--icon-name:icon-arrow-right;--icon-color:var(--token-color-foreground-success-on-surface)}.consul-intention-fieldsets .value-deny>:last-child::before,.consul-intention-list td.intent-deny strong::before,.consul-intention-permission-list .intent-deny::before,.consul-intention-search-bar .value-deny span::before{--icon-name:icon-skip;--icon-color:var(--token-color-foreground-critical-on-surface)}.consul-intention-fieldsets .value->:last-child::before,.consul-intention-list td.intent- strong::before,.consul-intention-search-bar .value- span::before{--icon-name:icon-layers}*{border-width:0}.animatable.tab-nav ul::after,.consul-auth-method-type,.consul-external-source,.consul-intention-action-warn-modal button.dangerous,.consul-intention-action-warn-modal button.dangerous:disabled,.consul-intention-action-warn-modal button.dangerous:focus,.consul-intention-action-warn-modal button.dangerous:hover:active,.consul-intention-action-warn-modal button.dangerous:hover:not(:disabled):not(:active),.consul-intention-list td.intent- strong,.consul-intention-permission-form button.type-submit,.consul-intention-permission-form button.type-submit:disabled,.consul-intention-permission-form button.type-submit:focus:not(:disabled),.consul-intention-permission-form button.type-submit:hover:not(:disabled),.consul-intention-search-bar .value- span,.consul-kind,.consul-source,.consul-transparent-proxy,.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:first-child,.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:focus:first-child,.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:hover:first-child,.discovery-chain .route-card>header ul li,.informed-action>ul>.dangerous>*,.informed-action>ul>.dangerous>:focus,.informed-action>ul>.dangerous>:hover,.leader,.menu-panel>ul>li.dangerous>:first-child,.menu-panel>ul>li.dangerous>:focus:first-child,.menu-panel>ul>li.dangerous>:hover:first-child,.modal-dialog [role=document]>footer,.modal-dialog [role=document]>header,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:first-child,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child,.tab-nav .selected>*,.topology-metrics-source-type,html[data-route^="dc.acls.index"] main td strong,span.policy-node-identity,span.policy-service-identity,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:first-child,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child{border-style:solid}.consul-auth-method-type,.consul-external-source,.consul-kind,.consul-source,.consul-transparent-proxy,.leader,.topology-metrics-source-type,span.policy-node-identity,span.policy-service-identity{background-color:var(--token-color-surface-strong);border-color:var(--token-color-foreground-faint);color:var(--token-color-foreground-primary)}.consul-intention-list td.intent- strong,.consul-intention-search-bar .value- span,.discovery-chain .route-card>header ul li,.modal-dialog [role=document]>footer,.modal-dialog [role=document]>header,html[data-route^="dc.acls.index"] main td strong{background-color:var(--token-color-surface-strong);border-color:var(--token-color-palette-neutral-300);color:var(--token-color-foreground-strong)}.animatable.tab-nav ul::after,.consul-intention-permission-form button.type-submit,.consul-intention-permission-form button.type-submit:disabled,.tab-nav .selected>*{background-color:var(--token-color-surface-primary);border-color:var(--token-color-foreground-action);color:var(--token-color-foreground-action)}.consul-intention-permission-form button.type-submit:focus:not(:disabled),.consul-intention-permission-form button.type-submit:hover:not(:disabled){background-color:var(--token-color-surface-action);border-color:var(--token-color-foreground-action);color:var(--token-color-palette-blue-500)}.consul-intention-action-warn-modal button.dangerous,.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:first-child,.informed-action>ul>.dangerous>*,.menu-panel>ul>li.dangerous>:first-child,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:first-child,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:first-child{background-color:transparent;border-color:var(--token-color-foreground-critical);color:var(--token-color-foreground-critical)}.consul-intention-action-warn-modal button.dangerous:disabled{background-color:var(--token-color-border-critical);border-color:var(--token-color-foreground-disabled);color:var(--token-color-surface-primary)}.consul-intention-action-warn-modal button.dangerous:focus,.consul-intention-action-warn-modal button.dangerous:hover:not(:disabled):not(:active),.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:focus:first-child,.disclosure-menu [aria-expanded]~*>ul>li.dangerous>:hover:first-child,.informed-action>ul>.dangerous>:focus,.informed-action>ul>.dangerous>:hover,.menu-panel>ul>li.dangerous>:focus:first-child,.menu-panel>ul>li.dangerous>:hover:first-child,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,.more-popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,.popover-menu>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,table.has-actions tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:focus:first-child,table.with-details tr>.actions>[type=checkbox]+label+div>ul>li.dangerous>:hover:first-child{background-color:var(--token-color-foreground-critical);border-color:var(--token-color-foreground-critical-high-contrast);color:var(--token-color-surface-primary)}.consul-intention-action-warn-modal button.dangerous:hover:active{background-color:var(--token-color-palette-red-400);border-color:var(--token-color-foreground-critical-high-contrast);color:var(--token-color-surface-primary)}[role=banner] nav:last-of-type .dangerous button:focus,[role=banner] nav:last-of-type .dangerous button:hover{color:var(--token-color-surface-primary)!important}[role=banner] nav:first-of-type .menu-panel a:focus,[role=banner] nav:first-of-type .menu-panel a:hover{background-color:var(--token-color-foreground-action)}.hover\:scale-125:hover{--tw-scale-x:1.25;--tw-scale-y:1.25}.group:hover .group-hover\:opacity-100{opacity:1} \ No newline at end of file diff --git a/agent/uiserver/dist/assets/consul-ui/routes-447282731d763ac6ad60d55ed447a4a6.js b/agent/uiserver/dist/assets/consul-ui/routes-447282731d763ac6ad60d55ed447a4a6.js new file mode 100644 index 000000000000..9c841e4bfc82 --- /dev/null +++ b/agent/uiserver/dist/assets/consul-ui/routes-447282731d763ac6ad60d55ed447a4a6.js @@ -0,0 +1 @@ +((e,t=("undefined"!=typeof document?document.currentScript.dataset:module.exports))=>{t.routes=JSON.stringify(e)})({dc:{_options:{path:"/:dc"},index:{_options:{path:"/",redirect:"../services"}},show:{_options:{path:"/overview",abilities:["access overview"]},serverstatus:{_options:{path:"/server-status",abilities:["read servers"]}},cataloghealth:{_options:{path:"/catalog-health",abilities:["access overview"]}},license:{_options:{path:"/license",abilities:["read license"]}}},services:{_options:{path:"/services"},index:{_options:{path:"/",queryParams:{sortBy:"sort",status:"status",source:"source",kind:"kind",searchproperty:{as:"searchproperty",empty:[["Partition","Name","Tags","PeerName"]]},search:{as:"filter",replace:!0}}}},show:{_options:{path:"/:name"},instances:{_options:{path:"/instances",queryParams:{sortBy:"sort",status:"status",source:"source",searchproperty:{as:"searchproperty",empty:[["Name","Node","Tags","ID","Address","Port","Service.Meta","Node.Meta"]]},search:{as:"filter",replace:!0}}}},intentions:{_options:{path:"/intentions"},index:{_options:{path:"",queryParams:{sortBy:"sort",access:"access",searchproperty:{as:"searchproperty",empty:[["SourceName","DestinationName"]]},search:{as:"filter",replace:!0}}}},edit:{_options:{path:"/:intention_id"}},create:{_options:{template:"../edit",path:"/create"}}},topology:{_options:{path:"/topology"}},services:{_options:{path:"/services",queryParams:{sortBy:"sort",instance:"instance",searchproperty:{as:"searchproperty",empty:[["Name","Tags"]]},search:{as:"filter",replace:!0}}}},upstreams:{_options:{path:"/upstreams",queryParams:{sortBy:"sort",instance:"instance",searchproperty:{as:"searchproperty",empty:[["Name","Tags"]]},search:{as:"filter",replace:!0}}}},routing:{_options:{path:"/routing"}},tags:{_options:{path:"/tags"}}},instance:{_options:{path:"/:name/instances/:node/:id",redirect:"./healthchecks"},healthchecks:{_options:{path:"/health-checks",queryParams:{sortBy:"sort",status:"status",check:"check",searchproperty:{as:"searchproperty",empty:[["Name","Node","CheckID","Notes","Output","ServiceTags"]]},search:{as:"filter",replace:!0}}}},upstreams:{_options:{path:"/upstreams",queryParams:{sortBy:"sort",search:{as:"filter",replace:!0},searchproperty:{as:"searchproperty",empty:[["DestinationName","LocalBindAddress","LocalBindPort"]]}}}},exposedpaths:{_options:{path:"/exposed-paths"}},addresses:{_options:{path:"/addresses"}},metadata:{_options:{path:"/metadata"}}},notfound:{_options:{path:"/:name/:node/:id"}}},nodes:{_options:{path:"/nodes"},index:{_options:{path:"",queryParams:{sortBy:"sort",status:"status",version:"version",searchproperty:{as:"searchproperty",empty:[["Node","Address","Meta","PeerName"]]},search:{as:"filter",replace:!0}}}},show:{_options:{path:"/:name"},healthchecks:{_options:{path:"/health-checks",queryParams:{sortBy:"sort",status:"status",kind:"kind",check:"check",searchproperty:{as:"searchproperty",empty:[["Name","Service","CheckID","Notes","Output","ServiceTags"]]},search:{as:"filter",replace:!0}}}},services:{_options:{path:"/service-instances",queryParams:{sortBy:"sort",status:"status",source:"source",searchproperty:{as:"searchproperty",empty:[["Name","Tags","ID","Address","Port","Service.Meta"]]},search:{as:"filter",replace:!0}}}},rtt:{_options:{path:"/round-trip-time"}},metadata:{_options:{path:"/metadata"}}}},intentions:{_options:{path:"/intentions"},index:{_options:{path:"/",queryParams:{sortBy:"sort",access:"access",searchproperty:{as:"searchproperty",empty:[["SourceName","DestinationName"]]},search:{as:"filter",replace:!0}}}},edit:{_options:{path:"/:intention_id",abilities:["read intentions"]}},create:{_options:{template:"../edit",path:"/create",abilities:["create intentions"]}}},kv:{_options:{path:"/kv"},index:{_options:{path:"/",queryParams:{sortBy:"sort",kind:"kind",search:{as:"filter",replace:!0}}}},folder:{_options:{template:"../index",path:"/*key"}},edit:{_options:{path:"/*key/edit"}},create:{_options:{template:"../edit",path:"/*key/create",abilities:["create kvs"]}},"root-create":{_options:{template:"../edit",path:"/create",abilities:["create kvs"]}}},acls:{_options:{path:"/acls",abilities:["access acls"]},policies:{_options:{path:"/policies",abilities:["read policies"]},edit:{_options:{path:"/:id"}},create:{_options:{path:"/create",abilities:["create policies"]}}},roles:{_options:{path:"/roles",abilities:["read roles"]},edit:{_options:{path:"/:id"}},create:{_options:{path:"/create",abilities:["create roles"]}}},tokens:{_options:{path:"/tokens",abilities:["access acls"]},edit:{_options:{path:"/:id"}},create:{_options:{path:"/create",abilities:["create tokens"]}}},"auth-methods":{_options:{path:"/auth-methods",abilities:["read auth-methods"]},show:{_options:{path:"/:id"},"auth-method":{_options:{path:"/auth-method"}},"binding-rules":{_options:{path:"/binding-rules"}},"nspace-rules":{_options:{path:"/nspace-rules"}}}}},"routing-config":{_options:{path:"/routing-config/:name"}}},index:{_options:{path:"/"}},settings:{_options:{path:"/settings"}},setting:{_options:{path:"/setting",redirect:"../settings"}},unavailable:{_options:{path:"/unavailable"}},notfound:{_options:{path:"/*notfound"}}}) diff --git a/agent/uiserver/dist/assets/consul-ui/routes-c69d5bf72b7c740af5e6ce29eefe65bf.js b/agent/uiserver/dist/assets/consul-ui/routes-c69d5bf72b7c740af5e6ce29eefe65bf.js deleted file mode 100644 index 0004d8645f90..000000000000 --- a/agent/uiserver/dist/assets/consul-ui/routes-c69d5bf72b7c740af5e6ce29eefe65bf.js +++ /dev/null @@ -1 +0,0 @@ -((e,t=("undefined"!=typeof document?document.currentScript.dataset:module.exports))=>{t.routes=JSON.stringify(e)})({dc:{_options:{path:"/:dc"},index:{_options:{path:"/",redirect:"../services"}},show:{_options:{path:"/overview",abilities:["access overview"]},serverstatus:{_options:{path:"/server-status",abilities:["read servers"]}},cataloghealth:{_options:{path:"/catalog-health",abilities:["access overview"]}},license:{_options:{path:"/license",abilities:["read license"]}}},services:{_options:{path:"/services"},index:{_options:{path:"/",queryParams:{sortBy:"sort",status:"status",source:"source",kind:"kind",searchproperty:{as:"searchproperty",empty:[["Partition","Name","Tags","PeerName"]]},search:{as:"filter",replace:!0}}}},show:{_options:{path:"/:name"},instances:{_options:{path:"/instances",queryParams:{sortBy:"sort",status:"status",source:"source",searchproperty:{as:"searchproperty",empty:[["Name","Node","Tags","ID","Address","Port","Service.Meta","Node.Meta"]]},search:{as:"filter",replace:!0}}}},intentions:{_options:{path:"/intentions"},index:{_options:{path:"",queryParams:{sortBy:"sort",access:"access",searchproperty:{as:"searchproperty",empty:[["SourceName","DestinationName"]]},search:{as:"filter",replace:!0}}}},edit:{_options:{path:"/:intention_id"}},create:{_options:{template:"../edit",path:"/create"}}},topology:{_options:{path:"/topology"}},services:{_options:{path:"/services",queryParams:{sortBy:"sort",instance:"instance",searchproperty:{as:"searchproperty",empty:[["Name","Tags"]]},search:{as:"filter",replace:!0}}}},upstreams:{_options:{path:"/upstreams",queryParams:{sortBy:"sort",instance:"instance",searchproperty:{as:"searchproperty",empty:[["Name","Tags"]]},search:{as:"filter",replace:!0}}}},routing:{_options:{path:"/routing"}},tags:{_options:{path:"/tags"}}},instance:{_options:{path:"/:name/instances/:node/:id",redirect:"./healthchecks"},healthchecks:{_options:{path:"/health-checks",queryParams:{sortBy:"sort",status:"status",check:"check",searchproperty:{as:"searchproperty",empty:[["Name","Node","CheckID","Notes","Output","ServiceTags"]]},search:{as:"filter",replace:!0}}}},upstreams:{_options:{path:"/upstreams",queryParams:{sortBy:"sort",search:{as:"filter",replace:!0},searchproperty:{as:"searchproperty",empty:[["DestinationName","LocalBindAddress","LocalBindPort"]]}}}},exposedpaths:{_options:{path:"/exposed-paths"}},addresses:{_options:{path:"/addresses"}},metadata:{_options:{path:"/metadata"}}},notfound:{_options:{path:"/:name/:node/:id"}}},nodes:{_options:{path:"/nodes"},index:{_options:{path:"",queryParams:{sortBy:"sort",status:"status",searchproperty:{as:"searchproperty",empty:[["Node","Address","Meta","PeerName"]]},search:{as:"filter",replace:!0}}}},show:{_options:{path:"/:name"},healthchecks:{_options:{path:"/health-checks",queryParams:{sortBy:"sort",status:"status",kind:"kind",check:"check",searchproperty:{as:"searchproperty",empty:[["Name","Service","CheckID","Notes","Output","ServiceTags"]]},search:{as:"filter",replace:!0}}}},services:{_options:{path:"/service-instances",queryParams:{sortBy:"sort",status:"status",source:"source",searchproperty:{as:"searchproperty",empty:[["Name","Tags","ID","Address","Port","Service.Meta"]]},search:{as:"filter",replace:!0}}}},rtt:{_options:{path:"/round-trip-time"}},metadata:{_options:{path:"/metadata"}}}},intentions:{_options:{path:"/intentions"},index:{_options:{path:"/",queryParams:{sortBy:"sort",access:"access",searchproperty:{as:"searchproperty",empty:[["SourceName","DestinationName"]]},search:{as:"filter",replace:!0}}}},edit:{_options:{path:"/:intention_id",abilities:["read intentions"]}},create:{_options:{template:"../edit",path:"/create",abilities:["create intentions"]}}},kv:{_options:{path:"/kv"},index:{_options:{path:"/",queryParams:{sortBy:"sort",kind:"kind",search:{as:"filter",replace:!0}}}},folder:{_options:{template:"../index",path:"/*key"}},edit:{_options:{path:"/*key/edit"}},create:{_options:{template:"../edit",path:"/*key/create",abilities:["create kvs"]}},"root-create":{_options:{template:"../edit",path:"/create",abilities:["create kvs"]}}},acls:{_options:{path:"/acls",abilities:["access acls"]},policies:{_options:{path:"/policies",abilities:["read policies"]},edit:{_options:{path:"/:id"}},create:{_options:{path:"/create",abilities:["create policies"]}}},roles:{_options:{path:"/roles",abilities:["read roles"]},edit:{_options:{path:"/:id"}},create:{_options:{path:"/create",abilities:["create roles"]}}},tokens:{_options:{path:"/tokens",abilities:["access acls"]},edit:{_options:{path:"/:id"}},create:{_options:{path:"/create",abilities:["create tokens"]}}},"auth-methods":{_options:{path:"/auth-methods",abilities:["read auth-methods"]},show:{_options:{path:"/:id"},"auth-method":{_options:{path:"/auth-method"}},"binding-rules":{_options:{path:"/binding-rules"}},"nspace-rules":{_options:{path:"/nspace-rules"}}}}},"routing-config":{_options:{path:"/routing-config/:name"}}},index:{_options:{path:"/"}},settings:{_options:{path:"/settings"}},setting:{_options:{path:"/setting",redirect:"../settings"}},notfound:{_options:{path:"/*notfound"}}}) diff --git a/agent/uiserver/dist/assets/consul-ui/routes-debug-41d0902009004c6875ddb9882b4ee3f6.js b/agent/uiserver/dist/assets/consul-ui/routes-debug-32b2d92bece3d10b0336085468debd34.js similarity index 100% rename from agent/uiserver/dist/assets/consul-ui/routes-debug-41d0902009004c6875ddb9882b4ee3f6.js rename to agent/uiserver/dist/assets/consul-ui/routes-debug-32b2d92bece3d10b0336085468debd34.js diff --git a/agent/uiserver/dist/assets/consul-ui/services-faa0d1867ff0795f940a4199bcf17128.js b/agent/uiserver/dist/assets/consul-ui/services-1f3464a4359aae30f3d6b0616a7b8be5.js similarity index 100% rename from agent/uiserver/dist/assets/consul-ui/services-faa0d1867ff0795f940a4199bcf17128.js rename to agent/uiserver/dist/assets/consul-ui/services-1f3464a4359aae30f3d6b0616a7b8be5.js diff --git a/agent/uiserver/dist/assets/consul-ui/services-debug-d1862bae590c1c8cd6dc0dd81645801a.js b/agent/uiserver/dist/assets/consul-ui/services-debug-68ed09c2ecbaa3f9ae29106fe0349617.js similarity index 100% rename from agent/uiserver/dist/assets/consul-ui/services-debug-d1862bae590c1c8cd6dc0dd81645801a.js rename to agent/uiserver/dist/assets/consul-ui/services-debug-68ed09c2ecbaa3f9ae29106fe0349617.js diff --git a/agent/uiserver/dist/assets/init-b7460a439b88b483c51ff7f67c5a5a24.js b/agent/uiserver/dist/assets/init-b7460a439b88b483c51ff7f67c5a5a24.js new file mode 100644 index 000000000000..c8f6cd956953 --- /dev/null +++ b/agent/uiserver/dist/assets/init-b7460a439b88b483c51ff7f67c5a5a24.js @@ -0,0 +1,5 @@ +(function(e,t){const n=new Map(Object.entries(JSON.parse(e.querySelector(`[data-${t}-fs]`).textContent))),o=function(t){var n=e.createElement("script") +n.src=t,e.body.appendChild(n)} +"TextDecoder"in window||(o(n.get(`${["text-encoding","encoding-indexes"].join("/")}.js`)),o(n.get(`${["text-encoding","encoding"].join("/")}.js`))),window.CSS&&window.CSS.escape||o(n.get(`${["css.escape","css.escape"].join("/")}.js`)) +try{const n=e.querySelector(`[name="${t}/config/environment"]`),o=JSON.parse(e.querySelector(`[data-${t}-config]`).textContent),c=JSON.parse(decodeURIComponent(n.getAttribute("content"))),s="string"!=typeof o.ContentPath?"":o.ContentPath +s.length>0&&(c.rootURL=s),n.setAttribute("content",encodeURIComponent(JSON.stringify(c)))}catch(c){throw new Error(`Unable to parse ${t} settings: ${c.message}`)}})(document,"consul-ui") diff --git a/agent/uiserver/dist/assets/init-fe2561b45ce1429092f4a9a2bbb9ce71.js b/agent/uiserver/dist/assets/init-fe2561b45ce1429092f4a9a2bbb9ce71.js deleted file mode 100644 index 084a65b5555a..000000000000 --- a/agent/uiserver/dist/assets/init-fe2561b45ce1429092f4a9a2bbb9ce71.js +++ /dev/null @@ -1,5 +0,0 @@ -(function(e,t){const n=new Map(Object.entries(JSON.parse(e.querySelector("[data-consul-ui-fs]").textContent))),o=function(t){var n=e.createElement("script") -n.src=t,e.body.appendChild(n)} -"TextDecoder"in window||(o(n.get(`${["text-encoding","encoding-indexes"].join("/")}.js`)),o(n.get(`${["text-encoding","encoding"].join("/")}.js`))),window.CSS&&window.CSS.escape||o(n.get(`${["css.escape","css.escape"].join("/")}.js`)) -try{const t=e.querySelector('[name="consul-ui/config/environment"]'),n=JSON.parse(e.querySelector("[data-consul-ui-config]").textContent),o=JSON.parse(decodeURIComponent(t.getAttribute("content"))),c="string"!=typeof n.ContentPath?"":n.ContentPath -c.length>0&&(o.rootURL=c),t.setAttribute("content",encodeURIComponent(JSON.stringify(o)))}catch(c){throw new Error(`Unable to parse consul-ui settings: ${c.message}`)}})(document) diff --git a/agent/uiserver/dist/assets/metrics-providers/consul-5e97a9af114229497d43377450c54418.js b/agent/uiserver/dist/assets/metrics-providers/consul-01a9b050be20fe471510e862e86d5d73.js similarity index 100% rename from agent/uiserver/dist/assets/metrics-providers/consul-5e97a9af114229497d43377450c54418.js rename to agent/uiserver/dist/assets/metrics-providers/consul-01a9b050be20fe471510e862e86d5d73.js diff --git a/agent/uiserver/dist/assets/metrics-providers/prometheus-8779f1c99f6a15611567154767f1f674.js b/agent/uiserver/dist/assets/metrics-providers/prometheus-b790531c6c9836e44ba75fe16468fa27.js similarity index 100% rename from agent/uiserver/dist/assets/metrics-providers/prometheus-8779f1c99f6a15611567154767f1f674.js rename to agent/uiserver/dist/assets/metrics-providers/prometheus-b790531c6c9836e44ba75fe16468fa27.js diff --git a/agent/uiserver/dist/assets/vendor-892a8787e7c054f43bebe02b1e5bc878.js b/agent/uiserver/dist/assets/vendor-892a8787e7c054f43bebe02b1e5bc878.js new file mode 100644 index 000000000000..a946838e47e4 --- /dev/null +++ b/agent/uiserver/dist/assets/vendor-892a8787e7c054f43bebe02b1e5bc878.js @@ -0,0 +1,11970 @@ +window.EmberENV=function(e,t){for(var r in t)e[r]=t[r] +return e}(window.EmberENV||{},{FEATURES:{},EXTEND_PROTOTYPES:{Date:!1},_APPLICATION_TEMPLATE_WRAPPER:!1,_DEFAULT_ASYNC_OBSERVERS:!0,_JQUERY_INTEGRATION:!1,_TEMPLATE_ONLY_GLIMMER_COMPONENTS:!0}) +var loader,define,requireModule,require,requirejs,runningTests=!1;(function(e){"use strict" +function t(){var e=Object.create(null) +return e.__=void 0,delete e.__,e}var r={loader:loader,define:define,requireModule:requireModule,require:require,requirejs:requirejs} +requirejs=require=requireModule=function(e){for(var t=[],r=u(e,"(require)",t),n=t.length-1;n>=0;n--)t[n].exports() +return r.module.exports},loader={noConflict:function(t){var n,i +for(n in t)t.hasOwnProperty(n)&&r.hasOwnProperty(n)&&(i=t[n],e[i]=e[n],e[n]=r[n])},makeDefaultExport:!0} +var n=t(),i=(t(),0) +var o=["require","exports","module"] +function s(e,t,r,n){this.uuid=i++,this.id=e,this.deps=!t.length&&r.length?o:t,this.module={exports:{}},this.callback=r,this.hasExportsAsDep=!1,this.isAlias=n,this.reified=new Array(t.length),this.state="new"}function a(){}function l(e){this.id=e}function u(e,t,r){for(var i=n[e]||n[e+"/index"];i&&i.isAlias;)i=n[i.id]||n[i.id+"/index"] +return i||function(e,t){throw new Error("Could not find module `"+e+"` imported from `"+t+"`")}(e,t),r&&"pending"!==i.state&&"finalized"!==i.state&&(i.findDeps(r),r.push(i)),i}function c(e,t){if("."!==e.charAt(0))return e +for(var r=e.split("/"),n=t.split("/").slice(0,-1),i=0,o=r.length;i2?arguments[2]:void 0,c=Math.min((void 0===u?s:i(u,s))-l,s-a),d=1 +for(l0;)l in r?r[a]=r[l]:delete r[a],a+=d,l+=d +return r}},{135:135,139:139,140:140}],38:[function(e,t,r){"use strict" +var n=e(140),i=e(135),o=e(139) +t.exports=function(e){for(var t=n(this),r=o(t.length),s=arguments.length,a=i(s>1?arguments[1]:void 0,r),l=s>2?arguments[2]:void 0,u=void 0===l?r:i(l,r);u>a;)t[a++]=e +return t}},{135:135,139:139,140:140}],39:[function(e,t,r){var n=e(138),i=e(139),o=e(135) +t.exports=function(e){return function(t,r,s){var a,l=n(t),u=i(l.length),c=o(s,u) +if(e&&r!=r){for(;u>c;)if((a=l[c++])!=a)return!0}else for(;u>c;c++)if((e||c in l)&&l[c]===r)return e||c||0 +return!e&&-1}}},{135:135,138:138,139:139}],40:[function(e,t,r){var n=e(52),i=e(75),o=e(140),s=e(139),a=e(43) +t.exports=function(e,t){var r=1==e,l=2==e,u=3==e,c=4==e,d=6==e,h=5==e||d,p=t||a +return function(t,a,f){for(var m,g,v=o(t),b=i(v),y=n(a,f,3),_=s(b.length),w=0,O=r?p(t,_):l?p(t,0):void 0;_>w;w++)if((h||w in b)&&(g=y(m=b[w],w,v),e))if(r)O[w]=g +else if(g)switch(e){case 3:return!0 +case 5:return m +case 6:return w +case 2:O.push(m)}else if(c)return!1 +return d?-1:u||c?c:O}}},{139:139,140:140,43:43,52:52,75:75}],41:[function(e,t,r){var n=e(31),i=e(140),o=e(75),s=e(139) +t.exports=function(e,t,r,a,l){n(t) +var u=i(e),c=o(u),d=s(u.length),h=l?d-1:0,p=l?-1:1 +if(r<2)for(;;){if(h in c){a=c[h],h+=p +break}if(h+=p,l?h<0:d<=h)throw TypeError("Reduce of empty array with no initial value")}for(;l?h>=0:d>h;h+=p)h in c&&(a=t(a,c[h],h,u)) +return a}},{139:139,140:140,31:31,75:75}],42:[function(e,t,r){var n=e(79),i=e(77),o=e(150)("species") +t.exports=function(e){var t +return i(e)&&("function"!=typeof(t=e.constructor)||t!==Array&&!i(t.prototype)||(t=void 0),n(t)&&null===(t=t[o])&&(t=void 0)),void 0===t?Array:t}},{150:150,77:77,79:79}],43:[function(e,t,r){var n=e(42) +t.exports=function(e,t){return new(n(e))(t)}},{42:42}],44:[function(e,t,r){"use strict" +var n=e(31),i=e(79),o=e(74),s=[].slice,a={} +t.exports=Function.bind||function(e){var t=n(this),r=s.call(arguments,1),l=function(){var n=r.concat(s.call(arguments)) +return this instanceof l?function(e,t,r){if(!(t in a)){for(var n=[],i=0;i1?arguments[1]:void 0,3);r=r?r.n:this._f;)for(n(r.v,r.k,this);r&&r.r;)r=r.p},has:function(e){return!!g(f(this,t),e)}}),h&&n(c.prototype,"size",{get:function(){return f(this,t)[m]}}),c},def:function(e,t,r){var n,i,o=g(e,t) +return o?o.v=r:(e._l=o={i:i=p(t,!0),k:t,v:r,p:n=e._l,n:void 0,r:!1},e._f||(e._f=o),n&&(n.n=o),e[m]++,"F"!==i&&(e._i[i]=o)),e},getEntry:g,setStrong:function(e,t,r){u(e,t,(function(e,r){this._t=f(e,t),this._k=r,this._l=void 0}),(function(){for(var e=this,t=e._k,r=e._l;r&&r.r;)r=r.p +return e._t&&(e._l=r=r?r.n:e._t._f)?c(0,"keys"==t?r.k:"values"==t?r.v:[r.k,r.v]):(e._t=void 0,c(1))}),r?"entries":"values",!r,!0),d(t)}}},{115:115,121:121,147:147,35:35,52:52,56:56,66:66,83:83,85:85,92:92,96:96,97:97}],48:[function(e,t,r){"use strict" +var n=e(115),i=e(92).getWeak,o=e(36),s=e(79),a=e(35),l=e(66),u=e(40),c=e(69),d=e(147),h=u(5),p=u(6),f=0,m=function(e){return e._l||(e._l=new g)},g=function(){this.a=[]},v=function(e,t){return h(e.a,(function(e){return e[0]===t}))} +g.prototype={get:function(e){var t=v(this,e) +if(t)return t[1]},has:function(e){return!!v(this,e)},set:function(e,t){var r=v(this,e) +r?r[1]=t:this.a.push([e,t])},delete:function(e){var t=p(this.a,(function(t){return t[0]===e})) +return~t&&this.a.splice(t,1),!!~t}},t.exports={getConstructor:function(e,t,r,o){var u=e((function(e,n){a(e,u,t,"_i"),e._t=t,e._i=f++,e._l=void 0,null!=n&&l(n,r,e[o],e)})) +return n(u.prototype,{delete:function(e){if(!s(e))return!1 +var r=i(e) +return!0===r?m(d(this,t)).delete(e):r&&c(r,this._i)&&delete r[this._i]},has:function(e){if(!s(e))return!1 +var r=i(e) +return!0===r?m(d(this,t)).has(e):r&&c(r,this._i)}}),u},def:function(e,t,r){var n=i(o(t),!0) +return!0===n?m(e).set(t,r):n[e._i]=r,e},ufstore:m}},{115:115,147:147,35:35,36:36,40:40,66:66,69:69,79:79,92:92}],49:[function(e,t,r){"use strict" +var n=e(68),i=e(60),o=e(116),s=e(115),a=e(92),l=e(66),u=e(35),c=e(79),d=e(62),h=e(84),p=e(122),f=e(73) +t.exports=function(e,t,r,m,g,v){var b=n[e],y=b,_=g?"set":"add",w=y&&y.prototype,O={},x=function(e){var t=w[e] +o(w,e,"delete"==e||"has"==e?function(e){return!(v&&!c(e))&&t.call(this,0===e?0:e)}:"get"==e?function(e){return v&&!c(e)?void 0:t.call(this,0===e?0:e)}:"add"==e?function(e){return t.call(this,0===e?0:e),this}:function(e,r){return t.call(this,0===e?0:e,r),this})} +if("function"==typeof y&&(v||w.forEach&&!d((function(){(new y).entries().next()})))){var S=new y,T=S[_](v?{}:-0,1)!=S,P=d((function(){S.has(1)})),k=h((function(e){new y(e)})),E=!v&&d((function(){for(var e=new y,t=5;t--;)e[_](t,t) +return!e.has(-0)})) +k||((y=t((function(t,r){u(t,y,e) +var n=f(new b,t,y) +return null!=r&&l(r,g,n[_],n),n}))).prototype=w,w.constructor=y),(P||E)&&(x("delete"),x("has"),g&&x("get")),(E||T)&&x(_),v&&w.clear&&delete w.clear}else y=m.getConstructor(t,e,g,_),s(y.prototype,r),a.NEED=!0 +return p(y,e),O[e]=y,i(i.G+i.W+i.F*(y!=b),O),v||m.setStrong(y,e,g),y}},{115:115,116:116,122:122,35:35,60:60,62:62,66:66,68:68,73:73,79:79,84:84,92:92}],50:[function(e,t,r){arguments[4][16][0].apply(r,arguments)},{16:16}],51:[function(e,t,r){"use strict" +var n=e(97),i=e(114) +t.exports=function(e,t,r){t in e?n.f(e,t,i(0,r)):e[t]=r}},{114:114,97:97}],52:[function(e,t,r){arguments[4][17][0].apply(r,arguments)},{17:17,31:31}],53:[function(e,t,r){"use strict" +var n=e(62),i=Date.prototype.getTime,o=Date.prototype.toISOString,s=function(e){return e>9?e:"0"+e} +t.exports=n((function(){return"0385-07-25T07:06:39.999Z"!=o.call(new Date(-50000000000001))}))||!n((function(){o.call(new Date(NaN))}))?function(){if(!isFinite(i.call(this)))throw RangeError("Invalid time value") +var e=this,t=e.getUTCFullYear(),r=e.getUTCMilliseconds(),n=t<0?"-":t>9999?"+":"" +return n+("00000"+Math.abs(t)).slice(n?-6:-4)+"-"+s(e.getUTCMonth()+1)+"-"+s(e.getUTCDate())+"T"+s(e.getUTCHours())+":"+s(e.getUTCMinutes())+":"+s(e.getUTCSeconds())+"."+(r>99?r:"0"+s(r))+"Z"}:o},{62:62}],54:[function(e,t,r){"use strict" +var n=e(36),i=e(141),o="number" +t.exports=function(e){if("string"!==e&&e!==o&&"default"!==e)throw TypeError("Incorrect hint") +return i(n(this),e!=o)}},{141:141,36:36}],55:[function(e,t,r){t.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e) +return e}},{}],56:[function(e,t,r){arguments[4][18][0].apply(r,arguments)},{18:18,62:62}],57:[function(e,t,r){arguments[4][19][0].apply(r,arguments)},{19:19,68:68,79:79}],58:[function(e,t,r){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},{}],59:[function(e,t,r){var n=e(105),i=e(102),o=e(106) +t.exports=function(e){var t=n(e),r=i.f +if(r)for(var s,a=r(e),l=o.f,u=0;a.length>u;)l.call(e,s=a[u++])&&t.push(s) +return t}},{102:102,105:105,106:106}],60:[function(e,t,r){var n=e(68),i=e(50),o=e(70),s=e(116),a=e(52),l="prototype",u=function(e,t,r){var c,d,h,p,f=e&u.F,m=e&u.G,g=e&u.S,v=e&u.P,b=e&u.B,y=m?n:g?n[t]||(n[t]={}):(n[t]||{})[l],_=m?i:i[t]||(i[t]={}),w=_[l]||(_[l]={}) +for(c in m&&(r=t),r)h=((d=!f&&y&&void 0!==y[c])?y:r)[c],p=b&&d?a(h,n):v&&"function"==typeof h?a(Function.call,h):h,y&&s(y,c,h,e&u.U),_[c]!=h&&o(_,c,p),v&&w[c]!=h&&(w[c]=h)} +n.core=i,u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,u.U=64,u.R=128,t.exports=u},{116:116,50:50,52:52,68:68,70:70}],61:[function(e,t,r){var n=e(150)("match") +t.exports=function(e){var t=/./ +try{"/./"[e](t)}catch(r){try{return t[n]=!1,!"/./"[e](t)}catch(i){}}return!0}},{150:150}],62:[function(e,t,r){arguments[4][21][0].apply(r,arguments)},{21:21}],63:[function(e,t,r){"use strict" +e(246) +var n=e(116),i=e(70),o=e(62),s=e(55),a=e(150),l=e(118),u=a("species"),c=!o((function(){var e=/./ +return e.exec=function(){var e=[] +return e.groups={a:"7"},e},"7"!=="".replace(e,"$")})),d=function(){var e=/(?:)/,t=e.exec +e.exec=function(){return t.apply(this,arguments)} +var r="ab".split(e) +return 2===r.length&&"a"===r[0]&&"b"===r[1]}() +t.exports=function(e,t,r){var h=a(e),p=!o((function(){var t={} +return t[h]=function(){return 7},7!=""[e](t)})),f=p?!o((function(){var t=!1,r=/a/ +return r.exec=function(){return t=!0,null},"split"===e&&(r.constructor={},r.constructor[u]=function(){return r}),r[h](""),!t})):void 0 +if(!p||!f||"replace"===e&&!c||"split"===e&&!d){var m=/./[h],g=r(s,h,""[e],(function(e,t,r,n,i){return t.exec===l?p&&!i?{done:!0,value:m.call(t,r,n)}:{done:!0,value:e.call(r,t,n)}:{done:!1}})),v=g[0],b=g[1] +n(String.prototype,e,v),i(RegExp.prototype,h,2==t?function(e,t){return b.call(e,this,t)}:function(e){return b.call(e,this)})}}},{116:116,118:118,150:150,246:246,55:55,62:62,70:70}],64:[function(e,t,r){"use strict" +var n=e(36) +t.exports=function(){var e=n(this),t="" +return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),e.unicode&&(t+="u"),e.sticky&&(t+="y"),t}},{36:36}],65:[function(e,t,r){"use strict" +var n=e(77),i=e(79),o=e(139),s=e(52),a=e(150)("isConcatSpreadable") +t.exports=function e(t,r,l,u,c,d,h,p){for(var f,m,g=c,v=0,b=!!h&&s(h,p,3);v0)g=e(t,r,f,o(f.length),g,d-1)-1 +else{if(g>=9007199254740991)throw TypeError() +t[g]=f}g++}v++}return g}},{139:139,150:150,52:52,77:77,79:79}],66:[function(e,t,r){var n=e(52),i=e(81),o=e(76),s=e(36),a=e(139),l=e(151),u={},c={};(r=t.exports=function(e,t,r,d,h){var p,f,m,g,v=h?function(){return e}:l(e),b=n(r,d,t?2:1),y=0 +if("function"!=typeof v)throw TypeError(e+" is not iterable!") +if(o(v)){for(p=a(e.length);p>y;y++)if((g=t?b(s(f=e[y])[0],f[1]):b(e[y]))===u||g===c)return g}else for(m=v.call(e);!(f=m.next()).done;)if((g=i(m,b,f.value,t))===u||g===c)return g}).BREAK=u,r.RETURN=c},{139:139,151:151,36:36,52:52,76:76,81:81}],67:[function(e,t,r){t.exports=e(124)("native-function-to-string",Function.toString)},{124:124}],68:[function(e,t,r){arguments[4][22][0].apply(r,arguments)},{22:22}],69:[function(e,t,r){arguments[4][23][0].apply(r,arguments)},{23:23}],70:[function(e,t,r){arguments[4][24][0].apply(r,arguments)},{114:114,24:24,56:56,97:97}],71:[function(e,t,r){var n=e(68).document +t.exports=n&&n.documentElement},{68:68}],72:[function(e,t,r){arguments[4][25][0].apply(r,arguments)},{25:25,56:56,57:57,62:62}],73:[function(e,t,r){var n=e(79),i=e(120).set +t.exports=function(e,t,r){var o,s=t.constructor +return s!==r&&"function"==typeof s&&(o=s.prototype)!==r.prototype&&n(o)&&i&&i(e,o),e}},{120:120,79:79}],74:[function(e,t,r){t.exports=function(e,t,r){var n=void 0===r +switch(t.length){case 0:return n?e():e.call(r) +case 1:return n?e(t[0]):e.call(r,t[0]) +case 2:return n?e(t[0],t[1]):e.call(r,t[0],t[1]) +case 3:return n?e(t[0],t[1],t[2]):e.call(r,t[0],t[1],t[2]) +case 4:return n?e(t[0],t[1],t[2],t[3]):e.call(r,t[0],t[1],t[2],t[3])}return e.apply(r,t)}},{}],75:[function(e,t,r){var n=e(46) +t.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==n(e)?e.split(""):Object(e)}},{46:46}],76:[function(e,t,r){var n=e(86),i=e(150)("iterator"),o=Array.prototype +t.exports=function(e){return void 0!==e&&(n.Array===e||o[i]===e)}},{150:150,86:86}],77:[function(e,t,r){var n=e(46) +t.exports=Array.isArray||function(e){return"Array"==n(e)}},{46:46}],78:[function(e,t,r){var n=e(79),i=Math.floor +t.exports=function(e){return!n(e)&&isFinite(e)&&i(e)===e}},{79:79}],79:[function(e,t,r){arguments[4][26][0].apply(r,arguments)},{26:26}],80:[function(e,t,r){var n=e(79),i=e(46),o=e(150)("match") +t.exports=function(e){var t +return n(e)&&(void 0!==(t=e[o])?!!t:"RegExp"==i(e))}},{150:150,46:46,79:79}],81:[function(e,t,r){var n=e(36) +t.exports=function(e,t,r,i){try{return i?t(n(r)[0],r[1]):t(r)}catch(s){var o=e.return +throw void 0!==o&&n(o.call(e)),s}}},{36:36}],82:[function(e,t,r){"use strict" +var n=e(96),i=e(114),o=e(122),s={} +e(70)(s,e(150)("iterator"),(function(){return this})),t.exports=function(e,t,r){e.prototype=n(s,{next:i(1,r)}),o(e,t+" Iterator")}},{114:114,122:122,150:150,70:70,96:96}],83:[function(e,t,r){"use strict" +var n=e(87),i=e(60),o=e(116),s=e(70),a=e(86),l=e(82),u=e(122),c=e(103),d=e(150)("iterator"),h=!([].keys&&"next"in[].keys()),p="keys",f="values",m=function(){return this} +t.exports=function(e,t,r,g,v,b,y){l(r,t,g) +var _,w,O,x=function(e){if(!h&&e in k)return k[e] +switch(e){case p:case f:return function(){return new r(this,e)}}return function(){return new r(this,e)}},S=t+" Iterator",T=v==f,P=!1,k=e.prototype,E=k[d]||k["@@iterator"]||v&&k[v],C=E||x(v),M=v?T?x("entries"):C:void 0,j="Array"==t&&k.entries||E +if(j&&(O=c(j.call(new e)))!==Object.prototype&&O.next&&(u(O,S,!0),n||"function"==typeof O[d]||s(O,d,m)),T&&E&&E.name!==f&&(P=!0,C=function(){return E.call(this)}),n&&!y||!h&&!P&&k[d]||s(k,d,C),a[t]=C,a[S]=m,v)if(_={values:T?C:x(f),keys:b?C:x(p),entries:M},y)for(w in _)w in k||o(k,w,_[w]) +else i(i.P+i.F*(h||P),t,_) +return _}},{103:103,116:116,122:122,150:150,60:60,70:70,82:82,86:86,87:87}],84:[function(e,t,r){var n=e(150)("iterator"),i=!1 +try{var o=[7][n]() +o.return=function(){i=!0},Array.from(o,(function(){throw 2}))}catch(s){}t.exports=function(e,t){if(!t&&!i)return!1 +var r=!1 +try{var o=[7],a=o[n]() +a.next=function(){return{done:r=!0}},o[n]=function(){return a},e(o)}catch(s){}return r}},{150:150}],85:[function(e,t,r){t.exports=function(e,t){return{value:t,done:!!e}}},{}],86:[function(e,t,r){t.exports={}},{}],87:[function(e,t,r){t.exports=!1},{}],88:[function(e,t,r){var n=Math.expm1 +t.exports=!n||n(10)>22025.465794806718||n(10)<22025.465794806718||-2e-17!=n(-2e-17)?function(e){return 0==(e=+e)?e:e>-1e-6&&e<1e-6?e+e*e/2:Math.exp(e)-1}:n},{}],89:[function(e,t,r){var n=e(91),i=Math.pow,o=i(2,-52),s=i(2,-23),a=i(2,127)*(2-s),l=i(2,-126) +t.exports=Math.fround||function(e){var t,r,i=Math.abs(e),u=n(e) +return ia||r!=r?u*(1/0):u*r}},{91:91}],90:[function(e,t,r){t.exports=Math.log1p||function(e){return(e=+e)>-1e-8&&e<1e-8?e-e*e/2:Math.log(1+e)}},{}],91:[function(e,t,r){t.exports=Math.sign||function(e){return 0==(e=+e)||e!=e?e:e<0?-1:1}},{}],92:[function(e,t,r){var n=e(145)("meta"),i=e(79),o=e(69),s=e(97).f,a=0,l=Object.isExtensible||function(){return!0},u=!e(62)((function(){return l(Object.preventExtensions({}))})),c=function(e){s(e,n,{value:{i:"O"+ ++a,w:{}}})},d=t.exports={KEY:n,NEED:!1,fastKey:function(e,t){if(!i(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e +if(!o(e,n)){if(!l(e))return"F" +if(!t)return"E" +c(e)}return e[n].i},getWeak:function(e,t){if(!o(e,n)){if(!l(e))return!0 +if(!t)return!1 +c(e)}return e[n].w},onFreeze:function(e){return u&&d.NEED&&l(e)&&!o(e,n)&&c(e),e}}},{145:145,62:62,69:69,79:79,97:97}],93:[function(e,t,r){var n=e(68),i=e(134).set,o=n.MutationObserver||n.WebKitMutationObserver,s=n.process,a=n.Promise,l="process"==e(46)(s) +t.exports=function(){var e,t,r,u=function(){var n,i +for(l&&(n=s.domain)&&n.exit();e;){i=e.fn,e=e.next +try{i()}catch(o){throw e?r():t=void 0,o}}t=void 0,n&&n.enter()} +if(l)r=function(){s.nextTick(u)} +else if(!o||n.navigator&&n.navigator.standalone)if(a&&a.resolve){var c=a.resolve(void 0) +r=function(){c.then(u)}}else r=function(){i.call(n,u)} +else{var d=!0,h=document.createTextNode("") +new o(u).observe(h,{characterData:!0}),r=function(){h.data=d=!d}}return function(n){var i={fn:n,next:void 0} +t&&(t.next=i),e||(e=i,r()),t=i}}},{134:134,46:46,68:68}],94:[function(e,t,r){"use strict" +var n=e(31) +function i(e){var t,r +this.promise=new e((function(e,n){if(void 0!==t||void 0!==r)throw TypeError("Bad Promise constructor") +t=e,r=n})),this.resolve=n(t),this.reject=n(r)}t.exports.f=function(e){return new i(e)}},{31:31}],95:[function(e,t,r){"use strict" +var n=e(56),i=e(105),o=e(102),s=e(106),a=e(140),l=e(75),u=Object.assign +t.exports=!u||e(62)((function(){var e={},t={},r=Symbol(),n="abcdefghijklmnopqrst" +return e[r]=7,n.split("").forEach((function(e){t[e]=e})),7!=u({},e)[r]||Object.keys(u({},t)).join("")!=n}))?function(e,t){for(var r=a(e),u=arguments.length,c=1,d=o.f,h=s.f;u>c;)for(var p,f=l(arguments[c++]),m=d?i(f).concat(d(f)):i(f),g=m.length,v=0;g>v;)p=m[v++],n&&!h.call(f,p)||(r[p]=f[p]) +return r}:u},{102:102,105:105,106:106,140:140,56:56,62:62,75:75}],96:[function(e,t,r){var n=e(36),i=e(98),o=e(58),s=e(123)("IE_PROTO"),a=function(){},l="prototype",u=function(){var t,r=e(57)("iframe"),n=o.length +for(r.style.display="none",e(71).appendChild(r),r.src="javascript:",(t=r.contentWindow.document).open(),t.write(" - - - + + + {{if .ACLsEnabled}} - + {{end}} {{if .PeeringEnabled}} - - + + {{end}} {{if .PartitionsEnabled}} - - + + {{end}} {{if .NamespacesEnabled}} - -{{end}} -{{if .HCPEnabled}} - - + {{end}} - - - - + + + + - - + + {{ range .ExtraScripts }} {{ end }} - + - +
      diff --git a/agent/uiserver/uiserver_test.go b/agent/uiserver/uiserver_test.go index ce649276546b..c1e21ce745be 100644 --- a/agent/uiserver/uiserver_test.go +++ b/agent/uiserver/uiserver_test.go @@ -13,10 +13,11 @@ import ( "strings" "testing" - "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/require" "golang.org/x/net/html" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/consul/agent/config" "github.com/hashicorp/consul/sdk/testutil" ) diff --git a/agent/xds/accesslogs/accesslogs.go b/agent/xds/accesslogs/accesslogs.go index a5aac415832f..bb166097d8a7 100644 --- a/agent/xds/accesslogs/accesslogs.go +++ b/agent/xds/accesslogs/accesslogs.go @@ -1,4 +1,4 @@ -// Copyright (c) HashiCorp, Inc. +// Copyrigh (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package accesslogs @@ -10,7 +10,6 @@ import ( envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_fileaccesslog_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/file/v3" envoy_streamaccesslog_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/stream/v3" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/structpb" @@ -53,12 +52,12 @@ const ( // on the proxy-defaults settings. Currently only one access logger is supported. // Listeners (as opposed to listener filters) can trigger an access log filter with the boolean. // Tests are located in agent/xds/listeners_test.go. -func MakeAccessLogs(logs structs.AccessLogs, isListener bool) ([]*envoy_accesslog_v3.AccessLog, error) { - if logs == nil || !logs.GetEnabled() { +func MakeAccessLogs(logs *structs.AccessLogsConfig, isListener bool) ([]*envoy_accesslog_v3.AccessLog, error) { + if logs == nil || !logs.Enabled { return nil, nil } - if isListener && logs.GetDisableListenerLogs() { + if isListener && logs.DisableListenerLogs { return nil, nil } @@ -86,37 +85,36 @@ func MakeAccessLogs(logs structs.AccessLogs, isListener bool) ([]*envoy_accesslo } // getLogger returns an individual instance of an Envoy logger based on proxy-defaults -func getLogger(logs structs.AccessLogs) (*anypb.Any, error) { +func getLogger(logs *structs.AccessLogsConfig) (*anypb.Any, error) { logFormat, err := getLogFormat(logs) if err != nil { return nil, fmt.Errorf("could not get envoy log format: %w", err) } - switch logs.GetType() { - case pbmesh.LogSinkType_LOG_SINK_TYPE_DEFAULT, pbmesh.LogSinkType_LOG_SINK_TYPE_STDOUT: + switch logs.Type { + case structs.DefaultLogSinkType, structs.StdOutLogSinkType: return getStdoutLogger(logFormat) - case pbmesh.LogSinkType_LOG_SINK_TYPE_STDERR: + case structs.StdErrLogSinkType: return getStderrLogger(logFormat) - case pbmesh.LogSinkType_LOG_SINK_TYPE_FILE: - return getFileLogger(logFormat, logs.GetPath()) + case structs.FileLogSinkType: + return getFileLogger(logFormat, logs.Path) default: - return nil, fmt.Errorf("unsupported log format: %s", logs.GetType()) + return nil, fmt.Errorf("unsupported log format: %s", logs.Type) } } // getLogFormat returns an Envoy log format object that is compatible with all log sinks. // If a format is not provided in the proxy-defaults, the default JSON format is used. -func getLogFormat(logs structs.AccessLogs) (*envoy_core_v3.SubstitutionFormatString, error) { - +func getLogFormat(logs *structs.AccessLogsConfig) (*envoy_core_v3.SubstitutionFormatString, error) { var format, formatType string - if logs.GetTextFormat() == "" && logs.GetJsonFormat() == "" { + if logs.TextFormat == "" && logs.JSONFormat == "" { format = defaultJSONFormat formatType = "json" - } else if logs.GetJsonFormat() != "" { - format = logs.GetJsonFormat() + } else if logs.JSONFormat != "" { + format = logs.JSONFormat formatType = "json" } else { - format = logs.GetTextFormat() + format = logs.TextFormat formatType = "text" } diff --git a/agent/xds/clusters.go b/agent/xds/clusters.go index b74fe371b28d..244585dfdf3e 100644 --- a/agent/xds/clusters.go +++ b/agent/xds/clusters.go @@ -93,7 +93,7 @@ func (s *ResourceGenerator) clustersFromSnapshotConnectProxy(cfgSnap *proxycfg.C clusters = append(clusters, appCluster) if cfgSnap.Proxy.Mode == structs.ProxyModeTransparent { - passthroughs, err := makePassthroughClusters(cfgSnap) + passthroughs, err := makePassthroughClusters(cfgSnap, cfgSnap.GetXDSCommonConfig(s.Logger)) if err != nil { return nil, fmt.Errorf("failed to make passthrough clusters for transparent proxy: %v", err) } @@ -148,7 +148,7 @@ func (s *ResourceGenerator) clustersFromSnapshotConnectProxy(cfgSnap *proxycfg.C // add clusters for jwt-providers for _, prov := range cfgSnap.JWTProviders { - //skip cluster creation for local providers + // skip cluster creation for local providers if prov.JSONWebKeySet == nil || prov.JSONWebKeySet.Remote == nil { continue } @@ -214,9 +214,12 @@ func makeJWTProviderCluster(p *structs.JWTProviderConfigEntry) (*envoy_cluster_v return nil, err } + discoveryType := makeJWKSDiscoveryClusterType(p.JSONWebKeySet.Remote) + lookupFamily := makeJWKSClusterDNSLookupFamilyType(discoveryType) cluster := &envoy_cluster_v3.Cluster{ Name: makeJWKSClusterName(p.Name), - ClusterDiscoveryType: makeJWKSDiscoveryClusterType(p.JSONWebKeySet.Remote), + ClusterDiscoveryType: discoveryType, + DnsLookupFamily: lookupFamily, LoadAssignment: &envoy_endpoint_v3.ClusterLoadAssignment{ ClusterName: makeJWKSClusterName(p.Name), Endpoints: []*envoy_endpoint_v3.LocalityLbEndpoints{ @@ -278,6 +281,23 @@ func makeJWKSDiscoveryClusterType(r *structs.RemoteJWKS) *envoy_cluster_v3.Clust return ct } +func makeJWKSClusterDNSLookupFamilyType(r *envoy_cluster_v3.Cluster_Type) envoy_cluster_v3.Cluster_DnsLookupFamily { + // When using LOGICAL_DNS we want to use the Cluster_ALL lookup family which will fetch all the ip addresses for a given hostname and then + // try to connect to each one and will create the cluster based on the first one that passes. + // When using STRICT_DNS we want to use the CLUSTER_V4_PREFERRED lookup family which will prefer + // creating clusters using ipv4 addresses if those are available. + // Otherwise we fallback to Cluser_AUTO which will use the default behavior, and will be ignored as per the documentation. + // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#envoy-v3-api-enum-config-cluster-v3-cluster-dnslookupfamily + switch r.Type { + case envoy_cluster_v3.Cluster_LOGICAL_DNS: + return envoy_cluster_v3.Cluster_ALL + case envoy_cluster_v3.Cluster_STRICT_DNS: + return envoy_cluster_v3.Cluster_V4_PREFERRED + default: + return envoy_cluster_v3.Cluster_AUTO + } +} + func makeJWTCertValidationContext(p *structs.JWKSCluster) *envoy_tls_v3.CertificateValidationContext { vc := &envoy_tls_v3.CertificateValidationContext{} if p == nil || p.TLSCertificates == nil { @@ -361,7 +381,7 @@ func makeExposeClusterName(destinationPort int) string { // All of these use Envoy's ORIGINAL_DST listener filter, which forwards to the original // destination address (before the iptables redirection). // The rest are for destinations inside the mesh, which require certificates for mTLS. -func makePassthroughClusters(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) { +func makePassthroughClusters(cfgSnap *proxycfg.ConfigSnapshot, xdsCfg *config.XDSCommonConfig) ([]proto.Message, error) { // This size is an upper bound. clusters := make([]proto.Message, 0, len(cfgSnap.ConnectProxy.PassthroughUpstreams)+1) @@ -438,7 +458,8 @@ func makePassthroughClusters(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_EDS}, EdsClusterConfig: &envoy_cluster_v3.Cluster_EdsClusterConfig{ EdsConfig: &envoy_core_v3.ConfigSource{ - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, + InitialFetchTimeout: xdsCfg.GetXDSFetchTimeout(), + ResourceApiVersion: envoy_core_v3.ApiVersion_V3, ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_Ads{ Ads: &envoy_core_v3.AggregatedConfigSource{}, }, @@ -480,7 +501,7 @@ func makeMTLSTransportSocket(cfgSnap *proxycfg.ConfigSnapshot, uid proxycfg.Upst cfgSnap.RootPEMs(), makeTLSParametersFromProxyTLSConfig(cfgSnap.MeshConfigTLSOutgoing()), ) - err := injectSANMatcher(commonTLSContext, spiffeID.URI().String()) + err := injectSANMatcher(commonTLSContext, false, spiffeID.URI().String()) if err != nil { return nil, fmt.Errorf("failed to inject SAN matcher rules for cluster %q: %v", sni, err) } @@ -531,6 +552,7 @@ func (s *ResourceGenerator) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.Co name: connect.GatewaySNI(key.Datacenter, key.Partition, cfgSnap.Roots.TrustDomain), hostnameEndpoints: cfgSnap.MeshGateway.HostnameDatacenters[key.String()], isRemote: true, + limits: cfgSnap.MeshGateway.Limits, } cluster := s.makeGatewayCluster(cfgSnap, opts) clusters = append(clusters, cluster) @@ -553,6 +575,7 @@ func (s *ResourceGenerator) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.Co name: cfgSnap.ServerSNIFn(key.Datacenter, ""), hostnameEndpoints: hostnameEndpoints, isRemote: !key.Matches(cfgSnap.Datacenter, cfgSnap.ProxyID.PartitionOrDefault()), + limits: cfgSnap.MeshGateway.Limits, } cluster := s.makeGatewayCluster(cfgSnap, opts) clusters = append(clusters, cluster) @@ -562,7 +585,8 @@ func (s *ResourceGenerator) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.Co servers, _ := cfgSnap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName) for _, srv := range servers { opts := clusterOpts{ - name: cfgSnap.ServerSNIFn(cfgSnap.Datacenter, srv.Node.Node), + name: cfgSnap.ServerSNIFn(cfgSnap.Datacenter, srv.Node.Node), + limits: cfgSnap.MeshGateway.Limits, } cluster := s.makeGatewayCluster(cfgSnap, opts) clusters = append(clusters, cluster) @@ -578,14 +602,15 @@ func (s *ResourceGenerator) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.Co // We avoid routing to read replicas since they will never be Raft voters. if haveVoters(servers) { cluster := s.makeGatewayCluster(cfgSnap, clusterOpts{ - name: connect.PeeringServerSAN(cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain), + name: connect.PeeringServerSAN(cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain), + limits: cfgSnap.MeshGateway.Limits, }) clusters = append(clusters, cluster) } } // generate the per-service/subset clusters - c, err := s.makeGatewayServiceClusters(cfgSnap, cfgSnap.MeshGateway.ServiceGroups, cfgSnap.MeshGateway.ServiceResolvers) + c, err := s.makeGatewayServiceClusters(cfgSnap, cfgSnap.MeshGateway.ServiceGroups, cfgSnap.MeshGateway.ServiceResolvers, cfgSnap.MeshGateway.Limits) if err != nil { return nil, err } @@ -663,7 +688,7 @@ func (s *ResourceGenerator) makePeerServerClusters(cfgSnap *proxycfg.ConfigSnaps // for a terminating gateway. This will include 1 cluster per Destination associated with this terminating gateway. func (s *ResourceGenerator) clustersFromSnapshotTerminatingGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) { res := []proto.Message{} - gwClusters, err := s.makeGatewayServiceClusters(cfgSnap, cfgSnap.TerminatingGateway.ServiceGroups, cfgSnap.TerminatingGateway.ServiceResolvers) + gwClusters, err := s.makeGatewayServiceClusters(cfgSnap, cfgSnap.TerminatingGateway.ServiceGroups, cfgSnap.TerminatingGateway.ServiceResolvers, nil) if err != nil { return nil, err } @@ -682,6 +707,7 @@ func (s *ResourceGenerator) makeGatewayServiceClusters( cfgSnap *proxycfg.ConfigSnapshot, services map[structs.ServiceName]structs.CheckServiceNodes, resolvers map[structs.ServiceName]*structs.ServiceResolverConfigEntry, + limits *structs.UpstreamLimits, ) ([]proto.Message, error) { var hostnameEndpoints structs.CheckServiceNodes @@ -723,6 +749,7 @@ func (s *ResourceGenerator) makeGatewayServiceClusters( hostnameEndpoints: hostnameEndpoints, connectTimeout: resolver.ConnectTimeout, isRemote: isRemote, + limits: limits, } cluster := s.makeGatewayCluster(cfgSnap, opts) @@ -762,6 +789,7 @@ func (s *ResourceGenerator) makeGatewayServiceClusters( onlyPassing: subset.OnlyPassing, connectTimeout: resolver.ConnectTimeout, isRemote: isRemote, + limits: limits, } cluster := s.makeGatewayCluster(cfgSnap, opts) @@ -811,6 +839,7 @@ func (s *ResourceGenerator) makeGatewayOutgoingClusterPeeringServiceClusters(cfg name: clusterName, isRemote: true, hostnameEndpoints: hostnameEndpoints, + limits: cfgSnap.MeshGateway.Limits, } cluster := s.makeGatewayCluster(cfgSnap, opts) @@ -874,7 +903,7 @@ func (s *ResourceGenerator) injectGatewayServiceAddons(cfgSnap *proxycfg.ConfigS } if mapping.SNI != "" { tlsContext.Sni = mapping.SNI - if err := injectSANMatcher(tlsContext.CommonTlsContext, mapping.SNI); err != nil { + if err := injectSANMatcher(tlsContext.CommonTlsContext, true, mapping.SNI); err != nil { return fmt.Errorf("failed to inject SNI matcher into TLS context: %v", err) } } @@ -903,7 +932,7 @@ func (s *ResourceGenerator) injectGatewayDestinationAddons(cfgSnap *proxycfg.Con } if mapping.SNI != "" { tlsContext.Sni = mapping.SNI - if err := injectSANMatcher(tlsContext.CommonTlsContext, mapping.SNI); err != nil { + if err := injectSANMatcher(tlsContext.CommonTlsContext, true, mapping.SNI); err != nil { return fmt.Errorf("failed to inject SNI matcher into TLS context: %v", err) } } @@ -914,7 +943,6 @@ func (s *ResourceGenerator) injectGatewayDestinationAddons(cfgSnap *proxycfg.Con } c.TransportSocket = transportSocket } - } return nil } @@ -996,6 +1024,8 @@ func (s *ResourceGenerator) clustersFromSnapshotAPIGateway(cfgSnap *proxycfg.Con createdClusters[uid] = true } } + + clusters = append(clusters, makeAPIGatewayJWKClusters(s.Logger, cfgSnap)...) return clusters, nil } @@ -1056,13 +1086,7 @@ func (s *ResourceGenerator) makeAppCluster(cfgSnap *proxycfg.ConfigSnapshot, nam var c *envoy_cluster_v3.Cluster var err error - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - + cfg := cfgSnap.GetProxyConfig(s.Logger) // If we have overridden local cluster config try to parse it into an Envoy cluster if cfg.LocalClusterJSON != "" { return makeClusterFromUserConfig(cfg.LocalClusterJSON) @@ -1142,7 +1166,6 @@ func (s *ResourceGenerator) makeUpstreamClusterForPeerService( } upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil { return c, err } @@ -1199,7 +1222,8 @@ func (s *ResourceGenerator) makeUpstreamClusterForPeerService( c.ClusterDiscoveryType = &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_EDS} c.EdsClusterConfig = &envoy_cluster_v3.Cluster_EdsClusterConfig{ EdsConfig: &envoy_core_v3.ConfigSource{ - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, + InitialFetchTimeout: cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), + ResourceApiVersion: envoy_core_v3.ApiVersion_V3, ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_Ads{ Ads: &envoy_core_v3.AggregatedConfigSource{}, }, @@ -1230,7 +1254,7 @@ func (s *ResourceGenerator) makeUpstreamClusterForPeerService( rootPEMs, makeTLSParametersFromProxyTLSConfig(cfgSnap.MeshConfigTLSOutgoing()), ) - err = injectSANMatcher(commonTLSContext, peerMeta.SpiffeID...) + err = injectSANMatcher(commonTLSContext, false, peerMeta.SpiffeID...) if err != nil { return nil, fmt.Errorf("failed to inject SAN matcher rules for cluster %q: %v", clusterName, err) } @@ -1282,7 +1306,8 @@ func (s *ResourceGenerator) makeUpstreamClusterForPreparedQuery(upstream structs ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_EDS}, EdsClusterConfig: &envoy_cluster_v3.Cluster_EdsClusterConfig{ EdsConfig: &envoy_core_v3.ConfigSource{ - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, + InitialFetchTimeout: cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), + ResourceApiVersion: envoy_core_v3.ApiVersion_V3, ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_Ads{ Ads: &envoy_core_v3.AggregatedConfigSource{}, }, @@ -1332,7 +1357,7 @@ func (s *ResourceGenerator) makeUpstreamClusterForPreparedQuery(upstream structs cfgSnap.RootPEMs(), makeTLSParametersFromProxyTLSConfig(cfgSnap.MeshConfigTLSOutgoing()), ) - err = injectSANMatcher(commonTLSContext, spiffeIDs...) + err = injectSANMatcher(commonTLSContext, false, spiffeIDs...) if err != nil { return nil, fmt.Errorf("failed to inject SAN matcher rules for cluster %q: %v", sni, err) } @@ -1489,6 +1514,7 @@ func (s *ResourceGenerator) makeUpstreamClustersForDiscoveryChain( // Construct the target clusters. for _, groupedTarget := range targetGroups { s.Logger.Debug("generating cluster for", "cluster", groupedTarget.ClusterName) + c := &envoy_cluster_v3.Cluster{ Name: groupedTarget.ClusterName, AltStatName: groupedTarget.ClusterName, @@ -1501,7 +1527,8 @@ func (s *ResourceGenerator) makeUpstreamClustersForDiscoveryChain( }, EdsClusterConfig: &envoy_cluster_v3.Cluster_EdsClusterConfig{ EdsConfig: &envoy_core_v3.ConfigSource{ - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, + InitialFetchTimeout: cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), + ResourceApiVersion: envoy_core_v3.ApiVersion_V3, ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_Ads{ Ads: &envoy_core_v3.AggregatedConfigSource{}, }, @@ -1610,7 +1637,7 @@ func (s *ResourceGenerator) makeExportedUpstreamClustersForMeshGateway(cfgSnap * } // injectSANMatcher updates a TLS context so that it verifies the upstream SAN. -func injectSANMatcher(tlsContext *envoy_tls_v3.CommonTlsContext, matchStrings ...string) error { +func injectSANMatcher(tlsContext *envoy_tls_v3.CommonTlsContext, terminatingEgress bool, matchStrings ...string) error { if tlsContext == nil { return fmt.Errorf("invalid type: expected CommonTlsContext_ValidationContext not to be nil") } @@ -1621,17 +1648,40 @@ func injectSANMatcher(tlsContext *envoy_tls_v3.CommonTlsContext, matchStrings .. tlsContext.ValidationContextType) } - var matchers []*envoy_matcher_v3.StringMatcher + // All mesh services should match by URI + types := []envoy_tls_v3.SubjectAltNameMatcher_SanType{ + envoy_tls_v3.SubjectAltNameMatcher_URI, + } + if terminatingEgress { + // Terminating gateways will need to match on many fields depending on user configuration, + // since they make egress calls outside of the cluster. Having more than one matcher behaves + // like an OR operation, where any match is sufficient to pass the certificate validation. + // To maintain backwards compatibility with the old untyped `match_subject_alt_names` behavior, + // we should match on all 4 enum types. + // https://github.com/hashicorp/consul/issues/20360 + // https://github.com/envoyproxy/envoy/pull/18628/files#diff-cf088136dc052ddf1762fb3c96c0e8de472f3031f288e7e300558e6e72c8e129R69-R75 + types = []envoy_tls_v3.SubjectAltNameMatcher_SanType{ + envoy_tls_v3.SubjectAltNameMatcher_URI, + envoy_tls_v3.SubjectAltNameMatcher_DNS, + envoy_tls_v3.SubjectAltNameMatcher_EMAIL, + envoy_tls_v3.SubjectAltNameMatcher_IP_ADDRESS, + } + } + var matchers []*envoy_tls_v3.SubjectAltNameMatcher for _, m := range matchStrings { - matchers = append(matchers, &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{ - Exact: m, - }, - }) + for _, t := range types { + matchers = append(matchers, &envoy_tls_v3.SubjectAltNameMatcher{ + SanType: t, + Matcher: &envoy_matcher_v3.StringMatcher{ + MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{ + Exact: m, + }, + }, + }) + } } - //nolint:staticcheck - validationCtx.ValidationContext.MatchSubjectAltNames = matchers + validationCtx.ValidationContext.MatchTypedSubjectAltNames = matchers return nil } @@ -1684,16 +1734,13 @@ type clusterOpts struct { // Corresponds to a valid address/port pairs to be routed externally // these addresses will be embedded in the cluster configuration and will never use EDS addresses []structs.ServiceAddress + + limits *structs.UpstreamLimits } // makeGatewayCluster creates an Envoy cluster for a mesh or terminating gateway func (s *ResourceGenerator) makeGatewayCluster(snap *proxycfg.ConfigSnapshot, opts clusterOpts) *envoy_cluster_v3.Cluster { - cfg, err := config.ParseGatewayConfig(snap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse gateway config", "error", err) - } + cfg := snap.GetGatewayConfig(s.Logger) if opts.connectTimeout <= 0 { opts.connectTimeout = time.Duration(cfg.ConnectTimeoutMs) * time.Millisecond } @@ -1733,7 +1780,8 @@ func (s *ResourceGenerator) makeGatewayCluster(snap *proxycfg.ConfigSnapshot, op cluster.ClusterDiscoveryType = &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_EDS} cluster.EdsClusterConfig = &envoy_cluster_v3.Cluster_EdsClusterConfig{ EdsConfig: &envoy_core_v3.ConfigSource{ - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, + InitialFetchTimeout: snap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), + ResourceApiVersion: envoy_core_v3.ApiVersion_V3, ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_Ads{ Ads: &envoy_core_v3.AggregatedConfigSource{}, }, @@ -1750,6 +1798,12 @@ func (s *ResourceGenerator) makeGatewayCluster(snap *proxycfg.ConfigSnapshot, op ) } + if opts.limits != nil { + cluster.CircuitBreakers = &envoy_cluster_v3.CircuitBreakers{ + Thresholds: makeThresholdsIfNeeded(opts.limits), + } + } + return cluster } @@ -1770,13 +1824,15 @@ func configureClusterWithHostnames( cluster.DnsRefreshRate = durationpb.New(rate) cluster.DnsLookupFamily = envoy_cluster_v3.Cluster_V4_ONLY + envoyMaxEndpoints := 1 discoveryType := envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_LOGICAL_DNS} if dnsDiscoveryType == "strict_dns" { discoveryType.Type = envoy_cluster_v3.Cluster_STRICT_DNS + envoyMaxEndpoints = len(hostnameEndpoints) } cluster.ClusterDiscoveryType = &discoveryType - endpoints := make([]*envoy_endpoint_v3.LbEndpoint, 0, 1) + endpoints := make([]*envoy_endpoint_v3.LbEndpoint, 0, envoyMaxEndpoints) uniqueHostnames := make(map[string]bool) var ( @@ -1794,12 +1850,15 @@ func configureClusterWithHostnames( continue } - if len(endpoints) == 0 { + if len(endpoints) < envoyMaxEndpoints { endpoints = append(endpoints, makeLbEndpoint(addr, port, health, weight)) hostname = addr idx = i - break + + if len(endpoints) == envoyMaxEndpoints { + break + } } } @@ -1813,8 +1872,8 @@ func configureClusterWithHostnames( endpoints = append(endpoints, fallback) } - if len(uniqueHostnames) > 1 { - logger.Warn(fmt.Sprintf("service contains instances with more than one unique hostname; only %q be resolved by Envoy", hostname), + if len(uniqueHostnames) > 1 && envoyMaxEndpoints == 1 { + logger.Warn(fmt.Sprintf("service contains instances with more than one unique hostname; only %q will be resolved by Envoy", hostname), "dc", dc, "service", service.String()) } @@ -1831,12 +1890,7 @@ func configureClusterWithHostnames( // makeExternalIPCluster creates an Envoy cluster for routing to IP addresses outside of Consul // This is used by terminating gateways for Destinations func (s *ResourceGenerator) makeExternalIPCluster(snap *proxycfg.ConfigSnapshot, opts clusterOpts) *envoy_cluster_v3.Cluster { - cfg, err := config.ParseGatewayConfig(snap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse gateway config", "error", err) - } + cfg := snap.GetGatewayConfig(s.Logger) if opts.connectTimeout <= 0 { opts.connectTimeout = time.Duration(cfg.ConnectTimeoutMs) * time.Millisecond } @@ -1870,12 +1924,7 @@ func (s *ResourceGenerator) makeExternalIPCluster(snap *proxycfg.ConfigSnapshot, // makeExternalHostnameCluster creates an Envoy cluster for hostname endpoints that will be resolved with DNS // This is used by both terminating gateways for Destinations, and Mesh Gateways for peering control plane traffic func (s *ResourceGenerator) makeExternalHostnameCluster(snap *proxycfg.ConfigSnapshot, opts clusterOpts, discoveryType envoy_cluster_v3.Cluster_DiscoveryType) *envoy_cluster_v3.Cluster { - cfg, err := config.ParseGatewayConfig(snap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse gateway config", "error", err) - } + cfg := snap.GetGatewayConfig(s.Logger) opts.connectTimeout = time.Duration(cfg.ConnectTimeoutMs) * time.Millisecond cluster := &envoy_cluster_v3.Cluster{ diff --git a/agent/xds/clusters_test.go b/agent/xds/clusters_test.go index ff6b0f70fc7c..75ef06693169 100644 --- a/agent/xds/clusters_test.go +++ b/agent/xds/clusters_test.go @@ -6,13 +6,10 @@ package xds import ( "bytes" "path/filepath" - "sort" "testing" "text/template" "time" - "github.com/hashicorp/consul/types" - envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" @@ -22,12 +19,6 @@ import ( "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/proxystateconverter" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/agent/xds/testcommon" - "github.com/hashicorp/consul/agent/xdsv2" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/sdk/testutil" ) type mockCfgFetcher struct { @@ -38,13 +29,6 @@ func (s *mockCfgFetcher) AdvertiseAddrLAN() string { return s.addressLan } -type clusterTestCase struct { - name string - create func(t testinf.T) *proxycfg.ConfigSnapshot - overrideGoldenName string - alsoRunTestForV2 bool -} - func uint32ptr(i uint32) *uint32 { return &i } @@ -53,1102 +37,6 @@ func durationPtr(d time.Duration) *time.Duration { return &d } -func makeClusterDiscoChainTests(enterprise bool) []clusterTestCase { - return []clusterTestCase{ - { - name: "custom-upstream-default-chain", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", enterprise, func(ns *structs.NodeService) { - ns.Proxy.Upstreams[0].Config["envoy_cluster_json"] = - customAppClusterJSON(t, customClusterJSONOptions{ - Name: "myservice", - }) - }, nil) - }, - // TODO(proxystate): requires custom cluster work - alsoRunTestForV2: false, - }, - { - name: "connect-proxy-with-chain-http2", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, func(ns *structs.NodeService) { - ns.Proxy.Upstreams[0].Config["protocol"] = "http2" - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-chain-and-overrides", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple-with-overrides", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-chain-and-failover", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover", enterprise, nil, nil) - }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway", enterprise, nil, nil) - }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, - }, - { - name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway-triggered", enterprise, nil, nil) - }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, - }, - { - name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway", enterprise, nil, nil) - }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, - }, - { - name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway-triggered", enterprise, nil, nil) - }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, - }, - { - name: "connect-proxy-with-tcp-chain-failover-through-local-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway", enterprise, nil, nil) - }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, - }, - { - name: "connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway-triggered", enterprise, nil, nil) - }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, - }, - { - name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway", enterprise, nil, nil) - }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, - }, - { - name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway-triggered", enterprise, nil, nil) - }, - // TODO(proxystate): requires routes work - alsoRunTestForV2: false, - }, - { - name: "splitter-with-resolver-redirect", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-with-resolver-redirect-multidc", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-lb-in-resolver", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "lb-resolver", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - } -} - -func TestClustersFromSnapshot(t *testing.T) { - // TODO: we should move all of these to TestAllResourcesFromSnapshot - // eventually to test all of the xDS types at once with the same input, - // just as it would be triggered by our xDS server. - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - tests := []clusterTestCase{ - { - name: "connect-proxy-with-tls-outgoing-min-version-auto", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Outgoing: &structs.MeshDirectionalTLSConfig{ - TLSMinVersion: types.TLSVersionAuto, - }, - }, - }, - }, - }, - }) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tls-outgoing-min-version", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Outgoing: &structs.MeshDirectionalTLSConfig{ - TLSMinVersion: types.TLSv1_3, - }, - }, - }, - }, - }, - }) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tls-outgoing-max-version", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Outgoing: &structs.MeshDirectionalTLSConfig{ - TLSMaxVersion: types.TLSv1_2, - }, - }, - }, - }, - }, - }) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tls-outgoing-cipher-suites", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Outgoing: &structs.MeshDirectionalTLSConfig{ - CipherSuites: []types.TLSCipherSuite{ - types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - }, - }, - }, - }, - }, - }, - }) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-jwt-config-entry-with-local", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "jwt-provider", - Result: &structs.IndexedConfigEntries{ - Kind: "jwt-provider", - Entries: []structs.ConfigEntry{ - &structs.JWTProviderConfigEntry{ - Name: "okta", - JSONWebKeySet: &structs.JSONWebKeySet{ - Local: &structs.LocalJWKS{ - JWKS: "xxx", - }, - }, - }, - }, - }, - }, - }) - }, - // TODO(proxystate): jwt work will come at a later time - alsoRunTestForV2: false, - }, - { - name: "connect-proxy-with-jwt-config-entry-with-remote-jwks", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "jwt-provider", - Result: &structs.IndexedConfigEntries{ - Kind: "jwt-provider", - Entries: []structs.ConfigEntry{ - &structs.JWTProviderConfigEntry{ - Name: "okta", - JSONWebKeySet: &structs.JSONWebKeySet{ - Remote: &structs.RemoteJWKS{ - RequestTimeoutMs: 1000, - FetchAsynchronously: true, - URI: "https://test.test.com", - JWKSCluster: &structs.JWKSCluster{ - DiscoveryType: structs.DiscoveryTypeStatic, - ConnectTimeout: time.Duration(5) * time.Second, - TLSCertificates: &structs.JWKSTLSCertificate{ - TrustedCA: &structs.JWKSTLSCertTrustedCA{ - Filename: "mycert.crt", - }, - }, - }, - }, - }, - }, - }, - }, - }, - }) - }, - // TODO(proxystate): jwt work will come at a later time - alsoRunTestForV2: false, - }, - { - name: "custom-local-app", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["envoy_local_cluster_json"] = - customAppClusterJSON(t, customClusterJSONOptions{ - Name: "mylocal", - }) - }, nil) - }, - // TODO(proxystate): requires custom cluster work - alsoRunTestForV2: false, - }, - { - name: "custom-upstream", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Upstreams[0].Config["envoy_cluster_json"] = - customAppClusterJSON(t, customClusterJSONOptions{ - Name: "myservice", - }) - }, nil) - }, - // TODO(proxystate): requires custom cluster work - alsoRunTestForV2: false, - }, - { - name: "custom-upstream-ignores-tls", - overrideGoldenName: "custom-upstream", // should be the same - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Upstreams[0].Config["envoy_cluster_json"] = - customAppClusterJSON(t, customClusterJSONOptions{ - Name: "myservice", - // Attempt to override the TLS context should be ignored - TLSContext: `"allowRenegotiation": false`, - }) - }, nil) - }, - // TODO(proxystate): requires custom cluster work - alsoRunTestForV2: false, - }, - { - name: "custom-upstream-with-prepared-query", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - for i := range ns.Proxy.Upstreams { - - switch ns.Proxy.Upstreams[i].DestinationName { - case "db": - if ns.Proxy.Upstreams[i].Config == nil { - ns.Proxy.Upstreams[i].Config = map[string]interface{}{} - } - - uid := proxycfg.NewUpstreamID(&ns.Proxy.Upstreams[i]) - - // Triggers an override with the presence of the escape hatch listener - ns.Proxy.Upstreams[i].DestinationType = structs.UpstreamDestTypePreparedQuery - - ns.Proxy.Upstreams[i].Config["envoy_cluster_json"] = - customClusterJSON(t, customClusterJSONOptions{ - Name: uid.EnvoyID() + ":custom-upstream", - }) - - // Also test that http2 options are triggered. - // A separate upstream without an override is required to test - case "geo-cache": - if ns.Proxy.Upstreams[i].Config == nil { - ns.Proxy.Upstreams[i].Config = map[string]interface{}{} - } - ns.Proxy.Upstreams[i].Config["protocol"] = "http2" - default: - continue - } - } - }, nil) - }, - // TODO(proxystate): requires custom cluster work - alsoRunTestForV2: false, - }, - { - name: "custom-timeouts", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["local_connect_timeout_ms"] = 1234 - ns.Proxy.Upstreams[0].Config["connect_timeout_ms"] = 2345 - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "custom-passive-healthcheck", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Upstreams[0].Config["passive_health_check"] = map[string]interface{}{ - "enforcing_consecutive_5xx": float64(80), - "max_failures": float64(5), - "interval": float64(10 * time.Second), - "max_ejection_percent": float64(100), - "base_ejection_time": float64(10 * time.Second), - } - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "custom-passive-healthcheck-zero-consecutive_5xx", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Upstreams[0].Config["passive_health_check"] = map[string]interface{}{ - "enforcing_consecutive_5xx": float64(0), - "max_failures": float64(5), - "interval": float64(10 * time.Second), - "max_ejection_percent": float64(100), - "base_ejection_time": float64(10 * time.Second), - } - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "custom-max-inbound-connections", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["max_inbound_connections"] = 3456 - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "custom-limits-max-connections-only", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - for i := range ns.Proxy.Upstreams { - // We check if Config is nil because the prepared_query upstream is - // initialized without a Config map. Use Upstreams[i] syntax to - // modify the actual ConfigSnapshot instead of copying the Upstream - // in the range. - if ns.Proxy.Upstreams[i].Config == nil { - ns.Proxy.Upstreams[i].Config = map[string]interface{}{} - } - - ns.Proxy.Upstreams[i].Config["limits"] = map[string]interface{}{ - "max_connections": 500, - } - } - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "custom-limits-set-to-zero", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - for i := range ns.Proxy.Upstreams { - if ns.Proxy.Upstreams[i].Config == nil { - ns.Proxy.Upstreams[i].Config = map[string]interface{}{} - } - - ns.Proxy.Upstreams[i].Config["limits"] = map[string]interface{}{ - "max_connections": 0, - "max_pending_requests": 0, - "max_concurrent_requests": 0, - } - } - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "custom-limits", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - for i := range ns.Proxy.Upstreams { - if ns.Proxy.Upstreams[i].Config == nil { - ns.Proxy.Upstreams[i].Config = map[string]interface{}{} - } - - ns.Proxy.Upstreams[i].Config["limits"] = map[string]interface{}{ - "max_connections": 500, - "max_pending_requests": 600, - "max_concurrent_requests": 700, - } - } - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "expose-paths-local-app-paths", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotExposeConfig(t, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "downstream-service-with-unix-sockets", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Address = "" - ns.Port = 0 - ns.Proxy.LocalServiceAddress = "" - ns.Proxy.LocalServicePort = 0 - ns.Proxy.LocalServiceSocketPath = "/tmp/downstream_proxy.sock" - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "expose-paths-new-cluster-http2", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotExposeConfig(t, func(ns *structs.NodeService) { - ns.Proxy.Expose.Paths[1] = structs.ExposePath{ - LocalPathPort: 9090, - Path: "/grpc.health.v1.Health/Check", - ListenerPort: 21501, - Protocol: "http2", - } - }) - }, - alsoRunTestForV2: true, - }, - { - name: "expose-checks", - create: proxycfg.TestConfigSnapshotExposeChecks, - alsoRunTestForV2: true, - }, - { - name: "expose-paths-grpc-new-cluster-http1", - create: proxycfg.TestConfigSnapshotGRPCExposeHTTP1, - alsoRunTestForV2: true, - }, - { - name: "mesh-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "default", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-using-federation-states", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "federation-states", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-using-federation-control-plane", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "mesh-gateway-federation", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-no-services", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "no-services", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-service-subsets", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "service-subsets", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-ignore-extra-resolvers", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "ignore-extra-resolvers", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-service-timeouts", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "service-timeouts", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-non-hash-lb-injected", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "non-hash-lb-injected", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-hash-lb-ignored", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "hash-lb-ignored", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-tcp-keepalives", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "default", func(ns *structs.NodeService) { - ns.Proxy.Config["envoy_gateway_remote_tcp_enable_keepalive"] = true - ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_time"] = 120 - ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_interval"] = 60 - ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_probes"] = 7 - }, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "default", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-gateway-nil-config-entry", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway_NilConfigEntry(t) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-gateway-with-tls-outgoing-min-version", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Outgoing: &structs.MeshDirectionalTLSConfig{ - TLSMinVersion: types.TLSv1_3, - }, - }, - }, - }, - }, - }) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-gateway-with-tls-outgoing-max-version", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Outgoing: &structs.MeshDirectionalTLSConfig{ - TLSMaxVersion: types.TLSv1_2, - }, - }, - }, - }, - }, - }) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-gateway-with-tls-outgoing-cipher-suites", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Outgoing: &structs.MeshDirectionalTLSConfig{ - CipherSuites: []types.TLSCipherSuite{ - types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - }, - }, - }, - }, - }, - }, - }) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-gateway-no-services", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, false, "tcp", - "default", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "simple", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-service-max-connections", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "simple", nil, - func(entry *structs.IngressGatewayConfigEntry) { - entry.Listeners[0].Services[0].MaxConnections = 4096 - }, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-defaults-service-max-connections", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "simple", nil, - func(entry *structs.IngressGatewayConfigEntry) { - entry.Defaults = &structs.IngressServiceConfig{ - MaxConnections: 2048, - MaxPendingRequests: 512, - MaxConcurrentRequests: 4096, - } - }, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-overwrite-defaults-service-max-connections", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "simple", nil, - func(entry *structs.IngressGatewayConfigEntry) { - entry.Defaults = &structs.IngressServiceConfig{ - MaxConnections: 2048, - MaxPendingRequests: 512, - } - entry.Listeners[0].Services[0].MaxConnections = 4096 - entry.Listeners[0].Services[0].MaxPendingRequests = 2048 - }, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-service-passive-health-check", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "simple", nil, - func(entry *structs.IngressGatewayConfigEntry) { - entry.Listeners[0].Services[0].MaxConnections = 4096 - entry.Listeners[0].Services[0].PassiveHealthCheck = &structs.PassiveHealthCheck{ - Interval: 5000000000, - MaxFailures: 10, - MaxEjectionPercent: uint32ptr(90), - } - }, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-defaults-passive-health-check", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "simple", nil, - func(entry *structs.IngressGatewayConfigEntry) { - enforcingConsecutive5xx := uint32(80) - entry.Defaults = &structs.IngressServiceConfig{ - MaxConnections: 2048, - MaxPendingRequests: 512, - MaxConcurrentRequests: 4096, - PassiveHealthCheck: &structs.PassiveHealthCheck{ - Interval: 5000000000, - MaxFailures: 10, - EnforcingConsecutive5xx: &enforcingConsecutive5xx, - MaxEjectionPercent: uint32ptr(90), - }, - } - }, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-overwrite-defaults-passive-health-check", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "simple", nil, - func(entry *structs.IngressGatewayConfigEntry) { - defaultEnforcingConsecutive5xx := uint32(80) - entry.Defaults = &structs.IngressServiceConfig{ - MaxConnections: 2048, - MaxPendingRequests: 512, - PassiveHealthCheck: &structs.PassiveHealthCheck{ - Interval: 5000000000, - EnforcingConsecutive5xx: &defaultEnforcingConsecutive5xx, - MaxEjectionPercent: uint32ptr(80), - }, - } - enforcingConsecutive5xx := uint32(50) - entry.Listeners[0].Services[0].MaxConnections = 4096 - entry.Listeners[0].Services[0].MaxPendingRequests = 2048 - entry.Listeners[0].Services[0].PassiveHealthCheck = &structs.PassiveHealthCheck{ - Interval: 8000000000, - EnforcingConsecutive5xx: &enforcingConsecutive5xx, - MaxEjectionPercent: uint32ptr(90), - BaseEjectionTime: durationPtr(12 * time.Second), - } - }, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain-external-sni", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "external-sni", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain-and-failover", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain-and-failover-to-cluster-peer", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-to-cluster-peer", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-failover-through-remote-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-remote-gateway", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-failover-through-remote-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-remote-gateway-triggered", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-double-failover-through-remote-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-double-remote-gateway", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-double-remote-gateway-triggered", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-failover-through-local-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-local-gateway", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-failover-through-local-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-local-gateway-triggered", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-double-failover-through-local-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-double-local-gateway", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-double-failover-through-local-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-double-local-gateway-triggered", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-splitter-with-resolver-redirect", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", - "splitter-with-resolver-redirect-multidc", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-lb-in-resolver", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", - "lb-resolver", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, nil) - }, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-no-services", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, false, nil, nil) - }, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-service-subsets", - create: proxycfg.TestConfigSnapshotTerminatingGatewayServiceSubsetsWebAndCache, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-hostname-service-subsets", - create: proxycfg.TestConfigSnapshotTerminatingGatewayHostnameSubsets, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-sni", - create: proxycfg.TestConfigSnapshotTerminatingGatewaySNI, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-http2-upstream", - create: proxycfg.TestConfigSnapshotTerminatingGatewayHTTP2, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-http2-upstream-subsets", - create: proxycfg.TestConfigSnapshotTerminatingGatewaySubsetsHTTP2, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-ignore-extra-resolvers", - create: proxycfg.TestConfigSnapshotTerminatingGatewayIgnoreExtraResolvers, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-lb-config", - create: proxycfg.TestConfigSnapshotTerminatingGatewayLBConfigNoHashPolicies, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-tcp-keepalives", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, func(ns *structs.NodeService) { - if ns.Proxy.Config == nil { - ns.Proxy.Config = map[string]interface{}{} - } - ns.Proxy.Config["envoy_gateway_remote_tcp_enable_keepalive"] = true - ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_time"] = 133 - ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_interval"] = 27 - ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_probes"] = 5 - }, nil) - }, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-multiple-listeners-duplicate-service", - create: proxycfg.TestConfigSnapshotIngress_MultipleListenersDuplicateService, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "transparent-proxy-catalog-destinations-only", - create: proxycfg.TestConfigSnapshotTransparentProxyCatalogDestinationsOnly, - alsoRunTestForV2: true, - }, - { - name: "transparent-proxy-dial-instances-directly", - create: proxycfg.TestConfigSnapshotTransparentProxyDialDirectly, - alsoRunTestForV2: true, - }, - } - - tests = append(tests, makeClusterDiscoChainTests(false)...) - - latestEnvoyVersion := xdscommon.EnvoyVersions[0] - for _, envoyVersion := range xdscommon.EnvoyVersions { - sf, err := xdscommon.DetermineSupportedProxyFeaturesFromString(envoyVersion) - require.NoError(t, err) - t.Run("envoy-"+envoyVersion, func(t *testing.T) { - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Sanity check default with no overrides first - snap := tt.create(t) - - // We need to replace the TLS certs with deterministic ones to make golden - // files workable. Note we don't update these otherwise they'd change - // golder files for every test case and so not be any use! - testcommon.SetupTLSRootsAndLeaf(t, snap) - - // Need server just for logger dependency - g := NewResourceGenerator(testutil.Logger(t), nil, false) - g.ProxyFeatures = sf - - clusters, err := g.clustersFromSnapshot(snap) - require.NoError(t, err) - - sort.Slice(clusters, func(i, j int) bool { - return clusters[i].(*envoy_cluster_v3.Cluster).Name < clusters[j].(*envoy_cluster_v3.Cluster).Name - }) - - r, err := response.CreateResponse(xdscommon.ClusterType, "00000001", "00000001", clusters) - require.NoError(t, err) - - t.Run("current-xdsv1", func(t *testing.T) { - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - require.JSONEq(t, goldenEnvoy(t, filepath.Join("clusters", gName), envoyVersion, latestEnvoyVersion, gotJSON), gotJSON) - }) - - if tt.alsoRunTestForV2 { - generator := xdsv2.NewResourceGenerator(testutil.Logger(t)) - - converter := proxystateconverter.NewConverter(testutil.Logger(t), &mockCfgFetcher{addressLan: "10.10.10.10"}) - proxyState, err := converter.ProxyStateFromSnapshot(snap) - require.NoError(t, err) - - res, err := generator.AllResourcesFromIR(proxyState) - require.NoError(t, err) - - clusters = res[xdscommon.ClusterType] - - // The order of clusters returned via CDS isn't relevant, so it's safe - // to sort these for the purposes of test comparisons. - sort.Slice(clusters, func(i, j int) bool { - return clusters[i].(*envoy_cluster_v3.Cluster).Name < clusters[j].(*envoy_cluster_v3.Cluster).Name - }) - - r, err := response.CreateResponse(xdscommon.ClusterType, "00000001", "00000001", clusters) - require.NoError(t, err) - - t.Run("current-xdsv2", func(t *testing.T) { - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - expectedJSON := goldenEnvoy(t, filepath.Join("clusters", gName), envoyVersion, latestEnvoyVersion, gotJSON) - require.JSONEq(t, expectedJSON, gotJSON) - }) - } - }) - } - }) - } -} - type customClusterJSONOptions struct { Name string TLSContext string @@ -1492,6 +380,56 @@ func TestMakeJWKSDiscoveryClusterType(t *testing.T) { } } +func TestMakeJWKSClusterDNSLookupFamilyType(t *testing.T) { + tests := map[string]struct { + clusterType *envoy_cluster_v3.Cluster_Type + expectedDNSLookupFamily envoy_cluster_v3.Cluster_DnsLookupFamily + }{ + // strict dns and logical dns are the only ones that are different + "jwks with strict dns": { + clusterType: &envoy_cluster_v3.Cluster_Type{ + Type: envoy_cluster_v3.Cluster_STRICT_DNS, + }, + expectedDNSLookupFamily: envoy_cluster_v3.Cluster_V4_PREFERRED, + }, + "jwks with logical dns": { + clusterType: &envoy_cluster_v3.Cluster_Type{ + Type: envoy_cluster_v3.Cluster_LOGICAL_DNS, + }, + expectedDNSLookupFamily: envoy_cluster_v3.Cluster_ALL, + }, + // all should be auto from here down + "jwks with cluster EDS": { + clusterType: &envoy_cluster_v3.Cluster_Type{ + Type: envoy_cluster_v3.Cluster_EDS, + }, + expectedDNSLookupFamily: envoy_cluster_v3.Cluster_AUTO, + }, + "jwks with static dns": { + clusterType: &envoy_cluster_v3.Cluster_Type{ + Type: envoy_cluster_v3.Cluster_STATIC, + }, + expectedDNSLookupFamily: envoy_cluster_v3.Cluster_AUTO, + }, + + "jwks with original dst": { + clusterType: &envoy_cluster_v3.Cluster_Type{ + Type: envoy_cluster_v3.Cluster_ORIGINAL_DST, + }, + expectedDNSLookupFamily: envoy_cluster_v3.Cluster_AUTO, + }, + } + + for name, tt := range tests { + tt := tt + t.Run(name, func(t *testing.T) { + actualDNSLookupFamily := makeJWKSClusterDNSLookupFamilyType(tt.clusterType) + + require.Equal(t, tt.expectedDNSLookupFamily, actualDNSLookupFamily) + }) + } +} + func TestParseJWTRemoteURL(t *testing.T) { tests := map[string]struct { uri string diff --git a/agent/xds/config/config.go b/agent/xds/config/config.go index 32c46d07d3ef..ed7da3c61c02 100644 --- a/agent/xds/config/config.go +++ b/agent/xds/config/config.go @@ -5,6 +5,7 @@ package config import ( "strings" + "time" envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" "google.golang.org/protobuf/types/known/durationpb" @@ -16,6 +17,47 @@ import ( "github.com/hashicorp/consul/lib/decode" ) +func parseConfig[T any](m map[string]any, cfg *T) error { + d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + DecodeHook: mapstructure.ComposeDecodeHookFunc( + decode.HookWeakDecodeFromSlice, + decode.HookTranslateKeys, + ), + Result: cfg, + WeaklyTypedInput: true, + }) + if err != nil { + return err + } + return d.Decode(m) +} + +// XDSCommonConfig contains the configuration from the opaque map that is common to both gateways and sidecar proxies. +type XDSCommonConfig struct { + // XDSFetchTimeoutMs specifies the amount of milliseconds to wait for dynamically configured Envoy data (EDS, RDS). + // Uses the Envoy default value if not specified or negative. A value of zero disables the timeout. + XDSFetchTimeoutMs *int `mapstructure:"xds_fetch_timeout_ms"` +} + +// ParseXDSCommonConfig returns the XDSCommonConfig parsed from an opaque map. If an +// error occurs during parsing, it is returned along with the default config. This +// allows the caller to choose whether and how to report the error +func ParseXDSCommonConfig(m map[string]interface{}) (XDSCommonConfig, error) { + var cfg XDSCommonConfig + err := parseConfig(m, &cfg) + return cfg, err +} + +func (c *XDSCommonConfig) GetXDSFetchTimeout() *durationpb.Duration { + if c == nil || c.XDSFetchTimeoutMs == nil { + return nil + } + if *c.XDSFetchTimeoutMs >= 0 { + return durationpb.New(time.Duration(*c.XDSFetchTimeoutMs) * time.Millisecond) + } + return nil +} + // ProxyConfig describes the keys we understand from Connect.Proxy.Config. Note // that this only includes config keys that affects runtime config delivered by // xDS. For Envoy config keys that affect bootstrap generation see @@ -87,23 +129,10 @@ type ProxyConfig struct { // allows caller to choose whether and how to report the error. func ParseProxyConfig(m map[string]interface{}) (ProxyConfig, error) { var cfg ProxyConfig - decodeConf := &mapstructure.DecoderConfig{ - DecodeHook: mapstructure.ComposeDecodeHookFunc( - decode.HookWeakDecodeFromSlice, - decode.HookTranslateKeys, - ), - Result: &cfg, - WeaklyTypedInput: true, - } - decoder, err := mapstructure.NewDecoder(decodeConf) - if err != nil { - return cfg, err - } - if err := decoder.Decode(m); err != nil { + if err := parseConfig(m, &cfg); err != nil { return cfg, err } - // Set defaults (even if error is returned) if cfg.Protocol == "" { cfg.Protocol = "tcp" } else { @@ -113,7 +142,7 @@ func ParseProxyConfig(m map[string]interface{}) (ProxyConfig, error) { cfg.LocalConnectTimeoutMs = 5000 } - return cfg, err + return cfg, nil } type GatewayConfig struct { @@ -154,28 +183,14 @@ type GatewayConfig struct { // allows the caller to choose whether and how to report the error func ParseGatewayConfig(m map[string]interface{}) (GatewayConfig, error) { var cfg GatewayConfig - d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ - DecodeHook: mapstructure.ComposeDecodeHookFunc( - decode.HookWeakDecodeFromSlice, - decode.HookTranslateKeys, - ), - Result: &cfg, - WeaklyTypedInput: true, - }) - if err != nil { + if err := parseConfig(m, &cfg); err != nil { return cfg, err } - if err := d.Decode(m); err != nil { - return cfg, err - } - if cfg.ConnectTimeoutMs < 1 { cfg.ConnectTimeoutMs = 5000 } - cfg.DNSDiscoveryType = strings.ToLower(cfg.DNSDiscoveryType) - - return cfg, err + return cfg, nil } // Return an envoy.OutlierDetection populated by the values from structs.PassiveHealthCheck. diff --git a/agent/xds/config/config_test.go b/agent/xds/config/config_test.go index 72e9a0e61461..79de29e4daaa 100644 --- a/agent/xds/config/config_test.go +++ b/agent/xds/config/config_test.go @@ -5,8 +5,11 @@ package config import ( "testing" + "time" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" "github.com/hashicorp/consul/agent/structs" ) @@ -309,3 +312,61 @@ func TestParseGatewayConfig(t *testing.T) { func intPointer(i int) *int { return &i } + +func Test_ProxyConfig_GetXDSFetchTimeout(t *testing.T) { + tests := map[string]struct { + conf map[string]interface{} + expect *durationpb.Duration + expectErr bool + }{ + "nil_conf": { + expect: nil, + conf: nil, + }, + "key_not_found": { + expect: nil, + conf: map[string]interface{}{}, + }, + "invalid_key": { + expect: nil, + conf: map[string]interface{}{ + "i_do_not_exist": "as_an_expected_field", + }, + }, + "nil_value_for_key": { + expect: nil, + conf: map[string]interface{}{ + "xds_fetch_timeout_ms": nil, + }, + }, + "bad_value_for_key": { + expectErr: true, + conf: map[string]interface{}{ + "xds_fetch_timeout_ms": "bad", + }, + }, + "negative_value_for_key": { + expect: nil, + conf: map[string]interface{}{ + "xds_fetch_timeout_ms": -1, + }, + }, + "valid_value_for_key": { + expect: durationpb.New(99 * time.Millisecond), + conf: map[string]interface{}{ + "xds_fetch_timeout_ms": 99, + }, + }, + } + for n, tc := range tests { + t.Run(n, func(t *testing.T) { + conf, err := ParseXDSCommonConfig(tc.conf) + if tc.expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + require.True(t, proto.Equal(tc.expect, conf.GetXDSFetchTimeout())) + }) + } +} diff --git a/agent/xds/delta.go b/agent/xds/delta.go index f5d07e2763ae..44b63fcdce18 100644 --- a/agent/xds/delta.go +++ b/agent/xds/delta.go @@ -8,6 +8,7 @@ import ( "encoding/hex" "errors" "fmt" + "os" "strconv" "sync" "sync/atomic" @@ -17,31 +18,34 @@ import ( envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" - "github.com/hashicorp/go-hclog" - goversion "github.com/hashicorp/go-version" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" + "github.com/hashicorp/go-hclog" + goversion "github.com/hashicorp/go-version" + "github.com/hashicorp/consul/agent/envoyextensions" external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/grpc-external/limiter" "github.com/hashicorp/consul/agent/proxycfg" + "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/configfetcher" "github.com/hashicorp/consul/agent/xds/extensionruntime" - "github.com/hashicorp/consul/agent/xdsv2" "github.com/hashicorp/consul/envoyextensions/extensioncommon" "github.com/hashicorp/consul/envoyextensions/xdscommon" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" "github.com/hashicorp/consul/logging" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/version" ) var errOverwhelmed = status.Error(codes.ResourceExhausted, "this server has too many xDS streams open, please try another") +var errConfigSyncError = status.Errorf(codes.Internal, "config-source sync loop terminated due to error") + +// xdsProtocolLegacyChildResend enables the legacy behavior for the `ensureChildResend` function. +// This environment variable exists as an escape hatch so that users can disable the behavior, if needed. +// Ideally, this is a flag we can remove in 1.19+ +var xdsProtocolLegacyChildResend = (os.Getenv("XDS_PROTOCOL_LEGACY_CHILD_RESEND") != "") type deltaRecvResponse int @@ -73,7 +77,10 @@ func (s *Server) DeltaAggregatedResources(stream ADSDeltaStream) error { close(reqCh) return } - reqCh <- req + select { + case <-stream.Context().Done(): + case reqCh <- req: + } } }() @@ -89,36 +96,14 @@ func (s *Server) DeltaAggregatedResources(stream ADSDeltaStream) error { } // getEnvoyConfiguration is a utility function that instantiates the proper -// Envoy resource generator based on whether it was passed a ConfigSource or -// ProxyState implementation of the ProxySnapshot interface and returns the -// generated Envoy configuration. -func getEnvoyConfiguration(proxySnapshot proxysnapshot.ProxySnapshot, logger hclog.Logger, cfgFetcher configfetcher.ConfigFetcher) (map[string][]proto.Message, error) { - switch proxySnapshot.(type) { - case *proxycfg.ConfigSnapshot: - logger.Trace("ProxySnapshot update channel received a ProxySnapshot of type ConfigSnapshot") - generator := NewResourceGenerator( - logger, - cfgFetcher, - true, - ) - - c := proxySnapshot.(*proxycfg.ConfigSnapshot) - return generator.AllResourcesFromSnapshot(c) - case *proxytracker.ProxyState: - logger.Trace("ProxySnapshot update channel received a ProxySnapshot of type ProxyState") - generator := xdsv2.NewResourceGenerator( - logger, - ) - c := proxySnapshot.(*proxytracker.ProxyState) - resources, err := generator.AllResourcesFromIR(c) - if err != nil { - logger.Error("error generating resources from proxy state template", "err", err) - return nil, err - } - return resources, nil - default: - return nil, errors.New("proxysnapshot must be of type ProxyState or ConfigSnapshot") - } +// Envoy resource generator and returns the generated Envoy configuration. +func getEnvoyConfiguration(snapshot *proxycfg.ConfigSnapshot, logger hclog.Logger, cfgFetcher configfetcher.ConfigFetcher) (map[string][]proto.Message, error) { + generator := NewResourceGenerator( + logger, + cfgFetcher, + true, + ) + return generator.AllResourcesFromSnapshot(snapshot) } const ( @@ -135,13 +120,14 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove // Loop state var ( - proxySnapshot proxysnapshot.ProxySnapshot - node *envoy_config_core_v3.Node - stateCh <-chan proxysnapshot.ProxySnapshot - drainCh limiter.SessionTerminatedChan - watchCancel func() - nonce uint64 // xDS requires a unique nonce to correlate response/request pairs - ready bool // set to true after the first snapshot arrives + snapshot *proxycfg.ConfigSnapshot + node *envoy_config_core_v3.Node + stateCh <-chan *proxycfg.ConfigSnapshot + drainCh limiter.SessionTerminatedChan + cfgSrcTerminated proxycfg.SrcTerminatedChan + watchCancel func() + nonce uint64 // xDS requires a unique nonce to correlate response/request pairs + ready bool // set to true after the first snapshot arrives streamStartTime = time.Now() streamStartOnce sync.Once @@ -167,13 +153,13 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove // Configure handlers for each type of request we currently care about. handlers := map[string]*xDSDeltaType{ xdscommon.ListenerType: newDeltaType(logger, stream, xdscommon.ListenerType, func() bool { - return proxySnapshot.AllowEmptyListeners() + return snapshot.AllowEmptyListeners() }), xdscommon.RouteType: newDeltaType(logger, stream, xdscommon.RouteType, func() bool { - return proxySnapshot.AllowEmptyRoutes() + return snapshot.AllowEmptyRoutes() }), xdscommon.ClusterType: newDeltaType(logger, stream, xdscommon.ClusterType, func() bool { - return proxySnapshot.AllowEmptyClusters() + return snapshot.AllowEmptyClusters() }), xdscommon.EndpointType: newDeltaType(logger, stream, xdscommon.EndpointType, nil), xdscommon.SecretType: newDeltaType(logger, stream, xdscommon.SecretType, nil), // TODO allowEmptyFn @@ -202,8 +188,8 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove authTimer = time.After(s.AuthCheckFrequency) } - checkStreamACLs := func(proxySnap proxysnapshot.ProxySnapshot) error { - return s.authorize(stream.Context(), proxySnap) + checkStreamACLs := func(snapshot *proxycfg.ConfigSnapshot) error { + return s.authorize(stream.Context(), snapshot) } for { @@ -214,7 +200,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove return errOverwhelmed case <-authTimer: // It's been too long since a Discovery{Request,Response} so recheck ACLs. - if err := checkStreamACLs(proxySnapshot); err != nil { + if err := checkStreamACLs(snapshot); err != nil { return err } extendAuthTimer() @@ -269,9 +255,9 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove // would've already exited this loop. return status.Error(codes.Aborted, "xDS stream terminated due to an irrecoverable error, please try again") } - proxySnapshot = cs + snapshot = cs - newRes, err := getEnvoyConfiguration(proxySnapshot, logger, s.CfgFetcher) + newRes, err := getEnvoyConfiguration(snapshot, logger, s.CfgFetcher) if err != nil { return status.Errorf(codes.Unavailable, "failed to generate all xDS resources from the snapshot: %v", err) } @@ -283,7 +269,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove s.ResourceMapMutateFn(newResourceMap) } - if newResourceMap, err = s.applyEnvoyExtensions(newResourceMap, proxySnapshot, node); err != nil { + if newResourceMap, err = s.applyEnvoyExtensions(newResourceMap, snapshot, node); err != nil { // err is already the result of calling status.Errorf return err } @@ -300,6 +286,12 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove resourceMap = newResourceMap currentVersions = newVersions ready = true + case <-cfgSrcTerminated: + // Ensure that we cancel and cleanup resources if the sync loop terminates for any reason. + // This is necessary to handle the scenario where an unexpected error occurs that the loop + // cannot recover from. + logger.Debug("config-source sync loop terminated due to error") + return errConfigSyncError } // Trigger state machine @@ -317,7 +309,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove } // Start authentication process, we need the proxyID - proxyID := newResourceIDFromEnvoyNode(node) + proxyID := structs.NewServiceID(node.Id, parseEnterpriseMeta(node)) // Start watching config for that proxy var err error @@ -326,7 +318,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove return status.Errorf(codes.Internal, "failed to watch proxy service: %s", err) } - stateCh, drainCh, watchCancel, err = s.ProxyWatcher.Watch(proxyID, nodeName, options.Token) + stateCh, drainCh, cfgSrcTerminated, watchCancel, err = s.ProxyWatcher.Watch(proxyID, nodeName, options.Token) switch { case errors.Is(err, limiter.ErrCapacityReached): return errOverwhelmed @@ -340,14 +332,14 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove // state machine. defer watchCancel() - logger = logger.With("service_id", proxyID.Name) // enhance future logs + logger = logger.With("service_id", proxyID.String()) // enhance future logs logger.Trace("watching proxy, pending initial proxycfg snapshot for xDS") // Now wait for the config so we can check ACL state = stateDeltaPendingInitialConfig case stateDeltaPendingInitialConfig: - if proxySnapshot == nil { + if snapshot == nil { // Nothing we can do until we get the initial config continue } @@ -356,7 +348,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove state = stateDeltaRunning // Upgrade the logger - loggerName := proxySnapshot.LoggerName() + loggerName := snapshot.LoggerName() if loggerName != "" { logger = logger.Named(loggerName) } @@ -367,7 +359,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove fallthrough case stateDeltaRunning: // Check ACLs on every Discovery{Request,Response}. - if err := checkStreamACLs(proxySnapshot); err != nil { + if err := checkStreamACLs(snapshot); err != nil { return err } // For the first time through the state machine, this is when the @@ -416,37 +408,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove } } -// newResourceIDFromEnvoyNode is a utility function that allows creating a -// Resource ID from an Envoy proxy node so that existing delta calls can easily -// use ProxyWatcher interface arguments for Watch(). -func newResourceIDFromEnvoyNode(node *envoy_config_core_v3.Node) *pbresource.ID { - entMeta := parseEnterpriseMeta(node) - - return &pbresource.ID{ - Name: node.Id, - Tenancy: &pbresource.Tenancy{ - Namespace: entMeta.NamespaceOrDefault(), - Partition: entMeta.PartitionOrDefault(), - }, - Type: pbmesh.ProxyStateTemplateType, - } -} - -func (s *Server) applyEnvoyExtensions(resources *xdscommon.IndexedResources, proxySnapshot proxysnapshot.ProxySnapshot, node *envoy_config_core_v3.Node) (*xdscommon.IndexedResources, error) { - // TODO(proxystate) - // This is a workaround for now as envoy extensions are not yet supported with ProxyState. - // For now, we cast to proxycfg.ConfigSnapshot and no-op if it's the pbmesh.ProxyState type. - var snapshot *proxycfg.ConfigSnapshot - switch proxySnapshot.(type) { - //TODO(proxystate): implement envoy extensions for ProxyState - case *proxytracker.ProxyState: - return resources, nil - case *proxycfg.ConfigSnapshot: - snapshot = proxySnapshot.(*proxycfg.ConfigSnapshot) - default: - return nil, status.Errorf(codes.InvalidArgument, - "unsupported config snapshot type to apply envoy extensions to %T", proxySnapshot) - } +func (s *Server) applyEnvoyExtensions(resources *xdscommon.IndexedResources, snapshot *proxycfg.ConfigSnapshot, node *envoy_config_core_v3.Node) (*xdscommon.IndexedResources, error) { var err error envoyVersion := xdscommon.DetermineEnvoyVersionFromNode(node) consulVersion, err := goversion.NewVersion(version.Version) @@ -1080,13 +1042,9 @@ func (t *xDSDeltaType) createDeltaResponse( } func (t *xDSDeltaType) ensureChildResend(parentName, childName string) { - if _, exist := t.deltaChild.childType.resourceVersions[childName]; !exist { - return - } if !t.subscribed(childName) { return } - t.logger.Trace( "triggering implicit update of resource", "typeUrl", t.typeURL, @@ -1094,11 +1052,41 @@ func (t *xDSDeltaType) ensureChildResend(parentName, childName string) { "childTypeUrl", t.deltaChild.childType.typeURL, "childResource", childName, ) - // resourceVersions tracks the last known version for this childName that Envoy // has ACKed. By setting this to empty it effectively tells us that Envoy does // not have any data for that child, and we need to re-send. - t.deltaChild.childType.resourceVersions[childName] = "" + if _, exist := t.deltaChild.childType.resourceVersions[childName]; exist { + t.deltaChild.childType.resourceVersions[childName] = "" + } + + if xdsProtocolLegacyChildResend { + return + // TODO: This legacy behavior can be removed in 1.19, provided there are no outstanding issues. + // + // In this legacy mode, there is a confirmed race condition: + // - Send update endpoints + // - Send update cluster + // - Recv ACK endpoints + // - Recv ACK cluster + // + // When this situation happens, Envoy wipes the child endpoints when the cluster is updated, + // but it would never receive new ones. The endpoints would not be resent, because their hash + // never changed since the previous ACK. + // + // Due to ambiguity with the Envoy protocol [https://github.com/envoyproxy/envoy/issues/13009], + // it's difficult to state with certainty that no other unexpected side-effects are possible. + // This legacy escape hatch is left in-place in case some other complex race condition crops up. + // + // Longer-term, we should modify the hash of children to include the parent hash so that this + // behavior is implicitly handled, rather than being an edge case. + } + + // pendingUpdates can contain newer versions that have been sent to Envoy but + // that we haven't processed an ACK for yet. These need to be cleared out, too, + // so that they aren't moved to resourceVersions by ack() + for nonce := range t.deltaChild.childType.pendingUpdates { + delete(t.deltaChild.childType.pendingUpdates[nonce], childName) + } } func computeResourceVersions(resourceMap *xdscommon.IndexedResources) (map[string]map[string]string, error) { diff --git a/agent/xds/delta_envoy_extender_ce_test.go b/agent/xds/delta_envoy_extender_ce_test.go index 30ebd9184b37..acd18700394a 100644 --- a/agent/xds/delta_envoy_extender_ce_test.go +++ b/agent/xds/delta_envoy_extender_ce_test.go @@ -445,7 +445,7 @@ end`, create: func(t testinf.T) *proxycfg.ConfigSnapshot { extra := makeLambdaServiceDefaults(false) extra.Name = "google" - return proxycfg.TestConfigSnapshotTransparentProxyHTTPUpstream(t, extra) + return proxycfg.TestConfigSnapshotTransparentProxyHTTPUpstream(t, nil, extra) }, }, // Make sure that if the upstream type is different from ExtensionConfiguration.Kind is, that the resources are not patched. @@ -766,6 +766,23 @@ end`, }, nil) }, }, + { + name: "tproxy-and-permissive-mtls-and-envoy-extension", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config = map[string]any{"protocol": "http"} + ns.Proxy.MutualTLSMode = structs.MutualTLSModePermissive + ns.Proxy.Mode = structs.ProxyModeTransparent + ns.Proxy.TransparentProxy.OutboundListenerPort = 1234 + // Arbitrarily chose ext-authz since it's available in CE + ns.Proxy.EnvoyExtensions = makeExtAuthzEnvoyExtension( + "https", + "dest=local", + ) + }, + nil) + }, + }, } latestEnvoyVersion := xdscommon.EnvoyVersions[0] diff --git a/agent/xds/delta_test.go b/agent/xds/delta_test.go index d93d06271bac..ab170f9d66b9 100644 --- a/agent/xds/delta_test.go +++ b/agent/xds/delta_test.go @@ -6,7 +6,6 @@ package xds import ( "errors" "fmt" - "github.com/hashicorp/consul/envoyextensions/xdscommon" "strconv" "strings" "sync" @@ -14,6 +13,8 @@ import ( "testing" "time" + "github.com/hashicorp/consul/envoyextensions/xdscommon" + "github.com/armon/go-metrics" envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" @@ -821,6 +822,147 @@ func TestServer_DeltaAggregatedResources_v3_BasicProtocol_TCP_clusterChangesImpa } } +func TestServer_DeltaAggregatedResources_v3_BasicProtocol_TCP_clusterChangeBeforeEndpointAck(t *testing.T) { + // This test ensures that the following race condition does not block indefinitely: + // - Send update endpoints + // - Send update cluster + // - Recv ACK endpoints + // - Recv ACK cluster + // Prior to a bug fix, this would have resulted in the endpoints NOT existing in Envoy. This occurred because + // the cluster update implicitly clears the endpoints in Envoy, but we would never re-send the endpoint data + // to compensate for the loss because we would incorrectly ACK the invalid old endpoint hash. Since the + // endpoint's hash did not actually change, they would not be resent. + aclResolve := func(id string) (acl.Authorizer, error) { + // Allow all + return acl.RootAuthorizer("manage"), nil + } + scenario := newTestServerDeltaScenario(t, aclResolve, "web-sidecar-proxy", "", 0) + mgr, errCh, envoy := scenario.mgr, scenario.errCh, scenario.envoy + + sid := structs.NewServiceID("web-sidecar-proxy", nil) + + // Register the proxy to create state needed to Watch() on + mgr.RegisterProxy(t, sid) + + var snap *proxycfg.ConfigSnapshot + testutil.RunStep(t, "initial setup", func(t *testing.T) { + snap = newTestSnapshot(t, nil, "", nil) + + // Send initial cluster discover. + envoy.SendDeltaReq(t, xdscommon.ClusterType, &envoy_discovery_v3.DeltaDiscoveryRequest{}) + + // Check no response sent yet + assertDeltaChanBlocked(t, envoy.deltaStream.sendCh) + + requireProtocolVersionGauge(t, scenario, "v3", 1) + + // Deliver a new snapshot (tcp with one tcp upstream) + mgr.DeliverConfig(t, sid, snap) + + assertDeltaResponseSent(t, envoy.deltaStream.sendCh, &envoy_discovery_v3.DeltaDiscoveryResponse{ + TypeUrl: xdscommon.ClusterType, + Nonce: hexString(1), + Resources: makeTestResources(t, + makeTestCluster(t, snap, "tcp:local_app"), + makeTestCluster(t, snap, "tcp:db"), + makeTestCluster(t, snap, "tcp:geo-cache"), + ), + }) + }) + + var newSnap *proxycfg.ConfigSnapshot + testutil.RunStep(t, "resend cluster immediately", func(t *testing.T) { + // Deliver updated snapshot with new CA roots and leaf certificate. This will not be + // sent to Envoy until the initial set of cluster message is ACKed. + newSnap = newTestSnapshot(t, nil, "", nil) + mgr.DeliverConfig(t, sid, newSnap) + + // Envoy then tries to discover endpoints for clusters. + envoy.SendDeltaReq(t, xdscommon.EndpointType, &envoy_discovery_v3.DeltaDiscoveryRequest{ + ResourceNamesSubscribe: []string{ + "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + }, + }) + + // We should get a response immediately since the config is already present in + // the server for endpoints. Note that this should not be racy if the server + // is behaving well since the Cluster send above should be blocked until we + // deliver a new config version. + assertDeltaResponseSent(t, envoy.deltaStream.sendCh, &envoy_discovery_v3.DeltaDiscoveryResponse{ + TypeUrl: xdscommon.EndpointType, + Nonce: hexString(2), + Resources: makeTestResources(t, + makeTestEndpoints(t, snap, "tcp:db"), + makeTestEndpoints(t, snap, "tcp:geo-cache"), + ), + }) + + // After receiving the endpoints Envoy sends an ACK for the clusters + envoy.SendDeltaReqACK(t, xdscommon.ClusterType, 1) + + // The updated cluster snapshot with new certificates is sent immediately + // after the first is ACKed. + assertDeltaResponseSent(t, envoy.deltaStream.sendCh, &envoy_discovery_v3.DeltaDiscoveryResponse{ + TypeUrl: xdscommon.ClusterType, + Nonce: hexString(3), + Resources: makeTestResources(t, + // SAME makeTestCluster(t, snap, "tcp:local_app"), + makeTestCluster(t, newSnap, "tcp:db"), + makeTestCluster(t, newSnap, "tcp:geo-cache"), + ), + }) + }) + + testutil.RunStep(t, "resend endpoints", func(t *testing.T) { + // Envoy requests listeners because it has received endpoints. We won't send listeners + // until Envoy ACKs the second cluster update. + envoy.SendDeltaReq(t, xdscommon.ListenerType, nil) + + // Envoy ACKs the endpoints from the first cluster update. + envoy.SendDeltaReqACK(t, xdscommon.EndpointType, 2) + + // Resend endpoints because the clusters changed. + assertDeltaResponseSent(t, envoy.deltaStream.sendCh, &envoy_discovery_v3.DeltaDiscoveryResponse{ + TypeUrl: xdscommon.EndpointType, + Nonce: hexString(4), + Resources: makeTestResources(t, + makeTestEndpoints(t, newSnap, "tcp:db"), + makeTestEndpoints(t, newSnap, "tcp:geo-cache"), + ), + }) + + // Envoy ACKs the new cluster and endpoints. + envoy.SendDeltaReqACK(t, xdscommon.ClusterType, 3) + envoy.SendDeltaReqACK(t, xdscommon.EndpointType, 4) + + // Listeners are sent after the cluster and endpoints are ACKed. + assertDeltaResponseSent(t, envoy.deltaStream.sendCh, &envoy_discovery_v3.DeltaDiscoveryResponse{ + TypeUrl: xdscommon.ListenerType, + Nonce: hexString(5), + Resources: makeTestResources(t, + makeTestListener(t, newSnap, "tcp:public_listener"), + makeTestListener(t, newSnap, "tcp:db"), + makeTestListener(t, newSnap, "tcp:geo-cache"), + ), + }) + + // We are caught up, so there should be nothing queued to send. + assertDeltaChanBlocked(t, envoy.deltaStream.sendCh) + + // ACKs the listener + envoy.SendDeltaReqACK(t, xdscommon.ListenerType, 5) + }) + + envoy.Close() + select { + case err := <-errCh: + require.NoError(t, err) + case <-time.After(50 * time.Millisecond): + t.Fatalf("timed out waiting for handler to finish") + } +} + func TestServer_DeltaAggregatedResources_v3_BasicProtocol_HTTP2_RDS_listenerChangesImpactRoutes(t *testing.T) { aclResolve := func(id string) (acl.Authorizer, error) { // Allow all @@ -1466,6 +1608,34 @@ func TestServer_DeltaAggregatedResources_v3_CapacityReached(t *testing.T) { } } +func TestServer_DeltaAggregatedResources_v3_CfgSrcTerminated(t *testing.T) { + aclResolve := func(id string) (acl.Authorizer, error) { return acl.ManageAll(), nil } + + scenario := newTestServerDeltaScenario(t, aclResolve, "web-sidecar-proxy", "", 0) + mgr, errCh, envoy := scenario.mgr, scenario.errCh, scenario.envoy + + sid := structs.NewServiceID("web-sidecar-proxy", nil) + + mgr.RegisterProxy(t, sid) + + snap := newTestSnapshot(t, nil, "", nil) + envoy.SendDeltaReq(t, xdscommon.ClusterType, &envoy_discovery_v3.DeltaDiscoveryRequest{ + InitialResourceVersions: mustMakeVersionMap(t, + makeTestCluster(t, snap, "tcp:geo-cache"), + ), + }) + mgr.CfgSrcTerminate(sid) + + select { + case err := <-errCh: + require.Error(t, err) + require.Equal(t, codes.Internal.String(), status.Code(err).String()) + require.Equal(t, errConfigSyncError, err) + case <-time.After(50 * time.Millisecond): + t.Fatalf("timed out waiting for handler to finish") + } +} + type capacityReachedLimiter struct{} func (capacityReachedLimiter) BeginSession() (limiter.Session, error) { diff --git a/agent/xds/endpoints_test.go b/agent/xds/endpoints_test.go index f16327f88b05..4a4cff89d050 100644 --- a/agent/xds/endpoints_test.go +++ b/agent/xds/endpoints_test.go @@ -4,23 +4,15 @@ package xds import ( - "path/filepath" - "sort" "testing" envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/proxystateconverter" "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/agent/xds/testcommon" - "github.com/hashicorp/consul/agent/xdsv2" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/go-hclog" "github.com/mitchellh/copystructure" - testinf "github.com/mitchellh/go-testing-interface" "github.com/stretchr/testify/require" ) @@ -237,422 +229,3 @@ func Test_makeLoadAssignment(t *testing.T) { }) } } - -type endpointTestCase struct { - name string - create func(t testinf.T) *proxycfg.ConfigSnapshot - overrideGoldenName string - alsoRunTestForV2 bool -} - -func makeEndpointDiscoChainTests(enterprise bool) []endpointTestCase { - return []endpointTestCase{ - { - name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway-triggered", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway-triggered", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tcp-chain-failover-through-local-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway-triggered", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway-triggered", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-default-chain-and-custom-cluster", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", enterprise, func(ns *structs.NodeService) { - ns.Proxy.Upstreams[0].Config["envoy_cluster_json"] = - customAppClusterJSON(t, customClusterJSONOptions{ - Name: "myservice", - }) - }, nil) - }, - // TODO(proxystate): requires custom cluster work - alsoRunTestForV2: false, - }, - { - name: "splitter-with-resolver-redirect", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-with-resolver-redirect-multidc", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - } -} - -func TestEndpointsFromSnapshot(t *testing.T) { - // TODO: we should move all of these to TestAllResourcesFromSnapshot - // eventually to test all of the xDS types at once with the same input, - // just as it would be triggered by our xDS server. - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - tests := []endpointTestCase{ - { - name: "mesh-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "default", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-using-federation-states", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "federation-states", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-newer-information-in-federation-states", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "newer-info-in-federation-states", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-using-federation-control-plane", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "mesh-gateway-federation", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-older-information-in-federation-states", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "older-info-in-federation-states", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-no-services", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "no-services", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-service-subsets", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "service-subsets2", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "mesh-gateway-default-service-subset", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "default-service-subsets2", nil, nil) - }, - // TODO(proxystate): mesh gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "default", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-gateway-nil-config-entry", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway_NilConfigEntry(t) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-gateway-no-services", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, false, "tcp", - "default", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "simple", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain-external-sni", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "external-sni", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain-and-failover", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain-and-failover-to-cluster-peer", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-to-cluster-peer", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-failover-through-remote-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-remote-gateway", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-failover-through-remote-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-remote-gateway-triggered", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-double-failover-through-remote-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-double-remote-gateway", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-double-remote-gateway-triggered", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-failover-through-local-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-local-gateway", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-failover-through-local-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-local-gateway-triggered", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-double-failover-through-local-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-double-local-gateway", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-tcp-chain-double-failover-through-local-gateway-triggered", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-double-local-gateway-triggered", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-splitter-with-resolver-redirect", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", - "splitter-with-resolver-redirect-multidc", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, nil) - }, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-no-services", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, false, nil, nil) - }, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-service-subsets", - create: proxycfg.TestConfigSnapshotTerminatingGatewayServiceSubsets, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-default-service-subset", - create: proxycfg.TestConfigSnapshotTerminatingGatewayDefaultServiceSubset, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-multiple-listeners-duplicate-service", - create: proxycfg.TestConfigSnapshotIngress_MultipleListenersDuplicateService, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - } - - tests = append(tests, makeEndpointDiscoChainTests(false)...) - - latestEnvoyVersion := xdscommon.EnvoyVersions[0] - for _, envoyVersion := range xdscommon.EnvoyVersions { - sf, err := xdscommon.DetermineSupportedProxyFeaturesFromString(envoyVersion) - require.NoError(t, err) - t.Run("envoy-"+envoyVersion, func(t *testing.T) { - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Sanity check default with no overrides first - snap := tt.create(t) - - // We need to replace the TLS certs with deterministic ones to make golden - // files workable. Note we don't update these otherwise they'd change - // golden files for every test case and so not be any use! - testcommon.SetupTLSRootsAndLeaf(t, snap) - - // Need server just for logger dependency - g := NewResourceGenerator(testutil.Logger(t), nil, false) - g.ProxyFeatures = sf - - endpoints, err := g.endpointsFromSnapshot(snap) - require.NoError(t, err) - - sort.Slice(endpoints, func(i, j int) bool { - return endpoints[i].(*envoy_endpoint_v3.ClusterLoadAssignment).ClusterName < endpoints[j].(*envoy_endpoint_v3.ClusterLoadAssignment).ClusterName - }) - r, err := response.CreateResponse(xdscommon.EndpointType, "00000001", "00000001", endpoints) - require.NoError(t, err) - - t.Run("current-xdsv1", func(t *testing.T) { - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - require.JSONEq(t, goldenEnvoy(t, filepath.Join("endpoints", gName), envoyVersion, latestEnvoyVersion, gotJSON), gotJSON) - }) - - if tt.alsoRunTestForV2 { - generator := xdsv2.NewResourceGenerator(testutil.Logger(t)) - - converter := proxystateconverter.NewConverter(testutil.Logger(t), &mockCfgFetcher{addressLan: "10.10.10.10"}) - proxyState, err := converter.ProxyStateFromSnapshot(snap) - require.NoError(t, err) - - res, err := generator.AllResourcesFromIR(proxyState) - require.NoError(t, err) - - endpoints = res[xdscommon.EndpointType] - // The order of listeners returned via LDS isn't relevant, so it's safe - // to sort these for the purposes of test comparisons. - sort.Slice(endpoints, func(i, j int) bool { - return endpoints[i].(*envoy_endpoint_v3.ClusterLoadAssignment).ClusterName < endpoints[j].(*envoy_endpoint_v3.ClusterLoadAssignment).ClusterName - }) - - r, err := response.CreateResponse(xdscommon.EndpointType, "00000001", "00000001", endpoints) - require.NoError(t, err) - - t.Run("current-xdsv2", func(t *testing.T) { - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - expectedJSON := goldenEnvoy(t, filepath.Join("endpoints", gName), envoyVersion, latestEnvoyVersion, gotJSON) - require.JSONEq(t, expectedJSON, gotJSON) - }) - } - }) - } - }) - } -} diff --git a/agent/xds/failover_policy.go b/agent/xds/failover_policy.go index ab3e86f25d1d..fdd351670a8f 100644 --- a/agent/xds/failover_policy.go +++ b/agent/xds/failover_policy.go @@ -132,7 +132,7 @@ func (s *ResourceGenerator) mapDiscoChainTargets(cfgSnap *proxycfg.ConfigSnapsho makeTLSParametersFromProxyTLSConfig(cfgSnap.MeshConfigTLSOutgoing()), ) - err := injectSANMatcher(commonTLSContext, spiffeIDs...) + err := injectSANMatcher(commonTLSContext, false, spiffeIDs...) if err != nil { return failoverTargets, fmt.Errorf("failed to inject SAN matcher rules for cluster %q: %v", sni, err) } diff --git a/agent/xds/jwt_authn_ce.go b/agent/xds/jwt_authn_ce.go index f8cf52957dc4..5b08de5e5e89 100644 --- a/agent/xds/jwt_authn_ce.go +++ b/agent/xds/jwt_authn_ce.go @@ -8,8 +8,11 @@ package xds import ( envoy_http_jwt_authn_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/jwt_authn/v3" envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" + "google.golang.org/protobuf/proto" + "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/go-hclog" ) type GatewayAuthFilterBuilder struct { @@ -22,3 +25,7 @@ type GatewayAuthFilterBuilder struct { func (g *GatewayAuthFilterBuilder) makeGatewayAuthFilters() ([]*envoy_http_v3.HttpFilter, error) { return nil, nil } + +func makeAPIGatewayJWKClusters(_ hclog.Logger, _ *proxycfg.ConfigSnapshot) []proto.Message { + return nil +} diff --git a/agent/xds/listeners.go b/agent/xds/listeners.go index 7e679bb811be..5b01bdc4dfe2 100644 --- a/agent/xds/listeners.go +++ b/agent/xds/listeners.go @@ -29,6 +29,7 @@ import ( envoy_tcp_proxy_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/tcp_proxy/v3" envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" + "github.com/hashicorp/consul/agent/xds/config" "github.com/hashicorp/consul/agent/xds/naming" "github.com/hashicorp/consul/agent/xds/platform" @@ -120,12 +121,7 @@ func (s *ResourceGenerator) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg. } } - proxyCfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } + proxyCfg := cfgSnap.GetProxyConfig(s.Logger) var tracing *envoy_http_v3.HttpConnectionManager_Tracing if proxyCfg.ListenerTracingJSON != "" { if tracing, err = makeTracingFromUserConfig(proxyCfg.ListenerTracingJSON); err != nil { @@ -180,13 +176,14 @@ func (s *ResourceGenerator) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg. // Generate the upstream listeners for when they are explicitly set with a local bind port or socket path if upstreamCfg != nil && upstreamCfg.HasLocalPortOrSocket() { filterChain, err := s.makeUpstreamFilterChain(filterChainOpts{ - accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: uid.EnvoyID(), - clusterName: clusterName, - filterName: filterName, - protocol: cfg.Protocol, - useRDS: useRDS, - tracing: tracing, + accessLogs: &cfgSnap.Proxy.AccessLogs, + routeName: uid.EnvoyID(), + clusterName: clusterName, + filterName: filterName, + protocol: cfg.Protocol, + useRDS: useRDS, + fetchTimeoutRDS: cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), + tracing: tracing, }) if err != nil { return nil, err @@ -215,13 +212,14 @@ func (s *ResourceGenerator) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg. // as we do for explicit upstreams above. filterChain, err := s.makeUpstreamFilterChain(filterChainOpts{ - accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: uid.EnvoyID(), - clusterName: clusterName, - filterName: filterName, - protocol: cfg.Protocol, - useRDS: useRDS, - tracing: tracing, + accessLogs: &cfgSnap.Proxy.AccessLogs, + routeName: uid.EnvoyID(), + clusterName: clusterName, + filterName: filterName, + protocol: cfg.Protocol, + useRDS: useRDS, + fetchTimeoutRDS: cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), + tracing: tracing, }) if err != nil { return nil, err @@ -298,12 +296,13 @@ func (s *ResourceGenerator) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg. const name = "~http" // name used for the shared route name routeName := clusterNameForDestination(cfgSnap, name, fmt.Sprintf("%d", svcConfig.Destination.Port), svcConfig.NamespaceOrDefault(), svcConfig.PartitionOrDefault()) filterChain, err := s.makeUpstreamFilterChain(filterChainOpts{ - accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: routeName, - filterName: routeName, - protocol: svcConfig.Protocol, - useRDS: true, - tracing: tracing, + accessLogs: &cfgSnap.Proxy.AccessLogs, + routeName: routeName, + filterName: routeName, + protocol: svcConfig.Protocol, + useRDS: true, + fetchTimeoutRDS: cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), + tracing: tracing, }) if err != nil { return err @@ -789,12 +788,8 @@ func parseCheckPath(check structs.CheckType) (structs.ExposePath, error) { // listenersFromSnapshotGateway returns the "listener" for a terminating-gateway or mesh-gateway service func (s *ResourceGenerator) listenersFromSnapshotGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) { - cfg, err := config.ParseGatewayConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } + var err error + cfg := cfgSnap.GetGatewayConfig(s.Logger) // We'll collect all of the desired listeners first, and deduplicate them later. type namedAddress struct { @@ -1139,7 +1134,7 @@ func injectHTTPFilterOnFilterChains( // since TLS validation will be done against root certs for all peers // that might dial this proxy. func (s *ResourceGenerator) injectConnectTLSForPublicListener(cfgSnap *proxycfg.ConfigSnapshot, listener *envoy_listener_v3.Listener) error { - transportSocket, err := createDownstreamTransportSocketForConnectTLS(cfgSnap, cfgSnap.PeeringTrustBundles()) + transportSocket, err := createDownstreamTransportSocketForConnectTLS(cfgSnap, cfgSnap.GetProxyConfig(s.Logger), cfgSnap.PeeringTrustBundles()) if err != nil { return err } @@ -1163,7 +1158,7 @@ func getAlpnProtocols(protocol string) []string { return alpnProtocols } -func createDownstreamTransportSocketForConnectTLS(cfgSnap *proxycfg.ConfigSnapshot, peerBundles []*pbpeering.PeeringTrustBundle) (*envoy_core_v3.TransportSocket, error) { +func createDownstreamTransportSocketForConnectTLS(cfgSnap *proxycfg.ConfigSnapshot, proxyCfg *config.ProxyConfig, peerBundles []*pbpeering.PeeringTrustBundle) (*envoy_core_v3.TransportSocket, error) { switch cfgSnap.Kind { case structs.ServiceKindConnectProxy: case structs.ServiceKindMeshGateway: @@ -1171,10 +1166,6 @@ func createDownstreamTransportSocketForConnectTLS(cfgSnap *proxycfg.ConfigSnapsh return nil, fmt.Errorf("cannot inject peering trust bundles for kind %q", cfgSnap.Kind) } - // Determine listener protocol type from configured service protocol. Don't hard fail on a config typo, - //The parse func returns default config if there is an error, so it's safe to continue. - cfg, _ := config.ParseProxyConfig(cfgSnap.Proxy.Config) - // Create TLS validation context for mTLS with leaf certificate and root certs. tlsContext := makeCommonTLSContext( cfgSnap.Leaf(), @@ -1184,33 +1175,13 @@ func createDownstreamTransportSocketForConnectTLS(cfgSnap *proxycfg.ConfigSnapsh if tlsContext != nil { // Configure alpn protocols on CommonTLSContext - tlsContext.AlpnProtocols = getAlpnProtocols(cfg.Protocol) + tlsContext.AlpnProtocols = getAlpnProtocols(proxyCfg.Protocol) } // Inject peering trust bundles if this service is exported to peered clusters. - if len(peerBundles) > 0 { - spiffeConfig, err := makeSpiffeValidatorConfig( - cfgSnap.Roots.TrustDomain, - cfgSnap.RootPEMs(), - peerBundles, - ) - if err != nil { - return nil, err - } - - typ, ok := tlsContext.ValidationContextType.(*envoy_tls_v3.CommonTlsContext_ValidationContext) - if !ok { - return nil, fmt.Errorf("unexpected type for TLS context validation: %T", tlsContext.ValidationContextType) - } - - // makeCommonTLSFromLead injects the local trust domain's CA root certs as the TrustedCA. - // We nil it out here since the local roots are included in the SPIFFE validator config. - typ.ValidationContext.TrustedCa = nil - typ.ValidationContext.CustomValidatorConfig = &envoy_core_v3.TypedExtensionConfig{ - // The typed config name is hard-coded because it is not available as a wellknown var in the control plane lib. - Name: "envoy.tls.cert_validator.spiffe", - TypedConfig: spiffeConfig, - } + err := injectSpiffeValidatorConfigForPeers(cfgSnap, tlsContext, peerBundles) + if err != nil { + return nil, err } return makeDownstreamTLSTransportSocket(&envoy_tls_v3.DownstreamTlsContext{ @@ -1219,6 +1190,32 @@ func createDownstreamTransportSocketForConnectTLS(cfgSnap *proxycfg.ConfigSnapsh }) } +func injectSpiffeValidatorConfigForPeers(cfgSnap *proxycfg.ConfigSnapshot, tlsContext *envoy_tls_v3.CommonTlsContext, peerBundles []*pbpeering.PeeringTrustBundle) error { + if len(peerBundles) == 0 { + return nil + } + + spiffeConfig, err := makeSpiffeValidatorConfig(cfgSnap.Roots.TrustDomain, cfgSnap.RootPEMs(), peerBundles) + if err != nil { + return err + } + + typ, ok := tlsContext.ValidationContextType.(*envoy_tls_v3.CommonTlsContext_ValidationContext) + if !ok { + return fmt.Errorf("unexpected type for TLS context validation: %T", tlsContext.ValidationContextType) + } + + // makeCommonTLSFromLead injects the local trust domain's CA root certs as the TrustedCA. + // We nil it out here since the local roots are included in the SPIFFE validator config. + typ.ValidationContext.TrustedCa = nil + typ.ValidationContext.CustomValidatorConfig = &envoy_core_v3.TypedExtensionConfig{ + // The typed config name is hard-coded because it is not available as a wellknown var in the control plane lib. + Name: "envoy.tls.cert_validator.spiffe", + TypedConfig: spiffeConfig, + } + return nil +} + // SPIFFECertValidatorConfig is used to validate certificates from trust domains other than our own. // With cluster peering we expect peered clusters to have independent certificate authorities. // This means that we cannot use a single set of root CA certificates to validate client certificates for mTLS, @@ -1265,13 +1262,7 @@ func (s *ResourceGenerator) makeInboundListener(cfgSnap *proxycfg.ConfigSnapshot var l *envoy_listener_v3.Listener var err error - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - + cfg := cfgSnap.GetProxyConfig(s.Logger) // This controls if we do L4 or L7 intention checks. useHTTPFilter := structs.IsProtocolHTTPLike(cfg.Protocol) @@ -1405,6 +1396,7 @@ func (s *ResourceGenerator) makeInboundListener(cfgSnap *proxycfg.ConfigSnapshot filterOpts.httpAuthzFilters = append(filterOpts.httpAuthzFilters, addMeta) } + setNormalizationOptions(cfgSnap.MeshConfig().GetHTTPIncomingRequestNormalization(), &filterOpts) } // If an inbound connect limit is set, inject a connection limit filter on each chain. @@ -1473,6 +1465,28 @@ func (s *ResourceGenerator) makeInboundListener(cfgSnap *proxycfg.ConfigSnapshot return l, err } +// setNormalizationOptions sets the normalization options for the listener filter. +// This is only used for inbound listeners today (see MeshHTTPConfig). +func setNormalizationOptions(rn *structs.RequestNormalizationMeshConfig, opts *listenerFilterOpts) { + // Note that these options are _always_ set, not just when rn is non-nil. This enables us to set + // Consul defaults (e.g. InsecureDisablePathNormalization = false) that override Envoy defaults + // (e.g. normalize_path = false). We override defaults here rather than in xDS code s.t. Consul + // defaults are only applied where Consul configuration dictates it should be. + + opts.normalizePath = !rn.GetInsecureDisablePathNormalization() // invert to enable path normalization by default + opts.mergeSlashes = rn.GetMergeSlashes() + if rn.GetPathWithEscapedSlashesAction() != "" { + v := string(rn.GetPathWithEscapedSlashesAction()) + a := envoy_http_v3.HttpConnectionManager_PathWithEscapedSlashesAction_value[v] + opts.pathWithEscapedSlashesAction = envoy_http_v3.HttpConnectionManager_PathWithEscapedSlashesAction(a) + } + if rn.GetHeadersWithUnderscoresAction() != "" { + v := string(rn.GetHeadersWithUnderscoresAction()) + a := envoy_core_v3.HttpProtocolOptions_HeadersWithUnderscoresAction_value[v] + opts.headersWithUnderscoresAction = envoy_core_v3.HttpProtocolOptions_HeadersWithUnderscoresAction(a) + } +} + func makePermissiveFilterChain(cfgSnap *proxycfg.ConfigSnapshot, opts listenerFilterOpts) (*envoy_listener_v3.FilterChain, error) { servicePort := cfgSnap.Proxy.LocalServicePort if servicePort <= 0 { @@ -1515,16 +1529,10 @@ func (s *ResourceGenerator) finalizePublicListenerFromConfig(l *envoy_listener_v } func (s *ResourceGenerator) makeExposedCheckListener(cfgSnap *proxycfg.ConfigSnapshot, cluster string, path structs.ExposePath) (proto.Message, error) { - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - // No user config, use default listener addr := cfgSnap.Address + cfg := cfgSnap.GetProxyConfig(s.Logger) // Override with bind address if one is set, otherwise default to 0.0.0.0 if cfg.BindAddress != "" { addr = cfg.BindAddress @@ -1774,6 +1782,9 @@ type terminatingGatewayFilterChainOpts struct { } func (s *ResourceGenerator) makeFilterChainTerminatingGateway(cfgSnap *proxycfg.ConfigSnapshot, tgtwyOpts terminatingGatewayFilterChainOpts) (*envoy_listener_v3.FilterChain, error) { + // We need to at least match the SNI and use the root PEMs from the local cluster + sniMatches := []string{tgtwyOpts.cluster} + tlsContext := &envoy_tls_v3.DownstreamTlsContext{ CommonTlsContext: makeCommonTLSContext( cfgSnap.TerminatingGateway.ServiceLeaves[tgtwyOpts.service], @@ -1782,13 +1793,29 @@ func (s *ResourceGenerator) makeFilterChainTerminatingGateway(cfgSnap *proxycfg. ), RequireClientCertificate: &wrapperspb.BoolValue{Value: true}, } + + // For TCP connections, TLS is not terminated at the mesh gateway but is instead proxied through; + // therefore, we need to account for callers from other datacenters when setting up our filter chain. + if tgtwyOpts.protocol == "tcp" { + for _, bundle := range tgtwyOpts.peerTrustBundles { + svc := tgtwyOpts.service + sourceSNI := connect.PeeredServiceSNI(svc.Name, svc.NamespaceOrDefault(), svc.PartitionOrDefault(), bundle.PeerName, cfgSnap.Roots.TrustDomain) + sniMatches = append(sniMatches, sourceSNI) + } + + err := injectSpiffeValidatorConfigForPeers(cfgSnap, tlsContext.CommonTlsContext, tgtwyOpts.peerTrustBundles) + if err != nil { + return nil, err + } + } + transportSocket, err := makeDownstreamTLSTransportSocket(tlsContext) if err != nil { return nil, err } filterChain := &envoy_listener_v3.FilterChain{ - FilterChainMatch: makeSNIFilterChainMatch(tgtwyOpts.cluster), + FilterChainMatch: makeSNIFilterChainMatch(sniMatches...), Filters: make([]*envoy_listener_v3.Filter, 0, 3), TransportSocket: transportSocket, } @@ -1814,12 +1841,7 @@ func (s *ResourceGenerator) makeFilterChainTerminatingGateway(cfgSnap *proxycfg. filterChain.Filters = append(filterChain.Filters, authFilter) } - proxyCfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } + proxyCfg := cfgSnap.GetProxyConfig(s.Logger) var tracing *envoy_http_v3.HttpConnectionManager_Tracing if proxyCfg.ListenerTracingJSON != "" { if tracing, err = makeTracingFromUserConfig(proxyCfg.ListenerTracingJSON); err != nil { @@ -1863,6 +1885,7 @@ func (s *ResourceGenerator) makeFilterChainTerminatingGateway(cfgSnap *proxycfg. opts.cluster = "" opts.useRDS = true + opts.fetchTimeoutRDS = cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout() if meshConfig := cfgSnap.MeshConfig(); meshConfig == nil || meshConfig.HTTP == nil || !meshConfig.HTTP.SanitizeXForwardedClientCert { opts.forwardClientDetails = true @@ -2148,6 +2171,7 @@ func (s *ResourceGenerator) makeMeshGatewayPeerFilterChain( filterName: filterName, protocol: chain.Protocol, useRDS: useRDS, + fetchTimeoutRDS: cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), statPrefix: "mesh_gateway_local_peered.", forwardClientDetails: true, forwardClientPolicy: envoy_http_v3.HttpConnectionManager_SANITIZE_SET, @@ -2180,7 +2204,7 @@ func (s *ResourceGenerator) makeMeshGatewayPeerFilterChain( } } - peeredTransportSocket, err := createDownstreamTransportSocketForConnectTLS(cfgSnap, peerBundles) + peeredTransportSocket, err := createDownstreamTransportSocketForConnectTLS(cfgSnap, cfgSnap.GetProxyConfig(s.Logger), peerBundles) if err != nil { return nil, err } @@ -2197,6 +2221,7 @@ type filterChainOpts struct { filterName string protocol string useRDS bool + fetchTimeoutRDS *durationpb.Duration tlsContext *envoy_tls_v3.DownstreamTlsContext statPrefix string forwardClientDetails bool @@ -2210,6 +2235,7 @@ func (s *ResourceGenerator) makeUpstreamFilterChain(opts filterChainOpts) (*envo } filter, err := makeListenerFilter(listenerFilterOpts{ useRDS: opts.useRDS, + fetchTimeoutRDS: opts.fetchTimeoutRDS, protocol: opts.protocol, filterName: opts.filterName, routeName: opts.routeName, @@ -2362,15 +2388,20 @@ type listenerFilterOpts struct { statPrefix string // HTTP listener filter options - forwardClientDetails bool - forwardClientPolicy envoy_http_v3.HttpConnectionManager_ForwardClientCertDetails - httpAuthzFilters []*envoy_http_v3.HttpFilter - idleTimeoutMs *int - requestTimeoutMs *int - routeName string - routePath string - tracing *envoy_http_v3.HttpConnectionManager_Tracing - useRDS bool + forwardClientDetails bool + forwardClientPolicy envoy_http_v3.HttpConnectionManager_ForwardClientCertDetails + httpAuthzFilters []*envoy_http_v3.HttpFilter + idleTimeoutMs *int + requestTimeoutMs *int + routeName string + routePath string + tracing *envoy_http_v3.HttpConnectionManager_Tracing + normalizePath bool + mergeSlashes bool + pathWithEscapedSlashesAction envoy_http_v3.HttpConnectionManager_PathWithEscapedSlashesAction + headersWithUnderscoresAction envoy_core_v3.HttpProtocolOptions_HeadersWithUnderscoresAction + useRDS bool + fetchTimeoutRDS *durationpb.Duration } func makeListenerFilter(opts listenerFilterOpts) (*envoy_listener_v3.Filter, error) { @@ -2486,6 +2517,19 @@ func makeHTTPFilter(opts listenerFilterOpts) (*envoy_listener_v3.Filter, error) cfg.Tracing = opts.tracing } + // Request normalization + if opts.normalizePath { + cfg.NormalizePath = &wrapperspb.BoolValue{Value: true} + } + cfg.MergeSlashes = opts.mergeSlashes + cfg.PathWithEscapedSlashesAction = opts.pathWithEscapedSlashesAction + if opts.headersWithUnderscoresAction != 0 { // check for non-default to avoid needless instantiation of options + if cfg.CommonHttpProtocolOptions == nil { + cfg.CommonHttpProtocolOptions = &envoy_core_v3.HttpProtocolOptions{} + } + cfg.CommonHttpProtocolOptions.HeadersWithUnderscoresAction = opts.headersWithUnderscoresAction + } + if opts.useRDS { if opts.cluster != "" { return nil, fmt.Errorf("cannot specify cluster name when using RDS") @@ -2494,7 +2538,8 @@ func makeHTTPFilter(opts listenerFilterOpts) (*envoy_listener_v3.Filter, error) Rds: &envoy_http_v3.Rds{ RouteConfigName: opts.routeName, ConfigSource: &envoy_core_v3.ConfigSource{ - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, + InitialFetchTimeout: opts.fetchTimeoutRDS, + ResourceApiVersion: envoy_core_v3.ApiVersion_V3, ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_Ads{ Ads: &envoy_core_v3.AggregatedConfigSource{}, }, diff --git a/agent/xds/listeners_apigateway.go b/agent/xds/listeners_apigateway.go index 771a48297203..34c5d18261ab 100644 --- a/agent/xds/listeners_apigateway.go +++ b/agent/xds/listeners_apigateway.go @@ -6,22 +6,19 @@ package xds import ( "fmt" - "golang.org/x/exp/maps" - envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_http_jwt_authn_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/jwt_authn/v3" envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" - - "github.com/hashicorp/consul/agent/consul/discoverychain" - "github.com/hashicorp/consul/agent/xds/naming" - + "golang.org/x/exp/maps" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/wrapperspb" + "github.com/hashicorp/consul/agent/consul/discoverychain" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/agent/xds/naming" "github.com/hashicorp/consul/types" ) @@ -35,13 +32,19 @@ func (s *ResourceGenerator) makeAPIGatewayListeners(address string, cfgSnap *pro listenerKey := readyListener.listenerKey boundListener := readyListener.boundListenerCfg - var certs []structs.InlineCertificateConfigEntry + // Collect the referenced certificate config entries + var certs []structs.ConfigEntry for _, certRef := range boundListener.Certificates { - cert, ok := cfgSnap.APIGateway.Certificates.Get(certRef) - if !ok { - continue + switch certRef.Kind { + case structs.InlineCertificate: + if cert, ok := cfgSnap.APIGateway.InlineCertificates.Get(certRef); ok { + certs = append(certs, cert) + } + case structs.FileSystemCertificate: + if cert, ok := cfgSnap.APIGateway.FileSystemCertificates.Get(certRef); ok { + certs = append(certs, cert) + } } - certs = append(certs, *cert) } isAPIGatewayWithTLS := len(boundListener.Certificates) > 0 @@ -93,13 +96,14 @@ func (s *ResourceGenerator) makeAPIGatewayListeners(address string, cfgSnap *pro l := makeListener(opts) filterChain, err := s.makeUpstreamFilterChain(filterChainOpts{ - accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: uid.EnvoyID(), - useRDS: useRDS, - clusterName: clusterName, - filterName: filterName, - protocol: cfg.Protocol, - tlsContext: tlsContext, + accessLogs: &cfgSnap.Proxy.AccessLogs, + routeName: uid.EnvoyID(), + useRDS: useRDS, + fetchTimeoutRDS: cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), + clusterName: clusterName, + filterName: filterName, + protocol: cfg.Protocol, + tlsContext: tlsContext, }) if err != nil { return nil, err @@ -110,18 +114,19 @@ func (s *ResourceGenerator) makeAPIGatewayListeners(address string, cfgSnap *pro if isAPIGatewayWithTLS { // construct SNI filter chains - l.FilterChains, err = makeInlineOverrideFilterChains( + l.FilterChains, err = s.makeInlineOverrideFilterChains( cfgSnap, cfgSnap.APIGateway.TLSConfig, listenerKey.Protocol, listenerFilterOpts{ - useRDS: useRDS, - protocol: listenerKey.Protocol, - routeName: listenerKey.RouteName(), - cluster: clusterName, - statPrefix: "ingress_upstream_", - accessLogs: &cfgSnap.Proxy.AccessLogs, - logger: s.Logger, + useRDS: useRDS, + fetchTimeoutRDS: cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), + protocol: listenerKey.Protocol, + routeName: listenerKey.RouteName(), + cluster: clusterName, + statPrefix: "ingress_upstream_", + accessLogs: &cfgSnap.Proxy.AccessLogs, + logger: s.Logger, }, certs, ) @@ -206,6 +211,7 @@ func (s *ResourceGenerator) makeAPIGatewayListeners(address string, cfgSnap *pro filterOpts := listenerFilterOpts{ useRDS: true, + fetchTimeoutRDS: cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), protocol: listenerKey.Protocol, filterName: listenerKey.RouteName(), routeName: listenerKey.RouteName(), @@ -222,7 +228,7 @@ func (s *ResourceGenerator) makeAPIGatewayListeners(address string, cfgSnap *pro sniFilterChains := []*envoy_listener_v3.FilterChain{} if isAPIGatewayWithTLS { - sniFilterChains, err = makeInlineOverrideFilterChains(cfgSnap, cfgSnap.IngressGateway.TLSConfig, listenerKey.Protocol, filterOpts, certs) + sniFilterChains, err = s.makeInlineOverrideFilterChains(cfgSnap, cfgSnap.IngressGateway.TLSConfig, listenerKey.Protocol, filterOpts, certs) if err != nil { return nil, err } @@ -390,11 +396,11 @@ func resolveAPIListenerTLSConfig(listenerTLSCfg structs.APIGatewayTLSConfigurati // when we have multiple certificates on a single listener, we need // to duplicate the filter chains with multiple TLS contexts -func makeInlineOverrideFilterChains(cfgSnap *proxycfg.ConfigSnapshot, +func (s *ResourceGenerator) makeInlineOverrideFilterChains(cfgSnap *proxycfg.ConfigSnapshot, tlsCfg structs.GatewayTLSConfig, protocol string, filterOpts listenerFilterOpts, - certs []structs.InlineCertificateConfigEntry, + certs []structs.ConfigEntry, ) ([]*envoy_listener_v3.FilterChain, error) { var chains []*envoy_listener_v3.FilterChain @@ -435,50 +441,72 @@ func makeInlineOverrideFilterChains(cfgSnap *proxycfg.ConfigSnapshot, // we only need to prune out overlapping hosts if we have more than // one certificate for _, cert := range certs { - hosts, err := cert.Hosts() - if err != nil { - return nil, fmt.Errorf("unable to parse hosts from x509 certificate: %v", hosts) - } - for _, host := range hosts { - if _, ok := allCertHosts[host]; ok { - overlappingHosts[host] = struct{}{} + switch tce := cert.(type) { + case *structs.InlineCertificateConfigEntry: + hosts, err := tce.Hosts() + if err != nil { + return nil, fmt.Errorf("unable to parse hosts from x509 certificate: %v", hosts) + } + for _, host := range hosts { + if _, ok := allCertHosts[host]; ok { + overlappingHosts[host] = struct{}{} + } + allCertHosts[host] = struct{}{} } - allCertHosts[host] = struct{}{} + default: + // do nothing for FileSystemCertificates because we don't actually have the certificate available } } } + constructTLSContext := func(certConfig structs.ConfigEntry) (*envoy_tls_v3.CommonTlsContext, error) { + switch tce := certConfig.(type) { + case *structs.InlineCertificateConfigEntry: + return makeInlineTLSContextFromGatewayTLSConfig(tlsCfg, tce), nil + case *structs.FileSystemCertificateConfigEntry: + return makeFileSystemTLSContextFromGatewayTLSConfig(tlsCfg, tce), nil + default: + return nil, fmt.Errorf("unsupported config entry kind %s", tce.GetKind()) + } + } + for _, cert := range certs { var hosts []string // if we only have one cert, we just use it for all ingress if multipleCerts { - // otherwise, we need an SNI per cert and to fallback to our ingress - // gateway certificate signed by our Consul CA - certHosts, err := cert.Hosts() - if err != nil { - return nil, fmt.Errorf("unable to parse hosts from x509 certificate: %v", hosts) - } - // filter out any overlapping hosts so we don't have collisions in our filter chains - for _, host := range certHosts { - if _, ok := overlappingHosts[host]; !ok { - hosts = append(hosts, host) + switch tce := cert.(type) { + case *structs.InlineCertificateConfigEntry: + certHosts, err := tce.Hosts() + if err != nil { + return nil, fmt.Errorf("unable to parse hosts from x509 certificate: %v", hosts) + } + // filter out any overlapping hosts so we don't have collisions in our filter chains + for _, host := range certHosts { + if _, ok := overlappingHosts[host]; !ok { + hosts = append(hosts, host) + } } - } - if len(hosts) == 0 { - // all of our hosts are overlapping, so we just skip this filter and it'll be - // handled by the default filter chain - continue + if len(hosts) == 0 { + // all of our hosts are overlapping, so we just skip this filter and it'll be + // handled by the default filter chain + continue + } } } - if err := constructChain(cert.Name, hosts, makeInlineTLSContextFromGatewayTLSConfig(tlsCfg, cert)); err != nil { + tlsContext, err := constructTLSContext(cert) + if err != nil { + continue + } + + if err := constructChain(cert.GetName(), hosts, tlsContext); err != nil { return nil, err } } - if multipleCerts { + if len(certs) > 1 { // if we have more than one cert, add a default handler that uses the leaf cert from connect if err := constructChain("default", nil, makeCommonTLSContext(cfgSnap.Leaf(), cfgSnap.RootPEMs(), makeTLSParametersFromGatewayTLSConfig(tlsCfg))); err != nil { return nil, err diff --git a/agent/xds/listeners_ingress.go b/agent/xds/listeners_ingress.go index e5e5a4980c41..76659b87d7eb 100644 --- a/agent/xds/listeners_ingress.go +++ b/agent/xds/listeners_ingress.go @@ -9,7 +9,6 @@ import ( envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" - "github.com/hashicorp/consul/agent/xds/naming" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/durationpb" @@ -17,13 +16,13 @@ import ( "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/agent/xds/naming" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/types" ) func (s *ResourceGenerator) makeIngressGatewayListeners(address string, cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) { var resources []proto.Message - for listenerKey, upstreams := range cfgSnap.IngressGateway.Upstreams { listenerCfg, ok := cfgSnap.IngressGateway.Listeners[listenerKey] if !ok { @@ -79,13 +78,14 @@ func (s *ResourceGenerator) makeIngressGatewayListeners(address string, cfgSnap l := makeListener(opts) filterChain, err := s.makeUpstreamFilterChain(filterChainOpts{ - accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: uid.EnvoyID(), - useRDS: useRDS, - clusterName: clusterName, - filterName: filterName, - protocol: cfg.Protocol, - tlsContext: tlsContext, + accessLogs: &cfgSnap.Proxy.AccessLogs, + routeName: uid.EnvoyID(), + useRDS: useRDS, + fetchTimeoutRDS: cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), + clusterName: clusterName, + filterName: filterName, + protocol: cfg.Protocol, + tlsContext: tlsContext, }) if err != nil { return nil, err @@ -110,6 +110,7 @@ func (s *ResourceGenerator) makeIngressGatewayListeners(address string, cfgSnap filterOpts := listenerFilterOpts{ useRDS: true, + fetchTimeoutRDS: cfgSnap.GetXDSCommonConfig(s.Logger).GetXDSFetchTimeout(), protocol: listenerKey.Protocol, filterName: listenerKey.RouteName(), routeName: listenerKey.RouteName(), @@ -390,7 +391,26 @@ func makeTLSParametersFromGatewayTLSConfig(tlsCfg structs.GatewayTLSConfig) *env return makeTLSParametersFromTLSConfig(tlsCfg.TLSMinVersion, tlsCfg.TLSMaxVersion, tlsCfg.CipherSuites) } -func makeInlineTLSContextFromGatewayTLSConfig(tlsCfg structs.GatewayTLSConfig, cert structs.InlineCertificateConfigEntry) *envoy_tls_v3.CommonTlsContext { +func makeFileSystemTLSContextFromGatewayTLSConfig(tlsCfg structs.GatewayTLSConfig, cert *structs.FileSystemCertificateConfigEntry) *envoy_tls_v3.CommonTlsContext { + return &envoy_tls_v3.CommonTlsContext{ + TlsParams: makeTLSParametersFromGatewayTLSConfig(tlsCfg), + TlsCertificateSdsSecretConfigs: []*envoy_tls_v3.SdsSecretConfig{ + { + // Delivering via SDS is required in order to get file system watches today. + // https://github.com/envoyproxy/envoy/issues/10387 + Name: cert.Name, // Reference the secret returned in xds/secrets.go by name here + SdsConfig: &envoy_core_v3.ConfigSource{ + ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_Ads{ + Ads: &envoy_core_v3.AggregatedConfigSource{}, + }, + ResourceApiVersion: envoy_core_v3.ApiVersion_V3, + }, + }, + }, + } +} + +func makeInlineTLSContextFromGatewayTLSConfig(tlsCfg structs.GatewayTLSConfig, cert *structs.InlineCertificateConfigEntry) *envoy_tls_v3.CommonTlsContext { return &envoy_tls_v3.CommonTlsContext{ TlsParams: makeTLSParametersFromGatewayTLSConfig(tlsCfg), TlsCertificates: []*envoy_tls_v3.TlsCertificate{{ diff --git a/agent/xds/listeners_test.go b/agent/xds/listeners_test.go index dfe088f57787..757310fc3c16 100644 --- a/agent/xds/listeners_test.go +++ b/agent/xds/listeners_test.go @@ -5,1416 +5,20 @@ package xds import ( "bytes" - "path/filepath" - "sort" "testing" "text/template" - "github.com/stretchr/testify/assert" - "google.golang.org/protobuf/proto" - - envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" + envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" testinf "github.com/mitchellh/go-testing-interface" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/configfetcher" - "github.com/hashicorp/consul/agent/xds/proxystateconverter" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/agent/xds/testcommon" - "github.com/hashicorp/consul/agent/xdsv2" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/proto/private/pbpeering" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/types" ) -type listenerTestCase struct { - name string - create func(t testinf.T) *proxycfg.ConfigSnapshot - // Setup is called before the test starts. It is passed the snapshot from - // TestConfigSnapshot and is allowed to modify it in any way to setup the - // test input. - overrideGoldenName string - generatorSetup func(*ResourceGenerator) - alsoRunTestForV2 bool -} - -func makeListenerDiscoChainTests(enterprise bool) []listenerTestCase { - return []listenerTestCase{ - { - name: "custom-upstream-ignored-with-disco-chain", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover", enterprise, func(ns *structs.NodeService) { - for i := range ns.Proxy.Upstreams { - if ns.Proxy.Upstreams[i].DestinationName != "db" { - continue // only tweak the db upstream - } - if ns.Proxy.Upstreams[i].Config == nil { - ns.Proxy.Upstreams[i].Config = map[string]interface{}{} - } - - uid := proxycfg.NewUpstreamID(&ns.Proxy.Upstreams[i]) - - ns.Proxy.Upstreams[i].Config["envoy_listener_json"] = - customListenerJSON(t, customListenerJSONOptions{ - Name: uid.EnvoyID() + ":custom-upstream", - }) - } - }, nil) - }, - }, - { - name: "splitter-with-resolver-redirect", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-with-resolver-redirect-multidc", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tcp-chain", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-http-chain", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil, - &structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, - Config: map[string]interface{}{ - "protocol": "http", - }, - }, - ) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-http2-chain", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil, - &structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, - Config: map[string]interface{}{ - "protocol": "http2", - }, - }, - ) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-grpc-chain", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil, - &structs.ProxyConfigEntry{ - Kind: structs.ProxyDefaults, - Name: structs.ProxyConfigGlobal, - Config: map[string]interface{}{ - "protocol": "grpc", - }, - }, - ) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-chain-and-overrides", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple-with-overrides", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tcp-chain-failover-through-local-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-jwt-config-entry-with-local", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, func(ns *structs.NodeService) { - ns.Proxy.Config["protocol"] = "http" - }, - []proxycfg.UpdateEvent{ - { - CorrelationID: "jwt-provider", - Result: &structs.IndexedConfigEntries{ - Kind: "jwt-provider", - Entries: []structs.ConfigEntry{ - &structs.JWTProviderConfigEntry{ - Name: "okta", - JSONWebKeySet: &structs.JSONWebKeySet{ - Local: &structs.LocalJWKS{ - JWKS: "aGVsbG8gd29ybGQK", - }, - }, - Locations: []*structs.JWTLocation{ - { - QueryParam: &structs.JWTLocationQueryParam{ - Name: "token", - }, - }, - { - Cookie: &structs.JWTLocationCookie{ - Name: "token", - }, - }, - }, - }, - }, - }, - }, - { - CorrelationID: "intentions", - Result: structs.SimplifiedIntentions{ - { - SourceName: "*", - DestinationName: "db", - Permissions: []*structs.IntentionPermission{ - { - JWT: &structs.IntentionJWTRequirement{ - Providers: []*structs.IntentionJWTProvider{ - { - Name: "okta", - }, - }, - }, - }, - }, - }, - }, - }, - }, - ) - }, - }, - } -} - -func TestListenersFromSnapshot(t *testing.T) { - // TODO: we should move all of these to TestAllResourcesFromSnapshot - // eventually to test all of the xDS types at once with the same input, - // just as it would be triggered by our xDS server. - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - tests := []listenerTestCase{ - { - name: "connect-proxy-with-tls-outgoing-min-version-auto", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Outgoing: &structs.MeshDirectionalTLSConfig{ - TLSMinVersion: types.TLSVersionAuto, - }, - }, - }, - }, - }, - }) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tls-incoming-min-version", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Incoming: &structs.MeshDirectionalTLSConfig{ - TLSMinVersion: types.TLSv1_3, - }, - }, - }, - }, - }, - }) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tls-incoming-max-version", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Incoming: &structs.MeshDirectionalTLSConfig{ - TLSMaxVersion: types.TLSv1_2, - }, - }, - }, - }, - }, - }) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-tls-incoming-cipher-suites", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Incoming: &structs.MeshDirectionalTLSConfig{ - CipherSuites: []types.TLSCipherSuite{ - types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - }, - }, - }, - }, - }, - }, - }) - }, - alsoRunTestForV2: true, - }, - { - name: "grpc-public-listener", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["protocol"] = "grpc" - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "listener-bind-address", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["bind_address"] = "127.0.0.2" - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "listener-bind-port", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["bind_port"] = 8888 - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "listener-bind-address-port", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["bind_address"] = "127.0.0.2" - ns.Proxy.Config["bind_port"] = 8888 - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "listener-unix-domain-socket", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Upstreams[0].LocalBindAddress = "" - ns.Proxy.Upstreams[0].LocalBindPort = 0 - ns.Proxy.Upstreams[0].LocalBindSocketPath = "/tmp/service-mesh/client-1/grpc-employee-server" - ns.Proxy.Upstreams[0].LocalBindSocketMode = "0640" - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "listener-max-inbound-connections", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["max_inbound_connections"] = 222 - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "http2-public-listener", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["protocol"] = "http2" - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "listener-balance-inbound-connections", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["balance_inbound_connections"] = "exact_balance" - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "listener-balance-outbound-connections-bind-port", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Upstreams[0].Config["balance_outbound_connections"] = "exact_balance" - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "http-public-listener", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["protocol"] = "http" - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "http-public-listener-no-xfcc", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, - func(ns *structs.NodeService) { - ns.Proxy.Config["protocol"] = "http" - }, - []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - HTTP: &structs.MeshHTTPConfig{ - SanitizeXForwardedClientCert: true, - }, - }, - }, - }, - }) - }, - alsoRunTestForV2: true, - }, - { - name: "http-listener-with-timeouts", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["protocol"] = "http" - ns.Proxy.Config["local_connect_timeout_ms"] = 1234 - ns.Proxy.Config["local_request_timeout_ms"] = 2345 - ns.Proxy.Config["local_idle_timeout_ms"] = 3456 - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "http-upstream", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Upstreams[0].Config["protocol"] = "http" - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "custom-public-listener", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["envoy_public_listener_json"] = - customListenerJSON(t, customListenerJSONOptions{ - Name: "custom-public-listen", - }) - }, nil) - }, - }, - { - name: "custom-public-listener-http", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["protocol"] = "http" - ns.Proxy.Config["envoy_public_listener_json"] = - customHTTPListenerJSON(t, customHTTPListenerJSONOptions{ - Name: "custom-public-listen", - }) - }, nil) - }, - }, - { - name: "custom-public-listener-http-2", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["protocol"] = "http" - ns.Proxy.Config["envoy_public_listener_json"] = - customHTTPListenerJSON(t, customHTTPListenerJSONOptions{ - Name: "custom-public-listen", - HTTPConnectionManagerName: httpConnectionManagerNewName, - }) - }, nil) - }, - }, - { - name: "custom-public-listener-http-missing", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["protocol"] = "http" - ns.Proxy.Config["envoy_public_listener_json"] = - customListenerJSON(t, customListenerJSONOptions{ - Name: "custom-public-listen", - }) - }, nil) - }, - }, - { - name: "custom-public-listener-ignores-tls", - overrideGoldenName: "custom-public-listener", // should be the same - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["envoy_public_listener_json"] = - customListenerJSON(t, customListenerJSONOptions{ - Name: "custom-public-listen", - // Attempt to override the TLS context should be ignored - TLSContext: `"allowRenegotiation": false`, - }) - }, nil) - }, - }, - { - name: "custom-upstream", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - for i := range ns.Proxy.Upstreams { - if ns.Proxy.Upstreams[i].DestinationName != "db" { - continue // only tweak the db upstream - } - if ns.Proxy.Upstreams[i].Config == nil { - ns.Proxy.Upstreams[i].Config = map[string]interface{}{} - } - - uid := proxycfg.NewUpstreamID(&ns.Proxy.Upstreams[i]) - - ns.Proxy.Upstreams[i].Config["envoy_listener_json"] = - customListenerJSON(t, customListenerJSONOptions{ - Name: uid.EnvoyID() + ":custom-upstream", - }) - } - }, nil) - }, - }, - { - name: "custom-upstream-with-prepared-query", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - for i := range ns.Proxy.Upstreams { - if ns.Proxy.Upstreams[i].DestinationName != "db" { - continue // only tweak the db upstream - } - if ns.Proxy.Upstreams[i].Config == nil { - ns.Proxy.Upstreams[i].Config = map[string]interface{}{} - } - - uid := proxycfg.NewUpstreamID(&ns.Proxy.Upstreams[i]) - - // Triggers an override with the presence of the escape hatch listener - ns.Proxy.Upstreams[i].DestinationType = structs.UpstreamDestTypePreparedQuery - - ns.Proxy.Upstreams[i].Config["envoy_listener_json"] = - customListenerJSON(t, customListenerJSONOptions{ - Name: uid.EnvoyID() + ":custom-upstream", - }) - } - }, nil) - }, - }, - { - name: "connect-proxy-upstream-defaults", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - for _, v := range ns.Proxy.Upstreams { - // Prepared queries do not get centrally configured upstream defaults merged into them. - if v.DestinationType == structs.UpstreamDestTypePreparedQuery { - continue - } - // Represent upstream config as if it came from centrally configured upstream defaults. - // The name/namespace must not make it onto the cluster name attached to the outbound listener. - v.CentrallyConfigured = true - v.DestinationNamespace = structs.WildcardSpecifier - v.DestinationName = structs.WildcardSpecifier - } - }, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "expose-paths-local-app-paths", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotExposeConfig(t, nil) - }, - }, - { - name: "expose-paths-new-cluster-http2", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotExposeConfig(t, func(ns *structs.NodeService) { - ns.Proxy.Expose.Paths[1] = structs.ExposePath{ - LocalPathPort: 9090, - Path: "/grpc.health.v1.Health/Check", - ListenerPort: 21501, - Protocol: "http2", - } - }) - }, - }, - { - // NOTE: if IPv6 is not supported in the kernel per - // platform.SupportsIPv6() then this test will fail because the golden - // files were generated assuming ipv6 support was present - name: "expose-checks-http", - create: proxycfg.TestConfigSnapshotExposeChecks, - generatorSetup: func(s *ResourceGenerator) { - s.CfgFetcher = configFetcherFunc(func() string { - return "192.0.2.1" - }) - }, - }, - { - // NOTE: if IPv6 is not supported in the kernel per - // platform.SupportsIPv6() then this test will fail because the golden - // files were generated assuming ipv6 support was present - name: "expose-checks-http-with-bind-override", - create: proxycfg.TestConfigSnapshotExposeChecksWithBindOverride, - generatorSetup: func(s *ResourceGenerator) { - s.CfgFetcher = configFetcherFunc(func() string { - return "192.0.2.1" - }) - }, - }, - { - // NOTE: if IPv6 is not supported in the kernel per - // platform.SupportsIPv6() then this test will fail because the golden - // files were generated assuming ipv6 support was present - name: "expose-checks-grpc", - create: proxycfg.TestConfigSnapshotExposeChecksGRPC, - generatorSetup: func(s *ResourceGenerator) { - s.CfgFetcher = configFetcherFunc(func() string { - return "192.0.2.1" - }) - }, - }, - { - name: "mesh-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "default", nil, nil) - }, - }, - { - name: "mesh-gateway-using-federation-states", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "federation-states", nil, nil) - }, - }, - { - name: "mesh-gateway-using-federation-control-plane", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "mesh-gateway-federation", nil, nil) - }, - }, - { - name: "mesh-gateway-no-services", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "no-services", nil, nil) - }, - }, - { - name: "mesh-gateway-tagged-addresses", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "default", func(ns *structs.NodeService) { - ns.Proxy.Config = map[string]interface{}{ - "envoy_mesh_gateway_no_default_bind": true, - "envoy_mesh_gateway_bind_tagged_addresses": true, - } - }, nil) - }, - }, - { - name: "mesh-gateway-custom-addresses", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotMeshGateway(t, "default", func(ns *structs.NodeService) { - ns.Proxy.Config = map[string]interface{}{ - "envoy_mesh_gateway_bind_addresses": map[string]structs.ServiceAddress{ - "foo": { - Address: "198.17.2.3", - Port: 8080, - }, - "bar": { - Address: "2001:db8::ff", - Port: 9999, - }, - "baz": { - Address: "127.0.0.1", - Port: 8765, - }, - }, - } - }, nil) - }, - }, - { - name: "api-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, nil, nil, nil, nil) - }, - }, - { - name: "api-gateway-nil-config-entry", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotAPIGateway_NilConfigEntry(t) - }, - }, - { - name: "api-gateway-tcp-listener", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { - entry.Listeners = []structs.APIGatewayListener{ - { - Name: "listener", - Protocol: structs.ListenerProtocolTCP, - Port: 8080, - }, - } - bound.Listeners = []structs.BoundAPIGatewayListener{ - { - Name: "listener", - }, - } - }, nil, nil, nil) - }, - }, - { - name: "api-gateway-tcp-listener-with-tcp-route", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { - entry.Listeners = []structs.APIGatewayListener{ - { - Name: "listener", - Protocol: structs.ListenerProtocolTCP, - Port: 8080, - }, - } - bound.Listeners = []structs.BoundAPIGatewayListener{ - { - Name: "listener", - Routes: []structs.ResourceReference{ - { - Name: "tcp-route", - Kind: structs.TCPRoute, - }, - }, - }, - } - - }, []structs.BoundRoute{ - &structs.TCPRouteConfigEntry{ - Name: "tcp-route", - Kind: structs.TCPRoute, - Parents: []structs.ResourceReference{ - { - Kind: structs.APIGateway, - Name: "api-gateway", - }, - }, - Services: []structs.TCPService{ - {Name: "tcp-service"}, - }, - }, - }, nil, nil) - }, - }, - { - name: "api-gateway-http-listener", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { - entry.Listeners = []structs.APIGatewayListener{ - { - Name: "listener", - Protocol: structs.ListenerProtocolHTTP, - Port: 8080, - }, - } - bound.Listeners = []structs.BoundAPIGatewayListener{ - { - Name: "listener", - Routes: []structs.ResourceReference{}, - }, - } - }, nil, nil, nil) - }, - }, - { - name: "api-gateway-http-listener-with-http-route", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { - entry.Listeners = []structs.APIGatewayListener{ - { - Name: "listener", - Protocol: structs.ListenerProtocolHTTP, - Port: 8080, - }, - } - bound.Listeners = []structs.BoundAPIGatewayListener{ - { - Name: "listener", - Routes: []structs.ResourceReference{ - { - Name: "http-route", - Kind: structs.HTTPRoute, - }, - }, - }, - } - }, []structs.BoundRoute{ - &structs.HTTPRouteConfigEntry{ - Name: "http-route", - Kind: structs.HTTPRoute, - Parents: []structs.ResourceReference{ - { - Kind: structs.APIGateway, - Name: "api-gateway", - }, - }, - Rules: []structs.HTTPRouteRule{ - { - Services: []structs.HTTPService{ - {Name: "http-service"}, - }, - }, - }, - }, - }, nil, nil) - }, - }, - { - name: "api-gateway-tcp-listener-with-tcp-and-http-route", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { - entry.Listeners = []structs.APIGatewayListener{ - { - Name: "listener-tcp", - Protocol: structs.ListenerProtocolTCP, - Port: 8080, - }, - { - Name: "listener-http", - Protocol: structs.ListenerProtocolHTTP, - Port: 8081, - }, - } - bound.Listeners = []structs.BoundAPIGatewayListener{ - { - Name: "listener-tcp", - Routes: []structs.ResourceReference{ - { - Name: "tcp-route", - Kind: structs.TCPRoute, - }, - }, - }, - { - Name: "listener-http", - Routes: []structs.ResourceReference{ - { - Name: "http-route", - Kind: structs.HTTPRoute, - }, - }, - }, - } - }, []structs.BoundRoute{ - &structs.TCPRouteConfigEntry{ - Name: "tcp-route", - Kind: structs.TCPRoute, - Parents: []structs.ResourceReference{ - { - Kind: structs.APIGateway, - Name: "api-gateway", - }, - }, - Services: []structs.TCPService{ - {Name: "tcp-service"}, - }, - }, - &structs.HTTPRouteConfigEntry{ - Name: "http-route", - Kind: structs.HTTPRoute, - Parents: []structs.ResourceReference{ - { - Kind: structs.APIGateway, - Name: "api-gateway", - }, - }, - Rules: []structs.HTTPRouteRule{ - { - Services: []structs.HTTPService{ - {Name: "http-service"}, - }, - }, - }, - }, - }, nil, nil) - }, - }, - { - name: "ingress-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, nil, nil) - }, - }, - { - name: "ingress-gateway-nil-config-entry", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway_NilConfigEntry(t) - }, - }, - { - name: "ingress-gateway-bind-addrs", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", func(ns *structs.NodeService) { - // - ns.TaggedAddresses = map[string]structs.ServiceAddress{ - "lan": {Address: "10.0.0.1"}, - "wan": {Address: "172.16.0.1"}, - } - ns.Proxy.Config = map[string]interface{}{ - "envoy_gateway_no_default_bind": true, - "envoy_gateway_bind_tagged_addresses": true, - "envoy_gateway_bind_addresses": map[string]structs.ServiceAddress{ - "foo": {Address: "8.8.8.8"}, - }, - } - }, nil, nil) - }, - }, - { - name: "ingress-gateway-no-services", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, false, "tcp", - "default", nil, nil, nil) - }, - }, - { - name: "ingress-with-chain-external-sni", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "external-sni", nil, nil, nil) - }, - }, - { - name: "ingress-with-tcp-chain-failover-through-remote-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-remote-gateway", nil, nil, nil) - }, - }, - { - name: "ingress-with-tcp-chain-failover-through-local-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "failover-through-local-gateway", nil, nil, nil) - }, - }, - { - name: "ingress-splitter-with-resolver-redirect", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", - "splitter-with-resolver-redirect-multidc", nil, nil, nil) - }, - }, - { - name: "terminating-gateway", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, nil) - }, - }, - { - name: "terminating-gateway-custom-trace-listener", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, func(ns *structs.NodeService) { - ns.Proxy.Config = map[string]interface{}{} - ns.Proxy.Config["protocol"] = "http" - ns.Proxy.Config["envoy_listener_tracing_json"] = customTraceJSON(t) - }, nil) - }, - }, - { - name: "terminating-gateway-with-tls-incoming-min-version", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Incoming: &structs.MeshDirectionalTLSConfig{ - TLSMinVersion: types.TLSv1_3, - }, - }, - }, - }, - }, - }) - }, - }, - { - name: "terminating-gateway-with-tls-incoming-max-version", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Incoming: &structs.MeshDirectionalTLSConfig{ - TLSMaxVersion: types.TLSv1_2, - }, - }, - }, - }, - }, - }) - }, - }, - { - name: "terminating-gateway-with-tls-incoming-cipher-suites", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "mesh", - Result: &structs.ConfigEntryResponse{ - Entry: &structs.MeshConfigEntry{ - TLS: &structs.MeshTLSConfig{ - Incoming: &structs.MeshDirectionalTLSConfig{ - CipherSuites: []types.TLSCipherSuite{ - types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - }, - }, - }, - }, - }, - }, - }) - }, - }, - { - name: "terminating-gateway-no-services", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, false, nil, nil) - }, - }, - { - name: "terminating-gateway-custom-and-tagged-addresses", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, func(ns *structs.NodeService) { - ns.Proxy.Config = map[string]interface{}{ - "envoy_gateway_no_default_bind": true, - "envoy_gateway_bind_tagged_addresses": true, - "envoy_gateway_bind_addresses": map[string]structs.ServiceAddress{ - // This bind address should not get a listener due to deduplication and it sorts to the end - "z-duplicate-of-tagged-wan-addr": { - Address: "198.18.0.1", - Port: 443, - }, - "foo": { - Address: "198.17.2.3", - Port: 8080, - }, - }, - } - }, nil) - }, - }, - { - name: "terminating-gateway-service-subsets", - create: proxycfg.TestConfigSnapshotTerminatingGatewayServiceSubsets, - }, - { - name: "ingress-http-multiple-services", - create: proxycfg.TestConfigSnapshotIngress_HTTPMultipleServices, - }, - { - name: "ingress-grpc-multiple-services", - create: proxycfg.TestConfigSnapshotIngress_GRPCMultipleServices, - }, - { - name: "terminating-gateway-no-api-cert", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - api := structs.NewServiceName("api", nil) - return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "service-leaf:" + api.String(), // serviceLeafIDPrefix - Result: nil, // tombstone this - }, - }) - }, - }, - { - name: "terminating-gateway-with-peer-trust-bundle", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - roots, _ := proxycfg.TestCerts(t) - return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, []proxycfg.UpdateEvent{ - { - CorrelationID: "peer-trust-bundle:web", - Result: &pbpeering.TrustBundleListByServiceResponse{ - Bundles: []*pbpeering.PeeringTrustBundle{ - { - TrustDomain: "foo.bar.gov", - PeerName: "dc2", - Partition: "default", - RootPEMs: []string{ - roots.Roots[0].RootCert, - }, - ExportedPartition: "default", - CreateIndex: 0, - ModifyIndex: 0, - }, - }, - }, - }, - { - CorrelationID: "service-intentions:web", - Result: structs.SimplifiedIntentions{ - { - SourceName: "source", - SourcePeer: "dc2", - DestinationName: "web", - DestinationPartition: "default", - Action: structs.IntentionActionAllow, - }, - }, - }, - }) - }, - }, - { - name: "ingress-with-tls-listener", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, - func(entry *structs.IngressGatewayConfigEntry) { - entry.TLS.Enabled = true - }, nil) - }, - }, - { - name: "ingress-with-tls-listener-min-version", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, - func(entry *structs.IngressGatewayConfigEntry) { - entry.TLS.Enabled = true - entry.TLS.TLSMinVersion = types.TLSv1_3 - }, nil) - }, - }, - { - name: "ingress-with-tls-listener-max-version", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, - func(entry *structs.IngressGatewayConfigEntry) { - entry.TLS.Enabled = true - entry.TLS.TLSMaxVersion = types.TLSv1_2 - }, nil) - }, - }, - { - name: "ingress-with-tls-listener-cipher-suites", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, - func(entry *structs.IngressGatewayConfigEntry) { - entry.TLS.Enabled = true - entry.TLS.CipherSuites = []types.TLSCipherSuite{ - types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - } - }, nil) - }, - }, - { - name: "ingress-with-tls-mixed-listeners", - create: proxycfg.TestConfigSnapshotIngressGateway_MixedListeners, - }, - { - name: "ingress-with-tls-min-version-listeners-gateway-defaults", - create: proxycfg.TestConfigSnapshotIngressGateway_TLSMinVersionListenersGatewayDefaults, - }, - { - name: "ingress-with-single-tls-listener", - create: proxycfg.TestConfigSnapshotIngressGateway_SingleTLSListener, - }, - { - name: "ingress-with-tls-mixed-min-version-listeners", - create: proxycfg.TestConfigSnapshotIngressGateway_TLSMixedMinVersionListeners, - }, - { - name: "ingress-with-tls-mixed-max-version-listeners", - create: proxycfg.TestConfigSnapshotIngressGateway_TLSMixedMaxVersionListeners, - }, - { - name: "ingress-with-tls-mixed-cipher-suites-listeners", - create: proxycfg.TestConfigSnapshotIngressGateway_TLSMixedCipherVersionListeners, - }, - { - name: "ingress-with-sds-listener-gw-level", - create: proxycfg.TestConfigSnapshotIngressGatewaySDS_GatewayLevel, - }, - { - name: "ingress-with-sds-listener-listener-level", - create: proxycfg.TestConfigSnapshotIngressGatewaySDS_GatewayAndListenerLevel, - }, - { - name: "ingress-with-sds-listener-gw-level-http", - create: proxycfg.TestConfigSnapshotIngressGatewaySDS_GatewayAndListenerLevel_HTTP, - }, - { - name: "ingress-with-sds-listener-gw-level-mixed-tls", - create: proxycfg.TestConfigSnapshotIngressGatewaySDS_GatewayLevel_MixedTLS, - }, - { - name: "ingress-with-sds-service-level", - create: proxycfg.TestConfigSnapshotIngressGatewaySDS_ServiceLevel, - }, - { - name: "ingress-with-sds-listener+service-level", - create: proxycfg.TestConfigSnapshotIngressGatewaySDS_ListenerAndServiceLevel, - }, - { - name: "ingress-with-sds-service-level-mixed-no-tls", - create: proxycfg.TestConfigSnapshotIngressGatewaySDS_MixedNoTLS, - }, - { - name: "ingress-with-grpc-single-tls-listener", - create: proxycfg.TestConfigSnapshotIngressGateway_SingleTLSListener_GRPC, - }, - { - name: "ingress-with-http2-single-tls-listener", - create: proxycfg.TestConfigSnapshotIngressGateway_SingleTLSListener_HTTP2, - }, - { - name: "ingress-with-http2-and-grpc-multiple-tls-listener", - create: proxycfg.TestConfigSnapshotIngressGateway_MultiTLSListener_MixedHTTP2gRPC, - }, - { - name: "ingress-with-http2-and-grpc-multiple-tls-listener", - create: proxycfg.TestConfigSnapshotIngressGateway_GWTLSListener_MixedHTTP2gRPC, - }, - { - name: "transparent-proxy-http-upstream", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTransparentProxyHTTPUpstream(t) - }, - alsoRunTestForV2: true, - }, - { - name: "transparent-proxy-with-resolver-redirect-upstream", - create: proxycfg.TestConfigSnapshotTransparentProxyResolverRedirectUpstream, - alsoRunTestForV2: true, - }, - { - name: "transparent-proxy-catalog-destinations-only", - create: proxycfg.TestConfigSnapshotTransparentProxyCatalogDestinationsOnly, - alsoRunTestForV2: true, - }, - { - name: "transparent-proxy-dial-instances-directly", - create: proxycfg.TestConfigSnapshotTransparentProxyDialDirectly, - alsoRunTestForV2: true, - }, - { - name: "transparent-proxy-terminating-gateway", - create: proxycfg.TestConfigSnapshotTransparentProxyTerminatingGatewayCatalogDestinationsOnly, - alsoRunTestForV2: true, - }, - { - name: "custom-trace-listener", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.Config["protocol"] = "http" - ns.Proxy.Config["envoy_listener_tracing_json"] = customTraceJSON(t) - }, nil) - }, - }, - { - name: "access-logs-defaults", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - // This should be passed into the snapshot through proxy-defaults - ns.Proxy.AccessLogs = structs.AccessLogsConfig{ - Enabled: true, - } - }, - nil) - }, - }, - { - name: "access-logs-json-file", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - // This should be passed into the snapshot through proxy-defaults - ns.Proxy.AccessLogs = structs.AccessLogsConfig{ - Enabled: true, - Type: structs.FileLogSinkType, - Path: "/tmp/accesslog.txt", - JSONFormat: "{ \"custom_start_time\": \"%START_TIME%\" }", - } - }, - nil) - }, - }, - { - name: "access-logs-text-stderr-disablelistenerlogs", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - // This should be passed into the snapshot through proxy-defaults - ns.Proxy.AccessLogs = structs.AccessLogsConfig{ - Enabled: true, - DisableListenerLogs: true, - Type: structs.StdErrLogSinkType, - TextFormat: "CUSTOM FORMAT %START_TIME%", - } - }, - nil) - }, - }, - { - name: "connect-proxy-with-tproxy-and-permissive-mtls", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.MutualTLSMode = structs.MutualTLSModePermissive - ns.Proxy.Mode = structs.ProxyModeTransparent - ns.Proxy.TransparentProxy.OutboundListenerPort = 1234 - }, - nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-without-tproxy-and-permissive-mtls", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - ns.Proxy.MutualTLSMode = structs.MutualTLSModePermissive - }, - nil) - }, - alsoRunTestForV2: true, - }, - } - - tests = append(tests, makeListenerDiscoChainTests(false)...) - - latestEnvoyVersion := xdscommon.EnvoyVersions[0] - for _, envoyVersion := range xdscommon.EnvoyVersions { - sf, err := xdscommon.DetermineSupportedProxyFeaturesFromString(envoyVersion) - require.NoError(t, err) - t.Run("envoy-"+envoyVersion, func(t *testing.T) { - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - // Sanity check default with no overrides first - snap := tt.create(t) - - // TODO: it would be nice to be able to ensure these snapshots are always valid before we use them in a test. - // require.True(t, snap.Valid()) - - // We need to replace the TLS certs with deterministic ones to make golden - // files workable. Note we don't update these otherwise they'd change - // golder files for every test case and so not be any use! - testcommon.SetupTLSRootsAndLeaf(t, snap) - - var listeners []proto.Message - - // Need server just for logger dependency - g := NewResourceGenerator(testutil.Logger(t), nil, false) - g.ProxyFeatures = sf - if tt.generatorSetup != nil { - tt.generatorSetup(g) - } - listeners, err = g.listenersFromSnapshot(snap) - require.NoError(t, err) - // The order of listeners returned via LDS isn't relevant, so it's safe - // to sort these for the purposes of test comparisons. - sort.Slice(listeners, func(i, j int) bool { - return listeners[i].(*envoy_listener_v3.Listener).Name < listeners[j].(*envoy_listener_v3.Listener).Name - }) - - r, err := response.CreateResponse(xdscommon.ListenerType, "00000001", "00000001", listeners) - require.NoError(t, err) - - t.Run("current-xdsv1", func(t *testing.T) { - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - expectedJSON := goldenEnvoy(t, filepath.Join("listeners", gName), envoyVersion, latestEnvoyVersion, gotJSON) - require.JSONEq(t, expectedJSON, gotJSON) - }) - - if tt.alsoRunTestForV2 { - generator := xdsv2.NewResourceGenerator(testutil.Logger(t)) - converter := proxystateconverter.NewConverter(testutil.Logger(t), nil) - proxyState, err := converter.ProxyStateFromSnapshot(snap) - require.NoError(t, err) - - res, err := generator.AllResourcesFromIR(proxyState) - require.NoError(t, err) - - listeners = res[xdscommon.ListenerType] - // The order of listeners returned via LDS isn't relevant, so it's safe - // to sort these for the purposes of test comparisons. - sort.Slice(listeners, func(i, j int) bool { - return listeners[i].(*envoy_listener_v3.Listener).Name < listeners[j].(*envoy_listener_v3.Listener).Name - }) - - r, err := response.CreateResponse(xdscommon.ListenerType, "00000001", "00000001", listeners) - require.NoError(t, err) - - t.Run("current-xdsv2", func(t *testing.T) { - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - expectedJSON := goldenEnvoy(t, filepath.Join("listeners", gName), envoyVersion, latestEnvoyVersion, gotJSON) - require.JSONEq(t, expectedJSON, gotJSON) - }) - } - - }) - } - }) - } -} - type customListenerJSONOptions struct { Name string TLSContext string @@ -1767,3 +371,71 @@ func TestGetAlpnProtocols(t *testing.T) { }) } } + +func Test_setNormalizationOptions(t *testing.T) { + tests := map[string]struct { + rn *structs.RequestNormalizationMeshConfig + opts *listenerFilterOpts + want *listenerFilterOpts + }{ + "nil entry": { + rn: nil, + opts: &listenerFilterOpts{}, + want: &listenerFilterOpts{ + normalizePath: true, + }, + }, + "empty entry": { + rn: &structs.RequestNormalizationMeshConfig{}, + opts: &listenerFilterOpts{}, + want: &listenerFilterOpts{ + normalizePath: true, + }, + }, + "empty is equivalent to defaults": { + rn: &structs.RequestNormalizationMeshConfig{}, + opts: &listenerFilterOpts{}, + want: &listenerFilterOpts{ + normalizePath: true, + mergeSlashes: false, + pathWithEscapedSlashesAction: envoy_http_v3.HttpConnectionManager_IMPLEMENTATION_SPECIFIC_DEFAULT, + headersWithUnderscoresAction: envoy_core_v3.HttpProtocolOptions_ALLOW, + }, + }, + "some options": { + rn: &structs.RequestNormalizationMeshConfig{ + InsecureDisablePathNormalization: false, + MergeSlashes: true, + PathWithEscapedSlashesAction: "", + HeadersWithUnderscoresAction: "DROP_HEADER", + }, + opts: &listenerFilterOpts{}, + want: &listenerFilterOpts{ + normalizePath: true, + mergeSlashes: true, + headersWithUnderscoresAction: envoy_core_v3.HttpProtocolOptions_DROP_HEADER, + }, + }, + "all options": { + rn: &structs.RequestNormalizationMeshConfig{ + InsecureDisablePathNormalization: true, // note: this is the opposite of the recommended default + MergeSlashes: true, + PathWithEscapedSlashesAction: "REJECT_REQUEST", + HeadersWithUnderscoresAction: "DROP_HEADER", + }, + opts: &listenerFilterOpts{}, + want: &listenerFilterOpts{ + normalizePath: false, + mergeSlashes: true, + pathWithEscapedSlashesAction: envoy_http_v3.HttpConnectionManager_REJECT_REQUEST, + headersWithUnderscoresAction: envoy_core_v3.HttpProtocolOptions_DROP_HEADER, + }, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + setNormalizationOptions(tc.rn, tc.opts) + assert.Equal(t, tc.want, tc.opts) + }) + } +} diff --git a/agent/xds/proxystateconverter/clusters.go b/agent/xds/proxystateconverter/clusters.go deleted file mode 100644 index fa3a5eadd884..000000000000 --- a/agent/xds/proxystateconverter/clusters.go +++ /dev/null @@ -1,1266 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "errors" - "fmt" - "strings" - "time" - - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-uuid" - - envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" - - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/config" - "github.com/hashicorp/consul/agent/xds/naming" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/consul/proto/private/pbpeering" -) - -const ( - meshGatewayExportedClusterNamePrefix = "exported~" -) - -type namedCluster struct { - name string - cluster *pbproxystate.Cluster -} - -// clustersFromSnapshot returns the xDS API representation of the "clusters" in the snapshot. -func (s *Converter) clustersFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) error { - if cfgSnap == nil { - return errors.New("nil config given") - } - - switch cfgSnap.Kind { - case structs.ServiceKindConnectProxy: - return s.clustersFromSnapshotConnectProxy(cfgSnap) - // TODO(proxystate): Terminating Gateways will be added in the future. - //case structs.ServiceKindTerminatingGateway: - // err := s.clustersFromSnapshotTerminatingGateway(cfgSnap) - // if err != nil { - // return err - // } - // return nil - // TODO(proxystate): Mesh Gateways will be added in the future. - //case structs.ServiceKindMeshGateway: - // err := s.clustersFromSnapshotMeshGateway(cfgSnap) - // if err != nil { - // return err - // } - // return nil - // TODO(proxystate): Ingress Gateways will be added in the future. - //case structs.ServiceKindIngressGateway: - // err := s.clustersFromSnapshotIngressGateway(cfgSnap) - // if err != nil { - // return err - // } - // return nil - // TODO(proxystate): API Gateways will be added in the future. - //case structs.ServiceKindAPIGateway: - // res, err := s.clustersFromSnapshotAPIGateway(cfgSnap) - // if err != nil { - // return err - // } - // return nil - default: - return fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind) - } -} - -// clustersFromSnapshot returns the xDS API representation of the "clusters" -// (upstreams) in the snapshot. -func (s *Converter) clustersFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnapshot) error { - // This is the list of listeners we add to. It will be empty to start. - clusters := s.proxyState.Clusters - var err error - - // Include the "app" cluster for the public listener - appCluster, err := s.makeAppCluster(cfgSnap, xdscommon.LocalAppClusterName, "", cfgSnap.Proxy.LocalServicePort) - if err != nil { - return err - } - clusters[appCluster.name] = appCluster.cluster - - if cfgSnap.Proxy.Mode == structs.ProxyModeTransparent { - passthroughs, err := s.makePassthroughClusters(cfgSnap) - if err != nil { - return fmt.Errorf("failed to make passthrough clusters for transparent proxy: %v", err) - } - for clusterName, cluster := range passthroughs { - clusters[clusterName] = cluster - } - } - - // NOTE: Any time we skip a chain below we MUST also skip that discovery chain in endpoints.go - // so that the sets of endpoints generated matches the sets of clusters. - for uid, chain := range cfgSnap.ConnectProxy.DiscoveryChain { - upstream, skip := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta) - if skip { - continue - } - - upstreamClusters, err := s.makeUpstreamClustersForDiscoveryChain( - uid, - upstream, - chain, - cfgSnap, - false, - ) - if err != nil { - return err - } - - for name, cluster := range upstreamClusters { - clusters[name] = cluster - } - } - - // TODO(proxystate): peering will be added in the future. - //// NOTE: Any time we skip an upstream below we MUST also skip that same - //// upstream in endpoints.go so that the sets of endpoints generated matches - //// the sets of clusters. - //for _, uid := range cfgSnap.ConnectProxy.PeeredUpstreamIDs() { - // upstream, skip := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta) - // if skip { - // continue - // } - // - // peerMeta, found := cfgSnap.ConnectProxy.UpstreamPeerMeta(uid) - // if !found { - // s.Logger.Warn("failed to fetch upstream peering metadata for cluster", "uid", uid) - // } - // cfg := s.getAndModifyUpstreamConfigForPeeredListener(uid, upstream, peerMeta) - // - // upstreamCluster, err := s.makeUpstreamClusterForPeerService(uid, cfg, peerMeta, cfgSnap) - // if err != nil { - // return nil, err - // } - // clusters = append(clusters, upstreamCluster) - //} - - // TODO(proxystate): L7 Intentions and JWT Auth will be added in the future. - //// add clusters for jwt-providers - //for _, prov := range cfgSnap.JWTProviders { - // //skip cluster creation for local providers - // if prov.JSONWebKeySet == nil || prov.JSONWebKeySet.Remote == nil { - // continue - // } - // - // cluster, err := makeJWTProviderCluster(prov) - // if err != nil { - // s.Logger.Warn("failed to make jwt-provider cluster", "provider name", prov.Name, "error", err) - // continue - // } - // - // clusters[cluster.GetName()] = cluster - //} - - for _, u := range cfgSnap.Proxy.Upstreams { - if u.DestinationType != structs.UpstreamDestTypePreparedQuery { - continue - } - - upstreamCluster, err := s.makeUpstreamClusterForPreparedQuery(u, cfgSnap) - if err != nil { - return err - } - clusters[upstreamCluster.name] = upstreamCluster.cluster - } - - cfgSnap.Proxy.Expose.Finalize() - paths := cfgSnap.Proxy.Expose.Paths - - // Add service health checks to the list of paths to create clusters for if needed - if cfgSnap.Proxy.Expose.Checks { - psid := structs.NewServiceID(cfgSnap.Proxy.DestinationServiceID, &cfgSnap.ProxyID.EnterpriseMeta) - for _, check := range cfgSnap.ConnectProxy.WatchedServiceChecks[psid] { - p, err := parseCheckPath(check) - if err != nil { - s.Logger.Warn("failed to create cluster for", "check", check.CheckID, "error", err) - continue - } - paths = append(paths, p) - } - } - - // Create a new cluster if we need to expose a port that is different from the service port - for _, path := range paths { - if path.LocalPathPort == cfgSnap.Proxy.LocalServicePort { - continue - } - c, err := s.makeAppCluster(cfgSnap, makeExposeClusterName(path.LocalPathPort), path.Protocol, path.LocalPathPort) - if err != nil { - s.Logger.Warn("failed to make local cluster", "path", path.Path, "error", err) - continue - } - clusters[c.name] = c.cluster - } - - return nil -} - -// TODO(proxystate): L7 Intentions and JWT Auth will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeJWTProviderCluster -// func makeJWKSDiscoveryClusterType -// func makeJWTCertValidationContext -// func parseJWTRemoteURL - -func makeExposeClusterName(destinationPort int) string { - return fmt.Sprintf("exposed_cluster_%d", destinationPort) -} - -// In transparent proxy mode there are potentially multiple passthrough clusters added. -// The first is for destinations outside of Consul's catalog. This is for a plain TCP proxy. -// All of these use Envoy's ORIGINAL_DST listener filter, which forwards to the original -// destination address (before the iptables redirection). -// The rest are for destinations inside the mesh, which require certificates for mTLS. -func (s *Converter) makePassthroughClusters(cfgSnap *proxycfg.ConfigSnapshot) (map[string]*pbproxystate.Cluster, error) { - // This size is an upper bound. - clusters := make(map[string]*pbproxystate.Cluster, 0) - if meshConf := cfgSnap.MeshConfig(); meshConf == nil || - !meshConf.TransparentProxy.MeshDestinationsOnly { - - clusters[naming.OriginalDestinationClusterName] = &pbproxystate.Cluster{ - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Passthrough{ - Passthrough: &pbproxystate.PassthroughEndpointGroup{ - Config: &pbproxystate.PassthroughEndpointGroupConfig{ - ConnectTimeout: durationpb.New(5 * time.Second), - }, - }, - }, - }, - }, - } - } - - for uid, chain := range cfgSnap.ConnectProxy.DiscoveryChain { - targetMap, ok := cfgSnap.ConnectProxy.PassthroughUpstreams[uid] - if !ok { - continue - } - - for targetID := range targetMap { - uid := proxycfg.NewUpstreamIDFromTargetID(targetID) - - sni := connect.ServiceSNI( - uid.Name, "", uid.NamespaceOrDefault(), - uid.PartitionOrDefault(), cfgSnap.Datacenter, - cfgSnap.Roots.TrustDomain) - - // Prefixed with passthrough to distinguish from non-passthrough clusters for the same upstream. - name := "passthrough~" + sni - - c := pbproxystate.Cluster{ - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Passthrough{ - Passthrough: &pbproxystate.PassthroughEndpointGroup{ - Config: &pbproxystate.PassthroughEndpointGroupConfig{ - ConnectTimeout: durationpb.New(5 * time.Second), - }, - }, - }, - }, - }, - } - - if discoTarget, ok := chain.Targets[targetID]; ok && discoTarget.ConnectTimeout > 0 { - c.GetEndpointGroup().GetPassthrough().GetConfig(). - ConnectTimeout = durationpb.New(discoTarget.ConnectTimeout) - } - - transportSocket, err := s.createOutboundMeshMTLS(cfgSnap, []string{getSpiffeID(cfgSnap, uid)}, sni) - if err != nil { - return nil, err - } - c.GetEndpointGroup().GetPassthrough().OutboundTls = transportSocket - - clusters[name] = &c - } - } - - err := cfgSnap.ConnectProxy.DestinationsUpstream.ForEachKeyE(func(uid proxycfg.UpstreamID) error { - svcConfig, ok := cfgSnap.ConnectProxy.DestinationsUpstream.Get(uid) - if !ok || svcConfig.Destination == nil { - return nil - } - - // One Cluster per Destination Address - for _, address := range svcConfig.Destination.Addresses { - name := clusterNameForDestination(cfgSnap, uid.Name, address, uid.NamespaceOrDefault(), uid.PartitionOrDefault()) - - c := &pbproxystate.Cluster{ - AltStatName: name, - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Dynamic{ - Dynamic: &pbproxystate.DynamicEndpointGroup{ - Config: &pbproxystate.DynamicEndpointGroupConfig{ - ConnectTimeout: durationpb.New(5 * time.Second), - // Endpoints are managed separately by EDS - // Having an empty config enables outlier detection with default config. - OutlierDetection: &pbproxystate.OutlierDetection{}, - DisablePanicThreshold: true, - }, - }, - }, - }, - }, - } - sni := connect.ServiceSNI( - uid.Name, "", uid.NamespaceOrDefault(), - uid.PartitionOrDefault(), cfgSnap.Datacenter, - cfgSnap.Roots.TrustDomain) - transportSocket, err := s.createOutboundMeshMTLS(cfgSnap, []string{getSpiffeID(cfgSnap, uid)}, sni) - if err != nil { - return err - } - c.GetEndpointGroup().GetDynamic().OutboundTls = transportSocket - clusters[name] = c - } - return nil - }) - if err != nil { - return nil, err - } - - return clusters, nil -} - -func getSpiffeID(cfgSnap *proxycfg.ConfigSnapshot, uid proxycfg.UpstreamID) string { - spiffeIDService := &connect.SpiffeIDService{ - Host: cfgSnap.Roots.TrustDomain, - Partition: uid.PartitionOrDefault(), - Namespace: uid.NamespaceOrDefault(), - Datacenter: cfgSnap.Datacenter, - Service: uid.Name, - } - return spiffeIDService.URI().String() -} -func clusterNameForDestination(cfgSnap *proxycfg.ConfigSnapshot, name string, - address string, namespace string, partition string) string { - name = destinationSpecificServiceName(name, address) - sni := connect.ServiceSNI(name, "", namespace, partition, - cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain) - - // Prefixed with destination to distinguish from non-passthrough clusters - // for the same upstream. - return "destination." + sni -} - -func destinationSpecificServiceName(name string, address string) string { - address = strings.ReplaceAll(address, ":", "-") - address = strings.ReplaceAll(address, ".", "-") - return fmt.Sprintf("%s.%s", address, name) -} - -// TODO(proxystate): Mesh Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func clustersFromSnapshotMeshGateway -// func haveVoters - -// TODO(proxystate): Peering will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makePeerServerClusters - -// TODO(proxystate): Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func clustersFromSnapshotTerminatingGateway - -// TODO(proxystate): Mesh Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeGatewayServiceClusters - -// TODO(proxystate): Cluster Peering will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeGatewayOutgoingClusterPeeringServiceClusters - -// TODO(proxystate): Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeDestinationClusters - -// TODO(proxystate): Mesh Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func injectGatewayServiceAddons - -// TODO(proxystate): Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func injectGatewayDestinationAddons - -// TODO(proxystate): Ingress Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func clustersFromSnapshotIngressGateway - -// TODO(proxystate): API Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func clustersFromSnapshotAPIGateway - -// TODO(proxystate): Ingress Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func configIngressUpstreamCluster - -func (s *Converter) makeAppCluster(cfgSnap *proxycfg.ConfigSnapshot, name, pathProtocol string, port int) (*namedCluster, error) { - var err error - namedCluster := &namedCluster{} - - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - - //// If we have overridden local cluster config try to parse it into an Envoy cluster - //if cfg.LocalClusterJSON != "" { - // return makeClusterFromUserConfig(cfg.LocalClusterJSON) - //} - - var endpoint *pbproxystate.Endpoint - if cfgSnap.Proxy.LocalServiceSocketPath != "" { - endpoint = makeUnixSocketEndpoint(cfgSnap.Proxy.LocalServiceSocketPath) - } else { - addr := cfgSnap.Proxy.LocalServiceAddress - if addr == "" { - addr = "127.0.0.1" - } - endpoint = makeHostPortEndpoint(addr, port) - } - s.proxyState.Endpoints[name] = &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{endpoint}, - } - - namedCluster.name = name - namedCluster.cluster = &pbproxystate.Cluster{ - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Static{ - Static: &pbproxystate.StaticEndpointGroup{ - Config: &pbproxystate.StaticEndpointGroupConfig{ - ConnectTimeout: durationpb.New(time.Duration(cfg.LocalConnectTimeoutMs) * time.Millisecond), - }, - }, - }, - }, - }, - } - - protocol := pathProtocol - if protocol == "" { - protocol = cfg.Protocol - } - namedCluster.cluster.Protocol = protocolMap[protocol] - if cfg.MaxInboundConnections > 0 { - namedCluster.cluster.GetEndpointGroup().GetStatic().GetConfig(). - CircuitBreakers = &pbproxystate.CircuitBreakers{ - UpstreamLimits: &pbproxystate.UpstreamLimits{ - MaxConnections: response.MakeUint32Value(cfg.MaxInboundConnections), - }, - } - } - - return namedCluster, err -} - -func (s *Converter) makeUpstreamClusterForPeerService( - uid proxycfg.UpstreamID, - upstreamConfig structs.UpstreamConfig, - peerMeta structs.PeeringServiceMeta, - cfgSnap *proxycfg.ConfigSnapshot, -) (string, *pbproxystate.Cluster, *pbproxystate.Endpoints, error) { - var ( - c *pbproxystate.Cluster - e *pbproxystate.Endpoints - err error - ) - - // TODO(proxystate): escapeHatches will be implemented in the future - //if upstreamConfig.EnvoyClusterJSON != "" { - // c, err = makeClusterFromUserConfig(upstreamConfig.EnvoyClusterJSON) - // if err != nil { - // return "", c, e, err - // } - // // In the happy path don't return yet as we need to inject TLS config still. - //} - - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - - if err != nil { - return "", c, e, err - } - - tbs, ok := upstreamsSnapshot.UpstreamPeerTrustBundles.Get(uid.Peer) - if !ok { - // this should never happen since we loop through upstreams with - // set trust bundles - return "", c, e, fmt.Errorf("trust bundle not ready for peer %s", uid.Peer) - } - - clusterName := generatePeeredClusterName(uid, tbs) - - outlierDetection := makeOutlierDetection(upstreamConfig.PassiveHealthCheck, nil, true) - // We can't rely on health checks for services on cluster peers because they - // don't take into account service resolvers, splitters and routers. Setting - // MaxEjectionPercent too 100% gives outlier detection the power to eject the - // entire cluster. - outlierDetection.MaxEjectionPercent = &wrapperspb.UInt32Value{Value: 100} - - s.Logger.Trace("generating cluster for", "cluster", clusterName) - if c == nil { - c = &pbproxystate.Cluster{} - - useEDS := true - if _, ok := cfgSnap.ConnectProxy.PeerUpstreamEndpointsUseHostnames[uid]; ok { - // If we're using local mesh gw, the fact that upstreams use hostnames don't matter. - // If we're not using local mesh gw, then resort to CDS. - if upstreamConfig.MeshGateway.Mode != structs.MeshGatewayModeLocal { - useEDS = false - } - } - - // If none of the service instances are addressed by a hostname we - // provide the endpoint IP addresses via EDS - if useEDS { - d := &pbproxystate.DynamicEndpointGroup{ - Config: &pbproxystate.DynamicEndpointGroupConfig{ - UseAltStatName: false, - ConnectTimeout: durationpb.New(time.Duration(upstreamConfig.ConnectTimeoutMs) * time.Millisecond), - DisablePanicThreshold: true, - CircuitBreakers: &pbproxystate.CircuitBreakers{ - UpstreamLimits: makeUpstreamLimitsIfNeeded(upstreamConfig.Limits), - }, - OutlierDetection: outlierDetection, - }, - } - c.Group = &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Dynamic{ - Dynamic: d, - }, - }, - } - transportSocket := &pbproxystate.TransportSocket{ - ConnectionTls: &pbproxystate.TransportSocket_OutboundMesh{ - OutboundMesh: &pbproxystate.OutboundMeshMTLS{ - ValidationContext: &pbproxystate.MeshOutboundValidationContext{ - SpiffeIds: peerMeta.SpiffeID, - TrustBundlePeerNameKey: uid.Peer, - }, - Sni: peerMeta.PrimarySNI(), - }, - }, - } - d.OutboundTls = transportSocket - } else { - d := &pbproxystate.DNSEndpointGroup{ - Config: &pbproxystate.DNSEndpointGroupConfig{ - UseAltStatName: false, - ConnectTimeout: durationpb.New(time.Duration(upstreamConfig.ConnectTimeoutMs) * time.Millisecond), - DisablePanicThreshold: true, - CircuitBreakers: &pbproxystate.CircuitBreakers{ - UpstreamLimits: makeUpstreamLimitsIfNeeded(upstreamConfig.Limits), - }, - OutlierDetection: outlierDetection, - }, - } - c.Group = &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Dns{ - Dns: d, - }, - }, - } - e = &pbproxystate.Endpoints{ - Endpoints: make([]*pbproxystate.Endpoint, 0), - } - - ep, _ := cfgSnap.ConnectProxy.PeerUpstreamEndpoints.Get(uid) - configureClusterWithHostnames( - s.Logger, - d, - e, - "", /*TODO:make configurable?*/ - ep, - true, /*isRemote*/ - false, /*onlyPassing*/ - ) - transportSocket := &pbproxystate.TransportSocket{ - ConnectionTls: &pbproxystate.TransportSocket_OutboundMesh{ - OutboundMesh: &pbproxystate.OutboundMeshMTLS{ - ValidationContext: &pbproxystate.MeshOutboundValidationContext{ - SpiffeIds: peerMeta.SpiffeID, - TrustBundlePeerNameKey: uid.Peer, - }, - Sni: peerMeta.PrimarySNI(), - }, - }, - } - d.OutboundTls = transportSocket - } - } - - return clusterName, c, e, nil -} - -func (s *Converter) makeUpstreamClusterForPreparedQuery(upstream structs.Upstream, cfgSnap *proxycfg.ConfigSnapshot) (*namedCluster, error) { - var c *pbproxystate.Cluster - var err error - - uid := proxycfg.NewUpstreamID(&upstream) - - dc := upstream.Datacenter - if dc == "" { - dc = cfgSnap.Datacenter - } - sni := connect.UpstreamSNI(&upstream, "", dc, cfgSnap.Roots.TrustDomain) - - cfg, _ := structs.ParseUpstreamConfig(upstream.Config) - // TODO(proxystate): add logger and enable this - //if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - //s.Logger.Warn("failed to parse", "upstream", uid, "error", err) - //} - - // TODO(proxystate): escapeHatches will be implemented in the future - //if cfg.EnvoyClusterJSON != "" { - // c, err = makeClusterFromUserConfig(cfg.EnvoyClusterJSON) - // if err != nil { - // return c, err - // } - // // In the happy path don't return yet as we need to inject TLS config still. - //} - - if c == nil { - c = &pbproxystate.Cluster{ - Protocol: protocolMap[cfg.Protocol], - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Dynamic{ - Dynamic: &pbproxystate.DynamicEndpointGroup{ - Config: &pbproxystate.DynamicEndpointGroupConfig{ - ConnectTimeout: durationpb.New(time.Duration(cfg.ConnectTimeoutMs) * time.Millisecond), - // Endpoints are managed separately by EDS - // Having an empty config enables outlier detection with default config. - OutlierDetection: makeOutlierDetection(cfg.PassiveHealthCheck, nil, true), - CircuitBreakers: &pbproxystate.CircuitBreakers{ - UpstreamLimits: makeUpstreamLimitsIfNeeded(cfg.Limits), - }, - }, - }, - }, - }, - }, - } - } - - endpoints := cfgSnap.ConnectProxy.PreparedQueryEndpoints[uid] - var ( - spiffeIDs = make([]string, 0) - seen = make(map[string]struct{}) - ) - for _, e := range endpoints { - id := fmt.Sprintf("%s/%s", e.Node.Datacenter, e.Service.CompoundServiceName()) - if _, ok := seen[id]; ok { - continue - } - seen[id] = struct{}{} - - name := e.Service.Proxy.DestinationServiceName - if e.Service.Connect.Native { - name = e.Service.Service - } - - spiffeIDs = append(spiffeIDs, connect.SpiffeIDService{ - Host: cfgSnap.Roots.TrustDomain, - Namespace: e.Service.NamespaceOrDefault(), - Partition: e.Service.PartitionOrDefault(), - Datacenter: e.Node.Datacenter, - Service: name, - }.URI().String()) - } - - transportSocket, err := s.createOutboundMeshMTLS(cfgSnap, spiffeIDs, sni) - if err != nil { - return nil, err - } - c.GetEndpointGroup().GetDynamic().OutboundTls = transportSocket - - return &namedCluster{name: sni, cluster: c}, nil -} - -func finalizeUpstreamConfig(cfg structs.UpstreamConfig, chain *structs.CompiledDiscoveryChain, connectTimeout time.Duration) structs.UpstreamConfig { - if cfg.Protocol == "" { - cfg.Protocol = chain.Protocol - } - - if cfg.Protocol == "" { - cfg.Protocol = "tcp" - } - - if cfg.ConnectTimeoutMs == 0 { - cfg.ConnectTimeoutMs = int(connectTimeout / time.Millisecond) - } - return cfg -} - -func (s *Converter) createOutboundMeshMTLS(cfgSnap *proxycfg.ConfigSnapshot, spiffeIDs []string, sni string) (*pbproxystate.TransportSocket, error) { - switch cfgSnap.Kind { - case structs.ServiceKindConnectProxy: - case structs.ServiceKindMeshGateway: - default: - return nil, fmt.Errorf("cannot inject peering trust bundles for kind %q", cfgSnap.Kind) - } - - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - - // Add all trust bundle peer names, including local. - trustBundlePeerNames := []string{"local"} - for _, tb := range cfgSnap.PeeringTrustBundles() { - trustBundlePeerNames = append(trustBundlePeerNames, tb.PeerName) - } - // Arbitrary UUID to reference the identity by. - uuid, err := uuid.GenerateUUID() - if err != nil { - return nil, err - } - - // Create the transport socket - ts := &pbproxystate.TransportSocket{} - - ts.ConnectionTls = &pbproxystate.TransportSocket_OutboundMesh{ - OutboundMesh: &pbproxystate.OutboundMeshMTLS{ - IdentityKey: uuid, - ValidationContext: &pbproxystate.MeshOutboundValidationContext{ - TrustBundlePeerNameKey: trustBundlePeerNames[0], - SpiffeIds: spiffeIDs, - }, - Sni: sni, - }, - } - s.proxyState.LeafCertificates[uuid] = &pbproxystate.LeafCertificate{ - Cert: cfgSnap.Leaf().CertPEM, - Key: cfgSnap.Leaf().PrivateKeyPEM, - } - ts.TlsParameters = makeTLSParametersFromProxyTLSConfig(cfgSnap.MeshConfigTLSOutgoing()) - ts.AlpnProtocols = getAlpnProtocols(cfg.Protocol) - - return ts, nil -} -func (s *Converter) makeUpstreamClustersForDiscoveryChain( - uid proxycfg.UpstreamID, - upstream *structs.Upstream, - chain *structs.CompiledDiscoveryChain, - cfgSnap *proxycfg.ConfigSnapshot, - forMeshGateway bool, -) (map[string]*pbproxystate.Cluster, error) { - if chain == nil { - return nil, fmt.Errorf("cannot create upstream cluster without discovery chain for %s", uid) - } - - if uid.Peer != "" && forMeshGateway { - return nil, fmt.Errorf("impossible to get a peer discovery chain in a mesh gateway") - } - - upstreamConfigMap := make(map[string]interface{}) - if upstream != nil { - upstreamConfigMap = upstream.Config - } - - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - - // Mesh gateways are exempt because upstreamsSnapshot is only used for - // cluster peering targets and transative failover/redirects are unsupported. - if err != nil && !forMeshGateway { - return nil, err - } - - rawUpstreamConfig, err := structs.ParseUpstreamConfigNoDefaults(upstreamConfigMap) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse", "upstream", uid, - "error", err) - } - - // TODO(proxystate): escapeHatches will be implemented in the future - //var escapeHatchCluster *pbproxystate.Cluster - //if !forMeshGateway { - // if rawUpstreamConfig.EnvoyClusterJSON != "" { - // if chain.Default { - // // If you haven't done anything to setup the discovery chain, then - // // you can use the envoy_cluster_json escape hatch. - // escapeHatchCluster = &pbproxystate.Cluster{ - // EscapeHatchClusterJson: rawUpstreamConfig.EnvoyClusterJSON, - // } - // } else { - // s.Logger.Warn("ignoring escape hatch setting, because a discovery chain is configured for", - // "discovery chain", chain.ServiceName, "upstream", uid, - // "envoy_cluster_json", chain.ServiceName) - // } - // } - //} - - out := make(map[string]*pbproxystate.Cluster) - for _, node := range chain.Nodes { - switch { - case node == nil: - return nil, fmt.Errorf("impossible to process a nil node") - case node.Type != structs.DiscoveryGraphNodeTypeResolver: - continue - case node.Resolver == nil: - return nil, fmt.Errorf("impossible to process a non-resolver node") - } - // These variables are prefixed with primary to avoid shaddowing bugs. - primaryTargetID := node.Resolver.Target - primaryTarget := chain.Targets[primaryTargetID] - primaryTargetClusterName := s.getTargetClusterName(upstreamsSnapshot, chain, primaryTargetID, forMeshGateway) - if primaryTargetClusterName == "" { - continue - } - if forMeshGateway && !cfgSnap.Locality.Matches(primaryTarget.Datacenter, primaryTarget.Partition) { - s.Logger.Warn("ignoring discovery chain target that crosses a datacenter or partition boundary in a mesh gateway", - "target", primaryTarget, - "gatewayLocality", cfgSnap.Locality, - ) - continue - } - - upstreamConfig := finalizeUpstreamConfig(rawUpstreamConfig, chain, node.Resolver.ConnectTimeout) - - mappedTargets, err := s.mapDiscoChainTargets(cfgSnap, chain, node, upstreamConfig, forMeshGateway) - if err != nil { - return nil, err - } - - targetGroups, err := mappedTargets.groupedTargets() - if err != nil { - return nil, err - } - - var failoverGroup *pbproxystate.FailoverGroup - endpointGroups := make([]*pbproxystate.EndpointGroup, 0) - if mappedTargets.failover { - // Create a failover group. The endpoint groups that are part of this failover group are created by the loop - // below. - failoverGroup = &pbproxystate.FailoverGroup{ - Config: &pbproxystate.FailoverGroupConfig{ - ConnectTimeout: durationpb.New(node.Resolver.ConnectTimeout), - UseAltStatName: true, - }, - } - } - - // Construct the target dynamic endpoint groups. If these are not part of a failover group, they will get added - // directly to the map of pbproxystate.Cluster, if they are a part of a failover group, they will be added to - // the failover group. - for _, groupedTarget := range targetGroups { - s.Logger.Debug("generating cluster for", "cluster", groupedTarget.ClusterName) - dynamic := &pbproxystate.DynamicEndpointGroup{ - Config: &pbproxystate.DynamicEndpointGroupConfig{ - UseAltStatName: true, - ConnectTimeout: durationpb.New(node.Resolver.ConnectTimeout), - // TODO(peering): make circuit breakers or outlier detection work? - CircuitBreakers: &pbproxystate.CircuitBreakers{ - UpstreamLimits: makeUpstreamLimitsIfNeeded(upstreamConfig.Limits), - }, - DisablePanicThreshold: true, - OutlierDetection: makeOutlierDetection(upstreamConfig.PassiveHealthCheck, nil, true), - }, - } - ti := groupedTarget.Targets[0] - transportSocket, err := s.createOutboundMeshMTLS(cfgSnap, ti.SpiffeIDs, ti.SNI) - if err != nil { - return nil, err - } - dynamic.OutboundTls = transportSocket - - var lb *structs.LoadBalancer - if node.LoadBalancer != nil { - lb = node.LoadBalancer - } - if err := injectLBToCluster(lb, dynamic.Config); err != nil { - return nil, fmt.Errorf("failed to apply load balancer configuration to cluster %q: %v", groupedTarget.ClusterName, err) - } - - // TODO: IR: http2 options not currently supported - //if upstreamConfig.Protocol == "http2" || upstreamConfig.Protocol == "grpc" { - // if err := s.setHttp2ProtocolOptions(c); err != nil { - // return nil, err - // } - //} - - switch len(groupedTarget.Targets) { - case 0: - continue - case 1: - // We expect one target so this passes through to continue setting the cluster up. - default: - return nil, fmt.Errorf("cannot have more than one target") - } - - if targetInfo := groupedTarget.Targets[0]; targetInfo.TransportSocket != nil { - dynamic.OutboundTls = targetInfo.TransportSocket - } - - // If the endpoint group is part of a failover group, add it to the failover group. Otherwise add it - // directly to the clusters. - if failoverGroup != nil { - eg := &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Dynamic{ - Dynamic: dynamic, - }, - Name: groupedTarget.ClusterName, - } - endpointGroups = append(endpointGroups, eg) - } else { - cluster := &pbproxystate.Cluster{ - AltStatName: mappedTargets.baseClusterName, - Protocol: protocolMap[upstreamConfig.Protocol], - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Dynamic{ - Dynamic: dynamic, - }, - }, - }, - Name: mappedTargets.baseClusterName, - } - - out[mappedTargets.baseClusterName] = cluster - } - } - - // If there's a failover group, we only add the failover group to the top level list of clusters. Its endpoint - // groups are inlined. - if failoverGroup != nil { - failoverGroup.EndpointGroups = endpointGroups - cluster := &pbproxystate.Cluster{ - AltStatName: mappedTargets.baseClusterName, - Protocol: protocolMap[upstreamConfig.Protocol], - Group: &pbproxystate.Cluster_FailoverGroup{ - FailoverGroup: failoverGroup, - }, - } - out[mappedTargets.baseClusterName] = cluster - } - } - - //if escapeHatchCluster != nil { - // if len(out) != 1 { - // return nil, fmt.Errorf("cannot inject escape hatch cluster when discovery chain had no nodes") - // } - // var defaultCluster *pbproxystate.Cluster - // for _, k := range out { - // defaultCluster = k - // break - // } - // - // // Overlay what the user provided. - // escapeHatchCluster.GetEndpointGroup().GetDynamic().OutboundTls.ConnectionTls = - // defaultCluster.GetEndpointGroup().GetDynamic().OutboundTls.ConnectionTls - // - // out = append(out, escapeHatchCluster) - //} - - return out, nil -} - -// TODO(proxystate): Mesh Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeExportedUpstreamClustersForMeshGateway - -// makeClusterFromUserConfig returns the listener config decoded from an -// arbitrary proto3 json format string or an error if it's invalid. -// -// For now we only support embedding in JSON strings because of the hcl parsing -// pain (see Background section in the comment for decode.HookWeakDecodeFromSlice). -// This may be fixed in decode.HookWeakDecodeFromSlice in the future. -// -// When we do that we can support just nesting the config directly into the -// JSON/hcl naturally but this is a stop-gap that gets us an escape hatch -// immediately. It's also probably not a bad thing to support long-term since -// any config generated by other systems will likely be in canonical protobuf -// from rather than our slight variant in JSON/hcl. - -// TODO(proxystate): Mesh and Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeGatewayCluster - -func configureClusterWithHostnames( - logger hclog.Logger, - dnsEndpointGroup *pbproxystate.DNSEndpointGroup, - endpointList *pbproxystate.Endpoints, - dnsDiscoveryType string, - // hostnameEndpoints is a list of endpoints with a hostname as their address - hostnameEndpoints structs.CheckServiceNodes, - // isRemote determines whether the cluster is in a remote DC or partition and we should prefer a WAN address - isRemote bool, - // onlyPassing determines whether endpoints that do not have a passing status should be considered unhealthy - onlyPassing bool, -) { - // When a service instance is addressed by a hostname we have Envoy do the DNS resolution - // by setting a DNS cluster type and passing the hostname endpoints via CDS. - if dnsEndpointGroup.Config == nil { - dnsEndpointGroup.Config = &pbproxystate.DNSEndpointGroupConfig{} - } - dnsEndpointGroup.Config.DiscoveryType = pbproxystate.DiscoveryType_DISCOVERY_TYPE_LOGICAL - if dnsDiscoveryType == "strict_dns" { - dnsEndpointGroup.Config.DiscoveryType = pbproxystate.DiscoveryType_DISCOVERY_TYPE_STRICT - } - - endpoints := make([]*envoy_endpoint_v3.LbEndpoint, 0, 1) - uniqueHostnames := make(map[string]bool) - - var ( - hostname string - idx int - fallback *pbproxystate.Endpoint - ) - for i, e := range hostnameEndpoints { - _, addr, port := e.BestAddress(isRemote) - uniqueHostnames[addr] = true - - health, weight := calculateEndpointHealthAndWeight(e, onlyPassing) - if health == pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY { - fallback = makeLbEndpoint(addr, port, health, weight) - continue - } - - if len(endpoints) == 0 { - endpointList.Endpoints = append(endpointList.Endpoints, makeLbEndpoint(addr, port, health, weight)) - - hostname = addr - idx = i - break - } - } - - dc := hostnameEndpoints[idx].Node.Datacenter - service := hostnameEndpoints[idx].Service.CompoundServiceName() - - // Fall back to last unhealthy endpoint if none were healthy - if len(endpoints) == 0 { - logger.Warn("upstream service does not contain any healthy instances", - "dc", dc, "service", service.String()) - - //endpoints = append(endpoints, fallback) - endpointList.Endpoints = append(endpointList.Endpoints, fallback) - } - if len(uniqueHostnames) > 1 { - logger.Warn(fmt.Sprintf("service contains instances with more than one unique hostname; only %q be resolved by Envoy", hostname), - "dc", dc, "service", service.String()) - } - -} - -// TODO(proxystate): Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeExternalIPCluster - -// TODO(proxystate): Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func makeExternalHostnameCluster - -func makeUpstreamLimitsIfNeeded(limits *structs.UpstreamLimits) *pbproxystate.UpstreamLimits { - if limits == nil { - return nil - } - - upstreamLimits := &pbproxystate.UpstreamLimits{} - - // Likewise, make sure to not set any threshold values on the zero-value in - // order to rely on Envoy defaults - if limits.MaxConnections != nil { - upstreamLimits.MaxConnections = response.MakeUint32Value(*limits.MaxConnections) - } - if limits.MaxPendingRequests != nil { - upstreamLimits.MaxPendingRequests = response.MakeUint32Value(*limits.MaxPendingRequests) - } - if limits.MaxConcurrentRequests != nil { - upstreamLimits.MaxConcurrentRequests = response.MakeUint32Value(*limits.MaxConcurrentRequests) - } - - return upstreamLimits -} - -func injectLBToCluster(ec *structs.LoadBalancer, dc *pbproxystate.DynamicEndpointGroupConfig) error { - if ec == nil { - return nil - } - - switch ec.Policy { - case "": - return nil - case structs.LBPolicyLeastRequest: - lr := &pbproxystate.DynamicEndpointGroupConfig_LeastRequest{ - LeastRequest: &pbproxystate.LBPolicyLeastRequest{}, - } - - dc.LbPolicy = lr - - if ec.LeastRequestConfig != nil { - lr.LeastRequest.ChoiceCount = &wrapperspb.UInt32Value{Value: ec.LeastRequestConfig.ChoiceCount} - } - case structs.LBPolicyRoundRobin: - dc.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_RoundRobin{ - RoundRobin: &pbproxystate.LBPolicyRoundRobin{}, - } - - case structs.LBPolicyRandom: - dc.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_Random{ - Random: &pbproxystate.LBPolicyRandom{}, - } - - case structs.LBPolicyRingHash: - rh := &pbproxystate.DynamicEndpointGroupConfig_RingHash{ - RingHash: &pbproxystate.LBPolicyRingHash{}, - } - - dc.LbPolicy = rh - - if ec.RingHashConfig != nil { - rh.RingHash.MinimumRingSize = &wrapperspb.UInt64Value{Value: ec.RingHashConfig.MinimumRingSize} - rh.RingHash.MaximumRingSize = &wrapperspb.UInt64Value{Value: ec.RingHashConfig.MaximumRingSize} - } - case structs.LBPolicyMaglev: - dc.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_Maglev{ - Maglev: &pbproxystate.LBPolicyMaglev{}, - } - - default: - return fmt.Errorf("unsupported load balancer policy %q", ec.Policy) - } - return nil -} - -// generatePeeredClusterName returns an SNI-like cluster name which mimics PeeredServiceSNI -// but excludes partition information which could be ambiguous (local vs remote partition). -func generatePeeredClusterName(uid proxycfg.UpstreamID, tb *pbpeering.PeeringTrustBundle) string { - return strings.Join([]string{ - uid.Name, - uid.NamespaceOrDefault(), - uid.Peer, - "external", - tb.TrustDomain, - }, ".") -} - -func (s *Converter) getTargetClusterName(upstreamsSnapshot *proxycfg.ConfigSnapshotUpstreams, chain *structs.CompiledDiscoveryChain, tid string, forMeshGateway bool) string { - target := chain.Targets[tid] - clusterName := target.Name - targetUID := proxycfg.NewUpstreamIDFromTargetID(tid) - if targetUID.Peer != "" { - tbs, ok := upstreamsSnapshot.UpstreamPeerTrustBundles.Get(targetUID.Peer) - // We can't generate cluster on peers without the trust bundle. The - // trust bundle should be ready soon. - if !ok { - s.Logger.Debug("peer trust bundle not ready for discovery chain target", - "peer", targetUID.Peer, - "target", tid, - ) - return "" - } - - clusterName = generatePeeredClusterName(targetUID, tbs) - } - clusterName = naming.CustomizeClusterName(clusterName, chain) - if forMeshGateway { - clusterName = meshGatewayExportedClusterNamePrefix + clusterName - } - return clusterName -} - -// Return an pbproxystate.OutlierDetection populated by the values from structs.PassiveHealthCheck. -// If all values are zero a default empty OutlierDetection will be returned to -// enable outlier detection with default values. -// - If override is not nil, it will overwrite the values from p, e.g., ingress gateway defaults -// - allowZero is added to handle the legacy case where connect-proxy and mesh gateway can set 0 -// for EnforcingConsecutive5xx. Due to the definition of proto of PassiveHealthCheck, ingress -// gateway's EnforcingConsecutive5xx must be > 0. -func makeOutlierDetection(p *structs.PassiveHealthCheck, override *structs.PassiveHealthCheck, allowZero bool) *pbproxystate.OutlierDetection { - od := &pbproxystate.OutlierDetection{} - if p != nil { - - if p.Interval != 0 { - od.Interval = durationpb.New(p.Interval) - } - if p.MaxFailures != 0 { - od.Consecutive_5Xx = &wrapperspb.UInt32Value{Value: p.MaxFailures} - } - - if p.EnforcingConsecutive5xx != nil { - // NOTE: EnforcingConsecutive5xx must be greater than 0 for ingress-gateway - if *p.EnforcingConsecutive5xx != 0 { - od.EnforcingConsecutive_5Xx = &wrapperspb.UInt32Value{Value: *p.EnforcingConsecutive5xx} - } else if allowZero { - od.EnforcingConsecutive_5Xx = &wrapperspb.UInt32Value{Value: *p.EnforcingConsecutive5xx} - } - } - - if p.MaxEjectionPercent != nil { - od.MaxEjectionPercent = &wrapperspb.UInt32Value{Value: *p.MaxEjectionPercent} - } - if p.BaseEjectionTime != nil { - od.BaseEjectionTime = durationpb.New(*p.BaseEjectionTime) - } - } - - if override == nil { - return od - } - - // override the default outlier detection value - if override.Interval != 0 { - od.Interval = durationpb.New(override.Interval) - } - if override.MaxFailures != 0 { - od.Consecutive_5Xx = &wrapperspb.UInt32Value{Value: override.MaxFailures} - } - - if override.EnforcingConsecutive5xx != nil { - // NOTE: EnforcingConsecutive5xx must be great than 0 for ingress-gateway - if *override.EnforcingConsecutive5xx != 0 { - od.EnforcingConsecutive_5Xx = &wrapperspb.UInt32Value{Value: *override.EnforcingConsecutive5xx} - } - // Because only ingress gateways have overrides and they cannot have a value of 0, there is no allowZero - // override case to handle - } - - if override.MaxEjectionPercent != nil { - od.MaxEjectionPercent = &wrapperspb.UInt32Value{Value: *override.MaxEjectionPercent} - } - if override.BaseEjectionTime != nil { - od.BaseEjectionTime = durationpb.New(*override.BaseEjectionTime) - } - - return od -} - -// protocolMap converts config entry protocols to proxystate protocol values. -// As documented on config entry protos, the valid values are "tcp", "http", -// "http2" and "grpc". Anything else is treated as tcp. -var protocolMap = map[string]pbproxystate.Protocol{ - "http": pbproxystate.Protocol_PROTOCOL_HTTP, - "http2": pbproxystate.Protocol_PROTOCOL_HTTP2, - "grpc": pbproxystate.Protocol_PROTOCOL_GRPC, - "tcp": pbproxystate.Protocol_PROTOCOL_TCP, -} diff --git a/agent/xds/proxystateconverter/converter.go b/agent/xds/proxystateconverter/converter.go deleted file mode 100644 index 4c31127400d2..000000000000 --- a/agent/xds/proxystateconverter/converter.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "fmt" - - "github.com/hashicorp/go-hclog" - - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/configfetcher" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" -) - -// Converter converts a single snapshot into a ProxyState. -type Converter struct { - Logger hclog.Logger - CfgFetcher configfetcher.ConfigFetcher - proxyState *proxytracker.ProxyState -} - -func NewConverter( - logger hclog.Logger, - cfgFetcher configfetcher.ConfigFetcher, -) *Converter { - return &Converter{ - Logger: logger, - CfgFetcher: cfgFetcher, - proxyState: &proxytracker.ProxyState{ - ProxyState: &pbmesh.ProxyState{ - Listeners: make([]*pbproxystate.Listener, 0), - Clusters: make(map[string]*pbproxystate.Cluster), - Routes: make(map[string]*pbproxystate.Route), - Endpoints: make(map[string]*pbproxystate.Endpoints), - }, - }, - } -} - -func (g *Converter) ProxyStateFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) (*proxytracker.ProxyState, error) { - err := g.resourcesFromSnapshot(cfgSnap) - if err != nil { - return nil, fmt.Errorf("failed to generate FullProxyState: %v", err) - } - - return g.proxyState, nil -} - -func (g *Converter) resourcesFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) error { - err := g.tlsConfigFromSnapshot(cfgSnap) - if err != nil { - return err - } - - err = g.listenersFromSnapshot(cfgSnap) - if err != nil { - return err - } - - err = g.endpointsFromSnapshot(cfgSnap) - if err != nil { - return err - } - err = g.clustersFromSnapshot(cfgSnap) - if err != nil { - return err - } - err = g.routesFromSnapshot(cfgSnap) - if err != nil { - return err - } - - //g.secretsFromSnapshot(cfgSnap) - return nil -} - -const localPeerKey = "local" - -func (g *Converter) tlsConfigFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) error { - proxyStateTLS := &pbproxystate.TLS{} - g.proxyState.TrustBundles = make(map[string]*pbproxystate.TrustBundle) - g.proxyState.LeafCertificates = make(map[string]*pbproxystate.LeafCertificate) - - // Set the TLS in the top level proxyState - g.proxyState.Tls = proxyStateTLS - - // Add local trust bundle - g.proxyState.TrustBundles[localPeerKey] = &pbproxystate.TrustBundle{ - TrustDomain: cfgSnap.Roots.TrustDomain, - Roots: []string{cfgSnap.RootPEMs()}, - } - - // Add peered trust bundles for remote peers that will dial this proxy. - for _, peeringTrustBundle := range cfgSnap.PeeringTrustBundles() { - g.proxyState.TrustBundles[peeringTrustBundle.PeerName] = &pbproxystate.TrustBundle{ - TrustDomain: peeringTrustBundle.GetTrustDomain(), - Roots: peeringTrustBundle.RootPEMs, - } - } - - // Add upstream peer trust bundles for dialing upstreams in remote peers. - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil { - if !(cfgSnap.Kind == structs.ServiceKindMeshGateway || cfgSnap.Kind == structs.ServiceKindTerminatingGateway) { - return err - } - } - if upstreamsSnapshot != nil { - upstreamsSnapshot.UpstreamPeerTrustBundles.ForEachKeyE(func(k proxycfg.PeerName) error { - tbs, ok := upstreamsSnapshot.UpstreamPeerTrustBundles.Get(k) - if ok { - g.proxyState.TrustBundles[k] = &pbproxystate.TrustBundle{ - TrustDomain: tbs.TrustDomain, - Roots: tbs.RootPEMs, - } - } - return nil - }) - } - - if cfgSnap.MeshConfigTLSOutgoing() != nil { - proxyStateTLS.OutboundTlsParameters = makeTLSParametersFromTLSConfig(cfgSnap.MeshConfigTLSOutgoing().TLSMinVersion, - cfgSnap.MeshConfigTLSOutgoing().TLSMaxVersion, cfgSnap.MeshConfigTLSOutgoing().CipherSuites) - } - - if cfgSnap.MeshConfigTLSIncoming() != nil { - proxyStateTLS.InboundTlsParameters = makeTLSParametersFromTLSConfig(cfgSnap.MeshConfigTLSIncoming().TLSMinVersion, - cfgSnap.MeshConfigTLSIncoming().TLSMaxVersion, cfgSnap.MeshConfigTLSIncoming().CipherSuites) - } - - return nil -} diff --git a/agent/xds/proxystateconverter/endpoints.go b/agent/xds/proxystateconverter/endpoints.go deleted file mode 100644 index 2ed7164316c1..000000000000 --- a/agent/xds/proxystateconverter/endpoints.go +++ /dev/null @@ -1,671 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "errors" - "fmt" - - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/go-bexpr" - - "google.golang.org/protobuf/types/known/wrapperspb" -) - -func makeLbEndpoint(addr string, port int, health pbproxystate.HealthStatus, weight int) *pbproxystate.Endpoint { - ep := &pbproxystate.Endpoint{ - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: addr, - Port: uint32(port), - }, - }, - } - ep.HealthStatus = health - ep.LoadBalancingWeight = &wrapperspb.UInt32Value{Value: uint32(weight)} - return ep -} - -// endpointsFromSnapshot returns the mesh API representation of the "routes" in the snapshot. -func (s *Converter) endpointsFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) error { - - if cfgSnap == nil { - return errors.New("nil config given") - } - - switch cfgSnap.Kind { - case structs.ServiceKindConnectProxy: - return s.endpointsFromSnapshotConnectProxy(cfgSnap) - //case structs.ServiceKindTerminatingGateway: - // return s.endpointsFromSnapshotTerminatingGateway(cfgSnap) - //case structs.ServiceKindMeshGateway: - // return s.endpointsFromSnapshotMeshGateway(cfgSnap) - //case structs.ServiceKindIngressGateway: - // return s.endpointsFromSnapshotIngressGateway(cfgSnap) - //case structs.ServiceKindAPIGateway: - // return s.endpointsFromSnapshotAPIGateway(cfgSnap) - default: - return fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind) - } -} - -// endpointsFromSnapshotConnectProxy returns the xDS API representation of the "endpoints" -// (upstream instances) in the snapshot. -func (s *Converter) endpointsFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnapshot) error { - eps := make(map[string]*pbproxystate.Endpoints) - - // NOTE: Any time we skip a chain below we MUST also skip that discovery chain in clusters.go - // so that the sets of endpoints generated matches the sets of clusters. - for uid, chain := range cfgSnap.ConnectProxy.DiscoveryChain { - upstream, skip := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta) - if skip { - // Discovery chain is not associated with a known explicit or implicit upstream so it is skipped. - continue - } - - var upstreamConfigMap map[string]interface{} - if upstream != nil { - upstreamConfigMap = upstream.Config - } - - es, err := s.endpointsFromDiscoveryChain( - uid, - chain, - cfgSnap, - cfgSnap.Locality, - upstreamConfigMap, - cfgSnap.ConnectProxy.WatchedUpstreamEndpoints[uid], - cfgSnap.ConnectProxy.WatchedGatewayEndpoints[uid], - false, - ) - if err != nil { - return err - } - - for clusterName, endpoints := range es { - eps[clusterName] = &pbproxystate.Endpoints{ - Endpoints: endpoints, - } - - } - } - - // NOTE: Any time we skip an upstream below we MUST also skip that same - // upstream in clusters.go so that the sets of endpoints generated matches - // the sets of clusters. - for _, uid := range cfgSnap.ConnectProxy.PeeredUpstreamIDs() { - upstream, skip := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta) - if skip { - // Discovery chain is not associated with a known explicit or implicit upstream so it is skipped. - continue - } - - tbs, ok := cfgSnap.ConnectProxy.UpstreamPeerTrustBundles.Get(uid.Peer) - if !ok { - // this should never happen since we loop through upstreams with - // set trust bundles - return fmt.Errorf("trust bundle not ready for peer %s", uid.Peer) - } - - clusterName := generatePeeredClusterName(uid, tbs) - - mgwMode := structs.MeshGatewayModeDefault - if upstream != nil { - mgwMode = upstream.MeshGateway.Mode - } - peerServiceEndpoints, err := s.makeEndpointsForPeerService(cfgSnap, uid, mgwMode) - if err != nil { - return err - } - - if peerServiceEndpoints != nil { - pbEndpoints := &pbproxystate.Endpoints{ - Endpoints: peerServiceEndpoints, - } - - eps[clusterName] = pbEndpoints - } - } - - // Looping over explicit upstreams is only needed for prepared queries because they do not have discovery chains - for _, u := range cfgSnap.Proxy.Upstreams { - if u.DestinationType != structs.UpstreamDestTypePreparedQuery { - continue - } - uid := proxycfg.NewUpstreamID(&u) - - dc := u.Datacenter - if dc == "" { - dc = cfgSnap.Datacenter - } - clusterName := connect.UpstreamSNI(&u, "", dc, cfgSnap.Roots.TrustDomain) - - endpoints, ok := cfgSnap.ConnectProxy.PreparedQueryEndpoints[uid] - if ok { - epts := makeEndpointsForLoadAssignment( - cfgSnap, - nil, - []loadAssignmentEndpointGroup{ - {Endpoints: endpoints}, - }, - cfgSnap.Locality, - ) - pbEndpoints := &pbproxystate.Endpoints{ - Endpoints: epts, - } - - eps[clusterName] = pbEndpoints - } - } - - // Loop over potential destinations in the mesh, then grab the gateway nodes associated with each - cfgSnap.ConnectProxy.DestinationsUpstream.ForEachKey(func(uid proxycfg.UpstreamID) bool { - svcConfig, ok := cfgSnap.ConnectProxy.DestinationsUpstream.Get(uid) - if !ok || svcConfig.Destination == nil { - return true - } - - for _, address := range svcConfig.Destination.Addresses { - clusterName := clusterNameForDestination(cfgSnap, uid.Name, address, uid.NamespaceOrDefault(), uid.PartitionOrDefault()) - - endpoints, ok := cfgSnap.ConnectProxy.DestinationGateways.Get(uid) - if ok { - epts := makeEndpointsForLoadAssignment( - cfgSnap, - nil, - []loadAssignmentEndpointGroup{ - {Endpoints: endpoints}, - }, - proxycfg.GatewayKey{ /*empty so it never matches*/ }, - ) - pbEndpoints := &pbproxystate.Endpoints{ - Endpoints: epts, - } - eps[clusterName] = pbEndpoints - } - } - - return true - }) - - s.proxyState.Endpoints = eps - return nil -} - -func (s *Converter) makeEndpointsForPeerService( - cfgSnap *proxycfg.ConfigSnapshot, - uid proxycfg.UpstreamID, - upstreamGatewayMode structs.MeshGatewayMode, -) ([]*pbproxystate.Endpoint, error) { - var eps []*pbproxystate.Endpoint - - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil { - return eps, err - } - - if upstreamGatewayMode == structs.MeshGatewayModeNone { - s.Logger.Warn(fmt.Sprintf("invalid mesh gateway mode 'none', defaulting to 'remote' for %q", uid)) - } - - // If an upstream is configured with local mesh gw mode, we make a load assignment - // from the gateway endpoints instead of those of the upstreams. - if upstreamGatewayMode == structs.MeshGatewayModeLocal { - localGw, ok := cfgSnap.ConnectProxy.WatchedLocalGWEndpoints.Get(cfgSnap.Locality.String()) - if !ok { - // local GW is not ready; return early - return eps, nil - } - eps = makeEndpointsForLoadAssignment( - cfgSnap, - nil, - []loadAssignmentEndpointGroup{ - {Endpoints: localGw}, - }, - cfgSnap.Locality, - ) - return eps, nil - } - - // Also skip peer instances with a hostname as their address. EDS - // cannot resolve hostnames, so we provide them through CDS instead. - if _, ok := upstreamsSnapshot.PeerUpstreamEndpointsUseHostnames[uid]; ok { - return eps, nil - } - - endpoints, ok := upstreamsSnapshot.PeerUpstreamEndpoints.Get(uid) - if !ok { - return nil, nil - } - eps = makeEndpointsForLoadAssignment( - cfgSnap, - nil, - []loadAssignmentEndpointGroup{ - {Endpoints: endpoints}, - }, - proxycfg.GatewayKey{ /*empty so it never matches*/ }, - ) - return eps, nil -} - -func (s *Converter) filterSubsetEndpoints(subset *structs.ServiceResolverSubset, endpoints structs.CheckServiceNodes) (structs.CheckServiceNodes, error) { - // locally execute the subsets filter - if subset.Filter != "" { - filter, err := bexpr.CreateFilter(subset.Filter, nil, endpoints) - if err != nil { - return nil, err - } - - raw, err := filter.Execute(endpoints) - if err != nil { - return nil, err - } - return raw.(structs.CheckServiceNodes), nil - } - return endpoints, nil -} - -// TODO(proxystate): Terminating Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func endpointsFromSnapshotTerminatingGateway - -// TODO(proxystate): Mesh Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func endpointsFromSnapshotMeshGateway - -// TODO(proxystate): Cluster Peering will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func makeEndpointsForOutgoingPeeredServices - -// TODO(proxystate): Mesh Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func endpointsFromServicesAndResolvers - -// TODO(proxystate): Mesh Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func makePeerServerEndpointsForMeshGateway - -// TODO(proxystate): Ingress Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func endpointsFromSnapshotIngressGateway - -// TODO(proxystate): API Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func endpointsFromSnapshotAPIGateway - -// used in clusters.go -func makeHostPortEndpoint(host string, port int) *pbproxystate.Endpoint { - return &pbproxystate.Endpoint{ - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: host, - Port: uint32(port), - }, - }, - } -} - -func makeUnixSocketEndpoint(path string) *pbproxystate.Endpoint { - return &pbproxystate.Endpoint{ - Address: &pbproxystate.Endpoint_UnixSocket{ - UnixSocket: &pbproxystate.UnixSocketAddress{ - Path: path, - // envoy's mode is particular to a pipe address and is uint32. - // it also says "The mode for the Pipe. Not applicable for abstract sockets." - // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-pipe - Mode: "0", - }, - }, - } -} - -func (s *Converter) makeUpstreamLoadAssignmentEndpointForPeerService( - cfgSnap *proxycfg.ConfigSnapshot, - uid proxycfg.UpstreamID, - upstreamGatewayMode structs.MeshGatewayMode, -) ([]*pbproxystate.Endpoint, error) { - var eps []*pbproxystate.Endpoint - - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil { - return eps, err - } - - if upstreamGatewayMode == structs.MeshGatewayModeNone { - s.Logger.Warn(fmt.Sprintf("invalid mesh gateway mode 'none', defaulting to 'remote' for %q", uid)) - } - - // If an upstream is configured with local mesh gw mode, we make a load assignment - // from the gateway endpoints instead of those of the upstreams. - if upstreamGatewayMode == structs.MeshGatewayModeLocal { - localGw, ok := cfgSnap.ConnectProxy.WatchedLocalGWEndpoints.Get(cfgSnap.Locality.String()) - if !ok { - // local GW is not ready; return early - return eps, nil - } - eps = makeEndpointsForLoadAssignment( - cfgSnap, - nil, - []loadAssignmentEndpointGroup{ - {Endpoints: localGw}, - }, - cfgSnap.Locality, - ) - return eps, nil - } - - // Also skip peer instances with a hostname as their address. EDS - // cannot resolve hostnames, so we provide them through CDS instead. - if _, ok := upstreamsSnapshot.PeerUpstreamEndpointsUseHostnames[uid]; ok { - return eps, nil - } - - endpoints, ok := upstreamsSnapshot.PeerUpstreamEndpoints.Get(uid) - if !ok { - return nil, nil - } - eps = makeEndpointsForLoadAssignment( - cfgSnap, - nil, - []loadAssignmentEndpointGroup{ - {Endpoints: endpoints}, - }, - proxycfg.GatewayKey{ /*empty so it never matches*/ }, - ) - return eps, nil -} - -func (s *Converter) endpointsFromDiscoveryChain( - uid proxycfg.UpstreamID, - chain *structs.CompiledDiscoveryChain, - cfgSnap *proxycfg.ConfigSnapshot, - gatewayKey proxycfg.GatewayKey, - upstreamConfigMap map[string]interface{}, - upstreamEndpoints map[string]structs.CheckServiceNodes, - gatewayEndpoints map[string]structs.CheckServiceNodes, - forMeshGateway bool, -) (map[string][]*pbproxystate.Endpoint, error) { - if chain == nil { - if forMeshGateway { - return nil, fmt.Errorf("missing discovery chain for %s", uid) - } - return nil, nil - } - - if upstreamConfigMap == nil { - upstreamConfigMap = make(map[string]interface{}) // TODO:needed? - } - - clusterEndpoints := make(map[string][]*pbproxystate.Endpoint) - - // TODO(proxystate): escape hatches will be implemented in the future - //var escapeHatchCluster *pbproxystate.Cluster - //if !forMeshGateway { - - //cfg, err := structs.ParseUpstreamConfigNoDefaults(upstreamConfigMap) - //if err != nil { - // // Don't hard fail on a config typo, just warn. The parse func returns - // // default config if there is an error so it's safe to continue. - // s.Logger.Warn("failed to parse", "upstream", uid, - // "error", err) - //} - - //if cfg.EnvoyClusterJSON != "" { - // if chain.Default { - // // If you haven't done anything to setup the discovery chain, then - // // you can use the envoy_cluster_json escape hatch. - // escapeHatchCluster, err = makeClusterFromUserConfig(cfg.EnvoyClusterJSON) - // if err != nil { - // return ce, nil - // } - // } else { - // s.Logger.Warn("ignoring escape hatch setting, because a discovery chain is configued for", - // "discovery chain", chain.ServiceName, "upstream", uid, - // "envoy_cluster_json", chain.ServiceName) - // } - //} - //} - - mgwMode := structs.MeshGatewayModeDefault - if upstream, _ := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta); upstream != nil { - mgwMode = upstream.MeshGateway.Mode - } - - // Find all resolver nodes. - for _, node := range chain.Nodes { - switch { - case node == nil: - return nil, fmt.Errorf("impossible to process a nil node") - case node.Type != structs.DiscoveryGraphNodeTypeResolver: - continue - case node.Resolver == nil: - return nil, fmt.Errorf("impossible to process a non-resolver node") - } - rawUpstreamConfig, err := structs.ParseUpstreamConfigNoDefaults(upstreamConfigMap) - if err != nil { - return nil, err - } - upstreamConfig := finalizeUpstreamConfig(rawUpstreamConfig, chain, node.Resolver.ConnectTimeout) - - mappedTargets, err := s.mapDiscoChainTargets(cfgSnap, chain, node, upstreamConfig, forMeshGateway) - if err != nil { - return nil, err - } - - targetGroups, err := mappedTargets.groupedTargets() - if err != nil { - return nil, err - } - - for _, groupedTarget := range targetGroups { - clusterName := groupedTarget.ClusterName - // TODO(proxystate): escape hatches will be implemented in the future - //if escapeHatchCluster != nil { - // clusterName = escapeHatchCluster.Name - //} - switch len(groupedTarget.Targets) { - case 0: - continue - case 1: - // We expect one target so this passes through to continue setting the load assignment up. - default: - return nil, fmt.Errorf("cannot have more than one target") - } - ti := groupedTarget.Targets[0] - s.Logger.Debug("generating endpoints for", "cluster", clusterName, "targetID", ti.TargetID) - targetUID := proxycfg.NewUpstreamIDFromTargetID(ti.TargetID) - if targetUID.Peer != "" { - peerServiceEndpoints, err := s.makeEndpointsForPeerService(cfgSnap, targetUID, mgwMode) - if err != nil { - return nil, err - } - if peerServiceEndpoints != nil { - clusterEndpoints[clusterName] = peerServiceEndpoints - } - continue - } - - endpointGroup, valid := makeLoadAssignmentEndpointGroup( - chain.Targets, - upstreamEndpoints, - gatewayEndpoints, - ti.TargetID, - gatewayKey, - forMeshGateway, - ) - if !valid { - continue // skip the cluster if we're still populating the snapshot - } - - epts := makeEndpointsForLoadAssignment( - cfgSnap, - ti.PrioritizeByLocality, - []loadAssignmentEndpointGroup{endpointGroup}, - gatewayKey, - ) - clusterEndpoints[clusterName] = epts - } - } - - return clusterEndpoints, nil -} - -// TODO(proxystate): Mesh Gateway will be added in the future. -// Functions to add from agent/xds/endpoints.go: -// func makeExportedUpstreamEndpointsForMeshGateway - -type loadAssignmentEndpointGroup struct { - Endpoints structs.CheckServiceNodes - OnlyPassing bool - OverrideHealth pbproxystate.HealthStatus -} - -func makeEndpointsForLoadAssignment(cfgSnap *proxycfg.ConfigSnapshot, - policy *structs.DiscoveryPrioritizeByLocality, - endpointGroups []loadAssignmentEndpointGroup, - localKey proxycfg.GatewayKey) []*pbproxystate.Endpoint { - pbEndpoints := make([]*pbproxystate.Endpoint, 0, len(endpointGroups)) - - // TODO(proxystate): this will be added with property overrides having golden files with this - //if len(endpointGroups) > 1 { - // cla.Policy = &envoy_endpoint_v3.ClusterLoadAssignment_Policy{ - // // We choose such a large value here that the failover math should - // // in effect not happen until zero instances are healthy. - // OverprovisioningFactor: response.MakeUint32Value(100000), - // } - //} - - var priority uint32 - - for _, endpointGroup := range endpointGroups { - endpointsByLocality, err := groupedEndpoints(cfgSnap.ServiceLocality, policy, endpointGroup.Endpoints) - - if err != nil { - continue - } - - for _, endpoints := range endpointsByLocality { - for _, ep := range endpoints { - // TODO (mesh-gateway) - should we respect the translate_wan_addrs configuration here or just always use the wan for cross-dc? - _, addr, port := ep.BestAddress(!localKey.Matches(ep.Node.Datacenter, ep.Node.PartitionOrDefault())) - healthStatus, weight := calculateEndpointHealthAndWeight(ep, endpointGroup.OnlyPassing) - - if endpointGroup.OverrideHealth != pbproxystate.HealthStatus_HEALTH_STATUS_UNKNOWN { - healthStatus = endpointGroup.OverrideHealth - } - - endpoint := makeHostPortEndpoint(addr, port) - endpoint.HealthStatus = healthStatus - endpoint.LoadBalancingWeight = response.MakeUint32Value(weight) - - pbEndpoints = append(pbEndpoints, endpoint) - } - - // TODO(proxystate): what do we do about priority downstream? - //cla.Endpoints = append(cla.Endpoints, &envoy_endpoint_v3.LocalityLbEndpoints{ - // Priority: priority, - // LbEndpoints: es, - //}) - - priority++ - } - } - - return pbEndpoints -} - -func makeLoadAssignmentEndpointGroup( - targets map[string]*structs.DiscoveryTarget, - targetHealth map[string]structs.CheckServiceNodes, - gatewayHealth map[string]structs.CheckServiceNodes, - targetID string, - localKey proxycfg.GatewayKey, - forMeshGateway bool, -) (loadAssignmentEndpointGroup, bool) { - realEndpoints, ok := targetHealth[targetID] - if !ok { - // skip the cluster if we're still populating the snapshot - return loadAssignmentEndpointGroup{}, false - } - target := targets[targetID] - - var gatewayKey proxycfg.GatewayKey - - switch target.MeshGateway.Mode { - case structs.MeshGatewayModeRemote: - gatewayKey.Datacenter = target.Datacenter - gatewayKey.Partition = target.Partition - case structs.MeshGatewayModeLocal: - gatewayKey = localKey - } - - if forMeshGateway || gatewayKey.IsEmpty() || localKey.Matches(target.Datacenter, target.Partition) { - // Gateways are not needed if the request isn't for a remote DC or partition. - return loadAssignmentEndpointGroup{ - Endpoints: realEndpoints, - OnlyPassing: target.Subset.OnlyPassing, - }, true - } - - // If using a mesh gateway we need to pull those endpoints instead. - gatewayEndpoints, ok := gatewayHealth[gatewayKey.String()] - if !ok { - // skip the cluster if we're still populating the snapshot - return loadAssignmentEndpointGroup{}, false - } - - // But we will use the health from the actual backend service. - overallHealth := pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - for _, ep := range realEndpoints { - health, _ := calculateEndpointHealthAndWeight(ep, target.Subset.OnlyPassing) - if health == pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY { - overallHealth = pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY - break - } - } - - return loadAssignmentEndpointGroup{ - Endpoints: gatewayEndpoints, - OverrideHealth: overallHealth, - }, true -} - -func calculateEndpointHealthAndWeight( - ep structs.CheckServiceNode, - onlyPassing bool, -) (pbproxystate.HealthStatus, int) { - healthStatus := pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY - weight := 1 - if ep.Service.Weights != nil { - weight = ep.Service.Weights.Passing - } - - for _, chk := range ep.Checks { - if chk.Status == api.HealthCritical { - healthStatus = pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - } - if onlyPassing && chk.Status != api.HealthPassing { - healthStatus = pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - } - if chk.Status == api.HealthWarning && ep.Service.Weights != nil { - weight = ep.Service.Weights.Warning - } - } - // Make weights fit Envoy's limits. A zero weight means that either Warning - // (likely) or Passing (weirdly) weight has been set to 0 effectively making - // this instance unhealthy and should not be sent traffic. - if weight < 1 { - healthStatus = pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - weight = 1 - } - if weight > 128 { - weight = 128 - } - return healthStatus, weight -} diff --git a/agent/xds/proxystateconverter/failover_policy.go b/agent/xds/proxystateconverter/failover_policy.go deleted file mode 100644 index 2b0c0617c6bf..000000000000 --- a/agent/xds/proxystateconverter/failover_policy.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "fmt" - - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" -) - -type discoChainTargets struct { - baseClusterName string - targets []targetInfo - failover bool - failoverPolicy structs.ServiceResolverFailoverPolicy -} - -type targetInfo struct { - TargetID string - TransportSocket *pbproxystate.TransportSocket - SNI string - RootPEMs string - SpiffeIDs []string - Region *string - - PrioritizeByLocality *structs.DiscoveryPrioritizeByLocality -} - -type discoChainTargetGroup struct { - Targets []targetInfo - ClusterName string -} - -func (ft discoChainTargets) groupedTargets() ([]discoChainTargetGroup, error) { - var targetGroups []discoChainTargetGroup - - if !ft.failover { - targetGroups = append(targetGroups, discoChainTargetGroup{ - ClusterName: ft.baseClusterName, - Targets: ft.targets, - }) - return targetGroups, nil - } - - switch ft.failoverPolicy.Mode { - case "sequential", "": - return ft.sequential() - case "order-by-locality": - return ft.orderByLocality() - default: - return targetGroups, fmt.Errorf("unexpected failover policy") - } -} - -func (s *Converter) mapDiscoChainTargets(cfgSnap *proxycfg.ConfigSnapshot, chain *structs.CompiledDiscoveryChain, node *structs.DiscoveryGraphNode, upstreamConfig structs.UpstreamConfig, forMeshGateway bool) (discoChainTargets, error) { - failoverTargets := discoChainTargets{} - - if node.Resolver == nil { - return discoChainTargets{}, fmt.Errorf("impossible to process a non-resolver node") - } - - primaryTargetID := node.Resolver.Target - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil && !forMeshGateway { - return discoChainTargets{}, err - } - - failoverTargets.baseClusterName = s.getTargetClusterName(upstreamsSnapshot, chain, primaryTargetID, forMeshGateway) - - tids := []string{primaryTargetID} - failover := node.Resolver.Failover - if failover != nil && !forMeshGateway { - tids = append(tids, failover.Targets...) - failoverTargets.failover = true - if failover.Policy == nil { - failoverTargets.failoverPolicy = structs.ServiceResolverFailoverPolicy{} - } else { - failoverTargets.failoverPolicy = *failover.Policy - } - } - - for _, tid := range tids { - target := chain.Targets[tid] - targetUID := proxycfg.NewUpstreamIDFromTargetID(tid) - ti := targetInfo{TargetID: tid, PrioritizeByLocality: target.PrioritizeByLocality} - - configureTLS := true - if forMeshGateway { - // We only initiate TLS if we're doing an L7 proxy. - configureTLS = structs.IsProtocolHTTPLike(upstreamConfig.Protocol) - } - - if !configureTLS { - failoverTargets.targets = append(failoverTargets.targets, ti) - continue - } - - if targetUID.Peer != "" { - tbs, _ := upstreamsSnapshot.UpstreamPeerTrustBundles.Get(targetUID.Peer) - - peerMeta, found := upstreamsSnapshot.UpstreamPeerMeta(targetUID) - if !found { - s.Logger.Warn("failed to fetch upstream peering metadata", "target", targetUID) - continue - } - ti.SNI = peerMeta.PrimarySNI() - ti.SpiffeIDs = peerMeta.SpiffeID - region := target.Locality.GetRegion() - ti.Region = ®ion - ti.RootPEMs = tbs.ConcatenatedRootPEMs() - } else { - ti.SNI = target.SNI - ti.RootPEMs = cfgSnap.RootPEMs() - ti.SpiffeIDs = []string{connect.SpiffeIDService{ - Host: cfgSnap.Roots.TrustDomain, - Namespace: target.Namespace, - Partition: target.Partition, - Datacenter: target.Datacenter, - Service: target.Service, - }.URI().String()} - } - failoverTargets.targets = append(failoverTargets.targets, ti) - } - - return failoverTargets, nil -} - -func (ft discoChainTargets) sequential() ([]discoChainTargetGroup, error) { - var targetGroups []discoChainTargetGroup - for i, t := range ft.targets { - targetGroups = append(targetGroups, discoChainTargetGroup{ - ClusterName: fmt.Sprintf("%s%d~%s", xdscommon.FailoverClusterNamePrefix, i, ft.baseClusterName), - Targets: []targetInfo{t}, - }) - } - return targetGroups, nil -} diff --git a/agent/xds/proxystateconverter/failover_policy_ce.go b/agent/xds/proxystateconverter/failover_policy_ce.go deleted file mode 100644 index b68d9b2e738b..000000000000 --- a/agent/xds/proxystateconverter/failover_policy_ce.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent - -package proxystateconverter - -import ( - "fmt" -) - -func (ft discoChainTargets) orderByLocality() ([]discoChainTargetGroup, error) { - return nil, fmt.Errorf("order-by-locality is a Consul Enterprise feature") -} diff --git a/agent/xds/proxystateconverter/listeners.go b/agent/xds/proxystateconverter/listeners.go deleted file mode 100644 index 266e96383c7a..000000000000 --- a/agent/xds/proxystateconverter/listeners.go +++ /dev/null @@ -1,1695 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "errors" - "fmt" - "net" - "net/url" - "regexp" - "strconv" - "strings" - "time" - - envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-uuid" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/config" - "github.com/hashicorp/consul/agent/xds/naming" - "github.com/hashicorp/consul/agent/xds/platform" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/consul/sdk/iptables" - "github.com/hashicorp/consul/types" -) - -// listenersFromSnapshot adds listeners to pbmesh.ProxyState using the config snapshot. -func (s *Converter) listenersFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) error { - if cfgSnap == nil { - return errors.New("nil config given") - } - - switch cfgSnap.Kind { - case structs.ServiceKindConnectProxy: - return s.listenersFromSnapshotConnectProxy(cfgSnap) - case structs.ServiceKindTerminatingGateway, - structs.ServiceKindMeshGateway, - structs.ServiceKindIngressGateway, - structs.ServiceKindAPIGateway: - // TODO(proxystate): gateway support will be added in the future - //return s.listenersFromSnapshotGateway(cfgSnap) - default: - return fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind) - } - return nil -} - -// listenersFromSnapshotConnectProxy returns the "listeners" for a connect proxy service -func (s *Converter) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnapshot) error { - // This is the list of listeners we add to. It will be empty to start. - listeners := s.proxyState.Listeners - var err error - - // Configure inbound listener. - inboundListener, err := s.makeInboundListener(cfgSnap, xdscommon.PublicListenerName) - if err != nil { - return err - } - listeners = append(listeners, inboundListener) - - // This outboundListener is exclusively used when transparent proxy mode is active. - // In that situation there is a single listener where we are redirecting outbound traffic, - // and each upstream gets a filter chain attached to that listener. - var outboundListener *pbproxystate.Listener - - if cfgSnap.Proxy.Mode == structs.ProxyModeTransparent { - port := iptables.DefaultTProxyOutboundPort - if cfgSnap.Proxy.TransparentProxy.OutboundListenerPort != 0 { - port = cfgSnap.Proxy.TransparentProxy.OutboundListenerPort - } - - opts := makeListenerOpts{ - name: xdscommon.OutboundListenerName, - //accessLogs: cfgSnap.Proxy.AccessLogs, - addr: "127.0.0.1", - port: port, - direction: pbproxystate.Direction_DIRECTION_OUTBOUND, - logger: s.Logger, - } - outboundListener = makeListener(opts) - if outboundListener.Capabilities == nil { - outboundListener.Capabilities = []pbproxystate.Capability{} - } - outboundListener.Capabilities = append(outboundListener.Capabilities, pbproxystate.Capability_CAPABILITY_TRANSPARENT) - } - - // TODO(proxystate): tracing escape hatch will be added in the future. It will be added to the top level in proxystate, and used in xds generation. - //proxyCfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - //if err != nil { - // // Don't hard fail on a config typo, just warn. The parse func returns - // // default config if there is an error so it's safe to continue. - // s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - //} - //var tracing *envoy_http_v3.HttpConnectionManager_Tracing - //if proxyCfg.ListenerTracingJSON != "" { - // if tracing, err = makeTracingFromUserConfig(proxyCfg.ListenerTracingJSON); err != nil { - // s.Logger.Warn("failed to parse ListenerTracingJSON config", "error", err) - // } - //} - - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil { - return err - } - - for uid, chain := range cfgSnap.ConnectProxy.DiscoveryChain { - upstreamCfg, skip := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta) - if skip { - // Discovery chain is not associated with a known explicit or implicit upstream so it is skipped. - continue - } - - cfg := s.getAndModifyUpstreamConfigForListener(uid, upstreamCfg, chain) - - // If escape hatch is present, create a listener from it and move on to the next - if cfg.EnvoyListenerJSON != "" { - upstreamListener := &pbproxystate.Listener{ - EscapeHatchListener: cfg.EnvoyListenerJSON, - } - listeners = append(listeners, upstreamListener) - continue - } - - // RDS, Envoy's Route Discovery Service, is only used for HTTP services with a customized discovery chain. - useRDS := chain.Protocol != "tcp" && !chain.Default - - var clusterName string - if !useRDS { - // When not using RDS we must generate a cluster name to attach to the filter chain. - // With RDS, cluster names get attached to the dynamic routes instead. - target, err := simpleChainTarget(chain) - if err != nil { - return err - } - - clusterName = s.getTargetClusterName(upstreamsSnapshot, chain, target.ID, false) - if clusterName == "" { - continue - } - } - - filterName := fmt.Sprintf("%s.%s.%s.%s", chain.ServiceName, chain.Namespace, chain.Partition, chain.Datacenter) - - // Generate the upstream listeners for when they are explicitly set with a local bind port or socket path - if upstreamCfg != nil && upstreamCfg.HasLocalPortOrSocket() { - router, err := s.makeUpstreamRouter(routerOpts{ - // TODO(proxystate): access logs and tracing will be added in the future. - //accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: uid.EnvoyID(), - clusterName: clusterName, - filterName: filterName, - protocol: cfg.Protocol, - useRDS: useRDS, - //tracing: tracing, - }) - if err != nil { - return err - } - - opts := makeListenerOpts{ - name: uid.EnvoyID(), - //accessLogs: cfgSnap.Proxy.AccessLogs, - direction: pbproxystate.Direction_DIRECTION_OUTBOUND, - logger: s.Logger, - upstream: upstreamCfg, - } - upstreamListener := makeListener(opts) - upstreamListener.BalanceConnections = balanceConnections[cfg.BalanceOutboundConnections] - - upstreamListener.Routers = append(upstreamListener.Routers, router) - listeners = append(listeners, upstreamListener) - - // Avoid creating filter chains below for upstreams that have dedicated listeners - continue - } - - // The rest of this loop is used exclusively for transparent proxies. - // Below we create a filter chain per upstream, rather than a listener per upstream - // as we do for explicit upstreams above. - - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: uid.EnvoyID(), - clusterName: clusterName, - filterName: filterName, - protocol: cfg.Protocol, - useRDS: useRDS, - //tracing: tracing, - }) - if err != nil { - return err - } - - endpoints := cfgSnap.ConnectProxy.WatchedUpstreamEndpoints[uid][chain.ID()] - uniqueAddrs := make(map[string]struct{}) - - if chain.Partition == cfgSnap.ProxyID.PartitionOrDefault() { - for _, ip := range chain.AutoVirtualIPs { - uniqueAddrs[ip] = struct{}{} - } - for _, ip := range chain.ManualVirtualIPs { - uniqueAddrs[ip] = struct{}{} - } - } - - // Match on the virtual IP for the upstream service (identified by the chain's ID). - // We do not match on all endpoints here since it would lead to load balancing across - // all instances when any instance address is dialed. - for _, e := range endpoints { - if e.Service.Kind == structs.ServiceKind(structs.TerminatingGateway) { - key := structs.ServiceGatewayVirtualIPTag(chain.CompoundServiceName()) - - if vip := e.Service.TaggedAddresses[key]; vip.Address != "" { - uniqueAddrs[vip.Address] = struct{}{} - } - - continue - } - if vip := e.Service.TaggedAddresses[structs.TaggedAddressVirtualIP]; vip.Address != "" { - uniqueAddrs[vip.Address] = struct{}{} - } - - // The virtualIPTag is used by consul-k8s to store the ClusterIP for a service. - // We only match on this virtual IP if the upstream is in the proxy's partition. - // This is because the IP is not guaranteed to be unique across k8s clusters. - if acl.EqualPartitions(e.Node.PartitionOrDefault(), cfgSnap.ProxyID.PartitionOrDefault()) { - if vip := e.Service.TaggedAddresses[naming.VirtualIPTag]; vip.Address != "" { - uniqueAddrs[vip.Address] = struct{}{} - } - } - } - if len(uniqueAddrs) > 2 { - s.Logger.Debug("detected multiple virtual IPs for an upstream, all will be used to match traffic", - "upstream", uid, "ip_count", len(uniqueAddrs)) - } - - // For every potential address we collected, create the appropriate address prefix to match on. - // In this case we are matching on exact addresses, so the prefix is the address itself, - // and the prefix length is based on whether it's IPv4 or IPv6. - upstreamRouter.Match = makeRouterMatchFromAddrs(uniqueAddrs) - - // Only attach the filter chain if there are addresses to match on - if upstreamRouter.Match != nil && len(upstreamRouter.Match.PrefixRanges) > 0 { - outboundListener.Routers = append(outboundListener.Routers, upstreamRouter) - } - } - requiresTLSInspector := false - requiresHTTPInspector := false - - configuredPorts := make(map[int]interface{}) - err = cfgSnap.ConnectProxy.DestinationsUpstream.ForEachKeyE(func(uid proxycfg.UpstreamID) error { - svcConfig, ok := cfgSnap.ConnectProxy.DestinationsUpstream.Get(uid) - if !ok || svcConfig == nil { - return nil - } - - if structs.IsProtocolHTTPLike(svcConfig.Protocol) { - if _, ok := configuredPorts[svcConfig.Destination.Port]; ok { - return nil - } - configuredPorts[svcConfig.Destination.Port] = struct{}{} - const name = "~http" // name used for the shared route name - routeName := clusterNameForDestination(cfgSnap, name, fmt.Sprintf("%d", svcConfig.Destination.Port), svcConfig.NamespaceOrDefault(), svcConfig.PartitionOrDefault()) - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: routeName, - filterName: routeName, - protocol: svcConfig.Protocol, - useRDS: true, - //tracing: tracing, - }) - if err != nil { - return err - } - upstreamRouter.Match = makeRouterMatchFromAddressWithPort("", svcConfig.Destination.Port) - outboundListener.Routers = append(outboundListener.Routers, upstreamRouter) - requiresHTTPInspector = true - } else { - for _, address := range svcConfig.Destination.Addresses { - clusterName := clusterNameForDestination(cfgSnap, uid.Name, address, uid.NamespaceOrDefault(), uid.PartitionOrDefault()) - - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: uid.EnvoyID(), - clusterName: clusterName, - filterName: clusterName, - protocol: svcConfig.Protocol, - //tracing: tracing, - }) - if err != nil { - return err - } - - upstreamRouter.Match = makeRouterMatchFromAddressWithPort(address, svcConfig.Destination.Port) - outboundListener.Routers = append(outboundListener.Routers, upstreamRouter) - - requiresTLSInspector = len(upstreamRouter.Match.ServerNames) != 0 || requiresTLSInspector - } - } - return nil - }) - if err != nil { - return err - } - - if requiresTLSInspector { - outboundListener.Capabilities = append(outboundListener.Capabilities, pbproxystate.Capability_CAPABILITY_L4_TLS_INSPECTION) - } - - if requiresHTTPInspector { - outboundListener.Capabilities = append(outboundListener.Capabilities, pbproxystate.Capability_CAPABILITY_L7_PROTOCOL_INSPECTION) - } - - // Looping over explicit and implicit upstreams is only needed for cross-peer - // because they do not have discovery chains. - for _, uid := range cfgSnap.ConnectProxy.PeeredUpstreamIDs() { - upstreamCfg, skip := cfgSnap.ConnectProxy.GetUpstream(uid, &cfgSnap.ProxyID.EnterpriseMeta) - if skip { - // Not associated with a known explicit or implicit upstream so it is skipped. - continue - } - - peerMeta, found := cfgSnap.ConnectProxy.UpstreamPeerMeta(uid) - if !found { - s.Logger.Warn("failed to fetch upstream peering metadata for listener", "uid", uid) - } - cfg := s.getAndModifyUpstreamConfigForPeeredListener(uid, upstreamCfg, peerMeta) - - // If escape hatch is present, create a listener from it and move on to the next - if cfg.EnvoyListenerJSON != "" { - upstreamListener := &pbproxystate.Listener{ - EscapeHatchListener: cfg.EnvoyListenerJSON, - } - listeners = append(listeners, upstreamListener) - continue - } - - tbs, ok := cfgSnap.ConnectProxy.UpstreamPeerTrustBundles.Get(uid.Peer) - if !ok { - // this should never happen since we loop through upstreams with - // set trust bundles - return fmt.Errorf("trust bundle not ready for peer %s", uid.Peer) - } - - clusterName := generatePeeredClusterName(uid, tbs) - - // Generate the upstream listeners for when they are explicitly set with a local bind port or socket path - if upstreamCfg != nil && upstreamCfg.HasLocalPortOrSocket() { - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - clusterName: clusterName, - filterName: fmt.Sprintf("%s.%s.%s", - upstreamCfg.DestinationName, - upstreamCfg.DestinationNamespace, - upstreamCfg.DestinationPeer), - routeName: uid.EnvoyID(), - protocol: cfg.Protocol, - useRDS: false, - statPrefix: "upstream_peered.", - }) - if err != nil { - return err - } - - opts := makeListenerOpts{ - name: uid.EnvoyID(), - //accessLogs: cfgSnap.Proxy.AccessLogs, - direction: pbproxystate.Direction_DIRECTION_OUTBOUND, - logger: s.Logger, - upstream: upstreamCfg, - } - upstreamListener := makeListener(opts) - upstreamListener.BalanceConnections = balanceConnections[cfg.BalanceOutboundConnections] - - upstreamListener.Routers = []*pbproxystate.Router{ - upstreamRouter, - } - listeners = append(listeners, upstreamListener) - - // Avoid creating filter chains below for upstreams that have dedicated listeners - continue - } - - // The rest of this loop is used exclusively for transparent proxies. - // Below we create a filter chain per upstream, rather than a listener per upstream - // as we do for explicit upstreams above. - - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - routeName: uid.EnvoyID(), - clusterName: clusterName, - filterName: fmt.Sprintf("%s.%s.%s", - uid.Name, - uid.NamespaceOrDefault(), - uid.Peer), - protocol: cfg.Protocol, - useRDS: false, - statPrefix: "upstream_peered.", - //tracing: tracing, - }) - if err != nil { - return err - } - - endpoints, _ := cfgSnap.ConnectProxy.PeerUpstreamEndpoints.Get(uid) - uniqueAddrs := make(map[string]struct{}) - - // Match on the virtual IP for the upstream service (identified by the chain's ID). - // We do not match on all endpoints here since it would lead to load balancing across - // all instances when any instance address is dialed. - for _, e := range endpoints { - if vip := e.Service.TaggedAddresses[structs.TaggedAddressVirtualIP]; vip.Address != "" { - uniqueAddrs[vip.Address] = struct{}{} - } - - // The virtualIPTag is used by consul-k8s to store the ClusterIP for a service. - // For services imported from a peer,the partition will be equal in all cases. - if acl.EqualPartitions(e.Node.PartitionOrDefault(), cfgSnap.ProxyID.PartitionOrDefault()) { - if vip := e.Service.TaggedAddresses[naming.VirtualIPTag]; vip.Address != "" { - uniqueAddrs[vip.Address] = struct{}{} - } - } - } - if len(uniqueAddrs) > 2 { - s.Logger.Debug("detected multiple virtual IPs for an upstream, all will be used to match traffic", - "upstream", uid, "ip_count", len(uniqueAddrs)) - } - - // For every potential address we collected, create the appropriate address prefix to match on. - // In this case we are matching on exact addresses, so the prefix is the address itself, - // and the prefix length is based on whether it's IPv4 or IPv6. - upstreamRouter.Match = makeRouterMatchFromAddrs(uniqueAddrs) - - // Only attach the filter chain if there are addresses to match on - if upstreamRouter.Match != nil && len(upstreamRouter.Match.PrefixRanges) > 0 { - outboundListener.Routers = append(outboundListener.Routers, upstreamRouter) - } - - } - - if outboundListener != nil { - // Add a passthrough for every mesh endpoint that can be dialed directly, - // as opposed to via a virtual IP. - var passthroughRouters []*pbproxystate.Router - - for _, targets := range cfgSnap.ConnectProxy.PassthroughUpstreams { - for tid, addrs := range targets { - uid := proxycfg.NewUpstreamIDFromTargetID(tid) - - sni := connect.ServiceSNI( - uid.Name, "", uid.NamespaceOrDefault(), uid.PartitionOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain) - - routerName := fmt.Sprintf("%s.%s.%s.%s", uid.Name, uid.NamespaceOrDefault(), uid.PartitionOrDefault(), cfgSnap.Datacenter) - - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - clusterName: "passthrough~" + sni, - filterName: routerName, - protocol: "tcp", - }) - if err != nil { - return err - } - upstreamRouter.Match = makeRouterMatchFromAddrs(addrs) - - passthroughRouters = append(passthroughRouters, upstreamRouter) - } - } - - outboundListener.Routers = append(outboundListener.Routers, passthroughRouters...) - - // Add a catch-all filter chain that acts as a TCP proxy to destinations outside the mesh - if meshConf := cfgSnap.MeshConfig(); meshConf == nil || - !meshConf.TransparentProxy.MeshDestinationsOnly { - - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - //accessLogs: &cfgSnap.Proxy.AccessLogs, - clusterName: naming.OriginalDestinationClusterName, - filterName: naming.OriginalDestinationClusterName, - protocol: "tcp", - }) - if err != nil { - return err - } - outboundListener.DefaultRouter = upstreamRouter - } - - // Only add the outbound listener if configured. - if len(outboundListener.Routers) > 0 || outboundListener.DefaultRouter != nil { - listeners = append(listeners, outboundListener) - - } - } - - // Looping over explicit upstreams is only needed for prepared queries because they do not have discovery chains - for uid, u := range cfgSnap.ConnectProxy.UpstreamConfig { - if u.DestinationType != structs.UpstreamDestTypePreparedQuery { - continue - } - - cfg, err := structs.ParseUpstreamConfig(u.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse", "upstream", uid, "error", err) - } - - // If escape hatch is present, create a listener from it and move on to the next - if cfg.EnvoyListenerJSON != "" { - upstreamListener := &pbproxystate.Listener{ - EscapeHatchListener: cfg.EnvoyListenerJSON, - } - listeners = append(listeners, upstreamListener) - continue - } - - opts := makeListenerOpts{ - name: uid.EnvoyID(), - //accessLogs: cfgSnap.Proxy.AccessLogs, - direction: pbproxystate.Direction_DIRECTION_OUTBOUND, - logger: s.Logger, - upstream: u, - } - upstreamListener := makeListener(opts) - upstreamListener.BalanceConnections = balanceConnections[cfg.BalanceOutboundConnections] - - upstreamRouter, err := s.makeUpstreamRouter(routerOpts{ - // TODO (SNI partition) add partition for upstream SNI - //accessLogs: &cfgSnap.Proxy.AccessLogs, - clusterName: connect.UpstreamSNI(u, "", cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain), - filterName: uid.EnvoyID(), - routeName: uid.EnvoyID(), - protocol: cfg.Protocol, - //tracing: tracing, - }) - if err != nil { - return err - } - upstreamListener.Routers = []*pbproxystate.Router{ - upstreamRouter, - } - listeners = append(listeners, upstreamListener) - } - - cfgSnap.Proxy.Expose.Finalize() - paths := cfgSnap.Proxy.Expose.Paths - - // Add service health checks to the list of paths to create listeners for if needed - if cfgSnap.Proxy.Expose.Checks { - psid := structs.NewServiceID(cfgSnap.Proxy.DestinationServiceID, &cfgSnap.ProxyID.EnterpriseMeta) - for _, check := range cfgSnap.ConnectProxy.WatchedServiceChecks[psid] { - p, err := parseCheckPath(check) - if err != nil { - s.Logger.Warn("failed to create listener for", "check", check.CheckID, "error", err) - continue - } - paths = append(paths, p) - } - } - - // Configure additional listener for exposed check paths - for _, path := range paths { - clusterName := xdscommon.LocalAppClusterName - if path.LocalPathPort != cfgSnap.Proxy.LocalServicePort { - clusterName = makeExposeClusterName(path.LocalPathPort) - } - - l, err := s.makeExposedCheckListener(cfgSnap, clusterName, path) - if err != nil { - return err - } - listeners = append(listeners, l) - } - - // Set listeners on the proxy state. - s.proxyState.Listeners = listeners - - return nil -} - -func makeRouterMatchFromAddrs(addrs map[string]struct{}) *pbproxystate.Match { - ranges := make([]*pbproxystate.CidrRange, 0) - - for addr := range addrs { - ip := net.ParseIP(addr) - if ip == nil { - continue - } - - pfxLen := uint32(32) - if ip.To4() == nil { - pfxLen = 128 - } - ranges = append(ranges, &pbproxystate.CidrRange{ - AddressPrefix: addr, - PrefixLen: &wrapperspb.UInt32Value{Value: pfxLen}, - }) - } - - return &pbproxystate.Match{ - PrefixRanges: ranges, - } -} - -func makeRouterMatchFromAddressWithPort(address string, port int) *pbproxystate.Match { - ranges := make([]*pbproxystate.CidrRange, 0) - - ip := net.ParseIP(address) - if ip == nil { - if address != "" { - return &pbproxystate.Match{ - ServerNames: []string{address}, - DestinationPort: &wrapperspb.UInt32Value{Value: uint32(port)}, - } - } - return &pbproxystate.Match{ - DestinationPort: &wrapperspb.UInt32Value{Value: uint32(port)}, - } - } - - pfxLen := uint32(32) - if ip.To4() == nil { - pfxLen = 128 - } - ranges = append(ranges, &pbproxystate.CidrRange{ - AddressPrefix: address, - PrefixLen: &wrapperspb.UInt32Value{Value: pfxLen}, - }) - - return &pbproxystate.Match{ - PrefixRanges: ranges, - DestinationPort: &wrapperspb.UInt32Value{Value: uint32(port)}, - } -} - -func parseCheckPath(check structs.CheckType) (structs.ExposePath, error) { - var path structs.ExposePath - - if check.HTTP != "" { - path.Protocol = "http" - - // Get path and local port from original HTTP target - u, err := url.Parse(check.HTTP) - if err != nil { - return path, fmt.Errorf("failed to parse url '%s': %v", check.HTTP, err) - } - path.Path = u.Path - - _, portStr, err := net.SplitHostPort(u.Host) - if err != nil { - return path, fmt.Errorf("failed to parse port from '%s': %v", check.HTTP, err) - } - path.LocalPathPort, err = strconv.Atoi(portStr) - if err != nil { - return path, fmt.Errorf("failed to parse port from '%s': %v", check.HTTP, err) - } - - // Get listener port from proxied HTTP target - u, err = url.Parse(check.ProxyHTTP) - if err != nil { - return path, fmt.Errorf("failed to parse url '%s': %v", check.ProxyHTTP, err) - } - - _, portStr, err = net.SplitHostPort(u.Host) - if err != nil { - return path, fmt.Errorf("failed to parse port from '%s': %v", check.ProxyHTTP, err) - } - path.ListenerPort, err = strconv.Atoi(portStr) - if err != nil { - return path, fmt.Errorf("failed to parse port from '%s': %v", check.ProxyHTTP, err) - } - } - - if check.GRPC != "" { - path.Path = "/grpc.health.v1.Health/Check" - path.Protocol = "http2" - - // Get local port from original GRPC target of the form: host/service - proxyServerAndService := strings.SplitN(check.GRPC, "/", 2) - _, portStr, err := net.SplitHostPort(proxyServerAndService[0]) - if err != nil { - return path, fmt.Errorf("failed to split host/port from '%s': %v", check.GRPC, err) - } - path.LocalPathPort, err = strconv.Atoi(portStr) - if err != nil { - return path, fmt.Errorf("failed to parse port from '%s': %v", check.GRPC, err) - } - - // Get listener port from proxied GRPC target of the form: host/service - proxyServerAndService = strings.SplitN(check.ProxyGRPC, "/", 2) - _, portStr, err = net.SplitHostPort(proxyServerAndService[0]) - if err != nil { - return path, fmt.Errorf("failed to split host/port from '%s': %v", check.ProxyGRPC, err) - } - path.ListenerPort, err = strconv.Atoi(portStr) - if err != nil { - return path, fmt.Errorf("failed to parse port from '%s': %v", check.ProxyGRPC, err) - } - } - - path.ParsedFromCheck = true - - return path, nil -} - -// TODO(proxystate): Gateway support will be added in the future. -// Functions to add from agent/xds/listeners.go: -// func listenersFromSnapshotGateway - -// makeListener returns a listener with name and bind details set. Routers and destinations -// must be added before it's useful. -// -// Note on names: Envoy listeners attempt graceful transitions of connections -// when their config changes but that means they can't have their bind address -// or port changed in a running instance. Since our users might choose to change -// a bind address or port for the public or upstream listeners, we need to -// encode those into the unique name for the listener such that if the user -// changes them, we actually create a whole new listener on the new address and -// port. Envoy should take care of closing the old one once it sees it's no -// longer in the config. -type makeListenerOpts struct { - addr string - //accessLogs structs.AccessLogsConfig - logger hclog.Logger - mode string - name string - path string - port int - direction pbproxystate.Direction - upstream *structs.Upstream -} - -func makeListener(opts makeListenerOpts) *pbproxystate.Listener { - if opts.upstream != nil && opts.upstream.LocalBindPort == 0 && opts.upstream.LocalBindSocketPath != "" { - opts.path = opts.upstream.LocalBindSocketPath - opts.mode = opts.upstream.LocalBindSocketMode - return makePipeListener(opts) - } - if opts.upstream != nil { - opts.port = opts.upstream.LocalBindPort - opts.addr = opts.upstream.LocalBindAddress - return makeListenerWithDefault(opts) - } - - return makeListenerWithDefault(opts) -} - -func makeListenerWithDefault(opts makeListenerOpts) *pbproxystate.Listener { - if opts.addr == "" { - opts.addr = "127.0.0.1" - } - // TODO(proxystate): Access logs will be added in the future. It will be added to top level IR, and used by xds code generation. - //accessLog, err := accesslogs.MakeAccessLogs(&opts.accessLogs, true) - //if err != nil && opts.logger != nil { - // // Since access logging is non-essential for routing, warn and move on - // opts.logger.Warn("error generating access log xds", err) - //} - return &pbproxystate.Listener{ - Name: fmt.Sprintf("%s:%s:%d", opts.name, opts.addr, opts.port), - //AccessLog: accessLog, - BindAddress: &pbproxystate.Listener_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: opts.addr, - Port: uint32(opts.port), - }, - }, - Direction: opts.direction, - } -} - -func makePipeListener(opts makeListenerOpts) *pbproxystate.Listener { - // TODO(proxystate): Access logs will be added in the future. It will be added to top level IR, and used by xds code generation. - //accessLog, err := accesslogs.MakeAccessLogs(&opts.accessLogs, true) - //if err != nil && opts.logger != nil { - // // Since access logging is non-essential for routing, warn and move on - // opts.logger.Warn("error generating access log xds", err) - //} - return &pbproxystate.Listener{ - Name: fmt.Sprintf("%s:%s", opts.name, opts.path), - //AccessLog: accessLog, - BindAddress: &pbproxystate.Listener_UnixSocket{ - UnixSocket: &pbproxystate.UnixSocketAddress{Path: opts.path, Mode: opts.mode}, - }, - Direction: opts.direction, - } -} - -// TODO(proxystate): Escape hatches will be added in the future. -// Functions to add from agent/xds/listeners.go: -// func makeListenerFromUserConfig - -// TODO(proxystate): Intentions will be added in the future -// Functions to add from agent/xds/listeners.go: -// func injectConnectFilters - -// TODO(proxystate): httpConnectionManager constants will need to be added when used for listeners L7 in the future. -// Constants to add from agent/xds/listeners.go: -// const httpConnectionManagerOldName -// const httpConnectionManagerNewName - -// TODO(proxystate): Extracting RDS resource names will be used when wiring up xds v2 server in the future. -// Functions to add from agent/xds/listeners.go: -// func extractRdsResourceNames - -// TODO(proxystate): Intentions will be added in the future. -// Functions to add from agent/xds/listeners.go: -// func injectHTTPFilterOnFilterChains - -// NOTE: This method MUST only be used for connect proxy public listeners, -// since TLS validation will be done against root certs for all peers -// that might dial this proxy. -func (s *Converter) injectConnectTLSForPublicListener(cfgSnap *proxycfg.ConfigSnapshot, listener *pbproxystate.Listener) error { - transportSocket, err := s.createInboundMeshMTLS(cfgSnap) - if err != nil { - return err - } - - for idx := range listener.Routers { - listener.Routers[idx].InboundTls = transportSocket - } - return nil -} - -func getAlpnProtocols(protocol string) []string { - var alpnProtocols []string - - switch protocol { - case "grpc", "http2": - alpnProtocols = append(alpnProtocols, "h2", "http/1.1") - case "http": - alpnProtocols = append(alpnProtocols, "http/1.1") - } - - return alpnProtocols -} - -func (s *Converter) createInboundMeshMTLS(cfgSnap *proxycfg.ConfigSnapshot) (*pbproxystate.TransportSocket, error) { - switch cfgSnap.Kind { - case structs.ServiceKindConnectProxy: - case structs.ServiceKindMeshGateway: - default: - return nil, fmt.Errorf("cannot inject peering trust bundles for kind %q", cfgSnap.Kind) - } - - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - - // Add all trust bundle peer names, including local. - trustBundlePeerNames := []string{"local"} - for _, tb := range cfgSnap.PeeringTrustBundles() { - trustBundlePeerNames = append(trustBundlePeerNames, tb.PeerName) - } - // Arbitrary UUID to reference the identity by. - uuid, err := uuid.GenerateUUID() - if err != nil { - return nil, err - } - // Create the transport socket - ts := &pbproxystate.TransportSocket{} - ts.ConnectionTls = &pbproxystate.TransportSocket_InboundMesh{ - InboundMesh: &pbproxystate.InboundMeshMTLS{ - IdentityKey: uuid, - ValidationContext: &pbproxystate.MeshInboundValidationContext{ - TrustBundlePeerNameKeys: trustBundlePeerNames, - }, - }, - } - s.proxyState.LeafCertificates[uuid] = &pbproxystate.LeafCertificate{ - Cert: cfgSnap.Leaf().CertPEM, - Key: cfgSnap.Leaf().PrivateKeyPEM, - } - ts.TlsParameters = makeTLSParametersFromProxyTLSConfig(cfgSnap.MeshConfigTLSIncoming()) - ts.AlpnProtocols = getAlpnProtocols(cfg.Protocol) - - return ts, nil -} - -func (s *Converter) makeInboundListener(cfgSnap *proxycfg.ConfigSnapshot, name string) (*pbproxystate.Listener, error) { - l := &pbproxystate.Listener{} - l.Routers = make([]*pbproxystate.Router, 0) - var err error - - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - - // This controls if we do L4 or L7 intention checks. - useHTTPFilter := structs.IsProtocolHTTPLike(cfg.Protocol) - - // TODO(proxystate): Escape hatches will be added in the future. This one is a top level escape hatch. - // Generate and return custom public listener from config if one was provided. - //if cfg.PublicListenerJSON != "" { - // l, err = makeListenerFromUserConfig(cfg.PublicListenerJSON) - // if err != nil { - // return nil, err - // } - // - // // For HTTP-like services attach an RBAC http filter and do a best-effort insert - // if useHTTPFilter { - // httpAuthzFilter, err := makeRBACHTTPFilter( - // cfgSnap.ConnectProxy.Intentions, - // cfgSnap.IntentionDefaultAllow, - // rbacLocalInfo{ - // trustDomain: cfgSnap.Roots.TrustDomain, - // datacenter: cfgSnap.Datacenter, - // partition: cfgSnap.ProxyID.PartitionOrDefault(), - // }, - // cfgSnap.ConnectProxy.InboundPeerTrustBundles, - // ) - // if err != nil { - // return nil, err - // } - // - // // Try our best to inject the HTTP RBAC filter. - // if err := injectHTTPFilterOnFilterChains(l, httpAuthzFilter); err != nil { - // s.Logger.Warn( - // "could not inject the HTTP RBAC filter to enforce intentions on user-provided "+ - // "'envoy_public_listener_json' config; falling back on the RBAC network filter instead", - // "proxy", cfgSnap.ProxyID, - // "error", err, - // ) - // - // // If we get an error inject the RBAC network filter instead. - // useHTTPFilter = false - // } - // } - // - // err := s.finalizePublicListenerFromConfig(l, cfgSnap, useHTTPFilter) - // if err != nil { - // return nil, fmt.Errorf("failed to attach Consul filters and TLS context to custom public listener: %v", err) - // } - // return l, nil - //} - - // No JSON user config, use default listener address - // Default to listening on all addresses, but override with bind address if one is set. - addr := cfgSnap.Address - if addr == "" { - addr = "0.0.0.0" - } - if cfg.BindAddress != "" { - addr = cfg.BindAddress - } - - // Override with bind port if one is set, otherwise default to - // proxy service's address - port := cfgSnap.Port - if cfg.BindPort != 0 { - port = cfg.BindPort - } - - opts := makeListenerOpts{ - name: name, - //accessLogs: cfgSnap.Proxy.AccessLogs, - addr: addr, - port: port, - direction: pbproxystate.Direction_DIRECTION_INBOUND, - logger: s.Logger, - } - l = makeListener(opts) - l.BalanceConnections = balanceConnections[cfg.BalanceInboundConnections] - - // TODO(proxystate): Escape hatches will be added in the future. This one is a top level escape hatch. - //var tracing *envoy_http_v3.HttpConnectionManager_Tracing - //if cfg.ListenerTracingJSON != "" { - // if tracing, err = makeTracingFromUserConfig(cfg.ListenerTracingJSON); err != nil { - // s.Logger.Warn("failed to parse ListenerTracingJSON config", "error", err) - // } - //} - - // make local app cluster router - localAppRouter := &pbproxystate.Router{} - - destOpts := destinationOpts{ - protocol: cfg.Protocol, - filterName: name, - routeName: name, - cluster: xdscommon.LocalAppClusterName, - requestTimeoutMs: cfg.LocalRequestTimeoutMs, - idleTimeoutMs: cfg.LocalIdleTimeoutMs, - //tracing: tracing, - //accessLogs: &cfgSnap.Proxy.AccessLogs, - logger: s.Logger, - } - - err = s.addRouterDestination(destOpts, localAppRouter) - if err != nil { - return nil, err - } - - if useHTTPFilter { - l7Dest := localAppRouter.GetL7() - if l7Dest == nil { - return nil, fmt.Errorf("l7 destination on inbound listener should not be empty") - } - - // TODO(proxystate): L7 traffic permissions and JWT Auth will be added in the future. For now, just add an empty traffic permission. - l7Dest.TrafficPermissions = &pbproxystate.TrafficPermissions{} - //jwtFilter, jwtFilterErr := makeJWTAuthFilter(cfgSnap.JWTProviders, cfgSnap.ConnectProxy.Intentions) - //if jwtFilterErr != nil { - // return nil, jwtFilterErr - //} - //rbacFilter, err := makeRBACHTTPFilter( - // cfgSnap.ConnectProxy.Intentions, - // cfgSnap.IntentionDefaultAllow, - // rbacLocalInfo{ - // trustDomain: cfgSnap.Roots.TrustDomain, - // datacenter: cfgSnap.Datacenter, - // partition: cfgSnap.ProxyID.PartitionOrDefault(), - // }, - // cfgSnap.ConnectProxy.InboundPeerTrustBundles, - //) - //if err != nil { - // return nil, err - //} - // - //filterOpts.httpAuthzFilters = []*envoy_http_v3.HttpFilter{rbacFilter} - // - //if jwtFilter != nil { - // filterOpts.httpAuthzFilters = append(filterOpts.httpAuthzFilters, jwtFilter) - //} - - meshConfig := cfgSnap.MeshConfig() - includeXFCC := meshConfig == nil || meshConfig.HTTP == nil || !meshConfig.HTTP.SanitizeXForwardedClientCert - notGRPC := cfg.Protocol != "grpc" - if includeXFCC && notGRPC { - l7Dest.IncludeXfccPolicy = includeXFCC - l7Dest.XfccPolicy = pbproxystate.XFCCPolicy_XFCC_POLICY_APPEND_FORWARD - l7Dest.ParseXfccHeaders = true - } - l7Dest.Protocol = l7Protocols[cfg.Protocol] - if cfg.MaxInboundConnections > 0 { - l7Dest.MaxInboundConnections = uint64(cfg.MaxInboundConnections) - } - } else { - l4Dest := localAppRouter.GetL4() - if l4Dest == nil { - return nil, fmt.Errorf("l4 destination on inbound listener should not be empty") - } - - if cfg.MaxInboundConnections > 0 { - l4Dest.MaxInboundConnections = uint64(cfg.MaxInboundConnections) - } - - l4Dest.TrafficPermissions = &pbproxystate.TrafficPermissions{} - } - l.Routers = append(l.Routers, localAppRouter) - - err = s.finalizePublicListenerFromConfig(l, cfgSnap) - if err != nil { - return nil, fmt.Errorf("failed to attach Consul filters and TLS context to custom public listener: %v", err) - } - - // When permissive mTLS mode is enabled, include an additional router - // that matches on the `destination_port == `. Traffic sent - // directly to the service port is passed through to the application - // unmodified. - if cfgSnap.Proxy.Mode == structs.ProxyModeTransparent && - cfgSnap.Proxy.MutualTLSMode == structs.MutualTLSModePermissive { - router, err := makePermissiveRouter(cfgSnap, destOpts) - if err != nil { - return nil, fmt.Errorf("unable to add permissive mtls router: %w", err) - } - if router == nil { - s.Logger.Debug("no service port defined for service in permissive mTLS mode; not adding filter chain for non-mTLS traffic") - } else { - l.Routers = append(l.Routers, router) - - // With tproxy, the REDIRECT iptables target rewrites the destination ip/port - // to the proxy ip/port (e.g. 127.0.0.1:20000) for incoming packets. - // We need the original_dst filter to recover the original destination address. - l.Capabilities = append(l.Capabilities, pbproxystate.Capability_CAPABILITY_TRANSPARENT) - } - } - return l, err -} - -func makePermissiveRouter(cfgSnap *proxycfg.ConfigSnapshot, opts destinationOpts) (*pbproxystate.Router, error) { - servicePort := cfgSnap.Proxy.LocalServicePort - if servicePort <= 0 { - // No service port means the service does not accept incoming traffic, so - // the connect proxy does not need to listen for incoming non-mTLS traffic. - return nil, nil - } - - opts.statPrefix += "permissive_" - dest, err := makeL4Destination(opts) - if err != nil { - return nil, err - } - - router := &pbproxystate.Router{ - Match: &pbproxystate.Match{ - DestinationPort: &wrapperspb.UInt32Value{Value: uint32(servicePort)}, - }, - Destination: &pbproxystate.Router_L4{L4: dest}, - } - return router, nil -} - -// finalizePublicListenerFromConfig is used for best-effort injection of L4 intentions and TLS onto listeners. -func (s *Converter) finalizePublicListenerFromConfig(l *pbproxystate.Listener, cfgSnap *proxycfg.ConfigSnapshot) error { - // TODO(proxystate): L4 intentions will be added in the future. - //if !useHTTPFilter { - // // Best-effort injection of L4 intentions - // if err := s.injectConnectFilters(cfgSnap, l); err != nil { - // return nil - // } - //} - - // Always apply TLS certificates - if err := s.injectConnectTLSForPublicListener(cfgSnap, l); err != nil { - return nil - } - - return nil -} - -func (s *Converter) makeExposedCheckListener(cfgSnap *proxycfg.ConfigSnapshot, cluster string, path structs.ExposePath) (*pbproxystate.Listener, error) { - cfg, err := config.ParseProxyConfig(cfgSnap.Proxy.Config) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) - } - - // No user config, use default listener - addr := cfgSnap.Address - - // Override with bind address if one is set, otherwise default to 0.0.0.0 - if cfg.BindAddress != "" { - addr = cfg.BindAddress - } else if addr == "" { - addr = "0.0.0.0" - } - - // Strip any special characters from path to make a valid and hopefully unique name - r := regexp.MustCompile(`[^a-zA-Z0-9]+`) - strippedPath := r.ReplaceAllString(path.Path, "") - listenerName := fmt.Sprintf("exposed_path_%s", strippedPath) - - listenerOpts := makeListenerOpts{ - name: listenerName, - //accessLogs: cfgSnap.Proxy.AccessLogs, - addr: addr, - port: path.ListenerPort, - direction: pbproxystate.Direction_DIRECTION_INBOUND, - logger: s.Logger, - } - l := makeListener(listenerOpts) - - filterName := fmt.Sprintf("exposed_path_filter_%s_%d", strippedPath, path.ListenerPort) - - destOpts := destinationOpts{ - useRDS: false, - protocol: path.Protocol, - filterName: filterName, - routeName: filterName, - cluster: cluster, - statPrefix: "", - routePath: path.Path, - httpAuthzFilters: nil, - //accessLogs: &cfgSnap.Proxy.AccessLogs, - logger: s.Logger, - // in the exposed check listener we don't set the tracing configuration - } - - router := &pbproxystate.Router{} - err = s.addRouterDestination(destOpts, router) - if err != nil { - return nil, err - } - - // For registered checks restrict traffic sources to localhost and Consul's advertise addr - if path.ParsedFromCheck { - - // For the advertise addr we use a CidrRange that only matches one address - advertise := s.CfgFetcher.AdvertiseAddrLAN() - - // Get prefix length based on whether address is ipv4 (32 bits) or ipv6 (128 bits) - advertiseLen := 32 - ip := net.ParseIP(advertise) - if ip != nil && strings.Contains(advertise, ":") { - advertiseLen = 128 - } - - ranges := make([]*pbproxystate.CidrRange, 0, 3) - ranges = append(ranges, - &pbproxystate.CidrRange{AddressPrefix: "127.0.0.1", PrefixLen: &wrapperspb.UInt32Value{Value: 8}}, - &pbproxystate.CidrRange{AddressPrefix: advertise, PrefixLen: &wrapperspb.UInt32Value{Value: uint32(advertiseLen)}}, - ) - - if ok, err := platform.SupportsIPv6(); err != nil { - return nil, err - } else if ok { - ranges = append(ranges, - &pbproxystate.CidrRange{AddressPrefix: "::1", PrefixLen: &wrapperspb.UInt32Value{Value: 128}}, - ) - } - - router.Match = &pbproxystate.Match{ - SourcePrefixRanges: ranges, - } - } - - l.Routers = []*pbproxystate.Router{router} - - return l, err -} - -// TODO(proxystate): Gateway support will be added in the future. -// Functions and types to convert from agent/xds/listeners.go: -// func makeTerminatingGatewayListener -// type terminatingGatewayFilterChainOpts -// func makeFilterChainTerminatingGateway -// func makeMeshGatewayListener -// func makeMeshGatewayPeerFilterChain - -type routerOpts struct { - //accessLogs *structs.AccessLogsConfig - routeName string - clusterName string - filterName string - protocol string - useRDS bool - statPrefix string - forwardClientDetails bool - forwardClientPolicy pbproxystate.XFCCPolicy - //tracing *envoy_http_v3.HttpConnectionManager_Tracing -} - -func (g *Converter) makeUpstreamRouter(opts routerOpts) (*pbproxystate.Router, error) { - if opts.statPrefix == "" { - opts.statPrefix = "upstream." - } - - router := &pbproxystate.Router{} - - err := g.addRouterDestination(destinationOpts{ - useRDS: opts.useRDS, - protocol: opts.protocol, - filterName: opts.filterName, - routeName: opts.routeName, - cluster: opts.clusterName, - statPrefix: opts.statPrefix, - forwardClientDetails: opts.forwardClientDetails, - forwardClientPolicy: opts.forwardClientPolicy, - //tracing: opts.tracing, - //accessLogs: opts.accessLogs, - logger: g.Logger, - }, router) - if err != nil { - return nil, err - } - - return router, nil -} - -// simpleChainTarget returns the discovery target for a chain with a single node. -// A chain can have a single target if it is for a TCP service or an HTTP service without -// multiple splits/routes/failovers. -func simpleChainTarget(chain *structs.CompiledDiscoveryChain) (*structs.DiscoveryTarget, error) { - startNode := chain.Nodes[chain.StartNode] - if startNode == nil { - return nil, fmt.Errorf("missing first node in compiled discovery chain for: %s", chain.ServiceName) - } - if startNode.Type != structs.DiscoveryGraphNodeTypeResolver { - return nil, fmt.Errorf("expected discovery chain with single node, found unexpected start node: %s", startNode.Type) - } - targetID := startNode.Resolver.Target - return chain.Targets[targetID], nil -} - -func (s *Converter) getAndModifyUpstreamConfigForListener( - uid proxycfg.UpstreamID, - u *structs.Upstream, - chain *structs.CompiledDiscoveryChain, -) structs.UpstreamConfig { - var ( - cfg structs.UpstreamConfig - err error - ) - - configMap := make(map[string]interface{}) - if u != nil { - configMap = u.Config - } - if chain == nil || chain.Default { - cfg, err = structs.ParseUpstreamConfigNoDefaults(configMap) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse", "upstream", uid, "error", err) - } - } else { - // Use NoDefaults here so that we can set the protocol to the chain - // protocol if necessary - cfg, err = structs.ParseUpstreamConfigNoDefaults(configMap) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse", "upstream", uid, "error", err) - } - - if cfg.EnvoyListenerJSON != "" { - s.Logger.Warn("ignoring escape hatch setting because already configured for", - "discovery chain", chain.ServiceName, "upstream", uid, "config", "envoy_listener_json") - - // Remove from config struct so we don't use it later on - cfg.EnvoyListenerJSON = "" - } - } - protocol := cfg.Protocol - if chain != nil { - if protocol == "" { - protocol = chain.Protocol - } - if protocol == "" { - protocol = "tcp" - } - } else { - protocol = "tcp" - } - - // set back on the config so that we can use it from return value - cfg.Protocol = protocol - - return cfg -} - -func (s *Converter) getAndModifyUpstreamConfigForPeeredListener( - uid proxycfg.UpstreamID, - u *structs.Upstream, - peerMeta structs.PeeringServiceMeta, -) structs.UpstreamConfig { - var ( - cfg structs.UpstreamConfig - err error - ) - - configMap := make(map[string]interface{}) - if u != nil { - configMap = u.Config - } - - cfg, err = structs.ParseUpstreamConfigNoDefaults(configMap) - if err != nil { - // Don't hard fail on a config typo, just warn. The parse func returns - // default config if there is an error so it's safe to continue. - s.Logger.Warn("failed to parse", "upstream", uid, "error", err) - } - - // Ignore the configured protocol for peer upstreams, since it is defined by the remote - // cluster, which we cannot control. - protocol := peerMeta.Protocol - if protocol == "" { - protocol = "tcp" - } - - // set back on the config so that we can use it from return value - cfg.Protocol = protocol - - if cfg.ConnectTimeoutMs == 0 { - cfg.ConnectTimeoutMs = 5000 - } - - if cfg.MeshGateway.Mode == "" && u != nil { - cfg.MeshGateway = u.MeshGateway - } - - return cfg -} - -type destinationOpts struct { - // All listener filters - // TODO(proxystate): access logs support will be added later - //accessLogs *structs.AccessLogsConfig - cluster string - filterName string - logger hclog.Logger - protocol string - statPrefix string - - // HTTP listener filter options - forwardClientDetails bool - forwardClientPolicy pbproxystate.XFCCPolicy - httpAuthzFilters []*envoy_http_v3.HttpFilter - idleTimeoutMs *int - requestTimeoutMs *int - routeName string - routePath string - // TODO(proxystate): tracing support will be added later - //tracing *envoy_http_v3.HttpConnectionManager_Tracing - useRDS bool -} - -func (g *Converter) addRouterDestination(opts destinationOpts, router *pbproxystate.Router) error { - switch opts.protocol { - case "grpc", "http2", "http": - dest, err := g.makeL7Destination(opts) - if err != nil { - return err - } - router.Destination = &pbproxystate.Router_L7{ - L7: dest, - } - return nil - case "tcp": - fallthrough - default: - if opts.useRDS { - return fmt.Errorf("RDS is not compatible with the tcp proxy filter") - } else if opts.cluster == "" { - return fmt.Errorf("cluster name is required for a tcp proxy filter") - } - dest, err := makeL4Destination(opts) - if err != nil { - return err - } - router.Destination = &pbproxystate.Router_L4{ - L4: dest, - } - return nil - } -} - -func makeL4Destination(opts destinationOpts) (*pbproxystate.L4Destination, error) { - // TODO(proxystate): implement access logs at top level - //accessLogs, err := accesslogs.MakeAccessLogs(opts.accessLogs, false) - //if err != nil && opts.logger != nil { - // opts.logger.Warn("could not make access log xds for tcp proxy", err) - //} - - l4Dest := &pbproxystate.L4Destination{ - //AccessLog: accessLogs, - Destination: &pbproxystate.L4Destination_Cluster{ - Cluster: &pbproxystate.DestinationCluster{ - Name: opts.cluster, - }, - }, - StatPrefix: makeStatPrefix(opts.statPrefix, opts.filterName), - } - return l4Dest, nil -} - -func makeStatPrefix(prefix, filterName string) string { - // Replace colons here because Envoy does that in the metrics for the actual - // clusters but doesn't in the stat prefix here while dashboards assume they - // will match. - return fmt.Sprintf("%s%s", prefix, strings.Replace(filterName, ":", "_", -1)) -} - -func (g *Converter) makeL7Destination(opts destinationOpts) (*pbproxystate.L7Destination, error) { - dest := &pbproxystate.L7Destination{} - - // TODO(proxystate) access logs will be added to proxystate top level and in xds generation - //accessLogs, err := accesslogs.MakeAccessLogs(opts.accessLogs, false) - //if err != nil && opts.logger != nil { - // opts.logger.Warn("could not make access log xds for http connection manager", err) - //} - - // An L7 Destination's name will be the route name, so during xds generation the route can be looked up. - dest.Route = &pbproxystate.L7DestinationRoute{ - Name: opts.routeName, - } - dest.StatPrefix = makeStatPrefix(opts.statPrefix, opts.filterName) - - // TODO(proxystate) tracing will be added at the top level proxystate and xds generation - //if opts.tracing != nil { - // cfg.Tracing = opts.tracing - //} - - if opts.useRDS { - if opts.cluster != "" { - return nil, fmt.Errorf("cannot specify cluster name when using RDS") - } - } else { - dest.StaticRoute = true - - if opts.cluster == "" { - return nil, fmt.Errorf("must specify cluster name when not using RDS") - } - - routeRule := &pbproxystate.RouteRule{ - Match: &pbproxystate.RouteMatch{ - PathMatch: &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: "/", - }, - }, - // TODO(banks) Envoy supports matching only valid GRPC - // requests which might be nice to add here for gRPC services - // but it's not supported in our current envoy SDK version - // although docs say it was supported by 1.8.0. Going to defer - // that until we've updated the deps. - }, - Destination: &pbproxystate.RouteDestination{ - Destination: &pbproxystate.RouteDestination_Cluster{ - Cluster: &pbproxystate.DestinationCluster{ - Name: opts.cluster, - }, - }, - }, - } - - var timeoutCfg *pbproxystate.TimeoutConfig - r := routeRule.GetDestination() - - if opts.requestTimeoutMs != nil { - if timeoutCfg == nil { - timeoutCfg = &pbproxystate.TimeoutConfig{} - } - timeoutCfg.Timeout = durationpb.New(time.Duration(*opts.requestTimeoutMs) * time.Millisecond) - } - - if opts.idleTimeoutMs != nil { - if timeoutCfg == nil { - timeoutCfg = &pbproxystate.TimeoutConfig{} - } - timeoutCfg.IdleTimeout = durationpb.New(time.Duration(*opts.idleTimeoutMs) * time.Millisecond) - } - r.DestinationConfiguration = &pbproxystate.DestinationConfiguration{ - TimeoutConfig: timeoutCfg, - } - - // If a path is provided, do not match on a catch-all prefix - if opts.routePath != "" { - routeRule.Match.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Exact{ - Exact: opts.routePath, - }, - } - } - - // Create static route object - route := &pbproxystate.Route{ - VirtualHosts: []*pbproxystate.VirtualHost{ - { - Name: opts.filterName, - Domains: []string{"*"}, - RouteRules: []*pbproxystate.RouteRule{ - routeRule, - }, - }, - }, - } - // Save the route to proxy state. - g.proxyState.Routes[opts.routeName] = route - } - - dest.Protocol = l7Protocols[opts.protocol] - - // Note the default leads to setting HttpConnectionManager_SANITIZE - if opts.forwardClientDetails { - dest.IncludeXfccPolicy = true - dest.XfccPolicy = opts.forwardClientPolicy - } - - // Like injectConnectFilters for L4, here we ensure that the first filter - // (other than the "envoy.grpc_http1_bridge" filter) in the http filter - // chain of a public listener is the authz filter to prevent unauthorized - // access and that every filter chain uses our TLS certs. - if len(opts.httpAuthzFilters) > 0 { - // TODO(proxystate) support intentions in the future - dest.TrafficPermissions = &pbproxystate.TrafficPermissions{} - //cfg.HttpFilters = append(opts.httpAuthzFilters, cfg.HttpFilters...) - } - - // TODO(proxystate) add grpc http filters in xds in future L7 task - //if opts.protocol == "grpc" { - // grpcHttp1Bridge, err := makeEnvoyHTTPFilter( - // "envoy.filters.http.grpc_http1_bridge", - // &envoy_grpc_http1_bridge_v3.Config{}, - // ) - // if err != nil { - // return nil, err - // } - // - // // In envoy 1.14.x the default value "stats_for_all_methods=true" was - // // deprecated, and was changed to "false" in 1.18.x. Avoid using the - // // default. TODO: we may want to expose this to users somehow easily. - // grpcStatsFilter, err := makeEnvoyHTTPFilter( - // "envoy.filters.http.grpc_stats", - // &envoy_grpc_stats_v3.FilterConfig{ - // PerMethodStatSpecifier: &envoy_grpc_stats_v3.FilterConfig_StatsForAllMethods{ - // StatsForAllMethods: makeBoolValue(true), - // }, - // }, - // ) - // if err != nil { - // return nil, err - // } - // - // // Add grpc bridge before router and authz, and the stats in front of that. - // cfg.HttpFilters = append([]*envoy_http_v3.HttpFilter{ - // grpcStatsFilter, - // grpcHttp1Bridge, - // }, cfg.HttpFilters...) - //} - - return dest, nil -} - -var tlsVersionsWithConfigurableCipherSuites = map[types.TLSVersion]struct{}{ - // Remove these two if Envoy ever sets TLS 1.3 as default minimum - types.TLSVersionUnspecified: {}, - types.TLSVersionAuto: {}, - - types.TLSv1_0: {}, - types.TLSv1_1: {}, - types.TLSv1_2: {}, -} - -func makeTLSParametersFromProxyTLSConfig(tlsConf *structs.MeshDirectionalTLSConfig) *pbproxystate.TLSParameters { - if tlsConf == nil { - return &pbproxystate.TLSParameters{} - } - - return makeTLSParametersFromTLSConfig(tlsConf.TLSMinVersion, tlsConf.TLSMaxVersion, tlsConf.CipherSuites) -} - -func makeTLSParametersFromTLSConfig( - tlsMinVersion types.TLSVersion, - tlsMaxVersion types.TLSVersion, - cipherSuites []types.TLSCipherSuite, -) *pbproxystate.TLSParameters { - tlsParams := pbproxystate.TLSParameters{} - - if tlsMinVersion != types.TLSVersionUnspecified { - tlsParams.MinVersion = tlsVersions[tlsMinVersion] - } - if tlsMaxVersion != types.TLSVersionUnspecified { - tlsParams.MaxVersion = tlsVersions[tlsMaxVersion] - } - if len(cipherSuites) != 0 { - var suites []pbproxystate.TLSCipherSuite - for _, cs := range cipherSuites { - suites = append(suites, tlsCipherSuites[cs]) - } - tlsParams.CipherSuites = suites - } - - return &tlsParams -} - -var tlsVersions = map[types.TLSVersion]pbproxystate.TLSVersion{ - types.TLSVersionAuto: pbproxystate.TLSVersion_TLS_VERSION_AUTO, - types.TLSv1_0: pbproxystate.TLSVersion_TLS_VERSION_1_0, - types.TLSv1_1: pbproxystate.TLSVersion_TLS_VERSION_1_1, - types.TLSv1_2: pbproxystate.TLSVersion_TLS_VERSION_1_2, - types.TLSv1_3: pbproxystate.TLSVersion_TLS_VERSION_1_3, -} - -var tlsCipherSuites = map[types.TLSCipherSuite]pbproxystate.TLSCipherSuite{ - types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256, - types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305, - types.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256, - types.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305, - types.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA, - types.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA, - types.TLS_RSA_WITH_AES_128_GCM_SHA256: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES128_GCM_SHA256, - types.TLS_RSA_WITH_AES_128_CBC_SHA: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES128_SHA, - types.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384, - types.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384, - types.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA, - types.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA, - types.TLS_RSA_WITH_AES_256_GCM_SHA384: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES256_GCM_SHA384, - types.TLS_RSA_WITH_AES_256_CBC_SHA: pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES256_SHA, -} - -var l7Protocols = map[string]pbproxystate.L7Protocol{ - "http": pbproxystate.L7Protocol_L7_PROTOCOL_HTTP, - "http2": pbproxystate.L7Protocol_L7_PROTOCOL_HTTP2, - "grpc": pbproxystate.L7Protocol_L7_PROTOCOL_GRPC, -} - -var balanceConnections = map[string]pbproxystate.BalanceConnections{ - "": pbproxystate.BalanceConnections_BALANCE_CONNECTIONS_DEFAULT, - structs.ConnectionExactBalance: pbproxystate.BalanceConnections_BALANCE_CONNECTIONS_EXACT, -} diff --git a/agent/xds/proxystateconverter/locality_policy.go b/agent/xds/proxystateconverter/locality_policy.go deleted file mode 100644 index c33f428fc2e2..000000000000 --- a/agent/xds/proxystateconverter/locality_policy.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "fmt" - - "github.com/hashicorp/consul/agent/structs" -) - -func groupedEndpoints(locality *structs.Locality, policy *structs.DiscoveryPrioritizeByLocality, csns structs.CheckServiceNodes) ([]structs.CheckServiceNodes, error) { - switch { - case policy == nil || policy.Mode == "" || policy.Mode == "none": - return []structs.CheckServiceNodes{csns}, nil - case policy.Mode == "failover": - return prioritizeByLocalityFailover(locality, csns), nil - default: - return nil, fmt.Errorf("unexpected priortize-by-locality mode %q", policy.Mode) - } -} diff --git a/agent/xds/proxystateconverter/locality_policy_ce.go b/agent/xds/proxystateconverter/locality_policy_ce.go deleted file mode 100644 index cd7a3e7912e1..000000000000 --- a/agent/xds/proxystateconverter/locality_policy_ce.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent - -package proxystateconverter - -import ( - "github.com/hashicorp/consul/agent/structs" -) - -func prioritizeByLocalityFailover(locality *structs.Locality, csns structs.CheckServiceNodes) []structs.CheckServiceNodes { - return nil -} diff --git a/agent/xds/proxystateconverter/routes.go b/agent/xds/proxystateconverter/routes.go deleted file mode 100644 index 9cdd24fe12b0..000000000000 --- a/agent/xds/proxystateconverter/routes.go +++ /dev/null @@ -1,777 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxystateconverter - -import ( - "errors" - "fmt" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "sort" - "strings" - "time" - - "github.com/hashicorp/consul/agent/xds/response" - - "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/structs" - "google.golang.org/protobuf/types/known/durationpb" -) - -// routesFromSnapshot returns the xDS API representation of the "routes" in the -// snapshot. -func (s *Converter) routesFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) error { - if cfgSnap == nil { - return errors.New("nil config given") - } - - switch cfgSnap.Kind { - case structs.ServiceKindConnectProxy: - return s.routesForConnectProxy(cfgSnap) - // TODO(proxystate): Ingress Gateways will be added in the future. - //case structs.ServiceKindIngressGateway: - // return s.routesForIngressGateway(cfgSnap) - // TODO(proxystate): API Gateways will be added in the future. - //case structs.ServiceKindAPIGateway: - // return s.routesForAPIGateway(cfgSnap) - // TODO(proxystate): Terminating Gateways will be added in the future. - //case structs.ServiceKindTerminatingGateway: - // return s.routesForTerminatingGateway(cfgSnap) - // TODO(proxystate): Mesh Gateways will be added in the future. - //case structs.ServiceKindMeshGateway: - // return s.routesForMeshGateway(cfgSnap) - default: - return fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind) - } -} - -// routesFromSnapshotConnectProxy returns the xDS API representation of the -// "routes" in the snapshot. -func (s *Converter) routesForConnectProxy(cfgSnap *proxycfg.ConfigSnapshot) error { - for uid, chain := range cfgSnap.ConnectProxy.DiscoveryChain { - if chain.Default { - continue - } - - virtualHost, err := s.makeUpstreamHostForDiscoveryChain(cfgSnap, uid, chain, []string{"*"}, false) - if err != nil { - return err - } - if virtualHost == nil { - continue - } - - route := &pbproxystate.Route{ - VirtualHosts: []*pbproxystate.VirtualHost{virtualHost}, - } - s.proxyState.Routes[uid.EnvoyID()] = route - } - addressesMap := make(map[string]map[string]string) - err := cfgSnap.ConnectProxy.DestinationsUpstream.ForEachKeyE(func(uid proxycfg.UpstreamID) error { - svcConfig, ok := cfgSnap.ConnectProxy.DestinationsUpstream.Get(uid) - if !ok || svcConfig == nil { - return nil - } - if !structs.IsProtocolHTTPLike(svcConfig.Protocol) { - // Routes can only be defined for HTTP services - return nil - } - - for _, address := range svcConfig.Destination.Addresses { - - routeName := clusterNameForDestination(cfgSnap, "~http", fmt.Sprintf("%d", svcConfig.Destination.Port), svcConfig.NamespaceOrDefault(), svcConfig.PartitionOrDefault()) - if _, ok := addressesMap[routeName]; !ok { - addressesMap[routeName] = make(map[string]string) - } - // cluster name is unique per address/port so we should not be doing any override here - clusterName := clusterNameForDestination(cfgSnap, svcConfig.Name, address, svcConfig.NamespaceOrDefault(), svcConfig.PartitionOrDefault()) - addressesMap[routeName][clusterName] = address - } - return nil - }) - - if err != nil { - return err - } - - for routeName, clusters := range addressesMap { - route, err := s.makeRouteForAddresses(clusters) - if err != nil { - return err - } - if route != nil { - s.proxyState.Routes[routeName] = route - } - } - - // TODO(rb): make sure we don't generate an empty result - return nil -} - -func (s *Converter) makeRouteForAddresses(addresses map[string]string) (*pbproxystate.Route, error) { - route, err := makeAddressesRoute(addresses) - if err != nil { - s.Logger.Error("failed to make route", "cluster", "error", err) - return nil, err - } - - return route, nil -} - -// TODO(proxystate): Terminating Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func routesForTerminatingGateway - -// TODO(proxystate): Mesh Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func routesForMeshGateway - -func makeAddressesRoute(addresses map[string]string) (*pbproxystate.Route, error) { - route := &pbproxystate.Route{} - for clusterName, address := range addresses { - destination := makeRouteDestinationFromName(clusterName) - virtualHost := &pbproxystate.VirtualHost{ - Name: clusterName, - Domains: []string{address}, - RouteRules: []*pbproxystate.RouteRule{ - { - Match: makeDefaultRouteMatch(), - Destination: destination, - }, - }, - } - route.VirtualHosts = append(route.VirtualHosts, virtualHost) - } - - // sort virtual hosts to have a stable order - sort.SliceStable(route.VirtualHosts, func(i, j int) bool { - return route.VirtualHosts[i].Name > route.VirtualHosts[j].Name - }) - return route, nil -} - -// makeRouteDestinationFromName (fka makeRouteActionFromName) -func makeRouteDestinationFromName(clusterName string) *pbproxystate.RouteDestination { - return &pbproxystate.RouteDestination{ - Destination: &pbproxystate.RouteDestination_Cluster{ - Cluster: &pbproxystate.DestinationCluster{ - Name: clusterName, - }, - }, - } -} - -// TODO(proxystate): Ingress Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func routesForIngressGateway - -// TODO(proxystate): API Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func routesForAPIGateway -// func buildHTTPRouteUpstream - -// TODO(proxystate): Ingress Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func findIngressServiceMatchingUpstream - -// TODO(proxystate): Ingress Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func generateUpstreamIngressDomains - -// TODO(proxystate): Ingress Gateways will be added in the future. -// Functions to add from agent/xds/clusters.go: -// func generateUpstreamAPIsDomains - -func (s *Converter) makeUpstreamHostForDiscoveryChain( - cfgSnap *proxycfg.ConfigSnapshot, - uid proxycfg.UpstreamID, - chain *structs.CompiledDiscoveryChain, - serviceDomains []string, - forMeshGateway bool, -) (*pbproxystate.VirtualHost, error) { - var routeRules []*pbproxystate.RouteRule - - startNode := chain.Nodes[chain.StartNode] - if startNode == nil { - return nil, fmt.Errorf("missing first node in compiled discovery chain for: %s", chain.ServiceName) - } - - upstreamsSnapshot, err := cfgSnap.ToConfigSnapshotUpstreams() - if err != nil && !forMeshGateway { - return nil, err - } - - switch startNode.Type { - case structs.DiscoveryGraphNodeTypeRouter: - routeRules = make([]*pbproxystate.RouteRule, 0, len(startNode.Routes)) - - for _, discoveryRoute := range startNode.Routes { - routeMatch := makeRouteMatchForDiscoveryRoute(discoveryRoute) - - var ( - routeDestination *pbproxystate.RouteDestination - err error - ) - - nextNode := chain.Nodes[discoveryRoute.NextNode] - - var lb *structs.LoadBalancer - if nextNode.LoadBalancer != nil { - lb = nextNode.LoadBalancer - } - - switch nextNode.Type { - case structs.DiscoveryGraphNodeTypeSplitter: - routeDestination, err = s.makeRouteDestinationForSplitter(upstreamsSnapshot, nextNode.Splits, chain, forMeshGateway) - if err != nil { - return nil, err - } - - case structs.DiscoveryGraphNodeTypeResolver: - rd, ok := s.makeRouteDestinationForChainCluster(upstreamsSnapshot, nextNode.Resolver.Target, chain, forMeshGateway) - if !ok { - continue - } - routeDestination = rd - - default: - return nil, fmt.Errorf("unexpected graph node after route %q", nextNode.Type) - } - - routeDestination.DestinationConfiguration = &pbproxystate.DestinationConfiguration{} - if err := injectLBToDestinationConfiguration(lb, routeDestination.DestinationConfiguration); err != nil { - return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err) - } - - // TODO(rb): Better help handle the envoy case where you need (prefix=/foo/,rewrite=/) and (exact=/foo,rewrite=/) to do a full rewrite - - destination := discoveryRoute.Definition.Destination - - routeRule := &pbproxystate.RouteRule{} - - if destination != nil { - configHandle := routeDestination.DestinationConfiguration - if destination.PrefixRewrite != "" { - configHandle.PrefixRewrite = destination.PrefixRewrite - } - - if destination.RequestTimeout > 0 || destination.IdleTimeout > 0 { - configHandle.TimeoutConfig = &pbproxystate.TimeoutConfig{} - } - if destination.RequestTimeout > 0 { - configHandle.TimeoutConfig.Timeout = durationpb.New(destination.RequestTimeout) - } - if destination.IdleTimeout > 0 { - configHandle.TimeoutConfig.IdleTimeout = durationpb.New(destination.IdleTimeout) - } - - if destination.HasRetryFeatures() { - configHandle.RetryPolicy = getRetryPolicyForDestination(destination) - } - - if err := injectHeaderManipToRoute(destination, routeRule); err != nil { - return nil, fmt.Errorf("failed to apply header manipulation configuration to route: %v", err) - } - } - - routeRule.Match = routeMatch - routeRule.Destination = routeDestination - - routeRules = append(routeRules, routeRule) - } - - case structs.DiscoveryGraphNodeTypeSplitter: - routeDestination, err := s.makeRouteDestinationForSplitter(upstreamsSnapshot, startNode.Splits, chain, forMeshGateway) - if err != nil { - return nil, err - } - var lb *structs.LoadBalancer - if startNode.LoadBalancer != nil { - lb = startNode.LoadBalancer - } - routeDestination.DestinationConfiguration = &pbproxystate.DestinationConfiguration{} - if err := injectLBToDestinationConfiguration(lb, routeDestination.DestinationConfiguration); err != nil { - return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err) - } - - defaultRoute := &pbproxystate.RouteRule{ - Match: makeDefaultRouteMatch(), - Destination: routeDestination, - } - - routeRules = []*pbproxystate.RouteRule{defaultRoute} - - case structs.DiscoveryGraphNodeTypeResolver: - routeDestination, ok := s.makeRouteDestinationForChainCluster(upstreamsSnapshot, startNode.Resolver.Target, chain, forMeshGateway) - if !ok { - break - } - var lb *structs.LoadBalancer - if startNode.LoadBalancer != nil { - lb = startNode.LoadBalancer - } - routeDestination.DestinationConfiguration = &pbproxystate.DestinationConfiguration{} - if err := injectLBToDestinationConfiguration(lb, routeDestination.DestinationConfiguration); err != nil { - return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err) - } - - if startNode.Resolver.RequestTimeout > 0 { - to := &pbproxystate.TimeoutConfig{ - Timeout: durationpb.New(startNode.Resolver.RequestTimeout), - } - routeDestination.DestinationConfiguration.TimeoutConfig = to - } - defaultRoute := &pbproxystate.RouteRule{ - Match: makeDefaultRouteMatch(), - Destination: routeDestination, - } - - routeRules = []*pbproxystate.RouteRule{defaultRoute} - - default: - return nil, fmt.Errorf("unknown first node in discovery chain of type: %s", startNode.Type) - } - - host := &pbproxystate.VirtualHost{ - Name: uid.EnvoyID(), - Domains: serviceDomains, - RouteRules: routeRules, - } - - return host, nil -} - -func getRetryPolicyForDestination(destination *structs.ServiceRouteDestination) *pbproxystate.RetryPolicy { - retryPolicy := &pbproxystate.RetryPolicy{} - if destination.NumRetries > 0 { - retryPolicy.NumRetries = response.MakeUint32Value(int(destination.NumRetries)) - } - - // The RetryOn magic values come from: https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/http_filters/router_filter#config-http-filters-router-x-envoy-retry-on - var retryStrings []string - - if len(destination.RetryOn) > 0 { - retryStrings = append(retryStrings, destination.RetryOn...) - } - - if destination.RetryOnConnectFailure { - // connect-failure can be enabled by either adding connect-failure to the RetryOn list or by using the legacy RetryOnConnectFailure option - // Check that it's not already in the RetryOn list, so we don't set it twice - connectFailureExists := false - for _, r := range retryStrings { - if r == "connect-failure" { - connectFailureExists = true - } - } - if !connectFailureExists { - retryStrings = append(retryStrings, "connect-failure") - } - } - - if len(destination.RetryOnStatusCodes) > 0 { - retryStrings = append(retryStrings, "retriable-status-codes") - retryPolicy.RetriableStatusCodes = destination.RetryOnStatusCodes - } - - retryPolicy.RetryOn = strings.Join(retryStrings, ",") - - return retryPolicy -} - -func makeRouteMatchForDiscoveryRoute(discoveryRoute *structs.DiscoveryRoute) *pbproxystate.RouteMatch { - match := discoveryRoute.Definition.Match - if match == nil || match.IsEmpty() { - return makeDefaultRouteMatch() - } - - routeMatch := &pbproxystate.RouteMatch{} - - switch { - case match.HTTP.PathExact != "": - routeMatch.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Exact{ - Exact: match.HTTP.PathExact, - }, - } - case match.HTTP.PathPrefix != "": - routeMatch.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: match.HTTP.PathPrefix, - }, - } - case match.HTTP.PathRegex != "": - routeMatch.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Regex{ - Regex: match.HTTP.PathRegex, - }, - } - default: - routeMatch.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: "/", - }, - } - } - - if len(match.HTTP.Header) > 0 { - routeMatch.HeaderMatches = make([]*pbproxystate.HeaderMatch, 0, len(match.HTTP.Header)) - for _, hdr := range match.HTTP.Header { - headerMatch := &pbproxystate.HeaderMatch{ - Name: hdr.Name, - } - - switch { - case hdr.Exact != "": - headerMatch.Match = &pbproxystate.HeaderMatch_Exact{ - Exact: hdr.Exact, - } - case hdr.Regex != "": - headerMatch.Match = &pbproxystate.HeaderMatch_Regex{ - Regex: hdr.Regex, - } - case hdr.Prefix != "": - headerMatch.Match = &pbproxystate.HeaderMatch_Prefix{ - Prefix: hdr.Prefix, - } - case hdr.Suffix != "": - headerMatch.Match = &pbproxystate.HeaderMatch_Suffix{ - Suffix: hdr.Suffix, - } - case hdr.Present: - headerMatch.Match = &pbproxystate.HeaderMatch_Present{ - Present: true, - } - default: - continue // skip this impossible situation - } - - if hdr.Invert { - headerMatch.InvertMatch = true - } - - routeMatch.HeaderMatches = append(routeMatch.HeaderMatches, headerMatch) - } - } - - if len(match.HTTP.Methods) > 0 { - routeMatch.MethodMatches = append(routeMatch.MethodMatches, match.HTTP.Methods...) - } - - if len(match.HTTP.QueryParam) > 0 { - routeMatch.QueryParameterMatches = make([]*pbproxystate.QueryParameterMatch, 0, len(match.HTTP.QueryParam)) - for _, qm := range match.HTTP.QueryParam { - - queryMatcher := &pbproxystate.QueryParameterMatch{ - Name: qm.Name, - } - - switch { - case qm.Exact != "": - queryMatcher.Match = &pbproxystate.QueryParameterMatch_Exact{ - Exact: qm.Exact, - } - case qm.Regex != "": - queryMatcher.Match = &pbproxystate.QueryParameterMatch_Regex{ - Regex: qm.Regex, - } - case qm.Present: - queryMatcher.Match = &pbproxystate.QueryParameterMatch_Present{ - Present: true, - } - default: - continue // skip this impossible situation - } - - routeMatch.QueryParameterMatches = append(routeMatch.QueryParameterMatches, queryMatcher) - } - } - - return routeMatch -} - -func makeDefaultRouteMatch() *pbproxystate.RouteMatch { - return &pbproxystate.RouteMatch{ - PathMatch: &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: "/", - }, - }, - // TODO(banks) Envoy supports matching only valid GRPC - // requests which might be nice to add here for gRPC services - // but it's not supported in our current envoy SDK version - // although docs say it was supported by 1.8.0. Going to defer - // that until we've updated the deps. - } -} - -func (s *Converter) makeRouteDestinationForChainCluster( - upstreamsSnapshot *proxycfg.ConfigSnapshotUpstreams, - targetID string, - chain *structs.CompiledDiscoveryChain, - forMeshGateway bool, -) (*pbproxystate.RouteDestination, bool) { - clusterName := s.getTargetClusterName(upstreamsSnapshot, chain, targetID, forMeshGateway) - if clusterName == "" { - return nil, false - } - return makeRouteDestinationFromName(clusterName), true -} - -func (s *Converter) makeRouteDestinationForSplitter( - upstreamsSnapshot *proxycfg.ConfigSnapshotUpstreams, - splits []*structs.DiscoverySplit, - chain *structs.CompiledDiscoveryChain, - forMeshGateway bool, -) (*pbproxystate.RouteDestination, error) { - clusters := make([]*pbproxystate.L7WeightedDestinationCluster, 0, len(splits)) - for _, split := range splits { - nextNode := chain.Nodes[split.NextNode] - - if nextNode.Type != structs.DiscoveryGraphNodeTypeResolver { - return nil, fmt.Errorf("unexpected splitter destination node type: %s", nextNode.Type) - } - targetID := nextNode.Resolver.Target - - clusterName := s.getTargetClusterName(upstreamsSnapshot, chain, targetID, forMeshGateway) - if clusterName == "" { - continue - } - - // The smallest representable weight is 1/10000 or .01% but envoy - // deals with integers so scale everything up by 100x. - weight := int(split.Weight * 100) - - clusterWeight := &pbproxystate.L7WeightedDestinationCluster{ - Name: clusterName, - Weight: response.MakeUint32Value(weight), - } - if err := injectHeaderManipToWeightedCluster(split.Definition, clusterWeight); err != nil { - return nil, err - } - - clusters = append(clusters, clusterWeight) - } - - if len(clusters) <= 0 { - return nil, fmt.Errorf("number of clusters in splitter must be > 0; got %d", len(clusters)) - } - - return &pbproxystate.RouteDestination{ - Destination: &pbproxystate.RouteDestination_WeightedClusters{ - WeightedClusters: &pbproxystate.L7WeightedClusterGroup{ - Clusters: clusters, - }, - }, - }, nil -} - -func injectLBToDestinationConfiguration(lb *structs.LoadBalancer, destinationConfig *pbproxystate.DestinationConfiguration) error { - if lb == nil || !lb.IsHashBased() { - return nil - } - - result := make([]*pbproxystate.LoadBalancerHashPolicy, 0, len(lb.HashPolicies)) - for _, policy := range lb.HashPolicies { - if policy.SourceIP { - p := &pbproxystate.LoadBalancerHashPolicy{ - Policy: &pbproxystate.LoadBalancerHashPolicy_ConnectionProperties{ - ConnectionProperties: &pbproxystate.ConnectionPropertiesPolicy{ - SourceIp: true, - Terminal: policy.Terminal, - }, - }, - } - result = append(result, p) - continue - } - - switch policy.Field { - case structs.HashPolicyHeader: - p := &pbproxystate.LoadBalancerHashPolicy{ - Policy: &pbproxystate.LoadBalancerHashPolicy_Header{ - Header: &pbproxystate.HeaderPolicy{ - Name: policy.FieldValue, - Terminal: policy.Terminal, - }, - }, - } - result = append(result, p) - - case structs.HashPolicyCookie: - - cookie := &pbproxystate.CookiePolicy{ - Name: policy.FieldValue, - Terminal: policy.Terminal, - } - if policy.CookieConfig != nil { - cookie.Path = policy.CookieConfig.Path - - if policy.CookieConfig.TTL != 0*time.Second { - cookie.Ttl = durationpb.New(policy.CookieConfig.TTL) - } - - // Envoy will generate a session cookie if the ttl is present and zero. - if policy.CookieConfig.Session { - cookie.Ttl = durationpb.New(0 * time.Second) - } - } - p := &pbproxystate.LoadBalancerHashPolicy{ - Policy: &pbproxystate.LoadBalancerHashPolicy_Cookie{ - Cookie: cookie, - }, - } - result = append(result, p) - - case structs.HashPolicyQueryParam: - p := &pbproxystate.LoadBalancerHashPolicy{ - Policy: &pbproxystate.LoadBalancerHashPolicy_QueryParameter{ - QueryParameter: &pbproxystate.QueryParameterPolicy{ - Name: policy.FieldValue, - Terminal: policy.Terminal, - }, - }, - } - result = append(result, p) - - default: - return fmt.Errorf("unsupported load balancer hash policy field: %v", policy.Field) - } - } - - destinationConfig.HashPolicies = result - return nil -} - -func injectHeaderManipToRoute(dest *structs.ServiceRouteDestination, r *pbproxystate.RouteRule) error { - if !dest.RequestHeaders.IsZero() { - r.HeaderMutations = append( - r.HeaderMutations, - makeRequestHeaderAdd(dest.RequestHeaders.Add, true)..., - ) - r.HeaderMutations = append( - r.HeaderMutations, - makeRequestHeaderAdd(dest.RequestHeaders.Set, false)..., - ) - r.HeaderMutations = append( - r.HeaderMutations, - makeRequestHeaderRemove(dest.RequestHeaders.Remove), - ) - } - if !dest.ResponseHeaders.IsZero() { - r.HeaderMutations = append( - r.HeaderMutations, - makeResponseHeaderAdd(dest.ResponseHeaders.Add, true)..., - ) - r.HeaderMutations = append( - r.HeaderMutations, - makeResponseHeaderAdd(dest.ResponseHeaders.Set, false)..., - ) - r.HeaderMutations = append( - r.HeaderMutations, - makeResponseHeaderRemove(dest.ResponseHeaders.Remove), - ) - } - return nil -} - -func injectHeaderManipToWeightedCluster(split *structs.ServiceSplit, c *pbproxystate.L7WeightedDestinationCluster) error { - if !split.RequestHeaders.IsZero() { - c.HeaderMutations = append( - c.HeaderMutations, - makeRequestHeaderAdd(split.RequestHeaders.Add, true)..., - ) - c.HeaderMutations = append( - c.HeaderMutations, - makeRequestHeaderAdd(split.RequestHeaders.Set, false)..., - ) - c.HeaderMutations = append( - c.HeaderMutations, - makeRequestHeaderRemove(split.RequestHeaders.Remove), - ) - } - if !split.ResponseHeaders.IsZero() { - c.HeaderMutations = append( - c.HeaderMutations, - makeResponseHeaderAdd(split.ResponseHeaders.Add, true)..., - ) - c.HeaderMutations = append( - c.HeaderMutations, - makeResponseHeaderAdd(split.ResponseHeaders.Set, false)..., - ) - c.HeaderMutations = append( - c.HeaderMutations, - makeResponseHeaderRemove(split.ResponseHeaders.Remove), - ) - } - return nil -} - -func makeRequestHeaderAdd(vals map[string]string, add bool) []*pbproxystate.HeaderMutation { - mutations := make([]*pbproxystate.HeaderMutation, 0, len(vals)) - - appendAction := pbproxystate.AppendAction_APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD - if add { - appendAction = pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - } - - for k, v := range vals { - m := &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_RequestHeaderAdd{ - RequestHeaderAdd: &pbproxystate.RequestHeaderAdd{ - Header: &pbproxystate.Header{ - Key: k, - Value: v, - }, - AppendAction: appendAction, - }, - }, - } - mutations = append(mutations, m) - } - return mutations -} - -func makeRequestHeaderRemove(values []string) *pbproxystate.HeaderMutation { - return &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_RequestHeaderRemove{ - RequestHeaderRemove: &pbproxystate.RequestHeaderRemove{ - HeaderKeys: values, - }, - }, - } -} - -func makeResponseHeaderAdd(vals map[string]string, add bool) []*pbproxystate.HeaderMutation { - mutations := make([]*pbproxystate.HeaderMutation, 0, len(vals)) - - appendAction := pbproxystate.AppendAction_APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD - if add { - appendAction = pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - } - - for k, v := range vals { - m := &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_ResponseHeaderAdd{ - ResponseHeaderAdd: &pbproxystate.ResponseHeaderAdd{ - Header: &pbproxystate.Header{ - Key: k, - Value: v, - }, - AppendAction: appendAction, - }, - }, - } - mutations = append(mutations, m) - } - return mutations -} - -func makeResponseHeaderRemove(values []string) *pbproxystate.HeaderMutation { - return &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_ResponseHeaderRemove{ - ResponseHeaderRemove: &pbproxystate.ResponseHeaderRemove{ - HeaderKeys: values, - }, - }, - } -} diff --git a/agent/xds/rbac.go b/agent/xds/rbac.go index d8252d7cabc9..09c1cd63c8f0 100644 --- a/agent/xds/rbac.go +++ b/agent/xds/rbac.go @@ -1107,9 +1107,6 @@ func parseXFCCToDynamicMetaHTTPFilter() (*envoy_http_v3.HttpFilter, error) { RegexValueRewrite: &envoy_matcher_v3.RegexMatchAndSubstitute{ Pattern: &envoy_matcher_v3.RegexMatcher{ Regex: downstreamServiceIdentityMatcher, - EngineType: &envoy_matcher_v3.RegexMatcher_GoogleRe2{ - GoogleRe2: &envoy_matcher_v3.RegexMatcher_GoogleRE2{}, - }, }, Substitution: f.sub, }, @@ -1253,7 +1250,7 @@ func convertPermission(perm *structs.IntentionPermission) *envoy_rbac_v3.Permiss MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{ Exact: hdr.Exact, }, - IgnoreCase: false, + IgnoreCase: hdr.IgnoreCase, }, } case hdr.Regex != "": @@ -1262,7 +1259,7 @@ func convertPermission(perm *structs.IntentionPermission) *envoy_rbac_v3.Permiss MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ SafeRegex: response.MakeEnvoyRegexMatch(hdr.Regex), }, - IgnoreCase: false, + // IgnoreCase is not supported for SafeRegex matching per Envoy docs. }, } @@ -1272,7 +1269,7 @@ func convertPermission(perm *structs.IntentionPermission) *envoy_rbac_v3.Permiss MatchPattern: &envoy_matcher_v3.StringMatcher_Prefix{ Prefix: hdr.Prefix, }, - IgnoreCase: false, + IgnoreCase: hdr.IgnoreCase, }, } @@ -1282,7 +1279,17 @@ func convertPermission(perm *structs.IntentionPermission) *envoy_rbac_v3.Permiss MatchPattern: &envoy_matcher_v3.StringMatcher_Suffix{ Suffix: hdr.Suffix, }, - IgnoreCase: false, + IgnoreCase: hdr.IgnoreCase, + }, + } + + case hdr.Contains != "": + eh.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_StringMatch{ + StringMatch: &envoy_matcher_v3.StringMatcher{ + MatchPattern: &envoy_matcher_v3.StringMatcher_Contains{ + Contains: hdr.Contains, + }, + IgnoreCase: hdr.IgnoreCase, }, } @@ -1310,8 +1317,12 @@ func convertPermission(perm *structs.IntentionPermission) *envoy_rbac_v3.Permiss eh := &envoy_route_v3.HeaderMatcher{ Name: ":method", - HeaderMatchSpecifier: &envoy_route_v3.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: response.MakeEnvoyRegexMatch(methodHeaderRegex), + HeaderMatchSpecifier: &envoy_route_v3.HeaderMatcher_StringMatch{ + StringMatch: &envoy_matcher_v3.StringMatcher{ + MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ + SafeRegex: response.MakeEnvoyRegexMatch(methodHeaderRegex), + }, + }, }, } diff --git a/agent/xds/rbac_test.go b/agent/xds/rbac_test.go index 71b2a6943326..399f46301010 100644 --- a/agent/xds/rbac_test.go +++ b/agent/xds/rbac_test.go @@ -10,17 +10,12 @@ import ( "sort" "testing" - envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_rbac_v3 "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3" envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xdsv2" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" "github.com/hashicorp/consul/proto/private/pbpeering" ) @@ -556,25 +551,9 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { } ) - makeSpiffe := func(name string, entMeta *acl.EnterpriseMeta) *pbproxystate.Spiffe { - em := *acl.DefaultEnterpriseMeta() - if entMeta != nil { - em = *entMeta - } - regex := makeSpiffePattern(rbacService{ - ServiceName: structs.ServiceName{ - Name: name, - EnterpriseMeta: em, - }, - TrustDomain: testTrustDomain, - }) - return &pbproxystate.Spiffe{Regex: regex} - } - tests := map[string]struct { - intentionDefaultAllow bool - v1Intentions structs.SimplifiedIntentions - v2L4TrafficPermissions *pbproxystate.TrafficPermissions + intentionDefaultAllow bool + v1Intentions structs.SimplifiedIntentions }{ "default-deny-mixed-precedence": { intentionDefaultAllow: false, @@ -583,34 +562,12 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { testIntention(t, "*", "api", structs.IntentionActionDeny), testIntention(t, "web", "*", structs.IntentionActionDeny), ), - v2L4TrafficPermissions: &pbproxystate.TrafficPermissions{ - AllowPermissions: []*pbproxystate.Permission{ - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: makeSpiffe("web", nil), - }, - }, - }, - }, - }, }, "default-deny-service-wildcard-allow": { intentionDefaultAllow: false, v1Intentions: sorted( testSourceIntention("*", structs.IntentionActionAllow), ), - v2L4TrafficPermissions: &pbproxystate.TrafficPermissions{ - AllowPermissions: []*pbproxystate.Permission{ - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: makeSpiffe("*", nil), - }, - }, - }, - }, - }, }, "default-allow-service-wildcard-deny": { intentionDefaultAllow: true, @@ -623,17 +580,6 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { v1Intentions: sorted( testSourceIntention("web", structs.IntentionActionAllow), ), - v2L4TrafficPermissions: &pbproxystate.TrafficPermissions{ - AllowPermissions: []*pbproxystate.Permission{ - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: makeSpiffe("web", nil), - }, - }, - }, - }, - }, }, "default-allow-one-deny": { intentionDefaultAllow: true, @@ -647,18 +593,6 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { testSourceIntention("web", structs.IntentionActionDeny), testSourceIntention("*", structs.IntentionActionAllow), ), - v2L4TrafficPermissions: &pbproxystate.TrafficPermissions{ - AllowPermissions: []*pbproxystate.Permission{ - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: makeSpiffe("*", nil), - ExcludeSpiffes: []*pbproxystate.Spiffe{makeSpiffe("web", nil)}, - }, - }, - }, - }, - }, }, "default-deny-kitchen-sink": { intentionDefaultAllow: false, @@ -669,89 +603,6 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { testSourceIntention("cron", structs.IntentionActionAllow), testSourceIntention("*", structs.IntentionActionAllow), ), - v2L4TrafficPermissions: &pbproxystate.TrafficPermissions{ - AllowPermissions: []*pbproxystate.Permission{ - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: makeSpiffe("cron", nil), - }, - { - Spiffe: makeSpiffe("web", nil), - }, - { - Spiffe: makeSpiffe("*", nil), - ExcludeSpiffes: []*pbproxystate.Spiffe{ - makeSpiffe("web", nil), - makeSpiffe("unsafe", nil), - makeSpiffe("cron", nil), - }, - }, - }, - }, - }, - }, - }, - "v2-kitchen-sink": { - intentionDefaultAllow: false, - v2L4TrafficPermissions: &pbproxystate.TrafficPermissions{ - AllowPermissions: []*pbproxystate.Permission{ - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: makeSpiffe("api", nil), - }, - { - Spiffe: makeSpiffe("*", nil), - ExcludeSpiffes: []*pbproxystate.Spiffe{ - makeSpiffe("unsafe", nil), - }, - }, - }, - }, - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: makeSpiffe("web", nil), - }, - }, - }, - }, - DenyPermissions: []*pbproxystate.Permission{ - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: makeSpiffe("db", nil), - }, - { - Spiffe: makeSpiffe("cron", nil), - }, - }, - }, - }, - }, - }, - "v2-default-deny": { - intentionDefaultAllow: false, - v2L4TrafficPermissions: &pbproxystate.TrafficPermissions{}, - }, - "v2-default-allow": { - intentionDefaultAllow: true, - v2L4TrafficPermissions: &pbproxystate.TrafficPermissions{}, - }, - // This validates that we don't send xDS messages to Envoy that will fail validation. - // Traffic permissions validations prevent this from being written to the IR, so the thing - // that matters is that the snapshot is valid to Envoy. - "v2-ignore-empty-permissions": { - intentionDefaultAllow: false, - v2L4TrafficPermissions: &pbproxystate.TrafficPermissions{ - DenyPermissions: []*pbproxystate.Permission{ - {}, - }, - AllowPermissions: []*pbproxystate.Permission{ - {}, - }, - }, }, "default-allow-kitchen-sink": { intentionDefaultAllow: true, @@ -935,11 +786,19 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { {Name: "x-bar", Exact: "xyz"}, {Name: "x-dib", Prefix: "gaz"}, {Name: "x-gir", Suffix: "zim"}, + {Name: "x-baz", Contains: "qux"}, {Name: "x-zim", Regex: "gi[rR]"}, + // Present does not support IgnoreCase + {Name: "y-bar", Exact: "xyz", IgnoreCase: true}, + {Name: "y-dib", Prefix: "gaz", IgnoreCase: true}, + {Name: "y-gir", Suffix: "zim", IgnoreCase: true}, + {Name: "y-baz", Contains: "qux", IgnoreCase: true}, + // Regex does not support IgnoreCase {Name: "z-foo", Present: true, Invert: true}, {Name: "z-bar", Exact: "xyz", Invert: true}, {Name: "z-dib", Prefix: "gaz", Invert: true}, {Name: "z-gir", Suffix: "zim", Invert: true}, + {Name: "z-baz", Contains: "qux", Invert: true}, {Name: "z-zim", Regex: "gi[rR]", Invert: true}, }, }, @@ -974,15 +833,25 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { Action: structs.IntentionActionDeny, HTTP: &structs.IntentionHTTPPermission{ Header: []structs.IntentionHTTPHeaderPermission{ + // Valid vanilla match options {Name: "x-foo", Present: true}, {Name: "x-bar", Exact: "xyz"}, {Name: "x-dib", Prefix: "gaz"}, {Name: "x-gir", Suffix: "zim"}, + {Name: "x-baz", Contains: "qux"}, {Name: "x-zim", Regex: "gi[rR]"}, + // Valid ignore case match options + // (Present and Regex do not support IgnoreCase) + {Name: "y-bar", Exact: "xyz", IgnoreCase: true}, + {Name: "y-dib", Prefix: "gaz", IgnoreCase: true}, + {Name: "y-gir", Suffix: "zim", IgnoreCase: true}, + {Name: "y-baz", Contains: "qux", IgnoreCase: true}, + // Valid invert match options {Name: "z-foo", Present: true, Invert: true}, {Name: "z-bar", Exact: "xyz", Invert: true}, {Name: "z-dib", Prefix: "gaz", Invert: true}, {Name: "z-gir", Suffix: "zim", Invert: true}, + {Name: "z-baz", Contains: "qux", Invert: true}, {Name: "z-zim", Regex: "gi[rR]", Invert: true}, }, }, @@ -1077,40 +946,17 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { require.JSONEq(t, goldenSimple(t, filepath.Join("rbac", name), gotJSON), gotJSON) }) - - t.Run("v1 vs v2", func(t *testing.T) { - if tt.v2L4TrafficPermissions == nil { - return - } - - tt.v2L4TrafficPermissions.DefaultAllow = tt.intentionDefaultAllow - - filters, err := xdsv2.MakeRBACNetworkFilters(tt.v2L4TrafficPermissions) - require.NoError(t, err) - - var gotJSON string - if len(filters) == 1 { - gotJSON = protoToJSON(t, filters[0]) - } else { - // This is wrapped because protoToJSON won't encode an array of protobufs. - chain := &envoy_listener_v3.FilterChain{} - chain.Filters = filters - gotJSON = protoToJSON(t, chain) - } - - require.JSONEq(t, goldenSimple(t, filepath.Join("rbac", name), gotJSON), gotJSON) - }) }) t.Run("http filter", func(t *testing.T) { - if len(tt.v1Intentions) == 0 { - return - } - - filter, err := makeRBACHTTPFilter(tt.v1Intentions, tt.intentionDefaultAllow, testLocalInfo, testPeerTrustBundle, testJWTProviderConfigEntry) - require.NoError(t, err) t.Run("current", func(t *testing.T) { + if len(tt.v1Intentions) == 0 { + return + } + + filter, err := makeRBACHTTPFilter(tt.v1Intentions, tt.intentionDefaultAllow, testLocalInfo, testPeerTrustBundle, testJWTProviderConfigEntry) + require.NoError(t, err) gotJSON := protoToJSON(t, filter) require.JSONEq(t, goldenSimple(t, filepath.Join("rbac", name+"--httpfilter"), gotJSON), gotJSON) diff --git a/agent/xds/resources_test.go b/agent/xds/resources_test.go index f5a4acca38b0..622127a99251 100644 --- a/agent/xds/resources_test.go +++ b/agent/xds/resources_test.go @@ -5,9 +5,6 @@ package xds import ( "fmt" - "github.com/hashicorp/consul/agent/xds/proxystateconverter" - "github.com/hashicorp/consul/agent/xdsv2" - "google.golang.org/protobuf/proto" "path/filepath" "sort" "testing" @@ -18,19 +15,19 @@ import ( envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/consul/discoverychain" - "github.com/hashicorp/consul/agent/xds/testcommon" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/types" - testinf "github.com/mitchellh/go-testing-interface" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + "github.com/hashicorp/consul/agent/connect" + "github.com/hashicorp/consul/agent/consul/discoverychain" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/response" + "github.com/hashicorp/consul/agent/xds/testcommon" + "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/consul/types" ) var testTypeUrlToPrettyName = map[string]string{ @@ -50,7 +47,6 @@ type goldenTestCase struct { setup func(snap *proxycfg.ConfigSnapshot) overrideGoldenName string generatorSetup func(*ResourceGenerator) - alsoRunTestForV2 bool } func TestAllResourcesFromSnapshot(t *testing.T) { @@ -90,6 +86,8 @@ func TestAllResourcesFromSnapshot(t *testing.T) { xdscommon.SecretType, } + // + // Deprecated: delete resourceSortingFunc := func(items []proto.Message, typeURL string) func(i, j int) bool { return func(i, j int) bool { switch typeURL { @@ -143,43 +141,6 @@ func TestAllResourcesFromSnapshot(t *testing.T) { require.JSONEq(t, expectedJSON, gotJSON) }) } - - if tt.alsoRunTestForV2 { - generator := xdsv2.NewResourceGenerator(testutil.Logger(t)) - - converter := proxystateconverter.NewConverter(testutil.Logger(t), &mockCfgFetcher{addressLan: "10.10.10.10"}) - proxyState, err := converter.ProxyStateFromSnapshot(snap) - require.NoError(t, err) - - v2Resources, err := generator.AllResourcesFromIR(proxyState) - require.NoError(t, err) - require.Len(t, v2Resources, len(typeUrls)-1) // secrets are not currently implemented in V2. - for _, typeUrl := range typeUrls { - prettyName := testTypeUrlToPrettyName[typeUrl] - t.Run(fmt.Sprintf("xdsv2-%s", prettyName), func(t *testing.T) { - if typeUrl == xdscommon.SecretType { - t.Skip("skipping. secrets are not yet implemented in xdsv2") - } - items, ok := v2Resources[typeUrl] - require.True(t, ok) - - sort.Slice(items, resourceSortingFunc(items, typeUrl)) - - r, err := response.CreateResponse(typeUrl, "00000001", "00000001", items) - require.NoError(t, err) - - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - expectedJSON := goldenEnvoy(t, filepath.Join(prettyName, gName), envoyVersion, latestEnvoyVersion, gotJSON) - require.JSONEq(t, expectedJSON, gotJSON) - }) - } - } } tests := []testcase{ @@ -188,93 +149,170 @@ func TestAllResourcesFromSnapshot(t *testing.T) { create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshot(t, nil, nil) }, - alsoRunTestForV2: true, }, { - name: "connect-proxy-with-chain", + name: "telemetry-collector", + create: proxycfg.TestConfigSnapshotTelemetryCollector, + }, + { + name: "grpc-public-listener", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", false, nil, nil) + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "grpc" + }, nil) }, - alsoRunTestForV2: true, }, { - name: "connect-proxy-with-chain-external-sni", + name: "listener-bind-address", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "external-sni", false, nil, nil) + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["bind_address"] = "127.0.0.2" + }, nil) }, - alsoRunTestForV2: true, }, { - name: "connect-proxy-with-chain-and-failover", + name: "listener-bind-port", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover", false, nil, nil) + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["bind_port"] = 8888 + }, nil) }, - alsoRunTestForV2: true, }, { - name: "connect-proxy-exported-to-peers", + name: "listener-bind-address-port", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { - // This test is only concerned about the SPIFFE cert validator config in the public listener - // so we empty out the upstreams to avoid generating unnecessary upstream listeners. - ns.Proxy.Upstreams = structs.Upstreams{} - }, []proxycfg.UpdateEvent{ - { - CorrelationID: "peering-trust-bundles", - Result: proxycfg.TestPeerTrustBundles(t), - }, - }) + ns.Proxy.Config["bind_address"] = "127.0.0.2" + ns.Proxy.Config["bind_port"] = 8888 + }, nil) }, - alsoRunTestForV2: true, }, { - name: "transparent-proxy", + name: "listener-unix-domain-socket", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTransparentProxy(t) + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].LocalBindAddress = "" + ns.Proxy.Upstreams[0].LocalBindPort = 0 + ns.Proxy.Upstreams[0].LocalBindSocketPath = "/tmp/service-mesh/client-1/grpc-employee-server" + ns.Proxy.Upstreams[0].LocalBindSocketMode = "0640" + }, nil) }, - alsoRunTestForV2: true, }, { - name: "connect-proxy-with-peered-upstreams", - create: proxycfg.TestConfigSnapshotPeering, - // TODO(proxystate): peering will come at a later date. - alsoRunTestForV2: false, + name: "listener-max-inbound-connections", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["max_inbound_connections"] = 222 + }, nil) + }, }, { - name: "connect-proxy-with-peered-upstreams-escape-overrides", - create: proxycfg.TestConfigSnapshotPeeringWithEscapeOverrides, - // TODO(proxystate): peering will come at a later date. - alsoRunTestForV2: false, + name: "http2-public-listener", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "http2" + }, nil) + }, }, { - name: "connect-proxy-with-peered-upstreams-http2", - create: proxycfg.TestConfigSnapshotPeeringWithHTTP2, - // TODO(proxystate): peering will come at a later date. - alsoRunTestForV2: false, + name: "listener-balance-inbound-connections", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["balance_inbound_connections"] = "exact_balance" + }, nil) + }, }, { - name: "transparent-proxy-with-peered-upstreams", - create: proxycfg.TestConfigSnapshotPeeringTProxy, - // TODO(proxystate): peering will come at a later date. - alsoRunTestForV2: false, + name: "listener-balance-outbound-connections-bind-port", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].Config["balance_outbound_connections"] = "exact_balance" + }, nil) + }, }, { - name: "local-mesh-gateway-with-peered-upstreams", - create: proxycfg.TestConfigSnapshotPeeringLocalMeshGateway, - // TODO(proxystate): mesh gateways and peering will come at a later date. - alsoRunTestForV2: false, + name: "http-public-listener", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "http" + }, nil) + }, + }, + { + name: "http-public-listener-no-xfcc", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, + func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "http" + }, + []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + HTTP: &structs.MeshHTTPConfig{ + SanitizeXForwardedClientCert: true, + }, + }, + }, + }, + }) + }, + }, + { + name: "http-listener-with-timeouts", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "http" + ns.Proxy.Config["local_connect_timeout_ms"] = 1234 + ns.Proxy.Config["local_request_timeout_ms"] = 2345 + ns.Proxy.Config["local_idle_timeout_ms"] = 3456 + }, nil) + }, }, { - name: "telemetry-collector", - create: proxycfg.TestConfigSnapshotTelemetryCollector, - alsoRunTestForV2: false, + name: "http-upstream", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].Config["protocol"] = "http" + }, nil) + }, + }, + { + name: "connect-proxy-upstream-defaults", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + for _, v := range ns.Proxy.Upstreams { + // Prepared queries do not get centrally configured upstream defaults merged into them. + if v.DestinationType == structs.UpstreamDestTypePreparedQuery { + continue + } + // Represent upstream config as if it came from centrally configured upstream defaults. + // The name/namespace must not make it onto the cluster name attached to the outbound listener. + v.CentrallyConfigured = true + v.DestinationNamespace = structs.WildcardSpecifier + v.DestinationName = structs.WildcardSpecifier + } + }, nil) + }, }, } + tests = append(tests, getConnectProxyDiscoChainTests(false)...) tests = append(tests, getConnectProxyTransparentProxyGoldenTestCases()...) + tests = append(tests, getMeshGatewayGoldenTestCases()...) tests = append(tests, getMeshGatewayPeeringGoldenTestCases()...) tests = append(tests, getTrafficControlPeeringGoldenTestCases(false)...) tests = append(tests, getEnterpriseGoldenTestCases(t)...) tests = append(tests, getAPIGatewayGoldenTestCases(t)...) + tests = append(tests, getExposePathGoldenTestCases()...) + tests = append(tests, getCustomConfigurationGoldenTestCases(false)...) + tests = append(tests, getConnectProxyJWTProviderGoldenTestCases()...) + tests = append(tests, getTerminatingGatewayPeeringGoldenTestCases()...) + tests = append(tests, getIngressGatewayGoldenTestCases()...) + tests = append(tests, getAccessLogsGoldenTestCases()...) + tests = append(tests, getTLSGoldenTestCases()...) + tests = append(tests, getPeeredGoldenTestCases()...) + tests = append(tests, getXDSFetchTimeoutTestCases()...) latestEnvoyVersion := xdscommon.EnvoyVersions[0] for _, envoyVersion := range xdscommon.EnvoyVersions { @@ -292,120 +330,524 @@ func TestAllResourcesFromSnapshot(t *testing.T) { func getConnectProxyTransparentProxyGoldenTestCases() []goldenTestCase { return []goldenTestCase{ + { + name: "transparent-proxy", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotTransparentProxy(t) + }, + }, + { + name: "transparent-proxy-catalog-destinations-only", + create: proxycfg.TestConfigSnapshotTransparentProxyCatalogDestinationsOnly, + }, + { + name: "transparent-proxy-dial-instances-directly", + create: proxycfg.TestConfigSnapshotTransparentProxyDialDirectly, + }, + { + name: "transparent-proxy-http-upstream", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotTransparentProxyHTTPUpstream(t, nil) + }, + }, + { + name: "transparent-proxy-with-resolver-redirect-upstream", + create: proxycfg.TestConfigSnapshotTransparentProxyResolverRedirectUpstream, + }, + { + name: "transparent-proxy-terminating-gateway", + create: proxycfg.TestConfigSnapshotTransparentProxyTerminatingGatewayCatalogDestinationsOnly, + }, { name: "transparent-proxy-destination", create: proxycfg.TestConfigSnapshotTransparentProxyDestination, - // TODO(proxystate): currently failing. should work. possible issue in converter. - alsoRunTestForV2: false, }, { name: "transparent-proxy-destination-http", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotTransparentProxyDestinationHTTP(t, nil) }, - // TODO(proxystate): currently failing. should work. possible issue in converter. - alsoRunTestForV2: false, }, { name: "transparent-proxy-terminating-gateway-destinations-only", create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshotTerminatingGatewayDestinations(t, true, nil) }, - // TODO(proxystate): terminating gateways will come at a later date. - alsoRunTestForV2: false, }, } } -func getMeshGatewayPeeringGoldenTestCases() []goldenTestCase { - return []goldenTestCase{ +func getConnectProxyDiscoChainTests(enterprise bool) []goldenTestCase { + cases := []goldenTestCase{ { - name: "mesh-gateway-with-exported-peered-services", + name: "connect-proxy-with-chain", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "default-services-tcp", nil, nil) + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil) }, - // TODO(proxystate): mesh gateways will come at a later date. - alsoRunTestForV2: false, }, { - name: "mesh-gateway-with-exported-peered-services-http", + name: "connect-proxy-with-chain-external-sni", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "default-services-http", nil, nil) + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "external-sni", enterprise, nil, nil) }, - // TODO(proxystate): mesh gateways will come at a later date. - alsoRunTestForV2: false, }, { - name: "mesh-gateway-with-exported-peered-services-http-with-router", + name: "connect-proxy-with-chain-and-failover", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "chain-and-l7-stuff", nil, nil) + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover", enterprise, nil, nil) }, - // TODO(proxystate): mesh gateways will come at a later date. - alsoRunTestForV2: false, }, { - name: "mesh-gateway-peering-control-plane", + name: "connect-proxy-exported-to-peers", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "control-plane", nil, nil) + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + // This test is only concerned about the SPIFFE cert validator config in the public listener + // so we empty out the upstreams to avoid generating unnecessary upstream listeners. + ns.Proxy.Upstreams = structs.Upstreams{} + }, []proxycfg.UpdateEvent{ + { + CorrelationID: "peering-trust-bundles", + Result: proxycfg.TestPeerTrustBundles(t), + }, + }) }, - // TODO(proxystate): mesh gateways will come at a later date. - alsoRunTestForV2: false, }, { - name: "mesh-gateway-with-imported-peered-services", + name: "custom-upstream-default-chain", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "imported-services", func(ns *structs.NodeService) { - ns.Proxy.Config = map[string]interface{}{ - "envoy_dns_discovery_type": "STRICT_DNS", - } + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", enterprise, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].Config["envoy_cluster_json"] = customAppClusterJSON(t, customClusterJSONOptions{ + Name: "myservice", + }) }, nil) }, - // TODO(proxystate): mesh gateways will come at a later date. - alsoRunTestForV2: false, }, { - name: "mesh-gateway-with-peer-through-mesh-gateway-enabled", + name: "connect-proxy-with-chain-http2", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "peer-through-mesh-gateway", nil, nil) + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].Config["protocol"] = "http2" + }, nil) }, - // TODO(proxystate): mesh gateways will come at a later date. - alsoRunTestForV2: false, }, - } -} - -func getTrafficControlPeeringGoldenTestCases(enterprise bool) []goldenTestCase { - cases := []goldenTestCase{ { - name: "connect-proxy-with-chain-and-failover-to-cluster-peer", + name: "connect-proxy-with-chain-and-overrides", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-to-cluster-peer", enterprise, nil, nil) + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple-with-overrides", enterprise, nil, nil) }, - // TODO(proxystate): peering will come at a later date. - alsoRunTestForV2: false, }, { - name: "connect-proxy-with-chain-and-redirect-to-cluster-peer", + name: "connect-proxy-with-chain-and-failover", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "redirect-to-cluster-peer", enterprise, nil, nil) + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover", enterprise, nil, nil) }, - // TODO(proxystate): peering will come at a later date. - alsoRunTestForV2: false, }, - } - - if enterprise { - for i := range cases { - cases[i].name = "enterprise-" + cases[i].name - } - } + { + name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway-triggered", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway-triggered", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-tcp-chain-failover-through-local-gateway", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway-triggered", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway-triggered", enterprise, nil, nil) + }, + }, + { + name: "splitter-with-resolver-redirect", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-with-resolver-redirect-multidc", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-lb-in-resolver", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "lb-resolver", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-default-chain-and-custom-cluster", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", enterprise, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].Config["envoy_cluster_json"] = customAppClusterJSON(t, customClusterJSONOptions{ + Name: "myservice", + }) + }, nil) + }, + }, + { + name: "connect-proxy-splitter-overweight", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-overweight", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-chain-and-splitter", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "chain-and-splitter", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + cfgSnap := proxycfg.TestConfigSnapshotDiscoveryChain(t, "chain-and-splitter", enterprise, nil, nil) + cfgSnap.ConnectProxy.MeshConfig = &structs.MeshConfigEntry{ + ValidateClusters: true, + } + return cfgSnap + }, + }, + { + name: "connect-proxy-with-grpc-router", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "grpc-router", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-chain-and-router", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "chain-and-router", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-route-to-lb-resolver", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "redirect-to-lb-node", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-resolver-with-lb", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "resolver-with-lb", enterprise, nil, nil) + }, + }, + { + name: "custom-upstream-ignored-with-disco-chain", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover", enterprise, func(ns *structs.NodeService) { + for i := range ns.Proxy.Upstreams { + if ns.Proxy.Upstreams[i].DestinationName != "db" { + continue // only tweak the db upstream + } + if ns.Proxy.Upstreams[i].Config == nil { + ns.Proxy.Upstreams[i].Config = map[string]interface{}{} + } - return cases -} + uid := proxycfg.NewUpstreamID(&ns.Proxy.Upstreams[i]) -const ( - gatewayTestPrivateKey = `-----BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAx95Opa6t4lGEpiTUogEBptqOdam2ch4BHQGhNhX/MrDwwuZQ + ns.Proxy.Upstreams[i].Config["envoy_listener_json"] = customListenerJSON(t, customListenerJSONOptions{ + Name: uid.EnvoyID() + ":custom-upstream", + }) + } + }, nil) + }, + }, + { + name: "connect-proxy-with-tcp-chain", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-http-chain", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil, + &structs.ProxyConfigEntry{ + Kind: structs.ProxyDefaults, + Name: structs.ProxyConfigGlobal, + Protocol: "http", + Config: map[string]interface{}{ + "protocol": "http", + }, + }, + ) + }, + }, + { + name: "connect-proxy-with-http2-chain", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil, + &structs.ProxyConfigEntry{ + Kind: structs.ProxyDefaults, + Name: structs.ProxyConfigGlobal, + Protocol: "http2", + Config: map[string]interface{}{ + "protocol": "http2", + }, + }, + ) + }, + }, + { + name: "connect-proxy-with-grpc-chain", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", enterprise, nil, nil, + &structs.ProxyConfigEntry{ + Kind: structs.ProxyDefaults, + Name: structs.ProxyConfigGlobal, + Protocol: "grpc", + Config: map[string]interface{}{ + "protocol": "grpc", + }, + }, + ) + }, + }, + } + + if enterprise { + for i := range cases { + cases[i].name = "enterprise-" + cases[i].name + } + } + + return cases +} + +func getMeshGatewayGoldenTestCases() []goldenTestCase { + return []goldenTestCase{ + { + name: "mesh-gateway", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "default", nil, nil) + }, + }, + { + name: "mesh-gateway-with-limits", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "limits-added", nil, nil) + }, + }, + { + name: "mesh-gateway-using-federation-states", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "federation-states", nil, nil) + }, + }, + { + name: "mesh-gateway-using-federation-control-plane", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "mesh-gateway-federation", nil, nil) + }, + }, + { + name: "mesh-gateway-newer-information-in-federation-states", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "newer-info-in-federation-states", nil, nil) + }, + }, + { + name: "mesh-gateway-older-information-in-federation-states", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "older-info-in-federation-states", nil, nil) + }, + }, + { + name: "mesh-gateway-no-services", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "no-services", nil, nil) + }, + }, + { + name: "mesh-gateway-service-subsets", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "service-subsets", nil, nil) + }, + }, + { + name: "mesh-gateway-service-subsets2", // TODO: make this merge with 'service-subsets' + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "service-subsets2", nil, nil) + }, + }, + { + name: "mesh-gateway-default-service-subset", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "default-service-subsets2", nil, nil) + }, + }, + { + name: "mesh-gateway-ignore-extra-resolvers", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "ignore-extra-resolvers", nil, nil) + }, + }, + { + name: "mesh-gateway-service-timeouts", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "service-timeouts", nil, nil) + }, + }, + { + name: "mesh-gateway-non-hash-lb-injected", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "non-hash-lb-injected", nil, nil) + }, + }, + { + name: "mesh-gateway-hash-lb-ignored", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "hash-lb-ignored", nil, nil) + }, + }, + { + name: "mesh-gateway-tcp-keepalives", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "default", func(ns *structs.NodeService) { + ns.Proxy.Config["envoy_gateway_remote_tcp_enable_keepalive"] = true + ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_time"] = 120 + ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_interval"] = 60 + ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_probes"] = 7 + }, nil) + }, + }, + { + name: "mesh-gateway-tagged-addresses", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "default", func(ns *structs.NodeService) { + ns.Proxy.Config = map[string]interface{}{ + "envoy_mesh_gateway_no_default_bind": true, + "envoy_mesh_gateway_bind_tagged_addresses": true, + } + }, nil) + }, + }, + { + name: "mesh-gateway-custom-addresses", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotMeshGateway(t, "default", func(ns *structs.NodeService) { + ns.Proxy.Config = map[string]interface{}{ + "envoy_mesh_gateway_bind_addresses": map[string]structs.ServiceAddress{ + "foo": { + Address: "198.17.2.3", + Port: 8080, + }, + "bar": { + Address: "2001:db8::ff", + Port: 9999, + }, + "baz": { + Address: "127.0.0.1", + Port: 8765, + }, + }, + } + }, nil) + }, + }, + } +} + +func getMeshGatewayPeeringGoldenTestCases() []goldenTestCase { + return []goldenTestCase{ + { + name: "mesh-gateway-with-exported-peered-services", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "default-services-tcp", nil, nil) + }, + }, + { + name: "mesh-gateway-with-exported-peered-services-http", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "default-services-http", nil, nil) + }, + }, + { + name: "mesh-gateway-with-exported-peered-services-http-with-router", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "chain-and-l7-stuff", nil, nil) + }, + }, + { + name: "mesh-gateway-peering-control-plane", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "control-plane", nil, nil) + }, + }, + { + name: "mesh-gateway-with-imported-peered-services", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "imported-services", func(ns *structs.NodeService) { + ns.Proxy.Config = map[string]interface{}{ + "envoy_dns_discovery_type": "STRICT_DNS", + } + }, nil) + }, + }, + { + name: "mesh-gateway-with-peer-through-mesh-gateway-enabled", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "peer-through-mesh-gateway", nil, nil) + }, + }, + } +} + +func getTrafficControlPeeringGoldenTestCases(enterprise bool) []goldenTestCase { + cases := []goldenTestCase{ + { + name: "connect-proxy-with-chain-and-failover-to-cluster-peer", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-to-cluster-peer", enterprise, nil, nil) + }, + }, + { + name: "connect-proxy-with-chain-and-redirect-to-cluster-peer", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "redirect-to-cluster-peer", enterprise, nil, nil) + }, + }, + } + + if enterprise { + for i := range cases { + cases[i].name = "enterprise-" + cases[i].name + } + } + + return cases +} + +const ( + gatewayTestPrivateKey = `-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAx95Opa6t4lGEpiTUogEBptqOdam2ch4BHQGhNhX/MrDwwuZQ httBwMfngQ/wd9NmYEPAwj0dumUoAITIq6i2jQlhqTodElkbsd5vWY8R/bxJWQSo NvVE12TlzECxGpJEiHt4W0r8pGffk+rvpljiUyCfnT1kGF3znOSjK1hRMTn6RKWC yYaBvXQiB4SGilfLgJcEpOJKtISIxmZ+S409g9X5VU88/Bmmrz4cMyxce86Kc2ug @@ -557,8 +999,6 @@ func getAPIGatewayGoldenTestCases(t *testing.T) []goldenTestCase { Certificate: gatewayTestCertificate, }}, nil) }, - // TODO(proxystate): api gateways will come at a later date. - alsoRunTestForV2: false, }, { name: "api-gateway-with-multiple-inline-certificates", @@ -632,8 +1072,6 @@ func getAPIGatewayGoldenTestCases(t *testing.T) []goldenTestCase { }, }, nil) }, - // TODO(proxystate): api gateways will come at a later date. - alsoRunTestForV2: false, }, { name: "api-gateway-with-http-route", @@ -715,8 +1153,6 @@ func getAPIGatewayGoldenTestCases(t *testing.T) []goldenTestCase { }, }}) }, - // TODO(proxystate): api gateways will come at a later date. - alsoRunTestForV2: false, }, { name: "api-gateway-with-http-route-timeoutfilter-one-set", @@ -791,8 +1227,1734 @@ func getAPIGatewayGoldenTestCases(t *testing.T) []goldenTestCase { }, }}) }, - // TODO(proxystate): api gateways will come at a later date. - alsoRunTestForV2: false, + }, + { + name: "api-gateway", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, nil, nil, nil, nil) + }, + }, + { + name: "api-gateway-nil-config-entry", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotAPIGateway_NilConfigEntry(t) + }, + }, + { + name: "api-gateway-tcp-listener", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { + entry.Listeners = []structs.APIGatewayListener{ + { + Name: "listener", + Protocol: structs.ListenerProtocolTCP, + Port: 8080, + }, + } + bound.Listeners = []structs.BoundAPIGatewayListener{ + { + Name: "listener", + }, + } + }, nil, nil, nil) + }, + }, + { + name: "api-gateway-tcp-listener-with-tcp-route", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { + entry.Listeners = []structs.APIGatewayListener{ + { + Name: "listener", + Protocol: structs.ListenerProtocolTCP, + Port: 8080, + }, + } + bound.Listeners = []structs.BoundAPIGatewayListener{ + { + Name: "listener", + Routes: []structs.ResourceReference{ + { + Name: "tcp-route", + Kind: structs.TCPRoute, + }, + }, + }, + } + }, []structs.BoundRoute{ + &structs.TCPRouteConfigEntry{ + Name: "tcp-route", + Kind: structs.TCPRoute, + Parents: []structs.ResourceReference{ + { + Kind: structs.APIGateway, + Name: "api-gateway", + }, + }, + Services: []structs.TCPService{ + {Name: "tcp-service"}, + }, + }, + }, nil, nil) + }, + }, + { + name: "api-gateway-http-listener", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { + entry.Listeners = []structs.APIGatewayListener{ + { + Name: "listener", + Protocol: structs.ListenerProtocolHTTP, + Port: 8080, + }, + } + bound.Listeners = []structs.BoundAPIGatewayListener{ + { + Name: "listener", + Routes: []structs.ResourceReference{}, + }, + } + }, nil, nil, nil) + }, + }, + { + name: "api-gateway-http-listener-with-http-route", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { + entry.Listeners = []structs.APIGatewayListener{ + { + Name: "listener", + Protocol: structs.ListenerProtocolHTTP, + Port: 8080, + }, + } + bound.Listeners = []structs.BoundAPIGatewayListener{ + { + Name: "listener", + Routes: []structs.ResourceReference{ + { + Name: "http-route", + Kind: structs.HTTPRoute, + }, + }, + }, + } + }, []structs.BoundRoute{ + &structs.HTTPRouteConfigEntry{ + Name: "http-route", + Kind: structs.HTTPRoute, + Parents: []structs.ResourceReference{ + { + Kind: structs.APIGateway, + Name: "api-gateway", + }, + }, + Rules: []structs.HTTPRouteRule{ + { + Services: []structs.HTTPService{ + {Name: "http-service"}, + }, + }, + }, + }, + }, nil, nil) + }, + }, + { + name: "api-gateway-tcp-listener-with-tcp-and-http-route", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { + entry.Listeners = []structs.APIGatewayListener{ + { + Name: "listener-tcp", + Protocol: structs.ListenerProtocolTCP, + Port: 8080, + }, + { + Name: "listener-http", + Protocol: structs.ListenerProtocolHTTP, + Port: 8081, + }, + } + bound.Listeners = []structs.BoundAPIGatewayListener{ + { + Name: "listener-tcp", + Routes: []structs.ResourceReference{ + { + Name: "tcp-route", + Kind: structs.TCPRoute, + }, + }, + }, + { + Name: "listener-http", + Routes: []structs.ResourceReference{ + { + Name: "http-route", + Kind: structs.HTTPRoute, + }, + }, + }, + } + }, []structs.BoundRoute{ + &structs.TCPRouteConfigEntry{ + Name: "tcp-route", + Kind: structs.TCPRoute, + Parents: []structs.ResourceReference{ + { + Kind: structs.APIGateway, + Name: "api-gateway", + }, + }, + Services: []structs.TCPService{ + {Name: "tcp-service"}, + }, + }, + &structs.HTTPRouteConfigEntry{ + Name: "http-route", + Kind: structs.HTTPRoute, + Parents: []structs.ResourceReference{ + { + Kind: structs.APIGateway, + Name: "api-gateway", + }, + }, + Rules: []structs.HTTPRouteRule{ + { + Services: []structs.HTTPService{ + {Name: "http-service"}, + }, + }, + }, + }, + }, nil, nil) + }, + }, + { + name: "api-gateway-with-multiple-hostnames", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { + entry.Listeners = []structs.APIGatewayListener{ + { + Name: "http", + Protocol: structs.ListenerProtocolHTTP, + Port: 8080, + Hostname: "*.example.com", + }, + } + bound.Listeners = []structs.BoundAPIGatewayListener{ + { + Name: "http", + Routes: []structs.ResourceReference{ + {Kind: structs.HTTPRoute, Name: "backend-route"}, + {Kind: structs.HTTPRoute, Name: "frontend-route"}, + {Kind: structs.HTTPRoute, Name: "generic-route"}, + }, + }, + } + }, + []structs.BoundRoute{ + &structs.HTTPRouteConfigEntry{ + Kind: structs.HTTPRoute, + Name: "backend-route", + Hostnames: []string{"backend.example.com"}, + Parents: []structs.ResourceReference{{Kind: structs.APIGateway, Name: "api-gateway"}}, + Rules: []structs.HTTPRouteRule{ + {Services: []structs.HTTPService{{Name: "backend"}}}, + }, + }, + &structs.HTTPRouteConfigEntry{ + Kind: structs.HTTPRoute, + Name: "frontend-route", + Hostnames: []string{"frontend.example.com"}, + Parents: []structs.ResourceReference{{Kind: structs.APIGateway, Name: "api-gateway"}}, + Rules: []structs.HTTPRouteRule{ + {Services: []structs.HTTPService{{Name: "frontend"}}}, + }, + }, + &structs.HTTPRouteConfigEntry{ + Kind: structs.HTTPRoute, + Name: "generic-route", + Parents: []structs.ResourceReference{{Kind: structs.APIGateway, Name: "api-gateway"}}, + Rules: []structs.HTTPRouteRule{ + { + Matches: []structs.HTTPMatch{{Path: structs.HTTPPathMatch{Match: structs.HTTPPathMatchPrefix, Value: "/frontend"}}}, + Services: []structs.HTTPService{{Name: "frontend"}}, + }, + { + Matches: []structs.HTTPMatch{{Path: structs.HTTPPathMatch{Match: structs.HTTPPathMatchPrefix, Value: "/backend"}}}, + Services: []structs.HTTPService{{Name: "backend"}}, + }, + }, + }, + }, nil, nil) + }, + }, + } +} + +func getExposePathGoldenTestCases() []goldenTestCase { + return []goldenTestCase{ + { + name: "expose-paths-local-app-paths", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotExposeConfig(t, nil) + }, + }, + { + name: "downstream-service-with-unix-sockets", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Address = "" + ns.Port = 0 + ns.Proxy.LocalServiceAddress = "" + ns.Proxy.LocalServicePort = 0 + ns.Proxy.LocalServiceSocketPath = "/tmp/downstream_proxy.sock" + }, nil) + }, + }, + { + name: "expose-paths-new-cluster-http2", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotExposeConfig(t, func(ns *structs.NodeService) { + ns.Proxy.Expose.Paths[1] = structs.ExposePath{ + LocalPathPort: 9090, + Path: "/grpc.health.v1.Health/Check", + ListenerPort: 21501, + Protocol: "http2", + } + }) + }, + }, + { + name: "expose-checks", + create: proxycfg.TestConfigSnapshotExposeChecks, + generatorSetup: func(s *ResourceGenerator) { + s.CfgFetcher = configFetcherFunc(func() string { + return "192.0.2.1" + }) + }, + }, + { + name: "expose-paths-grpc-new-cluster-http1", + create: proxycfg.TestConfigSnapshotGRPCExposeHTTP1, + }, + { + // NOTE: if IPv6 is not supported in the kernel per + // platform.SupportsIPv6() then this test will fail because the golden + // files were generated assuming ipv6 support was present + name: "expose-checks-http", + create: proxycfg.TestConfigSnapshotExposeChecks, + generatorSetup: func(s *ResourceGenerator) { + s.CfgFetcher = configFetcherFunc(func() string { + return "192.0.2.1" + }) + }, + }, + { + // NOTE: if IPv6 is not supported in the kernel per + // platform.SupportsIPv6() then this test will fail because the golden + // files were generated assuming ipv6 support was present + name: "expose-checks-http-with-bind-override", + create: proxycfg.TestConfigSnapshotExposeChecksWithBindOverride, + generatorSetup: func(s *ResourceGenerator) { + s.CfgFetcher = configFetcherFunc(func() string { + return "192.0.2.1" + }) + }, + }, + { + // NOTE: if IPv6 is not supported in the kernel per + // platform.SupportsIPv6() then this test will fail because the golden + // files were generated assuming ipv6 support was present + name: "expose-checks-grpc", + create: proxycfg.TestConfigSnapshotExposeChecksGRPC, + generatorSetup: func(s *ResourceGenerator) { + s.CfgFetcher = configFetcherFunc(func() string { + return "192.0.2.1" + }) + }, + }, + } +} + +func getCustomConfigurationGoldenTestCases(enterprise bool) []goldenTestCase { + return []goldenTestCase{ + { + name: "custom-upstream-default-chain", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", enterprise, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].Config["envoy_cluster_json"] = customAppClusterJSON(t, customClusterJSONOptions{ + Name: "myservice", + }) + }, nil) + }, + }, + { + name: "custom-local-app", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["envoy_local_cluster_json"] = customAppClusterJSON(t, customClusterJSONOptions{ + Name: "mylocal", + }) + }, nil) + }, + }, + { + name: "custom-upstream", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].Config["envoy_cluster_json"] = customAppClusterJSON(t, customClusterJSONOptions{ + Name: "myservice", + }) + }, nil) + }, + }, + { + name: "custom-upstream-ignores-tls", + overrideGoldenName: "custom-upstream", // should be the same + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].Config["envoy_cluster_json"] = customAppClusterJSON(t, customClusterJSONOptions{ + Name: "myservice", + // Attempt to override the TLS context should be ignored + TLSContext: `"allowRenegotiation": false`, + }) + }, nil) + }, + }, + { + name: "custom-upstream-with-prepared-query", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + for i := range ns.Proxy.Upstreams { + switch ns.Proxy.Upstreams[i].DestinationName { + case "db": + if ns.Proxy.Upstreams[i].Config == nil { + ns.Proxy.Upstreams[i].Config = map[string]interface{}{} + } + + uid := proxycfg.NewUpstreamID(&ns.Proxy.Upstreams[i]) + + // Triggers an override with the presence of the escape hatch listener + ns.Proxy.Upstreams[i].DestinationType = structs.UpstreamDestTypePreparedQuery + + ns.Proxy.Upstreams[i].Config["envoy_cluster_json"] = customClusterJSON(t, customClusterJSONOptions{ + Name: uid.EnvoyID() + ":custom-upstream", + }) + + // Also test that http2 options are triggered. + // A separate upstream without an override is required to test + case "geo-cache": + if ns.Proxy.Upstreams[i].Config == nil { + ns.Proxy.Upstreams[i].Config = map[string]interface{}{} + } + ns.Proxy.Upstreams[i].Config["protocol"] = "http2" + default: + continue + } + } + }, nil) + }, + }, + { + name: "custom-timeouts", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["local_connect_timeout_ms"] = 1234 + ns.Proxy.Upstreams[0].Config["connect_timeout_ms"] = 2345 + }, nil) + }, + }, + { + name: "custom-passive-healthcheck", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].Config["passive_health_check"] = map[string]interface{}{ + "enforcing_consecutive_5xx": float64(80), + "max_failures": float64(5), + "interval": float64(10 * time.Second), + "max_ejection_percent": float64(100), + "base_ejection_time": float64(10 * time.Second), + } + }, nil) + }, + }, + { + name: "custom-passive-healthcheck-zero-consecutive_5xx", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].Config["passive_health_check"] = map[string]interface{}{ + "enforcing_consecutive_5xx": float64(0), + "max_failures": float64(5), + "interval": float64(10 * time.Second), + "max_ejection_percent": float64(100), + "base_ejection_time": float64(10 * time.Second), + } + }, nil) + }, + }, + { + name: "custom-max-inbound-connections", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["max_inbound_connections"] = 3456 + }, nil) + }, + }, + { + name: "custom-limits-max-connections-only", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + for i := range ns.Proxy.Upstreams { + // We check if Config is nil because the prepared_query upstream is + // initialized without a Config map. Use Upstreams[i] syntax to + // modify the actual ConfigSnapshot instead of copying the Upstream + // in the range. + if ns.Proxy.Upstreams[i].Config == nil { + ns.Proxy.Upstreams[i].Config = map[string]interface{}{} + } + + ns.Proxy.Upstreams[i].Config["limits"] = map[string]interface{}{ + "max_connections": 500, + } + } + }, nil) + }, + }, + { + name: "custom-limits-set-to-zero", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + for i := range ns.Proxy.Upstreams { + if ns.Proxy.Upstreams[i].Config == nil { + ns.Proxy.Upstreams[i].Config = map[string]interface{}{} + } + + ns.Proxy.Upstreams[i].Config["limits"] = map[string]interface{}{ + "max_connections": 0, + "max_pending_requests": 0, + "max_concurrent_requests": 0, + } + } + }, nil) + }, + }, + { + name: "custom-limits", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + for i := range ns.Proxy.Upstreams { + if ns.Proxy.Upstreams[i].Config == nil { + ns.Proxy.Upstreams[i].Config = map[string]interface{}{} + } + + ns.Proxy.Upstreams[i].Config["limits"] = map[string]interface{}{ + "max_connections": 500, + "max_pending_requests": 600, + "max_concurrent_requests": 700, + } + } + }, nil) + }, + }, + { + name: "connect-proxy-with-default-chain-and-custom-cluster", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", enterprise, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].Config["envoy_cluster_json"] = customAppClusterJSON(t, customClusterJSONOptions{ + Name: "myservice", + }) + }, nil) + }, + }, + { + name: "custom-public-listener", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["envoy_public_listener_json"] = customListenerJSON(t, customListenerJSONOptions{ + Name: "custom-public-listen", + }) + }, nil) + }, + }, + { + name: "custom-public-listener-http", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "http" + ns.Proxy.Config["envoy_public_listener_json"] = customHTTPListenerJSON(t, customHTTPListenerJSONOptions{ + Name: "custom-public-listen", + }) + }, nil) + }, + }, + { + name: "custom-public-listener-http-2", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "http" + ns.Proxy.Config["envoy_public_listener_json"] = customHTTPListenerJSON(t, customHTTPListenerJSONOptions{ + Name: "custom-public-listen", + HTTPConnectionManagerName: httpConnectionManagerNewName, + }) + }, nil) + }, + }, + { + name: "custom-public-listener-http-missing", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "http" + ns.Proxy.Config["envoy_public_listener_json"] = customListenerJSON(t, customListenerJSONOptions{ + Name: "custom-public-listen", + }) + }, nil) + }, + }, + { + name: "custom-public-listener-ignores-tls", + overrideGoldenName: "custom-public-listener", // should be the same + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["envoy_public_listener_json"] = customListenerJSON(t, customListenerJSONOptions{ + Name: "custom-public-listen", + // Attempt to override the TLS context should be ignored + TLSContext: `"allowRenegotiation": false`, + }) + }, nil) + }, + }, + { + name: "custom-trace-listener", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "http" + ns.Proxy.Config["envoy_listener_tracing_json"] = customTraceJSON(t) + }, nil) + }, + }, + { + // Same as below case, but keeps the recommended default value of InsecureDisablePathNormalization + // to show that the inverse value is reflected in xDS `normalize_path` config. + name: "connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + cfgSnap := proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + // Ensure public inbound listener has HTTP filter so normalization applies. + ns.Proxy.Config["protocol"] = "http" + // Ensure outbound HTTP listener has HTTP filter so we can observe normalization is not applied. + ns.Proxy.Upstreams[0].Config["protocol"] = "http" + }, nil) + cfgSnap.ConnectProxy.MeshConfig = &structs.MeshConfigEntry{ + HTTP: &structs.MeshHTTPConfig{ + Incoming: &structs.MeshDirectionalHTTPConfig{ + RequestNormalization: &structs.RequestNormalizationMeshConfig{ + InsecureDisablePathNormalization: false, + MergeSlashes: true, + PathWithEscapedSlashesAction: "UNESCAPE_AND_FORWARD", + HeadersWithUnderscoresAction: "REJECT_REQUEST", + }, + }, + }, + } + return cfgSnap + }, + }, + { + // Same as above case, but inverts the recommended default value of InsecureDisablePathNormalization + // to show that the value is respected when explicitly set (does not set `normalize_path`). + name: "connect-proxy-with-mesh-config-request-normalization-all-consul-options", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + cfgSnap := proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + // Ensure public inbound listener has HTTP filter so normalization applies. + ns.Proxy.Config["protocol"] = "http" + // Ensure outbound HTTP listener has HTTP filter so we can observe normalization is not applied. + ns.Proxy.Upstreams[0].Config["protocol"] = "http" + }, nil) + cfgSnap.ConnectProxy.MeshConfig = &structs.MeshConfigEntry{ + HTTP: &structs.MeshHTTPConfig{ + Incoming: &structs.MeshDirectionalHTTPConfig{ + RequestNormalization: &structs.RequestNormalizationMeshConfig{ + InsecureDisablePathNormalization: true, // note: this is the opposite of the recommended default + MergeSlashes: true, + PathWithEscapedSlashesAction: "UNESCAPE_AND_FORWARD", + HeadersWithUnderscoresAction: "REJECT_REQUEST", + }, + }, + }, + } + return cfgSnap + }, + }, + } +} + +func getConnectProxyJWTProviderGoldenTestCases() []goldenTestCase { + return []goldenTestCase{ + { + name: "connect-proxy-with-jwt-config-entry-with-local", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "jwt-provider", + Result: &structs.IndexedConfigEntries{ + Kind: "jwt-provider", + Entries: []structs.ConfigEntry{ + &structs.JWTProviderConfigEntry{ + Name: "okta", + JSONWebKeySet: &structs.JSONWebKeySet{ + Local: &structs.LocalJWKS{ + JWKS: "xxx", + }, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "connect-proxy-with-jwt-config-entry-with-remote-jwks", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "jwt-provider", + Result: &structs.IndexedConfigEntries{ + Kind: "jwt-provider", + Entries: []structs.ConfigEntry{ + &structs.JWTProviderConfigEntry{ + Name: "okta", + JSONWebKeySet: &structs.JSONWebKeySet{ + Remote: &structs.RemoteJWKS{ + RequestTimeoutMs: 1000, + FetchAsynchronously: true, + URI: "https://test.test.com", + JWKSCluster: &structs.JWKSCluster{ + DiscoveryType: structs.DiscoveryTypeStatic, + ConnectTimeout: time.Duration(5) * time.Second, + TLSCertificates: &structs.JWKSTLSCertificate{ + TrustedCA: &structs.JWKSTLSCertTrustedCA{ + Filename: "mycert.crt", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }) + }, + }, + } +} + +func getTerminatingGatewayPeeringGoldenTestCases() []goldenTestCase { + return []goldenTestCase{ + { + name: "terminating-gateway", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, nil) + }, + }, + { + name: "terminating-gateway-no-services", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotTerminatingGateway(t, false, nil, nil) + }, + }, + { + name: "terminating-gateway-service-subsets", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotTerminatingGatewayServiceSubsetsWebAndCache(t, nil) + }, + }, + { + name: "terminating-gateway-hostname-service-subsets", + create: proxycfg.TestConfigSnapshotTerminatingGatewayHostnameSubsets, + }, + { + name: "terminating-gateway-sni", + create: proxycfg.TestConfigSnapshotTerminatingGatewaySNI, + }, + { + name: "terminating-gateway-http2-upstream", + create: proxycfg.TestConfigSnapshotTerminatingGatewayHTTP2, + }, + { + name: "terminating-gateway-http2-upstream-subsets", + create: proxycfg.TestConfigSnapshotTerminatingGatewaySubsetsHTTP2, + }, + { + name: "terminating-gateway-ignore-extra-resolvers", + create: proxycfg.TestConfigSnapshotTerminatingGatewayIgnoreExtraResolvers, + }, + { + name: "terminating-gateway-lb-config", + create: proxycfg.TestConfigSnapshotTerminatingGatewayLBConfig, + }, + { + name: "terminating-gateway-lb-config-no-hash-policies", + create: proxycfg.TestConfigSnapshotTerminatingGatewayLBConfigNoHashPolicies, + }, + { + name: "terminating-gateway-tcp-keepalives", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, func(ns *structs.NodeService) { + if ns.Proxy.Config == nil { + ns.Proxy.Config = map[string]interface{}{} + } + ns.Proxy.Config["envoy_gateway_remote_tcp_enable_keepalive"] = true + ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_time"] = 133 + ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_interval"] = 27 + ns.Proxy.Config["envoy_gateway_remote_tcp_keepalive_probes"] = 5 + }, nil) + }, + }, + { + name: "terminating-gateway-custom-trace-listener", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, func(ns *structs.NodeService) { + ns.Proxy.Config = map[string]interface{}{} + ns.Proxy.Config["protocol"] = "http" + ns.Proxy.Config["envoy_listener_tracing_json"] = customTraceJSON(t) + }, nil) + }, + }, + { + name: "terminating-gateway-with-tls-incoming-min-version", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Incoming: &structs.MeshDirectionalTLSConfig{ + TLSMinVersion: types.TLSv1_3, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "terminating-gateway-with-tls-incoming-max-version", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Incoming: &structs.MeshDirectionalTLSConfig{ + TLSMaxVersion: types.TLSv1_2, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "terminating-gateway-with-tls-incoming-cipher-suites", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Incoming: &structs.MeshDirectionalTLSConfig{ + CipherSuites: []types.TLSCipherSuite{ + types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + }, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "terminating-gateway-custom-and-tagged-addresses", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, func(ns *structs.NodeService) { + ns.Proxy.Config = map[string]interface{}{ + "envoy_gateway_no_default_bind": true, + "envoy_gateway_bind_tagged_addresses": true, + "envoy_gateway_bind_addresses": map[string]structs.ServiceAddress{ + // This bind address should not get a listener due to deduplication and it sorts to the end + "z-duplicate-of-tagged-wan-addr": { + Address: "198.18.0.1", + Port: 443, + }, + "foo": { + Address: "198.17.2.3", + Port: 8080, + }, + }, + } + }, nil) + }, + }, + { + name: "terminating-gateway-no-api-cert", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + api := structs.NewServiceName("api", nil) + return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "service-leaf:" + api.String(), // serviceLeafIDPrefix + Result: nil, // tombstone this + }, + }) + }, + }, + { + name: "terminating-gateway-with-peer-trust-bundle", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + bundles := proxycfg.TestPeerTrustBundles(t) + return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "peer-trust-bundle:web", + Result: bundles, + }, + { + CorrelationID: "service-intentions:web", + Result: structs.SimplifiedIntentions{ + { + SourceName: "source", + SourcePeer: bundles.Bundles[0].PeerName, + DestinationName: "web", + DestinationPartition: "default", + Action: structs.IntentionActionAllow, + }, + { + SourceName: "source", + SourcePeer: bundles.Bundles[1].PeerName, + DestinationName: "web", + DestinationPartition: "default", + Action: structs.IntentionActionAllow, + }, + }, + }, + }) + }, + }, + { + name: "terminating-gateway-default-service-subset", + create: proxycfg.TestConfigSnapshotTerminatingGatewayDefaultServiceSubset, + }, + } +} + +func getIngressGatewayGoldenTestCases() []goldenTestCase { + return []goldenTestCase{ + { + name: "ingress-gateway", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "default", nil, nil, nil) + }, + }, + { + name: "ingress-gateway-nil-config-entry", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway_NilConfigEntry(t) + }, + }, + { + name: "ingress-gateway-with-tls-outgoing-min-version", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Outgoing: &structs.MeshDirectionalTLSConfig{ + TLSMinVersion: types.TLSv1_3, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "ingress-gateway-with-tls-outgoing-max-version", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Outgoing: &structs.MeshDirectionalTLSConfig{ + TLSMaxVersion: types.TLSv1_2, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "ingress-gateway-with-tls-outgoing-cipher-suites", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Outgoing: &structs.MeshDirectionalTLSConfig{ + CipherSuites: []types.TLSCipherSuite{ + types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + }, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "ingress-gateway-no-services", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, false, "tcp", + "default", nil, nil, nil) + }, + }, + { + name: "ingress-with-chain", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "simple", nil, nil, nil) + }, + }, + { + name: "ingress-with-service-max-connections", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "simple", nil, + func(entry *structs.IngressGatewayConfigEntry) { + entry.Listeners[0].Services[0].MaxConnections = 4096 + }, nil) + }, + }, + { + name: "ingress-with-defaults-service-max-connections", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "simple", nil, + func(entry *structs.IngressGatewayConfigEntry) { + entry.Defaults = &structs.IngressServiceConfig{ + MaxConnections: 2048, + MaxPendingRequests: 512, + MaxConcurrentRequests: 4096, + } + }, nil) + }, + }, + { + name: "ingress-with-overwrite-defaults-service-max-connections", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "simple", nil, + func(entry *structs.IngressGatewayConfigEntry) { + entry.Defaults = &structs.IngressServiceConfig{ + MaxConnections: 2048, + MaxPendingRequests: 512, + } + entry.Listeners[0].Services[0].MaxConnections = 4096 + entry.Listeners[0].Services[0].MaxPendingRequests = 2048 + }, nil) + }, + }, + { + name: "ingress-with-service-passive-health-check", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "simple", nil, + func(entry *structs.IngressGatewayConfigEntry) { + entry.Listeners[0].Services[0].MaxConnections = 4096 + entry.Listeners[0].Services[0].PassiveHealthCheck = &structs.PassiveHealthCheck{ + Interval: 5000000000, + MaxFailures: 10, + MaxEjectionPercent: uint32ptr(90), + } + }, nil) + }, + }, + { + name: "ingress-with-defaults-passive-health-check", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "simple", nil, + func(entry *structs.IngressGatewayConfigEntry) { + enforcingConsecutive5xx := uint32(80) + entry.Defaults = &structs.IngressServiceConfig{ + MaxConnections: 2048, + MaxPendingRequests: 512, + MaxConcurrentRequests: 4096, + PassiveHealthCheck: &structs.PassiveHealthCheck{ + Interval: 5000000000, + MaxFailures: 10, + EnforcingConsecutive5xx: &enforcingConsecutive5xx, + MaxEjectionPercent: uint32ptr(90), + }, + } + }, nil) + }, + }, + { + name: "ingress-with-overwrite-defaults-passive-health-check", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "simple", nil, + func(entry *structs.IngressGatewayConfigEntry) { + defaultEnforcingConsecutive5xx := uint32(80) + entry.Defaults = &structs.IngressServiceConfig{ + MaxConnections: 2048, + MaxPendingRequests: 512, + PassiveHealthCheck: &structs.PassiveHealthCheck{ + Interval: 5000000000, + EnforcingConsecutive5xx: &defaultEnforcingConsecutive5xx, + MaxEjectionPercent: uint32ptr(80), + }, + } + enforcingConsecutive5xx := uint32(50) + entry.Listeners[0].Services[0].MaxConnections = 4096 + entry.Listeners[0].Services[0].MaxPendingRequests = 2048 + entry.Listeners[0].Services[0].PassiveHealthCheck = &structs.PassiveHealthCheck{ + Interval: 8000000000, + EnforcingConsecutive5xx: &enforcingConsecutive5xx, + MaxEjectionPercent: uint32ptr(90), + BaseEjectionTime: durationPtr(12 * time.Second), + } + }, nil) + }, + }, + { + name: "ingress-with-chain-external-sni", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "external-sni", nil, nil, nil) + }, + }, + { + name: "ingress-with-chain-and-failover", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "failover", nil, nil, nil) + }, + }, + { + name: "ingress-with-chain-and-failover-to-cluster-peer", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "failover-to-cluster-peer", nil, nil, nil) + }, + }, + { + name: "ingress-with-tcp-chain-failover-through-remote-gateway", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "failover-through-remote-gateway", nil, nil, nil) + }, + }, + { + name: "ingress-with-tcp-chain-failover-through-remote-gateway-triggered", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "failover-through-remote-gateway-triggered", nil, nil, nil) + }, + }, + { + name: "ingress-with-tcp-chain-double-failover-through-remote-gateway", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "failover-through-double-remote-gateway", nil, nil, nil) + }, + }, + { + name: "ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "failover-through-double-remote-gateway-triggered", nil, nil, nil) + }, + }, + { + name: "ingress-with-tcp-chain-failover-through-local-gateway", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "failover-through-local-gateway", nil, nil, nil) + }, + }, + { + name: "ingress-with-tcp-chain-failover-through-local-gateway-triggered", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "failover-through-local-gateway-triggered", nil, nil, nil) + }, + }, + { + name: "ingress-with-tcp-chain-double-failover-through-local-gateway", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "failover-through-double-local-gateway", nil, nil, nil) + }, + }, + { + name: "ingress-with-tcp-chain-double-failover-through-local-gateway-triggered", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", + "failover-through-double-local-gateway-triggered", nil, nil, nil) + }, + }, + { + name: "ingress-splitter-with-resolver-redirect", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", + "splitter-with-resolver-redirect-multidc", nil, nil, nil) + }, + }, + { + name: "ingress-lb-in-resolver", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", + "lb-resolver", nil, nil, nil) + }, + }, + { + name: "ingress-multiple-listeners-duplicate-service", + create: proxycfg.TestConfigSnapshotIngress_MultipleListenersDuplicateService, + }, + { + name: "ingress-config-entry-nil", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway_NilConfigEntry(t) + }, + }, + { + name: "ingress-defaults-no-chain", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, false, "tcp", + "default", nil, nil, nil) + }, + }, + { + name: "ingress-with-chain-and-splitter", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", + "chain-and-splitter", nil, nil, nil) + }, + }, + { + name: "ingress-with-grpc-router", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", + "grpc-router", nil, nil, nil) + }, + }, + { + name: "ingress-with-chain-and-router", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", + "chain-and-router", nil, nil, nil) + }, + }, + { + name: "ingress-http-multiple-services", + create: proxycfg.TestConfigSnapshotIngress_HTTPMultipleServices, + }, + { + name: "ingress-grpc-multiple-services", + create: proxycfg.TestConfigSnapshotIngress_GRPCMultipleServices, + }, + { + name: "ingress-with-chain-and-router-header-manip", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "router-header-manip", nil, nil) + }, + }, + { + name: "ingress-with-sds-listener-level", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-listener-level", nil, nil) + }, + }, + { + name: "ingress-with-sds-listener-level-wildcard", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-listener-level-wildcard", nil, nil) + }, + }, + { + name: "ingress-with-tls-listener", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, + func(entry *structs.IngressGatewayConfigEntry) { + entry.TLS.Enabled = true + }, nil) + }, + }, + { + name: "ingress-with-tls-listener-min-version", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, + func(entry *structs.IngressGatewayConfigEntry) { + entry.TLS.Enabled = true + entry.TLS.TLSMinVersion = types.TLSv1_3 + }, nil) + }, + }, + { + name: "ingress-with-tls-listener-max-version", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, + func(entry *structs.IngressGatewayConfigEntry) { + entry.TLS.Enabled = true + entry.TLS.TLSMaxVersion = types.TLSv1_2 + }, nil) + }, + }, + { + name: "ingress-with-tls-listener-cipher-suites", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, + func(entry *structs.IngressGatewayConfigEntry) { + entry.TLS.Enabled = true + entry.TLS.CipherSuites = []types.TLSCipherSuite{ + types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + } + }, nil) + }, + }, + { + name: "ingress-with-tls-mixed-listeners", + create: proxycfg.TestConfigSnapshotIngressGateway_MixedListeners, + }, + { + name: "ingress-with-tls-min-version-listeners-gateway-defaults", + create: proxycfg.TestConfigSnapshotIngressGateway_TLSMinVersionListenersGatewayDefaults, + }, + { + name: "ingress-with-single-tls-listener", + create: proxycfg.TestConfigSnapshotIngressGateway_SingleTLSListener, + }, + { + name: "ingress-with-tls-mixed-min-version-listeners", + create: proxycfg.TestConfigSnapshotIngressGateway_TLSMixedMinVersionListeners, + }, + { + name: "ingress-with-tls-mixed-max-version-listeners", + create: proxycfg.TestConfigSnapshotIngressGateway_TLSMixedMaxVersionListeners, + }, + { + name: "ingress-with-tls-mixed-cipher-suites-listeners", + create: proxycfg.TestConfigSnapshotIngressGateway_TLSMixedCipherVersionListeners, + }, + { + name: "ingress-with-sds-listener-gw-level", + create: proxycfg.TestConfigSnapshotIngressGatewaySDS_GatewayLevel, + }, + { + name: "ingress-with-sds-listener-listener-level", + create: proxycfg.TestConfigSnapshotIngressGatewaySDS_GatewayAndListenerLevel, + }, + { + name: "ingress-with-sds-listener-gw-level-http", + create: proxycfg.TestConfigSnapshotIngressGatewaySDS_GatewayAndListenerLevel_HTTP, + }, + { + name: "ingress-with-sds-listener-gw-level-mixed-tls", + create: proxycfg.TestConfigSnapshotIngressGatewaySDS_GatewayLevel_MixedTLS, + }, + // TODO: cross reference with ingress-with-sds-service-level and figure out which should stay + { + name: "ingress-with-sds-service-level-2", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-service-level", nil, nil) + }, + }, + { + name: "ingress-with-sds-service-level-mixed-tls", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-service-level-mixed-tls", nil, nil) + }, + }, + { + name: "ingress-with-sds-service-level", + create: proxycfg.TestConfigSnapshotIngressGatewaySDS_ServiceLevel, + }, + { + name: "ingress-with-sds-listener+service-level", + create: proxycfg.TestConfigSnapshotIngressGatewaySDS_ListenerAndServiceLevel, + }, + { + name: "ingress-with-sds-service-level-mixed-no-tls", + create: proxycfg.TestConfigSnapshotIngressGatewaySDS_MixedNoTLS, + }, + { + name: "ingress-with-grpc-single-tls-listener", + create: proxycfg.TestConfigSnapshotIngressGateway_SingleTLSListener_GRPC, + }, + { + name: "ingress-with-http2-single-tls-listener", + create: proxycfg.TestConfigSnapshotIngressGateway_SingleTLSListener_HTTP2, + }, + { + name: "ingress-with-http2-and-grpc-multiple-tls-listener", + create: proxycfg.TestConfigSnapshotIngressGateway_GWTLSListener_MixedHTTP2gRPC, + }, + { + name: "ingress-gateway-bind-addrs", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", func(ns *structs.NodeService) { + // + ns.TaggedAddresses = map[string]structs.ServiceAddress{ + "lan": {Address: "10.0.0.1"}, + "wan": {Address: "172.16.0.1"}, + } + ns.Proxy.Config = map[string]interface{}{ + "envoy_gateway_no_default_bind": true, + "envoy_gateway_bind_tagged_addresses": true, + "envoy_gateway_bind_addresses": map[string]structs.ServiceAddress{ + "foo": {Address: "8.8.8.8"}, + }, + } + }, nil, nil) + }, + }, + } +} + +func getAccessLogsGoldenTestCases() []goldenTestCase { + return []goldenTestCase{ + { + name: "access-logs-defaults", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + // This should be passed into the snapshot through proxy-defaults + ns.Proxy.AccessLogs = structs.AccessLogsConfig{ + Enabled: true, + } + }, + nil) + }, + }, + { + name: "access-logs-json-file", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + // This should be passed into the snapshot through proxy-defaults + ns.Proxy.AccessLogs = structs.AccessLogsConfig{ + Enabled: true, + Type: structs.FileLogSinkType, + Path: "/tmp/accesslog.txt", + JSONFormat: "{ \"custom_start_time\": \"%START_TIME%\" }", + } + }, + nil) + }, + }, + { + name: "access-logs-text-stderr-disablelistenerlogs", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + // This should be passed into the snapshot through proxy-defaults + ns.Proxy.AccessLogs = structs.AccessLogsConfig{ + Enabled: true, + DisableListenerLogs: true, + Type: structs.StdErrLogSinkType, + TextFormat: "CUSTOM FORMAT %START_TIME%", + } + }, + nil) + }, + }, + } +} + +func getTLSGoldenTestCases() []goldenTestCase { + return []goldenTestCase{ + { + name: "connect-proxy-with-tls-outgoing-min-version-auto", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Outgoing: &structs.MeshDirectionalTLSConfig{ + TLSMinVersion: types.TLSVersionAuto, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "connect-proxy-with-tls-outgoing-min-version", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Outgoing: &structs.MeshDirectionalTLSConfig{ + TLSMinVersion: types.TLSv1_3, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "connect-proxy-with-tls-outgoing-max-version", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Outgoing: &structs.MeshDirectionalTLSConfig{ + TLSMaxVersion: types.TLSv1_2, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "connect-proxy-with-tls-outgoing-cipher-suites", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Outgoing: &structs.MeshDirectionalTLSConfig{ + CipherSuites: []types.TLSCipherSuite{ + types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + }, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "connect-proxy-with-tls-incoming-min-version", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Incoming: &structs.MeshDirectionalTLSConfig{ + TLSMinVersion: types.TLSv1_3, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "connect-proxy-with-tls-incoming-max-version", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Incoming: &structs.MeshDirectionalTLSConfig{ + TLSMaxVersion: types.TLSv1_2, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "connect-proxy-with-tls-incoming-cipher-suites", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, nil, []proxycfg.UpdateEvent{ + { + CorrelationID: "mesh", + Result: &structs.ConfigEntryResponse{ + Entry: &structs.MeshConfigEntry{ + TLS: &structs.MeshTLSConfig{ + Incoming: &structs.MeshDirectionalTLSConfig{ + CipherSuites: []types.TLSCipherSuite{ + types.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + types.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + }, + }, + }, + }, + }, + }, + }) + }, + }, + { + name: "connect-proxy-with-tproxy-and-permissive-mtls", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.MutualTLSMode = structs.MutualTLSModePermissive + ns.Proxy.Mode = structs.ProxyModeTransparent + ns.Proxy.TransparentProxy.OutboundListenerPort = 1234 + }, + nil) + }, + }, + { + name: "connect-proxy-without-tproxy-and-permissive-mtls", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.MutualTLSMode = structs.MutualTLSModePermissive + }, + nil) + }, + }, + } +} + +func getPeeredGoldenTestCases() []goldenTestCase { + return []goldenTestCase{ + { + name: "connect-proxy-with-peered-upstreams", + create: proxycfg.TestConfigSnapshotPeering, + }, + { + name: "connect-proxy-with-peered-upstreams-escape-overrides", + create: proxycfg.TestConfigSnapshotPeeringWithEscapeOverrides, + }, + { + name: "connect-proxy-with-peered-upstreams-http2", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotPeeringWithHTTP2(t, nil) + }, + }, + { + name: "transparent-proxy-with-peered-upstreams", + create: proxycfg.TestConfigSnapshotPeeringTProxy, + }, + { + name: "local-mesh-gateway-with-peered-upstreams", + create: proxycfg.TestConfigSnapshotPeeringLocalMeshGateway, + }, + } +} + +func getXDSFetchTimeoutTestCases() []goldenTestCase { + return []goldenTestCase{ + { + name: "xds-fetch-timeout-ms-sidecar", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + // Covers cases in: + // - clusters.go:makeUpstreamClustersForDiscoveryChain + // - clusters.go:makeUpstreamClusterForPreparedQuery + // - listeners.go:listenersFromSnapshotConnectProxy (partially) + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "chain-and-router", false, func(ns *structs.NodeService) { + ns.Proxy.Config["xds_fetch_timeout_ms"] = 9999 + }, nil) + }, + }, + { + name: "xds-fetch-timeout-ms-tproxy-http-peering", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + // Covers cases in: + // - clusters.go:makeUpstreamClusterForPeerService + snap := proxycfg.TestConfigSnapshotPeeringWithHTTP2(t, func(ns *structs.NodeService) { + ns.Proxy.Config["xds_fetch_timeout_ms"] = 9999 + }) + return snap + }, + }, + { + name: "xds-fetch-timeout-ms-tproxy-passthrough", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + // Covers cases in: + // - clusters.go:makePassthrough + // - listeners.go:listenersFromSnapshotConnectProxy (partially) + return proxycfg.TestConfigSnapshotTransparentProxyDestinationHTTP(t, func(ns *structs.NodeService) { + ns.Proxy.Config = map[string]interface{}{ + "xds_fetch_timeout_ms": 9999, + } + }) + }, + }, + { + name: "xds-fetch-timeout-ms-term-gw", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + // Covers cases in: + // - listeners.go:makeFilterChainTerminatingGateway + // - clusters.go:makeGatewayCluster + return proxycfg.TestConfigSnapshotTerminatingGatewayServiceSubsetsWebAndCache(t, func(ns *structs.NodeService) { + ns.Proxy.Config = map[string]interface{}{ + "xds_fetch_timeout_ms": 9999, + } + }) + }, + }, + { + name: "xds-fetch-timeout-ms-mgw-peering", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + // Covers cases in: + // - listeners.go:makeMeshGatewayPeerFilterChain + // - clusters.go:makeGatewayCluster + return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "default-services-http", func(ns *structs.NodeService) { + ns.Proxy.Config["xds_fetch_timeout_ms"] = 9999 + }, nil) + }, + }, + { + name: "xds-fetch-timeout-ms-ingress-with-router", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + // Covers cases in: + // - listeners.go:makeIngressGatewayListeners (partially) + return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", "chain-and-router", func(ns *structs.NodeService) { + ns.Proxy.Config = map[string]interface{}{ + "xds_fetch_timeout_ms": 9999, + } + }, nil, nil) + }, }, } } diff --git a/agent/xds/response/response.go b/agent/xds/response/response.go index 91ce6d739738..5b5d8de364df 100644 --- a/agent/xds/response/response.go +++ b/agent/xds/response/response.go @@ -53,16 +53,19 @@ func MakePipeAddress(path string, mode uint32) *envoy_core_v3.Address { } func MakeAddress(ip string, port int) *envoy_core_v3.Address { - return &envoy_core_v3.Address{ - Address: &envoy_core_v3.Address_SocketAddress{ - SocketAddress: &envoy_core_v3.SocketAddress{ - Address: ip, - PortSpecifier: &envoy_core_v3.SocketAddress_PortValue{ - PortValue: uint32(port), + if port >= 0 && port <= 65535 { + return &envoy_core_v3.Address{ + Address: &envoy_core_v3.Address_SocketAddress{ + SocketAddress: &envoy_core_v3.SocketAddress{ + Address: ip, + PortSpecifier: &envoy_core_v3.SocketAddress_PortValue{ + PortValue: uint32(port), + }, }, }, - }, + } } + return nil } func MakeUint32Value(n int) *wrapperspb.UInt32Value { @@ -75,9 +78,6 @@ func MakeBoolValue(n bool) *wrapperspb.BoolValue { func MakeEnvoyRegexMatch(patt string) *envoy_matcher_v3.RegexMatcher { return &envoy_matcher_v3.RegexMatcher{ - EngineType: &envoy_matcher_v3.RegexMatcher_GoogleRe2{ - GoogleRe2: &envoy_matcher_v3.RegexMatcher_GoogleRE2{}, - }, Regex: patt, } } diff --git a/agent/xds/routes.go b/agent/xds/routes.go index d4e289e03378..a2ad845eb32c 100644 --- a/agent/xds/routes.go +++ b/agent/xds/routes.go @@ -17,16 +17,15 @@ import ( "golang.org/x/exp/maps" "golang.org/x/exp/slices" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" - "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/discoverychain" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/config" "github.com/hashicorp/consul/agent/xds/response" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/wrapperspb" ) // routesFromSnapshot returns the xDS API representation of the "routes" in the @@ -52,10 +51,19 @@ func (s *ResourceGenerator) routesFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot) } } +func meshValidateClusters(cfgSnap *proxycfg.ConfigSnapshot) bool { + validate := false + if mesh := cfgSnap.MeshConfig(); mesh != nil { + validate = mesh.ValidateClusters + } + return validate +} + // routesFromSnapshotConnectProxy returns the xDS API representation of the // "routes" in the snapshot. func (s *ResourceGenerator) routesForConnectProxy(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) { var resources []proto.Message + validateClusters := meshValidateClusters(cfgSnap) for uid, chain := range cfgSnap.ConnectProxy.DiscoveryChain { if chain.Default { continue @@ -77,10 +85,9 @@ func (s *ResourceGenerator) routesForConnectProxy(cfgSnap *proxycfg.ConfigSnapsh route := &envoy_route_v3.RouteConfiguration{ Name: uid.EnvoyID(), VirtualHosts: []*envoy_route_v3.VirtualHost{virtualHost}, - // ValidateClusters defaults to true when defined statically and false - // when done via RDS. Re-set the reasonable value of true to prevent - // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), + } + if validateClusters { + route.ValidateClusters = response.MakeBoolValue(true) } resources = append(resources, route) } @@ -113,7 +120,7 @@ func (s *ResourceGenerator) routesForConnectProxy(cfgSnap *proxycfg.ConfigSnapsh } for routeName, clusters := range addressesMap { - routes, err := s.makeRoutesForAddresses(routeName, clusters) + routes, err := s.makeRoutesForAddresses(routeName, clusters, validateClusters) if err != nil { return nil, err } @@ -126,10 +133,10 @@ func (s *ResourceGenerator) routesForConnectProxy(cfgSnap *proxycfg.ConfigSnapsh return resources, nil } -func (s *ResourceGenerator) makeRoutesForAddresses(routeName string, addresses map[string]string) ([]proto.Message, error) { +func (s *ResourceGenerator) makeRoutesForAddresses(routeName string, addresses map[string]string, validateClusters bool) ([]proto.Message, error) { var resources []proto.Message - route, err := makeNamedAddressesRoute(routeName, addresses) + route, err := makeNamedAddressesRoute(routeName, addresses, validateClusters) if err != nil { s.Logger.Error("failed to make route", "cluster", "error", err) return nil, err @@ -159,11 +166,13 @@ func (s *ResourceGenerator) routesForTerminatingGateway(cfgSnap *proxycfg.Config "error", err, ) } + service := cfgSnap.TerminatingGateway.GatewayServices[svc] + autoHostRewrite := service.AutoHostRewrite if !structs.IsProtocolHTTPLike(cfg.Protocol) { // Routes can only be defined for HTTP services continue } - routes, err := s.makeRoutes(cfgSnap, svc, clusterName, true) + routes, err := s.makeRoutes(cfgSnap, svc, clusterName, autoHostRewrite) if err != nil { return nil, err } @@ -222,7 +231,8 @@ func (s *ResourceGenerator) makeRoutes( if resolver.LoadBalancer != nil { lb = resolver.LoadBalancer } - route, err := makeNamedDefaultRouteWithLB(clusterName, lb, resolver.RequestTimeout, autoHostRewrite) + validateClusters := meshValidateClusters(cfgSnap) + route, err := makeNamedDefaultRouteWithLB(clusterName, lb, resolver.RequestTimeout, autoHostRewrite, validateClusters) if err != nil { s.Logger.Error("failed to make route", "cluster", clusterName, "error", err) return nil, err @@ -232,7 +242,7 @@ func (s *ResourceGenerator) makeRoutes( // If there is a service-resolver for this service then also setup routes for each subset for name := range resolver.Subsets { clusterName = connect.ServiceSNI(svc.Name, name, svc.NamespaceOrDefault(), svc.PartitionOrDefault(), cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain) - route, err := makeNamedDefaultRouteWithLB(clusterName, lb, resolver.RequestTimeout, true) + route, err := makeNamedDefaultRouteWithLB(clusterName, lb, resolver.RequestTimeout, autoHostRewrite, validateClusters) if err != nil { s.Logger.Error("failed to make route", "cluster", clusterName, "error", err) return nil, err @@ -275,10 +285,9 @@ func (s *ResourceGenerator) routesForMeshGateway(cfgSnap *proxycfg.ConfigSnapsho route := &envoy_route_v3.RouteConfiguration{ Name: uid.EnvoyID(), VirtualHosts: []*envoy_route_v3.VirtualHost{virtualHost}, - // ValidateClusters defaults to true when defined statically and false - // when done via RDS. Re-set the reasonable value of true to prevent - // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), + } + if meshValidateClusters(cfgSnap) { + route.ValidateClusters = response.MakeBoolValue(true) } resources = append(resources, route) } @@ -286,7 +295,7 @@ func (s *ResourceGenerator) routesForMeshGateway(cfgSnap *proxycfg.ConfigSnapsho return resources, nil } -func makeNamedDefaultRouteWithLB(clusterName string, lb *structs.LoadBalancer, timeout time.Duration, autoHostRewrite bool) (*envoy_route_v3.RouteConfiguration, error) { +func makeNamedDefaultRouteWithLB(clusterName string, lb *structs.LoadBalancer, timeout time.Duration, autoHostRewrite bool, validateClusters bool) (*envoy_route_v3.RouteConfiguration, error) { action := makeRouteActionFromName(clusterName) if err := injectLBToRouteAction(lb, action.Route); err != nil { @@ -304,7 +313,7 @@ func makeNamedDefaultRouteWithLB(clusterName string, lb *structs.LoadBalancer, t action.Route.Timeout = durationpb.New(timeout) } - return &envoy_route_v3.RouteConfiguration{ + route := &envoy_route_v3.RouteConfiguration{ Name: clusterName, VirtualHosts: []*envoy_route_v3.VirtualHost{ { @@ -318,20 +327,19 @@ func makeNamedDefaultRouteWithLB(clusterName string, lb *structs.LoadBalancer, t }, }, }, - // ValidateClusters defaults to true when defined statically and false - // when done via RDS. Re-set the reasonable value of true to prevent - // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), - }, nil + } + if validateClusters { + route.ValidateClusters = response.MakeBoolValue(true) + } + return route, nil } -func makeNamedAddressesRoute(routeName string, addresses map[string]string) (*envoy_route_v3.RouteConfiguration, error) { +func makeNamedAddressesRoute(routeName string, addresses map[string]string, validateClusters bool) (*envoy_route_v3.RouteConfiguration, error) { route := &envoy_route_v3.RouteConfiguration{ Name: routeName, - // ValidateClusters defaults to true when defined statically and false - // when done via RDS. Re-set the reasonable value of true to prevent - // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), + } + if validateClusters { + route.ValidateClusters = response.MakeBoolValue(true) } for clusterName, address := range addresses { action := makeRouteActionFromName(clusterName) @@ -370,10 +378,10 @@ func (s *ResourceGenerator) routesForIngressGateway(cfgSnap *proxycfg.ConfigSnap // don't have custom filter chains and routes to this. defaultRoute := &envoy_route_v3.RouteConfiguration{ Name: listenerKey.RouteName(), - // ValidateClusters defaults to true when defined statically and false - // when done via RDS. Re-set the reasonable value of true to prevent - // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), + } + validateClusters := meshValidateClusters(cfgSnap) + if validateClusters { + defaultRoute.ValidateClusters = response.MakeBoolValue(true) } for _, u := range upstreams { @@ -421,9 +429,11 @@ func (s *ResourceGenerator) routesForIngressGateway(cfgSnap *proxycfg.ConfigSnap defaultRoute.VirtualHosts = append(defaultRoute.VirtualHosts, virtualHost) } else { svcRoute := &envoy_route_v3.RouteConfiguration{ - Name: svcRouteName, - ValidateClusters: response.MakeBoolValue(true), - VirtualHosts: []*envoy_route_v3.VirtualHost{virtualHost}, + Name: svcRouteName, + VirtualHosts: []*envoy_route_v3.VirtualHost{virtualHost}, + } + if validateClusters { + svcRoute.ValidateClusters = response.MakeBoolValue(true) } result = append(result, svcRoute) } @@ -445,6 +455,8 @@ func (s *ResourceGenerator) routesForAPIGateway(cfgSnap *proxycfg.ConfigSnapshot readyListeners := getReadyListeners(cfgSnap) listenerNames := maps.Keys(readyListeners) sort.Strings(listenerNames) + + // Iterate over all listeners that are ready and configure their routes. for _, listenerName := range listenerNames { readyListener, ok := readyListeners[listenerName] if !ok { @@ -457,10 +469,10 @@ func (s *ResourceGenerator) routesForAPIGateway(cfgSnap *proxycfg.ConfigSnapshot listenerRoute := &envoy_route_v3.RouteConfiguration{ Name: readyListener.listenerKey.RouteName(), - // ValidateClusters defaults to true when defined statically and false - // when done via RDS. Re-set the reasonable value of true to prevent - // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), + } + validateClusters := meshValidateClusters(cfgSnap) + if validateClusters { + listenerRoute.ValidateClusters = response.MakeBoolValue(true) } // Consolidate all routes for this listener into the minimum possible set based on hostname matching. @@ -486,6 +498,7 @@ func (s *ResourceGenerator) routesForAPIGateway(cfgSnap *proxycfg.ConfigSnapshot continue } + consolidatedRoute := consolidatedRoute // Reassignment to avoid closure issues with the loop variable. domains := generateUpstreamAPIsDomains(readyListener.listenerKey, upstream, consolidatedRoute.Hostnames) filterBuilder := perRouteFilterBuilder{providerMap: cfgSnap.JWTProviders, listener: &readyListener.listenerCfg, route: &consolidatedRoute} @@ -533,7 +546,10 @@ func makeHeadersValueOptions(vals map[string]string, add bool) []*envoy_core_v3. Key: k, Value: v, }, - Append: response.MakeBoolValue(add), + } + if !add { + // default is APPEND_IF_EXISTS_OR_ADD + o.AppendAction = envoy_core_v3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD } opts = append(opts, o) } @@ -693,10 +709,18 @@ func (s *ResourceGenerator) makeUpstreamRouteForDiscoveryChain( if destination.RequestTimeout > 0 { routeAction.Route.Timeout = durationpb.New(destination.RequestTimeout) } + // Disable the timeout if user specifies negative value. Setting 0 disables the timeout in Envoy. + if destination.RequestTimeout < 0 { + routeAction.Route.Timeout = durationpb.New(0 * time.Second) + } if destination.IdleTimeout > 0 { routeAction.Route.IdleTimeout = durationpb.New(destination.IdleTimeout) } + // Disable the timeout if user specifies negative value. Setting 0 disables the timeout in Envoy. + if destination.IdleTimeout < 0 { + routeAction.Route.IdleTimeout = durationpb.New(0 * time.Second) + } if destination.HasRetryFeatures() { routeAction.Route.RetryPolicy = getRetryPolicyForDestination(destination) @@ -751,9 +775,18 @@ func (s *ResourceGenerator) makeUpstreamRouteForDiscoveryChain( return nil, fmt.Errorf("failed to apply load balancer configuration to route action: %v", err) } + // A request timeout can be configured on a resolver or router. If configured on a resolver, the timeout will + // only apply if the start node is a resolver. This is because the timeout is attached to an (Envoy + // RouteAction)[https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-routeaction] + // If there is a splitter before this resolver, the branches of the split are configured within the same + // RouteAction, and the timeout cannot be shared between branches of a split. if startNode.Resolver.RequestTimeout > 0 { routeAction.Route.Timeout = durationpb.New(startNode.Resolver.RequestTimeout) } + // Disable the timeout if user specifies negative value. Setting 0 disables the timeout in Envoy. + if startNode.Resolver.RequestTimeout < 0 { + routeAction.Route.Timeout = durationpb.New(0 * time.Second) + } defaultRoute := &envoy_route_v3.Route{ Match: makeDefaultRouteMatch(), Action: routeAction, @@ -838,6 +871,10 @@ func makeRouteMatchForDiscoveryRoute(discoveryRoute *structs.DiscoveryRoute) *en } } + if match.HTTP.CaseInsensitive { + em.CaseSensitive = wrapperspb.Bool(false) + } + if len(match.HTTP.Header) > 0 { em.Headers = make([]*envoy_route_v3.HeaderMatcher, 0, len(match.HTTP.Header)) for _, hdr := range match.HTTP.Header { @@ -906,8 +943,12 @@ func makeRouteMatchForDiscoveryRoute(discoveryRoute *structs.DiscoveryRoute) *en eh := &envoy_route_v3.HeaderMatcher{ Name: ":method", - HeaderMatchSpecifier: &envoy_route_v3.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: response.MakeEnvoyRegexMatch(methodHeaderRegex), + HeaderMatchSpecifier: &envoy_route_v3.HeaderMatcher_StringMatch{ + StringMatch: &envoy_matcher_v3.StringMatcher{ + MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ + SafeRegex: response.MakeEnvoyRegexMatch(methodHeaderRegex), + }, + }, }, } @@ -996,7 +1037,6 @@ func (s *ResourceGenerator) makeRouteActionForSplitter( forMeshGateway bool, ) (*envoy_route_v3.Route_Route, error) { clusters := make([]*envoy_route_v3.WeightedCluster_ClusterWeight, 0, len(splits)) - totalWeight := 0 for _, split := range splits { nextNode := chain.Nodes[split.NextNode] @@ -1013,7 +1053,6 @@ func (s *ResourceGenerator) makeRouteActionForSplitter( // The smallest representable weight is 1/10000 or .01% but envoy // deals with integers so scale everything up by 100x. weight := int(split.Weight * 100) - totalWeight += weight cw := &envoy_route_v3.WeightedCluster_ClusterWeight{ Weight: response.MakeUint32Value(weight), Name: clusterName, @@ -1029,18 +1068,11 @@ func (s *ResourceGenerator) makeRouteActionForSplitter( return nil, fmt.Errorf("number of clusters in splitter must be > 0; got %d", len(clusters)) } - var envoyWeightScale *wrapperspb.UInt32Value - if totalWeight == 10000 { - envoyWeightScale = response.MakeUint32Value(10000) - } - return &envoy_route_v3.Route_Route{ Route: &envoy_route_v3.RouteAction{ ClusterSpecifier: &envoy_route_v3.RouteAction_WeightedClusters{ WeightedClusters: &envoy_route_v3.WeightedCluster{ Clusters: clusters, - // this field is deprecated, and we should get the desired behavior with the front-end validation - TotalWeight: envoyWeightScale, // scaled up 100% }, }, }, @@ -1117,6 +1149,7 @@ func injectLBToRouteAction(lb *structs.LoadBalancer, action *envoy_route_v3.Rout } func injectHeaderManipToRoute(dest *structs.ServiceRouteDestination, r *envoy_route_v3.Route) error { + if !dest.RequestHeaders.IsZero() { r.RequestHeadersToAdd = append( r.RequestHeadersToAdd, diff --git a/agent/xds/routes_test.go b/agent/xds/routes_test.go index 616331036118..eff0e32ad1b8 100644 --- a/agent/xds/routes_test.go +++ b/agent/xds/routes_test.go @@ -4,389 +4,16 @@ package xds import ( - "path/filepath" - "sort" "testing" "time" envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" - testinf "github.com/mitchellh/go-testing-interface" "github.com/stretchr/testify/require" "google.golang.org/protobuf/types/known/durationpb" - "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/xds/proxystateconverter" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/agent/xds/testcommon" - "github.com/hashicorp/consul/agent/xdsv2" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/sdk/testutil" ) -type routeTestCase struct { - name string - create func(t testinf.T) *proxycfg.ConfigSnapshot - overrideGoldenName string - alsoRunTestForV2 bool -} - -func makeRouteDiscoChainTests(enterprise bool) []routeTestCase { - return []routeTestCase{ - { - name: "connect-proxy-splitter-overweight", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-overweight", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-chain-and-overrides", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple-with-overrides", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "splitter-with-resolver-redirect", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-with-resolver-redirect-multidc", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-chain-and-splitter", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "chain-and-splitter", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-grpc-router", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "grpc-router", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-with-chain-and-router", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "chain-and-router", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-lb-in-resolver", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "lb-resolver", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-route-to-lb-resolver", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "redirect-to-lb-node", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - { - name: "connect-proxy-resolver-with-lb", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "resolver-with-lb", enterprise, nil, nil) - }, - alsoRunTestForV2: true, - }, - } -} - -func TestRoutesFromSnapshot(t *testing.T) { - // TODO: we should move all of these to TestAllResourcesFromSnapshot - // eventually to test all of the xDS types at once with the same input, - // just as it would be triggered by our xDS server. - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - tests := []routeTestCase{ - // TODO(rb): test match stanza skipped for grpc - // Start ingress gateway test cases - { - name: "ingress-config-entry-nil", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway_NilConfigEntry(t) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-defaults-no-chain", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, false, "tcp", - "default", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "simple", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain-external-sni", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", - "external-sni", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-splitter-with-resolver-redirect", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", - "splitter-with-resolver-redirect-multidc", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain-and-splitter", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", - "chain-and-splitter", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-grpc-router", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", - "grpc-router", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain-and-router", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", - "chain-and-router", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-lb-in-resolver", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http", - "lb-resolver", nil, nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-http-multiple-services", - create: proxycfg.TestConfigSnapshotIngress_HTTPMultipleServices, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-grpc-multiple-services", - create: proxycfg.TestConfigSnapshotIngress_GRPCMultipleServices, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-chain-and-router-header-manip", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "router-header-manip", nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-sds-listener-level", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-listener-level", nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-sds-listener-level-wildcard", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-listener-level-wildcard", nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-sds-service-level", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-service-level", nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "ingress-with-sds-service-level-mixed-tls", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-service-level-mixed-tls", nil, nil) - }, - // TODO(proxystate): ingress gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "terminating-gateway-lb-config", - create: proxycfg.TestConfigSnapshotTerminatingGatewayLBConfig, - // TODO(proxystate): terminating gateway will come at a later time - alsoRunTestForV2: false, - }, - { - name: "api-gateway-with-multiple-hostnames", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotAPIGateway(t, "default", nil, func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { - entry.Listeners = []structs.APIGatewayListener{ - { - Name: "http", - Protocol: structs.ListenerProtocolHTTP, - Port: 8080, - Hostname: "*.example.com", - }, - } - bound.Listeners = []structs.BoundAPIGatewayListener{ - { - Name: "http", - Routes: []structs.ResourceReference{ - {Kind: structs.HTTPRoute, Name: "backend-route"}, - {Kind: structs.HTTPRoute, Name: "frontend-route"}, - {Kind: structs.HTTPRoute, Name: "generic-route"}, - }}, - } - }, - []structs.BoundRoute{ - &structs.HTTPRouteConfigEntry{ - Kind: structs.HTTPRoute, - Name: "backend-route", - Hostnames: []string{"backend.example.com"}, - Parents: []structs.ResourceReference{{Kind: structs.APIGateway, Name: "api-gateway"}}, - Rules: []structs.HTTPRouteRule{ - {Services: []structs.HTTPService{{Name: "backend"}}}, - }, - }, - &structs.HTTPRouteConfigEntry{ - Kind: structs.HTTPRoute, - Name: "frontend-route", - Hostnames: []string{"frontend.example.com"}, - Parents: []structs.ResourceReference{{Kind: structs.APIGateway, Name: "api-gateway"}}, - Rules: []structs.HTTPRouteRule{ - {Services: []structs.HTTPService{{Name: "frontend"}}}, - }, - }, - &structs.HTTPRouteConfigEntry{ - Kind: structs.HTTPRoute, - Name: "generic-route", - Parents: []structs.ResourceReference{{Kind: structs.APIGateway, Name: "api-gateway"}}, - Rules: []structs.HTTPRouteRule{ - { - Matches: []structs.HTTPMatch{{Path: structs.HTTPPathMatch{Match: structs.HTTPPathMatchPrefix, Value: "/frontend"}}}, - Services: []structs.HTTPService{{Name: "frontend"}}, - }, - { - Matches: []structs.HTTPMatch{{Path: structs.HTTPPathMatch{Match: structs.HTTPPathMatchPrefix, Value: "/backend"}}}, - Services: []structs.HTTPService{{Name: "backend"}}, - }, - }, - }, - }, nil, nil) - }, - }, - } - - tests = append(tests, makeRouteDiscoChainTests(false)...) - - latestEnvoyVersion := xdscommon.EnvoyVersions[0] - for _, envoyVersion := range xdscommon.EnvoyVersions { - sf, err := xdscommon.DetermineSupportedProxyFeaturesFromString(envoyVersion) - require.NoError(t, err) - t.Run("envoy-"+envoyVersion, func(t *testing.T) { - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Sanity check default with no overrides first - snap := tt.create(t) - - // We need to replace the TLS certs with deterministic ones to make golden - // files workable. Note we don't update these otherwise they'd change - // golden files for every test case and so not be any use! - testcommon.SetupTLSRootsAndLeaf(t, snap) - - g := NewResourceGenerator(testutil.Logger(t), nil, false) - g.ProxyFeatures = sf - - routes, err := g.routesFromSnapshot(snap) - require.NoError(t, err) - - sort.Slice(routes, func(i, j int) bool { - return routes[i].(*envoy_route_v3.RouteConfiguration).Name < routes[j].(*envoy_route_v3.RouteConfiguration).Name - }) - r, err := response.CreateResponse(xdscommon.RouteType, "00000001", "00000001", routes) - require.NoError(t, err) - - t.Run("current-xdsv1", func(t *testing.T) { - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - require.JSONEq(t, goldenEnvoy(t, filepath.Join("routes", gName), envoyVersion, latestEnvoyVersion, gotJSON), gotJSON) - }) - - if tt.alsoRunTestForV2 { - generator := xdsv2.NewResourceGenerator(testutil.Logger(t)) - - converter := proxystateconverter.NewConverter(testutil.Logger(t), &mockCfgFetcher{addressLan: "10.10.10.10"}) - proxyState, err := converter.ProxyStateFromSnapshot(snap) - require.NoError(t, err) - - res, err := generator.AllResourcesFromIR(proxyState) - require.NoError(t, err) - - routes = res[xdscommon.RouteType] - // The order of routes returned via RDS isn't relevant, so it's safe - // to sort these for the purposes of test comparisons. - sort.Slice(routes, func(i, j int) bool { - return routes[i].(*envoy_route_v3.Route).Name < routes[j].(*envoy_route_v3.Route).Name - }) - - r, err := response.CreateResponse(xdscommon.RouteType, "00000001", "00000001", routes) - require.NoError(t, err) - - t.Run("current-xdsv2", func(t *testing.T) { - gotJSON := protoToJSON(t, r) - - gName := tt.name - if tt.overrideGoldenName != "" { - gName = tt.overrideGoldenName - } - - expectedJSON := goldenEnvoy(t, filepath.Join("routes", gName), envoyVersion, latestEnvoyVersion, gotJSON) - require.JSONEq(t, expectedJSON, gotJSON) - }) - } - }) - } - }) - } -} - func TestEnvoyLBConfig_InjectToRouteAction(t *testing.T) { var tests = []struct { name string diff --git a/agent/xds/secrets.go b/agent/xds/secrets.go index 628cec7905ba..e844c0e263cb 100644 --- a/agent/xds/secrets.go +++ b/agent/xds/secrets.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" + envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" "google.golang.org/protobuf/proto" "github.com/hashicorp/consul/agent/proxycfg" @@ -21,13 +23,45 @@ func (s *ResourceGenerator) secretsFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot } switch cfgSnap.Kind { + case structs.ServiceKindAPIGateway: + return s.secretsFromSnapshotAPIGateway(cfgSnap), nil // return any attached certs case structs.ServiceKindConnectProxy, structs.ServiceKindTerminatingGateway, structs.ServiceKindMeshGateway, - structs.ServiceKindIngressGateway, - structs.ServiceKindAPIGateway: + structs.ServiceKindIngressGateway: return nil, nil default: return nil, fmt.Errorf("Invalid service kind: %v", cfgSnap.Kind) } } + +// secretsFromSnapshotAPIGateway returns the "secrets" for an api-gateway service +func (s *ResourceGenerator) secretsFromSnapshotAPIGateway(cfgSnap *proxycfg.ConfigSnapshot) []proto.Message { + var resources []proto.Message + + cfgSnap.APIGateway.FileSystemCertificates.ForEachKey(func(ref structs.ResourceReference) bool { + cert, ok := cfgSnap.APIGateway.FileSystemCertificates.Get(ref) + if !ok || cert == nil { + return true + } + resources = append(resources, &envoy_tls_v3.Secret{ + Name: ref.Name, + Type: &envoy_tls_v3.Secret_TlsCertificate{ + TlsCertificate: &envoy_tls_v3.TlsCertificate{ + CertificateChain: &envoy_core_v3.DataSource{ + Specifier: &envoy_core_v3.DataSource_Filename{ + Filename: cert.Certificate, + }}, + PrivateKey: &envoy_core_v3.DataSource{ + Specifier: &envoy_core_v3.DataSource_Filename{ + Filename: cert.PrivateKey, + }, + }, + }, + }, + }) + return true + }) + + return resources +} diff --git a/agent/xds/server.go b/agent/xds/server.go index 45c11fa0b3a1..22532684fce7 100644 --- a/agent/xds/server.go +++ b/agent/xds/server.go @@ -12,18 +12,19 @@ import ( "github.com/armon/go-metrics" "github.com/armon/go-metrics/prometheus" envoy_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" - "github.com/hashicorp/go-hclog" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/consul/acl" external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/grpc-external/limiter" + "github.com/hashicorp/consul/agent/proxycfg" + "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/configfetcher" "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - "github.com/hashicorp/consul/proto-public/pbresource" ) var ( @@ -83,7 +84,7 @@ type ACLResolverFunc func(id string) (acl.Authorizer, error) // ProxyConfigSource is the interface xds.Server requires to consume proxy // config updates. type ProxyWatcher interface { - Watch(proxyID *pbresource.ID, nodeName string, token string) (<-chan proxysnapshot.ProxySnapshot, limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) + Watch(proxyID structs.ServiceID, nodeName string, token string) (<-chan *proxycfg.ConfigSnapshot, limiter.SessionTerminatedChan, proxycfg.SrcTerminatedChan, context.CancelFunc, error) } // Server represents a gRPC server that can handle xDS requests from Envoy. All @@ -200,9 +201,9 @@ func (s *Server) authenticate(ctx context.Context) (acl.Authorizer, error) { // using a token with the same permissions, and that it stores the data by // proxy ID. We assume that any data in the snapshot was already filtered, // which allows this authorization to be a shallow authorization check -// for all the data in a ProxySnapshot. -func (s *Server) authorize(ctx context.Context, proxySnapshot proxysnapshot.ProxySnapshot) error { - if proxySnapshot == nil { +// for all the data in a ConfigSnapshot. +func (s *Server) authorize(ctx context.Context, snapshot *proxycfg.ConfigSnapshot) error { + if snapshot == nil { return status.Errorf(codes.Unauthenticated, "unauthenticated: no config snapshot") } @@ -211,5 +212,5 @@ func (s *Server) authorize(ctx context.Context, proxySnapshot proxysnapshot.Prox return err } - return proxySnapshot.Authorize(authz) + return snapshot.Authorize(authz) } diff --git a/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-local-grpc-service.latest.golden b/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-local-grpc-service.latest.golden index f790cfd0dfd4..386fcabc1264 100644 --- a/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-local-grpc-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-local-grpc-service.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-local-http-service.latest.golden b/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-local-http-service.latest.golden index 75698e93949e..afcb0af066b7 100644 --- a/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-local-http-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-local-http-service.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-upstream-grpc-service.latest.golden b/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-upstream-grpc-service.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-upstream-grpc-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-upstream-grpc-service.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-upstream-http-service.latest.golden b/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-upstream-http-service.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-upstream-http-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/ext-authz-http-upstream-http-service.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/ext-authz-tcp-local-grpc-service.latest.golden b/agent/xds/testdata/builtin_extension/clusters/ext-authz-tcp-local-grpc-service.latest.golden index f790cfd0dfd4..386fcabc1264 100644 --- a/agent/xds/testdata/builtin_extension/clusters/ext-authz-tcp-local-grpc-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/ext-authz-tcp-local-grpc-service.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/ext-authz-tcp-upstream-grpc-service.latest.golden b/agent/xds/testdata/builtin_extension/clusters/ext-authz-tcp-upstream-grpc-service.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/ext-authz-tcp-upstream-grpc-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/ext-authz-tcp-upstream-grpc-service.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lambda-and-lua-connect-proxy.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lambda-and-lua-connect-proxy.latest.golden index 81032f1d2d3d..e02f5639c2fb 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lambda-and-lua-connect-proxy.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lambda-and-lua-connect-proxy.latest.golden @@ -70,12 +70,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy-opposite-meta.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy-opposite-meta.latest.golden index 81032f1d2d3d..e02f5639c2fb 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy-opposite-meta.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy-opposite-meta.latest.golden @@ -70,12 +70,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy-tproxy.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy-tproxy.latest.golden index bc6a584cb234..20674f6faed7 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy-tproxy.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy-tproxy.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { @@ -194,9 +203,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/no-endpoints" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/no-endpoints" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy-with-terminating-gateway-upstream.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy-with-terminating-gateway-upstream.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy-with-terminating-gateway-upstream.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy-with-terminating-gateway-upstream.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy.latest.golden index 81032f1d2d3d..e02f5639c2fb 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lambda-connect-proxy.latest.golden @@ -70,12 +70,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lua-connect-proxy-with-terminating-gateway-upstream.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lua-connect-proxy-with-terminating-gateway-upstream.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lua-connect-proxy-with-terminating-gateway-upstream.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lua-connect-proxy-with-terminating-gateway-upstream.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lua-inbound-applies-to-inbound.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lua-inbound-applies-to-inbound.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lua-inbound-applies-to-inbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lua-inbound-applies-to-inbound.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lua-inbound-doesnt-apply-to-local-upstreams.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lua-inbound-doesnt-apply-to-local-upstreams.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lua-inbound-doesnt-apply-to-local-upstreams.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lua-inbound-doesnt-apply-to-local-upstreams.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden index 43ffe1773a93..2c627cfb7a0d 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -81,9 +84,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + }, + "sanType": "URI" } ], "trustedCa": { @@ -128,9 +134,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka2" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka2" + }, + "sanType": "URI" } ], "trustedCa": { @@ -175,9 +184,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka2" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka2" + }, + "sanType": "URI" } ], "trustedCa": { @@ -222,9 +234,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + }, + "sanType": "URI" } ], "trustedCa": { @@ -266,12 +281,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-applies-to-local-upstreams.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-applies-to-local-upstreams.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-applies-to-local-upstreams.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-applies-to-local-upstreams.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-inbound.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-inbound.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-inbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-inbound.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/otel-access-logging-http.latest.golden b/agent/xds/testdata/builtin_extension/clusters/otel-access-logging-http.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/otel-access-logging-http.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/otel-access-logging-http.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-keepalive.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-keepalive.latest.golden index cb4e0cec1ef8..1f17d8083116 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-keepalive.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-keepalive.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -83,12 +86,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-outlier-detection-multiple.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-outlier-detection-multiple.latest.golden index eb17f11f4849..9d2c057c8546 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-outlier-detection-multiple.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-outlier-detection-multiple.latest.golden @@ -37,9 +37,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -84,12 +87,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-outlier-detection.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-outlier-detection.latest.golden index 9432eb1b72e9..8646d9607def 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-outlier-detection.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-outlier-detection.latest.golden @@ -36,9 +36,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -82,12 +85,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-round-robin-lb-config.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-round-robin-lb-config.latest.golden index 680271c7235e..b4e4bf5ed079 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-round-robin-lb-config.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-add-round-robin-lb-config.latest.golden @@ -35,9 +35,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -80,12 +83,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-cluster-load-assignment-inbound-add.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-cluster-load-assignment-inbound-add.latest.golden index 7362f44a5775..6a4524b7cc10 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-cluster-load-assignment-inbound-add.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-cluster-load-assignment-inbound-add.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-cluster-load-assignment-outbound-add.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-cluster-load-assignment-outbound-add.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-cluster-load-assignment-outbound-add.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-cluster-load-assignment-outbound-add.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-inbound-doesnt-apply-to-outbound.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-inbound-doesnt-apply-to-outbound.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-inbound-doesnt-apply-to-outbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-inbound-doesnt-apply-to-outbound.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-listener-inbound-add.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-listener-inbound-add.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-listener-inbound-add.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-listener-inbound-add.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-listener-outbound-add.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-listener-outbound-add.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-listener-outbound-add.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-listener-outbound-add.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-outbound-doesnt-apply-to-inbound.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-outbound-doesnt-apply-to-inbound.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-outbound-doesnt-apply-to-inbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-outbound-doesnt-apply-to-inbound.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-failover.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-failover.latest.golden index 4b9c16277584..96442eb9aaf7 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-failover.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-failover.latest.golden @@ -56,9 +56,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -106,9 +109,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/fail" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/fail" + }, + "sanType": "URI" } ], "trustedCa": { @@ -150,12 +156,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-splitter.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-splitter.latest.golden index 0dcc1ca7521e..1abfefc30d1d 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-splitter.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-splitter.latest.golden @@ -30,12 +30,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { @@ -108,9 +114,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -158,9 +167,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service.latest.golden index 2f37bfe304d4..0832200489d7 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service.latest.golden @@ -55,9 +55,12 @@ "trustedCa": { "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" }, - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "sanType": "URI", + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + } } ] } @@ -103,9 +106,12 @@ "trustedCa": { "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" }, - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/fail" + "sanType": "URI", + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/fail" + } } ] } @@ -147,12 +153,18 @@ "trustedCa": { "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" }, - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "sanType": "URI", + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + } }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "sanType": "URI", + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + } } ] } diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-remove-outlier-detection.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-remove-outlier-detection.latest.golden index fe41565d6e50..32f4590f6189 100644 --- a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-remove-outlier-detection.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-remove-outlier-detection.latest.golden @@ -33,9 +33,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -76,12 +79,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden b/agent/xds/testdata/builtin_extension/clusters/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden new file mode 100644 index 000000000000..ccb53f24bc5f --- /dev/null +++ b/agent/xds/testdata/builtin_extension/clusters/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden @@ -0,0 +1,175 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "loadAssignment": { + "clusterName": "local_ext_authz", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + } + } + } + ] + } + ] + }, + "name": "local_ext_authz", + "type": "STATIC", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "lbPolicy": "CLUSTER_PROVIDED", + "name": "original-destination", + "type": "ORIGINAL_DST" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/clusters/wasm-http-local-file.latest.golden b/agent/xds/testdata/builtin_extension/clusters/wasm-http-local-file.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/wasm-http-local-file.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/wasm-http-local-file.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/wasm-http-remote-file.latest.golden b/agent/xds/testdata/builtin_extension/clusters/wasm-http-remote-file.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/wasm-http-remote-file.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/wasm-http-remote-file.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file-outbound.latest.golden b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file-outbound.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file-outbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file-outbound.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file.latest.golden b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file-outbound.latest.golden b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file-outbound.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file-outbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file-outbound.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file.latest.golden b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file.latest.golden +++ b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/builtin_extension/endpoints/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden b/agent/xds/testdata/builtin_extension/endpoints/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/endpoints/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-grpc-service.latest.golden b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-grpc-service.latest.golden index 2492e2ffaf4d..1e0abe2e8e22 100644 --- a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-grpc-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-grpc-service.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -177,6 +172,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -253,4 +249,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-http-service.latest.golden b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-http-service.latest.golden index 120bb1ee6fda..f36ab9bd4f76 100644 --- a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-http-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-local-http-service.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -178,6 +173,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -254,4 +250,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-grpc-service.latest.golden b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-grpc-service.latest.golden index 69dd07bf6340..79de5b7ea751 100644 --- a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-grpc-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-grpc-service.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -201,6 +196,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -277,4 +273,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-http-service.latest.golden b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-http-service.latest.golden index 52ff163ef607..dcd1f6473ccd 100644 --- a/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-http-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/ext-authz-http-upstream-http-service.latest.golden @@ -121,13 +121,11 @@ "patterns": [ { "safeRegex": { - "googleRe2": {}, "regex": "client-ok-header-1" } }, { "safeRegex": { - "googleRe2": {}, "regex": "client-ok-header-2" } } @@ -204,7 +202,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -218,7 +215,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -232,7 +228,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -246,7 +241,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -260,7 +254,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -277,6 +270,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -353,4 +347,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lambda-and-lua-connect-proxy.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lambda-and-lua-connect-proxy.latest.golden index bf09509b375d..e4ed710e26e8 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lambda-and-lua-connect-proxy.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lambda-and-lua-connect-proxy.latest.golden @@ -132,7 +132,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -146,7 +145,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -160,7 +158,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -174,7 +171,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -188,7 +184,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -202,7 +197,9 @@ "name": "envoy.filters.http.lua", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", - "inlineCode": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + "defaultSourceCode": { + "inlineString": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + } } }, { @@ -212,6 +209,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -288,4 +286,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-inbound-applies-to-inbound.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-inbound-applies-to-inbound.latest.golden index f0b2d4684088..327996fc8ba7 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-inbound-applies-to-inbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-inbound-applies-to-inbound.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -157,7 +152,9 @@ "name": "envoy.filters.http.lua", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", - "inlineCode": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + "defaultSourceCode": { + "inlineString": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + } } }, { @@ -167,6 +164,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -243,4 +241,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-inbound-doesnt-apply-to-local-upstreams.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-inbound-doesnt-apply-to-local-upstreams.latest.golden index 3b2dab64b526..48329b29199b 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-inbound-doesnt-apply-to-local-upstreams.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-inbound-doesnt-apply-to-local-upstreams.latest.golden @@ -123,7 +123,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -137,7 +136,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -151,7 +149,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -165,7 +162,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -179,7 +175,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -193,7 +188,9 @@ "name": "envoy.filters.http.lua", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", - "inlineCode": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + "defaultSourceCode": { + "inlineString": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + } } }, { @@ -203,6 +200,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -279,4 +277,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden index 0b349be9433b..b8eb216fd362 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden @@ -49,7 +49,9 @@ "name": "envoy.filters.http.lua", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", - "inlineCode": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + "defaultSourceCode": { + "inlineString": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + } } }, { @@ -93,7 +95,9 @@ "name": "envoy.filters.http.lua", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", - "inlineCode": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + "defaultSourceCode": { + "inlineString": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + } } }, { @@ -202,7 +206,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -216,7 +219,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -230,7 +232,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -244,7 +245,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -258,7 +258,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -275,6 +274,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -351,4 +351,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams.latest.golden index ade1593e2eab..5f397f4faf4d 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams.latest.golden @@ -21,7 +21,9 @@ "name": "envoy.filters.http.lua", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", - "inlineCode": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + "defaultSourceCode": { + "inlineString": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + } } }, { @@ -130,7 +132,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -144,7 +145,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -158,7 +158,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -172,7 +171,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -186,7 +184,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -203,6 +200,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -279,4 +277,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-inbound.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-inbound.latest.golden index cec77f10e445..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-inbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-inbound.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -160,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -236,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden index e8a4a1432082..ac46c9294aac 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden @@ -123,7 +123,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -137,7 +136,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -151,7 +149,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -165,7 +162,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -179,7 +175,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -196,6 +191,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -272,4 +268,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden index e8a4a1432082..ac46c9294aac 100644 --- a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden @@ -123,7 +123,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -137,7 +136,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -151,7 +149,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -165,7 +162,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -179,7 +175,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -196,6 +191,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -272,4 +268,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/otel-access-logging-http.latest.golden b/agent/xds/testdata/builtin_extension/listeners/otel-access-logging-http.latest.golden index ad4cde37e91f..2192863e8f4f 100644 --- a/agent/xds/testdata/builtin_extension/listeners/otel-access-logging-http.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/otel-access-logging-http.latest.golden @@ -137,7 +137,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -151,7 +150,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -165,7 +163,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -179,7 +176,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -193,7 +189,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -210,6 +205,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -286,4 +282,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-keepalive.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-keepalive.latest.golden index cec77f10e445..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-keepalive.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-keepalive.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -160,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -236,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection-multiple.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection-multiple.latest.golden index cec77f10e445..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection-multiple.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection-multiple.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -160,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -236,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection.latest.golden index cec77f10e445..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-outlier-detection.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -160,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -236,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-round-robin-lb-config.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-round-robin-lb-config.latest.golden index cec77f10e445..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-round-robin-lb-config.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-add-round-robin-lb-config.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -160,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -236,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-inbound-add.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-inbound-add.latest.golden index cec77f10e445..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-inbound-add.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-inbound-add.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -160,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -236,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-outbound-add.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-outbound-add.latest.golden index cec77f10e445..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-outbound-add.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-cluster-load-assignment-outbound-add.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -160,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -236,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-inbound-doesnt-apply-to-outbound.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-inbound-doesnt-apply-to-outbound.latest.golden index 63986a898dfc..a2637fb045c2 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-inbound-doesnt-apply-to-outbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-inbound-doesnt-apply-to-outbound.latest.golden @@ -89,7 +89,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -103,7 +102,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -117,7 +115,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -131,7 +128,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -145,7 +141,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -162,6 +157,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -239,4 +235,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-inbound-add.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-inbound-add.latest.golden index 9b756b88ea5f..b49e8bbc3deb 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-inbound-add.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-inbound-add.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -160,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -237,4 +233,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-outbound-add.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-outbound-add.latest.golden index 91b69ea92489..8b22c6e75fb1 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-outbound-add.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-listener-outbound-add.latest.golden @@ -89,7 +89,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -103,7 +102,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -117,7 +115,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -131,7 +128,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -145,7 +141,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -162,6 +157,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -238,4 +234,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-outbound-doesnt-apply-to-inbound.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-outbound-doesnt-apply-to-inbound.latest.golden index 63986a898dfc..a2637fb045c2 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-outbound-doesnt-apply-to-inbound.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-outbound-doesnt-apply-to-inbound.latest.golden @@ -89,7 +89,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -103,7 +102,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -117,7 +115,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -131,7 +128,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -145,7 +141,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -162,6 +157,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -239,4 +235,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-failover.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-failover.latest.golden index 81fdba1d6641..150c780fa90c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-failover.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-failover.latest.golden @@ -88,7 +88,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -102,7 +101,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -116,7 +114,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -130,7 +127,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -144,7 +140,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -161,6 +156,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -237,4 +233,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-splitter.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-splitter.latest.golden index 680526bfbcf3..7db42b9abb7e 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-splitter.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-splitter.latest.golden @@ -110,7 +110,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -124,7 +123,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -138,7 +136,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -152,7 +149,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -166,7 +162,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -183,6 +178,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -259,4 +255,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service.latest.golden index 7a4514f1d783..8437fb9b2ee2 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service.latest.golden @@ -109,7 +109,6 @@ "key": "trust-domain", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -123,7 +122,6 @@ "key": "partition", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -137,7 +135,6 @@ "key": "namespace", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -151,7 +148,6 @@ "key": "datacenter", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -165,7 +161,6 @@ "key": "service", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-remove-outlier-detection.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-remove-outlier-detection.latest.golden index cec77f10e445..b334e2c0337c 100644 --- a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-remove-outlier-detection.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-remove-outlier-detection.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -160,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -236,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden b/agent/xds/testdata/builtin_extension/listeners/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden new file mode 100644 index 000000000000..fa869cc25ef7 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/listeners/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden @@ -0,0 +1,306 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 1234 + } + }, + "defaultFilterChain": { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "original-destination", + "statPrefix": "upstream.original-destination" + } + } + ] + }, + "listenerFilters": [ + { + "name": "envoy.filters.listener.original_dst", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst" + } + } + ], + "name": "outbound_listener:127.0.0.1:1234", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.header_to_metadata", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config", + "requestRules": [ + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "trust-domain", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\1" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "partition", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\2" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "namespace", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\3" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "datacenter", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\4" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "service", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\5" + } + } + } + ] + } + }, + { + "name": "envoy.filters.http.ext_authz", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz", + "failureModeAllow": true, + "grpcService": { + "envoyGrpc": { + "clusterName": "local_ext_authz" + } + }, + "metadataContextNamespaces": [ + "consul" + ], + "statPrefix": "response", + "transportApiVersion": "V3" + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "normalizePath": true, + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "public_listener", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "public_listener", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "alpnProtocols": [ + "http/1.1" + ], + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "destinationPort": 8080 + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "permissive_public_listener" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.original_dst", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst" + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/builtin_extension/listeners/wasm-http-local-file.latest.golden b/agent/xds/testdata/builtin_extension/listeners/wasm-http-local-file.latest.golden index f7420d09994d..75ca9826a8b5 100644 --- a/agent/xds/testdata/builtin_extension/listeners/wasm-http-local-file.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/wasm-http-local-file.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -181,6 +176,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -257,4 +253,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/listeners/wasm-http-remote-file.latest.golden b/agent/xds/testdata/builtin_extension/listeners/wasm-http-remote-file.latest.golden index 6dfde3d213e3..3d168a28ce60 100644 --- a/agent/xds/testdata/builtin_extension/listeners/wasm-http-remote-file.latest.golden +++ b/agent/xds/testdata/builtin_extension/listeners/wasm-http-remote-file.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -186,6 +181,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -262,4 +258,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/builtin_extension/routes/lambda-terminating-gateway-with-service-resolvers.latest.golden b/agent/xds/testdata/builtin_extension/routes/lambda-terminating-gateway-with-service-resolvers.latest.golden index 192eed0b6cbe..3888c533f2c4 100644 --- a/agent/xds/testdata/builtin_extension/routes/lambda-terminating-gateway-with-service-resolvers.latest.golden +++ b/agent/xds/testdata/builtin_extension/routes/lambda-terminating-gateway-with-service-resolvers.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "canary1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -27,7 +26,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "canary2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -50,7 +48,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/builtin_extension/routes/lambda-terminating-gateway.latest.golden b/agent/xds/testdata/builtin_extension/routes/lambda-terminating-gateway.latest.golden index 5e25d5fdfafc..de8175e81e92 100644 --- a/agent/xds/testdata/builtin_extension/routes/lambda-terminating-gateway.latest.golden +++ b/agent/xds/testdata/builtin_extension/routes/lambda-terminating-gateway.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/builtin_extension/routes/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden b/agent/xds/testdata/builtin_extension/routes/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden index 0f3440e32e34..f91d4715d1e6 100644 --- a/agent/xds/testdata/builtin_extension/routes/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden +++ b/agent/xds/testdata/builtin_extension/routes/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "destination.443.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -27,7 +26,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "destination.9093.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service-splitter.latest.golden b/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service-splitter.latest.golden index dc51ff588d73..29ba8ff7c2c1 100644 --- a/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service-splitter.latest.golden +++ b/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service-splitter.latest.golden @@ -5,7 +5,6 @@ "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "mostSpecificHeaderMutationsWins": true, "name": "db", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -28,8 +27,7 @@ "name": "v2.db.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul", "weight": 5000 } - ], - "totalWeight": 10000 + ] } } } diff --git a/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service.latest.golden b/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service.latest.golden index 095330c68404..1b9284c99175 100644 --- a/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service.latest.golden +++ b/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service.latest.golden @@ -22,8 +22,7 @@ } ] } - ], - "validateClusters": true + ] } ], "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", diff --git a/agent/xds/testdata/builtin_extension/routes/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden b/agent/xds/testdata/builtin_extension/routes/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/builtin_extension/routes/tproxy-and-permissive-mtls-and-envoy-extension.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/access-logs-defaults.latest.golden b/agent/xds/testdata/clusters/access-logs-defaults.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/access-logs-defaults.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/access-logs-json-file.latest.golden b/agent/xds/testdata/clusters/access-logs-json-file.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/access-logs-json-file.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/access-logs-text-stderr-disablelistenerlogs.latest.golden b/agent/xds/testdata/clusters/access-logs-text-stderr-disablelistenerlogs.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/access-logs-text-stderr-disablelistenerlogs.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/api-gateway-http-listener-with-http-route.latest.golden b/agent/xds/testdata/clusters/api-gateway-http-listener-with-http-route.latest.golden new file mode 100644 index 000000000000..6adc2759b63c --- /dev/null +++ b/agent/xds/testdata/clusters/api-gateway-http-listener-with-http-route.latest.golden @@ -0,0 +1,58 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "http-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "http-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/http-service" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "http-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/api-gateway-http-listener.latest.golden b/agent/xds/testdata/clusters/api-gateway-http-listener.latest.golden new file mode 100644 index 000000000000..04106b67f20a --- /dev/null +++ b/agent/xds/testdata/clusters/api-gateway-http-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/api-gateway-nil-config-entry.latest.golden b/agent/xds/testdata/clusters/api-gateway-nil-config-entry.latest.golden new file mode 100644 index 000000000000..04106b67f20a --- /dev/null +++ b/agent/xds/testdata/clusters/api-gateway-nil-config-entry.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/api-gateway-tcp-listener-with-tcp-and-http-route.latest.golden b/agent/xds/testdata/clusters/api-gateway-tcp-listener-with-tcp-and-http-route.latest.golden new file mode 100644 index 000000000000..44b54139debd --- /dev/null +++ b/agent/xds/testdata/clusters/api-gateway-tcp-listener-with-tcp-and-http-route.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "http-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "http-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/http-service" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "http-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "tcp-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "tcp-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/tcp-service" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "tcp-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/api-gateway-tcp-listener-with-tcp-route.latest.golden b/agent/xds/testdata/clusters/api-gateway-tcp-listener-with-tcp-route.latest.golden new file mode 100644 index 000000000000..8a1b647fe8e2 --- /dev/null +++ b/agent/xds/testdata/clusters/api-gateway-tcp-listener-with-tcp-route.latest.golden @@ -0,0 +1,58 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "tcp-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "tcp-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/tcp-service" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "tcp-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/api-gateway-tcp-listener.latest.golden b/agent/xds/testdata/clusters/api-gateway-tcp-listener.latest.golden new file mode 100644 index 000000000000..04106b67f20a --- /dev/null +++ b/agent/xds/testdata/clusters/api-gateway-tcp-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden b/agent/xds/testdata/clusters/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden index 6ffbd421e068..0e1609fc1a17 100644 --- a/agent/xds/testdata/clusters/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden +++ b/agent/xds/testdata/clusters/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/service" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/service" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/api-gateway-with-http-route.latest.golden b/agent/xds/testdata/clusters/api-gateway-with-http-route.latest.golden index 6ffbd421e068..0e1609fc1a17 100644 --- a/agent/xds/testdata/clusters/api-gateway-with-http-route.latest.golden +++ b/agent/xds/testdata/clusters/api-gateway-with-http-route.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/service" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/service" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/api-gateway-with-multiple-hostnames.latest.golden b/agent/xds/testdata/clusters/api-gateway-with-multiple-hostnames.latest.golden new file mode 100644 index 000000000000..52ba9b3f70ea --- /dev/null +++ b/agent/xds/testdata/clusters/api-gateway-with-multiple-hostnames.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "backend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "backend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/backend" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "backend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "frontend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "frontend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/frontend" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "frontend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/api-gateway-with-multiple-inline-certificates.latest.golden b/agent/xds/testdata/clusters/api-gateway-with-multiple-inline-certificates.latest.golden index 6ffbd421e068..0e1609fc1a17 100644 --- a/agent/xds/testdata/clusters/api-gateway-with-multiple-inline-certificates.latest.golden +++ b/agent/xds/testdata/clusters/api-gateway-with-multiple-inline-certificates.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/service" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/service" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/api-gateway-with-tcp-route-and-inline-certificate.latest.golden b/agent/xds/testdata/clusters/api-gateway-with-tcp-route-and-inline-certificate.latest.golden index 6ffbd421e068..0e1609fc1a17 100644 --- a/agent/xds/testdata/clusters/api-gateway-with-tcp-route-and-inline-certificate.latest.golden +++ b/agent/xds/testdata/clusters/api-gateway-with-tcp-route-and-inline-certificate.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/service" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/service" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/api-gateway.latest.golden b/agent/xds/testdata/clusters/api-gateway.latest.golden new file mode 100644 index 000000000000..04106b67f20a --- /dev/null +++ b/agent/xds/testdata/clusters/api-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-lb-in-resolver.latest.golden b/agent/xds/testdata/clusters/connect-proxy-lb-in-resolver.latest.golden index dc004b4e2204..15da9c0948af 100644 --- a/agent/xds/testdata/clusters/connect-proxy-lb-in-resolver.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-lb-in-resolver.latest.golden @@ -39,9 +39,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -83,12 +86,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { @@ -159,9 +168,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/something-else" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/something-else" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-resolver-with-lb.latest.golden b/agent/xds/testdata/clusters/connect-proxy-resolver-with-lb.latest.golden new file mode 100644 index 000000000000..9396e8d11a0d --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-resolver-with-lb.latest.golden @@ -0,0 +1,141 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "lbPolicy": "RING_HASH", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "ringHashLbConfig": { + "maximumRingSize": "30", + "minimumRingSize": "20" + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-route-to-lb-resolver.latest.golden b/agent/xds/testdata/clusters/connect-proxy-route-to-lb-resolver.latest.golden new file mode 100644 index 000000000000..d596a62877ce --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-route-to-lb-resolver.latest.golden @@ -0,0 +1,192 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "lbPolicy": "RING_HASH", + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "ringHashLbConfig": { + "maximumRingSize": "30", + "minimumRingSize": "20" + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/web" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-splitter-overweight.latest.golden b/agent/xds/testdata/clusters/connect-proxy-splitter-overweight.latest.golden new file mode 100644 index 000000000000..ba4ae02e6fc2 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-splitter-overweight.latest.golden @@ -0,0 +1,238 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/big-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/goldilocks-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/lil-bit-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-upstream-defaults.latest.golden b/agent/xds/testdata/clusters/connect-proxy-upstream-defaults.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-upstream-defaults.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-failover-to-cluster-peer.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-failover-to-cluster-peer.latest.golden index 9a7a84c48bf9..e8c6fe498dde 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-failover-to-cluster-peer.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-failover-to-cluster-peer.latest.golden @@ -51,9 +51,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -99,9 +102,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -143,12 +149,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-failover.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-failover.latest.golden index a6c7b69749e6..9a2a48fc5ade 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-failover.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-failover.latest.golden @@ -51,9 +51,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -99,9 +102,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/fail" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/fail" + }, + "sanType": "URI" } ], "trustedCa": { @@ -143,12 +149,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-overrides.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-overrides.latest.golden index d438330c606b..855477a934c9 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-overrides.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-overrides.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -86,12 +89,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-redirect-to-cluster-peer.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-redirect-to-cluster-peer.latest.golden index 820039ff1385..f623f5cd389d 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-redirect-to-cluster-peer.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-redirect-to-cluster-peer.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-router.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-router.latest.golden new file mode 100644 index 000000000000..5e21bd47e6aa --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-router.latest.golden @@ -0,0 +1,1615 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/big-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/empty-match-1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/empty-match-2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/goldilocks-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-exact-with-method" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-not-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-prefix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-suffix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/header-manip" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/idle-timeout" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/just-methods" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/lil-bit-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/nil-match" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix-rewrite-1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix-rewrite-2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/req-timeout" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-all" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-codes" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-connect" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-reset" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden new file mode 100644 index 000000000000..930870b0067d --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden @@ -0,0 +1,289 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/big-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "25s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/goldilocks-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/lil-bit-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-chain-and-splitter.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-splitter.latest.golden new file mode 100644 index 000000000000..930870b0067d --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-chain-and-splitter.latest.golden @@ -0,0 +1,289 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/big-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "25s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/goldilocks-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/lil-bit-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-chain-external-sni.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-chain-external-sni.latest.golden index 26f0e477774d..a0b4401d9810 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-chain-external-sni.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-chain-external-sni.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-chain-http2.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-chain-http2.latest.golden index f03d8c0ffcc9..0ddad7ce0d66 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-chain-http2.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-chain-http2.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -86,12 +89,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-chain.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-chain.latest.golden index 69904e61ca16..7920034940e2 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-chain.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-chain.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-default-chain-and-custom-cluster.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-default-chain-and-custom-cluster.latest.golden new file mode 100644 index 000000000000..537e24c4187c --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-default-chain-and-custom-cluster.latest.golden @@ -0,0 +1,142 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "15s", + "loadAssignment": { + "clusterName": "myservice", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "myservice", + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-grpc-chain.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-grpc-chain.latest.golden new file mode 100644 index 000000000000..0ddad7ce0d66 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-grpc-chain.latest.golden @@ -0,0 +1,144 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-grpc-router.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-grpc-router.latest.golden new file mode 100644 index 000000000000..6d8ceeaf259f --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-grpc-router.latest.golden @@ -0,0 +1,203 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-http-chain.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-http-chain.latest.golden new file mode 100644 index 000000000000..7920034940e2 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-http-chain.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-http2-chain.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-http2-chain.latest.golden new file mode 100644 index 000000000000..0ddad7ce0d66 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-http2-chain.latest.golden @@ -0,0 +1,144 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-jwt-config-entry-with-local.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-jwt-config-entry-with-local.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-jwt-config-entry-with-local.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-jwt-config-entry-with-local.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden index b3aeed5b6380..a370a6b8517f 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden new file mode 100644 index 000000000000..22df9de55275 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden new file mode 100644 index 000000000000..22df9de55275 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden index d7aa33d71a7c..3a661a941244 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-escape-overrides.latest.golden @@ -66,9 +66,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/payments" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/payments" + }, + "sanType": "URI" } ], "trustedCa": { @@ -114,9 +117,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/refunds" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/refunds" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-http2.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-http2.latest.golden index 091cbbb5aa1c..17c0317f28a5 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-http2.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams-http2.latest.golden @@ -77,9 +77,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/payments" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/payments" + }, + "sanType": "URI" } ], "trustedCa": { @@ -134,9 +137,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/refunds" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/refunds" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams.latest.golden index 018997d5d0b8..1d8fd606ff65 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-peered-upstreams.latest.golden @@ -77,9 +77,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/payments" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/payments" + }, + "sanType": "URI" } ], "trustedCa": { @@ -126,9 +129,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/refunds" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/refunds" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden index eeff91635829..9b385cabdc86 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden @@ -52,9 +52,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -100,9 +103,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -148,9 +154,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -192,12 +201,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden index eeff91635829..9b385cabdc86 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden @@ -52,9 +52,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -100,9 +103,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -148,9 +154,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -192,12 +201,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden index eeff91635829..9b385cabdc86 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden @@ -52,9 +52,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -100,9 +103,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -148,9 +154,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -192,12 +201,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden index eeff91635829..9b385cabdc86 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden @@ -52,9 +52,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -100,9 +103,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -148,9 +154,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -192,12 +201,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden index e5c67ced9193..cc7976651edd 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden @@ -51,9 +51,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -99,9 +102,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -143,12 +149,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-local-gateway.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-local-gateway.latest.golden index e5c67ced9193..cc7976651edd 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-local-gateway.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-local-gateway.latest.golden @@ -51,9 +51,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -99,9 +102,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -143,12 +149,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden index e5c67ced9193..cc7976651edd 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden @@ -51,9 +51,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -99,9 +102,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -143,12 +149,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-remote-gateway.latest.golden index e5c67ced9193..cc7976651edd 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-remote-gateway.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-remote-gateway.latest.golden @@ -51,9 +51,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -99,9 +102,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -143,12 +149,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain.latest.golden new file mode 100644 index 000000000000..7920034940e2 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-tcp-chain.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tls-incoming-cipher-suites.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tls-incoming-cipher-suites.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-tls-incoming-cipher-suites.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tls-incoming-max-version.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tls-incoming-max-version.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-tls-incoming-max-version.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tls-incoming-min-version.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tls-incoming-min-version.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-tls-incoming-min-version.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden index 8f405e7dd333..f826871febb9 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden @@ -39,9 +39,12 @@ ] }, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -88,12 +91,18 @@ ] }, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-max-version.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-max-version.latest.golden index 24554d780d29..1f67e931787d 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-max-version.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-max-version.latest.golden @@ -36,9 +36,12 @@ "tlsMaximumProtocolVersion": "TLSv1_2" }, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -82,12 +85,18 @@ "tlsMaximumProtocolVersion": "TLSv1_2" }, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-min-version.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-min-version.latest.golden index 29763283b961..fc501a889945 100644 --- a/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-min-version.latest.golden +++ b/agent/xds/testdata/clusters/connect-proxy-with-tls-outgoing-min-version.latest.golden @@ -36,9 +36,12 @@ "tlsMinimumProtocolVersion": "TLSv1_3" }, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -82,12 +85,18 @@ "tlsMinimumProtocolVersion": "TLSv1_3" }, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden b/agent/xds/testdata/clusters/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden new file mode 100644 index 000000000000..a415de533fac --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden @@ -0,0 +1,143 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "lbPolicy": "CLUSTER_PROVIDED", + "name": "original-destination", + "type": "ORIGINAL_DST" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/connect-proxy-without-tproxy-and-permissive-mtls.latest.golden b/agent/xds/testdata/clusters/connect-proxy-without-tproxy-and-permissive-mtls.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/connect-proxy-without-tproxy-and-permissive-mtls.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/custom-limits-max-connections-only.latest.golden b/agent/xds/testdata/clusters/custom-limits-max-connections-only.latest.golden index f2f27cd06f27..afeebfc8e918 100644 --- a/agent/xds/testdata/clusters/custom-limits-max-connections-only.latest.golden +++ b/agent/xds/testdata/clusters/custom-limits-max-connections-only.latest.golden @@ -40,9 +40,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -90,12 +93,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/custom-limits-set-to-zero.latest.golden b/agent/xds/testdata/clusters/custom-limits-set-to-zero.latest.golden index d3e8277df935..957d75924533 100644 --- a/agent/xds/testdata/clusters/custom-limits-set-to-zero.latest.golden +++ b/agent/xds/testdata/clusters/custom-limits-set-to-zero.latest.golden @@ -42,9 +42,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -94,12 +97,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/custom-limits.latest.golden b/agent/xds/testdata/clusters/custom-limits.latest.golden index ac187b5ab003..45e81b64d1c0 100644 --- a/agent/xds/testdata/clusters/custom-limits.latest.golden +++ b/agent/xds/testdata/clusters/custom-limits.latest.golden @@ -42,9 +42,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -94,12 +97,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/custom-local-app.latest.golden b/agent/xds/testdata/clusters/custom-local-app.latest.golden index 9e5f75c55b3e..419125274a24 100644 --- a/agent/xds/testdata/clusters/custom-local-app.latest.golden +++ b/agent/xds/testdata/clusters/custom-local-app.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/custom-max-inbound-connections.latest.golden b/agent/xds/testdata/clusters/custom-max-inbound-connections.latest.golden index 8763544644cb..d379a3244719 100644 --- a/agent/xds/testdata/clusters/custom-max-inbound-connections.latest.golden +++ b/agent/xds/testdata/clusters/custom-max-inbound-connections.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden b/agent/xds/testdata/clusters/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden index 7ccbda45902d..9ffc5c8bb741 100644 --- a/agent/xds/testdata/clusters/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden +++ b/agent/xds/testdata/clusters/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden @@ -40,9 +40,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -84,12 +87,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/custom-passive-healthcheck.latest.golden b/agent/xds/testdata/clusters/custom-passive-healthcheck.latest.golden index 2f501e3ee857..bbc59af99a6a 100644 --- a/agent/xds/testdata/clusters/custom-passive-healthcheck.latest.golden +++ b/agent/xds/testdata/clusters/custom-passive-healthcheck.latest.golden @@ -40,9 +40,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -84,12 +87,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/custom-public-listener-http-2.latest.golden b/agent/xds/testdata/clusters/custom-public-listener-http-2.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/custom-public-listener-http-2.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/custom-public-listener-http-missing.latest.golden b/agent/xds/testdata/clusters/custom-public-listener-http-missing.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/custom-public-listener-http-missing.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/custom-public-listener-http.latest.golden b/agent/xds/testdata/clusters/custom-public-listener-http.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/custom-public-listener-http.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/custom-public-listener.latest.golden b/agent/xds/testdata/clusters/custom-public-listener.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/custom-public-listener.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/custom-timeouts.latest.golden b/agent/xds/testdata/clusters/custom-timeouts.latest.golden index 688adfb4c569..a5443ef29929 100644 --- a/agent/xds/testdata/clusters/custom-timeouts.latest.golden +++ b/agent/xds/testdata/clusters/custom-timeouts.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/custom-trace-listener.latest.golden b/agent/xds/testdata/clusters/custom-trace-listener.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/custom-trace-listener.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/custom-upstream-default-chain.latest.golden b/agent/xds/testdata/clusters/custom-upstream-default-chain.latest.golden index 8ec7314419f1..537e24c4187c 100644 --- a/agent/xds/testdata/clusters/custom-upstream-default-chain.latest.golden +++ b/agent/xds/testdata/clusters/custom-upstream-default-chain.latest.golden @@ -30,12 +30,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { @@ -113,9 +119,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/custom-upstream-ignored-with-disco-chain.latest.golden b/agent/xds/testdata/clusters/custom-upstream-ignored-with-disco-chain.latest.golden new file mode 100644 index 000000000000..9a2a48fc5ade --- /dev/null +++ b/agent/xds/testdata/clusters/custom-upstream-ignored-with-disco-chain.latest.golden @@ -0,0 +1,204 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "clusterType": { + "name": "envoy.clusters.aggregate", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.clusters.aggregate.v3.ClusterConfig", + "clusters": [ + "failover-target~0~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "failover-target~1~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + } + }, + "connectTimeout": "33s", + "lbPolicy": "CLUSTER_PROVIDED", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "failover-target~0~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "failover-target~0~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "failover-target~1~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "failover-target~1~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/fail" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "fail.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/custom-upstream-with-prepared-query.latest.golden b/agent/xds/testdata/clusters/custom-upstream-with-prepared-query.latest.golden index b82511b15e2f..364dbe018492 100644 --- a/agent/xds/testdata/clusters/custom-upstream-with-prepared-query.latest.golden +++ b/agent/xds/testdata/clusters/custom-upstream-with-prepared-query.latest.golden @@ -79,12 +79,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/custom-upstream.latest.golden b/agent/xds/testdata/clusters/custom-upstream.latest.golden index 8ec7314419f1..537e24c4187c 100644 --- a/agent/xds/testdata/clusters/custom-upstream.latest.golden +++ b/agent/xds/testdata/clusters/custom-upstream.latest.golden @@ -30,12 +30,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { @@ -113,9 +119,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/defaults.latest.golden b/agent/xds/testdata/clusters/defaults.latest.golden index 5a25e882ab31..3f142f8aa455 100644 --- a/agent/xds/testdata/clusters/defaults.latest.golden +++ b/agent/xds/testdata/clusters/defaults.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/downstream-service-with-unix-sockets.latest.golden b/agent/xds/testdata/clusters/downstream-service-with-unix-sockets.latest.golden index a6d0025aeca3..8f986425eb80 100644 --- a/agent/xds/testdata/clusters/downstream-service-with-unix-sockets.latest.golden +++ b/agent/xds/testdata/clusters/downstream-service-with-unix-sockets.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/expose-checks-grpc.latest.golden b/agent/xds/testdata/clusters/expose-checks-grpc.latest.golden new file mode 100644 index 000000000000..0c94321dbb68 --- /dev/null +++ b/agent/xds/testdata/clusters/expose-checks-grpc.latest.golden @@ -0,0 +1,65 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "exposed_cluster_9090", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9090 + } + } + } + } + ] + } + ] + }, + "name": "exposed_cluster_9090", + "type": "STATIC", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/expose-checks-http-with-bind-override.latest.golden b/agent/xds/testdata/clusters/expose-checks-http-with-bind-override.latest.golden new file mode 100644 index 000000000000..59d8b46b80e2 --- /dev/null +++ b/agent/xds/testdata/clusters/expose-checks-http-with-bind-override.latest.golden @@ -0,0 +1,57 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "exposed_cluster_8181", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8181 + } + } + } + } + ] + } + ] + }, + "name": "exposed_cluster_8181", + "type": "STATIC" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/expose-checks-http.latest.golden b/agent/xds/testdata/clusters/expose-checks-http.latest.golden new file mode 100644 index 000000000000..59d8b46b80e2 --- /dev/null +++ b/agent/xds/testdata/clusters/expose-checks-http.latest.golden @@ -0,0 +1,57 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "exposed_cluster_8181", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8181 + } + } + } + } + ] + } + ] + }, + "name": "exposed_cluster_8181", + "type": "STATIC" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/grpc-public-listener.latest.golden b/agent/xds/testdata/clusters/grpc-public-listener.latest.golden new file mode 100644 index 000000000000..dc6c3c60d727 --- /dev/null +++ b/agent/xds/testdata/clusters/grpc-public-listener.latest.golden @@ -0,0 +1,145 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "useDownstreamProtocolConfig": { + "http2ProtocolOptions": {}, + "httpProtocolOptions": {} + } + } + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/http-listener-with-timeouts.latest.golden b/agent/xds/testdata/clusters/http-listener-with-timeouts.latest.golden new file mode 100644 index 000000000000..a5443ef29929 --- /dev/null +++ b/agent/xds/testdata/clusters/http-listener-with-timeouts.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "1.234s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/http-public-listener-no-xfcc.latest.golden b/agent/xds/testdata/clusters/http-public-listener-no-xfcc.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/http-public-listener-no-xfcc.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/http-public-listener.latest.golden b/agent/xds/testdata/clusters/http-public-listener.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/http-public-listener.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/http-upstream.latest.golden b/agent/xds/testdata/clusters/http-upstream.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/http-upstream.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/http2-public-listener.latest.golden b/agent/xds/testdata/clusters/http2-public-listener.latest.golden new file mode 100644 index 000000000000..dc6c3c60d727 --- /dev/null +++ b/agent/xds/testdata/clusters/http2-public-listener.latest.golden @@ -0,0 +1,145 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "useDownstreamProtocolConfig": { + "http2ProtocolOptions": {}, + "httpProtocolOptions": {} + } + } + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-config-entry-nil.latest.golden b/agent/xds/testdata/clusters/ingress-config-entry-nil.latest.golden new file mode 100644 index 000000000000..04106b67f20a --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-config-entry-nil.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-defaults-no-chain.latest.golden b/agent/xds/testdata/clusters/ingress-defaults-no-chain.latest.golden new file mode 100644 index 000000000000..04106b67f20a --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-defaults-no-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-gateway-bind-addrs.latest.golden b/agent/xds/testdata/clusters/ingress-gateway-bind-addrs.latest.golden new file mode 100644 index 000000000000..6e7724c2e048 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-gateway-bind-addrs.latest.golden @@ -0,0 +1,58 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden b/agent/xds/testdata/clusters/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden index 5451b36da487..8304805b9e35 100644 --- a/agent/xds/testdata/clusters/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden +++ b/agent/xds/testdata/clusters/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden @@ -39,9 +39,12 @@ ] }, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-gateway-with-tls-outgoing-max-version.latest.golden b/agent/xds/testdata/clusters/ingress-gateway-with-tls-outgoing-max-version.latest.golden index 6e1bd3beafd1..6965884abf6a 100644 --- a/agent/xds/testdata/clusters/ingress-gateway-with-tls-outgoing-max-version.latest.golden +++ b/agent/xds/testdata/clusters/ingress-gateway-with-tls-outgoing-max-version.latest.golden @@ -36,9 +36,12 @@ "tlsMaximumProtocolVersion": "TLSv1_2" }, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-gateway-with-tls-outgoing-min-version.latest.golden b/agent/xds/testdata/clusters/ingress-gateway-with-tls-outgoing-min-version.latest.golden index 17b04f2d27d0..5750801ba4b2 100644 --- a/agent/xds/testdata/clusters/ingress-gateway-with-tls-outgoing-min-version.latest.golden +++ b/agent/xds/testdata/clusters/ingress-gateway-with-tls-outgoing-min-version.latest.golden @@ -36,9 +36,12 @@ "tlsMinimumProtocolVersion": "TLSv1_3" }, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-gateway.latest.golden b/agent/xds/testdata/clusters/ingress-gateway.latest.golden index 699ed14e9cc2..6e7724c2e048 100644 --- a/agent/xds/testdata/clusters/ingress-gateway.latest.golden +++ b/agent/xds/testdata/clusters/ingress-gateway.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-grpc-multiple-services.latest.golden b/agent/xds/testdata/clusters/ingress-grpc-multiple-services.latest.golden new file mode 100644 index 000000000000..2d1a992e00b1 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-grpc-multiple-services.latest.golden @@ -0,0 +1,125 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "22s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/bar" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "22s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/foo" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-http-multiple-services.latest.golden b/agent/xds/testdata/clusters/ingress-http-multiple-services.latest.golden new file mode 100644 index 000000000000..95d7aaa412c6 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-http-multiple-services.latest.golden @@ -0,0 +1,211 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "22s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/bar" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "baz.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "baz.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/baz" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "baz.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "22s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/foo" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "qux.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "qux.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/qux" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "qux.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-lb-in-resolver.latest.golden b/agent/xds/testdata/clusters/ingress-lb-in-resolver.latest.golden index ff94a34cac86..e0c6fb23ccc9 100644 --- a/agent/xds/testdata/clusters/ingress-lb-in-resolver.latest.golden +++ b/agent/xds/testdata/clusters/ingress-lb-in-resolver.latest.golden @@ -39,9 +39,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -87,9 +90,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/something-else" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/something-else" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-multiple-listeners-duplicate-service.latest.golden b/agent/xds/testdata/clusters/ingress-multiple-listeners-duplicate-service.latest.golden index 3d83307a008d..bf07a9f1b327 100644 --- a/agent/xds/testdata/clusters/ingress-multiple-listeners-duplicate-service.latest.golden +++ b/agent/xds/testdata/clusters/ingress-multiple-listeners-duplicate-service.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/bar" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/bar" + }, + "sanType": "URI" } ], "trustedCa": { @@ -82,9 +85,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/foo" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/foo" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-splitter-with-resolver-redirect.latest.golden b/agent/xds/testdata/clusters/ingress-splitter-with-resolver-redirect.latest.golden index 5280ee7a98b8..9a84de6484e9 100644 --- a/agent/xds/testdata/clusters/ingress-splitter-with-resolver-redirect.latest.golden +++ b/agent/xds/testdata/clusters/ingress-splitter-with-resolver-redirect.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -82,9 +85,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-chain-and-failover-to-cluster-peer.latest.golden b/agent/xds/testdata/clusters/ingress-with-chain-and-failover-to-cluster-peer.latest.golden index 17649071505c..399ab9722a15 100644 --- a/agent/xds/testdata/clusters/ingress-with-chain-and-failover-to-cluster-peer.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-chain-and-failover-to-cluster-peer.latest.golden @@ -52,9 +52,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -100,9 +103,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-chain-and-failover.latest.golden b/agent/xds/testdata/clusters/ingress-with-chain-and-failover.latest.golden index 8a2f77a98f71..0811cc28b07f 100644 --- a/agent/xds/testdata/clusters/ingress-with-chain-and-failover.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-chain-and-failover.latest.golden @@ -52,9 +52,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -100,9 +103,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/fail" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/fail" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-chain-and-router-header-manip.latest.golden b/agent/xds/testdata/clusters/ingress-with-chain-and-router-header-manip.latest.golden new file mode 100644 index 000000000000..4c3b758e475d --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-chain-and-router-header-manip.latest.golden @@ -0,0 +1,1537 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/big-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/empty-match-1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/empty-match-2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/goldilocks-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-exact-with-method" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-not-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-prefix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-suffix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/header-manip" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/idle-timeout" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/just-methods" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/lil-bit-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/nil-match" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix-rewrite-1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix-rewrite-2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/req-timeout" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-all" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-codes" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-connect" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-reset" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-chain-and-router.latest.golden b/agent/xds/testdata/clusters/ingress-with-chain-and-router.latest.golden new file mode 100644 index 000000000000..4c3b758e475d --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-chain-and-router.latest.golden @@ -0,0 +1,1537 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/big-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/empty-match-1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/empty-match-2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/goldilocks-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-exact-with-method" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-not-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-prefix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-suffix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/header-manip" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/idle-timeout" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/just-methods" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/lil-bit-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/nil-match" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix-rewrite-1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix-rewrite-2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/req-timeout" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-all" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-codes" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-connect" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-reset" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-chain-and-splitter.latest.golden b/agent/xds/testdata/clusters/ingress-with-chain-and-splitter.latest.golden new file mode 100644 index 000000000000..9ae1398b774a --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-chain-and-splitter.latest.golden @@ -0,0 +1,211 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/big-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "25s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/goldilocks-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/lil-bit-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-chain-external-sni.latest.golden b/agent/xds/testdata/clusters/ingress-with-chain-external-sni.latest.golden index e1dedd23fc2b..7491cea55040 100644 --- a/agent/xds/testdata/clusters/ingress-with-chain-external-sni.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-chain-external-sni.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-chain.latest.golden b/agent/xds/testdata/clusters/ingress-with-chain.latest.golden index 3c3dec4ccf0e..bd5b312d1a80 100644 --- a/agent/xds/testdata/clusters/ingress-with-chain.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-chain.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-defaults-passive-health-check.latest.golden b/agent/xds/testdata/clusters/ingress-with-defaults-passive-health-check.latest.golden index 854e52edbd2e..16435630b65a 100644 --- a/agent/xds/testdata/clusters/ingress-with-defaults-passive-health-check.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-defaults-passive-health-check.latest.golden @@ -47,9 +47,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-defaults-service-max-connections.latest.golden b/agent/xds/testdata/clusters/ingress-with-defaults-service-max-connections.latest.golden index bd9ac9dcb661..3013a698d324 100644 --- a/agent/xds/testdata/clusters/ingress-with-defaults-service-max-connections.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-defaults-service-max-connections.latest.golden @@ -42,9 +42,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-grpc-router.latest.golden b/agent/xds/testdata/clusters/ingress-with-grpc-router.latest.golden new file mode 100644 index 000000000000..2eefc5a5c143 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-grpc-router.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-grpc-single-tls-listener.latest.golden b/agent/xds/testdata/clusters/ingress-with-grpc-single-tls-listener.latest.golden new file mode 100644 index 000000000000..f30230437d67 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-grpc-single-tls-listener.latest.golden @@ -0,0 +1,125 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-http2-and-grpc-multiple-tls-listener.latest.golden b/agent/xds/testdata/clusters/ingress-with-http2-and-grpc-multiple-tls-listener.latest.golden new file mode 100644 index 000000000000..f30230437d67 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-http2-and-grpc-multiple-tls-listener.latest.golden @@ -0,0 +1,125 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-http2-single-tls-listener.latest.golden b/agent/xds/testdata/clusters/ingress-with-http2-single-tls-listener.latest.golden new file mode 100644 index 000000000000..f30230437d67 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-http2-single-tls-listener.latest.golden @@ -0,0 +1,125 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-overwrite-defaults-passive-health-check.latest.golden b/agent/xds/testdata/clusters/ingress-with-overwrite-defaults-passive-health-check.latest.golden index 63621f39f60a..48fdd7b0677e 100644 --- a/agent/xds/testdata/clusters/ingress-with-overwrite-defaults-passive-health-check.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-overwrite-defaults-passive-health-check.latest.golden @@ -46,9 +46,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-overwrite-defaults-service-max-connections.latest.golden b/agent/xds/testdata/clusters/ingress-with-overwrite-defaults-service-max-connections.latest.golden index f38254450d94..50465fe3433a 100644 --- a/agent/xds/testdata/clusters/ingress-with-overwrite-defaults-service-max-connections.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-overwrite-defaults-service-max-connections.latest.golden @@ -41,9 +41,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-sds-listener+service-level.latest.golden b/agent/xds/testdata/clusters/ingress-with-sds-listener+service-level.latest.golden new file mode 100644 index 000000000000..e18feea7c455 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-sds-listener+service-level.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-sds-listener-gw-level-http.latest.golden b/agent/xds/testdata/clusters/ingress-with-sds-listener-gw-level-http.latest.golden new file mode 100644 index 000000000000..8c2b57684ff7 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-sds-listener-gw-level-http.latest.golden @@ -0,0 +1,58 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/http" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-sds-listener-gw-level-mixed-tls.latest.golden b/agent/xds/testdata/clusters/ingress-with-sds-listener-gw-level-mixed-tls.latest.golden new file mode 100644 index 000000000000..4457208992c5 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-sds-listener-gw-level-mixed-tls.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "insecure.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "insecure.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/insecure" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "insecure.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "secure.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "secure.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/secure" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "secure.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-sds-listener-gw-level.latest.golden b/agent/xds/testdata/clusters/ingress-with-sds-listener-gw-level.latest.golden new file mode 100644 index 000000000000..6e7724c2e048 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-sds-listener-gw-level.latest.golden @@ -0,0 +1,58 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-sds-listener-level-wildcard.latest.golden b/agent/xds/testdata/clusters/ingress-with-sds-listener-level-wildcard.latest.golden new file mode 100644 index 000000000000..50e5df3d2f5f --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-sds-listener-level-wildcard.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "22s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/foo" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "22s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/web" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-sds-listener-level.latest.golden b/agent/xds/testdata/clusters/ingress-with-sds-listener-level.latest.golden new file mode 100644 index 000000000000..50e5df3d2f5f --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-sds-listener-level.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "22s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/foo" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "22s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/web" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-sds-listener-listener-level.latest.golden b/agent/xds/testdata/clusters/ingress-with-sds-listener-listener-level.latest.golden new file mode 100644 index 000000000000..6e7724c2e048 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-sds-listener-listener-level.latest.golden @@ -0,0 +1,58 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-sds-service-level-2.latest.golden b/agent/xds/testdata/clusters/ingress-with-sds-service-level-2.latest.golden new file mode 100644 index 000000000000..50e5df3d2f5f --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-sds-service-level-2.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "22s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/foo" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "22s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/web" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-sds-service-level-mixed-no-tls.latest.golden b/agent/xds/testdata/clusters/ingress-with-sds-service-level-mixed-no-tls.latest.golden new file mode 100644 index 000000000000..e18feea7c455 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-sds-service-level-mixed-no-tls.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-sds-service-level-mixed-tls.latest.golden b/agent/xds/testdata/clusters/ingress-with-sds-service-level-mixed-tls.latest.golden new file mode 100644 index 000000000000..50e5df3d2f5f --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-sds-service-level-mixed-tls.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "22s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/foo" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "22s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/web" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-sds-service-level.latest.golden b/agent/xds/testdata/clusters/ingress-with-sds-service-level.latest.golden new file mode 100644 index 000000000000..e18feea7c455 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-sds-service-level.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-service-max-connections.latest.golden b/agent/xds/testdata/clusters/ingress-with-service-max-connections.latest.golden index e8c73c3b771c..c3f3e2bea7eb 100644 --- a/agent/xds/testdata/clusters/ingress-with-service-max-connections.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-service-max-connections.latest.golden @@ -40,9 +40,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-service-passive-health-check.latest.golden b/agent/xds/testdata/clusters/ingress-with-service-passive-health-check.latest.golden index 5bea45a5757c..89cbcabf345b 100644 --- a/agent/xds/testdata/clusters/ingress-with-service-passive-health-check.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-service-passive-health-check.latest.golden @@ -44,9 +44,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-single-tls-listener.latest.golden b/agent/xds/testdata/clusters/ingress-with-single-tls-listener.latest.golden new file mode 100644 index 000000000000..e18feea7c455 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-single-tls-listener.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden index 36da92cce8f2..a8b6c5558122 100644 --- a/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden @@ -53,9 +53,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -101,9 +104,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -149,9 +155,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden b/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden index 36da92cce8f2..a8b6c5558122 100644 --- a/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden @@ -53,9 +53,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -101,9 +104,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -149,9 +155,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden index 36da92cce8f2..a8b6c5558122 100644 --- a/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden @@ -53,9 +53,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -101,9 +104,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -149,9 +155,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden index 36da92cce8f2..a8b6c5558122 100644 --- a/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden @@ -53,9 +53,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -101,9 +104,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -149,9 +155,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden index 37a8bbfcdc17..0f5322612523 100644 --- a/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden @@ -52,9 +52,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -100,9 +103,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-local-gateway.latest.golden b/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-local-gateway.latest.golden index 37a8bbfcdc17..0f5322612523 100644 --- a/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-local-gateway.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-local-gateway.latest.golden @@ -52,9 +52,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -100,9 +103,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden index 37a8bbfcdc17..0f5322612523 100644 --- a/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden @@ -52,9 +52,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -100,9 +103,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-remote-gateway.latest.golden index 37a8bbfcdc17..0f5322612523 100644 --- a/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-remote-gateway.latest.golden +++ b/agent/xds/testdata/clusters/ingress-with-tcp-chain-failover-through-remote-gateway.latest.golden @@ -52,9 +52,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -100,9 +103,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/ingress-with-tls-listener-cipher-suites.latest.golden b/agent/xds/testdata/clusters/ingress-with-tls-listener-cipher-suites.latest.golden new file mode 100644 index 000000000000..6e7724c2e048 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-tls-listener-cipher-suites.latest.golden @@ -0,0 +1,58 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-tls-listener-max-version.latest.golden b/agent/xds/testdata/clusters/ingress-with-tls-listener-max-version.latest.golden new file mode 100644 index 000000000000..6e7724c2e048 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-tls-listener-max-version.latest.golden @@ -0,0 +1,58 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-tls-listener-min-version.latest.golden b/agent/xds/testdata/clusters/ingress-with-tls-listener-min-version.latest.golden new file mode 100644 index 000000000000..6e7724c2e048 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-tls-listener-min-version.latest.golden @@ -0,0 +1,58 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-tls-listener.latest.golden b/agent/xds/testdata/clusters/ingress-with-tls-listener.latest.golden new file mode 100644 index 000000000000..6e7724c2e048 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-tls-listener.latest.golden @@ -0,0 +1,58 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-tls-min-version-listeners-gateway-defaults.latest.golden b/agent/xds/testdata/clusters/ingress-with-tls-min-version-listeners-gateway-defaults.latest.golden new file mode 100644 index 000000000000..904f1a4f1bf9 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-tls-min-version-listeners-gateway-defaults.latest.golden @@ -0,0 +1,211 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s3" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s4.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s4.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s4" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s4.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden b/agent/xds/testdata/clusters/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden new file mode 100644 index 000000000000..e18feea7c455 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-tls-mixed-listeners.latest.golden b/agent/xds/testdata/clusters/ingress-with-tls-mixed-listeners.latest.golden new file mode 100644 index 000000000000..e18feea7c455 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-tls-mixed-listeners.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-tls-mixed-max-version-listeners.latest.golden b/agent/xds/testdata/clusters/ingress-with-tls-mixed-max-version-listeners.latest.golden new file mode 100644 index 000000000000..a25ed52fea61 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-tls-mixed-max-version-listeners.latest.golden @@ -0,0 +1,160 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s3" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/ingress-with-tls-mixed-min-version-listeners.latest.golden b/agent/xds/testdata/clusters/ingress-with-tls-mixed-min-version-listeners.latest.golden new file mode 100644 index 000000000000..a25ed52fea61 --- /dev/null +++ b/agent/xds/testdata/clusters/ingress-with-tls-mixed-min-version-listeners.latest.golden @@ -0,0 +1,160 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/s3" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/listener-balance-inbound-connections.latest.golden b/agent/xds/testdata/clusters/listener-balance-inbound-connections.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/listener-balance-inbound-connections.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/listener-balance-outbound-connections-bind-port.latest.golden b/agent/xds/testdata/clusters/listener-balance-outbound-connections-bind-port.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/listener-balance-outbound-connections-bind-port.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/listener-bind-address-port.latest.golden b/agent/xds/testdata/clusters/listener-bind-address-port.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/listener-bind-address-port.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/listener-bind-address.latest.golden b/agent/xds/testdata/clusters/listener-bind-address.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/listener-bind-address.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/listener-bind-port.latest.golden b/agent/xds/testdata/clusters/listener-bind-port.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/listener-bind-port.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/listener-max-inbound-connections.latest.golden b/agent/xds/testdata/clusters/listener-max-inbound-connections.latest.golden new file mode 100644 index 000000000000..9d96abda6a54 --- /dev/null +++ b/agent/xds/testdata/clusters/listener-max-inbound-connections.latest.golden @@ -0,0 +1,143 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": { + "thresholds": [ + { + "maxConnections": 222 + } + ] + }, + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/listener-unix-domain-socket.latest.golden b/agent/xds/testdata/clusters/listener-unix-domain-socket.latest.golden new file mode 100644 index 000000000000..3f142f8aa455 --- /dev/null +++ b/agent/xds/testdata/clusters/listener-unix-domain-socket.latest.golden @@ -0,0 +1,136 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/local-mesh-gateway-with-peered-upstreams.latest.golden b/agent/xds/testdata/clusters/local-mesh-gateway-with-peered-upstreams.latest.golden index 018997d5d0b8..1d8fd606ff65 100644 --- a/agent/xds/testdata/clusters/local-mesh-gateway-with-peered-upstreams.latest.golden +++ b/agent/xds/testdata/clusters/local-mesh-gateway-with-peered-upstreams.latest.golden @@ -77,9 +77,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/payments" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/payments" + }, + "sanType": "URI" } ], "trustedCa": { @@ -126,9 +129,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/refunds" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/refunds" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/mesh-gateway-custom-addresses.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-custom-addresses.latest.golden new file mode 100644 index 000000000000..caa140aac2d5 --- /dev/null +++ b/agent/xds/testdata/clusters/mesh-gateway-custom-addresses.latest.golden @@ -0,0 +1,106 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-west-2.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-east-1.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/mesh-gateway-default-service-subset.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-default-service-subset.latest.golden new file mode 100644 index 000000000000..fb63679d49ba --- /dev/null +++ b/agent/xds/testdata/clusters/mesh-gateway-default-service-subset.latest.golden @@ -0,0 +1,158 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-west-2.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-east-1.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "v1.foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "v2.foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/mesh-gateway-newer-information-in-federation-states.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-newer-information-in-federation-states.latest.golden new file mode 100644 index 000000000000..caa140aac2d5 --- /dev/null +++ b/agent/xds/testdata/clusters/mesh-gateway-newer-information-in-federation-states.latest.golden @@ -0,0 +1,106 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-west-2.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-east-1.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/mesh-gateway-older-information-in-federation-states.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-older-information-in-federation-states.latest.golden new file mode 100644 index 000000000000..caa140aac2d5 --- /dev/null +++ b/agent/xds/testdata/clusters/mesh-gateway-older-information-in-federation-states.latest.golden @@ -0,0 +1,106 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-west-2.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-east-1.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/mesh-gateway-service-subsets2.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-service-subsets2.latest.golden new file mode 100644 index 000000000000..fb63679d49ba --- /dev/null +++ b/agent/xds/testdata/clusters/mesh-gateway-service-subsets2.latest.golden @@ -0,0 +1,158 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-west-2.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-east-1.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "v1.foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "v2.foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/mesh-gateway-tagged-addresses.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-tagged-addresses.latest.golden new file mode 100644 index 000000000000..caa140aac2d5 --- /dev/null +++ b/agent/xds/testdata/clusters/mesh-gateway-tagged-addresses.latest.golden @@ -0,0 +1,106 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-west-2.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-east-1.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden index f420e3236f1c..d9abfdd6d72d 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden @@ -73,9 +73,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/alt" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/alt" + }, + "sanType": "URI" } ], "trustedCa": { @@ -121,9 +124,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -169,9 +175,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/api" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/api" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http.latest.golden index 3c41ffedbce9..608443d6333a 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http.latest.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http.latest.golden @@ -47,9 +47,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/bar" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/bar" + }, + "sanType": "URI" } ], "trustedCa": { @@ -95,9 +98,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/foo" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/foo" + }, + "sanType": "URI" } ], "trustedCa": { @@ -143,9 +149,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/gir" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/gir" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/mesh-gateway-with-limits.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-with-limits.latest.golden new file mode 100644 index 000000000000..5be607cf8ce4 --- /dev/null +++ b/agent/xds/testdata/clusters/mesh-gateway-with-limits.latest.golden @@ -0,0 +1,151 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": { + "thresholds": [ + { + "maxConnections": 1, + "maxPendingRequests": 10, + "maxRequests": 100 + } + ] + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": { + "thresholds": [ + { + "maxConnections": 1, + "maxPendingRequests": 10, + "maxRequests": 100 + } + ] + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": { + "thresholds": [ + { + "maxConnections": 1, + "maxPendingRequests": 10, + "maxRequests": 100 + } + ] + }, + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-west-2.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": { + "thresholds": [ + { + "maxConnections": 1, + "maxPendingRequests": 10, + "maxRequests": 100 + } + ] + }, + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-east-1.elb.notaws.com", + "portValue": 443 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": { + "thresholds": [ + { + "maxConnections": 1, + "maxPendingRequests": 10, + "maxRequests": 100 + } + ] + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/splitter-with-resolver-redirect.latest.golden b/agent/xds/testdata/clusters/splitter-with-resolver-redirect.latest.golden index 72e8c720e9b2..e77c9cb11906 100644 --- a/agent/xds/testdata/clusters/splitter-with-resolver-redirect.latest.golden +++ b/agent/xds/testdata/clusters/splitter-with-resolver-redirect.latest.golden @@ -30,12 +30,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { @@ -106,9 +112,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -154,9 +163,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/telemetry-collector.latest.golden b/agent/xds/testdata/clusters/telemetry-collector.latest.golden index d9c8f4f8b8cc..1c5278843b5c 100644 --- a/agent/xds/testdata/clusters/telemetry-collector.latest.golden +++ b/agent/xds/testdata/clusters/telemetry-collector.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/consul-telemetry-collector" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/consul-telemetry-collector" + }, + "sanType": "URI" } ], "trustedCa": { @@ -90,9 +93,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -134,12 +140,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/terminating-gateway-custom-and-tagged-addresses.latest.golden b/agent/xds/testdata/clusters/terminating-gateway-custom-and-tagged-addresses.latest.golden new file mode 100644 index 000000000000..07cf25087bd1 --- /dev/null +++ b/agent/xds/testdata/clusters/terminating-gateway-custom-and-tagged-addresses.latest.golden @@ -0,0 +1,148 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "api.altdomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "filename": "api.cert.pem" + }, + "privateKey": { + "filename": "api.key.pem" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "cache.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "db.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/terminating-gateway-custom-trace-listener.latest.golden b/agent/xds/testdata/clusters/terminating-gateway-custom-trace-listener.latest.golden new file mode 100644 index 000000000000..07cf25087bd1 --- /dev/null +++ b/agent/xds/testdata/clusters/terminating-gateway-custom-trace-listener.latest.golden @@ -0,0 +1,148 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "api.altdomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "filename": "api.cert.pem" + }, + "privateKey": { + "filename": "api.key.pem" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "cache.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "db.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/terminating-gateway-default-service-subset.latest.golden b/agent/xds/testdata/clusters/terminating-gateway-default-service-subset.latest.golden new file mode 100644 index 000000000000..067195261be8 --- /dev/null +++ b/agent/xds/testdata/clusters/terminating-gateway-default-service-subset.latest.golden @@ -0,0 +1,202 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "api.altdomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "filename": "api.cert.pem" + }, + "privateKey": { + "filename": "api.key.pem" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "cache.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "db.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/terminating-gateway-lb-config-no-hash-policies.latest.golden b/agent/xds/testdata/clusters/terminating-gateway-lb-config-no-hash-policies.latest.golden new file mode 100644 index 000000000000..2820af6f1e97 --- /dev/null +++ b/agent/xds/testdata/clusters/terminating-gateway-lb-config-no-hash-policies.latest.golden @@ -0,0 +1,217 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "api.altdomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "filename": "api.cert.pem" + }, + "privateKey": { + "filename": "api.key.pem" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "cache.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "db.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "lbPolicy": "RING_HASH", + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "ringHashLbConfig": { + "maximumRingSize": "50", + "minimumRingSize": "20" + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "lbPolicy": "RING_HASH", + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "ringHashLbConfig": { + "maximumRingSize": "50", + "minimumRingSize": "20" + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "lbPolicy": "RING_HASH", + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "ringHashLbConfig": { + "maximumRingSize": "50", + "minimumRingSize": "20" + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/terminating-gateway-no-api-cert.latest.golden b/agent/xds/testdata/clusters/terminating-gateway-no-api-cert.latest.golden new file mode 100644 index 000000000000..07cf25087bd1 --- /dev/null +++ b/agent/xds/testdata/clusters/terminating-gateway-no-api-cert.latest.golden @@ -0,0 +1,148 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "api.altdomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "filename": "api.cert.pem" + }, + "privateKey": { + "filename": "api.key.pem" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "cache.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "db.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/terminating-gateway-sni.latest.golden b/agent/xds/testdata/clusters/terminating-gateway-sni.latest.golden index 160e9bfdffcd..190301470ad0 100644 --- a/agent/xds/testdata/clusters/terminating-gateway-sni.latest.golden +++ b/agent/xds/testdata/clusters/terminating-gateway-sni.latest.golden @@ -46,9 +46,30 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "bar.com" + "matcher": { + "exact": "bar.com" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "bar.com" + }, + "sanType": "DNS" + }, + { + "matcher": { + "exact": "bar.com" + }, + "sanType": "EMAIL" + }, + { + "matcher": { + "exact": "bar.com" + }, + "sanType": "IP_ADDRESS" } ], "trustedCa": { @@ -139,9 +160,30 @@ "commonTlsContext": { "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "foo.com" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "foo.com" + }, + "sanType": "DNS" + }, + { + "matcher": { + "exact": "foo.com" + }, + "sanType": "EMAIL" + }, { - "exact": "foo.com" + "matcher": { + "exact": "foo.com" + }, + "sanType": "IP_ADDRESS" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/terminating-gateway-with-peer-trust-bundle.latest.golden b/agent/xds/testdata/clusters/terminating-gateway-with-peer-trust-bundle.latest.golden new file mode 100644 index 000000000000..07cf25087bd1 --- /dev/null +++ b/agent/xds/testdata/clusters/terminating-gateway-with-peer-trust-bundle.latest.golden @@ -0,0 +1,148 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "api.altdomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "filename": "api.cert.pem" + }, + "privateKey": { + "filename": "api.key.pem" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "cache.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "db.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/terminating-gateway-with-tls-incoming-cipher-suites.latest.golden b/agent/xds/testdata/clusters/terminating-gateway-with-tls-incoming-cipher-suites.latest.golden new file mode 100644 index 000000000000..07cf25087bd1 --- /dev/null +++ b/agent/xds/testdata/clusters/terminating-gateway-with-tls-incoming-cipher-suites.latest.golden @@ -0,0 +1,148 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "api.altdomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "filename": "api.cert.pem" + }, + "privateKey": { + "filename": "api.key.pem" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "cache.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "db.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/terminating-gateway-with-tls-incoming-max-version.latest.golden b/agent/xds/testdata/clusters/terminating-gateway-with-tls-incoming-max-version.latest.golden new file mode 100644 index 000000000000..07cf25087bd1 --- /dev/null +++ b/agent/xds/testdata/clusters/terminating-gateway-with-tls-incoming-max-version.latest.golden @@ -0,0 +1,148 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "api.altdomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "filename": "api.cert.pem" + }, + "privateKey": { + "filename": "api.key.pem" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "cache.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "db.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/terminating-gateway-with-tls-incoming-min-version.latest.golden b/agent/xds/testdata/clusters/terminating-gateway-with-tls-incoming-min-version.latest.golden new file mode 100644 index 000000000000..07cf25087bd1 --- /dev/null +++ b/agent/xds/testdata/clusters/terminating-gateway-with-tls-incoming-min-version.latest.golden @@ -0,0 +1,148 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "api.altdomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "filename": "api.cert.pem" + }, + "privateKey": { + "filename": "api.key.pem" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "cache.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "db.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/transparent-proxy-catalog-destinations-only.latest.golden b/agent/xds/testdata/clusters/transparent-proxy-catalog-destinations-only.latest.golden index 3a3556a8617d..13e985402b3e 100644 --- a/agent/xds/testdata/clusters/transparent-proxy-catalog-destinations-only.latest.golden +++ b/agent/xds/testdata/clusters/transparent-proxy-catalog-destinations-only.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { @@ -129,9 +138,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + }, + "sanType": "URI" } ], "trustedCa": { @@ -202,9 +214,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/no-endpoints" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/no-endpoints" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/transparent-proxy-destination-http.latest.golden b/agent/xds/testdata/clusters/transparent-proxy-destination-http.latest.golden index 43ffe1773a93..2c627cfb7a0d 100644 --- a/agent/xds/testdata/clusters/transparent-proxy-destination-http.latest.golden +++ b/agent/xds/testdata/clusters/transparent-proxy-destination-http.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -81,9 +84,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + }, + "sanType": "URI" } ], "trustedCa": { @@ -128,9 +134,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka2" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka2" + }, + "sanType": "URI" } ], "trustedCa": { @@ -175,9 +184,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka2" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka2" + }, + "sanType": "URI" } ], "trustedCa": { @@ -222,9 +234,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + }, + "sanType": "URI" } ], "trustedCa": { @@ -266,12 +281,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/transparent-proxy-destination.latest.golden b/agent/xds/testdata/clusters/transparent-proxy-destination.latest.golden index 3fdcc1c26486..3de286c87c10 100644 --- a/agent/xds/testdata/clusters/transparent-proxy-destination.latest.golden +++ b/agent/xds/testdata/clusters/transparent-proxy-destination.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -81,9 +84,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + }, + "sanType": "URI" } ], "trustedCa": { @@ -128,9 +134,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + }, + "sanType": "URI" } ], "trustedCa": { @@ -175,9 +184,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + }, + "sanType": "URI" } ], "trustedCa": { @@ -222,9 +234,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + }, + "sanType": "URI" } ], "trustedCa": { @@ -266,12 +281,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/transparent-proxy-dial-instances-directly.latest.golden b/agent/xds/testdata/clusters/transparent-proxy-dial-instances-directly.latest.golden index 490ef2d07c19..6e2925189657 100644 --- a/agent/xds/testdata/clusters/transparent-proxy-dial-instances-directly.latest.golden +++ b/agent/xds/testdata/clusters/transparent-proxy-dial-instances-directly.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { @@ -129,9 +138,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + }, + "sanType": "URI" } ], "trustedCa": { @@ -202,9 +214,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/mongo" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/mongo" + }, + "sanType": "URI" } ], "trustedCa": { @@ -246,9 +261,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + }, + "sanType": "URI" } ], "trustedCa": { @@ -283,9 +301,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/mongo" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/mongo" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/transparent-proxy-http-upstream.latest.golden b/agent/xds/testdata/clusters/transparent-proxy-http-upstream.latest.golden new file mode 100644 index 000000000000..a142ff7e2daf --- /dev/null +++ b/agent/xds/testdata/clusters/transparent-proxy-http-upstream.latest.golden @@ -0,0 +1,245 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "no-endpoints.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "no-endpoints.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/no-endpoints" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "no-endpoints.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "lbPolicy": "CLUSTER_PROVIDED", + "name": "original-destination", + "type": "ORIGINAL_DST" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/transparent-proxy-terminating-gateway-destinations-only.latest.golden b/agent/xds/testdata/clusters/transparent-proxy-terminating-gateway-destinations-only.latest.golden index 980d7f4ec7dd..ff66e6cc86ef 100644 --- a/agent/xds/testdata/clusters/transparent-proxy-terminating-gateway-destinations-only.latest.golden +++ b/agent/xds/testdata/clusters/transparent-proxy-terminating-gateway-destinations-only.latest.golden @@ -166,9 +166,30 @@ "commonTlsContext": { "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "api.test.com" + "matcher": { + "exact": "api.test.com" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "api.test.com" + }, + "sanType": "DNS" + }, + { + "matcher": { + "exact": "api.test.com" + }, + "sanType": "EMAIL" + }, + { + "matcher": { + "exact": "api.test.com" + }, + "sanType": "IP_ADDRESS" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/transparent-proxy-terminating-gateway.latest.golden b/agent/xds/testdata/clusters/transparent-proxy-terminating-gateway.latest.golden new file mode 100644 index 000000000000..e02609b18206 --- /dev/null +++ b/agent/xds/testdata/clusters/transparent-proxy-terminating-gateway.latest.golden @@ -0,0 +1,238 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/transparent-proxy-with-peered-upstreams.latest.golden b/agent/xds/testdata/clusters/transparent-proxy-with-peered-upstreams.latest.golden index 4e9ce5333bb6..f6804a2d93b3 100644 --- a/agent/xds/testdata/clusters/transparent-proxy-with-peered-upstreams.latest.golden +++ b/agent/xds/testdata/clusters/transparent-proxy-with-peered-upstreams.latest.golden @@ -35,9 +35,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/api-a" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/api-a" + }, + "sanType": "URI" } ], "trustedCa": { @@ -84,9 +87,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/db" + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/transparent-proxy-with-resolver-redirect-upstream.latest.golden b/agent/xds/testdata/clusters/transparent-proxy-with-resolver-redirect-upstream.latest.golden new file mode 100644 index 000000000000..23471f004b42 --- /dev/null +++ b/agent/xds/testdata/clusters/transparent-proxy-with-resolver-redirect-upstream.latest.golden @@ -0,0 +1,194 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "name": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "lbPolicy": "CLUSTER_PROVIDED", + "name": "original-destination", + "type": "ORIGINAL_DST" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/transparent-proxy.latest.golden b/agent/xds/testdata/clusters/transparent-proxy.latest.golden index fdc8e773170d..a142ff7e2daf 100644 --- a/agent/xds/testdata/clusters/transparent-proxy.latest.golden +++ b/agent/xds/testdata/clusters/transparent-proxy.latest.golden @@ -34,9 +34,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" } ], "trustedCa": { @@ -78,12 +81,18 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" }, { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" } ], "trustedCa": { @@ -129,9 +138,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + }, + "sanType": "URI" } ], "trustedCa": { @@ -202,9 +214,12 @@ ], "tlsParams": {}, "validationContext": { - "matchSubjectAltNames": [ + "matchTypedSubjectAltNames": [ { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/no-endpoints" + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/no-endpoints" + }, + "sanType": "URI" } ], "trustedCa": { diff --git a/agent/xds/testdata/clusters/xds-fetch-timeout-ms-ingress-with-router.latest.golden b/agent/xds/testdata/clusters/xds-fetch-timeout-ms-ingress-with-router.latest.golden new file mode 100644 index 000000000000..3e06a34c379e --- /dev/null +++ b/agent/xds/testdata/clusters/xds-fetch-timeout-ms-ingress-with-router.latest.golden @@ -0,0 +1,1567 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/big-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/empty-match-1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/empty-match-2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/goldilocks-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-exact-with-method" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-not-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-prefix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-suffix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/header-manip" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/idle-timeout" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/just-methods" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/lil-bit-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/nil-match" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix-rewrite-1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix-rewrite-2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/req-timeout" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-all" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-codes" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-connect" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-reset" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/xds-fetch-timeout-ms-mgw-peering.latest.golden b/agent/xds/testdata/clusters/xds-fetch-timeout-ms-mgw-peering.latest.golden new file mode 100644 index 000000000000..fb9645aac488 --- /dev/null +++ b/agent/xds/testdata/clusters/xds-fetch-timeout-ms-mgw-peering.latest.golden @@ -0,0 +1,205 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "exported~bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "exported~bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/bar" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "exported~foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "exported~foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/foo" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "exported~gir.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "exported~gir.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/gir" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "gir.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "gir.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/xds-fetch-timeout-ms-sidecar.latest.golden b/agent/xds/testdata/clusters/xds-fetch-timeout-ms-sidecar.latest.golden new file mode 100644 index 000000000000..47d7f6097812 --- /dev/null +++ b/agent/xds/testdata/clusters/xds-fetch-timeout-ms-sidecar.latest.golden @@ -0,0 +1,1646 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/big-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "33s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/empty-match-1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/empty-match-2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/goldilocks-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-exact-with-method" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-not-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-prefix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/hdr-suffix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/header-manip" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/idle-timeout" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/just-methods" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/lil-bit-side" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/nil-match" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix-rewrite-1" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix-rewrite-2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prefix" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-exact" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-present" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/prm-regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/regex" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/req-timeout" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-all" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-codes" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-connect" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/retry-reset" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/xds-fetch-timeout-ms-term-gw.latest.golden b/agent/xds/testdata/clusters/xds-fetch-timeout-ms-term-gw.latest.golden new file mode 100644 index 000000000000..739d942a5d6a --- /dev/null +++ b/agent/xds/testdata/clusters/xds-fetch-timeout-ms-term-gw.latest.golden @@ -0,0 +1,235 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "api.altdomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "filename": "api.cert.pem" + }, + "privateKey": { + "filename": "api.key.pem" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "cache.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "db.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "cache.mydomain", + "portValue": 8081 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "type": "LOGICAL_DNS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + }, + "type": "EDS" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden b/agent/xds/testdata/clusters/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden new file mode 100644 index 000000000000..2c176c84eefd --- /dev/null +++ b/agent/xds/testdata/clusters/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden @@ -0,0 +1,170 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "dnsLookupFamily": "V4_ONLY", + "dnsRefreshRate": "10s", + "loadAssignment": { + "clusterName": "payments.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "123.us-east-1.elb.notaws.com", + "portValue": 8443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "name": "payments.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", + "outlierDetection": { + "maxEjectionPercent": 100 + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/payments" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICczCCAdwCCQC3BLnEmLCrSjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCQVoxEjAQBgNVBAcMCUZsYWdzdGFmZjEMMAoGA1UECgwDRm9v\nMRAwDgYDVQQLDAdleGFtcGxlMQ8wDQYDVQQDDAZwZWVyLWExHTAbBgkqhkiG9w0B\nCQEWDmZvb0BwZWVyLWEuY29tMB4XDTIyMDUyNjAxMDQ0NFoXDTIzMDUyNjAxMDQ0\nNFowfjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkFaMRIwEAYDVQQHDAlGbGFnc3Rh\nZmYxDDAKBgNVBAoMA0ZvbzEQMA4GA1UECwwHZXhhbXBsZTEPMA0GA1UEAwwGcGVl\nci1hMR0wGwYJKoZIhvcNAQkBFg5mb29AcGVlci1hLmNvbTCBnzANBgkqhkiG9w0B\nAQEFAAOBjQAwgYkCgYEA2zFYGTbXDAntT5pLTpZ2+VTiqx4J63VRJH1kdu11f0FV\nc2jl1pqCuYDbQXknDU0Pv1Q5y0+nSAihD2KqGS571r+vHQiPtKYPYRqPEe9FzAhR\n2KhWH6v/tk5DG1HqOjV9/zWRKB12gdFNZZqnw/e7NjLNq3wZ2UAwxXip5uJ8uwMC\nAwEAATANBgkqhkiG9w0BAQsFAAOBgQC/CJ9Syf4aL91wZizKTejwouRYoWv4gRAk\nyto45ZcNMHfJ0G2z+XAMl9ZbQsLgXmzAx4IM6y5Jckq8pKC4PEijCjlKTktLHlEy\n0ggmFxtNB1tid2NC8dOzcQ3l45+gDjDqdILhAvLDjlAIebdkqVqb2CfFNW/I2CQH\nZAuKN1aoKA==\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "payments.default.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul" + } + }, + "type": "LOGICAL_DNS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "refunds.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", + "outlierDetection": { + "maxEjectionPercent": 100 + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/cloud-dc/svc/refunds" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICczCCAdwCCQC3BLnEmLCrSjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCQVoxEjAQBgNVBAcMCUZsYWdzdGFmZjEMMAoGA1UECgwDRm9v\nMRAwDgYDVQQLDAdleGFtcGxlMQ8wDQYDVQQDDAZwZWVyLWExHTAbBgkqhkiG9w0B\nCQEWDmZvb0BwZWVyLWEuY29tMB4XDTIyMDUyNjAxMDQ0NFoXDTIzMDUyNjAxMDQ0\nNFowfjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkFaMRIwEAYDVQQHDAlGbGFnc3Rh\nZmYxDDAKBgNVBAoMA0ZvbzEQMA4GA1UECwwHZXhhbXBsZTEPMA0GA1UEAwwGcGVl\nci1hMR0wGwYJKoZIhvcNAQkBFg5mb29AcGVlci1hLmNvbTCBnzANBgkqhkiG9w0B\nAQEFAAOBjQAwgYkCgYEA2zFYGTbXDAntT5pLTpZ2+VTiqx4J63VRJH1kdu11f0FV\nc2jl1pqCuYDbQXknDU0Pv1Q5y0+nSAihD2KqGS571r+vHQiPtKYPYRqPEe9FzAhR\n2KhWH6v/tk5DG1HqOjV9/zWRKB12gdFNZZqnw/e7NjLNq3wZ2UAwxXip5uJ8uwMC\nAwEAATANBgkqhkiG9w0BAQsFAAOBgQC/CJ9Syf4aL91wZizKTejwouRYoWv4gRAk\nyto45ZcNMHfJ0G2z+XAMl9ZbQsLgXmzAx4IM6y5Jckq8pKC4PEijCjlKTktLHlEy\n0ggmFxtNB1tid2NC8dOzcQ3l45+gDjDqdILhAvLDjlAIebdkqVqb2CfFNW/I2CQH\nZAuKN1aoKA==\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "refunds.default.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul" + } + }, + "type": "EDS", + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": {} + } + } + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden b/agent/xds/testdata/clusters/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden new file mode 100644 index 000000000000..6d6212a30e78 --- /dev/null +++ b/agent/xds/testdata/clusters/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden @@ -0,0 +1,342 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "circuitBreakers": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "destination.192-168-2-1.kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "destination.192-168-2-1.kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "destination.192-168-2-1.kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "destination.192-168-2-2.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "destination.192-168-2-2.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "destination.192-168-2-2.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "destination.192-168-2-3.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "destination.192-168-2-3.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka2" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "destination.192-168-2-3.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "altStatName": "destination.www-google-com.google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "destination.www-google-com.google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "destination.www-google-com.google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "circuitBreakers": {}, + "connectTimeout": "5s", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + } + }, + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "matchTypedSubjectAltNames": [ + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + "sanType": "URI" + }, + { + "matcher": { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + }, + "sanType": "URI" + } + ], + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + }, + "type": "EDS" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + }, + "name": "local_app", + "type": "STATIC" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/access-logs-defaults.latest.golden b/agent/xds/testdata/endpoints/access-logs-defaults.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/access-logs-defaults.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/access-logs-json-file.latest.golden b/agent/xds/testdata/endpoints/access-logs-json-file.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/access-logs-json-file.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/access-logs-text-stderr-disablelistenerlogs.latest.golden b/agent/xds/testdata/endpoints/access-logs-text-stderr-disablelistenerlogs.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/access-logs-text-stderr-disablelistenerlogs.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/api-gateway-http-listener-with-http-route.latest.golden b/agent/xds/testdata/endpoints/api-gateway-http-listener-with-http-route.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/api-gateway-http-listener-with-http-route.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/api-gateway-http-listener.latest.golden b/agent/xds/testdata/endpoints/api-gateway-http-listener.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/api-gateway-http-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/api-gateway-nil-config-entry.latest.golden b/agent/xds/testdata/endpoints/api-gateway-nil-config-entry.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/api-gateway-nil-config-entry.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/api-gateway-tcp-listener-with-tcp-and-http-route.latest.golden b/agent/xds/testdata/endpoints/api-gateway-tcp-listener-with-tcp-and-http-route.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/api-gateway-tcp-listener-with-tcp-and-http-route.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/api-gateway-tcp-listener-with-tcp-route.latest.golden b/agent/xds/testdata/endpoints/api-gateway-tcp-listener-with-tcp-route.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/api-gateway-tcp-listener-with-tcp-route.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/api-gateway-tcp-listener.latest.golden b/agent/xds/testdata/endpoints/api-gateway-tcp-listener.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/api-gateway-tcp-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/api-gateway-with-multiple-hostnames.latest.golden b/agent/xds/testdata/endpoints/api-gateway-with-multiple-hostnames.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/api-gateway-with-multiple-hostnames.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/api-gateway.latest.golden b/agent/xds/testdata/endpoints/api-gateway.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/api-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-lb-in-resolver.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-lb-in-resolver.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-lb-in-resolver.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-resolver-with-lb.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-resolver-with-lb.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-resolver-with-lb.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-route-to-lb-resolver.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-route-to-lb-resolver.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-route-to-lb-resolver.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-splitter-overweight.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-splitter-overweight.latest.golden new file mode 100644 index 000000000000..fde7857a2ebd --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-splitter-overweight.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-upstream-defaults.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-upstream-defaults.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-upstream-defaults.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-chain-and-router.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-chain-and-router.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-chain-and-router.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-chain-and-splitter.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-chain-and-splitter.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-chain-and-splitter.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-chain-http2.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-chain-http2.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-chain-http2.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-grpc-chain.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-grpc-chain.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-grpc-chain.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-grpc-router.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-grpc-router.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-grpc-router.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-http-chain.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-http-chain.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-http-chain.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-http2-chain.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-http2-chain.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-http2-chain.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-jwt-config-entry-with-local.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-jwt-config-entry-with-local.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-jwt-config-entry-with-local.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden new file mode 100644 index 000000000000..41ea4a4f0206 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden new file mode 100644 index 000000000000..41ea4a4f0206 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-tcp-chain.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-tcp-chain.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-tcp-chain.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-tls-incoming-cipher-suites.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-tls-incoming-cipher-suites.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-tls-incoming-cipher-suites.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-tls-incoming-max-version.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-tls-incoming-max-version.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-tls-incoming-max-version.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-tls-incoming-min-version.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-tls-incoming-min-version.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-tls-incoming-min-version.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-tls-outgoing-max-version.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-tls-outgoing-max-version.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-tls-outgoing-max-version.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-tls-outgoing-min-version.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-tls-outgoing-min-version.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-tls-outgoing-min-version.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/connect-proxy-without-tproxy-and-permissive-mtls.latest.golden b/agent/xds/testdata/endpoints/connect-proxy-without-tproxy-and-permissive-mtls.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/connect-proxy-without-tproxy-and-permissive-mtls.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-limits-max-connections-only.latest.golden b/agent/xds/testdata/endpoints/custom-limits-max-connections-only.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-limits-max-connections-only.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-limits-set-to-zero.latest.golden b/agent/xds/testdata/endpoints/custom-limits-set-to-zero.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-limits-set-to-zero.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-limits.latest.golden b/agent/xds/testdata/endpoints/custom-limits.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-limits.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-local-app.latest.golden b/agent/xds/testdata/endpoints/custom-local-app.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-local-app.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-max-inbound-connections.latest.golden b/agent/xds/testdata/endpoints/custom-max-inbound-connections.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-max-inbound-connections.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden b/agent/xds/testdata/endpoints/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-passive-healthcheck.latest.golden b/agent/xds/testdata/endpoints/custom-passive-healthcheck.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-passive-healthcheck.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-public-listener-http-2.latest.golden b/agent/xds/testdata/endpoints/custom-public-listener-http-2.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-public-listener-http-2.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-public-listener-http-missing.latest.golden b/agent/xds/testdata/endpoints/custom-public-listener-http-missing.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-public-listener-http-missing.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-public-listener-http.latest.golden b/agent/xds/testdata/endpoints/custom-public-listener-http.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-public-listener-http.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-public-listener.latest.golden b/agent/xds/testdata/endpoints/custom-public-listener.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-public-listener.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-timeouts.latest.golden b/agent/xds/testdata/endpoints/custom-timeouts.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-timeouts.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-trace-listener.latest.golden b/agent/xds/testdata/endpoints/custom-trace-listener.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-trace-listener.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-upstream-default-chain.latest.golden b/agent/xds/testdata/endpoints/custom-upstream-default-chain.latest.golden new file mode 100644 index 000000000000..c0d604ae53a7 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-upstream-default-chain.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "myservice", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-upstream-ignored-with-disco-chain.latest.golden b/agent/xds/testdata/endpoints/custom-upstream-ignored-with-disco-chain.latest.golden new file mode 100644 index 000000000000..ffaf0a6bae06 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-upstream-ignored-with-disco-chain.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "failover-target~0~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "failover-target~1~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-upstream-with-prepared-query.latest.golden b/agent/xds/testdata/endpoints/custom-upstream-with-prepared-query.latest.golden new file mode 100644 index 000000000000..fde7857a2ebd --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-upstream-with-prepared-query.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/custom-upstream.latest.golden b/agent/xds/testdata/endpoints/custom-upstream.latest.golden new file mode 100644 index 000000000000..c0d604ae53a7 --- /dev/null +++ b/agent/xds/testdata/endpoints/custom-upstream.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "myservice", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/downstream-service-with-unix-sockets.latest.golden b/agent/xds/testdata/endpoints/downstream-service-with-unix-sockets.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/downstream-service-with-unix-sockets.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/expose-checks-grpc.latest.golden b/agent/xds/testdata/endpoints/expose-checks-grpc.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/expose-checks-grpc.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/expose-checks-http-with-bind-override.latest.golden b/agent/xds/testdata/endpoints/expose-checks-http-with-bind-override.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/expose-checks-http-with-bind-override.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/expose-checks-http.latest.golden b/agent/xds/testdata/endpoints/expose-checks-http.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/expose-checks-http.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/expose-checks.latest.golden b/agent/xds/testdata/endpoints/expose-checks.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/expose-checks.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/expose-paths-grpc-new-cluster-http1.latest.golden b/agent/xds/testdata/endpoints/expose-paths-grpc-new-cluster-http1.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/expose-paths-grpc-new-cluster-http1.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/expose-paths-local-app-paths.latest.golden b/agent/xds/testdata/endpoints/expose-paths-local-app-paths.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/expose-paths-local-app-paths.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/expose-paths-new-cluster-http2.latest.golden b/agent/xds/testdata/endpoints/expose-paths-new-cluster-http2.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/expose-paths-new-cluster-http2.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/grpc-public-listener.latest.golden b/agent/xds/testdata/endpoints/grpc-public-listener.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/grpc-public-listener.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/http-listener-with-timeouts.latest.golden b/agent/xds/testdata/endpoints/http-listener-with-timeouts.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/http-listener-with-timeouts.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/http-public-listener-no-xfcc.latest.golden b/agent/xds/testdata/endpoints/http-public-listener-no-xfcc.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/http-public-listener-no-xfcc.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/http-public-listener.latest.golden b/agent/xds/testdata/endpoints/http-public-listener.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/http-public-listener.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/http-upstream.latest.golden b/agent/xds/testdata/endpoints/http-upstream.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/http-upstream.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/http2-public-listener.latest.golden b/agent/xds/testdata/endpoints/http2-public-listener.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/http2-public-listener.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-config-entry-nil.latest.golden b/agent/xds/testdata/endpoints/ingress-config-entry-nil.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-config-entry-nil.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-defaults-no-chain.latest.golden b/agent/xds/testdata/endpoints/ingress-defaults-no-chain.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-defaults-no-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-gateway-bind-addrs.latest.golden b/agent/xds/testdata/endpoints/ingress-gateway-bind-addrs.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-gateway-bind-addrs.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden b/agent/xds/testdata/endpoints/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-gateway-with-tls-outgoing-max-version.latest.golden b/agent/xds/testdata/endpoints/ingress-gateway-with-tls-outgoing-max-version.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-gateway-with-tls-outgoing-max-version.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-gateway-with-tls-outgoing-min-version.latest.golden b/agent/xds/testdata/endpoints/ingress-gateway-with-tls-outgoing-min-version.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-gateway-with-tls-outgoing-min-version.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-grpc-multiple-services.latest.golden b/agent/xds/testdata/endpoints/ingress-grpc-multiple-services.latest.golden new file mode 100644 index 000000000000..15a7d2b789ad --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-grpc-multiple-services.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-http-multiple-services.latest.golden b/agent/xds/testdata/endpoints/ingress-http-multiple-services.latest.golden new file mode 100644 index 000000000000..a1b8a9153d0a --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-http-multiple-services.latest.golden @@ -0,0 +1,143 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "baz.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "qux.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-lb-in-resolver.latest.golden b/agent/xds/testdata/endpoints/ingress-lb-in-resolver.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-lb-in-resolver.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-chain-and-router-header-manip.latest.golden b/agent/xds/testdata/endpoints/ingress-with-chain-and-router-header-manip.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-chain-and-router-header-manip.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-chain-and-router.latest.golden b/agent/xds/testdata/endpoints/ingress-with-chain-and-router.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-chain-and-router.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-chain-and-splitter.latest.golden b/agent/xds/testdata/endpoints/ingress-with-chain-and-splitter.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-chain-and-splitter.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-defaults-passive-health-check.latest.golden b/agent/xds/testdata/endpoints/ingress-with-defaults-passive-health-check.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-defaults-passive-health-check.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-defaults-service-max-connections.latest.golden b/agent/xds/testdata/endpoints/ingress-with-defaults-service-max-connections.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-defaults-service-max-connections.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-grpc-router.latest.golden b/agent/xds/testdata/endpoints/ingress-with-grpc-router.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-grpc-router.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-grpc-single-tls-listener.latest.golden b/agent/xds/testdata/endpoints/ingress-with-grpc-single-tls-listener.latest.golden new file mode 100644 index 000000000000..c745542ee476 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-grpc-single-tls-listener.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-http2-and-grpc-multiple-tls-listener.latest.golden b/agent/xds/testdata/endpoints/ingress-with-http2-and-grpc-multiple-tls-listener.latest.golden new file mode 100644 index 000000000000..c745542ee476 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-http2-and-grpc-multiple-tls-listener.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-http2-single-tls-listener.latest.golden b/agent/xds/testdata/endpoints/ingress-with-http2-single-tls-listener.latest.golden new file mode 100644 index 000000000000..c745542ee476 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-http2-single-tls-listener.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-overwrite-defaults-passive-health-check.latest.golden b/agent/xds/testdata/endpoints/ingress-with-overwrite-defaults-passive-health-check.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-overwrite-defaults-passive-health-check.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-overwrite-defaults-service-max-connections.latest.golden b/agent/xds/testdata/endpoints/ingress-with-overwrite-defaults-service-max-connections.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-overwrite-defaults-service-max-connections.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-sds-listener+service-level.latest.golden b/agent/xds/testdata/endpoints/ingress-with-sds-listener+service-level.latest.golden new file mode 100644 index 000000000000..c745542ee476 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-sds-listener+service-level.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-sds-listener-gw-level-http.latest.golden b/agent/xds/testdata/endpoints/ingress-with-sds-listener-gw-level-http.latest.golden new file mode 100644 index 000000000000..71594fbf1b4e --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-sds-listener-gw-level-http.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-sds-listener-gw-level-mixed-tls.latest.golden b/agent/xds/testdata/endpoints/ingress-with-sds-listener-gw-level-mixed-tls.latest.golden new file mode 100644 index 000000000000..ccf0803dc0c1 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-sds-listener-gw-level-mixed-tls.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "insecure.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "secure.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-sds-listener-gw-level.latest.golden b/agent/xds/testdata/endpoints/ingress-with-sds-listener-gw-level.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-sds-listener-gw-level.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-sds-listener-level-wildcard.latest.golden b/agent/xds/testdata/endpoints/ingress-with-sds-listener-level-wildcard.latest.golden new file mode 100644 index 000000000000..903ff9e17f3c --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-sds-listener-level-wildcard.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-sds-listener-level.latest.golden b/agent/xds/testdata/endpoints/ingress-with-sds-listener-level.latest.golden new file mode 100644 index 000000000000..903ff9e17f3c --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-sds-listener-level.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-sds-listener-listener-level.latest.golden b/agent/xds/testdata/endpoints/ingress-with-sds-listener-listener-level.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-sds-listener-listener-level.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-sds-service-level-2.latest.golden b/agent/xds/testdata/endpoints/ingress-with-sds-service-level-2.latest.golden new file mode 100644 index 000000000000..903ff9e17f3c --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-sds-service-level-2.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-sds-service-level-mixed-no-tls.latest.golden b/agent/xds/testdata/endpoints/ingress-with-sds-service-level-mixed-no-tls.latest.golden new file mode 100644 index 000000000000..c745542ee476 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-sds-service-level-mixed-no-tls.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-sds-service-level-mixed-tls.latest.golden b/agent/xds/testdata/endpoints/ingress-with-sds-service-level-mixed-tls.latest.golden new file mode 100644 index 000000000000..903ff9e17f3c --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-sds-service-level-mixed-tls.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-sds-service-level.latest.golden b/agent/xds/testdata/endpoints/ingress-with-sds-service-level.latest.golden new file mode 100644 index 000000000000..c745542ee476 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-sds-service-level.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-service-max-connections.latest.golden b/agent/xds/testdata/endpoints/ingress-with-service-max-connections.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-service-max-connections.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-service-passive-health-check.latest.golden b/agent/xds/testdata/endpoints/ingress-with-service-passive-health-check.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-service-passive-health-check.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-single-tls-listener.latest.golden b/agent/xds/testdata/endpoints/ingress-with-single-tls-listener.latest.golden new file mode 100644 index 000000000000..c745542ee476 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-single-tls-listener.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-tls-listener-cipher-suites.latest.golden b/agent/xds/testdata/endpoints/ingress-with-tls-listener-cipher-suites.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-tls-listener-cipher-suites.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-tls-listener-max-version.latest.golden b/agent/xds/testdata/endpoints/ingress-with-tls-listener-max-version.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-tls-listener-max-version.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-tls-listener-min-version.latest.golden b/agent/xds/testdata/endpoints/ingress-with-tls-listener-min-version.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-tls-listener-min-version.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-tls-listener.latest.golden b/agent/xds/testdata/endpoints/ingress-with-tls-listener.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-tls-listener.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-tls-min-version-listeners-gateway-defaults.latest.golden b/agent/xds/testdata/endpoints/ingress-with-tls-min-version-listeners-gateway-defaults.latest.golden new file mode 100644 index 000000000000..29eb4029dd7e --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-tls-min-version-listeners-gateway-defaults.latest.golden @@ -0,0 +1,143 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s4.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden b/agent/xds/testdata/endpoints/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden new file mode 100644 index 000000000000..c745542ee476 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-tls-mixed-listeners.latest.golden b/agent/xds/testdata/endpoints/ingress-with-tls-mixed-listeners.latest.golden new file mode 100644 index 000000000000..c745542ee476 --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-tls-mixed-listeners.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-tls-mixed-max-version-listeners.latest.golden b/agent/xds/testdata/endpoints/ingress-with-tls-mixed-max-version-listeners.latest.golden new file mode 100644 index 000000000000..e77e740023ae --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-tls-mixed-max-version-listeners.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/ingress-with-tls-mixed-min-version-listeners.latest.golden b/agent/xds/testdata/endpoints/ingress-with-tls-mixed-min-version-listeners.latest.golden new file mode 100644 index 000000000000..e77e740023ae --- /dev/null +++ b/agent/xds/testdata/endpoints/ingress-with-tls-mixed-min-version-listeners.latest.golden @@ -0,0 +1,109 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/listener-balance-inbound-connections.latest.golden b/agent/xds/testdata/endpoints/listener-balance-inbound-connections.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/listener-balance-inbound-connections.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/listener-balance-outbound-connections-bind-port.latest.golden b/agent/xds/testdata/endpoints/listener-balance-outbound-connections-bind-port.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/listener-balance-outbound-connections-bind-port.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/listener-bind-address-port.latest.golden b/agent/xds/testdata/endpoints/listener-bind-address-port.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/listener-bind-address-port.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/listener-bind-address.latest.golden b/agent/xds/testdata/endpoints/listener-bind-address.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/listener-bind-address.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/listener-bind-port.latest.golden b/agent/xds/testdata/endpoints/listener-bind-port.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/listener-bind-port.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/listener-max-inbound-connections.latest.golden b/agent/xds/testdata/endpoints/listener-max-inbound-connections.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/listener-max-inbound-connections.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/listener-unix-domain-socket.latest.golden b/agent/xds/testdata/endpoints/listener-unix-domain-socket.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/listener-unix-domain-socket.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/mesh-gateway-custom-addresses.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-custom-addresses.latest.golden new file mode 100644 index 000000000000..4853c9dc932a --- /dev/null +++ b/agent/xds/testdata/endpoints/mesh-gateway-custom-addresses.latest.golden @@ -0,0 +1,145 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.6", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.7", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.8", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.1", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.2", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.3", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.4", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.5", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.9", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/mesh-gateway-hash-lb-ignored.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-hash-lb-ignored.latest.golden new file mode 100644 index 000000000000..860055162211 --- /dev/null +++ b/agent/xds/testdata/endpoints/mesh-gateway-hash-lb-ignored.latest.golden @@ -0,0 +1,159 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.6", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.7", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.8", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.1", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.2", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.3", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.4", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.5", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.9", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/mesh-gateway-ignore-extra-resolvers.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-ignore-extra-resolvers.latest.golden new file mode 100644 index 000000000000..7b345547990a --- /dev/null +++ b/agent/xds/testdata/endpoints/mesh-gateway-ignore-extra-resolvers.latest.golden @@ -0,0 +1,120 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.1", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.2", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.3", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.4", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.5", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.9", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/mesh-gateway-non-hash-lb-injected.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-non-hash-lb-injected.latest.golden new file mode 100644 index 000000000000..860055162211 --- /dev/null +++ b/agent/xds/testdata/endpoints/mesh-gateway-non-hash-lb-injected.latest.golden @@ -0,0 +1,159 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.6", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.7", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.8", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.1", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.2", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.3", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.4", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.5", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.9", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/mesh-gateway-service-subsets.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-service-subsets.latest.golden index f4e0c1e258b0..860055162211 100644 --- a/agent/xds/testdata/endpoints/mesh-gateway-service-subsets.latest.golden +++ b/agent/xds/testdata/endpoints/mesh-gateway-service-subsets.latest.golden @@ -143,124 +143,14 @@ "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", "clusterName": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.6", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.7", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "v1.foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.3", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.4", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } + {} ] }, { "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", "clusterName": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.8", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "v2.foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.5", - "portValue": 2222 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "172.16.1.9", - "portValue": 2222 - } - } - }, - "healthStatus": "UNHEALTHY", - "loadBalancingWeight": 1 - } - ] - } + {} ] } ], diff --git a/agent/xds/testdata/endpoints/mesh-gateway-service-subsets2.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-service-subsets2.latest.golden new file mode 100644 index 000000000000..f4e0c1e258b0 --- /dev/null +++ b/agent/xds/testdata/endpoints/mesh-gateway-service-subsets2.latest.golden @@ -0,0 +1,269 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.6", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.7", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.8", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.1", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.2", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.3", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.4", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.5", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.9", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.6", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.7", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v1.foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.3", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.4", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.8", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v2.foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.5", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.9", + "portValue": 2222 + } + } + }, + "healthStatus": "UNHEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/mesh-gateway-service-timeouts.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-service-timeouts.latest.golden new file mode 100644 index 000000000000..860055162211 --- /dev/null +++ b/agent/xds/testdata/endpoints/mesh-gateway-service-timeouts.latest.golden @@ -0,0 +1,159 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.6", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.7", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.8", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.1", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.2", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.3", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.4", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.5", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.9", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/mesh-gateway-tagged-addresses.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-tagged-addresses.latest.golden new file mode 100644 index 000000000000..4853c9dc932a --- /dev/null +++ b/agent/xds/testdata/endpoints/mesh-gateway-tagged-addresses.latest.golden @@ -0,0 +1,145 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.6", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.7", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.8", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.1", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.2", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.3", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.4", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.5", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.9", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/mesh-gateway-tcp-keepalives.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-tcp-keepalives.latest.golden new file mode 100644 index 000000000000..4853c9dc932a --- /dev/null +++ b/agent/xds/testdata/endpoints/mesh-gateway-tcp-keepalives.latest.golden @@ -0,0 +1,145 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.6", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.7", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.8", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.1", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.2", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.3", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.4", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.5", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.9", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/mesh-gateway-with-limits.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-with-limits.latest.golden new file mode 100644 index 000000000000..4853c9dc932a --- /dev/null +++ b/agent/xds/testdata/endpoints/mesh-gateway-with-limits.latest.golden @@ -0,0 +1,145 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.6", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.7", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.8", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.1", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "198.18.1.2", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.3", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.4", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.5", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.16.1.9", + "portValue": 2222 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-custom-and-tagged-addresses.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-custom-and-tagged-addresses.latest.golden new file mode 100644 index 000000000000..0b67b10323e3 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-custom-and-tagged-addresses.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-custom-trace-listener.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-custom-trace-listener.latest.golden new file mode 100644 index 000000000000..0b67b10323e3 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-custom-trace-listener.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-hostname-service-subsets.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-hostname-service-subsets.latest.golden new file mode 100644 index 000000000000..0b67b10323e3 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-hostname-service-subsets.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-http2-upstream-subsets.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-http2-upstream-subsets.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-http2-upstream-subsets.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-http2-upstream.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-http2-upstream.latest.golden new file mode 100644 index 000000000000..96ee5c709468 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-http2-upstream.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-ignore-extra-resolvers.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-ignore-extra-resolvers.latest.golden new file mode 100644 index 000000000000..5663c47c8264 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-ignore-extra-resolvers.latest.golden @@ -0,0 +1,28 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-lb-config-no-hash-policies.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-lb-config-no-hash-policies.latest.golden new file mode 100644 index 000000000000..5663c47c8264 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-lb-config-no-hash-policies.latest.golden @@ -0,0 +1,28 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-lb-config.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-lb-config.latest.golden new file mode 100644 index 000000000000..5663c47c8264 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-lb-config.latest.golden @@ -0,0 +1,28 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-no-api-cert.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-no-api-cert.latest.golden new file mode 100644 index 000000000000..0b67b10323e3 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-no-api-cert.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-sni.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-sni.latest.golden new file mode 100644 index 000000000000..0b67b10323e3 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-sni.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-tcp-keepalives.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-tcp-keepalives.latest.golden new file mode 100644 index 000000000000..0b67b10323e3 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-tcp-keepalives.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-with-peer-trust-bundle.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-with-peer-trust-bundle.latest.golden new file mode 100644 index 000000000000..0b67b10323e3 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-with-peer-trust-bundle.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-with-tls-incoming-cipher-suites.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-with-tls-incoming-cipher-suites.latest.golden new file mode 100644 index 000000000000..0b67b10323e3 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-with-tls-incoming-cipher-suites.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-with-tls-incoming-max-version.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-with-tls-incoming-max-version.latest.golden new file mode 100644 index 000000000000..0b67b10323e3 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-with-tls-incoming-max-version.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/terminating-gateway-with-tls-incoming-min-version.latest.golden b/agent/xds/testdata/endpoints/terminating-gateway-with-tls-incoming-min-version.latest.golden new file mode 100644 index 000000000000..0b67b10323e3 --- /dev/null +++ b/agent/xds/testdata/endpoints/terminating-gateway-with-tls-incoming-min-version.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/transparent-proxy-http-upstream.latest.golden b/agent/xds/testdata/endpoints/transparent-proxy-http-upstream.latest.golden new file mode 100644 index 000000000000..ebf0eb91d97e --- /dev/null +++ b/agent/xds/testdata/endpoints/transparent-proxy-http-upstream.latest.golden @@ -0,0 +1,104 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "9.9.9.9", + "portValue": 9090 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "no-endpoints.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + {} + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/transparent-proxy-terminating-gateway.latest.golden b/agent/xds/testdata/endpoints/transparent-proxy-terminating-gateway.latest.golden new file mode 100644 index 000000000000..ce0d1b671c92 --- /dev/null +++ b/agent/xds/testdata/endpoints/transparent-proxy-terminating-gateway.latest.golden @@ -0,0 +1,119 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "9.9.9.9", + "portValue": 9090 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "9.9.9.9", + "portValue": 9090 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/transparent-proxy-with-resolver-redirect-upstream.latest.golden b/agent/xds/testdata/endpoints/transparent-proxy-with-resolver-redirect-upstream.latest.golden new file mode 100644 index 000000000000..545759eaf5b4 --- /dev/null +++ b/agent/xds/testdata/endpoints/transparent-proxy-with-resolver-redirect-upstream.latest.golden @@ -0,0 +1,63 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "9.9.9.9", + "portValue": 9090 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-ingress-with-router.latest.golden b/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-ingress-with-router.latest.golden new file mode 100644 index 000000000000..2a1b29370b63 --- /dev/null +++ b/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-ingress-with-router.latest.golden @@ -0,0 +1,41 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-mgw-peering.latest.golden b/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-mgw-peering.latest.golden new file mode 100644 index 000000000000..ce19eaa7ffcb --- /dev/null +++ b/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-mgw-peering.latest.golden @@ -0,0 +1,211 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "exported~bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "exported~foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "exported~gir.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "gir.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-sidecar.latest.golden b/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-sidecar.latest.golden new file mode 100644 index 000000000000..b4372a3439e8 --- /dev/null +++ b/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-sidecar.latest.golden @@ -0,0 +1,75 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-term-gw.latest.golden b/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-term-gw.latest.golden new file mode 100644 index 000000000000..038021dd8677 --- /dev/null +++ b/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-term-gw.latest.golden @@ -0,0 +1,85 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden b/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden new file mode 100644 index 000000000000..060259960f01 --- /dev/null +++ b/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden @@ -0,0 +1,29 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "refunds.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "106.96.90.233", + "portValue": 443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden b/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden new file mode 100644 index 000000000000..a0896e11577b --- /dev/null +++ b/agent/xds/testdata/endpoints/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden @@ -0,0 +1,163 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "destination.192-168-2-1.kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.168.0.1", + "portValue": 8443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "destination.192-168-2-2.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.168.0.1", + "portValue": 8443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "destination.192-168-2-3.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.168.0.1", + "portValue": 8443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "destination.www-google-com.google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.168.0.1", + "portValue": 8443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/api-gateway-with-multiple-hostnames.latest.golden b/agent/xds/testdata/listeners/api-gateway-with-multiple-hostnames.latest.golden new file mode 100644 index 000000000000..6469727f9798 --- /dev/null +++ b/agent/xds/testdata/listeners/api-gateway-with-multiple-hostnames.latest.golden @@ -0,0 +1,54 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "8080" + }, + "statPrefix": "ingress_upstream_8080", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "http:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-lb-in-resolver.latest.golden b/agent/xds/testdata/listeners/connect-proxy-lb-in-resolver.latest.golden new file mode 100644 index 000000000000..96c6814291eb --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-lb-in-resolver.latest.golden @@ -0,0 +1,137 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "db" + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-resolver-with-lb.latest.golden b/agent/xds/testdata/listeners/connect-proxy-resolver-with-lb.latest.golden new file mode 100644 index 000000000000..96c6814291eb --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-resolver-with-lb.latest.golden @@ -0,0 +1,137 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "db" + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-route-to-lb-resolver.latest.golden b/agent/xds/testdata/listeners/connect-proxy-route-to-lb-resolver.latest.golden new file mode 100644 index 000000000000..96c6814291eb --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-route-to-lb-resolver.latest.golden @@ -0,0 +1,137 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "db" + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-splitter-overweight.latest.golden b/agent/xds/testdata/listeners/connect-proxy-splitter-overweight.latest.golden new file mode 100644 index 000000000000..96c6814291eb --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-splitter-overweight.latest.golden @@ -0,0 +1,137 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "db" + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-chain-and-router.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-chain-and-router.latest.golden new file mode 100644 index 000000000000..96c6814291eb --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-chain-and-router.latest.golden @@ -0,0 +1,137 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "db" + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden new file mode 100644 index 000000000000..96c6814291eb --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden @@ -0,0 +1,137 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "db" + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-chain-and-splitter.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-chain-and-splitter.latest.golden new file mode 100644 index 000000000000..96c6814291eb --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-chain-and-splitter.latest.golden @@ -0,0 +1,137 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "db" + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-chain-http2.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-chain-http2.latest.golden new file mode 100644 index 000000000000..287fd5d69ae8 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-chain-http2.latest.golden @@ -0,0 +1,152 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "http2ProtocolOptions": {}, + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "routeConfig": { + "name": "db", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "db.default.default.dc1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-default-chain-and-custom-cluster.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-default-chain-and-custom-cluster.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-default-chain-and-custom-cluster.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-grpc-router.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-grpc-router.latest.golden new file mode 100644 index 000000000000..bdfe7aa7bd6f --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-grpc-router.latest.golden @@ -0,0 +1,151 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "http2ProtocolOptions": {}, + "httpFilters": [ + { + "name": "envoy.filters.http.grpc_stats", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig", + "statsForAllMethods": true + } + }, + { + "name": "envoy.filters.http.grpc_http1_bridge", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_http1_bridge.v3.Config" + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "db" + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-jwt-config-entry-with-local.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-jwt-config-entry-with-local.latest.golden index e54314395977..0254a224d513 100644 --- a/agent/xds/testdata/listeners/connect-proxy-with-jwt-config-entry-with-local.latest.golden +++ b/agent/xds/testdata/listeners/connect-proxy-with-jwt-config-entry-with-local.latest.golden @@ -63,179 +63,19 @@ { "filters": [ { - "name": "envoy.filters.network.http_connection_manager", + "name": "envoy.filters.network.rbac", "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "forwardClientCertDetails": "APPEND_FORWARD", - "httpFilters": [ - { - "name": "envoy.filters.http.jwt_authn", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication", - "providers": { - "okta": { - "fromCookies": [ - "token" - ], - "fromParams": [ - "token" - ], - "localJwks": { - "inlineString": "hello world\n" - }, - "payloadInMetadata": "jwt_payload_okta" - } - }, - "rules": [ - { - "match": { - "prefix": "/" - }, - "requires": { - "requiresAny": { - "requirements": [ - { - "providerName": "okta" - }, - { - "allowMissingOrFailed": {} - } - ] - } - } - } - ] - } - }, - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.header_to_metadata", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config", - "requestRules": [ - { - "header": "x-forwarded-client-cert", - "onHeaderPresent": { - "key": "trust-domain", - "metadataNamespace": "consul", - "regexValueRewrite": { - "pattern": { - "googleRe2": {}, - "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" - }, - "substitution": "\\1" - } - } - }, - { - "header": "x-forwarded-client-cert", - "onHeaderPresent": { - "key": "partition", - "metadataNamespace": "consul", - "regexValueRewrite": { - "pattern": { - "googleRe2": {}, - "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" - }, - "substitution": "\\2" - } - } - }, - { - "header": "x-forwarded-client-cert", - "onHeaderPresent": { - "key": "namespace", - "metadataNamespace": "consul", - "regexValueRewrite": { - "pattern": { - "googleRe2": {}, - "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" - }, - "substitution": "\\3" - } - } - }, - { - "header": "x-forwarded-client-cert", - "onHeaderPresent": { - "key": "datacenter", - "metadataNamespace": "consul", - "regexValueRewrite": { - "pattern": { - "googleRe2": {}, - "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" - }, - "substitution": "\\4" - } - } - }, - { - "header": "x-forwarded-client-cert", - "onHeaderPresent": { - "key": "service", - "metadataNamespace": "consul", - "regexValueRewrite": { - "pattern": { - "googleRe2": {}, - "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" - }, - "substitution": "\\5" - } - } - } - ] - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "routeConfig": { - "name": "public_listener", - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener", - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app" - } - } - ] - } - ] - }, - "setCurrentClientCertDetails": { - "cert": true, - "chain": true, - "dns": true, - "subject": true, - "uri": true - }, - "statPrefix": "public_listener", - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" } } ], @@ -244,9 +84,6 @@ "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", "commonTlsContext": { - "alpnProtocols": [ - "http/1.1" - ], "tlsCertificates": [ { "certificateChain": { diff --git a/agent/xds/testdata/listeners/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden new file mode 100644 index 000000000000..459678e2a339 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden @@ -0,0 +1,275 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "routeConfig": { + "name": "db", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "db.default.default.dc1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "commonHttpProtocolOptions": { + "headersWithUnderscoresAction": "REJECT_REQUEST" + }, + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.header_to_metadata", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config", + "requestRules": [ + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "trust-domain", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\1" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "partition", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\2" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "namespace", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\3" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "datacenter", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\4" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "service", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\5" + } + } + } + ] + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "mergeSlashes": true, + "pathWithEscapedSlashesAction": "UNESCAPE_AND_FORWARD", + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "public_listener", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "public_listener", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "alpnProtocols": [ + "http/1.1" + ], + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden new file mode 100644 index 000000000000..92dfd7cc0c44 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden @@ -0,0 +1,276 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "routeConfig": { + "name": "db", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "db.default.default.dc1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "commonHttpProtocolOptions": { + "headersWithUnderscoresAction": "REJECT_REQUEST" + }, + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.header_to_metadata", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config", + "requestRules": [ + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "trust-domain", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\1" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "partition", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\2" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "namespace", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\3" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "datacenter", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\4" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "key": "service", + "metadataNamespace": "consul", + "regexValueRewrite": { + "pattern": { + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\5" + } + } + } + ] + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "mergeSlashes": true, + "normalizePath": true, + "pathWithEscapedSlashesAction": "UNESCAPE_AND_FORWARD", + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "public_listener", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "public_listener", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "alpnProtocols": [ + "http/1.1" + ], + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-tls-outgoing-max-version.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-tls-outgoing-max-version.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-tls-outgoing-max-version.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/connect-proxy-with-tls-outgoing-min-version.latest.golden b/agent/xds/testdata/listeners/connect-proxy-with-tls-outgoing-min-version.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/connect-proxy-with-tls-outgoing-min-version.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/custom-limits-max-connections-only.latest.golden b/agent/xds/testdata/listeners/custom-limits-max-connections-only.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/custom-limits-max-connections-only.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/custom-limits-set-to-zero.latest.golden b/agent/xds/testdata/listeners/custom-limits-set-to-zero.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/custom-limits-set-to-zero.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/custom-limits.latest.golden b/agent/xds/testdata/listeners/custom-limits.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/custom-limits.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/custom-local-app.latest.golden b/agent/xds/testdata/listeners/custom-local-app.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/custom-local-app.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/custom-max-inbound-connections.latest.golden b/agent/xds/testdata/listeners/custom-max-inbound-connections.latest.golden new file mode 100644 index 000000000000..7f5652c04738 --- /dev/null +++ b/agent/xds/testdata/listeners/custom-max-inbound-connections.latest.golden @@ -0,0 +1,123 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.connection_limit", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit", + "maxConnections": "3456", + "statPrefix": "inbound_connection_limit" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden b/agent/xds/testdata/listeners/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/custom-passive-healthcheck.latest.golden b/agent/xds/testdata/listeners/custom-passive-healthcheck.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/custom-passive-healthcheck.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/custom-timeouts.latest.golden b/agent/xds/testdata/listeners/custom-timeouts.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/custom-timeouts.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/custom-trace-listener.latest.golden b/agent/xds/testdata/listeners/custom-trace-listener.latest.golden index b72487ffba02..f6291296e70c 100644 --- a/agent/xds/testdata/listeners/custom-trace-listener.latest.golden +++ b/agent/xds/testdata/listeners/custom-trace-listener.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -160,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -259,4 +255,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/custom-upstream-default-chain.latest.golden b/agent/xds/testdata/listeners/custom-upstream-default-chain.latest.golden new file mode 100644 index 000000000000..0254a224d513 --- /dev/null +++ b/agent/xds/testdata/listeners/custom-upstream-default-chain.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/custom-upstream-with-prepared-query.latest.golden b/agent/xds/testdata/listeners/custom-upstream-with-prepared-query.latest.golden index ca92cf2177a5..41d2e0f4ff24 100644 --- a/agent/xds/testdata/listeners/custom-upstream-with-prepared-query.latest.golden +++ b/agent/xds/testdata/listeners/custom-upstream-with-prepared-query.latest.golden @@ -5,8 +5,8 @@ "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", "address": { "socketAddress": { - "address": "11.11.11.11", - "portValue": 11111 + "address": "127.0.0.1", + "portValue": 9191 } }, "filterChains": [ @@ -16,14 +16,15 @@ "name": "envoy.filters.network.tcp_proxy", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "cluster": "random-cluster", - "statPrefix": "foo-stats" + "cluster": "db.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_db" } } ] } ], - "name": "db:custom-upstream" + "name": "prepared_query:db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" }, { "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", @@ -37,11 +38,48 @@ { "filters": [ { - "name": "envoy.filters.network.tcp_proxy", + "name": "envoy.filters.network.http_connection_manager", "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", - "statPrefix": "upstream.prepared_query_geo-cache" + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "http2ProtocolOptions": {}, + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "routeConfig": { + "name": "prepared_query:geo-cache", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "prepared_query:geo-cache", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + "statPrefix": "upstream.prepared_query_geo-cache", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] } } ] diff --git a/agent/xds/testdata/listeners/custom-upstream.latest.golden b/agent/xds/testdata/listeners/custom-upstream.latest.golden index ca92cf2177a5..0254a224d513 100644 --- a/agent/xds/testdata/listeners/custom-upstream.latest.golden +++ b/agent/xds/testdata/listeners/custom-upstream.latest.golden @@ -5,8 +5,8 @@ "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", "address": { "socketAddress": { - "address": "11.11.11.11", - "portValue": 11111 + "address": "127.0.0.1", + "portValue": 9191 } }, "filterChains": [ @@ -16,14 +16,15 @@ "name": "envoy.filters.network.tcp_proxy", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "cluster": "random-cluster", - "statPrefix": "foo-stats" + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" } } ] } ], - "name": "db:custom-upstream" + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" }, { "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", diff --git a/agent/xds/testdata/listeners/downstream-service-with-unix-sockets.latest.golden b/agent/xds/testdata/listeners/downstream-service-with-unix-sockets.latest.golden new file mode 100644 index 000000000000..78526457cc95 --- /dev/null +++ b/agent/xds/testdata/listeners/downstream-service-with-unix-sockets.latest.golden @@ -0,0 +1,115 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 0 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:0", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/expose-checks.latest.golden b/agent/xds/testdata/listeners/expose-checks.latest.golden new file mode 100644 index 000000000000..2299f061ddec --- /dev/null +++ b/agent/xds/testdata/listeners/expose-checks.latest.golden @@ -0,0 +1,142 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 21500 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "sourcePrefixRanges": [ + { + "addressPrefix": "127.0.0.1", + "prefixLen": 8 + }, + { + "addressPrefix": "192.0.2.1", + "prefixLen": 32 + }, + { + "addressPrefix": "::1", + "prefixLen": 128 + } + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "routeConfig": { + "name": "exposed_path_filter_debug_21500", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "exposed_path_filter_debug_21500", + "routes": [ + { + "match": { + "path": "/debug" + }, + "route": { + "cluster": "exposed_cluster_8181" + } + } + ] + } + ] + }, + "statPrefix": "exposed_path_filter_debug_21500", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "exposed_path_debug:1.2.3.4:21500", + "trafficDirection": "INBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:1.2.3.4:8080", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/expose-paths-grpc-new-cluster-http1.latest.golden b/agent/xds/testdata/listeners/expose-paths-grpc-new-cluster-http1.latest.golden new file mode 100644 index 000000000000..530b60fb5094 --- /dev/null +++ b/agent/xds/testdata/listeners/expose-paths-grpc-new-cluster-http1.latest.golden @@ -0,0 +1,180 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 21500 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "routeConfig": { + "name": "exposed_path_filter_healthz_21500", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "exposed_path_filter_healthz_21500", + "routes": [ + { + "match": { + "path": "/healthz" + }, + "route": { + "cluster": "exposed_cluster_8090" + } + } + ] + } + ] + }, + "statPrefix": "exposed_path_filter_healthz_21500", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "exposed_path_healthz:1.2.3.4:21500", + "trafficDirection": "INBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "http2ProtocolOptions": {}, + "httpFilters": [ + { + "name": "envoy.filters.http.grpc_stats", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig", + "statsForAllMethods": true + } + }, + { + "name": "envoy.filters.http.grpc_http1_bridge", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_http1_bridge.v3.Config" + } + }, + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "normalizePath": true, + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "public_listener", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "statPrefix": "public_listener", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "alpnProtocols": [ + "h2", + "http/1.1" + ], + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:1.2.3.4:8080", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/listeners/grpc-public-listener.latest.golden b/agent/xds/testdata/listeners/grpc-public-listener.latest.golden index ac7d70ab1f27..be4df302b490 100644 --- a/agent/xds/testdata/listeners/grpc-public-listener.latest.golden +++ b/agent/xds/testdata/listeners/grpc-public-listener.latest.golden @@ -95,6 +95,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -165,4 +166,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/http-listener-with-timeouts.latest.golden b/agent/xds/testdata/listeners/http-listener-with-timeouts.latest.golden index a5e8bc06745f..82b73697adf9 100644 --- a/agent/xds/testdata/listeners/http-listener-with-timeouts.latest.golden +++ b/agent/xds/testdata/listeners/http-listener-with-timeouts.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -160,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -238,4 +234,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/http-public-listener-no-xfcc.latest.golden b/agent/xds/testdata/listeners/http-public-listener-no-xfcc.latest.golden index 66401ec1169d..d3cd78c70b7c 100644 --- a/agent/xds/testdata/listeners/http-public-listener-no-xfcc.latest.golden +++ b/agent/xds/testdata/listeners/http-public-listener-no-xfcc.latest.golden @@ -81,6 +81,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -150,4 +151,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/http-public-listener.latest.golden b/agent/xds/testdata/listeners/http-public-listener.latest.golden index cec77f10e445..b334e2c0337c 100644 --- a/agent/xds/testdata/listeners/http-public-listener.latest.golden +++ b/agent/xds/testdata/listeners/http-public-listener.latest.golden @@ -87,7 +87,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -101,7 +100,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -115,7 +113,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -129,7 +126,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -143,7 +139,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -160,6 +155,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -236,4 +232,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/http2-public-listener.latest.golden b/agent/xds/testdata/listeners/http2-public-listener.latest.golden index f78e46d25348..c659487acbf5 100644 --- a/agent/xds/testdata/listeners/http2-public-listener.latest.golden +++ b/agent/xds/testdata/listeners/http2-public-listener.latest.golden @@ -88,7 +88,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\1" @@ -102,7 +101,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\2" @@ -116,7 +114,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\3" @@ -130,7 +127,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\4" @@ -144,7 +140,6 @@ "metadataNamespace": "consul", "regexValueRewrite": { "pattern": { - "googleRe2": {}, "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" }, "substitution": "\\5" @@ -161,6 +156,7 @@ } } ], + "normalizePath": true, "routeConfig": { "name": "public_listener", "virtualHosts": [ @@ -238,4 +234,4 @@ ], "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", "versionInfo": "00000001" -} \ No newline at end of file +} diff --git a/agent/xds/testdata/listeners/ingress-config-entry-nil.latest.golden b/agent/xds/testdata/listeners/ingress-config-entry-nil.latest.golden new file mode 100644 index 000000000000..97cdec41ef13 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-config-entry-nil.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-defaults-no-chain.latest.golden b/agent/xds/testdata/listeners/ingress-defaults-no-chain.latest.golden new file mode 100644 index 000000000000..97cdec41ef13 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-defaults-no-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden b/agent/xds/testdata/listeners/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-gateway-with-tls-outgoing-max-version.latest.golden b/agent/xds/testdata/listeners/ingress-gateway-with-tls-outgoing-max-version.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-gateway-with-tls-outgoing-max-version.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-gateway-with-tls-outgoing-min-version.latest.golden b/agent/xds/testdata/listeners/ingress-gateway-with-tls-outgoing-min-version.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-gateway-with-tls-outgoing-min-version.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-lb-in-resolver.latest.golden b/agent/xds/testdata/listeners/ingress-lb-in-resolver.latest.golden new file mode 100644 index 000000000000..6469727f9798 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-lb-in-resolver.latest.golden @@ -0,0 +1,54 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "8080" + }, + "statPrefix": "ingress_upstream_8080", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "http:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-multiple-listeners-duplicate-service.latest.golden b/agent/xds/testdata/listeners/ingress-multiple-listeners-duplicate-service.latest.golden new file mode 100644 index 000000000000..63affa449885 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-multiple-listeners-duplicate-service.latest.golden @@ -0,0 +1,101 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 443 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "443" + }, + "statPrefix": "ingress_upstream_443", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "http:1.2.3.4:443", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "8080" + }, + "statPrefix": "ingress_upstream_8080", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "http:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-chain-and-failover-to-cluster-peer.latest.golden b/agent/xds/testdata/listeners/ingress-with-chain-and-failover-to-cluster-peer.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-chain-and-failover-to-cluster-peer.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-chain-and-failover.latest.golden b/agent/xds/testdata/listeners/ingress-with-chain-and-failover.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-chain-and-failover.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-chain-and-router-header-manip.latest.golden b/agent/xds/testdata/listeners/ingress-with-chain-and-router-header-manip.latest.golden new file mode 100644 index 000000000000..6469727f9798 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-chain-and-router-header-manip.latest.golden @@ -0,0 +1,54 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "8080" + }, + "statPrefix": "ingress_upstream_8080", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "http:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-chain-and-router.latest.golden b/agent/xds/testdata/listeners/ingress-with-chain-and-router.latest.golden new file mode 100644 index 000000000000..6469727f9798 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-chain-and-router.latest.golden @@ -0,0 +1,54 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "8080" + }, + "statPrefix": "ingress_upstream_8080", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "http:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-chain-and-splitter.latest.golden b/agent/xds/testdata/listeners/ingress-with-chain-and-splitter.latest.golden new file mode 100644 index 000000000000..6469727f9798 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-chain-and-splitter.latest.golden @@ -0,0 +1,54 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "8080" + }, + "statPrefix": "ingress_upstream_8080", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "http:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-chain.latest.golden b/agent/xds/testdata/listeners/ingress-with-chain.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-chain.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-defaults-passive-health-check.latest.golden b/agent/xds/testdata/listeners/ingress-with-defaults-passive-health-check.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-defaults-passive-health-check.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-defaults-service-max-connections.latest.golden b/agent/xds/testdata/listeners/ingress-with-defaults-service-max-connections.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-defaults-service-max-connections.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-grpc-router.latest.golden b/agent/xds/testdata/listeners/ingress-with-grpc-router.latest.golden new file mode 100644 index 000000000000..6469727f9798 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-grpc-router.latest.golden @@ -0,0 +1,54 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "8080" + }, + "statPrefix": "ingress_upstream_8080", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "http:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-overwrite-defaults-passive-health-check.latest.golden b/agent/xds/testdata/listeners/ingress-with-overwrite-defaults-passive-health-check.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-overwrite-defaults-passive-health-check.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-overwrite-defaults-service-max-connections.latest.golden b/agent/xds/testdata/listeners/ingress-with-overwrite-defaults-service-max-connections.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-overwrite-defaults-service-max-connections.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-sds-listener-level-wildcard.latest.golden b/agent/xds/testdata/listeners/ingress-with-sds-listener-level-wildcard.latest.golden new file mode 100644 index 000000000000..309e66dc0ed4 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-sds-listener-level-wildcard.latest.golden @@ -0,0 +1,87 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "9191" + }, + "statPrefix": "ingress_upstream_9191", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "alpnProtocols": [ + "http/1.1" + ], + "tlsCertificateSdsSecretConfigs": [ + { + "name": "listener-cert", + "sdsConfig": { + "apiConfigSource": { + "apiType": "GRPC", + "grpcServices": [ + { + "envoyGrpc": { + "clusterName": "listener-cluster" + }, + "timeout": "5s" + } + ], + "transportApiVersion": "V3" + }, + "resourceApiVersion": "V3" + } + } + ], + "tlsParams": {} + }, + "requireClientCertificate": false + } + } + } + ], + "name": "http:1.2.3.4:9191", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-sds-listener-level.latest.golden b/agent/xds/testdata/listeners/ingress-with-sds-listener-level.latest.golden new file mode 100644 index 000000000000..309e66dc0ed4 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-sds-listener-level.latest.golden @@ -0,0 +1,87 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "9191" + }, + "statPrefix": "ingress_upstream_9191", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "alpnProtocols": [ + "http/1.1" + ], + "tlsCertificateSdsSecretConfigs": [ + { + "name": "listener-cert", + "sdsConfig": { + "apiConfigSource": { + "apiType": "GRPC", + "grpcServices": [ + { + "envoyGrpc": { + "clusterName": "listener-cluster" + }, + "timeout": "5s" + } + ], + "transportApiVersion": "V3" + }, + "resourceApiVersion": "V3" + } + } + ], + "tlsParams": {} + }, + "requireClientCertificate": false + } + } + } + ], + "name": "http:1.2.3.4:9191", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-sds-service-level-2.latest.golden b/agent/xds/testdata/listeners/ingress-with-sds-service-level-2.latest.golden new file mode 100644 index 000000000000..db099e6b7d37 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-sds-service-level-2.latest.golden @@ -0,0 +1,172 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "www.example.com" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "9191_web" + }, + "statPrefix": "ingress_upstream_9191_web", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "alpnProtocols": [ + "http/1.1" + ], + "tlsCertificateSdsSecretConfigs": [ + { + "name": "www-cert", + "sdsConfig": { + "apiConfigSource": { + "apiType": "GRPC", + "grpcServices": [ + { + "envoyGrpc": { + "clusterName": "web-cluster" + }, + "timeout": "5s" + } + ], + "transportApiVersion": "V3" + }, + "resourceApiVersion": "V3" + } + } + ], + "tlsParams": {} + }, + "requireClientCertificate": false + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "foo.example.com" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "9191_foo" + }, + "statPrefix": "ingress_upstream_9191_foo", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "alpnProtocols": [ + "http/1.1" + ], + "tlsCertificateSdsSecretConfigs": [ + { + "name": "foo-cert", + "sdsConfig": { + "apiConfigSource": { + "apiType": "GRPC", + "grpcServices": [ + { + "envoyGrpc": { + "clusterName": "foo-cluster" + }, + "timeout": "5s" + } + ], + "transportApiVersion": "V3" + }, + "resourceApiVersion": "V3" + } + } + ], + "tlsParams": {} + }, + "requireClientCertificate": false + } + } + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "http:1.2.3.4:9191", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-sds-service-level-mixed-tls.latest.golden b/agent/xds/testdata/listeners/ingress-with-sds-service-level-mixed-tls.latest.golden new file mode 100644 index 000000000000..dca1e584ae53 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-sds-service-level-mixed-tls.latest.golden @@ -0,0 +1,134 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "www.example.com" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "9191_web" + }, + "statPrefix": "ingress_upstream_9191_web", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "alpnProtocols": [ + "http/1.1" + ], + "tlsCertificateSdsSecretConfigs": [ + { + "name": "www-cert", + "sdsConfig": { + "apiConfigSource": { + "apiType": "GRPC", + "grpcServices": [ + { + "envoyGrpc": { + "clusterName": "web-cluster" + }, + "timeout": "5s" + } + ], + "transportApiVersion": "V3" + }, + "resourceApiVersion": "V3" + } + } + ], + "tlsParams": {} + }, + "requireClientCertificate": false + } + } + }, + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "9191" + }, + "statPrefix": "ingress_upstream_9191", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "http:1.2.3.4:9191", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-service-max-connections.latest.golden b/agent/xds/testdata/listeners/ingress-with-service-max-connections.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-service-max-connections.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-service-passive-health-check.latest.golden b/agent/xds/testdata/listeners/ingress-with-service-passive-health-check.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-service-passive-health-check.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/listeners/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden b/agent/xds/testdata/listeners/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/listeners/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/listeners/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/listeners/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/listeners/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden new file mode 100644 index 000000000000..068e01983c92 --- /dev/null +++ b/agent/xds/testdata/listeners/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden @@ -0,0 +1,32 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/mesh-gateway-default-service-subset.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-default-service-subset.latest.golden new file mode 100644 index 000000000000..3b77ccca9b99 --- /dev/null +++ b/agent/xds/testdata/listeners/mesh-gateway-default-service-subset.latest.golden @@ -0,0 +1,96 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc2" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc4" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc6" + } + } + ] + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "mesh_gateway_local.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/mesh-gateway-hash-lb-ignored.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-hash-lb-ignored.latest.golden new file mode 100644 index 000000000000..3b77ccca9b99 --- /dev/null +++ b/agent/xds/testdata/listeners/mesh-gateway-hash-lb-ignored.latest.golden @@ -0,0 +1,96 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc2" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc4" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc6" + } + } + ] + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "mesh_gateway_local.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/mesh-gateway-ignore-extra-resolvers.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-ignore-extra-resolvers.latest.golden new file mode 100644 index 000000000000..3b77ccca9b99 --- /dev/null +++ b/agent/xds/testdata/listeners/mesh-gateway-ignore-extra-resolvers.latest.golden @@ -0,0 +1,96 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc2" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc4" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc6" + } + } + ] + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "mesh_gateway_local.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/mesh-gateway-newer-information-in-federation-states.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-newer-information-in-federation-states.latest.golden new file mode 100644 index 000000000000..3b77ccca9b99 --- /dev/null +++ b/agent/xds/testdata/listeners/mesh-gateway-newer-information-in-federation-states.latest.golden @@ -0,0 +1,96 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc2" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc4" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc6" + } + } + ] + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "mesh_gateway_local.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/mesh-gateway-non-hash-lb-injected.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-non-hash-lb-injected.latest.golden new file mode 100644 index 000000000000..3b77ccca9b99 --- /dev/null +++ b/agent/xds/testdata/listeners/mesh-gateway-non-hash-lb-injected.latest.golden @@ -0,0 +1,96 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc2" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc4" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc6" + } + } + ] + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "mesh_gateway_local.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/mesh-gateway-older-information-in-federation-states.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-older-information-in-federation-states.latest.golden new file mode 100644 index 000000000000..3b77ccca9b99 --- /dev/null +++ b/agent/xds/testdata/listeners/mesh-gateway-older-information-in-federation-states.latest.golden @@ -0,0 +1,96 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc2" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc4" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc6" + } + } + ] + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "mesh_gateway_local.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/mesh-gateway-service-subsets.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-service-subsets.latest.golden new file mode 100644 index 000000000000..3b77ccca9b99 --- /dev/null +++ b/agent/xds/testdata/listeners/mesh-gateway-service-subsets.latest.golden @@ -0,0 +1,96 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc2" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc4" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc6" + } + } + ] + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "mesh_gateway_local.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/mesh-gateway-service-subsets2.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-service-subsets2.latest.golden new file mode 100644 index 000000000000..3b77ccca9b99 --- /dev/null +++ b/agent/xds/testdata/listeners/mesh-gateway-service-subsets2.latest.golden @@ -0,0 +1,96 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc2" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc4" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc6" + } + } + ] + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "mesh_gateway_local.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/mesh-gateway-service-timeouts.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-service-timeouts.latest.golden new file mode 100644 index 000000000000..3b77ccca9b99 --- /dev/null +++ b/agent/xds/testdata/listeners/mesh-gateway-service-timeouts.latest.golden @@ -0,0 +1,96 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc2" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc4" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc6" + } + } + ] + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "mesh_gateway_local.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/mesh-gateway-tcp-keepalives.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-tcp-keepalives.latest.golden new file mode 100644 index 000000000000..3b77ccca9b99 --- /dev/null +++ b/agent/xds/testdata/listeners/mesh-gateway-tcp-keepalives.latest.golden @@ -0,0 +1,96 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc2" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc4" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc6" + } + } + ] + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "mesh_gateway_local.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/mesh-gateway-with-limits.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-with-limits.latest.golden new file mode 100644 index 000000000000..3b77ccca9b99 --- /dev/null +++ b/agent/xds/testdata/listeners/mesh-gateway-with-limits.latest.golden @@ -0,0 +1,96 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc2" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc4" + } + } + ] + }, + { + "filterChainMatch": { + "serverNames": [ + "*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "mesh_gateway_remote.default.dc6" + } + } + ] + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "mesh_gateway_local.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/terminating-gateway-default-service-subset.latest.golden b/agent/xds/testdata/listeners/terminating-gateway-default-service-subset.latest.golden new file mode 100644 index 000000000000..7f77ee4de3f8 --- /dev/null +++ b/agent/xds/testdata/listeners/terminating-gateway-default-service-subset.latest.golden @@ -0,0 +1,346 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.api.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkKgAwIBAgIRAJrvEdaRAkSltrotd/l/j2cwCgYIKoZIzj0EAwIwgbgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjE/MD0GA1UEAxM2Q29uc3VsIEFnZW50IENB\nIDk2NjM4NzM1MDkzNTU5NTIwNDk3MTQwOTU3MDY1MTc0OTg3NDMxMB4XDTIwMDQx\nNDIyMzE1MloXDTIxMDQxNDIyMzE1MlowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j\nb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ4v0FoIYI0OWmxE2MR6w5l\n0pWGhc02RpsOPj/6RS1fmXMMu7JzPzwCmkGcR16RlwwhNFKCZsWpvAjVRHf/pTp+\no4HHMIHEMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\nBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgk7kABFitAy3PluyNtmzYiC7H\njSN8W/K/OXNJQAQAscMwKwYDVR0jBCQwIoAgNKbPPepvRHXSAPTc+a/BXBzFX1qJ\ny+Zi7qtjlFX7qtUwLQYDVR0RBCYwJIIRc2VydmVyLmRjMS5jb25zdWyCCWxvY2Fs\naG9zdIcEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAhP4HmN5BWysWTbQWClXaWUah\nLpBGFrvc/2cCQuyEZKsCIQD6JyYCYMArtWwZ4G499zktxrFlqfX14bqyONrxtA5I\nDw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIE3KbKXHdsa0vvC1fysQaGdoJRgjRALIolI4XJanie+coAoGCCqGSM49\nAwEHoUQDQgAEOL9BaCGCNDlpsRNjEesOZdKVhoXNNkabDj4/+kUtX5lzDLuycz88\nAppBnEdekZcMITRSgmbFqbwI1UR3/6U6fg==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.cache.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkOgAwIBAgIRAKF+qDJbaOULNL1TIatrsBowCgYIKoZIzj0EAwIwgbkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB\nIDE4Nzg3MDAwNjUzMDcxOTYzNTk1ODkwNTE1ODY1NjEzMDA2MTU0NDAeFw0yMDA2\nMTkxNTMxMzRaFw0yMTA2MTkxNTMxMzRaMBwxGjAYBgNVBAMTEXNlcnZlci5kYzEu\nY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdQ8Igci5f7ZvvCVsxXt9\ntLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZbz/82EwPoS7Dqo3LTK4IuelOimoNNxuk\nkaOBxzCBxDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\nAQUFBwMCMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEILzTLkfJcdWQnTMKUcai/YJq\n0RqH1pjCqtY7SOU4gGOTMCsGA1UdIwQkMCKAIMa2vNcTEC5AGfHIYARJ/4sodX0o\nLzCj3lpw7BcEzPTcMC0GA1UdEQQmMCSCEXNlcnZlci5kYzEuY29uc3Vsgglsb2Nh\nbGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIgBZ/Z4GSLEc98WvT/qjTVCNTG\n1WNaAaesVbkRx+J0yl8CIQDAVoqY9ByA5vKHjnQrxWlc/JUtJz8wudg7e/OCRriP\nSg==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIN1v14FaNxgY4MgjDOOWthen8dgwB0lNMs9/j2TfrnxzoAoGCCqGSM49\nAwEHoUQDQgAEdQ8Igci5f7ZvvCVsxXt9tLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZ\nbz/82EwPoS7Dqo3LTK4IuelOimoNNxukkQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.web.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.web.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.web.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "terminating_gateway.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/terminating-gateway-hostname-service-subsets.latest.golden b/agent/xds/testdata/listeners/terminating-gateway-hostname-service-subsets.latest.golden new file mode 100644 index 000000000000..85a4720d732d --- /dev/null +++ b/agent/xds/testdata/listeners/terminating-gateway-hostname-service-subsets.latest.golden @@ -0,0 +1,462 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.api.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkKgAwIBAgIRAJrvEdaRAkSltrotd/l/j2cwCgYIKoZIzj0EAwIwgbgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjE/MD0GA1UEAxM2Q29uc3VsIEFnZW50IENB\nIDk2NjM4NzM1MDkzNTU5NTIwNDk3MTQwOTU3MDY1MTc0OTg3NDMxMB4XDTIwMDQx\nNDIyMzE1MloXDTIxMDQxNDIyMzE1MlowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j\nb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ4v0FoIYI0OWmxE2MR6w5l\n0pWGhc02RpsOPj/6RS1fmXMMu7JzPzwCmkGcR16RlwwhNFKCZsWpvAjVRHf/pTp+\no4HHMIHEMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\nBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgk7kABFitAy3PluyNtmzYiC7H\njSN8W/K/OXNJQAQAscMwKwYDVR0jBCQwIoAgNKbPPepvRHXSAPTc+a/BXBzFX1qJ\ny+Zi7qtjlFX7qtUwLQYDVR0RBCYwJIIRc2VydmVyLmRjMS5jb25zdWyCCWxvY2Fs\naG9zdIcEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAhP4HmN5BWysWTbQWClXaWUah\nLpBGFrvc/2cCQuyEZKsCIQD6JyYCYMArtWwZ4G499zktxrFlqfX14bqyONrxtA5I\nDw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIE3KbKXHdsa0vvC1fysQaGdoJRgjRALIolI4XJanie+coAoGCCqGSM49\nAwEHoUQDQgAEOL9BaCGCNDlpsRNjEesOZdKVhoXNNkabDj4/+kUtX5lzDLuycz88\nAppBnEdekZcMITRSgmbFqbwI1UR3/6U6fg==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.api.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkKgAwIBAgIRAJrvEdaRAkSltrotd/l/j2cwCgYIKoZIzj0EAwIwgbgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjE/MD0GA1UEAxM2Q29uc3VsIEFnZW50IENB\nIDk2NjM4NzM1MDkzNTU5NTIwNDk3MTQwOTU3MDY1MTc0OTg3NDMxMB4XDTIwMDQx\nNDIyMzE1MloXDTIxMDQxNDIyMzE1MlowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j\nb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ4v0FoIYI0OWmxE2MR6w5l\n0pWGhc02RpsOPj/6RS1fmXMMu7JzPzwCmkGcR16RlwwhNFKCZsWpvAjVRHf/pTp+\no4HHMIHEMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\nBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgk7kABFitAy3PluyNtmzYiC7H\njSN8W/K/OXNJQAQAscMwKwYDVR0jBCQwIoAgNKbPPepvRHXSAPTc+a/BXBzFX1qJ\ny+Zi7qtjlFX7qtUwLQYDVR0RBCYwJIIRc2VydmVyLmRjMS5jb25zdWyCCWxvY2Fs\naG9zdIcEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAhP4HmN5BWysWTbQWClXaWUah\nLpBGFrvc/2cCQuyEZKsCIQD6JyYCYMArtWwZ4G499zktxrFlqfX14bqyONrxtA5I\nDw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIE3KbKXHdsa0vvC1fysQaGdoJRgjRALIolI4XJanie+coAoGCCqGSM49\nAwEHoUQDQgAEOL9BaCGCNDlpsRNjEesOZdKVhoXNNkabDj4/+kUtX5lzDLuycz88\nAppBnEdekZcMITRSgmbFqbwI1UR3/6U6fg==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.cache.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkOgAwIBAgIRAKF+qDJbaOULNL1TIatrsBowCgYIKoZIzj0EAwIwgbkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB\nIDE4Nzg3MDAwNjUzMDcxOTYzNTk1ODkwNTE1ODY1NjEzMDA2MTU0NDAeFw0yMDA2\nMTkxNTMxMzRaFw0yMTA2MTkxNTMxMzRaMBwxGjAYBgNVBAMTEXNlcnZlci5kYzEu\nY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdQ8Igci5f7ZvvCVsxXt9\ntLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZbz/82EwPoS7Dqo3LTK4IuelOimoNNxuk\nkaOBxzCBxDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\nAQUFBwMCMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEILzTLkfJcdWQnTMKUcai/YJq\n0RqH1pjCqtY7SOU4gGOTMCsGA1UdIwQkMCKAIMa2vNcTEC5AGfHIYARJ/4sodX0o\nLzCj3lpw7BcEzPTcMC0GA1UdEQQmMCSCEXNlcnZlci5kYzEuY29uc3Vsgglsb2Nh\nbGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIgBZ/Z4GSLEc98WvT/qjTVCNTG\n1WNaAaesVbkRx+J0yl8CIQDAVoqY9ByA5vKHjnQrxWlc/JUtJz8wudg7e/OCRriP\nSg==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIN1v14FaNxgY4MgjDOOWthen8dgwB0lNMs9/j2TfrnxzoAoGCCqGSM49\nAwEHoUQDQgAEdQ8Igci5f7ZvvCVsxXt9tLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZ\nbz/82EwPoS7Dqo3LTK4IuelOimoNNxukkQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.cache.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.web.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "terminating_gateway.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/terminating-gateway-http2-upstream-subsets.latest.golden b/agent/xds/testdata/listeners/terminating-gateway-http2-upstream-subsets.latest.golden new file mode 100644 index 000000000000..1e4dd317a769 --- /dev/null +++ b/agent/xds/testdata/listeners/terminating-gateway-http2-upstream-subsets.latest.golden @@ -0,0 +1,46 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "terminating_gateway.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/terminating-gateway-http2-upstream.latest.golden b/agent/xds/testdata/listeners/terminating-gateway-http2-upstream.latest.golden new file mode 100644 index 000000000000..1e4dd317a769 --- /dev/null +++ b/agent/xds/testdata/listeners/terminating-gateway-http2-upstream.latest.golden @@ -0,0 +1,46 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "terminating_gateway.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/terminating-gateway-ignore-extra-resolvers.latest.golden b/agent/xds/testdata/listeners/terminating-gateway-ignore-extra-resolvers.latest.golden new file mode 100644 index 000000000000..a508e82d5159 --- /dev/null +++ b/agent/xds/testdata/listeners/terminating-gateway-ignore-extra-resolvers.latest.golden @@ -0,0 +1,433 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.api.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkKgAwIBAgIRAJrvEdaRAkSltrotd/l/j2cwCgYIKoZIzj0EAwIwgbgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjE/MD0GA1UEAxM2Q29uc3VsIEFnZW50IENB\nIDk2NjM4NzM1MDkzNTU5NTIwNDk3MTQwOTU3MDY1MTc0OTg3NDMxMB4XDTIwMDQx\nNDIyMzE1MloXDTIxMDQxNDIyMzE1MlowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j\nb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ4v0FoIYI0OWmxE2MR6w5l\n0pWGhc02RpsOPj/6RS1fmXMMu7JzPzwCmkGcR16RlwwhNFKCZsWpvAjVRHf/pTp+\no4HHMIHEMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\nBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgk7kABFitAy3PluyNtmzYiC7H\njSN8W/K/OXNJQAQAscMwKwYDVR0jBCQwIoAgNKbPPepvRHXSAPTc+a/BXBzFX1qJ\ny+Zi7qtjlFX7qtUwLQYDVR0RBCYwJIIRc2VydmVyLmRjMS5jb25zdWyCCWxvY2Fs\naG9zdIcEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAhP4HmN5BWysWTbQWClXaWUah\nLpBGFrvc/2cCQuyEZKsCIQD6JyYCYMArtWwZ4G499zktxrFlqfX14bqyONrxtA5I\nDw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIE3KbKXHdsa0vvC1fysQaGdoJRgjRALIolI4XJanie+coAoGCCqGSM49\nAwEHoUQDQgAEOL9BaCGCNDlpsRNjEesOZdKVhoXNNkabDj4/+kUtX5lzDLuycz88\nAppBnEdekZcMITRSgmbFqbwI1UR3/6U6fg==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.cache.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkOgAwIBAgIRAKF+qDJbaOULNL1TIatrsBowCgYIKoZIzj0EAwIwgbkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB\nIDE4Nzg3MDAwNjUzMDcxOTYzNTk1ODkwNTE1ODY1NjEzMDA2MTU0NDAeFw0yMDA2\nMTkxNTMxMzRaFw0yMTA2MTkxNTMxMzRaMBwxGjAYBgNVBAMTEXNlcnZlci5kYzEu\nY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdQ8Igci5f7ZvvCVsxXt9\ntLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZbz/82EwPoS7Dqo3LTK4IuelOimoNNxuk\nkaOBxzCBxDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\nAQUFBwMCMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEILzTLkfJcdWQnTMKUcai/YJq\n0RqH1pjCqtY7SOU4gGOTMCsGA1UdIwQkMCKAIMa2vNcTEC5AGfHIYARJ/4sodX0o\nLzCj3lpw7BcEzPTcMC0GA1UdEQQmMCSCEXNlcnZlci5kYzEuY29uc3Vsgglsb2Nh\nbGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIgBZ/Z4GSLEc98WvT/qjTVCNTG\n1WNaAaesVbkRx+J0yl8CIQDAVoqY9ByA5vKHjnQrxWlc/JUtJz8wudg7e/OCRriP\nSg==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIN1v14FaNxgY4MgjDOOWthen8dgwB0lNMs9/j2TfrnxzoAoGCCqGSM49\nAwEHoUQDQgAEdQ8Igci5f7ZvvCVsxXt9tLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZ\nbz/82EwPoS7Dqo3LTK4IuelOimoNNxukkQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.web.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.web.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.web.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "terminating_gateway.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/terminating-gateway-lb-config-no-hash-policies.latest.golden b/agent/xds/testdata/listeners/terminating-gateway-lb-config-no-hash-policies.latest.golden new file mode 100644 index 000000000000..a508e82d5159 --- /dev/null +++ b/agent/xds/testdata/listeners/terminating-gateway-lb-config-no-hash-policies.latest.golden @@ -0,0 +1,433 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.api.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkKgAwIBAgIRAJrvEdaRAkSltrotd/l/j2cwCgYIKoZIzj0EAwIwgbgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjE/MD0GA1UEAxM2Q29uc3VsIEFnZW50IENB\nIDk2NjM4NzM1MDkzNTU5NTIwNDk3MTQwOTU3MDY1MTc0OTg3NDMxMB4XDTIwMDQx\nNDIyMzE1MloXDTIxMDQxNDIyMzE1MlowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j\nb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ4v0FoIYI0OWmxE2MR6w5l\n0pWGhc02RpsOPj/6RS1fmXMMu7JzPzwCmkGcR16RlwwhNFKCZsWpvAjVRHf/pTp+\no4HHMIHEMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\nBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgk7kABFitAy3PluyNtmzYiC7H\njSN8W/K/OXNJQAQAscMwKwYDVR0jBCQwIoAgNKbPPepvRHXSAPTc+a/BXBzFX1qJ\ny+Zi7qtjlFX7qtUwLQYDVR0RBCYwJIIRc2VydmVyLmRjMS5jb25zdWyCCWxvY2Fs\naG9zdIcEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAhP4HmN5BWysWTbQWClXaWUah\nLpBGFrvc/2cCQuyEZKsCIQD6JyYCYMArtWwZ4G499zktxrFlqfX14bqyONrxtA5I\nDw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIE3KbKXHdsa0vvC1fysQaGdoJRgjRALIolI4XJanie+coAoGCCqGSM49\nAwEHoUQDQgAEOL9BaCGCNDlpsRNjEesOZdKVhoXNNkabDj4/+kUtX5lzDLuycz88\nAppBnEdekZcMITRSgmbFqbwI1UR3/6U6fg==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.cache.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkOgAwIBAgIRAKF+qDJbaOULNL1TIatrsBowCgYIKoZIzj0EAwIwgbkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB\nIDE4Nzg3MDAwNjUzMDcxOTYzNTk1ODkwNTE1ODY1NjEzMDA2MTU0NDAeFw0yMDA2\nMTkxNTMxMzRaFw0yMTA2MTkxNTMxMzRaMBwxGjAYBgNVBAMTEXNlcnZlci5kYzEu\nY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdQ8Igci5f7ZvvCVsxXt9\ntLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZbz/82EwPoS7Dqo3LTK4IuelOimoNNxuk\nkaOBxzCBxDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\nAQUFBwMCMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEILzTLkfJcdWQnTMKUcai/YJq\n0RqH1pjCqtY7SOU4gGOTMCsGA1UdIwQkMCKAIMa2vNcTEC5AGfHIYARJ/4sodX0o\nLzCj3lpw7BcEzPTcMC0GA1UdEQQmMCSCEXNlcnZlci5kYzEuY29uc3Vsgglsb2Nh\nbGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIgBZ/Z4GSLEc98WvT/qjTVCNTG\n1WNaAaesVbkRx+J0yl8CIQDAVoqY9ByA5vKHjnQrxWlc/JUtJz8wudg7e/OCRriP\nSg==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIN1v14FaNxgY4MgjDOOWthen8dgwB0lNMs9/j2TfrnxzoAoGCCqGSM49\nAwEHoUQDQgAEdQ8Igci5f7ZvvCVsxXt9tLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZ\nbz/82EwPoS7Dqo3LTK4IuelOimoNNxukkQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.web.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.web.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.web.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "terminating_gateway.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/terminating-gateway-lb-config.latest.golden b/agent/xds/testdata/listeners/terminating-gateway-lb-config.latest.golden new file mode 100644 index 000000000000..a508e82d5159 --- /dev/null +++ b/agent/xds/testdata/listeners/terminating-gateway-lb-config.latest.golden @@ -0,0 +1,433 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.api.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkKgAwIBAgIRAJrvEdaRAkSltrotd/l/j2cwCgYIKoZIzj0EAwIwgbgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjE/MD0GA1UEAxM2Q29uc3VsIEFnZW50IENB\nIDk2NjM4NzM1MDkzNTU5NTIwNDk3MTQwOTU3MDY1MTc0OTg3NDMxMB4XDTIwMDQx\nNDIyMzE1MloXDTIxMDQxNDIyMzE1MlowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j\nb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ4v0FoIYI0OWmxE2MR6w5l\n0pWGhc02RpsOPj/6RS1fmXMMu7JzPzwCmkGcR16RlwwhNFKCZsWpvAjVRHf/pTp+\no4HHMIHEMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\nBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgk7kABFitAy3PluyNtmzYiC7H\njSN8W/K/OXNJQAQAscMwKwYDVR0jBCQwIoAgNKbPPepvRHXSAPTc+a/BXBzFX1qJ\ny+Zi7qtjlFX7qtUwLQYDVR0RBCYwJIIRc2VydmVyLmRjMS5jb25zdWyCCWxvY2Fs\naG9zdIcEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAhP4HmN5BWysWTbQWClXaWUah\nLpBGFrvc/2cCQuyEZKsCIQD6JyYCYMArtWwZ4G499zktxrFlqfX14bqyONrxtA5I\nDw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIE3KbKXHdsa0vvC1fysQaGdoJRgjRALIolI4XJanie+coAoGCCqGSM49\nAwEHoUQDQgAEOL9BaCGCNDlpsRNjEesOZdKVhoXNNkabDj4/+kUtX5lzDLuycz88\nAppBnEdekZcMITRSgmbFqbwI1UR3/6U6fg==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.cache.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkOgAwIBAgIRAKF+qDJbaOULNL1TIatrsBowCgYIKoZIzj0EAwIwgbkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB\nIDE4Nzg3MDAwNjUzMDcxOTYzNTk1ODkwNTE1ODY1NjEzMDA2MTU0NDAeFw0yMDA2\nMTkxNTMxMzRaFw0yMTA2MTkxNTMxMzRaMBwxGjAYBgNVBAMTEXNlcnZlci5kYzEu\nY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdQ8Igci5f7ZvvCVsxXt9\ntLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZbz/82EwPoS7Dqo3LTK4IuelOimoNNxuk\nkaOBxzCBxDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\nAQUFBwMCMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEILzTLkfJcdWQnTMKUcai/YJq\n0RqH1pjCqtY7SOU4gGOTMCsGA1UdIwQkMCKAIMa2vNcTEC5AGfHIYARJ/4sodX0o\nLzCj3lpw7BcEzPTcMC0GA1UdEQQmMCSCEXNlcnZlci5kYzEuY29uc3Vsgglsb2Nh\nbGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIgBZ/Z4GSLEc98WvT/qjTVCNTG\n1WNaAaesVbkRx+J0yl8CIQDAVoqY9ByA5vKHjnQrxWlc/JUtJz8wudg7e/OCRriP\nSg==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIN1v14FaNxgY4MgjDOOWthen8dgwB0lNMs9/j2TfrnxzoAoGCCqGSM49\nAwEHoUQDQgAEdQ8Igci5f7ZvvCVsxXt9tLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZ\nbz/82EwPoS7Dqo3LTK4IuelOimoNNxukkQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.web.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.web.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.web.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "terminating_gateway.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/terminating-gateway-service-subsets.latest.golden b/agent/xds/testdata/listeners/terminating-gateway-service-subsets.latest.golden index a508e82d5159..61c0f6e3b98d 100644 --- a/agent/xds/testdata/listeners/terminating-gateway-service-subsets.latest.golden +++ b/agent/xds/testdata/listeners/terminating-gateway-service-subsets.latest.golden @@ -160,6 +160,56 @@ } } }, + { + "filterChainMatch": { + "serverNames": [ + "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.cache.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, { "filterChainMatch": { "serverNames": [ diff --git a/agent/xds/testdata/listeners/terminating-gateway-sni.latest.golden b/agent/xds/testdata/listeners/terminating-gateway-sni.latest.golden new file mode 100644 index 000000000000..45ad9d29a095 --- /dev/null +++ b/agent/xds/testdata/listeners/terminating-gateway-sni.latest.golden @@ -0,0 +1,246 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.api.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkKgAwIBAgIRAJrvEdaRAkSltrotd/l/j2cwCgYIKoZIzj0EAwIwgbgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjE/MD0GA1UEAxM2Q29uc3VsIEFnZW50IENB\nIDk2NjM4NzM1MDkzNTU5NTIwNDk3MTQwOTU3MDY1MTc0OTg3NDMxMB4XDTIwMDQx\nNDIyMzE1MloXDTIxMDQxNDIyMzE1MlowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j\nb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ4v0FoIYI0OWmxE2MR6w5l\n0pWGhc02RpsOPj/6RS1fmXMMu7JzPzwCmkGcR16RlwwhNFKCZsWpvAjVRHf/pTp+\no4HHMIHEMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\nBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgk7kABFitAy3PluyNtmzYiC7H\njSN8W/K/OXNJQAQAscMwKwYDVR0jBCQwIoAgNKbPPepvRHXSAPTc+a/BXBzFX1qJ\ny+Zi7qtjlFX7qtUwLQYDVR0RBCYwJIIRc2VydmVyLmRjMS5jb25zdWyCCWxvY2Fs\naG9zdIcEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAhP4HmN5BWysWTbQWClXaWUah\nLpBGFrvc/2cCQuyEZKsCIQD6JyYCYMArtWwZ4G499zktxrFlqfX14bqyONrxtA5I\nDw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIE3KbKXHdsa0vvC1fysQaGdoJRgjRALIolI4XJanie+coAoGCCqGSM49\nAwEHoUQDQgAEOL9BaCGCNDlpsRNjEesOZdKVhoXNNkabDj4/+kUtX5lzDLuycz88\nAppBnEdekZcMITRSgmbFqbwI1UR3/6U6fg==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.cache.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkOgAwIBAgIRAKF+qDJbaOULNL1TIatrsBowCgYIKoZIzj0EAwIwgbkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB\nIDE4Nzg3MDAwNjUzMDcxOTYzNTk1ODkwNTE1ODY1NjEzMDA2MTU0NDAeFw0yMDA2\nMTkxNTMxMzRaFw0yMTA2MTkxNTMxMzRaMBwxGjAYBgNVBAMTEXNlcnZlci5kYzEu\nY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdQ8Igci5f7ZvvCVsxXt9\ntLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZbz/82EwPoS7Dqo3LTK4IuelOimoNNxuk\nkaOBxzCBxDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\nAQUFBwMCMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEILzTLkfJcdWQnTMKUcai/YJq\n0RqH1pjCqtY7SOU4gGOTMCsGA1UdIwQkMCKAIMa2vNcTEC5AGfHIYARJ/4sodX0o\nLzCj3lpw7BcEzPTcMC0GA1UdEQQmMCSCEXNlcnZlci5kYzEuY29uc3Vsgglsb2Nh\nbGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIgBZ/Z4GSLEc98WvT/qjTVCNTG\n1WNaAaesVbkRx+J0yl8CIQDAVoqY9ByA5vKHjnQrxWlc/JUtJz8wudg7e/OCRriP\nSg==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIN1v14FaNxgY4MgjDOOWthen8dgwB0lNMs9/j2TfrnxzoAoGCCqGSM49\nAwEHoUQDQgAEdQ8Igci5f7ZvvCVsxXt9tLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZ\nbz/82EwPoS7Dqo3LTK4IuelOimoNNxukkQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.web.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "terminating_gateway.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/terminating-gateway-tcp-keepalives.latest.golden b/agent/xds/testdata/listeners/terminating-gateway-tcp-keepalives.latest.golden new file mode 100644 index 000000000000..45ad9d29a095 --- /dev/null +++ b/agent/xds/testdata/listeners/terminating-gateway-tcp-keepalives.latest.golden @@ -0,0 +1,246 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.api.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkKgAwIBAgIRAJrvEdaRAkSltrotd/l/j2cwCgYIKoZIzj0EAwIwgbgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjE/MD0GA1UEAxM2Q29uc3VsIEFnZW50IENB\nIDk2NjM4NzM1MDkzNTU5NTIwNDk3MTQwOTU3MDY1MTc0OTg3NDMxMB4XDTIwMDQx\nNDIyMzE1MloXDTIxMDQxNDIyMzE1MlowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j\nb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ4v0FoIYI0OWmxE2MR6w5l\n0pWGhc02RpsOPj/6RS1fmXMMu7JzPzwCmkGcR16RlwwhNFKCZsWpvAjVRHf/pTp+\no4HHMIHEMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\nBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgk7kABFitAy3PluyNtmzYiC7H\njSN8W/K/OXNJQAQAscMwKwYDVR0jBCQwIoAgNKbPPepvRHXSAPTc+a/BXBzFX1qJ\ny+Zi7qtjlFX7qtUwLQYDVR0RBCYwJIIRc2VydmVyLmRjMS5jb25zdWyCCWxvY2Fs\naG9zdIcEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAhP4HmN5BWysWTbQWClXaWUah\nLpBGFrvc/2cCQuyEZKsCIQD6JyYCYMArtWwZ4G499zktxrFlqfX14bqyONrxtA5I\nDw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIE3KbKXHdsa0vvC1fysQaGdoJRgjRALIolI4XJanie+coAoGCCqGSM49\nAwEHoUQDQgAEOL9BaCGCNDlpsRNjEesOZdKVhoXNNkabDj4/+kUtX5lzDLuycz88\nAppBnEdekZcMITRSgmbFqbwI1UR3/6U6fg==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.cache.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkOgAwIBAgIRAKF+qDJbaOULNL1TIatrsBowCgYIKoZIzj0EAwIwgbkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB\nIDE4Nzg3MDAwNjUzMDcxOTYzNTk1ODkwNTE1ODY1NjEzMDA2MTU0NDAeFw0yMDA2\nMTkxNTMxMzRaFw0yMTA2MTkxNTMxMzRaMBwxGjAYBgNVBAMTEXNlcnZlci5kYzEu\nY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdQ8Igci5f7ZvvCVsxXt9\ntLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZbz/82EwPoS7Dqo3LTK4IuelOimoNNxuk\nkaOBxzCBxDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\nAQUFBwMCMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEILzTLkfJcdWQnTMKUcai/YJq\n0RqH1pjCqtY7SOU4gGOTMCsGA1UdIwQkMCKAIMa2vNcTEC5AGfHIYARJ/4sodX0o\nLzCj3lpw7BcEzPTcMC0GA1UdEQQmMCSCEXNlcnZlci5kYzEuY29uc3Vsgglsb2Nh\nbGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIgBZ/Z4GSLEc98WvT/qjTVCNTG\n1WNaAaesVbkRx+J0yl8CIQDAVoqY9ByA5vKHjnQrxWlc/JUtJz8wudg7e/OCRriP\nSg==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIN1v14FaNxgY4MgjDOOWthen8dgwB0lNMs9/j2TfrnxzoAoGCCqGSM49\nAwEHoUQDQgAEdQ8Igci5f7ZvvCVsxXt9tLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZ\nbz/82EwPoS7Dqo3LTK4IuelOimoNNxukkQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.web.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "terminating_gateway.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/terminating-gateway-with-peer-trust-bundle.latest.golden b/agent/xds/testdata/listeners/terminating-gateway-with-peer-trust-bundle.latest.golden index d4b5f848831f..e11a9f724474 100644 --- a/agent/xds/testdata/listeners/terminating-gateway-with-peer-trust-bundle.latest.golden +++ b/agent/xds/testdata/listeners/terminating-gateway-with-peer-trust-bundle.latest.golden @@ -163,7 +163,9 @@ { "filterChainMatch": { "serverNames": [ - "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "web.default.default.peer-a.external.11111111-2222-3333-4444-555555555555.consul", + "web.default.default.peer-b.external.11111111-2222-3333-4444-555555555555.consul" ] }, "filters": [ @@ -184,8 +186,16 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, - "regex": "^spiffe://foo.bar.gov/ns/default/dc/[^/]+/svc/source$" + "regex": "^spiffe://1c053652-8512-4373-90cf-5a7f6263a994.consul/ns/default/dc/[^/]+/svc/source$" + } + } + } + }, + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://d89ac423-e95a-475d-94f2-1c557c57bf31.consul/ns/default/dc/[^/]+/svc/source$" } } } @@ -223,8 +233,31 @@ ], "tlsParams": {}, "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + "customValidatorConfig": { + "name": "envoy.tls.cert_validator.spiffe", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.SPIFFECertValidatorConfig", + "trustDomains": [ + { + "name": "11111111-2222-3333-4444-555555555555.consul", + "trustBundle": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + }, + { + "name": "1c053652-8512-4373-90cf-5a7f6263a994.consul", + "trustBundle": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICczCCAdwCCQC3BLnEmLCrSjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCQVoxEjAQBgNVBAcMCUZsYWdzdGFmZjEMMAoGA1UECgwDRm9v\nMRAwDgYDVQQLDAdleGFtcGxlMQ8wDQYDVQQDDAZwZWVyLWExHTAbBgkqhkiG9w0B\nCQEWDmZvb0BwZWVyLWEuY29tMB4XDTIyMDUyNjAxMDQ0NFoXDTIzMDUyNjAxMDQ0\nNFowfjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkFaMRIwEAYDVQQHDAlGbGFnc3Rh\nZmYxDDAKBgNVBAoMA0ZvbzEQMA4GA1UECwwHZXhhbXBsZTEPMA0GA1UEAwwGcGVl\nci1hMR0wGwYJKoZIhvcNAQkBFg5mb29AcGVlci1hLmNvbTCBnzANBgkqhkiG9w0B\nAQEFAAOBjQAwgYkCgYEA2zFYGTbXDAntT5pLTpZ2+VTiqx4J63VRJH1kdu11f0FV\nc2jl1pqCuYDbQXknDU0Pv1Q5y0+nSAihD2KqGS571r+vHQiPtKYPYRqPEe9FzAhR\n2KhWH6v/tk5DG1HqOjV9/zWRKB12gdFNZZqnw/e7NjLNq3wZ2UAwxXip5uJ8uwMC\nAwEAATANBgkqhkiG9w0BAQsFAAOBgQC/CJ9Syf4aL91wZizKTejwouRYoWv4gRAk\nyto45ZcNMHfJ0G2z+XAMl9ZbQsLgXmzAx4IM6y5Jckq8pKC4PEijCjlKTktLHlEy\n0ggmFxtNB1tid2NC8dOzcQ3l45+gDjDqdILhAvLDjlAIebdkqVqb2CfFNW/I2CQH\nZAuKN1aoKA==\n-----END CERTIFICATE-----\n" + } + }, + { + "name": "d89ac423-e95a-475d-94f2-1c557c57bf31.consul", + "trustBundle": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICcTCCAdoCCQDyGxC08cD0BDANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCENhcmxzYmFkMQwwCgYDVQQKDANGb28x\nEDAOBgNVBAsMB2V4YW1wbGUxDzANBgNVBAMMBnBlZXItYjEdMBsGCSqGSIb3DQEJ\nARYOZm9vQHBlZXItYi5jb20wHhcNMjIwNTI2MDExNjE2WhcNMjMwNTI2MDExNjE2\nWjB9MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCENhcmxzYmFk\nMQwwCgYDVQQKDANGb28xEDAOBgNVBAsMB2V4YW1wbGUxDzANBgNVBAMMBnBlZXIt\nYjEdMBsGCSqGSIb3DQEJARYOZm9vQHBlZXItYi5jb20wgZ8wDQYJKoZIhvcNAQEB\nBQADgY0AMIGJAoGBAL4i5erdZ5vKk3mzW9Qt6Wvw/WN/IpMDlL0a28wz9oDCtMLN\ncD/XQB9yT5jUwb2s4mD1lCDZtee8MHeD8zygICozufWVB+u2KvMaoA50T9GMQD0E\nz/0nz/Z703I4q13VHeTpltmEpYcfxw/7nJ3leKA34+Nj3zteJ70iqvD/TNBBAgMB\nAAEwDQYJKoZIhvcNAQELBQADgYEAbL04gicH+EIznDNhZJEb1guMBtBBJ8kujPyU\nao8xhlUuorDTLwhLpkKsOhD8619oSS8KynjEBichidQRkwxIaze0a2mrGT+tGBMf\npVz6UeCkqpde6bSJ/ozEe/2seQzKqYvRT1oUjLwYvY7OIh2DzYibOAxh6fewYAmU\n5j5qNLc=\n-----END CERTIFICATE-----\n" + } + } + ] + } } } }, diff --git a/agent/xds/testdata/listeners/xds-fetch-timeout-ms-ingress-with-router.latest.golden b/agent/xds/testdata/listeners/xds-fetch-timeout-ms-ingress-with-router.latest.golden new file mode 100644 index 000000000000..905e9966d48e --- /dev/null +++ b/agent/xds/testdata/listeners/xds-fetch-timeout-ms-ingress-with-router.latest.golden @@ -0,0 +1,55 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8080 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + }, + "routeConfigName": "8080" + }, + "statPrefix": "ingress_upstream_8080", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "http:1.2.3.4:8080", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/xds-fetch-timeout-ms-mgw-peering.latest.golden b/agent/xds/testdata/listeners/xds-fetch-timeout-ms-mgw-peering.latest.golden new file mode 100644 index 000000000000..d6ae12cfc49f --- /dev/null +++ b/agent/xds/testdata/listeners/xds-fetch-timeout-ms-mgw-peering.latest.golden @@ -0,0 +1,315 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "bar.default.default.peer-a.external.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "SANITIZE_SET", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + }, + "routeConfigName": "bar" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "mesh_gateway_local_peered.bar.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "customValidatorConfig": { + "name": "envoy.tls.cert_validator.spiffe", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.SPIFFECertValidatorConfig", + "trustDomains": [ + { + "name": "11111111-2222-3333-4444-555555555555.consul", + "trustBundle": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + }, + { + "name": "1c053652-8512-4373-90cf-5a7f6263a994.consul", + "trustBundle": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICczCCAdwCCQC3BLnEmLCrSjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCQVoxEjAQBgNVBAcMCUZsYWdzdGFmZjEMMAoGA1UECgwDRm9v\nMRAwDgYDVQQLDAdleGFtcGxlMQ8wDQYDVQQDDAZwZWVyLWExHTAbBgkqhkiG9w0B\nCQEWDmZvb0BwZWVyLWEuY29tMB4XDTIyMDUyNjAxMDQ0NFoXDTIzMDUyNjAxMDQ0\nNFowfjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkFaMRIwEAYDVQQHDAlGbGFnc3Rh\nZmYxDDAKBgNVBAoMA0ZvbzEQMA4GA1UECwwHZXhhbXBsZTEPMA0GA1UEAwwGcGVl\nci1hMR0wGwYJKoZIhvcNAQkBFg5mb29AcGVlci1hLmNvbTCBnzANBgkqhkiG9w0B\nAQEFAAOBjQAwgYkCgYEA2zFYGTbXDAntT5pLTpZ2+VTiqx4J63VRJH1kdu11f0FV\nc2jl1pqCuYDbQXknDU0Pv1Q5y0+nSAihD2KqGS571r+vHQiPtKYPYRqPEe9FzAhR\n2KhWH6v/tk5DG1HqOjV9/zWRKB12gdFNZZqnw/e7NjLNq3wZ2UAwxXip5uJ8uwMC\nAwEAATANBgkqhkiG9w0BAQsFAAOBgQC/CJ9Syf4aL91wZizKTejwouRYoWv4gRAk\nyto45ZcNMHfJ0G2z+XAMl9ZbQsLgXmzAx4IM6y5Jckq8pKC4PEijCjlKTktLHlEy\n0ggmFxtNB1tid2NC8dOzcQ3l45+gDjDqdILhAvLDjlAIebdkqVqb2CfFNW/I2CQH\nZAuKN1aoKA==\n-----END CERTIFICATE-----\n" + } + } + ] + } + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "foo.default.default.peer-a.external.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "SANITIZE_SET", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + }, + "routeConfigName": "foo" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "mesh_gateway_local_peered.foo.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "customValidatorConfig": { + "name": "envoy.tls.cert_validator.spiffe", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.SPIFFECertValidatorConfig", + "trustDomains": [ + { + "name": "11111111-2222-3333-4444-555555555555.consul", + "trustBundle": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + }, + { + "name": "1c053652-8512-4373-90cf-5a7f6263a994.consul", + "trustBundle": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICczCCAdwCCQC3BLnEmLCrSjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCQVoxEjAQBgNVBAcMCUZsYWdzdGFmZjEMMAoGA1UECgwDRm9v\nMRAwDgYDVQQLDAdleGFtcGxlMQ8wDQYDVQQDDAZwZWVyLWExHTAbBgkqhkiG9w0B\nCQEWDmZvb0BwZWVyLWEuY29tMB4XDTIyMDUyNjAxMDQ0NFoXDTIzMDUyNjAxMDQ0\nNFowfjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkFaMRIwEAYDVQQHDAlGbGFnc3Rh\nZmYxDDAKBgNVBAoMA0ZvbzEQMA4GA1UECwwHZXhhbXBsZTEPMA0GA1UEAwwGcGVl\nci1hMR0wGwYJKoZIhvcNAQkBFg5mb29AcGVlci1hLmNvbTCBnzANBgkqhkiG9w0B\nAQEFAAOBjQAwgYkCgYEA2zFYGTbXDAntT5pLTpZ2+VTiqx4J63VRJH1kdu11f0FV\nc2jl1pqCuYDbQXknDU0Pv1Q5y0+nSAihD2KqGS571r+vHQiPtKYPYRqPEe9FzAhR\n2KhWH6v/tk5DG1HqOjV9/zWRKB12gdFNZZqnw/e7NjLNq3wZ2UAwxXip5uJ8uwMC\nAwEAATANBgkqhkiG9w0BAQsFAAOBgQC/CJ9Syf4aL91wZizKTejwouRYoWv4gRAk\nyto45ZcNMHfJ0G2z+XAMl9ZbQsLgXmzAx4IM6y5Jckq8pKC4PEijCjlKTktLHlEy\n0ggmFxtNB1tid2NC8dOzcQ3l45+gDjDqdILhAvLDjlAIebdkqVqb2CfFNW/I2CQH\nZAuKN1aoKA==\n-----END CERTIFICATE-----\n" + } + } + ] + } + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "gir.default.default.peer-b.external.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "SANITIZE_SET", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + }, + "routeConfigName": "gir" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "mesh_gateway_local_peered.gir.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "customValidatorConfig": { + "name": "envoy.tls.cert_validator.spiffe", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.SPIFFECertValidatorConfig", + "trustDomains": [ + { + "name": "11111111-2222-3333-4444-555555555555.consul", + "trustBundle": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + }, + { + "name": "d89ac423-e95a-475d-94f2-1c557c57bf31.consul", + "trustBundle": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICcTCCAdoCCQDyGxC08cD0BDANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCENhcmxzYmFkMQwwCgYDVQQKDANGb28x\nEDAOBgNVBAsMB2V4YW1wbGUxDzANBgNVBAMMBnBlZXItYjEdMBsGCSqGSIb3DQEJ\nARYOZm9vQHBlZXItYi5jb20wHhcNMjIwNTI2MDExNjE2WhcNMjMwNTI2MDExNjE2\nWjB9MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCENhcmxzYmFk\nMQwwCgYDVQQKDANGb28xEDAOBgNVBAsMB2V4YW1wbGUxDzANBgNVBAMMBnBlZXIt\nYjEdMBsGCSqGSIb3DQEJARYOZm9vQHBlZXItYi5jb20wgZ8wDQYJKoZIhvcNAQEB\nBQADgY0AMIGJAoGBAL4i5erdZ5vKk3mzW9Qt6Wvw/WN/IpMDlL0a28wz9oDCtMLN\ncD/XQB9yT5jUwb2s4mD1lCDZtee8MHeD8zygICozufWVB+u2KvMaoA50T9GMQD0E\nz/0nz/Z703I4q13VHeTpltmEpYcfxw/7nJ3leKA34+Nj3zteJ70iqvD/TNBBAgMB\nAAEwDQYJKoZIhvcNAQELBQADgYEAbL04gicH+EIznDNhZJEb1guMBtBBJ8kujPyU\nao8xhlUuorDTLwhLpkKsOhD8619oSS8KynjEBichidQRkwxIaze0a2mrGT+tGBMf\npVz6UeCkqpde6bSJ/ozEe/2seQzKqYvRT1oUjLwYvY7OIh2DzYibOAxh6fewYAmU\n5j5qNLc=\n-----END CERTIFICATE-----\n" + } + } + ] + } + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "mesh_gateway_local.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/xds-fetch-timeout-ms-sidecar.latest.golden b/agent/xds/testdata/listeners/xds-fetch-timeout-ms-sidecar.latest.golden new file mode 100644 index 000000000000..56802fa0fa1d --- /dev/null +++ b/agent/xds/testdata/listeners/xds-fetch-timeout-ms-sidecar.latest.golden @@ -0,0 +1,138 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + }, + "routeConfigName": "db" + }, + "statPrefix": "upstream.db.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/xds-fetch-timeout-ms-term-gw.latest.golden b/agent/xds/testdata/listeners/xds-fetch-timeout-ms-term-gw.latest.golden new file mode 100644 index 000000000000..ab972459538b --- /dev/null +++ b/agent/xds/testdata/listeners/xds-fetch-timeout-ms-term-gw.latest.golden @@ -0,0 +1,486 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "1.2.3.4", + "portValue": 8443 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "serverNames": [ + "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.api.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkKgAwIBAgIRAJrvEdaRAkSltrotd/l/j2cwCgYIKoZIzj0EAwIwgbgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjE/MD0GA1UEAxM2Q29uc3VsIEFnZW50IENB\nIDk2NjM4NzM1MDkzNTU5NTIwNDk3MTQwOTU3MDY1MTc0OTg3NDMxMB4XDTIwMDQx\nNDIyMzE1MloXDTIxMDQxNDIyMzE1MlowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j\nb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ4v0FoIYI0OWmxE2MR6w5l\n0pWGhc02RpsOPj/6RS1fmXMMu7JzPzwCmkGcR16RlwwhNFKCZsWpvAjVRHf/pTp+\no4HHMIHEMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\nBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgk7kABFitAy3PluyNtmzYiC7H\njSN8W/K/OXNJQAQAscMwKwYDVR0jBCQwIoAgNKbPPepvRHXSAPTc+a/BXBzFX1qJ\ny+Zi7qtjlFX7qtUwLQYDVR0RBCYwJIIRc2VydmVyLmRjMS5jb25zdWyCCWxvY2Fs\naG9zdIcEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAhP4HmN5BWysWTbQWClXaWUah\nLpBGFrvc/2cCQuyEZKsCIQD6JyYCYMArtWwZ4G499zktxrFlqfX14bqyONrxtA5I\nDw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIE3KbKXHdsa0vvC1fysQaGdoJRgjRALIolI4XJanie+coAoGCCqGSM49\nAwEHoUQDQgAEOL9BaCGCNDlpsRNjEesOZdKVhoXNNkabDj4/+kUtX5lzDLuycz88\nAppBnEdekZcMITRSgmbFqbwI1UR3/6U6fg==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.cache.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICnTCCAkOgAwIBAgIRAKF+qDJbaOULNL1TIatrsBowCgYIKoZIzj0EAwIwgbkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw\nFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB\nIDE4Nzg3MDAwNjUzMDcxOTYzNTk1ODkwNTE1ODY1NjEzMDA2MTU0NDAeFw0yMDA2\nMTkxNTMxMzRaFw0yMTA2MTkxNTMxMzRaMBwxGjAYBgNVBAMTEXNlcnZlci5kYzEu\nY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdQ8Igci5f7ZvvCVsxXt9\ntLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZbz/82EwPoS7Dqo3LTK4IuelOimoNNxuk\nkaOBxzCBxDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\nAQUFBwMCMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEILzTLkfJcdWQnTMKUcai/YJq\n0RqH1pjCqtY7SOU4gGOTMCsGA1UdIwQkMCKAIMa2vNcTEC5AGfHIYARJ/4sodX0o\nLzCj3lpw7BcEzPTcMC0GA1UdEQQmMCSCEXNlcnZlci5kYzEuY29uc3Vsgglsb2Nh\nbGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIgBZ/Z4GSLEc98WvT/qjTVCNTG\n1WNaAaesVbkRx+J0yl8CIQDAVoqY9ByA5vKHjnQrxWlc/JUtJz8wudg7e/OCRriP\nSg==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIN1v14FaNxgY4MgjDOOWthen8dgwB0lNMs9/j2TfrnxzoAoGCCqGSM49\nAwEHoUQDQgAEdQ8Igci5f7ZvvCVsxXt9tLfvczD+60XHg0OC0+Aka7ZjQfbEjQwZ\nbz/82EwPoS7Dqo3LTK4IuelOimoNNxukkQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.cache.default.default.dc1" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICmjCCAkGgAwIBAgIQe1ZmC0rzRwer6jaH1YIUIjAKBggqhkjOPQQDAjCBuDEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMT8wPQYDVQQDEzZDb25zdWwgQWdlbnQgQ0Eg\nODE5ODAwNjg0MDM0MTM3ODkyNDYxNTA1MDk0NDU3OTU1MTQxNjEwHhcNMjAwNjE5\nMTU1MjAzWhcNMjEwNjE5MTU1MjAzWjAcMRowGAYDVQQDExFzZXJ2ZXIuZGMxLmNv\nbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH2aWaaa3fpQLBayheHiKlrH\n+z53m0frfGknKjOhOPVYDVHV8x0OE01negswVQbKHAtxPf1M8Zy+WbI9rK7Ua1mj\ngccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\nBQcDAjAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCDf9CPBSUwwZvpeW73oJLTmgQE2\ntW1NKpL5t1uq9WFcqDArBgNVHSMEJDAigCCPPd/NxgZB0tq2M8pdVpPj3Cr79iTv\ni4/T1ysodfMb7zAtBgNVHREEJjAkghFzZXJ2ZXIuZGMxLmNvbnN1bIIJbG9jYWxo\nb3N0hwR/AAABMAoGCCqGSM49BAMCA0cAMEQCIFCjFZAoXq0s2ied2eIBv0i1KoW5\nIhCylnKFt6iHkyDeAiBBCByTcjHRgEQmqyPojQKoO584EFiczTub9aWdnf9tEw==\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINsen3S8xzxMrKcRZIvxXzhKDn43Tw9ttqWEFU9TqS5hoAoGCCqGSM49\nAwEHoUQDQgAEfZpZpprd+lAsFrKF4eIqWsf7PnebR+t8aScqM6E49VgNUdXzHQ4T\nTWd6CzBVBsocC3E9/UzxnL5Zsj2srtRrWQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + }, + "routeConfigName": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.web.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + }, + "routeConfigName": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.web.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filterChainMatch": { + "serverNames": [ + "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "forwardClientCertDetails": "APPEND_FORWARD", + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + }, + "routeConfigName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "setCurrentClientCertDetails": { + "cert": true, + "chain": true, + "dns": true, + "subject": true, + "uri": true + }, + "statPrefix": "upstream.web.default.default.dc1", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + }, + { + "filters": [ + { + "name": "envoy.filters.network.sni_cluster", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "", + "statPrefix": "terminating_gateway.default" + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.tls_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" + } + } + ], + "name": "default:1.2.3.4:8443", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden b/agent/xds/testdata/listeners/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden new file mode 100644 index 000000000000..1454379bec48 --- /dev/null +++ b/agent/xds/testdata/listeners/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden @@ -0,0 +1,189 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9090 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "http2ProtocolOptions": {}, + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "routeConfig": { + "name": "payments?peer=cloud", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "payments.default.cloud", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "payments.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul" + } + } + ] + } + ] + }, + "statPrefix": "upstream_peered.payments.default.cloud", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "payments?peer=cloud:127.0.0.1:9090", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9090 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "http2ProtocolOptions": {}, + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "routeConfig": { + "name": "refunds?peer=cloud", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "refunds.default.cloud", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "refunds.default.cloud.external.1c053652-8512-4373-90cf-5a7f6263a994.consul" + } + } + ] + } + ] + }, + "statPrefix": "upstream_peered.refunds.default.cloud", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "name": "refunds?peer=cloud:127.0.0.1:9090", + "trafficDirection": "OUTBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden b/agent/xds/testdata/listeners/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden new file mode 100644 index 000000000000..367c3aaac7c1 --- /dev/null +++ b/agent/xds/testdata/listeners/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden @@ -0,0 +1,218 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.db.default.default.dc1" + } + } + ] + } + ], + "name": "db:127.0.0.1:9191", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 15001 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "destinationPort": 443 + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + }, + "routeConfigName": "destination.443.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "statPrefix": "upstream.destination.443.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + }, + { + "filterChainMatch": { + "destinationPort": 9093 + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "rds": { + "configSource": { + "ads": {}, + "initialFetchTimeout": "9.999s", + "resourceApiVersion": "V3" + }, + "routeConfigName": "destination.9093.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "statPrefix": "upstream.destination.9093.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "tracing": { + "randomSampling": {} + }, + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.original_dst", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst" + } + }, + { + "name": "envoy.filters.listener.http_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.http_inspector.v3.HttpInspector" + } + } + ], + "name": "outbound_listener:127.0.0.1:15001", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "statPrefix": "upstream.prepared_query_geo-cache" + } + } + ] + } + ], + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "cluster": "local_app", + "statPrefix": "public_listener" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "tlsParams": {}, + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "name": "public_listener:0.0.0.0:9999", + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/default-allow-deny-all-and-path-allow--httpfilter.golden b/agent/xds/testdata/rbac/default-allow-deny-all-and-path-allow--httpfilter.golden index 0659f2c4afc9..e2fe258af053 100644 --- a/agent/xds/testdata/rbac/default-allow-deny-all-and-path-allow--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-allow-deny-all-and-path-allow--httpfilter.golden @@ -19,7 +19,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } @@ -30,7 +29,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-allow-deny-all-and-path-allow.golden b/agent/xds/testdata/rbac/default-allow-deny-all-and-path-allow.golden index 956dd00006cc..7cd13fb8c898 100644 --- a/agent/xds/testdata/rbac/default-allow-deny-all-and-path-allow.golden +++ b/agent/xds/testdata/rbac/default-allow-deny-all-and-path-allow.golden @@ -16,7 +16,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -29,7 +28,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } @@ -40,7 +38,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-allow-deny-all-and-path-deny--httpfilter.golden b/agent/xds/testdata/rbac/default-allow-deny-all-and-path-deny--httpfilter.golden index d57d60bc770b..fda55dac329f 100644 --- a/agent/xds/testdata/rbac/default-allow-deny-all-and-path-deny--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-allow-deny-all-and-path-deny--httpfilter.golden @@ -19,7 +19,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } @@ -30,7 +29,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -57,7 +55,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-allow-deny-all-and-path-deny.golden b/agent/xds/testdata/rbac/default-allow-deny-all-and-path-deny.golden index 956dd00006cc..7cd13fb8c898 100644 --- a/agent/xds/testdata/rbac/default-allow-deny-all-and-path-deny.golden +++ b/agent/xds/testdata/rbac/default-allow-deny-all-and-path-deny.golden @@ -16,7 +16,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -29,7 +28,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } @@ -40,7 +38,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-allow-kitchen-sink--httpfilter.golden b/agent/xds/testdata/rbac/default-allow-kitchen-sink--httpfilter.golden index b220a6d38ed6..568b4fa1245e 100644 --- a/agent/xds/testdata/rbac/default-allow-kitchen-sink--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-allow-kitchen-sink--httpfilter.golden @@ -16,7 +16,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/cron$" } } @@ -26,7 +25,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -39,7 +37,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } @@ -50,7 +47,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -62,7 +58,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/unsafe$" } } @@ -74,7 +69,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/cron$" } } diff --git a/agent/xds/testdata/rbac/default-allow-kitchen-sink.golden b/agent/xds/testdata/rbac/default-allow-kitchen-sink.golden index 6bb4e9e2ff2e..7d6aebd7c7fb 100644 --- a/agent/xds/testdata/rbac/default-allow-kitchen-sink.golden +++ b/agent/xds/testdata/rbac/default-allow-kitchen-sink.golden @@ -16,7 +16,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/cron$" } } @@ -26,7 +25,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -39,7 +37,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } @@ -50,7 +47,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -62,7 +58,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/unsafe$" } } @@ -74,7 +69,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/cron$" } } diff --git a/agent/xds/testdata/rbac/default-allow-one-deny--httpfilter.golden b/agent/xds/testdata/rbac/default-allow-one-deny--httpfilter.golden index 851499ce9796..75497aca4bc1 100644 --- a/agent/xds/testdata/rbac/default-allow-one-deny--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-allow-one-deny--httpfilter.golden @@ -16,7 +16,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-allow-one-deny.golden b/agent/xds/testdata/rbac/default-allow-one-deny.golden index 19f25b92ff5f..f0dacb3ef1fe 100644 --- a/agent/xds/testdata/rbac/default-allow-one-deny.golden +++ b/agent/xds/testdata/rbac/default-allow-one-deny.golden @@ -16,7 +16,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-allow-path-allow.golden b/agent/xds/testdata/rbac/default-allow-path-allow.golden index 19f25b92ff5f..f0dacb3ef1fe 100644 --- a/agent/xds/testdata/rbac/default-allow-path-allow.golden +++ b/agent/xds/testdata/rbac/default-allow-path-allow.golden @@ -16,7 +16,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-allow-path-deny--httpfilter.golden b/agent/xds/testdata/rbac/default-allow-path-deny--httpfilter.golden index fc818d19ec37..9aaf467011fc 100644 --- a/agent/xds/testdata/rbac/default-allow-path-deny--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-allow-path-deny--httpfilter.golden @@ -20,7 +20,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-allow-path-deny.golden b/agent/xds/testdata/rbac/default-allow-path-deny.golden index 19f25b92ff5f..f0dacb3ef1fe 100644 --- a/agent/xds/testdata/rbac/default-allow-path-deny.golden +++ b/agent/xds/testdata/rbac/default-allow-path-deny.golden @@ -16,7 +16,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-allow-service-wildcard-deny--httpfilter.golden b/agent/xds/testdata/rbac/default-allow-service-wildcard-deny--httpfilter.golden index c16e12089d06..e1f14bf632a1 100644 --- a/agent/xds/testdata/rbac/default-allow-service-wildcard-deny--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-allow-service-wildcard-deny--httpfilter.golden @@ -16,7 +16,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } diff --git a/agent/xds/testdata/rbac/default-allow-service-wildcard-deny.golden b/agent/xds/testdata/rbac/default-allow-service-wildcard-deny.golden index 907c9e06b1f4..f9dc08623f2b 100644 --- a/agent/xds/testdata/rbac/default-allow-service-wildcard-deny.golden +++ b/agent/xds/testdata/rbac/default-allow-service-wildcard-deny.golden @@ -16,7 +16,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } diff --git a/agent/xds/testdata/rbac/default-allow-single-intention-with-kitchen-sink-perms--httpfilter.golden b/agent/xds/testdata/rbac/default-allow-single-intention-with-kitchen-sink-perms--httpfilter.golden index c2e9504c390c..b2c1d63a4459 100644 --- a/agent/xds/testdata/rbac/default-allow-single-intention-with-kitchen-sink-perms--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-allow-single-intention-with-kitchen-sink-perms--httpfilter.golden @@ -39,7 +39,6 @@ "urlPath": { "path": { "safeRegex": { - "googleRe2": {}, "regex": "/v[123]" } } @@ -48,9 +47,10 @@ { "header": { "name": ":method", - "safeRegexMatch": { - "googleRe2": {}, - "regex": "GET|HEAD|OPTIONS" + "stringMatch": { + "safeRegex": { + "regex": "GET|HEAD|OPTIONS" + } } } } @@ -114,17 +114,60 @@ } } }, + { + "header": { + "name": "x-baz", + "stringMatch": { + "contains": "qux" + } + } + }, { "header": { "name": "x-zim", "stringMatch": { "safeRegex": { - "googleRe2": {}, "regex": "gi[rR]" } } } }, + { + "header": { + "name": "y-bar", + "stringMatch": { + "exact": "xyz", + "ignoreCase": true + } + } + }, + { + "header": { + "name": "y-dib", + "stringMatch": { + "ignoreCase": true, + "prefix": "gaz" + } + } + }, + { + "header": { + "name": "y-gir", + "stringMatch": { + "ignoreCase": true, + "suffix": "zim" + } + } + }, + { + "header": { + "name": "y-baz", + "stringMatch": { + "contains": "qux", + "ignoreCase": true + } + } + }, { "header": { "invertMatch": true, @@ -159,13 +202,21 @@ } } }, + { + "header": { + "invertMatch": true, + "name": "z-baz", + "stringMatch": { + "contains": "qux" + } + } + }, { "header": { "invertMatch": true, "name": "z-zim", "stringMatch": { "safeRegex": { - "googleRe2": {}, "regex": "gi[rR]" } } @@ -182,7 +233,6 @@ "urlPath": { "path": { "safeRegex": { - "googleRe2": {}, "regex": "/v[123]" } } @@ -191,9 +241,10 @@ { "header": { "name": ":method", - "safeRegexMatch": { - "googleRe2": {}, - "regex": "GET|HEAD|OPTIONS" + "stringMatch": { + "safeRegex": { + "regex": "GET|HEAD|OPTIONS" + } } } } @@ -228,7 +279,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -239,4 +289,4 @@ } } } -} \ No newline at end of file +} diff --git a/agent/xds/testdata/rbac/default-allow-single-intention-with-kitchen-sink-perms.golden b/agent/xds/testdata/rbac/default-allow-single-intention-with-kitchen-sink-perms.golden index 19f25b92ff5f..f0dacb3ef1fe 100644 --- a/agent/xds/testdata/rbac/default-allow-single-intention-with-kitchen-sink-perms.golden +++ b/agent/xds/testdata/rbac/default-allow-single-intention-with-kitchen-sink-perms.golden @@ -16,7 +16,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-allow-two-path-deny-and-path-allow--httpfilter.golden b/agent/xds/testdata/rbac/default-allow-two-path-deny-and-path-allow--httpfilter.golden index ec4f26e958c1..2c8d3b86f7ea 100644 --- a/agent/xds/testdata/rbac/default-allow-two-path-deny-and-path-allow--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-allow-two-path-deny-and-path-allow--httpfilter.golden @@ -42,7 +42,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-allow-two-path-deny-and-path-allow.golden b/agent/xds/testdata/rbac/default-allow-two-path-deny-and-path-allow.golden index 19f25b92ff5f..f0dacb3ef1fe 100644 --- a/agent/xds/testdata/rbac/default-allow-two-path-deny-and-path-allow.golden +++ b/agent/xds/testdata/rbac/default-allow-two-path-deny-and-path-allow.golden @@ -16,7 +16,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-deny-allow-deny--httpfilter.golden b/agent/xds/testdata/rbac/default-deny-allow-deny--httpfilter.golden index cba46edc59cc..9eaeb2ad967e 100644 --- a/agent/xds/testdata/rbac/default-deny-allow-deny--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-deny-allow-deny--httpfilter.golden @@ -18,7 +18,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } @@ -29,7 +28,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-deny-allow-deny.golden b/agent/xds/testdata/rbac/default-deny-allow-deny.golden index 185bbc27343c..040def966e4e 100644 --- a/agent/xds/testdata/rbac/default-deny-allow-deny.golden +++ b/agent/xds/testdata/rbac/default-deny-allow-deny.golden @@ -18,7 +18,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } @@ -29,7 +28,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-deny-deny-all-and-path-allow--httpfilter.golden b/agent/xds/testdata/rbac/default-deny-deny-all-and-path-allow--httpfilter.golden index 880d5e18673f..4adcbd001ec5 100644 --- a/agent/xds/testdata/rbac/default-deny-deny-all-and-path-allow--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-deny-deny-all-and-path-allow--httpfilter.golden @@ -19,7 +19,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-deny-kitchen-sink--httpfilter.golden b/agent/xds/testdata/rbac/default-deny-kitchen-sink--httpfilter.golden index c551798d6bc2..90fe5eaeaea3 100644 --- a/agent/xds/testdata/rbac/default-deny-kitchen-sink--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-deny-kitchen-sink--httpfilter.golden @@ -15,7 +15,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/cron$" } } @@ -25,7 +24,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -38,7 +36,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } @@ -49,7 +46,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -61,7 +57,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/unsafe$" } } @@ -73,7 +68,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/cron$" } } diff --git a/agent/xds/testdata/rbac/default-deny-kitchen-sink.golden b/agent/xds/testdata/rbac/default-deny-kitchen-sink.golden index 173f54b3db16..3e1b6e844938 100644 --- a/agent/xds/testdata/rbac/default-deny-kitchen-sink.golden +++ b/agent/xds/testdata/rbac/default-deny-kitchen-sink.golden @@ -15,7 +15,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/cron$" } } @@ -25,7 +24,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -38,7 +36,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } @@ -49,7 +46,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -61,7 +57,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/unsafe$" } } @@ -73,7 +68,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/cron$" } } diff --git a/agent/xds/testdata/rbac/default-deny-mixed-precedence--httpfilter.golden b/agent/xds/testdata/rbac/default-deny-mixed-precedence--httpfilter.golden index fb2154c82e27..e066c2daedeb 100644 --- a/agent/xds/testdata/rbac/default-deny-mixed-precedence--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-deny-mixed-precedence--httpfilter.golden @@ -15,7 +15,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-deny-mixed-precedence.golden b/agent/xds/testdata/rbac/default-deny-mixed-precedence.golden index a02fd3518c1e..a67e2f89c90a 100644 --- a/agent/xds/testdata/rbac/default-deny-mixed-precedence.golden +++ b/agent/xds/testdata/rbac/default-deny-mixed-precedence.golden @@ -15,7 +15,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-deny-one-allow--httpfilter.golden b/agent/xds/testdata/rbac/default-deny-one-allow--httpfilter.golden index fb2154c82e27..e066c2daedeb 100644 --- a/agent/xds/testdata/rbac/default-deny-one-allow--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-deny-one-allow--httpfilter.golden @@ -15,7 +15,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-deny-one-allow.golden b/agent/xds/testdata/rbac/default-deny-one-allow.golden index a02fd3518c1e..a67e2f89c90a 100644 --- a/agent/xds/testdata/rbac/default-deny-one-allow.golden +++ b/agent/xds/testdata/rbac/default-deny-one-allow.golden @@ -15,7 +15,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-deny-path-allow--httpfilter.golden b/agent/xds/testdata/rbac/default-deny-path-allow--httpfilter.golden index 880d5e18673f..4adcbd001ec5 100644 --- a/agent/xds/testdata/rbac/default-deny-path-allow--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-deny-path-allow--httpfilter.golden @@ -19,7 +19,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-deny-peered-kitchen-sink--httpfilter.golden b/agent/xds/testdata/rbac/default-deny-peered-kitchen-sink--httpfilter.golden index 8b81593142cd..d69ba4fb2c7b 100644 --- a/agent/xds/testdata/rbac/default-deny-peered-kitchen-sink--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-deny-peered-kitchen-sink--httpfilter.golden @@ -15,7 +15,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -28,7 +27,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/gateway/mesh/dc/[^/]+$" } } @@ -42,7 +40,6 @@ "name": "x-forwarded-client-cert", "stringMatch": { "safeRegex": { - "googleRe2": {}, "regex": "^[^,]+;URI=spiffe://peer1.domain/ap/part1/ns/default/dc/[^/]+/svc/[^/]+(?:,.*)?$" } } @@ -54,7 +51,6 @@ "name": "x-forwarded-client-cert", "stringMatch": { "safeRegex": { - "googleRe2": {}, "regex": "^[^,]+;URI=spiffe://peer1.domain/ap/part1/ns/default/dc/[^/]+/svc/web(?:,.*)?$" } } diff --git a/agent/xds/testdata/rbac/default-deny-peered-kitchen-sink.golden b/agent/xds/testdata/rbac/default-deny-peered-kitchen-sink.golden index ba7fc6b4d0d0..7fb1bf303479 100644 --- a/agent/xds/testdata/rbac/default-deny-peered-kitchen-sink.golden +++ b/agent/xds/testdata/rbac/default-deny-peered-kitchen-sink.golden @@ -15,7 +15,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -28,7 +27,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://peer1.domain/ap/part1/ns/default/dc/[^/]+/svc/[^/]+$" } } @@ -39,7 +37,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://peer1.domain/ap/part1/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/default-deny-service-wildcard-allow--httpfilter.golden b/agent/xds/testdata/rbac/default-deny-service-wildcard-allow--httpfilter.golden index ce7174d5d013..bbad43cb100c 100644 --- a/agent/xds/testdata/rbac/default-deny-service-wildcard-allow--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-deny-service-wildcard-allow--httpfilter.golden @@ -15,7 +15,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } diff --git a/agent/xds/testdata/rbac/default-deny-service-wildcard-allow.golden b/agent/xds/testdata/rbac/default-deny-service-wildcard-allow.golden index caad3988db14..030cc138800b 100644 --- a/agent/xds/testdata/rbac/default-deny-service-wildcard-allow.golden +++ b/agent/xds/testdata/rbac/default-deny-service-wildcard-allow.golden @@ -15,7 +15,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } diff --git a/agent/xds/testdata/rbac/default-deny-single-intention-with-kitchen-sink-perms--httpfilter.golden b/agent/xds/testdata/rbac/default-deny-single-intention-with-kitchen-sink-perms--httpfilter.golden index e745e5278f36..7acd057dda6f 100644 --- a/agent/xds/testdata/rbac/default-deny-single-intention-with-kitchen-sink-perms--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-deny-single-intention-with-kitchen-sink-perms--httpfilter.golden @@ -38,7 +38,6 @@ "urlPath": { "path": { "safeRegex": { - "googleRe2": {}, "regex": "/v[123]" } } @@ -47,9 +46,10 @@ { "header": { "name": ":method", - "safeRegexMatch": { - "googleRe2": {}, - "regex": "GET|HEAD|OPTIONS" + "stringMatch": { + "safeRegex": { + "regex": "GET|HEAD|OPTIONS" + } } } } @@ -113,17 +113,60 @@ } } }, + { + "header": { + "name": "x-baz", + "stringMatch": { + "contains": "qux" + } + } + }, { "header": { "name": "x-zim", "stringMatch": { "safeRegex": { - "googleRe2": {}, "regex": "gi[rR]" } } } }, + { + "header": { + "name": "y-bar", + "stringMatch": { + "exact": "xyz", + "ignoreCase": true + } + } + }, + { + "header": { + "name": "y-dib", + "stringMatch": { + "ignoreCase": true, + "prefix": "gaz" + } + } + }, + { + "header": { + "name": "y-gir", + "stringMatch": { + "ignoreCase": true, + "suffix": "zim" + } + } + }, + { + "header": { + "name": "y-baz", + "stringMatch": { + "contains": "qux", + "ignoreCase": true + } + } + }, { "header": { "invertMatch": true, @@ -158,13 +201,21 @@ } } }, + { + "header": { + "invertMatch": true, + "name": "z-baz", + "stringMatch": { + "contains": "qux" + } + } + }, { "header": { "invertMatch": true, "name": "z-zim", "stringMatch": { "safeRegex": { - "googleRe2": {}, "regex": "gi[rR]" } } @@ -181,7 +232,6 @@ "urlPath": { "path": { "safeRegex": { - "googleRe2": {}, "regex": "/v[123]" } } @@ -190,9 +240,10 @@ { "header": { "name": ":method", - "safeRegexMatch": { - "googleRe2": {}, - "regex": "GET|HEAD|OPTIONS" + "stringMatch": { + "safeRegex": { + "regex": "GET|HEAD|OPTIONS" + } } } } @@ -227,7 +278,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } @@ -238,4 +288,4 @@ } } } -} \ No newline at end of file +} diff --git a/agent/xds/testdata/rbac/default-deny-two-path-deny-and-path-allow--httpfilter.golden b/agent/xds/testdata/rbac/default-deny-two-path-deny-and-path-allow--httpfilter.golden index bfaa5c46c387..cd558af911a5 100644 --- a/agent/xds/testdata/rbac/default-deny-two-path-deny-and-path-allow--httpfilter.golden +++ b/agent/xds/testdata/rbac/default-deny-two-path-deny-and-path-allow--httpfilter.golden @@ -43,7 +43,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/empty-top-level-jwt-with-one-permission--httpfilter.golden b/agent/xds/testdata/rbac/empty-top-level-jwt-with-one-permission--httpfilter.golden index 28cb4df8f41d..4a7c7dbb231e 100644 --- a/agent/xds/testdata/rbac/empty-top-level-jwt-with-one-permission--httpfilter.golden +++ b/agent/xds/testdata/rbac/empty-top-level-jwt-with-one-permission--httpfilter.golden @@ -67,7 +67,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/top-level-jwt-no-permissions--httpfilter.golden b/agent/xds/testdata/rbac/top-level-jwt-no-permissions--httpfilter.golden index 522e134591fc..59af52d88f2b 100644 --- a/agent/xds/testdata/rbac/top-level-jwt-no-permissions--httpfilter.golden +++ b/agent/xds/testdata/rbac/top-level-jwt-no-permissions--httpfilter.golden @@ -18,7 +18,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/top-level-jwt-no-permissions.golden b/agent/xds/testdata/rbac/top-level-jwt-no-permissions.golden index a02fd3518c1e..a67e2f89c90a 100644 --- a/agent/xds/testdata/rbac/top-level-jwt-no-permissions.golden +++ b/agent/xds/testdata/rbac/top-level-jwt-no-permissions.golden @@ -15,7 +15,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/top-level-jwt-with-multiple-permissions--httpfilter.golden b/agent/xds/testdata/rbac/top-level-jwt-with-multiple-permissions--httpfilter.golden index 461429f6c499..c3c57ae4e105 100644 --- a/agent/xds/testdata/rbac/top-level-jwt-with-multiple-permissions--httpfilter.golden +++ b/agent/xds/testdata/rbac/top-level-jwt-with-multiple-permissions--httpfilter.golden @@ -146,7 +146,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/top-level-jwt-with-one-permission--httpfilter.golden b/agent/xds/testdata/rbac/top-level-jwt-with-one-permission--httpfilter.golden index f384cbdd654b..994978cc80c0 100644 --- a/agent/xds/testdata/rbac/top-level-jwt-with-one-permission--httpfilter.golden +++ b/agent/xds/testdata/rbac/top-level-jwt-with-one-permission--httpfilter.golden @@ -95,7 +95,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/v2-L4-deny-L7-allow--httpfilter.golden b/agent/xds/testdata/rbac/v2-L4-deny-L7-allow--httpfilter.golden new file mode 100644 index 000000000000..25299cf176ef --- /dev/null +++ b/agent/xds/testdata/rbac/v2-L4-deny-L7-allow--httpfilter.golden @@ -0,0 +1,77 @@ +{ + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "action": "DENY", + "policies": { + "consul-intentions-layer4": { + "permissions": [ + { + "any": true + } + ], + "principals": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + } + ] + } + } + } + } + }, + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "policies": { + "consul-intentions-layer7-0": { + "permissions": [ + { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "prefix": "/v1" + } + } + }, + { + "header": { + "name": "x-foo", + "presentMatch": true + } + } + ] + } + } + ], + "principals": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + } + ] + } + } + } + } + } + ] +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-L4-deny-L7-allow.golden b/agent/xds/testdata/rbac/v2-L4-deny-L7-allow.golden new file mode 100644 index 000000000000..9bccccaa99f6 --- /dev/null +++ b/agent/xds/testdata/rbac/v2-L4-deny-L7-allow.golden @@ -0,0 +1,42 @@ +{ + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": { + "action": "DENY", + "policies": { + "consul-intentions-layer4": { + "permissions": [ + { + "any": true + } + ], + "principals": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + } + ] + } + } + }, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + } + ] +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-default-allow--httpfilter.golden b/agent/xds/testdata/rbac/v2-default-allow--httpfilter.golden new file mode 100644 index 000000000000..9e26dfeeb6e6 --- /dev/null +++ b/agent/xds/testdata/rbac/v2-default-allow--httpfilter.golden @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-default-deny--httpfilter.golden b/agent/xds/testdata/rbac/v2-default-deny--httpfilter.golden new file mode 100644 index 000000000000..a435b1f2b870 --- /dev/null +++ b/agent/xds/testdata/rbac/v2-default-deny--httpfilter.golden @@ -0,0 +1,7 @@ +{ + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-ignore-empty-permissions--httpfilter.golden b/agent/xds/testdata/rbac/v2-ignore-empty-permissions--httpfilter.golden new file mode 100644 index 000000000000..f947a2d0be05 --- /dev/null +++ b/agent/xds/testdata/rbac/v2-ignore-empty-permissions--httpfilter.golden @@ -0,0 +1,20 @@ +{ + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "action": "DENY" + } + } + }, + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + } + ] +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-kitchen-sink--httpfilter.golden b/agent/xds/testdata/rbac/v2-kitchen-sink--httpfilter.golden new file mode 100644 index 000000000000..6bc1fb6e5f10 --- /dev/null +++ b/agent/xds/testdata/rbac/v2-kitchen-sink--httpfilter.golden @@ -0,0 +1,114 @@ +{ + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "action": "DENY", + "policies": { + "consul-intentions-layer4": { + "permissions": [ + { + "any": true + } + ], + "principals": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/db$" + } + } + } + }, + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/cron$" + } + } + } + } + ] + } + } + } + } + }, + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "policies": { + "consul-intentions-layer4-0": { + "permissions": [ + { + "any": true + } + ], + "principals": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/api$" + } + } + } + }, + { + "andIds": { + "ids": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" + } + } + } + }, + { + "notId": { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/unsafe$" + } + } + } + } + } + ] + } + } + ] + }, + "consul-intentions-layer4-1": { + "permissions": [ + { + "any": true + } + ], + "principals": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + } + ] + } + } + } + } + } + ] +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-kitchen-sink.golden b/agent/xds/testdata/rbac/v2-kitchen-sink.golden index d298830ee935..78ece6002937 100644 --- a/agent/xds/testdata/rbac/v2-kitchen-sink.golden +++ b/agent/xds/testdata/rbac/v2-kitchen-sink.golden @@ -18,7 +18,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/db$" } } @@ -28,7 +27,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/cron$" } } @@ -58,7 +56,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/api$" } } @@ -71,7 +68,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/[^/]+$" } } @@ -82,7 +78,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/unsafe$" } } @@ -105,7 +100,6 @@ "authenticated": { "principalName": { "safeRegex": { - "googleRe2": {}, "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" } } diff --git a/agent/xds/testdata/rbac/v2-path-excludes--httpfilter.golden b/agent/xds/testdata/rbac/v2-path-excludes--httpfilter.golden new file mode 100644 index 000000000000..119cd921939b --- /dev/null +++ b/agent/xds/testdata/rbac/v2-path-excludes--httpfilter.golden @@ -0,0 +1,47 @@ +{ + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "policies": { + "consul-intentions-layer7-0": { + "permissions": [ + { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "prefix": "/" + } + } + }, + { + "notRule": { + "urlPath": { + "path": { + "prefix": "/admin" + } + } + } + } + ] + } + } + ], + "principals": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-path-excludes.golden b/agent/xds/testdata/rbac/v2-path-excludes.golden new file mode 100644 index 000000000000..b1fa47ea4c35 --- /dev/null +++ b/agent/xds/testdata/rbac/v2-path-excludes.golden @@ -0,0 +1,8 @@ +{ + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-path-method-header-excludes--httpfilter.golden b/agent/xds/testdata/rbac/v2-path-method-header-excludes--httpfilter.golden new file mode 100644 index 000000000000..780d64a19f5a --- /dev/null +++ b/agent/xds/testdata/rbac/v2-path-method-header-excludes--httpfilter.golden @@ -0,0 +1,69 @@ +{ + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "policies": { + "consul-intentions-layer7-0": { + "permissions": [ + { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "prefix": "/" + } + } + }, + { + "notRule": { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "prefix": "/admin" + } + } + }, + { + "header": { + "name": ":method", + "stringMatch": { + "safeRegex": { + "regex": "POST|DELETE" + } + } + } + }, + { + "header": { + "name": "experiment", + "presentMatch": true + } + } + ] + } + } + } + ] + } + } + ], + "principals": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-path-method-header-excludes.golden b/agent/xds/testdata/rbac/v2-path-method-header-excludes.golden new file mode 100644 index 000000000000..b1fa47ea4c35 --- /dev/null +++ b/agent/xds/testdata/rbac/v2-path-method-header-excludes.golden @@ -0,0 +1,8 @@ +{ + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-single-permission-multiple-destination-rules--httpfilter.golden b/agent/xds/testdata/rbac/v2-single-permission-multiple-destination-rules--httpfilter.golden new file mode 100644 index 000000000000..b4ccdccf748e --- /dev/null +++ b/agent/xds/testdata/rbac/v2-single-permission-multiple-destination-rules--httpfilter.golden @@ -0,0 +1,183 @@ +{ + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "policies": { + "consul-intentions-layer7-0": { + "permissions": [ + { + "andRules": { + "rules": [ + { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "prefix": "/v1" + } + } + }, + { + "header": { + "name": "x-foo", + "presentMatch": true + } + } + ] + } + }, + { + "notRule": { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "exact": "/v1/secret" + } + } + }, + { + "header": { + "name": "x-baz", + "presentMatch": true + } + }, + { + "header": { + "name": "x-bar", + "presentMatch": true + } + } + ] + } + } + }, + { + "notRule": { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "exact": "/v1/admin" + } + } + }, + { + "header": { + "name": "x-baz", + "presentMatch": true + } + }, + { + "header": { + "name": "x-bar", + "presentMatch": true + } + } + ] + } + } + } + ] + } + }, + { + "andRules": { + "rules": [ + { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "prefix": "/v2" + } + } + }, + { + "header": { + "name": "x-foo", + "presentMatch": true + } + } + ] + } + }, + { + "notRule": { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "exact": "/v2/secret" + } + } + }, + { + "header": { + "name": "x-baz", + "presentMatch": true + } + }, + { + "header": { + "name": "x-bar", + "presentMatch": true + } + } + ] + } + } + }, + { + "notRule": { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "exact": "/v2/admin" + } + } + }, + { + "header": { + "name": "x-baz", + "presentMatch": true + } + }, + { + "header": { + "name": "x-bar", + "presentMatch": true + } + } + ] + } + } + } + ] + } + } + ], + "principals": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-single-permission-multiple-destination-rules.golden b/agent/xds/testdata/rbac/v2-single-permission-multiple-destination-rules.golden new file mode 100644 index 000000000000..b1fa47ea4c35 --- /dev/null +++ b/agent/xds/testdata/rbac/v2-single-permission-multiple-destination-rules.golden @@ -0,0 +1,8 @@ +{ + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-single-permission-with-excludes--httpfilter.golden b/agent/xds/testdata/rbac/v2-single-permission-with-excludes--httpfilter.golden new file mode 100644 index 000000000000..eac270dada61 --- /dev/null +++ b/agent/xds/testdata/rbac/v2-single-permission-with-excludes--httpfilter.golden @@ -0,0 +1,104 @@ +{ + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "policies": { + "consul-intentions-layer7-0": { + "permissions": [ + { + "andRules": { + "rules": [ + { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "prefix": "/v1" + } + } + }, + { + "header": { + "name": "x-foo", + "presentMatch": true + } + } + ] + } + }, + { + "notRule": { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "exact": "/v1/secret" + } + } + }, + { + "header": { + "name": "x-baz", + "presentMatch": true + } + }, + { + "header": { + "name": "x-bar", + "presentMatch": true + } + } + ] + } + } + }, + { + "notRule": { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "exact": "/v1/admin" + } + } + }, + { + "header": { + "name": "x-baz", + "presentMatch": true + } + }, + { + "header": { + "name": "x-bar", + "presentMatch": true + } + } + ] + } + } + } + ] + } + } + ], + "principals": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-single-permission-with-excludes.golden b/agent/xds/testdata/rbac/v2-single-permission-with-excludes.golden new file mode 100644 index 000000000000..b1fa47ea4c35 --- /dev/null +++ b/agent/xds/testdata/rbac/v2-single-permission-with-excludes.golden @@ -0,0 +1,8 @@ +{ + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-single-permission-with-kitchen-sink-perms--httpfilter.golden b/agent/xds/testdata/rbac/v2-single-permission-with-kitchen-sink-perms--httpfilter.golden new file mode 100644 index 000000000000..7359d15faaf3 --- /dev/null +++ b/agent/xds/testdata/rbac/v2-single-permission-with-kitchen-sink-perms--httpfilter.golden @@ -0,0 +1,226 @@ +{ + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "policies": { + "consul-intentions-layer7-0": { + "permissions": [ + { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "prefix": "/v1" + } + } + }, + { + "notRule": { + "urlPath": { + "path": { + "exact": "/v1/secret" + } + } + } + } + ] + } + }, + { + "andRules": { + "rules": [ + { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "safeRegex": { + "regex": "/v[123]" + } + } + } + }, + { + "header": { + "name": ":method", + "stringMatch": { + "safeRegex": { + "regex": "GET|HEAD|OPTIONS" + } + } + } + } + ] + } + }, + { + "notRule": { + "urlPath": { + "path": { + "exact": "/v1/secret" + } + } + } + }, + { + "notRule": { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "exact": "/v1/admin" + } + } + }, + { + "header": { + "name": ":method", + "stringMatch": { + "safeRegex": { + "regex": "GET" + } + } + } + } + ] + } + } + } + ] + } + }, + { + "andRules": { + "rules": [ + { + "andRules": { + "rules": [ + { + "header": { + "name": "x-foo", + "presentMatch": true + } + }, + { + "header": { + "name": "x-bar", + "stringMatch": { + "exact": "xyz" + } + } + }, + { + "header": { + "name": "x-dib", + "stringMatch": { + "prefix": "gaz" + } + } + }, + { + "header": { + "name": "x-gir", + "stringMatch": { + "suffix": "zim" + } + } + }, + { + "header": { + "name": "x-zim", + "stringMatch": { + "safeRegex": { + "regex": "gi[rR]" + } + } + } + }, + { + "header": { + "invertMatch": true, + "name": "z-foo", + "presentMatch": true + } + }, + { + "header": { + "invertMatch": true, + "name": "z-bar", + "stringMatch": { + "exact": "xyz" + } + } + }, + { + "header": { + "invertMatch": true, + "name": "z-dib", + "stringMatch": { + "prefix": "gaz" + } + } + }, + { + "header": { + "invertMatch": true, + "name": "z-gir", + "stringMatch": { + "suffix": "zim" + } + } + }, + { + "header": { + "invertMatch": true, + "name": "z-zim", + "stringMatch": { + "safeRegex": { + "regex": "gi[rR]" + } + } + } + } + ] + } + }, + { + "notRule": { + "urlPath": { + "path": { + "exact": "/v1/secret" + } + } + } + }, + { + "notRule": { + "header": { + "name": "x-baz", + "presentMatch": true + } + } + } + ] + } + } + ], + "principals": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/v2-single-permission-with-kitchen-sink-perms.golden b/agent/xds/testdata/rbac/v2-single-permission-with-kitchen-sink-perms.golden new file mode 100644 index 000000000000..b1fa47ea4c35 --- /dev/null +++ b/agent/xds/testdata/rbac/v2-single-permission-with-kitchen-sink-perms.golden @@ -0,0 +1,8 @@ +{ + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/access-logs-defaults.latest.golden b/agent/xds/testdata/routes/access-logs-defaults.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/access-logs-defaults.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/access-logs-json-file.latest.golden b/agent/xds/testdata/routes/access-logs-json-file.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/access-logs-json-file.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/access-logs-text-stderr-disablelistenerlogs.latest.golden b/agent/xds/testdata/routes/access-logs-text-stderr-disablelistenerlogs.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/access-logs-text-stderr-disablelistenerlogs.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/api-gateway-http-listener-with-http-route.latest.golden b/agent/xds/testdata/routes/api-gateway-http-listener-with-http-route.latest.golden new file mode 100644 index 000000000000..92e5c9dfe078 --- /dev/null +++ b/agent/xds/testdata/routes/api-gateway-http-listener-with-http-route.latest.golden @@ -0,0 +1,30 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "*", + "*:8080" + ], + "name": "api-gateway-listener-9b9265b", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "http-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/api-gateway-http-listener.latest.golden b/agent/xds/testdata/routes/api-gateway-http-listener.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/api-gateway-http-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/api-gateway-nil-config-entry.latest.golden b/agent/xds/testdata/routes/api-gateway-nil-config-entry.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/api-gateway-nil-config-entry.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/api-gateway-tcp-listener-with-tcp-and-http-route.latest.golden b/agent/xds/testdata/routes/api-gateway-tcp-listener-with-tcp-and-http-route.latest.golden new file mode 100644 index 000000000000..282058fc7d7b --- /dev/null +++ b/agent/xds/testdata/routes/api-gateway-tcp-listener-with-tcp-and-http-route.latest.golden @@ -0,0 +1,30 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8081", + "virtualHosts": [ + { + "domains": [ + "*", + "*:8081" + ], + "name": "api-gateway-listener-http-9b9265b", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "http-service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/api-gateway-tcp-listener-with-tcp-route.latest.golden b/agent/xds/testdata/routes/api-gateway-tcp-listener-with-tcp-route.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/api-gateway-tcp-listener-with-tcp-route.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/api-gateway-tcp-listener.latest.golden b/agent/xds/testdata/routes/api-gateway-tcp-listener.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/api-gateway-tcp-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden b/agent/xds/testdata/routes/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden index 2c220ee70ef5..f404529d1a54 100644 --- a/agent/xds/testdata/routes/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden +++ b/agent/xds/testdata/routes/api-gateway-with-http-route-timeoutfilter-one-set.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "8080", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -19,14 +18,13 @@ }, "requestHeadersToAdd": [ { - "append": true, "header": { "key": "X-Header-Add", "value": "added" } }, { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "X-Header-Set", "value": "set" diff --git a/agent/xds/testdata/routes/api-gateway-with-http-route.latest.golden b/agent/xds/testdata/routes/api-gateway-with-http-route.latest.golden index 3137421e5188..6e9eb721b844 100644 --- a/agent/xds/testdata/routes/api-gateway-with-http-route.latest.golden +++ b/agent/xds/testdata/routes/api-gateway-with-http-route.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "8080", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -19,14 +18,13 @@ }, "requestHeadersToAdd": [ { - "append": true, "header": { "key": "X-Header-Add", "value": "added" } }, { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "X-Header-Set", "value": "set" diff --git a/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.latest.golden b/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.latest.golden index b268a5e5ac5e..bd70cabf2edc 100644 --- a/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.latest.golden +++ b/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "8080", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/api-gateway.latest.golden b/agent/xds/testdata/routes/api-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/api-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-lb-in-resolver.latest.golden b/agent/xds/testdata/routes/connect-proxy-lb-in-resolver.latest.golden index f748c3e8208e..14558185b25f 100644 --- a/agent/xds/testdata/routes/connect-proxy-lb-in-resolver.latest.golden +++ b/agent/xds/testdata/routes/connect-proxy-lb-in-resolver.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "db", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -57,8 +56,7 @@ "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "weight": 450 } - ], - "totalWeight": 10000 + ] } } } diff --git a/agent/xds/testdata/routes/connect-proxy-resolver-with-lb.latest.golden b/agent/xds/testdata/routes/connect-proxy-resolver-with-lb.latest.golden index 6d9d5242037e..2ff828f4258b 100644 --- a/agent/xds/testdata/routes/connect-proxy-resolver-with-lb.latest.golden +++ b/agent/xds/testdata/routes/connect-proxy-resolver-with-lb.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "db", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/connect-proxy-route-to-lb-resolver.latest.golden b/agent/xds/testdata/routes/connect-proxy-route-to-lb-resolver.latest.golden index 3ab67ba8f221..dd7498471dff 100644 --- a/agent/xds/testdata/routes/connect-proxy-route-to-lb-resolver.latest.golden +++ b/agent/xds/testdata/routes/connect-proxy-route-to-lb-resolver.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "db", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/connect-proxy-splitter-overweight.latest.golden b/agent/xds/testdata/routes/connect-proxy-splitter-overweight.latest.golden index b52cd3205ea8..bb98b73d0e18 100644 --- a/agent/xds/testdata/routes/connect-proxy-splitter-overweight.latest.golden +++ b/agent/xds/testdata/routes/connect-proxy-splitter-overweight.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "db", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -23,7 +22,7 @@ "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "requestHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "big" @@ -32,7 +31,7 @@ ], "responseHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "big" @@ -45,7 +44,7 @@ "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "requestHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "goldilocks" @@ -54,7 +53,7 @@ ], "responseHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "goldilocks" @@ -67,7 +66,7 @@ "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "requestHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "small" @@ -76,7 +75,7 @@ ], "responseHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "small" diff --git a/agent/xds/testdata/routes/connect-proxy-upstream-defaults.latest.golden b/agent/xds/testdata/routes/connect-proxy-upstream-defaults.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-upstream-defaults.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-chain-and-overrides.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-chain-and-overrides.latest.golden index 5d8b1dd41e83..9acc0918c914 100644 --- a/agent/xds/testdata/routes/connect-proxy-with-chain-and-overrides.latest.golden +++ b/agent/xds/testdata/routes/connect-proxy-with-chain-and-overrides.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "db", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/connect-proxy-with-chain-and-router.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-chain-and-router.latest.golden index 958709e3477e..3456b42bf8b9 100644 --- a/agent/xds/testdata/routes/connect-proxy-with-chain-and-router.latest.golden +++ b/agent/xds/testdata/routes/connect-proxy-with-chain-and-router.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "db", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -31,7 +30,6 @@ { "match": { "safeRegex": { - "googleRe2": {}, "regex": "/regex" } }, @@ -123,7 +121,6 @@ "name": "x-debug", "stringMatch": { "safeRegex": { - "googleRe2": {}, "regex": "regex" } } @@ -140,9 +137,10 @@ "headers": [ { "name": ":method", - "safeRegexMatch": { - "googleRe2": {}, - "regex": "GET|PUT" + "stringMatch": { + "safeRegex": { + "regex": "GET|PUT" + } } } ], @@ -163,9 +161,10 @@ }, { "name": ":method", - "safeRegexMatch": { - "googleRe2": {}, - "regex": "GET|PUT" + "stringMatch": { + "safeRegex": { + "regex": "GET|PUT" + } } } ], @@ -199,7 +198,6 @@ "name": "secretparam2", "stringMatch": { "safeRegex": { - "googleRe2": {}, "regex": "regex" } } @@ -360,8 +358,7 @@ "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "weight": 50 } - ], - "totalWeight": 10000 + ] } } }, @@ -371,14 +368,13 @@ }, "requestHeadersToAdd": [ { - "append": true, "header": { "key": "request", "value": "bar" } }, { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "bar", "value": "baz" @@ -390,14 +386,13 @@ ], "responseHeadersToAdd": [ { - "append": true, "header": { "key": "response", "value": "bar" } }, { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "bar", "value": "baz" diff --git a/agent/xds/testdata/routes/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden new file mode 100644 index 000000000000..fe5c69a399dd --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden @@ -0,0 +1,139 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "db", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "db", + "routes": [ + { + "match": { + "prefix": "/big-side" + }, + "route": { + "cluster": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "idleTimeout": "0s", + "timeout": "10s" + } + }, + { + "match": { + "prefix": "/lil-bit-side" + }, + "route": { + "cluster": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/" + }, + "route": { + "weightedClusters": { + "clusters": [ + { + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "requestHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "x-split-leg", + "value": "db" + } + } + ], + "responseHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "x-split-leg", + "value": "db" + } + } + ], + "weight": 100 + }, + { + "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "requestHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "x-split-leg", + "value": "big" + } + } + ], + "responseHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "x-split-leg", + "value": "big" + } + } + ], + "weight": 9550 + }, + { + "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "requestHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "x-split-leg", + "value": "goldilocks" + } + } + ], + "responseHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "x-split-leg", + "value": "goldilocks" + } + } + ], + "weight": 300 + }, + { + "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "requestHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "x-split-leg", + "value": "small" + } + } + ], + "responseHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "x-split-leg", + "value": "small" + } + } + ], + "weight": 50 + } + ] + } + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-chain-and-splitter.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-chain-and-splitter.latest.golden index 564167abe06e..5ff17ff04705 100644 --- a/agent/xds/testdata/routes/connect-proxy-with-chain-and-splitter.latest.golden +++ b/agent/xds/testdata/routes/connect-proxy-with-chain-and-splitter.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "db", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -12,6 +11,24 @@ ], "name": "db", "routes": [ + { + "match": { + "prefix": "/big-side" + }, + "route": { + "cluster": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "idleTimeout": "0s", + "timeout": "10s" + } + }, + { + "match": { + "prefix": "/lil-bit-side" + }, + "route": { + "cluster": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, { "match": { "prefix": "/" @@ -19,11 +36,33 @@ "route": { "weightedClusters": { "clusters": [ + { + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "requestHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "x-split-leg", + "value": "db" + } + } + ], + "responseHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "x-split-leg", + "value": "db" + } + } + ], + "weight": 100 + }, { "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "requestHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "big" @@ -32,7 +71,7 @@ ], "responseHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "big" @@ -45,7 +84,7 @@ "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "requestHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "goldilocks" @@ -54,20 +93,20 @@ ], "responseHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "goldilocks" } } ], - "weight": 400 + "weight": 300 }, { "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "requestHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "small" @@ -76,7 +115,7 @@ ], "responseHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "small" @@ -85,8 +124,7 @@ ], "weight": 50 } - ], - "totalWeight": 10000 + ] } } } diff --git a/agent/xds/testdata/routes/connect-proxy-with-chain-http2.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-chain-http2.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-chain-http2.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-default-chain-and-custom-cluster.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-default-chain-and-custom-cluster.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-default-chain-and-custom-cluster.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-grpc-chain.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-grpc-chain.latest.golden new file mode 100644 index 000000000000..5440895b8e3f --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-grpc-chain.latest.golden @@ -0,0 +1,30 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "db", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "db", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "33s" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-grpc-router.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-grpc-router.latest.golden index 474ac19cd71b..5ba0bfe3484a 100644 --- a/agent/xds/testdata/routes/connect-proxy-with-grpc-router.latest.golden +++ b/agent/xds/testdata/routes/connect-proxy-with-grpc-router.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "db", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/connect-proxy-with-http-chain.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-http-chain.latest.golden new file mode 100644 index 000000000000..5440895b8e3f --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-http-chain.latest.golden @@ -0,0 +1,30 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "db", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "db", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "33s" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-http2-chain.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-http2-chain.latest.golden new file mode 100644 index 000000000000..5440895b8e3f --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-http2-chain.latest.golden @@ -0,0 +1,30 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "db", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "db", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "33s" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-jwt-config-entry-with-local.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-jwt-config-entry-with-local.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-jwt-config-entry-with-local.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden new file mode 100644 index 000000000000..df1ae2ff9df7 --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden new file mode 100644 index 000000000000..df1ae2ff9df7 --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-failover-through-local-gateway.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-failover-through-local-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-failover-through-local-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-failover-through-remote-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain-failover-through-remote-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tcp-chain.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tcp-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tls-incoming-cipher-suites.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tls-incoming-cipher-suites.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tls-incoming-cipher-suites.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tls-incoming-max-version.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tls-incoming-max-version.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tls-incoming-max-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tls-incoming-min-version.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tls-incoming-min-version.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tls-incoming-min-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tls-outgoing-max-version.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tls-outgoing-max-version.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tls-outgoing-max-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tls-outgoing-min-version.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tls-outgoing-min-version.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tls-outgoing-min-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden b/agent/xds/testdata/routes/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/connect-proxy-without-tproxy-and-permissive-mtls.latest.golden b/agent/xds/testdata/routes/connect-proxy-without-tproxy-and-permissive-mtls.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/connect-proxy-without-tproxy-and-permissive-mtls.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-limits-max-connections-only.latest.golden b/agent/xds/testdata/routes/custom-limits-max-connections-only.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-limits-max-connections-only.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-limits-set-to-zero.latest.golden b/agent/xds/testdata/routes/custom-limits-set-to-zero.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-limits-set-to-zero.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-limits.latest.golden b/agent/xds/testdata/routes/custom-limits.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-limits.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-local-app.latest.golden b/agent/xds/testdata/routes/custom-local-app.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-local-app.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-max-inbound-connections.latest.golden b/agent/xds/testdata/routes/custom-max-inbound-connections.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-max-inbound-connections.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden b/agent/xds/testdata/routes/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-passive-healthcheck.latest.golden b/agent/xds/testdata/routes/custom-passive-healthcheck.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-passive-healthcheck.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-public-listener-http-2.latest.golden b/agent/xds/testdata/routes/custom-public-listener-http-2.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-public-listener-http-2.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-public-listener-http-missing.latest.golden b/agent/xds/testdata/routes/custom-public-listener-http-missing.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-public-listener-http-missing.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-public-listener-http.latest.golden b/agent/xds/testdata/routes/custom-public-listener-http.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-public-listener-http.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-public-listener.latest.golden b/agent/xds/testdata/routes/custom-public-listener.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-public-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-timeouts.latest.golden b/agent/xds/testdata/routes/custom-timeouts.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-timeouts.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-trace-listener.latest.golden b/agent/xds/testdata/routes/custom-trace-listener.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-trace-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-upstream-default-chain.latest.golden b/agent/xds/testdata/routes/custom-upstream-default-chain.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-upstream-default-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-upstream-ignored-with-disco-chain.latest.golden b/agent/xds/testdata/routes/custom-upstream-ignored-with-disco-chain.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-upstream-ignored-with-disco-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-upstream-with-prepared-query.latest.golden b/agent/xds/testdata/routes/custom-upstream-with-prepared-query.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-upstream-with-prepared-query.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/custom-upstream.latest.golden b/agent/xds/testdata/routes/custom-upstream.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/custom-upstream.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/downstream-service-with-unix-sockets.latest.golden b/agent/xds/testdata/routes/downstream-service-with-unix-sockets.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/downstream-service-with-unix-sockets.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/expose-checks-grpc.latest.golden b/agent/xds/testdata/routes/expose-checks-grpc.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/expose-checks-grpc.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/expose-checks-http-with-bind-override.latest.golden b/agent/xds/testdata/routes/expose-checks-http-with-bind-override.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/expose-checks-http-with-bind-override.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/expose-checks-http.latest.golden b/agent/xds/testdata/routes/expose-checks-http.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/expose-checks-http.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/expose-checks.latest.golden b/agent/xds/testdata/routes/expose-checks.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/expose-checks.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/expose-paths-grpc-new-cluster-http1.latest.golden b/agent/xds/testdata/routes/expose-paths-grpc-new-cluster-http1.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/expose-paths-grpc-new-cluster-http1.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/expose-paths-local-app-paths.latest.golden b/agent/xds/testdata/routes/expose-paths-local-app-paths.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/expose-paths-local-app-paths.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/expose-paths-new-cluster-http2.latest.golden b/agent/xds/testdata/routes/expose-paths-new-cluster-http2.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/expose-paths-new-cluster-http2.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/grpc-public-listener.latest.golden b/agent/xds/testdata/routes/grpc-public-listener.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/grpc-public-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/http-listener-with-timeouts.latest.golden b/agent/xds/testdata/routes/http-listener-with-timeouts.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/http-listener-with-timeouts.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/http-public-listener-no-xfcc.latest.golden b/agent/xds/testdata/routes/http-public-listener-no-xfcc.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/http-public-listener-no-xfcc.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/http-public-listener.latest.golden b/agent/xds/testdata/routes/http-public-listener.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/http-public-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/http-upstream.latest.golden b/agent/xds/testdata/routes/http-upstream.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/http-upstream.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/http2-public-listener.latest.golden b/agent/xds/testdata/routes/http2-public-listener.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/http2-public-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-gateway-bind-addrs.latest.golden b/agent/xds/testdata/routes/ingress-gateway-bind-addrs.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-gateway-bind-addrs.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-gateway-nil-config-entry.latest.golden b/agent/xds/testdata/routes/ingress-gateway-nil-config-entry.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-gateway-nil-config-entry.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-gateway-no-services.latest.golden b/agent/xds/testdata/routes/ingress-gateway-no-services.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-gateway-no-services.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden b/agent/xds/testdata/routes/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-gateway-with-tls-outgoing-max-version.latest.golden b/agent/xds/testdata/routes/ingress-gateway-with-tls-outgoing-max-version.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-gateway-with-tls-outgoing-max-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-gateway-with-tls-outgoing-min-version.latest.golden b/agent/xds/testdata/routes/ingress-gateway-with-tls-outgoing-min-version.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-gateway-with-tls-outgoing-min-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-gateway.latest.golden b/agent/xds/testdata/routes/ingress-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-grpc-multiple-services.latest.golden b/agent/xds/testdata/routes/ingress-grpc-multiple-services.latest.golden index 41c70e3de169..cdb43b252c31 100644 --- a/agent/xds/testdata/routes/ingress-grpc-multiple-services.latest.golden +++ b/agent/xds/testdata/routes/ingress-grpc-multiple-services.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "8080", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/ingress-http-multiple-services.latest.golden b/agent/xds/testdata/routes/ingress-http-multiple-services.latest.golden index a15b997a8fd9..a461171d214e 100644 --- a/agent/xds/testdata/routes/ingress-http-multiple-services.latest.golden +++ b/agent/xds/testdata/routes/ingress-http-multiple-services.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "443", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -45,7 +44,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "8080", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/ingress-lb-in-resolver.latest.golden b/agent/xds/testdata/routes/ingress-lb-in-resolver.latest.golden index 9660fb81a608..53a49ce05ffb 100644 --- a/agent/xds/testdata/routes/ingress-lb-in-resolver.latest.golden +++ b/agent/xds/testdata/routes/ingress-lb-in-resolver.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "8080", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -58,8 +57,7 @@ "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "weight": 450 } - ], - "totalWeight": 10000 + ] } } } diff --git a/agent/xds/testdata/routes/ingress-multiple-listeners-duplicate-service.latest.golden b/agent/xds/testdata/routes/ingress-multiple-listeners-duplicate-service.latest.golden new file mode 100644 index 000000000000..413e4ac227cf --- /dev/null +++ b/agent/xds/testdata/routes/ingress-multiple-listeners-duplicate-service.latest.golden @@ -0,0 +1,70 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "443", + "virtualHosts": [ + { + "domains": [ + "foo.ingress.*", + "foo.ingress.*:443" + ], + "name": "foo", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "foo.ingress.*", + "foo.ingress.*:8080" + ], + "name": "foo", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + }, + { + "domains": [ + "bar.ingress.*", + "bar.ingress.*:8080" + ], + "name": "bar", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-splitter-with-resolver-redirect.latest.golden b/agent/xds/testdata/routes/ingress-splitter-with-resolver-redirect.latest.golden index bf15c92982e7..219dfac078e1 100644 --- a/agent/xds/testdata/routes/ingress-splitter-with-resolver-redirect.latest.golden +++ b/agent/xds/testdata/routes/ingress-splitter-with-resolver-redirect.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "8080", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -28,8 +27,7 @@ "name": "v2.db.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul", "weight": 5000 } - ], - "totalWeight": 10000 + ] } } } diff --git a/agent/xds/testdata/routes/ingress-with-chain-and-failover-to-cluster-peer.latest.golden b/agent/xds/testdata/routes/ingress-with-chain-and-failover-to-cluster-peer.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-chain-and-failover-to-cluster-peer.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-chain-and-failover.latest.golden b/agent/xds/testdata/routes/ingress-with-chain-and-failover.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-chain-and-failover.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-chain-and-router-header-manip.latest.golden b/agent/xds/testdata/routes/ingress-with-chain-and-router-header-manip.latest.golden index 2a55ed339500..4bf0ec2a3d20 100644 --- a/agent/xds/testdata/routes/ingress-with-chain-and-router-header-manip.latest.golden +++ b/agent/xds/testdata/routes/ingress-with-chain-and-router-header-manip.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "8080", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -14,14 +13,13 @@ "name": "db", "requestHeadersToAdd": [ { - "append": true, "header": { "key": "foo", "value": "bar" } }, { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "bar", "value": "baz" @@ -33,14 +31,13 @@ ], "responseHeadersToAdd": [ { - "append": true, "header": { "key": "foo", "value": "bar" } }, { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "bar", "value": "baz" @@ -70,7 +67,6 @@ { "match": { "safeRegex": { - "googleRe2": {}, "regex": "/regex" } }, @@ -162,7 +158,6 @@ "name": "x-debug", "stringMatch": { "safeRegex": { - "googleRe2": {}, "regex": "regex" } } @@ -179,9 +174,10 @@ "headers": [ { "name": ":method", - "safeRegexMatch": { - "googleRe2": {}, - "regex": "GET|PUT" + "stringMatch": { + "safeRegex": { + "regex": "GET|PUT" + } } } ], @@ -202,9 +198,10 @@ }, { "name": ":method", - "safeRegexMatch": { - "googleRe2": {}, - "regex": "GET|PUT" + "stringMatch": { + "safeRegex": { + "regex": "GET|PUT" + } } } ], @@ -238,7 +235,6 @@ "name": "secretparam2", "stringMatch": { "safeRegex": { - "googleRe2": {}, "regex": "regex" } } @@ -399,8 +395,7 @@ "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "weight": 50 } - ], - "totalWeight": 10000 + ] } } }, @@ -410,14 +405,13 @@ }, "requestHeadersToAdd": [ { - "append": true, "header": { "key": "request", "value": "bar" } }, { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "bar", "value": "baz" @@ -429,14 +423,13 @@ ], "responseHeadersToAdd": [ { - "append": true, "header": { "key": "response", "value": "bar" } }, { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "bar", "value": "baz" diff --git a/agent/xds/testdata/routes/ingress-with-chain-and-router.latest.golden b/agent/xds/testdata/routes/ingress-with-chain-and-router.latest.golden index dac7fbcf0f28..d0eca099f45b 100644 --- a/agent/xds/testdata/routes/ingress-with-chain-and-router.latest.golden +++ b/agent/xds/testdata/routes/ingress-with-chain-and-router.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "8080", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -32,7 +31,6 @@ { "match": { "safeRegex": { - "googleRe2": {}, "regex": "/regex" } }, @@ -124,7 +122,6 @@ "name": "x-debug", "stringMatch": { "safeRegex": { - "googleRe2": {}, "regex": "regex" } } @@ -141,9 +138,10 @@ "headers": [ { "name": ":method", - "safeRegexMatch": { - "googleRe2": {}, - "regex": "GET|PUT" + "stringMatch": { + "safeRegex": { + "regex": "GET|PUT" + } } } ], @@ -164,9 +162,10 @@ }, { "name": ":method", - "safeRegexMatch": { - "googleRe2": {}, - "regex": "GET|PUT" + "stringMatch": { + "safeRegex": { + "regex": "GET|PUT" + } } } ], @@ -200,7 +199,6 @@ "name": "secretparam2", "stringMatch": { "safeRegex": { - "googleRe2": {}, "regex": "regex" } } @@ -361,8 +359,7 @@ "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "weight": 50 } - ], - "totalWeight": 10000 + ] } } }, @@ -372,14 +369,13 @@ }, "requestHeadersToAdd": [ { - "append": true, "header": { "key": "request", "value": "bar" } }, { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "bar", "value": "baz" @@ -391,14 +387,13 @@ ], "responseHeadersToAdd": [ { - "append": true, "header": { "key": "response", "value": "bar" } }, { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "bar", "value": "baz" diff --git a/agent/xds/testdata/routes/ingress-with-chain-and-splitter.latest.golden b/agent/xds/testdata/routes/ingress-with-chain-and-splitter.latest.golden index f5961883bcad..295bc827bfbe 100644 --- a/agent/xds/testdata/routes/ingress-with-chain-and-splitter.latest.golden +++ b/agent/xds/testdata/routes/ingress-with-chain-and-splitter.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "8080", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -13,6 +12,24 @@ ], "name": "db", "routes": [ + { + "match": { + "prefix": "/big-side" + }, + "route": { + "cluster": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "idleTimeout": "0s", + "timeout": "10s" + } + }, + { + "match": { + "prefix": "/lil-bit-side" + }, + "route": { + "cluster": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, { "match": { "prefix": "/" @@ -20,11 +37,33 @@ "route": { "weightedClusters": { "clusters": [ + { + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "requestHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "x-split-leg", + "value": "db" + } + } + ], + "responseHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "x-split-leg", + "value": "db" + } + } + ], + "weight": 100 + }, { "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "requestHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "big" @@ -33,7 +72,7 @@ ], "responseHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "big" @@ -46,7 +85,7 @@ "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "requestHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "goldilocks" @@ -55,20 +94,20 @@ ], "responseHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "goldilocks" } } ], - "weight": 400 + "weight": 300 }, { "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "requestHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "small" @@ -77,7 +116,7 @@ ], "responseHeadersToAdd": [ { - "append": false, + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", "header": { "key": "x-split-leg", "value": "small" @@ -86,8 +125,7 @@ ], "weight": 50 } - ], - "totalWeight": 10000 + ] } } } diff --git a/agent/xds/testdata/routes/ingress-with-defaults-passive-health-check.latest.golden b/agent/xds/testdata/routes/ingress-with-defaults-passive-health-check.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-defaults-passive-health-check.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-defaults-service-max-connections.latest.golden b/agent/xds/testdata/routes/ingress-with-defaults-service-max-connections.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-defaults-service-max-connections.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-grpc-router.latest.golden b/agent/xds/testdata/routes/ingress-with-grpc-router.latest.golden index 25afe4ee6dac..f3ab8fee7ecd 100644 --- a/agent/xds/testdata/routes/ingress-with-grpc-router.latest.golden +++ b/agent/xds/testdata/routes/ingress-with-grpc-router.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "8080", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/ingress-with-grpc-single-tls-listener.latest.golden b/agent/xds/testdata/routes/ingress-with-grpc-single-tls-listener.latest.golden new file mode 100644 index 000000000000..18c50d1c8931 --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-grpc-single-tls-listener.latest.golden @@ -0,0 +1,53 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "s1.ingress.*", + "s1.ingress.*:8080" + ], + "name": "s1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8081", + "virtualHosts": [ + { + "domains": [ + "s2.ingress.*", + "s2.ingress.*:8081" + ], + "name": "s2", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-http2-and-grpc-multiple-tls-listener.latest.golden b/agent/xds/testdata/routes/ingress-with-http2-and-grpc-multiple-tls-listener.latest.golden new file mode 100644 index 000000000000..18c50d1c8931 --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-http2-and-grpc-multiple-tls-listener.latest.golden @@ -0,0 +1,53 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "s1.ingress.*", + "s1.ingress.*:8080" + ], + "name": "s1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8081", + "virtualHosts": [ + { + "domains": [ + "s2.ingress.*", + "s2.ingress.*:8081" + ], + "name": "s2", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-http2-single-tls-listener.latest.golden b/agent/xds/testdata/routes/ingress-with-http2-single-tls-listener.latest.golden new file mode 100644 index 000000000000..18c50d1c8931 --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-http2-single-tls-listener.latest.golden @@ -0,0 +1,53 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "s1.ingress.*", + "s1.ingress.*:8080" + ], + "name": "s1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8081", + "virtualHosts": [ + { + "domains": [ + "s2.ingress.*", + "s2.ingress.*:8081" + ], + "name": "s2", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-overwrite-defaults-passive-health-check.latest.golden b/agent/xds/testdata/routes/ingress-with-overwrite-defaults-passive-health-check.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-overwrite-defaults-passive-health-check.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-overwrite-defaults-service-max-connections.latest.golden b/agent/xds/testdata/routes/ingress-with-overwrite-defaults-service-max-connections.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-overwrite-defaults-service-max-connections.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-sds-listener+service-level.latest.golden b/agent/xds/testdata/routes/ingress-with-sds-listener+service-level.latest.golden new file mode 100644 index 000000000000..96c1f714dadb --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-sds-listener+service-level.latest.golden @@ -0,0 +1,53 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "s2.ingress.*", + "s2.ingress.*:8080" + ], + "name": "s2", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080_s1", + "virtualHosts": [ + { + "domains": [ + "s1.ingress.*", + "s1.ingress.*:8080" + ], + "name": "s1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-sds-listener-gw-level-http.latest.golden b/agent/xds/testdata/routes/ingress-with-sds-listener-gw-level-http.latest.golden new file mode 100644 index 000000000000..a7b6e583c4b5 --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-sds-listener-gw-level-http.latest.golden @@ -0,0 +1,30 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "http.ingress.*", + "http.ingress.*:8080" + ], + "name": "http", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-sds-listener-gw-level-mixed-tls.latest.golden b/agent/xds/testdata/routes/ingress-with-sds-listener-gw-level-mixed-tls.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-sds-listener-gw-level-mixed-tls.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-sds-listener-gw-level.latest.golden b/agent/xds/testdata/routes/ingress-with-sds-listener-gw-level.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-sds-listener-gw-level.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-sds-listener-level-wildcard.latest.golden b/agent/xds/testdata/routes/ingress-with-sds-listener-level-wildcard.latest.golden index cf218b1c9574..ddf8aed433bc 100644 --- a/agent/xds/testdata/routes/ingress-with-sds-listener-level-wildcard.latest.golden +++ b/agent/xds/testdata/routes/ingress-with-sds-listener-level-wildcard.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "9191", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/ingress-with-sds-listener-level.latest.golden b/agent/xds/testdata/routes/ingress-with-sds-listener-level.latest.golden index 350f1605f645..12dc9cc93c5a 100644 --- a/agent/xds/testdata/routes/ingress-with-sds-listener-level.latest.golden +++ b/agent/xds/testdata/routes/ingress-with-sds-listener-level.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "9191", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/ingress-with-sds-listener-listener-level.latest.golden b/agent/xds/testdata/routes/ingress-with-sds-listener-listener-level.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-sds-listener-listener-level.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-sds-service-level-2.latest.golden b/agent/xds/testdata/routes/ingress-with-sds-service-level-2.latest.golden new file mode 100644 index 000000000000..358936f27028 --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-sds-service-level-2.latest.golden @@ -0,0 +1,55 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "9191_foo", + "virtualHosts": [ + { + "domains": [ + "foo.example.com", + "foo.example.com:9191" + ], + "name": "foo", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "22s" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "9191_web", + "virtualHosts": [ + { + "domains": [ + "www.example.com", + "www.example.com:9191" + ], + "name": "web", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "22s" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-sds-service-level-mixed-no-tls.latest.golden b/agent/xds/testdata/routes/ingress-with-sds-service-level-mixed-no-tls.latest.golden new file mode 100644 index 000000000000..96c1f714dadb --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-sds-service-level-mixed-no-tls.latest.golden @@ -0,0 +1,53 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "s2.ingress.*", + "s2.ingress.*:8080" + ], + "name": "s2", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080_s1", + "virtualHosts": [ + { + "domains": [ + "s1.ingress.*", + "s1.ingress.*:8080" + ], + "name": "s1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-sds-service-level-mixed-tls.latest.golden b/agent/xds/testdata/routes/ingress-with-sds-service-level-mixed-tls.latest.golden index 8cd0610d70ea..590fd05c6226 100644 --- a/agent/xds/testdata/routes/ingress-with-sds-service-level-mixed-tls.latest.golden +++ b/agent/xds/testdata/routes/ingress-with-sds-service-level-mixed-tls.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "9191", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -29,7 +28,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "9191_web", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/ingress-with-sds-service-level.latest.golden b/agent/xds/testdata/routes/ingress-with-sds-service-level.latest.golden index 48d9d7b77443..a6edbbfca1f6 100644 --- a/agent/xds/testdata/routes/ingress-with-sds-service-level.latest.golden +++ b/agent/xds/testdata/routes/ingress-with-sds-service-level.latest.golden @@ -3,23 +3,21 @@ "resources": [ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "9191_foo", - "validateClusters": true, + "name": "8080_s1", "virtualHosts": [ { "domains": [ - "foo.example.com", - "foo.example.com:9191" + "s1.ingress.*", + "s1.ingress.*:8080" ], - "name": "foo", + "name": "s1", "routes": [ { "match": { "prefix": "/" }, "route": { - "cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "timeout": "22s" + "cluster": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" } } ] @@ -28,23 +26,21 @@ }, { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "9191_web", - "validateClusters": true, + "name": "8080_s2", "virtualHosts": [ { "domains": [ - "www.example.com", - "www.example.com:9191" + "s2.ingress.*", + "s2.ingress.*:8080" ], - "name": "web", + "name": "s2", "routes": [ { "match": { "prefix": "/" }, "route": { - "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "timeout": "22s" + "cluster": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" } } ] diff --git a/agent/xds/testdata/routes/ingress-with-service-max-connections.latest.golden b/agent/xds/testdata/routes/ingress-with-service-max-connections.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-service-max-connections.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-service-passive-health-check.latest.golden b/agent/xds/testdata/routes/ingress-with-service-passive-health-check.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-service-passive-health-check.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-single-tls-listener.latest.golden b/agent/xds/testdata/routes/ingress-with-single-tls-listener.latest.golden new file mode 100644 index 000000000000..18c50d1c8931 --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-single-tls-listener.latest.golden @@ -0,0 +1,53 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "s1.ingress.*", + "s1.ingress.*:8080" + ], + "name": "s1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8081", + "virtualHosts": [ + { + "domains": [ + "s2.ingress.*", + "s2.ingress.*:8081" + ], + "name": "s2", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/routes/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden b/agent/xds/testdata/routes/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/routes/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/routes/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/routes/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tcp-chain-failover-through-local-gateway.latest.golden b/agent/xds/testdata/routes/ingress-with-tcp-chain-failover-through-local-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tcp-chain-failover-through-local-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/routes/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tcp-chain-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/routes/ingress-with-tcp-chain-failover-through-remote-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tcp-chain-failover-through-remote-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tls-listener-cipher-suites.latest.golden b/agent/xds/testdata/routes/ingress-with-tls-listener-cipher-suites.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tls-listener-cipher-suites.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tls-listener-max-version.latest.golden b/agent/xds/testdata/routes/ingress-with-tls-listener-max-version.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tls-listener-max-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tls-listener-min-version.latest.golden b/agent/xds/testdata/routes/ingress-with-tls-listener-min-version.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tls-listener-min-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tls-listener.latest.golden b/agent/xds/testdata/routes/ingress-with-tls-listener.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tls-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tls-min-version-listeners-gateway-defaults.latest.golden b/agent/xds/testdata/routes/ingress-with-tls-min-version-listeners-gateway-defaults.latest.golden new file mode 100644 index 000000000000..ed40b5faab02 --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tls-min-version-listeners-gateway-defaults.latest.golden @@ -0,0 +1,122 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "s1.ingress.*", + "s1.ingress.*:8080" + ], + "name": "s1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8081", + "virtualHosts": [ + { + "domains": [ + "s2.ingress.*", + "s2.ingress.*:8081" + ], + "name": "s2", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8082", + "virtualHosts": [ + { + "domains": [ + "s3.ingress.*", + "s3.ingress.*:8082" + ], + "name": "s3", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8083", + "virtualHosts": [ + { + "domains": [ + "s4.ingress.*", + "s4.ingress.*:8083" + ], + "name": "s4", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s4.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8084", + "virtualHosts": [ + { + "domains": [ + "s4.ingress.*", + "s4.ingress.*:8084" + ], + "name": "s4", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s4.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden b/agent/xds/testdata/routes/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden new file mode 100644 index 000000000000..18c50d1c8931 --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden @@ -0,0 +1,53 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "s1.ingress.*", + "s1.ingress.*:8080" + ], + "name": "s1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8081", + "virtualHosts": [ + { + "domains": [ + "s2.ingress.*", + "s2.ingress.*:8081" + ], + "name": "s2", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tls-mixed-listeners.latest.golden b/agent/xds/testdata/routes/ingress-with-tls-mixed-listeners.latest.golden new file mode 100644 index 000000000000..866fc179e6f9 --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tls-mixed-listeners.latest.golden @@ -0,0 +1,53 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "s1.ingress.*", + "s1.ingress.*:8080" + ], + "name": "s1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "9090", + "virtualHosts": [ + { + "domains": [ + "s2.ingress.*", + "s2.ingress.*:9090" + ], + "name": "s2", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tls-mixed-max-version-listeners.latest.golden b/agent/xds/testdata/routes/ingress-with-tls-mixed-max-version-listeners.latest.golden new file mode 100644 index 000000000000..f295797b3def --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tls-mixed-max-version-listeners.latest.golden @@ -0,0 +1,76 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "s1.ingress.*", + "s1.ingress.*:8080" + ], + "name": "s1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8081", + "virtualHosts": [ + { + "domains": [ + "s2.ingress.*", + "s2.ingress.*:8081" + ], + "name": "s2", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8082", + "virtualHosts": [ + { + "domains": [ + "s3.ingress.*", + "s3.ingress.*:8082" + ], + "name": "s3", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/ingress-with-tls-mixed-min-version-listeners.latest.golden b/agent/xds/testdata/routes/ingress-with-tls-mixed-min-version-listeners.latest.golden new file mode 100644 index 000000000000..f295797b3def --- /dev/null +++ b/agent/xds/testdata/routes/ingress-with-tls-mixed-min-version-listeners.latest.golden @@ -0,0 +1,76 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "s1.ingress.*", + "s1.ingress.*:8080" + ], + "name": "s1", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8081", + "virtualHosts": [ + { + "domains": [ + "s2.ingress.*", + "s2.ingress.*:8081" + ], + "name": "s2", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8082", + "virtualHosts": [ + { + "domains": [ + "s3.ingress.*", + "s3.ingress.*:8082" + ], + "name": "s3", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "s3.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/listener-balance-inbound-connections.latest.golden b/agent/xds/testdata/routes/listener-balance-inbound-connections.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/listener-balance-inbound-connections.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/listener-balance-outbound-connections-bind-port.latest.golden b/agent/xds/testdata/routes/listener-balance-outbound-connections-bind-port.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/listener-balance-outbound-connections-bind-port.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/listener-bind-address-port.latest.golden b/agent/xds/testdata/routes/listener-bind-address-port.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/listener-bind-address-port.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/listener-bind-address.latest.golden b/agent/xds/testdata/routes/listener-bind-address.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/listener-bind-address.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/listener-bind-port.latest.golden b/agent/xds/testdata/routes/listener-bind-port.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/listener-bind-port.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/listener-max-inbound-connections.latest.golden b/agent/xds/testdata/routes/listener-max-inbound-connections.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/listener-max-inbound-connections.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/listener-unix-domain-socket.latest.golden b/agent/xds/testdata/routes/listener-unix-domain-socket.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/listener-unix-domain-socket.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-custom-addresses.latest.golden b/agent/xds/testdata/routes/mesh-gateway-custom-addresses.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-custom-addresses.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-default-service-subset.latest.golden b/agent/xds/testdata/routes/mesh-gateway-default-service-subset.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-default-service-subset.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-hash-lb-ignored.latest.golden b/agent/xds/testdata/routes/mesh-gateway-hash-lb-ignored.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-hash-lb-ignored.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-ignore-extra-resolvers.latest.golden b/agent/xds/testdata/routes/mesh-gateway-ignore-extra-resolvers.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-ignore-extra-resolvers.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-newer-information-in-federation-states.latest.golden b/agent/xds/testdata/routes/mesh-gateway-newer-information-in-federation-states.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-newer-information-in-federation-states.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-no-services.latest.golden b/agent/xds/testdata/routes/mesh-gateway-no-services.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-no-services.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-non-hash-lb-injected.latest.golden b/agent/xds/testdata/routes/mesh-gateway-non-hash-lb-injected.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-non-hash-lb-injected.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-older-information-in-federation-states.latest.golden b/agent/xds/testdata/routes/mesh-gateway-older-information-in-federation-states.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-older-information-in-federation-states.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-service-subsets.latest.golden b/agent/xds/testdata/routes/mesh-gateway-service-subsets.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-service-subsets.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-service-subsets2.latest.golden b/agent/xds/testdata/routes/mesh-gateway-service-subsets2.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-service-subsets2.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-service-timeouts.latest.golden b/agent/xds/testdata/routes/mesh-gateway-service-timeouts.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-service-timeouts.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-tagged-addresses.latest.golden b/agent/xds/testdata/routes/mesh-gateway-tagged-addresses.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-tagged-addresses.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-tcp-keepalives.latest.golden b/agent/xds/testdata/routes/mesh-gateway-tcp-keepalives.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-tcp-keepalives.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-using-federation-control-plane.latest.golden b/agent/xds/testdata/routes/mesh-gateway-using-federation-control-plane.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-using-federation-control-plane.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-using-federation-states.latest.golden b/agent/xds/testdata/routes/mesh-gateway-using-federation-states.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-using-federation-states.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden b/agent/xds/testdata/routes/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden index 825473467d5e..9f4796ed05a0 100644 --- a/agent/xds/testdata/routes/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden +++ b/agent/xds/testdata/routes/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "db", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -27,8 +26,7 @@ "name": "exported~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", "weight": 4000 } - ], - "totalWeight": 10000 + ] } } }, diff --git a/agent/xds/testdata/routes/mesh-gateway-with-exported-peered-services-http.latest.golden b/agent/xds/testdata/routes/mesh-gateway-with-exported-peered-services-http.latest.golden index 4737a59e3156..96bd040bf982 100644 --- a/agent/xds/testdata/routes/mesh-gateway-with-exported-peered-services-http.latest.golden +++ b/agent/xds/testdata/routes/mesh-gateway-with-exported-peered-services-http.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "bar", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -27,7 +26,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "foo", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -50,7 +48,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "gir", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/mesh-gateway-with-limits.latest.golden b/agent/xds/testdata/routes/mesh-gateway-with-limits.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway-with-limits.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/mesh-gateway.latest.golden b/agent/xds/testdata/routes/mesh-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/mesh-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/splitter-with-resolver-redirect.latest.golden b/agent/xds/testdata/routes/splitter-with-resolver-redirect.latest.golden index 8c192286007c..7684d14c97fa 100644 --- a/agent/xds/testdata/routes/splitter-with-resolver-redirect.latest.golden +++ b/agent/xds/testdata/routes/splitter-with-resolver-redirect.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "db", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -27,8 +26,7 @@ "name": "v2.db.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul", "weight": 5000 } - ], - "totalWeight": 10000 + ] } } } diff --git a/agent/xds/testdata/routes/terminating-gateway-custom-and-tagged-addresses.latest.golden b/agent/xds/testdata/routes/terminating-gateway-custom-and-tagged-addresses.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-custom-and-tagged-addresses.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-custom-trace-listener.latest.golden b/agent/xds/testdata/routes/terminating-gateway-custom-trace-listener.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-custom-trace-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-default-service-subset.latest.golden b/agent/xds/testdata/routes/terminating-gateway-default-service-subset.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-default-service-subset.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-hostname-service-subsets.latest.golden b/agent/xds/testdata/routes/terminating-gateway-hostname-service-subsets.latest.golden new file mode 100644 index 000000000000..d30d528f000a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-hostname-service-subsets.latest.golden @@ -0,0 +1,99 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "alt.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "prod.cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-http2-upstream-subsets.latest.golden b/agent/xds/testdata/routes/terminating-gateway-http2-upstream-subsets.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-http2-upstream-subsets.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-http2-upstream.latest.golden b/agent/xds/testdata/routes/terminating-gateway-http2-upstream.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-http2-upstream.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-ignore-extra-resolvers.latest.golden b/agent/xds/testdata/routes/terminating-gateway-ignore-extra-resolvers.latest.golden new file mode 100644 index 000000000000..e0fae21af90f --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-ignore-extra-resolvers.latest.golden @@ -0,0 +1,76 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-lb-config-no-hash-policies.latest.golden b/agent/xds/testdata/routes/terminating-gateway-lb-config-no-hash-policies.latest.golden new file mode 100644 index 000000000000..33c3081ecffc --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-lb-config-no-hash-policies.latest.golden @@ -0,0 +1,79 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "0.200s" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "0.200s" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "0.200s" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-lb-config.latest.golden b/agent/xds/testdata/routes/terminating-gateway-lb-config.latest.golden index 1e7cdde138fa..1115f38e8f54 100644 --- a/agent/xds/testdata/routes/terminating-gateway-lb-config.latest.golden +++ b/agent/xds/testdata/routes/terminating-gateway-lb-config.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -48,7 +47,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -92,7 +90,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/terminating-gateway-no-api-cert.latest.golden b/agent/xds/testdata/routes/terminating-gateway-no-api-cert.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-no-api-cert.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-no-services.latest.golden b/agent/xds/testdata/routes/terminating-gateway-no-services.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-no-services.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-service-subsets.latest.golden b/agent/xds/testdata/routes/terminating-gateway-service-subsets.latest.golden new file mode 100644 index 000000000000..e0fae21af90f --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-service-subsets.latest.golden @@ -0,0 +1,76 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-sni.latest.golden b/agent/xds/testdata/routes/terminating-gateway-sni.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-sni.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-tcp-keepalives.latest.golden b/agent/xds/testdata/routes/terminating-gateway-tcp-keepalives.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-tcp-keepalives.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-with-peer-trust-bundle.latest.golden b/agent/xds/testdata/routes/terminating-gateway-with-peer-trust-bundle.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-with-peer-trust-bundle.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-with-tls-incoming-cipher-suites.latest.golden b/agent/xds/testdata/routes/terminating-gateway-with-tls-incoming-cipher-suites.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-with-tls-incoming-cipher-suites.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-with-tls-incoming-max-version.latest.golden b/agent/xds/testdata/routes/terminating-gateway-with-tls-incoming-max-version.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-with-tls-incoming-max-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway-with-tls-incoming-min-version.latest.golden b/agent/xds/testdata/routes/terminating-gateway-with-tls-incoming-min-version.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway-with-tls-incoming-min-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/terminating-gateway.latest.golden b/agent/xds/testdata/routes/terminating-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/terminating-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/transparent-proxy-destination-http.latest.golden b/agent/xds/testdata/routes/transparent-proxy-destination-http.latest.golden index 0f3440e32e34..f91d4715d1e6 100644 --- a/agent/xds/testdata/routes/transparent-proxy-destination-http.latest.golden +++ b/agent/xds/testdata/routes/transparent-proxy-destination-http.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "destination.443.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -27,7 +26,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "destination.9093.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/transparent-proxy-http-upstream.latest.golden b/agent/xds/testdata/routes/transparent-proxy-http-upstream.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/transparent-proxy-http-upstream.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/transparent-proxy-terminating-gateway-destinations-only.latest.golden b/agent/xds/testdata/routes/transparent-proxy-terminating-gateway-destinations-only.latest.golden index 14ac8198ffbd..25897fa65ec1 100644 --- a/agent/xds/testdata/routes/transparent-proxy-terminating-gateway-destinations-only.latest.golden +++ b/agent/xds/testdata/routes/transparent-proxy-terminating-gateway-destinations-only.latest.golden @@ -4,7 +4,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "destination.192-168-0-2.external-IP-HTTP.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ @@ -27,7 +26,6 @@ { "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", "name": "destination.httpbin-org.external-hostname-HTTP.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", - "validateClusters": true, "virtualHosts": [ { "domains": [ diff --git a/agent/xds/testdata/routes/transparent-proxy-terminating-gateway.latest.golden b/agent/xds/testdata/routes/transparent-proxy-terminating-gateway.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/transparent-proxy-terminating-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/transparent-proxy-with-resolver-redirect-upstream.latest.golden b/agent/xds/testdata/routes/transparent-proxy-with-resolver-redirect-upstream.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/transparent-proxy-with-resolver-redirect-upstream.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/xds-fetch-timeout-ms-ingress-with-router.latest.golden b/agent/xds/testdata/routes/xds-fetch-timeout-ms-ingress-with-router.latest.golden new file mode 100644 index 000000000000..d0eca099f45b --- /dev/null +++ b/agent/xds/testdata/routes/xds-fetch-timeout-ms-ingress-with-router.latest.golden @@ -0,0 +1,425 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ + { + "domains": [ + "db.ingress.*", + "db.ingress.*:8080" + ], + "name": "db", + "routes": [ + { + "match": { + "prefix": "/prefix" + }, + "route": { + "cluster": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "path": "/exact" + }, + "route": { + "cluster": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "safeRegex": { + "regex": "/regex" + } + }, + "route": { + "cluster": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": "x-debug", + "presentMatch": true + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "invertMatch": true, + "name": "x-debug", + "presentMatch": true + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": "x-debug", + "stringMatch": { + "exact": "exact" + } + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": "x-debug", + "stringMatch": { + "prefix": "prefix" + } + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": "x-debug", + "stringMatch": { + "suffix": "suffix" + } + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": "x-debug", + "stringMatch": { + "safeRegex": { + "regex": "regex" + } + } + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": ":method", + "stringMatch": { + "safeRegex": { + "regex": "GET|PUT" + } + } + } + ], + "prefix": "/" + }, + "route": { + "cluster": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": "x-debug", + "stringMatch": { + "exact": "exact" + } + }, + { + "name": ":method", + "stringMatch": { + "safeRegex": { + "regex": "GET|PUT" + } + } + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/", + "queryParameters": [ + { + "name": "secretparam1", + "stringMatch": { + "exact": "exact" + } + } + ] + }, + "route": { + "cluster": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/", + "queryParameters": [ + { + "name": "secretparam2", + "stringMatch": { + "safeRegex": { + "regex": "regex" + } + } + } + ] + }, + "route": { + "cluster": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/", + "queryParameters": [ + { + "name": "secretparam3", + "presentMatch": true + } + ] + }, + "route": { + "cluster": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/prefix" + }, + "route": { + "cluster": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "prefixRewrite": "/" + } + }, + { + "match": { + "prefix": "/prefix" + }, + "route": { + "cluster": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "prefixRewrite": "/nested/newlocation" + } + }, + { + "match": { + "prefix": "/timeout" + }, + "route": { + "cluster": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "33s" + } + }, + { + "match": { + "prefix": "/idle-timeout" + }, + "route": { + "cluster": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "idleTimeout": "33s" + } + }, + { + "match": { + "prefix": "/retry-connect" + }, + "route": { + "cluster": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "retryPolicy": { + "numRetries": 15, + "retryOn": "connect-failure" + } + } + }, + { + "match": { + "prefix": "/retry-reset" + }, + "route": { + "cluster": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "retryPolicy": { + "numRetries": 15, + "retryOn": "reset" + } + } + }, + { + "match": { + "prefix": "/retry-codes" + }, + "route": { + "cluster": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "retryPolicy": { + "numRetries": 15, + "retriableStatusCodes": [ + 401, + 409, + 451 + ], + "retryOn": "retriable-status-codes" + } + } + }, + { + "match": { + "prefix": "/retry-all" + }, + "route": { + "cluster": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "retryPolicy": { + "retriableStatusCodes": [ + 401, + 409, + 451 + ], + "retryOn": "5xx,gateway-error,reset,connect-failure,envoy-ratelimited,retriable-4xx,refused-stream,cancelled,deadline-exceeded,internal,resource-exhausted,unavailable,retriable-status-codes" + } + } + }, + { + "match": { + "prefix": "/split-3-ways" + }, + "route": { + "weightedClusters": { + "clusters": [ + { + "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "weight": 9550 + }, + { + "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "weight": 400 + }, + { + "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "weight": 50 + } + ] + } + } + }, + { + "match": { + "path": "/header-manip" + }, + "requestHeadersToAdd": [ + { + "header": { + "key": "request", + "value": "bar" + } + }, + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "bar", + "value": "baz" + } + } + ], + "requestHeadersToRemove": [ + "qux" + ], + "responseHeadersToAdd": [ + { + "header": { + "key": "response", + "value": "bar" + } + }, + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "bar", + "value": "baz" + } + } + ], + "responseHeadersToRemove": [ + "qux" + ], + "route": { + "cluster": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/xds-fetch-timeout-ms-mgw-peering.latest.golden b/agent/xds/testdata/routes/xds-fetch-timeout-ms-mgw-peering.latest.golden new file mode 100644 index 000000000000..96bd040bf982 --- /dev/null +++ b/agent/xds/testdata/routes/xds-fetch-timeout-ms-mgw-peering.latest.golden @@ -0,0 +1,73 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "bar", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "bar", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "exported~bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "foo", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "foo", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "exported~foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "gir", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "gir", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "exported~gir.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/xds-fetch-timeout-ms-sidecar.latest.golden b/agent/xds/testdata/routes/xds-fetch-timeout-ms-sidecar.latest.golden new file mode 100644 index 000000000000..3456b42bf8b9 --- /dev/null +++ b/agent/xds/testdata/routes/xds-fetch-timeout-ms-sidecar.latest.golden @@ -0,0 +1,424 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "db", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "db", + "routes": [ + { + "match": { + "prefix": "/prefix" + }, + "route": { + "cluster": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "path": "/exact" + }, + "route": { + "cluster": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "safeRegex": { + "regex": "/regex" + } + }, + "route": { + "cluster": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": "x-debug", + "presentMatch": true + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "invertMatch": true, + "name": "x-debug", + "presentMatch": true + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": "x-debug", + "stringMatch": { + "exact": "exact" + } + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": "x-debug", + "stringMatch": { + "prefix": "prefix" + } + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": "x-debug", + "stringMatch": { + "suffix": "suffix" + } + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": "x-debug", + "stringMatch": { + "safeRegex": { + "regex": "regex" + } + } + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": ":method", + "stringMatch": { + "safeRegex": { + "regex": "GET|PUT" + } + } + } + ], + "prefix": "/" + }, + "route": { + "cluster": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "headers": [ + { + "name": "x-debug", + "stringMatch": { + "exact": "exact" + } + }, + { + "name": ":method", + "stringMatch": { + "safeRegex": { + "regex": "GET|PUT" + } + } + } + ], + "prefix": "/" + }, + "route": { + "cluster": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/", + "queryParameters": [ + { + "name": "secretparam1", + "stringMatch": { + "exact": "exact" + } + } + ] + }, + "route": { + "cluster": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/", + "queryParameters": [ + { + "name": "secretparam2", + "stringMatch": { + "safeRegex": { + "regex": "regex" + } + } + } + ] + }, + "route": { + "cluster": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/", + "queryParameters": [ + { + "name": "secretparam3", + "presentMatch": true + } + ] + }, + "route": { + "cluster": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/prefix" + }, + "route": { + "cluster": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "prefixRewrite": "/" + } + }, + { + "match": { + "prefix": "/prefix" + }, + "route": { + "cluster": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "prefixRewrite": "/nested/newlocation" + } + }, + { + "match": { + "prefix": "/timeout" + }, + "route": { + "cluster": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "33s" + } + }, + { + "match": { + "prefix": "/idle-timeout" + }, + "route": { + "cluster": "idle-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "idleTimeout": "33s" + } + }, + { + "match": { + "prefix": "/retry-connect" + }, + "route": { + "cluster": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "retryPolicy": { + "numRetries": 15, + "retryOn": "connect-failure" + } + } + }, + { + "match": { + "prefix": "/retry-reset" + }, + "route": { + "cluster": "retry-reset.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "retryPolicy": { + "numRetries": 15, + "retryOn": "reset" + } + } + }, + { + "match": { + "prefix": "/retry-codes" + }, + "route": { + "cluster": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "retryPolicy": { + "numRetries": 15, + "retriableStatusCodes": [ + 401, + 409, + 451 + ], + "retryOn": "retriable-status-codes" + } + } + }, + { + "match": { + "prefix": "/retry-all" + }, + "route": { + "cluster": "retry-all.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "retryPolicy": { + "retriableStatusCodes": [ + 401, + 409, + 451 + ], + "retryOn": "5xx,gateway-error,reset,connect-failure,envoy-ratelimited,retriable-4xx,refused-stream,cancelled,deadline-exceeded,internal,resource-exhausted,unavailable,retriable-status-codes" + } + } + }, + { + "match": { + "prefix": "/split-3-ways" + }, + "route": { + "weightedClusters": { + "clusters": [ + { + "name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "weight": 9550 + }, + { + "name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "weight": 400 + }, + { + "name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "weight": 50 + } + ] + } + } + }, + { + "match": { + "path": "/header-manip" + }, + "requestHeadersToAdd": [ + { + "header": { + "key": "request", + "value": "bar" + } + }, + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "bar", + "value": "baz" + } + } + ], + "requestHeadersToRemove": [ + "qux" + ], + "responseHeadersToAdd": [ + { + "header": { + "key": "response", + "value": "bar" + } + }, + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "bar", + "value": "baz" + } + } + ], + "responseHeadersToRemove": [ + "qux" + ], + "route": { + "cluster": "header-manip.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/xds-fetch-timeout-ms-term-gw.latest.golden b/agent/xds/testdata/routes/xds-fetch-timeout-ms-term-gw.latest.golden new file mode 100644 index 000000000000..e0fae21af90f --- /dev/null +++ b/agent/xds/testdata/routes/xds-fetch-timeout-ms-term-gw.latest.golden @@ -0,0 +1,76 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "*" + ], + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "autoHostRewrite": true, + "cluster": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden b/agent/xds/testdata/routes/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden new file mode 100644 index 000000000000..8b919343d21a --- /dev/null +++ b/agent/xds/testdata/routes/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden b/agent/xds/testdata/routes/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden new file mode 100644 index 000000000000..f91d4715d1e6 --- /dev/null +++ b/agent/xds/testdata/routes/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden @@ -0,0 +1,83 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "destination.443.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "www.google.com" + ], + "name": "destination.www-google-com.google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "destination.www-google-com.google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "destination.9093.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "domains": [ + "192.168.2.3" + ], + "name": "destination.192-168-2-3.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "destination.192-168-2-3.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + }, + { + "domains": [ + "192.168.2.2" + ], + "name": "destination.192-168-2-2.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "destination.192-168-2-2.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + }, + { + "domains": [ + "192.168.2.1" + ], + "name": "destination.192-168-2-1.kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "destination.192-168-2-1.kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/access-logs-defaults.latest.golden b/agent/xds/testdata/secrets/access-logs-defaults.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/access-logs-defaults.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/access-logs-json-file.latest.golden b/agent/xds/testdata/secrets/access-logs-json-file.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/access-logs-json-file.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/access-logs-text-stderr-disablelistenerlogs.latest.golden b/agent/xds/testdata/secrets/access-logs-text-stderr-disablelistenerlogs.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/access-logs-text-stderr-disablelistenerlogs.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/api-gateway-http-listener-with-http-route.latest.golden b/agent/xds/testdata/secrets/api-gateway-http-listener-with-http-route.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/api-gateway-http-listener-with-http-route.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/api-gateway-http-listener.latest.golden b/agent/xds/testdata/secrets/api-gateway-http-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/api-gateway-http-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/api-gateway-nil-config-entry.latest.golden b/agent/xds/testdata/secrets/api-gateway-nil-config-entry.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/api-gateway-nil-config-entry.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/api-gateway-tcp-listener-with-tcp-and-http-route.latest.golden b/agent/xds/testdata/secrets/api-gateway-tcp-listener-with-tcp-and-http-route.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/api-gateway-tcp-listener-with-tcp-and-http-route.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/api-gateway-tcp-listener-with-tcp-route.latest.golden b/agent/xds/testdata/secrets/api-gateway-tcp-listener-with-tcp-route.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/api-gateway-tcp-listener-with-tcp-route.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/api-gateway-tcp-listener.latest.golden b/agent/xds/testdata/secrets/api-gateway-tcp-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/api-gateway-tcp-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/api-gateway-with-multiple-hostnames.latest.golden b/agent/xds/testdata/secrets/api-gateway-with-multiple-hostnames.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/api-gateway-with-multiple-hostnames.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/api-gateway.latest.golden b/agent/xds/testdata/secrets/api-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/api-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-lb-in-resolver.latest.golden b/agent/xds/testdata/secrets/connect-proxy-lb-in-resolver.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-lb-in-resolver.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-resolver-with-lb.latest.golden b/agent/xds/testdata/secrets/connect-proxy-resolver-with-lb.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-resolver-with-lb.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-route-to-lb-resolver.latest.golden b/agent/xds/testdata/secrets/connect-proxy-route-to-lb-resolver.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-route-to-lb-resolver.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-splitter-overweight.latest.golden b/agent/xds/testdata/secrets/connect-proxy-splitter-overweight.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-splitter-overweight.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-upstream-defaults.latest.golden b/agent/xds/testdata/secrets/connect-proxy-upstream-defaults.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-upstream-defaults.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-chain-and-overrides.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-chain-and-overrides.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-chain-and-overrides.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-chain-and-router.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-chain-and-router.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-chain-and-router.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-chain-and-splitter-and-mesh-validate-clusters.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-chain-and-splitter.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-chain-and-splitter.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-chain-and-splitter.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-chain-http2.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-chain-http2.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-chain-http2.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-default-chain-and-custom-cluster.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-default-chain-and-custom-cluster.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-default-chain-and-custom-cluster.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-grpc-chain.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-grpc-chain.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-grpc-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-grpc-router.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-grpc-router.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-grpc-router.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-http-chain.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-http-chain.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-http-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-http2-chain.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-http2-chain.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-http2-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-jwt-config-entry-with-local.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-jwt-config-entry-with-local.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-jwt-config-entry-with-local.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-jwt-config-entry-with-remote-jwks.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden new file mode 100644 index 000000000000..8b587d09eba8 --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-consul-options.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden new file mode 100644 index 000000000000..8b587d09eba8 --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-mesh-config-request-normalization-all-envoy-options-enabled.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-double-failover-through-local-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-double-failover-through-remote-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-failover-through-local-gateway.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-failover-through-local-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-failover-through-local-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-failover-through-remote-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain-failover-through-remote-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tcp-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tls-incoming-cipher-suites.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tls-incoming-cipher-suites.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tls-incoming-cipher-suites.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tls-incoming-max-version.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tls-incoming-max-version.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tls-incoming-max-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tls-incoming-min-version.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tls-incoming-min-version.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tls-incoming-min-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tls-outgoing-cipher-suites.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tls-outgoing-max-version.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tls-outgoing-max-version.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tls-outgoing-max-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tls-outgoing-min-version-auto.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tls-outgoing-min-version.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tls-outgoing-min-version.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tls-outgoing-min-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden b/agent/xds/testdata/secrets/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-with-tproxy-and-permissive-mtls.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/connect-proxy-without-tproxy-and-permissive-mtls.latest.golden b/agent/xds/testdata/secrets/connect-proxy-without-tproxy-and-permissive-mtls.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/connect-proxy-without-tproxy-and-permissive-mtls.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-limits-max-connections-only.latest.golden b/agent/xds/testdata/secrets/custom-limits-max-connections-only.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-limits-max-connections-only.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-limits-set-to-zero.latest.golden b/agent/xds/testdata/secrets/custom-limits-set-to-zero.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-limits-set-to-zero.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-limits.latest.golden b/agent/xds/testdata/secrets/custom-limits.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-limits.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-local-app.latest.golden b/agent/xds/testdata/secrets/custom-local-app.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-local-app.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-max-inbound-connections.latest.golden b/agent/xds/testdata/secrets/custom-max-inbound-connections.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-max-inbound-connections.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden b/agent/xds/testdata/secrets/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-passive-healthcheck-zero-consecutive_5xx.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-passive-healthcheck.latest.golden b/agent/xds/testdata/secrets/custom-passive-healthcheck.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-passive-healthcheck.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-public-listener-http-2.latest.golden b/agent/xds/testdata/secrets/custom-public-listener-http-2.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-public-listener-http-2.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-public-listener-http-missing.latest.golden b/agent/xds/testdata/secrets/custom-public-listener-http-missing.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-public-listener-http-missing.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-public-listener-http.latest.golden b/agent/xds/testdata/secrets/custom-public-listener-http.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-public-listener-http.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-public-listener.latest.golden b/agent/xds/testdata/secrets/custom-public-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-public-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-timeouts.latest.golden b/agent/xds/testdata/secrets/custom-timeouts.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-timeouts.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-trace-listener.latest.golden b/agent/xds/testdata/secrets/custom-trace-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-trace-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-upstream-default-chain.latest.golden b/agent/xds/testdata/secrets/custom-upstream-default-chain.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-upstream-default-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-upstream-ignored-with-disco-chain.latest.golden b/agent/xds/testdata/secrets/custom-upstream-ignored-with-disco-chain.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-upstream-ignored-with-disco-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-upstream-with-prepared-query.latest.golden b/agent/xds/testdata/secrets/custom-upstream-with-prepared-query.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-upstream-with-prepared-query.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/custom-upstream.latest.golden b/agent/xds/testdata/secrets/custom-upstream.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/custom-upstream.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/downstream-service-with-unix-sockets.latest.golden b/agent/xds/testdata/secrets/downstream-service-with-unix-sockets.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/downstream-service-with-unix-sockets.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/expose-checks-grpc.latest.golden b/agent/xds/testdata/secrets/expose-checks-grpc.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/expose-checks-grpc.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/expose-checks-http-with-bind-override.latest.golden b/agent/xds/testdata/secrets/expose-checks-http-with-bind-override.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/expose-checks-http-with-bind-override.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/expose-checks-http.latest.golden b/agent/xds/testdata/secrets/expose-checks-http.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/expose-checks-http.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/expose-checks.latest.golden b/agent/xds/testdata/secrets/expose-checks.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/expose-checks.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/expose-paths-grpc-new-cluster-http1.latest.golden b/agent/xds/testdata/secrets/expose-paths-grpc-new-cluster-http1.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/expose-paths-grpc-new-cluster-http1.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/expose-paths-local-app-paths.latest.golden b/agent/xds/testdata/secrets/expose-paths-local-app-paths.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/expose-paths-local-app-paths.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/expose-paths-new-cluster-http2.latest.golden b/agent/xds/testdata/secrets/expose-paths-new-cluster-http2.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/expose-paths-new-cluster-http2.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/grpc-public-listener.latest.golden b/agent/xds/testdata/secrets/grpc-public-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/grpc-public-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/http-listener-with-timeouts.latest.golden b/agent/xds/testdata/secrets/http-listener-with-timeouts.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/http-listener-with-timeouts.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/http-public-listener-no-xfcc.latest.golden b/agent/xds/testdata/secrets/http-public-listener-no-xfcc.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/http-public-listener-no-xfcc.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/http-public-listener.latest.golden b/agent/xds/testdata/secrets/http-public-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/http-public-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/http-upstream.latest.golden b/agent/xds/testdata/secrets/http-upstream.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/http-upstream.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/http2-public-listener.latest.golden b/agent/xds/testdata/secrets/http2-public-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/http2-public-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-config-entry-nil.latest.golden b/agent/xds/testdata/secrets/ingress-config-entry-nil.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-config-entry-nil.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-defaults-no-chain.latest.golden b/agent/xds/testdata/secrets/ingress-defaults-no-chain.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-defaults-no-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-gateway-bind-addrs.latest.golden b/agent/xds/testdata/secrets/ingress-gateway-bind-addrs.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-gateway-bind-addrs.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-gateway-nil-config-entry.latest.golden b/agent/xds/testdata/secrets/ingress-gateway-nil-config-entry.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-gateway-nil-config-entry.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-gateway-no-services.latest.golden b/agent/xds/testdata/secrets/ingress-gateway-no-services.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-gateway-no-services.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden b/agent/xds/testdata/secrets/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-gateway-with-tls-outgoing-cipher-suites.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-gateway-with-tls-outgoing-max-version.latest.golden b/agent/xds/testdata/secrets/ingress-gateway-with-tls-outgoing-max-version.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-gateway-with-tls-outgoing-max-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-gateway-with-tls-outgoing-min-version.latest.golden b/agent/xds/testdata/secrets/ingress-gateway-with-tls-outgoing-min-version.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-gateway-with-tls-outgoing-min-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-gateway.latest.golden b/agent/xds/testdata/secrets/ingress-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-grpc-multiple-services.latest.golden b/agent/xds/testdata/secrets/ingress-grpc-multiple-services.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-grpc-multiple-services.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-http-multiple-services.latest.golden b/agent/xds/testdata/secrets/ingress-http-multiple-services.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-http-multiple-services.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-lb-in-resolver.latest.golden b/agent/xds/testdata/secrets/ingress-lb-in-resolver.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-lb-in-resolver.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-multiple-listeners-duplicate-service.latest.golden b/agent/xds/testdata/secrets/ingress-multiple-listeners-duplicate-service.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-multiple-listeners-duplicate-service.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-splitter-with-resolver-redirect.latest.golden b/agent/xds/testdata/secrets/ingress-splitter-with-resolver-redirect.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-splitter-with-resolver-redirect.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-chain-and-failover-to-cluster-peer.latest.golden b/agent/xds/testdata/secrets/ingress-with-chain-and-failover-to-cluster-peer.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-chain-and-failover-to-cluster-peer.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-chain-and-failover.latest.golden b/agent/xds/testdata/secrets/ingress-with-chain-and-failover.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-chain-and-failover.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-chain-and-router-header-manip.latest.golden b/agent/xds/testdata/secrets/ingress-with-chain-and-router-header-manip.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-chain-and-router-header-manip.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-chain-and-router.latest.golden b/agent/xds/testdata/secrets/ingress-with-chain-and-router.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-chain-and-router.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-chain-and-splitter.latest.golden b/agent/xds/testdata/secrets/ingress-with-chain-and-splitter.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-chain-and-splitter.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-chain-external-sni.latest.golden b/agent/xds/testdata/secrets/ingress-with-chain-external-sni.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-chain-external-sni.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-chain.latest.golden b/agent/xds/testdata/secrets/ingress-with-chain.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-chain.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-defaults-passive-health-check.latest.golden b/agent/xds/testdata/secrets/ingress-with-defaults-passive-health-check.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-defaults-passive-health-check.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-defaults-service-max-connections.latest.golden b/agent/xds/testdata/secrets/ingress-with-defaults-service-max-connections.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-defaults-service-max-connections.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-grpc-router.latest.golden b/agent/xds/testdata/secrets/ingress-with-grpc-router.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-grpc-router.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-grpc-single-tls-listener.latest.golden b/agent/xds/testdata/secrets/ingress-with-grpc-single-tls-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-grpc-single-tls-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-http2-and-grpc-multiple-tls-listener.latest.golden b/agent/xds/testdata/secrets/ingress-with-http2-and-grpc-multiple-tls-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-http2-and-grpc-multiple-tls-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-http2-single-tls-listener.latest.golden b/agent/xds/testdata/secrets/ingress-with-http2-single-tls-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-http2-single-tls-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-overwrite-defaults-passive-health-check.latest.golden b/agent/xds/testdata/secrets/ingress-with-overwrite-defaults-passive-health-check.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-overwrite-defaults-passive-health-check.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-overwrite-defaults-service-max-connections.latest.golden b/agent/xds/testdata/secrets/ingress-with-overwrite-defaults-service-max-connections.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-overwrite-defaults-service-max-connections.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-sds-listener+service-level.latest.golden b/agent/xds/testdata/secrets/ingress-with-sds-listener+service-level.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-sds-listener+service-level.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-sds-listener-gw-level-http.latest.golden b/agent/xds/testdata/secrets/ingress-with-sds-listener-gw-level-http.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-sds-listener-gw-level-http.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-sds-listener-gw-level-mixed-tls.latest.golden b/agent/xds/testdata/secrets/ingress-with-sds-listener-gw-level-mixed-tls.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-sds-listener-gw-level-mixed-tls.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-sds-listener-gw-level.latest.golden b/agent/xds/testdata/secrets/ingress-with-sds-listener-gw-level.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-sds-listener-gw-level.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-sds-listener-level-wildcard.latest.golden b/agent/xds/testdata/secrets/ingress-with-sds-listener-level-wildcard.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-sds-listener-level-wildcard.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-sds-listener-level.latest.golden b/agent/xds/testdata/secrets/ingress-with-sds-listener-level.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-sds-listener-level.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-sds-listener-listener-level.latest.golden b/agent/xds/testdata/secrets/ingress-with-sds-listener-listener-level.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-sds-listener-listener-level.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-sds-service-level-2.latest.golden b/agent/xds/testdata/secrets/ingress-with-sds-service-level-2.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-sds-service-level-2.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-sds-service-level-mixed-no-tls.latest.golden b/agent/xds/testdata/secrets/ingress-with-sds-service-level-mixed-no-tls.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-sds-service-level-mixed-no-tls.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-sds-service-level-mixed-tls.latest.golden b/agent/xds/testdata/secrets/ingress-with-sds-service-level-mixed-tls.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-sds-service-level-mixed-tls.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-sds-service-level.latest.golden b/agent/xds/testdata/secrets/ingress-with-sds-service-level.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-sds-service-level.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-service-max-connections.latest.golden b/agent/xds/testdata/secrets/ingress-with-service-max-connections.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-service-max-connections.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-service-passive-health-check.latest.golden b/agent/xds/testdata/secrets/ingress-with-service-passive-health-check.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-service-passive-health-check.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-single-tls-listener.latest.golden b/agent/xds/testdata/secrets/ingress-with-single-tls-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-single-tls-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/secrets/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tcp-chain-double-failover-through-local-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden b/agent/xds/testdata/secrets/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tcp-chain-double-failover-through-local-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/secrets/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/secrets/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tcp-chain-double-failover-through-remote-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden b/agent/xds/testdata/secrets/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tcp-chain-failover-through-local-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tcp-chain-failover-through-local-gateway.latest.golden b/agent/xds/testdata/secrets/ingress-with-tcp-chain-failover-through-local-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tcp-chain-failover-through-local-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden b/agent/xds/testdata/secrets/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tcp-chain-failover-through-remote-gateway-triggered.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tcp-chain-failover-through-remote-gateway.latest.golden b/agent/xds/testdata/secrets/ingress-with-tcp-chain-failover-through-remote-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tcp-chain-failover-through-remote-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tls-listener-cipher-suites.latest.golden b/agent/xds/testdata/secrets/ingress-with-tls-listener-cipher-suites.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tls-listener-cipher-suites.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tls-listener-max-version.latest.golden b/agent/xds/testdata/secrets/ingress-with-tls-listener-max-version.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tls-listener-max-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tls-listener-min-version.latest.golden b/agent/xds/testdata/secrets/ingress-with-tls-listener-min-version.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tls-listener-min-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tls-listener.latest.golden b/agent/xds/testdata/secrets/ingress-with-tls-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tls-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tls-min-version-listeners-gateway-defaults.latest.golden b/agent/xds/testdata/secrets/ingress-with-tls-min-version-listeners-gateway-defaults.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tls-min-version-listeners-gateway-defaults.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden b/agent/xds/testdata/secrets/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tls-mixed-cipher-suites-listeners.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tls-mixed-listeners.latest.golden b/agent/xds/testdata/secrets/ingress-with-tls-mixed-listeners.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tls-mixed-listeners.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tls-mixed-max-version-listeners.latest.golden b/agent/xds/testdata/secrets/ingress-with-tls-mixed-max-version-listeners.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tls-mixed-max-version-listeners.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/ingress-with-tls-mixed-min-version-listeners.latest.golden b/agent/xds/testdata/secrets/ingress-with-tls-mixed-min-version-listeners.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/ingress-with-tls-mixed-min-version-listeners.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/listener-balance-inbound-connections.latest.golden b/agent/xds/testdata/secrets/listener-balance-inbound-connections.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/listener-balance-inbound-connections.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/listener-balance-outbound-connections-bind-port.latest.golden b/agent/xds/testdata/secrets/listener-balance-outbound-connections-bind-port.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/listener-balance-outbound-connections-bind-port.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/listener-bind-address-port.latest.golden b/agent/xds/testdata/secrets/listener-bind-address-port.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/listener-bind-address-port.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/listener-bind-address.latest.golden b/agent/xds/testdata/secrets/listener-bind-address.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/listener-bind-address.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/listener-bind-port.latest.golden b/agent/xds/testdata/secrets/listener-bind-port.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/listener-bind-port.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/listener-max-inbound-connections.latest.golden b/agent/xds/testdata/secrets/listener-max-inbound-connections.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/listener-max-inbound-connections.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/listener-unix-domain-socket.latest.golden b/agent/xds/testdata/secrets/listener-unix-domain-socket.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/listener-unix-domain-socket.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-custom-addresses.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-custom-addresses.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-custom-addresses.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-default-service-subset.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-default-service-subset.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-default-service-subset.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-hash-lb-ignored.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-hash-lb-ignored.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-hash-lb-ignored.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-ignore-extra-resolvers.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-ignore-extra-resolvers.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-ignore-extra-resolvers.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-newer-information-in-federation-states.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-newer-information-in-federation-states.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-newer-information-in-federation-states.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-no-services.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-no-services.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-no-services.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-non-hash-lb-injected.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-non-hash-lb-injected.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-non-hash-lb-injected.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-older-information-in-federation-states.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-older-information-in-federation-states.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-older-information-in-federation-states.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-service-subsets.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-service-subsets.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-service-subsets.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-service-subsets2.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-service-subsets2.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-service-subsets2.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-service-timeouts.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-service-timeouts.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-service-timeouts.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-tagged-addresses.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-tagged-addresses.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-tagged-addresses.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-tcp-keepalives.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-tcp-keepalives.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-tcp-keepalives.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-using-federation-control-plane.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-using-federation-control-plane.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-using-federation-control-plane.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-using-federation-states.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-using-federation-states.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-using-federation-states.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway-with-limits.latest.golden b/agent/xds/testdata/secrets/mesh-gateway-with-limits.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway-with-limits.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/mesh-gateway.latest.golden b/agent/xds/testdata/secrets/mesh-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/mesh-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/splitter-with-resolver-redirect.latest.golden b/agent/xds/testdata/secrets/splitter-with-resolver-redirect.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/splitter-with-resolver-redirect.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-custom-and-tagged-addresses.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-custom-and-tagged-addresses.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-custom-and-tagged-addresses.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-custom-trace-listener.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-custom-trace-listener.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-custom-trace-listener.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-default-service-subset.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-default-service-subset.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-default-service-subset.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-hostname-service-subsets.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-hostname-service-subsets.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-hostname-service-subsets.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-http2-upstream-subsets.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-http2-upstream-subsets.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-http2-upstream-subsets.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-http2-upstream.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-http2-upstream.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-http2-upstream.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-ignore-extra-resolvers.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-ignore-extra-resolvers.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-ignore-extra-resolvers.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-lb-config-no-hash-policies.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-lb-config-no-hash-policies.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-lb-config-no-hash-policies.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-lb-config.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-lb-config.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-lb-config.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-no-api-cert.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-no-api-cert.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-no-api-cert.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-no-services.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-no-services.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-no-services.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-service-subsets.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-service-subsets.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-service-subsets.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-sni.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-sni.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-sni.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-tcp-keepalives.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-tcp-keepalives.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-tcp-keepalives.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-with-peer-trust-bundle.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-with-peer-trust-bundle.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-with-peer-trust-bundle.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-with-tls-incoming-cipher-suites.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-with-tls-incoming-cipher-suites.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-with-tls-incoming-cipher-suites.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-with-tls-incoming-max-version.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-with-tls-incoming-max-version.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-with-tls-incoming-max-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway-with-tls-incoming-min-version.latest.golden b/agent/xds/testdata/secrets/terminating-gateway-with-tls-incoming-min-version.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway-with-tls-incoming-min-version.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/terminating-gateway.latest.golden b/agent/xds/testdata/secrets/terminating-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/terminating-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/transparent-proxy-http-upstream.latest.golden b/agent/xds/testdata/secrets/transparent-proxy-http-upstream.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/transparent-proxy-http-upstream.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/transparent-proxy-terminating-gateway.latest.golden b/agent/xds/testdata/secrets/transparent-proxy-terminating-gateway.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/transparent-proxy-terminating-gateway.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/transparent-proxy-with-resolver-redirect-upstream.latest.golden b/agent/xds/testdata/secrets/transparent-proxy-with-resolver-redirect-upstream.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/transparent-proxy-with-resolver-redirect-upstream.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/xds-fetch-timeout-ms-ingress-with-router.latest.golden b/agent/xds/testdata/secrets/xds-fetch-timeout-ms-ingress-with-router.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/xds-fetch-timeout-ms-ingress-with-router.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/xds-fetch-timeout-ms-mgw-peering.latest.golden b/agent/xds/testdata/secrets/xds-fetch-timeout-ms-mgw-peering.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/xds-fetch-timeout-ms-mgw-peering.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/xds-fetch-timeout-ms-sidecar.latest.golden b/agent/xds/testdata/secrets/xds-fetch-timeout-ms-sidecar.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/xds-fetch-timeout-ms-sidecar.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/xds-fetch-timeout-ms-term-gw.latest.golden b/agent/xds/testdata/secrets/xds-fetch-timeout-ms-term-gw.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/xds-fetch-timeout-ms-term-gw.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden b/agent/xds/testdata/secrets/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/xds-fetch-timeout-ms-tproxy-http-peering.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/secrets/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden b/agent/xds/testdata/secrets/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden new file mode 100644 index 000000000000..82e45650658b --- /dev/null +++ b/agent/xds/testdata/secrets/xds-fetch-timeout-ms-tproxy-passthrough.latest.golden @@ -0,0 +1,5 @@ +{ + "nonce": "00000001", + "typeUrl": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testing.go b/agent/xds/testing.go index 916bbd9b5077..6d90005cd78f 100644 --- a/agent/xds/testing.go +++ b/agent/xds/testing.go @@ -125,15 +125,15 @@ func stringToEnvoyVersion(vs string) (*envoy_type_v3.SemanticVersion, bool) { return nil, false } - major, err := strconv.Atoi(parts[0]) + major, err := strconv.ParseUint(parts[0], 10, 32) if err != nil { return nil, false } - minor, err := strconv.Atoi(parts[1]) + minor, err := strconv.ParseUint(parts[1], 10, 32) if err != nil { return nil, false } - patch, err := strconv.Atoi(parts[2]) + patch, err := strconv.ParseUint(parts[2], 10, 32) if err != nil { return nil, false } diff --git a/agent/xds/validateupstream-test/validateupstream_test.go b/agent/xds/validateupstream-test/validateupstream_test.go index 9c57bdf81aaf..e36466d624df 100644 --- a/agent/xds/validateupstream-test/validateupstream_test.go +++ b/agent/xds/validateupstream-test/validateupstream_test.go @@ -12,7 +12,7 @@ import ( "github.com/hashicorp/consul/agent/xds/testcommon" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/troubleshoot/proxy" + troubleshoot "github.com/hashicorp/consul/troubleshoot/proxy" testinf "github.com/mitchellh/go-testing-interface" "github.com/stretchr/testify/require" ) @@ -156,7 +156,7 @@ func TestValidateUpstreams(t *testing.T) { name: "tproxy-success", vip: "240.0.0.1", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTransparentProxyHTTPUpstream(t) + return proxycfg.TestConfigSnapshotTransparentProxyHTTPUpstream(t, nil) }, patcher: func(ir *xdscommon.IndexedResources) *xdscommon.IndexedResources { return ir @@ -166,7 +166,7 @@ func TestValidateUpstreams(t *testing.T) { name: "tproxy-http-missing-cluster", vip: "240.0.0.1", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTransparentProxyHTTPUpstream(t) + return proxycfg.TestConfigSnapshotTransparentProxyHTTPUpstream(t, nil) }, patcher: func(ir *xdscommon.IndexedResources) *xdscommon.IndexedResources { sni := "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" @@ -179,7 +179,7 @@ func TestValidateUpstreams(t *testing.T) { name: "tproxy-http-redirect-success", vip: "240.0.0.1", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTransparentProxyHTTPUpstream(t, configEntriesForGoogleRedirect()...) + return proxycfg.TestConfigSnapshotTransparentProxyHTTPUpstream(t, nil, configEntriesForGoogleRedirect()...) }, patcher: func(ir *xdscommon.IndexedResources) *xdscommon.IndexedResources { return ir @@ -189,7 +189,7 @@ func TestValidateUpstreams(t *testing.T) { name: "tproxy-http-split-success", vip: "240.0.0.1", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotTransparentProxyHTTPUpstream(t, configEntriesForGoogleSplits()...) + return proxycfg.TestConfigSnapshotTransparentProxyHTTPUpstream(t, nil, configEntriesForGoogleSplits()...) }, patcher: func(ir *xdscommon.IndexedResources) *xdscommon.IndexedResources { return ir diff --git a/agent/xds/xds_protocol_helpers_test.go b/agent/xds/xds_protocol_helpers_test.go index 655e0458f49e..ff2fbdf38614 100644 --- a/agent/xds/xds_protocol_helpers_test.go +++ b/agent/xds/xds_protocol_helpers_test.go @@ -4,6 +4,7 @@ package xds import ( + "context" "sort" "sync" "testing" @@ -34,12 +35,9 @@ import ( "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/grpc-external/limiter" "github.com/hashicorp/consul/agent/proxycfg" - "github.com/hashicorp/consul/agent/proxycfg-sources/catalog" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/response" "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/sdk/testutil" ) @@ -73,16 +71,18 @@ func newTestSnapshot( // testing. It also implements ConnectAuthz to allow control over authorization. type testManager struct { sync.Mutex - stateChans map[structs.ServiceID]chan proxysnapshot.ProxySnapshot - drainChans map[structs.ServiceID]chan struct{} - cancels chan structs.ServiceID + stateChans map[structs.ServiceID]chan *proxycfg.ConfigSnapshot + drainChans map[structs.ServiceID]chan struct{} + cfgSrcTerminateChans map[structs.ServiceID]chan struct{} + cancels chan structs.ServiceID } func newTestManager(t *testing.T) *testManager { return &testManager{ - stateChans: map[structs.ServiceID]chan proxysnapshot.ProxySnapshot{}, - drainChans: map[structs.ServiceID]chan struct{}{}, - cancels: make(chan structs.ServiceID, 10), + stateChans: map[structs.ServiceID]chan *proxycfg.ConfigSnapshot{}, + drainChans: map[structs.ServiceID]chan struct{}{}, + cfgSrcTerminateChans: map[structs.ServiceID]chan struct{}{}, + cancels: make(chan structs.ServiceID, 10), } } @@ -90,12 +90,13 @@ func newTestManager(t *testing.T) *testManager { func (m *testManager) RegisterProxy(t *testing.T, proxyID structs.ServiceID) { m.Lock() defer m.Unlock() - m.stateChans[proxyID] = make(chan proxysnapshot.ProxySnapshot, 1) + m.stateChans[proxyID] = make(chan *proxycfg.ConfigSnapshot, 1) m.drainChans[proxyID] = make(chan struct{}) + m.cfgSrcTerminateChans[proxyID] = make(chan struct{}) } // Deliver simulates a proxy registration -func (m *testManager) DeliverConfig(t *testing.T, proxyID structs.ServiceID, cfg proxysnapshot.ProxySnapshot) { +func (m *testManager) DeliverConfig(t *testing.T, proxyID structs.ServiceID, cfg *proxycfg.ConfigSnapshot) { t.Helper() m.Lock() defer m.Unlock() @@ -121,11 +122,23 @@ func (m *testManager) DrainStreams(proxyID structs.ServiceID) { close(ch) } +// CfgSrcTerminate terminates any open streams for the given proxyID by indicating that the +// corresponding config-source terminated unexpectedly. +func (m *testManager) CfgSrcTerminate(proxyID structs.ServiceID) { + m.Lock() + defer m.Unlock() + + ch, ok := m.cfgSrcTerminateChans[proxyID] + if !ok { + ch = make(chan struct{}) + m.cfgSrcTerminateChans[proxyID] = ch + } + close(ch) +} + // Watch implements ConfigManager -func (m *testManager) Watch(id *pbresource.ID, _ string, _ string) (<-chan proxysnapshot.ProxySnapshot, - limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) { - // Create service ID - proxyID := structs.NewServiceID(id.Name, catalog.GetEnterpriseMetaFromResourceID(id)) +func (m *testManager) Watch(proxyID structs.ServiceID, _ string, _ string) (<-chan *proxycfg.ConfigSnapshot, + limiter.SessionTerminatedChan, proxycfg.SrcTerminatedChan, context.CancelFunc, error) { m.Lock() defer m.Unlock() @@ -133,12 +146,12 @@ func (m *testManager) Watch(id *pbresource.ID, _ string, _ string) (<-chan proxy drainCh := m.drainChans[proxyID] select { case <-drainCh: - return nil, nil, nil, limiter.ErrCapacityReached + return nil, nil, nil, nil, limiter.ErrCapacityReached default: } // ch might be nil but then it will just block forever - return m.stateChans[proxyID], drainCh, func() { + return m.stateChans[proxyID], drainCh, m.cfgSrcTerminateChans[proxyID], func() { m.cancels <- proxyID }, nil } @@ -295,7 +308,7 @@ func xdsNewTransportSocket( }, } if len(spiffeID) > 0 { - require.NoError(t, injectSANMatcher(commonTLSContext, spiffeID...)) + require.NoError(t, injectSANMatcher(commonTLSContext, false, spiffeID...)) } var tlsContext proto.Message @@ -781,8 +794,7 @@ func makeTestRoute(t *testing.T, fixtureName string) *envoy_route_v3.RouteConfig switch fixtureName { case "http2:db", "http:db": return &envoy_route_v3.RouteConfiguration{ - Name: "db", - ValidateClusters: response.MakeBoolValue(true), + Name: "db", VirtualHosts: []*envoy_route_v3.VirtualHost{ { Name: "db", diff --git a/agent/xdsv2/cluster_resources.go b/agent/xdsv2/cluster_resources.go deleted file mode 100644 index 6e33d64ecf6b..000000000000 --- a/agent/xdsv2/cluster_resources.go +++ /dev/null @@ -1,363 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xdsv2 - -import ( - "errors" - "fmt" - envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" - envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" - envoy_aggregate_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/clusters/aggregate/v3" - envoy_upstreams_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3" - envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" -) - -func (pr *ProxyResources) makeClusters(name string) (map[string]proto.Message, error) { - envoyClusters := make(map[string]proto.Message) - proxyStateCluster, ok := pr.proxyState.Clusters[name] - if !ok { - return nil, fmt.Errorf("cluster %q not found", name) - } - - switch proxyStateCluster.Group.(type) { - case *pbproxystate.Cluster_FailoverGroup: - fg := proxyStateCluster.GetFailoverGroup() - clusters, err := pr.makeEnvoyAggregateCluster(name, proxyStateCluster.Protocol, fg) - if err != nil { - return nil, err - } - for _, c := range clusters { - envoyClusters[c.Name] = c - } - - case *pbproxystate.Cluster_EndpointGroup: - eg := proxyStateCluster.GetEndpointGroup() - cluster, err := pr.makeEnvoyCluster(name, proxyStateCluster.Protocol, eg) - if err != nil { - return nil, err - } - envoyClusters[cluster.Name] = cluster - - default: - return nil, errors.New("cluster group type should be Endpoint Group or Failover Group") - } - return envoyClusters, nil -} - -func (pr *ProxyResources) makeEnvoyCluster(name string, protocol pbproxystate.Protocol, eg *pbproxystate.EndpointGroup) (*envoy_cluster_v3.Cluster, error) { - if eg != nil { - switch t := eg.Group.(type) { - case *pbproxystate.EndpointGroup_Dynamic: - dynamic := eg.GetDynamic() - return pr.makeEnvoyDynamicCluster(name, protocol, dynamic) - case *pbproxystate.EndpointGroup_Static: - static := eg.GetStatic() - return pr.makeEnvoyStaticCluster(name, protocol, static) - case *pbproxystate.EndpointGroup_Dns: - dns := eg.GetDns() - return pr.makeEnvoyDnsCluster(name, protocol, dns) - case *pbproxystate.EndpointGroup_Passthrough: - passthrough := eg.GetPassthrough() - return pr.makeEnvoyPassthroughCluster(name, protocol, passthrough) - default: - return nil, fmt.Errorf("unsupported endpoint group type: %s", t) - } - } - return nil, fmt.Errorf("no endpoint group") -} - -func (pr *ProxyResources) makeEnvoyDynamicCluster(name string, protocol pbproxystate.Protocol, dynamic *pbproxystate.DynamicEndpointGroup) (*envoy_cluster_v3.Cluster, error) { - cluster := &envoy_cluster_v3.Cluster{ - Name: name, - ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_EDS}, - EdsClusterConfig: &envoy_cluster_v3.Cluster_EdsClusterConfig{ - EdsConfig: &envoy_core_v3.ConfigSource{ - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, - ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_Ads{ - Ads: &envoy_core_v3.AggregatedConfigSource{}, - }, - }, - }, - } - err := addHttpProtocolOptions(protocol, cluster) - if err != nil { - return nil, err - } - if dynamic.Config != nil { - if dynamic.Config.UseAltStatName { - cluster.AltStatName = name - } - cluster.ConnectTimeout = dynamic.Config.ConnectTimeout - if dynamic.Config.DisablePanicThreshold { - cluster.CommonLbConfig = &envoy_cluster_v3.Cluster_CommonLbConfig{ - HealthyPanicThreshold: &envoy_type_v3.Percent{ - Value: 0, // disable panic threshold - }, - } - } - addEnvoyCircuitBreakers(dynamic.Config.CircuitBreakers, cluster) - addEnvoyOutlierDetection(dynamic.Config.OutlierDetection, cluster) - - err := addEnvoyLBToCluster(dynamic.Config, cluster) - if err != nil { - return nil, err - } - } - - if dynamic.OutboundTls != nil { - envoyTransportSocket, err := pr.makeEnvoyTransportSocket(dynamic.OutboundTls) - if err != nil { - return nil, err - } - cluster.TransportSocket = envoyTransportSocket - } - - return cluster, nil - -} - -func (pr *ProxyResources) makeEnvoyStaticCluster(name string, protocol pbproxystate.Protocol, static *pbproxystate.StaticEndpointGroup) (*envoy_cluster_v3.Cluster, error) { - cluster := &envoy_cluster_v3.Cluster{ - Name: name, - ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_STATIC}, - } - - // todo (ishustava/v2): we need to be able to handle the case when empty endpoints are allowed on a cluster. - endpointList, ok := pr.proxyState.Endpoints[name] - if ok { - cluster.LoadAssignment = makeEnvoyClusterLoadAssignment(name, endpointList.Endpoints) - } - - var err error - if name == xdscommon.LocalAppClusterName { - err = addLocalAppHttpProtocolOptions(protocol, cluster) - } else { - err = addHttpProtocolOptions(protocol, cluster) - } - if err != nil { - return nil, err - } - - if static.Config != nil { - cluster.ConnectTimeout = static.Config.ConnectTimeout - addEnvoyCircuitBreakers(static.GetConfig().CircuitBreakers, cluster) - } - return cluster, nil -} - -func (pr *ProxyResources) makeEnvoyDnsCluster(name string, protocol pbproxystate.Protocol, dns *pbproxystate.DNSEndpointGroup) (*envoy_cluster_v3.Cluster, error) { - return nil, nil -} - -func (pr *ProxyResources) makeEnvoyPassthroughCluster(name string, protocol pbproxystate.Protocol, passthrough *pbproxystate.PassthroughEndpointGroup) (*envoy_cluster_v3.Cluster, error) { - cluster := &envoy_cluster_v3.Cluster{ - Name: name, - ConnectTimeout: passthrough.Config.ConnectTimeout, - LbPolicy: envoy_cluster_v3.Cluster_CLUSTER_PROVIDED, - ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_ORIGINAL_DST}, - } - if passthrough.OutboundTls != nil { - envoyTransportSocket, err := pr.makeEnvoyTransportSocket(passthrough.OutboundTls) - if err != nil { - return nil, err - } - cluster.TransportSocket = envoyTransportSocket - } - err := addHttpProtocolOptions(protocol, cluster) - if err != nil { - return nil, err - } - return cluster, nil -} - -func (pr *ProxyResources) makeEnvoyAggregateCluster(name string, protocol pbproxystate.Protocol, fg *pbproxystate.FailoverGroup) (map[string]*envoy_cluster_v3.Cluster, error) { - clusters := make(map[string]*envoy_cluster_v3.Cluster) - if fg != nil { - var egNames []string - for _, eg := range fg.EndpointGroups { - cluster, err := pr.makeEnvoyCluster(eg.Name, protocol, eg) - if err != nil { - return nil, err - } - egNames = append(egNames, cluster.Name) - clusters[cluster.Name] = cluster - } - aggregateClusterConfig, err := anypb.New(&envoy_aggregate_cluster_v3.ClusterConfig{ - Clusters: egNames, - }) - - if err != nil { - return nil, err - } - - c := &envoy_cluster_v3.Cluster{ - Name: name, - ConnectTimeout: fg.Config.ConnectTimeout, - LbPolicy: envoy_cluster_v3.Cluster_CLUSTER_PROVIDED, - ClusterDiscoveryType: &envoy_cluster_v3.Cluster_ClusterType{ - ClusterType: &envoy_cluster_v3.Cluster_CustomClusterType{ - Name: "envoy.clusters.aggregate", - TypedConfig: aggregateClusterConfig, - }, - }, - } - if fg.Config.UseAltStatName { - c.AltStatName = name - } - err = addHttpProtocolOptions(protocol, c) - if err != nil { - return nil, err - } - clusters[c.Name] = c - } - return clusters, nil -} - -func addLocalAppHttpProtocolOptions(protocol pbproxystate.Protocol, c *envoy_cluster_v3.Cluster) error { - if !(protocol == pbproxystate.Protocol_PROTOCOL_HTTP2 || protocol == pbproxystate.Protocol_PROTOCOL_GRPC) { - // do not error. returning nil means it won't get set. - return nil - } - cfg := &envoy_upstreams_v3.HttpProtocolOptions{ - UpstreamProtocolOptions: &envoy_upstreams_v3.HttpProtocolOptions_UseDownstreamProtocolConfig{ - UseDownstreamProtocolConfig: &envoy_upstreams_v3.HttpProtocolOptions_UseDownstreamHttpConfig{ - HttpProtocolOptions: &envoy_core_v3.Http1ProtocolOptions{}, - Http2ProtocolOptions: &envoy_core_v3.Http2ProtocolOptions{}, - }, - }, - } - any, err := anypb.New(cfg) - if err != nil { - return err - } - c.TypedExtensionProtocolOptions = map[string]*anypb.Any{ - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": any, - } - - return nil -} - -func addHttpProtocolOptions(protocol pbproxystate.Protocol, c *envoy_cluster_v3.Cluster) error { - if !(protocol == pbproxystate.Protocol_PROTOCOL_HTTP2 || protocol == pbproxystate.Protocol_PROTOCOL_GRPC) { - // do not error. returning nil means it won't get set. - return nil - } - cfg := &envoy_upstreams_v3.HttpProtocolOptions{ - UpstreamProtocolOptions: &envoy_upstreams_v3.HttpProtocolOptions_ExplicitHttpConfig_{ - ExplicitHttpConfig: &envoy_upstreams_v3.HttpProtocolOptions_ExplicitHttpConfig{ - ProtocolConfig: &envoy_upstreams_v3.HttpProtocolOptions_ExplicitHttpConfig_Http2ProtocolOptions{ - Http2ProtocolOptions: &envoy_core_v3.Http2ProtocolOptions{}, - }, - }, - }, - } - any, err := anypb.New(cfg) - if err != nil { - return err - } - c.TypedExtensionProtocolOptions = map[string]*anypb.Any{ - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": any, - } - return nil -} - -// addEnvoyOutlierDetection will add outlier detection config to the cluster, and if nil, add empty OutlierDetection to -// enable it with default values -func addEnvoyOutlierDetection(outlierDetection *pbproxystate.OutlierDetection, c *envoy_cluster_v3.Cluster) { - if outlierDetection == nil { - return - } - od := &envoy_cluster_v3.OutlierDetection{ - BaseEjectionTime: outlierDetection.GetBaseEjectionTime(), - Consecutive_5Xx: outlierDetection.GetConsecutive_5Xx(), - EnforcingConsecutive_5Xx: outlierDetection.GetEnforcingConsecutive_5Xx(), - Interval: outlierDetection.GetInterval(), - MaxEjectionPercent: outlierDetection.GetMaxEjectionPercent(), - } - c.OutlierDetection = od - -} - -func addEnvoyCircuitBreakers(circuitBreakers *pbproxystate.CircuitBreakers, c *envoy_cluster_v3.Cluster) { - if circuitBreakers != nil { - if circuitBreakers.UpstreamLimits == nil { - c.CircuitBreakers = &envoy_cluster_v3.CircuitBreakers{} - return - } - threshold := &envoy_cluster_v3.CircuitBreakers_Thresholds{} - threshold.MaxConnections = circuitBreakers.UpstreamLimits.MaxConnections - threshold.MaxPendingRequests = circuitBreakers.UpstreamLimits.MaxPendingRequests - threshold.MaxRequests = circuitBreakers.UpstreamLimits.MaxConcurrentRequests - - c.CircuitBreakers = &envoy_cluster_v3.CircuitBreakers{ - Thresholds: []*envoy_cluster_v3.CircuitBreakers_Thresholds{threshold}, - } - } -} - -func addEnvoyLBToCluster(dynamicConfig *pbproxystate.DynamicEndpointGroupConfig, c *envoy_cluster_v3.Cluster) error { - if dynamicConfig == nil || dynamicConfig.LbPolicy == nil { - return nil - } - - switch d := dynamicConfig.LbPolicy.(type) { - case *pbproxystate.DynamicEndpointGroupConfig_LeastRequest: - c.LbPolicy = envoy_cluster_v3.Cluster_LEAST_REQUEST - - lb := dynamicConfig.LbPolicy.(*pbproxystate.DynamicEndpointGroupConfig_LeastRequest) - if lb.LeastRequest != nil { - c.LbConfig = &envoy_cluster_v3.Cluster_LeastRequestLbConfig_{ - LeastRequestLbConfig: &envoy_cluster_v3.Cluster_LeastRequestLbConfig{ - ChoiceCount: lb.LeastRequest.ChoiceCount, - }, - } - } - case *pbproxystate.DynamicEndpointGroupConfig_RoundRobin: - c.LbPolicy = envoy_cluster_v3.Cluster_ROUND_ROBIN - - case *pbproxystate.DynamicEndpointGroupConfig_Random: - c.LbPolicy = envoy_cluster_v3.Cluster_RANDOM - - case *pbproxystate.DynamicEndpointGroupConfig_RingHash: - c.LbPolicy = envoy_cluster_v3.Cluster_RING_HASH - - lb := dynamicConfig.LbPolicy.(*pbproxystate.DynamicEndpointGroupConfig_RingHash) - if lb.RingHash != nil { - c.LbConfig = &envoy_cluster_v3.Cluster_RingHashLbConfig_{ - RingHashLbConfig: &envoy_cluster_v3.Cluster_RingHashLbConfig{ - MinimumRingSize: lb.RingHash.MinimumRingSize, - MaximumRingSize: lb.RingHash.MaximumRingSize, - }, - } - } - case *pbproxystate.DynamicEndpointGroupConfig_Maglev: - c.LbPolicy = envoy_cluster_v3.Cluster_MAGLEV - - default: - return fmt.Errorf("unsupported load balancer policy %q for cluster %q", d, c.Name) - } - return nil -} - -func (pr *ProxyResources) makeEnvoyClusterFromL4Destination(l4 *pbproxystate.L4Destination) error { - switch l4.Destination.(type) { - case *pbproxystate.L4Destination_Cluster: - pr.addEnvoyClustersAndEndpointsToEnvoyResources(l4.GetCluster().GetName()) - - case *pbproxystate.L4Destination_WeightedClusters: - psWeightedClusters := l4.GetWeightedClusters() - for _, psCluster := range psWeightedClusters.GetClusters() { - pr.addEnvoyClustersAndEndpointsToEnvoyResources(psCluster.Name) - } - default: - return errors.New("cluster group type should be Endpoint Group or Failover Group") - } - - return nil -} diff --git a/agent/xdsv2/endpoint_resources.go b/agent/xdsv2/endpoint_resources.go deleted file mode 100644 index ce81d5cad0f6..000000000000 --- a/agent/xdsv2/endpoint_resources.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xdsv2 - -import ( - envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" - envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" -) - -func makeEnvoyLbEndpoint(endpoint *pbproxystate.Endpoint) *envoy_endpoint_v3.LbEndpoint { - hs := int32(endpoint.GetHealthStatus().Number()) - return &envoy_endpoint_v3.LbEndpoint{ - HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{ - Endpoint: makeEnvoyEndpoint(endpoint), - }, - HealthStatus: envoy_core_v3.HealthStatus(hs), - LoadBalancingWeight: endpoint.GetLoadBalancingWeight(), - } -} - -func makeEnvoyEndpoint(endpoint *pbproxystate.Endpoint) *envoy_endpoint_v3.Endpoint { - var address *envoy_core_v3.Address - if endpoint.GetUnixSocket() != nil { - address = response.MakePipeAddress(endpoint.GetUnixSocket().GetPath(), 0) - } else { - address = response.MakeAddress(endpoint.GetHostPort().GetHost(), int(endpoint.GetHostPort().Port)) - } - - return &envoy_endpoint_v3.Endpoint{ - Address: address, - } -} - -func makeEnvoyClusterLoadAssignment(clusterName string, endpoints []*pbproxystate.Endpoint) *envoy_endpoint_v3.ClusterLoadAssignment { - localityLbEndpoints := &envoy_endpoint_v3.LocalityLbEndpoints{} - for _, endpoint := range endpoints { - localityLbEndpoints.LbEndpoints = append(localityLbEndpoints.LbEndpoints, makeEnvoyLbEndpoint(endpoint)) - } - return &envoy_endpoint_v3.ClusterLoadAssignment{ - ClusterName: clusterName, - Endpoints: []*envoy_endpoint_v3.LocalityLbEndpoints{localityLbEndpoints}, - } -} diff --git a/agent/xdsv2/listener_resources.go b/agent/xdsv2/listener_resources.go deleted file mode 100644 index a7f3976ed570..000000000000 --- a/agent/xdsv2/listener_resources.go +++ /dev/null @@ -1,1144 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xdsv2 - -import ( - "fmt" - "sort" - "strconv" - - envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" - envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" - envoy_grpc_http1_bridge_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/grpc_http1_bridge/v3" - envoy_grpc_stats_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/grpc_stats/v3" - envoy_http_header_to_meta_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/header_to_metadata/v3" - envoy_http_router_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/router/v3" - envoy_extensions_filters_listener_http_inspector_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/http_inspector/v3" - envoy_original_dst_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/original_dst/v3" - envoy_tls_inspector_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/tls_inspector/v3" - envoy_connection_limit_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/connection_limit/v3" - envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - envoy_sni_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/sni_cluster/v3" - envoy_tcp_proxy_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/tcp_proxy/v3" - envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" - envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" - envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" - - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/lib" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" -) - -const ( - envoyNetworkFilterName = "envoy.filters.network.tcp_proxy" - envoyOriginalDestinationListenerFilterName = "envoy.filters.listener.original_dst" - envoyTLSInspectorListenerFilterName = "envoy.filters.listener.tls_inspector" - envoyHttpInspectorListenerFilterName = "envoy.filters.listener.http_inspector" - envoyHttpConnectionManagerFilterName = "envoy.filters.network.http_connection_manager" -) - -func (pr *ProxyResources) makeEnvoyResourceGraphsStartingFromListeners() error { - for _, l := range pr.proxyState.Listeners { - protoListener, err := pr.makeListener(l) - // TODO: aggregate errors for listeners and still return any properly formed listeners. - if err != nil { - return err - } - pr.envoyResources[xdscommon.ListenerType][protoListener.Name] = protoListener - } - return nil -} - -func (pr *ProxyResources) makeListener(listener *pbproxystate.Listener) (*envoy_listener_v3.Listener, error) { - envoyListener := &envoy_listener_v3.Listener{} - - // Listener Address - var address *envoy_core_v3.Address - switch listener.BindAddress.(type) { - case *pbproxystate.Listener_HostPort: - address = makeIpPortEnvoyAddress(listener.BindAddress.(*pbproxystate.Listener_HostPort)) - case *pbproxystate.Listener_UnixSocket: - address = makeUnixSocketEnvoyAddress(listener.BindAddress.(*pbproxystate.Listener_UnixSocket)) - default: - // This should be impossible to reach because we're using protobufs. - return nil, fmt.Errorf("invalid listener bind address type: %t", listener.BindAddress) - } - envoyListener.Address = address - - // Listener Direction - var direction envoy_core_v3.TrafficDirection - switch listener.Direction { - case pbproxystate.Direction_DIRECTION_OUTBOUND: - direction = envoy_core_v3.TrafficDirection_OUTBOUND - case pbproxystate.Direction_DIRECTION_INBOUND: - direction = envoy_core_v3.TrafficDirection_INBOUND - case pbproxystate.Direction_DIRECTION_UNSPECIFIED: - direction = envoy_core_v3.TrafficDirection_UNSPECIFIED - default: - return nil, fmt.Errorf("no direction for listener %+v", listener.Name) - } - envoyListener.TrafficDirection = direction - - // Before creating the filter chains, sort routers by match to avoid draining if the list is provided out of order. - sortRouters(listener.Routers) - - // Listener filter chains - for _, r := range listener.Routers { - filterChain, err := pr.makeEnvoyListenerFilterChain(r) - if err != nil { - return nil, fmt.Errorf("could not make filter chain: %w", err) - } - envoyListener.FilterChains = append(envoyListener.FilterChains, filterChain) - } - - if listener.DefaultRouter != nil { - defaultFilterChain, err := pr.makeEnvoyListenerFilterChain(listener.DefaultRouter) - if err != nil { - return nil, fmt.Errorf("could not make filter chain: %w", err) - } - envoyListener.DefaultFilterChain = defaultFilterChain - } - - // Envoy builtin listener filters - for _, c := range listener.Capabilities { - listenerFilter, err := makeEnvoyListenerFilter(c) - if err != nil { - return nil, fmt.Errorf("could not make listener filter: %w", err) - } - envoyListener.ListenerFilters = append(envoyListener.ListenerFilters, listenerFilter) - } - - err := addEnvoyListenerConnectionBalanceConfig(listener.BalanceConnections, envoyListener) - if err != nil { - return nil, err - } - - envoyListener.Name = listener.Name - envoyListener.Address = address - envoyListener.TrafficDirection = direction - - return envoyListener, nil -} - -func makeEnvoyConnectionLimitFilter(maxInboundConns uint64) (*envoy_listener_v3.Filter, error) { - cfg := &envoy_connection_limit_v3.ConnectionLimit{ - StatPrefix: "inbound_connection_limit", - MaxConnections: wrapperspb.UInt64(maxInboundConns), - } - - return makeEnvoyFilter("envoy.filters.network.connection_limit", cfg) -} - -func addEnvoyListenerConnectionBalanceConfig(balanceType pbproxystate.BalanceConnections, listener *envoy_listener_v3.Listener) error { - switch balanceType { - case pbproxystate.BalanceConnections_BALANCE_CONNECTIONS_DEFAULT: - // Default with no balancing. - return nil - case pbproxystate.BalanceConnections_BALANCE_CONNECTIONS_EXACT: - listener.ConnectionBalanceConfig = &envoy_listener_v3.Listener_ConnectionBalanceConfig{ - BalanceType: &envoy_listener_v3.Listener_ConnectionBalanceConfig_ExactBalance_{}, - } - return nil - default: - // This should be impossible using protobufs. - return fmt.Errorf("unsupported connection balance option: %+v", balanceType) - } -} - -func makeIpPortEnvoyAddress(address *pbproxystate.Listener_HostPort) *envoy_core_v3.Address { - return &envoy_core_v3.Address{ - Address: &envoy_core_v3.Address_SocketAddress{ - SocketAddress: &envoy_core_v3.SocketAddress{ - Address: address.HostPort.Host, - PortSpecifier: &envoy_core_v3.SocketAddress_PortValue{ - PortValue: address.HostPort.Port, - }, - }, - }, - } -} - -func makeUnixSocketEnvoyAddress(address *pbproxystate.Listener_UnixSocket) *envoy_core_v3.Address { - modeInt, err := strconv.ParseUint(address.UnixSocket.Mode, 0, 32) - if err != nil { - modeInt = 0 - } - return &envoy_core_v3.Address{ - Address: &envoy_core_v3.Address_Pipe{ - Pipe: &envoy_core_v3.Pipe{ - Path: address.UnixSocket.Path, - Mode: uint32(modeInt), - }, - }, - } -} - -func (pr *ProxyResources) makeEnvoyListenerFilterChain(router *pbproxystate.Router) (*envoy_listener_v3.FilterChain, error) { - envoyFilterChain := &envoy_listener_v3.FilterChain{} - - if router == nil { - return nil, fmt.Errorf("no router to create filter chain") - } - - // Router Match - match := makeEnvoyFilterChainMatch(router.Match) - if match != nil { - envoyFilterChain.FilterChainMatch = match - } - - // Router Destination - var envoyFilters []*envoy_listener_v3.Filter - switch router.Destination.(type) { - case *pbproxystate.Router_L4: - l4Filters, err := pr.makeEnvoyResourcesForL4Destination(router.Destination.(*pbproxystate.Router_L4)) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, l4Filters...) - case *pbproxystate.Router_L7: - l7 := router.Destination.(*pbproxystate.Router_L7) - l7Filters, err := pr.makeEnvoyResourcesForL7Destination(l7) - if err != nil { - return nil, err - } - - // Inject ALPN protocols to router's TLS if destination is L7 - if router.InboundTls != nil { - router.InboundTls.AlpnProtocols = getAlpnProtocols(l7.L7.Protocol) - } - envoyFilters = append(envoyFilters, l7Filters...) - case *pbproxystate.Router_Sni: - sniFilters, err := pr.makeEnvoyResourcesForSNIDestination(router.Destination.(*pbproxystate.Router_Sni)) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, sniFilters...) - default: - // This should be impossible using protobufs. - return nil, fmt.Errorf("unsupported destination type: %t", router.Destination) - - } - - // Router TLS - ts, err := pr.makeEnvoyTransportSocket(router.InboundTls) - if err != nil { - return nil, err - } - envoyFilterChain.TransportSocket = ts - - envoyFilterChain.Filters = envoyFilters - return envoyFilterChain, err -} - -func makeEnvoyFilterChainMatch(routerMatch *pbproxystate.Match) *envoy_listener_v3.FilterChainMatch { - var envoyFilterChainMatch *envoy_listener_v3.FilterChainMatch - if routerMatch != nil { - envoyFilterChainMatch = &envoy_listener_v3.FilterChainMatch{} - - envoyFilterChainMatch.DestinationPort = routerMatch.DestinationPort - - if len(routerMatch.ServerNames) > 0 { - var serverNames []string - for _, n := range routerMatch.ServerNames { - serverNames = append(serverNames, n) - } - envoyFilterChainMatch.ServerNames = serverNames - } - if len(routerMatch.PrefixRanges) > 0 { - sortPrefixRanges(routerMatch.PrefixRanges) - var ranges []*envoy_core_v3.CidrRange - for _, r := range routerMatch.PrefixRanges { - cidrRange := &envoy_core_v3.CidrRange{ - PrefixLen: r.PrefixLen, - AddressPrefix: r.AddressPrefix, - } - ranges = append(ranges, cidrRange) - } - envoyFilterChainMatch.PrefixRanges = ranges - } - if len(routerMatch.SourcePrefixRanges) > 0 { - var ranges []*envoy_core_v3.CidrRange - for _, r := range routerMatch.SourcePrefixRanges { - cidrRange := &envoy_core_v3.CidrRange{ - PrefixLen: r.PrefixLen, - AddressPrefix: r.AddressPrefix, - } - ranges = append(ranges, cidrRange) - } - envoyFilterChainMatch.SourcePrefixRanges = ranges - } - if len(routerMatch.AlpnProtocols) > 0 { - sort.Strings(routerMatch.AlpnProtocols) - var alpnProtocols []string - for _, protocol := range routerMatch.AlpnProtocols { - alpnProtocols = append(alpnProtocols, protocol) - } - envoyFilterChainMatch.ApplicationProtocols = alpnProtocols - } - } - return envoyFilterChainMatch -} - -func (pr *ProxyResources) makeEnvoyResourcesForSNIDestination(sni *pbproxystate.Router_Sni) ([]*envoy_listener_v3.Filter, error) { - var envoyFilters []*envoy_listener_v3.Filter - sniFilter, err := makeEnvoyFilter("envoy.filters.network.sni_cluster", &envoy_sni_cluster_v3.SniCluster{}) - if err != nil { - return nil, err - } - tcp := &envoy_tcp_proxy_v3.TcpProxy{ - StatPrefix: sni.Sni.StatPrefix, - ClusterSpecifier: &envoy_tcp_proxy_v3.TcpProxy_Cluster{Cluster: ""}, - } - tcpFilter, err := makeEnvoyFilter(envoyNetworkFilterName, tcp) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, sniFilter, tcpFilter) - return envoyFilters, err -} - -func (pr *ProxyResources) makeEnvoyResourcesForL4Destination(l4 *pbproxystate.Router_L4) ([]*envoy_listener_v3.Filter, error) { - err := pr.makeEnvoyClusterFromL4Destination(l4.L4) - if err != nil { - return nil, err - } - envoyFilters, err := pr.makeL4Filters(l4.L4) - return envoyFilters, err -} - -func (pr *ProxyResources) makeEnvoyResourcesForL7Destination(l7 *pbproxystate.Router_L7) ([]*envoy_listener_v3.Filter, error) { - envoyFilters, err := pr.makeL7Filters(l7.L7) - if err != nil { - return nil, err - } - return envoyFilters, err -} - -func getAlpnProtocols(protocol pbproxystate.L7Protocol) []string { - var alpnProtocols []string - - switch protocol { - case pbproxystate.L7Protocol_L7_PROTOCOL_GRPC, pbproxystate.L7Protocol_L7_PROTOCOL_HTTP2: - alpnProtocols = append(alpnProtocols, "h2", "http/1.1") - case pbproxystate.L7Protocol_L7_PROTOCOL_HTTP: - alpnProtocols = append(alpnProtocols, "http/1.1") - } - - return alpnProtocols -} - -func (pr *ProxyResources) makeL4Filters(l4 *pbproxystate.L4Destination) ([]*envoy_listener_v3.Filter, error) { - var envoyFilters []*envoy_listener_v3.Filter - if l4 != nil { - rbacFilters, err := MakeRBACNetworkFilters(l4.TrafficPermissions) - if err != nil { - return nil, err - } - - if len(rbacFilters) > 0 { - envoyFilters = append(envoyFilters, rbacFilters...) - } - - if l4.MaxInboundConnections > 0 { - connectionLimitFilter, err := makeEnvoyConnectionLimitFilter(l4.MaxInboundConnections) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, connectionLimitFilter) - } - - // Add tcp proxy filter - tcp := &envoy_tcp_proxy_v3.TcpProxy{ - StatPrefix: l4.StatPrefix, - } - - switch dest := l4.Destination.(type) { - case *pbproxystate.L4Destination_Cluster: - tcp.ClusterSpecifier = &envoy_tcp_proxy_v3.TcpProxy_Cluster{Cluster: dest.Cluster.Name} - case *pbproxystate.L4Destination_WeightedClusters: - clusters := make([]*envoy_tcp_proxy_v3.TcpProxy_WeightedCluster_ClusterWeight, 0, len(dest.WeightedClusters.Clusters)) - for _, cluster := range dest.WeightedClusters.Clusters { - clusters = append(clusters, &envoy_tcp_proxy_v3.TcpProxy_WeightedCluster_ClusterWeight{ - Name: cluster.Name, - Weight: cluster.Weight.GetValue(), - }) - } - - tcp.ClusterSpecifier = &envoy_tcp_proxy_v3.TcpProxy_WeightedClusters{ - WeightedClusters: &envoy_tcp_proxy_v3.TcpProxy_WeightedCluster{ - Clusters: clusters, - }, - } - default: - return nil, fmt.Errorf("unexpected l4 destination type: %T", l4.Destination) - } - - tcpFilter, err := makeEnvoyFilter(envoyNetworkFilterName, tcp) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, tcpFilter) - } - return envoyFilters, nil - -} - -// TODO: Forward client cert details will be added as part of L7 listeners task. -func (pr *ProxyResources) makeL7Filters(l7 *pbproxystate.L7Destination) ([]*envoy_listener_v3.Filter, error) { - var envoyFilters []*envoy_listener_v3.Filter - var httpConnMgr *envoy_http_v3.HttpConnectionManager - - if l7 != nil { - // TODO: Intentions will be added in the future. - if l7.MaxInboundConnections > 0 { - connLimitFilter, err := makeEnvoyConnectionLimitFilter(l7.MaxInboundConnections) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, connLimitFilter) - } - envoyHttpRouter, err := makeEnvoyHTTPFilter("envoy.filters.http.router", &envoy_http_router_v3.Router{}) - if err != nil { - return nil, err - } - - httpConnMgr = &envoy_http_v3.HttpConnectionManager{ - StatPrefix: l7.StatPrefix, - CodecType: envoy_http_v3.HttpConnectionManager_AUTO, - HttpFilters: []*envoy_http_v3.HttpFilter{ - envoyHttpRouter, - }, - Tracing: &envoy_http_v3.HttpConnectionManager_Tracing{ - // Don't trace any requests by default unless the client application - // explicitly propagates trace headers that indicate this should be - // sampled. - RandomSampling: &envoy_type_v3.Percent{Value: 0.0}, - }, - // Explicitly enable WebSocket upgrades for all HTTP listeners - UpgradeConfigs: []*envoy_http_v3.HttpConnectionManager_UpgradeConfig{ - {UpgradeType: "websocket"}, - }, - } - - if l7.Route == nil { - return nil, fmt.Errorf("route should not be nil") - } - routeConfig := pr.makeEnvoyRouteConfigFromProxystateRoute(l7.Route.Name, pr.proxyState.Routes[l7.Route.Name]) - if err != nil { - return nil, err - } - - if l7.StaticRoute { - routeConfig.ValidateClusters = nil - httpConnMgr.RouteSpecifier = &envoy_http_v3.HttpConnectionManager_RouteConfig{ - RouteConfig: routeConfig, - } - } else { - // Add Envoy route under the route resource since it's not inlined. - pr.envoyResources[xdscommon.RouteType][routeConfig.Name] = routeConfig - - httpConnMgr.RouteSpecifier = &envoy_http_v3.HttpConnectionManager_Rds{ - Rds: &envoy_http_v3.Rds{ - RouteConfigName: l7.Route.Name, - ConfigSource: &envoy_core_v3.ConfigSource{ - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, - ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_Ads{ - Ads: &envoy_core_v3.AggregatedConfigSource{}, - }, - }, - }, - } - } - - if l7.IncludeXfccPolicy { - httpConnMgr.ForwardClientCertDetails = envoyXFCCPolicy[l7.XfccPolicy] - httpConnMgr.SetCurrentClientCertDetails = &envoy_http_v3.HttpConnectionManager_SetCurrentClientCertDetails{ - Subject: &wrapperspb.BoolValue{Value: true}, - Cert: true, - Chain: true, - Dns: true, - Uri: true, - } - } - - // Add http2 protocol options - if l7.Protocol == pbproxystate.L7Protocol_L7_PROTOCOL_HTTP2 || l7.Protocol == pbproxystate.L7Protocol_L7_PROTOCOL_GRPC { - httpConnMgr.Http2ProtocolOptions = &envoy_core_v3.Http2ProtocolOptions{} - } - - // Add http authorization filters. First are jwt auth filters (not yet implemented), then traffic permission filters (not yet implemented), then xfcc filters. - var httpAuthzFilters []*envoy_http_v3.HttpFilter - - // Add traffic permission filters. - // Currently only adds the empty filter since L7 traffic permissions are not yet implemented. - if l7.TrafficPermissions != nil { - // For now, MakeRBACHTTPFilters only has L4 granularity traffic permissions in it. - l7TrafficPermsFilters, err := MakeRBACHTTPFilters(l7.TrafficPermissions) - if err != nil { - return nil, err - } - httpAuthzFilters = append(httpAuthzFilters, l7TrafficPermsFilters...) - } - - if l7.ParseXfccHeaders { - parseXFCCFilter, err := parseXFCCToDynamicMetaHTTPFilter() - if err != nil { - return nil, err - } - httpAuthzFilters = append(httpAuthzFilters, parseXFCCFilter) - } - - // Here we ensure that the first filter - // (other than the "envoy.grpc_http1_bridge" filter) in the http filter - // chain of a public listener is the authz filter to prevent unauthorized - // access and that every filter chain uses our TLS certs. - if len(httpAuthzFilters) > 0 { - httpConnMgr.HttpFilters = append(httpAuthzFilters, httpConnMgr.HttpFilters...) - } - - // Add grpc envoy http filters. - if l7.Protocol == pbproxystate.L7Protocol_L7_PROTOCOL_GRPC { - grpcHttp1Bridge, err := makeEnvoyHTTPFilter( - "envoy.filters.http.grpc_http1_bridge", - &envoy_grpc_http1_bridge_v3.Config{}, - ) - if err != nil { - return nil, err - } - - // In envoy 1.14.x the default value "stats_for_all_methods=true" was - // deprecated, and was changed to "false" in 1.18.x. Avoid using the - // default. TODO: we may want to expose this to users somehow easily. - grpcStatsFilter, err := makeEnvoyHTTPFilter( - "envoy.filters.http.grpc_stats", - &envoy_grpc_stats_v3.FilterConfig{ - PerMethodStatSpecifier: &envoy_grpc_stats_v3.FilterConfig_StatsForAllMethods{ - StatsForAllMethods: &wrapperspb.BoolValue{Value: true}, - }, - }, - ) - if err != nil { - return nil, err - } - - // Add grpc bridge before envoyRouter and authz, and the stats in front of that. - httpConnMgr.HttpFilters = append([]*envoy_http_v3.HttpFilter{ - grpcStatsFilter, - grpcHttp1Bridge, - }, httpConnMgr.HttpFilters...) - } - - httpFilter, err := makeEnvoyFilter(envoyHttpConnectionManagerFilterName, httpConnMgr) - if err != nil { - return nil, err - } - envoyFilters = append(envoyFilters, httpFilter) - } - return envoyFilters, nil -} - -func (pr *ProxyResources) makeEnvoyTLSParameters(defaultParams *pbproxystate.TLSParameters, overrideParams *pbproxystate.TLSParameters) *envoy_tls_v3.TlsParameters { - tlsParams := &envoy_tls_v3.TlsParameters{} - - if overrideParams != nil { - if overrideParams.MinVersion != pbproxystate.TLSVersion_TLS_VERSION_UNSPECIFIED { - if minVersion, ok := envoyTLSVersions[overrideParams.MinVersion]; ok { - tlsParams.TlsMinimumProtocolVersion = minVersion - } - } - if overrideParams.MaxVersion != pbproxystate.TLSVersion_TLS_VERSION_UNSPECIFIED { - if maxVersion, ok := envoyTLSVersions[overrideParams.MaxVersion]; ok { - tlsParams.TlsMaximumProtocolVersion = maxVersion - } - } - if len(overrideParams.CipherSuites) != 0 { - tlsParams.CipherSuites = marshalEnvoyTLSCipherSuiteStrings(overrideParams.CipherSuites) - } - return tlsParams - } - - if defaultParams != nil { - if defaultParams.MinVersion != pbproxystate.TLSVersion_TLS_VERSION_UNSPECIFIED { - if minVersion, ok := envoyTLSVersions[defaultParams.MinVersion]; ok { - tlsParams.TlsMinimumProtocolVersion = minVersion - } - } - if defaultParams.MaxVersion != pbproxystate.TLSVersion_TLS_VERSION_UNSPECIFIED { - if maxVersion, ok := envoyTLSVersions[defaultParams.MaxVersion]; ok { - tlsParams.TlsMaximumProtocolVersion = maxVersion - } - } - if len(defaultParams.CipherSuites) != 0 { - tlsParams.CipherSuites = marshalEnvoyTLSCipherSuiteStrings(defaultParams.CipherSuites) - } - return tlsParams - } - - return tlsParams - -} - -func (pr *ProxyResources) makeEnvoyTransportSocket(ts *pbproxystate.TransportSocket) (*envoy_core_v3.TransportSocket, error) { - if ts == nil { - return nil, nil - } - commonTLSContext := &envoy_tls_v3.CommonTlsContext{} - if ts.AlpnProtocols != nil { - commonTLSContext.AlpnProtocols = ts.AlpnProtocols - } - - // Create connection TLS. Listeners should only look at inbound TLS. - switch ts.ConnectionTls.(type) { - case *pbproxystate.TransportSocket_InboundMesh: - downstreamContext := &envoy_tls_v3.DownstreamTlsContext{} - downstreamContext.CommonTlsContext = commonTLSContext - // Set TLS Parameters. - if pr.proxyState.Tls != nil { - tlsParams := pr.makeEnvoyTLSParameters(pr.proxyState.Tls.InboundTlsParameters, ts.TlsParameters) - commonTLSContext.TlsParams = tlsParams - } else { - commonTLSContext.TlsParams = &envoy_tls_v3.TlsParameters{} - } - - // Set the certificate config on the tls context. - // For inbound mesh, we need to add the identity certificate - // and the validation context for the mesh depending on the provided trust bundle names. - im := ts.ConnectionTls.(*pbproxystate.TransportSocket_InboundMesh).InboundMesh - leaf, ok := pr.proxyState.LeafCertificates[im.IdentityKey] - if !ok { - return nil, fmt.Errorf("failed to create transport socket: leaf certificate %q not found", im.IdentityKey) - } - err := pr.makeEnvoyCertConfig(commonTLSContext, leaf) - if err != nil { - return nil, fmt.Errorf("failed to create transport socket: %w", err) - } - - // Create validation context. - // When there's only one trust bundle name, we create a simple validation context - if len(im.ValidationContext.TrustBundlePeerNameKeys) == 1 { - peerName := im.ValidationContext.TrustBundlePeerNameKeys[0] - tb, ok := pr.proxyState.TrustBundles[peerName] - if !ok { - return nil, fmt.Errorf("failed to create transport socket: provided trust bundle name does not exist in proxystate trust bundle map: %s", peerName) - } - commonTLSContext.ValidationContextType = &envoy_tls_v3.CommonTlsContext_ValidationContext{ - ValidationContext: &envoy_tls_v3.CertificateValidationContext{ - // TODO(banks): later for L7 support we may need to configure ALPN here. - TrustedCa: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: RootPEMsAsString(tb.Roots), - }, - }, - }, - } - } else if len(im.ValidationContext.TrustBundlePeerNameKeys) > 1 { - cfg := &envoy_tls_v3.SPIFFECertValidatorConfig{ - TrustDomains: make([]*envoy_tls_v3.SPIFFECertValidatorConfig_TrustDomain, 0, len(im.ValidationContext.TrustBundlePeerNameKeys)), - } - - for _, peerName := range im.ValidationContext.TrustBundlePeerNameKeys { - // Look up the trust bundle ca in the map. - tb, ok := pr.proxyState.TrustBundles[peerName] - if !ok { - return nil, fmt.Errorf("failed to create transport socket: provided bundle name does not exist in trust bundle map: %s", peerName) - } - cfg.TrustDomains = append(cfg.TrustDomains, &envoy_tls_v3.SPIFFECertValidatorConfig_TrustDomain{ - Name: tb.TrustDomain, - TrustBundle: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: RootPEMsAsString(tb.Roots), - }, - }, - }) - } - // Sort the trust domains so the output is stable. - sortTrustDomains(cfg.TrustDomains) - - spiffeConfig, err := anypb.New(cfg) - if err != nil { - return nil, err - } - commonTLSContext.ValidationContextType = &envoy_tls_v3.CommonTlsContext_ValidationContext{ - ValidationContext: &envoy_tls_v3.CertificateValidationContext{ - CustomValidatorConfig: &envoy_core_v3.TypedExtensionConfig{ - // The typed config name is hard-coded because it is not available as a wellknown var in the control plane lib. - Name: "envoy.tls.cert_validator.spiffe", - TypedConfig: spiffeConfig, - }, - }, - } - } - // Always require client certificate - downstreamContext.RequireClientCertificate = &wrapperspb.BoolValue{Value: true} - transportSocket, err := makeTransportSocket("tls", downstreamContext) - if err != nil { - return nil, err - } - return transportSocket, nil - case *pbproxystate.TransportSocket_InboundNonMesh: - downstreamContext := &envoy_tls_v3.DownstreamTlsContext{} - downstreamContext.CommonTlsContext = commonTLSContext - // Set TLS Parameters. - if pr.proxyState.Tls != nil { - tlsParams := pr.makeEnvoyTLSParameters(pr.proxyState.Tls.InboundTlsParameters, ts.TlsParameters) - commonTLSContext.TlsParams = tlsParams - } else { - commonTLSContext.TlsParams = &envoy_tls_v3.TlsParameters{} - } - // For non-mesh, we don't care about validation context as currently we don't support mTLS for non-mesh connections. - nonMeshTLS := ts.ConnectionTls.(*pbproxystate.TransportSocket_InboundNonMesh).InboundNonMesh - err := pr.addNonMeshCertConfig(commonTLSContext, nonMeshTLS) - if err != nil { - return nil, fmt.Errorf("failed to create transport socket: %w", err) - } - transportSocket, err := makeTransportSocket("tls", downstreamContext) - if err != nil { - return nil, err - } - return transportSocket, nil - case *pbproxystate.TransportSocket_OutboundMesh: - upstreamContext := &envoy_tls_v3.UpstreamTlsContext{} - upstreamContext.CommonTlsContext = commonTLSContext - // Set TLS Parameters. - if pr.proxyState.Tls != nil { - tlsParams := pr.makeEnvoyTLSParameters(pr.proxyState.Tls.OutboundTlsParameters, ts.TlsParameters) - commonTLSContext.TlsParams = tlsParams - } else { - commonTLSContext.TlsParams = &envoy_tls_v3.TlsParameters{} - } - // For outbound mesh, we need to insert the mesh identity certificate - // and the validation context for the mesh depending on the provided trust bundle names. - om := ts.GetOutboundMesh() - leaf, ok := pr.proxyState.LeafCertificates[om.IdentityKey] - if !ok { - return nil, fmt.Errorf("leaf %s not found in proxyState", om.IdentityKey) - } - err := pr.makeEnvoyCertConfig(commonTLSContext, leaf) - if err != nil { - return nil, fmt.Errorf("failed to create transport socket: %w", err) - } - - // Create validation context - peerName := om.ValidationContext.TrustBundlePeerNameKey - tb, ok := pr.proxyState.TrustBundles[peerName] - if !ok { - return nil, fmt.Errorf("failed to create transport socket: provided peer name does not exist in trust bundle map: %s", peerName) - } - - var matchers []*envoy_matcher_v3.StringMatcher - if len(om.ValidationContext.SpiffeIds) > 0 { - matchers = make([]*envoy_matcher_v3.StringMatcher, 0) - for _, m := range om.ValidationContext.SpiffeIds { - matchers = append(matchers, &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{ - Exact: m, - }, - }) - } - } - commonTLSContext.ValidationContextType = &envoy_tls_v3.CommonTlsContext_ValidationContext{ - ValidationContext: &envoy_tls_v3.CertificateValidationContext{ - // TODO(banks): later for L7 support we may need to configure ALPN here. - TrustedCa: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: RootPEMsAsString(tb.Roots), - }, - }, - MatchSubjectAltNames: matchers, - }, - } - - upstreamContext.Sni = om.Sni - transportSocket, err := makeTransportSocket("tls", upstreamContext) - if err != nil { - return nil, err - } - return transportSocket, nil - default: - return nil, nil - } - -} - -func (pr *ProxyResources) makeEnvoyCertConfig(common *envoy_tls_v3.CommonTlsContext, certificate *pbproxystate.LeafCertificate) error { - if certificate == nil { - return fmt.Errorf("no leaf certificate provided") - } - common.TlsCertificates = []*envoy_tls_v3.TlsCertificate{ - { - CertificateChain: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: lib.EnsureTrailingNewline(certificate.Cert), - }, - }, - PrivateKey: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: lib.EnsureTrailingNewline(certificate.Key), - }, - }, - }, - } - return nil -} - -func (pr *ProxyResources) makeEnvoySDSCertConfig(common *envoy_tls_v3.CommonTlsContext, certificate *pbproxystate.SDSCertificate) error { - if certificate == nil { - return fmt.Errorf("no SDS certificate provided") - } - common.TlsCertificateSdsSecretConfigs = []*envoy_tls_v3.SdsSecretConfig{ - { - Name: certificate.CertResource, - SdsConfig: &envoy_core_v3.ConfigSource{ - ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_core_v3.ApiConfigSource{ - ApiType: envoy_core_v3.ApiConfigSource_GRPC, - TransportApiVersion: envoy_core_v3.ApiVersion_V3, - // Note ClusterNames can't be set here - that's only for REST type - // we need a full GRPC config instead. - GrpcServices: []*envoy_core_v3.GrpcService{ - { - TargetSpecifier: &envoy_core_v3.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_core_v3.GrpcService_EnvoyGrpc{ - ClusterName: certificate.ClusterName, - }, - }, - Timeout: &durationpb.Duration{Seconds: 5}, - }, - }, - }, - }, - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, - }, - }, - } - return nil -} - -func (pr *ProxyResources) addNonMeshCertConfig(common *envoy_tls_v3.CommonTlsContext, tls *pbproxystate.InboundNonMeshTLS) error { - if tls == nil { - return fmt.Errorf("no inbound non-mesh TLS provided") - } - - switch tls.Identity.(type) { - case *pbproxystate.InboundNonMeshTLS_LeafKey: - leafKey := tls.Identity.(*pbproxystate.InboundNonMeshTLS_LeafKey).LeafKey - leaf, ok := pr.proxyState.LeafCertificates[leafKey] - if !ok { - return fmt.Errorf("leaf key %s not found in leaf certificate map", leafKey) - } - common.TlsCertificates = []*envoy_tls_v3.TlsCertificate{ - { - CertificateChain: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: lib.EnsureTrailingNewline(leaf.Cert), - }, - }, - PrivateKey: &envoy_core_v3.DataSource{ - Specifier: &envoy_core_v3.DataSource_InlineString{ - InlineString: lib.EnsureTrailingNewline(leaf.Key), - }, - }, - }, - } - case *pbproxystate.InboundNonMeshTLS_Sds: - c := tls.Identity.(*pbproxystate.InboundNonMeshTLS_Sds).Sds - common.TlsCertificateSdsSecretConfigs = []*envoy_tls_v3.SdsSecretConfig{ - { - Name: c.CertResource, - SdsConfig: &envoy_core_v3.ConfigSource{ - ConfigSourceSpecifier: &envoy_core_v3.ConfigSource_ApiConfigSource{ - ApiConfigSource: &envoy_core_v3.ApiConfigSource{ - ApiType: envoy_core_v3.ApiConfigSource_GRPC, - TransportApiVersion: envoy_core_v3.ApiVersion_V3, - // Note ClusterNames can't be set here - that's only for REST type - // we need a full GRPC config instead. - GrpcServices: []*envoy_core_v3.GrpcService{ - { - TargetSpecifier: &envoy_core_v3.GrpcService_EnvoyGrpc_{ - EnvoyGrpc: &envoy_core_v3.GrpcService_EnvoyGrpc{ - ClusterName: c.ClusterName, - }, - }, - Timeout: &durationpb.Duration{Seconds: 5}, - }, - }, - }, - }, - ResourceApiVersion: envoy_core_v3.ApiVersion_V3, - }, - }, - } - } - - return nil -} - -func makeTransportSocket(name string, config proto.Message) (*envoy_core_v3.TransportSocket, error) { - any, err := anypb.New(config) - if err != nil { - return nil, err - } - return &envoy_core_v3.TransportSocket{ - Name: name, - ConfigType: &envoy_core_v3.TransportSocket_TypedConfig{ - TypedConfig: any, - }, - }, nil -} - -func makeEnvoyListenerFilter(c pbproxystate.Capability) (*envoy_listener_v3.ListenerFilter, error) { - var lf proto.Message - var name string - - switch c { - case pbproxystate.Capability_CAPABILITY_TRANSPARENT: - lf = &envoy_original_dst_v3.OriginalDst{} - name = envoyOriginalDestinationListenerFilterName - case pbproxystate.Capability_CAPABILITY_L4_TLS_INSPECTION: - name = envoyTLSInspectorListenerFilterName - lf = &envoy_tls_inspector_v3.TlsInspector{} - case pbproxystate.Capability_CAPABILITY_L7_PROTOCOL_INSPECTION: - name = envoyHttpInspectorListenerFilterName - lf = &envoy_extensions_filters_listener_http_inspector_v3.HttpInspector{} - default: - return nil, fmt.Errorf("unsupported listener captability: %s", c) - } - lfAsAny, err := anypb.New(lf) - if err != nil { - return nil, err - } - - return &envoy_listener_v3.ListenerFilter{ - Name: name, - ConfigType: &envoy_listener_v3.ListenerFilter_TypedConfig{TypedConfig: lfAsAny}, - }, nil -} - -func makeEnvoyFilter(name string, cfg proto.Message) (*envoy_listener_v3.Filter, error) { - any, err := anypb.New(cfg) - if err != nil { - return nil, err - } - - return &envoy_listener_v3.Filter{ - Name: name, - ConfigType: &envoy_listener_v3.Filter_TypedConfig{TypedConfig: any}, - }, nil -} - -func makeEnvoyHTTPFilter(name string, cfg proto.Message) (*envoy_http_v3.HttpFilter, error) { - any, err := anypb.New(cfg) - if err != nil { - return nil, err - } - - return &envoy_http_v3.HttpFilter{ - Name: name, - ConfigType: &envoy_http_v3.HttpFilter_TypedConfig{TypedConfig: any}, - }, nil -} - -func RootPEMsAsString(rootPEMs []string) string { - var rootPEMsString string - for _, root := range rootPEMs { - rootPEMsString += lib.EnsureTrailingNewline(root) - } - return rootPEMsString -} - -func marshalEnvoyTLSCipherSuiteStrings(cipherSuites []pbproxystate.TLSCipherSuite) []string { - envoyTLSCipherSuiteStrings := map[pbproxystate.TLSCipherSuite]string{ - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256: "ECDHE-ECDSA-AES128-GCM-SHA256", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305: "ECDHE-ECDSA-CHACHA20-POLY1305", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256: "ECDHE-RSA-AES128-GCM-SHA256", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305: "ECDHE-RSA-CHACHA20-POLY1305", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA: "ECDHE-ECDSA-AES128-SHA", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA: "ECDHE-RSA-AES128-SHA", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES128_GCM_SHA256: "AES128-GCM-SHA256", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES128_SHA: "AES128-SHA", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384: "ECDHE-ECDSA-AES256-GCM-SHA384", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384: "ECDHE-RSA-AES256-GCM-SHA384", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA: "ECDHE-ECDSA-AES256-SHA", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA: "ECDHE-RSA-AES256-SHA", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES256_GCM_SHA384: "AES256-GCM-SHA384", - pbproxystate.TLSCipherSuite_TLS_CIPHER_SUITE_AES256_SHA: "AES256-SHA", - } - - var cipherSuiteStrings []string - - for _, c := range cipherSuites { - if s, ok := envoyTLSCipherSuiteStrings[c]; ok { - cipherSuiteStrings = append(cipherSuiteStrings, s) - } - } - - return cipherSuiteStrings -} - -var envoyTLSVersions = map[pbproxystate.TLSVersion]envoy_tls_v3.TlsParameters_TlsProtocol{ - pbproxystate.TLSVersion_TLS_VERSION_AUTO: envoy_tls_v3.TlsParameters_TLS_AUTO, - pbproxystate.TLSVersion_TLS_VERSION_1_0: envoy_tls_v3.TlsParameters_TLSv1_0, - pbproxystate.TLSVersion_TLS_VERSION_1_1: envoy_tls_v3.TlsParameters_TLSv1_1, - pbproxystate.TLSVersion_TLS_VERSION_1_2: envoy_tls_v3.TlsParameters_TLSv1_2, - pbproxystate.TLSVersion_TLS_VERSION_1_3: envoy_tls_v3.TlsParameters_TLSv1_3, -} - -var envoyXFCCPolicy = map[pbproxystate.XFCCPolicy]envoy_http_v3.HttpConnectionManager_ForwardClientCertDetails{ - pbproxystate.XFCCPolicy_XFCC_POLICY_SANITIZE: envoy_http_v3.HttpConnectionManager_SANITIZE, - pbproxystate.XFCCPolicy_XFCC_POLICY_FORWARD_ONLY: envoy_http_v3.HttpConnectionManager_FORWARD_ONLY, - pbproxystate.XFCCPolicy_XFCC_POLICY_APPEND_FORWARD: envoy_http_v3.HttpConnectionManager_APPEND_FORWARD, - pbproxystate.XFCCPolicy_XFCC_POLICY_SANITIZE_SET: envoy_http_v3.HttpConnectionManager_SANITIZE_SET, - pbproxystate.XFCCPolicy_XFCC_POLICY_ALWAYS_FORWARD_ONLY: envoy_http_v3.HttpConnectionManager_ALWAYS_FORWARD_ONLY, -} - -// Sort the trust domains so that the output is stable. -// This benefits tests but also prevents Envoy from mistakenly thinking the listener -// changed and needs to be drained only because this ordering is different. -func sortTrustDomains(trustDomains []*envoy_tls_v3.SPIFFECertValidatorConfig_TrustDomain) { - sort.Slice(trustDomains, func(i int, j int) bool { - return trustDomains[i].Name < trustDomains[j].Name - }) -} - -// sortRouters stable sorts routers with a Match to avoid draining if the list is provided out of order. -// xdsv1 used to sort the filter chains on outbound listeners, so this adds that functionality by sorting routers with matches. -func sortRouters(routers []*pbproxystate.Router) { - if routers == nil { - return - } - sort.SliceStable(routers, func(i, j int) bool { - si := "" - sj := "" - if routers[i].Match != nil { - if len(routers[i].Match.PrefixRanges) > 0 { - si += routers[i].Match.PrefixRanges[0].AddressPrefix + - "/" + routers[i].Match.PrefixRanges[0].PrefixLen.String() + - ":" + routers[i].Match.DestinationPort.String() - } - if len(routers[i].Match.ServerNames) > 0 { - si += routers[i].Match.ServerNames[0] + - ":" + routers[i].Match.DestinationPort.String() - } else { - si += routers[i].Match.DestinationPort.String() - } - } - - if routers[j].Match != nil { - if len(routers[j].Match.PrefixRanges) > 0 { - sj += routers[j].Match.PrefixRanges[0].AddressPrefix + - "/" + routers[j].Match.PrefixRanges[0].PrefixLen.String() + - ":" + routers[j].Match.DestinationPort.String() - } - if len(routers[j].Match.ServerNames) > 0 { - sj += routers[j].Match.ServerNames[0] + - ":" + routers[j].Match.DestinationPort.String() - } else { - sj += routers[j].Match.DestinationPort.String() - } - } - - return si < sj - }) -} - -func sortPrefixRanges(prefixRanges []*pbproxystate.CidrRange) { - if prefixRanges == nil { - return - } - sort.SliceStable(prefixRanges, func(i, j int) bool { - return prefixRanges[i].AddressPrefix < prefixRanges[j].AddressPrefix - }) -} - -const ( - anyPath = `[^/]+` - trustDomain = anyPath + "." + anyPath -) - -// downstreamServiceIdentityMatcher needs to match XFCC headers in two cases: -// 1. Requests to cluster peered services through a mesh gateway. In this case, the XFCC header looks like the following (I added a new line after each ; for readability) -// By=spiffe://950df996-caef-ddef-ec5f-8d18a153b7b2.consul/gateway/mesh/dc/alpha; -// Hash=...; -// Cert=...; -// Chain=...; -// Subject=""; -// URI=spiffe://c7e1d24a-eed8-10a3-286a-52bdb6b6a6fd.consul/ns/default/dc/primary/svc/s1,By=spiffe://950df996-caef-ddef-ec5f-8d18a153b7b2.consul/ns/default/dc/alpha/svc/s2; -// Hash=...; -// Cert=...; -// Chain=...; -// Subject=""; -// URI=spiffe://950df996-caef-ddef-ec5f-8d18a153b7b2.consul/gateway/mesh/dc/alpha -// -// 2. Requests directly to another service -// By=spiffe://ae9dbea8-c1dd-7356-b211-c564f7917100.consul/ns/default/dc/primary/svc/s2; -// Hash=396218588ebc1655d32a49b68cedd6b66b9de7b3d69d0c0451bc5818132377d0; -// Cert=...; -// Chain=...; -// Subject=""; -// URI=spiffe://ae9dbea8-c1dd-7356-b211-c564f7917100.consul/ns/default/dc/primary/svc/s1 -// -// In either case, the regex matches the downstream service's spiffe id because mesh gateways use a different spiffe id format. -// Envoy requires us to include the trailing and leading .* to properly extract the properly submatch. -const downstreamServiceIdentityMatcher = ".*URI=spiffe://(" + trustDomain + - ")(?:/ap/(" + anyPath + - "))?/ns/(" + anyPath + - ")/dc/(" + anyPath + - ")/svc/([^/;,]+).*" - -func parseXFCCToDynamicMetaHTTPFilter() (*envoy_http_v3.HttpFilter, error) { - var rules []*envoy_http_header_to_meta_v3.Config_Rule - - fields := []struct { - name string - sub string - }{ - { - name: "trust-domain", - sub: `\1`, - }, - { - name: "partition", - sub: `\2`, - }, - { - name: "namespace", - sub: `\3`, - }, - { - name: "datacenter", - sub: `\4`, - }, - { - name: "service", - sub: `\5`, - }, - } - - for _, f := range fields { - rules = append(rules, &envoy_http_header_to_meta_v3.Config_Rule{ - Header: "x-forwarded-client-cert", - OnHeaderPresent: &envoy_http_header_to_meta_v3.Config_KeyValuePair{ - MetadataNamespace: "consul", - Key: f.name, - RegexValueRewrite: &envoy_matcher_v3.RegexMatchAndSubstitute{ - Pattern: &envoy_matcher_v3.RegexMatcher{ - Regex: downstreamServiceIdentityMatcher, - EngineType: &envoy_matcher_v3.RegexMatcher_GoogleRe2{ - GoogleRe2: &envoy_matcher_v3.RegexMatcher_GoogleRE2{}, - }, - }, - Substitution: f.sub, - }, - }, - }) - } - - cfg := &envoy_http_header_to_meta_v3.Config{RequestRules: rules} - - return makeEnvoyHTTPFilter("envoy.filters.http.header_to_metadata", cfg) -} diff --git a/agent/xdsv2/rbac_resources.go b/agent/xdsv2/rbac_resources.go deleted file mode 100644 index df670782ce43..000000000000 --- a/agent/xdsv2/rbac_resources.go +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xdsv2 - -import ( - "fmt" - - envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" - envoy_rbac_v3 "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3" - envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" - envoy_http_rbac_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/rbac/v3" - envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - envoy_network_rbac_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/rbac/v3" - envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" - - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" -) - -const ( - baseL4PermissionKey = "consul-intentions-layer4" -) - -// MakeL4RBAC returns the envoy deny and allow rules from the traffic permissions. After calling this function these -// rules can be put into a network rbac filter or http rbac filter depending on the local app port protocol. -func MakeL4RBAC(trafficPermissions *pbproxystate.TrafficPermissions) (deny *envoy_rbac_v3.RBAC, allow *envoy_rbac_v3.RBAC, err error) { - var denyRBAC *envoy_rbac_v3.RBAC - var allowRBAC *envoy_rbac_v3.RBAC - - if trafficPermissions == nil { - return nil, nil, nil - } - - if len(trafficPermissions.DenyPermissions) > 0 { - denyRBAC = &envoy_rbac_v3.RBAC{ - Action: envoy_rbac_v3.RBAC_DENY, - Policies: make(map[string]*envoy_rbac_v3.Policy), - } - denyRBAC.Policies = makeRBACPolicies(trafficPermissions.DenyPermissions) - } - - // Only include the allow RBAC when Consul is in default deny. - if !trafficPermissions.DefaultAllow { - allowRBAC = &envoy_rbac_v3.RBAC{ - Action: envoy_rbac_v3.RBAC_ALLOW, - Policies: make(map[string]*envoy_rbac_v3.Policy), - } - - allowRBAC.Policies = makeRBACPolicies(trafficPermissions.AllowPermissions) - } - - return denyRBAC, allowRBAC, nil -} - -// MakeRBACNetworkFilters calls MakeL4RBAC and wraps the result in envoy network filters meant for L4 protocols. -func MakeRBACNetworkFilters(trafficPermissions *pbproxystate.TrafficPermissions) ([]*envoy_listener_v3.Filter, error) { - var filters []*envoy_listener_v3.Filter - - deny, allow, err := MakeL4RBAC(trafficPermissions) - if err != nil { - return nil, err - } - - if deny != nil { - filter, err := makeRBACFilter(deny) - if err != nil { - return nil, err - } - filters = append(filters, filter) - } - - if allow != nil { - filter, err := makeRBACFilter(allow) - if err != nil { - return nil, err - } - filters = append(filters, filter) - - } - - return filters, nil -} - -// MakeRBACHTTPFilters calls MakeL4RBAC and wraps the result in envoy http filters meant for L7 protocols. Eventually -// this will need to also accumulate any L7 traffic permissions when that is implemented. -func MakeRBACHTTPFilters(trafficPermissions *pbproxystate.TrafficPermissions) ([]*envoy_http_v3.HttpFilter, error) { - var httpFilters []*envoy_http_v3.HttpFilter - - deny, allow, err := MakeL4RBAC(trafficPermissions) - if err != nil { - return nil, err - } - - if deny != nil { - filter, err := makeRBACHTTPFilter(deny) - if err != nil { - return nil, err - } - httpFilters = append(httpFilters, filter) - } - - if allow != nil { - filter, err := makeRBACHTTPFilter(allow) - if err != nil { - return nil, err - } - httpFilters = append(httpFilters, filter) - - } - - return httpFilters, nil -} - -const ( - envoyNetworkRBACFilterKey = "envoy.filters.network.rbac" - envoyHTTPRBACFilterKey = "envoy.filters.http.rbac" -) - -func makeRBACFilter(rbac *envoy_rbac_v3.RBAC) (*envoy_listener_v3.Filter, error) { - cfg := &envoy_network_rbac_v3.RBAC{ - StatPrefix: "connect_authz", - Rules: rbac, - } - return makeEnvoyFilter(envoyNetworkRBACFilterKey, cfg) -} - -func makeRBACHTTPFilter(rbac *envoy_rbac_v3.RBAC) (*envoy_http_v3.HttpFilter, error) { - cfg := &envoy_http_rbac_v3.RBAC{ - Rules: rbac, - } - return makeEnvoyHTTPFilter(envoyHTTPRBACFilterKey, cfg) -} - -func makeRBACPolicies(l4Permissions []*pbproxystate.Permission) map[string]*envoy_rbac_v3.Policy { - policyLabel := func(i int) string { - if len(l4Permissions) == 1 { - return baseL4PermissionKey - } - return fmt.Sprintf("%s-%d", baseL4PermissionKey, i) - } - - policies := make(map[string]*envoy_rbac_v3.Policy, len(l4Permissions)) - - for i, permission := range l4Permissions { - policy := makeRBACPolicy(permission) - if policy != nil { - policies[policyLabel(i)] = policy - } - } - - return policies -} - -func makeRBACPolicy(p *pbproxystate.Permission) *envoy_rbac_v3.Policy { - if len(p.Principals) == 0 { - return nil - } - - var principals []*envoy_rbac_v3.Principal - - for _, p := range p.Principals { - principals = append(principals, toEnvoyPrincipal(p)) - } - - return &envoy_rbac_v3.Policy{ - Principals: principals, - Permissions: []*envoy_rbac_v3.Permission{anyPermission()}, - } -} - -func toEnvoyPrincipal(p *pbproxystate.Principal) *envoy_rbac_v3.Principal { - includePrincipal := principal(p.Spiffe) - - if len(p.ExcludeSpiffes) == 0 { - return includePrincipal - } - - principals := make([]*envoy_rbac_v3.Principal, 0, len(p.ExcludeSpiffes)+1) - principals = append(principals, includePrincipal) - for _, s := range p.ExcludeSpiffes { - principals = append(principals, negatePrincipal(principal(s))) - } - return andPrincipals(principals) -} - -func principal(spiffe *pbproxystate.Spiffe) *envoy_rbac_v3.Principal { - var andIDs []*envoy_rbac_v3.Principal - andIDs = append(andIDs, idPrincipal(spiffe.Regex)) - - if len(spiffe.XfccRegex) > 0 { - andIDs = append(andIDs, xfccPrincipal(spiffe.XfccRegex)) - } - - return andPrincipals(andIDs) -} - -func negatePrincipal(p *envoy_rbac_v3.Principal) *envoy_rbac_v3.Principal { - return &envoy_rbac_v3.Principal{ - Identifier: &envoy_rbac_v3.Principal_NotId{ - NotId: p, - }, - } -} - -func idPrincipal(spiffeID string) *envoy_rbac_v3.Principal { - return &envoy_rbac_v3.Principal{ - Identifier: &envoy_rbac_v3.Principal_Authenticated_{ - Authenticated: &envoy_rbac_v3.Principal_Authenticated{ - PrincipalName: &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ - SafeRegex: response.MakeEnvoyRegexMatch(spiffeID), - }, - }, - }, - }, - } -} - -func andPrincipals(ids []*envoy_rbac_v3.Principal) *envoy_rbac_v3.Principal { - switch len(ids) { - case 1: - return ids[0] - default: - return &envoy_rbac_v3.Principal{ - Identifier: &envoy_rbac_v3.Principal_AndIds{ - AndIds: &envoy_rbac_v3.Principal_Set{ - Ids: ids, - }, - }, - } - } -} - -func xfccPrincipal(spiffeID string) *envoy_rbac_v3.Principal { - return &envoy_rbac_v3.Principal{ - Identifier: &envoy_rbac_v3.Principal_Header{ - Header: &envoy_route_v3.HeaderMatcher{ - Name: "x-forwarded-client-cert", - HeaderMatchSpecifier: &envoy_route_v3.HeaderMatcher_StringMatch{ - StringMatch: &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ - SafeRegex: response.MakeEnvoyRegexMatch(spiffeID), - }, - }, - }, - }, - }, - } -} - -func anyPermission() *envoy_rbac_v3.Permission { - return &envoy_rbac_v3.Permission{ - Rule: &envoy_rbac_v3.Permission_Any{Any: true}, - } -} diff --git a/agent/xdsv2/resources.go b/agent/xdsv2/resources.go deleted file mode 100644 index 1c3251930ceb..000000000000 --- a/agent/xdsv2/resources.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xdsv2 - -import ( - "fmt" - - "github.com/hashicorp/go-hclog" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/envoyextensions/xdscommon" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" -) - -// ResourceGenerator is associated with a single gRPC stream and creates xDS -// resources for a single client. -type ResourceGenerator struct { - Logger hclog.Logger - ProxyFeatures xdscommon.SupportedProxyFeatures -} - -// NewResourceGenerator will create a new ResourceGenerator. -func NewResourceGenerator( - logger hclog.Logger, -) *ResourceGenerator { - return &ResourceGenerator{ - Logger: logger, - } -} - -// ProxyResources is the main state used to convert proxyState resources to Envoy resources. -type ProxyResources struct { - // proxyState is the final proxyState computed by Consul controllers. - proxyState *proxytracker.ProxyState - // envoyResources is a map of each resource type (listener, endpoint, route, cluster, etc.) - // with a corresponding map of k/v pairs of resource name to envoy proto message. - // map[string]map[string]proto.Message is used over map[string][]proto.Message because - // AllResourcesFromIR() will create envoy resource by walking the object graph from listener - // to endpoint. In the process, the same resource might be referenced more than once, - // so the map is used to prevent duplicate resources being created and also will use - // an O(1) lookup to see if it exists (it actually will set the map key rather than - // checks everywhere) where as each lookup would be O(n) with a []proto structure. - envoyResources map[string]map[string]proto.Message -} - -func (g *ResourceGenerator) AllResourcesFromIR(proxyState *proxytracker.ProxyState) (map[string][]proto.Message, error) { - pr := &ProxyResources{ - proxyState: proxyState, - envoyResources: make(map[string]map[string]proto.Message), - } - pr.envoyResources[xdscommon.ListenerType] = make(map[string]proto.Message) - pr.envoyResources[xdscommon.RouteType] = make(map[string]proto.Message) - pr.envoyResources[xdscommon.ClusterType] = make(map[string]proto.Message) - pr.envoyResources[xdscommon.EndpointType] = make(map[string]proto.Message) - - err := pr.makeEnvoyResourceGraphsStartingFromListeners() - if err != nil { - return nil, fmt.Errorf("failed to generate xDS resources for ProxyState: %v", err) - } - - // Now account for Clusters that did not have a destination. - for name := range proxyState.Clusters { - if _, ok := pr.envoyResources[xdscommon.ClusterType][name]; !ok { - pr.addEnvoyClustersAndEndpointsToEnvoyResources(name) - } - } - - envoyResources := convertResourceMapsToResourceArrays(pr.envoyResources) - return envoyResources, nil -} - -// convertResourceMapsToResourceArrays will convert map[string]map[string]proto.Message, which is used to -// prevent duplicate resource being created, to map[string][]proto.Message which is used by Delta server. -func convertResourceMapsToResourceArrays(resourceMap map[string]map[string]proto.Message) map[string][]proto.Message { - resources := make(map[string][]proto.Message) - resources[xdscommon.ListenerType] = make([]proto.Message, 0) - resources[xdscommon.RouteType] = make([]proto.Message, 0) - resources[xdscommon.ClusterType] = make([]proto.Message, 0) - resources[xdscommon.EndpointType] = make([]proto.Message, 0) - - // This conversion incurs processing cost which is done once in the generating envoy resources. - // This tradeoff is preferable to doing array scan every time an envoy resource needs to be - // to pr.envoyResource to see if it already exists. - for resourceTypeName, resourceMap := range resourceMap { - for _, resource := range resourceMap { - resources[resourceTypeName] = append(resources[resourceTypeName], resource) - } - } - return resources -} diff --git a/agent/xdsv2/resources_test.go b/agent/xdsv2/resources_test.go deleted file mode 100644 index 1210124494e4..000000000000 --- a/agent/xdsv2/resources_test.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xdsv2 - -import ( - "fmt" - envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" - envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" - envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" - "github.com/hashicorp/consul/internal/testing/golden" - "sort" - "testing" - - envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" - envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" - - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" - meshv2beta1 "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/sdk/testutil" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/proto" -) - -var testTypeUrlToPrettyName = map[string]string{ - xdscommon.ListenerType: "listeners", - xdscommon.RouteType: "routes", - xdscommon.ClusterType: "clusters", - xdscommon.EndpointType: "endpoints", - xdscommon.SecretType: "secrets", -} - -// TestAllResourcesFromIR_XDSGoldenFileInputs tests the AllResourcesFromIR() by -// using the golden test output/expected files from the XDS controller tests as -// inputs to the XDSV2 resources generation. -func TestAllResourcesFromIR_XDSGoldenFileInputs(t *testing.T) { - inputPath := "../../internal/mesh/internal/controllers/xds" - - cases := []string{ - // destinations - please add in alphabetical order - "destination/l4-single-destination-ip-port-bind-address", - "destination/l4-single-destination-unix-socket-bind-address", - "destination/l4-single-implicit-destination-tproxy", - "destination/l4-multi-destination", - "destination/l4-multiple-implicit-destinations-tproxy", - "destination/l4-implicit-and-explicit-destinations-tproxy", - "destination/mixed-multi-destination", - "destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy", - "destination/multiport-l4-and-l7-single-implicit-destination-tproxy", - "destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy", - - //sources - please add in alphabetical order - "source/l7-expose-paths", - "source/local-and-inbound-connections", - "source/multiple-workload-addresses-with-specific-ports", - "source/multiple-workload-addresses-without-ports", - "source/multiport-l4-multiple-workload-addresses-with-specific-ports", - "source/multiport-l4-multiple-workload-addresses-without-ports", - "source/multiport-l4-workload-with-only-mesh-port", - "source/multiport-l7-multiple-workload-addresses-with-specific-ports", - "source/multiport-l7-multiple-workload-addresses-without-ports", - "source/single-workload-address-without-ports", - } - - for _, name := range cases { - t.Run(name, func(t *testing.T) { - // Arrange - paths to input and output golden files. - testFile := fmt.Sprintf("%s.golden", name) - inputFilePath := fmt.Sprintf("%s/testdata/%s", inputPath, testFile) - inputValueInput := golden.GetBytesAtFilePath(t, inputFilePath) - - // Act. - ps := jsonToProxyState(t, inputValueInput) - generator := NewResourceGenerator(testutil.Logger(t)) - resources, err := generator.AllResourcesFromIR(&proxytracker.ProxyState{ProxyState: ps}) - require.NoError(t, err) - - // Assert. - // Assert all resources were generated. - typeUrls := []string{ - xdscommon.ListenerType, - xdscommon.RouteType, - xdscommon.ClusterType, - xdscommon.EndpointType, - // TODO(proxystate): add in future - //xdscommon.SecretType, - } - require.Len(t, resources, len(typeUrls)) - - // Assert each resource type has actual XDS matching expected XDS. - for _, typeUrl := range typeUrls { - prettyName := testTypeUrlToPrettyName[typeUrl] - t.Run(prettyName, func(t *testing.T) { - items, ok := resources[typeUrl] - require.True(t, ok) - - // sort resources so they don't show up as flakey tests as - // ordering in JSON is not guaranteed. - sort.Slice(items, func(i, j int) bool { - switch typeUrl { - case xdscommon.ListenerType: - return items[i].(*envoy_listener_v3.Listener).Name < items[j].(*envoy_listener_v3.Listener).Name - case xdscommon.RouteType: - return items[i].(*envoy_route_v3.RouteConfiguration).Name < items[j].(*envoy_route_v3.RouteConfiguration).Name - case xdscommon.ClusterType: - return items[i].(*envoy_cluster_v3.Cluster).Name < items[j].(*envoy_cluster_v3.Cluster).Name - case xdscommon.EndpointType: - return items[i].(*envoy_endpoint_v3.ClusterLoadAssignment).ClusterName < items[j].(*envoy_endpoint_v3.ClusterLoadAssignment).ClusterName - case xdscommon.SecretType: - return items[i].(*envoy_tls_v3.Secret).Name < items[j].(*envoy_tls_v3.Secret).Name - default: - panic("not possible") - } - }) - - // Compare actual to expected. - resp, err := response.CreateResponse(typeUrl, "00000001", "00000001", items) - require.NoError(t, err) - gotJSON := protoToJSON(t, resp) - - expectedJSON := golden.Get(t, gotJSON, fmt.Sprintf("%s/%s", prettyName, testFile)) - require.JSONEq(t, expectedJSON, gotJSON) - }) - } - }) - } -} - -func protoToJSON(t *testing.T, pb proto.Message) string { - t.Helper() - m := protojson.MarshalOptions{ - Indent: " ", - } - gotJSON, err := m.Marshal(pb) - require.NoError(t, err) - return string(gotJSON) -} - -func jsonToProxyState(t *testing.T, json []byte) *meshv2beta1.ProxyState { - t.Helper() - um := protojson.UnmarshalOptions{} - ps := &meshv2beta1.ProxyState{} - err := um.Unmarshal(json, ps) - require.NoError(t, err) - return ps -} diff --git a/agent/xdsv2/route_resources.go b/agent/xdsv2/route_resources.go deleted file mode 100644 index d2306fd43638..000000000000 --- a/agent/xdsv2/route_resources.go +++ /dev/null @@ -1,550 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xdsv2 - -import ( - "fmt" - "strings" - - envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" - envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" - "google.golang.org/protobuf/types/known/wrapperspb" - - "github.com/hashicorp/consul/agent/xds/response" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - - envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" -) - -func (pr *ProxyResources) makeEnvoyRoute(name string) (*envoy_route_v3.RouteConfiguration, error) { - var route *envoy_route_v3.RouteConfiguration - // TODO(proxystate): This will make routes in the future. This function should distinguish between static routes - // inlined into listeners and non-static routes that should be added as top level Envoy resources. - _, ok := pr.proxyState.Routes[name] - if !ok { - // This should not happen with a valid proxy state. - return nil, fmt.Errorf("could not find route in ProxyState: %s", name) - } - return route, nil -} - -// makeEnvoyRouteConfigFromProxystateRoute converts the proxystate representation of a Route into Envoy proto message -// form. We don't throw any errors here, since the proxystate has already been validated. -func (pr *ProxyResources) makeEnvoyRouteConfigFromProxystateRoute(name string, psRoute *pbproxystate.Route) *envoy_route_v3.RouteConfiguration { - envoyRouteConfig := &envoy_route_v3.RouteConfiguration{ - Name: name, - // ValidateClusters defaults to true when defined statically and false - // when done via RDS. Re-set the reasonable value of true to prevent - // null-routing traffic. - ValidateClusters: response.MakeBoolValue(true), - } - - for _, vh := range psRoute.GetVirtualHosts() { - envoyRouteConfig.VirtualHosts = append(envoyRouteConfig.VirtualHosts, pr.makeEnvoyVHFromProxystateVH(vh)) - } - - return envoyRouteConfig -} - -func (pr *ProxyResources) makeEnvoyVHFromProxystateVH(psVirtualHost *pbproxystate.VirtualHost) *envoy_route_v3.VirtualHost { - envoyVirtualHost := &envoy_route_v3.VirtualHost{ - Name: psVirtualHost.Name, - Domains: psVirtualHost.GetDomains(), - } - - for _, rr := range psVirtualHost.GetRouteRules() { - envoyVirtualHost.Routes = append(envoyVirtualHost.Routes, pr.makeEnvoyRouteFromProxystateRouteRule(rr)) - } - - for _, hm := range psVirtualHost.GetHeaderMutations() { - injectEnvoyVirtualHostWithProxystateHeaderMutation(envoyVirtualHost, hm) - } - - return envoyVirtualHost -} - -func (pr *ProxyResources) makeEnvoyRouteFromProxystateRouteRule(psRouteRule *pbproxystate.RouteRule) *envoy_route_v3.Route { - envoyRouteRule := &envoy_route_v3.Route{ - Match: makeEnvoyRouteMatchFromProxystateRouteMatch(psRouteRule.GetMatch()), - Action: pr.makeEnvoyRouteActionFromProxystateRouteDestination(psRouteRule.GetDestination()), - } - - for _, hm := range psRouteRule.GetHeaderMutations() { - injectEnvoyRouteRuleWithProxystateHeaderMutation(envoyRouteRule, hm) - } - - return envoyRouteRule -} - -func makeEnvoyRouteMatchFromProxystateRouteMatch(psRouteMatch *pbproxystate.RouteMatch) *envoy_route_v3.RouteMatch { - envoyRouteMatch := &envoy_route_v3.RouteMatch{} - - switch psRouteMatch.PathMatch.GetPathMatch().(type) { - case *pbproxystate.PathMatch_Exact: - envoyRouteMatch.PathSpecifier = &envoy_route_v3.RouteMatch_Path{ - Path: psRouteMatch.PathMatch.GetExact(), - } - case *pbproxystate.PathMatch_Prefix: - envoyRouteMatch.PathSpecifier = &envoy_route_v3.RouteMatch_Prefix{ - Prefix: psRouteMatch.PathMatch.GetPrefix(), - } - case *pbproxystate.PathMatch_Regex: - envoyRouteMatch.PathSpecifier = &envoy_route_v3.RouteMatch_SafeRegex{ - SafeRegex: makeEnvoyRegexMatch(psRouteMatch.PathMatch.GetRegex()), - } - default: - // This shouldn't be possible considering the types of PathMatch - return nil - } - - if len(psRouteMatch.GetHeaderMatches()) > 0 { - envoyRouteMatch.Headers = make([]*envoy_route_v3.HeaderMatcher, 0, len(psRouteMatch.GetHeaderMatches())) - } - for _, psHM := range psRouteMatch.GetHeaderMatches() { - envoyRouteMatch.Headers = append(envoyRouteMatch.Headers, makeEnvoyHeaderMatcherFromProxystateHeaderMatch(psHM)) - } - - if len(psRouteMatch.MethodMatches) > 0 { - methodHeaderRegex := strings.Join(psRouteMatch.MethodMatches, "|") - - eh := &envoy_route_v3.HeaderMatcher{ - Name: ":method", - HeaderMatchSpecifier: &envoy_route_v3.HeaderMatcher_SafeRegexMatch{ - SafeRegexMatch: makeEnvoyRegexMatch(methodHeaderRegex), - }, - } - - envoyRouteMatch.Headers = append(envoyRouteMatch.Headers, eh) - } - - if len(psRouteMatch.GetQueryParameterMatches()) > 0 { - envoyRouteMatch.QueryParameters = make([]*envoy_route_v3.QueryParameterMatcher, 0, len(psRouteMatch.GetQueryParameterMatches())) - } - for _, psQM := range psRouteMatch.GetQueryParameterMatches() { - envoyRouteMatch.QueryParameters = append(envoyRouteMatch.QueryParameters, makeEnvoyQueryParamFromProxystateQueryMatch(psQM)) - } - - return envoyRouteMatch -} - -func makeEnvoyRegexMatch(pattern string) *envoy_matcher_v3.RegexMatcher { - return &envoy_matcher_v3.RegexMatcher{ - EngineType: &envoy_matcher_v3.RegexMatcher_GoogleRe2{ - GoogleRe2: &envoy_matcher_v3.RegexMatcher_GoogleRE2{}, - }, - Regex: pattern, - } -} - -func makeEnvoyHeaderMatcherFromProxystateHeaderMatch(psMatch *pbproxystate.HeaderMatch) *envoy_route_v3.HeaderMatcher { - envoyHeaderMatcher := &envoy_route_v3.HeaderMatcher{ - Name: psMatch.Name, - } - - switch psMatch.Match.(type) { - case *pbproxystate.HeaderMatch_Exact: - envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_StringMatch{ - StringMatch: &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{ - Exact: psMatch.GetExact(), - }, - IgnoreCase: false, - }, - } - - case *pbproxystate.HeaderMatch_Regex: - envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_StringMatch{ - StringMatch: &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ - SafeRegex: response.MakeEnvoyRegexMatch(psMatch.GetRegex()), - }, - IgnoreCase: false, - }, - } - - case *pbproxystate.HeaderMatch_Prefix: - envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_StringMatch{ - StringMatch: &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_Prefix{ - Prefix: psMatch.GetPrefix(), - }, - IgnoreCase: false, - }, - } - case *pbproxystate.HeaderMatch_Suffix: - envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_StringMatch{ - StringMatch: &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_Suffix{ - Suffix: psMatch.GetSuffix(), - }, - IgnoreCase: false, - }, - } - - case *pbproxystate.HeaderMatch_Present: - envoyHeaderMatcher.HeaderMatchSpecifier = &envoy_route_v3.HeaderMatcher_PresentMatch{ - PresentMatch: true, - } - default: - // This shouldn't be possible considering the types of HeaderMatch - return nil - } - - if psMatch.GetInvertMatch() { - envoyHeaderMatcher.InvertMatch = true - } - - return envoyHeaderMatcher -} - -func makeEnvoyQueryParamFromProxystateQueryMatch(psMatch *pbproxystate.QueryParameterMatch) *envoy_route_v3.QueryParameterMatcher { - envoyQueryParamMatcher := &envoy_route_v3.QueryParameterMatcher{ - Name: psMatch.Name, - } - - switch psMatch.Match.(type) { - case *pbproxystate.QueryParameterMatch_Exact: - envoyQueryParamMatcher.QueryParameterMatchSpecifier = &envoy_route_v3.QueryParameterMatcher_StringMatch{ - StringMatch: &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{ - Exact: psMatch.GetExact(), - }, - }, - } - - case *pbproxystate.QueryParameterMatch_Regex: - envoyQueryParamMatcher.QueryParameterMatchSpecifier = &envoy_route_v3.QueryParameterMatcher_StringMatch{ - StringMatch: &envoy_matcher_v3.StringMatcher{ - MatchPattern: &envoy_matcher_v3.StringMatcher_SafeRegex{ - SafeRegex: makeEnvoyRegexMatch(psMatch.GetRegex()), - }, - }, - } - case *pbproxystate.QueryParameterMatch_Present: - envoyQueryParamMatcher.QueryParameterMatchSpecifier = &envoy_route_v3.QueryParameterMatcher_PresentMatch{ - PresentMatch: true, - } - default: - // This shouldn't be possible considering the types of QueryMatch - return nil - } - - return envoyQueryParamMatcher -} - -func (pr *ProxyResources) addEnvoyClustersAndEndpointsToEnvoyResources(clusterName string) { - clusters, _ := pr.makeClusters(clusterName) - for name, cluster := range clusters { - pr.envoyResources[xdscommon.ClusterType][name] = cluster - - if name != xdscommon.LocalAppClusterName { - if endpointList, ok := pr.proxyState.Endpoints[name]; ok { - protoEndpoint := makeEnvoyClusterLoadAssignment(name, endpointList.Endpoints) - pr.envoyResources[xdscommon.EndpointType][name] = protoEndpoint - } - } - } -} - -// TODO (dans): Will this always be envoy_route_v3.Route_Route? -// Definitely for connect proxies this is the only option. -func (pr *ProxyResources) makeEnvoyRouteActionFromProxystateRouteDestination(psRouteDestination *pbproxystate.RouteDestination) *envoy_route_v3.Route_Route { - envoyRouteRoute := &envoy_route_v3.Route_Route{ - Route: &envoy_route_v3.RouteAction{}, - } - - switch psRouteDestination.Destination.(type) { - case *pbproxystate.RouteDestination_Cluster: - psCluster := psRouteDestination.GetCluster() - envoyRouteRoute.Route.ClusterSpecifier = &envoy_route_v3.RouteAction_Cluster{ - Cluster: psCluster.GetName(), - } - pr.addEnvoyClustersAndEndpointsToEnvoyResources(psCluster.Name) - - case *pbproxystate.RouteDestination_WeightedClusters: - psWeightedClusters := psRouteDestination.GetWeightedClusters() - envoyClusters := make([]*envoy_route_v3.WeightedCluster_ClusterWeight, 0, len(psWeightedClusters.GetClusters())) - totalWeight := 0 - for _, psCluster := range psWeightedClusters.GetClusters() { - pr.addEnvoyClustersAndEndpointsToEnvoyResources(psCluster.Name) - - totalWeight += int(psCluster.Weight.GetValue()) - envoyClusters = append(envoyClusters, makeEnvoyClusterWeightFromProxystateWeightedCluster(psCluster)) - } - var envoyWeightScale *wrapperspb.UInt32Value - if totalWeight == 10000 { - envoyWeightScale = response.MakeUint32Value(10000) - } - - envoyRouteRoute.Route.ClusterSpecifier = &envoy_route_v3.RouteAction_WeightedClusters{ - WeightedClusters: &envoy_route_v3.WeightedCluster{ - Clusters: envoyClusters, - TotalWeight: envoyWeightScale, - }, - } - default: - // This shouldn't be possible considering the types of Destination - return nil - } - - injectEnvoyRouteActionWithProxystateDestinationConfig(envoyRouteRoute.Route, psRouteDestination.GetDestinationConfiguration()) - - if psRouteDestination.GetDestinationConfiguration() != nil { - config := psRouteDestination.GetDestinationConfiguration() - action := envoyRouteRoute.Route - - action.PrefixRewrite = config.GetPrefixRewrite() - - if config.GetTimeoutConfig().GetTimeout() != nil { - action.Timeout = config.GetTimeoutConfig().GetTimeout() - } - - if config.GetTimeoutConfig().GetTimeout() != nil { - action.Timeout = config.GetTimeoutConfig().GetTimeout() - } - - if config.GetTimeoutConfig().GetIdleTimeout() != nil { - action.IdleTimeout = config.GetTimeoutConfig().GetIdleTimeout() - } - - if config.GetRetryPolicy() != nil { - action.RetryPolicy = makeEnvoyRetryPolicyFromProxystateRetryPolicy(config.GetRetryPolicy()) - } - } - - return envoyRouteRoute -} - -func makeEnvoyClusterWeightFromProxystateWeightedCluster(cluster *pbproxystate.L7WeightedDestinationCluster) *envoy_route_v3.WeightedCluster_ClusterWeight { - envoyClusterWeight := makeEnvoyClusterWeightFromNameAndWeight(cluster.GetName(), cluster.GetWeight()) - - for _, hm := range cluster.GetHeaderMutations() { - injectEnvoyClusterWeightWithProxystateHeaderMutation(envoyClusterWeight, hm) - } - - return envoyClusterWeight -} - -func makeEnvoyClusterWeightFromNameAndWeight(name string, weight *wrapperspb.UInt32Value) *envoy_route_v3.WeightedCluster_ClusterWeight { - envoyClusterWeight := &envoy_route_v3.WeightedCluster_ClusterWeight{ - Name: name, - Weight: weight, - } - - return envoyClusterWeight -} - -func injectEnvoyClusterWeightWithProxystateHeaderMutation(envoyClusterWeight *envoy_route_v3.WeightedCluster_ClusterWeight, mutation *pbproxystate.HeaderMutation) { - mutation.GetAction() - switch mutation.GetAction().(type) { - case *pbproxystate.HeaderMutation_RequestHeaderAdd: - action := mutation.GetRequestHeaderAdd() - header := action.GetHeader() - app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - - hvo := &envoy_core_v3.HeaderValueOption{ - Header: &envoy_core_v3.HeaderValue{ - Key: header.GetKey(), - Value: header.GetValue(), - }, - Append: response.MakeBoolValue(app), - } - envoyClusterWeight.RequestHeadersToAdd = append(envoyClusterWeight.RequestHeadersToAdd, hvo) - - case *pbproxystate.HeaderMutation_RequestHeaderRemove: - action := mutation.GetRequestHeaderRemove() - envoyClusterWeight.RequestHeadersToRemove = append(envoyClusterWeight.RequestHeadersToRemove, action.GetHeaderKeys()...) - - case *pbproxystate.HeaderMutation_ResponseHeaderAdd: - action := mutation.GetResponseHeaderAdd() - header := action.GetHeader() - app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - - hvo := &envoy_core_v3.HeaderValueOption{ - Header: &envoy_core_v3.HeaderValue{ - Key: header.GetKey(), - Value: header.GetValue(), - }, - Append: response.MakeBoolValue(app), - } - envoyClusterWeight.ResponseHeadersToAdd = append(envoyClusterWeight.ResponseHeadersToAdd, hvo) - - case *pbproxystate.HeaderMutation_ResponseHeaderRemove: - action := mutation.GetResponseHeaderRemove() - envoyClusterWeight.ResponseHeadersToRemove = append(envoyClusterWeight.ResponseHeadersToRemove, action.GetHeaderKeys()...) - - default: - // This shouldn't be possible considering the types of Destination - return - } -} - -func injectEnvoyRouteActionWithProxystateDestinationConfig(envoyAction *envoy_route_v3.RouteAction, config *pbproxystate.DestinationConfiguration) { - if config == nil { - return - } - - if len(config.GetHashPolicies()) > 0 { - envoyAction.HashPolicy = make([]*envoy_route_v3.RouteAction_HashPolicy, 0, len(config.GetHashPolicies())) - } - for _, policy := range config.GetHashPolicies() { - envoyPolicy := makeEnvoyHashPolicyFromProxystateLBHashPolicy(policy) - envoyAction.HashPolicy = append(envoyAction.HashPolicy, envoyPolicy) - } - - if config.AutoHostRewrite != nil { - envoyAction.HostRewriteSpecifier = &envoy_route_v3.RouteAction_AutoHostRewrite{ - AutoHostRewrite: config.AutoHostRewrite, - } - } -} - -func makeEnvoyHashPolicyFromProxystateLBHashPolicy(psPolicy *pbproxystate.LoadBalancerHashPolicy) *envoy_route_v3.RouteAction_HashPolicy { - switch psPolicy.GetPolicy().(type) { - case *pbproxystate.LoadBalancerHashPolicy_ConnectionProperties: - return &envoy_route_v3.RouteAction_HashPolicy{ - PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_ConnectionProperties_{ - ConnectionProperties: &envoy_route_v3.RouteAction_HashPolicy_ConnectionProperties{ - SourceIp: true, // always true - }, - }, - Terminal: psPolicy.GetConnectionProperties().GetTerminal(), - } - - case *pbproxystate.LoadBalancerHashPolicy_Header: - return &envoy_route_v3.RouteAction_HashPolicy{ - PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Header_{ - Header: &envoy_route_v3.RouteAction_HashPolicy_Header{ - HeaderName: psPolicy.GetHeader().GetName(), - }, - }, - Terminal: psPolicy.GetHeader().GetTerminal(), - } - - case *pbproxystate.LoadBalancerHashPolicy_Cookie: - cookie := &envoy_route_v3.RouteAction_HashPolicy_Cookie{ - Name: psPolicy.GetCookie().GetName(), - Path: psPolicy.GetCookie().GetPath(), - Ttl: psPolicy.GetCookie().GetTtl(), - } - - return &envoy_route_v3.RouteAction_HashPolicy{ - PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_Cookie_{ - Cookie: cookie, - }, - Terminal: psPolicy.GetCookie().GetTerminal(), - } - - case *pbproxystate.LoadBalancerHashPolicy_QueryParameter: - return &envoy_route_v3.RouteAction_HashPolicy{ - PolicySpecifier: &envoy_route_v3.RouteAction_HashPolicy_QueryParameter_{ - QueryParameter: &envoy_route_v3.RouteAction_HashPolicy_QueryParameter{ - Name: psPolicy.GetQueryParameter().GetName(), - }, - }, - Terminal: psPolicy.GetQueryParameter().GetTerminal(), - } - } - // This shouldn't be possible considering the types of LoadBalancerPolicy - return nil -} - -func makeEnvoyRetryPolicyFromProxystateRetryPolicy(psRetryPolicy *pbproxystate.RetryPolicy) *envoy_route_v3.RetryPolicy { - return &envoy_route_v3.RetryPolicy{ - NumRetries: psRetryPolicy.GetNumRetries(), - RetriableStatusCodes: psRetryPolicy.GetRetriableStatusCodes(), - RetryOn: psRetryPolicy.GetRetryOn(), - } -} - -func injectEnvoyRouteRuleWithProxystateHeaderMutation(envoyRouteRule *envoy_route_v3.Route, mutation *pbproxystate.HeaderMutation) { - mutation.GetAction() - switch mutation.GetAction().(type) { - case *pbproxystate.HeaderMutation_RequestHeaderAdd: - action := mutation.GetRequestHeaderAdd() - header := action.GetHeader() - app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - - hvo := &envoy_core_v3.HeaderValueOption{ - Header: &envoy_core_v3.HeaderValue{ - Key: header.GetKey(), - Value: header.GetValue(), - }, - Append: response.MakeBoolValue(app), - } - envoyRouteRule.RequestHeadersToAdd = append(envoyRouteRule.RequestHeadersToAdd, hvo) - - case *pbproxystate.HeaderMutation_RequestHeaderRemove: - action := mutation.GetRequestHeaderRemove() - envoyRouteRule.RequestHeadersToRemove = append(envoyRouteRule.RequestHeadersToRemove, action.GetHeaderKeys()...) - - case *pbproxystate.HeaderMutation_ResponseHeaderAdd: - action := mutation.GetResponseHeaderAdd() - header := action.GetHeader() - app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - - hvo := &envoy_core_v3.HeaderValueOption{ - Header: &envoy_core_v3.HeaderValue{ - Key: header.GetKey(), - Value: header.GetValue(), - }, - Append: response.MakeBoolValue(app), - } - envoyRouteRule.ResponseHeadersToAdd = append(envoyRouteRule.ResponseHeadersToAdd, hvo) - - case *pbproxystate.HeaderMutation_ResponseHeaderRemove: - action := mutation.GetResponseHeaderRemove() - envoyRouteRule.ResponseHeadersToRemove = append(envoyRouteRule.ResponseHeadersToRemove, action.GetHeaderKeys()...) - - default: - // This shouldn't be possible considering the types of Destination - return - } -} - -func injectEnvoyVirtualHostWithProxystateHeaderMutation(envoyVirtualHost *envoy_route_v3.VirtualHost, mutation *pbproxystate.HeaderMutation) { - mutation.GetAction() - switch mutation.GetAction().(type) { - case *pbproxystate.HeaderMutation_RequestHeaderAdd: - action := mutation.GetRequestHeaderAdd() - header := action.GetHeader() - app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - - hvo := &envoy_core_v3.HeaderValueOption{ - Header: &envoy_core_v3.HeaderValue{ - Key: header.GetKey(), - Value: header.GetValue(), - }, - Append: response.MakeBoolValue(app), - } - envoyVirtualHost.RequestHeadersToAdd = append(envoyVirtualHost.RequestHeadersToAdd, hvo) - - case *pbproxystate.HeaderMutation_RequestHeaderRemove: - action := mutation.GetRequestHeaderRemove() - envoyVirtualHost.RequestHeadersToRemove = append(envoyVirtualHost.RequestHeadersToRemove, action.GetHeaderKeys()...) - - case *pbproxystate.HeaderMutation_ResponseHeaderAdd: - action := mutation.GetResponseHeaderAdd() - header := action.GetHeader() - app := action.GetAppendAction() == pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD - - hvo := &envoy_core_v3.HeaderValueOption{ - Header: &envoy_core_v3.HeaderValue{ - Key: header.GetKey(), - Value: header.GetValue(), - }, - Append: response.MakeBoolValue(app), - } - envoyVirtualHost.ResponseHeadersToAdd = append(envoyVirtualHost.ResponseHeadersToAdd, hvo) - - case *pbproxystate.HeaderMutation_ResponseHeaderRemove: - action := mutation.GetResponseHeaderRemove() - envoyVirtualHost.ResponseHeadersToRemove = append(envoyVirtualHost.ResponseHeadersToRemove, action.GetHeaderKeys()...) - - default: - // This shouldn't be possible considering the types of Destination - return - } -} diff --git a/agent/xdsv2/testdata/clusters/destination/l4-implicit-and-explicit-destinations-tproxy.golden b/agent/xdsv2/testdata/clusters/destination/l4-implicit-and-explicit-destinations-tproxy.golden deleted file mode 100644 index 089bfb7c2003..000000000000 --- a/agent/xdsv2/testdata/clusters/destination/l4-implicit-and-explicit-destinations-tproxy.golden +++ /dev/null @@ -1,110 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "original-destination", - "type": "ORIGINAL_DST", - "connectTimeout": "5s", - "lbPolicy": "CLUSTER_PROVIDED" - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-1.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-2.default.dc1.internal.foo.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/destination/l4-multi-destination.golden b/agent/xdsv2/testdata/clusters/destination/l4-multi-destination.golden deleted file mode 100644 index c88d7770d85f..000000000000 --- a/agent/xdsv2/testdata/clusters/destination/l4-multi-destination.golden +++ /dev/null @@ -1,205 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "null_route_cluster", - "type": "STATIC", - "connectTimeout": "10s" - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-1.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-2.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp2.api-1.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp2" - ] - }, - "sni": "api-1.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp2.api-2.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp2" - ] - }, - "sni": "api-2.default.dc1.internal.foo.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/destination/l4-multiple-implicit-destinations-tproxy.golden b/agent/xdsv2/testdata/clusters/destination/l4-multiple-implicit-destinations-tproxy.golden deleted file mode 100644 index 089bfb7c2003..000000000000 --- a/agent/xdsv2/testdata/clusters/destination/l4-multiple-implicit-destinations-tproxy.golden +++ /dev/null @@ -1,110 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "original-destination", - "type": "ORIGINAL_DST", - "connectTimeout": "5s", - "lbPolicy": "CLUSTER_PROVIDED" - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-1.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-2.default.dc1.internal.foo.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/destination/l4-single-destination-ip-port-bind-address.golden b/agent/xdsv2/testdata/clusters/destination/l4-single-destination-ip-port-bind-address.golden deleted file mode 100644 index 293416e3737f..000000000000 --- a/agent/xdsv2/testdata/clusters/destination/l4-single-destination-ip-port-bind-address.golden +++ /dev/null @@ -1,109 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "null_route_cluster", - "type": "STATIC", - "connectTimeout": "10s" - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-1.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-2.default.dc1.internal.foo.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/destination/l4-single-destination-unix-socket-bind-address.golden b/agent/xdsv2/testdata/clusters/destination/l4-single-destination-unix-socket-bind-address.golden deleted file mode 100644 index 742dbd0ea838..000000000000 --- a/agent/xdsv2/testdata/clusters/destination/l4-single-destination-unix-socket-bind-address.golden +++ /dev/null @@ -1,55 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-2.default.dc1.internal.foo.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/destination/l4-single-implicit-destination-tproxy.golden b/agent/xdsv2/testdata/clusters/destination/l4-single-implicit-destination-tproxy.golden deleted file mode 100644 index 0c86051ad7df..000000000000 --- a/agent/xdsv2/testdata/clusters/destination/l4-single-implicit-destination-tproxy.golden +++ /dev/null @@ -1,62 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "original-destination", - "type": "ORIGINAL_DST", - "connectTimeout": "5s", - "lbPolicy": "CLUSTER_PROVIDED" - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-1.default.dc1.internal.foo.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/destination/mixed-multi-destination.golden b/agent/xdsv2/testdata/clusters/destination/mixed-multi-destination.golden deleted file mode 100644 index b87031ba81b1..000000000000 --- a/agent/xdsv2/testdata/clusters/destination/mixed-multi-destination.golden +++ /dev/null @@ -1,270 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "failover-target~0~http.api-1.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "55s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - } - ] - }, - "alpnProtocols": [ - "consul~http" - ] - }, - "sni": "api-1.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "failover-target~1~http.api-1.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/backup1-identity" - } - ] - }, - "alpnProtocols": [ - "consul~http" - ] - }, - "sni": "backup-1.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "http.api-1.default.dc1.internal.foo.consul", - "altStatName": "http.api-1.default.dc1.internal.foo.consul", - "clusterType": { - "name": "envoy.clusters.aggregate", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.clusters.aggregate.v3.ClusterConfig", - "clusters": [ - "failover-target~0~http.api-1.default.dc1.internal.foo.consul", - "failover-target~1~http.api-1.default.dc1.internal.foo.consul" - ] - } - }, - "connectTimeout": "55s", - "lbPolicy": "CLUSTER_PROVIDED" - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "http.api-2.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - } - ] - }, - "alpnProtocols": [ - "consul~http" - ] - }, - "sni": "api-2.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "null_route_cluster", - "type": "STATIC", - "connectTimeout": "10s" - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-1.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-2.default.dc1.internal.foo.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden b/agent/xdsv2/testdata/clusters/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden deleted file mode 100644 index ec39ef35787f..000000000000 --- a/agent/xdsv2/testdata/clusters/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden +++ /dev/null @@ -1,302 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "http.api-app.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - } - ] - }, - "alpnProtocols": [ - "consul~http" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "http.api-app2.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" - } - ] - }, - "alpnProtocols": [ - "consul~http" - ] - }, - "sni": "api-app2.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "original-destination", - "type": "ORIGINAL_DST", - "connectTimeout": "5s", - "lbPolicy": "CLUSTER_PROVIDED" - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-app.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-app2.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-app2.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp2.api-app.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp2" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp2.api-app2.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp2" - ] - }, - "sni": "api-app2.default.dc1.internal.foo.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden b/agent/xdsv2/testdata/clusters/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden deleted file mode 100644 index d8cad46e7904..000000000000 --- a/agent/xdsv2/testdata/clusters/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden +++ /dev/null @@ -1,158 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "http.api-app.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - } - ] - }, - "alpnProtocols": [ - "consul~http" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "original-destination", - "type": "ORIGINAL_DST", - "connectTimeout": "5s", - "lbPolicy": "CLUSTER_PROVIDED" - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-app.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp2.api-app.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp2" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden b/agent/xdsv2/testdata/clusters/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden deleted file mode 100644 index d8cad46e7904..000000000000 --- a/agent/xdsv2/testdata/clusters/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden +++ /dev/null @@ -1,158 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "http.api-app.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - } - ] - }, - "alpnProtocols": [ - "consul~http" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "original-destination", - "type": "ORIGINAL_DST", - "connectTimeout": "5s", - "lbPolicy": "CLUSTER_PROVIDED" - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp.api-app.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "tcp2.api-app.default.dc1.internal.foo.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": {}, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "commonLbConfig": { - "healthyPanicThreshold": {} - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - } - ] - }, - "alpnProtocols": [ - "consul~tcp2" - ] - }, - "sni": "api-app.default.dc1.internal.foo.consul" - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/source/l7-expose-paths.golden b/agent/xdsv2/testdata/clusters/source/l7-expose-paths.golden deleted file mode 100644 index a83751b4b502..000000000000 --- a/agent/xdsv2/testdata/clusters/source/l7-expose-paths.golden +++ /dev/null @@ -1,87 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "exposed_cluster_9090", - "type": "STATIC", - "loadAssignment": { - "clusterName": "exposed_cluster_9090", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - } - } - } - ] - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "exposed_cluster_9091", - "type": "STATIC", - "loadAssignment": { - "clusterName": "exposed_cluster_9091", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9091 - } - } - } - } - ] - } - ] - }, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:port1", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:port1", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/source/local-and-inbound-connections.golden b/agent/xdsv2/testdata/clusters/source/local-and-inbound-connections.golden deleted file mode 100644 index d4e6fd1d64ce..000000000000 --- a/agent/xdsv2/testdata/clusters/source/local-and-inbound-connections.golden +++ /dev/null @@ -1,127 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "exposed_cluster_9090", - "type": "STATIC", - "loadAssignment": { - "clusterName": "exposed_cluster_9090", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - } - } - } - ] - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "exposed_cluster_9091", - "type": "STATIC", - "loadAssignment": { - "clusterName": "exposed_cluster_9091", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9091 - } - } - } - } - ] - } - ] - }, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:port1", - "type": "STATIC", - "connectTimeout": "6s", - "loadAssignment": { - "clusterName": "local_app:port1", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - }, - "circuitBreakers": { - "thresholds": [ - { - "maxConnections": 123 - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:port3", - "type": "STATIC", - "connectTimeout": "8s", - "loadAssignment": { - "clusterName": "local_app:port3", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8081 - } - } - } - } - ] - } - ] - }, - "circuitBreakers": { - "thresholds": [ - { - "maxConnections": 123 - } - ] - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/source/multiple-workload-addresses-with-specific-ports.golden b/agent/xdsv2/testdata/clusters/source/multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 0d7d009aa102..000000000000 --- a/agent/xdsv2/testdata/clusters/source/multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,119 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:grpc", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:grpc", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8083 - } - } - } - } - ] - } - ] - }, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:http", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:http", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8081 - } - } - } - } - ] - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:http2", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:http2", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8082 - } - } - } - } - ] - } - ] - }, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:tcp", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:tcp", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/source/multiple-workload-addresses-without-ports.golden b/agent/xdsv2/testdata/clusters/source/multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 0d7d009aa102..000000000000 --- a/agent/xdsv2/testdata/clusters/source/multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,119 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:grpc", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:grpc", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8083 - } - } - } - } - ] - } - ] - }, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:http", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:http", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8081 - } - } - } - } - ] - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:http2", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:http2", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8082 - } - } - } - } - ] - } - ] - }, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:tcp", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:tcp", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden b/agent/xdsv2/testdata/clusters/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 045470a3e572..000000000000 --- a/agent/xdsv2/testdata/clusters/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,55 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:admin-port", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:admin-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:api-port", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:api-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - } - } - } - ] - } - ] - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/source/multiport-l4-multiple-workload-addresses-without-ports.golden b/agent/xdsv2/testdata/clusters/source/multiport-l4-multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 045470a3e572..000000000000 --- a/agent/xdsv2/testdata/clusters/source/multiport-l4-multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,55 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:admin-port", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:admin-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:api-port", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:api-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - } - } - } - ] - } - ] - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/source/multiport-l4-workload-with-only-mesh-port.golden b/agent/xdsv2/testdata/clusters/source/multiport-l4-workload-with-only-mesh-port.golden deleted file mode 100644 index 460d515fe589..000000000000 --- a/agent/xdsv2/testdata/clusters/source/multiport-l4-workload-with-only-mesh-port.golden +++ /dev/null @@ -1,12 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "black-hole-cluster", - "type": "STATIC" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden b/agent/xdsv2/testdata/clusters/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 339faaae6b0d..000000000000 --- a/agent/xdsv2/testdata/clusters/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,63 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:admin-port", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:admin-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:api-port", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:api-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - } - } - } - ] - } - ] - }, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/source/multiport-l7-multiple-workload-addresses-without-ports.golden b/agent/xdsv2/testdata/clusters/source/multiport-l7-multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 6246f19733b8..000000000000 --- a/agent/xdsv2/testdata/clusters/source/multiport-l7-multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,95 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:admin-port", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:admin-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:api-port", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:api-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - } - } - } - ] - } - ] - }, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:grpc-port", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:grpc-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9091 - } - } - } - } - ] - } - ] - }, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/clusters/source/single-workload-address-without-ports.golden b/agent/xdsv2/testdata/clusters/source/single-workload-address-without-ports.golden deleted file mode 100644 index 0d7d009aa102..000000000000 --- a/agent/xdsv2/testdata/clusters/source/single-workload-address-without-ports.golden +++ /dev/null @@ -1,119 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:grpc", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:grpc", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8083 - } - } - } - } - ] - } - ] - }, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:http", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:http", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8081 - } - } - } - } - ] - } - ] - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:http2", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:http2", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8082 - } - } - } - } - ] - } - ] - }, - "typedExtensionProtocolOptions": { - "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { - "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", - "explicitHttpConfig": { - "http2ProtocolOptions": {} - } - } - } - }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "local_app:tcp", - "type": "STATIC", - "loadAssignment": { - "clusterName": "local_app:tcp", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/destination/l4-implicit-and-explicit-destinations-tproxy.golden b/agent/xdsv2/testdata/endpoints/destination/l4-implicit-and-explicit-destinations-tproxy.golden deleted file mode 100644 index f7d569dc2266..000000000000 --- a/agent/xdsv2/testdata/endpoints/destination/l4-implicit-and-explicit-destinations-tproxy.golden +++ /dev/null @@ -1,49 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/destination/l4-multi-destination.golden b/agent/xdsv2/testdata/endpoints/destination/l4-multi-destination.golden deleted file mode 100644 index f8bca7ea3212..000000000000 --- a/agent/xdsv2/testdata/endpoints/destination/l4-multi-destination.golden +++ /dev/null @@ -1,91 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp2.api-1.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp2.api-2.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/destination/l4-multiple-implicit-destinations-tproxy.golden b/agent/xdsv2/testdata/endpoints/destination/l4-multiple-implicit-destinations-tproxy.golden deleted file mode 100644 index f7d569dc2266..000000000000 --- a/agent/xdsv2/testdata/endpoints/destination/l4-multiple-implicit-destinations-tproxy.golden +++ /dev/null @@ -1,49 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/destination/l4-single-destination-ip-port-bind-address.golden b/agent/xdsv2/testdata/endpoints/destination/l4-single-destination-ip-port-bind-address.golden deleted file mode 100644 index f7d569dc2266..000000000000 --- a/agent/xdsv2/testdata/endpoints/destination/l4-single-destination-ip-port-bind-address.golden +++ /dev/null @@ -1,49 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/destination/l4-single-destination-unix-socket-bind-address.golden b/agent/xdsv2/testdata/endpoints/destination/l4-single-destination-unix-socket-bind-address.golden deleted file mode 100644 index 8075b842d96c..000000000000 --- a/agent/xdsv2/testdata/endpoints/destination/l4-single-destination-unix-socket-bind-address.golden +++ /dev/null @@ -1,28 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/destination/l4-single-implicit-destination-tproxy.golden b/agent/xdsv2/testdata/endpoints/destination/l4-single-implicit-destination-tproxy.golden deleted file mode 100644 index 333765ea0cb2..000000000000 --- a/agent/xdsv2/testdata/endpoints/destination/l4-single-implicit-destination-tproxy.golden +++ /dev/null @@ -1,28 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/destination/mixed-multi-destination.golden b/agent/xdsv2/testdata/endpoints/destination/mixed-multi-destination.golden deleted file mode 100644 index e22812cafe4b..000000000000 --- a/agent/xdsv2/testdata/endpoints/destination/mixed-multi-destination.golden +++ /dev/null @@ -1,91 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "http.api-1.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "http.api-2.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden b/agent/xdsv2/testdata/endpoints/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden deleted file mode 100644 index 56ff9fb5884b..000000000000 --- a/agent/xdsv2/testdata/endpoints/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden +++ /dev/null @@ -1,133 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "http.api-app.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "http.api-app2.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-app.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-app2.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp2.api-app.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp2.api-app2.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden b/agent/xdsv2/testdata/endpoints/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden deleted file mode 100644 index 52f227f9d4b8..000000000000 --- a/agent/xdsv2/testdata/endpoints/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden +++ /dev/null @@ -1,70 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "http.api-app.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-app.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp2.api-app.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden b/agent/xdsv2/testdata/endpoints/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden deleted file mode 100644 index 52f227f9d4b8..000000000000 --- a/agent/xdsv2/testdata/endpoints/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden +++ /dev/null @@ -1,70 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "http.api-app.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp.api-app.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "tcp2.api-app.default.dc1.internal.foo.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "10.1.1.1", - "portValue": 20000 - } - } - }, - "healthStatus": "HEALTHY" - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/source/l7-expose-paths.golden b/agent/xdsv2/testdata/endpoints/source/l7-expose-paths.golden deleted file mode 100644 index 1ccb234c89db..000000000000 --- a/agent/xdsv2/testdata/endpoints/source/l7-expose-paths.golden +++ /dev/null @@ -1,67 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "exposed_cluster_9090", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "exposed_cluster_9091", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9091 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:port1", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/source/local-and-inbound-connections.golden b/agent/xdsv2/testdata/endpoints/source/local-and-inbound-connections.golden deleted file mode 100644 index c9e8727f031d..000000000000 --- a/agent/xdsv2/testdata/endpoints/source/local-and-inbound-connections.golden +++ /dev/null @@ -1,87 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "exposed_cluster_9090", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "exposed_cluster_9091", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9091 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:port1", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:port3", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8081 - } - } - } - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/source/multiple-workload-addresses-with-specific-ports.golden b/agent/xdsv2/testdata/endpoints/source/multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 5fc63eef9599..000000000000 --- a/agent/xdsv2/testdata/endpoints/source/multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,87 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:grpc", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8083 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:http", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8081 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:http2", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8082 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:tcp", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/source/multiple-workload-addresses-without-ports.golden b/agent/xdsv2/testdata/endpoints/source/multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 5fc63eef9599..000000000000 --- a/agent/xdsv2/testdata/endpoints/source/multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,87 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:grpc", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8083 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:http", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8081 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:http2", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8082 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:tcp", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden b/agent/xdsv2/testdata/endpoints/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 916fbc26ceab..000000000000 --- a/agent/xdsv2/testdata/endpoints/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,47 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:admin-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:api-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - } - } - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/source/multiport-l4-multiple-workload-addresses-without-ports.golden b/agent/xdsv2/testdata/endpoints/source/multiport-l4-multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 916fbc26ceab..000000000000 --- a/agent/xdsv2/testdata/endpoints/source/multiport-l4-multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,47 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:admin-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:api-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - } - } - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/source/multiport-l4-workload-with-only-mesh-port.golden b/agent/xdsv2/testdata/endpoints/source/multiport-l4-workload-with-only-mesh-port.golden deleted file mode 100644 index 47b46bca225b..000000000000 --- a/agent/xdsv2/testdata/endpoints/source/multiport-l4-workload-with-only-mesh-port.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden b/agent/xdsv2/testdata/endpoints/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 916fbc26ceab..000000000000 --- a/agent/xdsv2/testdata/endpoints/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,47 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:admin-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:api-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - } - } - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/source/multiport-l7-multiple-workload-addresses-without-ports.golden b/agent/xdsv2/testdata/endpoints/source/multiport-l7-multiple-workload-addresses-without-ports.golden deleted file mode 100644 index e3c67d2c90ae..000000000000 --- a/agent/xdsv2/testdata/endpoints/source/multiport-l7-multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,67 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:admin-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:api-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9090 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:grpc-port", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9091 - } - } - } - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/endpoints/source/single-workload-address-without-ports.golden b/agent/xdsv2/testdata/endpoints/source/single-workload-address-without-ports.golden deleted file mode 100644 index 5fc63eef9599..000000000000 --- a/agent/xdsv2/testdata/endpoints/source/single-workload-address-without-ports.golden +++ /dev/null @@ -1,87 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:grpc", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8083 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:http", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8081 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:http2", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8082 - } - } - } - } - ] - } - ] - }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "local_app:tcp", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 8080 - } - } - } - } - ] - } - ] - } - ], - "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/destination/l4-implicit-and-explicit-destinations-tproxy.golden b/agent/xdsv2/testdata/listeners/destination/l4-implicit-and-explicit-destinations-tproxy.golden deleted file mode 100644 index 35304ea0d7f5..000000000000 --- a/agent/xdsv2/testdata/listeners/destination/l4-implicit-and-explicit-destinations-tproxy.golden +++ /dev/null @@ -1,90 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "address": { - "socketAddress": { - "address": "1.1.1.1", - "portValue": 1234 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "cluster": "tcp.api-1.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "outbound_listener", - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 15001 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-2.default.default.dc1", - "cluster": "tcp.api-2.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "defaultFilterChain": { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.original-destination", - "cluster": "original-destination" - } - } - ] - }, - "listenerFilters": [ - { - "name": "envoy.filters.listener.original_dst", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst" - } - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/destination/l4-multi-destination.golden b/agent/xdsv2/testdata/listeners/destination/l4-multi-destination.golden deleted file mode 100644 index 105b508ef52c..000000000000 --- a/agent/xdsv2/testdata/listeners/destination/l4-multi-destination.golden +++ /dev/null @@ -1,137 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "default/local/default/api-1:tcp2:1.1.1.1:2345", - "address": { - "socketAddress": { - "address": "1.1.1.1", - "portValue": 2345 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp2.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp2.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp2.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "address": { - "socketAddress": { - "address": "1.1.1.1", - "portValue": 1234 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "default/local/default/api-2:tcp2:/path/to/socket", - "address": { - "pipe": { - "path": "/path/to/socket", - "mode": 438 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp2.api-2.default.default.dc1", - "cluster": "tcp2.api-2.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "default/local/default/api-2:tcp:/path/to/socket", - "address": { - "pipe": { - "path": "/path/to/socket", - "mode": 438 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-2.default.default.dc1", - "cluster": "tcp.api-2.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/destination/l4-multiple-implicit-destinations-tproxy.golden b/agent/xdsv2/testdata/listeners/destination/l4-multiple-implicit-destinations-tproxy.golden deleted file mode 100644 index 7901233ae959..000000000000 --- a/agent/xdsv2/testdata/listeners/destination/l4-multiple-implicit-destinations-tproxy.golden +++ /dev/null @@ -1,86 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "outbound_listener", - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 15001 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "cluster": "tcp.api-1.default.dc1.internal.foo.consul" - } - } - ] - }, - { - "filterChainMatch": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-2.default.default.dc1", - "cluster": "tcp.api-2.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "defaultFilterChain": { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.original-destination", - "cluster": "original-destination" - } - } - ] - }, - "listenerFilters": [ - { - "name": "envoy.filters.listener.original_dst", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst" - } - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/destination/l4-single-destination-ip-port-bind-address.golden b/agent/xdsv2/testdata/listeners/destination/l4-single-destination-ip-port-bind-address.golden deleted file mode 100644 index 5f78003e3fd8..000000000000 --- a/agent/xdsv2/testdata/listeners/destination/l4-single-destination-ip-port-bind-address.golden +++ /dev/null @@ -1,47 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "address": { - "socketAddress": { - "address": "1.1.1.1", - "portValue": 1234 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/destination/l4-single-destination-unix-socket-bind-address.golden b/agent/xdsv2/testdata/listeners/destination/l4-single-destination-unix-socket-bind-address.golden deleted file mode 100644 index cf468d7fbbcf..000000000000 --- a/agent/xdsv2/testdata/listeners/destination/l4-single-destination-unix-socket-bind-address.golden +++ /dev/null @@ -1,32 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "default/local/default/api-2:tcp:/path/to/socket", - "address": { - "pipe": { - "path": "/path/to/socket", - "mode": 438 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-2.default.default.dc1", - "cluster": "tcp.api-2.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/destination/l4-single-implicit-destination-tproxy.golden b/agent/xdsv2/testdata/listeners/destination/l4-single-implicit-destination-tproxy.golden deleted file mode 100644 index ce759b6b0211..000000000000 --- a/agent/xdsv2/testdata/listeners/destination/l4-single-implicit-destination-tproxy.golden +++ /dev/null @@ -1,61 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "outbound_listener", - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 15001 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "cluster": "tcp.api-1.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "defaultFilterChain": { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.original-destination", - "cluster": "original-destination" - } - } - ] - }, - "listenerFilters": [ - { - "name": "envoy.filters.listener.original_dst", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst" - } - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/destination/mixed-multi-destination.golden b/agent/xdsv2/testdata/listeners/destination/mixed-multi-destination.golden deleted file mode 100644 index eae168bf8aa0..000000000000 --- a/agent/xdsv2/testdata/listeners/destination/mixed-multi-destination.golden +++ /dev/null @@ -1,119 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "default/local/default/api-1:http:1.1.1.1:1234", - "address": { - "socketAddress": { - "address": "1.1.1.1", - "portValue": 1234 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "upstream.http.api-1.default.default.dc1", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "default/local/default/api-1:http:1.1.1.1:1234" - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "address": { - "socketAddress": { - "address": "1.1.1.1", - "portValue": 1234 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "default/local/default/api-2:tcp:/path/to/socket", - "address": { - "pipe": { - "path": "/path/to/socket", - "mode": 438 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-2.default.default.dc1", - "cluster": "tcp.api-2.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden b/agent/xdsv2/testdata/listeners/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden deleted file mode 100644 index b0477d8310e1..000000000000 --- a/agent/xdsv2/testdata/listeners/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden +++ /dev/null @@ -1,222 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "outbound_listener", - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 15001 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-app.default.default.dc1", - "cluster": "tcp.api-app.default.dc1.internal.foo.consul" - } - } - ] - }, - { - "filterChainMatch": { - "destinationPort": 8080, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "upstream.http.api-app.default.default.dc1", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "default/local/default/api-app:http" - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - }, - { - "filterChainMatch": { - "destinationPort": 8081, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp2.api-app.default.default.dc1", - "cluster": "tcp2.api-app.default.dc1.internal.foo.consul" - } - } - ] - }, - { - "filterChainMatch": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-app2.default.default.dc1", - "cluster": "tcp.api-app2.default.dc1.internal.foo.consul" - } - } - ] - }, - { - "filterChainMatch": { - "destinationPort": 8080, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "upstream.http.api-app2.default.default.dc1", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "default/local/default/api-app2:http" - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - }, - { - "filterChainMatch": { - "destinationPort": 8081, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp2.api-app2.default.default.dc1", - "cluster": "tcp2.api-app2.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "defaultFilterChain": { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.original-destination", - "cluster": "original-destination" - } - } - ] - }, - "listenerFilters": [ - { - "name": "envoy.filters.listener.original_dst", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst" - } - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden b/agent/xdsv2/testdata/listeners/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden deleted file mode 100644 index 180213b6523c..000000000000 --- a/agent/xdsv2/testdata/listeners/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden +++ /dev/null @@ -1,125 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "outbound_listener", - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 15001 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-app.default.default.dc1", - "cluster": "tcp.api-app.default.dc1.internal.foo.consul" - } - } - ] - }, - { - "filterChainMatch": { - "destinationPort": 8080, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "upstream.http.api-app.default.default.dc1", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "default/local/default/api-app:http" - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - }, - { - "filterChainMatch": { - "destinationPort": 8081, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp2.api-app.default.default.dc1", - "cluster": "tcp2.api-app.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "defaultFilterChain": { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.original-destination", - "cluster": "original-destination" - } - } - ] - }, - "listenerFilters": [ - { - "name": "envoy.filters.listener.original_dst", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst" - } - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden b/agent/xdsv2/testdata/listeners/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden deleted file mode 100644 index 180213b6523c..000000000000 --- a/agent/xdsv2/testdata/listeners/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden +++ /dev/null @@ -1,125 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "outbound_listener", - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 15001 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp.api-app.default.default.dc1", - "cluster": "tcp.api-app.default.dc1.internal.foo.consul" - } - } - ] - }, - { - "filterChainMatch": { - "destinationPort": 8080, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "upstream.http.api-app.default.default.dc1", - "rds": { - "configSource": { - "ads": {}, - "resourceApiVersion": "V3" - }, - "routeConfigName": "default/local/default/api-app:http" - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - }, - { - "filterChainMatch": { - "destinationPort": 8081, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.tcp2.api-app.default.default.dc1", - "cluster": "tcp2.api-app.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "defaultFilterChain": { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.original-destination", - "cluster": "original-destination" - } - } - ] - }, - "listenerFilters": [ - { - "name": "envoy.filters.listener.original_dst", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst" - } - } - ], - "trafficDirection": "OUTBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/source/l7-expose-paths.golden b/agent/xdsv2/testdata/listeners/source/l7-expose-paths.golden deleted file mode 100644 index 973c825a6c63..000000000000 --- a/agent/xdsv2/testdata/listeners/source/l7-expose-paths.golden +++ /dev/null @@ -1,201 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "exposed_path_GetHealth1235", - "address": { - "socketAddress": { - "address": "10.0.0.1", - "portValue": 1235 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "exposed_path_route_GetHealth1235", - "routeConfig": { - "name": "exposed_path_route_GetHealth1235", - "virtualHosts": [ - { - "name": "exposed_path_route_GetHealth1235", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "path": "GetHealth" - }, - "route": { - "cluster": "exposed_cluster_9091" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - } - ], - "trafficDirection": "INBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "exposed_path_health1234", - "address": { - "socketAddress": { - "address": "10.0.0.1", - "portValue": 1234 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "exposed_path_route_health1234", - "routeConfig": { - "name": "exposed_path_route_health1234", - "virtualHosts": [ - { - "name": "exposed_path_route_health1234", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "path": "/health" - }, - "route": { - "cluster": "exposed_cluster_9090" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - } - ], - "trafficDirection": "INBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener", - "address": { - "socketAddress": { - "address": "10.0.0.1", - "portValue": 20000 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~port1" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app:port1" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - } - }, - "requireClientCertificate": true - } - } - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/source/local-and-inbound-connections.golden b/agent/xdsv2/testdata/listeners/source/local-and-inbound-connections.golden deleted file mode 100644 index 916961daaf9f..000000000000 --- a/agent/xdsv2/testdata/listeners/source/local-and-inbound-connections.golden +++ /dev/null @@ -1,309 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "exposed_path_GetHealth1235", - "address": { - "socketAddress": { - "address": "10.0.0.1", - "portValue": 1235 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "exposed_path_route_GetHealth1235", - "routeConfig": { - "name": "exposed_path_route_GetHealth1235", - "virtualHosts": [ - { - "name": "exposed_path_route_GetHealth1235", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "path": "GetHealth" - }, - "route": { - "cluster": "exposed_cluster_9091" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - } - ], - "trafficDirection": "INBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "exposed_path_health1234", - "address": { - "socketAddress": { - "address": "10.0.0.1", - "portValue": 1234 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "exposed_path_route_health1234", - "routeConfig": { - "name": "exposed_path_route_health1234", - "virtualHosts": [ - { - "name": "exposed_path_route_health1234", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "path": "/health" - }, - "route": { - "cluster": "exposed_cluster_9090" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ] - } - ], - "trafficDirection": "INBOUND" - }, - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener", - "address": { - "socketAddress": { - "address": "10.0.0.1", - "portValue": 20000 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~port1" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.connection_limit", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit", - "statPrefix": "inbound_connection_limit", - "maxConnections": "123" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app:port1" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - } - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~port3" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.connection_limit", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit", - "statPrefix": "inbound_connection_limit", - "maxConnections": "123" - } - }, - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:port3", - "virtualHosts": [ - { - "name": "public_listener:port3", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:port3", - "timeout": "9s" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "INBOUND", - "connectionBalanceConfig": { - "exactBalance": {} - } - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/source/multiple-workload-addresses-with-specific-ports.golden b/agent/xdsv2/testdata/listeners/source/multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index cb81777262f6..000000000000 --- a/agent/xdsv2/testdata/listeners/source/multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,359 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener", - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 20000 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~grpc" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:grpc", - "virtualHosts": [ - { - "name": "public_listener:grpc", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:grpc" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.grpc_stats", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig", - "statsForAllMethods": true - } - }, - { - "name": "envoy.filters.http.grpc_http1_bridge", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_http1_bridge.v3.Config" - } - }, - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "h2", - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~http" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:http", - "virtualHosts": [ - { - "name": "public_listener:http", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:http" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~http2" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:http2", - "virtualHosts": [ - { - "name": "public_listener:http2", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:http2" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "h2", - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~tcp" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app:tcp" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - } - }, - "requireClientCertificate": true - } - } - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/source/multiple-workload-addresses-without-ports.golden b/agent/xdsv2/testdata/listeners/source/multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 81f3bcca70ff..000000000000 --- a/agent/xdsv2/testdata/listeners/source/multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,359 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener", - "address": { - "socketAddress": { - "address": "10.0.0.1", - "portValue": 20000 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~grpc" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:grpc", - "virtualHosts": [ - { - "name": "public_listener:grpc", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:grpc" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.grpc_stats", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig", - "statsForAllMethods": true - } - }, - { - "name": "envoy.filters.http.grpc_http1_bridge", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_http1_bridge.v3.Config" - } - }, - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "h2", - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~http" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:http", - "virtualHosts": [ - { - "name": "public_listener:http", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:http" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~http2" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:http2", - "virtualHosts": [ - { - "name": "public_listener:http2", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:http2" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "h2", - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~tcp" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app:tcp" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - } - }, - "requireClientCertificate": true - } - } - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden b/agent/xdsv2/testdata/listeners/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 10fcbb9c9b6c..000000000000 --- a/agent/xdsv2/testdata/listeners/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,128 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener", - "address": { - "socketAddress": { - "address": "10.0.0.3", - "portValue": 20000 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~admin-port" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app:admin-port" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - } - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~api-port" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app:api-port" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - } - }, - "requireClientCertificate": true - } - } - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/source/multiport-l4-multiple-workload-addresses-without-ports.golden b/agent/xdsv2/testdata/listeners/source/multiport-l4-multiple-workload-addresses-without-ports.golden deleted file mode 100644 index ba8670185485..000000000000 --- a/agent/xdsv2/testdata/listeners/source/multiport-l4-multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,128 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener", - "address": { - "socketAddress": { - "address": "10.0.0.1", - "portValue": 20000 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~admin-port" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app:admin-port" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - } - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~api-port" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app:api-port" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - } - }, - "requireClientCertificate": true - } - } - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/source/multiport-l4-workload-with-only-mesh-port.golden b/agent/xdsv2/testdata/listeners/source/multiport-l4-workload-with-only-mesh-port.golden deleted file mode 100644 index 15d019e69ca5..000000000000 --- a/agent/xdsv2/testdata/listeners/source/multiport-l4-workload-with-only-mesh-port.golden +++ /dev/null @@ -1,40 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener", - "address": { - "socketAddress": { - "address": "10.0.0.1", - "portValue": 20000 - } - }, - "filterChains": [ - { - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "black-hole-cluster" - } - } - ] - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden b/agent/xdsv2/testdata/listeners/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 1f0d971a9905..000000000000 --- a/agent/xdsv2/testdata/listeners/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,206 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener", - "address": { - "socketAddress": { - "address": "10.0.0.3", - "portValue": 20000 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~admin-port" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:admin-port", - "virtualHosts": [ - { - "name": "public_listener:admin-port", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:admin-port" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~api-port" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:api-port", - "virtualHosts": [ - { - "name": "public_listener:api-port", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:api-port" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "h2", - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/source/multiport-l7-multiple-workload-addresses-without-ports.golden b/agent/xdsv2/testdata/listeners/source/multiport-l7-multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 594d47c96c55..000000000000 --- a/agent/xdsv2/testdata/listeners/source/multiport-l7-multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,309 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener", - "address": { - "socketAddress": { - "address": "10.0.0.1", - "portValue": 20000 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~admin-port" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:admin-port", - "virtualHosts": [ - { - "name": "public_listener:admin-port", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:admin-port" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~api-port" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:api-port", - "virtualHosts": [ - { - "name": "public_listener:api-port", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:api-port" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "h2", - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~grpc-port" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:grpc-port", - "virtualHosts": [ - { - "name": "public_listener:grpc-port", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:grpc-port" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.grpc_stats", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig", - "statsForAllMethods": true - } - }, - { - "name": "envoy.filters.http.grpc_http1_bridge", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_http1_bridge.v3.Config" - } - }, - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "h2", - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/listeners/source/single-workload-address-without-ports.golden b/agent/xdsv2/testdata/listeners/source/single-workload-address-without-ports.golden deleted file mode 100644 index 81f3bcca70ff..000000000000 --- a/agent/xdsv2/testdata/listeners/source/single-workload-address-without-ports.golden +++ /dev/null @@ -1,359 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener", - "address": { - "socketAddress": { - "address": "10.0.0.1", - "portValue": 20000 - } - }, - "filterChains": [ - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~grpc" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:grpc", - "virtualHosts": [ - { - "name": "public_listener:grpc", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:grpc" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.grpc_stats", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig", - "statsForAllMethods": true - } - }, - { - "name": "envoy.filters.http.grpc_http1_bridge", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_http1_bridge.v3.Config" - } - }, - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "h2", - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~http" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:http", - "virtualHosts": [ - { - "name": "public_listener:http", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:http" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~http2" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "public_listener", - "routeConfig": { - "name": "public_listener:http2", - "virtualHosts": [ - { - "name": "public_listener:http2", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "local_app:http2" - } - } - ] - } - ] - }, - "httpFilters": [ - { - "name": "envoy.filters.http.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", - "rules": {} - } - }, - { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "randomSampling": {} - }, - "http2ProtocolOptions": {}, - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ] - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - }, - "alpnProtocols": [ - "h2", - "http/1.1" - ] - }, - "requireClientCertificate": true - } - } - }, - { - "filterChainMatch": { - "applicationProtocols": [ - "consul~tcp" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" - } - }, - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app:tcp" - } - } - ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "some-root\nsome-other-root\n" - } - } - }, - "requireClientCertificate": true - } - } - } - ], - "listenerFilters": [ - { - "name": "envoy.filters.listener.tls_inspector", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" - } - } - ], - "trafficDirection": "INBOUND" - } - ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/destination/l4-implicit-and-explicit-destinations-tproxy.golden b/agent/xdsv2/testdata/routes/destination/l4-implicit-and-explicit-destinations-tproxy.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/destination/l4-implicit-and-explicit-destinations-tproxy.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/destination/l4-multi-destination.golden b/agent/xdsv2/testdata/routes/destination/l4-multi-destination.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/destination/l4-multi-destination.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/destination/l4-multiple-implicit-destinations-tproxy.golden b/agent/xdsv2/testdata/routes/destination/l4-multiple-implicit-destinations-tproxy.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/destination/l4-multiple-implicit-destinations-tproxy.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/destination/l4-single-destination-ip-port-bind-address.golden b/agent/xdsv2/testdata/routes/destination/l4-single-destination-ip-port-bind-address.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/destination/l4-single-destination-ip-port-bind-address.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/destination/l4-single-destination-unix-socket-bind-address.golden b/agent/xdsv2/testdata/routes/destination/l4-single-destination-unix-socket-bind-address.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/destination/l4-single-destination-unix-socket-bind-address.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/destination/l4-single-implicit-destination-tproxy.golden b/agent/xdsv2/testdata/routes/destination/l4-single-implicit-destination-tproxy.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/destination/l4-single-implicit-destination-tproxy.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/destination/mixed-multi-destination.golden b/agent/xdsv2/testdata/routes/destination/mixed-multi-destination.golden deleted file mode 100644 index 28f9669ee371..000000000000 --- a/agent/xdsv2/testdata/routes/destination/mixed-multi-destination.golden +++ /dev/null @@ -1,67 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "default/local/default/api-1:http:1.1.1.1:1234", - "virtualHosts": [ - { - "name": "default/local/default/api-1:http:1.1.1.1:1234", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/split" - }, - "route": { - "weightedClusters": { - "clusters": [ - { - "name": "http.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "http.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - }, - "timeout": "77s" - } - }, - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "http.api-1.default.dc1.internal.foo.consul", - "timeout": "606s", - "retryPolicy": { - "retryOn": "connect-failure", - "numRetries": 4 - } - } - }, - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "null_route_cluster" - } - } - ] - } - ], - "validateClusters": true - } - ], - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden b/agent/xdsv2/testdata/routes/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden deleted file mode 100644 index c34c2a0602d2..000000000000 --- a/agent/xdsv2/testdata/routes/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden +++ /dev/null @@ -1,53 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "default/local/default/api-app2:http", - "virtualHosts": [ - { - "name": "default/local/default/api-app2:http", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "http.api-app2.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "validateClusters": true - }, - { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "default/local/default/api-app:http", - "virtualHosts": [ - { - "name": "default/local/default/api-app:http", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "http.api-app.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "validateClusters": true - } - ], - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden b/agent/xdsv2/testdata/routes/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden deleted file mode 100644 index caa0f6deb000..000000000000 --- a/agent/xdsv2/testdata/routes/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden +++ /dev/null @@ -1,30 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "default/local/default/api-app:http", - "virtualHosts": [ - { - "name": "default/local/default/api-app:http", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "http.api-app.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "validateClusters": true - } - ], - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden b/agent/xdsv2/testdata/routes/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden deleted file mode 100644 index caa0f6deb000..000000000000 --- a/agent/xdsv2/testdata/routes/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden +++ /dev/null @@ -1,30 +0,0 @@ -{ - "versionInfo": "00000001", - "resources": [ - { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "default/local/default/api-app:http", - "virtualHosts": [ - { - "name": "default/local/default/api-app:http", - "domains": [ - "*" - ], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "http.api-app.default.dc1.internal.foo.consul" - } - } - ] - } - ], - "validateClusters": true - } - ], - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/source/l7-expose-paths.golden b/agent/xdsv2/testdata/routes/source/l7-expose-paths.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/source/l7-expose-paths.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/source/local-and-inbound-connections.golden b/agent/xdsv2/testdata/routes/source/local-and-inbound-connections.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/source/local-and-inbound-connections.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/source/multiple-workload-addresses-with-specific-ports.golden b/agent/xdsv2/testdata/routes/source/multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/source/multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/source/multiple-workload-addresses-without-ports.golden b/agent/xdsv2/testdata/routes/source/multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/source/multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden b/agent/xdsv2/testdata/routes/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/source/multiport-l4-multiple-workload-addresses-without-ports.golden b/agent/xdsv2/testdata/routes/source/multiport-l4-multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/source/multiport-l4-multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/source/multiport-l4-workload-with-only-mesh-port.golden b/agent/xdsv2/testdata/routes/source/multiport-l4-workload-with-only-mesh-port.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/source/multiport-l4-workload-with-only-mesh-port.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden b/agent/xdsv2/testdata/routes/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/source/multiport-l7-multiple-workload-addresses-without-ports.golden b/agent/xdsv2/testdata/routes/source/multiport-l7-multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/source/multiport-l7-multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/agent/xdsv2/testdata/routes/source/single-workload-address-without-ports.golden b/agent/xdsv2/testdata/routes/source/single-workload-address-without-ports.golden deleted file mode 100644 index 306f5220e7b9..000000000000 --- a/agent/xdsv2/testdata/routes/source/single-workload-address-without-ports.golden +++ /dev/null @@ -1,5 +0,0 @@ -{ - "versionInfo": "00000001", - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" -} \ No newline at end of file diff --git a/api/.copywrite.hcl b/api/.copywrite.hcl index 34d99ba25e12..7e4c0b58a8a3 100644 --- a/api/.copywrite.hcl +++ b/api/.copywrite.hcl @@ -2,7 +2,7 @@ schema_version = 1 project { license = "MPL-2.0" - copyright_year = 2023 + copyright_year = 2024 header_ignore = [] } diff --git a/api/acl.go b/api/acl.go index 47b38eb6ca62..b0ec6f2f47b1 100644 --- a/api/acl.go +++ b/api/acl.go @@ -21,11 +21,12 @@ const ( ACLManagementType = "management" // ACLTemplatedPolicy names - ACLTemplatedPolicyServiceName = "builtin/service" - ACLTemplatedPolicyNodeName = "builtin/node" - ACLTemplatedPolicyDNSName = "builtin/dns" - ACLTemplatedPolicyNomadServerName = "builtin/nomad-server" - ACLTemplatedPolicyWorkloadIdentityName = "builtin/workload-identity" + ACLTemplatedPolicyServiceName = "builtin/service" + ACLTemplatedPolicyNodeName = "builtin/node" + ACLTemplatedPolicyDNSName = "builtin/dns" + ACLTemplatedPolicyNomadServerName = "builtin/nomad-server" + ACLTemplatedPolicyAPIGatewayName = "builtin/api-gateway" + ACLTemplatedPolicyNomadClientName = "builtin/nomad-client" ) type ACLLink struct { @@ -172,6 +173,7 @@ type ACLTemplatedPolicyResponse struct { TemplateName string Schema string Template string + Description string } type ACLTemplatedPolicyVariables struct { @@ -253,6 +255,9 @@ const ( // BindingRuleBindTypeNode binds to a node identity with given name. BindingRuleBindTypeNode BindingRuleBindType = "node" + // BindingRuleBindTypePolicy binds to a specific policy with given name. + BindingRuleBindTypePolicy BindingRuleBindType = "policy" + // BindingRuleBindTypeTemplatedPolicy binds to a templated policy with given template name and variables. BindingRuleBindTypeTemplatedPolicy BindingRuleBindType = "templated-policy" ) diff --git a/api/agent_test.go b/api/agent_test.go index 511d51607dec..067564f04e38 100644 --- a/api/agent_test.go +++ b/api/agent_test.go @@ -58,8 +58,13 @@ func TestAPI_AgentMetrics(t *testing.T) { if err != nil { r.Fatalf("err: %v", err) } + hostname, err := os.Hostname() + if err != nil { + r.Fatalf("error determining hostname: %v", err) + } + metricName := fmt.Sprintf("consul.%s.runtime.alloc_bytes", hostname) for _, g := range metrics.Gauges { - if g.Name == "consul.runtime.alloc_bytes" { + if g.Name == metricName { return } } diff --git a/api/api.go b/api/api.go index f62c0c5a1bf0..d4d853d5d4b1 100644 --- a/api/api.go +++ b/api/api.go @@ -10,6 +10,7 @@ import ( "encoding/json" "fmt" "io" + "math" "net" "net/http" "net/url" @@ -117,6 +118,13 @@ type QueryOptions struct { // Note: Partitions are available only in Consul Enterprise Partition string + // SamenessGroup is used find the SamenessGroup in the given + // Partition and will find the failover order for the Service + // from the SamenessGroup Members, with the given Partition being + // the first member. + // Note: SamenessGroups are available only in Consul Enterprise + SamenessGroup string + // Providing a datacenter overwrites the DC provided // by the Config Datacenter string @@ -847,6 +855,12 @@ func (r *request) setQueryOptions(q *QueryOptions) { // rather than the alternative short-hand "ap" r.params.Set("partition", q.Partition) } + if q.SamenessGroup != "" { + // For backwards-compatibility with existing tests, + // use the long-hand query param name "sameness-group" + // rather than the alternative short-hand "sg" + r.params.Set("sameness-group", q.SamenessGroup) + } if q.Datacenter != "" { // For backwards-compatibility with existing tests, // use the short-hand query param name "dc" @@ -1129,6 +1143,23 @@ func (c *Client) write(endpoint string, in, out interface{}, q *WriteOptions) (* return wm, nil } +// delete is used to do a DELETE request against an endpoint +func (c *Client) delete(endpoint string, q *QueryOptions) (*WriteMeta, error) { + r := c.newRequest("DELETE", endpoint) + r.setQueryOptions(q) + rtt, resp, err := c.doRequest(r) + if err != nil { + return nil, err + } + defer closeResponseBody(resp) + if err = requireHttpCodes(resp, 204, 200); err != nil { + return nil, err + } + + wm := &WriteMeta{RequestTime: rtt} + return wm, nil +} + // parseQueryMeta is used to help parse query meta-data // // TODO(rb): bug? the error from this function is never handled @@ -1151,6 +1182,9 @@ func parseQueryMeta(resp *http.Response, q *QueryMeta) error { if err != nil { return fmt.Errorf("Failed to parse X-Consul-LastContact: %v", err) } + if last > math.MaxInt64 { + return fmt.Errorf("X-Consul-LastContact Header value is out of range: %d", last) + } q.LastContact = time.Duration(last) * time.Millisecond // Parse the X-Consul-KnownLeader @@ -1192,6 +1226,9 @@ func parseQueryMeta(resp *http.Response, q *QueryMeta) error { if err != nil { return fmt.Errorf("Failed to parse Age Header: %v", err) } + if age > math.MaxInt64 { + return fmt.Errorf("Age Header value is out of range: %d", last) + } q.CacheAge = time.Duration(age) * time.Second } diff --git a/api/api_test.go b/api/api_test.go index 4d5dd1fda830..e8a03f7218cc 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -119,7 +119,7 @@ func makeClientWithConfig( var server *testutil.TestServer var err error retry.RunWith(retry.ThreeTimes(), t, func(r *retry.R) { - server, err = testutil.NewTestServerConfigT(t, cb2) + server, err = testutil.NewTestServerConfigT(r, cb2) if err != nil { r.Fatalf("Failed to start server: %v", err.Error()) } @@ -717,8 +717,11 @@ func TestAPI_ClientTLSOptions(t *testing.T) { // Should fail _, err = client.Agent().Self() - if err == nil || !strings.Contains(err.Error(), "bad certificate") { - t.Fatal(err) + // Check for one of the possible cert error messages + // See https://cs.opensource.google/go/go/+/62a994837a57a7d0c58bb364b580a389488446c9 + if err == nil || !(strings.Contains(err.Error(), "tls: bad certificate") || + strings.Contains(err.Error(), "tls: certificate required")) { + t.Fatalf("expected tls certificate error, but got '%v'", err) } }) diff --git a/api/config_entry.go b/api/config_entry.go index ffc18a85ed5c..8c3a080f70bd 100644 --- a/api/config_entry.go +++ b/api/config_entry.go @@ -29,13 +29,14 @@ const ( SamenessGroup string = "sameness-group" RateLimitIPConfig string = "control-plane-request-limit" - ProxyConfigGlobal string = "global" - MeshConfigMesh string = "mesh" - APIGateway string = "api-gateway" - TCPRoute string = "tcp-route" - InlineCertificate string = "inline-certificate" - HTTPRoute string = "http-route" - JWTProvider string = "jwt-provider" + ProxyConfigGlobal string = "global" + MeshConfigMesh string = "mesh" + APIGateway string = "api-gateway" + TCPRoute string = "tcp-route" + FileSystemCertificate string = "file-system-certificate" + InlineCertificate string = "inline-certificate" + HTTPRoute string = "http-route" + JWTProvider string = "jwt-provider" ) const ( @@ -447,6 +448,8 @@ func makeConfigEntry(kind, name string) (ConfigEntry, error) { return &APIGatewayConfigEntry{Kind: kind, Name: name}, nil case TCPRoute: return &TCPRouteConfigEntry{Kind: kind, Name: name}, nil + case FileSystemCertificate: + return &FileSystemCertificateConfigEntry{Kind: kind, Name: name}, nil case InlineCertificate: return &InlineCertificateConfigEntry{Kind: kind, Name: name}, nil case HTTPRoute: diff --git a/api/config_entry_discoverychain.go b/api/config_entry_discoverychain.go index eeb3a1074c0c..572d9d2d5e46 100644 --- a/api/config_entry_discoverychain.go +++ b/api/config_entry_discoverychain.go @@ -41,9 +41,10 @@ type ServiceRouteMatch struct { } type ServiceRouteHTTPMatch struct { - PathExact string `json:",omitempty" alias:"path_exact"` - PathPrefix string `json:",omitempty" alias:"path_prefix"` - PathRegex string `json:",omitempty" alias:"path_regex"` + PathExact string `json:",omitempty" alias:"path_exact"` + PathPrefix string `json:",omitempty" alias:"path_prefix"` + PathRegex string `json:",omitempty" alias:"path_regex"` + CaseInsensitive bool `json:",omitempty" alias:"case_insensitive"` Header []ServiceRouteHTTPMatchHeader `json:",omitempty"` QueryParam []ServiceRouteHTTPMatchQueryParam `json:",omitempty" alias:"query_param"` diff --git a/api/config_entry_discoverychain_test.go b/api/config_entry_discoverychain_test.go index 6b4a63e97e87..5d825a0db0fc 100644 --- a/api/config_entry_discoverychain_test.go +++ b/api/config_entry_discoverychain_test.go @@ -121,6 +121,7 @@ func TestAPI_ConfigEntry_DiscoveryChain(t *testing.T) { "alternate", "test-split", "test-route", + "test-route-case-insensitive", } { serviceDefaults := &ServiceConfigEntry{ Kind: ServiceDefaults, @@ -306,6 +307,67 @@ func TestAPI_ConfigEntry_DiscoveryChain(t *testing.T) { }, verify: verifyRouter, }, + { + name: "mega router case insensitive", // use one mega object to avoid multiple trips + entry: &ServiceRouterConfigEntry{ + Kind: ServiceRouter, + Name: "test-route-case-insensitive", + Partition: defaultPartition, + Namespace: defaultNamespace, + Routes: []ServiceRoute{ + { + Match: &ServiceRouteMatch{ + HTTP: &ServiceRouteHTTPMatch{ + PathPrefix: "/prEfix", + CaseInsensitive: true, + Header: []ServiceRouteHTTPMatchHeader{ + {Name: "x-debug", Exact: "1"}, + }, + QueryParam: []ServiceRouteHTTPMatchQueryParam{ + {Name: "debug", Exact: "1"}, + }, + }, + }, + Destination: &ServiceRouteDestination{ + Service: "test-failover", + ServiceSubset: "v2", + Namespace: defaultNamespace, + Partition: defaultPartition, + PrefixRewrite: "/", + RequestTimeout: 5 * time.Second, + NumRetries: 5, + RetryOnConnectFailure: true, + RetryOnStatusCodes: []uint32{500, 503, 401}, + RetryOn: []string{ + "gateway-error", + "reset", + "envoy-ratelimited", + "retriable-4xx", + "refused-stream", + "cancelled", + "deadline-exceeded", + "internal", + "resource-exhausted", + "unavailable", + }, + RequestHeaders: &HTTPHeaderModifiers{ + Set: map[string]string{ + "x-foo": "bar", + }, + }, + ResponseHeaders: &HTTPHeaderModifiers{ + Remove: []string{"x-foo"}, + }, + }, + }, + }, + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + }, + verify: verifyRouter, + }, } { tc := tc name := fmt.Sprintf("%s:%s: %s", tc.entry.GetKind(), tc.entry.GetName(), tc.name) diff --git a/api/config_entry_exports.go b/api/config_entry_exports.go index 97920e40ddcd..b8e9830e652d 100644 --- a/api/config_entry_exports.go +++ b/api/config_entry_exports.go @@ -3,7 +3,9 @@ package api -import "encoding/json" +import ( + "encoding/json" +) // ExportedServicesConfigEntry manages the exported services for a single admin partition. // Admin Partitions are a Consul Enterprise feature. diff --git a/api/config_entry_file_system_certificate.go b/api/config_entry_file_system_certificate.go new file mode 100644 index 000000000000..3a0f319acd06 --- /dev/null +++ b/api/config_entry_file_system_certificate.go @@ -0,0 +1,44 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package api + +type FileSystemCertificateConfigEntry struct { + // Kind of the config entry. This should be set to api.FileSystemCertificate. + Kind string + + Name string + + // Certificate is the path to a client certificate to use for TLS connections. + Certificate string `json:",omitempty" alias:"certificate"` + + // PrivateKey is the path to a private key to use for TLS connections. + PrivateKey string `json:",omitempty" alias:"private_key"` + + Meta map[string]string `json:",omitempty"` + + // CreateIndex is the Raft index this entry was created at. This is a + // read-only field. + CreateIndex uint64 + + // ModifyIndex is used for the Check-And-Set operations and can also be fed + // back into the WaitIndex of the QueryOptions in order to perform blocking + // queries. + ModifyIndex uint64 + + // Partition is the partition the config entry is associated with. + // Partitioning is a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // Namespace is the namespace the config entry is associated with. + // Namespacing is a Consul Enterprise feature. + Namespace string `json:",omitempty"` +} + +func (a *FileSystemCertificateConfigEntry) GetKind() string { return FileSystemCertificate } +func (a *FileSystemCertificateConfigEntry) GetName() string { return a.Name } +func (a *FileSystemCertificateConfigEntry) GetPartition() string { return a.Partition } +func (a *FileSystemCertificateConfigEntry) GetNamespace() string { return a.Namespace } +func (a *FileSystemCertificateConfigEntry) GetMeta() map[string]string { return a.Meta } +func (a *FileSystemCertificateConfigEntry) GetCreateIndex() uint64 { return a.CreateIndex } +func (a *FileSystemCertificateConfigEntry) GetModifyIndex() uint64 { return a.ModifyIndex } diff --git a/api/config_entry_gateways.go b/api/config_entry_gateways.go index baf274e2da02..ba2bac19efe7 100644 --- a/api/config_entry_gateways.go +++ b/api/config_entry_gateways.go @@ -195,6 +195,9 @@ type TerminatingGatewayConfigEntry struct { type LinkedService struct { // Referencing other partitions is not supported. + //DisableAutoHostRewrite disables terminating gateways auto host rewrite feature when set to true. + DisableAutoHostRewrite bool `json:",omitempty"` + // Namespace is where the service is registered. Namespace string `json:",omitempty"` diff --git a/api/config_entry_intentions.go b/api/config_entry_intentions.go index 3f03b0875b9c..642479c1ba53 100644 --- a/api/config_entry_intentions.go +++ b/api/config_entry_intentions.go @@ -63,13 +63,15 @@ type IntentionHTTPPermission struct { } type IntentionHTTPHeaderPermission struct { - Name string - Present bool `json:",omitempty"` - Exact string `json:",omitempty"` - Prefix string `json:",omitempty"` - Suffix string `json:",omitempty"` - Regex string `json:",omitempty"` - Invert bool `json:",omitempty"` + Name string + Present bool `json:",omitempty"` + Exact string `json:",omitempty"` + Prefix string `json:",omitempty"` + Suffix string `json:",omitempty"` + Contains string `json:",omitempty"` + Regex string `json:",omitempty"` + Invert bool `json:",omitempty"` + IgnoreCase bool `json:",omitempty" alias:"ignore_case"` } type IntentionJWTRequirement struct { diff --git a/api/config_entry_mesh.go b/api/config_entry_mesh.go index 1a1ebb8b536b..647b02b23800 100644 --- a/api/config_entry_mesh.go +++ b/api/config_entry_mesh.go @@ -26,6 +26,14 @@ type MeshConfigEntry struct { // MutualTLSMode=permissive in either service-defaults or proxy-defaults. AllowEnablingPermissiveMutualTLS bool `json:",omitempty" alias:"allow_enabling_permissive_mutual_tls"` + // ValidateClusters controls whether the clusters the route table refers to are validated. The default value is + // false. When set to false and a route refers to a cluster that does not exist, the route table loads and routing + // to a non-existent cluster results in a 404. When set to true and the route is set to a cluster that do not exist, + // the route table will not load. For more information, refer to + // [HTTP route configuration in the Envoy docs](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route.proto#envoy-v3-api-field-config-route-v3-routeconfiguration-validate-clusters) + // for more details. + ValidateClusters bool `json:",omitempty" alias:"validate_clusters"` + TLS *MeshTLSConfig `json:",omitempty"` HTTP *MeshHTTPConfig `json:",omitempty"` @@ -61,12 +69,53 @@ type MeshDirectionalTLSConfig struct { type MeshHTTPConfig struct { SanitizeXForwardedClientCert bool `alias:"sanitize_x_forwarded_client_cert"` + // Incoming configures settings for incoming HTTP traffic to mesh proxies. + Incoming *MeshDirectionalHTTPConfig `json:",omitempty"` +} + +// MeshDirectionalHTTPConfig holds mesh configuration specific to HTTP +// requests for a given traffic direction. +type MeshDirectionalHTTPConfig struct { + RequestNormalization *RequestNormalizationMeshConfig `json:",omitempty" alias:"request_normalization"` } type PeeringMeshConfig struct { PeerThroughMeshGateways bool `json:",omitempty" alias:"peer_through_mesh_gateways"` } +// RequestNormalizationMeshConfig contains options pertaining to the +// normalization of HTTP requests processed by mesh proxies. +type RequestNormalizationMeshConfig struct { + // InsecureDisablePathNormalization sets the value of the \`normalize_path\` option in the Envoy listener's + // `HttpConnectionManager`. The default value is \`false\`. When set to \`true\` in Consul, \`normalize_path\` is + // set to \`false\` for the Envoy proxy. This parameter disables the normalization of request URL paths according to + // RFC 3986, conversion of \`\\\` to \`/\`, and decoding non-reserved %-encoded characters. When using L7 intentions + // with path match rules, we recommend enabling path normalization in order to avoid match rule circumvention with + // non-normalized path values. + InsecureDisablePathNormalization bool `json:",omitempty" alias:"insecure_disable_path_normalization"` + // MergeSlashes sets the value of the \`merge_slashes\` option in the Envoy listener's \`HttpConnectionManager\`. + // The default value is \`false\`. This option controls the normalization of request URL paths by merging + // consecutive \`/\` characters. This normalization is not part of RFC 3986. When using L7 intentions with path + // match rules, we recommend enabling this setting to avoid match rule circumvention through non-normalized path + // values, unless legitimate service traffic depends on allowing for repeat \`/\` characters, or upstream services + // are configured to differentiate between single and multiple slashes. + MergeSlashes bool `json:",omitempty" alias:"merge_slashes"` + // PathWithEscapedSlashesAction sets the value of the \`path_with_escaped_slashes_action\` option in the Envoy + // listener's \`HttpConnectionManager\`. The default value of this option is empty, which is equivalent to + // \`IMPLEMENTATION_SPECIFIC_DEFAULT\`. This parameter controls the action taken in response to request URL paths + // with escaped slashes in the path. When using L7 intentions with path match rules, we recommend enabling this + // setting to avoid match rule circumvention through non-normalized path values, unless legitimate service traffic + // depends on allowing for escaped \`/\` or \`\\\` characters, or upstream services are configured to differentiate + // between escaped and unescaped slashes. Refer to the Envoy documentation for more information on available + // options. + PathWithEscapedSlashesAction string `json:",omitempty" alias:"path_with_escaped_slashes_action"` + // HeadersWithUnderscoresAction sets the value of the \`headers_with_underscores_action\` option in the Envoy + // listener's \`HttpConnectionManager\` under \`common_http_protocol_options\`. The default value of this option is + // empty, which is equivalent to \`ALLOW\`. Refer to the Envoy documentation for more information on available + // options. + HeadersWithUnderscoresAction string `json:",omitempty" alias:"headers_with_underscores_action"` +} + func (e *MeshConfigEntry) GetKind() string { return MeshConfig } func (e *MeshConfigEntry) GetName() string { return MeshConfigMesh } func (e *MeshConfigEntry) GetPartition() string { return e.Partition } diff --git a/api/config_entry_test.go b/api/config_entry_test.go index 2461c387b35f..d6fe8373c9c0 100644 --- a/api/config_entry_test.go +++ b/api/config_entry_test.go @@ -104,7 +104,7 @@ func TestAPI_ConfigEntries(t *testing.T) { service := &ServiceConfigEntry{ Kind: ServiceDefaults, Name: "foo", - Protocol: "udp", + Protocol: "http", MutualTLSMode: MutualTLSModeStrict, Meta: map[string]string{ "foo": "bar", @@ -124,7 +124,7 @@ func TestAPI_ConfigEntries(t *testing.T) { service2 := &ServiceConfigEntry{ Kind: ServiceDefaults, Name: "bar", - Protocol: "tcp", + Protocol: "http", Destination: dest, } @@ -176,7 +176,7 @@ func TestAPI_ConfigEntries(t *testing.T) { require.True(t, written) // update no cas - service.Protocol = "http" + service.Protocol = "tcp" _, wm, err = config_entries.Set(service, nil) require.NoError(t, err) diff --git a/api/exported_services.go b/api/exported_services.go new file mode 100644 index 000000000000..50483e9c8da6 --- /dev/null +++ b/api/exported_services.go @@ -0,0 +1,49 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package api + +type ResolvedExportedService struct { + // Service is the name of the service which is exported. + Service string + + // Partition of the service + Partition string `json:",omitempty"` + + // Namespace of the service + Namespace string `json:",omitempty"` + + // Consumers is a list of downstream consumers of the service. + Consumers ResolvedConsumers +} + +type ResolvedConsumers struct { + Peers []string `json:",omitempty"` + Partitions []string `json:",omitempty"` +} + +func (c *Client) ExportedServices(q *QueryOptions) ([]ResolvedExportedService, *QueryMeta, error) { + + r := c.newRequest("GET", "/v1/exported-services") + r.setQueryOptions(q) + rtt, resp, err := c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var expSvcs []ResolvedExportedService + + if err := decodeBody(resp, &expSvcs); err != nil { + return nil, nil, err + } + + return expSvcs, qm, nil +} diff --git a/api/go.mod b/api/go.mod index aa6e9a153349..8df6a0aaa1f5 100644 --- a/api/go.mod +++ b/api/go.mod @@ -4,9 +4,16 @@ go 1.19 replace github.com/hashicorp/consul/sdk => ../sdk +retract ( + v1.29.5 // cut from incorrect branch + v1.28.0 // tag was mutated + v1.27.1 // tag was mutated + v1.21.2 // tag was mutated +) + require ( github.com/google/go-cmp v0.5.9 - github.com/hashicorp/consul/sdk v0.15.0 + github.com/hashicorp/consul/sdk v0.16.1 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-hclog v1.5.0 github.com/hashicorp/go-multierror v1.1.1 @@ -14,14 +21,14 @@ require ( github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/serf v0.10.1 github.com/mitchellh/mapstructure v1.5.0 - github.com/stretchr/testify v1.8.3 + github.com/stretchr/testify v1.8.4 golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 ) require ( github.com/armon/go-metrics v0.4.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/fatih/color v1.14.1 // indirect + github.com/fatih/color v1.16.0 // indirect github.com/google/btree v1.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect @@ -30,17 +37,16 @@ require ( github.com/hashicorp/go-version v1.2.1 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/memberlist v0.5.0 // indirect - github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/miekg/dns v1.1.41 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/stretchr/objx v0.5.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.24.0 // indirect golang.org/x/sync v0.2.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/sys v0.19.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/api/go.sum b/api/go.sum index bfc3fb8a11fb..de53ac240dcc 100644 --- a/api/go.sum +++ b/api/go.sum @@ -16,7 +16,6 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -24,8 +23,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -91,9 +90,8 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -107,8 +105,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= @@ -167,8 +165,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -182,8 +180,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -211,8 +209,9 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= diff --git a/api/lock_test.go b/api/lock_test.go index 4003a94632f8..ee59a01abcef 100644 --- a/api/lock_test.go +++ b/api/lock_test.go @@ -13,10 +13,11 @@ import ( "testing" "time" + "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" ) -func createTestLock(t *testing.T, c *Client, key string) (*Lock, *Session) { +func createTestLock(t testutil.TestingTB, c *Client, key string) (*Lock, *Session) { t.Helper() session := c.Session() @@ -106,7 +107,7 @@ func TestAPI_LockForceInvalidate(t *testing.T) { defer s.Stop() retry.Run(t, func(r *retry.R) { - lock, session := createTestLock(t, c, "test/lock") + lock, session := createTestLock(r, c, "test/lock") defer session.Destroy(lock.opts.Session, nil) // Should work diff --git a/api/partition.go b/api/partition.go index 8467c3118966..8a9bfb482fcc 100644 --- a/api/partition.go +++ b/api/partition.go @@ -27,6 +27,9 @@ type Partition struct { // ModifyIndex is the latest Raft index at which the Partition was modified. ModifyIndex uint64 `json:"ModifyIndex,omitempty"` + + // DisableGossip will not enable a gossip pool for the partition + DisableGossip bool `json:"DisableGossip,omitempty"` } // PartitionDefaultName is the default partition value. diff --git a/api/raw.go b/api/raw.go index 639513d29fa8..7fb9c390c935 100644 --- a/api/raw.go +++ b/api/raw.go @@ -25,3 +25,8 @@ func (raw *Raw) Query(endpoint string, out interface{}, q *QueryOptions) (*Query func (raw *Raw) Write(endpoint string, in, out interface{}, q *WriteOptions) (*WriteMeta, error) { return raw.c.write(endpoint, in, out, q) } + +// Delete is used to do a DELETE request against an endpoint +func (raw *Raw) Delete(endpoint string, q *QueryOptions) (*WriteMeta, error) { + return raw.c.delete(endpoint, q) +} diff --git a/api/raw_test.go b/api/raw_test.go new file mode 100644 index 000000000000..3f48dfb736a5 --- /dev/null +++ b/api/raw_test.go @@ -0,0 +1,72 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package api + +import ( + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/sdk/testutil" +) + +type V2WriteRequest struct { + Data map[string]any `json:"data"` +} + +type V2WriteResponse struct { + ID struct { + Name string `json:"name"` + } `json:"id"` + Data map[string]any `json:"data"` +} + +// We are testing a v2 endpoint here in the v1 api module as a temporary measure to +// support v2 CRUD operations, until we have a final design for v2 api clients. +func TestAPI_RawV2ExportedServices(t *testing.T) { + t.Parallel() + c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { + conf.EnableDebug = true + }) + + defer s.Stop() + + endpoint := strings.ToLower(fmt.Sprintf("/api/multicluster/v2/exportedservices/e1")) + wResp := &V2WriteResponse{} + + wReq := &V2WriteRequest{ + Data: map[string]any{ + "consumers": []map[string]any{ + {"peer": "p1"}, + }, + "services": []string{"s1"}, + }, + } + + _, err := c.Raw().Write(endpoint, wReq, wResp, &WriteOptions{Datacenter: "dc1"}) + require.NoError(t, err) + require.NotEmpty(t, wResp.ID.Name) + + qOpts := &QueryOptions{Datacenter: "dc1"} + + var out map[string]interface{} + _, err = c.Raw().Query(endpoint, &out, qOpts) + require.NoError(t, err) + + require.Equal(t, map[string]any{ + "consumers": []any{ + map[string]any{"peer": "p1"}, + }, + "services": []any{"s1"}, + }, out["data"]) + + _, err = c.Raw().Delete(endpoint, qOpts) + require.NoError(t, err) + + out = make(map[string]interface{}) + _, err = c.Raw().Query(endpoint, &out, qOpts) + require.ErrorContains(t, err, "404") +} diff --git a/build-support/docker/Build-Go.dockerfile b/build-support/docker/Build-Go.dockerfile index 884bc4894af3..044f7439fcad 100644 --- a/build-support/docker/Build-Go.dockerfile +++ b/build-support/docker/Build-Go.dockerfile @@ -1,7 +1,7 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: BUSL-1.1 -ARG GOLANG_VERSION=1.20.10 -FROM golang:${GOLANG_VERSION} +ARG GOLANG_VERSION +FROM golang:${GOLANG_VERSION}-alpine3.19 WORKDIR /consul diff --git a/build-support/functions/10-util.sh b/build-support/functions/10-util.sh index 4bb9f35a9f38..8cbcb11c68b0 100644 --- a/build-support/functions/10-util.sh +++ b/build-support/functions/10-util.sh @@ -667,3 +667,21 @@ function go_mod_assert { fi return 0 } + +function get_consul_module_versions { + local module_directories + module_directories=( "." "api" "envoyextensions" "proto-public" "sdk" "troubleshoot") + for module_dir in "${module_directories[@]}"; do + echo "Module versions for directory: '$module_dir':" + echo "--------------" + (cd "$module_dir" && go list -m all | grep -e github.com/hashicorp/consul/api \ + -e github.com/hashicorp/consul/envoyextensions \ + -e github.com/hashicorp/consul/proto-public \ + -e github.com/hashicorp/consul/sdk \ + -e github.com/hashicorp/consul/troubleshoot \ + | if [ "$module_dir" != "." ]; then grep -v "consul/$module_dir"; else cat; fi) + echo "--------------" + echo "" + done + return 0 +} diff --git a/build-support/scripts/consul-module-versions-in-consul.sh b/build-support/scripts/consul-module-versions-in-consul.sh new file mode 100755 index 000000000000..46941d2413c1 --- /dev/null +++ b/build-support/scripts/consul-module-versions-in-consul.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + + +readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})" +readonly SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" +readonly SOURCE_DIR="$(dirname "$(dirname "${SCRIPT_DIR}")")" +readonly FN_DIR="$(dirname "${SCRIPT_DIR}")/functions" + +source "${SCRIPT_DIR}/functions.sh" + +function usage { +cat <<-EOF +Usage: ${SCRIPT_NAME} [] + +Description: + + This script reports the consul module versions in each of the go.mod files in the Consul repository. + +Options: + -h | --help Print this help text. +EOF +} + +function err_usage { + err "$1" + err "" + err "$(usage)" +} + +function main { + while test $# -gt 0 + do + case "$1" in + -h | --help ) + usage + return 0 + ;; + *) + err_usage "ERROR: Unknown argument: '$1'" + return 1 + ;; + esac + done + + get_consul_module_versions || return 1 + + return 0 +} + +main "$@" +exit $? + diff --git a/build-support/scripts/devtools.sh b/build-support/scripts/devtools.sh index b4cf687460d2..3dde6b7ea101 100755 --- a/build-support/scripts/devtools.sh +++ b/build-support/scripts/devtools.sh @@ -25,6 +25,7 @@ Options: -protobuf Just install tools for protobuf. -lint Just install tools for linting. -codegen Just install tools for codegen. + -pre-commit Just install pre-commit. -h | --help Print this help text. EOF } @@ -51,6 +52,10 @@ function main { codegen_install return 0 ;; + -pre-commit ) + pre_commit_install + return 0 + ;; -h | --help ) usage return 0 @@ -127,6 +132,8 @@ function proto_tools_install { install_local_protoc_generator "${SOURCE_DIR}/internal/tools/protoc-gen-consul-rate-limit" install_local_protoc_generator "${SOURCE_DIR}/internal/resource/protoc-gen-resource-types" + + install_local_protoc_generator "${SOURCE_DIR}/internal/tools/protoc-gen-grpc-clone" install_local_protoc_generator "${SOURCE_DIR}/internal/resource/protoc-gen-json-shim" @@ -136,12 +143,20 @@ function proto_tools_install { } function lint_install { + local lint_consul_retry_version + lint_consul_retry_version="$(make --no-print-directory print-LINT_CONSUL_RETRY_VERSION)" + local golangci_lint_version golangci_lint_version="$(make --no-print-directory print-GOLANGCI_LINT_VERSION)" - install_unversioned_tool \ + local gci_version + gci_version="$(make --no-print-directory print-GCI_VERSION)" + + install_versioned_tool \ 'lint-consul-retry' \ - 'github.com/hashicorp/lint-consul-retry@master' + 'github.com/hashicorp/lint-consul-retry' \ + "${lint_consul_retry_version}" \ + 'github.com/hashicorp/lint-consul-retry' install_unversioned_tool \ 'enumcover' \ @@ -152,6 +167,12 @@ function lint_install { 'github.com/golangci/golangci-lint' \ "${golangci_lint_version}" \ 'github.com/golangci/golangci-lint/cmd/golangci-lint' + + install_versioned_tool \ + 'gci' \ + 'github.com/daixiang0/gci' \ + "${gci_version}" \ + 'github.com/daixiang0/gci' } function codegen_install { @@ -181,11 +202,50 @@ function copywrite_install { 'github.com/hashicorp/copywrite' } -function tools_install { +function pre_commit_install { + # if already installed make sure the hook is also installed + if command -v "pre-commit" &>/dev/null; then + # Not to be confused with installing the tool, this installs + # the git hook locally (.git/hooks/pre-commit) which pre-commit + # uses as a vector to run checks on `git commit`. This hook is + # generated based on the local environment hence not source + # controlled. + pre-commit install + return 0 + fi + # Install options based on https://pre-commit.com/#installation + if command -v "brew" &>/dev/null; then + brew install pre-commit && pre-commit install + return 0 + fi + + # Try python regardless of platform (mac, linux, etc) + if command -v "pip3" &>/dev/null; then + pip3 install pre-commit && pre-commit install + return 0 + fi + + # Can't disappoint the linux/debian folks + if command -v "apt" &>/dev/null; then + sudo apt-get install -yq pre-commit && pre-commit install + return 0 + fi + + if [[ "$(uname)" == "Darwin" ]]; then + echo "ERROR: Install homebrew from https://brew.sh/ so that pre-commit (https://pre-commit.com) can be installed." + return 1 + fi + + echo "ERROR: Install python3 and pip3 so that pre-commit (https://pre-commit.com) can be installed." + return 1 +} + +function tools_install { lint_install proto_tools_install codegen_install + pre_commit_install copywrite_install return 0 diff --git a/build-support/scripts/gen-changelog.sh b/build-support/scripts/gen-changelog.sh new file mode 100755 index 000000000000..3690f24e9ba6 --- /dev/null +++ b/build-support/scripts/gen-changelog.sh @@ -0,0 +1,80 @@ +#! /bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +set -eo pipefail + +pr_number=$(gh pr list -H "$(git rev-parse --abbrev-ref HEAD)" -q ".[0].number" --json "number") + +if [ -z "$pr_number" ]; then + echo "Error: Could not find PR number." + exit 1 +fi + +# check if this changelog is referencing an enterprise change +curdir=$(pwd) + +filename=".changelog/$pr_number.txt" +if [[ ! $curdir == *"enterprise"* ]]; then + is_enterprise="n" + read -rp "Is this an enterprise PR? (y/n): " is_enterprise + + if [[ $is_enterprise == "y" ]]; then + filename=".changelog/_$pr_number.txt" + fi +else + filename=".changelog/_$pr_number.txt" +fi + +# create a new changelog file +touch "$filename" + +echo "Created a new changelog file for PR $pr_number." + +# prompt user to pick from list of types of changlog from "breaking-change", "security", "feature", "deprecation", or "bug" +echo "Please select the type of change:" +echo "1. breaking-change" +echo "2. security" +echo "3. feature" +echo "4. deprecation" +echo "5. bug" + +if [ -z "$1" ]; then + read -rp "Enter your choice: " choice +else + choice=$1 +fi + +type="" + +case $choice in +1) + type="breaking-change" + ;; +2) + type="security" + ;; +3) + type="feature" + ;; +4) + type="deprecation" + ;; +5) + type="bug" + ;; +*) + echo "Invalid choice. Please select a number from 1 to 5." + exit 1 + ;; +esac + +msg="" + +read -erp $'Please enter the changelog message:\n' msg + +echo -e "\`\`\`release-note:$type\n$msg\n\`\`\`" >>"$filename" + +echo -e "\nChangelog added to $filename. Contents:\n" + +cat "$filename" diff --git a/command/acl/acl_helpers.go b/command/acl/acl_helpers.go index 9dd40e9e0ee6..a847f979fb63 100644 --- a/command/acl/acl_helpers.go +++ b/command/acl/acl_helpers.go @@ -105,6 +105,10 @@ func GetPolicyIDByName(client *api.Client, name string) (string, error) { return "", err } + if policy == nil { + return "", fmt.Errorf("No such policy with name: %s", name) + } + return policy.ID, nil } diff --git a/command/acl/acl_test.go b/command/acl/acl_test.go index c2a46f18b042..cc172b3631db 100644 --- a/command/acl/acl_test.go +++ b/command/acl/acl_test.go @@ -48,6 +48,36 @@ func Test_GetPolicyIDByName_Builtins(t *testing.T) { } } +func Test_GetPolicyIDByName_NotFound(t *testing.T) { + t.Parallel() + + a := agent.StartTestAgent(t, + agent.TestAgent{ + LogOutput: io.Discard, + HCL: ` + primary_datacenter = "dc1" + acl { + enabled = true + tokens { + initial_management = "root" + } + } + `, + }, + ) + + defer a.Shutdown() + testrpc.WaitForTestAgent(t, a.RPC, "dc1", testrpc.WithToken("root")) + + client := a.Client() + client.AddHeader("X-Consul-Token", "root") + + id, err := GetPolicyIDByName(client, "not_found") + require.Error(t, err) + require.Equal(t, "", id) + +} + func Test_GetPolicyIDFromPartial_Builtins(t *testing.T) { t.Parallel() diff --git a/command/acl/bindingrule/create/bindingrule_create.go b/command/acl/bindingrule/create/bindingrule_create.go index ab6a16f3ed5c..0b09a5eb2f0c 100644 --- a/command/acl/bindingrule/create/bindingrule_create.go +++ b/command/acl/bindingrule/create/bindingrule_create.go @@ -73,7 +73,7 @@ func (c *cmd) init() { &c.bindType, "bind-type", string(api.BindingRuleBindTypeService), - "Type of binding to perform (\"service\", \"role\", \"node\" or \"templated-policy\").", + "Type of binding to perform (\"service\", \"role\", \"node\", \"policy\", or \"templated-policy\").", ) c.flags.Var( (*flags.FlagMapValue)(&c.bindVars), diff --git a/command/acl/bindingrule/update/bindingrule_update.go b/command/acl/bindingrule/update/bindingrule_update.go index ce7006748728..40c03cab546e 100644 --- a/command/acl/bindingrule/update/bindingrule_update.go +++ b/command/acl/bindingrule/update/bindingrule_update.go @@ -77,7 +77,7 @@ func (c *cmd) init() { &c.bindType, "bind-type", string(api.BindingRuleBindTypeService), - "Type of binding to perform (\"service\" or \"role\").", + "Type of binding to perform (\"service\", \"policy\", or \"role\").", ) c.flags.StringVar( &c.bindName, diff --git a/command/acl/bindingrule/update/bindingrule_update_test.go b/command/acl/bindingrule/update/bindingrule_update_test.go index 1bbcd35cc25d..c873aadcb489 100644 --- a/command/acl/bindingrule/update/bindingrule_update_test.go +++ b/command/acl/bindingrule/update/bindingrule_update_test.go @@ -242,6 +242,39 @@ func TestBindingRuleUpdateCommand(t *testing.T) { require.Equal(t, "serviceaccount.namespace==alt and serviceaccount.name==demo", rule.Selector) }) + t.Run("update all fields with policy", func(t *testing.T) { + id := createRule(t, false) + + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-token=root", + "-id", id, + "-description=test rule edited", + "-bind-type", "policy", + "-bind-name=policy-updated", + "-selector=serviceaccount.namespace==alt and serviceaccount.name==demo", + } + + code := cmd.Run(args) + require.Equal(t, code, 0, "err: %s", ui.ErrorWriter.String()) + require.Empty(t, ui.ErrorWriter.String()) + + rule, _, err := client.ACL().BindingRuleRead( + id, + &api.QueryOptions{Token: "root"}, + ) + require.NoError(t, err) + require.NotNil(t, rule) + + require.Equal(t, "test rule edited", rule.Description) + require.Equal(t, "policy-updated", rule.BindName) + require.Equal(t, api.BindingRuleBindTypePolicy, rule.BindType) + require.Equal(t, "serviceaccount.namespace==alt and serviceaccount.name==demo", rule.Selector) + }) + t.Run("update all fields with templated policy", func(t *testing.T) { id := createRule(t, false) diff --git a/command/acl/templatedpolicy/formatter.go b/command/acl/templatedpolicy/formatter.go index dec8378bcc5f..e71b52a37550 100644 --- a/command/acl/templatedpolicy/formatter.go +++ b/command/acl/templatedpolicy/formatter.go @@ -65,18 +65,17 @@ func (f *prettyFormatter) FormatTemplatedPolicy(templatedPolicy api.ACLTemplated var buffer bytes.Buffer buffer.WriteString(fmt.Sprintf("Name: %s\n", templatedPolicy.TemplateName)) + buffer.WriteString(fmt.Sprintf("Description: %s\n", templatedPolicy.Description)) buffer.WriteString("Input variables:") switch templatedPolicy.TemplateName { case api.ACLTemplatedPolicyServiceName: - buffer.WriteString(fmt.Sprintf("\n%sName: String - Required - The name of the service.\n", WhitespaceIndent)) - buffer.WriteString("Example usage:\n") - buffer.WriteString(WhitespaceIndent + "consul acl token create -templated-policy builtin/service -var name:api\n") + nameRequiredVariableOutput(&buffer, templatedPolicy.TemplateName, "The name of the service", "api") case api.ACLTemplatedPolicyNodeName: - buffer.WriteString(fmt.Sprintf("\n%sName: String - Required - The node name.\n", WhitespaceIndent)) - buffer.WriteString("Example usage:\n") - buffer.WriteString(fmt.Sprintf("%sconsul acl token create -templated-policy builtin/node -var name:node-1\n", WhitespaceIndent)) - case api.ACLTemplatedPolicyDNSName, api.ACLTemplatedPolicyNomadServerName: + nameRequiredVariableOutput(&buffer, templatedPolicy.TemplateName, "The node name", "node-1") + case api.ACLTemplatedPolicyAPIGatewayName: + nameRequiredVariableOutput(&buffer, templatedPolicy.TemplateName, "The api gateway service name", "api-gateway") + case api.ACLTemplatedPolicyDNSName, api.ACLTemplatedPolicyNomadServerName, api.ACLTemplatedPolicyNomadClientName: noRequiredVariablesOutput(&buffer, templatedPolicy.TemplateName) default: buffer.WriteString(" None\n") @@ -98,6 +97,12 @@ func noRequiredVariablesOutput(buffer *bytes.Buffer, templateName string) { buffer.WriteString(fmt.Sprintf("%sconsul acl token create -templated-policy %s\n", WhitespaceIndent, templateName)) } +func nameRequiredVariableOutput(buffer *bytes.Buffer, templateName, description, exampleName string) { + buffer.WriteString(fmt.Sprintf("\n%sName: String - Required - %s.\n", WhitespaceIndent, description)) + buffer.WriteString("Example usage:\n") + buffer.WriteString(fmt.Sprintf("%sconsul acl token create -templated-policy %s -var name:%s\n", WhitespaceIndent, templateName, exampleName)) +} + func (f *prettyFormatter) FormatTemplatedPolicyList(policies map[string]api.ACLTemplatedPolicyResponse) (string, error) { var buffer bytes.Buffer diff --git a/command/acl/templatedpolicy/formatter_test.go b/command/acl/templatedpolicy/formatter_test.go index aa00854980b4..fe2e11d8fd07 100644 --- a/command/acl/templatedpolicy/formatter_test.go +++ b/command/acl/templatedpolicy/formatter_test.go @@ -37,6 +37,7 @@ func testFormatTemplatedPolicy(t *testing.T, dirPath string) { TemplateName: api.ACLTemplatedPolicyNodeName, Schema: structs.ACLTemplatedPolicyNodeSchema, Template: structs.ACLTemplatedPolicyNode, + Description: structs.ACLTemplatedPolicyNodeDescription, }, }, "dns-templated-policy": { @@ -44,6 +45,7 @@ func testFormatTemplatedPolicy(t *testing.T, dirPath string) { TemplateName: api.ACLTemplatedPolicyDNSName, Schema: structs.ACLTemplatedPolicyNoRequiredVariablesSchema, Template: structs.ACLTemplatedPolicyDNS, + Description: structs.ACLTemplatedPolicyDNSDescription, }, }, "service-templated-policy": { @@ -51,6 +53,7 @@ func testFormatTemplatedPolicy(t *testing.T, dirPath string) { TemplateName: api.ACLTemplatedPolicyServiceName, Schema: structs.ACLTemplatedPolicyServiceSchema, Template: structs.ACLTemplatedPolicyService, + Description: structs.ACLTemplatedPolicyServiceDescription, }, }, "nomad-server-templated-policy": { @@ -58,6 +61,15 @@ func testFormatTemplatedPolicy(t *testing.T, dirPath string) { TemplateName: api.ACLTemplatedPolicyNomadServerName, Schema: structs.ACLTemplatedPolicyNoRequiredVariablesSchema, Template: structs.ACLTemplatedPolicyNomadServer, + Description: structs.ACLTemplatedPolicyNomadServerDescription, + }, + }, + "nomad-client-templated-policy": { + templatedPolicy: api.ACLTemplatedPolicyResponse{ + TemplateName: api.ACLTemplatedPolicyNomadClientName, + Schema: structs.ACLTemplatedPolicyNoRequiredVariablesSchema, + Template: structs.ACLTemplatedPolicyNomadClient, + Description: structs.ACLTemplatedPolicyNomadClientDescription, }, }, } @@ -98,16 +110,19 @@ func testFormatTemplatedPolicyList(t *testing.T, dirPath string) { TemplateName: api.ACLTemplatedPolicyNodeName, Schema: structs.ACLTemplatedPolicyNodeSchema, Template: structs.ACLTemplatedPolicyNode, + Description: structs.ACLTemplatedPolicyNodeDescription, }, "builtin/dns": { TemplateName: api.ACLTemplatedPolicyDNSName, Schema: structs.ACLTemplatedPolicyNoRequiredVariablesSchema, Template: structs.ACLTemplatedPolicyDNS, + Description: structs.ACLTemplatedPolicyDNSDescription, }, "builtin/service": { TemplateName: api.ACLTemplatedPolicyServiceName, Schema: structs.ACLTemplatedPolicyServiceSchema, Template: structs.ACLTemplatedPolicyService, + Description: structs.ACLTemplatedPolicyServiceDescription, }, } diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.json.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.json.golden index 36682729f1cb..98073893df79 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.json.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.json.golden @@ -1,5 +1,6 @@ { "TemplateName": "builtin/dns", "Schema": "", - "Template": "\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}\nquery_prefix \"\" {\n\tpolicy = \"read\"\n}" + "Template": "\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}\nquery_prefix \"\" {\n\tpolicy = \"read\"\n}", + "Description": "Gives the token or role permissions for the Consul DNS to query services in the network." } \ No newline at end of file diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty-meta.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty-meta.golden index a30a0c535547..f296c9b578e7 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty-meta.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty-meta.golden @@ -1,4 +1,5 @@ Name: builtin/dns +Description: Gives the token or role permissions for the Consul DNS to query services in the network. Input variables: None Example usage: consul acl token create -templated-policy builtin/dns diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty.golden index f52cfdfe1dfc..26afd29a4fd4 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/dns-templated-policy.pretty.golden @@ -1,4 +1,5 @@ Name: builtin/dns +Description: Gives the token or role permissions for the Consul DNS to query services in the network. Input variables: None Example usage: consul acl token create -templated-policy builtin/dns diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.json.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.json.golden index 22981af04666..3fd3b495fe13 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.json.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.json.golden @@ -1,5 +1,6 @@ { "TemplateName": "builtin/node", "Schema": "{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"name\": { \"type\": \"string\", \"$ref\": \"#/definitions/min-length-one\" }\n\t},\n\t\"required\": [\"name\"],\n\t\"definitions\": {\n\t\t\"min-length-one\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"minLength\": 1\n\t\t}\n\t}\n}", - "Template": "\nnode \"{{.Name}}\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}" + "Template": "\nnode \"{{.Name}}\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}", + "Description": "Gives the token or role permissions for a register an agent/node into the catalog. A node is typically a consul agent but can also be a physical server, cloud instance or a container." } \ No newline at end of file diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty-meta.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty-meta.golden index fda0d9559e37..1066fae0485a 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty-meta.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty-meta.golden @@ -1,4 +1,5 @@ Name: builtin/node +Description: Gives the token or role permissions for a register an agent/node into the catalog. A node is typically a consul agent but can also be a physical server, cloud instance or a container. Input variables: Name: String - Required - The node name. Example usage: diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty.golden index a923087028c0..099cb3106494 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/node-templated-policy.pretty.golden @@ -1,4 +1,5 @@ Name: builtin/node +Description: Gives the token or role permissions for a register an agent/node into the catalog. A node is typically a consul agent but can also be a physical server, cloud instance or a container. Input variables: Name: String - Required - The node name. Example usage: diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-client-templated-policy.json.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-client-templated-policy.json.golden new file mode 100644 index 000000000000..00d361fac806 --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-client-templated-policy.json.golden @@ -0,0 +1,6 @@ +{ + "TemplateName": "builtin/nomad-client", + "Schema": "", + "Template": "agent_prefix \"\" {\n policy = \"read\"\n}\nnode_prefix \"\" {\n policy = \"read\"\n}\nservice_prefix \"\" {\n policy = \"write\"\n}\nkey_prefix \"\" {\n policy = \"read\"\n}", + "Description": "Gives the token or role permissions required for integration with a nomad client." +} \ No newline at end of file diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-client-templated-policy.pretty-meta.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-client-templated-policy.pretty-meta.golden new file mode 100644 index 000000000000..bb8053bcc229 --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-client-templated-policy.pretty-meta.golden @@ -0,0 +1,18 @@ +Name: builtin/nomad-client +Description: Gives the token or role permissions required for integration with a nomad client. +Input variables: None +Example usage: + consul acl token create -templated-policy builtin/nomad-client +Raw Template: +agent_prefix "" { + policy = "read" +} +node_prefix "" { + policy = "read" +} +service_prefix "" { + policy = "write" +} +key_prefix "" { + policy = "read" +} diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-client-templated-policy.pretty.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-client-templated-policy.pretty.golden new file mode 100644 index 000000000000..6dd152d4985c --- /dev/null +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-client-templated-policy.pretty.golden @@ -0,0 +1,5 @@ +Name: builtin/nomad-client +Description: Gives the token or role permissions required for integration with a nomad client. +Input variables: None +Example usage: + consul acl token create -templated-policy builtin/nomad-client diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-server-templated-policy.json.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-server-templated-policy.json.golden index 7c9981e7f8c9..871b26dac349 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-server-templated-policy.json.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-server-templated-policy.json.golden @@ -1,5 +1,6 @@ { "TemplateName": "builtin/nomad-server", "Schema": "", - "Template": "\nacl = \"write\"\nagent_prefix \"\" {\n policy = \"read\"\n}\nnode_prefix \"\" {\n policy = \"read\"\n}\nservice_prefix \"\" {\n policy = \"write\"\n}" + "Template": "\nacl = \"write\"\nagent_prefix \"\" {\n policy = \"read\"\n}\nnode_prefix \"\" {\n policy = \"read\"\n}\nservice_prefix \"\" {\n policy = \"write\"\n}", + "Description": "Gives the token or role permissions required for integration with a nomad server." } \ No newline at end of file diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-server-templated-policy.pretty-meta.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-server-templated-policy.pretty-meta.golden index be000cce1d5c..60c196115180 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-server-templated-policy.pretty-meta.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-server-templated-policy.pretty-meta.golden @@ -1,4 +1,5 @@ Name: builtin/nomad-server +Description: Gives the token or role permissions required for integration with a nomad server. Input variables: None Example usage: consul acl token create -templated-policy builtin/nomad-server diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-server-templated-policy.pretty.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-server-templated-policy.pretty.golden index d4943665e78b..e65d016320a6 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-server-templated-policy.pretty.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/nomad-server-templated-policy.pretty.golden @@ -1,4 +1,5 @@ Name: builtin/nomad-server +Description: Gives the token or role permissions required for integration with a nomad server. Input variables: None Example usage: consul acl token create -templated-policy builtin/nomad-server diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.json.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.json.golden index e4b71de9b840..0cd714893ed8 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.json.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.json.golden @@ -1,5 +1,6 @@ { "TemplateName": "builtin/service", "Schema": "{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"name\": { \"type\": \"string\", \"$ref\": \"#/definitions/min-length-one\" }\n\t},\n\t\"required\": [\"name\"],\n\t\"definitions\": {\n\t\t\"min-length-one\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"minLength\": 1\n\t\t}\n\t}\n}", - "Template": "\nservice \"{{.Name}}\" {\n\tpolicy = \"write\"\n}\nservice \"{{.Name}}-sidecar-proxy\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}" + "Template": "\nservice \"{{.Name}}\" {\n\tpolicy = \"write\"\n}\nservice \"{{.Name}}-sidecar-proxy\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}", + "Description": "Gives the token or role permissions to register a service and discover services in the Consul catalog. It also gives the specified service's sidecar proxy the permission to discover and route traffic to other services." } \ No newline at end of file diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty-meta.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty-meta.golden index f3ae5c6d7be2..bcb0f8c26bdd 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty-meta.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty-meta.golden @@ -1,4 +1,5 @@ Name: builtin/service +Description: Gives the token or role permissions to register a service and discover services in the Consul catalog. It also gives the specified service's sidecar proxy the permission to discover and route traffic to other services. Input variables: Name: String - Required - The name of the service. Example usage: diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty.golden index bc3ffcfd25e0..0c0b545b6349 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicy/ce/service-templated-policy.pretty.golden @@ -1,4 +1,5 @@ Name: builtin/service +Description: Gives the token or role permissions to register a service and discover services in the Consul catalog. It also gives the specified service's sidecar proxy the permission to discover and route traffic to other services. Input variables: Name: String - Required - The name of the service. Example usage: diff --git a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicyList/ce/list.json.golden b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicyList/ce/list.json.golden index b634ddc9d8f4..af63cec4fc4d 100644 --- a/command/acl/templatedpolicy/testdata/FormatTemplatedPolicyList/ce/list.json.golden +++ b/command/acl/templatedpolicy/testdata/FormatTemplatedPolicyList/ce/list.json.golden @@ -2,16 +2,19 @@ "builtin/dns": { "TemplateName": "builtin/dns", "Schema": "", - "Template": "\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}\nquery_prefix \"\" {\n\tpolicy = \"read\"\n}" + "Template": "\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}\nquery_prefix \"\" {\n\tpolicy = \"read\"\n}", + "Description": "Gives the token or role permissions for the Consul DNS to query services in the network." }, "builtin/node": { "TemplateName": "builtin/node", "Schema": "{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"name\": { \"type\": \"string\", \"$ref\": \"#/definitions/min-length-one\" }\n\t},\n\t\"required\": [\"name\"],\n\t\"definitions\": {\n\t\t\"min-length-one\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"minLength\": 1\n\t\t}\n\t}\n}", - "Template": "\nnode \"{{.Name}}\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}" + "Template": "\nnode \"{{.Name}}\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}", + "Description": "Gives the token or role permissions for a register an agent/node into the catalog. A node is typically a consul agent but can also be a physical server, cloud instance or a container." }, "builtin/service": { "TemplateName": "builtin/service", "Schema": "{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"name\": { \"type\": \"string\", \"$ref\": \"#/definitions/min-length-one\" }\n\t},\n\t\"required\": [\"name\"],\n\t\"definitions\": {\n\t\t\"min-length-one\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"minLength\": 1\n\t\t}\n\t}\n}", - "Template": "\nservice \"{{.Name}}\" {\n\tpolicy = \"write\"\n}\nservice \"{{.Name}}-sidecar-proxy\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}" + "Template": "\nservice \"{{.Name}}\" {\n\tpolicy = \"write\"\n}\nservice \"{{.Name}}-sidecar-proxy\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n}\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}", + "Description": "Gives the token or role permissions to register a service and discover services in the Consul catalog. It also gives the specified service's sidecar proxy the permission to discover and route traffic to other services." } } \ No newline at end of file diff --git a/command/agent/agent.go b/command/agent/agent.go index 84515f2c94bd..b280fbf506f5 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -21,7 +21,7 @@ import ( "github.com/hashicorp/consul/agent" "github.com/hashicorp/consul/agent/config" - hcpbootstrap "github.com/hashicorp/consul/agent/hcp/bootstrap" + hcpbootstrap "github.com/hashicorp/consul/agent/hcp/bootstrap/config-loader" hcpclient "github.com/hashicorp/consul/agent/hcp/client" "github.com/hashicorp/consul/command/cli" "github.com/hashicorp/consul/command/flags" @@ -181,6 +181,8 @@ func (c *cmd) run(args []string) int { ui.Error(err.Error()) return 1 } + + loader = hcpbootstrap.AddAclPolicyAccessControlHeader(loader) } bd, err := agent.NewBaseDeps(loader, logGate, nil) diff --git a/command/config/write/config_write_test.go b/command/config/write/config_write_test.go index 15e7a4746532..ae782c082631 100644 --- a/command/config/write/config_write_test.go +++ b/command/config/write/config_write_test.go @@ -43,7 +43,7 @@ func TestConfigWrite(t *testing.T) { _, err := f.WriteString(` Kind = "service-defaults" Name = "web" - Protocol = "udp" + Protocol = "tcp" `) require.NoError(t, err) @@ -65,7 +65,7 @@ func TestConfigWrite(t *testing.T) { require.True(t, ok) require.Equal(t, api.ServiceDefaults, svc.Kind) require.Equal(t, "web", svc.Name) - require.Equal(t, "udp", svc.Protocol) + require.Equal(t, "tcp", svc.Protocol) }) t.Run("Stdin", func(t *testing.T) { @@ -170,6 +170,27 @@ kind = "proxy-defaults" `Config entry written: proxy-defaults/global`) require.Equal(t, 0, code) }) + + // Test that protocol field is first normalized and then validated + // before writing the config entry + t.Run("service defaults config entry mixed case in protocol field", func(t *testing.T) { + stdin := new(bytes.Buffer) + stdin.WriteString(` + Kind = "service-defaults" + Name = "web" + Protocol = "TcP" +`) + + ui := cli.NewMockUi() + c := New(ui) + c.testStdin = stdin + + code := c.Run([]string{"-http-addr=" + a.HTTPAddr(), "-"}) + require.Empty(t, ui.ErrorWriter.String()) + require.Contains(t, ui.OutputWriter.String(), + `Config entry written: service-defaults/web`) + require.Equal(t, 0, code) + }) } func TestConfigWrite_Warning(t *testing.T) { diff --git a/command/connect/envoy/bootstrap_config.go b/command/connect/envoy/bootstrap_config.go index 452d3679d6f2..e309e6648c23 100644 --- a/command/connect/envoy/bootstrap_config.go +++ b/command/connect/envoy/bootstrap_config.go @@ -251,6 +251,11 @@ func (c *BootstrapConfig) ConfigureArgs(args *BootstrapTplArgs, omitDeprecatedTa // Setup telemetry collector if needed. This MUST happen after the Static*JSON is set above if c.TelemetryCollectorBindSocketDir != "" { + // Override StatsFlushInterval as 60 seconds (1 minute) to reduce number of metric flushes. + // Only perform this override if there is no custom configuration for stats sinks and flush interval. + if c.StatsFlushInterval == "" && args.StatsSinksJSON == "" { + args.StatsFlushInterval = "60s" + } appendTelemetryCollectorConfig(args, c.TelemetryCollectorBindSocketDir) } @@ -648,7 +653,14 @@ func (c *BootstrapConfig) generateListenerConfig(args *BootstrapTplArgs, bindAdd "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "` + clusterName + `", "endpoints": [ @@ -858,7 +870,14 @@ func appendTelemetryCollectorConfig(args *BootstrapTplArgs, telemetryCollectorBi args.StaticClustersJSON += fmt.Sprintf(`{ "name": "consul_telemetry_collector_loopback", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "consul_telemetry_collector_loopback", "endpoints": [ diff --git a/command/connect/envoy/bootstrap_config_test.go b/command/connect/envoy/bootstrap_config_test.go index ef0578634714..27598b93b318 100644 --- a/command/connect/envoy/bootstrap_config_test.go +++ b/command/connect/envoy/bootstrap_config_test.go @@ -5,6 +5,7 @@ package envoy import ( "encoding/json" + "fmt" "reflect" "regexp" "strings" @@ -20,7 +21,14 @@ const ( "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "self_admin", "endpoints": [ @@ -46,7 +54,14 @@ const ( "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "self_admin", "endpoints": [ @@ -72,7 +87,14 @@ const ( "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "prometheus_backend", "endpoints": [ @@ -547,7 +569,14 @@ const ( expectedTelemetryCollectorCluster = `{ "name": "consul_telemetry_collector_loopback", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "consul_telemetry_collector_loopback", "endpoints": [ @@ -628,47 +657,50 @@ func TestBootstrapConfig_ConfigureArgs(t *testing.T) { TelemetryCollectorBindSocketDir: "/tmp/consul/telemetry-collector", }, wantArgs: BootstrapTplArgs{ - ProxyID: "web-sidecar-proxy", - StatsConfigJSON: defaultStatsConfigJSON, - StatsSinksJSON: `{ - "name": "envoy.stat_sinks.metrics_service", - "typed_config": { - "@type": "type.googleapis.com/envoy.config.metrics.v3.MetricsServiceConfig", - "transport_api_version": "V3", - "grpc_service": { - "envoy_grpc": { - "cluster_name": "consul_telemetry_collector_loopback" - } - }, - "emit_tags_as_labels": true - } - }`, - StaticClustersJSON: `{ - "name": "consul_telemetry_collector_loopback", - "type": "STATIC", - "http2_protocol_options": {}, - "loadAssignment": { - "clusterName": "consul_telemetry_collector_loopback", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "pipe": { - "path": "/tmp/consul/telemetry-collector/gqmuzdHCUPAEY5mbF8vgkZCNI14.sock" - } - } - } - } - ] - } - ] - } - }`, + StatsFlushInterval: "60s", + ProxyID: "web-sidecar-proxy", + StatsConfigJSON: defaultStatsConfigJSON, + StatsSinksJSON: expectedTelemetryCollectorStatsSink, + StaticClustersJSON: expectedTelemetryCollectorCluster, }, wantErr: false, }, + { + name: "telemetry-collector-no-default-flush-interval-when-interval-preconfigured", + baseArgs: BootstrapTplArgs{ + ProxyID: "web-sidecar-proxy", + }, + input: BootstrapConfig{ + // Explicitly defined StatsFlushInterval by end user should not be overriden. + StatsFlushInterval: "10s", + TelemetryCollectorBindSocketDir: "/tmp/consul/telemetry-collector", + }, + wantArgs: BootstrapTplArgs{ + StatsFlushInterval: "10s", + ProxyID: "web-sidecar-proxy", + StatsConfigJSON: defaultStatsConfigJSON, + StatsSinksJSON: expectedTelemetryCollectorStatsSink, + StaticClustersJSON: expectedTelemetryCollectorCluster, + }, + }, + { + name: "telemetry-collector-no-default-flush-interval-when-sinks-preconfigured", + baseArgs: BootstrapTplArgs{ + ProxyID: "web-sidecar-proxy", + }, + input: BootstrapConfig{ + // If stats sinks are explicitly defined by end user, do not default StatsFlushInterval. + StatsdURL: "udp://127.0.0.1:9125", + TelemetryCollectorBindSocketDir: "/tmp/consul/telemetry-collector", + }, + wantArgs: BootstrapTplArgs{ + StatsFlushInterval: "", + ProxyID: "web-sidecar-proxy", + StatsConfigJSON: defaultStatsConfigJSON, + StatsSinksJSON: fmt.Sprintf(`%s,%s`, expectedStatsdSink, expectedTelemetryCollectorStatsSink), + StaticClustersJSON: expectedTelemetryCollectorCluster, + }, + }, { name: "simple-statsd-sink", input: BootstrapConfig{ diff --git a/command/connect/envoy/bootstrap_tpl.go b/command/connect/envoy/bootstrap_tpl.go index 4b4bbc8db77f..21634f73ec05 100644 --- a/command/connect/envoy/bootstrap_tpl.go +++ b/command/connect/envoy/bootstrap_tpl.go @@ -161,7 +161,15 @@ type GRPC struct { const bootstrapTemplate = `{ "admin": { {{- if (not .AdminAccessLogConfig) }} - "access_log_path": "{{ .AdminAccessLogPath }}", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "{{ .AdminAccessLogPath }}" + } + } + ], {{- end}} {{- if .AdminAccessLogConfig }} "access_log": [ @@ -220,7 +228,14 @@ const bootstrapTemplate = `{ } }, {{- end }} - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "{{ .LocalAgentClusterName }}", "endpoints": [ diff --git a/command/connect/envoy/envoy.go b/command/connect/envoy/envoy.go index 3489f1017a65..b974a525e9cd 100644 --- a/command/connect/envoy/envoy.go +++ b/command/connect/envoy/envoy.go @@ -1052,7 +1052,7 @@ func checkEnvoyVersionCompatibility(envoyVersion string, unsupportedList []strin // Next build the constraint string using the bounds, make sure that we are less than but not equal to // maxSupported since we will add 1. Need to add one to the max minor version so that we accept all patches - splitS := strings.Split(xdscommon.GetMaxEnvoyMinorVersion(), ".") + splitS := strings.Split(xdscommon.GetMaxEnvoyMajorVersion(), ".") minor, err := strconv.Atoi(splitS[1]) if err != nil { return envoyCompat{}, err @@ -1061,7 +1061,7 @@ func checkEnvoyVersionCompatibility(envoyVersion string, unsupportedList []strin maxSupported := fmt.Sprintf("%s.%d", splitS[0], minor) cs.Reset() - cs.WriteString(fmt.Sprintf(">= %s, < %s", xdscommon.GetMinEnvoyMinorVersion(), maxSupported)) + cs.WriteString(fmt.Sprintf(">= %s, < %s", xdscommon.GetMinEnvoyMajorVersion(), maxSupported)) constraints, err := version.NewConstraint(cs.String()) if err != nil { return envoyCompat{}, err diff --git a/command/connect/envoy/envoy_test.go b/command/connect/envoy/envoy_test.go index 0e61eea1865a..64fd46c15883 100644 --- a/command/connect/envoy/envoy_test.go +++ b/command/connect/envoy/envoy_test.go @@ -137,6 +137,22 @@ type generateConfigTestCase struct { // the logic is. We also allow generating golden files but only for cases that // pass the test of having their template args generated as expected. func TestGenerateConfig(t *testing.T) { + + b, err := os.ReadFile("../../../test/ca/root.cer") + require.NoError(t, err) + + rootPEM := string(b) + rootPEM = strings.Replace(rootPEM, "\n", "\\n", -1) + + b, err = os.ReadFile("../../../test/ca_path/cert1.crt") + require.NoError(t, err) + pathPEM := string(b) + + b, err = os.ReadFile("../../../test/ca_path/cert2.crt") + require.NoError(t, err) + pathPEM += string(b) + pathPEM = strings.Replace(pathPEM, "\n", "\\n", -1) + cases := []generateConfigTestCase{ { Name: "no-args", @@ -499,7 +515,7 @@ func TestGenerateConfig(t *testing.T) { AdminAccessLogPath: "/dev/null", AdminBindAddress: "127.0.0.1", AdminBindPort: "19000", - AgentCAPEM: `-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD\nVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa\nBgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE\nAxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j\nb20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK\nExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl\nc3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU\nmH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU\nd0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG\nxcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg\nU2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f\npFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID\nAQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud\nIwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE\nChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10\nZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ\nAIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h\ngjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9\n2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g\njctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp\nlFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/\nPOLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----\n`, + AgentCAPEM: rootPEM, LocalAgentClusterName: xds.LocalAgentClusterName, PrometheusScrapePath: "/metrics", }, @@ -627,7 +643,7 @@ func TestGenerateConfig(t *testing.T) { AgentPort: "8502", AgentTLS: true, }, - AgentCAPEM: `-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD\nVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa\nBgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE\nAxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j\nb20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK\nExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl\nc3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU\nmH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU\nd0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG\nxcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg\nU2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f\npFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID\nAQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud\nIwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE\nChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10\nZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ\nAIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h\ngjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9\n2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g\njctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp\nlFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/\nPOLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----\n`, + AgentCAPEM: rootPEM, AdminAccessLogPath: "/dev/null", AdminBindAddress: "127.0.0.1", AdminBindPort: "19000", @@ -659,7 +675,7 @@ func TestGenerateConfig(t *testing.T) { AgentPort: "8502", AgentTLS: true, }, - AgentCAPEM: `-----BEGIN CERTIFICATE-----\nMIIFADCCAuqgAwIBAgIBATALBgkqhkiG9w0BAQswEzERMA8GA1UEAxMIQ2VydEF1\ndGgwHhcNMTUwNTExMjI0NjQzWhcNMjUwNTExMjI0NjU0WjATMREwDwYDVQQDEwhD\nZXJ0QXV0aDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALcMByyynHsA\n+K4PJwo5+XHygaEZAhPGvHiKQK2Cbc9NDm0ZTzx0rA/dRTZlvouhDyzcJHm+6R1F\nj6zQv7iaSC3qQtJiPnPsfZ+/0XhFZ3fQWMnfDiGbZpF1kJF01ofB6vnsuocFC0zG\naGC+SZiLAzs+QMP3Bebw1elCBIeoN+8NWnRYmLsYIaYGJGBSbNo/lCpLTuinofUn\nL3ehWEGv1INwpHnSVeN0Ml2GFe23d7PUlj/wNIHgUdpUR+KEJxIP3klwtsI3QpSH\nc4VjWdf4aIcka6K3IFuw+K0PUh3xAAPnMpAQOtCZk0AhF5rlvUbevC6jADxpKxLp\nOONmvCTer4LtyNURAoBH52vbK0r/DNcTpPEFV0IP66nXUFgkk0mRKsu8HTb4IOkC\nX3K4mp18EiWUUtrHZAnNct0iIniDBqKK0yhSNhztG6VakVt/1WdQY9Ey3mNtxN1O\nthqWFKdpKUzPKYC3P6PfVpiE7+VbWTLLXba+8BPe8BxWPsVkjJqGSGnCte4COusz\nM8/7bbTgifwJfsepwFtZG53tvwjWlO46Exl30VoDNTaIGvs1fO0GqJlh2A7FN5F2\nS1rS5VYHtPK8QdmUSvyq+7JDBc1HNT5I2zsIQbNcLwDTZ5EsbU6QR7NHDJKxjv/w\nbs3eTXJSSNcFD74wRU10pXjgE5wOFu9TAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIA\nBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQHazgZ3Puiuc6K2LzgcX5b6fAC\nPzAfBgNVHSMEGDAWgBQHazgZ3Puiuc6K2LzgcX5b6fACPzALBgkqhkiG9w0BAQsD\nggIBAEmeNrSUhpHg1I8dtfqu9hCU/6IZThjtcFA+QcPkkMa+Z1k0SOtsgW8MdlcA\ngCf5g5yQZ0DdpWM9nDB6xDIhQdccm91idHgf8wmpEHUj0an4uyn2ESCt8eqrAWf7\nAClYORCASTYfguJCxcfvwtI1uqaOeCxSOdmFay79UVitVsWeonbCRGsVgBDifJxw\nG2oCQqoYAmXPM4J6syk5GHhB1O9MMq+g1+hOx9s+XHyTui9FL4V+IUO1ygVqEQB5\nPSiRBvcIsajSGVao+vK0gf2XfcXzqr3y3NhBky9rFMp1g+ykb2yWekV4WiROJlCj\nTsWwWZDRyjiGahDbho/XW8JciouHZhJdjhmO31rqW3HdFviCTdXMiGk3GQIzz/Jg\nP+enOaHXoY9lcxzDvY9z1BysWBgNvNrMnVge/fLP9o+a0a0PRIIVl8T0Ef3zeg1O\nCLCSy/1Vae5Tx63ZTFvGFdOSusYkG9rlAUHXZE364JRCKzM9Bz0bM+t+LaO0MaEb\nYoxcXEPU+gB2IvmARpInN3oHexR6ekuYHVTRGdWrdmuHFzc7eFwygRqTFdoCCU+G\nQZEkd+lOEyv0zvQqYg+Jp0AEGz2B2zB53uBVECtn0EqrSdPtRzUBSByXVs6QhSXn\neVmy+z3U3MecP63X6oSPXekqSyZFuegXpNNuHkjNoL4ep2ix\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD\nVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa\nBgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE\nAxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j\nb20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK\nExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl\nc3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU\nmH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU\nd0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG\nxcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg\nU2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f\npFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID\nAQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud\nIwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE\nChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10\nZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ\nAIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h\ngjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9\n2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g\njctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp\nlFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/\nPOLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----\n`, + AgentCAPEM: pathPEM, AdminAccessLogPath: "/dev/null", AdminBindAddress: "127.0.0.1", AdminBindPort: "19000", @@ -677,7 +693,15 @@ func TestGenerateConfig(t *testing.T) { "envoy_bootstrap_json_tpl": ` { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "{{ .AdminBindAddress }}", @@ -919,7 +943,7 @@ func TestGenerateConfig(t *testing.T) { AgentPort: "8502", AgentTLS: true, }, - AgentCAPEM: `-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD\nVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa\nBgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE\nAxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j\nb20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK\nExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl\nc3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU\nmH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU\nd0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG\nxcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg\nU2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f\npFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID\nAQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud\nIwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE\nChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10\nZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ\nAIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h\ngjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9\n2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g\njctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp\nlFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/\nPOLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----\n`, + AgentCAPEM: rootPEM, AdminAccessLogPath: "/dev/null", AdminBindAddress: "127.0.0.1", AdminBindPort: "19000", @@ -976,7 +1000,7 @@ func TestGenerateConfig(t *testing.T) { AgentPort: "8502", AgentTLS: true, }, - AgentCAPEM: `-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD\nVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa\nBgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE\nAxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j\nb20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK\nExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl\nc3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU\nmH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU\nd0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG\nxcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg\nU2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f\npFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID\nAQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud\nIwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE\nChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10\nZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ\nAIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h\ngjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9\n2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g\njctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp\nlFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/\nPOLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----\n`, + AgentCAPEM: rootPEM, AdminAccessLogPath: "/dev/null", AdminBindAddress: "127.0.0.1", AdminBindPort: "19000", @@ -1826,7 +1850,7 @@ func TestCheckEnvoyVersionCompatibility(t *testing.T) { }, { name: "supported-at-max", - envoyVersion: xdscommon.GetMaxEnvoyMinorVersion(), + envoyVersion: xdscommon.GetMaxEnvoyMajorVersion(), unsupportedList: xdscommon.UnsupportedEnvoyVersions, expectedCompat: envoyCompat{ isCompatible: true, diff --git a/command/connect/envoy/exec_test.go b/command/connect/envoy/exec_test.go index e949019e8235..332dd77a4fe7 100644 --- a/command/connect/envoy/exec_test.go +++ b/command/connect/envoy/exec_test.go @@ -355,6 +355,9 @@ func patchExecArgs(t *testing.T) { } func TestMakeBootstrapPipe_DoesNotBlockOnAFullPipe(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } // A named pipe can buffer up to 64k, use a value larger than that bootstrap := bytes.Repeat([]byte("a"), 66000) diff --git a/command/connect/envoy/testdata/CONSUL_GRPC_ADDR-with-https-scheme-enables-tls.golden b/command/connect/envoy/testdata/CONSUL_GRPC_ADDR-with-https-scheme-enables-tls.golden index c8144ac72fa2..0c831cbb370f 100644 --- a/command/connect/envoy/testdata/CONSUL_GRPC_ADDR-with-https-scheme-enables-tls.golden +++ b/command/connect/envoy/testdata/CONSUL_GRPC_ADDR-with-https-scheme-enables-tls.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -40,13 +48,20 @@ "common_tls_context": { "validation_context": { "trusted_ca": { - "inline_string": "-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD\nVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa\nBgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE\nAxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j\nb20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK\nExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl\nc3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU\nmH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU\nd0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG\nxcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg\nU2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f\npFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID\nAQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud\nIwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE\nChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10\nZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ\nAIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h\ngjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9\n2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g\njctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp\nlFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/\nPOLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----\n" + "inline_string": "-----BEGIN CERTIFICATE-----\nMIIEEzCCAvugAwIBAgIUIYIXKNRBFBPuuOit2D2CfVJAoDAwDQYJKoZIhvcNAQEL\nBQAwgZgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZy\nYW5jaXNjbzEcMBoGA1UECgwTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECwwD\nRGV2MRYwFAYDVQQDDA10ZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0\nQGludGVybmFsLmNvbTAeFw0yMzExMDIxNTUwMjlaFw0zMzEwMzAxNTUwMjlaMIGY\nMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFuY2lz\nY28xHDAaBgNVBAoME0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsMA0RldjEW\nMBQGA1UEAwwNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRl\ncm5hbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCIA00iG5Iv\neRzZwf2P1Laih3eoiK2Wl1Re22cz2Pcpf6gb7agPguwU5Hco0DWzsnmek2Qyw9gl\noroX1t7LbTW2rxbK1hP7PkFCwSxi9u8MZDaLF3a79bwbsYZzf3toeoz8DCBxo9bB\nSSACj4uI/S+lUjMctQrK1nFjGoNUHfxioXPwIJH+TS/76TiZPu3Zj6kN6taVFNe3\nISBNXW6Vg8E3koz+9Bwv0a6Ty7oFRoJXpsud1k/83Iy288jhYDuB56+ypUmcCNqG\nT+e0Bn/VXHx26GXTx97cXSLJE+o+JrHZaI1TcQUL2Z5DJZVJRUg/wtcXggoMLVI1\nO0enJm2jdmLXAgMBAAGjUzBRMB0GA1UdDgQWBBTmrmqnZIdFOj6vhCUAJKLZNUDw\nFDAfBgNVHSMEGDAWgBTmrmqnZIdFOj6vhCUAJKLZNUDwFDAPBgNVHRMBAf8EBTAD\nAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB3j6gvalxq54hZSwVmVZPMzjdTVYRC11b0\n6C9pWKsLwu+WINcs59ui8wpYVjcw1AK4/2I1Q7P4RgpSarAxG5tYIMB1xcfFKqBn\nf/dDXexONgwpW6SoBJ58c7OB/aH8CenDT8Vwk3fwjYslOywbFRqBjH+PB8uTlu0e\nD1fzjpcQCrQeA5VD4pjJAaTmi7bLVuH5XIya3++f/N3xOn53GVMUDO1OdFz8ZMvJ\nWrrg7E/wMXB1b5Wo2n2ypVU4sejikSjg2nfdLojUWGMrZ8TuUnjFs88PeQ9CObAp\nA36dLfs4JLF3sVOtqTd6BGwegDsmmllYO5Ky6I+laoLSHpGDEihS\n-----END CERTIFICATE-----\n" } } } } }, - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/CONSUL_HTTP_ADDR-with-https-scheme-does-not-affect-grpc-tls.golden b/command/connect/envoy/testdata/CONSUL_HTTP_ADDR-with-https-scheme-does-not-affect-grpc-tls.golden index a89575d2c167..4b2b178861ae 100644 --- a/command/connect/envoy/testdata/CONSUL_HTTP_ADDR-with-https-scheme-does-not-affect-grpc-tls.golden +++ b/command/connect/envoy/testdata/CONSUL_HTTP_ADDR-with-https-scheme-does-not-affect-grpc-tls.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/access-log-path.golden b/command/connect/envoy/testdata/access-log-path.golden index 184a290b245f..4192419aec89 100644 --- a/command/connect/envoy/testdata/access-log-path.golden +++ b/command/connect/envoy/testdata/access-log-path.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/some/path/access.log", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/some/path/access.log" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/access-logs-enabled-custom.golden b/command/connect/envoy/testdata/access-logs-enabled-custom.golden index 50531f89c257..30b2fd78cdfb 100644 --- a/command/connect/envoy/testdata/access-logs-enabled-custom.golden +++ b/command/connect/envoy/testdata/access-logs-enabled-custom.golden @@ -46,7 +46,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/access-logs-enabled.golden b/command/connect/envoy/testdata/access-logs-enabled.golden index ea2e15060718..191a20a9c486 100644 --- a/command/connect/envoy/testdata/access-logs-enabled.golden +++ b/command/connect/envoy/testdata/access-logs-enabled.golden @@ -68,7 +68,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/acl-enabled-and-token.golden b/command/connect/envoy/testdata/acl-enabled-and-token.golden index a5427c7f2454..2181b174f848 100644 --- a/command/connect/envoy/testdata/acl-enabled-and-token.golden +++ b/command/connect/envoy/testdata/acl-enabled-and-token.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/acl-enabled-but-no-token.golden b/command/connect/envoy/testdata/acl-enabled-but-no-token.golden index a89575d2c167..4b2b178861ae 100644 --- a/command/connect/envoy/testdata/acl-enabled-but-no-token.golden +++ b/command/connect/envoy/testdata/acl-enabled-but-no-token.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-PLAIN-and-CONSUL_GRPC_ADDR-TLS-is-tls.golden b/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-PLAIN-and-CONSUL_GRPC_ADDR-TLS-is-tls.golden index c8144ac72fa2..0c831cbb370f 100644 --- a/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-PLAIN-and-CONSUL_GRPC_ADDR-TLS-is-tls.golden +++ b/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-PLAIN-and-CONSUL_GRPC_ADDR-TLS-is-tls.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -40,13 +48,20 @@ "common_tls_context": { "validation_context": { "trusted_ca": { - "inline_string": "-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD\nVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa\nBgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE\nAxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j\nb20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK\nExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl\nc3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU\nmH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU\nd0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG\nxcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg\nU2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f\npFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID\nAQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud\nIwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE\nChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10\nZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ\nAIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h\ngjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9\n2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g\njctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp\nlFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/\nPOLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----\n" + "inline_string": "-----BEGIN CERTIFICATE-----\nMIIEEzCCAvugAwIBAgIUIYIXKNRBFBPuuOit2D2CfVJAoDAwDQYJKoZIhvcNAQEL\nBQAwgZgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZy\nYW5jaXNjbzEcMBoGA1UECgwTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECwwD\nRGV2MRYwFAYDVQQDDA10ZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0\nQGludGVybmFsLmNvbTAeFw0yMzExMDIxNTUwMjlaFw0zMzEwMzAxNTUwMjlaMIGY\nMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFuY2lz\nY28xHDAaBgNVBAoME0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsMA0RldjEW\nMBQGA1UEAwwNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRl\ncm5hbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCIA00iG5Iv\neRzZwf2P1Laih3eoiK2Wl1Re22cz2Pcpf6gb7agPguwU5Hco0DWzsnmek2Qyw9gl\noroX1t7LbTW2rxbK1hP7PkFCwSxi9u8MZDaLF3a79bwbsYZzf3toeoz8DCBxo9bB\nSSACj4uI/S+lUjMctQrK1nFjGoNUHfxioXPwIJH+TS/76TiZPu3Zj6kN6taVFNe3\nISBNXW6Vg8E3koz+9Bwv0a6Ty7oFRoJXpsud1k/83Iy288jhYDuB56+ypUmcCNqG\nT+e0Bn/VXHx26GXTx97cXSLJE+o+JrHZaI1TcQUL2Z5DJZVJRUg/wtcXggoMLVI1\nO0enJm2jdmLXAgMBAAGjUzBRMB0GA1UdDgQWBBTmrmqnZIdFOj6vhCUAJKLZNUDw\nFDAfBgNVHSMEGDAWgBTmrmqnZIdFOj6vhCUAJKLZNUDwFDAPBgNVHRMBAf8EBTAD\nAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB3j6gvalxq54hZSwVmVZPMzjdTVYRC11b0\n6C9pWKsLwu+WINcs59ui8wpYVjcw1AK4/2I1Q7P4RgpSarAxG5tYIMB1xcfFKqBn\nf/dDXexONgwpW6SoBJ58c7OB/aH8CenDT8Vwk3fwjYslOywbFRqBjH+PB8uTlu0e\nD1fzjpcQCrQeA5VD4pjJAaTmi7bLVuH5XIya3++f/N3xOn53GVMUDO1OdFz8ZMvJ\nWrrg7E/wMXB1b5Wo2n2ypVU4sejikSjg2nfdLojUWGMrZ8TuUnjFs88PeQ9CObAp\nA36dLfs4JLF3sVOtqTd6BGwegDsmmllYO5Ky6I+laoLSHpGDEihS\n-----END CERTIFICATE-----\n" } } } } }, - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-TLS-and-CONSUL_GRPC_ADDR-PLAIN-is-plain.golden b/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-TLS-and-CONSUL_GRPC_ADDR-PLAIN-is-plain.golden index a89575d2c167..4b2b178861ae 100644 --- a/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-TLS-and-CONSUL_GRPC_ADDR-PLAIN-is-plain.golden +++ b/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-TLS-and-CONSUL_GRPC_ADDR-PLAIN-is-plain.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/custom-bootstrap.golden b/command/connect/envoy/testdata/custom-bootstrap.golden index 59bc467f6bf8..ff4eb1d7800c 100644 --- a/command/connect/envoy/testdata/custom-bootstrap.golden +++ b/command/connect/envoy/testdata/custom-bootstrap.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", diff --git a/command/connect/envoy/testdata/defaults-nodemeta.golden b/command/connect/envoy/testdata/defaults-nodemeta.golden index ea65421109f3..2b1cd345f928 100644 --- a/command/connect/envoy/testdata/defaults-nodemeta.golden +++ b/command/connect/envoy/testdata/defaults-nodemeta.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -34,7 +42,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/defaults.golden b/command/connect/envoy/testdata/defaults.golden index a89575d2c167..4b2b178861ae 100644 --- a/command/connect/envoy/testdata/defaults.golden +++ b/command/connect/envoy/testdata/defaults.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/deprecated-grpc-addr-config.golden b/command/connect/envoy/testdata/deprecated-grpc-addr-config.golden index e604c61d5063..dce3671a2fb3 100644 --- a/command/connect/envoy/testdata/deprecated-grpc-addr-config.golden +++ b/command/connect/envoy/testdata/deprecated-grpc-addr-config.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/envoy-readiness-probe.golden b/command/connect/envoy/testdata/envoy-readiness-probe.golden index 18680a3206b3..4fba6db59055 100644 --- a/command/connect/envoy/testdata/envoy-readiness-probe.golden +++ b/command/connect/envoy/testdata/envoy-readiness-probe.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ @@ -59,7 +74,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "self_admin", "endpoints": [ diff --git a/command/connect/envoy/testdata/existing-ca-file.golden b/command/connect/envoy/testdata/existing-ca-file.golden index c8144ac72fa2..0c831cbb370f 100644 --- a/command/connect/envoy/testdata/existing-ca-file.golden +++ b/command/connect/envoy/testdata/existing-ca-file.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -40,13 +48,20 @@ "common_tls_context": { "validation_context": { "trusted_ca": { - "inline_string": "-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD\nVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa\nBgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE\nAxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j\nb20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK\nExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl\nc3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU\nmH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU\nd0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG\nxcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg\nU2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f\npFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID\nAQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud\nIwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE\nChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10\nZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ\nAIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h\ngjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9\n2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g\njctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp\nlFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/\nPOLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----\n" + "inline_string": "-----BEGIN CERTIFICATE-----\nMIIEEzCCAvugAwIBAgIUIYIXKNRBFBPuuOit2D2CfVJAoDAwDQYJKoZIhvcNAQEL\nBQAwgZgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZy\nYW5jaXNjbzEcMBoGA1UECgwTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECwwD\nRGV2MRYwFAYDVQQDDA10ZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0\nQGludGVybmFsLmNvbTAeFw0yMzExMDIxNTUwMjlaFw0zMzEwMzAxNTUwMjlaMIGY\nMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFuY2lz\nY28xHDAaBgNVBAoME0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsMA0RldjEW\nMBQGA1UEAwwNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRl\ncm5hbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCIA00iG5Iv\neRzZwf2P1Laih3eoiK2Wl1Re22cz2Pcpf6gb7agPguwU5Hco0DWzsnmek2Qyw9gl\noroX1t7LbTW2rxbK1hP7PkFCwSxi9u8MZDaLF3a79bwbsYZzf3toeoz8DCBxo9bB\nSSACj4uI/S+lUjMctQrK1nFjGoNUHfxioXPwIJH+TS/76TiZPu3Zj6kN6taVFNe3\nISBNXW6Vg8E3koz+9Bwv0a6Ty7oFRoJXpsud1k/83Iy288jhYDuB56+ypUmcCNqG\nT+e0Bn/VXHx26GXTx97cXSLJE+o+JrHZaI1TcQUL2Z5DJZVJRUg/wtcXggoMLVI1\nO0enJm2jdmLXAgMBAAGjUzBRMB0GA1UdDgQWBBTmrmqnZIdFOj6vhCUAJKLZNUDw\nFDAfBgNVHSMEGDAWgBTmrmqnZIdFOj6vhCUAJKLZNUDwFDAPBgNVHRMBAf8EBTAD\nAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB3j6gvalxq54hZSwVmVZPMzjdTVYRC11b0\n6C9pWKsLwu+WINcs59ui8wpYVjcw1AK4/2I1Q7P4RgpSarAxG5tYIMB1xcfFKqBn\nf/dDXexONgwpW6SoBJ58c7OB/aH8CenDT8Vwk3fwjYslOywbFRqBjH+PB8uTlu0e\nD1fzjpcQCrQeA5VD4pjJAaTmi7bLVuH5XIya3++f/N3xOn53GVMUDO1OdFz8ZMvJ\nWrrg7E/wMXB1b5Wo2n2ypVU4sejikSjg2nfdLojUWGMrZ8TuUnjFs88PeQ9CObAp\nA36dLfs4JLF3sVOtqTd6BGwegDsmmllYO5Ky6I+laoLSHpGDEihS\n-----END CERTIFICATE-----\n" } } } } }, - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/existing-ca-path.golden b/command/connect/envoy/testdata/existing-ca-path.golden index c0566ab351d7..a5386e180d75 100644 --- a/command/connect/envoy/testdata/existing-ca-path.golden +++ b/command/connect/envoy/testdata/existing-ca-path.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -40,13 +48,20 @@ "common_tls_context": { "validation_context": { "trusted_ca": { - "inline_string": "-----BEGIN CERTIFICATE-----\nMIIFADCCAuqgAwIBAgIBATALBgkqhkiG9w0BAQswEzERMA8GA1UEAxMIQ2VydEF1\ndGgwHhcNMTUwNTExMjI0NjQzWhcNMjUwNTExMjI0NjU0WjATMREwDwYDVQQDEwhD\nZXJ0QXV0aDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALcMByyynHsA\n+K4PJwo5+XHygaEZAhPGvHiKQK2Cbc9NDm0ZTzx0rA/dRTZlvouhDyzcJHm+6R1F\nj6zQv7iaSC3qQtJiPnPsfZ+/0XhFZ3fQWMnfDiGbZpF1kJF01ofB6vnsuocFC0zG\naGC+SZiLAzs+QMP3Bebw1elCBIeoN+8NWnRYmLsYIaYGJGBSbNo/lCpLTuinofUn\nL3ehWEGv1INwpHnSVeN0Ml2GFe23d7PUlj/wNIHgUdpUR+KEJxIP3klwtsI3QpSH\nc4VjWdf4aIcka6K3IFuw+K0PUh3xAAPnMpAQOtCZk0AhF5rlvUbevC6jADxpKxLp\nOONmvCTer4LtyNURAoBH52vbK0r/DNcTpPEFV0IP66nXUFgkk0mRKsu8HTb4IOkC\nX3K4mp18EiWUUtrHZAnNct0iIniDBqKK0yhSNhztG6VakVt/1WdQY9Ey3mNtxN1O\nthqWFKdpKUzPKYC3P6PfVpiE7+VbWTLLXba+8BPe8BxWPsVkjJqGSGnCte4COusz\nM8/7bbTgifwJfsepwFtZG53tvwjWlO46Exl30VoDNTaIGvs1fO0GqJlh2A7FN5F2\nS1rS5VYHtPK8QdmUSvyq+7JDBc1HNT5I2zsIQbNcLwDTZ5EsbU6QR7NHDJKxjv/w\nbs3eTXJSSNcFD74wRU10pXjgE5wOFu9TAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIA\nBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQHazgZ3Puiuc6K2LzgcX5b6fAC\nPzAfBgNVHSMEGDAWgBQHazgZ3Puiuc6K2LzgcX5b6fACPzALBgkqhkiG9w0BAQsD\nggIBAEmeNrSUhpHg1I8dtfqu9hCU/6IZThjtcFA+QcPkkMa+Z1k0SOtsgW8MdlcA\ngCf5g5yQZ0DdpWM9nDB6xDIhQdccm91idHgf8wmpEHUj0an4uyn2ESCt8eqrAWf7\nAClYORCASTYfguJCxcfvwtI1uqaOeCxSOdmFay79UVitVsWeonbCRGsVgBDifJxw\nG2oCQqoYAmXPM4J6syk5GHhB1O9MMq+g1+hOx9s+XHyTui9FL4V+IUO1ygVqEQB5\nPSiRBvcIsajSGVao+vK0gf2XfcXzqr3y3NhBky9rFMp1g+ykb2yWekV4WiROJlCj\nTsWwWZDRyjiGahDbho/XW8JciouHZhJdjhmO31rqW3HdFviCTdXMiGk3GQIzz/Jg\nP+enOaHXoY9lcxzDvY9z1BysWBgNvNrMnVge/fLP9o+a0a0PRIIVl8T0Ef3zeg1O\nCLCSy/1Vae5Tx63ZTFvGFdOSusYkG9rlAUHXZE364JRCKzM9Bz0bM+t+LaO0MaEb\nYoxcXEPU+gB2IvmARpInN3oHexR6ekuYHVTRGdWrdmuHFzc7eFwygRqTFdoCCU+G\nQZEkd+lOEyv0zvQqYg+Jp0AEGz2B2zB53uBVECtn0EqrSdPtRzUBSByXVs6QhSXn\neVmy+z3U3MecP63X6oSPXekqSyZFuegXpNNuHkjNoL4ep2ix\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD\nVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa\nBgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE\nAxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j\nb20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK\nExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl\nc3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU\nmH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU\nd0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG\nxcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg\nU2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f\npFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID\nAQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud\nIwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE\nChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10\nZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ\nAIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h\ngjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9\n2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g\njctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp\nlFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/\nPOLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----\n" + "inline_string": "-----BEGIN CERTIFICATE-----\nMIIFADCCAuqgAwIBAgIBATALBgkqhkiG9w0BAQswEzERMA8GA1UEAxMIQ2VydEF1\ndGgwHhcNMTUwNTExMjI0NjQzWhcNMjUwNTExMjI0NjU0WjATMREwDwYDVQQDEwhD\nZXJ0QXV0aDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALcMByyynHsA\n+K4PJwo5+XHygaEZAhPGvHiKQK2Cbc9NDm0ZTzx0rA/dRTZlvouhDyzcJHm+6R1F\nj6zQv7iaSC3qQtJiPnPsfZ+/0XhFZ3fQWMnfDiGbZpF1kJF01ofB6vnsuocFC0zG\naGC+SZiLAzs+QMP3Bebw1elCBIeoN+8NWnRYmLsYIaYGJGBSbNo/lCpLTuinofUn\nL3ehWEGv1INwpHnSVeN0Ml2GFe23d7PUlj/wNIHgUdpUR+KEJxIP3klwtsI3QpSH\nc4VjWdf4aIcka6K3IFuw+K0PUh3xAAPnMpAQOtCZk0AhF5rlvUbevC6jADxpKxLp\nOONmvCTer4LtyNURAoBH52vbK0r/DNcTpPEFV0IP66nXUFgkk0mRKsu8HTb4IOkC\nX3K4mp18EiWUUtrHZAnNct0iIniDBqKK0yhSNhztG6VakVt/1WdQY9Ey3mNtxN1O\nthqWFKdpKUzPKYC3P6PfVpiE7+VbWTLLXba+8BPe8BxWPsVkjJqGSGnCte4COusz\nM8/7bbTgifwJfsepwFtZG53tvwjWlO46Exl30VoDNTaIGvs1fO0GqJlh2A7FN5F2\nS1rS5VYHtPK8QdmUSvyq+7JDBc1HNT5I2zsIQbNcLwDTZ5EsbU6QR7NHDJKxjv/w\nbs3eTXJSSNcFD74wRU10pXjgE5wOFu9TAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIA\nBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQHazgZ3Puiuc6K2LzgcX5b6fAC\nPzAfBgNVHSMEGDAWgBQHazgZ3Puiuc6K2LzgcX5b6fACPzALBgkqhkiG9w0BAQsD\nggIBAEmeNrSUhpHg1I8dtfqu9hCU/6IZThjtcFA+QcPkkMa+Z1k0SOtsgW8MdlcA\ngCf5g5yQZ0DdpWM9nDB6xDIhQdccm91idHgf8wmpEHUj0an4uyn2ESCt8eqrAWf7\nAClYORCASTYfguJCxcfvwtI1uqaOeCxSOdmFay79UVitVsWeonbCRGsVgBDifJxw\nG2oCQqoYAmXPM4J6syk5GHhB1O9MMq+g1+hOx9s+XHyTui9FL4V+IUO1ygVqEQB5\nPSiRBvcIsajSGVao+vK0gf2XfcXzqr3y3NhBky9rFMp1g+ykb2yWekV4WiROJlCj\nTsWwWZDRyjiGahDbho/XW8JciouHZhJdjhmO31rqW3HdFviCTdXMiGk3GQIzz/Jg\nP+enOaHXoY9lcxzDvY9z1BysWBgNvNrMnVge/fLP9o+a0a0PRIIVl8T0Ef3zeg1O\nCLCSy/1Vae5Tx63ZTFvGFdOSusYkG9rlAUHXZE364JRCKzM9Bz0bM+t+LaO0MaEb\nYoxcXEPU+gB2IvmARpInN3oHexR6ekuYHVTRGdWrdmuHFzc7eFwygRqTFdoCCU+G\nQZEkd+lOEyv0zvQqYg+Jp0AEGz2B2zB53uBVECtn0EqrSdPtRzUBSByXVs6QhSXn\neVmy+z3U3MecP63X6oSPXekqSyZFuegXpNNuHkjNoL4ep2ix\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD\nVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa\nBgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE\nAxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j\nb20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK\nExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl\nc3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU\nmH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU\nd0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG\nxcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg\nU2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f\npFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID\nAQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud\nIwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE\nChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10\nZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ\nAIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h\ngjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9\n2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g\njctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp\nlFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/\nPOLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----" } } } } }, - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/extra_-multiple.golden b/command/connect/envoy/testdata/extra_-multiple.golden index 819994f0c0ff..974027b21d3e 100644 --- a/command/connect/envoy/testdata/extra_-multiple.golden +++ b/command/connect/envoy/testdata/extra_-multiple.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/extra_-single.golden b/command/connect/envoy/testdata/extra_-single.golden index b1fb71997b3f..83b07ef5cae0 100644 --- a/command/connect/envoy/testdata/extra_-single.golden +++ b/command/connect/envoy/testdata/extra_-single.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/grpc-addr-env.golden b/command/connect/envoy/testdata/grpc-addr-env.golden index e604c61d5063..dce3671a2fb3 100644 --- a/command/connect/envoy/testdata/grpc-addr-env.golden +++ b/command/connect/envoy/testdata/grpc-addr-env.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/grpc-addr-flag.golden b/command/connect/envoy/testdata/grpc-addr-flag.golden index e604c61d5063..dce3671a2fb3 100644 --- a/command/connect/envoy/testdata/grpc-addr-flag.golden +++ b/command/connect/envoy/testdata/grpc-addr-flag.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/grpc-addr-unix-with-tls.golden b/command/connect/envoy/testdata/grpc-addr-unix-with-tls.golden index 2b902d48d476..c41c67ab7dab 100644 --- a/command/connect/envoy/testdata/grpc-addr-unix-with-tls.golden +++ b/command/connect/envoy/testdata/grpc-addr-unix-with-tls.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -40,13 +48,20 @@ "common_tls_context": { "validation_context": { "trusted_ca": { - "inline_string": "-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD\nVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa\nBgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE\nAxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j\nb20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK\nExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl\nc3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU\nmH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU\nd0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG\nxcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg\nU2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f\npFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID\nAQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud\nIwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE\nChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10\nZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ\nAIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h\ngjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9\n2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g\njctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp\nlFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/\nPOLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----\n" + "inline_string": "-----BEGIN CERTIFICATE-----\nMIIEEzCCAvugAwIBAgIUIYIXKNRBFBPuuOit2D2CfVJAoDAwDQYJKoZIhvcNAQEL\nBQAwgZgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZy\nYW5jaXNjbzEcMBoGA1UECgwTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECwwD\nRGV2MRYwFAYDVQQDDA10ZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0\nQGludGVybmFsLmNvbTAeFw0yMzExMDIxNTUwMjlaFw0zMzEwMzAxNTUwMjlaMIGY\nMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFuY2lz\nY28xHDAaBgNVBAoME0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsMA0RldjEW\nMBQGA1UEAwwNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRl\ncm5hbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCIA00iG5Iv\neRzZwf2P1Laih3eoiK2Wl1Re22cz2Pcpf6gb7agPguwU5Hco0DWzsnmek2Qyw9gl\noroX1t7LbTW2rxbK1hP7PkFCwSxi9u8MZDaLF3a79bwbsYZzf3toeoz8DCBxo9bB\nSSACj4uI/S+lUjMctQrK1nFjGoNUHfxioXPwIJH+TS/76TiZPu3Zj6kN6taVFNe3\nISBNXW6Vg8E3koz+9Bwv0a6Ty7oFRoJXpsud1k/83Iy288jhYDuB56+ypUmcCNqG\nT+e0Bn/VXHx26GXTx97cXSLJE+o+JrHZaI1TcQUL2Z5DJZVJRUg/wtcXggoMLVI1\nO0enJm2jdmLXAgMBAAGjUzBRMB0GA1UdDgQWBBTmrmqnZIdFOj6vhCUAJKLZNUDw\nFDAfBgNVHSMEGDAWgBTmrmqnZIdFOj6vhCUAJKLZNUDwFDAPBgNVHRMBAf8EBTAD\nAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB3j6gvalxq54hZSwVmVZPMzjdTVYRC11b0\n6C9pWKsLwu+WINcs59ui8wpYVjcw1AK4/2I1Q7P4RgpSarAxG5tYIMB1xcfFKqBn\nf/dDXexONgwpW6SoBJ58c7OB/aH8CenDT8Vwk3fwjYslOywbFRqBjH+PB8uTlu0e\nD1fzjpcQCrQeA5VD4pjJAaTmi7bLVuH5XIya3++f/N3xOn53GVMUDO1OdFz8ZMvJ\nWrrg7E/wMXB1b5Wo2n2ypVU4sejikSjg2nfdLojUWGMrZ8TuUnjFs88PeQ9CObAp\nA36dLfs4JLF3sVOtqTd6BGwegDsmmllYO5Ky6I+laoLSHpGDEihS\n-----END CERTIFICATE-----\n" } } } } }, - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/grpc-addr-unix.golden b/command/connect/envoy/testdata/grpc-addr-unix.golden index 88e6e46bfb95..415321891a44 100644 --- a/command/connect/envoy/testdata/grpc-addr-unix.golden +++ b/command/connect/envoy/testdata/grpc-addr-unix.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/grpc-tls-addr-config.golden b/command/connect/envoy/testdata/grpc-tls-addr-config.golden index e65fc5f09cd6..8ef32de0f726 100644 --- a/command/connect/envoy/testdata/grpc-tls-addr-config.golden +++ b/command/connect/envoy/testdata/grpc-tls-addr-config.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -46,7 +54,14 @@ } } }, - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/ingress-gateway-address-specified.golden b/command/connect/envoy/testdata/ingress-gateway-address-specified.golden index 038c8fcc5dd2..7ba3e2287cea 100644 --- a/command/connect/envoy/testdata/ingress-gateway-address-specified.golden +++ b/command/connect/envoy/testdata/ingress-gateway-address-specified.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ @@ -59,7 +74,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "self_admin", "endpoints": [ diff --git a/command/connect/envoy/testdata/ingress-gateway-no-auto-register.golden b/command/connect/envoy/testdata/ingress-gateway-no-auto-register.golden index 80f1f9a8b7c6..c866099ee0e7 100644 --- a/command/connect/envoy/testdata/ingress-gateway-no-auto-register.golden +++ b/command/connect/envoy/testdata/ingress-gateway-no-auto-register.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ @@ -59,7 +74,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "self_admin", "endpoints": [ diff --git a/command/connect/envoy/testdata/ingress-gateway-nodemeta.golden b/command/connect/envoy/testdata/ingress-gateway-nodemeta.golden index 8a2d5f62768e..39eae930d0b3 100644 --- a/command/connect/envoy/testdata/ingress-gateway-nodemeta.golden +++ b/command/connect/envoy/testdata/ingress-gateway-nodemeta.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -34,7 +42,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ @@ -60,7 +75,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "self_admin", "endpoints": [ diff --git a/command/connect/envoy/testdata/ingress-gateway-register-with-service-and-proxy-id.golden b/command/connect/envoy/testdata/ingress-gateway-register-with-service-and-proxy-id.golden index 6192f674ac17..44a3c25c69ba 100644 --- a/command/connect/envoy/testdata/ingress-gateway-register-with-service-and-proxy-id.golden +++ b/command/connect/envoy/testdata/ingress-gateway-register-with-service-and-proxy-id.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ @@ -59,7 +74,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "self_admin", "endpoints": [ diff --git a/command/connect/envoy/testdata/ingress-gateway-register-with-service-without-proxy-id.golden b/command/connect/envoy/testdata/ingress-gateway-register-with-service-without-proxy-id.golden index 92d80e033e9b..a9e6f7e5fa14 100644 --- a/command/connect/envoy/testdata/ingress-gateway-register-with-service-without-proxy-id.golden +++ b/command/connect/envoy/testdata/ingress-gateway-register-with-service-without-proxy-id.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ @@ -59,7 +74,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "self_admin", "endpoints": [ diff --git a/command/connect/envoy/testdata/ingress-gateway.golden b/command/connect/envoy/testdata/ingress-gateway.golden index 40a5c74d1bc2..e5c5e875939d 100644 --- a/command/connect/envoy/testdata/ingress-gateway.golden +++ b/command/connect/envoy/testdata/ingress-gateway.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ @@ -59,7 +74,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "self_admin", "endpoints": [ diff --git a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden index c93286e64e81..5754779b978c 100644 --- a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden +++ b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ @@ -59,7 +74,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "prometheus_backend", "endpoints": [ diff --git a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden index 272175f70733..c41b00fb2d29 100644 --- a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden +++ b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ @@ -59,7 +74,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "prometheus_backend", "endpoints": [ diff --git a/command/connect/envoy/testdata/prometheus-metrics.golden b/command/connect/envoy/testdata/prometheus-metrics.golden index 5806dd671f76..1b31b48f8a22 100644 --- a/command/connect/envoy/testdata/prometheus-metrics.golden +++ b/command/connect/envoy/testdata/prometheus-metrics.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ @@ -59,7 +74,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "5s", "type": "STATIC", - "http_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "prometheus_backend", "endpoints": [ diff --git a/command/connect/envoy/testdata/stats-config-override.golden b/command/connect/envoy/testdata/stats-config-override.golden index dd4ff53dd194..d045920bda04 100644 --- a/command/connect/envoy/testdata/stats-config-override.golden +++ b/command/connect/envoy/testdata/stats-config-override.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/telemetry-collector.golden b/command/connect/envoy/testdata/telemetry-collector.golden index 81ef48662298..a320b8ef50b6 100644 --- a/command/connect/envoy/testdata/telemetry-collector.golden +++ b/command/connect/envoy/testdata/telemetry-collector.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ @@ -57,7 +72,14 @@ { "name": "consul_telemetry_collector_loopback", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "consul_telemetry_collector_loopback", "endpoints": [ @@ -219,6 +241,7 @@ ], "use_all_default_tags": true }, + "stats_flush_interval": "60s", "dynamic_resources": { "lds_config": { "ads": {}, diff --git a/command/connect/envoy/testdata/token-arg.golden b/command/connect/envoy/testdata/token-arg.golden index 816bf7487572..2f0a0ef8ed43 100644 --- a/command/connect/envoy/testdata/token-arg.golden +++ b/command/connect/envoy/testdata/token-arg.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/token-env.golden b/command/connect/envoy/testdata/token-env.golden index 816bf7487572..2f0a0ef8ed43 100644 --- a/command/connect/envoy/testdata/token-env.golden +++ b/command/connect/envoy/testdata/token-env.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/token-file-arg.golden b/command/connect/envoy/testdata/token-file-arg.golden index 816bf7487572..2f0a0ef8ed43 100644 --- a/command/connect/envoy/testdata/token-file-arg.golden +++ b/command/connect/envoy/testdata/token-file-arg.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/token-file-env.golden b/command/connect/envoy/testdata/token-file-env.golden index 816bf7487572..2f0a0ef8ed43 100644 --- a/command/connect/envoy/testdata/token-file-env.golden +++ b/command/connect/envoy/testdata/token-file-env.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/xds-addr-config.golden b/command/connect/envoy/testdata/xds-addr-config.golden index e604c61d5063..dce3671a2fb3 100644 --- a/command/connect/envoy/testdata/xds-addr-config.golden +++ b/command/connect/envoy/testdata/xds-addr-config.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/connect/envoy/testdata/zipkin-tracing-config.golden b/command/connect/envoy/testdata/zipkin-tracing-config.golden index dc4779a7753d..acddc470abb5 100644 --- a/command/connect/envoy/testdata/zipkin-tracing-config.golden +++ b/command/connect/envoy/testdata/zipkin-tracing-config.golden @@ -1,6 +1,14 @@ { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -33,7 +41,14 @@ "ignore_health_on_host_removal": false, "connect_timeout": "1s", "type": "STATIC", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "loadAssignment": { "clusterName": "local_agent", "endpoints": [ diff --git a/command/helpers/helpers_test.go b/command/helpers/helpers_test.go index 6479386747ba..27ff1e01c145 100644 --- a/command/helpers/helpers_test.go +++ b/command/helpers/helpers_test.go @@ -2305,6 +2305,10 @@ func TestParseConfigEntry(t *testing.T) { name = "hdr-suffix" suffix = "suffix" }, + { + name = "hdr-contains" + contains = "contains" + }, { name = "hdr-regex" regex = "regex" @@ -2313,7 +2317,12 @@ func TestParseConfigEntry(t *testing.T) { name = "hdr-absent" present = true invert = true - } + }, + { + name = "hdr-ignore-case" + exact = "exact" + ignore_case = true + }, ] } }, @@ -2382,6 +2391,10 @@ func TestParseConfigEntry(t *testing.T) { Name = "hdr-suffix" Suffix = "suffix" }, + { + Name = "hdr-contains" + Contains = "contains" + }, { Name = "hdr-regex" Regex = "regex" @@ -2390,6 +2403,11 @@ func TestParseConfigEntry(t *testing.T) { Name = "hdr-absent" Present = true Invert = true + }, + { + Name = "hdr-ignore-case" + Exact = "exact" + IgnoreCase = true } ] } @@ -2460,6 +2478,10 @@ func TestParseConfigEntry(t *testing.T) { "name": "hdr-suffix", "suffix": "suffix" }, + { + "name": "hdr-contains", + "contains": "contains" + }, { "name": "hdr-regex", "regex": "regex" @@ -2468,6 +2490,11 @@ func TestParseConfigEntry(t *testing.T) { "name": "hdr-absent", "present": true, "invert": true + }, + { + "name": "hdr-ignore-case", + "exact": "exact", + "ignore_case": true } ] } @@ -2542,6 +2569,10 @@ func TestParseConfigEntry(t *testing.T) { "Name": "hdr-suffix", "Suffix": "suffix" }, + { + "Name": "hdr-contains", + "Contains": "contains" + }, { "Name": "hdr-regex", "Regex": "regex" @@ -2550,6 +2581,11 @@ func TestParseConfigEntry(t *testing.T) { "Name": "hdr-absent", "Present": true, "Invert": true + }, + { + "Name": "hdr-ignore-case", + "Exact": "exact", + "IgnoreCase": true } ] } @@ -2623,6 +2659,10 @@ func TestParseConfigEntry(t *testing.T) { Name: "hdr-suffix", Suffix: "suffix", }, + { + Name: "hdr-contains", + Contains: "contains", + }, { Name: "hdr-regex", Regex: "regex", @@ -2632,6 +2672,11 @@ func TestParseConfigEntry(t *testing.T) { Present: true, Invert: true, }, + { + Name: "hdr-ignore-case", + Exact: "exact", + IgnoreCase: true, + }, }, }, }, @@ -2719,7 +2764,7 @@ func TestParseConfigEntry(t *testing.T) { }, }, { - name: "mesh", + name: "mesh: kitchen sink", snake: ` kind = "mesh" meta { @@ -2729,6 +2774,8 @@ func TestParseConfigEntry(t *testing.T) { transparent_proxy { mesh_destinations_only = true } + allow_enabling_permissive_mutual_tls = true + validate_clusters = true tls { incoming { tls_min_version = "TLSv1_1" @@ -2747,6 +2794,20 @@ func TestParseConfigEntry(t *testing.T) { ] } } + http { + sanitize_x_forwarded_client_cert = true + incoming { + request_normalization { + insecure_disable_path_normalization = true + merge_slashes = true + path_with_escaped_slashes_action = "UNESCAPE_AND_FORWARD" + headers_with_underscores_action = "DROP_HEADER" + } + } + } + peering { + peer_through_mesh_gateways = true + } `, camel: ` Kind = "mesh" @@ -2757,6 +2818,8 @@ func TestParseConfigEntry(t *testing.T) { TransparentProxy { MeshDestinationsOnly = true } + AllowEnablingPermissiveMutualTLS = true + ValidateClusters = true TLS { Incoming { TLSMinVersion = "TLSv1_1" @@ -2775,6 +2838,20 @@ func TestParseConfigEntry(t *testing.T) { ] } } + HTTP { + SanitizeXForwardedClientCert = true + Incoming { + RequestNormalization { + InsecureDisablePathNormalization = true + MergeSlashes = true + PathWithEscapedSlashesAction = "UNESCAPE_AND_FORWARD" + HeadersWithUnderscoresAction = "DROP_HEADER" + } + } + } + Peering { + PeerThroughMeshGateways = true + } `, snakeJSON: ` { @@ -2786,6 +2863,8 @@ func TestParseConfigEntry(t *testing.T) { "transparent_proxy": { "mesh_destinations_only": true }, + "allow_enabling_permissive_mutual_tls": true, + "validate_clusters": true, "tls": { "incoming": { "tls_min_version": "TLSv1_1", @@ -2803,6 +2882,20 @@ func TestParseConfigEntry(t *testing.T) { "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" ] } + }, + "http": { + "sanitize_x_forwarded_client_cert": true, + "incoming": { + "request_normalization": { + "insecure_disable_path_normalization": true, + "merge_slashes": true, + "path_with_escaped_slashes_action": "UNESCAPE_AND_FORWARD", + "headers_with_underscores_action": "DROP_HEADER" + } + } + }, + "peering": { + "peer_through_mesh_gateways": true } } `, @@ -2816,6 +2909,8 @@ func TestParseConfigEntry(t *testing.T) { "TransparentProxy": { "MeshDestinationsOnly": true }, + "AllowEnablingPermissiveMutualTLS": true, + "ValidateClusters": true, "TLS": { "Incoming": { "TLSMinVersion": "TLSv1_1", @@ -2833,6 +2928,20 @@ func TestParseConfigEntry(t *testing.T) { "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" ] } + }, + "HTTP": { + "SanitizeXForwardedClientCert": true, + "Incoming": { + "RequestNormalization": { + "InsecureDisablePathNormalization": true, + "MergeSlashes": true, + "PathWithEscapedSlashesAction": "UNESCAPE_AND_FORWARD", + "HeadersWithUnderscoresAction": "DROP_HEADER" + } + } + }, + "Peering": { + "PeerThroughMeshGateways": true } } `, @@ -2844,6 +2953,8 @@ func TestParseConfigEntry(t *testing.T) { TransparentProxy: api.TransparentProxyMeshConfig{ MeshDestinationsOnly: true, }, + AllowEnablingPermissiveMutualTLS: true, + ValidateClusters: true, TLS: &api.MeshTLSConfig{ Incoming: &api.MeshDirectionalTLSConfig{ TLSMinVersion: "TLSv1_1", @@ -2862,6 +2973,20 @@ func TestParseConfigEntry(t *testing.T) { }, }, }, + HTTP: &api.MeshHTTPConfig{ + SanitizeXForwardedClientCert: true, + Incoming: &api.MeshDirectionalHTTPConfig{ + RequestNormalization: &api.RequestNormalizationMeshConfig{ + InsecureDisablePathNormalization: true, + MergeSlashes: true, + PathWithEscapedSlashesAction: "UNESCAPE_AND_FORWARD", + HeadersWithUnderscoresAction: "DROP_HEADER", + }, + }, + }, + Peering: &api.PeeringMeshConfig{ + PeerThroughMeshGateways: true, + }, }, }, { diff --git a/command/login/login_test.go b/command/login/login_test.go index c3bf11767617..794c7b362353 100644 --- a/command/login/login_test.go +++ b/command/login/login_test.go @@ -11,9 +11,9 @@ import ( "testing" "time" + "github.com/go-jose/go-jose/v3/jwt" "github.com/mitchellh/cli" "github.com/stretchr/testify/require" - "gopkg.in/square/go-jose.v2/jwt" "github.com/hashicorp/consul-awsauth/iamauthtest" "github.com/hashicorp/consul/agent" diff --git a/command/peering/exportedservices/exported_services.go b/command/peering/exportedservices/exported_services.go new file mode 100644 index 000000000000..d075257b33cc --- /dev/null +++ b/command/peering/exportedservices/exported_services.go @@ -0,0 +1,154 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package exportedservices + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "strings" + + "github.com/mitchellh/cli" + "github.com/ryanuber/columnize" + + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/command/flags" + "github.com/hashicorp/consul/command/peering" +) + +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + http *flags.HTTPFlags + help string + + name string + format string +} + +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + + c.flags.StringVar(&c.name, "name", "", "(Required) The local name assigned to the peer cluster.") + + c.flags.StringVar( + &c.format, + "format", + peering.PeeringFormatPretty, + fmt.Sprintf("Output format {%s} (default: %s)", strings.Join(peering.GetSupportedFormats(), "|"), peering.PeeringFormatPretty), + ) + + c.http = &flags.HTTPFlags{} + flags.Merge(c.flags, c.http.ClientFlags()) + flags.Merge(c.flags, c.http.PartitionFlag()) + c.help = flags.Usage(help, c.flags) +} + +func (c *cmd) Run(args []string) int { + if err := c.flags.Parse(args); err != nil { + return 1 + } + + if c.name == "" { + c.UI.Error("Missing the required -name flag") + return 1 + } + + if !peering.FormatIsValid(c.format) { + c.UI.Error(fmt.Sprintf("Invalid format, valid formats are {%s}", strings.Join(peering.GetSupportedFormats(), "|"))) + return 1 + } + + client, err := c.http.APIClient() + if err != nil { + c.UI.Error(fmt.Sprintf("Error connect to Consul agent: %s", err)) + return 1 + } + + peerings := client.Peerings() + + res, _, err := peerings.Read(context.Background(), c.name, &api.QueryOptions{}) + if err != nil { + c.UI.Error(fmt.Sprintf("Error reading peering: %s", err)) + return 1 + } + + if res == nil { + c.UI.Error(fmt.Sprintf("No peering with name %s found.", c.name)) + return 1 + } + + // Convert service to serviceID + services := make([]structs.ServiceID, 0, len(res.StreamStatus.ExportedServices)) + for _, svc := range res.StreamStatus.ExportedServices { + services = append(services, structs.ServiceIDFromString(svc)) + } + + if c.format == peering.PeeringFormatJSON { + output, err := json.Marshal(services) + if err != nil { + c.UI.Error(fmt.Sprintf("Error marshalling JSON: %s", err)) + return 1 + } + c.UI.Output(string(output)) + return 0 + } + + c.UI.Output(formatExportedServices(services)) + + return 0 +} + +func formatExportedServices(services []structs.ServiceID) string { + if len(services) == 0 { + return "" + } + + result := make([]string, 0, len(services)+1) + + if services[0].EnterpriseMeta.ToEnterprisePolicyMeta() != nil { + result = append(result, "Partition\x1fNamespace\x1fService Name") + } + + for _, svc := range services { + if svc.EnterpriseMeta.ToEnterprisePolicyMeta() == nil { + result = append(result, svc.ID) + } else { + result = append(result, fmt.Sprintf("%s\x1f%s\x1f%s", svc.EnterpriseMeta.PartitionOrDefault(), svc.EnterpriseMeta.NamespaceOrDefault(), svc.ID)) + } + } + + return columnize.Format(result, &columnize.Config{Delim: string([]byte{0x1f})}) +} + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return flags.Usage(c.help, nil) +} + +const ( + synopsis = "Lists exported services to a peer" + help = ` +Usage: consul peering exported-services [options] -name + + Lists services exported to the peer with the provided name. If the peer is not found, + the command exits with a non-zero code. The result is filtered according + to ACL policy configuration. + + Example: + + $ consul peering exported-services -name west-dc +` +) diff --git a/command/peering/exportedservices/exported_services_test.go b/command/peering/exportedservices/exported_services_test.go new file mode 100644 index 000000000000..d63b5b2c449e --- /dev/null +++ b/command/peering/exportedservices/exported_services_test.go @@ -0,0 +1,216 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package exportedservices + +import ( + "context" + "encoding/json" + "strings" + "testing" + + "github.com/mitchellh/cli" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/agent" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil/retry" + "github.com/hashicorp/consul/testrpc" +) + +func TestExportedServicesCommand_noTabs(t *testing.T) { + t.Parallel() + + if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') { + t.Fatal("help has tabs") + } +} + +func TestExportedServicesCommand(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + acceptor := agent.NewTestAgent(t, ``) + t.Cleanup(func() { _ = acceptor.Shutdown() }) + + dialer := agent.NewTestAgent(t, `datacenter = "dc2"`) + t.Cleanup(func() { _ = dialer.Shutdown() }) + + testrpc.WaitForTestAgent(t, acceptor.RPC, "dc1") + testrpc.WaitForTestAgent(t, dialer.RPC, "dc2") + + acceptingClient := acceptor.Client() + dialingClient := dialer.Client() + + t.Run("no name flag", func(t *testing.T) { + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + acceptor.HTTPAddr(), + } + + code := cmd.Run(args) + require.Equal(t, 1, code, "err: %s", ui.ErrorWriter.String()) + require.Contains(t, ui.ErrorWriter.String(), "Missing the required -name flag") + }) + + t.Run("invalid format", func(t *testing.T) { + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + acceptor.HTTPAddr(), + "-name=foo", + "-format=toml", + } + + code := cmd.Run(args) + require.Equal(t, 1, code, "exited successfully when it should have failed") + output := ui.ErrorWriter.String() + require.Contains(t, output, "Invalid format") + }) + + t.Run("peering does not exist", func(t *testing.T) { + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + acceptor.HTTPAddr(), + "-name=foo", + } + + code := cmd.Run(args) + require.Equal(t, 1, code, "err: %s", ui.ErrorWriter.String()) + require.Contains(t, ui.ErrorWriter.String(), "No peering with name") + }) + + t.Run("peering exist but no exported services", func(t *testing.T) { + // Generate token + generateReq := api.PeeringGenerateTokenRequest{ + PeerName: "foo", + Meta: map[string]string{ + "env": "production", + }, + } + + res, _, err := acceptingClient.Peerings().GenerateToken(context.Background(), generateReq, &api.WriteOptions{}) + require.NoError(t, err, "Could not generate peering token at acceptor for \"foo\"") + + // Establish peering + establishReq := api.PeeringEstablishRequest{ + PeerName: "bar", + PeeringToken: res.PeeringToken, + Meta: map[string]string{ + "env": "production", + }, + } + + _, _, err = dialingClient.Peerings().Establish(context.Background(), establishReq, &api.WriteOptions{}) + require.NoError(t, err, "Could not establish peering for \"bar\"") + + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + acceptor.HTTPAddr(), + "-name=foo", + } + + code := cmd.Run(args) + require.Equal(t, 0, code) + require.Equal(t, ui.ErrorWriter.String(), "") + }) + + t.Run("exported-services with pretty print", func(t *testing.T) { + // Generate token + generateReq := api.PeeringGenerateTokenRequest{ + PeerName: "foo", + Meta: map[string]string{ + "env": "production", + }, + } + + res, _, err := acceptingClient.Peerings().GenerateToken(context.Background(), generateReq, &api.WriteOptions{}) + require.NoError(t, err, "Could not generate peering token at acceptor for \"foo\"") + + // Establish peering + establishReq := api.PeeringEstablishRequest{ + PeerName: "bar", + PeeringToken: res.PeeringToken, + Meta: map[string]string{ + "env": "production", + }, + } + + _, _, err = dialingClient.Peerings().Establish(context.Background(), establishReq, &api.WriteOptions{}) + require.NoError(t, err, "Could not establish peering for \"bar\"") + + _, _, err = acceptingClient.ConfigEntries().Set(&api.ExportedServicesConfigEntry{ + Name: "default", + Services: []api.ExportedService{ + { + Name: "web", + Consumers: []api.ServiceConsumer{ + { + Peer: "foo", + }, + }, + }, + { + Name: "db", + Consumers: []api.ServiceConsumer{ + { + Peer: "foo", + }, + }, + }, + }, + }, nil) + require.NoError(t, err) + + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + acceptor.HTTPAddr(), + "-name=foo", + } + + retry.Run(t, func(r *retry.R) { + code := cmd.Run(args) + require.Equal(r, 0, code) + output := ui.OutputWriter.String() + + // Spot check some fields and values + require.Contains(r, output, "web") + require.Contains(r, output, "db") + }) + }) + + t.Run("exported-services with json", func(t *testing.T) { + + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + acceptor.HTTPAddr(), + "-name=foo", + "-format=json", + } + + code := cmd.Run(args) + require.Equal(t, 0, code) + output := ui.OutputWriter.Bytes() + + var services []structs.ServiceID + require.NoError(t, json.Unmarshal(output, &services)) + + require.Equal(t, "db", services[0].ID) + require.Equal(t, "web", services[1].ID) + }) +} diff --git a/command/peering/peering.go b/command/peering/peering.go index 157dd42c63d7..9c520b3d6fe3 100644 --- a/command/peering/peering.go +++ b/command/peering/peering.go @@ -64,6 +64,10 @@ Usage: consul peering [options] [args] $ consul peering read -name west-dc + Lists services exported to a peering connection: + + $ consul peering exported-services -name west-dc + Delete and close a peering connection: $ consul peering delete -name west-dc diff --git a/command/registry.go b/command/registry.go index 559189b6f988..381b86db9aab 100644 --- a/command/registry.go +++ b/command/registry.go @@ -108,21 +108,28 @@ import ( "github.com/hashicorp/consul/command/peering" peerdelete "github.com/hashicorp/consul/command/peering/delete" peerestablish "github.com/hashicorp/consul/command/peering/establish" + peerexported "github.com/hashicorp/consul/command/peering/exportedservices" peergenerate "github.com/hashicorp/consul/command/peering/generate" peerlist "github.com/hashicorp/consul/command/peering/list" peerread "github.com/hashicorp/consul/command/peering/read" "github.com/hashicorp/consul/command/reload" "github.com/hashicorp/consul/command/resource" resourceapply "github.com/hashicorp/consul/command/resource/apply" + resourceapplygrpc "github.com/hashicorp/consul/command/resource/apply-grpc" resourcedelete "github.com/hashicorp/consul/command/resource/delete" + resourcedeletegrpc "github.com/hashicorp/consul/command/resource/delete-grpc" resourcelist "github.com/hashicorp/consul/command/resource/list" + resourcelistgrpc "github.com/hashicorp/consul/command/resource/list-grpc" resourceread "github.com/hashicorp/consul/command/resource/read" + resourcereadgrpc "github.com/hashicorp/consul/command/resource/read-grpc" "github.com/hashicorp/consul/command/rtt" "github.com/hashicorp/consul/command/services" svcsderegister "github.com/hashicorp/consul/command/services/deregister" svcsexport "github.com/hashicorp/consul/command/services/export" + exportedservices "github.com/hashicorp/consul/command/services/exportedservices" svcsregister "github.com/hashicorp/consul/command/services/register" "github.com/hashicorp/consul/command/snapshot" + snapdecode "github.com/hashicorp/consul/command/snapshot/decode" snapinspect "github.com/hashicorp/consul/command/snapshot/inspect" snaprestore "github.com/hashicorp/consul/command/snapshot/restore" snapsave "github.com/hashicorp/consul/command/snapshot/save" @@ -132,6 +139,7 @@ import ( tlscert "github.com/hashicorp/consul/command/tls/cert" tlscertcreate "github.com/hashicorp/consul/command/tls/cert/create" "github.com/hashicorp/consul/command/troubleshoot" + troubleshootports "github.com/hashicorp/consul/command/troubleshoot/ports" troubleshootproxy "github.com/hashicorp/consul/command/troubleshoot/proxy" troubleshootupstreams "github.com/hashicorp/consul/command/troubleshoot/upstreams" "github.com/hashicorp/consul/command/validate" @@ -246,6 +254,7 @@ func RegisteredCommands(ui cli.Ui) map[string]mcli.CommandFactory { entry{"operator usage instances", func(ui cli.Ui) (cli.Command, error) { return instances.New(ui), nil }}, entry{"peering", func(cli.Ui) (cli.Command, error) { return peering.New(), nil }}, entry{"peering delete", func(ui cli.Ui) (cli.Command, error) { return peerdelete.New(ui), nil }}, + entry{"peering exported-services", func(ui cli.Ui) (cli.Command, error) { return peerexported.New(ui), nil }}, entry{"peering generate-token", func(ui cli.Ui) (cli.Command, error) { return peergenerate.New(ui), nil }}, entry{"peering establish", func(ui cli.Ui) (cli.Command, error) { return peerestablish.New(ui), nil }}, entry{"peering list", func(ui cli.Ui) (cli.Command, error) { return peerlist.New(ui), nil }}, @@ -255,13 +264,20 @@ func RegisteredCommands(ui cli.Ui) map[string]mcli.CommandFactory { entry{"resource read", func(ui cli.Ui) (cli.Command, error) { return resourceread.New(ui), nil }}, entry{"resource delete", func(ui cli.Ui) (cli.Command, error) { return resourcedelete.New(ui), nil }}, entry{"resource apply", func(ui cli.Ui) (cli.Command, error) { return resourceapply.New(ui), nil }}, + // will be refactored to resource apply + entry{"resource apply-grpc", func(ui cli.Ui) (cli.Command, error) { return resourceapplygrpc.New(ui), nil }}, + entry{"resource read-grpc", func(ui cli.Ui) (cli.Command, error) { return resourcereadgrpc.New(ui), nil }}, + entry{"resource list-grpc", func(ui cli.Ui) (cli.Command, error) { return resourcelistgrpc.New(ui), nil }}, + entry{"resource delete-grpc", func(ui cli.Ui) (cli.Command, error) { return resourcedeletegrpc.New(ui), nil }}, entry{"resource list", func(ui cli.Ui) (cli.Command, error) { return resourcelist.New(ui), nil }}, entry{"rtt", func(ui cli.Ui) (cli.Command, error) { return rtt.New(ui), nil }}, entry{"services", func(cli.Ui) (cli.Command, error) { return services.New(), nil }}, entry{"services register", func(ui cli.Ui) (cli.Command, error) { return svcsregister.New(ui), nil }}, entry{"services deregister", func(ui cli.Ui) (cli.Command, error) { return svcsderegister.New(ui), nil }}, entry{"services export", func(ui cli.Ui) (cli.Command, error) { return svcsexport.New(ui), nil }}, + entry{"services exported-services", func(ui cli.Ui) (cli.Command, error) { return exportedservices.New(ui), nil }}, entry{"snapshot", func(cli.Ui) (cli.Command, error) { return snapshot.New(), nil }}, + entry{"snapshot decode", func(ui cli.Ui) (cli.Command, error) { return snapdecode.New(ui), nil }}, entry{"snapshot inspect", func(ui cli.Ui) (cli.Command, error) { return snapinspect.New(ui), nil }}, entry{"snapshot restore", func(ui cli.Ui) (cli.Command, error) { return snaprestore.New(ui), nil }}, entry{"snapshot save", func(ui cli.Ui) (cli.Command, error) { return snapsave.New(ui), nil }}, @@ -273,6 +289,7 @@ func RegisteredCommands(ui cli.Ui) map[string]mcli.CommandFactory { entry{"troubleshoot", func(ui cli.Ui) (cli.Command, error) { return troubleshoot.New(), nil }}, entry{"troubleshoot proxy", func(ui cli.Ui) (cli.Command, error) { return troubleshootproxy.New(ui), nil }}, entry{"troubleshoot upstreams", func(ui cli.Ui) (cli.Command, error) { return troubleshootupstreams.New(ui), nil }}, + entry{"troubleshoot ports", func(ui cli.Ui) (cli.Command, error) { return troubleshootports.New(ui), nil }}, entry{"validate", func(ui cli.Ui) (cli.Command, error) { return validate.New(ui), nil }}, entry{"version", func(ui cli.Ui) (cli.Command, error) { return version.New(ui), nil }}, entry{"watch", func(ui cli.Ui) (cli.Command, error) { return watch.New(ui, MakeShutdownCh()), nil }}, diff --git a/command/resource/apply-grpc/apply.go b/command/resource/apply-grpc/apply.go new file mode 100644 index 000000000000..1819730c4861 --- /dev/null +++ b/command/resource/apply-grpc/apply.go @@ -0,0 +1,150 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package apply + +import ( + "encoding/json" + "errors" + "flag" + "fmt" + "io" + + "github.com/mitchellh/cli" + + "github.com/hashicorp/consul/command/resource" + "github.com/hashicorp/consul/command/resource/client" +) + +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + grpcFlags *client.GRPCFlags + help string + + filePath string + + testStdin io.Reader +} + +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.flags.StringVar(&c.filePath, "f", "", + "File path with resource definition") + + c.grpcFlags = &client.GRPCFlags{} + client.MergeFlags(c.flags, c.grpcFlags.ClientFlags()) + c.help = client.Usage(help, c.flags) +} + +func (c *cmd) Run(args []string) int { + if err := c.flags.Parse(args); err != nil { + if !errors.Is(err, flag.ErrHelp) { + c.UI.Error(fmt.Sprintf("Failed to parse args: %v", err)) + return 1 + } + c.UI.Error(fmt.Sprintf("Failed to run apply command: %v", err)) + return 1 + } + + // parse resource + input := c.filePath + if input == "" { + c.UI.Error("Required '-f' flag was not provided to specify where to load the resource content from") + return 1 + } + parsedResource, err := resource.ParseResourceInput(input, c.testStdin) + if err != nil { + c.UI.Error(fmt.Sprintf("Failed to decode resource from input file: %v", err)) + return 1 + } + if parsedResource == nil { + c.UI.Error("Unable to parse the file argument") + return 1 + } + + // initialize client + config, err := client.LoadGRPCConfig(nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Error loading config: %s", err)) + return 1 + } + c.grpcFlags.MergeFlagsIntoGRPCConfig(config) + resourceClient, err := client.NewGRPCClient(config) + if err != nil { + c.UI.Error(fmt.Sprintf("Error connect to Consul agent: %s", err)) + return 1 + } + + // write resource + res := resource.ResourceGRPC{C: resourceClient} + entry, err := res.Apply(parsedResource) + if err != nil { + c.UI.Error(fmt.Sprintf("Error writing resource %s/%s: %v", parsedResource.Id.Type, parsedResource.Id.GetName(), err)) + return 1 + } + + // display response + b, err := json.MarshalIndent(entry, "", resource.JSON_INDENT) + if err != nil { + c.UI.Error("Failed to encode output data") + return 1 + } + c.UI.Info(fmt.Sprintf("%s.%s.%s '%s' created.", parsedResource.Id.Type.Group, parsedResource.Id.Type.GroupVersion, parsedResource.Id.Type.Kind, parsedResource.Id.GetName())) + c.UI.Info(string(b)) + + return 0 +} + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return client.Usage(c.help, nil) +} + +const synopsis = "Writes/updates resource information" + +const help = ` +Usage: consul resource apply [options] + + Write and/or update a resource by providing the definition. The configuration + argument is either a file path or '-' to indicate that the resource + should be read from stdin. The data should be either in HCL or + JSON form. + + Example (with flag): + + $ consul resource apply -f=demo.hcl + + Example (from stdin): + + $ consul resource apply -f - < demo.hcl + + Sample demo.hcl: + + ID { + Type = gvk("group.version.kind") + Name = "resource-name" + Tenancy { + Partition = "default" + Namespace = "default" + PeerName = "local" + } + } + + Data { + Name = "demo" + } + + Metadata = { + "foo" = "bar" + } +` diff --git a/command/resource/apply-grpc/apply_test.go b/command/resource/apply-grpc/apply_test.go new file mode 100644 index 000000000000..d96e05039a9e --- /dev/null +++ b/command/resource/apply-grpc/apply_test.go @@ -0,0 +1,226 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package apply + +import ( + "errors" + "fmt" + "io" + "testing" + + "github.com/mitchellh/cli" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/agent" + "github.com/hashicorp/consul/sdk/freeport" + "github.com/hashicorp/consul/testrpc" +) + +func TestResourceApplyCommand(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + availablePort := freeport.GetOne(t) + a := agent.NewTestAgent(t, fmt.Sprintf("ports { grpc = %d }", availablePort)) + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + + t.Cleanup(func() { + a.Shutdown() + }) + + cases := []struct { + name string + output string + args []string + }{ + { + name: "sample output", + args: []string{"-f=../testdata/demo.hcl"}, + output: "demo.v2.Artist 'korn' created.", + }, + { + name: "nested data format", + args: []string{"-f=../testdata/nested_data.hcl"}, + output: "demo.v2.Festival 'woodstock' created.", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ui := cli.NewMockUi() + c := New(ui) + + args := []string{ + fmt.Sprintf("-grpc-addr=127.0.0.1:%d", availablePort), + "-token=root", + } + + args = append(args, tc.args...) + + code := c.Run(args) + require.Equal(t, 0, code) + require.Empty(t, ui.ErrorWriter.String()) + require.Contains(t, ui.OutputWriter.String(), tc.output) + }) + } +} + +func TestResourceApplyCommand_StdIn(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + availablePort := freeport.GetOne(t) + a := agent.NewTestAgent(t, fmt.Sprintf("ports { grpc = %d }", availablePort)) + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + + t.Cleanup(func() { + a.Shutdown() + }) + + t.Run("hcl", func(t *testing.T) { + stdinR, stdinW := io.Pipe() + + ui := cli.NewMockUi() + c := New(ui) + c.testStdin = stdinR + + stdInput := `ID { + Type = gvk("demo.v2.Artist") + Name = "korn" + Tenancy { + Partition = "default" + Namespace = "default" + } + } + + Data { + Name = "Korn" + Genre = "GENRE_METAL" + } + + Metadata = { + "foo" = "bar" + }` + + go func() { + stdinW.Write([]byte(stdInput)) + stdinW.Close() + }() + + args := []string{ + fmt.Sprintf("-grpc-addr=127.0.0.1:%d", availablePort), + "-token=root", + "-f", + "-", + } + + code := c.Run(args) + require.Equal(t, 0, code) + require.Empty(t, ui.ErrorWriter.String()) + // Todo: make up the read result check after finishing the read command + //expected := readResource(t, a, []string{"demo.v2.Artist", "korn"}) + require.Contains(t, ui.OutputWriter.String(), "demo.v2.Artist 'korn' created.") + //require.Contains(t, ui.OutputWriter.String(), expected) + }) + + t.Run("json", func(t *testing.T) { + stdinR, stdinW := io.Pipe() + + ui := cli.NewMockUi() + c := New(ui) + c.testStdin = stdinR + + stdInput := `{ + "data": { + "genre": "GENRE_METAL", + "name": "Korn" + }, + "id": { + "name": "korn", + "tenancy": { + "partition": "default", + "namespace": "default" + }, + "type": { + "group": "demo", + "groupVersion": "v2", + "kind": "Artist" + } + }, + "metadata": { + "foo": "bar" + } + }` + + go func() { + stdinW.Write([]byte(stdInput)) + stdinW.Close() + }() + + args := []string{ + "-f", + "-", + fmt.Sprintf("-grpc-addr=127.0.0.1:%d", availablePort), + "-token=root", + } + + code := c.Run(args) + require.Equal(t, 0, code) + require.Empty(t, ui.ErrorWriter.String()) + // Todo: make up the read result check after finishing the read command + //expected := readResource(t, a, []string{"demo.v2.Artist", "korn"}) + require.Contains(t, ui.OutputWriter.String(), "demo.v2.Artist 'korn' created.") + //require.Contains(t, ui.OutputWriter.String(), expected) + }) +} + +func TestResourceApplyInvalidArgs(t *testing.T) { + t.Parallel() + + type tc struct { + args []string + expectedCode int + expectedErr error + } + + cases := map[string]tc{ + "no file path": { + args: []string{"-f"}, + expectedCode: 1, + expectedErr: errors.New("Failed to parse args: flag needs an argument: -f"), + }, + "missing required flag": { + args: []string{}, + expectedCode: 1, + expectedErr: errors.New("Required '-f' flag was not provided to specify where to load the resource content from"), + }, + "file parsing failure": { + args: []string{"-f=../testdata/invalid.hcl"}, + expectedCode: 1, + expectedErr: errors.New("Failed to decode resource from input file"), + }, + "file not found": { + args: []string{"-f=../testdata/test.hcl"}, + expectedCode: 1, + expectedErr: errors.New("Failed to load data: Failed to read file: open ../testdata/test.hcl: no such file or directory"), + }, + } + + for desc, tc := range cases { + t.Run(desc, func(t *testing.T) { + ui := cli.NewMockUi() + c := New(ui) + + code := c.Run(tc.args) + + require.Equal(t, tc.expectedCode, code) + require.Contains(t, ui.ErrorWriter.String(), tc.expectedErr.Error()) + }) + } +} diff --git a/command/resource/apply/apply.go b/command/resource/apply/apply.go index df3f136c5028..cf92af9474d5 100644 --- a/command/resource/apply/apply.go +++ b/command/resource/apply/apply.go @@ -116,7 +116,6 @@ func (c *cmd) Run(args []string) int { opts := &client.QueryOptions{ Namespace: parsedResource.Id.Tenancy.GetNamespace(), Partition: parsedResource.Id.Tenancy.GetPartition(), - Peer: parsedResource.Id.Tenancy.GetPeerName(), Token: c.http.Token(), } @@ -187,7 +186,6 @@ Usage: consul resource apply [options] Tenancy { Namespace = "default" Partition = "default" - PeerName = "local" } } diff --git a/command/resource/apply/apply_test.go b/command/resource/apply/apply_test.go index 2644e7aaebdd..e0d56ec5f6a0 100644 --- a/command/resource/apply/apply_test.go +++ b/command/resource/apply/apply_test.go @@ -39,12 +39,12 @@ func TestResourceApplyCommand(t *testing.T) { { name: "nested data format", args: []string{"-f=../testdata/nested_data.hcl"}, - output: "mesh.v2beta1.Destinations 'api' created.", + output: "demo.v2.Festival 'woodstock' created.", }, { name: "file path with no flag", args: []string{"../testdata/nested_data.hcl"}, - output: "mesh.v2beta1.Destinations 'api' created.", + output: "demo.v2.Festival 'woodstock' created.", }, } @@ -109,7 +109,6 @@ func TestResourceApplyCommand_StdIn(t *testing.T) { Tenancy { Namespace = "default" Partition = "default" - PeerName = "local" } } @@ -134,7 +133,7 @@ func TestResourceApplyCommand_StdIn(t *testing.T) { } code := c.Run(args) - require.Equal(t, 0, code) + require.Equal(t, 0, code, ui.ErrorWriter.String()) require.Empty(t, ui.ErrorWriter.String()) expected := readResource(t, a, []string{"demo.v2.Artist", "korn"}) require.Contains(t, ui.OutputWriter.String(), "demo.v2.Artist 'korn' created.") @@ -157,8 +156,7 @@ func TestResourceApplyCommand_StdIn(t *testing.T) { "name": "korn", "tenancy": { "namespace": "default", - "partition": "default", - "peerName": "local" + "partition": "default" }, "type": { "group": "demo", @@ -183,7 +181,7 @@ func TestResourceApplyCommand_StdIn(t *testing.T) { } code := c.Run(args) - require.Equal(t, 0, code) + require.Equal(t, 0, code, ui.ErrorWriter.String()) require.Empty(t, ui.ErrorWriter.String()) expected := readResource(t, a, []string{"demo.v2.Artist", "korn"}) require.Contains(t, ui.OutputWriter.String(), "demo.v2.Artist 'korn' created.") diff --git a/command/resource/client/client.go b/command/resource/client/client.go index 0d0d59e2df99..7113e4e58733 100644 --- a/command/resource/client/client.go +++ b/command/resource/client/client.go @@ -6,7 +6,6 @@ package client import ( "bytes" "context" - "crypto/tls" "encoding/json" "fmt" "io" @@ -19,10 +18,10 @@ import ( "sync" "time" - "github.com/hashicorp/consul/api" "github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-rootcerts" + + "github.com/hashicorp/consul/api" ) // NOTE: This client is copied from the api module to temporarily facilitate the resource cli commands @@ -72,20 +71,6 @@ const ( // whether or not to disable certificate checking. HTTPSSLVerifyEnvName = "CONSUL_HTTP_SSL_VERIFY" - // GRPCAddrEnvName defines an environment variable name which sets the gRPC - // address for consul connect envoy. Note this isn't actually used by the api - // client in this package but is defined here for consistency with all the - // other ENV names we use. - GRPCAddrEnvName = "CONSUL_GRPC_ADDR" - - // GRPCCAFileEnvName defines an environment variable name which sets the - // CA file to use for talking to Consul gRPC over TLS. - GRPCCAFileEnvName = "CONSUL_GRPC_CACERT" - - // GRPCCAPathEnvName defines an environment variable name which sets the - // path to a directory of CA certs to use for talking to Consul gRPC over TLS. - GRPCCAPathEnvName = "CONSUL_GRPC_CAPATH" - // HTTPNamespaceEnvVar defines an environment variable name which sets // the HTTP Namespace to be used by default. This can still be overridden. HTTPNamespaceEnvName = "CONSUL_NAMESPACE" @@ -124,9 +109,6 @@ type QueryOptions struct { // by the Config Datacenter string - // Providing a peer name in the query option - Peer string - // AllowStale allows any Consul server (non-leader) to service // a read. This allows for lower latency and higher throughput AllowStale bool @@ -543,60 +525,6 @@ func defaultConfig(logger hclog.Logger, transportFn func() *http.Transport) *Con return config } -// TLSConfig is used to generate a TLSClientConfig that's useful for talking to -// Consul using TLS. -func SetupTLSConfig(tlsConfig *TLSConfig) (*tls.Config, error) { - tlsClientConfig := &tls.Config{ - InsecureSkipVerify: tlsConfig.InsecureSkipVerify, - } - - if tlsConfig.Address != "" { - server := tlsConfig.Address - hasPort := strings.LastIndex(server, ":") > strings.LastIndex(server, "]") - if hasPort { - var err error - server, _, err = net.SplitHostPort(server) - if err != nil { - return nil, err - } - } - tlsClientConfig.ServerName = server - } - - if len(tlsConfig.CertPEM) != 0 && len(tlsConfig.KeyPEM) != 0 { - tlsCert, err := tls.X509KeyPair(tlsConfig.CertPEM, tlsConfig.KeyPEM) - if err != nil { - return nil, err - } - tlsClientConfig.Certificates = []tls.Certificate{tlsCert} - } else if len(tlsConfig.CertPEM) != 0 || len(tlsConfig.KeyPEM) != 0 { - return nil, fmt.Errorf("both client cert and client key must be provided") - } - - if tlsConfig.CertFile != "" && tlsConfig.KeyFile != "" { - tlsCert, err := tls.LoadX509KeyPair(tlsConfig.CertFile, tlsConfig.KeyFile) - if err != nil { - return nil, err - } - tlsClientConfig.Certificates = []tls.Certificate{tlsCert} - } else if tlsConfig.CertFile != "" || tlsConfig.KeyFile != "" { - return nil, fmt.Errorf("both client cert and client key must be provided") - } - - if tlsConfig.CAFile != "" || tlsConfig.CAPath != "" || len(tlsConfig.CAPem) != 0 { - rootConfig := &rootcerts.Config{ - CAFile: tlsConfig.CAFile, - CAPath: tlsConfig.CAPath, - CACertificate: tlsConfig.CAPem, - } - if err := rootcerts.ConfigureTLS(tlsClientConfig, rootConfig); err != nil { - return nil, err - } - } - - return tlsClientConfig, nil -} - func (c *Config) GenerateEnv() []string { env := make([]string, 0, 10) @@ -835,15 +763,13 @@ func (r *request) SetQueryOptions(q *QueryOptions) { // rather than the alternative short-hand "ap" r.params.Set("partition", q.Partition) } + // TODO(peering/v2) handle peer tenancy if q.Datacenter != "" { // For backwards-compatibility with existing tests, // use the short-hand query param name "dc" // rather than the alternative long-hand "datacenter" r.params.Set("dc", q.Datacenter) } - if q.Peer != "" { - r.params.Set("peer", q.Peer) - } if q.AllowStale { r.params.Set("stale", "") } diff --git a/command/resource/client/grpc-client.go b/command/resource/client/grpc-client.go new file mode 100644 index 000000000000..1ba1a481febb --- /dev/null +++ b/command/resource/client/grpc-client.go @@ -0,0 +1,65 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import ( + "fmt" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/insecure" + + "github.com/hashicorp/consul/proto-public/pbresource" +) + +type GRPCClient struct { + Client pbresource.ResourceServiceClient + Config *GRPCConfig + Conn *grpc.ClientConn +} + +func NewGRPCClient(config *GRPCConfig) (*GRPCClient, error) { + conn, err := dial(config) + if err != nil { + return nil, fmt.Errorf("error dialing grpc: %+v", err) + } + return &GRPCClient{ + Client: pbresource.NewResourceServiceClient(conn), + Config: config, + Conn: conn, + }, nil +} + +func dial(c *GRPCConfig) (*grpc.ClientConn, error) { + err := checkCertificates(c) + if err != nil { + return nil, err + } + var dialOpts []grpc.DialOption + if c.GRPCTLS { + tlsConfig, err := SetupTLSConfig(c) + if err != nil { + return nil, fmt.Errorf("failed to setup tls config when tried to establish grpc call: %w", err) + } + dialOpts = append(dialOpts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))) + } else { + dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials())) + } + + return grpc.Dial(c.Address, dialOpts...) +} + +func checkCertificates(c *GRPCConfig) error { + if c.GRPCTLS { + certFileEmpty := c.CertFile == "" + keyFileEmpty := c.KeyFile == "" + + // both files need to be empty or both files need to be provided + if certFileEmpty != keyFileEmpty { + return fmt.Errorf("you have to provide client certificate file and key file at the same time " + + "if you intend to communicate in TLS/SSL mode") + } + } + return nil +} diff --git a/command/resource/client/grpc-client_test.go b/command/resource/client/grpc-client_test.go new file mode 100644 index 000000000000..837ff2cafe1f --- /dev/null +++ b/command/resource/client/grpc-client_test.go @@ -0,0 +1,147 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + + "github.com/hashicorp/consul/agent" + "github.com/hashicorp/consul/internal/resource/demo" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/hashicorp/consul/sdk/freeport" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/consul/testrpc" +) + +func TestResourceRead(t *testing.T) { + availablePort := freeport.GetOne(t) + a := agent.NewTestAgent(t, fmt.Sprintf("ports { grpc = %d }", availablePort)) + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + grpcConfig, err := LoadGRPCConfig(&GRPCConfig{Address: fmt.Sprintf("127.0.0.1:%d", availablePort)}) + require.NoError(t, err) + gRPCClient, err := NewGRPCClient(grpcConfig) + require.NoError(t, err) + + t.Cleanup(func() { + a.Shutdown() + gRPCClient.Conn.Close() + }) + + t.Run("test", func(t *testing.T) { + if err != nil { + fmt.Println("error when create new grpc client") + } + + v2Artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + writeRsp, err := gRPCClient.Client.Write(testutil.TestContext(t), &pbresource.WriteRequest{Resource: v2Artist}) + require.NoError(t, err) + + readRsp, err := gRPCClient.Client.Read(context.Background(), &pbresource.ReadRequest{Id: v2Artist.Id}) + require.NoError(t, err) + require.Equal(t, proto.Equal(readRsp.Resource.Id.Type, demo.TypeV2Artist), true) + prototest.AssertDeepEqual(t, writeRsp.Resource, readRsp.Resource) + }) +} + +func TestResourceReadInTLS(t *testing.T) { + tests := []struct { + name string + requireClientCert bool + grpcConfig func() (*GRPCConfig, int) + }{ + { + name: "Test with CertFile, KeyFile and CAFile", + requireClientCert: true, + grpcConfig: func() (*GRPCConfig, int) { + availablePort := freeport.GetOne(t) + return &GRPCConfig{ + Address: fmt.Sprintf("127.0.0.1:%d", availablePort), + GRPCTLS: true, + CertFile: "../../../test/client_certs/client.crt", + KeyFile: "../../../test/client_certs/client.key", + CAFile: "../../../test/client_certs/rootca.crt", + }, availablePort + }, + }, + { + name: "Test without CAFile", + requireClientCert: true, + grpcConfig: func() (*GRPCConfig, int) { + availablePort := freeport.GetOne(t) + return &GRPCConfig{ + Address: fmt.Sprintf("127.0.0.1:%d", availablePort), + GRPCTLS: true, + GRPCTLSVerify: false, + CertFile: "../../../test/client_certs/client.crt", + KeyFile: "../../../test/client_certs/client.key", + }, availablePort + }, + }, + { + name: "Test without client certificates", + requireClientCert: false, + grpcConfig: func() (*GRPCConfig, int) { + availablePort := freeport.GetOne(t) + return &GRPCConfig{ + Address: fmt.Sprintf("127.0.0.1:%d", availablePort), + GRPCTLS: true, + }, availablePort + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + grpcClientConfig, availablePort := tt.grpcConfig() + a := agent.StartTestAgent(t, agent.TestAgent{ + HCL: fmt.Sprintf(` + ports { grpc_tls = %d } + enable_agent_tls_for_checks = true + tls { + defaults { + verify_incoming = %t + key_file = "../../../test/client_certs/server.key" + cert_file = "../../../test/client_certs/server.crt" + ca_file = "../../../test/client_certs/rootca.crt" + } + }`, availablePort, tt.requireClientCert), + UseGRPCTLS: true, + }) + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + grpcConfig, err := LoadGRPCConfig(grpcClientConfig) + require.NoError(t, err) + gRPCClient, err := NewGRPCClient(grpcConfig) + require.NoError(t, err) + + t.Cleanup(func() { + a.Shutdown() + gRPCClient.Conn.Close() + }) + + v2Artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + _, err = gRPCClient.Client.Read(context.Background(), &pbresource.ReadRequest{Id: v2Artist.Id}) + require.Equal(t, codes.NotFound.String(), status.Code(err).String()) + + writeRsp, err := gRPCClient.Client.Write(testutil.TestContext(t), &pbresource.WriteRequest{Resource: v2Artist}) + require.NoError(t, err) + + readRsp, err := gRPCClient.Client.Read(context.Background(), &pbresource.ReadRequest{Id: v2Artist.Id}) + require.NoError(t, err) + require.Equal(t, proto.Equal(readRsp.Resource.Id.Type, demo.TypeV2Artist), true) + prototest.AssertDeepEqual(t, writeRsp.Resource, readRsp.Resource) + }) + } +} diff --git a/command/resource/client/grpc-config.go b/command/resource/client/grpc-config.go new file mode 100644 index 000000000000..988c2794a888 --- /dev/null +++ b/command/resource/client/grpc-config.go @@ -0,0 +1,174 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import ( + "fmt" + "os" + "strconv" + "strings" +) + +const ( + // GRPCAddrEnvName defines an environment variable name which sets the gRPC + // server address for the consul CLI. + GRPCAddrEnvName = "CONSUL_GRPC_ADDR" + + // GRPCTLSEnvName defines an environment variable name which sets the gRPC + // communication mode. Default is false in plaintext mode. + GRPCTLSEnvName = "CONSUL_GRPC_TLS" + + // GRPCTLSVerifyEnvName defines an environment variable name which sets + // whether to disable certificate checking. + GRPCTLSVerifyEnvName = "CONSUL_GRPC_TLS_VERIFY" + + // GRPCClientCertEnvName defines an environment variable name which sets the + // client cert file to use for talking to Consul over TLS. + GRPCClientCertEnvName = "CONSUL_GRPC_CLIENT_CERT" + + // GRPCClientKeyEnvName defines an environment variable name which sets the + // client key file to use for talking to Consul over TLS. + GRPCClientKeyEnvName = "CONSUL_GRPC_CLIENT_KEY" + + // GRPCCAFileEnvName defines an environment variable name which sets the + // CA file to use for talking to Consul gRPC over TLS. + GRPCCAFileEnvName = "CONSUL_GRPC_CACERT" + + // GRPCCAPathEnvName defines an environment variable name which sets the + // path to a directory of CA certs to use for talking to Consul gRPC over TLS. + GRPCCAPathEnvName = "CONSUL_GRPC_CAPATH" + + // GRPCTokenEnvName defines an environment variable name which sets + // the GRPC token. + GRPCTokenEnvName = "CONSUL_GRPC_TOKEN" + + // GRPCTokenFileEnvName defines an environment variable name which sets + // the GRPC token file. + GRPCTokenFileEnvName = "CONSUL_GRPC_TOKEN_FILE" +) + +type GRPCConfig struct { + // Address is the optional address of the Consul server in format of host:port. + // It doesn't include schema + Address string + + // GRPCTLS is the optional boolean flag to determine the communication protocol + GRPCTLS bool + + // GRPCTLSVerify is the optional boolean flag to disable certificate checking. + // Set to false only if you want to skip server verification + GRPCTLSVerify bool + + // CertFile is the optional path to the certificate for Consul + // communication. If this is set then you need to also set KeyFile. + CertFile string + + // KeyFile is the optional path to the private key for Consul communication. + // If this is set then you need to also set CertFile. + KeyFile string + + // CAFile is the optional path to the CA certificate used for Consul + // communication, defaults to the system bundle if not specified. + CAFile string + + // CAPath is the optional path to a directory of CA certificates to use for + // Consul communication, defaults to the system bundle if not specified. + CAPath string + + // Token is used to provide a per-request ACL token + // which overrides the agent's default token. + Token string + + // TokenFile is a file containing the current token to use for this client. + // If provided it is read once at startup and never again. + TokenFile string +} + +func GetDefaultGRPCConfig() *GRPCConfig { + return &GRPCConfig{ + Address: "127.0.0.1:8502", + GRPCTLSVerify: false, + } +} + +func LoadGRPCConfig(defaultConfig *GRPCConfig) (*GRPCConfig, error) { + if defaultConfig == nil { + defaultConfig = GetDefaultGRPCConfig() + } + + overwrittenConfig, err := loadEnvToDefaultConfig(defaultConfig) + if err != nil { + return nil, err + } + + return overwrittenConfig, nil +} + +func loadEnvToDefaultConfig(config *GRPCConfig) (*GRPCConfig, error) { + if addr := os.Getenv(GRPCAddrEnvName); addr != "" { + if strings.HasPrefix(strings.ToLower(addr), "https://") { + config.GRPCTLS = true + } + config.Address = removeSchemaFromGRPCAddress(addr) + } + + if tlsMode := os.Getenv(GRPCTLSEnvName); tlsMode != "" { + doTLS, err := strconv.ParseBool(tlsMode) + if err != nil { + return nil, fmt.Errorf("failed to parse %s: %w", GRPCTLSEnvName, err) + } + if doTLS { + config.GRPCTLS = true + } + } + + if v := os.Getenv(GRPCTLSVerifyEnvName); v != "" { + doVerify, err := strconv.ParseBool(v) + if err != nil { + return nil, fmt.Errorf("failed to parse %s: %w", GRPCTLSVerifyEnvName, err) + } + config.GRPCTLSVerify = doVerify + } + + if v := os.Getenv(GRPCClientCertEnvName); v != "" { + config.CertFile = v + } + + if v := os.Getenv(GRPCClientKeyEnvName); v != "" { + config.KeyFile = v + } + + if caFile := os.Getenv(GRPCCAFileEnvName); caFile != "" { + config.CAFile = caFile + } + + if caPath := os.Getenv(GRPCCAPathEnvName); caPath != "" { + config.CAPath = caPath + } + + if token := os.Getenv(GRPCTokenEnvName); token != "" { + config.Token = token + } + + if tokenFile := os.Getenv(GRPCTokenFileEnvName); tokenFile != "" { + config.TokenFile = tokenFile + } + + return config, nil +} + +func (c GRPCConfig) GetToken() (string, error) { + if c.TokenFile != "" { + data, err := os.ReadFile(c.TokenFile) + if err != nil { + return "", err + } + + return strings.TrimSpace(string(data)), nil + } + if c.Token != "" { + return c.Token, nil + } + return "", nil +} diff --git a/command/resource/client/grpc-config_test.go b/command/resource/client/grpc-config_test.go new file mode 100644 index 000000000000..fa7a54b470f2 --- /dev/null +++ b/command/resource/client/grpc-config_test.go @@ -0,0 +1,60 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestLoadGRPCConfig(t *testing.T) { + t.Run("Default Config", func(t *testing.T) { + // Test when defaultConfig is nil + config, err := LoadGRPCConfig(nil) + assert.NoError(t, err) + assert.Equal(t, GetDefaultGRPCConfig(), config) + }) + + // Test when environment variables are set + t.Run("Env Overwritten", func(t *testing.T) { + // Mock environment variables + t.Setenv(GRPCAddrEnvName, "localhost:8500") + t.Setenv(GRPCTLSEnvName, "true") + t.Setenv(GRPCTLSVerifyEnvName, "false") + t.Setenv(GRPCClientCertEnvName, "/path/to/client.crt") + t.Setenv(GRPCClientKeyEnvName, "/path/to/client.key") + t.Setenv(GRPCCAFileEnvName, "/path/to/ca.crt") + t.Setenv(GRPCCAPathEnvName, "/path/to/cacerts") + t.Setenv(GRPCTokenEnvName, "token") + t.Setenv(GRPCTokenFileEnvName, "/path/to/token/file") + + // Load and validate the configuration + config, err := LoadGRPCConfig(nil) + assert.NoError(t, err) + expectedConfig := &GRPCConfig{ + Address: "localhost:8500", + GRPCTLS: true, + GRPCTLSVerify: false, + CertFile: "/path/to/client.crt", + KeyFile: "/path/to/client.key", + CAFile: "/path/to/ca.crt", + CAPath: "/path/to/cacerts", + Token: "token", + TokenFile: "/path/to/token/file", + } + assert.Equal(t, expectedConfig, config) + }) + + // Test when there's an error parsing a boolean value from an environment variable + t.Run("Error Parsing Bool", func(t *testing.T) { + // Mock environment variable with an invalid boolean value + t.Setenv(GRPCTLSEnvName, "invalid_boolean_value") + + // Load and expect an error + config, err := LoadGRPCConfig(nil) + assert.Error(t, err, "failed to parse CONSUL_GRPC_TLS: strconv.ParseBool: parsing \"invalid_boolean_value\": invalid syntax") + assert.Nil(t, config) + }) +} diff --git a/command/resource/client/grpc-flags.go b/command/resource/client/grpc-flags.go new file mode 100644 index 000000000000..252b3dd516a5 --- /dev/null +++ b/command/resource/client/grpc-flags.go @@ -0,0 +1,90 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import ( + "flag" + "strings" +) + +type GRPCFlags struct { + address TValue[string] + grpcTLS TValue[bool] + certFile TValue[string] + keyFile TValue[string] + caFile TValue[string] + caPath TValue[string] + token TValue[string] + tokenFile TValue[string] +} + +// MergeFlagsIntoGRPCConfig merges flag values into grpc config +// caller has to parse the CLI args before loading them into flag values +// The flags take precedence over the environment values +func (f *GRPCFlags) MergeFlagsIntoGRPCConfig(c *GRPCConfig) { + if strings.HasPrefix(strings.ToLower(f.address.String()), "https://") { + c.GRPCTLS = true + } + if f.address.v != nil { + f.address.Set(removeSchemaFromGRPCAddress(f.address.String())) + f.address.Merge(&c.Address) + } + // won't overwrite the value if it's false + if f.grpcTLS.v != nil && *f.grpcTLS.v { + f.grpcTLS.Merge(&c.GRPCTLS) + } + f.certFile.Merge(&c.CertFile) + f.keyFile.Merge(&c.KeyFile) + f.caFile.Merge(&c.CAFile) + f.caPath.Merge(&c.CAPath) + f.token.Merge(&c.Token) + f.tokenFile.Merge(&c.TokenFile) +} + +// merge the client flags into command line flags then parse command line flags +func (f *GRPCFlags) ClientFlags() *flag.FlagSet { + fs := flag.NewFlagSet("", flag.ContinueOnError) + fs.Var(&f.address, "grpc-addr", + "The `address` and `port` of the Consul GRPC agent. The value can be an IP "+ + "address or DNS address, but it must also include the port. This can also be specified "+ + "via the CONSUL_GRPC_ADDR environment variable. The default value is "+ + "127.0.0.1:8502. If you intend to communicate in TLS mode, you have to either "+ + "include https:// schema in the address, use grpc-tls flag or set environment variable "+ + "CONSUL_GRPC_TLS = true, otherwise it uses plaintext mode") + fs.Var(&f.grpcTLS, "grpc-tls", + "Set to true if you aim to communicate in TLS mode in the GRPC call.") + fs.Var(&f.certFile, "client-cert", + "Path to a client cert file to use for TLS when 'verify_incoming' is enabled. This "+ + "can also be specified via the CONSUL_GRPC_CLIENT_CERT environment variable.") + fs.Var(&f.keyFile, "client-key", + "Path to a client key file to use for TLS when 'verify_incoming' is enabled. This "+ + "can also be specified via the CONSUL_GRPC_CLIENT_KEY environment variable.") + fs.Var(&f.caFile, "ca-file", + "Path to a CA file to use for TLS when communicating with Consul. This "+ + "can also be specified via the CONSUL_CACERT environment variable.") + fs.Var(&f.caPath, "ca-path", + "Path to a directory of CA certificates to use for TLS when communicating "+ + "with Consul. This can also be specified via the CONSUL_CAPATH environment variable.") + fs.Var(&f.token, "token", + "ACL token to use in the request. This can also be specified via the "+ + "CONSUL_GRPC_TOKEN environment variable. If unspecified, the query will "+ + "default to the token of the Consul agent at the GRPC address.") + fs.Var(&f.tokenFile, "token-file", + "File containing the ACL token to use in the request instead of one specified "+ + "via the -token-file argument or CONSUL_GRPC_TOKEN_FILE environment variable. "+ + "Notice the tokenFile takes precedence over token flag and environment variables.") + return fs +} + +func MergeFlags(dst, src *flag.FlagSet) { + if dst == nil { + panic("dst cannot be nil") + } + if src == nil { + return + } + src.VisitAll(func(f *flag.Flag) { + dst.Var(f.Value, f.Name, f.Usage) + }) +} diff --git a/command/resource/client/grpc-flags_test.go b/command/resource/client/grpc-flags_test.go new file mode 100644 index 000000000000..fff95f0560b2 --- /dev/null +++ b/command/resource/client/grpc-flags_test.go @@ -0,0 +1,104 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMergeFlagsIntoGRPCConfig(t *testing.T) { + t.Run("MergeFlagsIntoGRPCConfig", func(t *testing.T) { + // Setup GRPCFlags with some flag values + flags := &GRPCFlags{ + address: TValue[string]{v: stringPointer("https://example.com:8502")}, + grpcTLS: TValue[bool]{v: boolPointer(true)}, + certFile: TValue[string]{v: stringPointer("/path/to/client.crt")}, + keyFile: TValue[string]{v: stringPointer("/path/to/client.key")}, + caFile: TValue[string]{v: stringPointer("/path/to/ca.crt")}, + caPath: TValue[string]{v: stringPointer("/path/to/cacerts")}, + token: TValue[string]{v: stringPointer("token")}, + tokenFile: TValue[string]{v: stringPointer("/path/to/token/file")}, + } + + // Setup GRPCConfig with some initial values + config := &GRPCConfig{ + Address: "localhost:8500", + GRPCTLS: false, + GRPCTLSVerify: true, + CertFile: "/path/to/default/client.crt", + KeyFile: "/path/to/default/client.key", + CAFile: "/path/to/default/ca.crt", + CAPath: "/path/to/default/cacerts", + Token: "default-token", + TokenFile: "/path/to/default/token/file", + } + + // Call MergeFlagsIntoGRPCConfig to merge flag values into the config + flags.MergeFlagsIntoGRPCConfig(config) + + // Validate the merged config + expectedConfig := &GRPCConfig{ + Address: "example.com:8502", + GRPCTLS: true, + GRPCTLSVerify: true, + CertFile: "/path/to/client.crt", + KeyFile: "/path/to/client.key", + CAFile: "/path/to/ca.crt", + CAPath: "/path/to/cacerts", + Token: "token", + TokenFile: "/path/to/token/file", + } + + assert.Equal(t, expectedConfig, config) + }) + t.Run("MergeFlagsIntoGRPCConfig: allow empty values", func(t *testing.T) { + // Setup GRPCFlags with some flag values + flags := &GRPCFlags{ + address: TValue[string]{v: stringPointer("http://example.com:8502")}, + grpcTLS: TValue[bool]{}, + certFile: TValue[string]{v: stringPointer("/path/to/client.crt")}, + keyFile: TValue[string]{v: stringPointer("/path/to/client.key")}, + caFile: TValue[string]{v: stringPointer("/path/to/ca.crt")}, + caPath: TValue[string]{v: stringPointer("/path/to/cacerts")}, + } + + // Setup GRPCConfig with some initial values + config := &GRPCConfig{ + Address: "localhost:8500", + GRPCTLSVerify: true, + CertFile: "/path/to/default/client.crt", + KeyFile: "/path/to/default/client.key", + CAFile: "/path/to/default/ca.crt", + CAPath: "/path/to/default/cacerts", + } + + // Call MergeFlagsIntoGRPCConfig to merge flag values into the config + flags.MergeFlagsIntoGRPCConfig(config) + + // Validate the merged config + expectedConfig := &GRPCConfig{ + Address: "example.com:8502", + GRPCTLS: false, + GRPCTLSVerify: true, + CertFile: "/path/to/client.crt", + KeyFile: "/path/to/client.key", + CAFile: "/path/to/ca.crt", + CAPath: "/path/to/cacerts", + } + + assert.Equal(t, expectedConfig, config) + }) +} + +// Utility function to convert string to string pointer +func stringPointer(s string) *string { + return &s +} + +// Utility function to convert bool to bool pointer +func boolPointer(b bool) *bool { + return &b +} diff --git a/command/resource/client/grpc-resource-flags.go b/command/resource/client/grpc-resource-flags.go new file mode 100644 index 000000000000..576b39744db9 --- /dev/null +++ b/command/resource/client/grpc-resource-flags.go @@ -0,0 +1,44 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import "flag" + +type ResourceFlags struct { + partition TValue[string] + namespace TValue[string] + stale TValue[bool] +} + +func (f *ResourceFlags) ResourceFlags() *flag.FlagSet { + fs := flag.NewFlagSet("", flag.ContinueOnError) + fs.Var(&f.partition, "partition", + "Specifies the admin partition to query. If not provided, the admin partition will be inferred "+ + "from the request's ACL token, or will default to the `default` admin partition. "+ + "Admin Partitions are a Consul Enterprise feature.") + fs.Var(&f.namespace, "namespace", + "Specifies the namespace to query. If not provided, the namespace will be inferred "+ + "from the request's ACL token, or will default to the `default` namespace.") + fs.Var(&f.stale, "stale", + "Permit any Consul server (non-leader) to respond to this request. This "+ + "allows for lower latency and higher throughput, but can result in "+ + "stale data. This option has no effect on non-read operations. The "+ + "default value is false.") + return fs +} + +func (f *ResourceFlags) Partition() string { + return f.partition.String() +} + +func (f *ResourceFlags) Namespace() string { + return f.namespace.String() +} + +func (f *ResourceFlags) Stale() bool { + if f.stale.v == nil { + return false + } + return *f.stale.v +} diff --git a/command/resource/client/helper.go b/command/resource/client/helper.go new file mode 100644 index 000000000000..186691c50c03 --- /dev/null +++ b/command/resource/client/helper.go @@ -0,0 +1,93 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import ( + "crypto/tls" + "fmt" + "strconv" + "strings" + + "github.com/hashicorp/go-rootcerts" +) + +// tls.Config is used to establish communication in TLS mode +func SetupTLSConfig(c *GRPCConfig) (*tls.Config, error) { + tlsConfig := &tls.Config{ + InsecureSkipVerify: !c.GRPCTLSVerify, + } + + if c.CertFile != "" && c.KeyFile != "" { + tlsCert, err := tls.LoadX509KeyPair(c.CertFile, c.KeyFile) + if err != nil { + return nil, err + } + tlsConfig.Certificates = []tls.Certificate{tlsCert} + } + + var caConfig *rootcerts.Config + if c.CAFile != "" || c.CAPath != "" { + caConfig = &rootcerts.Config{ + CAFile: c.CAFile, + CAPath: c.CAPath, + } + } + // load system CA certs if user doesn't provide any + if err := rootcerts.ConfigureTLS(tlsConfig, caConfig); err != nil { + return nil, err + } + + return tlsConfig, nil +} + +func removeSchemaFromGRPCAddress(addr string) string { + // Parse as host:port with option http prefix + grpcAddr := strings.TrimPrefix(addr, "http://") + grpcAddr = strings.TrimPrefix(grpcAddr, "https://") + return grpcAddr +} + +type TValue[T string | bool] struct { + v *T +} + +// Set implements the flag.Value interface. +func (t *TValue[T]) Set(v string) error { + if t.v == nil { + t.v = new(T) + } + var err error + // have to use interface{}(t.v) to do type assertion + switch interface{}(t.v).(type) { + case *string: + // have to use interface{}(t.v).(*string) to assert t.v as *string + *(interface{}(t.v).(*string)) = v + case *bool: + // have to use interface{}(t.v).(*bool) to assert t.v as *bool + *(interface{}(t.v).(*bool)), err = strconv.ParseBool(v) + default: + err = fmt.Errorf("unsupported type %T", t.v) + } + return err +} + +// String implements the flag.Value interface. +func (t *TValue[T]) String() string { + var current T + if t.v != nil { + current = *(t.v) + } + return fmt.Sprintf("%v", current) +} + +// Merge will overlay this value if it has been set. +func (t *TValue[T]) Merge(onto *T) error { + if onto == nil { + return fmt.Errorf("onto is nil") + } + if t.v != nil { + *onto = *(t.v) + } + return nil +} diff --git a/command/resource/client/helper_test.go b/command/resource/client/helper_test.go new file mode 100644 index 000000000000..fbedc6552d33 --- /dev/null +++ b/command/resource/client/helper_test.go @@ -0,0 +1,70 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestTValue(t *testing.T) { + t.Run("String: set", func(t *testing.T) { + var tv TValue[string] + + err := tv.Set("testString") + assert.NoError(t, err) + + assert.Equal(t, *tv.v, "testString") + }) + + t.Run("String: merge", func(t *testing.T) { + var tv TValue[string] + var onto string + + testStr := "testString" + tv.v = &testStr + tv.Merge(&onto) + + assert.Equal(t, onto, "testString") + }) + + t.Run("String: merge nil", func(t *testing.T) { + var tv TValue[string] + var onto *string = nil + + testStr := "testString" + tv.v = &testStr + err := tv.Merge(onto) + + assert.Equal(t, err.Error(), "onto is nil") + }) + + t.Run("Get string", func(t *testing.T) { + var tv TValue[string] + testStr := "testString" + tv.v = &testStr + assert.Equal(t, tv.String(), "testString") + }) + + t.Run("Bool: set", func(t *testing.T) { + var tv TValue[bool] + + err := tv.Set("true") + assert.NoError(t, err) + + assert.Equal(t, *tv.v, true) + }) + + t.Run("Bool: merge", func(t *testing.T) { + var tv TValue[bool] + var onto bool + + testBool := true + tv.v = &testBool + tv.Merge(&onto) + + assert.Equal(t, onto, true) + }) +} diff --git a/command/resource/client/usage.go b/command/resource/client/usage.go new file mode 100644 index 000000000000..688b6de9a5ca --- /dev/null +++ b/command/resource/client/usage.go @@ -0,0 +1,85 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package client + +import ( + "bytes" + "flag" + "fmt" + "io" + "strings" + + "github.com/kr/text" +) + +func Usage(txt string, flags *flag.FlagSet) string { + u := &Usager{ + Usage: txt, + Flags: flags, + } + return u.String() +} + +type Usager struct { + Usage string + Flags *flag.FlagSet +} + +func (u *Usager) String() string { + out := new(bytes.Buffer) + out.WriteString(strings.TrimSpace(u.Usage)) + out.WriteString("\n") + out.WriteString("\n") + + if u.Flags != nil { + var cmdFlags *flag.FlagSet + u.Flags.VisitAll(func(f *flag.Flag) { + if cmdFlags == nil { + cmdFlags = flag.NewFlagSet("", flag.ContinueOnError) + } + cmdFlags.Var(f.Value, f.Name, f.Usage) + }) + + if cmdFlags != nil { + printTitle(out, "Command Options") + cmdFlags.VisitAll(func(f *flag.Flag) { + printFlag(out, f) + }) + } + } + + return strings.TrimRight(out.String(), "\n") +} + +// printTitle prints a consistently-formatted title to the given writer. +func printTitle(w io.Writer, s string) { + fmt.Fprintf(w, "%s\n\n", s) +} + +// printFlag prints a single flag to the given writer. +func printFlag(w io.Writer, f *flag.Flag) { + example, _ := flag.UnquoteUsage(f) + if example != "" { + fmt.Fprintf(w, " -%s=<%s>\n", f.Name, example) + } else { + fmt.Fprintf(w, " -%s\n", f.Name) + } + + indented := wrapAtLength(f.Usage, 5) + fmt.Fprintf(w, "%s\n\n", indented) +} + +// maxLineLength is the maximum width of any line. +const maxLineLength int = 72 + +// wrapAtLength wraps the given text at the maxLineLength, taking into account +// any provided left padding. +func wrapAtLength(s string, pad int) string { + wrapped := text.Wrap(s, maxLineLength-pad) + lines := strings.Split(wrapped, "\n") + for i, line := range lines { + lines[i] = strings.Repeat(" ", pad) + line + } + return strings.Join(lines, "\n") +} diff --git a/command/resource/delete-grpc/delete.go b/command/resource/delete-grpc/delete.go new file mode 100644 index 000000000000..c924a6bb9dc3 --- /dev/null +++ b/command/resource/delete-grpc/delete.go @@ -0,0 +1,163 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package delete + +import ( + "errors" + "flag" + "fmt" + + "github.com/mitchellh/cli" + + "github.com/hashicorp/consul/command/flags" + "github.com/hashicorp/consul/command/resource" + "github.com/hashicorp/consul/command/resource/client" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + grpcFlags *client.GRPCFlags + resourceFlags *client.ResourceFlags + help string + + filePath string +} + +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.flags.StringVar(&c.filePath, "f", "", + "File path with resource definition") + + c.grpcFlags = &client.GRPCFlags{} + c.resourceFlags = &client.ResourceFlags{} + client.MergeFlags(c.flags, c.grpcFlags.ClientFlags()) + client.MergeFlags(c.flags, c.resourceFlags.ResourceFlags()) + c.help = client.Usage(help, c.flags) +} + +func (c *cmd) Run(args []string) int { + var resourceType *pbresource.Type + var resourceTenancy *pbresource.Tenancy + var resourceName string + + if err := c.flags.Parse(args); err != nil { + if !errors.Is(err, flag.ErrHelp) { + c.UI.Error(fmt.Sprintf("Failed to parse args: %v", err)) + return 1 + } + c.UI.Error(fmt.Sprintf("Failed to run delete command: %v", err)) + return 1 + } + + // collect resource type, name and tenancy + if c.flags.Lookup("f").Value.String() != "" { + if c.filePath == "" { + c.UI.Error(fmt.Sprintf("Please provide an input file with resource definition")) + return 1 + } + parsedResource, err := resource.ParseResourceFromFile(c.filePath) + if err != nil { + c.UI.Error(fmt.Sprintf("Failed to decode resource from input file: %v", err)) + return 1 + } + + if parsedResource == nil { + c.UI.Error("Unable to parse the file argument") + return 1 + } + + resourceType = parsedResource.Id.Type + resourceTenancy = parsedResource.Id.Tenancy + resourceName = parsedResource.Id.Name + } else { + var err error + resourceType, resourceName, err = resource.GetTypeAndResourceName(args) + if err != nil { + c.UI.Error(fmt.Sprintf("Incorrect argument format: %s", err)) + return 1 + } + + inputArgs := args[2:] + err = resource.ParseInputParams(inputArgs, c.flags) + if err != nil { + c.UI.Error(fmt.Sprintf("Error parsing input arguments: %v", err)) + return 1 + } + if c.filePath != "" { + c.UI.Error("Incorrect argument format: File argument is not needed when resource information is provided with the command") + return 1 + } + resourceTenancy = &pbresource.Tenancy{ + Partition: c.resourceFlags.Partition(), + Namespace: c.resourceFlags.Namespace(), + } + } + + // initialize client + config, err := client.LoadGRPCConfig(nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Error loading config: %s", err)) + return 1 + } + c.grpcFlags.MergeFlagsIntoGRPCConfig(config) + resourceClient, err := client.NewGRPCClient(config) + if err != nil { + c.UI.Error(fmt.Sprintf("Error connect to Consul agent: %s", err)) + return 1 + } + + // delete resource + res := resource.ResourceGRPC{C: resourceClient} + err = res.Delete(resourceType, resourceTenancy, resourceName) + if err != nil { + c.UI.Error(fmt.Sprintf("Error deleting resource %s/%s: %v", resourceType, resourceName, err)) + return 1 + } + + c.UI.Info(fmt.Sprintf("%s.%s.%s/%s deleted", resourceType.Group, resourceType.GroupVersion, resourceType.Kind, resourceName)) + return 0 +} + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return flags.Usage(c.help, nil) +} + +const synopsis = "Delete resource information" +const help = ` +Usage: You have two options to delete the resource specified by the given +type, name, partition, namespace and peer and outputs its JSON representation. + +consul resource delete [type] [name] -partition= -namespace= -peer= +consul resource delete -f [resource_file_path] + +But you could only use one of the approaches. + +Example: + +$ consul resource delete catalog.v2beta1.Service card-processor -partition=billing -namespace=payments -peer=eu +$ consul resource delete -f resource.hcl + +In resource.hcl, it could be: +ID { + Type = gvk("catalog.v2beta1.Service") + Name = "card-processor" + Tenancy { + Partition = "billing" + Namespace = "payments" + PeerName = "eu" + } +} +` diff --git a/command/resource/delete-grpc/delete_test.go b/command/resource/delete-grpc/delete_test.go new file mode 100644 index 000000000000..a66cb5232497 --- /dev/null +++ b/command/resource/delete-grpc/delete_test.go @@ -0,0 +1,164 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 +package delete + +import ( + "errors" + "fmt" + "testing" + + "github.com/mitchellh/cli" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/agent" + "github.com/hashicorp/consul/command/resource/apply-grpc" + "github.com/hashicorp/consul/sdk/freeport" + "github.com/hashicorp/consul/testrpc" +) + +func TestResourceDeleteInvalidArgs(t *testing.T) { + t.Parallel() + + type tc struct { + args []string + expectedCode int + expectedErr error + } + + cases := map[string]tc{ + "nil args": { + args: nil, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: Must specify two arguments: resource type and resource name"), + }, + "empty args": { + args: []string{}, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: Must specify two arguments: resource type and resource name"), + }, + "missing file path": { + args: []string{"-f"}, + expectedCode: 1, + expectedErr: errors.New("Failed to parse args: flag needs an argument: -f"), + }, + "file not found": { + args: []string{"-f=../testdata/test.hcl"}, + expectedCode: 1, + expectedErr: errors.New("Failed to load data: Failed to read file: open ../testdata/test.hcl: no such file or directory"), + }, + "provide type and name": { + args: []string{"a.b.c"}, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: Must specify two arguments: resource type and resource name"), + }, + "provide type and name with -f": { + args: []string{"a.b.c", "name", "-f", "test.hcl"}, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: File argument is not needed when resource information is provided with the command"), + }, + "provide type and name with -f and other flags": { + args: []string{"a.b.c", "name", "-f", "test.hcl", "-namespace", "default"}, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: File argument is not needed when resource information is provided with the command"), + }, + "does not provide resource name after type": { + args: []string{"a.b.c", "-namespace", "default"}, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: Must provide resource name right after type"), + }, + "invalid resource type format": { + args: []string{"a.", "name", "-namespace", "default"}, + expectedCode: 1, + expectedErr: errors.New("Must provide resource type argument with either in group.version.kind format or its shorthand name"), + }, + } + + for desc, tc := range cases { + t.Run(desc, func(t *testing.T) { + ui := cli.NewMockUi() + c := New(ui) + + code := c.Run(tc.args) + + require.Equal(t, tc.expectedCode, code) + require.Contains(t, ui.ErrorWriter.String(), tc.expectedErr.Error()) + }) + } +} + +func createResource(t *testing.T, port int) { + applyUi := cli.NewMockUi() + applyCmd := apply.New(applyUi) + + args := []string{ + fmt.Sprintf("-grpc-addr=127.0.0.1:%d", port), + "-token=root", + } + + args = append(args, []string{"-f=../testdata/demo.hcl"}...) + + code := applyCmd.Run(args) + require.Equal(t, 0, code) + require.Empty(t, applyUi.ErrorWriter.String()) +} + +func TestResourceDelete(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + availablePort := freeport.GetOne(t) + a := agent.NewTestAgent(t, fmt.Sprintf("ports { grpc = %d }", availablePort)) + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + t.Cleanup(func() { + a.Shutdown() + }) + + defaultCmdArgs := []string{ + fmt.Sprintf("-grpc-addr=127.0.0.1:%d", availablePort), + "-token=root", + } + + cases := []struct { + name string + args []string + expectedCode int + createResource bool + }{ + { + name: "delete resource in hcl format", + args: []string{"-f=../testdata/demo.hcl"}, + expectedCode: 0, + createResource: true, + }, + { + name: "delete resource in command line format", + args: []string{"demo.v2.Artist", "korn", "-partition=default", "-namespace=default"}, + expectedCode: 0, + createResource: true, + }, + { + name: "delete resource that doesn't exist in command line format", + args: []string{"demo.v2.Artist", "korn", "-partition=default", "-namespace=default"}, + expectedCode: 0, + createResource: false, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ui := cli.NewMockUi() + c := New(ui) + cliArgs := append(tc.args, defaultCmdArgs...) + if tc.createResource { + createResource(t, availablePort) + } + code := c.Run(cliArgs) + require.Empty(t, ui.ErrorWriter.String()) + require.Equal(t, tc.expectedCode, code) + require.Contains(t, ui.OutputWriter.String(), "deleted") + }) + } +} diff --git a/command/resource/delete/delete.go b/command/resource/delete/delete.go index 06421d6d1e2d..bbe2d0413945 100644 --- a/command/resource/delete/delete.go +++ b/command/resource/delete/delete.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/consul/command/flags" "github.com/hashicorp/consul/command/resource" "github.com/hashicorp/consul/command/resource/client" + "github.com/hashicorp/consul/proto-public/pbresource" ) func New(ui cli.Ui) *cmd { @@ -38,7 +39,8 @@ func (c *cmd) init() { flags.Merge(c.flags, c.http.ClientFlags()) flags.Merge(c.flags, c.http.ServerFlags()) flags.Merge(c.flags, c.http.MultiTenancyFlags()) - flags.Merge(c.flags, c.http.AddPeerName()) + // TODO(peering/v2) add back ability to query peers + // flags.Merge(c.flags, c.http.AddPeerName()) c.help = flags.Usage(help, c.flags) } @@ -76,7 +78,6 @@ func (c *cmd) Run(args []string) int { opts = &client.QueryOptions{ Namespace: parsedResource.Id.Tenancy.GetNamespace(), Partition: parsedResource.Id.Tenancy.GetPartition(), - Peer: parsedResource.Id.Tenancy.GetPeerName(), Token: c.http.Token(), } } else { @@ -85,7 +86,13 @@ func (c *cmd) Run(args []string) int { } } else { var err error - gvk, resourceName, err = resource.GetTypeAndResourceName(args) + var resourceType *pbresource.Type + resourceType, resourceName, err = resource.GetTypeAndResourceName(args) + gvk = &resource.GVK{ + Group: resourceType.GetGroup(), + Version: resourceType.GetGroupVersion(), + Kind: resourceType.GetKind(), + } if err != nil { c.UI.Error(fmt.Sprintf("Incorrect argument format: %s", err)) return 1 @@ -104,7 +111,6 @@ func (c *cmd) Run(args []string) int { opts = &client.QueryOptions{ Namespace: c.http.Namespace(), Partition: c.http.Partition(), - Peer: c.http.PeerName(), Token: c.http.Token(), } } @@ -140,16 +146,16 @@ func (c *cmd) Help() string { const synopsis = "Delete resource information" const help = ` Usage: You have two options to delete the resource specified by the given -type, name, partition, namespace and peer and outputs its JSON representation. +type, name, partition and namespace and outputs its JSON representation. -consul resource delete [type] [name] -partition= -namespace= -peer= +consul resource delete [type] [name] -partition= -namespace= consul resource delete -f [resource_file_path] But you could only use one of the approaches. Example: -$ consul resource delete catalog.v2beta1.Service card-processor -partition=billing -namespace=payments -peer=eu +$ consul resource delete catalog.v2beta1.Service card-processor -partition=billing -namespace=payments $ consul resource delete -f resource.hcl In resource.hcl, it could be: @@ -159,7 +165,6 @@ ID { Tenancy { Namespace = "payments" Partition = "billing" - PeerName = "eu" } } ` diff --git a/command/resource/delete/delete_test.go b/command/resource/delete/delete_test.go index 7454455c941e..8e12aa486d92 100644 --- a/command/resource/delete/delete_test.go +++ b/command/resource/delete/delete_test.go @@ -67,7 +67,7 @@ func TestResourceDeleteInvalidArgs(t *testing.T) { "invalid resource type format": { args: []string{"a.", "name", "-namespace", "default"}, expectedCode: 1, - expectedErr: errors.New("Must provide resource type argument with either in group.verion.kind format or its shorthand name"), + expectedErr: errors.New("Must provide resource type argument with either in group.version.kind format or its shorthand name"), }, } @@ -129,13 +129,13 @@ func TestResourceDelete(t *testing.T) { }, { name: "delete resource in command line format", - args: []string{"demo.v2.Artist", "korn", "-partition=default", "-namespace=default", "-peer=local"}, + args: []string{"demo.v2.Artist", "korn", "-partition=default", "-namespace=default"}, expectedCode: 0, createResource: true, }, { name: "delete resource that doesn't exist in command line format", - args: []string{"demo.v2.Artist", "korn", "-partition=default", "-namespace=default", "-peer=local"}, + args: []string{"demo.v2.Artist", "korn", "-partition=default", "-namespace=default"}, expectedCode: 0, createResource: false, }, diff --git a/command/resource/helper.go b/command/resource/helper.go index 221a018599a7..69a06d9cc1a7 100644 --- a/command/resource/helper.go +++ b/command/resource/helper.go @@ -24,6 +24,8 @@ import ( "github.com/hashicorp/consul/proto-public/pbresource" ) +const JSON_INDENT = " " + type OuterResource struct { ID *ID `json:"id"` Owner *ID `json:"owner"` @@ -34,11 +36,12 @@ type OuterResource struct { } type Tenancy struct { - Namespace string `json:"namespace"` Partition string `json:"partition"` - PeerName string `json:"peerName"` + Namespace string `json:"namespace"` } +// TODO(peering/v2) handle v2 peering in the resource cli + type Type struct { Group string `json:"group"` GroupVersion string `json:"groupVersion"` @@ -150,7 +153,7 @@ func ParseInputParams(inputArgs []string, flags *flag.FlagSet) error { return nil } -func GetTypeAndResourceName(args []string) (gvk *GVK, resourceName string, e error) { +func GetTypeAndResourceName(args []string) (resourceType *pbresource.Type, resourceName string, e error) { if len(args) < 2 { return nil, "", fmt.Errorf("Must specify two arguments: resource type and resource name") } @@ -160,9 +163,9 @@ func GetTypeAndResourceName(args []string) (gvk *GVK, resourceName string, e err } resourceName = args[1] - gvk, e = inferGVKFromResourceType(args[0]) + resourceType, e = InferTypeFromResourceType(args[0]) - return + return resourceType, resourceName, e } type Resource struct { @@ -185,6 +188,10 @@ type ListResponse struct { Resources []map[string]interface{} `json:"resources"` } +func (gvk *GVK) String() string { + return fmt.Sprintf("%s.%s.%s", gvk.Group, gvk.Version, gvk.Kind) +} + func (resource *Resource) Read(gvk *GVK, resourceName string, q *client.QueryOptions) (map[string]interface{}, error) { r := resource.C.NewRequest("GET", strings.ToLower(fmt.Sprintf("/api/%s/%s/%s/%s", gvk.Group, gvk.Version, gvk.Kind, resourceName))) r.SetQueryOptions(q) @@ -263,7 +270,7 @@ func (resource *Resource) List(gvk *GVK, q *client.QueryOptions) (*ListResponse, return out, nil } -func inferGVKFromResourceType(resourceType string) (*GVK, error) { +func InferTypeFromResourceType(resourceType string) (*pbresource.Type, error) { s := strings.Split(resourceType, ".") switch length := len(s); { // only kind is provided @@ -278,23 +285,23 @@ func inferGVKFromResourceType(resourceType string) (*GVK, error) { case 1: // infer gvk from resource kind gvkSplit := strings.Split(kindToGVKMap[kind][0], ".") - return &GVK{ - Group: gvkSplit[0], - Version: gvkSplit[1], - Kind: gvkSplit[2], + return &pbresource.Type{ + Group: gvkSplit[0], + GroupVersion: gvkSplit[1], + Kind: gvkSplit[2], }, nil // it alerts error if any conflict is found default: return nil, fmt.Errorf("The shorthand name has conflicts %v, please use the full name", kindToGVKMap[s[0]]) } case length == 3: - return &GVK{ - Group: s[0], - Version: s[1], - Kind: s[2], + return &pbresource.Type{ + Group: s[0], + GroupVersion: s[1], + Kind: s[2], }, nil default: - return nil, fmt.Errorf("Must provide resource type argument with either in group.verion.kind format or its shorthand name") + return nil, fmt.Errorf("Must provide resource type argument with either in group.version.kind format or its shorthand name") } } diff --git a/command/resource/helper_test.go b/command/resource/helper_test.go index 003c2b7aa63a..1b3d6cbb29be 100644 --- a/command/resource/helper_test.go +++ b/command/resource/helper_test.go @@ -4,8 +4,9 @@ package resource import ( - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) func Test_parseJson(t *testing.T) { @@ -14,8 +15,8 @@ func Test_parseJson(t *testing.T) { js string wantErr bool }{ - {"valid resource", "{\n \"data\": {\n \"genre\": \"GENRE_METAL\",\n \"name\": \"Korn\"\n },\n \"generation\": \"01HAYWBPV1KMT2KWECJ6CEWDQ0\",\n \"id\": {\n \"name\": \"korn\",\n \"tenancy\": {\n \"namespace\": \"default\",\n \"partition\": \"default\",\n \"peerName\": \"local\"\n },\n \"type\": {\n \"group\": \"demo\",\n \"groupVersion\": \"v2\",\n \"kind\": \"Artist\"\n },\n \"uid\": \"01HAYWBPV1KMT2KWECJ4NW88S1\"\n },\n \"metadata\": {\n \"foo\": \"bar\"\n },\n \"version\": \"18\"\n}", false}, - {"invalid resource", "{\n \"data\": {\n \"genre\": \"GENRE_METAL\",\n \"name\": \"Korn\"\n },\n \"id\": {\n \"name\": \"korn\",\n \"tenancy\": {\n \"namespace\": \"default\",\n \"partition\": \"default\",\n \"peerName\": \"local\"\n },\n \"type\": \"\"\n },\n \"metadata\": {\n \"foo\": \"bar\"\n }\n}\n", true}, + {"valid resource", "{\n \"data\": {\n \"genre\": \"GENRE_METAL\",\n \"name\": \"Korn\"\n },\n \"generation\": \"01HAYWBPV1KMT2KWECJ6CEWDQ0\",\n \"id\": {\n \"name\": \"korn\",\n \"tenancy\": {\n \"namespace\": \"default\",\n \"partition\": \"default\"\n },\n \"type\": {\n \"group\": \"demo\",\n \"groupVersion\": \"v2\",\n \"kind\": \"Artist\"\n },\n \"uid\": \"01HAYWBPV1KMT2KWECJ4NW88S1\"\n },\n \"metadata\": {\n \"foo\": \"bar\"\n },\n \"version\": \"18\"\n}", false}, + {"invalid resource", "{\n \"data\": {\n \"genre\": \"GENRE_METAL\",\n \"name\": \"Korn\"\n },\n \"id\": {\n \"name\": \"korn\",\n \"tenancy\": {\n \"namespace\": \"default\",\n \"partition\": \"default\"\n },\n \"type\": \"\"\n },\n \"metadata\": {\n \"foo\": \"bar\"\n }\n}\n", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/command/resource/list-grpc/list.go b/command/resource/list-grpc/list.go new file mode 100644 index 000000000000..eea7621b9eff --- /dev/null +++ b/command/resource/list-grpc/list.go @@ -0,0 +1,192 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package list + +import ( + "encoding/json" + "errors" + "flag" + "fmt" + "strings" + + "github.com/mitchellh/cli" + + "github.com/hashicorp/consul/command/flags" + "github.com/hashicorp/consul/command/resource" + "github.com/hashicorp/consul/command/resource/client" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + grpcFlags *client.GRPCFlags + resourceFlags *client.ResourceFlags + help string + + filePath string + prefix string +} + +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.flags.StringVar(&c.filePath, "f", "", + "File path with resource definition") + c.flags.StringVar(&c.prefix, "p", "", + "Name prefix for listing resources if you need ambiguous match") + + c.grpcFlags = &client.GRPCFlags{} + c.resourceFlags = &client.ResourceFlags{} + client.MergeFlags(c.flags, c.grpcFlags.ClientFlags()) + client.MergeFlags(c.flags, c.resourceFlags.ResourceFlags()) + c.help = client.Usage(help, c.flags) +} + +func (c *cmd) Run(args []string) int { + var resourceType *pbresource.Type + var resourceTenancy *pbresource.Tenancy + + if err := c.flags.Parse(args); err != nil { + if !errors.Is(err, flag.ErrHelp) { + c.UI.Error(fmt.Sprintf("Failed to parse args: %v", err)) + return 1 + } + c.UI.Error(fmt.Sprintf("Failed to run list command: %v", err)) + return 1 + } + + // collect resource type, name and tenancy + if c.flags.Lookup("f").Value.String() != "" { + if c.filePath == "" { + c.UI.Error(fmt.Sprintf("Please provide an input file with resource definition")) + return 1 + } + parsedResource, err := resource.ParseResourceFromFile(c.filePath) + if err != nil { + c.UI.Error(fmt.Sprintf("Failed to decode resource from input file: %v", err)) + return 1 + } + + if parsedResource == nil { + c.UI.Error("Unable to parse the file argument") + return 1 + } + + resourceType = parsedResource.Id.Type + resourceTenancy = parsedResource.Id.Tenancy + } else { + var err error + args := c.flags.Args() + if err = validateArgs(args); err != nil { + c.UI.Error(fmt.Sprintf("Incorrect argument format: %s", err)) + return 1 + } + resourceType, err = resource.InferTypeFromResourceType(args[0]) + if err != nil { + c.UI.Error(fmt.Sprintf("Incorrect argument format: %s", err)) + return 1 + } + + // skip resource type to parse remaining args + inputArgs := c.flags.Args()[1:] + err = resource.ParseInputParams(inputArgs, c.flags) + if err != nil { + c.UI.Error(fmt.Sprintf("Error parsing input arguments: %v", err)) + return 1 + } + if c.filePath != "" { + c.UI.Error("Incorrect argument format: File argument is not needed when resource information is provided with the command") + return 1 + } + resourceTenancy = &pbresource.Tenancy{ + Partition: c.resourceFlags.Partition(), + Namespace: c.resourceFlags.Namespace(), + } + } + + // initialize client + config, err := client.LoadGRPCConfig(nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Error loading config: %s", err)) + return 1 + } + c.grpcFlags.MergeFlagsIntoGRPCConfig(config) + resourceClient, err := client.NewGRPCClient(config) + if err != nil { + c.UI.Error(fmt.Sprintf("Error connect to Consul agent: %s", err)) + return 1 + } + + // list resource + res := resource.ResourceGRPC{C: resourceClient} + entry, err := res.List(resourceType, resourceTenancy, c.prefix, c.resourceFlags.Stale()) + if err != nil { + c.UI.Error(fmt.Sprintf("Error listing resource %s/%s: %v", resourceType, c.prefix, err)) + return 1 + } + + // display response + b, err := json.MarshalIndent(entry, "", resource.JSON_INDENT) + if err != nil { + c.UI.Error("Failed to encode output data") + return 1 + } + + c.UI.Info(string(b)) + return 0 +} + +func validateArgs(args []string) error { + if args == nil { + return fmt.Errorf("Must include resource type or flag arguments") + } + if len(args) < 1 { + return fmt.Errorf("Must include resource type argument") + } + if len(args) > 1 && !strings.HasPrefix(args[1], "-") { + return fmt.Errorf("Must include flag arguments after resource type") + } + return nil +} + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return flags.Usage(c.help, nil) +} + +const synopsis = "Lists all resources by name prefix" +const help = ` +Usage: consul resource list [type] -partition= -namespace= -peer= +or +consul resource list -f [path/to/file.hcl] + +Lists all the resources specified by the type under the given partition, namespace and peer +and outputs in JSON format. + +Example: + +$ consul resource list catalog.v2beta1.Service -p=card -partition=billing -namespace=payments -peer=eu + +$ consul resource list -f=demo.hcl -p=card + +Sample demo.hcl: + +ID { + Type = gvk("group.version.kind") + Tenancy { + Partition = "default" + Namespace = "default" + PeerName = "local" + } + } +` diff --git a/command/resource/list-grpc/list_test.go b/command/resource/list-grpc/list_test.go new file mode 100644 index 000000000000..0b660f6874bd --- /dev/null +++ b/command/resource/list-grpc/list_test.go @@ -0,0 +1,192 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package list + +import ( + "errors" + "fmt" + "testing" + + "github.com/mitchellh/cli" + + "github.com/hashicorp/consul/agent" + "github.com/hashicorp/consul/sdk/freeport" + "github.com/hashicorp/consul/testrpc" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/command/resource/apply-grpc" +) + +func TestResourceListCommand(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + availablePort := freeport.GetOne(t) + a := agent.NewTestAgent(t, fmt.Sprintf("ports { grpc = %d }", availablePort)) + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + t.Cleanup(func() { + a.Shutdown() + }) + + applyCli := cli.NewMockUi() + + applyCmd := apply.New(applyCli) + code := applyCmd.Run([]string{ + "-f=../testdata/demo.hcl", + fmt.Sprintf("-grpc-addr=127.0.0.1:%d", availablePort), + "-token=root", + }) + require.Equal(t, 0, code) + require.Empty(t, applyCli.ErrorWriter.String()) + require.Contains(t, applyCli.OutputWriter.String(), "demo.v2.Artist 'korn' created.") + + cases := []struct { + name string + output string + extraArgs []string + }{ + { + name: "sample output", + output: "\"name\": \"korn\"", + extraArgs: []string{ + "demo.v2.Artist", + "-partition=default", + "-namespace=default", + }, + }, + { + name: "sample output with name prefix", + output: "\"name\": \"korn\"", + extraArgs: []string{ + "demo.v2.Artist", + "-p=korn", + "-partition=default", + "-namespace=default", + }, + }, + { + name: "file input", + output: "\"name\": \"korn\"", + extraArgs: []string{ + "-f=../testdata/demo.hcl", + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ui := cli.NewMockUi() + c := New(ui) + + args := []string{ + fmt.Sprintf("-grpc-addr=127.0.0.1:%d", availablePort), + "-token=root", + } + + args = append(args, tc.extraArgs...) + + actualCode := c.Run(args) + require.Equal(t, 0, actualCode) + require.Empty(t, ui.ErrorWriter.String()) + require.Contains(t, ui.OutputWriter.String(), tc.output) + }) + } +} + +func TestResourceListInvalidArgs(t *testing.T) { + t.Parallel() + + availablePort := freeport.GetOne(t) + a := agent.NewTestAgent(t, fmt.Sprintf("ports { grpc = %d }", availablePort)) + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + t.Cleanup(func() { + a.Shutdown() + }) + + type tc struct { + args []string + expectedCode int + expectedErr error + } + + cases := map[string]tc{ + "nil args": { + args: nil, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: Must include resource type or flag arguments"), + }, + "minimum args required": { + args: []string{}, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: Must include resource type argument"), + }, + "no file path": { + args: []string{ + "-f", + }, + expectedCode: 1, + expectedErr: errors.New("Failed to parse args: flag needs an argument: -f"), + }, + "file not found": { + args: []string{ + "-f=../testdata/test.hcl", + }, + expectedCode: 1, + expectedErr: errors.New("Failed to load data: Failed to read file: open ../testdata/test.hcl: no such file or directory"), + }, + "file parsing failure": { + args: []string{ + "-f=../testdata/invalid_type.hcl", + }, + expectedCode: 1, + expectedErr: errors.New("Failed to decode resource from input file"), + }, + "file argument with resource type": { + args: []string{ + "demo.v2.Artist", + "-partition=default", + "-namespace=default", + fmt.Sprintf("-grpc-addr=127.0.0.1:%d", availablePort), + "-token=root", + "-f=demo.hcl", + }, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: File argument is not needed when resource information is provided with the command"), + }, + "resource type invalid": { + args: []string{ + "test", + "-partition=default", + "-namespace=default", + }, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: The shorthand name does not map to any existing resource type"), + }, + "resource name is provided": { + args: []string{ + "demo.v2.Artist", + "test", + "-namespace=default", + "-partition=default", + }, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: Must include flag arguments after resource type"), + }, + } + + for desc, tc := range cases { + t.Run(desc, func(t *testing.T) { + ui := cli.NewMockUi() + c := New(ui) + + code := c.Run(tc.args) + + require.Equal(t, tc.expectedCode, code) + require.Contains(t, ui.ErrorWriter.String(), tc.expectedErr.Error()) + }) + } +} diff --git a/command/resource/list/list.go b/command/resource/list/list.go index d0a5f398a634..86e5fd875fc0 100644 --- a/command/resource/list/list.go +++ b/command/resource/list/list.go @@ -40,7 +40,8 @@ func (c *cmd) init() { flags.Merge(c.flags, c.http.ClientFlags()) flags.Merge(c.flags, c.http.ServerFlags()) flags.Merge(c.flags, c.http.MultiTenancyFlags()) - flags.Merge(c.flags, c.http.AddPeerName()) + // TODO(peering/v2) add back ability to query peers + // flags.Merge(c.flags, c.http.AddPeerName()) c.help = flags.Usage(help, c.flags) } @@ -76,7 +77,6 @@ func (c *cmd) Run(args []string) int { opts = &client.QueryOptions{ Namespace: parsedResource.Id.Tenancy.GetNamespace(), Partition: parsedResource.Id.Tenancy.GetPartition(), - Peer: parsedResource.Id.Tenancy.GetPeerName(), Token: c.http.Token(), RequireConsistent: !c.http.Stale(), } @@ -107,7 +107,6 @@ func (c *cmd) Run(args []string) int { opts = &client.QueryOptions{ Namespace: c.http.Namespace(), Partition: c.http.Partition(), - Peer: c.http.PeerName(), Token: c.http.Token(), RequireConsistent: !c.http.Stale(), } @@ -151,7 +150,7 @@ func getResourceType(args []string) (gvk *resource.GVK, e error) { s := strings.Split(args[0], ".") if len(s) < 3 { - return nil, fmt.Errorf("Must include resource type argument in group.verion.kind format") + return nil, fmt.Errorf("Must include resource type argument in group.version.kind format") } gvk = &resource.GVK{ Group: s[0], @@ -172,16 +171,16 @@ func (c *cmd) Help() string { const synopsis = "Reads all resources by type" const help = ` -Usage: consul resource list [type] -partition= -namespace= -peer= +Usage: consul resource list [type] -partition= -namespace= or consul resource list -f [path/to/file.hcl] -Lists all the resources specified by the type under the given partition, namespace and peer +Lists all the resources specified by the type under the given partition and namespace and outputs in JSON format. Example: -$ consul resource list catalog.v2beta1.Service card-processor -partition=billing -namespace=payments -peer=eu +$ consul resource list catalog.v2beta1.Service card-processor -partition=billing -namespace=payments $ consul resource list -f=demo.hcl @@ -193,7 +192,6 @@ ID { Tenancy { Namespace = "default" Partition = "default" - PeerName = "local" } } ` diff --git a/command/resource/list/list_test.go b/command/resource/list/list_test.go index b8fc12556a14..92afe4a6dc86 100644 --- a/command/resource/list/list_test.go +++ b/command/resource/list/list_test.go @@ -7,13 +7,14 @@ import ( "errors" "testing" + "github.com/mitchellh/cli" + "github.com/hashicorp/consul/agent" "github.com/hashicorp/consul/testrpc" - "github.com/mitchellh/cli" "github.com/stretchr/testify/require" - apply "github.com/hashicorp/consul/command/resource/apply" + "github.com/hashicorp/consul/command/resource/apply" ) func TestResourceListCommand(t *testing.T) { @@ -49,7 +50,6 @@ func TestResourceListCommand(t *testing.T) { extraArgs: []string{ "demo.v2.artist", "-namespace=default", - "-peer=local", "-partition=default", }, }, @@ -131,7 +131,6 @@ func TestResourceListInvalidArgs(t *testing.T) { args: []string{ "demo.v2.artist", "-namespace=default", - "-peer=local", "-partition=default", "-http-addr=" + a.HTTPAddr(), "-token=root", @@ -144,18 +143,16 @@ func TestResourceListInvalidArgs(t *testing.T) { args: []string{ "test", "-namespace=default", - "-peer=local", "-partition=default", }, expectedCode: 1, - expectedErr: errors.New("Must include resource type argument in group.verion.kind format"), + expectedErr: errors.New("Must include resource type argument in group.version.kind format"), }, "resource name is provided": { args: []string{ "demo.v2.artist", "test", "-namespace=default", - "-peer=local", "-partition=default", }, expectedCode: 1, diff --git a/command/resource/read-grpc/read.go b/command/resource/read-grpc/read.go new file mode 100644 index 000000000000..c681074ba708 --- /dev/null +++ b/command/resource/read-grpc/read.go @@ -0,0 +1,171 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package read + +import ( + "encoding/json" + "errors" + "flag" + "fmt" + + "github.com/mitchellh/cli" + + "github.com/hashicorp/consul/command/flags" + "github.com/hashicorp/consul/command/resource" + "github.com/hashicorp/consul/command/resource/client" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + grpcFlags *client.GRPCFlags + resourceFlags *client.ResourceFlags + help string + + filePath string +} + +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.flags.StringVar(&c.filePath, "f", "", + "File path with resource definition") + + c.grpcFlags = &client.GRPCFlags{} + c.resourceFlags = &client.ResourceFlags{} + client.MergeFlags(c.flags, c.grpcFlags.ClientFlags()) + client.MergeFlags(c.flags, c.resourceFlags.ResourceFlags()) + c.help = client.Usage(help, c.flags) +} + +func (c *cmd) Run(args []string) int { + var resourceType *pbresource.Type + var resourceTenancy *pbresource.Tenancy + var resourceName string + + if err := c.flags.Parse(args); err != nil { + if !errors.Is(err, flag.ErrHelp) { + c.UI.Error(fmt.Sprintf("Failed to parse args: %v", err)) + return 1 + } + c.UI.Error(fmt.Sprintf("Failed to run read command: %v", err)) + return 1 + } + + // collect resource type, name and tenancy + if c.flags.Lookup("f").Value.String() != "" { + if c.filePath == "" { + c.UI.Error(fmt.Sprintf("Please provide an input file with resource definition")) + return 1 + } + parsedResource, err := resource.ParseResourceFromFile(c.filePath) + if err != nil { + c.UI.Error(fmt.Sprintf("Failed to decode resource from input file: %v", err)) + return 1 + } + + if parsedResource == nil { + c.UI.Error("The parsed resource is nil") + return 1 + } + + resourceType = parsedResource.Id.Type + resourceTenancy = parsedResource.Id.Tenancy + resourceName = parsedResource.Id.Name + } else { + var err error + resourceType, resourceName, err = resource.GetTypeAndResourceName(args) + if err != nil { + c.UI.Error(fmt.Sprintf("Incorrect argument format: %s", err)) + return 1 + } + + inputArgs := args[2:] + err = resource.ParseInputParams(inputArgs, c.flags) + if err != nil { + c.UI.Error(fmt.Sprintf("Error parsing input arguments: %v", err)) + return 1 + } + if c.filePath != "" { + c.UI.Error("Incorrect argument format: File argument is not needed when resource information is provided with the command") + return 1 + } + resourceTenancy = &pbresource.Tenancy{ + Partition: c.resourceFlags.Partition(), + Namespace: c.resourceFlags.Namespace(), + } + } + + // initialize client + config, err := client.LoadGRPCConfig(nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Error loading config: %s", err)) + return 1 + } + c.grpcFlags.MergeFlagsIntoGRPCConfig(config) + resourceClient, err := client.NewGRPCClient(config) + if err != nil { + c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) + return 1 + } + + // read resource + res := resource.ResourceGRPC{C: resourceClient} + entry, err := res.Read(resourceType, resourceTenancy, resourceName, c.resourceFlags.Stale()) + if err != nil { + c.UI.Error(fmt.Sprintf("Error reading resource %s/%s: %v", resourceType, resourceName, err)) + return 1 + } + + // display response + b, err := json.MarshalIndent(entry, "", resource.JSON_INDENT) + if err != nil { + c.UI.Error("Failed to encode output data") + return 1 + } + + c.UI.Info(string(b)) + return 0 +} + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return flags.Usage(c.help, nil) +} + +const synopsis = "Read resource information" +const help = ` +Usage: You have two options to read the resource specified by the given +type, name, partition, namespace and peer and outputs its JSON representation. + +consul resource read [type] [name] -partition= -namespace= -peer= +consul resource read -f [resource_file_path] + +But you could only use one of the approaches. + +Example: + +$ consul resource read catalog.v2beta1.Service card-processor -partition=billing -namespace=payments -peer=eu +$ consul resource read -f resource.hcl + +In resource.hcl, it could be: +ID { + Type = gvk("catalog.v2beta1.Service") + Name = "card-processor" + Tenancy { + Partition = "billing" + Namespace = "payments" + PeerName = "eu" + } +} +` diff --git a/command/resource/read-grpc/read_test.go b/command/resource/read-grpc/read_test.go new file mode 100644 index 000000000000..b38388eb9e74 --- /dev/null +++ b/command/resource/read-grpc/read_test.go @@ -0,0 +1,161 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 +package read + +import ( + "errors" + "fmt" + "testing" + + "github.com/mitchellh/cli" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/agent" + "github.com/hashicorp/consul/command/resource/apply-grpc" + "github.com/hashicorp/consul/sdk/freeport" + "github.com/hashicorp/consul/testrpc" +) + +func TestResourceReadInvalidArgs(t *testing.T) { + t.Parallel() + + type tc struct { + args []string + expectedCode int + expectedErr error + } + + cases := map[string]tc{ + "nil args": { + args: nil, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: Must specify two arguments: resource type and resource name"), + }, + "empty args": { + args: []string{}, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: Must specify two arguments: resource type and resource name"), + }, + "missing file path": { + args: []string{"-f"}, + expectedCode: 1, + expectedErr: errors.New("Failed to parse args: flag needs an argument: -f"), + }, + "file not found": { + args: []string{"-f=../testdata/test.hcl"}, + expectedCode: 1, + expectedErr: errors.New("Failed to load data: Failed to read file: open ../testdata/test.hcl: no such file or directory"), + }, + "provide type and name": { + args: []string{"a.b.c"}, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: Must specify two arguments: resource type and resource name"), + }, + "provide type and name with -f": { + args: []string{"a.b.c", "name", "-f", "test.hcl"}, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: File argument is not needed when resource information is provided with the command"), + }, + "provide type and name with -f and other flags": { + args: []string{"a.b.c", "name", "-f", "test.hcl", "-namespace", "default"}, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: File argument is not needed when resource information is provided with the command"), + }, + "does not provide resource name after type": { + args: []string{"a.b.c", "-namespace", "default"}, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: Must provide resource name right after type"), + }, + "invalid resource type format": { + args: []string{"a.", "name", "-namespace", "default"}, + expectedCode: 1, + expectedErr: errors.New("Incorrect argument format: Must provide resource type argument with either in group.version.kind format or its shorthand name"), + }, + } + + for desc, tc := range cases { + t.Run(desc, func(t *testing.T) { + ui := cli.NewMockUi() + c := New(ui) + + code := c.Run(tc.args) + + require.Equal(t, tc.expectedCode, code) + require.Contains(t, ui.ErrorWriter.String(), tc.expectedErr.Error()) + }) + } +} + +func createResource(t *testing.T, port int) { + applyUi := cli.NewMockUi() + applyCmd := apply.New(applyUi) + + args := []string{ + fmt.Sprintf("-grpc-addr=127.0.0.1:%d", port), + "-token=root", + } + + args = append(args, []string{"-f=../testdata/demo.hcl"}...) + + code := applyCmd.Run(args) + require.Equal(t, 0, code) + require.Empty(t, applyUi.ErrorWriter.String()) +} + +func TestResourceRead(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + availablePort := freeport.GetOne(t) + a := agent.NewTestAgent(t, fmt.Sprintf("ports { grpc = %d }", availablePort)) + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + t.Cleanup(func() { + a.Shutdown() + }) + + defaultCmdArgs := []string{ + fmt.Sprintf("-grpc-addr=127.0.0.1:%d", availablePort), + "-token=root", + } + + createResource(t, availablePort) + cases := []struct { + name string + args []string + expectedCode int + errMsg string + }{ + { + name: "read resource in hcl format", + args: []string{"-f=../testdata/demo.hcl"}, + expectedCode: 0, + errMsg: "", + }, + { + name: "read resource in command line format", + args: []string{"demo.v2.Artist", "korn", "-partition=default", "-namespace=default"}, + expectedCode: 0, + errMsg: "", + }, + { + name: "read resource that doesn't exist", + args: []string{"demo.v2.Artist", "fake-korn", "-partition=default", "-namespace=default"}, + expectedCode: 1, + errMsg: "error reading resource: rpc error: code = NotFound desc = resource not found\n", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ui := cli.NewMockUi() + c := New(ui) + cliArgs := append(tc.args, defaultCmdArgs...) + code := c.Run(cliArgs) + require.Contains(t, ui.ErrorWriter.String(), tc.errMsg) + require.Equal(t, tc.expectedCode, code) + }) + } +} diff --git a/command/resource/read/read.go b/command/resource/read/read.go index fe35521056ba..14c38c45f48e 100644 --- a/command/resource/read/read.go +++ b/command/resource/read/read.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/consul/command/flags" "github.com/hashicorp/consul/command/resource" "github.com/hashicorp/consul/command/resource/client" + "github.com/hashicorp/consul/proto-public/pbresource" ) func New(ui cli.Ui) *cmd { @@ -39,7 +40,8 @@ func (c *cmd) init() { flags.Merge(c.flags, c.http.ClientFlags()) flags.Merge(c.flags, c.http.ServerFlags()) flags.Merge(c.flags, c.http.MultiTenancyFlags()) - flags.Merge(c.flags, c.http.AddPeerName()) + // TODO(peering/v2) add back ability to query peers + // flags.Merge(c.flags, c.http.AddPeerName()) c.help = flags.Usage(help, c.flags) } @@ -77,7 +79,6 @@ func (c *cmd) Run(args []string) int { opts = &client.QueryOptions{ Namespace: parsedResource.Id.Tenancy.GetNamespace(), Partition: parsedResource.Id.Tenancy.GetPartition(), - Peer: parsedResource.Id.Tenancy.GetPeerName(), Token: c.http.Token(), RequireConsistent: !c.http.Stale(), } @@ -86,12 +87,14 @@ func (c *cmd) Run(args []string) int { return 1 } } else { - if len(args) < 2 { - c.UI.Error("Incorrect argument format: Must specify two arguments: resource type and resource name") - return 1 - } var err error - gvk, resourceName, err = resource.GetTypeAndResourceName(args) + var resourceType *pbresource.Type + resourceType, resourceName, err = resource.GetTypeAndResourceName(args) + gvk = &resource.GVK{ + Group: resourceType.GetGroup(), + Version: resourceType.GetGroupVersion(), + Kind: resourceType.GetKind(), + } if err != nil { c.UI.Error(fmt.Sprintf("Incorrect argument format: %s", err)) return 1 @@ -110,7 +113,6 @@ func (c *cmd) Run(args []string) int { opts = &client.QueryOptions{ Namespace: c.http.Namespace(), Partition: c.http.Partition(), - Peer: c.http.PeerName(), Token: c.http.Token(), RequireConsistent: !c.http.Stale(), } @@ -154,16 +156,16 @@ func (c *cmd) Help() string { const synopsis = "Read resource information" const help = ` Usage: You have two options to read the resource specified by the given -type, name, partition, namespace and peer and outputs its JSON representation. +type, name, partition and namespace and outputs its JSON representation. -consul resource read [type] [name] -partition= -namespace= -peer= +consul resource read [type] [name] -partition= -namespace= consul resource read -f [resource_file_path] But you could only use one of the approaches. Example: -$ consul resource read catalog.v2beta1.Service card-processor -partition=billing -namespace=payments -peer=eu +$ consul resource read catalog.v2beta1.Service card-processor -partition=billing -namespace=payments $ consul resource read -f resource.hcl In resource.hcl, it could be: @@ -173,7 +175,6 @@ ID { Tenancy { Namespace = "payments" Partition = "billing" - PeerName = "eu" } } ` diff --git a/command/resource/read/read_test.go b/command/resource/read/read_test.go index a293a9faf5e2..1a4de5703e1d 100644 --- a/command/resource/read/read_test.go +++ b/command/resource/read/read_test.go @@ -67,7 +67,7 @@ func TestResourceReadInvalidArgs(t *testing.T) { "invalid resource type format": { args: []string{"a.", "name", "-namespace", "default"}, expectedCode: 1, - expectedErr: errors.New("Incorrect argument format: Must provide resource type argument with either in group.verion.kind format or its shorthand name"), + expectedErr: errors.New("Incorrect argument format: Must provide resource type argument with either in group.version.kind format or its shorthand name"), }, } @@ -131,15 +131,15 @@ func TestResourceRead(t *testing.T) { }, { name: "read resource in command line format", - args: []string{"demo.v2.Artist", "korn", "-partition=default", "-namespace=default", "-peer=local"}, + args: []string{"demo.v2.Artist", "korn", "-partition=default", "-namespace=default"}, expectedCode: 0, errMsg: "", }, { name: "read resource that doesn't exist", - args: []string{"demo.v2.Artist", "fake-korn", "-partition=default", "-namespace=default", "-peer=local"}, + args: []string{"demo.v2.Artist", "fake-korn", "-partition=default", "-namespace=default"}, expectedCode: 1, - errMsg: "Error reading resource &{demo v2 Artist}/fake-korn: Unexpected response code: 404 (rpc error: code = NotFound desc = resource not found)\n", + errMsg: "Error reading resource demo.v2.Artist/fake-korn: Unexpected response code: 404 (rpc error: code = NotFound desc = resource not found)\n", }, } @@ -149,7 +149,7 @@ func TestResourceRead(t *testing.T) { c := New(ui) cliArgs := append(tc.args, defaultCmdArgs...) code := c.Run(cliArgs) - require.Equal(t, ui.ErrorWriter.String(), tc.errMsg) + require.Equal(t, tc.errMsg, ui.ErrorWriter.String()) require.Equal(t, tc.expectedCode, code) }) } diff --git a/command/resource/resource-grpc.go b/command/resource/resource-grpc.go new file mode 100644 index 000000000000..94d7314597d9 --- /dev/null +++ b/command/resource/resource-grpc.go @@ -0,0 +1,123 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package resource + +import ( + "context" + "fmt" + + "google.golang.org/grpc/metadata" + + "github.com/hashicorp/consul/command/resource/client" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +const ( + HeaderConsulToken = "x-consul-token" +) + +type ResourceGRPC struct { + C *client.GRPCClient +} + +func (resource *ResourceGRPC) Apply(parsedResource *pbresource.Resource) (*pbresource.Resource, error) { + token, err := resource.C.Config.GetToken() + if err != nil { + return nil, err + } + ctx := context.Background() + if token != "" { + ctx = metadata.AppendToOutgoingContext(context.Background(), HeaderConsulToken, token) + } + + defer resource.C.Conn.Close() + writeRsp, err := resource.C.Client.Write(ctx, &pbresource.WriteRequest{Resource: parsedResource}) + if err != nil { + return nil, fmt.Errorf("error writing resource: %+v", err) + } + + return writeRsp.Resource, err +} + +func (resource *ResourceGRPC) Read(resourceType *pbresource.Type, resourceTenancy *pbresource.Tenancy, resourceName string, stale bool) (*pbresource.Resource, error) { + token, err := resource.C.Config.GetToken() + if err != nil { + return nil, err + } + ctx := context.Background() + if !stale { + ctx = metadata.AppendToOutgoingContext(ctx, "x-consul-consistency-mode", "consistent") + } + if token != "" { + ctx = metadata.AppendToOutgoingContext(context.Background(), HeaderConsulToken, token) + } + + defer resource.C.Conn.Close() + readRsp, err := resource.C.Client.Read(ctx, &pbresource.ReadRequest{ + Id: &pbresource.ID{ + Type: resourceType, + Tenancy: resourceTenancy, + Name: resourceName, + }, + }) + + if err != nil { + return nil, fmt.Errorf("error reading resource: %+v", err) + } + + return readRsp.Resource, err +} + +func (resource *ResourceGRPC) List(resourceType *pbresource.Type, resourceTenancy *pbresource.Tenancy, prefix string, stale bool) ([]*pbresource.Resource, error) { + token, err := resource.C.Config.GetToken() + if err != nil { + return nil, err + } + ctx := context.Background() + if !stale { + ctx = metadata.AppendToOutgoingContext(ctx, "x-consul-consistency-mode", "consistent") + } + if token != "" { + ctx = metadata.AppendToOutgoingContext(context.Background(), HeaderConsulToken, token) + } + + defer resource.C.Conn.Close() + listRsp, err := resource.C.Client.List(ctx, &pbresource.ListRequest{ + Type: resourceType, + Tenancy: resourceTenancy, + NamePrefix: prefix, + }) + + if err != nil { + return nil, fmt.Errorf("error listing resource: %+v", err) + } + + return listRsp.Resources, err +} + +func (resource *ResourceGRPC) Delete(resourceType *pbresource.Type, resourceTenancy *pbresource.Tenancy, resourceName string) error { + token, err := resource.C.Config.GetToken() + if err != nil { + return err + } + ctx := context.Background() + if token != "" { + ctx = metadata.AppendToOutgoingContext(context.Background(), HeaderConsulToken, token) + } + + defer resource.C.Conn.Close() + _, err = resource.C.Client.Delete(ctx, &pbresource.DeleteRequest{ + Id: &pbresource.ID{ + Type: resourceType, + Tenancy: resourceTenancy, + Name: resourceName, + }, + }) + + if err != nil { + return fmt.Errorf("error deleting resource: %+v", err) + } + + return nil +} diff --git a/command/resource/resource.go b/command/resource/resource.go index 709b03e4e49d..e7a74e498b9c 100644 --- a/command/resource/resource.go +++ b/command/resource/resource.go @@ -37,7 +37,7 @@ in the subcommands or the documentation. Read a resource: -$ consul resource read [type] [name] -partition= -namespace= -peer= -consistent= -json +$ consul resource read [type] [name] -partition= -namespace= -consistent= -json Write/update a resource: @@ -45,7 +45,7 @@ $ consul resource apply -f= List resources by type: -$ consul resource list [type] -partition= -namespace= -peer= +$ consul resource list [type] -partition= -namespace= Run diff --git a/command/resource/testdata/demo.hcl b/command/resource/testdata/demo.hcl index 35e72aba3125..9449bb0de7d6 100644 --- a/command/resource/testdata/demo.hcl +++ b/command/resource/testdata/demo.hcl @@ -5,9 +5,8 @@ ID { Type = gvk("demo.v2.Artist") Name = "korn" Tenancy { - Namespace = "default" Partition = "default" - PeerName = "local" + Namespace = "default" } } diff --git a/command/resource/testdata/invalid.hcl b/command/resource/testdata/invalid.hcl index 04c08e9212f2..5ab99b674c55 100644 --- a/command/resource/testdata/invalid.hcl +++ b/command/resource/testdata/invalid.hcl @@ -5,9 +5,8 @@ ID { Type = gvk("demo.v2.Artist") Name = "korn" Tenancy { - Namespace = "default" Partition = "default" - PeerName = "local" + Namespace = "default" } } diff --git a/command/resource/testdata/invalid_type.hcl b/command/resource/testdata/invalid_type.hcl index b3b87ae2458b..4b791bdffbd2 100644 --- a/command/resource/testdata/invalid_type.hcl +++ b/command/resource/testdata/invalid_type.hcl @@ -4,8 +4,7 @@ D { Type = gvk("demo.v2.Artist") Tenancy { - Namespace = "default" Partition = "default" - PeerName = "local" + Namespace = "default" } } diff --git a/command/resource/testdata/nested_data.hcl b/command/resource/testdata/nested_data.hcl index b62875c732b4..f52ed804beef 100644 --- a/command/resource/testdata/nested_data.hcl +++ b/command/resource/testdata/nested_data.hcl @@ -2,28 +2,30 @@ # SPDX-License-Identifier: BUSL-1.1 ID { - Type = gvk("mesh.v2beta1.Destinations") - Name = "api" + Type = gvk("demo.v2.Festival") + Name = "woodstock" } Data { - Workloads { - Prefixes = ["api"] - } + Genres = [ + "GENRE_JAZZ", + "GENRE_FOLK", + "GENRE_BLUES", + "GENRE_ROCK", + ] - Destinations = [ + Artists = [ { - DestinationRef = { - Type = gvk("catalog.v2beta1.Service") - Name = "db" - } - - DestinationPort = "tcp" - - IpPort = { - Ip = "127.0.0.1" - Port = 1234 - } + Name = "Arlo Guthrie" + Genre = "GENRE_FOLK" + }, + { + Name = "Santana" + Genre = "GENRE_BLUES" + }, + { + Name = "Grateful Dead" + Genre = "GENRE_ROCK" } ] } diff --git a/command/rtt/rtt.go b/command/rtt/rtt.go index db9e3efd06be..a26e2268ec2c 100644 --- a/command/rtt/rtt.go +++ b/command/rtt/rtt.go @@ -8,11 +8,12 @@ import ( "fmt" "strings" - "github.com/hashicorp/serf/coordinate" "github.com/mitchellh/cli" + "github.com/hashicorp/serf/coordinate" + "github.com/hashicorp/consul/command/flags" - "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/internal/gossip/librtt" ) // TODO(partitions): how will this command work when asking for RTT between a @@ -146,7 +147,7 @@ func (c *cmd) Run(args []string) int { } // Index all the coordinates by segment. - cs1, cs2 := make(lib.CoordinateSet), make(lib.CoordinateSet) + cs1, cs2 := make(librtt.CoordinateSet), make(librtt.CoordinateSet) for _, entry := range entries { if strings.EqualFold(entry.Node, nodes[0]) { cs1[entry.Segment] = entry.Coord diff --git a/command/services/exportedservices/exported_services.go b/command/services/exportedservices/exported_services.go new file mode 100644 index 000000000000..99710024b10b --- /dev/null +++ b/command/services/exportedservices/exported_services.go @@ -0,0 +1,176 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package exportedservices + +import ( + "encoding/json" + "flag" + "fmt" + "strings" + + "github.com/mitchellh/cli" + + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/command/flags" + "github.com/hashicorp/go-bexpr" + "github.com/ryanuber/columnize" +) + +const ( + PrettyFormat string = "pretty" + JSONFormat string = "json" +) + +func getSupportedFormats() []string { + return []string{PrettyFormat, JSONFormat} +} + +func formatIsValid(f string) bool { + for _, format := range getSupportedFormats() { + if f == format { + return true + } + } + return false + +} + +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + http *flags.HTTPFlags + help string + + format string + filter string +} + +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + + c.flags.StringVar( + &c.format, + "format", + PrettyFormat, + fmt.Sprintf("Output format {%s} (default: %s)", strings.Join(getSupportedFormats(), "|"), PrettyFormat), + ) + + c.flags.StringVar(&c.filter, "filter", "", "go-bexpr filter string to filter the response") + + c.http = &flags.HTTPFlags{} + flags.Merge(c.flags, c.http.ClientFlags()) + flags.Merge(c.flags, c.http.ServerFlags()) + flags.Merge(c.flags, c.http.PartitionFlag()) + c.help = flags.Usage(help, c.flags) +} + +func (c *cmd) Run(args []string) int { + if err := c.flags.Parse(args); err != nil { + return 1 + } + + if !formatIsValid(c.format) { + c.UI.Error(fmt.Sprintf("Invalid format, valid formats are {%s}", strings.Join(getSupportedFormats(), "|"))) + return 1 + } + + client, err := c.http.APIClient() + if err != nil { + c.UI.Error(fmt.Sprintf("Error connect to Consul agent: %s", err)) + return 1 + } + + exportedServices, _, err := client.ExportedServices(nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Error reading exported services: %v", err)) + return 1 + } + + var filterType []api.ResolvedExportedService + filter, err := bexpr.CreateFilter(c.filter, nil, filterType) + if err != nil { + c.UI.Error(fmt.Sprintf("Error while creating filter: %s", err)) + return 1 + } + + raw, err := filter.Execute(exportedServices) + if err != nil { + c.UI.Error(fmt.Sprintf("Error while filtering response: %s", err)) + return 1 + } + + filteredServices := raw.([]api.ResolvedExportedService) + + if len(filteredServices) == 0 { + c.UI.Info("No exported services found") + return 0 + } + + if c.format == JSONFormat { + output, err := json.MarshalIndent(filteredServices, "", " ") + if err != nil { + c.UI.Error(fmt.Sprintf("Error marshalling JSON: %s", err)) + return 1 + } + c.UI.Output(string(output)) + return 0 + } + + c.UI.Output(formatExportedServices(filteredServices)) + + return 0 +} + +func formatExportedServices(services []api.ResolvedExportedService) string { + result := make([]string, 0, len(services)+1) + + if services[0].Partition != "" { + result = append(result, "Service\x1fPartition\x1fNamespace\x1fConsumer Peers\x1fConsumer Partitions") + } else { + result = append(result, "Service\x1fConsumer Peers") + } + + for _, expService := range services { + row := "" + peers := strings.Join(expService.Consumers.Peers, ", ") + partitions := strings.Join(expService.Consumers.Partitions, ", ") + if expService.Partition != "" { + row = fmt.Sprintf("%s\x1f%s\x1f%s\x1f%s\x1f%s", expService.Service, expService.Partition, expService.Namespace, peers, partitions) + } else { + row = fmt.Sprintf("%s\x1f%s", expService.Service, peers) + } + + result = append(result, row) + + } + + return columnize.Format(result, &columnize.Config{Delim: string([]byte{0x1f})}) +} + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return flags.Usage(c.help, nil) +} + +const ( + synopsis = "Lists exported services" + help = ` +Usage: consul services exported-services [options] + + Lists all the exported services and their consumers. Wildcards and sameness groups(Enterprise) are expanded. + + Example: + + $ consul services exported-services +` +) diff --git a/command/services/exportedservices/exported_services_test.go b/command/services/exportedservices/exported_services_test.go new file mode 100644 index 000000000000..568646051937 --- /dev/null +++ b/command/services/exportedservices/exported_services_test.go @@ -0,0 +1,323 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package exportedservices + +import ( + "encoding/json" + "testing" + + "github.com/hashicorp/consul/agent" + "github.com/hashicorp/consul/api" + "github.com/mitchellh/cli" + + "github.com/stretchr/testify/require" +) + +func TestExportedServices_noTabs(t *testing.T) { + t.Parallel() + + require.NotContains(t, New(cli.NewMockUi()).Help(), "\t") +} + +func TestExportedServices_Error(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + a := agent.NewTestAgent(t, ``) + defer a.Shutdown() + + t.Run("No exported services", func(t *testing.T) { + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + } + + code := cmd.Run(args) + require.Equal(t, 0, code) + + output := ui.OutputWriter.String() + require.Equal(t, "No exported services found\n", output) + }) + + t.Run("invalid format", func(t *testing.T) { + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-format=toml", + } + + code := cmd.Run(args) + require.Equal(t, 1, code, "exited successfully when it should have failed") + output := ui.ErrorWriter.String() + require.Contains(t, output, "Invalid format") + }) +} + +func TestExportedServices_Pretty(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + a := agent.NewTestAgent(t, ``) + defer a.Shutdown() + client := a.Client() + + ui := cli.NewMockUi() + c := New(ui) + + set, _, err := client.ConfigEntries().Set(&api.ExportedServicesConfigEntry{ + Name: "default", + Services: []api.ExportedService{ + { + Name: "db", + Consumers: []api.ServiceConsumer{ + { + Peer: "east", + }, + { + Peer: "west", + }, + }, + }, + { + Name: "web", + Consumers: []api.ServiceConsumer{ + { + Peer: "east", + }, + }, + }, + }, + }, nil) + require.NoError(t, err) + require.True(t, set) + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + } + + code := c.Run(args) + require.Equal(t, 0, code) + + output := ui.OutputWriter.String() + + // Spot check some fields and values + require.Contains(t, output, "db") + require.Contains(t, output, "web") +} + +func TestExportedServices_JSON(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + a := agent.NewTestAgent(t, ``) + defer a.Shutdown() + client := a.Client() + + ui := cli.NewMockUi() + c := New(ui) + + set, _, err := client.ConfigEntries().Set(&api.ExportedServicesConfigEntry{ + Name: "default", + Services: []api.ExportedService{ + { + Name: "db", + Consumers: []api.ServiceConsumer{ + { + Peer: "east", + }, + { + Peer: "west", + }, + }, + }, + { + Name: "web", + Consumers: []api.ServiceConsumer{ + { + Peer: "east", + }, + }, + }, + }, + }, nil) + require.NoError(t, err) + require.True(t, set) + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-format=json", + } + + code := c.Run(args) + require.Equal(t, 0, code) + + var resp []api.ResolvedExportedService + + err = json.Unmarshal(ui.OutputWriter.Bytes(), &resp) + require.NoError(t, err) + + require.Equal(t, 2, len(resp)) + require.Equal(t, "db", resp[0].Service) + require.Equal(t, "web", resp[1].Service) + require.Equal(t, []string{"east", "west"}, resp[0].Consumers.Peers) + require.Equal(t, []string{"east"}, resp[1].Consumers.Peers) +} + +func TestExportedServices_filter(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + a := agent.NewTestAgent(t, ``) + defer a.Shutdown() + client := a.Client() + + set, _, err := client.ConfigEntries().Set(&api.ExportedServicesConfigEntry{ + Name: "default", + Services: []api.ExportedService{ + { + Name: "db", + Consumers: []api.ServiceConsumer{ + { + Peer: "east", + }, + { + Peer: "west", + }, + }, + }, + { + Name: "web", + Consumers: []api.ServiceConsumer{ + { + Peer: "east", + }, + }, + }, + { + Name: "backend", + Consumers: []api.ServiceConsumer{ + { + Peer: "west", + }, + }, + }, + { + Name: "frontend", + Consumers: []api.ServiceConsumer{ + { + Peer: "peer1", + }, + { + Peer: "peer2", + }, + }, + }, + }, + }, nil) + require.NoError(t, err) + require.True(t, set) + + t.Run("consumerPeer=east", func(t *testing.T) { + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-format=json", + "-filter=" + `east in Consumers.Peers`, + } + + code := cmd.Run(args) + require.Equal(t, 0, code) + + var resp []api.ResolvedExportedService + err = json.Unmarshal(ui.OutputWriter.Bytes(), &resp) + require.NoError(t, err) + + require.Equal(t, 2, len(resp)) + require.Equal(t, "db", resp[0].Service) + require.Equal(t, "web", resp[1].Service) + require.Equal(t, []string{"east", "west"}, resp[0].Consumers.Peers) + require.Equal(t, []string{"east"}, resp[1].Consumers.Peers) + + }) + + t.Run("consumerPeer=west", func(t *testing.T) { + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-format=json", + "-filter=" + `west in Consumers.Peers`, + } + + code := cmd.Run(args) + require.Equal(t, 0, code) + + var resp []api.ResolvedExportedService + err = json.Unmarshal(ui.OutputWriter.Bytes(), &resp) + require.NoError(t, err) + + require.Equal(t, 2, len(resp)) + require.Equal(t, "backend", resp[0].Service) + require.Equal(t, "db", resp[1].Service) + require.Equal(t, []string{"west"}, resp[0].Consumers.Peers) + require.Equal(t, []string{"east", "west"}, resp[1].Consumers.Peers) + }) + + t.Run("consumerPeer=peer1", func(t *testing.T) { + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-format=json", + "-filter=" + `peer1 in Consumers.Peers`, + } + + code := cmd.Run(args) + require.Equal(t, 0, code) + + var resp []api.ResolvedExportedService + err = json.Unmarshal(ui.OutputWriter.Bytes(), &resp) + require.NoError(t, err) + + require.Equal(t, 1, len(resp)) + require.Equal(t, "frontend", resp[0].Service) + require.Equal(t, []string{"peer1", "peer2"}, resp[0].Consumers.Peers) + }) + + t.Run("No exported services", func(t *testing.T) { + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-filter=" + `unknown in Consumers.Peers`, + } + + code := cmd.Run(args) + require.Equal(t, 0, code) + + output := ui.OutputWriter.String() + require.Equal(t, "No exported services found\n", output) + }) +} diff --git a/command/snapshot/decode/snapshot_decode.go b/command/snapshot/decode/snapshot_decode.go new file mode 100644 index 000000000000..03151c093cc0 --- /dev/null +++ b/command/snapshot/decode/snapshot_decode.go @@ -0,0 +1,218 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package decode + +import ( + "encoding/json" + "flag" + "fmt" + "io" + "os" + "path" + "strings" + + "github.com/hashicorp/consul-net-rpc/go-msgpack/codec" + "github.com/hashicorp/consul/agent/consul/fsm" + "github.com/hashicorp/consul/agent/consul/state" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/command/flags" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/pbpeering" + "github.com/hashicorp/consul/snapshot" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-raftchunking" + "github.com/hashicorp/raft" + "github.com/mitchellh/cli" +) + +var requestTypeZeroValues = map[structs.MessageType]func() any{ + structs.RegisterRequestType: func() any { return new(structs.RegisterRequest) }, + structs.KVSRequestType: func() any { return new(structs.KVSRequest) }, + structs.SessionRequestType: func() any { return new(structs.SessionRequest) }, + structs.TombstoneRequestType: func() any { return new(structs.TombstoneRequest) }, + structs.CoordinateBatchUpdateType: func() any { return new(structs.Coordinates) }, + structs.PreparedQueryRequestType: func() any { return new(structs.PreparedQueryRequest) }, + structs.AutopilotRequestType: func() any { return new(structs.AutopilotSetConfigRequest) }, + structs.IntentionRequestType: func() any { return new(structs.IntentionRequest) }, + structs.ConnectCARequestType: func() any { return new(structs.CARequest) }, + structs.ConnectCAProviderStateType: func() any { return new(structs.CAConsulProviderState) }, + structs.ConnectCAConfigType: func() any { return new(structs.CAConfiguration) }, + structs.IndexRequestType: func() any { return new(state.IndexEntry) }, + structs.ACLTokenSetRequestType: func() any { return new(structs.ACLToken) }, + structs.ACLPolicySetRequestType: func() any { return new(structs.ACLPolicy) }, + structs.ConfigEntryRequestType: func() any { return new(structs.ConfigEntryRequest) }, + structs.ACLRoleSetRequestType: func() any { return new(structs.ACLRole) }, + structs.ACLBindingRuleSetRequestType: func() any { return new(structs.ACLBindingRule) }, + structs.ACLAuthMethodSetRequestType: func() any { return new(structs.ACLAuthMethod) }, + structs.ChunkingStateType: func() any { return new(raftchunking.State) }, + structs.FederationStateRequestType: func() any { return new(structs.FederationStateRequest) }, + structs.SystemMetadataRequestType: func() any { return new(structs.SystemMetadataEntry) }, + structs.ServiceVirtualIPRequestType: func() any { return new(state.ServiceVirtualIP) }, + structs.FreeVirtualIPRequestType: func() any { return new(state.FreeVirtualIP) }, + structs.PeeringWriteType: func() any { return new(pbpeering.Peering) }, + structs.PeeringTrustBundleWriteType: func() any { return new(pbpeering.PeeringTrustBundle) }, + structs.PeeringSecretsWriteType: func() any { return new(pbpeering.PeeringSecrets) }, + structs.ResourceOperationType: func() any { return new(pbresource.Resource) }, +} + +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + help string + format string + + encoder *json.Encoder +} + +func (c *cmd) Write(p []byte) (n int, err error) { + s := string(p) + c.UI.Output(strings.TrimRight(s, "\n")) + return len(s), nil +} + +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.help = flags.Usage(help, c.flags) + c.encoder = json.NewEncoder(c) +} + +func (c *cmd) Run(args []string) int { + if err := c.flags.Parse(args); err != nil { + c.UI.Error(err.Error()) + return 1 + } + + var file string + args = c.flags.Args() + + switch len(args) { + case 0: + c.UI.Error("Missing FILE argument") + return 1 + case 1: + file = args[0] + default: + c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args))) + return 1 + } + + // Open the file. + f, err := os.Open(file) + if err != nil { + c.UI.Error(fmt.Sprintf("Error opening snapshot file: %s", err)) + return 1 + } + defer f.Close() + + var readFile *os.File + var meta *raft.SnapshotMeta + + if strings.ToLower(path.Base(file)) == "state.bin" { + // This is an internal raw raft snapshot not a gzipped archive one + // downloaded from the API, we can read it directly + readFile = f + + // Assume the meta is colocated and error if not. + metaRaw, err := os.ReadFile(path.Join(path.Dir(file), "meta.json")) + if err != nil { + c.UI.Error(fmt.Sprintf("Error reading meta.json from internal snapshot dir: %s", err)) + return 1 + } + var metaDecoded raft.SnapshotMeta + err = json.Unmarshal(metaRaw, &metaDecoded) + if err != nil { + c.UI.Error(fmt.Sprintf("Error parsing meta.json from internal snapshot dir: %s", err)) + return 1 + } + meta = &metaDecoded + } else { + readFile, meta, err = snapshot.Read(hclog.New(nil), f) + if err != nil { + c.UI.Error(fmt.Sprintf("Error reading snapshot: %s", err)) + return 1 + } + defer func() { + if err := readFile.Close(); err != nil { + c.UI.Error(fmt.Sprintf("Failed to close temp snapshot: %v", err)) + } + if err := os.Remove(readFile.Name()); err != nil { + c.UI.Error(fmt.Sprintf("Failed to clean up temp snapshot: %v", err)) + } + }() + } + + err = c.encoder.Encode(map[string]interface{}{ + "Type": "SnapshotHeader", + "Data": meta, + }) + if err != nil { + c.UI.Error(fmt.Sprintf("Error encoding snapshot header to the output stream: %v", err)) + return 1 + } + + err = c.decodeStream(readFile) + if err != nil { + c.UI.Error(fmt.Sprintf("Error extracting snapshot data: %s", err)) + return 1 + } + + return 0 +} + +// enhance utilizes ReadSnapshot to populate the struct with +// all of the snapshot's itemized data +func (c *cmd) decodeStream(file io.Reader) error { + handler := func(header *fsm.SnapshotHeader, msg structs.MessageType, dec *codec.Decoder) error { + name := structs.MessageType.String(msg) + var val interface{} + + if zeroVal, ok := requestTypeZeroValues[msg]; ok { + val = zeroVal() + } + + err := dec.Decode(&val) + if err != nil { + return fmt.Errorf("failed to decode msg type %v, error %v", name, err) + } + + err = c.encoder.Encode(map[string]interface{}{ + "Type": name, + "Data": val, + }) + + if err != nil { + return fmt.Errorf("failed to encode data into the object stream: %w", err) + } + + return nil + } + + return fsm.ReadSnapshot(file, handler) +} + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return c.help +} + +const synopsis = "Decodes the binary" +const help = ` +Usage: consul snapshot decode [options] FILE + + Decodes snapshot data and outputs a stream of line delimited JSON objects of the form: + + {"Type": "SnapshotHeader", "Data": {""}} + {"Type": "","Data": {}} + {"Type": "","Data": {}} + ... +` diff --git a/command/snapshot/decode/snapshot_decode_test.go b/command/snapshot/decode/snapshot_decode_test.go new file mode 100644 index 000000000000..bd456d558f70 --- /dev/null +++ b/command/snapshot/decode/snapshot_decode_test.go @@ -0,0 +1,107 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package decode + +import ( + "strings" + "testing" + + "github.com/hashicorp/consul/internal/testing/golden" + "github.com/hashicorp/consul/version/versiontest" + "github.com/mitchellh/cli" + "github.com/stretchr/testify/require" +) + +func TestSnapshotDecodeCommand_noTabs(t *testing.T) { + if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') { + t.Fatal("help has tabs") + } +} + +func TestSnapshotDecodeCommand_Validation(t *testing.T) { + ui := cli.NewMockUi() + c := New(ui) + + cases := map[string]struct { + args []string + output string + }{ + "no file": { + []string{}, + "Missing FILE argument", + }, + "extra args": { + []string{"foo", "bar", "baz"}, + "Too many arguments", + }, + } + + for name, tc := range cases { + // Ensure our buffer is always clear + if ui.ErrorWriter != nil { + ui.ErrorWriter.Reset() + } + if ui.OutputWriter != nil { + ui.OutputWriter.Reset() + } + + code := c.Run(tc.args) + if code == 0 { + t.Errorf("%s: expected non-zero exit", name) + } + + output := ui.ErrorWriter.String() + if !strings.Contains(output, tc.output) { + t.Errorf("%s: expected %q to contain %q", name, output, tc.output) + } + } +} + +func TestSnapshotDecodeCommand(t *testing.T) { + cases := map[string]string{ + "no-kv": "./testdata/backup.snap", + "with-kv": "./testdata/backupWithKV.snap", + "all": "./testdata/all.snap", + } + + for name, fpath := range cases { + fpath := fpath + t.Run(name, func(t *testing.T) { + // Inspect the snapshot + ui := cli.NewMockUi() + c := New(ui) + args := []string{fpath} + + code := c.Run(args) + if code != 0 { + t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String()) + } + + actual := ui.OutputWriter.String() + fname := t.Name() + ".ce.golden" + if versiontest.IsEnterprise() { + fname = t.Name() + ".ent.golden" + } + want := golden.Get(t, actual, fname) + require.Equal(t, want, actual) + }) + } +} + +func TestSnapshotDecodeInvalidFile(t *testing.T) { + // Attempt to open a non-snapshot file. + filepath := "./testdata/TestSnapshotDecodeCommand/no-kv.golden" + + // Inspect the snapshot + ui := cli.NewMockUi() + c := New(ui) + args := []string{filepath} + + code := c.Run(args) + // Just check it was an error code returned and not a panic - originally this + // would panic. + if code == 0 { + t.Fatalf("should return an error code") + } +} diff --git a/command/snapshot/decode/testdata/TestSnapshotDecodeCommand/all.ce.golden b/command/snapshot/decode/testdata/TestSnapshotDecodeCommand/all.ce.golden new file mode 100644 index 000000000000..f6fc2969b1ed --- /dev/null +++ b/command/snapshot/decode/testdata/TestSnapshotDecodeCommand/all.ce.golden @@ -0,0 +1,110 @@ +{"Data":{"Version":1,"ID":"2-62-1710350056693","Index":62,"Term":2,"Peers":"ka4xMjcuMC4wLjE6ODMwMA==","Configuration":{"Servers":[{"Suffrage":0,"ID":"065c1172-84a8-0bd1-269c-d24b2d0fb903","Address":"127.0.0.1:8300"}]},"ConfigurationIndex":1,"Size":25469},"Type":"SnapshotHeader"} +{"Data":"\n\u0007default\u0012\u0019Builtin Default Namespace0\n8\n","Type":"Unknown(65)"} +{"Data":"\n\u0007default\u0012\u0019Builtin Default Partition \t(\t","Type":"Unknown(69)"} +{"Data":{"Service":{"ServiceName":{"Name":"external"},"Peer":""},"IP":"0.0.0.3","ManualIPs":null,"CreateIndex":43,"ModifyIndex":43},"Type":"ServiceVirtualIP"} +{"Data":{"Service":{"ServiceName":{"Name":"foo"},"Peer":""},"IP":"0.0.0.2","ManualIPs":null,"CreateIndex":38,"ModifyIndex":38},"Type":"ServiceVirtualIP"} +{"Data":{"Service":{"ServiceName":{"Name":"web"},"Peer":""},"IP":"0.0.0.1","ManualIPs":null,"CreateIndex":37,"ModifyIndex":37},"Type":"ServiceVirtualIP"} +{"Data":{"IP":"0.0.0.3","IsCounter":true},"Type":"FreeVirtualIP"} +{"Data":{"Datacenter":"dc1","ID":"065c1172-84a8-0bd1-269c-d24b2d0fb903","Node":"mkeeler-C02F44FDMD6R","Address":"127.0.0.1","TaggedAddresses":{"lan":"127.0.0.1","lan_ipv4":"127.0.0.1","wan":"127.0.0.1","wan_ipv4":"127.0.0.1"},"NodeMeta":{"consul-network-segment":"","consul-version":"1.19.0"},"Service":null,"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":21,"ModifyIndex":22},"Type":"Register"} +{"Data":{"Datacenter":"dc1","ID":"065c1172-84a8-0bd1-269c-d24b2d0fb903","Node":"mkeeler-C02F44FDMD6R","Address":"127.0.0.1","TaggedAddresses":{"lan":"127.0.0.1","lan_ipv4":"127.0.0.1","wan":"127.0.0.1","wan_ipv4":"127.0.0.1"},"NodeMeta":{"consul-network-segment":"","consul-version":"1.19.0"},"Service":{"ID":"consul","Service":"consul","Tags":null,"Address":"","Meta":{"grpc_port":"8502","grpc_tls_port":"8503","non_voter":"false","raft_version":"3","read_replica":"false","serf_protocol_current":"2","serf_protocol_max":"5","serf_protocol_min":"1","version":"1.19.0"},"Port":8300,"Weights":{"Passing":1,"Warning":1},"EnableTagOverride":false,"Proxy":{"Mode":"","MeshGateway":{},"Expose":{}},"Connect":{},"PeerName":"","CreateIndex":21,"ModifyIndex":21},"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":21,"ModifyIndex":22},"Type":"Register"} +{"Data":{"Datacenter":"dc1","ID":"065c1172-84a8-0bd1-269c-d24b2d0fb903","Node":"mkeeler-C02F44FDMD6R","Address":"127.0.0.1","TaggedAddresses":{"lan":"127.0.0.1","lan_ipv4":"127.0.0.1","wan":"127.0.0.1","wan_ipv4":"127.0.0.1"},"NodeMeta":{"consul-network-segment":"","consul-version":"1.19.0"},"Service":null,"Check":{"Node":"mkeeler-C02F44FDMD6R","CheckID":"serfHealth","Name":"Serf Health Status","Status":"passing","Notes":"","Output":"Agent alive and reachable","ServiceID":"","ServiceName":"","ServiceTags":null,"Type":"","Interval":"","Timeout":"","ExposedPort":0,"Definition":{},"CreateIndex":21,"ModifyIndex":21},"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":21,"ModifyIndex":22},"Type":"Register"} +{"Data":{"Datacenter":"","Op":"","Session":{"ID":"","Name":"","Node":"","LockDelay":0,"Behavior":"","TTL":"","NodeChecks":null,"ServiceChecks":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"Session"} +{"Data":{"AccessorID":"d56136c7-a3a8-ceac-da70-9bee9755d252","SecretID":"a4794332-5fe2-51e1-3a78-47c684bd181c","Description":"","NodeIdentities":[{"NodeName":"localhost","Datacenter":"dc1"}],"Local":false,"CreateTime":"2024-03-13T13:14:15.109823-04:00","Hash":"ibqA3nqRxdh2zAJSHY+nIphdDX/hpYOmgv3RASkkU1w=","CreateIndex":31,"ModifyIndex":31},"Type":"ACLToken"} +{"Data":{"AccessorID":"00000000-0000-0000-0000-000000000002","SecretID":"anonymous","Description":"Anonymous Token","Local":false,"CreateTime":"2024-03-13T13:14:09.953116-04:00","Hash":"tgCOyeidw+oaoZXQ9mHy6+EnY7atKoGaBzg2ndTwXl0=","CreateIndex":7,"ModifyIndex":7},"Type":"ACLToken"} +{"Data":{"AccessorID":"cbb26776-68df-d4ec-5b38-b40366ebf6c2","SecretID":"root","Description":"Initial Management Token","Policies":[{"ID":"00000000-0000-0000-0000-000000000001","Name":"global-management"}],"Local":false,"CreateTime":"2024-03-13T13:14:09.951135-04:00","Hash":"a5y709jeB8xI19PvumK2BeZG3u+1w3hfzyxf2s3UdDY=","CreateIndex":6,"ModifyIndex":6},"Type":"ACLToken"} +{"Data":{"ID":"00000000-0000-0000-0000-000000000001","Name":"global-management","Description":"A built-in policy that grants read and write access to all Consul features","Rules":"\nacl = \"write\"\nagent_prefix \"\" {\n\tpolicy = \"write\"\n}\nevent_prefix \"\" {\n\tpolicy = \"write\"\n}\nidentity_prefix \"\" {\n\tpolicy = \"write\"\n\tintentions = \"write\"\n}\nkey_prefix \"\" {\n\tpolicy = \"write\"\n}\nkeyring = \"write\"\nnode_prefix \"\" {\n\tpolicy = \"write\"\n}\noperator = \"write\"\nmesh = \"write\"\npeering = \"write\"\nquery_prefix \"\" {\n\tpolicy = \"write\"\n}\nservice_prefix \"\" {\n\tpolicy = \"write\"\n\tintentions = \"write\"\n}\nsession_prefix \"\" {\n\tpolicy = \"write\"\n}\npartition_prefix \"\" {\n\tmesh = \"write\"\n\tpeering = \"write\"\n\tnamespace \"default\" {\n\t\tnode_prefix \"\" {\n\t\t\tpolicy = \"write\"\n\t\t}\n\t\tagent_prefix \"\" {\n\t\t\tpolicy = \"write\"\n\t\t}\n\t}\n\tnamespace_prefix \"\" {\n\t\tacl = \"write\"\n\t\tidentity_prefix \"\" {\n\t\t\tpolicy = \"write\"\n\t\t\tintentions = \"write\"\n\t\t}\n\t\tkey_prefix \"\" {\n\t\t\tpolicy = \"write\"\n\t\t}\n\t\tnode_prefix \"\" {\n\t\t\t# node policy is restricted to read within a namespace\n\t\t\tpolicy = \"read\"\n\t\t}\n\t\tsession_prefix \"\" {\n\t\t\tpolicy = \"write\"\n\t\t}\n\t\tservice_prefix \"\" {\n\t\t\tpolicy = \"write\"\n\t\t\tintentions = \"write\"\n\t\t}\n\t}\n}\n","Hash":"NXp0drmQNPohGVdZ4mkRoOqe6Vtx2wYMuXHvQJNMbiE=","CreateIndex":4,"ModifyIndex":4},"Type":"ACLPolicy"} +{"Data":{"ID":"00000000-0000-0000-0000-000000000002","Name":"builtin/global-read-only","Description":"A built-in policy that grants read-only access to all Consul features","Rules":"\nacl = \"read\"\nagent_prefix \"\" {\n\tpolicy = \"read\"\n}\nevent_prefix \"\" {\n\tpolicy = \"read\"\n}\nidentity_prefix \"\" {\n\tpolicy = \"read\"\n\tintentions = \"read\"\n}\nkey_prefix \"\" {\n\tpolicy = \"read\"\n}\nkeyring = \"read\"\nnode_prefix \"\" {\n\tpolicy = \"read\"\n}\noperator = \"read\"\nmesh = \"read\"\npeering = \"read\"\nquery_prefix \"\" {\n\tpolicy = \"read\"\n}\nservice_prefix \"\" {\n\tpolicy = \"read\"\n\tintentions = \"read\"\n}\nsession_prefix \"\" {\n\tpolicy = \"read\"\n}\npartition_prefix \"\" {\n\tmesh = \"read\"\n\tpeering = \"read\"\n\tnamespace \"default\" {\n\t\tnode_prefix \"\" {\n\t\t\tpolicy = \"read\"\n\t\t}\n\t\tagent_prefix \"\" {\n\t\t\tpolicy = \"read\"\n\t\t}\n\t}\n\tnamespace_prefix \"\" {\n\t\tacl = \"read\"\n\t\tidentity_prefix \"\" {\n\t\t\tpolicy = \"read\"\n\t\t\tintentions = \"read\"\n\t\t}\n\t\tkey_prefix \"\" {\n\t\t\tpolicy = \"read\"\n\t\t}\n\t\tnode_prefix \"\" {\n\t\t\t# node policy is restricted to read within a namespace\n\t\t\tpolicy = \"read\"\n\t\t}\n\t\tsession_prefix \"\" {\n\t\t\tpolicy = \"read\"\n\t\t}\n\t\tservice_prefix \"\" {\n\t\t\tpolicy = \"read\"\n\t\t\tintentions = \"read\"\n\t\t}\n\t}\n}\n","Hash":"l1CO3kg8k1ikfGq3P309ZHfazlibtJ9RSGfDminehaE=","CreateIndex":5,"ModifyIndex":5},"Type":"ACLPolicy"} +{"Data":{"ID":"cefa650e-8538-974a-00a0-833c6aa4634a","Name":"test","Description":"","Rules":"node_prefix \"\" { policy = \"write\" }","Hash":"Utaz0IM7r4OLGrVW3ESeiZVGaaql+03cjTU7UHZiVJs=","CreateIndex":32,"ModifyIndex":32},"Type":"ACLPolicy"} +{"Data":{"ID":"edbab2c0-4bd2-052f-8a08-2f31e65930b2","Name":"test","Description":"","Policies":[{"ID":"cefa650e-8538-974a-00a0-833c6aa4634a","Name":"test"}],"Hash":"lfkCqRLtTKoFk50xI5Hxij13bfzsyg7IN7kYwnMP4Y0=","CreateIndex":33,"ModifyIndex":33},"Type":"ACLRole"} +{"Data":{"ID":"2a7708b7-913a-8c1f-593f-019c7192d549","Description":"","AuthMethod":"test","Selector":"","BindType":"service","BindName":"service","CreateIndex":35,"ModifyIndex":35},"Type":"ACLBindingRule"} +{"Data":{"Name":"test","Type":"jwt","Config":{"JWTValidationPubKeys":["-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENRw6ZwlBOx5XZKjcc1HhU00sDehc\n8nqeeSnRZLv89yT7M7qUOFDtR29FR/AFUSAEOFl1iIYLqNMElHs2VkgAZA==\n-----END PUBLIC KEY-----"]},"CreateIndex":34,"ModifyIndex":34},"Type":"ACLAuthMethod"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","ReapIndex":0,"Token":""},"Type":"Tombstone"} +{"Data":{"Datacenter":"","Op":"","Query":null,"Token":"root"},"Type":"PreparedQuery"} +{"Data":{"Datacenter":"","Config":{"CleanupDeadServers":false,"LastContactThreshold":0,"MaxTrailingLogs":0,"MinQuorum":0,"ServerStabilizationTime":0,"RedundancyZoneTag":"","DisableUpgradeMigration":false,"UpgradeVersionTag":"","CreateIndex":0,"ModifyIndex":0},"CAS":false,"Token":""},"Type":"Autopilot"} +{"Data":{"Op":"","Datacenter":"","Index":0,"Roots":null,"Config":null,"ProviderState":null,"Token":""},"Type":"ConnectCA"} +{"Data":{"ID":"fb:50:9b:45:1a:65:15:c1:68:57:73:5f:da:cd:b8:0d:0f:e2:26:eb:68:66:43:11:85:9d:67:a9:7a:56:9c:b9","PrivateKey":"-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMnCtDuifZocILamO9VdbQtXoY6SGSDVknyV+HwbRRzUoAoGCCqGSM49\nAwEHoUQDQgAEf0yW1ejMmToqCbhtSPvlXylSnS8bxJtJD6fs4VGYh7567DjGfBda\nEdgefebLuDdPPl9xAzNOihV29jSb6WheUQ==\n-----END EC PRIVATE KEY-----\n","RootCert":"-----BEGIN CERTIFICATE-----\nMIICDjCCAbOgAwIBAgIBDjAKBggqhkjOPQQDAjAwMS4wLAYDVQQDEyVwcmktZ2Fn\nMXhrYS5jb25zdWwuY2EuZmM2YmY5NDYuY29uc3VsMB4XDTI0MDMxMzE3MTQwOVoX\nDTM0MDMxMTE3MTQwOVowMDEuMCwGA1UEAxMlcHJpLWdhZzF4a2EuY29uc3VsLmNh\nLmZjNmJmOTQ2LmNvbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH9MltXo\nzJk6Kgm4bUj75V8pUp0vG8SbSQ+n7OFRmIe+euw4xnwXWhHYHn3my7g3Tz5fcQMz\nTooVdvY0m+loXlGjgb0wgbowDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB\nAf8wKQYDVR0OBCIEILHtYgr0Zfai/xwJ6PEXOiNAtlDhn3ZSRkZcQNCGq+RnMCsG\nA1UdIwQkMCKAILHtYgr0Zfai/xwJ6PEXOiNAtlDhn3ZSRkZcQNCGq+RnMD8GA1Ud\nEQQ4MDaGNHNwaWZmZTovL2ZjNmJmOTQ2LTk3MzgtMzNmMi1hYmI2LThlYWI2ZGU1\nNmZiYS5jb25zdWwwCgYIKoZIzj0EAwIDSQAwRgIhAL/pd0eKuR/DoWBCYBV2ATNO\nPXjoamqziYct83HMqfv+AiEAzys8TxOmt6h83TujE+2CFmZxRZ1wTdUHPC4efjOb\nahw=\n-----END CERTIFICATE-----\n","IntermediateCert":"","CreateIndex":13,"ModifyIndex":15},"Type":"ConnectCAProviderState"} +{"Data":{"Provider":"consul","Config":{"IntermediateCertTTL":"8760h","LeafCertTTL":"72h","RootCertTTL":"87600h"},"State":null,"ForceWithoutCrossSigning":false,"CreateIndex":12,"ModifyIndex":16},"Type":"ConnectCAConfig"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"api-gateway","Name":"apigw","Listeners":[{"Name":"tcp","Hostname":"","Port":443,"Protocol":"tcp","TLS":{"Certificates":[{"Kind":"inline-certificate","Name":"blah","SectionName":""}],"MaxVersion":"","MinVersion":"","CipherSuites":null}},{"Name":"http","Hostname":"","Port":8080,"Protocol":"http","TLS":{"Certificates":null,"MaxVersion":"","MinVersion":"","CipherSuites":null}}],"Status":{"Conditions":[{"Type":"Accepted","Status":"True","Reason":"Accepted","Message":"gateway is valid","Resource":{"Kind":"","Name":"","SectionName":""},"LastTransitionTime":"2024-03-13T17:14:16.170758Z"},{"Type":"Conflicted","Status":"False","Reason":"NoConflict","Message":"listener has no route conflicts","Resource":{"Kind":"api-gateway","Name":"apigw","SectionName":"http"},"LastTransitionTime":"2024-03-13T17:14:16.170763Z"},{"Type":"Conflicted","Status":"False","Reason":"NoConflict","Message":"listener has no route conflicts","Resource":{"Kind":"api-gateway","Name":"apigw","SectionName":"tcp"},"LastTransitionTime":"2024-03-13T17:14:16.170763Z"},{"Type":"ResolvedRefs","Status":"True","Reason":"ResolvedRefs","Message":"resolved refs","Resource":{"Kind":"api-gateway","Name":"apigw","SectionName":"http"},"LastTransitionTime":"2024-03-13T17:14:16.170756Z"},{"Type":"ResolvedRefs","Status":"True","Reason":"ResolvedRefs","Message":"resolved refs","Resource":{"Kind":"api-gateway","Name":"apigw","SectionName":"tcp"},"LastTransitionTime":"2024-03-13T17:14:16.170757Z"}]},"Hash":6495004227697965289,"CreateIndex":48,"ModifyIndex":49},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"bound-api-gateway","Name":"apigw","Listeners":[{"Name":"tcp","Routes":[{"Kind":"tcp-route","Name":"fake","SectionName":""}],"Certificates":[{"Kind":"inline-certificate","Name":"blah","SectionName":""}]},{"Name":"http","Routes":null,"Certificates":null}],"Services":{"fake":[{"Kind":"tcp-route","Name":"fake","SectionName":""}]},"CreateIndex":50,"ModifyIndex":55},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"exported-services","Name":"default","Services":[{"Name":"web","Namespace":"default","Consumers":[{"Peer":"other"}]}],"Hash":15272881108129132528,"CreateIndex":46,"ModifyIndex":46},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"http-route","Name":"web","Parents":[{"Kind":"api-gateway","Name":"apigw","SectionName":"http"}],"Rules":[{"Filters":{"Headers":null,"URLRewrite":null,"RetryFilter":null,"TimeoutFilter":null,"JWT":null},"ResponseFilters":{"Headers":null},"Matches":null,"Services":[{"Name":"fake","Weight":1,"Filters":{"Headers":null,"URLRewrite":null,"RetryFilter":null,"TimeoutFilter":null,"JWT":null},"ResponseFilters":{"Headers":null}}]}],"Hostnames":null,"Status":{"Conditions":[{"Type":"Accepted","Status":"False","Reason":"InvalidDiscoveryChain","Message":"route protocol does not match targeted service protocol","Resource":{"Kind":"","Name":"","SectionName":""},"LastTransitionTime":"2024-03-13T17:14:16.417825Z"},{"Type":"Bound","Status":"False","Reason":"FailedToBind","Message":"failed to bind route to gateway apigw: route has not been accepted","Resource":{"Kind":"api-gateway","Name":"apigw","SectionName":"http"},"LastTransitionTime":"2024-03-13T17:14:16.417832Z"}]},"Hash":1173445267586960895,"CreateIndex":56,"ModifyIndex":57},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"ingress-gateway","Name":"api","TLS":{"Enabled":false},"Listeners":null,"Hash":15966540600821199974,"CreateIndex":42,"ModifyIndex":42},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"inline-certificate","Name":"blah","Certificate":"-----BEGIN CERTIFICATE-----\nMIICnjCCAkSgAwIBAgIQAxVHhSG0wSbdZm+3ToYAkDAKBggqhkjOPQQDAjCBuTEL\nMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv\nMRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV\nBgNVBAoTDkhhc2hpQ29ycCBJbmMuMUAwPgYDVQQDEzdDb25zdWwgQWdlbnQgQ0Eg\nMjgwNzE4MDMxODA1Mjk2OTA1NzQ4MzU3NjI1MTI5ODQ5NDA5NjI3MCAXDTIzMTEw\nMjE1Mjk0NVoYDzIxMjMxMDA5MTUyOTQ1WjAcMRowGAYDVQQDExFjbGllbnQuZGMx\nLmNvbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKvl1yhbsI9r7IxJxLrt\nZTNYXkCXuFy8q3gsokMqsl/MUynrIBrd9NrZEQA91ZArUYzF1+QlxM6D4hRJc5CR\n3x6jgccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr\nBgEFBQcDATAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCCvXve+zMFSJMXNS3l3YL9k\n2QH8zF74wa+TlwFSaQEjGzArBgNVHSMEJDAigCBGa65jF6Wwq9OmdbgJIRCYv++x\nHG8dRBUpwvSk0Mk1+jAtBgNVHREEJjAkghFjbGllbnQuZGMxLmNvbnN1bIIJbG9j\nYWxob3N0hwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIBLqa1Zh3KUE0RiQzWdoYXkU\nwZo5aBw9ujqzLyAqxToFAiEAihWmc4r6lDYRR35X4QB1nTT92POJRClsfLPOTRG5\nrsU=\n-----END CERTIFICATE-----","PrivateKey":"-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINE2CQhnu7ipo67FGbEBRXoYRCTM4uJdHgNRTrdkAnHCoAoGCCqGSM49\nAwEHoUQDQgAEq+XXKFuwj2vsjEnEuu1lM1heQJe4XLyreCyiQyqyX8xTKesgGt30\n2tkRAD3VkCtRjMXX5CXEzoPiFElzkJHfHg==\n-----END EC PRIVATE KEY-----","Hash":3420847368935414704,"CreateIndex":47,"ModifyIndex":47},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"jwt-provider","Name":"whocare","JSONWebKeySet":{"Local":{"Filename":"/tmp/jwks.json"}},"ClockSkewSeconds":30,"Hash":11700458008192259302,"CreateIndex":58,"ModifyIndex":58},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"mesh","TransparentProxy":{"MeshDestinationsOnly":false},"AllowEnablingPermissiveMutualTLS":true,"Hash":10541910966466195416,"CreateIndex":45,"ModifyIndex":45},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"proxy-defaults","Name":"global","Config":null,"TransparentProxy":{},"MeshGateway":{},"Expose":{},"AccessLogs":{},"Hash":2982631359577466273,"CreateIndex":36,"ModifyIndex":36},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"sameness-group","Name":"default","DefaultForFailover":true,"IncludeLocal":true,"Members":[{"Peer":"other"}],"Hash":8697701191886031964,"CreateIndex":51,"ModifyIndex":51},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"service-defaults","Name":"foo","Protocol":"http","TransparentProxy":{},"MeshGateway":{},"Expose":{},"Hash":6851507846005072818,"CreateIndex":38,"ModifyIndex":38},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"service-defaults","Name":"web","Protocol":"http","TransparentProxy":{},"MeshGateway":{},"Expose":{},"Hash":7641900064431671148,"CreateIndex":37,"ModifyIndex":37},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"service-intentions","Name":"web","Sources":[{"Name":"api","Action":"allow","Precedence":9,"Type":"consul"}],"Hash":1271129721167983805,"CreateIndex":44,"ModifyIndex":44},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"RequestTimeout":"3s","Kind":"service-resolver","Name":"web","Hash":3307964110661939386,"CreateIndex":41,"ModifyIndex":41},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"service-router","Name":"foo","Routes":[{"Match":{"HTTP":{"PathPrefix":"/foo"}},"Destination":{"Service":"web","Namespace":"default","Partition":"default"}}],"Hash":101247989479106989,"CreateIndex":39,"ModifyIndex":39},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"service-splitter","Name":"web","Splits":[{"Weight":100,"Service":"web"}],"Hash":18208480688038965425,"CreateIndex":40,"ModifyIndex":40},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"tcp-route","Name":"fake","Parents":[{"Kind":"api-gateway","Name":"apigw","SectionName":"tcp"}],"Services":[{"Name":"fake"}],"Status":{"Conditions":[{"Type":"Accepted","Status":"True","Reason":"Accepted","Message":"route is valid","Resource":{"Kind":"","Name":"","SectionName":""},"LastTransitionTime":"2024-03-13T17:14:16.353589Z"},{"Type":"Bound","Status":"True","Reason":"Bound","Message":"successfully bound route","Resource":{"Kind":"api-gateway","Name":"apigw","SectionName":"tcp"},"LastTransitionTime":"2024-03-13T17:14:16.353602Z"}]},"Hash":4006422401340817930,"CreateIndex":52,"ModifyIndex":54},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Op":"","Datacenter":"","Entry":{"Kind":"terminating-gateway","Name":"external","Services":[{"Name":"external"}],"Hash":15903386135938294095,"CreateIndex":43,"ModifyIndex":43},"Token":""},"Type":"ConfigEntry"} +{"Data":{"Datacenter":"","Op":"upsert","State":{"Datacenter":"dc1","UpdatedAt":"2024-03-13T17:14:10.392908Z","PrimaryModifyIndex":23,"CreateIndex":23,"ModifyIndex":23},"Token":""},"Type":"FederationState"} +{"Data":{"Key":"intention-format","Value":"config-entry","CreateIndex":17,"ModifyIndex":17},"Type":"SystemMetadata"} +{"Data":{"Key":"reporting-process-id","Value":"01HRWCX8N4S6GEPX7EMTK17B6F","CreateIndex":20,"ModifyIndex":20},"Type":"SystemMetadata"} +{"Data":{"Key":"server-management-token","Value":"16ccea12-b43d-eb04-d1f6-205124572d70","CreateIndex":8,"ModifyIndex":8},"Type":"SystemMetadata"} +{"Data":{"Key":"virtual-ips","Value":"true","CreateIndex":18,"ModifyIndex":18},"Type":"SystemMetadata"} +{"Data":{"Key":"virtual-ips-term-gateway","Value":"true","CreateIndex":19,"ModifyIndex":19},"Type":"SystemMetadata"} +{"Data":{"Key":"acl-auth-methods","Value":34},"Type":"Index"} +{"Data":{"Key":"acl-binding-rules","Value":35},"Type":"Index"} +{"Data":{"Key":"acl-policies","Value":32},"Type":"Index"} +{"Data":{"Key":"acl-roles","Value":33},"Type":"Index"} +{"Data":{"Key":"acl-token-bootstrap","Value":6},"Type":"Index"} +{"Data":{"Key":"acl-tokens","Value":31},"Type":"Index"} +{"Data":{"Key":"checks","Value":21},"Type":"Index"} +{"Data":{"Key":"config-entries","Value":58},"Type":"Index"} +{"Data":{"Key":"connect-ca-builtin","Value":15},"Type":"Index"} +{"Data":{"Key":"connect-ca-builtin-serial","Value":15},"Type":"Index"} +{"Data":{"Key":"connect-ca-roots","Value":16},"Type":"Index"} +{"Data":{"Key":"connect-intentions","Value":17},"Type":"Index"} +{"Data":{"Key":"federation-states","Value":23},"Type":"Index"} +{"Data":{"Key":"gateway-services","Value":43},"Type":"Index"} +{"Data":{"Key":"kind_service_names.partition.default:namespace.default:typical","Value":21},"Type":"Index"} +{"Data":{"Key":"kind_service_names.partition.default:typical","Value":21},"Type":"Index"} +{"Data":{"Key":"kind_service_names.typical","Value":21},"Type":"Index"} +{"Data":{"Key":"mesh-topology","Value":42},"Type":"Index"} +{"Data":{"Key":"nodes","Value":22},"Type":"Index"} +{"Data":{"Key":"partition","Value":9},"Type":"Index"} +{"Data":{"Key":"partition.default:acl-auth-methods","Value":34},"Type":"Index"} +{"Data":{"Key":"partition.default:acl-binding-rules","Value":35},"Type":"Index"} +{"Data":{"Key":"partition.default:acl-policies","Value":32},"Type":"Index"} +{"Data":{"Key":"partition.default:acl-roles","Value":33},"Type":"Index"} +{"Data":{"Key":"partition.default:acl-tokens","Value":31},"Type":"Index"} +{"Data":{"Key":"partition.default:kvs","Value":28},"Type":"Index"} +{"Data":{"Key":"partition.default:namespace","Value":10},"Type":"Index"} +{"Data":{"Key":"partition.default:namespace.default:acl-auth-methods","Value":34},"Type":"Index"} +{"Data":{"Key":"partition.default:namespace.default:acl-binding-rules","Value":35},"Type":"Index"} +{"Data":{"Key":"partition.default:namespace.default:acl-policies","Value":32},"Type":"Index"} +{"Data":{"Key":"partition.default:namespace.default:acl-roles","Value":33},"Type":"Index"} +{"Data":{"Key":"partition.default:namespace.default:acl-tokens","Value":31},"Type":"Index"} +{"Data":{"Key":"partition.default:namespace.default:kvs","Value":28},"Type":"Index"} +{"Data":{"Key":"partition.default:namespace.default:sessions","Value":29},"Type":"Index"} +{"Data":{"Key":"partition.default:namespace.default:tombstones","Value":28},"Type":"Index"} +{"Data":{"Key":"partition.default:peer.~:checks","Value":21},"Type":"Index"} +{"Data":{"Key":"partition.default:peer.~:namespace.default:checks","Value":21},"Type":"Index"} +{"Data":{"Key":"partition.default:peer.~:namespace.default:service.consul","Value":22},"Type":"Index"} +{"Data":{"Key":"partition.default:peer.~:namespace.default:service_kind.typical","Value":22},"Type":"Index"} +{"Data":{"Key":"partition.default:peer.~:namespace.default:services","Value":21},"Type":"Index"} +{"Data":{"Key":"partition.default:peer.~:node.mkeeler-C02F44FDMD6R","Value":22},"Type":"Index"} +{"Data":{"Key":"partition.default:peer.~:nodes","Value":22},"Type":"Index"} +{"Data":{"Key":"partition.default:peer.~:service_kind.typical","Value":22},"Type":"Index"} +{"Data":{"Key":"partition.default:peer.~:services","Value":21},"Type":"Index"} +{"Data":{"Key":"partition.default:peering","Value":62},"Type":"Index"} +{"Data":{"Key":"partition.default:peering-trust-bundles","Value":62},"Type":"Index"} +{"Data":{"Key":"partition.default:service-virtual-ips","Value":43},"Type":"Index"} +{"Data":{"Key":"partition.default:sessions","Value":29},"Type":"Index"} +{"Data":{"Key":"partition.default:namespace.default:tombstones","Value":28},"Type":"Index"} +{"Data":{"Key":"peering","Value":62},"Type":"Index"} +{"Data":{"Key":"peering-trust-bundles","Value":62},"Type":"Index"} +{"Data":{"Key":"prepared-queries","Value":30},"Type":"Index"} +{"Data":{"Key":"services","Value":21},"Type":"Index"} +{"Data":{"Key":"sessions","Value":29},"Type":"Index"} +{"Data":{"Key":"system-metadata","Value":20},"Type":"Index"} +{"Data":{"ID":"503f605c-6ac3-1bbc-4518-758e07212491","Name":"other","Partition":"default","State":1,"PeerCAPems":["-----BEGIN CERTIFICATE-----\nMIICDzCCAbWgAwIBAgIBCTAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktMWhk\nZG90d2IuY29uc3VsLmNhLjU4NGVjZjgyLmNvbnN1bDAeFw0yNDAzMTMxNzE0MDla\nFw0zNDAzMTExNzE0MDlaMDExLzAtBgNVBAMTJnByaS0xaGRkb3R3Yi5jb25zdWwu\nY2EuNTg0ZWNmODIuY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFC3D\n0+YDsc7BhFLJy5ePs5W86pEGScYI0PWilubR+NrV4o40hqgTbwANieTjd77oQTYr\nXD+uaPj+pIOnuOu5LqOBvTCBujAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\nAwEB/zApBgNVHQ4EIgQgLAzSlQKEkAhISEfhG1Y6m2uoA/jlY5kAYVGTHgMEbSMw\nKwYDVR0jBCQwIoAgLAzSlQKEkAhISEfhG1Y6m2uoA/jlY5kAYVGTHgMEbSMwPwYD\nVR0RBDgwNoY0c3BpZmZlOi8vNTg0ZWNmODItZmU5YS00NDY0LTVkZWItMjU5ZTRh\nYmExZGVlLmNvbnN1bDAKBggqhkjOPQQDAgNIADBFAiEAzD28+wMMO3RPfYR4kF9G\ncrqWkBCWP7k2fvwX10vLdNwCIBKf0pWS1qTOgJDxX1dn9+vqk1flv7stwwgFgJlH\nT0xb\n-----END CERTIFICATE-----\n"],"CreateIndex":59,"ModifyIndex":62,"Remote":{"Partition":"default","Datacenter":"dc1"}},"Type":"Peering"} +{"Data":{"TrustDomain":"584ecf82-fe9a-4464-5deb-259e4aba1dee.consul","PeerName":"other","Partition":"default","RootPEMs":["-----BEGIN CERTIFICATE-----\nMIICDzCCAbWgAwIBAgIBCTAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktMWhk\nZG90d2IuY29uc3VsLmNhLjU4NGVjZjgyLmNvbnN1bDAeFw0yNDAzMTMxNzE0MDla\nFw0zNDAzMTExNzE0MDlaMDExLzAtBgNVBAMTJnByaS0xaGRkb3R3Yi5jb25zdWwu\nY2EuNTg0ZWNmODIuY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFC3D\n0+YDsc7BhFLJy5ePs5W86pEGScYI0PWilubR+NrV4o40hqgTbwANieTjd77oQTYr\nXD+uaPj+pIOnuOu5LqOBvTCBujAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\nAwEB/zApBgNVHQ4EIgQgLAzSlQKEkAhISEfhG1Y6m2uoA/jlY5kAYVGTHgMEbSMw\nKwYDVR0jBCQwIoAgLAzSlQKEkAhISEfhG1Y6m2uoA/jlY5kAYVGTHgMEbSMwPwYD\nVR0RBDgwNoY0c3BpZmZlOi8vNTg0ZWNmODItZmU5YS00NDY0LTVkZWItMjU5ZTRh\nYmExZGVlLmNvbnN1bDAKBggqhkjOPQQDAgNIADBFAiEAzD28+wMMO3RPfYR4kF9G\ncrqWkBCWP7k2fvwX10vLdNwCIBKf0pWS1qTOgJDxX1dn9+vqk1flv7stwwgFgJlH\nT0xb\n-----END CERTIFICATE-----\n"],"ExportedPartition":"default","CreateIndex":62,"ModifyIndex":62},"Type":"PeeringTrustBundle"} +{"Data":{"PeerID":"503f605c-6ac3-1bbc-4518-758e07212491","stream":{"ActiveSecretID":"cda5e0b8-be51-5b62-a89d-8546f9c48da9"}},"Type":"PeeringSecret"} +{"Data":{"ChunkMap":{}},"Type":"ChunkingState"} diff --git a/command/snapshot/decode/testdata/TestSnapshotDecodeCommand/no-kv.ce.golden b/command/snapshot/decode/testdata/TestSnapshotDecodeCommand/no-kv.ce.golden new file mode 100644 index 000000000000..99536ad585e7 --- /dev/null +++ b/command/snapshot/decode/testdata/TestSnapshotDecodeCommand/no-kv.ce.golden @@ -0,0 +1,23 @@ +{"Data":{"Version":1,"ID":"2-13-1602222343947","Index":13,"Term":2,"Peers":"ka4xMjcuMC4wLjE6ODMwMA==","Configuration":{"Servers":[{"Suffrage":0,"ID":"a577b288-b354-770e-e909-da0972eb20e8","Address":"127.0.0.1:8300"}]},"ConfigurationIndex":1,"Size":5141},"Type":"SnapshotHeader"} +{"Data":{"Datacenter":"dc1","ID":"a577b288-b354-770e-e909-da0972eb20e8","Node":"macbook-pro.lan","Address":"127.0.0.1","TaggedAddresses":{"lan":"127.0.0.1","lan_ipv4":"127.0.0.1","wan":"127.0.0.1","wan_ipv4":"127.0.0.1"},"NodeMeta":{"consul-network-segment":""},"Service":null,"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":11,"ModifyIndex":12},"Type":"Register"} +{"Data":{"Datacenter":"dc1","ID":"a577b288-b354-770e-e909-da0972eb20e8","Node":"macbook-pro.lan","Address":"127.0.0.1","TaggedAddresses":{"lan":"127.0.0.1","lan_ipv4":"127.0.0.1","wan":"127.0.0.1","wan_ipv4":"127.0.0.1"},"NodeMeta":{"consul-network-segment":""},"Service":{"ID":"consul","Service":"consul","Tags":null,"Address":"","Meta":{"non_voter":"false","raft_version":"3","serf_protocol_current":"2","serf_protocol_max":"5","serf_protocol_min":"1","version":"1.9.0"},"Port":8300,"Weights":{"Passing":1,"Warning":1},"EnableTagOverride":false,"Proxy":{"Mode":"","MeshGateway":{},"Expose":{}},"Connect":{},"PeerName":"","CreateIndex":11,"ModifyIndex":11},"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":11,"ModifyIndex":12},"Type":"Register"} +{"Data":{"Datacenter":"dc1","ID":"a577b288-b354-770e-e909-da0972eb20e8","Node":"macbook-pro.lan","Address":"127.0.0.1","TaggedAddresses":{"lan":"127.0.0.1","lan_ipv4":"127.0.0.1","wan":"127.0.0.1","wan_ipv4":"127.0.0.1"},"NodeMeta":{"consul-network-segment":""},"Service":null,"Check":{"Node":"macbook-pro.lan","CheckID":"serfHealth","Name":"Serf Health Status","Status":"passing","Notes":"","Output":"Agent alive and reachable","ServiceID":"","ServiceName":"","ServiceTags":null,"Type":"","Interval":"","Timeout":"","ExposedPort":0,"Definition":{},"CreateIndex":11,"ModifyIndex":11},"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":11,"ModifyIndex":12},"Type":"Register"} +{"Data":{"Datacenter":"","Config":{"CleanupDeadServers":false,"LastContactThreshold":0,"MaxTrailingLogs":0,"MinQuorum":0,"ServerStabilizationTime":0,"RedundancyZoneTag":"","DisableUpgradeMigration":false,"UpgradeVersionTag":"","CreateIndex":0,"ModifyIndex":0},"CAS":false,"Token":""},"Type":"Autopilot"} +{"Data":{"Op":"","Datacenter":"","Index":0,"Roots":null,"Config":null,"ProviderState":null,"Token":""},"Type":"ConnectCA"} +{"Data":{"ID":"07:80:c8:de:f6:41:86:29:8f:9c:b8:17:d6:48:c2:d5:c5:5c:7f:0c:03:f7:cf:97:5a:a7:c1:68:aa:23:ae:81","PrivateKey":"-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIGwMuojUj9fSERmBjUjp3AbmkFhwRZZEEcm0XgdnCSyRoAoGCCqGSM49\nAwEHoUQDQgAEBi0AvynqnFMRIsxs1VNKkDBIvlKywpuFIaZY3TDMEvuVV/iLvFOl\n8I/OBkjXVsUPzXpao6Da6oPpbtzVuphD7A==\n-----END EC PRIVATE KEY-----\n","RootCert":"-----BEGIN CERTIFICATE-----\nMIICDjCCAbOgAwIBAgIBBzAKBggqhkjOPQQDAjAwMS4wLAYDVQQDEyVwcmktMXN5\nYzU4Zi5jb25zdWwuY2EuMzMzZDFmYTIuY29uc3VsMB4XDTIwMTAwOTA1NDUyNloX\nDTMwMTAwOTA1NDUyNlowMDEuMCwGA1UEAxMlcHJpLTFzeWM1OGYuY29uc3VsLmNh\nLjMzM2QxZmEyLmNvbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAYtAL8p\n6pxTESLMbNVTSpAwSL5SssKbhSGmWN0wzBL7lVf4i7xTpfCPzgZI11bFD816WqOg\n2uqD6W7c1bqYQ+yjgb0wgbowDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB\nAf8wKQYDVR0OBCIEIOZNpB8CrBdX2haue5rcSaauDsPs8S1Ld39j9ne1JP+xMCsG\nA1UdIwQkMCKAIOZNpB8CrBdX2haue5rcSaauDsPs8S1Ld39j9ne1JP+xMD8GA1Ud\nEQQ4MDaGNHNwaWZmZTovLzMzM2QxZmEyLTFjMTItMzgzYS05MDRlLWFmMjc0OTEz\nNmViZS5jb25zdWwwCgYIKoZIzj0EAwIDSQAwRgIhALy+D4SiHnHaEtxj62ncLyus\nxf6XS4amT2P3uc+zsURWAiEAvGAvh5/BwyUg0wzcVGZ40K+tllAVmk4fWL6dkUcT\nJ+o=\n-----END CERTIFICATE-----\n","IntermediateCert":"","CreateIndex":6,"ModifyIndex":8},"Type":"ConnectCAProviderState"} +{"Data":{"Provider":"consul","Config":{"IntermediateCertTTL":"8760h","LeafCertTTL":"72h","RotationPeriod":"2160h"},"State":null,"ForceWithoutCrossSigning":false,"CreateIndex":5,"ModifyIndex":5},"Type":"ConnectCAConfig"} +{"Data":{"Datacenter":"","Op":"upsert","State":{"Datacenter":"dc1","UpdatedAt":"2020-10-09T05:45:26.48447Z","PrimaryModifyIndex":13,"CreateIndex":13,"ModifyIndex":13},"Token":""},"Type":"FederationState"} +{"Data":{"Key":"intention-format","Value":"config-entry","CreateIndex":10,"ModifyIndex":10},"Type":"SystemMetadata"} +{"Data":{"Key":"checks","Value":11},"Type":"Index"} +{"Data":{"Key":"config-entries","Value":10},"Type":"Index"} +{"Data":{"Key":"connect-ca-builtin","Value":8},"Type":"Index"} +{"Data":{"Key":"connect-ca-builtin-serial","Value":7},"Type":"Index"} +{"Data":{"Key":"connect-ca-roots","Value":9},"Type":"Index"} +{"Data":{"Key":"connect-intentions","Value":10},"Type":"Index"} +{"Data":{"Key":"federation-states","Value":13},"Type":"Index"} +{"Data":{"Key":"nodes","Value":12},"Type":"Index"} +{"Data":{"Key":"service.consul","Value":12},"Type":"Index"} +{"Data":{"Key":"service_kind.typical","Value":12},"Type":"Index"} +{"Data":{"Key":"services","Value":11},"Type":"Index"} +{"Data":{"Key":"system-metadata","Value":10},"Type":"Index"} +{"Data":{"ChunkMap":{}},"Type":"ChunkingState"} diff --git a/command/snapshot/decode/testdata/TestSnapshotDecodeCommand/with-kv.ce.golden b/command/snapshot/decode/testdata/TestSnapshotDecodeCommand/with-kv.ce.golden new file mode 100644 index 000000000000..62c95700a452 --- /dev/null +++ b/command/snapshot/decode/testdata/TestSnapshotDecodeCommand/with-kv.ce.golden @@ -0,0 +1,51 @@ +{"Data":{"Version":1,"ID":"2-12426-1604593650375","Index":12426,"Term":2,"Peers":"kbMxOTIuMTY4Ljg2LjIzNjo4MzAw","Configuration":{"Servers":[{"Suffrage":0,"ID":"1047e34e-dc15-fa4b-8e1d-5bf74c2ac239","Address":"192.168.86.236:8300"}]},"ConfigurationIndex":1,"Size":17228},"Type":"SnapshotHeader"} +{"Data":{"Datacenter":"dc1","ID":"1047e34e-dc15-fa4b-8e1d-5bf74c2ac239","Node":"hashicorp.lan","Address":"192.168.86.236","TaggedAddresses":{"lan":"192.168.86.236","lan_ipv4":"192.168.86.236","wan":"192.168.86.236","wan_ipv4":"192.168.86.236"},"NodeMeta":{"consul-network-segment":""},"Service":null,"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":6,"ModifyIndex":7},"Type":"Register"} +{"Data":{"Datacenter":"dc1","ID":"1047e34e-dc15-fa4b-8e1d-5bf74c2ac239","Node":"hashicorp.lan","Address":"192.168.86.236","TaggedAddresses":{"lan":"192.168.86.236","lan_ipv4":"192.168.86.236","wan":"192.168.86.236","wan_ipv4":"192.168.86.236"},"NodeMeta":{"consul-network-segment":""},"Service":{"ID":"consul","Service":"consul","Tags":null,"Address":"","Meta":{"non_voter":"false","raft_version":"3","serf_protocol_current":"2","serf_protocol_max":"5","serf_protocol_min":"1","version":"1.8.5"},"Port":8300,"Weights":{"Passing":1,"Warning":1},"EnableTagOverride":false,"Proxy":{"Mode":"","MeshGateway":{},"Expose":{}},"Connect":{},"PeerName":"","CreateIndex":6,"ModifyIndex":6},"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":6,"ModifyIndex":7},"Type":"Register"} +{"Data":{"Datacenter":"dc1","ID":"1047e34e-dc15-fa4b-8e1d-5bf74c2ac239","Node":"hashicorp.lan","Address":"192.168.86.236","TaggedAddresses":{"lan":"192.168.86.236","lan_ipv4":"192.168.86.236","wan":"192.168.86.236","wan_ipv4":"192.168.86.236"},"NodeMeta":{"consul-network-segment":""},"Service":{"ID":"vault:127.0.0.1:8200","Service":"vault","Tags":["active","initialized"],"Address":"127.0.0.1","TaggedAddresses":{"lan_ipv4":{"Address":"127.0.0.1","Port":8200},"wan_ipv4":{"Address":"127.0.0.1","Port":8200}},"Meta":null,"Port":8200,"Weights":{"Passing":1,"Warning":1},"EnableTagOverride":false,"Proxy":{"Mode":"","MeshGateway":{},"Expose":{}},"Connect":{},"PeerName":"","CreateIndex":3470,"ModifyIndex":3497},"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":6,"ModifyIndex":7},"Type":"Register"} +{"Data":{"Datacenter":"dc1","ID":"1047e34e-dc15-fa4b-8e1d-5bf74c2ac239","Node":"hashicorp.lan","Address":"192.168.86.236","TaggedAddresses":{"lan":"192.168.86.236","lan_ipv4":"192.168.86.236","wan":"192.168.86.236","wan_ipv4":"192.168.86.236"},"NodeMeta":{"consul-network-segment":""},"Service":null,"Check":{"Node":"hashicorp.lan","CheckID":"serfHealth","Name":"Serf Health Status","Status":"passing","Notes":"","Output":"Agent alive and reachable","ServiceID":"","ServiceName":"","ServiceTags":null,"Type":"","Interval":"","Timeout":"","ExposedPort":0,"Definition":{},"CreateIndex":6,"ModifyIndex":6},"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":6,"ModifyIndex":7},"Type":"Register"} +{"Data":{"Datacenter":"dc1","ID":"1047e34e-dc15-fa4b-8e1d-5bf74c2ac239","Node":"hashicorp.lan","Address":"192.168.86.236","TaggedAddresses":{"lan":"192.168.86.236","lan_ipv4":"192.168.86.236","wan":"192.168.86.236","wan_ipv4":"192.168.86.236"},"NodeMeta":{"consul-network-segment":""},"Service":null,"Check":{"Node":"hashicorp.lan","CheckID":"vault:127.0.0.1:8200:vault-sealed-check","Name":"Vault Sealed Status","Status":"passing","Notes":"Vault service is healthy when Vault is in an unsealed status and can become an active Vault server","Output":"Vault Unsealed","ServiceID":"vault:127.0.0.1:8200","ServiceName":"vault","ServiceTags":["active","initialized"],"Type":"ttl","Interval":"","Timeout":"","ExposedPort":0,"Definition":{},"CreateIndex":3471,"ModifyIndex":6836},"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"","Token":"","CreateIndex":6,"ModifyIndex":7},"Type":"Register"} +{"Data":[{"Node":"hashicorp.lan","Segment":"","Coord":{"Vec":[0,0,0,0,0,0,0,0],"Error":1.5,"Adjustment":0,"Height":0.00001}}],"Type":"CoordinateBatchUpdate"} +{"Data":{"Datacenter":"","Op":"","Session":{"ID":"","Name":"","Node":"","LockDelay":0,"Behavior":"","TTL":"","NodeChecks":null,"ServiceChecks":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"Session"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","DirEnt":{"LockIndex":0,"Key":"","Flags":0,"Value":null,"CreateIndex":0,"ModifyIndex":0},"Token":""},"Type":"KVS"} +{"Data":{"Datacenter":"","Op":"","ReapIndex":0,"Token":""},"Type":"Tombstone"} +{"Data":{"Datacenter":"","Op":"","ReapIndex":0,"Token":""},"Type":"Tombstone"} +{"Data":{"Datacenter":"","Config":{"CleanupDeadServers":false,"LastContactThreshold":0,"MaxTrailingLogs":0,"MinQuorum":0,"ServerStabilizationTime":0,"RedundancyZoneTag":"","DisableUpgradeMigration":false,"UpgradeVersionTag":"","CreateIndex":0,"ModifyIndex":0},"CAS":false,"Token":""},"Type":"Autopilot"} +{"Data":{"Datacenter":"","Op":"upsert","State":{"Datacenter":"dc1","UpdatedAt":"2020-11-03T23:57:19.636962Z","PrimaryModifyIndex":5,"CreateIndex":5,"ModifyIndex":5},"Token":""},"Type":"FederationState"} +{"Data":{"Key":"checks","Value":6836},"Type":"Index"} +{"Data":{"Key":"coordinates","Value":12424},"Type":"Index"} +{"Data":{"Key":"federation-states","Value":5},"Type":"Index"} +{"Data":{"Key":"kvs","Value":12426},"Type":"Index"} +{"Data":{"Key":"nodes","Value":7},"Type":"Index"} +{"Data":{"Key":"service.consul","Value":7},"Type":"Index"} +{"Data":{"Key":"service.vault","Value":6836},"Type":"Index"} +{"Data":{"Key":"service_kind.typical","Value":6836},"Type":"Index"} +{"Data":{"Key":"services","Value":3497},"Type":"Index"} +{"Data":{"Key":"sessions","Value":3493},"Type":"Index"} +{"Data":{"Key":"tombstones","Value":12426},"Type":"Index"} +{"Data":{"ChunkMap":{}},"Type":"ChunkingState"} diff --git a/command/snapshot/decode/testdata/all.snap b/command/snapshot/decode/testdata/all.snap new file mode 100644 index 000000000000..8b69dec197bc Binary files /dev/null and b/command/snapshot/decode/testdata/all.snap differ diff --git a/command/snapshot/decode/testdata/backup.snap b/command/snapshot/decode/testdata/backup.snap new file mode 100644 index 000000000000..ddb621c396fb Binary files /dev/null and b/command/snapshot/decode/testdata/backup.snap differ diff --git a/command/snapshot/decode/testdata/backupWithKV.snap b/command/snapshot/decode/testdata/backupWithKV.snap new file mode 100644 index 000000000000..453b3a03f5bd Binary files /dev/null and b/command/snapshot/decode/testdata/backupWithKV.snap differ diff --git a/command/snapshot/decode/testdata/populate-all.sh b/command/snapshot/decode/testdata/populate-all.sh new file mode 100755 index 000000000000..dfecec724943 --- /dev/null +++ b/command/snapshot/decode/testdata/populate-all.sh @@ -0,0 +1,296 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +set -e + +trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT + + +readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})" +readonly SCRIPT_DIR="$(dirname ${BASH_SOURCE[0]})" + +# Start a couple dev agents in the background +echo "Starting Dev Agents" +consul agent -dev -hcl 'acl { enabled = true default_policy="allow" tokens { initial_management = "root" } }' >/dev/null 2>&1 & +consul agent -dev -dns-port=9600 -grpc-port=9502 -grpc-tls-port=9503 -http-port=9500 -serf-lan-port=9301 -serf-wan-port=9302 -server-port=9300 >/dev/null 2>&1 & + +# should be long enough for the dev agents to be available +sleep 5 + +# This script expects a consul dev agent with acls enabled in default allow to be running on localhost +# consul agent -dev -hcl 'acl { enabled = true default_policy="allow" tokens { initial_management = "root" } }' +# It also requires another dev agent running on alternative ports to peer with +# consul agent -dev -dns-port=9600 -grpc-port=9502 -grpc-tls-port=9503 -http-port=9500 -serf-lan-port=9301 -serf-wan-port=9302 -server-port=9300 + +# Just running Consul will cause the following data to be in the snapshot: +# Register +# ConnectCA +# ConnectCAProviderState +# ConnectCAConfig +# Autopilot +# Index +# SystemMetadata +# CoordinateBatchUpdate +# FederationState +# ChunkingState +# FreeVirtualIP +# Partition +# Tombstone + +# Ensure a KV entry ends up in the snapshot +echo "Creating KV Entry" +consul kv put foo/bar 1 >/dev/null + +# Ensure a tombstone ends up in the snapshot +echo "Forcing KV Tombstone Creation" +consul kv put foo/baz 2 >/dev/null +consul kv delete foo/baz > /dev/null + + +# Ensure a session ends up in the snapshot +echo "Creating Session" +curl -s -X PUT localhost:8500/v1/session/create >/dev/null + +# Ensure a prepared query ends up in the snapshot +echo "Creating Prepared Query" +curl -s -X POST localhost:8500/v1/query -d '{"Name": "test", "Token": "root", "Service": {"Service": "test"}}' >/dev/null + +# Ensure an ACL token ends up in the snapshot +echo "Creating ACL Token" +consul acl token create -node-identity=localhost:dc1 >/dev/null + +# Ensure an ACL policy ends up in the snapshot +echo "Creating ACL Policy" +consul acl policy create -name=test -rules='node_prefix "" { policy = "write" }' >/dev/null + +# Ensure an ACL role ends up in the snapshot +echo "Creating ACL Role" +consul acl role create -name=test -policy-name=test >/dev/null + +# Ensure an ACL auth method ends up in the snapshot +echo "Creating ACL Auth Method" +consul acl auth-method create -type jwt -name test -config '{"JWTValidationPubKeys": ["-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENRw6ZwlBOx5XZKjcc1HhU00sDehc\n8nqeeSnRZLv89yT7M7qUOFDtR29FR/AFUSAEOFl1iIYLqNMElHs2VkgAZA==\n-----END PUBLIC KEY-----"]}' >/dev/null + +# Ensure an ACL binding rule ends up in the snapshot +echo "Creating ACL Binding Rule" +consul acl binding-rule create -bind-type="service" -bind-name="service" -method="test" >/dev/null + +# Ensure config entries end up in the snapshot +echo "Creating Proxy Default Config Entry" +consul config write - >/dev/null </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null </dev/null +if [ $? -eq 0 ]; then +set -e +echo "Creating Sameness Group Config Entry" +consul config write - >/dev/null </dev/null </dev/null </dev/null </dev/null + +echo "Saving Snapshot to all.snap" +sleep 2 +consul snapshot save "${SCRIPT_DIR}/all.snap" >/dev/null \ No newline at end of file diff --git a/command/snapshot/snapshot_command.go b/command/snapshot/snapshot_command.go index 2e96550e191f..e5c4805e7fa3 100644 --- a/command/snapshot/snapshot_command.go +++ b/command/snapshot/snapshot_command.go @@ -45,6 +45,10 @@ Usage: consul snapshot [options] [args] Restore a snapshot: $ consul snapshot restore backup.snap + + Decode a snapshot: + + $ consul snapshot decode backup.snap Inspect a snapshot: diff --git a/command/troubleshoot/ports/troubleshoot_ports.go b/command/troubleshoot/ports/troubleshoot_ports.go new file mode 100644 index 000000000000..108870305110 --- /dev/null +++ b/command/troubleshoot/ports/troubleshoot_ports.go @@ -0,0 +1,89 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package ports + +import ( + "flag" + "fmt" + "github.com/hashicorp/consul/troubleshoot/ports" + "os" + + "github.com/hashicorp/consul/command/cli" + "github.com/hashicorp/consul/command/flags" +) + +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + help string + + // flags + host string + ports string +} + +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + + c.flags.StringVar(&c.host, "host", os.Getenv("CONSUL_HTTP_ADDR"), "The consul server host") + + c.flags.StringVar(&c.ports, "ports", "", "Custom ports to troubleshoot") + + c.help = flags.Usage(help, c.flags) +} + +func (c *cmd) Run(args []string) int { + + if err := c.flags.Parse(args); err != nil { + c.UI.Error(fmt.Sprintf("Failed to parse args: %v", err)) + return 1 + } + + if c.host == "" { + c.UI.Error("-host is required. or set environment variable CONSUL_HTTP_ADDR") + return 1 + } + + if c.ports == "" { + ports.TroubleshootDefaultPorts(c.host) + } else { + ports.TroubleShootCustomPorts(c.host, c.ports) + } + return 0 +} + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return c.help +} + +const ( + synopsis = "Prints open and closed ports on the Consul server" + help = ` +Usage: consul troubleshoot ports [options] + Checks ports for TCP connectivity. Add the -ports flag to check specific ports or omit the -ports flag to check default ports. + Refer to the following reference for default ports: https://developer.hashicorp.com/consul/docs/install/ports + + consul troubleshoot ports -host localhost + + or + export CONSUL_HTTP_ADDR=localhost + consul troubleshoot ports + + Use the -ports flag to check non-default ports, for example: + consul troubleshoot ports -host localhost -ports 1023,1024 + or + export CONSUL_HTTP_ADDR=localhost + consul troubleshoot ports -ports 1234,8500 +` +) diff --git a/connect/proxy/proxy_test.go b/connect/proxy/proxy_test.go index 20b4cdd55efe..73d65b82c6c2 100644 --- a/connect/proxy/proxy_test.go +++ b/connect/proxy/proxy_test.go @@ -98,7 +98,7 @@ func TestProxy_public(t *testing.T) { retry.Run(t, func(r *retry.R) { conn, err = svc.Dial(context.Background(), &connect.StaticResolver{ Addr: TestLocalAddr(ports[0]), - CertURI: agConnect.TestSpiffeIDService(t, "echo"), + CertURI: agConnect.TestSpiffeIDService(r, "echo"), }) if err != nil { r.Fatalf("err: %s", err) diff --git a/connect/service_test.go b/connect/service_test.go index 0f6ed51a8b45..88543a4145da 100644 --- a/connect/service_test.go +++ b/connect/service_test.go @@ -246,7 +246,7 @@ func TestService_HTTPClient(t *testing.T) { //require.Equal(t,"https://backend.service.consul:443", addr) return &StaticResolver{ Addr: testSvr.Addr, - CertURI: connect.TestSpiffeIDService(t, "backend"), + CertURI: connect.TestSpiffeIDService(r, "backend"), }, nil } diff --git a/contributing/INTERNALS.md b/contributing/INTERNALS.md deleted file mode 100644 index 0deb6675cbe3..000000000000 --- a/contributing/INTERNALS.md +++ /dev/null @@ -1 +0,0 @@ -Moved to [docs/README.md](../docs/README.md). diff --git a/contributing/README.md b/contributing/README.md deleted file mode 100644 index 5ab5e80d30cd..000000000000 --- a/contributing/README.md +++ /dev/null @@ -1 +0,0 @@ -Moved to [docs](../docs/README.md). diff --git a/docs/README.md b/docs/README.md index 0d61b30fa577..156dc946a495 100644 --- a/docs/README.md +++ b/docs/README.md @@ -25,7 +25,7 @@ be found in the public [user documentation]. 1. [Agent Configuration](./config) 1. [RPC](./rpc) 1. [Cluster Persistence](./persistence) -1. [Resources and Controllers](./resources) +1. [V2 Architecture](v2-architecture) 1. [Client Agent](./client-agent) 1. [Service Discovery](./service-discovery) 1. [Service Mesh (Connect)](./service-mesh) @@ -86,3 +86,4 @@ in the editor) to maintain a consistent Consul style for the diagrams. [mermaid-js live editor]: https://mermaid-js.github.io/mermaid-live-editor/edit/ [mermaid-js docs]: https://mermaid-js.github.io/mermaid/ [consul-mermaid-theme.json]: ./consul-mermaid-theme.json + diff --git a/docs/persistence/README.md b/docs/persistence/README.md index c8ca1089d807..52d48725986d 100644 --- a/docs/persistence/README.md +++ b/docs/persistence/README.md @@ -3,7 +3,7 @@ > **Note** > While the content of this document is still accurate, it doesn't cover the new > generic resource-oriented storage layer introduced in Consul 1.16. Please see -> [Resources](../resources) for more information. +> [Resources](../v2-architecture/controller-architecture) for more information. The cluser persistence subsystem runs entirely in Server Agents. It handles both read and write requests from the [RPC] subsystem. See the [Consul Architecture Guide] for an @@ -40,6 +40,7 @@ use [bbolt]. [boltdb]: https://github.com/boltdb/bolt [bbolt]: https://github.com/etcd-io/bbolt +See [diagrams](#diagrams) below for more details on the interaction. ## State Store @@ -111,3 +112,10 @@ storage. [hashicorp/raft-autopilot]: https://github.com/hashicorp/raft-autopilot + +## Diagrams +### High-level life of a write +![Overview](./write-overview.png) + +### Deep-dive into write through Raft +![Deep dive](./write-deep-dive.png) \ No newline at end of file diff --git a/docs/persistence/write-deep-dive.png b/docs/persistence/write-deep-dive.png new file mode 100644 index 000000000000..b3872fb65511 Binary files /dev/null and b/docs/persistence/write-deep-dive.png differ diff --git a/docs/persistence/write-overview.png b/docs/persistence/write-overview.png new file mode 100644 index 000000000000..e7238c13a208 Binary files /dev/null and b/docs/persistence/write-overview.png differ diff --git a/docs/resources/README.md b/docs/resources/README.md deleted file mode 100644 index b2a05744ad56..000000000000 --- a/docs/resources/README.md +++ /dev/null @@ -1,115 +0,0 @@ -# Resources - -> **Note** -> Looking for guidance on adding new resources and controllers to Consul? Check -> out the [developer guide](./guide.md). - -Consul 1.16 introduced a set of [generic APIs] for managing resources, and a -[controller runtime] for building functionality on top of them. - -[generic APIs]: ../../proto-public/pbresource/resource.proto -[controller runtime]: ../../internal/controller - -Previously, adding features to Consul involved making changes at every layer of -the stack, including: HTTP handlers, RPC handlers, MemDB tables, Raft -operations, and CLI commands. - -This architecture made sense when the product was maintained by a small core -group who could keep the entire system in their heads, but presented significant -collaboration, ownership, and onboarding challenges when our contributor base -expanded to many engineers, across several teams, and the product grew in -complexity. - -In the new model, teams can work with much greater autonomy by building on top -of a shared platform and own their resource types and controllers. - -## Architecture Overview - -![architecture diagram](./architecture-overview.png) - -[source](https://whimsical.com/state-store-v2-UKE6SaEPXNc4UrZBrZj4Kg) - -Our resource-oriented architecture comprises the following components: - -#### Resource Service - -[Resource Service](../../proto-public/pbresource/resource.proto) is a gRPC -service that contains the shared logic for creating, reading, updating, -deleting, and watching resources. It will be consumed by controllers, our -Kubernetes integration, the CLI, and mapped to an HTTP+JSON API. - -#### Type Registry - -[Type Registry](../../internal/resource/registry.go) is where teams register -their resource types, along with hooks for performing structural validation, -authorization, etc. - -#### Storage Backend - -[Storage Backend](../../internal/storage/storage.go) is an abstraction over -low-level storage primitives. Today, there are two implementations (Raft and -an in-memory backend for tests) but in the future, we envisage external storage -systems such as the Kubernetes API or an RDBMS could be supported which would -reduce operational complexity for our customers. - -#### Controllers - -[Controllers](../../internal/controller/api.go) implement Consul's business -logic using asynchronous control loops that respond to changes in resources. - -## Raft Storage Backend - -Our [Raft Storage Backend](../../internal/storage/raft/backend.go) integrates -with the existing Raft machinery (e.g. FSM) used by the [old state store]. It -also transparently forwards writes and strongly consistent reads to the leader -over gRPC. - -There's quite a lot going on here, so to dig into the details, let's take a look -at how a write operation is handled. - -[old state store]: ../persistence/ - -![raft storage backend diagram](./raft-backend.png) - -[source](https://whimsical.com/state-store-v2-UKE6SaEPXNc4UrZBrZj4Kg) - -#### Steps 1 & 2 - -User calls the resource service's `Write` endpoint, on a Raft follower, which -in-turn calls the storage backend's `WriteCAS` method. - -#### Steps 3 & 4 - -The storage backend determines that the current server is a Raft follower, and -forwards the operation to the leader via a gRPC [forwarding service] listening -on the multiplexed RPC port ([`ports.server`]). - -[forwarding service]: ../../proto/private/pbstorage/raft.proto -[`ports.server`]: https://developer.hashicorp.com/consul/docs/agent/config/config-files#server_rpc_port - -#### Step 5 - -The leader's storage backend serializes the operation to protobuf and applies it -to the Raft log. As we need to share the Raft log with the old state store, we go -through the [`consul.raftHandle`](../../agent/consul/raft_handle.go) and -[`consul.Server`](../../agent/consul/server/server.go) which applies a msgpack -envelope and type byte prefix. - -#### Step 6 - -Raft consensus happens! Once the log has been committed, it is applied to the -[FSM](../../agent/consul/fsm/fsm.go) which calls the storage backend's `Apply` -method to apply the protobuf-encoded operation to the [`inmem.Store`]. - -[`inmem.Store`]: ../../internal/storage/inmem/store.go - -#### Steps 7, 8, 9 - -At this point, the operation is complete. The forwarding service returns a -successful response, as does the follower's storage backend, and the user -gets a successful response too. - -#### Steps 10 & 11 - -Asynchronously, the log is replicated to followers and applied to their storage -backends. diff --git a/docs/resources/guide.md b/docs/resources/guide.md deleted file mode 100644 index aaecdecef07d..000000000000 --- a/docs/resources/guide.md +++ /dev/null @@ -1,441 +0,0 @@ -# Resource and Controller Developer Guide - -This is a whistle-stop tour through adding a new resource type and controller to -Consul 🚂 - -## Resource Schema - -Adding a new resource type begins with defining the object schema as a protobuf -message, in the appropriate package under [`proto-public`](../../proto-public). - -```shell -$ mkdir proto-public/pbfoo/v1alpha1 -``` - -```proto -// proto-public/pbfoo/v1alpha1/foo.proto -syntax = "proto3"; - -import "pbresource/resource.proto"; -import "pbresource/annotations.proto"; - -package hashicorp.consul.foo.v1alpha1; - -message Bar { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - string baz = 1; - hashicorp.consul.resource.ID qux = 2; -} -``` - -```shell -$ make proto -``` - -Next, we must add our resource type to the registry. At this point, it's useful -to add a package (e.g. under [`internal`](../../internal)) to contain the logic -associated with this resource type. - -The convention is to have this package export variables for its type identifiers -along with a method for registering its types: - -```Go -// internal/foo/types.go -package foo - -import ( - "github.com/hashicorp/consul/internal/resource" - pbv1alpha1 "github.com/hashicorp/consul/proto-public/pbfoo/v1alpha1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func RegisterTypes(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbv1alpha1.BarType, - Scope: resource.ScopePartition, - Proto: &pbv1alpha1.Bar{}, - }) -} -``` -Note that Scope reference the scope of the new resource, `resource.ScopePartition` -mean that resource will be at the partition level and have no namespace, while `resource.ScopeNamespace` mean it will have both a namespace -and a partition. - -Update the `NewTypeRegistry` method in [`type_registry.go`] to call your -package's type registration method: - -[`type_registry.go`]: ../../agent/consul/type_registry.go - -```Go -import ( - // … - "github.com/hashicorp/consul/internal/foo" - // … -) - -func NewTypeRegistry() resource.Registry { - // … - foo.RegisterTypes(registry) - // … -} -``` - -That should be all you need to start using your new resource type. Test it out -by starting an agent in dev mode: - -```shell -$ make dev -$ consul agent -dev -``` - -You can now use [grpcurl](https://github.com/fullstorydev/grpcurl) to interact -with the [resource service](../../proto-public/pbresource/resource.proto): - -```shell -$ grpcurl -d @ \ - -plaintext \ - -protoset pkg/consul.protoset \ - 127.0.0.1:8502 \ - hashicorp.consul.resource.ResourceService.Write \ -< **Warning** -> Writing a status to the resource will cause it to be re-reconciled. To avoid -> infinite loops, we recommend dirty checking the status before writing it with -> [`resource.EqualStatus`]. - -[`resource.EqualStatus`]: https://pkg.go.dev/github.com/hashicorp/consul/internal/resource#EqualStatus - -### Watching Other Resources - -In addition to watching their "managed" resources, controllers can also watch -resources of different, related, types. For example, the service endpoints -controller also watches workloads and services. - -```Go -func barController() controller.Controller { - return controller.ForType(pbv1alpha1.BarType). - WithWatch(pbv1alpha1.BazType, controller.MapOwner) - WithReconciler(barReconciler{}) -} -``` - -The second argument to `WithWatch` is a [dependency mapper] function. Whenever a -resource of the watched type is modified, the dependency mapper will be called -to determine which of the controller's managed resources need to be reconciled. - -[`controller.MapOwner`] is a convenience function which causes the watched -resource's [owner](#ownership--cascading-deletion) to be reconciled. - -[dependency mapper]: https://pkg.go.dev/github.com/hashicorp/consul/internal/controller#DependencyMapper -[`controller.MapOwner`]: https://pkg.go.dev/github.com/hashicorp/consul/internal/controller#MapOwner - -### Placement - -By default, only a single, leader-elected, replica of each controller will run -within a cluster. Sometimes it's necessary to override this, for example when -you want to run a copy of the controller on each server (e.g. to apply some -configuration to the server whenever it changes). You can do this by changing -the controller's placement. - -```Go -func barController() controller.Controller { - return controller.ForType(pbv1alpha1.BarType). - WithPlacement(controller.PlacementEachServer) - WithReconciler(barReconciler{}) -} -``` - -> **Warning** -> Controllers placed with [`controller.PlacementEachServer`] generally shouldn't -> modify resources (as it could lead to race conditions). - -[`controller.PlacementEachServer`]: https://pkg.go.dev/github.com/hashicorp/consul/internal/controller#PlacementEachServer - -## Ownership & Cascading Deletion - -The resource service implements a lightweight `1:N` ownership model where, on -creation, you can mark a resource as being "owned" by another resource. When the -owner is deleted, the owned resource will be deleted too. - -```Go -client.Write(ctx, &pbresource.WriteRequest{ - Resource: &pbresource.Resource{, - Owner: ownerID, - // … - }, -}) -``` diff --git a/docs/v2-architecture/controller-architecture/README.md b/docs/v2-architecture/controller-architecture/README.md new file mode 100644 index 000000000000..d781a63cc098 --- /dev/null +++ b/docs/v2-architecture/controller-architecture/README.md @@ -0,0 +1,116 @@ +# Overview + +> **Note** +> Looking for guidance on adding new resources and controllers to Consul? Check +> out the [developer guide](guide.md). + +Consul 1.16 introduced a set of [generic APIs] for managing resources, and a +[controller runtime] for building functionality on top of them. + +[generic APIs]: ../../../proto-public/pbresource/resource.proto +[controller runtime]: ../../../internal/controller + +Previously, adding features to Consul involved making changes at every layer of +the stack, including: HTTP handlers, RPC handlers, MemDB tables, Raft +operations, and CLI commands. + +This architecture made sense when the product was maintained by a small core +group who could keep the entire system in their heads, but presented significant +collaboration, ownership, and onboarding challenges when our contributor base +expanded to many engineers, across several teams, and the product grew in +complexity. + +In the new model, teams can work with much greater autonomy by building on top +of a shared platform and own their resource types and controllers. + +## Architecture Overview + +![architecture diagram](architecture-overview.png) + +[source](https://whimsical.com/state-store-v2-UKE6SaEPXNc4UrZBrZj4Kg) + +Our resource-oriented architecture comprises the following components: + +#### Resource Service + +[Resource Service](../../../proto-public/pbresource/resource.proto) is a gRPC +service that contains the shared logic for creating, reading, updating, +deleting, and watching resources. It will be consumed by controllers, our +Kubernetes integration, the CLI, and mapped to an HTTP+JSON API. + +#### Type Registry + +[Type Registry](../../../internal/resource/registry.go) is where teams register +their resource types, along with hooks for performing structural validation, +authorization, etc. + +#### Storage Backend + +[Storage Backend](../../../internal/storage/storage.go) is an abstraction over +low-level storage primitives. Today, there are two implementations (Raft and +an in-memory backend for tests) but in the future, we envisage external storage +systems such as the Kubernetes API or an RDBMS could be supported which would +reduce operational complexity for our customers. + +#### Controllers + +[Controllers](../../../internal/controller/api.go) implement Consul's business +logic using asynchronous control loops that respond to changes in resources. +Please see [Controller docs](controllers.md) for more details about controllers + +## Raft Storage Backend + +Our [Raft Storage Backend](../../../internal/storage/raft/backend.go) integrates +with the existing Raft machinery (e.g. FSM) used by the [old state store]. It +also transparently forwards writes and strongly consistent reads to the leader +over gRPC. + +There's quite a lot going on here, so to dig into the details, let's take a look +at how a write operation is handled. + +[old state store]: ../persistence/ + +![raft storage backend diagram](raft-backend.png) + +[source](https://whimsical.com/state-store-v2-UKE6SaEPXNc4UrZBrZj4Kg) + +#### Steps 1 & 2 + +User calls the resource service's `Write` endpoint, on a Raft follower, which +in-turn calls the storage backend's `WriteCAS` method. + +#### Steps 3 & 4 + +The storage backend determines that the current server is a Raft follower, and +forwards the operation to the leader via a gRPC [forwarding service] listening +on the multiplexed RPC port ([`ports.server`]). + +[forwarding service]: ../../../proto/private/pbstorage/raft.proto +[`ports.server`]: https://developer.hashicorp.com/consul/docs/agent/config/config-files#server_rpc_port + +#### Step 5 + +The leader's storage backend serializes the operation to protobuf and applies it +to the Raft log. As we need to share the Raft log with the old state store, we go +through the [`consul.raftHandle`](../../../agent/consul/raft_handle.go) and +[`consul.Server`](../../agent/consul/server/server.go) which applies a msgpack +envelope and type byte prefix. + +#### Step 6 + +Raft consensus happens! Once the log has been committed, it is applied to the +[FSM](../../../agent/consul/fsm/fsm.go) which calls the storage backend's `Apply` +method to apply the protobuf-encoded operation to the [`inmem.Store`]. + +[`inmem.Store`]: ../../../internal/storage/inmem/store.go + +#### Steps 7, 8, 9 + +At this point, the operation is complete. The forwarding service returns a +successful response, as does the follower's storage backend, and the user +gets a successful response too. + +#### Steps 10 & 11 + +Asynchronously, the log is replicated to followers and applied to their storage +backends. diff --git a/docs/resources/architecture-overview.png b/docs/v2-architecture/controller-architecture/architecture-overview.png similarity index 100% rename from docs/resources/architecture-overview.png rename to docs/v2-architecture/controller-architecture/architecture-overview.png diff --git a/docs/v2-architecture/controller-architecture/controllers.md b/docs/v2-architecture/controller-architecture/controllers.md new file mode 100644 index 000000000000..e521a07208cf --- /dev/null +++ b/docs/v2-architecture/controller-architecture/controllers.md @@ -0,0 +1,268 @@ +# Controllers + +This page describes how to write controllers in Consul's new controller architecture. + +-> **Note**: This information is valid as of Consul 1.17 but some portions may change in future releases. + +## Controller Basics + +A controller consists of several parts: + +1. **The watched type** - This is the main type a controller is watching and reconciling. +2. **Additional watched types** - These are additional types a controller may care about in addition to the main watched type. +3. **Additional custom watches** - These are the watches for things that aren't resources in Consul. +4. **Reconciler** - This is the instance that's responsible for reconciling requests whenever there's an event for the main watched type or for any of the watched types. +5. **Initializer** - This is responsible for anything that needs to be executed when the controller is started. + +A basic controller setup could look like this: + +```go +func barController() controller.Controller { + return controller.NewController("bar", pbexample.BarType). + WithReconciler(barReconciler{}) +} +``` + +barReconciler needs to implement the `Reconcile` method of the `Reconciler` interface. +It's important to note that the `Reconcile` method only gets the request with the `ID` of the main +watched resource and so it's up to the reconcile implementation to fetch the resource and any relevant information needed +to perform the reconciliation. The most basic reconciler could look as follows: + +```go +type barReconciler struct {} + +func (b *barReconciler) Reconcile(ctx context.Context, rt Runtime, req Request) error { + ... +} +``` + +## Watching Additional Resources + +Most of the time, controllers will need to watch more resources in addition to the main watched type. +To set up an additional watch, the main thing we need to figure out is how to map additional watched resource to the main +watched resource. Controller-runtime allows us to implement a mapper function that can take the additional watched resource +as the input and produce reconcile `Requests` for our main watched type. + +To figure out how to map the two resources together, we need to think about the relationship between the two resources. + +There are several common relationship types between resources that are being used currently: +1. Name-alignment: this relationship means that resources are named the same and live in the same tenancy, but have different data. Examples: `Service` and `ServiceEndpoints`, `Workload` and `ProxyStateTemplate`. +2. Selector: this relationship happens when one resource selects another by name or name prefix. Examples: `Service` and `Workload`, `ProxyConfiguration` and `Workload`. +3. Owner: in this relationship, one resource is the owner of another resource. Examples: `Service` and `ServiceEndpoints`, `HealthStatus` and `Workload`. +4. Arbitrary reference: in this relationship, one resource may reference another by some sort of reference. This reference could be a single string in the resource data or a more composite reference containing name, tenancy, and type. Examples: `Workload` and `WorkloadIdentity`, `HTTPRoute` and `Service`. + +Note that it's possible for the two watched resources to have more than one relationship type simultaneously. +For example, `FailoverPolicy` type is name-aligned with a service to which it applies, however, it also contains +references to destination services, and for a controller that reconciles `FailoverPolicy` and watches `Service` +we need to account for both type 1 and type 4 relationship whenever we get an event for a `Service`. + +### Simple Mappers + +Let's look at some simple mapping examples. + +#### Name-aligned resources +If our resources only have a name-aligned relationship, we can map them with a built-in function: + +```go +func barController() controller.Controller { + return controller.NewController("bar", pbexample.BarType). + WithWatch(pbexample.FooType, controller.ReplaceType(pbexample.BarType)). + WithReconciler(barReconciler{}) +} +``` + +Here, all we need to do is replace the type of the `Foo` resource whenever we get an event for it. + +#### Owned resources + +Let's say our `Foo` resource owns `Bar` resources, where any `Foo` resource can own multiple `Bar` resources. +In this case, whenever we see a new event for `Foo`, all we need to do is get all `Bar` resources that `Foo` currently owns. +For this, we can also use a built-in function to set up our watch: + +```go +func MapOwned(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + resp, err := rt.Client.ListByOwner(ctx, &pbresource.ListByOwnerRequest{Owner: res.Id}) + if err != nil { + return nil, err + } + + var result []controller.Request + for _, r := range resp.Resources { + result = append(result, controller.Request{ID: r.Id}) + } + + return result, nil +} + +func barController() controller.Controller { + return controller.NewController("bar", pbexample.BarType). + WithWatch(pbexample.FooType, MapOwned). + WithReconciler(barReconciler{}) +} +``` + +### Advanced Mappers and Caches + +For selector or arbitrary reference relationships, the mapping that we choose may need to be more advanced. + +#### Naive mapper implementation + +Let's first consider what a naive mapping function could look like in this case. Let's say that the `Bar` resource +references `Foo` resource by name in the data. Now to watch and map `Foo` resources, we need to be able to find all relevant `Bar` resources +whenever we get an event for a `Foo` resource. + +```go +func MapFoo(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + resp, err := rt.Client.List(ctx, &pbresource.ListRequest{Type: pbexample.BarType, Tenancy: res.Id.Tenancy}) + if err != nil { + return nil, err + } + + var result []controller.Request + for _, r := range resp.Resources { + decodedResource, err := resource.Decode[*pbexample.Bar](r) + if err != nil { + return nil, err + } + + // Only add Bar resources that match Foo by name. + if decodedResource.GetData().GetFooName() == res.Id.Name { + result = append(result, controller.Request{ID: r.Id}) + } + } +} +``` + +This approach is fine for cases when the number of `Bar` resources in a cluster is relatively small. If it's not, +then we'd be doing a large `O(N)` search on each `Bar` event which could be too expensive. + +#### Caching Mappers + +For cases when `N` is too large, we'd want to use a caching layer to help us make lookups more efficient so that they +don't require an `O(N)` search of potentially all cluster resources. + +The controller runtime contains a controller cache and the facilities to keep the cache up to date in response to watches. Additionally there are dependency mappers provided for querying the cache. + +_While it is possible to not use the builtin cache and manage state in dependency mappers yourself, this can get quite complex and reasoning about the correct times to track and untrack relationships is tricky to get right. Usage of the cache is therefore the advised approach._ + +At a high level, the controller author provides the indexes to track for each watchedtype and can then query thosfunc fooFromArgs(args ...any) ([]byte, error)e indexes in the { + +}future. The querying can occur during both dependency mapping and during resource reconciliation. + +The following example shows how to configure the "bar" controller to rereconcile a Bar resource whenever a Foo resource is changed that references the Bar + +```go +func fooReferenceFromBar(r *resource.DecodedResource[*pbexample.Bar]) (bool, []byte, error) { + idx := index.IndexFromRefOrID(&pbresource.ID{ + Type: pbexample.FooType, + Tenancy: r.Id.Tenancy, + Name: r.Data.GetFooName(), + }) + + return true, idx, nil +} + +func barController() controller.Controller { + fooIndex := indexers.DecodedSingleIndexer( + "foo", + index.ReferenceOrIDFromArgs, + fooReferenceFromBar, + ) + + return controller.NewController("bar", pbexample.BarType, fooIndex). + WithWatch( + pbexample.FooType, + dependency.CacheListMapper(pbexample.BarType, fooIndex.Name()), + ). + WithReconciler(barReconciler{}) +} +``` + +The controller will now reconcile Bar type resources whenever the Foo type resources they reference are updated. No further tracking is necessary as changes to all Bar types will automatically update the cache. + +One limitation of the cache is that it only has knowledge about the current state of resources. That specifically means that the previous state is forgotten once the cache observes a write. This can be problematic when you want to reconcile a resource to no longer take into account something that previously reference it. + +Lets say there are two types: `Baz` and `ComputedBaz` and a controller that will aggregate all `Baz` resource with some value into a single `ComputedBaz` object. When +a `Baz` resource gets updated to no longer have a value, it should not be represented in the `ComputedBaz` resource. The typical way to work around this is to: + +1. Store references to the resources that were used during reconciliation within the computed/reconciled resource. For types computed by controllers and not expected to be written directly by users a `bound_references` field should be added to the top level resource types message. For other user manageable types the references may need to be stored within the Status field. + +2. Add a cache index to the watch of the computed type (usually the controllers main managed type). This index can use one of the indexers specified within the [`internal/controller/cache/indexers`](../../../internal/controller/cache/indexers/) package. That package contains some builtin functionality around reference indexing. + +3. Update the dependency mappers to query the cache index *in addition to* looking at the current state of the dependent resource. In our example above the `Baz` dependency mapper could use the [`MultiMapper`] to combine querying the cache for `Baz` types that currently should be associated with a `ComputedBaz` and querying the index added in step 2 for previous references. + +#### Footgun: Needing Bound References + +When an interior (mutable) foreign key pointer on watched data is used to +determine the resources's applicability in a dependency mapper, it is subject +to the "orphaned computed resource" problem. + +(An example of this would be a ParentRef on an xRoute, or the Destination field +of a TrafficPermission.) + +When you edit the mutable pointer to point elsewhere, the DependencyMapper will +only witness the NEW value and will trigger reconciles for things derived from +the NEW pointer, but side effects from a prior reconcile using the OLD pointer +will be orphaned until some other event triggers that reconcile (if ever). + +This applies equally to all varieties of controller: + +- creates computed resources +- only updates status conditions on existing resources +- has other external side effects (xDS controller writes envoy config over a stream) + +To solve this we need to collect the list of bound references that were +"ingredients" into a computed resource's output and persist them on the newly +written resource. Then we load them up and index them such that we can use them +to AUGMENT a mapper event with additional maps using the OLD data as well. + +We have only actively worked to solve this for the computed resource flavor of +controller: + +1. The top level of the resource data protobuf needs a + `BoundReferences []*pbresource.Reference` field. + +2. Use a `*resource.BoundReferenceCollector` to capture any resource during + `Reconcile` that directly contributes to the final output resource data + payload. + +3. Call `brc.List()` on the above and set it to the `BoundReferences` field on + the computed resource before persisting. + +4. Use `indexers.BoundRefsIndex` to index this field on the primary type of the + controller. + +5. Create `boundRefsMapper := dependency.CacheListMapper(ZZZ, boundRefsIndex.Name())` + +6. For each watched type, wrap its DependencyMapper with + `dependency.MultiMapper(boundRefsMapper, ZZZ)` + +7. That's it. + +This will cause each reconcile to index the prior list of inputs and augment +the results of future mapper events with historical references. + +### Custom Watches + +In some cases, we may want to trigger reconciles for events that aren't generated from CRUD operations on resources, for example +when Envoy proxy connects or disconnects to a server. Controller-runtime allows us to setup watches from +events that come from a custom event channel. Please see [xds-controller](https://github.com/hashicorp/consul/blob/ecfeb7aac51df8730064d869bb1f2c633a531522/internal/mesh/internal/controllers/xds/controller.go#L40-L41) for examples of custom watches. + +## Statuses + +In many cases, controllers would need to update statuses on resources to let the user know about the successful or unsuccessful +state of a resource. + +These are the guidelines that we recommend for statuses: + +* While status conditions is a list, the Condition type should be treated as a key in a map, meaning a resource should not have two status conditions with the same type. +* Controllers need to both update successful and unsuccessful conditions states. This is because we need to make sure that we clear any failed status conditions. +* Status conditions should be named such that the `True` state is a successful state and `False` state is a failed state. + +## Best Practices + +Below is a list of controller best practices that we've learned so far. Many of them are inspired by [kubebuilder](https://book.kubebuilder.io/reference/good-practices). + +* Avoid monolithic controllers as much as possible. A single controller should only manage a single resource to avoid complexity and race conditions. +* If using cached mappers, aim to write (update or delete entries) to mappers in the `Reconcile` method and read from them in the mapper functions used by watches. +* Fetch all data in the `Reconcile` method and avoid caching it from the mapper functions. This ensures that we get the latest data for each reconciliation. diff --git a/docs/v2-architecture/controller-architecture/guide.md b/docs/v2-architecture/controller-architecture/guide.md new file mode 100644 index 000000000000..1c26838a6a63 --- /dev/null +++ b/docs/v2-architecture/controller-architecture/guide.md @@ -0,0 +1,564 @@ +# Resource and Controller Developer Guide + +This is a whistle-stop tour through adding a new resource type and controller to +Consul 🚂 + +## Resource Schema + +Adding a new resource type begins with defining the object schema as a protobuf +message, in the appropriate package under [`proto-public`](../../../proto-public). + +```shell +$ mkdir proto-public/pbfoo/v1alpha1 +``` + +```proto +// proto-public/pbfoo/v1alpha1/foo.proto +syntax = "proto3"; + +import "pbresource/resource.proto"; +import "pbresource/annotations.proto"; + +package hashicorp.consul.foo.v1alpha1; + +message Bar { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; + + string baz = 1; + hashicorp.consul.resource.ID qux = 2; +} +``` + +```shell +$ make proto +``` + +Next, we must add our resource type to the registry. At this point, it's useful +to add a package (e.g. under [`internal`](../../../internal)) to contain the logic +associated with this resource type. + +The convention is to have this package export variables for its type identifiers +along with a method for registering its types: + +```Go +// internal/foo/types.go +package foo + +import ( + "github.com/hashicorp/consul/internal/resource" + pbv1alpha1 "github.com/hashicorp/consul/proto-public/pbfoo/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +func RegisterTypes(r resource.Registry) { + r.Register(resource.Registration{ + Type: pbv1alpha1.BarType, + Scope: resource.ScopePartition, + Proto: &pbv1alpha1.Bar{}, + }) +} +``` +Note that Scope reference the scope of the new resource, `resource.ScopePartition` +mean that resource will be at the partition level and have no namespace, while `resource.ScopeNamespace` mean it will have both a namespace +and a partition. + +Update the `NewTypeRegistry` method in [`type_registry.go`] to call your +package's type registration method: + +[`type_registry.go`]: ../../../agent/consul/type_registry.go + +```Go +import ( + // … + "github.com/hashicorp/consul/internal/foo" + // … +) + +func NewTypeRegistry() resource.Registry { + // … + foo.RegisterTypes(registry) + // … +} +``` + +That should be all you need to start using your new resource type. Test it out +by starting an agent in dev mode: + +```shell +$ make dev +$ consul agent -dev +``` + +You can now use [grpcurl](https://github.com/fullstorydev/grpcurl) to interact +with the [resource service](../../../proto-public/pbresource/resource.proto): + +```shell +$ grpcurl -d @ \ + -plaintext \ + -protoset pkg/consul.protoset \ + 127.0.0.1:8502 \ + hashicorp.consul.resource.ResourceService.Write \ +< **Warning** +> Writing a status to the resource will cause it to be re-reconciled. To avoid +> infinite loops, we recommend dirty checking the status before writing it with +> [`resource.EqualStatus`]. + +[`resource.EqualStatus`]: https://pkg.go.dev/github.com/hashicorp/consul/internal/resource#EqualStatus + +### Watching Other Resources + +In addition to watching their "managed" resources, controllers can also watch +resources of different, related, types. For example, the service endpoints +controller also watches workloads and services. + +```Go +func barController() controller.Controller { + return controller.NewController("bar", pbv1alpha1.BarType). + WithWatch(pbv1alpha1.BazType, controller.MapOwner) + WithReconciler(barReconciler{}) +} +``` + +The second argument to `WithWatch` is a [dependency mapper] function. Whenever a +resource of the watched type is modified, the dependency mapper will be called +to determine which of the controller's managed resources need to be reconciled. + +[`dependency.MapOwner`] is a convenience function which causes the watched +resource's [owner](#ownership--cascading-deletion) to be reconciled. + +[dependency mapper]: https://pkg.go.dev/github.com/hashicorp/consul/internal/controller#DependencyMapper +[`dependency.MapOwner`]: https://pkg.go.dev/github.com/hashicorp/consul/internal/controller/dependency#MapOwner + +### Placement + +By default, only a single, leader-elected, replica of each controller will run +within a cluster. Sometimes it's necessary to override this, for example when +you want to run a copy of the controller on each server (e.g. to apply some +configuration to the server whenever it changes). You can do this by changing +the controller's placement. + +```Go +func barController() controller.Controller { + return controller.NewController("bar", pbv1alpha1.BarType). + WithPlacement(controller.PlacementEachServer) + WithReconciler(barReconciler{}) +} +``` + +> **Warning** +> Controllers placed with [`controller.PlacementEachServer`] generally shouldn't +> modify resources (as it could lead to race conditions). + +[`controller.PlacementEachServer`]: https://pkg.go.dev/github.com/hashicorp/consul/internal/controller#PlacementEachServer + +### Initializer + +If your controller needs to execute setup steps when the controller +first starts and before any resources are reconciled, you can add an +Initializer. + +If the controller has an Initializer, it will not start unless the +Initialize method is successful. The controller does not have retry +logic for the initialize method specifically, but the controller +is restarted on error. When restarted, the controller will attempt +to execute the initialization again. + +The example below has the controller creating a default resource as +part of initialization. + +```Go +package foo + +import ( + "context" + + "github.com/hashicorp/consul/internal/controller" + pbv1alpha1 "github.com/hashicorp/consul/proto-public/pbfoo/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +func barController() controller.Controller { + return controller.ForType(pbv1alpha1.BarType). + WithReconciler(barReconciler{}). + WithInitializer(barInitializer{}) +} + +type barInitializer struct{} + +func (barInitializer) Initialize(ctx context.Context, rt controller.Runtime) error { + _, err := rt.Client.Write(ctx, + &pbresource.WriteRequest{ + Resource: &pbresource.Resource{ + Id: &pbresource.ID{ + Name: "default", + Type: pbv1alpha1.BarType, + }, + }, + }, + ) + if err != nil { + return err + } + + return nil +} +``` + +### Finalizer + +A finalizer allows a controller to execute teardown logic before a +resource is deleted. This can be useful to perform cleanup or block +deletion until certain conditions are met. + +Finalizers are encoded as keys within a resource's metadata map. It +is the responsibility of each controller that adds a finalizer to a +resource to remove the finalizer when it is marked for deletion. +Once a resource has no finalizers present, it is deleted by the +resource service. + +When the `Delete` endpoint is called on a resource with one or more +finalizers, the resource is marked for deletion by adding an immutable +`deletionTimestamp` key to the resource's metadata map. The resource is +now effectively frozen and will only accept subsequent `Write`s +that remove finalizers. `WriteStatus` is still allowed. + +The `resource` package API can be used to manage finalizers and +check whether a resource has been marked for deletion. You would +typically use this API within the logic of your controller's +`Reconcile` method to either put a finalizer in place or perform +cleanup and then remove a finalizer. Don't forget to `Write` your +changes once you add or remove finalizers. + +```Go +package resource + +// IsMarkedForDeletion returns true if a resource has been marked for deletion, +// false otherwise. +func IsMarkedForDeletion(res *pbresource.Resource) bool { ... } + +// HasFinalizers returns true if a resource has one or more finalizers, false otherwise. +func HasFinalizers(res *pbresource.Resource) bool { ... } + +// HasFinalizer returns true if a resource has a given finalizer, false otherwise. +func HasFinalizer(res *pbresource.Resource, finalizer string) bool { ... } + +// AddFinalizer adds a finalizer to the given resource. +func AddFinalizer(res *pbresource.Resource, finalizer string) { ... } + +// RemoveFinalizer removes a finalizer from the given resource. +func RemoveFinalizer(res *pbresource.Resource, finalizer string) { ... } + +// GetFinalizers returns the set of finalizers for the given resource. +func GetFinalizers(res *pbresource.Resource) mapset.Set[string] { ... } +``` + +Example flow in a controller's `Reconcile` method +```Go +const finalizer = "consul.io/bar-finalizer" + +func (barReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { + ... + // Check if resource is marked for deletion. If yes, perform cleanup, remove finalizer, and Write the resource + if resource.IsMarkedForDeletion(res) { + // Perform some cleanup... + return EnsureFinalizerRemoved(ctx, rt, res, finalizer) + } + + // Check if resource has finalizer. If not, add it and Write the resource + if err := EnsureHasFinalizer(ctx, rt, res, finalizer); err != nil { + return err + } +} +``` + +## Ownership & Cascading Deletion + +The resource service implements a lightweight `1:N` ownership model where, on +creation, you can mark a resource as being "owned" by another resource. When the +owner is deleted, the owned resource will be deleted too. + +```Go +client.Write(ctx, &pbresource.WriteRequest{ + Resource: &pbresource.Resource{, + Owner: ownerID, + // … + }, +}) +``` + +## Testing + +Now that you have created your controller its time to test it. The types of tests each controller should have and boiler plat for test files is documented [here](./testing.md) diff --git a/docs/resources/raft-backend.png b/docs/v2-architecture/controller-architecture/raft-backend.png similarity index 100% rename from docs/resources/raft-backend.png rename to docs/v2-architecture/controller-architecture/raft-backend.png diff --git a/docs/v2-architecture/controller-architecture/testing.md b/docs/v2-architecture/controller-architecture/testing.md new file mode 100644 index 000000000000..6c49c40ecee2 --- /dev/null +++ b/docs/v2-architecture/controller-architecture/testing.md @@ -0,0 +1,219 @@ +# Controller Testing + +For every controller we want to enable 3 types of testing. + +1. Unit Tests - These should live alongside the controller and utilize mocks and the controller.TestController. Where possible split out controller functionality so that other functions can be independently tested. +2. Lightweight integration tests - These should live in an internal//test package. These tests utilize the in-memory resource service and the standard controller manager. There are two types of tests that should be created. + * Lifecycle Integration Tests - These go step by step to modify resources and check what the controller did. They are meant to go through the lifecycle of resources and how they are reconciled. Verifications are typically intermingled with resource updates. + * One-Shot Integration Tests - These tests publish a bunch of resources and then perform all the verifications. These mainly are focused on the controller eventually converging given all the resources thrown at it and aren't as concerned with any intermediate states resources go through. +3. Container based integration tests - These tests live along with our other container based integration tests. They utilize a full multi-node cluster (and sometimes client agents). There are 3 types of tests that can be created here: + * Lifecycle Integration Tests - These are the same as for the lighweight integration tests. + * One-shot IntegrationTests - These are the same as for the lightweight integration tests. + * Upgrade Tests - These are a special form of One-shot Integration tests where the cluster is brought up with some original version, data is pushed in, an upgrade is done and then we verify the consistency of the data post-upgrade. + + +Between the lightweight and container based integration tests there is a lot of duplication in what is being tested. For this reason these integration test bodies should be defined as exported functions within the apigroups test package. The container based tests can then import those packages and invoke the same functionality with minimal overhead. + +For one-shot integration tests, functions to do the resource publishing should be split from functions to perform the verifications. This allows upgrade tests to publish the resources once pre-upgrade and then validate that their correctness post-upgrade without requiring rewriting them. + +Sometimes it may also be a good idea to export functions in the test packages for running a specific controllers integration tests. This is a good idea when the controller will use a different version of a dependency in Consul Enterprise to allow for the enterprise implementations package to invoke the integration tests after setting up the controller with its injected dependency. + +## Unit Test Template + +These tests live alongside controller source. + +```go +package foo + +import ( + "testing" + + "github.com/stretchr/testif/mock" + "github.com/stretchr/testif/require" + "github.com/stretchr/testif/suite" +) + +func TestReconcile(t *testing.T) { + rtest.RunWithTenancies(func(tenancy *pbresource.Tenancy) { + suite.Run(t, &reconcileSuite{tenancy: tenancy}) + }) +} + +type reconcileSuite struct { + suite.Suite + + tenancy *pbresource.Tenancy + + ctx context.Context + ctl *controller.TestController + client *rtest.Client + + // Mock objects needed for testing +} + +func (suite *reconcileSuite) SetupTest() { + suite.ctx = testutil.TestContext(suite.T()) + + // Alternatively it is sometimes useful to use a mock resource service. For that + // you can use github.com/hashicorp/consul/grpcmocks.NewResourceServiceClient + // to create the client. + client := svctest.NewResourceServiceBuilder(). + // register this API groups types. Also register any other + // types this controller depends on. + WithRegisterFns(types.Register). + WithTenancies(suite.tenancy). + Run(suite.T()) + + // Build any mock objects or other dependencies of the controller here. + + // Build the TestController + suite.ctl = controller.NewTestController(Controller(), client) + suite.client = rtest.NewClient(suite.ctl.Runtime().Client) +} + +// Implement tests on the suite as needed. +func (suite *reconcileSuite) TestSomething() { + // Setup Mock expectations + + // Push resources into the resource service as needed. + + // Issue the Reconcile call + suite.ctl.Reconcile(suite.ctx, controller.Request{}) +} +``` + +## Integration Testing Templates + +These tests should live in internal//test. For these examples, assume the API group under test is named `foo` and the latest API group version is v2. + +### `run_test.go` + +This file is how `go test` knows to execute the tests. These integration tests should +be executed against an in-memory resource service with the standard controller manager. + +```go +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package footest + +import ( + "testing" + + "github.com/hashicorp/consul/internal/foo" + "github.com/hashicorp/consul/internal/controller/controllertest" + "github.com/hashicorp/consul/internal/resource/reaper" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +var ( + // This makes the CLI options available to control timing delays of requests. The + // randomized timings helps to build confidence that regardless of resources writes + // occurring in quick succession, the controller under test will eventually converge + // on its steady state. + clientOpts = rtest.ConfigureTestCLIFlags() +) + +func runInMemResourceServiceAndControllers(t *testing.T) pbresource.ResourceServiceClient { + t.Helper() + + return controllertest.NewControllerTestBuilder(). + // Register your types for the API group and any others that these tests will depend on + WithResourceRegisterFns(types.Register). + WithControllerRegisterFns( + reaper.RegisterControllers, + foo.RegisterControllers, + ).Run(t) +} + +// The basic integration test should operate mostly in a one-shot manner where resources +// are published and then verifications are performed. +func TestControllers_Integration(t *testing.T) { + client := runInMemResourceServiceAndControllers(t) + RunFooV2IntegrationTest(t, client, clientOpts.ClientOptions(t)...) +} + +// The lifecycle integration test is typically more complex and deals with changing +// some values over time to cause the controllers to do something differently. +func TestControllers_Lifecycle(t *testing.T) { + client := runInMemResourceServiceAndControllers(t) + RunFooV2LifecycleTest(t, client, clientOpts.ClientOptions(t)...) +} + +``` + +### `test_integration_v2.go` + + +```go +package footest + +import ( + "embed" + "fmt" + "testing" + + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +var ( + //go:embed integration_test_data + testData embed.FS +) + +// Execute the full integration test +func RunFooV2IntegrationTest(t *testing.T, client pbresource.ResourceServiceClient, opts ...rtest.ClientOption) { + t.Helper + + PublishFooV2IntegrationTestData(t, client, opts...) + VerifyFooV2IntegrationTestResults(t, client) +} + +// PublishFooV2IntegrationTestData publishes all the data that needs to exist in the resource service +// for the controllers to converge on the desired state. +func PublishFooV2IntegrationTestData(t *testing.T, client pbresource.ResourceServiceClient, opts ...rtest.ClientOption) { + t.Helper() + + c := rtest.NewClient(client, opts...) + + // Publishing resources manually is an option but alternatively you can store the resources on disk + // and use go:embed declarations to embed the whole test data filesystem into the test binary. + resources := rtest.ParseResourcesFromFilesystem(t, testData, "integration_test_data/v2") + c.PublishResources(t, resources) +} + +func VerifyFooV2IntegrationTestResults(t *testing.T, client pbresource.ResourceServiceClient) { + t.Helper() + + c := rtest.NewClient(client) + + // Perform verifications here. All verifications should be retryable except in very exceptional circumstances. + // This could be in a retry.Run block or could be retryed by using one of the WaitFor* methods on the rtest.Client. + // Having them be retryable will prevent flakes especially when the verifications are run in the context of + // a multi-server cluster where a raft follower hasn't yet observed some change. +} +``` + +### `test_lifecycle_v2.go` + +```go +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package footest + +import ( + "testing" + + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +func RunFooV2LifecycleIntegrationTest(t *testing.T, client pbresource.ResourceServiceClient, opts ...rtest.ClientOption) { + t.Helper() + + // execute tests. +} +``` diff --git a/docs/v2-architecture/service-mesh/README.md b/docs/v2-architecture/service-mesh/README.md new file mode 100644 index 000000000000..4d0b6e9ff279 --- /dev/null +++ b/docs/v2-architecture/service-mesh/README.md @@ -0,0 +1,47 @@ +# V2 Service Mesh Architecture + +In Consul 1.16 and 1.17 releases, Consul's service mesh has been rewritten to use the controller architecture and the +resource APIs. + +At a high level, the service mesh consists of resources and controllers living in three groups: `catalog`, `mesh`, +and `auth`. + +![controllers diagram](controllers.png) + +The controllers in each groups are responsible for producing an output that may then be used by other controllers. + +-> **Note:** This diagram is valid as of Consul 1.17. It may change in the future releases. + +## Catalog controllers + +Catalog controllers are responsible for reconciling resources in the `catalog` API group. + +1. **FailoverPolicy** controller validates `FailoverPolicy` resource has valid service references and updating the + status the `FailoverPolicy` resource with the result. +2. **WorkloadHealth** controller takes in workloads and any relevant health statuses and updates the status of a + workload with the combined health status. +3. **NodeHealth** controller takes in nodes and any relevant health statuses and updates the status of a node with the + combined health status. +4. **ServiceEndpoints** controller generates a `ServiceEndpoints` object that is name-aligned with a service and + contains workload addresses and ports that constitute a service. + +## Mesh Controllers + +1. **ProxyConfiguration** controller generates a `ComputedProxyConfiguration` resource that is name-aligned with a + workload. `ComputedProxyConfiguration` contains all merged `ProxyConfiguration` resources that apply to a specific + workload. +2. **Routes** controller generates a `ComputedRoutes` resource that is name-aligned with a service. It contains merged + configuration from all xRoutes objects as well as `FailoverPolicy` and `DestinationPolicy`. +3. **ExplicitDestinations** controller generates a `ComputedExplicitDestinations` resource that is name-aligned with a + workload. It contains merged `Destinations` resources that apply to a specific workload. +4. **SidecarProxy** controller takes in the results of the previous three controllers as well as some user-provided + resources and generates `ProxyStateTemplate` resource which serves as the representation of Envoy configuration for + sidecar proxies. +5. **XDSController** takes in `ProxyStateTemplate` resources, fills in missing endpoints references as well as + certificates and CA roots and sends them over to another component that sends this information over to Envoy. + +## Auth Controllers + +1. **TrafficPermissions** controller generates `ComputedTrafficPermissions` resource that is name-aligned + with `WorkloadIdentity`. This computed resource contains all traffic permissions that apply to a specific workload + identity. \ No newline at end of file diff --git a/docs/v2-architecture/service-mesh/controllers.png b/docs/v2-architecture/service-mesh/controllers.png new file mode 100644 index 000000000000..76efac1d059c Binary files /dev/null and b/docs/v2-architecture/service-mesh/controllers.png differ diff --git a/envoyextensions/extensioncommon/basic_envoy_extender.go b/envoyextensions/extensioncommon/basic_envoy_extender.go index 86cee8f14a4e..eb126c3e38b6 100644 --- a/envoyextensions/extensioncommon/basic_envoy_extender.go +++ b/envoyextensions/extensioncommon/basic_envoy_extender.go @@ -296,6 +296,27 @@ func (b *BasicEnvoyExtender) patchSupportedListenerFilterChains(config *RuntimeC func (b *BasicEnvoyExtender) patchListenerFilterChains(config *RuntimeConfig, l *envoy_listener_v3.Listener, nameOrSNI string) (*envoy_listener_v3.Listener, error) { var resultErr error + // Special case for Permissive mTLS, which adds a filter chain + // containing a TCP Proxy only. We don't care about errors + // applying filters as long as the main filter chain is + // patched successfully. + if IsInboundPublicListener(l) && len(l.FilterChains) > 1 { + var isPatched bool + for idx, filterChain := range l.FilterChains { + patchedFilterChain, err := b.patchFilterChain(config, filterChain, l) + if err != nil { + resultErr = multierror.Append(resultErr, fmt.Errorf("error patching listener filter chain %q: %w", nameOrSNI, err)) + continue + } + l.FilterChains[idx] = patchedFilterChain + isPatched = true + } + if isPatched { + return l, nil + } + return l, resultErr + } + for idx, filterChain := range l.FilterChains { if patchedFilterChain, err := b.patchFilterChain(config, filterChain, l); err == nil { l.FilterChains[idx] = patchedFilterChain diff --git a/envoyextensions/go.mod b/envoyextensions/go.mod index f6f1b1b186fc..9970e5d71f65 100644 --- a/envoyextensions/go.mod +++ b/envoyextensions/go.mod @@ -4,29 +4,32 @@ go 1.20 replace ( github.com/hashicorp/consul/api => ../api + github.com/hashicorp/consul/proto-public => ../proto-public github.com/hashicorp/consul/sdk => ../sdk ) +retract v0.7.2 // tag was mutated + require ( - github.com/envoyproxy/go-control-plane v0.11.0 + github.com/envoyproxy/go-control-plane v0.12.0 github.com/google/go-cmp v0.5.9 - github.com/hashicorp/consul/api v1.26.1 - github.com/hashicorp/consul/sdk v0.15.0 + github.com/hashicorp/consul/api v1.29.4 + github.com/hashicorp/consul/sdk v0.16.1 github.com/hashicorp/go-hclog v1.5.0 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-version v1.2.1 - github.com/stretchr/testify v1.8.3 - google.golang.org/protobuf v1.30.0 + github.com/stretchr/testify v1.8.4 + google.golang.org/protobuf v1.33.0 ) require ( github.com/armon/go-metrics v0.4.1 // indirect github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect - github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 // indirect + github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/envoyproxy/protoc-gen-validate v0.10.0 // indirect - github.com/fatih/color v1.14.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect @@ -35,13 +38,14 @@ require ( github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/serf v0.10.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect - golang.org/x/sys v0.13.0 // indirect - google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + golang.org/x/sys v0.19.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/envoyextensions/go.sum b/envoyextensions/go.sum index b611aa2308ee..d29e39ebe83f 100644 --- a/envoyextensions/go.sum +++ b/envoyextensions/go.sum @@ -22,23 +22,23 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 h1:58f1tJ1ra+zFINPlwLWvQsR9CzAKt2e+EWV2yX9oXQ4= -github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.11.0 h1:jtLewhRR2vMRNnq2ZZUoCjUlgut+Y0+sDDWPOfwOi1o= -github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.10.0 h1:oIfnZFdC0YhpNNEX+SuIqko4cqqVZeN9IGTrhZje83Y= -github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -50,15 +50,13 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -106,10 +104,10 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -123,8 +121,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= @@ -177,8 +175,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -200,7 +198,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -229,8 +227,9 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -248,15 +247,15 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/envoyextensions/xdscommon/ENVOY_VERSIONS b/envoyextensions/xdscommon/ENVOY_VERSIONS new file mode 100644 index 000000000000..884f30573206 --- /dev/null +++ b/envoyextensions/xdscommon/ENVOY_VERSIONS @@ -0,0 +1,14 @@ +# This file represents the canonical list of supported Envoy versions for this version of Consul. +# +# Every line must contain a valid version number in the format "x.y.z" where x, y, and z are integers. +# All other lines must be comments beginning with a "#", or a blank line. +# +# Every prior "minor" version for a given "major" (x.y) version is implicitly supported unless excluded by +# `xdscommon.UnsupportedEnvoyVersions`. For example, 1.28.3 implies support for 1.28.0, 1.28.1, and 1.28.2. +# +# See https://www.consul.io/docs/connect/proxies/envoy#supported-versions for more information on Consul's Envoy +# version support. +1.31.2 +1.30.6 +1.29.9 +1.28.7 diff --git a/envoyextensions/xdscommon/envoy_versioning.go b/envoyextensions/xdscommon/envoy_versioning.go index c5f9d4798c10..4b95e1bf2cd0 100644 --- a/envoyextensions/xdscommon/envoy_versioning.go +++ b/envoyextensions/xdscommon/envoy_versioning.go @@ -13,7 +13,7 @@ import ( var ( // minSupportedVersion is the oldest mainline version we support. This should always be // the zero'th point release of the last element of xdscommon.EnvoyVersions. - minSupportedVersion = version.Must(version.NewVersion(GetMinEnvoyMinorVersion())) + minSupportedVersion = version.Must(version.NewVersion(GetMinEnvoyMajorVersion())) specificUnsupportedVersions = []unsupportedVersion{} ) diff --git a/envoyextensions/xdscommon/envoy_versioning_test.go b/envoyextensions/xdscommon/envoy_versioning_test.go index 925e2fa5378f..8b0b42fc8c6f 100644 --- a/envoyextensions/xdscommon/envoy_versioning_test.go +++ b/envoyextensions/xdscommon/envoy_versioning_test.go @@ -4,6 +4,8 @@ package xdscommon import ( + "fmt" + "slices" "testing" envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" @@ -70,99 +72,53 @@ func TestDetermineEnvoyVersionFromNode(t *testing.T) { } func TestDetermineSupportedProxyFeaturesFromString(t *testing.T) { - const ( - errTooOld = "is too old and is not supported by Consul" - ) + const errTooOld = "is too old and is not supported by Consul" type testcase struct { + name string expect SupportedProxyFeatures expectErr string } + var cases []testcase - // Just the bad versions - cases := map[string]testcase{ - "1.9.0": {expectErr: "Envoy 1.9.0 " + errTooOld}, - "1.10.0": {expectErr: "Envoy 1.10.0 " + errTooOld}, - "1.11.0": {expectErr: "Envoy 1.11.0 " + errTooOld}, - "1.12.0": {expectErr: "Envoy 1.12.0 " + errTooOld}, - "1.12.1": {expectErr: "Envoy 1.12.1 " + errTooOld}, - "1.12.2": {expectErr: "Envoy 1.12.2 " + errTooOld}, - "1.12.3": {expectErr: "Envoy 1.12.3 " + errTooOld}, - "1.12.4": {expectErr: "Envoy 1.12.4 " + errTooOld}, - "1.12.5": {expectErr: "Envoy 1.12.5 " + errTooOld}, - "1.12.6": {expectErr: "Envoy 1.12.6 " + errTooOld}, - "1.12.7": {expectErr: "Envoy 1.12.7 " + errTooOld}, - "1.13.0": {expectErr: "Envoy 1.13.0 " + errTooOld}, - "1.13.1": {expectErr: "Envoy 1.13.1 " + errTooOld}, - "1.13.2": {expectErr: "Envoy 1.13.2 " + errTooOld}, - "1.13.3": {expectErr: "Envoy 1.13.3 " + errTooOld}, - "1.13.4": {expectErr: "Envoy 1.13.4 " + errTooOld}, - "1.13.5": {expectErr: "Envoy 1.13.5 " + errTooOld}, - "1.13.6": {expectErr: "Envoy 1.13.6 " + errTooOld}, - "1.13.7": {expectErr: "Envoy 1.13.7 " + errTooOld}, - "1.14.0": {expectErr: "Envoy 1.14.0 " + errTooOld}, - "1.14.1": {expectErr: "Envoy 1.14.1 " + errTooOld}, - "1.14.2": {expectErr: "Envoy 1.14.2 " + errTooOld}, - "1.14.3": {expectErr: "Envoy 1.14.3 " + errTooOld}, - "1.14.4": {expectErr: "Envoy 1.14.4 " + errTooOld}, - "1.14.5": {expectErr: "Envoy 1.14.5 " + errTooOld}, - "1.14.6": {expectErr: "Envoy 1.14.6 " + errTooOld}, - "1.14.7": {expectErr: "Envoy 1.14.7 " + errTooOld}, - "1.15.0": {expectErr: "Envoy 1.15.0 " + errTooOld}, - "1.15.1": {expectErr: "Envoy 1.15.1 " + errTooOld}, - "1.15.2": {expectErr: "Envoy 1.15.2 " + errTooOld}, - "1.15.3": {expectErr: "Envoy 1.15.3 " + errTooOld}, - "1.15.4": {expectErr: "Envoy 1.15.4 " + errTooOld}, - "1.15.5": {expectErr: "Envoy 1.15.5 " + errTooOld}, - "1.16.1": {expectErr: "Envoy 1.16.1 " + errTooOld}, - "1.16.2": {expectErr: "Envoy 1.16.2 " + errTooOld}, - "1.16.3": {expectErr: "Envoy 1.16.3 " + errTooOld}, - "1.16.4": {expectErr: "Envoy 1.16.4 " + errTooOld}, - "1.16.5": {expectErr: "Envoy 1.16.5 " + errTooOld}, - "1.16.6": {expectErr: "Envoy 1.16.6 " + errTooOld}, - "1.17.4": {expectErr: "Envoy 1.17.4 " + errTooOld}, - "1.18.6": {expectErr: "Envoy 1.18.6 " + errTooOld}, - "1.19.5": {expectErr: "Envoy 1.19.5 " + errTooOld}, - "1.20.7": {expectErr: "Envoy 1.20.7 " + errTooOld}, - "1.21.5": {expectErr: "Envoy 1.21.5 " + errTooOld}, - "1.22.0": {expectErr: "Envoy 1.22.0 " + errTooOld}, - "1.22.1": {expectErr: "Envoy 1.22.1 " + errTooOld}, - "1.22.2": {expectErr: "Envoy 1.22.2 " + errTooOld}, - "1.22.3": {expectErr: "Envoy 1.22.3 " + errTooOld}, - "1.22.4": {expectErr: "Envoy 1.22.4 " + errTooOld}, - "1.22.5": {expectErr: "Envoy 1.22.5 " + errTooOld}, - "1.22.6": {expectErr: "Envoy 1.22.6 " + errTooOld}, - "1.22.7": {expectErr: "Envoy 1.22.7 " + errTooOld}, - "1.22.8": {expectErr: "Envoy 1.22.8 " + errTooOld}, - "1.22.9": {expectErr: "Envoy 1.22.9 " + errTooOld}, - "1.22.10": {expectErr: "Envoy 1.22.10 " + errTooOld}, - "1.22.11": {expectErr: "Envoy 1.22.11 " + errTooOld}, + // Bad versions. + minMajorVersion := version.Must(version.NewVersion(getMinEnvoyVersion())) + minMajorVersionMajorPart := minMajorVersion.Segments()[len(minMajorVersion.Segments())-2] + for major := 9; major < minMajorVersionMajorPart; major++ { + for minor := 0; minor < 10; minor++ { + cases = append(cases, testcase{ + name: version.Must(version.NewVersion(fmt.Sprintf("1.%d.%d", major, minor))).String(), + expectErr: errTooOld, + }) + } } - // Insert a bunch of valid versions. - // Populate feature flags here when appropriate. See consul 1.10.x for reference. - /* Example from 1.18 - for _, v := range []string{ - "1.18.0", "1.18.1", "1.18.2", "1.18.3", "1.18.4", "1.18.5", "1.18.6", - } { - cases[v] = testcase{expect: SupportedProxyFeatures{ - ForceLDSandCDSToAlwaysUseWildcardsOnReconnect: true, - }} - } - */ - for _, v := range []string{ - "1.24.0", "1.24.1", "1.24.2", "1.24.3", "1.24.4", "1.24.5", "1.24.6", "1.24.7", "1.24.8", "1.24.9", "1.24.10", "1.24.11", "1.24.12", - "1.25.0", "1.25.1", "1.25.2", "1.25.3", "1.25.4", "1.25.5", "1.25.6", "1.25.7", "1.25.8", "1.25.9", "1.25.10", "1.25.11", - "1.26.0", "1.26.1", "1.26.2", "1.26.3", "1.26.4", "1.26.5", "1.26.6", - "1.27.0", "1.27.1", "1.27.2", - } { - cases[v] = testcase{expect: SupportedProxyFeatures{}} + // Good versions. + // Sort ascending so test output is ordered like bad cases above. + var supportedVersionsAscending []string + supportedVersionsAscending = append(supportedVersionsAscending, EnvoyVersions...) + slices.Reverse(supportedVersionsAscending) + for _, v := range supportedVersionsAscending { + envoyVersion := version.Must(version.NewVersion(v)) + // e.g. this is 27 in 1.27.4 + versionMajorPart := envoyVersion.Segments()[len(envoyVersion.Segments())-2] + // e.g. this is 4 in 1.27.4 + versionMinorPart := envoyVersion.Segments()[len(envoyVersion.Segments())-1] + + // Create synthetic minor versions from .0 through the actual configured version. + for minor := 0; minor <= versionMinorPart; minor++ { + minorVersion := version.Must(version.NewVersion(fmt.Sprintf("1.%d.%d", versionMajorPart, minor))) + cases = append(cases, testcase{ + name: minorVersion.String(), + expect: SupportedProxyFeatures{}, + }) + } } - for name, tc := range cases { + for _, tc := range cases { tc := tc - t.Run(name, func(t *testing.T) { - sf, err := DetermineSupportedProxyFeaturesFromString(name) + t.Run(tc.name, func(t *testing.T) { + sf, err := DetermineSupportedProxyFeaturesFromString(tc.name) if tc.expectErr == "" { require.NoError(t, err) require.Equal(t, tc.expect, sf) diff --git a/envoyextensions/xdscommon/proxysupport.go b/envoyextensions/xdscommon/proxysupport.go index 9e487e1867e2..d0afcc7390fe 100644 --- a/envoyextensions/xdscommon/proxysupport.go +++ b/envoyextensions/xdscommon/proxysupport.go @@ -3,7 +3,64 @@ package xdscommon -import "strings" +import ( + _ "embed" + "fmt" + "slices" + "strconv" + "strings" +) + +// File containing the canonical range of supported Envoy versions for this version of Consul. +// This file should contain exactly one point release for each major release of Envoy, per line. +// All other contents must be blank lines or comments. Comments must be on their own line starting with '#'. +// +//go:embed ENVOY_VERSIONS +var envoyVersionsRaw string + +// initEnvoyVersions calls parseEnvoyVersions and panics if it returns an error. Used to set EnvoyVersions. +func initEnvoyVersions() []string { + versions, err := parseEnvoyVersions(envoyVersionsRaw) + if err != nil { + panic(err) + } + return versions +} + +// parseEnvoyVersions parses the ENVOY_VERSIONS file and returns a list of supported Envoy versions. +func parseEnvoyVersions(raw string) ([]string, error) { + lines := strings.Split(raw, "\n") + var versionLines []string + for _, line := range lines { + trimmed := strings.TrimSpace(line) + if trimmed == "" || strings.HasPrefix(trimmed, "#") { + continue // skip empty lines and comments + } + + // Assume all remaining lines are valid Envoy versions in the format "X.Y.Z". + versionParts := strings.Split(trimmed, ".") + if len(versionParts) != 3 { + return nil, fmt.Errorf("invalid version in ENVOY_VERSIONS: %s", line) + } + for _, v := range versionParts { + if _, err := strconv.Atoi(v); err != nil { + return nil, fmt.Errorf("invalid version in ENVOY_VERSIONS: %s", line) + } + } + versionLines = append(versionLines, trimmed) + } + + // Ensure sorted in descending order. + // We do this here as well as tests because other code (e.g. Makefile) may depend on the order + // of these values, so we want early detection in case tests are not run before compilation. + if !slices.IsSortedFunc(versionLines, func(v1, v2 string) int { + return strings.Compare(v2, v1) + }) { + return nil, fmt.Errorf("ENVOY_VERSIONS must be sorted in descending order") + } + + return versionLines, nil +} // EnvoyVersions lists the latest officially supported versions of envoy. // @@ -11,12 +68,7 @@ import "strings" // each major release should be present. // // see: https://www.consul.io/docs/connect/proxies/envoy#supported-versions -var EnvoyVersions = []string{ - "1.27.2", - "1.26.6", - "1.25.11", - "1.24.12", -} +var EnvoyVersions = initEnvoyVersions() // UnsupportedEnvoyVersions lists any unsupported Envoy versions (mainly minor versions) that fall // within the range of EnvoyVersions above. @@ -27,18 +79,28 @@ var EnvoyVersions = []string{ // see: https://www.consul.io/docs/connect/proxies/envoy#supported-versions var UnsupportedEnvoyVersions = []string{} -// GetMaxEnvoyMinorVersion grabs the first value in EnvoyVersions and strips the patch number off in order -// to return the maximum supported Envoy minor version +// GetMaxEnvoyMajorVersion grabs the first value in EnvoyVersions and strips the last number off in order +// to return the maximum supported Envoy "major" version. // For example, if the input string is "1.14.1", the function would return "1.14". -func GetMaxEnvoyMinorVersion() string { - s := strings.Split(EnvoyVersions[0], ".") +func GetMaxEnvoyMajorVersion() string { + s := strings.Split(getMaxEnvoyVersion(), ".") return s[0] + "." + s[1] } -// GetMinEnvoyMinorVersion grabs the last value in EnvoyVersions and strips the patch number off in order -// to return the minimum supported Envoy minor version +// GetMinEnvoyMajorVersion grabs the last value in EnvoyVersions and strips the patch number off in order +// to return the minimum supported Envoy "major" version. // For example, if the input string is "1.12.1", the function would return "1.12". -func GetMinEnvoyMinorVersion() string { - s := strings.Split(EnvoyVersions[len(EnvoyVersions)-1], ".") +func GetMinEnvoyMajorVersion() string { + s := strings.Split(getMinEnvoyVersion(), ".") return s[0] + "." + s[1] } + +// getMaxEnvoyVersion returns the first (highest) value in EnvoyVersions. +func getMaxEnvoyVersion() string { + return EnvoyVersions[0] +} + +// getMinEnvoyVersion returns the last (lowest) value in EnvoyVersions. +func getMinEnvoyVersion() string { + return EnvoyVersions[len(EnvoyVersions)-1] +} diff --git a/envoyextensions/xdscommon/proxysupport_test.go b/envoyextensions/xdscommon/proxysupport_test.go index cc90b726c9d9..d61847834501 100644 --- a/envoyextensions/xdscommon/proxysupport_test.go +++ b/envoyextensions/xdscommon/proxysupport_test.go @@ -4,6 +4,7 @@ package xdscommon import ( + "slices" "sort" "testing" @@ -11,11 +12,17 @@ import ( "github.com/stretchr/testify/assert" ) +// TestProxySupportOrder tests that the values in EnvoyVersions are valid (X.Y.Z), contiguous by "major" (X.Y) version, +// and sorted in descending order. func TestProxySupportOrder(t *testing.T) { versions := make([]*version.Version, len(EnvoyVersions)) beforeSort := make([]*version.Version, len(EnvoyVersions)) for i, raw := range EnvoyVersions { v, _ := version.NewVersion(raw) + if v.Segments()[0] != 1 { + // If this fails, we need to add support for a new semver-major (x in x.y.z) version of Envoy + t.Fatalf("Expected major version to be 1, got: %v", v.Segments()[0]) + } versions[i] = v beforeSort[i] = v } @@ -30,4 +37,48 @@ func TestProxySupportOrder(t *testing.T) { for i := range EnvoyVersions { assert.True(t, versions[i].Equal(beforeSort[i])) } + + // Check that we have a continues set of versions + for i := 1; i < len(versions); i++ { + previousMajorVersion := getMajorVersion(versions[i-1]) + majorVersion := getMajorVersion(versions[i]) + assert.True(t, majorVersion == previousMajorVersion-1, + "Expected Envoy major version following %d.%d to be %d.%d, got %d.%d", + versions[i-1].Segments()[0], + previousMajorVersion, + versions[i-1].Segments()[0], + previousMajorVersion-1, + versions[i].Segments()[0], + majorVersion) + } +} + +func TestParseEnvoyVersions(t *testing.T) { + // Test with valid versions, comments, and blank lines + raw := "# Comment\n1.29.4\n\n# More\n# comments\n1.28.3\n\n1.27.5\n1.26.8\n\n" + expected := []string{"1.29.4", "1.28.3", "1.27.5", "1.26.8"} + + versions, err := parseEnvoyVersions(raw) + assert.NoError(t, err) + + if !slices.Equal(versions, expected) { + t.Fatalf("Expected %v, got: %v", expected, versions) + } + + // Test with invalid version + raw = "1.29.4\n1.26.8\nfoo" + + _, err = parseEnvoyVersions(raw) + assert.EqualError(t, err, "invalid version in ENVOY_VERSIONS: foo") + + // Test with out-of-order values + raw = "1.29.4\n1.26.8\n1.27.5" + + _, err = parseEnvoyVersions(raw) + assert.EqualError(t, err, "ENVOY_VERSIONS must be sorted in descending order") +} + +// getMajorVersion returns the "major" (Y in X.Y.Z) version of the given Envoy version. +func getMajorVersion(version *version.Version) int { + return version.Segments()[1] } diff --git a/envoyextensions/xdscommon/xdscommon.go b/envoyextensions/xdscommon/xdscommon.go index ae40f070210f..69a49ab6311b 100644 --- a/envoyextensions/xdscommon/xdscommon.go +++ b/envoyextensions/xdscommon/xdscommon.go @@ -8,6 +8,7 @@ import ( envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" + envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" "github.com/hashicorp/go-hclog" "google.golang.org/protobuf/proto" ) @@ -111,7 +112,7 @@ func IndexResources(logger hclog.Logger, resources map[string][]proto.Message) * } func GetResourceName(res proto.Message) string { - // NOTE: this only covers types that we currently care about for LDS/RDS/CDS/EDS + // NOTE: this only covers types that we currently care about for LDS/RDS/CDS/EDS/SDS switch x := res.(type) { case *envoy_listener_v3.Listener: // LDS return x.Name @@ -121,6 +122,8 @@ func GetResourceName(res proto.Message) string { return x.Name case *envoy_endpoint_v3.ClusterLoadAssignment: // EDS return x.ClusterName + case *envoy_tls_v3.Secret: // SDS + return x.Name default: return "" } @@ -133,6 +136,7 @@ func EmptyIndexedResources() *IndexedResources { RouteType: make(map[string]proto.Message), ClusterType: make(map[string]proto.Message), EndpointType: make(map[string]proto.Message), + SecretType: make(map[string]proto.Message), }, ChildIndex: map[string]map[string][]string{ ListenerType: make(map[string][]string), diff --git a/go.mod b/go.mod index a443ce4336e5..debde423e654 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/hashicorp/consul -go 1.20 +go 1.22 + +toolchain go1.22.5 replace ( github.com/hashicorp/consul/api => ./api @@ -21,40 +23,43 @@ require ( github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e github.com/armon/go-metrics v0.4.1 github.com/armon/go-radix v1.0.0 - github.com/aws/aws-sdk-go v1.44.289 - github.com/coredns/coredns v1.10.1 - github.com/coreos/go-oidc v2.1.0+incompatible + github.com/aws/aws-sdk-go v1.55.5 + github.com/coreos/go-oidc/v3 v3.9.0 github.com/deckarep/golang-set/v2 v2.3.1 github.com/docker/go-connections v0.4.0 - github.com/envoyproxy/go-control-plane v0.11.1 + github.com/envoyproxy/go-control-plane v0.12.0 github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e - github.com/fatih/color v1.14.1 + github.com/fatih/color v1.16.0 github.com/fsnotify/fsnotify v1.6.0 - github.com/go-openapi/runtime v0.25.0 - github.com/go-openapi/strfmt v0.21.3 + github.com/fullstorydev/grpchan v1.1.1 + github.com/go-jose/go-jose/v3 v3.0.3 + github.com/go-openapi/runtime v0.26.2 + github.com/go-openapi/strfmt v0.21.10 github.com/google/go-cmp v0.5.9 github.com/google/gofuzz v1.2.0 github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 + github.com/hashi-derek/grpc-proxy v0.0.0-20231207191910-191266484d75 github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706 github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69 - github.com/hashicorp/consul/api v1.26.1 - github.com/hashicorp/consul/envoyextensions v0.5.1 - github.com/hashicorp/consul/proto-public v0.5.1 - github.com/hashicorp/consul/sdk v0.15.0 - github.com/hashicorp/consul/troubleshoot v0.4.1 + github.com/hashicorp/consul/api v1.29.4 + github.com/hashicorp/consul/envoyextensions v0.7.3 + github.com/hashicorp/consul/proto-public v0.6.2 + github.com/hashicorp/consul/sdk v0.16.1 + github.com/hashicorp/consul/troubleshoot v0.7.1 github.com/hashicorp/go-bexpr v0.1.2 github.com/hashicorp/go-checkpoint v0.5.0 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-connlimit v0.3.0 - github.com/hashicorp/go-discover v0.0.0-20220714221025-1c234a67149a - github.com/hashicorp/go-hclog v1.5.0 + github.com/hashicorp/go-discover v0.0.0-20230724184603-e89ebd1b2f65 + github.com/hashicorp/go-hclog v1.6.3 github.com/hashicorp/go-immutable-radix v1.3.1 + github.com/hashicorp/go-immutable-radix/v2 v2.1.0 github.com/hashicorp/go-memdb v1.3.4 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-raftchunking v0.7.0 - github.com/hashicorp/go-retryablehttp v0.6.7 + github.com/hashicorp/go-retryablehttp v0.7.7 github.com/hashicorp/go-rootcerts v1.0.2 github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 github.com/hashicorp/go-sockaddr v1.0.2 @@ -65,8 +70,8 @@ require ( github.com/hashicorp/hcdiag v0.5.1 github.com/hashicorp/hcl v1.0.0 github.com/hashicorp/hcl/v2 v2.14.1 - github.com/hashicorp/hcp-scada-provider v0.2.3 - github.com/hashicorp/hcp-sdk-go v0.61.0 + github.com/hashicorp/hcp-scada-provider v0.2.4 + github.com/hashicorp/hcp-sdk-go v0.80.0 github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038 github.com/hashicorp/memberlist v0.5.0 github.com/hashicorp/raft v1.5.0 @@ -75,7 +80,7 @@ require ( github.com/hashicorp/raft-wal v0.4.1 github.com/hashicorp/serf v0.10.1 github.com/hashicorp/vault-plugin-auth-alicloud v0.14.0 - github.com/hashicorp/vault/api v1.8.3 + github.com/hashicorp/vault/api v1.12.2 github.com/hashicorp/vault/api/auth/gcp v0.3.0 github.com/hashicorp/vault/sdk v0.7.0 github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 @@ -91,7 +96,6 @@ require ( github.com/mitchellh/pointerstructure v1.2.1 github.com/mitchellh/reflectwalk v1.0.2 github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce - github.com/oklog/ulid v1.3.1 github.com/oklog/ulid/v2 v2.1.0 github.com/olekukonko/tablewriter v0.0.4 github.com/patrickmn/go-cache v2.1.0+incompatible @@ -100,27 +104,26 @@ require ( github.com/rboyer/safeio v0.2.3 github.com/ryanuber/columnize v2.1.2+incompatible github.com/shirou/gopsutil/v3 v3.22.9 - github.com/stretchr/testify v1.8.3 + github.com/stretchr/testify v1.8.4 github.com/xeipuuv/gojsonschema v1.2.0 github.com/zclconf/go-cty v1.11.1 go.etcd.io/bbolt v1.3.7 - go.opentelemetry.io/otel v1.16.0 - go.opentelemetry.io/otel/metric v1.16.0 - go.opentelemetry.io/otel/sdk v1.16.0 + go.opentelemetry.io/otel v1.17.0 + go.opentelemetry.io/otel/metric v1.17.0 + go.opentelemetry.io/otel/sdk v1.17.0 go.opentelemetry.io/otel/sdk/metric v0.39.0 - go.opentelemetry.io/proto/otlp v0.19.0 + go.opentelemetry.io/proto/otlp v1.0.0 go.uber.org/goleak v1.1.10 - golang.org/x/crypto v0.14.0 + golang.org/x/crypto v0.22.0 golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 - golang.org/x/net v0.17.0 - golang.org/x/oauth2 v0.7.0 + golang.org/x/net v0.24.0 + golang.org/x/oauth2 v0.15.0 golang.org/x/sync v0.3.0 - golang.org/x/sys v0.13.0 + golang.org/x/sys v0.20.0 golang.org/x/time v0.3.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e - google.golang.org/grpc v1.56.3 - google.golang.org/protobuf v1.30.0 - gopkg.in/square/go-jose.v2 v2.5.1 + google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 + google.golang.org/grpc v1.58.3 + google.golang.org/protobuf v1.33.0 gotest.tools/v3 v3.4.0 k8s.io/api v0.26.2 k8s.io/apimachinery v0.26.2 @@ -128,9 +131,9 @@ require ( ) require ( - cloud.google.com/go/compute v1.19.1 // indirect + cloud.google.com/go/compute v1.21.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.13.0 // indirect + cloud.google.com/go/iam v1.1.1 // indirect github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.28 // indirect @@ -149,7 +152,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect - github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/benbjohnson/immutable v0.4.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect @@ -169,43 +172,44 @@ require ( github.com/digitalocean/godo v1.10.0 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.10.1 // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-openapi/analysis v0.21.4 // indirect - github.com/go-openapi/errors v0.20.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.20.0 // indirect - github.com/go-openapi/loads v0.21.2 // indirect - github.com/go-openapi/spec v0.20.8 // indirect - github.com/go-openapi/swag v0.22.3 // indirect - github.com/go-openapi/validate v0.22.1 // indirect + github.com/go-openapi/analysis v0.21.5 // indirect + github.com/go-openapi/errors v0.21.0 // indirect + github.com/go-openapi/jsonpointer v0.20.1 // indirect + github.com/go-openapi/jsonreference v0.20.3 // indirect + github.com/go-openapi/loads v0.21.3 // indirect + github.com/go-openapi/spec v0.20.12 // indirect + github.com/go-openapi/swag v0.22.5 // indirect + github.com/go-openapi/validate v0.22.4 // indirect github.com/go-ozzo/ozzo-validation v3.6.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.2.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.0.1 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-querystring v1.0.0 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/s2a-go v0.1.4 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.7.1 // indirect + github.com/googleapis/gax-go/v2 v2.11.0 // indirect github.com/gophercloud/gophercloud v0.3.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-msgpack/v2 v2.0.0 // indirect - github.com/hashicorp/go-plugin v1.4.5 // indirect - github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.0 // indirect github.com/hashicorp/mdns v1.0.4 // indirect github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0 // indirect github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 // indirect github.com/huandu/xstrings v1.3.2 // indirect + github.com/jhump/protoreflect v1.11.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f // indirect @@ -214,7 +218,7 @@ require ( github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect @@ -225,15 +229,14 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 // indirect - github.com/oklog/run v1.0.0 // indirect + github.com/oklog/ulid v1.3.1 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c // indirect github.com/pierrec/lz4 v2.6.1+incompatible // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/posener/complete v1.2.3 // indirect github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect - github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 // indirect @@ -256,29 +259,28 @@ require ( github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect - go.mongodb.org/mongo-driver v1.11.0 // indirect + go.mongodb.org/mongo-driver v1.13.1 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel/trace v1.16.0 // indirect - go.uber.org/atomic v1.9.0 // indirect + go.opentelemetry.io/otel/trace v1.17.0 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/term v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect - google.golang.org/api v0.114.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e // indirect + google.golang.org/api v0.126.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/resty.v1 v1.12.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/klog/v2 v2.90.1 // indirect + k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect - k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 7ba17c40bc50..89ac14fdd68e 100644 --- a/go.sum +++ b/go.sum @@ -25,22 +25,20 @@ cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aD cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= -cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= +cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y= +cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -51,34 +49,21 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-sdk-for-go v44.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest v0.11.0/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= github.com/Azure/go-autorest/autorest v0.11.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwGGyuimVhWsHOEM= github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= -github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ= github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.0/go.mod h1:QRTvSZQpxqm8mSErhnbI+tANIBAKP7B+UIE2z4ypUO0= github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk= github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.0/go.mod h1:JljT387FplPzBA31vUcvsetLKF3pec5bdAxjVU4kI2s= github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 h1:0W/yGmFdTIT77fvdlGZ0LMISoLHFJ7Tx4U0yeB+uFs4= github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= -github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= @@ -86,11 +71,8 @@ github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+X github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= github.com/Azure/go-autorest/autorest/validation v0.3.0 h1:3I9AAI63HfcLtphd9g39ruUwRI+Ca+z/f36KHPFRUss= github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -109,14 +91,9 @@ github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmy github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.0.1 h1:iLrQrdwjDd52kHDA5op2UBJFjmOb9g+7scBan4RN8F0= github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14= github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= @@ -141,13 +118,11 @@ github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go v1.25.41/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.44.289 h1:5CVEjiHFvdiVlKPBzv0rjG4zH/21W/onT18R5AH/qx0= -github.com/aws/aws-sdk-go v1.44.289/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= +github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/benbjohnson/immutable v0.4.0 h1:CTqXbEerYso8YzVPxmWxh2gnoRQbbB9X1quUC8+vGZA= github.com/benbjohnson/immutable v0.4.0/go.mod h1:iAr8OjJGLnLmVUr9MZ/rz4PWUy6Ouc2JLYuMArmvAJM= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -186,15 +161,13 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/coredns/coredns v1.10.1 h1:6OyL7tcvYxeNHONj5iQlVM2GXBzAOq57L3/LUKP1DbA= -github.com/coredns/coredns v1.10.1/go.mod h1:oGgoY6cRrdJzKgNrsT30Hztu7/MutSHCYwqGDWngXCc= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.27+incompatible h1:QIudLb9KeBsE5zyYxd1mjzRSkzLg9Wf9QlRwFgd6oTA= github.com/coreos/etcd v3.3.27+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-oidc/v3 v3.9.0 h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo= +github.com/coreos/go-oidc/v3 v3.9.0/go.mod h1:rTKz2PYwftcrtoCzV5g5kvfJoWcm0Mk8AF8y1iAQro4= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= @@ -216,10 +189,8 @@ github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661 h1:lrWnAyy/F72 github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/digitalocean/godo v1.7.5/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= github.com/digitalocean/godo v1.10.0 h1:uW1/FcvZE/hoixnJcnlmIUvTVNdZCLjRLzmDtRi1xXY= github.com/digitalocean/godo v1.10.0/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= -github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= @@ -227,11 +198,8 @@ github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -242,87 +210,69 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= -github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e h1:g8euodkL4GdSpVAjfzhssb07KgVmOUqyF4QOmwFumTs= github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e/go.mod h1:/NGEcKqwNq3HAS2vCqHfsPx9sJZbkiNQ6dGx9gTE/NA= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.1 h1:kt9FtLiooDc0vbwTLhdg3dyNX1K9Qwa1EK9LcD4jVUQ= -github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs= -github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/fullstorydev/grpchan v1.1.1 h1:heQqIJlAv5Cnks9a70GRL2EJke6QQoUB25VGR6TZQas= +github.com/fullstorydev/grpchan v1.1.1/go.mod h1:f4HpiV8V6htfY/K44GWV1ESQzHBTq7DinhzqQ95lpgc= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= +github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= -github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= -github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= -github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.3 h1:rz6kiC84sqNQoqrtulzaL/VERgkoCyB6WdEkc2ujzUc= -github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= -github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= -github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= -github.com/go-openapi/runtime v0.25.0 h1:7yQTCdRbWhX8vnIjdzU8S00tBYf7Sg71EBeorlPHvhc= -github.com/go-openapi/runtime v0.25.0/go.mod h1:Ux6fikcHXyyob6LNWxtE96hWwjBPYF0DXgVFuMTneOs= -github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/spec v0.20.8 h1:ubHmXNY3FCIOinT8RNrrPfGc9t7I1qhPtdOGoG2AxRU= -github.com/go-openapi/spec v0.20.8/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= -github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.3 h1:xwhj5X6CjXEZZHMWy1zKJxvW9AfHC9pkyUjLvHtKG7o= -github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= -github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= -github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= +github.com/go-openapi/analysis v0.21.5 h1:3tHfEBh6Ia8eKc4M7khOGjPOAlWKJ10d877Cr9teujI= +github.com/go-openapi/analysis v0.21.5/go.mod h1:25YcZosX9Lwz2wBsrFrrsL8bmjjXdlyP6zsr2AMy29M= +github.com/go-openapi/errors v0.21.0 h1:FhChC/duCnfoLj1gZ0BgaBmzhJC2SL/sJr8a2vAobSY= +github.com/go-openapi/errors v0.21.0/go.mod h1:jxNTMUxRCKj65yb/okJGEtahVd7uvWnuWfj53bse4ho= +github.com/go-openapi/jsonpointer v0.20.1 h1:MkK4VEIEZMj4wT9PmjaUmGflVBr9nvud4Q4UVFbDoBE= +github.com/go-openapi/jsonpointer v0.20.1/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= +github.com/go-openapi/jsonreference v0.20.3 h1:EjGcjTW8pD1mRis6+w/gmoBdqv5+RbE9B85D1NgDOVQ= +github.com/go-openapi/jsonreference v0.20.3/go.mod h1:FviDZ46i9ivh810gqzFLl5NttD5q3tSlMLqLr6okedM= +github.com/go-openapi/loads v0.21.3 h1:8sSH2FIm/SnbDUGv572md4YqVMFne/a9Eubvcd3anew= +github.com/go-openapi/loads v0.21.3/go.mod h1:Y3aMR24iHbKHppOj91nQ/SHc0cuPbAr4ndY4a02xydc= +github.com/go-openapi/runtime v0.26.2 h1:elWyB9MacRzvIVgAZCBJmqTi7hBzU0hlKD4IvfX0Zl0= +github.com/go-openapi/runtime v0.26.2/go.mod h1:O034jyRZ557uJKzngbMDJXkcKJVzXJiymdSfgejrcRw= +github.com/go-openapi/spec v0.20.12 h1:cgSLbrsmziAP2iais+Vz7kSazwZ8rsUZd6TUzdDgkVI= +github.com/go-openapi/spec v0.20.12/go.mod h1:iSCgnBcwbMW9SfzJb8iYynXvcY6C/QFrI7otzF7xGM4= +github.com/go-openapi/strfmt v0.21.10 h1:JIsly3KXZB/Qf4UzvzJpg4OELH/0ASDQsyk//TTBDDk= +github.com/go-openapi/strfmt v0.21.10/go.mod h1:vNDMwbilnl7xKiO/Ve/8H8Bb2JIInBnH+lqiw6QWgis= +github.com/go-openapi/swag v0.22.5 h1:fVS63IE3M0lsuWRzuom3RLwUMVI2peDH01s6M70ugys= +github.com/go-openapi/swag v0.22.5/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= +github.com/go-openapi/validate v0.22.4 h1:5v3jmMyIPKTR8Lv9syBAIRxG6lY0RqeBPB1LKEijzk8= +github.com/go-openapi/validate v0.22.4/go.mod h1:qm6O8ZIcPVdSY5219468Jv7kBdGvkiZLPOmqnqTUZ2A= github.com/go-ozzo/ozzo-validation v3.6.0+incompatible h1:msy24VGS42fKO9K1vLz82/GeYW1cILu7Nuuj1N3BBkE= github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -330,43 +280,18 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -382,7 +307,6 @@ github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -400,8 +324,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -426,11 +350,9 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -453,36 +375,34 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2 h1:AtvtonGEH/fZK0XPNNBdB6swgy7Iudfx88wzyIpwqJ8= github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2/go.mod h1:DavVbd41y+b7ukKDmlnPR4nGYmkWXR6vHUkjQNiHPBs= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A= -github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4= +github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= github.com/gophercloud/gophercloud v0.3.0 h1:6sjpKIpVwRIIwmcEGp+WwNovNsem+c+2vm6oxshRpL8= github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/hashi-derek/grpc-proxy v0.0.0-20231207191910-191266484d75 h1:V5Uqf7VoWMd6UhNf/5EMA8LMPUm95GYvk2YF5SzT24o= +github.com/hashi-derek/grpc-proxy v0.0.0-20231207191910-191266484d75/go.mod h1:5eEnHfK72jOkp4gC1dI/Q/E9MFNOM/ewE/vql5ijV3g= github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706 h1:1ZEjnveDe20yFa6lSkfdQZm5BR/b271n0MsB5R2L3us= github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706/go.mod h1:1Cs8FlmD1BfSQXJGcFLSV5FuIx1AbJP+EJGdxosoS2g= github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69 h1:wzWurXrxfSyG1PHskIZlfuXlTSCj1Tsyatp9DtaasuY= @@ -500,18 +420,21 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-connlimit v0.3.0 h1:oAojHGjFxUTTTA8c5XXnDqWJ2HLuWbDiBPTpWvNzvqM= github.com/hashicorp/go-connlimit v0.3.0/go.mod h1:OUj9FGL1tPIhl/2RCfzYHrIiWj+VVPGNyVPnUX8AqS0= -github.com/hashicorp/go-discover v0.0.0-20220714221025-1c234a67149a h1:xeDSq/xo0CfnSZnPUkNH/00Qy8Q8ySJW0Ij2u/pH680= -github.com/hashicorp/go-discover v0.0.0-20220714221025-1c234a67149a/go.mod h1:1xfdKvc3pe5WKxfUUHHOGaKMk7NLGhHY1jkyhKo6098= +github.com/hashicorp/go-discover v0.0.0-20230724184603-e89ebd1b2f65 h1:+ZwaKkFuVWS7FZoiltT+7XW/MEFckY9Wxe+xIEErLcM= +github.com/hashicorp/go-discover v0.0.0-20230724184603-e89ebd1b2f65/go.mod h1:RH2Jr1/cCsZ1nRLmAOC65hp/gRehf55SsUIYV2+NAxI= github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo= +github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw= github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0/go.mod h1:xvb32K2keAc+R8DSFG2IwDcydK9DBQE+fGA5fsw6hSk= github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c= github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= @@ -525,20 +448,17 @@ github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= -github.com/hashicorp/go-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo= -github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= github.com/hashicorp/go-raftchunking v0.7.0 h1:APNMnCXmTOhumkFv/GpJIbq7HteWF7EnGZ3875lRN0Y= github.com/hashicorp/go-raftchunking v0.7.0/go.mod h1:Dg/eBOaJzE0jYKNwNLs5IA5j0OSmL5HoCUiMy3mDmrI= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo= -github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 h1:W9WN8p6moV1fjKLkeqEgkAMu5rauy9QeYDAmIaPuuiA= github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6/go.mod h1:MpCPSPGLDILGb4JMm94/mMi3YysIqsXzGCzkEZjcjXg= github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 h1:cCRo8gK7oq6A2L6LICkUZ+/a5rLiRXFMf1Qd4xSwxTc= github.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ= @@ -565,20 +485,21 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.0 h1:Lf+9eD8m5pncvHAOCQj49GSN6aQI8XGfI5OpXNkoWaA= +github.com/hashicorp/golang-lru/v2 v2.0.0/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcdiag v0.5.1 h1:KZcx9xzRfEOQ2OMbwPxVvHyXwLLRqYpSHxCEOtHfQ6w= github.com/hashicorp/hcdiag v0.5.1/go.mod h1:RMC2KkffN9uJ+5mFSaL67ZFVj4CDeetPF2d/53XpwXo= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl/v2 v2.14.1 h1:x0BpjfZ+CYdbiz+8yZTQ+gdLO7IXvOut7Da+XJayx34= github.com/hashicorp/hcl/v2 v2.14.1/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0= -github.com/hashicorp/hcp-scada-provider v0.2.3 h1:AarYR+/Pcv+cMvPdAlb92uOBmZfEH6ny4+DT+4NY2VQ= -github.com/hashicorp/hcp-scada-provider v0.2.3/go.mod h1:ZFTgGwkzNv99PLQjTsulzaCplCzOTBh0IUQsPKzrQFo= -github.com/hashicorp/hcp-sdk-go v0.61.0 h1:x4hJ8SlLI5WCE8Uzcu4q5jfdOEz/hFxfUkhAdoFdzSg= -github.com/hashicorp/hcp-sdk-go v0.61.0/go.mod h1:xP7wmWAmdMxs/7+ovH3jZn+MCDhHRj50Rn+m7JIY3Ck= +github.com/hashicorp/hcp-scada-provider v0.2.4 h1:XvctVEd4VqWVlqN1VA4vIhJANstZrc4gd2oCfrFLWZc= +github.com/hashicorp/hcp-scada-provider v0.2.4/go.mod h1:ZFTgGwkzNv99PLQjTsulzaCplCzOTBh0IUQsPKzrQFo= +github.com/hashicorp/hcp-sdk-go v0.80.0 h1:oKGx7+X0llBN5NEpkWg0Qe3x9DIAH6cc3MrxZptDB7Y= +github.com/hashicorp/hcp-sdk-go v0.80.0/go.mod h1:vQ4fzdL1AmhIAbCw+4zmFe5Hbpajj3NvRWkJoVuxmAk= github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038 h1:n9J0rwVWXDpNd5iZnwY7w4WZyq53/rROeI7OVvLW8Ok= github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/mdns v1.0.4 h1:sY0CMhFmjIPDMlTB+HfymFHCaYLhgifZ0QhjaYKD/UQ= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= @@ -595,6 +516,7 @@ github.com/hashicorp/raft-autopilot v0.1.6/go.mod h1:Af4jZBwaNOI+tXfIqIdbcAnh/Uy github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= github.com/hashicorp/raft-boltdb v0.0.0-20210409134258-03c10cc3d4ea/go.mod h1:qRd6nFJYYS6Iqnc/8HcUmko2/2Gw8qTFEmxDLii6W5I= github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0 h1:CO8dBMLH6dvE1jTn/30ZZw3iuPsNfajshWoJTnVc5cc= +github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0= github.com/hashicorp/raft-boltdb/v2 v2.2.2 h1:rlkPtOllgIcKLxVT4nutqlTH2NRFn+tO1wwZk/4Dxqw= github.com/hashicorp/raft-boltdb/v2 v2.2.2/go.mod h1:N8YgaZgNJLpZC+h+by7vDu5rzsRgONThTEeUS3zWbfY= github.com/hashicorp/raft-wal v0.4.1 h1:aU8XZ6x8R9BAIB/83Z1dTDtXvDVmv9YVYeXxd/1QBSA= @@ -604,8 +526,8 @@ github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfE github.com/hashicorp/vault-plugin-auth-alicloud v0.14.0 h1:O6tNk0s/arubLUbLeCyaRs5xGo9VwmbQazISY/BfPK4= github.com/hashicorp/vault-plugin-auth-alicloud v0.14.0/go.mod h1:We3fJplmALwK1VpjwrLuXr/4QCQHYMdnXLHmLUU6Ntg= github.com/hashicorp/vault/api v1.8.0/go.mod h1:uJrw6D3y9Rv7hhmS17JQC50jbPDAZdjZoTtrCCxxs7E= -github.com/hashicorp/vault/api v1.8.3 h1:cHQOLcMhBR+aVI0HzhPxO62w2+gJhIrKguQNONPzu6o= -github.com/hashicorp/vault/api v1.8.3/go.mod h1:4g/9lj9lmuJQMtT6CmVMHC5FW1yENaVv+Nv4ZfG8fAg= +github.com/hashicorp/vault/api v1.12.2 h1:7YkCTE5Ni90TcmYHDBExdt4WGJxhpzaHqR6uGbQb/rE= +github.com/hashicorp/vault/api v1.12.2/go.mod h1:LSGf1NGT1BnvFFnKVtnvcaLBM2Lz+gJdpL6HUYed8KE= github.com/hashicorp/vault/api/auth/gcp v0.3.0 h1:taum+3pCmOXnNgEKHlQbmgXmKw5daWHk7YJrLPP/w8g= github.com/hashicorp/vault/api/auth/gcp v0.3.0/go.mod h1:gnNBFOASYUaFunedTHOzdir7vKcHL3skWBUzEn263bo= github.com/hashicorp/vault/sdk v0.6.0/go.mod h1:+DRpzoXIdMvKc88R4qxr+edwy/RvH5QK8itmxLiDHLc= @@ -616,13 +538,11 @@ github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35n github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I= github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= @@ -633,66 +553,58 @@ github.com/jackc/pgx v3.3.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGk github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da h1:FjHUJJ7oBW4G/9j1KzlHaXL09LyMVM9rupS39lncbXk= github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= +github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= +github.com/jhump/protoreflect v1.11.0 h1:bvACHUD1Ua/3VxY4aAMpItKMhhwbimlKFJKsLsVgDjU= +github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f h1:ENpDacvnr8faw5ugQmEF1QYk+f/Y9lXFvuYmRxykago= github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f/go.mod h1:KDSfL7qe5ZfQqvlDMkVjCztbmcpp/c8M77vhQP8ZPvk= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= -github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/linode/linodego v0.7.1/go.mod h1:ga11n3ivecUrPCHN0rANxKmfWBJVkOXfLMZinAbj2sY= github.com/linode/linodego v0.10.0 h1:AMdb82HVgY8o3mjBXJcUv9B+fnJjfDMn2rNRGbX+jvM= github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c h1:VtwQ41oftZwlMnOEbMWQtSEUgU64U4s+GHk7hZK+jtY= github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -707,8 +619,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= @@ -716,7 +628,6 @@ github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= @@ -747,7 +658,6 @@ github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4 github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= @@ -764,17 +674,13 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce h1:TqjP/BTDrwN7zP9xyXVuLsMBXYMt6LLYi55PlrIcq8U= github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:ifHPsLndGGzvgzcaXUvzmt6LxKT4pJ+uzEhtnMt+f7A= github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 h1:BQ1HW7hr4IVovMwWg0E0PYcyW8CzqDcVmaew9cujU4s= github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -783,14 +689,10 @@ github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNs github.com/olekukonko/tablewriter v0.0.0-20180130162743-b8a9be070da4/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys= +github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= @@ -803,8 +705,6 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -821,8 +721,6 @@ github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSg github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c h1:NRoLoZvkBTKvR5gQLgA3e0hqjkY9u1wm+iOL45VN/qI= github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -834,8 +732,8 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1: github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -859,11 +757,10 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/zerolog v1.4.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -880,16 +777,14 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil/v3 v3.22.9 h1:yibtJhIVEMcdw+tCTbOPiF1VcsuDeTE4utJ8Dm4c5eA= github.com/shirou/gopsutil/v3 v3.22.9/go.mod h1:bBYl1kjgEJpWpxeHmLI+dVHWtyAwfcmSBLDsp2TNT8A= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -901,15 +796,12 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -932,12 +824,10 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tencentcloud/tencentcloud-sdk-go v1.0.162 h1:8fDzz4GuVg4skjY2B0nMN7h6uN61EDVkuLyI2+qGHhI= github.com/tencentcloud/tencentcloud-sdk-go v1.0.162/go.mod h1:asUz5BPXxgoPGaRgZaVm1iGcUAuHyYUo1nXqKa83cvI= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= @@ -955,10 +845,8 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT github.com/vmware/govmomi v0.18.0 h1:f7QxSmP7meCtoAmiKZogvVbLInT+CZx6Px6K5rYsJZo= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -983,11 +871,8 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= -go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= -go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= +go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= +go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -997,19 +882,19 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= -go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= -go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= -go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= -go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= -go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= +go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= +go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= +go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= +go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= +go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= +go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ= go.opentelemetry.io/otel/sdk/metric v0.39.0 h1:Kun8i1eYf48kHH83RucG93ffz0zGV1sh46FAScOTuDI= go.opentelemetry.io/otel/sdk/metric v0.39.0/go.mod h1:piDIRgjcK7u0HCL5pCA4e74qpK/jk3NiUoAHATVAmiI= -go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= -go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= +go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= +go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -1018,29 +903,26 @@ go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1080,15 +962,13 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1105,7 +985,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1127,16 +1006,17 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1152,14 +1032,12 @@ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1168,14 +1046,12 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1183,15 +1059,12 @@ golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1200,7 +1073,6 @@ golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1232,7 +1104,7 @@ golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1252,15 +1124,19 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1270,9 +1146,11 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1281,21 +1159,15 @@ golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -1344,6 +1216,7 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1378,16 +1251,17 @@ google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00 google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE= -google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= +google.golang.org/api v0.126.0 h1:q4GJq+cAdMAC7XP7njvQ4tvohGLiSlytuL4BQxbIZ+o= +google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1430,6 +1304,7 @@ google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= @@ -1446,13 +1321,12 @@ google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEc google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= -google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e h1:AZX1ra8YbFMSb7+1pI8S9v4rrgRR7jU1FmuFSSjTVcQ= -google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e h1:NumxXLPfHSndr3wBBdeKiVHjGVFzi9RX2HwwQke94iY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= +google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1481,9 +1355,9 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= -google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1499,18 +1373,15 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= @@ -1520,9 +1391,7 @@ gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHN gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc= gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1534,7 +1403,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= @@ -1548,37 +1416,25 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= k8s.io/api v0.26.2 h1:dM3cinp3PGB6asOySalOZxEG4CZ0IAdJsrYZXE/ovGQ= k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU= -k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ= k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= -k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= k8s.io/client-go v0.26.2 h1:s1WkVujHX3kTp4Zn4yGNFK+dlDXy1bAAkIl+cFAiuYI= k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU= -k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= -k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= -sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/grafana/README.md b/grafana/README.md deleted file mode 100644 index 2e8b2b588b75..000000000000 --- a/grafana/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Grafana Publishing - -The page for publishing this dashboard is https://grafana.com/grafana/dashboards/13396 - -## How to edit and Publish - - Start grafana locally (consul-docker-test/mesh-gateways-l7 will provide you two Consul DCs, grafana, and prometheus)_ - - Import the dashboard json into a new dashboard - - Make changes - - Click "share" and export for external publishing - - Login to Grafana via the team account (message a manager) - - Publish as a new version, including change notes. - -### Grafana dashboard for consul-k8s (control plane) - -A grafana dashboard for monitoring consul-k8s (control plane) can also be found in this directory: `consul-k8s-control-plane-monitoring.json`. This dashboard has not been published to https://grafana.com. diff --git a/grafana/consul-k8s-control-plane-monitoring.json b/grafana/consul-k8s-control-plane-monitoring.json index 2298a77b5362..1b6c33bad62d 100644 --- a/grafana/consul-k8s-control-plane-monitoring.json +++ b/grafana/consul-k8s-control-plane-monitoring.json @@ -1650,6 +1650,73 @@ "title": "Memory Limit (Consul Servers)", "type": "gauge" }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "Gives the filesystem storage used by consul servers", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-BlYlRd" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 9, + "x": 15, + "y": 36 + }, + "id": 100, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.5.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(container_fs_usage_bytes{consul_agent_type=\"server\"}) by (consul_agent_type)", + "instant": true, + "legendFormat": "{{consul_agent_type}}", + "range": false, + "refId": "A" + } + ], + "title": "Disk usage (Consul servers)", + "type": "gauge" + }, { "datasource": { "type": "prometheus", @@ -1715,6 +1782,113 @@ "x": 0, "y": 36 }, + "id": 101, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "expr": "sum(rate(container_fs_writes_bytes_total{pod=~\"consul-server-.*\", container=\"consul\"}[5m])) by (pod, device)", + "hide": false, + "legendFormat": "writes, {pod=\"{{pod}}\"}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "expr": "sum(rate(container_fs_reads_bytes_total{pod=~\"consul-server-.*\", container=\"consul\"}[5m])) by (pod, device)", + "hide": false, + "legendFormat": "reads, {pod=\"{{pod}}\"}", + "range": true, + "refId": "B" + } + ], + "title": "Disk Read/Write total per 5 minutes (Consul servers)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 15, + "x": 0, + "y": 44 + }, "id": 48, "options": { "legend": { diff --git a/grafana/consuldataplanedashboard.json b/grafana/consuldataplanedashboard.json new file mode 100644 index 000000000000..e8b6278bc4b3 --- /dev/null +++ b/grafana/consuldataplanedashboard.json @@ -0,0 +1,1453 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Envoy proxy monitoring Dashboard with cluster and service level templates. ", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 11021, + "graphTooltip": 0, + "id": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 3, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 1 + }, + { + "color": "#299c46", + "value": 2 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 9, + "maxDataPoints": 100, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(envoy_server_live{app=~\"$service\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Live servers", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 70, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!=\"5\", envoy_response_code_class!=\"4\",consul_destination_service=~\"$service\"}[10m])) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_service=~\"$service\"}[10m])) ", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total Request Success Rate", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [] + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 68, + "options": { + "displayLabels": [ + "name", + "value" + ], + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "values": [ + "value" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(increase(envoy_cluster_upstream_rq_xx{envoy_response_code_class=~\"4|5\", consul_destination_service=~\"$service\"}[10m])) by (local_cluster)", + "interval": "", + "legendFormat": "{{consul_destination_service}}", + "refId": "A" + } + ], + "title": "Total Failed Requests", + "type": "piechart" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 0, + "y": 7 + }, + "id": 64, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "value_and_name", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(envoy_http_downstream_rq_total{service=~\"$service\",envoy_http_conn_manager_prefix=\"public_listener\"}[5m])) by (service)", + "hide": false, + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Requests / sec", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 5, + "y": 7 + }, + "id": 19, + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "(sum(envoy_cluster_membership_healthy{app=~\"$service\",envoy_cluster_name=~\"$cluster\"}) - sum(envoy_cluster_membership_total{app=~\"$service\",envoy_cluster_name=~\"$cluster\"}))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Unhealthy Clusters", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 32 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 8, + "y": 7 + }, + "id": 58, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "titleSize": 12 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by (app) (envoy_cluster_upstream_cx_active{app=~\"$service\",envoy_cluster_name!~\"consul-dataplane|prometheus.*|local_app|original-.*\"})", + "instant": true, + "interval": "", + "legendFormat": "{{envoy_cluster_name}}", + "range": false, + "refId": "A" + } + ], + "title": "Connections ( $service)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 2, + "x": 16, + "y": 7 + }, + "id": 13, + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "SUM(envoy_server_memory_heap_size{app=~\"$service\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Heap Size", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 18, + "y": 7 + }, + "id": 11, + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "SUM(envoy_server_memory_allocated{app=~\"$service\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Allocated Memory", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 21, + "y": 7 + }, + "id": 12, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "avg(envoy_server_uptime{app=~\"$service\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Avg uptime per node", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "text": "NOT WELL" + }, + "1": { + "text": "OK" + } + }, + "type": "value" + }, + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0 + }, + { + "color": "#299c46", + "value": 1 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 5, + "y": 10 + }, + "id": 20, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "(sum(envoy_cluster_membership_total{app=~\"$service\",envoy_cluster_name=~\"$cluster\"})-sum(envoy_cluster_membership_healthy{app=~\"$service\",envoy_cluster_name=~\"$cluster\"})) == bool 0", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Cluster State", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 0.00001 + }, + { + "color": "red", + "value": 0.00002 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 20, + "x": 0, + "y": 13 + }, + "id": 18, + "options": { + "legend": { + "calcs": [ + "last" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Last", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "rate(container_cpu_cfs_throttled_seconds_total{namespace=~\"$namespace\"}[5m])", + "interval": "", + "legendFormat": "{{pod}}", + "range": true, + "refId": "A" + } + ], + "title": "CPU Throttled Seconds by Namespace", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 2, + "x": 20, + "y": 13 + }, + "id": 49, + "options": { + "displayMode": "gradient", + "maxVizHeight": 300, + "minVizHeight": 10, + "minVizWidth": 0, + "namePlacement": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "100 * max (container_memory_working_set_bytes{namespace=~\"$namespace\"} / on(container, pod) label_replace(kube_pod_container_resource_limits{resource=\"memory\"}, \"pod\", \"$1\", \"exported_pod\", \"(.+)\")) by (pod)", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Mem Usage % by pod limits", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 60 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 2, + "x": 22, + "y": 13 + }, + "id": 28, + "options": { + "displayMode": "gradient", + "maxVizHeight": 300, + "minVizHeight": 10, + "minVizWidth": 0, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "100 * max(\n container_memory_working_set_bytes{namespace=~\"$namespace\"} / \n on(container, pod) label_replace(kube_pod_container_resource_limits{resource=\"memory\"}, \"pod\", \"$1\", \"exported_pod\", \"(.+)\")\n) by (pod)\n\n", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "CPU Usage % by pod limits", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 3, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 12, + "x": 0, + "y": 22 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.4.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(envoy_cluster_upstream_cx_active{app=~\"$service\",envoy_cluster_name=~\"$cluster\"}) by (app, envoy_cluster_name)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{envoy_cluster_name}} ({{service}})", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "exemplar": true, + "expr": "sum(envoy_cluster_upstream_cx_active{app=~\"$service\"}) by (app)", + "hide": true, + "interval": "", + "legendFormat": "", + "refId": "B" + } + ], + "title": "Total Active Upstream Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 7, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 12, + "x": 12, + "y": 22 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.4.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(envoy_http_downstream_cx_active{app=~\"$service\"}) by (app)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{service}}", + "refId": "A" + } + ], + "title": "Total Active Downstream Connections", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "PBFA97CFB590B2093" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "definition": "label_values(envoy_server_live, app)", + "hide": 0, + "includeAll": true, + "label": "", + "multi": true, + "name": "service", + "options": [], + "query": { + "query": "label_values(envoy_server_live, app)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "definition": "label_values(envoy_cluster_upstream_cx_total{service=~\"$service\"}, envoy_cluster_name)", + "hide": 0, + "includeAll": true, + "label": "Cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(envoy_cluster_upstream_cx_total{service=~\"$service\"}, envoy_cluster_name)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "definition": "label_values(container_memory_working_set_bytes, namespace)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(container_memory_working_set_bytes, namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Consul DataPlane Dashboard", + "uid": "hashicupso", + "version": 4, + "weekStart": "" +} \ No newline at end of file diff --git a/grafana/consulservicedashboard.json b/grafana/consulservicedashboard.json new file mode 100644 index 000000000000..785b17ed26b4 --- /dev/null +++ b/grafana/consulservicedashboard.json @@ -0,0 +1,1513 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Envoy proxy monitoring Dashboard with cluster and service level templates. ", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 11021, + "graphTooltip": 0, + "id": 2, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 103, + "panels": [], + "title": "Overall Service Mesh Performance", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "#EAB839", + "value": 5 + }, + { + "color": "green", + "value": 6 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 1 + }, + "id": 65, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(envoy_server_live{app!=\"traffic-generator\"})", + "instant": false, + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Total Running Services", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 1 + }, + "id": 89, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!=\"5\", envoy_response_code_class!=\"4\",consul_destination_service=~\"$service\"}[10m])) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_service=~\"$service\"}[10m])) ", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total Request Success Rate", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 1 + }, + "id": 93, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class=~\"4|5\", consul_destination_service=~\"$service\"}[10m])) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_service=~\"$service\"}[10m]))", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total Failed Request Rate", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 95, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": true, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_cluster_upstream_rq_time_sum{consul_destination_service=~\"$service\"}[10m])) / sum(rate(envoy_cluster_upstream_rq_total{consul_destination_service=~\"$service\"}[10m]))", + "hide": false, + "interval": "", + "legendFormat": "", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "1000 * (sum(rate(envoy_cluster_upstream_rq_time_sum{consul_destination_service=~\"$service\"}[10m])) / sum(rate(envoy_cluster_upstream_rq_total{consul_destination_service=~\"$service\"}[10m])))", + "hide": true, + "interval": "", + "legendFormat": "", + "refId": "B" + } + ], + "title": "Average Request Response Time In MiliSeconds", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 10 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 91, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(increase(envoy_cluster_upstream_rq_xx{envoy_response_code_class=~\"4|5\", consul_destination_service=~\"$service\"}[10m]))by(local_cluster)", + "interval": "", + "legendFormat": "{{consul_destination_service}}", + "refId": "A" + } + ], + "title": "Total Failed Requests", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 5 + }, + { + "color": "orange", + "value": 8 + }, + { + "color": "semi-dark-green", + "value": 10 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 31, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "vertical", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": {}, + "textMode": "value_and_name", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.50, sum by(le) (rate(envoy_cluster_upstream_rq_time_bucket{kubernetes_namespace=~\"$namespace\" , local_cluster=~\"$service\"}[5m])))\n", + "hide": false, + "interval": "", + "legendFormat": "p50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.75, sum by(le) (rate(envoy_cluster_upstream_rq_time_bucket{kubernetes_namespace=~\"$namespace\", local_cluster=~\"$service\"}[5m])))", + "hide": false, + "interval": "", + "legendFormat": "p75", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.90, sum by(le) (rate(envoy_cluster_upstream_rq_time_bucket{kubernetes_namespace=~\"$namespace\", local_cluster=~\"$service\"}[5m])))", + "hide": false, + "interval": "", + "legendFormat": "p90", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(.999, sum by(le) (rate(envoy_cluster_upstream_rq_time_bucket{kubernetes_namespace=~\"$namespace\", local_cluster=~\"$service\"}[5m])))", + "hide": false, + "interval": "", + "legendFormat": "p99.9", + "range": true, + "refId": "D" + } + ], + "title": "Dataplane Latency: $service ", + "transparent": true, + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 102, + "panels": [], + "title": "TCP Metrics: High Level", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 0, + "y": 18 + }, + "id": 99, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_rx_bytes_total{}[10m])) by (local_cluster)", + "interval": "", + "legendFormat": "", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_tx_bytes_total{}[10m])) by (local_cluster)", + "hide": false, + "interval": "", + "legendFormat": "", + "refId": "B" + } + ], + "title": "Total TCP Inbound and Outbound Bytes", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 8, + "y": 18 + }, + "id": 101, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_rx_bytes_buffered{}[10m])) by (local_cluster)", + "interval": "", + "legendFormat": "", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_tx_bytes_buffered{}[10m])) by (local_cluster)", + "hide": false, + "interval": "", + "legendFormat": "", + "refId": "B" + } + ], + "title": "Total TCP Inbound and Outbound Bytes Buffered", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 16, + "y": 18 + }, + "id": 81, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_total{}[10m])) by(local_cluster)", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total TCP Downstream Active Connections", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 28 + }, + "id": 77, + "panels": [], + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "refId": "A" + } + ], + "title": "Service Dashboard", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 29 + }, + "id": 71, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(envoy_cluster_upstream_cx_active{app=~\"$service\"}) by (app)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{service}}", + "range": true, + "refId": "A" + } + ], + "title": "Total Active Http Upstream Connections", + "transformations": [ + { + "id": "calculateField", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 29 + }, + "id": 75, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "exemplar": true, + "expr": "sum(envoy_http_downstream_cx_active{app=~\"$service\"}) by (app)", + "interval": "", + "legendFormat": "{{service}}", + "refId": "A" + } + ], + "title": "Total Active Http Downstream Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 41, + "options": { + "legend": { + "calcs": [ + "last", + "sum" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Last", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by(namespace,app,envoy_response_code_class) (rate(envoy_cluster_upstream_rq_xx[5m]))", + "interval": "", + "legendFormat": "{{namespace}} : {{app}}-{{envoy_response_code_class}}xx", + "range": true, + "refId": "A" + } + ], + "title": "Upstream Rq by Status Code", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 51, + "options": { + "legend": { + "calcs": [ + "last", + "sum" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Last", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "expr": "sum(rate(envoy_http_downstream_rq_xx{envoy_http_conn_manager_prefix=\"public_listener\"}[5m])) by (namespace, app,envoy_response_code_class)\n", + "legendFormat": "{{namespace}} : {{app}}-{{envoy_response_code_class}}xx", + "range": true, + "refId": "A" + } + ], + "title": "Downstream Rq by Status Code", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 47 + }, + "id": 61, + "options": { + "legend": { + "calcs": [ + "max", + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": false, + "expr": "rate(envoy_listener_downstream_cx_overload_reject{}[$__interval])", + "hide": false, + "instant": false, + "interval": "3m", + "legendFormat": "{{namespace}} : {{consul_source_service}}-{{envoy_listener_address}}-overload", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "expr": "rate(envoy_listener_downstream_global_cx_overflow{}[$__interval])", + "hide": false, + "interval": "3m", + "legendFormat": "{{namespace}} : {{consul_source_service}}-{{envoy_listener_address}}-overflow", + "range": true, + "refId": "B" + } + ], + "title": "Connections Rejected", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "PBFA97CFB590B2093" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "definition": "label_values(envoy_server_live, consul_source_service)", + "hide": 0, + "includeAll": true, + "label": "", + "multi": true, + "name": "service", + "options": [], + "query": { + "query": "label_values(envoy_server_live, consul_source_service)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "definition": "label_values(container_memory_working_set_bytes, namespace)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(container_memory_working_set_bytes, namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Consul Service Dashboard", + "uid": "hashicupsnm", + "version": 8, + "weekStart": "" +} \ No newline at end of file diff --git a/grafana/consulservicetoservicedashboard.json b/grafana/consulservicetoservicedashboard.json new file mode 100644 index 000000000000..fe452d8c564e --- /dev/null +++ b/grafana/consulservicetoservicedashboard.json @@ -0,0 +1,1921 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 3, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 34, + "panels": [], + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "refId": "A" + } + ], + "title": "Access Logs and Errors Monitoring", + "type": "row" + }, + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "description": "Total Count of log lines in the specified time range", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "rgb(31, 255, 7)", + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "green", + "value": 10 + }, + { + "color": "green", + "value": 50 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 1 + }, + "id": 9, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "editorMode": "code", + "expr": "sum(count_over_time(({container=\"consul-dataplane\",namespace=~\"$namespace\"})[$__interval]))", + "hide": false, + "queryType": "range", + "refId": "A" + } + ], + "title": "Total Logs", + "type": "stat" + }, + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "description": "Total count of logs containing the search filter term in the specified time range", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "rgb(222, 15, 43)", + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "red", + "value": 10 + }, + { + "color": "red", + "value": 50 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 8, + "y": 1 + }, + "id": 10, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "editorMode": "code", + "expr": "sum(count_over_time({container=\"consul-dataplane\", namespace=~\"$namespace\"} |~ `(?i)(?i)$searchable_pattern` [$__interval]))", + "hide": false, + "queryType": "range", + "refId": "A" + } + ], + "title": "Total Logs Containing \"$searchable_pattern\"", + "type": "stat" + }, + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "description": "Percentage of logs containing the search filter term in the specified time range", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "#299c46", + "text": "0" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 16, + "y": 1 + }, + "id": 14, + "maxDataPoints": 1, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "editorMode": "builder", + "expr": "(sum(count_over_time({container=\"consul-dataplane\", namespace=~\"$namespace\"} |~ `(?i)(?i)$searchable_pattern` [$__interval])) * 100) / sum(count_over_time({container=\"consul-dataplane\", namespace=~\"$namespace\"} [$__interval]))", + "hide": false, + "queryType": "range", + "refId": "A" + } + ], + "title": "Percentage of Logs Containing \"$searchable_pattern\"", + "type": "stat" + }, + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [] + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 0, + "y": 4 + }, + "id": 4, + "maxDataPoints": 1, + "options": { + "displayLabels": [ + "percent" + ], + "legend": { + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "editorMode": "code", + "expr": "sum by(response_code) (count_over_time({container=\"consul-dataplane\", namespace=\"$namespace\"} | json | response_code != `0` | __error__=`` [$__range]))", + "key": "Q-aac7d4c8-664f-43c0-8064-9f737ce3e78e-0", + "legendFormat": "{{response_code}}", + "queryType": "range", + "refId": "A" + } + ], + "title": "Total Response Code Distribution", + "type": "piechart" + }, + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 15, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "log": 2, + "type": "log" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 8, + "y": 4 + }, + "id": 16, + "maxDataPoints": 100, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "editorMode": "builder", + "expr": "sum by(app) (rate({container=\"consul-dataplane\", namespace=~\"$namespace\"} |~ `(?i)(?i)$searchable_pattern` [$__range]))", + "hide": false, + "legendFormat": "{{pod}}", + "queryType": "range", + "refId": "A" + } + ], + "title": "Rate of Logs Containing \"$searchable_pattern\" per Service", + "type": "timeseries" + }, + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 4 + }, + "id": 15, + "interval": "1m", + "maxDataPoints": 1, + "options": { + "displayLabels": [ + "value" + ], + "legend": { + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "editorMode": "builder", + "expr": "sum by(app) (count_over_time({container=\"consul-dataplane\", namespace=~\"$namespace\"} |~ `(?i)(?i)$searchable_pattern` [$__interval]))", + "legendFormat": "{{pod}}", + "queryType": "instant", + "refId": "A" + } + ], + "title": "Total Logs Containing \"$searchable_pattern\" by Service", + "type": "piechart" + }, + { + "collapsed": false, + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 26, + "panels": [], + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "refId": "A" + } + ], + "title": "TCP Metrics: Service Level", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 0, + "y": 11 + }, + "id": 38, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_rx_bytes_total{}[10m])) by (service, destination_service)", + "interval": "", + "legendFormat": "$source_service", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_tx_bytes_total{}[10m])) by (service, destination_service)", + "hide": false, + "interval": "", + "legendFormat": "$destination_service", + "refId": "B" + } + ], + "title": "TCP Inbound and Outbound Bytes: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 8, + "y": 11 + }, + "id": 40, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_rx_bytes_buffered{}[10m])) by (service, destination_service)", + "interval": "", + "legendFormat": "$source_service", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(rate(envoy_tcp_downstream_cx_tx_bytes_buffered{}[10m])) by (service, destination_service)", + "hide": false, + "interval": "", + "legendFormat": "$destination_service", + "range": true, + "refId": "B" + } + ], + "title": "TCP Inbound and Outbound Bytes Buffered: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 8, + "x": 16, + "y": 11 + }, + "id": 28, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(envoy_tcp_downstream_cx_total) by (service, destination_service)", + "hide": false, + "interval": "", + "legendFormat": "$source_service ", + "range": true, + "refId": "A" + } + ], + "title": "TCP Downstream Connections: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 41, + "panels": [], + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "refId": "A" + } + ], + "title": "Outbound Traffic Monitoring", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 22 + }, + "id": 18, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_total{local_cluster=~\"$source_service\",\nconsul_destination_service=~\"$destination_service\"}[10m])) by ( local_cluster, consul_destination_service)", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Upstream Traffic: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 22, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.4.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "histogram_quantile(0.95, sum(rate(envoy_cluster_upstream_rq_time_bucket{local_cluster=~\"$source_service\",consul_destination_target!=\"\"}[10m])) by (le, consul_destination_target))", + "interval": "", + "legendFormat": "{{consul_destination_target}}", + "refId": "A" + } + ], + "title": "Upstream Request Response Timeliness: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 20, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!=\"5\",local_cluster=~\"$source_service\",\nconsul_destination_service=~\"$destination_service\"}[10m])) by (local_cluster, consul_destination_service) / sum(irate(envoy_cluster_upstream_rq_xx{local_cluster=~\"$source_service\",consul_destination_service=~\"$destination_service\"}[10m])) by (local_cluster,consul_destination_service)\n", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Upstream Request Success Rate: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 42, + "panels": [], + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "refId": "A" + } + ], + "title": "Inbound Traffic Monitoring", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 41 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_total{consul_destination_datacenter=\"dc1\", local_cluster=~\"$source_service\",\nconsul_destination_service=~\"$destination_service\"}[10m])) by (consul_destination_service, local_cluster)\n", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Requests Sent: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 41 + }, + "id": 43, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!=\"5\", local_cluster=~\"$source_service\", consul_destination_service=~\"$destination_service\"}[10m])) by (local_cluster, consul_destination_service) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_service=~\"$destination_service\"}[10m])) by (local_cluster , consul_destination_service)", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Request Success Rate: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 50 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(envoy_http_downstream_rq_xx{local_cluster=~\"$source_service\", envoy_http_conn_manager_prefix=\"public_listener\"}[10m])) by (local_cluster, envoy_response_code_class)", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Response Success by Status Code: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 50 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.95, sum(rate(envoy_cluster_upstream_rq_time_bucket{consul_destination_datacenter=\"dc1\", consul_destination_service=~\"$destination_service\",local_cluster=~\"$source_service\"}[10m])) by (le, cluster, local_cluster, consul_destination_service))", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Request Duration: $source_service -> $destination_service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 59 + }, + "id": 44, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(envoy_http_downstream_rq_total{local_cluster=~\"$source_service\", envoy_http_conn_manager_prefix=\"public_listener\"}[10m])) by (local_cluster)", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Response Success: $source_service ", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 59 + }, + "id": 8, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(irate(envoy_http_downstream_rq_total{local_cluster=~\"$source_service\",envoy_http_conn_manager_prefix=\"public_listener\"}[10m])) by (local_cluster)", + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Request Response Rate: $source_service", + "type": "stat" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "PBFA97CFB590B2093" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "definition": "label_values(envoy_server_live, consul_source_service)", + "hide": 0, + "includeAll": true, + "multi": false, + "name": "source_service", + "options": [], + "query": { + "query": "label_values(envoy_server_live, consul_source_service)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "definition": "label_values(envoy_cluster_upstream_rq_total, consul_destination_service)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "destination_service", + "options": [], + "query": { + "query": "label_values(envoy_cluster_upstream_rq_total, consul_destination_service)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "datasource": { + "type": "loki", + "uid": "P8E80F9AEF21F6940" + }, + "definition": "label_values(namespace)", + "hide": 0, + "includeAll": true, + "multi": false, + "name": "namespace", + "options": [], + "query": "label_values(namespace)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "", + "value": "" + }, + "hide": 0, + "label": "Search (case insensitive)", + "name": "searchable_pattern", + "options": [ + { + "selected": true, + "text": "\"response_code\":200", + "value": "\"response_code\":200" + } + ], + "query": "", + "skipUrlSync": false, + "type": "textbox" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Consul Service_To_Service Dashboard", + "uid": "qTEWJ0XSkm", + "version": 8, + "weekStart": "" +} \ No newline at end of file diff --git a/grpcmocks/proto-public/pbacl/mock_ACLServiceClient.go b/grpcmocks/proto-public/pbacl/mock_ACLServiceClient.go new file mode 100644 index 000000000000..b4f5f29e282f --- /dev/null +++ b/grpcmocks/proto-public/pbacl/mock_ACLServiceClient.go @@ -0,0 +1,188 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbacl + +import ( + context "context" + + grpc "google.golang.org/grpc" + + mock "github.com/stretchr/testify/mock" + + pbacl "github.com/hashicorp/consul/proto-public/pbacl" +) + +// ACLServiceClient is an autogenerated mock type for the ACLServiceClient type +type ACLServiceClient struct { + mock.Mock +} + +type ACLServiceClient_Expecter struct { + mock *mock.Mock +} + +func (_m *ACLServiceClient) EXPECT() *ACLServiceClient_Expecter { + return &ACLServiceClient_Expecter{mock: &_m.Mock} +} + +// Login provides a mock function with given fields: ctx, in, opts +func (_m *ACLServiceClient) Login(ctx context.Context, in *pbacl.LoginRequest, opts ...grpc.CallOption) (*pbacl.LoginResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Login") + } + + var r0 *pbacl.LoginResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbacl.LoginRequest, ...grpc.CallOption) (*pbacl.LoginResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbacl.LoginRequest, ...grpc.CallOption) *pbacl.LoginResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbacl.LoginResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbacl.LoginRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ACLServiceClient_Login_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Login' +type ACLServiceClient_Login_Call struct { + *mock.Call +} + +// Login is a helper method to define mock.On call +// - ctx context.Context +// - in *pbacl.LoginRequest +// - opts ...grpc.CallOption +func (_e *ACLServiceClient_Expecter) Login(ctx interface{}, in interface{}, opts ...interface{}) *ACLServiceClient_Login_Call { + return &ACLServiceClient_Login_Call{Call: _e.mock.On("Login", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ACLServiceClient_Login_Call) Run(run func(ctx context.Context, in *pbacl.LoginRequest, opts ...grpc.CallOption)) *ACLServiceClient_Login_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbacl.LoginRequest), variadicArgs...) + }) + return _c +} + +func (_c *ACLServiceClient_Login_Call) Return(_a0 *pbacl.LoginResponse, _a1 error) *ACLServiceClient_Login_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ACLServiceClient_Login_Call) RunAndReturn(run func(context.Context, *pbacl.LoginRequest, ...grpc.CallOption) (*pbacl.LoginResponse, error)) *ACLServiceClient_Login_Call { + _c.Call.Return(run) + return _c +} + +// Logout provides a mock function with given fields: ctx, in, opts +func (_m *ACLServiceClient) Logout(ctx context.Context, in *pbacl.LogoutRequest, opts ...grpc.CallOption) (*pbacl.LogoutResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Logout") + } + + var r0 *pbacl.LogoutResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbacl.LogoutRequest, ...grpc.CallOption) (*pbacl.LogoutResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbacl.LogoutRequest, ...grpc.CallOption) *pbacl.LogoutResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbacl.LogoutResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbacl.LogoutRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ACLServiceClient_Logout_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Logout' +type ACLServiceClient_Logout_Call struct { + *mock.Call +} + +// Logout is a helper method to define mock.On call +// - ctx context.Context +// - in *pbacl.LogoutRequest +// - opts ...grpc.CallOption +func (_e *ACLServiceClient_Expecter) Logout(ctx interface{}, in interface{}, opts ...interface{}) *ACLServiceClient_Logout_Call { + return &ACLServiceClient_Logout_Call{Call: _e.mock.On("Logout", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ACLServiceClient_Logout_Call) Run(run func(ctx context.Context, in *pbacl.LogoutRequest, opts ...grpc.CallOption)) *ACLServiceClient_Logout_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbacl.LogoutRequest), variadicArgs...) + }) + return _c +} + +func (_c *ACLServiceClient_Logout_Call) Return(_a0 *pbacl.LogoutResponse, _a1 error) *ACLServiceClient_Logout_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ACLServiceClient_Logout_Call) RunAndReturn(run func(context.Context, *pbacl.LogoutRequest, ...grpc.CallOption) (*pbacl.LogoutResponse, error)) *ACLServiceClient_Logout_Call { + _c.Call.Return(run) + return _c +} + +// NewACLServiceClient creates a new instance of ACLServiceClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewACLServiceClient(t interface { + mock.TestingT + Cleanup(func()) +}) *ACLServiceClient { + mock := &ACLServiceClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbacl/mock_ACLServiceServer.go b/grpcmocks/proto-public/pbacl/mock_ACLServiceServer.go new file mode 100644 index 000000000000..98803d82df43 --- /dev/null +++ b/grpcmocks/proto-public/pbacl/mock_ACLServiceServer.go @@ -0,0 +1,155 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbacl + +import ( + context "context" + + pbacl "github.com/hashicorp/consul/proto-public/pbacl" + mock "github.com/stretchr/testify/mock" +) + +// ACLServiceServer is an autogenerated mock type for the ACLServiceServer type +type ACLServiceServer struct { + mock.Mock +} + +type ACLServiceServer_Expecter struct { + mock *mock.Mock +} + +func (_m *ACLServiceServer) EXPECT() *ACLServiceServer_Expecter { + return &ACLServiceServer_Expecter{mock: &_m.Mock} +} + +// Login provides a mock function with given fields: _a0, _a1 +func (_m *ACLServiceServer) Login(_a0 context.Context, _a1 *pbacl.LoginRequest) (*pbacl.LoginResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Login") + } + + var r0 *pbacl.LoginResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbacl.LoginRequest) (*pbacl.LoginResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbacl.LoginRequest) *pbacl.LoginResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbacl.LoginResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbacl.LoginRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ACLServiceServer_Login_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Login' +type ACLServiceServer_Login_Call struct { + *mock.Call +} + +// Login is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbacl.LoginRequest +func (_e *ACLServiceServer_Expecter) Login(_a0 interface{}, _a1 interface{}) *ACLServiceServer_Login_Call { + return &ACLServiceServer_Login_Call{Call: _e.mock.On("Login", _a0, _a1)} +} + +func (_c *ACLServiceServer_Login_Call) Run(run func(_a0 context.Context, _a1 *pbacl.LoginRequest)) *ACLServiceServer_Login_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbacl.LoginRequest)) + }) + return _c +} + +func (_c *ACLServiceServer_Login_Call) Return(_a0 *pbacl.LoginResponse, _a1 error) *ACLServiceServer_Login_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ACLServiceServer_Login_Call) RunAndReturn(run func(context.Context, *pbacl.LoginRequest) (*pbacl.LoginResponse, error)) *ACLServiceServer_Login_Call { + _c.Call.Return(run) + return _c +} + +// Logout provides a mock function with given fields: _a0, _a1 +func (_m *ACLServiceServer) Logout(_a0 context.Context, _a1 *pbacl.LogoutRequest) (*pbacl.LogoutResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Logout") + } + + var r0 *pbacl.LogoutResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbacl.LogoutRequest) (*pbacl.LogoutResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbacl.LogoutRequest) *pbacl.LogoutResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbacl.LogoutResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbacl.LogoutRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ACLServiceServer_Logout_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Logout' +type ACLServiceServer_Logout_Call struct { + *mock.Call +} + +// Logout is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbacl.LogoutRequest +func (_e *ACLServiceServer_Expecter) Logout(_a0 interface{}, _a1 interface{}) *ACLServiceServer_Logout_Call { + return &ACLServiceServer_Logout_Call{Call: _e.mock.On("Logout", _a0, _a1)} +} + +func (_c *ACLServiceServer_Logout_Call) Run(run func(_a0 context.Context, _a1 *pbacl.LogoutRequest)) *ACLServiceServer_Logout_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbacl.LogoutRequest)) + }) + return _c +} + +func (_c *ACLServiceServer_Logout_Call) Return(_a0 *pbacl.LogoutResponse, _a1 error) *ACLServiceServer_Logout_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ACLServiceServer_Logout_Call) RunAndReturn(run func(context.Context, *pbacl.LogoutRequest) (*pbacl.LogoutResponse, error)) *ACLServiceServer_Logout_Call { + _c.Call.Return(run) + return _c +} + +// NewACLServiceServer creates a new instance of ACLServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewACLServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *ACLServiceServer { + mock := &ACLServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbacl/mock_UnsafeACLServiceServer.go b/grpcmocks/proto-public/pbacl/mock_UnsafeACLServiceServer.go new file mode 100644 index 000000000000..21572b566eef --- /dev/null +++ b/grpcmocks/proto-public/pbacl/mock_UnsafeACLServiceServer.go @@ -0,0 +1,64 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbacl + +import mock "github.com/stretchr/testify/mock" + +// UnsafeACLServiceServer is an autogenerated mock type for the UnsafeACLServiceServer type +type UnsafeACLServiceServer struct { + mock.Mock +} + +type UnsafeACLServiceServer_Expecter struct { + mock *mock.Mock +} + +func (_m *UnsafeACLServiceServer) EXPECT() *UnsafeACLServiceServer_Expecter { + return &UnsafeACLServiceServer_Expecter{mock: &_m.Mock} +} + +// mustEmbedUnimplementedACLServiceServer provides a mock function with given fields: +func (_m *UnsafeACLServiceServer) mustEmbedUnimplementedACLServiceServer() { + _m.Called() +} + +// UnsafeACLServiceServer_mustEmbedUnimplementedACLServiceServer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'mustEmbedUnimplementedACLServiceServer' +type UnsafeACLServiceServer_mustEmbedUnimplementedACLServiceServer_Call struct { + *mock.Call +} + +// mustEmbedUnimplementedACLServiceServer is a helper method to define mock.On call +func (_e *UnsafeACLServiceServer_Expecter) mustEmbedUnimplementedACLServiceServer() *UnsafeACLServiceServer_mustEmbedUnimplementedACLServiceServer_Call { + return &UnsafeACLServiceServer_mustEmbedUnimplementedACLServiceServer_Call{Call: _e.mock.On("mustEmbedUnimplementedACLServiceServer")} +} + +func (_c *UnsafeACLServiceServer_mustEmbedUnimplementedACLServiceServer_Call) Run(run func()) *UnsafeACLServiceServer_mustEmbedUnimplementedACLServiceServer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *UnsafeACLServiceServer_mustEmbedUnimplementedACLServiceServer_Call) Return() *UnsafeACLServiceServer_mustEmbedUnimplementedACLServiceServer_Call { + _c.Call.Return() + return _c +} + +func (_c *UnsafeACLServiceServer_mustEmbedUnimplementedACLServiceServer_Call) RunAndReturn(run func()) *UnsafeACLServiceServer_mustEmbedUnimplementedACLServiceServer_Call { + _c.Call.Return(run) + return _c +} + +// NewUnsafeACLServiceServer creates a new instance of UnsafeACLServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewUnsafeACLServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *UnsafeACLServiceServer { + mock := &UnsafeACLServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbconnectca/mock_ConnectCAServiceClient.go b/grpcmocks/proto-public/pbconnectca/mock_ConnectCAServiceClient.go new file mode 100644 index 000000000000..58ad21c26c38 --- /dev/null +++ b/grpcmocks/proto-public/pbconnectca/mock_ConnectCAServiceClient.go @@ -0,0 +1,188 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbconnectca + +import ( + context "context" + + grpc "google.golang.org/grpc" + + mock "github.com/stretchr/testify/mock" + + pbconnectca "github.com/hashicorp/consul/proto-public/pbconnectca" +) + +// ConnectCAServiceClient is an autogenerated mock type for the ConnectCAServiceClient type +type ConnectCAServiceClient struct { + mock.Mock +} + +type ConnectCAServiceClient_Expecter struct { + mock *mock.Mock +} + +func (_m *ConnectCAServiceClient) EXPECT() *ConnectCAServiceClient_Expecter { + return &ConnectCAServiceClient_Expecter{mock: &_m.Mock} +} + +// Sign provides a mock function with given fields: ctx, in, opts +func (_m *ConnectCAServiceClient) Sign(ctx context.Context, in *pbconnectca.SignRequest, opts ...grpc.CallOption) (*pbconnectca.SignResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Sign") + } + + var r0 *pbconnectca.SignResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbconnectca.SignRequest, ...grpc.CallOption) (*pbconnectca.SignResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbconnectca.SignRequest, ...grpc.CallOption) *pbconnectca.SignResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbconnectca.SignResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbconnectca.SignRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ConnectCAServiceClient_Sign_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Sign' +type ConnectCAServiceClient_Sign_Call struct { + *mock.Call +} + +// Sign is a helper method to define mock.On call +// - ctx context.Context +// - in *pbconnectca.SignRequest +// - opts ...grpc.CallOption +func (_e *ConnectCAServiceClient_Expecter) Sign(ctx interface{}, in interface{}, opts ...interface{}) *ConnectCAServiceClient_Sign_Call { + return &ConnectCAServiceClient_Sign_Call{Call: _e.mock.On("Sign", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ConnectCAServiceClient_Sign_Call) Run(run func(ctx context.Context, in *pbconnectca.SignRequest, opts ...grpc.CallOption)) *ConnectCAServiceClient_Sign_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbconnectca.SignRequest), variadicArgs...) + }) + return _c +} + +func (_c *ConnectCAServiceClient_Sign_Call) Return(_a0 *pbconnectca.SignResponse, _a1 error) *ConnectCAServiceClient_Sign_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ConnectCAServiceClient_Sign_Call) RunAndReturn(run func(context.Context, *pbconnectca.SignRequest, ...grpc.CallOption) (*pbconnectca.SignResponse, error)) *ConnectCAServiceClient_Sign_Call { + _c.Call.Return(run) + return _c +} + +// WatchRoots provides a mock function with given fields: ctx, in, opts +func (_m *ConnectCAServiceClient) WatchRoots(ctx context.Context, in *pbconnectca.WatchRootsRequest, opts ...grpc.CallOption) (pbconnectca.ConnectCAService_WatchRootsClient, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for WatchRoots") + } + + var r0 pbconnectca.ConnectCAService_WatchRootsClient + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbconnectca.WatchRootsRequest, ...grpc.CallOption) (pbconnectca.ConnectCAService_WatchRootsClient, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbconnectca.WatchRootsRequest, ...grpc.CallOption) pbconnectca.ConnectCAService_WatchRootsClient); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pbconnectca.ConnectCAService_WatchRootsClient) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbconnectca.WatchRootsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ConnectCAServiceClient_WatchRoots_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchRoots' +type ConnectCAServiceClient_WatchRoots_Call struct { + *mock.Call +} + +// WatchRoots is a helper method to define mock.On call +// - ctx context.Context +// - in *pbconnectca.WatchRootsRequest +// - opts ...grpc.CallOption +func (_e *ConnectCAServiceClient_Expecter) WatchRoots(ctx interface{}, in interface{}, opts ...interface{}) *ConnectCAServiceClient_WatchRoots_Call { + return &ConnectCAServiceClient_WatchRoots_Call{Call: _e.mock.On("WatchRoots", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ConnectCAServiceClient_WatchRoots_Call) Run(run func(ctx context.Context, in *pbconnectca.WatchRootsRequest, opts ...grpc.CallOption)) *ConnectCAServiceClient_WatchRoots_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbconnectca.WatchRootsRequest), variadicArgs...) + }) + return _c +} + +func (_c *ConnectCAServiceClient_WatchRoots_Call) Return(_a0 pbconnectca.ConnectCAService_WatchRootsClient, _a1 error) *ConnectCAServiceClient_WatchRoots_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ConnectCAServiceClient_WatchRoots_Call) RunAndReturn(run func(context.Context, *pbconnectca.WatchRootsRequest, ...grpc.CallOption) (pbconnectca.ConnectCAService_WatchRootsClient, error)) *ConnectCAServiceClient_WatchRoots_Call { + _c.Call.Return(run) + return _c +} + +// NewConnectCAServiceClient creates a new instance of ConnectCAServiceClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewConnectCAServiceClient(t interface { + mock.TestingT + Cleanup(func()) +}) *ConnectCAServiceClient { + mock := &ConnectCAServiceClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbconnectca/mock_ConnectCAServiceServer.go b/grpcmocks/proto-public/pbconnectca/mock_ConnectCAServiceServer.go new file mode 100644 index 000000000000..086d6840fc3d --- /dev/null +++ b/grpcmocks/proto-public/pbconnectca/mock_ConnectCAServiceServer.go @@ -0,0 +1,143 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbconnectca + +import ( + context "context" + + pbconnectca "github.com/hashicorp/consul/proto-public/pbconnectca" + mock "github.com/stretchr/testify/mock" +) + +// ConnectCAServiceServer is an autogenerated mock type for the ConnectCAServiceServer type +type ConnectCAServiceServer struct { + mock.Mock +} + +type ConnectCAServiceServer_Expecter struct { + mock *mock.Mock +} + +func (_m *ConnectCAServiceServer) EXPECT() *ConnectCAServiceServer_Expecter { + return &ConnectCAServiceServer_Expecter{mock: &_m.Mock} +} + +// Sign provides a mock function with given fields: _a0, _a1 +func (_m *ConnectCAServiceServer) Sign(_a0 context.Context, _a1 *pbconnectca.SignRequest) (*pbconnectca.SignResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Sign") + } + + var r0 *pbconnectca.SignResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbconnectca.SignRequest) (*pbconnectca.SignResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbconnectca.SignRequest) *pbconnectca.SignResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbconnectca.SignResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbconnectca.SignRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ConnectCAServiceServer_Sign_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Sign' +type ConnectCAServiceServer_Sign_Call struct { + *mock.Call +} + +// Sign is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbconnectca.SignRequest +func (_e *ConnectCAServiceServer_Expecter) Sign(_a0 interface{}, _a1 interface{}) *ConnectCAServiceServer_Sign_Call { + return &ConnectCAServiceServer_Sign_Call{Call: _e.mock.On("Sign", _a0, _a1)} +} + +func (_c *ConnectCAServiceServer_Sign_Call) Run(run func(_a0 context.Context, _a1 *pbconnectca.SignRequest)) *ConnectCAServiceServer_Sign_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbconnectca.SignRequest)) + }) + return _c +} + +func (_c *ConnectCAServiceServer_Sign_Call) Return(_a0 *pbconnectca.SignResponse, _a1 error) *ConnectCAServiceServer_Sign_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ConnectCAServiceServer_Sign_Call) RunAndReturn(run func(context.Context, *pbconnectca.SignRequest) (*pbconnectca.SignResponse, error)) *ConnectCAServiceServer_Sign_Call { + _c.Call.Return(run) + return _c +} + +// WatchRoots provides a mock function with given fields: _a0, _a1 +func (_m *ConnectCAServiceServer) WatchRoots(_a0 *pbconnectca.WatchRootsRequest, _a1 pbconnectca.ConnectCAService_WatchRootsServer) error { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for WatchRoots") + } + + var r0 error + if rf, ok := ret.Get(0).(func(*pbconnectca.WatchRootsRequest, pbconnectca.ConnectCAService_WatchRootsServer) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ConnectCAServiceServer_WatchRoots_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchRoots' +type ConnectCAServiceServer_WatchRoots_Call struct { + *mock.Call +} + +// WatchRoots is a helper method to define mock.On call +// - _a0 *pbconnectca.WatchRootsRequest +// - _a1 pbconnectca.ConnectCAService_WatchRootsServer +func (_e *ConnectCAServiceServer_Expecter) WatchRoots(_a0 interface{}, _a1 interface{}) *ConnectCAServiceServer_WatchRoots_Call { + return &ConnectCAServiceServer_WatchRoots_Call{Call: _e.mock.On("WatchRoots", _a0, _a1)} +} + +func (_c *ConnectCAServiceServer_WatchRoots_Call) Run(run func(_a0 *pbconnectca.WatchRootsRequest, _a1 pbconnectca.ConnectCAService_WatchRootsServer)) *ConnectCAServiceServer_WatchRoots_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbconnectca.WatchRootsRequest), args[1].(pbconnectca.ConnectCAService_WatchRootsServer)) + }) + return _c +} + +func (_c *ConnectCAServiceServer_WatchRoots_Call) Return(_a0 error) *ConnectCAServiceServer_WatchRoots_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ConnectCAServiceServer_WatchRoots_Call) RunAndReturn(run func(*pbconnectca.WatchRootsRequest, pbconnectca.ConnectCAService_WatchRootsServer) error) *ConnectCAServiceServer_WatchRoots_Call { + _c.Call.Return(run) + return _c +} + +// NewConnectCAServiceServer creates a new instance of ConnectCAServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewConnectCAServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *ConnectCAServiceServer { + mock := &ConnectCAServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbconnectca/mock_ConnectCAService_WatchRootsClient.go b/grpcmocks/proto-public/pbconnectca/mock_ConnectCAService_WatchRootsClient.go new file mode 100644 index 000000000000..6f545005b93d --- /dev/null +++ b/grpcmocks/proto-public/pbconnectca/mock_ConnectCAService_WatchRootsClient.go @@ -0,0 +1,384 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbconnectca + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + metadata "google.golang.org/grpc/metadata" + + pbconnectca "github.com/hashicorp/consul/proto-public/pbconnectca" +) + +// ConnectCAService_WatchRootsClient is an autogenerated mock type for the ConnectCAService_WatchRootsClient type +type ConnectCAService_WatchRootsClient struct { + mock.Mock +} + +type ConnectCAService_WatchRootsClient_Expecter struct { + mock *mock.Mock +} + +func (_m *ConnectCAService_WatchRootsClient) EXPECT() *ConnectCAService_WatchRootsClient_Expecter { + return &ConnectCAService_WatchRootsClient_Expecter{mock: &_m.Mock} +} + +// CloseSend provides a mock function with given fields: +func (_m *ConnectCAService_WatchRootsClient) CloseSend() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for CloseSend") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ConnectCAService_WatchRootsClient_CloseSend_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CloseSend' +type ConnectCAService_WatchRootsClient_CloseSend_Call struct { + *mock.Call +} + +// CloseSend is a helper method to define mock.On call +func (_e *ConnectCAService_WatchRootsClient_Expecter) CloseSend() *ConnectCAService_WatchRootsClient_CloseSend_Call { + return &ConnectCAService_WatchRootsClient_CloseSend_Call{Call: _e.mock.On("CloseSend")} +} + +func (_c *ConnectCAService_WatchRootsClient_CloseSend_Call) Run(run func()) *ConnectCAService_WatchRootsClient_CloseSend_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_CloseSend_Call) Return(_a0 error) *ConnectCAService_WatchRootsClient_CloseSend_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_CloseSend_Call) RunAndReturn(run func() error) *ConnectCAService_WatchRootsClient_CloseSend_Call { + _c.Call.Return(run) + return _c +} + +// Context provides a mock function with given fields: +func (_m *ConnectCAService_WatchRootsClient) Context() context.Context { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Context") + } + + var r0 context.Context + if rf, ok := ret.Get(0).(func() context.Context); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(context.Context) + } + } + + return r0 +} + +// ConnectCAService_WatchRootsClient_Context_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Context' +type ConnectCAService_WatchRootsClient_Context_Call struct { + *mock.Call +} + +// Context is a helper method to define mock.On call +func (_e *ConnectCAService_WatchRootsClient_Expecter) Context() *ConnectCAService_WatchRootsClient_Context_Call { + return &ConnectCAService_WatchRootsClient_Context_Call{Call: _e.mock.On("Context")} +} + +func (_c *ConnectCAService_WatchRootsClient_Context_Call) Run(run func()) *ConnectCAService_WatchRootsClient_Context_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_Context_Call) Return(_a0 context.Context) *ConnectCAService_WatchRootsClient_Context_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_Context_Call) RunAndReturn(run func() context.Context) *ConnectCAService_WatchRootsClient_Context_Call { + _c.Call.Return(run) + return _c +} + +// Header provides a mock function with given fields: +func (_m *ConnectCAService_WatchRootsClient) Header() (metadata.MD, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Header") + } + + var r0 metadata.MD + var r1 error + if rf, ok := ret.Get(0).(func() (metadata.MD, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() metadata.MD); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(metadata.MD) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ConnectCAService_WatchRootsClient_Header_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Header' +type ConnectCAService_WatchRootsClient_Header_Call struct { + *mock.Call +} + +// Header is a helper method to define mock.On call +func (_e *ConnectCAService_WatchRootsClient_Expecter) Header() *ConnectCAService_WatchRootsClient_Header_Call { + return &ConnectCAService_WatchRootsClient_Header_Call{Call: _e.mock.On("Header")} +} + +func (_c *ConnectCAService_WatchRootsClient_Header_Call) Run(run func()) *ConnectCAService_WatchRootsClient_Header_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_Header_Call) Return(_a0 metadata.MD, _a1 error) *ConnectCAService_WatchRootsClient_Header_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_Header_Call) RunAndReturn(run func() (metadata.MD, error)) *ConnectCAService_WatchRootsClient_Header_Call { + _c.Call.Return(run) + return _c +} + +// Recv provides a mock function with given fields: +func (_m *ConnectCAService_WatchRootsClient) Recv() (*pbconnectca.WatchRootsResponse, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Recv") + } + + var r0 *pbconnectca.WatchRootsResponse + var r1 error + if rf, ok := ret.Get(0).(func() (*pbconnectca.WatchRootsResponse, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() *pbconnectca.WatchRootsResponse); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbconnectca.WatchRootsResponse) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ConnectCAService_WatchRootsClient_Recv_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Recv' +type ConnectCAService_WatchRootsClient_Recv_Call struct { + *mock.Call +} + +// Recv is a helper method to define mock.On call +func (_e *ConnectCAService_WatchRootsClient_Expecter) Recv() *ConnectCAService_WatchRootsClient_Recv_Call { + return &ConnectCAService_WatchRootsClient_Recv_Call{Call: _e.mock.On("Recv")} +} + +func (_c *ConnectCAService_WatchRootsClient_Recv_Call) Run(run func()) *ConnectCAService_WatchRootsClient_Recv_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_Recv_Call) Return(_a0 *pbconnectca.WatchRootsResponse, _a1 error) *ConnectCAService_WatchRootsClient_Recv_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_Recv_Call) RunAndReturn(run func() (*pbconnectca.WatchRootsResponse, error)) *ConnectCAService_WatchRootsClient_Recv_Call { + _c.Call.Return(run) + return _c +} + +// RecvMsg provides a mock function with given fields: m +func (_m *ConnectCAService_WatchRootsClient) RecvMsg(m interface{}) error { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for RecvMsg") + } + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ConnectCAService_WatchRootsClient_RecvMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RecvMsg' +type ConnectCAService_WatchRootsClient_RecvMsg_Call struct { + *mock.Call +} + +// RecvMsg is a helper method to define mock.On call +// - m interface{} +func (_e *ConnectCAService_WatchRootsClient_Expecter) RecvMsg(m interface{}) *ConnectCAService_WatchRootsClient_RecvMsg_Call { + return &ConnectCAService_WatchRootsClient_RecvMsg_Call{Call: _e.mock.On("RecvMsg", m)} +} + +func (_c *ConnectCAService_WatchRootsClient_RecvMsg_Call) Run(run func(m interface{})) *ConnectCAService_WatchRootsClient_RecvMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_RecvMsg_Call) Return(_a0 error) *ConnectCAService_WatchRootsClient_RecvMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_RecvMsg_Call) RunAndReturn(run func(interface{}) error) *ConnectCAService_WatchRootsClient_RecvMsg_Call { + _c.Call.Return(run) + return _c +} + +// SendMsg provides a mock function with given fields: m +func (_m *ConnectCAService_WatchRootsClient) SendMsg(m interface{}) error { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for SendMsg") + } + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ConnectCAService_WatchRootsClient_SendMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendMsg' +type ConnectCAService_WatchRootsClient_SendMsg_Call struct { + *mock.Call +} + +// SendMsg is a helper method to define mock.On call +// - m interface{} +func (_e *ConnectCAService_WatchRootsClient_Expecter) SendMsg(m interface{}) *ConnectCAService_WatchRootsClient_SendMsg_Call { + return &ConnectCAService_WatchRootsClient_SendMsg_Call{Call: _e.mock.On("SendMsg", m)} +} + +func (_c *ConnectCAService_WatchRootsClient_SendMsg_Call) Run(run func(m interface{})) *ConnectCAService_WatchRootsClient_SendMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_SendMsg_Call) Return(_a0 error) *ConnectCAService_WatchRootsClient_SendMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_SendMsg_Call) RunAndReturn(run func(interface{}) error) *ConnectCAService_WatchRootsClient_SendMsg_Call { + _c.Call.Return(run) + return _c +} + +// Trailer provides a mock function with given fields: +func (_m *ConnectCAService_WatchRootsClient) Trailer() metadata.MD { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Trailer") + } + + var r0 metadata.MD + if rf, ok := ret.Get(0).(func() metadata.MD); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(metadata.MD) + } + } + + return r0 +} + +// ConnectCAService_WatchRootsClient_Trailer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Trailer' +type ConnectCAService_WatchRootsClient_Trailer_Call struct { + *mock.Call +} + +// Trailer is a helper method to define mock.On call +func (_e *ConnectCAService_WatchRootsClient_Expecter) Trailer() *ConnectCAService_WatchRootsClient_Trailer_Call { + return &ConnectCAService_WatchRootsClient_Trailer_Call{Call: _e.mock.On("Trailer")} +} + +func (_c *ConnectCAService_WatchRootsClient_Trailer_Call) Run(run func()) *ConnectCAService_WatchRootsClient_Trailer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_Trailer_Call) Return(_a0 metadata.MD) *ConnectCAService_WatchRootsClient_Trailer_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ConnectCAService_WatchRootsClient_Trailer_Call) RunAndReturn(run func() metadata.MD) *ConnectCAService_WatchRootsClient_Trailer_Call { + _c.Call.Return(run) + return _c +} + +// NewConnectCAService_WatchRootsClient creates a new instance of ConnectCAService_WatchRootsClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewConnectCAService_WatchRootsClient(t interface { + mock.TestingT + Cleanup(func()) +}) *ConnectCAService_WatchRootsClient { + mock := &ConnectCAService_WatchRootsClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbconnectca/mock_ConnectCAService_WatchRootsServer.go b/grpcmocks/proto-public/pbconnectca/mock_ConnectCAService_WatchRootsServer.go new file mode 100644 index 000000000000..4ca2d667e2ef --- /dev/null +++ b/grpcmocks/proto-public/pbconnectca/mock_ConnectCAService_WatchRootsServer.go @@ -0,0 +1,349 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbconnectca + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + metadata "google.golang.org/grpc/metadata" + + pbconnectca "github.com/hashicorp/consul/proto-public/pbconnectca" +) + +// ConnectCAService_WatchRootsServer is an autogenerated mock type for the ConnectCAService_WatchRootsServer type +type ConnectCAService_WatchRootsServer struct { + mock.Mock +} + +type ConnectCAService_WatchRootsServer_Expecter struct { + mock *mock.Mock +} + +func (_m *ConnectCAService_WatchRootsServer) EXPECT() *ConnectCAService_WatchRootsServer_Expecter { + return &ConnectCAService_WatchRootsServer_Expecter{mock: &_m.Mock} +} + +// Context provides a mock function with given fields: +func (_m *ConnectCAService_WatchRootsServer) Context() context.Context { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Context") + } + + var r0 context.Context + if rf, ok := ret.Get(0).(func() context.Context); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(context.Context) + } + } + + return r0 +} + +// ConnectCAService_WatchRootsServer_Context_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Context' +type ConnectCAService_WatchRootsServer_Context_Call struct { + *mock.Call +} + +// Context is a helper method to define mock.On call +func (_e *ConnectCAService_WatchRootsServer_Expecter) Context() *ConnectCAService_WatchRootsServer_Context_Call { + return &ConnectCAService_WatchRootsServer_Context_Call{Call: _e.mock.On("Context")} +} + +func (_c *ConnectCAService_WatchRootsServer_Context_Call) Run(run func()) *ConnectCAService_WatchRootsServer_Context_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_Context_Call) Return(_a0 context.Context) *ConnectCAService_WatchRootsServer_Context_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_Context_Call) RunAndReturn(run func() context.Context) *ConnectCAService_WatchRootsServer_Context_Call { + _c.Call.Return(run) + return _c +} + +// RecvMsg provides a mock function with given fields: m +func (_m *ConnectCAService_WatchRootsServer) RecvMsg(m interface{}) error { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for RecvMsg") + } + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ConnectCAService_WatchRootsServer_RecvMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RecvMsg' +type ConnectCAService_WatchRootsServer_RecvMsg_Call struct { + *mock.Call +} + +// RecvMsg is a helper method to define mock.On call +// - m interface{} +func (_e *ConnectCAService_WatchRootsServer_Expecter) RecvMsg(m interface{}) *ConnectCAService_WatchRootsServer_RecvMsg_Call { + return &ConnectCAService_WatchRootsServer_RecvMsg_Call{Call: _e.mock.On("RecvMsg", m)} +} + +func (_c *ConnectCAService_WatchRootsServer_RecvMsg_Call) Run(run func(m interface{})) *ConnectCAService_WatchRootsServer_RecvMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_RecvMsg_Call) Return(_a0 error) *ConnectCAService_WatchRootsServer_RecvMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_RecvMsg_Call) RunAndReturn(run func(interface{}) error) *ConnectCAService_WatchRootsServer_RecvMsg_Call { + _c.Call.Return(run) + return _c +} + +// Send provides a mock function with given fields: _a0 +func (_m *ConnectCAService_WatchRootsServer) Send(_a0 *pbconnectca.WatchRootsResponse) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Send") + } + + var r0 error + if rf, ok := ret.Get(0).(func(*pbconnectca.WatchRootsResponse) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ConnectCAService_WatchRootsServer_Send_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Send' +type ConnectCAService_WatchRootsServer_Send_Call struct { + *mock.Call +} + +// Send is a helper method to define mock.On call +// - _a0 *pbconnectca.WatchRootsResponse +func (_e *ConnectCAService_WatchRootsServer_Expecter) Send(_a0 interface{}) *ConnectCAService_WatchRootsServer_Send_Call { + return &ConnectCAService_WatchRootsServer_Send_Call{Call: _e.mock.On("Send", _a0)} +} + +func (_c *ConnectCAService_WatchRootsServer_Send_Call) Run(run func(_a0 *pbconnectca.WatchRootsResponse)) *ConnectCAService_WatchRootsServer_Send_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbconnectca.WatchRootsResponse)) + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_Send_Call) Return(_a0 error) *ConnectCAService_WatchRootsServer_Send_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_Send_Call) RunAndReturn(run func(*pbconnectca.WatchRootsResponse) error) *ConnectCAService_WatchRootsServer_Send_Call { + _c.Call.Return(run) + return _c +} + +// SendHeader provides a mock function with given fields: _a0 +func (_m *ConnectCAService_WatchRootsServer) SendHeader(_a0 metadata.MD) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for SendHeader") + } + + var r0 error + if rf, ok := ret.Get(0).(func(metadata.MD) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ConnectCAService_WatchRootsServer_SendHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendHeader' +type ConnectCAService_WatchRootsServer_SendHeader_Call struct { + *mock.Call +} + +// SendHeader is a helper method to define mock.On call +// - _a0 metadata.MD +func (_e *ConnectCAService_WatchRootsServer_Expecter) SendHeader(_a0 interface{}) *ConnectCAService_WatchRootsServer_SendHeader_Call { + return &ConnectCAService_WatchRootsServer_SendHeader_Call{Call: _e.mock.On("SendHeader", _a0)} +} + +func (_c *ConnectCAService_WatchRootsServer_SendHeader_Call) Run(run func(_a0 metadata.MD)) *ConnectCAService_WatchRootsServer_SendHeader_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(metadata.MD)) + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_SendHeader_Call) Return(_a0 error) *ConnectCAService_WatchRootsServer_SendHeader_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_SendHeader_Call) RunAndReturn(run func(metadata.MD) error) *ConnectCAService_WatchRootsServer_SendHeader_Call { + _c.Call.Return(run) + return _c +} + +// SendMsg provides a mock function with given fields: m +func (_m *ConnectCAService_WatchRootsServer) SendMsg(m interface{}) error { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for SendMsg") + } + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ConnectCAService_WatchRootsServer_SendMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendMsg' +type ConnectCAService_WatchRootsServer_SendMsg_Call struct { + *mock.Call +} + +// SendMsg is a helper method to define mock.On call +// - m interface{} +func (_e *ConnectCAService_WatchRootsServer_Expecter) SendMsg(m interface{}) *ConnectCAService_WatchRootsServer_SendMsg_Call { + return &ConnectCAService_WatchRootsServer_SendMsg_Call{Call: _e.mock.On("SendMsg", m)} +} + +func (_c *ConnectCAService_WatchRootsServer_SendMsg_Call) Run(run func(m interface{})) *ConnectCAService_WatchRootsServer_SendMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_SendMsg_Call) Return(_a0 error) *ConnectCAService_WatchRootsServer_SendMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_SendMsg_Call) RunAndReturn(run func(interface{}) error) *ConnectCAService_WatchRootsServer_SendMsg_Call { + _c.Call.Return(run) + return _c +} + +// SetHeader provides a mock function with given fields: _a0 +func (_m *ConnectCAService_WatchRootsServer) SetHeader(_a0 metadata.MD) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for SetHeader") + } + + var r0 error + if rf, ok := ret.Get(0).(func(metadata.MD) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ConnectCAService_WatchRootsServer_SetHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetHeader' +type ConnectCAService_WatchRootsServer_SetHeader_Call struct { + *mock.Call +} + +// SetHeader is a helper method to define mock.On call +// - _a0 metadata.MD +func (_e *ConnectCAService_WatchRootsServer_Expecter) SetHeader(_a0 interface{}) *ConnectCAService_WatchRootsServer_SetHeader_Call { + return &ConnectCAService_WatchRootsServer_SetHeader_Call{Call: _e.mock.On("SetHeader", _a0)} +} + +func (_c *ConnectCAService_WatchRootsServer_SetHeader_Call) Run(run func(_a0 metadata.MD)) *ConnectCAService_WatchRootsServer_SetHeader_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(metadata.MD)) + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_SetHeader_Call) Return(_a0 error) *ConnectCAService_WatchRootsServer_SetHeader_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_SetHeader_Call) RunAndReturn(run func(metadata.MD) error) *ConnectCAService_WatchRootsServer_SetHeader_Call { + _c.Call.Return(run) + return _c +} + +// SetTrailer provides a mock function with given fields: _a0 +func (_m *ConnectCAService_WatchRootsServer) SetTrailer(_a0 metadata.MD) { + _m.Called(_a0) +} + +// ConnectCAService_WatchRootsServer_SetTrailer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetTrailer' +type ConnectCAService_WatchRootsServer_SetTrailer_Call struct { + *mock.Call +} + +// SetTrailer is a helper method to define mock.On call +// - _a0 metadata.MD +func (_e *ConnectCAService_WatchRootsServer_Expecter) SetTrailer(_a0 interface{}) *ConnectCAService_WatchRootsServer_SetTrailer_Call { + return &ConnectCAService_WatchRootsServer_SetTrailer_Call{Call: _e.mock.On("SetTrailer", _a0)} +} + +func (_c *ConnectCAService_WatchRootsServer_SetTrailer_Call) Run(run func(_a0 metadata.MD)) *ConnectCAService_WatchRootsServer_SetTrailer_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(metadata.MD)) + }) + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_SetTrailer_Call) Return() *ConnectCAService_WatchRootsServer_SetTrailer_Call { + _c.Call.Return() + return _c +} + +func (_c *ConnectCAService_WatchRootsServer_SetTrailer_Call) RunAndReturn(run func(metadata.MD)) *ConnectCAService_WatchRootsServer_SetTrailer_Call { + _c.Call.Return(run) + return _c +} + +// NewConnectCAService_WatchRootsServer creates a new instance of ConnectCAService_WatchRootsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewConnectCAService_WatchRootsServer(t interface { + mock.TestingT + Cleanup(func()) +}) *ConnectCAService_WatchRootsServer { + mock := &ConnectCAService_WatchRootsServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbconnectca/mock_UnsafeConnectCAServiceServer.go b/grpcmocks/proto-public/pbconnectca/mock_UnsafeConnectCAServiceServer.go new file mode 100644 index 000000000000..e740378bd2e4 --- /dev/null +++ b/grpcmocks/proto-public/pbconnectca/mock_UnsafeConnectCAServiceServer.go @@ -0,0 +1,64 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbconnectca + +import mock "github.com/stretchr/testify/mock" + +// UnsafeConnectCAServiceServer is an autogenerated mock type for the UnsafeConnectCAServiceServer type +type UnsafeConnectCAServiceServer struct { + mock.Mock +} + +type UnsafeConnectCAServiceServer_Expecter struct { + mock *mock.Mock +} + +func (_m *UnsafeConnectCAServiceServer) EXPECT() *UnsafeConnectCAServiceServer_Expecter { + return &UnsafeConnectCAServiceServer_Expecter{mock: &_m.Mock} +} + +// mustEmbedUnimplementedConnectCAServiceServer provides a mock function with given fields: +func (_m *UnsafeConnectCAServiceServer) mustEmbedUnimplementedConnectCAServiceServer() { + _m.Called() +} + +// UnsafeConnectCAServiceServer_mustEmbedUnimplementedConnectCAServiceServer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'mustEmbedUnimplementedConnectCAServiceServer' +type UnsafeConnectCAServiceServer_mustEmbedUnimplementedConnectCAServiceServer_Call struct { + *mock.Call +} + +// mustEmbedUnimplementedConnectCAServiceServer is a helper method to define mock.On call +func (_e *UnsafeConnectCAServiceServer_Expecter) mustEmbedUnimplementedConnectCAServiceServer() *UnsafeConnectCAServiceServer_mustEmbedUnimplementedConnectCAServiceServer_Call { + return &UnsafeConnectCAServiceServer_mustEmbedUnimplementedConnectCAServiceServer_Call{Call: _e.mock.On("mustEmbedUnimplementedConnectCAServiceServer")} +} + +func (_c *UnsafeConnectCAServiceServer_mustEmbedUnimplementedConnectCAServiceServer_Call) Run(run func()) *UnsafeConnectCAServiceServer_mustEmbedUnimplementedConnectCAServiceServer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *UnsafeConnectCAServiceServer_mustEmbedUnimplementedConnectCAServiceServer_Call) Return() *UnsafeConnectCAServiceServer_mustEmbedUnimplementedConnectCAServiceServer_Call { + _c.Call.Return() + return _c +} + +func (_c *UnsafeConnectCAServiceServer_mustEmbedUnimplementedConnectCAServiceServer_Call) RunAndReturn(run func()) *UnsafeConnectCAServiceServer_mustEmbedUnimplementedConnectCAServiceServer_Call { + _c.Call.Return(run) + return _c +} + +// NewUnsafeConnectCAServiceServer creates a new instance of UnsafeConnectCAServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewUnsafeConnectCAServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *UnsafeConnectCAServiceServer { + mock := &UnsafeConnectCAServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbdataplane/mock_DataplaneServiceClient.go b/grpcmocks/proto-public/pbdataplane/mock_DataplaneServiceClient.go new file mode 100644 index 000000000000..3c8332f8976e --- /dev/null +++ b/grpcmocks/proto-public/pbdataplane/mock_DataplaneServiceClient.go @@ -0,0 +1,188 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbdataplane + +import ( + context "context" + + grpc "google.golang.org/grpc" + + mock "github.com/stretchr/testify/mock" + + pbdataplane "github.com/hashicorp/consul/proto-public/pbdataplane" +) + +// DataplaneServiceClient is an autogenerated mock type for the DataplaneServiceClient type +type DataplaneServiceClient struct { + mock.Mock +} + +type DataplaneServiceClient_Expecter struct { + mock *mock.Mock +} + +func (_m *DataplaneServiceClient) EXPECT() *DataplaneServiceClient_Expecter { + return &DataplaneServiceClient_Expecter{mock: &_m.Mock} +} + +// GetEnvoyBootstrapParams provides a mock function with given fields: ctx, in, opts +func (_m *DataplaneServiceClient) GetEnvoyBootstrapParams(ctx context.Context, in *pbdataplane.GetEnvoyBootstrapParamsRequest, opts ...grpc.CallOption) (*pbdataplane.GetEnvoyBootstrapParamsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetEnvoyBootstrapParams") + } + + var r0 *pbdataplane.GetEnvoyBootstrapParamsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbdataplane.GetEnvoyBootstrapParamsRequest, ...grpc.CallOption) (*pbdataplane.GetEnvoyBootstrapParamsResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbdataplane.GetEnvoyBootstrapParamsRequest, ...grpc.CallOption) *pbdataplane.GetEnvoyBootstrapParamsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbdataplane.GetEnvoyBootstrapParamsResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbdataplane.GetEnvoyBootstrapParamsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DataplaneServiceClient_GetEnvoyBootstrapParams_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEnvoyBootstrapParams' +type DataplaneServiceClient_GetEnvoyBootstrapParams_Call struct { + *mock.Call +} + +// GetEnvoyBootstrapParams is a helper method to define mock.On call +// - ctx context.Context +// - in *pbdataplane.GetEnvoyBootstrapParamsRequest +// - opts ...grpc.CallOption +func (_e *DataplaneServiceClient_Expecter) GetEnvoyBootstrapParams(ctx interface{}, in interface{}, opts ...interface{}) *DataplaneServiceClient_GetEnvoyBootstrapParams_Call { + return &DataplaneServiceClient_GetEnvoyBootstrapParams_Call{Call: _e.mock.On("GetEnvoyBootstrapParams", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *DataplaneServiceClient_GetEnvoyBootstrapParams_Call) Run(run func(ctx context.Context, in *pbdataplane.GetEnvoyBootstrapParamsRequest, opts ...grpc.CallOption)) *DataplaneServiceClient_GetEnvoyBootstrapParams_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbdataplane.GetEnvoyBootstrapParamsRequest), variadicArgs...) + }) + return _c +} + +func (_c *DataplaneServiceClient_GetEnvoyBootstrapParams_Call) Return(_a0 *pbdataplane.GetEnvoyBootstrapParamsResponse, _a1 error) *DataplaneServiceClient_GetEnvoyBootstrapParams_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DataplaneServiceClient_GetEnvoyBootstrapParams_Call) RunAndReturn(run func(context.Context, *pbdataplane.GetEnvoyBootstrapParamsRequest, ...grpc.CallOption) (*pbdataplane.GetEnvoyBootstrapParamsResponse, error)) *DataplaneServiceClient_GetEnvoyBootstrapParams_Call { + _c.Call.Return(run) + return _c +} + +// GetSupportedDataplaneFeatures provides a mock function with given fields: ctx, in, opts +func (_m *DataplaneServiceClient) GetSupportedDataplaneFeatures(ctx context.Context, in *pbdataplane.GetSupportedDataplaneFeaturesRequest, opts ...grpc.CallOption) (*pbdataplane.GetSupportedDataplaneFeaturesResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetSupportedDataplaneFeatures") + } + + var r0 *pbdataplane.GetSupportedDataplaneFeaturesResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbdataplane.GetSupportedDataplaneFeaturesRequest, ...grpc.CallOption) (*pbdataplane.GetSupportedDataplaneFeaturesResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbdataplane.GetSupportedDataplaneFeaturesRequest, ...grpc.CallOption) *pbdataplane.GetSupportedDataplaneFeaturesResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbdataplane.GetSupportedDataplaneFeaturesResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbdataplane.GetSupportedDataplaneFeaturesRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DataplaneServiceClient_GetSupportedDataplaneFeatures_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSupportedDataplaneFeatures' +type DataplaneServiceClient_GetSupportedDataplaneFeatures_Call struct { + *mock.Call +} + +// GetSupportedDataplaneFeatures is a helper method to define mock.On call +// - ctx context.Context +// - in *pbdataplane.GetSupportedDataplaneFeaturesRequest +// - opts ...grpc.CallOption +func (_e *DataplaneServiceClient_Expecter) GetSupportedDataplaneFeatures(ctx interface{}, in interface{}, opts ...interface{}) *DataplaneServiceClient_GetSupportedDataplaneFeatures_Call { + return &DataplaneServiceClient_GetSupportedDataplaneFeatures_Call{Call: _e.mock.On("GetSupportedDataplaneFeatures", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *DataplaneServiceClient_GetSupportedDataplaneFeatures_Call) Run(run func(ctx context.Context, in *pbdataplane.GetSupportedDataplaneFeaturesRequest, opts ...grpc.CallOption)) *DataplaneServiceClient_GetSupportedDataplaneFeatures_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbdataplane.GetSupportedDataplaneFeaturesRequest), variadicArgs...) + }) + return _c +} + +func (_c *DataplaneServiceClient_GetSupportedDataplaneFeatures_Call) Return(_a0 *pbdataplane.GetSupportedDataplaneFeaturesResponse, _a1 error) *DataplaneServiceClient_GetSupportedDataplaneFeatures_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DataplaneServiceClient_GetSupportedDataplaneFeatures_Call) RunAndReturn(run func(context.Context, *pbdataplane.GetSupportedDataplaneFeaturesRequest, ...grpc.CallOption) (*pbdataplane.GetSupportedDataplaneFeaturesResponse, error)) *DataplaneServiceClient_GetSupportedDataplaneFeatures_Call { + _c.Call.Return(run) + return _c +} + +// NewDataplaneServiceClient creates a new instance of DataplaneServiceClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDataplaneServiceClient(t interface { + mock.TestingT + Cleanup(func()) +}) *DataplaneServiceClient { + mock := &DataplaneServiceClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbdataplane/mock_DataplaneServiceServer.go b/grpcmocks/proto-public/pbdataplane/mock_DataplaneServiceServer.go new file mode 100644 index 000000000000..826137e0e81a --- /dev/null +++ b/grpcmocks/proto-public/pbdataplane/mock_DataplaneServiceServer.go @@ -0,0 +1,155 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbdataplane + +import ( + context "context" + + pbdataplane "github.com/hashicorp/consul/proto-public/pbdataplane" + mock "github.com/stretchr/testify/mock" +) + +// DataplaneServiceServer is an autogenerated mock type for the DataplaneServiceServer type +type DataplaneServiceServer struct { + mock.Mock +} + +type DataplaneServiceServer_Expecter struct { + mock *mock.Mock +} + +func (_m *DataplaneServiceServer) EXPECT() *DataplaneServiceServer_Expecter { + return &DataplaneServiceServer_Expecter{mock: &_m.Mock} +} + +// GetEnvoyBootstrapParams provides a mock function with given fields: _a0, _a1 +func (_m *DataplaneServiceServer) GetEnvoyBootstrapParams(_a0 context.Context, _a1 *pbdataplane.GetEnvoyBootstrapParamsRequest) (*pbdataplane.GetEnvoyBootstrapParamsResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for GetEnvoyBootstrapParams") + } + + var r0 *pbdataplane.GetEnvoyBootstrapParamsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbdataplane.GetEnvoyBootstrapParamsRequest) (*pbdataplane.GetEnvoyBootstrapParamsResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbdataplane.GetEnvoyBootstrapParamsRequest) *pbdataplane.GetEnvoyBootstrapParamsResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbdataplane.GetEnvoyBootstrapParamsResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbdataplane.GetEnvoyBootstrapParamsRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DataplaneServiceServer_GetEnvoyBootstrapParams_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEnvoyBootstrapParams' +type DataplaneServiceServer_GetEnvoyBootstrapParams_Call struct { + *mock.Call +} + +// GetEnvoyBootstrapParams is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbdataplane.GetEnvoyBootstrapParamsRequest +func (_e *DataplaneServiceServer_Expecter) GetEnvoyBootstrapParams(_a0 interface{}, _a1 interface{}) *DataplaneServiceServer_GetEnvoyBootstrapParams_Call { + return &DataplaneServiceServer_GetEnvoyBootstrapParams_Call{Call: _e.mock.On("GetEnvoyBootstrapParams", _a0, _a1)} +} + +func (_c *DataplaneServiceServer_GetEnvoyBootstrapParams_Call) Run(run func(_a0 context.Context, _a1 *pbdataplane.GetEnvoyBootstrapParamsRequest)) *DataplaneServiceServer_GetEnvoyBootstrapParams_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbdataplane.GetEnvoyBootstrapParamsRequest)) + }) + return _c +} + +func (_c *DataplaneServiceServer_GetEnvoyBootstrapParams_Call) Return(_a0 *pbdataplane.GetEnvoyBootstrapParamsResponse, _a1 error) *DataplaneServiceServer_GetEnvoyBootstrapParams_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DataplaneServiceServer_GetEnvoyBootstrapParams_Call) RunAndReturn(run func(context.Context, *pbdataplane.GetEnvoyBootstrapParamsRequest) (*pbdataplane.GetEnvoyBootstrapParamsResponse, error)) *DataplaneServiceServer_GetEnvoyBootstrapParams_Call { + _c.Call.Return(run) + return _c +} + +// GetSupportedDataplaneFeatures provides a mock function with given fields: _a0, _a1 +func (_m *DataplaneServiceServer) GetSupportedDataplaneFeatures(_a0 context.Context, _a1 *pbdataplane.GetSupportedDataplaneFeaturesRequest) (*pbdataplane.GetSupportedDataplaneFeaturesResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for GetSupportedDataplaneFeatures") + } + + var r0 *pbdataplane.GetSupportedDataplaneFeaturesResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbdataplane.GetSupportedDataplaneFeaturesRequest) (*pbdataplane.GetSupportedDataplaneFeaturesResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbdataplane.GetSupportedDataplaneFeaturesRequest) *pbdataplane.GetSupportedDataplaneFeaturesResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbdataplane.GetSupportedDataplaneFeaturesResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbdataplane.GetSupportedDataplaneFeaturesRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DataplaneServiceServer_GetSupportedDataplaneFeatures_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSupportedDataplaneFeatures' +type DataplaneServiceServer_GetSupportedDataplaneFeatures_Call struct { + *mock.Call +} + +// GetSupportedDataplaneFeatures is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbdataplane.GetSupportedDataplaneFeaturesRequest +func (_e *DataplaneServiceServer_Expecter) GetSupportedDataplaneFeatures(_a0 interface{}, _a1 interface{}) *DataplaneServiceServer_GetSupportedDataplaneFeatures_Call { + return &DataplaneServiceServer_GetSupportedDataplaneFeatures_Call{Call: _e.mock.On("GetSupportedDataplaneFeatures", _a0, _a1)} +} + +func (_c *DataplaneServiceServer_GetSupportedDataplaneFeatures_Call) Run(run func(_a0 context.Context, _a1 *pbdataplane.GetSupportedDataplaneFeaturesRequest)) *DataplaneServiceServer_GetSupportedDataplaneFeatures_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbdataplane.GetSupportedDataplaneFeaturesRequest)) + }) + return _c +} + +func (_c *DataplaneServiceServer_GetSupportedDataplaneFeatures_Call) Return(_a0 *pbdataplane.GetSupportedDataplaneFeaturesResponse, _a1 error) *DataplaneServiceServer_GetSupportedDataplaneFeatures_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DataplaneServiceServer_GetSupportedDataplaneFeatures_Call) RunAndReturn(run func(context.Context, *pbdataplane.GetSupportedDataplaneFeaturesRequest) (*pbdataplane.GetSupportedDataplaneFeaturesResponse, error)) *DataplaneServiceServer_GetSupportedDataplaneFeatures_Call { + _c.Call.Return(run) + return _c +} + +// NewDataplaneServiceServer creates a new instance of DataplaneServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDataplaneServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *DataplaneServiceServer { + mock := &DataplaneServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbdataplane/mock_UnsafeDataplaneServiceServer.go b/grpcmocks/proto-public/pbdataplane/mock_UnsafeDataplaneServiceServer.go new file mode 100644 index 000000000000..077c5371ba19 --- /dev/null +++ b/grpcmocks/proto-public/pbdataplane/mock_UnsafeDataplaneServiceServer.go @@ -0,0 +1,64 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbdataplane + +import mock "github.com/stretchr/testify/mock" + +// UnsafeDataplaneServiceServer is an autogenerated mock type for the UnsafeDataplaneServiceServer type +type UnsafeDataplaneServiceServer struct { + mock.Mock +} + +type UnsafeDataplaneServiceServer_Expecter struct { + mock *mock.Mock +} + +func (_m *UnsafeDataplaneServiceServer) EXPECT() *UnsafeDataplaneServiceServer_Expecter { + return &UnsafeDataplaneServiceServer_Expecter{mock: &_m.Mock} +} + +// mustEmbedUnimplementedDataplaneServiceServer provides a mock function with given fields: +func (_m *UnsafeDataplaneServiceServer) mustEmbedUnimplementedDataplaneServiceServer() { + _m.Called() +} + +// UnsafeDataplaneServiceServer_mustEmbedUnimplementedDataplaneServiceServer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'mustEmbedUnimplementedDataplaneServiceServer' +type UnsafeDataplaneServiceServer_mustEmbedUnimplementedDataplaneServiceServer_Call struct { + *mock.Call +} + +// mustEmbedUnimplementedDataplaneServiceServer is a helper method to define mock.On call +func (_e *UnsafeDataplaneServiceServer_Expecter) mustEmbedUnimplementedDataplaneServiceServer() *UnsafeDataplaneServiceServer_mustEmbedUnimplementedDataplaneServiceServer_Call { + return &UnsafeDataplaneServiceServer_mustEmbedUnimplementedDataplaneServiceServer_Call{Call: _e.mock.On("mustEmbedUnimplementedDataplaneServiceServer")} +} + +func (_c *UnsafeDataplaneServiceServer_mustEmbedUnimplementedDataplaneServiceServer_Call) Run(run func()) *UnsafeDataplaneServiceServer_mustEmbedUnimplementedDataplaneServiceServer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *UnsafeDataplaneServiceServer_mustEmbedUnimplementedDataplaneServiceServer_Call) Return() *UnsafeDataplaneServiceServer_mustEmbedUnimplementedDataplaneServiceServer_Call { + _c.Call.Return() + return _c +} + +func (_c *UnsafeDataplaneServiceServer_mustEmbedUnimplementedDataplaneServiceServer_Call) RunAndReturn(run func()) *UnsafeDataplaneServiceServer_mustEmbedUnimplementedDataplaneServiceServer_Call { + _c.Call.Return(run) + return _c +} + +// NewUnsafeDataplaneServiceServer creates a new instance of UnsafeDataplaneServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewUnsafeDataplaneServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *UnsafeDataplaneServiceServer { + mock := &UnsafeDataplaneServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbdataplane/mock_isGetEnvoyBootstrapParamsRequest_NodeSpec.go b/grpcmocks/proto-public/pbdataplane/mock_isGetEnvoyBootstrapParamsRequest_NodeSpec.go new file mode 100644 index 000000000000..98f54341cece --- /dev/null +++ b/grpcmocks/proto-public/pbdataplane/mock_isGetEnvoyBootstrapParamsRequest_NodeSpec.go @@ -0,0 +1,64 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbdataplane + +import mock "github.com/stretchr/testify/mock" + +// isGetEnvoyBootstrapParamsRequest_NodeSpec is an autogenerated mock type for the isGetEnvoyBootstrapParamsRequest_NodeSpec type +type isGetEnvoyBootstrapParamsRequest_NodeSpec struct { + mock.Mock +} + +type isGetEnvoyBootstrapParamsRequest_NodeSpec_Expecter struct { + mock *mock.Mock +} + +func (_m *isGetEnvoyBootstrapParamsRequest_NodeSpec) EXPECT() *isGetEnvoyBootstrapParamsRequest_NodeSpec_Expecter { + return &isGetEnvoyBootstrapParamsRequest_NodeSpec_Expecter{mock: &_m.Mock} +} + +// isGetEnvoyBootstrapParamsRequest_NodeSpec provides a mock function with given fields: +func (_m *isGetEnvoyBootstrapParamsRequest_NodeSpec) isGetEnvoyBootstrapParamsRequest_NodeSpec() { + _m.Called() +} + +// isGetEnvoyBootstrapParamsRequest_NodeSpec_isGetEnvoyBootstrapParamsRequest_NodeSpec_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'isGetEnvoyBootstrapParamsRequest_NodeSpec' +type isGetEnvoyBootstrapParamsRequest_NodeSpec_isGetEnvoyBootstrapParamsRequest_NodeSpec_Call struct { + *mock.Call +} + +// isGetEnvoyBootstrapParamsRequest_NodeSpec is a helper method to define mock.On call +func (_e *isGetEnvoyBootstrapParamsRequest_NodeSpec_Expecter) isGetEnvoyBootstrapParamsRequest_NodeSpec() *isGetEnvoyBootstrapParamsRequest_NodeSpec_isGetEnvoyBootstrapParamsRequest_NodeSpec_Call { + return &isGetEnvoyBootstrapParamsRequest_NodeSpec_isGetEnvoyBootstrapParamsRequest_NodeSpec_Call{Call: _e.mock.On("isGetEnvoyBootstrapParamsRequest_NodeSpec")} +} + +func (_c *isGetEnvoyBootstrapParamsRequest_NodeSpec_isGetEnvoyBootstrapParamsRequest_NodeSpec_Call) Run(run func()) *isGetEnvoyBootstrapParamsRequest_NodeSpec_isGetEnvoyBootstrapParamsRequest_NodeSpec_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *isGetEnvoyBootstrapParamsRequest_NodeSpec_isGetEnvoyBootstrapParamsRequest_NodeSpec_Call) Return() *isGetEnvoyBootstrapParamsRequest_NodeSpec_isGetEnvoyBootstrapParamsRequest_NodeSpec_Call { + _c.Call.Return() + return _c +} + +func (_c *isGetEnvoyBootstrapParamsRequest_NodeSpec_isGetEnvoyBootstrapParamsRequest_NodeSpec_Call) RunAndReturn(run func()) *isGetEnvoyBootstrapParamsRequest_NodeSpec_isGetEnvoyBootstrapParamsRequest_NodeSpec_Call { + _c.Call.Return(run) + return _c +} + +// newIsGetEnvoyBootstrapParamsRequest_NodeSpec creates a new instance of isGetEnvoyBootstrapParamsRequest_NodeSpec. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newIsGetEnvoyBootstrapParamsRequest_NodeSpec(t interface { + mock.TestingT + Cleanup(func()) +}) *isGetEnvoyBootstrapParamsRequest_NodeSpec { + mock := &isGetEnvoyBootstrapParamsRequest_NodeSpec{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbdns/mock_DNSServiceClient.go b/grpcmocks/proto-public/pbdns/mock_DNSServiceClient.go new file mode 100644 index 000000000000..0b0e9496a04a --- /dev/null +++ b/grpcmocks/proto-public/pbdns/mock_DNSServiceClient.go @@ -0,0 +1,114 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbdns + +import ( + context "context" + + grpc "google.golang.org/grpc" + + mock "github.com/stretchr/testify/mock" + + pbdns "github.com/hashicorp/consul/proto-public/pbdns" +) + +// DNSServiceClient is an autogenerated mock type for the DNSServiceClient type +type DNSServiceClient struct { + mock.Mock +} + +type DNSServiceClient_Expecter struct { + mock *mock.Mock +} + +func (_m *DNSServiceClient) EXPECT() *DNSServiceClient_Expecter { + return &DNSServiceClient_Expecter{mock: &_m.Mock} +} + +// Query provides a mock function with given fields: ctx, in, opts +func (_m *DNSServiceClient) Query(ctx context.Context, in *pbdns.QueryRequest, opts ...grpc.CallOption) (*pbdns.QueryResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Query") + } + + var r0 *pbdns.QueryResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbdns.QueryRequest, ...grpc.CallOption) (*pbdns.QueryResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbdns.QueryRequest, ...grpc.CallOption) *pbdns.QueryResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbdns.QueryResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbdns.QueryRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DNSServiceClient_Query_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Query' +type DNSServiceClient_Query_Call struct { + *mock.Call +} + +// Query is a helper method to define mock.On call +// - ctx context.Context +// - in *pbdns.QueryRequest +// - opts ...grpc.CallOption +func (_e *DNSServiceClient_Expecter) Query(ctx interface{}, in interface{}, opts ...interface{}) *DNSServiceClient_Query_Call { + return &DNSServiceClient_Query_Call{Call: _e.mock.On("Query", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *DNSServiceClient_Query_Call) Run(run func(ctx context.Context, in *pbdns.QueryRequest, opts ...grpc.CallOption)) *DNSServiceClient_Query_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbdns.QueryRequest), variadicArgs...) + }) + return _c +} + +func (_c *DNSServiceClient_Query_Call) Return(_a0 *pbdns.QueryResponse, _a1 error) *DNSServiceClient_Query_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DNSServiceClient_Query_Call) RunAndReturn(run func(context.Context, *pbdns.QueryRequest, ...grpc.CallOption) (*pbdns.QueryResponse, error)) *DNSServiceClient_Query_Call { + _c.Call.Return(run) + return _c +} + +// NewDNSServiceClient creates a new instance of DNSServiceClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDNSServiceClient(t interface { + mock.TestingT + Cleanup(func()) +}) *DNSServiceClient { + mock := &DNSServiceClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbdns/mock_DNSServiceServer.go b/grpcmocks/proto-public/pbdns/mock_DNSServiceServer.go new file mode 100644 index 000000000000..eceb76755811 --- /dev/null +++ b/grpcmocks/proto-public/pbdns/mock_DNSServiceServer.go @@ -0,0 +1,96 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbdns + +import ( + context "context" + + pbdns "github.com/hashicorp/consul/proto-public/pbdns" + mock "github.com/stretchr/testify/mock" +) + +// DNSServiceServer is an autogenerated mock type for the DNSServiceServer type +type DNSServiceServer struct { + mock.Mock +} + +type DNSServiceServer_Expecter struct { + mock *mock.Mock +} + +func (_m *DNSServiceServer) EXPECT() *DNSServiceServer_Expecter { + return &DNSServiceServer_Expecter{mock: &_m.Mock} +} + +// Query provides a mock function with given fields: _a0, _a1 +func (_m *DNSServiceServer) Query(_a0 context.Context, _a1 *pbdns.QueryRequest) (*pbdns.QueryResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Query") + } + + var r0 *pbdns.QueryResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbdns.QueryRequest) (*pbdns.QueryResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbdns.QueryRequest) *pbdns.QueryResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbdns.QueryResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbdns.QueryRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DNSServiceServer_Query_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Query' +type DNSServiceServer_Query_Call struct { + *mock.Call +} + +// Query is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbdns.QueryRequest +func (_e *DNSServiceServer_Expecter) Query(_a0 interface{}, _a1 interface{}) *DNSServiceServer_Query_Call { + return &DNSServiceServer_Query_Call{Call: _e.mock.On("Query", _a0, _a1)} +} + +func (_c *DNSServiceServer_Query_Call) Run(run func(_a0 context.Context, _a1 *pbdns.QueryRequest)) *DNSServiceServer_Query_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbdns.QueryRequest)) + }) + return _c +} + +func (_c *DNSServiceServer_Query_Call) Return(_a0 *pbdns.QueryResponse, _a1 error) *DNSServiceServer_Query_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DNSServiceServer_Query_Call) RunAndReturn(run func(context.Context, *pbdns.QueryRequest) (*pbdns.QueryResponse, error)) *DNSServiceServer_Query_Call { + _c.Call.Return(run) + return _c +} + +// NewDNSServiceServer creates a new instance of DNSServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDNSServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *DNSServiceServer { + mock := &DNSServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbdns/mock_UnsafeDNSServiceServer.go b/grpcmocks/proto-public/pbdns/mock_UnsafeDNSServiceServer.go new file mode 100644 index 000000000000..06a1f30e70e2 --- /dev/null +++ b/grpcmocks/proto-public/pbdns/mock_UnsafeDNSServiceServer.go @@ -0,0 +1,64 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbdns + +import mock "github.com/stretchr/testify/mock" + +// UnsafeDNSServiceServer is an autogenerated mock type for the UnsafeDNSServiceServer type +type UnsafeDNSServiceServer struct { + mock.Mock +} + +type UnsafeDNSServiceServer_Expecter struct { + mock *mock.Mock +} + +func (_m *UnsafeDNSServiceServer) EXPECT() *UnsafeDNSServiceServer_Expecter { + return &UnsafeDNSServiceServer_Expecter{mock: &_m.Mock} +} + +// mustEmbedUnimplementedDNSServiceServer provides a mock function with given fields: +func (_m *UnsafeDNSServiceServer) mustEmbedUnimplementedDNSServiceServer() { + _m.Called() +} + +// UnsafeDNSServiceServer_mustEmbedUnimplementedDNSServiceServer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'mustEmbedUnimplementedDNSServiceServer' +type UnsafeDNSServiceServer_mustEmbedUnimplementedDNSServiceServer_Call struct { + *mock.Call +} + +// mustEmbedUnimplementedDNSServiceServer is a helper method to define mock.On call +func (_e *UnsafeDNSServiceServer_Expecter) mustEmbedUnimplementedDNSServiceServer() *UnsafeDNSServiceServer_mustEmbedUnimplementedDNSServiceServer_Call { + return &UnsafeDNSServiceServer_mustEmbedUnimplementedDNSServiceServer_Call{Call: _e.mock.On("mustEmbedUnimplementedDNSServiceServer")} +} + +func (_c *UnsafeDNSServiceServer_mustEmbedUnimplementedDNSServiceServer_Call) Run(run func()) *UnsafeDNSServiceServer_mustEmbedUnimplementedDNSServiceServer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *UnsafeDNSServiceServer_mustEmbedUnimplementedDNSServiceServer_Call) Return() *UnsafeDNSServiceServer_mustEmbedUnimplementedDNSServiceServer_Call { + _c.Call.Return() + return _c +} + +func (_c *UnsafeDNSServiceServer_mustEmbedUnimplementedDNSServiceServer_Call) RunAndReturn(run func()) *UnsafeDNSServiceServer_mustEmbedUnimplementedDNSServiceServer_Call { + _c.Call.Return(run) + return _c +} + +// NewUnsafeDNSServiceServer creates a new instance of UnsafeDNSServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewUnsafeDNSServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *UnsafeDNSServiceServer { + mock := &UnsafeDNSServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbresource/mock_ResourceServiceClient.go b/grpcmocks/proto-public/pbresource/mock_ResourceServiceClient.go new file mode 100644 index 000000000000..fc49e0f50d57 --- /dev/null +++ b/grpcmocks/proto-public/pbresource/mock_ResourceServiceClient.go @@ -0,0 +1,632 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbresource + +import ( + context "context" + + grpc "google.golang.org/grpc" + + mock "github.com/stretchr/testify/mock" + + pbresource "github.com/hashicorp/consul/proto-public/pbresource" +) + +// ResourceServiceClient is an autogenerated mock type for the ResourceServiceClient type +type ResourceServiceClient struct { + mock.Mock +} + +type ResourceServiceClient_Expecter struct { + mock *mock.Mock +} + +func (_m *ResourceServiceClient) EXPECT() *ResourceServiceClient_Expecter { + return &ResourceServiceClient_Expecter{mock: &_m.Mock} +} + +// Delete provides a mock function with given fields: ctx, in, opts +func (_m *ResourceServiceClient) Delete(ctx context.Context, in *pbresource.DeleteRequest, opts ...grpc.CallOption) (*pbresource.DeleteResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Delete") + } + + var r0 *pbresource.DeleteResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.DeleteRequest, ...grpc.CallOption) (*pbresource.DeleteResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.DeleteRequest, ...grpc.CallOption) *pbresource.DeleteResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.DeleteResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.DeleteRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceClient_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' +type ResourceServiceClient_Delete_Call struct { + *mock.Call +} + +// Delete is a helper method to define mock.On call +// - ctx context.Context +// - in *pbresource.DeleteRequest +// - opts ...grpc.CallOption +func (_e *ResourceServiceClient_Expecter) Delete(ctx interface{}, in interface{}, opts ...interface{}) *ResourceServiceClient_Delete_Call { + return &ResourceServiceClient_Delete_Call{Call: _e.mock.On("Delete", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ResourceServiceClient_Delete_Call) Run(run func(ctx context.Context, in *pbresource.DeleteRequest, opts ...grpc.CallOption)) *ResourceServiceClient_Delete_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbresource.DeleteRequest), variadicArgs...) + }) + return _c +} + +func (_c *ResourceServiceClient_Delete_Call) Return(_a0 *pbresource.DeleteResponse, _a1 error) *ResourceServiceClient_Delete_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceClient_Delete_Call) RunAndReturn(run func(context.Context, *pbresource.DeleteRequest, ...grpc.CallOption) (*pbresource.DeleteResponse, error)) *ResourceServiceClient_Delete_Call { + _c.Call.Return(run) + return _c +} + +// List provides a mock function with given fields: ctx, in, opts +func (_m *ResourceServiceClient) List(ctx context.Context, in *pbresource.ListRequest, opts ...grpc.CallOption) (*pbresource.ListResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for List") + } + + var r0 *pbresource.ListResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.ListRequest, ...grpc.CallOption) (*pbresource.ListResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.ListRequest, ...grpc.CallOption) *pbresource.ListResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.ListResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.ListRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceClient_List_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'List' +type ResourceServiceClient_List_Call struct { + *mock.Call +} + +// List is a helper method to define mock.On call +// - ctx context.Context +// - in *pbresource.ListRequest +// - opts ...grpc.CallOption +func (_e *ResourceServiceClient_Expecter) List(ctx interface{}, in interface{}, opts ...interface{}) *ResourceServiceClient_List_Call { + return &ResourceServiceClient_List_Call{Call: _e.mock.On("List", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ResourceServiceClient_List_Call) Run(run func(ctx context.Context, in *pbresource.ListRequest, opts ...grpc.CallOption)) *ResourceServiceClient_List_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbresource.ListRequest), variadicArgs...) + }) + return _c +} + +func (_c *ResourceServiceClient_List_Call) Return(_a0 *pbresource.ListResponse, _a1 error) *ResourceServiceClient_List_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceClient_List_Call) RunAndReturn(run func(context.Context, *pbresource.ListRequest, ...grpc.CallOption) (*pbresource.ListResponse, error)) *ResourceServiceClient_List_Call { + _c.Call.Return(run) + return _c +} + +// ListByOwner provides a mock function with given fields: ctx, in, opts +func (_m *ResourceServiceClient) ListByOwner(ctx context.Context, in *pbresource.ListByOwnerRequest, opts ...grpc.CallOption) (*pbresource.ListByOwnerResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for ListByOwner") + } + + var r0 *pbresource.ListByOwnerResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.ListByOwnerRequest, ...grpc.CallOption) (*pbresource.ListByOwnerResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.ListByOwnerRequest, ...grpc.CallOption) *pbresource.ListByOwnerResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.ListByOwnerResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.ListByOwnerRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceClient_ListByOwner_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListByOwner' +type ResourceServiceClient_ListByOwner_Call struct { + *mock.Call +} + +// ListByOwner is a helper method to define mock.On call +// - ctx context.Context +// - in *pbresource.ListByOwnerRequest +// - opts ...grpc.CallOption +func (_e *ResourceServiceClient_Expecter) ListByOwner(ctx interface{}, in interface{}, opts ...interface{}) *ResourceServiceClient_ListByOwner_Call { + return &ResourceServiceClient_ListByOwner_Call{Call: _e.mock.On("ListByOwner", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ResourceServiceClient_ListByOwner_Call) Run(run func(ctx context.Context, in *pbresource.ListByOwnerRequest, opts ...grpc.CallOption)) *ResourceServiceClient_ListByOwner_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbresource.ListByOwnerRequest), variadicArgs...) + }) + return _c +} + +func (_c *ResourceServiceClient_ListByOwner_Call) Return(_a0 *pbresource.ListByOwnerResponse, _a1 error) *ResourceServiceClient_ListByOwner_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceClient_ListByOwner_Call) RunAndReturn(run func(context.Context, *pbresource.ListByOwnerRequest, ...grpc.CallOption) (*pbresource.ListByOwnerResponse, error)) *ResourceServiceClient_ListByOwner_Call { + _c.Call.Return(run) + return _c +} + +// MutateAndValidate provides a mock function with given fields: ctx, in, opts +func (_m *ResourceServiceClient) MutateAndValidate(ctx context.Context, in *pbresource.MutateAndValidateRequest, opts ...grpc.CallOption) (*pbresource.MutateAndValidateResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for MutateAndValidate") + } + + var r0 *pbresource.MutateAndValidateResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.MutateAndValidateRequest, ...grpc.CallOption) (*pbresource.MutateAndValidateResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.MutateAndValidateRequest, ...grpc.CallOption) *pbresource.MutateAndValidateResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.MutateAndValidateResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.MutateAndValidateRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceClient_MutateAndValidate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MutateAndValidate' +type ResourceServiceClient_MutateAndValidate_Call struct { + *mock.Call +} + +// MutateAndValidate is a helper method to define mock.On call +// - ctx context.Context +// - in *pbresource.MutateAndValidateRequest +// - opts ...grpc.CallOption +func (_e *ResourceServiceClient_Expecter) MutateAndValidate(ctx interface{}, in interface{}, opts ...interface{}) *ResourceServiceClient_MutateAndValidate_Call { + return &ResourceServiceClient_MutateAndValidate_Call{Call: _e.mock.On("MutateAndValidate", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ResourceServiceClient_MutateAndValidate_Call) Run(run func(ctx context.Context, in *pbresource.MutateAndValidateRequest, opts ...grpc.CallOption)) *ResourceServiceClient_MutateAndValidate_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbresource.MutateAndValidateRequest), variadicArgs...) + }) + return _c +} + +func (_c *ResourceServiceClient_MutateAndValidate_Call) Return(_a0 *pbresource.MutateAndValidateResponse, _a1 error) *ResourceServiceClient_MutateAndValidate_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceClient_MutateAndValidate_Call) RunAndReturn(run func(context.Context, *pbresource.MutateAndValidateRequest, ...grpc.CallOption) (*pbresource.MutateAndValidateResponse, error)) *ResourceServiceClient_MutateAndValidate_Call { + _c.Call.Return(run) + return _c +} + +// Read provides a mock function with given fields: ctx, in, opts +func (_m *ResourceServiceClient) Read(ctx context.Context, in *pbresource.ReadRequest, opts ...grpc.CallOption) (*pbresource.ReadResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Read") + } + + var r0 *pbresource.ReadResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.ReadRequest, ...grpc.CallOption) (*pbresource.ReadResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.ReadRequest, ...grpc.CallOption) *pbresource.ReadResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.ReadResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.ReadRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceClient_Read_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Read' +type ResourceServiceClient_Read_Call struct { + *mock.Call +} + +// Read is a helper method to define mock.On call +// - ctx context.Context +// - in *pbresource.ReadRequest +// - opts ...grpc.CallOption +func (_e *ResourceServiceClient_Expecter) Read(ctx interface{}, in interface{}, opts ...interface{}) *ResourceServiceClient_Read_Call { + return &ResourceServiceClient_Read_Call{Call: _e.mock.On("Read", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ResourceServiceClient_Read_Call) Run(run func(ctx context.Context, in *pbresource.ReadRequest, opts ...grpc.CallOption)) *ResourceServiceClient_Read_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbresource.ReadRequest), variadicArgs...) + }) + return _c +} + +func (_c *ResourceServiceClient_Read_Call) Return(_a0 *pbresource.ReadResponse, _a1 error) *ResourceServiceClient_Read_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceClient_Read_Call) RunAndReturn(run func(context.Context, *pbresource.ReadRequest, ...grpc.CallOption) (*pbresource.ReadResponse, error)) *ResourceServiceClient_Read_Call { + _c.Call.Return(run) + return _c +} + +// WatchList provides a mock function with given fields: ctx, in, opts +func (_m *ResourceServiceClient) WatchList(ctx context.Context, in *pbresource.WatchListRequest, opts ...grpc.CallOption) (pbresource.ResourceService_WatchListClient, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for WatchList") + } + + var r0 pbresource.ResourceService_WatchListClient + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.WatchListRequest, ...grpc.CallOption) (pbresource.ResourceService_WatchListClient, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.WatchListRequest, ...grpc.CallOption) pbresource.ResourceService_WatchListClient); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pbresource.ResourceService_WatchListClient) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.WatchListRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceClient_WatchList_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchList' +type ResourceServiceClient_WatchList_Call struct { + *mock.Call +} + +// WatchList is a helper method to define mock.On call +// - ctx context.Context +// - in *pbresource.WatchListRequest +// - opts ...grpc.CallOption +func (_e *ResourceServiceClient_Expecter) WatchList(ctx interface{}, in interface{}, opts ...interface{}) *ResourceServiceClient_WatchList_Call { + return &ResourceServiceClient_WatchList_Call{Call: _e.mock.On("WatchList", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ResourceServiceClient_WatchList_Call) Run(run func(ctx context.Context, in *pbresource.WatchListRequest, opts ...grpc.CallOption)) *ResourceServiceClient_WatchList_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbresource.WatchListRequest), variadicArgs...) + }) + return _c +} + +func (_c *ResourceServiceClient_WatchList_Call) Return(_a0 pbresource.ResourceService_WatchListClient, _a1 error) *ResourceServiceClient_WatchList_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceClient_WatchList_Call) RunAndReturn(run func(context.Context, *pbresource.WatchListRequest, ...grpc.CallOption) (pbresource.ResourceService_WatchListClient, error)) *ResourceServiceClient_WatchList_Call { + _c.Call.Return(run) + return _c +} + +// Write provides a mock function with given fields: ctx, in, opts +func (_m *ResourceServiceClient) Write(ctx context.Context, in *pbresource.WriteRequest, opts ...grpc.CallOption) (*pbresource.WriteResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Write") + } + + var r0 *pbresource.WriteResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.WriteRequest, ...grpc.CallOption) (*pbresource.WriteResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.WriteRequest, ...grpc.CallOption) *pbresource.WriteResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.WriteResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.WriteRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceClient_Write_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Write' +type ResourceServiceClient_Write_Call struct { + *mock.Call +} + +// Write is a helper method to define mock.On call +// - ctx context.Context +// - in *pbresource.WriteRequest +// - opts ...grpc.CallOption +func (_e *ResourceServiceClient_Expecter) Write(ctx interface{}, in interface{}, opts ...interface{}) *ResourceServiceClient_Write_Call { + return &ResourceServiceClient_Write_Call{Call: _e.mock.On("Write", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ResourceServiceClient_Write_Call) Run(run func(ctx context.Context, in *pbresource.WriteRequest, opts ...grpc.CallOption)) *ResourceServiceClient_Write_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbresource.WriteRequest), variadicArgs...) + }) + return _c +} + +func (_c *ResourceServiceClient_Write_Call) Return(_a0 *pbresource.WriteResponse, _a1 error) *ResourceServiceClient_Write_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceClient_Write_Call) RunAndReturn(run func(context.Context, *pbresource.WriteRequest, ...grpc.CallOption) (*pbresource.WriteResponse, error)) *ResourceServiceClient_Write_Call { + _c.Call.Return(run) + return _c +} + +// WriteStatus provides a mock function with given fields: ctx, in, opts +func (_m *ResourceServiceClient) WriteStatus(ctx context.Context, in *pbresource.WriteStatusRequest, opts ...grpc.CallOption) (*pbresource.WriteStatusResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for WriteStatus") + } + + var r0 *pbresource.WriteStatusResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.WriteStatusRequest, ...grpc.CallOption) (*pbresource.WriteStatusResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.WriteStatusRequest, ...grpc.CallOption) *pbresource.WriteStatusResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.WriteStatusResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.WriteStatusRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceClient_WriteStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WriteStatus' +type ResourceServiceClient_WriteStatus_Call struct { + *mock.Call +} + +// WriteStatus is a helper method to define mock.On call +// - ctx context.Context +// - in *pbresource.WriteStatusRequest +// - opts ...grpc.CallOption +func (_e *ResourceServiceClient_Expecter) WriteStatus(ctx interface{}, in interface{}, opts ...interface{}) *ResourceServiceClient_WriteStatus_Call { + return &ResourceServiceClient_WriteStatus_Call{Call: _e.mock.On("WriteStatus", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ResourceServiceClient_WriteStatus_Call) Run(run func(ctx context.Context, in *pbresource.WriteStatusRequest, opts ...grpc.CallOption)) *ResourceServiceClient_WriteStatus_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbresource.WriteStatusRequest), variadicArgs...) + }) + return _c +} + +func (_c *ResourceServiceClient_WriteStatus_Call) Return(_a0 *pbresource.WriteStatusResponse, _a1 error) *ResourceServiceClient_WriteStatus_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceClient_WriteStatus_Call) RunAndReturn(run func(context.Context, *pbresource.WriteStatusRequest, ...grpc.CallOption) (*pbresource.WriteStatusResponse, error)) *ResourceServiceClient_WriteStatus_Call { + _c.Call.Return(run) + return _c +} + +// NewResourceServiceClient creates a new instance of ResourceServiceClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewResourceServiceClient(t interface { + mock.TestingT + Cleanup(func()) +}) *ResourceServiceClient { + mock := &ResourceServiceClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbresource/mock_ResourceServiceServer.go b/grpcmocks/proto-public/pbresource/mock_ResourceServiceServer.go new file mode 100644 index 000000000000..3ed07e777dee --- /dev/null +++ b/grpcmocks/proto-public/pbresource/mock_ResourceServiceServer.go @@ -0,0 +1,497 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbresource + +import ( + context "context" + + pbresource "github.com/hashicorp/consul/proto-public/pbresource" + mock "github.com/stretchr/testify/mock" +) + +// ResourceServiceServer is an autogenerated mock type for the ResourceServiceServer type +type ResourceServiceServer struct { + mock.Mock +} + +type ResourceServiceServer_Expecter struct { + mock *mock.Mock +} + +func (_m *ResourceServiceServer) EXPECT() *ResourceServiceServer_Expecter { + return &ResourceServiceServer_Expecter{mock: &_m.Mock} +} + +// Delete provides a mock function with given fields: _a0, _a1 +func (_m *ResourceServiceServer) Delete(_a0 context.Context, _a1 *pbresource.DeleteRequest) (*pbresource.DeleteResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Delete") + } + + var r0 *pbresource.DeleteResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.DeleteRequest) (*pbresource.DeleteResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.DeleteRequest) *pbresource.DeleteResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.DeleteResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.DeleteRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceServer_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' +type ResourceServiceServer_Delete_Call struct { + *mock.Call +} + +// Delete is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbresource.DeleteRequest +func (_e *ResourceServiceServer_Expecter) Delete(_a0 interface{}, _a1 interface{}) *ResourceServiceServer_Delete_Call { + return &ResourceServiceServer_Delete_Call{Call: _e.mock.On("Delete", _a0, _a1)} +} + +func (_c *ResourceServiceServer_Delete_Call) Run(run func(_a0 context.Context, _a1 *pbresource.DeleteRequest)) *ResourceServiceServer_Delete_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbresource.DeleteRequest)) + }) + return _c +} + +func (_c *ResourceServiceServer_Delete_Call) Return(_a0 *pbresource.DeleteResponse, _a1 error) *ResourceServiceServer_Delete_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceServer_Delete_Call) RunAndReturn(run func(context.Context, *pbresource.DeleteRequest) (*pbresource.DeleteResponse, error)) *ResourceServiceServer_Delete_Call { + _c.Call.Return(run) + return _c +} + +// List provides a mock function with given fields: _a0, _a1 +func (_m *ResourceServiceServer) List(_a0 context.Context, _a1 *pbresource.ListRequest) (*pbresource.ListResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for List") + } + + var r0 *pbresource.ListResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.ListRequest) (*pbresource.ListResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.ListRequest) *pbresource.ListResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.ListResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.ListRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceServer_List_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'List' +type ResourceServiceServer_List_Call struct { + *mock.Call +} + +// List is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbresource.ListRequest +func (_e *ResourceServiceServer_Expecter) List(_a0 interface{}, _a1 interface{}) *ResourceServiceServer_List_Call { + return &ResourceServiceServer_List_Call{Call: _e.mock.On("List", _a0, _a1)} +} + +func (_c *ResourceServiceServer_List_Call) Run(run func(_a0 context.Context, _a1 *pbresource.ListRequest)) *ResourceServiceServer_List_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbresource.ListRequest)) + }) + return _c +} + +func (_c *ResourceServiceServer_List_Call) Return(_a0 *pbresource.ListResponse, _a1 error) *ResourceServiceServer_List_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceServer_List_Call) RunAndReturn(run func(context.Context, *pbresource.ListRequest) (*pbresource.ListResponse, error)) *ResourceServiceServer_List_Call { + _c.Call.Return(run) + return _c +} + +// ListByOwner provides a mock function with given fields: _a0, _a1 +func (_m *ResourceServiceServer) ListByOwner(_a0 context.Context, _a1 *pbresource.ListByOwnerRequest) (*pbresource.ListByOwnerResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for ListByOwner") + } + + var r0 *pbresource.ListByOwnerResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.ListByOwnerRequest) (*pbresource.ListByOwnerResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.ListByOwnerRequest) *pbresource.ListByOwnerResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.ListByOwnerResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.ListByOwnerRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceServer_ListByOwner_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListByOwner' +type ResourceServiceServer_ListByOwner_Call struct { + *mock.Call +} + +// ListByOwner is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbresource.ListByOwnerRequest +func (_e *ResourceServiceServer_Expecter) ListByOwner(_a0 interface{}, _a1 interface{}) *ResourceServiceServer_ListByOwner_Call { + return &ResourceServiceServer_ListByOwner_Call{Call: _e.mock.On("ListByOwner", _a0, _a1)} +} + +func (_c *ResourceServiceServer_ListByOwner_Call) Run(run func(_a0 context.Context, _a1 *pbresource.ListByOwnerRequest)) *ResourceServiceServer_ListByOwner_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbresource.ListByOwnerRequest)) + }) + return _c +} + +func (_c *ResourceServiceServer_ListByOwner_Call) Return(_a0 *pbresource.ListByOwnerResponse, _a1 error) *ResourceServiceServer_ListByOwner_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceServer_ListByOwner_Call) RunAndReturn(run func(context.Context, *pbresource.ListByOwnerRequest) (*pbresource.ListByOwnerResponse, error)) *ResourceServiceServer_ListByOwner_Call { + _c.Call.Return(run) + return _c +} + +// MutateAndValidate provides a mock function with given fields: _a0, _a1 +func (_m *ResourceServiceServer) MutateAndValidate(_a0 context.Context, _a1 *pbresource.MutateAndValidateRequest) (*pbresource.MutateAndValidateResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for MutateAndValidate") + } + + var r0 *pbresource.MutateAndValidateResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.MutateAndValidateRequest) (*pbresource.MutateAndValidateResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.MutateAndValidateRequest) *pbresource.MutateAndValidateResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.MutateAndValidateResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.MutateAndValidateRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceServer_MutateAndValidate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MutateAndValidate' +type ResourceServiceServer_MutateAndValidate_Call struct { + *mock.Call +} + +// MutateAndValidate is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbresource.MutateAndValidateRequest +func (_e *ResourceServiceServer_Expecter) MutateAndValidate(_a0 interface{}, _a1 interface{}) *ResourceServiceServer_MutateAndValidate_Call { + return &ResourceServiceServer_MutateAndValidate_Call{Call: _e.mock.On("MutateAndValidate", _a0, _a1)} +} + +func (_c *ResourceServiceServer_MutateAndValidate_Call) Run(run func(_a0 context.Context, _a1 *pbresource.MutateAndValidateRequest)) *ResourceServiceServer_MutateAndValidate_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbresource.MutateAndValidateRequest)) + }) + return _c +} + +func (_c *ResourceServiceServer_MutateAndValidate_Call) Return(_a0 *pbresource.MutateAndValidateResponse, _a1 error) *ResourceServiceServer_MutateAndValidate_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceServer_MutateAndValidate_Call) RunAndReturn(run func(context.Context, *pbresource.MutateAndValidateRequest) (*pbresource.MutateAndValidateResponse, error)) *ResourceServiceServer_MutateAndValidate_Call { + _c.Call.Return(run) + return _c +} + +// Read provides a mock function with given fields: _a0, _a1 +func (_m *ResourceServiceServer) Read(_a0 context.Context, _a1 *pbresource.ReadRequest) (*pbresource.ReadResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Read") + } + + var r0 *pbresource.ReadResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.ReadRequest) (*pbresource.ReadResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.ReadRequest) *pbresource.ReadResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.ReadResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.ReadRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceServer_Read_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Read' +type ResourceServiceServer_Read_Call struct { + *mock.Call +} + +// Read is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbresource.ReadRequest +func (_e *ResourceServiceServer_Expecter) Read(_a0 interface{}, _a1 interface{}) *ResourceServiceServer_Read_Call { + return &ResourceServiceServer_Read_Call{Call: _e.mock.On("Read", _a0, _a1)} +} + +func (_c *ResourceServiceServer_Read_Call) Run(run func(_a0 context.Context, _a1 *pbresource.ReadRequest)) *ResourceServiceServer_Read_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbresource.ReadRequest)) + }) + return _c +} + +func (_c *ResourceServiceServer_Read_Call) Return(_a0 *pbresource.ReadResponse, _a1 error) *ResourceServiceServer_Read_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceServer_Read_Call) RunAndReturn(run func(context.Context, *pbresource.ReadRequest) (*pbresource.ReadResponse, error)) *ResourceServiceServer_Read_Call { + _c.Call.Return(run) + return _c +} + +// WatchList provides a mock function with given fields: _a0, _a1 +func (_m *ResourceServiceServer) WatchList(_a0 *pbresource.WatchListRequest, _a1 pbresource.ResourceService_WatchListServer) error { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for WatchList") + } + + var r0 error + if rf, ok := ret.Get(0).(func(*pbresource.WatchListRequest, pbresource.ResourceService_WatchListServer) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ResourceServiceServer_WatchList_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchList' +type ResourceServiceServer_WatchList_Call struct { + *mock.Call +} + +// WatchList is a helper method to define mock.On call +// - _a0 *pbresource.WatchListRequest +// - _a1 pbresource.ResourceService_WatchListServer +func (_e *ResourceServiceServer_Expecter) WatchList(_a0 interface{}, _a1 interface{}) *ResourceServiceServer_WatchList_Call { + return &ResourceServiceServer_WatchList_Call{Call: _e.mock.On("WatchList", _a0, _a1)} +} + +func (_c *ResourceServiceServer_WatchList_Call) Run(run func(_a0 *pbresource.WatchListRequest, _a1 pbresource.ResourceService_WatchListServer)) *ResourceServiceServer_WatchList_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbresource.WatchListRequest), args[1].(pbresource.ResourceService_WatchListServer)) + }) + return _c +} + +func (_c *ResourceServiceServer_WatchList_Call) Return(_a0 error) *ResourceServiceServer_WatchList_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceServiceServer_WatchList_Call) RunAndReturn(run func(*pbresource.WatchListRequest, pbresource.ResourceService_WatchListServer) error) *ResourceServiceServer_WatchList_Call { + _c.Call.Return(run) + return _c +} + +// Write provides a mock function with given fields: _a0, _a1 +func (_m *ResourceServiceServer) Write(_a0 context.Context, _a1 *pbresource.WriteRequest) (*pbresource.WriteResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Write") + } + + var r0 *pbresource.WriteResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.WriteRequest) (*pbresource.WriteResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.WriteRequest) *pbresource.WriteResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.WriteResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.WriteRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceServer_Write_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Write' +type ResourceServiceServer_Write_Call struct { + *mock.Call +} + +// Write is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbresource.WriteRequest +func (_e *ResourceServiceServer_Expecter) Write(_a0 interface{}, _a1 interface{}) *ResourceServiceServer_Write_Call { + return &ResourceServiceServer_Write_Call{Call: _e.mock.On("Write", _a0, _a1)} +} + +func (_c *ResourceServiceServer_Write_Call) Run(run func(_a0 context.Context, _a1 *pbresource.WriteRequest)) *ResourceServiceServer_Write_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbresource.WriteRequest)) + }) + return _c +} + +func (_c *ResourceServiceServer_Write_Call) Return(_a0 *pbresource.WriteResponse, _a1 error) *ResourceServiceServer_Write_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceServer_Write_Call) RunAndReturn(run func(context.Context, *pbresource.WriteRequest) (*pbresource.WriteResponse, error)) *ResourceServiceServer_Write_Call { + _c.Call.Return(run) + return _c +} + +// WriteStatus provides a mock function with given fields: _a0, _a1 +func (_m *ResourceServiceServer) WriteStatus(_a0 context.Context, _a1 *pbresource.WriteStatusRequest) (*pbresource.WriteStatusResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for WriteStatus") + } + + var r0 *pbresource.WriteStatusResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.WriteStatusRequest) (*pbresource.WriteStatusResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbresource.WriteStatusRequest) *pbresource.WriteStatusResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.WriteStatusResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbresource.WriteStatusRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceServiceServer_WriteStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WriteStatus' +type ResourceServiceServer_WriteStatus_Call struct { + *mock.Call +} + +// WriteStatus is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *pbresource.WriteStatusRequest +func (_e *ResourceServiceServer_Expecter) WriteStatus(_a0 interface{}, _a1 interface{}) *ResourceServiceServer_WriteStatus_Call { + return &ResourceServiceServer_WriteStatus_Call{Call: _e.mock.On("WriteStatus", _a0, _a1)} +} + +func (_c *ResourceServiceServer_WriteStatus_Call) Run(run func(_a0 context.Context, _a1 *pbresource.WriteStatusRequest)) *ResourceServiceServer_WriteStatus_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*pbresource.WriteStatusRequest)) + }) + return _c +} + +func (_c *ResourceServiceServer_WriteStatus_Call) Return(_a0 *pbresource.WriteStatusResponse, _a1 error) *ResourceServiceServer_WriteStatus_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceServiceServer_WriteStatus_Call) RunAndReturn(run func(context.Context, *pbresource.WriteStatusRequest) (*pbresource.WriteStatusResponse, error)) *ResourceServiceServer_WriteStatus_Call { + _c.Call.Return(run) + return _c +} + +// NewResourceServiceServer creates a new instance of ResourceServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewResourceServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *ResourceServiceServer { + mock := &ResourceServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbresource/mock_ResourceService_WatchListClient.go b/grpcmocks/proto-public/pbresource/mock_ResourceService_WatchListClient.go new file mode 100644 index 000000000000..60df7d5cc6ec --- /dev/null +++ b/grpcmocks/proto-public/pbresource/mock_ResourceService_WatchListClient.go @@ -0,0 +1,384 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbresource + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + metadata "google.golang.org/grpc/metadata" + + pbresource "github.com/hashicorp/consul/proto-public/pbresource" +) + +// ResourceService_WatchListClient is an autogenerated mock type for the ResourceService_WatchListClient type +type ResourceService_WatchListClient struct { + mock.Mock +} + +type ResourceService_WatchListClient_Expecter struct { + mock *mock.Mock +} + +func (_m *ResourceService_WatchListClient) EXPECT() *ResourceService_WatchListClient_Expecter { + return &ResourceService_WatchListClient_Expecter{mock: &_m.Mock} +} + +// CloseSend provides a mock function with given fields: +func (_m *ResourceService_WatchListClient) CloseSend() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for CloseSend") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ResourceService_WatchListClient_CloseSend_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CloseSend' +type ResourceService_WatchListClient_CloseSend_Call struct { + *mock.Call +} + +// CloseSend is a helper method to define mock.On call +func (_e *ResourceService_WatchListClient_Expecter) CloseSend() *ResourceService_WatchListClient_CloseSend_Call { + return &ResourceService_WatchListClient_CloseSend_Call{Call: _e.mock.On("CloseSend")} +} + +func (_c *ResourceService_WatchListClient_CloseSend_Call) Run(run func()) *ResourceService_WatchListClient_CloseSend_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ResourceService_WatchListClient_CloseSend_Call) Return(_a0 error) *ResourceService_WatchListClient_CloseSend_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceService_WatchListClient_CloseSend_Call) RunAndReturn(run func() error) *ResourceService_WatchListClient_CloseSend_Call { + _c.Call.Return(run) + return _c +} + +// Context provides a mock function with given fields: +func (_m *ResourceService_WatchListClient) Context() context.Context { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Context") + } + + var r0 context.Context + if rf, ok := ret.Get(0).(func() context.Context); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(context.Context) + } + } + + return r0 +} + +// ResourceService_WatchListClient_Context_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Context' +type ResourceService_WatchListClient_Context_Call struct { + *mock.Call +} + +// Context is a helper method to define mock.On call +func (_e *ResourceService_WatchListClient_Expecter) Context() *ResourceService_WatchListClient_Context_Call { + return &ResourceService_WatchListClient_Context_Call{Call: _e.mock.On("Context")} +} + +func (_c *ResourceService_WatchListClient_Context_Call) Run(run func()) *ResourceService_WatchListClient_Context_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ResourceService_WatchListClient_Context_Call) Return(_a0 context.Context) *ResourceService_WatchListClient_Context_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceService_WatchListClient_Context_Call) RunAndReturn(run func() context.Context) *ResourceService_WatchListClient_Context_Call { + _c.Call.Return(run) + return _c +} + +// Header provides a mock function with given fields: +func (_m *ResourceService_WatchListClient) Header() (metadata.MD, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Header") + } + + var r0 metadata.MD + var r1 error + if rf, ok := ret.Get(0).(func() (metadata.MD, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() metadata.MD); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(metadata.MD) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceService_WatchListClient_Header_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Header' +type ResourceService_WatchListClient_Header_Call struct { + *mock.Call +} + +// Header is a helper method to define mock.On call +func (_e *ResourceService_WatchListClient_Expecter) Header() *ResourceService_WatchListClient_Header_Call { + return &ResourceService_WatchListClient_Header_Call{Call: _e.mock.On("Header")} +} + +func (_c *ResourceService_WatchListClient_Header_Call) Run(run func()) *ResourceService_WatchListClient_Header_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ResourceService_WatchListClient_Header_Call) Return(_a0 metadata.MD, _a1 error) *ResourceService_WatchListClient_Header_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceService_WatchListClient_Header_Call) RunAndReturn(run func() (metadata.MD, error)) *ResourceService_WatchListClient_Header_Call { + _c.Call.Return(run) + return _c +} + +// Recv provides a mock function with given fields: +func (_m *ResourceService_WatchListClient) Recv() (*pbresource.WatchEvent, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Recv") + } + + var r0 *pbresource.WatchEvent + var r1 error + if rf, ok := ret.Get(0).(func() (*pbresource.WatchEvent, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() *pbresource.WatchEvent); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.WatchEvent) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResourceService_WatchListClient_Recv_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Recv' +type ResourceService_WatchListClient_Recv_Call struct { + *mock.Call +} + +// Recv is a helper method to define mock.On call +func (_e *ResourceService_WatchListClient_Expecter) Recv() *ResourceService_WatchListClient_Recv_Call { + return &ResourceService_WatchListClient_Recv_Call{Call: _e.mock.On("Recv")} +} + +func (_c *ResourceService_WatchListClient_Recv_Call) Run(run func()) *ResourceService_WatchListClient_Recv_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ResourceService_WatchListClient_Recv_Call) Return(_a0 *pbresource.WatchEvent, _a1 error) *ResourceService_WatchListClient_Recv_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ResourceService_WatchListClient_Recv_Call) RunAndReturn(run func() (*pbresource.WatchEvent, error)) *ResourceService_WatchListClient_Recv_Call { + _c.Call.Return(run) + return _c +} + +// RecvMsg provides a mock function with given fields: m +func (_m *ResourceService_WatchListClient) RecvMsg(m interface{}) error { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for RecvMsg") + } + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ResourceService_WatchListClient_RecvMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RecvMsg' +type ResourceService_WatchListClient_RecvMsg_Call struct { + *mock.Call +} + +// RecvMsg is a helper method to define mock.On call +// - m interface{} +func (_e *ResourceService_WatchListClient_Expecter) RecvMsg(m interface{}) *ResourceService_WatchListClient_RecvMsg_Call { + return &ResourceService_WatchListClient_RecvMsg_Call{Call: _e.mock.On("RecvMsg", m)} +} + +func (_c *ResourceService_WatchListClient_RecvMsg_Call) Run(run func(m interface{})) *ResourceService_WatchListClient_RecvMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *ResourceService_WatchListClient_RecvMsg_Call) Return(_a0 error) *ResourceService_WatchListClient_RecvMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceService_WatchListClient_RecvMsg_Call) RunAndReturn(run func(interface{}) error) *ResourceService_WatchListClient_RecvMsg_Call { + _c.Call.Return(run) + return _c +} + +// SendMsg provides a mock function with given fields: m +func (_m *ResourceService_WatchListClient) SendMsg(m interface{}) error { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for SendMsg") + } + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ResourceService_WatchListClient_SendMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendMsg' +type ResourceService_WatchListClient_SendMsg_Call struct { + *mock.Call +} + +// SendMsg is a helper method to define mock.On call +// - m interface{} +func (_e *ResourceService_WatchListClient_Expecter) SendMsg(m interface{}) *ResourceService_WatchListClient_SendMsg_Call { + return &ResourceService_WatchListClient_SendMsg_Call{Call: _e.mock.On("SendMsg", m)} +} + +func (_c *ResourceService_WatchListClient_SendMsg_Call) Run(run func(m interface{})) *ResourceService_WatchListClient_SendMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *ResourceService_WatchListClient_SendMsg_Call) Return(_a0 error) *ResourceService_WatchListClient_SendMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceService_WatchListClient_SendMsg_Call) RunAndReturn(run func(interface{}) error) *ResourceService_WatchListClient_SendMsg_Call { + _c.Call.Return(run) + return _c +} + +// Trailer provides a mock function with given fields: +func (_m *ResourceService_WatchListClient) Trailer() metadata.MD { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Trailer") + } + + var r0 metadata.MD + if rf, ok := ret.Get(0).(func() metadata.MD); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(metadata.MD) + } + } + + return r0 +} + +// ResourceService_WatchListClient_Trailer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Trailer' +type ResourceService_WatchListClient_Trailer_Call struct { + *mock.Call +} + +// Trailer is a helper method to define mock.On call +func (_e *ResourceService_WatchListClient_Expecter) Trailer() *ResourceService_WatchListClient_Trailer_Call { + return &ResourceService_WatchListClient_Trailer_Call{Call: _e.mock.On("Trailer")} +} + +func (_c *ResourceService_WatchListClient_Trailer_Call) Run(run func()) *ResourceService_WatchListClient_Trailer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ResourceService_WatchListClient_Trailer_Call) Return(_a0 metadata.MD) *ResourceService_WatchListClient_Trailer_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceService_WatchListClient_Trailer_Call) RunAndReturn(run func() metadata.MD) *ResourceService_WatchListClient_Trailer_Call { + _c.Call.Return(run) + return _c +} + +// NewResourceService_WatchListClient creates a new instance of ResourceService_WatchListClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewResourceService_WatchListClient(t interface { + mock.TestingT + Cleanup(func()) +}) *ResourceService_WatchListClient { + mock := &ResourceService_WatchListClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbresource/mock_ResourceService_WatchListServer.go b/grpcmocks/proto-public/pbresource/mock_ResourceService_WatchListServer.go new file mode 100644 index 000000000000..df2158cb6483 --- /dev/null +++ b/grpcmocks/proto-public/pbresource/mock_ResourceService_WatchListServer.go @@ -0,0 +1,349 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbresource + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + metadata "google.golang.org/grpc/metadata" + + pbresource "github.com/hashicorp/consul/proto-public/pbresource" +) + +// ResourceService_WatchListServer is an autogenerated mock type for the ResourceService_WatchListServer type +type ResourceService_WatchListServer struct { + mock.Mock +} + +type ResourceService_WatchListServer_Expecter struct { + mock *mock.Mock +} + +func (_m *ResourceService_WatchListServer) EXPECT() *ResourceService_WatchListServer_Expecter { + return &ResourceService_WatchListServer_Expecter{mock: &_m.Mock} +} + +// Context provides a mock function with given fields: +func (_m *ResourceService_WatchListServer) Context() context.Context { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Context") + } + + var r0 context.Context + if rf, ok := ret.Get(0).(func() context.Context); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(context.Context) + } + } + + return r0 +} + +// ResourceService_WatchListServer_Context_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Context' +type ResourceService_WatchListServer_Context_Call struct { + *mock.Call +} + +// Context is a helper method to define mock.On call +func (_e *ResourceService_WatchListServer_Expecter) Context() *ResourceService_WatchListServer_Context_Call { + return &ResourceService_WatchListServer_Context_Call{Call: _e.mock.On("Context")} +} + +func (_c *ResourceService_WatchListServer_Context_Call) Run(run func()) *ResourceService_WatchListServer_Context_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ResourceService_WatchListServer_Context_Call) Return(_a0 context.Context) *ResourceService_WatchListServer_Context_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceService_WatchListServer_Context_Call) RunAndReturn(run func() context.Context) *ResourceService_WatchListServer_Context_Call { + _c.Call.Return(run) + return _c +} + +// RecvMsg provides a mock function with given fields: m +func (_m *ResourceService_WatchListServer) RecvMsg(m interface{}) error { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for RecvMsg") + } + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ResourceService_WatchListServer_RecvMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RecvMsg' +type ResourceService_WatchListServer_RecvMsg_Call struct { + *mock.Call +} + +// RecvMsg is a helper method to define mock.On call +// - m interface{} +func (_e *ResourceService_WatchListServer_Expecter) RecvMsg(m interface{}) *ResourceService_WatchListServer_RecvMsg_Call { + return &ResourceService_WatchListServer_RecvMsg_Call{Call: _e.mock.On("RecvMsg", m)} +} + +func (_c *ResourceService_WatchListServer_RecvMsg_Call) Run(run func(m interface{})) *ResourceService_WatchListServer_RecvMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *ResourceService_WatchListServer_RecvMsg_Call) Return(_a0 error) *ResourceService_WatchListServer_RecvMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceService_WatchListServer_RecvMsg_Call) RunAndReturn(run func(interface{}) error) *ResourceService_WatchListServer_RecvMsg_Call { + _c.Call.Return(run) + return _c +} + +// Send provides a mock function with given fields: _a0 +func (_m *ResourceService_WatchListServer) Send(_a0 *pbresource.WatchEvent) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Send") + } + + var r0 error + if rf, ok := ret.Get(0).(func(*pbresource.WatchEvent) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ResourceService_WatchListServer_Send_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Send' +type ResourceService_WatchListServer_Send_Call struct { + *mock.Call +} + +// Send is a helper method to define mock.On call +// - _a0 *pbresource.WatchEvent +func (_e *ResourceService_WatchListServer_Expecter) Send(_a0 interface{}) *ResourceService_WatchListServer_Send_Call { + return &ResourceService_WatchListServer_Send_Call{Call: _e.mock.On("Send", _a0)} +} + +func (_c *ResourceService_WatchListServer_Send_Call) Run(run func(_a0 *pbresource.WatchEvent)) *ResourceService_WatchListServer_Send_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbresource.WatchEvent)) + }) + return _c +} + +func (_c *ResourceService_WatchListServer_Send_Call) Return(_a0 error) *ResourceService_WatchListServer_Send_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceService_WatchListServer_Send_Call) RunAndReturn(run func(*pbresource.WatchEvent) error) *ResourceService_WatchListServer_Send_Call { + _c.Call.Return(run) + return _c +} + +// SendHeader provides a mock function with given fields: _a0 +func (_m *ResourceService_WatchListServer) SendHeader(_a0 metadata.MD) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for SendHeader") + } + + var r0 error + if rf, ok := ret.Get(0).(func(metadata.MD) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ResourceService_WatchListServer_SendHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendHeader' +type ResourceService_WatchListServer_SendHeader_Call struct { + *mock.Call +} + +// SendHeader is a helper method to define mock.On call +// - _a0 metadata.MD +func (_e *ResourceService_WatchListServer_Expecter) SendHeader(_a0 interface{}) *ResourceService_WatchListServer_SendHeader_Call { + return &ResourceService_WatchListServer_SendHeader_Call{Call: _e.mock.On("SendHeader", _a0)} +} + +func (_c *ResourceService_WatchListServer_SendHeader_Call) Run(run func(_a0 metadata.MD)) *ResourceService_WatchListServer_SendHeader_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(metadata.MD)) + }) + return _c +} + +func (_c *ResourceService_WatchListServer_SendHeader_Call) Return(_a0 error) *ResourceService_WatchListServer_SendHeader_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceService_WatchListServer_SendHeader_Call) RunAndReturn(run func(metadata.MD) error) *ResourceService_WatchListServer_SendHeader_Call { + _c.Call.Return(run) + return _c +} + +// SendMsg provides a mock function with given fields: m +func (_m *ResourceService_WatchListServer) SendMsg(m interface{}) error { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for SendMsg") + } + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ResourceService_WatchListServer_SendMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendMsg' +type ResourceService_WatchListServer_SendMsg_Call struct { + *mock.Call +} + +// SendMsg is a helper method to define mock.On call +// - m interface{} +func (_e *ResourceService_WatchListServer_Expecter) SendMsg(m interface{}) *ResourceService_WatchListServer_SendMsg_Call { + return &ResourceService_WatchListServer_SendMsg_Call{Call: _e.mock.On("SendMsg", m)} +} + +func (_c *ResourceService_WatchListServer_SendMsg_Call) Run(run func(m interface{})) *ResourceService_WatchListServer_SendMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *ResourceService_WatchListServer_SendMsg_Call) Return(_a0 error) *ResourceService_WatchListServer_SendMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceService_WatchListServer_SendMsg_Call) RunAndReturn(run func(interface{}) error) *ResourceService_WatchListServer_SendMsg_Call { + _c.Call.Return(run) + return _c +} + +// SetHeader provides a mock function with given fields: _a0 +func (_m *ResourceService_WatchListServer) SetHeader(_a0 metadata.MD) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for SetHeader") + } + + var r0 error + if rf, ok := ret.Get(0).(func(metadata.MD) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ResourceService_WatchListServer_SetHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetHeader' +type ResourceService_WatchListServer_SetHeader_Call struct { + *mock.Call +} + +// SetHeader is a helper method to define mock.On call +// - _a0 metadata.MD +func (_e *ResourceService_WatchListServer_Expecter) SetHeader(_a0 interface{}) *ResourceService_WatchListServer_SetHeader_Call { + return &ResourceService_WatchListServer_SetHeader_Call{Call: _e.mock.On("SetHeader", _a0)} +} + +func (_c *ResourceService_WatchListServer_SetHeader_Call) Run(run func(_a0 metadata.MD)) *ResourceService_WatchListServer_SetHeader_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(metadata.MD)) + }) + return _c +} + +func (_c *ResourceService_WatchListServer_SetHeader_Call) Return(_a0 error) *ResourceService_WatchListServer_SetHeader_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceService_WatchListServer_SetHeader_Call) RunAndReturn(run func(metadata.MD) error) *ResourceService_WatchListServer_SetHeader_Call { + _c.Call.Return(run) + return _c +} + +// SetTrailer provides a mock function with given fields: _a0 +func (_m *ResourceService_WatchListServer) SetTrailer(_a0 metadata.MD) { + _m.Called(_a0) +} + +// ResourceService_WatchListServer_SetTrailer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetTrailer' +type ResourceService_WatchListServer_SetTrailer_Call struct { + *mock.Call +} + +// SetTrailer is a helper method to define mock.On call +// - _a0 metadata.MD +func (_e *ResourceService_WatchListServer_Expecter) SetTrailer(_a0 interface{}) *ResourceService_WatchListServer_SetTrailer_Call { + return &ResourceService_WatchListServer_SetTrailer_Call{Call: _e.mock.On("SetTrailer", _a0)} +} + +func (_c *ResourceService_WatchListServer_SetTrailer_Call) Run(run func(_a0 metadata.MD)) *ResourceService_WatchListServer_SetTrailer_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(metadata.MD)) + }) + return _c +} + +func (_c *ResourceService_WatchListServer_SetTrailer_Call) Return() *ResourceService_WatchListServer_SetTrailer_Call { + _c.Call.Return() + return _c +} + +func (_c *ResourceService_WatchListServer_SetTrailer_Call) RunAndReturn(run func(metadata.MD)) *ResourceService_WatchListServer_SetTrailer_Call { + _c.Call.Return(run) + return _c +} + +// NewResourceService_WatchListServer creates a new instance of ResourceService_WatchListServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewResourceService_WatchListServer(t interface { + mock.TestingT + Cleanup(func()) +}) *ResourceService_WatchListServer { + mock := &ResourceService_WatchListServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbresource/mock_UnsafeResourceServiceServer.go b/grpcmocks/proto-public/pbresource/mock_UnsafeResourceServiceServer.go new file mode 100644 index 000000000000..59e1aef0c7e0 --- /dev/null +++ b/grpcmocks/proto-public/pbresource/mock_UnsafeResourceServiceServer.go @@ -0,0 +1,64 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbresource + +import mock "github.com/stretchr/testify/mock" + +// UnsafeResourceServiceServer is an autogenerated mock type for the UnsafeResourceServiceServer type +type UnsafeResourceServiceServer struct { + mock.Mock +} + +type UnsafeResourceServiceServer_Expecter struct { + mock *mock.Mock +} + +func (_m *UnsafeResourceServiceServer) EXPECT() *UnsafeResourceServiceServer_Expecter { + return &UnsafeResourceServiceServer_Expecter{mock: &_m.Mock} +} + +// mustEmbedUnimplementedResourceServiceServer provides a mock function with given fields: +func (_m *UnsafeResourceServiceServer) mustEmbedUnimplementedResourceServiceServer() { + _m.Called() +} + +// UnsafeResourceServiceServer_mustEmbedUnimplementedResourceServiceServer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'mustEmbedUnimplementedResourceServiceServer' +type UnsafeResourceServiceServer_mustEmbedUnimplementedResourceServiceServer_Call struct { + *mock.Call +} + +// mustEmbedUnimplementedResourceServiceServer is a helper method to define mock.On call +func (_e *UnsafeResourceServiceServer_Expecter) mustEmbedUnimplementedResourceServiceServer() *UnsafeResourceServiceServer_mustEmbedUnimplementedResourceServiceServer_Call { + return &UnsafeResourceServiceServer_mustEmbedUnimplementedResourceServiceServer_Call{Call: _e.mock.On("mustEmbedUnimplementedResourceServiceServer")} +} + +func (_c *UnsafeResourceServiceServer_mustEmbedUnimplementedResourceServiceServer_Call) Run(run func()) *UnsafeResourceServiceServer_mustEmbedUnimplementedResourceServiceServer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *UnsafeResourceServiceServer_mustEmbedUnimplementedResourceServiceServer_Call) Return() *UnsafeResourceServiceServer_mustEmbedUnimplementedResourceServiceServer_Call { + _c.Call.Return() + return _c +} + +func (_c *UnsafeResourceServiceServer_mustEmbedUnimplementedResourceServiceServer_Call) RunAndReturn(run func()) *UnsafeResourceServiceServer_mustEmbedUnimplementedResourceServiceServer_Call { + _c.Call.Return(run) + return _c +} + +// NewUnsafeResourceServiceServer creates a new instance of UnsafeResourceServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewUnsafeResourceServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *UnsafeResourceServiceServer { + mock := &UnsafeResourceServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbresource/mock_isWatchEvent_Event.go b/grpcmocks/proto-public/pbresource/mock_isWatchEvent_Event.go new file mode 100644 index 000000000000..1a9acfd5293b --- /dev/null +++ b/grpcmocks/proto-public/pbresource/mock_isWatchEvent_Event.go @@ -0,0 +1,64 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbresource + +import mock "github.com/stretchr/testify/mock" + +// isWatchEvent_Event is an autogenerated mock type for the isWatchEvent_Event type +type isWatchEvent_Event struct { + mock.Mock +} + +type isWatchEvent_Event_Expecter struct { + mock *mock.Mock +} + +func (_m *isWatchEvent_Event) EXPECT() *isWatchEvent_Event_Expecter { + return &isWatchEvent_Event_Expecter{mock: &_m.Mock} +} + +// isWatchEvent_Event provides a mock function with given fields: +func (_m *isWatchEvent_Event) isWatchEvent_Event() { + _m.Called() +} + +// isWatchEvent_Event_isWatchEvent_Event_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'isWatchEvent_Event' +type isWatchEvent_Event_isWatchEvent_Event_Call struct { + *mock.Call +} + +// isWatchEvent_Event is a helper method to define mock.On call +func (_e *isWatchEvent_Event_Expecter) isWatchEvent_Event() *isWatchEvent_Event_isWatchEvent_Event_Call { + return &isWatchEvent_Event_isWatchEvent_Event_Call{Call: _e.mock.On("isWatchEvent_Event")} +} + +func (_c *isWatchEvent_Event_isWatchEvent_Event_Call) Run(run func()) *isWatchEvent_Event_isWatchEvent_Event_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *isWatchEvent_Event_isWatchEvent_Event_Call) Return() *isWatchEvent_Event_isWatchEvent_Event_Call { + _c.Call.Return() + return _c +} + +func (_c *isWatchEvent_Event_isWatchEvent_Event_Call) RunAndReturn(run func()) *isWatchEvent_Event_isWatchEvent_Event_Call { + _c.Call.Return(run) + return _c +} + +// newIsWatchEvent_Event creates a new instance of isWatchEvent_Event. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newIsWatchEvent_Event(t interface { + mock.TestingT + Cleanup(func()) +}) *isWatchEvent_Event { + mock := &isWatchEvent_Event{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbserverdiscovery/mock_ServerDiscoveryServiceClient.go b/grpcmocks/proto-public/pbserverdiscovery/mock_ServerDiscoveryServiceClient.go new file mode 100644 index 000000000000..8ec2fca4ccf5 --- /dev/null +++ b/grpcmocks/proto-public/pbserverdiscovery/mock_ServerDiscoveryServiceClient.go @@ -0,0 +1,114 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbserverdiscovery + +import ( + context "context" + + grpc "google.golang.org/grpc" + + mock "github.com/stretchr/testify/mock" + + pbserverdiscovery "github.com/hashicorp/consul/proto-public/pbserverdiscovery" +) + +// ServerDiscoveryServiceClient is an autogenerated mock type for the ServerDiscoveryServiceClient type +type ServerDiscoveryServiceClient struct { + mock.Mock +} + +type ServerDiscoveryServiceClient_Expecter struct { + mock *mock.Mock +} + +func (_m *ServerDiscoveryServiceClient) EXPECT() *ServerDiscoveryServiceClient_Expecter { + return &ServerDiscoveryServiceClient_Expecter{mock: &_m.Mock} +} + +// WatchServers provides a mock function with given fields: ctx, in, opts +func (_m *ServerDiscoveryServiceClient) WatchServers(ctx context.Context, in *pbserverdiscovery.WatchServersRequest, opts ...grpc.CallOption) (pbserverdiscovery.ServerDiscoveryService_WatchServersClient, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for WatchServers") + } + + var r0 pbserverdiscovery.ServerDiscoveryService_WatchServersClient + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *pbserverdiscovery.WatchServersRequest, ...grpc.CallOption) (pbserverdiscovery.ServerDiscoveryService_WatchServersClient, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *pbserverdiscovery.WatchServersRequest, ...grpc.CallOption) pbserverdiscovery.ServerDiscoveryService_WatchServersClient); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pbserverdiscovery.ServerDiscoveryService_WatchServersClient) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *pbserverdiscovery.WatchServersRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ServerDiscoveryServiceClient_WatchServers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchServers' +type ServerDiscoveryServiceClient_WatchServers_Call struct { + *mock.Call +} + +// WatchServers is a helper method to define mock.On call +// - ctx context.Context +// - in *pbserverdiscovery.WatchServersRequest +// - opts ...grpc.CallOption +func (_e *ServerDiscoveryServiceClient_Expecter) WatchServers(ctx interface{}, in interface{}, opts ...interface{}) *ServerDiscoveryServiceClient_WatchServers_Call { + return &ServerDiscoveryServiceClient_WatchServers_Call{Call: _e.mock.On("WatchServers", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *ServerDiscoveryServiceClient_WatchServers_Call) Run(run func(ctx context.Context, in *pbserverdiscovery.WatchServersRequest, opts ...grpc.CallOption)) *ServerDiscoveryServiceClient_WatchServers_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*pbserverdiscovery.WatchServersRequest), variadicArgs...) + }) + return _c +} + +func (_c *ServerDiscoveryServiceClient_WatchServers_Call) Return(_a0 pbserverdiscovery.ServerDiscoveryService_WatchServersClient, _a1 error) *ServerDiscoveryServiceClient_WatchServers_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ServerDiscoveryServiceClient_WatchServers_Call) RunAndReturn(run func(context.Context, *pbserverdiscovery.WatchServersRequest, ...grpc.CallOption) (pbserverdiscovery.ServerDiscoveryService_WatchServersClient, error)) *ServerDiscoveryServiceClient_WatchServers_Call { + _c.Call.Return(run) + return _c +} + +// NewServerDiscoveryServiceClient creates a new instance of ServerDiscoveryServiceClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewServerDiscoveryServiceClient(t interface { + mock.TestingT + Cleanup(func()) +}) *ServerDiscoveryServiceClient { + mock := &ServerDiscoveryServiceClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbserverdiscovery/mock_ServerDiscoveryServiceServer.go b/grpcmocks/proto-public/pbserverdiscovery/mock_ServerDiscoveryServiceServer.go new file mode 100644 index 000000000000..b61f066e96f7 --- /dev/null +++ b/grpcmocks/proto-public/pbserverdiscovery/mock_ServerDiscoveryServiceServer.go @@ -0,0 +1,82 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbserverdiscovery + +import ( + pbserverdiscovery "github.com/hashicorp/consul/proto-public/pbserverdiscovery" + mock "github.com/stretchr/testify/mock" +) + +// ServerDiscoveryServiceServer is an autogenerated mock type for the ServerDiscoveryServiceServer type +type ServerDiscoveryServiceServer struct { + mock.Mock +} + +type ServerDiscoveryServiceServer_Expecter struct { + mock *mock.Mock +} + +func (_m *ServerDiscoveryServiceServer) EXPECT() *ServerDiscoveryServiceServer_Expecter { + return &ServerDiscoveryServiceServer_Expecter{mock: &_m.Mock} +} + +// WatchServers provides a mock function with given fields: _a0, _a1 +func (_m *ServerDiscoveryServiceServer) WatchServers(_a0 *pbserverdiscovery.WatchServersRequest, _a1 pbserverdiscovery.ServerDiscoveryService_WatchServersServer) error { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for WatchServers") + } + + var r0 error + if rf, ok := ret.Get(0).(func(*pbserverdiscovery.WatchServersRequest, pbserverdiscovery.ServerDiscoveryService_WatchServersServer) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ServerDiscoveryServiceServer_WatchServers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchServers' +type ServerDiscoveryServiceServer_WatchServers_Call struct { + *mock.Call +} + +// WatchServers is a helper method to define mock.On call +// - _a0 *pbserverdiscovery.WatchServersRequest +// - _a1 pbserverdiscovery.ServerDiscoveryService_WatchServersServer +func (_e *ServerDiscoveryServiceServer_Expecter) WatchServers(_a0 interface{}, _a1 interface{}) *ServerDiscoveryServiceServer_WatchServers_Call { + return &ServerDiscoveryServiceServer_WatchServers_Call{Call: _e.mock.On("WatchServers", _a0, _a1)} +} + +func (_c *ServerDiscoveryServiceServer_WatchServers_Call) Run(run func(_a0 *pbserverdiscovery.WatchServersRequest, _a1 pbserverdiscovery.ServerDiscoveryService_WatchServersServer)) *ServerDiscoveryServiceServer_WatchServers_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbserverdiscovery.WatchServersRequest), args[1].(pbserverdiscovery.ServerDiscoveryService_WatchServersServer)) + }) + return _c +} + +func (_c *ServerDiscoveryServiceServer_WatchServers_Call) Return(_a0 error) *ServerDiscoveryServiceServer_WatchServers_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDiscoveryServiceServer_WatchServers_Call) RunAndReturn(run func(*pbserverdiscovery.WatchServersRequest, pbserverdiscovery.ServerDiscoveryService_WatchServersServer) error) *ServerDiscoveryServiceServer_WatchServers_Call { + _c.Call.Return(run) + return _c +} + +// NewServerDiscoveryServiceServer creates a new instance of ServerDiscoveryServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewServerDiscoveryServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *ServerDiscoveryServiceServer { + mock := &ServerDiscoveryServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbserverdiscovery/mock_ServerDiscoveryService_WatchServersClient.go b/grpcmocks/proto-public/pbserverdiscovery/mock_ServerDiscoveryService_WatchServersClient.go new file mode 100644 index 000000000000..eb397adadef5 --- /dev/null +++ b/grpcmocks/proto-public/pbserverdiscovery/mock_ServerDiscoveryService_WatchServersClient.go @@ -0,0 +1,384 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbserverdiscovery + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + metadata "google.golang.org/grpc/metadata" + + pbserverdiscovery "github.com/hashicorp/consul/proto-public/pbserverdiscovery" +) + +// ServerDiscoveryService_WatchServersClient is an autogenerated mock type for the ServerDiscoveryService_WatchServersClient type +type ServerDiscoveryService_WatchServersClient struct { + mock.Mock +} + +type ServerDiscoveryService_WatchServersClient_Expecter struct { + mock *mock.Mock +} + +func (_m *ServerDiscoveryService_WatchServersClient) EXPECT() *ServerDiscoveryService_WatchServersClient_Expecter { + return &ServerDiscoveryService_WatchServersClient_Expecter{mock: &_m.Mock} +} + +// CloseSend provides a mock function with given fields: +func (_m *ServerDiscoveryService_WatchServersClient) CloseSend() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for CloseSend") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ServerDiscoveryService_WatchServersClient_CloseSend_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CloseSend' +type ServerDiscoveryService_WatchServersClient_CloseSend_Call struct { + *mock.Call +} + +// CloseSend is a helper method to define mock.On call +func (_e *ServerDiscoveryService_WatchServersClient_Expecter) CloseSend() *ServerDiscoveryService_WatchServersClient_CloseSend_Call { + return &ServerDiscoveryService_WatchServersClient_CloseSend_Call{Call: _e.mock.On("CloseSend")} +} + +func (_c *ServerDiscoveryService_WatchServersClient_CloseSend_Call) Run(run func()) *ServerDiscoveryService_WatchServersClient_CloseSend_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_CloseSend_Call) Return(_a0 error) *ServerDiscoveryService_WatchServersClient_CloseSend_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_CloseSend_Call) RunAndReturn(run func() error) *ServerDiscoveryService_WatchServersClient_CloseSend_Call { + _c.Call.Return(run) + return _c +} + +// Context provides a mock function with given fields: +func (_m *ServerDiscoveryService_WatchServersClient) Context() context.Context { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Context") + } + + var r0 context.Context + if rf, ok := ret.Get(0).(func() context.Context); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(context.Context) + } + } + + return r0 +} + +// ServerDiscoveryService_WatchServersClient_Context_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Context' +type ServerDiscoveryService_WatchServersClient_Context_Call struct { + *mock.Call +} + +// Context is a helper method to define mock.On call +func (_e *ServerDiscoveryService_WatchServersClient_Expecter) Context() *ServerDiscoveryService_WatchServersClient_Context_Call { + return &ServerDiscoveryService_WatchServersClient_Context_Call{Call: _e.mock.On("Context")} +} + +func (_c *ServerDiscoveryService_WatchServersClient_Context_Call) Run(run func()) *ServerDiscoveryService_WatchServersClient_Context_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_Context_Call) Return(_a0 context.Context) *ServerDiscoveryService_WatchServersClient_Context_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_Context_Call) RunAndReturn(run func() context.Context) *ServerDiscoveryService_WatchServersClient_Context_Call { + _c.Call.Return(run) + return _c +} + +// Header provides a mock function with given fields: +func (_m *ServerDiscoveryService_WatchServersClient) Header() (metadata.MD, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Header") + } + + var r0 metadata.MD + var r1 error + if rf, ok := ret.Get(0).(func() (metadata.MD, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() metadata.MD); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(metadata.MD) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ServerDiscoveryService_WatchServersClient_Header_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Header' +type ServerDiscoveryService_WatchServersClient_Header_Call struct { + *mock.Call +} + +// Header is a helper method to define mock.On call +func (_e *ServerDiscoveryService_WatchServersClient_Expecter) Header() *ServerDiscoveryService_WatchServersClient_Header_Call { + return &ServerDiscoveryService_WatchServersClient_Header_Call{Call: _e.mock.On("Header")} +} + +func (_c *ServerDiscoveryService_WatchServersClient_Header_Call) Run(run func()) *ServerDiscoveryService_WatchServersClient_Header_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_Header_Call) Return(_a0 metadata.MD, _a1 error) *ServerDiscoveryService_WatchServersClient_Header_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_Header_Call) RunAndReturn(run func() (metadata.MD, error)) *ServerDiscoveryService_WatchServersClient_Header_Call { + _c.Call.Return(run) + return _c +} + +// Recv provides a mock function with given fields: +func (_m *ServerDiscoveryService_WatchServersClient) Recv() (*pbserverdiscovery.WatchServersResponse, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Recv") + } + + var r0 *pbserverdiscovery.WatchServersResponse + var r1 error + if rf, ok := ret.Get(0).(func() (*pbserverdiscovery.WatchServersResponse, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() *pbserverdiscovery.WatchServersResponse); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbserverdiscovery.WatchServersResponse) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ServerDiscoveryService_WatchServersClient_Recv_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Recv' +type ServerDiscoveryService_WatchServersClient_Recv_Call struct { + *mock.Call +} + +// Recv is a helper method to define mock.On call +func (_e *ServerDiscoveryService_WatchServersClient_Expecter) Recv() *ServerDiscoveryService_WatchServersClient_Recv_Call { + return &ServerDiscoveryService_WatchServersClient_Recv_Call{Call: _e.mock.On("Recv")} +} + +func (_c *ServerDiscoveryService_WatchServersClient_Recv_Call) Run(run func()) *ServerDiscoveryService_WatchServersClient_Recv_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_Recv_Call) Return(_a0 *pbserverdiscovery.WatchServersResponse, _a1 error) *ServerDiscoveryService_WatchServersClient_Recv_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_Recv_Call) RunAndReturn(run func() (*pbserverdiscovery.WatchServersResponse, error)) *ServerDiscoveryService_WatchServersClient_Recv_Call { + _c.Call.Return(run) + return _c +} + +// RecvMsg provides a mock function with given fields: m +func (_m *ServerDiscoveryService_WatchServersClient) RecvMsg(m interface{}) error { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for RecvMsg") + } + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ServerDiscoveryService_WatchServersClient_RecvMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RecvMsg' +type ServerDiscoveryService_WatchServersClient_RecvMsg_Call struct { + *mock.Call +} + +// RecvMsg is a helper method to define mock.On call +// - m interface{} +func (_e *ServerDiscoveryService_WatchServersClient_Expecter) RecvMsg(m interface{}) *ServerDiscoveryService_WatchServersClient_RecvMsg_Call { + return &ServerDiscoveryService_WatchServersClient_RecvMsg_Call{Call: _e.mock.On("RecvMsg", m)} +} + +func (_c *ServerDiscoveryService_WatchServersClient_RecvMsg_Call) Run(run func(m interface{})) *ServerDiscoveryService_WatchServersClient_RecvMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_RecvMsg_Call) Return(_a0 error) *ServerDiscoveryService_WatchServersClient_RecvMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_RecvMsg_Call) RunAndReturn(run func(interface{}) error) *ServerDiscoveryService_WatchServersClient_RecvMsg_Call { + _c.Call.Return(run) + return _c +} + +// SendMsg provides a mock function with given fields: m +func (_m *ServerDiscoveryService_WatchServersClient) SendMsg(m interface{}) error { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for SendMsg") + } + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ServerDiscoveryService_WatchServersClient_SendMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendMsg' +type ServerDiscoveryService_WatchServersClient_SendMsg_Call struct { + *mock.Call +} + +// SendMsg is a helper method to define mock.On call +// - m interface{} +func (_e *ServerDiscoveryService_WatchServersClient_Expecter) SendMsg(m interface{}) *ServerDiscoveryService_WatchServersClient_SendMsg_Call { + return &ServerDiscoveryService_WatchServersClient_SendMsg_Call{Call: _e.mock.On("SendMsg", m)} +} + +func (_c *ServerDiscoveryService_WatchServersClient_SendMsg_Call) Run(run func(m interface{})) *ServerDiscoveryService_WatchServersClient_SendMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_SendMsg_Call) Return(_a0 error) *ServerDiscoveryService_WatchServersClient_SendMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_SendMsg_Call) RunAndReturn(run func(interface{}) error) *ServerDiscoveryService_WatchServersClient_SendMsg_Call { + _c.Call.Return(run) + return _c +} + +// Trailer provides a mock function with given fields: +func (_m *ServerDiscoveryService_WatchServersClient) Trailer() metadata.MD { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Trailer") + } + + var r0 metadata.MD + if rf, ok := ret.Get(0).(func() metadata.MD); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(metadata.MD) + } + } + + return r0 +} + +// ServerDiscoveryService_WatchServersClient_Trailer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Trailer' +type ServerDiscoveryService_WatchServersClient_Trailer_Call struct { + *mock.Call +} + +// Trailer is a helper method to define mock.On call +func (_e *ServerDiscoveryService_WatchServersClient_Expecter) Trailer() *ServerDiscoveryService_WatchServersClient_Trailer_Call { + return &ServerDiscoveryService_WatchServersClient_Trailer_Call{Call: _e.mock.On("Trailer")} +} + +func (_c *ServerDiscoveryService_WatchServersClient_Trailer_Call) Run(run func()) *ServerDiscoveryService_WatchServersClient_Trailer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_Trailer_Call) Return(_a0 metadata.MD) *ServerDiscoveryService_WatchServersClient_Trailer_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersClient_Trailer_Call) RunAndReturn(run func() metadata.MD) *ServerDiscoveryService_WatchServersClient_Trailer_Call { + _c.Call.Return(run) + return _c +} + +// NewServerDiscoveryService_WatchServersClient creates a new instance of ServerDiscoveryService_WatchServersClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewServerDiscoveryService_WatchServersClient(t interface { + mock.TestingT + Cleanup(func()) +}) *ServerDiscoveryService_WatchServersClient { + mock := &ServerDiscoveryService_WatchServersClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbserverdiscovery/mock_ServerDiscoveryService_WatchServersServer.go b/grpcmocks/proto-public/pbserverdiscovery/mock_ServerDiscoveryService_WatchServersServer.go new file mode 100644 index 000000000000..ea6234ed5dd9 --- /dev/null +++ b/grpcmocks/proto-public/pbserverdiscovery/mock_ServerDiscoveryService_WatchServersServer.go @@ -0,0 +1,349 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbserverdiscovery + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + metadata "google.golang.org/grpc/metadata" + + pbserverdiscovery "github.com/hashicorp/consul/proto-public/pbserverdiscovery" +) + +// ServerDiscoveryService_WatchServersServer is an autogenerated mock type for the ServerDiscoveryService_WatchServersServer type +type ServerDiscoveryService_WatchServersServer struct { + mock.Mock +} + +type ServerDiscoveryService_WatchServersServer_Expecter struct { + mock *mock.Mock +} + +func (_m *ServerDiscoveryService_WatchServersServer) EXPECT() *ServerDiscoveryService_WatchServersServer_Expecter { + return &ServerDiscoveryService_WatchServersServer_Expecter{mock: &_m.Mock} +} + +// Context provides a mock function with given fields: +func (_m *ServerDiscoveryService_WatchServersServer) Context() context.Context { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Context") + } + + var r0 context.Context + if rf, ok := ret.Get(0).(func() context.Context); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(context.Context) + } + } + + return r0 +} + +// ServerDiscoveryService_WatchServersServer_Context_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Context' +type ServerDiscoveryService_WatchServersServer_Context_Call struct { + *mock.Call +} + +// Context is a helper method to define mock.On call +func (_e *ServerDiscoveryService_WatchServersServer_Expecter) Context() *ServerDiscoveryService_WatchServersServer_Context_Call { + return &ServerDiscoveryService_WatchServersServer_Context_Call{Call: _e.mock.On("Context")} +} + +func (_c *ServerDiscoveryService_WatchServersServer_Context_Call) Run(run func()) *ServerDiscoveryService_WatchServersServer_Context_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_Context_Call) Return(_a0 context.Context) *ServerDiscoveryService_WatchServersServer_Context_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_Context_Call) RunAndReturn(run func() context.Context) *ServerDiscoveryService_WatchServersServer_Context_Call { + _c.Call.Return(run) + return _c +} + +// RecvMsg provides a mock function with given fields: m +func (_m *ServerDiscoveryService_WatchServersServer) RecvMsg(m interface{}) error { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for RecvMsg") + } + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ServerDiscoveryService_WatchServersServer_RecvMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RecvMsg' +type ServerDiscoveryService_WatchServersServer_RecvMsg_Call struct { + *mock.Call +} + +// RecvMsg is a helper method to define mock.On call +// - m interface{} +func (_e *ServerDiscoveryService_WatchServersServer_Expecter) RecvMsg(m interface{}) *ServerDiscoveryService_WatchServersServer_RecvMsg_Call { + return &ServerDiscoveryService_WatchServersServer_RecvMsg_Call{Call: _e.mock.On("RecvMsg", m)} +} + +func (_c *ServerDiscoveryService_WatchServersServer_RecvMsg_Call) Run(run func(m interface{})) *ServerDiscoveryService_WatchServersServer_RecvMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_RecvMsg_Call) Return(_a0 error) *ServerDiscoveryService_WatchServersServer_RecvMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_RecvMsg_Call) RunAndReturn(run func(interface{}) error) *ServerDiscoveryService_WatchServersServer_RecvMsg_Call { + _c.Call.Return(run) + return _c +} + +// Send provides a mock function with given fields: _a0 +func (_m *ServerDiscoveryService_WatchServersServer) Send(_a0 *pbserverdiscovery.WatchServersResponse) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Send") + } + + var r0 error + if rf, ok := ret.Get(0).(func(*pbserverdiscovery.WatchServersResponse) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ServerDiscoveryService_WatchServersServer_Send_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Send' +type ServerDiscoveryService_WatchServersServer_Send_Call struct { + *mock.Call +} + +// Send is a helper method to define mock.On call +// - _a0 *pbserverdiscovery.WatchServersResponse +func (_e *ServerDiscoveryService_WatchServersServer_Expecter) Send(_a0 interface{}) *ServerDiscoveryService_WatchServersServer_Send_Call { + return &ServerDiscoveryService_WatchServersServer_Send_Call{Call: _e.mock.On("Send", _a0)} +} + +func (_c *ServerDiscoveryService_WatchServersServer_Send_Call) Run(run func(_a0 *pbserverdiscovery.WatchServersResponse)) *ServerDiscoveryService_WatchServersServer_Send_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbserverdiscovery.WatchServersResponse)) + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_Send_Call) Return(_a0 error) *ServerDiscoveryService_WatchServersServer_Send_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_Send_Call) RunAndReturn(run func(*pbserverdiscovery.WatchServersResponse) error) *ServerDiscoveryService_WatchServersServer_Send_Call { + _c.Call.Return(run) + return _c +} + +// SendHeader provides a mock function with given fields: _a0 +func (_m *ServerDiscoveryService_WatchServersServer) SendHeader(_a0 metadata.MD) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for SendHeader") + } + + var r0 error + if rf, ok := ret.Get(0).(func(metadata.MD) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ServerDiscoveryService_WatchServersServer_SendHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendHeader' +type ServerDiscoveryService_WatchServersServer_SendHeader_Call struct { + *mock.Call +} + +// SendHeader is a helper method to define mock.On call +// - _a0 metadata.MD +func (_e *ServerDiscoveryService_WatchServersServer_Expecter) SendHeader(_a0 interface{}) *ServerDiscoveryService_WatchServersServer_SendHeader_Call { + return &ServerDiscoveryService_WatchServersServer_SendHeader_Call{Call: _e.mock.On("SendHeader", _a0)} +} + +func (_c *ServerDiscoveryService_WatchServersServer_SendHeader_Call) Run(run func(_a0 metadata.MD)) *ServerDiscoveryService_WatchServersServer_SendHeader_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(metadata.MD)) + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_SendHeader_Call) Return(_a0 error) *ServerDiscoveryService_WatchServersServer_SendHeader_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_SendHeader_Call) RunAndReturn(run func(metadata.MD) error) *ServerDiscoveryService_WatchServersServer_SendHeader_Call { + _c.Call.Return(run) + return _c +} + +// SendMsg provides a mock function with given fields: m +func (_m *ServerDiscoveryService_WatchServersServer) SendMsg(m interface{}) error { + ret := _m.Called(m) + + if len(ret) == 0 { + panic("no return value specified for SendMsg") + } + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ServerDiscoveryService_WatchServersServer_SendMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendMsg' +type ServerDiscoveryService_WatchServersServer_SendMsg_Call struct { + *mock.Call +} + +// SendMsg is a helper method to define mock.On call +// - m interface{} +func (_e *ServerDiscoveryService_WatchServersServer_Expecter) SendMsg(m interface{}) *ServerDiscoveryService_WatchServersServer_SendMsg_Call { + return &ServerDiscoveryService_WatchServersServer_SendMsg_Call{Call: _e.mock.On("SendMsg", m)} +} + +func (_c *ServerDiscoveryService_WatchServersServer_SendMsg_Call) Run(run func(m interface{})) *ServerDiscoveryService_WatchServersServer_SendMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_SendMsg_Call) Return(_a0 error) *ServerDiscoveryService_WatchServersServer_SendMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_SendMsg_Call) RunAndReturn(run func(interface{}) error) *ServerDiscoveryService_WatchServersServer_SendMsg_Call { + _c.Call.Return(run) + return _c +} + +// SetHeader provides a mock function with given fields: _a0 +func (_m *ServerDiscoveryService_WatchServersServer) SetHeader(_a0 metadata.MD) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for SetHeader") + } + + var r0 error + if rf, ok := ret.Get(0).(func(metadata.MD) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ServerDiscoveryService_WatchServersServer_SetHeader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetHeader' +type ServerDiscoveryService_WatchServersServer_SetHeader_Call struct { + *mock.Call +} + +// SetHeader is a helper method to define mock.On call +// - _a0 metadata.MD +func (_e *ServerDiscoveryService_WatchServersServer_Expecter) SetHeader(_a0 interface{}) *ServerDiscoveryService_WatchServersServer_SetHeader_Call { + return &ServerDiscoveryService_WatchServersServer_SetHeader_Call{Call: _e.mock.On("SetHeader", _a0)} +} + +func (_c *ServerDiscoveryService_WatchServersServer_SetHeader_Call) Run(run func(_a0 metadata.MD)) *ServerDiscoveryService_WatchServersServer_SetHeader_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(metadata.MD)) + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_SetHeader_Call) Return(_a0 error) *ServerDiscoveryService_WatchServersServer_SetHeader_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_SetHeader_Call) RunAndReturn(run func(metadata.MD) error) *ServerDiscoveryService_WatchServersServer_SetHeader_Call { + _c.Call.Return(run) + return _c +} + +// SetTrailer provides a mock function with given fields: _a0 +func (_m *ServerDiscoveryService_WatchServersServer) SetTrailer(_a0 metadata.MD) { + _m.Called(_a0) +} + +// ServerDiscoveryService_WatchServersServer_SetTrailer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetTrailer' +type ServerDiscoveryService_WatchServersServer_SetTrailer_Call struct { + *mock.Call +} + +// SetTrailer is a helper method to define mock.On call +// - _a0 metadata.MD +func (_e *ServerDiscoveryService_WatchServersServer_Expecter) SetTrailer(_a0 interface{}) *ServerDiscoveryService_WatchServersServer_SetTrailer_Call { + return &ServerDiscoveryService_WatchServersServer_SetTrailer_Call{Call: _e.mock.On("SetTrailer", _a0)} +} + +func (_c *ServerDiscoveryService_WatchServersServer_SetTrailer_Call) Run(run func(_a0 metadata.MD)) *ServerDiscoveryService_WatchServersServer_SetTrailer_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(metadata.MD)) + }) + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_SetTrailer_Call) Return() *ServerDiscoveryService_WatchServersServer_SetTrailer_Call { + _c.Call.Return() + return _c +} + +func (_c *ServerDiscoveryService_WatchServersServer_SetTrailer_Call) RunAndReturn(run func(metadata.MD)) *ServerDiscoveryService_WatchServersServer_SetTrailer_Call { + _c.Call.Return(run) + return _c +} + +// NewServerDiscoveryService_WatchServersServer creates a new instance of ServerDiscoveryService_WatchServersServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewServerDiscoveryService_WatchServersServer(t interface { + mock.TestingT + Cleanup(func()) +}) *ServerDiscoveryService_WatchServersServer { + mock := &ServerDiscoveryService_WatchServersServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/grpcmocks/proto-public/pbserverdiscovery/mock_UnsafeServerDiscoveryServiceServer.go b/grpcmocks/proto-public/pbserverdiscovery/mock_UnsafeServerDiscoveryServiceServer.go new file mode 100644 index 000000000000..935dbbdbf5bb --- /dev/null +++ b/grpcmocks/proto-public/pbserverdiscovery/mock_UnsafeServerDiscoveryServiceServer.go @@ -0,0 +1,64 @@ +// Code generated by mockery v2.41.0. DO NOT EDIT. + +package mockpbserverdiscovery + +import mock "github.com/stretchr/testify/mock" + +// UnsafeServerDiscoveryServiceServer is an autogenerated mock type for the UnsafeServerDiscoveryServiceServer type +type UnsafeServerDiscoveryServiceServer struct { + mock.Mock +} + +type UnsafeServerDiscoveryServiceServer_Expecter struct { + mock *mock.Mock +} + +func (_m *UnsafeServerDiscoveryServiceServer) EXPECT() *UnsafeServerDiscoveryServiceServer_Expecter { + return &UnsafeServerDiscoveryServiceServer_Expecter{mock: &_m.Mock} +} + +// mustEmbedUnimplementedServerDiscoveryServiceServer provides a mock function with given fields: +func (_m *UnsafeServerDiscoveryServiceServer) mustEmbedUnimplementedServerDiscoveryServiceServer() { + _m.Called() +} + +// UnsafeServerDiscoveryServiceServer_mustEmbedUnimplementedServerDiscoveryServiceServer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'mustEmbedUnimplementedServerDiscoveryServiceServer' +type UnsafeServerDiscoveryServiceServer_mustEmbedUnimplementedServerDiscoveryServiceServer_Call struct { + *mock.Call +} + +// mustEmbedUnimplementedServerDiscoveryServiceServer is a helper method to define mock.On call +func (_e *UnsafeServerDiscoveryServiceServer_Expecter) mustEmbedUnimplementedServerDiscoveryServiceServer() *UnsafeServerDiscoveryServiceServer_mustEmbedUnimplementedServerDiscoveryServiceServer_Call { + return &UnsafeServerDiscoveryServiceServer_mustEmbedUnimplementedServerDiscoveryServiceServer_Call{Call: _e.mock.On("mustEmbedUnimplementedServerDiscoveryServiceServer")} +} + +func (_c *UnsafeServerDiscoveryServiceServer_mustEmbedUnimplementedServerDiscoveryServiceServer_Call) Run(run func()) *UnsafeServerDiscoveryServiceServer_mustEmbedUnimplementedServerDiscoveryServiceServer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *UnsafeServerDiscoveryServiceServer_mustEmbedUnimplementedServerDiscoveryServiceServer_Call) Return() *UnsafeServerDiscoveryServiceServer_mustEmbedUnimplementedServerDiscoveryServiceServer_Call { + _c.Call.Return() + return _c +} + +func (_c *UnsafeServerDiscoveryServiceServer_mustEmbedUnimplementedServerDiscoveryServiceServer_Call) RunAndReturn(run func()) *UnsafeServerDiscoveryServiceServer_mustEmbedUnimplementedServerDiscoveryServiceServer_Call { + _c.Call.Return(run) + return _c +} + +// NewUnsafeServerDiscoveryServiceServer creates a new instance of UnsafeServerDiscoveryServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewUnsafeServerDiscoveryServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *UnsafeServerDiscoveryServiceServer { + mock := &UnsafeServerDiscoveryServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/auth/exports.go b/internal/auth/exports.go deleted file mode 100644 index abbed80abe03..000000000000 --- a/internal/auth/exports.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package auth - -import ( - "github.com/hashicorp/consul/internal/auth/internal/controllers" - "github.com/hashicorp/consul/internal/auth/internal/controllers/trafficpermissions" - "github.com/hashicorp/consul/internal/auth/internal/mappers/trafficpermissionsmapper" - "github.com/hashicorp/consul/internal/auth/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" -) - -var ( - // Controller statuses - - StatusKey = trafficpermissions.StatusKey - TrafficPermissionsConditionComputed = trafficpermissions.ConditionComputed - TrafficPermissionsConditionFailedToCompute = trafficpermissions.ConditionFailedToCompute -) - -// RegisterTypes adds all resource types within the "catalog" API group -// to the given type registry -func RegisterTypes(r resource.Registry) { - types.Register(r) -} - -type ControllerDependencies = controllers.Dependencies - -func DefaultControllerDependencies() ControllerDependencies { - return ControllerDependencies{ - TrafficPermissionsMapper: trafficpermissionsmapper.New(), - } -} - -// RegisterControllers registers controllers for the auth types with -// the given controller manager. -func RegisterControllers(mgr *controller.Manager, deps ControllerDependencies) { - controllers.Register(mgr, deps) -} diff --git a/internal/auth/internal/controllers/register.go b/internal/auth/internal/controllers/register.go deleted file mode 100644 index 03fc31c5bc45..000000000000 --- a/internal/auth/internal/controllers/register.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package controllers - -import ( - "github.com/hashicorp/consul/internal/auth/internal/controllers/trafficpermissions" - "github.com/hashicorp/consul/internal/controller" -) - -type Dependencies struct { - TrafficPermissionsMapper trafficpermissions.TrafficPermissionsMapper -} - -func Register(mgr *controller.Manager, deps Dependencies) { - mgr.Register(trafficpermissions.Controller(deps.TrafficPermissionsMapper)) -} diff --git a/internal/auth/internal/controllers/trafficpermissions/controller.go b/internal/auth/internal/controllers/trafficpermissions/controller.go deleted file mode 100644 index 9e5912dc5e3c..000000000000 --- a/internal/auth/internal/controllers/trafficpermissions/controller.go +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package trafficpermissions - -import ( - "context" - - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// TrafficPermissionsMapper is used to map a watch event for a TrafficPermissions resource and translate -// it to a ComputedTrafficPermissions resource which contains the effective permissions -// from all referencing TrafficPermissions resources. -type TrafficPermissionsMapper interface { - // MapTrafficPermissions will take a TrafficPermission resource and return controller requests for all - // ComputedTrafficPermissions associated with that TrafficPermission. - MapTrafficPermissions(context.Context, controller.Runtime, *pbresource.Resource) ([]controller.Request, error) - - // UntrackTrafficPermissions instructs the Mapper to forget about the TrafficPermission. - UntrackTrafficPermissions(*pbresource.ID) - - // GetTrafficPermissionsForCTP returns the tracked TrafficPermissions that are used to create a CTP - GetTrafficPermissionsForCTP(*pbresource.ID) []*pbresource.Reference -} - -// Controller creates a controller for automatic ComputedTrafficPermissions management for -// updates to WorkloadIdentity or TrafficPermission resources. -func Controller(mapper TrafficPermissionsMapper) controller.Controller { - if mapper == nil { - panic("No TrafficPermissionsMapper was provided to the TrafficPermissionsController constructor") - } - - return controller.ForType(pbauth.ComputedTrafficPermissionsType). - WithWatch(pbauth.WorkloadIdentityType, controller.ReplaceType(pbauth.ComputedTrafficPermissionsType)). - WithWatch(pbauth.TrafficPermissionsType, mapper.MapTrafficPermissions). - WithReconciler(&reconciler{mapper: mapper}) -} - -type reconciler struct { - mapper TrafficPermissionsMapper -} - -// Reconcile will reconcile one ComputedTrafficPermission (CTP) in response to some event. -// Events include adding, modifying or deleting a WorkloadIdentity or TrafficPermission. -func (r *reconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", StatusKey) - /* - * A CTP ID could come in for a variety of reasons. - * 1. workload identity create / delete: this results in the creation / deletion of a new CTP - * 2. traffic permission create / modify / delete: this results in a potential modification of an existing CTP - * - * Part 1: Handle Workload Identity changes: - * Check if the workload identity exists. If it doesn't we can stop here. - * CTPs are always generated from WorkloadIdentities, therefore the WI resource must already exist. - * If it is missing, that means it was deleted. - */ - ctpID := req.ID - wi := resource.ReplaceType(pbauth.WorkloadIdentityType, ctpID) - workloadIdentity, err := resource.GetDecodedResource[*pbauth.WorkloadIdentity](ctx, rt.Client, wi) - if err != nil { - rt.Logger.Error("error retrieving corresponding Workload Identity", "error", err) - return err - } - if workloadIdentity == nil || workloadIdentity.Resource == nil { - rt.Logger.Trace("workload identity has been deleted") - return nil - } - - // Check if CTP exists: - oldCTPData, err := resource.GetDecodedResource[*pbauth.ComputedTrafficPermissions](ctx, rt.Client, ctpID) - if err != nil { - rt.Logger.Error("error retrieving computed permissions", "error", err) - return err - } - var oldResource *pbresource.Resource - var owner *pbresource.ID - if oldCTPData == nil { - // CTP does not yet exist, so we need to make a new one - rt.Logger.Trace("creating new computed traffic permissions for workload identity") - owner = workloadIdentity.Resource.Id - } else { - oldResource = oldCTPData.Resource - owner = oldCTPData.Resource.Owner - } - - // Part 2: Recompute a CTP from TP create / modify / delete, or create a new CTP from existing TPs: - latestTrafficPermissions, err := computeNewTrafficPermissions(ctx, rt, r.mapper, ctpID, oldResource) - if err != nil { - rt.Logger.Error("error calculating computed permissions", "error", err) - return err - } - - if oldCTPData != nil && proto.Equal(oldCTPData.Data, latestTrafficPermissions) { - // there are no changes to the computed traffic permissions, and we can return early - rt.Logger.Trace("no new computed traffic permissions") - return nil - } - newCTPData, err := anypb.New(latestTrafficPermissions) - if err != nil { - rt.Logger.Error("error marshalling latest traffic permissions", "error", err) - writeFailedStatus(ctx, rt, oldResource, nil, err.Error()) - return err - } - rt.Logger.Trace("writing computed traffic permissions") - rsp, err := rt.Client.Write(ctx, &pbresource.WriteRequest{ - Resource: &pbresource.Resource{ - Id: req.ID, - Data: newCTPData, - Owner: owner, - }, - }) - if err != nil || rsp.Resource == nil { - rt.Logger.Error("error writing new computed traffic permissions", "error", err) - writeFailedStatus(ctx, rt, oldResource, nil, err.Error()) - return err - } else { - rt.Logger.Trace("new computed traffic permissions were successfully written") - } - newStatus := &pbresource.Status{ - ObservedGeneration: rsp.Resource.Generation, - Conditions: []*pbresource.Condition{ - ConditionComputed(req.ID.Name, latestTrafficPermissions.IsDefault), - }, - } - _, err = rt.Client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ - Id: rsp.Resource.Id, - Key: StatusKey, - Status: newStatus, - }) - return err -} - -func writeFailedStatus(ctx context.Context, rt controller.Runtime, ctp *pbresource.Resource, tp *pbresource.ID, errDetail string) error { - if ctp == nil { - return nil - } - newStatus := &pbresource.Status{ - ObservedGeneration: ctp.Generation, - Conditions: []*pbresource.Condition{ - ConditionFailedToCompute(ctp.Id.Name, tp.Name, errDetail), - }, - } - _, err := rt.Client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ - Id: ctp.Id, - Key: StatusKey, - Status: newStatus, - }) - return err -} - -// computeNewTrafficPermissions will use all associated Traffic Permissions to create new ComputedTrafficPermissions data -func computeNewTrafficPermissions(ctx context.Context, rt controller.Runtime, wm TrafficPermissionsMapper, ctpID *pbresource.ID, ctp *pbresource.Resource) (*pbauth.ComputedTrafficPermissions, error) { - // Part 1: Get all TPs that apply to workload identity - // Get already associated WorkloadIdentities/CTPs for reconcile requests: - trackedTPs := wm.GetTrafficPermissionsForCTP(ctpID) - if len(trackedTPs) > 0 { - rt.Logger.Trace("got tracked traffic permissions for CTP", "tps:", trackedTPs) - } else { - rt.Logger.Trace("found no tracked traffic permissions for CTP") - } - ap := make([]*pbauth.Permission, 0) - dp := make([]*pbauth.Permission, 0) - isDefault := true - for _, t := range trackedTPs { - rsp, err := resource.GetDecodedResource[*pbauth.TrafficPermissions](ctx, rt.Client, resource.IDFromReference(t)) - if err != nil { - rt.Logger.Error("error reading traffic permissions resource for computation", "error", err) - writeFailedStatus(ctx, rt, ctp, resource.IDFromReference(t), err.Error()) - return nil, err - } - if rsp == nil { - rt.Logger.Trace("untracking deleted TrafficPermissions", "traffic-permissions-name", t.Name) - wm.UntrackTrafficPermissions(resource.IDFromReference(t)) - continue - } - isDefault = false - if rsp.Data.Action == pbauth.Action_ACTION_ALLOW { - ap = append(ap, rsp.Data.Permissions...) - } else { - dp = append(dp, rsp.Data.Permissions...) - } - } - return &pbauth.ComputedTrafficPermissions{ - AllowPermissions: ap, - DenyPermissions: dp, - IsDefault: isDefault, - }, nil -} diff --git a/internal/auth/internal/controllers/trafficpermissions/controller_test.go b/internal/auth/internal/controllers/trafficpermissions/controller_test.go deleted file mode 100644 index 910a6fb88e71..000000000000 --- a/internal/auth/internal/controllers/trafficpermissions/controller_test.go +++ /dev/null @@ -1,681 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package trafficpermissions - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/auth/internal/mappers/trafficpermissionsmapper" - "github.com/hashicorp/consul/internal/auth/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -type controllerSuite struct { - suite.Suite - ctx context.Context - client *rtest.Client - rt controller.Runtime - - mapper *trafficpermissionsmapper.TrafficPermissionsMapper - reconciler *reconciler -} - -func (suite *controllerSuite) SetupTest() { - suite.ctx = testutil.TestContext(suite.T()) - client := svctest.RunResourceService(suite.T(), types.Register) - suite.client = rtest.NewClient(client) - suite.rt = controller.Runtime{ - Client: suite.client, - Logger: testutil.Logger(suite.T()), - } - suite.mapper = trafficpermissionsmapper.New() - suite.reconciler = &reconciler{mapper: suite.mapper} -} - -func (suite *controllerSuite) requireTrafficPermissionsTracking(tp *pbresource.Resource, ids ...*pbresource.ID) { - reqs, err := suite.mapper.MapTrafficPermissions(suite.ctx, suite.rt, tp) - require.NoError(suite.T(), err) - require.Len(suite.T(), reqs, len(ids)) - for _, id := range ids { - prototest.AssertContainsElement(suite.T(), reqs, controller.Request{ID: id}) - } - for _, req := range reqs { - prototest.AssertContainsElement(suite.T(), ids, req.ID) - } -} - -func (suite *controllerSuite) requireCTP(resource *pbresource.Resource, allowExpected []*pbauth.Permission, denyExpected []*pbauth.Permission) { - dec := rtest.MustDecode[*pbauth.ComputedTrafficPermissions](suite.T(), resource) - ctp := dec.Data - require.Len(suite.T(), ctp.AllowPermissions, len(allowExpected)) - require.Len(suite.T(), ctp.DenyPermissions, len(denyExpected)) - prototest.AssertElementsMatch(suite.T(), allowExpected, ctp.AllowPermissions) - prototest.AssertElementsMatch(suite.T(), denyExpected, ctp.DenyPermissions) -} - -func (suite *controllerSuite) TestReconcile_CTPCreate_NoReferencingTrafficPermissionsExist() { - wi := rtest.Resource(pbauth.WorkloadIdentityType, "wi1").Write(suite.T(), suite.client) - require.NotNil(suite.T(), wi) - id := rtest.Resource(pbauth.ComputedTrafficPermissionsType, wi.Id.Name).WithTenancy(resource.DefaultNamespacedTenancy()).WithOwner(wi.Id).ID() - require.NotNil(suite.T(), id) - - err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - // Ensure that the CTP was created - ctp := suite.client.RequireResourceExists(suite.T(), id) - suite.requireCTP(ctp, []*pbauth.Permission{}, []*pbauth.Permission{}) -} - -func (suite *controllerSuite) TestReconcile_CTPCreate_ReferencingTrafficPermissionsExist() { - // create dead-end traffic permissions - p1 := &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - IdentityName: "foo", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - } - tp1 := rtest.Resource(pbauth.TrafficPermissionsType, "tp1").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action_ACTION_DENY, - Permissions: []*pbauth.Permission{p1}, - }).Write(suite.T(), suite.client) - wi1ID := &pbresource.ID{ - Name: "wi1", - Type: pbauth.ComputedTrafficPermissionsType, - Tenancy: tp1.Id.Tenancy, - } - suite.requireTrafficPermissionsTracking(tp1, wi1ID) - p2 := &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - IdentityName: "wi2", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - } - tp2 := rtest.Resource(pbauth.TrafficPermissionsType, "tp2").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{p2}, - }).Write(suite.T(), suite.client) - suite.requireTrafficPermissionsTracking(tp2, wi1ID) - - // create the workload identity that they reference - wi := rtest.Resource(pbauth.WorkloadIdentityType, "wi1").Write(suite.T(), suite.client) - id := rtest.Resource(pbauth.ComputedTrafficPermissionsType, wi.Id.Name).WithTenancy(resource.DefaultNamespacedTenancy()).WithOwner(wi.Id).ID() - - err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - // Ensure that the CTP was created - ctp := suite.client.RequireResourceExists(suite.T(), id) - suite.requireCTP(ctp, []*pbauth.Permission{p2}, []*pbauth.Permission{p1}) - rtest.RequireOwner(suite.T(), ctp, wi.Id, true) -} - -func (suite *controllerSuite) TestReconcile_WorkloadIdentityDelete_ReferencingTrafficPermissionsExist() { - p1 := &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - IdentityName: "foo", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - } - tp1 := rtest.Resource(pbauth.TrafficPermissionsType, "tp1").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action_ACTION_DENY, - Permissions: []*pbauth.Permission{p1}, - }).Write(suite.T(), suite.client) - wi1ID := &pbresource.ID{ - Name: "wi1", - Type: pbauth.ComputedTrafficPermissionsType, - Tenancy: tp1.Id.Tenancy, - } - suite.requireTrafficPermissionsTracking(tp1, wi1ID) - p2 := &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - IdentityName: "wi2", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - } - tp2 := rtest.Resource(pbauth.TrafficPermissionsType, "tp2").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{p2}, - }).Write(suite.T(), suite.client) - suite.requireTrafficPermissionsTracking(tp2, wi1ID) - - // create the workload identity that they reference - wi := rtest.Resource(pbauth.WorkloadIdentityType, "wi1").Write(suite.T(), suite.client) - id := rtest.Resource(pbauth.ComputedTrafficPermissionsType, wi.Id.Name).WithTenancy(resource.DefaultNamespacedTenancy()).WithOwner(wi.Id).ID() - - err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - // delete the workload identity - suite.client.MustDelete(suite.T(), wi.Id) - - // re-reconcile: should untrack the CTP - err = suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) -} - -func (suite *controllerSuite) TestReconcile_WorkloadIdentityDelete_NoReferencingTrafficPermissionsExist() { - // create the workload identity that they reference - wi := rtest.Resource(pbauth.WorkloadIdentityType, "wi1").Write(suite.T(), suite.client) - id := rtest.Resource(pbauth.ComputedTrafficPermissionsType, wi.Id.Name).WithTenancy(resource.DefaultNamespacedTenancy()).WithOwner(wi.Id).ID() - - err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - // delete the workload identity - suite.client.MustDelete(suite.T(), wi.Id) - - // re-reconcile: should untrack the CTP - err = suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - // there should not be any traffic permissions to compute - tps := suite.mapper.GetTrafficPermissionsForCTP(id) - require.Len(suite.T(), tps, 0) -} - -func (suite *controllerSuite) TestReconcile_TrafficPermissionsCreate_DestinationWorkloadIdentityExists() { - // create the workload identity to be referenced - wi := rtest.Resource(pbauth.WorkloadIdentityType, "wi1").Write(suite.T(), suite.client) - id := rtest.Resource(pbauth.ComputedTrafficPermissionsType, wi.Id.Name).WithTenancy(resource.DefaultNamespacedTenancy()).WithOwner(wi.Id).ID() - - err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - ctpResource := suite.client.RequireResourceExists(suite.T(), id) - assertCTPDefaultStatus(suite.T(), ctpResource, true) - - // create traffic permissions - p1 := &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - IdentityName: "foo", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - } - tp1 := rtest.Resource(pbauth.TrafficPermissionsType, "tp1").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action_ACTION_DENY, - Permissions: []*pbauth.Permission{p1}, - }).Write(suite.T(), suite.client) - suite.requireTrafficPermissionsTracking(tp1, id) - - p2 := &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - IdentityName: "wi2", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - } - tp2 := rtest.Resource(pbauth.TrafficPermissionsType, "tp2").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{p2}, - }).Write(suite.T(), suite.client) - suite.requireTrafficPermissionsTracking(tp2, id) - - err = suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - // Ensure that the CTP was updated - ctpResource = suite.client.RequireResourceExists(suite.T(), id) - suite.requireCTP(ctpResource, []*pbauth.Permission{p2}, []*pbauth.Permission{p1}) - rtest.RequireOwner(suite.T(), ctpResource, wi.Id, true) - assertCTPDefaultStatus(suite.T(), ctpResource, false) - - // Add another TP - p3 := &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - IdentityName: "wi3", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - } - tp3 := rtest.Resource(pbauth.TrafficPermissionsType, "tp3").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action_ACTION_DENY, - Permissions: []*pbauth.Permission{p3}, - }).Write(suite.T(), suite.client) - suite.requireTrafficPermissionsTracking(tp3, id) - - err = suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - // Ensure that the CTP was updated - ctpResource = suite.client.RequireResourceExists(suite.T(), id) - suite.requireCTP(ctpResource, []*pbauth.Permission{p2}, []*pbauth.Permission{p1, p3}) - rtest.RequireOwner(suite.T(), ctpResource, wi.Id, true) - assertCTPDefaultStatus(suite.T(), ctpResource, false) - - // Delete the traffic permissions without updating the caches. Ensure is default is right even when the caches contain stale data. - suite.client.MustDelete(suite.T(), tp1.Id) - suite.client.MustDelete(suite.T(), tp2.Id) - suite.client.MustDelete(suite.T(), tp3.Id) - - err = suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - ctpResource = suite.client.RequireResourceExists(suite.T(), id) - suite.requireCTP(ctpResource, []*pbauth.Permission{}, []*pbauth.Permission{}) - rtest.RequireOwner(suite.T(), ctpResource, wi.Id, true) - assertCTPDefaultStatus(suite.T(), ctpResource, true) -} - -func (suite *controllerSuite) TestReconcile_TrafficPermissionsDelete_DestinationWorkloadIdentityExists() { - // create the workload identity to be referenced - wi := rtest.Resource(pbauth.WorkloadIdentityType, "wi1").Write(suite.T(), suite.client) - id := rtest.Resource(pbauth.ComputedTrafficPermissionsType, wi.Id.Name).WithTenancy(resource.DefaultNamespacedTenancy()).WithOwner(wi.Id).ID() - - err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - // create traffic permissions - p1 := &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - IdentityName: "foo", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - } - tp1 := rtest.Resource(pbauth.TrafficPermissionsType, "tp1").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action_ACTION_DENY, - Permissions: []*pbauth.Permission{p1}, - }).Write(suite.T(), suite.client) - suite.requireTrafficPermissionsTracking(tp1, id) - p2 := &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - IdentityName: "wi2", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - } - tp2 := rtest.Resource(pbauth.TrafficPermissionsType, "tp2").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{p2}, - }).Write(suite.T(), suite.client) - suite.requireTrafficPermissionsTracking(tp2, id) - - err = suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - ctp := suite.client.RequireResourceExists(suite.T(), id) - suite.requireCTP(ctp, []*pbauth.Permission{p2}, []*pbauth.Permission{p1}) - rtest.RequireOwner(suite.T(), ctp, wi.Id, true) - - // Delete TP2 - suite.client.MustDelete(suite.T(), tp2.Id) - - err = suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - // Ensure that the CTP was updated - ctp = suite.client.RequireResourceExists(suite.T(), id) - suite.requireCTP(ctp, []*pbauth.Permission{}, []*pbauth.Permission{p1}) - - // Ensure TP2 is untracked - newTps := suite.mapper.GetTrafficPermissionsForCTP(ctp.Id) - require.Len(suite.T(), newTps, 1) - require.Equal(suite.T(), newTps[0].Name, tp1.Id.Name) -} - -func (suite *controllerSuite) TestReconcile_TrafficPermissionsDelete_DestinationWorkloadIdentityDoesNotExist() { - // create traffic permissions - p1 := &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - IdentityName: "foo", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - } - tp1 := rtest.Resource(pbauth.TrafficPermissionsType, "tp1").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action_ACTION_DENY, - Permissions: []*pbauth.Permission{p1}, - }).Write(suite.T(), suite.client) - wi1ID := &pbresource.ID{ - Name: "wi1", - Type: pbauth.ComputedTrafficPermissionsType, - Tenancy: tp1.Id.Tenancy, - } - suite.requireTrafficPermissionsTracking(tp1, wi1ID) - p2 := &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - IdentityName: "wi2", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - } - tp2 := rtest.Resource(pbauth.TrafficPermissionsType, "tp2").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{p2}, - }).Write(suite.T(), suite.client) - suite.requireTrafficPermissionsTracking(tp2, wi1ID) - - // Delete TP2 - suite.client.MustDelete(suite.T(), tp2.Id) - - // Ensure that no CTPs exist - rsp, err := suite.client.List(suite.ctx, &pbresource.ListRequest{ - Type: pbauth.ComputedTrafficPermissionsType, - Tenancy: resource.DefaultNamespacedTenancy(), - }) - require.NoError(suite.T(), err) - require.Empty(suite.T(), rsp.Resources) -} - -func (suite *controllerSuite) TestControllerBasic() { - // TODO: refactor this - // In this test we check basic operations for a workload identity and referencing traffic permission - mgr := controller.NewManager(suite.client, suite.rt.Logger) - mgr.Register(Controller(suite.mapper)) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - // Add a workload identity - workloadIdentity := rtest.Resource(pbauth.WorkloadIdentityType, "wi1").Write(suite.T(), suite.client) - - // Wait for the controller to record that the CTP has been computed - res := suite.client.WaitForReconciliation(suite.T(), resource.ReplaceType(pbauth.ComputedTrafficPermissionsType, workloadIdentity.Id), StatusKey) - // Check that the status was updated - rtest.RequireStatusCondition(suite.T(), res, StatusKey, ConditionComputed("wi1", true)) - - // Check that the CTP resource exists and contains no permissions - ctpID := rtest.Resource(pbauth.ComputedTrafficPermissionsType, "wi1").ID() - ctpObject := suite.client.RequireResourceExists(suite.T(), ctpID) - suite.requireCTP(ctpObject, nil, nil) - - // add a traffic permission that references wi1 - p1 := &pbauth.Permission{ - Sources: []*pbauth.Source{{ - IdentityName: "wi2", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - DestinationRules: nil, - } - tp1 := rtest.Resource(pbauth.TrafficPermissionsType, "tp1").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{IdentityName: "wi1"}, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{p1}, - }).Write(suite.T(), suite.client) - suite.client.RequireResourceExists(suite.T(), tp1.Id) - // Wait for the controller to record that the CTP has been re-computed - suite.client.WaitForReconciliation(suite.T(), resource.ReplaceType(pbauth.ComputedTrafficPermissionsType, workloadIdentity.Id), StatusKey) - // Check that the ctp has been regenerated - ctpObject = suite.client.WaitForNewVersion(suite.T(), ctpID, ctpObject.Version) - rtest.RequireStatusCondition(suite.T(), ctpObject, StatusKey, ConditionComputed("wi1", false)) - // check wi1 - suite.requireCTP(ctpObject, []*pbauth.Permission{p1}, nil) - - // add a traffic permission that references wi2 - p2 := &pbauth.Permission{ - Sources: []*pbauth.Source{{ - IdentityName: "wi1", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - DestinationRules: nil, - } - tp2 := rtest.Resource(pbauth.TrafficPermissionsType, "tp2").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{IdentityName: "wi2"}, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{p2}, - }).Write(suite.T(), suite.client) - suite.client.RequireResourceExists(suite.T(), tp2.Id) - // check wi1 is the same - ctpObject = suite.client.RequireResourceExists(suite.T(), ctpID) - suite.requireCTP(ctpObject, []*pbauth.Permission{p1}, nil) - // check no ctp2 - ctpID2 := rtest.Resource(pbauth.ComputedTrafficPermissionsType, "wi2").ID() - suite.client.RequireResourceNotFound(suite.T(), ctpID2) - - // delete tp1 - suite.client.MustDelete(suite.T(), tp1.Id) - suite.client.WaitForDeletion(suite.T(), tp1.Id) - // check wi1 has no permissions - ctpObject = suite.client.WaitForNewVersion(suite.T(), ctpID, ctpObject.Version) - suite.requireCTP(ctpObject, nil, nil) - - // edit tp2 to point to wi1 - rtest.Resource(pbauth.TrafficPermissionsType, "tp2").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{IdentityName: "wi1"}, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{p2}, - }).Write(suite.T(), suite.client) - // check wi1 has tp2's permissions - ctpObject = suite.client.WaitForNewVersion(suite.T(), ctpID, ctpObject.Version) - suite.requireCTP(ctpObject, []*pbauth.Permission{p2}, nil) - // check no ctp2 - ctpID2 = rtest.Resource(pbauth.ComputedTrafficPermissionsType, "wi2").ID() - suite.client.RequireResourceNotFound(suite.T(), ctpID2) -} - -func (suite *controllerSuite) TestControllerMultipleTrafficPermissions() { - // TODO: refactor this, turn back on once timing flakes are understood - suite.T().Skip("flaky behavior observed") - // In this test we check operations for a workload identity and multiple referencing traffic permissions - mgr := controller.NewManager(suite.client, suite.rt.Logger) - mgr.Register(Controller(suite.mapper)) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - wi1ID := &pbresource.ID{ - Name: "wi1", - Type: pbauth.ComputedTrafficPermissionsType, - Tenancy: resource.DefaultNamespacedTenancy(), - } - // add tp1 and tp2 - p1 := &pbauth.Permission{ - Sources: []*pbauth.Source{{ - IdentityName: "wi2", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - DestinationRules: nil, - } - tp1 := rtest.Resource(pbauth.TrafficPermissionsType, "tp1").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{IdentityName: "wi1"}, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{p1}, - }).Write(suite.T(), suite.client) - suite.client.RequireResourceExists(suite.T(), tp1.Id) - suite.requireTrafficPermissionsTracking(tp1, wi1ID) - p2 := &pbauth.Permission{ - Sources: []*pbauth.Source{{ - IdentityName: "wi3", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - DestinationRules: nil, - } - tp2 := rtest.Resource(pbauth.TrafficPermissionsType, "tp2").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{IdentityName: "wi1"}, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{p2}, - }).Write(suite.T(), suite.client) - suite.client.RequireResourceExists(suite.T(), tp2.Id) - suite.requireTrafficPermissionsTracking(tp1, wi1ID) - - // Add a workload identity - workloadIdentity := rtest.Resource(pbauth.WorkloadIdentityType, "wi1").Write(suite.T(), suite.client) - ctpID := resource.ReplaceType(pbauth.ComputedTrafficPermissionsType, workloadIdentity.Id) - // Wait for the controller to record that the CTP has been computed - res := suite.client.WaitForReconciliation(suite.T(), ctpID, StatusKey) - rtest.RequireStatusCondition(suite.T(), res, StatusKey, ConditionComputed("wi1", false)) - // check ctp1 has tp1 and tp2 - ctpObject := suite.client.RequireResourceExists(suite.T(), res.Id) - suite.requireCTP(ctpObject, []*pbauth.Permission{p1, p2}, nil) - - // add tp3 - p3 := &pbauth.Permission{ - Sources: []*pbauth.Source{{ - IdentityName: "wi4", - Namespace: "default", - Partition: "default", - Peer: "local", - }}, - DestinationRules: nil, - } - tp3 := rtest.Resource(pbauth.TrafficPermissionsType, "tp3").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{IdentityName: "wi1"}, - Action: pbauth.Action_ACTION_DENY, - Permissions: []*pbauth.Permission{p3}, - }).Write(suite.T(), suite.client) - suite.client.RequireResourceExists(suite.T(), tp3.Id) - // check ctp1 has tp3 - ctpObject = suite.client.WaitForReconciliation(suite.T(), ctpObject.Id, StatusKey) - ctpObject = suite.client.WaitForNewVersion(suite.T(), ctpObject.Id, ctpObject.Version) - suite.requireCTP(ctpObject, []*pbauth.Permission{p1, p2}, []*pbauth.Permission{p3}) - - // delete ctp - suite.client.MustDelete(suite.T(), ctpObject.Id) - suite.client.WaitForDeletion(suite.T(), ctpObject.Id) - // check ctp regenerated, has all permissions - res = suite.client.WaitForReconciliation(suite.T(), ctpID, StatusKey) - rtest.RequireStatusCondition(suite.T(), res, StatusKey, ConditionComputed("wi1", false)) - ctpObject = suite.client.RequireResourceExists(suite.T(), res.Id) - suite.requireCTP(ctpObject, []*pbauth.Permission{p1, p2}, []*pbauth.Permission{p3}) - - // delete wi1 - suite.client.MustDelete(suite.T(), workloadIdentity.Id) - suite.client.WaitForDeletion(suite.T(), workloadIdentity.Id) - - // recreate wi1 - rtest.Resource(pbauth.WorkloadIdentityType, "wi1").Write(suite.T(), suite.client) - // check ctp regenerated, has all permissions - res = suite.client.WaitForReconciliation(suite.T(), ctpID, StatusKey) - rtest.RequireStatusCondition(suite.T(), res, StatusKey, ConditionComputed("wi1", false)) - ctpObject = suite.client.RequireResourceExists(suite.T(), res.Id) - suite.requireCTP(ctpObject, []*pbauth.Permission{p1, p2}, []*pbauth.Permission{p3}) - - // delete tp3 - suite.client.MustDelete(suite.T(), tp3.Id) - suite.client.WaitForDeletion(suite.T(), tp3.Id) - suite.client.RequireResourceNotFound(suite.T(), tp3.Id) - // check ctp1 has tp1 and tp2, and not tp3 - res = suite.client.WaitForReconciliation(suite.T(), ctpObject.Id, StatusKey) - ctpObject = suite.client.WaitForNewVersion(suite.T(), res.Id, ctpObject.Version) - suite.requireCTP(ctpObject, []*pbauth.Permission{p1, p2}, nil) - - // add wi2 - workloadIdentity2 := rtest.Resource(pbauth.WorkloadIdentityType, "wi2").Write(suite.T(), suite.client) - // Wait for the controller to record that the CTP has been computed - res2 := suite.client.WaitForReconciliation(suite.T(), resource.ReplaceType(pbauth.ComputedTrafficPermissionsType, workloadIdentity2.Id), StatusKey) - rtest.RequireStatusCondition(suite.T(), res2, StatusKey, ConditionComputed("wi2", false)) - // check ctp2 has no permissions - ctpObject2 := suite.client.RequireResourceExists(suite.T(), res2.Id) - suite.requireCTP(ctpObject2, nil, nil) - - // edit all traffic permissions to point to wi2 - tp1 = rtest.Resource(pbauth.TrafficPermissionsType, "tp1").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{IdentityName: "wi2"}, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{p1}, - }).Write(suite.T(), suite.client) - tp2 = rtest.Resource(pbauth.TrafficPermissionsType, "tp2").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{IdentityName: "wi2"}, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{p2}, - }).Write(suite.T(), suite.client) - tp3 = rtest.Resource(pbauth.TrafficPermissionsType, "tp3").WithData(suite.T(), &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{IdentityName: "wi2"}, - Action: pbauth.Action_ACTION_DENY, - Permissions: []*pbauth.Permission{p3}, - }).Write(suite.T(), suite.client) - suite.client.RequireResourceExists(suite.T(), tp1.Id) - suite.client.RequireResourceExists(suite.T(), tp2.Id) - suite.client.RequireResourceExists(suite.T(), tp3.Id) - - // check wi2 has updated with all permissions after 6 reconciles - ctpObject2 = suite.client.WaitForReconciliation(suite.T(), ctpObject2.Id, StatusKey) - res2 = suite.client.WaitForReconciliation(suite.T(), ctpObject2.Id, StatusKey) - suite.client.WaitForResourceState(suite.T(), res2.Id, func(t rtest.T, res *pbresource.Resource) { - suite.requireCTP(res, []*pbauth.Permission{p1, p2}, []*pbauth.Permission{p3}) - }) - // check wi1 has no permissions after 6 reconciles - ctpObject = suite.client.WaitForReconciliation(suite.T(), ctpObject.Id, StatusKey) - res = suite.client.WaitForReconciliation(suite.T(), ctpObject.Id, StatusKey) - suite.client.WaitForResourceState(suite.T(), res.Id, func(t rtest.T, res *pbresource.Resource) { - suite.requireCTP(res, nil, nil) - }) -} - -func TestController(t *testing.T) { - suite.Run(t, new(controllerSuite)) -} - -func assertCTPDefaultStatus(t *testing.T, resource *pbresource.Resource, isDefault bool) { - dec := rtest.MustDecode[*pbauth.ComputedTrafficPermissions](t, resource) - require.Equal(t, isDefault, dec.Data.IsDefault) -} diff --git a/internal/auth/internal/controllers/trafficpermissions/status.go b/internal/auth/internal/controllers/trafficpermissions/status.go deleted file mode 100644 index bfcc64bc131c..000000000000 --- a/internal/auth/internal/controllers/trafficpermissions/status.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package trafficpermissions - -import ( - "fmt" - - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - StatusKey = "consul.io/traffic-permissions" - StatusTrafficPermissionsComputed = "Traffic permissions have been computed" - StatusTrafficPermissionsNotComputed = "Traffic permissions have not been computed" - ConditionPermissionsAppliedMsg = "Workload identity %s has new permissions" - ConditionNoPermissionsMsg = "Workload identity %s has no permissions" - ConditionPermissionsFailedMsg = "Unable to calculate new permission set for Workload identity %s" -) - -func ConditionComputed(workloadIdentity string, isDefault bool) *pbresource.Condition { - msgTpl := ConditionPermissionsAppliedMsg - if isDefault { - msgTpl = ConditionNoPermissionsMsg - } - return &pbresource.Condition{ - Type: StatusTrafficPermissionsComputed, - State: pbresource.Condition_STATE_TRUE, - Message: fmt.Sprintf(msgTpl, workloadIdentity), - } -} - -func ConditionFailedToCompute(workloadIdentity string, trafficPermissions string, errDetail string) *pbresource.Condition { - message := fmt.Sprintf(ConditionPermissionsFailedMsg, workloadIdentity) - if len(trafficPermissions) > 0 { - message = message + fmt.Sprintf(", traffic permission %s cannot be computed", trafficPermissions) - } - if len(errDetail) > 0 { - message = message + fmt.Sprintf(", error details: %s", errDetail) - } - return &pbresource.Condition{ - Type: StatusTrafficPermissionsNotComputed, - State: pbresource.Condition_STATE_FALSE, - Message: message, - } -} diff --git a/internal/auth/internal/mappers/trafficpermissionsmapper/traffic_permissions_mapper.go b/internal/auth/internal/mappers/trafficpermissionsmapper/traffic_permissions_mapper.go deleted file mode 100644 index be2812645880..000000000000 --- a/internal/auth/internal/mappers/trafficpermissionsmapper/traffic_permissions_mapper.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package trafficpermissionsmapper - -import ( - "context" - "sync" - - "github.com/hashicorp/consul/internal/auth/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type TrafficPermissionsMapper struct { - lock sync.Mutex - mapper *bimapper.Mapper -} - -func New() *TrafficPermissionsMapper { - return &TrafficPermissionsMapper{ - lock: sync.Mutex{}, - mapper: bimapper.New(pbauth.TrafficPermissionsType, pbauth.ComputedTrafficPermissionsType), - } -} - -// TrafficPermissionsMapper functions - -func (tm *TrafficPermissionsMapper) MapTrafficPermissions(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - tm.lock.Lock() - defer tm.lock.Unlock() - var tp pbauth.TrafficPermissions - err := res.Data.UnmarshalTo(&tp) - if err != nil { - return nil, resource.NewErrDataParse(&tp, err) - } - // get new CTP associations based on destination - if len(tp.Destination.IdentityName) == 0 { - // this error should never happen if validation is working - return nil, types.ErrWildcardNotSupported - } - newCTP := &pbresource.ID{ - Name: tp.Destination.IdentityName, - Type: pbauth.ComputedTrafficPermissionsType, - Tenancy: res.Id.Tenancy, - } - requests := []controller.Request{{ID: newCTP}} - // add already associated WorkloadIdentities/CTPs for reconcile requests: - oldCTPs := tm.mapper.LinkIDsForItem(res.Id) - for _, mappedWI := range oldCTPs { - if mappedWI.Name != newCTP.Name { - requests = append(requests, controller.Request{ID: mappedWI}) - } - } - // re-map traffic permission to new CTP - tm.mapper.TrackItem(res.Id, []resource.ReferenceOrID{newCTP}) - return requests, nil -} - -func (tm *TrafficPermissionsMapper) UntrackTrafficPermissions(tp *pbresource.ID) { - tm.lock.Lock() - defer tm.lock.Unlock() - tm.mapper.UntrackItem(tp) -} - -func (tm *TrafficPermissionsMapper) GetTrafficPermissionsForCTP(ctp *pbresource.ID) []*pbresource.Reference { - tm.lock.Lock() - defer tm.lock.Unlock() - return tm.mapper.ItemRefsForLink(ctp) -} diff --git a/internal/auth/internal/types/computed_traffic_permissions.go b/internal/auth/internal/types/computed_traffic_permissions.go deleted file mode 100644 index 800d2a8fb66f..000000000000 --- a/internal/auth/internal/types/computed_traffic_permissions.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type DecodedComputedTrafficPermissions = resource.DecodedResource[*pbauth.ComputedTrafficPermissions] - -func RegisterComputedTrafficPermission(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbauth.ComputedTrafficPermissionsType, - Proto: &pbauth.ComputedTrafficPermissions{}, - ACLs: &resource.ACLHooks{ - Read: aclReadHookComputedTrafficPermissions, - Write: aclWriteHookComputedTrafficPermissions, - List: resource.NoOpACLListHook, - }, - Validate: ValidateComputedTrafficPermissions, - Scope: resource.ScopeNamespace, - }) -} - -var ValidateComputedTrafficPermissions = resource.DecodeAndValidate(validateComputedTrafficPermissions) - -func validateComputedTrafficPermissions(res *DecodedComputedTrafficPermissions) error { - var merr error - - for i, permission := range res.Data.AllowPermissions { - wrapErr := func(err error) error { - return resource.ErrInvalidListElement{ - Name: "allow_permissions", - Index: i, - Wrapped: err, - } - } - if err := validatePermission(permission, wrapErr); err != nil { - merr = multierror.Append(merr, err) - } - } - - for i, permission := range res.Data.DenyPermissions { - wrapErr := func(err error) error { - return resource.ErrInvalidListElement{ - Name: "deny_permissions", - Index: i, - Wrapped: err, - } - } - if err := validatePermission(permission, wrapErr); err != nil { - merr = multierror.Append(merr, err) - } - } - - return merr -} - -func aclReadHookComputedTrafficPermissions(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID, _ *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().TrafficPermissionsReadAllowed(id.Name, authzContext) -} - -func aclWriteHookComputedTrafficPermissions(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().TrafficPermissionsWriteAllowed(res.Id.Name, authzContext) -} diff --git a/internal/auth/internal/types/computed_traffic_permissions_test.go b/internal/auth/internal/types/computed_traffic_permissions_test.go deleted file mode 100644 index e5c4379a8180..000000000000 --- a/internal/auth/internal/types/computed_traffic_permissions_test.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestValidateComputedTrafficPermissions_Permissions(t *testing.T) { - for n, tc := range permissionsTestCases() { - t.Run(n, func(t *testing.T) { - - for _, s := range tc.p.Sources { - normalizedTenancyForSource(s, resource.DefaultNamespacedTenancy()) - } - - allowCTP := &pbauth.ComputedTrafficPermissions{ - AllowPermissions: []*pbauth.Permission{tc.p}, - } - - denyCTP := &pbauth.ComputedTrafficPermissions{ - DenyPermissions: []*pbauth.Permission{tc.p}, - } - - for _, ctp := range []*pbauth.ComputedTrafficPermissions{allowCTP, denyCTP} { - res := resourcetest.Resource(pbauth.ComputedTrafficPermissionsType, "tp"). - WithData(t, ctp). - Build() - - err := ValidateComputedTrafficPermissions(res) - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - }) - } -} - -func TestComputedTrafficPermissionsACLs(t *testing.T) { - // Wire up a registry to generically invoke hooks - registry := resource.NewRegistry() - Register(registry) - - type testcase struct { - rules string - check func(t *testing.T, authz acl.Authorizer, res *pbresource.Resource) - readOK string - writeOK string - listOK string - } - - const ( - DENY = "deny" - ALLOW = "allow" - DEFAULT = "default" - ) - - checkF := func(t *testing.T, expect string, got error) { - switch expect { - case ALLOW: - if acl.IsErrPermissionDenied(got) { - t.Fatal("should be allowed") - } - case DENY: - if !acl.IsErrPermissionDenied(got) { - t.Fatal("should be denied") - } - case DEFAULT: - require.Nil(t, got, "expected fallthrough decision") - default: - t.Fatalf("unexpected expectation: %q", expect) - } - } - - reg, ok := registry.Resolve(pbauth.ComputedTrafficPermissionsType) - require.True(t, ok) - - run := func(t *testing.T, tc testcase) { - ctpData := &pbauth.ComputedTrafficPermissions{} - res := resourcetest.Resource(pbauth.ComputedTrafficPermissionsType, "wi1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, ctpData). - Build() - resourcetest.ValidateAndNormalize(t, registry, res) - - config := acl.Config{ - WildcardName: structs.WildcardSpecifier, - } - authz, err := acl.NewAuthorizerFromRules(tc.rules, &config, nil) - require.NoError(t, err) - authz = acl.NewChainedAuthorizer([]acl.Authorizer{authz, acl.DenyAll()}) - - t.Run("read", func(t *testing.T) { - err := reg.ACLs.Read(authz, &acl.AuthorizerContext{}, res.Id, res) - checkF(t, tc.readOK, err) - }) - t.Run("write", func(t *testing.T) { - err := reg.ACLs.Write(authz, &acl.AuthorizerContext{}, res) - checkF(t, tc.writeOK, err) - }) - t.Run("list", func(t *testing.T) { - err := reg.ACLs.List(authz, &acl.AuthorizerContext{}) - checkF(t, tc.listOK, err) - }) - } - - cases := map[string]testcase{ - "no rules": { - rules: ``, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity w1 read, no intentions": { - rules: `identity "wi1" { policy = "read" }`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity w1 read, deny intentions": { - rules: `identity "wi1" { policy = "read", intentions = "deny" }`, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity w1 read, intentions read": { - rules: `identity "wi1" { policy = "read", intentions = "read" }`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity w1 write, write intentions": { - rules: `identity "wi1" { policy = "read", intentions = "write" }`, - readOK: ALLOW, - writeOK: ALLOW, - listOK: DEFAULT, - }, - "workload identity w1 write, deny intentions": { - rules: `identity "wi1" { policy = "write", intentions = "deny" }`, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity w1 write, intentions read": { - rules: `identity "wi1" { policy = "write", intentions = "read" }`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity w1 write, intentions write": { - rules: `identity "wi1" { policy = "write", intentions = "write" }`, - readOK: ALLOW, - writeOK: ALLOW, - listOK: DEFAULT, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/auth/internal/types/errors.go b/internal/auth/internal/types/errors.go deleted file mode 100644 index b11fac630476..000000000000 --- a/internal/auth/internal/types/errors.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import "errors" - -var ( - errInvalidAction = errors.New("action must be either allow or deny") - errSourcesTenancy = errors.New("permissions sources may not specify partitions, peers, and sameness_groups together") - errSourceWildcards = errors.New("permission sources may not have wildcard namespaces and explicit names.") - errSourceExcludes = errors.New("must be defined on wildcard sources") - errInvalidPrefixValues = errors.New("prefix values, regex values, and explicit names must not combined") - ErrWildcardNotSupported = errors.New("traffic permissions without explicit destinations are not yet supported") - ErrL7NotSupported = errors.New("traffic permissions with L7 rules are not yet supported") -) diff --git a/internal/auth/internal/types/traffic_permissions.go b/internal/auth/internal/types/traffic_permissions.go deleted file mode 100644 index acf265537169..000000000000 --- a/internal/auth/internal/types/traffic_permissions.go +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type DecodedTrafficPermissions = resource.DecodedResource[*pbauth.TrafficPermissions] - -func RegisterTrafficPermissions(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbauth.TrafficPermissionsType, - Proto: &pbauth.TrafficPermissions{}, - ACLs: &resource.ACLHooks{ - Read: resource.DecodeAndAuthorizeRead(aclReadHookTrafficPermissions), - Write: resource.DecodeAndAuthorizeWrite(aclWriteHookTrafficPermissions), - List: resource.NoOpACLListHook, - }, - Validate: ValidateTrafficPermissions, - Mutate: MutateTrafficPermissions, - Scope: resource.ScopeNamespace, - }) -} - -var MutateTrafficPermissions = resource.DecodeAndMutate(mutateTrafficPermissions) - -func mutateTrafficPermissions(res *DecodedTrafficPermissions) (bool, error) { - var changed bool - - for _, p := range res.Data.Permissions { - for _, s := range p.Sources { - if updated := normalizedTenancyForSource(s, res.Id.Tenancy); updated { - changed = true - } - } - } - - return changed, nil -} - -func normalizedTenancyForSource(src *pbauth.Source, parentTenancy *pbresource.Tenancy) bool { - var changed bool - - if t, c := defaultedSourceTenancy(src, parentTenancy); c { - src.Partition = t.Partition - src.Peer = t.PeerName - src.Namespace = t.Namespace - changed = true - } - - for _, e := range src.Exclude { - if t, c := defaultedSourceTenancy(e, parentTenancy); c { - e.Partition = t.Partition - e.Peer = t.PeerName - e.Namespace = t.Namespace - changed = true - } - } - - return changed -} - -func defaultedSourceTenancy(s pbauth.SourceToSpiffe, parentTenancy *pbresource.Tenancy) (*pbresource.Tenancy, bool) { - if !isLocalPeer(s.GetPeer()) { - return nil, false - } - - tenancy := pbauth.SourceToTenancy(s) - - var peerChanged bool - tenancy.PeerName, peerChanged = firstNonEmptyString(tenancy.PeerName, parentTenancy.PeerName, resource.DefaultPeerName) - - var partitionChanged bool - tenancy.Partition, partitionChanged = firstNonEmptyString(tenancy.Partition, parentTenancy.Partition, resource.DefaultPartitionName) - - var namespaceChanged bool - if s.GetIdentityName() != "" { - if tenancy.Partition == parentTenancy.Partition { - tenancy.Namespace, namespaceChanged = firstNonEmptyString(tenancy.Namespace, parentTenancy.Namespace, resource.DefaultNamespaceName) - } else { - tenancy.Namespace, namespaceChanged = firstNonEmptyString(tenancy.Namespace, resource.DefaultNamespaceName, resource.DefaultNamespaceName) - } - } - - return tenancy, peerChanged || partitionChanged || namespaceChanged -} - -func firstNonEmptyString(a, b, c string) (string, bool) { - if a != "" { - return a, false - } - - if b != "" { - return b, true - } - - return c, true -} - -var ValidateTrafficPermissions = resource.DecodeAndValidate(validateTrafficPermissions) - -func validateTrafficPermissions(res *DecodedTrafficPermissions) error { - var merr error - - // enumcover:pbauth.Action - switch res.Data.Action { - case pbauth.Action_ACTION_ALLOW: - case pbauth.Action_ACTION_DENY: - case pbauth.Action_ACTION_UNSPECIFIED: - fallthrough - default: - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "data.action", - Wrapped: errInvalidAction, - }) - } - - if res.Data.Destination == nil || (len(res.Data.Destination.IdentityName) == 0) { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "data.destination", - Wrapped: resource.ErrEmpty, - }) - } - // Validate permissions - for i, permission := range res.Data.Permissions { - wrapErr := func(err error) error { - return resource.ErrInvalidListElement{ - Name: "permissions", - Index: i, - Wrapped: err, - } - } - if err := validatePermission(permission, wrapErr); err != nil { - merr = multierror.Append(merr, err) - } - } - - return merr -} - -func validatePermission(p *pbauth.Permission, wrapErr func(error) error) error { - var merr error - - if len(p.Sources) == 0 { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "sources", - Wrapped: resource.ErrEmpty, - })) - } - - for s, src := range p.Sources { - wrapSrcErr := func(err error) error { - return wrapErr(resource.ErrInvalidListElement{ - Name: "sources", - Index: s, - Wrapped: err, - }) - } - if sourceHasIncompatibleTenancies(src) { - merr = multierror.Append(merr, wrapSrcErr(resource.ErrInvalidListElement{ - Name: "source", - Wrapped: errSourcesTenancy, - })) - } - - if src.Namespace == "" && src.IdentityName != "" { - merr = multierror.Append(merr, wrapSrcErr(resource.ErrInvalidField{ - Name: "source", - Wrapped: errSourceWildcards, - })) - } - - // Excludes are only valid for wildcard sources. - if src.IdentityName != "" && len(src.Exclude) > 0 { - merr = multierror.Append(merr, wrapSrcErr(resource.ErrInvalidField{ - Name: "exclude_sources", - Wrapped: errSourceExcludes, - })) - continue - } - - for e, d := range src.Exclude { - wrapExclSrcErr := func(err error) error { - return wrapErr(resource.ErrInvalidListElement{ - Name: "exclude_sources", - Index: e, - Wrapped: err, - }) - } - if sourceHasIncompatibleTenancies(d) { - merr = multierror.Append(merr, wrapExclSrcErr(resource.ErrInvalidField{ - Name: "exclude_source", - Wrapped: errSourcesTenancy, - })) - } - - if d.Namespace == "" && d.IdentityName != "" { - merr = multierror.Append(merr, wrapExclSrcErr(resource.ErrInvalidField{ - Name: "source", - Wrapped: errSourceWildcards, - })) - } - } - } - for d, dest := range p.DestinationRules { - wrapDestRuleErr := func(err error) error { - return wrapErr(resource.ErrInvalidListElement{ - Name: "destination_rules", - Index: d, - Wrapped: err, - }) - } - // TODO: remove this when L7 traffic permissions are implemented - if len(dest.PathExact) > 0 || len(dest.PathPrefix) > 0 || len(dest.PathRegex) > 0 || len(dest.Methods) > 0 || dest.Header != nil { - merr = multierror.Append(merr, wrapDestRuleErr(resource.ErrInvalidListElement{ - Name: "destination_rule", - Wrapped: ErrL7NotSupported, - })) - } - if (len(dest.PathExact) > 0 && len(dest.PathPrefix) > 0) || - (len(dest.PathRegex) > 0 && len(dest.PathExact) > 0) || - (len(dest.PathRegex) > 0 && len(dest.PathPrefix) > 0) { - merr = multierror.Append(merr, wrapDestRuleErr(resource.ErrInvalidListElement{ - Name: "destination_rule", - Wrapped: errInvalidPrefixValues, - })) - } - if len(dest.Exclude) > 0 { - for e, excl := range dest.Exclude { - wrapExclPermRuleErr := func(err error) error { - return wrapDestRuleErr(resource.ErrInvalidListElement{ - Name: "exclude_permission_rules", - Index: e, - Wrapped: err, - }) - } - // TODO: remove this when L7 traffic permissions are implemented - if len(excl.PathExact) > 0 || len(excl.PathPrefix) > 0 || len(excl.PathRegex) > 0 || len(excl.Methods) > 0 || excl.Header != nil { - merr = multierror.Append(merr, wrapDestRuleErr(resource.ErrInvalidListElement{ - Name: "exclude_permission_rules", - Wrapped: ErrL7NotSupported, - })) - } - if (len(excl.PathExact) > 0 && len(excl.PathPrefix) > 0) || - (len(excl.PathRegex) > 0 && len(excl.PathExact) > 0) || - (len(excl.PathRegex) > 0 && len(excl.PathPrefix) > 0) { - merr = multierror.Append(merr, wrapExclPermRuleErr(resource.ErrInvalidListElement{ - Name: "exclude_permission_rule", - Wrapped: errInvalidPrefixValues, - })) - } - } - } - } - - return merr -} - -func sourceHasIncompatibleTenancies(src pbauth.SourceToSpiffe) bool { - peerSet := src.GetPeer() != resource.DefaultPeerName - apSet := src.GetPartition() != resource.DefaultPartitionName - sgSet := src.GetSamenessGroup() != "" - - return (apSet && peerSet) || (apSet && sgSet) || (peerSet && sgSet) -} - -func isLocalPeer(p string) bool { - return p == "local" || p == "" -} - -func aclReadHookTrafficPermissions(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *DecodedTrafficPermissions) error { - return authorizer.ToAllowAuthorizer().TrafficPermissionsReadAllowed(res.Data.Destination.IdentityName, authzContext) -} - -func aclWriteHookTrafficPermissions(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *DecodedTrafficPermissions) error { - return authorizer.ToAllowAuthorizer().TrafficPermissionsWriteAllowed(res.Data.Destination.IdentityName, authzContext) -} diff --git a/internal/auth/internal/types/traffic_permissions_test.go b/internal/auth/internal/types/traffic_permissions_test.go deleted file mode 100644 index 94fb165c3b8b..000000000000 --- a/internal/auth/internal/types/traffic_permissions_test.go +++ /dev/null @@ -1,838 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestValidateTrafficPermissions_ParseError(t *testing.T) { - data := &pbauth.ComputedTrafficPermissions{AllowPermissions: nil} - - res := resourcetest.Resource(pbauth.TrafficPermissionsType, "tp"). - WithData(t, data). - Build() - - err := ValidateTrafficPermissions(res) - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) -} - -func TestValidateTrafficPermissions(t *testing.T) { - cases := map[string]struct { - tp *pbauth.TrafficPermissions - expectErr string - }{ - "ok-minimal": { - tp: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{IdentityName: "wi-1"}, - Action: pbauth.Action_ACTION_ALLOW, - }, - }, - "unspecified-action": { - // Any type other than the TrafficPermissions type would work - // to cause the error we are expecting - tp: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action_ACTION_UNSPECIFIED, - Permissions: nil, - }, - expectErr: `invalid "data.action" field: action must be either allow or deny`, - }, - "invalid-action": { - tp: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "wi1", - }, - Action: pbauth.Action(50), - Permissions: nil, - }, - expectErr: `invalid "data.action" field: action must be either allow or deny`, - }, - "no-destination": { - tp: &pbauth.TrafficPermissions{ - Action: pbauth.Action_ACTION_ALLOW, - Permissions: nil, - }, - expectErr: `invalid "data.destination" field: cannot be empty`, - }, - "source-tenancy": { - tp: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "w1", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Partition: "ap1", - Peer: "cl1", - SamenessGroup: "sg1", - }, - }, - DestinationRules: nil, - }, - }, - }, - expectErr: `invalid element at index 0 of list "permissions": invalid element at index 0 of list "sources": invalid element at index 0 of list "source": permissions sources may not specify partitions, peers, and sameness_groups together`, - }, - // TODO: remove when L7 traffic permissions are implemented - "l7-fields-path": { - tp: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "w1", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Partition: "ap1", - }, - }, - DestinationRules: []*pbauth.DestinationRule{ - { - PathExact: "wi2", - }, - }, - }, - }, - }, - expectErr: `invalid element at index 0 of list "permissions": invalid element at index 0 of list "destination_rules": invalid element at index 0 of list "destination_rule": traffic permissions with L7 rules are not yet supported`, - }, - "l7-fields-methods": { - tp: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "w1", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Partition: "ap1", - }, - }, - DestinationRules: []*pbauth.DestinationRule{ - { - Methods: []string{"PUT"}, - }, - }, - }, - }, - }, - expectErr: `invalid element at index 0 of list "permissions": invalid element at index 0 of list "destination_rules": invalid element at index 0 of list "destination_rule": traffic permissions with L7 rules are not yet supported`, - }, - "l7-fields-header": { - tp: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "w1", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Partition: "ap1", - }, - }, - DestinationRules: []*pbauth.DestinationRule{ - { - Header: &pbauth.DestinationRuleHeader{Name: "foo"}, - }, - }, - }, - }, - }, - expectErr: `invalid element at index 0 of list "permissions": invalid element at index 0 of list "destination_rules": invalid element at index 0 of list "destination_rule": traffic permissions with L7 rules are not yet supported`, - }, - } - - for n, tc := range cases { - t.Run(n, func(t *testing.T) { - res := resourcetest.Resource(pbauth.TrafficPermissionsType, "tp"). - WithData(t, tc.tp). - Build() - - err := ValidateTrafficPermissions(res) - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - }) - } -} - -type permissionTestCase struct { - p *pbauth.Permission - expectErr string -} - -func permissionsTestCases() map[string]permissionTestCase { - return map[string]permissionTestCase{ - "empty": { - p: &pbauth.Permission{}, - expectErr: `invalid "sources" field: cannot be empty`, - }, - "empty-sources": { - p: &pbauth.Permission{ - Sources: nil, - DestinationRules: []*pbauth.DestinationRule{ - { - PathPrefix: "foo", - Exclude: []*pbauth.ExcludePermissionRule{ - { - PathExact: "baz", - }, - }, - }, - { - PathPrefix: "bar", - }, - }, - }, - expectErr: `invalid "sources" field: cannot be empty`, - }, - "empty-destination-rules": { - p: &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - // wildcard identity name - Namespace: "ns1", - }, - { - Namespace: "ns1", - Exclude: []*pbauth.ExcludeSource{ - // wildcard identity name - {Namespace: "ns1"}, - }, - }, - { - IdentityName: "wi-3", - Namespace: "ns1", - }, - }, - }, - }, - "explicit source with excludes": { - p: &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - IdentityName: "i1", - Exclude: []*pbauth.ExcludeSource{ - { - IdentityName: "i1", - }, - }, - }, - }, - }, - expectErr: `invalid "exclude_sources" field: must be defined on wildcard sources`, - }, - "source-partition-and-peer": { - p: &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - Partition: "ap1", - Peer: "cluster-01", - }, - }, - }, - expectErr: `permissions sources may not specify partitions, peers, and sameness_groups together`, - }, - "source-partition-and-sameness-group": { - p: &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - Partition: "ap1", - SamenessGroup: "sg-1", - }, - }, - }, - expectErr: `permissions sources may not specify partitions, peers, and sameness_groups together`, - }, - "source-peer-and-sameness-group": { - p: &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - Partition: "ap1", - SamenessGroup: "sg-1", - }, - }, - }, - expectErr: `permissions sources may not specify partitions, peers, and sameness_groups together`, - }, - "exclude-source-partition-and-peer": { - p: &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - Exclude: []*pbauth.ExcludeSource{ - { - Partition: "ap1", - Peer: "cluster-01", - }, - }, - }, - }, - }, - expectErr: `permissions sources may not specify partitions, peers, and sameness_groups together`, - }, - "exclude-source-partition-and-sameness-group": { - p: &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - Exclude: []*pbauth.ExcludeSource{ - { - Partition: "ap1", - SamenessGroup: "sg-1", - }, - }, - }, - }, - }, - expectErr: `permissions sources may not specify partitions, peers, and sameness_groups together`, - }, - "exclude-source-peer-and-sameness-group": { - p: &pbauth.Permission{ - Sources: []*pbauth.Source{ - { - Exclude: []*pbauth.ExcludeSource{ - { - Peer: "ap1", - SamenessGroup: "sg-1", - }, - }, - }, - }, - }, - expectErr: `permissions sources may not specify partitions, peers, and sameness_groups together`, - }, - "destination-rule-path-prefix-regex": { - p: &pbauth.Permission{ - Sources: nil, - DestinationRules: []*pbauth.DestinationRule{ - { - PathExact: "wi2", - PathPrefix: "wi", - PathRegex: "wi.*", - }, - }, - }, - expectErr: `invalid element at index 0 of list "destination_rule": prefix values, regex values, and explicit names must not combined`, - }, - } -} - -func TestValidateTrafficPermissions_Permissions(t *testing.T) { - for n, tc := range permissionsTestCases() { - t.Run(n, func(t *testing.T) { - tp := &pbauth.TrafficPermissions{ - Action: pbauth.Action_ACTION_ALLOW, - Destination: &pbauth.Destination{ - IdentityName: "w1", - }, - Permissions: []*pbauth.Permission{tc.p}, - } - - res := resourcetest.Resource(pbauth.TrafficPermissionsType, "tp"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, tp). - Build() - - err := MutateTrafficPermissions(res) - require.NoError(t, err) - - err = ValidateTrafficPermissions(res) - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - }) - } -} - -func TestMutateTrafficPermissions(t *testing.T) { - type testcase struct { - policyTenancy *pbresource.Tenancy - tp *pbauth.TrafficPermissions - expect *pbauth.TrafficPermissions - expectErr string - } - - run := func(t *testing.T, tc testcase) { - tenancy := tc.policyTenancy - if tenancy == nil { - tenancy = resource.DefaultNamespacedTenancy() - } - res := resourcetest.Resource(pbauth.TrafficPermissionsType, "api"). - WithTenancy(tenancy). - WithData(t, tc.tp). - Build() - - err := MutateTrafficPermissions(res) - - got := resourcetest.MustDecode[*pbauth.TrafficPermissions](t, res) - - if tc.expectErr == "" { - require.NoError(t, err) - prototest.AssertDeepEqual(t, tc.expect, got.Data) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "empty-1": { - tp: &pbauth.TrafficPermissions{}, - expect: &pbauth.TrafficPermissions{}, - }, - "kitchen-sink-default-partition": { - tp: &pbauth.TrafficPermissions{ - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - {}, - { - Peer: "not-default", - }, - { - Namespace: "ns1", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Partition: "ap1", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Peer: "local", - }, - }, - }, - }, - }, - expect: &pbauth.TrafficPermissions{ - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Partition: "default", - Peer: "local", - }, - { - Peer: "not-default", - }, - { - Namespace: "ns1", - Partition: "default", - Peer: "local", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Partition: "ap1", - Peer: "local", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Partition: "default", - Peer: "local", - }, - }, - }, - }, - }, - }, - "kitchen-sink-excludes-default-partition": { - tp: &pbauth.TrafficPermissions{ - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Exclude: []*pbauth.ExcludeSource{ - {}, - { - Peer: "not-default", - }, - { - Namespace: "ns1", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Partition: "ap1", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Peer: "local", - }, - }, - }, - }, - }, - }, - }, - expect: &pbauth.TrafficPermissions{ - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Partition: "default", - Peer: "local", - Exclude: []*pbauth.ExcludeSource{ - { - Partition: "default", - Peer: "local", - }, - { - Peer: "not-default", - }, - { - Namespace: "ns1", - Partition: "default", - Peer: "local", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Partition: "ap1", - Peer: "local", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Partition: "default", - Peer: "local", - }, - }, - }, - }, - }, - }, - }, - }, - "kitchen-sink-non-default-partition": { - policyTenancy: &pbresource.Tenancy{ - Partition: "ap1", - Namespace: "ns3", - PeerName: "local", - }, - tp: &pbauth.TrafficPermissions{ - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - {}, - { - Peer: "not-default", - }, - { - Namespace: "ns1", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Partition: "ap5", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Peer: "local", - }, - { - IdentityName: "i2", - }, - { - IdentityName: "i2", - Partition: "non-default", - }, - }, - }, - }, - }, - expect: &pbauth.TrafficPermissions{ - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Partition: "ap1", - Namespace: "", - Peer: "local", - }, - { - Peer: "not-default", - }, - { - Namespace: "ns1", - Partition: "ap1", - Peer: "local", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Partition: "ap5", - Peer: "local", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Partition: "ap1", - Peer: "local", - }, - { - IdentityName: "i2", - Namespace: "ns3", - Partition: "ap1", - Peer: "local", - }, - { - IdentityName: "i2", - Namespace: "default", - Partition: "non-default", - Peer: "local", - }, - }, - }, - }, - }, - }, - "kitchen-sink-excludes-non-default-partition": { - policyTenancy: &pbresource.Tenancy{ - Partition: "ap1", - Namespace: "ns3", - PeerName: "local", - }, - tp: &pbauth.TrafficPermissions{ - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Exclude: []*pbauth.ExcludeSource{ - {}, - { - Peer: "not-default", - }, - { - Namespace: "ns1", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Partition: "ap5", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Peer: "local", - }, - { - IdentityName: "i2", - }, - }, - }, - }, - }, - }, - }, - expect: &pbauth.TrafficPermissions{ - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Partition: "ap1", - Peer: "local", - Exclude: []*pbauth.ExcludeSource{ - { - Partition: "ap1", - Namespace: "", - Peer: "local", - }, - { - Peer: "not-default", - }, - { - Namespace: "ns1", - Partition: "ap1", - Peer: "local", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Partition: "ap5", - Peer: "local", - }, - { - IdentityName: "i1", - Namespace: "ns1", - Partition: "ap1", - Peer: "local", - }, - { - IdentityName: "i2", - Namespace: "ns3", - Partition: "ap1", - Peer: "local", - }, - }, - }, - }, - }, - }, - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestTrafficPermissionsACLs(t *testing.T) { - // Wire up a registry to generically invoke hooks - registry := resource.NewRegistry() - Register(registry) - - type testcase struct { - rules string - check func(t *testing.T, authz acl.Authorizer, res *pbresource.Resource) - readOK string - writeOK string - listOK string - } - - const ( - DENY = "deny" - ALLOW = "allow" - DEFAULT = "default" - ) - - checkF := func(t *testing.T, expect string, got error) { - switch expect { - case ALLOW: - if acl.IsErrPermissionDenied(got) { - t.Fatal("should be allowed") - } - case DENY: - if !acl.IsErrPermissionDenied(got) { - t.Fatal("should be denied") - } - case DEFAULT: - require.Nil(t, got, "expected fallthrough decision") - default: - t.Fatalf("unexpected expectation: %q", expect) - } - } - - reg, ok := registry.Resolve(pbauth.TrafficPermissionsType) - require.True(t, ok) - - run := func(t *testing.T, tc testcase) { - tpData := &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{IdentityName: "wi1"}, - Action: pbauth.Action_ACTION_ALLOW, - } - res := resourcetest.Resource(pbauth.TrafficPermissionsType, "tp1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, tpData). - Build() - resourcetest.ValidateAndNormalize(t, registry, res) - - config := acl.Config{ - WildcardName: structs.WildcardSpecifier, - } - authz, err := acl.NewAuthorizerFromRules(tc.rules, &config, nil) - require.NoError(t, err) - authz = acl.NewChainedAuthorizer([]acl.Authorizer{authz, acl.DenyAll()}) - - t.Run("read", func(t *testing.T) { - err := reg.ACLs.Read(authz, &acl.AuthorizerContext{}, res.Id, res) - checkF(t, tc.readOK, err) - }) - t.Run("write", func(t *testing.T) { - err := reg.ACLs.Write(authz, &acl.AuthorizerContext{}, res) - checkF(t, tc.writeOK, err) - }) - t.Run("list", func(t *testing.T) { - err := reg.ACLs.List(authz, &acl.AuthorizerContext{}) - checkF(t, tc.listOK, err) - }) - } - - cases := map[string]testcase{ - "no rules": { - rules: ``, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity w1 read, no intentions": { - rules: `identity "wi1" { policy = "read" }`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity w1 read, deny intentions": { - rules: `identity "wi1" { policy = "read", intentions = "deny" }`, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity w1 read, intentions read": { - rules: `identity "wi1" { policy = "read", intentions = "read" }`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity w1 write, write intentions": { - rules: `identity "wi1" { policy = "read", intentions = "write" }`, - readOK: ALLOW, - writeOK: ALLOW, - listOK: DEFAULT, - }, - "workload identity w1 write, deny intentions": { - rules: `identity "wi1" { policy = "write", intentions = "deny" }`, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity w1 write, intentions read": { - rules: `identity "wi1" { policy = "write", intentions = "read" }`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity w1 write, intentions write": { - rules: `identity "wi1" { policy = "write", intentions = "write" }`, - readOK: ALLOW, - writeOK: ALLOW, - listOK: DEFAULT, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/auth/internal/types/types.go b/internal/auth/internal/types/types.go deleted file mode 100644 index 46fc49e1b75f..000000000000 --- a/internal/auth/internal/types/types.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/internal/resource" -) - -func Register(r resource.Registry) { - RegisterWorkloadIdentity(r) - RegisterTrafficPermissions(r) - RegisterComputedTrafficPermission(r) -} diff --git a/internal/auth/internal/types/workload_identity.go b/internal/auth/internal/types/workload_identity.go deleted file mode 100644 index a15fd5bf5b2d..000000000000 --- a/internal/auth/internal/types/workload_identity.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type DecodedWorkloadIdentity = resource.DecodedResource[*pbauth.WorkloadIdentity] - -func RegisterWorkloadIdentity(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbauth.WorkloadIdentityType, - Proto: &pbauth.WorkloadIdentity{}, - Scope: resource.ScopeNamespace, - ACLs: &resource.ACLHooks{ - Read: aclReadHookWorkloadIdentity, - Write: aclWriteHookWorkloadIdentity, - List: resource.NoOpACLListHook, - }, - Validate: ValidateWorkloadIdentity, - }) -} - -var ValidateWorkloadIdentity = resource.DecodeAndValidate(validateWorkloadIdentity) - -func validateWorkloadIdentity(res *DecodedWorkloadIdentity) error { - // currently the WorkloadIdentity type has no fields. - return nil -} - -func aclReadHookWorkloadIdentity( - authorizer acl.Authorizer, - authzCtx *acl.AuthorizerContext, - id *pbresource.ID, - res *pbresource.Resource, -) error { - if id != nil { - return authorizer.ToAllowAuthorizer().IdentityReadAllowed(id.Name, authzCtx) - } - if res != nil { - return authorizer.ToAllowAuthorizer().IdentityReadAllowed(res.Id.Name, authzCtx) - } - return resource.ErrNeedResource -} - -func aclWriteHookWorkloadIdentity( - authorizer acl.Authorizer, - authzCtx *acl.AuthorizerContext, - res *pbresource.Resource) error { - if res == nil { - return resource.ErrNeedResource - } - return authorizer.ToAllowAuthorizer().IdentityWriteAllowed(res.Id.Name, authzCtx) -} diff --git a/internal/auth/internal/types/workload_identity_test.go b/internal/auth/internal/types/workload_identity_test.go deleted file mode 100644 index 19ed4cbeea87..000000000000 --- a/internal/auth/internal/types/workload_identity_test.go +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func TestWorkloadIdentityACLs(t *testing.T) { - const ( - DENY = "deny" - ALLOW = "allow" - DEFAULT = "default" - ) - - registry := resource.NewRegistry() - Register(registry) - - reg, ok := registry.Resolve(pbauth.WorkloadIdentityType) - require.True(t, ok) - - type testcase struct { - rules string - check func(t *testing.T, authz acl.Authorizer, res *pbresource.Resource) - readOK string - writeOK string - listOK string - } - - checkF := func(t *testing.T, expect string, got error) { - switch expect { - case ALLOW: - if acl.IsErrPermissionDenied(got) { - t.Fatal("should be allowed") - } - case DENY: - if !acl.IsErrPermissionDenied(got) { - t.Fatal("should be denied") - } - case DEFAULT: - require.Nil(t, got, "expected fallthrough decision") - default: - t.Fatalf("unexpected expectation: %q", expect) - } - } - - run := func(t *testing.T, tc testcase) { - wid := &pbauth.WorkloadIdentity{} - res := resourcetest.Resource(pbauth.WorkloadIdentityType, "wi1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, wid). - Build() - resourcetest.ValidateAndNormalize(t, registry, res) - - config := acl.Config{ - WildcardName: structs.WildcardSpecifier, - } - authz, err := acl.NewAuthorizerFromRules(tc.rules, &config, nil) - require.NoError(t, err) - authz = acl.NewChainedAuthorizer([]acl.Authorizer{authz, acl.DenyAll()}) - - t.Run("read", func(t *testing.T) { - err := reg.ACLs.Read(authz, &acl.AuthorizerContext{}, res.Id, res) - checkF(t, tc.readOK, err) - }) - t.Run("write", func(t *testing.T) { - err := reg.ACLs.Write(authz, &acl.AuthorizerContext{}, res) - checkF(t, tc.writeOK, err) - }) - t.Run("list", func(t *testing.T) { - err := reg.ACLs.List(authz, &acl.AuthorizerContext{}) - checkF(t, tc.listOK, err) - }) - t.Run("errors", func(t *testing.T) { - require.ErrorIs(t, reg.ACLs.Read(authz, &acl.AuthorizerContext{}, nil, nil), resource.ErrNeedResource) - require.ErrorIs(t, reg.ACLs.Write(authz, &acl.AuthorizerContext{}, nil), resource.ErrNeedResource) - }) - } - - cases := map[string]testcase{ - "no rules": { - rules: ``, - readOK: DENY, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity wi1 read, no intentions": { - rules: `identity "wi1" { policy = "read" }`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity wi1 read, deny intentions has no effect": { - rules: `identity "wi1" { policy = "read", intentions = "deny" }`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity wi1 read, intentions read has no effect": { - rules: `identity "wi1" { policy = "read", intentions = "read" }`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity wi1 write, write intentions has no effect": { - rules: `identity "wi1" { policy = "read", intentions = "write" }`, - readOK: ALLOW, - writeOK: DENY, - listOK: DEFAULT, - }, - "workload identity wi1 write, deny intentions has no effect": { - rules: `identity "wi1" { policy = "write", intentions = "deny" }`, - readOK: ALLOW, - writeOK: ALLOW, - listOK: DEFAULT, - }, - "workload identity wi1 write, intentions read has no effect": { - rules: `identity "wi1" { policy = "write", intentions = "read" }`, - readOK: ALLOW, - writeOK: ALLOW, - listOK: DEFAULT, - }, - "workload identity wi1 write, intentions write": { - rules: `identity "wi1" { policy = "write", intentions = "write" }`, - readOK: ALLOW, - writeOK: ALLOW, - listOK: DEFAULT, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestWorkloadIdentity_ParseError(t *testing.T) { - rsc := resourcetest.Resource(pbauth.WorkloadIdentityType, "example"). - WithData(t, &pbauth.TrafficPermissions{}). - Build() - - err := ValidateWorkloadIdentity(rsc) - var parseErr resource.ErrDataParse - require.ErrorAs(t, err, &parseErr) -} diff --git a/internal/catalog/catalogtest/helpers/acl_hooks_test_helpers.go b/internal/catalog/catalogtest/helpers/acl_hooks_test_helpers.go deleted file mode 100644 index 097647ed08d1..000000000000 --- a/internal/catalog/catalogtest/helpers/acl_hooks_test_helpers.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package helpers - -import ( - "testing" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/catalog/internal/testhelpers" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func RunWorkloadSelectingTypeACLsTests[T catalog.WorkloadSelecting](t *testing.T, typ *pbresource.Type, - getData func(selector *pbcatalog.WorkloadSelector) T, - registerFunc func(registry resource.Registry), -) { - testhelpers.RunWorkloadSelectingTypeACLsTests[T](t, typ, getData, registerFunc) -} diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-service.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-service.json deleted file mode 100644 index 5509e726d8dc..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-service.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Service" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Service", - "workloads": { - "prefixes": [ - "api-" - ] - }, - "ports": [ - { - "target_port": "http", - "protocol": "PROTOCOL_HTTP" - }, - { - "target_port": "grpc", - "protocol": "PROTOCOL_GRPC" - }, - { - "target_port": "mesh", - "protocol": "PROTOCOL_MESH" - } - ] - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-1-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-1-health.json deleted file mode 100644 index d64671960ad7..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-1-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-1-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-1" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_PASSING" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-1.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-1.json deleted file mode 100644 index fe7d6318fb50..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-1.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-1" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.1" - }, - { - "host": "198.18.2.1", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-1" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-10-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-10-health.json deleted file mode 100644 index f1f4c0596887..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-10-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-10-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-10" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_WARNING" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-10.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-10.json deleted file mode 100644 index 768cab21d020..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-10.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-10" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.10" - }, - { - "host": "198.18.2.10", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-3" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-11-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-11-health.json deleted file mode 100644 index 4c266d4e2a76..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-11-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-11-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-11" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_CRITICAL" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-11.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-11.json deleted file mode 100644 index c0110034565f..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-11.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-11" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.11" - }, - { - "host": "198.18.2.11", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-3" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-12-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-12-health.json deleted file mode 100644 index 9b8079ed4a8d..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-12-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-12-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-12" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_MAINTENANCE" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-12.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-12.json deleted file mode 100644 index 0c406c0ecdcb..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-12.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-12" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.12" - }, - { - "host": "198.18.2.12", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-3" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-13-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-13-health.json deleted file mode 100644 index 346ebfb2f489..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-13-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-13-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-13" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_PASSING" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-13.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-13.json deleted file mode 100644 index acedb1ebd477..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-13.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-13" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.13" - }, - { - "host": "198.18.2.13", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-4" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-14-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-14-health.json deleted file mode 100644 index 9a97dfda1439..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-14-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-14-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-14" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_WARNING" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-14.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-14.json deleted file mode 100644 index fefe9dabcf3b..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-14.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-14" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.14" - }, - { - "host": "198.18.2.14", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-4" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-15-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-15-health.json deleted file mode 100644 index b289dd269e68..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-15-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-15-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-15" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_CRITICAL" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-15.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-15.json deleted file mode 100644 index faddd57fe704..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-15.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-15" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.15" - }, - { - "host": "198.18.2.15", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-4" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-16-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-16-health.json deleted file mode 100644 index e4de67be793e..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-16-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-16-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-16" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_MAINTENANCE" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-16.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-16.json deleted file mode 100644 index 46590c467fb3..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-16.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-16" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.16" - }, - { - "host": "198.18.2.16", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-4" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-17-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-17-health.json deleted file mode 100644 index e9955bf2097e..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-17-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-17-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-17" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_PASSING" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-17.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-17.json deleted file mode 100644 index bf3069201f5d..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-17.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-17" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.17" - }, - { - "host": "198.18.2.17", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-18-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-18-health.json deleted file mode 100644 index ec8490601267..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-18-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-18-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-18" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_WARNING" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-18.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-18.json deleted file mode 100644 index cb96652199b6..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-18.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-18" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.18" - }, - { - "host": "198.18.2.18", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-19-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-19-health.json deleted file mode 100644 index d353aac240e2..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-19-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-19-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-19" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_CRITICAL" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-19.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-19.json deleted file mode 100644 index dcf2cf4b0340..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-19.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-19" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.19" - }, - { - "host": "198.18.2.19", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-2-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-2-health.json deleted file mode 100644 index 08165a75d0a6..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-2-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-2-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-2" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_WARNING" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-2.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-2.json deleted file mode 100644 index cc2ea0fdc26e..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-2.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-2" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.2" - }, - { - "host": "198.18.2.2", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-1" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-20-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-20-health.json deleted file mode 100644 index 49283150584c..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-20-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-20-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-20" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_MAINTENANCE" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-20.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-20.json deleted file mode 100644 index 315874eeaf2b..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-20.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-20" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.20" - }, - { - "host": "198.18.2.20", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-3-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-3-health.json deleted file mode 100644 index 44bc2a3531bb..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-3-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-3-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-3" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_CRITICAL" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-3.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-3.json deleted file mode 100644 index 2ecd501d6e98..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-3.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-3" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.3" - }, - { - "host": "198.18.2.3", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-1" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-4-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-4-health.json deleted file mode 100644 index 5ead7793f120..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-4-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-4-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-4" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_MAINTENANCE" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-4.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-4.json deleted file mode 100644 index 639fdd3f6773..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-4.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-4" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.4" - }, - { - "host": "198.18.2.4", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-1" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-5-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-5-health.json deleted file mode 100644 index f2f1013f2021..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-5-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-5-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-5" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_PASSING" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-5.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-5.json deleted file mode 100644 index 0e19253d4df5..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-5.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-5" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.5" - }, - { - "host": "198.18.2.5", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-2" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-6-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-6-health.json deleted file mode 100644 index ef0bef454b66..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-6-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-6-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-6" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_WARNING" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-6.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-6.json deleted file mode 100644 index fe9780e94698..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-6.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-6" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.6" - }, - { - "host": "198.18.2.6", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-2" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-7-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-7-health.json deleted file mode 100644 index f3c963481e0d..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-7-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-7-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-7" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_CRITICAL" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-7.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-7.json deleted file mode 100644 index 7199c042b8a6..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-7.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-7" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.7" - }, - { - "host": "198.18.2.7", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-2" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-8-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-8-health.json deleted file mode 100644 index e55348b1ea35..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-8-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-8-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-8" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_MAINTENANCE" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-8.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-8.json deleted file mode 100644 index 8828e1ee2653..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-8.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-8" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.8" - }, - { - "host": "198.18.2.8", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-2" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-9-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-9-health.json deleted file mode 100644 index 81ac189b173b..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-9-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-9-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-9" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_PASSING" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-9.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-9.json deleted file mode 100644 index 1c02d466fbfe..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/api-workload-9.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Workload" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "api-9" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Workload", - "addresses": [ - { - "host": "172.16.1.9" - }, - { - "host": "198.18.2.9", - "external": true, - "ports": [ - "mesh" - ] - } - ], - "ports": { - "http": { - "port": 8080, - "protocol": "PROTOCOL_HTTP" - }, - "grpc": { - "port": 9090, - "protocol": "PROTOCOL_GRPC" - }, - "mesh": { - "port": 10000, - "protocol": "PROTOCOL_MESH" - } - }, - "identity": "api", - "node_name": "node-3" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/foo-service-endpoints.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/foo-service-endpoints.json deleted file mode 100644 index fe7925a88501..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/foo-service-endpoints.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "ServiceEndpoints" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "foo" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Service" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "foo" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.ServiceEndpoints", - "endpoints": [ - { - "addresses": [ - { - "host": "198.18.0.1" - } - ], - "ports": { - "external-service-port": { - "port": 9876, - "protocol": "PROTOCOL_HTTP2" - } - }, - "health_status": "HEALTH_PASSING" - } - ] - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/foo-service.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/foo-service.json deleted file mode 100644 index bbe87511e17e..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/foo-service.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Service" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "foo" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Service", - "ports": [ - { - "target_port": "external-service-port", - "protocol": "PROTOCOL_HTTP2" - } - ] - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/grpc-api-service.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/grpc-api-service.json deleted file mode 100644 index 7dff2ee10ff3..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/grpc-api-service.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Service" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "grpc-api" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Service", - "workloads": { - "names": [ - "api-1", - "api-2", - "api-3", - "api-4", - "api-5", - "api-6", - "api-7", - "api-8", - "api-9", - "api-20" - ] - }, - "ports": [ - { - "target_port": "grpc", - "protocol": "PROTOCOL_GRPC" - }, - { - "target_port": "mesh", - "protocol": "PROTOCOL_MESH" - } - ] - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/http-api-service.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/http-api-service.json deleted file mode 100644 index 02b80d29aef6..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/http-api-service.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Service" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "http-api" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Service", - "workloads": { - "prefixes": [ - "api-1" - ] - }, - "ports": [ - { - "target_port": "http", - "protocol": "PROTOCOL_HTTP" - } - ] - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-1-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/node-1-health.json deleted file mode 100644 index 705eeb6ced26..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-1-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "node-1-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Node" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "node-1" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_PASSING" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-1.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/node-1.json deleted file mode 100644 index a190e5bc1ab1..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-1.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Node" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "node-1" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Node", - "addresses": [ - { - "host": "198.18.1.1", - "external": true - }, - { - "host": "172.16.0.1" - } - ] - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-2-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/node-2-health.json deleted file mode 100644 index 1e9baaefde5e..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-2-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "node-2-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Node" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "node-2" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_WARNING" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-2.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/node-2.json deleted file mode 100644 index 218f8d1ae35b..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-2.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Node" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "node-2" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Node", - "addresses": [ - { - "host": "198.18.1.2", - "external": true - }, - { - "host": "172.16.0.2" - } - ] - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-3-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/node-3-health.json deleted file mode 100644 index 5e2df1a13f8b..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-3-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "node-3-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Node" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "node-3" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_CRITICAL" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-3.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/node-3.json deleted file mode 100644 index f02361cd58fa..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-3.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Node" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "node-3" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Node", - "addresses": [ - { - "host": "198.18.1.3", - "external": true - }, - { - "host": "172.16.0.3" - } - ] - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-4-health.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/node-4-health.json deleted file mode 100644 index f403c929b4ea..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-4-health.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "HealthStatus" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "node-4-health" - }, - "owner": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Node" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "node-4" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.HealthStatus", - "type": "synthetic", - "status": "HEALTH_MAINTENANCE" - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-4.json b/internal/catalog/catalogtest/integration_test_data/v2beta1/node-4.json deleted file mode 100644 index c66e70fd0c64..000000000000 --- a/internal/catalog/catalogtest/integration_test_data/v2beta1/node-4.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": { - "type": { - "group": "catalog", - "group_version": "v2beta1", - "kind": "Node" - }, - "tenancy": { - "partition": "default", - "namespace": "default", - "peer_name": "local" - }, - "name": "node-4" - }, - "data": { - "@type": "hashicorp.consul.catalog.v2beta1.Node", - "addresses": [ - { - "host": "198.18.1.4", - "external": true - }, - { - "host": "172.16.0.4" - } - ] - } -} \ No newline at end of file diff --git a/internal/catalog/catalogtest/run_test.go b/internal/catalog/catalogtest/run_test.go deleted file mode 100644 index 5a6e1e62e354..000000000000 --- a/internal/catalog/catalogtest/run_test.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package catalogtest - -import ( - "testing" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/catalog/internal/controllers" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource/reaper" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" -) - -func runInMemResourceServiceAndControllers(t *testing.T, deps controllers.Dependencies) pbresource.ResourceServiceClient { - t.Helper() - - ctx := testutil.TestContext(t) - - // Create the in-mem resource service - client := svctest.RunResourceService(t, catalog.RegisterTypes) - - // Setup/Run the controller manager - mgr := controller.NewManager(client, testutil.Logger(t)) - catalog.RegisterControllers(mgr, deps) - - // We also depend on the reaper to take care of cleaning up owned health statuses and - // service endpoints so we must enable that controller as well - reaper.RegisterControllers(mgr) - mgr.SetRaftLeader(true) - go mgr.Run(ctx) - - return client -} - -func TestControllers_Integration(t *testing.T) { - client := runInMemResourceServiceAndControllers(t, catalog.DefaultControllerDependencies()) - RunCatalogV2Beta1IntegrationTest(t, client) -} - -func TestControllers_Lifecycle(t *testing.T) { - client := runInMemResourceServiceAndControllers(t, catalog.DefaultControllerDependencies()) - RunCatalogV2Beta1LifecycleIntegrationTest(t, client) -} diff --git a/internal/catalog/catalogtest/test_integration_v2beta1.go b/internal/catalog/catalogtest/test_integration_v2beta1.go deleted file mode 100644 index 79ffea7e7953..000000000000 --- a/internal/catalog/catalogtest/test_integration_v2beta1.go +++ /dev/null @@ -1,752 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package catalogtest - -import ( - "embed" - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/catalog/internal/controllers/endpoints" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/nodehealth" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/workloadhealth" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -var ( - //go:embed integration_test_data - testData embed.FS -) - -// RunCatalogV2Beta1IntegrationTest will push up a bunch of catalog related data and then -// verify that all the expected reconciliations happened correctly. This test is -// intended to exercise a large swathe of behavior of the overall catalog package. -// Besides just controller reconciliation behavior, the intent is also to verify -// that integrations with the resource service are also working (i.e. the various -// validation, mutation and ACL hooks get invoked and are working properly) -// -// This test specifically is not doing any sort of lifecycle related tests to ensure -// that modification to values results in re-reconciliation as expected. Instead there -// is another RunCatalogIntegrationTestLifeCycle function that can be used for those -// purposes. The two are distinct so that the data being published and the assertions -// made against the system can be reused in upgrade tests. -func RunCatalogV2Beta1IntegrationTest(t *testing.T, client pbresource.ResourceServiceClient) { - t.Helper() - - PublishCatalogV2Beta1IntegrationTestData(t, client) - VerifyCatalogV2Beta1IntegrationTestResults(t, client) -} - -// PublishCatalogV2Beta1IntegrationTestData will perform a whole bunch of resource writes -// for Service, ServiceEndpoints, Workload, Node and HealthStatus objects -func PublishCatalogV2Beta1IntegrationTestData(t *testing.T, client pbresource.ResourceServiceClient) { - t.Helper() - - c := rtest.NewClient(client) - - resources := rtest.ParseResourcesFromFilesystem(t, testData, "integration_test_data/v2beta1") - c.PublishResources(t, resources) -} - -func VerifyCatalogV2Beta1IntegrationTestResults(t *testing.T, client pbresource.ResourceServiceClient) { - t.Helper() - - c := rtest.NewClient(client) - - testutil.RunStep(t, "resources-exist", func(t *testing.T) { - c.RequireResourceExists(t, rtest.Resource(pbcatalog.ServiceType, "api").ID()) - c.RequireResourceExists(t, rtest.Resource(pbcatalog.ServiceType, "http-api").ID()) - c.RequireResourceExists(t, rtest.Resource(pbcatalog.ServiceType, "grpc-api").ID()) - c.RequireResourceExists(t, rtest.Resource(pbcatalog.ServiceType, "foo").ID()) - - for i := 1; i < 5; i++ { - nodeId := rtest.Resource(pbcatalog.NodeType, fmt.Sprintf("node-%d", i)).WithTenancy(resource.DefaultNamespacedTenancy()).ID() - c.RequireResourceExists(t, nodeId) - - res := c.RequireResourceExists(t, rtest.Resource(pbcatalog.HealthStatusType, fmt.Sprintf("node-%d-health", i)).ID()) - rtest.RequireOwner(t, res, nodeId, true) - } - - for i := 1; i < 21; i++ { - workloadId := rtest.Resource(pbcatalog.WorkloadType, fmt.Sprintf("api-%d", i)).WithTenancy(resource.DefaultNamespacedTenancy()).ID() - c.RequireResourceExists(t, workloadId) - - res := c.RequireResourceExists(t, rtest.Resource(pbcatalog.HealthStatusType, fmt.Sprintf("api-%d-health", i)).ID()) - rtest.RequireOwner(t, res, workloadId, true) - } - }) - - testutil.RunStep(t, "node-health-reconciliation", func(t *testing.T) { - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.NodeType, "node-1").ID(), nodehealth.StatusKey, nodehealth.ConditionPassing) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.NodeType, "node-2").ID(), nodehealth.StatusKey, nodehealth.ConditionWarning) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.NodeType, "node-3").ID(), nodehealth.StatusKey, nodehealth.ConditionCritical) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.NodeType, "node-4").ID(), nodehealth.StatusKey, nodehealth.ConditionMaintenance) - }) - - testutil.RunStep(t, "workload-health-reconciliation", func(t *testing.T) { - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-1").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadPassing) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-2").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadWarning) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-3").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadCritical) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-4").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadMaintenance) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-5").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeWarning) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-6").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadWarning) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-7").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadCritical) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-8").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadMaintenance) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-9").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeCritical) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-10").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadCritical) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-11").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadCritical) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-12").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadMaintenance) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-13").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeMaintenance) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-14").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadMaintenance) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-15").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadMaintenance) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-16").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadMaintenance) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-17").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadPassing) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-18").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadWarning) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-19").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadCritical) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.WorkloadType, "api-20").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadMaintenance) - }) - - testutil.RunStep(t, "service-reconciliation", func(t *testing.T) { - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.ServiceType, "foo").ID(), endpoints.StatusKey, endpoints.ConditionUnmanaged) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.ServiceType, "api").ID(), endpoints.StatusKey, endpoints.ConditionManaged) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.ServiceType, "http-api").ID(), endpoints.StatusKey, endpoints.ConditionManaged) - c.WaitForStatusCondition(t, rtest.Resource(pbcatalog.ServiceType, "grpc-api").ID(), endpoints.StatusKey, endpoints.ConditionManaged) - }) - - testutil.RunStep(t, "service-endpoints-generation", func(t *testing.T) { - verifyServiceEndpoints(t, c, rtest.Resource(pbcatalog.ServiceEndpointsType, "foo").ID(), expectedFooServiceEndpoints()) - verifyServiceEndpoints(t, c, rtest.Resource(pbcatalog.ServiceEndpointsType, "api").ID(), expectedApiServiceEndpoints(t, c)) - verifyServiceEndpoints(t, c, rtest.Resource(pbcatalog.ServiceEndpointsType, "http-api").ID(), expectedHTTPApiServiceEndpoints(t, c)) - verifyServiceEndpoints(t, c, rtest.Resource(pbcatalog.ServiceEndpointsType, "grpc-api").ID(), expectedGRPCApiServiceEndpoints(t, c)) - }) -} - -func expectedFooServiceEndpoints() *pbcatalog.ServiceEndpoints { - return &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "198.18.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "external-service-port": { - Port: 9876, - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, - }, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - }, - } -} - -func expectedApiServiceEndpoints(t *testing.T, c *rtest.Client) *pbcatalog.ServiceEndpoints { - return &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - // api-1 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-1").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.1", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.1", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }, - // api-2 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-2").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.2", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.2", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_WARNING, - Identity: "api", - }, - // api-3 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-3").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.3", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.3", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - // api-4 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-4").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.4", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.4", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-5 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-5").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.5", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.5", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_WARNING, - Identity: "api", - }, - // api-6 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-6").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.6", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.6", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_WARNING, - Identity: "api", - }, - // api-7 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-7").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.7", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.7", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - // api-8 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-8").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.8", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.8", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-9 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-9").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.9", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.9", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - // api-10 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-10").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.10", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.10", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - // api-11 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-11").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.11", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.11", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - // api-12 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-12").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.12", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.12", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-13 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-13").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.13", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.13", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-14 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-14").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.14", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.14", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-15 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-15").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.15", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.15", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-16 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-16").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.16", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.16", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-17 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-17").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.17", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.17", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }, - // api-18 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-18").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.18", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.18", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_WARNING, - Identity: "api", - }, - // api-19 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-19").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.19", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.19", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - // api-20 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-20").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.20", Ports: []string{"grpc", "http", "mesh"}}, - {Host: "198.18.2.20", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - }, - } -} - -func expectedHTTPApiServiceEndpoints(t *testing.T, c *rtest.Client) *pbcatalog.ServiceEndpoints { - return &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - // api-1 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-1").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.1", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }, - // api-10 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-10").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.10", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - // api-11 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-11").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.11", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - // api-12 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-12").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.12", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-13 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-13").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.13", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-14 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-14").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.14", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-15 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-15").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.15", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-16 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-16").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.16", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-17 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-17").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.17", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }, - // api-18 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-18").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.18", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_WARNING, - Identity: "api", - }, - // api-19 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-19").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.19", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - }, - } -} - -func expectedGRPCApiServiceEndpoints(t *testing.T, c *rtest.Client) *pbcatalog.ServiceEndpoints { - return &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - // api-1 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-1").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.1", Ports: []string{"grpc", "mesh"}}, - {Host: "198.18.2.1", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }, - // api-2 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-2").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.2", Ports: []string{"grpc", "mesh"}}, - {Host: "198.18.2.2", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_WARNING, - Identity: "api", - }, - // api-3 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-3").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.3", Ports: []string{"grpc", "mesh"}}, - {Host: "198.18.2.3", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - // api-4 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-4").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.4", Ports: []string{"grpc", "mesh"}}, - {Host: "198.18.2.4", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-5 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-5").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.5", Ports: []string{"grpc", "mesh"}}, - {Host: "198.18.2.5", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_WARNING, - Identity: "api", - }, - // api-6 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-6").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.6", Ports: []string{"grpc", "mesh"}}, - {Host: "198.18.2.6", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_WARNING, - Identity: "api", - }, - // api-7 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-7").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.7", Ports: []string{"grpc", "mesh"}}, - {Host: "198.18.2.7", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - // api-8 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-8").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.8", Ports: []string{"grpc", "mesh"}}, - {Host: "198.18.2.8", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - // api-9 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-9").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.9", Ports: []string{"grpc", "mesh"}}, - {Host: "198.18.2.9", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - // api-20 - { - TargetRef: c.ResolveResourceID(t, rtest.Resource(pbcatalog.WorkloadType, "api-20").ID()), - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "172.16.1.20", Ports: []string{"grpc", "mesh"}}, - {Host: "198.18.2.20", External: true, Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, - Identity: "api", - }, - }, - } -} - -func verifyServiceEndpoints(t *testing.T, c *rtest.Client, id *pbresource.ID, expected *pbcatalog.ServiceEndpoints) { - t.Helper() - c.WaitForResourceState(t, id, func(t rtest.T, res *pbresource.Resource) { - var actual pbcatalog.ServiceEndpoints - err := res.Data.UnmarshalTo(&actual) - require.NoError(t, err) - prototest.AssertElementsMatch(t, expected.Endpoints, actual.Endpoints) - }) -} diff --git a/internal/catalog/catalogtest/test_lifecycle_v2beta1.go b/internal/catalog/catalogtest/test_lifecycle_v2beta1.go deleted file mode 100644 index ea935dd4c56b..000000000000 --- a/internal/catalog/catalogtest/test_lifecycle_v2beta1.go +++ /dev/null @@ -1,716 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package catalogtest - -import ( - "testing" - - "github.com/hashicorp/consul/internal/catalog" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" -) - -// RunCatalogV2Beta1LifecycleIntegrationTest intends to excercise functionality of -// managing catalog resources over their normal lifecycle where they will be modified -// several times, change state etc. -func RunCatalogV2Beta1LifecycleIntegrationTest(t *testing.T, client pbresource.ResourceServiceClient) { - t.Helper() - - testutil.RunStep(t, "node-lifecycle", func(t *testing.T) { - RunCatalogV2Beta1NodeLifecycleIntegrationTest(t, client) - }) - - testutil.RunStep(t, "workload-lifecycle", func(t *testing.T) { - RunCatalogV2Beta1WorkloadLifecycleIntegrationTest(t, client) - }) - - testutil.RunStep(t, "endpoints-lifecycle", func(t *testing.T) { - RunCatalogV2Beta1EndpointsLifecycleIntegrationTest(t, client) - }) -} - -// RunCatalogV2Beta1NodeLifecycleIntegrationTest verifies correct functionality of -// the node-health controller. This test will exercise the following behaviors: -// -// * Creating a Node without associated HealthStatuses will mark the node as passing -// * Associating a HealthStatus with a Node will cause recomputation of the Health -// * Changing HealthStatus to a worse health will cause recomputation of the Health -// * Changing HealthStatus to a better health will cause recomputation of the Health -// * Deletion of associated HealthStatuses will recompute the Health (back to passing) -// * Deletion of the node will cause deletion of associated health statuses -func RunCatalogV2Beta1NodeLifecycleIntegrationTest(t *testing.T, client pbresource.ResourceServiceClient) { - c := rtest.NewClient(client) - - nodeName := "test-lifecycle" - nodeHealthName := "test-lifecycle-node-status" - - // initial node creation - node := rtest.Resource(pbcatalog.NodeType, nodeName). - WithData(t, &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{ - {Host: "172.16.2.3"}, - {Host: "198.18.2.3", External: true}, - }, - }). - Write(t, c) - - // wait for the node health controller to mark the node as healthy - c.WaitForStatusCondition(t, node.Id, - catalog.NodeHealthStatusKey, - catalog.NodeHealthConditions[pbcatalog.Health_HEALTH_PASSING]) - - // Its easy enough to simply repeatedly set the health status and it proves - // that going both from better to worse health and worse to better all - // happen as expected. We leave the health in a warning state to allow for - // the subsequent health status deletion to cause the health to go back - // to passing. - healthChanges := []pbcatalog.Health{ - pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_MAINTENANCE, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - } - - // This will be set within the loop and used afterwards to delete the health status - var nodeHealth *pbresource.Resource - - // Iterate through the various desired health statuses, updating - // a HealthStatus resource owned by the node and waiting for - // reconciliation at each point - for _, health := range healthChanges { - // update the health check - nodeHealth = setHealthStatus(t, c, node.Id, nodeHealthName, health) - - // wait for reconciliation to kick in and put the node into the right - // health status. - c.WaitForStatusCondition(t, node.Id, - catalog.NodeHealthStatusKey, - catalog.NodeHealthConditions[health]) - } - - // now delete the health status and ensure things go back to passing - c.MustDelete(t, nodeHealth.Id) - - // wait for the node health controller to mark the node as healthy - c.WaitForStatusCondition(t, node.Id, - catalog.NodeHealthStatusKey, - catalog.NodeHealthConditions[pbcatalog.Health_HEALTH_PASSING]) - - // Add the health status back once more, the actual status doesn't matter. - // It just must be owned by the node so that we can show cascading - // deletions of owned health statuses working. - healthStatus := setHealthStatus(t, c, node.Id, nodeHealthName, pbcatalog.Health_HEALTH_CRITICAL) - - // Delete the node and wait for the health status to be deleted. - c.MustDelete(t, node.Id) - c.WaitForDeletion(t, healthStatus.Id) -} - -// RunCatalogV2Beta1WorkloadLifecycleIntegrationTest verifies correct functionality of -// the workload-health controller. This test will exercise the following behaviors: -// -// - Associating a workload with a node causes recomputation of the health and takes -// into account the nodes health -// - Modifying the workloads associated node causes health recomputation and takes into -// account the new nodes health -// - Removal of the node association causes recomputation of health and for no node health -// to be taken into account. -// - Creating a workload without associated health statuses or node association will -// be marked passing -// - Creating a workload without associated health statuses but with a node will -// inherit its health from the node. -// - Changing HealthStatus to a worse health will cause recompuation of the Health -// - Changing HealthStatus to a better health will cause recompuation of the Health -// - Overall health is computed as the worst health amongst the nodes health and all -// of the workloads associated HealthStatuses -// - Deletion of the workload will cause deletion of all associated health statuses. -func RunCatalogV2Beta1WorkloadLifecycleIntegrationTest(t *testing.T, client pbresource.ResourceServiceClient) { - c := rtest.NewClient(client) - testutil.RunStep(t, "nodeless-workload", func(t *testing.T) { - runV2Beta1NodelessWorkloadLifecycleIntegrationTest(t, c) - }) - - testutil.RunStep(t, "node-associated-workload", func(t *testing.T) { - runV2Beta1NodeAssociatedWorkloadLifecycleIntegrationTest(t, c) - }) -} - -// runV2Beta1NodelessWorkloadLifecycleIntegrationTest verifies correct functionality of -// the workload-health controller for workloads without node associations. In particular -// the following behaviors are being tested -// -// - Creating a workload without associated health statuses or node association will -// be marked passing -// - Changing HealthStatus to a worse health will cause recompuation of the Health -// - Changing HealthStatus to a better health will cause recompuation of the Health -// - Deletion of associated HealthStatus for a nodeless workload will be set back to passing -// - Deletion of the workload will cause deletion of all associated health statuses. -func runV2Beta1NodelessWorkloadLifecycleIntegrationTest(t *testing.T, c *rtest.Client) { - workloadName := "test-lifecycle-workload" - workloadHealthName := "test-lifecycle-workload-status" - - // create a workload without a node association or health statuses yet - workload := rtest.Resource(pbcatalog.WorkloadType, workloadName). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "198.18.9.8"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "test-lifecycle", - }). - Write(t, c) - - // wait for the workload health controller to mark the workload as healthy - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadHealthConditions[pbcatalog.Health_HEALTH_PASSING]) - - // We may not need to iterate through all of these states but its easy - // enough and quick enough to do so. The general rationale is that we - // should move through changing the workloads associated health status - // in this progression. We can prove that moving from better to worse - // health or worse to better both function correctly. - healthChanges := []pbcatalog.Health{ - pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_MAINTENANCE, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - } - - var workloadHealth *pbresource.Resource - // Iterate through the various desired health statuses, updating - // a HealthStatus resource owned by the workload and waiting for - // reconciliation at each point - for _, health := range healthChanges { - // update the health status - workloadHealth = setHealthStatus(t, c, workload.Id, workloadHealthName, health) - - // wait for reconciliation to kick in and put the workload into - // the right health status. - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadHealthConditions[health]) - } - - // Now delete the health status, things should go back to passing status - c.MustDelete(t, workloadHealth.Id) - - // ensure the workloads health went back to passing - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadHealthConditions[pbcatalog.Health_HEALTH_PASSING]) - - // Reset the workload health. The actual health is irrelevant, we just want it - // to exist to provde that Health Statuses get deleted along with the workload - // when its deleted. - workloadHealth = setHealthStatus(t, c, workload.Id, workloadHealthName, pbcatalog.Health_HEALTH_WARNING) - - // Delete the workload and wait for the HealthStatus to also be deleted - c.MustDelete(t, workload.Id) - c.WaitForDeletion(t, workloadHealth.Id) -} - -// runV2Beta1NodeAssociatedWorkloadLifecycleIntegrationTest verifies correct functionality of -// the workload-health controller. This test will exercise the following behaviors: -// -// - Associating a workload with a node causes recomputation of the health and takes -// into account the nodes health -// - Modifying the workloads associated node causes health recomputation and takes into -// account the new nodes health -// - Removal of the node association causes recomputation of health and for no node health -// to be taken into account. -// - Creating a workload without associated health statuses but with a node will -// inherit its health from the node. -// - Overall health is computed as the worst health amongst the nodes health and all -// of the workloads associated HealthStatuses -func runV2Beta1NodeAssociatedWorkloadLifecycleIntegrationTest(t *testing.T, c *rtest.Client) { - workloadName := "test-lifecycle" - workloadHealthName := "test-lifecycle" - nodeName1 := "test-lifecycle-1" - nodeName2 := "test-lifecycle-2" - nodeHealthName1 := "test-lifecycle-node-1" - nodeHealthName2 := "test-lifecycle-node-2" - - // Insert a some nodes to link the workloads to at various points throughout the test - node1 := rtest.Resource(pbcatalog.NodeType, nodeName1). - WithData(t, &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{{Host: "172.17.9.10"}}, - }). - Write(t, c) - node2 := rtest.Resource(pbcatalog.NodeType, nodeName2). - WithData(t, &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{{Host: "172.17.9.11"}}, - }). - Write(t, c) - - // Set some non-passing health statuses for those nodes. Using non-passing will make - // it easy to see that changing a passing workloads node association appropriately - // impacts the overall workload health. - setHealthStatus(t, c, node1.Id, nodeHealthName1, pbcatalog.Health_HEALTH_CRITICAL) - setHealthStatus(t, c, node2.Id, nodeHealthName2, pbcatalog.Health_HEALTH_WARNING) - - // Add the workload but don't immediately associate with any node. - workload := rtest.Resource(pbcatalog.WorkloadType, workloadName). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "198.18.9.8"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "test-lifecycle", - }). - Write(t, c) - - // wait for the workload health controller to mark the workload as healthy - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadHealthConditions[pbcatalog.Health_HEALTH_PASSING]) - - // now modify the workload to associate it with node 1 (currently with CRITICAL health) - workload = rtest.ResourceID(workload.Id). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "198.18.9.8"}}, - Ports: map[string]*pbcatalog.WorkloadPort{"http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - Identity: "test-lifecycle", - // this is the only difference from the previous write - NodeName: node1.Id.Name, - }). - Write(t, c) - - // wait for the workload health controller to mark the workload as critical (due to node 1 having critical health) - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadAndNodeHealthConditions[pbcatalog.Health_HEALTH_PASSING][pbcatalog.Health_HEALTH_CRITICAL]) - - // Now reassociate the workload with node 2. This should cause recalculation of its health into the warning state - workload = rtest.ResourceID(workload.Id). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "198.18.9.8"}}, - Ports: map[string]*pbcatalog.WorkloadPort{"http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - Identity: "test-lifecycle", - // this is the only difference from the previous write - NodeName: node2.Id.Name, - }). - Write(t, c) - - // Wait for the workload health controller to mark the workload as warning (due to node 2 having warning health) - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadAndNodeHealthConditions[pbcatalog.Health_HEALTH_PASSING][pbcatalog.Health_HEALTH_WARNING]) - - // Delete the node, this should cause the health to be recalculated as critical because the node association - // is broken. - c.MustDelete(t, node2.Id) - - // Wait for the workload health controller to mark the workload as critical due to the missing node - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadAndNodeHealthConditions[pbcatalog.Health_HEALTH_PASSING][pbcatalog.Health_HEALTH_CRITICAL]) - - // Now fixup the node association to point at node 1 - workload = rtest.ResourceID(workload.Id). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "198.18.9.8"}}, - Ports: map[string]*pbcatalog.WorkloadPort{"http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - Identity: "test-lifecycle", - // this is the only difference from the previous write - NodeName: node1.Id.Name, - }). - Write(t, c) - - // Also set node 1 health down to WARNING - setHealthStatus(t, c, node1.Id, nodeHealthName1, pbcatalog.Health_HEALTH_WARNING) - - // Wait for the workload health controller to mark the workload as warning (due to node 1 having warning health now) - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadAndNodeHealthConditions[pbcatalog.Health_HEALTH_PASSING][pbcatalog.Health_HEALTH_WARNING]) - - // Now add a critical workload health check to ensure that both node and workload health are accounted for. - setHealthStatus(t, c, workload.Id, workloadHealthName, pbcatalog.Health_HEALTH_CRITICAL) - - // Wait for the workload health to be recomputed and put into the critical status. - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadAndNodeHealthConditions[pbcatalog.Health_HEALTH_CRITICAL][pbcatalog.Health_HEALTH_WARNING]) - - // Reset the workloads health to passing. We expect the overall health to go back to warning - setHealthStatus(t, c, workload.Id, workloadHealthName, pbcatalog.Health_HEALTH_PASSING) - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadAndNodeHealthConditions[pbcatalog.Health_HEALTH_PASSING][pbcatalog.Health_HEALTH_WARNING]) - - // Remove the node association and wait for the health to go back to passing - workload = rtest.ResourceID(workload.Id). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "198.18.9.8"}}, - Ports: map[string]*pbcatalog.WorkloadPort{"http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - Identity: "test-lifecycle", - }). - Write(t, c) - c.WaitForStatusCondition(t, workload.Id, - catalog.WorkloadHealthStatusKey, - catalog.WorkloadHealthConditions[pbcatalog.Health_HEALTH_PASSING]) -} - -// RunCatalogV2Beta1EndpointsLifecycleIntegrationTest verifies the correct functionality of -// the endpoints controller. This test will exercise the following behaviors: -// -// * Services without a selector get marked with status indicating their endpoints are unmanaged -// * Services with a selector get marked with status indicating their endpoints are managed -// * Deleting a service will delete the associated endpoints (regardless of them being managed or not) -// * Moving from managed to unmanaged endpoints will delete the managed endpoints -// * Moving from unmanaged to managed endpoints will overwrite any previous endpoints. -// * A service with a selector that matches no workloads will still have the endpoints object written. -// * Adding ports to a service will recalculate the endpoints -// * Removing ports from a service will recalculate the endpoints -// * Changing the workload will recalculate the endpoints (ports, addresses, or health) -func RunCatalogV2Beta1EndpointsLifecycleIntegrationTest(t *testing.T, client pbresource.ResourceServiceClient) { - c := rtest.NewClient(client) - serviceName := "test-lifecycle" - - // Create the service without a selector. We should not see endpoints generated but we should see the - // status updated to note endpoints are not being managed. - service := rtest.Resource(pbcatalog.ServiceType, serviceName). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{{TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - }). - Write(t, c) - - // Wait to ensure the status is updated accordingly - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionUnmanaged) - - // Verify that no endpoints were created. - endpointsID := rtest.Resource(pbcatalog.ServiceEndpointsType, serviceName).ID() - c.RequireResourceNotFound(t, endpointsID) - - // Add some empty endpoints (type validations enforce that they are owned by the service) - rtest.ResourceID(endpointsID). - WithData(t, &pbcatalog.ServiceEndpoints{}). - WithOwner(service.Id). - Write(t, c) - - // Now delete the service and ensure that they are cleaned up. - c.MustDelete(t, service.Id) - c.WaitForDeletion(t, endpointsID) - - // Add some workloads to eventually select by the service - - // api-1 has all ports (http, grpc and mesh). It also has a mixture of Addresses - // that select individual ports and one that selects all ports implicitly - api1 := rtest.Resource(pbcatalog.WorkloadType, "api-1"). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - {Host: "::1", Ports: []string{"grpc"}}, - {Host: "127.0.0.2", Ports: []string{"http"}}, - {Host: "172.17.1.1", Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - Identity: "api", - }). - Write(t, c) - - // api-2 has only grpc and mesh ports. It also has a mixture of Addresses that - // select individual ports and one that selects all ports implicitly - api2 := rtest.Resource(pbcatalog.WorkloadType, "api-2"). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - {Host: "::1", Ports: []string{"grpc"}}, - {Host: "172.17.1.2", Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - Identity: "api", - }). - Write(t, c) - - // api-3 has the mesh and HTTP ports. It also has a mixture of Addresses that - // select individual ports and one that selects all ports. - api3 := rtest.Resource(pbcatalog.WorkloadType, "api-3"). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - {Host: "172.17.1.3", Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "api", - }). - Write(t, c) - - // Now create a service with unmanaged endpoints again - service = rtest.Resource(pbcatalog.ServiceType, serviceName). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{{TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - }). - Write(t, c) - - // Inject the endpoints resource. We want to prove that transition from unmanaged to - // managed endpoints results in overwriting of the old endpoints - rtest.ResourceID(endpointsID). - WithData(t, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "198.18.1.1", External: true}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 443, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }, - }, - }). - WithOwner(service.Id). - Write(t, c) - - // Wait to ensure the status is updated accordingly - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionUnmanaged) - - // Now move the service to having managed endpoints - service = rtest.ResourceID(service.Id). - WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"bar"}}, - Ports: []*pbcatalog.ServicePort{{TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - }). - Write(t, c) - - // Verify that this status is updated to show this service as having managed endpoints - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionManaged) - - // Verify that the service endpoints are created. In this case they will be empty - verifyServiceEndpoints(t, c, endpointsID, &pbcatalog.ServiceEndpoints{}) - - // Rewrite the service to select the API workloads - just select the singular port for now - service = rtest.ResourceID(service.Id). - WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{{TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}}, - }). - Write(t, c) - - // Wait for the status to be updated. The condition itself will remain unchanged but we are waiting for - // the generations to match to know that the endpoints would have been regenerated - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionManaged) - - // ensure that api-1 and api-3 are selected but api-2 is excluded due to not having the desired port - verifyServiceEndpoints(t, c, endpointsID, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: api1.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"http"}}, - {Host: "127.0.0.2", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }, - { - TargetRef: api3.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }, - }, - }) - - // Rewrite the service to select the API workloads - changing from selecting the HTTP port to the gRPC port - service = rtest.ResourceID(service.Id). - WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{{TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}}, - }). - Write(t, c) - - // Wait for the status to be updated. The condition itself will remain unchanged but we are waiting for - // the generations to match to know that the endpoints would have been regenerated - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionManaged) - - // Check that the endpoints were generated as expected - verifyServiceEndpoints(t, c, endpointsID, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: api1.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"grpc"}}, - {Host: "::1", Ports: []string{"grpc"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }, - { - TargetRef: api2.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"grpc"}}, - {Host: "::1", Ports: []string{"grpc"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }, - }, - }) - - // Update the service to change the ports used. This should result in the workload being removed - // from the endpoints - rtest.ResourceID(api2.Id). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - {Host: "::1", Ports: []string{"http"}}, - {Host: "172.17.1.2", Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "api", - }). - Write(t, c) - - // Verify that api-2 was removed from the service endpoints as it no longer has a grpc port - verifyServiceEndpoints(t, c, endpointsID, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: api1.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"grpc"}}, - {Host: "::1", Ports: []string{"grpc"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }, - }, - }) - - // Remove the ::1 address from workload api1 which should result in recomputing endpoints - rtest.ResourceID(api1.Id). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - {Host: "172.17.1.1", Ports: []string{"mesh"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - Identity: "api", - }). - Write(t, c) - - // Verify that api-1 had its addresses modified appropriately - verifyServiceEndpoints(t, c, endpointsID, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: api1.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"grpc"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }, - }, - }) - - // Add a failing health status to the api1 workload to force recomputation of endpoints - setHealthStatus(t, c, api1.Id, "api-failed", pbcatalog.Health_HEALTH_CRITICAL) - - // Verify that api-1 within the endpoints has the expected health - verifyServiceEndpoints(t, c, endpointsID, &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: api1.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"grpc"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }, - }, - }) - - // Move the service to being unmanaged. We should see the ServiceEndpoints being removed. - service = rtest.ResourceID(service.Id). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{{TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}}, - }). - Write(t, c) - - // Wait for the endpoints controller to inform us that the endpoints are not being managed - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionUnmanaged) - // Ensure that the managed endpoints were deleted - c.WaitForDeletion(t, endpointsID) - - // Put the service back into managed mode. - service = rtest.ResourceID(service.Id). - WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{{TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}}, - }). - Write(t, c) - - // Wait for the service endpoints to be regenerated - c.WaitForStatusCondition(t, service.Id, catalog.EndpointsStatusKey, catalog.EndpointsStatusConditionManaged) - c.RequireResourceExists(t, endpointsID) - - // Now delete the service and ensure that the endpoints eventually are deleted as well - c.MustDelete(t, service.Id) - c.WaitForDeletion(t, endpointsID) -} - -func setHealthStatus(t *testing.T, client *rtest.Client, owner *pbresource.ID, name string, health pbcatalog.Health) *pbresource.Resource { - return rtest.Resource(pbcatalog.HealthStatusType, name). - WithData(t, &pbcatalog.HealthStatus{ - Type: "synthetic", - Status: health, - }). - WithOwner(owner). - Write(t, client) -} diff --git a/internal/catalog/exports.go b/internal/catalog/exports.go deleted file mode 100644 index 3c43643de419..000000000000 --- a/internal/catalog/exports.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package catalog - -import ( - "github.com/hashicorp/consul/internal/catalog/internal/controllers" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/endpoints" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/failover" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/nodehealth" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/workloadhealth" - "github.com/hashicorp/consul/internal/catalog/internal/mappers/failovermapper" - "github.com/hashicorp/consul/internal/catalog/internal/mappers/nodemapper" - "github.com/hashicorp/consul/internal/catalog/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/selectiontracker" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -var ( - // Controller Statuses - NodeHealthStatusKey = nodehealth.StatusKey - NodeHealthStatusConditionHealthy = nodehealth.StatusConditionHealthy - NodeHealthConditions = nodehealth.Conditions - - WorkloadHealthStatusKey = workloadhealth.StatusKey - WorkloadHealthStatusConditionHealthy = workloadhealth.StatusConditionHealthy - WorkloadHealthConditions = workloadhealth.WorkloadConditions - WorkloadAndNodeHealthConditions = workloadhealth.NodeAndWorkloadConditions - - EndpointsStatusKey = endpoints.StatusKey - EndpointsStatusConditionEndpointsManaged = endpoints.StatusConditionEndpointsManaged - EndpointsStatusConditionManaged = endpoints.ConditionManaged - EndpointsStatusConditionUnmanaged = endpoints.ConditionUnmanaged - StatusConditionBoundIdentities = endpoints.StatusConditionBoundIdentities - StatusReasonWorkloadIdentitiesFound = endpoints.StatusReasonWorkloadIdentitiesFound - StatusReasonNoWorkloadIdentitiesFound = endpoints.StatusReasonNoWorkloadIdentitiesFound - - FailoverStatusKey = failover.StatusKey - FailoverStatusConditionAccepted = failover.StatusConditionAccepted - FailoverStatusConditionAcceptedOKReason = failover.OKReason - FailoverStatusConditionAcceptedMissingServiceReason = failover.MissingServiceReason - FailoverStatusConditionAcceptedUnknownPortReason = failover.UnknownPortReason - FailoverStatusConditionAcceptedMissingDestinationServiceReason = failover.MissingDestinationServiceReason - FailoverStatusConditionAcceptedUnknownDestinationPortReason = failover.UnknownDestinationPortReason - FailoverStatusConditionAcceptedUsingMeshDestinationPortReason = failover.UsingMeshDestinationPortReason -) - -type WorkloadSelecting = types.WorkloadSelecting - -func ACLHooksForWorkloadSelectingType[T WorkloadSelecting]() *resource.ACLHooks { - return types.ACLHooksForWorkloadSelectingType[T]() -} - -// RegisterTypes adds all resource types within the "catalog" API group -// to the given type registry -func RegisterTypes(r resource.Registry) { - types.Register(r) -} - -type ControllerDependencies = controllers.Dependencies - -func DefaultControllerDependencies() ControllerDependencies { - return ControllerDependencies{ - WorkloadHealthNodeMapper: nodemapper.New(), - EndpointsWorkloadMapper: selectiontracker.New(), - FailoverMapper: failovermapper.New(), - } -} - -// RegisterControllers registers controllers for the catalog types with -// the given controller Manager. -func RegisterControllers(mgr *controller.Manager, deps ControllerDependencies) { - controllers.Register(mgr, deps) -} - -// SimplifyFailoverPolicy fully populates the PortConfigs map and clears the -// Configs map using the provided Service. -func SimplifyFailoverPolicy(svc *pbcatalog.Service, failover *pbcatalog.FailoverPolicy) *pbcatalog.FailoverPolicy { - return types.SimplifyFailoverPolicy(svc, failover) -} - -// FailoverPolicyMapper maintains the bidirectional tracking relationship of a -// FailoverPolicy to the Services related to it. -type FailoverPolicyMapper interface { - TrackFailover(failover *resource.DecodedResource[*pbcatalog.FailoverPolicy]) - UntrackFailover(failoverID *pbresource.ID) - FailoverIDsByService(svcID *pbresource.ID) []*pbresource.ID -} - -func NewFailoverPolicyMapper() FailoverPolicyMapper { - return failovermapper.New() -} - -// ValidateLocalServiceRefNoSection ensures the following: -// -// - ref is non-nil -// - type is ServiceType -// - section is empty -// - tenancy is set and partition/namespace are both non-empty -// - peer_name must be "local" -// -// Each possible validation error is wrapped in the wrapErr function before -// being collected in a multierror.Error. -func ValidateLocalServiceRefNoSection(ref *pbresource.Reference, wrapErr func(error) error) error { - return types.ValidateLocalServiceRefNoSection(ref, wrapErr) -} - -// ValidateSelector ensures that the selector has at least one exact or prefix -// match constraint, and that if a filter is present it is valid. -// -// The selector can be nil, and have zero exact/prefix matches if allowEmpty is -// set to true. -func ValidateSelector(sel *pbcatalog.WorkloadSelector, allowEmpty bool) error { - return types.ValidateSelector(sel, allowEmpty) -} - -func ValidatePortName(name string) error { - return types.ValidatePortName(name) -} - -func IsValidUnixSocketPath(host string) bool { - return types.IsValidUnixSocketPath(host) -} - -func ValidateProtocol(protocol pbcatalog.Protocol) error { - return types.ValidateProtocol(protocol) -} diff --git a/internal/catalog/internal/controllers/endpoints/controller.go b/internal/catalog/internal/controllers/endpoints/controller.go deleted file mode 100644 index ef0c20f97961..000000000000 --- a/internal/catalog/internal/controllers/endpoints/controller.go +++ /dev/null @@ -1,404 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package endpoints - -import ( - "context" - "sort" - - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/catalog/internal/controllers/workloadhealth" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - endpointsMetaManagedBy = "managed-by-controller" -) - -// The WorkloadMapper interface is used to provide an implementation around being able -// to map a watch even for a Workload resource and translate it to reconciliation requests -type WorkloadMapper interface { - // MapWorkload conforms to the controller.DependencyMapper signature. Given a Workload - // resource it should report the resource IDs that have selected the workload. - MapWorkload(context.Context, controller.Runtime, *pbresource.Resource) ([]controller.Request, error) - - // TrackIDForSelector should be used to associate the specified WorkloadSelector with - // the given resource ID. Future calls to MapWorkload - TrackIDForSelector(*pbresource.ID, *pbcatalog.WorkloadSelector) - - // UntrackID should be used to inform the tracker to forget about the specified ID - UntrackID(*pbresource.ID) -} - -// ServiceEndpointsController creates a controller to perform automatic endpoint management for -// services. -func ServiceEndpointsController(workloadMap WorkloadMapper) controller.Controller { - if workloadMap == nil { - panic("No WorkloadMapper was provided to the ServiceEndpointsController constructor") - } - - return controller.ForType(pbcatalog.ServiceEndpointsType). - WithWatch(pbcatalog.ServiceType, controller.ReplaceType(pbcatalog.ServiceEndpointsType)). - WithWatch(pbcatalog.WorkloadType, workloadMap.MapWorkload). - WithReconciler(newServiceEndpointsReconciler(workloadMap)) -} - -type serviceEndpointsReconciler struct { - workloadMap WorkloadMapper -} - -func newServiceEndpointsReconciler(workloadMap WorkloadMapper) *serviceEndpointsReconciler { - return &serviceEndpointsReconciler{ - workloadMap: workloadMap, - } -} - -// Reconcile will reconcile one ServiceEndpoints resource in response to some event. -func (r *serviceEndpointsReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - // The runtime is passed by value so replacing it here for the remainder of this - // reconciliation request processing will not affect future invocations. - rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", StatusKey) - - rt.Logger.Trace("reconciling service endpoints") - - endpointsID := req.ID - serviceID := &pbresource.ID{ - Type: pbcatalog.ServiceType, - Tenancy: endpointsID.Tenancy, - Name: endpointsID.Name, - } - - // First we read and unmarshal the service - - serviceData, err := getServiceData(ctx, rt, serviceID) - if err != nil { - rt.Logger.Error("error retrieving corresponding Service", "error", err) - return err - } - - // Check if the service exists. If it doesn't we can avoid a bunch of other work. - if serviceData == nil { - rt.Logger.Trace("service has been deleted") - - // The service was deleted so we need to update the WorkloadMapper to tell it to - // stop tracking this service - r.workloadMap.UntrackID(req.ID) - - // Note that because we configured ServiceEndpoints to be owned by the service, - // the service endpoints object should eventually be automatically deleted. - // There is no reason to attempt deletion here. - return nil - } - - // Now read and unmarshal the endpoints. We don't need this data just yet but all - // code paths from this point on will need this regardless of branching so we pull - // it now. - endpointsData, err := getEndpointsData(ctx, rt, endpointsID) - if err != nil { - rt.Logger.Error("error retrieving existing endpoints", "error", err) - return err - } - - var statusConditions []*pbresource.Condition - - if serviceUnderManagement(serviceData.service) { - rt.Logger.Trace("service is enabled for automatic endpoint management") - // This service should have its endpoints automatically managed - statusConditions = append(statusConditions, ConditionManaged) - - // Inform the WorkloadMapper to track this service and its selectors. So - // future workload updates that would be matched by the services selectors - // cause this service to be rereconciled. - r.workloadMap.TrackIDForSelector(req.ID, serviceData.service.GetWorkloads()) - - // Now read and unmarshal all workloads selected by the service. It is imperative - // that this happens after we notify the selection tracker to be tracking that - // selection criteria. If the order were reversed we could potentially miss - // workload creations that should be selected if they happen after gathering - // the workloads but before tracking the selector. Tracking first ensures that - // any event that happens after that would get mapped to an event for these - // endpoints. - workloadData, err := getWorkloadData(ctx, rt, serviceData) - if err != nil { - rt.Logger.Trace("error retrieving selected workloads", "error", err) - return err - } - - // Calculate the latest endpoints from the already gathered workloads - latestEndpoints := workloadsToEndpoints(serviceData.service, workloadData) - - // Add status - if endpointsData != nil { - statusConditions = append(statusConditions, - workloadIdentityStatusFromEndpoints(latestEndpoints)) - } - - // Before writing the endpoints actually check to see if they are changed - if endpointsData == nil || !proto.Equal(endpointsData.endpoints, latestEndpoints) { - rt.Logger.Trace("endpoints have changed") - - // First encode the endpoints data as an Any type. - endpointData, err := anypb.New(latestEndpoints) - if err != nil { - rt.Logger.Error("error marshalling latest endpoints", "error", err) - return err - } - - // Now perform the write. The endpoints resource should be owned by the service - // so that it will automatically be deleted upon service deletion. We are using - // a special metadata entry to track that this controller is responsible for - // the management of this resource. - _, err = rt.Client.Write(ctx, &pbresource.WriteRequest{ - Resource: &pbresource.Resource{ - Id: req.ID, - Owner: serviceData.resource.Id, - Metadata: map[string]string{ - endpointsMetaManagedBy: StatusKey, - }, - Data: endpointData, - }, - }) - if err != nil { - rt.Logger.Error("error writing generated endpoints", "error", err) - return err - } else { - rt.Logger.Trace("updated endpoints were successfully written") - } - } - } else { - rt.Logger.Trace("endpoints are not being automatically managed") - // This service is not having its endpoints automatically managed - statusConditions = append(statusConditions, ConditionUnmanaged) - - // Inform the WorkloadMapper that it no longer needs to track this service - // as it is no longer under endpoint management - r.workloadMap.UntrackID(req.ID) - - // Delete the managed ServiceEndpoints if necessary if the metadata would - // indicate that they were previously managed by this controller - if endpointsData != nil && endpointsData.resource.Metadata[endpointsMetaManagedBy] == StatusKey { - rt.Logger.Trace("removing previous managed endpoints") - - // This performs a CAS deletion to protect against the case where the user - // has overwritten the endpoints since we fetched them. - _, err := rt.Client.Delete(ctx, &pbresource.DeleteRequest{ - Id: endpointsData.resource.Id, - Version: endpointsData.resource.Version, - }) - - // Potentially we could look for CAS failures by checking if the gRPC - // status code is Aborted. However its an edge case and there could - // possibly be other reasons why the gRPC status code would be aborted - // besides CAS version mismatches. The simplest thing to do is to just - // propagate the error and retry reconciliation later. - if err != nil { - rt.Logger.Error("error deleting previously managed endpoints", "error", err) - return err - } - } - } - - // Update the Service status if necessary. Mainly we want to inform the user - // whether we are automatically managing the endpoints to set expectations - // for that object existing or not. - newStatus := &pbresource.Status{ - ObservedGeneration: serviceData.resource.Generation, - Conditions: statusConditions, - } - // If the status is unchanged then we should return and avoid the unnecessary write - if resource.EqualStatus(serviceData.resource.Status[StatusKey], newStatus, false) { - return nil - } - - _, err = rt.Client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ - Id: serviceData.resource.Id, - Key: StatusKey, - Status: newStatus, - }) - - if err != nil { - rt.Logger.Error("error updating the service's status", "error", err, "service", serviceID) - } - return err -} - -// determineWorkloadHealth will find the workload-health controller's status -// within the resource status and parse the workloads health out of it. If -// the workload-health controller has yet to reconcile the workload health -// or the status isn't in the expected form then this function will return -// HEALTH_CRITICAL. -func determineWorkloadHealth(workload *pbresource.Resource) pbcatalog.Health { - status, found := workload.Status[workloadhealth.StatusKey] - if !found { - return pbcatalog.Health_HEALTH_CRITICAL - } - - for _, condition := range status.Conditions { - if condition.Type == workloadhealth.StatusConditionHealthy { - raw, found := pbcatalog.Health_value[condition.Reason] - if found { - return pbcatalog.Health(raw) - } - return pbcatalog.Health_HEALTH_CRITICAL - } - } - return pbcatalog.Health_HEALTH_CRITICAL -} - -// serviceUnderManagement detects whether this service should have its -// endpoints automatically managed by the controller -func serviceUnderManagement(svc *pbcatalog.Service) bool { - sel := svc.GetWorkloads() - if sel == nil { - // The selector wasn't present at all. Therefore this service is not under - // automatic endpoint management. - return false - } - - if len(sel.Names) < 1 && len(sel.Prefixes) < 1 { - // The selector was set in the request but the list of workload names - // and prefixes were both empty. Therefore this service is not under - // automatic endpoint management - return false - } - - // Some workload selection criteria exists, so this service is considered - // under automatic endpoint management. - return true -} - -// workloadsToEndpoints will translate the Workload resources into a ServiceEndpoints resource -func workloadsToEndpoints(svc *pbcatalog.Service, workloads []*workloadData) *pbcatalog.ServiceEndpoints { - var endpoints []*pbcatalog.Endpoint - - for _, workload := range workloads { - endpoint := workloadToEndpoint(svc, workload) - if endpoint != nil { - endpoints = append(endpoints, endpoint) - } - } - - return &pbcatalog.ServiceEndpoints{ - Endpoints: endpoints, - } -} - -// workloadToEndpoint will convert a workload resource into a singular Endpoint to be -// put within a ServiceEndpoints resource. -// -// The conversion process involves parsing the workloads health and filtering its -// addresses and ports down to just what the service wants to consume. -// -// Determining the workloads health requires the workload-health controller to already -// have reconciled the workloads health and stored it within the resources Status field. -// Any unreconciled workload health will be represented in the ServiceEndpoints with -// the ANY health status. -func workloadToEndpoint(svc *pbcatalog.Service, data *workloadData) *pbcatalog.Endpoint { - health := determineWorkloadHealth(data.resource) - - endpointPorts := make(map[string]*pbcatalog.WorkloadPort) - - // Create the endpoints filtered ports map. Only workload ports specified in - // one of the services ports are included. Ports with a protocol mismatch - // between the service and workload will be excluded as well. - for _, svcPort := range svc.Ports { - workloadPort, found := data.workload.Ports[svcPort.TargetPort] - if !found { - // this workload doesn't have this port so ignore it - continue - } - - // If workload protocol is not specified, we will default to service's protocol. - // This is because on some platforms (kubernetes), workload protocol is not always - // known, and so we need to inherit from the service instead. - if workloadPort.Protocol == pbcatalog.Protocol_PROTOCOL_UNSPECIFIED { - workloadPort.Protocol = svcPort.Protocol - } else if workloadPort.Protocol != svcPort.Protocol { - // Otherwise, there's workload port mismatch - ignore it. - continue - } - - endpointPorts[svcPort.TargetPort] = workloadPort - } - - var workloadAddrs []*pbcatalog.WorkloadAddress - - // Now we filter down the addresses and their corresponding port usage to just - // what the service needs to consume. If the address isn't being used to serve - // any of the services target ports, it will be entirely excluded from the - // address list. If some but not all of its ports are served, then the list - // of ports will be reduced to just the intersection of the service ports - // and the workload addresses ports - for _, addr := range data.workload.Addresses { - var ports []string - - if len(addr.Ports) > 0 { - // The workload address has defined ports, filter these as necessary - - for _, portName := range addr.Ports { - // check if the workload port has been selected by the service - _, found := endpointPorts[portName] - if !found { - // this port isn't selected by the service so drop this port - continue - } - - ports = append(ports, portName) - } - } else { - // The workload address doesn't specify ports. This lack of port specification - // means that all ports are exposed on the interface so here we create a list - // of all the port names exposed by the service. - for portName := range endpointPorts { - ports = append(ports, portName) - } - } - - // sort the ports to keep them stable and prevent unnecessary rewrites when the endpoints - // get diffed - sort.Slice(ports, func(i, j int) bool { - return ports[i] < ports[j] - }) - - // Only record this workload address if one or more of its ports were consumed - // by the service. - if len(ports) > 0 { - workloadAddrs = append(workloadAddrs, &pbcatalog.WorkloadAddress{ - Host: addr.Host, - External: addr.External, - Ports: ports, - }) - } - } - - // If all the workload addresses were filtered out then we should completely ignore - // the workload. While the name matched nothing else did so it isn't useable as - // far as the service is concerned. - if len(workloadAddrs) < 1 { - return nil - } - - return &pbcatalog.Endpoint{ - TargetRef: data.resource.Id, - HealthStatus: health, - Addresses: workloadAddrs, - Ports: endpointPorts, - Identity: data.workload.Identity, - } -} - -func workloadIdentityStatusFromEndpoints(endpoints *pbcatalog.ServiceEndpoints) *pbresource.Condition { - identities := endpoints.GetIdentities() - - if len(identities) > 0 { - return ConditionIdentitiesFound(identities) - } - - return ConditionIdentitiesNotFound -} diff --git a/internal/catalog/internal/controllers/endpoints/controller_test.go b/internal/catalog/internal/controllers/endpoints/controller_test.go deleted file mode 100644 index 5a0155ef7683..000000000000 --- a/internal/catalog/internal/controllers/endpoints/controller_test.go +++ /dev/null @@ -1,856 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package endpoints - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/workloadhealth" - "github.com/hashicorp/consul/internal/catalog/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource/mappers/selectiontracker" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" -) - -var ( - badId = rtest.Resource(&pbresource.Type{Group: "not", Kind: "found", GroupVersion: "vfake"}, "foo").ID() -) - -func TestWorkloadsToEndpoints(t *testing.T) { - // This test's purpose is to ensure that converting multiple workloads to endpoints - // happens as expected. It is not concerned with the data in each endpoint but rather - // the removal of unconvertable workloads (nil endpoints returned by workloadToEndpoint). - - // The workload to endpoint conversion only cares about the service ports - service := &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http2", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - }, - } - - workloadAddresses := []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - } - - // This workload is port-matched with the service and should show up as an - // endpoint in the final set. - workloadData1 := &pbcatalog.Workload{ - Addresses: workloadAddresses, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http2": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - }, - } - - // This workload is NOT port-matched with the service and should be omitted. - workloadData2 := &pbcatalog.Workload{ - Addresses: workloadAddresses, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - // Build out the workloads. - workloads := []*workloadData{ - { - // this workload should result in an endpoints - resource: rtest.Resource(pbcatalog.WorkloadType, "foo"). - WithData(t, workloadData1). - Build(), - workload: workloadData1, - }, - { - // this workload should be filtered out - resource: rtest.Resource(pbcatalog.WorkloadType, "bar"). - WithData(t, workloadData2). - Build(), - workload: workloadData2, - }, - } - - endpoints := workloadsToEndpoints(service, workloads) - require.Len(t, endpoints.Endpoints, 1) - prototest.AssertDeepEqual(t, workloads[0].resource.Id, endpoints.Endpoints[0].TargetRef) -} - -func TestWorkloadToEndpoint(t *testing.T) { - // This test handles ensuring that the bulk of the functionality of - // the workloadToEndpoint function works correctly. - // - // * WorkloadPorts that are not selected by one service port are ignored - // and not present in the resulting Endpoint - // * WorkloadPorts that have a protocol mismatch with the service port - // are ignored and not present in the resulting Endpoint - // * WorkloadAddresses with 0 non-ignored ports are omitted from the - // resulting Endpoint. - // * Specifying no ports for a WorkloadAddress will use all the non-ignored - // ports. These are explicitly set but that is intended to be an - // implementation detail at this point. - - service := &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - // the workload will not have this port so it should be ignored - {TargetPort: "not-found", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - // the workload will have a different protocol for this port and so it - // will be ignored. - {TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - } - - workload := &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - // this address will be in the endpoint with all the ports that are - // not filtered out - so just http - {Host: "127.0.0.1"}, - // this address will be in the endpoint but with a filtered ports list - {Host: "198.18.1.1", Ports: []string{"http", "grpc"}}, - // this address should not show up in the endpoint because the port it - // uses is filtered out - {Host: "198.8.0.1", Ports: []string{"grpc"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - // the protocol is wrong here so it will not show up in the endpoints. - "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - }, - Identity: "test-identity", - } - - data := &workloadData{ - resource: rtest.Resource(pbcatalog.WorkloadType, "foo"). - WithData(t, workload). - Build(), - workload: workload, - } - - expected := &pbcatalog.Endpoint{ - TargetRef: data.resource.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"http"}}, - {Host: "198.18.1.1", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": workload.Ports["http"], - }, - // The health is critical because we are not setting the workload's - // health status. The tests for determineWorkloadHealth will ensure - // that we can properly determine the health status and the overall - // controller tests will prove that the integration works as expected. - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: workload.Identity, - } - - prototest.AssertDeepEqual(t, expected, workloadToEndpoint(service, data)) -} - -func TestWorkloadToEndpoint_AllAddressesFiltered(t *testing.T) { - // This test checks the specific case where the workload has no - // address/port combinations that remain unfiltered. In this - // case we want to ensure nil is returned instead of an Endpoint - // with no addresses. - - service := &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "not-found", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - workload := &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - data := &workloadData{ - resource: rtest.Resource(pbcatalog.WorkloadType, "foo"). - WithData(t, workload). - Build(), - workload: workload, - } - - require.Nil(t, workloadToEndpoint(service, data)) -} - -func TestWorkloadToEndpoint_MissingWorkloadProtocol(t *testing.T) { - // This test checks that when a workload is missing its protocol, - // we will default to service's protocol. - - service := &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "test-port", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - workload := &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "test-port": {Port: 8080}, - }, - } - - data := &workloadData{ - resource: rtest.Resource(pbcatalog.WorkloadType, "foo"). - WithData(t, workload). - Build(), - workload: workload, - } - - expected := &pbcatalog.Endpoint{ - TargetRef: data.resource.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"test-port"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "test-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - // The health is critical because we are not setting the workload's - // health status. The tests for determineWorkloadHealth will ensure - // that we can properly determine the health status and the overall - // controller tests will prove that the integration works as expected. - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: workload.Identity, - } - - prototest.AssertDeepEqual(t, expected, workloadToEndpoint(service, data)) -} - -func TestServiceUnderManagement(t *testing.T) { - // This test ensures that we can properly detect when a service - // should have endpoints generated for it vs when those endpoints - // are not being automatically managed. - - type testCase struct { - svc *pbcatalog.Service - managed bool - } - - cases := map[string]testCase{ - "nil": { - svc: nil, - managed: false, - }, - "nil-selector": { - svc: &pbcatalog.Service{Workloads: nil}, - managed: false, - }, - "empty-selector": { - svc: &pbcatalog.Service{Workloads: &pbcatalog.WorkloadSelector{}}, - managed: false, - }, - "exact-match": { - svc: &pbcatalog.Service{Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"foo"}, - }}, - managed: true, - }, - "prefix-match": { - svc: &pbcatalog.Service{Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo"}, - }}, - managed: true, - }, - "multiple": { - svc: &pbcatalog.Service{Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"foo"}, - Prefixes: []string{"api-"}, - }}, - managed: true, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - require.Equal(t, tcase.managed, serviceUnderManagement(tcase.svc)) - }) - } -} - -func TestDetermineWorkloadHealth(t *testing.T) { - // This test ensures that parsing workload health out of the - // resource status works as expected. - - type testCase struct { - res *pbresource.Resource - expected pbcatalog.Health - } - - cases := map[string]testCase{ - "no-status": { - res: rtest.Resource(pbcatalog.WorkloadType, "foo").Build(), - expected: pbcatalog.Health_HEALTH_CRITICAL, - }, - "condition-not-found": { - res: rtest.Resource(pbcatalog.WorkloadType, "foo"). - WithStatus(workloadhealth.StatusKey, &pbresource.Status{ - Conditions: []*pbresource.Condition{ - { - Type: "other", - State: pbresource.Condition_STATE_TRUE, - Reason: "NOT_RELEVANT", - }, - }, - }). - Build(), - expected: pbcatalog.Health_HEALTH_CRITICAL, - }, - "invalid-reason": { - res: rtest.Resource(pbcatalog.WorkloadType, "foo"). - WithStatus(workloadhealth.StatusKey, &pbresource.Status{ - Conditions: []*pbresource.Condition{ - { - Type: workloadhealth.StatusConditionHealthy, - State: pbresource.Condition_STATE_TRUE, - Reason: "INVALID_HEALTH_STATUS_REASON", - }, - }, - }). - Build(), - expected: pbcatalog.Health_HEALTH_CRITICAL, - }, - "passing": { - res: rtest.Resource(pbcatalog.WorkloadType, "foo"). - WithStatus(workloadhealth.StatusKey, &pbresource.Status{ - Conditions: []*pbresource.Condition{ - { - Type: workloadhealth.StatusConditionHealthy, - State: pbresource.Condition_STATE_TRUE, - Reason: pbcatalog.Health_HEALTH_PASSING.String(), - }, - }, - }). - Build(), - expected: pbcatalog.Health_HEALTH_PASSING, - }, - "warning": { - res: rtest.Resource(pbcatalog.WorkloadType, "foo"). - WithStatus(workloadhealth.StatusKey, &pbresource.Status{ - Conditions: []*pbresource.Condition{ - { - Type: workloadhealth.StatusConditionHealthy, - State: pbresource.Condition_STATE_TRUE, - Reason: pbcatalog.Health_HEALTH_WARNING.String(), - }, - }, - }). - Build(), - expected: pbcatalog.Health_HEALTH_WARNING, - }, - "critical": { - res: rtest.Resource(pbcatalog.WorkloadType, "foo"). - WithStatus(workloadhealth.StatusKey, &pbresource.Status{ - Conditions: []*pbresource.Condition{ - { - Type: workloadhealth.StatusConditionHealthy, - State: pbresource.Condition_STATE_TRUE, - Reason: pbcatalog.Health_HEALTH_CRITICAL.String(), - }, - }, - }). - Build(), - expected: pbcatalog.Health_HEALTH_CRITICAL, - }, - "maintenance": { - res: rtest.Resource(pbcatalog.WorkloadType, "foo"). - WithStatus(workloadhealth.StatusKey, &pbresource.Status{ - Conditions: []*pbresource.Condition{ - { - Type: workloadhealth.StatusConditionHealthy, - State: pbresource.Condition_STATE_TRUE, - Reason: pbcatalog.Health_HEALTH_MAINTENANCE.String(), - }, - }, - }). - Build(), - expected: pbcatalog.Health_HEALTH_MAINTENANCE, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - require.Equal(t, tcase.expected, determineWorkloadHealth(tcase.res)) - }) - } -} - -func TestWorkloadIdentityStatusFromEndpoints(t *testing.T) { - cases := map[string]struct { - endpoints *pbcatalog.ServiceEndpoints - expStatus *pbresource.Condition - }{ - "endpoints are nil": { - expStatus: ConditionIdentitiesNotFound, - }, - "endpoints without identities": { - endpoints: &pbcatalog.ServiceEndpoints{}, - expStatus: ConditionIdentitiesNotFound, - }, - "endpoints with identities": { - endpoints: &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Identity: "foo", - }, - }, - }, - expStatus: ConditionIdentitiesFound([]string{"foo"}), - }, - "endpoints with multiple identities": { - endpoints: &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Identity: "foo", - }, - { - Identity: "bar", - }, - }, - }, - expStatus: ConditionIdentitiesFound([]string{"bar", "foo"}), - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - prototest.AssertDeepEqual(t, c.expStatus, workloadIdentityStatusFromEndpoints(c.endpoints)) - }) - } -} - -type controllerSuite struct { - suite.Suite - - ctx context.Context - client *rtest.Client - rt controller.Runtime - - tracker *selectiontracker.WorkloadSelectionTracker - reconciler *serviceEndpointsReconciler -} - -func (suite *controllerSuite) SetupTest() { - suite.ctx = testutil.TestContext(suite.T()) - client := svctest.RunResourceService(suite.T(), types.Register) - suite.rt = controller.Runtime{ - Client: client, - Logger: testutil.Logger(suite.T()), - } - suite.client = rtest.NewClient(client) - suite.tracker = selectiontracker.New() - suite.reconciler = newServiceEndpointsReconciler(suite.tracker) -} - -func (suite *controllerSuite) requireTracking(workload *pbresource.Resource, ids ...*pbresource.ID) { - reqs, err := suite.tracker.MapWorkload(suite.ctx, suite.rt, workload) - require.NoError(suite.T(), err) - require.Len(suite.T(), reqs, len(ids)) - for _, id := range ids { - prototest.AssertContainsElement(suite.T(), reqs, controller.Request{ID: id}) - } -} - -func (suite *controllerSuite) requireEndpoints(resource *pbresource.Resource, expected ...*pbcatalog.Endpoint) { - var svcEndpoints pbcatalog.ServiceEndpoints - require.NoError(suite.T(), resource.Data.UnmarshalTo(&svcEndpoints)) - require.Len(suite.T(), svcEndpoints.Endpoints, len(expected)) - prototest.AssertElementsMatch(suite.T(), expected, svcEndpoints.Endpoints) -} - -func (suite *controllerSuite) TestReconcile_ServiceNotFound() { - // This test's purpose is to ensure that when we are reconciling - // endpoints for a service that no longer exists, we stop - // tracking the endpoints resource ID in the selection tracker. - - // generate a workload resource to use for checking if it maps - // to a service endpoints object - workload := rtest.Resource(pbcatalog.WorkloadType, "foo").Build() - - // ensure that the tracker knows about the service prior to - // calling reconcile so that we can ensure it removes tracking - id := rtest.Resource(pbcatalog.ServiceEndpointsType, "not-found").ID() - suite.tracker.TrackIDForSelector(id, &pbcatalog.WorkloadSelector{Prefixes: []string{""}}) - - // verify that mapping the workload to service endpoints returns a - // non-empty list prior to reconciliation which should remove the - // tracking. - suite.requireTracking(workload, id) - - // Because the endpoints don't exist, this reconcile call should - // cause tracking of the endpoints to be removed - err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) - require.NoError(suite.T(), err) - - // Now ensure that the tracking was removed - suite.requireTracking(workload) -} - -func (suite *controllerSuite) TestReconcile_NoSelector_NoEndpoints() { - // This test's purpose is to ensure that the service's status is - // updated to record that its endpoints are not being automatically - // managed. Additionally, with no endpoints pre-existing it will - // not attempt to delete them. - - service := rtest.Resource(pbcatalog.ServiceType, "test"). - WithData(suite.T(), &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - }). - Write(suite.T(), suite.client) - - endpointsID := rtest.Resource(pbcatalog.ServiceEndpointsType, "test").ID() - - err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: endpointsID}) - require.NoError(suite.T(), err) - - suite.client.RequireStatusCondition(suite.T(), service.Id, StatusKey, ConditionUnmanaged) -} - -func (suite *controllerSuite) TestReconcile_NoSelector_ManagedEndpoints() { - // This test's purpose is to ensure that when moving from managed endpoints - // to unmanaged endpoints for a service, any already generated managed endpoints - // get deleted. - - service := rtest.Resource(pbcatalog.ServiceType, "test"). - WithData(suite.T(), &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - }). - Write(suite.T(), suite.client) - - endpoints := rtest.Resource(pbcatalog.ServiceEndpointsType, "test"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{}). - // this marks these endpoints as under management - WithMeta(endpointsMetaManagedBy, StatusKey). - Write(suite.T(), suite.client) - - err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: endpoints.Id}) - require.NoError(suite.T(), err) - // the status should indicate the services endpoints are not being managed - suite.client.RequireStatusCondition(suite.T(), service.Id, StatusKey, ConditionUnmanaged) - // endpoints under management should be deleted - suite.client.RequireResourceNotFound(suite.T(), endpoints.Id) -} - -func (suite *controllerSuite) TestReconcile_NoSelector_UnmanagedEndpoints() { - // This test's purpose is to ensure that when re-reconciling a service that - // doesn't have its endpoints managed, that we do not delete any unmanaged - // ServiceEndpoints resource that the user would have manually written. - - service := rtest.Resource(pbcatalog.ServiceType, "test"). - WithData(suite.T(), &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - }). - Write(suite.T(), suite.client) - - endpoints := rtest.Resource(pbcatalog.ServiceEndpointsType, "test"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{}). - Write(suite.T(), suite.client) - - err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: endpoints.Id}) - require.NoError(suite.T(), err) - // the status should indicate the services endpoints are not being managed - suite.client.RequireStatusCondition(suite.T(), service.Id, StatusKey, ConditionUnmanaged) - // unmanaged endpoints should not be deleted when the service is unmanaged - suite.client.RequireResourceExists(suite.T(), endpoints.Id) -} - -func (suite *controllerSuite) TestReconcile_Managed_NoPreviousEndpoints() { - // This test's purpose is to ensure the managed endpoint generation occurs - // as expected when there are no pre-existing endpoints. - - service := rtest.Resource(pbcatalog.ServiceType, "test"). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - }). - Write(suite.T(), suite.client) - - endpointsID := rtest.Resource(pbcatalog.ServiceEndpointsType, "test").ID() - - rtest.Resource(pbcatalog.WorkloadType, "test-workload"). - WithData(suite.T(), &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "127.0.0.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - }). - Write(suite.T(), suite.client) - - err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: endpointsID}) - require.NoError(suite.T(), err) - - // Verify that the services status has been set to indicate endpoints are automatically managed. - suite.client.RequireStatusCondition(suite.T(), service.Id, StatusKey, ConditionManaged) - - // The service endpoints metadata should include our tag to indcate it was generated by this controller - res := suite.client.RequireResourceMeta(suite.T(), endpointsID, endpointsMetaManagedBy, StatusKey) - - var endpoints pbcatalog.ServiceEndpoints - err = res.Data.UnmarshalTo(&endpoints) - require.NoError(suite.T(), err) - require.Len(suite.T(), endpoints.Endpoints, 1) - // We are not going to retest that the workloads to endpoints conversion process - // The length check should be sufficient to prove the endpoints are being - // converted. The unit tests for the workloadsToEndpoints functions prove that - // the process works correctly in all cases. -} - -func (suite *controllerSuite) TestReconcile_Managed_ExistingEndpoints() { - // This test's purpose is to ensure that when the current set of endpoints - // differs from any prior set of endpoints that the resource gets rewritten. - - service := rtest.Resource(pbcatalog.ServiceType, "test"). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - }). - Write(suite.T(), suite.client) - - endpoints := rtest.Resource(pbcatalog.ServiceEndpointsType, "test"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{}). - WithOwner(service.Id). - Write(suite.T(), suite.client) - - rtest.Resource(pbcatalog.WorkloadType, "test-workload"). - WithData(suite.T(), &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "127.0.0.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - }). - Write(suite.T(), suite.client) - - err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: endpoints.Id}) - require.NoError(suite.T(), err) - - suite.client.RequireStatusCondition(suite.T(), service.Id, StatusKey, ConditionManaged) - res := suite.client.RequireResourceMeta(suite.T(), endpoints.Id, endpointsMetaManagedBy, StatusKey) - - var newEndpoints pbcatalog.ServiceEndpoints - err = res.Data.UnmarshalTo(&newEndpoints) - require.NoError(suite.T(), err) - require.Len(suite.T(), newEndpoints.Endpoints, 1) -} - -func (suite *controllerSuite) TestController() { - // This test's purpose is to exercise the controller in a halfway realistic way. - // Generally we are trying to go through the whole lifecycle of creating services, - // adding workloads, modifying workload health and modifying the service selection - // criteria. This isn't a full integration test as that would require also - // executing the workload health controller. Instead workload health status is - // synthesized as necessary. - - // Run the controller manager - mgr := controller.NewManager(suite.client, suite.rt.Logger) - mgr.Register(ServiceEndpointsController(suite.tracker)) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - // Add a service - there are no workloads so an empty endpoints - // object should be created. - service := rtest.Resource(pbcatalog.ServiceType, "api"). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - }). - Write(suite.T(), suite.client) - - // Wait for the controller to record that the endpoints are being managed - res := suite.client.WaitForReconciliation(suite.T(), service.Id, StatusKey) - // Check that the services status was updated accordingly - rtest.RequireStatusCondition(suite.T(), res, StatusKey, ConditionManaged) - rtest.RequireStatusCondition(suite.T(), res, StatusKey, ConditionIdentitiesNotFound) - - // Check that the endpoints resource exists and contains 0 endpoints - endpointsID := rtest.Resource(pbcatalog.ServiceEndpointsType, "api").ID() - endpoints := suite.client.RequireResourceExists(suite.T(), endpointsID) - suite.requireEndpoints(endpoints) - - // Now add a workload that would be selected by the service. Leave - // the workload in a state where its health has not been reconciled - workload := rtest.Resource(pbcatalog.WorkloadType, "api-1"). - WithData(suite.T(), &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "127.0.0.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 8081, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - Identity: "api", - }). - Write(suite.T(), suite.client) - - suite.client.WaitForStatusCondition(suite.T(), service.Id, StatusKey, - ConditionIdentitiesFound([]string{"api"})) - - // Wait for the endpoints to be regenerated - endpoints = suite.client.WaitForNewVersion(suite.T(), endpointsID, endpoints.Version) - - // Verify that the generated endpoints now contain the workload - suite.requireEndpoints(endpoints, &pbcatalog.Endpoint{ - TargetRef: workload.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - Identity: "api", - }) - - // Update the health status of the workload - suite.client.WriteStatus(suite.ctx, &pbresource.WriteStatusRequest{ - Id: workload.Id, - Key: workloadhealth.StatusKey, - Status: &pbresource.Status{ - ObservedGeneration: workload.Generation, - Conditions: []*pbresource.Condition{ - { - Type: workloadhealth.StatusConditionHealthy, - State: pbresource.Condition_STATE_TRUE, - Reason: "HEALTH_PASSING", - }, - }, - }, - }) - - // Wait for the endpoints to be regenerated - endpoints = suite.client.WaitForNewVersion(suite.T(), endpointsID, endpoints.Version) - - // ensure the endpoint was put into the passing state - suite.requireEndpoints(endpoints, &pbcatalog.Endpoint{ - TargetRef: workload.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "api", - }) - - // Update workload identity and check that the status on the service is updated - workload = rtest.Resource(pbcatalog.WorkloadType, "api-1"). - WithData(suite.T(), &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "127.0.0.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "grpc": {Port: 8081, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - Identity: "endpoints-api-identity", - }). - Write(suite.T(), suite.client) - - suite.client.WaitForStatusCondition(suite.T(), service.Id, StatusKey, ConditionIdentitiesFound([]string{"endpoints-api-identity"})) - - // Verify that the generated endpoints now contain the workload - endpoints = suite.client.WaitForNewVersion(suite.T(), endpointsID, endpoints.Version) - suite.requireEndpoints(endpoints, &pbcatalog.Endpoint{ - TargetRef: workload.Id, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1", Ports: []string{"http"}}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - Identity: "endpoints-api-identity", - }) - - // rewrite the service to add more selection criteria. This should trigger - // reconciliation but shouldn't result in updating the endpoints because - // the actual list of currently selected workloads has not changed - rtest.Resource(pbcatalog.ServiceType, "api"). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - Names: []string{"doesnt-matter"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - }). - Write(suite.T(), suite.client) - - // Wait for the service status' observed generation to get bumped - service = suite.client.WaitForReconciliation(suite.T(), service.Id, StatusKey) - - // Verify that the endpoints were not regenerated - suite.client.RequireVersionUnchanged(suite.T(), endpointsID, endpoints.Version) - - // Update the service. - updatedService := rtest.Resource(pbcatalog.ServiceType, "api"). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - }). - Write(suite.T(), suite.client) - - // Wait for the endpoints to be regenerated - endpoints = suite.client.WaitForNewVersion(suite.T(), endpointsID, endpoints.Version) - rtest.RequireOwner(suite.T(), endpoints, updatedService.Id, false) - - // Delete the endpoints. The controller should bring these back momentarily - suite.client.Delete(suite.ctx, &pbresource.DeleteRequest{Id: endpointsID}) - - // Wait for controller to recreate the endpoints - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireResourceExists(r, endpointsID) - }) - - // Move the service to having unmanaged endpoints - rtest.Resource(pbcatalog.ServiceType, "api"). - WithData(suite.T(), &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - }). - Write(suite.T(), suite.client) - - res = suite.client.WaitForReconciliation(suite.T(), service.Id, StatusKey) - rtest.RequireStatusCondition(suite.T(), res, StatusKey, ConditionUnmanaged) - - // Verify that the endpoints were deleted - suite.client.RequireResourceNotFound(suite.T(), endpointsID) -} - -func TestController(t *testing.T) { - suite.Run(t, new(controllerSuite)) -} diff --git a/internal/catalog/internal/controllers/endpoints/reconciliation_data.go b/internal/catalog/internal/controllers/endpoints/reconciliation_data.go deleted file mode 100644 index 320ad47470d5..000000000000 --- a/internal/catalog/internal/controllers/endpoints/reconciliation_data.go +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package endpoints - -import ( - "context" - "fmt" - "sort" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type serviceData struct { - resource *pbresource.Resource - service *pbcatalog.Service -} - -type endpointsData struct { - resource *pbresource.Resource - endpoints *pbcatalog.ServiceEndpoints -} - -type workloadData struct { - resource *pbresource.Resource - workload *pbcatalog.Workload -} - -// getServiceData will read the service with the given ID and unmarshal the -// Data field. The return value is a struct that contains the retrieved -// resource as well as the unmsashalled form. If the resource doesn't -// exist, nil will be returned. Any other error either with retrieving -// the resource or unmarshalling it will cause the error to be returned -// to the caller -func getServiceData(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*serviceData, error) { - rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) - switch { - case status.Code(err) == codes.NotFound: - return nil, nil - case err != nil: - return nil, err - } - - var service pbcatalog.Service - err = rsp.Resource.Data.UnmarshalTo(&service) - if err != nil { - return nil, resource.NewErrDataParse(&service, err) - } - - return &serviceData{resource: rsp.Resource, service: &service}, nil -} - -// getEndpointsData will read the endpoints with the given ID and unmarshal the -// Data field. The return value is a struct that contains the retrieved -// resource as well as the unmsashalled form. If the resource doesn't -// exist, nil will be returned. Any other error either with retrieving -// the resource or unmarshalling it will cause the error to be returned -// to the caller -func getEndpointsData(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*endpointsData, error) { - rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) - switch { - case status.Code(err) == codes.NotFound: - return nil, nil - case err != nil: - return nil, err - } - - var endpoints pbcatalog.ServiceEndpoints - err = rsp.Resource.Data.UnmarshalTo(&endpoints) - if err != nil { - return nil, resource.NewErrDataParse(&endpoints, err) - } - - return &endpointsData{resource: rsp.Resource, endpoints: &endpoints}, nil -} - -// getWorkloadData will retrieve all workloads for the given services selector -// and unmarhshal them, returning a slic of objects hold both the resource and -// unmarshaled forms. Unmarshalling errors, or other resource service errors -// will be returned to the caller. -func getWorkloadData(ctx context.Context, rt controller.Runtime, svc *serviceData) ([]*workloadData, error) { - workloadResources, err := gatherWorkloadsForService(ctx, rt, svc) - if err != nil { - return nil, err - } - - var results []*workloadData - for _, res := range workloadResources { - var workload pbcatalog.Workload - err = res.Data.UnmarshalTo(&workload) - if err != nil { - return nil, resource.NewErrDataParse(&workload, err) - } - - results = append(results, &workloadData{resource: res, workload: &workload}) - } - - return results, nil -} - -// gatherWorkloadsForService will retrieve all the unique workloads for a given selector. -// NotFound errors for workloads selected by Name will be ignored. Any other -// resource service errors will be returned to the caller. Prior to returning -// the slice of resources, they will be sorted by name. The consistent ordering -// will allow callers to diff two versions of the data to determine if anything -// has changed but it also will make testing a little easier. -func gatherWorkloadsForService(ctx context.Context, rt controller.Runtime, svc *serviceData) ([]*pbresource.Resource, error) { - var workloads []*pbresource.Resource - - sel := svc.service.GetWorkloads() - - // this map will track all the gathered workloads by name, this is mainly to deduplicate workloads if they - // are specified multiple times throughout the list of selection criteria - workloadNames := make(map[string]struct{}) - - // First gather all the prefix matched workloads. We could do this second but by doing - // it first its possible we can avoid some resource service calls to read individual - // workloads selected by name if they are also matched by a prefix. - for _, prefix := range sel.GetPrefixes() { - rsp, err := rt.Client.List(ctx, &pbresource.ListRequest{ - Type: pbcatalog.WorkloadType, - Tenancy: svc.resource.Id.Tenancy, - NamePrefix: prefix, - }) - if err != nil { - return nil, err - } - - // append all workloads in the list response to our list of all selected workloads - for _, workload := range rsp.Resources { - // ignore duplicate workloads - if _, found := workloadNames[workload.Id.Name]; !found { - workloads = append(workloads, workload) - workloadNames[workload.Id.Name] = struct{}{} - } - } - } - - // Now gather the exact match selections - for _, name := range sel.GetNames() { - // ignore names we have already fetched - if _, found := workloadNames[name]; found { - continue - } - - workloadID := &pbresource.ID{ - Type: pbcatalog.WorkloadType, - Tenancy: svc.resource.Id.Tenancy, - Name: name, - } - - rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: workloadID}) - switch { - case status.Code(err) == codes.NotFound: - // Ignore not found errors as services may select workloads that do not - // yet exist. This is not considered an error state or mis-configuration - // as the user could be getting ready to add the workloads. - continue - case err != nil: - return nil, err - } - - workloads = append(workloads, rsp.Resource) - workloadNames[rsp.Resource.Id.Name] = struct{}{} - } - - if sel.GetFilter() != "" && len(workloads) > 0 { - var err error - workloads, err = resource.FilterResourcesByMetadata(workloads, sel.GetFilter()) - if err != nil { - return nil, fmt.Errorf("error filtering results by metadata: %w", err) - } - } - - // Sorting ensures deterministic output. This will help for testing but - // the real reason to do this is so we will be able to diff the set of - // workloads endpoints to determine if we need to update them. - sort.Slice(workloads, func(i, j int) bool { - return workloads[i].Id.Name < workloads[j].Id.Name - }) - - return workloads, nil -} diff --git a/internal/catalog/internal/controllers/endpoints/reconciliation_data_test.go b/internal/catalog/internal/controllers/endpoints/reconciliation_data_test.go deleted file mode 100644 index d855c710f6c2..000000000000 --- a/internal/catalog/internal/controllers/endpoints/reconciliation_data_test.go +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package endpoints - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -type reconciliationDataSuite struct { - suite.Suite - - ctx context.Context - client pbresource.ResourceServiceClient - rt controller.Runtime - - apiServiceData *pbcatalog.Service - apiService *pbresource.Resource - apiServiceSubsetData *pbcatalog.Service - apiServiceSubset *pbresource.Resource - apiEndpoints *pbresource.Resource - api1Workload *pbresource.Resource - api2Workload *pbresource.Resource - api123Workload *pbresource.Resource - web1Workload *pbresource.Resource - web2Workload *pbresource.Resource -} - -func (suite *reconciliationDataSuite) SetupTest() { - suite.ctx = testutil.TestContext(suite.T()) - suite.client = svctest.RunResourceService(suite.T(), types.Register) - suite.rt = controller.Runtime{ - Client: suite.client, - Logger: testutil.Logger(suite.T()), - } - - suite.apiServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - // This services selectors are specially crafted to exercise both the - // dedeuplication and sorting behaviors of gatherWorkloadsForService - Prefixes: []string{"api-"}, - Names: []string{"api-1", "web-2", "web-1", "api-1", "not-found"}, - }, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "http", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - suite.apiServiceSubsetData = proto.Clone(suite.apiServiceData).(*pbcatalog.Service) - suite.apiServiceSubsetData.Workloads.Filter = "(zim in metadata) and (metadata.zim matches `^g.`)" - - suite.apiService = rtest.Resource(pbcatalog.ServiceType, "api"). - WithData(suite.T(), suite.apiServiceData). - Write(suite.T(), suite.client) - - suite.apiServiceSubset = rtest.Resource(pbcatalog.ServiceType, "api-subset"). - WithData(suite.T(), suite.apiServiceSubsetData). - Write(suite.T(), suite.client) - - suite.api1Workload = rtest.Resource(pbcatalog.WorkloadType, "api-1"). - WithMeta("zim", "dib"). - WithData(suite.T(), &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "api", - }). - Write(suite.T(), suite.client) - - suite.api2Workload = rtest.Resource(pbcatalog.WorkloadType, "api-2"). - WithData(suite.T(), &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "api", - }). - Write(suite.T(), suite.client) - - suite.api123Workload = rtest.Resource(pbcatalog.WorkloadType, "api-123"). - WithMeta("zim", "gir"). - WithData(suite.T(), &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "api", - }). - Write(suite.T(), suite.client) - - suite.web1Workload = rtest.Resource(pbcatalog.WorkloadType, "web-1"). - WithMeta("zim", "gaz"). - WithData(suite.T(), &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "web", - }). - Write(suite.T(), suite.client) - - suite.web2Workload = rtest.Resource(pbcatalog.WorkloadType, "web-2"). - WithData(suite.T(), &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "127.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Identity: "web", - }). - Write(suite.T(), suite.client) - - suite.apiEndpoints = rtest.Resource(pbcatalog.ServiceEndpointsType, "api"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: rtest.Resource(pbcatalog.WorkloadType, "api-1").WithTenancy(resource.DefaultNamespacedTenancy()).ID(), - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "127.0.0.1", - Ports: []string{"http"}, - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - }, - }). - Write(suite.T(), suite.client) -} - -func (suite *reconciliationDataSuite) TestGetServiceData_NotFound() { - // This test's purposes is to ensure that NotFound errors when retrieving - // the service data are ignored properly. - data, err := getServiceData(suite.ctx, suite.rt, rtest.Resource(pbcatalog.ServiceType, "not-found").WithTenancy(resource.DefaultNamespacedTenancy()).ID()) - require.NoError(suite.T(), err) - require.Nil(suite.T(), data) -} - -func (suite *reconciliationDataSuite) TestGetServiceData_ReadError() { - // This test's purpose is to ensure that Read errors other than NotFound - // are propagated back to the caller. Specifying a resource ID with an - // unregistered type is the easiest way to force a resource service error. - badType := &pbresource.Type{ - Group: "not", - Kind: "found", - GroupVersion: "vfake", - } - data, err := getServiceData(suite.ctx, suite.rt, rtest.Resource(badType, "foo").ID()) - require.Error(suite.T(), err) - require.Equal(suite.T(), codes.InvalidArgument, status.Code(err)) - require.Nil(suite.T(), data) -} - -func (suite *reconciliationDataSuite) TestGetServiceData_UnmarshalError() { - // This test's purpose is to ensure that unmarshlling errors are returned - // to the caller. We are using a resource id that points to an endpoints - // object instead of a service to ensure that the data will be unmarshallable. - data, err := getServiceData(suite.ctx, suite.rt, rtest.Resource(pbcatalog.ServiceEndpointsType, "api").ID()) - require.Error(suite.T(), err) - var parseErr resource.ErrDataParse - require.ErrorAs(suite.T(), err, &parseErr) - require.Nil(suite.T(), data) -} - -func (suite *reconciliationDataSuite) TestGetServiceData_Ok() { - // This test's purpose is to ensure that the happy path for - // retrieving a service works as expected. - data, err := getServiceData(suite.ctx, suite.rt, suite.apiService.Id) - require.NoError(suite.T(), err) - require.NotNil(suite.T(), data) - require.NotNil(suite.T(), data.resource) - prototest.AssertDeepEqual(suite.T(), suite.apiService.Id, data.resource.Id) - require.Len(suite.T(), data.service.Ports, 1) -} - -func (suite *reconciliationDataSuite) TestGetEndpointsData_NotFound() { - // This test's purposes is to ensure that NotFound errors when retrieving - // the endpoint data are ignored properly. - data, err := getEndpointsData(suite.ctx, suite.rt, rtest.Resource(pbcatalog.ServiceEndpointsType, "not-found").ID()) - require.NoError(suite.T(), err) - require.Nil(suite.T(), data) -} - -func (suite *reconciliationDataSuite) TestGetEndpointsData_ReadError() { - // This test's purpose is to ensure that Read errors other than NotFound - // are propagated back to the caller. Specifying a resource ID with an - // unregistered type is the easiest way to force a resource service error. - badType := &pbresource.Type{ - Group: "not", - Kind: "found", - GroupVersion: "vfake", - } - data, err := getEndpointsData(suite.ctx, suite.rt, rtest.Resource(badType, "foo").ID()) - require.Error(suite.T(), err) - require.Equal(suite.T(), codes.InvalidArgument, status.Code(err)) - require.Nil(suite.T(), data) -} - -func (suite *reconciliationDataSuite) TestGetEndpointsData_UnmarshalError() { - // This test's purpose is to ensure that unmarshlling errors are returned - // to the caller. We are using a resource id that points to a service object - // instead of an endpoints object to ensure that the data will be unmarshallable. - data, err := getEndpointsData(suite.ctx, suite.rt, rtest.Resource(pbcatalog.ServiceType, "api").ID()) - require.Error(suite.T(), err) - var parseErr resource.ErrDataParse - require.ErrorAs(suite.T(), err, &parseErr) - require.Nil(suite.T(), data) -} - -func (suite *reconciliationDataSuite) TestGetEndpointsData_Ok() { - // This test's purpose is to ensure that the happy path for - // retrieving an endpoints object works as expected. - data, err := getEndpointsData(suite.ctx, suite.rt, suite.apiEndpoints.Id) - require.NoError(suite.T(), err) - require.NotNil(suite.T(), data) - require.NotNil(suite.T(), data.resource) - prototest.AssertDeepEqual(suite.T(), suite.apiEndpoints.Id, data.resource.Id) - require.Len(suite.T(), data.endpoints.Endpoints, 1) -} - -func (suite *reconciliationDataSuite) TestGetWorkloadData() { - // This test's purpose is to ensure that gather workloads for - // a service work as expected. The services selector was crafted - // to exercise the deduplication behavior as well as the sorting - // behavior. The assertions in this test will verify that only - // unique workloads are returned and that they are ordered. - - data, err := getWorkloadData(suite.ctx, suite.rt, &serviceData{ - resource: suite.apiService, - service: suite.apiServiceData, - }) - - require.NoError(suite.T(), err) - require.Len(suite.T(), data, 5) - prototest.AssertDeepEqual(suite.T(), suite.api1Workload, data[0].resource) - prototest.AssertDeepEqual(suite.T(), suite.api123Workload, data[1].resource) - prototest.AssertDeepEqual(suite.T(), suite.api2Workload, data[2].resource) - prototest.AssertDeepEqual(suite.T(), suite.web1Workload, data[3].resource) - prototest.AssertDeepEqual(suite.T(), suite.web2Workload, data[4].resource) -} - -func (suite *reconciliationDataSuite) TestGetWorkloadDataWithFilter() { - // This is like TestGetWorkloadData except it exercises the post-read - // filter on the selector. - data, err := getWorkloadData(suite.ctx, suite.rt, &serviceData{ - resource: suite.apiServiceSubset, - service: suite.apiServiceSubsetData, - }) - - require.NoError(suite.T(), err) - require.Len(suite.T(), data, 2) - prototest.AssertDeepEqual(suite.T(), suite.api123Workload, data[0].resource) - prototest.AssertDeepEqual(suite.T(), suite.web1Workload, data[1].resource) -} - -func TestReconciliationData(t *testing.T) { - suite.Run(t, new(reconciliationDataSuite)) -} diff --git a/internal/catalog/internal/controllers/endpoints/status.go b/internal/catalog/internal/controllers/endpoints/status.go deleted file mode 100644 index 078d5e9a5f7f..000000000000 --- a/internal/catalog/internal/controllers/endpoints/status.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package endpoints - -import ( - "fmt" - "strings" - - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - StatusKey = "consul.io/endpoint-manager" - StatusConditionEndpointsManaged = "EndpointsManaged" - - StatusReasonSelectorNotFound = "SelectorNotFound" - StatusReasonSelectorFound = "SelectorFound" - - selectorFoundMessage = "A valid workload selector is present within the service." - selectorNotFoundMessage = "Either the workload selector was not present or contained no selection criteria." - - StatusConditionBoundIdentities = "BoundIdentities" - - StatusReasonWorkloadIdentitiesFound = "WorkloadIdentitiesFound" - StatusReasonNoWorkloadIdentitiesFound = "NoWorkloadIdentitiesFound" - - identitiesFoundMessageFormat = "Found workload identities associated with this service: %q." - identitiesNotFoundChangedMessage = "No associated workload identities found." -) - -var ( - ConditionManaged = &pbresource.Condition{ - Type: StatusConditionEndpointsManaged, - State: pbresource.Condition_STATE_TRUE, - Reason: StatusReasonSelectorFound, - Message: selectorFoundMessage, - } - - ConditionUnmanaged = &pbresource.Condition{ - Type: StatusConditionEndpointsManaged, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonSelectorNotFound, - Message: selectorNotFoundMessage, - } - - ConditionIdentitiesNotFound = &pbresource.Condition{ - Type: StatusConditionBoundIdentities, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonNoWorkloadIdentitiesFound, - Message: identitiesNotFoundChangedMessage, - } -) - -func ConditionIdentitiesFound(identities []string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionBoundIdentities, - State: pbresource.Condition_STATE_TRUE, - Reason: StatusReasonWorkloadIdentitiesFound, - Message: fmt.Sprintf(identitiesFoundMessageFormat, strings.Join(identities, ",")), - } -} diff --git a/internal/catalog/internal/controllers/failover/controller.go b/internal/catalog/internal/controllers/failover/controller.go deleted file mode 100644 index ef236b954ca4..000000000000 --- a/internal/catalog/internal/controllers/failover/controller.go +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package failover - -import ( - "context" - - "github.com/hashicorp/consul/internal/catalog/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// FailoverMapper tracks the relationship between a FailoverPolicy an a Service -// it references whether due to name-alignment or from a reference in a -// FailoverDestination leg. -type FailoverMapper interface { - // TrackFailover extracts all Service references from the provided - // FailoverPolicy and indexes them so that MapService can turn Service - // events into FailoverPolicy events properly. - TrackFailover(failover *resource.DecodedResource[*pbcatalog.FailoverPolicy]) - - // UntrackFailover forgets the links inserted by TrackFailover for the - // provided FailoverPolicyID. - UntrackFailover(failoverID *pbresource.ID) - - // MapService will take a Service resource and return controller requests - // for all FailoverPolicies associated with the Service. - MapService(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) -} - -func FailoverPolicyController(mapper FailoverMapper) controller.Controller { - if mapper == nil { - panic("No FailoverMapper was provided to the FailoverPolicyController constructor") - } - return controller.ForType(pbcatalog.FailoverPolicyType). - WithWatch(pbcatalog.ServiceType, mapper.MapService). - WithReconciler(newFailoverPolicyReconciler(mapper)) -} - -type failoverPolicyReconciler struct { - mapper FailoverMapper -} - -func newFailoverPolicyReconciler(mapper FailoverMapper) *failoverPolicyReconciler { - return &failoverPolicyReconciler{ - mapper: mapper, - } -} - -func (r *failoverPolicyReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - // The runtime is passed by value so replacing it here for the remainder of this - // reconciliation request processing will not affect future invocations. - rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", StatusKey) - - rt.Logger.Trace("reconciling failover policy") - - failoverPolicyID := req.ID - - failoverPolicy, err := getFailoverPolicy(ctx, rt, failoverPolicyID) - if err != nil { - rt.Logger.Error("error retrieving failover policy", "error", err) - return err - } - if failoverPolicy == nil { - r.mapper.UntrackFailover(failoverPolicyID) - - // Either the failover policy was deleted, or it doesn't exist but an - // update to a Service came through and we can ignore it. - return nil - } - - r.mapper.TrackFailover(failoverPolicy) - - // FailoverPolicy is name-aligned with the Service it controls. - serviceID := &pbresource.ID{ - Type: pbcatalog.ServiceType, - Tenancy: failoverPolicyID.Tenancy, - Name: failoverPolicyID.Name, - } - - service, err := getService(ctx, rt, serviceID) - if err != nil { - rt.Logger.Error("error retrieving corresponding service", "error", err) - return err - } - destServices := make(map[resource.ReferenceKey]*resource.DecodedResource[*pbcatalog.Service]) - if service != nil { - destServices[resource.NewReferenceKey(serviceID)] = service - } - - // Denorm the ports and stuff. After this we have no empty ports. - if service != nil { - failoverPolicy.Data = types.SimplifyFailoverPolicy( - service.Data, - failoverPolicy.Data, - ) - } - - // Fetch services. - for _, dest := range failoverPolicy.Data.GetUnderlyingDestinations() { - if dest.Ref == nil || !isServiceType(dest.Ref.Type) || dest.Ref.Section != "" { - continue // invalid, not possible due to validation hook - } - - key := resource.NewReferenceKey(dest.Ref) - - if _, ok := destServices[key]; ok { - continue - } - - destID := resource.IDFromReference(dest.Ref) - - destService, err := getService(ctx, rt, destID) - if err != nil { - rt.Logger.Error("error retrieving destination service", "service", key, "error", err) - return err - } - - if destService != nil { - destServices[key] = destService - } - } - - newStatus := computeNewStatus(failoverPolicy, service, destServices) - - if resource.EqualStatus(failoverPolicy.Resource.Status[StatusKey], newStatus, false) { - rt.Logger.Trace("resource's failover policy status is unchanged", - "conditions", newStatus.Conditions) - return nil - } - - _, err = rt.Client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ - Id: failoverPolicy.Resource.Id, - Key: StatusKey, - Status: newStatus, - }) - - if err != nil { - rt.Logger.Error("error encountered when attempting to update the resource's failover policy status", "error", err) - return err - } - - rt.Logger.Trace("resource's failover policy status was updated", - "conditions", newStatus.Conditions) - return nil -} - -func getFailoverPolicy(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*resource.DecodedResource[*pbcatalog.FailoverPolicy], error) { - return resource.GetDecodedResource[*pbcatalog.FailoverPolicy](ctx, rt.Client, id) -} - -func getService(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*resource.DecodedResource[*pbcatalog.Service], error) { - return resource.GetDecodedResource[*pbcatalog.Service](ctx, rt.Client, id) -} - -func computeNewStatus( - failoverPolicy *resource.DecodedResource[*pbcatalog.FailoverPolicy], - service *resource.DecodedResource[*pbcatalog.Service], - destServices map[resource.ReferenceKey]*resource.DecodedResource[*pbcatalog.Service], -) *pbresource.Status { - if service == nil { - return &pbresource.Status{ - ObservedGeneration: failoverPolicy.Resource.Generation, - Conditions: []*pbresource.Condition{ - ConditionMissingService, - }, - } - } - - allowedPortProtocols := make(map[string]pbcatalog.Protocol) - for _, port := range service.Data.Ports { - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue // skip - } - allowedPortProtocols[port.TargetPort] = port.Protocol - } - - var conditions []*pbresource.Condition - - if failoverPolicy.Data.Config != nil { - for _, dest := range failoverPolicy.Data.Config.Destinations { - // We know from validation that a Ref must be set, and the type it - // points to is a Service. - // - // Rather than do additional validation, just do a quick - // belt-and-suspenders check-and-skip if something looks weird. - if dest.Ref == nil || !isServiceType(dest.Ref.Type) { - continue - } - - if cond := serviceHasPort(dest, destServices); cond != nil { - conditions = append(conditions, cond) - } - } - // TODO: validate that referenced sameness groups exist - } - - for port, pc := range failoverPolicy.Data.PortConfigs { - if _, ok := allowedPortProtocols[port]; !ok { - conditions = append(conditions, ConditionUnknownPort(port)) - } - - for _, dest := range pc.Destinations { - // We know from validation that a Ref must be set, and the type it - // points to is a Service. - // - // Rather than do additional validation, just do a quick - // belt-and-suspenders check-and-skip if something looks weird. - if dest.Ref == nil || !isServiceType(dest.Ref.Type) { - continue - } - - if cond := serviceHasPort(dest, destServices); cond != nil { - conditions = append(conditions, cond) - } - } - - // TODO: validate that referenced sameness groups exist - } - - if len(conditions) > 0 { - return &pbresource.Status{ - ObservedGeneration: failoverPolicy.Resource.Generation, - Conditions: conditions, - } - } - - return &pbresource.Status{ - ObservedGeneration: failoverPolicy.Resource.Generation, - Conditions: []*pbresource.Condition{ - ConditionOK, - }, - } -} - -func serviceHasPort( - dest *pbcatalog.FailoverDestination, - destServices map[resource.ReferenceKey]*resource.DecodedResource[*pbcatalog.Service], -) *pbresource.Condition { - key := resource.NewReferenceKey(dest.Ref) - destService, ok := destServices[key] - if !ok { - return ConditionMissingDestinationService(dest.Ref) - } - - found := false - mesh := false - for _, port := range destService.Data.Ports { - if port.TargetPort == dest.Port { - found = true - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - mesh = true - } - break - } - } - - if !found { - return ConditionUnknownDestinationPort(dest.Ref, dest.Port) - } else if mesh { - return ConditionUsingMeshDestinationPort(dest.Ref, dest.Port) - } - - return nil -} - -func isServiceType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, pbcatalog.ServiceType): - return true - } - return false -} diff --git a/internal/catalog/internal/controllers/failover/controller_test.go b/internal/catalog/internal/controllers/failover/controller_test.go deleted file mode 100644 index a82a6f0fdee6..000000000000 --- a/internal/catalog/internal/controllers/failover/controller_test.go +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package failover - -import ( - "context" - "testing" - - "github.com/stretchr/testify/suite" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog/internal/mappers/failovermapper" - "github.com/hashicorp/consul/internal/catalog/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/sdk/testutil" -) - -type controllerSuite struct { - suite.Suite - - ctx context.Context - client *rtest.Client - rt controller.Runtime - - failoverMapper FailoverMapper - - ctl failoverPolicyReconciler -} - -func (suite *controllerSuite) SetupTest() { - suite.ctx = testutil.TestContext(suite.T()) - client := svctest.RunResourceService(suite.T(), types.Register) - suite.rt = controller.Runtime{ - Client: client, - Logger: testutil.Logger(suite.T()), - } - suite.client = rtest.NewClient(client) - - suite.failoverMapper = failovermapper.New() -} - -func (suite *controllerSuite) TestController() { - // This test's purpose is to exercise the controller in a halfway realistic - // way, verifying the event triggers work in the live code. - - // Run the controller manager - mgr := controller.NewManager(suite.client, suite.rt.Logger) - mgr.Register(FailoverPolicyController(suite.failoverMapper)) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - // Create an advance pointer to some services. - apiServiceRef := resource.Reference(rtest.Resource(pbcatalog.ServiceType, "api").WithTenancy(resource.DefaultNamespacedTenancy()).ID(), "") - otherServiceRef := resource.Reference(rtest.Resource(pbcatalog.ServiceType, "other").WithTenancy(resource.DefaultNamespacedTenancy()).ID(), "") - - // create a failover without any services - failoverData := &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: apiServiceRef, - }}, - }, - } - failover := rtest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithData(suite.T(), failoverData). - Write(suite.T(), suite.client) - - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionMissingService) - - // Provide the service. - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{{ - TargetPort: "http", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }}, - } - _ = rtest.Resource(pbcatalog.ServiceType, "api"). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionOK) - - // Update the failover to reference an unknown port - failoverData = &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: apiServiceRef, - Port: "http", - }}, - }, - "admin": { - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: apiServiceRef, - Port: "admin", - }}, - }, - }, - } - _ = rtest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithData(suite.T(), failoverData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionUnknownPort("admin")) - - // update the service to fix the stray reference, but point to a mesh port - apiServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "http", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "admin", - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - } - _ = rtest.Resource(pbcatalog.ServiceType, "api"). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionUsingMeshDestinationPort(apiServiceRef, "admin")) - - // update the service to fix the stray reference to not be a mesh port - apiServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "http", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "admin", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - _ = rtest.Resource(pbcatalog.ServiceType, "api"). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionOK) - - // change failover leg to point to missing service - failoverData = &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: apiServiceRef, - Port: "http", - }}, - }, - "admin": { - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: otherServiceRef, - Port: "admin", - }}, - }, - }, - } - _ = rtest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithData(suite.T(), failoverData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionMissingDestinationService(otherServiceRef)) - - // Create the missing service, but forget the port. - otherServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"other-"}}, - Ports: []*pbcatalog.ServicePort{{ - TargetPort: "http", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }}, - } - _ = rtest.Resource(pbcatalog.ServiceType, "other"). - WithData(suite.T(), otherServiceData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionUnknownDestinationPort(otherServiceRef, "admin")) - - // fix the destination leg's port - otherServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"other-"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "http", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "admin", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - _ = rtest.Resource(pbcatalog.ServiceType, "other"). - WithData(suite.T(), otherServiceData). - Write(suite.T(), suite.client) - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionOK) - - // Update the two services to use differnet port names so the easy path doesn't work - apiServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "foo", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "bar", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - _ = rtest.Resource(pbcatalog.ServiceType, "api"). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - - otherServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"other-"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "foo", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "baz", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - _ = rtest.Resource(pbcatalog.ServiceType, "other"). - WithData(suite.T(), otherServiceData). - Write(suite.T(), suite.client) - - failoverData = &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: otherServiceRef, - }}, - }, - } - failover = rtest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithData(suite.T(), failoverData). - Write(suite.T(), suite.client) - - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionUnknownDestinationPort(otherServiceRef, "bar")) - - // and fix it the silly way by removing it from api+failover - apiServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"api-"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "foo", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - _ = rtest.Resource(pbcatalog.ServiceType, "api"). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - - suite.client.WaitForStatusCondition(suite.T(), failover.Id, StatusKey, ConditionOK) -} - -func TestFailoverController(t *testing.T) { - suite.Run(t, new(controllerSuite)) -} diff --git a/internal/catalog/internal/controllers/failover/status.go b/internal/catalog/internal/controllers/failover/status.go deleted file mode 100644 index b2801c41ed93..000000000000 --- a/internal/catalog/internal/controllers/failover/status.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package failover - -import ( - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - StatusKey = "consul.io/failover-policy" - StatusConditionAccepted = "accepted" - - OKReason = "Ok" - OKMessage = "failover policy was accepted" - - MissingServiceReason = "MissingService" - MissingServiceMessage = "service for failover policy does not exist" - - UnknownPortReason = "UnknownPort" - UnknownPortMessagePrefix = "port is not defined on service: " - - MissingDestinationServiceReason = "MissingDestinationService" - MissingDestinationServiceMessagePrefix = "destination service for failover policy does not exist: " - - UnknownDestinationPortReason = "UnknownDestinationPort" - UnknownDestinationPortMessagePrefix = "port is not defined on destination service: " - - UsingMeshDestinationPortReason = "UsingMeshDestinationPort" - UsingMeshDestinationPortMessagePrefix = "port is a special unroutable mesh port on destination service: " -) - -var ( - ConditionOK = &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_TRUE, - Reason: OKReason, - Message: OKMessage, - } - - ConditionMissingService = &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: MissingServiceReason, - Message: MissingServiceMessage, - } -) - -func ConditionUnknownPort(port string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: UnknownPortReason, - Message: UnknownPortMessagePrefix + port, - } -} - -func ConditionMissingDestinationService(ref *pbresource.Reference) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: MissingDestinationServiceReason, - Message: MissingDestinationServiceMessagePrefix + resource.ReferenceToString(ref), - } -} - -func ConditionUnknownDestinationPort(ref *pbresource.Reference, port string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: UnknownDestinationPortReason, - Message: UnknownDestinationPortMessagePrefix + port + " on " + resource.ReferenceToString(ref), - } -} - -func ConditionUsingMeshDestinationPort(ref *pbresource.Reference, port string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: UnknownDestinationPortReason, - Message: UnknownDestinationPortMessagePrefix + port + " on " + resource.ReferenceToString(ref), - } -} diff --git a/internal/catalog/internal/controllers/nodehealth/controller.go b/internal/catalog/internal/controllers/nodehealth/controller.go deleted file mode 100644 index 9ef656b6a8bb..000000000000 --- a/internal/catalog/internal/controllers/nodehealth/controller.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package nodehealth - -import ( - "context" - "fmt" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func NodeHealthController() controller.Controller { - return controller.ForType(pbcatalog.NodeType). - WithWatch(pbcatalog.HealthStatusType, controller.MapOwnerFiltered(pbcatalog.NodeType)). - WithReconciler(&nodeHealthReconciler{}) -} - -type nodeHealthReconciler struct{} - -func (r *nodeHealthReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - // The runtime is passed by value so replacing it here for the remainder of this - // reconciliation request processing will not affect future invocations. - rt.Logger = rt.Logger.With("resource-id", req.ID) - - rt.Logger.Trace("reconciling node health") - - // read the node - rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: req.ID}) - switch { - case status.Code(err) == codes.NotFound: - rt.Logger.Trace("node has been deleted") - return nil - case err != nil: - rt.Logger.Error("the resource service has returned an unexpected error", "error", err) - return err - } - - res := rsp.Resource - - health, err := getNodeHealth(ctx, rt, req.ID) - if err != nil { - rt.Logger.Error("failed to calculate the nodes health", "error", err) - return err - } - - newStatus := &pbresource.Status{ - ObservedGeneration: res.Generation, - Conditions: []*pbresource.Condition{ - Conditions[health], - }, - } - - if resource.EqualStatus(res.Status[StatusKey], newStatus, false) { - rt.Logger.Trace("resources node health status is unchanged", "health", health.String()) - return nil - } - - _, err = rt.Client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ - Id: res.Id, - Key: StatusKey, - Status: newStatus, - }) - - if err != nil { - rt.Logger.Error("error encountered when attempting to update the resources node health status", "error", err) - return err - } - - rt.Logger.Trace("resources node health status was updated", "health", health.String()) - return nil -} - -func getNodeHealth(ctx context.Context, rt controller.Runtime, nodeRef *pbresource.ID) (pbcatalog.Health, error) { - rsp, err := rt.Client.ListByOwner(ctx, &pbresource.ListByOwnerRequest{ - Owner: nodeRef, - }) - - if err != nil { - return pbcatalog.Health_HEALTH_CRITICAL, err - } - - health := pbcatalog.Health_HEALTH_PASSING - - for _, res := range rsp.Resources { - if resource.EqualType(res.Id.Type, pbcatalog.HealthStatusType) { - var hs pbcatalog.HealthStatus - if err := res.Data.UnmarshalTo(&hs); err != nil { - // This should be impossible as the resource service + type validations the - // catalog is performing will ensure that no data gets written where unmarshalling - // to this type will error. - return pbcatalog.Health_HEALTH_CRITICAL, fmt.Errorf("error unmarshalling health status data: %w", err) - } - - if hs.Status > health { - health = hs.Status - } - } - } - - return health, nil -} diff --git a/internal/catalog/internal/controllers/nodehealth/controller_test.go b/internal/catalog/internal/controllers/nodehealth/controller_test.go deleted file mode 100644 index b21c52e521f8..000000000000 --- a/internal/catalog/internal/controllers/nodehealth/controller_test.go +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package nodehealth - -import ( - "context" - "fmt" - "testing" - - "github.com/oklog/ulid/v2" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" -) - -var ( - nodeData = &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{ - { - Host: "127.0.0.1", - }, - }, - } - - dnsPolicyData = &pbcatalog.DNSPolicy{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - Weights: &pbcatalog.Weights{ - Passing: 1, - Warning: 1, - }, - } -) - -func resourceID(rtype *pbresource.Type, name string) *pbresource.ID { - return &pbresource.ID{ - Type: rtype, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: name, - } -} - -type nodeHealthControllerTestSuite struct { - suite.Suite - - resourceClient pbresource.ResourceServiceClient - runtime controller.Runtime - - ctl nodeHealthReconciler - - nodeNoHealth *pbresource.ID - nodePassing *pbresource.ID - nodeWarning *pbresource.ID - nodeCritical *pbresource.ID - nodeMaintenance *pbresource.ID -} - -func (suite *nodeHealthControllerTestSuite) SetupTest() { - suite.resourceClient = svctest.RunResourceService(suite.T(), types.Register, types.RegisterDNSPolicy) - suite.runtime = controller.Runtime{Client: suite.resourceClient, Logger: testutil.Logger(suite.T())} - - // The rest of the setup will be to prime the resource service with some data - suite.nodeNoHealth = resourcetest.Resource(pbcatalog.NodeType, "test-node-no-health"). - WithData(suite.T(), nodeData). - Write(suite.T(), suite.resourceClient).Id - - suite.nodePassing = resourcetest.Resource(pbcatalog.NodeType, "test-node-passing"). - WithData(suite.T(), nodeData). - Write(suite.T(), suite.resourceClient).Id - - suite.nodeWarning = resourcetest.Resource(pbcatalog.NodeType, "test-node-warning"). - WithData(suite.T(), nodeData). - Write(suite.T(), suite.resourceClient).Id - - suite.nodeCritical = resourcetest.Resource(pbcatalog.NodeType, "test-node-critical"). - WithData(suite.T(), nodeData). - Write(suite.T(), suite.resourceClient).Id - - suite.nodeMaintenance = resourcetest.Resource(pbcatalog.NodeType, "test-node-maintenance"). - WithData(suite.T(), nodeData). - Write(suite.T(), suite.resourceClient).Id - - nodeHealthDesiredStatus := map[string]pbcatalog.Health{ - suite.nodePassing.Name: pbcatalog.Health_HEALTH_PASSING, - suite.nodeWarning.Name: pbcatalog.Health_HEALTH_WARNING, - suite.nodeCritical.Name: pbcatalog.Health_HEALTH_CRITICAL, - suite.nodeMaintenance.Name: pbcatalog.Health_HEALTH_MAINTENANCE, - } - - // In order to exercise the behavior to ensure that its not a last-status-wins sort of thing - // we are strategically naming health statuses so that they will be returned in an order with - // the most precedent status being in the middle of the list. This will ensure that statuses - // seen later can overide a previous status and that statuses seen later do not override if - // they would lower the overall status such as going from critical -> warning. - precedenceHealth := []pbcatalog.Health{ - pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_MAINTENANCE, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_PASSING, - } - - for _, node := range []*pbresource.ID{suite.nodePassing, suite.nodeWarning, suite.nodeCritical, suite.nodeMaintenance} { - for idx, health := range precedenceHealth { - if nodeHealthDesiredStatus[node.Name] >= health { - resourcetest.Resource(pbcatalog.HealthStatusType, fmt.Sprintf("test-check-%s-%d", node.Name, idx)). - WithData(suite.T(), &pbcatalog.HealthStatus{Type: "tcp", Status: health}). - WithOwner(node). - Write(suite.T(), suite.resourceClient) - } - } - } - - // create a DNSPolicy to be owned by the node. The type doesn't really matter it just needs - // to be something that doesn't care about its owner. All we want to prove is that we are - // filtering out non-HealthStatus types appropriately. - resourcetest.Resource(pbcatalog.DNSPolicyType, "test-policy"). - WithData(suite.T(), dnsPolicyData). - WithOwner(suite.nodeNoHealth). - Write(suite.T(), suite.resourceClient) -} - -func (suite *nodeHealthControllerTestSuite) TestGetNodeHealthListError() { - // This resource id references a resource type that will not be - // registered with the resource service. The ListByOwner call - // should produce an InvalidArgument error. This test is meant - // to validate how that error is handled (its propagated back - // to the caller) - ref := resourceID( - &pbresource.Type{Group: "not", GroupVersion: "v1", Kind: "found"}, - "irrelevant", - ) - health, err := getNodeHealth(context.Background(), suite.runtime, ref) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_CRITICAL, health) - require.Error(suite.T(), err) - require.Equal(suite.T(), codes.InvalidArgument, status.Code(err)) -} - -func (suite *nodeHealthControllerTestSuite) TestGetNodeHealthNoNode() { - // This test is meant to ensure that when the node doesn't exist - // no error is returned but also no data is. The default passing - // status should then be returned in the same manner as the node - // existing but with no associated HealthStatus resources. - ref := resourceID(pbcatalog.NodeType, "foo") - ref.Uid = ulid.Make().String() - health, err := getNodeHealth(context.Background(), suite.runtime, ref) - - require.NoError(suite.T(), err) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_PASSING, health) -} - -func (suite *nodeHealthControllerTestSuite) TestGetNodeHealthNoStatus() { - health, err := getNodeHealth(context.Background(), suite.runtime, suite.nodeNoHealth) - require.NoError(suite.T(), err) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_PASSING, health) -} - -func (suite *nodeHealthControllerTestSuite) TestGetNodeHealthPassingStatus() { - health, err := getNodeHealth(context.Background(), suite.runtime, suite.nodePassing) - require.NoError(suite.T(), err) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_PASSING, health) -} - -func (suite *nodeHealthControllerTestSuite) TestGetNodeHealthCriticalStatus() { - health, err := getNodeHealth(context.Background(), suite.runtime, suite.nodeCritical) - require.NoError(suite.T(), err) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_CRITICAL, health) -} - -func (suite *nodeHealthControllerTestSuite) TestGetNodeHealthWarningStatus() { - health, err := getNodeHealth(context.Background(), suite.runtime, suite.nodeWarning) - require.NoError(suite.T(), err) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_WARNING, health) -} - -func (suite *nodeHealthControllerTestSuite) TestGetNodeHealthMaintenanceStatus() { - health, err := getNodeHealth(context.Background(), suite.runtime, suite.nodeMaintenance) - require.NoError(suite.T(), err) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_MAINTENANCE, health) -} - -func (suite *nodeHealthControllerTestSuite) TestReconcileNodeNotFound() { - // This test ensures that removed nodes are ignored. In particular we don't - // want to propagate the error and indefinitely keep re-reconciling in this case. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: resourceID(pbcatalog.NodeType, "not-found"), - }) - require.NoError(suite.T(), err) -} - -func (suite *nodeHealthControllerTestSuite) TestReconcilePropagateReadError() { - // This test aims to ensure that errors other than NotFound errors coming - // from the initial resource read get propagated. This case is very unrealistic - // as the controller should not have given us a request ID for a resource type - // that doesn't exist but this was the easiest way I could think of to synthesize - // a Read error. - ref := resourceID( - &pbresource.Type{Group: "not", GroupVersion: "v1", Kind: "found"}, - "irrelevant", - ) - - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: ref, - }) - require.Error(suite.T(), err) - require.Equal(suite.T(), codes.InvalidArgument, status.Code(err)) -} - -func (suite *nodeHealthControllerTestSuite) testReconcileStatus(id *pbresource.ID, expectedStatus *pbresource.Condition) *pbresource.Resource { - suite.T().Helper() - - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: id, - }) - require.NoError(suite.T(), err) - - rsp, err := suite.resourceClient.Read(context.Background(), &pbresource.ReadRequest{ - Id: id, - }) - require.NoError(suite.T(), err) - - nodeHealthStatus, found := rsp.Resource.Status[StatusKey] - require.True(suite.T(), found) - require.Equal(suite.T(), rsp.Resource.Generation, nodeHealthStatus.ObservedGeneration) - require.Len(suite.T(), nodeHealthStatus.Conditions, 1) - prototest.AssertDeepEqual(suite.T(), - nodeHealthStatus.Conditions[0], - expectedStatus) - - return rsp.Resource -} - -func (suite *nodeHealthControllerTestSuite) TestReconcile_StatusPassing() { - suite.testReconcileStatus(suite.nodePassing, &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_TRUE, - Reason: "HEALTH_PASSING", - Message: NodeHealthyMessage, - }) -} - -func (suite *nodeHealthControllerTestSuite) TestReconcile_StatusWarning() { - suite.testReconcileStatus(suite.nodeWarning, &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_WARNING", - Message: NodeUnhealthyMessage, - }) -} - -func (suite *nodeHealthControllerTestSuite) TestReconcile_StatusCritical() { - suite.testReconcileStatus(suite.nodeCritical, &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_CRITICAL", - Message: NodeUnhealthyMessage, - }) -} - -func (suite *nodeHealthControllerTestSuite) TestReconcile_StatusMaintenance() { - suite.testReconcileStatus(suite.nodeMaintenance, &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_MAINTENANCE", - Message: NodeUnhealthyMessage, - }) -} - -func (suite *nodeHealthControllerTestSuite) TestReconcile_AvoidRereconciliationWrite() { - res1 := suite.testReconcileStatus(suite.nodeWarning, &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_WARNING", - Message: NodeUnhealthyMessage, - }) - - res2 := suite.testReconcileStatus(suite.nodeWarning, &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_WARNING", - Message: NodeUnhealthyMessage, - }) - - // If another status write was performed then the versions would differ. This - // therefore proves that after a second reconciliation without any change in status - // that we are not making subsequent status writes. - require.Equal(suite.T(), res1.Version, res2.Version) -} - -func (suite *nodeHealthControllerTestSuite) waitForReconciliation(id *pbresource.ID, reason string) { - suite.T().Helper() - - retry.Run(suite.T(), func(r *retry.R) { - rsp, err := suite.resourceClient.Read(context.Background(), &pbresource.ReadRequest{ - Id: id, - }) - require.NoError(r, err) - - nodeHealthStatus, found := rsp.Resource.Status[StatusKey] - require.True(r, found) - require.Equal(r, rsp.Resource.Generation, nodeHealthStatus.ObservedGeneration) - require.Len(r, nodeHealthStatus.Conditions, 1) - require.Equal(r, reason, nodeHealthStatus.Conditions[0].Reason) - }) -} -func (suite *nodeHealthControllerTestSuite) TestController() { - // create the controller manager - mgr := controller.NewManager(suite.resourceClient, testutil.Logger(suite.T())) - - // register our controller - mgr.Register(NodeHealthController()) - mgr.SetRaftLeader(true) - ctx, cancel := context.WithCancel(context.Background()) - suite.T().Cleanup(cancel) - - // run the manager - go mgr.Run(ctx) - - // ensure that the node health eventually gets set. - suite.waitForReconciliation(suite.nodePassing, "HEALTH_PASSING") - - // rewrite the resource - this will cause the nodes health - // to be rereconciled but wont result in any health change - resourcetest.Resource(pbcatalog.NodeType, suite.nodePassing.Name). - WithData(suite.T(), &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{ - { - Host: "198.18.0.1", - }, - }, - }). - Write(suite.T(), suite.resourceClient) - - // wait for rereconciliation to happen - suite.waitForReconciliation(suite.nodePassing, "HEALTH_PASSING") - - resourcetest.Resource(pbcatalog.HealthStatusType, "failure"). - WithData(suite.T(), &pbcatalog.HealthStatus{Type: "fake", Status: pbcatalog.Health_HEALTH_CRITICAL}). - WithOwner(suite.nodePassing). - Write(suite.T(), suite.resourceClient) - - suite.waitForReconciliation(suite.nodePassing, "HEALTH_CRITICAL") -} - -func TestNodeHealthController(t *testing.T) { - suite.Run(t, new(nodeHealthControllerTestSuite)) -} diff --git a/internal/catalog/internal/controllers/nodehealth/status.go b/internal/catalog/internal/controllers/nodehealth/status.go deleted file mode 100644 index 11997bc47e68..000000000000 --- a/internal/catalog/internal/controllers/nodehealth/status.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package nodehealth - -import ( - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - StatusKey = "consul.io/node-health" - StatusConditionHealthy = "healthy" - - NodeHealthyMessage = "All node health checks are passing" - NodeUnhealthyMessage = "One or more node health checks are not passing" -) - -var ( - ConditionPassing = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_TRUE, - Reason: pbcatalog.Health_HEALTH_PASSING.String(), - Message: NodeHealthyMessage, - } - - ConditionWarning = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: pbcatalog.Health_HEALTH_WARNING.String(), - Message: NodeUnhealthyMessage, - } - - ConditionCritical = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: pbcatalog.Health_HEALTH_CRITICAL.String(), - Message: NodeUnhealthyMessage, - } - - ConditionMaintenance = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: pbcatalog.Health_HEALTH_MAINTENANCE.String(), - Message: NodeUnhealthyMessage, - } - - Conditions = map[pbcatalog.Health]*pbresource.Condition{ - pbcatalog.Health_HEALTH_PASSING: ConditionPassing, - pbcatalog.Health_HEALTH_WARNING: ConditionWarning, - pbcatalog.Health_HEALTH_CRITICAL: ConditionCritical, - pbcatalog.Health_HEALTH_MAINTENANCE: ConditionMaintenance, - } -) diff --git a/internal/catalog/internal/controllers/register.go b/internal/catalog/internal/controllers/register.go deleted file mode 100644 index df1f7c88c7b2..000000000000 --- a/internal/catalog/internal/controllers/register.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package controllers - -import ( - "github.com/hashicorp/consul/internal/catalog/internal/controllers/endpoints" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/failover" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/nodehealth" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/workloadhealth" - "github.com/hashicorp/consul/internal/controller" -) - -type Dependencies struct { - WorkloadHealthNodeMapper workloadhealth.NodeMapper - EndpointsWorkloadMapper endpoints.WorkloadMapper - FailoverMapper failover.FailoverMapper -} - -func Register(mgr *controller.Manager, deps Dependencies) { - mgr.Register(nodehealth.NodeHealthController()) - mgr.Register(workloadhealth.WorkloadHealthController(deps.WorkloadHealthNodeMapper)) - mgr.Register(endpoints.ServiceEndpointsController(deps.EndpointsWorkloadMapper)) - mgr.Register(failover.FailoverPolicyController(deps.FailoverMapper)) -} diff --git a/internal/catalog/internal/controllers/workloadhealth/controller.go b/internal/catalog/internal/controllers/workloadhealth/controller.go deleted file mode 100644 index 05cfd36a84bf..000000000000 --- a/internal/catalog/internal/controllers/workloadhealth/controller.go +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package workloadhealth - -import ( - "context" - "errors" - "fmt" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/hashicorp/consul/internal/catalog/internal/controllers/nodehealth" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -var ( - errNodeUnreconciled = errors.New("Node health has not been reconciled yet") - errNodeHealthInvalid = errors.New("Node health has invalid reason") - errNodeHealthConditionNotFound = fmt.Errorf("Node health status is missing the %s condition", nodehealth.StatusConditionHealthy) -) - -// The NodeMapper interface is used to provide an implementation around being able to -// map a watch event for a Node resource and translate it to reconciliation requests -// for all Workloads assigned to that node. -type NodeMapper interface { - // MapNodeToWorkloads will take a Node resource and return controller requests - // for all Workloads associated with the Node. - MapNodeToWorkloads(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) - - // TrackWorkload instructs the NodeMapper to associate the given workload - // ID with the given node ID. - TrackWorkload(workloadID *pbresource.ID, nodeID *pbresource.ID) - - // UntrackWorkload instructs the Nodemapper to forget about any - // association it was tracking for this workload. - UntrackWorkload(workloadID *pbresource.ID) - - // NodeIDFromWorkload is used to generate the resource ID for the Node referenced - // within the NodeName field of the Workload. - NodeIDFromWorkload(workload *pbresource.Resource, workloadData *pbcatalog.Workload) *pbresource.ID -} - -func WorkloadHealthController(nodeMap NodeMapper) controller.Controller { - if nodeMap == nil { - panic("No NodeMapper was provided to the WorkloadHealthController constructor") - } - - return controller.ForType(pbcatalog.WorkloadType). - WithWatch(pbcatalog.HealthStatusType, controller.MapOwnerFiltered(pbcatalog.WorkloadType)). - WithWatch(pbcatalog.NodeType, nodeMap.MapNodeToWorkloads). - WithReconciler(&workloadHealthReconciler{nodeMap: nodeMap}) -} - -type workloadHealthReconciler struct { - nodeMap NodeMapper -} - -func (r *workloadHealthReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - // The runtime is passed by value so replacing it here for the remainder of this - // reconciliation request processing will not affect future invocations. - rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", StatusKey) - - rt.Logger.Trace("reconciling workload health") - - // read the workload - rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: req.ID}) - switch { - case status.Code(err) == codes.NotFound: - rt.Logger.Trace("workload has been deleted") - r.nodeMap.UntrackWorkload(req.ID) - return nil - case err != nil: - rt.Logger.Error("the resource service has returned an unexpected error", "error", err) - return err - } - - res := rsp.Resource - var workload pbcatalog.Workload - if err := res.Data.UnmarshalTo(&workload); err != nil { - // This should be impossible and will not be exercised in tests. Various - // type validations on admission ensure that all Workloads would - // be marshallable in this way. - rt.Logger.Error("error unmarshalling workload data", "error", err) - return err - } - - nodeHealth := pbcatalog.Health_HEALTH_PASSING - if workload.NodeName != "" { - nodeID := r.nodeMap.NodeIDFromWorkload(res, &workload) - r.nodeMap.TrackWorkload(res.Id, nodeID) - - // It is important that getting the nodes health happens after tracking the - // Workload with the node mapper. If the order were reversed we could - // potentially miss events for data that changes after we read the node but - // before we configured the node mapper to map subsequent events to this - // workload. - nodeHealth, err = getNodeHealth(ctx, rt, nodeID) - if err != nil { - rt.Logger.Error("error looking up node health", "error", err, "node-id", nodeID) - return err - } - } else { - // the node association may be been removed so stop tracking it. - r.nodeMap.UntrackWorkload(res.Id) - } - - // passing the workload from the response because getWorkloadHealth uses - // resourceClient.ListByOwner which requires ownerID have a Uid and this is the - // safest way for application and test code to ensure Uid is provided. - workloadHealth, err := getWorkloadHealth(ctx, rt, rsp.Resource.Id) - if err != nil { - // This should be impossible under normal operations and will not be exercised - // within the unit tests. This can only fail if the resource service fails - // or allows admission of invalid health statuses. - rt.Logger.Error("error aggregating workload health statuses", "error", err) - return err - } - - health := nodeHealth - if workloadHealth > health { - health = workloadHealth - } - - condition := WorkloadConditions[workloadHealth] - if workload.NodeName != "" { - condition = NodeAndWorkloadConditions[workloadHealth][nodeHealth] - } - - newStatus := &pbresource.Status{ - ObservedGeneration: res.Generation, - Conditions: []*pbresource.Condition{ - condition, - }, - } - - if resource.EqualStatus(res.Status[StatusKey], newStatus, false) { - rt.Logger.Trace("resources workload health status is unchanged", - "health", health.String(), - "node-health", nodeHealth.String(), - "workload-health", workloadHealth.String()) - return nil - } - - _, err = rt.Client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ - Id: res.Id, - Key: StatusKey, - Status: newStatus, - }) - - if err != nil { - rt.Logger.Error("error encountered when attempting to update the resources workload status", "error", err) - return err - } - - rt.Logger.Trace("resource's workload health status was updated", - "health", health.String(), - "node-health", nodeHealth.String(), - "workload-health", workloadHealth.String()) - return nil -} - -func getNodeHealth(ctx context.Context, rt controller.Runtime, nodeRef *pbresource.ID) (pbcatalog.Health, error) { - rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: nodeRef}) - switch { - case status.Code(err) == codes.NotFound: - return pbcatalog.Health_HEALTH_CRITICAL, nil - case err != nil: - return pbcatalog.Health_HEALTH_CRITICAL, err - default: - healthStatus, ok := rsp.Resource.Status[nodehealth.StatusKey] - if !ok { - // The Nodes health has never been reconciled and therefore the - // workloads health cannot be determined. Returning nil is acceptable - // because the controller should sometime soon run reconciliation for - // the node which will then trigger rereconciliation of this workload - return pbcatalog.Health_HEALTH_CRITICAL, errNodeUnreconciled - } - - for _, condition := range healthStatus.Conditions { - if condition.Type == nodehealth.StatusConditionHealthy { - if condition.State == pbresource.Condition_STATE_TRUE { - return pbcatalog.Health_HEALTH_PASSING, nil - } - - healthReason, valid := pbcatalog.Health_value[condition.Reason] - if !valid { - // The Nodes health is unknown - presumably the node health controller - // will come along and fix that up momentarily causing this workload - // reconciliation to occur again. - return pbcatalog.Health_HEALTH_CRITICAL, errNodeHealthInvalid - } - return pbcatalog.Health(healthReason), nil - } - } - return pbcatalog.Health_HEALTH_CRITICAL, errNodeHealthConditionNotFound - } -} - -func getWorkloadHealth(ctx context.Context, rt controller.Runtime, workloadRef *pbresource.ID) (pbcatalog.Health, error) { - rt.Logger.Trace("getWorkloadHealth", "workloadRef", workloadRef) - rsp, err := rt.Client.ListByOwner(ctx, &pbresource.ListByOwnerRequest{ - Owner: workloadRef, - }) - - if err != nil { - return pbcatalog.Health_HEALTH_CRITICAL, err - } - - workloadHealth := pbcatalog.Health_HEALTH_PASSING - - for _, res := range rsp.Resources { - if resource.EqualType(res.Id.Type, pbcatalog.HealthStatusType) { - var hs pbcatalog.HealthStatus - if err := res.Data.UnmarshalTo(&hs); err != nil { - // This should be impossible and will not be executing in tests. The resource type - // is the HealthStatus type and therefore must be unmarshallable into the HealthStatus - // object or else it wouldn't have passed admission validation checks. - return workloadHealth, fmt.Errorf("error unmarshalling health status data: %w", err) - } - - if hs.Status > workloadHealth { - workloadHealth = hs.Status - } - } - } - - return workloadHealth, nil -} diff --git a/internal/catalog/internal/controllers/workloadhealth/controller_test.go b/internal/catalog/internal/controllers/workloadhealth/controller_test.go deleted file mode 100644 index ba72b9934f94..000000000000 --- a/internal/catalog/internal/controllers/workloadhealth/controller_test.go +++ /dev/null @@ -1,842 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package workloadhealth - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/hashicorp/consul/internal/resource" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/testing/protocmp" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/catalog/internal/controllers/nodehealth" - "github.com/hashicorp/consul/internal/catalog/internal/mappers/nodemapper" - "github.com/hashicorp/consul/internal/catalog/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" -) - -var ( - nodeData = &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{ - { - Host: "127.0.0.1", - }, - }, - } - - fakeType = &pbresource.Type{ - Group: "not", - GroupVersion: "vfake", - Kind: "found", - } -) - -func resourceID(rtype *pbresource.Type, name string, tenancy *pbresource.Tenancy) *pbresource.ID { - defaultTenancy := resource.DefaultNamespacedTenancy() - if tenancy != nil { - defaultTenancy = tenancy - } - - return &pbresource.ID{ - Type: rtype, - Tenancy: defaultTenancy, - Name: name, - } -} - -func workloadData(nodeName string) *pbcatalog.Workload { - return &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "198.18.0.1", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": { - Port: 8080, - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - Identity: "test", - NodeName: nodeName, - } -} - -// controllerSuite is just the base information the three other test suites -// in this file will use. It will be embedded into the others allowing -// for the test helpers and default setup to be reused and to force consistent -// anming of the various data bits this holds on to. -type controllerSuite struct { - suite.Suite - client pbresource.ResourceServiceClient - runtime controller.Runtime - - isEnterprise bool - tenancies []*pbresource.Tenancy -} - -func (suite *controllerSuite) SetupTest() { - suite.tenancies = resourcetest.TestTenancies() - mockTenancyBridge := &svc.MockTenancyBridge{} - for _, tenancy := range suite.tenancies { - mockTenancyBridge.On("PartitionExists", tenancy.Partition).Return(true, nil) - mockTenancyBridge.On("IsPartitionMarkedForDeletion", tenancy.Partition).Return(false, nil) - mockTenancyBridge.On("NamespaceExists", tenancy.Partition, tenancy.Namespace).Return(true, nil) - mockTenancyBridge.On("IsNamespaceMarkedForDeletion", tenancy.Partition, tenancy.Namespace).Return(false, nil) - } - - suite.client = svctest.RunResourceServiceWithConfig(suite.T(), svc.Config{TenancyBridge: mockTenancyBridge}, types.Register) - suite.runtime = controller.Runtime{Client: suite.client, Logger: testutil.Logger(suite.T())} - suite.isEnterprise = (structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default") -} - -// injectNodeWithStatus is a helper method to write a Node resource and synthesize its status -// in a manner consistent with the node-health controller. This allows us to not actually -// run and test the node-health controller but consume its "api" in the form of how -// it encodes status. -func (suite *controllerSuite) injectNodeWithStatus(name string, health pbcatalog.Health, tenancy *pbresource.Tenancy) *pbresource.Resource { - suite.T().Helper() - state := pbresource.Condition_STATE_TRUE - if health >= pbcatalog.Health_HEALTH_WARNING { - state = pbresource.Condition_STATE_FALSE - } - - return resourcetest.Resource(pbcatalog.NodeType, name). - WithData(suite.T(), nodeData). - WithTenancy(tenancy). - WithStatus(nodehealth.StatusKey, &pbresource.Status{ - Conditions: []*pbresource.Condition{ - { - Type: nodehealth.StatusConditionHealthy, - State: state, - Reason: health.String(), - }, - }, - }). - Write(suite.T(), suite.client) -} - -// the workloadHealthControllerTestSuite intends to test the main Reconciliation -// functionality but will not do exhaustive testing of the getNodeHealth -// or getWorkloadHealth functions. Without mocking the resource service which -// we for now are avoiding, it should be impossible to inject errors into -// those functions that would force some kinds of error cases. Therefore, -// those other functions will be tested with their own test suites. -type workloadHealthControllerTestSuite struct { - controllerSuite - - mapper *nodemapper.NodeMapper - reconciler *workloadHealthReconciler -} - -func (suite *workloadHealthControllerTestSuite) SetupTest() { - // invoke all the other suite setup - suite.controllerSuite.SetupTest() - - suite.mapper = nodemapper.New() - suite.reconciler = &workloadHealthReconciler{ - nodeMap: suite.mapper, - } -} - -// testReconcileWithNode will inject a node with the given health, a workload -// associated with that node and then a health status owned by the workload -// with the given workload health. Once all the resource injection has been -// performed this will invoke the Reconcile method once on the reconciler -// and checks a couple things: -// -// * The node to workload association is now being tracked by the node mapper -// * The workloads status was updated and now matches the expected value -func (suite *workloadHealthControllerTestSuite) testReconcileWithNode(nodeHealth, workloadHealth pbcatalog.Health, tenancy *pbresource.Tenancy, status *pbresource.Condition) *pbresource.Resource { - suite.T().Helper() - - node := suite.injectNodeWithStatus("test-node", nodeHealth, tenancy) - - workload := resourcetest.Resource(pbcatalog.WorkloadType, "test-workload"). - WithData(suite.T(), workloadData(node.Id.Name)). - WithTenancy(tenancy). - Write(suite.T(), suite.client) - - resourcetest.Resource(pbcatalog.HealthStatusType, "test-status"). - WithData(suite.T(), &pbcatalog.HealthStatus{Type: "tcp", Status: workloadHealth}). - WithOwner(workload.Id). - WithTenancy(tenancy). - Write(suite.T(), suite.client) - - err := suite.reconciler.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: workload.Id, - }) - - require.NoError(suite.T(), err) - - // ensure that the node is now being tracked by the mapper - reqs, err := suite.mapper.MapNodeToWorkloads(context.Background(), suite.runtime, node) - require.NoError(suite.T(), err) - require.Len(suite.T(), reqs, 1) - protocmp.Transform() - prototest.AssertDeepEqual(suite.T(), workload.Id, reqs[0].ID, protocmp.IgnoreFields(workload.Id, "uid")) - - suite.T().Cleanup(func() { - // future calls to reconcile would normally have done this as the resource was - // removed. In the case of reconcile being called manually, when the resources - // are automatically removed, the tracking will be stale. In most tests this step - // to remove the tracking should be unnecessary as they will not be reusing a - // mapper between subtests and so it will get "removed" as the mapper is gc'ed. - suite.mapper.UntrackWorkload(workload.Id) - }) - - return suite.checkWorkloadStatus(workload.Id, status) -} - -// testReconcileWithoutNode will inject a workload associated and then a health status -// owned by the workload with the given workload health. Once all the resource injection -// has been performed this will invoke the Reconcile method once on the reconciler -// and check that the computed status matches the expected value -// -// This is really just a tirmmed down version of testReconcileWithNode. It seemed -// simpler and easier to read if these were two separate methods instead of combining -// them in one with more branching based off of detecting whether nodes are in use. -func (suite *workloadHealthControllerTestSuite) testReconcileWithoutNode(workloadHealth pbcatalog.Health, tenancy *pbresource.Tenancy, status *pbresource.Condition) *pbresource.Resource { - suite.T().Helper() - workload := resourcetest.Resource(pbcatalog.WorkloadType, "test-workload"). - WithData(suite.T(), workloadData("")). - WithTenancy(tenancy). - Write(suite.T(), suite.client) - - resourcetest.Resource(pbcatalog.HealthStatusType, "test-status"). - WithData(suite.T(), &pbcatalog.HealthStatus{Type: "tcp", Status: workloadHealth}). - WithTenancy(tenancy). - WithOwner(workload.Id). - Write(suite.T(), suite.client) - - err := suite.reconciler.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: workload.Id, - }) - - require.NoError(suite.T(), err) - - // Read the resource back so we can detect the status changes - return suite.checkWorkloadStatus(workload.Id, status) -} - -// checkWorkloadStatus will read the workload resource and verify that its -// status has the expected value. -func (suite *workloadHealthControllerTestSuite) checkWorkloadStatus(id *pbresource.ID, status *pbresource.Condition) *pbresource.Resource { - suite.T().Helper() - - rsp, err := suite.client.Read(context.Background(), &pbresource.ReadRequest{ - Id: id, - }) - - require.NoError(suite.T(), err) - - actualStatus, found := rsp.Resource.Status[StatusKey] - require.True(suite.T(), found) - require.Equal(suite.T(), rsp.Resource.Generation, actualStatus.ObservedGeneration) - require.Len(suite.T(), actualStatus.Conditions, 1) - prototest.AssertDeepEqual(suite.T(), status, actualStatus.Conditions[0]) - - return rsp.Resource -} - -func (suite *workloadHealthControllerTestSuite) TestReconcile() { - // This test intends to ensure all the permutations of node health and workload - // health end up with the correct computed status. When a test case omits - // the workload health (or sets it to pbcatalog.Health_HEALTH_ANY) then the - // workloads are nodeless and therefore node health will not be considered. - // Additionally the messages put in the status for nodeless workloads are - // a little different to not mention nodes and provide the user more context - // about where the failing health checks are. - - type testCase struct { - nodeHealth pbcatalog.Health - workloadHealth pbcatalog.Health - expectedStatus *pbresource.Condition - } - - cases := map[string]testCase{ - "workload-passing": { - workloadHealth: pbcatalog.Health_HEALTH_PASSING, - expectedStatus: &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_TRUE, - Reason: "HEALTH_PASSING", - Message: WorkloadHealthyMessage, - }, - }, - "workload-warning": { - workloadHealth: pbcatalog.Health_HEALTH_WARNING, - expectedStatus: &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_WARNING", - Message: WorkloadUnhealthyMessage, - }, - }, - "workload-critical": { - workloadHealth: pbcatalog.Health_HEALTH_CRITICAL, - expectedStatus: &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_CRITICAL", - Message: WorkloadUnhealthyMessage, - }, - }, - "workload-maintenance": { - workloadHealth: pbcatalog.Health_HEALTH_MAINTENANCE, - expectedStatus: &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_MAINTENANCE", - Message: WorkloadUnhealthyMessage, - }, - }, - "combined-passing": { - nodeHealth: pbcatalog.Health_HEALTH_PASSING, - workloadHealth: pbcatalog.Health_HEALTH_PASSING, - expectedStatus: &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_TRUE, - Reason: "HEALTH_PASSING", - Message: NodeAndWorkloadHealthyMessage, - }, - }, - "combined-warning-node": { - nodeHealth: pbcatalog.Health_HEALTH_WARNING, - workloadHealth: pbcatalog.Health_HEALTH_PASSING, - expectedStatus: &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_WARNING", - Message: nodehealth.NodeUnhealthyMessage, - }, - }, - "combined-warning-workload": { - nodeHealth: pbcatalog.Health_HEALTH_PASSING, - workloadHealth: pbcatalog.Health_HEALTH_WARNING, - expectedStatus: &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_WARNING", - Message: WorkloadUnhealthyMessage, - }, - }, - "combined-critical-node": { - nodeHealth: pbcatalog.Health_HEALTH_CRITICAL, - workloadHealth: pbcatalog.Health_HEALTH_WARNING, - expectedStatus: &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_CRITICAL", - Message: NodeAndWorkloadUnhealthyMessage, - }, - }, - "combined-critical-workload": { - nodeHealth: pbcatalog.Health_HEALTH_WARNING, - workloadHealth: pbcatalog.Health_HEALTH_CRITICAL, - expectedStatus: &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_CRITICAL", - Message: NodeAndWorkloadUnhealthyMessage, - }, - }, - "combined-maintenance-node": { - nodeHealth: pbcatalog.Health_HEALTH_MAINTENANCE, - workloadHealth: pbcatalog.Health_HEALTH_CRITICAL, - expectedStatus: &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_MAINTENANCE", - Message: NodeAndWorkloadUnhealthyMessage, - }, - }, - "combined-maintenance-workload": { - nodeHealth: pbcatalog.Health_HEALTH_CRITICAL, - workloadHealth: pbcatalog.Health_HEALTH_MAINTENANCE, - expectedStatus: &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_MAINTENANCE", - Message: NodeAndWorkloadUnhealthyMessage, - }, - }, - } - - for name, tcase := range cases { - suite.Run(name, func() { - suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - if tcase.nodeHealth != pbcatalog.Health_HEALTH_ANY { - suite.testReconcileWithNode(tcase.nodeHealth, tcase.workloadHealth, tenancy, tcase.expectedStatus) - } else { - suite.testReconcileWithoutNode(tcase.workloadHealth, tenancy, tcase.expectedStatus) - } - }) - }) - } -} - -func (suite *workloadHealthControllerTestSuite) TestReconcileReadError() { - // This test's goal is to prove that errors other than NotFound from the Resource service - // when reading the workload to reconcile will be propagate back to the Reconcile caller. - // - // Passing a resource with an unknown type isn't particularly realistic as the controller - // manager running our reconciliation will ensure all resource ids used are valid. However - // its a really easy way right not to force the error. - suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - id := resourceID(fakeType, "blah", tenancy) - - err := suite.reconciler.Reconcile(context.Background(), suite.runtime, controller.Request{ID: id}) - require.Error(suite.T(), err) - require.Equal(suite.T(), codes.InvalidArgument, status.Code(err)) - }) -} - -func (suite *workloadHealthControllerTestSuite) TestReconcileNotFound() { - // This test wants to ensure that tracking for a workload is removed when the workload is deleted - // so this test will inject the tracking, issue the Reconcile call which will get a - // not found error and then ensure that the tracking was removed. - suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - workload := resourcetest.Resource(pbcatalog.WorkloadType, "foo"). - WithData(suite.T(), workloadData("test-node")). - // don't write this because then in the call to reconcile the resource - // would be found and defeat the purpose of the tes - WithTenancy(tenancy). - Build() - - node := resourcetest.Resource(pbcatalog.NodeType, "test-node"). - WithData(suite.T(), nodeData). - WithTenancy(tenancy). - // Whether this gets written or not doesn't matter - Build() - - // Track the workload - this simulates a previous round of reconciliation - // where the workload existed and was associated to the node. Other tests - // will cover more of the lifecycle of the controller so for the purposes - // of this test we can just inject it ourselves. - suite.mapper.TrackWorkload(workload.Id, node.Id) - - // check that the worklooad is in fact tracked properly - reqs, err := suite.mapper.MapNodeToWorkloads(context.Background(), suite.runtime, node) - - require.NoError(suite.T(), err) - require.Len(suite.T(), reqs, 1) - prototest.AssertDeepEqual(suite.T(), workload.Id, reqs[0].ID) - - // This workload was never actually inserted so the request should return a NotFound - // error and remove the workload from tracking - require.NoError( - suite.T(), - suite.reconciler.Reconcile( - context.Background(), - suite.runtime, - controller.Request{ID: workload.Id})) - - // Check the mapper again to ensure the node:workload association was removed. - reqs, err = suite.mapper.MapNodeToWorkloads(context.Background(), suite.runtime, node) - require.NoError(suite.T(), err) - require.Empty(suite.T(), reqs) - }) -} - -func (suite *workloadHealthControllerTestSuite) TestGetNodeHealthError() { - // This test aims to ensure that errors coming from the getNodeHealth - // function are propagated back to the caller. In order to do so - // we are going to inject a node but not set its status yet. This - // simulates the condition where the workload health controller happened - // to start reconciliation before the node health controller. In that - // case we also expect the errNodeUnreconciled error to be returned - // but the exact error isn't very relevant to the core reason this - // test exists. - - suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - node := resourcetest.Resource(pbcatalog.NodeType, "test-node"). - WithData(suite.T(), nodeData). - WithTenancy(tenancy). - Write(suite.T(), suite.client) - - workload := resourcetest.Resource(pbcatalog.WorkloadType, "test-workload"). - WithData(suite.T(), workloadData(node.Id.Name)). - WithTenancy(tenancy). - Write(suite.T(), suite.client) - - resourcetest.Resource(pbcatalog.HealthStatusType, "test-status"). - WithData(suite.T(), &pbcatalog.HealthStatus{Type: "tcp", Status: pbcatalog.Health_HEALTH_CRITICAL}). - WithOwner(workload.Id). - WithTenancy(tenancy). - Write(suite.T(), suite.client) - - err := suite.reconciler.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: workload.Id, - }) - - require.Error(suite.T(), err) - require.Equal(suite.T(), errNodeUnreconciled, err) - }) -} - -func (suite *workloadHealthControllerTestSuite) TestReconcile_AvoidReconciliationWrite() { - // The sole purpose of this test is to ensure that calls to Reconcile for an already - // reconciled workload will not perform extra/unnecessary status writes. Basically - // we check that calling Reconcile twice in a row without any actual health change - // doesn't bump the Version (which would increased for any write of the resource - // or its status) - suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - status := &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "HEALTH_WARNING", - Message: WorkloadUnhealthyMessage, - } - res1 := suite.testReconcileWithoutNode(pbcatalog.Health_HEALTH_WARNING, tenancy, status) - - err := suite.reconciler.Reconcile(context.Background(), suite.runtime, controller.Request{ID: res1.Id}) - require.NoError(suite.T(), err) - - // check that the status hasn't changed - res2 := suite.checkWorkloadStatus(res1.Id, status) - - // If another status write was performed then the versions would differ. This - // therefore proves that after a second reconciliation without any change - // in status that the controller is not making extra status writes. - require.Equal(suite.T(), res1.Version, res2.Version) - }) -} - -func (suite *workloadHealthControllerTestSuite) TestController() { - // This test aims to be a very light weight integration test of the - // controller with the controller manager as well as a general - // controller lifecycle test. - - // create the controller manager - mgr := controller.NewManager(suite.client, testutil.Logger(suite.T())) - - // register our controller - mgr.Register(WorkloadHealthController(suite.mapper)) - mgr.SetRaftLeader(true) - ctx, cancel := context.WithCancel(context.Background()) - suite.T().Cleanup(cancel) - - // run the manager - go mgr.Run(ctx) - - suite.controllerSuite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - node := suite.injectNodeWithStatus("test-node", pbcatalog.Health_HEALTH_PASSING, tenancy) - - // create the workload - workload := resourcetest.Resource(pbcatalog.WorkloadType, "test-workload"). - WithData(suite.T(), workloadData(node.Id.Name)). - WithTenancy(tenancy). - Write(suite.T(), suite.client) - - // Wait for reconciliation to occur and mark the workload as passing. - suite.waitForReconciliation(workload.Id, "HEALTH_PASSING") - - // Simulate a node unhealthy - suite.injectNodeWithStatus("test-node", pbcatalog.Health_HEALTH_WARNING, tenancy) - - // Wait for reconciliation to occur and mark the workload as warning - // due to the node going into the warning state. - suite.waitForReconciliation(workload.Id, "HEALTH_WARNING") - - // Now register a critical health check that should supercede the nodes - // warning status - - resourcetest.Resource(pbcatalog.HealthStatusType, "test-status"). - WithData(suite.T(), &pbcatalog.HealthStatus{Type: "tcp", Status: pbcatalog.Health_HEALTH_CRITICAL}). - WithOwner(workload.Id). - WithTenancy(tenancy). - Write(suite.T(), suite.client) - - // Wait for reconciliation to occur again and mark the workload as unhealthy - suite.waitForReconciliation(workload.Id, "HEALTH_CRITICAL") - - // Put the health status back into a passing state and delink the node - resourcetest.Resource(pbcatalog.HealthStatusType, "test-status"). - WithData(suite.T(), &pbcatalog.HealthStatus{Type: "tcp", Status: pbcatalog.Health_HEALTH_PASSING}). - WithOwner(workload.Id). - WithTenancy(tenancy). - Write(suite.T(), suite.client) - workload = resourcetest.Resource(pbcatalog.WorkloadType, "test-workload"). - WithData(suite.T(), workloadData("")). - WithTenancy(tenancy). - Write(suite.T(), suite.client) - - // Now that the workload health is passing and its not associated with the node its status should - // eventually become passing - suite.waitForReconciliation(workload.Id, "HEALTH_PASSING") - }) -} - -// wait for reconciliation is a helper to check if a resource has been reconciled and -// is marked with the expected status. -func (suite *workloadHealthControllerTestSuite) waitForReconciliation(id *pbresource.ID, reason string) { - suite.T().Helper() - - retry.RunWith(&retry.Timer{Wait: 100 * time.Millisecond, Timeout: 5 * time.Second}, - suite.T(), func(r *retry.R) { - rsp, err := suite.client.Read(context.Background(), &pbresource.ReadRequest{ - Id: id, - }) - require.NoError(r, err) - - status, found := rsp.Resource.Status[StatusKey] - require.True(r, found) - require.Equal(r, rsp.Resource.Generation, status.ObservedGeneration) - require.Len(r, status.Conditions, 1) - require.Equal(r, reason, status.Conditions[0].Reason) - }) -} - -func TestWorkloadHealthController(t *testing.T) { - suite.Run(t, new(workloadHealthControllerTestSuite)) -} - -type getWorkloadHealthTestSuite struct { - controllerSuite -} - -func (suite *getWorkloadHealthTestSuite) addHealthStatuses(workload *pbresource.ID, tenancy *pbresource.Tenancy, desiredHealth pbcatalog.Health) { - // In order to exercise the behavior to ensure that the ordering a health status is - // seen doesn't matter this is strategically naming health status so that they will be - // returned in an order with the most precedent status being in the middle of the list. - // This will ensure that statuses seen later can override a previous status that that - // status seen later do not override if they would lower the overall status such as - // going from critical -> warning. - healthStatuses := []pbcatalog.Health{ - pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_MAINTENANCE, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_PASSING, - } - - for idx, health := range healthStatuses { - if desiredHealth >= health { - resourcetest.Resource(pbcatalog.HealthStatusType, fmt.Sprintf("check-%s-%d", workload.Name, idx)). - WithData(suite.T(), &pbcatalog.HealthStatus{Type: "tcp", Status: health}). - WithTenancy(tenancy). - WithOwner(workload). - Write(suite.T(), suite.client) - } - } -} - -func (suite *getWorkloadHealthTestSuite) TestListError() { - // This test's goal is to exercise the error propgataion behavior within - // getWorkloadHealth. When the resource listing fails, we want to - // propagate the error which should eventually result in retrying - // the operation. - suite.controllerSuite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - health, err := getWorkloadHealth(context.Background(), suite.runtime, resourceID(fakeType, "foo", tenancy)) - - require.Error(suite.T(), err) - require.Equal(suite.T(), codes.InvalidArgument, status.Code(err)) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_CRITICAL, health) - }) -} - -func (suite *getWorkloadHealthTestSuite) TestNoHealthStatuses() { - // This test's goal is to ensure that when no HealthStatuses are owned by the - // workload that the health is assumed to be passing. - suite.controllerSuite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - workload := resourcetest.Resource(pbcatalog.WorkloadType, "foo"). - WithData(suite.T(), workloadData("")). - WithTenancy(tenancy). - Write(suite.T(), suite.client) - - health, err := getWorkloadHealth(context.Background(), suite.runtime, workload.Id) - require.NoError(suite.T(), err) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_PASSING, health) - }) -} - -func (suite *getWorkloadHealthTestSuite) TestWithStatuses() { - // This test's goal is to ensure that the health calculation given multiple - // statuses results in the most precedent winning. The addHealthStatuses - // helper method is used to inject multiple statuses in a way such that - // the resource service will return them in a predictable order and can - // properly exercise the code. - suite.controllerSuite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - for value, status := range pbcatalog.Health_name { - health := pbcatalog.Health(value) - if health == pbcatalog.Health_HEALTH_ANY { - continue - } - - suite.Run(status, func() { - workload := resourcetest.Resource(pbcatalog.WorkloadType, "foo"). - WithData(suite.T(), workloadData("")). - WithTenancy(tenancy). - Write(suite.T(), suite.client) - - suite.addHealthStatuses(workload.Id, tenancy, health) - - actualHealth, err := getWorkloadHealth(context.Background(), suite.runtime, workload.Id) - require.NoError(suite.T(), err) - require.Equal(suite.T(), health, actualHealth) - }) - } - }) -} - -func TestGetWorkloadHealth(t *testing.T) { - suite.Run(t, new(getWorkloadHealthTestSuite)) -} - -type getNodeHealthTestSuite struct { - controllerSuite -} - -func (suite *getNodeHealthTestSuite) TestNotfound() { - // This test's goal is to ensure that getNodeHealth when called with a node id that isn't - // present in the system results in a the critical health but no error. This situation - // could occur when a linked node gets removed without the workloads being modified/removed. - // When that occurs we want to steer traffic away from the linked node as soon as possible. - suite.controllerSuite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - health, err := getNodeHealth(context.Background(), suite.runtime, resourceID(pbcatalog.NodeType, "not-found", tenancy)) - require.NoError(suite.T(), err) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_CRITICAL, health) - }) -} - -func (suite *getNodeHealthTestSuite) TestReadError() { - // This test's goal is to ensure the getNodeHealth propagates unexpected errors from - // its resource read call back to the caller. - suite.controllerSuite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - health, err := getNodeHealth(context.Background(), suite.runtime, resourceID(fakeType, "not-found", tenancy)) - require.Error(suite.T(), err) - require.Equal(suite.T(), codes.InvalidArgument, status.Code(err)) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_CRITICAL, health) - }) -} - -func (suite *getNodeHealthTestSuite) TestUnreconciled() { - // This test's goal is to ensure that nodes with unreconciled health are deemed - // critical. Basically, the workload health controller should defer calculating - // the workload health until the associated nodes health is known. - suite.controllerSuite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - node := resourcetest.Resource(pbcatalog.NodeType, "unreconciled"). - WithData(suite.T(), nodeData). - WithTenancy(tenancy). - Write(suite.T(), suite.client). - GetId() - - health, err := getNodeHealth(context.Background(), suite.runtime, node) - require.Error(suite.T(), err) - require.Equal(suite.T(), errNodeUnreconciled, err) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_CRITICAL, health) - }) -} - -func (suite *getNodeHealthTestSuite) TestNoConditions() { - // This test's goal is to ensure that if a node's health status doesn't have - // the expected condition then its deemed critical. This should never happen - // in the integrated system as the node health controller would have to be - // buggy to add an empty status. However it could also indicate some breaking - // change went in. Regardless, the code to handle this state is written - // and it will be tested here. - suite.controllerSuite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - node := resourcetest.Resource(pbcatalog.NodeType, "no-conditions"). - WithData(suite.T(), nodeData). - WithTenancy(tenancy). - WithStatus(nodehealth.StatusKey, &pbresource.Status{}). - Write(suite.T(), suite.client). - GetId() - - health, err := getNodeHealth(context.Background(), suite.runtime, node) - require.Error(suite.T(), err) - require.Equal(suite.T(), errNodeHealthConditionNotFound, err) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_CRITICAL, health) - }) -} - -func (suite *getNodeHealthTestSuite) TestInvalidReason() { - // This test has the same goal as TestNoConditions which is to ensure that if - // the node health status isn't properly formed then we assume it is unhealthy. - // Just like that other test, it should be impossible for the normal running - // system to actually get into this state or at least for the node-health - // controller to put it into this state. As users or other controllers could - // potentially force it into this state by writing the status themselves, it - // would be good to ensure the defined behavior works as expected. - suite.controllerSuite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - node := resourcetest.Resource(pbcatalog.NodeType, "invalid-reason"). - WithData(suite.T(), nodeData). - WithTenancy(tenancy). - WithStatus(nodehealth.StatusKey, &pbresource.Status{ - Conditions: []*pbresource.Condition{ - { - Type: nodehealth.StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: "INVALID_REASON", - }, - }, - }). - Write(suite.T(), suite.client). - GetId() - - health, err := getNodeHealth(context.Background(), suite.runtime, node) - require.Error(suite.T(), err) - require.Equal(suite.T(), errNodeHealthInvalid, err) - require.Equal(suite.T(), pbcatalog.Health_HEALTH_CRITICAL, health) - }) -} - -func (suite *getNodeHealthTestSuite) TestValidHealth() { - // This test aims to ensure that all status that would be reported by the node-health - // controller gets accurately detected and returned by the getNodeHealth function. - suite.controllerSuite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { - for value, healthStr := range pbcatalog.Health_name { - health := pbcatalog.Health(value) - - // this is not a valid health that a health status - // may be in. - if health == pbcatalog.Health_HEALTH_ANY { - continue - } - - suite.T().Run(healthStr, func(t *testing.T) { - node := suite.injectNodeWithStatus("test-node", health, tenancy) - - actualHealth, err := getNodeHealth(context.Background(), suite.runtime, node.Id) - require.NoError(t, err) - require.Equal(t, health, actualHealth) - }) - } - }) -} - -func TestGetNodeHealth(t *testing.T) { - suite.Run(t, new(getNodeHealthTestSuite)) -} - -func (suite *controllerSuite) runTestCaseWithTenancies(testFunc func(*pbresource.Tenancy)) { - for _, tenancy := range suite.tenancies { - suite.Run(suite.appendTenancyInfo(tenancy), func() { - testFunc(tenancy) - }) - } -} - -func (suite *controllerSuite) appendTenancyInfo(tenancy *pbresource.Tenancy) string { - return fmt.Sprintf("%s_Namespace_%s_Partition", tenancy.Namespace, tenancy.Partition) -} diff --git a/internal/catalog/internal/controllers/workloadhealth/status.go b/internal/catalog/internal/controllers/workloadhealth/status.go deleted file mode 100644 index 133bd4cec989..000000000000 --- a/internal/catalog/internal/controllers/workloadhealth/status.go +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package workloadhealth - -import ( - "github.com/hashicorp/consul/internal/catalog/internal/controllers/nodehealth" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - StatusKey = "consul.io/workload-health" - StatusConditionHealthy = "healthy" - - NodeAndWorkloadHealthyMessage = "All workload and associated node health checks are passing" - WorkloadHealthyMessage = "All workload health checks are passing" - NodeAndWorkloadUnhealthyMessage = "One or more workload and node health checks are not passing" - WorkloadUnhealthyMessage = "One or more workload health checks are not passing" -) - -var ( - ConditionWorkloadPassing = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_TRUE, - Reason: pbcatalog.Health_HEALTH_PASSING.String(), - Message: WorkloadHealthyMessage, - } - - ConditionWorkloadWarning = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: pbcatalog.Health_HEALTH_WARNING.String(), - Message: WorkloadUnhealthyMessage, - } - - ConditionWorkloadCritical = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: pbcatalog.Health_HEALTH_CRITICAL.String(), - Message: WorkloadUnhealthyMessage, - } - - ConditionWorkloadMaintenance = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: pbcatalog.Health_HEALTH_MAINTENANCE.String(), - Message: WorkloadUnhealthyMessage, - } - - ConditionNodeAndWorkloadPassing = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_TRUE, - Reason: pbcatalog.Health_HEALTH_PASSING.String(), - Message: NodeAndWorkloadHealthyMessage, - } - - ConditionNodeAndWorkloadWarning = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: pbcatalog.Health_HEALTH_WARNING.String(), - Message: NodeAndWorkloadUnhealthyMessage, - } - - ConditionNodeAndWorkloadCritical = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: pbcatalog.Health_HEALTH_CRITICAL.String(), - Message: NodeAndWorkloadUnhealthyMessage, - } - - ConditionNodeAndWorkloadMaintenance = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: pbcatalog.Health_HEALTH_MAINTENANCE.String(), - Message: NodeAndWorkloadUnhealthyMessage, - } - - ConditionNodeWarning = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: pbcatalog.Health_HEALTH_WARNING.String(), - Message: nodehealth.NodeUnhealthyMessage, - } - - ConditionNodeCritical = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: pbcatalog.Health_HEALTH_CRITICAL.String(), - Message: nodehealth.NodeUnhealthyMessage, - } - - ConditionNodeMaintenance = &pbresource.Condition{ - Type: StatusConditionHealthy, - State: pbresource.Condition_STATE_FALSE, - Reason: pbcatalog.Health_HEALTH_MAINTENANCE.String(), - Message: nodehealth.NodeUnhealthyMessage, - } - - // WorkloadConditions is a map of the workloadhealth to the status condition - // used to represent that health. - WorkloadConditions = map[pbcatalog.Health]*pbresource.Condition{ - pbcatalog.Health_HEALTH_PASSING: ConditionWorkloadPassing, - pbcatalog.Health_HEALTH_WARNING: ConditionWorkloadWarning, - pbcatalog.Health_HEALTH_CRITICAL: ConditionWorkloadCritical, - pbcatalog.Health_HEALTH_MAINTENANCE: ConditionWorkloadMaintenance, - } - - // NodeAndWorkloadConditions is a map whose ultimate values are the status conditions - // used to represent the combined health of a workload and its associated node. - // The outer map's keys are the workloads health and the inner maps keys are the nodes - // health - NodeAndWorkloadConditions = map[pbcatalog.Health]map[pbcatalog.Health]*pbresource.Condition{ - pbcatalog.Health_HEALTH_PASSING: { - pbcatalog.Health_HEALTH_PASSING: ConditionNodeAndWorkloadPassing, - pbcatalog.Health_HEALTH_WARNING: ConditionNodeWarning, - pbcatalog.Health_HEALTH_CRITICAL: ConditionNodeCritical, - pbcatalog.Health_HEALTH_MAINTENANCE: ConditionNodeMaintenance, - }, - pbcatalog.Health_HEALTH_WARNING: { - pbcatalog.Health_HEALTH_PASSING: ConditionWorkloadWarning, - pbcatalog.Health_HEALTH_WARNING: ConditionNodeAndWorkloadWarning, - pbcatalog.Health_HEALTH_CRITICAL: ConditionNodeAndWorkloadCritical, - pbcatalog.Health_HEALTH_MAINTENANCE: ConditionNodeAndWorkloadMaintenance, - }, - pbcatalog.Health_HEALTH_CRITICAL: { - pbcatalog.Health_HEALTH_PASSING: ConditionWorkloadCritical, - pbcatalog.Health_HEALTH_WARNING: ConditionNodeAndWorkloadCritical, - pbcatalog.Health_HEALTH_CRITICAL: ConditionNodeAndWorkloadCritical, - pbcatalog.Health_HEALTH_MAINTENANCE: ConditionNodeAndWorkloadMaintenance, - }, - pbcatalog.Health_HEALTH_MAINTENANCE: { - pbcatalog.Health_HEALTH_PASSING: ConditionWorkloadMaintenance, - pbcatalog.Health_HEALTH_WARNING: ConditionNodeAndWorkloadMaintenance, - pbcatalog.Health_HEALTH_CRITICAL: ConditionNodeAndWorkloadMaintenance, - pbcatalog.Health_HEALTH_MAINTENANCE: ConditionNodeAndWorkloadMaintenance, - }, - } -) diff --git a/internal/catalog/internal/mappers/failovermapper/failover_mapper.go b/internal/catalog/internal/mappers/failovermapper/failover_mapper.go deleted file mode 100644 index 7cd40b47b453..000000000000 --- a/internal/catalog/internal/mappers/failovermapper/failover_mapper.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package failovermapper - -import ( - "context" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// Mapper tracks the relationship between a FailoverPolicy an a Service it -// references whether due to name-alignment or from a reference in a -// FailoverDestination leg. -type Mapper struct { - b *bimapper.Mapper -} - -// New creates a new Mapper. -func New() *Mapper { - return &Mapper{ - b: bimapper.New(pbcatalog.FailoverPolicyType, pbcatalog.ServiceType), - } -} - -// TrackFailover extracts all Service references from the provided -// FailoverPolicy and indexes them so that MapService can turn Service events -// into FailoverPolicy events properly. -func (m *Mapper) TrackFailover(failover *resource.DecodedResource[*pbcatalog.FailoverPolicy]) { - destRefs := failover.Data.GetUnderlyingDestinationRefs() - destRefs = append(destRefs, &pbresource.Reference{ - Type: pbcatalog.ServiceType, - Tenancy: failover.Resource.Id.Tenancy, - Name: failover.Resource.Id.Name, - }) - m.trackFailover(failover.Resource.Id, destRefs) -} - -func (m *Mapper) trackFailover(failover *pbresource.ID, services []*pbresource.Reference) { - var servicesAsIDsOrRefs []resource.ReferenceOrID - for _, s := range services { - servicesAsIDsOrRefs = append(servicesAsIDsOrRefs, s) - } - m.b.TrackItem(failover, servicesAsIDsOrRefs) -} - -// UntrackFailover forgets the links inserted by TrackFailover for the provided -// FailoverPolicyID. -func (m *Mapper) UntrackFailover(failoverID *pbresource.ID) { - m.b.UntrackItem(failoverID) -} - -func (m *Mapper) MapService(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - return m.b.MapLink(ctx, rt, res) -} - -func (m *Mapper) FailoverIDsByService(svcID *pbresource.ID) []*pbresource.ID { - return m.b.ItemsForLink(svcID) -} diff --git a/internal/catalog/internal/mappers/failovermapper/failover_mapper_test.go b/internal/catalog/internal/mappers/failovermapper/failover_mapper_test.go deleted file mode 100644 index 6149fddbf261..000000000000 --- a/internal/catalog/internal/mappers/failovermapper/failover_mapper_test.go +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package failovermapper - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/catalog/internal/types" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestMapper_Tracking(t *testing.T) { - registry := resource.NewRegistry() - types.Register(registry) - - // Create an advance pointer to some services. - randoSvc := rtest.Resource(pbcatalog.ServiceType, "rando"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbcatalog.Service{}). - Build() - rtest.ValidateAndNormalize(t, registry, randoSvc) - - apiSvc := rtest.Resource(pbcatalog.ServiceType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbcatalog.Service{}). - Build() - rtest.ValidateAndNormalize(t, registry, apiSvc) - - fooSvc := rtest.Resource(pbcatalog.ServiceType, "foo"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbcatalog.Service{}). - Build() - rtest.ValidateAndNormalize(t, registry, fooSvc) - - barSvc := rtest.Resource(pbcatalog.ServiceType, "bar"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbcatalog.Service{}). - Build() - rtest.ValidateAndNormalize(t, registry, barSvc) - - wwwSvc := rtest.Resource(pbcatalog.ServiceType, "www"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbcatalog.Service{}). - Build() - rtest.ValidateAndNormalize(t, registry, wwwSvc) - - fail1 := rtest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "foo")}, - {Ref: newRef(pbcatalog.ServiceType, "bar")}, - }, - }, - }). - Build() - rtest.ValidateAndNormalize(t, registry, fail1) - failDec1 := rtest.MustDecode[*pbcatalog.FailoverPolicy](t, fail1) - - fail2 := rtest.Resource(pbcatalog.FailoverPolicyType, "www"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "www"), Datacenter: "dc2"}, - {Ref: newRef(pbcatalog.ServiceType, "foo")}, - }, - }, - }). - Build() - rtest.ValidateAndNormalize(t, registry, fail2) - failDec2 := rtest.MustDecode[*pbcatalog.FailoverPolicy](t, fail2) - - fail1_updated := rtest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "bar")}, - }, - }, - }). - Build() - rtest.ValidateAndNormalize(t, registry, fail1_updated) - failDec1_updated := rtest.MustDecode[*pbcatalog.FailoverPolicy](t, fail1_updated) - - m := New() - - // Nothing tracked yet so we assume nothing. - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc) - requireServicesTracked(t, m, fooSvc) - requireServicesTracked(t, m, barSvc) - requireServicesTracked(t, m, wwwSvc) - - // no-ops - m.UntrackFailover(fail1.Id) - - // still nothing - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc) - requireServicesTracked(t, m, fooSvc) - requireServicesTracked(t, m, barSvc) - requireServicesTracked(t, m, wwwSvc) - - // Actually insert some data. - m.TrackFailover(failDec1) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc, fail1.Id) - requireServicesTracked(t, m, fooSvc, fail1.Id) - requireServicesTracked(t, m, barSvc, fail1.Id) - requireServicesTracked(t, m, wwwSvc) - - // track it again, no change - m.TrackFailover(failDec1) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc, fail1.Id) - requireServicesTracked(t, m, fooSvc, fail1.Id) - requireServicesTracked(t, m, barSvc, fail1.Id) - requireServicesTracked(t, m, wwwSvc) - - // track new one that overlaps slightly - m.TrackFailover(failDec2) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc, fail1.Id) - requireServicesTracked(t, m, fooSvc, fail1.Id, fail2.Id) - requireServicesTracked(t, m, barSvc, fail1.Id) - requireServicesTracked(t, m, wwwSvc, fail2.Id) - - // update the original to change it - m.TrackFailover(failDec1_updated) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc, fail1.Id) - requireServicesTracked(t, m, fooSvc, fail2.Id) - requireServicesTracked(t, m, barSvc, fail1.Id) - requireServicesTracked(t, m, wwwSvc, fail2.Id) - - // delete the original - m.UntrackFailover(fail1.Id) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc) - requireServicesTracked(t, m, fooSvc, fail2.Id) - requireServicesTracked(t, m, barSvc) - requireServicesTracked(t, m, wwwSvc, fail2.Id) - - // delete the other one - m.UntrackFailover(fail2.Id) - - requireServicesTracked(t, m, randoSvc) - requireServicesTracked(t, m, apiSvc) - requireServicesTracked(t, m, fooSvc) - requireServicesTracked(t, m, barSvc) - requireServicesTracked(t, m, wwwSvc) -} - -func requireServicesTracked(t *testing.T, mapper *Mapper, svc *pbresource.Resource, failovers ...*pbresource.ID) { - t.Helper() - - reqs, err := mapper.MapService( - context.Background(), - controller.Runtime{}, - svc, - ) - require.NoError(t, err) - - require.Len(t, reqs, len(failovers)) - - for _, failover := range failovers { - prototest.AssertContainsElement(t, reqs, controller.Request{ID: failover}) - } -} - -func newRef(typ *pbresource.Type, name string) *pbresource.Reference { - return rtest.Resource(typ, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - Reference("") -} diff --git a/internal/catalog/internal/mappers/nodemapper/node_mapper.go b/internal/catalog/internal/mappers/nodemapper/node_mapper.go deleted file mode 100644 index 9c17478d7639..000000000000 --- a/internal/catalog/internal/mappers/nodemapper/node_mapper.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package nodemapper - -import ( - "context" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type NodeMapper struct { - b *bimapper.Mapper -} - -func New() *NodeMapper { - return &NodeMapper{ - b: bimapper.New(pbcatalog.WorkloadType, pbcatalog.NodeType), - } -} - -// NodeIDFromWorkload will create a resource ID referencing the Node type with the same tenancy as -// the workload and with the name populated from the workloads NodeName field. -func (m *NodeMapper) NodeIDFromWorkload(workload *pbresource.Resource, workloadData *pbcatalog.Workload) *pbresource.ID { - return &pbresource.ID{ - Type: pbcatalog.NodeType, - Tenancy: workload.Id.Tenancy, - Name: workloadData.NodeName, - } -} - -// MapNodeToWorkloads will take a Node resource and return controller requests -// for all Workloads associated with the Node. -func (m *NodeMapper) MapNodeToWorkloads(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - ids := m.b.ItemIDsForLink(res.Id) - return controller.MakeRequests(pbcatalog.WorkloadType, ids), nil -} - -// TrackWorkload instructs the NodeMapper to associate the given workload -// ID with the given node ID. -func (m *NodeMapper) TrackWorkload(workloadID *pbresource.ID, nodeID *pbresource.ID) { - m.b.TrackItem(workloadID, []resource.ReferenceOrID{ - nodeID, - }) -} - -// UntrackWorkload will cause the node mapper to forget about the specified -// workload if it is currently tracking it. -func (m *NodeMapper) UntrackWorkload(workloadID *pbresource.ID) { - m.b.UntrackItem(workloadID) -} diff --git a/internal/catalog/internal/mappers/nodemapper/node_mapper_test.go b/internal/catalog/internal/mappers/nodemapper/node_mapper_test.go deleted file mode 100644 index fda260361fe8..000000000000 --- a/internal/catalog/internal/mappers/nodemapper/node_mapper_test.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package nodemapper - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestNodeMapper_NodeIDFromWorkload(t *testing.T) { - mapper := New() - - data := &pbcatalog.Workload{ - NodeName: "test-node", - // the other fields should be irrelevant - } - - workload := resourcetest.Resource(pbcatalog.WorkloadType, "test-workload"). - WithData(t, data).Build() - - actual := mapper.NodeIDFromWorkload(workload, data) - expected := &pbresource.ID{ - Type: pbcatalog.NodeType, - Tenancy: workload.Id.Tenancy, - Name: "test-node", - } - - prototest.AssertDeepEqual(t, expected, actual) -} - -func requireWorkloadsTracked(t *testing.T, mapper *NodeMapper, node *pbresource.Resource, workloads ...*pbresource.ID) { - t.Helper() - reqs, err := mapper.MapNodeToWorkloads( - context.Background(), - controller.Runtime{}, - node) - - require.NoError(t, err) - require.Len(t, reqs, len(workloads)) - for _, workload := range workloads { - prototest.AssertContainsElement(t, reqs, controller.Request{ID: workload}) - } -} - -func TestNodeMapper_WorkloadTracking(t *testing.T) { - mapper := New() - - node1 := resourcetest.Resource(pbcatalog.NodeType, "node1"). - WithData(t, &pbcatalog.Node{Addresses: []*pbcatalog.NodeAddress{{Host: "198.18.0.1"}}}). - Build() - - node2 := resourcetest.Resource(pbcatalog.NodeType, "node2"). - WithData(t, &pbcatalog.Node{Addresses: []*pbcatalog.NodeAddress{{Host: "198.18.0.2"}}}). - Build() - - tenant := &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - } - - workload1 := &pbresource.ID{Type: pbcatalog.WorkloadType, Tenancy: tenant, Name: "workload1"} - workload2 := &pbresource.ID{Type: pbcatalog.WorkloadType, Tenancy: tenant, Name: "workload2"} - workload3 := &pbresource.ID{Type: pbcatalog.WorkloadType, Tenancy: tenant, Name: "workload3"} - workload4 := &pbresource.ID{Type: pbcatalog.WorkloadType, Tenancy: tenant, Name: "workload4"} - workload5 := &pbresource.ID{Type: pbcatalog.WorkloadType, Tenancy: tenant, Name: "workload5"} - - // No Workloads have been tracked so the mapper should return empty lists - requireWorkloadsTracked(t, mapper, node1) - requireWorkloadsTracked(t, mapper, node2) - // As nothing is tracked these should be pretty much no-ops - mapper.UntrackWorkload(workload1) - mapper.UntrackWorkload(workload2) - mapper.UntrackWorkload(workload2) - mapper.UntrackWorkload(workload3) - mapper.UntrackWorkload(workload4) - mapper.UntrackWorkload(workload5) - - // Now track some workloads - mapper.TrackWorkload(workload1, node1.Id) - mapper.TrackWorkload(workload2, node1.Id) - mapper.TrackWorkload(workload3, node2.Id) - mapper.TrackWorkload(workload4, node2.Id) - - // Mapping should now return 2 workload requests for each node - requireWorkloadsTracked(t, mapper, node1, workload1, workload2) - requireWorkloadsTracked(t, mapper, node2, workload3, workload4) - - // Track the same workloads again, this should end up being mostly a no-op - mapper.TrackWorkload(workload1, node1.Id) - mapper.TrackWorkload(workload2, node1.Id) - mapper.TrackWorkload(workload3, node2.Id) - mapper.TrackWorkload(workload4, node2.Id) - - // Mappings should be unchanged from the initial workload tracking - requireWorkloadsTracked(t, mapper, node1, workload1, workload2) - requireWorkloadsTracked(t, mapper, node2, workload3, workload4) - - // Change the workload association for workload2 - mapper.TrackWorkload(workload2, node2.Id) - - // Node1 should now track just the single workload and node2 should track 3 - requireWorkloadsTracked(t, mapper, node1, workload1) - requireWorkloadsTracked(t, mapper, node2, workload2, workload3, workload4) - - // Untrack the workloads - this is done in very specific ordering to ensure all - // the workload tracking removal paths get hit. This does assume that the ordering - // of requests is stable between removals. - - // remove the one and only workload from a node - mapper.UntrackWorkload(workload1) - requireWorkloadsTracked(t, mapper, node1) - - // track an additional workload - mapper.TrackWorkload(workload5, node2.Id) - reqs, err := mapper.MapNodeToWorkloads(context.Background(), controller.Runtime{}, node2) - require.NoError(t, err) - require.Len(t, reqs, 4) - - first := reqs[0].ID - second := reqs[1].ID - third := reqs[2].ID - fourth := reqs[3].ID - - // remove from the middle of the request list - mapper.UntrackWorkload(second) - requireWorkloadsTracked(t, mapper, node2, first, third, fourth) - - // remove from the end of the list - mapper.UntrackWorkload(fourth) - requireWorkloadsTracked(t, mapper, node2, first, third) - - // remove from the beginning of the list - mapper.UntrackWorkload(first) - requireWorkloadsTracked(t, mapper, node2, third) - - // remove the last element - mapper.UntrackWorkload(third) - requireWorkloadsTracked(t, mapper, node2) -} diff --git a/internal/catalog/internal/testhelpers/acl_hooks_test_helpers.go b/internal/catalog/internal/testhelpers/acl_hooks_test_helpers.go deleted file mode 100644 index 17796a85c59a..000000000000 --- a/internal/catalog/internal/testhelpers/acl_hooks_test_helpers.go +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package testhelpers - -import ( - "testing" - - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// WorkloadSelecting denotes a resource type that uses workload selectors. -type WorkloadSelecting interface { - proto.Message - GetWorkloads() *pbcatalog.WorkloadSelector -} - -func RunWorkloadSelectingTypeACLsTests[T WorkloadSelecting](t *testing.T, typ *pbresource.Type, - getData func(selector *pbcatalog.WorkloadSelector) T, - registerFunc func(registry resource.Registry), -) { - // Wire up a registry to generically invoke hooks - registry := resource.NewRegistry() - registerFunc(registry) - - cases := map[string]resourcetest.ACLTestCase{ - "no rules": { - Rules: ``, - Data: getData(&pbcatalog.WorkloadSelector{Names: []string{"workload"}}), - Typ: typ, - ReadOK: resourcetest.DENY, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "service test read": { - Rules: `service "test" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{Names: []string{"workload"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "service test write with named selectors and insufficient policy": { - Rules: `service "test" { policy = "write" }`, - Data: getData(&pbcatalog.WorkloadSelector{Names: []string{"workload"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "service test write with prefixed selectors and insufficient policy": { - Rules: `service "test" { policy = "write" }`, - Data: getData(&pbcatalog.WorkloadSelector{Prefixes: []string{"workload"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "service test write with named selectors": { - Rules: `service "test" { policy = "write" } service "workload" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{Names: []string{"workload"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.ALLOW, - ListOK: resourcetest.DEFAULT, - }, - "service test write with multiple named selectors": { - Rules: `service "test" { policy = "write" } service "workload1" { policy = "read" } service "workload2" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{Names: []string{"workload1", "workload2"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.ALLOW, - ListOK: resourcetest.DEFAULT, - }, - "service test write with multiple named selectors and insufficient policy": { - Rules: `service "test" { policy = "write" } service "workload1" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{Names: []string{"workload1", "workload2"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "service test write with multiple named selectors and prefixed policy": { - Rules: `service "test" { policy = "write" } service_prefix "workload" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{Names: []string{"workload1", "workload2"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.ALLOW, - ListOK: resourcetest.DEFAULT, - }, - "service test write with prefixed selectors": { - Rules: `service "test" { policy = "write" } service_prefix "workload-" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{Prefixes: []string{"workload-"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.ALLOW, - ListOK: resourcetest.DEFAULT, - }, - "service test write with prefixed selectors and a policy with more specific prefix than the selector": { - Rules: `service "test" { policy = "write" } service_prefix "workload-" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{Prefixes: []string{"wor"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - - "service test write with prefixed selectors and a policy with less specific prefix than the selector": { - Rules: `service "test" { policy = "write" } service_prefix "wor" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{Prefixes: []string{"workload-"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.ALLOW, - ListOK: resourcetest.DEFAULT, - }, - // Prefix-based selectors should not allow writes when a policy only allows - // to read a specific service from that selector. - "service test write with prefixed selectors and a policy with a specific service": { - Rules: `service "test" { policy = "write" } service "workload" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{Prefixes: []string{"workload"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "service test write with multiple prefixed selectors": { - Rules: `service "test" { policy = "write" } service_prefix "workload" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{Prefixes: []string{"workload-1", "workload-2"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.ALLOW, - ListOK: resourcetest.DEFAULT, - }, - "service test write with multiple prefixed selectors and insufficient policy": { - Rules: `service "test" { policy = "write" } service_prefix "workload-1" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{Prefixes: []string{"workload-1", "workload-2"}}), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "service test write with a mix of named and prefixed selectors and insufficient policy": { - Rules: `service "test" { policy = "write" } service_prefix "workload" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{ - Prefixes: []string{"workload-1", "workload-2"}, - Names: []string{"other-1", "other-2"}, - }), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "service test write with a mix of named and prefixed selectors and prefixed policy": { - Rules: `service "test" { policy = "write" } service_prefix "workload" { policy = "read" } service_prefix "other" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{ - Prefixes: []string{"workload-1", "workload-2"}, - Names: []string{"other-1", "other-2"}, - }), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.ALLOW, - ListOK: resourcetest.DEFAULT, - }, - "service test write with a mix of named and prefixed selectors and both prefixed and specific policy": { - Rules: `service "test" { policy = "write" } service_prefix "workload" { policy = "read" } service "other-1" { policy = "read" } service "other-2" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{ - Prefixes: []string{"workload-1", "workload-2"}, - Names: []string{"other-1", "other-2"}, - }), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.ALLOW, - ListOK: resourcetest.DEFAULT, - }, - "service test write with a mix of named and prefixed selectors and wildcard service read policy": { - Rules: `service "test" { policy = "write" } service_prefix "" { policy = "read" }`, - Data: getData(&pbcatalog.WorkloadSelector{ - Prefixes: []string{"workload-1", "workload-2"}, - Names: []string{"other-1", "other-2"}, - }), - Typ: typ, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.ALLOW, - ListOK: resourcetest.DEFAULT, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - resourcetest.RunACLTestCase(t, tc, registry) - }) - } -} diff --git a/internal/catalog/internal/types/acl_hooks.go b/internal/catalog/internal/types/acl_hooks.go deleted file mode 100644 index d9ddcb8e93cc..000000000000 --- a/internal/catalog/internal/types/acl_hooks.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func aclReadHookResourceWithWorkloadSelector(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID, _ *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().ServiceReadAllowed(id.GetName(), authzContext) -} - -func aclWriteHookResourceWithWorkloadSelector[T WorkloadSelecting](authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, r *resource.DecodedResource[T]) error { - // First check service:write on the name. - err := authorizer.ToAllowAuthorizer().ServiceWriteAllowed(r.GetId().GetName(), authzContext) - if err != nil { - return err - } - - // Then also check whether we're allowed to select a service. - for _, name := range r.Data.GetWorkloads().GetNames() { - err = authorizer.ToAllowAuthorizer().ServiceReadAllowed(name, authzContext) - if err != nil { - return err - } - } - - for _, prefix := range r.Data.GetWorkloads().GetPrefixes() { - err = authorizer.ToAllowAuthorizer().ServiceReadPrefixAllowed(prefix, authzContext) - if err != nil { - return err - } - } - - return nil -} - -func ACLHooksForWorkloadSelectingType[T WorkloadSelecting]() *resource.ACLHooks { - return &resource.ACLHooks{ - Read: aclReadHookResourceWithWorkloadSelector, - Write: resource.DecodeAndAuthorizeWrite(aclWriteHookResourceWithWorkloadSelector[T]), - List: resource.NoOpACLListHook, - } -} diff --git a/internal/catalog/internal/types/dns_policy.go b/internal/catalog/internal/types/dns_policy.go deleted file mode 100644 index 91dd2615455c..000000000000 --- a/internal/catalog/internal/types/dns_policy.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "math" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" -) - -type DecodedDNSPolicy = resource.DecodedResource[*pbcatalog.DNSPolicy] - -func RegisterDNSPolicy(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbcatalog.DNSPolicyType, - Proto: &pbcatalog.DNSPolicy{}, - Scope: resource.ScopeNamespace, - Validate: ValidateDNSPolicy, - ACLs: ACLHooksForWorkloadSelectingType[*pbcatalog.DNSPolicy](), - }) -} - -var ValidateDNSPolicy = resource.DecodeAndValidate(validateDNSPolicy) - -func validateDNSPolicy(res *DecodedDNSPolicy) error { - var err error - // Ensure that this resource isn't useless and is attempting to - // select at least one workload. - if selErr := ValidateSelector(res.Data.Workloads, false); selErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "workloads", - Wrapped: selErr, - }) - } - - // Validate the weights - if weightErr := validateDNSPolicyWeights(res.Data.Weights); weightErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "weights", - Wrapped: weightErr, - }) - } - - return err -} - -func validateDNSPolicyWeights(weights *pbcatalog.Weights) error { - // Non nil weights are required - if weights == nil { - return resource.ErrMissing - } - - var err error - if weights.Passing < 1 || weights.Passing > math.MaxUint16 { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "passing", - Wrapped: errDNSPassingWeightOutOfRange, - }) - } - - // Each weight is an unsigned integer so we don't need to - // check for negative weights. - if weights.Warning > math.MaxUint16 { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "warning", - Wrapped: errDNSWarningWeightOutOfRange, - }) - } - - return err -} diff --git a/internal/catalog/internal/types/dns_policy_test.go b/internal/catalog/internal/types/dns_policy_test.go deleted file mode 100644 index 1303d2878cf7..000000000000 --- a/internal/catalog/internal/types/dns_policy_test.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/catalog/internal/testhelpers" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func createDNSPolicyResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { - res := &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.DNSPolicyType, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: "test-policy", - }, - } - - var err error - res.Data, err = anypb.New(data) - require.NoError(t, err) - return res -} - -func TestValidateDNSPolicy_Ok(t *testing.T) { - data := &pbcatalog.DNSPolicy{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - Weights: &pbcatalog.Weights{ - Passing: 3, - Warning: 0, - }, - } - - res := createDNSPolicyResource(t, data) - - err := ValidateDNSPolicy(res) - require.NoError(t, err) -} - -func TestValidateDNSPolicy_ParseError(t *testing.T) { - // Any type other than the DNSPolicy type would work - // to cause the error we are expecting - data := &pbcatalog.IP{Address: "198.18.0.1"} - - res := createDNSPolicyResource(t, data) - - err := ValidateDNSPolicy(res) - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) -} - -func TestValidateDNSPolicy_MissingWeights(t *testing.T) { - data := &pbcatalog.DNSPolicy{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - } - - res := createDNSPolicyResource(t, data) - - err := ValidateDNSPolicy(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "weights", - Wrapped: resource.ErrMissing, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateDNSPolicy_InvalidPassingWeight(t *testing.T) { - for _, weight := range []uint32{0, 1000000} { - t.Run(fmt.Sprintf("%d", weight), func(t *testing.T) { - data := &pbcatalog.DNSPolicy{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - Weights: &pbcatalog.Weights{ - Passing: weight, - }, - } - - res := createDNSPolicyResource(t, data) - - err := ValidateDNSPolicy(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "passing", - Wrapped: errDNSPassingWeightOutOfRange, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, "weights", actual.Name) - err = actual.Unwrap() - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) - }) - } -} - -func TestValidateDNSPolicy_InvalidWarningWeight(t *testing.T) { - data := &pbcatalog.DNSPolicy{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - Weights: &pbcatalog.Weights{ - Passing: 1, - Warning: 1000000, - }, - } - - res := createDNSPolicyResource(t, data) - - err := ValidateDNSPolicy(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "warning", - Wrapped: errDNSWarningWeightOutOfRange, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, "weights", actual.Name) - err = actual.Unwrap() - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateDNSPolicy_EmptySelector(t *testing.T) { - data := &pbcatalog.DNSPolicy{ - Weights: &pbcatalog.Weights{ - Passing: 10, - Warning: 3, - }, - } - - res := createDNSPolicyResource(t, data) - - err := ValidateDNSPolicy(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "workloads", - Wrapped: resource.ErrEmpty, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestDNSPolicyACLs(t *testing.T) { - // Wire up a registry to generically invoke hooks - registry := resource.NewRegistry() - RegisterDNSPolicy(registry) - - testhelpers.RunWorkloadSelectingTypeACLsTests[*pbcatalog.DNSPolicy](t, pbcatalog.DNSPolicyType, - func(selector *pbcatalog.WorkloadSelector) *pbcatalog.DNSPolicy { - return &pbcatalog.DNSPolicy{ - Workloads: selector, - Weights: &pbcatalog.Weights{Passing: 1, Warning: 0}, - } - }, - RegisterDNSPolicy, - ) -} diff --git a/internal/catalog/internal/types/errors.go b/internal/catalog/internal/types/errors.go deleted file mode 100644 index 3b331a9a6302..000000000000 --- a/internal/catalog/internal/types/errors.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" -) - -var ( - errNotDNSLabel = errors.New(fmt.Sprintf("value must match regex: %s", dnsLabelRegex)) - errNotIPAddress = errors.New("value is not a valid IP address") - errUnixSocketMultiport = errors.New("Unix socket address references more than one port") - errInvalidPhysicalPort = errors.New("port number is outside the range 1 to 65535") - errInvalidVirtualPort = errors.New("port number is outside the range 0 to 65535") - errDNSWarningWeightOutOfRange = errors.New("DNS warning weight is outside the range 0 to 65535") - errDNSPassingWeightOutOfRange = errors.New("DNS passing weight is outside of the range 1 to 65535") - errLocalityZoneNoRegion = errors.New("locality region cannot be empty if the zone is set") - errInvalidHealth = errors.New("health status must be one of: passing, warning, critical or maintenance") -) - -type errInvalidWorkloadHostFormat struct { - Host string -} - -func (err errInvalidWorkloadHostFormat) Error() string { - return fmt.Sprintf("%q is not an IP address, Unix socket path or a DNS name.", err.Host) -} - -type errInvalidNodeHostFormat struct { - Host string -} - -func (err errInvalidNodeHostFormat) Error() string { - return fmt.Sprintf("%q is not an IP address or a DNS name.", err.Host) -} - -type errInvalidPortReference struct { - Name string -} - -func (err errInvalidPortReference) Error() string { - return fmt.Sprintf("port with name %q has not been defined", err.Name) -} - -type errVirtualPortReused struct { - Index int - Value uint32 -} - -func (err errVirtualPortReused) Error() string { - return fmt.Sprintf("virtual port %d was previously assigned at index %d", err.Value, err.Index) -} - -type errTooMuchMesh struct { - Ports []string -} - -func (err errTooMuchMesh) Error() string { - return fmt.Sprintf("protocol \"mesh\" was specified in more than 1 port: %+v", err.Ports) -} - -type errInvalidEndpointsOwnerName struct { - Name string - OwnerName string -} - -func (err errInvalidEndpointsOwnerName) Error() string { - return fmt.Sprintf("invalid owner name %q. ServiceEndpoints objects must be owned by a Service with the same name: %q", err.OwnerName, err.Name) -} diff --git a/internal/catalog/internal/types/errors_test.go b/internal/catalog/internal/types/errors_test.go deleted file mode 100644 index 08f227166aa2..000000000000 --- a/internal/catalog/internal/types/errors_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "flag" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/require" -) - -// update allows golden files to be updated based on the current output. -var update = flag.Bool("update", false, "update golden files") - -func goldenError(t *testing.T, name string, actual string) { - t.Helper() - - fpath := filepath.Join("testdata", name+".golden") - - if *update { - require.NoError(t, os.WriteFile(fpath, []byte(actual), 0644)) - } else { - expected, err := os.ReadFile(fpath) - require.NoError(t, err) - require.Equal(t, string(expected), actual) - } -} - -func TestErrorStrings(t *testing.T) { - type testCase struct { - err error - expected string - } - - cases := map[string]error{ - "errInvalidWorkloadHostFormat": errInvalidWorkloadHostFormat{ - Host: "-foo-bar-", - }, - "errInvalidNodeHostFormat": errInvalidNodeHostFormat{ - Host: "unix:///node.sock", - }, - "errInvalidPortReference": errInvalidPortReference{ - Name: "http", - }, - "errVirtualPortReused": errVirtualPortReused{ - Index: 3, - Value: 8080, - }, - "errTooMuchMesh": errTooMuchMesh{ - Ports: []string{"http", "grpc"}, - }, - "errInvalidEndpointsOwnerName": errInvalidEndpointsOwnerName{ - Name: "foo", - OwnerName: "bar", - }, - "errNotDNSLabel": errNotDNSLabel, - "errNotIPAddress": errNotIPAddress, - "errUnixSocketMultiport": errUnixSocketMultiport, - "errInvalidPhysicalPort": errInvalidPhysicalPort, - "errInvalidVirtualPort": errInvalidVirtualPort, - "errDNSWarningWeightOutOfRange": errDNSWarningWeightOutOfRange, - "errDNSPassingWeightOutOfRange": errDNSPassingWeightOutOfRange, - "errLocalityZoneNoRegion": errLocalityZoneNoRegion, - } - - for name, err := range cases { - t.Run(name, func(t *testing.T) { - goldenError(t, name, err.Error()) - }) - } -} diff --git a/internal/catalog/internal/types/failover_policy.go b/internal/catalog/internal/types/failover_policy.go deleted file mode 100644 index 012150fc046d..000000000000 --- a/internal/catalog/internal/types/failover_policy.go +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "fmt" - - "github.com/hashicorp/go-multierror" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type DecodedFailoverPolicy = resource.DecodedResource[*pbcatalog.FailoverPolicy] - -func RegisterFailoverPolicy(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbcatalog.FailoverPolicyType, - Proto: &pbcatalog.FailoverPolicy{}, - Scope: resource.ScopeNamespace, - Mutate: MutateFailoverPolicy, - Validate: ValidateFailoverPolicy, - ACLs: &resource.ACLHooks{ - Read: aclReadHookFailoverPolicy, - Write: resource.DecodeAndAuthorizeWrite(aclWriteHookFailoverPolicy), - List: resource.NoOpACLListHook, - }, - }) -} - -var MutateFailoverPolicy = resource.DecodeAndMutate(mutateFailoverPolicy) - -func mutateFailoverPolicy(res *DecodedFailoverPolicy) (bool, error) { - changed := false - - // Handle eliding empty configs. - if res.Data.Config != nil && res.Data.Config.IsEmpty() { - res.Data.Config = nil - changed = true - } - - if res.Data.Config != nil { - if mutateFailoverConfig(res.Id.Tenancy, res.Data.Config) { - changed = true - } - } - - for port, pc := range res.Data.PortConfigs { - if pc.IsEmpty() { - delete(res.Data.PortConfigs, port) - changed = true - } else { - if mutateFailoverConfig(res.Id.Tenancy, pc) { - changed = true - } - } - } - if len(res.Data.PortConfigs) == 0 { - res.Data.PortConfigs = nil - changed = true - } - - return changed, nil -} - -func mutateFailoverConfig(policyTenancy *pbresource.Tenancy, config *pbcatalog.FailoverConfig) (changed bool) { - if policyTenancy != nil && !isLocalPeer(policyTenancy.PeerName) { - // TODO(peering/v2): remove this bypass when we know what to do with - // non-local peer references. - return false - } - - for _, dest := range config.Destinations { - if dest.Ref == nil { - continue - } - if dest.Ref.Tenancy != nil && !isLocalPeer(dest.Ref.Tenancy.PeerName) { - // TODO(peering/v2): remove this bypass when we know what to do with - // non-local peer references. - continue - } - - orig := proto.Clone(dest.Ref).(*pbresource.Reference) - resource.DefaultReferenceTenancy( - dest.Ref, - policyTenancy, - resource.DefaultNamespacedTenancy(), // Services are all namespace scoped. - ) - - if !proto.Equal(orig, dest.Ref) { - changed = true - } - } - - return changed -} - -func isLocalPeer(p string) bool { - return p == "local" || p == "" -} - -var ValidateFailoverPolicy = resource.DecodeAndValidate(validateFailoverPolicy) - -func validateFailoverPolicy(res *DecodedFailoverPolicy) error { - var merr error - - if res.Data.Config == nil && len(res.Data.PortConfigs) == 0 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "config", - Wrapped: fmt.Errorf("at least one of config or port_configs must be set"), - }) - } - - if res.Data.Config != nil { - wrapConfigErr := func(err error) error { - return resource.ErrInvalidField{ - Name: "config", - Wrapped: err, - } - } - if cfgErr := validateFailoverConfig(res.Data.Config, false, wrapConfigErr); cfgErr != nil { - merr = multierror.Append(merr, cfgErr) - } - } - - for portName, pc := range res.Data.PortConfigs { - wrapConfigErr := func(err error) error { - return resource.ErrInvalidMapValue{ - Map: "port_configs", - Key: portName, - Wrapped: err, - } - } - if portNameErr := ValidatePortName(portName); portNameErr != nil { - merr = multierror.Append(merr, resource.ErrInvalidMapKey{ - Map: "port_configs", - Key: portName, - Wrapped: portNameErr, - }) - } - - if cfgErr := validateFailoverConfig(pc, true, wrapConfigErr); cfgErr != nil { - merr = multierror.Append(merr, cfgErr) - } - - // TODO: should sameness group be a ref once that's a resource? - } - - return merr -} - -func validateFailoverConfig(config *pbcatalog.FailoverConfig, ported bool, wrapErr func(error) error) error { - var merr error - - if config.SamenessGroup != "" { - // TODO(v2): handle other forms of failover - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "sameness_group", - Wrapped: fmt.Errorf("not supported in this release"), - })) - } - - if len(config.Regions) > 0 { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "regions", - Wrapped: fmt.Errorf("not supported in this release"), - })) - } - - // TODO(peering/v2): remove this bypass when we know what to do with - - if (len(config.Destinations) > 0) == (config.SamenessGroup != "") { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "destinations", - Wrapped: fmt.Errorf("exactly one of destinations or sameness_group should be set"), - })) - } - for i, dest := range config.Destinations { - wrapDestErr := func(err error) error { - return wrapErr(resource.ErrInvalidListElement{ - Name: "destinations", - Index: i, - Wrapped: err, - }) - } - if destErr := validateFailoverPolicyDestination(dest, ported, wrapDestErr); destErr != nil { - merr = multierror.Append(merr, destErr) - } - } - - if config.Mode != pbcatalog.FailoverMode_FAILOVER_MODE_UNSPECIFIED { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "mode", - Wrapped: fmt.Errorf("not supported in this release"), - })) - } - - // TODO(v2): uncomment after this is supported - // switch config.Mode { - // case pbcatalog.FailoverMode_FAILOVER_MODE_UNSPECIFIED: - // // means pbcatalog.FailoverMode_FAILOVER_MODE_SEQUENTIAL - // case pbcatalog.FailoverMode_FAILOVER_MODE_SEQUENTIAL: - // case pbcatalog.FailoverMode_FAILOVER_MODE_ORDER_BY_LOCALITY: - // default: - // merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - // Name: "mode", - // Wrapped: fmt.Errorf("not a supported enum value: %v", config.Mode), - // })) - // } - - // TODO: validate sameness group requirements - - return merr -} - -func validateFailoverPolicyDestination(dest *pbcatalog.FailoverDestination, ported bool, wrapErr func(error) error) error { - var merr error - - wrapRefErr := func(err error) error { - return wrapErr(resource.ErrInvalidField{ - Name: "ref", - Wrapped: err, - }) - } - - if refErr := ValidateLocalServiceRefNoSection(dest.Ref, wrapRefErr); refErr != nil { - merr = multierror.Append(merr, refErr) - } - - // NOTE: Destinations here cannot define ports. Port equality is - // assumed and will be reconciled. - if dest.Port != "" { - if ported { - if portNameErr := ValidatePortName(dest.Port); portNameErr != nil { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "port", - Wrapped: portNameErr, - })) - } - } else { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "port", - Wrapped: fmt.Errorf("ports cannot be specified explicitly for the general failover section since it relies upon port alignment"), - })) - } - } - - hasPeer := false - if dest.Ref != nil { - hasPeer = dest.Ref.Tenancy.PeerName != "" && dest.Ref.Tenancy.PeerName != "local" - } - - if hasPeer && dest.Datacenter != "" { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "datacenter", - Wrapped: fmt.Errorf("ref.tenancy.peer_name and datacenter are mutually exclusive fields"), - })) - } - - return merr -} - -// SimplifyFailoverPolicy fully populates the PortConfigs map and clears the -// Configs map using the provided Service. -func SimplifyFailoverPolicy(svc *pbcatalog.Service, failover *pbcatalog.FailoverPolicy) *pbcatalog.FailoverPolicy { - if failover == nil { - panic("failover is required") - } - if svc == nil { - panic("service is required") - } - - // Copy so we can edit it. - dup := proto.Clone(failover) - failover = dup.(*pbcatalog.FailoverPolicy) - - if failover.PortConfigs == nil { - failover.PortConfigs = make(map[string]*pbcatalog.FailoverConfig) - } - - for _, port := range svc.Ports { - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue // skip - } - - if pc, ok := failover.PortConfigs[port.TargetPort]; ok { - for i, dest := range pc.Destinations { - // Assume port alignment. - if dest.Port == "" { - dest.Port = port.TargetPort - pc.Destinations[i] = dest - } - } - continue - } - - if failover.Config != nil { - // Duplicate because each port will get this uniquely. - pc2 := proto.Clone(failover.Config).(*pbcatalog.FailoverConfig) - for _, dest := range pc2.Destinations { - dest.Port = port.TargetPort - } - failover.PortConfigs[port.TargetPort] = pc2 - } - } - - if failover.Config != nil { - failover.Config = nil - } - - return failover -} - -func aclReadHookFailoverPolicy(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID, _ *pbresource.Resource) error { - // FailoverPolicy is name-aligned with Service - serviceName := id.Name - - // Check service:read permissions. - return authorizer.ToAllowAuthorizer().ServiceReadAllowed(serviceName, authzContext) -} - -func aclWriteHookFailoverPolicy(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *DecodedFailoverPolicy) error { - // FailoverPolicy is name-aligned with Service - serviceName := res.Id.Name - - // Check service:write permissions on the service this is controlling. - if err := authorizer.ToAllowAuthorizer().ServiceWriteAllowed(serviceName, authzContext); err != nil { - return err - } - - // Ensure you have service:read on any destination that may be affected by - // traffic FROM this config change. - if res.Data.Config != nil { - for _, dest := range res.Data.Config.Destinations { - destAuthzContext := resource.AuthorizerContext(dest.Ref.GetTenancy()) - destServiceName := dest.Ref.GetName() - if err := authorizer.ToAllowAuthorizer().ServiceReadAllowed(destServiceName, destAuthzContext); err != nil { - return err - } - } - } - for _, pc := range res.Data.PortConfigs { - for _, dest := range pc.Destinations { - destAuthzContext := resource.AuthorizerContext(dest.Ref.GetTenancy()) - destServiceName := dest.Ref.GetName() - if err := authorizer.ToAllowAuthorizer().ServiceReadAllowed(destServiceName, destAuthzContext); err != nil { - return err - } - } - } - - return nil - -} diff --git a/internal/catalog/internal/types/failover_policy_test.go b/internal/catalog/internal/types/failover_policy_test.go deleted file mode 100644 index 5628ed57741c..000000000000 --- a/internal/catalog/internal/types/failover_policy_test.go +++ /dev/null @@ -1,849 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestMutateFailoverPolicy(t *testing.T) { - type testcase struct { - policyTenancy *pbresource.Tenancy - failover *pbcatalog.FailoverPolicy - expect *pbcatalog.FailoverPolicy - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithTenancy(tc.policyTenancy). - WithData(t, tc.failover). - Build() - - err := MutateFailoverPolicy(res) - - got := resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, res) - - if tc.expectErr == "" { - require.NoError(t, err) - prototest.AssertDeepEqual(t, tc.expect, got.Data) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "empty-1": { - failover: &pbcatalog.FailoverPolicy{}, - expect: &pbcatalog.FailoverPolicy{}, - }, - "empty-config-1": { - failover: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{}, - }, - expect: &pbcatalog.FailoverPolicy{}, - }, - "empty-config-2": { - failover: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: make([]*pbcatalog.FailoverDestination, 0), - }, - }, - expect: &pbcatalog.FailoverPolicy{}, - }, - "empty-map-1": { - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: make(map[string]*pbcatalog.FailoverConfig), - }, - expect: &pbcatalog.FailoverPolicy{}, - }, - "empty-map-config-1": { - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": {}, - }, - }, - expect: &pbcatalog.FailoverPolicy{}, - }, - "empty-map-config-2": { - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: make([]*pbcatalog.FailoverDestination, 0), - }, - }, - }, - expect: &pbcatalog.FailoverPolicy{}, - }, - "normal": { - failover: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Mode: pbcatalog.FailoverMode_FAILOVER_MODE_SEQUENTIAL, - Regions: []string{"foo", "bar"}, - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "a")}, - {Ref: newRef(pbcatalog.ServiceType, "b")}, - }, - }, - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "foo")}, - {Ref: newRef(pbcatalog.ServiceType, "bar")}, - }, - }, - "admin": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "y")}, - {Ref: newRef(pbcatalog.ServiceType, "z")}, - }, - }, - }, - }, - expect: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Mode: pbcatalog.FailoverMode_FAILOVER_MODE_SEQUENTIAL, - Regions: []string{"foo", "bar"}, - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "a")}, - {Ref: newRef(pbcatalog.ServiceType, "b")}, - }, - }, - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "foo")}, - {Ref: newRef(pbcatalog.ServiceType, "bar")}, - }, - }, - "admin": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "y")}, - {Ref: newRef(pbcatalog.ServiceType, "z")}, - }, - }, - }, - }, - }, - "dest ref tenancy defaulting": { - policyTenancy: resourcetest.Tenancy("foo.bar"), - failover: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Mode: pbcatalog.FailoverMode_FAILOVER_MODE_SEQUENTIAL, - Regions: []string{"foo", "bar"}, - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRefWithTenancy(pbcatalog.ServiceType, "", "api")}, - {Ref: newRefWithTenancy(pbcatalog.ServiceType, ".zim", "api")}, - {Ref: newRefWithTenancy(pbcatalog.ServiceType, "gir.zim", "api")}, - }, - }, - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRefWithTenancy(pbcatalog.ServiceType, "", "api")}, - {Ref: newRefWithTenancy(pbcatalog.ServiceType, ".luthor", "api")}, - {Ref: newRefWithTenancy(pbcatalog.ServiceType, "lex.luthor", "api")}, - }, - }, - }, - }, - expect: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Mode: pbcatalog.FailoverMode_FAILOVER_MODE_SEQUENTIAL, - Regions: []string{"foo", "bar"}, - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRefWithTenancy(pbcatalog.ServiceType, "foo.bar", "api")}, - {Ref: newRefWithTenancy(pbcatalog.ServiceType, "foo.zim", "api")}, - {Ref: newRefWithTenancy(pbcatalog.ServiceType, "gir.zim", "api")}, - }, - }, - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRefWithTenancy(pbcatalog.ServiceType, "foo.bar", "api")}, - {Ref: newRefWithTenancy(pbcatalog.ServiceType, "foo.luthor", "api")}, - {Ref: newRefWithTenancy(pbcatalog.ServiceType, "lex.luthor", "api")}, - }, - }, - }, - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestValidateFailoverPolicy(t *testing.T) { - type configTestcase struct { - config *pbcatalog.FailoverConfig - expectErr string - } - - type testcase struct { - failover *pbcatalog.FailoverPolicy - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, tc.failover). - Build() - - require.NoError(t, MutateFailoverPolicy(res)) - - // Verify that mutate didn't actually change the object. - got := resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, res) - prototest.AssertDeepEqual(t, tc.failover, got.Data) - - err := ValidateFailoverPolicy(res) - - // Verify that validate didn't actually change the object. - got = resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, res) - prototest.AssertDeepEqual(t, tc.failover, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - configCases := map[string]configTestcase{ - "dest with sameness": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "api-backup")}, - }, - SamenessGroup: "blah", - }, - // TODO(v2): uncomment after this is supported - // expectErr: `invalid "destinations" field: exactly one of destinations or sameness_group should be set`, - expectErr: `invalid "sameness_group" field: not supported in this release`, - }, - "dest without sameness": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "api-backup")}, - }, - }, - }, - "sameness without dest": { - config: &pbcatalog.FailoverConfig{ - SamenessGroup: "blah", - }, - // TODO(v2): remove after this is supported - expectErr: `invalid "sameness_group" field: not supported in this release`, - }, - "regions without dest": { - config: &pbcatalog.FailoverConfig{ - Regions: []string{"us-east1", "us-west2"}, - }, - // TODO(v2): remove after this is supported - expectErr: `invalid "regions" field: not supported in this release`, - }, - "mode without dest": { - config: &pbcatalog.FailoverConfig{ - Mode: pbcatalog.FailoverMode_FAILOVER_MODE_SEQUENTIAL, - }, - // TODO(v2): remove after this is supported - expectErr: `invalid "mode" field: not supported in this release`, - }, - // TODO(v2): uncomment after this is supported - // "mode: invalid": { - // config: &pbcatalog.FailoverConfig{ - // Mode: 99, - // Destinations: []*pbcatalog.FailoverDestination{ - // {Ref: newRef(pbcatalog.ServiceType, "api-backup")}, - // }, - // }, - // expectErr: `invalid "mode" field: not a supported enum value: 99`, - // }, - "dest: no ref": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "ref" field: missing required field`, - }, - "dest: non-service ref": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.WorkloadType, "api-backup")}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "ref" field: invalid "type" field: reference must have type catalog.v2beta1.Service`, - }, - "dest: ref with section": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: resourcetest.Resource(pbcatalog.ServiceType, "api").WithTenancy(resource.DefaultNamespacedTenancy()).Reference("blah")}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "ref" field: invalid "section" field: section cannot be set here`, - }, - // TODO(v2/peering): re-enable when peering can exist - // "dest: ref peer and datacenter": { - // config: &pbcatalog.FailoverConfig{ - // Destinations: []*pbcatalog.FailoverDestination{ - // {Ref: newRefWithPeer(pbcatalog.ServiceType, "api", "peer1"), Datacenter: "dc2"}, - // }, - // }, - // expectErr: `invalid element at index 0 of list "destinations": invalid "datacenter" field: ref.tenancy.peer_name and datacenter are mutually exclusive fields`, - // }, - // TODO(v2/peering): re-enable when peering can exist - // "dest: ref peer without datacenter": { - // config: &pbcatalog.FailoverConfig{ - // Destinations: []*pbcatalog.FailoverDestination{ - // {Ref: newRefWithPeer(pbcatalog.ServiceType, "api", "peer1")}, - // }, - // }, - // }, - "dest: ref datacenter without peer": { - config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "api"), Datacenter: "dc2"}, - }, - }, - }, - } - - cases := map[string]testcase{ - // emptiness - "empty": { - failover: &pbcatalog.FailoverPolicy{}, - expectErr: `invalid "config" field: at least one of config or port_configs must be set`, - }, - "non-empty: one port config but no plain config": { - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "api-backup")}, - }, - }, - }, - }, - }, - "non-empty: some plain config but no port configs": { - failover: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "api-backup")}, - }, - }, - }, - }, - // plain config - "plain config: bad dest: any port name": { - failover: &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "api-backup"), Port: "web"}, - }, - }, - }, - expectErr: `invalid "config" field: invalid element at index 0 of list "destinations": invalid "port" field: ports cannot be specified explicitly for the general failover section since it relies upon port alignment`, - }, - // ported config - "ported config: bad dest: invalid port name": { - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "api-backup"), Port: "$bad$"}, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid element at index 0 of list "destinations": invalid "port" field: value must match regex: ^[a-z0-9]([a-z0-9\-_]*[a-z0-9])?$`, - }, - "ported config: bad ported in map": { - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "$bad$": { - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: newRef(pbcatalog.ServiceType, "api-backup"), Port: "http"}, - }, - }, - }, - }, - expectErr: `map port_configs contains an invalid key - "$bad$": value must match regex: ^[a-z0-9]([a-z0-9\-_]*[a-z0-9])?$`, - }, - } - - maybeWrap := func(wrapPrefix, base string) string { - if base != "" { - return wrapPrefix + base - } - return "" - } - - for name, tc := range configCases { - cases["plain config: "+name] = testcase{ - failover: &pbcatalog.FailoverPolicy{ - Config: proto.Clone(tc.config).(*pbcatalog.FailoverConfig), - }, - expectErr: maybeWrap(`invalid "config" field: `, tc.expectErr), - } - - cases["ported config: "+name] = testcase{ - failover: &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": proto.Clone(tc.config).(*pbcatalog.FailoverConfig), - }, - }, - expectErr: maybeWrap(`invalid value of key "http" within port_configs: `, tc.expectErr), - } - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestSimplifyFailoverPolicy(t *testing.T) { - registry := resource.NewRegistry() - Register(registry) - - type testcase struct { - svc *pbresource.Resource - failover *pbresource.Resource - expect *pbresource.Resource - } - run := func(t *testing.T, tc testcase) { - // Ensure we only use valid inputs. - resourcetest.ValidateAndNormalize(t, registry, tc.svc) - resourcetest.ValidateAndNormalize(t, registry, tc.failover) - resourcetest.ValidateAndNormalize(t, registry, tc.expect) - - svc := resourcetest.MustDecode[*pbcatalog.Service](t, tc.svc) - failover := resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, tc.failover) - expect := resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, tc.expect) - - inputFailoverCopy := proto.Clone(failover.Data).(*pbcatalog.FailoverPolicy) - - got := SimplifyFailoverPolicy(svc.Data, failover.Data) - prototest.AssertDeepEqual(t, expect.Data, got) - - // verify input was not altered - prototest.AssertDeepEqual(t, inputFailoverCopy, failover.Data) - } - - newPort := func(name string, virtualPort uint32, protocol pbcatalog.Protocol) *pbcatalog.ServicePort { - return &pbcatalog.ServicePort{ - VirtualPort: virtualPort, - TargetPort: name, - Protocol: protocol, - } - } - - cases := map[string]testcase{ - "implicit with mesh port skipping": { - svc: resourcetest.Resource(pbcatalog.ServiceType, "api"). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - newPort("mesh", 21001, pbcatalog.Protocol_PROTOCOL_MESH), - newPort("http", 8080, pbcatalog.Protocol_PROTOCOL_HTTP), - }, - }). - Build(), - failover: resourcetest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(pbcatalog.ServiceType, "api-backup"), - }, - }, - }, - }). - Build(), - expect: resourcetest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(pbcatalog.ServiceType, "api-backup"), - Port: "http", // port defaulted - }, - }, - }, - }, - }). - Build(), - }, - "explicit with port aligned defaulting": { - svc: resourcetest.Resource(pbcatalog.ServiceType, "api"). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - newPort("mesh", 9999, pbcatalog.Protocol_PROTOCOL_MESH), - newPort("http", 8080, pbcatalog.Protocol_PROTOCOL_HTTP), - newPort("rest", 8282, pbcatalog.Protocol_PROTOCOL_HTTP2), - }, - }). - Build(), - failover: resourcetest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(pbcatalog.ServiceType, "api-backup"), - Port: "www", - }, - { - Ref: newRef(pbcatalog.ServiceType, "api-double-backup"), - }, - }, - }, - }, - }). - Build(), - expect: resourcetest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(pbcatalog.ServiceType, "api-backup"), - Port: "www", - }, - { - Ref: newRef(pbcatalog.ServiceType, "api-double-backup"), - Port: "http", // port defaulted - }, - }, - }, - }, - }). - Build(), - }, - "implicit port explosion": { - svc: resourcetest.Resource(pbcatalog.ServiceType, "api"). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - newPort("http", 8080, pbcatalog.Protocol_PROTOCOL_HTTP), - newPort("rest", 8282, pbcatalog.Protocol_PROTOCOL_HTTP2), - }, - }). - Build(), - failover: resourcetest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(pbcatalog.ServiceType, "api-backup"), - }, - { - Ref: newRef(pbcatalog.ServiceType, "api-double-backup"), - }, - }, - }, - }). - Build(), - expect: resourcetest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(pbcatalog.ServiceType, "api-backup"), - Port: "http", - }, - { - Ref: newRef(pbcatalog.ServiceType, "api-double-backup"), - Port: "http", - }, - }, - }, - "rest": { - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(pbcatalog.ServiceType, "api-backup"), - Port: "rest", - }, - { - Ref: newRef(pbcatalog.ServiceType, "api-double-backup"), - Port: "rest", - }, - }, - }, - }, - }). - Build(), - }, - "mixed port explosion with skip": { - svc: resourcetest.Resource(pbcatalog.ServiceType, "api"). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - newPort("http", 8080, pbcatalog.Protocol_PROTOCOL_HTTP), - newPort("rest", 8282, pbcatalog.Protocol_PROTOCOL_HTTP2), - }, - }). - Build(), - failover: resourcetest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(pbcatalog.ServiceType, "api-backup"), - }, - { - Ref: newRef(pbcatalog.ServiceType, "api-double-backup"), - }, - }, - }, - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "rest": { - // TODO(v2): uncomment when this works - // Mode: pbcatalog.FailoverMode_FAILOVER_MODE_ORDER_BY_LOCALITY, - // Regions: []string{"us", "eu"}, - // SamenessGroup: "sameweb", - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(pbcatalog.ServiceType, "api-backup"), - Port: "rest", - }, - { - Ref: newRef(pbcatalog.ServiceType, "api-double-backup"), - Port: "rest", - }, - }, - }, - }, - }). - Build(), - expect: resourcetest.Resource(pbcatalog.FailoverPolicyType, "api"). - WithData(t, &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(pbcatalog.ServiceType, "api-backup"), - Port: "http", - }, - { - Ref: newRef(pbcatalog.ServiceType, "api-double-backup"), - Port: "http", - }, - }, - }, - "rest": { - // TODO(v2): uncomment when this works - // Mode: pbcatalog.FailoverMode_FAILOVER_MODE_ORDER_BY_LOCALITY, - // Regions: []string{"us", "eu"}, - // SamenessGroup: "sameweb", - Destinations: []*pbcatalog.FailoverDestination{ - { - Ref: newRef(pbcatalog.ServiceType, "api-backup"), - Port: "rest", - }, - { - Ref: newRef(pbcatalog.ServiceType, "api-double-backup"), - Port: "rest", - }, - }, - }, - }, - }). - Build(), - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestFailoverPolicyACLs(t *testing.T) { - // Wire up a registry to generically invoke hooks - registry := resource.NewRegistry() - Register(registry) - - newFailover := func(t *testing.T, name, tenancyStr string, destRefs []*pbresource.Reference) []*pbresource.Resource { - var dr []*pbcatalog.FailoverDestination - for _, destRef := range destRefs { - dr = append(dr, &pbcatalog.FailoverDestination{Ref: destRef}) - } - - res1 := resourcetest.Resource(pbcatalog.FailoverPolicyType, name). - WithTenancy(resourcetest.Tenancy(tenancyStr)). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{Destinations: dr}, - }). - Build() - resourcetest.ValidateAndNormalize(t, registry, res1) - - res2 := resourcetest.Resource(pbcatalog.FailoverPolicyType, name). - WithTenancy(resourcetest.Tenancy(tenancyStr)). - WithData(t, &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": {Destinations: dr}, - }, - }). - Build() - resourcetest.ValidateAndNormalize(t, registry, res2) - - return []*pbresource.Resource{res1, res2} - } - - type testcase struct { - res *pbresource.Resource - rules string - check func(t *testing.T, authz acl.Authorizer, res *pbresource.Resource) - readOK string - writeOK string - } - - const ( - DENY = resourcetest.DENY - ALLOW = resourcetest.ALLOW - DEFAULT = resourcetest.DEFAULT - ) - - serviceRef := func(tenancy, name string) *pbresource.Reference { - return newRefWithTenancy(pbcatalog.ServiceType, tenancy, name) - } - - resOneDest := func(tenancy, destTenancy string) []*pbresource.Resource { - return newFailover(t, "api", tenancy, []*pbresource.Reference{ - serviceRef(destTenancy, "dest1"), - }) - } - - resTwoDests := func(tenancy, destTenancy string) []*pbresource.Resource { - return newFailover(t, "api", tenancy, []*pbresource.Reference{ - serviceRef(destTenancy, "dest1"), - serviceRef(destTenancy, "dest2"), - }) - } - - run := func(t *testing.T, name string, tc resourcetest.ACLTestCase) { - t.Run(name, func(t *testing.T) { - resourcetest.RunACLTestCase(t, tc, registry) - }) - } - - isEnterprise := (structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default") - - serviceRead := func(partition, namespace, name string) string { - if isEnterprise { - return fmt.Sprintf(` partition %q { namespace %q { service %q { policy = "read" } } }`, partition, namespace, name) - } - return fmt.Sprintf(` service %q { policy = "read" } `, name) - } - serviceWrite := func(partition, namespace, name string) string { - if isEnterprise { - return fmt.Sprintf(` partition %q { namespace %q { service %q { policy = "write" } } }`, partition, namespace, name) - } - return fmt.Sprintf(` service %q { policy = "write" } `, name) - } - - assert := func(t *testing.T, name string, rules string, resList []*pbresource.Resource, readOK, writeOK string) { - for i, res := range resList { - tc := resourcetest.ACLTestCase{ - AuthCtx: resource.AuthorizerContext(res.Id.Tenancy), - Res: res, - Rules: rules, - ReadOK: readOK, - WriteOK: writeOK, - ListOK: DEFAULT, - } - run(t, fmt.Sprintf("%s-%d", name, i), tc) - } - } - - tenancies := []string{"default.default"} - if isEnterprise { - tenancies = append(tenancies, "default.foo", "alpha.default", "alpha.foo") - } - - for _, policyTenancyStr := range tenancies { - t.Run("policy tenancy: "+policyTenancyStr, func(t *testing.T) { - for _, destTenancyStr := range tenancies { - t.Run("dest tenancy: "+destTenancyStr, func(t *testing.T) { - for _, aclTenancyStr := range tenancies { - t.Run("acl tenancy: "+aclTenancyStr, func(t *testing.T) { - aclTenancy := resourcetest.Tenancy(aclTenancyStr) - - maybe := func(match string, parentOnly bool) string { - if policyTenancyStr != aclTenancyStr { - return DENY - } - if !parentOnly && destTenancyStr != aclTenancyStr { - return DENY - } - return match - } - - t.Run("no rules", func(t *testing.T) { - rules := `` - assert(t, "1dest", rules, resOneDest(policyTenancyStr, destTenancyStr), DENY, DENY) - assert(t, "2dests", rules, resTwoDests(policyTenancyStr, destTenancyStr), DENY, DENY) - }) - t.Run("api:read", func(t *testing.T) { - rules := serviceRead(aclTenancy.Partition, aclTenancy.Namespace, "api") - assert(t, "1dest", rules, resOneDest(policyTenancyStr, destTenancyStr), maybe(ALLOW, true), DENY) - assert(t, "2dests", rules, resTwoDests(policyTenancyStr, destTenancyStr), maybe(ALLOW, true), DENY) - }) - t.Run("api:write", func(t *testing.T) { - rules := serviceWrite(aclTenancy.Partition, aclTenancy.Namespace, "api") - assert(t, "1dest", rules, resOneDest(policyTenancyStr, destTenancyStr), maybe(ALLOW, true), DENY) - assert(t, "2dests", rules, resTwoDests(policyTenancyStr, destTenancyStr), maybe(ALLOW, true), DENY) - }) - t.Run("api:write dest1:read", func(t *testing.T) { - rules := serviceWrite(aclTenancy.Partition, aclTenancy.Namespace, "api") + - serviceRead(aclTenancy.Partition, aclTenancy.Namespace, "dest1") - assert(t, "1dest", rules, resOneDest(policyTenancyStr, destTenancyStr), maybe(ALLOW, true), maybe(ALLOW, false)) - assert(t, "2dests", rules, resTwoDests(policyTenancyStr, destTenancyStr), maybe(ALLOW, true), DENY) - }) - }) - } - }) - } - }) - } -} - -func newRef(typ *pbresource.Type, name string) *pbresource.Reference { - return resourcetest.Resource(typ, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - Reference("") -} - -func newRefWithTenancy(typ *pbresource.Type, tenancyStr, name string) *pbresource.Reference { - return resourcetest.Resource(typ, name). - WithTenancy(resourcetest.Tenancy(tenancyStr)). - Reference("") -} - -func newRefWithPeer(typ *pbresource.Type, name string, peer string) *pbresource.Reference { - ref := newRef(typ, name) - ref.Tenancy.PeerName = peer - return ref -} diff --git a/internal/catalog/internal/types/health_checks.go b/internal/catalog/internal/types/health_checks.go deleted file mode 100644 index 3d819e12885a..000000000000 --- a/internal/catalog/internal/types/health_checks.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" -) - -type DecodedHealthChecks = resource.DecodedResource[*pbcatalog.HealthChecks] - -func RegisterHealthChecks(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbcatalog.HealthChecksType, - Proto: &pbcatalog.HealthChecks{}, - Scope: resource.ScopeNamespace, - Validate: ValidateHealthChecks, - ACLs: ACLHooksForWorkloadSelectingType[*pbcatalog.HealthChecks](), - }) -} - -var ValidateHealthChecks = resource.DecodeAndValidate(validateHealthChecks) - -func validateHealthChecks(res *DecodedHealthChecks) error { - var err error - - // Validate the workload selector - if selErr := ValidateSelector(res.Data.Workloads, false); selErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "workloads", - Wrapped: selErr, - }) - } - - // Validate each check - for idx, check := range res.Data.HealthChecks { - if checkErr := validateCheck(check); checkErr != nil { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "checks", - Index: idx, - Wrapped: checkErr, - }) - } - } - - return err -} - -func validateCheck(check *pbcatalog.HealthCheck) error { - var err error - // Validate the check name - if check.Name == "" { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "name", - Wrapped: resource.ErrMissing, - }) - } else if !isValidDNSLabel(check.Name) { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "name", - Wrapped: errNotDNSLabel, - }) - } - - // Validate the definition - if check.Definition == nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "definition", - Wrapped: resource.ErrMissing, - }) - } - - // In theory it would be nice to validate the individual check definition. - // However whether a check is valid will be up for interpretation by - // the check executor. The executor may default some addressing, - // allow for templating etc. Therefore we cannot really know at admission - // time whether the check will be executable. Therefore it is expected - // that check executors will update the status of the resource to note - // whether it was valid for that executor. - - return err -} diff --git a/internal/catalog/internal/types/health_checks_test.go b/internal/catalog/internal/types/health_checks_test.go deleted file mode 100644 index c9cdf01ae84c..000000000000 --- a/internal/catalog/internal/types/health_checks_test.go +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/known/anypb" - "google.golang.org/protobuf/types/known/durationpb" - - "github.com/hashicorp/consul/internal/catalog/internal/testhelpers" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func createHealthChecksResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { - res := &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.HealthChecksType, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: "test-checks", - }, - } - - var err error - res.Data, err = anypb.New(data) - require.NoError(t, err) - return res -} - -func TestValidateHealthChecks_Ok(t *testing.T) { - data := &pbcatalog.HealthChecks{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - HealthChecks: []*pbcatalog.HealthCheck{ - { - Name: "test-check", - Definition: &pbcatalog.HealthCheck_Tcp{ - Tcp: &pbcatalog.TCPCheck{ - Address: "198.18.0.1", - }, - }, - Interval: durationpb.New(30 * time.Second), - Timeout: durationpb.New(15 * time.Second), - }, - }, - } - - res := createHealthChecksResource(t, data) - - err := ValidateHealthChecks(res) - require.NoError(t, err) -} - -func TestValidateHealthChecks_ParseError(t *testing.T) { - // Any type other than the HealthChecks type would work - // to cause the error we are expecting - data := &pbcatalog.IP{Address: "198.18.0.1"} - - res := createHealthChecksResource(t, data) - - err := ValidateHealthChecks(res) - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) -} - -func TestValidateHealthChecks_InvalidCheckName(t *testing.T) { - genData := func(name string) *pbcatalog.HealthChecks { - return &pbcatalog.HealthChecks{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - HealthChecks: []*pbcatalog.HealthCheck{ - { - Name: name, - Definition: &pbcatalog.HealthCheck_Tcp{ - Tcp: &pbcatalog.TCPCheck{ - Address: "198.18.0.1", - }, - }, - Interval: durationpb.New(30 * time.Second), - Timeout: durationpb.New(15 * time.Second), - }, - }, - } - } - - type testCase struct { - name string - err bool - expectedErr resource.ErrInvalidField - } - - // These checks are not exhaustive of the classes of names which - // would be accepted or rejected. The tests for the isValidDNSLabel - // function have more thorough testing. Here we just ensure that - // we can get the errNotDNSLabel error to indicate that calling - // that function returned false and was emitted by ValidateHealthChecks - cases := map[string]testCase{ - "basic": { - name: "foo-check", - }, - "missing-name": { - err: true, - expectedErr: resource.ErrInvalidField{ - Name: "name", - Wrapped: resource.ErrEmpty, - }, - }, - "invalid-dns-label": { - name: "UPPERCASE", - err: true, - expectedErr: resource.ErrInvalidField{ - Name: "name", - Wrapped: errNotDNSLabel, - }, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - data := genData(tcase.name) - err := ValidateHealthChecks(createHealthChecksResource(t, data)) - - if tcase.err { - require.Error(t, err) - - } else { - require.NoError(t, err) - } - }) - } -} - -func TestValidateHealthChecks_MissingDefinition(t *testing.T) { - data := &pbcatalog.HealthChecks{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - HealthChecks: []*pbcatalog.HealthCheck{ - { - Name: "test-check", - Interval: durationpb.New(30 * time.Second), - Timeout: durationpb.New(15 * time.Second), - }, - }, - } - - res := createHealthChecksResource(t, data) - - err := ValidateHealthChecks(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "definition", - Wrapped: resource.ErrMissing, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateHealthChecks_EmptySelector(t *testing.T) { - data := &pbcatalog.HealthChecks{ - HealthChecks: []*pbcatalog.HealthCheck{ - { - Name: "test-check", - Definition: &pbcatalog.HealthCheck_Tcp{ - Tcp: &pbcatalog.TCPCheck{ - Address: "198.18.0.1", - }, - }, - Interval: durationpb.New(30 * time.Second), - Timeout: durationpb.New(15 * time.Second), - }, - }, - } - - res := createHealthChecksResource(t, data) - - err := ValidateHealthChecks(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "workloads", - Wrapped: resource.ErrEmpty, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestHealthChecksACLs(t *testing.T) { - testhelpers.RunWorkloadSelectingTypeACLsTests[*pbcatalog.HealthChecks](t, pbcatalog.HealthChecksType, - func(selector *pbcatalog.WorkloadSelector) *pbcatalog.HealthChecks { - return &pbcatalog.HealthChecks{Workloads: selector} - }, - RegisterHealthChecks, - ) -} diff --git a/internal/catalog/internal/types/health_status.go b/internal/catalog/internal/types/health_status.go deleted file mode 100644 index c5ea7e106fa3..000000000000 --- a/internal/catalog/internal/types/health_status.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type DecodedHealthStatus = resource.DecodedResource[*pbcatalog.HealthStatus] - -func RegisterHealthStatus(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbcatalog.HealthStatusType, - Proto: &pbcatalog.HealthStatus{}, - Scope: resource.ScopeNamespace, - Validate: ValidateHealthStatus, - ACLs: &resource.ACLHooks{ - Read: resource.AuthorizeReadWithResource(aclReadHookHealthStatus), - Write: aclWriteHookHealthStatus, - List: resource.NoOpACLListHook, - }, - }) -} - -var ValidateHealthStatus = resource.DecodeAndValidate(validateHealthStatus) - -func validateHealthStatus(res *DecodedHealthStatus) error { - var err error - - // Should we allow empty types? I think for now it will be safest to require - // the type field is set and we can relax this restriction in the future - // if we deem it desirable. - if res.Data.Type == "" { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "type", - Wrapped: resource.ErrMissing, - }) - } - - switch res.Data.Status { - case pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_MAINTENANCE: - default: - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "status", - Wrapped: errInvalidHealth, - }) - } - - // Ensure that the HealthStatus' owner is a type that we want to allow. The - // owner is currently the resource that this HealthStatus applies to. If we - // change this to be a parent reference within the HealthStatus.Data then - // we could allow for other owners. - if res.Resource.Owner == nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "owner", - Wrapped: resource.ErrMissing, - }) - } else if !resource.EqualType(res.Owner.Type, pbcatalog.WorkloadType) && !resource.EqualType(res.Owner.Type, pbcatalog.NodeType) { - err = multierror.Append(err, resource.ErrOwnerTypeInvalid{ResourceType: res.Id.Type, OwnerType: res.Owner.Type}) - } - - return err -} - -func aclReadHookHealthStatus(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { - // For a health status of a workload we need to check service:read perms. - if res.GetOwner() != nil && resource.EqualType(res.GetOwner().GetType(), pbcatalog.WorkloadType) { - return authorizer.ToAllowAuthorizer().ServiceReadAllowed(res.GetOwner().GetName(), authzContext) - } - - // For a health status of a node we need to check node:read perms. - if res.GetOwner() != nil && resource.EqualType(res.GetOwner().GetType(), pbcatalog.NodeType) { - return authorizer.ToAllowAuthorizer().NodeReadAllowed(res.GetOwner().GetName(), authzContext) - } - - return acl.PermissionDenied("cannot read catalog.HealthStatus because there is no owner") -} - -func aclWriteHookHealthStatus(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { - // For a health status of a workload we need to check service:write perms. - if res.GetOwner() != nil && resource.EqualType(res.GetOwner().GetType(), pbcatalog.WorkloadType) { - return authorizer.ToAllowAuthorizer().ServiceWriteAllowed(res.GetOwner().GetName(), authzContext) - } - - // For a health status of a node we need to check node:write perms. - if res.GetOwner() != nil && resource.EqualType(res.GetOwner().GetType(), pbcatalog.NodeType) { - return authorizer.ToAllowAuthorizer().NodeWriteAllowed(res.GetOwner().GetName(), authzContext) - } - - return acl.PermissionDenied("cannot write catalog.HealthStatus because there is no owner") -} diff --git a/internal/catalog/internal/types/health_status_test.go b/internal/catalog/internal/types/health_status_test.go deleted file mode 100644 index 9482e4770e40..000000000000 --- a/internal/catalog/internal/types/health_status_test.go +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -var ( - defaultHealthStatusOwnerTenancy = &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - } - - defaultHealthStatusOwner = &pbresource.ID{ - Type: pbcatalog.WorkloadType, - Tenancy: defaultHealthStatusOwnerTenancy, - Name: "foo", - } -) - -func createHealthStatusResource(t *testing.T, data protoreflect.ProtoMessage, owner *pbresource.ID) *pbresource.Resource { - res := &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.HealthStatusType, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: "test-status", - }, - Owner: owner, - } - - var err error - res.Data, err = anypb.New(data) - require.NoError(t, err) - return res -} - -func TestValidateHealthStatus_Ok(t *testing.T) { - data := &pbcatalog.HealthStatus{ - Type: "tcp", - Status: pbcatalog.Health_HEALTH_PASSING, - Description: "Doesn't matter as this is user settable", - Output: "Health check executors are free to use this field", - } - - type testCase struct { - owner *pbresource.ID - } - - cases := map[string]testCase{ - "workload-owned": { - owner: &pbresource.ID{ - Type: pbcatalog.WorkloadType, - Tenancy: defaultHealthStatusOwnerTenancy, - Name: "foo-workload", - }, - }, - "node-owned": { - owner: &pbresource.ID{ - Type: pbcatalog.NodeType, - Tenancy: defaultHealthStatusOwnerTenancy, - Name: "bar-node", - }, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - res := createHealthStatusResource(t, data, tcase.owner) - err := ValidateHealthStatus(res) - require.NoError(t, err) - }) - } -} - -func TestValidateHealthStatus_ParseError(t *testing.T) { - // Any type other than the HealthStatus type would work - // to cause the error we are expecting - data := &pbcatalog.IP{Address: "198.18.0.1"} - - res := createHealthStatusResource(t, data, defaultHealthStatusOwner) - - err := ValidateHealthStatus(res) - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) -} - -func TestValidateHealthStatus_InvalidHealth(t *testing.T) { - // while this is a valid enum value it is not allowed to be used - // as the Status field. - data := &pbcatalog.HealthStatus{ - Type: "tcp", - Status: pbcatalog.Health_HEALTH_ANY, - } - - res := createHealthStatusResource(t, data, defaultHealthStatusOwner) - - err := ValidateHealthStatus(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "status", - Wrapped: errInvalidHealth, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateHealthStatus_MissingType(t *testing.T) { - data := &pbcatalog.HealthStatus{ - Status: pbcatalog.Health_HEALTH_PASSING, - } - - res := createHealthStatusResource(t, data, defaultHealthStatusOwner) - - err := ValidateHealthStatus(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "type", - Wrapped: resource.ErrMissing, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateHealthStatus_MissingOwner(t *testing.T) { - data := &pbcatalog.HealthStatus{ - Type: "tcp", - Status: pbcatalog.Health_HEALTH_PASSING, - } - - res := createHealthStatusResource(t, data, nil) - - err := ValidateHealthStatus(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "owner", - Wrapped: resource.ErrMissing, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateHealthStatus_InvalidOwner(t *testing.T) { - data := &pbcatalog.HealthStatus{ - Type: "tcp", - Status: pbcatalog.Health_HEALTH_PASSING, - } - - type testCase struct { - owner *pbresource.ID - } - - cases := map[string]testCase{ - "group-mismatch": { - owner: &pbresource.ID{ - Type: &pbresource.Type{ - Group: "fake", - GroupVersion: pbcatalog.Version, - Kind: pbcatalog.WorkloadKind, - }, - Tenancy: defaultHealthStatusOwnerTenancy, - Name: "baz", - }, - }, - "group-version-mismatch": { - owner: &pbresource.ID{ - Type: &pbresource.Type{ - Group: pbcatalog.GroupName, - GroupVersion: "v99", - Kind: pbcatalog.WorkloadKind, - }, - Tenancy: defaultHealthStatusOwnerTenancy, - Name: "baz", - }, - }, - "kind-mismatch": { - owner: &pbresource.ID{ - Type: pbcatalog.ServiceType, - Tenancy: defaultHealthStatusOwnerTenancy, - Name: "baz", - }, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - res := createHealthStatusResource(t, data, tcase.owner) - err := ValidateHealthStatus(res) - require.Error(t, err) - expected := resource.ErrOwnerTypeInvalid{ - ResourceType: pbcatalog.HealthStatusType, - OwnerType: tcase.owner.Type, - } - var actual resource.ErrOwnerTypeInvalid - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) - }) - } -} - -func TestHealthStatusACLs(t *testing.T) { - registry := resource.NewRegistry() - Register(registry) - - workload := resourcetest.Resource(pbcatalog.WorkloadType, "test").ID() - node := resourcetest.Resource(pbcatalog.NodeType, "test").ID() - - healthStatusData := &pbcatalog.HealthStatus{ - Type: "tcp", - Status: pbcatalog.Health_HEALTH_PASSING, - } - - cases := map[string]resourcetest.ACLTestCase{ - "no rules": { - Rules: ``, - Data: healthStatusData, - Owner: workload, - Typ: pbcatalog.HealthStatusType, - ReadOK: resourcetest.DENY, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "service test read": { - Rules: `service "test" { policy = "read" }`, - Data: healthStatusData, - Owner: workload, - Typ: pbcatalog.HealthStatusType, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "service test write": { - Rules: `service "test" { policy = "write" }`, - Data: healthStatusData, - Owner: workload, - Typ: pbcatalog.HealthStatusType, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.ALLOW, - ListOK: resourcetest.DEFAULT, - }, - "service test read with node owner": { - Rules: `service "test" { policy = "read" }`, - Data: healthStatusData, - Owner: node, - Typ: pbcatalog.HealthStatusType, - ReadOK: resourcetest.DENY, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "service test write with node owner": { - Rules: `service "test" { policy = "write" }`, - Data: healthStatusData, - Owner: node, - Typ: pbcatalog.HealthStatusType, - ReadOK: resourcetest.DENY, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "node test read with node owner": { - Rules: `node "test" { policy = "read" }`, - Data: healthStatusData, - Owner: node, - Typ: pbcatalog.HealthStatusType, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "node test write with node owner": { - Rules: `node "test" { policy = "write" }`, - Data: healthStatusData, - Owner: node, - Typ: pbcatalog.HealthStatusType, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.ALLOW, - ListOK: resourcetest.DEFAULT, - }, - "node test read with workload owner": { - Rules: `node "test" { policy = "read" }`, - Data: healthStatusData, - Owner: workload, - Typ: pbcatalog.HealthStatusType, - ReadOK: resourcetest.DENY, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "node test write with workload owner": { - Rules: `node "test" { policy = "write" }`, - Data: healthStatusData, - Owner: workload, - Typ: pbcatalog.HealthStatusType, - ReadOK: resourcetest.DENY, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - resourcetest.RunACLTestCase(t, tc, registry) - }) - } -} diff --git a/internal/catalog/internal/types/node.go b/internal/catalog/internal/types/node.go deleted file mode 100644 index 1ee68f22ca82..000000000000 --- a/internal/catalog/internal/types/node.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type DecodedNode = resource.DecodedResource[*pbcatalog.Node] - -func RegisterNode(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbcatalog.NodeType, - Proto: &pbcatalog.Node{}, - // TODO: A node should be partition scoped. However its HealthStatus which is - // namespace scoped has Node as an owner. We do not support ownership between resources - // of differing scope at this time. HealthStatus will probably be split out into two different - // types, one for namespace scoped owners and the other for partition scoped owners. - // Until that time, Node will remain namespace scoped. - Scope: resource.ScopeNamespace, - Validate: ValidateNode, - ACLs: &resource.ACLHooks{ - Read: aclReadHookNode, - Write: aclWriteHookNode, - List: resource.NoOpACLListHook, - }, - }) -} - -var ValidateNode = resource.DecodeAndValidate(validateNode) - -func validateNode(res *DecodedNode) error { - var err error - // Validate that the node has at least 1 address - if len(res.Data.Addresses) < 1 { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "addresses", - Wrapped: resource.ErrEmpty, - }) - } - - // Validate each node address - for idx, addr := range res.Data.Addresses { - if addrErr := validateNodeAddress(addr); addrErr != nil { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "addresses", - Index: idx, - Wrapped: addrErr, - }) - } - } - - return err -} - -// Validates a single node address -func validateNodeAddress(addr *pbcatalog.NodeAddress) error { - // Currently the only field needing validation is the Host field. If that - // changes then this func should get updated to use a multierror.Append - // to collect the errors and return the overall set. - - // Check that the host is empty - if addr.Host == "" { - return resource.ErrInvalidField{ - Name: "host", - Wrapped: resource.ErrMissing, - } - } - - // Check if the host represents an IP address or a DNS name. Unix socket paths - // are not allowed for Node addresses unlike workload addresses. - if !isValidIPAddress(addr.Host) && !isValidDNSName(addr.Host) { - return resource.ErrInvalidField{ - Name: "host", - Wrapped: errInvalidNodeHostFormat{Host: addr.Host}, - } - } - - return nil -} - -func aclReadHookNode(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID, _ *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().NodeReadAllowed(id.GetName(), authzContext) -} - -func aclWriteHookNode(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().NodeWriteAllowed(res.GetId().GetName(), authzContext) -} diff --git a/internal/catalog/internal/types/node_test.go b/internal/catalog/internal/types/node_test.go deleted file mode 100644 index 5a678745e3a3..000000000000 --- a/internal/catalog/internal/types/node_test.go +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func createNodeResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { - res := &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.NodeType, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: "test-node", - }, - } - - var err error - res.Data, err = anypb.New(data) - require.NoError(t, err) - return res -} - -func TestValidateNode_Ok(t *testing.T) { - data := &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{ - { - Host: "198.18.0.1", - }, - { - Host: "fe80::316a:ed5b:f62c:7321", - }, - { - Host: "foo.node.example.com", - External: true, - }, - }, - } - - res := createNodeResource(t, data) - - err := ValidateNode(res) - require.NoError(t, err) -} - -func TestValidateNode_ParseError(t *testing.T) { - // Any type other than the Node type would work - // to cause the error we are expecting - data := &pbcatalog.IP{Address: "198.18.0.1"} - - res := createNodeResource(t, data) - - err := ValidateNode(res) - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) -} - -func TestValidateNode_EmptyAddresses(t *testing.T) { - data := &pbcatalog.Node{} - - res := createNodeResource(t, data) - - err := ValidateNode(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "addresses", - Wrapped: resource.ErrEmpty, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateNode_InvalidAddress(t *testing.T) { - data := &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{ - { - Host: "unix:///node.sock", - }, - }, - } - - res := createNodeResource(t, data) - - err := ValidateNode(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "host", - Wrapped: errInvalidNodeHostFormat{Host: "unix:///node.sock"}, - } - - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateNode_AddressMissingHost(t *testing.T) { - data := &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{ - {}, - }, - } - - res := createNodeResource(t, data) - - err := ValidateNode(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "host", - Wrapped: resource.ErrMissing, - } - - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestNodeACLs(t *testing.T) { - registry := resource.NewRegistry() - Register(registry) - - nodeData := &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{ - { - Host: "1.1.1.1", - }, - }, - } - cases := map[string]resourcetest.ACLTestCase{ - "no rules": { - Rules: ``, - Data: nodeData, - Typ: pbcatalog.NodeType, - ReadOK: resourcetest.DENY, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "node test read": { - Rules: `node "test" { policy = "read" }`, - Data: nodeData, - Typ: pbcatalog.NodeType, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.DENY, - ListOK: resourcetest.DEFAULT, - }, - "node test write": { - Rules: `node "test" { policy = "write" }`, - Data: nodeData, - Typ: pbcatalog.NodeType, - ReadOK: resourcetest.ALLOW, - WriteOK: resourcetest.ALLOW, - ListOK: resourcetest.DEFAULT, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - resourcetest.RunACLTestCase(t, tc, registry) - }) - } -} diff --git a/internal/catalog/internal/types/service.go b/internal/catalog/internal/types/service.go deleted file mode 100644 index bb56fe10a571..000000000000 --- a/internal/catalog/internal/types/service.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "math" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" -) - -type DecodedService = resource.DecodedResource[*pbcatalog.Service] - -func RegisterService(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbcatalog.ServiceType, - Proto: &pbcatalog.Service{}, - Scope: resource.ScopeNamespace, - Validate: ValidateService, - Mutate: MutateService, - ACLs: ACLHooksForWorkloadSelectingType[*pbcatalog.Service](), - }) -} - -var MutateService = resource.DecodeAndMutate(mutateService) - -func mutateService(res *DecodedService) (bool, error) { - changed := false - - // Default service port protocols. - for _, port := range res.Data.Ports { - if port.Protocol == pbcatalog.Protocol_PROTOCOL_UNSPECIFIED { - port.Protocol = pbcatalog.Protocol_PROTOCOL_TCP - changed = true - } - } - - return changed, nil -} - -var ValidateService = resource.DecodeAndValidate(validateService) - -func validateService(res *DecodedService) error { - var err error - - // Validate the workload selector. We are allowing selectors with no - // selection criteria as it will allow for users to manually manage - // ServiceEndpoints objects for this service such as when desiring to - // configure endpoint information for external services that are not - // registered as workloads - if selErr := ValidateSelector(res.Data.Workloads, true); selErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "workloads", - Wrapped: selErr, - }) - } - - usedVirtualPorts := make(map[uint32]int) - - // Validate each port - for idx, port := range res.Data.Ports { - if usedIdx, found := usedVirtualPorts[port.VirtualPort]; found { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "ports", - Index: idx, - Wrapped: resource.ErrInvalidField{ - Name: "virtual_port", - Wrapped: errVirtualPortReused{ - Index: usedIdx, - Value: port.VirtualPort, - }, - }, - }) - } else if port.VirtualPort != 0 { - usedVirtualPorts[port.VirtualPort] = idx - } - - // validate the target port - if nameErr := ValidatePortName(port.TargetPort); nameErr != nil { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "ports", - Index: idx, - Wrapped: resource.ErrInvalidField{ - Name: "target_port", - Wrapped: nameErr, - }, - }) - } - - if protoErr := ValidateProtocol(port.Protocol); protoErr != nil { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "ports", - Index: idx, - Wrapped: resource.ErrInvalidField{ - Name: "protocol", - Wrapped: protoErr, - }, - }) - } - - // validate the virtual port is within the allowed range - 0 is allowed - // to signify that no virtual port should be used and the port will not - // be available for transparent proxying within the mesh. - if port.VirtualPort > math.MaxUint16 { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "ports", - Index: idx, - Wrapped: resource.ErrInvalidField{ - Name: "virtual_port", - Wrapped: errInvalidVirtualPort, - }, - }) - } - - // basic protobuf deserialization should enforce that only known variants of the protocol field are set. - } - - // Validate that the Virtual IPs are all IP addresses - for idx, vip := range res.Data.VirtualIps { - if vipErr := validateIPAddress(vip); vipErr != nil { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "virtual_ips", - Index: idx, - Wrapped: vipErr, - }) - } - } - - return err -} diff --git a/internal/catalog/internal/types/service_endpoints.go b/internal/catalog/internal/types/service_endpoints.go deleted file mode 100644 index b78a1bc705fa..000000000000 --- a/internal/catalog/internal/types/service_endpoints.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "math" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type DecodedServiceEndpoints = resource.DecodedResource[*pbcatalog.ServiceEndpoints] - -func RegisterServiceEndpoints(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbcatalog.ServiceEndpointsType, - Proto: &pbcatalog.ServiceEndpoints{}, - Scope: resource.ScopeNamespace, - Validate: ValidateServiceEndpoints, - Mutate: MutateServiceEndpoints, - ACLs: &resource.ACLHooks{ - Read: func(authorizer acl.Authorizer, context *acl.AuthorizerContext, id *pbresource.ID, _ *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().ServiceReadAllowed(id.GetName(), context) - }, - Write: func(authorizer acl.Authorizer, context *acl.AuthorizerContext, p *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().ServiceWriteAllowed(p.GetId().GetName(), context) - }, - List: resource.NoOpACLListHook, - }, - }) -} - -func MutateServiceEndpoints(res *pbresource.Resource) error { - if res.Owner == nil { - res.Owner = &pbresource.ID{ - Type: pbcatalog.ServiceType, - Tenancy: res.Id.Tenancy, - Name: res.Id.Name, - } - } - - return nil -} - -var ValidateServiceEndpoints = resource.DecodeAndValidate[*pbcatalog.ServiceEndpoints](validateServiceEndpoints) - -func validateServiceEndpoints(res *DecodedServiceEndpoints) error { - var err error - if !resource.EqualType(res.Owner.Type, pbcatalog.ServiceType) { - err = multierror.Append(err, resource.ErrOwnerTypeInvalid{ - ResourceType: pbcatalog.ServiceEndpointsType, - OwnerType: res.Owner.Type, - }) - } - - if !resource.EqualTenancy(res.Owner.Tenancy, res.Id.Tenancy) { - err = multierror.Append(err, resource.ErrOwnerTenantInvalid{ - ResourceType: pbcatalog.ServiceEndpointsType, - ResourceTenancy: res.Id.Tenancy, - OwnerTenancy: res.Owner.Tenancy, - }) - } - - if res.Owner.Name != res.Id.Name { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "name", - Wrapped: errInvalidEndpointsOwnerName{ - Name: res.Id.Name, - OwnerName: res.Owner.Name, - }, - }) - } - - for idx, endpoint := range res.Data.Endpoints { - if endpointErr := validateEndpoint(endpoint, res.Resource); endpointErr != nil { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "endpoints", - Index: idx, - Wrapped: endpointErr, - }) - } - } - - return err -} - -func validateEndpoint(endpoint *pbcatalog.Endpoint, res *pbresource.Resource) error { - var err error - - // Validate the target ref if not nil. When it is nil we are assuming that - // the endpoints are being managed for an external service that has no - // corresponding workloads that Consul has knowledge of. - if endpoint.TargetRef != nil { - // Validate the target reference - if refErr := validateReference(pbcatalog.WorkloadType, res.Id.GetTenancy(), endpoint.TargetRef); refErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "target_ref", - Wrapped: refErr, - }) - } - } - - // Validate the endpoint Addresses - for addrIdx, addr := range endpoint.Addresses { - if addrErr := validateWorkloadAddress(addr, endpoint.Ports); addrErr != nil { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "addresses", - Index: addrIdx, - Wrapped: addrErr, - }) - } - } - - // Ensure that the endpoint has at least 1 port. - if len(endpoint.Ports) < 1 { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "ports", - Wrapped: resource.ErrEmpty, - }) - } - - if healthErr := validateHealth(endpoint.HealthStatus); healthErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "health_status", - Wrapped: healthErr, - }) - } - - // Validate the endpoints ports - for portName, port := range endpoint.Ports { - // Port names must be DNS labels - if portNameErr := ValidatePortName(portName); portNameErr != nil { - err = multierror.Append(err, resource.ErrInvalidMapKey{ - Map: "ports", - Key: portName, - Wrapped: portNameErr, - }) - } - - if protoErr := ValidateProtocol(port.Protocol); protoErr != nil { - err = multierror.Append(err, resource.ErrInvalidMapValue{ - Map: "ports", - Key: portName, - Wrapped: resource.ErrInvalidField{ - Name: "protocol", - Wrapped: protoErr, - }, - }) - } - - // As the physical port is the real port the endpoint will be bound to - // it must be in the standard 1-65535 range. - if port.Port < 1 || port.Port > math.MaxUint16 { - err = multierror.Append(err, resource.ErrInvalidMapValue{ - Map: "ports", - Key: portName, - Wrapped: resource.ErrInvalidField{ - Name: "physical_port", - Wrapped: errInvalidPhysicalPort, - }, - }) - } - } - - return err -} diff --git a/internal/catalog/internal/types/service_endpoints_test.go b/internal/catalog/internal/types/service_endpoints_test.go deleted file mode 100644 index 7a298e397949..000000000000 --- a/internal/catalog/internal/types/service_endpoints_test.go +++ /dev/null @@ -1,304 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -var ( - defaultEndpointTenancy = &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - } - - badEndpointTenancy = &pbresource.Tenancy{ - Partition: "default", - Namespace: "bad", - PeerName: "local", - } -) - -func TestValidateServiceEndpoints_Ok(t *testing.T) { - data := &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: &pbresource.ID{ - Type: pbcatalog.WorkloadType, - Tenancy: defaultEndpointTenancy, - Name: "foo", - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "198.18.0.1", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "foo": { - Port: 8443, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - }, - } - - res := rtest.Resource(pbcatalog.ServiceEndpointsType, "test-service"). - WithTenancy(defaultEndpointTenancy). - WithData(t, data). - Build() - - // fill in owner automatically - require.NoError(t, MutateServiceEndpoints(res)) - - // Now validate that everything is good. - err := ValidateServiceEndpoints(res) - require.NoError(t, err) -} - -func TestValidateServiceEndpoints_ParseError(t *testing.T) { - // Any type other than the ServiceEndpoints type would work - // to cause the error we are expecting - data := &pbcatalog.IP{Address: "198.18.0.1"} - - res := rtest.Resource(pbcatalog.ServiceEndpointsType, "test-service").WithData(t, data).Build() - - err := ValidateServiceEndpoints(res) - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) -} - -func TestValidateServiceEndpoints_EndpointInvalid(t *testing.T) { - genData := func() *pbcatalog.Endpoint { - return &pbcatalog.Endpoint{ - TargetRef: &pbresource.ID{ - Type: pbcatalog.WorkloadType, - Tenancy: defaultEndpointTenancy, - Name: "foo", - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "198.18.0.1", - Ports: []string{"foo"}, - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "foo": { - Port: 42, - }, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - } - } - - type testCase struct { - owner *pbresource.ID - modify func(*pbcatalog.Endpoint) - validateErr func(t *testing.T, err error) - } - - cases := map[string]testCase{ - "invalid-target": { - modify: func(endpoint *pbcatalog.Endpoint) { - endpoint.TargetRef.Type = pbcatalog.NodeType - }, - validateErr: func(t *testing.T, err error) { - require.ErrorIs(t, err, resource.ErrInvalidReferenceType{AllowedType: pbcatalog.WorkloadType}) - }, - }, - "invalid-address": { - modify: func(endpoint *pbcatalog.Endpoint) { - endpoint.Addresses[0].Ports = []string{"bar"} - }, - validateErr: func(t *testing.T, err error) { - require.ErrorIs(t, err, errInvalidPortReference{Name: "bar"}) - }, - }, - "no-ports": { - modify: func(endpoint *pbcatalog.Endpoint) { - endpoint.Ports = nil - }, - validateErr: func(t *testing.T, err error) { - require.ErrorIs(t, err, resource.ErrEmpty) - }, - }, - "invalid-health-status": { - modify: func(endpoint *pbcatalog.Endpoint) { - endpoint.Ports["foo"] = &pbcatalog.WorkloadPort{ - Port: 42, - } - endpoint.HealthStatus = 99 - }, - validateErr: func(t *testing.T, err error) { - rtest.RequireError(t, err, resource.ErrInvalidField{ - Name: "health_status", - Wrapped: resource.NewConstError("not a supported enum value: 99"), - }) - }, - }, - "invalid-port-name": { - modify: func(endpoint *pbcatalog.Endpoint) { - endpoint.Ports[""] = &pbcatalog.WorkloadPort{ - Port: 42, - } - }, - validateErr: func(t *testing.T, err error) { - rtest.RequireError(t, err, resource.ErrInvalidMapKey{ - Map: "ports", - Key: "", - Wrapped: resource.ErrEmpty, - }) - }, - }, - "invalid-port-protocol": { - modify: func(endpoint *pbcatalog.Endpoint) { - endpoint.Ports["foo"] = &pbcatalog.WorkloadPort{ - Port: 42, - Protocol: 99, - } - }, - validateErr: func(t *testing.T, err error) { - rtest.RequireError(t, err, resource.ErrInvalidMapValue{ - Map: "ports", - Key: "foo", - Wrapped: resource.ErrInvalidField{ - Name: "protocol", - Wrapped: resource.NewConstError("not a supported enum value: 99"), - }, - }) - }, - }, - "port-0": { - modify: func(endpoint *pbcatalog.Endpoint) { - endpoint.Ports["foo"].Port = 0 - }, - validateErr: func(t *testing.T, err error) { - require.ErrorIs(t, err, errInvalidPhysicalPort) - }, - }, - "port-out-of-range": { - modify: func(endpoint *pbcatalog.Endpoint) { - endpoint.Ports["foo"].Port = 65536 - }, - validateErr: func(t *testing.T, err error) { - require.ErrorIs(t, err, errInvalidPhysicalPort) - }, - }, - "invalid-owner": { - owner: &pbresource.ID{ - Type: pbcatalog.DNSPolicyType, - Tenancy: badEndpointTenancy, - Name: "wrong", - }, - validateErr: func(t *testing.T, err error) { - rtest.RequireError(t, err, resource.ErrOwnerTypeInvalid{ - ResourceType: pbcatalog.ServiceEndpointsType, - OwnerType: pbcatalog.DNSPolicyType}) - rtest.RequireError(t, err, resource.ErrOwnerTenantInvalid{ - ResourceType: pbcatalog.ServiceEndpointsType, - ResourceTenancy: defaultEndpointTenancy, - OwnerTenancy: badEndpointTenancy, - }) - rtest.RequireError(t, err, resource.ErrInvalidField{ - Name: "name", - Wrapped: errInvalidEndpointsOwnerName{ - Name: "test-service", - OwnerName: "wrong"}, - }) - }, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - endpoint := genData() - if tcase.modify != nil { - tcase.modify(endpoint) - } - - data := &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - endpoint, - }, - } - res := rtest.Resource(pbcatalog.ServiceEndpointsType, "test-service"). - WithTenancy(defaultEndpointTenancy). - WithOwner(tcase.owner). - WithData(t, data). - Build() - - // Run the mututation to setup defaults - require.NoError(t, MutateServiceEndpoints(res)) - - err := ValidateServiceEndpoints(res) - require.Error(t, err) - tcase.validateErr(t, err) - }) - } -} - -func TestMutateServiceEndpoints_PopulateOwner(t *testing.T) { - res := rtest.Resource(pbcatalog.ServiceEndpointsType, "test-service"). - WithTenancy(defaultEndpointTenancy). - Build() - - require.NoError(t, MutateServiceEndpoints(res)) - require.NotNil(t, res.Owner) - require.True(t, resource.EqualType(res.Owner.Type, pbcatalog.ServiceType)) - require.True(t, resource.EqualTenancy(res.Owner.Tenancy, defaultEndpointTenancy)) - require.Equal(t, res.Owner.Name, res.Id.Name) -} - -func TestServiceEndpointsACLs(t *testing.T) { - registry := resource.NewRegistry() - Register(registry) - - service := rtest.Resource(pbcatalog.ServiceType, "test"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID() - serviceEndpointsData := &pbcatalog.ServiceEndpoints{} - cases := map[string]rtest.ACLTestCase{ - "no rules": { - Rules: ``, - Data: serviceEndpointsData, - Owner: service, - Typ: pbcatalog.ServiceEndpointsType, - ReadOK: rtest.DENY, - WriteOK: rtest.DENY, - ListOK: rtest.DEFAULT, - }, - "service test read": { - Rules: `service "test" { policy = "read" }`, - Data: serviceEndpointsData, - Owner: service, - Typ: pbcatalog.ServiceEndpointsType, - ReadOK: rtest.ALLOW, - WriteOK: rtest.DENY, - ListOK: rtest.DEFAULT, - }, - "service test write": { - Rules: `service "test" { policy = "write" }`, - Data: serviceEndpointsData, - Owner: service, - Typ: pbcatalog.ServiceEndpointsType, - ReadOK: rtest.ALLOW, - WriteOK: rtest.ALLOW, - ListOK: rtest.DEFAULT, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - rtest.RunACLTestCase(t, tc, registry) - }) - } -} diff --git a/internal/catalog/internal/types/service_test.go b/internal/catalog/internal/types/service_test.go deleted file mode 100644 index 18649dda9a0a..000000000000 --- a/internal/catalog/internal/types/service_test.go +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/catalog/internal/testhelpers" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func createServiceResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { - res := &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.ServiceType, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: "test-policy", - }, - } - - var err error - res.Data, err = anypb.New(data) - require.NoError(t, err) - return res -} - -func TestMutateServicePorts(t *testing.T) { - data := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"foo", "bar"}, - }, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "tcp", - Protocol: pbcatalog.Protocol_PROTOCOL_UNSPECIFIED, - }, - { - TargetPort: "http", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - VirtualIps: []string{"198.18.0.1"}, - } - - res := createServiceResource(t, data) - - err := MutateService(res) - require.NoError(t, err) - - got := resourcetest.MustDecode[*pbcatalog.Service](t, res) - - require.Len(t, got.Data.Ports, 2) - require.Equal(t, pbcatalog.Protocol_PROTOCOL_TCP, got.Data.Ports[0].Protocol) - - // Check that specified protocol is not mutated. - require.Equal(t, data.Ports[1].Protocol, got.Data.Ports[1].Protocol) -} - -func TestValidateService_Ok(t *testing.T) { - data := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"foo", "bar"}, - Prefixes: []string{"abc-"}, - }, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "http-internal", - VirtualPort: 42, - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "other", - // leaving VirtualPort unset to verify that seeing - // a zero virtual port multiple times is fine. - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, - }, - { - TargetPort: "other2", - // leaving VirtualPort unset to verify that seeing - // a zero virtual port multiple times is fine. - Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, - }, - }, - VirtualIps: []string{"198.18.0.1"}, - } - - res := createServiceResource(t, data) - - err := ValidateService(res) - require.NoError(t, err) -} - -func TestValidateService_ParseError(t *testing.T) { - // Any type other than the Service type would work - // to cause the error we are expecting - data := &pbcatalog.IP{Address: "198.18.0.1"} - - res := createServiceResource(t, data) - - err := ValidateService(res) - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) -} - -func TestValidateService_EmptySelector(t *testing.T) { - data := &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "http-internal", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - - res := createServiceResource(t, data) - - err := ValidateService(res) - require.NoError(t, err) -} - -func TestValidateService_InvalidSelector(t *testing.T) { - data := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{""}, - }, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "http-internal", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - - res := createServiceResource(t, data) - - err := ValidateService(res) - expected := resource.ErrInvalidListElement{ - Name: "names", - Index: 0, - Wrapped: resource.ErrEmpty, - } - - var actual resource.ErrInvalidListElement - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateService_InvalidTargetPort(t *testing.T) { - data := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "", - }, - }, - } - - res := createServiceResource(t, data) - - err := ValidateService(res) - require.Error(t, err) - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, "target_port", actual.Name) - require.Equal(t, resource.ErrEmpty, actual.Wrapped) -} - -func TestValidateService_VirtualPortReused(t *testing.T) { - data := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - Ports: []*pbcatalog.ServicePort{ - { - VirtualPort: 42, - TargetPort: "foo", - }, - { - VirtualPort: 42, - TargetPort: "bar", - }, - }, - } - - res := createServiceResource(t, data) - - err := ValidateService(res) - require.Error(t, err) - var actual errVirtualPortReused - require.ErrorAs(t, err, &actual) - require.EqualValues(t, 0, actual.Index) - require.EqualValues(t, 42, actual.Value) -} - -func TestValidateService_InvalidPortProtocol(t *testing.T) { - data := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "foo", - Protocol: 99, - }, - }, - } - - res := createServiceResource(t, data) - - err := ValidateService(res) - - expected := resource.ErrInvalidListElement{ - Name: "ports", - Index: 0, - Wrapped: resource.ErrInvalidField{ - Name: "protocol", - Wrapped: resource.NewConstError("not a supported enum value: 99"), - }, - } - - var actual resource.ErrInvalidListElement - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateService_VirtualPortInvalid(t *testing.T) { - data := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - Ports: []*pbcatalog.ServicePort{ - { - VirtualPort: 100000, - TargetPort: "foo", - }, - }, - } - - res := createServiceResource(t, data) - - err := ValidateService(res) - require.Error(t, err) - require.ErrorIs(t, err, errInvalidVirtualPort) -} - -func TestValidateService_InvalidVIP(t *testing.T) { - data := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{""}, - }, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "foo", - }, - }, - VirtualIps: []string{"foo"}, - } - - res := createServiceResource(t, data) - - err := ValidateService(res) - require.Error(t, err) - require.ErrorIs(t, err, errNotIPAddress) -} - -func TestServiceACLs(t *testing.T) { - testhelpers.RunWorkloadSelectingTypeACLsTests[*pbcatalog.Service](t, pbcatalog.ServiceType, - func(selector *pbcatalog.WorkloadSelector) *pbcatalog.Service { - return &pbcatalog.Service{Workloads: selector} - }, - RegisterService, - ) -} diff --git a/internal/catalog/internal/types/testdata/errDNSPassingWeightOutOfRange.golden b/internal/catalog/internal/types/testdata/errDNSPassingWeightOutOfRange.golden deleted file mode 100644 index c364e6a17571..000000000000 --- a/internal/catalog/internal/types/testdata/errDNSPassingWeightOutOfRange.golden +++ /dev/null @@ -1 +0,0 @@ -DNS passing weight is outside of the range 1 to 65535 \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errDNSWarningWeightOutOfRange.golden b/internal/catalog/internal/types/testdata/errDNSWarningWeightOutOfRange.golden deleted file mode 100644 index 0457e418b45c..000000000000 --- a/internal/catalog/internal/types/testdata/errDNSWarningWeightOutOfRange.golden +++ /dev/null @@ -1 +0,0 @@ -DNS warning weight is outside the range 0 to 65535 \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errInvalidEndpointsOwnerName.golden b/internal/catalog/internal/types/testdata/errInvalidEndpointsOwnerName.golden deleted file mode 100644 index 38fc896f57e3..000000000000 --- a/internal/catalog/internal/types/testdata/errInvalidEndpointsOwnerName.golden +++ /dev/null @@ -1 +0,0 @@ -invalid owner name "bar". ServiceEndpoints objects must be owned by a Service with the same name: "foo" \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errInvalidNodeHostFormat.golden b/internal/catalog/internal/types/testdata/errInvalidNodeHostFormat.golden deleted file mode 100644 index 6eb2e24ebdf4..000000000000 --- a/internal/catalog/internal/types/testdata/errInvalidNodeHostFormat.golden +++ /dev/null @@ -1 +0,0 @@ -"unix:///node.sock" is not an IP address or a DNS name. \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errInvalidPhysicalPort.golden b/internal/catalog/internal/types/testdata/errInvalidPhysicalPort.golden deleted file mode 100644 index eb971cb8a399..000000000000 --- a/internal/catalog/internal/types/testdata/errInvalidPhysicalPort.golden +++ /dev/null @@ -1 +0,0 @@ -port number is outside the range 1 to 65535 \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errInvalidPortReference.golden b/internal/catalog/internal/types/testdata/errInvalidPortReference.golden deleted file mode 100644 index 3a165011c512..000000000000 --- a/internal/catalog/internal/types/testdata/errInvalidPortReference.golden +++ /dev/null @@ -1 +0,0 @@ -port with name "http" has not been defined \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errInvalidVirtualPort.golden b/internal/catalog/internal/types/testdata/errInvalidVirtualPort.golden deleted file mode 100644 index 2cabd9cb28a0..000000000000 --- a/internal/catalog/internal/types/testdata/errInvalidVirtualPort.golden +++ /dev/null @@ -1 +0,0 @@ -port number is outside the range 0 to 65535 \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errInvalidWorkloadHostFormat.golden b/internal/catalog/internal/types/testdata/errInvalidWorkloadHostFormat.golden deleted file mode 100644 index eb57dc2ef03c..000000000000 --- a/internal/catalog/internal/types/testdata/errInvalidWorkloadHostFormat.golden +++ /dev/null @@ -1 +0,0 @@ -"-foo-bar-" is not an IP address, Unix socket path or a DNS name. \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errLocalityZoneNoRegion.golden b/internal/catalog/internal/types/testdata/errLocalityZoneNoRegion.golden deleted file mode 100644 index 9a6ec59d0861..000000000000 --- a/internal/catalog/internal/types/testdata/errLocalityZoneNoRegion.golden +++ /dev/null @@ -1 +0,0 @@ -locality region cannot be empty if the zone is set \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errNotDNSLabel.golden b/internal/catalog/internal/types/testdata/errNotDNSLabel.golden deleted file mode 100644 index a5866fbbf0f2..000000000000 --- a/internal/catalog/internal/types/testdata/errNotDNSLabel.golden +++ /dev/null @@ -1 +0,0 @@ -value must match regex: ^[a-z0-9]([a-z0-9\-_]*[a-z0-9])?$ \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errNotIPAddress.golden b/internal/catalog/internal/types/testdata/errNotIPAddress.golden deleted file mode 100644 index db33684367df..000000000000 --- a/internal/catalog/internal/types/testdata/errNotIPAddress.golden +++ /dev/null @@ -1 +0,0 @@ -value is not a valid IP address \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errTooMuchMesh.golden b/internal/catalog/internal/types/testdata/errTooMuchMesh.golden deleted file mode 100644 index 48ce0969d82d..000000000000 --- a/internal/catalog/internal/types/testdata/errTooMuchMesh.golden +++ /dev/null @@ -1 +0,0 @@ -protocol "mesh" was specified in more than 1 port: [http grpc] \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errUnixSocketMultiport.golden b/internal/catalog/internal/types/testdata/errUnixSocketMultiport.golden deleted file mode 100644 index c28c2f069509..000000000000 --- a/internal/catalog/internal/types/testdata/errUnixSocketMultiport.golden +++ /dev/null @@ -1 +0,0 @@ -Unix socket address references more than one port \ No newline at end of file diff --git a/internal/catalog/internal/types/testdata/errVirtualPortReused.golden b/internal/catalog/internal/types/testdata/errVirtualPortReused.golden deleted file mode 100644 index 5a8c8b799b08..000000000000 --- a/internal/catalog/internal/types/testdata/errVirtualPortReused.golden +++ /dev/null @@ -1 +0,0 @@ -virtual port 8080 was previously assigned at index 3 \ No newline at end of file diff --git a/internal/catalog/internal/types/types.go b/internal/catalog/internal/types/types.go deleted file mode 100644 index 15ed6b148de7..000000000000 --- a/internal/catalog/internal/types/types.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/internal/resource" -) - -func Register(r resource.Registry) { - RegisterWorkload(r) - RegisterService(r) - RegisterServiceEndpoints(r) - RegisterNode(r) - RegisterHealthStatus(r) - RegisterFailoverPolicy(r) - - // todo (v2): re-register once these resources are implemented. - //RegisterHealthChecks(r) - //RegisterDNSPolicy(r) - //RegisterVirtualIPs(r) -} diff --git a/internal/catalog/internal/types/types_test.go b/internal/catalog/internal/types/types_test.go deleted file mode 100644 index 4facd921c368..000000000000 --- a/internal/catalog/internal/types/types_test.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func TestTypeRegistration(t *testing.T) { - // This test will ensure that all the required types have been registered - // It is not trying to determine whether the settings for the registrations - // are correct as that would amount more or less to hardcoding structs - // from types.go a second time here. - requiredKinds := []string{ - pbcatalog.WorkloadKind, - pbcatalog.ServiceKind, - pbcatalog.ServiceEndpointsKind, - pbcatalog.NodeKind, - pbcatalog.HealthStatusKind, - // todo (ishustava): uncomment once we implement these - //pbcatalog.HealthChecksKind, - //pbcatalog.DNSPolicyKind, - //pbcatalog.VirtualIPsKind, - } - - r := resource.NewRegistry() - Register(r) - - for _, kind := range requiredKinds { - t.Run(kind, func(t *testing.T) { - registration, ok := r.Resolve(&pbresource.Type{ - Group: pbcatalog.GroupName, - GroupVersion: pbcatalog.Version, - Kind: kind, - }) - - require.True(t, ok, "Resource kind %s has not been registered to the type registry", kind) - require.NotNil(t, registration, "Registration for %s was found but is nil", kind) - }) - } -} diff --git a/internal/catalog/internal/types/validators.go b/internal/catalog/internal/types/validators.go deleted file mode 100644 index 07dfbd356967..000000000000 --- a/internal/catalog/internal/types/validators.go +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" - "net" - "regexp" - "strings" - - "github.com/hashicorp/go-multierror" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - // 108 characters is the max size that Linux (and probably other OSes) will - // allow for the length of the Unix socket path. - maxUnixSocketPathLen = 108 -) - -var ( - dnsLabelRegex = `^[a-z0-9]([a-z0-9\-_]*[a-z0-9])?$` - dnsLabelMatcher = regexp.MustCompile(dnsLabelRegex) -) - -func isValidIPAddress(host string) bool { - return net.ParseIP(host) != nil -} - -func isValidDNSName(host string) bool { - if len(host) > 256 { - return false - } - - labels := strings.Split(host, ".") - for _, label := range labels { - if !isValidDNSLabel(label) { - return false - } - } - - return true -} - -func isValidDNSLabel(label string) bool { - if len(label) > 64 { - return false - } - - return dnsLabelMatcher.Match([]byte(label)) -} - -func IsValidUnixSocketPath(host string) bool { - if len(host) > maxUnixSocketPathLen || !strings.HasPrefix(host, "unix://") || strings.Contains(host, "\000") { - return false - } - - return true -} - -func validateWorkloadHost(host string) error { - // Check that the host is empty - if host == "" { - return errInvalidWorkloadHostFormat{Host: host} - } - - // Check if the host represents an IP address, unix socket path or a DNS name - if !isValidIPAddress(host) && !IsValidUnixSocketPath(host) && !isValidDNSName(host) { - return errInvalidWorkloadHostFormat{Host: host} - } - - return nil -} - -func ValidateSelector(sel *pbcatalog.WorkloadSelector, allowEmpty bool) error { - if sel == nil { - if allowEmpty { - return nil - } - - return resource.ErrEmpty - } - - if len(sel.Names) == 0 && len(sel.Prefixes) == 0 { - if !allowEmpty { - return resource.ErrEmpty - } - - if sel.Filter != "" { - return resource.ErrInvalidField{ - Name: "filter", - Wrapped: errors.New("filter cannot be set unless there is a name or prefix selector"), - } - } - return nil - } - - var merr error - - // Validate that all the exact match names are non-empty. This is - // mostly for the sake of not admitting values that should always - // be meaningless and never actually cause selection of a workload. - // This is because workloads must have non-empty names. - for idx, name := range sel.Names { - if name == "" { - merr = multierror.Append(merr, resource.ErrInvalidListElement{ - Name: "names", - Index: idx, - Wrapped: resource.ErrEmpty, - }) - } - } - - if err := resource.ValidateMetadataFilter(sel.GetFilter()); err != nil { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "filter", - Wrapped: err, - }) - } - - return merr -} - -func validateIPAddress(ip string) error { - if ip == "" { - return resource.ErrEmpty - } - - if !isValidIPAddress(ip) { - return errNotIPAddress - } - - return nil -} - -func ValidatePortName(name string) error { - if name == "" { - return resource.ErrEmpty - } - - if !isValidDNSLabel(name) { - return errNotDNSLabel - } - - return nil -} - -func ValidateProtocol(protocol pbcatalog.Protocol) error { - // enumcover:pbcatalog.Protocol - switch protocol { - case pbcatalog.Protocol_PROTOCOL_UNSPECIFIED, - // means pbcatalog.FailoverMode_FAILOVER_MODE_TCP - pbcatalog.Protocol_PROTOCOL_TCP, - pbcatalog.Protocol_PROTOCOL_HTTP, - pbcatalog.Protocol_PROTOCOL_HTTP2, - pbcatalog.Protocol_PROTOCOL_GRPC, - pbcatalog.Protocol_PROTOCOL_MESH: - return nil - default: - return resource.NewConstError(fmt.Sprintf("not a supported enum value: %v", protocol)) - } -} - -// validateWorkloadAddress will validate the WorkloadAddress type. This involves validating -// the Host within the workload address and the ports references. For ports references we -// ensure that values in the addresses ports array are present in the set of map keys. -// Additionally for UNIX socket addresses we ensure that they specify only 1 port either -// explicitly in their ports references or implicitly by omitting the references and there -// only being 1 value in the ports map. -func validateWorkloadAddress(addr *pbcatalog.WorkloadAddress, ports map[string]*pbcatalog.WorkloadPort) error { - var err error - - if hostErr := validateWorkloadHost(addr.Host); hostErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "host", - Wrapped: hostErr, - }) - } - - // Ensure that unix sockets reference exactly 1 port. They may also indirectly reference 1 port - // by the workload having only a single port and omitting any explicit port assignment. - if IsValidUnixSocketPath(addr.Host) && - (len(addr.Ports) > 1 || (len(addr.Ports) == 0 && len(ports) > 1)) { - err = multierror.Append(err, errUnixSocketMultiport) - } - - // Check that all referenced ports exist - for idx, port := range addr.Ports { - _, found := ports[port] - if !found { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "ports", - Index: idx, - Wrapped: errInvalidPortReference{Name: port}, - }) - } - } - return err -} - -func validateReferenceType(allowed *pbresource.Type, check *pbresource.Type) error { - if allowed.Group == check.Group && - allowed.GroupVersion == check.GroupVersion && - allowed.Kind == check.Kind { - return nil - } - - return resource.ErrInvalidReferenceType{ - AllowedType: allowed, - } -} - -func validateReferenceTenancy(allowed *pbresource.Tenancy, check *pbresource.Tenancy) error { - if proto.Equal(allowed, check) { - return nil - } - - return resource.ErrReferenceTenancyNotEqual -} - -func validateReference(allowedType *pbresource.Type, allowedTenancy *pbresource.Tenancy, check *pbresource.ID) error { - var err error - - // Validate the references type is the allowed type. - if typeErr := validateReferenceType(allowedType, check.GetType()); typeErr != nil { - err = multierror.Append(err, typeErr) - } - - // Validate the references tenancy matches the allowed tenancy. - if tenancyErr := validateReferenceTenancy(allowedTenancy, check.GetTenancy()); tenancyErr != nil { - err = multierror.Append(err, tenancyErr) - } - - return err -} - -func validateHealth(health pbcatalog.Health) error { - // enumcover:pbcatalog.Health - switch health { - case pbcatalog.Health_HEALTH_ANY, - pbcatalog.Health_HEALTH_PASSING, - pbcatalog.Health_HEALTH_WARNING, - pbcatalog.Health_HEALTH_CRITICAL, - pbcatalog.Health_HEALTH_MAINTENANCE: - return nil - default: - return resource.NewConstError(fmt.Sprintf("not a supported enum value: %v", health)) - } -} - -// ValidateLocalServiceRefNoSection ensures the following: -// -// - ref is non-nil -// - type is ServiceType -// - section is empty -// - tenancy is set and partition/namespace are both non-empty -// - peer_name must be "local" -// -// Each possible validation error is wrapped in the wrapErr function before -// being collected in a multierror.Error. -func ValidateLocalServiceRefNoSection(ref *pbresource.Reference, wrapErr func(error) error) error { - if ref == nil { - return wrapErr(resource.ErrMissing) - } - - if !resource.EqualType(ref.Type, pbcatalog.ServiceType) { - return wrapErr(resource.ErrInvalidField{ - Name: "type", - Wrapped: resource.ErrInvalidReferenceType{ - AllowedType: pbcatalog.ServiceType, - }, - }) - } - - var merr error - if ref.Section != "" { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "section", - Wrapped: errors.New("section cannot be set here"), - })) - } - - if ref.Tenancy == nil { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "tenancy", - Wrapped: resource.ErrMissing, - })) - } else { - // NOTE: these are Service specific, since that's a Namespace-scoped type. - if ref.Tenancy.Partition == "" { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "tenancy", - Wrapped: resource.ErrInvalidField{ - Name: "partition", - Wrapped: resource.ErrEmpty, - }, - })) - } - if ref.Tenancy.Namespace == "" { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "tenancy", - Wrapped: resource.ErrInvalidField{ - Name: "namespace", - Wrapped: resource.ErrEmpty, - }, - })) - } - if ref.Tenancy.PeerName != "local" { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "tenancy", - Wrapped: resource.ErrInvalidField{ - Name: "peer_name", - Wrapped: errors.New(`must be set to "local"`), - }, - })) - } - } - - if ref.Name == "" { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "name", - Wrapped: resource.ErrMissing, - })) - } - - return merr -} diff --git a/internal/catalog/internal/types/validators_test.go b/internal/catalog/internal/types/validators_test.go deleted file mode 100644 index 7a334727a998..000000000000 --- a/internal/catalog/internal/types/validators_test.go +++ /dev/null @@ -1,635 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" - "strings" - "testing" - - "github.com/hashicorp/go-multierror" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func TestIsValidDNSLabel(t *testing.T) { - type testCase struct { - name string - valid bool - } - - cases := map[string]testCase{ - "min-length": { - name: "a", - valid: true, - }, - "max-length": { - name: strings.Repeat("a1b2c3d4", 8), - valid: true, - }, - "underscores": { - name: "has_underscores", - valid: true, - }, - "hyphenated": { - name: "has-hyphen3", - valid: true, - }, - "uppercase-not-allowed": { - name: "UPPERCASE", - valid: false, - }, - "numeric-start": { - name: "1abc", - valid: true, - }, - "underscore-start-not-allowed": { - name: "_abc", - valid: false, - }, - "hyphen-start-not-allowed": { - name: "-abc", - valid: false, - }, - "underscore-end-not-allowed": { - name: "abc_", - valid: false, - }, - "hyphen-end-not-allowed": { - name: "abc-", - valid: false, - }, - "unicode-not allowed": { - name: "abc∑", - valid: false, - }, - "too-long": { - name: strings.Repeat("aaaaaaaaa", 8), - valid: false, - }, - "missing-name": { - name: "", - valid: false, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - require.Equal(t, tcase.valid, isValidDNSLabel(tcase.name)) - }) - } -} - -func TestIsValidDNSName(t *testing.T) { - // TestIsValidDNSLabel tests all of the individual label matching - // criteria. This test therefore is more limited to just the extra - // validations that IsValidDNSName does. Mainly that it ensures - // the overall length is less than 256 and that generally is made - // up of DNS labels joined with '.' - - type testCase struct { - name string - valid bool - } - - cases := map[string]testCase{ - "valid": { - name: "foo-something.example3.com", - valid: true, - }, - "exceeds-max-length": { - name: strings.Repeat("aaaa.aaaa", 29), - valid: false, - }, - "invalid-label": { - name: "foo._bar.com", - valid: false, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - require.Equal(t, tcase.valid, isValidDNSName(tcase.name)) - }) - } -} - -func TestIsValidIPAddress(t *testing.T) { - type testCase struct { - name string - valid bool - } - - cases := map[string]testCase{ - "ipv4": { - name: "192.168.1.2", - valid: true, - }, - "ipv6": { - name: "2001:db8::1", - valid: true, - }, - "ipv4-mapped-ipv6": { - name: "::ffff:192.0.2.128", - valid: true, - }, - "invalid": { - name: "foo", - valid: false, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - require.Equal(t, tcase.valid, isValidIPAddress(tcase.name)) - }) - } -} - -func TestIsValidUnixSocketPath(t *testing.T) { - type testCase struct { - name string - valid bool - } - - cases := map[string]testCase{ - "valid": { - name: "unix:///foo/bar.sock", - valid: true, - }, - "missing-prefix": { - name: "/foo/bar.sock", - valid: false, - }, - "too-long": { - name: fmt.Sprintf("unix://%s/bar.sock", strings.Repeat("/aaaaaaaaaa", 11)), - valid: false, - }, - "nul-in-name": { - name: "unix:///foo/bar\000sock", - valid: false, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - require.Equal(t, tcase.valid, IsValidUnixSocketPath(tcase.name)) - }) - } -} - -func TestValidateHost(t *testing.T) { - type testCase struct { - name string - valid bool - } - - cases := map[string]testCase{ - "ip-address": { - name: "198.18.0.1", - valid: true, - }, - "unix-socket": { - name: "unix:///foo.sock", - valid: true, - }, - "dns-name": { - name: "foo.com", - valid: true, - }, - "host-empty": { - name: "", - valid: false, - }, - "host-invalid": { - name: "unix:///foo/bar\000sock", - valid: false, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - err := validateWorkloadHost(tcase.name) - if tcase.valid { - require.NoError(t, err) - } else { - require.Error(t, err) - require.Equal(t, errInvalidWorkloadHostFormat{Host: tcase.name}, err) - } - }) - } -} - -func TestValidateSelector(t *testing.T) { - type testCase struct { - selector *pbcatalog.WorkloadSelector - allowEmpty bool - err error - } - - cases := map[string]testCase{ - "nil-disallowed": { - selector: nil, - allowEmpty: false, - err: resource.ErrEmpty, - }, - "nil-allowed": { - selector: nil, - allowEmpty: true, - err: nil, - }, - "empty-allowed": { - selector: &pbcatalog.WorkloadSelector{}, - allowEmpty: true, - err: nil, - }, - "empty-disallowed": { - selector: &pbcatalog.WorkloadSelector{}, - allowEmpty: false, - err: resource.ErrEmpty, - }, - "ok": { - selector: &pbcatalog.WorkloadSelector{ - Names: []string{"foo", "bar"}, - Prefixes: []string{"foo", "bar"}, - }, - allowEmpty: false, - err: nil, - }, - "empty-name": { - selector: &pbcatalog.WorkloadSelector{ - Names: []string{"", "bar", ""}, - Prefixes: []string{"foo", "bar"}, - }, - allowEmpty: false, - err: &multierror.Error{ - Errors: []error{ - resource.ErrInvalidListElement{ - Name: "names", - Index: 0, - Wrapped: resource.ErrEmpty, - }, - resource.ErrInvalidListElement{ - Name: "names", - Index: 2, - Wrapped: resource.ErrEmpty, - }, - }, - }, - }, - "filter-with-empty-query": { - selector: &pbcatalog.WorkloadSelector{ - Filter: "garbage.value == zzz", - }, - allowEmpty: true, - err: resource.ErrInvalidField{ - Name: "filter", - Wrapped: errors.New( - `filter cannot be set unless there is a name or prefix selector`, - ), - }, - }, - "bad-filter": { - selector: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo", "bar"}, - Filter: "garbage.value == zzz", - }, - allowEmpty: false, - err: &multierror.Error{ - Errors: []error{ - resource.ErrInvalidField{ - Name: "filter", - Wrapped: fmt.Errorf( - `filter "garbage.value == zzz" is invalid: %w`, - errors.New(`Selector "garbage" is not valid`), - ), - }, - }, - }, - }, - "good-filter": { - selector: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo", "bar"}, - Filter: "metadata.zone == west1", - }, - allowEmpty: false, - err: nil, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - err := ValidateSelector(tcase.selector, tcase.allowEmpty) - if tcase.err == nil { - require.NoError(t, err) - } else { - require.Error(t, err) - require.Equal(t, tcase.err, err) - } - }) - } -} - -func TestValidateIPAddress(t *testing.T) { - // this test does not perform extensive validation of what constitutes - // an IP address. Instead that is handled in the test for the - // isValidIPAddress function - - t.Run("empty", func(t *testing.T) { - require.Equal(t, resource.ErrEmpty, validateIPAddress("")) - }) - - t.Run("invalid", func(t *testing.T) { - require.Equal(t, errNotIPAddress, validateIPAddress("foo.com")) - }) - - t.Run("ok", func(t *testing.T) { - require.NoError(t, validateIPAddress("192.168.0.1")) - }) -} - -func TestValidatePortName(t *testing.T) { - // this test does not perform extensive validation of what constitutes - // a valid port name. In general the criteria is that it must not - // be empty and must be a valid DNS label. Therefore extensive testing - // of what it means to be a valid DNS label is performed within the - // test for the isValidDNSLabel function. - - t.Run("empty", func(t *testing.T) { - require.Equal(t, resource.ErrEmpty, ValidatePortName("")) - }) - - t.Run("invalid", func(t *testing.T) { - require.Equal(t, errNotDNSLabel, ValidatePortName("foo.com")) - }) - - t.Run("ok", func(t *testing.T) { - require.NoError(t, ValidatePortName("http")) - }) -} - -func TestValidateWorkloadAddress(t *testing.T) { - type testCase struct { - addr *pbcatalog.WorkloadAddress - ports map[string]*pbcatalog.WorkloadPort - validateErr func(*testing.T, error) - } - - cases := map[string]testCase{ - "invalid-host": { - addr: &pbcatalog.WorkloadAddress{ - Host: "-blarg", - }, - ports: map[string]*pbcatalog.WorkloadPort{}, - validateErr: func(t *testing.T, err error) { - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, "host", actual.Name) - }, - }, - "unix-socket-multiport-explicit": { - addr: &pbcatalog.WorkloadAddress{ - Host: "unix:///foo.sock", - Ports: []string{"foo", "bar"}, - }, - ports: map[string]*pbcatalog.WorkloadPort{ - "foo": {}, - "bar": {}, - }, - validateErr: func(t *testing.T, err error) { - require.ErrorIs(t, err, errUnixSocketMultiport) - }, - }, - "unix-socket-multiport-implicit": { - addr: &pbcatalog.WorkloadAddress{ - Host: "unix:///foo.sock", - }, - ports: map[string]*pbcatalog.WorkloadPort{ - "foo": {}, - "bar": {}, - }, - validateErr: func(t *testing.T, err error) { - require.ErrorIs(t, err, errUnixSocketMultiport) - }, - }, - - "unix-socket-singleport": { - addr: &pbcatalog.WorkloadAddress{ - Host: "unix:///foo.sock", - Ports: []string{"foo"}, - }, - ports: map[string]*pbcatalog.WorkloadPort{ - "foo": {}, - "bar": {}, - }, - }, - "invalid-port-reference": { - addr: &pbcatalog.WorkloadAddress{ - Host: "198.18.0.1", - Ports: []string{"foo"}, - }, - ports: map[string]*pbcatalog.WorkloadPort{ - "http": {}, - }, - validateErr: func(t *testing.T, err error) { - var actual errInvalidPortReference - require.ErrorAs(t, err, &actual) - require.Equal(t, "foo", actual.Name) - }, - }, - "ok": { - addr: &pbcatalog.WorkloadAddress{ - Host: "198.18.0.1", - Ports: []string{"http", "grpc"}, - External: true, - }, - ports: map[string]*pbcatalog.WorkloadPort{ - "http": {}, - "grpc": {}, - }, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - err := validateWorkloadAddress(tcase.addr, tcase.ports) - if tcase.validateErr != nil { - require.Error(t, err) - tcase.validateErr(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func TestValidateReferenceType(t *testing.T) { - allowedType := &pbresource.Type{ - Group: "foo", - GroupVersion: "v1", - Kind: "Bar", - } - - type testCase struct { - check *pbresource.Type - err bool - } - - cases := map[string]testCase{ - "ok": { - check: allowedType, - err: false, - }, - "group-mismatch": { - check: &pbresource.Type{ - Group: "food", - GroupVersion: "v1", - Kind: "Bar", - }, - err: true, - }, - "group-version-mismatch": { - check: &pbresource.Type{ - Group: "foo", - GroupVersion: "v2", - Kind: "Bar", - }, - err: true, - }, - "kind-mismatch": { - check: &pbresource.Type{ - Group: "foo", - GroupVersion: "v1", - Kind: "Baz", - }, - err: true, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - err := validateReferenceType(allowedType, tcase.check) - if tcase.err { - require.Equal(t, resource.ErrInvalidReferenceType{AllowedType: allowedType}, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func TestValidateReferenceTenancy(t *testing.T) { - allowedTenancy := &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - } - - type testCase struct { - check *pbresource.Tenancy - err bool - } - - cases := map[string]testCase{ - "ok": { - check: allowedTenancy, - err: false, - }, - "partition-mismatch": { - check: &pbresource.Tenancy{ - Partition: "food", - Namespace: "default", - PeerName: "local", - }, - err: true, - }, - "group-version-mismatch": { - check: &pbresource.Tenancy{ - Partition: "default", - Namespace: "v2", - PeerName: "local", - }, - err: true, - }, - "kind-mismatch": { - check: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "Baz", - }, - err: true, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - err := validateReferenceTenancy(allowedTenancy, tcase.check) - if tcase.err { - require.Equal(t, resource.ErrReferenceTenancyNotEqual, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func TestValidateReference(t *testing.T) { - allowedTenancy := &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - } - - allowedType := pbcatalog.WorkloadType - - type testCase struct { - check *pbresource.ID - err error - } - - cases := map[string]testCase{ - "ok": { - check: &pbresource.ID{ - Type: allowedType, - Tenancy: allowedTenancy, - Name: "foo", - }, - }, - "type-err": { - check: &pbresource.ID{ - Type: pbcatalog.NodeType, - Tenancy: allowedTenancy, - Name: "foo", - }, - err: resource.ErrInvalidReferenceType{AllowedType: allowedType}, - }, - "tenancy-mismatch": { - check: &pbresource.ID{ - Type: allowedType, - Tenancy: &pbresource.Tenancy{ - Partition: "foo", - Namespace: "bar", - PeerName: "baz", - }, - Name: "foo", - }, - err: resource.ErrReferenceTenancyNotEqual, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - err := validateReference(allowedType, allowedTenancy, tcase.check) - if tcase.err != nil { - require.ErrorIs(t, err, tcase.err) - } else { - require.NoError(t, err) - } - }) - } -} diff --git a/internal/catalog/internal/types/virtual_ips.go b/internal/catalog/internal/types/virtual_ips.go deleted file mode 100644 index be692f63ed65..000000000000 --- a/internal/catalog/internal/types/virtual_ips.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type DecodedVirtualIPs = resource.DecodedResource[*pbcatalog.VirtualIPs] - -func RegisterVirtualIPs(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbcatalog.VirtualIPsType, - Proto: &pbcatalog.VirtualIPs{}, - Scope: resource.ScopeNamespace, - Validate: ValidateVirtualIPs, - ACLs: &resource.ACLHooks{ - Read: func(authorizer acl.Authorizer, context *acl.AuthorizerContext, id *pbresource.ID, p *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().ServiceReadAllowed(id.GetName(), context) - }, - Write: func(authorizer acl.Authorizer, context *acl.AuthorizerContext, p *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().ServiceWriteAllowed(p.GetId().GetName(), context) - }, - List: resource.NoOpACLListHook, - }, - }) -} - -var ValidateVirtualIPs = resource.DecodeAndValidate(validateVirtualIPs) - -func validateVirtualIPs(res *DecodedVirtualIPs) error { - var err error - for idx, ip := range res.Data.Ips { - if vipErr := validateIPAddress(ip.Address); vipErr != nil { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "ips", - Index: idx, - Wrapped: resource.ErrInvalidField{ - Name: "address", - Wrapped: vipErr, - }, - }) - } - } - return err -} diff --git a/internal/catalog/internal/types/virtual_ips_test.go b/internal/catalog/internal/types/virtual_ips_test.go deleted file mode 100644 index 0107e1cfd94f..000000000000 --- a/internal/catalog/internal/types/virtual_ips_test.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func createVirtualIPsResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { - res := &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.VirtualIPsType, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: "test-vip", - }, - } - - var err error - res.Data, err = anypb.New(data) - require.NoError(t, err) - return res -} - -func TestValidateVirtualIPs_Ok(t *testing.T) { - data := &pbcatalog.VirtualIPs{ - Ips: []*pbcatalog.IP{ - { - Address: "::ffff:192.0.2.128", - Generated: true, - }, - { - Address: "10.0.1.42", - Generated: false, - }, - }, - } - - res := createVirtualIPsResource(t, data) - - err := ValidateVirtualIPs(res) - require.NoError(t, err) -} - -func TestValidateVirtualIPs_ParseError(t *testing.T) { - // Any type other than the VirtualIPs type would work - // to cause the error we are expecting - data := &pbcatalog.IP{Address: "198.18.0.1"} - - res := createVirtualIPsResource(t, data) - - err := ValidateVirtualIPs(res) - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) -} - -func TestValidateVirtualIPs_InvalidIP(t *testing.T) { - data := &pbcatalog.VirtualIPs{ - Ips: []*pbcatalog.IP{ - { - Address: "foo", - }, - }, - } - - res := createVirtualIPsResource(t, data) - - err := ValidateVirtualIPs(res) - require.Error(t, err) - require.ErrorIs(t, err, errNotIPAddress) -} - -func TestVirtualIPsACLs(t *testing.T) { - registry := resource.NewRegistry() - RegisterVirtualIPs(registry) - - service := rtest.Resource(pbcatalog.ServiceType, "test"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID() - virtualIPsData := &pbcatalog.VirtualIPs{} - cases := map[string]rtest.ACLTestCase{ - "no rules": { - Rules: ``, - Data: virtualIPsData, - Owner: service, - Typ: pbcatalog.VirtualIPsType, - ReadOK: rtest.DENY, - WriteOK: rtest.DENY, - ListOK: rtest.DEFAULT, - }, - "service test read": { - Rules: `service "test" { policy = "read" }`, - Data: virtualIPsData, - Owner: service, - Typ: pbcatalog.VirtualIPsType, - ReadOK: rtest.ALLOW, - WriteOK: rtest.DENY, - ListOK: rtest.DEFAULT, - }, - "service test write": { - Rules: `service "test" { policy = "write" }`, - Data: virtualIPsData, - Owner: service, - Typ: pbcatalog.VirtualIPsType, - ReadOK: rtest.ALLOW, - WriteOK: rtest.ALLOW, - ListOK: rtest.DEFAULT, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - rtest.RunACLTestCase(t, tc, registry) - }) - } -} diff --git a/internal/catalog/internal/types/workload.go b/internal/catalog/internal/types/workload.go deleted file mode 100644 index 8535a6250491..000000000000 --- a/internal/catalog/internal/types/workload.go +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "math" - "sort" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type DecodedWorkload = resource.DecodedResource[*pbcatalog.Workload] - -func RegisterWorkload(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbcatalog.WorkloadType, - Proto: &pbcatalog.Workload{}, - Scope: resource.ScopeNamespace, - Validate: ValidateWorkload, - ACLs: &resource.ACLHooks{ - Read: aclReadHookWorkload, - Write: resource.DecodeAndAuthorizeWrite(aclWriteHookWorkload), - List: resource.NoOpACLListHook, - }, - }) -} - -var ValidateWorkload = resource.DecodeAndValidate(validateWorkload) - -func validateWorkload(res *DecodedWorkload) error { - var err error - - // Validate that the workload has at least one port - if len(res.Data.Ports) < 1 { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "ports", - Wrapped: resource.ErrEmpty, - }) - } - - var meshPorts []string - - // Validate the Workload Ports - for portName, port := range res.Data.Ports { - if portNameErr := ValidatePortName(portName); portNameErr != nil { - err = multierror.Append(err, resource.ErrInvalidMapKey{ - Map: "ports", - Key: portName, - Wrapped: portNameErr, - }) - } - - // disallow port 0 for now - if port.Port < 1 || port.Port > math.MaxUint16 { - err = multierror.Append(err, resource.ErrInvalidMapValue{ - Map: "ports", - Key: portName, - Wrapped: resource.ErrInvalidField{ - Name: "port", - Wrapped: errInvalidPhysicalPort, - }, - }) - } - - if protoErr := ValidateProtocol(port.Protocol); protoErr != nil { - err = multierror.Append(err, resource.ErrInvalidMapValue{ - Map: "ports", - Key: portName, - Wrapped: resource.ErrInvalidField{ - Name: "protocol", - Wrapped: protoErr, - }, - }) - } - - // Collect the list of mesh ports - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - meshPorts = append(meshPorts, portName) - } - } - - if len(meshPorts) > 1 { - sort.Strings(meshPorts) - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "ports", - Wrapped: errTooMuchMesh{ - Ports: meshPorts, - }, - }) - } - - // If the workload is mesh enabled then a valid identity must be provided. - // If not mesh enabled but a non-empty identity is provided then we still - // validate that its valid. - if len(meshPorts) > 0 && res.Data.Identity == "" { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "identity", - Wrapped: resource.ErrMissing, - }) - } else if res.Data.Identity != "" && !isValidDNSLabel(res.Data.Identity) { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "identity", - Wrapped: errNotDNSLabel, - }) - } - - // Validate workload locality - if res.Data.Locality != nil && res.Data.Locality.Region == "" && res.Data.Locality.Zone != "" { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "locality", - Wrapped: errLocalityZoneNoRegion, - }) - } - - // Node associations are optional but if present the name should - // be a valid DNS label. - if res.Data.NodeName != "" { - if !isValidDNSLabel(res.Data.NodeName) { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "node_name", - Wrapped: errNotDNSLabel, - }) - } - } - - if len(res.Data.Addresses) < 1 { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "addresses", - Wrapped: resource.ErrEmpty, - }) - } - - // Validate Workload Addresses - for idx, addr := range res.Data.Addresses { - if addrErr := validateWorkloadAddress(addr, res.Data.Ports); addrErr != nil { - err = multierror.Append(err, resource.ErrInvalidListElement{ - Name: "addresses", - Index: idx, - Wrapped: addrErr, - }) - } - } - - return err -} - -func aclReadHookWorkload(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID, _ *pbresource.Resource) error { - return authorizer.ToAllowAuthorizer().ServiceReadAllowed(id.GetName(), authzContext) -} - -func aclWriteHookWorkload(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *DecodedWorkload) error { - // First check service:write on the workload name. - err := authorizer.ToAllowAuthorizer().ServiceWriteAllowed(res.GetId().GetName(), authzContext) - if err != nil { - return err - } - - // Check node:read permissions if node is specified. - if res.Data.GetNodeName() != "" { - return authorizer.ToAllowAuthorizer().NodeReadAllowed(res.Data.GetNodeName(), authzContext) - } - - // Check identity:read permissions if identity is specified. - if res.Data.GetIdentity() != "" { - return authorizer.ToAllowAuthorizer().IdentityReadAllowed(res.Data.GetIdentity(), authzContext) - } - - return nil -} diff --git a/internal/catalog/internal/types/workload_selecting.go b/internal/catalog/internal/types/workload_selecting.go deleted file mode 100644 index 6d129bfaa693..000000000000 --- a/internal/catalog/internal/types/workload_selecting.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "google.golang.org/protobuf/proto" - - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" -) - -// WorkloadSelecting denotes a resource type that uses workload selectors. -type WorkloadSelecting interface { - proto.Message - GetWorkloads() *pbcatalog.WorkloadSelector -} diff --git a/internal/catalog/internal/types/workload_test.go b/internal/catalog/internal/types/workload_test.go deleted file mode 100644 index 1c7f7b825594..000000000000 --- a/internal/catalog/internal/types/workload_test.go +++ /dev/null @@ -1,464 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func createWorkloadResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { - res := &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.WorkloadType, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: "api-1234", - }, - } - - var err error - res.Data, err = anypb.New(data) - require.NoError(t, err) - return res -} - -func validWorkload() *pbcatalog.Workload { - return &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "127.0.0.1", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": { - Port: 8443, - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, - }, - }, - NodeName: "foo", - Identity: "api", - Locality: &pbcatalog.Locality{ - Region: "us-east-1", - Zone: "1a", - }, - } -} - -func TestValidateWorkload_Ok(t *testing.T) { - res := createWorkloadResource(t, validWorkload()) - - err := ValidateWorkload(res) - require.NoError(t, err) -} - -func TestValidateWorkload_ParseError(t *testing.T) { - // Any type other than the Workload type would work - // to cause the error we are expecting - data := &pbcatalog.IP{Address: "198.18.0.1"} - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) -} - -func TestValidateWorkload_EmptyAddresses(t *testing.T) { - data := validWorkload() - data.Addresses = nil - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "addresses", - Wrapped: resource.ErrEmpty, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateWorkload_InvalidAddress(t *testing.T) { - data := validWorkload() - data.Addresses[0].Host = "-not-a-host" - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "host", - Wrapped: errInvalidWorkloadHostFormat{Host: "-not-a-host"}, - } - - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateWorkload_MissingIdentity(t *testing.T) { - data := validWorkload() - data.Ports["mesh"] = &pbcatalog.WorkloadPort{ - Port: 9090, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - } - data.Identity = "" - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "identity", - Wrapped: resource.ErrMissing, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateWorkload_InvalidIdentity(t *testing.T) { - data := validWorkload() - data.Identity = "/foiujd" - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "identity", - Wrapped: errNotDNSLabel, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateWorkload_InvalidNodeName(t *testing.T) { - data := validWorkload() - data.NodeName = "/foiujd" - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "node_name", - Wrapped: errNotDNSLabel, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateWorkload_NoPorts(t *testing.T) { - data := validWorkload() - data.Ports = nil - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "ports", - Wrapped: resource.ErrEmpty, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateWorkload_TooMuchMesh(t *testing.T) { - data := validWorkload() - data.Ports["mesh1"] = &pbcatalog.WorkloadPort{ - Port: 9090, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - } - data.Ports["mesh2"] = &pbcatalog.WorkloadPort{ - Port: 9091, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - } - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "ports", - Wrapped: errTooMuchMesh{ - Ports: []string{"mesh1", "mesh2"}, - }, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateWorkload_InvalidPortName(t *testing.T) { - data := validWorkload() - data.Ports[""] = &pbcatalog.WorkloadPort{ - Port: 42, - } - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidMapKey{ - Map: "ports", - Key: "", - Wrapped: resource.ErrEmpty, - } - var actual resource.ErrInvalidMapKey - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateWorkload_InvalidPortProtocol(t *testing.T) { - data := validWorkload() - data.Ports["foo"] = &pbcatalog.WorkloadPort{ - Port: 42, - Protocol: 99, - } - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidMapValue{ - Map: "ports", - Key: "foo", - Wrapped: resource.ErrInvalidField{ - Name: "protocol", - Wrapped: resource.NewConstError("not a supported enum value: 99"), - }, - } - var actual resource.ErrInvalidMapValue - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateWorkload_Port0(t *testing.T) { - data := validWorkload() - data.Ports["bar"] = &pbcatalog.WorkloadPort{Port: 0} - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "port", - Wrapped: errInvalidPhysicalPort, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateWorkload_PortTooHigh(t *testing.T) { - data := validWorkload() - data.Ports["bar"] = &pbcatalog.WorkloadPort{Port: 65536} - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "port", - Wrapped: errInvalidPhysicalPort, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestValidateWorkload_Locality(t *testing.T) { - data := validWorkload() - data.Locality = &pbcatalog.Locality{ - Zone: "1a", - } - - res := createWorkloadResource(t, data) - - err := ValidateWorkload(res) - require.Error(t, err) - expected := resource.ErrInvalidField{ - Name: "locality", - Wrapped: errLocalityZoneNoRegion, - } - var actual resource.ErrInvalidField - require.ErrorAs(t, err, &actual) - require.Equal(t, expected, actual) -} - -func TestWorkloadACLs(t *testing.T) { - registry := resource.NewRegistry() - Register(registry) - - cases := map[string]rtest.ACLTestCase{ - "no rules": { - Rules: ``, - Data: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "1.1.1.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - }, - }, - Typ: pbcatalog.WorkloadType, - ReadOK: rtest.DENY, - WriteOK: rtest.DENY, - ListOK: rtest.DEFAULT, - }, - "service test read": { - Rules: `service "test" { policy = "read" }`, - Data: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "1.1.1.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - }, - }, - Typ: pbcatalog.WorkloadType, - ReadOK: rtest.ALLOW, - WriteOK: rtest.DENY, - ListOK: rtest.DEFAULT, - }, - "service test write": { - Rules: `service "test" { policy = "write" }`, - Data: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "1.1.1.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - }, - }, - Typ: pbcatalog.WorkloadType, - ReadOK: rtest.ALLOW, - WriteOK: rtest.ALLOW, - ListOK: rtest.DEFAULT, - }, - "service test write with node": { - Rules: `service "test" { policy = "write" }`, - Data: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "1.1.1.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - }, - NodeName: "test-node", - }, - Typ: pbcatalog.WorkloadType, - ReadOK: rtest.ALLOW, - WriteOK: rtest.DENY, - ListOK: rtest.DEFAULT, - }, - "service test write with workload identity": { - Rules: `service "test" { policy = "write" }`, - Data: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "1.1.1.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - }, - Identity: "test-identity", - }, - Typ: pbcatalog.WorkloadType, - ReadOK: rtest.ALLOW, - WriteOK: rtest.DENY, - ListOK: rtest.DEFAULT, - }, - "service test write with workload identity and node": { - Rules: `service "test" { policy = "write" }`, - Data: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "1.1.1.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - }, - NodeName: "test-node", - Identity: "test-identity", - }, - Typ: pbcatalog.WorkloadType, - ReadOK: rtest.ALLOW, - WriteOK: rtest.DENY, - ListOK: rtest.DEFAULT, - }, - "service test write with node and node policy": { - Rules: `service "test" { policy = "write" } node "test-node" { policy = "read" }`, - Data: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "1.1.1.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - }, - NodeName: "test-node", - }, - Typ: pbcatalog.WorkloadType, - ReadOK: rtest.ALLOW, - WriteOK: rtest.ALLOW, - ListOK: rtest.DEFAULT, - }, - "service test write with workload identity and identity policy ": { - Rules: `service "test" { policy = "write" } identity "test-identity" { policy = "read" }`, - Data: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "1.1.1.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - }, - Identity: "test-identity", - }, - Typ: pbcatalog.WorkloadType, - ReadOK: rtest.ALLOW, - WriteOK: rtest.ALLOW, - ListOK: rtest.DEFAULT, - }, - "service test write with workload identity and node with both node and identity policy": { - Rules: `service "test" { policy = "write" } identity "test-identity" { policy = "read" } node "test-node" { policy = "read" }`, - Data: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "1.1.1.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - }, - NodeName: "test-node", - Identity: "test-identity", - }, - Typ: pbcatalog.WorkloadType, - ReadOK: rtest.ALLOW, - WriteOK: rtest.ALLOW, - ListOK: rtest.DEFAULT, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - rtest.RunACLTestCase(t, tc, registry) - }) - } -} diff --git a/internal/controller/.mockery.yaml b/internal/controller/.mockery.yaml new file mode 100644 index 000000000000..dddcc58a354a --- /dev/null +++ b/internal/controller/.mockery.yaml @@ -0,0 +1,11 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +with-expecter: true +all: true +recursive: false +dir: "controllermock" +outpkg: "controllermock" +mockname: "{{.InterfaceName}}" +packages: + github.com/hashicorp/consul/internal/controller: diff --git a/internal/controller/api.go b/internal/controller/api.go deleted file mode 100644 index 5c2fc2e78271..000000000000 --- a/internal/controller/api.go +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package controller - -import ( - "context" - "fmt" - "strings" - "time" - - "github.com/hashicorp/go-hclog" - - "github.com/hashicorp/consul/agent/consul/controller/queue" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// ForType begins building a Controller for the given resource type. -func ForType(managedType *pbresource.Type) Controller { - return Controller{managedType: managedType} -} - -// WithReconciler changes the controller's reconciler. -func (c Controller) WithReconciler(reconciler Reconciler) Controller { - if reconciler == nil { - panic("reconciler must not be nil") - } - - c.reconciler = reconciler - return c -} - -// WithWatch adds a watch on the given type/dependency to the controller. mapper -// will be called to determine which resources must be reconciled as a result of -// a watched resource changing. -func (c Controller) WithWatch(watchedType *pbresource.Type, mapper DependencyMapper) Controller { - if watchedType == nil { - panic("watchedType must not be nil") - } - - if mapper == nil { - panic("mapper must not be nil") - } - - c.watches = append(c.watches, watch{watchedType, mapper}) - return c -} - -// WithCustomWatch adds a custom watch on the given dependency to the controller. Custom mapper -// will be called to map events produced by source to the controller's watched type. -func (c Controller) WithCustomWatch(source *Source, mapper CustomDependencyMapper) Controller { - if source == nil { - panic("source must not be nil") - } - - if mapper == nil { - panic("mapper must not be nil") - } - - c.customWatches = append(c.customWatches, customWatch{source, mapper}) - return c -} - -// WithLogger changes the controller's logger. -func (c Controller) WithLogger(logger hclog.Logger) Controller { - if logger == nil { - panic("logger must not be nil") - } - - c.logger = logger - return c -} - -// WithBackoff changes the base and maximum backoff values for the controller's -// retry rate limiter. -func (c Controller) WithBackoff(base, max time.Duration) Controller { - c.baseBackoff = base - c.maxBackoff = max - return c -} - -// WithPlacement changes where and how many replicas of the controller will run. -// In the majority of cases, the default placement (one leader elected instance -// per cluster) is the most appropriate and you shouldn't need to override it. -func (c Controller) WithPlacement(placement Placement) Controller { - c.placement = placement - return c -} - -// String returns a textual description of the controller, useful for debugging. -func (c Controller) String() string { - watchedTypes := make([]string, len(c.watches)) - for idx, w := range c.watches { - watchedTypes[idx] = fmt.Sprintf("%q", resource.ToGVK(w.watchedType)) - } - base, max := c.backoff() - return fmt.Sprintf( - ", placement=%q>", - resource.ToGVK(c.managedType), - strings.Join(watchedTypes, ", "), - base, max, - c.placement, - ) -} - -func (c Controller) backoff() (time.Duration, time.Duration) { - base := c.baseBackoff - if base == 0 { - base = 5 * time.Millisecond - } - max := c.maxBackoff - if max == 0 { - max = 1000 * time.Second - } - return base, max -} - -// Controller runs a reconciliation loop to respond to changes in resources and -// their dependencies. It is heavily inspired by Kubernetes' controller pattern: -// https://kubernetes.io/docs/concepts/architecture/controller/ -// -// Use the builder methods in this package (starting with ForType) to construct -// a controller, and then pass it to a Manager to be executed. -type Controller struct { - managedType *pbresource.Type - reconciler Reconciler - logger hclog.Logger - watches []watch - customWatches []customWatch - baseBackoff time.Duration - maxBackoff time.Duration - placement Placement -} - -type watch struct { - watchedType *pbresource.Type - mapper DependencyMapper -} - -// Watch is responsible for watching for custom events from source and adding them to -// the event queue. -func (s *Source) Watch(ctx context.Context, add func(e Event)) error { - for { - select { - case <-ctx.Done(): - return nil - case evt, ok := <-s.Source: - if !ok { - return nil - } - add(evt) - } - } -} - -// Source is used as a generic source of events. This can be used when events aren't coming from resources -// stored by the resource API. -type Source struct { - Source <-chan Event -} - -// Event captures an event in the system which the API can choose to respond to. -type Event struct { - Obj queue.ItemType -} - -// Key returns a string that will be used to de-duplicate items in the queue. -func (e Event) Key() string { - return e.Obj.Key() -} - -// customWatch represent a Watch on a custom Event source and a Mapper to map said -// Events into Requests that the controller can respond to. -type customWatch struct { - source *Source - mapper CustomDependencyMapper -} - -// Request represents a request to reconcile the resource with the given ID. -type Request struct { - // ID of the resource that needs to be reconciled. - ID *pbresource.ID -} - -// Key satisfies the queue.ItemType interface. It returns a string which will be -// used to de-duplicate requests in the queue. -func (r Request) Key() string { - return fmt.Sprintf( - "part=%q,peer=%q,ns=%q,name=%q,uid=%q", - r.ID.Tenancy.Partition, - r.ID.Tenancy.PeerName, - r.ID.Tenancy.Namespace, - r.ID.Name, - r.ID.Uid, - ) -} - -// Runtime contains the dependencies required by reconcilers. -type Runtime struct { - Client pbresource.ResourceServiceClient - Logger hclog.Logger -} - -// Reconciler implements the business logic of a controller. -type Reconciler interface { - // Reconcile the resource identified by req.ID. - Reconcile(ctx context.Context, rt Runtime, req Request) error -} - -// Placement determines where and how many replicas of the controller will run. -type Placement int - -const ( - // PlacementSingleton ensures there is a single, leader-elected, instance of - // the controller running in the cluster at any time. It's the default and is - // suitable for most use-cases. - PlacementSingleton Placement = iota - - // PlacementEachServer ensures there is a replica of the controller running on - // each server in the cluster. It is useful for cases where the controller is - // responsible for applying some configuration resource to the server whenever - // it changes (e.g. rate-limit configuration). Generally, controllers in this - // placement mode should not modify resources. - PlacementEachServer -) - -// String satisfies the fmt.Stringer interface. -func (p Placement) String() string { - switch p { - case PlacementSingleton: - return "singleton" - case PlacementEachServer: - return "each-server" - } - panic(fmt.Sprintf("unknown placement %d", p)) -} - -// RequeueAfterError is an error that allows a Reconciler to override the -// exponential backoff behavior of the Controller, rather than applying -// the backoff algorithm, returning a RequeueAfterError will cause the -// Controller to reschedule the Request at a given time in the future. -type RequeueAfterError time.Duration - -// Error implements the error interface. -func (r RequeueAfterError) Error() string { - return fmt.Sprintf("requeue at %s", time.Duration(r)) -} - -// RequeueAfter constructs a RequeueAfterError with the given duration -// setting. -func RequeueAfter(after time.Duration) error { - return RequeueAfterError(after) -} - -// RequeueNow constructs a RequeueAfterError that reschedules the Request -// immediately. -func RequeueNow() error { - return RequeueAfterError(0) -} diff --git a/internal/controller/api_test.go b/internal/controller/api_test.go deleted file mode 100644 index e80458541008..000000000000 --- a/internal/controller/api_test.go +++ /dev/null @@ -1,394 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package controller_test - -import ( - "context" - "errors" - "testing" - "time" - - "github.com/stretchr/testify/require" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource/demo" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestController_API(t *testing.T) { - t.Parallel() - - rec := newTestReconciler() - client := svctest.RunResourceService(t, demo.RegisterTypes) - - concertsChan := make(chan controller.Event) - defer close(concertsChan) - concertSource := &controller.Source{Source: concertsChan} - concertMapper := func(ctx context.Context, rt controller.Runtime, event controller.Event) ([]controller.Request, error) { - artistID := event.Obj.(*Concert).artistID - var requests []controller.Request - requests = append(requests, controller.Request{ID: artistID}) - return requests, nil - } - - ctrl := controller. - ForType(demo.TypeV2Artist). - WithWatch(demo.TypeV2Album, controller.MapOwner). - WithCustomWatch(concertSource, concertMapper). - WithBackoff(10*time.Millisecond, 100*time.Millisecond). - WithReconciler(rec) - - mgr := controller.NewManager(client, testutil.Logger(t)) - mgr.Register(ctrl) - mgr.SetRaftLeader(true) - go mgr.Run(testContext(t)) - - t.Run("managed resource type", func(t *testing.T) { - res, err := demo.GenerateV2Artist() - require.NoError(t, err) - - rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - - req := rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - }) - - t.Run("watched resource type", func(t *testing.T) { - res, err := demo.GenerateV2Artist() - require.NoError(t, err) - - rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - - req := rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - - rec.expectNoRequest(t, 500*time.Millisecond) - - album, err := demo.GenerateV2Album(rsp.Resource.Id) - require.NoError(t, err) - - _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: album}) - require.NoError(t, err) - - req = rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - }) - - t.Run("custom watched resource type", func(t *testing.T) { - res, err := demo.GenerateV2Artist() - require.NoError(t, err) - - rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - - req := rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - - rec.expectNoRequest(t, 500*time.Millisecond) - - concertsChan <- controller.Event{Obj: &Concert{name: "test-concert", artistID: rsp.Resource.Id}} - - watchedReq := rec.wait(t) - prototest.AssertDeepEqual(t, req.ID, watchedReq.ID) - - otherArtist, err := demo.GenerateV2Artist() - require.NoError(t, err) - - concertsChan <- controller.Event{Obj: &Concert{name: "test-concert", artistID: otherArtist.Id}} - - watchedReq = rec.wait(t) - prototest.AssertDeepEqual(t, otherArtist.Id, watchedReq.ID) - }) - - t.Run("error retries", func(t *testing.T) { - rec.failNext(errors.New("KABOOM")) - - res, err := demo.GenerateV2Artist() - require.NoError(t, err) - - rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - - req := rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - - // Reconciler should be called with the same request again. - req = rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - }) - - t.Run("panic retries", func(t *testing.T) { - rec.panicNext("KABOOM") - - res, err := demo.GenerateV2Artist() - require.NoError(t, err) - - rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - - req := rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - - // Reconciler should be called with the same request again. - req = rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - }) - - t.Run("defer", func(t *testing.T) { - rec.failNext(controller.RequeueAfter(1 * time.Second)) - - res, err := demo.GenerateV2Artist() - require.NoError(t, err) - - rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - - req := rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - - rec.expectNoRequest(t, 750*time.Millisecond) - - req = rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - }) -} - -func TestController_Placement(t *testing.T) { - t.Parallel() - - t.Run("singleton", func(t *testing.T) { - rec := newTestReconciler() - client := svctest.RunResourceService(t, demo.RegisterTypes) - - ctrl := controller. - ForType(demo.TypeV2Artist). - WithWatch(demo.TypeV2Album, controller.MapOwner). - WithPlacement(controller.PlacementSingleton). - WithReconciler(rec) - - mgr := controller.NewManager(client, testutil.Logger(t)) - mgr.Register(ctrl) - go mgr.Run(testContext(t)) - - res, err := demo.GenerateV2Artist() - require.NoError(t, err) - - // Reconciler should not be called until we're the Raft leader. - _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - rec.expectNoRequest(t, 500*time.Millisecond) - - // Become the leader and check the reconciler is called. - mgr.SetRaftLeader(true) - _ = rec.wait(t) - - // Should not be called after losing leadership. - mgr.SetRaftLeader(false) - _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - rec.expectNoRequest(t, 500*time.Millisecond) - }) - - t.Run("each server", func(t *testing.T) { - rec := newTestReconciler() - client := svctest.RunResourceService(t, demo.RegisterTypes) - - ctrl := controller. - ForType(demo.TypeV2Artist). - WithWatch(demo.TypeV2Album, controller.MapOwner). - WithPlacement(controller.PlacementEachServer). - WithReconciler(rec) - - mgr := controller.NewManager(client, testutil.Logger(t)) - mgr.Register(ctrl) - go mgr.Run(testContext(t)) - - res, err := demo.GenerateV2Artist() - require.NoError(t, err) - - // Reconciler should be called even though we're not the Raft leader. - _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - _ = rec.wait(t) - }) -} - -func TestController_String(t *testing.T) { - ctrl := controller. - ForType(demo.TypeV2Artist). - WithWatch(demo.TypeV2Album, controller.MapOwner). - WithBackoff(5*time.Second, 1*time.Hour). - WithPlacement(controller.PlacementEachServer) - - require.Equal(t, - `, placement="each-server">`, - ctrl.String(), - ) -} - -func TestController_NoReconciler(t *testing.T) { - client := svctest.RunResourceService(t, demo.RegisterTypes) - mgr := controller.NewManager(client, testutil.Logger(t)) - - ctrl := controller.ForType(demo.TypeV2Artist) - require.PanicsWithValue(t, - `cannot register controller without a reconciler , placement="singleton">`, - func() { mgr.Register(ctrl) }) -} - -func TestController_Watch(t *testing.T) { - t.Parallel() - - t.Run("partitioned scoped resources", func(t *testing.T) { - rec := newTestReconciler() - - client := svctest.RunResourceService(t, demo.RegisterTypes) - - ctrl := controller. - ForType(demo.TypeV1RecordLabel). - WithReconciler(rec) - - mgr := controller.NewManager(client, testutil.Logger(t)) - mgr.SetRaftLeader(true) - mgr.Register(ctrl) - - ctx := testContext(t) - go mgr.Run(ctx) - - res, err := demo.GenerateV1RecordLabel("test") - require.NoError(t, err) - - rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - - req := rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - }) - - t.Run("cluster scoped resources", func(t *testing.T) { - rec := newTestReconciler() - - client := svctest.RunResourceService(t, demo.RegisterTypes) - - ctrl := controller. - ForType(demo.TypeV1Executive). - WithReconciler(rec) - - mgr := controller.NewManager(client, testutil.Logger(t)) - mgr.SetRaftLeader(true) - mgr.Register(ctrl) - - go mgr.Run(testContext(t)) - - exec, err := demo.GenerateV1Executive("test", "CEO") - require.NoError(t, err) - - rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: exec}) - require.NoError(t, err) - - req := rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - }) - - t.Run("namespace scoped resources", func(t *testing.T) { - rec := newTestReconciler() - - client := svctest.RunResourceService(t, demo.RegisterTypes) - - ctrl := controller. - ForType(demo.TypeV2Artist). - WithReconciler(rec) - - mgr := controller.NewManager(client, testutil.Logger(t)) - mgr.SetRaftLeader(true) - mgr.Register(ctrl) - - go mgr.Run(testContext(t)) - - artist, err := demo.GenerateV2Artist() - require.NoError(t, err) - - rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: artist}) - require.NoError(t, err) - - req := rec.wait(t) - prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) - }) -} - -func newTestReconciler() *testReconciler { - return &testReconciler{ - calls: make(chan controller.Request), - errors: make(chan error, 1), - panics: make(chan any, 1), - } -} - -type testReconciler struct { - calls chan controller.Request - errors chan error - panics chan any -} - -func (r *testReconciler) Reconcile(_ context.Context, _ controller.Runtime, req controller.Request) error { - r.calls <- req - - select { - case err := <-r.errors: - return err - case p := <-r.panics: - panic(p) - default: - return nil - } -} - -func (r *testReconciler) failNext(err error) { r.errors <- err } -func (r *testReconciler) panicNext(p any) { r.panics <- p } - -func (r *testReconciler) expectNoRequest(t *testing.T, duration time.Duration) { - t.Helper() - - started := time.Now() - select { - case req := <-r.calls: - t.Fatalf("expected no request for %s, but got: %s after %s", duration, req.ID, time.Since(started)) - case <-time.After(duration): - } -} - -func (r *testReconciler) wait(t *testing.T) controller.Request { - t.Helper() - - var req controller.Request - select { - case req = <-r.calls: - case <-time.After(500 * time.Millisecond): - t.Fatal("Reconcile was not called after 500ms") - } - return req -} - -func testContext(t *testing.T) context.Context { - t.Helper() - - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(cancel) - - return ctx -} - -type Concert struct { - name string - artistID *pbresource.ID -} - -func (c Concert) Key() string { - return c.name -} diff --git a/internal/controller/cache/.mockery.yaml b/internal/controller/cache/.mockery.yaml new file mode 100644 index 000000000000..e5bd10816513 --- /dev/null +++ b/internal/controller/cache/.mockery.yaml @@ -0,0 +1,15 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +with-expecter: true +recursive: false +all: true +# We don't want the mocks within proto-public so as to force a dependency +# of the testify library on the modules usage. The mocks are only for +# internal testing purposes. Other consumers can generated the mocks into +# their own code base. +dir: "{{.PackageName}}mock" +outpkg: "{{.PackageName}}mock" +mockname: "{{.InterfaceName}}" +packages: + github.com/hashicorp/consul/internal/controller/cache: diff --git a/internal/controller/cache/cache.go b/internal/controller/cache/cache.go new file mode 100644 index 000000000000..2f501838f61c --- /dev/null +++ b/internal/controller/cache/cache.go @@ -0,0 +1,213 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cache + +import ( + "github.com/hashicorp/consul/internal/controller/cache/index" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// Query is the function type to use for named query callbacks +type Query func(c ReadOnlyCache, args ...any) (ResourceIterator, error) + +type Cache interface { + // AddType will add a new resource type to the cache. This will + // include configuring an `id` index based on the resources Id + AddType(it *pbresource.Type) + // AddIndex will add a new index for the specified type to the cache. + // If the type isn't yet known to the cache, it will first add it + // including setting up its `id` index. + AddIndex(it *pbresource.Type, index *index.Index) error + // AddQuery will add a new named query to the cache. This query + // can potentially use multiple different cache indexes to come + // up with the final result iterator. + AddQuery(name string, fn Query) error + + ReadOnlyCache + WriteCache +} + +// ReadOnlyCache is the set of methods on the Resource cache that can be used +// to query the cache. +type ReadOnlyCache interface { + // Get retrieves a single resource from the specified index that matches the provided args. + // If more than one match is found the first is returned. + Get(it *pbresource.Type, indexName string, args ...any) (*pbresource.Resource, error) + + // List retrieves all the resources from the specified index matching the provided args. + List(it *pbresource.Type, indexName string, args ...any) ([]*pbresource.Resource, error) + + // ListIterator retrieves an iterator over all resources from the specified index matching the provided args. + ListIterator(it *pbresource.Type, indexName string, args ...any) (ResourceIterator, error) + + // Parents retrieves all resources whos index value is a parent (or prefix) of the value calculated + // from the provided args. + Parents(it *pbresource.Type, indexName string, args ...any) ([]*pbresource.Resource, error) + + // ParentsIterator retrieves an iterator over all resources whos index value is a parent (or prefix) + // of the value calculated from the provided args. + ParentsIterator(it *pbresource.Type, indexName string, args ...any) (ResourceIterator, error) + + // Query will execute a named query against the cache and return an interator over its results + Query(name string, args ...any) (ResourceIterator, error) +} + +type WriteCache interface { + // Insert will add a single resource into the cache. If it already exists, this will update + // all indexing to the current values. + Insert(r *pbresource.Resource) error + + // Delete will remove a single resource from the cache. + Delete(r *pbresource.Resource) error +} + +type ResourceIterator interface { + Next() *pbresource.Resource +} + +type unversionedType struct { + Group string + Kind string +} + +type cache struct { + kinds map[unversionedType]*kindIndices + queries map[string]Query +} + +func New() Cache { + return newCache() +} + +func newCache() *cache { + return &cache{ + kinds: make(map[unversionedType]*kindIndices), + queries: make(map[string]Query), + } +} + +func (c *cache) ensureTypeCached(it *pbresource.Type) *kindIndices { + ut := unversionedType{Group: it.Group, Kind: it.Kind} + + _, ok := c.kinds[ut] + if !ok { + c.kinds[ut] = newKindIndices() + } + + return c.kinds[ut] +} + +func (c *cache) AddType(it *pbresource.Type) { + c.ensureTypeCached(it) +} + +func (c *cache) AddIndex(it *pbresource.Type, index *index.Index) error { + kind := c.ensureTypeCached(it) + err := kind.addIndex(index) + if err != nil { + return CacheTypeError{it: unversionedType{Group: it.Group, Kind: it.Kind}, err: err} + } + return nil +} + +func (c *cache) AddQuery(name string, fn Query) error { + if fn == nil { + return QueryRequired + } + if _, found := c.queries[name]; found { + return DuplicateQueryError{name: name} + } + + c.queries[name] = fn + return nil +} + +func (c *cache) Query(name string, args ...any) (ResourceIterator, error) { + fn, found := c.queries[name] + if !found { + return nil, QueryNotFoundError{name: name} + } + + return fn(c, args...) +} + +func (c *cache) Get(it *pbresource.Type, indexName string, args ...any) (*pbresource.Resource, error) { + indices, err := c.getTypeIndices(it) + if err != nil { + return nil, err + } + + return indices.get(indexName, args...) +} + +func (c *cache) ListIterator(it *pbresource.Type, indexName string, args ...any) (ResourceIterator, error) { + indices, err := c.getTypeIndices(it) + if err != nil { + return nil, err + } + + return indices.listIterator(indexName, args...) +} + +func (c *cache) List(it *pbresource.Type, indexName string, args ...any) ([]*pbresource.Resource, error) { + return expandIterator(c.ListIterator(it, indexName, args...)) +} + +func (c *cache) ParentsIterator(it *pbresource.Type, indexName string, args ...any) (ResourceIterator, error) { + indices, err := c.getTypeIndices(it) + if err != nil { + return nil, err + } + + return indices.parentsIterator(indexName, args...) +} + +func (c *cache) Parents(it *pbresource.Type, indexName string, args ...any) ([]*pbresource.Resource, error) { + return expandIterator(c.ParentsIterator(it, indexName, args...)) +} + +func (c *cache) Insert(r *pbresource.Resource) error { + indices, err := c.getTypeIndices(r.Id.Type) + if err != nil { + return err + } + + return indices.insert(r) +} + +func (c *cache) Delete(r *pbresource.Resource) error { + indices, err := c.getTypeIndices(r.Id.Type) + if err != nil { + return err + } + + return indices.delete(r) +} + +func (c *cache) getTypeIndices(it *pbresource.Type) (*kindIndices, error) { + if it == nil { + return nil, TypeUnspecifiedError + } + + ut := unversionedType{Group: it.Group, Kind: it.Kind} + + indices, ok := c.kinds[ut] + if !ok { + return nil, TypeNotIndexedError + } + return indices, nil +} + +func expandIterator(iter ResourceIterator, err error) ([]*pbresource.Resource, error) { + if err != nil { + return nil, err + } + + var results []*pbresource.Resource + for res := iter.Next(); res != nil; res = iter.Next() { + results = append(results, res) + } + + return results, nil +} diff --git a/internal/controller/cache/cache_test.go b/internal/controller/cache/cache_test.go new file mode 100644 index 000000000000..705a2d1df995 --- /dev/null +++ b/internal/controller/cache/cache_test.go @@ -0,0 +1,353 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cache + +import ( + "encoding/binary" + "testing" + + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + "github.com/hashicorp/consul/internal/controller/cache/index" + "github.com/hashicorp/consul/internal/controller/cache/indexers" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v1" + "github.com/hashicorp/consul/proto/private/prototest" +) + +const ( + errQueryName = "error-query" + okQueryName = "ok-query" +) + +func namePrefixIndexer() *index.Index { + return indexers.DecodedSingleIndexer( + "name_prefix", + index.SingleValueFromArgs(func(value string) ([]byte, error) { + return []byte(value), nil + }), + func(r *resource.DecodedResource[*pbdemo.Album]) (bool, []byte, error) { + return true, []byte(r.Data.Name), nil + }) +} + +func releaseYearIndexer() *index.Index { + return indexers.DecodedSingleIndexer( + "year", + index.SingleValueFromArgs(func(value int32) ([]byte, error) { + var b index.Builder + binary.Write(&b, binary.BigEndian, value) + return b.Bytes(), nil + }), + func(r *resource.DecodedResource[*pbdemo.Album]) (bool, []byte, error) { + var b index.Builder + binary.Write(&b, binary.BigEndian, r.Data.YearOfRelease) + return true, b.Bytes(), nil + }) +} + +func tracksIndexer() *index.Index { + return indexers.DecodedMultiIndexer( + "tracks", + index.SingleValueFromOneOrTwoArgs(func(value string, prefix bool) ([]byte, error) { + var b index.Builder + if prefix { + b.Raw([]byte(value)) + } else { + b.String(value) + } + return b.Bytes(), nil + }), + func(r *resource.DecodedResource[*pbdemo.Album]) (bool, [][]byte, error) { + indexes := make([][]byte, len(r.Data.Tracks)) + for idx, track := range r.Data.Tracks { + var b index.Builder + b.String(track) + indexes[idx] = b.Bytes() + } + + return true, indexes, nil + }) +} + +func requireCacheIndex(t *testing.T, c *cache, rtype *pbresource.Type, indexes ...string) { + t.Helper() + indices, err := c.getTypeIndices(rtype) + require.NoError(t, err) + require.NotNil(t, indices) + + for _, name := range indexes { + index, err := indices.getIndex(name) + require.NoError(t, err) + require.NotNil(t, index) + } +} + +func TestCacheAddType(t *testing.T) { + c := newCache() + c.AddType(pbdemo.AlbumType) + + // Adding a type will ensure that the `id` index exists + requireCacheIndex(t, c, pbdemo.AlbumType, "id") +} + +func TestCacheAddIndex(t *testing.T) { + c := newCache() + require.NoError(t, c.AddIndex(pbdemo.AlbumType, releaseYearIndexer())) + require.NoError(t, c.AddIndex(pbdemo.AlbumType, tracksIndexer())) + + // Adding indexes should also have the side effect of ensuring that the `id` index exists + requireCacheIndex(t, c, pbdemo.AlbumType, "id", "year", "tracks") +} + +func TestCacheAddIndex_Duplicate(t *testing.T) { + c := newCache() + require.NoError(t, c.AddIndex(pbdemo.AlbumType, releaseYearIndexer())) + // should get an error due to a duplicate index name + require.Error(t, c.AddIndex(pbdemo.AlbumType, releaseYearIndexer())) +} + +func noopQuery(_ ReadOnlyCache, _ ...any) (ResourceIterator, error) { + return nil, nil +} + +func errQuery(_ ReadOnlyCache, _ ...any) (ResourceIterator, error) { + return nil, injectedError +} + +func TestCacheAddQuery(t *testing.T) { + c := newCache() + require.NoError(t, c.AddQuery("foo", noopQuery)) + require.NoError(t, c.AddQuery("bar", errQuery)) + + fn, found := c.queries["foo"] + require.True(t, found) + iter, err := fn(c) + require.NoError(t, err) + require.Nil(t, iter) + + fn, found = c.queries["bar"] + require.True(t, found) + iter, err = fn(c) + require.ErrorIs(t, err, injectedError) + require.Nil(t, iter) +} + +func TestCacheAddQuery_Duplicate(t *testing.T) { + c := newCache() + + require.NoError(t, c.AddQuery("foo", noopQuery)) + // should get an error due to a duplicate query name + require.Error(t, c.AddQuery("foo", noopQuery)) +} + +func TestCacheAddQuery_Nil(t *testing.T) { + c := newCache() + require.ErrorIs(t, c.AddQuery("foo", nil), QueryRequired) +} + +func TestQuery_NotFound(t *testing.T) { + c := newCache() + iter, err := c.Query("foo", "something") + require.ErrorIs(t, err, QueryNotFoundError{"foo"}) + require.Nil(t, iter) +} + +func TestCache(t *testing.T) { + suite.Run(t, &cacheSuite{}) +} + +type cacheSuite struct { + suite.Suite + c Cache + + album1 *pbresource.Resource + album2 *pbresource.Resource + album3 *pbresource.Resource + album4 *pbresource.Resource +} + +func (suite *cacheSuite) SetupTest() { + suite.c = New() + + require.NoError(suite.T(), suite.c.AddIndex(pbdemo.AlbumType, namePrefixIndexer())) + require.NoError(suite.T(), suite.c.AddQuery(okQueryName, func(c ReadOnlyCache, args ...any) (ResourceIterator, error) { + return c.ParentsIterator(pbdemo.AlbumType, "name_prefix", args...) + })) + require.NoError(suite.T(), suite.c.AddIndex(pbdemo.AlbumType, releaseYearIndexer())) + require.NoError(suite.T(), suite.c.AddQuery(errQueryName, errQuery)) + require.NoError(suite.T(), suite.c.AddIndex(pbdemo.AlbumType, tracksIndexer())) + + suite.album1 = resourcetest.Resource(pbdemo.AlbumType, "one"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(suite.T(), &pbdemo.Album{ + Name: "one", + YearOfRelease: 2023, + Tracks: []string{"foo", "bar", "baz"}, + }). + Build() + + suite.album2 = resourcetest.Resource(pbdemo.AlbumType, "two"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(suite.T(), &pbdemo.Album{ + Name: "two", + YearOfRelease: 2023, + Tracks: []string{"fangorn", "zoo"}, + }). + Build() + + suite.album3 = resourcetest.Resource(pbdemo.AlbumType, "third"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(suite.T(), &pbdemo.Album{ + Name: "foo", + YearOfRelease: 2022, + Tracks: []string{"blah", "something", "else"}, + }). + Build() + + suite.album4 = resourcetest.Resource(pbdemo.AlbumType, "four"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(suite.T(), &pbdemo.Album{ + Name: "food", + YearOfRelease: 2020, + Tracks: []string{"nothing", "food"}, + }). + Build() + + require.NoError(suite.T(), suite.c.Insert(suite.album1)) + require.NoError(suite.T(), suite.c.Insert(suite.album2)) + require.NoError(suite.T(), suite.c.Insert(suite.album3)) + require.NoError(suite.T(), suite.c.Insert(suite.album4)) +} + +func (suite *cacheSuite) TestGet() { + res, err := suite.c.Get(pbdemo.AlbumType, "id", suite.album1.Id) + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.album1, res) + + res, err = suite.c.Get(pbdemo.AlbumType, "year", int32(2022)) + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.album3, res) + + res, err = suite.c.Get(pbdemo.AlbumType, "tracks", "fangorn") + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.album2, res) +} + +func (suite *cacheSuite) TestGet_NilType() { + res, err := suite.c.Get(nil, "id", suite.album1.Id) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, TypeUnspecifiedError) + require.Nil(suite.T(), res) +} + +func (suite *cacheSuite) TestGet_UncachedType() { + res, err := suite.c.Get(pbdemo.ArtistType, "id", suite.album1.Id) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, TypeNotIndexedError) + require.Nil(suite.T(), res) +} + +func (suite *cacheSuite) TestGet_IndexNotFound() { + res, err := suite.c.Get(pbdemo.AlbumType, "blah", suite.album1.Id) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, IndexNotFoundError{name: "blah"}) + require.Nil(suite.T(), res) +} + +func (suite *cacheSuite) TestList() { + resources, err := suite.c.List(pbdemo.AlbumType, "year", int32(2023)) + require.NoError(suite.T(), err) + prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album1, suite.album2}, resources) + + resources, err = suite.c.List(pbdemo.AlbumType, "tracks", "f", true) + require.NoError(suite.T(), err) + prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album1, suite.album2, suite.album4}, resources) +} + +func (suite *cacheSuite) TestList_NilType() { + res, err := suite.c.List(nil, "id", suite.album1.Id) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, TypeUnspecifiedError) + require.Nil(suite.T(), res) +} + +func (suite *cacheSuite) TestList_UncachedType() { + res, err := suite.c.List(pbdemo.ArtistType, "id", suite.album1.Id) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, TypeNotIndexedError) + require.Nil(suite.T(), res) +} + +func (suite *cacheSuite) TestList_IndexNotFound() { + res, err := suite.c.List(pbdemo.AlbumType, "blah", suite.album1.Id) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, IndexNotFoundError{name: "blah"}) + require.Nil(suite.T(), res) +} + +func (suite *cacheSuite) TestParents() { + resources, err := suite.c.Parents(pbdemo.AlbumType, "name_prefix", "food") + require.NoError(suite.T(), err) + prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album3, suite.album4}, resources) +} + +func (suite *cacheSuite) TestQuery() { + resources, err := expandIterator(suite.c.Query(okQueryName, "food")) + require.NoError(suite.T(), err) + prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album3, suite.album4}, resources) +} + +func (suite *cacheSuite) TestParents_NilType() { + res, err := suite.c.Parents(nil, "id", suite.album1.Id) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, TypeUnspecifiedError) + require.Nil(suite.T(), res) +} + +func (suite *cacheSuite) TestParents_UncachedType() { + res, err := suite.c.Parents(pbdemo.ArtistType, "id", suite.album1.Id) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, TypeNotIndexedError) + require.Nil(suite.T(), res) +} + +func (suite *cacheSuite) TestParents_IndexNotFound() { + res, err := suite.c.Parents(pbdemo.AlbumType, "blah", suite.album1.Id) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, IndexNotFoundError{name: "blah"}) + require.Nil(suite.T(), res) +} + +func (suite *cacheSuite) TestInsert_UncachedType() { + err := suite.c.Insert(resourcetest.Resource(pbdemo.ArtistType, "blah").Build()) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, TypeNotIndexedError) +} + +func (suite *cacheSuite) TestDelete() { + err := suite.c.Delete(suite.album1) + require.NoError(suite.T(), err) + + res, err := suite.c.Get(pbdemo.AlbumType, "id", suite.album1.Id) + require.NoError(suite.T(), err) + require.Nil(suite.T(), res) + + resources, err := suite.c.List(pbdemo.AlbumType, "year", int32(2023)) + require.NoError(suite.T(), err) + prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album2}, resources) + + resources, err = suite.c.Parents(pbdemo.AlbumType, "name_prefix", "onesie") + require.NoError(suite.T(), err) + require.Nil(suite.T(), resources) +} + +func (suite *cacheSuite) TestDelete_UncachedType() { + err := suite.c.Delete(resourcetest.Resource(pbdemo.ArtistType, "blah").Build()) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, TypeNotIndexedError) +} diff --git a/internal/controller/cache/cachemock/mock_Cache.go b/internal/controller/cache/cachemock/mock_Cache.go new file mode 100644 index 000000000000..2908a4ffcdc5 --- /dev/null +++ b/internal/controller/cache/cachemock/mock_Cache.go @@ -0,0 +1,637 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package cachemock + +import ( + cache "github.com/hashicorp/consul/internal/controller/cache" + index "github.com/hashicorp/consul/internal/controller/cache/index" + + mock "github.com/stretchr/testify/mock" + + pbresource "github.com/hashicorp/consul/proto-public/pbresource" +) + +// Cache is an autogenerated mock type for the Cache type +type Cache struct { + mock.Mock +} + +type Cache_Expecter struct { + mock *mock.Mock +} + +func (_m *Cache) EXPECT() *Cache_Expecter { + return &Cache_Expecter{mock: &_m.Mock} +} + +// AddIndex provides a mock function with given fields: it, _a1 +func (_m *Cache) AddIndex(it *pbresource.Type, _a1 *index.Index) error { + ret := _m.Called(it, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(*pbresource.Type, *index.Index) error); ok { + r0 = rf(it, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Cache_AddIndex_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddIndex' +type Cache_AddIndex_Call struct { + *mock.Call +} + +// AddIndex is a helper method to define mock.On call +// - it *pbresource.Type +// - _a1 *index.Index +func (_e *Cache_Expecter) AddIndex(it interface{}, _a1 interface{}) *Cache_AddIndex_Call { + return &Cache_AddIndex_Call{Call: _e.mock.On("AddIndex", it, _a1)} +} + +func (_c *Cache_AddIndex_Call) Run(run func(it *pbresource.Type, _a1 *index.Index)) *Cache_AddIndex_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbresource.Type), args[1].(*index.Index)) + }) + return _c +} + +func (_c *Cache_AddIndex_Call) Return(_a0 error) *Cache_AddIndex_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Cache_AddIndex_Call) RunAndReturn(run func(*pbresource.Type, *index.Index) error) *Cache_AddIndex_Call { + _c.Call.Return(run) + return _c +} + +// AddQuery provides a mock function with given fields: name, fn +func (_m *Cache) AddQuery(name string, fn cache.Query) error { + ret := _m.Called(name, fn) + + var r0 error + if rf, ok := ret.Get(0).(func(string, cache.Query) error); ok { + r0 = rf(name, fn) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Cache_AddQuery_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddQuery' +type Cache_AddQuery_Call struct { + *mock.Call +} + +// AddQuery is a helper method to define mock.On call +// - name string +// - fn cache.Query +func (_e *Cache_Expecter) AddQuery(name interface{}, fn interface{}) *Cache_AddQuery_Call { + return &Cache_AddQuery_Call{Call: _e.mock.On("AddQuery", name, fn)} +} + +func (_c *Cache_AddQuery_Call) Run(run func(name string, fn cache.Query)) *Cache_AddQuery_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(cache.Query)) + }) + return _c +} + +func (_c *Cache_AddQuery_Call) Return(_a0 error) *Cache_AddQuery_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Cache_AddQuery_Call) RunAndReturn(run func(string, cache.Query) error) *Cache_AddQuery_Call { + _c.Call.Return(run) + return _c +} + +// AddType provides a mock function with given fields: it +func (_m *Cache) AddType(it *pbresource.Type) { + _m.Called(it) +} + +// Cache_AddType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddType' +type Cache_AddType_Call struct { + *mock.Call +} + +// AddType is a helper method to define mock.On call +// - it *pbresource.Type +func (_e *Cache_Expecter) AddType(it interface{}) *Cache_AddType_Call { + return &Cache_AddType_Call{Call: _e.mock.On("AddType", it)} +} + +func (_c *Cache_AddType_Call) Run(run func(it *pbresource.Type)) *Cache_AddType_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbresource.Type)) + }) + return _c +} + +func (_c *Cache_AddType_Call) Return() *Cache_AddType_Call { + _c.Call.Return() + return _c +} + +func (_c *Cache_AddType_Call) RunAndReturn(run func(*pbresource.Type)) *Cache_AddType_Call { + _c.Call.Return(run) + return _c +} + +// Delete provides a mock function with given fields: r +func (_m *Cache) Delete(r *pbresource.Resource) error { + ret := _m.Called(r) + + var r0 error + if rf, ok := ret.Get(0).(func(*pbresource.Resource) error); ok { + r0 = rf(r) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Cache_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' +type Cache_Delete_Call struct { + *mock.Call +} + +// Delete is a helper method to define mock.On call +// - r *pbresource.Resource +func (_e *Cache_Expecter) Delete(r interface{}) *Cache_Delete_Call { + return &Cache_Delete_Call{Call: _e.mock.On("Delete", r)} +} + +func (_c *Cache_Delete_Call) Run(run func(r *pbresource.Resource)) *Cache_Delete_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbresource.Resource)) + }) + return _c +} + +func (_c *Cache_Delete_Call) Return(_a0 error) *Cache_Delete_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Cache_Delete_Call) RunAndReturn(run func(*pbresource.Resource) error) *Cache_Delete_Call { + _c.Call.Return(run) + return _c +} + +// Get provides a mock function with given fields: it, indexName, args +func (_m *Cache) Get(it *pbresource.Type, indexName string, args ...interface{}) (*pbresource.Resource, error) { + var _ca []interface{} + _ca = append(_ca, it, indexName) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 *pbresource.Resource + var r1 error + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) (*pbresource.Resource, error)); ok { + return rf(it, indexName, args...) + } + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) *pbresource.Resource); ok { + r0 = rf(it, indexName, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.Resource) + } + } + + if rf, ok := ret.Get(1).(func(*pbresource.Type, string, ...interface{}) error); ok { + r1 = rf(it, indexName, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Cache_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' +type Cache_Get_Call struct { + *mock.Call +} + +// Get is a helper method to define mock.On call +// - it *pbresource.Type +// - indexName string +// - args ...interface{} +func (_e *Cache_Expecter) Get(it interface{}, indexName interface{}, args ...interface{}) *Cache_Get_Call { + return &Cache_Get_Call{Call: _e.mock.On("Get", + append([]interface{}{it, indexName}, args...)...)} +} + +func (_c *Cache_Get_Call) Run(run func(it *pbresource.Type, indexName string, args ...interface{})) *Cache_Get_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(*pbresource.Type), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *Cache_Get_Call) Return(_a0 *pbresource.Resource, _a1 error) *Cache_Get_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Cache_Get_Call) RunAndReturn(run func(*pbresource.Type, string, ...interface{}) (*pbresource.Resource, error)) *Cache_Get_Call { + _c.Call.Return(run) + return _c +} + +// Insert provides a mock function with given fields: r +func (_m *Cache) Insert(r *pbresource.Resource) error { + ret := _m.Called(r) + + var r0 error + if rf, ok := ret.Get(0).(func(*pbresource.Resource) error); ok { + r0 = rf(r) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Cache_Insert_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Insert' +type Cache_Insert_Call struct { + *mock.Call +} + +// Insert is a helper method to define mock.On call +// - r *pbresource.Resource +func (_e *Cache_Expecter) Insert(r interface{}) *Cache_Insert_Call { + return &Cache_Insert_Call{Call: _e.mock.On("Insert", r)} +} + +func (_c *Cache_Insert_Call) Run(run func(r *pbresource.Resource)) *Cache_Insert_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbresource.Resource)) + }) + return _c +} + +func (_c *Cache_Insert_Call) Return(_a0 error) *Cache_Insert_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Cache_Insert_Call) RunAndReturn(run func(*pbresource.Resource) error) *Cache_Insert_Call { + _c.Call.Return(run) + return _c +} + +// List provides a mock function with given fields: it, indexName, args +func (_m *Cache) List(it *pbresource.Type, indexName string, args ...interface{}) ([]*pbresource.Resource, error) { + var _ca []interface{} + _ca = append(_ca, it, indexName) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 []*pbresource.Resource + var r1 error + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) ([]*pbresource.Resource, error)); ok { + return rf(it, indexName, args...) + } + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) []*pbresource.Resource); ok { + r0 = rf(it, indexName, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*pbresource.Resource) + } + } + + if rf, ok := ret.Get(1).(func(*pbresource.Type, string, ...interface{}) error); ok { + r1 = rf(it, indexName, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Cache_List_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'List' +type Cache_List_Call struct { + *mock.Call +} + +// List is a helper method to define mock.On call +// - it *pbresource.Type +// - indexName string +// - args ...interface{} +func (_e *Cache_Expecter) List(it interface{}, indexName interface{}, args ...interface{}) *Cache_List_Call { + return &Cache_List_Call{Call: _e.mock.On("List", + append([]interface{}{it, indexName}, args...)...)} +} + +func (_c *Cache_List_Call) Run(run func(it *pbresource.Type, indexName string, args ...interface{})) *Cache_List_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(*pbresource.Type), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *Cache_List_Call) Return(_a0 []*pbresource.Resource, _a1 error) *Cache_List_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Cache_List_Call) RunAndReturn(run func(*pbresource.Type, string, ...interface{}) ([]*pbresource.Resource, error)) *Cache_List_Call { + _c.Call.Return(run) + return _c +} + +// ListIterator provides a mock function with given fields: it, indexName, args +func (_m *Cache) ListIterator(it *pbresource.Type, indexName string, args ...interface{}) (cache.ResourceIterator, error) { + var _ca []interface{} + _ca = append(_ca, it, indexName) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 cache.ResourceIterator + var r1 error + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) (cache.ResourceIterator, error)); ok { + return rf(it, indexName, args...) + } + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) cache.ResourceIterator); ok { + r0 = rf(it, indexName, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(cache.ResourceIterator) + } + } + + if rf, ok := ret.Get(1).(func(*pbresource.Type, string, ...interface{}) error); ok { + r1 = rf(it, indexName, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Cache_ListIterator_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListIterator' +type Cache_ListIterator_Call struct { + *mock.Call +} + +// ListIterator is a helper method to define mock.On call +// - it *pbresource.Type +// - indexName string +// - args ...interface{} +func (_e *Cache_Expecter) ListIterator(it interface{}, indexName interface{}, args ...interface{}) *Cache_ListIterator_Call { + return &Cache_ListIterator_Call{Call: _e.mock.On("ListIterator", + append([]interface{}{it, indexName}, args...)...)} +} + +func (_c *Cache_ListIterator_Call) Run(run func(it *pbresource.Type, indexName string, args ...interface{})) *Cache_ListIterator_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(*pbresource.Type), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *Cache_ListIterator_Call) Return(_a0 cache.ResourceIterator, _a1 error) *Cache_ListIterator_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Cache_ListIterator_Call) RunAndReturn(run func(*pbresource.Type, string, ...interface{}) (cache.ResourceIterator, error)) *Cache_ListIterator_Call { + _c.Call.Return(run) + return _c +} + +// Parents provides a mock function with given fields: it, indexName, args +func (_m *Cache) Parents(it *pbresource.Type, indexName string, args ...interface{}) ([]*pbresource.Resource, error) { + var _ca []interface{} + _ca = append(_ca, it, indexName) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 []*pbresource.Resource + var r1 error + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) ([]*pbresource.Resource, error)); ok { + return rf(it, indexName, args...) + } + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) []*pbresource.Resource); ok { + r0 = rf(it, indexName, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*pbresource.Resource) + } + } + + if rf, ok := ret.Get(1).(func(*pbresource.Type, string, ...interface{}) error); ok { + r1 = rf(it, indexName, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Cache_Parents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Parents' +type Cache_Parents_Call struct { + *mock.Call +} + +// Parents is a helper method to define mock.On call +// - it *pbresource.Type +// - indexName string +// - args ...interface{} +func (_e *Cache_Expecter) Parents(it interface{}, indexName interface{}, args ...interface{}) *Cache_Parents_Call { + return &Cache_Parents_Call{Call: _e.mock.On("Parents", + append([]interface{}{it, indexName}, args...)...)} +} + +func (_c *Cache_Parents_Call) Run(run func(it *pbresource.Type, indexName string, args ...interface{})) *Cache_Parents_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(*pbresource.Type), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *Cache_Parents_Call) Return(_a0 []*pbresource.Resource, _a1 error) *Cache_Parents_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Cache_Parents_Call) RunAndReturn(run func(*pbresource.Type, string, ...interface{}) ([]*pbresource.Resource, error)) *Cache_Parents_Call { + _c.Call.Return(run) + return _c +} + +// ParentsIterator provides a mock function with given fields: it, indexName, args +func (_m *Cache) ParentsIterator(it *pbresource.Type, indexName string, args ...interface{}) (cache.ResourceIterator, error) { + var _ca []interface{} + _ca = append(_ca, it, indexName) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 cache.ResourceIterator + var r1 error + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) (cache.ResourceIterator, error)); ok { + return rf(it, indexName, args...) + } + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) cache.ResourceIterator); ok { + r0 = rf(it, indexName, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(cache.ResourceIterator) + } + } + + if rf, ok := ret.Get(1).(func(*pbresource.Type, string, ...interface{}) error); ok { + r1 = rf(it, indexName, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Cache_ParentsIterator_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParentsIterator' +type Cache_ParentsIterator_Call struct { + *mock.Call +} + +// ParentsIterator is a helper method to define mock.On call +// - it *pbresource.Type +// - indexName string +// - args ...interface{} +func (_e *Cache_Expecter) ParentsIterator(it interface{}, indexName interface{}, args ...interface{}) *Cache_ParentsIterator_Call { + return &Cache_ParentsIterator_Call{Call: _e.mock.On("ParentsIterator", + append([]interface{}{it, indexName}, args...)...)} +} + +func (_c *Cache_ParentsIterator_Call) Run(run func(it *pbresource.Type, indexName string, args ...interface{})) *Cache_ParentsIterator_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(*pbresource.Type), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *Cache_ParentsIterator_Call) Return(_a0 cache.ResourceIterator, _a1 error) *Cache_ParentsIterator_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Cache_ParentsIterator_Call) RunAndReturn(run func(*pbresource.Type, string, ...interface{}) (cache.ResourceIterator, error)) *Cache_ParentsIterator_Call { + _c.Call.Return(run) + return _c +} + +// Query provides a mock function with given fields: name, args +func (_m *Cache) Query(name string, args ...interface{}) (cache.ResourceIterator, error) { + var _ca []interface{} + _ca = append(_ca, name) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 cache.ResourceIterator + var r1 error + if rf, ok := ret.Get(0).(func(string, ...interface{}) (cache.ResourceIterator, error)); ok { + return rf(name, args...) + } + if rf, ok := ret.Get(0).(func(string, ...interface{}) cache.ResourceIterator); ok { + r0 = rf(name, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(cache.ResourceIterator) + } + } + + if rf, ok := ret.Get(1).(func(string, ...interface{}) error); ok { + r1 = rf(name, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Cache_Query_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Query' +type Cache_Query_Call struct { + *mock.Call +} + +// Query is a helper method to define mock.On call +// - name string +// - args ...interface{} +func (_e *Cache_Expecter) Query(name interface{}, args ...interface{}) *Cache_Query_Call { + return &Cache_Query_Call{Call: _e.mock.On("Query", + append([]interface{}{name}, args...)...)} +} + +func (_c *Cache_Query_Call) Run(run func(name string, args ...interface{})) *Cache_Query_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(string), variadicArgs...) + }) + return _c +} + +func (_c *Cache_Query_Call) Return(_a0 cache.ResourceIterator, _a1 error) *Cache_Query_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Cache_Query_Call) RunAndReturn(run func(string, ...interface{}) (cache.ResourceIterator, error)) *Cache_Query_Call { + _c.Call.Return(run) + return _c +} + +// NewCache creates a new instance of Cache. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewCache(t interface { + mock.TestingT + Cleanup(func()) +}) *Cache { + mock := &Cache{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/cachemock/mock_Query.go b/internal/controller/cache/cachemock/mock_Query.go new file mode 100644 index 000000000000..3c3311cce9fc --- /dev/null +++ b/internal/controller/cache/cachemock/mock_Query.go @@ -0,0 +1,100 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package cachemock + +import ( + cache "github.com/hashicorp/consul/internal/controller/cache" + mock "github.com/stretchr/testify/mock" +) + +// Query is an autogenerated mock type for the Query type +type Query struct { + mock.Mock +} + +type Query_Expecter struct { + mock *mock.Mock +} + +func (_m *Query) EXPECT() *Query_Expecter { + return &Query_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: c, args +func (_m *Query) Execute(c cache.ReadOnlyCache, args ...interface{}) (cache.ResourceIterator, error) { + var _ca []interface{} + _ca = append(_ca, c) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 cache.ResourceIterator + var r1 error + if rf, ok := ret.Get(0).(func(cache.ReadOnlyCache, ...interface{}) (cache.ResourceIterator, error)); ok { + return rf(c, args...) + } + if rf, ok := ret.Get(0).(func(cache.ReadOnlyCache, ...interface{}) cache.ResourceIterator); ok { + r0 = rf(c, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(cache.ResourceIterator) + } + } + + if rf, ok := ret.Get(1).(func(cache.ReadOnlyCache, ...interface{}) error); ok { + r1 = rf(c, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Query_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type Query_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - c cache.ReadOnlyCache +// - args ...interface{} +func (_e *Query_Expecter) Execute(c interface{}, args ...interface{}) *Query_Execute_Call { + return &Query_Execute_Call{Call: _e.mock.On("Execute", + append([]interface{}{c}, args...)...)} +} + +func (_c *Query_Execute_Call) Run(run func(c cache.ReadOnlyCache, args ...interface{})) *Query_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(cache.ReadOnlyCache), variadicArgs...) + }) + return _c +} + +func (_c *Query_Execute_Call) Return(_a0 cache.ResourceIterator, _a1 error) *Query_Execute_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Query_Execute_Call) RunAndReturn(run func(cache.ReadOnlyCache, ...interface{}) (cache.ResourceIterator, error)) *Query_Execute_Call { + _c.Call.Return(run) + return _c +} + +// NewQuery creates a new instance of Query. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewQuery(t interface { + mock.TestingT + Cleanup(func()) +}) *Query { + mock := &Query{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/cachemock/mock_ReadOnlyCache.go b/internal/controller/cache/cachemock/mock_ReadOnlyCache.go new file mode 100644 index 000000000000..8d2f346a5dcb --- /dev/null +++ b/internal/controller/cache/cachemock/mock_ReadOnlyCache.go @@ -0,0 +1,432 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package cachemock + +import ( + cache "github.com/hashicorp/consul/internal/controller/cache" + mock "github.com/stretchr/testify/mock" + + pbresource "github.com/hashicorp/consul/proto-public/pbresource" +) + +// ReadOnlyCache is an autogenerated mock type for the ReadOnlyCache type +type ReadOnlyCache struct { + mock.Mock +} + +type ReadOnlyCache_Expecter struct { + mock *mock.Mock +} + +func (_m *ReadOnlyCache) EXPECT() *ReadOnlyCache_Expecter { + return &ReadOnlyCache_Expecter{mock: &_m.Mock} +} + +// Get provides a mock function with given fields: it, indexName, args +func (_m *ReadOnlyCache) Get(it *pbresource.Type, indexName string, args ...interface{}) (*pbresource.Resource, error) { + var _ca []interface{} + _ca = append(_ca, it, indexName) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 *pbresource.Resource + var r1 error + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) (*pbresource.Resource, error)); ok { + return rf(it, indexName, args...) + } + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) *pbresource.Resource); ok { + r0 = rf(it, indexName, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.Resource) + } + } + + if rf, ok := ret.Get(1).(func(*pbresource.Type, string, ...interface{}) error); ok { + r1 = rf(it, indexName, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ReadOnlyCache_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' +type ReadOnlyCache_Get_Call struct { + *mock.Call +} + +// Get is a helper method to define mock.On call +// - it *pbresource.Type +// - indexName string +// - args ...interface{} +func (_e *ReadOnlyCache_Expecter) Get(it interface{}, indexName interface{}, args ...interface{}) *ReadOnlyCache_Get_Call { + return &ReadOnlyCache_Get_Call{Call: _e.mock.On("Get", + append([]interface{}{it, indexName}, args...)...)} +} + +func (_c *ReadOnlyCache_Get_Call) Run(run func(it *pbresource.Type, indexName string, args ...interface{})) *ReadOnlyCache_Get_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(*pbresource.Type), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *ReadOnlyCache_Get_Call) Return(_a0 *pbresource.Resource, _a1 error) *ReadOnlyCache_Get_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ReadOnlyCache_Get_Call) RunAndReturn(run func(*pbresource.Type, string, ...interface{}) (*pbresource.Resource, error)) *ReadOnlyCache_Get_Call { + _c.Call.Return(run) + return _c +} + +// List provides a mock function with given fields: it, indexName, args +func (_m *ReadOnlyCache) List(it *pbresource.Type, indexName string, args ...interface{}) ([]*pbresource.Resource, error) { + var _ca []interface{} + _ca = append(_ca, it, indexName) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 []*pbresource.Resource + var r1 error + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) ([]*pbresource.Resource, error)); ok { + return rf(it, indexName, args...) + } + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) []*pbresource.Resource); ok { + r0 = rf(it, indexName, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*pbresource.Resource) + } + } + + if rf, ok := ret.Get(1).(func(*pbresource.Type, string, ...interface{}) error); ok { + r1 = rf(it, indexName, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ReadOnlyCache_List_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'List' +type ReadOnlyCache_List_Call struct { + *mock.Call +} + +// List is a helper method to define mock.On call +// - it *pbresource.Type +// - indexName string +// - args ...interface{} +func (_e *ReadOnlyCache_Expecter) List(it interface{}, indexName interface{}, args ...interface{}) *ReadOnlyCache_List_Call { + return &ReadOnlyCache_List_Call{Call: _e.mock.On("List", + append([]interface{}{it, indexName}, args...)...)} +} + +func (_c *ReadOnlyCache_List_Call) Run(run func(it *pbresource.Type, indexName string, args ...interface{})) *ReadOnlyCache_List_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(*pbresource.Type), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *ReadOnlyCache_List_Call) Return(_a0 []*pbresource.Resource, _a1 error) *ReadOnlyCache_List_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ReadOnlyCache_List_Call) RunAndReturn(run func(*pbresource.Type, string, ...interface{}) ([]*pbresource.Resource, error)) *ReadOnlyCache_List_Call { + _c.Call.Return(run) + return _c +} + +// ListIterator provides a mock function with given fields: it, indexName, args +func (_m *ReadOnlyCache) ListIterator(it *pbresource.Type, indexName string, args ...interface{}) (cache.ResourceIterator, error) { + var _ca []interface{} + _ca = append(_ca, it, indexName) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 cache.ResourceIterator + var r1 error + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) (cache.ResourceIterator, error)); ok { + return rf(it, indexName, args...) + } + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) cache.ResourceIterator); ok { + r0 = rf(it, indexName, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(cache.ResourceIterator) + } + } + + if rf, ok := ret.Get(1).(func(*pbresource.Type, string, ...interface{}) error); ok { + r1 = rf(it, indexName, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ReadOnlyCache_ListIterator_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListIterator' +type ReadOnlyCache_ListIterator_Call struct { + *mock.Call +} + +// ListIterator is a helper method to define mock.On call +// - it *pbresource.Type +// - indexName string +// - args ...interface{} +func (_e *ReadOnlyCache_Expecter) ListIterator(it interface{}, indexName interface{}, args ...interface{}) *ReadOnlyCache_ListIterator_Call { + return &ReadOnlyCache_ListIterator_Call{Call: _e.mock.On("ListIterator", + append([]interface{}{it, indexName}, args...)...)} +} + +func (_c *ReadOnlyCache_ListIterator_Call) Run(run func(it *pbresource.Type, indexName string, args ...interface{})) *ReadOnlyCache_ListIterator_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(*pbresource.Type), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *ReadOnlyCache_ListIterator_Call) Return(_a0 cache.ResourceIterator, _a1 error) *ReadOnlyCache_ListIterator_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ReadOnlyCache_ListIterator_Call) RunAndReturn(run func(*pbresource.Type, string, ...interface{}) (cache.ResourceIterator, error)) *ReadOnlyCache_ListIterator_Call { + _c.Call.Return(run) + return _c +} + +// Parents provides a mock function with given fields: it, indexName, args +func (_m *ReadOnlyCache) Parents(it *pbresource.Type, indexName string, args ...interface{}) ([]*pbresource.Resource, error) { + var _ca []interface{} + _ca = append(_ca, it, indexName) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 []*pbresource.Resource + var r1 error + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) ([]*pbresource.Resource, error)); ok { + return rf(it, indexName, args...) + } + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) []*pbresource.Resource); ok { + r0 = rf(it, indexName, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*pbresource.Resource) + } + } + + if rf, ok := ret.Get(1).(func(*pbresource.Type, string, ...interface{}) error); ok { + r1 = rf(it, indexName, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ReadOnlyCache_Parents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Parents' +type ReadOnlyCache_Parents_Call struct { + *mock.Call +} + +// Parents is a helper method to define mock.On call +// - it *pbresource.Type +// - indexName string +// - args ...interface{} +func (_e *ReadOnlyCache_Expecter) Parents(it interface{}, indexName interface{}, args ...interface{}) *ReadOnlyCache_Parents_Call { + return &ReadOnlyCache_Parents_Call{Call: _e.mock.On("Parents", + append([]interface{}{it, indexName}, args...)...)} +} + +func (_c *ReadOnlyCache_Parents_Call) Run(run func(it *pbresource.Type, indexName string, args ...interface{})) *ReadOnlyCache_Parents_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(*pbresource.Type), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *ReadOnlyCache_Parents_Call) Return(_a0 []*pbresource.Resource, _a1 error) *ReadOnlyCache_Parents_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ReadOnlyCache_Parents_Call) RunAndReturn(run func(*pbresource.Type, string, ...interface{}) ([]*pbresource.Resource, error)) *ReadOnlyCache_Parents_Call { + _c.Call.Return(run) + return _c +} + +// ParentsIterator provides a mock function with given fields: it, indexName, args +func (_m *ReadOnlyCache) ParentsIterator(it *pbresource.Type, indexName string, args ...interface{}) (cache.ResourceIterator, error) { + var _ca []interface{} + _ca = append(_ca, it, indexName) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 cache.ResourceIterator + var r1 error + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) (cache.ResourceIterator, error)); ok { + return rf(it, indexName, args...) + } + if rf, ok := ret.Get(0).(func(*pbresource.Type, string, ...interface{}) cache.ResourceIterator); ok { + r0 = rf(it, indexName, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(cache.ResourceIterator) + } + } + + if rf, ok := ret.Get(1).(func(*pbresource.Type, string, ...interface{}) error); ok { + r1 = rf(it, indexName, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ReadOnlyCache_ParentsIterator_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParentsIterator' +type ReadOnlyCache_ParentsIterator_Call struct { + *mock.Call +} + +// ParentsIterator is a helper method to define mock.On call +// - it *pbresource.Type +// - indexName string +// - args ...interface{} +func (_e *ReadOnlyCache_Expecter) ParentsIterator(it interface{}, indexName interface{}, args ...interface{}) *ReadOnlyCache_ParentsIterator_Call { + return &ReadOnlyCache_ParentsIterator_Call{Call: _e.mock.On("ParentsIterator", + append([]interface{}{it, indexName}, args...)...)} +} + +func (_c *ReadOnlyCache_ParentsIterator_Call) Run(run func(it *pbresource.Type, indexName string, args ...interface{})) *ReadOnlyCache_ParentsIterator_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(*pbresource.Type), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *ReadOnlyCache_ParentsIterator_Call) Return(_a0 cache.ResourceIterator, _a1 error) *ReadOnlyCache_ParentsIterator_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ReadOnlyCache_ParentsIterator_Call) RunAndReturn(run func(*pbresource.Type, string, ...interface{}) (cache.ResourceIterator, error)) *ReadOnlyCache_ParentsIterator_Call { + _c.Call.Return(run) + return _c +} + +// Query provides a mock function with given fields: name, args +func (_m *ReadOnlyCache) Query(name string, args ...interface{}) (cache.ResourceIterator, error) { + var _ca []interface{} + _ca = append(_ca, name) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 cache.ResourceIterator + var r1 error + if rf, ok := ret.Get(0).(func(string, ...interface{}) (cache.ResourceIterator, error)); ok { + return rf(name, args...) + } + if rf, ok := ret.Get(0).(func(string, ...interface{}) cache.ResourceIterator); ok { + r0 = rf(name, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(cache.ResourceIterator) + } + } + + if rf, ok := ret.Get(1).(func(string, ...interface{}) error); ok { + r1 = rf(name, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ReadOnlyCache_Query_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Query' +type ReadOnlyCache_Query_Call struct { + *mock.Call +} + +// Query is a helper method to define mock.On call +// - name string +// - args ...interface{} +func (_e *ReadOnlyCache_Expecter) Query(name interface{}, args ...interface{}) *ReadOnlyCache_Query_Call { + return &ReadOnlyCache_Query_Call{Call: _e.mock.On("Query", + append([]interface{}{name}, args...)...)} +} + +func (_c *ReadOnlyCache_Query_Call) Run(run func(name string, args ...interface{})) *ReadOnlyCache_Query_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(string), variadicArgs...) + }) + return _c +} + +func (_c *ReadOnlyCache_Query_Call) Return(_a0 cache.ResourceIterator, _a1 error) *ReadOnlyCache_Query_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ReadOnlyCache_Query_Call) RunAndReturn(run func(string, ...interface{}) (cache.ResourceIterator, error)) *ReadOnlyCache_Query_Call { + _c.Call.Return(run) + return _c +} + +// NewReadOnlyCache creates a new instance of ReadOnlyCache. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewReadOnlyCache(t interface { + mock.TestingT + Cleanup(func()) +}) *ReadOnlyCache { + mock := &ReadOnlyCache{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/cachemock/mock_ResourceIterator.go b/internal/controller/cache/cachemock/mock_ResourceIterator.go new file mode 100644 index 000000000000..63178fcdf3d9 --- /dev/null +++ b/internal/controller/cache/cachemock/mock_ResourceIterator.go @@ -0,0 +1,78 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package cachemock + +import ( + pbresource "github.com/hashicorp/consul/proto-public/pbresource" + mock "github.com/stretchr/testify/mock" +) + +// ResourceIterator is an autogenerated mock type for the ResourceIterator type +type ResourceIterator struct { + mock.Mock +} + +type ResourceIterator_Expecter struct { + mock *mock.Mock +} + +func (_m *ResourceIterator) EXPECT() *ResourceIterator_Expecter { + return &ResourceIterator_Expecter{mock: &_m.Mock} +} + +// Next provides a mock function with given fields: +func (_m *ResourceIterator) Next() *pbresource.Resource { + ret := _m.Called() + + var r0 *pbresource.Resource + if rf, ok := ret.Get(0).(func() *pbresource.Resource); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.Resource) + } + } + + return r0 +} + +// ResourceIterator_Next_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Next' +type ResourceIterator_Next_Call struct { + *mock.Call +} + +// Next is a helper method to define mock.On call +func (_e *ResourceIterator_Expecter) Next() *ResourceIterator_Next_Call { + return &ResourceIterator_Next_Call{Call: _e.mock.On("Next")} +} + +func (_c *ResourceIterator_Next_Call) Run(run func()) *ResourceIterator_Next_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ResourceIterator_Next_Call) Return(_a0 *pbresource.Resource) *ResourceIterator_Next_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceIterator_Next_Call) RunAndReturn(run func() *pbresource.Resource) *ResourceIterator_Next_Call { + _c.Call.Return(run) + return _c +} + +// NewResourceIterator creates a new instance of ResourceIterator. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewResourceIterator(t interface { + mock.TestingT + Cleanup(func()) +}) *ResourceIterator { + mock := &ResourceIterator{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/cachemock/mock_WriteCache.go b/internal/controller/cache/cachemock/mock_WriteCache.go new file mode 100644 index 000000000000..ef51b380d827 --- /dev/null +++ b/internal/controller/cache/cachemock/mock_WriteCache.go @@ -0,0 +1,119 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package cachemock + +import ( + pbresource "github.com/hashicorp/consul/proto-public/pbresource" + mock "github.com/stretchr/testify/mock" +) + +// WriteCache is an autogenerated mock type for the WriteCache type +type WriteCache struct { + mock.Mock +} + +type WriteCache_Expecter struct { + mock *mock.Mock +} + +func (_m *WriteCache) EXPECT() *WriteCache_Expecter { + return &WriteCache_Expecter{mock: &_m.Mock} +} + +// Delete provides a mock function with given fields: r +func (_m *WriteCache) Delete(r *pbresource.Resource) error { + ret := _m.Called(r) + + var r0 error + if rf, ok := ret.Get(0).(func(*pbresource.Resource) error); ok { + r0 = rf(r) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// WriteCache_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' +type WriteCache_Delete_Call struct { + *mock.Call +} + +// Delete is a helper method to define mock.On call +// - r *pbresource.Resource +func (_e *WriteCache_Expecter) Delete(r interface{}) *WriteCache_Delete_Call { + return &WriteCache_Delete_Call{Call: _e.mock.On("Delete", r)} +} + +func (_c *WriteCache_Delete_Call) Run(run func(r *pbresource.Resource)) *WriteCache_Delete_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbresource.Resource)) + }) + return _c +} + +func (_c *WriteCache_Delete_Call) Return(_a0 error) *WriteCache_Delete_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *WriteCache_Delete_Call) RunAndReturn(run func(*pbresource.Resource) error) *WriteCache_Delete_Call { + _c.Call.Return(run) + return _c +} + +// Insert provides a mock function with given fields: r +func (_m *WriteCache) Insert(r *pbresource.Resource) error { + ret := _m.Called(r) + + var r0 error + if rf, ok := ret.Get(0).(func(*pbresource.Resource) error); ok { + r0 = rf(r) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// WriteCache_Insert_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Insert' +type WriteCache_Insert_Call struct { + *mock.Call +} + +// Insert is a helper method to define mock.On call +// - r *pbresource.Resource +func (_e *WriteCache_Expecter) Insert(r interface{}) *WriteCache_Insert_Call { + return &WriteCache_Insert_Call{Call: _e.mock.On("Insert", r)} +} + +func (_c *WriteCache_Insert_Call) Run(run func(r *pbresource.Resource)) *WriteCache_Insert_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbresource.Resource)) + }) + return _c +} + +func (_c *WriteCache_Insert_Call) Return(_a0 error) *WriteCache_Insert_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *WriteCache_Insert_Call) RunAndReturn(run func(*pbresource.Resource) error) *WriteCache_Insert_Call { + _c.Call.Return(run) + return _c +} + +// NewWriteCache creates a new instance of WriteCache. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewWriteCache(t interface { + mock.TestingT + Cleanup(func()) +}) *WriteCache { + mock := &WriteCache{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/client.go b/internal/controller/cache/client.go new file mode 100644 index 000000000000..df37c7381cb9 --- /dev/null +++ b/internal/controller/cache/client.go @@ -0,0 +1,56 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cache + +import ( + "context" + + "github.com/hashicorp/consul/proto-public/pbresource" + "google.golang.org/grpc" +) + +type writeThroughCacheClient struct { + cache WriteCache + pbresource.ResourceServiceClient +} + +func NewCachedClient(cache WriteCache, client pbresource.ResourceServiceClient) pbresource.ResourceServiceClient { + return &writeThroughCacheClient{ + cache: cache, + ResourceServiceClient: client, + } +} + +func (c *writeThroughCacheClient) Write(ctx context.Context, in *pbresource.WriteRequest, opts ...grpc.CallOption) (*pbresource.WriteResponse, error) { + rsp, err := c.ResourceServiceClient.Write(ctx, in, opts...) + if err != nil { + return rsp, err + } + + // There was no error so insert the resource into the cache + c.cache.Insert(rsp.Resource) + return rsp, err +} + +func (c *writeThroughCacheClient) WriteStatus(ctx context.Context, in *pbresource.WriteStatusRequest, opts ...grpc.CallOption) (*pbresource.WriteStatusResponse, error) { + rsp, err := c.ResourceServiceClient.WriteStatus(ctx, in, opts...) + if err != nil { + return rsp, err + } + + // There was no error so insert the resource into the cache + c.cache.Insert(rsp.Resource) + return rsp, err +} + +func (c *writeThroughCacheClient) Delete(ctx context.Context, in *pbresource.DeleteRequest, opts ...grpc.CallOption) (*pbresource.DeleteResponse, error) { + rsp, err := c.ResourceServiceClient.Delete(ctx, in, opts...) + if err != nil { + return rsp, err + } + + // There was no error so delete the resource from the cache + c.cache.Delete(&pbresource.Resource{Id: in.Id}) + return rsp, err +} diff --git a/internal/controller/cache/client_test.go b/internal/controller/cache/client_test.go new file mode 100644 index 000000000000..9e167a84bf87 --- /dev/null +++ b/internal/controller/cache/client_test.go @@ -0,0 +1,265 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cache + +import ( + "context" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + mockpbresource "github.com/hashicorp/consul/grpcmocks/proto-public/pbresource" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v1" + "github.com/hashicorp/consul/proto/private/prototest" +) + +type cacheClientSuite struct { + suite.Suite + + cache Cache + mclient *mockpbresource.ResourceServiceClient_Expecter + client pbresource.ResourceServiceClient + + album1 *pbresource.Resource + album2 *pbresource.Resource +} + +func (suite *cacheClientSuite) SetupTest() { + suite.cache = New() + + // It would be difficult to use the inmem resource service here due to cyclical dependencies. + // Any type registrations from other packages cannot be imported because those packages + // will require the controller package which will require this cache package. The easiest + // way of getting around this was to not use the real resource service and require type registrations. + client := mockpbresource.NewResourceServiceClient(suite.T()) + suite.mclient = client.EXPECT() + + require.NoError(suite.T(), suite.cache.AddIndex(pbdemo.AlbumType, namePrefixIndexer())) + require.NoError(suite.T(), suite.cache.AddIndex(pbdemo.AlbumType, releaseYearIndexer())) + require.NoError(suite.T(), suite.cache.AddIndex(pbdemo.AlbumType, tracksIndexer())) + + suite.album1 = resourcetest.Resource(pbdemo.AlbumType, "one"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(suite.T(), &pbdemo.Album{ + Name: "one", + YearOfRelease: 2023, + Tracks: []string{"foo", "bar", "baz"}, + }). + Build() + + suite.album2 = resourcetest.Resource(pbdemo.AlbumType, "two"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(suite.T(), &pbdemo.Album{ + Name: "two", + YearOfRelease: 2023, + Tracks: []string{"fangorn", "zoo"}, + }). + Build() + + suite.cache.Insert(suite.album1) + suite.cache.Insert(suite.album2) + + suite.client = NewCachedClient(suite.cache, client) +} + +func (suite *cacheClientSuite) performWrite(res *pbresource.Resource, shouldError bool) { + req := &pbresource.WriteRequest{ + Resource: res, + } + + // Setup the expectation for the inner mocked client to receive the real request + if shouldError { + suite.mclient.Write(mock.Anything, req). + Return(nil, fakeWrappedErr). + Once() + } else { + suite.mclient.Write(mock.Anything, req). + Return(&pbresource.WriteResponse{ + Resource: res, + }, nil). + Once() + } + + // Now use the wrapper client to perform the request + out, err := suite.client.Write(context.Background(), req) + if shouldError { + require.ErrorIs(suite.T(), err, fakeWrappedErr) + require.Nil(suite.T(), out) + } else { + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), res, out.Resource) + } +} + +func (suite *cacheClientSuite) performDelete(id *pbresource.ID, shouldError bool) { + req := &pbresource.DeleteRequest{ + Id: id, + } + + // Setup the expectation for the inner mocked client to receive the real request + if shouldError { + suite.mclient.Delete(mock.Anything, req). + Return(nil, fakeWrappedErr). + Once() + } else { + suite.mclient.Delete(mock.Anything, req). + Return(&pbresource.DeleteResponse{}, nil). + Once() + } + + // Now use the wrapper client to perform the request + out, err := suite.client.Delete(context.Background(), req) + if shouldError { + require.ErrorIs(suite.T(), err, fakeWrappedErr) + require.Nil(suite.T(), out) + } else { + require.NoError(suite.T(), err) + require.NotNil(suite.T(), out) + } +} + +func (suite *cacheClientSuite) performWriteStatus(res *pbresource.Resource, key string, status *pbresource.Status, shouldError bool) { + req := &pbresource.WriteStatusRequest{ + Id: res.Id, + Key: key, + Status: status, + } + + // Setup the expectation for the inner mocked client to receive the real request + if shouldError { + suite.mclient.WriteStatus(mock.Anything, req). + Return(nil, fakeWrappedErr). + Once() + } else { + suite.mclient.WriteStatus(mock.Anything, req). + Return(&pbresource.WriteStatusResponse{ + Resource: res, + }, nil). + Once() + } + + // Now use the wrapper client to perform the request + out, err := suite.client.WriteStatus(context.Background(), req) + if shouldError { + require.ErrorIs(suite.T(), err, fakeWrappedErr) + require.Nil(suite.T(), out) + } else { + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), res, out.Resource) + } +} + +func (suite *cacheClientSuite) TestWrite_Ok() { + newRes := resourcetest.ResourceID(suite.album1.Id). + WithTenancy(&pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + }). + WithData(suite.T(), &pbdemo.Album{ + Name: "changed", + YearOfRelease: 2023, + Tracks: []string{"fangorn", "zoo"}, + }). + Build() + + suite.performWrite(newRes, false) + + // now ensure the entry was updated in the cache + res, err := suite.cache.Get(suite.album1.Id.Type, "id", suite.album1.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), res) + prototest.AssertDeepEqual(suite.T(), newRes, res) +} + +func (suite *cacheClientSuite) TestWrite_Error() { + newRes := resourcetest.ResourceID(suite.album1.Id). + WithData(suite.T(), &pbdemo.Album{ + Name: "changed", + YearOfRelease: 2023, + Tracks: []string{"fangorn", "zoo"}, + }). + WithVersion("notaversion"). + Build() + + suite.performWrite(newRes, true) + + // now ensure the entry was not updated in the cache + res, err := suite.cache.Get(suite.album1.Id.Type, "id", suite.album1.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), res) + prototest.AssertDeepEqual(suite.T(), suite.album1, res) +} + +func (suite *cacheClientSuite) TestWriteStatus_Ok() { + status := &pbresource.Status{ObservedGeneration: suite.album1.Generation} + + updatedRes := resourcetest.ResourceID(suite.album1.Id). + WithData(suite.T(), &pbdemo.Album{ + Name: "changed", + YearOfRelease: 2023, + Tracks: []string{"fangorn", "zoo"}, + }). + WithStatus("testing", status). + WithVersion("notaversion"). + Build() + + suite.performWriteStatus(updatedRes, "testing", status, false) + + // now ensure the entry was updated in the cache + res, err := suite.cache.Get(suite.album1.Id.Type, "id", suite.album1.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), res) + _, updated := res.Status["testing"] + require.True(suite.T(), updated) +} + +func (suite *cacheClientSuite) TestWriteStatus_Error() { + status := &pbresource.Status{ObservedGeneration: suite.album1.Generation} + + updatedRes := resourcetest.ResourceID(suite.album1.Id). + WithData(suite.T(), &pbdemo.Album{ + Name: "changed", + YearOfRelease: 2023, + Tracks: []string{"fangorn", "zoo"}, + }). + WithStatus("testing", status). + WithVersion("notaversion"). + Build() + + suite.performWriteStatus(updatedRes, "testing", status, true) + + // now ensure the entry was not updated in the cache + res, err := suite.cache.Get(suite.album1.Id.Type, "id", suite.album1.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), res) + _, updated := res.Status["testing"] + require.False(suite.T(), updated) +} + +func (suite *cacheClientSuite) TestDelete_Ok() { + suite.performDelete(suite.album1.Id, false) + + // now ensure the entry was removed from the cache + res, err := suite.cache.Get(suite.album1.Id.Type, "id", suite.album1.Id) + require.NoError(suite.T(), err) + require.Nil(suite.T(), res) +} + +func (suite *cacheClientSuite) TestDelete_Error() { + suite.performDelete(suite.album1.Id, true) + + // now ensure the entry was NOT removed from the cache + res, err := suite.cache.Get(suite.album1.Id.Type, "id", suite.album1.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), res) +} + +func TestCacheClient(t *testing.T) { + suite.Run(t, new(cacheClientSuite)) +} diff --git a/internal/controller/cache/clone.go b/internal/controller/cache/clone.go new file mode 100644 index 000000000000..056dc0ca1e44 --- /dev/null +++ b/internal/controller/cache/clone.go @@ -0,0 +1,93 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cache + +import ( + "github.com/hashicorp/consul/internal/protoutil" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// NewCloningReadOnlyCache will wrap the provided ReadOnlyCache with +// an implementation which clones resources that are read out of the cache. +// +// In order to protect the Cache (and the resource service it shares resources with) +// from accidental user modification, the ReadOnlyCache interface is wrapped with +// the cloning variant. This wrapped/cloning cache is then what is given to +// dependency mappers and controller reconcilers. This allows those methods to +// freely modify data they get back from the cache without having to worry about +// accidental data modifications that could wreck the consistent state storage. +func NewCloningReadOnlyCache(cache ReadOnlyCache) ReadOnlyCache { + return cloningReadOnlyCache{ReadOnlyCache: cache} +} + +type cloningReadOnlyCache struct { + ReadOnlyCache +} + +func (c cloningReadOnlyCache) Get(it *pbresource.Type, indexName string, args ...any) (*pbresource.Resource, error) { + res, err := c.ReadOnlyCache.Get(it, indexName, args...) + if err != nil { + return nil, err + } + + return protoutil.Clone(res), nil +} + +func (c cloningReadOnlyCache) List(it *pbresource.Type, indexName string, args ...any) ([]*pbresource.Resource, error) { + resources, err := c.ReadOnlyCache.List(it, indexName, args...) + if err != nil { + return nil, err + } + + return protoutil.CloneSlice(resources), nil +} + +func (c cloningReadOnlyCache) ListIterator(it *pbresource.Type, indexName string, args ...any) (ResourceIterator, error) { + rit, err := c.ReadOnlyCache.ListIterator(it, indexName, args...) + if err != nil { + return nil, err + } + + return cloningIterator{ResourceIterator: rit}, nil +} + +func (c cloningReadOnlyCache) Parents(it *pbresource.Type, indexName string, args ...any) ([]*pbresource.Resource, error) { + resources, err := c.ReadOnlyCache.Parents(it, indexName, args...) + if err != nil { + return nil, err + } + + return protoutil.CloneSlice(resources), nil +} + +func (c cloningReadOnlyCache) ParentsIterator(it *pbresource.Type, indexName string, args ...any) (ResourceIterator, error) { + rit, err := c.ReadOnlyCache.ParentsIterator(it, indexName, args...) + if err != nil { + return nil, err + } + + return cloningIterator{ResourceIterator: rit}, nil +} + +func (c cloningReadOnlyCache) Query(name string, args ...any) (ResourceIterator, error) { + rit, err := c.ReadOnlyCache.Query(name, args...) + if err != nil { + return nil, err + } + + return cloningIterator{ResourceIterator: rit}, nil +} + +type cloningIterator struct { + ResourceIterator +} + +func (it cloningIterator) Next() *pbresource.Resource { + res := it.ResourceIterator.Next() + if res == nil { + return nil + } + + return protoutil.Clone(res) +} diff --git a/internal/controller/cache/clone_test.go b/internal/controller/cache/clone_test.go new file mode 100644 index 000000000000..cf45178f5cd8 --- /dev/null +++ b/internal/controller/cache/clone_test.go @@ -0,0 +1,214 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cache_test + +import ( + "errors" + "testing" + + "github.com/hashicorp/consul/internal/controller/cache" + "github.com/hashicorp/consul/internal/controller/cache/cachemock" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +var ( + injectedError = errors.New("injected") + indexName = "some-index" +) + +type cloningReadOnlyCacheSuite struct { + suite.Suite + + rtype *pbresource.Type + res1 *pbresource.Resource + res2 *pbresource.Resource + + mcache *cachemock.ReadOnlyCache + ccache cache.ReadOnlyCache +} + +func TestReadOnlyCache(t *testing.T) { + suite.Run(t, new(cloningReadOnlyCacheSuite)) +} + +func (suite *cloningReadOnlyCacheSuite) SetupTest() { + suite.rtype = &pbresource.Type{ + Group: "testing", + GroupVersion: "v1", + Kind: "Fake", + } + + suite.res1 = resourcetest.Resource(suite.rtype, "foo").Build() + suite.res2 = resourcetest.Resource(suite.rtype, "bar").Build() + + suite.mcache = cachemock.NewReadOnlyCache(suite.T()) + suite.ccache = cache.NewCloningReadOnlyCache(suite.mcache) +} + +func (suite *cloningReadOnlyCacheSuite) makeMockIterator(resources ...*pbresource.Resource) *cachemock.ResourceIterator { + iter := cachemock.NewResourceIterator(suite.T()) + for _, res := range resources { + iter.EXPECT(). + Next(). + Return(res). + Once() + } + + iter.EXPECT(). + Next(). + Return(nil). + Times(0) + + return iter +} + +func (suite *cloningReadOnlyCacheSuite) requireEqualNotSame(expected, actual *pbresource.Resource) { + require.Equal(suite.T(), expected, actual) + require.NotSame(suite.T(), expected, actual) +} + +func (suite *cloningReadOnlyCacheSuite) TestGet_Ok() { + suite.mcache.EXPECT(). + Get(suite.rtype, indexName, "ok"). + Return(suite.res1, nil) + + actual, err := suite.ccache.Get(suite.rtype, indexName, "ok") + require.NoError(suite.T(), err) + suite.requireEqualNotSame(suite.res1, actual) +} + +func (suite *cloningReadOnlyCacheSuite) TestGet_Error() { + suite.mcache.EXPECT(). + Get(suite.rtype, indexName, "error"). + Return(nil, injectedError) + + actual, err := suite.ccache.Get(suite.rtype, indexName, "error") + require.ErrorIs(suite.T(), err, injectedError) + require.Nil(suite.T(), actual) +} + +func (suite *cloningReadOnlyCacheSuite) TestList_Ok() { + preClone := []*pbresource.Resource{suite.res1, suite.res2} + + suite.mcache.EXPECT(). + List(suite.rtype, indexName, "ok"). + Return(preClone, nil) + + postClone, err := suite.ccache.List(suite.rtype, indexName, "ok") + require.NoError(suite.T(), err) + require.Len(suite.T(), postClone, len(preClone)) + for i, actual := range postClone { + suite.requireEqualNotSame(preClone[i], actual) + } +} + +func (suite *cloningReadOnlyCacheSuite) TestList_Error() { + suite.mcache.EXPECT(). + List(suite.rtype, indexName, "error"). + Return(nil, injectedError) + + actual, err := suite.ccache.List(suite.rtype, indexName, "error") + require.ErrorIs(suite.T(), err, injectedError) + require.Nil(suite.T(), actual) +} + +func (suite *cloningReadOnlyCacheSuite) TestParents_Ok() { + preClone := []*pbresource.Resource{suite.res1, suite.res2} + + suite.mcache.EXPECT(). + Parents(suite.rtype, indexName, "ok"). + Return(preClone, nil) + + postClone, err := suite.ccache.Parents(suite.rtype, indexName, "ok") + require.NoError(suite.T(), err) + require.Len(suite.T(), postClone, len(preClone)) + for i, actual := range postClone { + suite.requireEqualNotSame(preClone[i], actual) + } +} + +func (suite *cloningReadOnlyCacheSuite) TestParents_Error() { + suite.mcache.EXPECT(). + Parents(suite.rtype, indexName, "error"). + Return(nil, injectedError) + + actual, err := suite.ccache.Parents(suite.rtype, indexName, "error") + require.ErrorIs(suite.T(), err, injectedError) + require.Nil(suite.T(), actual) +} + +func (suite *cloningReadOnlyCacheSuite) TestListIterator_Ok() { + suite.mcache.EXPECT(). + ListIterator(suite.rtype, indexName, "ok"). + Return(suite.makeMockIterator(suite.res1, suite.res2), nil) + + iter, err := suite.ccache.ListIterator(suite.rtype, indexName, "ok") + require.NoError(suite.T(), err) + require.NotNil(suite.T(), iter) + + suite.requireEqualNotSame(suite.res1, iter.Next()) + suite.requireEqualNotSame(suite.res2, iter.Next()) + require.Nil(suite.T(), iter.Next()) +} + +func (suite *cloningReadOnlyCacheSuite) TestListIterator_Error() { + suite.mcache.EXPECT(). + ListIterator(suite.rtype, indexName, "error"). + Return(nil, injectedError) + + actual, err := suite.ccache.ListIterator(suite.rtype, indexName, "error") + require.ErrorIs(suite.T(), err, injectedError) + require.Nil(suite.T(), actual) +} + +func (suite *cloningReadOnlyCacheSuite) TestParentsIterator_Ok() { + suite.mcache.EXPECT(). + ParentsIterator(suite.rtype, indexName, "ok"). + Return(suite.makeMockIterator(suite.res1, suite.res2), nil) + + iter, err := suite.ccache.ParentsIterator(suite.rtype, indexName, "ok") + require.NoError(suite.T(), err) + require.NotNil(suite.T(), iter) + + suite.requireEqualNotSame(suite.res1, iter.Next()) + suite.requireEqualNotSame(suite.res2, iter.Next()) + require.Nil(suite.T(), iter.Next()) +} + +func (suite *cloningReadOnlyCacheSuite) TestParentsIterator_Error() { + suite.mcache.EXPECT(). + ParentsIterator(suite.rtype, indexName, "error"). + Return(nil, injectedError) + + actual, err := suite.ccache.ParentsIterator(suite.rtype, indexName, "error") + require.ErrorIs(suite.T(), err, injectedError) + require.Nil(suite.T(), actual) +} + +func (suite *cloningReadOnlyCacheSuite) TestQuery_Ok() { + suite.mcache.EXPECT(). + Query(indexName, "ok"). + Return(suite.makeMockIterator(suite.res1, suite.res2), nil) + + iter, err := suite.ccache.Query(indexName, "ok") + require.NoError(suite.T(), err) + require.NotNil(suite.T(), iter) + + suite.requireEqualNotSame(suite.res1, iter.Next()) + suite.requireEqualNotSame(suite.res2, iter.Next()) + require.Nil(suite.T(), iter.Next()) +} + +func (suite *cloningReadOnlyCacheSuite) TestQuery_Error() { + suite.mcache.EXPECT(). + Query(indexName, "error"). + Return(nil, injectedError) + + actual, err := suite.ccache.Query(indexName, "error") + require.ErrorIs(suite.T(), err, injectedError) + require.Nil(suite.T(), actual) +} diff --git a/internal/controller/cache/decoded.go b/internal/controller/cache/decoded.go new file mode 100644 index 000000000000..76c6b2d7c9c5 --- /dev/null +++ b/internal/controller/cache/decoded.go @@ -0,0 +1,107 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cache + +import ( + "google.golang.org/protobuf/proto" + + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// Get retrieves a single resource from the specified index that matches the provided args. +// If more than one match is found the first is returned. +func GetDecoded[T proto.Message](c ReadOnlyCache, it *pbresource.Type, indexName string, args ...any) (*resource.DecodedResource[T], error) { + res, err := c.Get(it, indexName, args...) + if err != nil { + return nil, err + } + + if res == nil { + return nil, nil + } + + return resource.Decode[T](res) +} + +// List retrieves all the resources from the specified index matching the provided args. +func ListDecoded[T proto.Message](c ReadOnlyCache, it *pbresource.Type, indexName string, args ...any) ([]*resource.DecodedResource[T], error) { + resources, err := c.List(it, indexName, args...) + if err != nil { + return nil, err + } + + return resource.DecodeList[T](resources) +} + +// ListIterator retrieves an iterator over all resources from the specified index matching the provided args. +func ListIteratorDecoded[T proto.Message](c ReadOnlyCache, it *pbresource.Type, indexName string, args ...any) (DecodedResourceIterator[T], error) { + iter, err := c.ListIterator(it, indexName, args...) + if err != nil { + return nil, err + } + + if iter == nil { + return nil, nil + } + + return decodedResourceIterator[T]{iter}, nil +} + +// Parents retrieves all resources whos index value is a parent (or prefix) of the value calculated +// from the provided args. +func ParentsDecoded[T proto.Message](c ReadOnlyCache, it *pbresource.Type, indexName string, args ...any) ([]*resource.DecodedResource[T], error) { + resources, err := c.Parents(it, indexName, args...) + if err != nil { + return nil, err + } + + return resource.DecodeList[T](resources) +} + +// ParentsIterator retrieves an iterator over all resources whos index value is a parent (or prefix) +// of the value calculated from the provided args. +func ParentsIteratorDecoded[T proto.Message](c ReadOnlyCache, it *pbresource.Type, indexName string, args ...any) (DecodedResourceIterator[T], error) { + iter, err := c.ParentsIterator(it, indexName, args...) + if err != nil { + return nil, err + } + + if iter == nil { + return nil, nil + } + + return decodedResourceIterator[T]{iter}, nil +} + +// Query will execute a named query against the cache and return an interator over its results +func QueryDecoded[T proto.Message](c ReadOnlyCache, name string, args ...any) (DecodedResourceIterator[T], error) { + iter, err := c.Query(name, args...) + if err != nil { + return nil, err + } + + if iter == nil { + return nil, nil + } + + return decodedResourceIterator[T]{iter}, nil +} + +type DecodedResourceIterator[T proto.Message] interface { + Next() (*resource.DecodedResource[T], error) +} + +type decodedResourceIterator[T proto.Message] struct { + ResourceIterator +} + +func (iter decodedResourceIterator[T]) Next() (*resource.DecodedResource[T], error) { + res := iter.ResourceIterator.Next() + if res == nil { + return nil, nil + } + + return resource.Decode[T](res) +} diff --git a/internal/controller/cache/decoded_test.go b/internal/controller/cache/decoded_test.go new file mode 100644 index 000000000000..81ab62d80f28 --- /dev/null +++ b/internal/controller/cache/decoded_test.go @@ -0,0 +1,360 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cache_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + "github.com/hashicorp/consul/internal/controller/cache" + "github.com/hashicorp/consul/internal/controller/cache/cachemock" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/demo" + "github.com/hashicorp/consul/proto-public/pbresource" + pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v2" + "github.com/hashicorp/consul/proto/private/prototest" +) + +type decodedSuite struct { + suite.Suite + rc *cachemock.ReadOnlyCache + iter *cachemock.ResourceIterator + + artistGood *resource.DecodedResource[*pbdemo.Artist] + artistGood2 *resource.DecodedResource[*pbdemo.Artist] + artistBad *pbresource.Resource +} + +func (suite *decodedSuite) SetupTest() { + suite.rc = cachemock.NewReadOnlyCache(suite.T()) + suite.iter = cachemock.NewResourceIterator(suite.T()) + artist, err := demo.GenerateV2Artist() + require.NoError(suite.T(), err) + suite.artistGood, err = resource.Decode[*pbdemo.Artist](artist) + require.NoError(suite.T(), err) + + artist2, err := demo.GenerateV2Artist() + require.NoError(suite.T(), err) + suite.artistGood2, err = resource.Decode[*pbdemo.Artist](artist2) + require.NoError(suite.T(), err) + + suite.artistBad, err = demo.GenerateV2Album(artist.Id) + require.NoError(suite.T(), err) +} + +func (suite *decodedSuite) TestGetDecoded_Ok() { + suite.rc.EXPECT().Get(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(suite.artistGood.Resource, nil) + + dec, err := cache.GetDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data) +} + +func (suite *decodedSuite) TestGetDecoded_DecodeError() { + suite.rc.EXPECT().Get(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(suite.artistBad, nil) + + dec, err := cache.GetDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.Error(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestGetDecoded_CacheError() { + suite.rc.EXPECT().Get(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, injectedError) + + dec, err := cache.GetDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.ErrorIs(suite.T(), err, injectedError) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestGetDecoded_Nil() { + suite.rc.EXPECT().Get(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, nil) + + dec, err := cache.GetDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.NoError(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestListDecoded_Ok() { + suite.rc.EXPECT().List(pbdemo.ArtistType, "id", suite.artistGood.Id). + Return([]*pbresource.Resource{suite.artistGood.Resource, suite.artistGood2.Resource}, nil) + + dec, err := cache.ListDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.NoError(suite.T(), err) + require.Len(suite.T(), dec, 2) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec[0].Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec[0].Data) + prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Resource, dec[1].Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Data, dec[1].Data) +} + +func (suite *decodedSuite) TestListDecoded_DecodeError() { + suite.rc.EXPECT().List(pbdemo.ArtistType, "id", suite.artistGood.Id). + Return([]*pbresource.Resource{suite.artistGood.Resource, suite.artistBad}, nil) + + dec, err := cache.ListDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.Error(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestListDecoded_CacheError() { + suite.rc.EXPECT().List(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, injectedError) + + dec, err := cache.ListDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.ErrorIs(suite.T(), err, injectedError) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestListDecoded_Nil() { + suite.rc.EXPECT().List(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, nil) + + dec, err := cache.ListDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.NoError(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestListIteratorDecoded_Ok() { + suite.iter.EXPECT().Next().Return(suite.artistGood.Resource).Once() + suite.iter.EXPECT().Next().Return(suite.artistGood2.Resource).Once() + suite.iter.EXPECT().Next().Return(nil).Times(0) + suite.rc.EXPECT().ListIterator(pbdemo.ArtistType, "id", suite.artistGood.Id). + Return(suite.iter, nil) + + iter, err := cache.ListIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), iter) + + dec, err := iter.Next() + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data) + + dec, err = iter.Next() + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Resource, dec.Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Data, dec.Data) + + dec, err = iter.Next() + require.NoError(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestListIteratorDecoded_DecodeError() { + suite.iter.EXPECT().Next().Return(suite.artistGood.Resource).Once() + suite.iter.EXPECT().Next().Return(suite.artistBad).Once() + suite.iter.EXPECT().Next().Return(nil).Times(0) + suite.rc.EXPECT().ListIterator(pbdemo.ArtistType, "id", suite.artistGood.Id). + Return(suite.iter, nil) + + iter, err := cache.ListIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), iter) + + dec, err := iter.Next() + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data) + + dec, err = iter.Next() + require.Error(suite.T(), err) + require.Nil(suite.T(), dec) + + dec, err = iter.Next() + require.NoError(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestListIteratorDecoded_CacheError() { + suite.rc.EXPECT().ListIterator(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, injectedError) + + iter, err := cache.ListIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.ErrorIs(suite.T(), err, injectedError) + require.Nil(suite.T(), iter) +} + +func (suite *decodedSuite) TestListIteratorDecoded_Nil() { + suite.rc.EXPECT().ListIterator(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, nil) + + dec, err := cache.ListIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.NoError(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestParentsDecoded_Ok() { + suite.rc.EXPECT().Parents(pbdemo.ArtistType, "id", suite.artistGood.Id). + Return([]*pbresource.Resource{suite.artistGood.Resource, suite.artistGood2.Resource}, nil) + + dec, err := cache.ParentsDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.NoError(suite.T(), err) + require.Len(suite.T(), dec, 2) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec[0].Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec[0].Data) + prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Resource, dec[1].Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Data, dec[1].Data) +} + +func (suite *decodedSuite) TestParentsDecoded_DecodeError() { + suite.rc.EXPECT().Parents(pbdemo.ArtistType, "id", suite.artistGood.Id). + Return([]*pbresource.Resource{suite.artistGood.Resource, suite.artistBad}, nil) + + dec, err := cache.ParentsDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.Error(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestParentsDecoded_CacheError() { + suite.rc.EXPECT().Parents(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, injectedError) + + dec, err := cache.ParentsDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.ErrorIs(suite.T(), err, injectedError) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestParentsDecoded_Nil() { + suite.rc.EXPECT().Parents(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, nil) + + dec, err := cache.ParentsDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.NoError(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestParentsIteratorDecoded_Ok() { + suite.iter.EXPECT().Next().Return(suite.artistGood.Resource).Once() + suite.iter.EXPECT().Next().Return(suite.artistGood2.Resource).Once() + suite.iter.EXPECT().Next().Return(nil).Times(0) + suite.rc.EXPECT().ParentsIterator(pbdemo.ArtistType, "id", suite.artistGood.Id). + Return(suite.iter, nil) + + iter, err := cache.ParentsIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), iter) + + dec, err := iter.Next() + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data) + + dec, err = iter.Next() + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Resource, dec.Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Data, dec.Data) + + dec, err = iter.Next() + require.NoError(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestParentsIteratorDecoded_DecodeError() { + suite.iter.EXPECT().Next().Return(suite.artistGood.Resource).Once() + suite.iter.EXPECT().Next().Return(suite.artistBad).Once() + suite.iter.EXPECT().Next().Return(nil).Times(0) + suite.rc.EXPECT().ParentsIterator(pbdemo.ArtistType, "id", suite.artistGood.Id). + Return(suite.iter, nil) + + iter, err := cache.ParentsIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), iter) + + dec, err := iter.Next() + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data) + + dec, err = iter.Next() + require.Error(suite.T(), err) + require.Nil(suite.T(), dec) + + dec, err = iter.Next() + require.NoError(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestParentsIteratorDecoded_CacheError() { + suite.rc.EXPECT().ParentsIterator(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, injectedError) + + iter, err := cache.ParentsIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.ErrorIs(suite.T(), err, injectedError) + require.Nil(suite.T(), iter) +} + +func (suite *decodedSuite) TestParentsIteratorDecoded_Nil() { + suite.rc.EXPECT().ParentsIterator(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, nil) + + dec, err := cache.ParentsIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id) + require.NoError(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestQueryDecoded_Ok() { + suite.iter.EXPECT().Next().Return(suite.artistGood.Resource).Once() + suite.iter.EXPECT().Next().Return(suite.artistGood2.Resource).Once() + suite.iter.EXPECT().Next().Return(nil).Times(0) + suite.rc.EXPECT().Query("query", "blah"). + Return(suite.iter, nil) + + iter, err := cache.QueryDecoded[*pbdemo.Artist](suite.rc, "query", "blah") + require.NoError(suite.T(), err) + require.NotNil(suite.T(), iter) + + dec, err := iter.Next() + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data) + + dec, err = iter.Next() + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Resource, dec.Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Data, dec.Data) + + dec, err = iter.Next() + require.NoError(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestQueryDecoded_DecodeError() { + suite.iter.EXPECT().Next().Return(suite.artistGood.Resource).Once() + suite.iter.EXPECT().Next().Return(suite.artistBad).Once() + suite.iter.EXPECT().Next().Return(nil).Times(0) + suite.rc.EXPECT().Query("query", "blah"). + Return(suite.iter, nil) + + iter, err := cache.QueryDecoded[*pbdemo.Artist](suite.rc, "query", "blah") + require.NoError(suite.T(), err) + require.NotNil(suite.T(), iter) + + dec, err := iter.Next() + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource) + prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data) + + dec, err = iter.Next() + require.Error(suite.T(), err) + require.Nil(suite.T(), dec) + + dec, err = iter.Next() + require.NoError(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestQueryDecoded_CacheError() { + suite.rc.EXPECT().Query("query", "blah").Return(nil, injectedError) + + dec, err := cache.QueryDecoded[*pbdemo.Artist](suite.rc, "query", "blah") + require.ErrorIs(suite.T(), err, injectedError) + require.Nil(suite.T(), dec) +} + +func (suite *decodedSuite) TestQueryDecoded_Nil() { + suite.rc.EXPECT().Query("query", "blah").Return(nil, nil) + + dec, err := cache.QueryDecoded[*pbdemo.Artist](suite.rc, "query", "blah") + require.NoError(suite.T(), err) + require.Nil(suite.T(), dec) +} + +func TestDecodedCache(t *testing.T) { + suite.Run(t, new(decodedSuite)) +} diff --git a/internal/controller/cache/errors.go b/internal/controller/cache/errors.go new file mode 100644 index 000000000000..e269b4755a9c --- /dev/null +++ b/internal/controller/cache/errors.go @@ -0,0 +1,73 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cache + +import ( + "errors" + "fmt" +) + +var ( + QueryRequired = errors.New("A non-nil query function was not specified") + TypeUnspecifiedError = errors.New("the resource type was not specified") + TypeNotIndexedError = errors.New("the resource type specified is not indexed") +) + +type QueryNotFoundError struct { + name string +} + +func (e QueryNotFoundError) Error() string { + return fmt.Sprintf("No query with name %q exists", e.name) +} + +type IndexNotFoundError struct { + name string +} + +func (e IndexNotFoundError) Error() string { + return fmt.Sprintf("No index with name %q exists", e.name) +} + +type CacheTypeError struct { + err error + it unversionedType +} + +func (e CacheTypeError) Error() string { + return fmt.Sprintf("operation on resource type %s.%s failed: %v", e.it.Group, e.it.Kind, e.err.Error()) +} + +func (e CacheTypeError) Unwrap() error { + return e.err +} + +type IndexError struct { + err error + name string +} + +func (e IndexError) Error() string { + return fmt.Sprintf("operation on index %q failed: %v", e.name, e.err.Error()) +} + +func (e IndexError) Unwrap() error { + return e.err +} + +type DuplicateIndexError struct { + name string +} + +func (e DuplicateIndexError) Error() string { + return fmt.Sprintf("Index with name %q is already defined.", e.name) +} + +type DuplicateQueryError struct { + name string +} + +func (e DuplicateQueryError) Error() string { + return fmt.Sprintf("Query with name %q is already defined.", e.name) +} diff --git a/internal/controller/cache/errors_test.go b/internal/controller/cache/errors_test.go new file mode 100644 index 000000000000..af5f660d4e78 --- /dev/null +++ b/internal/controller/cache/errors_test.go @@ -0,0 +1,59 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cache + +import ( + "fmt" + "testing" + + "github.com/hashicorp/consul/internal/testing/errors" +) + +var ( + fakeWrappedErr = fmt.Errorf("fake test error") +) + +func TestErrorStrings(t *testing.T) { + errors.TestErrorStrings(t, map[string]error{ + "IndexNotFound": IndexNotFoundError{name: "fake"}, + "QueryNotFound": QueryNotFoundError{name: "fake"}, + "QueryRequired": QueryRequired, + "CacheTypeError": CacheTypeError{ + err: fakeWrappedErr, + it: unversionedType{ + Group: "something", + Kind: "else", + }, + }, + "IndexError": IndexError{ + err: fakeWrappedErr, + name: "foo", + }, + "DuplicateIndexError": DuplicateIndexError{ + name: "addresses", + }, + "DuplicateQueryError": DuplicateQueryError{ + name: "addresses", + }, + }) +} + +func TestErrorUnwrap(t *testing.T) { + errors.TestErrorUnwrap(t, map[string]errors.UnwrapErrorTestCase{ + "IndexError": { + Err: IndexError{ + name: "blah", + err: fakeWrappedErr, + }, + Expected: fakeWrappedErr, + }, + "CacheTypeError": { + Err: CacheTypeError{ + it: unversionedType{Group: "something", Kind: "else"}, + err: fakeWrappedErr, + }, + Expected: fakeWrappedErr, + }, + }) +} diff --git a/internal/controller/cache/index/.mockery.yaml b/internal/controller/cache/index/.mockery.yaml new file mode 100644 index 000000000000..c198bc603693 --- /dev/null +++ b/internal/controller/cache/index/.mockery.yaml @@ -0,0 +1,23 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +with-expecter: true +recursive: false +# We don't want the mocks within proto-public so as to force a dependency +# of the testify library on the modules usage. The mocks are only for +# internal testing purposes. Other consumers can generated the mocks into +# their own code base. +dir: "indexmock" +outpkg: "indexmock" +# camelcase ensure that private interfaces also get public mocks +mockname: "{{.InterfaceName | camelcase }}" + +# The Txn and IndexOption interfaces require this package and if the mocks +# are generated out of package (in the indexmock package) then it will +# cause there to be cyclical imports. As we don't need mocks for these +# right now it is easier to just exclude them. +include-regex: ".*" +exclude-regex: "^(Txn|IndexOption)$" + +packages: + github.com/hashicorp/consul/internal/controller/cache/index: diff --git a/internal/controller/cache/index/builder.go b/internal/controller/cache/index/builder.go new file mode 100644 index 000000000000..16841a722c60 --- /dev/null +++ b/internal/controller/cache/index/builder.go @@ -0,0 +1,33 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import ( + "bytes" +) + +// indexSeparator delimits the segments of our radix tree keys. +const indexSeparator = "\x00" + +type Builder bytes.Buffer + +func (i *Builder) Raw(v []byte) { + (*bytes.Buffer)(i).Write(v) +} + +func (i *Builder) String(s string) { + (*bytes.Buffer)(i).WriteString(s) + (*bytes.Buffer)(i).WriteString(indexSeparator) +} + +func (i *Builder) Bytes() []byte { + return (*bytes.Buffer)(i).Bytes() +} + +func (i *Builder) Write(b []byte) (int, error) { + (*bytes.Buffer)(i).Write(b) + (*bytes.Buffer)(i).WriteString(indexSeparator) + + return len(b), nil +} diff --git a/internal/controller/cache/index/builder_test.go b/internal/controller/cache/index/builder_test.go new file mode 100644 index 000000000000..754c16f62fbf --- /dev/null +++ b/internal/controller/cache/index/builder_test.go @@ -0,0 +1,33 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBuilderRaw(t *testing.T) { + var b Builder + b.Raw([]byte{1, 2, 3}) + + require.Equal(t, []byte{1, 2, 3}, b.Bytes()) +} + +func TestBuilderString(t *testing.T) { + var b Builder + b.String("abc") + + // Ensure that the null terminator is tacked on + require.Equal(t, []byte{'a', 'b', 'c', 0}, b.Bytes()) +} + +func TestBuilderWrite(t *testing.T) { + var b Builder + wrote, err := b.Write([]byte{1, 2, 3}) + require.NoError(t, err) + require.Equal(t, 3, wrote) + require.Equal(t, []byte{1, 2, 3, 0}, b.Bytes()) +} diff --git a/internal/controller/cache/index/convenience.go b/internal/controller/cache/index/convenience.go new file mode 100644 index 000000000000..5c742dd23997 --- /dev/null +++ b/internal/controller/cache/index/convenience.go @@ -0,0 +1,144 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import ( + "fmt" + + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/storage" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +type IndexQueryOptions struct { + Prefix bool +} + +func IndexFromID(id *pbresource.ID, includeUid bool) []byte { + var b Builder + b.Raw(IndexFromType(id.Type)) + b.Raw(IndexFromTenancy(id.Tenancy)) + b.String(id.Name) + if includeUid { + b.String(id.Uid) + } + return b.Bytes() +} + +func IndexFromRefOrID(ref resource.ReferenceOrID) []byte { + var b Builder + b.Raw(IndexFromType(ref.GetType())) + b.Raw(IndexFromTenancy(ref.GetTenancy())) + b.String(ref.GetName()) + return b.Bytes() +} + +func PrefixIndexFromRefOrID(ref resource.ReferenceOrID) []byte { + var b Builder + b.Raw(IndexFromType(ref.GetType())) + + raw, done := prefixIndexFromTenancy(ref.GetTenancy()) + b.Raw(raw) + + if done { + return b.Bytes() + } + + b.Raw([]byte(ref.GetName())) + return b.Bytes() +} + +func prefixIndexFromTenancy(t *pbresource.Tenancy) ([]byte, bool) { + var b Builder + partition := t.GetPartition() + if partition == "" || partition == storage.Wildcard { + return b.Bytes(), true + } + + b.String(partition) + + namespace := t.GetNamespace() + + if namespace == "" || namespace == storage.Wildcard { + return b.Bytes(), true + } + + b.String(namespace) + + return b.Bytes(), false +} + +func IndexFromType(t *pbresource.Type) []byte { + var b Builder + b.String(t.Group) + b.String(t.Kind) + return b.Bytes() +} + +func IndexFromTenancy(t *pbresource.Tenancy) []byte { + var b Builder + b.String(t.GetPartition()) + b.String(t.GetNamespace()) + return b.Bytes() +} + +var ReferenceOrIDFromArgs = SingleValueFromArgs[resource.ReferenceOrID](func(r resource.ReferenceOrID) ([]byte, error) { + return IndexFromRefOrID(r), nil +}) + +var PrefixReferenceOrIDFromArgs = SingleValueFromArgs[resource.ReferenceOrID](func(r resource.ReferenceOrID) ([]byte, error) { + return PrefixIndexFromRefOrID(r), nil +}) + +var MaybePrefixReferenceOrIDFromArgs = SingleValueFromOneOrTwoArgs[resource.ReferenceOrID, IndexQueryOptions](func(r resource.ReferenceOrID, opts IndexQueryOptions) ([]byte, error) { + if opts.Prefix { + return PrefixIndexFromRefOrID(r), nil + } else { + return IndexFromRefOrID(r), nil + } +}) + +func SingleValueFromArgs[T any](indexer func(value T) ([]byte, error)) func(args ...any) ([]byte, error) { + return func(args ...any) ([]byte, error) { + var zero T + if l := len(args); l != 1 { + return nil, fmt.Errorf("expected 1 arg, got: %d", l) + } + + value, ok := args[0].(T) + if !ok { + return nil, fmt.Errorf("expected %T, got: %T", zero, args[0]) + } + + return indexer(value) + } +} + +func SingleValueFromOneOrTwoArgs[T1 any, T2 any](indexer func(value T1, optional T2) ([]byte, error)) func(args ...any) ([]byte, error) { + return func(args ...any) ([]byte, error) { + var value T1 + var optional T2 + + l := len(args) + switch l { + case 2: + val, ok := args[1].(T2) + if !ok { + return nil, fmt.Errorf("expected second argument type of %T, got: %T", optional, args[1]) + } + optional = val + fallthrough + case 1: + val, ok := args[0].(T1) + if !ok { + return nil, fmt.Errorf("expected first argument type of %T, got: %T", value, args[0]) + } + value = val + default: + return nil, fmt.Errorf("expected 1 or 2 args, got: %d", l) + } + + return indexer(value, optional) + } +} diff --git a/internal/controller/cache/index/convenience_test.go b/internal/controller/cache/index/convenience_test.go new file mode 100644 index 000000000000..f5fe5cae4580 --- /dev/null +++ b/internal/controller/cache/index/convenience_test.go @@ -0,0 +1,383 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import ( + "errors" + "testing" + + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/storage" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/stretchr/testify/require" +) + +func TestIndexFromID(t *testing.T) { + id := &pbresource.ID{ + Type: &pbresource.Type{ + Group: "test", + GroupVersion: "v1", + Kind: "fake", + }, + Tenancy: &pbresource.Tenancy{ + Partition: "foo", + Namespace: "bar", + }, + Name: "baz", + Uid: "01G9R78VJ5VXAJRA2K7V0RXB87", + } + + val := IndexFromID(id, false) + expected := []byte("test\x00fake\x00foo\x00bar\x00baz\x00") + require.Equal(t, expected, val) + + val = IndexFromID(id, true) + expected = []byte("test\x00fake\x00foo\x00bar\x00baz\x0001G9R78VJ5VXAJRA2K7V0RXB87\x00") + require.Equal(t, expected, val) +} + +func TestIndexFromRefOrID(t *testing.T) { + id := &pbresource.ID{ + Type: &pbresource.Type{ + Group: "test", + GroupVersion: "v1", + Kind: "fake", + }, + Tenancy: &pbresource.Tenancy{ + Partition: "foo", + Namespace: "bar", + }, + Name: "baz", + Uid: "01G9R78VJ5VXAJRA2K7V0RXB87", + } + + ref := resource.Reference(id, "") + + idVal := IndexFromRefOrID(id) + refVal := IndexFromRefOrID(ref) + + expected := "test\x00fake\x00foo\x00bar\x00baz\x00" + require.Equal(t, []byte(expected), idVal) + require.Equal(t, []byte(expected), refVal) +} + +func TestPrefixIndexFromRefOrID(t *testing.T) { + t.Run("no partition", func(t *testing.T) { + ref := &pbresource.Reference{ + Type: &pbresource.Type{ + Group: "test", + GroupVersion: "v1", + Kind: "fake", + }, + } + + require.Equal(t, []byte("test\x00fake\x00"), PrefixIndexFromRefOrID(ref)) + }) + + t.Run("no namespace", func(t *testing.T) { + ref := &pbresource.Reference{ + Type: &pbresource.Type{ + Group: "test", + GroupVersion: "v1", + Kind: "fake", + }, + Tenancy: &pbresource.Tenancy{ + Partition: "test", + }, + } + + require.Equal(t, []byte("test\x00fake\x00test\x00"), PrefixIndexFromRefOrID(ref)) + }) + + t.Run("name prefix", func(t *testing.T) { + id := &pbresource.ID{ + Type: &pbresource.Type{ + Group: "test", + GroupVersion: "v1", + Kind: "fake", + }, + Tenancy: &pbresource.Tenancy{ + Partition: "test", + Namespace: "test", + }, + Name: "prefix", + } + + require.Equal(t, []byte("test\x00fake\x00test\x00test\x00prefix"), PrefixIndexFromRefOrID(id)) + }) +} + +func TestPrefixIndexFromTenancy(t *testing.T) { + t.Run("nil tenancy", func(t *testing.T) { + idx, done := prefixIndexFromTenancy(nil) + require.Len(t, idx, 0) + require.True(t, done) + }) + + t.Run("partition empty", func(t *testing.T) { + tenant := &pbresource.Tenancy{} + idx, done := prefixIndexFromTenancy(tenant) + require.Len(t, idx, 0) + require.True(t, done) + }) + + t.Run("partition wildcard", func(t *testing.T) { + tenant := &pbresource.Tenancy{ + Partition: storage.Wildcard, + } + idx, done := prefixIndexFromTenancy(tenant) + require.Len(t, idx, 0) + require.True(t, done) + }) + + t.Run("namespace empty", func(t *testing.T) { + tenant := &pbresource.Tenancy{ + Partition: "test", + Namespace: "", + } + idx, done := prefixIndexFromTenancy(tenant) + require.Equal(t, []byte("test\x00"), idx) + require.True(t, done) + }) + + t.Run("namespace wildcard", func(t *testing.T) { + tenant := &pbresource.Tenancy{ + Partition: "test", + Namespace: storage.Wildcard, + } + idx, done := prefixIndexFromTenancy(tenant) + require.Equal(t, []byte("test\x00"), idx) + require.True(t, done) + }) + + t.Run("namespace populated", func(t *testing.T) { + tenant := &pbresource.Tenancy{ + Partition: "test", + Namespace: "blah", + } + idx, done := prefixIndexFromTenancy(tenant) + require.Equal(t, []byte("test\x00blah\x00"), idx) + require.False(t, done) + }) +} + +func TestIndexFromType(t *testing.T) { + val := IndexFromType(&pbresource.Type{ + Group: "test", + GroupVersion: "v1", + Kind: "fake", + }) + + require.Equal(t, []byte("test\x00fake\x00"), val) + + val = IndexFromType(&pbresource.Type{ + Group: "test", + GroupVersion: "v1", + }) + + require.Equal(t, []byte("test\x00\x00"), val) +} + +func TestReferenceOrIDFromArgs(t *testing.T) { + ref := &pbresource.Reference{ + Type: &pbresource.Type{ + Group: "test", + GroupVersion: "v1", + Kind: "fake", + }, + Tenancy: &pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + }, + Name: "foo", + } + t.Run("invalid length", func(t *testing.T) { + // the second arg will cause a validation error + val, err := ReferenceOrIDFromArgs(ref, 2) + require.Nil(t, val) + require.Error(t, err) + }) + + t.Run("invalid type", func(t *testing.T) { + val, err := ReferenceOrIDFromArgs("string type unexpected") + require.Nil(t, val) + require.Error(t, err) + }) + + t.Run("ok", func(t *testing.T) { + val, err := ReferenceOrIDFromArgs(ref) + require.NoError(t, err) + require.Equal(t, IndexFromRefOrID(ref), val) + }) +} + +func TestPrefixReferenceOrIDFromArgs(t *testing.T) { + ref := &pbresource.Reference{ + Type: &pbresource.Type{ + Group: "test", + GroupVersion: "v1", + Kind: "fake", + }, + Tenancy: &pbresource.Tenancy{ + Partition: "default", + }, + } + t.Run("invalid length", func(t *testing.T) { + // the second arg will cause a validation error + val, err := PrefixReferenceOrIDFromArgs(ref, 2) + require.Nil(t, val) + require.Error(t, err) + }) + + t.Run("invalid type", func(t *testing.T) { + val, err := PrefixReferenceOrIDFromArgs("string type unexpected") + require.Nil(t, val) + require.Error(t, err) + }) + + t.Run("ok", func(t *testing.T) { + val, err := PrefixReferenceOrIDFromArgs(ref) + require.NoError(t, err) + require.Equal(t, PrefixIndexFromRefOrID(ref), val) + }) +} + +func TestMaybePrefixReferenceOrIDFromArgs(t *testing.T) { + ref := &pbresource.Reference{ + Type: &pbresource.Type{ + Group: "test", + GroupVersion: "v1", + Kind: "fake", + }, + Tenancy: &pbresource.Tenancy{ + Partition: "default", + }, + } + t.Run("invalid length", func(t *testing.T) { + // the second arg will cause a validation error + val, err := MaybePrefixReferenceOrIDFromArgs(ref, IndexQueryOptions{Prefix: false}, 3) + require.Nil(t, val) + require.Error(t, err) + }) + + t.Run("invalid type arg 1", func(t *testing.T) { + val, err := MaybePrefixReferenceOrIDFromArgs("string type unexpected", IndexQueryOptions{Prefix: true}) + require.Nil(t, val) + require.Error(t, err) + }) + + t.Run("invalid type arg 2", func(t *testing.T) { + val, err := MaybePrefixReferenceOrIDFromArgs(ref, "string type unexpected") + require.Nil(t, val) + require.Error(t, err) + }) + + t.Run("ok single arg", func(t *testing.T) { + val, err := MaybePrefixReferenceOrIDFromArgs(ref) + require.NoError(t, err) + require.Equal(t, IndexFromRefOrID(ref), val) + }) + + t.Run("ok two args no prefix", func(t *testing.T) { + val, err := MaybePrefixReferenceOrIDFromArgs(ref, IndexQueryOptions{Prefix: false}) + require.NoError(t, err) + require.Equal(t, IndexFromRefOrID(ref), val) + }) + + t.Run("ok two args with prefix", func(t *testing.T) { + val, err := MaybePrefixReferenceOrIDFromArgs(ref, IndexQueryOptions{Prefix: true}) + require.NoError(t, err) + require.Equal(t, PrefixIndexFromRefOrID(ref), val) + }) +} + +func TestSingleValueFromArgs(t *testing.T) { + injectedError := errors.New("injected test error") + + idx := SingleValueFromArgs(func(val string) ([]byte, error) { + return []byte(val), nil + }) + + errIdx := SingleValueFromArgs(func(val string) ([]byte, error) { + return nil, injectedError + }) + + t.Run("invalid length", func(t *testing.T) { + // the second arg will cause a validation error + val, err := idx("blah", 2) + require.Nil(t, val) + require.Error(t, err) + }) + + t.Run("invalid type", func(t *testing.T) { + val, err := idx(3) + require.Nil(t, val) + require.Error(t, err) + }) + + t.Run("propagate error", func(t *testing.T) { + val, err := errIdx("blah") + require.Nil(t, val) + require.ErrorIs(t, err, injectedError) + }) + + t.Run("ok", func(t *testing.T) { + val, err := idx("blah") + require.NoError(t, err) + require.Equal(t, []byte("blah"), val) + }) +} + +func TestSingleValueFromOneOrTwoArgs(t *testing.T) { + injectedError := errors.New("injected test error") + + idx := SingleValueFromOneOrTwoArgs(func(val string, optional bool) ([]byte, error) { + if optional { + return []byte(val + val), nil + } + return []byte(val), nil + }) + + errIdx := SingleValueFromOneOrTwoArgs(func(val string, optional bool) ([]byte, error) { + return nil, injectedError + }) + + t.Run("invalid length", func(t *testing.T) { + // the third arg will cause a validation error + val, err := idx("blah", true, 4) + require.Nil(t, val) + require.Error(t, err) + }) + + t.Run("invalid first type", func(t *testing.T) { + val, err := idx(4, true) + require.Nil(t, val) + require.Error(t, err) + }) + + t.Run("invalid second type", func(t *testing.T) { + val, err := idx("blah", 3) + require.Nil(t, val) + require.Error(t, err) + }) + + t.Run("propagate error", func(t *testing.T) { + val, err := errIdx("blah") + require.Nil(t, val) + require.ErrorIs(t, err, injectedError) + }) + + t.Run("one arg ok", func(t *testing.T) { + val, err := idx("blah") + require.NoError(t, err) + require.Equal(t, []byte("blah"), val) + }) + + t.Run("two arg ok", func(t *testing.T) { + val, err := idx("blah", true) + require.NoError(t, err) + require.Equal(t, []byte("blahblah"), val) + }) + +} diff --git a/internal/controller/cache/index/errors.go b/internal/controller/cache/index/errors.go new file mode 100644 index 000000000000..4977e88d130e --- /dev/null +++ b/internal/controller/cache/index/errors.go @@ -0,0 +1,16 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import ( + "fmt" +) + +type MissingRequiredIndexError struct { + Name string +} + +func (err MissingRequiredIndexError) Error() string { + return fmt.Sprintf("the indexer produced no value for the required %q index", err.Name) +} diff --git a/internal/controller/cache/index/errors_test.go b/internal/controller/cache/index/errors_test.go new file mode 100644 index 000000000000..d3d96c65f888 --- /dev/null +++ b/internal/controller/cache/index/errors_test.go @@ -0,0 +1,16 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import ( + "testing" + + "github.com/hashicorp/consul/internal/testing/errors" +) + +func TestErrorStrings(t *testing.T) { + errors.TestErrorStrings(t, map[string]error{ + "MissingRequiredIndex": MissingRequiredIndexError{Name: "fake-index-name"}, + }) +} diff --git a/internal/controller/cache/index/index.go b/internal/controller/cache/index/index.go new file mode 100644 index 000000000000..aa3ba047f5c8 --- /dev/null +++ b/internal/controller/cache/index/index.go @@ -0,0 +1,96 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import ( + "github.com/hashicorp/consul/proto-public/pbresource" + iradix "github.com/hashicorp/go-immutable-radix/v2" +) + +type Index struct { + name string + required bool + indexer MultiIndexer +} + +func New(name string, i Indexer, opts ...IndexOption) *Index { + if name == "" { + panic("all indexers must have a non-empty name") + } + if i == nil { + panic("no indexer was supplied when creating a new cache Index") + } + + var multiIndexer MultiIndexer + switch v := i.(type) { + case SingleIndexer: + multiIndexer = singleIndexWrapper{indexer: v} + case MultiIndexer: + multiIndexer = v + default: + panic("The Indexer must also implement one of the SingleIndexer or MultiIndexer interfaces") + } + + idx := &Index{ + name: name, + indexer: multiIndexer, + } + + for _, opt := range opts { + opt(idx) + } + + return idx +} + +func (i *Index) Name() string { + return i.name +} + +// IndexedData combines the Index with an radix tree for index and resource storage. +func (i *Index) IndexedData() *IndexedData { + return &IndexedData{ + Index: i, + tree: iradix.New[[]*pbresource.Resource](), + } +} + +// IndexedData is a wrapper around an Index and an radix tree for index and resource storage. +type IndexedData struct { + *Index + tree *iradix.Tree[[]*pbresource.Resource] +} + +func (i *IndexedData) Txn() Txn { + return &txn{ + inner: i.tree.Txn(), + index: i, + dirty: false, + } +} + +func (i *Index) fromArgs(args ...any) ([]byte, error) { + return i.indexer.FromArgs(args...) +} + +func (i *Index) fromResource(r *pbresource.Resource) (bool, [][]byte, error) { + return i.indexer.FromResource(r) +} + +type singleIndexWrapper struct { + indexer SingleIndexer +} + +func (s singleIndexWrapper) FromArgs(args ...any) ([]byte, error) { + return s.indexer.FromArgs(args...) +} + +func (s singleIndexWrapper) FromResource(r *pbresource.Resource) (bool, [][]byte, error) { + indexed, val, err := s.indexer.FromResource(r) + if err != nil || !indexed { + return false, nil, err + } + + return true, [][]byte{val}, nil +} diff --git a/internal/controller/cache/index/index_test.go b/internal/controller/cache/index/index_test.go new file mode 100644 index 000000000000..d1c492ff0ed4 --- /dev/null +++ b/internal/controller/cache/index/index_test.go @@ -0,0 +1,189 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import ( + "errors" + "testing" + + "github.com/hashicorp/consul/internal/controller/cache/index/indexmock" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/stretchr/testify/require" +) + +type testSingleIndexer struct{} + +func (testSingleIndexer) FromArgs(args ...any) ([]byte, error) { + return ReferenceOrIDFromArgs(args...) +} + +func (testSingleIndexer) FromResource(res *pbresource.Resource) (bool, []byte, error) { + return true, IndexFromRefOrID(res.Id), nil +} + +type testMultiIndexer struct{} + +func (testMultiIndexer) FromArgs(args ...any) ([]byte, error) { + return ReferenceOrIDFromArgs(args...) +} + +func (testMultiIndexer) FromResource(*pbresource.Resource) (bool, [][]byte, error) { + return false, nil, nil +} + +type argsOnlyIdx struct{} + +func (argsOnlyIdx) FromArgs(args ...any) ([]byte, error) { + return nil, nil +} + +func TestNew(t *testing.T) { + t.Run("no name", func(t *testing.T) { + require.Panics(t, func() { + New("", testSingleIndexer{}) + }) + }) + + t.Run("nil indexer", func(t *testing.T) { + require.Panics(t, func() { + New("test", nil) + }) + }) + + t.Run("indexer interface not satisfied", func(t *testing.T) { + require.Panics(t, func() { + New("test", argsOnlyIdx{}) + }) + }) + + t.Run("single indexer", func(t *testing.T) { + require.NotNil(t, New("test", testSingleIndexer{})) + }) + + t.Run("multi indexer", func(t *testing.T) { + require.NotNil(t, New("test", testMultiIndexer{})) + }) + + t.Run("required", func(t *testing.T) { + idx := New("test", testSingleIndexer{}, IndexRequired) + require.NotNil(t, idx) + require.True(t, idx.required) + require.Equal(t, "test", idx.Name()) + }) +} + +func TestSingleIndexWrapper(t *testing.T) { + injectedError := errors.New("injected") + rtype := &pbresource.Type{ + Group: "test", + GroupVersion: "v1", + Kind: "fake", + } + res := resourcetest.Resource(rtype, "foo").Build() + + t.Run("FromArgs ok", func(t *testing.T) { + m := indexmock.NewSingleIndexer(t) + wrapper := singleIndexWrapper{indexer: m} + + m.On("FromArgs", 1).Return([]byte{1, 2, 3}, nil) + vals, err := wrapper.FromArgs(1) + require.NoError(t, err) + require.Equal(t, []byte{1, 2, 3}, vals) + }) + + t.Run("FromArgs err", func(t *testing.T) { + m := indexmock.NewSingleIndexer(t) + wrapper := singleIndexWrapper{indexer: m} + + m.On("FromArgs", 1).Return([]byte(nil), injectedError) + vals, err := wrapper.FromArgs(1) + require.Error(t, err) + require.ErrorIs(t, err, injectedError) + require.Nil(t, vals) + }) + + t.Run("FromResource err", func(t *testing.T) { + m := indexmock.NewSingleIndexer(t) + wrapper := singleIndexWrapper{indexer: m} + m.On("FromResource", res).Return(false, []byte(nil), injectedError) + indexed, vals, err := wrapper.FromResource(res) + require.False(t, indexed) + require.Nil(t, vals) + require.ErrorIs(t, err, injectedError) + }) + + t.Run("FromResource not indexed", func(t *testing.T) { + m := indexmock.NewSingleIndexer(t) + wrapper := singleIndexWrapper{indexer: m} + m.On("FromResource", res).Return(false, []byte(nil), nil) + indexed, vals, err := wrapper.FromResource(res) + require.False(t, indexed) + require.Nil(t, vals) + require.Nil(t, err) + }) + + t.Run("FromResource ok", func(t *testing.T) { + m := indexmock.NewSingleIndexer(t) + wrapper := singleIndexWrapper{indexer: m} + m.On("FromResource", res).Return(true, []byte{1, 2, 3}, nil) + indexed, vals, err := wrapper.FromResource(res) + require.NoError(t, err) + require.True(t, indexed) + require.Len(t, vals, 1) + require.Equal(t, []byte{1, 2, 3}, vals[0]) + }) +} + +func TestIndexReuse(t *testing.T) { + rtype := &pbresource.Type{ + Group: "test", + GroupVersion: "v1", + Kind: "fake", + } + id := resourcetest.Resource(rtype, "foo").ID() + + res1 := resourcetest.ResourceID(id).Build() + res2 := resourcetest.ResourceID(id).WithStatus("foo", &pbresource.Status{ + ObservedGeneration: "woo", + }).Build() + + indexer := testSingleIndexer{} + + // Verify that the indexer produces an identical index for both resources. If this + // isn't true then the rest of the checks we do don't actually prove that the + // two IndexedData objects have independent resource storage. + _, idx1, _ := indexer.FromResource(res1) + _, idx2, _ := indexer.FromResource(res2) + require.Equal(t, idx1, idx2) + + // Create the index and two indepent indexed data storage objects + idx := New("test", indexer) + data1 := idx.IndexedData() + data2 := idx.IndexedData() + + // Push 1 resource into each + txn := data1.Txn() + txn.Insert(res1) + txn.Commit() + + txn = data2.Txn() + txn.Insert(res2) + txn.Commit() + + // Verify that querying the first indexed data can only return the first resource + iter, err := data1.Txn().ListIterator(id) + require.NoError(t, err) + res := iter.Next() + prototest.AssertDeepEqual(t, res1, res) + require.Nil(t, iter.Next()) + + // Verify that querying the second indexed data can only return the second resource + iter, err = data2.Txn().ListIterator(id) + require.NoError(t, err) + res = iter.Next() + prototest.AssertDeepEqual(t, res2, res) + require.Nil(t, iter.Next()) +} diff --git a/internal/controller/cache/index/indexmock/mock_Indexer.go b/internal/controller/cache/index/indexmock/mock_Indexer.go new file mode 100644 index 000000000000..28426ab5bb56 --- /dev/null +++ b/internal/controller/cache/index/indexmock/mock_Indexer.go @@ -0,0 +1,95 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package indexmock + +import mock "github.com/stretchr/testify/mock" + +// Indexer is an autogenerated mock type for the Indexer type +type Indexer struct { + mock.Mock +} + +type Indexer_Expecter struct { + mock *mock.Mock +} + +func (_m *Indexer) EXPECT() *Indexer_Expecter { + return &Indexer_Expecter{mock: &_m.Mock} +} + +// FromArgs provides a mock function with given fields: args +func (_m *Indexer) FromArgs(args ...interface{}) ([]byte, error) { + var _ca []interface{} + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(...interface{}) ([]byte, error)); ok { + return rf(args...) + } + if rf, ok := ret.Get(0).(func(...interface{}) []byte); ok { + r0 = rf(args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(...interface{}) error); ok { + r1 = rf(args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Indexer_FromArgs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FromArgs' +type Indexer_FromArgs_Call struct { + *mock.Call +} + +// FromArgs is a helper method to define mock.On call +// - args ...interface{} +func (_e *Indexer_Expecter) FromArgs(args ...interface{}) *Indexer_FromArgs_Call { + return &Indexer_FromArgs_Call{Call: _e.mock.On("FromArgs", + append([]interface{}{}, args...)...)} +} + +func (_c *Indexer_FromArgs_Call) Run(run func(args ...interface{})) *Indexer_FromArgs_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-0) + for i, a := range args[0:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(variadicArgs...) + }) + return _c +} + +func (_c *Indexer_FromArgs_Call) Return(_a0 []byte, _a1 error) *Indexer_FromArgs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Indexer_FromArgs_Call) RunAndReturn(run func(...interface{}) ([]byte, error)) *Indexer_FromArgs_Call { + _c.Call.Return(run) + return _c +} + +// NewIndexer creates a new instance of Indexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewIndexer(t interface { + mock.TestingT + Cleanup(func()) +}) *Indexer { + mock := &Indexer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/index/indexmock/mock_MultiIndexer.go b/internal/controller/cache/index/indexmock/mock_MultiIndexer.go new file mode 100644 index 000000000000..24f24313cca9 --- /dev/null +++ b/internal/controller/cache/index/indexmock/mock_MultiIndexer.go @@ -0,0 +1,159 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package indexmock + +import ( + pbresource "github.com/hashicorp/consul/proto-public/pbresource" + mock "github.com/stretchr/testify/mock" +) + +// MultiIndexer is an autogenerated mock type for the MultiIndexer type +type MultiIndexer struct { + mock.Mock +} + +type MultiIndexer_Expecter struct { + mock *mock.Mock +} + +func (_m *MultiIndexer) EXPECT() *MultiIndexer_Expecter { + return &MultiIndexer_Expecter{mock: &_m.Mock} +} + +// FromArgs provides a mock function with given fields: args +func (_m *MultiIndexer) FromArgs(args ...interface{}) ([]byte, error) { + var _ca []interface{} + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(...interface{}) ([]byte, error)); ok { + return rf(args...) + } + if rf, ok := ret.Get(0).(func(...interface{}) []byte); ok { + r0 = rf(args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(...interface{}) error); ok { + r1 = rf(args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MultiIndexer_FromArgs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FromArgs' +type MultiIndexer_FromArgs_Call struct { + *mock.Call +} + +// FromArgs is a helper method to define mock.On call +// - args ...interface{} +func (_e *MultiIndexer_Expecter) FromArgs(args ...interface{}) *MultiIndexer_FromArgs_Call { + return &MultiIndexer_FromArgs_Call{Call: _e.mock.On("FromArgs", + append([]interface{}{}, args...)...)} +} + +func (_c *MultiIndexer_FromArgs_Call) Run(run func(args ...interface{})) *MultiIndexer_FromArgs_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-0) + for i, a := range args[0:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(variadicArgs...) + }) + return _c +} + +func (_c *MultiIndexer_FromArgs_Call) Return(_a0 []byte, _a1 error) *MultiIndexer_FromArgs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MultiIndexer_FromArgs_Call) RunAndReturn(run func(...interface{}) ([]byte, error)) *MultiIndexer_FromArgs_Call { + _c.Call.Return(run) + return _c +} + +// FromResource provides a mock function with given fields: r +func (_m *MultiIndexer) FromResource(r *pbresource.Resource) (bool, [][]byte, error) { + ret := _m.Called(r) + + var r0 bool + var r1 [][]byte + var r2 error + if rf, ok := ret.Get(0).(func(*pbresource.Resource) (bool, [][]byte, error)); ok { + return rf(r) + } + if rf, ok := ret.Get(0).(func(*pbresource.Resource) bool); ok { + r0 = rf(r) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(*pbresource.Resource) [][]byte); ok { + r1 = rf(r) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).([][]byte) + } + } + + if rf, ok := ret.Get(2).(func(*pbresource.Resource) error); ok { + r2 = rf(r) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MultiIndexer_FromResource_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FromResource' +type MultiIndexer_FromResource_Call struct { + *mock.Call +} + +// FromResource is a helper method to define mock.On call +// - r *pbresource.Resource +func (_e *MultiIndexer_Expecter) FromResource(r interface{}) *MultiIndexer_FromResource_Call { + return &MultiIndexer_FromResource_Call{Call: _e.mock.On("FromResource", r)} +} + +func (_c *MultiIndexer_FromResource_Call) Run(run func(r *pbresource.Resource)) *MultiIndexer_FromResource_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbresource.Resource)) + }) + return _c +} + +func (_c *MultiIndexer_FromResource_Call) Return(_a0 bool, _a1 [][]byte, _a2 error) *MultiIndexer_FromResource_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MultiIndexer_FromResource_Call) RunAndReturn(run func(*pbresource.Resource) (bool, [][]byte, error)) *MultiIndexer_FromResource_Call { + _c.Call.Return(run) + return _c +} + +// NewMultiIndexer creates a new instance of MultiIndexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMultiIndexer(t interface { + mock.TestingT + Cleanup(func()) +}) *MultiIndexer { + mock := &MultiIndexer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/index/indexmock/mock_ResourceIterator.go b/internal/controller/cache/index/indexmock/mock_ResourceIterator.go new file mode 100644 index 000000000000..c248a3e03938 --- /dev/null +++ b/internal/controller/cache/index/indexmock/mock_ResourceIterator.go @@ -0,0 +1,78 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package indexmock + +import ( + pbresource "github.com/hashicorp/consul/proto-public/pbresource" + mock "github.com/stretchr/testify/mock" +) + +// ResourceIterator is an autogenerated mock type for the ResourceIterator type +type ResourceIterator struct { + mock.Mock +} + +type ResourceIterator_Expecter struct { + mock *mock.Mock +} + +func (_m *ResourceIterator) EXPECT() *ResourceIterator_Expecter { + return &ResourceIterator_Expecter{mock: &_m.Mock} +} + +// Next provides a mock function with given fields: +func (_m *ResourceIterator) Next() *pbresource.Resource { + ret := _m.Called() + + var r0 *pbresource.Resource + if rf, ok := ret.Get(0).(func() *pbresource.Resource); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.Resource) + } + } + + return r0 +} + +// ResourceIterator_Next_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Next' +type ResourceIterator_Next_Call struct { + *mock.Call +} + +// Next is a helper method to define mock.On call +func (_e *ResourceIterator_Expecter) Next() *ResourceIterator_Next_Call { + return &ResourceIterator_Next_Call{Call: _e.mock.On("Next")} +} + +func (_c *ResourceIterator_Next_Call) Run(run func()) *ResourceIterator_Next_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ResourceIterator_Next_Call) Return(_a0 *pbresource.Resource) *ResourceIterator_Next_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ResourceIterator_Next_Call) RunAndReturn(run func() *pbresource.Resource) *ResourceIterator_Next_Call { + _c.Call.Return(run) + return _c +} + +// NewResourceIterator creates a new instance of ResourceIterator. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewResourceIterator(t interface { + mock.TestingT + Cleanup(func()) +}) *ResourceIterator { + mock := &ResourceIterator{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/index/indexmock/mock_SingleIndexer.go b/internal/controller/cache/index/indexmock/mock_SingleIndexer.go new file mode 100644 index 000000000000..cba9a6d2e607 --- /dev/null +++ b/internal/controller/cache/index/indexmock/mock_SingleIndexer.go @@ -0,0 +1,159 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package indexmock + +import ( + pbresource "github.com/hashicorp/consul/proto-public/pbresource" + mock "github.com/stretchr/testify/mock" +) + +// SingleIndexer is an autogenerated mock type for the SingleIndexer type +type SingleIndexer struct { + mock.Mock +} + +type SingleIndexer_Expecter struct { + mock *mock.Mock +} + +func (_m *SingleIndexer) EXPECT() *SingleIndexer_Expecter { + return &SingleIndexer_Expecter{mock: &_m.Mock} +} + +// FromArgs provides a mock function with given fields: args +func (_m *SingleIndexer) FromArgs(args ...interface{}) ([]byte, error) { + var _ca []interface{} + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(...interface{}) ([]byte, error)); ok { + return rf(args...) + } + if rf, ok := ret.Get(0).(func(...interface{}) []byte); ok { + r0 = rf(args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(...interface{}) error); ok { + r1 = rf(args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SingleIndexer_FromArgs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FromArgs' +type SingleIndexer_FromArgs_Call struct { + *mock.Call +} + +// FromArgs is a helper method to define mock.On call +// - args ...interface{} +func (_e *SingleIndexer_Expecter) FromArgs(args ...interface{}) *SingleIndexer_FromArgs_Call { + return &SingleIndexer_FromArgs_Call{Call: _e.mock.On("FromArgs", + append([]interface{}{}, args...)...)} +} + +func (_c *SingleIndexer_FromArgs_Call) Run(run func(args ...interface{})) *SingleIndexer_FromArgs_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-0) + for i, a := range args[0:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(variadicArgs...) + }) + return _c +} + +func (_c *SingleIndexer_FromArgs_Call) Return(_a0 []byte, _a1 error) *SingleIndexer_FromArgs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SingleIndexer_FromArgs_Call) RunAndReturn(run func(...interface{}) ([]byte, error)) *SingleIndexer_FromArgs_Call { + _c.Call.Return(run) + return _c +} + +// FromResource provides a mock function with given fields: r +func (_m *SingleIndexer) FromResource(r *pbresource.Resource) (bool, []byte, error) { + ret := _m.Called(r) + + var r0 bool + var r1 []byte + var r2 error + if rf, ok := ret.Get(0).(func(*pbresource.Resource) (bool, []byte, error)); ok { + return rf(r) + } + if rf, ok := ret.Get(0).(func(*pbresource.Resource) bool); ok { + r0 = rf(r) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(*pbresource.Resource) []byte); ok { + r1 = rf(r) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).([]byte) + } + } + + if rf, ok := ret.Get(2).(func(*pbresource.Resource) error); ok { + r2 = rf(r) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// SingleIndexer_FromResource_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FromResource' +type SingleIndexer_FromResource_Call struct { + *mock.Call +} + +// FromResource is a helper method to define mock.On call +// - r *pbresource.Resource +func (_e *SingleIndexer_Expecter) FromResource(r interface{}) *SingleIndexer_FromResource_Call { + return &SingleIndexer_FromResource_Call{Call: _e.mock.On("FromResource", r)} +} + +func (_c *SingleIndexer_FromResource_Call) Run(run func(r *pbresource.Resource)) *SingleIndexer_FromResource_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbresource.Resource)) + }) + return _c +} + +func (_c *SingleIndexer_FromResource_Call) Return(_a0 bool, _a1 []byte, _a2 error) *SingleIndexer_FromResource_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *SingleIndexer_FromResource_Call) RunAndReturn(run func(*pbresource.Resource) (bool, []byte, error)) *SingleIndexer_FromResource_Call { + _c.Call.Return(run) + return _c +} + +// NewSingleIndexer creates a new instance of SingleIndexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewSingleIndexer(t interface { + mock.TestingT + Cleanup(func()) +}) *SingleIndexer { + mock := &SingleIndexer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/index/indexmock/mock_resourceIterable.go b/internal/controller/cache/index/indexmock/mock_resourceIterable.go new file mode 100644 index 000000000000..8c5646f19b3a --- /dev/null +++ b/internal/controller/cache/index/indexmock/mock_resourceIterable.go @@ -0,0 +1,97 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package indexmock + +import ( + pbresource "github.com/hashicorp/consul/proto-public/pbresource" + mock "github.com/stretchr/testify/mock" +) + +// ResourceIterable is an autogenerated mock type for the resourceIterable type +type ResourceIterable struct { + mock.Mock +} + +type ResourceIterable_Expecter struct { + mock *mock.Mock +} + +func (_m *ResourceIterable) EXPECT() *ResourceIterable_Expecter { + return &ResourceIterable_Expecter{mock: &_m.Mock} +} + +// Next provides a mock function with given fields: +func (_m *ResourceIterable) Next() ([]byte, []*pbresource.Resource, bool) { + ret := _m.Called() + + var r0 []byte + var r1 []*pbresource.Resource + var r2 bool + if rf, ok := ret.Get(0).(func() ([]byte, []*pbresource.Resource, bool)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() []byte); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func() []*pbresource.Resource); ok { + r1 = rf() + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).([]*pbresource.Resource) + } + } + + if rf, ok := ret.Get(2).(func() bool); ok { + r2 = rf() + } else { + r2 = ret.Get(2).(bool) + } + + return r0, r1, r2 +} + +// ResourceIterable_Next_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Next' +type ResourceIterable_Next_Call struct { + *mock.Call +} + +// Next is a helper method to define mock.On call +func (_e *ResourceIterable_Expecter) Next() *ResourceIterable_Next_Call { + return &ResourceIterable_Next_Call{Call: _e.mock.On("Next")} +} + +func (_c *ResourceIterable_Next_Call) Run(run func()) *ResourceIterable_Next_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ResourceIterable_Next_Call) Return(_a0 []byte, _a1 []*pbresource.Resource, _a2 bool) *ResourceIterable_Next_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *ResourceIterable_Next_Call) RunAndReturn(run func() ([]byte, []*pbresource.Resource, bool)) *ResourceIterable_Next_Call { + _c.Call.Return(run) + return _c +} + +// NewResourceIterable creates a new instance of ResourceIterable. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewResourceIterable(t interface { + mock.TestingT + Cleanup(func()) +}) *ResourceIterable { + mock := &ResourceIterable{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/index/interfaces.go b/internal/controller/cache/index/interfaces.go new file mode 100644 index 000000000000..e890c3d2696f --- /dev/null +++ b/internal/controller/cache/index/interfaces.go @@ -0,0 +1,60 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import "github.com/hashicorp/consul/proto-public/pbresource" + +// Indexer is the base interface that all indexers must implement. Additionally +// an indexer must also implement either the SingleIndexer or MultiIndexer interface +// +//go:generate mockery --name Indexer --with-expecter +type Indexer interface { + FromArgs(args ...interface{}) ([]byte, error) +} + +// SingleIndexer is the interface to use to extract a single index value from a +// resource. E.g. extracting the resources owner ID. +// +//go:generate mockery --name SingleIndexer --with-expecter +type SingleIndexer interface { + Indexer + FromResource(r *pbresource.Resource) (bool, []byte, error) +} + +// MultiIndexer is the interface to implement for extracting multiple index +// values from a resource. E.g. extracting all resource References from the +// slice of references. +// +//go:generate mockery --name MultiIndexer --with-expecter +type MultiIndexer interface { + Indexer + FromResource(r *pbresource.Resource) (bool, [][]byte, error) +} + +// IndexOption is a functional option to use to modify an Indexes behavior. +type IndexOption func(*Index) + +// IndexRequired will cause the index to return a MissingRequiredIndexError +// in the event that the indexer returns no values for a resource. +func IndexRequired(s *Index) { + s.required = true +} + +// ResourceIterator is the interface that will be returned to iterate through +// a collection of results. +// +//go:generate mockery --name ResourceIterator --with-expecter +type ResourceIterator interface { + Next() *pbresource.Resource +} + +// Txn is an interface to control changes to an index within an transaction. +type Txn interface { + Get(args ...any) (*pbresource.Resource, error) + ListIterator(args ...any) (ResourceIterator, error) + ParentsIterator(args ...any) (ResourceIterator, error) + Insert(r *pbresource.Resource) error + Delete(r *pbresource.Resource) error + Commit() +} diff --git a/internal/controller/cache/index/iterator.go b/internal/controller/cache/index/iterator.go new file mode 100644 index 000000000000..906162367394 --- /dev/null +++ b/internal/controller/cache/index/iterator.go @@ -0,0 +1,37 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import "github.com/hashicorp/consul/proto-public/pbresource" + +//go:generate mockery --name resourceIterable --with-expecter --exported +type resourceIterable interface { + Next() ([]byte, []*pbresource.Resource, bool) +} + +type resourceIterator struct { + current []*pbresource.Resource + iter resourceIterable +} + +func (i *resourceIterator) Next() *pbresource.Resource { + // Maybe get a new list from the internal iterator + if len(i.current) == 0 { + _, i.current, _ = i.iter.Next() + } + + var rsc *pbresource.Resource + switch len(i.current) { + case 0: + // we are completely out of data so we can return + case 1: + rsc = i.current[0] + i.current = nil + default: + rsc = i.current[0] + i.current = i.current[1:] + } + + return rsc +} diff --git a/internal/controller/cache/index/iterator_test.go b/internal/controller/cache/index/iterator_test.go new file mode 100644 index 000000000000..7b2f56749ae4 --- /dev/null +++ b/internal/controller/cache/index/iterator_test.go @@ -0,0 +1,65 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import ( + "testing" + + "github.com/hashicorp/consul/internal/controller/cache/index/indexmock" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/stretchr/testify/require" +) + +var ( + testResourceType = &pbresource.Type{ + Group: "test", + GroupVersion: "v1", + Kind: "fake", + } +) + +func testResource(name string) *pbresource.Resource { + return resourcetest.Resource(testResourceType, name). + WithTenancy(resource.DefaultNamespacedTenancy()). + Build() +} + +func TestResourceIteratorNext(t *testing.T) { + m := indexmock.NewResourceIterable(t) + + r1 := testResource("one") + + r2 := testResource("two") + r3 := testResource("three") + + m.EXPECT().Next().Once().Return(nil, []*pbresource.Resource{r1}, true) + m.EXPECT().Next().Once().Return(nil, []*pbresource.Resource{r2, r3}, false) + m.EXPECT().Next().Return(nil, nil, false) + + i := resourceIterator{ + iter: m, + } + + // iterator is processing the first list of items + actual := i.Next() + require.NotNil(t, actual) + prototest.AssertDeepEqual(t, r1, actual) + // iterator should now be processing the second list of items. + actual = i.Next() + require.NotNil(t, actual) + prototest.AssertDeepEqual(t, r2, actual) + // second element of second list returned + actual = i.Next() + require.NotNil(t, actual) + prototest.AssertDeepEqual(t, r3, actual) + // no more items so a call to Next should return nil + actual = i.Next() + require.Nil(t, actual) + // verify that it continues to return nil indefinitely without causing a panic. + actual = i.Next() + require.Nil(t, actual) +} diff --git a/internal/controller/cache/index/testdata/MissingRequiredIndex.golden b/internal/controller/cache/index/testdata/MissingRequiredIndex.golden new file mode 100644 index 000000000000..5095d1bb63e8 --- /dev/null +++ b/internal/controller/cache/index/testdata/MissingRequiredIndex.golden @@ -0,0 +1 @@ +the indexer produced no value for the required "fake-index-name" index \ No newline at end of file diff --git a/internal/controller/cache/index/txn.go b/internal/controller/cache/index/txn.go new file mode 100644 index 000000000000..2a932e6a20aa --- /dev/null +++ b/internal/controller/cache/index/txn.go @@ -0,0 +1,173 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import ( + iradix "github.com/hashicorp/go-immutable-radix/v2" + + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +type txn struct { + inner *iradix.Txn[[]*pbresource.Resource] + index *IndexedData + dirty bool +} + +func (t *txn) Get(args ...any) (*pbresource.Resource, error) { + val, err := t.index.fromArgs(args...) + if err != nil { + return nil, err + } + + return t.getRaw(val), nil +} + +func (t *txn) getRaw(val []byte) *pbresource.Resource { + resources, found := t.inner.Get(val) + if !found || len(resources) < 1 { + return nil + } + + return resources[0] +} + +func (t *txn) ListIterator(args ...any) (ResourceIterator, error) { + val, err := t.index.fromArgs(args...) + if err != nil { + return nil, err + } + + iter := t.inner.Root().Iterator() + iter.SeekPrefix(val) + + return &resourceIterator{iter: iter}, nil +} + +func (t *txn) ParentsIterator(args ...any) (ResourceIterator, error) { + val, err := t.index.fromArgs(args...) + if err != nil { + return nil, err + } + + iter := t.inner.Root().PathIterator(val) + + return &resourceIterator{iter: iter}, nil +} + +func (t *txn) Insert(r *pbresource.Resource) error { + indexed, vals, err := t.index.fromResource(r) + if err != nil { + return err + } + + if !indexed && t.index.required { + return MissingRequiredIndexError{Name: t.index.Name()} + } + + for _, val := range vals { + if t.insertOne(val, r) { + t.dirty = true + } + } + + return nil +} + +func (t *txn) insertOne(idxVal []byte, r *pbresource.Resource) bool { + var newResources []*pbresource.Resource + existing, found := t.inner.Get(idxVal) + if found { + newResources = make([]*pbresource.Resource, 0, len(existing)+1) + found := false + for _, rsc := range existing { + if !resource.EqualID(rsc.GetId(), r.GetId()) { + newResources = append(newResources, rsc) + } else { + found = true + newResources = append(newResources, r) + } + } + + if !found { + newResources = append(newResources, r) + } + } else { + newResources = []*pbresource.Resource{r} + } + t.inner.Insert(idxVal, newResources) + return true +} + +func (t *txn) Delete(r *pbresource.Resource) error { + indexed, vals, err := t.index.fromResource(r) + if err != nil { + return err + } + + if !indexed && t.index.required { + return MissingRequiredIndexError{Name: t.index.Name()} + } + + for _, val := range vals { + if t.deleteOne(val, r) { + t.dirty = true + } + } + + return nil +} + +func (t *txn) deleteOne(idxVal []byte, r *pbresource.Resource) bool { + existing, found := t.inner.Get(idxVal) + if !found { + // this resource is not currently indexed + return false + } + + existingIdx := -1 + for idx, rsc := range existing { + if resource.EqualID(rsc.GetId(), r.GetId()) { + existingIdx = idx + break + } + } + + switch { + // The index value maps to some resources but none had the same id as the one we wish + // to delete. Therefore we can leave the slice alone because the delete is a no-op + case existingIdx < 0: + return false + + // We found something (existingIdex >= 0) but there is only one thing in the array. In + // this case we should remove the whole resource slice from the tree. + case len(existing) == 1: + t.inner.Delete(idxVal) + + // The first slice element is the resource to delete so we can reslice safely + case existingIdx == 0: + t.inner.Insert(idxVal, existing[1:]) + + // The last slice element is the resource to delete so we can reslice safely + case existingIdx == len(existing)-1: + t.inner.Insert(idxVal, existing[:len(existing)-1]) + + // The resource to delete exists somewhere in the middle of the slice. So we must + // recreate a new backing array to maintain immutability of the data being stored + default: + newResources := make([]*pbresource.Resource, len(existing)-1) + copy(newResources[0:existingIdx], existing[0:existingIdx]) + copy(newResources[existingIdx:], existing[existingIdx+1:]) + t.inner.Insert(idxVal, newResources) + } + + return true +} + +func (t *txn) Commit() { + if t.dirty { + t.index.tree = t.inner.Commit() + } +} diff --git a/internal/controller/cache/index/txn_test.go b/internal/controller/cache/index/txn_test.go new file mode 100644 index 000000000000..5dfc24813791 --- /dev/null +++ b/internal/controller/cache/index/txn_test.go @@ -0,0 +1,382 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package index + +import ( + "errors" + "testing" + + "github.com/hashicorp/consul/internal/controller/cache/index/indexmock" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +var fakeTestError = errors.New("fake test error") + +func TestTxn(t *testing.T) { + suite.Run(t, new(txnSuite)) +} + +type txnSuite struct { + suite.Suite + + indexer *indexmock.SingleIndexer + index *IndexedData + + r1 *pbresource.Resource + r2 *pbresource.Resource + r11 *pbresource.Resource + r123 *pbresource.Resource +} + +func (suite *txnSuite) SetupTest() { + suite.indexer = indexmock.NewSingleIndexer(suite.T()) + suite.index = New("test", suite.indexer, IndexRequired).IndexedData() + + suite.r1 = testResource("r1") + suite.r2 = testResource("r2") + suite.r11 = testResource("r11") + suite.r123 = testResource("r123") + + exp := suite.indexer.EXPECT() + exp.FromResource(suite.r1).Return(true, PrefixIndexFromRefOrID(suite.r1.Id), nil).Once() + exp.FromResource(suite.r2).Return(true, PrefixIndexFromRefOrID(suite.r2.Id), nil).Once() + exp.FromResource(suite.r11).Return(true, PrefixIndexFromRefOrID(suite.r11.Id), nil).Once() + exp.FromResource(suite.r123).Return(true, PrefixIndexFromRefOrID(suite.r123.Id), nil).Once() + + txn := suite.index.Txn() + txn.Insert(suite.r1) + txn.Insert(suite.r2) + txn.Insert(suite.r11) + txn.Insert(suite.r123) + txn.Commit() +} + +func (suite *txnSuite) TestGet() { + suite.indexer.EXPECT(). + FromArgs(suite.r1.Id). + RunAndReturn(PrefixReferenceOrIDFromArgs). + Once() + + actual, err := suite.index.Txn().Get(suite.r1.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), actual) + prototest.AssertDeepEqual(suite.T(), suite.r1, actual) +} + +func (suite *txnSuite) TestGet_NotFound() { + suite.indexer.EXPECT(). + FromArgs(suite.r1.Id). + Return(nil, nil). + Once() + + actual, err := suite.index.Txn().Get(suite.r1.Id) + require.NoError(suite.T(), err) + require.Nil(suite.T(), actual) +} + +func (suite *txnSuite) TestGet_Error() { + suite.indexer.EXPECT(). + FromArgs(suite.r1.Id). + Return(nil, fakeTestError). + Once() + + actual, err := suite.index.Txn().Get(suite.r1.Id) + require.ErrorIs(suite.T(), err, fakeTestError) + require.Nil(suite.T(), actual) +} + +func (suite *txnSuite) TestListIterator() { + refQuery := &pbresource.Reference{ + Type: testResourceType, + } + + suite.indexer.EXPECT(). + FromArgs(refQuery). + // Calculate a prefix based query for use with the ListIterator + RunAndReturn(PrefixReferenceOrIDFromArgs). + Once() + + iter, err := suite.index.Txn().ListIterator(refQuery) + require.NoError(suite.T(), err) + + r := iter.Next() + require.NotNil(suite.T(), r) + prototest.AssertDeepEqual(suite.T(), suite.r1, r) + + r = iter.Next() + require.NotNil(suite.T(), r) + prototest.AssertDeepEqual(suite.T(), suite.r11, r) + + r = iter.Next() + require.NotNil(suite.T(), r) + prototest.AssertDeepEqual(suite.T(), suite.r123, r) + + r = iter.Next() + require.NotNil(suite.T(), r) + prototest.AssertDeepEqual(suite.T(), suite.r2, r) + + r = iter.Next() + require.Nil(suite.T(), r) +} + +func (suite *txnSuite) TestListIterator_Error() { + suite.indexer.EXPECT(). + // abusing the mock to create a shortened index for us. + FromArgs("sentinel"). + Return(nil, fakeTestError). + Once() + + iter, err := suite.index.Txn().ListIterator("sentinel") + require.ErrorIs(suite.T(), err, fakeTestError) + require.Nil(suite.T(), iter) +} + +func (suite *txnSuite) TestParentsIterator() { + suite.indexer.EXPECT(). + // abusing the mock to create a shortened index for us. + FromArgs(suite.r123.Id). + RunAndReturn(ReferenceOrIDFromArgs). + Once() + + iter, err := suite.index.Txn().ParentsIterator(suite.r123.Id) + require.NoError(suite.T(), err) + + r := iter.Next() + require.NotNil(suite.T(), r) + prototest.AssertDeepEqual(suite.T(), suite.r1, r) + + r = iter.Next() + require.NotNil(suite.T(), r) + prototest.AssertDeepEqual(suite.T(), suite.r123, r) + + r = iter.Next() + require.Nil(suite.T(), r) +} + +func (suite *txnSuite) TestParentsIterator_Error() { + suite.indexer.EXPECT(). + // abusing the mock to create a shortened index for us. + FromArgs("sentinel"). + Return(nil, fakeTestError). + Once() + + iter, err := suite.index.Txn().ParentsIterator("sentinel") + require.ErrorIs(suite.T(), err, fakeTestError) + require.Nil(suite.T(), iter) +} + +func (suite *txnSuite) TestInsert_MissingRequiredIndex() { + suite.indexer.EXPECT(). + FromResource(suite.r1). + Return(false, nil, nil). + Once() + + err := suite.index.Txn().Insert(suite.r1) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, MissingRequiredIndexError{Name: "test"}) +} + +func (suite *txnSuite) TestInsert_IndexError() { + suite.indexer.EXPECT(). + FromResource(suite.r1). + Return(false, nil, fakeTestError). + Once() + + err := suite.index.Txn().Insert(suite.r1) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, fakeTestError) +} + +func (suite *txnSuite) TestInsert_UpdateInternalSlice() { + // So if you look closely this is going to insert the newR + // resource but is calculating the index value of the r1 + // resource. This is done to exercise the insertion functionality + // where indexes are non-unique and at each leaf in the radix + // tree we must keep a list of items. + newR := testResource("newR") + suite.indexer.EXPECT(). + FromResource(newR). + Return(true, PrefixIndexFromRefOrID(suite.r1.Id), nil). + Once() + + // here we are setting up the expecation for re-inserting r1 + newR1 := testResource("r1") + suite.indexer.EXPECT(). + FromResource(newR1). + Return(true, PrefixIndexFromRefOrID(newR1.Id), nil). + Once() + + // Actually index the resource + txn := suite.index.Txn() + require.NoError(suite.T(), txn.Insert(newR)) + require.NoError(suite.T(), txn.Insert(newR1)) + txn.Commit() + + // No validate that the insertions worked correctly. + suite.indexer.EXPECT(). + FromArgs(newR1.Id). + RunAndReturn(PrefixReferenceOrIDFromArgs). + Once() + iter, err := suite.index.Txn().ListIterator(newR1.Id) + require.NoError(suite.T(), err) + + var resources []*pbresource.Resource + for r := iter.Next(); r != nil; r = iter.Next() { + resources = append(resources, r) + } + + prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{newR, newR1, suite.r11, suite.r123}, resources) +} + +func (suite *txnSuite) TestDelete() { + // expected to index the resource during deletion + suite.indexer.EXPECT(). + FromResource(suite.r1). + Return(true, PrefixIndexFromRefOrID(suite.r1.Id), nil). + Once() + + // perform the deletion + txn := suite.index.Txn() + require.NoError(suite.T(), txn.Delete(suite.r1)) + txn.Commit() + + // expect to index the ID during the query + suite.indexer.EXPECT(). + FromArgs(suite.r1.Id). + RunAndReturn(PrefixReferenceOrIDFromArgs). + Once() + + // ensure that the deletion worked + res, err := suite.index.Txn().Get(suite.r1.Id) + require.NoError(suite.T(), err) + require.Nil(suite.T(), res) +} + +func (suite *txnSuite) TestDelete_NotFound() { + res := testResource("foo") + suite.indexer.EXPECT(). + FromResource(res). + Return(true, PrefixIndexFromRefOrID(res.Id), nil). + Once() + + // attempt the deletion + txn := suite.index.Txn() + require.NoError(suite.T(), txn.Delete(res)) + txn.Commit() +} + +func (suite *txnSuite) TestDelete_IdxPresentValNotFound() { + // The index holds a radix tree that points to a slice of resources. + // A slice is used to account for non-unique indexes. This test case + // is meant to specifically exercise the case where the radix leaf + // node exists but a resource with an equivalent ID is not present + // in the slice. + + // Calculating the index from the r1 resource will ensure that a + // radix leaf exists but since newR was never inserted this should + // exercise the case where the resource is not found within the slice + newR := testResource("newR") + suite.indexer.EXPECT(). + FromResource(newR). + Return(true, PrefixIndexFromRefOrID(suite.r1.Id), nil). + Once() + + txn := suite.index.Txn() + require.NoError(suite.T(), txn.Delete(newR)) + txn.Commit() +} + +func (suite *txnSuite) TestDelete_SliceModifications() { + commonIndex := []byte("fake\x00") + + injectResource := func(name string) *pbresource.Resource { + r := testResource(name) + suite.indexer.EXPECT(). + FromResource(r). + Return(true, commonIndex, nil). + Once() + + txn := suite.index.Txn() + require.NoError(suite.T(), txn.Insert(r)) + txn.Commit() + + return r + } + + fr1 := injectResource("fr1") + fr2 := injectResource("fr2") + fr3 := injectResource("fr3") + fr4 := injectResource("fr4") + fr5 := injectResource("fr5") + + txn := suite.index.Txn() + + // excercise deletion of the first slice element + suite.indexer.EXPECT(). + FromResource(fr1). + Return(true, commonIndex, nil). + Once() + + require.NoError(suite.T(), txn.Delete(fr1)) + + // excercise deletion of the last slice element + suite.indexer.EXPECT(). + FromResource(fr5). + Return(true, commonIndex, nil). + Once() + + require.NoError(suite.T(), txn.Delete(fr5)) + + // excercise deletion from the middle of the list + suite.indexer.EXPECT(). + FromResource(fr3). + Return(true, commonIndex, nil). + Once() + + require.NoError(suite.T(), txn.Delete(fr3)) + + txn.Commit() + + // no verify that only fr2 and fr4 exist + suite.indexer.EXPECT(). + FromArgs(fr2.Id). + Return(commonIndex, nil). + Once() + + iter, err := suite.index.Txn().ListIterator(fr2.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), iter) + + var resources []*pbresource.Resource + for r := iter.Next(); r != nil; r = iter.Next() { + resources = append(resources, r) + } + + prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{fr2, fr4}, resources) +} + +func (suite *txnSuite) TestDelete_MissingRequiredIndex() { + suite.indexer.EXPECT(). + FromResource(suite.r1). + Return(false, nil, nil). + Once() + + err := suite.index.Txn().Delete(suite.r1) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, MissingRequiredIndexError{Name: "test"}) +} + +func (suite *txnSuite) TestDelete_IndexError() { + suite.indexer.EXPECT(). + FromResource(suite.r1). + Return(false, nil, fakeTestError). + Once() + + err := suite.index.Txn().Delete(suite.r1) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, fakeTestError) +} diff --git a/internal/controller/cache/indexers/.mockery.yaml b/internal/controller/cache/indexers/.mockery.yaml new file mode 100644 index 000000000000..5346da58669c --- /dev/null +++ b/internal/controller/cache/indexers/.mockery.yaml @@ -0,0 +1,15 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +with-expecter: true +all: true +recursive: false +# We don't want the mocks within proto-public so as to force a dependency +# of the testify library on the modules usage. The mocks are only for +# internal testing purposes. Other consumers can generated the mocks into +# their own code base. +dir: "indexersmock" +outpkg: "indexersmock" +mockname: "{{.InterfaceName}}" +packages: + github.com/hashicorp/consul/internal/controller/cache/indexers: diff --git a/internal/controller/cache/indexers/decoded_indexer.go b/internal/controller/cache/indexers/decoded_indexer.go new file mode 100644 index 000000000000..213f5993870d --- /dev/null +++ b/internal/controller/cache/indexers/decoded_indexer.go @@ -0,0 +1,65 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package indexers + +import ( + "github.com/hashicorp/consul/internal/controller/cache/index" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" + "google.golang.org/protobuf/proto" +) + +type FromArgs func(args ...any) ([]byte, error) +type SingleIndexer[T proto.Message] func(r *resource.DecodedResource[T]) (bool, []byte, error) +type MultiIndexer[T proto.Message] func(r *resource.DecodedResource[T]) (bool, [][]byte, error) + +func DecodedSingleIndexer[T proto.Message](name string, args FromArgs, idx SingleIndexer[T]) *index.Index { + return index.New(name, &singleIndexer[T]{ + decodedIndexer: idx, + indexArgs: args, + }) +} + +func DecodedMultiIndexer[T proto.Message](name string, args FromArgs, idx MultiIndexer[T]) *index.Index { + return index.New(name, &multiIndexer[T]{ + indexArgs: args, + decodedIndexer: idx, + }) +} + +type singleIndexer[T proto.Message] struct { + indexArgs FromArgs + decodedIndexer SingleIndexer[T] +} + +func (i *singleIndexer[T]) FromArgs(args ...any) ([]byte, error) { + return i.indexArgs(args...) +} + +func (i *singleIndexer[T]) FromResource(r *pbresource.Resource) (bool, []byte, error) { + res, err := resource.Decode[T](r) + if err != nil { + return false, nil, err + } + + return i.decodedIndexer(res) +} + +type multiIndexer[T proto.Message] struct { + decodedIndexer MultiIndexer[T] + indexArgs FromArgs +} + +func (i *multiIndexer[T]) FromArgs(args ...any) ([]byte, error) { + return i.indexArgs(args...) +} + +func (i *multiIndexer[T]) FromResource(r *pbresource.Resource) (bool, [][]byte, error) { + res, err := resource.Decode[T](r) + if err != nil { + return false, nil, err + } + + return i.decodedIndexer(res) +} diff --git a/internal/controller/cache/indexers/decoded_indexer_test.go b/internal/controller/cache/indexers/decoded_indexer_test.go new file mode 100644 index 000000000000..0fa876c193ef --- /dev/null +++ b/internal/controller/cache/indexers/decoded_indexer_test.go @@ -0,0 +1,295 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package indexers + +import ( + "errors" + "testing" + + "github.com/hashicorp/consul/internal/controller/cache/indexers/indexersmock" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/resourcetest" + pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v1" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +var ( + fakeTestError = errors.New("fake test error") +) + +func TestSingleIndexer(t *testing.T) { + suite.Run(t, &decodedSingleIndexerSuite{}) +} + +type decodedSingleIndexerSuite struct { + suite.Suite + + indexer *indexersmock.SingleIndexer[*pbdemo.Album] + args *indexersmock.FromArgs + + index *singleIndexer[*pbdemo.Album] +} + +func (suite *decodedSingleIndexerSuite) SetupTest() { + suite.indexer = indexersmock.NewSingleIndexer[*pbdemo.Album](suite.T()) + suite.args = indexersmock.NewFromArgs(suite.T()) + suite.index = &singleIndexer[*pbdemo.Album]{ + indexArgs: suite.args.Execute, + decodedIndexer: suite.indexer.Execute, + } +} + +func (suite *decodedSingleIndexerSuite) TestFromArgs() { + suite.args.EXPECT(). + Execute("blah", 1, true). + Return([]byte("foo"), nil). + Once() + + val, err := suite.index.FromArgs("blah", 1, true) + require.NoError(suite.T(), err) + require.Equal(suite.T(), []byte("foo"), val) +} + +func (suite *decodedSingleIndexerSuite) TestFromArgs_Error() { + suite.args.EXPECT(). + Execute("blah", 1, true). + Return(nil, fakeTestError). + Once() + + val, err := suite.index.FromArgs("blah", 1, true) + require.ErrorIs(suite.T(), err, fakeTestError) + require.Nil(suite.T(), val) +} + +func (suite *decodedSingleIndexerSuite) TestFromResource() { + res := resourcetest.Resource(pbdemo.AlbumType, "foo"). + WithData(suite.T(), &pbdemo.Album{ + Name: "blah", + }). + Build() + + dec := resourcetest.MustDecode[*pbdemo.Album](suite.T(), res) + + suite.indexer.EXPECT(). + Execute(dec). + Return(true, []byte{1, 2, 3}, nil). + Once() + + indexed, val, err := suite.index.FromResource(res) + require.True(suite.T(), indexed) + require.NoError(suite.T(), err) + require.Equal(suite.T(), []byte{1, 2, 3}, val) +} + +func (suite *decodedSingleIndexerSuite) TestFromResource_Error() { + res := resourcetest.Resource(pbdemo.AlbumType, "foo"). + WithData(suite.T(), &pbdemo.Album{ + Name: "blah", + }). + Build() + + dec := resourcetest.MustDecode[*pbdemo.Album](suite.T(), res) + + suite.indexer.EXPECT(). + Execute(dec). + Return(false, nil, fakeTestError). + Once() + + indexed, val, err := suite.index.FromResource(res) + require.False(suite.T(), indexed) + require.ErrorIs(suite.T(), err, fakeTestError) + require.Nil(suite.T(), val) +} + +func (suite *decodedSingleIndexerSuite) TestFromResource_DecodeError() { + res := resourcetest.Resource(pbdemo.ArtistType, "foo"). + WithData(suite.T(), &pbdemo.Artist{ + Name: "blah", + }). + Build() + + var expectedErr resource.ErrDataParse + indexed, val, err := suite.index.FromResource(res) + require.False(suite.T(), indexed) + require.ErrorAs(suite.T(), err, &expectedErr) + require.Nil(suite.T(), val) +} + +func (suite *decodedSingleIndexerSuite) TestIntegration() { + // This test attempts to do enough to ensure that the + // cache Index creator configures all the interfaces/funcs + // the correct way. It is not meant to fully test the + // Index type itself. + res := resourcetest.Resource(pbdemo.AlbumType, "foo"). + WithData(suite.T(), &pbdemo.Album{ + Name: "blah", + }). + Build() + + dec := resourcetest.MustDecode[*pbdemo.Album](suite.T(), res) + + idx := DecodedSingleIndexer("test", suite.args.Execute, suite.indexer.Execute).IndexedData() + + suite.indexer.EXPECT(). + Execute(dec). + Return(true, []byte{1, 2}, nil). + Once() + + txn := idx.Txn() + require.NoError(suite.T(), txn.Insert(res)) + txn.Commit() + + suite.args.EXPECT(). + Execute("fake"). + Return([]byte{1, 2}, nil). + Once() + + r, err := idx.Txn().Get("fake") + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), res, r) +} + +func TestMultiIndexer(t *testing.T) { + suite.Run(t, &decodedMultiIndexerSuite{}) +} + +type decodedMultiIndexerSuite struct { + suite.Suite + + indexer *indexersmock.MultiIndexer[*pbdemo.Album] + args *indexersmock.FromArgs + + index *multiIndexer[*pbdemo.Album] +} + +func (suite *decodedMultiIndexerSuite) SetupTest() { + suite.indexer = indexersmock.NewMultiIndexer[*pbdemo.Album](suite.T()) + suite.args = indexersmock.NewFromArgs(suite.T()) + suite.index = &multiIndexer[*pbdemo.Album]{ + indexArgs: suite.args.Execute, + decodedIndexer: suite.indexer.Execute, + } +} + +func (suite *decodedMultiIndexerSuite) TestFromArgs() { + suite.args.EXPECT(). + Execute("blah", 1, true). + Return([]byte("foo"), nil). + Once() + + val, err := suite.index.FromArgs("blah", 1, true) + require.NoError(suite.T(), err) + require.Equal(suite.T(), []byte("foo"), val) +} + +func (suite *decodedMultiIndexerSuite) TestFromArgs_Error() { + suite.args.EXPECT(). + Execute("blah", 1, true). + Return(nil, fakeTestError). + Once() + + val, err := suite.index.FromArgs("blah", 1, true) + require.ErrorIs(suite.T(), err, fakeTestError) + require.Nil(suite.T(), val) +} + +func (suite *decodedMultiIndexerSuite) TestFromResource() { + res := resourcetest.Resource(pbdemo.AlbumType, "foo"). + WithData(suite.T(), &pbdemo.Album{ + Name: "blah", + }). + Build() + + dec := resourcetest.MustDecode[*pbdemo.Album](suite.T(), res) + + suite.indexer.EXPECT(). + Execute(dec). + Return(true, [][]byte{{1, 2}, {3}}, nil). + Once() + + indexed, val, err := suite.index.FromResource(res) + require.True(suite.T(), indexed) + require.NoError(suite.T(), err) + require.Equal(suite.T(), [][]byte{{1, 2}, {3}}, val) +} + +func (suite *decodedMultiIndexerSuite) TestFromResource_Error() { + res := resourcetest.Resource(pbdemo.AlbumType, "foo"). + WithData(suite.T(), &pbdemo.Album{ + Name: "blah", + }). + Build() + + dec := resourcetest.MustDecode[*pbdemo.Album](suite.T(), res) + + suite.indexer.EXPECT(). + Execute(dec). + Return(false, nil, fakeTestError). + Once() + + indexed, val, err := suite.index.FromResource(res) + require.False(suite.T(), indexed) + require.ErrorIs(suite.T(), err, fakeTestError) + require.Nil(suite.T(), val) +} + +func (suite *decodedMultiIndexerSuite) TestFromResource_DecodeError() { + res := resourcetest.Resource(pbdemo.ArtistType, "foo"). + WithData(suite.T(), &pbdemo.Artist{ + Name: "blah", + }). + Build() + + var expectedErr resource.ErrDataParse + indexed, val, err := suite.index.FromResource(res) + require.False(suite.T(), indexed) + require.ErrorAs(suite.T(), err, &expectedErr) + require.Nil(suite.T(), val) +} + +func (suite *decodedMultiIndexerSuite) TestIntegration() { + // This test attempts to do enough to ensure that the + // cache Index creator configures all the interfaces/funcs + // the correct way. It is not meant to fully test the + // Index type itself. + res := resourcetest.Resource(pbdemo.AlbumType, "foo"). + WithData(suite.T(), &pbdemo.Album{ + Name: "blah", + }). + Build() + + dec := resourcetest.MustDecode[*pbdemo.Album](suite.T(), res) + + idx := DecodedMultiIndexer("test", suite.args.Execute, suite.indexer.Execute).IndexedData() + + suite.indexer.EXPECT(). + Execute(dec). + Return(true, [][]byte{{1, 2}, {3}}, nil). + Once() + + txn := idx.Txn() + require.NoError(suite.T(), txn.Insert(res)) + txn.Commit() + + suite.args.EXPECT(). + Execute("fake"). + Return([]byte{1, 2}, nil). + Once() + + suite.args.EXPECT(). + Execute("fake2"). + Return([]byte{3}, nil). + Once() + + txn = idx.Txn() + r, err := txn.Get("fake") + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), res, r) + + r, err = txn.Get("fake2") + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), res, r) +} diff --git a/internal/controller/cache/indexers/id_indexer.go b/internal/controller/cache/indexers/id_indexer.go new file mode 100644 index 000000000000..f50d609446f0 --- /dev/null +++ b/internal/controller/cache/indexers/id_indexer.go @@ -0,0 +1,48 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package indexers + +import ( + "github.com/hashicorp/consul/internal/controller/cache/index" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +func IDIndex(name string, opts ...index.IndexOption) *index.Index { + return index.New(name, &idOrRefIndexer{getID: getResourceID}, opts...) +} + +func OwnerIndex(name string, opts ...index.IndexOption) *index.Index { + return index.New(name, &idOrRefIndexer{getID: getOwnerID}, opts...) +} + +func SingleIDOrRefIndex(name string, f GetSingleRefOrID, opts ...index.IndexOption) *index.Index { + return index.New(name, &idOrRefIndexer{getID: f}, opts...) +} + +//go:generate mockery --name GetSingleRefOrID --with-expecter +type GetSingleRefOrID func(*pbresource.Resource) resource.ReferenceOrID + +func getResourceID(r *pbresource.Resource) resource.ReferenceOrID { + return r.GetId() +} + +func getOwnerID(r *pbresource.Resource) resource.ReferenceOrID { + return r.GetOwner() +} + +type idOrRefIndexer struct { + getID GetSingleRefOrID +} + +// FromArgs constructs a radix tree key from an ID for lookup. +func (i idOrRefIndexer) FromArgs(args ...any) ([]byte, error) { + return index.MaybePrefixReferenceOrIDFromArgs(args...) +} + +// FromObject constructs a radix tree key from a Resource at write-time, or an +// ID at delete-time. +func (i idOrRefIndexer) FromResource(r *pbresource.Resource) (bool, []byte, error) { + return true, index.IndexFromRefOrID(i.getID(r)), nil +} diff --git a/internal/controller/cache/indexers/id_indexer_test.go b/internal/controller/cache/indexers/id_indexer_test.go new file mode 100644 index 000000000000..a5b80e3fdb31 --- /dev/null +++ b/internal/controller/cache/indexers/id_indexer_test.go @@ -0,0 +1,96 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package indexers + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/internal/controller/cache/index" + "github.com/hashicorp/consul/internal/controller/cache/indexers/indexersmock" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v1" + "github.com/hashicorp/consul/proto/private/prototest" +) + +func TestIDIndex(t *testing.T) { + idx := IDIndex("test", index.IndexRequired).IndexedData() + + r1 := resourcetest.Resource(pbdemo.AlbumType, "foo"). + WithTenancy(&pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + }). + WithData(t, &pbdemo.Album{ + Name: "foo", + }). + Build() + + txn := idx.Txn() + require.NoError(t, txn.Insert(r1)) + txn.Commit() + + out, err := idx.Txn().Get(r1.Id) + require.NoError(t, err) + prototest.AssertDeepEqual(t, r1, out) +} + +func TestOwnerIndex(t *testing.T) { + idx := OwnerIndex("test", index.IndexRequired).IndexedData() + + r1 := resourcetest.Resource(pbdemo.AlbumType, "foo"). + WithTenancy(&pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + }). + WithData(t, &pbdemo.Album{ + Name: "foo", + }). + WithOwner(&pbresource.ID{ + Type: pbdemo.ArtistType, + Tenancy: &pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + }, + }). + Build() + + txn := idx.Txn() + require.NoError(t, txn.Insert(r1)) + txn.Commit() + + out, err := idx.Txn().Get(r1.Owner) + require.NoError(t, err) + prototest.AssertDeepEqual(t, r1, out) +} + +func TestSingleIDOrRefIndex(t *testing.T) { + getRef := indexersmock.NewGetSingleRefOrID(t) + + idx := SingleIDOrRefIndex("test", getRef.Execute).IndexedData() + + r1 := resourcetest.Resource(pbdemo.AlbumType, "foo").Build() + ref := &pbresource.Reference{ + Type: pbdemo.ArtistType, + Tenancy: &pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + }, + Name: "foo", + } + + getRef.EXPECT().Execute(r1). + Return(ref). + Once() + + txn := idx.Txn() + require.NoError(t, txn.Insert(r1)) + txn.Commit() + + out, err := idx.Txn().Get(ref) + require.NoError(t, err) + prototest.AssertDeepEqual(t, r1, out) +} diff --git a/internal/controller/cache/indexers/indexersmock/mock_BoundReferences.go b/internal/controller/cache/indexers/indexersmock/mock_BoundReferences.go new file mode 100644 index 000000000000..aa8bf7b0058c --- /dev/null +++ b/internal/controller/cache/indexers/indexersmock/mock_BoundReferences.go @@ -0,0 +1,122 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package indexersmock + +import ( + pbresource "github.com/hashicorp/consul/proto-public/pbresource" + mock "github.com/stretchr/testify/mock" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" +) + +// BoundReferences is an autogenerated mock type for the BoundReferences type +type BoundReferences struct { + mock.Mock +} + +type BoundReferences_Expecter struct { + mock *mock.Mock +} + +func (_m *BoundReferences) EXPECT() *BoundReferences_Expecter { + return &BoundReferences_Expecter{mock: &_m.Mock} +} + +// GetBoundReferences provides a mock function with given fields: +func (_m *BoundReferences) GetBoundReferences() []*pbresource.Reference { + ret := _m.Called() + + var r0 []*pbresource.Reference + if rf, ok := ret.Get(0).(func() []*pbresource.Reference); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*pbresource.Reference) + } + } + + return r0 +} + +// BoundReferences_GetBoundReferences_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBoundReferences' +type BoundReferences_GetBoundReferences_Call struct { + *mock.Call +} + +// GetBoundReferences is a helper method to define mock.On call +func (_e *BoundReferences_Expecter) GetBoundReferences() *BoundReferences_GetBoundReferences_Call { + return &BoundReferences_GetBoundReferences_Call{Call: _e.mock.On("GetBoundReferences")} +} + +func (_c *BoundReferences_GetBoundReferences_Call) Run(run func()) *BoundReferences_GetBoundReferences_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *BoundReferences_GetBoundReferences_Call) Return(_a0 []*pbresource.Reference) *BoundReferences_GetBoundReferences_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *BoundReferences_GetBoundReferences_Call) RunAndReturn(run func() []*pbresource.Reference) *BoundReferences_GetBoundReferences_Call { + _c.Call.Return(run) + return _c +} + +// ProtoReflect provides a mock function with given fields: +func (_m *BoundReferences) ProtoReflect() protoreflect.Message { + ret := _m.Called() + + var r0 protoreflect.Message + if rf, ok := ret.Get(0).(func() protoreflect.Message); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(protoreflect.Message) + } + } + + return r0 +} + +// BoundReferences_ProtoReflect_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProtoReflect' +type BoundReferences_ProtoReflect_Call struct { + *mock.Call +} + +// ProtoReflect is a helper method to define mock.On call +func (_e *BoundReferences_Expecter) ProtoReflect() *BoundReferences_ProtoReflect_Call { + return &BoundReferences_ProtoReflect_Call{Call: _e.mock.On("ProtoReflect")} +} + +func (_c *BoundReferences_ProtoReflect_Call) Run(run func()) *BoundReferences_ProtoReflect_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *BoundReferences_ProtoReflect_Call) Return(_a0 protoreflect.Message) *BoundReferences_ProtoReflect_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *BoundReferences_ProtoReflect_Call) RunAndReturn(run func() protoreflect.Message) *BoundReferences_ProtoReflect_Call { + _c.Call.Return(run) + return _c +} + +// NewBoundReferences creates a new instance of BoundReferences. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewBoundReferences(t interface { + mock.TestingT + Cleanup(func()) +}) *BoundReferences { + mock := &BoundReferences{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/indexers/indexersmock/mock_FromArgs.go b/internal/controller/cache/indexers/indexersmock/mock_FromArgs.go new file mode 100644 index 000000000000..bb74bbd61de6 --- /dev/null +++ b/internal/controller/cache/indexers/indexersmock/mock_FromArgs.go @@ -0,0 +1,95 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package indexersmock + +import mock "github.com/stretchr/testify/mock" + +// FromArgs is an autogenerated mock type for the FromArgs type +type FromArgs struct { + mock.Mock +} + +type FromArgs_Expecter struct { + mock *mock.Mock +} + +func (_m *FromArgs) EXPECT() *FromArgs_Expecter { + return &FromArgs_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: args +func (_m *FromArgs) Execute(args ...interface{}) ([]byte, error) { + var _ca []interface{} + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(...interface{}) ([]byte, error)); ok { + return rf(args...) + } + if rf, ok := ret.Get(0).(func(...interface{}) []byte); ok { + r0 = rf(args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(...interface{}) error); ok { + r1 = rf(args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FromArgs_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type FromArgs_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - args ...interface{} +func (_e *FromArgs_Expecter) Execute(args ...interface{}) *FromArgs_Execute_Call { + return &FromArgs_Execute_Call{Call: _e.mock.On("Execute", + append([]interface{}{}, args...)...)} +} + +func (_c *FromArgs_Execute_Call) Run(run func(args ...interface{})) *FromArgs_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-0) + for i, a := range args[0:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(variadicArgs...) + }) + return _c +} + +func (_c *FromArgs_Execute_Call) Return(_a0 []byte, _a1 error) *FromArgs_Execute_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FromArgs_Execute_Call) RunAndReturn(run func(...interface{}) ([]byte, error)) *FromArgs_Execute_Call { + _c.Call.Return(run) + return _c +} + +// NewFromArgs creates a new instance of FromArgs. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewFromArgs(t interface { + mock.TestingT + Cleanup(func()) +}) *FromArgs { + mock := &FromArgs{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/indexers/indexersmock/mock_GetSingleRefOrID.go b/internal/controller/cache/indexers/indexersmock/mock_GetSingleRefOrID.go new file mode 100644 index 000000000000..77ec942bf709 --- /dev/null +++ b/internal/controller/cache/indexers/indexersmock/mock_GetSingleRefOrID.go @@ -0,0 +1,80 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package indexersmock + +import ( + resource "github.com/hashicorp/consul/internal/resource" + pbresource "github.com/hashicorp/consul/proto-public/pbresource" + mock "github.com/stretchr/testify/mock" +) + +// GetSingleRefOrID is an autogenerated mock type for the GetSingleRefOrID type +type GetSingleRefOrID struct { + mock.Mock +} + +type GetSingleRefOrID_Expecter struct { + mock *mock.Mock +} + +func (_m *GetSingleRefOrID) EXPECT() *GetSingleRefOrID_Expecter { + return &GetSingleRefOrID_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: _a0 +func (_m *GetSingleRefOrID) Execute(_a0 *pbresource.Resource) resource.ReferenceOrID { + ret := _m.Called(_a0) + + var r0 resource.ReferenceOrID + if rf, ok := ret.Get(0).(func(*pbresource.Resource) resource.ReferenceOrID); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(resource.ReferenceOrID) + } + } + + return r0 +} + +// GetSingleRefOrID_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type GetSingleRefOrID_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - _a0 *pbresource.Resource +func (_e *GetSingleRefOrID_Expecter) Execute(_a0 interface{}) *GetSingleRefOrID_Execute_Call { + return &GetSingleRefOrID_Execute_Call{Call: _e.mock.On("Execute", _a0)} +} + +func (_c *GetSingleRefOrID_Execute_Call) Run(run func(_a0 *pbresource.Resource)) *GetSingleRefOrID_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*pbresource.Resource)) + }) + return _c +} + +func (_c *GetSingleRefOrID_Execute_Call) Return(_a0 resource.ReferenceOrID) *GetSingleRefOrID_Execute_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GetSingleRefOrID_Execute_Call) RunAndReturn(run func(*pbresource.Resource) resource.ReferenceOrID) *GetSingleRefOrID_Execute_Call { + _c.Call.Return(run) + return _c +} + +// NewGetSingleRefOrID creates a new instance of GetSingleRefOrID. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewGetSingleRefOrID(t interface { + mock.TestingT + Cleanup(func()) +}) *GetSingleRefOrID { + mock := &GetSingleRefOrID{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/indexers/indexersmock/mock_MultiIndexer.go b/internal/controller/cache/indexers/indexersmock/mock_MultiIndexer.go new file mode 100644 index 000000000000..080b45d28b8f --- /dev/null +++ b/internal/controller/cache/indexers/indexersmock/mock_MultiIndexer.go @@ -0,0 +1,97 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package indexersmock + +import ( + resource "github.com/hashicorp/consul/internal/resource" + mock "github.com/stretchr/testify/mock" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" +) + +// MultiIndexer is an autogenerated mock type for the MultiIndexer type +type MultiIndexer[T protoreflect.ProtoMessage] struct { + mock.Mock +} + +type MultiIndexer_Expecter[T protoreflect.ProtoMessage] struct { + mock *mock.Mock +} + +func (_m *MultiIndexer[T]) EXPECT() *MultiIndexer_Expecter[T] { + return &MultiIndexer_Expecter[T]{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: r +func (_m *MultiIndexer[T]) Execute(r *resource.DecodedResource[T]) (bool, [][]byte, error) { + ret := _m.Called(r) + + var r0 bool + var r1 [][]byte + var r2 error + if rf, ok := ret.Get(0).(func(*resource.DecodedResource[T]) (bool, [][]byte, error)); ok { + return rf(r) + } + if rf, ok := ret.Get(0).(func(*resource.DecodedResource[T]) bool); ok { + r0 = rf(r) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(*resource.DecodedResource[T]) [][]byte); ok { + r1 = rf(r) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).([][]byte) + } + } + + if rf, ok := ret.Get(2).(func(*resource.DecodedResource[T]) error); ok { + r2 = rf(r) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// MultiIndexer_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type MultiIndexer_Execute_Call[T protoreflect.ProtoMessage] struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - r *resource.DecodedResource[T] +func (_e *MultiIndexer_Expecter[T]) Execute(r interface{}) *MultiIndexer_Execute_Call[T] { + return &MultiIndexer_Execute_Call[T]{Call: _e.mock.On("Execute", r)} +} + +func (_c *MultiIndexer_Execute_Call[T]) Run(run func(r *resource.DecodedResource[T])) *MultiIndexer_Execute_Call[T] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*resource.DecodedResource[T])) + }) + return _c +} + +func (_c *MultiIndexer_Execute_Call[T]) Return(_a0 bool, _a1 [][]byte, _a2 error) *MultiIndexer_Execute_Call[T] { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *MultiIndexer_Execute_Call[T]) RunAndReturn(run func(*resource.DecodedResource[T]) (bool, [][]byte, error)) *MultiIndexer_Execute_Call[T] { + _c.Call.Return(run) + return _c +} + +// NewMultiIndexer creates a new instance of MultiIndexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMultiIndexer[T protoreflect.ProtoMessage](t interface { + mock.TestingT + Cleanup(func()) +}) *MultiIndexer[T] { + mock := &MultiIndexer[T]{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/indexers/indexersmock/mock_RefOrIDFetcher.go b/internal/controller/cache/indexers/indexersmock/mock_RefOrIDFetcher.go new file mode 100644 index 000000000000..090f89d70c06 --- /dev/null +++ b/internal/controller/cache/indexers/indexersmock/mock_RefOrIDFetcher.go @@ -0,0 +1,80 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package indexersmock + +import ( + resource "github.com/hashicorp/consul/internal/resource" + mock "github.com/stretchr/testify/mock" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" +) + +// RefOrIDFetcher is an autogenerated mock type for the RefOrIDFetcher type +type RefOrIDFetcher[T protoreflect.ProtoMessage, V resource.ReferenceOrID] struct { + mock.Mock +} + +type RefOrIDFetcher_Expecter[T protoreflect.ProtoMessage, V resource.ReferenceOrID] struct { + mock *mock.Mock +} + +func (_m *RefOrIDFetcher[T, V]) EXPECT() *RefOrIDFetcher_Expecter[T, V] { + return &RefOrIDFetcher_Expecter[T, V]{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: _a0 +func (_m *RefOrIDFetcher[T, V]) Execute(_a0 *resource.DecodedResource[T]) []V { + ret := _m.Called(_a0) + + var r0 []V + if rf, ok := ret.Get(0).(func(*resource.DecodedResource[T]) []V); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]V) + } + } + + return r0 +} + +// RefOrIDFetcher_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type RefOrIDFetcher_Execute_Call[T protoreflect.ProtoMessage, V resource.ReferenceOrID] struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - _a0 *resource.DecodedResource[T] +func (_e *RefOrIDFetcher_Expecter[T, V]) Execute(_a0 interface{}) *RefOrIDFetcher_Execute_Call[T, V] { + return &RefOrIDFetcher_Execute_Call[T, V]{Call: _e.mock.On("Execute", _a0)} +} + +func (_c *RefOrIDFetcher_Execute_Call[T, V]) Run(run func(_a0 *resource.DecodedResource[T])) *RefOrIDFetcher_Execute_Call[T, V] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*resource.DecodedResource[T])) + }) + return _c +} + +func (_c *RefOrIDFetcher_Execute_Call[T, V]) Return(_a0 []V) *RefOrIDFetcher_Execute_Call[T, V] { + _c.Call.Return(_a0) + return _c +} + +func (_c *RefOrIDFetcher_Execute_Call[T, V]) RunAndReturn(run func(*resource.DecodedResource[T]) []V) *RefOrIDFetcher_Execute_Call[T, V] { + _c.Call.Return(run) + return _c +} + +// NewRefOrIDFetcher creates a new instance of RefOrIDFetcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewRefOrIDFetcher[T protoreflect.ProtoMessage, V resource.ReferenceOrID](t interface { + mock.TestingT + Cleanup(func()) +}) *RefOrIDFetcher[T, V] { + mock := &RefOrIDFetcher[T, V]{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/indexers/indexersmock/mock_SingleIndexer.go b/internal/controller/cache/indexers/indexersmock/mock_SingleIndexer.go new file mode 100644 index 000000000000..38cdfb71c45a --- /dev/null +++ b/internal/controller/cache/indexers/indexersmock/mock_SingleIndexer.go @@ -0,0 +1,97 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package indexersmock + +import ( + resource "github.com/hashicorp/consul/internal/resource" + mock "github.com/stretchr/testify/mock" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" +) + +// SingleIndexer is an autogenerated mock type for the SingleIndexer type +type SingleIndexer[T protoreflect.ProtoMessage] struct { + mock.Mock +} + +type SingleIndexer_Expecter[T protoreflect.ProtoMessage] struct { + mock *mock.Mock +} + +func (_m *SingleIndexer[T]) EXPECT() *SingleIndexer_Expecter[T] { + return &SingleIndexer_Expecter[T]{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: r +func (_m *SingleIndexer[T]) Execute(r *resource.DecodedResource[T]) (bool, []byte, error) { + ret := _m.Called(r) + + var r0 bool + var r1 []byte + var r2 error + if rf, ok := ret.Get(0).(func(*resource.DecodedResource[T]) (bool, []byte, error)); ok { + return rf(r) + } + if rf, ok := ret.Get(0).(func(*resource.DecodedResource[T]) bool); ok { + r0 = rf(r) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(*resource.DecodedResource[T]) []byte); ok { + r1 = rf(r) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).([]byte) + } + } + + if rf, ok := ret.Get(2).(func(*resource.DecodedResource[T]) error); ok { + r2 = rf(r) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// SingleIndexer_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type SingleIndexer_Execute_Call[T protoreflect.ProtoMessage] struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - r *resource.DecodedResource[T] +func (_e *SingleIndexer_Expecter[T]) Execute(r interface{}) *SingleIndexer_Execute_Call[T] { + return &SingleIndexer_Execute_Call[T]{Call: _e.mock.On("Execute", r)} +} + +func (_c *SingleIndexer_Execute_Call[T]) Run(run func(r *resource.DecodedResource[T])) *SingleIndexer_Execute_Call[T] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*resource.DecodedResource[T])) + }) + return _c +} + +func (_c *SingleIndexer_Execute_Call[T]) Return(_a0 bool, _a1 []byte, _a2 error) *SingleIndexer_Execute_Call[T] { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *SingleIndexer_Execute_Call[T]) RunAndReturn(run func(*resource.DecodedResource[T]) (bool, []byte, error)) *SingleIndexer_Execute_Call[T] { + _c.Call.Return(run) + return _c +} + +// NewSingleIndexer creates a new instance of SingleIndexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewSingleIndexer[T protoreflect.ProtoMessage](t interface { + mock.TestingT + Cleanup(func()) +}) *SingleIndexer[T] { + mock := &SingleIndexer[T]{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/cache/indexers/ref_indexer.go b/internal/controller/cache/indexers/ref_indexer.go new file mode 100644 index 000000000000..89562582f28b --- /dev/null +++ b/internal/controller/cache/indexers/ref_indexer.go @@ -0,0 +1,37 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package indexers + +import ( + "github.com/hashicorp/consul/internal/controller/cache/index" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" + "google.golang.org/protobuf/proto" +) + +//go:generate mockery --name RefOrIDFetcher --with-expecter +type RefOrIDFetcher[T proto.Message, V resource.ReferenceOrID] func(*resource.DecodedResource[T]) []V + +func RefOrIDIndex[T proto.Message, V resource.ReferenceOrID](name string, fetch RefOrIDFetcher[T, V]) *index.Index { + return DecodedMultiIndexer[T](name, index.ReferenceOrIDFromArgs, func(r *resource.DecodedResource[T]) (bool, [][]byte, error) { + refs := fetch(r) + indexes := make([][]byte, len(refs)) + for idx, ref := range refs { + indexes[idx] = index.IndexFromRefOrID(ref) + } + + return len(indexes) > 0, indexes, nil + }) +} + +type BoundReferences interface { + GetBoundReferences() []*pbresource.Reference + proto.Message +} + +func BoundRefsIndex[T BoundReferences](name string) *index.Index { + return RefOrIDIndex[T](name, func(res *resource.DecodedResource[T]) []*pbresource.Reference { + return res.Data.GetBoundReferences() + }) +} diff --git a/internal/controller/cache/indexers/ref_indexer_test.go b/internal/controller/cache/indexers/ref_indexer_test.go new file mode 100644 index 000000000000..bf51cfc03c42 --- /dev/null +++ b/internal/controller/cache/indexers/ref_indexer_test.go @@ -0,0 +1,106 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package indexers + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/internal/controller/cache/indexers/indexersmock" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v1" + pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2" + "github.com/hashicorp/consul/proto/private/prototest" +) + +func TestRefOrIDIndex(t *testing.T) { + ref1 := &pbresource.Reference{ + Type: pbdemo.AlbumType, + Tenancy: &pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + }, + Name: "foo", + } + + ref2 := &pbresource.Reference{ + Type: pbdemo.AlbumType, + Tenancy: &pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + }, + Name: "bar", + } + + r1 := resourcetest.Resource(pbdemo.AlbumType, "foo"). + WithData(t, &pbdemo.Album{Name: "foo"}). + Build() + + dec := resourcetest.MustDecode[*pbdemo.Album](t, r1) + + refs := indexersmock.NewRefOrIDFetcher[*pbdemo.Album, *pbresource.Reference](t) + + idx := RefOrIDIndex("test", refs.Execute).IndexedData() + + refs.EXPECT().Execute(dec). + Return([]*pbresource.Reference{ref1, ref2}). + Once() + + txn := idx.Txn() + require.NoError(t, txn.Insert(r1)) + txn.Commit() + + out, err := idx.Txn().Get(ref1) + require.NoError(t, err) + prototest.AssertDeepEqual(t, r1, out) + + out, err = idx.Txn().Get(ref2) + require.NoError(t, err) + prototest.AssertDeepEqual(t, r1, out) +} + +func TestBoundRefsIndex(t *testing.T) { + ref1 := &pbresource.Reference{ + Type: pbdemov2.FestivalType, + Tenancy: &pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + }, + Name: "api", + } + + ref2 := &pbresource.Reference{ + Type: pbdemov2.FestivalType, + Tenancy: &pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + }, + Name: "api-2", + } + + r1 := resourcetest.Resource(pbdemov2.FestivalType, "api"). + WithData(t, &pbdemov2.Festival{ + BoundReferences: []*pbresource.Reference{ + ref1, + ref2, + }, + }). + Build() + + idx := BoundRefsIndex[*pbdemov2.Festival]("test").IndexedData() + + txn := idx.Txn() + require.NoError(t, txn.Insert(r1)) + txn.Commit() + + out, err := idx.Txn().Get(ref1) + require.NoError(t, err) + prototest.AssertDeepEqual(t, r1, out) + + out, err = idx.Txn().Get(ref2) + require.NoError(t, err) + prototest.AssertDeepEqual(t, r1, out) +} diff --git a/internal/controller/cache/kind.go b/internal/controller/cache/kind.go new file mode 100644 index 000000000000..1c4c4e3f1fe1 --- /dev/null +++ b/internal/controller/cache/kind.go @@ -0,0 +1,188 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cache + +import ( + "sync" + + "github.com/hashicorp/consul/internal/controller/cache/index" + "github.com/hashicorp/consul/internal/controller/cache/indexers" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +const IDIndex = "id" + +type kindIndices struct { + mu sync.RWMutex + + it unversionedType + + indices map[string]*index.IndexedData +} + +func newKindIndices() *kindIndices { + kind := &kindIndices{ + indices: make(map[string]*index.IndexedData), + } + + // add the id index + kind.indices[IDIndex] = indexers.IDIndex(IDIndex, index.IndexRequired).IndexedData() + + return kind +} + +func (k *kindIndices) addIndex(i *index.Index) error { + _, found := k.indices[i.Name()] + if found { + return DuplicateIndexError{name: i.Name()} + } + + k.indices[i.Name()] = i.IndexedData() + return nil +} + +func (k *kindIndices) get(indexName string, args ...any) (*pbresource.Resource, error) { + k.mu.RLock() + defer k.mu.RUnlock() + + idx, err := k.getIndex(indexName) + if err != nil { + return nil, err + } + + r, err := idx.Txn().Get(args...) + if err != nil { + return nil, IndexError{err: err, name: indexName} + } + return r, nil +} + +func (k *kindIndices) listIterator(indexName string, args ...any) (ResourceIterator, error) { + k.mu.RLock() + defer k.mu.RUnlock() + + idx, err := k.getIndex(indexName) + if err != nil { + return nil, err + } + + iter, err := idx.Txn().ListIterator(args...) + if err != nil { + return nil, IndexError{err: err, name: indexName} + } + return iter, nil +} + +func (k *kindIndices) parentsIterator(indexName string, args ...any) (ResourceIterator, error) { + k.mu.RLock() + defer k.mu.RUnlock() + idx, err := k.getIndex(indexName) + if err != nil { + return nil, err + } + + iter, err := idx.Txn().ParentsIterator(args...) + if err != nil { + return nil, IndexError{err: err, name: indexName} + } + return iter, nil +} + +func (k *kindIndices) insert(r *pbresource.Resource) error { + k.mu.Lock() + defer k.mu.Unlock() + + idx, err := k.getIndex(IDIndex) + if err != nil { + return err + } + + existing, err := idx.Txn().Get(r.Id) + if err != nil { + return err + } + + commit := false + for name, idx := range k.indices { + txn := idx.Txn() + + // Delete the previous version of the resource from the index. + if existing != nil { + if err := txn.Delete(existing); err != nil { + return IndexError{name: name, err: err} + } + } + + // Now insert the new version into the index. + err := txn.Insert(r) + if err != nil { + return IndexError{name: name, err: err} + } + // commit all radix trees once we know all index applies were successful. This is + // still while holding the big write lock for this resource type so the order that + // the radix tree updates occur shouldn't matter. + defer func() { + if commit { + txn.Commit() + } + }() + } + + // set commit to true so that the deferred funcs will commit all the radix tree transactions + commit = true + + return nil +} + +func (k *kindIndices) delete(r *pbresource.Resource) error { + k.mu.Lock() + defer k.mu.Unlock() + + idx, err := k.getIndex(IDIndex) + if err != nil { + return err + } + + idTxn := idx.Txn() + + existing, err := idTxn.Get(r.Id) + if err != nil { + return err + } + if existing == nil { + return nil + } + + commit := false + for name, idx := range k.indices { + txn := idx.Txn() + + if err := txn.Delete(existing); err != nil { + return IndexError{name: name, err: err} + } + + // commit all radix trees once we know all index applies were successful. This is + // still while holding the big write lock for this resource type so the order that + // the radix tree updates occur shouldn't matter. + defer func() { + if commit { + txn.Commit() + } + }() + } + + // set commit to true so that the deferred txn commits will get executed + commit = true + + return nil +} + +func (k *kindIndices) getIndex(name string) (*index.IndexedData, error) { + idx, ok := k.indices[name] + if !ok { + return nil, CacheTypeError{err: IndexNotFoundError{name: name}, it: k.it} + } + + return idx, nil +} diff --git a/internal/controller/cache/kind_test.go b/internal/controller/cache/kind_test.go new file mode 100644 index 000000000000..60ad60ebb1ed --- /dev/null +++ b/internal/controller/cache/kind_test.go @@ -0,0 +1,202 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cache + +import ( + "errors" + "testing" + + "github.com/hashicorp/consul/internal/controller/cache/index" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v1" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +var injectedError = errors.New("test-error") + +type argsErrorIndexer struct{} + +func (i argsErrorIndexer) FromArgs(args ...any) ([]byte, error) { + return nil, injectedError +} + +func (i argsErrorIndexer) FromResource(r *pbresource.Resource) (bool, []byte, error) { + return true, index.IndexFromRefOrID(r.GetId()), nil +} + +type resourceErrorIndexer struct{} + +func (i resourceErrorIndexer) FromArgs(args ...any) ([]byte, error) { + return index.ReferenceOrIDFromArgs(args...) +} + +func (i resourceErrorIndexer) FromResource(r *pbresource.Resource) (bool, []byte, error) { + return false, nil, injectedError +} + +func TestKindIndices(t *testing.T) { + suite.Run(t, &kindSuite{}) +} + +type kindSuite struct { + suite.Suite + k *kindIndices + + album1 *pbresource.Resource + album2 *pbresource.Resource + album3 *pbresource.Resource + album4 *pbresource.Resource +} + +func (suite *kindSuite) SetupTest() { + suite.k = newKindIndices() + + require.NoError(suite.T(), suite.k.addIndex(namePrefixIndexer())) + require.NoError(suite.T(), suite.k.addIndex(releaseYearIndexer())) + require.NoError(suite.T(), suite.k.addIndex(tracksIndexer())) + + suite.album1 = resourcetest.Resource(pbdemo.AlbumType, "one"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(suite.T(), &pbdemo.Album{ + Name: "one", + YearOfRelease: 2023, + Tracks: []string{"foo", "bar", "baz"}, + }). + Build() + + suite.album2 = resourcetest.Resource(pbdemo.AlbumType, "two"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(suite.T(), &pbdemo.Album{ + Name: "two", + YearOfRelease: 2023, + Tracks: []string{"fangorn", "zoo"}, + }). + Build() + + suite.album3 = resourcetest.Resource(pbdemo.AlbumType, "third"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(suite.T(), &pbdemo.Album{ + Name: "foo", + YearOfRelease: 2022, + Tracks: []string{"blah", "something", "else"}, + }). + Build() + + suite.album4 = resourcetest.Resource(pbdemo.AlbumType, "four"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(suite.T(), &pbdemo.Album{ + Name: "food", + YearOfRelease: 2020, + Tracks: []string{"nothing", "food"}, + }). + Build() + + require.NoError(suite.T(), suite.k.insert(suite.album1)) + require.NoError(suite.T(), suite.k.insert(suite.album2)) + require.NoError(suite.T(), suite.k.insert(suite.album3)) + require.NoError(suite.T(), suite.k.insert(suite.album4)) +} + +func (suite *kindSuite) TestGet() { + res, err := suite.k.get("id", suite.album1.Id) + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.album1, res) + + res, err = suite.k.get("year", int32(2022)) + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.album3, res) + + res, err = suite.k.get("tracks", "fangorn") + require.NoError(suite.T(), err) + prototest.AssertDeepEqual(suite.T(), suite.album2, res) +} + +func (suite *kindSuite) TestGet_IndexNotFound() { + res, err := suite.k.get("blah", suite.album1.Id) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, IndexNotFoundError{name: "blah"}) + require.Nil(suite.T(), res) +} + +func (suite *kindSuite) TestList() { + resources, err := expandIterator(suite.k.listIterator("year", int32(2023))) + require.NoError(suite.T(), err) + prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album1, suite.album2}, resources) + + resources, err = expandIterator(suite.k.listIterator("tracks", "f", true)) + require.NoError(suite.T(), err) + prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album1, suite.album2, suite.album4}, resources) +} + +func (suite *kindSuite) TestList_IndexNotFound() { + res, err := expandIterator(suite.k.listIterator("blah", suite.album1.Id)) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, IndexNotFoundError{name: "blah"}) + require.Nil(suite.T(), res) +} + +func (suite *kindSuite) TestParents() { + resources, err := expandIterator(suite.k.parentsIterator("name_prefix", "food")) + require.NoError(suite.T(), err) + prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album3, suite.album4}, resources) +} + +func (suite *kindSuite) TestParents_IndexNotFound() { + res, err := expandIterator(suite.k.parentsIterator("blah", suite.album1.Id)) + require.Error(suite.T(), err) + require.ErrorIs(suite.T(), err, IndexNotFoundError{name: "blah"}) + require.Nil(suite.T(), res) +} +func (suite *kindSuite) TestDelete() { + err := suite.k.delete(suite.album1) + require.NoError(suite.T(), err) + + res, err := suite.k.get("id", suite.album1.Id) + require.NoError(suite.T(), err) + require.Nil(suite.T(), res) + + resources, err := expandIterator(suite.k.listIterator("year", int32(2023))) + require.NoError(suite.T(), err) + prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album2}, resources) + + resources, err = expandIterator(suite.k.parentsIterator("name_prefix", "onesie")) + require.NoError(suite.T(), err) + require.Nil(suite.T(), resources) +} + +func (suite *kindSuite) TestInsertIndexError() { + err := suite.k.insert( + resourcetest.Resource(pbdemo.ConceptType, "foo"). + WithTenancy(resource.DefaultNamespacedTenancy()). + WithData(suite.T(), &pbdemo.Concept{}). + Build()) + + require.Error(suite.T(), err) + require.ErrorAs(suite.T(), err, &IndexError{}) +} + +func (suite *kindSuite) TestGetIndexError() { + val, err := suite.k.get("year", "blah") + require.Error(suite.T(), err) + require.ErrorAs(suite.T(), err, &IndexError{}) + require.Nil(suite.T(), val) +} + +func (suite *kindSuite) TestListIteratorIndexError() { + vals, err := suite.k.listIterator("year", "blah") + require.Error(suite.T(), err) + require.ErrorAs(suite.T(), err, &IndexError{}) + require.Nil(suite.T(), vals) +} + +func (suite *kindSuite) TestParentsIteratorIndexError() { + vals, err := suite.k.parentsIterator("year", "blah") + require.Error(suite.T(), err) + require.ErrorAs(suite.T(), err, &IndexError{}) + require.Nil(suite.T(), vals) +} diff --git a/internal/controller/cache/testdata/CacheTypeError.golden b/internal/controller/cache/testdata/CacheTypeError.golden new file mode 100644 index 000000000000..92f325380720 --- /dev/null +++ b/internal/controller/cache/testdata/CacheTypeError.golden @@ -0,0 +1 @@ +operation on resource type something.else failed: fake test error \ No newline at end of file diff --git a/internal/controller/cache/testdata/DuplicateIndexError.golden b/internal/controller/cache/testdata/DuplicateIndexError.golden new file mode 100644 index 000000000000..38201281042d --- /dev/null +++ b/internal/controller/cache/testdata/DuplicateIndexError.golden @@ -0,0 +1 @@ +Index with name "addresses" is already defined. \ No newline at end of file diff --git a/internal/controller/cache/testdata/DuplicateQueryError.golden b/internal/controller/cache/testdata/DuplicateQueryError.golden new file mode 100644 index 000000000000..2a7393c1733e --- /dev/null +++ b/internal/controller/cache/testdata/DuplicateQueryError.golden @@ -0,0 +1 @@ +Query with name "addresses" is already defined. \ No newline at end of file diff --git a/internal/controller/cache/testdata/IndexError.golden b/internal/controller/cache/testdata/IndexError.golden new file mode 100644 index 000000000000..8f52e92f2f6a --- /dev/null +++ b/internal/controller/cache/testdata/IndexError.golden @@ -0,0 +1 @@ +operation on index "foo" failed: fake test error \ No newline at end of file diff --git a/internal/controller/cache/testdata/IndexNotFound.golden b/internal/controller/cache/testdata/IndexNotFound.golden new file mode 100644 index 000000000000..9f5e62f48db7 --- /dev/null +++ b/internal/controller/cache/testdata/IndexNotFound.golden @@ -0,0 +1 @@ +No index with name "fake" exists \ No newline at end of file diff --git a/internal/controller/cache/testdata/QueryNotFound.golden b/internal/controller/cache/testdata/QueryNotFound.golden new file mode 100644 index 000000000000..ede6b89e5d5d --- /dev/null +++ b/internal/controller/cache/testdata/QueryNotFound.golden @@ -0,0 +1 @@ +No query with name "fake" exists \ No newline at end of file diff --git a/internal/controller/cache/testdata/QueryRequired.golden b/internal/controller/cache/testdata/QueryRequired.golden new file mode 100644 index 000000000000..41aeda42d11c --- /dev/null +++ b/internal/controller/cache/testdata/QueryRequired.golden @@ -0,0 +1 @@ +A non-nil query function was not specified \ No newline at end of file diff --git a/internal/controller/controller.go b/internal/controller/controller.go index 97955db6a3c1..286459e97b78 100644 --- a/internal/controller/controller.go +++ b/internal/controller/controller.go @@ -5,244 +5,357 @@ package controller import ( "context" - "errors" "fmt" + "strings" "time" "github.com/hashicorp/go-hclog" - "golang.org/x/sync/errgroup" - "github.com/hashicorp/consul/agent/consul/controller/queue" + "github.com/hashicorp/consul/internal/controller/cache" + "github.com/hashicorp/consul/internal/controller/cache/index" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" ) -// controllerRunner contains the actual implementation of running a controller -// including creating watches, calling the reconciler, handling retries, etc. -type controllerRunner struct { - ctrl Controller - client pbresource.ResourceServiceClient - logger hclog.Logger -} - -func (c *controllerRunner) run(ctx context.Context) error { - c.logger.Debug("controller running") - defer c.logger.Debug("controller stopping") - - group, groupCtx := errgroup.WithContext(ctx) - recQueue := runQueue[Request](groupCtx, c.ctrl) - - // Managed Type Events → Reconciliation Queue - group.Go(func() error { - return c.watch(groupCtx, c.ctrl.managedType, func(res *pbresource.Resource) { - recQueue.Add(Request{ID: res.Id}) - }) - }) - - for _, w := range c.ctrl.watches { - mapQueue := runQueue[mapperRequest](groupCtx, c.ctrl) - watcher := w - // Watched Type Events → Mapper Queue - group.Go(func() error { - return c.watch(groupCtx, watcher.watchedType, func(res *pbresource.Resource) { - mapQueue.Add(mapperRequest{res: res}) - }) - }) - - // Mapper Queue → Mapper → Reconciliation Queue - group.Go(func() error { - return c.runMapper(groupCtx, watcher, mapQueue, recQueue, func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error) { - return watcher.mapper(ctx, runtime, itemType.(mapperRequest).res) - }) - }) - } - - for _, cw := range c.ctrl.customWatches { - customMapQueue := runQueue[Event](groupCtx, c.ctrl) - watcher := cw - // Custom Events → Mapper Queue - group.Go(func() error { - return watcher.source.Watch(groupCtx, func(e Event) { - customMapQueue.Add(e) - }) - }) - - // Mapper Queue → Mapper → Reconciliation Queue - group.Go(func() error { - return c.runCustomMapper(groupCtx, watcher, customMapQueue, recQueue, func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error) { - return watcher.mapper(ctx, runtime, itemType.(Event)) - }) - }) - } - - // Reconciliation Queue → Reconciler - group.Go(func() error { - return c.runReconciler(groupCtx, recQueue) - }) - - return group.Wait() -} - -func runQueue[T queue.ItemType](ctx context.Context, ctrl Controller) queue.WorkQueue[T] { - base, max := ctrl.backoff() - return queue.RunWorkQueue[T](ctx, base, max) -} - -func (c *controllerRunner) watch(ctx context.Context, typ *pbresource.Type, add func(*pbresource.Resource)) error { - wl, err := c.client.WatchList(ctx, &pbresource.WatchListRequest{ - Type: typ, - }) - if err != nil { - c.logger.Error("failed to create watch", "error", err) - return err - } - - for { - event, err := wl.Recv() - if err != nil { - c.logger.Warn("error received from watch", "error", err) - return err - } - add(event.Resource) +// DependencyMapper is called when a dependency watched via WithWatch is changed +// to determine which of the controller's managed resources need to be reconciled. +type DependencyMapper func( + ctx context.Context, + rt Runtime, + res *pbresource.Resource, +) ([]Request, error) + +// Controller runs a reconciliation loop to respond to changes in resources and +// their dependencies. It is heavily inspired by Kubernetes' controller pattern: +// https://kubernetes.io/docs/concepts/architecture/controller/ +// +// Use the builder methods in this package (starting with NewController) to construct +// a controller, and then pass it to a Manager to be executed. +type Controller struct { + name string + reconciler Reconciler + initializer Initializer + managedTypeWatch *watch + watches map[string]*watch + queries map[string]cache.Query + customWatches []customWatch + placement Placement + baseBackoff time.Duration + maxBackoff time.Duration + logger hclog.Logger + startCb RuntimeCallback + stopCb RuntimeCallback + // forceReconcileEvery is the time to wait after a successful reconciliation + // before forcing a reconciliation. The net result is a reconciliation of + // the managed type on a regular interval. This ensures that the state of the + // world is continually reconciled, hence correct in the face of missed events + // or other issues. + forceReconcileEvery time.Duration +} + +type RuntimeCallback func(context.Context, Runtime) + +// NewController creates a controller that is setup to watched the managed type. +// Extra cache indexes may be provided as well and these indexes will be automatically managed. +// Typically, further calls to other builder methods will be needed to fully configure +// the controller such as using WithReconcile to define the code that will be called +// when the managed resource needs reconciliation. +func NewController(name string, managedType *pbresource.Type, indexes ...*index.Index) *Controller { + w := &watch{ + watchedType: managedType, + indexes: make(map[string]*index.Index), + } + + for _, idx := range indexes { + w.addIndex(idx) + } + + return &Controller{ + name: name, + managedTypeWatch: w, + watches: make(map[string]*watch), + queries: make(map[string]cache.Query), + forceReconcileEvery: 8 * time.Hour, } } -func (c *controllerRunner) runMapper( - ctx context.Context, - w watch, - from queue.WorkQueue[mapperRequest], - to queue.WorkQueue[Request], - mapper func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error), -) error { - logger := c.logger.With("watched_resource_type", resource.ToGVK(w.watchedType)) - - for { - item, shutdown := from.Get() - if shutdown { - return nil - } +// WithNotifyStart registers a callback to be run when the controller is being started. +// This happens prior to watches being started and with a fresh cache. +func (ctl *Controller) WithNotifyStart(start RuntimeCallback) *Controller { + ctl.startCb = start + return ctl +} - if err := c.doMap(ctx, mapper, to, item, logger); err != nil { - from.AddRateLimited(item) - from.Done(item) - continue - } +// WithNotifyStop registers a callback to be run when the controller has been stopped. +// This happens after all the watches and mapper/reconcile queues have been stopped. The +// cache will contain everything that was present when we started stopping watches. +func (ctl *Controller) WithNotifyStop(stop RuntimeCallback) *Controller { + ctl.stopCb = stop + return ctl +} - from.Forget(item) - from.Done(item) +// WithReconciler changes the controller's reconciler. +func (ctl *Controller) WithReconciler(reconciler Reconciler) *Controller { + if reconciler == nil { + panic("reconciler must not be nil") } + + ctl.reconciler = reconciler + return ctl } -func (c *controllerRunner) runCustomMapper( - ctx context.Context, - cw customWatch, - from queue.WorkQueue[Event], - to queue.WorkQueue[Request], - mapper func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error), -) error { - logger := c.logger.With("watched_event", cw.source) - - for { - item, shutdown := from.Get() - if shutdown { - return nil - } +// WithWatch enables watching of the specified resource type and mapping it to the managed type +// via the provided DependencyMapper. Extra cache indexes to calculate on the watched type +// may also be provided. +func (ctl *Controller) WithWatch(watchedType *pbresource.Type, mapper DependencyMapper, indexes ...*index.Index) *Controller { + key := resource.ToGVK(watchedType) - if err := c.doMap(ctx, mapper, to, item, logger); err != nil { - from.AddRateLimited(item) - from.Done(item) - continue - } + _, alreadyWatched := ctl.watches[key] + if alreadyWatched { + panic(fmt.Sprintf("resource type %q already has a configured watch", key)) + } - from.Forget(item) - from.Done(item) + w := newWatch(watchedType, mapper) + + for _, idx := range indexes { + w.addIndex(idx) } + + ctl.watches[key] = w + + return ctl } -func (c *controllerRunner) doMap(ctx context.Context, mapper func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error), to queue.WorkQueue[Request], item queue.ItemType, logger hclog.Logger) error { - var reqs []Request - if err := c.handlePanic(func() error { - var err error - reqs, err = mapper(ctx, c.runtime(), item) - return err - }); err != nil { - return err +// WithQuery will add a named query to the controllers cache for usage during reconcile or in dependency mappers +func (ctl *Controller) WithQuery(queryName string, fn cache.Query) *Controller { + _, duplicate := ctl.queries[queryName] + if duplicate { + panic(fmt.Sprintf("a predefined cache query with name %q already exists", queryName)) } - for _, r := range reqs { - if !resource.EqualType(r.ID.Type, c.ctrl.managedType) { - logger.Error("dependency mapper returned request for a resource of the wrong type", - "type_expected", resource.ToGVK(c.ctrl.managedType), - "type_got", resource.ToGVK(r.ID.Type), - ) - continue - } - to.Add(r) + ctl.queries[queryName] = fn + return ctl +} + +// WithCustomWatch adds a new custom watch. Custom watches do not affect the controller cache. +func (ctl *Controller) WithCustomWatch(source *Source, mapper CustomDependencyMapper) *Controller { + if source == nil { + panic("source must not be nil") + } + + if mapper == nil { + panic("mapper must not be nil") } - return nil + + ctl.customWatches = append(ctl.customWatches, customWatch{source, mapper}) + return ctl } -func (c *controllerRunner) runReconciler(ctx context.Context, queue queue.WorkQueue[Request]) error { - for { - req, shutdown := queue.Get() - if shutdown { - return nil - } +// WithLogger changes the controller's logger. +func (ctl *Controller) WithLogger(logger hclog.Logger) *Controller { + if logger == nil { + panic("logger must not be nil") + } - c.logger.Trace("handling request", "request", req) - err := c.handlePanic(func() error { - return c.ctrl.reconciler.Reconcile(ctx, c.runtime(), req) - }) - if err == nil { - queue.Forget(req) - } else { - var requeueAfter RequeueAfterError - if errors.As(err, &requeueAfter) { - queue.Forget(req) - queue.AddAfter(req, time.Duration(requeueAfter)) - } else { - queue.AddRateLimited(req) - } + ctl.logger = logger + return ctl +} + +// WithBackoff changes the base and maximum backoff values for the controller's +// retry rate limiter. +func (ctl *Controller) WithBackoff(base, max time.Duration) *Controller { + ctl.baseBackoff = base + ctl.maxBackoff = max + return ctl +} + +// WithPlacement changes where and how many replicas of the controller will run. +// In the majority of cases, the default placement (one leader elected instance +// per cluster) is the most appropriate and you shouldn't need to override it. +func (ctl *Controller) WithPlacement(placement Placement) *Controller { + ctl.placement = placement + return ctl +} + +// WithForceReconcileEvery controls how often a resource gets periodically reconciled +// to ensure that the state of the world is correct (8 hours is the default). +// This exists for tests only and should not be customized by controller authors! +func (ctl *Controller) WithForceReconcileEvery(duration time.Duration) *Controller { + ctl.logger.Warn("WithForceReconcileEvery is for testing only and should not be set by controllers") + ctl.forceReconcileEvery = duration + return ctl +} + +// buildCache will construct a controller Cache given the watches/indexes that have +// been added to the controller. This is mainly to be used by the TestController and +// Manager when setting up how things +func (ctl *Controller) buildCache() cache.Cache { + c := cache.New() + + addWatchToCache(c, ctl.managedTypeWatch) + for _, w := range ctl.watches { + addWatchToCache(c, w) + } + + for name, query := range ctl.queries { + if err := c.AddQuery(name, query); err != nil { + panic(err) } - queue.Done(req) } + + return c } -func (c *controllerRunner) handlePanic(fn func() error) (err error) { - defer func() { - if r := recover(); r != nil { - stack := hclog.Stacktrace() - c.logger.Error("controller panic", - "panic", r, - "stack", stack, - ) - err = fmt.Errorf("panic [recovered]: %v", r) - return +// dryRunMapper will trigger the appropriate DependencyMapper for an update of +// the provided type and return the requested reconciles. +// +// This is mainly to be used by the TestController. +func (ctl *Controller) dryRunMapper( + ctx context.Context, + rt Runtime, + res *pbresource.Resource, +) ([]Request, error) { + if resource.EqualType(ctl.managedTypeWatch.watchedType, res.Id.Type) { + return nil, nil // no-op + } + + for _, w := range ctl.watches { + if resource.EqualType(w.watchedType, res.Id.Type) { + return w.mapper(ctx, rt, res) } - }() + } + return nil, fmt.Errorf("no mapper for type: %s", resource.TypeToString(res.Id.Type)) +} + +// String returns a textual description of the controller, useful for debugging. +func (ctl *Controller) String() string { + watchedTypes := make([]string, 0, len(ctl.watches)) + for watchedType := range ctl.watches { + watchedTypes = append(watchedTypes, watchedType) + } + base, max := ctl.backoff() + return fmt.Sprintf( + ", placement=%s>", + resource.ToGVK(ctl.managedTypeWatch.watchedType), + strings.Join(watchedTypes, ", "), + base, max, + ctl.placement, + ) +} + +func (ctl *Controller) backoff() (time.Duration, time.Duration) { + base := ctl.baseBackoff + if base == 0 { + base = 5 * time.Millisecond + } + max := ctl.maxBackoff + if max == 0 { + max = 1000 * time.Second + } + return base, max +} + +func (ctl *Controller) buildLogger(defaultLogger hclog.Logger) hclog.Logger { + logger := defaultLogger + if ctl.logger != nil { + logger = ctl.logger + } + + return logger.With("controller", ctl.name, "managed_type", resource.ToGVK(ctl.managedTypeWatch.watchedType)) +} - return fn() +func addWatchToCache(c cache.Cache, w *watch) { + c.AddType(w.watchedType) + for _, index := range w.indexes { + if err := c.AddIndex(w.watchedType, index); err != nil { + panic(err) + } + } } -func (c *controllerRunner) runtime() Runtime { - return Runtime{ - Client: c.client, - Logger: c.logger, +// Placement determines where and how many replicas of the controller will run. +type Placement int + +const ( + // PlacementSingleton ensures there is a single, leader-elected, instance of + // the controller running in the cluster at any time. It's the default and is + // suitable for most use-cases. + PlacementSingleton Placement = iota + + // PlacementEachServer ensures there is a replica of the controller running on + // each server in the cluster. It is useful for cases where the controller is + // responsible for applying some configuration resource to the server whenever + // it changes (e.g. rate-limit configuration). Generally, controllers in this + // placement mode should not modify resources. + PlacementEachServer +) + +// String satisfies the fmt.Stringer interface. +func (p Placement) String() string { + switch p { + case PlacementSingleton: + return "singleton" + case PlacementEachServer: + return "each-server" } + panic(fmt.Sprintf("unknown placement %d", p)) } -type mapperRequest struct{ res *pbresource.Resource } +// Reconciler implements the business logic of a controller. +type Reconciler interface { + // Reconcile the resource identified by req.ID. + Reconcile(ctx context.Context, rt Runtime, req Request) error +} + +// RequeueAfterError is an error that allows a Reconciler to override the +// exponential backoff behavior of the Controller, rather than applying +// the backoff algorithm, returning a RequeueAfterError will cause the +// Controller to reschedule the Request at a given time in the future. +type RequeueAfterError time.Duration + +// Error implements the error interface. +func (r RequeueAfterError) Error() string { + return fmt.Sprintf("requeue at %s", time.Duration(r)) +} + +// RequeueAfter constructs a RequeueAfterError with the given duration +// setting. +func RequeueAfter(after time.Duration) error { + return RequeueAfterError(after) +} + +// RequeueNow constructs a RequeueAfterError that reschedules the Request +// immediately. +func RequeueNow() error { + return RequeueAfterError(0) +} + +// Request represents a request to reconcile the resource with the given ID. +type Request struct { + // ID of the resource that needs to be reconciled. + ID *pbresource.ID +} // Key satisfies the queue.ItemType interface. It returns a string which will be // used to de-duplicate requests in the queue. -func (i mapperRequest) Key() string { +func (r Request) Key() string { return fmt.Sprintf( - "type=%q,part=%q,peer=%q,ns=%q,name=%q,uid=%q", - resource.ToGVK(i.res.Id.Type), - i.res.Id.Tenancy.Partition, - i.res.Id.Tenancy.PeerName, - i.res.Id.Tenancy.Namespace, - i.res.Id.Name, - i.res.Id.Uid, + "part=%q,ns=%q,name=%q,uid=%q", + r.ID.Tenancy.Partition, + r.ID.Tenancy.Namespace, + r.ID.Name, + r.ID.Uid, ) } + +// Initializer implements the business logic that is executed when the +// controller is first started. +type Initializer interface { + Initialize(ctx context.Context, rt Runtime) error +} + +// WithInitializer changes the controller's initializer. +func (c *Controller) WithInitializer(initializer Initializer) *Controller { + c.initializer = initializer + return c +} diff --git a/internal/controller/controller_test.go b/internal/controller/controller_test.go new file mode 100644 index 000000000000..db1c49b505b8 --- /dev/null +++ b/internal/controller/controller_test.go @@ -0,0 +1,740 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package controller_test + +import ( + "context" + "errors" + "fmt" + "sync/atomic" + "testing" + "time" + + "github.com/stretchr/testify/require" + + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" + controller "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/controller/cache" + "github.com/hashicorp/consul/internal/controller/cache/index" + "github.com/hashicorp/consul/internal/controller/cache/indexers" + "github.com/hashicorp/consul/internal/controller/dependency" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/demo" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + pbdemov1 "github.com/hashicorp/consul/proto/private/pbdemo/v1" + pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/consul/sdk/testutil/retry" +) + +var injectedError = errors.New("injected error") + +func errQuery(_ cache.ReadOnlyCache, _ ...any) (cache.ResourceIterator, error) { + return nil, injectedError +} + +func TestController_API(t *testing.T) { + t.Parallel() + + idx := indexers.DecodedSingleIndexer("genre", index.SingleValueFromArgs(func(value string) ([]byte, error) { + var b index.Builder + b.String(value) + return b.Bytes(), nil + }), func(res *resource.DecodedResource[*pbdemov2.Artist]) (bool, []byte, error) { + var b index.Builder + b.String(res.Data.Genre.String()) + return true, b.Bytes(), nil + }) + + rec := newTestReconciler() + init := newTestInitializer(1) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + concertsChan := make(chan controller.Event) + defer close(concertsChan) + concertSource := &controller.Source{Source: concertsChan} + concertMapper := func(ctx context.Context, rt controller.Runtime, event controller.Event) ([]controller.Request, error) { + artistID := event.Obj.(*Concert).artistID + var requests []controller.Request + requests = append(requests, controller.Request{ID: artistID}) + return requests, nil + } + + ctrl := controller. + NewController("artist", pbdemov2.ArtistType, idx). + WithWatch(pbdemov2.AlbumType, dependency.MapOwner, indexers.OwnerIndex("owner")). + WithQuery("some-query", errQuery). + WithCustomWatch(concertSource, concertMapper). + WithBackoff(10*time.Millisecond, 100*time.Millisecond). + WithReconciler(rec). + WithInitializer(init) + + mgr := controller.NewManager(client, testutil.Logger(t)) + mgr.Register(ctrl) + mgr.SetRaftLeader(true) + go mgr.Run(testContext(t)) + + // Wait for initialization to complete + init.wait(t) + + t.Run("managed resource type", func(t *testing.T) { + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + rt, req := rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + + // ensure that the cache index is being properly managed + dec := resourcetest.MustDecode[*pbdemov2.Artist](t, res) + resources, err := rt.Cache.List(pbdemov2.ArtistType, "genre", dec.Data.Genre.String()) + require.NoError(t, err) + prototest.AssertElementsMatch(t, []*pbresource.Resource{rsp.Resource}, resources) + + // ensure that the query was successfully registered - as we should not do equality + // checks on functions we are using a constant error return query to ensure it was + // registered properly. + iter, err := rt.Cache.Query("some-query", "irrelevant") + require.ErrorIs(t, err, injectedError) + require.Nil(t, iter) + }) + + t.Run("watched resource type", func(t *testing.T) { + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + _, req := rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + + rec.expectNoRequest(t, 500*time.Millisecond) + + album, err := demo.GenerateV2Album(rsp.Resource.Id) + require.NoError(t, err) + + albumRsp1, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: album}) + require.NoError(t, err) + + _, req = rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + + album2, err := demo.GenerateV2Album(rsp.Resource.Id) + require.NoError(t, err) + + albumRsp2, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: album2}) + require.NoError(t, err) + + rt, req := rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + + // ensure that the watched type cache is being updated + resources, err := rt.Cache.List(pbdemov2.AlbumType, "owner", rsp.Resource.Id) + require.NoError(t, err) + prototest.AssertElementsMatch(t, []*pbresource.Resource{albumRsp1.Resource, albumRsp2.Resource}, resources) + }) + + t.Run("custom watched resource type", func(t *testing.T) { + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + _, req := rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + + rec.expectNoRequest(t, 500*time.Millisecond) + + concertsChan <- controller.Event{Obj: &Concert{name: "test-concert", artistID: rsp.Resource.Id}} + + _, watchedReq := rec.wait(t) + prototest.AssertDeepEqual(t, req.ID, watchedReq.ID) + + otherArtist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + concertsChan <- controller.Event{Obj: &Concert{name: "test-concert", artistID: otherArtist.Id}} + + _, watchedReq = rec.wait(t) + prototest.AssertDeepEqual(t, otherArtist.Id, watchedReq.ID) + }) + + t.Run("error retries", func(t *testing.T) { + rec.failNext(errors.New("KABOOM")) + + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + _, req := rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + + // Reconciler should be called with the same request again. + _, req = rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + }) + + t.Run("panic retries", func(t *testing.T) { + rec.panicNext("KABOOM") + + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + _, req := rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + + // Reconciler should be called with the same request again. + _, req = rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + }) + + t.Run("defer", func(t *testing.T) { + rec.failNext(controller.RequeueAfter(1 * time.Second)) + + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + _, req := rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + + rec.expectNoRequest(t, 750*time.Millisecond) + + _, req = rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + }) +} + +func TestController_API_InitializeRetry(t *testing.T) { + t.Parallel() + + // Configure initializer to error initially in order to test retries + expectedInitAttempts := 2 + init := newTestInitializer(expectedInitAttempts) + + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + rec := newTestReconciler() + + ctrl := controller. + NewController("artist", pbdemov2.ArtistType). + WithBackoff(10*time.Millisecond, 100*time.Millisecond). + WithReconciler(rec). + WithInitializer(init) + + mgr := controller.NewManager(client, testutil.Logger(t)) + mgr.Register(ctrl) + mgr.SetRaftLeader(true) + go mgr.Run(testContext(t)) + + // Wait for initialization attempts to complete + for i := 0; i < expectedInitAttempts; i++ { + init.wait(t) + } + + // Create a resource and expect it to reconcile now that initialization is complete + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + rec.wait(t) +} + +func waitForAtomicBoolValue(t testutil.TestingTB, actual *atomic.Bool, expected bool) { + t.Helper() + retry.Run(t, func(r *retry.R) { + require.Equal(r, expected, actual.Load()) + }) +} + +func TestController_WithForceReconcileEvery_UpsertSuccess(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + t.Parallel() + + // Given a controller + // When the controller reconciles a resource due to an upsert and succeeds + // Then the controller manager should scheduled a forced reconcile after forceReconcileEvery + rec := newTestReconciler() + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + // Create sizeable gap between reconcile #1 and forced reconcile #2 to ensure the delay occurs + forceReconcileEvery := 5 * time.Second + ctrl := controller. + NewController("artist", pbdemov2.ArtistType). + WithLogger(testutil.Logger(t)). + WithForceReconcileEvery(forceReconcileEvery). + WithReconciler(rec) + + mgr := controller.NewManager(client, testutil.Logger(t)) + mgr.Register(ctrl) + mgr.SetRaftLeader(true) + go mgr.Run(testContext(t)) + + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + // Verify reconcile #1 happens immediately + _, req := rec.waitFor(t, time.Second) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + + // Verify no reconciles occur between reconcile #1 and forced reconcile #2. + // Remove a second for max jitter (20% of 5s) and one more second to be safe. + rec.expectNoRequest(t, forceReconcileEvery-time.Second-time.Second) + + // Verify forced reconcile #2 occurred (forceReconcileEvery - 1s - 1s + 3s > forceReconcileEvery) + _, req = rec.waitFor(t, time.Second*3) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) +} + +func TestController_WithForceReconcileEvery_SkipOnReconcileError(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + t.Parallel() + + // Given a controller configured with a forceReconcileEvery duration + // When the controller reconciles a resource due to an upsert and returns an error + // Then the controller manager should not schedule a forced reconcile and allow + // the existing error handling to schedule a rate-limited retry + rec := newTestReconciler() + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + // Large enough gap to test for a period of no-reconciles + forceReconcileEvery := 5 * time.Second + ctrl := controller. + NewController("artist", pbdemov2.ArtistType). + WithLogger(testutil.Logger(t)). + WithForceReconcileEvery(forceReconcileEvery). + WithReconciler(rec) + + mgr := controller.NewManager(client, testutil.Logger(t)) + mgr.Register(ctrl) + mgr.SetRaftLeader(true) + go mgr.Run(testContext(t)) + + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + // Setup reconcile #1 to fail + rec.failNext(errors.New("reconcile #1 error")) + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + // Observe failed reconcile #1 + _, req := rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + + // Observe successful (rate-limited retry) reconcile #2. By not failNext'ing it, + // we're expecting it now'ish. + _, req = rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + + // Observe no forced reconcile for gap after last successful reconcile + // -1s for 20% jitter reduction + // -1s for just to be safe + rec.expectNoRequest(t, forceReconcileEvery-time.Second-time.Second) + + // Finally observe forced reconcile #3 up to 1 sec past (5-1-1+3) accumulated forceReconcileEvery delay + _, req = rec.waitFor(t, 3*time.Second) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) +} + +func TestController_WithForceReconcileEvery_SkipOnDelete(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + t.Parallel() + // Given a controller configured with a forceReconcileEvery duration + // When the controller reconciles a resource due to a delete and succeeds + // Then the controller manager should not schedule a forced reconcile + rec := newTestReconciler() + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + // Large enough gap to test for a period of no-reconciles + forceReconcileEvery := 5 * time.Second + ctrl := controller. + NewController("artist", pbdemov2.ArtistType). + WithLogger(testutil.Logger(t)). + WithForceReconcileEvery(forceReconcileEvery). + WithReconciler(rec) + + mgr := controller.NewManager(client, testutil.Logger(t)) + mgr.Register(ctrl) + mgr.SetRaftLeader(true) + go mgr.Run(testContext(t)) + + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + // Account for reconcile #1 due to initial write + _, req := rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + + // Perform a delete + _, err = client.Delete(testContext(t), &pbresource.DeleteRequest{Id: rsp.Resource.Id}) + require.NoError(t, err) + + // Account for the reconcile #2 due to the delete + _, req = rec.wait(t) + + // Account for the deferred forced reconcile #3 from the original write event since deferred + // reconciles don't seem to be de-duped against non-deferred reconciles. + _, req = rec.waitFor(t, forceReconcileEvery) + + // Verify no further reconciles occur + rec.expectNoRequest(t, forceReconcileEvery) +} + +func TestController_Placement(t *testing.T) { + t.Parallel() + + t.Run("singleton", func(t *testing.T) { + var running atomic.Bool + running.Store(false) + + rec := newTestReconciler() + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + WithCloningDisabled(). + Run(t) + + ctrl := controller. + NewController("artist", pbdemov2.ArtistType). + WithWatch(pbdemov2.AlbumType, dependency.MapOwner). + WithPlacement(controller.PlacementSingleton). + WithNotifyStart(func(context.Context, controller.Runtime) { + running.Store(true) + }). + WithNotifyStop(func(context.Context, controller.Runtime) { + running.Store(false) + }). + WithReconciler(rec) + + mgr := controller.NewManager(client, testutil.Logger(t)) + mgr.Register(ctrl) + go mgr.Run(testContext(t)) + + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + // Reconciler should not be called until we're the Raft leader. + _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + rec.expectNoRequest(t, 500*time.Millisecond) + + // Become the leader and check the reconciler is called. + mgr.SetRaftLeader(true) + waitForAtomicBoolValue(t, &running, true) + _, _ = rec.wait(t) + + // Should not be called after losing leadership. + mgr.SetRaftLeader(false) + waitForAtomicBoolValue(t, &running, false) + _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + rec.expectNoRequest(t, 500*time.Millisecond) + }) + + t.Run("each server", func(t *testing.T) { + var running atomic.Bool + running.Store(false) + + rec := newTestReconciler() + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + ctrl := controller. + NewController("artist", pbdemov2.ArtistType). + WithWatch(pbdemov2.AlbumType, dependency.MapOwner). + WithPlacement(controller.PlacementEachServer). + WithNotifyStart(func(context.Context, controller.Runtime) { + running.Store(true) + }). + WithReconciler(rec) + + mgr := controller.NewManager(client, testutil.Logger(t)) + mgr.Register(ctrl) + go mgr.Run(testContext(t)) + waitForAtomicBoolValue(t, &running, true) + + res, err := demo.GenerateV2Artist() + require.NoError(t, err) + + // Reconciler should be called even though we're not the Raft leader. + _, err = client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + _, _ = rec.wait(t) + }) +} + +func TestController_String(t *testing.T) { + ctrl := controller. + NewController("artist", pbdemov2.ArtistType). + WithWatch(pbdemov2.AlbumType, dependency.MapOwner). + WithBackoff(5*time.Second, 1*time.Hour). + WithPlacement(controller.PlacementEachServer) + + require.Equal(t, + `, placement=each-server>`, + ctrl.String(), + ) +} + +func TestController_NoReconciler(t *testing.T) { + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + mgr := controller.NewManager(client, testutil.Logger(t)) + + ctrl := controller.NewController("artist", pbdemov2.ArtistType) + require.PanicsWithValue(t, + fmt.Sprintf("cannot register controller without a reconciler %s", ctrl.String()), + func() { mgr.Register(ctrl) }) +} + +func TestController_Watch(t *testing.T) { + t.Parallel() + + t.Run("partitioned scoped resources", func(t *testing.T) { + rec := newTestReconciler() + + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + ctrl := controller. + NewController("labels", pbdemov1.RecordLabelType). + WithReconciler(rec) + + mgr := controller.NewManager(client, testutil.Logger(t)) + mgr.SetRaftLeader(true) + mgr.Register(ctrl) + + ctx := testContext(t) + go mgr.Run(ctx) + + res, err := demo.GenerateV1RecordLabel("test") + require.NoError(t, err) + + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + _, req := rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + }) + + t.Run("cluster scoped resources", func(t *testing.T) { + rec := newTestReconciler() + + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + ctrl := controller. + NewController("executives", pbdemov1.ExecutiveType). + WithReconciler(rec) + + mgr := controller.NewManager(client, testutil.Logger(t)) + mgr.SetRaftLeader(true) + mgr.Register(ctrl) + + go mgr.Run(testContext(t)) + + exec, err := demo.GenerateV1Executive("test", "CEO") + require.NoError(t, err) + + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: exec}) + require.NoError(t, err) + + _, req := rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + }) + + t.Run("namespace scoped resources", func(t *testing.T) { + rec := newTestReconciler() + + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + + ctrl := controller. + NewController("artists", pbdemov2.ArtistType). + WithReconciler(rec) + + mgr := controller.NewManager(client, testutil.Logger(t)) + mgr.SetRaftLeader(true) + mgr.Register(ctrl) + + go mgr.Run(testContext(t)) + + artist, err := demo.GenerateV2Artist() + require.NoError(t, err) + + rsp, err := client.Write(testContext(t), &pbresource.WriteRequest{Resource: artist}) + require.NoError(t, err) + + _, req := rec.wait(t) + prototest.AssertDeepEqual(t, rsp.Resource.Id, req.ID) + }) +} + +func newTestReconciler() *testReconciler { + return &testReconciler{ + calls: make(chan requestArgs), + errors: make(chan error, 1), + panics: make(chan any, 1), + } +} + +type requestArgs struct { + req controller.Request + rt controller.Runtime +} + +type testReconciler struct { + calls chan requestArgs + errors chan error + panics chan any +} + +func (r *testReconciler) Reconcile(_ context.Context, rt controller.Runtime, req controller.Request) error { + r.calls <- requestArgs{req: req, rt: rt} + + select { + case err := <-r.errors: + return err + case p := <-r.panics: + panic(p) + default: + return nil + } +} + +func (r *testReconciler) failNext(err error) { + r.errors <- err +} + +func (r *testReconciler) panicNext(p any) { + r.panics <- p +} + +func (r *testReconciler) expectNoRequest(t *testing.T, duration time.Duration) { + t.Helper() + + started := time.Now() + select { + case args := <-r.calls: + t.Fatalf("expected no request for %s, but got: %s after %s", duration, args.req.ID, time.Since(started)) + case <-time.After(duration): + } +} + +func (r *testReconciler) wait(t *testing.T) (controller.Runtime, controller.Request) { + t.Helper() + return r.waitFor(t, 500*time.Millisecond) +} + +func (r *testReconciler) waitFor(t *testing.T, duration time.Duration) (controller.Runtime, controller.Request) { + t.Helper() + + var args requestArgs + select { + case args = <-r.calls: + case <-time.After(duration): + t.Fatalf("Reconcile was not called after %v", duration) + } + return args.rt, args.req +} + +func testContext(t *testing.T) context.Context { + t.Helper() + + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + + return ctx +} + +type Concert struct { + name string + artistID *pbresource.ID +} + +func (c Concert) Key() string { + return c.name +} + +func newTestInitializer(errorCount int) *testInitializer { + return &testInitializer{ + calls: make(chan error, 1), + expectedAttempts: errorCount, + } +} + +type testInitializer struct { + expectedAttempts int // number of times the initializer should run to test retries + attempts int // running count of times initialize is called + calls chan error +} + +func (i *testInitializer) Initialize(_ context.Context, _ controller.Runtime) error { + i.attempts++ + if i.attempts < i.expectedAttempts { + // Return an error to cause a retry + err := errors.New("initialization error") + i.calls <- err + return err + } else { + i.calls <- nil + return nil + } +} + +func (i *testInitializer) wait(t *testing.T) { + t.Helper() + select { + case err := <-i.calls: + if err == nil { + // Initialize did not error, no more calls should be expected + close(i.calls) + } + return + case <-time.After(1000 * time.Millisecond): + t.Fatal("Initialize was not called after 1000ms") + } +} diff --git a/internal/controller/controllermock/mock_CacheIDModifier.go b/internal/controller/controllermock/mock_CacheIDModifier.go new file mode 100644 index 000000000000..3b86dc099708 --- /dev/null +++ b/internal/controller/controllermock/mock_CacheIDModifier.go @@ -0,0 +1,95 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package controllermock + +import ( + context "context" + + controller "github.com/hashicorp/consul/internal/controller" + mock "github.com/stretchr/testify/mock" + + pbresource "github.com/hashicorp/consul/proto-public/pbresource" +) + +// CacheIDModifier is an autogenerated mock type for the CacheIDModifier type +type CacheIDModifier struct { + mock.Mock +} + +type CacheIDModifier_Expecter struct { + mock *mock.Mock +} + +func (_m *CacheIDModifier) EXPECT() *CacheIDModifier_Expecter { + return &CacheIDModifier_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: ctx, rt, id +func (_m *CacheIDModifier) Execute(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*pbresource.ID, error) { + ret := _m.Called(ctx, rt, id) + + var r0 *pbresource.ID + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, *pbresource.ID) (*pbresource.ID, error)); ok { + return rf(ctx, rt, id) + } + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, *pbresource.ID) *pbresource.ID); ok { + r0 = rf(ctx, rt, id) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.ID) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, controller.Runtime, *pbresource.ID) error); ok { + r1 = rf(ctx, rt, id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CacheIDModifier_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type CacheIDModifier_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - ctx context.Context +// - rt controller.Runtime +// - id *pbresource.ID +func (_e *CacheIDModifier_Expecter) Execute(ctx interface{}, rt interface{}, id interface{}) *CacheIDModifier_Execute_Call { + return &CacheIDModifier_Execute_Call{Call: _e.mock.On("Execute", ctx, rt, id)} +} + +func (_c *CacheIDModifier_Execute_Call) Run(run func(ctx context.Context, rt controller.Runtime, id *pbresource.ID)) *CacheIDModifier_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(controller.Runtime), args[2].(*pbresource.ID)) + }) + return _c +} + +func (_c *CacheIDModifier_Execute_Call) Return(_a0 *pbresource.ID, _a1 error) *CacheIDModifier_Execute_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *CacheIDModifier_Execute_Call) RunAndReturn(run func(context.Context, controller.Runtime, *pbresource.ID) (*pbresource.ID, error)) *CacheIDModifier_Execute_Call { + _c.Call.Return(run) + return _c +} + +// NewCacheIDModifier creates a new instance of CacheIDModifier. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewCacheIDModifier(t interface { + mock.TestingT + Cleanup(func()) +}) *CacheIDModifier { + mock := &CacheIDModifier{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/controllermock/mock_CustomDependencyMapper.go b/internal/controller/controllermock/mock_CustomDependencyMapper.go new file mode 100644 index 000000000000..70e25ca98fd4 --- /dev/null +++ b/internal/controller/controllermock/mock_CustomDependencyMapper.go @@ -0,0 +1,93 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package controllermock + +import ( + context "context" + + controller "github.com/hashicorp/consul/internal/controller" + mock "github.com/stretchr/testify/mock" +) + +// CustomDependencyMapper is an autogenerated mock type for the CustomDependencyMapper type +type CustomDependencyMapper struct { + mock.Mock +} + +type CustomDependencyMapper_Expecter struct { + mock *mock.Mock +} + +func (_m *CustomDependencyMapper) EXPECT() *CustomDependencyMapper_Expecter { + return &CustomDependencyMapper_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: ctx, rt, event +func (_m *CustomDependencyMapper) Execute(ctx context.Context, rt controller.Runtime, event controller.Event) ([]controller.Request, error) { + ret := _m.Called(ctx, rt, event) + + var r0 []controller.Request + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, controller.Event) ([]controller.Request, error)); ok { + return rf(ctx, rt, event) + } + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, controller.Event) []controller.Request); ok { + r0 = rf(ctx, rt, event) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]controller.Request) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, controller.Runtime, controller.Event) error); ok { + r1 = rf(ctx, rt, event) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CustomDependencyMapper_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type CustomDependencyMapper_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - ctx context.Context +// - rt controller.Runtime +// - event controller.Event +func (_e *CustomDependencyMapper_Expecter) Execute(ctx interface{}, rt interface{}, event interface{}) *CustomDependencyMapper_Execute_Call { + return &CustomDependencyMapper_Execute_Call{Call: _e.mock.On("Execute", ctx, rt, event)} +} + +func (_c *CustomDependencyMapper_Execute_Call) Run(run func(ctx context.Context, rt controller.Runtime, event controller.Event)) *CustomDependencyMapper_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(controller.Runtime), args[2].(controller.Event)) + }) + return _c +} + +func (_c *CustomDependencyMapper_Execute_Call) Return(_a0 []controller.Request, _a1 error) *CustomDependencyMapper_Execute_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *CustomDependencyMapper_Execute_Call) RunAndReturn(run func(context.Context, controller.Runtime, controller.Event) ([]controller.Request, error)) *CustomDependencyMapper_Execute_Call { + _c.Call.Return(run) + return _c +} + +// NewCustomDependencyMapper creates a new instance of CustomDependencyMapper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewCustomDependencyMapper(t interface { + mock.TestingT + Cleanup(func()) +}) *CustomDependencyMapper { + mock := &CustomDependencyMapper{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/controllermock/mock_DependencyMapper.go b/internal/controller/controllermock/mock_DependencyMapper.go new file mode 100644 index 000000000000..be2519783a85 --- /dev/null +++ b/internal/controller/controllermock/mock_DependencyMapper.go @@ -0,0 +1,95 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package controllermock + +import ( + context "context" + + controller "github.com/hashicorp/consul/internal/controller" + mock "github.com/stretchr/testify/mock" + + pbresource "github.com/hashicorp/consul/proto-public/pbresource" +) + +// DependencyMapper is an autogenerated mock type for the DependencyMapper type +type DependencyMapper struct { + mock.Mock +} + +type DependencyMapper_Expecter struct { + mock *mock.Mock +} + +func (_m *DependencyMapper) EXPECT() *DependencyMapper_Expecter { + return &DependencyMapper_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: ctx, rt, res +func (_m *DependencyMapper) Execute(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + ret := _m.Called(ctx, rt, res) + + var r0 []controller.Request + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, *pbresource.Resource) ([]controller.Request, error)); ok { + return rf(ctx, rt, res) + } + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, *pbresource.Resource) []controller.Request); ok { + r0 = rf(ctx, rt, res) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]controller.Request) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, controller.Runtime, *pbresource.Resource) error); ok { + r1 = rf(ctx, rt, res) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DependencyMapper_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type DependencyMapper_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - ctx context.Context +// - rt controller.Runtime +// - res *pbresource.Resource +func (_e *DependencyMapper_Expecter) Execute(ctx interface{}, rt interface{}, res interface{}) *DependencyMapper_Execute_Call { + return &DependencyMapper_Execute_Call{Call: _e.mock.On("Execute", ctx, rt, res)} +} + +func (_c *DependencyMapper_Execute_Call) Run(run func(ctx context.Context, rt controller.Runtime, res *pbresource.Resource)) *DependencyMapper_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(controller.Runtime), args[2].(*pbresource.Resource)) + }) + return _c +} + +func (_c *DependencyMapper_Execute_Call) Return(_a0 []controller.Request, _a1 error) *DependencyMapper_Execute_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DependencyMapper_Execute_Call) RunAndReturn(run func(context.Context, controller.Runtime, *pbresource.Resource) ([]controller.Request, error)) *DependencyMapper_Execute_Call { + _c.Call.Return(run) + return _c +} + +// NewDependencyMapper creates a new instance of DependencyMapper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDependencyMapper(t interface { + mock.TestingT + Cleanup(func()) +}) *DependencyMapper { + mock := &DependencyMapper{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/controllermock/mock_DependencyTransform.go b/internal/controller/controllermock/mock_DependencyTransform.go new file mode 100644 index 000000000000..7f1611c67309 --- /dev/null +++ b/internal/controller/controllermock/mock_DependencyTransform.go @@ -0,0 +1,95 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package controllermock + +import ( + context "context" + + controller "github.com/hashicorp/consul/internal/controller" + mock "github.com/stretchr/testify/mock" + + pbresource "github.com/hashicorp/consul/proto-public/pbresource" +) + +// DependencyTransform is an autogenerated mock type for the DependencyTransform type +type DependencyTransform struct { + mock.Mock +} + +type DependencyTransform_Expecter struct { + mock *mock.Mock +} + +func (_m *DependencyTransform) EXPECT() *DependencyTransform_Expecter { + return &DependencyTransform_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: ctx, rt, res +func (_m *DependencyTransform) Execute(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]*pbresource.Resource, error) { + ret := _m.Called(ctx, rt, res) + + var r0 []*pbresource.Resource + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, *pbresource.Resource) ([]*pbresource.Resource, error)); ok { + return rf(ctx, rt, res) + } + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, *pbresource.Resource) []*pbresource.Resource); ok { + r0 = rf(ctx, rt, res) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*pbresource.Resource) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, controller.Runtime, *pbresource.Resource) error); ok { + r1 = rf(ctx, rt, res) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DependencyTransform_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type DependencyTransform_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - ctx context.Context +// - rt controller.Runtime +// - res *pbresource.Resource +func (_e *DependencyTransform_Expecter) Execute(ctx interface{}, rt interface{}, res interface{}) *DependencyTransform_Execute_Call { + return &DependencyTransform_Execute_Call{Call: _e.mock.On("Execute", ctx, rt, res)} +} + +func (_c *DependencyTransform_Execute_Call) Run(run func(ctx context.Context, rt controller.Runtime, res *pbresource.Resource)) *DependencyTransform_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(controller.Runtime), args[2].(*pbresource.Resource)) + }) + return _c +} + +func (_c *DependencyTransform_Execute_Call) Return(_a0 []*pbresource.Resource, _a1 error) *DependencyTransform_Execute_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DependencyTransform_Execute_Call) RunAndReturn(run func(context.Context, controller.Runtime, *pbresource.Resource) ([]*pbresource.Resource, error)) *DependencyTransform_Execute_Call { + _c.Call.Return(run) + return _c +} + +// NewDependencyTransform creates a new instance of DependencyTransform. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDependencyTransform(t interface { + mock.TestingT + Cleanup(func()) +}) *DependencyTransform { + mock := &DependencyTransform{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/controllermock/mock_Lease.go b/internal/controller/controllermock/mock_Lease.go new file mode 100644 index 000000000000..eb9e5cda77f7 --- /dev/null +++ b/internal/controller/controllermock/mock_Lease.go @@ -0,0 +1,116 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package controllermock + +import mock "github.com/stretchr/testify/mock" + +// Lease is an autogenerated mock type for the Lease type +type Lease struct { + mock.Mock +} + +type Lease_Expecter struct { + mock *mock.Mock +} + +func (_m *Lease) EXPECT() *Lease_Expecter { + return &Lease_Expecter{mock: &_m.Mock} +} + +// Changed provides a mock function with given fields: +func (_m *Lease) Changed() <-chan struct{} { + ret := _m.Called() + + var r0 <-chan struct{} + if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(<-chan struct{}) + } + } + + return r0 +} + +// Lease_Changed_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Changed' +type Lease_Changed_Call struct { + *mock.Call +} + +// Changed is a helper method to define mock.On call +func (_e *Lease_Expecter) Changed() *Lease_Changed_Call { + return &Lease_Changed_Call{Call: _e.mock.On("Changed")} +} + +func (_c *Lease_Changed_Call) Run(run func()) *Lease_Changed_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Lease_Changed_Call) Return(_a0 <-chan struct{}) *Lease_Changed_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Lease_Changed_Call) RunAndReturn(run func() <-chan struct{}) *Lease_Changed_Call { + _c.Call.Return(run) + return _c +} + +// Held provides a mock function with given fields: +func (_m *Lease) Held() bool { + ret := _m.Called() + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// Lease_Held_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Held' +type Lease_Held_Call struct { + *mock.Call +} + +// Held is a helper method to define mock.On call +func (_e *Lease_Expecter) Held() *Lease_Held_Call { + return &Lease_Held_Call{Call: _e.mock.On("Held")} +} + +func (_c *Lease_Held_Call) Run(run func()) *Lease_Held_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Lease_Held_Call) Return(_a0 bool) *Lease_Held_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Lease_Held_Call) RunAndReturn(run func() bool) *Lease_Held_Call { + _c.Call.Return(run) + return _c +} + +// NewLease creates a new instance of Lease. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewLease(t interface { + mock.TestingT + Cleanup(func()) +}) *Lease { + mock := &Lease{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/controllermock/mock_Reconciler.go b/internal/controller/controllermock/mock_Reconciler.go new file mode 100644 index 000000000000..5488978ea4b7 --- /dev/null +++ b/internal/controller/controllermock/mock_Reconciler.go @@ -0,0 +1,81 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package controllermock + +import ( + context "context" + + controller "github.com/hashicorp/consul/internal/controller" + mock "github.com/stretchr/testify/mock" +) + +// Reconciler is an autogenerated mock type for the Reconciler type +type Reconciler struct { + mock.Mock +} + +type Reconciler_Expecter struct { + mock *mock.Mock +} + +func (_m *Reconciler) EXPECT() *Reconciler_Expecter { + return &Reconciler_Expecter{mock: &_m.Mock} +} + +// Reconcile provides a mock function with given fields: ctx, rt, req +func (_m *Reconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { + ret := _m.Called(ctx, rt, req) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, controller.Request) error); ok { + r0 = rf(ctx, rt, req) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Reconciler_Reconcile_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Reconcile' +type Reconciler_Reconcile_Call struct { + *mock.Call +} + +// Reconcile is a helper method to define mock.On call +// - ctx context.Context +// - rt controller.Runtime +// - req controller.Request +func (_e *Reconciler_Expecter) Reconcile(ctx interface{}, rt interface{}, req interface{}) *Reconciler_Reconcile_Call { + return &Reconciler_Reconcile_Call{Call: _e.mock.On("Reconcile", ctx, rt, req)} +} + +func (_c *Reconciler_Reconcile_Call) Run(run func(ctx context.Context, rt controller.Runtime, req controller.Request)) *Reconciler_Reconcile_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(controller.Runtime), args[2].(controller.Request)) + }) + return _c +} + +func (_c *Reconciler_Reconcile_Call) Return(_a0 error) *Reconciler_Reconcile_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Reconciler_Reconcile_Call) RunAndReturn(run func(context.Context, controller.Runtime, controller.Request) error) *Reconciler_Reconcile_Call { + _c.Call.Return(run) + return _c +} + +// NewReconciler creates a new instance of Reconciler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewReconciler(t interface { + mock.TestingT + Cleanup(func()) +}) *Reconciler { + mock := &Reconciler{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/controllermock/mock_task.go b/internal/controller/controllermock/mock_task.go new file mode 100644 index 000000000000..6707fc1e56fd --- /dev/null +++ b/internal/controller/controllermock/mock_task.go @@ -0,0 +1,78 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package controllermock + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" +) + +// task is an autogenerated mock type for the task type +type task struct { + mock.Mock +} + +type task_Expecter struct { + mock *mock.Mock +} + +func (_m *task) EXPECT() *task_Expecter { + return &task_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: _a0 +func (_m *task) Execute(_a0 context.Context) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// task_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type task_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - _a0 context.Context +func (_e *task_Expecter) Execute(_a0 interface{}) *task_Execute_Call { + return &task_Execute_Call{Call: _e.mock.On("Execute", _a0)} +} + +func (_c *task_Execute_Call) Run(run func(_a0 context.Context)) *task_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *task_Execute_Call) Return(_a0 error) *task_Execute_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *task_Execute_Call) RunAndReturn(run func(context.Context) error) *task_Execute_Call { + _c.Call.Return(run) + return _c +} + +// newTask creates a new instance of task. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newTask(t interface { + mock.TestingT + Cleanup(func()) +}) *task { + mock := &task{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/controllertest/builder.go b/internal/controller/controllertest/builder.go new file mode 100644 index 000000000000..8754ad355200 --- /dev/null +++ b/internal/controller/controllertest/builder.go @@ -0,0 +1,90 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package controllertest + +import ( + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil" +) + +type Builder struct { + serviceBuilder *svctest.Builder + controllerRegisterFns []func(*controller.Manager) +} + +// NewControllerTestBuilder starts to build out out the necessary controller testing +// runtime for lightweight controller integration testing. This will run a single +// in-memory resource service instance and the controller manager. Usage of this +// builder is an easy way to ensure that all the right resource gRPC connections/clients +// get set up appropriately in a manner identical to how they would be on a full +// running server. +func NewControllerTestBuilder() *Builder { + return &Builder{ + // disable cloning because we will enable it after passing the non-cloning variant + // to the controller manager. + serviceBuilder: svctest.NewResourceServiceBuilder().WithCloningDisabled(), + } +} + +// Registry retrieves the resource registry from the internal im-mem resource service. +func (b *Builder) Registry() resource.Registry { + return b.serviceBuilder.Registry() +} + +// WithResourceRegisterFns allows configuring functions to be run to register resource +// types with the internal in-mem resource service for the duration of the test. +func (b *Builder) WithResourceRegisterFns(registerFns ...func(resource.Registry)) *Builder { + b.serviceBuilder = b.serviceBuilder.WithRegisterFns(registerFns...) + return b +} + +// WithControllerRegisterFns allows configuring a set of controllers that should be registered +// with the controller manager and executed during Run. +func (b *Builder) WithControllerRegisterFns(registerFns ...func(*controller.Manager)) *Builder { + for _, registerFn := range registerFns { + b.controllerRegisterFns = append(b.controllerRegisterFns, registerFn) + } + return b +} + +// WithACLResolver is used to provide an ACLResolver implementation to the internal resource service. +func (b *Builder) WithACLResolver(aclResolver svc.ACLResolver) *Builder { + b.serviceBuilder = b.serviceBuilder.WithACLResolver(aclResolver) + return b +} + +// WithTenancies adds additional tenancies if default/default is not sufficient. +func (b *Builder) WithTenancies(tenancies ...*pbresource.Tenancy) *Builder { + b.serviceBuilder = b.serviceBuilder.WithTenancies(tenancies...) + return b +} + +// Run executes both the internal resource service and the controller manager. +// The controller manager gets told it is the Raft leader so all controllers +// will get executed. The resource service, controller manager and all controllers +// will be stopped when the test finishes by registering a cleanup method on +// the test. +func (b *Builder) Run(t testutil.TestingTB) pbresource.ResourceServiceClient { + t.Helper() + + ctx := testutil.TestContext(t) + + client := b.serviceBuilder.Run(t) + + mgr := controller.NewManager(client, testutil.Logger(t)) + for _, register := range b.controllerRegisterFns { + register(mgr) + } + + mgr.SetRaftLeader(true) + go mgr.Run(ctx) + + // auto-clone messages going through the client so that test + // code is free to modify objects in place without cloning themselves. + return pbresource.NewCloningResourceServiceClient(client) +} diff --git a/internal/controller/custom_watch.go b/internal/controller/custom_watch.go new file mode 100644 index 000000000000..627a5e48f40a --- /dev/null +++ b/internal/controller/custom_watch.go @@ -0,0 +1,57 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package controller + +import ( + "context" + + "github.com/hashicorp/consul/agent/consul/controller/queue" +) + +// CustomDependencyMapper is called when an Event occurs to determine which of the +// controller's managed resources need to be reconciled. +type CustomDependencyMapper func( + ctx context.Context, + rt Runtime, + event Event, +) ([]Request, error) + +// Watch is responsible for watching for custom events from source and adding them to +// the event queue. +func (s *Source) Watch(ctx context.Context, add func(e Event)) error { + for { + select { + case <-ctx.Done(): + return nil + case evt, ok := <-s.Source: + if !ok { + return nil + } + add(evt) + } + } +} + +// Source is used as a generic source of events. This can be used when events aren't coming from resources +// stored by the resource API. +type Source struct { + Source <-chan Event +} + +// Event captures an event in the system which the API can choose to respond to. +type Event struct { + Obj queue.ItemType +} + +// Key returns a string that will be used to de-duplicate items in the queue. +func (e Event) Key() string { + return e.Obj.Key() +} + +// customWatch represent a Watch on a custom Event source and a Mapper to map said +// Events into Requests that the controller can respond to. +type customWatch struct { + source *Source + mapper CustomDependencyMapper +} diff --git a/internal/controller/dependencies.go b/internal/controller/dependencies.go index 6a91d91ff7b7..fb3f151bebb1 100644 --- a/internal/controller/dependencies.go +++ b/internal/controller/dependencies.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/hashicorp/go-multierror" + "golang.org/x/exp/maps" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" @@ -66,12 +67,23 @@ func (m *Manager) CalculateDependencies(registrations []resource.Registration) D } for _, c := range m.controllers { - watches := make([]string, 0, len(c.watches)) + watches := map[string]struct{}{} + + // Extend existing watch list if one is present. This is necessary + // because there can be multiple controllers for a given type. + // ProxyStateTemplate, for example, is controlled by sidecar proxy and + // gateway proxy controllers. + if existing, ok := out[typeToString(c.managedTypeWatch.watchedType)]; ok { + for _, w := range existing { + watches[w] = struct{}{} + } + } + for _, w := range c.watches { - watches = append(watches, typeToString(w.watchedType)) + watches[typeToString(w.watchedType)] = struct{}{} } - out[typeToString(c.managedType)] = watches + out[typeToString(c.managedTypeWatch.watchedType)] = maps.Keys(watches) } return out diff --git a/internal/controller/dependency/.mockery.yaml b/internal/controller/dependency/.mockery.yaml new file mode 100644 index 000000000000..4595f3b527ab --- /dev/null +++ b/internal/controller/dependency/.mockery.yaml @@ -0,0 +1,11 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +with-expecter: true +all: true +recursive: false +dir: "{{.PackageName}}mock" +outpkg: "{{.PackageName}}mock" +mockname: "{{.InterfaceName}}" +packages: + github.com/hashicorp/consul/internal/controller/dependency: diff --git a/internal/controller/dependency/cache.go b/internal/controller/dependency/cache.go new file mode 100644 index 000000000000..321e57ac6d6e --- /dev/null +++ b/internal/controller/dependency/cache.go @@ -0,0 +1,218 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dependency + +import ( + "context" + "fmt" + + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// CacheIDModifier is used to alter the Resource ID of the various Cache* +// controller.DependencyMappers prior to making the request to the cache. This is most +// useful to replace the type of resource queried (such as when resource types +// are name aligned) or to modify the tenancy in some way. +type CacheIDModifier func( + ctx context.Context, + rt controller.Runtime, + id *pbresource.ID, +) (*pbresource.ID, error) + +// CacheGetMapper is used to map an event for a watched resource by performing a Get of +// a single cached resource of any type. +func CacheGetMapper(indexedType *pbresource.Type, indexName string, mods ...CacheIDModifier) controller.DependencyMapper { + return func(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + id, err := applyCacheIDMods(ctx, rt, res.GetId(), mods...) + if err != nil { + return nil, err + } + + if rt.Logger.IsTrace() { + rt.Logger.Trace("mapping dependencies from cache", + "type", resource.ToGVK(indexedType), + "index", indexName, + "resource", resource.IDToString(res.GetId()), + ) + } + mapped, err := rt.Cache.Get(indexedType, indexName, id) + if err != nil { + rt.Logger.Error("failed to map dependencies from the cache", + "type", resource.ToGVK(indexedType), + "index", indexName, + "resource", resource.IDToString(res.GetId()), + "error", err, + ) + return nil, fmt.Errorf("failed to list from cache index %q on type %q: %w", indexName, resource.ToGVK(indexedType), err) + } + + results := []controller.Request{ + {ID: mapped.GetId()}, + } + if rt.Logger.IsTrace() { + rt.Logger.Trace("mapped dependencies", + "type", resource.ToGVK(indexedType), + "index", indexName, + "resource", resource.IDToString(res.GetId()), + "dependency", mapped.GetId(), + ) + } + + return results, nil + } +} + +// CacheListMapper is used to map the incoming resource to a set of requests for all +// the cached resources returned by the caches List operation. +func CacheListMapper(indexedType *pbresource.Type, indexName string, mods ...CacheIDModifier) controller.DependencyMapper { + return func(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + id, err := applyCacheIDMods(ctx, rt, res.GetId(), mods...) + if err != nil { + return nil, err + } + + if rt.Logger.IsTrace() { + rt.Logger.Trace("mapping dependencies from cache", + "type", resource.ToGVK(indexedType), + "index", indexName, + "resource", resource.IDToString(res.GetId()), + ) + } + iter, err := rt.Cache.ListIterator(indexedType, indexName, id) + if err != nil { + rt.Logger.Error("failed to map dependencies from the cache", + "type", resource.ToGVK(indexedType), + "index", indexName, + "resource", resource.IDToString(res.GetId()), + "error", err, + ) + return nil, fmt.Errorf("failed to list from cache index %q on type %q: %w", indexName, resource.ToGVK(indexedType), err) + } + + var results []controller.Request + for res := iter.Next(); res != nil; res = iter.Next() { + results = append(results, controller.Request{ID: res.GetId()}) + } + if rt.Logger.IsTrace() { + rt.Logger.Trace("mapped dependencies", + "type", resource.ToGVK(indexedType), + "index", indexName, + "resource", resource.IDToString(res.GetId()), + "dependencies", results, + ) + } + + return results, nil + } +} + +// CacheParentsMapper is used to map the incoming resource to a set of requests for all +// the cached resources returned by the caches Parents operation. +func CacheParentsMapper(indexedType *pbresource.Type, indexName string, mods ...CacheIDModifier) controller.DependencyMapper { + return func(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + id, err := applyCacheIDMods(ctx, rt, res.GetId(), mods...) + if err != nil { + return nil, err + } + + if rt.Logger.IsTrace() { + rt.Logger.Trace("mapping dependencies from cache", + "type", resource.ToGVK(indexedType), + "index", indexName, + "resource", resource.IDToString(res.GetId()), + ) + } + iter, err := rt.Cache.ParentsIterator(indexedType, indexName, id) + if err != nil { + rt.Logger.Error("failed to map dependencies from the cache", + "type", resource.ToGVK(indexedType), + "index", indexName, + "resource", resource.IDToString(res.GetId()), + "error", err, + ) + return nil, fmt.Errorf("failed to list from cache index %q on type %q: %w", indexName, resource.ToGVK(indexedType), err) + } + + var results []controller.Request + for res := iter.Next(); res != nil; res = iter.Next() { + results = append(results, controller.Request{ID: res.GetId()}) + } + if rt.Logger.IsTrace() { + rt.Logger.Trace("mapped dependencies", + "type", resource.ToGVK(indexedType), + "index", indexName, + "resource", resource.IDToString(res.GetId()), + "dependencies", results, + ) + } + + return results, nil + } +} + +// CacheListTransform operates like CacheListMapper. The only difference is that the cache results +// are left as the whole cached resource instead of condensing down to just their IDs. +func CacheListTransform(indexedType *pbresource.Type, indexName string, mods ...CacheIDModifier) DependencyTransform { + return func(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]*pbresource.Resource, error) { + id, err := applyCacheIDMods(ctx, rt, res.GetId(), mods...) + if err != nil { + return nil, err + } + + if rt.Logger.IsTrace() { + rt.Logger.Trace("transforming dependencies from cache", + "type", resource.ToGVK(indexedType), + "index", indexName, + "resource", resource.IDToString(res.GetId()), + ) + } + results, err := rt.Cache.List(indexedType, indexName, id) + if err != nil { + rt.Logger.Error("failed to transform dependencies from the cache", + "type", resource.ToGVK(indexedType), + "index", indexName, + "resource", resource.IDToString(res.GetId()), + "error", err, + ) + return nil, fmt.Errorf( + "failed to list from cache index %q on type %q: %w", + indexName, + resource.ToGVK(indexedType), + err, + ) + } + + if rt.Logger.IsTrace() { + rt.Logger.Trace("transformed dependencies", + "type", resource.ToGVK(indexedType), + "index", indexName, + "resource", resource.IDToString(res.GetId()), + "dependencies", results, + ) + } + + return results, nil + } +} + +// ReplaceCacheIDType will generate a CacheIDModifier that replaces the original ID's +// type with the desired type specified. +func ReplaceCacheIDType(desiredType *pbresource.Type) CacheIDModifier { + return func(_ context.Context, _ controller.Runtime, id *pbresource.ID) (*pbresource.ID, error) { + return resource.ReplaceType(desiredType, id), nil + } +} + +func applyCacheIDMods(ctx context.Context, rt controller.Runtime, id *pbresource.ID, mods ...CacheIDModifier) (*pbresource.ID, error) { + var err error + for _, mod := range mods { + id, err = mod(ctx, rt, id) + if err != nil { + return nil, err + } + } + return id, err +} diff --git a/internal/controller/dependency/cache_test.go b/internal/controller/dependency/cache_test.go new file mode 100644 index 000000000000..8b686e22e456 --- /dev/null +++ b/internal/controller/dependency/cache_test.go @@ -0,0 +1,346 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dependency + +import ( + "context" + "testing" + + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/controller/cache/cachemock" + "github.com/hashicorp/consul/internal/controller/dependency/dependencymock" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +type cacheSuite struct { + suite.Suite + + cache *cachemock.ReadOnlyCache + idMod *dependencymock.CacheIDModifier + res *pbresource.Resource + rt controller.Runtime +} + +func (suite *cacheSuite) SetupTest() { + suite.res = resourcetest.Resource(fakeMapType, "foo"). + WithTenancy(resource.DefaultNamespacedTenancy()). + Build() + suite.idMod = dependencymock.NewCacheIDModifier(suite.T()) + suite.cache = cachemock.NewReadOnlyCache(suite.T()) + suite.rt = controller.Runtime{ + Cache: suite.cache, + Logger: testutil.Logger(suite.T()), + } +} + +func (suite *cacheSuite) TestGetMapper_ModErr() { + suite.idMod.EXPECT(). + Execute(mock.Anything, suite.rt, suite.res.Id). + Return(nil, injectedErr). + Once() + + reqs, err := CacheGetMapper(suite.res.Id.Type, "doesnt-matter", suite.idMod.Execute)( + context.Background(), + suite.rt, + suite.res, + ) + + require.Nil(suite.T(), reqs) + require.ErrorIs(suite.T(), err, injectedErr) +} + +func (suite *cacheSuite) TestGetMapper_CacheErr() { + id := resourceID("testing", "v1", "fake", "foo") + suite.idMod.EXPECT(). + Execute(mock.Anything, suite.rt, suite.res.Id). + Return(id, nil). + Once() + + suite.cache.EXPECT(). + Get(suite.res.Id.Type, "fake-index", id). + Return(nil, injectedErr). + Once() + + reqs, err := CacheGetMapper(suite.res.Id.Type, "fake-index", suite.idMod.Execute)( + context.Background(), + suite.rt, + suite.res, + ) + + require.Nil(suite.T(), reqs) + require.ErrorIs(suite.T(), err, injectedErr) +} + +func (suite *cacheSuite) TestGetMapper_Ok() { + out := resourcetest.Resource(altFakeResourceType, "blah"). + WithTenancy(resource.DefaultNamespacedTenancy()). + Build() + id := resourceID("testing", "v1", "fake", "foo") + suite.idMod.EXPECT(). + Execute(mock.Anything, suite.rt, suite.res.Id). + Return(id, nil). + Once() + + suite.cache.EXPECT(). + Get(suite.res.Id.Type, "fake-index", id). + Return(out, nil). + Once() + + reqs, err := CacheGetMapper(suite.res.Id.Type, "fake-index", suite.idMod.Execute)( + context.Background(), + suite.rt, + suite.res, + ) + + require.NoError(suite.T(), err) + require.Len(suite.T(), reqs, 1) + prototest.AssertDeepEqual(suite.T(), out.Id, reqs[0].ID) +} + +func (suite *cacheSuite) TestListMapper_ModErr() { + suite.idMod.EXPECT(). + Execute(mock.Anything, suite.rt, suite.res.Id). + Return(nil, injectedErr). + Once() + + reqs, err := CacheListMapper(suite.res.Id.Type, "doesnt-matter", suite.idMod.Execute)( + context.Background(), + suite.rt, + suite.res, + ) + + require.Nil(suite.T(), reqs) + require.ErrorIs(suite.T(), err, injectedErr) +} + +func (suite *cacheSuite) TestListMapper_CacheErr() { + id := resourceID("testing", "v1", "fake", "foo") + suite.idMod.EXPECT(). + Execute(mock.Anything, suite.rt, suite.res.Id). + Return(id, nil). + Once() + + suite.cache.EXPECT(). + ListIterator(suite.res.Id.Type, "fake-index", id). + Return(nil, injectedErr). + Once() + + reqs, err := CacheListMapper(suite.res.Id.Type, "fake-index", suite.idMod.Execute)( + context.Background(), + suite.rt, + suite.res, + ) + + require.Nil(suite.T(), reqs) + require.ErrorIs(suite.T(), err, injectedErr) +} + +func (suite *cacheSuite) TestListMapper_Ok() { + out := resourcetest.Resource(altFakeResourceType, "blah"). + WithTenancy(resource.DefaultNamespacedTenancy()). + Build() + out2 := resourcetest.Resource(altFakeResourceType, "blah2"). + WithTenancy(resource.DefaultNamespacedTenancy()). + Build() + id := resourceID("testing", "v1", "fake", "foo") + suite.idMod.EXPECT(). + Execute(mock.Anything, suite.rt, suite.res.Id). + Return(id, nil). + Once() + + mockIter := cachemock.NewResourceIterator(suite.T()) + mockIter.EXPECT().Next().Return(out).Once() + mockIter.EXPECT().Next().Return(out2).Once() + mockIter.EXPECT().Next().Return(nil).Once() + + suite.cache.EXPECT(). + ListIterator(suite.res.Id.Type, "fake-index", id). + Return(mockIter, nil). + Once() + + reqs, err := CacheListMapper(suite.res.Id.Type, "fake-index", suite.idMod.Execute)( + context.Background(), + suite.rt, + suite.res, + ) + + require.NoError(suite.T(), err) + require.Len(suite.T(), reqs, 2) + expected := []controller.Request{ + {ID: out.Id}, + {ID: out2.Id}, + } + prototest.AssertElementsMatch(suite.T(), expected, reqs) +} + +func (suite *cacheSuite) TestParentsMapper_ModErr() { + suite.idMod.EXPECT(). + Execute(mock.Anything, suite.rt, suite.res.Id). + Return(nil, injectedErr). + Once() + + reqs, err := CacheParentsMapper(suite.res.Id.Type, "doesnt-matter", suite.idMod.Execute)( + context.Background(), + suite.rt, + suite.res, + ) + + require.Nil(suite.T(), reqs) + require.ErrorIs(suite.T(), err, injectedErr) +} + +func (suite *cacheSuite) TestParentsMapper_CacheErr() { + id := resourceID("testing", "v1", "fake", "foo") + suite.idMod.EXPECT(). + Execute(mock.Anything, suite.rt, suite.res.Id). + Return(id, nil). + Once() + + suite.cache.EXPECT(). + ParentsIterator(suite.res.Id.Type, "fake-index", id). + Return(nil, injectedErr). + Once() + + reqs, err := CacheParentsMapper(suite.res.Id.Type, "fake-index", suite.idMod.Execute)( + context.Background(), + suite.rt, + suite.res, + ) + + require.Nil(suite.T(), reqs) + require.ErrorIs(suite.T(), err, injectedErr) +} + +func (suite *cacheSuite) TestParentsMapper_Ok() { + out := resourcetest.Resource(altFakeResourceType, "blah"). + WithTenancy(resource.DefaultNamespacedTenancy()). + Build() + out2 := resourcetest.Resource(altFakeResourceType, "blah2"). + WithTenancy(resource.DefaultNamespacedTenancy()). + Build() + id := resourceID("testing", "v1", "fake", "foo") + suite.idMod.EXPECT(). + Execute(mock.Anything, suite.rt, suite.res.Id). + Return(id, nil). + Once() + + mockIter := cachemock.NewResourceIterator(suite.T()) + mockIter.EXPECT().Next().Return(out).Once() + mockIter.EXPECT().Next().Return(out2).Once() + mockIter.EXPECT().Next().Return(nil).Once() + + suite.cache.EXPECT(). + ParentsIterator(suite.res.Id.Type, "fake-index", id). + Return(mockIter, nil). + Once() + + reqs, err := CacheParentsMapper(suite.res.Id.Type, "fake-index", suite.idMod.Execute)( + context.Background(), + suite.rt, + suite.res, + ) + + require.NoError(suite.T(), err) + require.Len(suite.T(), reqs, 2) + expected := []controller.Request{ + {ID: out.Id}, + {ID: out2.Id}, + } + prototest.AssertElementsMatch(suite.T(), expected, reqs) +} + +func (suite *cacheSuite) TestListTransform_ModErr() { + suite.idMod.EXPECT(). + Execute(mock.Anything, suite.rt, suite.res.Id). + Return(nil, injectedErr). + Once() + + reqs, err := CacheListTransform(suite.res.Id.Type, "doesnt-matter", suite.idMod.Execute)( + context.Background(), + suite.rt, + suite.res, + ) + + require.Nil(suite.T(), reqs) + require.ErrorIs(suite.T(), err, injectedErr) +} + +func (suite *cacheSuite) TestListTransform_CacheErr() { + id := resourceID("testing", "v1", "fake", "foo") + suite.idMod.EXPECT(). + Execute(mock.Anything, suite.rt, suite.res.Id). + Return(id, nil). + Once() + + suite.cache.EXPECT(). + List(suite.res.Id.Type, "fake-index", id). + Return(nil, injectedErr). + Once() + + resources, err := CacheListTransform(suite.res.Id.Type, "fake-index", suite.idMod.Execute)( + context.Background(), + suite.rt, + suite.res, + ) + + require.Nil(suite.T(), resources) + require.ErrorIs(suite.T(), err, injectedErr) +} + +func (suite *cacheSuite) TestListTransform_Ok() { + out := resourcetest.Resource(altFakeResourceType, "blah"). + WithTenancy(resource.DefaultNamespacedTenancy()). + Build() + out2 := resourcetest.Resource(altFakeResourceType, "blah2"). + WithTenancy(resource.DefaultNamespacedTenancy()). + Build() + id := resourceID("testing", "v1", "fake", "foo") + suite.idMod.EXPECT(). + Execute(mock.Anything, suite.rt, suite.res.Id). + Return(id, nil). + Once() + + expected := []*pbresource.Resource{out, out2} + suite.cache.EXPECT(). + List(suite.res.Id.Type, "fake-index", id). + Return(expected, nil). + Once() + + resources, err := CacheListTransform(suite.res.Id.Type, "fake-index", suite.idMod.Execute)( + context.Background(), + suite.rt, + suite.res, + ) + + require.NoError(suite.T(), err) + prototest.AssertElementsMatch(suite.T(), expected, resources) +} + +func TestCacheDependencies(t *testing.T) { + suite.Run(t, new(cacheSuite)) +} + +func TestReplaceCacheIDType(t *testing.T) { + rt := controller.Runtime{ + // populate something to differentiate from zero value + Logger: hclog.Default(), + } + + in := resourceID("testing", "v1", "pre-mod", "foo") + + mod := ReplaceCacheIDType(fakeResourceType) + + out, err := mod(context.Background(), rt, in) + require.NoError(t, err) + prototest.AssertDeepEqual(t, resource.ReplaceType(fakeResourceType, in), out) + +} diff --git a/internal/controller/dependency/dependencymock/mock_CacheIDModifier.go b/internal/controller/dependency/dependencymock/mock_CacheIDModifier.go new file mode 100644 index 000000000000..f9e582372dfe --- /dev/null +++ b/internal/controller/dependency/dependencymock/mock_CacheIDModifier.go @@ -0,0 +1,96 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package dependencymock + +import ( + context "context" + + controller "github.com/hashicorp/consul/internal/controller" + + mock "github.com/stretchr/testify/mock" + + pbresource "github.com/hashicorp/consul/proto-public/pbresource" +) + +// CacheIDModifier is an autogenerated mock type for the CacheIDModifier type +type CacheIDModifier struct { + mock.Mock +} + +type CacheIDModifier_Expecter struct { + mock *mock.Mock +} + +func (_m *CacheIDModifier) EXPECT() *CacheIDModifier_Expecter { + return &CacheIDModifier_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: ctx, rt, id +func (_m *CacheIDModifier) Execute(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*pbresource.ID, error) { + ret := _m.Called(ctx, rt, id) + + var r0 *pbresource.ID + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, *pbresource.ID) (*pbresource.ID, error)); ok { + return rf(ctx, rt, id) + } + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, *pbresource.ID) *pbresource.ID); ok { + r0 = rf(ctx, rt, id) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pbresource.ID) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, controller.Runtime, *pbresource.ID) error); ok { + r1 = rf(ctx, rt, id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CacheIDModifier_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type CacheIDModifier_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - ctx context.Context +// - rt controller.Runtime +// - id *pbresource.ID +func (_e *CacheIDModifier_Expecter) Execute(ctx interface{}, rt interface{}, id interface{}) *CacheIDModifier_Execute_Call { + return &CacheIDModifier_Execute_Call{Call: _e.mock.On("Execute", ctx, rt, id)} +} + +func (_c *CacheIDModifier_Execute_Call) Run(run func(ctx context.Context, rt controller.Runtime, id *pbresource.ID)) *CacheIDModifier_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(controller.Runtime), args[2].(*pbresource.ID)) + }) + return _c +} + +func (_c *CacheIDModifier_Execute_Call) Return(_a0 *pbresource.ID, _a1 error) *CacheIDModifier_Execute_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *CacheIDModifier_Execute_Call) RunAndReturn(run func(context.Context, controller.Runtime, *pbresource.ID) (*pbresource.ID, error)) *CacheIDModifier_Execute_Call { + _c.Call.Return(run) + return _c +} + +// NewCacheIDModifier creates a new instance of CacheIDModifier. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewCacheIDModifier(t interface { + mock.TestingT + Cleanup(func()) +}) *CacheIDModifier { + mock := &CacheIDModifier{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/dependency/dependencymock/mock_DependencyTransform.go b/internal/controller/dependency/dependencymock/mock_DependencyTransform.go new file mode 100644 index 000000000000..13168f2bbbdc --- /dev/null +++ b/internal/controller/dependency/dependencymock/mock_DependencyTransform.go @@ -0,0 +1,96 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package dependencymock + +import ( + context "context" + + controller "github.com/hashicorp/consul/internal/controller" + + mock "github.com/stretchr/testify/mock" + + pbresource "github.com/hashicorp/consul/proto-public/pbresource" +) + +// DependencyTransform is an autogenerated mock type for the DependencyTransform type +type DependencyTransform struct { + mock.Mock +} + +type DependencyTransform_Expecter struct { + mock *mock.Mock +} + +func (_m *DependencyTransform) EXPECT() *DependencyTransform_Expecter { + return &DependencyTransform_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: ctx, rt, res +func (_m *DependencyTransform) Execute(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]*pbresource.Resource, error) { + ret := _m.Called(ctx, rt, res) + + var r0 []*pbresource.Resource + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, *pbresource.Resource) ([]*pbresource.Resource, error)); ok { + return rf(ctx, rt, res) + } + if rf, ok := ret.Get(0).(func(context.Context, controller.Runtime, *pbresource.Resource) []*pbresource.Resource); ok { + r0 = rf(ctx, rt, res) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*pbresource.Resource) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, controller.Runtime, *pbresource.Resource) error); ok { + r1 = rf(ctx, rt, res) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DependencyTransform_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type DependencyTransform_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - ctx context.Context +// - rt controller.Runtime +// - res *pbresource.Resource +func (_e *DependencyTransform_Expecter) Execute(ctx interface{}, rt interface{}, res interface{}) *DependencyTransform_Execute_Call { + return &DependencyTransform_Execute_Call{Call: _e.mock.On("Execute", ctx, rt, res)} +} + +func (_c *DependencyTransform_Execute_Call) Run(run func(ctx context.Context, rt controller.Runtime, res *pbresource.Resource)) *DependencyTransform_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(controller.Runtime), args[2].(*pbresource.Resource)) + }) + return _c +} + +func (_c *DependencyTransform_Execute_Call) Return(_a0 []*pbresource.Resource, _a1 error) *DependencyTransform_Execute_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DependencyTransform_Execute_Call) RunAndReturn(run func(context.Context, controller.Runtime, *pbresource.Resource) ([]*pbresource.Resource, error)) *DependencyTransform_Execute_Call { + _c.Call.Return(run) + return _c +} + +// NewDependencyTransform creates a new instance of DependencyTransform. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDependencyTransform(t interface { + mock.TestingT + Cleanup(func()) +}) *DependencyTransform { + mock := &DependencyTransform{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/controller/dependency/higher_order.go b/internal/controller/dependency/higher_order.go new file mode 100644 index 000000000000..2f2e4c8e3c44 --- /dev/null +++ b/internal/controller/dependency/higher_order.go @@ -0,0 +1,47 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dependency + +import ( + "context" + + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// WrapAndReplaceType will invoke the provided dependency mapper and then replace +// the type of all generated requests with the desired type. +func WrapAndReplaceType(desiredType *pbresource.Type, mapper controller.DependencyMapper) controller.DependencyMapper { + return func(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + reqs, err := mapper(ctx, rt, res) + if err != nil { + return nil, err + } + + for idx, req := range reqs { + req.ID = resource.ReplaceType(desiredType, req.ID) + reqs[idx] = req + } + return reqs, nil + } +} + +// MultiMapper can be used to concatenate the results of multiple dependency mappers. This +// helps to allow composition of different relationships without having to implement larger +// functions to perform all the various mappings. The goal here being to enable more reusuable +// dependency mappers. +func MultiMapper(mappers ...controller.DependencyMapper) controller.DependencyMapper { + return func(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + var results []controller.Request + for _, mapper := range mappers { + reqs, err := mapper(ctx, rt, res) + if err != nil { + return nil, err + } + results = append(results, reqs...) + } + return results, nil + } +} diff --git a/internal/controller/dependency/higher_order_test.go b/internal/controller/dependency/higher_order_test.go new file mode 100644 index 000000000000..03022356464b --- /dev/null +++ b/internal/controller/dependency/higher_order_test.go @@ -0,0 +1,144 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dependency + +import ( + "context" + "errors" + "testing" + + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/controller/controllermock" + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" +) + +var ( + fakeMapType = &pbresource.Type{ + Group: "testing", + GroupVersion: "v1", + Kind: "pre-map", + } + + fakeResourceType = &pbresource.Type{ + Group: "testing", + GroupVersion: "v1", + Kind: "fake", + } + + altFakeResourceType = &pbresource.Type{ + Group: "testing", + GroupVersion: "v1", + Kind: "alt-fake", + } + + injectedErr = errors.New("injected") +) + +func TestWrapAndReplaceType(t *testing.T) { + res := resourcetest.Resource(fakeMapType, "something").Build() + // populating the runtime with something so we can tell that + // the runtime is passed through + rt := controller.Runtime{ + Logger: hclog.Default(), + } + + t.Run("ok", func(t *testing.T) { + mm := controllermock.NewDependencyMapper(t) + mm.EXPECT(). + Execute(mock.Anything, rt, res). + Return([]controller.Request{ + {ID: resourceID("testing", "v1", "fake", "foo")}, + {ID: resourceID("testing", "v1", "fake", "bar")}, + }, nil). + Once() + + mapper := WrapAndReplaceType(altFakeResourceType, mm.Execute) + reqs, err := mapper(context.Background(), rt, res) + require.NoError(t, err) + require.Len(t, reqs, 2) + expected := []controller.Request{ + {ID: resourceID("testing", "v1", "alt-fake", "foo")}, + {ID: resourceID("testing", "v1", "alt-fake", "bar")}, + } + prototest.AssertElementsMatch(t, expected, reqs) + }) + + t.Run("err", func(t *testing.T) { + mm := controllermock.NewDependencyMapper(t) + mm.EXPECT(). + Execute(mock.Anything, rt, res). + Return(nil, injectedErr). + Once() + mapper := WrapAndReplaceType(altFakeResourceType, mm.Execute) + reqs, err := mapper(context.Background(), rt, res) + require.Nil(t, reqs) + require.ErrorIs(t, err, injectedErr) + }) +} + +func TestMultiMapper(t *testing.T) { + res := resourcetest.Resource(fakeMapType, "something").Build() + // populating the runtime with something so we can tell that + // the runtime is passed through + rt := controller.Runtime{ + Logger: hclog.Default(), + } + + t.Run("ok", func(t *testing.T) { + mockMapper := controllermock.NewDependencyMapper(t) + mockMapper.EXPECT(). + Execute(mock.Anything, rt, res). + Return([]controller.Request{ + {ID: resourceID("testing", "v1", "fake", "foo")}, + {ID: resourceID("testing", "v1", "fake", "bar")}, + }, nil). + Times(2) + + mm := MultiMapper( + mockMapper.Execute, + WrapAndReplaceType(altFakeResourceType, mockMapper.Execute), + ) + + reqs, err := mm(context.Background(), rt, res) + require.NoError(t, err) + require.Len(t, reqs, 4) + expected := []controller.Request{ + {ID: resourceID("testing", "v1", "alt-fake", "foo")}, + {ID: resourceID("testing", "v1", "alt-fake", "bar")}, + {ID: resourceID("testing", "v1", "fake", "foo")}, + {ID: resourceID("testing", "v1", "fake", "bar")}, + } + prototest.AssertElementsMatch(t, expected, reqs) + }) + + t.Run("err", func(t *testing.T) { + mockMapper := controllermock.NewDependencyMapper(t) + mockMapper.EXPECT(). + Execute(mock.Anything, rt, res). + Return([]controller.Request{ + {ID: resourceID("testing", "v1", "fake", "foo")}, + {ID: resourceID("testing", "v1", "fake", "bar")}, + }, nil). + Once() + + mockMapper.EXPECT(). + Execute(mock.Anything, rt, res). + Return(nil, injectedErr). + Once() + + mm := MultiMapper( + mockMapper.Execute, + WrapAndReplaceType(altFakeResourceType, mockMapper.Execute), + ) + reqs, err := mm(context.Background(), rt, res) + require.Nil(t, reqs) + require.ErrorIs(t, err, injectedErr) + }) +} diff --git a/internal/controller/dependency/simple.go b/internal/controller/dependency/simple.go new file mode 100644 index 000000000000..93284ac5df87 --- /dev/null +++ b/internal/controller/dependency/simple.go @@ -0,0 +1,68 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dependency + +import ( + "context" + + "google.golang.org/protobuf/proto" + + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// MapOwner implements a DependencyMapper that returns the updated resource's owner. +func MapOwner(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + var reqs []controller.Request + if res.Owner != nil { + reqs = append(reqs, controller.Request{ID: res.Owner}) + } + return reqs, nil +} + +// MapOwnerFiltered creates a DependencyMapper that returns owner IDs as Requests +// if the type of the owner ID matches the given filter type. +func MapOwnerFiltered(filter *pbresource.Type) controller.DependencyMapper { + return func(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + if res.Owner == nil { + return nil, nil + } + + if !resource.EqualType(res.Owner.GetType(), filter) { + return nil, nil + } + + return []controller.Request{{ID: res.Owner}}, nil + } +} + +// ReplaceType creates a DependencyMapper that returns request IDs with the same +// name and tenancy as the original resource but with the type replaced with +// the type specified as this functions parameter. +func ReplaceType(desiredType *pbresource.Type) controller.DependencyMapper { + return func(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + return []controller.Request{ + { + ID: &pbresource.ID{ + Type: desiredType, + Tenancy: res.Id.Tenancy, + Name: res.Id.Name, + }, + }, + }, nil + } +} + +type DecodedDependencyMapper[T proto.Message] func(context.Context, controller.Runtime, *resource.DecodedResource[T]) ([]controller.Request, error) + +func MapDecoded[T proto.Message](mapper DecodedDependencyMapper[T]) controller.DependencyMapper { + return func(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + decoded, err := resource.Decode[T](res) + if err != nil { + return nil, err + } + return mapper(ctx, rt, decoded) + } +} diff --git a/internal/controller/dependency/simple_test.go b/internal/controller/dependency/simple_test.go new file mode 100644 index 000000000000..b5a671a5cbc5 --- /dev/null +++ b/internal/controller/dependency/simple_test.go @@ -0,0 +1,192 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dependency + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v1" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/hashicorp/consul/sdk/testutil" +) + +func resourceID(group string, version string, kind string, name string) *pbresource.ID { + return &pbresource.ID{ + Type: &pbresource.Type{ + Group: group, + GroupVersion: version, + Kind: kind, + }, + Tenancy: &pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + }, + Name: name, + } +} + +func TestMapOwner(t *testing.T) { + owner := resourceID("foo", "v99", "bar", "object") + + res := &pbresource.Resource{ + Id: resourceID("something", "v1", "else", "x"), + Owner: owner, + } + + reqs, err := MapOwner(context.Background(), controller.Runtime{}, res) + require.NoError(t, err) + require.Len(t, reqs, 1) + prototest.AssertDeepEqual(t, owner, reqs[0].ID) +} + +func TestMapOwnerFiltered(t *testing.T) { + mapper := MapOwnerFiltered(&pbresource.Type{ + Group: "foo", + GroupVersion: "v1", + Kind: "bar", + }) + + type testCase struct { + owner *pbresource.ID + matches bool + } + + cases := map[string]testCase{ + "nil-owner": { + owner: nil, + matches: false, + }, + "group-mismatch": { + owner: resourceID("other", "v1", "bar", "irrelevant"), + matches: false, + }, + "group-version-mismatch": { + owner: resourceID("foo", "v2", "bar", "irrelevant"), + matches: false, + }, + "kind-mismatch": { + owner: resourceID("foo", "v1", "baz", "irrelevant"), + matches: false, + }, + "match": { + owner: resourceID("foo", "v1", "bar", "irrelevant"), + matches: true, + }, + } + + for name, tcase := range cases { + t.Run(name, func(t *testing.T) { + // the runtime is not used by the mapper so its fine to pass an empty struct + req, err := mapper(context.Background(), controller.Runtime{}, &pbresource.Resource{ + Id: resourceID("foo", "v1", "other", "x"), + Owner: tcase.owner, + }) + + // The mapper has no error paths at present + require.NoError(t, err) + + if tcase.matches { + require.NotNil(t, req) + require.Len(t, req, 1) + prototest.AssertDeepEqual(t, req[0].ID, tcase.owner, cmpopts.EquateEmpty()) + } else { + require.Nil(t, req) + } + }) + } +} + +func TestReplaceType(t *testing.T) { + rtype := &pbresource.Type{ + Group: "foo", + GroupVersion: "v1", + Kind: "bar", + } + + tenant := &pbresource.Tenancy{ + Partition: "not", + Namespace: "using", + } + + in := &pbresource.Resource{ + Id: &pbresource.ID{ + Type: &pbresource.Type{ + Group: "other", + GroupVersion: "v2", + Kind: "baz", + }, + Tenancy: tenant, + Name: "arr-matey", + }, + } + + mapper := ReplaceType(rtype) + + reqs, err := mapper(nil, controller.Runtime{}, in) + require.NoError(t, err) + require.Len(t, reqs, 1) + + expected := &pbresource.ID{ + Type: rtype, + Tenancy: tenant, + Name: "arr-matey", + } + prototest.AssertDeepEqual(t, expected, reqs[0].ID) +} + +func TestMapDecoded(t *testing.T) { + mapper := MapDecoded[*pbdemo.Artist](func(_ context.Context, _ controller.Runtime, res *resource.DecodedResource[*pbdemo.Artist]) ([]controller.Request, error) { + return []controller.Request{ + { + ID: &pbresource.ID{ + Type: res.Id.Type, + Tenancy: res.Id.Tenancy, + // not realistic for how the Artist's Name is intended but we just want to pull + // some data out of the decoded portion and return it. + Name: res.Data.Name, + }, + }, + }, nil + }) + + for _, tenancy := range resourcetest.TestTenancies() { + t.Run(resourcetest.AppendTenancyInfo(t.Name(), tenancy), func(t *testing.T) { + ctx := testutil.TestContext(t) + + res1 := resourcetest.Resource(pbdemo.ArtistType, "foo"). + WithTenancy(tenancy). + WithData(t, &pbdemo.Artist{Name: "something"}). + Build() + + res2 := resourcetest.Resource(pbdemo.ArtistType, "foo"). + WithTenancy(tenancy). + // Wrong data type here to force an error in the outer decoder + WithData(t, &pbdemo.Album{Name: "else"}). + Build() + + reqs, err := mapper(ctx, controller.Runtime{}, res1) + require.NoError(t, err) + require.Len(t, reqs, 1) + + expected := &pbresource.ID{ + Type: res1.Id.Type, + Tenancy: res1.Id.Tenancy, + Name: "something", + } + prototest.AssertDeepEqual(t, expected, reqs[0].ID) + + reqs, err = mapper(ctx, controller.Runtime{}, res2) + require.Nil(t, reqs) + require.Error(t, err) + }) + } +} diff --git a/internal/controller/dependency/transform.go b/internal/controller/dependency/transform.go new file mode 100644 index 000000000000..9edff3fb81bf --- /dev/null +++ b/internal/controller/dependency/transform.go @@ -0,0 +1,74 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dependency + +import ( + "context" + + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// DependencyTransform is used when the incoming resource from a watch needs to +// be transformed to a different resource or set of resources and then have +// a DependencyMapper executed on each element in that result set. This should +// only be needed for dealing with more complex dependency relationships where +// the managed type and watched type are not directly related. +type DependencyTransform func( + ctx context.Context, + rt controller.Runtime, + res *pbresource.Resource, +) ([]*pbresource.Resource, error) + +// MapperWithTransform will execute the provided DependencyTransform and then execute +// the provided DependencyMapper once for each of the resources output by the transform. +// The DependencyMapper outputs will then be concatenated together to form the whole +// set of mapped Requests. +func MapperWithTransform(mapper controller.DependencyMapper, transform DependencyTransform) controller.DependencyMapper { + return func(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + transformed, err := transform(ctx, rt, res) + if err != nil { + return nil, err + } + + var reqs []controller.Request + for _, res := range transformed { + newReqs, err := mapper(ctx, rt, res) + if err != nil { + return nil, err + } + + reqs = append(reqs, newReqs...) + } + + return reqs, nil + } +} + +// TransformChain takes a set of transformers and will execute them as a pipeline. +// The first transformer will output some resources. Those resources will then be +// used as inputs to the next transform. The chain will then continue until all +// transformers have been run. +func TransformChain(transformers ...DependencyTransform) DependencyTransform { + return func(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]*pbresource.Resource, error) { + toTransform := []*pbresource.Resource{res} + + for _, transform := range transformers { + var nextResources []*pbresource.Resource + + for _, res := range toTransform { + next, err := transform(ctx, rt, res) + if err != nil { + return nil, err + } + + nextResources = append(nextResources, next...) + } + + toTransform = nextResources + } + + return toTransform, nil + } +} diff --git a/internal/controller/dependency/transform_test.go b/internal/controller/dependency/transform_test.go new file mode 100644 index 000000000000..abdc9f991966 --- /dev/null +++ b/internal/controller/dependency/transform_test.go @@ -0,0 +1,166 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dependency + +import ( + "context" + "testing" + + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/controller/controllermock" + "github.com/hashicorp/consul/internal/controller/dependency/dependencymock" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestMapperWithTransform(t *testing.T) { + res := resourcetest.Resource(fakeMapType, "something").Build() + rt := controller.Runtime{ + // populating some field to differentiate from zero value + Logger: hclog.Default(), + } + transformed1 := resourcetest.Resource(fakeResourceType, "foo").Build() + transformed2 := resourcetest.Resource(fakeResourceType, "bar").Build() + + t.Run("transform-err", func(t *testing.T) { + mockTransform := dependencymock.NewDependencyTransform(t) + mockTransform.EXPECT(). + Execute(mock.Anything, rt, res). + Return(nil, injectedErr). + Once() + + mockMapper := controllermock.NewDependencyMapper(t) + + mt := MapperWithTransform(mockMapper.Execute, mockTransform.Execute) + reqs, err := mt(context.Background(), rt, res) + require.Nil(t, reqs) + require.ErrorIs(t, err, injectedErr) + }) + + t.Run("mapper-err", func(t *testing.T) { + mockTransform := dependencymock.NewDependencyTransform(t) + mockTransform.EXPECT(). + Execute(mock.Anything, rt, res). + Return([]*pbresource.Resource{transformed1, transformed2}, nil). + Once() + + mockMapper := controllermock.NewDependencyMapper(t) + mockMapper.EXPECT(). + Execute(mock.Anything, rt, transformed1). + Return(nil, injectedErr). + Once() + + mt := MapperWithTransform(mockMapper.Execute, mockTransform.Execute) + reqs, err := mt(context.Background(), rt, res) + require.Nil(t, reqs) + require.ErrorIs(t, err, injectedErr) + }) + + t.Run("ok", func(t *testing.T) { + mockTransform := dependencymock.NewDependencyTransform(t) + mockTransform.EXPECT(). + Execute(mock.Anything, rt, res). + Return([]*pbresource.Resource{transformed1, transformed2}, nil). + Once() + + mockMapper := controllermock.NewDependencyMapper(t) + mockMapper.EXPECT(). + Execute(mock.Anything, rt, transformed1). + Return([]controller.Request{ + {ID: resourceID("testing", "v1", "alt-fake", "foo")}, + {ID: resourceID("testing", "v1", "alt-fake", "bar")}, + }, nil). + Once() + + mockMapper.EXPECT(). + Execute(mock.Anything, rt, transformed2). + Return([]controller.Request{ + {ID: resourceID("testing", "v1", "alt-fake", "foo2")}, + {ID: resourceID("testing", "v1", "alt-fake", "bar2")}, + }, nil). + Once() + + mt := MapperWithTransform(mockMapper.Execute, mockTransform.Execute) + reqs, err := mt(context.Background(), rt, res) + require.NoError(t, err) + require.Len(t, reqs, 4) + expected := []controller.Request{ + {ID: resourceID("testing", "v1", "alt-fake", "foo")}, + {ID: resourceID("testing", "v1", "alt-fake", "bar")}, + {ID: resourceID("testing", "v1", "alt-fake", "foo2")}, + {ID: resourceID("testing", "v1", "alt-fake", "bar2")}, + } + prototest.AssertElementsMatch(t, expected, reqs) + }) +} + +func TestTransformChain(t *testing.T) { + res := resourcetest.Resource(fakeMapType, "something").Build() + rt := controller.Runtime{ + // populating some field to differentiate from zero value + Logger: hclog.Default(), + } + transformed1 := resourcetest.Resource(fakeResourceType, "foo").Build() + transformed2 := resourcetest.Resource(fakeResourceType, "bar").Build() + + out1 := resourcetest.Resource(altFakeResourceType, "foo").Build() + out2 := resourcetest.Resource(altFakeResourceType, "bar").Build() + out3 := resourcetest.Resource(altFakeResourceType, "baz").Build() + + t.Run("err", func(t *testing.T) { + mockTransform := dependencymock.NewDependencyTransform(t) + mockTransform.EXPECT(). + Execute(mock.Anything, rt, res). + Return([]*pbresource.Resource{transformed1}, nil). + Once() + mockTransform.EXPECT(). + Execute(mock.Anything, rt, transformed1). + Return(nil, injectedErr). + Once() + + resources, err := TransformChain(mockTransform.Execute, mockTransform.Execute)( + context.Background(), + rt, + res, + ) + + require.Nil(t, resources) + require.ErrorIs(t, err, injectedErr) + }) + + t.Run("ok", func(t *testing.T) { + mockTransform := dependencymock.NewDependencyTransform(t) + // Transform Chain + // + // 1. Transform original res to the two outputs + // 2. Transform the first output from 1 + // 3. Transform the second output from 1 + mockTransform.EXPECT(). + Execute(mock.Anything, rt, res). + Return([]*pbresource.Resource{transformed1, transformed2}, nil). + Once() + mockTransform.EXPECT(). + Execute(mock.Anything, rt, transformed1). + Return([]*pbresource.Resource{out1, out2}, nil). + Once() + mockTransform.EXPECT(). + Execute(mock.Anything, rt, transformed2). + Return([]*pbresource.Resource{out3}, nil). + Once() + + resources, err := TransformChain(mockTransform.Execute, mockTransform.Execute)( + context.Background(), + rt, + res, + ) + + require.NoError(t, err) + expected := []*pbresource.Resource{out1, out2, out3} + prototest.AssertElementsMatch(t, expected, resources) + }) +} diff --git a/internal/controller/dependency_mappers.go b/internal/controller/dependency_mappers.go deleted file mode 100644 index 1ac331ffafdd..000000000000 --- a/internal/controller/dependency_mappers.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package controller - -import ( - "context" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// DependencyMapper is called when a dependency watched via WithWatch is changed -// to determine which of the controller's managed resources need to be reconciled. -type DependencyMapper func( - ctx context.Context, - rt Runtime, - res *pbresource.Resource, -) ([]Request, error) - -// CustomDependencyMapper is called when an Event occurs to determine which of the -// controller's managed resources need to be reconciled. -type CustomDependencyMapper func( - ctx context.Context, - rt Runtime, - event Event, -) ([]Request, error) - -// MapOwner implements a DependencyMapper that returns the updated resource's owner. -func MapOwner(_ context.Context, _ Runtime, res *pbresource.Resource) ([]Request, error) { - var reqs []Request - if res.Owner != nil { - reqs = append(reqs, Request{ID: res.Owner}) - } - return reqs, nil -} - -// MapOwnerFiltered creates a DependencyMapper that returns owner IDs as Requests -// if the type of the owner ID matches the given filter type. -func MapOwnerFiltered(filter *pbresource.Type) DependencyMapper { - return func(_ context.Context, _ Runtime, res *pbresource.Resource) ([]Request, error) { - if res.Owner == nil { - return nil, nil - } - - if !resource.EqualType(res.Owner.GetType(), filter) { - return nil, nil - } - - return []Request{{ID: res.Owner}}, nil - } -} - -// ReplaceType creates a DependencyMapper that returns request IDs with the same -// name and tenancy as the original resource but with the type replaced with -// the type specified as this functions parameter. -func ReplaceType(desiredType *pbresource.Type) DependencyMapper { - return func(_ context.Context, _ Runtime, res *pbresource.Resource) ([]Request, error) { - return []Request{ - { - ID: &pbresource.ID{ - Type: desiredType, - Tenancy: res.Id.Tenancy, - Name: res.Id.Name, - }, - }, - }, nil - } -} diff --git a/internal/controller/dependency_mappers_test.go b/internal/controller/dependency_mappers_test.go deleted file mode 100644 index b9956cdb71f4..000000000000 --- a/internal/controller/dependency_mappers_test.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package controller - -import ( - "context" - "testing" - - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/stretchr/testify/require" -) - -func resourceID(group string, version string, kind string, name string) *pbresource.ID { - return &pbresource.ID{ - Type: &pbresource.Type{ - Group: group, - GroupVersion: version, - Kind: kind, - }, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: name, - } -} - -func TestMapOwner(t *testing.T) { - owner := resourceID("foo", "v99", "bar", "object") - - res := &pbresource.Resource{ - Id: resourceID("something", "v1", "else", "x"), - Owner: owner, - } - - reqs, err := MapOwner(context.Background(), Runtime{}, res) - require.NoError(t, err) - require.Len(t, reqs, 1) - prototest.AssertDeepEqual(t, owner, reqs[0].ID) -} - -func TestMapOwnerFiltered(t *testing.T) { - mapper := MapOwnerFiltered(&pbresource.Type{ - Group: "foo", - GroupVersion: "v1", - Kind: "bar", - }) - - type testCase struct { - owner *pbresource.ID - matches bool - } - - cases := map[string]testCase{ - "nil-owner": { - owner: nil, - matches: false, - }, - "group-mismatch": { - owner: resourceID("other", "v1", "bar", "irrelevant"), - matches: false, - }, - "group-version-mismatch": { - owner: resourceID("foo", "v2", "bar", "irrelevant"), - matches: false, - }, - "kind-mismatch": { - owner: resourceID("foo", "v1", "baz", "irrelevant"), - matches: false, - }, - "match": { - owner: resourceID("foo", "v1", "bar", "irrelevant"), - matches: true, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - // the runtime is not used by the mapper so its fine to pass an empty struct - req, err := mapper(context.Background(), Runtime{}, &pbresource.Resource{ - Id: resourceID("foo", "v1", "other", "x"), - Owner: tcase.owner, - }) - - // The mapper has no error paths at present - require.NoError(t, err) - - if tcase.matches { - require.NotNil(t, req) - require.Len(t, req, 1) - prototest.AssertDeepEqual(t, req[0].ID, tcase.owner, cmpopts.EquateEmpty()) - } else { - require.Nil(t, req) - } - }) - } -} - -func TestReplaceType(t *testing.T) { - rtype := &pbresource.Type{ - Group: "foo", - GroupVersion: "v1", - Kind: "bar", - } - - tenant := &pbresource.Tenancy{ - Partition: "not", - Namespace: "using", - PeerName: "the-defaults", - } - - in := &pbresource.Resource{ - Id: &pbresource.ID{ - Type: &pbresource.Type{ - Group: "other", - GroupVersion: "v2", - Kind: "baz", - }, - Tenancy: tenant, - Name: "arr-matey", - }, - } - - mapper := ReplaceType(rtype) - - reqs, err := mapper(nil, Runtime{}, in) - require.NoError(t, err) - require.Len(t, reqs, 1) - - expected := &pbresource.ID{ - Type: rtype, - Tenancy: tenant, - Name: "arr-matey", - } - prototest.AssertDeepEqual(t, expected, reqs[0].ID) -} diff --git a/internal/controller/helper.go b/internal/controller/helper.go index 431ca5e6f3ce..f5fe9939a6ea 100644 --- a/internal/controller/helper.go +++ b/internal/controller/helper.go @@ -36,3 +36,36 @@ func MakeRequests[V resource.ReferenceOrID]( return out } + +// MakeRequestsFromResources accepts a list of items and converts them into a +// slice of []controller.Request items where the Type of the items has replaced +// by 'typ'. +func MakeRequestsFromResources[V interface { + GetId() *pbresource.ID +}]( + typ *pbresource.Type, + resources []V, +) []Request { + if len(resources) == 0 { + return nil + } + + out := make([]Request, 0, len(resources)) + for _, res := range resources { + id := res.GetId() + + // if type is not provided, we will use the type in the ID or reference. + if typ == nil { + typ = id.GetType() + } + out = append(out, Request{ + ID: &pbresource.ID{ + Type: typ, + Tenancy: id.GetTenancy(), + Name: id.GetName(), + }, + }) + } + + return out +} diff --git a/internal/controller/manager.go b/internal/controller/manager.go index 2e46b2140083..8e42bf6260af 100644 --- a/internal/controller/manager.go +++ b/internal/controller/manager.go @@ -23,7 +23,7 @@ type Manager struct { mu sync.Mutex running bool - controllers []Controller + controllers []*Controller leaseChans []chan struct{} } @@ -38,7 +38,7 @@ func NewManager(client pbresource.ResourceServiceClient, logger hclog.Logger) *M // Register the given controller to be executed by the Manager. Cannot be called // once the Manager is running. -func (m *Manager) Register(ctrl Controller) { +func (m *Manager) Register(ctrl *Controller) { m.mu.Lock() defer m.mu.Unlock() @@ -65,16 +65,7 @@ func (m *Manager) Run(ctx context.Context) { m.running = true for _, desc := range m.controllers { - logger := desc.logger - if logger == nil { - logger = m.logger.With("managed_type", desc.managedType.Kind) - } - - runner := &controllerRunner{ - ctrl: desc, - client: m.client, - logger: logger, - } + runner := newControllerRunner(desc, m.client, m.logger) go newSupervisor(runner.run, m.newLeaseLocked(desc)).run(ctx) } } @@ -100,7 +91,7 @@ func (m *Manager) SetRaftLeader(leader bool) { } } -func (m *Manager) newLeaseLocked(ctrl Controller) Lease { +func (m *Manager) newLeaseLocked(ctrl *Controller) Lease { if ctrl.placement == PlacementEachServer { return eternalLease{} } diff --git a/internal/controller/mem_consistency_test.go b/internal/controller/mem_consistency_test.go new file mode 100644 index 000000000000..d61b2767723d --- /dev/null +++ b/internal/controller/mem_consistency_test.go @@ -0,0 +1,374 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package controller + +import ( + "context" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" + + mockpbresource "github.com/hashicorp/consul/grpcmocks/proto-public/pbresource" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/resource/resourcetest" + "github.com/hashicorp/consul/internal/storage" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/hashicorp/consul/sdk/testutil" +) + +var ( + fakeType = &pbresource.Type{ + Group: "testing", + GroupVersion: "v1", + Kind: "Fake", + } + + fakeV2Type = &pbresource.Type{ + Group: "testing", + GroupVersion: "v2", + Kind: "Fake", + } +) + +type memCheckResult struct { + clientGet *pbresource.Resource + clientGetError error + cacheGet *pbresource.Resource + cacheGetError error +} + +type memCheckReconciler struct { + mu sync.Mutex + closed bool + reconcileCh chan memCheckResult + mapCh chan memCheckResult +} + +func newMemCheckReconciler(t testutil.TestingTB) *memCheckReconciler { + t.Helper() + + r := &memCheckReconciler{ + reconcileCh: make(chan memCheckResult, 10), + mapCh: make(chan memCheckResult, 10), + } + + t.Cleanup(r.Shutdown) + return r +} + +func (r *memCheckReconciler) Shutdown() { + r.mu.Lock() + defer r.mu.Unlock() + r.closed = true + close(r.reconcileCh) + close(r.mapCh) +} + +func (r *memCheckReconciler) requireNotClosed(t testutil.TestingTB) { + t.Helper() + if r.closed { + require.FailNow(t, "the memCheckReconciler has been closed") + } +} + +func (r *memCheckReconciler) checkReconcileResult(t testutil.TestingTB, ctx context.Context, res *pbresource.Resource) { + t.Helper() + r.requireEqualNotSameMemCheckResult(t, ctx, r.reconcileCh, res) +} + +func (r *memCheckReconciler) checkMapResult(t testutil.TestingTB, ctx context.Context, res *pbresource.Resource) { + t.Helper() + r.requireEqualNotSameMemCheckResult(t, ctx, r.mapCh, res) +} + +func (r *memCheckReconciler) requireEqualNotSameMemCheckResult(t testutil.TestingTB, ctx context.Context, ch <-chan memCheckResult, res *pbresource.Resource) { + t.Helper() + + select { + case result := <-ch: + require.NoError(t, result.clientGetError) + require.NoError(t, result.cacheGetError) + // Equal but NotSame means the values are all the same but + // the pointers are different. Note that this probably doesn't + // check that the values within the resource haven't been shallow + // copied but that probably should be checked elsewhere + prototest.AssertDeepEqual(t, res, result.clientGet) + require.NotSame(t, res, result.clientGet) + prototest.AssertDeepEqual(t, res, result.cacheGet) + require.NotSame(t, res, result.cacheGet) + case <-ctx.Done(): + require.Fail(t, "didn't receive mem check result before context cancellation", ctx.Err()) + } +} + +func (r *memCheckReconciler) Reconcile(ctx context.Context, rt Runtime, req Request) error { + r.mu.Lock() + defer r.mu.Unlock() + if !r.closed { + r.getAndSend(ctx, rt, req.ID, r.reconcileCh) + } + return nil +} + +func (r *memCheckReconciler) MapToNothing( + ctx context.Context, + rt Runtime, + res *pbresource.Resource, +) ([]Request, error) { + r.mu.Lock() + defer r.mu.Unlock() + if !r.closed { + r.getAndSend(ctx, rt, res.Id, r.mapCh) + } + return nil, nil +} + +func (*memCheckReconciler) getAndSend(ctx context.Context, rt Runtime, id *pbresource.ID, ch chan<- memCheckResult) { + var res memCheckResult + response, err := rt.Client.Read(ctx, &pbresource.ReadRequest{ + Id: id, + }) + res.clientGetError = err + if response != nil { + res.clientGet = response.Resource + } + + res.cacheGet, res.cacheGetError = rt.Cache.Get(id.Type, "id", id) + + ch <- res +} + +func watchListEvents(t testutil.TestingTB, events ...*pbresource.WatchEvent) pbresource.ResourceService_WatchListClient { + t.Helper() + ctx := testutil.TestContext(t) + + watchListClient := mockpbresource.NewResourceService_WatchListClient(t) + + // Return the events in the specified order as soon as they are requested + for _, event := range events { + evt := event + watchListClient.EXPECT(). + Recv(). + RunAndReturn(func() (*pbresource.WatchEvent, error) { + return evt, nil + }). + Once() + } + + watchListClient.EXPECT(). + Recv(). + RunAndReturn(func() (*pbresource.WatchEvent, error) { + return &pbresource.WatchEvent{ + Event: &pbresource.WatchEvent_EndOfSnapshot_{ + EndOfSnapshot: &pbresource.WatchEvent_EndOfSnapshot{}, + }, + }, nil + }). + Once() + + // Now that all specified events have been exhausted we loop until the test finishes + // and the context bound to the tests lifecycle has been cancelled. This prevents getting + // any weird errors from the controller manager/runner. + watchListClient.EXPECT(). + Recv(). + RunAndReturn(func() (*pbresource.WatchEvent, error) { + <-ctx.Done() + return nil, ctx.Err() + }). + Maybe() + + return watchListClient +} + +// TestControllerRuntimeMemoryCloning mainly is testing that the runtimes +// provided to reconcilers and dependency mappers will return data from +// the resource service client and the cache that have been cloned so that +// the controller should be free to modify the data as needed. +func TestControllerRuntimeMemoryCloning(t *testing.T) { + ctx := testutil.TestContext(t) + + // create some resources to use during the test + res1 := resourcetest.Resource(fakeType, "foo"). + WithTenancy(resource.DefaultNamespacedTenancy()). + Build() + res2 := resourcetest.Resource(fakeV2Type, "bar"). + WithTenancy(resource.DefaultNamespacedTenancy()). + Build() + + // create the reconciler that will read the desired resource + // from both the resource service client and the cache client. + reconciler := newMemCheckReconciler(t) + + // Create the v1 watch list client to be returned when the controller runner + // calls WatchList on the v1 testing type. + v1WatchListClientCreate := func() pbresource.ResourceService_WatchListClient { + return watchListEvents(t, &pbresource.WatchEvent{ + Event: &pbresource.WatchEvent_Upsert_{ + Upsert: &pbresource.WatchEvent_Upsert{ + Resource: res1, + }, + }, + }) + } + + // Create the v2 watch list client to be returned when the controller runner + // calls WatchList on the v2 testing type. + v2WatchListClientCreate := func() pbresource.ResourceService_WatchListClient { + return watchListEvents(t, nil, &pbresource.WatchEvent{ + Event: &pbresource.WatchEvent_Upsert_{ + Upsert: &pbresource.WatchEvent_Upsert{ + Resource: res2, + }, + }, + }) + } + + // Create the mock resource service client + mres := mockpbresource.NewResourceServiceClient(t) + // Setup the expectation for the controller runner to issue a WatchList + // request for the managed type (fake v2 type) + mres.EXPECT(). + WatchList(mock.Anything, &pbresource.WatchListRequest{ + Type: fakeV2Type, + Tenancy: &pbresource.Tenancy{ + Partition: storage.Wildcard, + Namespace: storage.Wildcard, + }, + }). + RunAndReturn(func(_ context.Context, _ *pbresource.WatchListRequest, _ ...grpc.CallOption) (pbresource.ResourceService_WatchListClient, error) { + return v2WatchListClientCreate(), nil + }). + Twice() // once for cache prime, once for the rest + + // Setup the expectation for the controller runner to issue a WatchList + // request for the secondary Watch type (fake v1 type) + mres.EXPECT(). + WatchList(mock.Anything, &pbresource.WatchListRequest{ + Type: fakeType, + Tenancy: &pbresource.Tenancy{ + Partition: storage.Wildcard, + Namespace: storage.Wildcard, + }, + }). + RunAndReturn(func(_ context.Context, _ *pbresource.WatchListRequest, _ ...grpc.CallOption) (pbresource.ResourceService_WatchListClient, error) { + return v1WatchListClientCreate(), nil + }). + Twice() // once for cache prime, once for the rest + + // The cloning resource clients will forward actual calls onto the main resource service client. + // Here we are configuring the service mock to return either of the resources depending on the + // id present in the request. + mres.EXPECT(). + Read(mock.Anything, mock.Anything). + RunAndReturn(func(_ context.Context, req *pbresource.ReadRequest, opts ...grpc.CallOption) (*pbresource.ReadResponse, error) { + res := res2 + if resource.EqualID(res1.Id, req.Id) { + res = res1 + } + return &pbresource.ReadResponse{Resource: res}, nil + }). + Times(0) + + // create the test controller + ctl := NewController("test", fakeV2Type). + WithWatch(fakeType, reconciler.MapToNothing). + WithReconciler(reconciler) + + // create the controller manager and register our test controller + manager := NewManager(mres, testutil.Logger(t)) + manager.Register(ctl) + + // run the controller manager + manager.SetRaftLeader(true) + go manager.Run(ctx) + + // All future assertions should easily be able to run within 5s although they + // should typically run a couple orders of magnitude faster. + timeLimitedCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + t.Cleanup(cancel) + + // validate that the v2 resource type event was seen and that the + // cache and the resource service client return cloned resources + reconciler.checkReconcileResult(t, timeLimitedCtx, res2) + + // Validate that the dependency mapper's resource and cache clients return + // cloned resources. + reconciler.checkMapResult(t, timeLimitedCtx, res1) +} + +// TestRunnerSharedMemoryCache is mainly testing to ensure that resources +// within the cache are shared with the resource service and have not been +// cloned. +func TestControllerRunnerSharedMemoryCache(t *testing.T) { + ctx := testutil.TestContext(t) + + // create resource to use during the test + res := resourcetest.Resource(fakeV2Type, "bar"). + WithTenancy(resource.DefaultNamespacedTenancy()). + Build() + + // create the reconciler that will read the desired resource + // from both the resource service client and the cache client. + reconciler := newMemCheckReconciler(t) + + // Create the v2 watch list client to be returned when the controller runner + // calls WatchList on the v2 testing type. + v2WatchListClientCreate := func() pbresource.ResourceService_WatchListClient { + return watchListEvents(t, nil, &pbresource.WatchEvent{ + Event: &pbresource.WatchEvent_Upsert_{ + Upsert: &pbresource.WatchEvent_Upsert{ + Resource: res, + }, + }, + }) + } + + // Create the mock resource service client + mres := mockpbresource.NewResourceServiceClient(t) + // Setup the expectation for the controller runner to issue a WatchList + // request for the managed type (fake v2 type) + mres.EXPECT(). + WatchList(mock.Anything, &pbresource.WatchListRequest{ + Type: fakeV2Type, + Tenancy: &pbresource.Tenancy{ + Partition: storage.Wildcard, + Namespace: storage.Wildcard, + }, + }). + RunAndReturn(func(_ context.Context, _ *pbresource.WatchListRequest, _ ...grpc.CallOption) (pbresource.ResourceService_WatchListClient, error) { + return v2WatchListClientCreate(), nil + }). + Twice() // once for cache prime, once for the rest + + // The cloning resource clients will forward actual calls onto the main resource service client. + // Here we are configuring the service mock to return our singular resource always. + mres.EXPECT(). + Read(mock.Anything, mock.Anything). + Return(&pbresource.ReadResponse{Resource: res}, nil). + Times(0) + + // create the test controller + ctl := NewController("test", fakeV2Type). + WithReconciler(reconciler) + + runner := newControllerRunner(ctl, mres, testutil.Logger(t)) + go runner.run(ctx) + + // Wait for reconcile to be called before we check the values in + // the cache. This will also validate that the resource service client + // and cache client given to the reconciler cloned the resource but + // that is tested more thoroughly in another test and isn't of primary + // concern here. + reconciler.checkReconcileResult(t, ctx, res) + + // Now validate that the cache hold the same resource pointer as the original data + actual, err := runner.cache.Get(fakeV2Type, "id", res.Id) + require.NoError(t, err) + require.Same(t, res, actual) +} diff --git a/internal/controller/runner.go b/internal/controller/runner.go new file mode 100644 index 000000000000..6ec2d3568f46 --- /dev/null +++ b/internal/controller/runner.go @@ -0,0 +1,467 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package controller + +import ( + "context" + "errors" + "fmt" + "math/rand" + "time" + + "golang.org/x/sync/errgroup" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/hashicorp/go-hclog" + + "github.com/hashicorp/consul/agent/consul/controller/queue" + "github.com/hashicorp/consul/internal/controller/cache" + "github.com/hashicorp/consul/internal/protoutil" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/internal/storage" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// Runtime contains the dependencies required by reconcilers. +type Runtime struct { + Client pbresource.ResourceServiceClient + Logger hclog.Logger + Cache cache.ReadOnlyCache +} + +// controllerRunner contains the actual implementation of running a controller +// including creating watches, calling the reconciler, handling retries, etc. +type controllerRunner struct { + ctrl *Controller + // watchClient will be used by the controller infrastructure internally to + // perform watches and maintain the cache. On servers, this client will use + // the in-memory gRPC clients which DO NOT cause cloning of data returned by + // the resource service. This is desirable so that our cache doesn't incur + // the overhead of duplicating all resources that are watched. Generally + // dependency mappers and reconcilers should not be given this client so + // that they can be free to modify the data they are returned. + watchClient pbresource.ResourceServiceClient + // runtimeClient will be used by dependency mappers and reconcilers to + // access the resource service. On servers, this client will use the in-memory + // gRPC client wrapped with the cloning client to force cloning of protobuf + // messages as they pass through the client. This is desirable so that + // controllers and their mappers can be free to modify the data returned + // to them without having to think about the fact that the data should + // be immutable as it is shared with the controllers cache as well as the + // resource service itself. + runtimeClient pbresource.ResourceServiceClient + logger hclog.Logger + cache cache.Cache +} + +func newControllerRunner(c *Controller, client pbresource.ResourceServiceClient, defaultLogger hclog.Logger) *controllerRunner { + return &controllerRunner{ + ctrl: c, + watchClient: client, + runtimeClient: pbresource.NewCloningResourceServiceClient(client), + logger: c.buildLogger(defaultLogger), + // Do not build the cache here. If we build/set it when the controller runs + // then if a controller is restarted it will invalidate the previous cache automatically. + } +} + +func (cr *controllerRunner) run(ctx context.Context) error { + cr.logger.Debug("controller running") + defer cr.logger.Debug("controller stopping") + + // Initialize the controller if required + if cr.ctrl.initializer != nil { + cr.logger.Debug("controller initializing") + err := cr.ctrl.initializer.Initialize(ctx, cr.runtime(cr.logger)) + if err != nil { + return err + } + cr.logger.Debug("controller initialized") + } + + cr.cache = cr.ctrl.buildCache() + defer func() { + // once no longer running we should nil out the cache + // so that we don't hold pointers to resources which may + // become out of date in the future. + cr.cache = nil + }() + + if cr.ctrl.startCb != nil { + cr.ctrl.startCb(ctx, cr.runtime(cr.logger)) + } + + if cr.ctrl.stopCb != nil { + defer cr.ctrl.stopCb(ctx, cr.runtime(cr.logger)) + } + + // Before we launch the reconciler or the dependency mappers, ensure the + // cache is properly primed to avoid errant reconciles. + // + // Without doing this the cache is unsafe for general use without causing + // reconcile regressions in certain cases. + { + cr.logger.Debug("priming caches") + primeGroup, primeGroupCtx := errgroup.WithContext(ctx) + // Managed Type Events + primeGroup.Go(func() error { + return cr.primeCache(primeGroupCtx, cr.ctrl.managedTypeWatch.watchedType) + }) + for _, w := range cr.ctrl.watches { + watcher := w + // Watched Type Events + primeGroup.Go(func() error { + return cr.primeCache(primeGroupCtx, watcher.watchedType) + }) + } + + if err := primeGroup.Wait(); err != nil { + return err + } + cr.logger.Debug("priming caches complete") + } + + group, groupCtx := errgroup.WithContext(ctx) + recQueue := runQueue[Request](groupCtx, cr.ctrl) + + // Managed Type Events → Managed Type Reconciliation Queue + group.Go(func() error { + return cr.watch(groupCtx, cr.ctrl.managedTypeWatch.watchedType, func(res *pbresource.Resource) { + recQueue.Add(Request{ID: res.Id}) + }) + }) + + for _, w := range cr.ctrl.watches { + mapQueue := runQueue[mapperRequest](groupCtx, cr.ctrl) + watcher := w + + // Watched Type Events → Watched Type Mapper Queue + group.Go(func() error { + return cr.watch(groupCtx, watcher.watchedType, func(res *pbresource.Resource) { + mapQueue.Add(mapperRequest{res: res}) + }) + }) + + // Watched Type Mapper Queue → Watched Type Mapper → Managed Type Reconciliation Queue + group.Go(func() error { + return cr.runMapper(groupCtx, watcher, mapQueue, recQueue, func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error) { + return watcher.mapper(ctx, runtime, itemType.(mapperRequest).res) + }) + }) + } + + for _, cw := range cr.ctrl.customWatches { + customMapQueue := runQueue[Event](groupCtx, cr.ctrl) + watcher := cw + // Custom Events → Custom Mapper Queue + group.Go(func() error { + return watcher.source.Watch(groupCtx, func(e Event) { + customMapQueue.Add(e) + }) + }) + + // Custom Mapper Queue → Custom Dependency Mapper → Managed Type Reconciliation Queue + group.Go(func() error { + return cr.runCustomMapper(groupCtx, watcher, customMapQueue, recQueue, func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error) { + return watcher.mapper(ctx, runtime, itemType.(Event)) + }) + }) + } + + // Managed Type Reconciliation Queue → Reconciler + group.Go(func() error { + return cr.runReconciler(groupCtx, recQueue) + }) + + return group.Wait() +} + +func runQueue[T queue.ItemType](ctx context.Context, ctrl *Controller) queue.WorkQueue[T] { + base, max := ctrl.backoff() + return queue.RunWorkQueue[T](ctx, base, max) +} + +func (cr *controllerRunner) primeCache(ctx context.Context, typ *pbresource.Type) error { + wl, err := cr.watchClient.WatchList(ctx, &pbresource.WatchListRequest{ + Type: typ, + Tenancy: &pbresource.Tenancy{ + Partition: storage.Wildcard, + Namespace: storage.Wildcard, + }, + }) + if err != nil { + cr.handleInvalidControllerWatch(err) + cr.logger.Error("failed to create cache priming watch", "error", err) + return err + } + + for { + event, err := wl.Recv() + if err != nil { + cr.handleInvalidControllerWatch(err) + cr.logger.Warn("error received from cache priming watch", "error", err) + return err + } + + switch { + case event.GetUpsert() != nil: + cr.cache.Insert(event.GetUpsert().Resource) + case event.GetDelete() != nil: + cr.cache.Delete(event.GetDelete().Resource) + case event.GetEndOfSnapshot() != nil: + // This concludes the initial snapshot. The cache is primed. + return nil + default: + cr.logger.Warn("skipping unexpected event type", "type", hclog.Fmt("%T", event.GetEvent())) + continue + } + } +} + +func (cr *controllerRunner) watch(ctx context.Context, typ *pbresource.Type, add func(*pbresource.Resource)) error { + wl, err := cr.watchClient.WatchList(ctx, &pbresource.WatchListRequest{ + Type: typ, + Tenancy: &pbresource.Tenancy{ + Partition: storage.Wildcard, + Namespace: storage.Wildcard, + }, + }) + if err != nil { + cr.handleInvalidControllerWatch(err) + cr.logger.Error("failed to create watch", "error", err) + return err + } + + for { + event, err := wl.Recv() + if err != nil { + cr.handleInvalidControllerWatch(err) + cr.logger.Warn("error received from watch", "error", err) + return err + } + + // Keep the cache up to date. There main reason to do this here is + // to ensure that any mapper/reconciliation queue deduping won't + // hide events from being observed and updating the cache state. + // Therefore we should do this before any queueing. + var resource *pbresource.Resource + switch { + case event.GetUpsert() != nil: + resource = event.GetUpsert().GetResource() + cr.cache.Insert(resource) + case event.GetDelete() != nil: + resource = event.GetDelete().GetResource() + cr.cache.Delete(resource) + case event.GetEndOfSnapshot() != nil: + continue // ignore + default: + cr.logger.Warn("skipping unexpected event type", "type", hclog.Fmt("%T", event.GetEvent())) + continue + } + + // Before adding the resource into the queue we must clone it. + // While we want the cache to not have duplicate copies of all the + // data, we do want downstream consumers like dependency mappers and + // controllers to be able to freely modify the data they are given. + // Therefore we clone the resource here to prevent any accidental + // mutation of data held by the cache (and presumably by the resource + // service assuming that the regular client we were given is the inmem + // variant) + add(protoutil.Clone(resource)) + } +} + +func (cr *controllerRunner) runMapper( + ctx context.Context, + w *watch, + from queue.WorkQueue[mapperRequest], + to queue.WorkQueue[Request], + mapper func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error), +) error { + logger := cr.logger.With("watched_resource_type", resource.ToGVK(w.watchedType)) + + for { + item, shutdown := from.Get() + if shutdown { + return nil + } + + if err := cr.doMap(ctx, mapper, to, item, logger); err != nil { + from.AddRateLimited(item) + from.Done(item) + continue + } + + from.Forget(item) + from.Done(item) + } +} + +func (cr *controllerRunner) runCustomMapper( + ctx context.Context, + cw customWatch, + from queue.WorkQueue[Event], + to queue.WorkQueue[Request], + mapper func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error), +) error { + logger := cr.logger.With("watched_event", cw.source) + + for { + item, shutdown := from.Get() + if shutdown { + return nil + } + + if err := cr.doMap(ctx, mapper, to, item, logger); err != nil { + from.AddRateLimited(item) + from.Done(item) + continue + } + + from.Forget(item) + from.Done(item) + } +} + +func (cr *controllerRunner) doMap(ctx context.Context, mapper func(ctx context.Context, runtime Runtime, itemType queue.ItemType) ([]Request, error), to queue.WorkQueue[Request], item queue.ItemType, logger hclog.Logger) error { + var reqs []Request + if err := cr.handlePanic(func() error { + var err error + reqs, err = mapper(ctx, cr.runtime(logger.With("map-request-key", item.Key())), item) + return err + }); err != nil { + return err + } + + for _, r := range reqs { + if !resource.EqualType(r.ID.Type, cr.ctrl.managedTypeWatch.watchedType) { + logger.Error("dependency mapper returned request for a resource of the wrong type", + "type_expected", resource.ToGVK(cr.ctrl.managedTypeWatch.watchedType), + "type_got", resource.ToGVK(r.ID.Type), + ) + continue + } + to.Add(r) + } + return nil +} + +// maybeScheduleForcedReconcile makes sure that a "reconcile the world" happens periodically for the +// controller's managed type. +func (cr *controllerRunner) maybeScheduleForcedReconcile(queue queue.WorkQueue[Request], req Request) { + // In order to periodically "reconcile the world", we schedule a deferred reconcile request + // (aka forced reconcile) minus a sizeable random jitter to avoid a thundering herd. + // + // A few notes on how this integrates with existing non-"reconcile the world" requests: + // + // 1. Successful reconciles result in a new deferred "reconcile the world" request being scheduled. + // The net effect is that the managed type will be continually reconciled regardless of any updates. + // 2. Failed reconciles are re-queued with a rate limit and get added to the deferred reconcile queue. + // Any existing deferred "reconcile the world" request will be replaced by the rate-limited deferred + // request. + // 3. An existing deferred "reconcile the world" request can't be removed on the successful reconcile + // of a delete operation. We rely on controller idempotency to eventually process the deferred request + // as a no-op. + _, err := cr.runtimeClient.Read(context.Background(), &pbresource.ReadRequest{Id: req.ID}) + switch { + case err != nil && status.Code(err) == codes.NotFound: + // Resource was deleted -> nothing to force reconcile so do nothing + return + default: + // Reconcile of resource upsert was successful or we had an unexpected + // error. In either case, we should schedule a forced reconcile for completeness. + scheduleAt := reduceByRandomJitter(cr.ctrl.forceReconcileEvery) + queue.AddAfter(req, scheduleAt, true) + } +} + +// reduceByRandomJitter returns a duration reduced by a random amount up to 20%. +func reduceByRandomJitter(d time.Duration) time.Duration { + percent := rand.Float64() * 0.2 + reduction := time.Duration(float64(d) * percent) + return d - reduction +} + +func (cr *controllerRunner) runReconciler(ctx context.Context, queue queue.WorkQueue[Request]) error { + for { + req, shutdown := queue.Get() + if shutdown { + return nil + } + + cr.logger.Trace("handling request", "request", req) + err := cr.handlePanic(func() error { + return cr.ctrl.reconciler.Reconcile(ctx, cr.runtime(cr.logger.With("resource-id", req.ID.String())), req) + }) + if err == nil { + queue.Forget(req) + cr.maybeScheduleForcedReconcile(queue, req) + } else { + cr.logger.Trace("post-processing reconcile failure") + var requeueAfter RequeueAfterError + if errors.As(err, &requeueAfter) { + queue.Forget(req) + queue.AddAfter(req, time.Duration(requeueAfter), false) + } else { + queue.AddRateLimited(req) + } + } + queue.Done(req) + } +} + +func (cr *controllerRunner) handlePanic(fn func() error) (err error) { + defer func() { + if r := recover(); r != nil { + stack := hclog.Stacktrace() + cr.logger.Error("controller panic", + "panic", r, + "stack", stack, + ) + err = fmt.Errorf("panic [recovered]: %v", r) + return + } + }() + + return fn() +} + +func (cr *controllerRunner) runtime(logger hclog.Logger) Runtime { + return Runtime{ + // dependency mappers and controllers are always given the cloning client + // so that they do not have to care about mutating values that they read + // through the client. + Client: cr.runtimeClient, + Logger: logger, + // ensure that resources queried via the cache get cloned so that the + // dependency mapper or reconciler is free to modify them. + Cache: cache.NewCloningReadOnlyCache(cr.cache), + } +} + +func (cr *controllerRunner) handleInvalidControllerWatch(err error) { + st, ok := status.FromError(err) + if ok && st.Code() == codes.InvalidArgument { + panic(fmt.Sprintf("controller %s attempted to initiate an invalid watch: %q. This is a bug within the controller.", cr.ctrl.name, err.Error())) + } +} + +type mapperRequest struct { + // res is the resource that was watched and is being mapped. + res *pbresource.Resource +} + +// Key satisfies the queue.ItemType interface. It returns a string which will be +// used to de-duplicate requests in the queue. +func (i mapperRequest) Key() string { + return fmt.Sprintf( + "type=%q,part=%q,ns=%q,name=%q,uid=%q", + resource.ToGVK(i.res.Id.Type), + i.res.Id.Tenancy.Partition, + i.res.Id.Tenancy.Namespace, + i.res.Id.Name, + i.res.Id.Uid, + ) +} diff --git a/internal/controller/testing.go b/internal/controller/testing.go new file mode 100644 index 000000000000..1f7fb9ce348f --- /dev/null +++ b/internal/controller/testing.go @@ -0,0 +1,79 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package controller + +import ( + "context" + + "github.com/hashicorp/go-hclog" + + "github.com/hashicorp/consul/internal/controller/cache" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// TestController is most useful when writing unit tests for a controller where +// individual Reconcile calls need to be made instead of having a Manager +// execute the controller in response to watch events. +// +// TODO(controller-testing) Ideally this would live within the controllertest +// package. However it makes light use of unexported fields on the Controller +// and therefore cannot live in another package without more refactorings +// to have the Controller include a config struct of sorts defined in an +// internal package with exported fields. For now this seems fine. +type TestController struct { + c *Controller + cache cache.Cache + client pbresource.ResourceServiceClient + logger hclog.Logger +} + +// NewTestController will create a new TestController from the provided Controller +// and ResourceServiceClient. The test controller will build the controllers +// cache with the configured indexes and will maintain the cached state in response +// to Write, WriteStatus and Delete calls made on the wrapped ResourceServiceClient. +// Call the Runtime() method to get at the wrapped client. +func NewTestController(ctl *Controller, client pbresource.ResourceServiceClient) *TestController { + ctlCache := ctl.buildCache() + return &TestController{ + c: ctl, + cache: ctlCache, + client: cache.NewCachedClient(ctlCache, client), + logger: ctl.buildLogger(hclog.NewNullLogger()), + } +} + +func (tc *TestController) WithLogger(logger hclog.Logger) *TestController { + tc.logger = tc.c.buildLogger(logger) + return tc +} + +// Reconcile invokes the controllers configured reconciler with the cache enabled Runtime +func (tc *TestController) Reconcile(ctx context.Context, req Request) error { + return tc.c.reconciler.Reconcile(ctx, tc.Runtime(), req) +} + +// Reconciler returns the controllers configured reconciler +func (tc *TestController) Reconciler() Reconciler { + return tc.c.reconciler +} + +// Runtime returns the Runtime that should be used for calls to reconcile or to perform +// operations that would also affect the managed cache. +func (tc *TestController) Runtime() Runtime { + return Runtime{ + Client: tc.client, + Logger: tc.logger, + Cache: tc.cache, + } +} + +// DryRunMapper will trigger the appropriate DependencyMapper for an update of +// the provided type and return the requested reconciles. +// +// Useful for testing just the DependencyMapper+Cache interactions for chains +// that are more complicated than just a full controller interaction test would +// be able to easily verify. +func (tc *TestController) DryRunMapper(ctx context.Context, res *pbresource.Resource) ([]Request, error) { + return tc.c.dryRunMapper(ctx, tc.Runtime(), res) +} diff --git a/internal/controller/watch.go b/internal/controller/watch.go new file mode 100644 index 000000000000..0fd821daade6 --- /dev/null +++ b/internal/controller/watch.go @@ -0,0 +1,42 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package controller + +import ( + "fmt" + + "github.com/hashicorp/consul/internal/controller/cache/index" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +type watch struct { + watchedType *pbresource.Type + mapper DependencyMapper + indexes map[string]*index.Index +} + +func newWatch(watchedType *pbresource.Type, mapper DependencyMapper) *watch { + if mapper == nil { + panic("mapper not provided") + } + + return &watch{ + watchedType: watchedType, + indexes: make(map[string]*index.Index), + mapper: mapper, + } +} + +func (w *watch) addIndex(index *index.Index) { + if _, indexExists := w.indexes[index.Name()]; indexExists { + panic(fmt.Sprintf("index with name %s is already defined", index.Name())) + } + + w.indexes[index.Name()] = index +} + +func (w *watch) key() string { + return resource.ToGVK(w.watchedType) +} diff --git a/internal/dnsutil/dns.go b/internal/dnsutil/dns.go new file mode 100644 index 000000000000..07c7306091ef --- /dev/null +++ b/internal/dnsutil/dns.go @@ -0,0 +1,91 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dnsutil + +import ( + "errors" + "net" + "regexp" + "slices" + "strings" + + "github.com/miekg/dns" +) + +type TranslateAddressAccept int + +// MaxLabelLength is the maximum length for a name that can be used in DNS. +const ( + MaxLabelLength = 63 + + arpaLabel = "arpa" + arpaIPV4Label = "in-addr" + arpaIPV6Label = "ip6" + + TranslateAddressAcceptDomain TranslateAddressAccept = 1 << iota + TranslateAddressAcceptIPv4 + TranslateAddressAcceptIPv6 + + TranslateAddressAcceptAny TranslateAddressAccept = ^0 +) + +// InvalidNameRe is a regex that matches characters which can not be included in +// a DNS name. +var InvalidNameRe = regexp.MustCompile(`[^A-Za-z0-9\\-]+`) + +// matches valid DNS labels according to RFC 1123, should be at most 63 +// characters according to the RFC +var validLabel = regexp.MustCompile(`^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?$`) + +// IsValidLabel returns true if the string given is a valid DNS label (RFC 1123). +// Note: the only difference between RFC 1035 and RFC 1123 labels is that in +// RFC 1123 labels can begin with a number. +func IsValidLabel(name string) bool { + return validLabel.MatchString(name) +} + +// ValidateLabel is similar to IsValidLabel except it returns an error +// instead of false when name is not a valid DNS label. The error will contain +// reference to what constitutes a valid DNS label. +func ValidateLabel(name string) error { + if !IsValidLabel(name) { + return errors.New("a valid DNS label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character") + } + return nil +} + +// IPFromARPA returns the net.IP address from a fully-qualified ARPA PTR domain name. +// If the address is an invalid format, it returns nil. +func IPFromARPA(arpa string) net.IP { + labels := dns.SplitDomainName(arpa) + if len(labels) != 6 && len(labels) != 34 { + return nil + } + + // The last two labels should be "in-addr" or "ip6" and "arpa" + if labels[len(labels)-1] != arpaLabel { + return nil + } + + var ip net.IP + switch labels[len(labels)-2] { + case arpaIPV4Label: + parts := labels[:len(labels)-2] + slices.Reverse(parts) + ip = net.ParseIP(strings.Join(parts, ".")) + case arpaIPV6Label: + parts := labels[:len(labels)-2] + slices.Reverse(parts) + + // Condense the different words of the address + address := strings.Join(parts[0:4], "") + for i := 4; i <= len(parts)-4; i = i + 4 { + word := parts[i : i+4] + address = address + ":" + strings.Join(word, "") + } + ip = net.ParseIP(address) + // default: fallthrough + } + return ip +} diff --git a/internal/dnsutil/dns_test.go b/internal/dnsutil/dns_test.go new file mode 100644 index 000000000000..92b3051ca400 --- /dev/null +++ b/internal/dnsutil/dns_test.go @@ -0,0 +1,122 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package dnsutil + +import ( + "net" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestValidLabel(t *testing.T) { + cases := map[string]bool{ + "CrEaTeD": true, + "created": true, + "create-deleted": true, + "foo": true, + "": false, + "_foo_": false, + "-foo": false, + "foo-": false, + "-foo-": false, + "-foo-bar-": false, + "no spaces allowed": false, + "thisvaluecontainsalotofcharactersbutnottoomanyandthecaseisatrue": true, // 63 chars + "thisvaluecontainstoomanycharactersandisthusinvalidandtestisfalse": false, // 64 chars + } + + t.Run("*", func(t *testing.T) { + t.Run("IsValidLabel", func(t *testing.T) { + require.False(t, IsValidLabel("*")) + }) + t.Run("ValidateLabel", func(t *testing.T) { + require.Error(t, ValidateLabel("*")) + }) + }) + + for name, expect := range cases { + t.Run(name, func(t *testing.T) { + t.Run("IsValidDNSLabel", func(t *testing.T) { + require.Equal(t, expect, IsValidLabel(name)) + }) + t.Run("ValidateLabel", func(t *testing.T) { + if expect { + require.NoError(t, ValidateLabel(name)) + } else { + require.Error(t, ValidateLabel(name)) + } + }) + }) + } +} + +func TestDNSInvalidRegex(t *testing.T) { + tests := []struct { + desc string + in string + invalid bool + }{ + {"Valid Hostname", "testnode", false}, + {"Valid Hostname", "test-node", false}, + {"Invalid Hostname with special chars", "test#$$!node", true}, + {"Invalid Hostname with special chars in the end", "testnode%^", true}, + {"Whitespace", " ", true}, + {"Only special chars", "./$", true}, + } + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + if got, want := InvalidNameRe.MatchString(test.in), test.invalid; got != want { + t.Fatalf("Expected %v to return %v", test.in, want) + } + }) + + } +} + +func Test_IPFromARPA(t *testing.T) { + testCases := []struct { + name string + input string + expected net.IP + }{ + { + name: "valid ipv4", + input: "4.3.2.1.in-addr.arpa.", + expected: net.ParseIP("1.2.3.4"), + }, + { + name: "valid ipv6", + input: "b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", + expected: net.ParseIP("2001:db8::567:89ab"), + }, + { + name: "invalid subdomain", + input: "4.3.2.1.addressplz.arpa", + }, + { + name: "invalid ipv4 - invalid octet", + input: "277.3.2.1.in-addr.arpa", + }, + { + name: "invalid ipv4 - too short", + input: "3.2.1.in-addr.arpa", + }, + { + name: "invalid ipv6 - invalid hex char", + input: "x.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", + }, + { + name: "invalid ipv6 - too long", + input: "d.b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actual := IPFromARPA(tc.input) + require.Equal(t, tc.expected, actual) + }) + } +} diff --git a/internal/go-sso/go.mod.sample b/internal/go-sso/go.mod.sample index f52a14618e02..45fbf668f7c4 100644 --- a/internal/go-sso/go.mod.sample +++ b/internal/go-sso/go.mod.sample @@ -1,18 +1,35 @@ module github.com/hashicorp/consul/go-sso -go 1.13 +go 1.20 require ( - github.com/coreos/go-oidc v2.1.0+incompatible - github.com/hashicorp/go-cleanhttp v0.5.1 - github.com/hashicorp/go-hclog v0.12.0 - github.com/hashicorp/go-uuid v1.0.2 - github.com/mitchellh/go-testing-interface v1.14.0 - github.com/mitchellh/pointerstructure v1.0.0 + github.com/coreos/go-oidc/v3 v3.9.0 + github.com/go-jose/go-jose/v3 v3.0.3 + github.com/hashicorp/consul v1.18.0 + github.com/hashicorp/go-cleanhttp v0.5.2 + github.com/hashicorp/go-hclog v1.5.0 + github.com/hashicorp/go-uuid v1.0.3 + github.com/mitchellh/pointerstructure v1.2.1 github.com/patrickmn/go-cache v2.1.0+incompatible - github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect - github.com/stretchr/testify v1.2.2 - golang.org/x/crypto v0.0.0-20191106202628-ed6320f186d4 // indirect - golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 - gopkg.in/square/go-jose.v2 v2.4.1 + github.com/stretchr/testify v1.8.4 + golang.org/x/oauth2 v0.15.0 +) + +require ( + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/fatih/color v1.14.1 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/sys v0.17.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/square/go-jose.v2 v2.5.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/internal/go-sso/go.sum.sample b/internal/go-sso/go.sum.sample index d21d37a761cd..afdc796375fa 100644 --- a/internal/go-sso/go.sum.sample +++ b/internal/go-sso/go.sum.sample @@ -1,56 +1,126 @@ -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/coreos/go-oidc/v3 v3.9.0 h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo= +github.com/coreos/go-oidc/v3 v3.9.0/go.mod h1:rTKz2PYwftcrtoCzV5g5kvfJoWcm0Mk8AF8y1iAQro4= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= -github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mitchellh/go-testing-interface v1.14.0 h1:/x0XQ6h+3U3nAyk1yx+bHPURrKa9sVVvYbuqZ7pIAtI= -github.com/mitchellh/go-testing-interface v1.14.0/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/pointerstructure v1.0.0 h1:ATSdz4NWrmWPOF1CeCBU4sMCno2hgqdbSrRPFWQSVZI= -github.com/mitchellh/pointerstructure v1.0.0/go.mod h1:k4XwG94++jLVsSiTxo7qdIfXA9pj9EAeo0QsNNJOLZ8= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= +github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/hashicorp/consul v1.18.0 h1:s2ZVuc2mxmlsZ+JL3TNI4DjjlCAjUamBHeLJ5JAZHm0= +github.com/hashicorp/consul v1.18.0/go.mod h1:lVrxsAxllgdk+6EJ4J1jhGGpDKOM7BcjIIGWKQg3Tu8= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= +github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191106202628-ed6320f186d4 h1:PDpCLFAH/YIX0QpHPf2eO7L4rC2OOirBrKtXTLLiNTY= -golang.org/x/crypto v0.0.0-20191106202628-ed6320f186d4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y= -gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/go-sso/oidcauth/auth.go b/internal/go-sso/oidcauth/auth.go index a2f35763a3d0..e4a1fe766eff 100644 --- a/internal/go-sso/oidcauth/auth.go +++ b/internal/go-sso/oidcauth/auth.go @@ -16,7 +16,7 @@ import ( "net/http" "sync" - "github.com/coreos/go-oidc" + "github.com/coreos/go-oidc/v3/oidc" "github.com/hashicorp/go-hclog" "github.com/patrickmn/go-cache" ) diff --git a/internal/go-sso/oidcauth/config.go b/internal/go-sso/oidcauth/config.go index 84bbac9e0cbe..9f95363b352e 100644 --- a/internal/go-sso/oidcauth/config.go +++ b/internal/go-sso/oidcauth/config.go @@ -11,7 +11,7 @@ import ( "strings" "time" - "github.com/coreos/go-oidc" + "github.com/coreos/go-oidc/v3/oidc" ) const ( @@ -45,7 +45,6 @@ type Config struct { // Comma-separated list of 'aud' claims that are valid for login; any match // is sufficient - // TODO(sso): actually just send these down as string claims? BoundAudiences []string // Mappings of claims (key) that will be copied to a metadata field diff --git a/internal/go-sso/oidcauth/config_test.go b/internal/go-sso/oidcauth/config_test.go index c72a69e0845f..2766c6c7bfdc 100644 --- a/internal/go-sso/oidcauth/config_test.go +++ b/internal/go-sso/oidcauth/config_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/coreos/go-oidc" + "github.com/coreos/go-oidc/v3/oidc" "github.com/hashicorp/consul/internal/go-sso/oidcauth/oidcauthtest" "github.com/stretchr/testify/require" ) diff --git a/internal/go-sso/oidcauth/jwt.go b/internal/go-sso/oidcauth/jwt.go index fbb6a31669c8..b71fdb2b31bc 100644 --- a/internal/go-sso/oidcauth/jwt.go +++ b/internal/go-sso/oidcauth/jwt.go @@ -15,7 +15,7 @@ import ( "fmt" "time" - "gopkg.in/square/go-jose.v2/jwt" + "github.com/go-jose/go-jose/v3/jwt" ) const claimDefaultLeeway = 150 diff --git a/internal/go-sso/oidcauth/jwt_test.go b/internal/go-sso/oidcauth/jwt_test.go index 621fb6660b53..7cfae3aa92c1 100644 --- a/internal/go-sso/oidcauth/jwt_test.go +++ b/internal/go-sso/oidcauth/jwt_test.go @@ -15,11 +15,11 @@ import ( "testing" "time" - "github.com/coreos/go-oidc" + "github.com/coreos/go-oidc/v3/oidc" + "github.com/go-jose/go-jose/v3/jwt" "github.com/hashicorp/consul/internal/go-sso/oidcauth/oidcauthtest" "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/require" - "gopkg.in/square/go-jose.v2/jwt" ) func setupForJWT(t *testing.T, authType int, f func(c *Config)) (*Authenticator, string) { diff --git a/internal/go-sso/oidcauth/oidc.go b/internal/go-sso/oidcauth/oidc.go index df00dfcc25f6..80b5131bd726 100644 --- a/internal/go-sso/oidcauth/oidc.go +++ b/internal/go-sso/oidcauth/oidc.go @@ -11,7 +11,7 @@ import ( "strings" "time" - "github.com/coreos/go-oidc" + "github.com/coreos/go-oidc/v3/oidc" "github.com/hashicorp/go-uuid" "golang.org/x/oauth2" ) @@ -235,7 +235,8 @@ func (a *Authenticator) verifyOIDCToken(ctx context.Context, rawToken string) (m if err := idToken.Claims(&allClaims); err != nil { return nil, fmt.Errorf("unable to successfully parse all claims from token: %v", err) } - // TODO(sso): why isn't this strict for OIDC? + // Follows behavior of hashicorp/vault-plugin-auth-jwt (non-strict validation). + // See https://developer.hashicorp.com/consul/docs/security/acl/auth-methods/oidc#oidc-configuration-troubleshooting. if err := validateAudience(a.config.BoundAudiences, idToken.Audience, false); err != nil { return nil, fmt.Errorf("error validating claims: %v", err) } diff --git a/internal/go-sso/oidcauth/oidc_test.go b/internal/go-sso/oidcauth/oidc_test.go index 48de99b64181..ac61755e6546 100644 --- a/internal/go-sso/oidcauth/oidc_test.go +++ b/internal/go-sso/oidcauth/oidc_test.go @@ -11,11 +11,11 @@ import ( "testing" "time" + "github.com/go-jose/go-jose/v3/jwt" "github.com/hashicorp/consul/internal/go-sso/oidcauth/oidcauthtest" "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gopkg.in/square/go-jose.v2/jwt" ) func setupForOIDC(t *testing.T) (*Authenticator, *oidcauthtest.Server) { @@ -390,7 +390,7 @@ func TestOIDC_ClaimsFromAuthCode(t *testing.T) { context.Background(), state, "wrong_code", ) - requireErrorContains(t, err, "cannot fetch token") + requireErrorContains(t, err, "Error exchanging oidc code") requireProviderError(t, err) }) diff --git a/internal/go-sso/oidcauth/oidcauthtest/testing.go b/internal/go-sso/oidcauth/oidcauthtest/testing.go index 0956673c0515..628dd5bed2f5 100644 --- a/internal/go-sso/oidcauth/oidcauthtest/testing.go +++ b/internal/go-sso/oidcauth/oidcauthtest/testing.go @@ -27,9 +27,9 @@ import ( "sync" "time" + "github.com/go-jose/go-jose/v3" + "github.com/go-jose/go-jose/v3/jwt" "github.com/stretchr/testify/require" - "gopkg.in/square/go-jose.v2" - "gopkg.in/square/go-jose.v2/jwt" "github.com/hashicorp/consul/internal/go-sso/oidcauth/internal/strutil" ) diff --git a/lib/rtt.go b/internal/gossip/librtt/rtt.go similarity index 99% rename from lib/rtt.go rename to internal/gossip/librtt/rtt.go index d716e6fcbe1c..697ddf731598 100644 --- a/lib/rtt.go +++ b/internal/gossip/librtt/rtt.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package lib +package librtt import ( "math" diff --git a/lib/rtt_test.go b/internal/gossip/librtt/rtt_test.go similarity index 99% rename from lib/rtt_test.go rename to internal/gossip/librtt/rtt_test.go index 1e7779b9adde..206752aa79df 100644 --- a/lib/rtt_test.go +++ b/internal/gossip/librtt/rtt_test.go @@ -1,15 +1,16 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package lib +package librtt import ( "math" "testing" "time" - "github.com/hashicorp/serf/coordinate" "github.com/stretchr/testify/require" + + "github.com/hashicorp/serf/coordinate" ) func TestRTT_ComputeDistance(t *testing.T) { diff --git a/lib/serf/serf.go b/internal/gossip/libserf/serf.go similarity index 94% rename from lib/serf/serf.go rename to internal/gossip/libserf/serf.go index 932fed427ba9..4e4f7de55609 100644 --- a/lib/serf/serf.go +++ b/internal/gossip/libserf/serf.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package serf +package libserf import ( "time" @@ -29,7 +29,7 @@ func DefaultConfig() *serf.Config { // This gives leaves some time to propagate through the cluster before // we shut down. The value was chosen to be reasonably short, but to // allow a leave to get to over 99.99% of the cluster with 100k nodes - // (using https://www.serf.io/docs/internals/simulator.html). + // (using https://github.com/hashicorp/serf/blob/master/docs/internals/simulator.html.erb). base.LeavePropagateDelay = 3 * time.Second return base diff --git a/internal/hcp/exports.go b/internal/hcp/exports.go new file mode 100644 index 000000000000..18ede30d2797 --- /dev/null +++ b/internal/hcp/exports.go @@ -0,0 +1,34 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package hcp + +import ( + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/hcp/internal/controllers" + "github.com/hashicorp/consul/internal/hcp/internal/controllers/link" + "github.com/hashicorp/consul/internal/hcp/internal/types" + "github.com/hashicorp/consul/internal/resource" +) + +// RegisterTypes adds all resource types within the "hcp" API group +// to the given type registry +func RegisterTypes(r resource.Registry) { + types.Register(r) +} + +type ControllerDependencies = controllers.Dependencies + +var IsValidated = link.IsValidated +var LinkName = types.LinkName + +// RegisterControllers registers controllers for the catalog types with +// the given controller Manager. +func RegisterControllers(mgr *controller.Manager, deps ControllerDependencies) { + controllers.Register(mgr, deps) +} + +// Needed for testing +var StatusKey = link.StatusKey +var ConditionValidatedSuccess = link.ConditionValidatedSuccess +var ConditionValidatedFailed = link.ConditionValidatedFailed diff --git a/internal/hcp/internal/controllers/link/controller.go b/internal/hcp/internal/controllers/link/controller.go new file mode 100644 index 000000000000..77c439f5cb4d --- /dev/null +++ b/internal/hcp/internal/controllers/link/controller.go @@ -0,0 +1,234 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package link + +import ( + "context" + "crypto/tls" + "strings" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/anypb" + + gnmmod "github.com/hashicorp/hcp-sdk-go/clients/cloud-global-network-manager-service/preview/2022-02-15/models" + + hcpclient "github.com/hashicorp/consul/agent/hcp/client" + "github.com/hashicorp/consul/agent/hcp/config" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/hcp/internal/types" + "github.com/hashicorp/consul/internal/storage" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// HCPClientFn is a function that can be used to create an HCP client from a Link object. +// This function type should be passed to a LinkController in order to tell it how to make a client from +// a Link. For normal use, DefaultHCPClientFn should be used, but tests can substitute in a function that creates a +// mock client. +type HCPClientFn func(config.CloudConfig) (hcpclient.Client, error) + +var DefaultHCPClientFn HCPClientFn = func(cfg config.CloudConfig) (hcpclient.Client, error) { + hcpClient, err := hcpclient.NewClient(cfg) + if err != nil { + return nil, err + } + return hcpClient, nil +} + +func LinkController( + hcpClientFn HCPClientFn, + cfg config.CloudConfig, +) *controller.Controller { + return controller.NewController("link", pbhcp.LinkType). + WithInitializer( + &linkInitializer{ + cloudConfig: cfg, + }, + ). + WithReconciler( + &linkReconciler{ + hcpClientFn: hcpClientFn, + cloudConfig: cfg, + }, + ) +} + +type linkReconciler struct { + hcpClientFn HCPClientFn + cloudConfig config.CloudConfig +} + +func hcpAccessLevelToConsul(level *gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevel) pbhcp.AccessLevel { + if level == nil { + return pbhcp.AccessLevel_ACCESS_LEVEL_UNSPECIFIED + } + + switch *level { + case gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELUNSPECIFIED: + return pbhcp.AccessLevel_ACCESS_LEVEL_UNSPECIFIED + case gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELGLOBALREADWRITE: + return pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE + case gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELGLOBALREADONLY: + return pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_ONLY + default: + return pbhcp.AccessLevel_ACCESS_LEVEL_UNSPECIFIED + } +} + +func (r *linkReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { + // The runtime is passed by value so replacing it here for the remainder of this + // reconciliation request processing will not affect future invocations. + rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", StatusKey) + + rt.Logger.Trace("reconciling link") + + rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: req.ID}) + switch { + case status.Code(err) == codes.NotFound: + rt.Logger.Trace("link has been deleted") + return nil + case err != nil: + rt.Logger.Error("the resource service has returned an unexpected error", "error", err) + return err + } + + res := rsp.Resource + var link pbhcp.Link + if err := res.Data.UnmarshalTo(&link); err != nil { + rt.Logger.Error("error unmarshalling link data", "error", err) + return err + } + + newStatus := &pbresource.Status{ + ObservedGeneration: res.Generation, + Conditions: []*pbresource.Condition{}, + } + defer writeStatusIfNotEqual(ctx, rt, res, newStatus) + newStatus.Conditions = append(newStatus.Conditions, ConditionValidatedSuccess) + + // Merge the link data with the existing cloud config so that we only overwrite the + // fields that are provided by the link. This ensures that: + // 1. The HCP configuration (i.e., how to connect to HCP) is preserved + // 2. The Consul agent's node ID and node name are preserved + newCfg := CloudConfigFromLink(&link) + cfg := config.Merge(r.cloudConfig, newCfg) + hcpClient, err := r.hcpClientFn(cfg) + if err != nil { + rt.Logger.Error("error creating HCP client", "error", err) + return err + } + + // Sync cluster data from HCP + cluster, err := hcpClient.GetCluster(ctx) + if err != nil { + rt.Logger.Error("error querying HCP for cluster", "error", err) + condition := linkingFailedCondition(err) + newStatus.Conditions = append(newStatus.Conditions, condition) + return err + } + accessLevel := hcpAccessLevelToConsul(cluster.AccessLevel) + + if link.HcpClusterUrl != cluster.HCPPortalURL || + link.AccessLevel != accessLevel { + + link.HcpClusterUrl = cluster.HCPPortalURL + link.AccessLevel = accessLevel + + updatedData, err := anypb.New(&link) + if err != nil { + rt.Logger.Error("error marshalling link data", "error", err) + return err + } + _, err = rt.Client.Write( + ctx, &pbresource.WriteRequest{Resource: &pbresource.Resource{ + Id: &pbresource.ID{ + Name: types.LinkName, + Type: pbhcp.LinkType, + }, + Metadata: res.Metadata, + Data: updatedData, + }}, + ) + if err != nil { + rt.Logger.Error("error updating link", "error", err) + return err + } + } + + newStatus.Conditions = append(newStatus.Conditions, ConditionLinked(link.ResourceId)) + + return writeStatusIfNotEqual(ctx, rt, res, newStatus) +} + +type linkInitializer struct { + cloudConfig config.CloudConfig +} + +func (i *linkInitializer) Initialize(ctx context.Context, rt controller.Runtime) error { + if !i.cloudConfig.IsConfigured() { + return nil + } + + // Construct a link resource to reflect the configuration + data, err := anypb.New( + &pbhcp.Link{ + ResourceId: i.cloudConfig.ResourceID, + ClientId: i.cloudConfig.ClientID, + ClientSecret: i.cloudConfig.ClientSecret, + }, + ) + if err != nil { + return err + } + + // Create the link resource for a configuration-based link + _, err = rt.Client.Write( + ctx, + &pbresource.WriteRequest{ + Resource: &pbresource.Resource{ + Id: &pbresource.ID{ + Name: types.LinkName, + Type: pbhcp.LinkType, + }, + Metadata: map[string]string{ + types.MetadataSourceKey: types.MetadataSourceConfig, + }, + Data: data, + }, + }, + ) + if err != nil { + if strings.Contains(err.Error(), storage.ErrWrongUid.Error()) || + strings.Contains(err.Error(), "leader unknown") { + // If the error is likely ignorable and could eventually resolve itself, + // log it as TRACE rather than ERROR. + rt.Logger.Trace("error initializing controller", "error", err) + } else { + rt.Logger.Error("error initializing controller", "error", err) + } + return err + } + + return nil +} + +func CloudConfigFromLink(link *pbhcp.Link) config.CloudConfig { + var cfg config.CloudConfig + if link == nil { + return cfg + } + cfg = config.CloudConfig{ + ResourceID: link.GetResourceId(), + ClientID: link.GetClientId(), + ClientSecret: link.GetClientSecret(), + } + if link.GetHcpConfig() != nil { + cfg.AuthURL = link.GetHcpConfig().GetAuthUrl() + cfg.ScadaAddress = link.GetHcpConfig().GetScadaAddress() + cfg.Hostname = link.GetHcpConfig().GetApiAddress() + cfg.TLSConfig = &tls.Config{InsecureSkipVerify: link.GetHcpConfig().GetTlsInsecureSkipVerify()} + } + return cfg +} diff --git a/internal/hcp/internal/controllers/link/controller_test.go b/internal/hcp/internal/controllers/link/controller_test.go new file mode 100644 index 000000000000..fc23c3c627ba --- /dev/null +++ b/internal/hcp/internal/controllers/link/controller_test.go @@ -0,0 +1,248 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package link + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + gnmmod "github.com/hashicorp/hcp-sdk-go/clients/cloud-global-network-manager-service/preview/2022-02-15/models" + + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" + hcpclient "github.com/hashicorp/consul/agent/hcp/client" + "github.com/hashicorp/consul/agent/hcp/config" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/hcp/internal/types" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil" +) + +type controllerSuite struct { + suite.Suite + + ctx context.Context + client *rtest.Client + rt controller.Runtime + + tenancies []*pbresource.Tenancy +} + +func mockHcpClientFn(t *testing.T) (*hcpclient.MockClient, HCPClientFn) { + mockClient := hcpclient.NewMockClient(t) + + mockClientFunc := func(config config.CloudConfig) (hcpclient.Client, error) { + return mockClient, nil + } + + return mockClient, mockClientFunc +} + +func (suite *controllerSuite) SetupTest() { + suite.ctx = testutil.TestContext(suite.T()) + suite.tenancies = rtest.TestTenancies() + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(types.Register). + WithTenancies(suite.tenancies...). + Run(suite.T()) + + suite.rt = controller.Runtime{ + Client: client, + Logger: testutil.Logger(suite.T()), + } + suite.client = rtest.NewClient(client) +} + +func TestLinkController(t *testing.T) { + suite.Run(t, new(controllerSuite)) +} + +func (suite *controllerSuite) deleteResourceFunc(id *pbresource.ID) func() { + return func() { + suite.client.MustDelete(suite.T(), id) + suite.client.WaitForDeletion(suite.T(), id) + } +} + +func (suite *controllerSuite) TestController_Ok() { + // Run the controller manager + mgr := controller.NewManager(suite.client, suite.rt.Logger) + mockClient, mockClientFn := mockHcpClientFn(suite.T()) + readWrite := gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELGLOBALREADWRITE + mockClient.EXPECT().GetCluster(mock.Anything).Return(&hcpclient.Cluster{ + HCPPortalURL: "http://test.com", + AccessLevel: &readWrite, + }, nil) + + mgr.Register(LinkController( + mockClientFn, + config.CloudConfig{}, + )) + mgr.SetRaftLeader(true) + go mgr.Run(suite.ctx) + + linkData := &pbhcp.Link{ + ClientId: "abc", + ClientSecret: "abc", + ResourceId: types.GenerateTestResourceID(suite.T()), + } + + link := rtest.Resource(pbhcp.LinkType, "global"). + WithData(suite.T(), linkData). + Write(suite.T(), suite.client) + + suite.T().Cleanup(suite.deleteResourceFunc(link.Id)) + + suite.client.WaitForStatusCondition(suite.T(), link.Id, StatusKey, ConditionLinked(linkData.ResourceId)) + var updatedLink pbhcp.Link + updatedLinkResource := suite.client.WaitForNewVersion(suite.T(), link.Id, link.Version) + require.NoError(suite.T(), updatedLinkResource.Data.UnmarshalTo(&updatedLink)) + require.Equal(suite.T(), "http://test.com", updatedLink.HcpClusterUrl) + require.Equal(suite.T(), pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE, updatedLink.AccessLevel) +} + +func (suite *controllerSuite) TestController_Initialize() { + // Run the controller manager with a configured link + mgr := controller.NewManager(suite.client, suite.rt.Logger) + + mockClient, mockClientFn := mockHcpClientFn(suite.T()) + readOnly := gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELGLOBALREADONLY + mockClient.EXPECT().GetCluster(mock.Anything).Return(&hcpclient.Cluster{ + HCPPortalURL: "http://test.com", + AccessLevel: &readOnly, + }, nil) + + cloudCfg := config.CloudConfig{ + ClientID: "client-id-abc", + ClientSecret: "client-secret-abc", + ResourceID: types.GenerateTestResourceID(suite.T()), + } + + mgr.Register(LinkController( + mockClientFn, + cloudCfg, + )) + mgr.SetRaftLeader(true) + go mgr.Run(suite.ctx) + + // Wait for link to be created by initializer + id := &pbresource.ID{ + Type: pbhcp.LinkType, + Name: types.LinkName, + } + suite.T().Cleanup(suite.deleteResourceFunc(id)) + r := suite.client.WaitForResourceExists(suite.T(), id) + + // Check that created link has expected values + var link pbhcp.Link + err := r.Data.UnmarshalTo(&link) + require.NoError(suite.T(), err) + + require.Equal(suite.T(), cloudCfg.ResourceID, link.ResourceId) + require.Equal(suite.T(), cloudCfg.ClientID, link.ClientId) + require.Equal(suite.T(), cloudCfg.ClientSecret, link.ClientSecret) + require.Equal(suite.T(), types.MetadataSourceConfig, r.Metadata[types.MetadataSourceKey]) + + // Wait for link to be connected successfully + suite.client.WaitForStatusCondition(suite.T(), id, StatusKey, ConditionLinked(link.ResourceId)) +} + +func (suite *controllerSuite) TestController_GetClusterError() { + type testCase struct { + expectErr error + expectCondition *pbresource.Condition + } + tt := map[string]testCase{ + "unexpected": { + expectErr: fmt.Errorf("error"), + expectCondition: ConditionFailed, + }, + "unauthorized": { + expectErr: hcpclient.ErrUnauthorized, + expectCondition: ConditionUnauthorized, + }, + "forbidden": { + expectErr: hcpclient.ErrForbidden, + expectCondition: ConditionForbidden, + }, + } + + for name, tc := range tt { + suite.T().Run(name, func(t *testing.T) { + // Run the controller manager + mgr := controller.NewManager(suite.client, suite.rt.Logger) + mockClient, mockClientFunc := mockHcpClientFn(t) + mockClient.EXPECT().GetCluster(mock.Anything).Return(nil, tc.expectErr) + + mgr.Register(LinkController( + mockClientFunc, + config.CloudConfig{}, + )) + + mgr.SetRaftLeader(true) + ctx, cancel := context.WithCancel(suite.ctx) + t.Cleanup(cancel) + go mgr.Run(ctx) + + linkData := &pbhcp.Link{ + ClientId: "abc", + ClientSecret: "abc", + ResourceId: types.GenerateTestResourceID(t), + } + link := rtest.Resource(pbhcp.LinkType, "global"). + WithData(t, linkData). + Write(t, suite.client) + + t.Cleanup(suite.deleteResourceFunc(link.Id)) + + suite.client.WaitForStatusCondition(t, link.Id, StatusKey, tc.expectCondition) + }) + } +} + +func Test_hcpAccessModeToConsul(t *testing.T) { + type testCase struct { + hcpAccessLevel *gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevel + consulAccessLevel pbhcp.AccessLevel + } + tt := map[string]testCase{ + "unspecified": { + hcpAccessLevel: func() *gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevel { + t := gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELUNSPECIFIED + return &t + }(), + consulAccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_UNSPECIFIED, + }, + "invalid": { + hcpAccessLevel: nil, + consulAccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_UNSPECIFIED, + }, + "read_only": { + hcpAccessLevel: func() *gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevel { + t := gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELGLOBALREADONLY + return &t + }(), + consulAccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_ONLY, + }, + "read_write": { + hcpAccessLevel: func() *gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevel { + t := gnmmod.HashicorpCloudGlobalNetworkManager20220215ClusterConsulAccessLevelCONSULACCESSLEVELGLOBALREADWRITE + return &t + }(), + consulAccessLevel: pbhcp.AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE, + }, + } + for name, tc := range tt { + t.Run(name, func(t *testing.T) { + accessLevel := hcpAccessLevelToConsul(tc.hcpAccessLevel) + require.Equal(t, tc.consulAccessLevel, accessLevel) + }) + } +} diff --git a/internal/hcp/internal/controllers/link/status.go b/internal/hcp/internal/controllers/link/status.go new file mode 100644 index 000000000000..88210c4a4997 --- /dev/null +++ b/internal/hcp/internal/controllers/link/status.go @@ -0,0 +1,142 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package link + +import ( + "context" + "errors" + "fmt" + + "github.com/hashicorp/consul/agent/hcp/client" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/resource" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +const ( + StatusKey = "consul.io/hcp/link" + + // Statuses + StatusLinked = "linked" + StatusValidated = "validated" + + LinkedSuccessReason = "SUCCESS" + LinkedFailedReason = "FAILED" + LinkedDisabledReasonV2ResourcesUnsupportedReason = "DISABLED_V2_RESOURCES_UNSUPPORTED" + LinkedUnauthorizedReason = "UNAUTHORIZED" + LinkedForbiddenReason = "FORBIDDEN" + ValidatedSuccessReason = "SUCCESS" + ValidatedFailedV2ResourcesReason = "V2_RESOURCES_UNSUPPORTED" + + LinkedMessageFormat = "Successfully linked to cluster '%s'" + FailedMessage = "Failed to link to HCP due to unexpected error" + DisabledResourceAPIsEnabledMessage = "Link is disabled because resource-apis are enabled" + UnauthorizedMessage = "Access denied, check client_id and client_secret" + ForbiddenMessage = "Access denied, check the resource_id" + ValidatedSuccessMessage = "Successfully validated link" + ValidatedFailedV2ResourcesMessage = "Link is disabled because resource-apis are enabled" +) + +var ( + ConditionDisabled = &pbresource.Condition{ + Type: StatusLinked, + State: pbresource.Condition_STATE_FALSE, + Reason: LinkedDisabledReasonV2ResourcesUnsupportedReason, + Message: DisabledResourceAPIsEnabledMessage, + } + ConditionFailed = &pbresource.Condition{ + Type: StatusLinked, + State: pbresource.Condition_STATE_FALSE, + Reason: LinkedFailedReason, + Message: FailedMessage, + } + ConditionUnauthorized = &pbresource.Condition{ + Type: StatusLinked, + State: pbresource.Condition_STATE_FALSE, + Reason: LinkedUnauthorizedReason, + Message: UnauthorizedMessage, + } + ConditionForbidden = &pbresource.Condition{ + Type: StatusLinked, + State: pbresource.Condition_STATE_FALSE, + Reason: LinkedForbiddenReason, + Message: ForbiddenMessage, + } + ConditionValidatedSuccess = &pbresource.Condition{ + Type: StatusValidated, + State: pbresource.Condition_STATE_TRUE, + Reason: ValidatedSuccessReason, + Message: ValidatedSuccessMessage, + } + ConditionValidatedFailed = &pbresource.Condition{ + Type: StatusValidated, + State: pbresource.Condition_STATE_FALSE, + Reason: ValidatedFailedV2ResourcesReason, + Message: ValidatedFailedV2ResourcesMessage, + } +) + +func ConditionLinked(resourceId string) *pbresource.Condition { + return &pbresource.Condition{ + Type: StatusLinked, + State: pbresource.Condition_STATE_TRUE, + Reason: LinkedSuccessReason, + Message: fmt.Sprintf(LinkedMessageFormat, resourceId), + } +} + +func writeStatusIfNotEqual(ctx context.Context, rt controller.Runtime, res *pbresource.Resource, status *pbresource.Status) error { + if resource.EqualStatus(res.Status[StatusKey], status, false) { + return nil + } + _, err := rt.Client.WriteStatus( + ctx, &pbresource.WriteStatusRequest{ + Id: res.Id, + Key: StatusKey, + Status: status, + }, + ) + if err != nil { + rt.Logger.Error("error writing link status", "error", err) + } + return err +} + +func linkingFailedCondition(err error) *pbresource.Condition { + switch { + case errors.Is(err, client.ErrUnauthorized): + return ConditionUnauthorized + case errors.Is(err, client.ErrForbidden): + return ConditionForbidden + default: + return ConditionFailed + } +} + +func IsLinked(res *pbresource.Resource) (linked bool, reason string) { + return isConditionTrue(res, StatusLinked) +} + +func IsValidated(res *pbresource.Resource) (linked bool, reason string) { + return isConditionTrue(res, StatusValidated) +} + +func isConditionTrue(res *pbresource.Resource, statusType string) (bool, string) { + if !resource.EqualType(res.GetId().GetType(), pbhcp.LinkType) { + return false, "resource is not hcp.Link type" + } + + linkStatus, ok := res.GetStatus()[StatusKey] + if !ok { + return false, "link status not set" + } + + for _, cond := range linkStatus.GetConditions() { + if cond.Type == statusType && cond.GetState() == pbresource.Condition_STATE_TRUE { + return true, "" + } + } + return false, fmt.Sprintf("link status does not include positive %s condition", statusType) +} diff --git a/internal/hcp/internal/controllers/register.go b/internal/hcp/internal/controllers/register.go new file mode 100644 index 000000000000..05203f525cb6 --- /dev/null +++ b/internal/hcp/internal/controllers/register.go @@ -0,0 +1,26 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package controllers + +import ( + "github.com/hashicorp/consul/agent/hcp/config" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/hcp/internal/controllers/link" + "github.com/hashicorp/consul/internal/hcp/internal/controllers/telemetrystate" +) + +type Dependencies struct { + CloudConfig config.CloudConfig +} + +func Register(mgr *controller.Manager, deps Dependencies) { + mgr.Register( + link.LinkController( + link.DefaultHCPClientFn, + deps.CloudConfig, + ), + ) + + mgr.Register(telemetrystate.TelemetryStateController(link.DefaultHCPClientFn)) +} diff --git a/internal/hcp/internal/controllers/telemetrystate/controller.go b/internal/hcp/internal/controllers/telemetrystate/controller.go new file mode 100644 index 000000000000..e21c85685ed8 --- /dev/null +++ b/internal/hcp/internal/controllers/telemetrystate/controller.go @@ -0,0 +1,203 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package telemetrystate + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" + + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/controller/dependency" + "github.com/hashicorp/consul/internal/hcp/internal/controllers/link" + "github.com/hashicorp/consul/internal/hcp/internal/types" + "github.com/hashicorp/consul/internal/resource" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +var ( + globalID = &pbresource.ID{ + Name: "global", + Type: pbhcp.TelemetryStateType, + Tenancy: &pbresource.Tenancy{}, + } +) + +const MetaKeyDebugSkipDeletion = StatusKey + "/debug/skip-deletion" + +func TelemetryStateController(hcpClientFn link.HCPClientFn) *controller.Controller { + return controller.NewController(StatusKey, pbhcp.TelemetryStateType). + WithWatch(pbhcp.LinkType, dependency.ReplaceType(pbhcp.TelemetryStateType)). + WithReconciler(&telemetryStateReconciler{ + hcpClientFn: hcpClientFn, + }) +} + +type telemetryStateReconciler struct { + hcpClientFn link.HCPClientFn +} + +func (r *telemetryStateReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { + // The runtime is passed by value so replacing it here for the remainder of this + // reconciliation request processing will not affect future invocations. + rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", StatusKey) + + rt.Logger.Trace("reconciling telemetry-state") + + // First get the link resource in order to build a hcp client. If the link resource + // doesn't exist then the telemetry-state should not exist either. + res, err := getLinkResource(ctx, rt) + if err != nil { + rt.Logger.Error("failed to lookup Link resource", "error", err) + return err + } + if res == nil { + return ensureTelemetryStateDeleted(ctx, rt) + } + + // Check that the link resource indicates the cluster is linked + // If the cluster is not linked, the telemetry-state resource should not exist + if linked, reason := link.IsLinked(res.GetResource()); !linked { + rt.Logger.Trace("cluster is not linked", "reason", reason) + return ensureTelemetryStateDeleted(ctx, rt) + } + + hcpClient, err := r.hcpClientFn(link.CloudConfigFromLink(res.GetData())) + if err != nil { + rt.Logger.Error("error creating HCP Client", "error", err) + return err + } + + // Get the telemetry configuration and observability scoped credentials from hcp + tCfg, err := hcpClient.FetchTelemetryConfig(ctx) + if err != nil { + rt.Logger.Error("error requesting telemetry config", "error", err) + return err + } + clientID, clientSecret, err := hcpClient.GetObservabilitySecret(ctx) + if err != nil { + rt.Logger.Error("error requesting telemetry credentials", "error", err) + return nil + } + + // TODO allow hcp client config override from hcp TelemetryConfig + hcpCfg := res.GetData().GetHcpConfig() + + // TODO implement proxy options from hcp + proxyCfg := &pbhcp.ProxyConfig{} + + state := &pbhcp.TelemetryState{ + ResourceId: res.GetData().ResourceId, + ClientId: clientID, + ClientSecret: clientSecret, + HcpConfig: hcpCfg, + Proxy: proxyCfg, + Metrics: &pbhcp.MetricsConfig{ + Labels: tCfg.MetricsConfig.Labels, + Disabled: tCfg.MetricsConfig.Disabled, + }, + } + + if tCfg.MetricsConfig.Endpoint != nil { + state.Metrics.Endpoint = tCfg.MetricsConfig.Endpoint.String() + } + if tCfg.MetricsConfig.Filters != nil { + state.Metrics.IncludeList = []string{tCfg.MetricsConfig.Filters.String()} + } + + if err := writeTelemetryStateIfUpdated(ctx, rt, state); err != nil { + rt.Logger.Error("error updating telemetry-state", "error", err) + return err + } + + return nil +} + +func ensureTelemetryStateDeleted(ctx context.Context, rt controller.Runtime) error { + resp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: &pbresource.ID{Name: "global", Type: pbhcp.TelemetryStateType}}) + switch { + case status.Code(err) == codes.NotFound: + return nil + case err != nil: + rt.Logger.Error("the resource service has returned an unexpected error", "error", err) + return err + } + + rt.Logger.Trace("deleting telemetry-state") + if _, ok := resp.GetResource().Metadata[MetaKeyDebugSkipDeletion]; ok { + rt.Logger.Debug("skip-deletion metadata key found, skipping deletion of telemetry-state resource") + return nil + } + + if _, err := rt.Client.Delete(ctx, &pbresource.DeleteRequest{Id: resp.GetResource().GetId()}); err != nil { + rt.Logger.Error("error deleting telemetry-state resource", "error", err) + return err + } + return nil +} + +func writeTelemetryStateIfUpdated(ctx context.Context, rt controller.Runtime, state *pbhcp.TelemetryState) error { + currentState, err := getTelemetryStateResource(ctx, rt) + if err != nil { + return err + } + + if currentState != nil && proto.Equal(currentState.GetData(), state) { + return nil + } + + stateData, err := anypb.New(state) + if err != nil { + return err + } + + _, err = rt.Client.Write(ctx, &pbresource.WriteRequest{Resource: &pbresource.Resource{ + Id: &pbresource.ID{ + Name: "global", + Type: pbhcp.TelemetryStateType, + }, + Data: stateData, + }}) + return err +} + +func getGlobalResource(ctx context.Context, rt controller.Runtime, t *pbresource.Type) (*pbresource.Resource, error) { + resp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: &pbresource.ID{Name: "global", Type: t}}) + switch { + case status.Code(err) == codes.NotFound: + return nil, nil + case err != nil: + return nil, err + } + + return resp.GetResource(), nil +} + +// getLinkResource returns the cluster scoped pbhcp.Link resource. If the resource is not found a nil +// pointer and no error will be returned. +func getLinkResource(ctx context.Context, rt controller.Runtime) (*types.DecodedLink, error) { + res, err := getGlobalResource(ctx, rt, pbhcp.LinkType) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return resource.Decode[*pbhcp.Link](res) +} + +func getTelemetryStateResource(ctx context.Context, rt controller.Runtime) (*types.DecodedTelemetryState, error) { + res, err := getGlobalResource(ctx, rt, pbhcp.TelemetryStateType) + if err != nil { + return nil, err + } + if res == nil { + return nil, nil + } + return resource.Decode[*pbhcp.TelemetryState](res) +} diff --git a/internal/hcp/internal/controllers/telemetrystate/controller_test.go b/internal/hcp/internal/controllers/telemetrystate/controller_test.go new file mode 100644 index 000000000000..e11c1e30638f --- /dev/null +++ b/internal/hcp/internal/controllers/telemetrystate/controller_test.go @@ -0,0 +1,174 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package telemetrystate + +import ( + "context" + "net/url" + "regexp" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" + hcpclient "github.com/hashicorp/consul/agent/hcp/client" + "github.com/hashicorp/consul/agent/hcp/config" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/hcp/internal/controllers/link" + "github.com/hashicorp/consul/internal/hcp/internal/types" + "github.com/hashicorp/consul/internal/resource" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil" +) + +type controllerSuite struct { + suite.Suite + + ctx context.Context + client *rtest.Client + rt controller.Runtime + + ctl *controller.TestController + tenancies []*pbresource.Tenancy + + hcpMock *hcpclient.MockClient +} + +func mockHcpClientFn(t *testing.T) (*hcpclient.MockClient, link.HCPClientFn) { + mockClient := hcpclient.NewMockClient(t) + + mockClientFunc := func(link config.CloudConfig) (hcpclient.Client, error) { + return mockClient, nil + } + + return mockClient, mockClientFunc +} + +func (suite *controllerSuite) SetupTest() { + suite.ctx = testutil.TestContext(suite.T()) + suite.tenancies = rtest.TestTenancies() + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(types.Register). + WithTenancies(suite.tenancies...). + Run(suite.T()) + + hcpMock, hcpClientFn := mockHcpClientFn(suite.T()) + suite.hcpMock = hcpMock + suite.ctl = controller.NewTestController(TelemetryStateController(hcpClientFn), client). + WithLogger(testutil.Logger(suite.T())) + + suite.rt = suite.ctl.Runtime() + suite.client = rtest.NewClient(client) +} + +func TestTelemetryStateController(t *testing.T) { + suite.Run(t, new(controllerSuite)) +} + +func (suite *controllerSuite) deleteResourceFunc(id *pbresource.ID) func() { + return func() { + suite.client.MustDelete(suite.T(), id) + } +} + +func (suite *controllerSuite) TestController_Ok() { + // Run the controller manager + mgr := controller.NewManager(suite.client, suite.rt.Logger) + mockClient, mockClientFn := mockHcpClientFn(suite.T()) + mockClient.EXPECT().FetchTelemetryConfig(mock.Anything).Return(&hcpclient.TelemetryConfig{ + MetricsConfig: &hcpclient.MetricsConfig{ + Endpoint: &url.URL{ + Scheme: "http", + Host: "localhost", + Path: "/test", + }, + Labels: map[string]string{"foo": "bar"}, + Filters: regexp.MustCompile(".*"), + }, + RefreshConfig: &hcpclient.RefreshConfig{}, + }, nil) + mockClient.EXPECT().GetObservabilitySecret(mock.Anything).Return("xxx", "yyy", nil) + mgr.Register(TelemetryStateController(mockClientFn)) + mgr.SetRaftLeader(true) + go mgr.Run(suite.ctx) + + link := suite.writeLinkResource() + + tsRes := suite.client.WaitForResourceExists(suite.T(), &pbresource.ID{Name: "global", Type: pbhcp.TelemetryStateType}) + decodedState, err := resource.Decode[*pbhcp.TelemetryState](tsRes) + require.NoError(suite.T(), err) + require.Equal(suite.T(), link.GetData().GetResourceId(), decodedState.GetData().ResourceId) + require.Equal(suite.T(), "xxx", decodedState.GetData().ClientId) + require.Equal(suite.T(), "http://localhost/test", decodedState.GetData().Metrics.Endpoint) + + suite.client.MustDelete(suite.T(), link.Id) + suite.client.WaitForDeletion(suite.T(), tsRes.Id) +} + +func (suite *controllerSuite) TestReconcile_AvoidReconciliationWriteLoop() { + suite.hcpMock.EXPECT().FetchTelemetryConfig(mock.Anything).Return(&hcpclient.TelemetryConfig{ + MetricsConfig: &hcpclient.MetricsConfig{ + Endpoint: &url.URL{ + Scheme: "http", + Host: "localhost", + Path: "/test", + }, + Labels: map[string]string{"foo": "bar"}, + Filters: regexp.MustCompile(".*"), + }, + RefreshConfig: &hcpclient.RefreshConfig{}, + }, nil) + link := suite.writeLinkResource() + suite.hcpMock.EXPECT().GetObservabilitySecret(mock.Anything).Return("xxx", "yyy", nil) + suite.NoError(suite.ctl.Reconcile(context.Background(), controller.Request{ID: link.Id})) + tsRes := suite.client.WaitForResourceExists(suite.T(), &pbresource.ID{Name: "global", Type: pbhcp.TelemetryStateType}) + suite.NoError(suite.ctl.Reconcile(context.Background(), controller.Request{ID: tsRes.Id})) + suite.client.RequireVersionUnchanged(suite.T(), tsRes.Id, tsRes.Version) +} + +func (suite *controllerSuite) TestController_LinkingDisabled() { + // Run the controller manager + mgr := controller.NewManager(suite.client, suite.rt.Logger) + _, mockClientFn := mockHcpClientFn(suite.T()) + mgr.Register(TelemetryStateController(mockClientFn)) + mgr.SetRaftLeader(true) + go mgr.Run(suite.ctx) + + linkData := &pbhcp.Link{ + ClientId: "abc", + ClientSecret: "abc", + ResourceId: types.GenerateTestResourceID(suite.T()), + } + + rtest.Resource(pbhcp.LinkType, "global"). + WithData(suite.T(), linkData). + WithStatus(link.StatusKey, &pbresource.Status{Conditions: []*pbresource.Condition{link.ConditionDisabled}}). + Write(suite.T(), suite.client) + + suite.client.WaitForDeletion(suite.T(), &pbresource.ID{Name: "global", Type: pbhcp.TelemetryStateType}) +} + +func (suite *controllerSuite) writeLinkResource() *types.DecodedLink { + suite.T().Helper() + + linkData := &pbhcp.Link{ + ClientId: "abc", + ClientSecret: "abc", + ResourceId: types.GenerateTestResourceID(suite.T()), + } + + res := rtest.Resource(pbhcp.LinkType, "global"). + WithData(suite.T(), linkData). + WithStatus(link.StatusKey, &pbresource.Status{Conditions: []*pbresource.Condition{link.ConditionLinked(linkData.ResourceId)}}). + Write(suite.T(), suite.client) + + suite.T().Cleanup(suite.deleteResourceFunc(res.Id)) + link, err := resource.Decode[*pbhcp.Link](res) + require.NoError(suite.T(), err) + return link +} diff --git a/internal/hcp/internal/controllers/telemetrystate/status.go b/internal/hcp/internal/controllers/telemetrystate/status.go new file mode 100644 index 000000000000..d68873b6d91b --- /dev/null +++ b/internal/hcp/internal/controllers/telemetrystate/status.go @@ -0,0 +1,8 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package telemetrystate + +const ( + StatusKey = "consul.io/hcp/telemetry-state" +) diff --git a/internal/hcp/internal/types/link.go b/internal/hcp/internal/types/link.go new file mode 100644 index 000000000000..111f58a85899 --- /dev/null +++ b/internal/hcp/internal/types/link.go @@ -0,0 +1,117 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package types + +import ( + "errors" + + "github.com/hashicorp/go-multierror" + hcpresource "github.com/hashicorp/hcp-sdk-go/resource" + + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/internal/resource" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +type DecodedLink = resource.DecodedResource[*pbhcp.Link] + +const ( + LinkName = "global" + MetadataSourceKey = "source" + MetadataSourceConfig = "config" +) + +var ( + errLinkConfigurationName = errors.New("only a single Link resource is allowed and it must be named global") + errInvalidHCPResourceID = errors.New("could not parse, invalid format") +) + +func RegisterLink(r resource.Registry) { + r.Register(resource.Registration{ + Type: pbhcp.LinkType, + Proto: &pbhcp.Link{}, + Scope: resource.ScopeCluster, + Validate: ValidateLink, + ACLs: &resource.ACLHooks{ + Read: aclReadHookLink, + Write: aclWriteHookLink, + List: aclListHookLink, + }, + }) +} + +func aclReadHookLink(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, _ *pbresource.ID, _ *pbresource.Resource) error { + err := authorizer.ToAllowAuthorizer().OperatorReadAllowed(authzContext) + if err != nil { + return err + } + return nil +} + +func aclWriteHookLink(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, _ *pbresource.Resource) error { + err := authorizer.ToAllowAuthorizer().OperatorWriteAllowed(authzContext) + if err != nil { + return err + } + + err = authorizer.ToAllowAuthorizer().ACLWriteAllowed(authzContext) + if err != nil { + return err + } + + return nil +} + +func aclListHookLink(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext) error { + err := authorizer.ToAllowAuthorizer().OperatorReadAllowed(authzContext) + if err != nil { + return err + } + return nil +} + +var ValidateLink = resource.DecodeAndValidate(validateLink) + +func validateLink(res *DecodedLink) error { + var err error + + if res.Id.Name != LinkName { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "name", + Wrapped: errLinkConfigurationName, + }) + } + + if res.Data.ClientId == "" { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "client_id", + Wrapped: resource.ErrMissing, + }) + } + + if res.Data.ClientSecret == "" { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "client_secret", + Wrapped: resource.ErrMissing, + }) + } + + if res.Data.ResourceId == "" { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "resource_id", + Wrapped: resource.ErrMissing, + }) + } else { + _, parseErr := hcpresource.FromString(res.Data.ResourceId) + if parseErr != nil { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "resource_id", + Wrapped: errInvalidHCPResourceID, + }) + } + } + + return err +} diff --git a/internal/hcp/internal/types/link_test.go b/internal/hcp/internal/types/link_test.go new file mode 100644 index 000000000000..2de25091d276 --- /dev/null +++ b/internal/hcp/internal/types/link_test.go @@ -0,0 +1,205 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/known/anypb" + + "github.com/hashicorp/consul/internal/resource" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +func createCloudLinkResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { + res := &pbresource.Resource{ + Id: &pbresource.ID{ + Type: pbhcp.LinkType, + Name: "global", + }, + } + + var err error + res.Data, err = anypb.New(data) + require.NoError(t, err) + return res +} + +func TestValidateLink_Ok(t *testing.T) { + data := &pbhcp.Link{ + ClientId: "abc", + ClientSecret: "abc", + ResourceId: GenerateTestResourceID(t), + } + + res := createCloudLinkResource(t, data) + + err := ValidateLink(res) + require.NoError(t, err) +} + +func TestValidateLink_ParseError(t *testing.T) { + // Any type other than the Link type would work + // to cause the error we are expecting + data := &pbresource.Type{Group: "a", GroupVersion: "b", Kind: "c"} + + res := createCloudLinkResource(t, data) + + err := ValidateLink(res) + require.Error(t, err) + require.ErrorAs(t, err, &resource.ErrDataParse{}) +} + +func TestValidateLink_InvalidName(t *testing.T) { + data := &pbhcp.Link{ + ClientId: "abc", + ClientSecret: "abc", + ResourceId: GenerateTestResourceID(t), + } + + res := createCloudLinkResource(t, data) + res.Id.Name = "default" + + err := ValidateLink(res) + + expected := resource.ErrInvalidField{ + Name: "name", + Wrapped: errLinkConfigurationName, + } + + var actual resource.ErrInvalidField + require.ErrorAs(t, err, &actual) + require.Equal(t, expected, actual) +} + +func TestValidateLink_MissingClientId(t *testing.T) { + data := &pbhcp.Link{ + ClientId: "", + ClientSecret: "abc", + ResourceId: GenerateTestResourceID(t), + } + + res := createCloudLinkResource(t, data) + + err := ValidateLink(res) + + expected := resource.ErrInvalidField{ + Name: "client_id", + Wrapped: resource.ErrMissing, + } + + var actual resource.ErrInvalidField + require.ErrorAs(t, err, &actual) + require.Equal(t, expected, actual) +} + +func TestValidateLink_MissingClientSecret(t *testing.T) { + data := &pbhcp.Link{ + ClientId: "abc", + ClientSecret: "", + ResourceId: GenerateTestResourceID(t), + } + + res := createCloudLinkResource(t, data) + + err := ValidateLink(res) + + expected := resource.ErrInvalidField{ + Name: "client_secret", + Wrapped: resource.ErrMissing, + } + + var actual resource.ErrInvalidField + require.ErrorAs(t, err, &actual) + require.Equal(t, expected, actual) +} + +func TestValidateLink_MissingResourceId(t *testing.T) { + data := &pbhcp.Link{ + ClientId: "abc", + ClientSecret: "abc", + ResourceId: "", + } + + res := createCloudLinkResource(t, data) + + err := ValidateLink(res) + + expected := resource.ErrInvalidField{ + Name: "resource_id", + Wrapped: resource.ErrMissing, + } + + var actual resource.ErrInvalidField + require.ErrorAs(t, err, &actual) + require.Equal(t, expected, actual) +} + +func TestValidateLink_InvalidResourceId(t *testing.T) { + data := &pbhcp.Link{ + ClientId: "abc", + ClientSecret: "abc", + ResourceId: "abc", + } + + res := createCloudLinkResource(t, data) + + err := ValidateLink(res) + + expected := resource.ErrInvalidField{ + Name: "resource_id", + Wrapped: errInvalidHCPResourceID, + } + + var actual resource.ErrInvalidField + require.ErrorAs(t, err, &actual) + require.Equal(t, expected, actual) +} + +// Currently, we have no specific ACLs configured so the default `operator` permissions are required +func TestLinkACLs(t *testing.T) { + registry := resource.NewRegistry() + RegisterLink(registry) + + data := &pbhcp.Link{ + ClientId: "abc", + ClientSecret: "abc", + ResourceId: GenerateTestResourceID(t), + } + link := createCloudLinkResource(t, data) + + cases := map[string]rtest.ACLTestCase{ + "no rules": { + Rules: ``, + Res: link, + ReadOK: rtest.DENY, + WriteOK: rtest.DENY, + ListOK: rtest.DENY, + }, + "link test read and list": { + Rules: `{"operator": "read"}`, + Res: link, + ReadOK: rtest.ALLOW, + WriteOK: rtest.DENY, + ListOK: rtest.ALLOW, + }, + "link test write": { + Rules: `{"operator": "write", "acl": "write"}`, + Res: link, + ReadOK: rtest.ALLOW, + WriteOK: rtest.ALLOW, + ListOK: rtest.ALLOW, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + rtest.RunACLTestCase(t, tc, registry) + }) + } +} diff --git a/internal/hcp/internal/types/telemetry_state.go b/internal/hcp/internal/types/telemetry_state.go new file mode 100644 index 000000000000..7c6b3971cf1e --- /dev/null +++ b/internal/hcp/internal/types/telemetry_state.go @@ -0,0 +1,85 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package types + +import ( + "errors" + + "github.com/hashicorp/go-multierror" + + "github.com/hashicorp/consul/internal/resource" + pbhcp "github.com/hashicorp/consul/proto-public/pbhcp/v2" +) + +type DecodedTelemetryState = resource.DecodedResource[*pbhcp.TelemetryState] + +var ( + telemetryStateConfigurationNameError = errors.New("only a single Telemetry resource is allowed and it must be named global") +) + +func RegisterTelemetryState(r resource.Registry) { + r.Register(resource.Registration{ + Type: pbhcp.TelemetryStateType, + Proto: &pbhcp.TelemetryState{}, + Scope: resource.ScopeCluster, + Validate: ValidateTelemetryState, + }) +} + +var ValidateTelemetryState = resource.DecodeAndValidate(validateTelemetryState) + +func validateTelemetryState(res *DecodedTelemetryState) error { + var err error + + if res.GetId().GetName() != "global" { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "name", + Wrapped: telemetryStateConfigurationNameError, + }) + } + + if res.GetData().GetClientId() == "" { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "client_id", + Wrapped: resource.ErrMissing, + }) + } + + if res.GetData().GetClientSecret() == "" { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "client_secret", + Wrapped: resource.ErrMissing, + }) + } + + if res.GetData().GetResourceId() == "" { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "resource_id", + Wrapped: resource.ErrMissing, + }) + } + + if res.GetData().GetMetrics().GetEndpoint() == "" { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "metrics.endpoint", + Wrapped: resource.ErrMissing, + }) + } + + if res.GetData().GetMetrics().GetIncludeList() == nil { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "metrics.include_list", + Wrapped: resource.ErrMissing, + }) + } + + if res.GetData().GetMetrics().GetLabels() == nil { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "metrics.labels", + Wrapped: resource.ErrMissing, + }) + } + + return err +} diff --git a/internal/hcp/internal/types/testing.go b/internal/hcp/internal/types/testing.go new file mode 100644 index 000000000000..420f79e920ef --- /dev/null +++ b/internal/hcp/internal/types/testing.go @@ -0,0 +1,23 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package types + +import ( + "fmt" + "testing" + + "github.com/hashicorp/go-uuid" + "github.com/stretchr/testify/require" +) + +func GenerateTestResourceID(t *testing.T) string { + orgID, err := uuid.GenerateUUID() + require.NoError(t, err) + + projectID, err := uuid.GenerateUUID() + require.NoError(t, err) + + template := "organization/%s/project/%s/hashicorp.consul.global-network-manager.cluster/test-cluster" + return fmt.Sprintf(template, orgID, projectID) +} diff --git a/internal/hcp/internal/types/types.go b/internal/hcp/internal/types/types.go new file mode 100644 index 000000000000..17b495fabf6f --- /dev/null +++ b/internal/hcp/internal/types/types.go @@ -0,0 +1,11 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package types + +import "github.com/hashicorp/consul/internal/resource" + +func Register(r resource.Registry) { + RegisterLink(r) + RegisterTelemetryState(r) +} diff --git a/internal/mesh/exports.go b/internal/mesh/exports.go deleted file mode 100644 index 7b4926c5b08c..000000000000 --- a/internal/mesh/exports.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package mesh - -import ( - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" -) - -var ( - // Controller statuses. - - // Routes controller - RoutesStatusKey = routes.StatusKey - RoutesStatusConditionAccepted = routes.StatusConditionAccepted - RoutesStatusConditionAcceptedMissingParentRefReason = routes.MissingParentRefReason - RoutesStatusConditionAcceptedMissingBackendRefReason = routes.MissingBackendRefReason - RoutesStatusConditionAcceptedParentRefOutsideMeshReason = routes.ParentRefOutsideMeshReason - RoutesStatusConditionAcceptedBackendRefOutsideMeshReason = routes.BackendRefOutsideMeshReason - RoutesStatusConditionAcceptedParentRefUsingMeshPortReason = routes.ParentRefUsingMeshPortReason - RoutesStatusConditionAcceptedBackendRefUsingMeshPortReason = routes.BackendRefUsingMeshPortReason - RoutesStatusConditionAcceptedUnknownParentRefPortReason = routes.UnknownParentRefPortReason - RoutesStatusConditionAcceptedUnknownBackendRefPortReason = routes.UnknownBackendRefPortReason - RoutesStatusConditionAcceptedConflictNotBoundToParentRefReason = routes.ConflictNotBoundToParentRefReason -) - -const ( - // Important constants - - NullRouteBackend = types.NullRouteBackend -) - -// RegisterTypes adds all resource types within the "mesh" API group -// to the given type registry -func RegisterTypes(r resource.Registry) { - types.Register(r) -} - -// RegisterControllers registers controllers for the mesh types with -// the given controller Manager. -func RegisterControllers(mgr *controller.Manager, deps ControllerDependencies) { - controllers.Register(mgr, deps) -} - -type TrustDomainFetcher = sidecarproxy.TrustDomainFetcher - -type ControllerDependencies = controllers.Dependencies diff --git a/internal/mesh/internal/controllers/explicitdestinations/controller.go b/internal/mesh/internal/controllers/explicitdestinations/controller.go deleted file mode 100644 index 41eb87289649..000000000000 --- a/internal/mesh/internal/controllers/explicitdestinations/controller.go +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package explicitdestinations - -import ( - "context" - "fmt" - "sort" - - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/explicitdestinations/mapper" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ControllerName = "consul.io/explicit-mapper-controller" - -func Controller(mapper *mapper.Mapper) controller.Controller { - if mapper == nil { - panic("mapper is required") - } - - return controller.ForType(pbmesh.ComputedExplicitDestinationsType). - WithWatch(pbmesh.DestinationsType, mapper.MapDestinations). - WithWatch(pbcatalog.WorkloadType, controller.ReplaceType(pbmesh.ComputedExplicitDestinationsType)). - WithWatch(pbcatalog.ServiceType, mapper.MapService). - WithWatch(pbmesh.ComputedRoutesType, mapper.MapComputedRoute). - WithReconciler(&reconciler{mapper: mapper}) -} - -type reconciler struct { - mapper *mapper.Mapper -} - -func (r *reconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - rt.Logger = rt.Logger.With("controller", ControllerName, "id", req.ID) - - // Look up the associated workload. - workloadID := resource.ReplaceType(pbcatalog.WorkloadType, req.ID) - workload, err := resource.GetDecodedResource[*pbcatalog.Workload](ctx, rt.Client, workloadID) - if err != nil { - rt.Logger.Error("error fetching workload", "error", err) - return err - } - - // If workload is not found, the decoded resource will be nil. - if workload == nil || workload.GetResource() == nil || workload.GetData() == nil { - // When workload is not there, we don't need to manually delete the resource - // because it is owned by the workload. In this case, we skip reconcile - // because there's nothing for us to do. - rt.Logger.Trace("the corresponding workload does not exist", "id", workloadID) - r.mapper.UntrackComputedExplicitDestinations(req.ID) - return nil - } - - // Get existing ComputedExplicitDestinations resource (if any). - ced, err := resource.GetDecodedResource[*pbmesh.ComputedExplicitDestinations](ctx, rt.Client, req.ID) - if err != nil { - rt.Logger.Error("error fetching ComputedExplicitDestinations", "error", err) - return err - } - - // If workload is not on the mesh, we need to delete the resource and return - // as for non-mesh workloads there should be no mapper. - if !workload.GetData().IsMeshEnabled() { - rt.Logger.Trace("workload is not on the mesh, skipping reconcile and deleting any corresponding ComputedDestinations", "id", workloadID) - r.mapper.UntrackComputedExplicitDestinations(req.ID) - - // Delete CED only if it exists. - if ced != nil { - _, err = rt.Client.Delete(ctx, &pbresource.DeleteRequest{Id: req.ID}) - if err != nil { - // If there's an error deleting CD, we want to re-trigger reconcile again. - rt.Logger.Error("error deleting ComputedDestinations", "error", err) - return err - } - } - - // Otherwise, return as there's nothing else for us to do. - return nil - } - - // Now get any mapper that we have in the cache that have selectors matching the name - // of this CD (name-aligned with workload). - destinationIDs := r.mapper.DestinationsForWorkload(req.ID) - rt.Logger.Trace("cached destinations IDs", "ids", destinationIDs) - - decodedDestinations, err := r.fetchDestinations(ctx, rt.Client, destinationIDs, workload) - if err != nil { - rt.Logger.Error("error fetching mapper", "error", err) - return err - } - - if len(decodedDestinations) > 0 { - r.mapper.TrackDestinations(req.ID, decodedDestinations) - } else { - r.mapper.UntrackComputedExplicitDestinations(req.ID) - } - - conflicts := findConflicts(decodedDestinations) - - newComputedDestinationsData := &pbmesh.ComputedExplicitDestinations{} - for _, dst := range decodedDestinations { - updatedStatus := &pbresource.Status{ - ObservedGeneration: dst.GetResource().GetGeneration(), - } - - // First check if this resource has a conflict. If it does, update status and don't include it in the computed resource. - if _, ok := conflicts[resource.NewReferenceKey(dst.GetResource().GetId())]; ok { - rt.Logger.Trace("skipping this Destinations resource because it has conflicts with others", "id", dst.GetResource().GetId()) - updatedStatus.Conditions = append(updatedStatus.Conditions, ConditionConflictFound(workload.GetResource().GetId())) - } else { - valid, cond := validate(ctx, rt.Client, dst) - - // Only add it to computed mapper if its mapper are valid. - if valid { - newComputedDestinationsData.Destinations = append(newComputedDestinationsData.Destinations, dst.GetData().GetDestinations()...) - } else { - rt.Logger.Trace("Destinations is not valid", "condition", cond) - } - - updatedStatus.Conditions = append(updatedStatus.Conditions, ConditionConflictNotFound, cond) - } - - // Write status for this destination. - currentStatus := dst.GetResource().GetStatus()[ControllerName] - - // If the status is unchanged then we should return and avoid the unnecessary write - if !resource.EqualStatus(currentStatus, updatedStatus, false) { - rt.Logger.Trace("updating status", "id", dst.GetResource().GetId()) - _, err = rt.Client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ - Id: dst.GetResource().GetId(), - Key: ControllerName, - Status: updatedStatus, - }) - if err != nil { - rt.Logger.Error("error writing new status", "id", dst.GetResource().GetId(), "error", err) - return err - } - } - } - - // If after fetching and validating, we don't have any destinations, - // we need to skip reconcile and delete the resource. - if len(newComputedDestinationsData.GetDestinations()) == 0 { - rt.Logger.Trace("found no destinations associated with this workload") - - if ced != nil { - rt.Logger.Trace("deleting ComputedDestinations") - _, err = rt.Client.Delete(ctx, &pbresource.DeleteRequest{Id: req.ID}) - if err != nil { - // If there's an error deleting CD, we want to re-trigger reconcile again. - rt.Logger.Error("error deleting ComputedExplicitDestinations", "error", err) - return err - } - } - - return nil - } - - // Lastly, write the resource. - if ced == nil || !proto.Equal(ced.GetData(), newComputedDestinationsData) { - rt.Logger.Trace("writing new ComputedExplicitDestinations") - - // First encode the endpoints data as an Any type. - cpcDataAsAny, err := anypb.New(newComputedDestinationsData) - if err != nil { - rt.Logger.Error("error marshalling latest ComputedExplicitDestinations", "error", err) - return err - } - - _, err = rt.Client.Write(ctx, &pbresource.WriteRequest{ - Resource: &pbresource.Resource{ - Id: req.ID, - Owner: workloadID, - Data: cpcDataAsAny, - }, - }) - if err != nil { - rt.Logger.Error("error writing ComputedExplicitDestinations", "error", err) - return err - } - } - - return nil -} - -func validate( - ctx context.Context, - client pbresource.ResourceServiceClient, - destinations *types.DecodedDestinations) (bool, *pbresource.Condition) { - for _, dest := range destinations.GetData().GetDestinations() { - serviceRef := resource.ReferenceToString(dest.DestinationRef) - - // Fetch and validate service. - service, err := resource.GetDecodedResource[*pbcatalog.Service](ctx, client, resource.IDFromReference(dest.DestinationRef)) - if err != nil { - return false, ConditionDestinationServiceReadError(serviceRef) - } - if service == nil { - return false, ConditionDestinationServiceNotFound(serviceRef) - } - - if !service.GetData().IsMeshEnabled() { - return false, ConditionMeshProtocolNotFound(serviceRef) - } - - if service.GetData().FindServicePort(dest.DestinationPort) != nil && - service.GetData().FindServicePort(dest.DestinationPort).Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - return false, ConditionMeshProtocolDestinationPort(serviceRef, dest.DestinationPort) - } - - // Fetch and validate computed routes for service. - serviceID := resource.IDFromReference(dest.DestinationRef) - cr, err := resource.GetDecodedResource[*pbmesh.ComputedRoutes](ctx, client, resource.ReplaceType(pbmesh.ComputedRoutesType, serviceID)) - if err != nil { - return false, ConditionDestinationComputedRoutesReadErr(serviceRef) - } - if cr == nil { - return false, ConditionDestinationComputedRoutesNotFound(serviceRef) - } - - _, ok := cr.Data.PortedConfigs[dest.DestinationPort] - if !ok { - return false, ConditionDestinationComputedRoutesPortNotFound(serviceRef, dest.DestinationPort) - } - - // Otherwise, continue to the next destination. - } - - return true, ConditionDestinationsAccepted() -} - -func (r *reconciler) fetchDestinations( - ctx context.Context, - client pbresource.ResourceServiceClient, - destinationIDs []*pbresource.ID, - workload *types.DecodedWorkload, -) ([]*types.DecodedDestinations, error) { - // Sort all configs alphabetically. - sort.Slice(destinationIDs, func(i, j int) bool { - return destinationIDs[i].GetName() < destinationIDs[j].GetName() - }) - - var decoded []*types.DecodedDestinations - for _, id := range destinationIDs { - res, err := resource.GetDecodedResource[*pbmesh.Destinations](ctx, client, id) - if err != nil { - return nil, err - } - if res == nil || res.GetResource() == nil || res.GetData() == nil { - // If resource is not found, we should untrack it. - r.mapper.UntrackDestinations(id) - continue - } - - if res.Data.Workloads.Filter != "" { - match, err := resource.FilterMatchesResourceMetadata(workload.Resource, res.Data.Workloads.Filter) - if err != nil { - return nil, fmt.Errorf("error checking selector filters: %w", err) - } - if !match { - continue - } - } - - decoded = append(decoded, res) - } - - return decoded, nil -} - -// Find conflicts finds any resources where listen addresses of the destinations are conflicting. -// It will record both resources as conflicting in the resulting map. -func findConflicts(destinations []*types.DecodedDestinations) map[resource.ReferenceKey]struct{} { - addresses := make(map[string]*pbresource.ID) - duplicates := make(map[resource.ReferenceKey]struct{}) - - for _, decDestinations := range destinations { - for _, dst := range decDestinations.GetData().GetDestinations() { - var address string - - switch dst.ListenAddr.(type) { - case *pbmesh.Destination_IpPort: - listenAddr := dst.GetListenAddr().(*pbmesh.Destination_IpPort) - address = fmt.Sprintf("%s:%d", listenAddr.IpPort.GetIp(), listenAddr.IpPort.GetPort()) - case *pbmesh.Destination_Unix: - listenAddr := dst.GetListenAddr().(*pbmesh.Destination_Unix) - address = listenAddr.Unix.GetPath() - default: - continue - } - - if id, ok := addresses[address]; ok { - // if there's already a listen address for one of the mapper, that means we've found a duplicate. - duplicates[resource.NewReferenceKey(decDestinations.GetResource().GetId())] = struct{}{} - - // Also record the original resource as conflicting one. - duplicates[resource.NewReferenceKey(id)] = struct{}{} - - // Don't evaluate the rest of mapper in this resource because this resource already has a duplicate. - break - } else { - // Otherwise, record this address. - addresses[address] = decDestinations.GetResource().GetId() - } - } - } - - return duplicates -} diff --git a/internal/mesh/internal/controllers/explicitdestinations/controller_test.go b/internal/mesh/internal/controllers/explicitdestinations/controller_test.go deleted file mode 100644 index 72004eecbadb..000000000000 --- a/internal/mesh/internal/controllers/explicitdestinations/controller_test.go +++ /dev/null @@ -1,846 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package explicitdestinations - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - "google.golang.org/protobuf/proto" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/explicitdestinations/mapper" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" -) - -type controllerTestSuite struct { - suite.Suite - - client *resourcetest.Client - runtime controller.Runtime - - ctl *reconciler - ctx context.Context - - workload *pbcatalog.Workload - workloadRes *pbresource.Resource - - dest1 *pbmesh.Destinations - dest2 *pbmesh.Destinations - - destService1 *pbresource.Resource - destService2 *pbresource.Resource - destService3 *pbresource.Resource - - destService1Ref *pbresource.Reference - destService2Ref *pbresource.Reference - destService3Ref *pbresource.Reference - - serviceData *pbcatalog.Service - - destService1Routes *pbmesh.ComputedRoutes - destService2Routes *pbmesh.ComputedRoutes - destService3Routes *pbmesh.ComputedRoutes - - expComputedDest *pbmesh.ComputedExplicitDestinations -} - -func TestFindDuplicates(t *testing.T) { - // Create some conflicting destinations. - dest1 := &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"foo"}, - }, - Destinations: []*pbmesh.Destination{ - { - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 1000, - }, - }, - }, - { - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 2000, - }, - }, - }, - }, - } - dest2 := &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"foo"}, - }, - Destinations: []*pbmesh.Destination{ - { - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 1000, - }, - }, - }, - }, - } - dest3 := &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"foo"}, - }, - Destinations: []*pbmesh.Destination{ - { - ListenAddr: &pbmesh.Destination_Unix{ - Unix: &pbmesh.UnixSocketAddress{ - Path: "/foo/bar", - }, - }, - }, - }, - } - dest4 := &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"foo"}, - }, - Destinations: []*pbmesh.Destination{ - { - ListenAddr: &pbmesh.Destination_Unix{ - Unix: &pbmesh.UnixSocketAddress{ - Path: "/foo/bar", - }, - }, - }, - }, - } - destNonConflicting := &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"foo"}, - }, - Destinations: []*pbmesh.Destination{ - { - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 3000, - }, - }, - }, - { - ListenAddr: &pbmesh.Destination_Unix{ - Unix: &pbmesh.UnixSocketAddress{ - Path: "/baz/bar", - }, - }, - }, - }, - } - - var destinations []*types.DecodedDestinations - dest1Res := resourcetest.Resource(pbmesh.DestinationsType, "dest1"). - WithData(t, dest1). - Build() - destinations = append(destinations, resourcetest.MustDecode[*pbmesh.Destinations](t, dest1Res)) - dest2Res := resourcetest.Resource(pbmesh.DestinationsType, "dest2"). - WithData(t, dest2). - Build() - destinations = append(destinations, resourcetest.MustDecode[*pbmesh.Destinations](t, dest2Res)) - dest3Res := resourcetest.Resource(pbmesh.DestinationsType, "dest3"). - WithData(t, dest3). - Build() - destinations = append(destinations, resourcetest.MustDecode[*pbmesh.Destinations](t, dest3Res)) - dest4Res := resourcetest.Resource(pbmesh.DestinationsType, "dest4"). - WithData(t, dest4). - Build() - destinations = append(destinations, resourcetest.MustDecode[*pbmesh.Destinations](t, dest4Res)) - nonConflictingDestRes := resourcetest.Resource(pbmesh.DestinationsType, "nonConflictingDest"). - WithData(t, destNonConflicting). - Build() - destinations = append(destinations, resourcetest.MustDecode[*pbmesh.Destinations](t, nonConflictingDestRes)) - - duplicates := findConflicts(destinations) - - require.Contains(t, duplicates, resource.NewReferenceKey(dest1Res.Id)) - require.Contains(t, duplicates, resource.NewReferenceKey(dest2Res.Id)) - require.Contains(t, duplicates, resource.NewReferenceKey(dest3Res.Id)) - require.Contains(t, duplicates, resource.NewReferenceKey(dest4Res.Id)) - require.NotContains(t, duplicates, resource.NewReferenceKey(nonConflictingDestRes.Id)) -} - -func (suite *controllerTestSuite) SetupTest() { - resourceClient := svctest.RunResourceService(suite.T(), types.Register, catalog.RegisterTypes) - suite.client = resourcetest.NewClient(resourceClient) - suite.runtime = controller.Runtime{Client: resourceClient, Logger: testutil.Logger(suite.T())} - suite.ctx = testutil.TestContext(suite.T()) - - suite.ctl = &reconciler{ - mapper: mapper.New(), - } - - suite.workload = &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "1.1.1.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - Identity: "test", - } - - suite.workloadRes = resourcetest.Resource(pbcatalog.WorkloadType, "test-workload"). - WithData(suite.T(), suite.workload). - Write(suite.T(), suite.client) - - suite.serviceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"service-1-workloads"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "tcp", - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - { - TargetPort: "admin", - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - { - TargetPort: "mesh", - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - } - suite.destService1 = resourcetest.Resource(pbcatalog.ServiceType, "dest-service-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), suite.serviceData). - Build() - suite.destService2 = resourcetest.Resource(pbcatalog.ServiceType, "dest-service-2"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), suite.serviceData). - Build() - suite.destService3 = resourcetest.Resource(pbcatalog.ServiceType, "dest-service-3"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), suite.serviceData). - Build() - - suite.destService1Ref = resource.Reference(suite.destService1.Id, "") - suite.destService2Ref = resource.Reference(suite.destService2.Id, "") - suite.destService3Ref = resource.Reference(suite.destService3.Id, "") - - suite.destService1Routes = routestest.BuildComputedRoutes(suite.T(), resource.ReplaceType(pbmesh.ComputedRoutesType, suite.destService1.Id), - resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.destService1), - ).GetData() - - suite.destService2Routes = routestest.BuildComputedRoutes(suite.T(), resource.ReplaceType(pbmesh.ComputedRoutesType, suite.destService2.Id), - resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.destService2), - ).GetData() - - suite.destService3Routes = routestest.BuildComputedRoutes(suite.T(), resource.ReplaceType(pbmesh.ComputedRoutesType, suite.destService3.Id), - resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.destService3), - ).GetData() - - suite.dest1 = &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{suite.workloadRes.Id.Name}, - }, - Destinations: []*pbmesh.Destination{ - { - DestinationRef: suite.destService1Ref, - DestinationPort: "tcp", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 1000, - }, - }, - }, - { - DestinationRef: suite.destService2Ref, - DestinationPort: "tcp", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 2000, - }, - }, - }, - }, - } - - suite.dest2 = &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"test-"}, - }, - Destinations: []*pbmesh.Destination{ - { - DestinationRef: suite.destService3Ref, - DestinationPort: "tcp", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 3000, - }, - }, - }, - { - DestinationRef: suite.destService2Ref, - DestinationPort: "admin", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 4000, - }, - }, - }, - }, - } - - suite.expComputedDest = &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: suite.destService1Ref, - DestinationPort: "tcp", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 1000, - }, - }, - }, - { - DestinationRef: suite.destService2Ref, - DestinationPort: "tcp", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 2000, - }, - }, - }, - { - DestinationRef: suite.destService3Ref, - DestinationPort: "tcp", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 3000, - }, - }, - }, - { - DestinationRef: suite.destService2Ref, - DestinationPort: "admin", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 4000, - }, - }, - }, - }, - } -} - -func (suite *controllerTestSuite) TestReconcile_NoWorkload() { - id := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, "not-found").ID() - dest := resourcetest.Resource(pbmesh.DestinationsType, "dest1"). - WithData(suite.T(), suite.dest1). - Build() - decDest := resourcetest.MustDecode[*pbmesh.Destinations](suite.T(), dest) - suite.ctl.mapper.TrackDestinations(id, []*types.DecodedDestinations{decDest}) - - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: id, - }) - require.NoError(suite.T(), err) - - suite.client.RequireResourceNotFound(suite.T(), id) - - // Check that we're not tracking services for this workload anymore. - reqs, err := suite.ctl.mapper.MapService(context.TODO(), controller.Runtime{}, suite.destService1) - require.NoError(suite.T(), err) - require.Nil(suite.T(), reqs) - - reqs, err = suite.ctl.mapper.MapService(context.TODO(), controller.Runtime{}, suite.destService2) - require.NoError(suite.T(), err) - require.Nil(suite.T(), reqs) -} - -func (suite *controllerTestSuite) TestReconcile_NonMeshWorkload() { - resourcetest.Resource(pbcatalog.WorkloadType, "non-mesh"). - WithData(suite.T(), &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "1.1.1.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - }, - }). - Write(suite.T(), suite.client) - - cdID := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, "non-mesh"). - Write(suite.T(), suite.client).Id - - dest := resourcetest.Resource(pbmesh.DestinationsType, "dest1"). - WithData(suite.T(), suite.dest1). - Build() - decDest := resourcetest.MustDecode[*pbmesh.Destinations](suite.T(), dest) - suite.ctl.mapper.TrackDestinations(cdID, []*types.DecodedDestinations{decDest}) - - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cdID, - }) - require.NoError(suite.T(), err) - - suite.client.RequireResourceNotFound(suite.T(), cdID) - - // Check that we're not tracking services for this workload anymore. - reqs, err := suite.ctl.mapper.MapService(context.TODO(), controller.Runtime{}, suite.destService1) - require.NoError(suite.T(), err) - require.Nil(suite.T(), reqs) - - reqs, err = suite.ctl.mapper.MapService(context.TODO(), controller.Runtime{}, suite.destService2) - require.NoError(suite.T(), err) - require.Nil(suite.T(), reqs) -} - -func (suite *controllerTestSuite) writeServices(t *testing.T) { - // Write all services. - resourcetest.Resource(pbcatalog.ServiceType, suite.destService1Ref.Name). - WithData(t, suite.serviceData). - Write(t, suite.client) - resourcetest.Resource(pbcatalog.ServiceType, suite.destService2Ref.Name). - WithData(t, suite.serviceData). - Write(t, suite.client) - resourcetest.Resource(pbcatalog.ServiceType, suite.destService3Ref.Name). - WithData(t, suite.serviceData). - Write(t, suite.client) -} - -func (suite *controllerTestSuite) writeComputedRoutes(t *testing.T) { - // Write computed routes - resourcetest.Resource(pbmesh.ComputedRoutesType, suite.destService1Ref.Name). - WithData(t, suite.destService1Routes). - Write(t, suite.client) - resourcetest.Resource(pbmesh.ComputedRoutesType, suite.destService2Ref.Name). - WithData(t, suite.destService2Routes). - Write(t, suite.client) - resourcetest.Resource(pbmesh.ComputedRoutesType, suite.destService3Ref.Name). - WithData(t, suite.destService3Routes). - Write(t, suite.client) -} - -func (suite *controllerTestSuite) TestReconcile_HappyPath() { - // Add configs in reverse alphabetical order. - d2 := resourcetest.Resource(pbmesh.DestinationsType, "dest2"). - WithData(suite.T(), suite.dest2). - Write(suite.T(), suite.client) - _, err := suite.ctl.mapper.MapDestinations(suite.ctx, suite.runtime, d2) - require.NoError(suite.T(), err) - - d1 := resourcetest.Resource(pbmesh.DestinationsType, "dest1"). - WithData(suite.T(), suite.dest1). - Write(suite.T(), suite.client) - _, err = suite.ctl.mapper.MapDestinations(suite.ctx, suite.runtime, d1) - require.NoError(suite.T(), err) - - suite.writeServices(suite.T()) - suite.writeComputedRoutes(suite.T()) - - cdID := resource.ReplaceType(pbmesh.ComputedExplicitDestinationsType, suite.workloadRes.Id) - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cdID, - }) - - require.NoError(suite.T(), err) - - suite.requireComputedDestinations(suite.T(), cdID) - suite.client.RequireStatusCondition(suite.T(), d1.Id, ControllerName, ConditionDestinationsAccepted()) -} - -func (suite *controllerTestSuite) TestReconcile_NoDestinations() { - dest := resourcetest.Resource(pbmesh.DestinationsType, "dest"). - WithData(suite.T(), suite.dest1). - Build() - _, err := suite.ctl.mapper.MapDestinations(suite.ctx, suite.runtime, dest) - require.NoError(suite.T(), err) - - cdID := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.workloadRes.Id.Name). - Write(suite.T(), suite.client).Id - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cdID, - }) - - require.NoError(suite.T(), err) - - suite.client.RequireResourceNotFound(suite.T(), cdID) -} - -func (suite *controllerTestSuite) TestReconcile_AllDestinationsInvalid() { - // We add a destination with services refs that don't exist which should result - // in computed mapper being deleted because all mapper are invalid. - dest := resourcetest.Resource(pbmesh.DestinationsType, "dest"). - WithData(suite.T(), suite.dest1). - Write(suite.T(), suite.client) - _, err := suite.ctl.mapper.MapDestinations(suite.ctx, suite.runtime, dest) - require.NoError(suite.T(), err) - - cdID := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.workloadRes.Id.Name). - Write(suite.T(), suite.client).Id - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cdID, - }) - - require.NoError(suite.T(), err) - - suite.client.RequireResourceNotFound(suite.T(), cdID) -} - -func (suite *controllerTestSuite) TestReconcile_StatusUpdate_ConflictingDestination() { - dest1 := resourcetest.Resource(pbmesh.DestinationsType, "dest1"). - WithData(suite.T(), suite.dest1). - Write(suite.T(), suite.client) - _, err := suite.ctl.mapper.MapDestinations(suite.ctx, suite.runtime, dest1) - require.NoError(suite.T(), err) - - // Write a conflicting destinations resource. - destData := proto.Clone(suite.dest2).(*pbmesh.Destinations) - destData.Destinations[0] = suite.dest1.Destinations[0] - - dest2 := resourcetest.Resource(pbmesh.DestinationsType, "dest2"). - WithData(suite.T(), destData). - Write(suite.T(), suite.client) - _, err = suite.ctl.mapper.MapDestinations(suite.ctx, suite.runtime, dest2) - require.NoError(suite.T(), err) - - cdID := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.workloadRes.Id.Name). - Write(suite.T(), suite.client).Id - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cdID, - }) - require.NoError(suite.T(), err) - suite.client.RequireResourceNotFound(suite.T(), cdID) - - // Expect that the status on both resource is updated showing conflict. - suite.client.RequireStatusCondition(suite.T(), dest1.Id, ControllerName, - ConditionConflictFound(suite.workloadRes.Id)) - suite.client.RequireStatusCondition(suite.T(), dest2.Id, ControllerName, - ConditionConflictFound(suite.workloadRes.Id)) - - // Update dest2 back to have non-conflicting data. - dest2 = resourcetest.Resource(pbmesh.DestinationsType, "dest2"). - WithData(suite.T(), suite.dest2). - Write(suite.T(), suite.client) - _, err = suite.ctl.mapper.MapDestinations(suite.ctx, suite.runtime, dest2) - require.NoError(suite.T(), err) - - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cdID, - }) - require.NoError(suite.T(), err) - - // Expect status on both to be updated to say that there's no conflict. - suite.client.RequireStatusCondition(suite.T(), dest1.Id, ControllerName, - ConditionConflictNotFound) - suite.client.RequireStatusCondition(suite.T(), dest2.Id, ControllerName, - ConditionConflictNotFound) -} - -func (suite *controllerTestSuite) TestReconcile_StatusUpdate_NoService() { - dest := resourcetest.Resource(pbmesh.DestinationsType, "dest"). - WithData(suite.T(), suite.dest2). - Write(suite.T(), suite.client) - _, err := suite.ctl.mapper.MapDestinations(suite.ctx, suite.runtime, dest) - require.NoError(suite.T(), err) - cdID := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.workloadRes.Id.Name). - Write(suite.T(), suite.client).Id - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cdID, - }) - require.NoError(suite.T(), err) - suite.client.RequireResourceNotFound(suite.T(), cdID) - - suite.client.RequireStatusCondition(suite.T(), dest.Id, ControllerName, - ConditionDestinationServiceNotFound(resource.ReferenceToString(suite.destService3Ref))) -} - -func (suite *controllerTestSuite) TestReconcile_StatusUpdate_ServiceNotOnMesh() { - dest := resourcetest.Resource(pbmesh.DestinationsType, "dest"). - WithData(suite.T(), suite.dest2). - Write(suite.T(), suite.client) - _, err := suite.ctl.mapper.MapDestinations(suite.ctx, suite.runtime, dest) - require.NoError(suite.T(), err) - - resourcetest.Resource(pbcatalog.ServiceType, suite.destService3Ref.Name). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{suite.workloadRes.Id.Name}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "tcp", - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - }, - }). - Write(suite.T(), suite.client) - - cdID := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.workloadRes.Id.Name). - Write(suite.T(), suite.client).Id - - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cdID, - }) - require.NoError(suite.T(), err) - suite.client.RequireResourceNotFound(suite.T(), cdID) - - suite.client.RequireStatusCondition(suite.T(), dest.Id, ControllerName, - ConditionMeshProtocolNotFound(resource.ReferenceToString(suite.destService3Ref))) -} - -func (suite *controllerTestSuite) TestReconcile_StatusUpdate_DestinationPortIsMesh() { - dest := resourcetest.Resource(pbmesh.DestinationsType, "dest"). - WithData(suite.T(), suite.dest2). - Write(suite.T(), suite.client) - _, err := suite.ctl.mapper.MapDestinations(suite.ctx, suite.runtime, dest) - require.NoError(suite.T(), err) - - resourcetest.Resource(pbcatalog.ServiceType, suite.destService3Ref.Name). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{suite.workloadRes.Id.Name}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "tcp", - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - }). - Write(suite.T(), suite.client) - - cdID := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.workloadRes.Id.Name). - Write(suite.T(), suite.client).Id - - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cdID, - }) - require.NoError(suite.T(), err) - suite.client.RequireResourceNotFound(suite.T(), cdID) - - suite.client.RequireStatusCondition(suite.T(), dest.Id, ControllerName, - ConditionMeshProtocolDestinationPort(resource.ReferenceToString(suite.destService3Ref), "tcp")) -} - -func (suite *controllerTestSuite) TestReconcile_StatusUpdate_ComputedRoutesNotFound() { - dest := resourcetest.Resource(pbmesh.DestinationsType, "dest"). - WithData(suite.T(), suite.dest2). - Write(suite.T(), suite.client) - _, err := suite.ctl.mapper.MapDestinations(suite.ctx, suite.runtime, dest) - require.NoError(suite.T(), err) - - resourcetest.Resource(pbcatalog.ServiceType, suite.destService3Ref.Name). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{suite.workloadRes.Id.Name}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "tcp", - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - { - TargetPort: "mesh", - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - }). - Write(suite.T(), suite.client) - - cdID := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.workloadRes.Id.Name). - Write(suite.T(), suite.client).Id - - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cdID, - }) - require.NoError(suite.T(), err) - suite.client.RequireResourceNotFound(suite.T(), cdID) - - suite.client.RequireStatusCondition(suite.T(), dest.Id, ControllerName, - ConditionDestinationComputedRoutesNotFound(resource.ReferenceToString(suite.destService3Ref))) -} - -func (suite *controllerTestSuite) TestReconcile_StatusUpdate_ComputedRoutesPortNotFound() { - dest := resourcetest.Resource(pbmesh.DestinationsType, "dest"). - WithData(suite.T(), suite.dest2). - Write(suite.T(), suite.client) - _, err := suite.ctl.mapper.MapDestinations(suite.ctx, suite.runtime, dest) - require.NoError(suite.T(), err) - - destService := resourcetest.Resource(pbcatalog.ServiceType, suite.destService3Ref.Name). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{suite.workloadRes.Id.Name}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "tcp", - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - { - TargetPort: "mesh", - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - }). - Write(suite.T(), suite.client) - - resourcetest.Resource(pbmesh.ComputedRoutesType, destService.Id.Name). - WithData(suite.T(), &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "some-other-port": { - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{}, - }, - }, - }, - }). - Write(suite.T(), suite.client) - - cdID := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.workloadRes.Id.Name). - Write(suite.T(), suite.client).Id - - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cdID, - }) - require.NoError(suite.T(), err) - suite.client.RequireResourceNotFound(suite.T(), cdID) - - suite.client.RequireStatusCondition(suite.T(), dest.Id, ControllerName, - ConditionDestinationComputedRoutesPortNotFound(resource.ReferenceToString(suite.destService3Ref), "tcp")) -} - -func (suite *controllerTestSuite) TestController() { - mgr := controller.NewManager(suite.client, suite.runtime.Logger) - - m := mapper.New() - mgr.Register(Controller(m)) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - cdID := resource.ReplaceType(pbmesh.ComputedExplicitDestinationsType, suite.workloadRes.Id) - - dest1 := resourcetest.Resource(pbmesh.DestinationsType, "dest1"). - WithData(suite.T(), suite.dest1). - Write(suite.T(), suite.client) - - // At this point, none of the services or routes yet exist and so we should see the status of the destinations - // resource to reflect that. The CED resource should not be created in this case. - testutil.RunStep(suite.T(), "check that destinations status is updated", func(t *testing.T) { - retry.Run(t, func(r *retry.R) { - serviceRef := resource.IDToString(suite.destService1.Id) - suite.client.WaitForStatusCondition(r, dest1.Id, ControllerName, ConditionDestinationServiceNotFound(serviceRef)) - - suite.client.RequireResourceNotFound(r, cdID) - }) - }) - - dest2 := resourcetest.Resource(pbmesh.DestinationsType, "dest2"). - WithData(suite.T(), suite.dest2). - Write(suite.T(), suite.client) - - suite.writeServices(suite.T()) - - // After we write services, we expect another reconciliation to be kicked off to validate and find that there are no computed routes. - testutil.RunStep(suite.T(), "check that destinations status says that there are no computed routes", func(t *testing.T) { - retry.Run(t, func(r *retry.R) { - suite.client.WaitForStatusCondition(r, dest1.Id, ControllerName, - ConditionDestinationComputedRoutesNotFound(resource.IDToString(suite.destService1.Id))) - suite.client.WaitForStatusCondition(r, dest2.Id, ControllerName, - ConditionDestinationComputedRoutesNotFound(resource.IDToString(suite.destService3.Id))) - - suite.client.RequireResourceNotFound(r, cdID) - }) - }) - - // Now write computed routes to get a computed resource. - suite.writeComputedRoutes(suite.T()) - - testutil.RunStep(suite.T(), "computed destinations generation", func(t *testing.T) { - retry.Run(t, func(r *retry.R) { - suite.client.RequireResourceExists(r, cdID) - suite.requireComputedDestinations(r, cdID) - }) - }) - - testutil.RunStep(suite.T(), "add another workload", func(t *testing.T) { - // Create another workload that will match only dest2. - matchingWorkload := resourcetest.Resource(pbcatalog.WorkloadType, "test-extra-workload"). - WithData(t, suite.workload). - Write(t, suite.client) - matchingWorkloadCDID := resource.ReplaceType(pbmesh.ComputedExplicitDestinationsType, matchingWorkload.Id) - - retry.Run(t, func(r *retry.R) { - suite.client.RequireResourceExists(r, cdID) - suite.requireComputedDestinations(r, cdID) - - matchingWorkloadCD := suite.client.RequireResourceExists(r, matchingWorkloadCDID) - dec := resourcetest.MustDecode[*pbmesh.ComputedExplicitDestinations](r, matchingWorkloadCD) - prototest.AssertDeepEqual(r, suite.dest2.GetDestinations(), dec.GetData().GetDestinations()) - }) - }) - - testutil.RunStep(suite.T(), "update workload selector", func(t *testing.T) { - // Update workload selector to no point to some non-existing workload - updatedDestinations := proto.Clone(suite.dest2).(*pbmesh.Destinations) - updatedDestinations.Workloads = &pbcatalog.WorkloadSelector{ - Names: []string{"other-workload"}, - } - - matchingWorkload := resourcetest.Resource(pbcatalog.WorkloadType, "other-workload"). - WithData(t, suite.workload). - Write(t, suite.client) - matchingWorkloadCDID := resource.ReplaceType(pbmesh.ComputedExplicitDestinationsType, matchingWorkload.Id) - resourcetest.Resource(pbmesh.DestinationsType, "dest2"). - WithData(suite.T(), updatedDestinations). - Write(suite.T(), suite.client) - - retry.Run(t, func(r *retry.R) { - res := suite.client.RequireResourceExists(r, cdID) - - // The "test-workload" computed destinations should now be updated to use only proxy dest1. - expDest := &pbmesh.ComputedExplicitDestinations{ - Destinations: suite.dest1.Destinations, - } - dec := resourcetest.MustDecode[*pbmesh.ComputedExplicitDestinations](t, res) - prototest.AssertDeepEqual(r, expDest.GetDestinations(), dec.GetData().GetDestinations()) - - matchingWorkloadCD := suite.client.RequireResourceExists(r, matchingWorkloadCDID) - dec = resourcetest.MustDecode[*pbmesh.ComputedExplicitDestinations](r, matchingWorkloadCD) - prototest.AssertDeepEqual(r, suite.dest2.GetDestinations(), dec.GetData().GetDestinations()) - }) - }) - - // Delete all destinations. - suite.client.MustDelete(suite.T(), dest1.Id) - suite.client.MustDelete(suite.T(), dest2.Id) - - testutil.RunStep(suite.T(), "all destinations are deleted", func(t *testing.T) { - retry.Run(t, func(r *retry.R) { - suite.client.RequireResourceNotFound(r, cdID) - }) - }) -} - -func TestControllerSuite(t *testing.T) { - suite.Run(t, new(controllerTestSuite)) -} - -func (suite *controllerTestSuite) requireComputedDestinations(t resourcetest.T, id *pbresource.ID) { - cdRes := suite.client.RequireResourceExists(t, id) - decCD := resourcetest.MustDecode[*pbmesh.ComputedExplicitDestinations](t, cdRes) - prototest.AssertElementsMatch(t, suite.expComputedDest.GetDestinations(), decCD.Data.GetDestinations()) - resourcetest.RequireOwner(t, cdRes, resource.ReplaceType(pbcatalog.WorkloadType, id), true) -} diff --git a/internal/mesh/internal/controllers/explicitdestinations/mapper/mapper.go b/internal/mesh/internal/controllers/explicitdestinations/mapper/mapper.go deleted file mode 100644 index 48e4cb03f7b0..000000000000 --- a/internal/mesh/internal/controllers/explicitdestinations/mapper/mapper.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package mapper - -import ( - "context" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/mappers/workloadselectionmapper" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type Mapper struct { - workloadSelectionMapper *workloadselectionmapper.Mapper[*pbmesh.Destinations] - - serviceRefMapper *bimapper.Mapper -} - -func New() *Mapper { - return &Mapper{ - workloadSelectionMapper: workloadselectionmapper.New[*pbmesh.Destinations](pbmesh.ComputedExplicitDestinationsType), - serviceRefMapper: bimapper.New(pbmesh.ComputedExplicitDestinationsType, pbcatalog.ServiceType), - } -} - -func (m *Mapper) MapService(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - serviceRef := resource.Reference(res.GetId(), "") - - compDestinations := m.serviceRefMapper.ItemIDsForLink(serviceRef) - - return controller.MakeRequests(pbmesh.ComputedExplicitDestinationsType, compDestinations), nil -} - -func (m *Mapper) MapDestinations(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - return m.workloadSelectionMapper.MapToComputedType(ctx, rt, res) -} - -func (m *Mapper) MapComputedRoute(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - serviceID := resource.ReplaceType(pbcatalog.ServiceType, res.GetId()) - serviceRef := resource.Reference(serviceID, "") - - compDestinations := m.serviceRefMapper.ItemIDsForLink(serviceRef) - - return controller.MakeRequests(pbmesh.ComputedExplicitDestinationsType, compDestinations), nil -} - -func (m *Mapper) TrackDestinations(id *pbresource.ID, destinations []*types.DecodedDestinations) { - var links []resource.ReferenceOrID - for _, dst := range destinations { - for _, d := range dst.GetData().GetDestinations() { - links = append(links, d.DestinationRef) - } - } - - m.serviceRefMapper.TrackItem(id, links) -} - -func (m *Mapper) UntrackComputedExplicitDestinations(id *pbresource.ID) { - m.serviceRefMapper.UntrackItem(id) -} - -func (m *Mapper) UntrackDestinations(id *pbresource.ID) { - m.workloadSelectionMapper.UntrackID(id) -} - -func (m *Mapper) DestinationsForWorkload(id *pbresource.ID) []*pbresource.ID { - return m.workloadSelectionMapper.IDsForWorkload(id) -} diff --git a/internal/mesh/internal/controllers/explicitdestinations/status.go b/internal/mesh/internal/controllers/explicitdestinations/status.go deleted file mode 100644 index 20466561ea59..000000000000 --- a/internal/mesh/internal/controllers/explicitdestinations/status.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package explicitdestinations - -import ( - "fmt" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - StatusConditionDestinationsAccepted = "DestinationsAccepted" - - StatusReasonMeshProtocolNotFound = "MeshPortProtocolNotFound" - StatusReasonMeshProtocolFound = "AllDestinationServicesValid" - - StatusReasonMeshProtocolDestinationPort = "DestinationWithMeshPortProtocol" - - StatusReasonDestinationServiceNotFound = "ServiceNotFound" - StatusReasonDestinationServiceReadError = "ServiceReadError" - - StatusReasonDestinationComputedRoutesNotFound = "ComputedRoutesNotFound" - StatusReasonDestinationComputedRoutesReadError = "ComputedRoutesReadError" - - StatusReasonDestinationComputedRoutesPortNotFound = "ComputedRoutesPortNotFound" - - StatusConditionConflictFound = "ConflictFound" - StatusReasonDuplicateListenAddress = "ConflictingListenAddress" - StatusReasonNoDuplicateListenAddress = "AllListenAddressesAreUnique" -) - -var ConditionConflictNotFound = &pbresource.Condition{ - Type: StatusConditionConflictFound, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonNoDuplicateListenAddress, - Message: "All mapper have unique listen addresses.", -} - -func ConditionConflictFound(workloadID *pbresource.ID) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionConflictFound, - State: pbresource.Condition_STATE_TRUE, - Reason: StatusReasonDuplicateListenAddress, - Message: fmt.Sprintf("Another Destinations resource selecting workload %q configures the same listen address as one of the mapper in this resource. "+ - "This resource will be skipped.", resource.IDToString(workloadID)), - } -} - -func ConditionMeshProtocolNotFound(serviceRef string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionDestinationsAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonMeshProtocolNotFound, - Message: fmt.Sprintf("service %q cannot be referenced as a Destination because it's not mesh-enabled.", serviceRef), - } -} - -func ConditionDestinationsAccepted() *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionDestinationsAccepted, - State: pbresource.Condition_STATE_TRUE, - Reason: StatusReasonMeshProtocolFound, - Message: "all destination services are valid.", - } -} - -func ConditionDestinationServiceNotFound(serviceRef string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionDestinationsAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonDestinationServiceNotFound, - Message: fmt.Sprintf("service %q does not exist.", serviceRef), - } -} - -func ConditionDestinationServiceReadError(serviceRef string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionDestinationsAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonDestinationServiceReadError, - Message: fmt.Sprintf("error reading service %q", serviceRef), - } -} - -func ConditionMeshProtocolDestinationPort(serviceRef, port string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionDestinationsAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonMeshProtocolDestinationPort, - Message: fmt.Sprintf("destination port %q for service %q has PROTOCOL_MESH which is unsupported for destination services", port, serviceRef), - } -} - -func ConditionDestinationComputedRoutesNotFound(serviceRef string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionDestinationsAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonDestinationComputedRoutesNotFound, - Message: fmt.Sprintf("computed routes %q does not exist.", serviceRef), - } -} - -func ConditionDestinationComputedRoutesReadErr(serviceRef string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionDestinationsAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonDestinationComputedRoutesReadError, - Message: fmt.Sprintf("error reading computed routes for %q service.", serviceRef), - } -} - -func ConditionDestinationComputedRoutesPortNotFound(serviceRef, port string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionDestinationsAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonDestinationComputedRoutesPortNotFound, - Message: fmt.Sprintf("computed routes %q does not exist for port %q.", serviceRef, port), - } -} diff --git a/internal/mesh/internal/controllers/proxyconfiguration/controller.go b/internal/mesh/internal/controllers/proxyconfiguration/controller.go deleted file mode 100644 index e0ac5d42ad48..000000000000 --- a/internal/mesh/internal/controllers/proxyconfiguration/controller.go +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxyconfiguration - -import ( - "context" - "fmt" - - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/mappers/workloadselectionmapper" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ControllerName = "consul.io/proxy-configuration-controller" - -func Controller(proxyConfigMapper *workloadselectionmapper.Mapper[*pbmesh.ProxyConfiguration]) controller.Controller { - if proxyConfigMapper == nil { - panic("proxy config mapper is required") - } - - return controller.ForType(pbmesh.ComputedProxyConfigurationType). - WithWatch(pbmesh.ProxyConfigurationType, proxyConfigMapper.MapToComputedType). - WithWatch(pbcatalog.WorkloadType, controller.ReplaceType(pbmesh.ComputedProxyConfigurationType)). - WithReconciler(&reconciler{proxyConfigMapper: proxyConfigMapper}) -} - -type reconciler struct { - proxyConfigMapper *workloadselectionmapper.Mapper[*pbmesh.ProxyConfiguration] -} - -func (r *reconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - rt.Logger = rt.Logger.With("controller", ControllerName, "id", req.ID) - - // Look up the associated workload. - workloadID := resource.ReplaceType(pbcatalog.WorkloadType, req.ID) - workload, err := resource.GetDecodedResource[*pbcatalog.Workload](ctx, rt.Client, workloadID) - if err != nil { - rt.Logger.Error("error fetching workload", "error", err) - return err - } - - // If workload is not found, the decoded resource will be nil. - if workload == nil { - // When workload is not there, we don't need to manually delete the resource - // because it is owned by the workload. In this case, we skip reconcile - // because there's nothing for us to do. - rt.Logger.Trace("the corresponding workload does not exist", "id", workloadID) - return nil - } - - // Get existing ComputedProxyConfiguration resource (if any). - cpc, err := resource.GetDecodedResource[*pbmesh.ComputedProxyConfiguration](ctx, rt.Client, req.ID) - if err != nil { - rt.Logger.Error("error fetching ComputedProxyConfiguration", "error", err) - return err - } - - // If workload is not on the mesh, we need to delete the resource and return - // as for non-mesh workloads there should be no proxy configuration. - if !workload.GetData().IsMeshEnabled() { - rt.Logger.Trace("workload is not on the mesh, skipping reconcile and deleting any corresponding ComputedProxyConfiguration", "id", workloadID) - - // Delete CPC only if it exists. - if cpc != nil { - _, err = rt.Client.Delete(ctx, &pbresource.DeleteRequest{Id: req.ID}) - if err != nil { - // If there's an error deleting CPC, we want to re-trigger reconcile again. - rt.Logger.Error("error deleting ComputedProxyConfiguration", "error", err) - return err - } - } - - // Otherwise, return as there's nothing else for us to do. - return nil - } - - // Now get any proxy configurations IDs that we have in the cache that have selectors matching the name - // of this CPC (name-aligned with the workload). - proxyCfgIDs := r.proxyConfigMapper.IDsForWorkload(req.ID) - rt.Logger.Trace("cached proxy cfg IDs", "ids", proxyCfgIDs) - - decodedProxyCfgs, err := r.fetchProxyConfigs(ctx, rt.Client, proxyCfgIDs, workload) - if err != nil { - rt.Logger.Error("error fetching proxy configurations", "error", err) - return err - } - - // If after fetching, we don't have any proxy configs, we need to skip reconcile and delete the resource. - if len(decodedProxyCfgs) == 0 { - rt.Logger.Trace("found no proxy configurations associated with this workload") - - if cpc != nil { - rt.Logger.Trace("deleting ComputedProxyConfiguration") - _, err = rt.Client.Delete(ctx, &pbresource.DeleteRequest{Id: req.ID}) - if err != nil { - // If there's an error deleting CPC, we want to re-trigger reconcile again. - rt.Logger.Error("error deleting ComputedProxyConfiguration", "error", err) - return err - } - } - - return nil - } - - // Next, we need to sort configs so that we can resolve conflicts. - sortedProxyCfgs := SortProxyConfigurations(decodedProxyCfgs, req.ID.GetName()) - - mergedProxyCfg := &pbmesh.ProxyConfiguration{} - // Walk sorted configs in reverse order so that the ones that take precedence - // do not overwrite the ones that don't. - for i := len(sortedProxyCfgs) - 1; i >= 0; i-- { - proto.Merge(mergedProxyCfg, sortedProxyCfgs[i].GetData()) - } - - newCPCData := &pbmesh.ComputedProxyConfiguration{ - DynamicConfig: mergedProxyCfg.GetDynamicConfig(), - BootstrapConfig: mergedProxyCfg.GetBootstrapConfig(), - } - - // Lastly, write the resource. - if cpc == nil || !proto.Equal(cpc.GetData(), newCPCData) { - rt.Logger.Trace("writing new ComputedProxyConfiguration") - - // First encode the endpoints data as an Any type. - cpcDataAsAny, err := anypb.New(newCPCData) - if err != nil { - rt.Logger.Error("error marshalling latest ComputedProxyConfiguration", "error", err) - return err - } - - _, err = rt.Client.Write(ctx, &pbresource.WriteRequest{ - Resource: &pbresource.Resource{ - Id: req.ID, - Owner: workloadID, - Data: cpcDataAsAny, - }, - }) - if err != nil { - rt.Logger.Error("error writing latest ComputedProxyConfiguration", "error", err) - return err - } - } - - return nil -} - -func (r *reconciler) fetchProxyConfigs( - ctx context.Context, - client pbresource.ResourceServiceClient, - proxyCfgIds []*pbresource.ID, - workload *types.DecodedWorkload, -) ([]*types.DecodedProxyConfiguration, error) { - var decoded []*types.DecodedProxyConfiguration - for _, id := range proxyCfgIds { - res, err := resource.GetDecodedResource[*pbmesh.ProxyConfiguration](ctx, client, id) - if err != nil { - return nil, err - } - if res == nil || res.GetResource() == nil || res.GetData() == nil { - // If resource is not found, we should untrack it. - r.proxyConfigMapper.UntrackID(id) - continue - } - - if res.Data.Workloads.Filter != "" { - match, err := resource.FilterMatchesResourceMetadata(workload.Resource, res.Data.Workloads.Filter) - if err != nil { - return nil, fmt.Errorf("error checking selector filters: %w", err) - } - if !match { - continue - } - } - - decoded = append(decoded, res) - } - - return decoded, nil -} diff --git a/internal/mesh/internal/controllers/proxyconfiguration/controller_test.go b/internal/mesh/internal/controllers/proxyconfiguration/controller_test.go deleted file mode 100644 index 554f57ab5a06..000000000000 --- a/internal/mesh/internal/controllers/proxyconfiguration/controller_test.go +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxyconfiguration - -import ( - "context" - "testing" - "time" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/durationpb" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/mappers/workloadselectionmapper" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/iptables" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" -) - -type controllerTestSuite struct { - suite.Suite - - client *resourcetest.Client - runtime controller.Runtime - - ctl *reconciler - ctx context.Context - - workload *pbcatalog.Workload - workloadRes *pbresource.Resource - - proxyCfg1 *pbmesh.ProxyConfiguration - proxyCfg2 *pbmesh.ProxyConfiguration - proxyCfg3 *pbmesh.ProxyConfiguration - - expComputedProxyCfg *pbmesh.ComputedProxyConfiguration -} - -func (suite *controllerTestSuite) SetupTest() { - resourceClient := svctest.RunResourceService(suite.T(), types.Register, catalog.RegisterTypes) - suite.client = resourcetest.NewClient(resourceClient) - suite.runtime = controller.Runtime{Client: resourceClient, Logger: testutil.Logger(suite.T())} - suite.ctx = testutil.TestContext(suite.T()) - - suite.ctl = &reconciler{ - proxyConfigMapper: workloadselectionmapper.New[*pbmesh.ProxyConfiguration](pbmesh.ComputedProxyConfigurationType), - } - - suite.workload = &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "1.1.1.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - Identity: "test", - } - - suite.workloadRes = resourcetest.Resource(pbcatalog.WorkloadType, "test-workload"). - WithData(suite.T(), suite.workload). - Write(suite.T(), suite.client) - - suite.proxyCfg1 = &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{suite.workloadRes.Id.Name}, - }, - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - }, - } - - suite.proxyCfg2 = &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"test-"}, - }, - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_DIRECT, // this setting should be overridden by proxycfg1 - LocalConnection: map[string]*pbmesh.ConnectionConfig{ - "tcp": {ConnectTimeout: durationpb.New(2 * time.Second)}, - }, - }, - } - - suite.proxyCfg3 = &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"test-wor"}, - }, - BootstrapConfig: &pbmesh.BootstrapConfig{ - PrometheusBindAddr: "0.0.0.0:9000", - }, - } - - suite.expComputedProxyCfg = &pbmesh.ComputedProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - TransparentProxy: &pbmesh.TransparentProxy{OutboundListenerPort: iptables.DefaultTProxyOutboundPort}, - LocalConnection: map[string]*pbmesh.ConnectionConfig{ - "tcp": {ConnectTimeout: durationpb.New(2 * time.Second)}, - }, - }, - BootstrapConfig: &pbmesh.BootstrapConfig{ - PrometheusBindAddr: "0.0.0.0:9000", - }, - } -} - -func (suite *controllerTestSuite) TestReconcile_NoWorkload() { - // This test ensures that removed workloads are ignored and don't result - // in the creation of the proxy state template. - id := resourcetest.Resource(pbmesh.ComputedProxyConfigurationType, "not-found").ID() - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: id, - }) - require.NoError(suite.T(), err) - - suite.client.RequireResourceNotFound(suite.T(), id) -} - -func (suite *controllerTestSuite) TestReconcile_NonMeshWorkload() { - resourcetest.Resource(pbcatalog.WorkloadType, "non-mesh"). - WithData(suite.T(), &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "1.1.1.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - }, - }). - Write(suite.T(), suite.client) - - cpcID := resourcetest.Resource(pbmesh.ComputedProxyConfigurationType, "non-mesh"). - Write(suite.T(), suite.client).Id - - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cpcID, - }) - require.NoError(suite.T(), err) - - suite.client.RequireResourceNotFound(suite.T(), cpcID) -} - -func (suite *controllerTestSuite) TestReconcile_HappyPath() { - // Write all three proxy cfgs. - pCfg1 := resourcetest.Resource(pbmesh.ProxyConfigurationType, "cfg1"). - WithData(suite.T(), suite.proxyCfg1). - Write(suite.T(), suite.client) - _, err := suite.ctl.proxyConfigMapper.MapToComputedType(suite.ctx, suite.runtime, pCfg1) - require.NoError(suite.T(), err) - - pCfg2 := resourcetest.Resource(pbmesh.ProxyConfigurationType, "cfg2"). - WithData(suite.T(), suite.proxyCfg2). - Write(suite.T(), suite.client) - _, err = suite.ctl.proxyConfigMapper.MapToComputedType(suite.ctx, suite.runtime, pCfg2) - require.NoError(suite.T(), err) - - pCfg3 := resourcetest.Resource(pbmesh.ProxyConfigurationType, "cfg3"). - WithData(suite.T(), suite.proxyCfg3). - Write(suite.T(), suite.client) - _, err = suite.ctl.proxyConfigMapper.MapToComputedType(suite.ctx, suite.runtime, pCfg3) - require.NoError(suite.T(), err) - - cpcID := resource.ReplaceType(pbmesh.ComputedProxyConfigurationType, suite.workloadRes.Id) - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cpcID, - }) - - require.NoError(suite.T(), err) - - suite.requireComputedProxyConfiguration(suite.T(), cpcID) -} - -func (suite *controllerTestSuite) TestReconcile_NoProxyConfigs() { - // Create a proxy cfg and map it so that it gets saved to cache. - pCfg1 := resourcetest.Resource(pbmesh.ProxyConfigurationType, "cfg1"). - WithData(suite.T(), suite.proxyCfg1). - Build() - _, err := suite.ctl.proxyConfigMapper.MapToComputedType(suite.ctx, suite.runtime, pCfg1) - require.NoError(suite.T(), err) - - cpcID := resourcetest.Resource(pbmesh.ComputedProxyConfigurationType, suite.workloadRes.Id.Name). - Write(suite.T(), suite.client).Id - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: cpcID, - }) - - require.NoError(suite.T(), err) - - suite.client.RequireResourceNotFound(suite.T(), cpcID) -} - -func (suite *controllerTestSuite) TestController() { - // Run the controller manager - mgr := controller.NewManager(suite.client, suite.runtime.Logger) - - m := workloadselectionmapper.New[*pbmesh.ProxyConfiguration](pbmesh.ComputedProxyConfigurationType) - mgr.Register(Controller(m)) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - // Write proxy configs. - pCfg1 := resourcetest.Resource(pbmesh.ProxyConfigurationType, "cfg1"). - WithData(suite.T(), suite.proxyCfg1). - Write(suite.T(), suite.client) - - pCfg2 := resourcetest.Resource(pbmesh.ProxyConfigurationType, "cfg2"). - WithData(suite.T(), suite.proxyCfg2). - Write(suite.T(), suite.client) - - pCfg3 := resourcetest.Resource(pbmesh.ProxyConfigurationType, "cfg3"). - WithData(suite.T(), suite.proxyCfg3). - Write(suite.T(), suite.client) - - cpcID := resource.ReplaceType(pbmesh.ComputedProxyConfigurationType, suite.workloadRes.Id) - testutil.RunStep(suite.T(), "computed proxy config generation", func(t *testing.T) { - retry.Run(t, func(r *retry.R) { - suite.client.RequireResourceExists(r, cpcID) - suite.requireComputedProxyConfiguration(r, cpcID) - }) - }) - - testutil.RunStep(suite.T(), "add another workload", func(t *testing.T) { - // Create another workload that will match only proxyCfg2. - matchingWorkload := resourcetest.Resource(pbcatalog.WorkloadType, "test-extra-workload"). - WithData(t, suite.workload). - Write(t, suite.client) - matchingWorkloadCPCID := resource.ReplaceType(pbmesh.ComputedProxyConfigurationType, matchingWorkload.Id) - - retry.Run(t, func(r *retry.R) { - suite.client.RequireResourceExists(r, cpcID) - suite.requireComputedProxyConfiguration(r, cpcID) - - matchingWorkloadCPC := suite.client.RequireResourceExists(r, matchingWorkloadCPCID) - dec := resourcetest.MustDecode[*pbmesh.ComputedProxyConfiguration](r, matchingWorkloadCPC) - prototest.AssertDeepEqual(r, suite.proxyCfg2.GetDynamicConfig(), dec.GetData().GetDynamicConfig()) - prototest.AssertDeepEqual(r, suite.proxyCfg2.GetBootstrapConfig(), dec.GetData().GetBootstrapConfig()) - }) - }) - - testutil.RunStep(suite.T(), "update proxy config selector", func(t *testing.T) { - // Update proxy config selector to no longer select "test-workload" - updatedProxyCfg := proto.Clone(suite.proxyCfg2).(*pbmesh.ProxyConfiguration) - updatedProxyCfg.Workloads = &pbcatalog.WorkloadSelector{ - Names: []string{"test-extra-workload"}, - } - - matchingWorkload := resourcetest.Resource(pbcatalog.WorkloadType, "test-extra-workload"). - WithData(t, suite.workload). - Write(t, suite.client) - matchingWorkloadCPCID := resource.ReplaceType(pbmesh.ComputedProxyConfigurationType, matchingWorkload.Id) - resourcetest.Resource(pbmesh.ProxyConfigurationType, "cfg2"). - WithData(suite.T(), updatedProxyCfg). - Write(suite.T(), suite.client) - - retry.Run(t, func(r *retry.R) { - res := suite.client.RequireResourceExists(r, cpcID) - - // The "test-workload" computed proxy configurations should now be updated to use only proxy cfg 1 and 3. - expProxyCfg := &pbmesh.ComputedProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - TransparentProxy: &pbmesh.TransparentProxy{OutboundListenerPort: iptables.DefaultTProxyOutboundPort}, - }, - BootstrapConfig: &pbmesh.BootstrapConfig{ - PrometheusBindAddr: "0.0.0.0:9000", - }, - } - dec := resourcetest.MustDecode[*pbmesh.ComputedProxyConfiguration](t, res) - prototest.AssertDeepEqual(r, expProxyCfg.GetDynamicConfig(), dec.GetData().GetDynamicConfig()) - prototest.AssertDeepEqual(r, expProxyCfg.GetBootstrapConfig(), dec.GetData().GetBootstrapConfig()) - - matchingWorkloadCPC := suite.client.RequireResourceExists(r, matchingWorkloadCPCID) - dec = resourcetest.MustDecode[*pbmesh.ComputedProxyConfiguration](r, matchingWorkloadCPC) - prototest.AssertDeepEqual(r, suite.proxyCfg2.GetDynamicConfig(), dec.GetData().GetDynamicConfig()) - prototest.AssertDeepEqual(r, suite.proxyCfg2.GetBootstrapConfig(), dec.GetData().GetBootstrapConfig()) - }) - }) - - // Delete all proxy cfgs. - suite.client.MustDelete(suite.T(), pCfg1.Id) - suite.client.MustDelete(suite.T(), pCfg2.Id) - suite.client.MustDelete(suite.T(), pCfg3.Id) - - testutil.RunStep(suite.T(), "all proxy configs are deleted", func(t *testing.T) { - retry.Run(t, func(r *retry.R) { - suite.client.RequireResourceNotFound(r, cpcID) - }) - }) -} - -func TestControllerSuite(t *testing.T) { - suite.Run(t, new(controllerTestSuite)) -} - -func (suite *controllerTestSuite) requireComputedProxyConfiguration(t resourcetest.T, id *pbresource.ID) { - cpcRes := suite.client.RequireResourceExists(t, id) - decCPC := resourcetest.MustDecode[*pbmesh.ComputedProxyConfiguration](t, cpcRes) - prototest.AssertDeepEqual(t, suite.expComputedProxyCfg, decCPC.Data) - resourcetest.RequireOwner(t, cpcRes, resource.ReplaceType(pbcatalog.WorkloadType, id), true) -} diff --git a/internal/mesh/internal/controllers/proxyconfiguration/sort.go b/internal/mesh/internal/controllers/proxyconfiguration/sort.go deleted file mode 100644 index 771286899d0c..000000000000 --- a/internal/mesh/internal/controllers/proxyconfiguration/sort.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxyconfiguration - -import ( - "sort" - "strings" - - "github.com/oklog/ulid/v2" - "golang.org/x/exp/slices" - - "github.com/hashicorp/consul/internal/mesh/internal/types" -) - -// SortProxyConfigurations sorts proxy configurations using the following rules: -// -// 1. Proxy config with a more specific selector wins. For example, -// if there's a proxy config with a name selector and another conflicting -// with a prefix selector, we will choose the one that selects by name because -// it's more specific. For two prefix-based conflicting proxy configs, we will choose -// the one that has the longer prefix. -// 2. Otherwise, the proxy configuration created first (i.e. with an earlier timestamp) wins. -// 3. Lastly, if creation timestamps are the same, the conflict will be resolved using lexicographic -// order. -// -// It returns them in order such that proxy configurations that take precedence occur first in the list. -func SortProxyConfigurations(proxyCfgs []*types.DecodedProxyConfiguration, workloadName string) []*types.DecodedProxyConfiguration { - // Shallow-copy proxy configs so that we don't mutate the original slice. - proxyCfgsToSort := make([]*types.DecodedProxyConfiguration, len(proxyCfgs)) - for i, cfg := range proxyCfgs { - proxyCfgsToSort[i] = cfg - } - - sorter := proxyCfgsSorter{ - proxyCfgs: proxyCfgsToSort, - workloadName: workloadName, - } - - sort.Sort(sorter) - - return sorter.proxyCfgs -} - -type proxyCfgsSorter struct { - proxyCfgs []*types.DecodedProxyConfiguration - workloadName string -} - -func (p proxyCfgsSorter) Len() int { return len(p.proxyCfgs) } - -// Less returns true if i-th element is less than j-th element. -func (p proxyCfgsSorter) Less(i, j int) bool { - iPrefixMatch := p.findLongestPrefixMatch(i) - iMatchesByName := p.matchesByName(i) - - jPrefixMatch := p.findLongestPrefixMatch(j) - jMatchesByName := p.matchesByName(j) - - switch { - // If i matches by name but j doesn't, then i should come before j. - case iMatchesByName && !jMatchesByName: - return true - case !iMatchesByName && jMatchesByName: - return false - case !iMatchesByName && !jMatchesByName: - if len(iPrefixMatch) != len(jPrefixMatch) { - // In this case, the longest prefix wins. - return len(iPrefixMatch) > len(jPrefixMatch) - } - - // Fallthrough to the default case if lengths of prefix matches are the same. - fallthrough - case iMatchesByName && jMatchesByName: - fallthrough - default: - iID := ulid.MustParse(p.proxyCfgs[i].Resource.Id.Uid) - jID := ulid.MustParse(p.proxyCfgs[j].Resource.Id.Uid) - if iID.Time() != jID.Time() { - return iID.Time() < jID.Time() - } else { - // It's impossible for names to be equal, and so we are checking if - // i's name is "less" lexicographically than j's name. - return p.proxyCfgs[i].GetResource().GetId().GetName() < p.proxyCfgs[j].GetResource().GetId().GetName() - } - } -} - -func (p proxyCfgsSorter) Swap(i, j int) { - p.proxyCfgs[i], p.proxyCfgs[j] = p.proxyCfgs[j], p.proxyCfgs[i] -} - -func (p proxyCfgsSorter) matchesByName(idx int) bool { - return slices.Contains(p.proxyCfgs[idx].GetData().GetWorkloads().GetNames(), p.workloadName) -} - -func (p proxyCfgsSorter) findLongestPrefixMatch(idx int) string { - var prefixMatch string - for _, prefix := range p.proxyCfgs[idx].GetData().GetWorkloads().GetPrefixes() { - if strings.Contains(p.workloadName, prefix) && - len(prefix) > len(prefixMatch) { - - prefixMatch = prefix - } - } - - return prefixMatch -} diff --git a/internal/mesh/internal/controllers/proxyconfiguration/sort_test.go b/internal/mesh/internal/controllers/proxyconfiguration/sort_test.go deleted file mode 100644 index 1fbf8254ee60..000000000000 --- a/internal/mesh/internal/controllers/proxyconfiguration/sort_test.go +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxyconfiguration - -import ( - "fmt" - "testing" - "time" - - "github.com/oklog/ulid/v2" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestSortProxyConfigurations(t *testing.T) { - workloadName := "foo-123" - cases := map[string]struct { - selectors []*pbcatalog.WorkloadSelector - expSortedIndices []int - }{ - "first matched by name, second by prefix": { - selectors: []*pbcatalog.WorkloadSelector{ - { - Names: []string{workloadName}, - }, - { - Prefixes: []string{"foo-"}, - }, - }, - expSortedIndices: []int{0, 1}, - }, - "first matched by prefix, second by name": { - selectors: []*pbcatalog.WorkloadSelector{ - { - Prefixes: []string{"foo-"}, - }, - { - Names: []string{workloadName}, - }, - }, - expSortedIndices: []int{1, 0}, - }, - "both matched by name (sorted order should match the order of creation)": { - selectors: []*pbcatalog.WorkloadSelector{ - { - Names: []string{workloadName}, - }, - { - Names: []string{workloadName}, - }, - }, - expSortedIndices: []int{0, 1}, - }, - "both matched by different prefix": { - selectors: []*pbcatalog.WorkloadSelector{ - { - Prefixes: []string{"foo"}, - }, - { - Prefixes: []string{"foo-"}, - }, - }, - expSortedIndices: []int{1, 0}, - }, - "both matched by the same prefix": { - selectors: []*pbcatalog.WorkloadSelector{ - { - Prefixes: []string{"foo-"}, - }, - { - Prefixes: []string{"foo-"}, - }, - }, - expSortedIndices: []int{0, 1}, - }, - "both matched by the multiple different prefixes": { - selectors: []*pbcatalog.WorkloadSelector{ - { - Prefixes: []string{"foo-1", "foo-"}, - }, - { - Prefixes: []string{"foo-1", "foo-12"}, - }, - }, - expSortedIndices: []int{1, 0}, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - resourceClient := svctest.RunResourceService(t, types.Register) - - var decProxyCfgs []*types.DecodedProxyConfiguration - for i, ws := range c.selectors { - proxyCfg := &pbmesh.ProxyConfiguration{ - Workloads: ws, - DynamicConfig: &pbmesh.DynamicConfig{}, - } - resName := fmt.Sprintf("cfg-%d", i) - proxyCfgRes := resourcetest.Resource(pbmesh.ProxyConfigurationType, resName). - WithData(t, proxyCfg). - // We need to run it through resource service so that ULIDs are set. - Write(t, resourceClient) - decProxyCfgs = append(decProxyCfgs, resourcetest.MustDecode[*pbmesh.ProxyConfiguration](t, proxyCfgRes)) - - // Wait for a few milliseconds so that creation timestamp will always be different between resources. - time.Sleep(2 * time.Millisecond) - } - - sortedCfgs := SortProxyConfigurations(decProxyCfgs, workloadName) - - for i, idx := range c.expSortedIndices { - prototest.AssertDeepEqual(t, decProxyCfgs[idx], sortedCfgs[i]) - } - }) - } -} - -func TestSortProxyConfigurations_SameCreationTime(t *testing.T) { - var decProxyCfgs []*types.DecodedProxyConfiguration - - proxyCfg := &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"foo-123"}, - }, - } - - // Make cfg1 name such that it should appear after cfg2 lexicographically. - cfg1 := resourcetest.Resource(pbmesh.ProxyConfigurationType, "def-cfg-1"). - WithData(t, proxyCfg). - Build() - // Explicitly set ulid. For the first one, we'll just the current timestamp. - cfg1.Id.Uid = ulid.Make().String() - - decProxyCfgs = append(decProxyCfgs, resourcetest.MustDecode[*pbmesh.ProxyConfiguration](t, cfg1)) - - cfg2 := resourcetest.Resource(pbmesh.ProxyConfigurationType, "abc-cfg-2"). - WithData(t, proxyCfg). - Build() - // Explicitly set ulid. For the second one, we'll the timestamp of the first one. - parsedCfg1Ulid := ulid.MustParse(cfg1.Id.Uid) - cfg2.Id.Uid = ulid.MustNew(parsedCfg1Ulid.Time(), ulid.DefaultEntropy()).String() - - decProxyCfgs = append(decProxyCfgs, resourcetest.MustDecode[*pbmesh.ProxyConfiguration](t, cfg2)) - - sortedCfgs := SortProxyConfigurations(decProxyCfgs, "foo-123") - - // We expect that given the same creation timestamp, the second proxy cfg should be first - // in the sorted order because of its name. - prototest.AssertDeepEqual(t, decProxyCfgs[0], sortedCfgs[1]) - prototest.AssertDeepEqual(t, decProxyCfgs[1], sortedCfgs[0]) -} diff --git a/internal/mesh/internal/controllers/register.go b/internal/mesh/internal/controllers/register.go deleted file mode 100644 index fec92dba1b30..000000000000 --- a/internal/mesh/internal/controllers/register.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package controllers - -import ( - "context" - - "github.com/hashicorp/consul/agent/leafcert" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/explicitdestinations" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/explicitdestinations/mapper" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/proxyconfiguration" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/cache" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/xds" - "github.com/hashicorp/consul/internal/mesh/internal/mappers/workloadselectionmapper" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" -) - -type Dependencies struct { - TrustDomainFetcher sidecarproxy.TrustDomainFetcher - LocalDatacenter string - DefaultAllow bool - TrustBundleFetcher xds.TrustBundleFetcher - ProxyUpdater xds.ProxyUpdater - LeafCertManager *leafcert.Manager -} - -func Register(mgr *controller.Manager, deps Dependencies) { - endpointsMapper := bimapper.New(pbmesh.ProxyStateTemplateType, pbcatalog.ServiceEndpointsType) - leafMapper := &xds.LeafMapper{ - Mapper: bimapper.New(pbmesh.ProxyStateTemplateType, xds.InternalLeafType), - } - leafCancels := &xds.LeafCancels{ - Cancels: make(map[string]context.CancelFunc), - } - mgr.Register(xds.Controller(endpointsMapper, deps.ProxyUpdater, deps.TrustBundleFetcher, deps.LeafCertManager, leafMapper, leafCancels, deps.LocalDatacenter)) - - mgr.Register( - sidecarproxy.Controller(cache.New(), deps.TrustDomainFetcher, deps.LocalDatacenter, deps.DefaultAllow), - ) - - mgr.Register(routes.Controller()) - - mgr.Register(proxyconfiguration.Controller(workloadselectionmapper.New[*pbmesh.ProxyConfiguration](pbmesh.ComputedProxyConfigurationType))) - mgr.Register(explicitdestinations.Controller(mapper.New())) -} diff --git a/internal/mesh/internal/controllers/routes/controller.go b/internal/mesh/internal/controllers/routes/controller.go deleted file mode 100644 index e55bac45ccb7..000000000000 --- a/internal/mesh/internal/controllers/routes/controller.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routes - -import ( - "context" - - "github.com/hashicorp/go-hclog" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/loader" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/xroutemapper" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func Controller() controller.Controller { - mapper := xroutemapper.New() - - r := &routesReconciler{ - mapper: mapper, - } - return controller.ForType(pbmesh.ComputedRoutesType). - WithWatch(pbmesh.HTTPRouteType, mapper.MapHTTPRoute). - WithWatch(pbmesh.GRPCRouteType, mapper.MapGRPCRoute). - WithWatch(pbmesh.TCPRouteType, mapper.MapTCPRoute). - WithWatch(pbmesh.DestinationPolicyType, mapper.MapDestinationPolicy). - WithWatch(pbcatalog.FailoverPolicyType, mapper.MapFailoverPolicy). - WithWatch(pbcatalog.ServiceType, mapper.MapService). - WithReconciler(r) -} - -type routesReconciler struct { - mapper *xroutemapper.Mapper -} - -func (r *routesReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - // Notably don't inject the resource-id here into the logger, since we have - // to do a fan-out to multiple resources due to xRoutes having multiple - // parent refs. - rt.Logger = rt.Logger.With("controller", StatusKey) - - rt.Logger.Trace("reconciling computed routes") - - loggerFor := func(id *pbresource.ID) hclog.Logger { - return rt.Logger.With("resource-id", id) - } - related, err := loader.LoadResourcesForComputedRoutes(ctx, loggerFor, rt.Client, r.mapper, req.ID) - if err != nil { - rt.Logger.Error("error loading relevant resources", "error", err) - return err - } - - pending := make(PendingStatuses) - - ValidateXRouteReferences(related, pending) - - generatedResults := GenerateComputedRoutes(related, pending) - - if err := UpdatePendingStatuses(ctx, rt, pending); err != nil { - rt.Logger.Error("error updating statuses for affected relevant resources", "error", err) - return err - } - - for _, result := range generatedResults { - computedRoutesID := result.ID - - logger := rt.Logger.With("resource-id", computedRoutesID) - - prev, err := resource.GetDecodedResource[*pbmesh.ComputedRoutes](ctx, rt.Client, computedRoutesID) - if err != nil { - logger.Error("error loading previous computed routes", "error", err) - return err - } - - if prev != nil { - r.mapper.TrackComputedRoutes(prev) - } else { - r.mapper.UntrackComputedRoutes(computedRoutesID) - } - - if err := ensureComputedRoutesIsSynced(ctx, logger, rt.Client, result, prev); err != nil { - return err - } - } - - return nil -} - -func ensureComputedRoutesIsSynced( - ctx context.Context, - logger hclog.Logger, - client pbresource.ResourceServiceClient, - result *ComputedRoutesResult, - prev *types.DecodedComputedRoutes, -) error { - if result.Data == nil { - return deleteComputedRoutes(ctx, logger, client, prev) - } - - // Upsert the resource if changed. - if prev != nil { - if proto.Equal(prev.Data, result.Data) { - return nil // no change - } - result.ID = prev.Resource.Id - } - - return upsertComputedRoutes(ctx, logger, client, result.ID, result.OwnerID, result.Data) -} - -func upsertComputedRoutes( - ctx context.Context, - logger hclog.Logger, - client pbresource.ResourceServiceClient, - id *pbresource.ID, - ownerID *pbresource.ID, - data *pbmesh.ComputedRoutes, -) error { - mcData, err := anypb.New(data) - if err != nil { - logger.Error("error marshalling new computed routes payload", "error", err) - return err - } - - // Now perform the write. The computed routes resource should be owned - // by the service so that it will automatically be deleted upon service - // deletion. - - _, err = client.Write(ctx, &pbresource.WriteRequest{ - Resource: &pbresource.Resource{ - Id: id, - Owner: ownerID, - Data: mcData, - }, - }) - if err != nil { - logger.Error("error writing computed routes", "error", err) - return err - } - - logger.Trace("updated computed routes resource was successfully written") - - return nil -} - -func deleteComputedRoutes( - ctx context.Context, - logger hclog.Logger, - client pbresource.ResourceServiceClient, - prev *types.DecodedComputedRoutes, -) error { - if prev == nil { - return nil - } - - // The service the computed routes controls no longer participates in the - // mesh at all. - - logger.Trace("removing previous computed routes") - - // This performs a CAS deletion. - _, err := client.Delete(ctx, &pbresource.DeleteRequest{ - Id: prev.Resource.Id, - Version: prev.Resource.Version, - }) - // Potentially we could look for CAS failures by checking if the gRPC - // status code is Aborted. However its an edge case and there could - // possibly be other reasons why the gRPC status code would be aborted - // besides CAS version mismatches. The simplest thing to do is to just - // propagate the error and retry reconciliation later. - if err != nil { - logger.Error("error deleting previous computed routes resource", "error", err) - return err - } - - return nil -} diff --git a/internal/mesh/internal/controllers/routes/controller_test.go b/internal/mesh/internal/controllers/routes/controller_test.go deleted file mode 100644 index 653eac28ed15..000000000000 --- a/internal/mesh/internal/controllers/routes/controller_test.go +++ /dev/null @@ -1,1340 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routes - -import ( - "context" - "fmt" - "testing" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" -) - -type controllerSuite struct { - suite.Suite - - ctx context.Context - client *rtest.Client - rt controller.Runtime -} - -func (suite *controllerSuite) SetupTest() { - suite.ctx = testutil.TestContext(suite.T()) - client := svctest.RunResourceService(suite.T(), types.Register, catalog.RegisterTypes) - suite.rt = controller.Runtime{ - Client: client, - Logger: testutil.Logger(suite.T()), - } - suite.client = rtest.NewClient(client) -} - -func (suite *controllerSuite) TestController() { - mgr := controller.NewManager(suite.client, suite.rt.Logger) - mgr.Register(Controller()) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - backendName := func(name, port string) string { - return fmt.Sprintf("catalog.v2beta1.Service/default.local.default/%s?port=%s", name, port) - } - - var ( - apiServiceRef = rtest.Resource(pbcatalog.ServiceType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - Reference("") - fooServiceRef = rtest.Resource(pbcatalog.ServiceType, "foo"). - WithTenancy(resource.DefaultNamespacedTenancy()). - Reference("") - barServiceRef = rtest.Resource(pbcatalog.ServiceType, "bar"). - WithTenancy(resource.DefaultNamespacedTenancy()). - Reference("") - - computedRoutesID = rtest.Resource(pbmesh.ComputedRoutesType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - ID() - ) - - // Start out by creating a single port service and let it create the - // default computed routes for tcp. - - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - // {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - _ = rtest.Resource(pbcatalog.ServiceType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - - var lastVersion string - testutil.RunStep(suite.T(), "default tcp route", func(t *testing.T) { - // Check that the computed routes resource exists and it has one port that is the default. - expect := &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "tcp": { - UsingDefaultConfig: true, - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{ - Rules: []*pbmesh.ComputedTCPRouteRule{{ - BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ - BackendTarget: backendName("api", "tcp"), - }}, - }}, - }, - }, - ParentRef: newParentRef(apiServiceRef, "tcp"), - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("api", "tcp"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(apiServiceRef, "tcp", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - } - - lastVersion = requireNewComputedRoutesVersion(t, suite.client, computedRoutesID, "", expect) - }) - - // Let the default http/http2/grpc routes get created. - - apiServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "http2", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - {TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - } - - _ = rtest.Resource(pbcatalog.ServiceType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - - // also create the fooService so we can point to it. - fooServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "http2", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - {TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - } - - _ = rtest.Resource(pbcatalog.ServiceType, "foo"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), fooServiceData). - Write(suite.T(), suite.client) - - testutil.RunStep(suite.T(), "default other routes", func(t *testing.T) { - expect := &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "tcp": { - UsingDefaultConfig: true, - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{ - Rules: []*pbmesh.ComputedTCPRouteRule{{ - BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ - BackendTarget: backendName("api", "tcp"), - }}, - }}, - }, - }, - ParentRef: newParentRef(apiServiceRef, "tcp"), - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("api", "tcp"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(apiServiceRef, "tcp", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "http": { - UsingDefaultConfig: true, - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/", - }, - }}, - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("api", "http"), - }}, - }}, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("api", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(apiServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "http2": { - UsingDefaultConfig: true, - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/", - }, - }}, - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("api", "http2"), - }}, - }}, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http2"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("api", "http2"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(apiServiceRef, "http2", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "grpc": { - UsingDefaultConfig: true, - Config: &pbmesh.ComputedPortRoutes_Grpc{ - Grpc: &pbmesh.ComputedGRPCRoute{ - Rules: []*pbmesh.ComputedGRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{}}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: backendName("api", "grpc"), - }}, - }}, - }, - }, - ParentRef: newParentRef(apiServiceRef, "grpc"), - Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("api", "grpc"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(apiServiceRef, "grpc", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - } - - lastVersion = requireNewComputedRoutesVersion(t, suite.client, computedRoutesID, lastVersion, expect) - }) - - // Customize each route type. - - tcpRoute1 := &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "tcp"), - }, - Rules: []*pbmesh.TCPRouteRule{{ - BackendRefs: []*pbmesh.TCPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - tcpRoute1ID := rtest.Resource(pbmesh.TCPRouteType, "api-tcp-route1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), tcpRoute1). - Write(suite.T(), suite.client). - Id - - httpRoute1 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http2"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - httpRoute1ID := rtest.Resource(pbmesh.HTTPRouteType, "api-http-route1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), httpRoute1). - Write(suite.T(), suite.client). - Id - - grpcRoute1 := &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "grpc"), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - grpcRoute1ID := rtest.Resource(pbmesh.GRPCRouteType, "api-grpc-route1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), grpcRoute1). - Write(suite.T(), suite.client). - Id - - testutil.RunStep(suite.T(), "one of each", func(t *testing.T) { - expect := &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - fooServiceRef, - resource.Reference(grpcRoute1ID, ""), - resource.Reference(httpRoute1ID, ""), - resource.Reference(tcpRoute1ID, ""), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "tcp": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{ - Rules: []*pbmesh.ComputedTCPRouteRule{{ - BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ - BackendTarget: backendName("foo", "tcp"), - }}, - }}, - }, - }, - ParentRef: newParentRef(apiServiceRef, "tcp"), - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "tcp"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "tcp", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "grpc": { - Config: &pbmesh.ComputedPortRoutes_Grpc{ - Grpc: &pbmesh.ComputedGRPCRoute{ - Rules: []*pbmesh.ComputedGRPCRouteRule{ - { - Matches: []*pbmesh.GRPCRouteMatch{{}}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: backendName("foo", "grpc"), - }}, - }, - { - Matches: []*pbmesh.GRPCRouteMatch{{}}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "grpc"), - Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "grpc"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "grpc", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "http2": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http2"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http2"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http2"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http2", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - } - - lastVersion = requireNewComputedRoutesVersion(t, suite.client, computedRoutesID, lastVersion, expect) - - suite.client.WaitForStatusCondition(t, tcpRoute1ID, StatusKey, ConditionXRouteOK) - suite.client.WaitForStatusCondition(t, httpRoute1ID, StatusKey, ConditionXRouteOK) - suite.client.WaitForStatusCondition(t, grpcRoute1ID, StatusKey, ConditionXRouteOK) - }) - - // Add another route, with a bad mapping. - - tcpRoute2 := &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "tcp"), - }, - Rules: []*pbmesh.TCPRouteRule{{ - BackendRefs: []*pbmesh.TCPBackendRef{{ - BackendRef: newBackendRef(barServiceRef, "", ""), - }}, - }}, - } - tcpRoute2ID := rtest.Resource(pbmesh.TCPRouteType, "api-tcp-route2"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), tcpRoute2). - Write(suite.T(), suite.client). - Id - - httpRoute2 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http2"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/healthz", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(barServiceRef, "", ""), - }}, - }}, - } - httpRoute2ID := rtest.Resource(pbmesh.HTTPRouteType, "api-http-route2"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), httpRoute2). - Write(suite.T(), suite.client). - Id - - grpcRoute2 := &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "grpc"), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT, - Service: "billing", - Method: "charge", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(barServiceRef, "", ""), - }}, - }}, - } - grpcRoute2ID := rtest.Resource(pbmesh.GRPCRouteType, "api-grpc-route2"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), grpcRoute2). - Write(suite.T(), suite.client). - Id - - testutil.RunStep(suite.T(), "one good one bad route", func(t *testing.T) { - expect := &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - fooServiceRef, - resource.Reference(grpcRoute1ID, ""), - resource.Reference(grpcRoute2ID, ""), - resource.Reference(httpRoute1ID, ""), - resource.Reference(httpRoute2ID, ""), - resource.Reference(tcpRoute1ID, ""), - resource.Reference(tcpRoute2ID, ""), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "tcp": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{ - Rules: []*pbmesh.ComputedTCPRouteRule{ - { - BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ - BackendTarget: backendName("foo", "tcp"), - }}, - }, - { - BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "tcp"), - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "tcp"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "tcp", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/healthz", - }, - }}, - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "grpc": { - Config: &pbmesh.ComputedPortRoutes_Grpc{ - Grpc: &pbmesh.ComputedGRPCRoute{ - Rules: []*pbmesh.ComputedGRPCRouteRule{ - { - Matches: []*pbmesh.GRPCRouteMatch{{}}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: backendName("foo", "grpc"), - }}, - }, - { - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT, - Service: "billing", - Method: "charge", - }, - }}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - { - Matches: []*pbmesh.GRPCRouteMatch{{}}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "grpc"), - Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "grpc"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "grpc", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "http2": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/healthz", - }, - }}, - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http2"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http2"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http2"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http2", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - } - - lastVersion = requireNewComputedRoutesVersion(t, suite.client, computedRoutesID, lastVersion, expect) - - suite.client.WaitForStatusCondition(t, tcpRoute1ID, StatusKey, ConditionXRouteOK) - suite.client.WaitForStatusCondition(t, httpRoute1ID, StatusKey, ConditionXRouteOK) - suite.client.WaitForStatusCondition(t, grpcRoute1ID, StatusKey, ConditionXRouteOK) - - suite.client.WaitForStatusCondition(t, tcpRoute2ID, StatusKey, - ConditionMissingBackendRef(newRef(pbcatalog.ServiceType, "bar"))) - suite.client.WaitForStatusCondition(t, httpRoute2ID, StatusKey, - ConditionMissingBackendRef(newRef(pbcatalog.ServiceType, "bar"))) - suite.client.WaitForStatusCondition(t, grpcRoute2ID, StatusKey, - ConditionMissingBackendRef(newRef(pbcatalog.ServiceType, "bar"))) - }) - - // Update the route2 routes to point to a real service, but overlap in - // their parentrefs with existing ports tied to other xRoutes. - // - // tcp2 -> http1 - // http2 -> grpc1 - // grpc2 -> tcp1 - // - // Also remove customization for the protocol http2. - - tcpRoute2 = &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - }, - Rules: []*pbmesh.TCPRouteRule{{ - BackendRefs: []*pbmesh.TCPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - rtest.ResourceID(tcpRoute2ID). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), tcpRoute2). - Write(suite.T(), suite.client) - - httpRoute2 = &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "grpc"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/healthz", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - rtest.ResourceID(httpRoute2ID). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), httpRoute2). - Write(suite.T(), suite.client) - - grpcRoute2 = &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "tcp"), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT, - Service: "billing", - Method: "charge", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - rtest.ResourceID(grpcRoute2ID). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), grpcRoute2). - Write(suite.T(), suite.client) - - testutil.RunStep(suite.T(), "overlapping xRoutes generate conflicts", func(t *testing.T) { - expect := &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - fooServiceRef, - resource.Reference(grpcRoute1ID, ""), - resource.Reference(grpcRoute2ID, ""), - resource.Reference(httpRoute1ID, ""), - resource.Reference(httpRoute2ID, ""), - resource.Reference(tcpRoute1ID, ""), - resource.Reference(tcpRoute2ID, ""), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "tcp": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{ - Rules: []*pbmesh.ComputedTCPRouteRule{{ - BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ - BackendTarget: backendName("foo", "tcp"), - }}, - }}, - }, - }, - ParentRef: newParentRef(apiServiceRef, "tcp"), - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "tcp"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "tcp", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "grpc": { - Config: &pbmesh.ComputedPortRoutes_Grpc{ - Grpc: &pbmesh.ComputedGRPCRoute{ - Rules: []*pbmesh.ComputedGRPCRouteRule{ - { - Matches: []*pbmesh.GRPCRouteMatch{{}}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: backendName("foo", "grpc"), - }}, - }, - { - Matches: []*pbmesh.GRPCRouteMatch{{}}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "grpc"), - Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "grpc"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "grpc", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "http2": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http2"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http2"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http2"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http2", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - } - - lastVersion = requireNewComputedRoutesVersion(t, suite.client, computedRoutesID, lastVersion, expect) - - suite.client.WaitForStatusCondition(t, tcpRoute1ID, StatusKey, ConditionXRouteOK) - suite.client.WaitForStatusCondition(t, httpRoute1ID, StatusKey, ConditionXRouteOK) - suite.client.WaitForStatusCondition(t, grpcRoute1ID, StatusKey, ConditionXRouteOK) - - suite.client.WaitForStatusCondition(t, tcpRoute2ID, StatusKey, - ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api"), "http", pbmesh.HTTPRouteType)) - suite.client.WaitForStatusCondition(t, httpRoute2ID, StatusKey, - ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api"), "grpc", pbmesh.GRPCRouteType)) - suite.client.WaitForStatusCondition(t, grpcRoute2ID, StatusKey, - ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api"), "tcp", pbmesh.TCPRouteType)) - }) - - // - Delete the bad routes - // - delete the original grpc route - // - create a new grpc route with a later name so it loses the conflict - // battle, and do a wildcard port binding - - suite.client.MustDelete(suite.T(), tcpRoute2ID) - suite.client.MustDelete(suite.T(), httpRoute2ID) - suite.client.MustDelete(suite.T(), grpcRoute1ID) - suite.client.MustDelete(suite.T(), grpcRoute2ID) - - suite.client.WaitForDeletion(suite.T(), tcpRoute2ID) - suite.client.WaitForDeletion(suite.T(), httpRoute2ID) - suite.client.WaitForDeletion(suite.T(), grpcRoute1ID) - suite.client.WaitForDeletion(suite.T(), grpcRoute2ID) - - // Re-create with newarly the same data (wildcard port now) with a newer name. - grpcRoute1 = &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - grpcRoute1ID = rtest.Resource(pbmesh.GRPCRouteType, "zzz-bad-route"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), grpcRoute1). - Write(suite.T(), suite.client). - Id - - testutil.RunStep(suite.T(), "overlapping xRoutes due to port wildcarding", func(t *testing.T) { - expect := &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - fooServiceRef, - resource.Reference(grpcRoute1ID, ""), - resource.Reference(httpRoute1ID, ""), - resource.Reference(tcpRoute1ID, ""), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "tcp": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{ - Rules: []*pbmesh.ComputedTCPRouteRule{{ - BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ - BackendTarget: backendName("foo", "tcp"), - }}, - }}, - }, - }, - ParentRef: newParentRef(apiServiceRef, "tcp"), - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "tcp"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "tcp", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "grpc": { - Config: &pbmesh.ComputedPortRoutes_Grpc{ - Grpc: &pbmesh.ComputedGRPCRoute{ - Rules: []*pbmesh.ComputedGRPCRouteRule{ - { - Matches: []*pbmesh.GRPCRouteMatch{{}}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: backendName("foo", "grpc"), - }}, - }, - { - Matches: []*pbmesh.GRPCRouteMatch{{}}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "grpc"), - Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "grpc"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "grpc", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "http2": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http2"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http2"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http2"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http2", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - } - - suite.client.WaitForStatusConditions(t, grpcRoute1ID, StatusKey, - ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api"), "http", pbmesh.HTTPRouteType), - ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api"), "http2", pbmesh.HTTPRouteType), - ConditionConflictNotBoundToParentRef(newRef(pbcatalog.ServiceType, "api"), "tcp", pbmesh.TCPRouteType)) - - lastVersion = requireNewComputedRoutesVersion(t, suite.client, computedRoutesID, "" /*no change*/, expect) - - suite.client.WaitForStatusCondition(t, tcpRoute1ID, StatusKey, ConditionXRouteOK) - suite.client.WaitForStatusCondition(t, httpRoute1ID, StatusKey, ConditionXRouteOK) - - }) - - // Remove the mesh port from api service. - - apiServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "http2", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - {TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - } - - _ = rtest.Resource(pbcatalog.ServiceType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), apiServiceData). - Write(suite.T(), suite.client) - - testutil.RunStep(suite.T(), "entire generated resource is deleted", func(t *testing.T) { - suite.client.WaitForDeletion(t, computedRoutesID) - - suite.client.WaitForStatusCondition(t, tcpRoute1ID, StatusKey, - ConditionParentRefOutsideMesh(newRef(pbcatalog.ServiceType, "api"))) - suite.client.WaitForStatusCondition(t, httpRoute1ID, StatusKey, - ConditionParentRefOutsideMesh(newRef(pbcatalog.ServiceType, "api"))) - suite.client.WaitForStatusCondition(t, grpcRoute1ID, StatusKey, - ConditionParentRefOutsideMesh(newRef(pbcatalog.ServiceType, "api"))) - }) - - // Get down to just 2 ports for all relevant services. - for _, name := range []string{"foo", "bar", "api"} { - _ = rtest.Resource(pbcatalog.ServiceType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{name + "-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - }). - Write(suite.T(), suite.client) - } - - httpRoute1 = &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(fooServiceRef, "http"), - newParentRef(barServiceRef, "http"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(apiServiceRef, "", ""), - }}, - }}, - } - httpRoute1ID = rtest.Resource(pbmesh.HTTPRouteType, "route1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), httpRoute1). - Write(suite.T(), suite.client). - Id - - var ( - fooLastVersion string - barLastVersion string - - fooComputedRoutesID = rtest.Resource(pbmesh.ComputedRoutesType, "foo"). - WithTenancy(resource.DefaultNamespacedTenancy()). - ID() - barComputedRoutesID = rtest.Resource(pbmesh.ComputedRoutesType, "bar"). - WithTenancy(resource.DefaultNamespacedTenancy()). - ID() - ) - - testutil.RunStep(suite.T(), "create a route linked to two parents", func(t *testing.T) { - expectFoo := &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - fooServiceRef, - resource.Reference(httpRoute1ID, ""), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("api", "http"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(fooServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("api", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(apiServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - } - expectBar := &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - barServiceRef, - resource.Reference(httpRoute1ID, ""), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("api", "http"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(barServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("api", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(apiServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - } - - fooLastVersion = requireNewComputedRoutesVersion(t, suite.client, fooComputedRoutesID, fooLastVersion, expectFoo) - barLastVersion = requireNewComputedRoutesVersion(t, suite.client, barComputedRoutesID, barLastVersion, expectBar) - - suite.client.WaitForStatusCondition(t, httpRoute1ID, StatusKey, ConditionXRouteOK) - }) - - // Remove bar parent - httpRoute1 = &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(fooServiceRef, "http"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(apiServiceRef, "", ""), - }}, - }}, - } - httpRoute1ID = rtest.Resource(pbmesh.HTTPRouteType, "route1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), httpRoute1). - Write(suite.T(), suite.client). - Id - - testutil.RunStep(suite.T(), "remove a parent ref and show that the old computed routes is reconciled one more time", func(t *testing.T) { - expectBar := &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - barServiceRef, - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("bar", "http"), - }}, - }, - }, - }, - }, - UsingDefaultConfig: true, - ParentRef: newParentRef(barServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("bar", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(barServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - } - - barLastVersion = requireNewComputedRoutesVersion(t, suite.client, barComputedRoutesID, barLastVersion, expectBar) - - suite.client.WaitForStatusCondition(t, httpRoute1ID, StatusKey, ConditionXRouteOK) - }) -} - -func newParentRef(ref *pbresource.Reference, port string) *pbmesh.ParentReference { - return &pbmesh.ParentReference{ - Ref: ref, - Port: port, - } -} - -func newBackendRef(ref *pbresource.Reference, port string, datacenter string) *pbmesh.BackendReference { - return &pbmesh.BackendReference{ - Ref: ref, - Port: port, - Datacenter: datacenter, - } -} - -func requireNewComputedRoutesVersion( - t *testing.T, - client *rtest.Client, - id *pbresource.ID, - version string, - expected *pbmesh.ComputedRoutes, -) string { - t.Helper() - - var nextVersion string - retry.Run(t, func(r *retry.R) { - res := client.WaitForNewVersion(r, id, version) - - var mc pbmesh.ComputedRoutes - require.NoError(r, res.Data.UnmarshalTo(&mc)) - prototest.AssertDeepEqual(r, expected, &mc) - - nextVersion = res.Version - }) - return nextVersion -} - -func TestController(t *testing.T) { - suite.Run(t, new(controllerSuite)) -} diff --git a/internal/mesh/internal/controllers/routes/generate.go b/internal/mesh/internal/controllers/routes/generate.go deleted file mode 100644 index 9bfb2808e303..000000000000 --- a/internal/mesh/internal/controllers/routes/generate.go +++ /dev/null @@ -1,835 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routes - -import ( - "fmt" - "time" - - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/durationpb" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/loader" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// GenerateComputedRoutes walks a set of related resources and assembles them -// into one effective easy-to-consume ComputedRoutes result. -// -// Any status conditions generated during traversal can be queued for -// persistence using the PendingStatuses map. -// -// This should not internally generate, nor return any errors. -func GenerateComputedRoutes( - related *loader.RelatedResources, - pending PendingStatuses, -) []*ComputedRoutesResult { - out := make([]*ComputedRoutesResult, 0, len(related.ComputedRoutesList)) - for _, computedRoutesID := range related.ComputedRoutesList { - out = append(out, compile(related, computedRoutesID, pending)) - } - return out -} - -type ComputedRoutesResult struct { - // ID is always required. - ID *pbresource.ID - // OwnerID is only required on upserts. - OwnerID *pbresource.ID - // Data being empty means delete if exists. - Data *pbmesh.ComputedRoutes -} - -func compile( - related *loader.RelatedResources, - computedRoutesID *pbresource.ID, - pending PendingStatuses, -) *ComputedRoutesResult { - // There is one computed routes resource for the entire service (perfect name alignment). - // - // All ports are embedded within. - - parentServiceID := &pbresource.ID{ - Type: pbcatalog.ServiceType, - Tenancy: computedRoutesID.Tenancy, - Name: computedRoutesID.Name, - } - - parentServiceRef := resource.Reference(parentServiceID, "") - - // The bound reference collector is supposed to aggregate all - // references to resources that influence the production of - // a ComputedRoutes resource. - // - // We only add a reference to the collector if the following are ALL true: - // - // - We load the resource for some reason. - // - The resource is found. - // - We decided to use the information in that resource to produce - // ComputedRoutes. - // - // We currently add all of the data here, but only use the xRoute - // references to enhance the DependencyMappers for this Controller. In the - // future we could use the others, but for now they are harmless to include - // in the produced resource and is beneficial from an audit/debugging - // perspective to know all of the inputs that produced this output. - boundRefCollector := NewBoundReferenceCollector() - - parentServiceDec := related.GetService(parentServiceID) - if parentServiceDec == nil { - return &ComputedRoutesResult{ - ID: computedRoutesID, - Data: nil, // returning nil signals a delete is requested - } - } - parentServiceID = parentServiceDec.Resource.Id // get ULID out of it - - boundRefCollector.AddRefOrID(parentServiceRef) - - var ( - inMesh = false - parentMeshPort string - allowedPortProtocols = make(map[string]pbcatalog.Protocol) - ) - for _, port := range parentServiceDec.Data.Ports { - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - inMesh = true - parentMeshPort = port.TargetPort - continue // skip - } - allowedPortProtocols[port.TargetPort] = port.Protocol - } - - if !inMesh { - return &ComputedRoutesResult{ - ID: computedRoutesID, - Data: nil, // returning nil signals a delete is requested - } - } - - computedRoutes := &pbmesh.ComputedRoutes{ - PortedConfigs: make(map[string]*pbmesh.ComputedPortRoutes), - } - - // Visit all of the routes relevant to this computed routes. - routeNodesByPort := make(map[string][]*inputRouteNode) - related.WalkRoutesForParentRef(parentServiceRef, func( - rk resource.ReferenceKey, - res *pbresource.Resource, - xroute types.XRouteData, - ) { - var ( - ports []string - wildcardedPort bool - ) - for _, ref := range xroute.GetParentRefs() { - if resource.ReferenceOrIDMatch(ref.Ref, parentServiceRef) { - if ref.Port == "" { - wildcardedPort = true - break - } - if _, ok := allowedPortProtocols[ref.Port]; ok { - ports = append(ports, ref.Port) - } - } - } - - // Do a port explosion. - if wildcardedPort { - ports = nil - for port := range allowedPortProtocols { - ports = append(ports, port) - } - } - - if len(ports) == 0 { - return // not relevant to this computed routes - } - boundRefCollector.AddRefOrID(res.Id) - - for _, port := range ports { - if port == "" { - panic("impossible to have an empty port here") - } - - var node *inputRouteNode - switch route := xroute.(type) { - case *pbmesh.HTTPRoute: - node = compileHTTPRouteNode(port, res, route, related, boundRefCollector) - case *pbmesh.GRPCRoute: - node = compileGRPCRouteNode(port, res, route, related, boundRefCollector) - case *pbmesh.TCPRoute: - node = compileTCPRouteNode(port, res, route, related, boundRefCollector) - default: - panic(fmt.Sprintf("unexpected xroute type: %T", xroute)) - } - - routeNodesByPort[node.ParentPort] = append(routeNodesByPort[node.ParentPort], node) - } - }) - - // Fill in defaults where there was no xroute defined at all. - for port, protocol := range allowedPortProtocols { - if _, ok := routeNodesByPort[port]; !ok { - var typ *pbresource.Type - - // enumcover:pbcatalog.Protocol - switch protocol { - case pbcatalog.Protocol_PROTOCOL_HTTP2: - typ = pbmesh.HTTPRouteType - case pbcatalog.Protocol_PROTOCOL_HTTP: - typ = pbmesh.HTTPRouteType - case pbcatalog.Protocol_PROTOCOL_GRPC: - typ = pbmesh.GRPCRouteType - case pbcatalog.Protocol_PROTOCOL_TCP: - typ = pbmesh.TCPRouteType - case pbcatalog.Protocol_PROTOCOL_MESH: - fallthrough // to default - case pbcatalog.Protocol_PROTOCOL_UNSPECIFIED: - fallthrough // to default - default: - continue // not possible - } - - routeNode := createDefaultRouteNode(parentServiceRef, parentMeshPort, port, typ) - - routeNodesByPort[port] = append(routeNodesByPort[port], routeNode) - } - } - - // First sort the input routes by the final criteria, so we can let the - // stable sort take care of the ultimate tiebreakers. - for port, routeNodes := range routeNodesByPort { - gammaInitialSortWrappedRoutes(routeNodes) - - // Now that they are sorted by age and name, we can figure out which - // xRoute should apply to each port (the first). - var top *inputRouteNode - for i, routeNode := range routeNodes { - if i == 0 { - top = routeNode - continue - } - if top.RouteType != routeNode.RouteType { - // This should only happen with user-provided ones, since we - // would never have two synthetic default routes at once. - res := routeNode.OriginalResource - if res != nil { - pending.AddConditions(resource.NewReferenceKey(res.Id), res, []*pbresource.Condition{ - ConditionConflictNotBoundToParentRef( - parentServiceRef, - port, - top.RouteType, - ), - }) - } - continue - } - top.AppendRulesFrom(routeNode) - top.AddTargetsFrom(routeNode) - } - - // Clear this field as it's no longer used and doesn't make sense once - // this represents multiple xRoutes or defaults. - top.OriginalResource = nil - - // Now we can do the big sort. - gammaSortRouteRules(top) - - // Inject catch-all rules to ensure stray requests will explicitly be blackholed. - if !top.Default { - if types.IsTCPRouteType(top.RouteType) { - if len(top.TCPRules) == 0 { - // User requests traffic blackhole. - appendDefaultRouteNode(top, types.NullRouteBackend) - } - } else { - // There are no match criteria on a TCPRoute, so never a need - // to add a catch-all. - appendDefaultRouteNode(top, types.NullRouteBackend) - } - } - - parentRef := &pbmesh.ParentReference{ - Ref: parentServiceRef, - Port: port, - } - - mc := &pbmesh.ComputedPortRoutes{ - UsingDefaultConfig: top.Default, - ParentRef: parentRef, - Protocol: allowedPortProtocols[port], - Targets: top.NewTargets, - } - - switch { - case resource.EqualType(top.RouteType, pbmesh.HTTPRouteType): - if mc.Protocol == pbcatalog.Protocol_PROTOCOL_TCP { - // The rest are HTTP-like - mc.Protocol = pbcatalog.Protocol_PROTOCOL_HTTP - } - mc.Config = &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: top.HTTPRules, - }, - } - case resource.EqualType(top.RouteType, pbmesh.GRPCRouteType): - mc.Protocol = pbcatalog.Protocol_PROTOCOL_GRPC - mc.Config = &pbmesh.ComputedPortRoutes_Grpc{ - Grpc: &pbmesh.ComputedGRPCRoute{ - Rules: top.GRPCRules, - }, - } - case resource.EqualType(top.RouteType, pbmesh.TCPRouteType): - mc.Protocol = pbcatalog.Protocol_PROTOCOL_TCP - mc.Config = &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{ - Rules: top.TCPRules, - }, - } - default: - panic("impossible") - } - - computedRoutes.PortedConfigs[port] = mc - - // The first pass collects the failover policies and generates additional targets. - for _, details := range mc.Targets { - svcRef := details.BackendRef.Ref - - svc := related.GetService(svcRef) - if svc == nil { - panic("impossible at this point; should already have been handled before getting here") - } - boundRefCollector.AddRefOrID(svcRef) - - failoverPolicy := related.GetFailoverPolicyForService(svcRef) - if failoverPolicy != nil { - simpleFailoverPolicy := catalog.SimplifyFailoverPolicy(svc.Data, failoverPolicy.Data) - portFailoverConfig, ok := simpleFailoverPolicy.PortConfigs[details.BackendRef.Port] - if ok { - boundRefCollector.AddRefOrID(failoverPolicy.Resource.Id) - - details.FailoverConfig = compileFailoverConfig( - related, - portFailoverConfig, - mc.Targets, - boundRefCollector, - ) - } - } - } - - // Do a second pass to handle shared things after we've dumped the - // failover legs into here. - for _, details := range mc.Targets { - svcRef := details.BackendRef.Ref - destPolicy := related.GetDestinationPolicyForService(svcRef) - if destPolicy != nil { - portDestConfig, ok := destPolicy.Data.PortConfigs[details.BackendRef.Port] - if ok { - boundRefCollector.AddRefOrID(destPolicy.Resource.Id) - details.DestinationConfig = portDestConfig - } - } - details.DestinationConfig = fillInDefaultDestConfig(details.DestinationConfig) - } - - // Pull target information up to the level of the rules. - switch x := mc.Config.(type) { - case *pbmesh.ComputedPortRoutes_Http: - route := x.Http - for _, rule := range route.Rules { - // If there are multiple legs (split) then choose the first actually set value. - var requestTimeoutFallback *durationpb.Duration - for _, backendRef := range rule.BackendRefs { - if backendRef.BackendTarget == types.NullRouteBackend { - continue - } - details, ok := mc.Targets[backendRef.BackendTarget] - if !ok { - continue - } - if details.DestinationConfig.RequestTimeout != nil { - requestTimeoutFallback = details.DestinationConfig.RequestTimeout - break - } - } - - if requestTimeoutFallback == nil { - continue // nothing to do - } - - if rule.Timeouts == nil { - rule.Timeouts = &pbmesh.HTTPRouteTimeouts{} - } - if rule.Timeouts.Request == nil { - rule.Timeouts.Request = requestTimeoutFallback - } - } - case *pbmesh.ComputedPortRoutes_Grpc: - route := x.Grpc - for _, rule := range route.Rules { - // If there are multiple legs (split) then choose the first actually set value. - var requestTimeoutFallback *durationpb.Duration - for _, backendRef := range rule.BackendRefs { - if backendRef.BackendTarget == types.NullRouteBackend { - continue - } - details, ok := mc.Targets[backendRef.BackendTarget] - if !ok { - continue - } - if details.DestinationConfig.RequestTimeout != nil { - requestTimeoutFallback = details.DestinationConfig.RequestTimeout - break - } - } - - if requestTimeoutFallback == nil { - continue // nothing to do - } - - if rule.Timeouts == nil { - rule.Timeouts = &pbmesh.HTTPRouteTimeouts{} - } - if rule.Timeouts.Request == nil { - rule.Timeouts.Request = requestTimeoutFallback - } - } - case *pbmesh.ComputedPortRoutes_Tcp: - } - - computedRoutes.PortedConfigs[port] = mc - } - - if len(computedRoutes.PortedConfigs) == 0 { - // This service only exposes a "mesh" port, so it cannot be another service's upstream. - return &ComputedRoutesResult{ - ID: computedRoutesID, - Data: nil, // returning nil signals a delete is requested - } - } - - computedRoutes.BoundReferences = boundRefCollector.List() - - return &ComputedRoutesResult{ - ID: computedRoutesID, - OwnerID: parentServiceID, - Data: computedRoutes, - } -} - -func compileFailoverConfig( - related *loader.RelatedResources, - failoverConfig *pbcatalog.FailoverConfig, - targets map[string]*pbmesh.BackendTargetDetails, - brc *BoundReferenceCollector, -) *pbmesh.ComputedFailoverConfig { - if failoverConfig == nil { - return nil - } - - cfc := &pbmesh.ComputedFailoverConfig{ - Destinations: make([]*pbmesh.ComputedFailoverDestination, 0, len(failoverConfig.Destinations)), - Mode: failoverConfig.Mode, - Regions: failoverConfig.Regions, - SamenessGroup: failoverConfig.SamenessGroup, - } - - for _, dest := range failoverConfig.Destinations { - backendRef := &pbmesh.BackendReference{ - Ref: dest.Ref, - Port: dest.Port, - Datacenter: dest.Datacenter, - } - - destSvcRef := dest.Ref - - svc := related.GetService(destSvcRef) - if svc != nil { - brc.AddRefOrID(svc.Resource.Id) - } - - var backendTargetName string - ok, meshPort := shouldRouteTrafficToBackend(svc, backendRef) - if !ok { - continue // skip this leg of failover for now - } - - destTargetName := types.BackendRefToComputedRoutesTarget(backendRef) - - if _, exists := targets[destTargetName]; !exists { - // Add to output as an indirect target. - targets[destTargetName] = &pbmesh.BackendTargetDetails{ - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_INDIRECT, - BackendRef: backendRef, - MeshPort: meshPort, - } - } - backendTargetName = destTargetName - - cfc.Destinations = append(cfc.Destinations, &pbmesh.ComputedFailoverDestination{ - BackendTarget: backendTargetName, - }) - } - return cfc -} - -func fillInDefaultDestConfig(target *pbmesh.DestinationConfig) *pbmesh.DestinationConfig { - base := defaultDestConfig() - - if target == nil { - return proto.Clone(base).(*pbmesh.DestinationConfig) - } - - out := proto.Clone(target).(*pbmesh.DestinationConfig) - - if out.ConnectTimeout == nil { - out.ConnectTimeout = base.GetConnectTimeout() - } - - return out -} - -func defaultDestConfig() *pbmesh.DestinationConfig { - return &pbmesh.DestinationConfig{ - ConnectTimeout: durationpb.New(5 * time.Second), - } -} - -func compileHTTPRouteNode( - port string, - res *pbresource.Resource, - route *pbmesh.HTTPRoute, - serviceGetter serviceGetter, - brc *BoundReferenceCollector, -) *inputRouteNode { - route = protoClone(route) - node := newInputRouteNode(port) - - node.RouteType = pbmesh.HTTPRouteType - node.OriginalResource = res - node.HTTPRules = make([]*pbmesh.ComputedHTTPRouteRule, 0, len(route.Rules)) - for _, rule := range route.Rules { - irule := &pbmesh.ComputedHTTPRouteRule{ - Matches: protoSliceClone(rule.Matches), - Filters: protoSliceClone(rule.Filters), - BackendRefs: make([]*pbmesh.ComputedHTTPBackendRef, 0, len(rule.BackendRefs)), - Timeouts: rule.Timeouts, - Retries: rule.Retries, - } - - // https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteRule - // - // If no matches are specified, the default is a prefix path match - // on “/”, which has the effect of matching every HTTP request. - if len(irule.Matches) == 0 { - irule.Matches = defaultHTTPRouteMatches() - } - for _, match := range irule.Matches { - if match.Path == nil { - // Path specifies a HTTP request path matcher. If this - // field is not specified, a default prefix match on - // the “/” path is provided. - match.Path = defaultHTTPPathMatch() - } - } - - for _, backendRef := range rule.BackendRefs { - // Infer port name from parent ref. - if backendRef.BackendRef.Port == "" { - backendRef.BackendRef.Port = port - } - - var ( - backendTarget string - backendSvc = serviceGetter.GetService(backendRef.BackendRef.Ref) - ) - if backendSvc != nil { - brc.AddRefOrID(backendSvc.Resource.Id) - } - if ok, meshPort := shouldRouteTrafficToBackend(backendSvc, backendRef.BackendRef); ok { - details := &pbmesh.BackendTargetDetails{ - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - BackendRef: backendRef.BackendRef, - MeshPort: meshPort, - } - backendTarget = node.AddTarget(backendRef.BackendRef, details) - } else { - backendTarget = types.NullRouteBackend - } - ibr := &pbmesh.ComputedHTTPBackendRef{ - BackendTarget: backendTarget, - Weight: backendRef.Weight, - Filters: backendRef.Filters, - } - irule.BackendRefs = append(irule.BackendRefs, ibr) - } - - node.HTTPRules = append(node.HTTPRules, irule) - } - - return node -} - -func compileGRPCRouteNode( - port string, - res *pbresource.Resource, - route *pbmesh.GRPCRoute, - serviceGetter serviceGetter, - brc *BoundReferenceCollector, -) *inputRouteNode { - route = protoClone(route) - - node := newInputRouteNode(port) - - node.RouteType = pbmesh.GRPCRouteType - node.OriginalResource = res - node.GRPCRules = make([]*pbmesh.ComputedGRPCRouteRule, 0, len(route.Rules)) - for _, rule := range route.Rules { - irule := &pbmesh.ComputedGRPCRouteRule{ - Matches: protoSliceClone(rule.Matches), - Filters: protoSliceClone(rule.Filters), - BackendRefs: make([]*pbmesh.ComputedGRPCBackendRef, 0, len(rule.BackendRefs)), - Timeouts: rule.Timeouts, - Retries: rule.Retries, - } - - // https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRouteRule - // - // If no matches are specified, the implementation MUST match every gRPC request. - if len(irule.Matches) == 0 { - irule.Matches = defaultGRPCRouteMatches() - } - - for _, backendRef := range rule.BackendRefs { - // Infer port name from parent ref. - if backendRef.BackendRef.Port == "" { - backendRef.BackendRef.Port = port - } - - var ( - backendTarget string - backendSvc = serviceGetter.GetService(backendRef.BackendRef.Ref) - ) - if backendSvc != nil { - brc.AddRefOrID(backendSvc.Resource.Id) - } - if ok, meshPort := shouldRouteTrafficToBackend(backendSvc, backendRef.BackendRef); ok { - details := &pbmesh.BackendTargetDetails{ - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - BackendRef: backendRef.BackendRef, - MeshPort: meshPort, - } - backendTarget = node.AddTarget(backendRef.BackendRef, details) - } else { - backendTarget = types.NullRouteBackend - } - - ibr := &pbmesh.ComputedGRPCBackendRef{ - BackendTarget: backendTarget, - Weight: backendRef.Weight, - Filters: backendRef.Filters, - } - irule.BackendRefs = append(irule.BackendRefs, ibr) - } - - node.GRPCRules = append(node.GRPCRules, irule) - } - - return node -} - -func compileTCPRouteNode( - port string, - res *pbresource.Resource, - route *pbmesh.TCPRoute, - serviceGetter serviceGetter, - brc *BoundReferenceCollector, -) *inputRouteNode { - route = protoClone(route) - - node := newInputRouteNode(port) - - node.RouteType = pbmesh.TCPRouteType - node.OriginalResource = res - node.TCPRules = make([]*pbmesh.ComputedTCPRouteRule, 0, len(route.Rules)) - for _, rule := range route.Rules { - irule := &pbmesh.ComputedTCPRouteRule{ - BackendRefs: make([]*pbmesh.ComputedTCPBackendRef, 0, len(rule.BackendRefs)), - } - - // https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.TCPRoute - - for _, backendRef := range rule.BackendRefs { - // Infer port name from parent ref. - if backendRef.BackendRef.Port == "" { - backendRef.BackendRef.Port = port - } - - var ( - backendTarget string - backendSvc = serviceGetter.GetService(backendRef.BackendRef.Ref) - ) - if backendSvc != nil { - brc.AddRefOrID(backendSvc.Resource.Id) - } - if ok, meshPort := shouldRouteTrafficToBackend(backendSvc, backendRef.BackendRef); ok { - details := &pbmesh.BackendTargetDetails{ - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - BackendRef: backendRef.BackendRef, - MeshPort: meshPort, - } - backendTarget = node.AddTarget(backendRef.BackendRef, details) - } else { - backendTarget = types.NullRouteBackend - } - - ibr := &pbmesh.ComputedTCPBackendRef{ - BackendTarget: backendTarget, - Weight: backendRef.Weight, - } - irule.BackendRefs = append(irule.BackendRefs, ibr) - } - - node.TCPRules = append(node.TCPRules, irule) - } - - return node -} - -func shouldRouteTrafficToBackend(backendSvc *types.DecodedService, backendRef *pbmesh.BackendReference) (bool, string) { - if backendSvc == nil { - return false, "" - } - - var ( - found = false - inMesh = false - meshPort string - ) - for _, port := range backendSvc.Data.Ports { - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - inMesh = true - meshPort = port.TargetPort - continue - } - if port.TargetPort == backendRef.Port { - found = true - } - } - - return inMesh && found, meshPort -} - -func createDefaultRouteNode( - parentServiceRef *pbresource.Reference, - parentMeshPort string, - port string, - typ *pbresource.Type, -) *inputRouteNode { - // always add the parent as a possible target due to catch-all - defaultBackendRef := &pbmesh.BackendReference{ - Ref: parentServiceRef, - Port: port, - } - - routeNode := newInputRouteNode(port) - - defaultBackendTarget := routeNode.AddTarget(defaultBackendRef, &pbmesh.BackendTargetDetails{ - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - BackendRef: defaultBackendRef, - MeshPort: parentMeshPort, - }) - switch { - case resource.EqualType(pbmesh.HTTPRouteType, typ): - routeNode.RouteType = pbmesh.HTTPRouteType - appendDefaultHTTPRouteRule(routeNode, defaultBackendTarget) - case resource.EqualType(pbmesh.GRPCRouteType, typ): - routeNode.RouteType = pbmesh.GRPCRouteType - appendDefaultGRPCRouteRule(routeNode, defaultBackendTarget) - case resource.EqualType(pbmesh.TCPRouteType, typ): - fallthrough - default: - routeNode.RouteType = pbmesh.TCPRouteType - appendDefaultTCPRouteRule(routeNode, defaultBackendTarget) - } - - routeNode.Default = true - return routeNode -} - -func appendDefaultRouteNode( - routeNode *inputRouteNode, - defaultBackendTarget string, -) { - switch { - case resource.EqualType(pbmesh.HTTPRouteType, routeNode.RouteType): - appendDefaultHTTPRouteRule(routeNode, defaultBackendTarget) - case resource.EqualType(pbmesh.GRPCRouteType, routeNode.RouteType): - appendDefaultGRPCRouteRule(routeNode, defaultBackendTarget) - case resource.EqualType(pbmesh.TCPRouteType, routeNode.RouteType): - fallthrough - default: - appendDefaultTCPRouteRule(routeNode, defaultBackendTarget) - } -} - -func appendDefaultHTTPRouteRule( - routeNode *inputRouteNode, - backendTarget string, -) { - routeNode.HTTPRules = append(routeNode.HTTPRules, &pbmesh.ComputedHTTPRouteRule{ - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendTarget, - }}, - }) -} - -func appendDefaultGRPCRouteRule( - routeNode *inputRouteNode, - backendTarget string, -) { - routeNode.GRPCRules = append(routeNode.GRPCRules, &pbmesh.ComputedGRPCRouteRule{ - Matches: defaultGRPCRouteMatches(), - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: backendTarget, - }}, - }) -} - -func appendDefaultTCPRouteRule( - routeNode *inputRouteNode, - backendTarget string, -) { - routeNode.TCPRules = append(routeNode.TCPRules, &pbmesh.ComputedTCPRouteRule{ - BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ - BackendTarget: backendTarget, - }}, - }) -} - -func defaultHTTPRouteMatches() []*pbmesh.HTTPRouteMatch { - return []*pbmesh.HTTPRouteMatch{{ - Path: defaultHTTPPathMatch(), - }} -} - -func defaultHTTPPathMatch() *pbmesh.HTTPPathMatch { - return &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/", - } -} - -func defaultGRPCRouteMatches() []*pbmesh.GRPCRouteMatch { - return []*pbmesh.GRPCRouteMatch{{}} -} diff --git a/internal/mesh/internal/controllers/routes/generate_test.go b/internal/mesh/internal/controllers/routes/generate_test.go deleted file mode 100644 index 4dc4a9c0793e..000000000000 --- a/internal/mesh/internal/controllers/routes/generate_test.go +++ /dev/null @@ -1,1684 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routes - -import ( - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/anypb" - "google.golang.org/protobuf/types/known/durationpb" - - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/loader" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestGenerateComputedRoutes(t *testing.T) { - registry := resource.NewRegistry() - types.Register(registry) - catalog.RegisterTypes(registry) - - run := func( - t *testing.T, - related *loader.RelatedResources, - expect []*ComputedRoutesResult, - expectPending PendingStatuses, - ) { - pending := make(PendingStatuses) - - got := GenerateComputedRoutes(related, pending) - - prototest.AssertElementsMatch[*ComputedRoutesResult]( - t, expect, got, - ) - - require.Len(t, pending, len(expectPending)) - if len(expectPending) > 0 { - for rk, expectItem := range expectPending { - gotItem, ok := pending[rk] - require.True(t, ok, "missing expected pending status for %v", rk) - prototest.AssertDeepEqual(t, expectItem, gotItem) - } - for rk := range pending { - _, ok := expectPending[rk] - require.True(t, ok, "extra pending status for %v", rk) - } - } - } - - newService := func(name string, data *pbcatalog.Service) *types.DecodedService { - svc := rtest.Resource(pbcatalog.ServiceType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data).Build() - rtest.ValidateAndNormalize(t, registry, svc) - return rtest.MustDecode[*pbcatalog.Service](t, svc) - } - - newHTTPRoute := func(name string, data *pbmesh.HTTPRoute) *types.DecodedHTTPRoute { - svc := rtest.Resource(pbmesh.HTTPRouteType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data).Build() - rtest.ValidateAndNormalize(t, registry, svc) - return rtest.MustDecode[*pbmesh.HTTPRoute](t, svc) - } - newGRPCRoute := func(name string, data *pbmesh.GRPCRoute) *types.DecodedGRPCRoute { - svc := rtest.Resource(pbmesh.GRPCRouteType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data).Build() - rtest.ValidateAndNormalize(t, registry, svc) - return rtest.MustDecode[*pbmesh.GRPCRoute](t, svc) - } - newTCPRoute := func(name string, data *pbmesh.TCPRoute) *types.DecodedTCPRoute { - svc := rtest.Resource(pbmesh.TCPRouteType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data).Build() - rtest.ValidateAndNormalize(t, registry, svc) - return rtest.MustDecode[*pbmesh.TCPRoute](t, svc) - } - - newDestPolicy := func(name string, data *pbmesh.DestinationPolicy) *types.DecodedDestinationPolicy { - policy := rtest.Resource(pbmesh.DestinationPolicyType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data).Build() - rtest.ValidateAndNormalize(t, registry, policy) - return rtest.MustDecode[*pbmesh.DestinationPolicy](t, policy) - } - - newFailPolicy := func(name string, data *pbcatalog.FailoverPolicy) *types.DecodedFailoverPolicy { - policy := rtest.Resource(pbcatalog.FailoverPolicyType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data).Build() - rtest.ValidateAndNormalize(t, registry, policy) - return rtest.MustDecode[*pbcatalog.FailoverPolicy](t, policy) - } - - backendName := func(name, port string) string { - return fmt.Sprintf("catalog.v2beta1.Service/default.local.default/%s?port=%s", name, port) - } - - var ( - apiServiceID = rtest.Resource(pbcatalog.ServiceType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - ID() - apiServiceRef = resource.Reference(apiServiceID, "") - apiComputedRoutesID = rtest.Resource(pbmesh.ComputedRoutesType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - ID() - - fooServiceID = rtest.Resource(pbcatalog.ServiceType, "foo"). - WithTenancy(resource.DefaultNamespacedTenancy()). - ID() - fooServiceRef = resource.Reference(fooServiceID, "") - - barServiceID = rtest.Resource(pbcatalog.ServiceType, "bar"). - WithTenancy(resource.DefaultNamespacedTenancy()). - ID() - barServiceRef = resource.Reference(barServiceID, "") - - deadServiceID = rtest.Resource(pbcatalog.ServiceType, "dead"). - WithTenancy(resource.DefaultNamespacedTenancy()). - ID() - deadServiceRef = resource.Reference(deadServiceID, "") - ) - - t.Run("none", func(t *testing.T) { - run(t, loader.NewRelatedResources(), nil, nil) - }) - - t.Run("no aligned service", func(t *testing.T) { - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID) - expect := []*ComputedRoutesResult{ - { - ID: apiComputedRoutesID, - Data: nil, - }, - } - run(t, related, expect, nil) - }) - - t.Run("aligned service not in mesh", func(t *testing.T) { - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources(newService("api", &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - }, - })) - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - Data: nil, - }} - run(t, related, expect, nil) - }) - - t.Run("aligned service in mesh but no actual ports", func(t *testing.T) { - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources(newService("api", &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - })) - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - Data: nil, - }} - run(t, related, expect, nil) - }) - - t.Run("tcp service with default route", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources(newService("api", apiServiceData)) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "tcp": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{ - Rules: []*pbmesh.ComputedTCPRouteRule{{ - BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ - BackendTarget: backendName("api", "tcp"), - }}, - }}, - }, - }, - UsingDefaultConfig: true, - ParentRef: newParentRef(apiServiceRef, "tcp"), - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("api", "tcp"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(apiServiceRef, "tcp", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - }}, - } - run(t, related, expect, nil) - }) - - for protoName, protocol := range map[string]pbcatalog.Protocol{ - "http": pbcatalog.Protocol_PROTOCOL_HTTP, - "http2": pbcatalog.Protocol_PROTOCOL_HTTP2, - } { - t.Run(protoName+" service with default route", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: protoName, Protocol: protocol}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources(newService("api", apiServiceData)) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - protoName: { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/", - }, - }}, - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("api", protoName), - }}, - }}, - }, - }, - UsingDefaultConfig: true, - ParentRef: newParentRef(apiServiceRef, protoName), - Protocol: protocol, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("api", protoName): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(apiServiceRef, protoName, ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) - } - - t.Run("grpc service with default route", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources(newService("api", apiServiceData)) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "grpc": { - Config: &pbmesh.ComputedPortRoutes_Grpc{ - Grpc: &pbmesh.ComputedGRPCRoute{ - Rules: []*pbmesh.ComputedGRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{}}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: backendName("api", "grpc"), - }}, - }}, - }, - }, - UsingDefaultConfig: true, - ParentRef: newParentRef(apiServiceRef, "grpc"), - Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("api", "grpc"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(apiServiceRef, "grpc", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) - - t.Run("all ports with a mix of routes", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "http2", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - {TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - } - - fooServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "http2", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - {TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - } - - tcpRoute1 := &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "tcp"), - }, - Rules: []*pbmesh.TCPRouteRule{{ - BackendRefs: []*pbmesh.TCPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - httpRoute1 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http2"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - grpcRoute1 := &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "grpc"), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources( - newService("api", apiServiceData), - newService("foo", fooServiceData), - newTCPRoute("api-tcp-route1", tcpRoute1), - newHTTPRoute("api-http-route1", httpRoute1), - newGRPCRoute("api-grpc-route1", grpcRoute1), - ) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - fooServiceRef, - newRef(pbmesh.GRPCRouteType, "api-grpc-route1"), - newRef(pbmesh.HTTPRouteType, "api-http-route1"), - newRef(pbmesh.TCPRouteType, "api-tcp-route1"), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "tcp": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{ - Rules: []*pbmesh.ComputedTCPRouteRule{{ - BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ - BackendTarget: backendName("foo", "tcp"), - }}, - }}, - }, - }, - ParentRef: newParentRef(apiServiceRef, "tcp"), - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "tcp"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "tcp", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "http2": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http2"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http2"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http2"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http2", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - "grpc": { - Config: &pbmesh.ComputedPortRoutes_Grpc{ - Grpc: &pbmesh.ComputedGRPCRoute{ - Rules: []*pbmesh.ComputedGRPCRouteRule{ - { - Matches: []*pbmesh.GRPCRouteMatch{{}}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: backendName("foo", "grpc"), - }}, - }, - { - Matches: []*pbmesh.GRPCRouteMatch{{}}, - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "grpc"), - Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "grpc"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "grpc", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) - - t.Run("all ports with a wildcard route only bypassing the protocol", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "http2", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - {TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - } - - fooServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "http2", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - {TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - } - - httpRoute1 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources( - newService("api", apiServiceData), - newService("foo", fooServiceData), - newHTTPRoute("api-http-route1", httpRoute1), - ) - - chunk := func(portName string, protocol pbcatalog.Protocol) *pbmesh.ComputedPortRoutes { - return &pbmesh.ComputedPortRoutes{ - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", portName), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, portName), - Protocol: protocol, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", portName): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, portName, ""), - DestinationConfig: defaultDestConfig(), - }, - }, - } - } - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - fooServiceRef, - newRef(pbmesh.HTTPRouteType, "api-http-route1"), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - // note: tcp has been upgraded to http in the presence of an HTTPRoute - "tcp": chunk("tcp", pbcatalog.Protocol_PROTOCOL_HTTP), - "http": chunk("http", pbcatalog.Protocol_PROTOCOL_HTTP), - "http2": chunk("http2", pbcatalog.Protocol_PROTOCOL_HTTP2), - "grpc": chunk("grpc", pbcatalog.Protocol_PROTOCOL_GRPC), - }, - }, - }} - run(t, related, expect, nil) - }) - - t.Run("stale-weird: stale mapper causes visit of irrelevant xRoute", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - fooServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - httpRoute1 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - apiSvc := newService("api", apiServiceData) - fooSvc := newService("foo", fooServiceData) - apiHTTPRoute1 := newHTTPRoute("api-http-route1", httpRoute1) - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). // deliberately skip adding 'foo' here to exercise the bug - AddResources(apiSvc, fooSvc, apiHTTPRoute1) - - // Update this after the fact, but don't update the inner indexing in - // the 'related' struct. - { - httpRoute1.ParentRefs[0] = newParentRef(newRef(pbcatalog.ServiceType, "foo"), "") - apiHTTPRoute1.Data = httpRoute1 - - anyData, err := anypb.New(httpRoute1) - require.NoError(t, err) - apiHTTPRoute1.Resource.Data = anyData - } - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/", - }, - }}, - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("api", "http"), - }}, - }}, - }, - }, - UsingDefaultConfig: true, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("api", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(apiServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) - - t.Run("stale-weird: parent ref uses invalid port", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - fooServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - httpRoute1 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - // Using bad parent port (www). - newParentRef(newRef(pbcatalog.ServiceType, "api"), "www"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "http", ""), - }}, - }}, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources( - newService("api", apiServiceData), - newService("foo", fooServiceData), - newHTTPRoute("api-http-route1", httpRoute1), - ) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/", - }, - }}, - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("api", "http"), - }}, - }}, - }, - }, - UsingDefaultConfig: true, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("api", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(apiServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) - - t.Run("overlapping xRoutes", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - fooServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - httpRouteData := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - // Using bad parent port (www). - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "http", ""), - }}, - }}, - } - httpRoute := newHTTPRoute("api-http-route", httpRouteData) - - tcpRouteData := &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - // Using bad parent port (www). - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - }, - Rules: []*pbmesh.TCPRouteRule{{ - BackendRefs: []*pbmesh.TCPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "http", ""), - }}, - }}, - } - tcpRoute := newTCPRoute("api-tcp-route", tcpRouteData) - // Force them to have the same generation, so that we fall back on - // lexicographic sort on the names as tiebreaker. - // - // api-http-route < api-tcp-route - tcpRoute.Resource.Generation = httpRoute.Resource.Generation - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources( - newService("api", apiServiceData), - newService("foo", fooServiceData), - httpRoute, - tcpRoute, - ) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - fooServiceRef, - resource.Reference(httpRoute.Resource.Id, ""), - resource.Reference(tcpRoute.Resource.Id, ""), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - }, - }} - - expectPending := make(PendingStatuses) - expectPending[resource.NewReferenceKey(tcpRoute.Resource.Id)] = &PendingResourceStatusUpdate{ - ID: tcpRoute.Resource.Id, - Generation: tcpRoute.Resource.Generation, - NewConditions: []*pbresource.Condition{ - ConditionConflictNotBoundToParentRef( - apiServiceRef, - "http", - pbmesh.HTTPRouteType, - ), - }, - } - - run(t, related, expect, expectPending) - }) - - t.Run("two http routes", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - fooServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - barServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"bar-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - httpRoute1 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/gir", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - httpRoute2 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/zim", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(barServiceRef, "", ""), - }}, - }}, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources( - newService("api", apiServiceData), - newService("foo", fooServiceData), - newService("bar", barServiceData), - newHTTPRoute("api-http-route1", httpRoute1), - newHTTPRoute("api-http-route2", httpRoute2), - ) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - barServiceRef, - fooServiceRef, - newRef(pbmesh.HTTPRouteType, "api-http-route1"), - newRef(pbmesh.HTTPRouteType, "api-http-route2"), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/gir", - }, - }}, - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http"), - }}, - }, - { - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/zim", - }, - }}, - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("bar", "http"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - backendName("bar", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(barServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) - - t.Run("http route with empty match path", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - fooServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - httpRoute1 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: nil, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources( - newService("api", apiServiceData), - newService("foo", fooServiceData), - newHTTPRoute("api-http-route1", httpRoute1), - ) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - fooServiceRef, - newRef(pbmesh.HTTPRouteType, "api-http-route1"), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) - - t.Run("stale-weird: destination with no service", func(t *testing.T) { - t.Run("http", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - httpRoute1 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources( - newService("api", apiServiceData), - newHTTPRoute("api-http-route1", httpRoute1), - ) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - newRef(pbmesh.HTTPRouteType, "api-http-route1"), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) - t.Run("grpc", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - }, - } - - grpcRoute1 := &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "grpc"), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources( - newService("api", apiServiceData), - newGRPCRoute("api-grpc-route1", grpcRoute1), - ) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - newRef(pbmesh.GRPCRouteType, "api-grpc-route1"), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "grpc": { - ParentRef: newParentRef(apiServiceRef, "grpc"), - Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, - Config: &pbmesh.ComputedPortRoutes_Grpc{ - Grpc: &pbmesh.ComputedGRPCRoute{ - Rules: []*pbmesh.ComputedGRPCRouteRule{ - { - Matches: defaultGRPCRouteMatches(), - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - { - Matches: defaultGRPCRouteMatches(), - BackendRefs: []*pbmesh.ComputedGRPCBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) - t.Run("tcp", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - }, - } - - tcpRoute1 := &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "tcp"), - }, - Rules: []*pbmesh.TCPRouteRule{{ - BackendRefs: []*pbmesh.TCPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources( - newService("api", apiServiceData), - newTCPRoute("api-tcp-route1", tcpRoute1), - ) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - newRef(pbmesh.TCPRouteType, "api-tcp-route1"), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "tcp": { - ParentRef: newParentRef(apiServiceRef, "tcp"), - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{ - Rules: []*pbmesh.ComputedTCPRouteRule{ - { - BackendRefs: []*pbmesh.ComputedTCPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) - }) - - t.Run("stale-weird: http destination with service not in mesh", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - fooServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - httpRoute1 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources( - newService("api", apiServiceData), - newService("foo", fooServiceData), - newHTTPRoute("api-http-route1", httpRoute1), - ) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - fooServiceRef, - newRef(pbmesh.HTTPRouteType, "api-http-route1"), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) - - t.Run("http route with dest policy", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - fooServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - httpRoute1 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - destPolicy := &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - }, - }, - } - portDestConfig := &pbmesh.DestinationConfig{ - ConnectTimeout: durationpb.New(55 * time.Second), - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources( - newService("api", apiServiceData), - newService("foo", fooServiceData), - newHTTPRoute("api-http-route1", httpRoute1), - newDestPolicy("foo", destPolicy), - ) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiServiceRef, - fooServiceRef, - newRef(pbmesh.DestinationPolicyType, "foo"), - newRef(pbmesh.HTTPRouteType, "api-http-route1"), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http", ""), - DestinationConfig: portDestConfig, - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) - - t.Run("http route with failover policy", func(t *testing.T) { - apiServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - fooServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"foo-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - barServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"bar-"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - } - - httpRoute1 := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(fooServiceRef, "", ""), - }}, - }}, - } - - failoverPolicy := &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{ - {Ref: barServiceRef}, - {Ref: deadServiceRef}, // no service - }, - }, - } - portFailoverConfig := &pbmesh.ComputedFailoverConfig{ - Destinations: []*pbmesh.ComputedFailoverDestination{ - {BackendTarget: backendName("bar", "http")}, - // we skip the dead route - }, - } - - related := loader.NewRelatedResources(). - AddComputedRoutesIDs(apiComputedRoutesID). - AddResources( - newService("api", apiServiceData), - newService("foo", fooServiceData), - newService("bar", barServiceData), - newHTTPRoute("api-http-route1", httpRoute1), - newFailPolicy("foo", failoverPolicy), - ) - - expect := []*ComputedRoutesResult{{ - ID: apiComputedRoutesID, - OwnerID: apiServiceID, - Data: &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - newRef(pbcatalog.FailoverPolicyType, "foo"), - apiServiceRef, - barServiceRef, - fooServiceRef, - newRef(pbmesh.HTTPRouteType, "api-http-route1"), - }, - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Http{ - Http: &pbmesh.ComputedHTTPRoute{ - Rules: []*pbmesh.ComputedHTTPRouteRule{ - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: backendName("foo", "http"), - }}, - }, - { - Matches: defaultHTTPRouteMatches(), - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: types.NullRouteBackend, - }}, - }, - }, - }, - }, - ParentRef: newParentRef(apiServiceRef, "http"), - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - Targets: map[string]*pbmesh.BackendTargetDetails{ - backendName("foo", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(fooServiceRef, "http", ""), - FailoverConfig: portFailoverConfig, - DestinationConfig: defaultDestConfig(), - }, - backendName("bar", "http"): { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_INDIRECT, - MeshPort: "mesh", - BackendRef: newBackendRef(barServiceRef, "http", ""), - DestinationConfig: defaultDestConfig(), - }, - }, - }, - }, - }, - }} - run(t, related, expect, nil) - }) -} diff --git a/internal/mesh/internal/controllers/routes/intermediate.go b/internal/mesh/internal/controllers/routes/intermediate.go deleted file mode 100644 index bc7aa348eea4..000000000000 --- a/internal/mesh/internal/controllers/routes/intermediate.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routes - -import ( - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// inputRouteNode is a dressed up version of an XRoute meant as working state -// for one pass of the compilation procedure. -type inputRouteNode struct { - ParentPort string // always set - - RouteType *pbresource.Type - Default bool - - // only one of these can be set to non-empty - HTTPRules []*pbmesh.ComputedHTTPRouteRule - GRPCRules []*pbmesh.ComputedGRPCRouteRule - TCPRules []*pbmesh.ComputedTCPRouteRule - - NewTargets map[string]*pbmesh.BackendTargetDetails - - // This field is non-nil for nodes based on a single xRoute, and nil for - // composite nodes or default nodes. - OriginalResource *pbresource.Resource -} - -func newInputRouteNode(port string) *inputRouteNode { - return &inputRouteNode{ - ParentPort: port, - NewTargets: make(map[string]*pbmesh.BackendTargetDetails), - } -} - -func (n *inputRouteNode) AddTarget(backendRef *pbmesh.BackendReference, data *pbmesh.BackendTargetDetails) string { - n.Default = false - key := types.BackendRefToComputedRoutesTarget(backendRef) - - if _, ok := n.NewTargets[key]; !ok { - n.NewTargets[key] = data - } - - return key -} - -func (n *inputRouteNode) AddTargetsFrom(next *inputRouteNode) { - n.Default = false - for key, details := range next.NewTargets { - if _, ok := n.NewTargets[key]; !ok { - n.NewTargets[key] = details // add if not already there - } - } -} - -func (n *inputRouteNode) AppendRulesFrom(next *inputRouteNode) { - n.Default = false - switch { - case resource.EqualType(n.RouteType, pbmesh.HTTPRouteType): - n.HTTPRules = append(n.HTTPRules, next.HTTPRules...) - case resource.EqualType(n.RouteType, pbmesh.GRPCRouteType): - n.GRPCRules = append(n.GRPCRules, next.GRPCRules...) - case resource.EqualType(n.RouteType, pbmesh.TCPRouteType): - n.TCPRules = append(n.TCPRules, next.TCPRules...) - default: - panic("impossible") - } -} diff --git a/internal/mesh/internal/controllers/routes/loader/loader.go b/internal/mesh/internal/controllers/routes/loader/loader.go deleted file mode 100644 index 4e7be5e64971..000000000000 --- a/internal/mesh/internal/controllers/routes/loader/loader.go +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package loader - -import ( - "context" - "fmt" - - "github.com/hashicorp/go-hclog" - - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/xroutemapper" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type loader struct { - mapper *xroutemapper.Mapper - - mem *memoizingLoader - - // output var - out *RelatedResources - - // working state - mcToLoad map[resource.ReferenceKey]struct{} - mcDone map[resource.ReferenceKey]struct{} -} - -func LoadResourcesForComputedRoutes( - ctx context.Context, - loggerFor func(*pbresource.ID) hclog.Logger, - client pbresource.ResourceServiceClient, - mapper *xroutemapper.Mapper, - computedRoutesID *pbresource.ID, -) (*RelatedResources, error) { - if loggerFor == nil { - loggerFor = func(_ *pbresource.ID) hclog.Logger { - return hclog.NewNullLogger() - } - } - loader := &loader{ - mapper: mapper, - mem: newMemoizingLoader(client), - mcToLoad: make(map[resource.ReferenceKey]struct{}), - mcDone: make(map[resource.ReferenceKey]struct{}), - } - - if err := loader.load(ctx, loggerFor, computedRoutesID); err != nil { - return nil, err - } - - return loader.out, nil -} - -func (l *loader) requestLoad(computedRoutesID *pbresource.ID) { - if !resource.EqualType(computedRoutesID.Type, pbmesh.ComputedRoutesType) { - panic("input must be a ComputedRoutes type") - } - rk := resource.NewReferenceKey(computedRoutesID) - - if _, done := l.mcDone[rk]; done { - return - } - l.mcToLoad[rk] = struct{}{} -} - -func (l *loader) markLoaded(computedRoutesID *pbresource.ID) { - if !resource.EqualType(computedRoutesID.Type, pbmesh.ComputedRoutesType) { - panic("input must be a ComputedRoutes type") - } - rk := resource.NewReferenceKey(computedRoutesID) - - l.mcDone[rk] = struct{}{} - delete(l.mcToLoad, rk) -} - -func (l *loader) nextRequested() *pbresource.ID { - for rk := range l.mcToLoad { - return rk.ToID() - } - return nil -} - -func (l *loader) load( - ctx context.Context, - loggerFor func(*pbresource.ID) hclog.Logger, - computedRoutesID *pbresource.ID, -) error { - l.out = NewRelatedResources() - - // Seed the graph fetch for our starting position. - l.requestLoad(computedRoutesID) - - for { - mcID := l.nextRequested() - if mcID == nil { - break - } - - if err := l.loadOne(ctx, loggerFor, mcID); err != nil { - return err - } - } - - return nil -} - -func (l *loader) loadOne( - ctx context.Context, - loggerFor func(*pbresource.ID) hclog.Logger, - computedRoutesID *pbresource.ID, -) error { - logger := loggerFor(computedRoutesID) - - // There is one computed routes for the entire service (perfect name alignment). - // - // All ports are embedded within. - - parentServiceID := changeResourceType(computedRoutesID, pbcatalog.ServiceType) - parentServiceRef := resource.Reference(parentServiceID, "") - - if err := l.loadUpstreamService(ctx, logger, parentServiceID); err != nil { - return err - } - - if err := l.gatherXRoutesAsInput(ctx, logger, parentServiceRef); err != nil { - return err - } - - l.out.AddComputedRoutesIDs(computedRoutesID) - - l.markLoaded(computedRoutesID) - - return nil -} - -func (l *loader) gatherXRoutesAsInput( - ctx context.Context, - logger hclog.Logger, - parentServiceRef *pbresource.Reference, -) error { - routeIDs := l.mapper.RouteIDsByParentServiceRef(parentServiceRef) - - // read the xRoutes - for _, routeID := range routeIDs { - switch { - case resource.EqualType(routeID.Type, pbmesh.HTTPRouteType): - route, err := l.mem.GetHTTPRoute(ctx, routeID) - if err != nil { - return fmt.Errorf("the resource service has returned an unexpected error loading %s: %w", routeID, err) - } - var routeData types.XRouteData - if route != nil { - routeData = route.Data - } - err = l.gatherSingleXRouteAsInput(ctx, logger, routeID, routeData, func() { - l.out.AddHTTPRoute(route) - }) - if err != nil { - return fmt.Errorf("the resource service has returned an unexpected error loading %s: %w", routeID, err) - } - case resource.EqualType(routeID.Type, pbmesh.GRPCRouteType): - route, err := l.mem.GetGRPCRoute(ctx, routeID) - if err != nil { - return fmt.Errorf("the resource service has returned an unexpected error loading %s: %w", routeID, err) - } - var routeData types.XRouteData - if route != nil { - routeData = route.Data - } - err = l.gatherSingleXRouteAsInput(ctx, logger, routeID, routeData, func() { - l.out.AddGRPCRoute(route) - }) - if err != nil { - return fmt.Errorf("the resource service has returned an unexpected error loading %s: %w", routeID, err) - } - case resource.EqualType(routeID.Type, pbmesh.TCPRouteType): - route, err := l.mem.GetTCPRoute(ctx, routeID) - if err != nil { - return fmt.Errorf("the resource service has returned an unexpected error loading %s: %w", routeID, err) - } - var routeData types.XRouteData - if route != nil { - routeData = route.Data - } - err = l.gatherSingleXRouteAsInput(ctx, logger, routeID, routeData, func() { - l.out.AddTCPRoute(route) - }) - if err != nil { - return fmt.Errorf("the resource service has returned an unexpected error loading %s: %w", routeID, err) - } - default: - logger.Warn("skipping xRoute reference of unknown type", "ID", resource.IDToString(routeID)) - continue - } - } - - return nil -} - -func (l *loader) loadUpstreamService( - ctx context.Context, - logger hclog.Logger, - svcID *pbresource.ID, -) error { - logger = logger.With("service-id", resource.IDToString(svcID)) - - service, err := l.mem.GetService(ctx, svcID) - if err != nil { - logger.Error("error retrieving the service", "serviceID", svcID, "error", err) - return err - } - if service != nil { - l.out.AddService(service) - - failoverPolicyID := changeResourceType(svcID, pbcatalog.FailoverPolicyType) - failoverPolicy, err := l.mem.GetFailoverPolicy(ctx, failoverPolicyID) - if err != nil { - logger.Error("error retrieving the failover policy", "failoverPolicyID", failoverPolicyID, "error", err) - return err - } - if failoverPolicy != nil { - l.mapper.TrackFailoverPolicy(failoverPolicy) - l.out.AddFailoverPolicy(failoverPolicy) - - destRefs := failoverPolicy.Data.GetUnderlyingDestinationRefs() - for _, destRef := range destRefs { - destID := resource.IDFromReference(destRef) - - failService, err := l.mem.GetService(ctx, destID) - if err != nil { - logger.Error("error retrieving a failover destination service", - "serviceID", destID, "error", err) - return err - } - if failService != nil { - l.out.AddService(failService) - - if err := l.loadDestConfig(ctx, logger, failService.Resource.Id); err != nil { - return err - } - } - } - } else { - l.mapper.UntrackFailoverPolicy(failoverPolicyID) - } - - if err := l.loadDestConfig(ctx, logger, svcID); err != nil { - return err - } - } - - return nil -} - -func (l *loader) loadDestConfig( - ctx context.Context, - logger hclog.Logger, - svcID *pbresource.ID, -) error { - destPolicyID := changeResourceType(svcID, pbmesh.DestinationPolicyType) - destPolicy, err := l.mem.GetDestinationPolicy(ctx, destPolicyID) - if err != nil { - logger.Error("error retrieving the destination config", "destPolicyID", destPolicyID, "error", err) - return err - } - if destPolicy != nil { - l.out.AddDestinationPolicy(destPolicy) - } - return nil -} - -func (l *loader) gatherSingleXRouteAsInput( - ctx context.Context, - logger hclog.Logger, - routeID *pbresource.ID, - route types.XRouteData, - relatedRouteCaptureFn func(), -) error { - if route == nil { - logger.Trace("XRoute has been deleted") - l.mapper.UntrackXRoute(routeID) - return nil - } - l.mapper.TrackXRoute(routeID, route) - - relatedRouteCaptureFn() - - for _, parentRef := range route.GetParentRefs() { - if types.IsServiceType(parentRef.Ref.Type) { - parentComputedRoutesID := &pbresource.ID{ - Type: pbmesh.ComputedRoutesType, - Tenancy: parentRef.Ref.Tenancy, - Name: parentRef.Ref.Name, - } - // Note: this will only schedule things to load that have not already been loaded - l.requestLoad(parentComputedRoutesID) - } - } - - for _, backendRef := range route.GetUnderlyingBackendRefs() { - if types.IsServiceType(backendRef.Ref.Type) { - svcID := resource.IDFromReference(backendRef.Ref) - if err := l.loadUpstreamService(ctx, logger, svcID); err != nil { - return err - } - } - } - - return nil -} - -func changeResourceType(id *pbresource.ID, newType *pbresource.Type) *pbresource.ID { - return &pbresource.ID{ - Type: newType, - Tenancy: id.Tenancy, - Name: id.Name, - } -} diff --git a/internal/mesh/internal/controllers/routes/loader/loader_test.go b/internal/mesh/internal/controllers/routes/loader/loader_test.go deleted file mode 100644 index a665635d05f7..000000000000 --- a/internal/mesh/internal/controllers/routes/loader/loader_test.go +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package loader - -import ( - "testing" - "time" - - "github.com/hashicorp/go-hclog" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/durationpb" - - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/xroutemapper" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestLoadResourcesForComputedRoutes(t *testing.T) { - ctx := testutil.TestContext(t) - rclient := svctest.RunResourceService(t, types.Register, catalog.RegisterTypes) - rt := controller.Runtime{ - Client: rclient, - Logger: testutil.Logger(t), - } - client := rtest.NewClient(rclient) - - loggerFor := func(id *pbresource.ID) hclog.Logger { - return rt.Logger.With("resource-id", id) - } - - mapper := xroutemapper.New() - - deleteRes := func(id *pbresource.ID, untrack bool) { - client.MustDelete(t, id) - if untrack { - switch { - case types.IsRouteType(id.Type): - mapper.UntrackXRoute(id) - case types.IsFailoverPolicyType(id.Type): - mapper.UntrackFailoverPolicy(id) - } - } - } - - writeHTTP := func(name string, data *pbmesh.HTTPRoute) *types.DecodedHTTPRoute { - res := rtest.Resource(pbmesh.HTTPRouteType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data). - Write(t, client) - mapper.TrackXRoute(res.Id, data) - dec, err := resource.Decode[*pbmesh.HTTPRoute](res) - require.NoError(t, err) - return dec - } - - writeGRPC := func(name string, data *pbmesh.GRPCRoute) *types.DecodedGRPCRoute { - res := rtest.Resource(pbmesh.GRPCRouteType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data). - Write(t, client) - mapper.TrackXRoute(res.Id, data) - dec, err := resource.Decode[*pbmesh.GRPCRoute](res) - require.NoError(t, err) - return dec - } - _ = writeGRPC // TODO - - writeTCP := func(name string, data *pbmesh.TCPRoute) *types.DecodedTCPRoute { - res := rtest.Resource(pbmesh.TCPRouteType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data). - Write(t, client) - mapper.TrackXRoute(res.Id, data) - dec, err := resource.Decode[*pbmesh.TCPRoute](res) - require.NoError(t, err) - return dec - } - _ = writeTCP // TODO - - writeDestPolicy := func(name string, data *pbmesh.DestinationPolicy) *types.DecodedDestinationPolicy { - res := rtest.Resource(pbmesh.DestinationPolicyType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data). - Write(t, client) - dec, err := resource.Decode[*pbmesh.DestinationPolicy](res) - require.NoError(t, err) - return dec - } - - writeFailover := func(name string, data *pbcatalog.FailoverPolicy) *types.DecodedFailoverPolicy { - res := rtest.Resource(pbcatalog.FailoverPolicyType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data). - Write(t, client) - dec, err := resource.Decode[*pbcatalog.FailoverPolicy](res) - require.NoError(t, err) - return dec - } - - writeService := func(name string, data *pbcatalog.Service) *types.DecodedService { - res := rtest.Resource(pbcatalog.ServiceType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data). - Write(t, client) - dec, err := resource.Decode[*pbcatalog.Service](res) - require.NoError(t, err) - return dec - } - - ///////////////////////////////////// - - // Init some port-aligned services. - apiSvc := writeService("api", &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }) - adminSvc := writeService("admin", &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }) - fooSvc := writeService("foo", &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }) - barSvc := writeService("bar", &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }) - - apiRoutesID := &pbresource.ID{ - Type: pbmesh.ComputedRoutesType, - Tenancy: resource.DefaultNamespacedTenancy(), - Name: "api", - } - adminRoutesID := &pbresource.ID{ - Type: pbmesh.ComputedRoutesType, - Tenancy: resource.DefaultNamespacedTenancy(), - Name: "admin", - } - - testutil.RunStep(t, "only service", func(t *testing.T) { - out, err := LoadResourcesForComputedRoutes(ctx, loggerFor, rt.Client, mapper, apiRoutesID) - require.NoError(t, err) - - prototest.AssertDeepEqual(t, NewRelatedResources().AddResources( - apiSvc, - ).AddComputedRoutesIDs(apiRoutesID), out) - require.Equal(t, doubleMap(t /* empty */), out.RoutesByParentRef) - }) - - // Write one silly http route - route1 := writeHTTP("api-route1", &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{{ - Ref: newRef(pbcatalog.ServiceType, "api"), - // all ports - }}, - }) - - testutil.RunStep(t, "one silly route", func(t *testing.T) { - out, err := LoadResourcesForComputedRoutes(ctx, loggerFor, rt.Client, mapper, apiRoutesID) - require.NoError(t, err) - - prototest.AssertDeepEqual(t, NewRelatedResources().AddResources( - apiSvc, - route1, - ).AddComputedRoutesIDs(apiRoutesID), out) - require.Equal(t, doubleMap(t, - apiSvc, route1, - ), out.RoutesByParentRef) - }) - - // add a second route that is more interesting and is TCP - route2 := writeTCP("api-route2", &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{{ - Ref: newRef(pbcatalog.ServiceType, "api"), - // all ports - }}, - Rules: []*pbmesh.TCPRouteRule{{ - BackendRefs: []*pbmesh.TCPBackendRef{ - { - BackendRef: &pbmesh.BackendReference{ - Ref: newRef(pbcatalog.ServiceType, "foo"), - }, - Weight: 30, - }, - { - BackendRef: &pbmesh.BackendReference{ - Ref: newRef(pbcatalog.ServiceType, "bar"), - }, - Weight: 70, - }, - }, - }}, - }) - - testutil.RunStep(t, "two routes", func(t *testing.T) { - out, err := LoadResourcesForComputedRoutes(ctx, loggerFor, rt.Client, mapper, apiRoutesID) - require.NoError(t, err) - - prototest.AssertDeepEqual(t, NewRelatedResources().AddResources( - apiSvc, - fooSvc, - barSvc, - route1, - route2, - ).AddComputedRoutesIDs(apiRoutesID), out) - require.Equal(t, doubleMap(t, - apiSvc, route1, - apiSvc, route2, - ), out.RoutesByParentRef) - }) - - // update the first to overlap with the second - route1 = writeHTTP("api-route1", &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - { - Ref: newRef(pbcatalog.ServiceType, "api"), - // all ports - }, - { - Ref: newRef(pbcatalog.ServiceType, "admin"), - // all ports - }, - }, - }) - - testutil.RunStep(t, "two overlapping computed routes resources", func(t *testing.T) { - out, err := LoadResourcesForComputedRoutes(ctx, loggerFor, rt.Client, mapper, apiRoutesID) - require.NoError(t, err) - - prototest.AssertDeepEqual(t, NewRelatedResources().AddResources( - apiSvc, - fooSvc, - barSvc, - adminSvc, - route1, - route2, - ).AddComputedRoutesIDs(apiRoutesID, adminRoutesID), out) - require.Equal(t, doubleMap(t, - apiSvc, route1, - apiSvc, route2, - adminSvc, route1, - ), out.RoutesByParentRef) - }) - - // add a third (GRPC) that overlaps them both - - route3 := writeGRPC("api-route3", &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - { - Ref: newRef(pbcatalog.ServiceType, "api"), - // all ports - }, - { - Ref: newRef(pbcatalog.ServiceType, "admin"), - // all ports - }, - }, - }) - - testutil.RunStep(t, "three overlapping computed routes resources", func(t *testing.T) { - out, err := LoadResourcesForComputedRoutes(ctx, loggerFor, rt.Client, mapper, apiRoutesID) - require.NoError(t, err) - - prototest.AssertDeepEqual(t, NewRelatedResources().AddResources( - apiSvc, - fooSvc, - barSvc, - adminSvc, - route1, - route2, - route3, - ).AddComputedRoutesIDs(apiRoutesID, adminRoutesID), out) - require.Equal(t, doubleMap(t, - apiSvc, route1, - apiSvc, route2, - apiSvc, route3, - adminSvc, route1, - adminSvc, route3, - ), out.RoutesByParentRef) - }) - - // We untrack the first, but we let the third one be a dangling reference - // so that the loader has to fix it up. - deleteRes(route1.Resource.Id, true) - deleteRes(route3.Resource.Id, false) - - testutil.RunStep(t, "delete first and third route", func(t *testing.T) { - out, err := LoadResourcesForComputedRoutes(ctx, loggerFor, rt.Client, mapper, apiRoutesID) - require.NoError(t, err) - - prototest.AssertDeepEqual(t, NewRelatedResources().AddResources( - apiSvc, - fooSvc, - barSvc, - route2, - ).AddComputedRoutesIDs(apiRoutesID), out) - require.Equal(t, doubleMap(t, - apiSvc, route2, - ), out.RoutesByParentRef) - }) - - barFailover := writeFailover("bar", &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: newRef(pbcatalog.ServiceType, "admin"), - }}, - }, - }) - - testutil.RunStep(t, "add a failover", func(t *testing.T) { - out, err := LoadResourcesForComputedRoutes(ctx, loggerFor, rt.Client, mapper, apiRoutesID) - require.NoError(t, err) - - prototest.AssertDeepEqual(t, NewRelatedResources().AddResources( - apiSvc, - fooSvc, - barSvc, - adminSvc, - route2, - barFailover, - ).AddComputedRoutesIDs(apiRoutesID), out) - require.Equal(t, doubleMap(t, - apiSvc, route2, - ), out.RoutesByParentRef) - }) - - fooDestPolicy := writeDestPolicy("foo", &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "www": { - ConnectTimeout: durationpb.New(55 * time.Second), - }, - }, - }) - adminDestPolicy := writeDestPolicy("admin", &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(222 * time.Second), - }, - }, - }) - - testutil.RunStep(t, "add a dest policy", func(t *testing.T) { - out, err := LoadResourcesForComputedRoutes(ctx, loggerFor, rt.Client, mapper, apiRoutesID) - require.NoError(t, err) - - prototest.AssertDeepEqual(t, NewRelatedResources().AddResources( - apiSvc, - fooSvc, - barSvc, - adminSvc, - route2, - barFailover, - fooDestPolicy, - adminDestPolicy, // adminDestPolicy shows up indirectly via a FailoverPolicy - ).AddComputedRoutesIDs(apiRoutesID), out) - require.Equal(t, doubleMap(t, - apiSvc, route2, - ), out.RoutesByParentRef) - }) -} - -func newRef(typ *pbresource.Type, name string) *pbresource.Reference { - return rtest.Resource(typ, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - Reference("") -} - -type resourceGetter interface { - GetResource() *pbresource.Resource -} - -func doubleMap(t *testing.T, list ...resourceGetter) map[resource.ReferenceKey]map[resource.ReferenceKey]struct{} { - if len(list)%2 != 0 { - t.Fatalf("list must have an even number of references") - } - out := make(map[resource.ReferenceKey]map[resource.ReferenceKey]struct{}) - for i := 0; i < len(list); i += 2 { - svcRK := resource.NewReferenceKey(list[i].GetResource().Id) - routeRK := resource.NewReferenceKey(list[i+1].GetResource().Id) - - m, ok := out[svcRK] - if !ok { - m = make(map[resource.ReferenceKey]struct{}) - out[svcRK] = m - } - m[routeRK] = struct{}{} - } - return out -} diff --git a/internal/mesh/internal/controllers/routes/loader/memoized.go b/internal/mesh/internal/controllers/routes/loader/memoized.go deleted file mode 100644 index 8fe912496f5a..000000000000 --- a/internal/mesh/internal/controllers/routes/loader/memoized.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package loader - -import ( - "context" - "fmt" - - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type memoizingLoader struct { - client pbresource.ResourceServiceClient - - mapHTTPRoute map[resource.ReferenceKey]*types.DecodedHTTPRoute - mapGRPCRoute map[resource.ReferenceKey]*types.DecodedGRPCRoute - mapTCPRoute map[resource.ReferenceKey]*types.DecodedTCPRoute - mapDestinationPolicy map[resource.ReferenceKey]*types.DecodedDestinationPolicy - mapFailoverPolicy map[resource.ReferenceKey]*types.DecodedFailoverPolicy - mapService map[resource.ReferenceKey]*types.DecodedService -} - -func newMemoizingLoader(client pbresource.ResourceServiceClient) *memoizingLoader { - if client == nil { - panic("client is required") - } - return &memoizingLoader{ - client: client, - mapHTTPRoute: make(map[resource.ReferenceKey]*types.DecodedHTTPRoute), - mapGRPCRoute: make(map[resource.ReferenceKey]*types.DecodedGRPCRoute), - mapTCPRoute: make(map[resource.ReferenceKey]*types.DecodedTCPRoute), - mapDestinationPolicy: make(map[resource.ReferenceKey]*types.DecodedDestinationPolicy), - mapFailoverPolicy: make(map[resource.ReferenceKey]*types.DecodedFailoverPolicy), - mapService: make(map[resource.ReferenceKey]*types.DecodedService), - } -} - -func (m *memoizingLoader) GetHTTPRoute(ctx context.Context, id *pbresource.ID) (*types.DecodedHTTPRoute, error) { - return getOrCacheResource[*pbmesh.HTTPRoute](ctx, m.client, m.mapHTTPRoute, pbmesh.HTTPRouteType, id) -} - -func (m *memoizingLoader) GetGRPCRoute(ctx context.Context, id *pbresource.ID) (*types.DecodedGRPCRoute, error) { - return getOrCacheResource[*pbmesh.GRPCRoute](ctx, m.client, m.mapGRPCRoute, pbmesh.GRPCRouteType, id) -} - -func (m *memoizingLoader) GetTCPRoute(ctx context.Context, id *pbresource.ID) (*types.DecodedTCPRoute, error) { - return getOrCacheResource[*pbmesh.TCPRoute](ctx, m.client, m.mapTCPRoute, pbmesh.TCPRouteType, id) -} - -func (m *memoizingLoader) GetDestinationPolicy(ctx context.Context, id *pbresource.ID) (*types.DecodedDestinationPolicy, error) { - return getOrCacheResource[*pbmesh.DestinationPolicy](ctx, m.client, m.mapDestinationPolicy, pbmesh.DestinationPolicyType, id) -} - -func (m *memoizingLoader) GetFailoverPolicy(ctx context.Context, id *pbresource.ID) (*types.DecodedFailoverPolicy, error) { - return getOrCacheResource[*pbcatalog.FailoverPolicy](ctx, m.client, m.mapFailoverPolicy, pbcatalog.FailoverPolicyType, id) -} - -func (m *memoizingLoader) GetService(ctx context.Context, id *pbresource.ID) (*types.DecodedService, error) { - return getOrCacheResource[*pbcatalog.Service](ctx, m.client, m.mapService, pbcatalog.ServiceType, id) -} - -func getOrCacheResource[T proto.Message]( - ctx context.Context, - client pbresource.ResourceServiceClient, - cache map[resource.ReferenceKey]*resource.DecodedResource[T], - typ *pbresource.Type, - id *pbresource.ID, -) (*resource.DecodedResource[T], error) { - if !resource.EqualType(id.Type, typ) { - return nil, fmt.Errorf("expected %s not %s", resource.TypeToString(typ), resource.TypeToString(id.Type)) - } - - rk := resource.NewReferenceKey(id) - - if cached, ok := cache[rk]; ok { - return cached, nil // cached value may be nil - } - - dec, err := resource.GetDecodedResource[T](ctx, client, id) - if err != nil { - return nil, err - } - - cache[rk] = dec - return dec, nil -} diff --git a/internal/mesh/internal/controllers/routes/loader/related.go b/internal/mesh/internal/controllers/routes/loader/related.go deleted file mode 100644 index a2ae9d853ab7..000000000000 --- a/internal/mesh/internal/controllers/routes/loader/related.go +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package loader - -import ( - "fmt" - - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// RelatedResources is a spiritual successor of *configentry.DiscoveryChainSet -type RelatedResources struct { - ComputedRoutesList []*pbresource.ID - // RoutesByParentRef is a map of a parent Service to the xRoutes that compose it. - RoutesByParentRef map[resource.ReferenceKey]map[resource.ReferenceKey]struct{} - HTTPRoutes map[resource.ReferenceKey]*types.DecodedHTTPRoute - GRPCRoutes map[resource.ReferenceKey]*types.DecodedGRPCRoute - TCPRoutes map[resource.ReferenceKey]*types.DecodedTCPRoute - Services map[resource.ReferenceKey]*types.DecodedService - FailoverPolicies map[resource.ReferenceKey]*types.DecodedFailoverPolicy - DestinationPolicies map[resource.ReferenceKey]*types.DecodedDestinationPolicy -} - -func NewRelatedResources() *RelatedResources { - return &RelatedResources{ - RoutesByParentRef: make(map[resource.ReferenceKey]map[resource.ReferenceKey]struct{}), - HTTPRoutes: make(map[resource.ReferenceKey]*types.DecodedHTTPRoute), - GRPCRoutes: make(map[resource.ReferenceKey]*types.DecodedGRPCRoute), - TCPRoutes: make(map[resource.ReferenceKey]*types.DecodedTCPRoute), - Services: make(map[resource.ReferenceKey]*types.DecodedService), - FailoverPolicies: make(map[resource.ReferenceKey]*types.DecodedFailoverPolicy), - DestinationPolicies: make(map[resource.ReferenceKey]*types.DecodedDestinationPolicy), - } -} - -func (r *RelatedResources) AddComputedRoutesIDs(list ...*pbresource.ID) *RelatedResources { - for _, id := range list { - r.AddComputedRoutesID(id) - } - return r -} - -func (r *RelatedResources) AddComputedRoutesID(id *pbresource.ID) *RelatedResources { - if !resource.EqualType(id.Type, pbmesh.ComputedRoutesType) { - panic(fmt.Sprintf("expected *mesh.ComputedRoutes, not %s", resource.TypeToString(id.Type))) - } - r.ComputedRoutesList = append(r.ComputedRoutesList, id) - return r -} - -// AddResources must only be called with valid *resource.DecodedResource[T] -// types. -// -// This is provided as a testing convenience. Non-test code should call the -// type-specific adder. -func (r *RelatedResources) AddResources(list ...any) *RelatedResources { - for _, res := range list { - r.AddResource(res) - } - return r -} - -// AddResource must only be called with valid *resource.DecodedResource[T] types. -// -// This is provided as a testing convenience. Non-test code should call the -// type-specific adder. -func (r *RelatedResources) AddResource(res any) { - if res == nil { - return - } - - switch dec := res.(type) { - case *types.DecodedHTTPRoute: - r.AddHTTPRoute(dec) - case *types.DecodedGRPCRoute: - r.AddGRPCRoute(dec) - case *types.DecodedTCPRoute: - r.AddTCPRoute(dec) - case *types.DecodedDestinationPolicy: - r.AddDestinationPolicy(dec) - case *types.DecodedService: - r.AddService(dec) - case *types.DecodedFailoverPolicy: - r.AddFailoverPolicy(dec) - default: - panic(fmt.Sprintf("unknown decoded resource type: %T", res)) - } -} - -func (r *RelatedResources) AddHTTPRoute(dec *types.DecodedHTTPRoute) { - r.addRouteSetEntries(dec.Resource, dec.Data) - addResource(dec.Resource.Id, dec, r.HTTPRoutes) -} - -func (r *RelatedResources) AddGRPCRoute(dec *types.DecodedGRPCRoute) { - r.addRouteSetEntries(dec.Resource, dec.Data) - addResource(dec.Resource.Id, dec, r.GRPCRoutes) -} - -func (r *RelatedResources) AddTCPRoute(dec *types.DecodedTCPRoute) { - r.addRouteSetEntries(dec.Resource, dec.Data) - addResource(dec.Resource.Id, dec, r.TCPRoutes) -} - -func (r *RelatedResources) AddDestinationPolicy(dec *types.DecodedDestinationPolicy) { - addResource(dec.Resource.Id, dec, r.DestinationPolicies) -} - -func (r *RelatedResources) AddService(dec *types.DecodedService) { - addResource(dec.Resource.Id, dec, r.Services) -} - -func (r *RelatedResources) AddFailoverPolicy(dec *types.DecodedFailoverPolicy) { - addResource(dec.Resource.Id, dec, r.FailoverPolicies) -} - -func (r *RelatedResources) addRouteSetEntries( - res *pbresource.Resource, - xroute types.XRouteData, -) { - if res == nil || xroute == nil { - return - } - - routeRK := resource.NewReferenceKey(res.Id) - - for _, parentRef := range xroute.GetParentRefs() { - if parentRef.Ref == nil || !types.IsServiceType(parentRef.Ref.Type) { - continue - } - svcRK := resource.NewReferenceKey(parentRef.Ref) - - r.addRouteByParentRef(svcRK, routeRK) - } -} - -func (r *RelatedResources) addRouteByParentRef(svcRK, xRouteRK resource.ReferenceKey) { - m, ok := r.RoutesByParentRef[svcRK] - if !ok { - m = make(map[resource.ReferenceKey]struct{}) - r.RoutesByParentRef[svcRK] = m - } - m[xRouteRK] = struct{}{} -} - -type RouteWalkFunc func( - rk resource.ReferenceKey, - res *pbresource.Resource, - route types.XRouteData, -) - -func (r *RelatedResources) WalkRoutes(fn RouteWalkFunc) { - for rk, route := range r.HTTPRoutes { - fn(rk, route.Resource, route.Data) - } - for rk, route := range r.GRPCRoutes { - fn(rk, route.Resource, route.Data) - } - for rk, route := range r.TCPRoutes { - fn(rk, route.Resource, route.Data) - } -} - -func (r *RelatedResources) WalkRoutesForParentRef(parentRef *pbresource.Reference, fn RouteWalkFunc) { - if !resource.EqualType(parentRef.Type, pbcatalog.ServiceType) { - panic(fmt.Sprintf("expected *catalog.Service, not %s", resource.TypeToString(parentRef.Type))) - } - routeMap := r.RoutesByParentRef[resource.NewReferenceKey(parentRef)] - if len(routeMap) == 0 { - return - } - - for rk := range routeMap { - if route, ok := r.HTTPRoutes[rk]; ok { - fn(rk, route.Resource, route.Data) - continue - } - if route, ok := r.GRPCRoutes[rk]; ok { - fn(rk, route.Resource, route.Data) - continue - } - if route, ok := r.TCPRoutes[rk]; ok { - fn(rk, route.Resource, route.Data) - continue - } - } -} - -func (r *RelatedResources) GetService(ref resource.ReferenceOrID) *types.DecodedService { - return r.Services[resource.NewReferenceKey(ref)] -} - -func (r *RelatedResources) GetFailoverPolicy(ref resource.ReferenceOrID) *types.DecodedFailoverPolicy { - return r.FailoverPolicies[resource.NewReferenceKey(ref)] -} - -func (r *RelatedResources) GetFailoverPolicyForService(ref resource.ReferenceOrID) *types.DecodedFailoverPolicy { - failRef := &pbresource.Reference{ - Type: pbcatalog.FailoverPolicyType, - Tenancy: ref.GetTenancy(), - Name: ref.GetName(), - } - return r.GetFailoverPolicy(failRef) -} - -func (r *RelatedResources) GetDestinationPolicy(ref resource.ReferenceOrID) *types.DecodedDestinationPolicy { - return r.DestinationPolicies[resource.NewReferenceKey(ref)] -} - -func (r *RelatedResources) GetDestinationPolicyForService(ref resource.ReferenceOrID) *types.DecodedDestinationPolicy { - destRef := &pbresource.Reference{ - Type: pbmesh.DestinationPolicyType, - Tenancy: ref.GetTenancy(), - Name: ref.GetName(), - } - return r.GetDestinationPolicy(destRef) -} - -func addResource[V any](id *pbresource.ID, res *V, m map[resource.ReferenceKey]*V) { - if res == nil { - return - } - - rk := resource.NewReferenceKey(id) - if _, ok := m[rk]; !ok { - m[rk] = res - } -} diff --git a/internal/mesh/internal/controllers/routes/pending_status.go b/internal/mesh/internal/controllers/routes/pending_status.go deleted file mode 100644 index 1c33e2db2b82..000000000000 --- a/internal/mesh/internal/controllers/routes/pending_status.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routes - -import ( - "context" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type PendingResourceStatusUpdate struct { - ID *pbresource.ID - Generation string - CurrStatus *pbresource.Status - - NewConditions []*pbresource.Condition -} - -type PendingStatuses map[resource.ReferenceKey]*PendingResourceStatusUpdate - -func (p PendingStatuses) AddConditions( - rk resource.ReferenceKey, - res *pbresource.Resource, - newConditions []*pbresource.Condition, -) { - state, ok := p[rk] - if !ok { - state = &PendingResourceStatusUpdate{ - ID: res.Id, - Generation: res.Generation, - CurrStatus: res.Status[StatusKey], - } - p[rk] = state - } - - state.NewConditions = append(state.NewConditions, newConditions...) -} - -func UpdatePendingStatuses( - ctx context.Context, - rt controller.Runtime, - pending PendingStatuses, -) error { - for _, state := range pending { - logger := rt.Logger.With("resource", resource.IDToString(state.ID)) - - var newStatus *pbresource.Status - if len(state.NewConditions) > 0 { - newStatus = &pbresource.Status{ - ObservedGeneration: state.Generation, - Conditions: state.NewConditions, - } - } else { - newStatus = &pbresource.Status{ - ObservedGeneration: state.Generation, - Conditions: []*pbresource.Condition{ - ConditionXRouteOK, - }, - } - } - if resource.EqualStatus(state.CurrStatus, newStatus, false) { - logger.Trace( - "resource's status is unchanged", - "conditions", newStatus.Conditions, - ) - } else { - _, err := rt.Client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ - Id: state.ID, - Key: StatusKey, - Status: newStatus, - }) - - if err != nil { - logger.Error( - "error encountered when attempting to update the resource's status", - "error", err, - ) - return err - } - - logger.Trace( - "resource's status was updated", - "conditions", newStatus.Conditions, - ) - } - } - - return nil -} diff --git a/internal/mesh/internal/controllers/routes/ref_validation.go b/internal/mesh/internal/controllers/routes/ref_validation.go deleted file mode 100644 index b860eede202d..000000000000 --- a/internal/mesh/internal/controllers/routes/ref_validation.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routes - -import ( - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/loader" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// ValidateXRouteReferences examines all of the ParentRefs and BackendRefs of -// xRoutes provided and issues status conditions if anything is unacceptable. -func ValidateXRouteReferences(related *loader.RelatedResources, pending PendingStatuses) { - related.WalkRoutes(func( - rk resource.ReferenceKey, - res *pbresource.Resource, - route types.XRouteData, - ) { - parentRefs := route.GetParentRefs() - backendRefs := route.GetUnderlyingBackendRefs() - - conditions := computeNewRouteRefConditions(related, parentRefs, backendRefs) - - pending.AddConditions(rk, res, conditions) - }) -} - -type serviceGetter interface { - GetService(ref resource.ReferenceOrID) *types.DecodedService -} - -func computeNewRouteRefConditions( - related serviceGetter, - parentRefs []*pbmesh.ParentReference, - backendRefs []*pbmesh.BackendReference, -) []*pbresource.Condition { - var conditions []*pbresource.Condition - - // TODO(rb): handle port numbers here too if we are allowing those instead of the name? - - for _, parentRef := range parentRefs { - if parentRef.Ref == nil || !resource.EqualType(parentRef.Ref.Type, pbcatalog.ServiceType) { - continue // not possible due to xRoute validation - } - if parentRef.Ref.Section != "" { - continue // not possible due to xRoute validation - } - if svc := related.GetService(parentRef.Ref); svc != nil { - found := false - usingMesh := false - hasMesh := false - for _, port := range svc.Data.Ports { - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - hasMesh = true - } - if port.TargetPort == parentRef.Port { - found = true - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - usingMesh = true - } - } - } - switch { - case !hasMesh: - conditions = append(conditions, ConditionParentRefOutsideMesh(parentRef.Ref)) - case !found: - if parentRef.Port != "" { - conditions = append(conditions, ConditionUnknownParentRefPort(parentRef.Ref, parentRef.Port)) - } - case usingMesh: - conditions = append(conditions, ConditionParentRefUsingMeshPort(parentRef.Ref, parentRef.Port)) - } - } else { - conditions = append(conditions, ConditionMissingParentRef(parentRef.Ref)) - } - } - - for _, backendRef := range backendRefs { - if backendRef.Ref == nil || !resource.EqualType(backendRef.Ref.Type, pbcatalog.ServiceType) { - continue // not possible due to xRoute validation - } - if backendRef.Ref.Section != "" { - continue // not possible due to xRoute validation - } - if svc := related.GetService(backendRef.Ref); svc != nil { - found := false - usingMesh := false - hasMesh := false - for _, port := range svc.Data.Ports { - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - hasMesh = true - } - if port.TargetPort == backendRef.Port { - found = true - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - usingMesh = true - } - } - } - switch { - case !hasMesh: - conditions = append(conditions, ConditionBackendRefOutsideMesh(backendRef.Ref)) - case !found: - if backendRef.Port != "" { - conditions = append(conditions, ConditionUnknownBackendRefPort(backendRef.Ref, backendRef.Port)) - } - case usingMesh: - conditions = append(conditions, ConditionBackendRefUsingMeshPort(backendRef.Ref, backendRef.Port)) - } - } else { - conditions = append(conditions, ConditionMissingBackendRef(backendRef.Ref)) - } - } - - return conditions -} diff --git a/internal/mesh/internal/controllers/routes/ref_validation_test.go b/internal/mesh/internal/controllers/routes/ref_validation_test.go deleted file mode 100644 index 3f6db4207865..000000000000 --- a/internal/mesh/internal/controllers/routes/ref_validation_test.go +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routes - -import ( - "testing" - - "github.com/stretchr/testify/require" - - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestComputeNewRouteRefConditions(t *testing.T) { - registry := resource.NewRegistry() - types.Register(registry) - catalog.RegisterTypes(registry) - - newService := func(name string, ports map[string]pbcatalog.Protocol) *types.DecodedService { - var portSlice []*pbcatalog.ServicePort - for name, proto := range ports { - portSlice = append(portSlice, &pbcatalog.ServicePort{ - TargetPort: name, - Protocol: proto, - }) - } - svc := rtest.Resource(pbcatalog.ServiceType, name). - WithData(t, &pbcatalog.Service{Ports: portSlice}). - Build() - rtest.ValidateAndNormalize(t, registry, svc) - - dec, err := resource.Decode[*pbcatalog.Service](svc) - require.NoError(t, err) - return dec - } - - t.Run("no refs", func(t *testing.T) { - sg := newTestServiceGetter() - got := computeNewRouteRefConditions(sg, nil, nil) - require.Empty(t, got) - }) - - t.Run("parent refs", func(t *testing.T) { - t.Run("with no service", func(t *testing.T) { - sg := newTestServiceGetter() - got := computeNewRouteRefConditions(sg, []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), ""), - }, nil) - require.Len(t, got, 1) - prototest.AssertContainsElement(t, got, ConditionMissingParentRef( - newRef(pbcatalog.ServiceType, "api"), - )) - }) - - t.Run("with service but no mesh port", func(t *testing.T) { - sg := newTestServiceGetter(newService("api", map[string]pbcatalog.Protocol{ - "http": pbcatalog.Protocol_PROTOCOL_HTTP, - })) - got := computeNewRouteRefConditions(sg, []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), ""), - }, nil) - require.Len(t, got, 1) - prototest.AssertContainsElement(t, got, ConditionParentRefOutsideMesh( - newRef(pbcatalog.ServiceType, "api"), - )) - }) - - t.Run("with service but using mesh port", func(t *testing.T) { - sg := newTestServiceGetter(newService("api", map[string]pbcatalog.Protocol{ - "http": pbcatalog.Protocol_PROTOCOL_HTTP, - "mesh": pbcatalog.Protocol_PROTOCOL_MESH, - })) - got := computeNewRouteRefConditions(sg, []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "mesh"), - }, nil) - require.Len(t, got, 1) - prototest.AssertContainsElement(t, got, ConditionParentRefUsingMeshPort( - newRef(pbcatalog.ServiceType, "api"), - "mesh", - )) - }) - - t.Run("with service and using missing port", func(t *testing.T) { - sg := newTestServiceGetter(newService("api", map[string]pbcatalog.Protocol{ - "http": pbcatalog.Protocol_PROTOCOL_HTTP, - "mesh": pbcatalog.Protocol_PROTOCOL_MESH, - })) - got := computeNewRouteRefConditions(sg, []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "web"), - }, nil) - require.Len(t, got, 1) - prototest.AssertContainsElement(t, got, ConditionUnknownParentRefPort( - newRef(pbcatalog.ServiceType, "api"), - "web", - )) - }) - - t.Run("with service and using empty port", func(t *testing.T) { - sg := newTestServiceGetter(newService("api", map[string]pbcatalog.Protocol{ - "http": pbcatalog.Protocol_PROTOCOL_HTTP, - "mesh": pbcatalog.Protocol_PROTOCOL_MESH, - })) - got := computeNewRouteRefConditions(sg, []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), ""), - }, nil) - require.Empty(t, got) - }) - - t.Run("with service and using correct port", func(t *testing.T) { - sg := newTestServiceGetter(newService("api", map[string]pbcatalog.Protocol{ - "http": pbcatalog.Protocol_PROTOCOL_HTTP, - "mesh": pbcatalog.Protocol_PROTOCOL_MESH, - })) - got := computeNewRouteRefConditions(sg, []*pbmesh.ParentReference{ - newParentRef(newRef(pbcatalog.ServiceType, "api"), "http"), - }, nil) - require.Empty(t, got) - }) - }) - - t.Run("backend refs", func(t *testing.T) { - t.Run("with no service", func(t *testing.T) { - sg := newTestServiceGetter() - got := computeNewRouteRefConditions(sg, nil, []*pbmesh.BackendReference{ - newBackendRef(newRef(pbcatalog.ServiceType, "api"), "", ""), - }) - require.Len(t, got, 1) - prototest.AssertContainsElement(t, got, ConditionMissingBackendRef( - newRef(pbcatalog.ServiceType, "api"), - )) - }) - - t.Run("with service but no mesh port", func(t *testing.T) { - sg := newTestServiceGetter(newService("api", map[string]pbcatalog.Protocol{ - "http": pbcatalog.Protocol_PROTOCOL_HTTP, - })) - got := computeNewRouteRefConditions(sg, nil, []*pbmesh.BackendReference{ - newBackendRef(newRef(pbcatalog.ServiceType, "api"), "", ""), - }) - require.Len(t, got, 1) - prototest.AssertContainsElement(t, got, ConditionBackendRefOutsideMesh( - newRef(pbcatalog.ServiceType, "api"), - )) - }) - - t.Run("with service but using mesh port", func(t *testing.T) { - sg := newTestServiceGetter(newService("api", map[string]pbcatalog.Protocol{ - "http": pbcatalog.Protocol_PROTOCOL_HTTP, - "mesh": pbcatalog.Protocol_PROTOCOL_MESH, - })) - got := computeNewRouteRefConditions(sg, nil, []*pbmesh.BackendReference{ - newBackendRef(newRef(pbcatalog.ServiceType, "api"), "mesh", ""), - }) - require.Len(t, got, 1) - prototest.AssertContainsElement(t, got, ConditionBackendRefUsingMeshPort( - newRef(pbcatalog.ServiceType, "api"), - "mesh", - )) - }) - - t.Run("with service and using missing port", func(t *testing.T) { - sg := newTestServiceGetter(newService("api", map[string]pbcatalog.Protocol{ - "http": pbcatalog.Protocol_PROTOCOL_HTTP, - "mesh": pbcatalog.Protocol_PROTOCOL_MESH, - })) - got := computeNewRouteRefConditions(sg, nil, []*pbmesh.BackendReference{ - newBackendRef(newRef(pbcatalog.ServiceType, "api"), "web", ""), - }) - require.Len(t, got, 1) - prototest.AssertContainsElement(t, got, ConditionUnknownBackendRefPort( - newRef(pbcatalog.ServiceType, "api"), - "web", - )) - }) - - t.Run("with service and using empty port", func(t *testing.T) { - sg := newTestServiceGetter(newService("api", map[string]pbcatalog.Protocol{ - "http": pbcatalog.Protocol_PROTOCOL_HTTP, - "mesh": pbcatalog.Protocol_PROTOCOL_MESH, - })) - got := computeNewRouteRefConditions(sg, nil, []*pbmesh.BackendReference{ - newBackendRef(newRef(pbcatalog.ServiceType, "api"), "", ""), - }) - require.Empty(t, got) - }) - - t.Run("with service and using correct port", func(t *testing.T) { - sg := newTestServiceGetter(newService("api", map[string]pbcatalog.Protocol{ - "http": pbcatalog.Protocol_PROTOCOL_HTTP, - "mesh": pbcatalog.Protocol_PROTOCOL_MESH, - })) - got := computeNewRouteRefConditions(sg, nil, []*pbmesh.BackendReference{ - newBackendRef(newRef(pbcatalog.ServiceType, "api"), "http", ""), - }) - require.Empty(t, got) - }) - }) -} - -func newRef(typ *pbresource.Type, name string) *pbresource.Reference { - return rtest.Resource(typ, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - Reference("") -} - -type testServiceGetter struct { - services map[resource.ReferenceKey]*types.DecodedService -} - -func newTestServiceGetter(svcs ...*types.DecodedService) serviceGetter { - g := &testServiceGetter{ - services: make(map[resource.ReferenceKey]*types.DecodedService), - } - for _, svc := range svcs { - g.services[resource.NewReferenceKey(svc.Resource.Id)] = svc - } - return g -} - -func (g *testServiceGetter) GetService(ref resource.ReferenceOrID) *types.DecodedService { - if g.services == nil { - return nil - } - return g.services[resource.NewReferenceKey(ref)] -} diff --git a/internal/mesh/internal/controllers/routes/routestest/routestest.go b/internal/mesh/internal/controllers/routes/routestest/routestest.go deleted file mode 100644 index 77ba33138d90..000000000000 --- a/internal/mesh/internal/controllers/routes/routestest/routestest.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routestest - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/loader" - "github.com/hashicorp/consul/internal/mesh/internal/types" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" -) - -func ReconcileComputedRoutes( - t *testing.T, - client pbresource.ResourceServiceClient, - id *pbresource.ID, - decResList ...any, -) *types.DecodedComputedRoutes { - t.Helper() - if client == nil { - panic("client is required") - } - return makeComputedRoutes(t, client, id, decResList...) -} - -func BuildComputedRoutes( - t *testing.T, - id *pbresource.ID, - decResList ...any, -) *types.DecodedComputedRoutes { - t.Helper() - return makeComputedRoutes(t, nil, id, decResList...) -} - -func MutateTargets( - t *testing.T, - routes *pbmesh.ComputedRoutes, - parentPort string, - mutFn func(t *testing.T, details *pbmesh.BackendTargetDetails), -) *pbmesh.ComputedPortRoutes { - t.Helper() - - portConfig, ok := routes.PortedConfigs[parentPort] - require.True(t, ok, "port %q not found in ported_configs", parentPort) - - portConfig = proto.Clone(portConfig).(*pbmesh.ComputedPortRoutes) - - for _, details := range portConfig.Targets { - mutFn(t, details) - } - - return portConfig -} - -func makeComputedRoutes( - t *testing.T, - client pbresource.ResourceServiceClient, - id *pbresource.ID, - decResList ...any, -) *types.DecodedComputedRoutes { - t.Helper() - - related := loader.NewRelatedResources(). - AddComputedRoutesID(id). - AddResources(decResList...) - - pending := make(routes.PendingStatuses) - got := routes.GenerateComputedRoutes(related, pending) - require.Empty(t, pending, "programmer error if there are warnings") - require.Len(t, got, 1, "should only compute one output") - - item := got[0] - - if item.Data == nil { - if client != nil { - ctx := testutil.TestContext(t) - _, err := client.Delete(ctx, &pbresource.DeleteRequest{Id: got[0].ID}) - require.NoError(t, err) - } - return nil - } - - b := rtest.ResourceID(id). - // WithOwner(item.OwnerID). - WithData(t, item.Data) - - var res *pbresource.Resource - if client != nil { - res = b.Write(t, client) - } else { - res = b.Build() - } - require.NoError(t, types.ValidateComputedRoutes(res)) - - return rtest.MustDecode[*pbmesh.ComputedRoutes](t, res) -} diff --git a/internal/mesh/internal/controllers/routes/sort_rules.go b/internal/mesh/internal/controllers/routes/sort_rules.go deleted file mode 100644 index a7198d31300f..000000000000 --- a/internal/mesh/internal/controllers/routes/sort_rules.go +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routes - -import ( - "sort" - - "github.com/oklog/ulid" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" -) - -func gammaSortRouteRules(node *inputRouteNode) { - switch { - case resource.EqualType(node.RouteType, pbmesh.HTTPRouteType): - gammaSortHTTPRouteRules(node.HTTPRules) - case resource.EqualType(node.RouteType, pbmesh.GRPCRouteType): - // TODO(rb): do a determinstic sort of something - case resource.EqualType(node.RouteType, pbmesh.TCPRouteType): - // TODO(rb): do a determinstic sort of something - default: - panic("impossible") - } -} - -func gammaSortHTTPRouteRules(rules []*pbmesh.ComputedHTTPRouteRule) { - // First generate a parallel slice. - sortable := &sortableHTTPRouteRules{ - rules: rules, - derivedInfo: make([]*derivedHTTPRouteRuleInfo, 0, len(rules)), - } - - for _, rule := range rules { - var sr derivedHTTPRouteRuleInfo - for _, m := range rule.Matches { - if m.Path != nil { - switch m.Path.Type { - case pbmesh.PathMatchType_PATH_MATCH_TYPE_EXACT: - sr.hasPathExact = true - case pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX: - sr.hasPathPrefix = true - v := len(m.Path.Value) - if v > sr.pathPrefixLength { - sr.pathPrefixLength = v - } - } - } - - if m.Method != "" { - sr.hasMethod = true - } - if v := len(m.Headers); v > sr.numHeaders { - sr.numHeaders = v - } - if v := len(m.QueryParams); v > sr.numQueryParams { - sr.numQueryParams = v - } - } - sortable.derivedInfo = append(sortable.derivedInfo, &sr) - } - - // Similar to - // "agent/consul/discoverychain/gateway_httproute.go" - // compareHTTPRules - - // Sort this by the GAMMA spec. We assume the caller has pre-sorted this - // for tiebreakers based on resource metadata. - - sort.Stable(sortable) -} - -type derivedHTTPRouteRuleInfo struct { - // sortable fields extracted from route - hasPathExact bool - hasPathPrefix bool - pathPrefixLength int - hasMethod bool - numHeaders int - numQueryParams int -} - -type sortableHTTPRouteRules struct { - rules []*pbmesh.ComputedHTTPRouteRule - derivedInfo []*derivedHTTPRouteRuleInfo -} - -var _ sort.Interface = (*sortableHTTPRouteRules)(nil) - -func (r *sortableHTTPRouteRules) Len() int { return len(r.rules) } - -func (r *sortableHTTPRouteRules) Swap(i, j int) { - r.rules[i], r.rules[j] = r.rules[j], r.rules[i] - r.derivedInfo[i], r.derivedInfo[j] = r.derivedInfo[j], r.derivedInfo[i] -} - -func (r *sortableHTTPRouteRules) Less(i, j int) bool { - a := r.derivedInfo[i] - b := r.derivedInfo[j] - - // (1) “Exact” path match. - switch { - case a.hasPathExact && b.hasPathExact: - // NEXT TIE BREAK - case a.hasPathExact && !b.hasPathExact: - return true - case !a.hasPathExact && b.hasPathExact: - return false - } - - // (2) “Prefix” path match with largest number of characters. - switch { - case a.hasPathPrefix && b.hasPathPrefix: - if a.pathPrefixLength != b.pathPrefixLength { - return a.pathPrefixLength > b.pathPrefixLength - } - // NEXT TIE BREAK - case a.hasPathPrefix && !b.hasPathPrefix: - return true - case !a.hasPathPrefix && b.hasPathPrefix: - return false - } - - // (3) Method match. - switch { - case a.hasMethod && b.hasMethod: - // NEXT TIE BREAK - case a.hasMethod && !b.hasMethod: - return true - case !a.hasMethod && b.hasMethod: - return false - } - - // (4) Largest number of header matches. - switch { - case a.numHeaders == b.numHeaders: - // NEXT TIE BREAK - case a.numHeaders > b.numHeaders: - return true - case a.numHeaders < b.numHeaders: - return false - } - - // (5) Largest number of query param matches. - return a.numQueryParams > b.numQueryParams -} - -// gammaInitialSortWrappedRoutes will sort the original inputs by the -// resource-envelope-only fields before we further stable sort by type-specific -// fields. -// -// If more than 1 route is provided the OriginalResource field must be set on -// all inputs (i.e. no synthetic default routes should be processed here). -func gammaInitialSortWrappedRoutes(routes []*inputRouteNode) { - if len(routes) < 2 { - return - } - - // First sort the input routes by the final criteria, so we can let the - // stable sort take care of the ultimate tiebreakers. - sort.Slice(routes, func(i, j int) bool { - var ( - resA = routes[i].OriginalResource - resB = routes[j].OriginalResource - ) - - if resA == nil || resB == nil { - panic("some provided nodes lacked original resources") - } - - var ( - genA = resA.Generation - genB = resB.Generation - ) - - // (END-1) The oldest Route based on creation timestamp. - // - // Because these are ULIDs, we should be able to lexicographically sort - // them to determine the oldest, but we also need to have a further - // tiebreaker AFTER per-gamma so we cannot. - aULID, aErr := ulid.Parse(genA) - bULID, bErr := ulid.Parse(genB) - if aErr == nil && bErr == nil { - aTime := aULID.Time() - bTime := bULID.Time() - - switch { - case aTime < bTime: - return true - case aTime > bTime: - return false - default: - // NEXT TIE BREAK - } - } - - // (END-2) The Route appearing first in alphabetical order by “{namespace}/{name}”. - var ( - tenancyA = resA.Id.Tenancy - tenancyB = resB.Id.Tenancy - - nsA = tenancyA.Namespace - nsB = tenancyB.Namespace - ) - - if nsA == "" { - nsA = "default" - } - if nsB == "" { - nsB = "default" - } - switch { - case nsA < nsB: - return true - case nsA > nsB: - return false - default: - // NEXT TIE BREAK - } - - return resA.Id.Name < resB.Id.Name - - // We get this for free b/c of the stable sort. - // - // If ties still exist within an HTTPRoute, matching precedence MUST - // be granted to the FIRST matching rule (in list order) with a match - // meeting the above criteria. - }) -} diff --git a/internal/mesh/internal/controllers/routes/sort_rules_test.go b/internal/mesh/internal/controllers/routes/sort_rules_test.go deleted file mode 100644 index 50504f09cf4d..000000000000 --- a/internal/mesh/internal/controllers/routes/sort_rules_test.go +++ /dev/null @@ -1,493 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routes - -import ( - "math/rand" - "sort" - "testing" - - "github.com/stretchr/testify/require" - "golang.org/x/exp/slices" - - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func TestGammaInitialSortWrappedRoutes(t *testing.T) { - // These generations were created with ulid.Make().String() at 1 second - // intervals. They are in ascending order. - generations := []string{ - "01H8HGKHXCAJY7TRNJ06JGEZP9", - "01H8HGKJWMEYWKZATG44QZF0G7", - "01H8HGKKVW2339KFHAFXMEFRHP", - "01H8HGKMV45XAC2W1KCQ7KJ00J", - "01H8HGKNTCB3ZYN16AZ2KSXN54", - "01H8HGKPSN9V3QQXTQVZ1EQM2T", - "01H8HGKQRXMR8NY662AC520CDE", - "01H8HGKRR5C41RHGXY7H3N0JYX", - "01H8HGKSQDNSQ54VN86SBTR149", - "01H8HGKTPPRWFXWHKV90M2WW5R", - } - require.True(t, sort.StringsAreSorted(generations)) - - nodeID := func(node *inputRouteNode) string { - return resource.IDToString(node.OriginalResource.Id) + ":" + node.OriginalResource.Generation - } - - nodeIDSlice := func(nodes []*inputRouteNode) []string { - var out []string - for _, node := range nodes { - out = append(out, nodeID(node)) - } - return out - } - - // newNode will only populate the fields that the sorting function cares - // about. - newNode := func(tenancy *pbresource.Tenancy, name string, gen string) *inputRouteNode { - id := rtest.Resource(pbmesh.HTTPRouteType, name). - WithTenancy(tenancy). - ID() - - res := rtest.ResourceID(id). - WithGeneration(gen). - WithData(t, &pbmesh.HTTPRoute{}). - Build() - - return &inputRouteNode{ - OriginalResource: res, - } - } - - type testcase struct { - routes []*inputRouteNode - } - - run := func(t *testing.T, tc testcase) { - expect := nodeIDSlice(tc.routes) - - if len(tc.routes) > 1 { - // Randomly permute it - in := tc.routes - for { - rand.Shuffle(len(in), func(i, j int) { - in[i], in[j] = in[j], in[i] - }) - curr := nodeIDSlice(tc.routes) - - if slices.Equal(expect, curr) { - // Loop until the shuffle was actually different. - } else { - break - } - - } - } - - gammaInitialSortWrappedRoutes(tc.routes) - - got := nodeIDSlice(tc.routes) - - require.Equal(t, expect, got) - } - - // Order: - // 1. generation older first - // 2. tenancy namespace A first - // 3. object name A first - cases := map[string]testcase{ - "empty": {}, - "one": { - routes: []*inputRouteNode{ - newNode(defaultTenancy(), "foo", generations[0]), - }, - }, - "two: by generation": { - routes: []*inputRouteNode{ - newNode(defaultTenancy(), "foo", generations[0]), - newNode(defaultTenancy(), "foo", generations[1]), - }, - }, - "two: by namespace": { - routes: []*inputRouteNode{ - newNode(&pbresource.Tenancy{Namespace: "aaa"}, "foo", generations[0]), - newNode(&pbresource.Tenancy{Namespace: "bbb"}, "foo", generations[0]), - }, - }, - "two: by name": { - routes: []*inputRouteNode{ - newNode(defaultTenancy(), "bar", generations[0]), - newNode(defaultTenancy(), "foo", generations[0]), - }, - }, - "two: by name with empty namespace": { - routes: []*inputRouteNode{ - newNode(nsTenancy(""), "bar", generations[0]), - newNode(nsTenancy(""), "foo", generations[0]), - }, - }, - "four: by generation": { - routes: []*inputRouteNode{ - newNode(defaultTenancy(), "foo", generations[0]), - newNode(defaultTenancy(), "foo", generations[1]), - newNode(defaultTenancy(), "foo", generations[2]), - newNode(defaultTenancy(), "foo", generations[3]), - }, - }, - "four: by name with some empty namespaces": { - routes: []*inputRouteNode{ - newNode(nsTenancy("aaa"), "foo", generations[0]), - newNode(nsTenancy("bbb"), "foo", generations[0]), - newNode(&pbresource.Tenancy{}, "bar", generations[0]), - newNode(&pbresource.Tenancy{}, "foo", generations[0]), - }, - }, - "mixed": { - // Seed this with data such that each later sort criteria should - // want to be more to the top than an earlier criteria would allow, - // to prove that the sort is going to have to shake out the way the - // algorithm wants it to for maximum algorithm exercise. - routes: []*inputRouteNode{ - // gen beats name - newNode(defaultTenancy(), "zzz", generations[0]), - newNode(defaultTenancy(), "aaa", generations[1]), - // gen beats ns - newNode(nsTenancy("zzz"), "foo", generations[2]), - newNode(nsTenancy("aaa"), "foo", generations[3]), - // ns beats name - newNode(nsTenancy("aaa"), "zzz", generations[4]), - newNode(nsTenancy("bbb"), "aaa", generations[5]), - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestGammaSortHTTPRouteRules(t *testing.T) { - type testcase struct { - rules []*pbmesh.ComputedHTTPRouteRule - } - - // In this test we will use the 'backend target' field to track the rule - // identity to make assertions easy. - - targetSlice := func(rules []*pbmesh.ComputedHTTPRouteRule) []string { - var out []string - for _, rule := range rules { - out = append(out, rule.BackendRefs[0].BackendTarget) - } - return out - } - - run := func(t *testing.T, tc testcase) { - expect := targetSlice(tc.rules) - - if len(tc.rules) > 1 { - // Randomly permute it - in := tc.rules - for { - rand.Shuffle(len(in), func(i, j int) { - in[i], in[j] = in[j], in[i] - }) - curr := targetSlice(tc.rules) - - if slices.Equal(expect, curr) { - // Loop until the shuffle was actually different. - } else { - break - } - - } - } - - gammaSortHTTPRouteRules(tc.rules) - - got := targetSlice(tc.rules) - - require.Equal(t, expect, got) - } - - newRule := func(target string, m ...*pbmesh.HTTPRouteMatch) *pbmesh.ComputedHTTPRouteRule { - return &pbmesh.ComputedHTTPRouteRule{ - Matches: m, - BackendRefs: []*pbmesh.ComputedHTTPBackendRef{{ - BackendTarget: target, - }}, - } - } - - // Rules: - // 1. exact path match exists - // 2. prefix match exists - // 3. prefix match has lots of characters - // 4. has method match - // 5. has lots of header matches - // 6. has lots of query param matches - cases := map[string]testcase{ - "empty": {}, - "one": { - rules: []*pbmesh.ComputedHTTPRouteRule{ - newRule("r1", &pbmesh.HTTPRouteMatch{ - // - }), - }, - }, - "two: by exact path match exists": { - rules: []*pbmesh.ComputedHTTPRouteRule{ - newRule("r1", &pbmesh.HTTPRouteMatch{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_EXACT, - Value: "/", - }, - }), - newRule("r2", &pbmesh.HTTPRouteMatch{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/", - }, - }), - }, - }, - "two: by prefix path match exists": { - rules: []*pbmesh.ComputedHTTPRouteRule{ - newRule("r1", &pbmesh.HTTPRouteMatch{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/", - }, - }), - newRule("r2", &pbmesh.HTTPRouteMatch{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_REGEX, - Value: "/[a]", - }, - }), - }, - }, - "two: by prefix path match length": { - rules: []*pbmesh.ComputedHTTPRouteRule{ - newRule("r1", &pbmesh.HTTPRouteMatch{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/longer", - }, - }), - newRule("r2", &pbmesh.HTTPRouteMatch{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/short", - }, - }), - }, - }, - "two: by method match exists": { - rules: []*pbmesh.ComputedHTTPRouteRule{ - newRule("r1", &pbmesh.HTTPRouteMatch{ - Method: "GET", - }), - newRule("r2", &pbmesh.HTTPRouteMatch{ - Headers: []*pbmesh.HTTPHeaderMatch{{ - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-blah", - Value: "foo", - }}, - }), - }, - }, - "two: by header match quantity": { - rules: []*pbmesh.ComputedHTTPRouteRule{ - newRule("r1", &pbmesh.HTTPRouteMatch{ - Headers: []*pbmesh.HTTPHeaderMatch{ - { - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-blah", - Value: "foo", - }, - { - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-other", - Value: "bar", - }, - }, - }), - newRule("r2", &pbmesh.HTTPRouteMatch{ - Headers: []*pbmesh.HTTPHeaderMatch{{ - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-blah", - Value: "foo", - }}, - }), - }, - }, - "two: by query param match quantity": { - rules: []*pbmesh.ComputedHTTPRouteRule{ - newRule("r1", &pbmesh.HTTPRouteMatch{ - QueryParams: []*pbmesh.HTTPQueryParamMatch{ - { - Type: pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT, - Name: "foo", - Value: "1", - }, - { - Type: pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT, - Name: "bar", - Value: "1", - }, - }, - }), - newRule("r2", &pbmesh.HTTPRouteMatch{ - QueryParams: []*pbmesh.HTTPQueryParamMatch{{ - Type: pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT, - Name: "foo", - Value: "1", - }}, - }), - }, - }, - "mixed: has path exact beats has path prefix when both are present": { - rules: []*pbmesh.ComputedHTTPRouteRule{ - newRule("r1", - &pbmesh.HTTPRouteMatch{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_EXACT, - Value: "/", - }, - }, - &pbmesh.HTTPRouteMatch{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/short", - }, - }, - ), - newRule("r2", &pbmesh.HTTPRouteMatch{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/longer", - }, - }), - }, - }, - "mixed: longer path prefix beats shorter when both are present": { - rules: []*pbmesh.ComputedHTTPRouteRule{ - newRule("r1", - &pbmesh.HTTPRouteMatch{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/longer", - }, - }, - &pbmesh.HTTPRouteMatch{ - Method: "GET", - }, - ), - newRule("r2", &pbmesh.HTTPRouteMatch{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/short", - }, - }), - }, - }, - "mixed: has method match beats header match when both are present": { - rules: []*pbmesh.ComputedHTTPRouteRule{ - newRule("r1", - &pbmesh.HTTPRouteMatch{ - Method: "GET", - }, - &pbmesh.HTTPRouteMatch{ - Headers: []*pbmesh.HTTPHeaderMatch{{ - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-blah", - Value: "foo", - }}, - }, - ), - newRule("r2", &pbmesh.HTTPRouteMatch{ - Headers: []*pbmesh.HTTPHeaderMatch{ - { - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-blah", - Value: "foo", - }, - { - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-other", - Value: "bar", - }, - }, - }), - }, - }, - "mixed: header match beats query param match when both are present": { - rules: []*pbmesh.ComputedHTTPRouteRule{ - newRule("r1", &pbmesh.HTTPRouteMatch{ - Headers: []*pbmesh.HTTPHeaderMatch{ - { - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-blah", - Value: "foo", - }, - { - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-other", - Value: "bar", - }, - }, - QueryParams: []*pbmesh.HTTPQueryParamMatch{{ - Type: pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT, - Name: "foo", - Value: "1", - }}, - }), - newRule("r2", &pbmesh.HTTPRouteMatch{ - QueryParams: []*pbmesh.HTTPQueryParamMatch{ - { - Type: pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT, - Name: "foo", - Value: "1", - }, - { - Type: pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT, - Name: "bar", - Value: "1", - }, - }, - }), - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func newID(typ *pbresource.Type, tenancy *pbresource.Tenancy, name string) *pbresource.ID { - return rtest.Resource(typ, name). - WithTenancy(tenancy). - ID() -} - -func nsTenancy(ns string) *pbresource.Tenancy { - return &pbresource.Tenancy{ - Partition: "default", - Namespace: ns, - PeerName: "local", - } -} - -func defaultTenancy() *pbresource.Tenancy { - return nsTenancy("default") -} diff --git a/internal/mesh/internal/controllers/routes/status.go b/internal/mesh/internal/controllers/routes/status.go deleted file mode 100644 index 71b6b8cd5b0b..000000000000 --- a/internal/mesh/internal/controllers/routes/status.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routes - -import ( - "fmt" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - StatusKey = "consul.io/routes-controller" - StatusConditionAccepted = "accepted" - - // conditions on xRoutes - - XRouteOKReason = "Ok" - XRouteOKMessage = "xRoute was accepted" - - MissingParentRefReason = "MissingParentRef" - MissingBackendRefReason = "MissingBackendRef" - - ParentRefOutsideMeshReason = "ParentRefOutsideMesh" - BackendRefOutsideMeshReason = "BackendRefOutsideMesh" - - ParentRefUsingMeshPortReason = "ParentRefUsingMeshPort" - BackendRefUsingMeshPortReason = "BackendRefUsingMeshPort" - - UnknownParentRefPortReason = "UnknownParentRefPort" - UnknownBackendRefPortReason = "UnknownBackendRefPort" - - ConflictNotBoundToParentRefReason = "ConflictNotBoundToParentRef" -) - -var ( - ConditionXRouteOK = &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_TRUE, - Reason: XRouteOKReason, - Message: XRouteOKMessage, - } -) - -func ConditionParentRefUsingMeshPort(ref *pbresource.Reference, port string) *pbresource.Condition { - return conditionRefUsingMeshPort(ref, port, false) -} - -func ConditionBackendRefUsingMeshPort(ref *pbresource.Reference, port string) *pbresource.Condition { - return conditionRefUsingMeshPort(ref, port, true) -} - -func conditionRefUsingMeshPort(ref *pbresource.Reference, port string, forBackend bool) *pbresource.Condition { - reason := ParentRefUsingMeshPortReason - short := "parent" - if forBackend { - reason = BackendRefUsingMeshPortReason - short = "backend" - } - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: reason, - Message: fmt.Sprintf( - "service for %s ref %q uses port %q which is a special unroutable mesh port", - short, - resource.ReferenceToString(ref), - port, - ), - } -} - -func ConditionMissingParentRef(ref *pbresource.Reference) *pbresource.Condition { - return conditionMissingRef(ref, false) -} - -func ConditionMissingBackendRef(ref *pbresource.Reference) *pbresource.Condition { - return conditionMissingRef(ref, true) -} - -func conditionMissingRef(ref *pbresource.Reference, forBackend bool) *pbresource.Condition { - reason := MissingParentRefReason - short := "parent" - if forBackend { - reason = MissingBackendRefReason - short = "backend" - } - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: reason, - Message: fmt.Sprintf( - "service for %s ref %q does not exist", - short, - resource.ReferenceToString(ref), - ), - } -} - -func ConditionParentRefOutsideMesh(ref *pbresource.Reference) *pbresource.Condition { - return conditionRefOutsideMesh(ref, false) -} - -func ConditionBackendRefOutsideMesh(ref *pbresource.Reference) *pbresource.Condition { - return conditionRefOutsideMesh(ref, true) -} - -func conditionRefOutsideMesh(ref *pbresource.Reference, forBackend bool) *pbresource.Condition { - reason := ParentRefOutsideMeshReason - short := "parent" - if forBackend { - reason = BackendRefOutsideMeshReason - short = "backend" - } - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: reason, - Message: fmt.Sprintf( - "service for %s ref %q does not expose a mesh port", - short, - resource.ReferenceToString(ref), - ), - } -} - -func ConditionUnknownParentRefPort(ref *pbresource.Reference, port string) *pbresource.Condition { - return conditionUnknownRefPort(ref, port, false) -} - -func ConditionUnknownBackendRefPort(ref *pbresource.Reference, port string) *pbresource.Condition { - return conditionUnknownRefPort(ref, port, true) -} - -func conditionUnknownRefPort(ref *pbresource.Reference, port string, forBackend bool) *pbresource.Condition { - reason := UnknownParentRefPortReason - short := "parent" - if forBackend { - reason = UnknownBackendRefPortReason - short = "backend" - } - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: reason, - Message: fmt.Sprintf( - "service for %s ref %q does not expose port %q", - short, - resource.ReferenceToString(ref), - port, - ), - } -} - -func ConditionConflictNotBoundToParentRef(ref *pbresource.Reference, port string, realType *pbresource.Type) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: ConflictNotBoundToParentRefReason, - Message: fmt.Sprintf( - "Existing routes of type %q are bound to parent ref %q on port %q preventing this from binding", - resource.TypeToString(realType), - resource.ReferenceToString(ref), - port, - ), - } -} diff --git a/internal/mesh/internal/controllers/routes/util.go b/internal/mesh/internal/controllers/routes/util.go deleted file mode 100644 index 8f9fb87825ae..000000000000 --- a/internal/mesh/internal/controllers/routes/util.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package routes - -import ( - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/protoutil" -) - -// Deprecated: see protoutil.Clone -func protoClone[T proto.Message](v T) T { - return protoutil.Clone(v) -} - -// Deprecated: see protoutil.CloneSlice -func protoSliceClone[T proto.Message](in []T) []T { - return protoutil.CloneSlice(in) -} diff --git a/internal/mesh/internal/controllers/routes/xroutemapper/util.go b/internal/mesh/internal/controllers/routes/xroutemapper/util.go deleted file mode 100644 index e3d843cb2833..000000000000 --- a/internal/mesh/internal/controllers/routes/xroutemapper/util.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xroutemapper - -import ( - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func refSliceToRefSlice(refs []*pbresource.Reference) []resource.ReferenceOrID { - if refs == nil { - return nil - } - out := make([]resource.ReferenceOrID, 0, len(refs)) - for _, ref := range refs { - out = append(out, ref) - } - return out -} - -func parentRefSliceToRefSlice(parentRefs []*pbmesh.ParentReference) []resource.ReferenceOrID { - if parentRefs == nil { - return nil - } - parents := make([]resource.ReferenceOrID, 0, len(parentRefs)) - for _, parentRef := range parentRefs { - if parentRef.Ref != nil { - parents = append(parents, parentRef.Ref) - } - } - return parents -} - -func backendRefSliceToRefSlice(backendRefs []*pbmesh.BackendReference) []resource.ReferenceOrID { - if backendRefs == nil { - return nil - } - backends := make([]resource.ReferenceOrID, 0, len(backendRefs)) - for _, backendRef := range backendRefs { - if backendRef.Ref != nil { - backends = append(backends, backendRef.Ref) - } - } - return backends -} - -func sliceReplaceType(list []*pbresource.ID, typ *pbresource.Type) []*pbresource.ID { - if list == nil { - return nil - } - out := make([]*pbresource.ID, 0, len(list)) - for _, id := range list { - out = append(out, resource.ReplaceType(typ, id)) - } - return out -} diff --git a/internal/mesh/internal/controllers/routes/xroutemapper/xroutemapper.go b/internal/mesh/internal/controllers/routes/xroutemapper/xroutemapper.go deleted file mode 100644 index 2c240ee71819..000000000000 --- a/internal/mesh/internal/controllers/routes/xroutemapper/xroutemapper.go +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xroutemapper - -import ( - "context" - "fmt" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// Mapper tracks the following relationships: -// -// - xRoute <-> ParentRef Service -// - xRoute <-> BackendRef Service -// - FailoverPolicy <-> DestRef Service -// -// It is the job of the controller, loader, and mapper to keep the mappings up -// to date whenever new data is loaded. Notably because the dep mapper events -// do not signal when data is deleted, it is the job of the reconcile load of -// the data causing the event to notice something has been deleted and to -// untrack it here. -type Mapper struct { - boundRefMapper *bimapper.Mapper - - httpRouteParentMapper *bimapper.Mapper - grpcRouteParentMapper *bimapper.Mapper - tcpRouteParentMapper *bimapper.Mapper - - httpRouteBackendMapper *bimapper.Mapper - grpcRouteBackendMapper *bimapper.Mapper - tcpRouteBackendMapper *bimapper.Mapper - - failMapper catalog.FailoverPolicyMapper -} - -// New creates a new Mapper. -func New() *Mapper { - return &Mapper{ - boundRefMapper: bimapper.NewWithWildcardLinkType(pbmesh.ComputedRoutesType), - - httpRouteParentMapper: bimapper.New(pbmesh.HTTPRouteType, pbcatalog.ServiceType), - grpcRouteParentMapper: bimapper.New(pbmesh.GRPCRouteType, pbcatalog.ServiceType), - tcpRouteParentMapper: bimapper.New(pbmesh.TCPRouteType, pbcatalog.ServiceType), - - httpRouteBackendMapper: bimapper.New(pbmesh.HTTPRouteType, pbcatalog.ServiceType), - grpcRouteBackendMapper: bimapper.New(pbmesh.GRPCRouteType, pbcatalog.ServiceType), - tcpRouteBackendMapper: bimapper.New(pbmesh.TCPRouteType, pbcatalog.ServiceType), - - failMapper: catalog.NewFailoverPolicyMapper(), - } -} - -func (m *Mapper) getRouteBiMappers(typ *pbresource.Type) (parent, backend *bimapper.Mapper) { - switch { - case resource.EqualType(pbmesh.HTTPRouteType, typ): - return m.httpRouteParentMapper, m.httpRouteBackendMapper - case resource.EqualType(pbmesh.GRPCRouteType, typ): - return m.grpcRouteParentMapper, m.grpcRouteBackendMapper - case resource.EqualType(pbmesh.TCPRouteType, typ): - return m.tcpRouteParentMapper, m.tcpRouteBackendMapper - default: - panic("unknown xroute type: " + resource.TypeToString(typ)) - } -} - -func (m *Mapper) walkRouteParentBiMappers(fn func(bm *bimapper.Mapper)) { - for _, bm := range []*bimapper.Mapper{ - m.httpRouteParentMapper, - m.grpcRouteParentMapper, - m.tcpRouteParentMapper, - } { - fn(bm) - } -} - -func (m *Mapper) walkRouteBackendBiMappers(fn func(bm *bimapper.Mapper)) { - for _, bm := range []*bimapper.Mapper{ - m.httpRouteBackendMapper, - m.grpcRouteBackendMapper, - m.tcpRouteBackendMapper, - } { - fn(bm) - } -} - -func (m *Mapper) TrackComputedRoutes(cr *types.DecodedComputedRoutes) { - if cr != nil { - refs := refSliceToRefSlice(cr.Data.BoundReferences) - m.boundRefMapper.TrackItem(cr.Resource.Id, refs) - } -} - -func (m *Mapper) UntrackComputedRoutes(id *pbresource.ID) { - m.boundRefMapper.UntrackItem(id) -} - -// TrackXRoute indexes the xRoute->parentRefService and -// xRoute->backendRefService relationship. -func (m *Mapper) TrackXRoute(id *pbresource.ID, xroute types.XRouteData) { - parent, backend := m.getRouteBiMappers(id.Type) - if parent == nil || backend == nil { - return - } - - parentRefs := parentRefSliceToRefSlice(xroute.GetParentRefs()) - backendRefs := backendRefSliceToRefSlice(xroute.GetUnderlyingBackendRefs()) - - parent.TrackItem(id, parentRefs) - backend.TrackItem(id, backendRefs) -} - -// UntrackXRoute undoes TrackXRoute. -func (m *Mapper) UntrackXRoute(id *pbresource.ID) { - parent, backend := m.getRouteBiMappers(id.Type) - if parent == nil || backend == nil { - return - } - - parent.UntrackItem(id) - backend.UntrackItem(id) -} - -// RouteIDsByParentServiceRef returns xRoute IDs that have a direct parentRef link to -// the provided service. -func (m *Mapper) RouteIDsByParentServiceRef(ref *pbresource.Reference) []*pbresource.ID { - var out []*pbresource.ID - m.walkRouteParentBiMappers(func(bm *bimapper.Mapper) { - got := bm.ItemsForLink(resource.IDFromReference(ref)) - out = append(out, got...) - }) - return out -} - -// RouteIDsByBackendServiceRef returns xRoute IDs that have a direct backendRef -// link to the provided service. -func (m *Mapper) RouteIDsByBackendServiceRef(ref *pbresource.Reference) []*pbresource.ID { - var out []*pbresource.ID - m.walkRouteBackendBiMappers(func(bm *bimapper.Mapper) { - got := bm.ItemsForLink(resource.IDFromReference(ref)) - out = append(out, got...) - }) - return out -} - -// ParentServiceRefsByRouteID is the opposite of RouteIDsByParentServiceRef. -func (m *Mapper) ParentServiceRefsByRouteID(item *pbresource.ID) []*pbresource.Reference { - parent, _ := m.getRouteBiMappers(item.Type) - if parent == nil { - return nil - } - return parent.LinksForItem(item) -} - -// BackendServiceRefsByRouteID is the opposite of RouteIDsByBackendServiceRef. -func (m *Mapper) BackendServiceRefsByRouteID(item *pbresource.ID) []*pbresource.Reference { - _, backend := m.getRouteBiMappers(item.Type) - if backend == nil { - return nil - } - return backend.LinksForItem(item) -} - -// MapHTTPRoute will map HTTPRoute changes to ComputedRoutes changes. -func (m *Mapper) MapHTTPRoute(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - return mapXRouteToComputedRoutes[*pbmesh.HTTPRoute](res, m) -} - -// MapGRPCRoute will map GRPCRoute changes to ComputedRoutes changes. -func (m *Mapper) MapGRPCRoute(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - return mapXRouteToComputedRoutes[*pbmesh.GRPCRoute](res, m) -} - -// MapTCPRoute will map TCPRoute changes to ComputedRoutes changes. -func (m *Mapper) MapTCPRoute(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - return mapXRouteToComputedRoutes[*pbmesh.TCPRoute](res, m) -} - -// mapXRouteToComputedRoutes will map xRoute changes to ComputedRoutes changes. -func mapXRouteToComputedRoutes[T types.XRouteData](res *pbresource.Resource, m *Mapper) ([]controller.Request, error) { - dec, err := resource.Decode[T](res) - if err != nil { - return nil, fmt.Errorf("error unmarshalling xRoute: %w", err) - } - - route := dec.Data - - m.TrackXRoute(res.Id, route) - - refs := parentRefSliceToRefSlice(route.GetParentRefs()) - - // Augment with any bound refs to cover the case where an xRoute used to - // have a parentRef to a service and now no longer does. - prevRefs := m.boundRefMapper.ItemRefsForLink(dec.Resource.Id) - for _, ref := range prevRefs { - refs = append(refs, ref) - } - - return controller.MakeRequests(pbmesh.ComputedRoutesType, refs), nil -} - -func (m *Mapper) MapFailoverPolicy( - _ context.Context, - _ controller.Runtime, - res *pbresource.Resource, -) ([]controller.Request, error) { - if !types.IsFailoverPolicyType(res.Id.Type) { - return nil, fmt.Errorf("type is not a failover policy type: %s", res.Id.Type) - } - - dec, err := resource.Decode[*pbcatalog.FailoverPolicy](res) - if err != nil { - return nil, fmt.Errorf("error unmarshalling failover policy: %w", err) - } - - m.failMapper.TrackFailover(dec) - - // Since this is name-aligned, just switch the type and find routes that - // will route any traffic to this destination service. - svcID := resource.ReplaceType(pbcatalog.ServiceType, res.Id) - - return m.mapXRouteDirectServiceRefToComputedRoutesByID(svcID) -} - -func (m *Mapper) TrackFailoverPolicy(failover *types.DecodedFailoverPolicy) { - if failover != nil { - m.failMapper.TrackFailover(failover) - } -} - -func (m *Mapper) UntrackFailoverPolicy(failoverPolicyID *pbresource.ID) { - m.failMapper.UntrackFailover(failoverPolicyID) -} - -func (m *Mapper) MapDestinationPolicy( - _ context.Context, - _ controller.Runtime, - res *pbresource.Resource, -) ([]controller.Request, error) { - if !types.IsDestinationPolicyType(res.Id.Type) { - return nil, fmt.Errorf("type is not a destination policy type: %s", res.Id.Type) - } - - // Since this is name-aligned, just switch the type and find routes that - // will route any traffic to this destination service. - svcID := resource.ReplaceType(pbcatalog.ServiceType, res.Id) - - return m.mapXRouteDirectServiceRefToComputedRoutesByID(svcID) -} - -func (m *Mapper) MapService( - _ context.Context, - _ controller.Runtime, - res *pbresource.Resource, -) ([]controller.Request, error) { - // Ultimately we want to wake up a ComputedRoutes if either of the - // following exist: - // - // 1. xRoute[parentRef=OUTPUT_EVENT; backendRef=INPUT_EVENT] - // 2. xRoute[parentRef=OUTPUT_EVENT; backendRef=SOMETHING], FailoverPolicy[name=SOMETHING, destRef=INPUT_EVENT] - - // (case 2) First find all failover policies that have a reference to our input service. - failPolicyIDs := m.failMapper.FailoverIDsByService(res.Id) - effectiveServiceIDs := sliceReplaceType(failPolicyIDs, pbcatalog.ServiceType) - - // (case 1) Do the direct mapping also. - effectiveServiceIDs = append(effectiveServiceIDs, res.Id) - - var reqs []controller.Request - for _, svcID := range effectiveServiceIDs { - got, err := m.mapXRouteDirectServiceRefToComputedRoutesByID(svcID) - if err != nil { - return nil, err - } - reqs = append(reqs, got...) - } - - return reqs, nil -} - -// NOTE: this function does not interrogate down into failover policies -func (m *Mapper) mapXRouteDirectServiceRefToComputedRoutesByID(svcID *pbresource.ID) ([]controller.Request, error) { - if !types.IsServiceType(svcID.Type) { - return nil, fmt.Errorf("type is not a service type: %s", svcID.Type) - } - - // return 1 hit for the name aligned mesh config - primaryReq := controller.Request{ - ID: resource.ReplaceType(pbmesh.ComputedRoutesType, svcID), - } - - svcRef := resource.Reference(svcID, "") - - // Find all routes with an explicit backend ref to this service. - // - // the "name aligned" inclusion above should handle the implicit default - // destination implied by a parent ref without us having to do much more. - routeIDs := m.RouteIDsByBackendServiceRef(svcRef) - - out := make([]controller.Request, 0, 1+len(routeIDs)) // estimated - out = append(out, primaryReq) - - for _, routeID := range routeIDs { - // Find all parent refs of this route. - svcRefs := m.ParentServiceRefsByRouteID(routeID) - - out = append(out, controller.MakeRequests( - pbmesh.ComputedRoutesType, - svcRefs, - )...) - } - - return out, nil -} diff --git a/internal/mesh/internal/controllers/routes/xroutemapper/xroutemapper_test.go b/internal/mesh/internal/controllers/routes/xroutemapper/xroutemapper_test.go deleted file mode 100644 index e74b049b7dce..000000000000 --- a/internal/mesh/internal/controllers/routes/xroutemapper/xroutemapper_test.go +++ /dev/null @@ -1,694 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xroutemapper - -import ( - "context" - "testing" - "time" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/durationpb" - - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestMapper_HTTPRoute_Tracking(t *testing.T) { - testMapper_Tracking(t, pbmesh.HTTPRouteType, func(t *testing.T, parentRefs []*pbmesh.ParentReference, backendRefs []*pbmesh.BackendReference) proto.Message { - route := &pbmesh.HTTPRoute{ - ParentRefs: parentRefs, - } - for _, backendRef := range backendRefs { - route.Rules = append(route.Rules, &pbmesh.HTTPRouteRule{ - BackendRefs: []*pbmesh.HTTPBackendRef{ - {BackendRef: backendRef}, - }, - }) - } - return route - }) -} - -func TestMapper_GRPCRoute_Tracking(t *testing.T) { - testMapper_Tracking(t, pbmesh.GRPCRouteType, func(t *testing.T, parentRefs []*pbmesh.ParentReference, backendRefs []*pbmesh.BackendReference) proto.Message { - route := &pbmesh.GRPCRoute{ - ParentRefs: parentRefs, - } - for _, backendRef := range backendRefs { - route.Rules = append(route.Rules, &pbmesh.GRPCRouteRule{ - BackendRefs: []*pbmesh.GRPCBackendRef{ - {BackendRef: backendRef}, - }, - }) - } - return route - }) -} - -func TestMapper_TCPRoute_Tracking(t *testing.T) { - testMapper_Tracking(t, pbmesh.TCPRouteType, func(t *testing.T, parentRefs []*pbmesh.ParentReference, backendRefs []*pbmesh.BackendReference) proto.Message { - route := &pbmesh.TCPRoute{ - ParentRefs: parentRefs, - } - for _, backendRef := range backendRefs { - route.Rules = append(route.Rules, &pbmesh.TCPRouteRule{ - BackendRefs: []*pbmesh.TCPBackendRef{ - {BackendRef: backendRef}, - }, - }) - } - return route - }) -} - -func testMapper_Tracking(t *testing.T, typ *pbresource.Type, newRoute func(t *testing.T, parentRefs []*pbmesh.ParentReference, backendRefs []*pbmesh.BackendReference) proto.Message) { - registry := resource.NewRegistry() - types.Register(registry) - catalog.RegisterTypes(registry) - - newService := func(name string) *pbresource.Resource { - svc := rtest.Resource(pbcatalog.ServiceType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbcatalog.Service{}). - Build() - rtest.ValidateAndNormalize(t, registry, svc) - return svc - } - - newDestPolicy := func(name string, dur time.Duration) *pbresource.Resource { - policy := rtest.Resource(pbmesh.DestinationPolicyType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(dur), - }, - }, - }).Build() - rtest.ValidateAndNormalize(t, registry, policy) - return policy - } - - newFailPolicy := func(name string, refs ...*pbresource.Reference) *pbresource.Resource { - var dests []*pbcatalog.FailoverDestination - for _, ref := range refs { - dests = append(dests, &pbcatalog.FailoverDestination{ - Ref: ref, - }) - } - policy := rtest.Resource(pbcatalog.FailoverPolicyType, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: dests, - }, - }).Build() - rtest.ValidateAndNormalize(t, registry, policy) - return policy - } - - apiComputedRoutes := newID(pbmesh.ComputedRoutesType, "api") - wwwComputedRoutes := newID(pbmesh.ComputedRoutesType, "www") - barComputedRoutes := newID(pbmesh.ComputedRoutesType, "bar") - fooComputedRoutes := newID(pbmesh.ComputedRoutesType, "foo") - zimComputedRoutes := newID(pbmesh.ComputedRoutesType, "zim") - girComputedRoutes := newID(pbmesh.ComputedRoutesType, "gir") - - m := New() - - var ( - apiSvc = newService("api") - wwwSvc = newService("www") - barSvc = newService("bar") - fooSvc = newService("foo") - zimSvc = newService("zim") - girSvc = newService("gir") - - apiSvcRef = resource.Reference(apiSvc.Id, "") - wwwSvcRef = resource.Reference(wwwSvc.Id, "") - barSvcRef = resource.Reference(barSvc.Id, "") - fooSvcRef = resource.Reference(fooSvc.Id, "") - zimSvcRef = resource.Reference(zimSvc.Id, "") - girSvcRef = resource.Reference(girSvc.Id, "") - - apiDest = newDestPolicy("api", 55*time.Second) - wwwDest = newDestPolicy("www", 123*time.Second) - - // Start out easy and don't have failover policies that reference other services. - apiFail = newFailPolicy("api", newRef(pbcatalog.ServiceType, "api")) - wwwFail = newFailPolicy("www", newRef(pbcatalog.ServiceType, "www")) - barFail = newFailPolicy("bar", newRef(pbcatalog.ServiceType, "bar")) - ) - - testutil.RunStep(t, "only name aligned defaults", func(t *testing.T) { - requireTracking(t, m, apiSvc, apiComputedRoutes) - requireTracking(t, m, wwwSvc, wwwComputedRoutes) - requireTracking(t, m, barSvc, barComputedRoutes) - requireTracking(t, m, fooSvc, fooComputedRoutes) - requireTracking(t, m, zimSvc, zimComputedRoutes) - requireTracking(t, m, girSvc, girComputedRoutes) - - requireTracking(t, m, apiDest, apiComputedRoutes) - requireTracking(t, m, wwwDest, wwwComputedRoutes) - - // This will track the failover policies. - requireTracking(t, m, apiFail, apiComputedRoutes) - requireTracking(t, m, wwwFail, wwwComputedRoutes) - requireTracking(t, m, barFail, barComputedRoutes) - - // verify other helper methods - for _, ref := range []*pbresource.Reference{apiSvcRef, wwwSvcRef, barSvcRef, fooSvcRef, zimSvcRef, girSvcRef} { - require.Empty(t, m.RouteIDsByBackendServiceRef(ref)) - require.Empty(t, m.RouteIDsByParentServiceRef(ref)) - } - }) - - var ( - route1 *pbresource.Resource - ) - testutil.RunStep(t, "track a name-aligned xroute", func(t *testing.T) { - // First route will also not cross any services. - route1 := rtest.Resource(typ, "route-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, newRoute(t, - []*pbmesh.ParentReference{ - {Ref: newRef(pbcatalog.ServiceType, "api")}, - }, - []*pbmesh.BackendReference{ - newBackendRef("api"), - }, - )).Build() - rtest.ValidateAndNormalize(t, registry, route1) - - requireTracking(t, m, route1, apiComputedRoutes) - - // Now 'api' references should trigger more, but be duplicate-suppressed. - requireTracking(t, m, apiSvc, apiComputedRoutes) - requireTracking(t, m, wwwSvc, wwwComputedRoutes) - requireTracking(t, m, barSvc, barComputedRoutes) - requireTracking(t, m, fooSvc, fooComputedRoutes) - requireTracking(t, m, zimSvc, zimComputedRoutes) - requireTracking(t, m, girSvc, girComputedRoutes) - - requireTracking(t, m, apiDest, apiComputedRoutes) - requireTracking(t, m, wwwDest, wwwComputedRoutes) - - requireTracking(t, m, apiFail, apiComputedRoutes) - requireTracking(t, m, wwwFail, wwwComputedRoutes) - requireTracking(t, m, barFail, barComputedRoutes) - - // verify other helper methods - prototest.AssertElementsMatch(t, []*pbresource.Reference{apiSvcRef}, m.BackendServiceRefsByRouteID(route1.Id)) - prototest.AssertElementsMatch(t, []*pbresource.Reference{apiSvcRef}, m.ParentServiceRefsByRouteID(route1.Id)) - - prototest.AssertElementsMatch(t, []*pbresource.ID{route1.Id}, m.RouteIDsByBackendServiceRef(apiSvcRef)) - prototest.AssertElementsMatch(t, []*pbresource.ID{route1.Id}, m.RouteIDsByParentServiceRef(apiSvcRef)) - - for _, ref := range []*pbresource.Reference{wwwSvcRef, barSvcRef, fooSvcRef, zimSvcRef, girSvcRef} { - require.Empty(t, m.RouteIDsByBackendServiceRef(ref)) - require.Empty(t, m.RouteIDsByParentServiceRef(ref)) - } - }) - - testutil.RunStep(t, "make the route cross services", func(t *testing.T) { - route1 = rtest.Resource(typ, "route-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, newRoute(t, - []*pbmesh.ParentReference{ - {Ref: newRef(pbcatalog.ServiceType, "api")}, - }, - []*pbmesh.BackendReference{ - newBackendRef("www"), - }, - )).Build() - rtest.ValidateAndNormalize(t, registry, route1) - - // Now witness the update. - requireTracking(t, m, route1, apiComputedRoutes) - - // Now 'api' references should trigger different things. - requireTracking(t, m, apiSvc, apiComputedRoutes) - requireTracking(t, m, wwwSvc, wwwComputedRoutes, apiComputedRoutes) - requireTracking(t, m, barSvc, barComputedRoutes) - requireTracking(t, m, fooSvc, fooComputedRoutes) - requireTracking(t, m, zimSvc, zimComputedRoutes) - requireTracking(t, m, girSvc, girComputedRoutes) - - requireTracking(t, m, apiDest, apiComputedRoutes) - requireTracking(t, m, wwwDest, wwwComputedRoutes, apiComputedRoutes) - - requireTracking(t, m, apiFail, apiComputedRoutes) - requireTracking(t, m, wwwFail, wwwComputedRoutes, apiComputedRoutes) - requireTracking(t, m, barFail, barComputedRoutes) - - // verify other helper methods - prototest.AssertElementsMatch(t, []*pbresource.Reference{wwwSvcRef}, m.BackendServiceRefsByRouteID(route1.Id)) - prototest.AssertElementsMatch(t, []*pbresource.Reference{apiSvcRef}, m.ParentServiceRefsByRouteID(route1.Id)) - - require.Empty(t, m.RouteIDsByBackendServiceRef(apiSvcRef)) - prototest.AssertElementsMatch(t, []*pbresource.ID{route1.Id}, m.RouteIDsByParentServiceRef(apiSvcRef)) - - prototest.AssertElementsMatch(t, []*pbresource.ID{route1.Id}, m.RouteIDsByBackendServiceRef(wwwSvcRef)) - require.Empty(t, m.RouteIDsByParentServiceRef(wwwSvcRef)) - - for _, ref := range []*pbresource.Reference{barSvcRef, fooSvcRef, zimSvcRef, girSvcRef} { - require.Empty(t, m.RouteIDsByBackendServiceRef(ref)) - require.Empty(t, m.RouteIDsByParentServiceRef(ref)) - } - }) - - var ( - route2 *pbresource.Resource - ) - testutil.RunStep(t, "make another route sharing a parent with the first", func(t *testing.T) { - route2 = rtest.Resource(typ, "route-2"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, newRoute(t, - []*pbmesh.ParentReference{ - {Ref: newRef(pbcatalog.ServiceType, "api")}, - {Ref: newRef(pbcatalog.ServiceType, "foo")}, - }, - []*pbmesh.BackendReference{ - newBackendRef("bar"), - }, - )).Build() - rtest.ValidateAndNormalize(t, registry, route1) - - // Now witness a route with multiple parents, overlapping the other route. - requireTracking(t, m, route2, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, apiSvc, apiComputedRoutes) - requireTracking(t, m, wwwSvc, wwwComputedRoutes, apiComputedRoutes) - requireTracking(t, m, barSvc, barComputedRoutes, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, fooSvc, fooComputedRoutes) - requireTracking(t, m, zimSvc, zimComputedRoutes) - requireTracking(t, m, girSvc, girComputedRoutes) - - requireTracking(t, m, apiDest, apiComputedRoutes) - requireTracking(t, m, wwwDest, wwwComputedRoutes, apiComputedRoutes) - - requireTracking(t, m, apiFail, apiComputedRoutes) - requireTracking(t, m, wwwFail, wwwComputedRoutes, apiComputedRoutes) - requireTracking(t, m, barFail, barComputedRoutes, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, route1, apiComputedRoutes) - // skip re-verifying route2 - // requireTracking(t, m, route2, apiComputedRoutes, fooComputedRoutes) - - // verify other helper methods - prototest.AssertElementsMatch(t, []*pbresource.Reference{wwwSvcRef}, m.BackendServiceRefsByRouteID(route1.Id)) - prototest.AssertElementsMatch(t, []*pbresource.Reference{apiSvcRef}, m.ParentServiceRefsByRouteID(route1.Id)) - - prototest.AssertElementsMatch(t, []*pbresource.Reference{barSvcRef}, m.BackendServiceRefsByRouteID(route2.Id)) - prototest.AssertElementsMatch(t, []*pbresource.Reference{apiSvcRef, fooSvcRef}, m.ParentServiceRefsByRouteID(route2.Id)) - - require.Empty(t, m.RouteIDsByBackendServiceRef(apiSvcRef)) - prototest.AssertElementsMatch(t, []*pbresource.ID{route1.Id, route2.Id}, m.RouteIDsByParentServiceRef(apiSvcRef)) - - prototest.AssertElementsMatch(t, []*pbresource.ID{route1.Id}, m.RouteIDsByBackendServiceRef(wwwSvcRef)) - require.Empty(t, m.RouteIDsByParentServiceRef(wwwSvcRef)) - - prototest.AssertElementsMatch(t, []*pbresource.ID{route2.Id}, m.RouteIDsByBackendServiceRef(barSvcRef)) - require.Empty(t, m.RouteIDsByParentServiceRef(barSvcRef)) - - require.Empty(t, m.RouteIDsByBackendServiceRef(fooSvcRef)) - prototest.AssertElementsMatch(t, []*pbresource.ID{route2.Id}, m.RouteIDsByParentServiceRef(fooSvcRef)) - - for _, ref := range []*pbresource.Reference{zimSvcRef, girSvcRef} { - require.Empty(t, m.RouteIDsByBackendServiceRef(ref)) - require.Empty(t, m.RouteIDsByParentServiceRef(ref)) - } - }) - - testutil.RunStep(t, "update the failover policy to cross services", func(t *testing.T) { - apiFail = newFailPolicy("api", - newRef(pbcatalog.ServiceType, "foo"), - newRef(pbcatalog.ServiceType, "zim")) - requireTracking(t, m, apiFail, apiComputedRoutes) - - requireTracking(t, m, apiSvc, apiComputedRoutes) - requireTracking(t, m, wwwSvc, wwwComputedRoutes, apiComputedRoutes) - requireTracking(t, m, barSvc, barComputedRoutes, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, fooSvc, fooComputedRoutes, apiComputedRoutes) - requireTracking(t, m, zimSvc, zimComputedRoutes, apiComputedRoutes) - requireTracking(t, m, girSvc, girComputedRoutes) - - requireTracking(t, m, apiDest, apiComputedRoutes) - requireTracking(t, m, wwwDest, wwwComputedRoutes, apiComputedRoutes) - - // skipping verification of apiFail b/c it happened above already - // requireTracking(t, m, apiFail, apiComputedRoutes) - requireTracking(t, m, wwwFail, wwwComputedRoutes, apiComputedRoutes) - requireTracking(t, m, barFail, barComputedRoutes, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, route1, apiComputedRoutes) - requireTracking(t, m, route2, apiComputedRoutes, fooComputedRoutes) - - // verify other helper methods - prototest.AssertElementsMatch(t, []*pbresource.Reference{wwwSvcRef}, m.BackendServiceRefsByRouteID(route1.Id)) - prototest.AssertElementsMatch(t, []*pbresource.Reference{apiSvcRef}, m.ParentServiceRefsByRouteID(route1.Id)) - - prototest.AssertElementsMatch(t, []*pbresource.Reference{barSvcRef}, m.BackendServiceRefsByRouteID(route2.Id)) - prototest.AssertElementsMatch(t, []*pbresource.Reference{apiSvcRef, fooSvcRef}, m.ParentServiceRefsByRouteID(route2.Id)) - - require.Empty(t, m.RouteIDsByBackendServiceRef(apiSvcRef)) - prototest.AssertElementsMatch(t, []*pbresource.ID{route1.Id, route2.Id}, m.RouteIDsByParentServiceRef(apiSvcRef)) - - prototest.AssertElementsMatch(t, []*pbresource.ID{route1.Id}, m.RouteIDsByBackendServiceRef(wwwSvcRef)) - require.Empty(t, m.RouteIDsByParentServiceRef(wwwSvcRef)) - - prototest.AssertElementsMatch(t, []*pbresource.ID{route2.Id}, m.RouteIDsByBackendServiceRef(barSvcRef)) - require.Empty(t, m.RouteIDsByParentServiceRef(barSvcRef)) - - require.Empty(t, m.RouteIDsByBackendServiceRef(fooSvcRef)) - prototest.AssertElementsMatch(t, []*pbresource.ID{route2.Id}, m.RouteIDsByParentServiceRef(fooSvcRef)) - - for _, ref := range []*pbresource.Reference{zimSvcRef, girSvcRef} { - require.Empty(t, m.RouteIDsByBackendServiceRef(ref)) - require.Empty(t, m.RouteIDsByParentServiceRef(ref)) - } - }) - - testutil.RunStep(t, "set a new failover policy for a service in route2", func(t *testing.T) { - barFail = newFailPolicy("bar", - newRef(pbcatalog.ServiceType, "gir")) - requireTracking(t, m, barFail, barComputedRoutes, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, apiSvc, apiComputedRoutes) - requireTracking(t, m, wwwSvc, wwwComputedRoutes, apiComputedRoutes) - requireTracking(t, m, barSvc, barComputedRoutes, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, fooSvc, fooComputedRoutes, apiComputedRoutes) - requireTracking(t, m, zimSvc, zimComputedRoutes, apiComputedRoutes) - requireTracking(t, m, girSvc, girComputedRoutes, barComputedRoutes, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, apiDest, apiComputedRoutes) - requireTracking(t, m, wwwDest, wwwComputedRoutes, apiComputedRoutes) - - requireTracking(t, m, apiFail, apiComputedRoutes) - requireTracking(t, m, wwwFail, wwwComputedRoutes, apiComputedRoutes) - // skipping verification of barFail b/c it happened above already - // requireTracking(t, m, barFail, barComputedRoutes, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, route1, apiComputedRoutes) - requireTracking(t, m, route2, apiComputedRoutes, fooComputedRoutes) - - // verify other helper methods - prototest.AssertElementsMatch(t, []*pbresource.Reference{wwwSvcRef}, m.BackendServiceRefsByRouteID(route1.Id)) - prototest.AssertElementsMatch(t, []*pbresource.Reference{apiSvcRef}, m.ParentServiceRefsByRouteID(route1.Id)) - - prototest.AssertElementsMatch(t, []*pbresource.Reference{barSvcRef}, m.BackendServiceRefsByRouteID(route2.Id)) - prototest.AssertElementsMatch(t, []*pbresource.Reference{apiSvcRef, fooSvcRef}, m.ParentServiceRefsByRouteID(route2.Id)) - - require.Empty(t, m.RouteIDsByBackendServiceRef(apiSvcRef)) - prototest.AssertElementsMatch(t, []*pbresource.ID{route1.Id, route2.Id}, m.RouteIDsByParentServiceRef(apiSvcRef)) - - prototest.AssertElementsMatch(t, []*pbresource.ID{route1.Id}, m.RouteIDsByBackendServiceRef(wwwSvcRef)) - require.Empty(t, m.RouteIDsByParentServiceRef(wwwSvcRef)) - - prototest.AssertElementsMatch(t, []*pbresource.ID{route2.Id}, m.RouteIDsByBackendServiceRef(barSvcRef)) - require.Empty(t, m.RouteIDsByParentServiceRef(barSvcRef)) - - require.Empty(t, m.RouteIDsByBackendServiceRef(fooSvcRef)) - prototest.AssertElementsMatch(t, []*pbresource.ID{route2.Id}, m.RouteIDsByParentServiceRef(fooSvcRef)) - - for _, ref := range []*pbresource.Reference{zimSvcRef, girSvcRef} { - require.Empty(t, m.RouteIDsByBackendServiceRef(ref)) - require.Empty(t, m.RouteIDsByParentServiceRef(ref)) - } - }) - - testutil.RunStep(t, "delete first route", func(t *testing.T) { - m.UntrackXRoute(route1.Id) - route1 = nil - - requireTracking(t, m, apiSvc, apiComputedRoutes) - requireTracking(t, m, wwwSvc, wwwComputedRoutes) - requireTracking(t, m, barSvc, barComputedRoutes, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, fooSvc, fooComputedRoutes, apiComputedRoutes) - requireTracking(t, m, zimSvc, zimComputedRoutes, apiComputedRoutes) - requireTracking(t, m, girSvc, girComputedRoutes, barComputedRoutes, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, apiDest, apiComputedRoutes) - requireTracking(t, m, wwwDest, wwwComputedRoutes) - - requireTracking(t, m, apiFail, apiComputedRoutes) - requireTracking(t, m, wwwFail, wwwComputedRoutes) - requireTracking(t, m, barFail, barComputedRoutes, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, route2, apiComputedRoutes, fooComputedRoutes) - - // verify other helper methods - prototest.AssertElementsMatch(t, []*pbresource.Reference{barSvcRef}, m.BackendServiceRefsByRouteID(route2.Id)) - prototest.AssertElementsMatch(t, []*pbresource.Reference{apiSvcRef, fooSvcRef}, m.ParentServiceRefsByRouteID(route2.Id)) - - require.Empty(t, m.RouteIDsByBackendServiceRef(apiSvcRef)) - prototest.AssertElementsMatch(t, []*pbresource.ID{route2.Id}, m.RouteIDsByParentServiceRef(apiSvcRef)) - - prototest.AssertElementsMatch(t, []*pbresource.ID{route2.Id}, m.RouteIDsByBackendServiceRef(barSvcRef)) - require.Empty(t, m.RouteIDsByParentServiceRef(barSvcRef)) - - require.Empty(t, m.RouteIDsByBackendServiceRef(fooSvcRef)) - prototest.AssertElementsMatch(t, []*pbresource.ID{route2.Id}, m.RouteIDsByParentServiceRef(fooSvcRef)) - - for _, ref := range []*pbresource.Reference{wwwSvcRef, zimSvcRef, girSvcRef} { - require.Empty(t, m.RouteIDsByBackendServiceRef(ref)) - require.Empty(t, m.RouteIDsByParentServiceRef(ref)) - } - }) - - testutil.RunStep(t, "delete all failover", func(t *testing.T) { - m.UntrackFailoverPolicy(apiFail.Id) - m.UntrackFailoverPolicy(wwwFail.Id) - m.UntrackFailoverPolicy(barFail.Id) - - apiFail = nil - wwwFail = nil - barFail = nil - - requireTracking(t, m, apiSvc, apiComputedRoutes) - requireTracking(t, m, wwwSvc, wwwComputedRoutes) - requireTracking(t, m, barSvc, barComputedRoutes, apiComputedRoutes, fooComputedRoutes) - - requireTracking(t, m, fooSvc, fooComputedRoutes) - requireTracking(t, m, zimSvc, zimComputedRoutes) - requireTracking(t, m, girSvc, girComputedRoutes) - - requireTracking(t, m, apiDest, apiComputedRoutes) - requireTracking(t, m, wwwDest, wwwComputedRoutes) - - requireTracking(t, m, route2, apiComputedRoutes, fooComputedRoutes) - - // verify other helper methods - prototest.AssertElementsMatch(t, []*pbresource.Reference{barSvcRef}, m.BackendServiceRefsByRouteID(route2.Id)) - prototest.AssertElementsMatch(t, []*pbresource.Reference{apiSvcRef, fooSvcRef}, m.ParentServiceRefsByRouteID(route2.Id)) - - require.Empty(t, m.RouteIDsByBackendServiceRef(apiSvcRef)) - prototest.AssertElementsMatch(t, []*pbresource.ID{route2.Id}, m.RouteIDsByParentServiceRef(apiSvcRef)) - - prototest.AssertElementsMatch(t, []*pbresource.ID{route2.Id}, m.RouteIDsByBackendServiceRef(barSvcRef)) - require.Empty(t, m.RouteIDsByParentServiceRef(barSvcRef)) - - require.Empty(t, m.RouteIDsByBackendServiceRef(fooSvcRef)) - prototest.AssertElementsMatch(t, []*pbresource.ID{route2.Id}, m.RouteIDsByParentServiceRef(fooSvcRef)) - - for _, ref := range []*pbresource.Reference{wwwSvcRef, zimSvcRef, girSvcRef} { - require.Empty(t, m.RouteIDsByBackendServiceRef(ref)) - require.Empty(t, m.RouteIDsByParentServiceRef(ref)) - } - }) - - testutil.RunStep(t, "delete second route", func(t *testing.T) { - m.UntrackXRoute(route2.Id) - route2 = nil - - requireTracking(t, m, apiSvc, apiComputedRoutes) - requireTracking(t, m, wwwSvc, wwwComputedRoutes) - requireTracking(t, m, barSvc, barComputedRoutes) - - requireTracking(t, m, fooSvc, fooComputedRoutes) - requireTracking(t, m, zimSvc, zimComputedRoutes) - requireTracking(t, m, girSvc, girComputedRoutes) - - requireTracking(t, m, apiDest, apiComputedRoutes) - requireTracking(t, m, wwwDest, wwwComputedRoutes) - - // verify other helper methods - for _, ref := range []*pbresource.Reference{apiSvcRef, wwwSvcRef, barSvcRef, fooSvcRef, zimSvcRef, girSvcRef} { - require.Empty(t, m.RouteIDsByBackendServiceRef(ref)) - require.Empty(t, m.RouteIDsByParentServiceRef(ref)) - } - }) - - testutil.RunStep(t, "removal of a parent still triggers for old computed routes until the bound reference is cleared", func(t *testing.T) { - route1 = rtest.Resource(typ, "route-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, newRoute(t, - []*pbmesh.ParentReference{ - {Ref: newRef(pbcatalog.ServiceType, "bar")}, - {Ref: newRef(pbcatalog.ServiceType, "foo")}, - }, - []*pbmesh.BackendReference{ - newBackendRef("api"), - }, - )).Build() - rtest.ValidateAndNormalize(t, registry, route1) - - requireTracking(t, m, route1, barComputedRoutes, fooComputedRoutes) - - // Simulate a Reconcile that would update the mapper. - // - // NOTE: we do not ValidateAndNormalize these since the mapper doesn't use the data. - fooCR := rtest.ResourceID(fooComputedRoutes). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiSvcRef, - fooSvcRef, - resource.Reference(route1.Id, ""), - }, - }).Build() - m.TrackComputedRoutes(rtest.MustDecode[*pbmesh.ComputedRoutes](t, fooCR)) - - barCR := rtest.ResourceID(barComputedRoutes). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiSvcRef, - barSvcRef, - resource.Reference(route1.Id, ""), - }, - }).Build() - m.TrackComputedRoutes(rtest.MustDecode[*pbmesh.ComputedRoutes](t, barCR)) - - // Still has the same tracking. - requireTracking(t, m, route1, barComputedRoutes, fooComputedRoutes) - - // Now change the route to remove "bar" - - route1 = rtest.Resource(typ, "route-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, newRoute(t, - []*pbmesh.ParentReference{ - {Ref: newRef(pbcatalog.ServiceType, "foo")}, - }, - []*pbmesh.BackendReference{ - newBackendRef("api"), - }, - )).Build() - rtest.ValidateAndNormalize(t, registry, route1) - - // Now we see that it still emits the event for bar, so we get a chance to update it. - requireTracking(t, m, route1, barComputedRoutes, fooComputedRoutes) - - // Update the bound references on 'bar' to remove the route - barCR = rtest.ResourceID(barComputedRoutes). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbmesh.ComputedRoutes{ - BoundReferences: []*pbresource.Reference{ - apiSvcRef, - barSvcRef, - }, - }).Build() - m.TrackComputedRoutes(rtest.MustDecode[*pbmesh.ComputedRoutes](t, barCR)) - - // Now 'bar' no longer has a link to the route. - requireTracking(t, m, route1, fooComputedRoutes) - }) -} - -func requireTracking( - t *testing.T, - mapper *Mapper, - res *pbresource.Resource, - computedRoutesIDs ...*pbresource.ID, -) { - t.Helper() - - require.NotNil(t, res) - - var ( - reqs []controller.Request - err error - ) - switch { - case resource.EqualType(pbmesh.HTTPRouteType, res.Id.Type): - reqs, err = mapper.MapHTTPRoute(context.Background(), controller.Runtime{}, res) - case resource.EqualType(pbmesh.GRPCRouteType, res.Id.Type): - reqs, err = mapper.MapGRPCRoute(context.Background(), controller.Runtime{}, res) - case resource.EqualType(pbmesh.TCPRouteType, res.Id.Type): - reqs, err = mapper.MapTCPRoute(context.Background(), controller.Runtime{}, res) - case resource.EqualType(pbmesh.DestinationPolicyType, res.Id.Type): - reqs, err = mapper.MapDestinationPolicy(context.Background(), controller.Runtime{}, res) - case resource.EqualType(pbcatalog.FailoverPolicyType, res.Id.Type): - reqs, err = mapper.MapFailoverPolicy(context.Background(), controller.Runtime{}, res) - case resource.EqualType(pbcatalog.ServiceType, res.Id.Type): - reqs, err = mapper.MapService(context.Background(), controller.Runtime{}, res) - default: - t.Fatalf("unhandled resource type: %s", resource.TypeToString(res.Id.Type)) - } - - require.NoError(t, err) - reqs = testDeduplicateRequests(reqs) - require.Len(t, reqs, len(computedRoutesIDs)) - for _, computedRoutesID := range computedRoutesIDs { - require.NotNil(t, computedRoutesID) - prototest.AssertContainsElement(t, reqs, controller.Request{ID: computedRoutesID}) - } -} - -func newBackendRef(name string) *pbmesh.BackendReference { - return &pbmesh.BackendReference{ - Ref: newRef(pbcatalog.ServiceType, name), - } -} - -func newRef(typ *pbresource.Type, name string) *pbresource.Reference { - return rtest.Resource(typ, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - Reference("") -} - -func newID(typ *pbresource.Type, name string) *pbresource.ID { - return rtest.Resource(typ, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - ID() -} - -func testDeduplicateRequests(reqs []controller.Request) []controller.Request { - type resID struct { - resource.ReferenceKey - UID string - } - - out := make([]controller.Request, 0, len(reqs)) - seen := make(map[resID]struct{}) - - for _, req := range reqs { - rid := resID{ - ReferenceKey: resource.NewReferenceKey(req.ID), - UID: req.ID.Uid, - } - if _, ok := seen[rid]; !ok { - out = append(out, req) - seen[rid] = struct{}{} - } - } - - return out -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/builder.go b/internal/mesh/internal/controllers/sidecarproxy/builder/builder.go deleted file mode 100644 index 459c68666b98..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/builder.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "fmt" - - "github.com/hashicorp/consul/internal/resource" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// Builder builds a ProxyStateTemplate. -type Builder struct { - id *pbresource.ID - proxyStateTemplate *pbmesh.ProxyStateTemplate - proxyCfg *pbmesh.ComputedProxyConfiguration - trustDomain string - localDatacenter string - defaultAllow bool -} - -func New( - id *pbresource.ID, - identity *pbresource.Reference, - trustDomain string, - dc string, - defaultAllow bool, - proxyCfg *pbmesh.ComputedProxyConfiguration, -) *Builder { - if !resource.EqualType(pbmesh.ProxyStateTemplateType, id.GetType()) { - panic(fmt.Sprintf("wrong type: expected pbmesh.ProxyStateTemplate, but got %T", id.Type)) - } - - if !resource.EqualType(pbauth.WorkloadIdentityType, identity.GetType()) { - panic(fmt.Sprintf("wrong type: expected pbauth.WorkloadIdentityType, but got %T", identity.Type)) - } - return &Builder{ - id: id, - trustDomain: trustDomain, - localDatacenter: dc, - defaultAllow: defaultAllow, - proxyCfg: proxyCfg, - proxyStateTemplate: &pbmesh.ProxyStateTemplate{ - ProxyState: &pbmesh.ProxyState{ - Identity: identity, - Clusters: make(map[string]*pbproxystate.Cluster), - Endpoints: make(map[string]*pbproxystate.Endpoints), - Routes: make(map[string]*pbproxystate.Route), - }, - RequiredEndpoints: make(map[string]*pbproxystate.EndpointRef), - RequiredLeafCertificates: make(map[string]*pbproxystate.LeafCertificateRef), - RequiredTrustBundles: make(map[string]*pbproxystate.TrustBundleRef), - }, - } -} - -func (b *Builder) Build() *pbmesh.ProxyStateTemplate { - workloadIdentity := b.proxyStateTemplate.ProxyState.Identity.Name - b.proxyStateTemplate.RequiredLeafCertificates[workloadIdentity] = &pbproxystate.LeafCertificateRef{ - Name: workloadIdentity, - Namespace: b.id.Tenancy.Namespace, - Partition: b.id.Tenancy.Partition, - } - - b.proxyStateTemplate.RequiredTrustBundles[b.id.Tenancy.PeerName] = &pbproxystate.TrustBundleRef{ - Peer: b.id.Tenancy.PeerName, - } - - finalCleanupOfProxyStateTemplate(b.proxyStateTemplate) - - return b.proxyStateTemplate -} - -func finalCleanupOfProxyStateTemplate(pst *pbmesh.ProxyStateTemplate) { - if pst.ProxyState != nil { - // Ensure all clusters have names by duplicating them from the map - // if the above assembly code neglected any. - for name, cluster := range pst.ProxyState.Clusters { - if cluster.Name == "" && name != "" { - cluster.Name = name - } - } - } -} - -type ListenerBuilder struct { - listener *pbproxystate.Listener - builder *Builder -} - -func (b *Builder) NewListenerBuilder(l *pbproxystate.Listener) *ListenerBuilder { - return &ListenerBuilder{ - listener: l, - builder: b, - } -} - -func (l *ListenerBuilder) buildListener() { - if l.listener != nil { - l.builder.proxyStateTemplate.ProxyState.Listeners = append(l.builder.proxyStateTemplate.ProxyState.Listeners, l.listener) - } -} - -type RouterBuilder struct { - router *pbproxystate.Router - builder *ListenerBuilder -} - -func (b *ListenerBuilder) NewRouterBuilder(r *pbproxystate.Router) *RouterBuilder { - return &RouterBuilder{ - router: r, - builder: b, - } -} - -func (r *RouterBuilder) buildRouter() { - r.builder.listener.Routers = append(r.builder.listener.Routers, r.router) -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/builder_test.go b/internal/mesh/internal/controllers/sidecarproxy/builder/builder_test.go deleted file mode 100644 index 4128fc083950..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/builder_test.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "flag" - "os" - "testing" - - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestMain(m *testing.M) { - flag.Parse() - os.Exit(m.Run()) -} - -func protoToJSON(t *testing.T, pb proto.Message) string { - return prototest.ProtoToJSON(t, pb) -} - -func JSONToProxyTemplate(t *testing.T, json []byte) *pbmesh.ProxyStateTemplate { - t.Helper() - proxyTemplate := &pbmesh.ProxyStateTemplate{} - m := protojson.UnmarshalOptions{} - err := m.Unmarshal(json, proxyTemplate) - require.NoError(t, err) - return proxyTemplate -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/destination_multiport_test.go b/internal/mesh/internal/controllers/sidecarproxy/builder/destination_multiport_test.go deleted file mode 100644 index 289c8c76548e..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/destination_multiport_test.go +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "fmt" - "sort" - "testing" - - "github.com/stretchr/testify/require" - - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - "github.com/hashicorp/consul/internal/testing/golden" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func TestBuildMultiportImplicitDestinations(t *testing.T) { - // TODO(rb/v2): add a fetchertest package to construct implicit upstreams - // correctly from inputs. the following is far too manual and error prone - // to be an accurate representation of what implicit upstreams look like. - const ( - apiApp = "api-app" - apiApp2 = "api-app2" - trustDomain = "foo.consul" - datacenter = "dc1" - ) - proxyCfg := &pbmesh.ComputedProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - TransparentProxy: &pbmesh.TransparentProxy{ - OutboundListenerPort: 15001, - }, - }, - } - - multiportServiceData := &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "tcp", - VirtualPort: 7070, - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - { - TargetPort: "tcp2", - VirtualPort: 8081, - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - { - TargetPort: "http", - VirtualPort: 8080, - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "mesh", - VirtualPort: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - } - - multiportEndpointsData := &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "10.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - } - apiAppService := resourcetest.Resource(pbcatalog.ServiceType, apiApp). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, multiportServiceData). - Build() - - apiApp2Service := resourcetest.Resource(pbcatalog.ServiceType, apiApp2). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, multiportServiceData). - Build() - - apiAppEndpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, apiApp). - WithOwner(apiAppService.Id). - WithData(t, multiportEndpointsData). - WithTenancy(resource.DefaultNamespacedTenancy()).Build() - - apiApp2Endpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, apiApp2). - WithOwner(apiApp2Service.Id). - WithData(t, multiportEndpointsData). - WithTenancy(resource.DefaultNamespacedTenancy()).Build() - - mwEndpointsData := &pbcatalog.ServiceEndpoints{ // variant on apiAppEndpoints - Endpoints: []*pbcatalog.Endpoint{ - { - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "10.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - { - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "10.0.0.2"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - } - mwEndpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, apiApp). - WithOwner(apiAppService.Id). - WithData(t, mwEndpointsData). - WithTenancy(resource.DefaultNamespacedTenancy()).Build() - - apiAppIdentity := &pbresource.Reference{ - Name: fmt.Sprintf("%s-identity", apiApp), - Tenancy: apiAppEndpoints.Id.Tenancy, - } - - apiApp2Identity := &pbresource.Reference{ - Name: fmt.Sprintf("%s-identity", apiApp2), - Tenancy: apiApp2Endpoints.Id.Tenancy, - } - - apiAppComputedRoutesID := resource.ReplaceType(pbmesh.ComputedRoutesType, apiAppService.Id) - apiAppComputedRoutes := routestest.BuildComputedRoutes(t, apiAppComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](t, apiAppService), - ) - require.NotNil(t, apiAppComputedRoutes) - - apiApp2ComputedRoutesID := resource.ReplaceType(pbmesh.ComputedRoutesType, apiApp2Service.Id) - apiApp2ComputedRoutes := routestest.BuildComputedRoutes(t, apiApp2ComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](t, apiApp2Service), - ) - require.NotNil(t, apiApp2ComputedRoutes) - - newImplicitDestination := func( - svc *pbresource.Resource, - endpoints *pbresource.Resource, - computedRoutes *types.DecodedComputedRoutes, - identities []*pbresource.Reference, - virtualIPs []string, - ) []*intermediate.Destination { - svcDec := resourcetest.MustDecode[*pbcatalog.Service](t, svc) - seDec := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](t, endpoints) - - var out []*intermediate.Destination - for _, port := range svcDec.Data.Ports { - portName := port.TargetPort - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue - } - - dest := &intermediate.Destination{ - Service: svcDec, - ComputedPortRoutes: routestest.MutateTargets(t, computedRoutes.Data, portName, func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(svc.Id, details.BackendRef.Ref) && details.BackendRef.Port == portName: - details.ServiceEndpointsId = endpoints.Id - details.ServiceEndpoints = seDec.Data - details.IdentityRefs = identities - } - }), - VirtualIPs: virtualIPs, - } - out = append(out, dest) - } - return out - } - - apiAppDestinations := newImplicitDestination( - apiAppService, - apiAppEndpoints, - apiAppComputedRoutes, - []*pbresource.Reference{apiAppIdentity}, - []string{"1.1.1.1"}, - ) - - apiApp2Destinations := newImplicitDestination( - apiApp2Service, - apiApp2Endpoints, - apiApp2ComputedRoutes, - []*pbresource.Reference{apiApp2Identity}, - []string{"2.2.2.2", "3.3.3.3"}, - ) - - mwDestinations := newImplicitDestination( - apiAppService, - mwEndpoints, - apiAppComputedRoutes, - []*pbresource.Reference{apiAppIdentity}, - []string{"1.1.1.1"}, - ) - - twoImplicitDestinations := append( - append([]*intermediate.Destination{}, apiAppDestinations...), - apiApp2Destinations..., - ) - - cases := map[string]struct { - getDestinations func() []*intermediate.Destination - }{ - // Most basic test that multiport configuration works - "destination/multiport-l4-and-l7-single-implicit-destination-tproxy": { - getDestinations: func() []*intermediate.Destination { return apiAppDestinations }, - }, - // Test shows that with multiple workloads for a service exposing the same ports, the routers - // and clusters do not get duplicated. - "destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy": { - getDestinations: func() []*intermediate.Destination { return mwDestinations }, - }, - // Test shows that with multiple workloads for a service exposing the same ports, the routers - // and clusters do not get duplicated. - "destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy": { - getDestinations: func() []*intermediate.Destination { return twoImplicitDestinations }, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - proxyTmpl := New(testProxyStateTemplateID(), testIdentityRef(), trustDomain, datacenter, false, proxyCfg). - BuildDestinations(c.getDestinations()). - Build() - - // sort routers because of test flakes where order was flip flopping. - actualRouters := proxyTmpl.ProxyState.Listeners[0].Routers - sort.Slice(actualRouters, func(i, j int) bool { - return actualRouters[i].String() < actualRouters[j].String() - }) - - actual := protoToJSON(t, proxyTmpl) - expected := JSONToProxyTemplate(t, golden.GetBytes(t, actual, name+".golden")) - - // sort routers on listener from golden file - expectedRouters := expected.ProxyState.Listeners[0].Routers - sort.Slice(expectedRouters, func(i, j int) bool { - return expectedRouters[i].String() < expectedRouters[j].String() - }) - - // convert back to json after sorting so that test output does not contain extraneous fields. - require.Equal(t, protoToJSON(t, expected), protoToJSON(t, proxyTmpl)) - }) - } -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/destinations.go b/internal/mesh/internal/controllers/sidecarproxy/builder/destinations.go deleted file mode 100644 index c078c3273e43..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/destinations.go +++ /dev/null @@ -1,715 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "fmt" - "time" - - "github.com/hashicorp/consul/agent/xds/naming" - - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" - - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" - "github.com/hashicorp/consul/internal/protoutil" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// BuildDestinations creates listeners, routers, clusters, and endpointRefs for all destinations -// and adds them to the proxyState. -func (b *Builder) BuildDestinations(destinations []*intermediate.Destination) *Builder { - var lb *ListenerBuilder - if b.proxyCfg.IsTransparentProxy() { - lb = b.addTransparentProxyOutboundListener(b.proxyCfg.DynamicConfig.TransparentProxy.OutboundListenerPort) - lb.listener.DefaultRouter = lb.addL4RouterForDirect(naming.OriginalDestinationClusterName, fmt.Sprintf("upstream.%s", naming.OriginalDestinationClusterName)).router - b.addL4ClusterForDirect(naming.OriginalDestinationClusterName) - } - - for _, destination := range destinations { - b.buildDestination(lb, destination) - } - - if b.proxyCfg.IsTransparentProxy() { - lb.buildListener() - } - - return b -} - -func (b *Builder) buildDestination( - tproxyOutboundListenerBuilder *ListenerBuilder, - destination *intermediate.Destination, -) *Builder { - var ( - effectiveProtocol = destination.ComputedPortRoutes.Protocol - targets = destination.ComputedPortRoutes.Targets - ) - - cpr := destination.ComputedPortRoutes - - var lb *ListenerBuilder - if destination.Explicit != nil { - lb = b.addExplicitOutboundListener(destination.Explicit) - } else { - lb = tproxyOutboundListenerBuilder - } - - // router matches based on destination ports should only occur on - // implicit destinations for explicit - var virtualPortNumber uint32 - if destination.Explicit == nil { - for _, port := range destination.Service.Data.Ports { - if port.TargetPort == cpr.ParentRef.Port { - virtualPortNumber = port.VirtualPort - } - } - } - - defaultDC := func(dc string) string { - if destination.Explicit != nil { - dc = orDefault(dc, destination.Explicit.Datacenter) - } - dc = orDefault(dc, b.localDatacenter) - if dc != b.localDatacenter { - panic("cross datacenter service discovery clusters are not supported in v2") - } - return dc - } - - statPrefix := DestinationStatPrefix( - cpr.ParentRef.Ref, - cpr.ParentRef.Port, - defaultDC(""), - ) - - var routeName string - if destination.Explicit != nil { - routeName = lb.listener.Name - } else { - routeName = DestinationResourceID(cpr.ParentRef.Ref, cpr.ParentRef.Port) - } - - var ( - useRDS bool - needsNullRouteCluster bool - ) - switch config := cpr.Config.(type) { - case *pbmesh.ComputedPortRoutes_Http: - // NOTE: this could be HTTP/HTTP2/GRPC - useRDS = true - - route := config.Http - - // this corresponds to roughly "makeUpstreamRouteForDiscoveryChain" - - var proxyRouteRules []*pbproxystate.RouteRule - for _, routeRule := range route.Rules { - for _, backendRef := range routeRule.BackendRefs { - if backendRef.BackendTarget == types.NullRouteBackend { - needsNullRouteCluster = true - } - } - destConfig := b.makeDestinationConfiguration(routeRule.Timeouts, routeRule.Retries) - headerMutations := applyRouteFilters(destConfig, routeRule.Filters) - applyLoadBalancerPolicy(destConfig, cpr, routeRule.BackendRefs) - - dest := b.makeHTTPRouteDestination( - routeRule.BackendRefs, - destConfig, - targets, - defaultDC, - ) - - // Explode out by matches - for _, match := range routeRule.Matches { - routeMatch := makeHTTPRouteMatch(match) - - proxyRouteRules = append(proxyRouteRules, &pbproxystate.RouteRule{ - Match: routeMatch, - Destination: protoutil.Clone(dest), - HeaderMutations: protoutil.CloneSlice(headerMutations), - }) - } - } - - b.addRoute(routeName, &pbproxystate.Route{ - VirtualHosts: []*pbproxystate.VirtualHost{{ - Name: routeName, - Domains: []string{"*"}, - RouteRules: proxyRouteRules, - }}, - }) - - case *pbmesh.ComputedPortRoutes_Grpc: - useRDS = true - route := config.Grpc - - var proxyRouteRules []*pbproxystate.RouteRule - for _, routeRule := range route.Rules { - for _, backendRef := range routeRule.BackendRefs { - if backendRef.BackendTarget == types.NullRouteBackend { - needsNullRouteCluster = true - } - } - destConfig := b.makeDestinationConfiguration(routeRule.Timeouts, routeRule.Retries) - headerMutations := applyRouteFilters(destConfig, routeRule.Filters) - applyLoadBalancerPolicy(destConfig, cpr, routeRule.BackendRefs) - - // nolint:staticcheck - dest := b.makeGRPCRouteDestination( - routeRule.BackendRefs, - destConfig, - targets, - defaultDC, - ) - - // Explode out by matches - for _, match := range routeRule.Matches { - routeMatch := makeGRPCRouteMatch(match) - - proxyRouteRules = append(proxyRouteRules, &pbproxystate.RouteRule{ - Match: routeMatch, - Destination: protoutil.Clone(dest), - HeaderMutations: protoutil.CloneSlice(headerMutations), - }) - } - } - - b.addRoute(routeName, &pbproxystate.Route{ - VirtualHosts: []*pbproxystate.VirtualHost{{ - Name: routeName, - Domains: []string{"*"}, - RouteRules: proxyRouteRules, - }}, - }) - - case *pbmesh.ComputedPortRoutes_Tcp: - route := config.Tcp - useRDS = false - - if len(route.Rules) != 1 { - panic("not possible due to validation and computation") - } - - // When not using RDS we must generate a cluster name to attach to - // the filter chain. With RDS, cluster names get attached to the - // dynamic routes instead. - - routeRule := route.Rules[0] - - for _, backendRef := range routeRule.BackendRefs { - if backendRef.BackendTarget == types.NullRouteBackend { - needsNullRouteCluster = true - } - } - - switch len(routeRule.BackendRefs) { - case 0: - panic("not possible to have a tcp route rule with no backend refs") - case 1: - tcpBackendRef := routeRule.BackendRefs[0] - - clusterName := b.backendTargetToClusterName(tcpBackendRef.BackendTarget, targets, defaultDC) - - rb := lb.addL4RouterForDirect(clusterName, statPrefix) - if destination.Explicit == nil { - rb.addIPAndPortMatch(destination.VirtualIPs, virtualPortNumber) - } - rb.buildRouter() - default: - clusters := make([]*pbproxystate.L4WeightedDestinationCluster, 0, len(routeRule.BackendRefs)) - for _, tcpBackendRef := range routeRule.BackendRefs { - clusterName := b.backendTargetToClusterName(tcpBackendRef.BackendTarget, targets, defaultDC) - - clusters = append(clusters, &pbproxystate.L4WeightedDestinationCluster{ - Name: clusterName, - Weight: wrapperspb.UInt32(tcpBackendRef.Weight), - }) - } - - rb := lb.addL4RouterForSplit(clusters, statPrefix) - if destination.Explicit == nil { - rb.addIPAndPortMatch(destination.VirtualIPs, virtualPortNumber) - } - rb.buildRouter() - } - } - - if useRDS { - if !isProtocolHTTPLike(effectiveProtocol) { - panic(fmt.Sprintf("it should not be possible to have a tcp protocol here: %v", effectiveProtocol)) - } - - rb := lb.addL7Router(routeName, statPrefix, effectiveProtocol) - if destination.Explicit == nil { - rb.addIPAndPortMatch(destination.VirtualIPs, virtualPortNumber) - } - rb.buildRouter() - } else { - if isProtocolHTTPLike(effectiveProtocol) { - panic(fmt.Sprintf("it should not be possible to have an http-like protocol here: %v", effectiveProtocol)) - } - } - - // Build outbound listener if the destination is explicit. - if destination.Explicit != nil { - lb.buildListener() - } - - if needsNullRouteCluster { - b.addNullRouteCluster() - } - - for _, details := range targets { - // NOTE: we only emit clusters for DIRECT targets here. The others will - // be folded into one or more aggregate clusters somehow. - if details.Type != pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT { - continue - } - - connectTimeout := details.DestinationConfig.ConnectTimeout - loadBalancer := details.DestinationConfig.LoadBalancer - - // NOTE: we collect both DIRECT and INDIRECT target information here. - dc := defaultDC(details.BackendRef.Datacenter) - portName := details.BackendRef.Port - - sni := DestinationSNI( - details.BackendRef.Ref, - dc, - b.trustDomain, - ) - clusterName := fmt.Sprintf("%s.%s", portName, sni) - - egName := "" - if details.FailoverConfig != nil { - egName = fmt.Sprintf("%s%d~%s", xdscommon.FailoverClusterNamePrefix, 0, clusterName) - } - egBase := b.newClusterEndpointGroup(egName, sni, portName, details.IdentityRefs, connectTimeout, loadBalancer) - - var endpointGroups []*pbproxystate.EndpointGroup - - // Original target is the first (or only) target. - endpointGroups = append(endpointGroups, egBase) - b.addEndpointsRef(clusterName, details.ServiceEndpointsId, details.MeshPort) - - if details.FailoverConfig != nil { - failover := details.FailoverConfig - // TODO(v2): handle other forms of failover (regions/locality/etc) - - for i, dest := range failover.Destinations { - if dest.BackendTarget == types.NullRouteBackend { - continue // not possible - } - destDetails, ok := targets[dest.BackendTarget] - if !ok { - continue // not possible - } - - destConnectTimeout := destDetails.DestinationConfig.ConnectTimeout - destLoadBalancer := destDetails.DestinationConfig.LoadBalancer - - destDC := defaultDC(destDetails.BackendRef.Datacenter) - destPortName := destDetails.BackendRef.Port - - destSNI := DestinationSNI( - destDetails.BackendRef.Ref, - destDC, - b.trustDomain, - ) - - // index 0 was already given to non-fail original - failoverGroupIndex := i + 1 - destClusterName := fmt.Sprintf("%s%d~%s", xdscommon.FailoverClusterNamePrefix, failoverGroupIndex, clusterName) - - egDest := b.newClusterEndpointGroup(destClusterName, destSNI, destPortName, destDetails.IdentityRefs, destConnectTimeout, destLoadBalancer) - - endpointGroups = append(endpointGroups, egDest) - b.addEndpointsRef(destClusterName, destDetails.ServiceEndpointsId, destDetails.MeshPort) - } - } - - b.addCluster(clusterName, endpointGroups, connectTimeout, pbproxystate.Protocol(effectiveProtocol)) - } - - return b -} - -const NullRouteClusterName = "null_route_cluster" - -func (b *Builder) addNullRouteCluster() *Builder { - cluster := &pbproxystate.Cluster{ - Name: NullRouteClusterName, - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Static{ - Static: &pbproxystate.StaticEndpointGroup{ - Config: &pbproxystate.StaticEndpointGroupConfig{ - ConnectTimeout: durationpb.New(10 * time.Second), - }, - }, - }, - }, - }, - Protocol: pbproxystate.Protocol_PROTOCOL_TCP, - } - - b.proxyStateTemplate.ProxyState.Clusters[cluster.Name] = cluster - return b -} - -func (b *ListenerBuilder) addL4RouterForDirect(clusterName, statPrefix string) *RouterBuilder { - // For explicit destinations, we have no filter chain match, and filters - // are based on port protocol. - router := &pbproxystate.Router{} - - if statPrefix == "" { - statPrefix = fmt.Sprintf("upstream.%s", clusterName) - } - - router.Destination = &pbproxystate.Router_L4{ - L4: &pbproxystate.L4Destination{ - Destination: &pbproxystate.L4Destination_Cluster{ - Cluster: &pbproxystate.DestinationCluster{ - Name: clusterName, - }, - }, - StatPrefix: statPrefix, - }, - } - - return b.NewRouterBuilder(router) -} - -func (b *Builder) addL4ClusterForDirect(clusterName string) *Builder { - cluster := &pbproxystate.Cluster{ - Name: clusterName, - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Passthrough{ - Passthrough: &pbproxystate.PassthroughEndpointGroup{ - Config: &pbproxystate.PassthroughEndpointGroupConfig{ - ConnectTimeout: durationpb.New(5 * time.Second), - }, - }, - }, - }, - }, - Protocol: pbproxystate.Protocol_PROTOCOL_TCP, - } - - b.proxyStateTemplate.ProxyState.Clusters[cluster.Name] = cluster - return b -} - -func (b *ListenerBuilder) addL4RouterForSplit( - clusters []*pbproxystate.L4WeightedDestinationCluster, - statPrefix string, -) *RouterBuilder { - // For explicit destinations, we have no filter chain match, and filters - // are based on port protocol. - router := &pbproxystate.Router{} - - if statPrefix == "" { - statPrefix = "upstream." - } - - router.Destination = &pbproxystate.Router_L4{ - L4: &pbproxystate.L4Destination{ - Destination: &pbproxystate.L4Destination_WeightedClusters{ - WeightedClusters: &pbproxystate.L4WeightedClusterGroup{ - Clusters: clusters, - }, - }, - StatPrefix: statPrefix, - // TODO(rb/v2): can we use RDS for TCPRoute split? - }, - } - - return b.NewRouterBuilder(router) -} - -func (b *ListenerBuilder) addL7Router(routeName string, statPrefix string, protocol pbcatalog.Protocol) *RouterBuilder { - // For explicit destinations, we have no filter chain match, and filters - // are based on port protocol. - router := &pbproxystate.Router{} - - if routeName == "" { - panic("routeName is required") - } - - if statPrefix == "" { - statPrefix = "upstream." - } - - if !isProtocolHTTPLike(protocol) { - panic(fmt.Sprintf("unexpected protocol: %v", protocol)) - } - - router.Destination = &pbproxystate.Router_L7{ - L7: &pbproxystate.L7Destination{ - Route: &pbproxystate.L7DestinationRoute{ - Name: routeName, - }, - StatPrefix: statPrefix, - StaticRoute: false, - Protocol: protocolMapCatalogToL7[protocol], - }, - } - - return b.NewRouterBuilder(router) -} - -// addExplicitOutboundListener creates an outbound listener for an explicit destination. -func (b *Builder) addExplicitOutboundListener(explicit *pbmesh.Destination) *ListenerBuilder { - listener := makeExplicitListener(explicit, pbproxystate.Direction_DIRECTION_OUTBOUND) - - return b.NewListenerBuilder(listener) -} - -func makeExplicitListener(explicit *pbmesh.Destination, direction pbproxystate.Direction) *pbproxystate.Listener { - if explicit == nil { - panic("explicit upstream required") - } - - listener := &pbproxystate.Listener{ - Direction: direction, - } - - // TODO(v2): access logs, connection balancing - - // Create outbound listener address. - switch explicit.ListenAddr.(type) { - case *pbmesh.Destination_IpPort: - destinationAddr := explicit.ListenAddr.(*pbmesh.Destination_IpPort) - listener.BindAddress = &pbproxystate.Listener_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: destinationAddr.IpPort.Ip, - Port: destinationAddr.IpPort.Port, - }, - } - listener.Name = DestinationListenerName(explicit.DestinationRef, explicit.DestinationPort, destinationAddr.IpPort.Ip, destinationAddr.IpPort.Port) - case *pbmesh.Destination_Unix: - destinationAddr := explicit.ListenAddr.(*pbmesh.Destination_Unix) - listener.BindAddress = &pbproxystate.Listener_UnixSocket{ - UnixSocket: &pbproxystate.UnixSocketAddress{ - Path: destinationAddr.Unix.Path, - Mode: destinationAddr.Unix.Mode, - }, - } - listener.Name = DestinationListenerName(explicit.DestinationRef, explicit.DestinationPort, destinationAddr.Unix.Path, 0) - } - - return listener -} - -// addTransparentProxyOutboundListener creates an outbound listener for transparent proxy mode. -func (b *Builder) addTransparentProxyOutboundListener(port uint32) *ListenerBuilder { - listener := &pbproxystate.Listener{ - Name: xdscommon.OutboundListenerName, - Direction: pbproxystate.Direction_DIRECTION_OUTBOUND, - BindAddress: &pbproxystate.Listener_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "127.0.0.1", - Port: port, - }, - }, - Capabilities: []pbproxystate.Capability{pbproxystate.Capability_CAPABILITY_TRANSPARENT}, - } - - return b.NewListenerBuilder(listener) -} - -func isProtocolHTTPLike(protocol pbcatalog.Protocol) bool { - // enumcover:pbcatalog.Protocol - switch protocol { - case pbcatalog.Protocol_PROTOCOL_TCP: - return false - case pbcatalog.Protocol_PROTOCOL_HTTP2, - pbcatalog.Protocol_PROTOCOL_HTTP, - pbcatalog.Protocol_PROTOCOL_GRPC: - return true - case pbcatalog.Protocol_PROTOCOL_MESH: - fallthrough // to default - case pbcatalog.Protocol_PROTOCOL_UNSPECIFIED: - fallthrough // to default - default: - return false - } -} - -func (b *RouterBuilder) addIPMatch(vips []string) *RouterBuilder { - return b.addIPAndPortMatch(vips, 0) -} - -func (b *RouterBuilder) addIPAndPortMatch(vips []string, virtualPort uint32) *RouterBuilder { - b.router.Match = makeRouterMatchForIPAndPort(vips, virtualPort) - return b -} - -func makeRouterMatchForIPAndPort(vips []string, virtualPort uint32) *pbproxystate.Match { - match := &pbproxystate.Match{} - for _, vip := range vips { - match.PrefixRanges = append(match.PrefixRanges, &pbproxystate.CidrRange{ - AddressPrefix: vip, - PrefixLen: &wrapperspb.UInt32Value{Value: 32}, - }) - - if virtualPort > 0 { - match.DestinationPort = &wrapperspb.UInt32Value{Value: virtualPort} - } - } - return match -} - -// addCluster creates and adds a cluster to the proxyState based on the destination. -func (b *Builder) addCluster( - clusterName string, - endpointGroups []*pbproxystate.EndpointGroup, - connectTimeout *durationpb.Duration, - protocol pbproxystate.Protocol, -) { - cluster := &pbproxystate.Cluster{ - Name: clusterName, - AltStatName: clusterName, - Protocol: protocol, - } - switch len(endpointGroups) { - case 0: - panic("no endpoint groups provided") - case 1: - cluster.Group = &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: endpointGroups[0], - } - default: - cluster.Group = &pbproxystate.Cluster_FailoverGroup{ - FailoverGroup: &pbproxystate.FailoverGroup{ - EndpointGroups: endpointGroups, - Config: &pbproxystate.FailoverGroupConfig{ - UseAltStatName: true, - ConnectTimeout: connectTimeout, - }, - }, - } - } - - b.proxyStateTemplate.ProxyState.Clusters[cluster.Name] = cluster -} - -func (b *Builder) newClusterEndpointGroup( - clusterName string, - sni string, - portName string, - destinationIdentities []*pbresource.Reference, - connectTimeout *durationpb.Duration, - loadBalancer *pbmesh.LoadBalancer, -) *pbproxystate.EndpointGroup { - var spiffeIDs []string - for _, identity := range destinationIdentities { - spiffeIDs = append(spiffeIDs, connect.SpiffeIDFromIdentityRef(b.trustDomain, identity)) - } - - // TODO(v2): DestinationPolicy: circuit breakers, outlier detection - - // TODO(v2): if http2/grpc then set http2protocol options - - degConfig := &pbproxystate.DynamicEndpointGroupConfig{ - DisablePanicThreshold: true, - ConnectTimeout: connectTimeout, - } - - if loadBalancer != nil { - // enumcover:pbmesh.LoadBalancerPolicy - switch loadBalancer.Policy { - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RANDOM: - degConfig.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_Random{} - - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_ROUND_ROBIN: - degConfig.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_RoundRobin{} - - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST: - var choiceCount uint32 - cfg, ok := loadBalancer.Config.(*pbmesh.LoadBalancer_LeastRequestConfig) - if ok { - choiceCount = cfg.LeastRequestConfig.GetChoiceCount() - } - degConfig.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_LeastRequest{ - LeastRequest: &pbproxystate.LBPolicyLeastRequest{ - ChoiceCount: wrapperspb.UInt32(choiceCount), - }, - } - - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV: - degConfig.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_Maglev{} - - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH: - policy := &pbproxystate.DynamicEndpointGroupConfig_RingHash{} - - cfg, ok := loadBalancer.Config.(*pbmesh.LoadBalancer_RingHashConfig) - if ok { - policy.RingHash = &pbproxystate.LBPolicyRingHash{ - MinimumRingSize: wrapperspb.UInt64(cfg.RingHashConfig.MinimumRingSize), - MaximumRingSize: wrapperspb.UInt64(cfg.RingHashConfig.MaximumRingSize), - } - } - - degConfig.LbPolicy = policy - - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_UNSPECIFIED: - // fallthrough to default - default: - // do nothing - } - } - - return &pbproxystate.EndpointGroup{ - Name: clusterName, - Group: &pbproxystate.EndpointGroup_Dynamic{ - Dynamic: &pbproxystate.DynamicEndpointGroup{ - Config: degConfig, - OutboundTls: &pbproxystate.TransportSocket{ - ConnectionTls: &pbproxystate.TransportSocket_OutboundMesh{ - OutboundMesh: &pbproxystate.OutboundMeshMTLS{ - IdentityKey: b.proxyStateTemplate.ProxyState.Identity.Name, - ValidationContext: &pbproxystate.MeshOutboundValidationContext{ - SpiffeIds: spiffeIDs, - TrustBundlePeerNameKey: b.id.Tenancy.PeerName, - }, - Sni: sni, - }, - }, - AlpnProtocols: []string{getAlpnProtocolFromPortName(portName)}, - }, - }, - }, - } -} - -func (b *Builder) addRoute(listenerName string, route *pbproxystate.Route) { - b.proxyStateTemplate.ProxyState.Routes[listenerName] = route -} - -// addEndpointsRef creates and add an endpointRef for each serviceEndpoint for a destination and -// adds it to the proxyStateTemplate so it will be processed later during reconciliation by -// the XDS controller. -func (b *Builder) addEndpointsRef(clusterName string, serviceEndpointsID *pbresource.ID, destinationPort string) { - b.proxyStateTemplate.RequiredEndpoints[clusterName] = &pbproxystate.EndpointRef{ - Id: serviceEndpointsID, - Port: destinationPort, - } -} - -func orDefault(v, def string) string { - if v != "" { - return v - } - return def -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/destinations_test.go b/internal/mesh/internal/controllers/sidecarproxy/builder/destinations_test.go deleted file mode 100644 index c6b5a7659254..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/destinations_test.go +++ /dev/null @@ -1,581 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - "github.com/hashicorp/consul/internal/testing/golden" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -var ( - endpointsData = &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "10.0.0.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 7070, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "tcp2": {Port: 8081, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - } - - serviceData = &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "tcp", - VirtualPort: 7070, - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - { - TargetPort: "tcp2", - VirtualPort: 8081, - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - { - TargetPort: "http", - VirtualPort: 8080, - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "mesh", - VirtualPort: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - } -) - -func TestBuildExplicitDestinations(t *testing.T) { - registry := resource.NewRegistry() - types.Register(registry) - catalog.RegisterTypes(registry) - - api1Service := resourcetest.Resource(pbcatalog.ServiceType, "api-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, serviceData). - Build() - - api2Service := resourcetest.Resource(pbcatalog.ServiceType, "api-2"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, serviceData). - Build() - - api3Service := resourcetest.Resource(pbcatalog.ServiceType, "api-3"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, serviceData). - Build() - - backup1Service := resourcetest.Resource(pbcatalog.ServiceType, "backup-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, serviceData). - Build() - - for _, res := range []*pbresource.Resource{ - api1Service, api2Service, api3Service, backup1Service, - } { - resourcetest.ValidateAndNormalize(t, registry, res) - } - - api1Endpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, endpointsData). - Build() - - api2Endpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-2"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, endpointsData). - Build() - - backup1Endpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, "backup-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, endpointsData). - Build() - - for _, res := range []*pbresource.Resource{ - api1Endpoints, api2Endpoints, backup1Endpoints, - } { - resourcetest.ValidateAndNormalize(t, registry, res) - } - - api1Identity := &pbresource.Reference{ - Name: "api1-identity", - Tenancy: api1Endpoints.Id.Tenancy, - } - - api2Identity := &pbresource.Reference{ - Name: "api2-identity", - Tenancy: api2Endpoints.Id.Tenancy, - } - - backup1Identity := &pbresource.Reference{ - Name: "backup1-identity", - Tenancy: backup1Endpoints.Id.Tenancy, - } - - api1DestPolicy := resourcetest.Resource(pbmesh.DestinationPolicyType, api1Service.Id.Name). - WithTenancy(api1Service.Id.GetTenancy()). - WithData(t, &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - RequestTimeout: durationpb.New(77 * time.Second), - // LoadBalancer *LoadBalancer `protobuf:"bytes,3,opt,name=load_balancer,json=loadBalancer,proto3" json:"load_balancer,omitempty"` - }, - }, - }). - Build() - - api1HTTPRoute := resourcetest.Resource(pbmesh.HTTPRouteType, "api-1-http-route"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{{ - Ref: resource.Reference(api1Service.Id, ""), - Port: "http", - }}, - Rules: []*pbmesh.HTTPRouteRule{ - { - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/split", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{ - { - BackendRef: &pbmesh.BackendReference{ - Ref: resource.Reference(api2Service.Id, ""), - }, - Weight: 60, - }, - { - BackendRef: &pbmesh.BackendReference{ - Ref: resource.Reference(api1Service.Id, ""), - }, - Weight: 40, - }, - { - BackendRef: &pbmesh.BackendReference{ - Ref: resource.Reference(api3Service.Id, ""), - }, - Weight: 10, - }, - }, - }, - { - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: &pbmesh.BackendReference{ - Ref: resource.Reference(api1Service.Id, ""), - }, - }}, - Timeouts: &pbmesh.HTTPRouteTimeouts{ - Request: durationpb.New(606 * time.Second), // differnet than the 77s - }, - Retries: &pbmesh.HTTPRouteRetries{ - Number: wrapperspb.UInt32(4), - OnConnectFailure: true, - }, - }, - }, - }). - Build() - resourcetest.ValidateAndNormalize(t, registry, api1HTTPRoute) - - api1FailoverPolicy := resourcetest.Resource(pbcatalog.FailoverPolicyType, "api-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbcatalog.FailoverPolicy{ - PortConfigs: map[string]*pbcatalog.FailoverConfig{ - "http": { - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: resource.Reference(backup1Service.Id, ""), - Port: "http", - }}, - }, - }, - }). - Build() - resourcetest.ValidateAndNormalize(t, registry, api1FailoverPolicy) - - api1TCPRoute := resourcetest.Resource(pbmesh.TCPRouteType, "api-1-tcp-route"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{{ - Ref: resource.Reference(api1Service.Id, ""), - Port: "tcp", - }}, - Rules: []*pbmesh.TCPRouteRule{{ - BackendRefs: []*pbmesh.TCPBackendRef{ - { - BackendRef: &pbmesh.BackendReference{ - Ref: resource.Reference(api2Service.Id, ""), - }, - Weight: 60, - }, - { - BackendRef: &pbmesh.BackendReference{ - Ref: resource.Reference(api1Service.Id, ""), - }, - Weight: 40, - }, - { - BackendRef: &pbmesh.BackendReference{ - Ref: resource.Reference(api3Service.Id, ""), - }, - Weight: 10, - }, - }, - }}, - }). - Build() - resourcetest.ValidateAndNormalize(t, registry, api1TCPRoute) - - api1TCP2Route := resourcetest.Resource(pbmesh.TCPRouteType, "api-1-tcp2-route"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{{ - Ref: resource.Reference(api1Service.Id, ""), - Port: "tcp2", - }}, - Rules: []*pbmesh.TCPRouteRule{{ - BackendRefs: []*pbmesh.TCPBackendRef{ - { - BackendRef: &pbmesh.BackendReference{ - Ref: resource.Reference(api2Service.Id, ""), - }, - Weight: 60, - }, - { - BackendRef: &pbmesh.BackendReference{ - Ref: resource.Reference(api1Service.Id, ""), - }, - Weight: 40, - }, - { - BackendRef: &pbmesh.BackendReference{ - Ref: resource.Reference(api3Service.Id, ""), - }, - Weight: 10, - }, - }, - }}, - }). - Build() - - api1ComputedRoutesID := resource.ReplaceType(pbmesh.ComputedRoutesType, api1Service.Id) - api1ComputedRoutes := routestest.BuildComputedRoutes(t, api1ComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), - resourcetest.MustDecode[*pbcatalog.Service](t, api2Service), - resourcetest.MustDecode[*pbcatalog.Service](t, backup1Service), - // notably we do NOT include api3Service here so we trigger a null route to be generated - resourcetest.MustDecode[*pbmesh.DestinationPolicy](t, api1DestPolicy), - resourcetest.MustDecode[*pbmesh.HTTPRoute](t, api1HTTPRoute), - resourcetest.MustDecode[*pbmesh.TCPRoute](t, api1TCPRoute), - resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, api1FailoverPolicy), - resourcetest.MustDecode[*pbmesh.TCPRoute](t, api1TCP2Route), - ) - require.NotNil(t, api1ComputedRoutes) - - api2ComputedRoutesID := resource.ReplaceType(pbmesh.ComputedRoutesType, api2Service.Id) - api2ComputedRoutes := routestest.BuildComputedRoutes(t, api2ComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](t, api2Service), - ) - require.NotNil(t, api2ComputedRoutes) - - destinationIpPort := &intermediate.Destination{ - Explicit: &pbmesh.Destination{ - DestinationRef: resource.Reference(api1Endpoints.Id, ""), - DestinationPort: "tcp", - Datacenter: "dc1", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{Ip: "1.1.1.1", Port: 1234}, - }, - }, - Service: resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), - ComputedPortRoutes: routestest.MutateTargets(t, api1ComputedRoutes.Data, "tcp", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(api1Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp": - details.ServiceEndpointsId = api1Endpoints.Id - details.ServiceEndpoints = endpointsData - details.IdentityRefs = []*pbresource.Reference{api1Identity} - case resource.ReferenceOrIDMatch(api2Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp": - details.ServiceEndpointsId = api2Endpoints.Id - details.ServiceEndpoints = endpointsData - details.IdentityRefs = []*pbresource.Reference{api2Identity} - } - }), - } - - destinationIpPort2 := &intermediate.Destination{ - Explicit: &pbmesh.Destination{ - DestinationRef: resource.Reference(api1Endpoints.Id, ""), - DestinationPort: "tcp2", - Datacenter: "dc1", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{Ip: "1.1.1.1", Port: 2345}, - }, - }, - Service: resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), - ComputedPortRoutes: routestest.MutateTargets(t, api1ComputedRoutes.Data, "tcp2", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(api1Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp2": - details.ServiceEndpointsId = api1Endpoints.Id - details.ServiceEndpoints = endpointsData - details.IdentityRefs = []*pbresource.Reference{api1Identity} - case resource.ReferenceOrIDMatch(api2Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp2": - details.ServiceEndpointsId = api2Endpoints.Id - details.ServiceEndpoints = endpointsData - details.IdentityRefs = []*pbresource.Reference{api2Identity} - } - }), - } - - destinationUnix := &intermediate.Destination{ - Explicit: &pbmesh.Destination{ - DestinationRef: resource.Reference(api2Endpoints.Id, ""), - DestinationPort: "tcp", - Datacenter: "dc1", - ListenAddr: &pbmesh.Destination_Unix{ - Unix: &pbmesh.UnixSocketAddress{Path: "/path/to/socket", Mode: "0666"}, - }, - }, - Service: resourcetest.MustDecode[*pbcatalog.Service](t, api2Service), - ComputedPortRoutes: routestest.MutateTargets(t, api2ComputedRoutes.Data, "tcp", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(api2Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp": - details.ServiceEndpointsId = api2Endpoints.Id - details.ServiceEndpoints = endpointsData - details.IdentityRefs = []*pbresource.Reference{api2Identity} - } - }), - } - - destinationUnix2 := &intermediate.Destination{ - Explicit: &pbmesh.Destination{ - DestinationRef: resource.Reference(api2Endpoints.Id, ""), - DestinationPort: "tcp2", - Datacenter: "dc1", - ListenAddr: &pbmesh.Destination_Unix{ - Unix: &pbmesh.UnixSocketAddress{Path: "/path/to/socket", Mode: "0666"}, - }, - }, - Service: resourcetest.MustDecode[*pbcatalog.Service](t, api2Service), - ComputedPortRoutes: routestest.MutateTargets(t, api2ComputedRoutes.Data, "tcp2", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(api2Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp2": - details.ServiceEndpointsId = api2Endpoints.Id - details.ServiceEndpoints = endpointsData - details.IdentityRefs = []*pbresource.Reference{api2Identity} - } - }), - } - destinationIpPortHTTP := &intermediate.Destination{ - Explicit: &pbmesh.Destination{ - DestinationRef: resource.Reference(api1Endpoints.Id, ""), - DestinationPort: "http", - Datacenter: "dc1", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{Ip: "1.1.1.1", Port: 1234}, - }, - }, - Service: resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), - ComputedPortRoutes: routestest.MutateTargets(t, api1ComputedRoutes.Data, "http", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(api1Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "http": - details.ServiceEndpointsId = api1Endpoints.Id - details.ServiceEndpoints = endpointsData - details.IdentityRefs = []*pbresource.Reference{api1Identity} - case resource.ReferenceOrIDMatch(api2Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "http": - details.ServiceEndpointsId = api2Endpoints.Id - details.ServiceEndpoints = endpointsData - details.IdentityRefs = []*pbresource.Reference{api2Identity} - case resource.ReferenceOrIDMatch(backup1Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "http": - details.ServiceEndpointsId = backup1Endpoints.Id - details.ServiceEndpoints = endpointsData - details.IdentityRefs = []*pbresource.Reference{backup1Identity} - } - }), - } - _ = backup1Identity - - cases := map[string]struct { - destinations []*intermediate.Destination - }{ - "destination/l4-single-destination-ip-port-bind-address": { - destinations: []*intermediate.Destination{destinationIpPort}, - }, - "destination/l4-single-destination-unix-socket-bind-address": { - destinations: []*intermediate.Destination{destinationUnix}, - }, - "destination/l4-multi-destination": { - destinations: []*intermediate.Destination{destinationIpPort, destinationUnix, destinationIpPort2, destinationUnix2}, - }, - "destination/mixed-multi-destination": { - destinations: []*intermediate.Destination{destinationIpPort, destinationUnix, destinationIpPortHTTP}, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - proxyTmpl := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", false, nil). - BuildDestinations(c.destinations). - Build() - - actual := protoToJSON(t, proxyTmpl) - expected := golden.Get(t, actual, name+".golden") - - require.JSONEq(t, expected, actual) - }) - } -} - -func TestBuildImplicitDestinations(t *testing.T) { - api1Service := resourcetest.Resource(pbcatalog.ServiceType, "api-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, serviceData). - Build() - - api2Service := resourcetest.Resource(pbcatalog.ServiceType, "api-2"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, serviceData). - Build() - - api1Endpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-1"). - WithOwner(api1Service.Id). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, endpointsData).Build() - - api2Endpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-2"). - WithOwner(api2Service.Id). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, endpointsData).Build() - - api1Identity := &pbresource.Reference{ - Name: "api1-identity", - Tenancy: api1Endpoints.Id.Tenancy, - } - - api2Identity := &pbresource.Reference{ - Name: "api2-identity", - Tenancy: api2Endpoints.Id.Tenancy, - } - - api1ComputedRoutesID := resource.ReplaceType(pbmesh.ComputedRoutesType, api1Service.Id) - api1ComputedRoutes := routestest.BuildComputedRoutes(t, api1ComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), - ) - require.NotNil(t, api1ComputedRoutes) - - api2ComputedRoutesID := resource.ReplaceType(pbmesh.ComputedRoutesType, api2Service.Id) - api2ComputedRoutes := routestest.BuildComputedRoutes(t, api2ComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](t, api2Service), - ) - require.NotNil(t, api2ComputedRoutes) - - proxyCfg := &pbmesh.ComputedProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - TransparentProxy: &pbmesh.TransparentProxy{ - OutboundListenerPort: 15001, - }, - }, - } - - destination1 := &intermediate.Destination{ - Service: resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), - ComputedPortRoutes: routestest.MutateTargets(t, api1ComputedRoutes.Data, "tcp", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(api1Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp": - details.ServiceEndpointsId = api1Endpoints.Id - details.ServiceEndpoints = endpointsData - details.IdentityRefs = []*pbresource.Reference{api1Identity} - } - }), - VirtualIPs: []string{"1.1.1.1"}, - } - - destination2 := &intermediate.Destination{ - Service: resourcetest.MustDecode[*pbcatalog.Service](t, api2Service), - ComputedPortRoutes: routestest.MutateTargets(t, api2ComputedRoutes.Data, "tcp", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(api2Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp": - details.ServiceEndpointsId = api2Endpoints.Id - details.ServiceEndpoints = endpointsData - details.IdentityRefs = []*pbresource.Reference{api2Identity} - } - }), - VirtualIPs: []string{"2.2.2.2", "3.3.3.3"}, - } - - destination3 := &intermediate.Destination{ - Explicit: &pbmesh.Destination{ - DestinationRef: resource.Reference(api1Endpoints.Id, ""), - DestinationPort: "tcp", - Datacenter: "dc1", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{Ip: "1.1.1.1", Port: 1234}, - }, - }, - Service: resourcetest.MustDecode[*pbcatalog.Service](t, api1Service), - ComputedPortRoutes: routestest.MutateTargets(t, api1ComputedRoutes.Data, "tcp", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(api1Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp": - details.ServiceEndpointsId = api1Endpoints.Id - details.ServiceEndpoints = endpointsData - details.IdentityRefs = []*pbresource.Reference{api1Identity} - } - }), - } - - cases := map[string]struct { - destinations []*intermediate.Destination - }{ - "destination/l4-single-implicit-destination-tproxy": { - destinations: []*intermediate.Destination{destination1}, - }, - "destination/l4-multiple-implicit-destinations-tproxy": { - destinations: []*intermediate.Destination{destination1, destination2}, - }, - "destination/l4-implicit-and-explicit-destinations-tproxy": { - destinations: []*intermediate.Destination{destination2, destination3}, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - proxyTmpl := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", false, proxyCfg). - BuildDestinations(c.destinations). - Build() - - actual := protoToJSON(t, proxyTmpl) - expected := golden.Get(t, actual, name+".golden") - - require.JSONEq(t, expected, actual) - }) - } -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/expose_paths.go b/internal/mesh/internal/controllers/sidecarproxy/builder/expose_paths.go deleted file mode 100644 index 991d6e6c7a87..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/expose_paths.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "fmt" - "regexp" - - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" -) - -func (b *Builder) buildExposePaths(workload *pbcatalog.Workload) { - if b.proxyCfg.GetDynamicConfig() != nil && b.proxyCfg.GetDynamicConfig().GetExposeConfig() != nil { - for _, exposePath := range b.proxyCfg.GetDynamicConfig().GetExposeConfig().GetExposePaths() { - clusterName := exposePathClusterName(exposePath) - - b.addExposePathsListener(workload, exposePath). - addExposePathsRouter(exposePath). - buildListener() - - var protocol pbcatalog.Protocol - switch exposePath.Protocol { - case pbmesh.ExposePathProtocol_EXPOSE_PATH_PROTOCOL_HTTP: - protocol = pbcatalog.Protocol_PROTOCOL_HTTP - case pbmesh.ExposePathProtocol_EXPOSE_PATH_PROTOCOL_HTTP2: - protocol = pbcatalog.Protocol_PROTOCOL_HTTP2 - default: - panic("unsupported expose paths protocol") - } - - b.addExposePathsRoute(exposePath, clusterName). - addLocalAppCluster(clusterName, nil, pbproxystate.Protocol(protocol)). - addLocalAppStaticEndpoints(clusterName, exposePath.LocalPathPort) - } - } -} - -func (b *Builder) addExposePathsListener(workload *pbcatalog.Workload, exposePath *pbmesh.ExposePath) *ListenerBuilder { - listenerName := exposePathListenerName(exposePath) - - listener := &pbproxystate.Listener{ - Name: listenerName, - Direction: pbproxystate.Direction_DIRECTION_INBOUND, - } - - meshAddress := workload.GetFirstNonExternalMeshAddress() - if meshAddress == nil { - return b.NewListenerBuilder(nil) - } - - listener.BindAddress = &pbproxystate.Listener_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: meshAddress.Host, - Port: exposePath.ListenerPort, - }, - } - - return b.NewListenerBuilder(listener) -} - -func (b *ListenerBuilder) addExposePathsRouter(exposePath *pbmesh.ExposePath) *ListenerBuilder { - if b.listener == nil { - return b - } - destinationName := exposePathRouteName(exposePath) - - var l7Protocol pbproxystate.L7Protocol - - switch exposePath.Protocol { - case pbmesh.ExposePathProtocol_EXPOSE_PATH_PROTOCOL_HTTP: - l7Protocol = pbproxystate.L7Protocol_L7_PROTOCOL_HTTP - case pbmesh.ExposePathProtocol_EXPOSE_PATH_PROTOCOL_HTTP2: - l7Protocol = pbproxystate.L7Protocol_L7_PROTOCOL_HTTP2 - default: - panic("unsupported expose paths protocol") - } - routerDestination := &pbproxystate.Router_L7{ - L7: &pbproxystate.L7Destination{ - Route: &pbproxystate.L7DestinationRoute{ - Name: destinationName, - }, - StatPrefix: destinationName, - StaticRoute: true, - Protocol: l7Protocol, - }, - } - - router := &pbproxystate.Router{ - Destination: routerDestination, - } - - b.listener.Routers = append(b.listener.Routers, router) - - return b -} - -func (b *Builder) addExposePathsRoute(exposePath *pbmesh.ExposePath, clusterName string) *Builder { - routeName := exposePathRouteName(exposePath) - routeRule := &pbproxystate.RouteRule{ - Match: &pbproxystate.RouteMatch{ - PathMatch: &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Exact{ - Exact: exposePath.Path, - }, - }, - }, - Destination: &pbproxystate.RouteDestination{ - Destination: &pbproxystate.RouteDestination_Cluster{ - Cluster: &pbproxystate.DestinationCluster{ - Name: clusterName, - }, - }, - }, - } - virtualHost := &pbproxystate.VirtualHost{ - Name: routeName, - Domains: []string{"*"}, - RouteRules: []*pbproxystate.RouteRule{routeRule}, - } - route := &pbproxystate.Route{ - VirtualHosts: []*pbproxystate.VirtualHost{virtualHost}, - } - - b.proxyStateTemplate.ProxyState.Routes[routeName] = route - return b -} - -func exposePathName(exposePath *pbmesh.ExposePath) string { - r := regexp.MustCompile(`[^a-zA-Z0-9]+`) - // The regex removes anything not a letter or number from the path. - path := r.ReplaceAllString(exposePath.Path, "") - return path -} - -func exposePathListenerName(exposePath *pbmesh.ExposePath) string { - // The path could be empty, so the unique name for this exposed path is the path and listener port. - pathPort := fmt.Sprintf("%s%d", exposePathName(exposePath), exposePath.ListenerPort) - listenerName := fmt.Sprintf("exposed_path_%s", pathPort) - return listenerName -} - -func exposePathRouteName(exposePath *pbmesh.ExposePath) string { - // The path could be empty, so the unique name for this exposed path is the path and listener port. - pathPort := fmt.Sprintf("%s%d", exposePathName(exposePath), exposePath.ListenerPort) - return fmt.Sprintf("exposed_path_route_%s", pathPort) -} - -func exposePathClusterName(exposePath *pbmesh.ExposePath) string { - return fmt.Sprintf("exposed_cluster_%d", exposePath.LocalPathPort) -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/expose_paths_test.go b/internal/mesh/internal/controllers/sidecarproxy/builder/expose_paths_test.go deleted file mode 100644 index c2c9217f4093..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/expose_paths_test.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "testing" - - "github.com/stretchr/testify/require" - - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/sdk/testutil" -) - -// This file contains tests only for error and edge cases cases. The happy case is tested in local_app_test.go - -func TestBuildExposePaths_NilChecks(t *testing.T) { - testutil.RunStep(t, "proxy cfg is nil", func(t *testing.T) { - b := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", true, nil) - require.NotPanics(t, func() { - b.buildExposePaths(nil) - }) - }) - - testutil.RunStep(t, "dynamic cfg is nil", func(t *testing.T) { - b := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", true, &pbmesh.ComputedProxyConfiguration{}) - require.NotPanics(t, func() { - b.buildExposePaths(nil) - }) - }) - - testutil.RunStep(t, "expose cfg is nil", func(t *testing.T) { - b := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", true, &pbmesh.ComputedProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{}, - }) - require.NotPanics(t, func() { - b.buildExposePaths(nil) - }) - }) -} - -func TestBuildExposePaths_NoExternalMeshWorkloadAddress(t *testing.T) { - workload := &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "1.1.1.1", External: true}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - "mesh": {Port: 20000}, - }, - } - - proxycfg := &pbmesh.ComputedProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - ExposeConfig: &pbmesh.ExposeConfig{ - ExposePaths: []*pbmesh.ExposePath{ - { - ListenerPort: 1234, - LocalPathPort: 9090, - Path: "/health", - }, - }, - }, - }, - } - - b := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", true, proxycfg) - b.buildExposePaths(workload) - require.Empty(t, b.proxyStateTemplate.ProxyState.Listeners) -} - -func TestBuildExposePaths_InvalidProtocol(t *testing.T) { - workload := &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "1.1.1.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - } - - proxycfg := &pbmesh.ComputedProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - ExposeConfig: &pbmesh.ExposeConfig{ - ExposePaths: []*pbmesh.ExposePath{ - { - ListenerPort: 1234, - LocalPathPort: 9090, - Path: "/health", - Protocol: 3, - }, - }, - }, - }, - } - - b := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", true, proxycfg) - require.PanicsWithValue(t, "unsupported expose paths protocol", func() { - b.buildExposePaths(workload) - }) -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/local_app.go b/internal/mesh/internal/controllers/sidecarproxy/builder/local_app.go deleted file mode 100644 index 871cb444bd5d..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/local_app.go +++ /dev/null @@ -1,500 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "fmt" - - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "google.golang.org/protobuf/types/known/wrapperspb" - - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" -) - -func (b *Builder) BuildLocalApp(workload *pbcatalog.Workload, ctp *pbauth.ComputedTrafficPermissions) *Builder { - // Add the public listener. - lb := b.addInboundListener(xdscommon.PublicListenerName, workload) - lb.buildListener() - - trafficPermissions := buildTrafficPermissions(b.defaultAllow, b.trustDomain, workload, ctp) - - // Go through workload ports and add the routers, clusters, endpoints, and TLS. - // Note that the order of ports is non-deterministic here but the xds generation - // code should make sure to send it in the same order to Envoy to avoid unnecessary - // updates. - foundInboundNonMeshPorts := false - for portName, port := range workload.Ports { - clusterName := fmt.Sprintf("%s:%s", xdscommon.LocalAppClusterName, portName) - routeName := fmt.Sprintf("%s:%s", lb.listener.Name, portName) - - if port.Protocol != pbcatalog.Protocol_PROTOCOL_MESH { - foundInboundNonMeshPorts = true - lb.addInboundRouter(clusterName, routeName, port, portName, trafficPermissions[portName], b.proxyCfg.GetDynamicConfig().GetInboundConnections()). - addInboundTLS() - - if isL7(port.Protocol) { - b.addLocalAppRoute(routeName, clusterName, portName) - } - b.addLocalAppCluster(clusterName, &portName, pbproxystate.Protocol(port.Protocol)). - addLocalAppStaticEndpoints(clusterName, port.GetPort()) - } - } - - b.buildExposePaths(workload) - - // If there are no inbound ports other than the mesh port, we black-hole all inbound traffic. - if !foundInboundNonMeshPorts { - lb.addBlackHoleRouter() - b.addBlackHoleCluster() - } - - return b -} - -func buildTrafficPermissions(globalDefaultAllow bool, trustDomain string, workload *pbcatalog.Workload, computed *pbauth.ComputedTrafficPermissions) map[string]*pbproxystate.TrafficPermissions { - portsWithProtocol := workload.GetPortsByProtocol() - var defaultAllow bool - // If the computed traffic permissions don't exist yet, use default deny just to be safe. - // When it exists, use default deny unless no traffic permissions exist and default allow - // is configured globally. - if computed != nil && computed.IsDefault && globalDefaultAllow { - defaultAllow = true - } - - out := make(map[string]*pbproxystate.TrafficPermissions) - portToProtocol := make(map[string]pbcatalog.Protocol) - var allPorts []string - for protocol, ports := range portsWithProtocol { - if protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue - } - - for _, p := range ports { - allPorts = append(allPorts, p) - portToProtocol[p] = protocol - out[p] = &pbproxystate.TrafficPermissions{ - DefaultAllow: defaultAllow, - } - } - } - - if computed == nil { - return out - } - - for _, p := range computed.DenyPermissions { - drsByPort := destinationRulesByPort(allPorts, p.DestinationRules) - principals := makePrincipals(trustDomain, p) - for port := range drsByPort { - out[port].DenyPermissions = append(out[port].DenyPermissions, &pbproxystate.Permission{ - Principals: principals, - }) - } - } - - for _, p := range computed.AllowPermissions { - drsByPort := destinationRulesByPort(allPorts, p.DestinationRules) - principals := makePrincipals(trustDomain, p) - for port := range drsByPort { - if _, ok := out[port]; !ok { - continue - } - - out[port].AllowPermissions = append(out[port].AllowPermissions, &pbproxystate.Permission{ - Principals: principals, - }) - } - } - - return out -} - -// TODO this is a placeholder until we add them to the IR. -type DestinationRule struct{} - -func destinationRulesByPort(allPorts []string, destinationRules []*pbauth.DestinationRule) map[string][]DestinationRule { - out := make(map[string][]DestinationRule) - - if len(destinationRules) == 0 { - for _, p := range allPorts { - out[p] = nil - } - - return out - } - - for _, destinationRule := range destinationRules { - ports, dr := convertDestinationRule(allPorts, destinationRule) - for _, p := range ports { - out[p] = append(out[p], dr) - } - } - - return out -} - -func convertDestinationRule(allPorts []string, dr *pbauth.DestinationRule) ([]string, DestinationRule) { - ports := make(map[string]struct{}) - if len(dr.PortNames) > 0 { - for _, p := range dr.PortNames { - ports[p] = struct{}{} - } - } else { - for _, p := range allPorts { - ports[p] = struct{}{} - } - } - - for _, exclude := range dr.Exclude { - for _, p := range exclude.PortNames { - delete(ports, p) - } - } - - var out []string - for p := range ports { - out = append(out, p) - } - - return out, DestinationRule{} -} - -func makePrincipals(trustDomain string, perm *pbauth.Permission) []*pbproxystate.Principal { - var principals []*pbproxystate.Principal - for _, s := range perm.Sources { - principals = append(principals, makePrincipal(trustDomain, s)) - } - - return principals -} - -func makePrincipal(trustDomain string, s *pbauth.Source) *pbproxystate.Principal { - excludes := make([]*pbproxystate.Spiffe, 0, len(s.Exclude)) - for _, es := range s.Exclude { - excludes = append(excludes, sourceToSpiffe(trustDomain, es)) - } - - return &pbproxystate.Principal{ - Spiffe: sourceToSpiffe(trustDomain, s), - ExcludeSpiffes: excludes, - } -} - -const ( - anyPath = `[^/]+` -) - -func sourceToSpiffe(trustDomain string, s pbauth.SourceToSpiffe) *pbproxystate.Spiffe { - var ( - name = s.GetIdentityName() - ns = s.GetNamespace() - ap = s.GetPartition() - ) - - if ns == "" && name != "" { - panic(fmt.Sprintf("not possible to have a wildcarded namespace %q but an exact identity %q", ns, name)) - } - - if ap == "" { - panic("not possible to have a wildcarded source partition") - } - - if ns == "" { - ns = anyPath - } - if name == "" { - name = anyPath - } - - spiffeURI := connect.SpiffeIDWorkloadIdentity{ - TrustDomain: trustDomain, - Partition: ap, - Namespace: ns, - WorkloadIdentity: name, - }.URI() - - matcher := fmt.Sprintf(`^%s://%s%s$`, spiffeURI.Scheme, spiffeURI.Host, spiffeURI.Path) - - return &pbproxystate.Spiffe{ - Regex: matcher, - } -} - -func (b *Builder) addInboundListener(name string, workload *pbcatalog.Workload) *ListenerBuilder { - listener := &pbproxystate.Listener{ - Name: name, - Direction: pbproxystate.Direction_DIRECTION_INBOUND, - } - - // We will take listener bind port from the workload. - // Find mesh port. - meshPort, ok := workload.GetMeshPortName() - if !ok { - // At this point, we should only get workloads that have mesh ports. - return &ListenerBuilder{ - builder: b, - } - } - - // Check if the workload has a specific address for the mesh port. - meshAddresses := workload.GetNonExternalAddressesForPort(meshPort) - - // If there are no mesh addresses, return. This should be impossible. - if len(meshAddresses) == 0 { - return &ListenerBuilder{ - builder: b, - } - } - - // If there are more than one mesh address, use the first one in the list. - var meshAddress string - if len(meshAddresses) > 0 { - meshAddress = meshAddresses[0].Host - } - - listener.BindAddress = &pbproxystate.Listener_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: meshAddress, - Port: workload.Ports[meshPort].Port, - }, - } - - // Add TLS inspection capability to be able to parse ALPN and/or SNI information from inbound connections. - listener.Capabilities = append(listener.Capabilities, pbproxystate.Capability_CAPABILITY_L4_TLS_INSPECTION) - - if b.proxyCfg.GetDynamicConfig() != nil && b.proxyCfg.GetDynamicConfig().InboundConnections != nil { - listener.BalanceConnections = pbproxystate.BalanceConnections(b.proxyCfg.DynamicConfig.InboundConnections.BalanceInboundConnections) - } - return b.NewListenerBuilder(listener) -} - -func (l *ListenerBuilder) addInboundRouter(clusterName string, routeName string, - port *pbcatalog.WorkloadPort, portName string, tp *pbproxystate.TrafficPermissions, - ic *pbmesh.InboundConnectionsConfig) *ListenerBuilder { - - if l.listener == nil { - return l - } - - if port.Protocol == pbcatalog.Protocol_PROTOCOL_TCP { - r := &pbproxystate.Router{ - Destination: &pbproxystate.Router_L4{ - L4: &pbproxystate.L4Destination{ - Destination: &pbproxystate.L4Destination_Cluster{ - Cluster: &pbproxystate.DestinationCluster{ - Name: clusterName, - }, - }, - StatPrefix: l.listener.Name, - TrafficPermissions: tp, - }, - }, - Match: &pbproxystate.Match{ - AlpnProtocols: []string{getAlpnProtocolFromPortName(portName)}, - }, - } - - if ic != nil { - // MaxInboundConnections is uint32 that is used on: - // - router destinations MaxInboundConnection (uint64). - // - cluster circuit breakers UpstreamLimits.MaxConnections (uint32). - // It is cast to a uint64 here similarly as it is to the proxystateconverter code. - r.GetL4().MaxInboundConnections = uint64(ic.MaxInboundConnections) - } - - l.listener.Routers = append(l.listener.Routers, r) - } else if isL7(port.Protocol) { - r := &pbproxystate.Router{ - Destination: &pbproxystate.Router_L7{ - L7: &pbproxystate.L7Destination{ - StatPrefix: l.listener.Name, - Protocol: protocolMapCatalogToL7[port.Protocol], - TrafficPermissions: tp, - StaticRoute: true, - // Route name for l7 local app destinations differentiates between routes for each port. - Route: &pbproxystate.L7DestinationRoute{ - Name: routeName, - }, - }, - }, - Match: &pbproxystate.Match{ - AlpnProtocols: []string{getAlpnProtocolFromPortName(portName)}, - }, - } - - if ic != nil { - // MaxInboundConnections is cast to a uint64 here similarly as it is to the - // as the L4 case statement above and in proxystateconverter code. - r.GetL7().MaxInboundConnections = uint64(ic.MaxInboundConnections) - } - - l.listener.Routers = append(l.listener.Routers, r) - } - return l -} - -func (l *ListenerBuilder) addBlackHoleRouter() *ListenerBuilder { - if l.listener == nil { - return l - } - - r := &pbproxystate.Router{ - Destination: &pbproxystate.Router_L4{ - L4: &pbproxystate.L4Destination{ - Destination: &pbproxystate.L4Destination_Cluster{ - Cluster: &pbproxystate.DestinationCluster{ - Name: xdscommon.BlackHoleClusterName, - }, - }, - StatPrefix: l.listener.Name, - }, - }, - } - l.listener.Routers = append(l.listener.Routers, r) - - return l -} - -func getAlpnProtocolFromPortName(portName string) string { - return fmt.Sprintf("consul~%s", portName) -} - -func (b *Builder) addLocalAppRoute(routeName, clusterName, portName string) { - proxyRouteRule := &pbproxystate.RouteRule{ - Match: &pbproxystate.RouteMatch{ - PathMatch: &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: "/", - }, - }, - }, - Destination: &pbproxystate.RouteDestination{ - Destination: &pbproxystate.RouteDestination_Cluster{ - Cluster: &pbproxystate.DestinationCluster{ - Name: clusterName, - }, - }, - }, - } - if b.proxyCfg.GetDynamicConfig() != nil && b.proxyCfg.GetDynamicConfig().LocalConnection != nil { - lc, lcOK := b.proxyCfg.GetDynamicConfig().LocalConnection[portName] - if lcOK { - proxyRouteRule.Destination.DestinationConfiguration = - &pbproxystate.DestinationConfiguration{ - TimeoutConfig: &pbproxystate.TimeoutConfig{ - Timeout: lc.RequestTimeout, - }, - } - } - } - - // Each route name for the local app is listenerName:port since there is a route per port on the local app listener. - b.addRoute(routeName, &pbproxystate.Route{ - VirtualHosts: []*pbproxystate.VirtualHost{{ - Name: routeName, - Domains: []string{"*"}, - RouteRules: []*pbproxystate.RouteRule{proxyRouteRule}, - }}, - }) -} - -func isL7(protocol pbcatalog.Protocol) bool { - if protocol == pbcatalog.Protocol_PROTOCOL_HTTP || protocol == pbcatalog.Protocol_PROTOCOL_HTTP2 || protocol == pbcatalog.Protocol_PROTOCOL_GRPC { - return true - } - return false -} - -func (b *Builder) addLocalAppCluster(clusterName string, portName *string, protocol pbproxystate.Protocol) *Builder { - // Make cluster for this router destination. - cluster := &pbproxystate.Cluster{ - Group: &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: &pbproxystate.EndpointGroup{ - Group: &pbproxystate.EndpointGroup_Static{ - Static: &pbproxystate.StaticEndpointGroup{}, - }, - }, - }, - Protocol: protocol, - } - - // configure inbound connections or connection timeout if either is defined - if b.proxyCfg.GetDynamicConfig() != nil && portName != nil { - lc, lcOK := b.proxyCfg.DynamicConfig.LocalConnection[*portName] - - if lcOK || b.proxyCfg.DynamicConfig.InboundConnections != nil { - cluster.GetEndpointGroup().GetStatic().Config = &pbproxystate.StaticEndpointGroupConfig{} - - if lcOK { - cluster.GetEndpointGroup().GetStatic().GetConfig().ConnectTimeout = lc.ConnectTimeout - } - - if b.proxyCfg.DynamicConfig.InboundConnections != nil { - cluster.GetEndpointGroup().GetStatic().GetConfig().CircuitBreakers = &pbproxystate.CircuitBreakers{ - UpstreamLimits: &pbproxystate.UpstreamLimits{ - MaxConnections: &wrapperspb.UInt32Value{Value: b.proxyCfg.DynamicConfig.InboundConnections.MaxInboundConnections}, - }, - } - } - } - } - - b.proxyStateTemplate.ProxyState.Clusters[clusterName] = cluster - return b -} - -func (b *Builder) addBlackHoleCluster() *Builder { - return b.addLocalAppCluster(xdscommon.BlackHoleClusterName, nil, pbproxystate.Protocol_PROTOCOL_TCP) -} - -func (b *Builder) addLocalAppStaticEndpoints(clusterName string, port uint32) { - // We're adding endpoints statically as opposed to creating an endpoint ref - // because this endpoint is less likely to change as we're not tracking the health. - endpoint := &pbproxystate.Endpoint{ - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "127.0.0.1", - Port: port, - }, - }, - } - b.proxyStateTemplate.ProxyState.Endpoints[clusterName] = &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{endpoint}, - } -} - -func (l *ListenerBuilder) addInboundTLS() *ListenerBuilder { - if l.listener == nil { - return nil - } - - // For inbound TLS, we want to use this proxy's identity. - workloadIdentity := l.builder.proxyStateTemplate.ProxyState.Identity.Name - - inboundTLS := &pbproxystate.TransportSocket{ - ConnectionTls: &pbproxystate.TransportSocket_InboundMesh{ - InboundMesh: &pbproxystate.InboundMeshMTLS{ - IdentityKey: workloadIdentity, - ValidationContext: &pbproxystate.MeshInboundValidationContext{ - TrustBundlePeerNameKeys: []string{l.builder.id.Tenancy.PeerName}, - }, - }, - }, - } - - for i := range l.listener.Routers { - l.listener.Routers[i].InboundTls = inboundTLS - } - return l -} - -var protocolMapCatalogToL7 = map[pbcatalog.Protocol]pbproxystate.L7Protocol{ - pbcatalog.Protocol_PROTOCOL_HTTP: pbproxystate.L7Protocol_L7_PROTOCOL_HTTP, - pbcatalog.Protocol_PROTOCOL_HTTP2: pbproxystate.L7Protocol_L7_PROTOCOL_HTTP2, - pbcatalog.Protocol_PROTOCOL_GRPC: pbproxystate.L7Protocol_L7_PROTOCOL_GRPC, -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/local_app_multiport_test.go b/internal/mesh/internal/controllers/sidecarproxy/builder/local_app_multiport_test.go deleted file mode 100644 index 12cbb387af3a..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/local_app_multiport_test.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "sort" - "testing" - - "github.com/hashicorp/consul/internal/testing/golden" - - "github.com/stretchr/testify/require" - - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" -) - -func TestBuildLocalApp_Multiport(t *testing.T) { - cases := map[string]struct { - workload *pbcatalog.Workload - }{ - "source/multiport-l7-single-workload-address-without-ports": { - workload: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - "grpc-port": {Port: 9091, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - "source/multiport-l7-multiple-workload-addresses-without-ports": { - workload: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - }, - { - Host: "10.0.0.2", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - "grpc-port": {Port: 9091, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - "source/multiport-l7-multiple-workload-addresses-with-specific-ports": { - workload: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - Ports: []string{"admin-port"}, - }, - { - Host: "10.0.0.2", - Ports: []string{"api-port"}, - }, - { - Host: "10.0.0.3", - Ports: []string{"mesh"}, - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - "source/multiport-l4-single-workload-address-without-ports": { - workload: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - "source/multiport-l4-multiple-workload-addresses-without-ports": { - workload: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - }, - { - Host: "10.0.0.2", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - "source/multiport-l4-multiple-workload-addresses-with-specific-ports": { - workload: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - Ports: []string{"admin-port"}, - }, - { - Host: "10.0.0.2", - Ports: []string{"api-port"}, - }, - { - Host: "10.0.0.3", - Ports: []string{"mesh"}, - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "admin-port": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "api-port": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - "source/multiport-l4-workload-with-only-mesh-port": { - workload: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - proxyTmpl := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", false, nil). - BuildLocalApp(c.workload, nil). - Build() - - // sort routers because of test flakes where order was flip flopping. - actualRouters := proxyTmpl.ProxyState.Listeners[0].Routers - sort.Slice(actualRouters, func(i, j int) bool { - return actualRouters[i].String() < actualRouters[j].String() - }) - - actual := protoToJSON(t, proxyTmpl) - expected := JSONToProxyTemplate(t, golden.GetBytes(t, actual, name+".golden")) - - // sort routers on listener from golden file - expectedRouters := expected.ProxyState.Listeners[0].Routers - sort.Slice(expectedRouters, func(i, j int) bool { - return expectedRouters[i].String() < expectedRouters[j].String() - }) - - // convert back to json after sorting so that test output does not contain extraneous fields. - require.Equal(t, protoToJSON(t, expected), protoToJSON(t, proxyTmpl)) - }) - } -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/local_app_test.go b/internal/mesh/internal/controllers/sidecarproxy/builder/local_app_test.go deleted file mode 100644 index 7c4ff8df04a3..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/local_app_test.go +++ /dev/null @@ -1,582 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "google.golang.org/protobuf/types/known/durationpb" - "sort" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - "github.com/hashicorp/consul/internal/testing/golden" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestBuildLocalApp(t *testing.T) { - cases := map[string]struct { - workload *pbcatalog.Workload - ctp *pbauth.ComputedTrafficPermissions - defaultAllow bool - }{ - "source/single-workload-address-without-ports": { - workload: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "http": {Port: 8081, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "http2": {Port: 8082, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - "grpc": {Port: 8083, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - "source/multiple-workload-addresses-without-ports": { - workload: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - }, - { - Host: "10.0.0.2", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "http": {Port: 8081, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "http2": {Port: 8082, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - "grpc": {Port: 8083, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - "source/multiple-workload-addresses-with-specific-ports": { - workload: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "127.0.0.1", - Ports: []string{"tcp", "grpc", "mesh"}, - }, - { - Host: "10.0.0.2", - Ports: []string{"http", "http2", "mesh"}, - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "http": {Port: 8081, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "http2": {Port: 8082, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - "grpc": {Port: 8083, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - ctp: &pbauth.ComputedTrafficPermissions{ - AllowPermissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - IdentityName: "foo", - Namespace: "default", - Partition: "default", - }, - }, - }, - }, - }, - defaultAllow: true, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - proxyTmpl := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", true, nil). - BuildLocalApp(c.workload, nil). - Build() - - // sort routers because of test flakes where order was flip flopping. - actualRouters := proxyTmpl.ProxyState.Listeners[0].Routers - sort.Slice(actualRouters, func(i, j int) bool { - return actualRouters[i].String() < actualRouters[j].String() - }) - - actual := protoToJSON(t, proxyTmpl) - expected := JSONToProxyTemplate(t, golden.GetBytes(t, actual, name+".golden")) - - // sort routers on listener from golden file - expectedRouters := expected.ProxyState.Listeners[0].Routers - sort.Slice(expectedRouters, func(i, j int) bool { - return expectedRouters[i].String() < expectedRouters[j].String() - }) - - // convert back to json after sorting so that test output does not contain extraneous fields. - require.Equal(t, protoToJSON(t, expected), protoToJSON(t, proxyTmpl)) - }) - } -} - -func TestBuildLocalApp_WithProxyConfiguration(t *testing.T) { - cases := map[string]struct { - workload *pbcatalog.Workload - proxyCfg *pbmesh.ComputedProxyConfiguration - }{ - "source/l7-expose-paths": { - workload: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "port1": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "port2": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - proxyCfg: &pbmesh.ComputedProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - ExposeConfig: &pbmesh.ExposeConfig{ - ExposePaths: []*pbmesh.ExposePath{ - { - ListenerPort: 1234, - Path: "/health", - LocalPathPort: 9090, - Protocol: pbmesh.ExposePathProtocol_EXPOSE_PATH_PROTOCOL_HTTP, - }, - { - ListenerPort: 1235, - Path: "GetHealth", - LocalPathPort: 9091, - Protocol: pbmesh.ExposePathProtocol_EXPOSE_PATH_PROTOCOL_HTTP2, - }, - }, - }, - }, - }, - }, - // source/local-and-inbound-connections shows that configuring LocalCOnnection - // and InboundConnections in DynamicConfig will set fields on standard clusters and routes, - // but will not set fields on exposed path clusters and routes. - "source/local-and-inbound-connections": { - workload: &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "port1": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "port2": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - "port3": {Port: 8081, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - }, - proxyCfg: &pbmesh.ComputedProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - LocalConnection: map[string]*pbmesh.ConnectionConfig{ - "port1": { - ConnectTimeout: durationpb.New(6 * time.Second), - RequestTimeout: durationpb.New(7 * time.Second)}, - "port3": { - ConnectTimeout: durationpb.New(8 * time.Second), - RequestTimeout: durationpb.New(9 * time.Second)}, - }, - InboundConnections: &pbmesh.InboundConnectionsConfig{ - MaxInboundConnections: 123, - BalanceInboundConnections: pbmesh.BalanceConnections(pbproxystate.BalanceConnections_BALANCE_CONNECTIONS_EXACT), - }, - ExposeConfig: &pbmesh.ExposeConfig{ - ExposePaths: []*pbmesh.ExposePath{ - { - ListenerPort: 1234, - Path: "/health", - LocalPathPort: 9090, - Protocol: pbmesh.ExposePathProtocol_EXPOSE_PATH_PROTOCOL_HTTP, - }, - { - ListenerPort: 1235, - Path: "GetHealth", - LocalPathPort: 9091, - Protocol: pbmesh.ExposePathProtocol_EXPOSE_PATH_PROTOCOL_HTTP2, - }, - }, - }, - }, - }, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - proxyTmpl := New(testProxyStateTemplateID(), testIdentityRef(), "foo.consul", "dc1", true, c.proxyCfg). - BuildLocalApp(c.workload, nil). - Build() - - // sort routers because of test flakes where order was flip flopping. - actualRouters := proxyTmpl.ProxyState.Listeners[0].Routers - sort.Slice(actualRouters, func(i, j int) bool { - return actualRouters[i].String() < actualRouters[j].String() - }) - - actual := protoToJSON(t, proxyTmpl) - expected := JSONToProxyTemplate(t, golden.GetBytes(t, actual, name+".golden")) - - // sort routers on listener from golden file - expectedRouters := expected.ProxyState.Listeners[0].Routers - sort.Slice(expectedRouters, func(i, j int) bool { - return expectedRouters[i].String() < expectedRouters[j].String() - }) - - // convert back to json after sorting so that test output does not contain extraneous fields. - require.Equal(t, protoToJSON(t, expected), protoToJSON(t, proxyTmpl)) - }) - } -} - -func TestBuildL4TrafficPermissions(t *testing.T) { - testTrustDomain := "test.consul" - - cases := map[string]struct { - defaultAllow bool - workloadPorts map[string]*pbcatalog.WorkloadPort - ctp *pbauth.ComputedTrafficPermissions - expected map[string]*pbproxystate.TrafficPermissions - }{ - "empty": { - defaultAllow: true, - workloadPorts: map[string]*pbcatalog.WorkloadPort{ - "p1": { - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - "p2": { - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - "p3": {}, - "mesh": { - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - expected: map[string]*pbproxystate.TrafficPermissions{ - "p1": { - DefaultAllow: false, - }, - "p2": { - DefaultAllow: false, - }, - "p3": { - DefaultAllow: false, - }, - }, - }, - "default allow everywhere": { - defaultAllow: true, - workloadPorts: map[string]*pbcatalog.WorkloadPort{ - "p1": { - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - "p2": { - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - "p3": {}, - "mesh": { - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - ctp: &pbauth.ComputedTrafficPermissions{ - IsDefault: true, - }, - expected: map[string]*pbproxystate.TrafficPermissions{ - "p1": { - DefaultAllow: true, - }, - "p2": { - DefaultAllow: true, - }, - "p3": { - DefaultAllow: true, - }, - }, - }, - "preserves default deny": { - defaultAllow: false, - workloadPorts: map[string]*pbcatalog.WorkloadPort{ - "p1": { - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - "p2": { - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - ctp: &pbauth.ComputedTrafficPermissions{ - AllowPermissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - IdentityName: "foo", - Partition: "default", - Namespace: "default", - }, - }, - DestinationRules: []*pbauth.DestinationRule{ - { - PortNames: []string{"p1"}, - }, - }, - }, - }, - }, - expected: map[string]*pbproxystate.TrafficPermissions{ - "p1": { - DefaultAllow: false, - AllowPermissions: []*pbproxystate.Permission{ - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: &pbproxystate.Spiffe{Regex: "^spiffe://test.consul/ap/default/ns/default/identity/foo$"}, - }, - }, - }, - }, - }, - "p2": { - DefaultAllow: false, - }, - }, - }, - "default allow with a non-empty ctp becomes default deny on all ports": { - defaultAllow: true, - workloadPorts: map[string]*pbcatalog.WorkloadPort{ - "p1": { - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - "p2": { - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - ctp: &pbauth.ComputedTrafficPermissions{ - AllowPermissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - IdentityName: "baz", - Partition: "default", - Namespace: "default", - }, - }, - DestinationRules: []*pbauth.DestinationRule{ - { - PortNames: []string{"no-match"}, - }, - }, - }, - }, - }, - expected: map[string]*pbproxystate.TrafficPermissions{ - "p1": { - DefaultAllow: false, - }, - "p2": { - DefaultAllow: false, - }, - }, - }, - "kitchen sink": { - defaultAllow: true, - workloadPorts: map[string]*pbcatalog.WorkloadPort{ - "p1": { - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - "p2": { - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - ctp: &pbauth.ComputedTrafficPermissions{ - AllowPermissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - IdentityName: "foo", - Partition: "default", - Namespace: "default", - }, - { - IdentityName: "", - Partition: "default", - Namespace: "default", - Exclude: []*pbauth.ExcludeSource{ - { - IdentityName: "bar", - Namespace: "default", - Partition: "default", - }, - }, - }, - }, - DestinationRules: []*pbauth.DestinationRule{ - // This should be p2. - { - Exclude: []*pbauth.ExcludePermissionRule{ - { - PortNames: []string{"p1"}, - }, - }, - }, - }, - }, - { - Sources: []*pbauth.Source{ - { - IdentityName: "baz", - Partition: "default", - Namespace: "default", - }, - }, - DestinationRules: []*pbauth.DestinationRule{ - { - PortNames: []string{"p1"}, - }, - }, - }, - }, - DenyPermissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - IdentityName: "qux", - Partition: "default", - Namespace: "default", - }, - }, - }, - { - Sources: []*pbauth.Source{ - { - IdentityName: "", - Namespace: "default", - Partition: "default", - Exclude: []*pbauth.ExcludeSource{ - { - IdentityName: "quux", - Partition: "default", - Namespace: "default", - }, - }, - }, - }, - }, - }, - }, - expected: map[string]*pbproxystate.TrafficPermissions{ - "p1": { - DefaultAllow: false, - DenyPermissions: []*pbproxystate.Permission{ - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: &pbproxystate.Spiffe{Regex: "^spiffe://test.consul/ap/default/ns/default/identity/qux$"}, - }, - }, - }, - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: &pbproxystate.Spiffe{Regex: `^spiffe://test.consul/ap/default/ns/default/identity/[^/]+$`}, - ExcludeSpiffes: []*pbproxystate.Spiffe{ - {Regex: "^spiffe://test.consul/ap/default/ns/default/identity/quux$"}, - }, - }, - }, - }, - }, - AllowPermissions: []*pbproxystate.Permission{ - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: &pbproxystate.Spiffe{Regex: "^spiffe://test.consul/ap/default/ns/default/identity/baz$"}, - }, - }, - }, - }, - }, - "p2": { - DefaultAllow: false, - DenyPermissions: []*pbproxystate.Permission{ - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: &pbproxystate.Spiffe{Regex: "^spiffe://test.consul/ap/default/ns/default/identity/qux$"}, - }, - }, - }, - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: &pbproxystate.Spiffe{Regex: `^spiffe://test.consul/ap/default/ns/default/identity/[^/]+$`}, - ExcludeSpiffes: []*pbproxystate.Spiffe{ - {Regex: "^spiffe://test.consul/ap/default/ns/default/identity/quux$"}, - }, - }, - }, - }, - }, - AllowPermissions: []*pbproxystate.Permission{ - { - Principals: []*pbproxystate.Principal{ - { - Spiffe: &pbproxystate.Spiffe{Regex: "^spiffe://test.consul/ap/default/ns/default/identity/foo$"}, - }, - { - Spiffe: &pbproxystate.Spiffe{Regex: `^spiffe://test.consul/ap/default/ns/default/identity/[^/]+$`}, - ExcludeSpiffes: []*pbproxystate.Spiffe{ - {Regex: "^spiffe://test.consul/ap/default/ns/default/identity/bar$"}, - }, - }, - }, - }, - }, - }, - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - workload := &pbcatalog.Workload{ - Ports: tc.workloadPorts, - } - permissions := buildTrafficPermissions(tc.defaultAllow, testTrustDomain, workload, tc.ctp) - require.Equal(t, len(tc.expected), len(permissions)) - for k, v := range tc.expected { - prototest.AssertDeepEqual(t, v, permissions[k]) - } - }) - } -} - -func testProxyStateTemplateID() *pbresource.ID { - return resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test"). - WithTenancy(resource.DefaultNamespacedTenancy()). - ID() -} - -func testIdentityRef() *pbresource.Reference { - return &pbresource.Reference{ - Name: "test-identity", - Tenancy: &pbresource.Tenancy{ - Namespace: "default", - Partition: "default", - PeerName: "local", - }, - Type: pbauth.WorkloadIdentityType, - } -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/naming.go b/internal/mesh/internal/controllers/sidecarproxy/builder/naming.go deleted file mode 100644 index 13a21e4e597d..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/naming.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "fmt" - - "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func DestinationSNI(serviceRef *pbresource.Reference, datacenter, trustDomain string) string { - return connect.ServiceSNI(serviceRef.Name, - "", - serviceRef.Tenancy.Namespace, - serviceRef.Tenancy.Partition, - datacenter, - trustDomain) -} - -func DestinationStatPrefix(serviceRef *pbresource.Reference, portName, datacenter string) string { - return fmt.Sprintf("upstream.%s.%s.%s.%s.%s", - portName, - serviceRef.Name, - serviceRef.Tenancy.Namespace, - serviceRef.Tenancy.Partition, - datacenter) -} - -func DestinationListenerName(destinationRef *pbresource.Reference, portName string, address string, port uint32) string { - name := fmt.Sprintf("%s:%s", DestinationResourceID(destinationRef, portName), address) - if port != 0 { - return fmt.Sprintf("%s:%d", name, port) - } - - return name -} - -// DestinationResourceID returns a string representation that uniquely identifies the -// upstream in a canonical but human readable way. -func DestinationResourceID(destinationRef *pbresource.Reference, port string) string { - tenancyPrefix := fmt.Sprintf("%s/%s/%s", destinationRef.Tenancy.Partition, - destinationRef.Tenancy.PeerName, destinationRef.Tenancy.Namespace) - return fmt.Sprintf("%s/%s:%s", tenancyPrefix, destinationRef.Name, port) -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/routes.go b/internal/mesh/internal/controllers/sidecarproxy/builder/routes.go deleted file mode 100644 index 03d68bdf081a..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/routes.go +++ /dev/null @@ -1,595 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package builder - -import ( - "fmt" - "strings" - "time" - - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" - - "github.com/hashicorp/consul/internal/mesh/internal/types" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" -) - -func (b *Builder) backendTargetToClusterName( - backendTarget string, - targets map[string]*pbmesh.BackendTargetDetails, - defaultDC func(string) string, -) string { - if backendTarget == types.NullRouteBackend { - return NullRouteClusterName - } - - details, ok := targets[backendTarget] - if !ok { - panic("dangling reference") - } - - backendRef := details.BackendRef - - dc := defaultDC(backendRef.Datacenter) - - sni := DestinationSNI( - details.BackendRef.Ref, - dc, - b.trustDomain, - ) - - return fmt.Sprintf("%s.%s", details.BackendRef.Port, sni) -} - -func (b *Builder) makeHTTPRouteDestination( - computedBackendRefs []*pbmesh.ComputedHTTPBackendRef, - destConfig *pbproxystate.DestinationConfiguration, - targets map[string]*pbmesh.BackendTargetDetails, - defaultDC func(string) string, -) *pbproxystate.RouteDestination { - switch len(computedBackendRefs) { - case 0: - panic("not possible to have a route rule with no backend refs") - case 1: - return b.makeRouteDestinationForDirect(computedBackendRefs[0].BackendTarget, destConfig, targets, defaultDC) - default: - clusters := make([]*pbproxystate.L7WeightedDestinationCluster, 0, len(computedBackendRefs)) - for _, computedBackendRef := range computedBackendRefs { - clusterName := b.backendTargetToClusterName(computedBackendRef.BackendTarget, targets, defaultDC) - - clusters = append(clusters, &pbproxystate.L7WeightedDestinationCluster{ - Name: clusterName, - Weight: &wrapperspb.UInt32Value{ - Value: computedBackendRef.Weight, - }, - }) - } - return b.makeRouteDestinationForSplit(clusters, destConfig) - } -} - -func (b *Builder) makeGRPCRouteDestination( - computedBackendRefs []*pbmesh.ComputedGRPCBackendRef, - destConfig *pbproxystate.DestinationConfiguration, - targets map[string]*pbmesh.BackendTargetDetails, - defaultDC func(string) string, -) *pbproxystate.RouteDestination { - switch len(computedBackendRefs) { - case 0: - panic("not possible to have a route rule with no backend refs") - case 1: - return b.makeRouteDestinationForDirect(computedBackendRefs[0].BackendTarget, destConfig, targets, defaultDC) - default: - clusters := make([]*pbproxystate.L7WeightedDestinationCluster, 0, len(computedBackendRefs)) - for _, computedBackendRef := range computedBackendRefs { - clusterName := b.backendTargetToClusterName(computedBackendRef.BackendTarget, targets, defaultDC) - - clusters = append(clusters, &pbproxystate.L7WeightedDestinationCluster{ - Name: clusterName, - Weight: &wrapperspb.UInt32Value{ - Value: computedBackendRef.Weight, - }, - }) - } - return b.makeRouteDestinationForSplit(clusters, destConfig) - } -} - -func (b *Builder) makeRouteDestinationForDirect( - backendTarget string, - destConfig *pbproxystate.DestinationConfiguration, - targets map[string]*pbmesh.BackendTargetDetails, - defaultDC func(string) string, -) *pbproxystate.RouteDestination { - clusterName := b.backendTargetToClusterName(backendTarget, targets, defaultDC) - - return &pbproxystate.RouteDestination{ - Destination: &pbproxystate.RouteDestination_Cluster{ - Cluster: &pbproxystate.DestinationCluster{ - Name: clusterName, - }, - }, - DestinationConfiguration: destConfig, - } -} - -func (b *Builder) makeRouteDestinationForSplit( - clusters []*pbproxystate.L7WeightedDestinationCluster, - destConfig *pbproxystate.DestinationConfiguration, -) *pbproxystate.RouteDestination { - return &pbproxystate.RouteDestination{ - Destination: &pbproxystate.RouteDestination_WeightedClusters{ - WeightedClusters: &pbproxystate.L7WeightedClusterGroup{ - Clusters: clusters, - }, - }, - DestinationConfiguration: destConfig, - } -} - -func (b *Builder) makeDestinationConfiguration( - timeouts *pbmesh.HTTPRouteTimeouts, - retries *pbmesh.HTTPRouteRetries, -) *pbproxystate.DestinationConfiguration { - cfg := &pbproxystate.DestinationConfiguration{ - TimeoutConfig: translateTimeouts(timeouts), - RetryPolicy: translateRetries(retries), - } - if cfg.TimeoutConfig == nil && cfg.RetryPolicy == nil { - return nil - } - - return cfg -} - -func applyRouteFilters[V interface { - GetRequestHeaderModifier() *pbmesh.HTTPHeaderFilter - GetResponseHeaderModifier() *pbmesh.HTTPHeaderFilter - GetUrlRewrite() *pbmesh.HTTPURLRewriteFilter -}]( - psDestConfig *pbproxystate.DestinationConfiguration, - filters []V, -) []*pbproxystate.HeaderMutation { - var headerMutations []*pbproxystate.HeaderMutation - for _, filter := range filters { - switch { - case filter.GetRequestHeaderModifier() != nil: - mod := filter.GetRequestHeaderModifier() - - for _, hdr := range mod.Set { - headerMutations = append(headerMutations, &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_RequestHeaderAdd{ - RequestHeaderAdd: &pbproxystate.RequestHeaderAdd{ - Header: &pbproxystate.Header{ - Key: hdr.Name, - Value: hdr.Value, - }, - AppendAction: pbproxystate.AppendAction_APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD, - }, - }, - }) - } - for _, hdr := range mod.Add { - headerMutations = append(headerMutations, &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_RequestHeaderAdd{ - RequestHeaderAdd: &pbproxystate.RequestHeaderAdd{ - Header: &pbproxystate.Header{ - Key: hdr.Name, - Value: hdr.Value, - }, - AppendAction: pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD, - }, - }, - }) - } - - if len(mod.Remove) > 0 { - headerMutations = append(headerMutations, &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_RequestHeaderRemove{ - RequestHeaderRemove: &pbproxystate.RequestHeaderRemove{ - HeaderKeys: mod.Remove, - }, - }, - }) - } - - case filter.GetResponseHeaderModifier() != nil: - mod := filter.GetResponseHeaderModifier() - - for _, hdr := range mod.Set { - headerMutations = append(headerMutations, &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_ResponseHeaderAdd{ - ResponseHeaderAdd: &pbproxystate.ResponseHeaderAdd{ - Header: &pbproxystate.Header{ - Key: hdr.Name, - Value: hdr.Value, - }, - AppendAction: pbproxystate.AppendAction_APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD, - }, - }, - }) - } - for _, hdr := range mod.Add { - headerMutations = append(headerMutations, &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_ResponseHeaderAdd{ - ResponseHeaderAdd: &pbproxystate.ResponseHeaderAdd{ - Header: &pbproxystate.Header{ - Key: hdr.Name, - Value: hdr.Value, - }, - AppendAction: pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD, - }, - }, - }) - } - - if len(mod.Remove) > 0 { - headerMutations = append(headerMutations, &pbproxystate.HeaderMutation{ - Action: &pbproxystate.HeaderMutation_ResponseHeaderRemove{ - ResponseHeaderRemove: &pbproxystate.ResponseHeaderRemove{ - HeaderKeys: mod.Remove, - }, - }, - }) - } - - case filter.GetUrlRewrite() != nil: - prefix := filter.GetUrlRewrite().PathPrefix - if prefix != "" { - psDestConfig.PrefixRewrite = prefix - } - } - } - return headerMutations -} - -func applyLoadBalancerPolicy[V interface { - GetBackendTarget() string -}]( - psDestConfig *pbproxystate.DestinationConfiguration, - cpr *pbmesh.ComputedPortRoutes, - backendRefs []V, -) { - var lb *pbmesh.LoadBalancer - - // If there are multiple targets, just pick the lb policy from - // the first one configured. - for _, backendRef := range backendRefs { - if backendRef.GetBackendTarget() == types.NullRouteBackend { - continue - } - details, ok := cpr.Targets[backendRef.GetBackendTarget()] - if !ok { - continue - } - thisLB := details.DestinationConfig.LoadBalancer - if thisLB != nil { - lb = thisLB - break - } - } - - if lb == nil { - return - } - - for _, policy := range lb.HashPolicies { - if policy.SourceIp { - psDestConfig.HashPolicies = append(psDestConfig.HashPolicies, &pbproxystate.LoadBalancerHashPolicy{ - Policy: &pbproxystate.LoadBalancerHashPolicy_ConnectionProperties{ - ConnectionProperties: &pbproxystate.ConnectionPropertiesPolicy{ - SourceIp: true, - Terminal: policy.Terminal, - }, - }, - }) - - continue - } - - // enumcover:pbmesh.HashPolicyField - switch policy.Field { - case pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER: - psDestConfig.HashPolicies = append(psDestConfig.HashPolicies, &pbproxystate.LoadBalancerHashPolicy{ - Policy: &pbproxystate.LoadBalancerHashPolicy_Header{ - Header: &pbproxystate.HeaderPolicy{ - Name: policy.FieldValue, - Terminal: policy.Terminal, - }, - }, - }) - case pbmesh.HashPolicyField_HASH_POLICY_FIELD_COOKIE: - cookie := &pbproxystate.CookiePolicy{ - Name: policy.FieldValue, - Terminal: policy.Terminal, - } - if policy.CookieConfig != nil { - cookie.Path = policy.CookieConfig.Path - - if policy.CookieConfig.Ttl != nil { - if policy.CookieConfig.Ttl.AsDuration() != 0 { - cookie.Ttl = policy.CookieConfig.Ttl - } - } - - // Envoy will generate a session cookie if the ttl is present and zero. - if policy.CookieConfig.Session { - cookie.Ttl = durationpb.New(0 * time.Second) - } - } - - psDestConfig.HashPolicies = append(psDestConfig.HashPolicies, &pbproxystate.LoadBalancerHashPolicy{ - Policy: &pbproxystate.LoadBalancerHashPolicy_Cookie{ - Cookie: cookie, - }, - }) - case pbmesh.HashPolicyField_HASH_POLICY_FIELD_QUERY_PARAMETER: - psDestConfig.HashPolicies = append(psDestConfig.HashPolicies, &pbproxystate.LoadBalancerHashPolicy{ - Policy: &pbproxystate.LoadBalancerHashPolicy_QueryParameter{ - QueryParameter: &pbproxystate.QueryParameterPolicy{ - Name: policy.FieldValue, - Terminal: policy.Terminal, - }, - }, - }) - case pbmesh.HashPolicyField_HASH_POLICY_FIELD_UNSPECIFIED: - // fallthrough to default - default: - // not possible from validation - } - } -} - -func makeHTTPRouteMatch(match *pbmesh.HTTPRouteMatch) *pbproxystate.RouteMatch { - em := &pbproxystate.RouteMatch{} - - if match.Path != nil { - // enumcover:pbmesh.PathMatchType - switch match.Path.Type { - case pbmesh.PathMatchType_PATH_MATCH_TYPE_EXACT: - em.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Exact{ - Exact: match.Path.Value, - }, - } - case pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX: - em.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: match.Path.Value, - }, - } - case pbmesh.PathMatchType_PATH_MATCH_TYPE_REGEX: - em.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Regex{ - Regex: match.Path.Value, - }, - } - case pbmesh.PathMatchType_PATH_MATCH_TYPE_UNSPECIFIED: - fallthrough // to default - default: - panic(fmt.Sprintf("unknown path match type: %v", match.Path.Type)) - } - } else { - em.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: "/", - }, - } - } - - em.HeaderMatches = translateHeaderMatches(match.Headers, (*pbmesh.HTTPHeaderMatch).GetInvert) - - if match.Method != "" { - em.MethodMatches = []string{match.Method} - } - - if len(match.QueryParams) > 0 { - em.QueryParameterMatches = make([]*pbproxystate.QueryParameterMatch, 0, len(match.QueryParams)) - for _, qm := range match.QueryParams { - eq := &pbproxystate.QueryParameterMatch{ - Name: qm.Name, - } - - // *QueryParameterMatch_Exact - // enumcover:pbmesh.QueryParamMatchType - switch qm.Type { - case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT: - eq.Match = &pbproxystate.QueryParameterMatch_Exact{ - Exact: qm.Value, - } - case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_REGEX: - eq.Match = &pbproxystate.QueryParameterMatch_Regex{ - Regex: qm.Value, - } - case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_PRESENT: - eq.Match = &pbproxystate.QueryParameterMatch_Present{ - Present: true, - } - case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_UNSPECIFIED: - fallthrough // to default - default: - panic(fmt.Sprintf("unknown query param match type: %v", qm.Type)) - } - - em.QueryParameterMatches = append(em.QueryParameterMatches, eq) - } - } - - return em -} - -func makeGRPCRouteMatch(match *pbmesh.GRPCRouteMatch) *pbproxystate.RouteMatch { - em := &pbproxystate.RouteMatch{} - - if match.Method != nil { - mm := match.Method - switch mm.Type { - case pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT: - switch { - case mm.Method == "": - em.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: fmt.Sprintf("/%s/", mm.Service), - }, - } - case mm.Service == "": - em.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Regex{ - Regex: fmt.Sprintf("/[^/]+/%s", mm.Method), - }, - } - default: - em.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Exact{ - Exact: fmt.Sprintf("/%s/%s", mm.Service, mm.Method), - }, - } - } - case pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_REGEX: - switch { - case mm.Method == "": - em.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Regex{ - Regex: fmt.Sprintf("/%s/.+", mm.Service), - }, - } - case mm.Service == "": - em.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Regex{ - Regex: fmt.Sprintf("/[^/]+/%s", mm.Method), - }, - } - default: - em.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Regex{ - Regex: fmt.Sprintf("/%s/%s", mm.Service, mm.Method), - }, - } - } - case pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_UNSPECIFIED: - fallthrough // to default - default: - panic(fmt.Sprintf("unknown method match type: %v", match.Method.Type)) - } - } else { - em.PathMatch = &pbproxystate.PathMatch{ - PathMatch: &pbproxystate.PathMatch_Prefix{ - Prefix: "/", - }, - } - } - - em.HeaderMatches = translateHeaderMatches(match.Headers, nil) - - return em -} - -func translateHeaderMatches[V interface { - GetType() pbmesh.HeaderMatchType - GetName() string - GetValue() string -}]( - headers []V, - getInvert func(v V) bool, -) []*pbproxystate.HeaderMatch { - if len(headers) == 0 { - return nil - } - var out []*pbproxystate.HeaderMatch - out = make([]*pbproxystate.HeaderMatch, 0, len(headers)) - for _, hdr := range headers { - eh := &pbproxystate.HeaderMatch{ - Name: hdr.GetName(), - } - - // enumcover:pbmesh.HeaderMatchType - switch hdr.GetType() { - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT: - eh.Match = &pbproxystate.HeaderMatch_Exact{ - Exact: hdr.GetValue(), - } - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_REGEX: - eh.Match = &pbproxystate.HeaderMatch_Regex{ - Regex: hdr.GetValue(), - } - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_PREFIX: - eh.Match = &pbproxystate.HeaderMatch_Prefix{ - Prefix: hdr.GetValue(), - } - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_SUFFIX: - eh.Match = &pbproxystate.HeaderMatch_Suffix{ - Suffix: hdr.GetValue(), - } - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_PRESENT: - eh.Match = &pbproxystate.HeaderMatch_Present{ - Present: true, - } - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_UNSPECIFIED: - fallthrough // to default - default: - panic(fmt.Sprintf("unknown header match type: %v", hdr.GetType())) - } - - // HTTPHeaderMatch only - if getInvert != nil && getInvert(hdr) { - eh.InvertMatch = true - } - - out = append(out, eh) - } - return out -} - -func translateTimeouts(timeouts *pbmesh.HTTPRouteTimeouts) *pbproxystate.TimeoutConfig { - if timeouts == nil || (timeouts.Request == nil && timeouts.Idle == nil) { - return nil - } - - return &pbproxystate.TimeoutConfig{ - Timeout: timeouts.Request, - IdleTimeout: timeouts.Idle, - } -} - -func translateRetries(retries *pbmesh.HTTPRouteRetries) *pbproxystate.RetryPolicy { - if retries == nil { - return nil - } - - retryPolicy := &pbproxystate.RetryPolicy{} - if retries.Number != nil { - retryPolicy.NumRetries = retries.Number - } - - // The RetryOn magic values come from: https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/http_filters/router_filter#config-http-filters-router-x-envoy-retry-on - var retryStrings []string - - if len(retries.OnConditions) > 0 { - retryStrings = append(retryStrings, retries.OnConditions...) - } - - if retries.OnConnectFailure { - // connect-failure can be enabled by either adding connect-failure to the RetryOn list or by using the legacy RetryOnConnectFailure option - // Check that it's not already in the RetryOn list, so we don't set it twice - connectFailureExists := false - for _, r := range retryStrings { - if r == "connect-failure" { - connectFailureExists = true - } - } - if !connectFailureExists { - retryStrings = append(retryStrings, "connect-failure") - } - } - - if len(retries.OnStatusCodes) > 0 { - retryStrings = append(retryStrings, "retriable-status-codes") - retryPolicy.RetriableStatusCodes = retries.OnStatusCodes - } - - retryPolicy.RetryOn = strings.Join(retryStrings, ",") - - return retryPolicy -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden deleted file mode 100644 index 098beac1af9b..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden +++ /dev/null @@ -1,194 +0,0 @@ -{ - "proxyState": { - "clusters": { - "original-destination": { - "endpointGroup": { - "passthrough": { - "config": { - "connectTimeout": "5s" - } - } - }, - "name": "original-destination", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 1234 - }, - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-1.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-1.default.default.dc1" - } - } - ] - }, - { - "capabilities": [ - "CAPABILITY_TRANSPARENT" - ], - "defaultRouter": { - "l4": { - "cluster": { - "name": "original-destination" - }, - "statPrefix": "upstream.original-destination" - } - }, - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 - }, - "name": "outbound_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-2.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - } - } - ] - } - ] - }, - "requiredEndpoints": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "id": { - "name": "api-1", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "id": { - "name": "api-2", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multi-destination.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multi-destination.golden deleted file mode 100644 index 1f925e4b5a2b..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multi-destination.golden +++ /dev/null @@ -1,320 +0,0 @@ -{ - "proxyState": { - "clusters": { - "null_route_cluster": { - "endpointGroup": { - "static": { - "config": { - "connectTimeout": "10s" - } - } - }, - "name": "null_route_cluster", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp2.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp2.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp2" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp2.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp2.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp2.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp2" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp2.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 1234 - }, - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "routers": [ - { - "l4": { - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - } - } - ] - }, - { - "direction": "DIRECTION_OUTBOUND", - "name": "default/local/default/api-2:tcp:/path/to/socket", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-2.default.default.dc1" - } - } - ], - "unixSocket": { - "mode": "0666", - "path": "/path/to/socket" - } - }, - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 2345 - }, - "name": "default/local/default/api-1:tcp2:1.1.1.1:2345", - "routers": [ - { - "l4": { - "statPrefix": "upstream.tcp2.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp2.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp2.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - } - } - ] - }, - { - "direction": "DIRECTION_OUTBOUND", - "name": "default/local/default/api-2:tcp2:/path/to/socket", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp2.api-2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp2.api-2.default.default.dc1" - } - } - ], - "unixSocket": { - "mode": "0666", - "path": "/path/to/socket" - } - } - ] - }, - "requiredEndpoints": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "id": { - "name": "api-1", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "id": { - "name": "api-2", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp2.api-1.default.dc1.internal.foo.consul": { - "id": { - "name": "api-1", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp2.api-2.default.dc1.internal.foo.consul": { - "id": { - "name": "api-2", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden deleted file mode 100644 index e00c9d08e010..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden +++ /dev/null @@ -1,193 +0,0 @@ -{ - "proxyState": { - "clusters": { - "original-destination": { - "endpointGroup": { - "passthrough": { - "config": { - "connectTimeout": "5s" - } - } - }, - "name": "original-destination", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_TRANSPARENT" - ], - "defaultRouter": { - "l4": { - "cluster": { - "name": "original-destination" - }, - "statPrefix": "upstream.original-destination" - } - }, - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 - }, - "name": "outbound_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-1.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-1.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l4": { - "cluster": { - "name": "tcp.api-2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-2.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - } - } - ] - } - ] - }, - "requiredEndpoints": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "id": { - "name": "api-1", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "id": { - "name": "api-2", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-ip-port-bind-address.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-ip-port-bind-address.golden deleted file mode 100644 index ae2d99c94261..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-ip-port-bind-address.golden +++ /dev/null @@ -1,165 +0,0 @@ -{ - "proxyState": { - "clusters": { - "null_route_cluster": { - "endpointGroup": { - "static": { - "config": { - "connectTimeout": "10s" - } - } - }, - "name": "null_route_cluster", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 1234 - }, - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "routers": [ - { - "l4": { - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - } - } - ] - } - ] - }, - "requiredEndpoints": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "id": { - "name": "api-1", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "id": { - "name": "api-2", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-unix-socket-bind-address.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-unix-socket-bind-address.golden deleted file mode 100644 index 2af48e9f29e3..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-destination-unix-socket-bind-address.golden +++ /dev/null @@ -1,97 +0,0 @@ -{ - "proxyState": { - "clusters": { - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "direction": "DIRECTION_OUTBOUND", - "name": "default/local/default/api-2:tcp:/path/to/socket", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-2.default.default.dc1" - } - } - ], - "unixSocket": { - "mode": "0666", - "path": "/path/to/socket" - } - } - ] - }, - "requiredEndpoints": { - "tcp.api-2.default.dc1.internal.foo.consul": { - "id": { - "name": "api-2", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-implicit-destination-tproxy.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-implicit-destination-tproxy.golden deleted file mode 100644 index 50e871481174..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/l4-single-implicit-destination-tproxy.golden +++ /dev/null @@ -1,128 +0,0 @@ -{ - "proxyState": { - "clusters": { - "original-destination": { - "endpointGroup": { - "passthrough": { - "config": { - "connectTimeout": "5s" - } - } - }, - "name": "original-destination", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_TRANSPARENT" - ], - "defaultRouter": { - "l4": { - "cluster": { - "name": "original-destination" - }, - "statPrefix": "upstream.original-destination" - } - }, - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 - }, - "name": "outbound_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-1.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-1.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - } - ] - } - ] - }, - "requiredEndpoints": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "id": { - "name": "api-1", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/mixed-multi-destination.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/mixed-multi-destination.golden deleted file mode 100644 index cbd28e7a70a4..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/mixed-multi-destination.golden +++ /dev/null @@ -1,415 +0,0 @@ -{ - "proxyState": { - "clusters": { - "http.api-1.default.dc1.internal.foo.consul": { - "altStatName": "http.api-1.default.dc1.internal.foo.consul", - "failoverGroup": { - "config": { - "connectTimeout": "55s", - "useAltStatName": true - }, - "endpointGroups": [ - { - "dynamic": { - "config": { - "connectTimeout": "55s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - }, - "name": "failover-target~0~http.api-1.default.dc1.internal.foo.consul" - }, - { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "backup-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/backup1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - }, - "name": "failover-target~1~http.api-1.default.dc1.internal.foo.consul" - } - ] - }, - "name": "http.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_HTTP" - }, - "http.api-2.default.dc1.internal.foo.consul": { - "altStatName": "http.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "http.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_HTTP" - }, - "null_route_cluster": { - "endpointGroup": { - "static": { - "config": { - "connectTimeout": "10s" - } - } - }, - "name": "null_route_cluster", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 1234 - }, - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "routers": [ - { - "l4": { - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - } - } - ] - }, - { - "direction": "DIRECTION_OUTBOUND", - "name": "default/local/default/api-2:tcp:/path/to/socket", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-2.default.default.dc1" - } - } - ], - "unixSocket": { - "mode": "0666", - "path": "/path/to/socket" - } - }, - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 1234 - }, - "name": "default/local/default/api-1:http:1.1.1.1:1234", - "routers": [ - { - "l7": { - "route": { - "name": "default/local/default/api-1:http:1.1.1.1:1234" - }, - "statPrefix": "upstream.http.api-1.default.default.dc1" - } - } - ] - } - ], - "routes": { - "default/local/default/api-1:http:1.1.1.1:1234": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "default/local/default/api-1:http:1.1.1.1:1234", - "routeRules": [ - { - "destination": { - "destinationConfiguration": { - "timeoutConfig": { - "timeout": "77s" - } - }, - "weightedClusters": { - "clusters": [ - { - "name": "http.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "http.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - }, - "match": { - "pathMatch": { - "prefix": "/split" - } - } - }, - { - "destination": { - "cluster": { - "name": "http.api-1.default.dc1.internal.foo.consul" - }, - "destinationConfiguration": { - "retryPolicy": { - "numRetries": 4, - "retryOn": "connect-failure" - }, - "timeoutConfig": { - "timeout": "606s" - } - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - }, - { - "destination": { - "cluster": { - "name": "null_route_cluster" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - } - }, - "requiredEndpoints": { - "failover-target~1~http.api-1.default.dc1.internal.foo.consul": { - "id": { - "name": "backup-1", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "http.api-1.default.dc1.internal.foo.consul": { - "id": { - "name": "api-1", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "http.api-2.default.dc1.internal.foo.consul": { - "id": { - "name": "api-2", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "id": { - "name": "api-1", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "id": { - "name": "api-2", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden deleted file mode 100644 index 94e8e1c21577..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden +++ /dev/null @@ -1,495 +0,0 @@ -{ - "proxyState": { - "clusters": { - "http.api-app.default.dc1.internal.foo.consul": { - "altStatName": "http.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "http.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_HTTP" - }, - "http.api-app2.default.dc1.internal.foo.consul": { - "altStatName": "http.api-app2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "http.api-app2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_HTTP" - }, - "original-destination": { - "endpointGroup": { - "passthrough": { - "config": { - "connectTimeout": "5s" - } - } - }, - "name": "original-destination", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-app.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-app2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-app2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-app2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp2.api-app.default.dc1.internal.foo.consul": { - "altStatName": "tcp2.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp2" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp2.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp2.api-app2.default.dc1.internal.foo.consul": { - "altStatName": "tcp2.api-app2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp2" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp2.api-app2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_TRANSPARENT" - ], - "defaultRouter": { - "l4": { - "cluster": { - "name": "original-destination" - }, - "statPrefix": "upstream.original-destination" - } - }, - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 - }, - "name": "outbound_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-app.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l4": { - "cluster": { - "name": "tcp.api-app2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-app2.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - } - }, - { - "l7": { - "route": { - "name": "default/local/default/api-app:http" - }, - "statPrefix": "upstream.http.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 8080, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l7": { - "route": { - "name": "default/local/default/api-app2:http" - }, - "statPrefix": "upstream.http.api-app2.default.default.dc1" - }, - "match": { - "destinationPort": 8080, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - } - }, - { - "l4": { - "cluster": { - "name": "tcp2.api-app.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp2.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 8081, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l4": { - "cluster": { - "name": "tcp2.api-app2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp2.api-app2.default.default.dc1" - }, - "match": { - "destinationPort": 8081, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - } - } - ] - } - ], - "routes": { - "default/local/default/api-app2:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "default/local/default/api-app2:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "http.api-app2.default.dc1.internal.foo.consul" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "default/local/default/api-app:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "default/local/default/api-app:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "http.api-app.default.dc1.internal.foo.consul" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - } - }, - "requiredEndpoints": { - "http.api-app.default.dc1.internal.foo.consul": { - "id": { - "name": "api-app", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "http.api-app2.default.dc1.internal.foo.consul": { - "id": { - "name": "api-app2", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp.api-app.default.dc1.internal.foo.consul": { - "id": { - "name": "api-app", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp.api-app2.default.dc1.internal.foo.consul": { - "id": { - "name": "api-app2", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp2.api-app.default.dc1.internal.foo.consul": { - "id": { - "name": "api-app", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp2.api-app2.default.dc1.internal.foo.consul": { - "id": { - "name": "api-app2", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden deleted file mode 100644 index 479a4e7aefd2..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden +++ /dev/null @@ -1,276 +0,0 @@ -{ - "proxyState": { - "clusters": { - "http.api-app.default.dc1.internal.foo.consul": { - "altStatName": "http.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "http.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_HTTP" - }, - "original-destination": { - "endpointGroup": { - "passthrough": { - "config": { - "connectTimeout": "5s" - } - } - }, - "name": "original-destination", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-app.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp2.api-app.default.dc1.internal.foo.consul": { - "altStatName": "tcp2.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp2" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp2.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_TRANSPARENT" - ], - "defaultRouter": { - "l4": { - "cluster": { - "name": "original-destination" - }, - "statPrefix": "upstream.original-destination" - } - }, - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 - }, - "name": "outbound_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-app.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l7": { - "route": { - "name": "default/local/default/api-app:http" - }, - "statPrefix": "upstream.http.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 8080, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l4": { - "cluster": { - "name": "tcp2.api-app.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp2.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 8081, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - } - ] - } - ], - "routes": { - "default/local/default/api-app:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "default/local/default/api-app:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "http.api-app.default.dc1.internal.foo.consul" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - } - }, - "requiredEndpoints": { - "http.api-app.default.dc1.internal.foo.consul": { - "id": { - "name": "api-app", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp.api-app.default.dc1.internal.foo.consul": { - "id": { - "name": "api-app", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp2.api-app.default.dc1.internal.foo.consul": { - "id": { - "name": "api-app", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden deleted file mode 100644 index 479a4e7aefd2..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden +++ /dev/null @@ -1,276 +0,0 @@ -{ - "proxyState": { - "clusters": { - "http.api-app.default.dc1.internal.foo.consul": { - "altStatName": "http.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "http.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_HTTP" - }, - "original-destination": { - "endpointGroup": { - "passthrough": { - "config": { - "connectTimeout": "5s" - } - } - }, - "name": "original-destination", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-app.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp2.api-app.default.dc1.internal.foo.consul": { - "altStatName": "tcp2.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp2" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp2.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_TRANSPARENT" - ], - "defaultRouter": { - "l4": { - "cluster": { - "name": "original-destination" - }, - "statPrefix": "upstream.original-destination" - } - }, - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 - }, - "name": "outbound_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-app.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l7": { - "route": { - "name": "default/local/default/api-app:http" - }, - "statPrefix": "upstream.http.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 8080, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l4": { - "cluster": { - "name": "tcp2.api-app.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp2.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 8081, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - } - ] - } - ], - "routes": { - "default/local/default/api-app:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "default/local/default/api-app:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "http.api-app.default.dc1.internal.foo.consul" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - } - }, - "requiredEndpoints": { - "http.api-app.default.dc1.internal.foo.consul": { - "id": { - "name": "api-app", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp.api-app.default.dc1.internal.foo.consul": { - "id": { - "name": "api-app", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - }, - "tcp2.api-app.default.dc1.internal.foo.consul": { - "id": { - "name": "api-app", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "catalog", - "groupVersion": "v2beta1", - "kind": "ServiceEndpoints" - } - }, - "port": "mesh" - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l7-expose-paths.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l7-expose-paths.golden deleted file mode 100644 index 2af5ce9c06d4..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/l7-expose-paths.golden +++ /dev/null @@ -1,212 +0,0 @@ -{ - "proxyState": { - "clusters": { - "exposed_cluster_9090": { - "endpointGroup": { - "static": {} - }, - "name": "exposed_cluster_9090", - "protocol": "PROTOCOL_HTTP" - }, - "exposed_cluster_9091": { - "endpointGroup": { - "static": {} - }, - "name": "exposed_cluster_9091", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:port1": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:port1", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "exposed_cluster_9090": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - }, - "exposed_cluster_9091": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9091 - } - } - ] - }, - "local_app:port1": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:port1" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~port1" - ] - } - } - ] - }, - { - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 1234 - }, - "name": "exposed_path_health1234", - "routers": [ - { - "l7": { - "route": { - "name": "exposed_path_route_health1234" - }, - "statPrefix": "exposed_path_route_health1234", - "staticRoute": true - } - } - ] - }, - { - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 1235 - }, - "name": "exposed_path_GetHealth1235", - "routers": [ - { - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "exposed_path_route_GetHealth1235" - }, - "statPrefix": "exposed_path_route_GetHealth1235", - "staticRoute": true - } - } - ] - } - ], - "routes": { - "exposed_path_route_GetHealth1235": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "exposed_path_route_GetHealth1235", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "exposed_cluster_9091" - } - }, - "match": { - "pathMatch": { - "exact": "GetHealth" - } - } - } - ] - } - ] - }, - "exposed_path_route_health1234": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "exposed_path_route_health1234", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "exposed_cluster_9090" - } - }, - "match": { - "pathMatch": { - "exact": "/health" - } - } - } - ] - } - ] - } - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/local-and-inbound-connections.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/local-and-inbound-connections.golden deleted file mode 100644 index 299b051ef69d..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/local-and-inbound-connections.golden +++ /dev/null @@ -1,304 +0,0 @@ -{ - "proxyState": { - "clusters": { - "exposed_cluster_9090": { - "endpointGroup": { - "static": {} - }, - "name": "exposed_cluster_9090", - "protocol": "PROTOCOL_HTTP" - }, - "exposed_cluster_9091": { - "endpointGroup": { - "static": {} - }, - "name": "exposed_cluster_9091", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:port1": { - "endpointGroup": { - "static": { - "config": { - "circuitBreakers": { - "upstreamLimits": { - "maxConnections": 123 - } - }, - "connectTimeout": "6s" - } - } - }, - "name": "local_app:port1", - "protocol": "PROTOCOL_TCP" - }, - "local_app:port3": { - "endpointGroup": { - "static": { - "config": { - "circuitBreakers": { - "upstreamLimits": { - "maxConnections": 123 - } - }, - "connectTimeout": "8s" - } - } - }, - "name": "local_app:port3", - "protocol": "PROTOCOL_HTTP" - } - }, - "endpoints": { - "exposed_cluster_9090": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - }, - "exposed_cluster_9091": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9091 - } - } - ] - }, - "local_app:port1": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:port3": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8081 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "balanceConnections": "BALANCE_CONNECTIONS_EXACT", - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:port1" - }, - "maxInboundConnections": "123", - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~port1" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "maxInboundConnections": "123", - "route": { - "name": "public_listener:port3" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~port3" - ] - } - } - ] - }, - { - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 1234 - }, - "name": "exposed_path_health1234", - "routers": [ - { - "l7": { - "route": { - "name": "exposed_path_route_health1234" - }, - "statPrefix": "exposed_path_route_health1234", - "staticRoute": true - } - } - ] - }, - { - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 1235 - }, - "name": "exposed_path_GetHealth1235", - "routers": [ - { - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "exposed_path_route_GetHealth1235" - }, - "statPrefix": "exposed_path_route_GetHealth1235", - "staticRoute": true - } - } - ] - } - ], - "routes": { - "exposed_path_route_GetHealth1235": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "exposed_path_route_GetHealth1235", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "exposed_cluster_9091" - } - }, - "match": { - "pathMatch": { - "exact": "GetHealth" - } - } - } - ] - } - ] - }, - "exposed_path_route_health1234": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "exposed_path_route_health1234", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "exposed_cluster_9090" - } - }, - "match": { - "pathMatch": { - "exact": "/health" - } - } - } - ] - } - ] - }, - "public_listener:port3": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:port3", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:port3" - }, - "destinationConfiguration": { - "timeoutConfig": { - "timeout": "9s" - } - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiple-workload-addresses-with-specific-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 70d0232467f1..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,291 +0,0 @@ -{ - "proxyState": { - "clusters": { - "local_app:grpc": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:grpc", - "protocol": "PROTOCOL_GRPC" - }, - "local_app:http": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:http", - "protocol": "PROTOCOL_HTTP" - }, - "local_app:http2": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:http2", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:tcp": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:tcp", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "local_app:grpc": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8083 - } - } - ] - }, - "local_app:http": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8081 - } - } - ] - }, - "local_app:http2": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8082 - } - } - ] - }, - "local_app:tcp": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_GRPC", - "route": { - "name": "public_listener:grpc" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~grpc" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "route": { - "name": "public_listener:http" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~http" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "public_listener:http2" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~http2" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:tcp" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~tcp" - ] - } - } - ] - } - ], - "routes": { - "public_listener:grpc": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:grpc", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:grpc" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:http" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:http2": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:http2", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:http2" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiple-workload-addresses-without-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiple-workload-addresses-without-ports.golden deleted file mode 100644 index b86daa281714..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,291 +0,0 @@ -{ - "proxyState": { - "clusters": { - "local_app:grpc": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:grpc", - "protocol": "PROTOCOL_GRPC" - }, - "local_app:http": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:http", - "protocol": "PROTOCOL_HTTP" - }, - "local_app:http2": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:http2", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:tcp": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:tcp", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "local_app:grpc": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8083 - } - } - ] - }, - "local_app:http": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8081 - } - } - ] - }, - "local_app:http2": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8082 - } - } - ] - }, - "local_app:tcp": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_GRPC", - "route": { - "name": "public_listener:grpc" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~grpc" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "route": { - "name": "public_listener:http" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~http" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "public_listener:http2" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~http2" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:tcp" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~tcp" - ] - } - } - ] - } - ], - "routes": { - "public_listener:grpc": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:grpc", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:grpc" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:http" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:http2": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:http2", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:http2" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index 93a69b2bb033..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,130 +0,0 @@ -{ - "proxyState": { - "clusters": { - "local_app:admin-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:admin-port", - "protocol": "PROTOCOL_TCP" - }, - "local_app:api-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:api-port", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.3", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:admin-port" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:api-port" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~api-port" - ] - } - } - ] - } - ] - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-without-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 3831349ccdbd..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,130 +0,0 @@ -{ - "proxyState": { - "clusters": { - "local_app:admin-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:admin-port", - "protocol": "PROTOCOL_TCP" - }, - "local_app:api-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:api-port", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:admin-port" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:api-port" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~api-port" - ] - } - } - ] - } - ] - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-single-workload-address-without-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-single-workload-address-without-ports.golden deleted file mode 100644 index 3831349ccdbd..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-single-workload-address-without-ports.golden +++ /dev/null @@ -1,130 +0,0 @@ -{ - "proxyState": { - "clusters": { - "local_app:admin-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:admin-port", - "protocol": "PROTOCOL_TCP" - }, - "local_app:api-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:api-port", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:admin-port" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:api-port" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~api-port" - ] - } - } - ] - } - ] - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-workload-with-only-mesh-port.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-workload-with-only-mesh-port.golden deleted file mode 100644 index dc9afc44fa43..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l4-workload-with-only-mesh-port.golden +++ /dev/null @@ -1,61 +0,0 @@ -{ - "proxyState": { - "clusters": { - "black-hole-cluster": { - "endpointGroup": { - "static": {} - }, - "name": "black-hole-cluster", - "protocol": "PROTOCOL_TCP" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "black-hole-cluster" - }, - "statPrefix": "public_listener" - } - } - ] - } - ] - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index dcba1dc58150..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,183 +0,0 @@ -{ - "proxyState": { - "clusters": { - "local_app:admin-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:admin-port", - "protocol": "PROTOCOL_HTTP" - }, - "local_app:api-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:api-port", - "protocol": "PROTOCOL_HTTP2" - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.3", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "route": { - "name": "public_listener:admin-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "public_listener:api-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~api-port" - ] - } - } - ] - } - ], - "routes": { - "public_listener:admin-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:admin-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:admin-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:api-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:api-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:api-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l7-multiple-workload-addresses-without-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l7-multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 08d9faa234ea..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l7-multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,250 +0,0 @@ -{ - "proxyState": { - "clusters": { - "local_app:admin-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:admin-port", - "protocol": "PROTOCOL_HTTP" - }, - "local_app:api-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:api-port", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:grpc-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:grpc-port", - "protocol": "PROTOCOL_GRPC" - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - }, - "local_app:grpc-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9091 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "route": { - "name": "public_listener:admin-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "public_listener:api-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~api-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_GRPC", - "route": { - "name": "public_listener:grpc-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~grpc-port" - ] - } - } - ] - } - ], - "routes": { - "public_listener:admin-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:admin-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:admin-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:api-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:api-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:api-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:grpc-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:grpc-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:grpc-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l7-single-workload-address-without-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l7-single-workload-address-without-ports.golden deleted file mode 100644 index 08d9faa234ea..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/multiport-l7-single-workload-address-without-ports.golden +++ /dev/null @@ -1,250 +0,0 @@ -{ - "proxyState": { - "clusters": { - "local_app:admin-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:admin-port", - "protocol": "PROTOCOL_HTTP" - }, - "local_app:api-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:api-port", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:grpc-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:grpc-port", - "protocol": "PROTOCOL_GRPC" - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - }, - "local_app:grpc-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9091 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "route": { - "name": "public_listener:admin-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "public_listener:api-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~api-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_GRPC", - "route": { - "name": "public_listener:grpc-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~grpc-port" - ] - } - } - ] - } - ], - "routes": { - "public_listener:admin-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:admin-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:admin-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:api-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:api-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:api-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:grpc-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:grpc-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:grpc-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/single-workload-address-without-ports.golden b/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/single-workload-address-without-ports.golden deleted file mode 100644 index b86daa281714..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/builder/testdata/source/single-workload-address-without-ports.golden +++ /dev/null @@ -1,291 +0,0 @@ -{ - "proxyState": { - "clusters": { - "local_app:grpc": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:grpc", - "protocol": "PROTOCOL_GRPC" - }, - "local_app:http": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:http", - "protocol": "PROTOCOL_HTTP" - }, - "local_app:http2": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:http2", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:tcp": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:tcp", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "local_app:grpc": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8083 - } - } - ] - }, - "local_app:http": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8081 - } - } - ] - }, - "local_app:http2": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8082 - } - } - ] - }, - "local_app:tcp": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_GRPC", - "route": { - "name": "public_listener:grpc" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~grpc" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "route": { - "name": "public_listener:http" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~http" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "public_listener:http2" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~http2" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:tcp" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~tcp" - ] - } - } - ] - } - ], - "routes": { - "public_listener:grpc": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:grpc", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:grpc" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:http" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:http2": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:http2", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:http2" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - } - }, - "requiredLeafCertificates": { - "test-identity": { - "name": "test-identity", - "namespace": "default", - "partition": "default" - } - }, - "requiredTrustBundles": { - "local": { - "peer": "local" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/sidecarproxy/cache/cache.go b/internal/mesh/internal/controllers/sidecarproxy/cache/cache.go deleted file mode 100644 index b2007d5b0d43..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/cache/cache.go +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package cache - -import ( - "context" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" - "github.com/hashicorp/consul/internal/resource/mappers/selectiontracker" - "github.com/hashicorp/consul/internal/storage" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type Cache struct { - // computedRoutes keeps track of computed routes IDs to service references it applies to. - computedRoutes *bimapper.Mapper - - // identities keeps track of which identity a workload is mapped to. - identities *bimapper.Mapper - - // computedDestinations keeps track of the computed explicit destinations IDs to service references that are - // referenced in that resource. - computedDestinations *bimapper.Mapper - - // serviceSelectorTracker keeps track of which workload selectors a service is currently using. - serviceSelectorTracker *selectiontracker.WorkloadSelectionTracker -} - -func New() *Cache { - return &Cache{ - computedRoutes: bimapper.New(pbmesh.ComputedRoutesType, pbcatalog.ServiceType), - identities: bimapper.New(pbcatalog.WorkloadType, pbauth.WorkloadIdentityType), - computedDestinations: bimapper.New(pbmesh.ComputedExplicitDestinationsType, pbcatalog.ServiceType), - serviceSelectorTracker: selectiontracker.New(), - } -} - -func (c *Cache) TrackComputedDestinations(computedDestinations *types.DecodedComputedDestinations) { - var serviceRefs []resource.ReferenceOrID - - for _, dest := range computedDestinations.Data.Destinations { - serviceRefs = append(serviceRefs, dest.DestinationRef) - } - - c.computedDestinations.TrackItem(computedDestinations.Resource.Id, serviceRefs) -} - -func (c *Cache) UntrackComputedDestinations(computedDestinationsID *pbresource.ID) { - c.computedDestinations.UntrackItem(computedDestinationsID) -} - -func (c *Cache) UntrackComputedRoutes(computedRoutesID *pbresource.ID) { - c.computedRoutes.UntrackItem(computedRoutesID) -} - -func (c *Cache) TrackWorkload(workload *types.DecodedWorkload) { - identityID := &pbresource.ID{ - Name: workload.GetData().Identity, - Tenancy: workload.GetResource().Id.Tenancy, - Type: pbauth.WorkloadIdentityType, - } - c.identities.TrackItem(workload.GetResource().GetId(), []resource.ReferenceOrID{identityID}) -} - -// UntrackWorkload removes tracking for the given workload ID. -func (c *Cache) UntrackWorkload(wID *pbresource.ID) { - c.identities.UntrackItem(wID) -} - -func (c *Cache) ComputedDestinationsByService(id resource.ReferenceOrID) []*pbresource.ID { - return c.computedDestinations.ItemIDsForLink(id) -} - -func (c *Cache) trackComputedRoutes(computedRoutes *types.DecodedComputedRoutes) { - var serviceRefs []resource.ReferenceOrID - - for _, pcr := range computedRoutes.Data.PortedConfigs { - for _, details := range pcr.Targets { - serviceRefs = append(serviceRefs, details.BackendRef.Ref) - } - } - - c.computedRoutes.TrackItem(computedRoutes.Resource.Id, serviceRefs) -} - -func (c *Cache) computedRoutesByService(id resource.ReferenceOrID) []*pbresource.ID { - return c.computedRoutes.ItemIDsForLink(id) -} - -func (c *Cache) WorkloadsByWorkloadIdentity(id *pbresource.ID) []*pbresource.ID { - return c.identities.ItemIDsForLink(id) -} - -func (c *Cache) ServicesForWorkload(id *pbresource.ID) []*pbresource.ID { - return c.serviceSelectorTracker.GetIDsForWorkload(id) -} - -func (c *Cache) UntrackService(id *pbresource.ID) { - c.serviceSelectorTracker.UntrackID(id) -} - -func (c *Cache) MapComputedRoutes(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - computedRoutes, err := resource.Decode[*pbmesh.ComputedRoutes](res) - if err != nil { - return nil, err - } - - ids, err := c.mapComputedRoutesToProxyStateTemplate(ctx, rt, res.Id) - if err != nil { - return nil, err - } - - c.trackComputedRoutes(computedRoutes) - - return controller.MakeRequests(pbmesh.ProxyStateTemplateType, ids), nil -} - -func (c *Cache) mapComputedRoutesToProxyStateTemplate(ctx context.Context, rt controller.Runtime, computedRoutesID *pbresource.ID) ([]*pbresource.ID, error) { - // Each Destination gets a single ComputedRoutes. - serviceID := resource.ReplaceType(pbcatalog.ServiceType, computedRoutesID) - serviceRef := resource.Reference(serviceID, "") - - return c.mapServiceThroughDestinations(ctx, rt, serviceRef) -} - -func (c *Cache) TrackService(svc *types.DecodedService) { - c.serviceSelectorTracker.TrackIDForSelector(svc.Resource.GetId(), svc.GetData().GetWorkloads()) -} - -func (c *Cache) MapService(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - // Record workload selector in the cache every time we see an event for a service. - decodedService, err := resource.Decode[*pbcatalog.Service](res) - if err != nil { - return nil, err - } - c.TrackService(decodedService) - - serviceRef := resource.Reference(res.Id, "") - - pstIDs, err := c.mapServiceThroughDestinations(ctx, rt, serviceRef) - if err != nil { - return nil, err - } - - // Now walk the mesh configuration information backwards because - // we need to find any PST that needs to DISCOVER endpoints for this - // service as a part of mesh configuration and traffic routing. - - // Find all ComputedRoutes that reference this service. - routeIDs := c.computedRoutesByService(serviceRef) - for _, routeID := range routeIDs { - // Find all Upstreams that reference a Service aligned with this ComputedRoutes. - // Afterwards, find all Workloads selected by the Upstreams, and align a PST with those. - ids, err := c.mapComputedRoutesToProxyStateTemplate(ctx, rt, routeID) - if err != nil { - return nil, err - } - - pstIDs = append(pstIDs, ids...) - } - - return controller.MakeRequests(pbmesh.ProxyStateTemplateType, pstIDs), nil -} - -// mapServiceThroughDestinations takes an explicit -// Service and traverses back through Destinations to Workloads to -// ProxyStateTemplates. -// -// This is in a separate function so it can be chained for more complicated -// relationships. -func (c *Cache) mapServiceThroughDestinations( - ctx context.Context, - rt controller.Runtime, - serviceRef *pbresource.Reference, -) ([]*pbresource.ID, error) { - - // The relationship is: - // - // - PST (replace type) Workload - // - Workload (name-aligned) ComputedDestinations - // - ComputedDestinations (contains) Service - // - // When we wake up for Service we should: - // - // - look up computed destinations for the service - // - rewrite computed destination types to PST - - var pstIDs []*pbresource.ID - - // Get all source proxies if they're referenced in any explicit destinations from computed destinations (name-aligned with workload/PST). - sources := c.ComputedDestinationsByService(serviceRef) - for _, cdID := range sources { - pstIDs = append(pstIDs, resource.ReplaceType(pbmesh.ProxyStateTemplateType, cdID)) - } - - // TODO(v2): remove this after we can do proper performant implicit upstream determination - // - // TODO(rb): shouldn't this instead list all Workloads that have a mesh port? - allIDs, err := c.listAllProxyStateTemplatesTemporarily(ctx, rt, serviceRef.Tenancy) - if err != nil { - return nil, err - } - - pstIDs = append(pstIDs, allIDs...) - - return pstIDs, nil -} - -func (c *Cache) listAllProxyStateTemplatesTemporarily(ctx context.Context, rt controller.Runtime, tenancy *pbresource.Tenancy) ([]*pbresource.ID, error) { - // todo (ishustava): this is a stub for now until we implement implicit destinations. - // For tproxy, we generate requests for all proxy states in the cluster. - // This will generate duplicate events for proxies already added above, - // however, we expect that the controller runtime will de-dup for us. - rsp, err := rt.Client.List(ctx, &pbresource.ListRequest{ - Type: pbmesh.ProxyStateTemplateType, - Tenancy: &pbresource.Tenancy{ - Namespace: storage.Wildcard, - Partition: tenancy.Partition, - PeerName: tenancy.PeerName, - }, - }) - if err != nil { - return nil, err - } - - result := make([]*pbresource.ID, 0, len(rsp.Resources)) - for _, r := range rsp.Resources { - result = append(result, r.Id) - } - return result, nil -} - -func (c *Cache) MapComputedTrafficPermissions(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - var ctp pbauth.ComputedTrafficPermissions - err := res.Data.UnmarshalTo(&ctp) - if err != nil { - return nil, err - } - - workloadIdentityID := resource.ReplaceType(pbauth.WorkloadIdentityType, res.Id) - ids := c.WorkloadsByWorkloadIdentity(workloadIdentityID) - - return controller.MakeRequests(pbmesh.ProxyStateTemplateType, ids), nil -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/cache/cache_test.go b/internal/mesh/internal/controllers/sidecarproxy/cache/cache_test.go deleted file mode 100644 index 2aa5484db498..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/cache/cache_test.go +++ /dev/null @@ -1,443 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package cache - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestIdentities(t *testing.T) { - cache := New() - - identityID1 := resourcetest.Resource(pbauth.WorkloadIdentityType, "workload-identity-1"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID() - identityID2 := resourcetest.Resource(pbauth.WorkloadIdentityType, "workload-identity-2"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID() - - w1 := resourcetest.Resource(pbcatalog.WorkloadType, "service-workload-1"). - WithData(t, &pbcatalog.Workload{ - Identity: identityID1.Name, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - decW1 := resourcetest.MustDecode[*pbcatalog.Workload](t, w1) - w2 := resourcetest.Resource(pbcatalog.WorkloadType, "service-workload-2"). - WithData(t, &pbcatalog.Workload{ - Identity: identityID2.Name, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - decW2 := resourcetest.MustDecode[*pbcatalog.Workload](t, w2) - - // Empty cache - require.Nil(t, cache.WorkloadsByWorkloadIdentity(identityID1)) - require.Nil(t, cache.WorkloadsByWorkloadIdentity(identityID2)) - - // Insert value and fetch it. - cache.TrackWorkload(decW1) - require.Equal(t, []*pbresource.ID{w1.Id}, cache.WorkloadsByWorkloadIdentity(identityID1)) - require.Nil(t, cache.WorkloadsByWorkloadIdentity(identityID2)) - - // Insert another value referencing the same identity. - decW2.GetData().Identity = identityID1.Name - cache.TrackWorkload(decW2) - require.ElementsMatch(t, []*pbresource.ID{w1.Id, w2.Id}, cache.WorkloadsByWorkloadIdentity(identityID1)) - require.Nil(t, cache.WorkloadsByWorkloadIdentity(identityID2)) - - // Now workload 1 uses identity 2 - decW1.GetData().Identity = identityID2.Name - cache.TrackWorkload(decW1) - require.Equal(t, []*pbresource.ID{w1.Id}, cache.WorkloadsByWorkloadIdentity(identityID2)) - require.Equal(t, []*pbresource.ID{w2.Id}, cache.WorkloadsByWorkloadIdentity(identityID1)) - - // Untrack workload 2 - cache.UntrackWorkload(w2.Id) - require.Equal(t, []*pbresource.ID{w1.Id}, cache.WorkloadsByWorkloadIdentity(identityID2)) - require.Nil(t, cache.WorkloadsByWorkloadIdentity(identityID1)) - - // Untrack workload 1 - cache.UntrackWorkload(w1.Id) - require.Nil(t, cache.WorkloadsByWorkloadIdentity(identityID2)) - require.Nil(t, cache.WorkloadsByWorkloadIdentity(identityID1)) -} - -func TestMapComputedTrafficPermissions(t *testing.T) { - client := svctest.RunResourceService(t, types.Register, catalog.RegisterTypes) - ctp := resourcetest.Resource(pbauth.ComputedTrafficPermissionsType, "workload-identity-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbauth.ComputedTrafficPermissions{}). - Build() - - c := New() - - // Empty results when the cache isn't populated. - requests, err := c.MapComputedTrafficPermissions(context.Background(), controller.Runtime{Client: client}, ctp) - require.NoError(t, err) - require.Len(t, requests, 0) - - identityID1 := resourcetest.Resource(pbauth.WorkloadIdentityType, "workload-identity-1"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID() - - w1 := resourcetest.Resource(pbcatalog.WorkloadType, "service-workload-1"). - WithData(t, &pbcatalog.Workload{ - Identity: identityID1.Name, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - decW1 := resourcetest.MustDecode[*pbcatalog.Workload](t, w1) - w2 := resourcetest.Resource(pbcatalog.WorkloadType, "service-workload-2"). - WithData(t, &pbcatalog.Workload{ - Identity: identityID1.Name, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - decW2 := resourcetest.MustDecode[*pbcatalog.Workload](t, w2) - - c.TrackWorkload(decW1) - - // Empty results when the cache isn't populated. - requests, err = c.MapComputedTrafficPermissions(context.Background(), controller.Runtime{Client: client}, ctp) - require.NoError(t, err) - prototest.AssertElementsMatch(t, - []controller.Request{{ID: resource.ReplaceType(pbmesh.ProxyStateTemplateType, w1.Id)}}, requests) - - c.TrackWorkload(decW2) - - // Empty results when the cache isn't populated. - requests, err = c.MapComputedTrafficPermissions(context.Background(), controller.Runtime{Client: client}, ctp) - require.NoError(t, err) - prototest.AssertElementsMatch(t, []controller.Request{ - {ID: resource.ReplaceType(pbmesh.ProxyStateTemplateType, w1.Id)}, - {ID: resource.ReplaceType(pbmesh.ProxyStateTemplateType, w2.Id)}, - }, requests) -} - -func TestUnified_AllMappingsToProxyStateTemplate(t *testing.T) { - var ( - cache = New() - client = svctest.RunResourceService(t, types.Register, catalog.RegisterTypes) - ) - - anyServiceData := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"src-workload"}, - }, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "tcp1", - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - { - TargetPort: "tcp2", - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - { - TargetPort: "mesh", - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - } - - // The thing we link through Destinations. - destService := resourcetest.Resource(pbcatalog.ServiceType, "web"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, anyServiceData). - Build() - destServiceRef := resource.Reference(destService.Id, "") - - // The thing we reach through the mesh config. - targetService := resourcetest.Resource(pbcatalog.ServiceType, "db"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, anyServiceData). - Build() - targetServiceRef := resource.Reference(targetService.Id, "") - - backupTargetService := resourcetest.Resource(pbcatalog.ServiceType, "db-backup"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, anyServiceData). - Build() - backupTargetServiceRef := resource.Reference(backupTargetService.Id, "") - - // The way we make 'web' actually route traffic to 'db'. - tcpRoute := resourcetest.Resource(pbmesh.TCPRouteType, "tcp-route"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{{ - Ref: destServiceRef, - }}, - Rules: []*pbmesh.TCPRouteRule{{ - BackendRefs: []*pbmesh.TCPBackendRef{{ - BackendRef: &pbmesh.BackendReference{ - Ref: targetServiceRef, - }, - }}, - }}, - }). - Build() - failoverPolicy := resourcetest.ResourceID(resource.ReplaceType(pbcatalog.FailoverPolicyType, targetService.Id)). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbcatalog.FailoverPolicy{ - Config: &pbcatalog.FailoverConfig{ - Destinations: []*pbcatalog.FailoverDestination{{ - Ref: backupTargetServiceRef, - }}, - }, - }). - Build() - webRoutes := routestest.BuildComputedRoutes(t, resource.ReplaceType(pbmesh.ComputedRoutesType, destService.Id), - resourcetest.MustDecode[*pbcatalog.Service](t, destService), - resourcetest.MustDecode[*pbcatalog.Service](t, targetService), - resourcetest.MustDecode[*pbcatalog.Service](t, backupTargetService), - resourcetest.MustDecode[*pbmesh.TCPRoute](t, tcpRoute), - resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, failoverPolicy), - ) - - var ( - sourceProxy1 = newID(pbmesh.ProxyStateTemplateType, "src-workload-1") - sourceProxy2 = newID(pbmesh.ProxyStateTemplateType, "src-workload-2") - sourceProxy3 = newID(pbmesh.ProxyStateTemplateType, "src-workload-3") - sourceProxy4 = newID(pbmesh.ProxyStateTemplateType, "src-workload-4") - sourceProxy5 = newID(pbmesh.ProxyStateTemplateType, "src-workload-5") - sourceProxy6 = newID(pbmesh.ProxyStateTemplateType, "src-workload-6") - ) - - compDestProxy1 := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, sourceProxy1.Name). - WithData(t, &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: destServiceRef, - DestinationPort: "tcp1", - }, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - - compDestProxy2 := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, sourceProxy2.Name). - WithData(t, &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: destServiceRef, - DestinationPort: "tcp1", - }, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - - compDestProxy3 := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, sourceProxy3.Name). - WithData(t, &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: destServiceRef, - DestinationPort: "tcp2", - }, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - - compDestProxy4 := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, sourceProxy4.Name). - WithData(t, &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: destServiceRef, - DestinationPort: "tcp2", - }, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - - compDestProxy5 := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, sourceProxy5.Name). - WithData(t, &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: destServiceRef, - DestinationPort: "mesh", - }, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - - compDestProxy6 := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, sourceProxy6.Name). - WithData(t, &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: destServiceRef, - DestinationPort: "mesh", - }, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - - cache.trackComputedRoutes(webRoutes) - cache.TrackComputedDestinations(resourcetest.MustDecode[*pbmesh.ComputedExplicitDestinations](t, compDestProxy1)) - cache.TrackComputedDestinations(resourcetest.MustDecode[*pbmesh.ComputedExplicitDestinations](t, compDestProxy2)) - cache.TrackComputedDestinations(resourcetest.MustDecode[*pbmesh.ComputedExplicitDestinations](t, compDestProxy3)) - cache.TrackComputedDestinations(resourcetest.MustDecode[*pbmesh.ComputedExplicitDestinations](t, compDestProxy4)) - cache.TrackComputedDestinations(resourcetest.MustDecode[*pbmesh.ComputedExplicitDestinations](t, compDestProxy5)) - cache.TrackComputedDestinations(resourcetest.MustDecode[*pbmesh.ComputedExplicitDestinations](t, compDestProxy6)) - - t.Run("Service", func(t *testing.T) { - t.Run("map dest service", func(t *testing.T) { - requests, err := cache.MapService( - context.Background(), - controller.Runtime{Client: client}, - destService, - ) - require.NoError(t, err) - - // Only wake up things with dest as an upstream. - expRequests := []controller.Request{ - {ID: sourceProxy1}, - {ID: sourceProxy2}, - {ID: sourceProxy3}, - {ID: sourceProxy4}, - {ID: sourceProxy5}, - {ID: sourceProxy6}, - } - - prototest.AssertElementsMatch(t, expRequests, requests) - - // Check that service's workload selector is tracked. - prototest.AssertElementsMatch(t, - []*pbresource.ID{destService.Id}, - cache.serviceSelectorTracker.GetIDsForWorkload(resource.ReplaceType(pbcatalog.WorkloadType, sourceProxy1))) - prototest.AssertElementsMatch(t, - []*pbresource.ID{destService.Id}, - cache.serviceSelectorTracker.GetIDsForWorkload(resource.ReplaceType(pbcatalog.WorkloadType, sourceProxy2))) - prototest.AssertElementsMatch(t, - []*pbresource.ID{destService.Id}, - cache.serviceSelectorTracker.GetIDsForWorkload(resource.ReplaceType(pbcatalog.WorkloadType, sourceProxy3))) - prototest.AssertElementsMatch(t, - []*pbresource.ID{destService.Id}, - cache.serviceSelectorTracker.GetIDsForWorkload(resource.ReplaceType(pbcatalog.WorkloadType, sourceProxy4))) - prototest.AssertElementsMatch(t, - []*pbresource.ID{destService.Id}, - cache.serviceSelectorTracker.GetIDsForWorkload(resource.ReplaceType(pbcatalog.WorkloadType, sourceProxy5))) - prototest.AssertElementsMatch(t, - []*pbresource.ID{destService.Id}, - cache.serviceSelectorTracker.GetIDsForWorkload(resource.ReplaceType(pbcatalog.WorkloadType, sourceProxy6))) - }) - - t.Run("map target endpoints (TCPRoute)", func(t *testing.T) { - requests, err := cache.MapService( - context.Background(), - controller.Runtime{Client: client}, - targetService, - ) - require.NoError(t, err) - - requests = testDeduplicateRequests(requests) - - expRequests := []controller.Request{ - // Wakeup things that have destService as a destination b/c of the TCPRoute reference. - {ID: sourceProxy1}, - {ID: sourceProxy2}, - {ID: sourceProxy3}, - {ID: sourceProxy4}, - {ID: sourceProxy5}, - {ID: sourceProxy6}, - } - - prototest.AssertElementsMatch(t, expRequests, requests) - }) - - t.Run("map backup target endpoints (FailoverPolicy)", func(t *testing.T) { - requests, err := cache.MapService( - context.Background(), - controller.Runtime{Client: client}, - backupTargetService, - ) - require.NoError(t, err) - - requests = testDeduplicateRequests(requests) - - expRequests := []controller.Request{ - // Wakeup things that have destService as a destination b/c of the FailoverPolicy reference. - {ID: sourceProxy1}, - {ID: sourceProxy2}, - {ID: sourceProxy3}, - {ID: sourceProxy4}, - {ID: sourceProxy5}, - {ID: sourceProxy6}, - } - - prototest.AssertElementsMatch(t, expRequests, requests) - }) - }) - - t.Run("ComputedRoutes", func(t *testing.T) { - t.Run("map web routes", func(t *testing.T) { - requests, err := cache.MapComputedRoutes( - context.Background(), - controller.Runtime{Client: client}, - webRoutes.Resource, - ) - require.NoError(t, err) - - // Only wake up things with dest as an upstream. - expRequests := []controller.Request{ - {ID: sourceProxy1}, - {ID: sourceProxy2}, - {ID: sourceProxy3}, - {ID: sourceProxy4}, - {ID: sourceProxy5}, - {ID: sourceProxy6}, - } - - prototest.AssertElementsMatch(t, expRequests, requests) - }) - }) -} - -func newID(typ *pbresource.Type, name string) *pbresource.ID { - return &pbresource.ID{ - Type: typ, - Tenancy: resource.DefaultNamespacedTenancy(), - Name: name, - } -} - -func testDeduplicateRequests(reqs []controller.Request) []controller.Request { - type resID struct { - resource.ReferenceKey - UID string - } - - out := make([]controller.Request, 0, len(reqs)) - seen := make(map[resID]struct{}) - - for _, req := range reqs { - rid := resID{ - ReferenceKey: resource.NewReferenceKey(req.ID), - UID: req.ID.Uid, - } - if _, ok := seen[rid]; !ok { - out = append(out, req) - seen[rid] = struct{}{} - } - } - - return out -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/controller.go b/internal/mesh/internal/controllers/sidecarproxy/controller.go deleted file mode 100644 index 6b81b04b8c0f..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/controller.go +++ /dev/null @@ -1,350 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sidecarproxy - -import ( - "context" - - "github.com/hashicorp/go-hclog" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/builder" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/cache" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/fetcher" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// ControllerName is the name for this controller. It's used for logging or status keys. -const ControllerName = "consul.io/sidecar-proxy-controller" - -type TrustDomainFetcher func() (string, error) - -func Controller( - cache *cache.Cache, - trustDomainFetcher TrustDomainFetcher, - dc string, - defaultAllow bool, -) controller.Controller { - if cache == nil || trustDomainFetcher == nil { - panic("cache and trust domain fetcher are required") - } - - /* - Workload PST - ComputedDestinations PST(==Workload) - ComputedDestinations Service(destinations) - ComputedProxyConfiguration PST(==Workload) - ComputedRoutes Service(upstream) - ComputedRoutes Service(disco) - ComputedTrafficPermissions WorkloadIdentity - Workload WorkloadIdentity - - These relationships then dictate the following reconcile logic. - - controller: read workload for PST - controller: read previous PST - controller: read ComputedProxyConfiguration for Workload - controller: read ComputedDestinations for workload to walk explicit upstreams - controller: read ComputedTrafficPermissions for workload using workload.identity field. - - fetcher: read Service(Destination) - fetcher: read ComputedRoutes - - fetcher: read ServiceEndpoints - - - - fetcher: list ALL ComputedRoutes - - fetcher: read Service(upstream) - - fetcher: read ServiceEndpoints - - - - */ - - /* - Which means for equivalence, the following mapper relationships should exist: - - Service: find destinations with Service; Recurse(ComputedDestinations); - find ComputedRoutes with this in a Target or FailoverConfig; Recurse(ComputedRoutes) - ComputedDestinations: replace type CED=>PST - ComputedProxyConfiguration: replace type CPC=>PST - ComputedRoutes: CR=>Service; find destinations with Service; Recurse(Destinations) - [implicit/temp]: trigger all - ComputedTrafficPermissions: find workloads in cache stored for this CTP=Workload, workloads=>PST reconcile requests - */ - - return controller.ForType(pbmesh.ProxyStateTemplateType). - WithWatch(pbcatalog.ServiceType, cache.MapService). - WithWatch(pbcatalog.WorkloadType, controller.ReplaceType(pbmesh.ProxyStateTemplateType)). - WithWatch(pbmesh.ComputedExplicitDestinationsType, controller.ReplaceType(pbmesh.ProxyStateTemplateType)). - WithWatch(pbmesh.ComputedProxyConfigurationType, controller.ReplaceType(pbmesh.ProxyStateTemplateType)). - WithWatch(pbmesh.ComputedRoutesType, cache.MapComputedRoutes). - WithWatch(pbauth.ComputedTrafficPermissionsType, cache.MapComputedTrafficPermissions). - WithReconciler(&reconciler{ - cache: cache, - getTrustDomain: trustDomainFetcher, - dc: dc, - defaultAllow: defaultAllow, - }) -} - -type reconciler struct { - cache *cache.Cache - getTrustDomain TrustDomainFetcher - defaultAllow bool - dc string -} - -func (r *reconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", ControllerName) - - rt.Logger.Trace("reconciling proxy state template") - - // Instantiate a data fetcher to fetch all reconciliation data. - dataFetcher := fetcher.New(rt.Client, r.cache) - - // Check if the workload exists. - workloadID := resource.ReplaceType(pbcatalog.WorkloadType, req.ID) - workload, err := dataFetcher.FetchWorkload(ctx, workloadID) - if err != nil { - rt.Logger.Error("error reading the associated workload", "error", err) - return err - } - if workload == nil { - // If workload has been deleted, then return as ProxyStateTemplate should be cleaned up - // by the garbage collector because of the owner reference. - rt.Logger.Trace("workload doesn't exist; skipping reconciliation", "workload", workloadID) - return nil - } - - proxyStateTemplate, err := dataFetcher.FetchProxyStateTemplate(ctx, req.ID) - if err != nil { - rt.Logger.Error("error reading proxy state template", "error", err) - return nil - } - - if proxyStateTemplate == nil { - // If proxy state template has been deleted, we will need to generate a new one. - rt.Logger.Trace("proxy state template for this workload doesn't yet exist; generating a new one") - } - - if !workload.GetData().IsMeshEnabled() { - // Skip non-mesh workloads. - - // If there's existing proxy state template, delete it. - if proxyStateTemplate != nil { - rt.Logger.Trace("deleting existing proxy state template because workload is no longer on the mesh") - _, err = rt.Client.Delete(ctx, &pbresource.DeleteRequest{Id: req.ID}) - if err != nil { - rt.Logger.Error("error deleting existing proxy state template", "error", err) - return err - } - } - rt.Logger.Trace("skipping proxy state template generation because workload is not on the mesh", "workload", workload.Resource.Id) - return nil - } - - // First get the trust domain. - trustDomain, err := r.getTrustDomain() - if err != nil { - rt.Logger.Error("error fetching trust domain to compute proxy state template", "error", err) - return err - } - - // Fetch proxy configuration. - proxyCfg, err := dataFetcher.FetchComputedProxyConfiguration(ctx, req.ID) - if err != nil { - rt.Logger.Error("error fetching proxy and merging proxy configurations", "error", err) - return err - } - - trafficPermissions, err := dataFetcher.FetchComputedTrafficPermissions(ctx, computedTrafficPermissionsIDFromWorkload(workload)) - if err != nil { - rt.Logger.Error("error fetching computed traffic permissions to compute proxy state template", "error", err) - return err - } - - var ctp *pbauth.ComputedTrafficPermissions - if trafficPermissions != nil { - ctp = trafficPermissions.Data - } - - workloadPorts, err := r.workloadPortProtocolsFromService(ctx, dataFetcher, workload, rt.Logger) - if err != nil { - rt.Logger.Error("error determining workload ports", "error", err) - return err - } - workloadDataWithInheritedPorts := proto.Clone(workload.Data).(*pbcatalog.Workload) - workloadDataWithInheritedPorts.Ports = workloadPorts - - b := builder.New(req.ID, identityRefFromWorkload(workload), trustDomain, r.dc, r.defaultAllow, proxyCfg.GetData()). - BuildLocalApp(workloadDataWithInheritedPorts, ctp) - - // Get all destinationsData. - destinationsData, err := dataFetcher.FetchExplicitDestinationsData(ctx, req.ID) - if err != nil { - rt.Logger.Error("error fetching explicit destinations for this proxy", "error", err) - return err - } - - if proxyCfg.GetData() != nil && proxyCfg.GetData().IsTransparentProxy() { - rt.Logger.Trace("transparent proxy is enabled; fetching implicit destinations") - destinationsData, err = dataFetcher.FetchImplicitDestinationsData(ctx, req.ID, destinationsData) - if err != nil { - rt.Logger.Error("error fetching implicit destinations for this proxy", "error", err) - return err - } - } - - b.BuildDestinations(destinationsData) - - newProxyTemplate := b.Build() - - if proxyStateTemplate == nil || !proto.Equal(proxyStateTemplate.Data, newProxyTemplate) { - if proxyStateTemplate == nil { - req.ID.Uid = "" - } - proxyTemplateData, err := anypb.New(newProxyTemplate) - if err != nil { - rt.Logger.Error("error creating proxy state template data", "error", err) - return err - } - rt.Logger.Trace("updating proxy state template") - _, err = rt.Client.Write(ctx, &pbresource.WriteRequest{ - Resource: &pbresource.Resource{ - Id: req.ID, - Owner: workload.Resource.Id, - Data: proxyTemplateData, - }, - }) - if err != nil { - rt.Logger.Error("error writing proxy state template", "error", err) - return err - } - } else { - rt.Logger.Trace("proxy state template data has not changed, skipping update") - } - - return nil -} - -func (r *reconciler) workloadPortProtocolsFromService( - ctx context.Context, - fetcher *fetcher.Fetcher, - workload *types.DecodedWorkload, - logger hclog.Logger, -) (map[string]*pbcatalog.WorkloadPort, error) { - - // Fetch all services for this workload. - serviceIDs := r.cache.ServicesForWorkload(workload.GetResource().GetId()) - - var services []*types.DecodedService - - for _, serviceID := range serviceIDs { - svc, err := fetcher.FetchService(ctx, serviceID) - if err != nil { - return nil, err - } - - // If service is not found, we should untrack it. - if svc == nil { - r.cache.UntrackService(serviceID) - continue - } - - services = append(services, svc) - } - - // Now walk through all workload ports. - // For ports that don't have a protocol explicitly specified, inherit it from the service. - - result := make(map[string]*pbcatalog.WorkloadPort) - - for portName, port := range workload.GetData().GetPorts() { - if port.GetProtocol() != pbcatalog.Protocol_PROTOCOL_UNSPECIFIED { - // Add any specified protocols as is. - result[portName] = port - continue - } - - // Check if we have any service IDs or fetched services. - if len(serviceIDs) == 0 || len(services) == 0 { - logger.Trace("found no services for this workload's port; using default TCP protocol", "port", portName) - result[portName] = &pbcatalog.WorkloadPort{ - Port: port.GetPort(), - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - } - continue - } - - // Otherwise, look for port protocol in the service. - inheritedProtocol := pbcatalog.Protocol_PROTOCOL_UNSPECIFIED - for _, svc := range services { - // Find workload's port as the target port. - svcPort := svc.GetData().FindServicePort(portName) - - // If this service doesn't select this port, go to the next service. - if svcPort == nil { - continue - } - - // Check for conflicts. - // If protocols between services selecting this workload on this port do not match, - // we use the default protocol (tcp) instead. - if inheritedProtocol != pbcatalog.Protocol_PROTOCOL_UNSPECIFIED && - svcPort.GetProtocol() != inheritedProtocol { - - logger.Trace("found conflicting service protocols that select this workload port; using default TCP protocol", "port", portName) - inheritedProtocol = pbcatalog.Protocol_PROTOCOL_TCP - - // We won't check any remaining services as there's already a conflict. - break - } - - inheritedProtocol = svcPort.GetProtocol() - } - - // If after going through all services, we haven't found a protocol, use the default. - if inheritedProtocol == pbcatalog.Protocol_PROTOCOL_UNSPECIFIED { - logger.Trace("no services select this workload port; using default TCP protocol", "port", portName) - result[portName] = &pbcatalog.WorkloadPort{ - Port: port.GetPort(), - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - } - } else { - result[portName] = &pbcatalog.WorkloadPort{ - Port: port.GetPort(), - Protocol: inheritedProtocol, - } - } - } - - return result, nil -} - -func identityRefFromWorkload(w *types.DecodedWorkload) *pbresource.Reference { - return &pbresource.Reference{ - Name: w.Data.Identity, - Tenancy: w.Resource.Id.Tenancy, - Type: pbauth.WorkloadIdentityType, - } -} - -func computedTrafficPermissionsIDFromWorkload(w *types.DecodedWorkload) *pbresource.ID { - return &pbresource.ID{ - Type: pbauth.ComputedTrafficPermissionsType, - Name: w.Data.Identity, - Tenancy: w.Resource.Id.Tenancy, - } -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/controller_test.go b/internal/mesh/internal/controllers/sidecarproxy/controller_test.go deleted file mode 100644 index 0d6684f0ef54..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/controller_test.go +++ /dev/null @@ -1,921 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package sidecarproxy - -import ( - "context" - "strings" - "testing" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/internal/auth" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/builder" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/cache" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/fetcher" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" -) - -type controllerTestSuite struct { - suite.Suite - - client *resourcetest.Client - runtime controller.Runtime - - ctl *reconciler - ctx context.Context - - apiWorkloadID *pbresource.ID - apiWorkload *pbcatalog.Workload - apiComputedTrafficPermissions *pbresource.Resource - apiComputedTrafficPermissionsData *pbauth.ComputedTrafficPermissions - apiService *pbresource.Resource - apiServiceData *pbcatalog.Service - apiEndpoints *pbresource.Resource - apiEndpointsData *pbcatalog.ServiceEndpoints - webWorkload *pbresource.Resource - - dbWorkloadID *pbresource.ID - dbWorkload *pbcatalog.Workload - dbService *pbresource.Resource - dbEndpoints *pbresource.Resource - dbEndpointsData *pbcatalog.ServiceEndpoints - - proxyStateTemplate *pbmesh.ProxyStateTemplate -} - -func (suite *controllerTestSuite) SetupTest() { - resourceClient := svctest.RunResourceService(suite.T(), types.Register, catalog.RegisterTypes, auth.RegisterTypes) - suite.client = resourcetest.NewClient(resourceClient) - suite.runtime = controller.Runtime{Client: resourceClient, Logger: testutil.Logger(suite.T())} - suite.ctx = testutil.TestContext(suite.T()) - - suite.ctl = &reconciler{ - cache: cache.New(), - getTrustDomain: func() (string, error) { - return "test.consul", nil - }, - } - - { - // DB will be a service with a single workload, IN the mesh that will - // be a destination of web. - - suite.dbWorkload = &pbcatalog.Workload{ - Identity: "db-identity", - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: "10.0.4.1"}, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - } - suite.dbWorkloadID = resourcetest.Resource(pbcatalog.WorkloadType, "db-abc"). - WithData(suite.T(), suite.dbWorkload). - Write(suite.T(), resourceClient).Id - - suite.dbService = resourcetest.Resource(pbcatalog.ServiceType, "db-service"). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"db-abc"}}, - VirtualIps: []string{"1.1.1.1"}, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }}). - Write(suite.T(), suite.client) - - suite.dbEndpointsData = &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: suite.dbWorkloadID, - Addresses: suite.dbWorkload.Addresses, - Ports: suite.dbWorkload.Ports, - Identity: "db-identity", - }, - }, - } - suite.dbEndpoints = resourcetest.Resource(pbcatalog.ServiceEndpointsType, "db-service"). - WithData(suite.T(), suite.dbEndpointsData). - Write(suite.T(), suite.client) - - } - - suite.apiWorkload = &pbcatalog.Workload{ - Identity: "api-identity", - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - } - - suite.apiWorkloadID = resourcetest.Resource(pbcatalog.WorkloadType, "api-abc"). - WithData(suite.T(), suite.apiWorkload). - Write(suite.T(), resourceClient).Id - - suite.apiServiceData = &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"api-abc"}}, - VirtualIps: []string{"1.1.1.1"}, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - } - - suite.apiComputedTrafficPermissionsData = &pbauth.ComputedTrafficPermissions{ - IsDefault: false, - AllowPermissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - IdentityName: "foo", - Namespace: "default", - Partition: "default", - Peer: "local", - }, - }, - }, - }, - } - - suite.apiComputedTrafficPermissions = resourcetest.Resource(pbauth.ComputedTrafficPermissionsType, suite.apiWorkload.Identity). - WithData(suite.T(), suite.apiComputedTrafficPermissionsData). - Write(suite.T(), resourceClient) - - suite.apiService = resourcetest.Resource(pbcatalog.ServiceType, "api-service"). - WithData(suite.T(), suite.apiServiceData). - Write(suite.T(), suite.client.ResourceServiceClient) - - suite.apiEndpointsData = &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: suite.apiWorkloadID, - Addresses: suite.apiWorkload.Addresses, - Ports: suite.apiWorkload.Ports, - Identity: "api-identity", - }, - }, - } - suite.apiEndpoints = resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-service"). - WithData(suite.T(), suite.apiEndpointsData). - Write(suite.T(), suite.client.ResourceServiceClient) - - webWorkloadData := &pbcatalog.Workload{ - Identity: "web-identity", - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.2", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8081, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - } - suite.webWorkload = resourcetest.Resource(pbcatalog.WorkloadType, "web-def"). - WithData(suite.T(), webWorkloadData). - Write(suite.T(), suite.client) - - resourcetest.Resource(pbauth.ComputedTrafficPermissionsType, webWorkloadData.Identity). - WithData(suite.T(), &pbauth.ComputedTrafficPermissions{IsDefault: true}). - Write(suite.T(), resourceClient) - - resourcetest.Resource(pbcatalog.ServiceType, "web"). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"web-def"}}, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }}). - Write(suite.T(), suite.client) - - resourcetest.Resource(pbcatalog.ServiceEndpointsType, "web"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: suite.webWorkload.Id, - Addresses: webWorkloadData.Addresses, - Ports: webWorkloadData.Ports, - Identity: "web-identity", - }, - }, - }).Write(suite.T(), suite.client) - - identityRef := &pbresource.Reference{ - Name: suite.apiWorkload.Identity, - Tenancy: suite.apiWorkloadID.Tenancy, - Type: pbauth.WorkloadIdentityType, - } - - suite.proxyStateTemplate = builder.New(resource.ReplaceType(pbmesh.ProxyStateTemplateType, suite.apiWorkloadID), - identityRef, "test.consul", "dc1", false, nil). - BuildLocalApp(suite.apiWorkload, suite.apiComputedTrafficPermissionsData). - Build() -} - -func (suite *controllerTestSuite) TestWorkloadPortProtocolsFromService_NoServicesInCache() { - dataFetcher := fetcher.New(suite.client, suite.ctl.cache) - - workload := resourcetest.Resource(pbcatalog.WorkloadType, "api-workload"). - WithData(suite.T(), &pbcatalog.Workload{ - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - }, - }). - Build() - - decWorkload := resourcetest.MustDecode[*pbcatalog.Workload](suite.T(), workload) - workloadPorts, err := suite.ctl.workloadPortProtocolsFromService(suite.ctx, dataFetcher, decWorkload, suite.runtime.Logger) - require.NoError(suite.T(), err) - prototest.AssertDeepEqual(suite.T(), pbcatalog.Protocol_PROTOCOL_TCP, workloadPorts["tcp"].GetProtocol()) -} - -func (suite *controllerTestSuite) TestWorkloadPortProtocolsFromService_ServiceNotFound() { - c := cache.New() - dataFetcher := fetcher.New(suite.client, c) - ctrl := &reconciler{ - cache: c, - getTrustDomain: func() (string, error) { - return "test.consul", nil - }, - } - svc := resourcetest.Resource(pbcatalog.ServiceType, "not-found"). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"api-workload"}, - }, - }). - Build() - - decSvc := resourcetest.MustDecode[*pbcatalog.Service](suite.T(), svc) - c.TrackService(decSvc) - - workload := resourcetest.Resource(pbcatalog.WorkloadType, "api-workload"). - WithData(suite.T(), &pbcatalog.Workload{ - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080}, - }, - }). - Build() - - decWorkload := resourcetest.MustDecode[*pbcatalog.Workload](suite.T(), workload) - - workloadPorts, err := ctrl.workloadPortProtocolsFromService(suite.ctx, dataFetcher, decWorkload, suite.runtime.Logger) - require.NoError(suite.T(), err) - prototest.AssertDeepEqual(suite.T(), pbcatalog.Protocol_PROTOCOL_TCP, workloadPorts["tcp"].GetProtocol()) - // Check that the service is no longer in cache. - require.Nil(suite.T(), c.ServicesForWorkload(workload.Id)) -} - -func (suite *controllerTestSuite) TestWorkloadPortProtocolsFromService() { - c := cache.New() - dataFetcher := fetcher.New(suite.client, c) - ctrl := &reconciler{ - cache: c, - getTrustDomain: func() (string, error) { - return "test.consul", nil - }, - } - svc1 := resourcetest.Resource(pbcatalog.ServiceType, "api-1"). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"api-workload"}, - }, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "http1", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "conflict", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - }). - Write(suite.T(), suite.client) - - decSvc := resourcetest.MustDecode[*pbcatalog.Service](suite.T(), svc1) - c.TrackService(decSvc) - - svc2 := resourcetest.Resource(pbcatalog.ServiceType, "api-2"). - WithData(suite.T(), &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"api-workload"}, - }, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "http2", - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, - }, - { - TargetPort: "conflict", - Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, - }, - }, - }). - Write(suite.T(), suite.client) - - decSvc = resourcetest.MustDecode[*pbcatalog.Service](suite.T(), svc2) - c.TrackService(decSvc) - - workload := resourcetest.Resource(pbcatalog.WorkloadType, "api-workload"). - WithData(suite.T(), &pbcatalog.Workload{ - Ports: map[string]*pbcatalog.WorkloadPort{ - "http1": {Port: 8080}, - "http2": {Port: 9090}, - "conflict": {Port: 9091}, - "not-selected": {Port: 8081}, - "specified-protocol": {Port: 8082, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - - decWorkload := resourcetest.MustDecode[*pbcatalog.Workload](suite.T(), workload) - - expWorkloadPorts := map[string]*pbcatalog.WorkloadPort{ - // This protocol should be inherited from service 1. - "http1": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - - // this protocol should be inherited from service 2. - "http2": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, - - // This port is not selected by the service and should default to tcp. - "not-selected": {Port: 8081, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - - // This port has conflicting protocols in each service and so it should default to tcp. - "conflict": {Port: 9091, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - - // These port should keep its existing protocol. - "specified-protocol": {Port: 8082, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - } - - workloadPorts, err := ctrl.workloadPortProtocolsFromService(suite.ctx, dataFetcher, decWorkload, suite.runtime.Logger) - require.NoError(suite.T(), err) - - prototest.AssertDeepEqual(suite.T(), expWorkloadPorts, workloadPorts) -} - -func (suite *controllerTestSuite) TestReconcile_NoWorkload() { - // This test ensures that removed workloads are ignored and don't result - // in the creation of the proxy state template. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: resourceID(pbmesh.ProxyStateTemplateType, "not-found"), - }) - require.NoError(suite.T(), err) - - suite.client.RequireResourceNotFound(suite.T(), resourceID(pbmesh.ProxyStateTemplateType, "not-found")) -} - -func (suite *controllerTestSuite) TestReconcile_NonMeshWorkload() { - // This test ensures that non-mesh workloads are ignored by the controller. - - nonMeshWorkload := &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - }, - } - - resourcetest.Resource(pbcatalog.WorkloadType, "test-non-mesh-api-workload"). - WithData(suite.T(), nonMeshWorkload). - Write(suite.T(), suite.client.ResourceServiceClient) - - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: resourceID(pbmesh.ProxyStateTemplateType, "test-non-mesh-api-workload"), - }) - - require.NoError(suite.T(), err) - suite.client.RequireResourceNotFound(suite.T(), resourceID(pbmesh.ProxyStateTemplateType, "test-non-mesh-api-workload")) -} - -func (suite *controllerTestSuite) TestReconcile_NoExistingProxyStateTemplate() { - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: resourceID(pbmesh.ProxyStateTemplateType, suite.apiWorkloadID.Name), - }) - require.NoError(suite.T(), err) - - res := suite.client.RequireResourceExists(suite.T(), resourceID(pbmesh.ProxyStateTemplateType, suite.apiWorkloadID.Name)) - require.NoError(suite.T(), err) - require.NotNil(suite.T(), res.Data) - prototest.AssertDeepEqual(suite.T(), suite.apiWorkloadID, res.Owner) -} - -func (suite *controllerTestSuite) TestReconcile_ExistingProxyStateTemplate_WithUpdates() { - // This test ensures that we write a new proxy state template when there are changes. - - // Write the original. - resourcetest.Resource(pbmesh.ProxyStateTemplateType, "api-abc"). - WithData(suite.T(), suite.proxyStateTemplate). - WithOwner(suite.apiWorkloadID). - Write(suite.T(), suite.client.ResourceServiceClient) - - // Update the apiWorkload and check that we default the port to tcp if it's unspecified. - suite.apiWorkload.Ports["tcp"].Protocol = pbcatalog.Protocol_PROTOCOL_UNSPECIFIED - - updatedWorkloadID := resourcetest.Resource(pbcatalog.WorkloadType, "api-abc"). - WithData(suite.T(), suite.apiWorkload). - Write(suite.T(), suite.client.ResourceServiceClient).Id - - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: resourceID(pbmesh.ProxyStateTemplateType, updatedWorkloadID.Name), - }) - require.NoError(suite.T(), err) - - res := suite.client.RequireResourceExists(suite.T(), resourceID(pbmesh.ProxyStateTemplateType, updatedWorkloadID.Name)) - require.NoError(suite.T(), err) - require.NotNil(suite.T(), res.Data) - prototest.AssertDeepEqual(suite.T(), updatedWorkloadID, res.Owner) - - var updatedProxyStateTemplate pbmesh.ProxyStateTemplate - err = res.Data.UnmarshalTo(&updatedProxyStateTemplate) - require.NoError(suite.T(), err) - - // Check that our value is updated in the proxy state template. - require.Len(suite.T(), updatedProxyStateTemplate.ProxyState.Listeners, 1) - require.Len(suite.T(), updatedProxyStateTemplate.ProxyState.Listeners[0].Routers, 1) - - l4InboundRouter := updatedProxyStateTemplate.ProxyState.Listeners[0]. - Routers[0].GetL4() - require.NotNil(suite.T(), l4InboundRouter) -} - -func (suite *controllerTestSuite) TestReconcile_ExistingProxyStateTemplate_NoUpdates() { - // This test ensures that we skip writing of the proxy state template when there are no changes to it. - - // Write the original. - originalProxyState := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "api-abc"). - WithData(suite.T(), suite.proxyStateTemplate). - WithOwner(suite.apiWorkloadID). - Write(suite.T(), suite.client.ResourceServiceClient) - - // Update the metadata on the apiWorkload which should result in no changes. - updatedWorkloadID := resourcetest.Resource(pbcatalog.WorkloadType, "api-abc"). - WithData(suite.T(), suite.apiWorkload). - WithMeta("some", "meta"). - Write(suite.T(), suite.client.ResourceServiceClient).Id - - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: resourceID(pbmesh.ProxyStateTemplateType, updatedWorkloadID.Name), - }) - require.NoError(suite.T(), err) - - updatedProxyState := suite.client.RequireResourceExists(suite.T(), resourceID(pbmesh.ProxyStateTemplateType, suite.apiWorkloadID.Name)) - resourcetest.RequireVersionUnchanged(suite.T(), updatedProxyState, originalProxyState.Version) -} - -func (suite *controllerTestSuite) TestController() { - // This is a comprehensive test that checks the overall controller behavior as various resources change state. - // This should test interactions between the reconciler, the mappers, and the destinationsCache to ensure they work - // together and produce expected result. - - // Run the controller manager - mgr := controller.NewManager(suite.client, suite.runtime.Logger) - - // Initialize controller dependencies. - c := cache.New() - trustDomainFetcher := func() (string, error) { return "test.consul", nil } - - mgr.Register(Controller(c, trustDomainFetcher, "dc1", false)) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - var ( - // Create proxy state template IDs to check against in this test. - apiProxyStateTemplateID = resourcetest.Resource(pbmesh.ProxyStateTemplateType, "api-abc").ID() - webProxyStateTemplateID = resourcetest.Resource(pbmesh.ProxyStateTemplateType, "web-def").ID() - - apiComputedRoutesID = resource.ReplaceType(pbmesh.ComputedRoutesType, suite.apiService.Id) - dbComputedRoutesID = resource.ReplaceType(pbmesh.ComputedRoutesType, suite.dbService.Id) - - apiProxyStateTemplate *pbresource.Resource - webProxyStateTemplate *pbresource.Resource - webComputedDestinations *pbresource.Resource - ) - - testutil.RunStep(suite.T(), "proxy state template generation", func(t *testing.T) { - // Check that proxy state template resource is generated for both the api and web workloads. - retry.Run(t, func(r *retry.R) { - suite.client.RequireResourceExists(r, apiProxyStateTemplateID) - webProxyStateTemplate = suite.client.RequireResourceExists(r, webProxyStateTemplateID) - apiProxyStateTemplate = suite.client.RequireResourceExists(r, apiProxyStateTemplateID) - }) - }) - - // Write a default ComputedRoutes for api. - routestest.ReconcileComputedRoutes(suite.T(), suite.client, apiComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.apiService), - ) - - // Add a source service and check that a new proxy state is generated. - webComputedDestinations = resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.webWorkload.Id.Name). - WithData(suite.T(), &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: resource.Reference(suite.apiService.Id, ""), - DestinationPort: "tcp", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 1234, - }, - }, - }, - }, - }).Write(suite.T(), suite.client) - - testutil.RunStep(suite.T(), "add explicit destinations and check that new proxy state is generated", func(t *testing.T) { - webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version) - - requireExplicitDestinationsFound(t, "api", webProxyStateTemplate) - }) - - testutil.RunStep(suite.T(), "update api's ports to be non-mesh", func(t *testing.T) { - // Update destination's service endpoints and workload to be non-mesh - // and check that: - // * api's proxy state template is deleted - // * we get a new web proxy resource re-generated - // * the status on Upstreams resource is updated with a validation error - nonMeshPorts := map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - } - - // Note: the order matters here because in reality service endpoints will only - // be reconciled after the workload has been updated, and so we need to write the - // workload and service before we write service endpoints. - resourcetest.Resource(pbcatalog.WorkloadType, "api-abc"). - WithData(suite.T(), &pbcatalog.Workload{ - Identity: "api-identity", - Addresses: suite.apiWorkload.Addresses, - Ports: nonMeshPorts}). - Write(suite.T(), suite.client) - - suite.apiService = resourcetest.ResourceID(suite.apiService.Id). - WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"api-abc"}}, - VirtualIps: []string{"1.1.1.1"}, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - // {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }). - Write(suite.T(), suite.client) - - resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-service"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: suite.apiWorkloadID, - Addresses: suite.apiWorkload.Addresses, - Ports: nonMeshPorts, - Identity: "api-identity", - }, - }, - }). - Write(suite.T(), suite.client.ResourceServiceClient) - - // Refresh the computed routes in light of api losing a mesh port. - routestest.ReconcileComputedRoutes(suite.T(), suite.client, apiComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](t, suite.apiService), - ) - - // Check that api proxy template is gone. - retry.Run(t, func(r *retry.R) { - suite.client.RequireResourceNotFound(r, apiProxyStateTemplateID) - }) - - // We should get a new web proxy template resource because this destination should be removed. - webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version) - - requireExplicitDestinationsNotFound(t, "api", webProxyStateTemplate) - }) - - testutil.RunStep(suite.T(), "update ports to be mesh again", func(t *testing.T) { - // Update destination's service endpoints back to mesh and check that we get a new web proxy resource re-generated - // and that the status on Upstreams resource is updated to be empty. - suite.runtime.Logger.Trace("updating ports to mesh") - - resourcetest.Resource(pbcatalog.WorkloadType, "api-abc"). - WithData(suite.T(), suite.apiWorkload). - Write(suite.T(), suite.client) - - suite.apiService = resourcetest.Resource(pbcatalog.ServiceType, "api-service"). - WithData(suite.T(), suite.apiServiceData). - Write(suite.T(), suite.client.ResourceServiceClient) - - resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-service"). - WithData(suite.T(), suite.apiEndpointsData). - Write(suite.T(), suite.client.ResourceServiceClient) - - // Refresh the computed routes in light of api losing a mesh port. - routestest.ReconcileComputedRoutes(suite.T(), suite.client, apiComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](t, suite.apiService), - ) - - // We should also get a new web proxy template resource as this destination should be added again. - webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version) - - requireExplicitDestinationsFound(t, "api", webProxyStateTemplate) - }) - - testutil.RunStep(suite.T(), "delete the proxy state template and check re-generation", func(t *testing.T) { - // Delete the proxy state template resource and check that it gets regenerated. - suite.runtime.Logger.Trace("deleting web proxy") - _, err := suite.client.Delete(suite.ctx, &pbresource.DeleteRequest{Id: webProxyStateTemplateID}) - require.NoError(suite.T(), err) - - webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version) - requireExplicitDestinationsFound(t, "api", webProxyStateTemplate) - }) - - testutil.RunStep(suite.T(), "add implicit upstream and enable tproxy", func(t *testing.T) { - // Delete explicit destinations resource. - suite.runtime.Logger.Trace("deleting web destinations") - _, err := suite.client.Delete(suite.ctx, &pbresource.DeleteRequest{Id: webComputedDestinations.Id}) - require.NoError(t, err) - - webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version) - - // Write a default ComputedRoutes for db, so it's eligible. - dbCR := routestest.ReconcileComputedRoutes(suite.T(), suite.client, dbComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](t, suite.dbService), - ) - require.NotNil(t, dbCR) - - // Enable transparent proxy for the web proxy. - resourcetest.Resource(pbmesh.ComputedProxyConfigurationType, suite.webWorkload.Id.Name). - WithData(t, &pbmesh.ComputedProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - TransparentProxy: &pbmesh.TransparentProxy{ - OutboundListenerPort: 15001, - }, - }, - }).Write(suite.T(), suite.client) - - webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version) - apiProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), apiProxyStateTemplateID, apiProxyStateTemplate.Version) - - requireImplicitDestinationsFound(t, "api", webProxyStateTemplate) - requireImplicitDestinationsFound(t, "db", webProxyStateTemplate) - }) - - testutil.RunStep(suite.T(), "traffic permissions", func(t *testing.T) { - // Global default deny applies to all identities. - assertTrafficPermissionDefaultPolicy(t, false, apiProxyStateTemplate) - assertTrafficPermissionDefaultPolicy(t, false, webProxyStateTemplate) - - suite.runtime.Logger.Trace("deleting computed traffic permissions") - _, err := suite.client.Delete(suite.ctx, &pbresource.DeleteRequest{Id: suite.apiComputedTrafficPermissions.Id}) - require.NoError(t, err) - suite.client.WaitForDeletion(t, suite.apiComputedTrafficPermissions.Id) - - apiProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), apiProxyStateTemplateID, apiProxyStateTemplate.Version) - - suite.runtime.Logger.Trace("creating computed traffic permissions") - resourcetest.Resource(pbauth.ComputedTrafficPermissionsType, suite.apiWorkload.Identity). - WithData(t, suite.apiComputedTrafficPermissionsData). - Write(t, suite.client) - - suite.client.WaitForNewVersion(t, apiProxyStateTemplateID, apiProxyStateTemplate.Version) - }) - - testutil.RunStep(suite.T(), "add an HTTPRoute with a simple split on the tcp port", func(t *testing.T) { - // NOTE: because at this point we have tproxy in all-to-all mode, we will get an - // implicit upstream on 'db' - - // Create a route NOT in the state store, only to more easily feed - // into the generator. - routeData := &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{{ - Ref: resource.Reference(suite.dbService.Id, ""), - Port: "", // implicitly applies to 'http' - }}, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{ - { - BackendRef: &pbmesh.BackendReference{ - Ref: resource.Reference(suite.apiService.Id, ""), - Port: "tcp", - }, - Weight: 60, - }, - { - BackendRef: &pbmesh.BackendReference{ - Ref: resource.Reference(suite.dbService.Id, ""), - Port: "", // assumed to be 'http' - }, - Weight: 40, - }, - }, - }}, - } - route := resourcetest.Resource(pbmesh.HTTPRouteType, "db-http-route"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, routeData). - Build() - require.NoError(t, types.MutateHTTPRoute(route)) - require.NoError(t, types.ValidateHTTPRoute(route)) - - dbCRID := resource.ReplaceType(pbmesh.ComputedRoutesType, suite.dbService.Id) - - dbCR := routestest.ReconcileComputedRoutes(suite.T(), suite.client, dbCRID, - resourcetest.MustDecode[*pbmesh.HTTPRoute](t, route), - resourcetest.MustDecode[*pbcatalog.Service](t, suite.dbService), - resourcetest.MustDecode[*pbcatalog.Service](t, suite.apiService), - ) - require.NotNil(t, dbCR, "computed routes for db was deleted instead of created") - - webProxyStateTemplate = suite.client.WaitForNewVersion(suite.T(), webProxyStateTemplateID, webProxyStateTemplate.Version) - - requireImplicitDestinationsFound(t, "api", webProxyStateTemplate) - requireImplicitDestinationsFound(t, "db", webProxyStateTemplate) - }) -} - -func (suite *controllerTestSuite) TestControllerDefaultAllow() { - // Run the controller manager - mgr := controller.NewManager(suite.client, suite.runtime.Logger) - - // Initialize controller dependencies. - c := cache.New() - trustDomainFetcher := func() (string, error) { return "test.consul", nil } - - mgr.Register(Controller(c, trustDomainFetcher, "dc1", true)) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - var ( - // Create proxy state template IDs to check against in this test. - apiProxyStateTemplateID = resourcetest.Resource(pbmesh.ProxyStateTemplateType, "api-abc").ID() - webProxyStateTemplateID = resourcetest.Resource(pbmesh.ProxyStateTemplateType, "web-def").ID() - ) - - retry.Run(suite.T(), func(r *retry.R) { - webProxyStateTemplate := suite.client.RequireResourceExists(r, webProxyStateTemplateID) - apiProxyStateTemplate := suite.client.RequireResourceExists(r, apiProxyStateTemplateID) - - // Default deny because api has non-empty computed traffic permissions. - assertTrafficPermissionDefaultPolicy(r, false, apiProxyStateTemplate) - assertTrafficPermissionDefaultPolicy(r, true, webProxyStateTemplate) - }) -} - -func TestMeshController(t *testing.T) { - suite.Run(t, new(controllerTestSuite)) -} - -func requireExplicitDestinationsFound(t *testing.T, name string, tmplResource *pbresource.Resource) { - requireExplicitDestinations(t, name, tmplResource, true) -} - -func requireExplicitDestinationsNotFound(t *testing.T, name string, tmplResource *pbresource.Resource) { - requireExplicitDestinations(t, name, tmplResource, false) -} - -func requireExplicitDestinations(t *testing.T, name string, tmplResource *pbresource.Resource, found bool) { - t.Helper() - - var tmpl pbmesh.ProxyStateTemplate - err := tmplResource.Data.UnmarshalTo(&tmpl) - require.NoError(t, err) - - // Check outbound listener. - var foundListener bool - for _, l := range tmpl.ProxyState.Listeners { - if strings.Contains(l.Name, name) && l.Direction == pbproxystate.Direction_DIRECTION_OUTBOUND { - foundListener = true - break - } - } - - require.Equal(t, found, foundListener) - - requireClustersAndEndpoints(t, name, &tmpl, found) -} - -func requireImplicitDestinationsFound(t *testing.T, name string, tmplResource *pbresource.Resource) { - t.Helper() - - var tmpl pbmesh.ProxyStateTemplate - err := tmplResource.Data.UnmarshalTo(&tmpl) - require.NoError(t, err) - - // Check outbound listener. - var foundListener bool - for _, l := range tmpl.ProxyState.Listeners { - if strings.Contains(l.Name, xdscommon.OutboundListenerName) && l.Direction == pbproxystate.Direction_DIRECTION_OUTBOUND { - foundListener = true - - // Check the listener filter chain - for _, r := range l.Routers { - foundByName := false - switch x := r.Destination.(type) { - case *pbproxystate.Router_L4: - // TcpProxy is easy, so just having this exist is - // sufficient. We don't have to deep inspect it. We care - // that there IS a listener matching the destination. If - // there is a TCPRoute with a split or a rename we don't - // care here. - foundByName = true - case *pbproxystate.Router_L7: - require.NotNil(t, x.L7.Route) - routerName := x.L7.Route.Name - foundByName = strings.Contains(routerName, name) - default: - t.Fatalf("unexpected type of destination: %T", r.Destination) - } - - if foundByName { - // We expect that there is a filter chain match for transparent proxy destinations. - require.NotNil(t, r.Match) - require.NotEmpty(t, r.Match.PrefixRanges) - break - } - } - break - } - } - require.True(t, foundListener) - - requireClustersAndEndpoints(t, name, &tmpl, true) -} - -func requireClustersAndEndpoints(t *testing.T, name string, tmpl *pbmesh.ProxyStateTemplate, found bool) { - t.Helper() - - var foundCluster bool - for c := range tmpl.ProxyState.Clusters { - if strings.Contains(c, name) { - foundCluster = true - break - } - } - - require.Equal(t, found, foundCluster) - - var foundEndpoints bool - for c := range tmpl.RequiredEndpoints { - if strings.Contains(c, name) { - foundEndpoints = true - break - } - } - - require.Equal(t, found, foundEndpoints) -} - -func resourceID(rtype *pbresource.Type, name string) *pbresource.ID { - return &pbresource.ID{ - Type: rtype, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: name, - } -} - -func assertTrafficPermissionDefaultPolicy(t resourcetest.T, defaultAllow bool, resource *pbresource.Resource) { - dec := resourcetest.MustDecode[*pbmesh.ProxyStateTemplate](t, resource) - var listener *pbproxystate.Listener - for _, l := range dec.Data.ProxyState.Listeners { - if l.Name == "public_listener" { - listener = l - break - } - } - require.Len(t, listener.Routers, 1) - l4 := listener.Routers[0].GetL4() - require.NotNil(t, l4) - require.Equal(t, defaultAllow, l4.TrafficPermissions.DefaultAllow) -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher.go b/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher.go deleted file mode 100644 index 7a31798a244b..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher.go +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package fetcher - -import ( - "context" - "fmt" - "strings" - - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/cache" - "github.com/hashicorp/consul/internal/mesh/internal/types" - intermediateTypes "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/storage" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type Fetcher struct { - client pbresource.ResourceServiceClient - cache *cache.Cache -} - -func New(client pbresource.ResourceServiceClient, cache *cache.Cache) *Fetcher { - return &Fetcher{ - client: client, - cache: cache, - } -} - -func (f *Fetcher) FetchWorkload(ctx context.Context, id *pbresource.ID) (*types.DecodedWorkload, error) { - dec, err := resource.GetDecodedResource[*pbcatalog.Workload](ctx, f.client, id) - if err != nil { - return nil, err - } else if dec == nil { - // We also need to make sure to delete the associated proxy from cache. - f.cache.UntrackWorkload(id) - return nil, nil - } - - f.cache.TrackWorkload(dec) - - return dec, err -} - -func (f *Fetcher) FetchProxyStateTemplate(ctx context.Context, id *pbresource.ID) (*types.DecodedProxyStateTemplate, error) { - return resource.GetDecodedResource[*pbmesh.ProxyStateTemplate](ctx, f.client, id) -} - -func (f *Fetcher) FetchComputedTrafficPermissions(ctx context.Context, id *pbresource.ID) (*types.DecodedComputedTrafficPermissions, error) { - return resource.GetDecodedResource[*pbauth.ComputedTrafficPermissions](ctx, f.client, id) -} - -func (f *Fetcher) FetchServiceEndpoints(ctx context.Context, id *pbresource.ID) (*types.DecodedServiceEndpoints, error) { - return resource.GetDecodedResource[*pbcatalog.ServiceEndpoints](ctx, f.client, id) -} - -func (f *Fetcher) FetchService(ctx context.Context, id *pbresource.ID) (*types.DecodedService, error) { - return resource.GetDecodedResource[*pbcatalog.Service](ctx, f.client, id) -} - -func (f *Fetcher) FetchDestinations(ctx context.Context, id *pbresource.ID) (*types.DecodedDestinations, error) { - return resource.GetDecodedResource[*pbmesh.Destinations](ctx, f.client, id) -} - -func (f *Fetcher) FetchComputedRoutes(ctx context.Context, id *pbresource.ID) (*types.DecodedComputedRoutes, error) { - if !types.IsComputedRoutesType(id.Type) { - return nil, fmt.Errorf("id must be a ComputedRoutes type") - } - - dec, err := resource.GetDecodedResource[*pbmesh.ComputedRoutes](ctx, f.client, id) - if err != nil { - return nil, err - } else if dec == nil { - f.cache.UntrackComputedRoutes(id) - } - - return dec, err -} - -func (f *Fetcher) FetchExplicitDestinationsData( - ctx context.Context, - proxyID *pbresource.ID, -) ([]*intermediateTypes.Destination, error) { - - var destinations []*intermediateTypes.Destination - - // Fetch computed explicit destinations first. - cdID := resource.ReplaceType(pbmesh.ComputedExplicitDestinationsType, proxyID) - cd, err := resource.GetDecodedResource[*pbmesh.ComputedExplicitDestinations](ctx, f.client, cdID) - if err != nil { - return nil, err - } - if cd == nil { - f.cache.UntrackComputedDestinations(cdID) - return nil, nil - } - - // Otherwise, track this resource in the destinations cache. - f.cache.TrackComputedDestinations(cd) - - for _, dest := range cd.GetData().GetDestinations() { - d := &intermediateTypes.Destination{} - - var ( - serviceID = resource.IDFromReference(dest.DestinationRef) - ) - - // Fetch Service - svc, err := f.FetchService(ctx, serviceID) - if err != nil { - return nil, err - } - - if svc == nil { - // If the Service resource is not found, skip this destination. - continue - } - - d.Service = svc - - // Check if this service is mesh-enabled. If not, update the status. - if !svc.GetData().IsMeshEnabled() { - // This error should not cause the execution to stop, as we want to make sure that this non-mesh destination - // service gets removed from the proxy state. - continue - } - - // Check if the desired port exists on the service and skip it doesn't. - if svc.GetData().FindServicePort(dest.DestinationPort) == nil { - continue - } - - // No destination port should point to a port with "mesh" protocol, - // so check if destination port has the mesh protocol and skip it if it does. - if svc.GetData().FindServicePort(dest.DestinationPort).GetProtocol() == pbcatalog.Protocol_PROTOCOL_MESH { - continue - } - - // Fetch ComputedRoutes. - cr, err := f.FetchComputedRoutes(ctx, resource.ReplaceType(pbmesh.ComputedRoutesType, serviceID)) - if err != nil { - return nil, err - } else if cr == nil { - // This is required, so wait until it exists. - continue - } - - portConfig, ok := cr.Data.PortedConfigs[dest.DestinationPort] - if !ok { - // This is required, so wait until it exists. - continue - } - - // Copy this so we can mutate the targets. - d.ComputedPortRoutes = proto.Clone(portConfig).(*pbmesh.ComputedPortRoutes) - - // As Destinations resource contains a list of destinations, - // we need to find the one that references our service and port. - d.Explicit = dest - - // NOTE: we collect both DIRECT and INDIRECT target information here. - for _, routeTarget := range d.ComputedPortRoutes.Targets { - targetServiceID := resource.IDFromReference(routeTarget.BackendRef.Ref) - - // Fetch ServiceEndpoints. - se, err := f.FetchServiceEndpoints(ctx, resource.ReplaceType(pbcatalog.ServiceEndpointsType, targetServiceID)) - if err != nil { - return nil, err - } - - if se != nil { - routeTarget.ServiceEndpointsId = se.Resource.Id - routeTarget.ServiceEndpoints = se.Data - - // Gather all identities. - var identities []*pbresource.Reference - for _, identity := range se.GetData().GetIdentities() { - identities = append(identities, &pbresource.Reference{ - Name: identity, - Tenancy: se.Resource.Id.Tenancy, - }) - } - routeTarget.IdentityRefs = identities - } - } - - destinations = append(destinations, d) - } - - return destinations, nil -} - -type PortReferenceKey struct { - resource.ReferenceKey - Port string -} - -// FetchImplicitDestinationsData fetches all implicit destinations and adds them to existing destinations. -// If the implicit destination is already in addToDestinations, it will be skipped. -// todo (ishustava): this function will eventually need to fetch implicit destinations from the ImplicitDestinations resource instead. -func (f *Fetcher) FetchImplicitDestinationsData( - ctx context.Context, - proxyID *pbresource.ID, - addToDestinations []*intermediateTypes.Destination, -) ([]*intermediateTypes.Destination, error) { - // First, convert existing destinations to a map so we can de-dup. - // - // This is keyed by the serviceID+port of the upstream, which is effectively - // the same as the id of the computed routes for the service. - destinations := make(map[PortReferenceKey]*intermediateTypes.Destination) - for _, d := range addToDestinations { - prk := PortReferenceKey{ - ReferenceKey: resource.NewReferenceKey(d.Service.Resource.Id), - Port: d.ComputedPortRoutes.ParentRef.Port, - } - destinations[prk] = d - } - - // For now we need to look up all computed routes within a partition. - rsp, err := f.client.List(ctx, &pbresource.ListRequest{ - Type: pbmesh.ComputedRoutesType, - Tenancy: &pbresource.Tenancy{ - Namespace: storage.Wildcard, - Partition: proxyID.Tenancy.Partition, - PeerName: proxyID.Tenancy.PeerName, - }, - }) - if err != nil { - return nil, err - } - - for _, r := range rsp.Resources { - svcID := resource.ReplaceType(pbcatalog.ServiceType, r.Id) - computedRoutes, err := resource.Decode[*pbmesh.ComputedRoutes](r) - if err != nil { - return nil, err - } - - if computedRoutes == nil { - // the routes-controller doesn't deem this worthy of the mesh - continue - } - - // Fetch the service. - // todo (ishustava): this should eventually grab virtual IPs resource. - svc, err := f.FetchService(ctx, resource.ReplaceType(pbcatalog.ServiceType, r.Id)) - if err != nil { - return nil, err - } - if svc == nil { - // If service no longer exists, skip. - continue - } - - // If this proxy is a part of this service, ignore it. - if isPartOfService(resource.ReplaceType(pbcatalog.WorkloadType, proxyID), svc) { - continue - } - - inMesh := false - for _, port := range svc.Data.Ports { - if port.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - inMesh = true - break - } - } - - if !inMesh { - // If a service is no longer in the mesh, skip. - continue - } - - // Fetch the resources that may show up duplicated. - // - // NOTE: we collect both DIRECT and INDIRECT target information here. - endpointsMap := make(map[resource.ReferenceKey]*types.DecodedServiceEndpoints) - for _, portConfig := range computedRoutes.Data.PortedConfigs { - for _, routeTarget := range portConfig.Targets { - targetServiceID := resource.IDFromReference(routeTarget.BackendRef.Ref) - - seID := resource.ReplaceType(pbcatalog.ServiceEndpointsType, targetServiceID) - seRK := resource.NewReferenceKey(seID) - - if _, ok := endpointsMap[seRK]; !ok { - se, err := f.FetchServiceEndpoints(ctx, seID) - if err != nil { - return nil, err - } - // We only add the endpoint to the map if it's not nil. If it's missing on lookup now, the - // controller should get triggered when the endpoint exists again since it watches service - // endpoints. - if se != nil { - endpointsMap[seRK] = se - } - } - } - } - - for portName, portConfig := range computedRoutes.Data.PortedConfigs { - // If it's already in destinations, ignore it. - prk := PortReferenceKey{ - ReferenceKey: resource.NewReferenceKey(svcID), - Port: portName, - } - if _, ok := destinations[prk]; ok { - continue - } - - // Copy this so we can mutate the targets. - portConfig = proto.Clone(portConfig).(*pbmesh.ComputedPortRoutes) - - d := &intermediateTypes.Destination{ - Service: svc, - ComputedPortRoutes: portConfig, - VirtualIPs: svc.Data.VirtualIps, - } - for _, routeTarget := range portConfig.Targets { - targetServiceID := resource.IDFromReference(routeTarget.BackendRef.Ref) - seID := resource.ReplaceType(pbcatalog.ServiceEndpointsType, targetServiceID) - - // Fetch ServiceEndpoints. - se, ok := endpointsMap[resource.NewReferenceKey(seID)] - if ok { - routeTarget.ServiceEndpointsId = se.Resource.Id - routeTarget.ServiceEndpoints = se.Data - - // Gather all identities. - var identities []*pbresource.Reference - for _, ep := range se.Data.Endpoints { - identities = append(identities, &pbresource.Reference{ - Name: ep.Identity, - Tenancy: se.Resource.Id.Tenancy, - }) - } - routeTarget.IdentityRefs = identities - } - } - addToDestinations = append(addToDestinations, d) - } - } - return addToDestinations, err -} - -// FetchComputedProxyConfiguration fetches proxy configurations for the proxy state template provided by id -// and merges them into one object. -func (f *Fetcher) FetchComputedProxyConfiguration(ctx context.Context, id *pbresource.ID) (*types.DecodedComputedProxyConfiguration, error) { - compProxyCfgID := resource.ReplaceType(pbmesh.ComputedProxyConfigurationType, id) - - return resource.GetDecodedResource[*pbmesh.ComputedProxyConfiguration](ctx, f.client, compProxyCfgID) -} - -func isPartOfService(workloadID *pbresource.ID, svc *types.DecodedService) bool { - if !resource.EqualTenancy(workloadID.GetTenancy(), svc.Resource.Id.GetTenancy()) { - return false - } - sel := svc.Data.Workloads - for _, exact := range sel.GetNames() { - if workloadID.GetName() == exact { - return true - } - } - for _, prefix := range sel.GetPrefixes() { - if strings.HasPrefix(workloadID.GetName(), prefix) { - return true - } - } - return false -} diff --git a/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher_test.go b/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher_test.go deleted file mode 100644 index 457fa393b43f..000000000000 --- a/internal/mesh/internal/controllers/sidecarproxy/fetcher/data_fetcher_test.go +++ /dev/null @@ -1,598 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package fetcher - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/sidecarproxy/cache" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/mesh/internal/types/intermediate" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -type dataFetcherSuite struct { - suite.Suite - - ctx context.Context - client pbresource.ResourceServiceClient - rt controller.Runtime - - api1Service *pbresource.Resource - api1ServiceData *pbcatalog.Service - api2Service *pbresource.Resource - api2ServiceData *pbcatalog.Service - api1ServiceEndpoints *pbresource.Resource - api1ServiceEndpointsData *pbcatalog.ServiceEndpoints - api2ServiceEndpoints *pbresource.Resource - api2ServiceEndpointsData *pbcatalog.ServiceEndpoints - webComputedDestinationsData *pbmesh.ComputedExplicitDestinations - webProxy *pbresource.Resource - webWorkload *pbresource.Resource -} - -func (suite *dataFetcherSuite) SetupTest() { - suite.ctx = testutil.TestContext(suite.T()) - suite.client = svctest.RunResourceService(suite.T(), types.Register, catalog.RegisterTypes) - suite.rt = controller.Runtime{ - Client: suite.client, - Logger: testutil.Logger(suite.T()), - } - - suite.api1ServiceData = &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", VirtualPort: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", VirtualPort: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - } - suite.api1Service = resourcetest.Resource(pbcatalog.ServiceType, "api-1"). - WithData(suite.T(), suite.api1ServiceData). - Write(suite.T(), suite.client) - - suite.api1ServiceEndpointsData = &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Addresses: []*pbcatalog.WorkloadAddress{{Host: "10.0.0.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - Identity: "api-1-identity", - }, - }, - } - suite.api1ServiceEndpoints = resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-1"). - WithData(suite.T(), suite.api1ServiceEndpointsData). - Write(suite.T(), suite.client) - - suite.api2ServiceData = &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp1", VirtualPort: 9080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "tcp2", VirtualPort: 9081, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", VirtualPort: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - } - suite.api2Service = resourcetest.Resource(pbcatalog.ServiceType, "api-2"). - WithData(suite.T(), suite.api2ServiceData). - Write(suite.T(), suite.client) - - suite.api2ServiceEndpointsData = &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Addresses: []*pbcatalog.WorkloadAddress{{Host: "10.0.0.2"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp1": {Port: 9080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "tcp2": {Port: 9081, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - Identity: "api-2-identity", - }, - }, - } - suite.api2ServiceEndpoints = resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-2"). - WithData(suite.T(), suite.api2ServiceEndpointsData). - Write(suite.T(), suite.client) - - suite.webComputedDestinationsData = &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: resource.Reference(suite.api1Service.Id, ""), - DestinationPort: "tcp", - }, - { - DestinationRef: resource.Reference(suite.api2Service.Id, ""), - DestinationPort: "tcp1", - }, - { - DestinationRef: resource.Reference(suite.api2Service.Id, ""), - DestinationPort: "tcp2", - }, - }, - } - - suite.webProxy = resourcetest.Resource(pbmesh.ProxyStateTemplateType, "web-abc"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{}). - Write(suite.T(), suite.client) - - suite.webWorkload = resourcetest.Resource(pbcatalog.WorkloadType, "web-abc"). - WithData(suite.T(), &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "10.0.0.2"}}, - Ports: map[string]*pbcatalog.WorkloadPort{"tcp": {Port: 8081, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}}, - }). - Write(suite.T(), suite.client) -} - -func (suite *dataFetcherSuite) TestFetcher_FetchWorkload_WorkloadNotFound() { - identityID := resourcetest.Resource(pbauth.WorkloadIdentityType, "workload-identity-abc").ID() - - // Create cache and pre-populate it. - c := cache.New() - - f := Fetcher{ - cache: c, - client: suite.client, - } - - workloadID := resourcetest.Resource(pbcatalog.WorkloadType, "not-found").ID() - - // Track workload with its identity. - workload := resourcetest.Resource(pbcatalog.WorkloadType, workloadID.GetName()). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), &pbcatalog.Workload{ - Identity: identityID.Name, - }).Build() - - c.TrackWorkload(resourcetest.MustDecode[*pbcatalog.Workload](suite.T(), workload)) - - // Now fetch the workload so that we can check that it's been removed from cache. - _, err := f.FetchWorkload(context.Background(), workloadID) - require.NoError(suite.T(), err) - require.Nil(suite.T(), c.WorkloadsByWorkloadIdentity(identityID)) -} - -func (suite *dataFetcherSuite) TestFetcher_FetchWorkload_WorkloadFound() { - identityID := resourcetest.Resource(pbauth.WorkloadIdentityType, "workload-identity-abc").ID() - - // Create cache and pre-populate it. - c := cache.New() - - f := Fetcher{ - cache: c, - client: suite.client, - } - - workload := resourcetest.Resource(pbcatalog.WorkloadType, "service-workload-abc"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), &pbcatalog.Workload{ - Identity: identityID.Name, - Ports: map[string]*pbcatalog.WorkloadPort{ - "foo": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.0.0.1", - Ports: []string{"foo"}, - }, - }, - }).Write(suite.T(), suite.client) - - // This call should track the workload's identity - _, err := f.FetchWorkload(context.Background(), workload.Id) - require.NoError(suite.T(), err) - - // Check that the workload is tracked - workload.Id.Uid = "" - prototest.AssertElementsMatch(suite.T(), []*pbresource.ID{workload.Id}, c.WorkloadsByWorkloadIdentity(identityID)) -} - -func (suite *dataFetcherSuite) TestFetcher_FetchExplicitDestinationsData() { - c := cache.New() - - var ( - api1ServiceRef = resource.Reference(suite.api1Service.Id, "") - ) - - f := Fetcher{ - cache: c, - client: suite.client, - } - - testutil.RunStep(suite.T(), "computed destinations not found", func(t *testing.T) { - // First add computed destination to cache so we can check if it's untracked later. - compDest := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.webProxy.Id.Name). - WithData(t, &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: api1ServiceRef, - DestinationPort: "tcp1", - }, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Build() - c.TrackComputedDestinations(resourcetest.MustDecode[*pbmesh.ComputedExplicitDestinations](t, compDest)) - - // We will try to fetch explicit destinations for a proxy that doesn't have one. - destinations, err := f.FetchExplicitDestinationsData(suite.ctx, suite.webProxy.Id) - require.NoError(t, err) - require.Nil(t, destinations) - - // Check that cache no longer has this destination. - require.Nil(t, c.ComputedDestinationsByService(resource.IDFromReference(api1ServiceRef))) - }) - - testutil.RunStep(suite.T(), "invalid destinations: service not found", func(t *testing.T) { - notFoundServiceRef := resourcetest.Resource(pbcatalog.ServiceType, "not-found"). - WithTenancy(resource.DefaultNamespacedTenancy()). - ReferenceNoSection() - - compDest := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.webProxy.Id.Name). - WithData(t, &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: notFoundServiceRef, - DestinationPort: "tcp", - }, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Write(t, suite.client) - - destinations, err := f.FetchExplicitDestinationsData(suite.ctx, suite.webProxy.Id) - require.NoError(t, err) - require.Nil(t, destinations) - cachedCompDestIDs := c.ComputedDestinationsByService(resource.IDFromReference(notFoundServiceRef)) - compDest.Id.Uid = "" - prototest.AssertElementsMatch(t, []*pbresource.ID{compDest.Id}, cachedCompDestIDs) - }) - - testutil.RunStep(suite.T(), "invalid destinations: service not on mesh", func(t *testing.T) { - apiNonMeshServiceData := &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - }, - } - resourcetest.ResourceID(suite.api1Service.Id). - WithData(t, apiNonMeshServiceData). - Write(t, suite.client) - compDest := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.webProxy.Id.Name). - WithData(t, &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: api1ServiceRef, - DestinationPort: "tcp", - }, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Write(t, suite.client) - - destinations, err := f.FetchExplicitDestinationsData(suite.ctx, suite.webProxy.Id) - require.NoError(t, err) - require.Nil(t, destinations) - cachedCompDestIDs := c.ComputedDestinationsByService(resource.IDFromReference(api1ServiceRef)) - compDest.Id.Uid = "" - prototest.AssertElementsMatch(t, []*pbresource.ID{compDest.Id}, cachedCompDestIDs) - }) - - testutil.RunStep(suite.T(), "invalid destinations: destination port not found", func(t *testing.T) { - resourcetest.ResourceID(suite.api1Service.Id). - WithData(t, &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "some-other-port", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }). - Write(t, suite.client) - compDest := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.webProxy.Id.Name). - WithData(t, &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: api1ServiceRef, - DestinationPort: "tcp", - }, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Write(t, suite.client) - - destinations, err := f.FetchExplicitDestinationsData(suite.ctx, suite.webProxy.Id) - require.NoError(t, err) - require.Nil(t, destinations) - cachedCompDestIDs := c.ComputedDestinationsByService(resource.IDFromReference(api1ServiceRef)) - compDest.Id.Uid = "" - prototest.AssertElementsMatch(t, []*pbresource.ID{compDest.Id}, cachedCompDestIDs) - }) - - suite.api1Service = resourcetest.ResourceID(suite.api1Service.Id). - WithData(suite.T(), suite.api1ServiceData). - Write(suite.T(), suite.client) - - suite.api2Service = resourcetest.ResourceID(suite.api2Service.Id). - WithData(suite.T(), suite.api2ServiceData). - Write(suite.T(), suite.client) - - testutil.RunStep(suite.T(), "invalid destinations: destination is pointing to a mesh port", func(t *testing.T) { - // Create a computed destinations resource pointing to the mesh port. - compDest := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.webProxy.Id.Name). - WithData(t, &pbmesh.ComputedExplicitDestinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: api1ServiceRef, - DestinationPort: "mesh", - }, - }, - }). - WithTenancy(resource.DefaultNamespacedTenancy()). - Write(t, suite.client) - - destinations, err := f.FetchExplicitDestinationsData(suite.ctx, suite.webProxy.Id) - require.NoError(t, err) - require.Empty(t, destinations) - - cachedCompDestIDs := c.ComputedDestinationsByService(resource.IDFromReference(api1ServiceRef)) - compDest.Id.Uid = "" - prototest.AssertElementsMatch(t, []*pbresource.ID{compDest.Id}, cachedCompDestIDs) - }) - - compDest := resourcetest.Resource(pbmesh.ComputedExplicitDestinationsType, suite.webProxy.Id.Name). - WithData(suite.T(), suite.webComputedDestinationsData). - WithTenancy(resource.DefaultNamespacedTenancy()). - Write(suite.T(), suite.client) - - testutil.RunStep(suite.T(), "invalid destinations: destination is pointing to a port but computed routes is not aware of it yet", func(t *testing.T) { - apiNonTCPServiceData := &pbcatalog.Service{ - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - } - apiNonTCPService := resourcetest.ResourceID(suite.api1Service.Id). - WithData(t, apiNonTCPServiceData). - Build() - - api1ComputedRoutesID := resource.ReplaceType(pbmesh.ComputedRoutesType, suite.api1Service.Id) - api1ComputedRoutes := routestest.ReconcileComputedRoutes(suite.T(), suite.client, api1ComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](suite.T(), apiNonTCPService), - ) - require.NotNil(suite.T(), api1ComputedRoutes) - - // This destination points to TCP, but the computed routes is stale and only knows about HTTP. - destinations, err := f.FetchExplicitDestinationsData(suite.ctx, suite.webProxy.Id) - require.NoError(t, err) - - // Check that we didn't return any destinations. - require.Nil(t, destinations) - - // Check that destination service is still in cache because it's still referenced from the pbmesh.Destinations - // resource. - cachedCompDestIDs := c.ComputedDestinationsByService(resource.IDFromReference(api1ServiceRef)) - compDest.Id.Uid = "" - prototest.AssertElementsMatch(t, []*pbresource.ID{compDest.Id}, cachedCompDestIDs) - }) - - testutil.RunStep(suite.T(), "happy path", func(t *testing.T) { - // Write a default ComputedRoutes for api1 and api2. - var ( - api1ComputedRoutesID = resource.ReplaceType(pbmesh.ComputedRoutesType, suite.api1Service.Id) - api2ComputedRoutesID = resource.ReplaceType(pbmesh.ComputedRoutesType, suite.api2Service.Id) - ) - api1ComputedRoutes := routestest.ReconcileComputedRoutes(suite.T(), suite.client, api1ComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api1Service), - ) - require.NotNil(suite.T(), api1ComputedRoutes) - api2ComputedRoutes := routestest.ReconcileComputedRoutes(suite.T(), suite.client, api2ComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api2Service), - ) - require.NotNil(suite.T(), api2ComputedRoutes) - - resourcetest.ResourceID(suite.api1Service.Id) - - expectedDestinations := []*intermediate.Destination{ - { - Explicit: suite.webComputedDestinationsData.Destinations[0], - Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api1Service), - ComputedPortRoutes: routestest.MutateTargets(suite.T(), api1ComputedRoutes.Data, "tcp", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(suite.api1Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp": - se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api1ServiceEndpoints) - details.ServiceEndpointsId = se.Resource.Id - details.ServiceEndpoints = se.Data - details.IdentityRefs = []*pbresource.Reference{{ - Name: "api-1-identity", - Tenancy: suite.api1Service.Id.Tenancy, - }} - } - }), - }, - { - Explicit: suite.webComputedDestinationsData.Destinations[1], - Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api2Service), - ComputedPortRoutes: routestest.MutateTargets(suite.T(), api2ComputedRoutes.Data, "tcp1", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(suite.api2Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp1": - se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api2ServiceEndpoints) - details.ServiceEndpointsId = se.Resource.Id - details.ServiceEndpoints = se.Data - details.IdentityRefs = []*pbresource.Reference{{ - Name: "api-2-identity", - Tenancy: suite.api2Service.Id.Tenancy, - }} - } - }), - }, - { - Explicit: suite.webComputedDestinationsData.Destinations[2], - Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api2Service), - ComputedPortRoutes: routestest.MutateTargets(suite.T(), api2ComputedRoutes.Data, "tcp2", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(suite.api2Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp2": - se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api2ServiceEndpoints) - details.ServiceEndpointsId = se.Resource.Id - details.ServiceEndpoints = se.Data - details.IdentityRefs = []*pbresource.Reference{{ - Name: "api-2-identity", - Tenancy: suite.api2Service.Id.Tenancy, - }} - } - }), - }, - } - - actualDestinations, err := f.FetchExplicitDestinationsData(suite.ctx, suite.webProxy.Id) - require.NoError(t, err) - - // Check that we've computed expanded destinations correctly. - prototest.AssertElementsMatch(t, expectedDestinations, actualDestinations) - }) -} - -func (suite *dataFetcherSuite) TestFetcher_FetchImplicitDestinationsData() { - // Create a few other services to be implicit upstreams. - api3Service := resourcetest.Resource(pbcatalog.ServiceType, "api-3"). - WithData(suite.T(), &pbcatalog.Service{ - VirtualIps: []string{"192.1.1.1"}, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", VirtualPort: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", VirtualPort: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }). - Write(suite.T(), suite.client) - - api3ServiceEndpointsData := &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - TargetRef: &pbresource.ID{ - Name: "api-3-abc", - Tenancy: api3Service.Id.Tenancy, - Type: pbcatalog.WorkloadType, - }, - Addresses: []*pbcatalog.WorkloadAddress{{Host: "10.0.0.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - Identity: "api-3-identity", - }, - }, - } - api3ServiceEndpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, "api-3"). - WithData(suite.T(), api3ServiceEndpointsData). - Write(suite.T(), suite.client) - - // Write a default ComputedRoutes for api1, api2, and api3. - var ( - api1ComputedRoutesID = resource.ReplaceType(pbmesh.ComputedRoutesType, suite.api1Service.Id) - api2ComputedRoutesID = resource.ReplaceType(pbmesh.ComputedRoutesType, suite.api2Service.Id) - api3ComputedRoutesID = resource.ReplaceType(pbmesh.ComputedRoutesType, api3Service.Id) - ) - api1ComputedRoutes := routestest.ReconcileComputedRoutes(suite.T(), suite.client, api1ComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api1Service), - ) - require.NotNil(suite.T(), api1ComputedRoutes) - api2ComputedRoutes := routestest.ReconcileComputedRoutes(suite.T(), suite.client, api2ComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api2Service), - ) - require.NotNil(suite.T(), api2ComputedRoutes) - api3ComputedRoutes := routestest.ReconcileComputedRoutes(suite.T(), suite.client, api3ComputedRoutesID, - resourcetest.MustDecode[*pbcatalog.Service](suite.T(), api3Service), - ) - require.NotNil(suite.T(), api3ComputedRoutes) - - existingDestinations := []*intermediate.Destination{ - { - Explicit: suite.webComputedDestinationsData.Destinations[0], - Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api1Service), - ComputedPortRoutes: routestest.MutateTargets(suite.T(), api1ComputedRoutes.Data, "tcp", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(suite.api1Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp": - se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api1ServiceEndpoints) - details.ServiceEndpointsId = se.Resource.Id - details.ServiceEndpoints = se.Data - details.IdentityRefs = []*pbresource.Reference{{ - Name: "api-1-identity", - Tenancy: suite.api1Service.Id.Tenancy, - }} - } - }), - }, - { - Explicit: suite.webComputedDestinationsData.Destinations[1], - Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api2Service), - ComputedPortRoutes: routestest.MutateTargets(suite.T(), api2ComputedRoutes.Data, "tcp1", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(suite.api2Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp1": - se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api2ServiceEndpoints) - details.ServiceEndpointsId = se.Resource.Id - details.ServiceEndpoints = se.Data - details.IdentityRefs = []*pbresource.Reference{{ - Name: "api-2-identity", - Tenancy: suite.api1Service.Id.Tenancy, - }} - } - }), - }, - { - Explicit: suite.webComputedDestinationsData.Destinations[2], - Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), suite.api2Service), - ComputedPortRoutes: routestest.MutateTargets(suite.T(), api2ComputedRoutes.Data, "tcp2", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(suite.api2Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp2": - se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), suite.api2ServiceEndpoints) - details.ServiceEndpointsId = se.Resource.Id - details.ServiceEndpoints = se.Data - details.IdentityRefs = []*pbresource.Reference{{ - Name: "api-2-identity", - Tenancy: suite.api1Service.Id.Tenancy, - }} - } - }), - }, - { - // implicit - Service: resourcetest.MustDecode[*pbcatalog.Service](suite.T(), api3Service), - ComputedPortRoutes: routestest.MutateTargets(suite.T(), api3ComputedRoutes.Data, "tcp", func(t *testing.T, details *pbmesh.BackendTargetDetails) { - switch { - case resource.ReferenceOrIDMatch(api3Service.Id, details.BackendRef.Ref) && details.BackendRef.Port == "tcp": - se := resourcetest.MustDecode[*pbcatalog.ServiceEndpoints](suite.T(), api3ServiceEndpoints) - details.ServiceEndpointsId = se.Resource.Id - details.ServiceEndpoints = se.Data - details.IdentityRefs = []*pbresource.Reference{{ - Name: "api-3-identity", - Tenancy: suite.api1Service.Id.Tenancy, - }} - } - }), - VirtualIPs: []string{"192.1.1.1"}, - }, - } - - f := Fetcher{ - client: suite.client, - } - - actualDestinations, err := f.FetchImplicitDestinationsData(context.Background(), suite.webProxy.Id, existingDestinations) - require.NoError(suite.T(), err) - - prototest.AssertElementsMatch(suite.T(), existingDestinations, actualDestinations) -} - -func TestDataFetcher(t *testing.T) { - suite.Run(t, new(dataFetcherSuite)) -} diff --git a/internal/mesh/internal/controllers/xds/controller.go b/internal/mesh/internal/controllers/xds/controller.go deleted file mode 100644 index 678cfd0539d8..000000000000 --- a/internal/mesh/internal/controllers/xds/controller.go +++ /dev/null @@ -1,418 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "context" - "fmt" - "time" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/cacheshim" - "github.com/hashicorp/consul/agent/leafcert" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/xds/status" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" - "github.com/hashicorp/consul/lib" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ControllerName = "consul.io/xds-controller" - -const defaultTenancy = "default" - -func Controller(endpointsMapper *bimapper.Mapper, updater ProxyUpdater, fetcher TrustBundleFetcher, leafCertManager *leafcert.Manager, leafMapper *LeafMapper, leafCancels *LeafCancels, datacenter string) controller.Controller { - leafCertEvents := make(chan controller.Event, 1000) - if endpointsMapper == nil || fetcher == nil || leafCertManager == nil || leafMapper == nil || datacenter == "" { - panic("endpointsMapper, updater, fetcher, leafCertManager, leafMapper, and datacenter are required") - } - - return controller.ForType(pbmesh.ProxyStateTemplateType). - WithWatch(pbcatalog.ServiceEndpointsType, endpointsMapper.MapLink). - WithCustomWatch(proxySource(updater), proxyMapper). - WithCustomWatch(&controller.Source{Source: leafCertEvents}, leafMapper.EventMapLink). - WithPlacement(controller.PlacementEachServer). - WithReconciler(&xdsReconciler{endpointsMapper: endpointsMapper, updater: updater, fetchTrustBundle: fetcher, leafCertManager: leafCertManager, leafCancels: leafCancels, leafCertEvents: leafCertEvents, leafMapper: leafMapper, datacenter: datacenter}) -} - -type xdsReconciler struct { - // Fields for fetching and watching endpoints. - endpointsMapper *bimapper.Mapper - // Fields for proxy management. - updater ProxyUpdater - // Fields for fetching and watching trust bundles. - fetchTrustBundle TrustBundleFetcher - // Fields for fetching and watching leaf certificates. - leafCertManager *leafcert.Manager - leafMapper *LeafMapper - leafCancels *LeafCancels - leafCertEvents chan controller.Event - datacenter string -} - -type TrustBundleFetcher func() (*pbproxystate.TrustBundle, error) - -// ProxyUpdater is an interface that defines the ability to push proxy updates to the updater -// and also check its connectivity to the server. -type ProxyUpdater interface { - // PushChange allows pushing a computed ProxyState to xds for xds resource generation to send to a proxy. - PushChange(id *pbresource.ID, snapshot proxysnapshot.ProxySnapshot) error - - // ProxyConnectedToServer returns whether this id is connected to this server. - ProxyConnectedToServer(id *pbresource.ID) (string, bool) - - // EventChannel returns a channel of events that are consumed by the Custom Watcher. - EventChannel() chan controller.Event -} - -func (r *xdsReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", ControllerName) - - rt.Logger.Trace("reconciling proxy state template", "id", req.ID) - - // Get the ProxyStateTemplate. - proxyStateTemplate, err := getProxyStateTemplate(ctx, rt, req.ID) - if err != nil { - rt.Logger.Error("error reading proxy state template", "error", err) - return err - } - - token, proxyConnected := r.updater.ProxyConnectedToServer(req.ID) - - if proxyStateTemplate == nil || proxyStateTemplate.Template == nil || !proxyConnected { - rt.Logger.Trace("proxy state template has been deleted or this controller is not responsible for this proxy state template", "id", req.ID) - - // If the proxy state template (PST) was deleted, we should: - // 1. Remove references from endpoints mapper. - // 2. Remove references from leaf mapper. - // 3. Cancel all leaf watches. - - // 1. Remove PST from endpoints mapper. - r.endpointsMapper.UntrackItem(req.ID) - // Grab the leafs related to this PST before untracking the PST so we know which ones to cancel. - leafLinks := r.leafMapper.LinkRefsForItem(req.ID) - // 2. Remove PST from leaf mapper. - r.leafMapper.UntrackItem(req.ID) - - // 3. Cancel watches for leafs that were related to this PST as long as it's not referenced by any other PST. - r.cancelWatches(leafLinks) - - return nil - } - - var ( - statusCondition *pbresource.Condition - pstResource *pbresource.Resource - ) - pstResource = proxyStateTemplate.Resource - - if proxyStateTemplate.Template.ProxyState == nil { - rt.Logger.Error("proxy state was missing from proxy state template") - // Set the status. - statusCondition = status.ConditionRejectedNilProxyState(status.KeyFromID(req.ID)) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - - return err - } - - // TODO: Fetch trust bundles for all peers when peering is supported. - trustBundle, err := r.fetchTrustBundle() - if err != nil { - rt.Logger.Error("error fetching root trust bundle", "error", err) - // Set the status. - statusCondition = status.ConditionRejectedTrustBundleFetchFailed(status.KeyFromID(req.ID)) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - return err - } - - // Initialize ProxyState maps. - if proxyStateTemplate.Template.ProxyState.TrustBundles == nil { - proxyStateTemplate.Template.ProxyState.TrustBundles = make(map[string]*pbproxystate.TrustBundle) - } - // TODO: Figure out the correct key for the default trust bundle. - proxyStateTemplate.Template.ProxyState.TrustBundles["local"] = trustBundle - - if proxyStateTemplate.Template.ProxyState.Endpoints == nil { - proxyStateTemplate.Template.ProxyState.Endpoints = make(map[string]*pbproxystate.Endpoints) - } - if proxyStateTemplate.Template.ProxyState.LeafCertificates == nil { - proxyStateTemplate.Template.ProxyState.LeafCertificates = make(map[string]*pbproxystate.LeafCertificate) - } - - // Iterate through the endpoint references. - // For endpoints, the controller should: - // 1. Resolve ServiceEndpoint references - // 2. Translate them into pbproxystate.Endpoints - // 3. Add the pbproxystate.Endpoints to the ProxyState endpoints map. - // 4. Track relationships between ProxyState and ServiceEndpoints, such that we can look up ServiceEndpoints and - // figure out which ProxyStates are associated with it (for mapping watches) and vice versa (for looking up - // references). The bimapper package is useful for tracking these relationships. - endpointReferencesMap := proxyStateTemplate.Template.RequiredEndpoints - var endpointsInProxyStateTemplate []resource.ReferenceOrID - for xdsClusterName, endpointRef := range endpointReferencesMap { - - // Step 1: Resolve the reference by looking up the ServiceEndpoints. - // serviceEndpoints will not be nil unless there is an error. - // - // TODO(rb/v2): note we should expose a flag on the endpointRef indicating if the user - // wants the absence of an Endpoints to imply returning a slice of no data, vs failing outright. - // In xdsv1 we call this the "allowEmpty" semantic. Here we are assuming "allowEmpty=true" - var psEndpoints *pbproxystate.Endpoints - if endpointRef.Id != nil { - serviceEndpoints, err := getServiceEndpoints(ctx, rt, endpointRef.Id) - if err != nil { - rt.Logger.Error("error reading service endpoint", "id", endpointRef.Id, "error", err) - // Set the status. - statusCondition = status.ConditionRejectedErrorReadingEndpoints(status.KeyFromID(endpointRef.Id), err.Error()) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - - return err - } - - // Step 2: Translate it into pbproxystate.Endpoints. - psEndpoints, err = generateProxyStateEndpoints(serviceEndpoints, endpointRef.Port) - if err != nil { - rt.Logger.Error("error translating service endpoints to proxy state endpoints", "endpoint", endpointRef.Id, "error", err) - - // Set the status. - statusCondition = status.ConditionRejectedCreatingProxyStateEndpoints(status.KeyFromID(endpointRef.Id), err.Error()) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - - return err - } - } else { - psEndpoints = &pbproxystate.Endpoints{} - } - - // Step 3: Add the endpoints to ProxyState. - proxyStateTemplate.Template.ProxyState.Endpoints[xdsClusterName] = psEndpoints - - if endpointRef.Id != nil { - // Track all the endpoints that are used by this ProxyStateTemplate, so we can use this for step 4. - endpointResourceRef := resource.Reference(endpointRef.Id, "") - endpointsInProxyStateTemplate = append(endpointsInProxyStateTemplate, endpointResourceRef) - } - } - - // Step 4: Track relationships between ProxyStateTemplates and ServiceEndpoints. - r.endpointsMapper.TrackItem(req.ID, endpointsInProxyStateTemplate) - if len(endpointsInProxyStateTemplate) == 0 { - r.endpointsMapper.UntrackItem(req.ID) - } - - // Iterate through leaf certificate references. - // For each leaf certificate reference, the controller should: - // 1. Setup a watch for the leaf certificate so that the leaf cert manager will generate and store a leaf - // certificate if it's not already in the leaf cert manager cache. - // 1a. Store a cancel function for that leaf certificate watch. - // 2. Get the leaf certificate from the leaf cert manager. (This should succeed if a watch has been set up). - // 3. Put the leaf certificate contents into the ProxyState leaf certificates map. - // 4. Track relationships between ProxyState and leaf certificates using a bimapper. - leafReferencesMap := proxyStateTemplate.Template.RequiredLeafCertificates - var leafsInProxyStateTemplate []resource.ReferenceOrID - for workloadIdentityName, leafRef := range leafReferencesMap { - - // leafRef must include the namespace and partition - leafResourceReference := leafResourceRef(leafRef.Name, leafRef.Namespace, leafRef.Partition) - leafKey := keyFromReference(leafResourceReference) - leafRequest := &leafcert.ConnectCALeafRequest{ - Token: token, - WorkloadIdentity: leafRef.Name, - EnterpriseMeta: acl.NewEnterpriseMetaWithPartition(leafRef.Partition, leafRef.Namespace), - // Add some jitter to the max query time so that all goroutines don't wake up at approximately the same time. - // Without this, it's likely that these queries will all fire at roughly the same time, because the server - // will have spawned many watches immediately on boot. Typically because the index number will not have changed, - // this controller will not be notified anyway, but it's still better to space out the waking of goroutines. - MaxQueryTime: (10 * time.Minute) + lib.RandomStagger(10*time.Minute), - } - - // Step 1: Setup a watch for this leaf if one doesn't already exist. - if _, ok := r.leafCancels.Get(leafKey); !ok { - certWatchContext, cancel := context.WithCancel(ctx) - err = r.leafCertManager.NotifyCallback(certWatchContext, leafRequest, "", func(ctx context.Context, event cacheshim.UpdateEvent) { - cert, ok := event.Result.(*structs.IssuedCert) - if !ok { - panic("wrong type") - } - if cert == nil { - return - } - controllerEvent := controller.Event{ - Obj: cert, - } - select { - // This callback function is running in its own goroutine, so blocking inside this goroutine to send the - // update event doesn't affect the controller or other leaf certificates. r.leafCertEvents is a buffered - // channel, which should constantly be consumed by the controller custom events queue. If the controller - // custom events consumer isn't clearing up the leafCertEvents channel, then that would be the main - // issue to address, as opposed to this goroutine blocking. - case r.leafCertEvents <- controllerEvent: - // This context is the certWatchContext, so we will reach this case if the watch is canceled, and exit - // the callback goroutine. - case <-ctx.Done(): - } - }) - if err != nil { - rt.Logger.Error("error creating leaf watch", "leafRef", leafResourceReference, "error", err) - // Set the status. - statusCondition = status.ConditionRejectedErrorCreatingLeafWatch(keyFromReference(leafResourceReference), err.Error()) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - - cancel() - return err - } - r.leafCancels.Set(leafKey, cancel) - } - - // Step 2: Get the leaf certificate. - cert, _, err := r.leafCertManager.Get(ctx, leafRequest) - if err != nil { - rt.Logger.Error("error getting leaf", "leafRef", leafResourceReference, "error", err) - // Set the status. - statusCondition = status.ConditionRejectedErrorGettingLeaf(keyFromReference(leafResourceReference), err.Error()) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - - return err - } - - // Create the pbproxystate.LeafCertificate out of the structs.IssuedCert returned from the manager. - psLeaf := generateProxyStateLeafCertificates(cert) - if psLeaf == nil { - rt.Logger.Error("error getting leaf certificate contents", "leafRef", leafResourceReference) - - // Set the status. - statusCondition = status.ConditionRejectedErrorCreatingProxyStateLeaf(keyFromReference(leafResourceReference), err.Error()) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - - return err - } - - // Step 3: Add the leaf certificate to ProxyState. - proxyStateTemplate.Template.ProxyState.LeafCertificates[workloadIdentityName] = psLeaf - - // Track all the leaf certificates that are used by this ProxyStateTemplate, so we can use this for step 4. - leafsInProxyStateTemplate = append(leafsInProxyStateTemplate, leafResourceReference) - - } - // Get the previously tracked leafs for this ProxyStateTemplate so we can use this to cancel watches in step 5. - prevWatchedLeafs := r.leafMapper.LinkRefsForItem(req.ID) - - // Step 4: Track relationships between ProxyStateTemplates and leaf certificates for the current leafs referenced in - // ProxyStateTemplate. - r.leafMapper.TrackItem(req.ID, leafsInProxyStateTemplate) - - // Step 5: Compute whether there are leafs that are no longer referenced by this proxy state template, and cancel - // watches for them if they aren't referenced anywhere. - watches := prevWatchesToCancel(prevWatchedLeafs, leafsInProxyStateTemplate) - r.cancelWatches(watches) - - // Now that the references have been resolved, push the computed proxy state to the updater. - computedProxyState := proxyStateTemplate.Template.ProxyState - - err = r.updater.PushChange(req.ID, &proxytracker.ProxyState{ProxyState: computedProxyState}) - if err != nil { - // Set the status. - statusCondition = status.ConditionRejectedPushChangeFailed(status.KeyFromID(req.ID)) - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - return err - } - - // Set the status. - statusCondition = status.ConditionAccepted() - status.WriteStatusIfChanged(ctx, rt, pstResource, statusCondition) - return nil -} - -// leafResourceRef translates a leaf certificate reference in ProxyState template to an internal resource reference. The -// bimapper package uses resource references, so we use an internal type to create a leaf resource reference since leaf -// certificates are not v2 resources. -func leafResourceRef(workloadIdentity, namespace, partition string) *pbresource.Reference { - // Since leaf certificate references aren't resources in the resource API, we don't have the same guarantees that - // namespace and partition are set. So this is to ensure that we always do set values for tenancy. - if namespace == "" { - namespace = defaultTenancy - } - if partition == "" { - partition = defaultTenancy - } - ref := &pbresource.Reference{ - Name: workloadIdentity, - Type: InternalLeafType, - Tenancy: &pbresource.Tenancy{ - Partition: partition, - Namespace: namespace, - }, - } - return ref -} - -// InternalLeafType sets up an internal resource type to use for leaf certificates, since they are not yet a v2 -// resource. It's exported because it's used by the mesh controller registration which needs to set up the bimapper for -// leaf certificates. -var InternalLeafType = &pbresource.Type{ - Group: "internal", - GroupVersion: "v2beta1", - Kind: "leaf", -} - -// keyFromReference is used to create string keys from resource references. -func keyFromReference(ref resource.ReferenceOrID) string { - return fmt.Sprintf("%s/%s/%s", - resource.ToGVK(ref.GetType()), - tenancyToString(ref.GetTenancy()), - ref.GetName()) -} - -func tenancyToString(tenancy *pbresource.Tenancy) string { - return fmt.Sprintf("%s.%s", tenancy.Partition, tenancy.Namespace) -} - -// generateProxyStateLeafCertificates translates a *structs.IssuedCert into a *pbproxystate.LeafCertificate. -func generateProxyStateLeafCertificates(cert *structs.IssuedCert) *pbproxystate.LeafCertificate { - if cert.CertPEM == "" || cert.PrivateKeyPEM == "" { - return nil - } - return &pbproxystate.LeafCertificate{ - Cert: cert.CertPEM, - Key: cert.PrivateKeyPEM, - } -} - -// cancelWatches cancels watches for leafs that no longer need to be watched, as long as it is referenced by zero ProxyStateTemplates. -func (r *xdsReconciler) cancelWatches(leafResourceRefs []*pbresource.Reference) { - for _, leaf := range leafResourceRefs { - pstItems := r.leafMapper.ItemRefsForLink(leaf) - if len(pstItems) > 0 { - // Don't delete and cancel watches, since this leaf is referenced elsewhere. - continue - } - cancel, ok := r.leafCancels.Get(keyFromReference(leaf)) - if ok { - cancel() - r.leafCancels.Delete(keyFromReference(leaf)) - } - } -} - -// prevWatchesToCancel computes if there are any items in prevWatchedLeafs that are not in currentLeafs, and returns a list of those items. -func prevWatchesToCancel(prevWatchedLeafs []*pbresource.Reference, currentLeafs []resource.ReferenceOrID) []*pbresource.Reference { - prevWatchedLeafsToCancel := make([]*pbresource.Reference, 0, len(prevWatchedLeafs)) - newLeafs := make(map[string]struct{}) - for _, newLeaf := range currentLeafs { - newLeafs[keyFromReference(newLeaf)] = struct{}{} - } - for _, prevLeaf := range prevWatchedLeafs { - if _, ok := newLeafs[keyFromReference(prevLeaf)]; !ok { - prevWatchedLeafsToCancel = append(prevWatchedLeafsToCancel, prevLeaf) - } - } - return prevWatchedLeafsToCancel -} diff --git a/internal/mesh/internal/controllers/xds/controller_test.go b/internal/mesh/internal/controllers/xds/controller_test.go deleted file mode 100644 index 15c4536e5582..000000000000 --- a/internal/mesh/internal/controllers/xds/controller_test.go +++ /dev/null @@ -1,1169 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "context" - "crypto/x509" - "encoding/pem" - "fmt" - "strings" - "testing" - - "github.com/hashicorp/consul/internal/testing/golden" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - "google.golang.org/protobuf/encoding/protojson" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/agent/leafcert" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/controllers/xds/status" - "github.com/hashicorp/consul/internal/mesh/internal/types" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" -) - -type xdsControllerTestSuite struct { - suite.Suite - - ctx context.Context - client *resourcetest.Client - runtime controller.Runtime - - ctl *xdsReconciler - mapper *bimapper.Mapper - updater *mockUpdater - fetcher TrustBundleFetcher - leafMapper *LeafMapper - leafCertManager *leafcert.Manager - leafCancels *LeafCancels - leafCertEvents chan controller.Event - signer *leafcert.TestSigner - - fooProxyStateTemplate *pbresource.Resource - barProxyStateTemplate *pbresource.Resource - barEndpointRefs map[string]*pbproxystate.EndpointRef - fooEndpointRefs map[string]*pbproxystate.EndpointRef - fooLeafRefs map[string]*pbproxystate.LeafCertificateRef - fooEndpoints *pbresource.Resource - fooService *pbresource.Resource - fooBarEndpoints *pbresource.Resource - fooBarService *pbresource.Resource - expectedFooProxyStateEndpoints map[string]*pbproxystate.Endpoints - expectedBarProxyStateEndpoints map[string]*pbproxystate.Endpoints - expectedFooProxyStateSpiffes map[string]string - expectedTrustBundle map[string]*pbproxystate.TrustBundle -} - -func (suite *xdsControllerTestSuite) SetupTest() { - suite.ctx = testutil.TestContext(suite.T()) - resourceClient := svctest.RunResourceService(suite.T(), types.Register, catalog.RegisterTypes) - suite.runtime = controller.Runtime{Client: resourceClient, Logger: testutil.Logger(suite.T())} - suite.client = resourcetest.NewClient(resourceClient) - suite.fetcher = mockFetcher - - suite.mapper = bimapper.New(pbmesh.ProxyStateTemplateType, pbcatalog.ServiceEndpointsType) - suite.updater = newMockUpdater() - - suite.leafMapper = &LeafMapper{ - bimapper.New(pbmesh.ProxyStateTemplateType, InternalLeafType), - } - lcm, signer := leafcert.NewTestManager(suite.T(), nil) - signer.UpdateCA(suite.T(), nil) - suite.signer = signer - suite.leafCertManager = lcm - suite.leafCancels = &LeafCancels{ - Cancels: make(map[string]context.CancelFunc), - } - suite.leafCertEvents = make(chan controller.Event, 1000) - - suite.ctl = &xdsReconciler{ - endpointsMapper: suite.mapper, - updater: suite.updater, - fetchTrustBundle: suite.fetcher, - leafMapper: suite.leafMapper, - leafCertManager: suite.leafCertManager, - leafCancels: suite.leafCancels, - leafCertEvents: suite.leafCertEvents, - datacenter: "dc1", - } -} - -func mockFetcher() (*pbproxystate.TrustBundle, error) { - var bundle pbproxystate.TrustBundle - bundle = pbproxystate.TrustBundle{ - TrustDomain: "some-trust-domain", - Roots: []string{"some-root", "some-other-root"}, - } - return &bundle, nil -} - -// This test ensures when a ProxyState is deleted, it is no longer tracked in the mappers. -func (suite *xdsControllerTestSuite) TestReconcile_NoProxyStateTemplate() { - // Track the id of a non-existent ProxyStateTemplate. - proxyStateTemplateId := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "not-found").ID() - suite.mapper.TrackItem(proxyStateTemplateId, []resource.ReferenceOrID{}) - suite.leafMapper.TrackItem(proxyStateTemplateId, []resource.ReferenceOrID{}) - require.False(suite.T(), suite.mapper.IsEmpty()) - require.False(suite.T(), suite.leafMapper.IsEmpty()) - - // Run the reconcile, and since no ProxyStateTemplate is stored, this simulates a deletion. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: proxyStateTemplateId, - }) - require.NoError(suite.T(), err) - - // Assert that nothing is tracked in the endpoints mapper. - require.True(suite.T(), suite.mapper.IsEmpty()) - require.True(suite.T(), suite.leafMapper.IsEmpty()) -} - -// This test ensures if the controller was previously tracking a ProxyStateTemplate, and now that proxy has -// disconnected from this server, it's ignored and removed from the mapper. -func (suite *xdsControllerTestSuite) TestReconcile_RemoveTrackingProxiesNotConnectedToServer() { - // Store the initial ProxyStateTemplate and track it in the mapper. - proxyStateTemplate := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{}). - Write(suite.T(), suite.client) - - suite.mapper.TrackItem(proxyStateTemplate.Id, []resource.ReferenceOrID{}) - - // Simulate the proxy disconnecting from this server. The resource still exists, but this proxy might be connected - // to a different server now, so we no longer need to track it. - suite.updater.notConnected = true - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: proxyStateTemplate.Id, - }) - require.NoError(suite.T(), err) - - // Assert that nothing is tracked in the mapper. - require.True(suite.T(), suite.mapper.IsEmpty()) -} - -// This test sets up the updater to return an error when calling PushChange, and ensures the status is set -// correctly. -func (suite *xdsControllerTestSuite) TestReconcile_PushChangeError() { - // Have the mock simulate an error from the PushChange call. - suite.updater.pushChangeError = true - - // Setup a happy path scenario. - suite.setupFooProxyStateTemplateWithReferences() - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: suite.fooProxyStateTemplate.Id, - }) - require.Error(suite.T(), err) - - // Assert on the status reflecting endpoint not found. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionRejectedPushChangeFailed(status.KeyFromID(suite.fooProxyStateTemplate.Id))) -} - -// This test sets up a ProxyStateTemplate that references a ServiceEndpoints that doesn't exist, and ensures the -// status is correct. -func (suite *xdsControllerTestSuite) TestReconcile_MissingEndpoint() { - // Set fooProxyStateTemplate with a reference to fooEndpoints, without storing fooEndpoints so the controller should - // notice it's missing. - fooEndpointsId := resourcetest.Resource(pbcatalog.ServiceEndpointsType, "foo-service").WithTenancy(resource.DefaultNamespacedTenancy()).ID() - fooRequiredEndpoints := make(map[string]*pbproxystate.EndpointRef) - fooRequiredEndpoints["test-cluster-1"] = &pbproxystate.EndpointRef{ - Id: fooEndpointsId, - Port: "mesh", - } - - fooProxyStateTemplate := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "foo-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - RequiredEndpoints: fooRequiredEndpoints, - ProxyState: &pbmesh.ProxyState{}, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireResourceExists(r, fooProxyStateTemplate.Id) - }) - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: fooProxyStateTemplate.Id, - }) - require.Error(suite.T(), err) - - // Assert on the status reflecting endpoint not found. - suite.client.RequireStatusCondition(suite.T(), fooProxyStateTemplate.Id, ControllerName, status.ConditionRejectedErrorReadingEndpoints(status.KeyFromID(fooEndpointsId), "rpc error: code = NotFound desc = resource not found")) -} - -// This test sets up a ProxyStateTemplate that references a ServiceEndpoints that can't be read correctly, and -// checks the status is correct. -func (suite *xdsControllerTestSuite) TestReconcile_ReadEndpointError() { - badID := &pbresource.ID{ - Type: &pbresource.Type{ - Group: "not", - Kind: "found", - GroupVersion: "vfake", - }, - Tenancy: &pbresource.Tenancy{Namespace: "default", Partition: "default", PeerName: "local"}, - } - fooRequiredEndpoints := make(map[string]*pbproxystate.EndpointRef) - fooRequiredEndpoints["test-cluster-1"] = &pbproxystate.EndpointRef{ - Id: badID, - Port: "mesh", - } - - fooProxyStateTemplate := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "foo-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - RequiredEndpoints: fooRequiredEndpoints, - ProxyState: &pbmesh.ProxyState{}, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireResourceExists(r, fooProxyStateTemplate.Id) - }) - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: fooProxyStateTemplate.Id, - }) - require.Error(suite.T(), err) - - // Assert on the status reflecting endpoint couldn't be read. - suite.client.RequireStatusCondition(suite.T(), fooProxyStateTemplate.Id, ControllerName, status.ConditionRejectedErrorReadingEndpoints( - status.KeyFromID(badID), - "rpc error: code = InvalidArgument desc = id.name invalid: a resource name must consist of lower case alphanumeric characters or '-', must start and end with an alphanumeric character and be less than 64 characters, got: \"\"", - )) -} - -// This test is a happy path creation test to make sure pbproxystate.Endpoints are created in the computed -// pbmesh.ProxyState from the RequiredEndpoints references. More specific translations between endpoint references -// and pbproxystate.Endpoints are unit tested in endpoint_builder.go. -func (suite *xdsControllerTestSuite) TestReconcile_ProxyStateTemplateComputesEndpoints() { - // Set up fooEndpoints and fooProxyStateTemplate with a reference to fooEndpoints and store them in the state store. - // This setup saves expected values in the suite so it can be asserted against later. - suite.setupFooProxyStateTemplateWithReferences() - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: suite.fooProxyStateTemplate.Id, - }) - require.NoError(suite.T(), err) - - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - - // Assert that the endpoints computed in the controller matches the expected endpoints. - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - prototest.AssertDeepEqual(suite.T(), suite.expectedFooProxyStateEndpoints, actualEndpoints) -} - -func (suite *xdsControllerTestSuite) TestReconcile_ProxyStateTemplateComputesLeafCerts() { - // Set up fooEndpoints and fooProxyStateTemplate with a reference to fooEndpoints and store them in the state store. - // This setup saves expected values in the suite so it can be asserted against later. - suite.setupFooProxyStateTemplateWithReferences() - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: suite.fooProxyStateTemplate.Id, - }) - require.NoError(suite.T(), err) - - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - - // Assert that the actual leaf certs computed are match the expected leaf cert spiffes. - actualLeafs := suite.updater.GetLeafs(suite.fooProxyStateTemplate.Id.Name) - - for k, l := range actualLeafs { - pem, _ := pem.Decode([]byte(l.Cert)) - cert, err := x509.ParseCertificate(pem.Bytes) - require.NoError(suite.T(), err) - require.Equal(suite.T(), cert.URIs[0].String(), suite.expectedFooProxyStateSpiffes[k]) - } -} - -// This test is a happy path creation test to make sure pbproxystate.Template.TrustBundles are created in the computed -// pbmesh.ProxyState from the TrustBundleFetcher. -func (suite *xdsControllerTestSuite) TestReconcile_ProxyStateTemplateSetsTrustBundles() { - suite.setupFooProxyStateTemplateWithReferences() - - // Run the reconcile. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: suite.fooProxyStateTemplate.Id, - }) - require.NoError(suite.T(), err) - - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - - // Assert that the endpoints computed in the controller matches the expected endpoints. - actualTrustBundle := suite.updater.GetTrustBundle(suite.fooProxyStateTemplate.Id.Name) - prototest.AssertDeepEqual(suite.T(), suite.expectedTrustBundle, actualTrustBundle) -} - -// This test is a happy path creation test that calls reconcile multiple times with a more complex setup. This -// scenario is trickier to test in the controller test because the end computation of the xds controller is not -// stored in the state store. So this test ensures that between multiple reconciles the correct ProxyStates are -// computed for each ProxyStateTemplate. -func (suite *xdsControllerTestSuite) TestReconcile_MultipleProxyStateTemplatesComputesMultipleEndpoints() { - // Set up fooProxyStateTemplate and barProxyStateTemplate and their associated resources and store them. Resources - // and expected results are stored in the suite to assert against. - suite.setupFooBarProxyStateTemplateAndEndpoints() - - // Reconcile the fooProxyStateTemplate. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: suite.fooProxyStateTemplate.Id, - }) - require.NoError(suite.T(), err) - - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - - // Assert that the endpoints computed in the controller matches the expected endpoints. - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - prototest.AssertDeepEqual(suite.T(), suite.expectedFooProxyStateEndpoints, actualEndpoints) - - // Reconcile the barProxyStateTemplate. - err = suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: suite.barProxyStateTemplate.Id, - }) - require.NoError(suite.T(), err) - - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.barProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - - // Assert that the endpoints computed in the controller matches the expected endpoints. - actualBarEndpoints := suite.updater.GetEndpoints(suite.barProxyStateTemplate.Id.Name) - prototest.AssertDeepEqual(suite.T(), suite.expectedBarProxyStateEndpoints, actualBarEndpoints) -} - -// Sets up a full controller, and tests that reconciles are getting triggered for the events it should. -func (suite *xdsControllerTestSuite) TestController_ComputeAddUpdateEndpointReferences() { - // Run the controller manager. - mgr := controller.NewManager(suite.client, suite.runtime.Logger) - mgr.Register(Controller(suite.mapper, suite.updater, suite.fetcher, suite.leafCertManager, suite.leafMapper, suite.leafCancels, "dc1")) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - suite.setupFooProxyStateTemplateWithReferences() - - // Assert that the expected ProxyState matches the actual ProxyState that PushChange was called with. This needs to - // be in a retry block unlike the Reconcile tests because the controller triggers asynchronously. - retry.Run(suite.T(), func(r *retry.R) { - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - // Assert on the status. - suite.client.RequireStatusCondition(r, suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - // Assert that the endpoints computed in the controller matches the expected endpoints. - prototest.AssertDeepEqual(r, suite.expectedFooProxyStateEndpoints, actualEndpoints) - }) - - // Now, update the endpoint to be unhealthy. This will ensure the controller is getting triggered on changes to this - // endpoint that it should be tracking, even when the ProxyStateTemplate does not change. - resourcetest.Resource(pbcatalog.ServiceEndpointsType, "foo-service"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.1.1.1", - Ports: []string{"mesh"}, - }, - { - Host: "10.2.2.2", - Ports: []string{"mesh"}, - }, - }, - HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, - }, - }}). - WithOwner(suite.fooService.Id). - Write(suite.T(), suite.client) - - // Wait for the endpoint to be written. - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireVersionChanged(suite.T(), suite.fooEndpoints.Id, suite.fooEndpoints.Version) - }) - - // Update the expected endpoints to also have unhealthy status. - suite.expectedFooProxyStateEndpoints["test-cluster-1"].Endpoints[0].HealthStatus = pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - suite.expectedFooProxyStateEndpoints["test-cluster-1"].Endpoints[1].HealthStatus = pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - - retry.Run(suite.T(), func(r *retry.R) { - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - // Assert that the endpoints computed in the controller matches the expected endpoints. - prototest.AssertDeepEqual(r, suite.expectedFooProxyStateEndpoints, actualEndpoints) - }) - - // Now add a new endpoint reference and endpoint to the fooProxyStateTemplate. This will ensure that the controller - // now tracks the newly added endpoint. - secondService := resourcetest.Resource(pbcatalog.ServiceType, "second-service"). - WithData(suite.T(), &pbcatalog.Service{}). - Write(suite.T(), suite.client) - - secondEndpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, "second-service"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.5.5.5", - Ports: []string{"mesh"}, - }, - { - Host: "10.6.6.6", - Ports: []string{"mesh"}, - }, - }, - }, - }}). - WithOwner(secondService.Id). - Write(suite.T(), suite.client) - - // Update the endpoint references on the fooProxyStateTemplate. - suite.fooEndpointRefs["test-cluster-2"] = &pbproxystate.EndpointRef{ - Id: secondEndpoints.Id, - Port: "mesh", - } - - oldVersion := suite.fooProxyStateTemplate.Version - fooProxyStateTemplate := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "foo-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - RequiredEndpoints: suite.fooEndpointRefs, - ProxyState: &pbmesh.ProxyState{}, - RequiredLeafCertificates: suite.fooLeafRefs, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireVersionChanged(r, fooProxyStateTemplate.Id, oldVersion) - }) - - // Update the expected endpoints with this new endpoints. - suite.expectedFooProxyStateEndpoints["test-cluster-2"] = &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.5.5.5", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.6.6.6", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }, - } - - retry.Run(suite.T(), func(r *retry.R) { - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - // Assert on the status. - suite.client.RequireStatusCondition(suite.T(), suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - // Assert that the endpoints computed in the controller matches the expected endpoints. - prototest.AssertDeepEqual(r, suite.expectedFooProxyStateEndpoints, actualEndpoints) - }) - -} - -// Sets up a full controller, and tests that reconciles are getting triggered for the leaf cert events it should. -// This test ensures when a CA is updated, the controller is triggered to update the leaf cert when it changes. -func (suite *xdsControllerTestSuite) TestController_ComputeAddUpdateDeleteLeafReferences() { - // Run the controller manager. - mgr := controller.NewManager(suite.client, suite.runtime.Logger) - mgr.Register(Controller(suite.mapper, suite.updater, suite.fetcher, suite.leafCertManager, suite.leafMapper, suite.leafCancels, "dc1")) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - suite.setupFooProxyStateTemplateWithReferences() - leafCertRef := suite.fooLeafRefs["foo-workload-identity"] - fooLeafResRef := leafResourceRef(leafCertRef.Name, leafCertRef.Namespace, leafCertRef.Partition) - - // oldLeaf will store the original leaf from before we trigger a CA update. - var oldLeaf *x509.Certificate - - // Assert that the expected ProxyState matches the actual ProxyState that PushChange was called with. This needs to - // be in a retry block unlike the Reconcile tests because the controller triggers asynchronously. - retry.Run(suite.T(), func(r *retry.R) { - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - actualLeafs := suite.updater.GetLeafs(suite.fooProxyStateTemplate.Id.Name) - // Assert on the status. - suite.client.RequireStatusCondition(r, suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - // Assert that the endpoints computed in the controller matches the expected endpoints. - prototest.AssertDeepEqual(r, suite.expectedFooProxyStateEndpoints, actualEndpoints) - // Assert that the leafs computed in the controller matches the expected leafs. - require.Len(r, actualLeafs, 1) - for k, l := range actualLeafs { - pem, _ := pem.Decode([]byte(l.Cert)) - cert, err := x509.ParseCertificate(pem.Bytes) - oldLeaf = cert - require.NoError(r, err) - require.Equal(r, cert.URIs[0].String(), suite.expectedFooProxyStateSpiffes[k]) - // Check the state of the cancel functions map. - _, ok := suite.leafCancels.Get(keyFromReference(fooLeafResRef)) - require.True(r, ok) - } - }) - - // Update the CA, and ensure the leaf cert is different from the leaf certificate from the step above. - suite.signer.UpdateCA(suite.T(), nil) - retry.Run(suite.T(), func(r *retry.R) { - actualLeafs := suite.updater.GetLeafs(suite.fooProxyStateTemplate.Id.Name) - require.Len(r, actualLeafs, 1) - for k, l := range actualLeafs { - pem, _ := pem.Decode([]byte(l.Cert)) - cert, err := x509.ParseCertificate(pem.Bytes) - // Ensure the leaf was actually updated by checking that the leaf we just got is different from the old leaf. - require.NotEqual(r, oldLeaf.Raw, cert.Raw) - require.NoError(r, err) - require.Equal(r, suite.expectedFooProxyStateSpiffes[k], cert.URIs[0].String()) - // Check the state of the cancel functions map. Even though we've updated the leaf cert, we should still - // have a watch going for it. - _, ok := suite.leafCancels.Get(keyFromReference(fooLeafResRef)) - require.True(r, ok) - } - }) - - // Delete the leaf references on the fooProxyStateTemplate - delete(suite.fooLeafRefs, "foo-workload-identity") - oldVersion := suite.fooProxyStateTemplate.Version - fooProxyStateTemplate := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "foo-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - RequiredEndpoints: suite.fooEndpointRefs, - ProxyState: &pbmesh.ProxyState{}, - RequiredLeafCertificates: suite.fooLeafRefs, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireVersionChanged(r, fooProxyStateTemplate.Id, oldVersion) - }) - - // Ensure the leaf certificate watches were cancelled since we deleted the leaf reference. - retry.Run(suite.T(), func(r *retry.R) { - _, ok := suite.leafCancels.Get(keyFromReference(fooLeafResRef)) - require.False(r, ok) - }) -} - -// Sets up a full controller, and tests that reconciles are getting triggered for the leaf cert events it should. -// This test ensures that when a ProxyStateTemplate is deleted, the leaf watches are cancelled. -func (suite *xdsControllerTestSuite) TestController_ComputeLeafReferencesDeletePST() { - // Run the controller manager. - mgr := controller.NewManager(suite.client, suite.runtime.Logger) - mgr.Register(Controller(suite.mapper, suite.updater, suite.fetcher, suite.leafCertManager, suite.leafMapper, suite.leafCancels, "dc1")) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - suite.setupFooProxyStateTemplateWithReferences() - leafCertRef := suite.fooLeafRefs["foo-workload-identity"] - fooLeafResRef := leafResourceRef(leafCertRef.Name, leafCertRef.Namespace, leafCertRef.Partition) - - // Assert that the expected ProxyState matches the actual ProxyState that PushChange was called with. This needs to - // be in a retry block unlike the Reconcile tests because the controller triggers asynchronously. - retry.Run(suite.T(), func(r *retry.R) { - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - actualLeafs := suite.updater.GetLeafs(suite.fooProxyStateTemplate.Id.Name) - // Assert on the status. - suite.client.RequireStatusCondition(r, suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - // Assert that the endpoints computed in the controller matches the expected endpoints. - prototest.AssertDeepEqual(r, suite.expectedFooProxyStateEndpoints, actualEndpoints) - // Assert that the leafs computed in the controller matches the expected leafs. - require.Len(r, actualLeafs, 1) - for k, l := range actualLeafs { - pem, _ := pem.Decode([]byte(l.Cert)) - cert, err := x509.ParseCertificate(pem.Bytes) - require.NoError(r, err) - require.Equal(r, cert.URIs[0].String(), suite.expectedFooProxyStateSpiffes[k]) - // Check the state of the cancel functions map. - _, ok := suite.leafCancels.Get(keyFromReference(fooLeafResRef)) - require.True(r, ok) - } - }) - - // Delete the fooProxyStateTemplate - - req := &pbresource.DeleteRequest{ - Id: suite.fooProxyStateTemplate.Id, - } - suite.client.Delete(suite.ctx, req) - - // Ensure the leaf certificate watches were cancelled since we deleted the leaf reference. - retry.Run(suite.T(), func(r *retry.R) { - _, ok := suite.leafCancels.Get(keyFromReference(fooLeafResRef)) - require.False(r, ok) - }) -} - -// Sets up a full controller, and tests that reconciles are getting triggered for the events it should. -func (suite *xdsControllerTestSuite) TestController_ComputeEndpointForProxyConnections() { - // Run the controller manager. - mgr := controller.NewManager(suite.client, suite.runtime.Logger) - - mgr.Register(Controller(suite.mapper, suite.updater, suite.fetcher, suite.leafCertManager, suite.leafMapper, suite.leafCancels, "dc1")) - mgr.SetRaftLeader(true) - go mgr.Run(suite.ctx) - - // Set up fooEndpoints and fooProxyStateTemplate with a reference to fooEndpoints. These need to be stored - // because the controller reconcile looks them up. - suite.setupFooProxyStateTemplateWithReferences() - - // Assert that the expected ProxyState matches the actual ProxyState that PushChange was called with. This needs to - // be in a retry block unlike the Reconcile tests because the controller triggers asynchronously. - retry.Run(suite.T(), func(r *retry.R) { - actualEndpoints := suite.updater.GetEndpoints(suite.fooProxyStateTemplate.Id.Name) - // Assert on the status. - suite.client.RequireStatusCondition(r, suite.fooProxyStateTemplate.Id, ControllerName, status.ConditionAccepted()) - // Assert that the endpoints computed in the controller matches the expected endpoints. - prototest.AssertDeepEqual(r, suite.expectedFooProxyStateEndpoints, actualEndpoints) - }) - - eventChannel := suite.updater.EventChannel() - eventChannel <- controller.Event{Obj: &proxytracker.ProxyConnection{ProxyID: suite.fooProxyStateTemplate.Id}} - - // Wait for the proxy state template to be re-evaluated. - proxyStateTemp := suite.client.WaitForNewVersion(suite.T(), suite.fooProxyStateTemplate.Id, suite.fooProxyStateTemplate.Version) - require.NotNil(suite.T(), proxyStateTemp) -} - -// Setup: fooProxyStateTemplate with: -// - an EndpointsRef to fooEndpoints -// - a LeafCertificateRef to "foo-workload-identity" -// -// Saves all related resources to the suite so they can be looked up by the controller or modified if needed. -func (suite *xdsControllerTestSuite) setupFooProxyStateTemplateWithReferences() { - fooService := resourcetest.Resource(pbcatalog.ServiceType, "foo-service"). - WithData(suite.T(), &pbcatalog.Service{}). - Write(suite.T(), suite.client) - - fooEndpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, "foo-service"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.1.1.1", - Ports: []string{"mesh"}, - }, - { - Host: "10.2.2.2", - Ports: []string{"mesh"}, - }, - }, - }, - }}). - WithOwner(fooService.Id). - Write(suite.T(), suite.client) - - fooRequiredEndpoints := make(map[string]*pbproxystate.EndpointRef) - fooRequiredEndpoints["test-cluster-1"] = &pbproxystate.EndpointRef{ - Id: fooEndpoints.Id, - Port: "mesh", - } - - fooRequiredLeafs := make(map[string]*pbproxystate.LeafCertificateRef) - fooRequiredLeafs["foo-workload-identity"] = &pbproxystate.LeafCertificateRef{ - Name: "foo-workload-identity", - } - - fooProxyStateTemplate := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "foo-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - RequiredEndpoints: fooRequiredEndpoints, - RequiredLeafCertificates: fooRequiredLeafs, - ProxyState: &pbmesh.ProxyState{}, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireResourceExists(r, fooProxyStateTemplate.Id) - }) - - expectedFooLeafSpiffes := map[string]string{ - "foo-workload-identity": "spiffe://11111111-2222-3333-4444-555555555555.consul/ap/default/ns/default/identity/foo-workload-identity", - } - expectedFooProxyStateEndpoints := map[string]*pbproxystate.Endpoints{ - "test-cluster-1": {Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.1.1.1", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.2.2.2", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }}, - } - - expectedTrustBundle := map[string]*pbproxystate.TrustBundle{ - "local": { - TrustDomain: "some-trust-domain", - Roots: []string{"some-root", "some-other-root"}, - }, - } - - suite.fooService = fooService - suite.fooEndpoints = fooEndpoints - suite.fooEndpointRefs = fooRequiredEndpoints - suite.fooLeafRefs = fooRequiredLeafs - suite.fooProxyStateTemplate = fooProxyStateTemplate - suite.expectedFooProxyStateEndpoints = expectedFooProxyStateEndpoints - suite.expectedTrustBundle = expectedTrustBundle - suite.expectedFooProxyStateSpiffes = expectedFooLeafSpiffes -} - -// Setup: -// - fooProxyStateTemplate with an EndpointsRef to fooEndpoints and fooBarEndpoints. -// - barProxyStateTemplate with an EndpointsRef to fooBarEndpoints. -// -// Saves all related resources to the suite so they can be modified if needed. -func (suite *xdsControllerTestSuite) setupFooBarProxyStateTemplateAndEndpoints() { - fooService := resourcetest.Resource(pbcatalog.ServiceType, "foo-service"). - WithData(suite.T(), &pbcatalog.Service{}). - Write(suite.T(), suite.client) - - fooEndpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, "foo-service"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.1.1.1", - Ports: []string{"mesh"}, - }, - { - Host: "10.2.2.2", - Ports: []string{"mesh"}, - }, - }, - }, - }}). - WithOwner(fooService.Id). - Write(suite.T(), suite.client) - - fooBarService := resourcetest.Resource(pbcatalog.ServiceType, "foo-bar-service"). - WithData(suite.T(), &pbcatalog.Service{}). - Write(suite.T(), suite.client) - - fooBarEndpoints := resourcetest.Resource(pbcatalog.ServiceEndpointsType, "foo-bar-service"). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.3.3.3", - Ports: []string{"mesh"}, - }, - { - Host: "10.4.4.4", - Ports: []string{"mesh"}, - }, - }, - }, - }}). - WithOwner(fooBarService.Id). - Write(suite.T(), suite.client) - - fooRequiredEndpoints := make(map[string]*pbproxystate.EndpointRef) - fooRequiredEndpoints["test-cluster-1"] = &pbproxystate.EndpointRef{ - Id: fooEndpoints.Id, - Port: "mesh", - } - fooRequiredEndpoints["test-cluster-2"] = &pbproxystate.EndpointRef{ - Id: fooBarEndpoints.Id, - Port: "mesh", - } - - barRequiredEndpoints := make(map[string]*pbproxystate.EndpointRef) - barRequiredEndpoints["test-cluster-1"] = &pbproxystate.EndpointRef{ - Id: fooBarEndpoints.Id, - // Sidecar proxy controller will usually set mesh port here. - Port: "mesh", - } - - fooProxyStateTemplate := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "foo-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - // Contains the foo and foobar endpoints. - RequiredEndpoints: fooRequiredEndpoints, - ProxyState: &pbmesh.ProxyState{}, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireResourceExists(r, fooProxyStateTemplate.Id) - }) - - barProxyStateTemplate := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "bar-pst"). - WithData(suite.T(), &pbmesh.ProxyStateTemplate{ - // Contains the foobar endpoint. - RequiredEndpoints: barRequiredEndpoints, - ProxyState: &pbmesh.ProxyState{}, - }). - Write(suite.T(), suite.client) - - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireResourceExists(r, barProxyStateTemplate.Id) - }) - - expectedFooProxyStateEndpoints := map[string]*pbproxystate.Endpoints{ - "test-cluster-1": {Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.1.1.1", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.2.2.2", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }}, - "test-cluster-2": {Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.3.3.3", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.4.4.4", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }}, - } - - expectedBarProxyStateEndpoints := map[string]*pbproxystate.Endpoints{ - "test-cluster-1": {Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.3.3.3", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.4.4.4", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }}, - } - - suite.fooProxyStateTemplate = fooProxyStateTemplate - suite.barProxyStateTemplate = barProxyStateTemplate - suite.barEndpointRefs = barRequiredEndpoints - suite.fooEndpointRefs = fooRequiredEndpoints - suite.fooEndpoints = fooEndpoints - suite.fooService = fooService - suite.fooBarEndpoints = fooBarEndpoints - suite.fooBarService = fooBarService - suite.expectedFooProxyStateEndpoints = expectedFooProxyStateEndpoints - suite.expectedBarProxyStateEndpoints = expectedBarProxyStateEndpoints -} - -func (suite *xdsControllerTestSuite) TestReconcile_prevWatchesToCancel() { - makeRef := func(names ...string) []*pbresource.Reference { - out := make([]*pbresource.Reference, len(names)) - for i, name := range names { - out[i] = &pbresource.Reference{ - Name: name, - Type: &pbresource.Type{ - Group: "g", - GroupVersion: "v", - Kind: "k", - }, - Tenancy: &pbresource.Tenancy{}, - } - } - return out - } - convert := func(input []*pbresource.Reference) []resource.ReferenceOrID { - asInterface := make([]resource.ReferenceOrID, len(input)) - for i := range input { - asInterface[i] = input[i] - } - return asInterface - } - - cases := []struct { - old []*pbresource.Reference - new []*pbresource.Reference - expect []*pbresource.Reference - }{ - { - old: makeRef("a", "b", "c"), - new: makeRef("a", "c"), - expect: makeRef("b"), - }, - { - old: makeRef("a", "b", "c"), - new: makeRef("a", "b", "c"), - expect: makeRef(), - }, - { - old: makeRef(), - new: makeRef("a", "b"), - expect: makeRef(), - }, - { - old: makeRef("a", "b"), - new: makeRef(), - expect: makeRef("a", "b"), - }, - { - old: makeRef(), - new: makeRef(), - expect: makeRef(), - }, - } - - for _, tc := range cases { - toCancel := prevWatchesToCancel(tc.old, convert(tc.new)) - require.ElementsMatch(suite.T(), toCancel, tc.expect) - } -} - -func TestXdsController(t *testing.T) { - suite.Run(t, new(xdsControllerTestSuite)) -} - -// TestReconcile_SidecarProxyGoldenFileInputs tests the Reconcile() by using -// the golden test output/expected files from the sidecar proxy tests as inputs -// to the XDS controller reconciliation. -// XDS controller reconciles the full ProxyStateTemplate object. The fields -// that things that it focuses on are leaf certs, endpoints, and trust bundles, -// which is just a subset of the ProxyStateTemplate struct. Prior to XDS controller -// reconciliation, the sidecar proxy controller will have reconciled the other parts -// of the ProxyStateTemplate. -// Since the XDS controller does act on the ProxyStateTemplate, the tests -// utilize that entire object rather than just the parts that XDS controller -// internals reconciles. Namely, by using checking the full ProxyStateTemplate -// rather than just endpoints, leaf certs, and trust bundles, the test also ensures -// side effects or change in scope to XDS controller are not introduce mistakenly. -func (suite *xdsControllerTestSuite) TestReconcile_SidecarProxyGoldenFileInputs() { - path := "../sidecarproxy/builder/testdata" - cases := []string{ - // destinations - please add in alphabetical order - "destination/l4-single-destination-ip-port-bind-address", - "destination/l4-single-destination-unix-socket-bind-address", - "destination/l4-single-implicit-destination-tproxy", - "destination/l4-multi-destination", - "destination/l4-multiple-implicit-destinations-tproxy", - "destination/l4-implicit-and-explicit-destinations-tproxy", - "destination/mixed-multi-destination", - "destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy", - "destination/multiport-l4-and-l7-single-implicit-destination-tproxy", - "destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy", - - //sources - please add in alphabetical order - "source/l7-expose-paths", - "source/local-and-inbound-connections", - "source/multiple-workload-addresses-with-specific-ports", - "source/multiple-workload-addresses-without-ports", - "source/multiport-l4-multiple-workload-addresses-with-specific-ports", - "source/multiport-l4-multiple-workload-addresses-without-ports", - "source/multiport-l4-workload-with-only-mesh-port", - "source/multiport-l7-multiple-workload-addresses-with-specific-ports", - "source/multiport-l7-multiple-workload-addresses-without-ports", - "source/multiport-l7-multiple-workload-addresses-without-ports", - "source/single-workload-address-without-ports", - } - - for _, name := range cases { - suite.Run(name, func() { - // Create ProxyStateTemplate from the golden file. - pst := JSONToProxyTemplate(suite.T(), - golden.GetBytesAtFilePath(suite.T(), fmt.Sprintf("%s/%s.golden", path, name))) - - // Destinations will need endpoint refs set up. - if strings.Split(name, "/")[0] == "destination" && len(pst.ProxyState.Endpoints) == 0 { - suite.addRequiredEndpointsAndRefs(pst) - } - - // Store the initial ProxyStateTemplate. - proxyStateTemplate := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test"). - WithData(suite.T(), pst). - Write(suite.T(), suite.client) - - // Check with resource service that it exists. - retry.Run(suite.T(), func(r *retry.R) { - suite.client.RequireResourceExists(r, proxyStateTemplate.Id) - }) - - // Track it in the mapper. - suite.mapper.TrackItem(proxyStateTemplate.Id, []resource.ReferenceOrID{}) - - // Run the reconcile, and since no ProxyStateTemplate is stored, this simulates a deletion. - err := suite.ctl.Reconcile(context.Background(), suite.runtime, controller.Request{ - ID: proxyStateTemplate.Id, - }) - require.NoError(suite.T(), err) - require.NotNil(suite.T(), proxyStateTemplate) - - // Get the reconciled proxyStateTemplate to check the reconcile results. - reconciledPS := suite.updater.Get(proxyStateTemplate.Id.Name) - - // Verify leaf cert contents then hard code them for comparison - // and downstream tests since they change from test run to test run. - require.NotEmpty(suite.T(), reconciledPS.LeafCertificates) - reconciledPS.LeafCertificates = map[string]*pbproxystate.LeafCertificate{ - "test-identity": { - Cert: "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - Key: "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n", - }, - } - - // Compare actual vs expected. - actual := prototest.ProtoToJSON(suite.T(), reconciledPS) - expected := golden.Get(suite.T(), actual, name+".golden") - require.JSONEq(suite.T(), expected, actual) - }) - } -} - -func (suite *xdsControllerTestSuite) addRequiredEndpointsAndRefs(pst *pbmesh.ProxyStateTemplate) { - //get service data - serviceData := &pbcatalog.Service{} - var vp uint32 = 7000 - requiredEps := make(map[string]*pbproxystate.EndpointRef) - - // iterate through clusters and set up endpoints for cluster/mesh port. - for clusterName := range pst.ProxyState.Clusters { - if clusterName == "null_route_cluster" || clusterName == "original-destination" { - continue - } - - //increment the random port number. - vp++ - clusterNameSplit := strings.Split(clusterName, ".") - port := clusterNameSplit[0] - svcName := clusterNameSplit[1] - - // set up service data with port info. - serviceData.Ports = append(serviceData.Ports, &pbcatalog.ServicePort{ - TargetPort: port, - VirtualPort: vp, - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }) - - // create service. - svc := resourcetest.Resource(pbcatalog.ServiceType, svcName). - WithData(suite.T(), &pbcatalog.Service{}). - Write(suite.T(), suite.client) - - // create endpoints with svc as owner. - eps := resourcetest.Resource(pbcatalog.ServiceEndpointsType, svcName). - WithData(suite.T(), &pbcatalog.ServiceEndpoints{Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.1.1.1", - Ports: []string{"mesh"}, - }, - }, - }, - }}). - WithOwner(svc.Id). - Write(suite.T(), suite.client) - - // add to working list of required endpoints. - requiredEps[clusterName] = &pbproxystate.EndpointRef{ - Id: eps.Id, - Port: "mesh", - } - } - - // set working list of required endpoints as proxy state's RequiredEndpoints. - pst.RequiredEndpoints = requiredEps -} - -func JSONToProxyTemplate(t *testing.T, json []byte) *pbmesh.ProxyStateTemplate { - t.Helper() - proxyTemplate := &pbmesh.ProxyStateTemplate{} - m := protojson.UnmarshalOptions{} - err := m.Unmarshal(json, proxyTemplate) - require.NoError(t, err) - return proxyTemplate -} diff --git a/internal/mesh/internal/controllers/xds/endpoint_builder.go b/internal/mesh/internal/controllers/xds/endpoint_builder.go deleted file mode 100644 index d0e3f84366f9..000000000000 --- a/internal/mesh/internal/controllers/xds/endpoint_builder.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "fmt" - "net" - - "golang.org/x/exp/slices" - - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" -) - -func generateProxyStateEndpoints(serviceEndpoints *ServiceEndpointsData, portName string) (*pbproxystate.Endpoints, error) { - var psEndpoints []*pbproxystate.Endpoint - - if serviceEndpoints.Endpoints == nil || serviceEndpoints.Resource == nil { - return nil, fmt.Errorf("service endpoints requires both endpoints and resource") - } - eps := serviceEndpoints.Endpoints.GetEndpoints() - - for _, ep := range eps { - for _, addr := range ep.Addresses { - // Check if the address is using the portName name this proxy state endpoints is for. If it does, create the - // endpoint. - if slices.Contains(addr.Ports, portName) { - // Lookup the portName number from the portName name. - wlPort, ok := ep.Ports[portName] - if !ok { - // This should never happen, as it should be validated by the ServiceEndpoints controller. - return nil, fmt.Errorf("could not find portName %q in endpoint %s", portName, serviceEndpoints.Resource.Id) - } - portNum := wlPort.Port - - psEndpoint, err := createProxyStateEndpoint(addr.Host, portNum, ep.HealthStatus) - if err != nil { - return nil, err - } - psEndpoints = append(psEndpoints, psEndpoint) - } - } - } - - return &pbproxystate.Endpoints{Endpoints: psEndpoints}, nil -} - -func createProxyStateEndpoint(host string, port uint32, health pbcatalog.Health) (*pbproxystate.Endpoint, error) { - addr := net.ParseIP(host) - if addr == nil { - return nil, fmt.Errorf("host is not an ip") - } - - psEndpoint := &pbproxystate.Endpoint{ - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: host, - Port: port, - }, - }, - HealthStatus: endpointHealth(health), - // TODO(xds): Weight will be added later. More information is potentially needed in the reference. - } - return psEndpoint, nil -} - -func endpointHealth(catalogHealth pbcatalog.Health) pbproxystate.HealthStatus { - health := pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY - - if catalogHealth == pbcatalog.Health_HEALTH_CRITICAL { - health = pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY - } - return health -} diff --git a/internal/mesh/internal/controllers/xds/endpoint_builder_test.go b/internal/mesh/internal/controllers/xds/endpoint_builder_test.go deleted file mode 100644 index 756acdb7e990..000000000000 --- a/internal/mesh/internal/controllers/xds/endpoint_builder_test.go +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestMakeProxyStateEndpointsFromServiceEndpoints(t *testing.T) { - type test struct { - name string - serviceEndpointsData *ServiceEndpointsData - portName string - expErr string - expectedProxyStateEndpoints *pbproxystate.Endpoints - } - cases := []test{ - { - name: "endpoints with passing health", - serviceEndpointsData: serviceEndpointsData("passing"), - portName: "mesh", - expectedProxyStateEndpoints: &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.1.1.1", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.2.2.2", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.3.3.3", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }, - }, - }, - { - name: "endpoints with critical health", - serviceEndpointsData: serviceEndpointsData("critical"), - portName: "mesh", - expectedProxyStateEndpoints: &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.1.1.1", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.2.2.2", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.3.3.3", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_UNHEALTHY, - }, - }, - }, - }, - { - name: "endpoints with any health are considered healthy", - serviceEndpointsData: serviceEndpointsData("any"), - portName: "mesh", - expectedProxyStateEndpoints: &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{ - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.1.1.1", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.2.2.2", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - { - Address: &pbproxystate.Endpoint_HostPort{ - HostPort: &pbproxystate.HostPortAddress{ - Host: "10.3.3.3", - Port: 20000, - }, - }, - HealthStatus: pbproxystate.HealthStatus_HEALTH_STATUS_HEALTHY, - }, - }, - }, - }, - { - name: "endpoints with missing ports returns an error", - serviceEndpointsData: serviceEndpointsData("missing port lookup"), - portName: "mesh", - expErr: "could not find portName", - }, - { - name: "nil endpoints returns an error", - serviceEndpointsData: serviceEndpointsData("nil endpoints"), - portName: "mesh", - expErr: "service endpoints requires both endpoints and resource", - }, - { - name: "nil resource returns an error", - serviceEndpointsData: serviceEndpointsData("nil resource"), - portName: "mesh", - expErr: "service endpoints requires both endpoints and resource", - }, - { - name: "portName doesn't exist in endpoints results in empty endpoints", - serviceEndpointsData: serviceEndpointsData("passing"), - portName: "does-not-exist", - expectedProxyStateEndpoints: &pbproxystate.Endpoints{ - Endpoints: []*pbproxystate.Endpoint{}, - }, - }, - } - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - actualEndpoints, err := generateProxyStateEndpoints(tc.serviceEndpointsData, tc.portName) - if tc.expErr != "" { - require.ErrorContains(t, err, tc.expErr) - } else { - prototest.AssertDeepEqual(t, tc.expectedProxyStateEndpoints, actualEndpoints) - } - }) - } -} - -func serviceEndpointsData(variation string) *ServiceEndpointsData { - r := resourcetest.Resource(pbcatalog.ServiceEndpointsType, "test").Build() - eps := &pbcatalog.ServiceEndpoints{ - Endpoints: []*pbcatalog.Endpoint{ - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.1.1.1", - Ports: []string{"mesh"}, - }, - { - Host: "10.2.2.2", - Ports: []string{"mesh"}, - }, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - { - Ports: map[string]*pbcatalog.WorkloadPort{ - "mesh": { - Port: 20000, - Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - }, - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "10.3.3.3", - Ports: []string{"mesh"}, - }, - }, - HealthStatus: pbcatalog.Health_HEALTH_PASSING, - }, - }, - } - - switch variation { - case "passing": - case "critical": - eps.Endpoints[0].HealthStatus = pbcatalog.Health_HEALTH_CRITICAL - eps.Endpoints[1].HealthStatus = pbcatalog.Health_HEALTH_CRITICAL - case "any": - eps.Endpoints[0].HealthStatus = pbcatalog.Health_HEALTH_ANY - eps.Endpoints[1].HealthStatus = pbcatalog.Health_HEALTH_ANY - case "missing port lookup": - delete(eps.Endpoints[0].Ports, "mesh") - case "nil endpoints": - eps = nil - case "nil resource": - r = nil - } - - return &ServiceEndpointsData{ - Resource: r, - Endpoints: eps, - } -} diff --git a/internal/mesh/internal/controllers/xds/leaf_cancels.go b/internal/mesh/internal/controllers/xds/leaf_cancels.go deleted file mode 100644 index b1451487d7db..000000000000 --- a/internal/mesh/internal/controllers/xds/leaf_cancels.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "context" - "sync" -) - -// LeafCancels holds the cancel functions for leaf certificates being watched by this controller instance. -type LeafCancels struct { - sync.Mutex - // Cancels is a map from a string key constructed from the pbproxystate.LeafReference to a cancel function for the - // leaf watch. - Cancels map[string]context.CancelFunc -} - -func (l *LeafCancels) Get(key string) (context.CancelFunc, bool) { - l.Lock() - defer l.Unlock() - v, ok := l.Cancels[key] - return v, ok -} -func (l *LeafCancels) Set(key string, value context.CancelFunc) { - l.Lock() - defer l.Unlock() - l.Cancels[key] = value -} -func (l *LeafCancels) Delete(key string) { - l.Lock() - defer l.Unlock() - delete(l.Cancels, key) -} diff --git a/internal/mesh/internal/controllers/xds/leaf_mapper.go b/internal/mesh/internal/controllers/xds/leaf_mapper.go deleted file mode 100644 index b268b6b97ccb..000000000000 --- a/internal/mesh/internal/controllers/xds/leaf_mapper.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "context" - "fmt" - - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource/mappers/bimapper" -) - -// LeafMapper is a wrapper around endpointsMapper to allow mapping from events to requests for PSTs (as opposed to from a resource to requests for PSTs). -type LeafMapper struct { - *bimapper.Mapper -} - -func (m *LeafMapper) EventMapLink(_ context.Context, _ controller.Runtime, event controller.Event) ([]controller.Request, error) { - // Get cert from event. - cert, ok := event.Obj.(*structs.IssuedCert) - if !ok { - return nil, fmt.Errorf("got invalid event type; expected *structs.IssuedCert") - } - - // The LeafMapper has mappings from leaf certificate resource references to PSTs. So we need to translate the - // contents of the certificate from the event to a leaf resource reference. - leafRef := leafResourceRef(cert.WorkloadIdentity, cert.EnterpriseMeta.NamespaceOrDefault(), cert.EnterpriseMeta.PartitionOrDefault()) - - // Get all the ProxyStateTemplates that reference this leaf. - itemIDs := m.ItemIDsForLink(leafRef) - out := make([]controller.Request, 0, len(itemIDs)) - - for _, item := range itemIDs { - out = append(out, controller.Request{ID: item}) - } - return out, nil -} diff --git a/internal/mesh/internal/controllers/xds/mock_updater.go b/internal/mesh/internal/controllers/xds/mock_updater.go deleted file mode 100644 index 5d62acc4855e..000000000000 --- a/internal/mesh/internal/controllers/xds/mock_updater.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "fmt" - "sync" - - "github.com/hashicorp/consul/internal/controller" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// mockUpdater mocks the updater functions, and stores ProxyStates from calls to PushChange, so we can assert it was -// computed correctly in the controller. -type mockUpdater struct { - lock sync.Mutex - // latestPs is a map from a ProxyStateTemplate's id.Name in string form to the last computed ProxyState for that - // ProxyStateTemplate. - latestPs map[string]proxysnapshot.ProxySnapshot - notConnected bool - pushChangeError bool - eventChan chan controller.Event -} - -func newMockUpdater() *mockUpdater { - return &mockUpdater{ - latestPs: make(map[string]proxysnapshot.ProxySnapshot), - } -} - -func (m *mockUpdater) SetPushChangeErrorTrue() { - m.lock.Lock() - defer m.lock.Unlock() - m.pushChangeError = true -} - -func (m *mockUpdater) SetProxyAsNotConnected() { - m.lock.Lock() - defer m.lock.Unlock() - m.notConnected = true -} - -func (m *mockUpdater) PushChange(id *pbresource.ID, snapshot proxysnapshot.ProxySnapshot) error { - m.lock.Lock() - defer m.lock.Unlock() - if m.pushChangeError { - return fmt.Errorf("mock push change error") - } else { - m.setUnsafe(id.Name, snapshot.(*proxytracker.ProxyState)) - } - return nil -} - -func (m *mockUpdater) ProxyConnectedToServer(_ *pbresource.ID) (string, bool) { - m.lock.Lock() - defer m.lock.Unlock() - if m.notConnected { - return "", false - } - return "atoken", true -} - -func (m *mockUpdater) EventChannel() chan controller.Event { - if m.eventChan == nil { - m.eventChan = make(chan controller.Event) - } - return m.eventChan -} - -func (p *mockUpdater) Get(name string) *proxytracker.ProxyState { - p.lock.Lock() - defer p.lock.Unlock() - ps, ok := p.latestPs[name] - if ok { - return ps.(*proxytracker.ProxyState) - } - return nil -} - -func (p *mockUpdater) GetEndpoints(name string) map[string]*pbproxystate.Endpoints { - p.lock.Lock() - defer p.lock.Unlock() - ps, ok := p.latestPs[name] - if ok { - return ps.(*proxytracker.ProxyState).Endpoints - } - return nil -} - -func (p *mockUpdater) GetLeafs(name string) map[string]*pbproxystate.LeafCertificate { - p.lock.Lock() - defer p.lock.Unlock() - ps, ok := p.latestPs[name] - if ok { - return ps.(*proxytracker.ProxyState).LeafCertificates - } - return nil -} - -func (p *mockUpdater) GetTrustBundle(name string) map[string]*pbproxystate.TrustBundle { - p.lock.Lock() - defer p.lock.Unlock() - ps, ok := p.latestPs[name] - if ok { - return ps.(*proxytracker.ProxyState).TrustBundles - } - return nil -} - -func (p *mockUpdater) Set(name string, ps *proxytracker.ProxyState) { - p.lock.Lock() - defer p.lock.Unlock() - p.setUnsafe(name, ps) -} - -func (p *mockUpdater) setUnsafe(name string, ps *proxytracker.ProxyState) { - p.latestPs[name] = ps -} diff --git a/internal/mesh/internal/controllers/xds/proxy_tracker_watch.go b/internal/mesh/internal/controllers/xds/proxy_tracker_watch.go deleted file mode 100644 index cf21dc0f7f40..000000000000 --- a/internal/mesh/internal/controllers/xds/proxy_tracker_watch.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "context" - "fmt" - - "github.com/hashicorp/consul/internal/controller" - proxytracker "github.com/hashicorp/consul/internal/mesh/proxy-tracker" -) - -func proxySource(updater ProxyUpdater) *controller.Source { - return &controller.Source{Source: updater.EventChannel()} -} - -func proxyMapper(ctx context.Context, rt controller.Runtime, event controller.Event) ([]controller.Request, error) { - connection, ok := event.Obj.(*proxytracker.ProxyConnection) - if !ok { - return nil, fmt.Errorf("expected event to be of type *proxytracker.ProxyConnection but was %+v", event) - } - return []controller.Request{{ID: connection.ProxyID}}, nil -} diff --git a/internal/mesh/internal/controllers/xds/reconciliation_data.go b/internal/mesh/internal/controllers/xds/reconciliation_data.go deleted file mode 100644 index cdbb3a1cd334..000000000000 --- a/internal/mesh/internal/controllers/xds/reconciliation_data.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package xds - -import ( - "context" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type ServiceEndpointsData struct { - Resource *pbresource.Resource - Endpoints *pbcatalog.ServiceEndpoints -} - -type ProxyStateTemplateData struct { - Resource *pbresource.Resource - Template *pbmesh.ProxyStateTemplate -} - -// getServiceEndpoints will return a non-nil &ServiceEndpointsData unless there is an error. -func getServiceEndpoints(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*ServiceEndpointsData, error) { - rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) - if err != nil { - return nil, err - } - - var se pbcatalog.ServiceEndpoints - err = rsp.Resource.Data.UnmarshalTo(&se) - if err != nil { - return nil, resource.NewErrDataParse(&se, err) - } - - return &ServiceEndpointsData{Resource: rsp.Resource, Endpoints: &se}, nil -} - -func getProxyStateTemplate(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*ProxyStateTemplateData, error) { - rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) - switch { - case status.Code(err) == codes.NotFound: - return nil, nil - case err != nil: - return nil, err - } - - var pst pbmesh.ProxyStateTemplate - err = rsp.Resource.Data.UnmarshalTo(&pst) - if err != nil { - return nil, resource.NewErrDataParse(&pst, err) - } - - return &ProxyStateTemplateData{Resource: rsp.Resource, Template: &pst}, nil -} diff --git a/internal/mesh/internal/controllers/xds/status/status.go b/internal/mesh/internal/controllers/xds/status/status.go deleted file mode 100644 index 145451f91471..000000000000 --- a/internal/mesh/internal/controllers/xds/status/status.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package status - -import ( - "context" - "fmt" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - StatusConditionProxyStateAccepted = "ProxyStateAccepted" - StatusReasonNilProxyState = "ProxyStateNil" - StatusReasonProxyStateReferencesComputed = "ProxyStateReferencesComputed" - StatusReasonEndpointNotRead = "ProxyStateEndpointReferenceReadError" - StatusReasonCreatingProxyStateEndpointsFailed = "ProxyStateEndpointsNotComputed" - StatusReasonPushChangeFailed = "ProxyStatePushChangeFailed" - StatusReasonTrustBundleFetchFailed = "ProxyStateTrustBundleFetchFailed" - StatusReasonLeafWatchSetupFailed = "ProxyStateLeafWatchSetupError" - StatusReasonLeafFetchFailed = "ProxyStateLeafFetchError" - StatusReasonLeafEmpty = "ProxyStateLeafEmptyError" -) - -func KeyFromID(id *pbresource.ID) string { - return fmt.Sprintf("%s/%s/%s", - resource.ToGVK(id.Type), - resource.TenancyToString(id.Tenancy), - id.Name) -} - -func ConditionAccepted() *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_TRUE, - Reason: StatusReasonProxyStateReferencesComputed, - Message: fmt.Sprintf("proxy state was computed and pushed."), - } -} -func ConditionRejectedNilProxyState(pstRef string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonNilProxyState, - Message: fmt.Sprintf("nil proxy state is not valid %q.", pstRef), - } -} -func ConditionRejectedErrorCreatingLeafWatch(leafRef string, err string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonLeafWatchSetupFailed, - Message: fmt.Sprintf("error creating leaf watch %q: %s", leafRef, err), - } -} -func ConditionRejectedErrorGettingLeaf(leafRef string, err string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonLeafFetchFailed, - Message: fmt.Sprintf("error getting leaf from leaf certificate manager %q: %s", leafRef, err), - } -} -func ConditionRejectedErrorCreatingProxyStateLeaf(leafRef string, err string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonLeafEmpty, - Message: fmt.Sprintf("error getting leaf certificate contents %q: %s", leafRef, err), - } -} -func ConditionRejectedErrorReadingEndpoints(endpointRef string, err string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonEndpointNotRead, - Message: fmt.Sprintf("error reading referenced service endpoints %q: %s", endpointRef, err), - } -} -func ConditionRejectedCreatingProxyStateEndpoints(endpointRef string, err string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonCreatingProxyStateEndpointsFailed, - Message: fmt.Sprintf("could not create proxy state endpoints from service endpoints %q: %s", endpointRef, err), - } -} -func ConditionRejectedPushChangeFailed(pstRef string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonPushChangeFailed, - Message: fmt.Sprintf("failed to push change for proxy state template %q", pstRef), - } -} -func ConditionRejectedTrustBundleFetchFailed(pstRef string) *pbresource.Condition { - return &pbresource.Condition{ - Type: StatusConditionProxyStateAccepted, - State: pbresource.Condition_STATE_FALSE, - Reason: StatusReasonTrustBundleFetchFailed, - Message: fmt.Sprintf("failed to fetch trust bundle for proxy state template %q", pstRef), - } -} - -// WriteStatusIfChanged updates the ProxyStateTemplate status if it has changed. -func WriteStatusIfChanged(ctx context.Context, rt controller.Runtime, res *pbresource.Resource, condition *pbresource.Condition) { - newStatus := &pbresource.Status{ - ObservedGeneration: res.Generation, - Conditions: []*pbresource.Condition{ - condition, - }, - } - // If the status is unchanged then we should return and avoid the unnecessary write - const controllerName = "consul.io/xds-controller" - if resource.EqualStatus(res.Status[controllerName], newStatus, false) { - return - } else { - _, err := rt.Client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ - Id: res.Id, - Key: controllerName, - Status: newStatus, - }) - - if err != nil { - rt.Logger.Error("error updating the proxy state template status", "error", err, "proxyStateTeamplate", res.Id) - } - } -} diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden deleted file mode 100644 index dd425312053b..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/destination/l4-implicit-and-explicit-destinations-tproxy.golden +++ /dev/null @@ -1,185 +0,0 @@ -{ - "clusters": { - "original-destination": { - "endpointGroup": { - "passthrough": { - "config": { - "connectTimeout": "5s" - } - } - }, - "name": "original-destination", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 1234 - }, - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-1.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-1.default.default.dc1" - } - } - ] - }, - { - "capabilities": [ - "CAPABILITY_TRANSPARENT" - ], - "defaultRouter": { - "l4": { - "cluster": { - "name": "original-destination" - }, - "statPrefix": "upstream.original-destination" - } - }, - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 - }, - "name": "outbound_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-2.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - } - } - ] - } - ], - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-multi-destination.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-multi-destination.golden deleted file mode 100644 index 70448ca45048..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/destination/l4-multi-destination.golden +++ /dev/null @@ -1,301 +0,0 @@ -{ - "clusters": { - "null_route_cluster": { - "endpointGroup": { - "static": { - "config": { - "connectTimeout": "10s" - } - } - }, - "name": "null_route_cluster", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp2.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp2.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp2" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp2.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp2.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp2.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp2" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp2.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp2.api-1.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp2.api-2.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 1234 - }, - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "routers": [ - { - "l4": { - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - } - } - ] - }, - { - "direction": "DIRECTION_OUTBOUND", - "name": "default/local/default/api-2:tcp:/path/to/socket", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-2.default.default.dc1" - } - } - ], - "unixSocket": { - "mode": "0666", - "path": "/path/to/socket" - } - }, - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 2345 - }, - "name": "default/local/default/api-1:tcp2:1.1.1.1:2345", - "routers": [ - { - "l4": { - "statPrefix": "upstream.tcp2.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp2.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp2.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - } - } - ] - }, - { - "direction": "DIRECTION_OUTBOUND", - "name": "default/local/default/api-2:tcp2:/path/to/socket", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp2.api-2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp2.api-2.default.default.dc1" - } - } - ], - "unixSocket": { - "mode": "0666", - "path": "/path/to/socket" - } - } - ], - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden deleted file mode 100644 index 24c917a4d338..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/destination/l4-multiple-implicit-destinations-tproxy.golden +++ /dev/null @@ -1,184 +0,0 @@ -{ - "clusters": { - "original-destination": { - "endpointGroup": { - "passthrough": { - "config": { - "connectTimeout": "5s" - } - } - }, - "name": "original-destination", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_TRANSPARENT" - ], - "defaultRouter": { - "l4": { - "cluster": { - "name": "original-destination" - }, - "statPrefix": "upstream.original-destination" - } - }, - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 - }, - "name": "outbound_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-1.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-1.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l4": { - "cluster": { - "name": "tcp.api-2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-2.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - } - } - ] - } - ], - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden deleted file mode 100644 index d3657463fde9..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-ip-port-bind-address.golden +++ /dev/null @@ -1,156 +0,0 @@ -{ - "clusters": { - "null_route_cluster": { - "endpointGroup": { - "static": { - "config": { - "connectTimeout": "10s" - } - } - }, - "name": "null_route_cluster", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 1234 - }, - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "routers": [ - { - "l4": { - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - } - } - ] - } - ], - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-unix-socket-bind-address.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-unix-socket-bind-address.golden deleted file mode 100644 index 19ca75501d5b..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-destination-unix-socket-bind-address.golden +++ /dev/null @@ -1,93 +0,0 @@ -{ - "clusters": { - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "tcp.api-2.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "direction": "DIRECTION_OUTBOUND", - "name": "default/local/default/api-2:tcp:/path/to/socket", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-2.default.default.dc1" - } - } - ], - "unixSocket": { - "mode": "0666", - "path": "/path/to/socket" - } - } - ], - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-implicit-destination-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-implicit-destination-tproxy.golden deleted file mode 100644 index 780d2a6f49a8..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/destination/l4-single-implicit-destination-tproxy.golden +++ /dev/null @@ -1,124 +0,0 @@ -{ - "clusters": { - "original-destination": { - "endpointGroup": { - "passthrough": { - "config": { - "connectTimeout": "5s" - } - } - }, - "name": "original-destination", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "tcp.api-1.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_TRANSPARENT" - ], - "defaultRouter": { - "l4": { - "cluster": { - "name": "original-destination" - }, - "statPrefix": "upstream.original-destination" - } - }, - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 - }, - "name": "outbound_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-1.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-1.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - } - ] - } - ], - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden b/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden deleted file mode 100644 index 3acd9869e51d..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/destination/mixed-multi-destination.golden +++ /dev/null @@ -1,380 +0,0 @@ -{ - "clusters": { - "http.api-1.default.dc1.internal.foo.consul": { - "altStatName": "http.api-1.default.dc1.internal.foo.consul", - "failoverGroup": { - "config": { - "connectTimeout": "55s", - "useAltStatName": true - }, - "endpointGroups": [ - { - "dynamic": { - "config": { - "connectTimeout": "55s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - }, - "name": "failover-target~0~http.api-1.default.dc1.internal.foo.consul" - }, - { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "backup-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/backup1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - }, - "name": "failover-target~1~http.api-1.default.dc1.internal.foo.consul" - } - ] - }, - "name": "http.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_HTTP" - }, - "http.api-2.default.dc1.internal.foo.consul": { - "altStatName": "http.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "http.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_HTTP" - }, - "null_route_cluster": { - "endpointGroup": { - "static": { - "config": { - "connectTimeout": "10s" - } - } - }, - "name": "null_route_cluster", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-1.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-1.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api1-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "http.api-1.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "http.api-2.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp.api-1.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp.api-2.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 1234 - }, - "name": "default/local/default/api-1:tcp:1.1.1.1:1234", - "routers": [ - { - "l4": { - "statPrefix": "upstream.tcp.api-1.default.default.dc1", - "weightedClusters": { - "clusters": [ - { - "name": "tcp.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "tcp.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - } - } - ] - }, - { - "direction": "DIRECTION_OUTBOUND", - "name": "default/local/default/api-2:tcp:/path/to/socket", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-2.default.default.dc1" - } - } - ], - "unixSocket": { - "mode": "0666", - "path": "/path/to/socket" - } - }, - { - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "1.1.1.1", - "port": 1234 - }, - "name": "default/local/default/api-1:http:1.1.1.1:1234", - "routers": [ - { - "l7": { - "route": { - "name": "default/local/default/api-1:http:1.1.1.1:1234" - }, - "statPrefix": "upstream.http.api-1.default.default.dc1" - } - } - ] - } - ], - "routes": { - "default/local/default/api-1:http:1.1.1.1:1234": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "default/local/default/api-1:http:1.1.1.1:1234", - "routeRules": [ - { - "destination": { - "destinationConfiguration": { - "timeoutConfig": { - "timeout": "77s" - } - }, - "weightedClusters": { - "clusters": [ - { - "name": "http.api-2.default.dc1.internal.foo.consul", - "weight": 60 - }, - { - "name": "http.api-1.default.dc1.internal.foo.consul", - "weight": 40 - }, - { - "name": "null_route_cluster", - "weight": 10 - } - ] - } - }, - "match": { - "pathMatch": { - "prefix": "/split" - } - } - }, - { - "destination": { - "cluster": { - "name": "http.api-1.default.dc1.internal.foo.consul" - }, - "destinationConfiguration": { - "retryPolicy": { - "numRetries": 4, - "retryOn": "connect-failure" - }, - "timeoutConfig": { - "timeout": "606s" - } - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - }, - { - "destination": { - "cluster": { - "name": "null_route_cluster" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - }, - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden deleted file mode 100644 index 0158f07aa2c5..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-multiple-implicit-destinations-tproxy.golden +++ /dev/null @@ -1,466 +0,0 @@ -{ - "clusters": { - "http.api-app.default.dc1.internal.foo.consul": { - "altStatName": "http.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "http.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_HTTP" - }, - "http.api-app2.default.dc1.internal.foo.consul": { - "altStatName": "http.api-app2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "http.api-app2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_HTTP" - }, - "original-destination": { - "endpointGroup": { - "passthrough": { - "config": { - "connectTimeout": "5s" - } - } - }, - "name": "original-destination", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-app.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-app2.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-app2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-app2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp2.api-app.default.dc1.internal.foo.consul": { - "altStatName": "tcp2.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp2" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp2.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp2.api-app2.default.dc1.internal.foo.consul": { - "altStatName": "tcp2.api-app2.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp2" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app2.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app2-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp2.api-app2.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "http.api-app.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "http.api-app2.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp.api-app.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp.api-app2.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp2.api-app.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp2.api-app2.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_TRANSPARENT" - ], - "defaultRouter": { - "l4": { - "cluster": { - "name": "original-destination" - }, - "statPrefix": "upstream.original-destination" - } - }, - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 - }, - "name": "outbound_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-app.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l4": { - "cluster": { - "name": "tcp.api-app2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-app2.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - } - }, - { - "l7": { - "route": { - "name": "default/local/default/api-app:http" - }, - "statPrefix": "upstream.http.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 8080, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l7": { - "route": { - "name": "default/local/default/api-app2:http" - }, - "statPrefix": "upstream.http.api-app2.default.default.dc1" - }, - "match": { - "destinationPort": 8080, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - } - }, - { - "l4": { - "cluster": { - "name": "tcp2.api-app.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp2.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 8081, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l4": { - "cluster": { - "name": "tcp2.api-app2.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp2.api-app2.default.default.dc1" - }, - "match": { - "destinationPort": 8081, - "prefixRanges": [ - { - "addressPrefix": "2.2.2.2", - "prefixLen": 32 - }, - { - "addressPrefix": "3.3.3.3", - "prefixLen": 32 - } - ] - } - } - ] - } - ], - "routes": { - "default/local/default/api-app2:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "default/local/default/api-app2:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "http.api-app2.default.dc1.internal.foo.consul" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "default/local/default/api-app:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "default/local/default/api-app:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "http.api-app.default.dc1.internal.foo.consul" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - }, - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden deleted file mode 100644 index 3c9d62fb4ea1..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-tproxy.golden +++ /dev/null @@ -1,262 +0,0 @@ -{ - "clusters": { - "http.api-app.default.dc1.internal.foo.consul": { - "altStatName": "http.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "http.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_HTTP" - }, - "original-destination": { - "endpointGroup": { - "passthrough": { - "config": { - "connectTimeout": "5s" - } - } - }, - "name": "original-destination", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-app.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp2.api-app.default.dc1.internal.foo.consul": { - "altStatName": "tcp2.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp2" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp2.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "http.api-app.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp.api-app.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp2.api-app.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_TRANSPARENT" - ], - "defaultRouter": { - "l4": { - "cluster": { - "name": "original-destination" - }, - "statPrefix": "upstream.original-destination" - } - }, - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 - }, - "name": "outbound_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-app.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l7": { - "route": { - "name": "default/local/default/api-app:http" - }, - "statPrefix": "upstream.http.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 8080, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l4": { - "cluster": { - "name": "tcp2.api-app.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp2.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 8081, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - } - ] - } - ], - "routes": { - "default/local/default/api-app:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "default/local/default/api-app:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "http.api-app.default.dc1.internal.foo.consul" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - }, - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden b/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden deleted file mode 100644 index 3c9d62fb4ea1..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/destination/multiport-l4-and-l7-single-implicit-destination-with-multiple-workloads-tproxy.golden +++ /dev/null @@ -1,262 +0,0 @@ -{ - "clusters": { - "http.api-app.default.dc1.internal.foo.consul": { - "altStatName": "http.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~http" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "http.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_HTTP" - }, - "original-destination": { - "endpointGroup": { - "passthrough": { - "config": { - "connectTimeout": "5s" - } - } - }, - "name": "original-destination", - "protocol": "PROTOCOL_TCP" - }, - "tcp.api-app.default.dc1.internal.foo.consul": { - "altStatName": "tcp.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - }, - "tcp2.api-app.default.dc1.internal.foo.consul": { - "altStatName": "tcp2.api-app.default.dc1.internal.foo.consul", - "endpointGroup": { - "dynamic": { - "config": { - "connectTimeout": "5s", - "disablePanicThreshold": true - }, - "outboundTls": { - "alpnProtocols": [ - "consul~tcp2" - ], - "outboundMesh": { - "identityKey": "test-identity", - "sni": "api-app.default.dc1.internal.foo.consul", - "validationContext": { - "spiffeIds": [ - "spiffe://foo.consul/ap/default/ns/default/identity/api-app-identity" - ], - "trustBundlePeerNameKey": "local" - } - } - } - } - }, - "name": "tcp2.api-app.default.dc1.internal.foo.consul", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "http.api-app.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp.api-app.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - }, - "tcp2.api-app.default.dc1.internal.foo.consul": { - "endpoints": [ - { - "healthStatus": "HEALTH_STATUS_HEALTHY", - "hostPort": { - "host": "10.1.1.1", - "port": 20000 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_TRANSPARENT" - ], - "defaultRouter": { - "l4": { - "cluster": { - "name": "original-destination" - }, - "statPrefix": "upstream.original-destination" - } - }, - "direction": "DIRECTION_OUTBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 15001 - }, - "name": "outbound_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "tcp.api-app.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 7070, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l7": { - "route": { - "name": "default/local/default/api-app:http" - }, - "statPrefix": "upstream.http.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 8080, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - }, - { - "l4": { - "cluster": { - "name": "tcp2.api-app.default.dc1.internal.foo.consul" - }, - "statPrefix": "upstream.tcp2.api-app.default.default.dc1" - }, - "match": { - "destinationPort": 8081, - "prefixRanges": [ - { - "addressPrefix": "1.1.1.1", - "prefixLen": 32 - } - ] - } - } - ] - } - ], - "routes": { - "default/local/default/api-app:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "default/local/default/api-app:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "http.api-app.default.dc1.internal.foo.consul" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - }, - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/source/l7-expose-paths.golden b/internal/mesh/internal/controllers/xds/testdata/source/l7-expose-paths.golden deleted file mode 100644 index 994b00f41514..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/source/l7-expose-paths.golden +++ /dev/null @@ -1,213 +0,0 @@ -{ - "clusters": { - "exposed_cluster_9090": { - "endpointGroup": { - "static": {} - }, - "name": "exposed_cluster_9090", - "protocol": "PROTOCOL_HTTP" - }, - "exposed_cluster_9091": { - "endpointGroup": { - "static": {} - }, - "name": "exposed_cluster_9091", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:port1": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:port1", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "exposed_cluster_9090": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - }, - "exposed_cluster_9091": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9091 - } - } - ] - }, - "local_app:port1": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:port1" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~port1" - ] - } - } - ] - }, - { - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 1234 - }, - "name": "exposed_path_health1234", - "routers": [ - { - "l7": { - "route": { - "name": "exposed_path_route_health1234" - }, - "statPrefix": "exposed_path_route_health1234", - "staticRoute": true - } - } - ] - }, - { - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 1235 - }, - "name": "exposed_path_GetHealth1235", - "routers": [ - { - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "exposed_path_route_GetHealth1235" - }, - "statPrefix": "exposed_path_route_GetHealth1235", - "staticRoute": true - } - } - ] - } - ], - "routes": { - "exposed_path_route_GetHealth1235": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "exposed_path_route_GetHealth1235", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "exposed_cluster_9091" - } - }, - "match": { - "pathMatch": { - "exact": "GetHealth" - } - } - } - ] - } - ] - }, - "exposed_path_route_health1234": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "exposed_path_route_health1234", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "exposed_cluster_9090" - } - }, - "match": { - "pathMatch": { - "exact": "/health" - } - } - } - ] - } - ] - } - }, - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/source/local-and-inbound-connections.golden b/internal/mesh/internal/controllers/xds/testdata/source/local-and-inbound-connections.golden deleted file mode 100644 index f75354038bf4..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/source/local-and-inbound-connections.golden +++ /dev/null @@ -1,305 +0,0 @@ -{ - "clusters": { - "exposed_cluster_9090": { - "endpointGroup": { - "static": {} - }, - "name": "exposed_cluster_9090", - "protocol": "PROTOCOL_HTTP" - }, - "exposed_cluster_9091": { - "endpointGroup": { - "static": {} - }, - "name": "exposed_cluster_9091", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:port1": { - "endpointGroup": { - "static": { - "config": { - "circuitBreakers": { - "upstreamLimits": { - "maxConnections": 123 - } - }, - "connectTimeout": "6s" - } - } - }, - "name": "local_app:port1", - "protocol": "PROTOCOL_TCP" - }, - "local_app:port3": { - "endpointGroup": { - "static": { - "config": { - "circuitBreakers": { - "upstreamLimits": { - "maxConnections": 123 - } - }, - "connectTimeout": "8s" - } - } - }, - "name": "local_app:port3", - "protocol": "PROTOCOL_HTTP" - } - }, - "endpoints": { - "exposed_cluster_9090": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - }, - "exposed_cluster_9091": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9091 - } - } - ] - }, - "local_app:port1": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:port3": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8081 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "balanceConnections": "BALANCE_CONNECTIONS_EXACT", - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:port1" - }, - "maxInboundConnections": "123", - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~port1" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "maxInboundConnections": "123", - "route": { - "name": "public_listener:port3" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~port3" - ] - } - } - ] - }, - { - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 1234 - }, - "name": "exposed_path_health1234", - "routers": [ - { - "l7": { - "route": { - "name": "exposed_path_route_health1234" - }, - "statPrefix": "exposed_path_route_health1234", - "staticRoute": true - } - } - ] - }, - { - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 1235 - }, - "name": "exposed_path_GetHealth1235", - "routers": [ - { - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "exposed_path_route_GetHealth1235" - }, - "statPrefix": "exposed_path_route_GetHealth1235", - "staticRoute": true - } - } - ] - } - ], - "routes": { - "exposed_path_route_GetHealth1235": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "exposed_path_route_GetHealth1235", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "exposed_cluster_9091" - } - }, - "match": { - "pathMatch": { - "exact": "GetHealth" - } - } - } - ] - } - ] - }, - "exposed_path_route_health1234": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "exposed_path_route_health1234", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "exposed_cluster_9090" - } - }, - "match": { - "pathMatch": { - "exact": "/health" - } - } - } - ] - } - ] - }, - "public_listener:port3": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:port3", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:port3" - }, - "destinationConfiguration": { - "timeoutConfig": { - "timeout": "9s" - } - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - }, - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/source/multiple-workload-addresses-with-specific-ports.golden b/internal/mesh/internal/controllers/xds/testdata/source/multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index b67d034c7e34..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/source/multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,292 +0,0 @@ -{ - "clusters": { - "local_app:grpc": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:grpc", - "protocol": "PROTOCOL_GRPC" - }, - "local_app:http": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:http", - "protocol": "PROTOCOL_HTTP" - }, - "local_app:http2": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:http2", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:tcp": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:tcp", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "local_app:grpc": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8083 - } - } - ] - }, - "local_app:http": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8081 - } - } - ] - }, - "local_app:http2": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8082 - } - } - ] - }, - "local_app:tcp": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "127.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_GRPC", - "route": { - "name": "public_listener:grpc" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~grpc" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "route": { - "name": "public_listener:http" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~http" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "public_listener:http2" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~http2" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:tcp" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~tcp" - ] - } - } - ] - } - ], - "routes": { - "public_listener:grpc": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:grpc", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:grpc" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:http" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:http2": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:http2", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:http2" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - }, - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/source/multiple-workload-addresses-without-ports.golden b/internal/mesh/internal/controllers/xds/testdata/source/multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 8b0491894865..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/source/multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,292 +0,0 @@ -{ - "clusters": { - "local_app:grpc": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:grpc", - "protocol": "PROTOCOL_GRPC" - }, - "local_app:http": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:http", - "protocol": "PROTOCOL_HTTP" - }, - "local_app:http2": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:http2", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:tcp": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:tcp", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "local_app:grpc": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8083 - } - } - ] - }, - "local_app:http": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8081 - } - } - ] - }, - "local_app:http2": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8082 - } - } - ] - }, - "local_app:tcp": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_GRPC", - "route": { - "name": "public_listener:grpc" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~grpc" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "route": { - "name": "public_listener:http" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~http" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "public_listener:http2" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~http2" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:tcp" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~tcp" - ] - } - } - ] - } - ], - "routes": { - "public_listener:grpc": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:grpc", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:grpc" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:http" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:http2": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:http2", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:http2" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - }, - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden b/internal/mesh/internal/controllers/xds/testdata/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index e2798c8d4e49..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l4-multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,131 +0,0 @@ -{ - "clusters": { - "local_app:admin-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:admin-port", - "protocol": "PROTOCOL_TCP" - }, - "local_app:api-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:api-port", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.3", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:admin-port" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:api-port" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~api-port" - ] - } - } - ] - } - ], - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l4-multiple-workload-addresses-without-ports.golden b/internal/mesh/internal/controllers/xds/testdata/source/multiport-l4-multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 21402c187b5e..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l4-multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,131 +0,0 @@ -{ - "clusters": { - "local_app:admin-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:admin-port", - "protocol": "PROTOCOL_TCP" - }, - "local_app:api-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:api-port", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:admin-port" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:api-port" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~api-port" - ] - } - } - ] - } - ], - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l4-single-workload-address-without-ports.golden b/internal/mesh/internal/controllers/xds/testdata/source/multiport-l4-single-workload-address-without-ports.golden deleted file mode 100644 index 1487da213341..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l4-single-workload-address-without-ports.golden +++ /dev/null @@ -1,129 +0,0 @@ -{ - "clusters": { - "local_app:admin-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:admin-port" - }, - "local_app:api-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:api-port" - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:admin-port" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:api-port" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~api-port" - ] - } - } - ] - } - ], - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l4-workload-with-only-mesh-port.golden b/internal/mesh/internal/controllers/xds/testdata/source/multiport-l4-workload-with-only-mesh-port.golden deleted file mode 100644 index 92f491e9e04d..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l4-workload-with-only-mesh-port.golden +++ /dev/null @@ -1,62 +0,0 @@ -{ - "clusters": { - "black-hole-cluster": { - "endpointGroup": { - "static": {} - }, - "name": "black-hole-cluster", - "protocol": "PROTOCOL_TCP" - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "l4": { - "cluster": { - "name": "black-hole-cluster" - }, - "statPrefix": "public_listener" - } - } - ] - } - ], - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden b/internal/mesh/internal/controllers/xds/testdata/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden deleted file mode 100644 index fdab88cd7c18..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l7-multiple-workload-addresses-with-specific-ports.golden +++ /dev/null @@ -1,184 +0,0 @@ -{ - "clusters": { - "local_app:admin-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:admin-port", - "protocol": "PROTOCOL_HTTP" - }, - "local_app:api-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:api-port", - "protocol": "PROTOCOL_HTTP2" - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.3", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "route": { - "name": "public_listener:admin-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "public_listener:api-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~api-port" - ] - } - } - ] - } - ], - "routes": { - "public_listener:admin-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:admin-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:admin-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:api-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:api-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:api-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - }, - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l7-multiple-workload-addresses-without-ports.golden b/internal/mesh/internal/controllers/xds/testdata/source/multiport-l7-multiple-workload-addresses-without-ports.golden deleted file mode 100644 index 3403eed7a864..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l7-multiple-workload-addresses-without-ports.golden +++ /dev/null @@ -1,251 +0,0 @@ -{ - "clusters": { - "local_app:admin-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:admin-port", - "protocol": "PROTOCOL_HTTP" - }, - "local_app:api-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:api-port", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:grpc-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:grpc-port", - "protocol": "PROTOCOL_GRPC" - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - }, - "local_app:grpc-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9091 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "route": { - "name": "public_listener:admin-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "public_listener:api-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~api-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_GRPC", - "route": { - "name": "public_listener:grpc-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~grpc-port" - ] - } - } - ] - } - ], - "routes": { - "public_listener:admin-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:admin-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:admin-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:api-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:api-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:api-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:grpc-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:grpc-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:grpc-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - }, - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l7-single-workload-address-without-ports.golden b/internal/mesh/internal/controllers/xds/testdata/source/multiport-l7-single-workload-address-without-ports.golden deleted file mode 100644 index 460ede98100a..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/source/multiport-l7-single-workload-address-without-ports.golden +++ /dev/null @@ -1,248 +0,0 @@ -{ - "clusters": { - "local_app:admin-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:admin-port" - }, - "local_app:api-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:api-port" - }, - "local_app:grpc-port": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:grpc-port" - } - }, - "endpoints": { - "local_app:admin-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - }, - "local_app:api-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9090 - } - } - ] - }, - "local_app:grpc-port": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 9091 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "route": { - "name": "public_listener:admin-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~admin-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "public_listener:api-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~api-port" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_GRPC", - "route": { - "name": "public_listener:grpc-port" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~grpc-port" - ] - } - } - ] - } - ], - "routes": { - "public_listener:admin-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:admin-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:admin-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:api-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:api-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:api-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:grpc-port": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:grpc-port", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:grpc-port" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - }, - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/controllers/xds/testdata/source/single-workload-address-without-ports.golden b/internal/mesh/internal/controllers/xds/testdata/source/single-workload-address-without-ports.golden deleted file mode 100644 index 8b0491894865..000000000000 --- a/internal/mesh/internal/controllers/xds/testdata/source/single-workload-address-without-ports.golden +++ /dev/null @@ -1,292 +0,0 @@ -{ - "clusters": { - "local_app:grpc": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:grpc", - "protocol": "PROTOCOL_GRPC" - }, - "local_app:http": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:http", - "protocol": "PROTOCOL_HTTP" - }, - "local_app:http2": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:http2", - "protocol": "PROTOCOL_HTTP2" - }, - "local_app:tcp": { - "endpointGroup": { - "static": {} - }, - "name": "local_app:tcp", - "protocol": "PROTOCOL_TCP" - } - }, - "endpoints": { - "local_app:grpc": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8083 - } - } - ] - }, - "local_app:http": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8081 - } - } - ] - }, - "local_app:http2": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8082 - } - } - ] - }, - "local_app:tcp": { - "endpoints": [ - { - "hostPort": { - "host": "127.0.0.1", - "port": 8080 - } - } - ] - } - }, - "identity": { - "name": "test-identity", - "tenancy": { - "namespace": "default", - "partition": "default", - "peerName": "local" - }, - "type": { - "group": "auth", - "groupVersion": "v2beta1", - "kind": "WorkloadIdentity" - } - }, - "leafCertificates": { - "test-identity": { - "cert": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBAjAKBggqhkjOPQQDAjAUMRIwEAYDVQQDEwlUZXN0IENB\nIDEwHhcNMjMxMDE2MTYxMzI5WhcNMjMxMDE2MTYyMzI5WjAAMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9\nta/bGT+5orZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJaOCAQowggEGMA4GA1UdDwEB\n/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/\nBAIwADApBgNVHQ4EIgQg3ogXVz9cqaK2B6xdiJYMa5NtT0KkYv7BA2dR7h9EcwUw\nKwYDVR0jBCQwIoAgq+C1mPlPoGa4lt7sSft1goN5qPGyBIB/3mUHJZKSFY8wbwYD\nVR0RAQH/BGUwY4Zhc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9hcC9kZWZhdWx0L25zL2RlZmF1bHQvaWRlbnRpdHkv\ndGVzdC1pZGVudGl0eTAKBggqhkjOPQQDAgNHADBEAiB6L+t5bzRrBPhiQYNeA7fF\nUCuLWrdjW4Xbv3SLg0IKMgIgfRC5hEx+DqzQxTCP4sexX3hVWMjKoWmHdwiUcg+K\n/IE=\n-----END CERTIFICATE-----\n", - "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIFIFkTIL1iUV4O/RpveVHzHs7ZzhSkvYIzbdXDttz9EooAoGCCqGSM49\nAwEHoUQDQgAErErAIosDPheZQGbxFQ4hYC/e9Fi4MG9z/zjfCnCq/oK9ta/bGT+5\norZqTmdN/ICsKQDhykxZ2u/Xr6845zhcJQ==\n-----END EC PRIVATE KEY-----\n" - } - }, - "listeners": [ - { - "capabilities": [ - "CAPABILITY_L4_TLS_INSPECTION" - ], - "direction": "DIRECTION_INBOUND", - "hostPort": { - "host": "10.0.0.1", - "port": 20000 - }, - "name": "public_listener", - "routers": [ - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_GRPC", - "route": { - "name": "public_listener:grpc" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~grpc" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "route": { - "name": "public_listener:http" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~http" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l7": { - "protocol": "L7_PROTOCOL_HTTP2", - "route": { - "name": "public_listener:http2" - }, - "statPrefix": "public_listener", - "staticRoute": true, - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~http2" - ] - } - }, - { - "inboundTls": { - "inboundMesh": { - "identityKey": "test-identity", - "validationContext": { - "trustBundlePeerNameKeys": [ - "local" - ] - } - } - }, - "l4": { - "cluster": { - "name": "local_app:tcp" - }, - "statPrefix": "public_listener", - "trafficPermissions": {} - }, - "match": { - "alpnProtocols": [ - "consul~tcp" - ] - } - } - ] - } - ], - "routes": { - "public_listener:grpc": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:grpc", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:grpc" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:http": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:http", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:http" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - }, - "public_listener:http2": { - "virtualHosts": [ - { - "domains": [ - "*" - ], - "name": "public_listener:http2", - "routeRules": [ - { - "destination": { - "cluster": { - "name": "local_app:http2" - } - }, - "match": { - "pathMatch": { - "prefix": "/" - } - } - } - ] - } - ] - } - }, - "trustBundles": { - "local": { - "roots": [ - "some-root", - "some-other-root" - ], - "trustDomain": "some-trust-domain" - } - } -} \ No newline at end of file diff --git a/internal/mesh/internal/mappers/common/workload_selector_util.go b/internal/mesh/internal/mappers/common/workload_selector_util.go deleted file mode 100644 index 90d96b8f9b47..000000000000 --- a/internal/mesh/internal/mappers/common/workload_selector_util.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package common - -import ( - "context" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// MapSelector returns requests of the provided type given a workload -// selector and tenancy. The type has to be name-aligned with the workload. -func MapSelector(ctx context.Context, - client pbresource.ResourceServiceClient, - typ *pbresource.Type, - selector *pbcatalog.WorkloadSelector, - tenancy *pbresource.Tenancy) ([]controller.Request, error) { - if selector == nil { - return nil, nil - } - - var result []controller.Request - - for _, prefix := range selector.GetPrefixes() { - resp, err := client.List(ctx, &pbresource.ListRequest{ - Type: pbcatalog.WorkloadType, - Tenancy: tenancy, - NamePrefix: prefix, - }) - if err != nil { - return nil, err - } - for _, r := range resp.Resources { - id := resource.ReplaceType(typ, r.Id) - result = append(result, controller.Request{ - ID: id, - }) - } - } - - // We don't do lookups for names as this should be done in the controller's reconcile. - for _, name := range selector.GetNames() { - id := &pbresource.ID{ - Name: name, - Tenancy: tenancy, - Type: typ, - } - result = append(result, controller.Request{ - ID: id, - }) - } - - return result, nil -} diff --git a/internal/mesh/internal/mappers/common/workload_selector_util_test.go b/internal/mesh/internal/mappers/common/workload_selector_util_test.go deleted file mode 100644 index 6f9e71e1af54..000000000000 --- a/internal/mesh/internal/mappers/common/workload_selector_util_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package common - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestMapSelector(t *testing.T) { - client := svctest.RunResourceService(t, types.Register, catalog.RegisterTypes) - - // Create some workloads. - // For this test, we don't care about the workload data, so we will re-use - // the same data for all workloads. - workloadData := &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "127.0.0.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{"p1": {Port: 8080}}, - } - w1 := resourcetest.Resource(pbcatalog.WorkloadType, "w1"). - WithData(t, workloadData). - Write(t, client).Id - w2 := resourcetest.Resource(pbcatalog.WorkloadType, "w2"). - WithData(t, workloadData). - Write(t, client).Id - w3 := resourcetest.Resource(pbcatalog.WorkloadType, "prefix-w3"). - WithData(t, workloadData). - Write(t, client).Id - w4 := resourcetest.Resource(pbcatalog.WorkloadType, "prefix-w4"). - WithData(t, workloadData). - Write(t, client).Id - // This workload should not be used as it's not selected by the workload selector. - resourcetest.Resource(pbcatalog.WorkloadType, "not-selected-workload"). - WithData(t, workloadData). - Write(t, client) - - selector := &pbcatalog.WorkloadSelector{ - Names: []string{"w1", "w2"}, - Prefixes: []string{"prefix"}, - } - expReqs := []controller.Request{ - {ID: resource.ReplaceType(pbmesh.ProxyStateTemplateType, w1)}, - {ID: resource.ReplaceType(pbmesh.ProxyStateTemplateType, w2)}, - {ID: resource.ReplaceType(pbmesh.ProxyStateTemplateType, w3)}, - {ID: resource.ReplaceType(pbmesh.ProxyStateTemplateType, w4)}, - } - - reqs, err := MapSelector(context.Background(), client, - pbmesh.ProxyStateTemplateType, selector, resource.DefaultNamespacedTenancy()) - require.NoError(t, err) - require.Len(t, reqs, len(expReqs)) - prototest.AssertElementsMatch(t, expReqs, reqs) -} diff --git a/internal/mesh/internal/mappers/workloadselectionmapper/workload_selection_mapper.go b/internal/mesh/internal/mappers/workloadselectionmapper/workload_selection_mapper.go deleted file mode 100644 index 7b064248414b..000000000000 --- a/internal/mesh/internal/mappers/workloadselectionmapper/workload_selection_mapper.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package workloadselectionmapper - -import ( - "context" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/mappers/common" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/mappers/selectiontracker" - "github.com/hashicorp/consul/lib/stringslice" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type Mapper[T catalog.WorkloadSelecting] struct { - workloadSelectionTracker *selectiontracker.WorkloadSelectionTracker - computedType *pbresource.Type -} - -func New[T catalog.WorkloadSelecting](computedType *pbresource.Type) *Mapper[T] { - if computedType == nil { - panic("computed type is required") - } - return &Mapper[T]{ - workloadSelectionTracker: selectiontracker.New(), - computedType: computedType, - } -} - -// MapToComputedType is responsible for mapping types with workload selectors to the corresponding computed type -// resources which are name-aligned with the workload. This function will also track workload selectors with the ids -// from the workload-selectable types in the mapper. -func (m *Mapper[T]) MapToComputedType(ctx context.Context, rt controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - dec, err := resource.Decode[T](res) - if err != nil { - return nil, err - } - - // First, we return any existing workloads that this proxy configuration selects. - // The number of selected workloads may change in the future, but for this even we - // only need to care about triggering reconcile requests for the current ones. - requests, err := common.MapSelector(ctx, rt.Client, m.computedType, - dec.GetData().GetWorkloads(), res.Id.Tenancy) - if err != nil { - return nil, err - } - - // Then generate requests for any previously selected workloads. - prevSelector := m.workloadSelectionTracker.GetSelector(res.GetId()) - - if !(stringslice.Equal(prevSelector.GetNames(), dec.GetData().GetWorkloads().GetNames()) && - stringslice.Equal(prevSelector.GetPrefixes(), dec.GetData().GetWorkloads().GetPrefixes())) { - // the selector is different, so we need to map those selectors as well. - requestsForPrevSelector, err := common.MapSelector(ctx, rt.Client, m.computedType, - prevSelector, res.Id.Tenancy) - if err != nil { - return nil, err - } - requests = append(requests, requestsForPrevSelector...) - } - - // Second, we track this proxy configuration's selector and ID in the tracker. - m.workloadSelectionTracker.TrackIDForSelector(res.Id, dec.GetData().GetWorkloads()) - - return requests, nil -} - -// IDsForWorkload returns IDs of workload-selecting types that we're tracking for the -// given workload name. -func (m *Mapper[T]) IDsForWorkload(id *pbresource.ID) []*pbresource.ID { - return m.workloadSelectionTracker.GetIDsForWorkload(id) -} - -// UntrackID removes tracking for the workload-selecting resource with the given ID. -func (m *Mapper[T]) UntrackID(id *pbresource.ID) { - m.workloadSelectionTracker.UntrackID(id) -} diff --git a/internal/mesh/internal/mappers/workloadselectionmapper/workload_selection_mapper_test.go b/internal/mesh/internal/mappers/workloadselectionmapper/workload_selection_mapper_test.go deleted file mode 100644 index 071be1f60d2f..000000000000 --- a/internal/mesh/internal/mappers/workloadselectionmapper/workload_selection_mapper_test.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package workloadselectionmapper - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/mesh/internal/types" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestMapToComputedType(t *testing.T) { - resourceClient := svctest.RunResourceService(t, types.Register, catalog.RegisterTypes) - mapper := New[*pbmesh.ProxyConfiguration](pbmesh.ComputedProxyConfigurationType) - - workloadData := &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{{Host: "1.1.1.1"}}, - Ports: map[string]*pbcatalog.WorkloadPort{ - "tcp": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - Identity: "test", - } - wID1 := resourcetest.Resource(pbcatalog.WorkloadType, "api-1"). - WithData(t, workloadData). - Write(t, resourceClient).GetId() - wID2 := resourcetest.Resource(pbcatalog.WorkloadType, "api-2"). - WithData(t, workloadData). - Write(t, resourceClient).GetId() - wID3 := resourcetest.Resource(pbcatalog.WorkloadType, "api-abc"). - WithData(t, workloadData). - Write(t, resourceClient).GetId() - wID4 := resourcetest.Resource(pbcatalog.WorkloadType, "foo"). - WithData(t, workloadData). - Write(t, resourceClient).GetId() - - pCfg1 := resourcetest.Resource(pbmesh.ProxyConfigurationType, "cfg1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"foo", "api-1"}, - Prefixes: []string{"api-a"}, - }, - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - }, - }).Build() - reqs, err := mapper.MapToComputedType(context.Background(), controller.Runtime{Client: resourceClient}, pCfg1) - require.NoError(t, err) - prototest.AssertElementsMatch(t, - controller.MakeRequests(pbmesh.ComputedProxyConfigurationType, []*pbresource.ID{wID1, wID3, wID4}), - reqs) - - pCfg2 := resourcetest.Resource(pbmesh.ProxyConfigurationType, "cfg2"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - Names: []string{"foo"}, - }, - BootstrapConfig: &pbmesh.BootstrapConfig{ - PrometheusBindAddr: "0.0.0.0:9000", - }, - }).Build() - - reqs, err = mapper.MapToComputedType(context.Background(), controller.Runtime{Client: resourceClient}, pCfg2) - require.NoError(t, err) - prototest.AssertElementsMatch(t, - controller.MakeRequests(pbmesh.ComputedProxyConfigurationType, []*pbresource.ID{wID1, wID2, wID3, wID4}), - reqs) - - // Check mapper state for each workload. - ids := mapper.IDsForWorkload(wID1) - prototest.AssertElementsMatch(t, []*pbresource.ID{pCfg1.Id, pCfg2.Id}, ids) - - ids = mapper.IDsForWorkload(wID2) - prototest.AssertElementsMatch(t, []*pbresource.ID{pCfg2.Id}, ids) - - ids = mapper.IDsForWorkload(wID3) - prototest.AssertElementsMatch(t, []*pbresource.ID{pCfg1.Id, pCfg2.Id}, ids) - - ids = mapper.IDsForWorkload(wID4) - prototest.AssertElementsMatch(t, []*pbresource.ID{pCfg1.Id, pCfg2.Id}, ids) - - // Update pCfg2's selector and check that we generate requests for previous and new selector. - pCfg2 = resourcetest.Resource(pbmesh.ProxyConfigurationType, "cfg2"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"foo"}, - }, - BootstrapConfig: &pbmesh.BootstrapConfig{ - PrometheusBindAddr: "0.0.0.0:9000", - }, - }).Build() - - reqs, err = mapper.MapToComputedType(context.Background(), controller.Runtime{Client: resourceClient}, pCfg2) - require.NoError(t, err) - prototest.AssertElementsMatch(t, - controller.MakeRequests(pbmesh.ComputedProxyConfigurationType, []*pbresource.ID{wID4, wID1, wID2, wID3, wID4}), - reqs) - - // Check mapper state for each workload. - ids = mapper.IDsForWorkload(wID1) - prototest.AssertElementsMatch(t, []*pbresource.ID{pCfg1.Id}, ids) - - ids = mapper.IDsForWorkload(wID2) - prototest.AssertElementsMatch(t, []*pbresource.ID{}, ids) - - ids = mapper.IDsForWorkload(wID3) - prototest.AssertElementsMatch(t, []*pbresource.ID{pCfg1.Id}, ids) - - ids = mapper.IDsForWorkload(wID4) - prototest.AssertElementsMatch(t, []*pbresource.ID{pCfg1.Id, pCfg2.Id}, ids) - - // Untrack one of the proxy cfgs and check that mapper is updated. - mapper.UntrackID(pCfg1.Id) - - ids = mapper.IDsForWorkload(wID1) - prototest.AssertElementsMatch(t, []*pbresource.ID{}, ids) - - ids = mapper.IDsForWorkload(wID2) - prototest.AssertElementsMatch(t, []*pbresource.ID{}, ids) - - ids = mapper.IDsForWorkload(wID3) - prototest.AssertElementsMatch(t, []*pbresource.ID{}, ids) - - ids = mapper.IDsForWorkload(wID4) - prototest.AssertElementsMatch(t, []*pbresource.ID{pCfg2.Id}, ids) -} diff --git a/internal/mesh/internal/types/computed_explicit_destinations.go b/internal/mesh/internal/types/computed_explicit_destinations.go deleted file mode 100644 index ac6bbe77798b..000000000000 --- a/internal/mesh/internal/types/computed_explicit_destinations.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" -) - -func RegisterComputedExplicitDestinations(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmesh.ComputedExplicitDestinationsType, - Proto: &pbmesh.ComputedExplicitDestinations{}, - Scope: resource.ScopeNamespace, - }) -} diff --git a/internal/mesh/internal/types/computed_proxy_configuration.go b/internal/mesh/internal/types/computed_proxy_configuration.go deleted file mode 100644 index 672f4426b634..000000000000 --- a/internal/mesh/internal/types/computed_proxy_configuration.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" -) - -func RegisterComputedProxyConfiguration(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmesh.ComputedProxyConfigurationType, - Proto: &pbmesh.ComputedProxyConfiguration{}, - Scope: resource.ScopeNamespace, - }) -} diff --git a/internal/mesh/internal/types/computed_routes.go b/internal/mesh/internal/types/computed_routes.go deleted file mode 100644 index b572c01fc376..000000000000 --- a/internal/mesh/internal/types/computed_routes.go +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" -) - -const ( - // NullRouteBackend is the sentinel string used in ComputedRoutes backend - // targets to indicate that traffic arriving at this destination should - // fail in a protocol-specific way (i.e. HTTP is 5xx) - NullRouteBackend = "NULL-ROUTE" -) - -func RegisterComputedRoutes(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmesh.ComputedRoutesType, - Proto: &pbmesh.ComputedRoutes{}, - Scope: resource.ScopeNamespace, - Validate: ValidateComputedRoutes, - }) -} - -var ValidateComputedRoutes = resource.DecodeAndValidate(validateComputedRoutes) - -func validateComputedRoutes(res *DecodedComputedRoutes) error { - var merr error - - if len(res.Data.PortedConfigs) == 0 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "ported_configs", - Wrapped: resource.ErrEmpty, - }) - } - - // TODO(rb): do more elaborate validation - - for port, pmc := range res.Data.PortedConfigs { - wrapErr := func(err error) error { - return resource.ErrInvalidMapValue{ - Map: "ported_configs", - Key: port, - Wrapped: err, - } - } - if pmc.Config == nil { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "config", - Wrapped: resource.ErrEmpty, - })) - } - - for targetName, target := range pmc.Targets { - wrapTargetErr := func(err error) error { - return wrapErr(resource.ErrInvalidMapValue{ - Map: "targets", - Key: targetName, - Wrapped: err, - }) - } - - switch target.Type { - case pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_UNSPECIFIED: - merr = multierror.Append(merr, wrapTargetErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: resource.ErrMissing, - }), - ) - case pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT: - case pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_INDIRECT: - if target.FailoverConfig != nil { - merr = multierror.Append(merr, wrapTargetErr( - resource.ErrInvalidField{ - Name: "failover_config", - Wrapped: errors.New("failover_config not supported for type = INDIRECT"), - }), - ) - } - default: - merr = multierror.Append(merr, wrapTargetErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: fmt.Errorf("not a supported enum value: %v", target.Type), - }, - )) - } - - if target.DestinationConfig == nil { - merr = multierror.Append(merr, wrapTargetErr(resource.ErrInvalidField{ - Name: "destination_config", - Wrapped: resource.ErrMissing, - })) - } else { - wrapDestConfigErr := func(err error) error { - return wrapTargetErr(resource.ErrInvalidField{ - Name: "destination_config", - Wrapped: err, - }) - } - - destConfig := target.DestinationConfig - if destConfig.ConnectTimeout == nil { - merr = multierror.Append(merr, wrapDestConfigErr(resource.ErrInvalidField{ - Name: "connect_timeout", - Wrapped: resource.ErrMissing, - })) - } else { - connectTimeout := destConfig.ConnectTimeout.AsDuration() - if connectTimeout < 0 { - merr = multierror.Append(merr, wrapDestConfigErr(resource.ErrInvalidField{ - Name: "connect_timeout", - Wrapped: errTimeoutCannotBeNegative(connectTimeout), - })) - } - } - } - - if target.MeshPort == "" { - merr = multierror.Append(merr, wrapTargetErr(resource.ErrInvalidField{ - Name: "mesh_port", - Wrapped: resource.ErrEmpty, - })) - } - if target.ServiceEndpointsId != nil { - merr = multierror.Append(merr, wrapTargetErr(resource.ErrInvalidField{ - Name: "service_endpoints_id", - Wrapped: fmt.Errorf("field should be empty"), - })) - } - if target.ServiceEndpoints != nil { - merr = multierror.Append(merr, wrapTargetErr(resource.ErrInvalidField{ - Name: "service_endpoints", - Wrapped: fmt.Errorf("field should be empty"), - })) - } - if len(target.IdentityRefs) > 0 { - merr = multierror.Append(merr, wrapTargetErr(resource.ErrInvalidField{ - Name: "identity_refs", - Wrapped: fmt.Errorf("field should be empty"), - })) - } - } - - // TODO(rb): do a deep inspection of the config to verify that all - // xRoute backends ultimately point to an item in the targets map. - } - - return merr -} diff --git a/internal/mesh/internal/types/computed_routes_test.go b/internal/mesh/internal/types/computed_routes_test.go deleted file mode 100644 index 8f6aa06f8fcf..000000000000 --- a/internal/mesh/internal/types/computed_routes_test.go +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/durationpb" - - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestValidateComputedRoutes(t *testing.T) { - type testcase struct { - routes *pbmesh.ComputedRoutes - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.ComputedRoutesType, "api"). - WithData(t, tc.routes). - Build() - - err := ValidateComputedRoutes(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.ComputedRoutes](t, res) - prototest.AssertDeepEqual(t, tc.routes, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "empty": { - routes: &pbmesh.ComputedRoutes{}, - expectErr: `invalid "ported_configs" field: cannot be empty`, - }, - "empty config": { - routes: &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: nil, - }, - }, - }, - expectErr: `invalid value of key "http" within ported_configs: invalid "config" field: cannot be empty`, - }, - "target/missing mesh port": { - routes: &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{}, - }, - Targets: map[string]*pbmesh.BackendTargetDetails{ - "foo": { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "", - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within ported_configs: invalid value of key "foo" within targets: invalid "mesh_port" field: cannot be empty`, - }, - "target/missing type": { - routes: &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{}, - }, - Targets: map[string]*pbmesh.BackendTargetDetails{ - "foo": { - MeshPort: "mesh", - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within ported_configs: invalid value of key "foo" within targets: invalid "type" field: missing required field`, - }, - "target/bad type": { - routes: &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{}, - }, - Targets: map[string]*pbmesh.BackendTargetDetails{ - "foo": { - Type: 99, - MeshPort: "mesh", - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within ported_configs: invalid value of key "foo" within targets: invalid "type" field: not a supported enum value: 99`, - }, - "target/indirect cannot have failover": { - routes: &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{}, - }, - Targets: map[string]*pbmesh.BackendTargetDetails{ - "foo": { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_INDIRECT, - MeshPort: "mesh", - FailoverConfig: &pbmesh.ComputedFailoverConfig{}, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within ported_configs: invalid value of key "foo" within targets: invalid "failover_config" field: failover_config not supported for type = INDIRECT`, - }, - "target/should not have service endpoints id": { - routes: &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{}, - }, - Targets: map[string]*pbmesh.BackendTargetDetails{ - "foo": { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - ServiceEndpointsId: &pbresource.ID{}, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within ported_configs: invalid value of key "foo" within targets: invalid "service_endpoints_id" field: field should be empty`, - }, - "target/should not have service endpoints": { - routes: &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{}, - }, - Targets: map[string]*pbmesh.BackendTargetDetails{ - "foo": { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - ServiceEndpoints: &pbcatalog.ServiceEndpoints{}, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within ported_configs: invalid value of key "foo" within targets: invalid "service_endpoints" field: field should be empty`, - }, - "target/should not have identity refs": { - routes: &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{}, - }, - Targets: map[string]*pbmesh.BackendTargetDetails{ - "foo": { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - IdentityRefs: []*pbresource.Reference{ - {}, - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within ported_configs: invalid value of key "foo" within targets: invalid "identity_refs" field: field should be empty`, - }, - "valid": { - routes: &pbmesh.ComputedRoutes{ - PortedConfigs: map[string]*pbmesh.ComputedPortRoutes{ - "http": { - Config: &pbmesh.ComputedPortRoutes_Tcp{ - Tcp: &pbmesh.ComputedTCPRoute{}, - }, - Targets: map[string]*pbmesh.BackendTargetDetails{ - "foo": { - Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT, - MeshPort: "mesh", - DestinationConfig: &pbmesh.DestinationConfig{ - ConnectTimeout: durationpb.New(5 * time.Second), - }, - }, - }, - }, - }, - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/mesh/internal/types/decoded.go b/internal/mesh/internal/types/decoded.go deleted file mode 100644 index be4836c066ff..000000000000 --- a/internal/mesh/internal/types/decoded.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/internal/resource" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" -) - -type ( - DecodedHTTPRoute = resource.DecodedResource[*pbmesh.HTTPRoute] - DecodedGRPCRoute = resource.DecodedResource[*pbmesh.GRPCRoute] - DecodedTCPRoute = resource.DecodedResource[*pbmesh.TCPRoute] - DecodedDestinationPolicy = resource.DecodedResource[*pbmesh.DestinationPolicy] - DecodedDestinationsConfiguration = resource.DecodedResource[*pbmesh.DestinationsConfiguration] - DecodedComputedRoutes = resource.DecodedResource[*pbmesh.ComputedRoutes] - DecodedComputedTrafficPermissions = resource.DecodedResource[*pbauth.ComputedTrafficPermissions] - DecodedFailoverPolicy = resource.DecodedResource[*pbcatalog.FailoverPolicy] - DecodedService = resource.DecodedResource[*pbcatalog.Service] - DecodedServiceEndpoints = resource.DecodedResource[*pbcatalog.ServiceEndpoints] - DecodedWorkload = resource.DecodedResource[*pbcatalog.Workload] - DecodedProxyConfiguration = resource.DecodedResource[*pbmesh.ProxyConfiguration] - DecodedComputedProxyConfiguration = resource.DecodedResource[*pbmesh.ComputedProxyConfiguration] - DecodedDestinations = resource.DecodedResource[*pbmesh.Destinations] - DecodedComputedDestinations = resource.DecodedResource[*pbmesh.ComputedExplicitDestinations] - DecodedProxyStateTemplate = resource.DecodedResource[*pbmesh.ProxyStateTemplate] -) diff --git a/internal/mesh/internal/types/destination_policy.go b/internal/mesh/internal/types/destination_policy.go deleted file mode 100644 index 4fe3062367cf..000000000000 --- a/internal/mesh/internal/types/destination_policy.go +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func RegisterDestinationPolicy(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmesh.DestinationPolicyType, - Proto: &pbmesh.DestinationPolicy{}, - Scope: resource.ScopeNamespace, - Validate: ValidateDestinationPolicy, - ACLs: &resource.ACLHooks{ - Read: aclReadHookDestinationPolicy, - Write: aclWriteHookDestinationPolicy, - List: resource.NoOpACLListHook, - }, - }) -} - -var ValidateDestinationPolicy = resource.DecodeAndValidate(validateDestinationPolicy) - -func validateDestinationPolicy(res *DecodedDestinationPolicy) error { - var merr error - - if len(res.Data.PortConfigs) == 0 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "port_configs", - Wrapped: resource.ErrEmpty, - }) - } - - for port, pc := range res.Data.PortConfigs { - wrapErr := func(err error) error { - return resource.ErrInvalidMapValue{ - Map: "port_configs", - Key: port, - Wrapped: err, - } - } - - if dur := pc.ConnectTimeout.AsDuration(); dur < 0 { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "connect_timeout", - Wrapped: fmt.Errorf("'%v', must be >= 0", dur), - })) - } - if dur := pc.RequestTimeout.AsDuration(); dur < 0 { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "request_timeout", - Wrapped: fmt.Errorf("'%v', must be >= 0", dur), - })) - } - - if pc.LoadBalancer != nil { - lb := pc.LoadBalancer - wrapLBErr := func(err error) error { - return wrapErr(resource.ErrInvalidField{ - Name: "load_balancer", - Wrapped: err, - }) - } - - switch lb.Policy { - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_UNSPECIFIED: - // means just do the default - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RANDOM: - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_ROUND_ROBIN: - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST: - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV: - case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH: - default: - merr = multierror.Append(merr, wrapLBErr(resource.ErrInvalidField{ - Name: "policy", - Wrapped: fmt.Errorf("not a supported enum value: %v", lb.Policy), - })) - } - - if lb.Policy != pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH && lb.Config != nil { - if _, ok := lb.Config.(*pbmesh.LoadBalancer_RingHashConfig); ok { - merr = multierror.Append(merr, wrapLBErr(resource.ErrInvalidField{ - Name: "config", - Wrapped: fmt.Errorf("ring_hash_config specified for incompatible load balancing policy %q", lb.Policy), - })) - } - } - - if lb.Policy != pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST && lb.Config != nil { - if _, ok := lb.Config.(*pbmesh.LoadBalancer_LeastRequestConfig); ok { - merr = multierror.Append(merr, wrapLBErr(resource.ErrInvalidField{ - Name: "config", - Wrapped: fmt.Errorf("least_request_config specified for incompatible load balancing policy %q", lb.Policy), - })) - } - } - - if !lb.Policy.IsHashBased() && len(lb.HashPolicies) > 0 { - merr = multierror.Append(merr, wrapLBErr(resource.ErrInvalidField{ - Name: "hash_policies", - Wrapped: fmt.Errorf("hash_policies specified for non-hash-based policy %q", lb.Policy), - })) - } - - LOOP: - for i, hp := range lb.HashPolicies { - wrapHPErr := func(err error) error { - return wrapLBErr(resource.ErrInvalidListElement{ - Name: "hash_policies", - Index: i, - Wrapped: err, - }) - } - - var hasField bool - switch hp.Field { - case pbmesh.HashPolicyField_HASH_POLICY_FIELD_UNSPECIFIED: - case pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER, - pbmesh.HashPolicyField_HASH_POLICY_FIELD_COOKIE, - pbmesh.HashPolicyField_HASH_POLICY_FIELD_QUERY_PARAMETER: - hasField = true - default: - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "field", - Wrapped: fmt.Errorf("not a supported enum value: %v", hp.Field), - })) - continue LOOP // no need to keep validating - } - - if hp.SourceIp { - if hasField { - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "field", - Wrapped: fmt.Errorf("a single hash policy cannot hash both a source address and a %q", hp.Field), - })) - } - if hp.FieldValue != "" { - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "field_value", - Wrapped: errors.New("cannot be specified when hashing source_ip"), - })) - } - } - - if hasField && hp.FieldValue == "" { - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "field_value", - Wrapped: fmt.Errorf("field %q was specified without a field_value", hp.Field), - })) - } - if hp.FieldValue != "" && !hasField { - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "field", - Wrapped: resource.ErrMissing, - })) - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "field_value", - Wrapped: errors.New("requires a field to apply to"), - })) - } - if hp.CookieConfig != nil { - if hp.Field != pbmesh.HashPolicyField_HASH_POLICY_FIELD_COOKIE { - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "cookie_config", - Wrapped: fmt.Errorf("incompatible with field %q", hp.Field), - })) - } - if hp.CookieConfig.Session && hp.CookieConfig.Ttl.AsDuration() != 0 { - merr = multierror.Append(merr, wrapHPErr(resource.ErrInvalidField{ - Name: "cookie_config", - Wrapped: resource.ErrInvalidField{ - Name: "ttl", - Wrapped: fmt.Errorf("a session cookie cannot have an associated TTL"), - }, - })) - } - } - } - } - - if pc.LocalityPrioritization != nil { - lp := pc.LocalityPrioritization - wrapLPErr := func(err error) error { - return wrapErr(resource.ErrInvalidField{ - Name: "locality_prioritization", - Wrapped: err, - }) - } - - switch lp.Mode { - case pbmesh.LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED: - // means pbmesh.LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_NONE - case pbmesh.LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_NONE: - case pbmesh.LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_FAILOVER: - default: - merr = multierror.Append(merr, wrapLPErr(resource.ErrInvalidField{ - Name: "mode", - Wrapped: fmt.Errorf("not a supported enum value: %v", lp.Mode), - })) - } - } - } - - return merr -} - -func aclReadHookDestinationPolicy(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID, _ *pbresource.Resource) error { - // DestinationPolicy is name-aligned with Service - serviceName := id.Name - - // Check service:read permissions. - return authorizer.ToAllowAuthorizer().ServiceReadAllowed(serviceName, authzContext) -} - -func aclWriteHookDestinationPolicy(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, res *pbresource.Resource) error { - // DestinationPolicy is name-aligned with Service - serviceName := res.Id.Name - - // Check service:write permissions on the service this is controlling. - return authorizer.ToAllowAuthorizer().ServiceWriteAllowed(serviceName, authzContext) -} diff --git a/internal/mesh/internal/types/destination_policy_test.go b/internal/mesh/internal/types/destination_policy_test.go deleted file mode 100644 index 8edb51b2d831..000000000000 --- a/internal/mesh/internal/types/destination_policy_test.go +++ /dev/null @@ -1,609 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/durationpb" - - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestValidateDestinationPolicy(t *testing.T) { - type testcase struct { - policy *pbmesh.DestinationPolicy - expectErr string - expectErrs []string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.DestinationPolicyType, "api"). - WithData(t, tc.policy). - Build() - - err := ValidateDestinationPolicy(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.DestinationPolicy](t, res) - prototest.AssertDeepEqual(t, tc.policy, got.Data) - - if tc.expectErr != "" && len(tc.expectErrs) > 0 { - t.Fatalf("cannot test singular and list errors at the same time") - } - - if tc.expectErr == "" && len(tc.expectErrs) == 0 { - require.NoError(t, err) - } else if tc.expectErr != "" { - testutil.RequireErrorContains(t, err, tc.expectErr) - } else { - for _, expectErr := range tc.expectErrs { - testutil.RequireErrorContains(t, err, expectErr) - } - } - } - - cases := map[string]testcase{ - // emptiness - "empty": { - policy: &pbmesh.DestinationPolicy{}, - expectErr: `invalid "port_configs" field: cannot be empty`, - }, - "good connect timeout": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - }, - }, - }, - }, - "bad connect timeout": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(-55 * time.Second), - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "connect_timeout" field: '-55s', must be >= 0`, - }, - "good request timeout": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - RequestTimeout: durationpb.New(55 * time.Second), - }, - }, - }, - }, - "bad request timeout": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - RequestTimeout: durationpb.New(-55 * time.Second), - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "request_timeout" field: '-55s', must be >= 0`, - }, - // load balancer - "lbpolicy: missing enum": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{}, - }, - }, - }, - }, - "lbpolicy: bad enum": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: 99, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid "policy" field: not a supported enum value: 99`, - }, - "lbpolicy: supported": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RANDOM, - }, - }, - }, - }, - }, - "lbpolicy: bad for least request config": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH, - Config: &pbmesh.LoadBalancer_LeastRequestConfig{ - LeastRequestConfig: &pbmesh.LeastRequestConfig{ - ChoiceCount: 10, - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid "config" field: least_request_config specified for incompatible load balancing policy "LOAD_BALANCER_POLICY_RING_HASH"`, - }, - "lbpolicy: bad for ring hash config": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST, - Config: &pbmesh.LoadBalancer_RingHashConfig{ - RingHashConfig: &pbmesh.RingHashConfig{ - MinimumRingSize: 1024, - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid "config" field: ring_hash_config specified for incompatible load balancing policy "LOAD_BALANCER_POLICY_LEAST_REQUEST"`, - }, - "lbpolicy: good for least request config": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST, - Config: &pbmesh.LoadBalancer_LeastRequestConfig{ - LeastRequestConfig: &pbmesh.LeastRequestConfig{ - ChoiceCount: 10, - }, - }, - }, - }, - }, - }, - }, - "lbpolicy: good for ring hash config": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH, - Config: &pbmesh.LoadBalancer_RingHashConfig{ - RingHashConfig: &pbmesh.RingHashConfig{ - MinimumRingSize: 1024, - }, - }, - }, - }, - }, - }, - }, - "lbpolicy: empty policy with hash policy": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - HashPolicies: []*pbmesh.HashPolicy{ - {SourceIp: true}, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid "hash_policies" field: hash_policies specified for non-hash-based policy "LOAD_BALANCER_POLICY_UNSPECIFIED"`, - }, - "lbconfig: cookie config with header policy": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER, - FieldValue: "x-user-id", - CookieConfig: &pbmesh.CookieConfig{ - Ttl: durationpb.New(10 * time.Second), - Path: "/root", - }, - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "cookie_config" field: incompatible with field "HASH_POLICY_FIELD_HEADER"`, - }, - "lbconfig: cannot generate session cookie with ttl": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_COOKIE, - FieldValue: "good-cookie", - CookieConfig: &pbmesh.CookieConfig{ - Session: true, - Ttl: durationpb.New(10 * time.Second), - }, - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "cookie_config" field: invalid "ttl" field: a session cookie cannot have an associated TTL`, - }, - "lbconfig: valid cookie policy": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_COOKIE, - FieldValue: "good-cookie", - CookieConfig: &pbmesh.CookieConfig{ - Ttl: durationpb.New(10 * time.Second), - Path: "/oven", - }, - }, - }, - }, - }, - }, - }, - }, - "lbconfig: bad match field": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: 99, - FieldValue: "X-Consul-Token", - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field" field: not a supported enum value: 99`, - }, - "lbconfig: supported match field": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER, - FieldValue: "X-Consul-Token", - }, - }, - }, - }, - }, - }, - }, - "lbconfig: missing match field": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - FieldValue: "X-Consul-Token", - }, - }, - }, - }, - }, - }, - expectErrs: []string{ - `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field" field: missing required field`, - `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field_value" field: requires a field to apply to`, - }, - }, - "lbconfig: cannot match on source address and custom field": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER, - SourceIp: true, - }, - }, - }, - }, - }, - }, - expectErrs: []string{ - `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field" field: a single hash policy cannot hash both a source address and a "HASH_POLICY_FIELD_HEADER"`, - `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field_value" field: field "HASH_POLICY_FIELD_HEADER" was specified without a field_value`, - }, - }, - "lbconfig: matchvalue not compatible with source address": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - FieldValue: "X-Consul-Token", - SourceIp: true, - }, - }, - }, - }, - }, - }, - expectErrs: []string{ - `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field_value" field: cannot be specified when hashing source_ip`, - `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field_value" field: requires a field to apply to`, - }, - }, - "lbconfig: field without match value": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER, - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field_value" field: field "HASH_POLICY_FIELD_HEADER" was specified without a field_value`, - }, - "lbconfig: matchvalue without field": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - HashPolicies: []*pbmesh.HashPolicy{ - { - FieldValue: "my-cookie", - }, - }, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "load_balancer" field: invalid element at index 0 of list "hash_policies": invalid "field_value" field: requires a field to apply to`, - }, - "lbconfig: ring hash kitchen sink": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH, - Config: &pbmesh.LoadBalancer_RingHashConfig{ - RingHashConfig: &pbmesh.RingHashConfig{ - MaximumRingSize: 10, - MinimumRingSize: 2, - }, - }, - HashPolicies: []*pbmesh.HashPolicy{ - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_COOKIE, - FieldValue: "my-cookie", - }, - { - Field: pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER, - FieldValue: "alt-header", - Terminal: true, - }, - }, - }, - }, - }, - }, - }, - "lbconfig: least request kitchen sink": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - LoadBalancer: &pbmesh.LoadBalancer{ - Policy: pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST, - Config: &pbmesh.LoadBalancer_LeastRequestConfig{ - LeastRequestConfig: &pbmesh.LeastRequestConfig{ - ChoiceCount: 10, - }, - }, - }, - }, - }, - }, - }, - "locality: good mode": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - LocalityPrioritization: &pbmesh.LocalityPrioritization{ - Mode: pbmesh.LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_FAILOVER, - }, - }, - }, - }, - }, - "locality: unset mode": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - LocalityPrioritization: &pbmesh.LocalityPrioritization{ - Mode: pbmesh.LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED, - }, - }, - }, - }, - }, - "locality: bad mode": { - policy: &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - LocalityPrioritization: &pbmesh.LocalityPrioritization{ - Mode: 99, - }, - }, - }, - }, - expectErr: `invalid value of key "http" within port_configs: invalid "locality_prioritization" field: invalid "mode" field: not a supported enum value: 99`, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestDestinationPolicyACLs(t *testing.T) { - // Wire up a registry to generically invoke hooks - registry := resource.NewRegistry() - Register(registry) - - newPolicy := func(t *testing.T, tenancyStr string) *pbresource.Resource { - res := resourcetest.Resource(pbmesh.DestinationPolicyType, "api"). - WithTenancy(resourcetest.Tenancy(tenancyStr)). - WithData(t, &pbmesh.DestinationPolicy{ - PortConfigs: map[string]*pbmesh.DestinationConfig{ - "http": { - ConnectTimeout: durationpb.New(55 * time.Second), - }, - }, - }). - Build() - resourcetest.ValidateAndNormalize(t, registry, res) - return res - } - - const ( - DENY = resourcetest.DENY - ALLOW = resourcetest.ALLOW - DEFAULT = resourcetest.DEFAULT - ) - - run := func(t *testing.T, name string, tc resourcetest.ACLTestCase) { - t.Run(name, func(t *testing.T) { - resourcetest.RunACLTestCase(t, tc, registry) - }) - } - - isEnterprise := (structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default") - - serviceRead := func(partition, namespace, name string) string { - if isEnterprise { - return fmt.Sprintf(` partition %q { namespace %q { service %q { policy = "read" } } }`, partition, namespace, name) - } - return fmt.Sprintf(` service %q { policy = "read" } `, name) - } - serviceWrite := func(partition, namespace, name string) string { - if isEnterprise { - return fmt.Sprintf(` partition %q { namespace %q { service %q { policy = "write" } } }`, partition, namespace, name) - } - return fmt.Sprintf(` service %q { policy = "write" } `, name) - } - - assert := func(t *testing.T, name string, rules string, res *pbresource.Resource, readOK, writeOK string) { - tc := resourcetest.ACLTestCase{ - AuthCtx: resource.AuthorizerContext(res.Id.Tenancy), - Rules: rules, - Res: res, - ReadOK: readOK, - WriteOK: writeOK, - ListOK: DEFAULT, - } - run(t, name, tc) - } - - tenancies := []string{"default.default"} - if isEnterprise { - tenancies = append(tenancies, "default.foo", "alpha.default", "alpha.foo") - } - - for _, policyTenancyStr := range tenancies { - t.Run("policy tenancy: "+policyTenancyStr, func(t *testing.T) { - for _, aclTenancyStr := range tenancies { - t.Run("acl tenancy: "+aclTenancyStr, func(t *testing.T) { - aclTenancy := resourcetest.Tenancy(aclTenancyStr) - - maybe := func(match string) string { - if policyTenancyStr != aclTenancyStr { - return DENY - } - return match - } - - t.Run("no rules", func(t *testing.T) { - rules := `` - assert(t, "any", rules, newPolicy(t, policyTenancyStr), DENY, DENY) - }) - t.Run("api:read", func(t *testing.T) { - rules := serviceRead(aclTenancy.Partition, aclTenancy.Namespace, "api") - assert(t, "any", rules, newPolicy(t, policyTenancyStr), maybe(ALLOW), DENY) - }) - t.Run("api:write", func(t *testing.T) { - rules := serviceWrite(aclTenancy.Partition, aclTenancy.Namespace, "api") - assert(t, "any", rules, newPolicy(t, policyTenancyStr), maybe(ALLOW), maybe(ALLOW)) - }) - }) - } - }) - } -} diff --git a/internal/mesh/internal/types/destinations.go b/internal/mesh/internal/types/destinations.go deleted file mode 100644 index 7de3011e3ef0..000000000000 --- a/internal/mesh/internal/types/destinations.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "net" - - "github.com/hashicorp/go-multierror" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func RegisterDestinations(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmesh.DestinationsType, - Proto: &pbmesh.Destinations{}, - Scope: resource.ScopeNamespace, - Mutate: MutateDestinations, - Validate: ValidateDestinations, - ACLs: catalog.ACLHooksForWorkloadSelectingType[*pbmesh.Destinations](), - }) -} - -var MutateDestinations = resource.DecodeAndMutate(mutateDestinations) - -func mutateDestinations(res *DecodedDestinations) (bool, error) { - changed := false - - for _, dest := range res.Data.Destinations { - if dest.DestinationRef == nil { - continue // skip; let the validation hook error out instead - } - if dest.DestinationRef.Tenancy != nil && !isLocalPeer(dest.DestinationRef.Tenancy.PeerName) { - // TODO(peering/v2): remove this bypass when we know what to do with - // non-local peer references. - continue - } - orig := proto.Clone(dest.DestinationRef).(*pbresource.Reference) - resource.DefaultReferenceTenancy( - dest.DestinationRef, - res.Id.GetTenancy(), - resource.DefaultNamespacedTenancy(), // Services are all namespace scoped. - ) - - if !proto.Equal(orig, dest.DestinationRef) { - changed = true - } - } - - return changed, nil -} - -func isLocalPeer(p string) bool { - return p == "local" || p == "" -} - -var ValidateDestinations = resource.DecodeAndValidate(validateDestinations) - -func validateDestinations(res *DecodedDestinations) error { - var merr error - - if selErr := catalog.ValidateSelector(res.Data.Workloads, false); selErr != nil { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "workloads", - Wrapped: selErr, - }) - } - - if res.Data.GetPqDestinations() != nil { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "pq_destinations", - Wrapped: resource.ErrUnsupported, - }) - } - - for i, dest := range res.Data.Destinations { - wrapDestErr := func(err error) error { - return resource.ErrInvalidListElement{ - Name: "destinations", - Index: i, - Wrapped: err, - } - } - - wrapRefErr := func(err error) error { - return wrapDestErr(resource.ErrInvalidField{ - Name: "destination_ref", - Wrapped: err, - }) - } - - if refErr := catalog.ValidateLocalServiceRefNoSection(dest.DestinationRef, wrapRefErr); refErr != nil { - merr = multierror.Append(merr, refErr) - } - - if portErr := catalog.ValidatePortName(dest.DestinationPort); portErr != nil { - merr = multierror.Append(merr, wrapDestErr(resource.ErrInvalidField{ - Name: "destination_port", - Wrapped: portErr, - })) - } - - if dest.GetDatacenter() != "" { - merr = multierror.Append(merr, wrapDestErr(resource.ErrInvalidField{ - Name: "datacenter", - Wrapped: resource.ErrUnsupported, - })) - } - - if listenAddrErr := validateListenAddr(dest); listenAddrErr != nil { - merr = multierror.Append(merr, wrapDestErr(listenAddrErr)) - } - } - - return merr -} - -func validateListenAddr(dest *pbmesh.Destination) error { - var merr error - - if dest.GetListenAddr() == nil { - return multierror.Append(merr, resource.ErrInvalidFields{ - Names: []string{"ip_port", "unix"}, - Wrapped: resource.ErrMissingOneOf, - }) - } - - switch listenAddr := dest.GetListenAddr().(type) { - case *pbmesh.Destination_IpPort: - if ipPortErr := validateIPPort(listenAddr.IpPort); ipPortErr != nil { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "ip_port", - Wrapped: ipPortErr, - }) - } - case *pbmesh.Destination_Unix: - if !catalog.IsValidUnixSocketPath(listenAddr.Unix.GetPath()) { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "unix", - Wrapped: resource.ErrInvalidField{ - Name: "path", - Wrapped: errInvalidUnixSocketPath, - }, - }) - } - } - - return merr -} - -func validateIPPort(ipPort *pbmesh.IPPortAddress) error { - var merr error - - if listenPortErr := validatePort(ipPort.GetPort(), "port"); listenPortErr != nil { - merr = multierror.Append(merr, listenPortErr) - } - - if net.ParseIP(ipPort.GetIp()) == nil { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "ip", - Wrapped: errInvalidIP, - }) - } - - return merr -} diff --git a/internal/mesh/internal/types/destinations_configuration.go b/internal/mesh/internal/types/destinations_configuration.go deleted file mode 100644 index 7d46d93ed999..000000000000 --- a/internal/mesh/internal/types/destinations_configuration.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/catalog" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" -) - -func RegisterDestinationsConfiguration(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmesh.DestinationsConfigurationType, - Proto: &pbmesh.DestinationsConfiguration{}, - Scope: resource.ScopeNamespace, - Validate: ValidateDestinationsConfiguration, - ACLs: catalog.ACLHooksForWorkloadSelectingType[*pbmesh.DestinationsConfiguration](), - }) -} - -var ValidateDestinationsConfiguration = resource.DecodeAndValidate(validateDestinationsConfiguration) - -func validateDestinationsConfiguration(res *DecodedDestinationsConfiguration) error { - var merr error - - // Validate the workload selector - if selErr := catalog.ValidateSelector(res.Data.Workloads, false); selErr != nil { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "workloads", - Wrapped: selErr, - }) - } - - return merr -} diff --git a/internal/mesh/internal/types/destinations_configuration_test.go b/internal/mesh/internal/types/destinations_configuration_test.go deleted file mode 100644 index 11af0732d5d9..000000000000 --- a/internal/mesh/internal/types/destinations_configuration_test.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - catalogtesthelpers "github.com/hashicorp/consul/internal/catalog/catalogtest/helpers" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestDestinationsConfigurationACLs(t *testing.T) { - catalogtesthelpers.RunWorkloadSelectingTypeACLsTests[*pbmesh.DestinationsConfiguration](t, pbmesh.DestinationsConfigurationType, - func(selector *pbcatalog.WorkloadSelector) *pbmesh.DestinationsConfiguration { - return &pbmesh.DestinationsConfiguration{Workloads: selector} - }, - RegisterDestinationsConfiguration, - ) -} - -func TestValidateDestinationsConfiguration(t *testing.T) { - type testcase struct { - data *pbmesh.DestinationsConfiguration - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.DestinationsConfigurationType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, tc.data). - Build() - - err := ValidateDestinationsConfiguration(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.DestinationsConfiguration](t, res) - prototest.AssertDeepEqual(t, tc.data, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - // emptiness - "empty": { - data: &pbmesh.DestinationsConfiguration{}, - expectErr: `invalid "workloads" field: cannot be empty`, - }, - "empty selector": { - data: &pbmesh.DestinationsConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{}, - }, - expectErr: `invalid "workloads" field: cannot be empty`, - }, - "bad selector": { - data: &pbmesh.DestinationsConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"blah"}, - Filter: "garbage.foo == bar", - }, - }, - expectErr: `invalid "filter" field: filter "garbage.foo == bar" is invalid: Selector "garbage" is not valid`, - }, - "good selector": { - data: &pbmesh.DestinationsConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"blah"}, - Filter: "metadata.foo == bar", - }, - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/mesh/internal/types/destinations_test.go b/internal/mesh/internal/types/destinations_test.go deleted file mode 100644 index 55624a6316f4..000000000000 --- a/internal/mesh/internal/types/destinations_test.go +++ /dev/null @@ -1,427 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - catalogtesthelpers "github.com/hashicorp/consul/internal/catalog/catalogtest/helpers" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestMutateDestinations(t *testing.T) { - type testcase struct { - tenancy *pbresource.Tenancy - data *pbmesh.Destinations - expect *pbmesh.Destinations - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.DestinationsType, "api"). - WithTenancy(tc.tenancy). - WithData(t, tc.data). - Build() - - err := MutateDestinations(res) - - got := resourcetest.MustDecode[*pbmesh.Destinations](t, res) - - if tc.expectErr == "" { - require.NoError(t, err) - prototest.AssertDeepEqual(t, tc.expect, got.Data) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "empty-1": { - data: &pbmesh.Destinations{}, - expect: &pbmesh.Destinations{}, - }, - "invalid/nil dest ref": { - data: &pbmesh.Destinations{ - Destinations: []*pbmesh.Destination{ - {DestinationRef: nil}, - }, - }, - expect: &pbmesh.Destinations{ // untouched - Destinations: []*pbmesh.Destination{ - {DestinationRef: nil}, - }, - }, - }, - "dest ref tenancy defaulting": { - tenancy: resourcetest.Tenancy("foo.bar"), - data: &pbmesh.Destinations{ - Destinations: []*pbmesh.Destination{ - {DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "", "api")}, - {DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, ".zim", "api")}, - {DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "gir.zim", "api")}, - }, - }, - expect: &pbmesh.Destinations{ - Destinations: []*pbmesh.Destination{ - {DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo.bar", "api")}, - {DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo.zim", "api")}, - {DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "gir.zim", "api")}, - }, - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestValidateDestinations(t *testing.T) { - type testcase struct { - data *pbmesh.Destinations - skipMutate bool - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.DestinationsType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, tc.data). - Build() - - if !tc.skipMutate { - require.NoError(t, MutateDestinations(res)) - - // Verify that mutate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.Destinations](t, res) - prototest.AssertDeepEqual(t, tc.data, got.Data) - } - - err := ValidateDestinations(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.Destinations](t, res) - prototest.AssertDeepEqual(t, tc.data, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - // emptiness - "empty": { - data: &pbmesh.Destinations{}, - expectErr: `invalid "workloads" field: cannot be empty`, - }, - "empty selector": { - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{}, - }, - expectErr: `invalid "workloads" field: cannot be empty`, - }, - "bad selector": { - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"blah"}, - Filter: "garbage.foo == bar", - }, - }, - expectErr: `invalid "filter" field: filter "garbage.foo == bar" is invalid: Selector "garbage" is not valid`, - }, - "dest/nil ref": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"blah"}, - }, - Destinations: []*pbmesh.Destination{ - {DestinationRef: nil}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "destination_ref" field: missing required field`, - }, - "dest/bad type": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"blah"}, - }, - Destinations: []*pbmesh.Destination{ - {DestinationRef: newRefWithTenancy(pbcatalog.WorkloadType, "default.default", "api")}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "destination_ref" field: invalid "type" field: reference must have type catalog.v2beta1.Service`, - }, - "dest/nil tenancy": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"blah"}, - }, - Destinations: []*pbmesh.Destination{ - {DestinationRef: &pbresource.Reference{Type: pbcatalog.ServiceType, Name: "api"}}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "destination_ref" field: invalid "tenancy" field: missing required field`, - }, - "dest/bad dest tenancy/partition": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"blah"}, - }, - Destinations: []*pbmesh.Destination{ - {DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, ".bar", "api")}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "destination_ref" field: invalid "tenancy" field: invalid "partition" field: cannot be empty`, - }, - "dest/bad dest tenancy/namespace": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"blah"}, - }, - Destinations: []*pbmesh.Destination{ - {DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo", "api")}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "destination_ref" field: invalid "tenancy" field: invalid "namespace" field: cannot be empty`, - }, - "dest/bad dest tenancy/peer_name": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"blah"}, - }, - Destinations: []*pbmesh.Destination{ - {DestinationRef: resourcetest.Resource(pbcatalog.ServiceType, "api"). - WithTenancy(&pbresource.Tenancy{Partition: "foo", Namespace: "bar"}). - Reference("")}, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "destination_ref" field: invalid "tenancy" field: invalid "peer_name" field: must be set to "local"`, - }, - "unsupported pq_destinations": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"foo"}}, - PqDestinations: []*pbmesh.PreparedQueryDestination{ - {Name: "foo-query"}, - }, - }, - expectErr: `invalid "pq_destinations" field: field is currently not supported`, - }, - "missing destination port": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"foo"}}, - Destinations: []*pbmesh.Destination{ - { - DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo.bar", "api"), - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 1234, - }, - }, - }, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "destination_port" field: cannot be empty`, - }, - "unsupported datacenter": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"foo"}}, - Destinations: []*pbmesh.Destination{ - { - DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo.bar", "api"), - DestinationPort: "p1", - Datacenter: "dc2", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 1234, - }, - }, - }, - }, - }, - expectErr: `invalid element at index 0 of list "destinations": invalid "datacenter" field: field is currently not supported`, - }, - "missing listen addr": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"foo"}}, - Destinations: []*pbmesh.Destination{ - { - DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo.bar", "api"), - DestinationPort: "p1", - }, - }, - }, - expectErr: `invalid "ip_port,unix" fields: missing one of the required fields`, - }, - "invalid ip for listen addr": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"foo"}}, - Destinations: []*pbmesh.Destination{ - { - DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo.bar", "api"), - DestinationPort: "p1", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "invalid", - Port: 1234, - }, - }, - }, - }, - }, - expectErr: `invalid "ip" field: IP address is not valid`, - }, - "invalid port for listen addr": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"foo"}}, - Destinations: []*pbmesh.Destination{ - { - DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo.bar", "api"), - DestinationPort: "p1", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 0, - }, - }, - }, - }, - }, - expectErr: `invalid "port" field: port number is outside the range 1 to 65535`, - }, - "invalid unix path for listen addr": { - skipMutate: true, - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"foo"}}, - Destinations: []*pbmesh.Destination{ - { - DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo.bar", "api"), - DestinationPort: "p1", - ListenAddr: &pbmesh.Destination_Unix{ - Unix: &pbmesh.UnixSocketAddress{ - Path: "foo", - }, - }, - }, - }, - }, - expectErr: `invalid "unix" field: invalid "path" field: unix socket path is not valid`, - }, - "normal": { - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"foo"}}, - Destinations: []*pbmesh.Destination{ - { - DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo.bar", "api"), - DestinationPort: "p1", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 1234, - }, - }, - }, - { - DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo.zim", "api"), - DestinationPort: "p2", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 1235, - }, - }, - }, - { - DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "gir.zim", "api"), - DestinationPort: "p3", - ListenAddr: &pbmesh.Destination_Unix{ - Unix: &pbmesh.UnixSocketAddress{ - Path: "unix://foo/bar", - }, - }, - }, - }, - }, - }, - "normal with selector": { - data: &pbmesh.Destinations{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"blah"}, - Filter: "metadata.foo == bar", - }, - Destinations: []*pbmesh.Destination{ - { - DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo.bar", "api"), - DestinationPort: "p1", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 1234, - }, - }, - }, - { - DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "foo.zim", "api"), - DestinationPort: "p2", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "127.0.0.1", - Port: 1235, - }, - }, - }, - { - DestinationRef: newRefWithTenancy(pbcatalog.ServiceType, "gir.zim", "api"), - DestinationPort: "p3", - ListenAddr: &pbmesh.Destination_Unix{ - Unix: &pbmesh.UnixSocketAddress{ - Path: "unix://foo/bar", - }, - }, - }, - }, - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestDestinationsACLs(t *testing.T) { - catalogtesthelpers.RunWorkloadSelectingTypeACLsTests[*pbmesh.Destinations](t, pbmesh.DestinationsType, - func(selector *pbcatalog.WorkloadSelector) *pbmesh.Destinations { - return &pbmesh.Destinations{Workloads: selector} - }, - RegisterDestinations, - ) -} diff --git a/internal/mesh/internal/types/errors.go b/internal/mesh/internal/types/errors.go deleted file mode 100644 index bc9dacbbf0c4..000000000000 --- a/internal/mesh/internal/types/errors.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" -) - -var ( - errInvalidPort = errors.New("port number is outside the range 1 to 65535") - errInvalidIP = errors.New("IP address is not valid") - errInvalidUnixSocketPath = errors.New("unix socket path is not valid") - errInvalidExposePathProtocol = errors.New("invalid protocol: only HTTP and HTTP2 protocols are allowed") - errMissingProxyConfigData = errors.New("at least one of \"bootstrap_config\" or \"dynamic_config\" fields must be set") -) diff --git a/internal/mesh/internal/types/grpc_route.go b/internal/mesh/internal/types/grpc_route.go deleted file mode 100644 index b861abccdc05..000000000000 --- a/internal/mesh/internal/types/grpc_route.go +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" -) - -func RegisterGRPCRoute(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmesh.GRPCRouteType, - Proto: &pbmesh.GRPCRoute{}, - Scope: resource.ScopeNamespace, - Mutate: MutateGRPCRoute, - Validate: ValidateGRPCRoute, - ACLs: xRouteACLHooks[*pbmesh.GRPCRoute](), - }) -} - -var MutateGRPCRoute = resource.DecodeAndMutate(mutateGRPCRoute) - -func mutateGRPCRoute(res *DecodedGRPCRoute) (bool, error) { - changed := false - - if mutateParentRefs(res.Id.Tenancy, res.Data.ParentRefs) { - changed = true - } - - for _, rule := range res.Data.Rules { - for _, backend := range rule.BackendRefs { - if backend.BackendRef == nil || backend.BackendRef.Ref == nil { - continue - } - if mutateXRouteRef(res.Id.Tenancy, backend.BackendRef.Ref) { - changed = true - } - } - } - - return changed, nil -} - -var ValidateGRPCRoute = resource.DecodeAndValidate(validateGRPCRoute) - -func validateGRPCRoute(res *DecodedGRPCRoute) error { - var merr error - if err := validateParentRefs(res.Id, res.Data.ParentRefs); err != nil { - merr = multierror.Append(merr, err) - } - - if len(res.Data.Hostnames) > 0 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "hostnames", - Wrapped: errors.New("should not populate hostnames"), - }) - } - - for i, rule := range res.Data.Rules { - wrapRuleErr := func(err error) error { - return resource.ErrInvalidListElement{ - Name: "rules", - Index: i, - Wrapped: err, - } - } - - for j, match := range rule.Matches { - wrapMatchErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "matches", - Index: j, - Wrapped: err, - }) - } - - if match.Method != nil { - switch match.Method.Type { - case pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_UNSPECIFIED: - merr = multierror.Append(merr, wrapMatchErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: resource.ErrMissing, - }, - )) - case pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT: - case pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_REGEX: - default: - merr = multierror.Append(merr, wrapMatchErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: fmt.Errorf("not a supported enum value: %v", match.Method.Type), - }, - )) - } - if match.Method.Service == "" && match.Method.Method == "" { - merr = multierror.Append(merr, wrapMatchErr( - resource.ErrInvalidField{ - Name: "service", - Wrapped: errors.New("at least one of \"service\" or \"method\" must be set"), - }, - )) - } - } - - for k, header := range match.Headers { - wrapMatchHeaderErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "headers", - Index: k, - Wrapped: err, - }) - } - - if err := validateHeaderMatchType(header.Type); err != nil { - merr = multierror.Append(merr, wrapMatchHeaderErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: err, - }), - ) - } - - if header.Name == "" { - merr = multierror.Append(merr, wrapMatchHeaderErr( - resource.ErrInvalidField{ - Name: "name", - Wrapped: resource.ErrMissing, - }), - ) - } - } - } - - for j, filter := range rule.Filters { - wrapFilterErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "filters", - Index: j, - Wrapped: err, - }) - } - set := 0 - if filter.RequestHeaderModifier != nil { - set++ - } - if filter.ResponseHeaderModifier != nil { - set++ - } - if filter.UrlRewrite != nil { - set++ - if filter.UrlRewrite.PathPrefix == "" { - merr = multierror.Append(merr, wrapFilterErr( - resource.ErrInvalidField{ - Name: "url_rewrite", - Wrapped: resource.ErrInvalidField{ - Name: "path_prefix", - Wrapped: errors.New("field should not be empty if enclosing section is set"), - }, - }, - )) - } - } - if set != 1 { - merr = multierror.Append(merr, wrapFilterErr( - errors.New("exactly one of request_header_modifier, response_header_modifier, or url_rewrite is required"), - )) - } - } - - if len(rule.BackendRefs) == 0 { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "backend_refs", - Wrapped: resource.ErrEmpty, - }, - )) - } - for j, hbref := range rule.BackendRefs { - wrapBackendRefErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "backend_refs", - Index: j, - Wrapped: err, - }) - } - - wrapBackendRefFieldErr := func(err error) error { - return wrapBackendRefErr(resource.ErrInvalidField{ - Name: "backend_ref", - Wrapped: err, - }) - } - if err := validateBackendRef(hbref.BackendRef, wrapBackendRefFieldErr); err != nil { - merr = multierror.Append(merr, err) - } - - if len(hbref.Filters) > 0 { - merr = multierror.Append(merr, wrapBackendRefErr( - resource.ErrInvalidField{ - Name: "filters", - Wrapped: errors.New("filters are not supported at this level yet"), - }, - )) - } - } - - if rule.Timeouts != nil { - for _, err := range validateHTTPTimeouts(rule.Timeouts) { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "timeouts", - Wrapped: err, - }, - )) - } - } - if rule.Retries != nil { - for _, err := range validateHTTPRetries(rule.Retries) { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "retries", - Wrapped: err, - }, - )) - } - } - } - - return merr -} diff --git a/internal/mesh/internal/types/grpc_route_test.go b/internal/mesh/internal/types/grpc_route_test.go deleted file mode 100644 index 26340bff77bb..000000000000 --- a/internal/mesh/internal/types/grpc_route_test.go +++ /dev/null @@ -1,653 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestMutateGRPCRoute(t *testing.T) { - type testcase struct { - routeTenancy *pbresource.Tenancy - route *pbmesh.GRPCRoute - expect *pbmesh.GRPCRoute - } - - cases := map[string]testcase{} - - // Add common parent refs test cases. - for name, parentTC := range getXRouteParentRefMutateTestCases() { - cases["parent-ref: "+name] = testcase{ - routeTenancy: parentTC.routeTenancy, - route: &pbmesh.GRPCRoute{ - ParentRefs: parentTC.refs, - }, - expect: &pbmesh.GRPCRoute{ - ParentRefs: parentTC.expect, - }, - } - } - // add common backend ref test cases. - for name, backendTC := range getXRouteBackendRefMutateTestCases() { - var ( - refs []*pbmesh.GRPCBackendRef - expect []*pbmesh.GRPCBackendRef - ) - for _, br := range backendTC.refs { - refs = append(refs, &pbmesh.GRPCBackendRef{ - BackendRef: br, - }) - } - for _, br := range backendTC.expect { - expect = append(expect, &pbmesh.GRPCBackendRef{ - BackendRef: br, - }) - } - cases["backend-ref: "+name] = testcase{ - routeTenancy: backendTC.routeTenancy, - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{ - {BackendRefs: refs}, - }, - }, - expect: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{ - {BackendRefs: expect}, - }, - }, - } - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.GRPCRouteType, "api"). - WithTenancy(tc.routeTenancy). - WithData(t, tc.route). - Build() - resource.DefaultIDTenancy(res.Id, nil, resource.DefaultNamespacedTenancy()) - - err := MutateGRPCRoute(res) - require.NoError(t, err) - - got := resourcetest.MustDecode[*pbmesh.GRPCRoute](t, res) - - if tc.expect == nil { - tc.expect = proto.Clone(tc.route).(*pbmesh.GRPCRoute) - } - - prototest.AssertDeepEqual(t, tc.expect, got.Data) - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestValidateGRPCRoute(t *testing.T) { - type testcase struct { - routeTenancy *pbresource.Tenancy - route *pbmesh.GRPCRoute - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.GRPCRouteType, "api"). - WithTenancy(tc.routeTenancy). - WithData(t, tc.route). - Build() - resource.DefaultIDTenancy(res.Id, nil, resource.DefaultNamespacedTenancy()) - - // Ensure things are properly mutated and updated in the inputs. - err := MutateGRPCRoute(res) - require.NoError(t, err) - { - mutated := resourcetest.MustDecode[*pbmesh.GRPCRoute](t, res) - tc.route = mutated.Data - } - - err = ValidateGRPCRoute(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.GRPCRoute](t, res) - prototest.AssertDeepEqual(t, tc.route, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "hostnames not supported for services": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Hostnames: []string{"foo.local"}, - }, - expectErr: `invalid "hostnames" field: should not populate hostnames`, - }, - "no rules": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - }, - }, - "rules with no matches": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "rules with matches that are empty": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - // none - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "method match with no type is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Service: "foo", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "type" field: missing required field`, - }, - "method match with unknown type is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: 99, - Service: "foo", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "type" field: not a supported enum value: 99`, - }, - "method match with no service nor method is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT, - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "service" field: at least one of "service" or "method" must be set`, - }, - "method match is good (1)": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT, - Service: "foo", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "method match is good (2)": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT, - Method: "bar", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "method match is good (3)": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Method: &pbmesh.GRPCMethodMatch{ - Type: pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT, - Service: "foo", - Method: "bar", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "header match with no type is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Headers: []*pbmesh.GRPCHeaderMatch{{ - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "headers": invalid "type" field: missing required field`, - }, - "header match with unknown type is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Headers: []*pbmesh.GRPCHeaderMatch{{ - Type: 99, - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "headers": invalid "type" field: not a supported enum value: 99`, - }, - "header match with no name is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Headers: []*pbmesh.GRPCHeaderMatch{{ - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - }}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "headers": invalid "name" field: missing required field`, - }, - "header match is good": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Matches: []*pbmesh.GRPCRouteMatch{{ - Headers: []*pbmesh.GRPCHeaderMatch{{ - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter empty is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - // none - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter req header mod is ok": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter resp header mod is ok": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter rewrite header mod missing path prefix": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": invalid "url_rewrite" field: invalid "path_prefix" field: field should not be empty if enclosing section is set`, - }, - "filter rewrite header mod is ok": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter req+resp header mod is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter req+rewrite header mod is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter resp+rewrite header mod is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter req+resp+rewrite header mod is bad": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Filters: []*pbmesh.GRPCRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "backend ref with filters is unsupported": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - Filters: []*pbmesh.GRPCRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "backend_refs": invalid "filters" field: filters are not supported at this level yet`, - }, - "nil backend ref": { - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - BackendRefs: []*pbmesh.GRPCBackendRef{nil}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "backend_refs": invalid "backend_ref" field: missing required field`, - }, - } - - // Add common timeouts test cases. - for name, timeoutsTC := range getXRouteTimeoutsTestCases() { - cases["timeouts: "+name] = testcase{ - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Timeouts: timeoutsTC.timeouts, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: timeoutsTC.expectErr, - } - } - - // Add common retries test cases. - for name, retriesTC := range getXRouteRetriesTestCases() { - cases["retries: "+name] = testcase{ - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{{ - Retries: retriesTC.retries, - BackendRefs: []*pbmesh.GRPCBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: retriesTC.expectErr, - } - } - - // Add common parent refs test cases. - for name, parentTC := range getXRouteParentRefTestCases() { - cases["parent-ref: "+name] = testcase{ - routeTenancy: parentTC.routeTenancy, - route: &pbmesh.GRPCRoute{ - ParentRefs: parentTC.refs, - }, - expectErr: parentTC.expectErr, - } - } - // add common backend ref test cases. - for name, backendTC := range getXRouteBackendRefTestCases() { - var refs []*pbmesh.GRPCBackendRef - for _, br := range backendTC.refs { - refs = append(refs, &pbmesh.GRPCBackendRef{ - BackendRef: br, - }) - } - cases["backend-ref: "+name] = testcase{ - routeTenancy: backendTC.routeTenancy, - route: &pbmesh.GRPCRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.GRPCRouteRule{ - {BackendRefs: refs}, - }, - }, - expectErr: backendTC.expectErr, - } - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestGRPCRouteACLs(t *testing.T) { - testXRouteACLs[*pbmesh.GRPCRoute](t, func(t *testing.T, parentRefs, backendRefs []*pbresource.Reference) *pbresource.Resource { - data := &pbmesh.GRPCRoute{ - ParentRefs: nil, - } - for _, ref := range parentRefs { - data.ParentRefs = append(data.ParentRefs, &pbmesh.ParentReference{ - Ref: ref, - }) - } - - var ruleRefs []*pbmesh.GRPCBackendRef - for _, ref := range backendRefs { - ruleRefs = append(ruleRefs, &pbmesh.GRPCBackendRef{ - BackendRef: &pbmesh.BackendReference{ - Ref: ref, - }, - }) - } - data.Rules = []*pbmesh.GRPCRouteRule{ - {BackendRefs: ruleRefs}, - } - - return resourcetest.Resource(pbmesh.GRPCRouteType, "api-grpc-route"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data). - Build() - }) -} diff --git a/internal/mesh/internal/types/http_route.go b/internal/mesh/internal/types/http_route.go deleted file mode 100644 index d32f55dc6cc8..000000000000 --- a/internal/mesh/internal/types/http_route.go +++ /dev/null @@ -1,350 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" - "net/http" - "strings" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" -) - -func RegisterHTTPRoute(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmesh.HTTPRouteType, - Proto: &pbmesh.HTTPRoute{}, - Scope: resource.ScopeNamespace, - Mutate: MutateHTTPRoute, - Validate: ValidateHTTPRoute, - ACLs: xRouteACLHooks[*pbmesh.HTTPRoute](), - }) -} - -var MutateHTTPRoute = resource.DecodeAndMutate(mutateHTTPRoute) - -func mutateHTTPRoute(res *DecodedHTTPRoute) (bool, error) { - changed := false - - if mutateParentRefs(res.Id.Tenancy, res.Data.ParentRefs) { - changed = true - } - - for _, rule := range res.Data.Rules { - for _, match := range rule.Matches { - if match.Method != "" { - norm := strings.ToUpper(match.Method) - if match.Method != norm { - match.Method = norm - changed = true - } - } - } - for _, backend := range rule.BackendRefs { - if backend.BackendRef == nil || backend.BackendRef.Ref == nil { - continue - } - if mutateXRouteRef(res.Id.Tenancy, backend.BackendRef.Ref) { - changed = true - } - } - } - - return changed, nil -} - -var ValidateHTTPRoute = resource.DecodeAndValidate(validateHTTPRoute) - -func validateHTTPRoute(res *DecodedHTTPRoute) error { - var merr error - if err := validateParentRefs(res.Id, res.Data.ParentRefs); err != nil { - merr = multierror.Append(merr, err) - } - - if len(res.Data.Hostnames) > 0 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "hostnames", - Wrapped: errors.New("should not populate hostnames"), - }) - } - - for i, rule := range res.Data.Rules { - wrapRuleErr := func(err error) error { - return resource.ErrInvalidListElement{ - Name: "rules", - Index: i, - Wrapped: err, - } - } - - for j, match := range rule.Matches { - wrapMatchErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "matches", - Index: j, - Wrapped: err, - }) - } - - if match.Path != nil { - wrapMatchPathErr := func(err error) error { - return wrapMatchErr(resource.ErrInvalidField{ - Name: "path", - Wrapped: err, - }) - } - // enumcover:pbmesh.PathMatchType - switch match.Path.Type { - case pbmesh.PathMatchType_PATH_MATCH_TYPE_UNSPECIFIED: - merr = multierror.Append(merr, wrapMatchPathErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: resource.ErrMissing, - }, - )) - case pbmesh.PathMatchType_PATH_MATCH_TYPE_EXACT: - if !strings.HasPrefix(match.Path.Value, "/") { - merr = multierror.Append(merr, wrapMatchPathErr( - resource.ErrInvalidField{ - Name: "value", - Wrapped: fmt.Errorf("exact patch value does not start with '/': %q", match.Path.Value), - }, - )) - } - case pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX: - if !strings.HasPrefix(match.Path.Value, "/") { - merr = multierror.Append(merr, wrapMatchPathErr( - resource.ErrInvalidField{ - Name: "value", - Wrapped: fmt.Errorf("prefix patch value does not start with '/': %q", match.Path.Value), - }, - )) - } - case pbmesh.PathMatchType_PATH_MATCH_TYPE_REGEX: - if match.Path.Value == "" { - merr = multierror.Append(merr, wrapMatchPathErr( - resource.ErrInvalidField{ - Name: "value", - Wrapped: resource.ErrEmpty, - }, - )) - } - default: - merr = multierror.Append(merr, wrapMatchPathErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: fmt.Errorf("not a supported enum value: %v", match.Path.Type), - }, - )) - } - } - - for k, hdr := range match.Headers { - wrapMatchHeaderErr := func(err error) error { - return wrapMatchErr(resource.ErrInvalidListElement{ - Name: "headers", - Index: k, - Wrapped: err, - }) - } - - if err := validateHeaderMatchType(hdr.Type); err != nil { - merr = multierror.Append(merr, wrapMatchHeaderErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: err, - }), - ) - } - - if hdr.Name == "" { - merr = multierror.Append(merr, wrapMatchHeaderErr( - resource.ErrInvalidField{ - Name: "name", - Wrapped: resource.ErrMissing, - }), - ) - } - } - - for k, qm := range match.QueryParams { - wrapMatchParamErr := func(err error) error { - return wrapMatchErr(resource.ErrInvalidListElement{ - Name: "query_params", - Index: k, - Wrapped: err, - }) - } - - // enumcover:pbmesh.QueryParamMatchType - switch qm.Type { - case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_UNSPECIFIED: - merr = multierror.Append(merr, wrapMatchParamErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: resource.ErrMissing, - }), - ) - case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT: - case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_REGEX: - case pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_PRESENT: - default: - merr = multierror.Append(merr, wrapMatchParamErr( - resource.ErrInvalidField{ - Name: "type", - Wrapped: fmt.Errorf("not a supported enum value: %v", qm.Type), - }, - )) - } - - if qm.Name == "" { - merr = multierror.Append(merr, wrapMatchParamErr( - resource.ErrInvalidField{ - Name: "name", - Wrapped: resource.ErrMissing, - }), - ) - } - } - - if match.Method != "" && !isValidHTTPMethod(match.Method) { - merr = multierror.Append(merr, wrapMatchErr( - resource.ErrInvalidField{ - Name: "method", - Wrapped: fmt.Errorf("not a valid http method: %q", match.Method), - }, - )) - } - } - - var ( - hasReqMod bool - hasUrlRewrite bool - ) - for j, filter := range rule.Filters { - wrapFilterErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "filters", - Index: j, - Wrapped: err, - }) - } - set := 0 - if filter.RequestHeaderModifier != nil { - set++ - hasReqMod = true - } - if filter.ResponseHeaderModifier != nil { - set++ - } - if filter.UrlRewrite != nil { - set++ - hasUrlRewrite = true - if filter.UrlRewrite.PathPrefix == "" { - merr = multierror.Append(merr, wrapFilterErr( - resource.ErrInvalidField{ - Name: "url_rewrite", - Wrapped: resource.ErrInvalidField{ - Name: "path_prefix", - Wrapped: errors.New("field should not be empty if enclosing section is set"), - }, - }, - )) - } - } - if set != 1 { - merr = multierror.Append(merr, wrapFilterErr( - errors.New("exactly one of request_header_modifier, response_header_modifier, or url_rewrite is required"), - )) - } - } - - if hasReqMod && hasUrlRewrite { - merr = multierror.Append(merr, wrapRuleErr( - errors.New("exactly one of request_header_modifier or url_rewrite can be set at a time"), - )) - } - - if len(rule.BackendRefs) == 0 { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "backend_refs", - Wrapped: resource.ErrEmpty, - }, - )) - } - for j, hbref := range rule.BackendRefs { - wrapBackendRefErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "backend_refs", - Index: j, - Wrapped: err, - }) - } - - wrapBackendRefFieldErr := func(err error) error { - return wrapBackendRefErr(resource.ErrInvalidField{ - Name: "backend_ref", - Wrapped: err, - }) - } - if err := validateBackendRef(hbref.BackendRef, wrapBackendRefFieldErr); err != nil { - merr = multierror.Append(merr, err) - } - - if len(hbref.Filters) > 0 { - merr = multierror.Append(merr, wrapBackendRefErr( - resource.ErrInvalidField{ - Name: "filters", - Wrapped: errors.New("filters are not supported at this level yet"), - }, - )) - } - } - - if rule.Timeouts != nil { - for _, err := range validateHTTPTimeouts(rule.Timeouts) { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "timeouts", - Wrapped: err, - }, - )) - } - } - if rule.Retries != nil { - for _, err := range validateHTTPRetries(rule.Retries) { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "retries", - Wrapped: err, - }, - )) - } - } - } - - return merr -} - -func isValidHTTPMethod(method string) bool { - switch method { - case http.MethodGet, - http.MethodHead, - http.MethodPost, - http.MethodPut, - http.MethodPatch, - http.MethodDelete, - http.MethodConnect, - http.MethodOptions, - http.MethodTrace: - return true - default: - return false - } -} diff --git a/internal/mesh/internal/types/http_route_test.go b/internal/mesh/internal/types/http_route_test.go deleted file mode 100644 index 81c8b5ab0041..000000000000 --- a/internal/mesh/internal/types/http_route_test.go +++ /dev/null @@ -1,911 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestMutateHTTPRoute(t *testing.T) { - type testcase struct { - routeTenancy *pbresource.Tenancy - route *pbmesh.HTTPRoute - expect *pbmesh.HTTPRoute - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.HTTPRouteType, "api"). - WithTenancy(tc.routeTenancy). - WithData(t, tc.route). - Build() - resource.DefaultIDTenancy(res.Id, nil, resource.DefaultNamespacedTenancy()) - - err := MutateHTTPRoute(res) - - got := resourcetest.MustDecode[*pbmesh.HTTPRoute](t, res) - - if tc.expectErr == "" { - require.NoError(t, err) - - if tc.expect == nil { - tc.expect = proto.Clone(tc.route).(*pbmesh.HTTPRoute) - } - - prototest.AssertDeepEqual(t, tc.expect, got.Data) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "no-rules": { - route: &pbmesh.HTTPRoute{}, - }, - "rules-with-no-matches": { - route: &pbmesh.HTTPRoute{ - Rules: []*pbmesh.HTTPRouteRule{{ - // none - }}, - }, - }, - "rules-with-matches-no-methods": { - route: &pbmesh.HTTPRoute{ - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/foo", - }, - }}, - }}, - }, - }, - "rules-with-matches-methods-uppercase": { - route: &pbmesh.HTTPRoute{ - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{ - { - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/foo", - }, - Method: "GET", - }, - { - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/bar", - }, - Method: "POST", - }, - }, - }}, - }, - }, - "rules-with-matches-methods-lowercase": { - route: &pbmesh.HTTPRoute{ - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{ - { - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/foo", - }, - Method: "get", - }, - { - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/bar", - }, - Method: "post", - }, - }, - }}, - }, - expect: &pbmesh.HTTPRoute{ - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{ - { - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/foo", - }, - Method: "GET", - }, - { - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/bar", - }, - Method: "POST", - }, - }, - }}, - }, - }, - } - - // Add common parent refs test cases. - for name, parentTC := range getXRouteParentRefMutateTestCases() { - cases["parent-ref: "+name] = testcase{ - routeTenancy: parentTC.routeTenancy, - route: &pbmesh.HTTPRoute{ - ParentRefs: parentTC.refs, - }, - expect: &pbmesh.HTTPRoute{ - ParentRefs: parentTC.expect, - }, - } - } - // add common backend ref test cases. - for name, backendTC := range getXRouteBackendRefMutateTestCases() { - var ( - refs []*pbmesh.HTTPBackendRef - expect []*pbmesh.HTTPBackendRef - ) - for _, br := range backendTC.refs { - refs = append(refs, &pbmesh.HTTPBackendRef{ - BackendRef: br, - }) - } - for _, br := range backendTC.expect { - expect = append(expect, &pbmesh.HTTPBackendRef{ - BackendRef: br, - }) - } - cases["backend-ref: "+name] = testcase{ - routeTenancy: backendTC.routeTenancy, - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{ - {BackendRefs: refs}, - }, - }, - expect: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{ - {BackendRefs: expect}, - }, - }, - } - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestValidateHTTPRoute(t *testing.T) { - type testcase struct { - routeTenancy *pbresource.Tenancy - route *pbmesh.HTTPRoute - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.HTTPRouteType, "api"). - WithTenancy(tc.routeTenancy). - WithData(t, tc.route). - Build() - resource.DefaultIDTenancy(res.Id, nil, resource.DefaultNamespacedTenancy()) - - // Ensure things are properly mutated and updated in the inputs. - err := MutateHTTPRoute(res) - require.NoError(t, err) - { - mutated := resourcetest.MustDecode[*pbmesh.HTTPRoute](t, res) - tc.route = mutated.Data - } - - err = ValidateHTTPRoute(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.HTTPRoute](t, res) - prototest.AssertDeepEqual(t, tc.route, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "hostnames not supported for services": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Hostnames: []string{"foo.local"}, - }, - expectErr: `invalid "hostnames" field: should not populate hostnames`, - }, - "no rules": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - }, - }, - "rules with no matches": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "rules with matches that are empty": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - // none - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "path match with no type is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Value: "/foo", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "path" field: invalid "type" field: missing required field`, - }, - "path match with unknown type is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: 99, - Value: "/foo", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "path" field: invalid "type" field: not a supported enum value: 99`, - }, - "exact path match with no leading slash is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_EXACT, - Value: "foo", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "path" field: invalid "value" field: exact patch value does not start with '/': "foo"`, - }, - "prefix path match with no leading slash is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "foo", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "path" field: invalid "value" field: prefix patch value does not start with '/': "foo"`, - }, - "exact path match with leading slash is good": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_EXACT, - Value: "/foo", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "prefix path match with leading slash is good": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX, - Value: "/foo", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "regex empty path match is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_REGEX, - Value: "", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "path" field: invalid "value" field: cannot be empty`, - }, - "regex path match is good": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Path: &pbmesh.HTTPPathMatch{ - Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_REGEX, - Value: "/[^/]+/healthz", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "header match with no type is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Headers: []*pbmesh.HTTPHeaderMatch{{ - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid element at index 0 of list "headers": invalid "type" field: missing required field`, - }, - "header match with unknown type is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Headers: []*pbmesh.HTTPHeaderMatch{{ - Type: 99, - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid element at index 0 of list "headers": invalid "type" field: not a supported enum value: 99`, - }, - "header match with no name is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Headers: []*pbmesh.HTTPHeaderMatch{{ - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid element at index 0 of list "headers": invalid "name" field: missing required field`, - }, - "header match is good": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Headers: []*pbmesh.HTTPHeaderMatch{{ - Type: pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT, - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "queryparam match with no type is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - QueryParams: []*pbmesh.HTTPQueryParamMatch{{ - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid element at index 0 of list "query_params": invalid "type" field: missing required field`, - }, - "queryparam match with unknown type is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - QueryParams: []*pbmesh.HTTPQueryParamMatch{{ - Type: 99, - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid element at index 0 of list "query_params": invalid "type" field: not a supported enum value: 99`, - }, - "queryparam match with no name is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - QueryParams: []*pbmesh.HTTPQueryParamMatch{{ - Type: pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT, - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid element at index 0 of list "query_params": invalid "name" field: missing required field`, - }, - "queryparam match is good": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - QueryParams: []*pbmesh.HTTPQueryParamMatch{{ - Type: pbmesh.QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT, - Name: "x-foo", - }}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "method match is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Method: "BOB", - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "matches": invalid "method" field: not a valid http method: "BOB"`, - }, - "method match is good": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Matches: []*pbmesh.HTTPRouteMatch{{ - Method: "DELETE", - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter empty is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - // none - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter req header mod is ok": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter resp header mod is ok": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter rewrite header mod missing path prefix": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": invalid "url_rewrite" field: invalid "path_prefix" field: field should not be empty if enclosing section is set`, - }, - "filter rewrite header mod is ok": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - }, - "filter req+resp header mod is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter req+rewrite header mod is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter resp+rewrite header mod is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "filter req+rewrite on two rules is not allowed": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{ - { - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }, - { - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }, - }, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": exactly one of request_header_modifier or url_rewrite can be set at a time`, - }, - "filter req+resp+rewrite header mod is bad": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Filters: []*pbmesh.HTTPRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - ResponseHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - UrlRewrite: &pbmesh.HTTPURLRewriteFilter{ - PathPrefix: "/blah", - }, - }}, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`, - }, - "backend ref with filters is unsupported": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - Filters: []*pbmesh.HTTPRouteFilter{{ - RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{}, - }}, - }}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "backend_refs": invalid "filters" field: filters are not supported at this level yet`, - }, - "nil backend ref": { - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - BackendRefs: []*pbmesh.HTTPBackendRef{nil}, - }}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "backend_refs": invalid "backend_ref" field: missing required field`, - }, - } - - // Add common timeouts test cases. - for name, timeoutsTC := range getXRouteTimeoutsTestCases() { - cases["timeouts: "+name] = testcase{ - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Timeouts: timeoutsTC.timeouts, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: timeoutsTC.expectErr, - } - } - - // Add common retries test cases. - for name, retriesTC := range getXRouteRetriesTestCases() { - cases["retries: "+name] = testcase{ - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{{ - Retries: retriesTC.retries, - BackendRefs: []*pbmesh.HTTPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }}, - }, - expectErr: retriesTC.expectErr, - } - } - - // Add common parent refs test cases. - for name, parentTC := range getXRouteParentRefTestCases() { - cases["parent-ref: "+name] = testcase{ - routeTenancy: parentTC.routeTenancy, - route: &pbmesh.HTTPRoute{ - ParentRefs: parentTC.refs, - }, - expectErr: parentTC.expectErr, - } - } - // add common backend ref test cases. - for name, backendTC := range getXRouteBackendRefTestCases() { - var refs []*pbmesh.HTTPBackendRef - for _, br := range backendTC.refs { - refs = append(refs, &pbmesh.HTTPBackendRef{ - BackendRef: br, - }) - } - cases["backend-ref: "+name] = testcase{ - routeTenancy: backendTC.routeTenancy, - route: &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.HTTPRouteRule{ - {BackendRefs: refs}, - }, - }, - expectErr: backendTC.expectErr, - } - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestHTTPRouteACLs(t *testing.T) { - testXRouteACLs[*pbmesh.HTTPRoute](t, func(t *testing.T, parentRefs, backendRefs []*pbresource.Reference) *pbresource.Resource { - data := &pbmesh.HTTPRoute{ - ParentRefs: nil, - } - for _, ref := range parentRefs { - data.ParentRefs = append(data.ParentRefs, &pbmesh.ParentReference{ - Ref: ref, - }) - } - - var ruleRefs []*pbmesh.HTTPBackendRef - for _, ref := range backendRefs { - ruleRefs = append(ruleRefs, &pbmesh.HTTPBackendRef{ - BackendRef: &pbmesh.BackendReference{ - Ref: ref, - }, - }) - } - data.Rules = []*pbmesh.HTTPRouteRule{ - {BackendRefs: ruleRefs}, - } - - return resourcetest.Resource(pbmesh.HTTPRouteType, "api-http-route"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data). - Build() - }) -} diff --git a/internal/mesh/internal/types/intermediate/types.go b/internal/mesh/internal/types/intermediate/types.go deleted file mode 100644 index d6b4b39e42e4..000000000000 --- a/internal/mesh/internal/types/intermediate/types.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package intermediate - -import ( - "github.com/hashicorp/consul/internal/mesh/internal/types" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type Destination struct { - Explicit *pbmesh.Destination - Service *types.DecodedService // for the name of this destination - VirtualIPs []string // for the name of this destination - ComputedPortRoutes *pbmesh.ComputedPortRoutes // for the name of this destination -} - -type Status struct { - ID *pbresource.ID - Generation string - Conditions []*pbresource.Condition - OldStatus map[string]*pbresource.Status -} diff --git a/internal/mesh/internal/types/proxy_configuration.go b/internal/mesh/internal/types/proxy_configuration.go deleted file mode 100644 index 9a4388a40f01..000000000000 --- a/internal/mesh/internal/types/proxy_configuration.go +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "math" - - "github.com/hashicorp/consul/internal/catalog" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/sdk/iptables" -) - -func RegisterProxyConfiguration(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmesh.ProxyConfigurationType, - Proto: &pbmesh.ProxyConfiguration{}, - Scope: resource.ScopeNamespace, - Mutate: MutateProxyConfiguration, - Validate: ValidateProxyConfiguration, - ACLs: catalog.ACLHooksForWorkloadSelectingType[*pbmesh.ProxyConfiguration](), - }) -} - -var MutateProxyConfiguration = resource.DecodeAndMutate(mutateProxyConfiguration) - -func mutateProxyConfiguration(res *DecodedProxyConfiguration) (bool, error) { - changed := false - - // Default the tproxy outbound port. - if res.Data.IsTransparentProxy() { - if res.Data.GetDynamicConfig().GetTransparentProxy() == nil { - res.Data.DynamicConfig.TransparentProxy = &pbmesh.TransparentProxy{ - OutboundListenerPort: iptables.DefaultTProxyOutboundPort, - } - changed = true - } else if res.Data.GetDynamicConfig().GetTransparentProxy().OutboundListenerPort == 0 { - res.Data.DynamicConfig.TransparentProxy.OutboundListenerPort = iptables.DefaultTProxyOutboundPort - changed = true - } - } - - return changed, nil -} - -var ValidateProxyConfiguration = resource.DecodeAndValidate(validateProxyConfiguration) - -func validateProxyConfiguration(res *DecodedProxyConfiguration) error { - var err error - - if selErr := catalog.ValidateSelector(res.Data.Workloads, false); selErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "workloads", - Wrapped: selErr, - }) - } - - if res.Data.GetDynamicConfig() == nil && res.Data.GetBootstrapConfig() == nil { - err = multierror.Append(err, resource.ErrInvalidFields{ - Names: []string{"dynamic_config", "bootstrap_config"}, - Wrapped: errMissingProxyConfigData, - }) - } - - // nolint:staticcheck - if res.Data.GetOpaqueConfig() != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "opaque_config", - Wrapped: resource.ErrUnsupported, - }) - } - - if dynamicCfgErr := validateDynamicProxyConfiguration(res.Data.GetDynamicConfig()); dynamicCfgErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "dynamic_config", - Wrapped: dynamicCfgErr, - }) - } - - return err -} - -func validateDynamicProxyConfiguration(cfg *pbmesh.DynamicConfig) error { - if cfg == nil { - return nil - } - - var err error - - // Error if any of the currently unsupported fields is set. - if cfg.GetMutualTlsMode() != pbmesh.MutualTLSMode_MUTUAL_TLS_MODE_DEFAULT { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "mutual_tls_mode", - Wrapped: resource.ErrUnsupported, - }) - } - - if cfg.GetMeshGatewayMode() != pbmesh.MeshGatewayMode_MESH_GATEWAY_MODE_UNSPECIFIED { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "mesh_gateway_mode", - Wrapped: resource.ErrUnsupported, - }) - } - - if cfg.GetAccessLogs() != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "access_logs", - Wrapped: resource.ErrUnsupported, - }) - } - - if cfg.GetPublicListenerJson() != "" { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "public_listener_json", - Wrapped: resource.ErrUnsupported, - }) - } - - if cfg.GetListenerTracingJson() != "" { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "listener_tracing_json", - Wrapped: resource.ErrUnsupported, - }) - } - - if cfg.GetLocalClusterJson() != "" { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "local_cluster_json", - Wrapped: resource.ErrUnsupported, - }) - } - - // nolint:staticcheck - if cfg.GetLocalWorkloadAddress() != "" { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "local_workload_address", - Wrapped: resource.ErrUnsupported, - }) - } - - // nolint:staticcheck - if cfg.GetLocalWorkloadPort() != 0 { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "local_workload_port", - Wrapped: resource.ErrUnsupported, - }) - } - - // nolint:staticcheck - if cfg.GetLocalWorkloadSocketPath() != "" { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "local_workload_socket_path", - Wrapped: resource.ErrUnsupported, - }) - } - - if tproxyCfg := cfg.GetTransparentProxy(); tproxyCfg != nil { - if tproxyCfg.DialedDirectly { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "transparent_proxy", - Wrapped: resource.ErrInvalidField{ - Name: "dialed_directly", - Wrapped: resource.ErrUnsupported, - }, - }) - } - - if outboundListenerPortErr := validatePort(tproxyCfg.OutboundListenerPort, "outbound_listener_port"); outboundListenerPortErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "transparent_proxy", - Wrapped: outboundListenerPortErr, - }) - } - } - - if exposeCfg := cfg.GetExposeConfig(); exposeCfg != nil { - for i, path := range exposeCfg.GetExposePaths() { - if listenerPortErr := validatePort(path.ListenerPort, "listener_port"); listenerPortErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "expose_config", - Wrapped: resource.ErrInvalidListElement{ - Name: "expose_paths", - Index: i, - Wrapped: listenerPortErr, - }, - }) - } - - if localPathPortErr := validatePort(path.LocalPathPort, "local_path_port"); localPathPortErr != nil { - err = multierror.Append(err, resource.ErrInvalidField{ - Name: "expose_config", - Wrapped: resource.ErrInvalidListElement{ - Name: "expose_paths", - Index: i, - Wrapped: localPathPortErr, - }, - }) - } - } - } - - return err -} - -func validatePort(port uint32, fieldName string) error { - if port < 1 || port > math.MaxUint16 { - return resource.ErrInvalidField{ - Name: fieldName, - Wrapped: errInvalidPort, - } - } - return nil -} diff --git a/internal/mesh/internal/types/proxy_configuration_test.go b/internal/mesh/internal/types/proxy_configuration_test.go deleted file mode 100644 index f5c52d474c35..000000000000 --- a/internal/mesh/internal/types/proxy_configuration_test.go +++ /dev/null @@ -1,362 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "math" - "testing" - - "github.com/hashicorp/go-multierror" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/structpb" - - catalogtesthelpers "github.com/hashicorp/consul/internal/catalog/catalogtest/helpers" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/iptables" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestProxyConfigurationACLs(t *testing.T) { - catalogtesthelpers.RunWorkloadSelectingTypeACLsTests[*pbmesh.ProxyConfiguration](t, pbmesh.ProxyConfigurationType, - func(selector *pbcatalog.WorkloadSelector) *pbmesh.ProxyConfiguration { - return &pbmesh.ProxyConfiguration{ - Workloads: selector, - DynamicConfig: &pbmesh.DynamicConfig{}, - } - }, - RegisterProxyConfiguration, - ) -} - -func TestMutateProxyConfiguration(t *testing.T) { - cases := map[string]struct { - data *pbmesh.ProxyConfiguration - expData *pbmesh.ProxyConfiguration - }{ - "tproxy disabled": { - data: &pbmesh.ProxyConfiguration{}, - expData: &pbmesh.ProxyConfiguration{}, - }, - "tproxy disabled explicitly": { - data: &pbmesh.ProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_DIRECT, - }, - }, - expData: &pbmesh.ProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_DIRECT, - }, - }, - }, - "tproxy enabled and tproxy config is nil": { - data: &pbmesh.ProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - }, - }, - expData: &pbmesh.ProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - TransparentProxy: &pbmesh.TransparentProxy{ - OutboundListenerPort: iptables.DefaultTProxyOutboundPort, - }, - }, - }, - }, - "tproxy enabled and tproxy config is empty": { - data: &pbmesh.ProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - TransparentProxy: &pbmesh.TransparentProxy{}, - }, - }, - expData: &pbmesh.ProxyConfiguration{ - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - TransparentProxy: &pbmesh.TransparentProxy{ - OutboundListenerPort: iptables.DefaultTProxyOutboundPort, - }, - }, - }, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - res := resourcetest.Resource(pbmesh.ProxyConfigurationType, "test"). - WithData(t, c.data). - Build() - - err := MutateProxyConfiguration(res) - require.NoError(t, err) - - got := resourcetest.MustDecode[*pbmesh.ProxyConfiguration](t, res) - prototest.AssertDeepEqual(t, c.expData, got.GetData()) - }) - } -} - -func TestValidateProxyConfiguration_MissingBothDynamicAndBootstrapConfig(t *testing.T) { - proxyCfg := &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"foo"}}, - } - - res := resourcetest.Resource(pbmesh.ProxyConfigurationType, "test"). - WithData(t, proxyCfg). - Build() - - err := ValidateProxyConfiguration(res) - - var expError error - expError = multierror.Append(expError, - resource.ErrInvalidFields{ - Names: []string{"dynamic_config", "bootstrap_config"}, - Wrapped: errMissingProxyConfigData, - }, - ) - require.Equal(t, err, expError) -} - -func TestValidateProxyConfiguration_AllFieldsInvalid(t *testing.T) { - proxyCfg := &pbmesh.ProxyConfiguration{ - // Omit workload selector. - - DynamicConfig: &pbmesh.DynamicConfig{ - // Set unsupported fields. - MutualTlsMode: pbmesh.MutualTLSMode_MUTUAL_TLS_MODE_PERMISSIVE, - MeshGatewayMode: pbmesh.MeshGatewayMode_MESH_GATEWAY_MODE_LOCAL, - AccessLogs: &pbmesh.AccessLogsConfig{}, - PublicListenerJson: "listener-json", - ListenerTracingJson: "tracing-json", - LocalClusterJson: "cluster-json", - LocalWorkloadAddress: "1.1.1.1", - LocalWorkloadPort: 1234, - LocalWorkloadSocketPath: "/foo/bar", - - TransparentProxy: &pbmesh.TransparentProxy{ - DialedDirectly: true, // unsupported - OutboundListenerPort: math.MaxUint16 + 1, // invalid - }, - - // Create invalid expose paths config. - ExposeConfig: &pbmesh.ExposeConfig{ - ExposePaths: []*pbmesh.ExposePath{ - { - ListenerPort: 0, - LocalPathPort: math.MaxUint16 + 1, - }, - }, - }, - }, - - OpaqueConfig: &structpb.Struct{}, - } - - res := resourcetest.Resource(pbmesh.ProxyConfigurationType, "test"). - WithData(t, proxyCfg). - Build() - - err := ValidateProxyConfiguration(res) - - var dynamicCfgErr error - unsupportedFields := []string{ - "mutual_tls_mode", - "mesh_gateway_mode", - "access_logs", - "public_listener_json", - "listener_tracing_json", - "local_cluster_json", - "local_workload_address", - "local_workload_port", - "local_workload_socket_path", - } - for _, f := range unsupportedFields { - dynamicCfgErr = multierror.Append(dynamicCfgErr, - resource.ErrInvalidField{ - Name: f, - Wrapped: resource.ErrUnsupported, - }, - ) - } - dynamicCfgErr = multierror.Append(dynamicCfgErr, - resource.ErrInvalidField{ - Name: "transparent_proxy", - Wrapped: resource.ErrInvalidField{ - Name: "dialed_directly", - Wrapped: resource.ErrUnsupported, - }, - }, - resource.ErrInvalidField{ - Name: "transparent_proxy", - Wrapped: resource.ErrInvalidField{ - Name: "outbound_listener_port", - Wrapped: errInvalidPort, - }, - }, - resource.ErrInvalidField{ - Name: "expose_config", - Wrapped: resource.ErrInvalidListElement{ - Name: "expose_paths", - Wrapped: resource.ErrInvalidField{ - Name: "listener_port", - Wrapped: errInvalidPort, - }, - }, - }, - resource.ErrInvalidField{ - Name: "expose_config", - Wrapped: resource.ErrInvalidListElement{ - Name: "expose_paths", - Wrapped: resource.ErrInvalidField{ - Name: "local_path_port", - Wrapped: errInvalidPort, - }, - }, - }, - ) - - var expError error - expError = multierror.Append(expError, - resource.ErrInvalidField{ - Name: "workloads", - Wrapped: resource.ErrEmpty, - }, - resource.ErrInvalidField{ - Name: "opaque_config", - Wrapped: resource.ErrUnsupported, - }, - resource.ErrInvalidField{ - Name: "dynamic_config", - Wrapped: dynamicCfgErr, - }, - ) - - require.Equal(t, err, expError) -} - -func TestValidateProxyConfiguration_AllFieldsValid(t *testing.T) { - proxyCfg := &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"foo"}}, - - DynamicConfig: &pbmesh.DynamicConfig{ - MutualTlsMode: pbmesh.MutualTLSMode_MUTUAL_TLS_MODE_DEFAULT, - MeshGatewayMode: pbmesh.MeshGatewayMode_MESH_GATEWAY_MODE_UNSPECIFIED, - - TransparentProxy: &pbmesh.TransparentProxy{ - DialedDirectly: false, - OutboundListenerPort: 15500, - }, - - ExposeConfig: &pbmesh.ExposeConfig{ - ExposePaths: []*pbmesh.ExposePath{ - { - ListenerPort: 1234, - LocalPathPort: 1235, - }, - }, - }, - }, - - BootstrapConfig: &pbmesh.BootstrapConfig{ - StatsdUrl: "stats-url", - DogstatsdUrl: "dogstats-url", - StatsTags: []string{"tags"}, - PrometheusBindAddr: "prom-bind-addr", - StatsBindAddr: "stats-bind-addr", - ReadyBindAddr: "ready-bind-addr", - OverrideJsonTpl: "override-json-tpl", - StaticClustersJson: "static-clusters-json", - StaticListenersJson: "static-listeners-json", - StatsSinksJson: "stats-sinks-json", - StatsConfigJson: "stats-config-json", - StatsFlushInterval: "stats-flush-interval", - TracingConfigJson: "tracing-config-json", - TelemetryCollectorBindSocketDir: "telemetry-collector-bind-socket-dir", - }, - } - - res := resourcetest.Resource(pbmesh.ProxyConfigurationType, "test"). - WithData(t, proxyCfg). - Build() - - err := ValidateProxyConfiguration(res) - require.NoError(t, err) -} - -func TestValidateProxyConfiguration_WorkloadSelector(t *testing.T) { - type testcase struct { - data *pbmesh.ProxyConfiguration - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.ProxyConfigurationType, "api"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, tc.data). - Build() - - // Ensure things are properly mutated and updated in the inputs. - err := MutateProxyConfiguration(res) - require.NoError(t, err) - { - mutated := resourcetest.MustDecode[*pbmesh.ProxyConfiguration](t, res) - tc.data = mutated.Data - } - - err = ValidateProxyConfiguration(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.ProxyConfiguration](t, res) - prototest.AssertDeepEqual(t, tc.data, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - // emptiness - "empty": { - data: &pbmesh.ProxyConfiguration{}, - expectErr: `invalid "workloads" field: cannot be empty`, - }, - "empty selector": { - data: &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{}, - }, - expectErr: `invalid "workloads" field: cannot be empty`, - }, - "bad selector": { - data: &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"blah"}, - Filter: "garbage.foo == bar", - }, - }, - expectErr: `invalid "filter" field: filter "garbage.foo == bar" is invalid: Selector "garbage" is not valid`, - }, - "good selector": { - data: &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"blah"}, - Filter: "metadata.foo == bar", - }, - DynamicConfig: &pbmesh.DynamicConfig{}, - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} diff --git a/internal/mesh/internal/types/proxy_state_template.go b/internal/mesh/internal/types/proxy_state_template.go deleted file mode 100644 index 43d2148217e0..000000000000 --- a/internal/mesh/internal/types/proxy_state_template.go +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "fmt" - "github.com/hashicorp/consul/internal/catalog" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func RegisterProxyStateTemplate(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmesh.ProxyStateTemplateType, - Proto: &pbmesh.ProxyStateTemplate{}, - Scope: resource.ScopeNamespace, - Validate: ValidateProxyStateTemplate, - ACLs: &resource.ACLHooks{ - Read: func(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, id *pbresource.ID, _ *pbresource.Resource) error { - // Check service:read and operator:read permissions. - // If service:read is not allowed, check operator:read. We want to allow both as this - // resource is mostly useful for debuggability and we want to cover - // the most cases that serve that purpose. - serviceReadErr := authorizer.ToAllowAuthorizer().ServiceReadAllowed(id.Name, authzContext) - operatorReadErr := authorizer.ToAllowAuthorizer().OperatorReadAllowed(authzContext) - - switch { - case serviceReadErr != nil: - return serviceReadErr - case operatorReadErr != nil: - return operatorReadErr - } - - return nil - }, - Write: func(authorizer acl.Authorizer, authzContext *acl.AuthorizerContext, p *pbresource.Resource) error { - // Require operator:write only for "break-glass" scenarios as this resource should be mostly - // managed by a controller. - return authorizer.ToAllowAuthorizer().OperatorWriteAllowed(authzContext) - }, - List: resource.NoOpACLListHook, - }, - }) -} - -var ValidateProxyStateTemplate = resource.DecodeAndValidate(validateProxyStateTemplate) - -func validateProxyStateTemplate(res *DecodedProxyStateTemplate) error { - // TODO(v2): validate a lot more of this - - var merr error - - if res.Data.ProxyState != nil { - wrapProxyStateErr := func(err error) error { - return resource.ErrInvalidField{ - Name: "proxy_state", - Wrapped: err, - } - } - for name, cluster := range res.Data.ProxyState.Clusters { - if name == "" { - merr = multierror.Append(merr, wrapProxyStateErr(resource.ErrInvalidMapKey{ - Map: "clusters", - Key: name, - Wrapped: resource.ErrEmpty, - })) - continue - } - - wrapClusterErr := func(err error) error { - return wrapProxyStateErr(resource.ErrInvalidMapValue{ - Map: "clusters", - Key: name, - Wrapped: err, - }) - } - - if name != cluster.Name { - merr = multierror.Append(merr, wrapClusterErr(resource.ErrInvalidField{ - Name: "name", - Wrapped: fmt.Errorf("cluster name %q does not match map key %q", cluster.Name, name), - })) - } - - if portErr := catalog.ValidateProtocol(pbcatalog.Protocol(cluster.Protocol)); portErr != nil { - merr = multierror.Append(merr, wrapClusterErr(resource.ErrInvalidField{ - Name: "protocol", - Wrapped: portErr, - })) - } - - if pbcatalog.Protocol(cluster.Protocol) == pbcatalog.Protocol_PROTOCOL_UNSPECIFIED { - merr = multierror.Append(merr, wrapClusterErr(resource.ErrInvalidField{ - Name: "protocol", - Wrapped: resource.ErrMissing, - })) - } - - if pbcatalog.Protocol(cluster.Protocol) == pbcatalog.Protocol_PROTOCOL_MESH { - merr = multierror.Append(merr, wrapClusterErr(resource.ErrInvalidField{ - Name: "protocol", - Wrapped: fmt.Errorf("protocol %q is not a valid cluster traffic protocol", - cluster.Protocol.String()), - })) - } - - wrapGroupErr := func(err error) error { - return wrapClusterErr(resource.ErrInvalidField{ - Name: "group", - Wrapped: err, - }) - } - - if cluster.Group == nil { - merr = multierror.Append(merr, wrapGroupErr(resource.ErrMissing)) - } else { - switch x := cluster.Group.(type) { - case *pbproxystate.Cluster_EndpointGroup: - wrapInnerGroupErr := func(err error) error { - return wrapGroupErr(resource.ErrInvalidField{ - Name: "endpoint_group", - Wrapped: err, - }) - } - - if x.EndpointGroup == nil { - merr = multierror.Append(merr, wrapInnerGroupErr(resource.ErrMissing)) - continue - } - - // The inner name field is optional, but if specified it has to - // match the enclosing cluster. - - if x.EndpointGroup.Name != "" && x.EndpointGroup.Name != cluster.Name { - merr = multierror.Append(merr, wrapInnerGroupErr(resource.ErrInvalidField{ - Name: "name", - Wrapped: fmt.Errorf("optional but %q does not match enclosing cluster name %q", - x.EndpointGroup.Name, cluster.Name), - })) - } - - case *pbproxystate.Cluster_FailoverGroup: - wrapInnerGroupErr := func(err error) error { - return wrapGroupErr(resource.ErrInvalidField{ - Name: "failover_group", - Wrapped: err, - }) - } - - if x.FailoverGroup == nil { - merr = multierror.Append(merr, wrapInnerGroupErr(resource.ErrMissing)) - continue - } - - if len(x.FailoverGroup.EndpointGroups) == 0 { - merr = multierror.Append(merr, wrapInnerGroupErr(resource.ErrInvalidField{ - Name: "endpoint_groups", - Wrapped: resource.ErrEmpty, - })) - } - - for i, eg := range x.FailoverGroup.EndpointGroups { - wrapFailoverEndpointGroupErr := func(err error) error { - return wrapInnerGroupErr(resource.ErrInvalidListElement{ - Name: "endpoint_groups", - Index: i, - Wrapped: err, - }) - } - // The inner name field is required and cannot match the enclosing cluster. - switch { - case eg.Name == "": - merr = multierror.Append(merr, wrapFailoverEndpointGroupErr(resource.ErrInvalidField{ - Name: "name", - Wrapped: resource.ErrEmpty, - })) - case eg.Name == cluster.Name: - merr = multierror.Append(merr, wrapFailoverEndpointGroupErr(resource.ErrInvalidField{ - Name: "name", - Wrapped: fmt.Errorf( - "name cannot be the same as the enclosing cluster %q", - eg.Name, - ), - })) - } - } - default: - merr = multierror.Append(merr, wrapGroupErr(fmt.Errorf("unknown type: %T", cluster.Group))) - } - } - } - } - - return merr -} diff --git a/internal/mesh/internal/types/proxy_state_template_test.go b/internal/mesh/internal/types/proxy_state_template_test.go deleted file mode 100644 index d562a9c43a29..000000000000 --- a/internal/mesh/internal/types/proxy_state_template_test.go +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestValidateProxyStateTemplate(t *testing.T) { - type testcase struct { - pst *pbmesh.ProxyStateTemplate - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "api"). - WithData(t, tc.pst). - Build() - - err := ValidateProxyStateTemplate(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.ProxyStateTemplate](t, res) - prototest.AssertDeepEqual(t, tc.pst, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - pstForCluster := func(name string, cluster *pbproxystate.Cluster) *pbmesh.ProxyStateTemplate { - return &pbmesh.ProxyStateTemplate{ - ProxyState: &pbmesh.ProxyState{ - Clusters: map[string]*pbproxystate.Cluster{ - name: cluster, - }, - }, - } - } - - clusterForGroups := func(name string, groups ...*pbproxystate.EndpointGroup) *pbproxystate.Cluster { - cluster := &pbproxystate.Cluster{ - Name: name, - Protocol: pbproxystate.Protocol_PROTOCOL_TCP, - } - - require.NotEmpty(t, groups) - - if len(groups) == 1 { - cluster.Group = &pbproxystate.Cluster_EndpointGroup{ - EndpointGroup: groups[0], - } - } else { - cluster.Group = &pbproxystate.Cluster_FailoverGroup{ - FailoverGroup: &pbproxystate.FailoverGroup{ - EndpointGroups: groups, - }, - } - } - return cluster - } - - endpointGroup := func(name string) *pbproxystate.EndpointGroup { - return &pbproxystate.EndpointGroup{ - Name: name, - Group: &pbproxystate.EndpointGroup_Dynamic{ - Dynamic: &pbproxystate.DynamicEndpointGroup{}, - }, - } - } - - // also cover clusters with names that don't match the map key - // also empty map keys - cases := map[string]testcase{ - // ============== COMMON ============== - "cluster with invalid protocol": { - pst: pstForCluster("api-cluster", &pbproxystate.Cluster{ - Name: "api-cluster", - Protocol: 100, - }), - expectErr: `invalid value of key "api-cluster" within clusters: invalid "protocol" field: not a supported enum value: 100`, - }, - "cluster with mesh protocol": { - pst: pstForCluster("api-cluster", &pbproxystate.Cluster{ - Name: "api-cluster", - Protocol: pbproxystate.Protocol_PROTOCOL_MESH, - }), - expectErr: `invalid value of key "api-cluster" within clusters: invalid "protocol" field: protocol "PROTOCOL_MESH" is not a valid cluster traffic protocol`, - }, - "cluster with missing protocol": { - pst: pstForCluster("api-cluster", &pbproxystate.Cluster{ - Name: "api-cluster", - Protocol: pbproxystate.Protocol_PROTOCOL_UNSPECIFIED, - }), - expectErr: `invalid value of key "api-cluster" within clusters: invalid "protocol" field: missing required field`, - }, - "cluster with missing cluster group": { - pst: pstForCluster("api-cluster", &pbproxystate.Cluster{ - Name: "api-cluster", - }), - expectErr: `invalid "proxy_state" field: invalid value of key "api-cluster" within clusters: invalid "group" field: missing required field`, - }, - // ============== STANDARD ============== - "standard cluster with empty map key": { - pst: pstForCluster("", clusterForGroups("api-cluster", - endpointGroup(""), - )), - expectErr: `invalid "proxy_state" field: map clusters contains an invalid key - "": cannot be empty`, - }, - "standard cluster with missing cluster name": { - pst: pstForCluster("api-cluster", clusterForGroups("", - endpointGroup(""), - )), - expectErr: `invalid "proxy_state" field: invalid value of key "api-cluster" within clusters: invalid "name" field: cluster name "" does not match map key "api-cluster"`, - }, - "standard cluster with empty endpoint group name": { - pst: pstForCluster("api-cluster", clusterForGroups("api-cluster", - endpointGroup(""), - )), - }, - "standard cluster with same endpoint group name": { - pst: pstForCluster("api-cluster", clusterForGroups("api-cluster", - endpointGroup("api-cluster"), - )), - }, - "standard cluster with different endpoint group name": { - pst: pstForCluster("api-cluster", clusterForGroups("api-cluster", - endpointGroup("garbage"), - )), - expectErr: `invalid "proxy_state" field: invalid value of key "api-cluster" within clusters: invalid "group" field: invalid "endpoint_group" field: invalid "name" field: optional but "garbage" does not match enclosing cluster name "api-cluster"`, - }, - // ============== FAILOVER ============== - "failover cluster with empty map key": { - pst: pstForCluster("", clusterForGroups("api-cluster", - endpointGroup("api-cluster~0"), - endpointGroup("api-cluster~1"), - )), - expectErr: `invalid "proxy_state" field: map clusters contains an invalid key - "": cannot be empty`, - }, - "failover cluster with missing cluster name": { - pst: pstForCluster("api-cluster", clusterForGroups("", - endpointGroup("api-cluster~0"), - endpointGroup("api-cluster~1"), - )), - expectErr: `invalid "proxy_state" field: invalid value of key "api-cluster" within clusters: invalid "name" field: cluster name "" does not match map key "api-cluster"`, - }, - "failover cluster with empty endpoint group name": { - pst: pstForCluster("api-cluster", clusterForGroups("api-cluster", - endpointGroup("api-cluster~0"), - endpointGroup(""), - )), - expectErr: `invalid "proxy_state" field: invalid value of key "api-cluster" within clusters: invalid "group" field: invalid "failover_group" field: invalid element at index 1 of list "endpoint_groups": invalid "name" field: cannot be empty`, - }, - "failover cluster with same endpoint group name": { - pst: pstForCluster("api-cluster", clusterForGroups("api-cluster", - endpointGroup("api-cluster~0"), - endpointGroup("api-cluster"), - )), - expectErr: `invalid "proxy_state" field: invalid value of key "api-cluster" within clusters: invalid "group" field: invalid "failover_group" field: invalid element at index 1 of list "endpoint_groups": invalid "name" field: name cannot be the same as the enclosing cluster "api-cluster"`, - }, - "failover cluster with no groups": { - pst: pstForCluster("api-cluster", &pbproxystate.Cluster{ - Name: "api-cluster", - Group: &pbproxystate.Cluster_FailoverGroup{ - FailoverGroup: &pbproxystate.FailoverGroup{ - EndpointGroups: nil, - }, - }, - }), - expectErr: `invalid "proxy_state" field: invalid value of key "api-cluster" within clusters: invalid "group" field: invalid "failover_group" field: invalid "endpoint_groups" field: cannot be empty`, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - t.Logf("%+v", tc.pst) - run(t, tc) - }) - } -} diff --git a/internal/mesh/internal/types/tcp_route.go b/internal/mesh/internal/types/tcp_route.go deleted file mode 100644 index 02dd5aaa10fd..000000000000 --- a/internal/mesh/internal/types/tcp_route.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "fmt" - - "github.com/hashicorp/go-multierror" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" -) - -func RegisterTCPRoute(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbmesh.TCPRouteType, - Proto: &pbmesh.TCPRoute{}, - Scope: resource.ScopeNamespace, - Mutate: MutateTCPRoute, - Validate: ValidateTCPRoute, - ACLs: xRouteACLHooks[*pbmesh.TCPRoute](), - }) -} - -var MutateTCPRoute = resource.DecodeAndMutate(mutateTCPRoute) - -func mutateTCPRoute(res *DecodedTCPRoute) (bool, error) { - changed := false - - if mutateParentRefs(res.Id.Tenancy, res.Data.ParentRefs) { - changed = true - } - - for _, rule := range res.Data.Rules { - for _, backend := range rule.BackendRefs { - if backend.BackendRef == nil || backend.BackendRef.Ref == nil { - continue - } - if mutateXRouteRef(res.Id.Tenancy, backend.BackendRef.Ref) { - changed = true - } - } - } - - return changed, nil -} - -var ValidateTCPRoute = resource.DecodeAndValidate(validateTCPRoute) - -func validateTCPRoute(res *DecodedTCPRoute) error { - var merr error - - if err := validateParentRefs(res.Id, res.Data.ParentRefs); err != nil { - merr = multierror.Append(merr, err) - } - - if len(res.Data.Rules) > 1 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "rules", - Wrapped: fmt.Errorf("must only specify a single rule for now"), - }) - } - - for i, rule := range res.Data.Rules { - wrapRuleErr := func(err error) error { - return resource.ErrInvalidListElement{ - Name: "rules", - Index: i, - Wrapped: err, - } - } - - if len(rule.BackendRefs) == 0 { - merr = multierror.Append(merr, wrapRuleErr( - resource.ErrInvalidField{ - Name: "backend_refs", - Wrapped: resource.ErrEmpty, - }, - )) - } - for j, hbref := range rule.BackendRefs { - wrapBackendRefErr := func(err error) error { - return wrapRuleErr(resource.ErrInvalidListElement{ - Name: "backend_refs", - Index: j, - Wrapped: err, - }) - } - - wrapBackendRefFieldErr := func(err error) error { - return wrapBackendRefErr(resource.ErrInvalidField{ - Name: "backend_ref", - Wrapped: err, - }) - } - if err := validateBackendRef(hbref.BackendRef, wrapBackendRefFieldErr); err != nil { - merr = multierror.Append(merr, err) - } - } - } - - return merr -} diff --git a/internal/mesh/internal/types/tcp_route_test.go b/internal/mesh/internal/types/tcp_route_test.go deleted file mode 100644 index 7dd9a6a80d28..000000000000 --- a/internal/mesh/internal/types/tcp_route_test.go +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestMutateTCPRoute(t *testing.T) { - type testcase struct { - routeTenancy *pbresource.Tenancy - route *pbmesh.TCPRoute - expect *pbmesh.TCPRoute - } - - cases := map[string]testcase{} - - // Add common parent refs test cases. - for name, parentTC := range getXRouteParentRefMutateTestCases() { - cases["parent-ref: "+name] = testcase{ - routeTenancy: parentTC.routeTenancy, - route: &pbmesh.TCPRoute{ - ParentRefs: parentTC.refs, - }, - expect: &pbmesh.TCPRoute{ - ParentRefs: parentTC.expect, - }, - } - } - // add common backend ref test cases. - for name, backendTC := range getXRouteBackendRefMutateTestCases() { - var ( - refs []*pbmesh.TCPBackendRef - expect []*pbmesh.TCPBackendRef - ) - for _, br := range backendTC.refs { - refs = append(refs, &pbmesh.TCPBackendRef{ - BackendRef: br, - }) - } - for _, br := range backendTC.expect { - expect = append(expect, &pbmesh.TCPBackendRef{ - BackendRef: br, - }) - } - cases["backend-ref: "+name] = testcase{ - routeTenancy: backendTC.routeTenancy, - route: &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.TCPRouteRule{ - {BackendRefs: refs}, - }, - }, - expect: &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.TCPRouteRule{ - {BackendRefs: expect}, - }, - }, - } - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.TCPRouteType, "api"). - WithTenancy(tc.routeTenancy). - WithData(t, tc.route). - Build() - resource.DefaultIDTenancy(res.Id, nil, resource.DefaultNamespacedTenancy()) - - err := MutateTCPRoute(res) - require.NoError(t, err) - - got := resourcetest.MustDecode[*pbmesh.TCPRoute](t, res) - - if tc.expect == nil { - tc.expect = proto.Clone(tc.route).(*pbmesh.TCPRoute) - } - - prototest.AssertDeepEqual(t, tc.expect, got.Data) - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestValidateTCPRoute(t *testing.T) { - type testcase struct { - routeTenancy *pbresource.Tenancy - route *pbmesh.TCPRoute - expectErr string - } - - run := func(t *testing.T, tc testcase) { - res := resourcetest.Resource(pbmesh.TCPRouteType, "api"). - WithTenancy(tc.routeTenancy). - WithData(t, tc.route). - Build() - resource.DefaultIDTenancy(res.Id, nil, resource.DefaultNamespacedTenancy()) - - // Ensure things are properly mutated and updated in the inputs. - err := MutateTCPRoute(res) - require.NoError(t, err) - { - mutated := resourcetest.MustDecode[*pbmesh.TCPRoute](t, res) - tc.route = mutated.Data - } - - err = ValidateTCPRoute(res) - - // Verify that validate didn't actually change the object. - got := resourcetest.MustDecode[*pbmesh.TCPRoute](t, res) - prototest.AssertDeepEqual(t, tc.route, got.Data) - - if tc.expectErr == "" { - require.NoError(t, err) - } else { - testutil.RequireErrorContains(t, err, tc.expectErr) - } - } - - cases := map[string]testcase{ - "no rules": { - route: &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - }, - }, - "more than one rule": { - route: &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.TCPRouteRule{ - { - BackendRefs: []*pbmesh.TCPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "api", ""), - }}, - }, - { - BackendRefs: []*pbmesh.TCPBackendRef{{ - BackendRef: newBackendRef(pbcatalog.ServiceType, "db", ""), - }}, - }, - }, - }, - expectErr: `invalid "rules" field: must only specify a single rule for now`, - }, - } - - // Add common parent refs test cases. - for name, parentTC := range getXRouteParentRefTestCases() { - cases["parent-ref: "+name] = testcase{ - routeTenancy: parentTC.routeTenancy, - route: &pbmesh.TCPRoute{ - ParentRefs: parentTC.refs, - }, - expectErr: parentTC.expectErr, - } - } - // add common backend ref test cases. - for name, backendTC := range getXRouteBackendRefTestCases() { - var refs []*pbmesh.TCPBackendRef - for _, br := range backendTC.refs { - refs = append(refs, &pbmesh.TCPBackendRef{ - BackendRef: br, - }) - } - cases["backend-ref: "+name] = testcase{ - routeTenancy: backendTC.routeTenancy, - route: &pbmesh.TCPRoute{ - ParentRefs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "web", ""), - }, - Rules: []*pbmesh.TCPRouteRule{ - {BackendRefs: refs}, - }, - }, - expectErr: backendTC.expectErr, - } - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func TestTCPRouteACLs(t *testing.T) { - testXRouteACLs[*pbmesh.TCPRoute](t, func(t *testing.T, parentRefs, backendRefs []*pbresource.Reference) *pbresource.Resource { - data := &pbmesh.TCPRoute{ - ParentRefs: nil, - } - for _, ref := range parentRefs { - data.ParentRefs = append(data.ParentRefs, &pbmesh.ParentReference{ - Ref: ref, - }) - } - - var ruleRefs []*pbmesh.TCPBackendRef - for _, ref := range backendRefs { - ruleRefs = append(ruleRefs, &pbmesh.TCPBackendRef{ - BackendRef: &pbmesh.BackendReference{ - Ref: ref, - }, - }) - } - data.Rules = []*pbmesh.TCPRouteRule{ - {BackendRefs: ruleRefs}, - } - - return resourcetest.Resource(pbmesh.TCPRouteType, "api-tcp-route"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(t, data). - Build() - }) -} diff --git a/internal/mesh/internal/types/types.go b/internal/mesh/internal/types/types.go deleted file mode 100644 index cf1443aabf18..000000000000 --- a/internal/mesh/internal/types/types.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "github.com/hashicorp/consul/internal/resource" -) - -func Register(r resource.Registry) { - RegisterProxyConfiguration(r) - RegisterComputedProxyConfiguration(r) - RegisterDestinations(r) - RegisterComputedExplicitDestinations(r) - RegisterProxyStateTemplate(r) - RegisterHTTPRoute(r) - RegisterTCPRoute(r) - RegisterGRPCRoute(r) - RegisterDestinationPolicy(r) - RegisterComputedRoutes(r) - // todo (v2): uncomment once we implement it. - //RegisterDestinationsConfiguration(r) -} diff --git a/internal/mesh/internal/types/types_test.go b/internal/mesh/internal/types/types_test.go deleted file mode 100644 index 801d3de01846..000000000000 --- a/internal/mesh/internal/types/types_test.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func TestTypeRegistration(t *testing.T) { - // This test will ensure that all the required types have been registered - // It is not trying to determine whether the settings for the registrations - // are correct as that would amount more or less to hardcoding structs - // from types.go a second time here. - requiredKinds := []string{ - pbmesh.ProxyConfigurationKind, - pbmesh.DestinationsKind, - pbmesh.ProxyStateTemplateKind, - pbmesh.HTTPRouteKind, - pbmesh.TCPRouteKind, - pbmesh.GRPCRouteKind, - pbmesh.DestinationPolicyKind, - pbmesh.ComputedRoutesKind, - // todo (v2): re-enable once we implement it. - //pbmesh.DestinationsConfigurationKind, - } - - r := resource.NewRegistry() - Register(r) - - for _, kind := range requiredKinds { - t.Run(kind, func(t *testing.T) { - registration, ok := r.Resolve(&pbresource.Type{ - Group: pbmesh.GroupName, - GroupVersion: pbmesh.Version, - Kind: kind, - }) - - require.True(t, ok, "Resource kind %s has not been registered to the type registry", kind) - require.NotNil(t, registration, "Registration for %s was found but is nil", kind) - }) - } -} diff --git a/internal/mesh/internal/types/util.go b/internal/mesh/internal/types/util.go deleted file mode 100644 index a484f0943f8d..000000000000 --- a/internal/mesh/internal/types/util.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "fmt" - - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func IsRouteType(typ *pbresource.Type) bool { - return IsHTTPRouteType(typ) || - IsGRPCRouteType(typ) || - IsTCPRouteType(typ) -} - -func IsHTTPRouteType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, pbmesh.HTTPRouteType): - return true - } - return false -} - -func IsGRPCRouteType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, pbmesh.GRPCRouteType): - return true - } - return false -} - -func IsTCPRouteType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, pbmesh.TCPRouteType): - return true - } - return false -} - -func IsFailoverPolicyType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, pbcatalog.FailoverPolicyType): - return true - } - return false -} - -func IsDestinationPolicyType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, pbmesh.DestinationPolicyType): - return true - } - return false -} - -func IsServiceType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, pbcatalog.ServiceType): - return true - } - return false -} - -func IsComputedRoutesType(typ *pbresource.Type) bool { - switch { - case resource.EqualType(typ, pbmesh.ComputedRoutesType): - return true - } - return false -} - -// BackendRefToComputedRoutesTarget turns the provided BackendReference into an -// opaque string format suitable for use as a map key and reference in a -// standalone object or reference. -// -// It is opaque in that the caller should not attempt to parse it, and there is -// no implied storage or wire compatibility concern, since the data is treated -// opaquely at use time. -func BackendRefToComputedRoutesTarget(backendRef *pbmesh.BackendReference) string { - ref := backendRef.Ref - - s := fmt.Sprintf( - "%s/%s/%s?port=%s", - resource.TypeToString(ref.Type), - resource.TenancyToString(ref.Tenancy), - ref.Name, - backendRef.Port, - ) - - if backendRef.Datacenter != "" { - s += "&dc=" + backendRef.Datacenter - } - - return s -} diff --git a/internal/mesh/internal/types/xroute.go b/internal/mesh/internal/types/xroute.go deleted file mode 100644 index 92e2136cd135..000000000000 --- a/internal/mesh/internal/types/xroute.go +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "errors" - "fmt" - "time" - - "github.com/hashicorp/go-multierror" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/catalog" - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type XRouteData interface { - proto.Message - XRouteWithRefs -} - -type XRouteWithRefs interface { - GetParentRefs() []*pbmesh.ParentReference - GetUnderlyingBackendRefs() []*pbmesh.BackendReference -} - -type portedRefKey struct { - Key resource.ReferenceKey - Port string -} - -func mutateParentRefs(xrouteTenancy *pbresource.Tenancy, parentRefs []*pbmesh.ParentReference) (changed bool) { - for _, parent := range parentRefs { - if parent.Ref == nil { - continue - } - changedThis := mutateXRouteRef(xrouteTenancy, parent.Ref) - if changedThis { - changed = true - } - } - return changed -} - -func mutateXRouteRef(xrouteTenancy *pbresource.Tenancy, ref *pbresource.Reference) (changed bool) { - if ref == nil { - return false - } - orig := proto.Clone(ref).(*pbresource.Reference) - resource.DefaultReferenceTenancy( - ref, - xrouteTenancy, - resource.DefaultNamespacedTenancy(), // All xRoutes are namespace scoped. - ) - - return !proto.Equal(orig, ref) -} - -func validateParentRefs(id *pbresource.ID, parentRefs []*pbmesh.ParentReference) error { - var merr error - if len(parentRefs) == 0 { - merr = multierror.Append(merr, resource.ErrInvalidField{ - Name: "parent_refs", - Wrapped: resource.ErrEmpty, - }) - } - - var ( - seen = make(map[portedRefKey]struct{}) - seenAny = make(map[resource.ReferenceKey][]string) - ) - for i, parent := range parentRefs { - wrapErr := func(err error) error { - return resource.ErrInvalidListElement{ - Name: "parent_refs", - Index: i, - Wrapped: err, - } - } - - wrapRefErr := func(err error) error { - return wrapErr(resource.ErrInvalidField{ - Name: "ref", - Wrapped: err, - }) - } - - if err := catalog.ValidateLocalServiceRefNoSection(parent.Ref, wrapRefErr); err != nil { - merr = multierror.Append(merr, err) - } else { - if !resource.EqualTenancy(id.Tenancy, parent.Ref.Tenancy) { - merr = multierror.Append(merr, wrapRefErr(resource.ErrInvalidField{ - Name: "tenancy", - Wrapped: resource.ErrReferenceTenancyNotEqual, - })) - } - prk := portedRefKey{ - Key: resource.NewReferenceKey(parent.Ref), - Port: parent.Port, - } - - _, portExist := seen[prk] - - if parent.Port == "" { - coveredPorts, exactExists := seenAny[prk.Key] - - if portExist { // check for duplicate wild - merr = multierror.Append(merr, wrapErr( - resource.ErrInvalidField{ - Name: "port", - Wrapped: fmt.Errorf( - "parent ref %q for wildcard port exists twice", - resource.ReferenceToString(parent.Ref), - ), - }, - )) - } else if exactExists { // check for existing exact - merr = multierror.Append(merr, wrapErr( - resource.ErrInvalidField{ - Name: "port", - Wrapped: fmt.Errorf( - "parent ref %q for ports %v covered by wildcard port already", - resource.ReferenceToString(parent.Ref), - coveredPorts, - ), - }, - )) - } else { - seen[prk] = struct{}{} - } - - } else { - prkWild := prk - prkWild.Port = "" - _, wildExist := seen[prkWild] - - if portExist { // check for duplicate exact - merr = multierror.Append(merr, wrapErr( - resource.ErrInvalidField{ - Name: "port", - Wrapped: fmt.Errorf( - "parent ref %q for port %q exists twice", - resource.ReferenceToString(parent.Ref), - parent.Port, - ), - }, - )) - } else if wildExist { // check for existing wild - merr = multierror.Append(merr, wrapErr( - resource.ErrInvalidField{ - Name: "port", - Wrapped: fmt.Errorf( - "parent ref %q for port %q covered by wildcard port already", - resource.ReferenceToString(parent.Ref), - parent.Port, - ), - }, - )) - } else { - seen[prk] = struct{}{} - seenAny[prk.Key] = append(seenAny[prk.Key], parent.Port) - } - } - } - } - - return merr -} - -func validateBackendRef(backendRef *pbmesh.BackendReference, wrapErr func(error) error) error { - if backendRef == nil { - return wrapErr(resource.ErrMissing) - } - - var merr error - - wrapRefErr := func(err error) error { - return wrapErr(resource.ErrInvalidField{ - Name: "ref", - Wrapped: err, - }) - } - if err := catalog.ValidateLocalServiceRefNoSection(backendRef.Ref, wrapRefErr); err != nil { - merr = multierror.Append(merr, err) - } - if backendRef.Datacenter != "" { - merr = multierror.Append(merr, wrapErr(resource.ErrInvalidField{ - Name: "datacenter", - Wrapped: errors.New("datacenter is not yet supported on backend refs"), - })) - } - - return merr -} - -func validateHeaderMatchType(typ pbmesh.HeaderMatchType) error { - // enumcover:pbmesh.HeaderMatchType - switch typ { - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_UNSPECIFIED: - return resource.ErrMissing - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT: - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_REGEX: - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_PRESENT: - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_PREFIX: - case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_SUFFIX: - default: - return fmt.Errorf("not a supported enum value: %v", typ) - } - return nil -} - -func errTimeoutCannotBeNegative(d time.Duration) error { - return fmt.Errorf("timeout cannot be negative: %v", d) -} - -func validateHTTPTimeouts(timeouts *pbmesh.HTTPRouteTimeouts) []error { - if timeouts == nil { - return nil - } - - var errs []error - - if timeouts.Request != nil { - val := timeouts.Request.AsDuration() - if val < 0 { - errs = append(errs, resource.ErrInvalidField{ - Name: "request", - Wrapped: errTimeoutCannotBeNegative(val), - }) - } - } - if timeouts.Idle != nil { - val := timeouts.Idle.AsDuration() - if val < 0 { - errs = append(errs, resource.ErrInvalidField{ - Name: "idle", - Wrapped: errTimeoutCannotBeNegative(val), - }) - } - } - - return errs -} - -func validateHTTPRetries(retries *pbmesh.HTTPRouteRetries) []error { - if retries == nil { - return nil - } - - var errs []error - - for i, condition := range retries.OnConditions { - if !isValidRetryCondition(condition) { - errs = append(errs, resource.ErrInvalidListElement{ - Name: "on_conditions", - Index: i, - Wrapped: fmt.Errorf("not a valid retry condition: %q", condition), - }) - } - } - - return errs -} - -func isValidRetryCondition(retryOn string) bool { - switch retryOn { - case "5xx", - "gateway-error", - "reset", - "connect-failure", - "envoy-ratelimited", - "retriable-4xx", - "refused-stream", - "cancelled", - "deadline-exceeded", - "internal", - "resource-exhausted", - "unavailable": - return true - default: - return false - } -} - -func xRouteACLHooks[R XRouteData]() *resource.ACLHooks { - hooks := &resource.ACLHooks{ - Read: resource.DecodeAndAuthorizeRead(aclReadHookXRoute[R]), - Write: resource.DecodeAndAuthorizeWrite(aclWriteHookXRoute[R]), - List: resource.NoOpACLListHook, - } - - return hooks -} - -func aclReadHookXRoute[R XRouteData](authorizer acl.Authorizer, _ *acl.AuthorizerContext, res *resource.DecodedResource[R]) error { - // Need service:read on ALL of the services this is controlling traffic for. - for _, parentRef := range res.Data.GetParentRefs() { - parentAuthzContext := resource.AuthorizerContext(parentRef.Ref.GetTenancy()) - parentServiceName := parentRef.Ref.GetName() - - if err := authorizer.ToAllowAuthorizer().ServiceReadAllowed(parentServiceName, parentAuthzContext); err != nil { - return err - } - } - - return nil -} - -func aclWriteHookXRoute[R XRouteData](authorizer acl.Authorizer, _ *acl.AuthorizerContext, res *resource.DecodedResource[R]) error { - // Need service:write on ALL of the services this is controlling traffic for. - for _, parentRef := range res.Data.GetParentRefs() { - parentAuthzContext := resource.AuthorizerContext(parentRef.Ref.GetTenancy()) - parentServiceName := parentRef.Ref.GetName() - - if err := authorizer.ToAllowAuthorizer().ServiceWriteAllowed(parentServiceName, parentAuthzContext); err != nil { - return err - } - } - - // Need service:read on ALL of the services this directs traffic at. - for _, backendRef := range res.Data.GetUnderlyingBackendRefs() { - backendAuthzContext := resource.AuthorizerContext(backendRef.Ref.GetTenancy()) - backendServiceName := backendRef.Ref.GetName() - - if err := authorizer.ToAllowAuthorizer().ServiceReadAllowed(backendServiceName, backendAuthzContext); err != nil { - return err - } - } - - return nil -} diff --git a/internal/mesh/internal/types/xroute_test.go b/internal/mesh/internal/types/xroute_test.go deleted file mode 100644 index 5ba39e24cc07..000000000000 --- a/internal/mesh/internal/types/xroute_test.go +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/wrapperspb" - - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type xRouteParentRefMutateTestcase struct { - routeTenancy *pbresource.Tenancy - refs []*pbmesh.ParentReference - expect []*pbmesh.ParentReference -} - -func getXRouteParentRefMutateTestCases() map[string]xRouteParentRefMutateTestcase { - newRef := func(typ *pbresource.Type, tenancyStr, name string) *pbresource.Reference { - return resourcetest.Resource(typ, name). - WithTenancy(resourcetest.Tenancy(tenancyStr)). - Reference("") - } - - newParentRef := func(typ *pbresource.Type, tenancyStr, name, port string) *pbmesh.ParentReference { - return &pbmesh.ParentReference{ - Ref: newRef(typ, tenancyStr, name), - Port: port, - } - } - - return map[string]xRouteParentRefMutateTestcase{ - "parent ref tenancies defaulted": { - routeTenancy: resourcetest.Tenancy("foo.bar"), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "", "api", ""), - newParentRef(pbcatalog.ServiceType, ".zim", "api", ""), - newParentRef(pbcatalog.ServiceType, "gir.zim", "api", ""), - }, - expect: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "foo.bar", "api", ""), - newParentRef(pbcatalog.ServiceType, "foo.zim", "api", ""), - newParentRef(pbcatalog.ServiceType, "gir.zim", "api", ""), - }, - }, - } -} - -type xRouteBackendRefMutateTestcase struct { - routeTenancy *pbresource.Tenancy - refs []*pbmesh.BackendReference - expect []*pbmesh.BackendReference -} - -func getXRouteBackendRefMutateTestCases() map[string]xRouteBackendRefMutateTestcase { - newRef := func(typ *pbresource.Type, tenancyStr, name string) *pbresource.Reference { - return resourcetest.Resource(typ, name). - WithTenancy(resourcetest.Tenancy(tenancyStr)). - Reference("") - } - - newBackendRef := func(typ *pbresource.Type, tenancyStr, name, port string) *pbmesh.BackendReference { - return &pbmesh.BackendReference{ - Ref: newRef(typ, tenancyStr, name), - Port: port, - } - } - - return map[string]xRouteBackendRefMutateTestcase{ - "backend ref tenancies defaulted": { - routeTenancy: resourcetest.Tenancy("foo.bar"), - refs: []*pbmesh.BackendReference{ - newBackendRef(pbcatalog.ServiceType, "", "api", ""), - newBackendRef(pbcatalog.ServiceType, ".zim", "api", ""), - newBackendRef(pbcatalog.ServiceType, "gir.zim", "api", ""), - }, - expect: []*pbmesh.BackendReference{ - newBackendRef(pbcatalog.ServiceType, "foo.bar", "api", ""), - newBackendRef(pbcatalog.ServiceType, "foo.zim", "api", ""), - newBackendRef(pbcatalog.ServiceType, "gir.zim", "api", ""), - }, - }, - } -} - -type xRouteParentRefTestcase struct { - routeTenancy *pbresource.Tenancy - refs []*pbmesh.ParentReference - expectErr string -} - -func getXRouteParentRefTestCases() map[string]xRouteParentRefTestcase { - newRef := func(typ *pbresource.Type, tenancyStr, name string) *pbresource.Reference { - return resourcetest.Resource(typ, name). - WithTenancy(resourcetest.Tenancy(tenancyStr)). - Reference("") - } - - newParentRef := func(typ *pbresource.Type, tenancyStr, name, port string) *pbmesh.ParentReference { - return &pbmesh.ParentReference{ - Ref: newRef(typ, tenancyStr, name), - Port: port, - } - } - - return map[string]xRouteParentRefTestcase{ - "no parent refs": { - routeTenancy: resource.DefaultNamespacedTenancy(), - expectErr: `invalid "parent_refs" field: cannot be empty`, - }, - "parent ref with nil ref": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "", "api", ""), - { - Ref: nil, - Port: "http", - }, - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "ref" field: missing required field`, - }, - "parent ref with bad type ref": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "", "api", ""), - newParentRef(pbcatalog.WorkloadType, "", "api", ""), - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "ref" field: invalid "type" field: reference must have type catalog.v2beta1.Service`, - }, - "parent ref with section": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "", "api", ""), - { - Ref: resourcetest.Resource(pbcatalog.ServiceType, "web").Reference("section2"), - Port: "http", - }, - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "ref" field: invalid "section" field: section cannot be set here`, - }, - "cross namespace parent": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "default.foo", "api", ""), - }, - expectErr: `invalid element at index 0 of list "parent_refs": invalid "ref" field: invalid "tenancy" field: resource tenancy and reference tenancy differ`, - }, - "cross partition parent": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "alpha.default", "api", ""), - }, - expectErr: `invalid element at index 0 of list "parent_refs": invalid "ref" field: invalid "tenancy" field: resource tenancy and reference tenancy differ`, - }, - "cross tenancy parent": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "alpha.foo", "api", ""), - }, - expectErr: `invalid element at index 0 of list "parent_refs": invalid "ref" field: invalid "tenancy" field: resource tenancy and reference tenancy differ`, - }, - "duplicate exact parents": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "", "api", "http"), - newParentRef(pbcatalog.ServiceType, "", "api", "http"), - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "port" field: parent ref "catalog.v2beta1.Service/default.local.default/api" for port "http" exists twice`, - }, - "duplicate wild parents": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "", "api", ""), - newParentRef(pbcatalog.ServiceType, "", "api", ""), - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "port" field: parent ref "catalog.v2beta1.Service/default.local.default/api" for wildcard port exists twice`, - }, - "duplicate parents via exact+wild overlap": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "", "api", "http"), - newParentRef(pbcatalog.ServiceType, "", "api", ""), - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "port" field: parent ref "catalog.v2beta1.Service/default.local.default/api" for ports [http] covered by wildcard port already`, - }, - "duplicate parents via exact+wild overlap (reversed)": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "", "api", ""), - newParentRef(pbcatalog.ServiceType, "", "api", "http"), - }, - expectErr: `invalid element at index 1 of list "parent_refs": invalid "port" field: parent ref "catalog.v2beta1.Service/default.local.default/api" for port "http" covered by wildcard port already`, - }, - "good single parent ref": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "", "api", "http"), - }, - }, - "good muliple parent refs": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.ParentReference{ - newParentRef(pbcatalog.ServiceType, "", "api", "http"), - newParentRef(pbcatalog.ServiceType, "", "web", ""), - }, - }, - } -} - -type xRouteBackendRefTestcase struct { - routeTenancy *pbresource.Tenancy - refs []*pbmesh.BackendReference - expectErr string -} - -func getXRouteBackendRefTestCases() map[string]xRouteBackendRefTestcase { - newRef := func(typ *pbresource.Type, tenancyStr, name string) *pbresource.Reference { - return resourcetest.Resource(typ, name). - WithTenancy(resourcetest.Tenancy(tenancyStr)). - Reference("") - } - - newBackendRef := func(typ *pbresource.Type, tenancyStr, name, port string) *pbmesh.BackendReference { - return &pbmesh.BackendReference{ - Ref: newRef(typ, tenancyStr, name), - Port: port, - } - } - return map[string]xRouteBackendRefTestcase{ - "no backend refs": { - routeTenancy: resource.DefaultNamespacedTenancy(), - expectErr: `invalid "backend_refs" field: cannot be empty`, - }, - "backend ref with nil ref": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.BackendReference{ - newBackendRef(pbcatalog.ServiceType, "", "api", ""), - { - Ref: nil, - Port: "http", - }, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 1 of list "backend_refs": invalid "backend_ref" field: invalid "ref" field: missing required field`, - }, - "backend ref with bad type ref": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.BackendReference{ - newBackendRef(pbcatalog.ServiceType, "", "api", ""), - newBackendRef(pbcatalog.WorkloadType, "", "api", ""), - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 1 of list "backend_refs": invalid "backend_ref" field: invalid "ref" field: invalid "type" field: reference must have type catalog.v2beta1.Service`, - }, - "backend ref with section": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.BackendReference{ - newBackendRef(pbcatalog.ServiceType, "", "api", ""), - { - Ref: resourcetest.Resource(pbcatalog.ServiceType, "web").Reference("section2"), - Port: "http", - }, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 1 of list "backend_refs": invalid "backend_ref" field: invalid "ref" field: invalid "section" field: section cannot be set here`, - }, - "backend ref with datacenter": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.BackendReference{ - newBackendRef(pbcatalog.ServiceType, "", "api", ""), - { - Ref: newRef(pbcatalog.ServiceType, "", "db"), - Port: "http", - Datacenter: "dc2", - }, - }, - expectErr: `invalid element at index 0 of list "rules": invalid element at index 1 of list "backend_refs": invalid "backend_ref" field: invalid "datacenter" field: datacenter is not yet supported on backend refs`, - }, - "cross namespace backend": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.BackendReference{ - newBackendRef(pbcatalog.ServiceType, "default.foo", "api", ""), - }, - }, - "cross partition backend": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.BackendReference{ - newBackendRef(pbcatalog.ServiceType, "alpha.default", "api", ""), - }, - }, - "cross tenancy backend": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.BackendReference{ - newBackendRef(pbcatalog.ServiceType, "alpha.foo", "api", ""), - }, - }, - "good backend ref": { - routeTenancy: resource.DefaultNamespacedTenancy(), - refs: []*pbmesh.BackendReference{ - newBackendRef(pbcatalog.ServiceType, "", "api", ""), - { - Ref: newRef(pbcatalog.ServiceType, "", "db"), - Port: "http", - }, - }, - }, - } -} - -type xRouteTimeoutsTestcase struct { - timeouts *pbmesh.HTTPRouteTimeouts - expectErr string -} - -func getXRouteTimeoutsTestCases() map[string]xRouteTimeoutsTestcase { - return map[string]xRouteTimeoutsTestcase{ - "bad request": { - timeouts: &pbmesh.HTTPRouteTimeouts{ - Request: durationpb.New(-1 * time.Second), - }, - expectErr: `invalid element at index 0 of list "rules": invalid "timeouts" field: invalid "request" field: timeout cannot be negative: -1s`, - }, - "bad idle": { - timeouts: &pbmesh.HTTPRouteTimeouts{ - Idle: durationpb.New(-1 * time.Second), - }, - expectErr: `invalid element at index 0 of list "rules": invalid "timeouts" field: invalid "idle" field: timeout cannot be negative: -1s`, - }, - "good all": { - timeouts: &pbmesh.HTTPRouteTimeouts{ - Request: durationpb.New(1 * time.Second), - Idle: durationpb.New(3 * time.Second), - }, - }, - } -} - -type xRouteRetriesTestcase struct { - retries *pbmesh.HTTPRouteRetries - expectErr string -} - -func getXRouteRetriesTestCases() map[string]xRouteRetriesTestcase { - return map[string]xRouteRetriesTestcase{ - "bad conditions": { - retries: &pbmesh.HTTPRouteRetries{ - OnConditions: []string{"garbage"}, - }, - expectErr: `invalid element at index 0 of list "rules": invalid "retries" field: invalid element at index 0 of list "on_conditions": not a valid retry condition: "garbage"`, - }, - "good all": { - retries: &pbmesh.HTTPRouteRetries{ - Number: wrapperspb.UInt32(5), - OnConditions: []string{"internal"}, - }, - }, - } -} - -func testXRouteACLs[R XRouteData](t *testing.T, newRoute func(t *testing.T, parentRefs, backendRefs []*pbresource.Reference) *pbresource.Resource) { - // Wire up a registry to generically invoke hooks - registry := resource.NewRegistry() - Register(registry) - - userNewRoute := newRoute - newRoute = func(t *testing.T, parentRefs, backendRefs []*pbresource.Reference) *pbresource.Resource { - require.NotEmpty(t, parentRefs) - require.NotEmpty(t, backendRefs) - res := userNewRoute(t, parentRefs, backendRefs) - res.Id.Tenancy = parentRefs[0].Tenancy - resourcetest.ValidateAndNormalize(t, registry, res) - return res - } - - const ( - DENY = resourcetest.DENY - ALLOW = resourcetest.ALLOW - DEFAULT = resourcetest.DEFAULT - ) - - serviceRef := func(tenancy, name string) *pbresource.Reference { - return newRefWithTenancy(pbcatalog.ServiceType, tenancy, name) - } - - resOneParentOneBackend := func(parentTenancy, backendTenancy string) *pbresource.Resource { - return newRoute(t, - []*pbresource.Reference{ - serviceRef(parentTenancy, "api1"), - }, - []*pbresource.Reference{ - serviceRef(backendTenancy, "backend1"), - }, - ) - } - resTwoParentsOneBackend := func(parentTenancy, backendTenancy string) *pbresource.Resource { - return newRoute(t, - []*pbresource.Reference{ - serviceRef(parentTenancy, "api1"), - serviceRef(parentTenancy, "api2"), - }, - []*pbresource.Reference{ - serviceRef(backendTenancy, "backend1"), - }, - ) - } - resOneParentTwoBackends := func(parentTenancy, backendTenancy string) *pbresource.Resource { - return newRoute(t, - []*pbresource.Reference{ - serviceRef(parentTenancy, "api1"), - }, - []*pbresource.Reference{ - serviceRef(backendTenancy, "backend1"), - serviceRef(backendTenancy, "backend2"), - }, - ) - } - resTwoParentsTwoBackends := func(parentTenancy, backendTenancy string) *pbresource.Resource { - return newRoute(t, - []*pbresource.Reference{ - serviceRef(parentTenancy, "api1"), - serviceRef(parentTenancy, "api2"), - }, - []*pbresource.Reference{ - serviceRef(backendTenancy, "backend1"), - serviceRef(backendTenancy, "backend2"), - }, - ) - } - - run := func(t *testing.T, name string, tc resourcetest.ACLTestCase) { - t.Run(name, func(t *testing.T) { - resourcetest.RunACLTestCase(t, tc, registry) - }) - } - - isEnterprise := (structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default") - - serviceRead := func(partition, namespace, name string) string { - if isEnterprise { - return fmt.Sprintf(` partition %q { namespace %q { service %q { policy = "read" } } }`, partition, namespace, name) - } - return fmt.Sprintf(` service %q { policy = "read" } `, name) - } - serviceWrite := func(partition, namespace, name string) string { - if isEnterprise { - return fmt.Sprintf(` partition %q { namespace %q { service %q { policy = "write" } } }`, partition, namespace, name) - } - return fmt.Sprintf(` service %q { policy = "write" } `, name) - } - - assert := func(t *testing.T, name string, rules string, res *pbresource.Resource, readOK, writeOK string) { - tc := resourcetest.ACLTestCase{ - Rules: rules, - Res: res, - ReadOK: readOK, - WriteOK: writeOK, - ListOK: DEFAULT, - ReadHookRequiresResource: true, - } - run(t, name, tc) - } - - tenancies := []string{"default.default"} - if isEnterprise { - tenancies = append(tenancies, "default.foo", "alpha.default", "alpha.foo") - } - - for _, parentTenancyStr := range tenancies { - t.Run("route tenancy: "+parentTenancyStr, func(t *testing.T) { - for _, backendTenancyStr := range tenancies { - t.Run("backend tenancy: "+backendTenancyStr, func(t *testing.T) { - for _, aclTenancyStr := range tenancies { - t.Run("acl tenancy: "+aclTenancyStr, func(t *testing.T) { - aclTenancy := resourcetest.Tenancy(aclTenancyStr) - - maybe := func(match string, parentOnly bool) string { - if parentTenancyStr != aclTenancyStr { - return DENY - } - if !parentOnly && backendTenancyStr != aclTenancyStr { - return DENY - } - return match - } - - t.Run("no rules", func(t *testing.T) { - rules := `` - assert(t, "1parent 1backend", rules, resOneParentOneBackend(parentTenancyStr, backendTenancyStr), DENY, DENY) - assert(t, "1parent 2backends", rules, resOneParentTwoBackends(parentTenancyStr, backendTenancyStr), DENY, DENY) - assert(t, "2parents 1backend", rules, resTwoParentsOneBackend(parentTenancyStr, backendTenancyStr), DENY, DENY) - assert(t, "2parents 2backends", rules, resTwoParentsTwoBackends(parentTenancyStr, backendTenancyStr), DENY, DENY) - }) - t.Run("api1:read", func(t *testing.T) { - rules := serviceRead(aclTenancy.Partition, aclTenancy.Namespace, "api1") - assert(t, "1parent 1backend", rules, resOneParentOneBackend(parentTenancyStr, backendTenancyStr), maybe(ALLOW, true), DENY) - assert(t, "1parent 2backends", rules, resOneParentTwoBackends(parentTenancyStr, backendTenancyStr), maybe(ALLOW, true), DENY) - assert(t, "2parents 1backend", rules, resTwoParentsOneBackend(parentTenancyStr, backendTenancyStr), DENY, DENY) - assert(t, "2parents 2backends", rules, resTwoParentsTwoBackends(parentTenancyStr, backendTenancyStr), DENY, DENY) - }) - t.Run("api1:write", func(t *testing.T) { - rules := serviceWrite(aclTenancy.Partition, aclTenancy.Namespace, "api1") - assert(t, "1parent 1backend", rules, resOneParentOneBackend(parentTenancyStr, backendTenancyStr), maybe(ALLOW, true), DENY) - assert(t, "1parent 2backends", rules, resOneParentTwoBackends(parentTenancyStr, backendTenancyStr), maybe(ALLOW, true), DENY) - assert(t, "2parents 1backend", rules, resTwoParentsOneBackend(parentTenancyStr, backendTenancyStr), DENY, DENY) - assert(t, "2parents 2backends", rules, resTwoParentsTwoBackends(parentTenancyStr, backendTenancyStr), DENY, DENY) - }) - t.Run("api1:write backend1:read", func(t *testing.T) { - rules := serviceWrite(aclTenancy.Partition, aclTenancy.Namespace, "api1") + - serviceRead(aclTenancy.Partition, aclTenancy.Namespace, "backend1") - assert(t, "1parent 1backend", rules, resOneParentOneBackend(parentTenancyStr, backendTenancyStr), maybe(ALLOW, true), maybe(ALLOW, false)) - assert(t, "1parent 2backends", rules, resOneParentTwoBackends(parentTenancyStr, backendTenancyStr), maybe(ALLOW, true), DENY) - assert(t, "2parents 1backend", rules, resTwoParentsOneBackend(parentTenancyStr, backendTenancyStr), DENY, DENY) - assert(t, "2parents 2backends", rules, resTwoParentsTwoBackends(parentTenancyStr, backendTenancyStr), DENY, DENY) - }) - }) - } - }) - } - }) - } -} - -func newRef(typ *pbresource.Type, name string) *pbresource.Reference { - return resourcetest.Resource(typ, name). - WithTenancy(resource.DefaultNamespacedTenancy()). - Reference("") -} - -func newRefWithTenancy(typ *pbresource.Type, tenancyStr, name string) *pbresource.Reference { - return resourcetest.Resource(typ, name). - WithTenancy(resourcetest.Tenancy(tenancyStr)). - Reference("") -} - -func newBackendRef(typ *pbresource.Type, name, port string) *pbmesh.BackendReference { - return &pbmesh.BackendReference{ - Ref: newRef(typ, name), - Port: port, - } -} - -func newParentRef(typ *pbresource.Type, name, port string) *pbmesh.ParentReference { - return newParentRefWithTenancy(typ, "default.default", name, port) -} - -func newParentRefWithTenancy(typ *pbresource.Type, tenancyStr string, name, port string) *pbmesh.ParentReference { - return &pbmesh.ParentReference{ - Ref: newRefWithTenancy(typ, tenancyStr, name), - Port: port, - } -} diff --git a/internal/mesh/proxy-snapshot/proxy_snapshot.go b/internal/mesh/proxy-snapshot/proxy_snapshot.go deleted file mode 100644 index e1c972c08a4e..000000000000 --- a/internal/mesh/proxy-snapshot/proxy_snapshot.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxysnapshot - -import "github.com/hashicorp/consul/acl" - -// ProxySnapshot is an abstraction that allows interchangeability between -// Catalog V1 ConfigSnapshot and Catalog V2 ProxyState. -type ProxySnapshot interface { - AllowEmptyListeners() bool - AllowEmptyRoutes() bool - AllowEmptyClusters() bool - Authorize(authz acl.Authorizer) error - LoggerName() string -} - -// CancelFunc is a type for a returned function that can be called to cancel a -// watch. -type CancelFunc func() diff --git a/internal/mesh/proxy-tracker/mock_SessionLimiter.go b/internal/mesh/proxy-tracker/mock_SessionLimiter.go deleted file mode 100644 index 32375dbdc386..000000000000 --- a/internal/mesh/proxy-tracker/mock_SessionLimiter.go +++ /dev/null @@ -1,53 +0,0 @@ -// Code generated by mockery v2.33.1. DO NOT EDIT. - -package proxytracker - -import ( - limiter "github.com/hashicorp/consul/agent/grpc-external/limiter" - mock "github.com/stretchr/testify/mock" -) - -// MockSessionLimiter is an autogenerated mock type for the SessionLimiter type -type MockSessionLimiter struct { - mock.Mock -} - -// BeginSession provides a mock function with given fields: -func (_m *MockSessionLimiter) BeginSession() (limiter.Session, error) { - ret := _m.Called() - - var r0 limiter.Session - var r1 error - if rf, ok := ret.Get(0).(func() (limiter.Session, error)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() limiter.Session); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(limiter.Session) - } - } - - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewMockSessionLimiter creates a new instance of MockSessionLimiter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewMockSessionLimiter(t interface { - mock.TestingT - Cleanup(func()) -}) *MockSessionLimiter { - mock := &MockSessionLimiter{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/internal/mesh/proxy-tracker/proxy_state_exports.go b/internal/mesh/proxy-tracker/proxy_state_exports.go deleted file mode 100644 index cdc6d6d84580..000000000000 --- a/internal/mesh/proxy-tracker/proxy_state_exports.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxytracker - -import ( - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" -) - -// ProxyState is an implementation of the ProxySnapshot interface for pbmesh.ProxyState. -// It is a simple wrapper around pbmesh.ProxyState so that it can be used -// by the ProxyWatcher interface in XDS processing. This struct is necessary -// because pbmesh.ProxyState is a proto definition and there were complications -// adding these functions directly to that proto definition. -type ProxyState struct { - *pbmesh.ProxyState -} - -// TODO(proxystate): need to modify ProxyState to carry a type/kind (connect proxy, mesh gateway, etc.) -// for sidecar proxies, all Allow* functions -// should return false, but for different gateways we'd need to add it to IR. - -func (p *ProxyState) AllowEmptyListeners() bool { - return false -} - -func (p *ProxyState) AllowEmptyRoutes() bool { - return false -} - -func (p *ProxyState) AllowEmptyClusters() bool { - return false -} - -func (p *ProxyState) Authorize(authz acl.Authorizer) error { - // authorize for mesh proxies. - // TODO(proxystate): implement differently for gateways - allow := authz.ToAllowAuthorizer() - if err := allow.IdentityWriteAllowed(p.Identity.Name, resource.AuthorizerContext(p.Identity.Tenancy)); err != nil { - return err - } - - return nil -} - -func (p *ProxyState) LoggerName() string { - return "" -} diff --git a/internal/mesh/proxy-tracker/proxy_state_exports_test.go b/internal/mesh/proxy-tracker/proxy_state_exports_test.go deleted file mode 100644 index 18d15fb53dad..000000000000 --- a/internal/mesh/proxy-tracker/proxy_state_exports_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxytracker - -import ( - "github.com/hashicorp/consul/acl" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "strings" - "testing" -) - -func TestProxyState_Authorize(t *testing.T) { - testIdentity := &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "mesh", - GroupVersion: "v1alpha1", - Kind: "Identity", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: "test-identity", - } - - type testCase struct { - description string - proxyState *ProxyState - configureAuthorizer func(authorizer *acl.MockAuthorizer) - expectedErrorMessage string - } - testsCases := []testCase{ - { - description: "ProxyState - if identity write is allowed for the workload then allow.", - proxyState: &ProxyState{ - ProxyState: &pbmesh.ProxyState{ - Identity: testIdentity, - }, - }, - expectedErrorMessage: "", - configureAuthorizer: func(authz *acl.MockAuthorizer) { - authz.On("IdentityWrite", testIdentity.Name, mock.Anything).Return(acl.Allow) - }, - }, - { - description: "ProxyState - if identity write is not allowed for the workload then deny.", - proxyState: &ProxyState{ - ProxyState: &pbmesh.ProxyState{ - Identity: testIdentity, - }, - }, - expectedErrorMessage: "Permission denied: token with AccessorID '' lacks permission 'identity:write' on \"test-identity\"", - configureAuthorizer: func(authz *acl.MockAuthorizer) { - authz.On("IdentityWrite", testIdentity.Name, mock.Anything).Return(acl.Deny) - }, - }, - } - for _, tc := range testsCases { - t.Run(tc.description, func(t *testing.T) { - authz := &acl.MockAuthorizer{} - authz.On("ToAllow").Return(acl.AllowAuthorizer{Authorizer: authz}) - tc.configureAuthorizer(authz) - err := tc.proxyState.Authorize(authz) - errMsg := "" - if err != nil { - errMsg = err.Error() - } - // using contains because Enterprise tests append the parition and namespace - // information to the message. - require.True(t, strings.Contains(errMsg, tc.expectedErrorMessage)) - }) - } -} diff --git a/internal/mesh/proxy-tracker/proxy_tracker.go b/internal/mesh/proxy-tracker/proxy_tracker.go deleted file mode 100644 index d9dae03a13cd..000000000000 --- a/internal/mesh/proxy-tracker/proxy_tracker.go +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxytracker - -import ( - "errors" - "fmt" - "sync" - - "github.com/hashicorp/go-hclog" - - "github.com/hashicorp/consul/agent/grpc-external/limiter" - "github.com/hashicorp/consul/internal/controller" - proxysnapshot "github.com/hashicorp/consul/internal/mesh/proxy-snapshot" - "github.com/hashicorp/consul/internal/resource" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -// ProxyConnection implements the queue.ItemType interface so that it can be used in a controller.Event. -// It is sent on the newProxyConnectionCh channel. -// TODO(ProxyState): needs to support tenancy in the future. -type ProxyConnection struct { - ProxyID *pbresource.ID -} - -// Key is current resourceID.Name. -func (e *ProxyConnection) Key() string { - return e.ProxyID.GetName() -} - -// proxyWatchData is a handle on all of the relevant bits that is created by calling Watch(). -// It is meant to be stored in the proxies cache by proxyID so that watches can be notified -// when the ProxyState for that proxyID has changed. -type proxyWatchData struct { - // notifyCh is the channel that the watcher receives updates from ProxyTracker. - notifyCh chan proxysnapshot.ProxySnapshot - // state is the current/last updated ProxyState for a given proxy. - state proxysnapshot.ProxySnapshot - // token is the ACL token provided by the watcher. - token string - // nodeName is the node where the given proxy resides. - nodeName string -} - -type ProxyTrackerConfig struct { - // logger will be used to write log messages. - Logger hclog.Logger - - // sessionLimiter is used to enforce xDS concurrency limits. - SessionLimiter SessionLimiter -} - -// ProxyTracker implements the Watcher and Updater interfaces. The Watcher is used by the xds server to add a new proxy -// to this server, and get back a channel for updates. The Updater is used by the ProxyState controller running on the -// server to push ProxyState updates to the notify channel. -type ProxyTracker struct { - config ProxyTrackerConfig - // proxies is a cache of the proxies connected to this server and configuration information for each one. - proxies map[resource.ReferenceKey]*proxyWatchData - // newProxyConnectionCh is the channel that the "updater" retains to receive messages from ProxyTracker that a new - // proxy has connected to ProxyTracker and a signal the "updater" should call PushChanges with a new state. - newProxyConnectionCh chan controller.Event - // shutdownCh is a channel that closes when ProxyTracker is shutdown. ShutdownChannel is never written to, only closed to - // indicate a shutdown has been initiated. - shutdownCh chan struct{} - // mu is a mutex that is used internally for locking when reading and modifying ProxyTracker state, namely the proxies map. - mu sync.Mutex -} - -// NewProxyTracker returns a ProxyTracker instance given a configuration. -func NewProxyTracker(cfg ProxyTrackerConfig) *ProxyTracker { - return &ProxyTracker{ - config: cfg, - proxies: make(map[resource.ReferenceKey]*proxyWatchData), - // buffering this channel since ProxyTracker will be registering watches for all proxies. - // using the buffer will limit errors related to controller and the proxy are both running - // but the controllers listening function is not blocking on the particular receive line. - // This channel is meant to error when the controller is "not ready" which means up and alive. - // This buffer will try to reduce false negatives and limit unnecessary erroring. - newProxyConnectionCh: make(chan controller.Event, 1000), - shutdownCh: make(chan struct{}), - } -} - -// Watch connects a proxy with ProxyTracker and returns the consumer a channel to receive updates, -// a channel to notify of xDS terminated session, and a cancel function to cancel the watch. -func (pt *ProxyTracker) Watch(proxyID *pbresource.ID, - nodeName string, token string) (<-chan proxysnapshot.ProxySnapshot, - limiter.SessionTerminatedChan, proxysnapshot.CancelFunc, error) { - pt.config.Logger.Trace("watch initiated", "proxyID", proxyID, "nodeName", nodeName) - if err := pt.validateWatchArgs(proxyID, nodeName); err != nil { - pt.config.Logger.Error("args failed validation", err) - return nil, nil, nil, err - } - // Begin a session with the xDS session concurrency limiter. - // - // See: https://github.com/hashicorp/consul/issues/15753 - session, err := pt.config.SessionLimiter.BeginSession() - if err != nil { - pt.config.Logger.Error("failed to begin session with xDS session concurrency limiter", err) - return nil, nil, nil, err - } - - // This buffering is crucial otherwise we'd block immediately trying to - // deliver the current snapshot below if we already have one. - - proxyStateChan := make(chan proxysnapshot.ProxySnapshot, 1) - watchData := &proxyWatchData{ - notifyCh: proxyStateChan, - state: nil, - token: token, - nodeName: nodeName, - } - - proxyReferenceKey := resource.NewReferenceKey(proxyID) - cancel := func() { - pt.mu.Lock() - defer pt.mu.Unlock() - pt.cancelWatchLocked(proxyReferenceKey, proxyStateChan, session) - } - - pt.mu.Lock() - defer pt.mu.Unlock() - - pt.proxies[proxyReferenceKey] = watchData - - //Send an event to the controller - err = pt.notifyNewProxyChannel(proxyID) - if err != nil { - pt.config.Logger.Error("failed to notify controller of new proxy connection", err) - pt.cancelWatchLocked(proxyReferenceKey, watchData.notifyCh, session) - return nil, nil, nil, err - } - pt.config.Logger.Trace("controller notified of watch created", "proxyID", proxyID, "nodeName", nodeName) - - return proxyStateChan, session.Terminated(), cancel, nil -} - -// notifyNewProxyChannel attempts to send a message to newProxyConnectionCh and will return an error if there's no receiver. -// This will handle conditions where a proxy is connected but there's no controller for some reason to receive the event. -// This will error back to the proxy's Watch call and will cause the proxy call Watch again to retry connection until the controller -// is available. -func (pt *ProxyTracker) notifyNewProxyChannel(proxyID *pbresource.ID) error { - controllerEvent := controller.Event{ - Obj: &ProxyConnection{ - ProxyID: proxyID, - }, - } - select { - case pt.newProxyConnectionCh <- controllerEvent: - return nil - // using default here to return errors is only safe when we have a large buffer. - // the receiver is on a loop to read from the channel. If the sequence of - // sender blocks on the channel and then the receiver blocks on the channel is not - // aligned, then extraneous errors could be returned to the proxy that are just - // false negatives and the controller could be up and healthy. - default: - return fmt.Errorf("failed to notify the controller of the proxy connecting") - } -} - -// cancelWatchLocked does the following: -// - deletes the key from the proxies array. -// - ends the session with xDS session limiter. -// - closes the proxy state channel assigned to the proxy. -// This function assumes the state lock is already held. -func (pt *ProxyTracker) cancelWatchLocked(proxyReferenceKey resource.ReferenceKey, proxyStateChan chan proxysnapshot.ProxySnapshot, session limiter.Session) { - delete(pt.proxies, proxyReferenceKey) - session.End() - close(proxyStateChan) - pt.config.Logger.Trace("watch cancelled", "proxyReferenceKey", proxyReferenceKey) -} - -// validateWatchArgs checks the proxyIDand nodeName passed to Watch -// and returns an error if the args are not properly constructed. -func (pt *ProxyTracker) validateWatchArgs(proxyID *pbresource.ID, - nodeName string) error { - if proxyID == nil { - return errors.New("proxyID is required") - } else if proxyID.GetType().GetKind() != pbmesh.ProxyStateTemplateType.Kind { - return fmt.Errorf("proxyID must be a %s", pbmesh.ProxyStateTemplateType.GetKind()) - } else if nodeName == "" { - return errors.New("nodeName is required") - } - - return nil -} - -// PushChange allows pushing a computed ProxyState to xds for xds resource generation to send to a proxy. -func (pt *ProxyTracker) PushChange(proxyID *pbresource.ID, proxyState proxysnapshot.ProxySnapshot) error { - pt.config.Logger.Trace("push change called for proxy", "proxyID", proxyID) - proxyReferenceKey := resource.NewReferenceKey(proxyID) - pt.mu.Lock() - defer pt.mu.Unlock() - if data, ok := pt.proxies[proxyReferenceKey]; ok { - data.state = proxyState - - pt.deliverLatest(proxyID, proxyState, data.notifyCh) - } else { - return errors.New("proxyState change could not be sent because proxy is not connected") - } - - return nil -} - -func (pt *ProxyTracker) deliverLatest(proxyID *pbresource.ID, proxyState proxysnapshot.ProxySnapshot, ch chan proxysnapshot.ProxySnapshot) { - pt.config.Logger.Trace("delivering latest proxy snapshot to proxy", "proxyID", proxyID) - // Send if chan is empty - select { - case ch <- proxyState: - return - default: - } - - // Not empty, drain the chan of older snapshots and redeliver. For now we only - // use 1-buffered chans but this will still work if we change that later. -OUTER: - for { - select { - case <-ch: - continue - default: - break OUTER - } - } - - // Now send again - select { - case ch <- proxyState: - return - default: - // This should not be possible since we should be the only sender, enforced - // by m.mu but error and drop the update rather than panic. - pt.config.Logger.Error("failed to deliver proxyState to proxy", - "proxy", proxyID.String(), - ) - } -} - -// EventChannel returns an event channel that sends controller events when a proxy connects to a server. -func (pt *ProxyTracker) EventChannel() chan controller.Event { - return pt.newProxyConnectionCh -} - -// ShutdownChannel returns a channel that closes when ProxyTracker is shutdown. ShutdownChannel is never written to, only closed to -// indicate a shutdown has been initiated. -func (pt *ProxyTracker) ShutdownChannel() chan struct{} { - return pt.shutdownCh -} - -// ProxyConnectedToServer returns whether this id is connected to this server. -func (pt *ProxyTracker) ProxyConnectedToServer(proxyID *pbresource.ID) (string, bool) { - pt.mu.Lock() - defer pt.mu.Unlock() - proxyReferenceKey := resource.NewReferenceKey(proxyID) - proxyData, ok := pt.proxies[proxyReferenceKey] - if ok { - return proxyData.token, ok - } - return "", ok -} - -// Shutdown removes all state and close all channels. -func (pt *ProxyTracker) Shutdown() { - pt.config.Logger.Info("proxy tracker shutdown initiated") - pt.mu.Lock() - defer pt.mu.Unlock() - - // Close all current watchers first - for proxyID, watchData := range pt.proxies { - close(watchData.notifyCh) - delete(pt.proxies, proxyID) - } - - close(pt.newProxyConnectionCh) - close(pt.shutdownCh) -} - -//go:generate mockery --name SessionLimiter --inpackage -type SessionLimiter interface { - BeginSession() (limiter.Session, error) -} diff --git a/internal/mesh/proxy-tracker/proxy_tracker_test.go b/internal/mesh/proxy-tracker/proxy_tracker_test.go deleted file mode 100644 index d6c1fc1ce5e0..000000000000 --- a/internal/mesh/proxy-tracker/proxy_tracker_test.go +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package proxytracker - -import ( - "errors" - "fmt" - "testing" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/agent/grpc-external/limiter" - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestProxyTracker_Watch(t *testing.T) { - resourceID := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test").ID() - proxyReferenceKey := resource.NewReferenceKey(resourceID) - lim := NewMockSessionLimiter(t) - session1 := newMockSession(t) - session1TermCh := make(limiter.SessionTerminatedChan) - session1.On("Terminated").Return(session1TermCh) - session1.On("End").Return() - lim.On("BeginSession").Return(session1, nil) - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - // Watch() - proxyStateChan, _, cancelFunc, err := pt.Watch(resourceID, "node 1", "token") - require.NoError(t, err) - - // ensure New Proxy Connection message is sent - newProxyMsg := <-pt.EventChannel() - require.Equal(t, resourceID.Name, newProxyMsg.Obj.Key()) - - // watchData is stored in the proxies array with a nil state - watchData, ok := pt.proxies[proxyReferenceKey] - require.True(t, ok) - require.NotNil(t, watchData) - require.Nil(t, watchData.state) - - // calling cancelFunc does the following: - // - closes the proxy state channel - // - and removes the map entry for the proxy - // - session is ended - cancelFunc() - - // read channel to see if there is data and it is open. - receivedState, channelOpen := <-proxyStateChan - require.Nil(t, receivedState) - require.False(t, channelOpen) - - // key is removed from proxies array - _, ok = pt.proxies[proxyReferenceKey] - require.False(t, ok) - - // session ended - session1.AssertCalled(t, "Terminated") - session1.AssertCalled(t, "End") -} - -func TestProxyTracker_Watch_ErrorConsumerNotReady(t *testing.T) { - resourceID := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test").ID() - proxyReferenceKey := resource.NewReferenceKey(resourceID) - lim := NewMockSessionLimiter(t) - session1 := newMockSession(t) - session1.On("End").Return() - lim.On("BeginSession").Return(session1, nil) - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - //fill up buffered channel while the consumer is not ready to simulate the error - for i := 0; i < 1000; i++ { - event := controller.Event{Obj: &ProxyConnection{ProxyID: resourcetest.Resource(pbmesh.ProxyStateTemplateType, fmt.Sprintf("test%d", i)).ID()}} - pt.newProxyConnectionCh <- event - } - - // Watch() - proxyStateChan, sessionTerminatedCh, cancelFunc, err := pt.Watch(resourceID, "node 1", "token") - require.Nil(t, cancelFunc) - require.Nil(t, proxyStateChan) - require.Nil(t, sessionTerminatedCh) - require.Error(t, err) - require.Equal(t, "failed to notify the controller of the proxy connecting", err.Error()) - - // it is not stored in the proxies array - watchData, ok := pt.proxies[proxyReferenceKey] - require.False(t, ok) - require.Nil(t, watchData) -} - -func TestProxyTracker_Watch_ArgValidationErrors(t *testing.T) { - type testcase struct { - description string - proxyID *pbresource.ID - nodeName string - token string - expectedError error - } - testcases := []*testcase{ - { - description: "Empty proxyID", - proxyID: nil, - nodeName: "something", - token: "something", - expectedError: errors.New("proxyID is required"), - }, - { - description: "Empty nodeName", - proxyID: resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test").ID(), - nodeName: "", - token: "something", - expectedError: errors.New("nodeName is required"), - }, - { - description: "resource is not ProxyStateTemplate", - proxyID: resourcetest.Resource(pbmesh.ProxyConfigurationType, "test").ID(), - nodeName: "something", - token: "something else", - expectedError: errors.New("proxyID must be a ProxyStateTemplate"), - }, - } - for _, tc := range testcases { - lim := NewMockSessionLimiter(t) - lim.On("BeginSession").Return(nil, nil).Maybe() - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - // Watch() - proxyStateChan, sessionTerminateCh, cancelFunc, err := pt.Watch(tc.proxyID, tc.nodeName, tc.token) - require.Error(t, err) - require.Equal(t, tc.expectedError, err) - require.Nil(t, proxyStateChan) - require.Nil(t, sessionTerminateCh) - require.Nil(t, cancelFunc) - } -} - -func TestProxyTracker_Watch_SessionLimiterError(t *testing.T) { - resourceID := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test").ID() - lim := NewMockSessionLimiter(t) - lim.On("BeginSession").Return(nil, errors.New("kaboom")) - logger := testutil.Logger(t) - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - // Watch() - proxyStateChan, sessionTerminateCh, cancelFunc, err := pt.Watch(resourceID, "node 1", "token") - require.Error(t, err) - require.Equal(t, "kaboom", err.Error()) - require.Nil(t, proxyStateChan) - require.Nil(t, sessionTerminateCh) - require.Nil(t, cancelFunc) -} - -func TestProxyTracker_PushChange(t *testing.T) { - resourceID := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test").ID() - proxyReferenceKey := resource.NewReferenceKey(resourceID) - lim := NewMockSessionLimiter(t) - session1 := newMockSession(t) - session1TermCh := make(limiter.SessionTerminatedChan) - session1.On("Terminated").Return(session1TermCh) - lim.On("BeginSession").Return(session1, nil) - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - // Watch() - proxyStateChan, _, _, err := pt.Watch(resourceID, "node 1", "token") - require.NoError(t, err) - - // PushChange - proxyState := &ProxyState{ProxyState: &pbmesh.ProxyState{}} - - // using a goroutine so that the channel and main test thread do not cause - // blocking issues with each other - go func() { - err = pt.PushChange(resourceID, proxyState) - require.NoError(t, err) - }() - - // channel receives a copy - receivedState, channelOpen := <-proxyStateChan - require.True(t, channelOpen) - require.Equal(t, proxyState, receivedState) - - // it is stored in the proxies array - watchData, ok := pt.proxies[proxyReferenceKey] - require.True(t, ok) - require.Equal(t, proxyState, watchData.state) -} - -func TestProxyTracker_PushChanges_ErrorProxyNotConnected(t *testing.T) { - resourceID := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test").ID() - lim := NewMockSessionLimiter(t) - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - // PushChange - proxyState := &ProxyState{ProxyState: &pbmesh.ProxyState{}} - - err := pt.PushChange(resourceID, proxyState) - require.Error(t, err) - require.Equal(t, "proxyState change could not be sent because proxy is not connected", err.Error()) -} - -func TestProxyTracker_ProxyConnectedToServer(t *testing.T) { - type testcase struct { - name string - shouldExist bool - preProcessingFunc func(pt *ProxyTracker, resourceID *pbresource.ID, limiter *MockSessionLimiter, session *mockSession, channel limiter.SessionTerminatedChan) - } - testsCases := []*testcase{ - { - name: "Resource that has not been sent through Watch() should return false", - shouldExist: false, - preProcessingFunc: func(pt *ProxyTracker, resourceID *pbresource.ID, limiter *MockSessionLimiter, session *mockSession, channel limiter.SessionTerminatedChan) { - session.On("Terminated").Return(channel).Maybe() - session.On("End").Return().Maybe() - limiter.On("BeginSession").Return(session, nil).Maybe() - }, - }, - { - name: "Resource used that is already passed in through Watch() should return true", - shouldExist: true, - preProcessingFunc: func(pt *ProxyTracker, resourceID *pbresource.ID, limiter *MockSessionLimiter, session *mockSession, channel limiter.SessionTerminatedChan) { - session.On("Terminated").Return(channel).Maybe() - session.On("End").Return().Maybe() - limiter.On("BeginSession").Return(session, nil) - _, _, _, _ = pt.Watch(resourceID, "node 1", "token") - }, - }, - } - - for _, tc := range testsCases { - lim := NewMockSessionLimiter(t) - session1 := newMockSession(t) - session1TermCh := make(limiter.SessionTerminatedChan) - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - resourceID := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test").ID() - tc.preProcessingFunc(pt, resourceID, lim, session1, session1TermCh) - _, ok := pt.ProxyConnectedToServer(resourceID) - require.Equal(t, tc.shouldExist, ok) - } -} - -func TestProxyTracker_Shutdown(t *testing.T) { - resourceID := resourcetest.Resource(pbmesh.ProxyStateTemplateType, "test").ID() - proxyReferenceKey := resource.NewReferenceKey(resourceID) - lim := NewMockSessionLimiter(t) - session1 := newMockSession(t) - session1TermCh := make(limiter.SessionTerminatedChan) - session1.On("Terminated").Return(session1TermCh) - session1.On("End").Return().Maybe() - lim.On("BeginSession").Return(session1, nil) - logger := testutil.Logger(t) - - pt := NewProxyTracker(ProxyTrackerConfig{ - Logger: logger, - SessionLimiter: lim, - }) - - // Watch() - proxyStateChan, _, _, err := pt.Watch(resourceID, "node 1", "token") - require.NoError(t, err) - - pt.Shutdown() - - // proxy channels are all disconnected and proxy is removed from proxies map - receivedState, channelOpen := <-proxyStateChan - require.Nil(t, receivedState) - require.False(t, channelOpen) - _, ok := pt.proxies[proxyReferenceKey] - require.False(t, ok) - - // shutdownCh is closed - select { - case <-pt.ShutdownChannel(): - default: - t.Fatalf("shutdown channel should be closed") - } - // newProxyConnectionCh is closed - select { - case <-pt.EventChannel(): - default: - t.Fatalf("shutdown channel should be closed") - } -} - -type mockSession struct { - mock.Mock -} - -func newMockSession(t *testing.T) *mockSession { - m := &mockSession{} - m.Mock.Test(t) - - t.Cleanup(func() { m.AssertExpectations(t) }) - - return m -} - -func (m *mockSession) End() { m.Called() } - -func (m *mockSession) Terminated() limiter.SessionTerminatedChan { - return m.Called().Get(0).(limiter.SessionTerminatedChan) -} diff --git a/internal/multicluster/exports.go b/internal/multicluster/exports.go index fcf5873d81ce..7d84cdb5e972 100644 --- a/internal/multicluster/exports.go +++ b/internal/multicluster/exports.go @@ -4,19 +4,27 @@ package multicluster import ( + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/multicluster/internal/controllers" + "github.com/hashicorp/consul/internal/multicluster/internal/controllers/v1compat" "github.com/hashicorp/consul/internal/multicluster/internal/types" "github.com/hashicorp/consul/internal/resource" ) -var ( - // API Group Information - APIGroup = types.GroupName - VersionV2Beta1 = types.VersionV2Beta1 - CurrentVersion = types.CurrentVersion -) - // RegisterTypes adds all resource types within the "multicluster" API group // to the given type registry func RegisterTypes(r resource.Registry) { types.Register(r) } + +type CompatControllerDependencies = controllers.CompatDependencies + +func DefaultCompatControllerDependencies(ac v1compat.AggregatedConfig) CompatControllerDependencies { + return CompatControllerDependencies{ + ConfigEntryExports: ac, + } +} + +func RegisterCompatControllers(mgr *controller.Manager, deps CompatControllerDependencies) { + controllers.RegisterCompat(mgr, deps) +} diff --git a/internal/multicluster/internal/controllers/register.go b/internal/multicluster/internal/controllers/register.go new file mode 100644 index 000000000000..3470b275bc94 --- /dev/null +++ b/internal/multicluster/internal/controllers/register.go @@ -0,0 +1,17 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package controllers + +import ( + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/multicluster/internal/controllers/v1compat" +) + +type CompatDependencies struct { + ConfigEntryExports v1compat.AggregatedConfig +} + +func RegisterCompat(mgr *controller.Manager, deps CompatDependencies) { + mgr.Register(v1compat.Controller(deps.ConfigEntryExports)) +} diff --git a/internal/multicluster/internal/controllers/v1compat/controller.go b/internal/multicluster/internal/controllers/v1compat/controller.go new file mode 100644 index 000000000000..9f6e98c76bfb --- /dev/null +++ b/internal/multicluster/internal/controllers/v1compat/controller.go @@ -0,0 +1,419 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package v1compat + +import ( + "context" + "fmt" + "slices" + "sort" + + "golang.org/x/exp/maps" + + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/controller/cache" + "github.com/hashicorp/consul/internal/controller/cache/index" + "github.com/hashicorp/consul/internal/multicluster/internal/types" + "github.com/hashicorp/consul/internal/resource" + pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +const ( + ControllerName = "consul.io/exported-services-v1-compat" + controllerMetaKey = "managed-by-controller" +) + +//go:generate mockery --name AggregatedConfig --inpackage --with-expecter --filename mock_AggregatedConfig.go +type AggregatedConfig interface { + Start(context.Context) + GetExportedServicesConfigEntry(context.Context, string, *acl.EnterpriseMeta) (*structs.ExportedServicesConfigEntry, error) + WriteExportedServicesConfigEntry(context.Context, *structs.ExportedServicesConfigEntry) error + DeleteExportedServicesConfigEntry(context.Context, string, *acl.EnterpriseMeta) error + EventChannel() chan controller.Event +} + +func mapExportedServices(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + return []controller.Request{ + { + ID: &pbresource.ID{ + Type: pbmulticluster.ComputedExportedServicesType, + Tenancy: &pbresource.Tenancy{ + Partition: res.Id.Tenancy.Partition, + }, + Name: types.ComputedExportedServicesName, + }, + }, + }, nil +} + +func mapConfigEntryEvents(ctx context.Context, rt controller.Runtime, event controller.Event) ([]controller.Request, error) { + partition := event.Obj.Key() + + return []controller.Request{ + { + ID: &pbresource.ID{ + Type: pbmulticluster.ComputedExportedServicesType, + Tenancy: &pbresource.Tenancy{ + Partition: partition, + }, + Name: types.ComputedExportedServicesName, + }, + }, + }, nil +} + +func Controller(config AggregatedConfig) *controller.Controller { + return controller.NewController(ControllerName, pbmulticluster.ComputedExportedServicesType). + WithNotifyStart(func(ctx context.Context, r controller.Runtime) { + go config.Start(ctx) + }). + WithWatch(pbmulticluster.PartitionExportedServicesType, mapExportedServices). + WithWatch(pbmulticluster.NamespaceExportedServicesType, mapExportedServices). + WithWatch(pbmulticluster.ExportedServicesType, mapExportedServices). + WithCustomWatch(&controller.Source{Source: config.EventChannel()}, mapConfigEntryEvents). + WithReconciler(&reconciler{config: config}) +} + +type reconciler struct { + config AggregatedConfig +} + +// Reconcile will reconcile one ComputedExportedServices in response to some event. +func (r *reconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { + rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", ControllerName) + + entMeta := acl.DefaultEnterpriseMeta() + entMeta.OverridePartition(req.ID.Tenancy.Partition) + existing, err := r.config.GetExportedServicesConfigEntry(ctx, req.ID.Tenancy.Partition, entMeta) + if err != nil { + // When we can't read the existing exported-services we purposely allow + // reconciler to continue so we can still write a new one + rt.Logger.Warn("error getting exported service config entry but continuing reconcile", "error", err) + } + + if existing != nil && existing.Meta["managed-by-controller"] != ControllerName { + // in order to not cause an outage we need to ensure that the user has replicated all + // of their exports to v2 resources first and then setting the meta key on the existing + // config entry to allow this controller to overwrite what the user previously had. + rt.Logger.Info("existing exported-services config entry is not managed with v2 resources. Add a metadata value of %q with a value of %q to opt-in to controller management of that config entry", controllerMetaKey, ControllerName) + return nil + } + + newCfg := &structs.ExportedServicesConfigEntry{ + // v1 exported-services config entries must have a Name that is the partitions name + Name: req.ID.Tenancy.Partition, + Meta: map[string]string{ + controllerMetaKey: ControllerName, + }, + EnterpriseMeta: *entMeta, + } + + partitionExports, err := cache.ListDecoded[*pbmulticluster.PartitionExportedServices]( + rt.Cache, + pbmulticluster.PartitionExportedServicesType, + "id", + &pbresource.ID{ + Type: pbmulticluster.PartitionExportedServicesType, + Tenancy: req.ID.Tenancy, + }, + index.IndexQueryOptions{Prefix: true}, + ) + if err != nil { + rt.Logger.Error("error retrieving partition exported services", "error", err) + return err + } + + namespaceExports, err := cache.ListDecoded[*pbmulticluster.NamespaceExportedServices]( + rt.Cache, + pbmulticluster.NamespaceExportedServicesType, + "id", + &pbresource.ID{ + Type: pbmulticluster.NamespaceExportedServicesType, + Tenancy: req.ID.Tenancy, + }, + index.IndexQueryOptions{Prefix: true}, + ) + if err != nil { + rt.Logger.Error("error retrieving namespace exported services", "error", err) + return err + } + + serviceExports, err := cache.ListDecoded[*pbmulticluster.ExportedServices]( + rt.Cache, + pbmulticluster.ExportedServicesType, + "id", + &pbresource.ID{ + Type: pbmulticluster.ExportedServicesType, + Tenancy: req.ID.Tenancy, + }, + index.IndexQueryOptions{Prefix: true}, + ) + if err != nil { + rt.Logger.Error("error retrieving exported services", "error", err) + return err + } + + if len(partitionExports) == 0 && len(namespaceExports) == 0 && len(serviceExports) == 0 { + if existing == nil { + return nil + } + + if err := r.config.DeleteExportedServicesConfigEntry(ctx, req.ID.Tenancy.Partition, entMeta); err != nil { + rt.Logger.Error("error deleting exported services config entry", "error", err) + return err + } + return nil + } + + exports := newExportTracker() + + for _, partitionExport := range partitionExports { + exports.trackPartitionConsumer(partitionExport.Data.Consumers) + } + + for _, namespaceExport := range namespaceExports { + exports.trackNamespaceConsumers(namespaceExport.Id.Tenancy.Namespace, namespaceExport.Data.Consumers) + } + + for _, serviceExport := range serviceExports { + for _, svc := range serviceExport.Data.Services { + svcId := &pbresource.ID{ + Type: fakeServiceType, + Tenancy: serviceExport.Id.Tenancy, + Name: svc, + } + + exports.trackExportedServices(svcId, serviceExport.Data.Consumers) + } + } + + newCfg.Services = exports.allExports() + + if existing != nil && configEntryEquivalent(existing, newCfg) { + rt.Logger.Trace("managed exported-services config entry is already up to date") + return nil + } + + if err := r.config.WriteExportedServicesConfigEntry(ctx, newCfg); err != nil { + rt.Logger.Error("error writing exported services config entry", "error", err) + return err + } + + rt.Logger.Debug("Updated exported services config entry") + return nil +} + +type exportTracker struct { + partitions *exportConsumers + namespaces map[string]*exportConsumers + services map[resource.ReferenceKey]*exportConsumers +} + +type exportConsumers struct { + partitions map[string]struct{} + peers map[string]struct{} + samenessGroups map[string]struct{} +} + +func newExportConsumers() *exportConsumers { + return &exportConsumers{ + partitions: make(map[string]struct{}), + peers: make(map[string]struct{}), + samenessGroups: make(map[string]struct{}), + } +} + +func (c *exportConsumers) addConsumers(consumers []*pbmulticluster.ExportedServicesConsumer) { + for _, consumer := range consumers { + switch v := consumer.ConsumerTenancy.(type) { + case *pbmulticluster.ExportedServicesConsumer_Peer: + c.peers[v.Peer] = struct{}{} + case *pbmulticluster.ExportedServicesConsumer_Partition: + c.partitions[v.Partition] = struct{}{} + case *pbmulticluster.ExportedServicesConsumer_SamenessGroup: + c.samenessGroups[v.SamenessGroup] = struct{}{} + default: + panic(fmt.Errorf("Unknown exported service consumer type: %T", v)) + } + } +} + +func (c *exportConsumers) configEntryConsumers() []structs.ServiceConsumer { + consumers := make([]structs.ServiceConsumer, 0, len(c.partitions)+len(c.peers)+len(c.samenessGroups)) + + partitions := maps.Keys(c.partitions) + slices.Sort(partitions) + for _, consumer := range partitions { + consumers = append(consumers, structs.ServiceConsumer{ + Partition: consumer, + }) + } + + peers := maps.Keys(c.peers) + slices.Sort(peers) + for _, consumer := range peers { + consumers = append(consumers, structs.ServiceConsumer{ + Peer: consumer, + }) + } + + samenessGroups := maps.Keys(c.samenessGroups) + slices.Sort(samenessGroups) + for _, consumer := range samenessGroups { + consumers = append(consumers, structs.ServiceConsumer{ + SamenessGroup: consumer, + }) + } + + return consumers +} + +func newExportTracker() *exportTracker { + return &exportTracker{ + partitions: newExportConsumers(), + namespaces: make(map[string]*exportConsumers), + services: make(map[resource.ReferenceKey]*exportConsumers), + } +} + +func (t *exportTracker) trackPartitionConsumer(consumers []*pbmulticluster.ExportedServicesConsumer) { + t.partitions.addConsumers(consumers) +} + +func (t *exportTracker) trackNamespaceConsumers(namespace string, consumers []*pbmulticluster.ExportedServicesConsumer) { + c, ok := t.namespaces[namespace] + if !ok { + c = newExportConsumers() + t.namespaces[namespace] = c + } + + c.addConsumers(consumers) +} + +func (t *exportTracker) trackExportedServices(svcID *pbresource.ID, consumers []*pbmulticluster.ExportedServicesConsumer) { + key := resource.NewReferenceKey(svcID) + + c, ok := t.services[key] + if !ok { + c = newExportConsumers() + t.services[key] = c + } + + c.addConsumers(consumers) +} + +func (t *exportTracker) allExports() []structs.ExportedService { + var exports []structs.ExportedService + + partitionConsumers := t.partitions.configEntryConsumers() + if len(partitionConsumers) > 0 { + exports = append(exports, structs.ExportedService{ + Name: "*", + Namespace: "*", + Consumers: partitionConsumers, + }) + } + + namespaces := maps.Keys(t.namespaces) + slices.Sort(namespaces) + for _, ns := range namespaces { + exports = append(exports, structs.ExportedService{ + Name: "*", + Namespace: ns, + Consumers: t.namespaces[ns].configEntryConsumers(), + }) + } + + services := maps.Keys(t.services) + sort.Slice(services, func(i, j int) bool { + // the partitions must already be equal because we are only + // looking at resource exports for a single partition. + + if services[i].Namespace < services[j].Namespace { + return false + } else if services[i].Namespace > services[j].Namespace { + return true + } + + if services[i].Name < services[j].Name { + return false + } else if services[i].Name > services[j].Name { + return true + } + + return false + }) + for _, svcKey := range services { + exports = append(exports, structs.ExportedService{ + Name: svcKey.Name, + Namespace: svcKey.Namespace, + Consumers: t.services[svcKey].configEntryConsumers(), + }) + } + + return exports +} + +func configEntryEquivalent(a, b *structs.ExportedServicesConfigEntry) bool { + if a.Name != b.Name { + return false + } + + if len(a.Services) != len(b.Services) { + return false + } + + for i := 0; i < len(a.Services); i++ { + svcA := a.Services[i] + svcB := b.Services[i] + + if svcA.Name != svcB.Name { + return false + } + + if svcA.Namespace != svcB.Namespace { + return false + } + + if len(svcA.Consumers) != len(svcB.Consumers) { + return false + } + + for j := 0; j < len(svcA.Consumers); j++ { + consumerA := svcA.Consumers[j] + consumerB := svcB.Consumers[j] + + if consumerA.Partition != consumerB.Partition { + return false + } + + if consumerA.Peer != consumerB.Peer { + return false + } + + if consumerA.SamenessGroup != consumerB.SamenessGroup { + return false + } + } + } + return true +} + +func keys[K comparable, V any](m map[K]V) []K { + keys := make([]K, 0, len(m)) + for key := range m { + keys = append(keys, key) + } + + return keys +} + +var fakeServiceType = &pbresource.Type{ + Group: "catalog", + GroupVersion: "v2beta1", + Kind: "Service", +} diff --git a/internal/multicluster/internal/controllers/v1compat/controller_test.go b/internal/multicluster/internal/controllers/v1compat/controller_test.go new file mode 100644 index 000000000000..a736bbf439f0 --- /dev/null +++ b/internal/multicluster/internal/controllers/v1compat/controller_test.go @@ -0,0 +1,427 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package v1compat + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + "github.com/hashicorp/consul/acl" + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/multicluster/internal/types" + "github.com/hashicorp/consul/internal/resource" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/consul/version/versiontest" +) + +type controllerSuite struct { + suite.Suite + ctx context.Context + ctl *controller.TestController + isEnterprise bool + tenancies []*pbresource.Tenancy + config *MockAggregatedConfig +} + +func (suite *controllerSuite) SetupTest() { + suite.tenancies = rtest.TestTenancies() + suite.isEnterprise = versiontest.IsEnterprise() + suite.ctx = testutil.TestContext(suite.T()) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(types.Register). + WithTenancies(suite.tenancies...). + Run(suite.T()) + + suite.config = NewMockAggregatedConfig(suite.T()) + suite.config.EXPECT().EventChannel().Return(make(chan controller.Event)) + suite.ctl = controller.NewTestController( + Controller(suite.config), + client, + ).WithLogger(testutil.Logger(suite.T())) +} + +// Test that we do nothing if V1 exports have not been replicated to v2 resources compatible with this controller +func (suite *controllerSuite) TestReconcile_V1ExportsExist() { + incompatibleConfig := &structs.ExportedServicesConfigEntry{ + Name: "v1Legacy", + Meta: map[string]string{controllerMetaKey: "foo-controller"}, + } + + suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { + entMeta := acl.DefaultEnterpriseMeta() + entMeta.OverridePartition(tenancy.Partition) + + suite.config.EXPECT(). + GetExportedServicesConfigEntry(suite.ctx, tenancy.Partition, entMeta). + Return(incompatibleConfig, nil) + + resID := &pbresource.ID{ + Type: pbmulticluster.ComputedExportedServicesType, + Tenancy: &pbresource.Tenancy{Partition: tenancy.Partition}, + Name: types.ComputedExportedServicesName, + } + err := suite.ctl.Reconcile(suite.ctx, controller.Request{ID: resID}) + require.NoError(suite.T(), err) + }) +} + +// Test that we do not stop reconciler even when we fail to retrieve the config entry +func (suite *controllerSuite) TestReconcile_GetExportedServicesConfigEntry_Error() { + suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { + entMeta := acl.DefaultEnterpriseMeta() + entMeta.OverridePartition(tenancy.Partition) + + suite.config.EXPECT(). + GetExportedServicesConfigEntry(suite.ctx, tenancy.Partition, entMeta). + Return(nil, fmt.Errorf("failed to retrieve config entry")) + + resID := &pbresource.ID{ + Type: pbmulticluster.ComputedExportedServicesType, + Tenancy: &pbresource.Tenancy{Partition: tenancy.Partition}, + Name: types.ComputedExportedServicesName, + } + err := suite.ctl.Reconcile(suite.ctx, controller.Request{ID: resID}) + require.NoError(suite.T(), err) + }) +} + +// Delete config entry for case where resources aren't found +func (suite *controllerSuite) TestReconcile_DeleteConfig_MissingResources() { + suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { + entMeta := acl.DefaultEnterpriseMeta() + entMeta.OverridePartition(tenancy.Partition) + + configEntry := &structs.ExportedServicesConfigEntry{ + // v1 exported-services config entries must have a Name that is the partitions name + Name: tenancy.Partition, + Meta: map[string]string{ + controllerMetaKey: ControllerName, + }, + EnterpriseMeta: acl.NewEnterpriseMetaWithPartition(tenancy.Partition, ""), + } + + suite.config.EXPECT().GetExportedServicesConfigEntry(suite.ctx, tenancy.Partition, entMeta).Return(configEntry, nil) + suite.config.EXPECT().DeleteExportedServicesConfigEntry(suite.ctx, tenancy.Partition, entMeta).Return(nil) + + resID := &pbresource.ID{ + Type: pbmulticluster.ComputedExportedServicesType, + Tenancy: &pbresource.Tenancy{Partition: tenancy.Partition}, + Name: types.ComputedExportedServicesName, + } + err := suite.ctl.Reconcile(suite.ctx, controller.Request{ID: resID}) + require.NoError(suite.T(), err) + }) +} + +func (suite *controllerSuite) TestReconcile_NewExport_PartitionExport() { + if !suite.isEnterprise { + suite.T().Skip("this test should only run against the enterprise build") + } + + suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { + entMeta := acl.DefaultEnterpriseMeta() + entMeta.OverridePartition(tenancy.Partition) + + // used as a return value for GetExportedServicesConfigEntry + existingCE := &structs.ExportedServicesConfigEntry{ + // v1 exported-services config entries must have a Name that is the partitions name + Name: tenancy.Partition, + Meta: map[string]string{ + controllerMetaKey: ControllerName, + }, + EnterpriseMeta: acl.NewEnterpriseMetaWithPartition(tenancy.Partition, ""), + } + suite.config.EXPECT().GetExportedServicesConfigEntry(suite.ctx, tenancy.Partition, entMeta).Return(existingCE, nil) + + // expected config entry to be written by reconcile + expectedCE := &structs.ExportedServicesConfigEntry{ + Name: tenancy.Partition, + Services: []structs.ExportedService{ + { + Name: "s1", + Namespace: resource.DefaultNamespaceName, + Consumers: []structs.ServiceConsumer{ + { + Partition: "p1", + }, + }, + }, + }, + Meta: map[string]string{ + controllerMetaKey: ControllerName, + }, + EnterpriseMeta: *entMeta, + } + suite.config.EXPECT().WriteExportedServicesConfigEntry(suite.ctx, expectedCE).Return(nil) + + name := "s1" + expSv := &pbmulticluster.ExportedServices{ + Services: []string{name}, + Consumers: []*pbmulticluster.ExportedServicesConsumer{ + {ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Partition{Partition: "p1"}}, + }, + } + rtest.Resource(pbmulticluster.ExportedServicesType, "exported-svcs"). + WithData(suite.T(), expSv). + WithTenancy(&pbresource.Tenancy{Partition: tenancy.Partition}). + Write(suite.T(), suite.ctl.Runtime().Client) + cesID := &pbresource.ID{ + Type: pbmulticluster.ComputedExportedServicesType, + Tenancy: &pbresource.Tenancy{Partition: tenancy.Partition}, + Name: types.ComputedExportedServicesName, + } + err := suite.ctl.Reconcile(suite.ctx, controller.Request{ID: cesID}) + require.NoError(suite.T(), err) + }) +} + +func (suite *controllerSuite) TestReconcile_NewExport_PeerExport() { + if !suite.isEnterprise { + suite.T().Skip("this test should only run against the enterprise build") + } + + suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { + entMeta := acl.DefaultEnterpriseMeta() + entMeta.OverridePartition(tenancy.Partition) + + // used as a return value for GetExportedServicesConfigEntry + existingCE := &structs.ExportedServicesConfigEntry{ + // v1 exported-services config entries must have a Name that is the partitions name + Name: tenancy.Partition, + Meta: map[string]string{ + controllerMetaKey: ControllerName, + }, + EnterpriseMeta: acl.NewEnterpriseMetaWithPartition(tenancy.Partition, ""), + } + suite.config.EXPECT().GetExportedServicesConfigEntry(suite.ctx, tenancy.Partition, entMeta).Return(existingCE, nil) + + // expected config entry to be written by reconcile + expectedCE := &structs.ExportedServicesConfigEntry{ + Name: tenancy.Partition, + Services: []structs.ExportedService{ + { + Name: "s1", + Namespace: resource.DefaultNamespaceName, + Consumers: []structs.ServiceConsumer{ + { + Peer: "peer1", + }, + }, + }, + }, + Meta: map[string]string{ + controllerMetaKey: ControllerName, + }, + EnterpriseMeta: *entMeta, + } + suite.config.EXPECT().WriteExportedServicesConfigEntry(suite.ctx, expectedCE).Return(nil) + + name := "s1" + expSv := &pbmulticluster.ExportedServices{ + Services: []string{name}, + Consumers: []*pbmulticluster.ExportedServicesConsumer{ + {ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Peer{Peer: "peer1"}}, + }, + } + rtest.Resource(pbmulticluster.ExportedServicesType, "exported-svcs"). + WithData(suite.T(), expSv). + WithTenancy(&pbresource.Tenancy{Partition: tenancy.Partition}). + Write(suite.T(), suite.ctl.Runtime().Client) + cesID := &pbresource.ID{ + Type: pbmulticluster.ComputedExportedServicesType, + Tenancy: &pbresource.Tenancy{Partition: tenancy.Partition}, + Name: types.ComputedExportedServicesName, + } + err := suite.ctl.Reconcile(suite.ctx, controller.Request{ID: cesID}) + require.NoError(suite.T(), err) + }) +} + +func (suite *controllerSuite) TestReconcile_NewExport_SamenessGroupsExport() { + if !suite.isEnterprise { + suite.T().Skip("this test should only run against the enterprise build") + } + + suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { + entMeta := acl.DefaultEnterpriseMeta() + entMeta.OverridePartition(tenancy.Partition) + + // used as a return value for GetExportedServicesConfigEntry + existingCE := &structs.ExportedServicesConfigEntry{ + // v1 exported-services config entries must have a Name that is the partitions name + Name: tenancy.Partition, + Meta: map[string]string{ + controllerMetaKey: ControllerName, + }, + EnterpriseMeta: acl.NewEnterpriseMetaWithPartition(tenancy.Partition, ""), + } + suite.config.EXPECT().GetExportedServicesConfigEntry(suite.ctx, tenancy.Partition, entMeta).Return(existingCE, nil) + + // expected config entry to be written by reconcile + expectedCE := &structs.ExportedServicesConfigEntry{ + Name: tenancy.Partition, + Services: []structs.ExportedService{ + { + Name: "s1", + Namespace: resource.DefaultNamespaceName, + Consumers: []structs.ServiceConsumer{ + { + SamenessGroup: "sg1", + }, + }, + }, + }, + Meta: map[string]string{ + controllerMetaKey: ControllerName, + }, + EnterpriseMeta: *entMeta, + } + suite.config.EXPECT().WriteExportedServicesConfigEntry(suite.ctx, expectedCE).Return(nil) + + name := "s1" + expSv := &pbmulticluster.ExportedServices{ + Services: []string{name}, + Consumers: []*pbmulticluster.ExportedServicesConsumer{ + {ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_SamenessGroup{SamenessGroup: "sg1"}}, + }, + } + rtest.Resource(pbmulticluster.ExportedServicesType, "exported-svcs"). + WithData(suite.T(), expSv). + WithTenancy(&pbresource.Tenancy{Partition: tenancy.Partition}). + Write(suite.T(), suite.ctl.Runtime().Client) + cesID := &pbresource.ID{ + Type: pbmulticluster.ComputedExportedServicesType, + Tenancy: &pbresource.Tenancy{Partition: tenancy.Partition}, + Name: types.ComputedExportedServicesName, + } + err := suite.ctl.Reconcile(suite.ctx, controller.Request{ID: cesID}) + require.NoError(suite.T(), err) + }) +} + +func (suite *controllerSuite) TestReconcile_MultipleExports() { + if !suite.isEnterprise { + suite.T().Skip("this test should only run against the enterprise build") + } + + suite.runTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { + entMeta := acl.DefaultEnterpriseMeta() + entMeta.OverridePartition(tenancy.Partition) + configCE := &structs.ExportedServicesConfigEntry{ + // v1 exported-services config entries must have a Name that is the partitions name + Name: tenancy.Partition, + Meta: map[string]string{ + controllerMetaKey: ControllerName, + }, + EnterpriseMeta: acl.NewEnterpriseMetaWithPartition(tenancy.Partition, ""), + } + + suite.config.EXPECT(). + GetExportedServicesConfigEntry(suite.ctx, tenancy.Partition, entMeta). + Return(configCE, nil) + + expSv1 := &pbmulticluster.ExportedServices{ + Services: []string{"s1"}, + Consumers: []*pbmulticluster.ExportedServicesConsumer{ + {ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Partition{Partition: "p1"}}, + {ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Partition{Partition: "p4"}}, + }, + } + expSv2 := &pbmulticluster.ExportedServices{ + Services: []string{"s2"}, + Consumers: []*pbmulticluster.ExportedServicesConsumer{ + {ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Partition{Partition: "p2"}}, + {ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Peer{Peer: "peer1"}}, + }, + } + expSv3 := &pbmulticluster.ExportedServices{ + Services: []string{"s1", "s3"}, + Consumers: []*pbmulticluster.ExportedServicesConsumer{ + {ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_Partition{Partition: "p3"}}, + {ConsumerTenancy: &pbmulticluster.ExportedServicesConsumer_SamenessGroup{SamenessGroup: "sg1"}}, + }, + } + + for i, s := range []*pbmulticluster.ExportedServices{expSv1, expSv2, expSv3} { + rtest.Resource(pbmulticluster.ExportedServicesType, fmt.Sprintf("exported-svcs-%d", i)). + WithData(suite.T(), s). + WithTenancy(&pbresource.Tenancy{Partition: tenancy.Partition}). + Write(suite.T(), suite.ctl.Runtime().Client) + } + + cesID := &pbresource.ID{ + Type: pbmulticluster.ComputedExportedServicesType, + Tenancy: &pbresource.Tenancy{Partition: tenancy.Partition}, + Name: types.ComputedExportedServicesName, + } + + // expected computed config entry to be written by reconcile + computedConfigEntry := &structs.ExportedServicesConfigEntry{ + Name: tenancy.Partition, + Meta: map[string]string{ + controllerMetaKey: ControllerName, + }, + Services: []structs.ExportedService{ + { + Name: "s3", + Namespace: resource.DefaultNamespaceName, + Consumers: []structs.ServiceConsumer{ + {Partition: "p3"}, + {SamenessGroup: "sg1"}, + }, + }, + { + Name: "s2", + Namespace: resource.DefaultNamespaceName, + Consumers: []structs.ServiceConsumer{ + {Partition: "p2"}, + {Peer: "peer1"}, + }, + }, + { + Name: "s1", + Namespace: resource.DefaultNamespaceName, + Consumers: []structs.ServiceConsumer{ + {Partition: "p1"}, + {Partition: "p3"}, + {Partition: "p4"}, + {SamenessGroup: "sg1"}, + }, + }, + }, + EnterpriseMeta: acl.NewEnterpriseMetaWithPartition(tenancy.Partition, resource.DefaultNamespaceName), + } + suite.config.EXPECT(). + WriteExportedServicesConfigEntry(suite.ctx, computedConfigEntry). + Return(nil) + + err := suite.ctl.Reconcile(suite.ctx, controller.Request{ID: cesID}) + require.NoError(suite.T(), err) + }) +} + +func (suite *controllerSuite) runTestCaseWithTenancies(testFunc func(*pbresource.Tenancy)) { + for _, tenancy := range suite.tenancies { + suite.Run(suite.appendTenancyInfo(tenancy), func() { + testFunc(tenancy) + }) + } +} + +func (suite *controllerSuite) appendTenancyInfo(tenancy *pbresource.Tenancy) string { + return fmt.Sprintf("%s_Namespace_%s_Partition", tenancy.Namespace, tenancy.Partition) +} + +func TestController(t *testing.T) { + suite.Run(t, new(controllerSuite)) +} diff --git a/internal/multicluster/internal/controllers/v1compat/mock_AggregatedConfig.go b/internal/multicluster/internal/controllers/v1compat/mock_AggregatedConfig.go new file mode 100644 index 000000000000..4d33ce585814 --- /dev/null +++ b/internal/multicluster/internal/controllers/v1compat/mock_AggregatedConfig.go @@ -0,0 +1,262 @@ +// Code generated by mockery v2.20.0. DO NOT EDIT. + +package v1compat + +import ( + context "context" + + acl "github.com/hashicorp/consul/acl" + + controller "github.com/hashicorp/consul/internal/controller" + + mock "github.com/stretchr/testify/mock" + + structs "github.com/hashicorp/consul/agent/structs" +) + +// MockAggregatedConfig is an autogenerated mock type for the AggregatedConfig type +type MockAggregatedConfig struct { + mock.Mock +} + +type MockAggregatedConfig_Expecter struct { + mock *mock.Mock +} + +func (_m *MockAggregatedConfig) EXPECT() *MockAggregatedConfig_Expecter { + return &MockAggregatedConfig_Expecter{mock: &_m.Mock} +} + +// DeleteExportedServicesConfigEntry provides a mock function with given fields: _a0, _a1, _a2 +func (_m *MockAggregatedConfig) DeleteExportedServicesConfigEntry(_a0 context.Context, _a1 string, _a2 *acl.EnterpriseMeta) error { + ret := _m.Called(_a0, _a1, _a2) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, *acl.EnterpriseMeta) error); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockAggregatedConfig_DeleteExportedServicesConfigEntry_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteExportedServicesConfigEntry' +type MockAggregatedConfig_DeleteExportedServicesConfigEntry_Call struct { + *mock.Call +} + +// DeleteExportedServicesConfigEntry is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 string +// - _a2 *acl.EnterpriseMeta +func (_e *MockAggregatedConfig_Expecter) DeleteExportedServicesConfigEntry(_a0 interface{}, _a1 interface{}, _a2 interface{}) *MockAggregatedConfig_DeleteExportedServicesConfigEntry_Call { + return &MockAggregatedConfig_DeleteExportedServicesConfigEntry_Call{Call: _e.mock.On("DeleteExportedServicesConfigEntry", _a0, _a1, _a2)} +} + +func (_c *MockAggregatedConfig_DeleteExportedServicesConfigEntry_Call) Run(run func(_a0 context.Context, _a1 string, _a2 *acl.EnterpriseMeta)) *MockAggregatedConfig_DeleteExportedServicesConfigEntry_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(*acl.EnterpriseMeta)) + }) + return _c +} + +func (_c *MockAggregatedConfig_DeleteExportedServicesConfigEntry_Call) Return(_a0 error) *MockAggregatedConfig_DeleteExportedServicesConfigEntry_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockAggregatedConfig_DeleteExportedServicesConfigEntry_Call) RunAndReturn(run func(context.Context, string, *acl.EnterpriseMeta) error) *MockAggregatedConfig_DeleteExportedServicesConfigEntry_Call { + _c.Call.Return(run) + return _c +} + +// EventChannel provides a mock function with given fields: +func (_m *MockAggregatedConfig) EventChannel() chan controller.Event { + ret := _m.Called() + + var r0 chan controller.Event + if rf, ok := ret.Get(0).(func() chan controller.Event); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(chan controller.Event) + } + } + + return r0 +} + +// MockAggregatedConfig_EventChannel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EventChannel' +type MockAggregatedConfig_EventChannel_Call struct { + *mock.Call +} + +// EventChannel is a helper method to define mock.On call +func (_e *MockAggregatedConfig_Expecter) EventChannel() *MockAggregatedConfig_EventChannel_Call { + return &MockAggregatedConfig_EventChannel_Call{Call: _e.mock.On("EventChannel")} +} + +func (_c *MockAggregatedConfig_EventChannel_Call) Run(run func()) *MockAggregatedConfig_EventChannel_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *MockAggregatedConfig_EventChannel_Call) Return(_a0 chan controller.Event) *MockAggregatedConfig_EventChannel_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockAggregatedConfig_EventChannel_Call) RunAndReturn(run func() chan controller.Event) *MockAggregatedConfig_EventChannel_Call { + _c.Call.Return(run) + return _c +} + +// GetExportedServicesConfigEntry provides a mock function with given fields: _a0, _a1, _a2 +func (_m *MockAggregatedConfig) GetExportedServicesConfigEntry(_a0 context.Context, _a1 string, _a2 *acl.EnterpriseMeta) (*structs.ExportedServicesConfigEntry, error) { + ret := _m.Called(_a0, _a1, _a2) + + var r0 *structs.ExportedServicesConfigEntry + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, *acl.EnterpriseMeta) (*structs.ExportedServicesConfigEntry, error)); ok { + return rf(_a0, _a1, _a2) + } + if rf, ok := ret.Get(0).(func(context.Context, string, *acl.EnterpriseMeta) *structs.ExportedServicesConfigEntry); ok { + r0 = rf(_a0, _a1, _a2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*structs.ExportedServicesConfigEntry) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, *acl.EnterpriseMeta) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockAggregatedConfig_GetExportedServicesConfigEntry_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetExportedServicesConfigEntry' +type MockAggregatedConfig_GetExportedServicesConfigEntry_Call struct { + *mock.Call +} + +// GetExportedServicesConfigEntry is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 string +// - _a2 *acl.EnterpriseMeta +func (_e *MockAggregatedConfig_Expecter) GetExportedServicesConfigEntry(_a0 interface{}, _a1 interface{}, _a2 interface{}) *MockAggregatedConfig_GetExportedServicesConfigEntry_Call { + return &MockAggregatedConfig_GetExportedServicesConfigEntry_Call{Call: _e.mock.On("GetExportedServicesConfigEntry", _a0, _a1, _a2)} +} + +func (_c *MockAggregatedConfig_GetExportedServicesConfigEntry_Call) Run(run func(_a0 context.Context, _a1 string, _a2 *acl.EnterpriseMeta)) *MockAggregatedConfig_GetExportedServicesConfigEntry_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(*acl.EnterpriseMeta)) + }) + return _c +} + +func (_c *MockAggregatedConfig_GetExportedServicesConfigEntry_Call) Return(_a0 *structs.ExportedServicesConfigEntry, _a1 error) *MockAggregatedConfig_GetExportedServicesConfigEntry_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockAggregatedConfig_GetExportedServicesConfigEntry_Call) RunAndReturn(run func(context.Context, string, *acl.EnterpriseMeta) (*structs.ExportedServicesConfigEntry, error)) *MockAggregatedConfig_GetExportedServicesConfigEntry_Call { + _c.Call.Return(run) + return _c +} + +// Start provides a mock function with given fields: _a0 +func (_m *MockAggregatedConfig) Start(_a0 context.Context) { + _m.Called(_a0) +} + +// MockAggregatedConfig_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type MockAggregatedConfig_Start_Call struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +// - _a0 context.Context +func (_e *MockAggregatedConfig_Expecter) Start(_a0 interface{}) *MockAggregatedConfig_Start_Call { + return &MockAggregatedConfig_Start_Call{Call: _e.mock.On("Start", _a0)} +} + +func (_c *MockAggregatedConfig_Start_Call) Run(run func(_a0 context.Context)) *MockAggregatedConfig_Start_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *MockAggregatedConfig_Start_Call) Return() *MockAggregatedConfig_Start_Call { + _c.Call.Return() + return _c +} + +func (_c *MockAggregatedConfig_Start_Call) RunAndReturn(run func(context.Context)) *MockAggregatedConfig_Start_Call { + _c.Call.Return(run) + return _c +} + +// WriteExportedServicesConfigEntry provides a mock function with given fields: _a0, _a1 +func (_m *MockAggregatedConfig) WriteExportedServicesConfigEntry(_a0 context.Context, _a1 *structs.ExportedServicesConfigEntry) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *structs.ExportedServicesConfigEntry) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockAggregatedConfig_WriteExportedServicesConfigEntry_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WriteExportedServicesConfigEntry' +type MockAggregatedConfig_WriteExportedServicesConfigEntry_Call struct { + *mock.Call +} + +// WriteExportedServicesConfigEntry is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *structs.ExportedServicesConfigEntry +func (_e *MockAggregatedConfig_Expecter) WriteExportedServicesConfigEntry(_a0 interface{}, _a1 interface{}) *MockAggregatedConfig_WriteExportedServicesConfigEntry_Call { + return &MockAggregatedConfig_WriteExportedServicesConfigEntry_Call{Call: _e.mock.On("WriteExportedServicesConfigEntry", _a0, _a1)} +} + +func (_c *MockAggregatedConfig_WriteExportedServicesConfigEntry_Call) Run(run func(_a0 context.Context, _a1 *structs.ExportedServicesConfigEntry)) *MockAggregatedConfig_WriteExportedServicesConfigEntry_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*structs.ExportedServicesConfigEntry)) + }) + return _c +} + +func (_c *MockAggregatedConfig_WriteExportedServicesConfigEntry_Call) Return(_a0 error) *MockAggregatedConfig_WriteExportedServicesConfigEntry_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockAggregatedConfig_WriteExportedServicesConfigEntry_Call) RunAndReturn(run func(context.Context, *structs.ExportedServicesConfigEntry) error) *MockAggregatedConfig_WriteExportedServicesConfigEntry_Call { + _c.Call.Return(run) + return _c +} + +type mockConstructorTestingTNewMockAggregatedConfig interface { + mock.TestingT + Cleanup(func()) +} + +// NewMockAggregatedConfig creates a new instance of MockAggregatedConfig. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewMockAggregatedConfig(t mockConstructorTestingTNewMockAggregatedConfig) *MockAggregatedConfig { + mock := &MockAggregatedConfig{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/multicluster/internal/types/computed_exported_services.go b/internal/multicluster/internal/types/computed_exported_services.go index 70c900c9b86c..2090f9b211e6 100644 --- a/internal/multicluster/internal/types/computed_exported_services.go +++ b/internal/multicluster/internal/types/computed_exported_services.go @@ -6,7 +6,7 @@ package types import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/internal/resource" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" + pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" "github.com/hashicorp/consul/proto-public/pbresource" ) diff --git a/internal/multicluster/internal/types/computed_exported_services_test.go b/internal/multicluster/internal/types/computed_exported_services_test.go index 79462c7088c3..f86750137637 100644 --- a/internal/multicluster/internal/types/computed_exported_services_test.go +++ b/internal/multicluster/internal/types/computed_exported_services_test.go @@ -5,21 +5,23 @@ package types import ( "errors" - "github.com/hashicorp/consul/agent/structs" + "testing" + + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" + pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/stretchr/testify/require" - "testing" + "github.com/hashicorp/consul/version/versiontest" ) func computedExportedServicesWithPartition(partitionName string) *pbmulticluster.ComputedExportedServices { - consumers := []*pbmulticluster.ComputedExportedService{ + services := []*pbmulticluster.ComputedExportedService{ { - Consumers: []*pbmulticluster.ComputedExportedServicesConsumer{ + Consumers: []*pbmulticluster.ComputedExportedServiceConsumer{ { - ConsumerTenancy: &pbmulticluster.ComputedExportedServicesConsumer_Partition{ + Tenancy: &pbmulticluster.ComputedExportedServiceConsumer_Partition{ Partition: partitionName, }, }, @@ -27,16 +29,16 @@ func computedExportedServicesWithPartition(partitionName string) *pbmulticluster }, } return &pbmulticluster.ComputedExportedServices{ - Consumers: consumers, + Services: services, } } func computedExportedServicesWithPeer(peerName string) *pbmulticluster.ComputedExportedServices { - consumers := []*pbmulticluster.ComputedExportedService{ + services := []*pbmulticluster.ComputedExportedService{ { - Consumers: []*pbmulticluster.ComputedExportedServicesConsumer{ + Consumers: []*pbmulticluster.ComputedExportedServiceConsumer{ { - ConsumerTenancy: &pbmulticluster.ComputedExportedServicesConsumer_Peer{ + Tenancy: &pbmulticluster.ComputedExportedServiceConsumer_Peer{ Peer: peerName, }, }, @@ -44,7 +46,7 @@ func computedExportedServicesWithPeer(peerName string) *pbmulticluster.ComputedE }, } return &pbmulticluster.ComputedExportedServices{ - Consumers: consumers, + Services: services, } } @@ -123,7 +125,7 @@ func TestComputedExportedServicesValidations(t *testing.T) { expectErrorENT []string } - isEnterprise := structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default" + isEnterprise := versiontest.IsEnterprise() run := func(t *testing.T, tc testcase) { expectError := tc.expectErrorCE diff --git a/internal/multicluster/internal/types/decoded.go b/internal/multicluster/internal/types/decoded.go new file mode 100644 index 000000000000..a41174ba5d6e --- /dev/null +++ b/internal/multicluster/internal/types/decoded.go @@ -0,0 +1,15 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package types + +import ( + "github.com/hashicorp/consul/internal/resource" + v2 "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" +) + +type ( + DecodedExportedServices = resource.DecodedResource[*v2.ExportedServices] + DecodedNamespaceExportedServices = resource.DecodedResource[*v2.NamespaceExportedServices] + DecodedPartitionExportedServices = resource.DecodedResource[*v2.PartitionExportedServices] +) diff --git a/internal/multicluster/internal/types/exported_services.go b/internal/multicluster/internal/types/exported_services.go index 87cebb244ab4..5ba6ca11ddac 100644 --- a/internal/multicluster/internal/types/exported_services.go +++ b/internal/multicluster/internal/types/exported_services.go @@ -6,7 +6,7 @@ package types import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/internal/resource" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" + pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" "github.com/hashicorp/consul/proto-public/pbresource" ) diff --git a/internal/multicluster/internal/types/exported_services_test.go b/internal/multicluster/internal/types/exported_services_test.go index ea80b16e43df..b5f29dba1fb9 100644 --- a/internal/multicluster/internal/types/exported_services_test.go +++ b/internal/multicluster/internal/types/exported_services_test.go @@ -5,13 +5,15 @@ package types import ( "errors" - "github.com/hashicorp/consul/agent/structs" + "testing" + + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" + pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/stretchr/testify/require" - "testing" + "github.com/hashicorp/consul/version/versiontest" ) func inValidExportedServices() *pbmulticluster.ExportedServices { @@ -149,7 +151,7 @@ func TestExportedServicesValidation(t *testing.T) { expectErrorENT []string } - isEnterprise := structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default" + isEnterprise := versiontest.IsEnterprise() run := func(t *testing.T, tc testcase) { expectError := tc.expectErrorCE diff --git a/internal/multicluster/internal/types/helpers.go b/internal/multicluster/internal/types/helpers.go index 5dac17f1e7a9..40c0a4010369 100644 --- a/internal/multicluster/internal/types/helpers.go +++ b/internal/multicluster/internal/types/helpers.go @@ -5,8 +5,9 @@ package types import ( "fmt" + "github.com/hashicorp/consul/internal/resource" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" + pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/go-multierror" ) @@ -15,7 +16,7 @@ func validateExportedServiceConsumerCommon(consumer *pbmulticluster.ExportedServ switch consumer.GetConsumerTenancy().(type) { case *pbmulticluster.ExportedServicesConsumer_Peer: { - if consumer.GetPeer() == "" || consumer.GetPeer() == "local" { + if consumer.GetPeer() == "" || consumer.GetPeer() == resource.DefaultPeerName { return resource.ErrInvalidListElement{ Name: "peer", Index: indx, diff --git a/internal/multicluster/internal/types/helpers_ce.go b/internal/multicluster/internal/types/helpers_ce.go index b997b8671ad0..90e9ffdd2006 100644 --- a/internal/multicluster/internal/types/helpers_ce.go +++ b/internal/multicluster/internal/types/helpers_ce.go @@ -7,9 +7,11 @@ package types import ( "fmt" - "github.com/hashicorp/consul/internal/resource" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" + "github.com/hashicorp/go-multierror" + + "github.com/hashicorp/consul/internal/resource" + pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" ) func validateExportedServicesConsumer(consumer *pbmulticluster.ExportedServicesConsumer, indx int) error { @@ -34,24 +36,24 @@ func ValidateComputedExportedServicesEnterprise(computedExportedServices *pbmult var merr error - for indx, consumer := range computedExportedServices.GetConsumers() { - for _, computedExportedServiceConsumer := range consumer.GetConsumers() { - switch computedExportedServiceConsumer.GetConsumerTenancy().(type) { - case *pbmulticluster.ComputedExportedServicesConsumer_Partition: + for indx, service := range computedExportedServices.GetServices() { + for _, consumer := range service.GetConsumers() { + switch consumer.GetTenancy().(type) { + case *pbmulticluster.ComputedExportedServiceConsumer_Partition: merr = multierror.Append(merr, resource.ErrInvalidListElement{ Name: "partition", Index: indx, Wrapped: fmt.Errorf("can only be set in Enterprise"), }) - if computedExportedServiceConsumer.GetPartition() == "" { + if consumer.GetPartition() == "" { merr = multierror.Append(merr, resource.ErrInvalidListElement{ Name: "partition", Index: indx, Wrapped: fmt.Errorf("can not be empty"), }) } - case *pbmulticluster.ComputedExportedServicesConsumer_Peer: - if computedExportedServiceConsumer.GetPeer() == "" { + case *pbmulticluster.ComputedExportedServiceConsumer_Peer: + if consumer.GetPeer() == "" { merr = multierror.Append(merr, resource.ErrInvalidListElement{ Name: "peer", Index: indx, diff --git a/internal/multicluster/internal/types/namespace_exported_services.go b/internal/multicluster/internal/types/namespace_exported_services.go index 857ea868b8e9..39d371f6723e 100644 --- a/internal/multicluster/internal/types/namespace_exported_services.go +++ b/internal/multicluster/internal/types/namespace_exported_services.go @@ -6,7 +6,7 @@ package types import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/internal/resource" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" + pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" "github.com/hashicorp/consul/proto-public/pbresource" ) diff --git a/internal/multicluster/internal/types/namespace_exported_services_test.go b/internal/multicluster/internal/types/namespace_exported_services_test.go index ab88a03767fc..a81e9d92fb90 100644 --- a/internal/multicluster/internal/types/namespace_exported_services_test.go +++ b/internal/multicluster/internal/types/namespace_exported_services_test.go @@ -4,13 +4,15 @@ package types import ( - "github.com/hashicorp/consul/agent/structs" + "testing" + + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" + pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/stretchr/testify/require" - "testing" + "github.com/hashicorp/consul/version/versiontest" ) func validNamespaceExportedServicesWithPeer(peerName string) *pbmulticluster.NamespaceExportedServices { @@ -51,6 +53,7 @@ func validNamespaceExportedServicesWithSamenessGroup(samenessGroupName string) * Consumers: consumers, } } + func TestNamespaceExportedServicesACLs(t *testing.T) { // Wire up a registry to generically invoke hooks registry := resource.NewRegistry() @@ -115,7 +118,7 @@ func TestNamespaceExportedServicesValidations(t *testing.T) { expectErrorENT []string } - isEnterprise := structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default" + isEnterprise := versiontest.IsEnterprise() run := func(t *testing.T, tc testcase) { expectError := tc.expectErrorCE diff --git a/internal/multicluster/internal/types/partition_exported_services.go b/internal/multicluster/internal/types/partition_exported_services.go index 110eb5d6efa1..113105168d23 100644 --- a/internal/multicluster/internal/types/partition_exported_services.go +++ b/internal/multicluster/internal/types/partition_exported_services.go @@ -6,7 +6,7 @@ package types import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/internal/resource" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" + pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" "github.com/hashicorp/consul/proto-public/pbresource" ) diff --git a/internal/multicluster/internal/types/partition_exported_services_test.go b/internal/multicluster/internal/types/partition_exported_services_test.go index fdd90ef11d12..0327a6820e4d 100644 --- a/internal/multicluster/internal/types/partition_exported_services_test.go +++ b/internal/multicluster/internal/types/partition_exported_services_test.go @@ -4,13 +4,15 @@ package types import ( - "github.com/hashicorp/consul/agent/structs" + "testing" + + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/resourcetest" - pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2beta1" + pbmulticluster "github.com/hashicorp/consul/proto-public/pbmulticluster/v2" "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/stretchr/testify/require" - "testing" + "github.com/hashicorp/consul/version/versiontest" ) func validPartitionExportedServicesWithPeer(peerName string) *pbmulticluster.PartitionExportedServices { @@ -116,7 +118,7 @@ func TestPartitionExportedServicesValidations(t *testing.T) { expectErrorENT []string } - isEnterprise := structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default" + isEnterprise := versiontest.IsEnterprise() run := func(t *testing.T, tc testcase) { expectError := tc.expectErrorCE diff --git a/internal/multicluster/internal/types/types.go b/internal/multicluster/internal/types/types.go index 9ee6691e19ec..4ed2537a6671 100644 --- a/internal/multicluster/internal/types/types.go +++ b/internal/multicluster/internal/types/types.go @@ -7,12 +7,6 @@ import ( "github.com/hashicorp/consul/internal/resource" ) -const ( - GroupName = "multicluster" - VersionV2Beta1 = "v2beta1" - CurrentVersion = VersionV2Beta1 -) - func Register(r resource.Registry) { RegisterExportedServices(r) RegisterNamespaceExportedServices(r) diff --git a/internal/protohcl/testproto/example.pb.go b/internal/protohcl/testproto/example.pb.go index 304eac53d6d9..1b2504ddd6eb 100644 --- a/internal/protohcl/testproto/example.pb.go +++ b/internal/protohcl/testproto/example.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: example.proto diff --git a/internal/resource/authz.go b/internal/resource/authz.go index 77a5d7850f9a..f0725d952aab 100644 --- a/internal/resource/authz.go +++ b/internal/resource/authz.go @@ -5,7 +5,7 @@ package resource func peerNameV2ToV1(peer string) string { // The name of the local/default peer is different between v1 and v2. - if peer == "local" { + if peer == DefaultPeerName { return "" } return peer @@ -14,7 +14,7 @@ func peerNameV2ToV1(peer string) string { func peerNameV1ToV2(peer string) string { // The name of the local/default peer is different between v1 and v2. if peer == "" { - return "local" + return DefaultPeerName } return peer } diff --git a/internal/resource/authz_ce.go b/internal/resource/authz_ce.go index 69a1749e2017..d41a1b9e892a 100644 --- a/internal/resource/authz_ce.go +++ b/internal/resource/authz_ce.go @@ -12,7 +12,6 @@ import ( // AuthorizerContext builds an ACL AuthorizerContext for the given tenancy. func AuthorizerContext(t *pbresource.Tenancy) *acl.AuthorizerContext { - return &acl.AuthorizerContext{ - Peer: peerNameV2ToV1(t.PeerName), - } + // TODO(peering/v2) handle non-local peers here + return &acl.AuthorizerContext{} } diff --git a/internal/resource/authz_ce_test.go b/internal/resource/authz_ce_test.go index a2b76f86bfe1..9808d8d9ee3f 100644 --- a/internal/resource/authz_ce_test.go +++ b/internal/resource/authz_ce_test.go @@ -31,21 +31,9 @@ func TestAuthorizerContext_CE(t *testing.T) { AuthorizerContext(&pbresource.Tenancy{ Partition: "foo", Namespace: "bar", - PeerName: "local", }), ) }) - t.Run("with non-local peer", func(t *testing.T) { - require.Equal(t, - &acl.AuthorizerContext{ - Peer: "remote", - }, - AuthorizerContext(&pbresource.Tenancy{ - Partition: "foo", - Namespace: "bar", - PeerName: "remote", - }), - ) - }) + // TODO(peering/v2): add a test here for non-local peers } diff --git a/internal/mesh/internal/controllers/routes/bound_refs.go b/internal/resource/bound_refs.go similarity index 75% rename from internal/mesh/internal/controllers/routes/bound_refs.go rename to internal/resource/bound_refs.go index afdac8460be8..039c77543fdd 100644 --- a/internal/mesh/internal/controllers/routes/bound_refs.go +++ b/internal/resource/bound_refs.go @@ -1,17 +1,16 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -package routes +package resource import ( "sort" - "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" ) type sectionRefKey struct { - resource.ReferenceKey + ReferenceKey Section string } @@ -36,17 +35,17 @@ func (c *BoundReferenceCollector) List() []*pbresource.Reference { } sort.Slice(out, func(i, j int) bool { - return resource.LessReference(out[i], out[j]) + return LessReference(out[i], out[j]) }) return out } -func (c *BoundReferenceCollector) AddRefOrID(ref resource.ReferenceOrID) { +func (c *BoundReferenceCollector) AddRefOrID(ref ReferenceOrID) { if c == nil { return } - c.AddRef(resource.ReferenceFromReferenceOrID(ref)) + c.AddRef(ReferenceFromReferenceOrID(ref)) } func (c *BoundReferenceCollector) AddRef(ref *pbresource.Reference) { @@ -54,7 +53,7 @@ func (c *BoundReferenceCollector) AddRef(ref *pbresource.Reference) { return } srk := sectionRefKey{ - ReferenceKey: resource.NewReferenceKey(ref), + ReferenceKey: NewReferenceKey(ref), Section: ref.Section, } diff --git a/internal/resource/decode.go b/internal/resource/decode.go index d96cb79a9a7c..461fd9376e49 100644 --- a/internal/resource/decode.go +++ b/internal/resource/decode.go @@ -58,6 +58,22 @@ func Decode[T proto.Message](res *pbresource.Resource) (*DecodedResource[T], err }, nil } +// DecodeList will generically decode the provided resource list into a list of 2-field +// structures that holds onto the original Resource and the decoded contents. +// +// Returns an ErrDataParse on unmarshalling errors. +func DecodeList[T proto.Message](resources []*pbresource.Resource) ([]*DecodedResource[T], error) { + var decoded []*DecodedResource[T] + for _, res := range resources { + d, err := Decode[T](res) + if err != nil { + return nil, err + } + decoded = append(decoded, d) + } + return decoded, nil +} + // GetDecodedResource will generically read the requested resource using the // client and either return nil on a NotFound or decode the response value. func GetDecodedResource[T proto.Message](ctx context.Context, client pbresource.ResourceServiceClient, id *pbresource.ID) (*DecodedResource[T], error) { @@ -70,3 +86,20 @@ func GetDecodedResource[T proto.Message](ctx context.Context, client pbresource. } return Decode[T](rsp.Resource) } + +func ListDecodedResource[T proto.Message](ctx context.Context, client pbresource.ResourceServiceClient, req *pbresource.ListRequest) ([]*DecodedResource[T], error) { + rsp, err := client.List(ctx, req) + if err != nil { + return nil, err + } + + results := make([]*DecodedResource[T], len(rsp.Resources)) + for idx, rsc := range rsp.Resources { + d, err := Decode[T](rsc) + if err != nil { + return nil, err + } + results[idx] = d + } + return results, nil +} diff --git a/internal/resource/decode_test.go b/internal/resource/decode_test.go index 02e86fddfbf7..9df601c901c9 100644 --- a/internal/resource/decode_test.go +++ b/internal/resource/decode_test.go @@ -22,7 +22,7 @@ import ( func TestGetDecodedResource(t *testing.T) { var ( - baseClient = svctest.RunResourceService(t, demo.RegisterTypes) + baseClient = svctest.NewResourceServiceBuilder().WithRegisterFns(demo.RegisterTypes).Run(t) client = rtest.NewClient(baseClient) ctx = testutil.TestContext(t) ) @@ -112,3 +112,50 @@ func TestDecode(t *testing.T) { require.Error(t, err) }) } + +func TestDecodeList(t *testing.T) { + t.Run("good", func(t *testing.T) { + artist1, err := demo.GenerateV2Artist() + require.NoError(t, err) + artist2, err := demo.GenerateV2Artist() + require.NoError(t, err) + dec1, err := resource.Decode[*pbdemo.Artist](artist1) + require.NoError(t, err) + dec2, err := resource.Decode[*pbdemo.Artist](artist2) + require.NoError(t, err) + + resources := []*pbresource.Resource{artist1, artist2} + + decList, err := resource.DecodeList[*pbdemo.Artist](resources) + require.NoError(t, err) + require.Len(t, decList, 2) + + prototest.AssertDeepEqual(t, dec1.Resource, decList[0].Resource) + prototest.AssertDeepEqual(t, dec1.Data, decList[0].Data) + prototest.AssertDeepEqual(t, dec2.Resource, decList[1].Resource) + prototest.AssertDeepEqual(t, dec2.Data, decList[1].Data) + }) + + t.Run("bad", func(t *testing.T) { + artist1, err := demo.GenerateV2Artist() + require.NoError(t, err) + + foo := &pbresource.Resource{ + Id: &pbresource.ID{ + Type: demo.TypeV2Artist, + Tenancy: resource.DefaultNamespacedTenancy(), + Name: "babypants", + }, + Data: &anypb.Any{ + TypeUrl: "garbage", + Value: []byte("more garbage"), + }, + Metadata: map[string]string{ + "generated_at": time.Now().Format(time.RFC3339), + }, + } + + _, err = resource.DecodeList[*pbdemo.Artist]([]*pbresource.Resource{artist1, foo}) + require.Error(t, err) + }) +} diff --git a/internal/resource/demo/controller.go b/internal/resource/demo/controller.go index a8757fcae262..b67da4782cb1 100644 --- a/internal/resource/demo/controller.go +++ b/internal/resource/demo/controller.go @@ -14,6 +14,7 @@ import ( "google.golang.org/protobuf/proto" "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/controller/dependency" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2" @@ -27,9 +28,9 @@ func RegisterControllers(mgr *controller.Manager) { mgr.Register(artistController()) } -func artistController() controller.Controller { - return controller.ForType(TypeV2Artist). - WithWatch(TypeV2Album, controller.MapOwner). +func artistController() *controller.Controller { + return controller.NewController("artists", TypeV2Artist). + WithWatch(TypeV2Album, dependency.MapOwner). WithReconciler(&artistReconciler{}) } diff --git a/internal/resource/demo/controller_test.go b/internal/resource/demo/controller_test.go index a8c2640d615a..303ecfe23589 100644 --- a/internal/resource/demo/controller_test.go +++ b/internal/resource/demo/controller_test.go @@ -16,7 +16,9 @@ import ( ) func TestArtistReconciler(t *testing.T) { - client := svctest.RunResourceService(t, RegisterTypes) + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(RegisterTypes). + Run(t) // Seed the database with an artist. res, err := GenerateV2Artist() diff --git a/internal/resource/demo/demo.go b/internal/resource/demo/demo.go index 12fced6718e6..ca363382c0b2 100644 --- a/internal/resource/demo/demo.go +++ b/internal/resource/demo/demo.go @@ -72,6 +72,13 @@ var ( GroupVersion: "v2", Kind: "Album", } + + // TypeV2Festival represents a named collection of artists and genres. + TypeV2Festival = &pbresource.Type{ + Group: "demo", + GroupVersion: "v2", + Kind: "Festival", + } ) const ( @@ -230,6 +237,17 @@ func RegisterTypes(r resource.Registry) { List: makeListACL(TypeV2Album), }, }) + + r.Register(resource.Registration{ + Type: TypeV2Festival, + Proto: &pbdemov2.Festival{}, + Scope: resource.ScopeNamespace, + ACLs: &resource.ACLHooks{ + Read: readACL, + Write: writeACL, + List: makeListACL(TypeV2Festival), + }, + }) } // GenerateV1Executive generates a named Executive resource. diff --git a/internal/resource/equality.go b/internal/resource/equality.go index 25e098b1a361..106d5a476a68 100644 --- a/internal/resource/equality.go +++ b/internal/resource/equality.go @@ -31,10 +31,11 @@ func EqualTenancy(a, b *pbresource.Tenancy) bool { } return a.Partition == b.Partition && - a.PeerName == b.PeerName && a.Namespace == b.Namespace } +// TODO(peering/v2) add equality method peer tenancy + // EqualID compares two resource IDs for equality without reflection. func EqualID(a, b *pbresource.ID) bool { if a == b { diff --git a/internal/resource/equality_test.go b/internal/resource/equality_test.go index 841390560638..f4c17d0ff55d 100644 --- a/internal/resource/equality_test.go +++ b/internal/resource/equality_test.go @@ -85,7 +85,6 @@ func TestEqualTenancy(t *testing.T) { t.Run("same pointer", func(t *testing.T) { ten := &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", } require.True(t, resource.EqualTenancy(ten, ten)) @@ -94,7 +93,6 @@ func TestEqualTenancy(t *testing.T) { t.Run("equal", func(t *testing.T) { a := &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", } b := clone(a) @@ -104,7 +102,6 @@ func TestEqualTenancy(t *testing.T) { t.Run("nil", func(t *testing.T) { a := &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", } require.False(t, resource.EqualTenancy(a, nil)) @@ -114,7 +111,6 @@ func TestEqualTenancy(t *testing.T) { t.Run("different Partition", func(t *testing.T) { a := &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", } b := clone(a) @@ -122,21 +118,9 @@ func TestEqualTenancy(t *testing.T) { require.False(t, resource.EqualTenancy(a, b)) }) - t.Run("different PeerName", func(t *testing.T) { - a := &pbresource.Tenancy{ - Partition: "foo", - PeerName: "bar", - Namespace: "baz", - } - b := clone(a) - b.PeerName = "qux" - require.False(t, resource.EqualTenancy(a, b)) - }) - t.Run("different Namespace", func(t *testing.T) { a := &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", } b := clone(a) @@ -155,7 +139,6 @@ func TestEqualID(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -173,7 +156,6 @@ func TestEqualID(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -192,7 +174,6 @@ func TestEqualID(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -211,7 +192,6 @@ func TestEqualID(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -231,7 +211,6 @@ func TestEqualID(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -251,7 +230,6 @@ func TestEqualID(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -271,7 +249,6 @@ func TestEqualID(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -281,6 +258,8 @@ func TestEqualID(t *testing.T) { b.Uid = ulid.Make().String() require.False(t, resource.EqualID(a, b)) }) + + // TODO(peering/v2) Add test for when the peer tenancy of an object differs } func TestEqualReference(t *testing.T) { @@ -293,7 +272,6 @@ func TestEqualReference(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -311,7 +289,6 @@ func TestEqualReference(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -330,7 +307,6 @@ func TestEqualReference(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -349,7 +325,6 @@ func TestEqualReference(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -369,7 +344,6 @@ func TestEqualReference(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -389,7 +363,6 @@ func TestEqualReference(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -409,7 +382,6 @@ func TestEqualReference(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -419,6 +391,8 @@ func TestEqualReference(t *testing.T) { b.Section = "not-blah" require.False(t, resource.EqualReference(a, b)) }) + + // TODO(peering/v2) add test for peer tenancies differing } func TestReferenceOrIDMatch(t *testing.T) { @@ -431,7 +405,6 @@ func TestReferenceOrIDMatch(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -445,7 +418,6 @@ func TestReferenceOrIDMatch(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -463,7 +435,6 @@ func TestReferenceOrIDMatch(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -477,7 +448,6 @@ func TestReferenceOrIDMatch(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -496,7 +466,6 @@ func TestReferenceOrIDMatch(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -510,7 +479,6 @@ func TestReferenceOrIDMatch(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -529,7 +497,6 @@ func TestReferenceOrIDMatch(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -543,7 +510,6 @@ func TestReferenceOrIDMatch(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -562,7 +528,6 @@ func TestReferenceOrIDMatch(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -576,7 +541,6 @@ func TestReferenceOrIDMatch(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -585,6 +549,8 @@ func TestReferenceOrIDMatch(t *testing.T) { b.Name = "boom" require.False(t, resource.ReferenceOrIDMatch(a, b)) }) + + // TODO(peering/v2) Add tests for peer tenancy matching } func TestEqualStatus(t *testing.T) { @@ -604,7 +570,6 @@ func TestEqualStatus(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo-partition", - PeerName: "foo-peer-name", Namespace: "foo-namespace", }, Name: "foo-name", @@ -666,6 +631,8 @@ func TestEqualStatus(t *testing.T) { "different Condition.Resource.Section": func(s *pbresource.Status) { s.Conditions[0].Resource.Section = "bar-section" }, + + // TODO(peering/v2) Add tests for non-local peers in the resource ref } for desc, modFn := range testCases { t.Run(desc, func(t *testing.T) { @@ -842,12 +809,10 @@ func BenchmarkEqualTenancy(b *testing.B) { // BenchmarkEqualTenancy/reflection-16 2283500 550.3 ns/op 128 B/op 7 allocs/op tenA := &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", } tenB := &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "qux", } b.ResetTimer() @@ -877,7 +842,6 @@ func BenchmarkEqualID(b *testing.B) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo", - PeerName: "bar", Namespace: "baz", }, Name: "qux", @@ -920,7 +884,6 @@ func BenchmarkEqualStatus(b *testing.B) { }, Tenancy: &pbresource.Tenancy{ Partition: "foo-partition", - PeerName: "foo-peer-name", Namespace: "foo-namespace", }, Name: "foo-name", diff --git a/internal/resource/errors.go b/internal/resource/errors.go index 24dd96e90ec4..00f073d8f29a 100644 --- a/internal/resource/errors.go +++ b/internal/resource/errors.go @@ -139,22 +139,22 @@ type ErrOwnerTenantInvalid struct { func (err ErrOwnerTenantInvalid) Error() string { if err.ResourceTenancy == nil && err.OwnerTenancy != nil { return fmt.Sprintf( - "empty resource tenancy cannot be owned by a resource in partition %s, namespace %s and peer %s", - err.OwnerTenancy.Partition, err.OwnerTenancy.Namespace, err.OwnerTenancy.PeerName, + "empty resource tenancy cannot be owned by a resource in partition %s and namespace %s", + err.OwnerTenancy.Partition, err.OwnerTenancy.Namespace, ) } if err.ResourceTenancy != nil && err.OwnerTenancy == nil { return fmt.Sprintf( - "resource in partition %s, namespace %s and peer %s cannot be owned by a resource with empty tenancy", - err.ResourceTenancy.Partition, err.ResourceTenancy.Namespace, err.ResourceTenancy.PeerName, + "resource in partition %s and namespace %s cannot be owned by a resource with empty tenancy", + err.ResourceTenancy.Partition, err.ResourceTenancy.Namespace, ) } return fmt.Sprintf( - "resource in partition %s, namespace %s and peer %s cannot be owned by a resource in partition %s, namespace %s and peer %s", - err.ResourceTenancy.Partition, err.ResourceTenancy.Namespace, err.ResourceTenancy.PeerName, - err.OwnerTenancy.Partition, err.OwnerTenancy.Namespace, err.OwnerTenancy.PeerName, + "resource in partition %s and namespace %s cannot be owned by a resource in partition %s and namespace %s", + err.ResourceTenancy.Partition, err.ResourceTenancy.Namespace, + err.OwnerTenancy.Partition, err.OwnerTenancy.Namespace, ) } diff --git a/internal/resource/filter.go b/internal/resource/filter.go index 44a368929357..09e251e218bf 100644 --- a/internal/resource/filter.go +++ b/internal/resource/filter.go @@ -11,6 +11,10 @@ import ( "github.com/hashicorp/consul/proto-public/pbresource" ) +type MetadataFilterableResources interface { + GetMetadata() map[string]string +} + // FilterResourcesByMetadata will use the provided go-bexpr based filter to // retain matching items from the provided slice. // @@ -18,7 +22,7 @@ import ( // by "metadata." // // If no filter is provided, then this does nothing and returns the input. -func FilterResourcesByMetadata(resources []*pbresource.Resource, filter string) ([]*pbresource.Resource, error) { +func FilterResourcesByMetadata[T MetadataFilterableResources](resources []T, filter string) ([]T, error) { if filter == "" || len(resources) == 0 { return resources, nil } @@ -28,10 +32,10 @@ func FilterResourcesByMetadata(resources []*pbresource.Resource, filter string) return nil, err } - filtered := make([]*pbresource.Resource, 0, len(resources)) + filtered := make([]T, 0, len(resources)) for _, res := range resources { vars := &metadataFilterFieldDetails{ - Meta: res.Metadata, + Meta: res.GetMetadata(), } match, err := eval.Evaluate(vars) if err != nil { diff --git a/internal/resource/http/http.go b/internal/resource/http/http.go index fd5d6adb7979..6be00596694b 100644 --- a/internal/resource/http/http.go +++ b/internal/resource/http/http.go @@ -28,7 +28,14 @@ const ( HeaderConsistencyMode = "x-consul-consistency-mode" ) +// NewHandler creates a new HTTP handler for the resource service. +// httpPathPrefix is the prefix to be used for all HTTP endpoints. Should start with "/" and +// end without a trailing "/". +// client is the gRPC client to be used to communicate with the resource service. +// registry is the resource registry to be used to determine the resource types. +// parseToken is a function that will be called to parse the Consul token from the request. func NewHandler( + httpPathPrefix string, client pbresource.ResourceServiceClient, registry resource.Registry, parseToken func(req *http.Request, token *string), @@ -38,10 +45,10 @@ func NewHandler( // List Endpoint base := strings.ToLower(fmt.Sprintf("/%s/%s/%s", t.Type.Group, t.Type.GroupVersion, t.Type.Kind)) mux.Handle(base, http.StripPrefix(base, &listHandler{t, client, parseToken, logger})) + logger.Info("Registered resource endpoint", "endpoint", fmt.Sprintf("%s%s", httpPathPrefix, base)) // Individual Resource Endpoints prefix := strings.ToLower(fmt.Sprintf("%s/", base)) - logger.Info("Registered resource endpoint", "endpoint", prefix) mux.Handle(prefix, http.StripPrefix(prefix, &resourceHandler{t, client, parseToken, logger})) } @@ -184,16 +191,14 @@ func parseParams(r *http.Request) (tenancy *pbresource.Tenancy, params map[strin if namespace == "" { namespace = query.Get("ns") } - peer := query.Get("peer") - if peer == "" { - peer = query.Get("peer_name") - } + tenancy = &pbresource.Tenancy{ Partition: query.Get("partition"), - PeerName: peer, Namespace: namespace, } + // TODO(peering/v2) handle parsing peer tenancy + resourceName := path.Base(r.URL.Path) if resourceName == "." || resourceName == "/" { resourceName = "" diff --git a/internal/resource/http/http_test.go b/internal/resource/http/http_test.go index aeb85f0b8332..aae02c694ac8 100644 --- a/internal/resource/http/http_test.go +++ b/internal/resource/http/http_test.go @@ -12,17 +12,17 @@ import ( "strings" "testing" - "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - resourceSvc "github.com/hashicorp/consul/agent/grpc-external/services/resource" - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - pbdemov1 "github.com/hashicorp/consul/proto/private/pbdemo/v1" + "github.com/hashicorp/go-hclog" + svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/proto-public/pbresource" + pbdemov1 "github.com/hashicorp/consul/proto/private/pbdemo/v1" pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2" "github.com/hashicorp/consul/sdk/testutil" ) @@ -44,7 +44,11 @@ func TestResourceHandler_InputValidation(t *testing.T) { expectedResponseCode int responseBodyContains string } - client := svctest.RunResourceService(t, demo.RegisterTypes) + + client := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + Run(t) + resourceHandler := resourceHandler{ resource.Registration{ Type: demo.TypeV2Artist, @@ -125,17 +129,17 @@ func TestResourceHandler_InputValidation(t *testing.T) { } func TestResourceWriteHandler(t *testing.T) { - aclResolver := &resourceSvc.MockACLResolver{} + aclResolver := &svc.MockACLResolver{} aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistReadPolicy, mock.Anything, mock.Anything). Return(svctest.AuthorizerFrom(t, demo.ArtistV1ReadPolicy, demo.ArtistV2ReadPolicy), nil) aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistWritePolicy, mock.Anything, mock.Anything). Return(svctest.AuthorizerFrom(t, demo.ArtistV1WritePolicy, demo.ArtistV2WritePolicy), nil) - client := svctest.RunResourceServiceWithConfig(t, resourceSvc.Config{ACLResolver: aclResolver}, demo.RegisterTypes) - - r := resource.NewRegistry() - demo.RegisterTypes(r) - handler := NewHandler(client, r, parseToken, hclog.NewNullLogger()) + builder := svctest.NewResourceServiceBuilder(). + WithACLResolver(aclResolver). + WithRegisterFns(demo.RegisterTypes) + client := builder.Run(t) + handler := NewHandler("/api", client, builder.Registry(), parseToken, hclog.NewNullLogger()) t.Run("should be blocked if the token is not authorized", func(t *testing.T) { rsp := httptest.NewRecorder() @@ -157,6 +161,7 @@ func TestResourceWriteHandler(t *testing.T) { require.Equal(t, http.StatusForbidden, rsp.Result().StatusCode) }) + var readRsp *pbresource.ReadResponse t.Run("should write to the resource backend", func(t *testing.T) { rsp := httptest.NewRecorder() @@ -265,7 +270,6 @@ func TestResourceWriteHandler(t *testing.T) { }, "tenancy": { "partition": "default", - "peer_name": "local", "namespace": "default" } } @@ -352,7 +356,7 @@ func deleteResource(t *testing.T, artistHandler http.Handler, resourceUri *Resou } func TestResourceReadHandler(t *testing.T) { - aclResolver := &resourceSvc.MockACLResolver{} + aclResolver := &svc.MockACLResolver{} aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistReadPolicy, mock.Anything, mock.Anything). Return(svctest.AuthorizerFrom(t, demo.ArtistV1ReadPolicy, demo.ArtistV2ReadPolicy), nil) aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistWritePolicy, mock.Anything, mock.Anything). @@ -360,11 +364,11 @@ func TestResourceReadHandler(t *testing.T) { aclResolver.On("ResolveTokenAndDefaultMeta", fakeToken, mock.Anything, mock.Anything). Return(svctest.AuthorizerFrom(t, ""), nil) - client := svctest.RunResourceServiceWithConfig(t, resourceSvc.Config{ACLResolver: aclResolver}, demo.RegisterTypes) - - r := resource.NewRegistry() - demo.RegisterTypes(r) - handler := NewHandler(client, r, parseToken, hclog.NewNullLogger()) + builder := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + WithACLResolver(aclResolver) + client := builder.Run(t) + handler := NewHandler("/api", client, builder.Registry(), parseToken, hclog.NewNullLogger()) createdResource := createResource(t, handler, nil) @@ -407,18 +411,17 @@ func TestResourceReadHandler(t *testing.T) { } func TestResourceDeleteHandler(t *testing.T) { - aclResolver := &resourceSvc.MockACLResolver{} + aclResolver := &svc.MockACLResolver{} aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistReadPolicy, mock.Anything, mock.Anything). Return(svctest.AuthorizerFrom(t, demo.ArtistV2ReadPolicy), nil) aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistWritePolicy, mock.Anything, mock.Anything). Return(svctest.AuthorizerFrom(t, demo.ArtistV2WritePolicy), nil) - client := svctest.RunResourceServiceWithConfig(t, resourceSvc.Config{ACLResolver: aclResolver}, demo.RegisterTypes) - - r := resource.NewRegistry() - demo.RegisterTypes(r) - - handler := NewHandler(client, r, parseToken, hclog.NewNullLogger()) + builder := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + WithACLResolver(aclResolver) + client := builder.Run(t) + handler := NewHandler("/api", client, builder.Registry(), parseToken, hclog.NewNullLogger()) t.Run("should surface PermissionDenied error from resource service", func(t *testing.T) { createResource(t, handler, nil) @@ -484,18 +487,17 @@ func TestResourceDeleteHandler(t *testing.T) { } func TestResourceListHandler(t *testing.T) { - aclResolver := &resourceSvc.MockACLResolver{} + aclResolver := &svc.MockACLResolver{} aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistListPolicy, mock.Anything, mock.Anything). Return(svctest.AuthorizerFrom(t, demo.ArtistV2ListPolicy), nil) aclResolver.On("ResolveTokenAndDefaultMeta", testACLTokenArtistWritePolicy, mock.Anything, mock.Anything). Return(svctest.AuthorizerFrom(t, demo.ArtistV2WritePolicy), nil) - client := svctest.RunResourceServiceWithConfig(t, resourceSvc.Config{ACLResolver: aclResolver}, demo.RegisterTypes) - - r := resource.NewRegistry() - demo.RegisterTypes(r) - - handler := NewHandler(client, r, parseToken, hclog.NewNullLogger()) + builder := svctest.NewResourceServiceBuilder(). + WithRegisterFns(demo.RegisterTypes). + WithACLResolver(aclResolver) + client := builder.Run(t) + handler := NewHandler("/api", client, builder.Registry(), parseToken, hclog.NewNullLogger()) t.Run("should return MethodNotAllowed", func(t *testing.T) { rsp := httptest.NewRecorder() diff --git a/internal/resource/mappers/selectiontracker/selection_tracker.go b/internal/resource/mappers/selectiontracker/selection_tracker.go deleted file mode 100644 index 5b60680bb546..000000000000 --- a/internal/resource/mappers/selectiontracker/selection_tracker.go +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package selectiontracker - -import ( - "context" - "fmt" - "sync" - - "golang.org/x/exp/slices" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/radix" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/lib/stringslice" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type WorkloadSelectionTracker struct { - lock sync.Mutex - prefixes *radix.Tree[[]*pbresource.ID] - exact *radix.Tree[[]*pbresource.ID] - - // workloadSelectors contains a map keyed on resource references with values - // being the selector that resource is currently associated with. This map - // is kept mainly to make tracking removal operations more efficient. - // Generally any operation that could take advantage of knowing where - // in the trees the resource id is referenced can use this to prevent - // needing to search the whole tree. - workloadSelectors map[resource.ReferenceKey]*pbcatalog.WorkloadSelector -} - -func New() *WorkloadSelectionTracker { - return &WorkloadSelectionTracker{ - prefixes: radix.New[[]*pbresource.ID](), - exact: radix.New[[]*pbresource.ID](), - workloadSelectors: make(map[resource.ReferenceKey]*pbcatalog.WorkloadSelector), - } -} - -// MapWorkload will return a slice of controller.Requests with 1 resource for -// each resource that selects the specified Workload resource. -func (t *WorkloadSelectionTracker) MapWorkload(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { - resIds := t.GetIDsForWorkload(res.Id) - - return controller.MakeRequests(nil, resIds), nil -} - -func (t *WorkloadSelectionTracker) GetIDsForWorkload(id *pbresource.ID) []*pbresource.ID { - t.lock.Lock() - defer t.lock.Unlock() - - var result []*pbresource.ID - - workloadTreeKey := treePathFromNameOrPrefix(id.GetTenancy(), id.GetName()) - - // gather the list of all resources that select the specified workload using a prefix match - t.prefixes.WalkPath(workloadTreeKey, func(path string, ids []*pbresource.ID) bool { - result = append(result, ids...) - return false - }) - - // gather the list of all resources that select the specified workload using an exact match - exactReqs, _ := t.exact.Get(workloadTreeKey) - - // return the combined list of all resources that select the specified workload - return append(result, exactReqs...) -} - -// TrackIDForSelector will associate workloads matching the specified workload -// selector with the given resource id. -func (t *WorkloadSelectionTracker) TrackIDForSelector(id *pbresource.ID, selector *pbcatalog.WorkloadSelector) { - t.lock.Lock() - defer t.lock.Unlock() - - ref := resource.NewReferenceKey(id) - if previousSelector, found := t.workloadSelectors[ref]; found { - if stringslice.Equal(previousSelector.Names, selector.Names) && - stringslice.Equal(previousSelector.Prefixes, selector.Prefixes) { - // the selector is unchanged so do nothing - return - } - - // Potentially we could detect differences and do more minimal work. However - // users are not expected to alter workload selectors often and therefore - // not optimizing this further is probably fine. Therefore we are going - // to wipe all tracking of the id and reinsert things. - t.untrackID(id) - } - - // loop over all the exact matching rules and associate those workload names - // with the given resource id - for _, name := range selector.GetNames() { - key := treePathFromNameOrPrefix(id.GetTenancy(), name) - - // lookup any resource id associations for the given workload name - leaf, _ := t.exact.Get(key) - - // append the ID to the existing request list - t.exact.Insert(key, append(leaf, id)) - } - - // loop over all the prefix matching rules and associate those prefixes - // with the given resource id. - for _, prefix := range selector.GetPrefixes() { - key := treePathFromNameOrPrefix(id.GetTenancy(), prefix) - - // lookup any resource id associations for the given workload name prefix - leaf, _ := t.prefixes.Get(key) - - // append the new resource ID to the existing request list - t.prefixes.Insert(key, append(leaf, id)) - } - - t.workloadSelectors[ref] = selector -} - -// UntrackID causes the tracker to stop tracking the given resource ID -func (t *WorkloadSelectionTracker) UntrackID(id *pbresource.ID) { - t.lock.Lock() - defer t.lock.Unlock() - t.untrackID(id) -} - -// GetSelector returns the currently stored selector for the given ID. -func (t *WorkloadSelectionTracker) GetSelector(id *pbresource.ID) *pbcatalog.WorkloadSelector { - t.lock.Lock() - defer t.lock.Unlock() - - return t.workloadSelectors[resource.NewReferenceKey(id)] -} - -// untrackID should be called to stop tracking a resource ID. -// This method assumes the lock is already held. Besides modifying -// the prefix & name trees to not reference this ID, it will also -// delete any corresponding entry within the workloadSelectors map -func (t *WorkloadSelectionTracker) untrackID(id *pbresource.ID) { - ref := resource.NewReferenceKey(id) - selector, found := t.workloadSelectors[ref] - if !found { - return - } - - exactTreePaths := make([]string, len(selector.GetNames())) - for i, name := range selector.GetNames() { - exactTreePaths[i] = treePathFromNameOrPrefix(id.GetTenancy(), name) - } - - prefixTreePaths := make([]string, len(selector.GetPrefixes())) - for i, prefix := range selector.GetPrefixes() { - prefixTreePaths[i] = treePathFromNameOrPrefix(id.GetTenancy(), prefix) - } - - removeIDFromTreeAtPaths(t.exact, id, exactTreePaths) - removeIDFromTreeAtPaths(t.prefixes, id, prefixTreePaths) - - // If we don't do this deletion then reinsertion of the id for - // tracking in the future could prevent selection criteria from - // being properly inserted into the radix trees. - delete(t.workloadSelectors, ref) -} - -// removeIDFromTree will remove the given resource ID from all leaf nodes in the radix tree. -func removeIDFromTreeAtPaths(t *radix.Tree[[]*pbresource.ID], id *pbresource.ID, paths []string) { - for _, path := range paths { - ids, _ := t.Get(path) - - foundIdx := -1 - for idx, resID := range ids { - if resource.EqualID(resID, id) { - foundIdx = idx - break - } - } - - if foundIdx != -1 { - l := len(ids) - - if foundIdx == l-1 { - ids = ids[:foundIdx] - } else { - ids = slices.Delete(ids, foundIdx, foundIdx+1) - } - - if len(ids) > 0 { - t.Insert(path, ids) - } else { - t.Delete(path) - } - } - } -} - -// treePathFromNameOrPrefix computes radix tree key from the resource tenancy and a selector name or prefix. -// The keys will be computed in the following form: -// ///. -func treePathFromNameOrPrefix(tenancy *pbresource.Tenancy, nameOrPrefix string) string { - return fmt.Sprintf("%s/%s/%s/%s", - tenancy.GetPartition(), - tenancy.GetPeerName(), - tenancy.GetNamespace(), - nameOrPrefix) -} diff --git a/internal/resource/mappers/selectiontracker/selection_tracker_test.go b/internal/resource/mappers/selectiontracker/selection_tracker_test.go deleted file mode 100644 index 345ac848ab40..000000000000 --- a/internal/resource/mappers/selectiontracker/selection_tracker_test.go +++ /dev/null @@ -1,383 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package selectiontracker - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/radix" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/proto/private/prototest" -) - -var ( - workloadData = &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - { - Host: "198.18.0.1", - }, - }, - Ports: map[string]*pbcatalog.WorkloadPort{ - "http": { - Port: 8080, - Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, - }, - }, - } - - tenancyCases = map[string]*pbresource.Tenancy{ - "default": resource.DefaultNamespacedTenancy(), - "bar ns, default partition, local peer": { - Partition: "default", - Namespace: "bar", - PeerName: "local", - }, - "default ns, baz partition, local peer": { - Partition: "baz", - Namespace: "default", - PeerName: "local", - }, - "bar ns, baz partition, local peer": { - Partition: "baz", - Namespace: "bar", - PeerName: "local", - }, - "bar ns, baz partition, non-local peer": { - Partition: "baz", - Namespace: "bar", - PeerName: "non-local", - }, - } -) - -func TestRemoveIDFromTreeAtPaths(t *testing.T) { - tree := radix.New[[]*pbresource.ID]() - - tenancy := resource.DefaultNamespacedTenancy() - toRemove := rtest.Resource(pbcatalog.ServiceEndpointsType, "blah").WithTenancy(tenancy).ID() - other1 := rtest.Resource(pbcatalog.ServiceEndpointsType, "other1").WithTenancy(tenancy).ID() - other2 := rtest.Resource(pbcatalog.ServiceEndpointsType, "other2").WithTenancy(tenancy).ID() - - // we are trying to create a tree such that removal of the toRemove id causes a - // few things to happen. - // - // * All the slice modification conditions are executed - // - removal from beginning of the list - // - removal from the end of the list - // - removal of only element in the list - // - removal from middle of the list - // * Paths without matching ids are ignored - - notMatching := []*pbresource.ID{ - other1, - other2, - } - - matchAtBeginning := []*pbresource.ID{ - toRemove, - other1, - other2, - } - - // For this case, we only add one other not matching to test that we don't remove - // non-matching ones. - matchAtEnd := []*pbresource.ID{ - other1, - toRemove, - } - - matchInMiddle := []*pbresource.ID{ - other1, - toRemove, - other2, - } - - matchOnly := []*pbresource.ID{ - toRemove, - } - - noMatchKey := treePathFromNameOrPrefix(tenancy, "no-match") - matchBeginningKey := treePathFromNameOrPrefix(tenancy, "match-beginning") - matchEndKey := treePathFromNameOrPrefix(tenancy, "match-end") - matchMiddleKey := treePathFromNameOrPrefix(tenancy, "match-middle") - matchOnlyKey := treePathFromNameOrPrefix(tenancy, "match-only") - - tree.Insert(noMatchKey, notMatching) - tree.Insert(matchBeginningKey, matchAtBeginning) - tree.Insert(matchEndKey, matchAtEnd) - tree.Insert(matchMiddleKey, matchInMiddle) - tree.Insert(matchOnlyKey, matchOnly) - - removeIDFromTreeAtPaths(tree, toRemove, []string{ - noMatchKey, - matchBeginningKey, - matchEndKey, - matchMiddleKey, - matchOnlyKey, - }) - - reqs, found := tree.Get(noMatchKey) - require.True(t, found) - require.Equal(t, notMatching, reqs) - - reqs, found = tree.Get(matchBeginningKey) - require.True(t, found) - require.Equal(t, notMatching, reqs) - - reqs, found = tree.Get(matchEndKey) - require.True(t, found) - require.Equal(t, []*pbresource.ID{other1}, reqs) - - reqs, found = tree.Get(matchMiddleKey) - require.True(t, found) - require.Equal(t, notMatching, reqs) - - // The last tracked request should cause removal from the tree - _, found = tree.Get(matchOnlyKey) - require.False(t, found) -} - -type selectionTrackerSuite struct { - suite.Suite - - rt controller.Runtime - tracker *WorkloadSelectionTracker - - // The test setup adds resources with various tenancy settings. Because tenancies are stored in a map, - // it adds "free" order randomization, and so we need to remember the order in which those tenancy were executed. - executedTenancies []*pbresource.Tenancy - - endpointsFoo []*pbresource.ID - endpointsBar []*pbresource.ID - workloadsAPI []*pbresource.Resource - workloadsWeb []*pbresource.Resource -} - -func (suite *selectionTrackerSuite) SetupTest() { - suite.tracker = New() - - for _, tenancy := range tenancyCases { - suite.executedTenancies = append(suite.executedTenancies, tenancy) - - endpointsFooID := rtest.Resource(pbcatalog.ServiceEndpointsType, "foo"). - WithTenancy(tenancy).ID() - suite.endpointsFoo = append(suite.endpointsFoo, endpointsFooID) - - endpointsBarID := rtest.Resource(pbcatalog.ServiceEndpointsType, "bar"). - WithTenancy(tenancy).ID() - suite.endpointsBar = append(suite.endpointsBar, endpointsBarID) - - suite.workloadsAPI = append(suite.workloadsAPI, rtest.Resource(pbcatalog.WorkloadType, "api-1"). - WithData(suite.T(), workloadData). - WithTenancy(tenancy). - Build()) - suite.workloadsWeb = append(suite.workloadsWeb, rtest.Resource(pbcatalog.WorkloadType, "web-1"). - WithData(suite.T(), workloadData). - WithTenancy(tenancy). - Build()) - } -} - -func (suite *selectionTrackerSuite) TearDownTest() { - suite.executedTenancies = nil - suite.workloadsAPI = nil - suite.workloadsWeb = nil - suite.endpointsFoo = nil - suite.endpointsBar = nil -} - -func (suite *selectionTrackerSuite) requireMappedIDs(t *testing.T, workload *pbresource.Resource, ids ...*pbresource.ID) { - t.Helper() - - reqs, err := suite.tracker.MapWorkload(context.Background(), suite.rt, workload) - require.NoError(suite.T(), err) - require.Len(t, reqs, len(ids)) - for _, id := range ids { - prototest.AssertContainsElement(t, reqs, controller.Request{ID: id}) - } -} - -func (suite *selectionTrackerSuite) requireMappedIDsAllTenancies(t *testing.T, workloads []*pbresource.Resource, ids ...[]*pbresource.ID) { - t.Helper() - - for i := range suite.executedTenancies { - reqs, err := suite.tracker.MapWorkload(context.Background(), suite.rt, workloads[i]) - require.NoError(suite.T(), err) - require.Len(t, reqs, len(ids)) - for _, id := range ids { - prototest.AssertContainsElement(t, reqs, controller.Request{ID: id[i]}) - } - } -} - -func (suite *selectionTrackerSuite) trackIDForSelectorInAllTenancies(ids []*pbresource.ID, selector *pbcatalog.WorkloadSelector) { - suite.T().Helper() - - for i := range suite.executedTenancies { - suite.tracker.TrackIDForSelector(ids[i], selector) - } -} - -func (suite *selectionTrackerSuite) TestMapWorkload_Empty() { - // If we aren't tracking anything than the default mapping behavior - // should be to return an empty list of requests. - suite.requireMappedIDs(suite.T(), - rtest.Resource(pbcatalog.WorkloadType, "api-1").WithData(suite.T(), workloadData).Build()) -} - -func (suite *selectionTrackerSuite) TestUntrackID_Empty() { - // this test has no assertions but mainly is here to prove that things - // don't explode if this is attempted. - suite.tracker.UntrackID(rtest.Resource(pbcatalog.ServiceEndpointsType, "foo").ID()) -} - -func (suite *selectionTrackerSuite) TestTrackAndMap_SingleResource_MultipleWorkloadMappings() { - // This test aims to prove that tracking a resources workload selector and - // then mapping a workload back to that resource works as expected when the - // result set is a single resource. This test will ensure that both prefix - // and exact match criteria are handle correctly and that one resource - // can be mapped from multiple distinct workloads. - - // Create resources for the test and track endpoints. - suite.trackIDForSelectorInAllTenancies(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ - Names: []string{"bar", "api", "web-1"}, - Prefixes: []string{"api-"}, - }) - - suite.requireMappedIDsAllTenancies(suite.T(), suite.workloadsAPI, suite.endpointsFoo) - suite.requireMappedIDsAllTenancies(suite.T(), suite.workloadsWeb, suite.endpointsFoo) -} - -func (suite *selectionTrackerSuite) TestTrackAndMap_MultiResource_SingleWorkloadMapping() { - // This test aims to prove that multiple resources selecting of a workload - // will result in multiple requests when mapping that workload. - - cases := map[string]struct { - selector *pbcatalog.WorkloadSelector - }{ - "names": { - selector: &pbcatalog.WorkloadSelector{ - Names: []string{"api-1"}, - }, - }, - "prefixes": { - selector: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api"}, - }, - }, - } - - for name, c := range cases { - suite.T().Run(name, func(t *testing.T) { - for i := range suite.executedTenancies { - // associate the foo endpoints with some workloads - suite.tracker.TrackIDForSelector(suite.endpointsFoo[i], c.selector) - - // associate the bar endpoints with some workloads - suite.tracker.TrackIDForSelector(suite.endpointsBar[i], c.selector) - } - - // now the mapping should return both endpoints resource ids - suite.requireMappedIDsAllTenancies(t, suite.workloadsAPI, suite.endpointsFoo, suite.endpointsBar) - }) - } -} - -func (suite *selectionTrackerSuite) TestDuplicateTracking() { - // This test aims to prove that tracking some ID multiple times doesn't - // result in multiple requests for the same ID - - // associate the foo endpoints with some workloads 3 times without changing - // the selection criteria. The second two times should be no-ops - workloadAPI1 := rtest.Resource(pbcatalog.WorkloadType, "api-1"). - WithTenancy(resource.DefaultNamespacedTenancy()). - WithData(suite.T(), workloadData).Build() - endpointsFoo := rtest.Resource(pbcatalog.ServiceEndpointsType, "foo"). - WithTenancy(resource.DefaultNamespacedTenancy()).ID() - - suite.tracker.TrackIDForSelector(endpointsFoo, &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }) - - suite.tracker.TrackIDForSelector(endpointsFoo, &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }) - - suite.tracker.TrackIDForSelector(endpointsFoo, &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }) - - // regardless of the number of times tracked we should only see a single request - suite.requireMappedIDs(suite.T(), workloadAPI1, endpointsFoo) -} - -func (suite *selectionTrackerSuite) TestModifyTracking() { - // This test aims to prove that modifying selection criteria for a resource - // works as expected. Adding new criteria results in all being tracked. - // Removal of some criteria doesn't result in removal of all etc. More or - // less we want to ensure that updating selection criteria leaves the - // tracker in a consistent/expected state. - - // Create resources for the test and track endpoints. - suite.trackIDForSelectorInAllTenancies(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ - Names: []string{"web-1"}, - }) - - // ensure that api-1 isn't mapped but web-1 is - suite.requireMappedIDsAllTenancies(suite.T(), suite.workloadsAPI) - suite.requireMappedIDsAllTenancies(suite.T(), suite.workloadsWeb, suite.endpointsFoo) - - // now also track the api- prefix - suite.trackIDForSelectorInAllTenancies(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ - Names: []string{"web-1"}, - Prefixes: []string{"api-"}, - }) - - // ensure that both workloads are mapped appropriately - suite.requireMappedIDsAllTenancies(suite.T(), suite.workloadsAPI, suite.endpointsFoo) - suite.requireMappedIDsAllTenancies(suite.T(), suite.workloadsWeb, suite.endpointsFoo) - - // now remove the web tracking - suite.trackIDForSelectorInAllTenancies(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ - Prefixes: []string{"api-"}, - }) - - // ensure that only api-1 is mapped - suite.requireMappedIDsAllTenancies(suite.T(), suite.workloadsAPI, suite.endpointsFoo) - suite.requireMappedIDsAllTenancies(suite.T(), suite.workloadsWeb) -} - -func (suite *selectionTrackerSuite) TestRemove() { - // This test aims to prove that removal of a resource from tracking - // actually prevents subsequent mapping calls from returning the - // workload. - - // track the web-1 workload - suite.trackIDForSelectorInAllTenancies(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ - Names: []string{"web-1"}, - }) - - // ensure web-1 is mapped - suite.requireMappedIDsAllTenancies(suite.T(), suite.workloadsWeb, suite.endpointsFoo) - - for i := range suite.executedTenancies { - // untrack the resource - suite.tracker.UntrackID(suite.endpointsFoo[i]) - } - - // ensure that we no longer map the previous workload to the resource - suite.requireMappedIDsAllTenancies(suite.T(), suite.workloadsWeb) -} - -func TestWorkloadSelectionSuite(t *testing.T) { - suite.Run(t, new(selectionTrackerSuite)) -} diff --git a/internal/resource/protoc-gen-resource-types/internal/generate/generate.go b/internal/resource/protoc-gen-resource-types/internal/generate/generate.go index 3d74077da93b..0e1b6ddc29d8 100644 --- a/internal/resource/protoc-gen-resource-types/internal/generate/generate.go +++ b/internal/resource/protoc-gen-resource-types/internal/generate/generate.go @@ -68,7 +68,7 @@ func (g *generator) addResourceKindsFromFile(f *protogen.File) error { continue } - gvkString := strings.TrimPrefix(string(m.Desc.FullName()), "hashicorp.consul.") + gvkString := strings.TrimPrefix(strings.TrimPrefix(string(m.Desc.FullName()), "hashicorp.consul."), "internal.") rtype, err := resource.ParseGVK(gvkString) if err != nil { return err @@ -113,7 +113,7 @@ func (g *generator) ensureAPIGroup(gv apiGroupVersion, importPath protogen.GoImp func (g *generator) generateTypes(gp *protogen.Plugin) error { for _, info := range g.resources { - f := gp.NewGeneratedFile(filepath.Join(info.Directory, "resource_types.gen.go"), info.ImportPath) + f := gp.NewGeneratedFile(filepath.Join(info.Directory, "resources.rtypes.go"), info.ImportPath) sort.Slice(info.Kinds, func(a, b int) bool { return info.Kinds[a].Name < info.Kinds[b].Name diff --git a/internal/resource/reaper/controller.go b/internal/resource/reaper/controller.go index f8de86f92196..27337c7b2063 100644 --- a/internal/resource/reaper/controller.go +++ b/internal/resource/reaper/controller.go @@ -7,11 +7,12 @@ import ( "context" "time" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "github.com/hashicorp/consul/internal/controller" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) const ( @@ -25,8 +26,8 @@ func RegisterControllers(mgr *controller.Manager) { mgr.Register(reaperController()) } -func reaperController() controller.Controller { - return controller.ForType(resource.TypeV1Tombstone). +func reaperController() *controller.Controller { + return controller.NewController(statusKeyReaperController, resource.TypeV1Tombstone). WithReconciler(newReconciler()) } diff --git a/internal/resource/reaper/controller_test.go b/internal/resource/reaper/controller_test.go index c06ccedab582..58ed2564fe3f 100644 --- a/internal/resource/reaper/controller_test.go +++ b/internal/resource/reaper/controller_test.go @@ -15,179 +15,209 @@ import ( "github.com/hashicorp/consul/internal/controller" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" + "github.com/hashicorp/consul/internal/resource/resourcetest" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/sdk/testutil" ) func TestReconcile_ResourceWithNoChildren(t *testing.T) { - client := svctest.RunResourceService(t, demo.RegisterTypes) - - // Seed the database with an artist. - res, err := demo.GenerateV2Artist() - require.NoError(t, err) - ctx := testutil.TestContext(t) - writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - - // Delete the artist to create a tombstone - _, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id}) - require.NoError(t, err) - - // Retrieve tombstone - listRsp, err := client.List(ctx, &pbresource.ListRequest{ - Type: resource.TypeV1Tombstone, - Tenancy: writeRsp.Resource.Id.Tenancy, + client := setupResourceService(t) + runReaperTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { + // Seed the database with an artist. + res, err := demo.GenerateV2Artist() + + // set resource tenancy from default to test tenancy + res.Id.Tenancy = tenancy + + require.NoError(t, err) + ctx := testutil.TestContext(t) + writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + // Delete the artist to create a tombstone + _, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id}) + require.NoError(t, err) + + // Retrieve tombstone + listRsp, err := client.List(ctx, &pbresource.ListRequest{ + Type: resource.TypeV1Tombstone, + Tenancy: tenancy, + }) + require.NoError(t, err) + require.Len(t, listRsp.Resources, 1) + tombstone := listRsp.Resources[0] + + // Verify reconcile does first pass and queues up for a second pass + rec := newReconciler() + runtime := controller.Runtime{ + Client: client, + Logger: testutil.Logger(t), + } + req := controller.Request{ID: tombstone.Id} + require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req)) + + // Verify condition FirstPassCompleted is true + readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id}) + require.NoError(t, err) + tombstone = readRsp.Resource + condition := tombstone.Status[statusKeyReaperController].Conditions[0] + require.Equal(t, conditionTypeFirstPassCompleted, condition.Type) + require.Equal(t, pbresource.Condition_STATE_TRUE, condition.State) + + // Verify reconcile does second pass and tombstone is deleted + // Fake out time so elapsed time > secondPassDelay + rec.timeNow = func() time.Time { return time.Now().Add(secondPassDelay + time.Second) } + require.NoError(t, rec.Reconcile(ctx, runtime, req)) + _, err = client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id}) + require.Error(t, err) + require.Equal(t, codes.NotFound.String(), status.Code(err).String()) + + // Reconcile again to verify no-op on an already deleted tombstone + require.NoError(t, rec.Reconcile(ctx, runtime, req)) }) - require.NoError(t, err) - require.Len(t, listRsp.Resources, 1) - tombstone := listRsp.Resources[0] - - // Verify reconcile does first pass and queues up for a second pass - rec := newReconciler() - runtime := controller.Runtime{ - Client: client, - Logger: testutil.Logger(t), - } - req := controller.Request{ID: tombstone.Id} - require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req)) - - // Verify condition FirstPassCompleted is true - readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id}) - require.NoError(t, err) - tombstone = readRsp.Resource - condition := tombstone.Status[statusKeyReaperController].Conditions[0] - require.Equal(t, conditionTypeFirstPassCompleted, condition.Type) - require.Equal(t, pbresource.Condition_STATE_TRUE, condition.State) - - // Verify reconcile does second pass and tombstone is deleted - // Fake out time so elapsed time > secondPassDelay - rec.timeNow = func() time.Time { return time.Now().Add(secondPassDelay + time.Second) } - require.NoError(t, rec.Reconcile(ctx, runtime, req)) - _, err = client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id}) - require.Error(t, err) - require.Equal(t, codes.NotFound.String(), status.Code(err).String()) - - // Reconcile again to verify no-op on an already deleted tombstone - require.NoError(t, rec.Reconcile(ctx, runtime, req)) } func TestReconcile_ResourceWithChildren(t *testing.T) { - client := svctest.RunResourceService(t, demo.RegisterTypes) + client := setupResourceService(t) + runReaperTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { + // Seed the database with an artist + res, err := demo.GenerateV2Artist() - // Seed the database with an artist - res, err := demo.GenerateV2Artist() - require.NoError(t, err) - ctx := testutil.TestContext(t) - writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - artist := writeRsp.Resource + // set resource tenancy from default to test tenancy + res.Id.Tenancy = tenancy - // Create 3 albums owned by the artist - numAlbums := 3 - for i := 0; i < numAlbums; i++ { - res, err = demo.GenerateV2Album(artist.Id) require.NoError(t, err) - _, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res}) + ctx := testutil.TestContext(t) + writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + artist := writeRsp.Resource + + // Create 3 albums owned by the artist + numAlbums := 3 + for i := 0; i < numAlbums; i++ { + res, err = demo.GenerateV2Album(artist.Id) + require.NoError(t, err) + _, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + } + + // Delete the artist to create a tombstone + _, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id}) require.NoError(t, err) - } - - // Delete the artist to create a tombstone - _, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id}) - require.NoError(t, err) - // Retrieve the tombstone - listRsp, err := client.List(ctx, &pbresource.ListRequest{ - Type: resource.TypeV1Tombstone, - Tenancy: writeRsp.Resource.Id.Tenancy, - }) - require.NoError(t, err) - require.Len(t, listRsp.Resources, 1) - tombstone := listRsp.Resources[0] - - // Verify reconcile does first pass delete and queues up for a second pass - rec := newReconciler() - runtime := controller.Runtime{ - Client: client, - Logger: testutil.Logger(t), - } - req := controller.Request{ID: tombstone.Id} - require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req)) + // Retrieve the tombstone + listRsp, err := client.List(ctx, &pbresource.ListRequest{ + Type: resource.TypeV1Tombstone, + Tenancy: writeRsp.Resource.Id.Tenancy, + }) + require.NoError(t, err) + require.Len(t, listRsp.Resources, 1) + tombstone := listRsp.Resources[0] + + // Verify reconcile does first pass delete and queues up for a second pass + rec := newReconciler() + runtime := controller.Runtime{ + Client: client, + Logger: testutil.Logger(t), + } + req := controller.Request{ID: tombstone.Id} + require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req)) + + // Verify 3 albums deleted + listRsp, err = client.List(ctx, &pbresource.ListRequest{ + Type: demo.TypeV2Album, + Tenancy: artist.Id.Tenancy, + }) + require.NoError(t, err) + require.Empty(t, listRsp.Resources) - // Verify 3 albums deleted - listRsp, err = client.List(ctx, &pbresource.ListRequest{ - Type: demo.TypeV2Album, - Tenancy: artist.Id.Tenancy, - }) - require.NoError(t, err) - require.Empty(t, listRsp.Resources) - - // Verify condition FirstPassCompleted is true - readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id}) - require.NoError(t, err) - tombstone = readRsp.Resource - condition := tombstone.Status[statusKeyReaperController].Conditions[0] - require.Equal(t, conditionTypeFirstPassCompleted, condition.Type) - require.Equal(t, pbresource.Condition_STATE_TRUE, condition.State) - - // Verify reconcile does second pass - // Fake out time so elapsed time > secondPassDelay - rec.timeNow = func() time.Time { return time.Now().Add(secondPassDelay + time.Second) } - require.NoError(t, rec.Reconcile(ctx, runtime, req)) - - // Verify artist tombstone deleted - _, err = client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id}) - require.Error(t, err) - require.Equal(t, codes.NotFound.String(), status.Code(err).String()) - - // Verify tombstones for 3 albums created - listRsp, err = client.List(ctx, &pbresource.ListRequest{ - Type: resource.TypeV1Tombstone, - Tenancy: artist.Id.Tenancy, + // Verify condition FirstPassCompleted is true + readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id}) + require.NoError(t, err) + tombstone = readRsp.Resource + condition := tombstone.Status[statusKeyReaperController].Conditions[0] + require.Equal(t, conditionTypeFirstPassCompleted, condition.Type) + require.Equal(t, pbresource.Condition_STATE_TRUE, condition.State) + + // Verify reconcile does second pass + // Fake out time so elapsed time > secondPassDelay + rec.timeNow = func() time.Time { return time.Now().Add(secondPassDelay + time.Second) } + require.NoError(t, rec.Reconcile(ctx, runtime, req)) + + // Verify artist tombstone deleted + _, err = client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id}) + require.Error(t, err) + require.Equal(t, codes.NotFound.String(), status.Code(err).String()) + + // Verify tombstones for 3 albums created + listRsp, err = client.List(ctx, &pbresource.ListRequest{ + Type: resource.TypeV1Tombstone, + Tenancy: artist.Id.Tenancy, + }) + require.NoError(t, err) + require.Len(t, listRsp.Resources, numAlbums) }) - require.NoError(t, err) - require.Len(t, listRsp.Resources, numAlbums) } func TestReconcile_RequeueWithDelayWhenSecondPassDelayNotElapsed(t *testing.T) { - client := svctest.RunResourceService(t, demo.RegisterTypes) - - // Seed the database with an artist. - res, err := demo.GenerateV2Artist() - require.NoError(t, err) - ctx := testutil.TestContext(t) - writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - - // Delete the artist to create a tombstone - _, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id}) - require.NoError(t, err) - - // Retrieve tombstone - listRsp, err := client.List(ctx, &pbresource.ListRequest{ - Type: resource.TypeV1Tombstone, - Tenancy: writeRsp.Resource.Id.Tenancy, + client := setupResourceService(t) + runReaperTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) { + // Seed the database with an artist. + res, err := demo.GenerateV2Artist() + + // set resource tenancy from default to test tenancy + res.Id.Tenancy = tenancy + + require.NoError(t, err) + ctx := testutil.TestContext(t) + writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res}) + require.NoError(t, err) + + // Delete the artist to create a tombstone + _, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id}) + require.NoError(t, err) + + // Retrieve tombstone + listRsp, err := client.List(ctx, &pbresource.ListRequest{ + Type: resource.TypeV1Tombstone, + Tenancy: writeRsp.Resource.Id.Tenancy, + }) + require.NoError(t, err) + require.Len(t, listRsp.Resources, 1) + tombstone := listRsp.Resources[0] + + // Verify reconcile does first pass and queues up for a second pass + rec := newReconciler() + runtime := controller.Runtime{ + Client: client, + Logger: testutil.Logger(t), + } + req := controller.Request{ID: tombstone.Id} + require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req)) + + // Verify condition FirstPassCompleted is true + readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id}) + require.NoError(t, err) + tombstone = readRsp.Resource + condition := tombstone.Status[statusKeyReaperController].Conditions[0] + require.Equal(t, conditionTypeFirstPassCompleted, condition.Type) + require.Equal(t, pbresource.Condition_STATE_TRUE, condition.State) + + // Verify requeued for second pass since secondPassDelay time has not elapsed + require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req)) }) - require.NoError(t, err) - require.Len(t, listRsp.Resources, 1) - tombstone := listRsp.Resources[0] - - // Verify reconcile does first pass and queues up for a second pass - rec := newReconciler() - runtime := controller.Runtime{ - Client: client, - Logger: testutil.Logger(t), +} + +func runReaperTestCaseWithTenancies(testCase func(tenancy *pbresource.Tenancy)) { + for _, tenancy := range resourcetest.TestTenancies() { + testCase(tenancy) } - req := controller.Request{ID: tombstone.Id} - require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req)) - - // Verify condition FirstPassCompleted is true - readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id}) - require.NoError(t, err) - tombstone = readRsp.Resource - condition := tombstone.Status[statusKeyReaperController].Conditions[0] - require.Equal(t, conditionTypeFirstPassCompleted, condition.Type) - require.Equal(t, pbresource.Condition_STATE_TRUE, condition.State) - - // Verify requeued for second pass since secondPassDelay time has not elapsed - require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req)) +} + +func setupResourceService(t *testing.T) pbresource.ResourceServiceClient { + return svctest.NewResourceServiceBuilder(). + WithTenancies(rtest.TestTenancies()...). + WithRegisterFns(demo.RegisterTypes). + Run(t) } diff --git a/internal/resource/refkey.go b/internal/resource/refkey.go index 44f0765c206c..c22c0b2c7c64 100644 --- a/internal/resource/refkey.go +++ b/internal/resource/refkey.go @@ -16,8 +16,8 @@ type ReferenceKey struct { GVK string Partition string // Tenancy.* Namespace string // Tenancy.* - PeerName string // Tenancy.* - Name string + // TODO(peering/v2) account for peer tenancy + Name string } // String returns a string representation of the ReferenceKey. This should not @@ -26,10 +26,10 @@ type ReferenceKey struct { // // This format should be aligned with IDToString and ReferenceToString. func (r ReferenceKey) String() string { - return fmt.Sprintf("%s/%s.%s.%s/%s", + // TODO(peering/v2) account for peer tenancy + return fmt.Sprintf("%s/%s.%s/%s", r.GVK, orDefault(r.Partition, "default"), - orDefault(r.PeerName, "local"), orDefault(r.Namespace, "default"), r.Name, ) @@ -38,7 +38,6 @@ func (r ReferenceKey) String() string { func (r ReferenceKey) GetTenancy() *pbresource.Tenancy { return &pbresource.Tenancy{ Partition: r.Partition, - PeerName: r.PeerName, Namespace: r.Namespace, } } @@ -68,7 +67,6 @@ func NewReferenceKey(refOrID ReferenceOrID) ReferenceKey { GVK: ToGVK(refOrID.GetType()), Partition: orDefault(refOrID.GetTenancy().GetPartition(), "default"), Namespace: orDefault(refOrID.GetTenancy().GetNamespace(), "default"), - PeerName: orDefault(refOrID.GetTenancy().GetPeerName(), "local"), Name: refOrID.GetName(), } } diff --git a/internal/resource/refkey_test.go b/internal/resource/refkey_test.go index 8c4b5eaf92b2..89f044a39fe6 100644 --- a/internal/resource/refkey_test.go +++ b/internal/resource/refkey_test.go @@ -15,17 +15,16 @@ import ( ) func TestReferenceKey(t *testing.T) { + // TODO(peering/v2) update the test to account for peer tenancy tenancy1 := &pbresource.Tenancy{} tenancy1_actual := defaultTenancy() tenancy2 := &pbresource.Tenancy{ Partition: "ap1", Namespace: "ns-billing", - PeerName: "peer-dc4", } tenancy3 := &pbresource.Tenancy{ Partition: "ap2", Namespace: "ns-intern", - PeerName: "peer-sea", } res1, err := demo.GenerateV2Artist() @@ -82,6 +81,5 @@ func defaultTenancy() *pbresource.Tenancy { return &pbresource.Tenancy{ Partition: "default", Namespace: "default", - PeerName: "local", } } diff --git a/internal/resource/registry.go b/internal/resource/registry.go index 7897ffb1b4bc..7faf84fe5eb6 100644 --- a/internal/resource/registry.go +++ b/internal/resource/registry.go @@ -10,8 +10,6 @@ import ( "strings" "sync" - "google.golang.org/protobuf/proto" - "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/internal/storage" "github.com/hashicorp/consul/proto-public/pbresource" @@ -53,32 +51,6 @@ type ValidationHook func(*pbresource.Resource) error // the data gets reencoded and stored back to the Data field. type MutationHook func(*pbresource.Resource) error -type Registration struct { - // Type is the GVK of the resource type. - Type *pbresource.Type - - // Proto is the resource's protobuf message type. - Proto proto.Message - - // ACLs are hooks called to perform authorization on RPCs. - // The hooks can assume that Validate has been called. - ACLs *ACLHooks - - // Validate is called to structurally validate the resource (e.g. - // check for required fields). Validate can assume that Mutate - // has been called. - Validate ValidationHook - - // Mutate is called to fill out any autogenerated fields (e.g. UUIDs) or - // apply defaults before validation. Mutate can assume that - // Resource.ID is populated and has non-empty tenancy fields. This does - // not mean those tenancy fields actually exist. - Mutate MutationHook - - // Scope describes the tenancy scope of a resource. - Scope Scope -} - var ErrNeedResource = errors.New("authorization check requires the entire resource") type ACLAuthorizeReadHook func(acl.Authorizer, *acl.AuthorizerContext, *pbresource.ID, *pbresource.Resource) error diff --git a/internal/resource/registry_ce.go b/internal/resource/registry_ce.go new file mode 100644 index 000000000000..985a81640615 --- /dev/null +++ b/internal/resource/registry_ce.go @@ -0,0 +1,38 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +//go:build !consulent + +package resource + +import ( + "google.golang.org/protobuf/proto" + + "github.com/hashicorp/consul/proto-public/pbresource" +) + +type Registration struct { + // Type is the GVK of the resource type. + Type *pbresource.Type + + // Proto is the resource's protobuf message type. + Proto proto.Message + + // ACLs are hooks called to perform authorization on RPCs. + // The hooks can assume that Validate has been called. + ACLs *ACLHooks + + // Validate is called to structurally validate the resource (e.g. + // check for required fields). Validate can assume that Mutate + // has been called. + Validate ValidationHook + + // Mutate is called to fill out any autogenerated fields (e.g. UUIDs) or + // apply defaults before validation. Mutate can assume that + // Resource.ID is populated and has non-empty tenancy fields. This does + // not mean those tenancy fields actually exist. + Mutate MutationHook + + // Scope describes the tenancy scope of a resource. + Scope Scope +} diff --git a/internal/resource/resource.go b/internal/resource/resource.go index 2f3a7a05ca2c..24ffc2a65bdc 100644 --- a/internal/resource/resource.go +++ b/internal/resource/resource.go @@ -9,7 +9,7 @@ import ( mapset "github.com/deckarep/golang-set/v2" - "github.com/hashicorp/consul/agent/dns" + "github.com/hashicorp/consul/internal/dnsutil" "github.com/hashicorp/consul/proto-public/pbresource" ) @@ -27,7 +27,7 @@ const FinalizerKey = "finalizers" // ValidateName returns an error a name is not a valid resource name. // The error will contain reference to what constitutes a valid resource name. func ValidateName(name string) error { - if !dns.IsValidLabel(name) || strings.ToLower(name) != name || len(name) > MaxNameLength { + if !dnsutil.IsValidLabel(name) || strings.ToLower(name) != name || len(name) > MaxNameLength { return fmt.Errorf("a resource name must consist of lower case alphanumeric characters or '-', must start and end with an alphanumeric character and be less than %d characters, got: %q", MaxNameLength+1, name) } return nil @@ -67,10 +67,21 @@ func AddFinalizer(res *pbresource.Resource, finalizer string) { func RemoveFinalizer(res *pbresource.Resource, finalizer string) { finalizerSet := GetFinalizers(res) finalizerSet.Remove(finalizer) - if res.Metadata == nil { - res.Metadata = map[string]string{} + + if finalizerSet.Cardinality() == 0 { + // Remove key if no finalizers to prevent dual representations of + // the same state. + _, keyExists := res.Metadata[FinalizerKey] + if keyExists { + delete(res.Metadata, FinalizerKey) + } + } else { + // Add/update key + if res.Metadata == nil { + res.Metadata = map[string]string{} + } + res.Metadata[FinalizerKey] = strings.Join(finalizerSet.ToSlice(), " ") } - res.Metadata[FinalizerKey] = strings.Join(finalizerSet.ToSlice(), " ") } // GetFinalizers returns the set of finalizers for the given resource. diff --git a/internal/resource/resource_test.go b/internal/resource/resource_test.go index 5057bd4cf8f3..d865618934eb 100644 --- a/internal/resource/resource_test.go +++ b/internal/resource/resource_test.go @@ -11,12 +11,12 @@ import ( "github.com/hashicorp/consul/internal/resource" rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" + pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v2" ) func TestFinalizer(t *testing.T) { t.Run("no finalizers", func(t *testing.T) { - res := rtest.Resource(pbtenancy.NamespaceType, "ns1").Build() + res := rtest.Resource(pbdemo.ArtistType, "art1").Build() require.False(t, resource.HasFinalizers(res)) require.False(t, resource.HasFinalizer(res, "finalizer1")) require.Equal(t, mapset.NewSet[string](), resource.GetFinalizers(res)) @@ -24,7 +24,7 @@ func TestFinalizer(t *testing.T) { }) t.Run("add finalizer", func(t *testing.T) { - res := rtest.Resource(pbtenancy.NamespaceType, "ns1").Build() + res := rtest.Resource(pbdemo.ArtistType, "art1").Build() resource.AddFinalizer(res, "finalizer1") require.True(t, resource.HasFinalizers(res)) require.True(t, resource.HasFinalizer(res, "finalizer1")) @@ -37,7 +37,7 @@ func TestFinalizer(t *testing.T) { }) t.Run("remove finalizer", func(t *testing.T) { - res := rtest.Resource(pbtenancy.NamespaceType, "ns1").Build() + res := rtest.Resource(pbdemo.ArtistType, "art1").Build() resource.AddFinalizer(res, "finalizer1") resource.AddFinalizer(res, "finalizer2") resource.RemoveFinalizer(res, "finalizer1") diff --git a/internal/resource/resourcetest/builder.go b/internal/resource/resourcetest/builder.go index 3de836a71db3..c4fdcbfea890 100644 --- a/internal/resource/resourcetest/builder.go +++ b/internal/resource/resourcetest/builder.go @@ -56,6 +56,11 @@ func (b *resourceBuilder) WithTenancy(tenant *pbresource.Tenancy) *resourceBuild return b } +func (b *resourceBuilder) WithVersion(version string) *resourceBuilder { + b.resource.Version = version + return b +} + func (b *resourceBuilder) WithData(t T, data protoreflect.ProtoMessage) *resourceBuilder { t.Helper() @@ -108,13 +113,15 @@ func (b *resourceBuilder) Build() *pbresource.Resource { } // Now create the status map - res.Status = make(map[string]*pbresource.Status) - for key, original := range b.statuses { - status := &pbresource.Status{ - ObservedGeneration: res.Generation, - Conditions: original.Conditions, + if len(b.statuses) > 0 { + res.Status = make(map[string]*pbresource.Status) + for key, original := range b.statuses { + status := &pbresource.Status{ + ObservedGeneration: res.Generation, + Conditions: original.Conditions, + } + res.Status[key] = status } - res.Status[key] = status } return res @@ -178,7 +185,7 @@ func (b *resourceBuilder) Write(t T, client pbresource.ResourceServiceClient) *p id := proto.Clone(rsp.Resource.Id).(*pbresource.ID) id.Uid = "" t.Cleanup(func() { - rtestClient.MustDelete(t, id) + rtestClient.CleanupDelete(t, id) }) } diff --git a/internal/resource/resourcetest/client.go b/internal/resource/resourcetest/client.go index 94bcd604265e..894f6e7e5b86 100644 --- a/internal/resource/resourcetest/client.go +++ b/internal/resource/resourcetest/client.go @@ -5,12 +5,14 @@ package resourcetest import ( "context" + "flag" "fmt" "math/rand" "time" "github.com/stretchr/testify/require" "golang.org/x/exp/slices" + "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" @@ -21,25 +23,67 @@ import ( "github.com/hashicorp/consul/sdk/testutil/retry" ) +type ClientOption func(*Client) + +func WithRNGSeed(seed int64) ClientOption { + return func(c *Client) { + c.rng = rand.New(rand.NewSource(seed)) + } +} + +func WithRequestDelay(minMilliseconds int, maxMilliseconds int) ClientOption { + return func(c *Client) { + + min := minMilliseconds + max := maxMilliseconds + if max < min { + min = maxMilliseconds + max = minMilliseconds + } + c.requestDelayMin = min + c.requestDelayMax = max + } +} + +func WithACLToken(token string) ClientOption { + return func(c *Client) { + c.token = token + } +} + type Client struct { pbresource.ResourceServiceClient timeout time.Duration wait time.Duration token string -} -func NewClient(client pbresource.ResourceServiceClient) *Client { - return NewClientWithACLToken(client, "") + rng *rand.Rand + + requestDelayMin int + requestDelayMax int } -func NewClientWithACLToken(client pbresource.ResourceServiceClient, token string) *Client { - return &Client{ +func NewClient(client pbresource.ResourceServiceClient, opts ...ClientOption) *Client { + c := &Client{ ResourceServiceClient: client, timeout: 7 * time.Second, wait: 25 * time.Millisecond, - token: token, + rng: rand.New(rand.NewSource(time.Now().UnixNano())), + // arbitrary write delays are opt-in only + requestDelayMin: 0, + requestDelayMax: 0, } + + for _, opt := range opts { + opt(c) + } + + return c +} + +func NewClientWithACLToken(client pbresource.ResourceServiceClient, token string) *Client { + return NewClient(client, WithACLToken(token)) } func (client *Client) SetRetryerConfig(timeout time.Duration, wait time.Duration) { @@ -60,7 +104,7 @@ func (client *Client) PublishResources(t T, resources []*pbresource.Resource) { // controllers should eventually converge on the desired state. The exception to this // is that you cannot insert resources with owner refs before the resource they are // owned by or insert a resource into a non-default tenant before that tenant exists. - rand.Shuffle(len(resources), func(i, j int) { + client.rng.Shuffle(len(resources), func(i, j int) { temp := resources[i] resources[i] = resources[j] resources[j] = temp @@ -97,7 +141,7 @@ func (client *Client) PublishResources(t T, resources []*pbresource.Resource) { id := rsp.Resource.Id t.Cleanup(func() { - client.MustDelete(t, id) + client.CleanupDelete(t, id) }) // track the number of resources published @@ -119,6 +163,11 @@ func (client *Client) PublishResources(t T, resources []*pbresource.Resource) { require.Empty(t, resources, "Could not publish all resources - some resources have invalid owner references") } +func (client *Client) Write(ctx context.Context, in *pbresource.WriteRequest, opts ...grpc.CallOption) (*pbresource.WriteResponse, error) { + client.delayRequest() + return client.ResourceServiceClient.Write(ctx, in, opts...) +} + func (client *Client) Context(t T) context.Context { ctx := testutil.TestContext(t) @@ -275,6 +324,17 @@ func (client *Client) WaitForResourceState(t T, id *pbresource.ID, verify func(T return res } +func (client *Client) WaitForResourceExists(t T, id *pbresource.ID) *pbresource.Resource { + t.Helper() + + var res *pbresource.Resource + client.retry(t, func(r *retry.R) { + res = client.RequireResourceExists(r, id) + }) + + return res +} + func (client *Client) WaitForDeletion(t T, id *pbresource.ID) { t.Helper() @@ -291,11 +351,32 @@ func (client *Client) ResolveResourceID(t T, id *pbresource.ID) *pbresource.ID { return client.RequireResourceExists(t, id).Id } +// MustDelete will delete a resource by its id, retrying if necessary and fail the test +// if it cannot delete it within the timeout. The clients request delay settings are +// taken into account with this operation. func (client *Client) MustDelete(t T, id *pbresource.ID) { + t.Helper() + client.retryDelete(t, id, true) +} + +// CleanupDelete will perform the same operations as MustDelete to ensure the resource is +// deleted. The clients request delay settings are ignored for this operation and it is +// assumed this will only be called in the context of test Cleanup routines where we +// are no longer testing that a controller eventually converges on some values in response +// to the delete. +func (client *Client) CleanupDelete(t T, id *pbresource.ID) { + t.Helper() + client.retryDelete(t, id, false) +} + +func (client *Client) retryDelete(t T, id *pbresource.ID, shouldDelay bool) { t.Helper() ctx := client.Context(t) client.retry(t, func(r *retry.R) { + if shouldDelay { + client.delayRequest() + } _, err := client.Delete(ctx, &pbresource.DeleteRequest{Id: id}) if status.Code(err) == codes.NotFound { return @@ -311,3 +392,53 @@ func (client *Client) MustDelete(t T, id *pbresource.ID) { require.NoError(r, err) }) } + +func (client *Client) delayRequest() { + if client.requestDelayMin == 0 && client.requestDelayMax == 0 { + return + } + + var delay time.Duration + if client.requestDelayMin == client.requestDelayMax { + delay = time.Duration(client.requestDelayMin) * time.Millisecond + } else { + delay = time.Duration(client.rng.Intn(client.requestDelayMax-client.requestDelayMin)+client.requestDelayMin) * time.Millisecond + } + time.Sleep(delay) +} + +type CLIOptions struct { + minRequestDelay int + maxRequestDelay int + seed int64 +} + +type CLIOptionT interface { + Helper() + Logf(string, ...any) +} + +func (o *CLIOptions) ClientOptions(t CLIOptionT) []ClientOption { + t.Helper() + t.Logf("Using %d for the random number generator seed. Pass -rng-seed= to overwrite the time based seed", o.seed) + t.Logf("Using random request delays between %dms and %dms. Use -min-request-delay= or -max-request-delay= to override the defaults", o.minRequestDelay, o.maxRequestDelay) + + return []ClientOption{ + WithRNGSeed(o.seed), + WithRequestDelay(o.minRequestDelay, o.maxRequestDelay), + } +} + +func ConfigureTestCLIFlags() *CLIOptions { + opts := &CLIOptions{ + minRequestDelay: 0, + maxRequestDelay: 0, + seed: time.Now().UnixNano(), + } + + flag.Int64Var(&opts.seed, "rng-seed", opts.seed, "Seed to use for pseudo-random-number-generators") + flag.IntVar(&opts.minRequestDelay, "min-request-delay", 10, "Minimum delay before performing a resource write (milliseconds: default=10)") + flag.IntVar(&opts.maxRequestDelay, "max-request-delay", 50, "Maximum delay before performing a resource write (milliseconds: default=50)") + + return opts +} diff --git a/internal/resource/resourcetest/decode.go b/internal/resource/resourcetest/decode.go index 109ad39ceb75..c84f56df4eb3 100644 --- a/internal/resource/resourcetest/decode.go +++ b/internal/resource/resourcetest/decode.go @@ -16,3 +16,9 @@ func MustDecode[Tp proto.Message](t T, res *pbresource.Resource) *resource.Decod require.NoError(t, err) return dec } + +func MustDecodeList[Tp proto.Message](t T, resources []*pbresource.Resource) []*resource.DecodedResource[Tp] { + dec, err := resource.DecodeList[Tp](resources) + require.NoError(t, err) + return dec +} diff --git a/internal/resource/resourcetest/tenancy.go b/internal/resource/resourcetest/tenancy.go index d05306e8f295..1d97bdcae44a 100644 --- a/internal/resource/resourcetest/tenancy.go +++ b/internal/resource/resourcetest/tenancy.go @@ -4,34 +4,42 @@ package resourcetest import ( + "fmt" "strings" "testing" - "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/version/versiontest" ) // TestTenancies returns a list of tenancies which represent // the namespace and partition combinations that can be used in unit tests func TestTenancies() []*pbresource.Tenancy { - isEnterprise := (structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty() == "default") + isEnterprise := versiontest.IsEnterprise() tenancies := []*pbresource.Tenancy{Tenancy("default.default")} if isEnterprise { + // TODO(namespaces/v2) move the default partition + non-default namespace test to run even for CE. tenancies = append(tenancies, Tenancy("default.bar"), Tenancy("foo.default"), Tenancy("foo.bar")) } return tenancies } +func ToPartitionScoped(t *pbresource.Tenancy) *pbresource.Tenancy { + return &pbresource.Tenancy{ + Partition: t.Partition, + } +} + // Tenancy constructs a pbresource.Tenancy from a concise string representation // suitable for use in unit tests. // -// - "" : partition="" namespace="" peerName="local" -// - "foo" : partition="foo" namespace="" peerName="local" -// - "foo.bar" : partition="foo" namespace="bar" peerName="local" -// - : partition="BAD" namespace="BAD" peerName="BAD" +// - "" : partition="" namespace="" +// - "foo" : partition="foo" namespace="" +// - "foo.bar" : partition="foo" namespace="bar" +// - : partition="BAD" namespace="BAD" func Tenancy(s string) *pbresource.Tenancy { parts := strings.Split(s, ".") switch len(parts) { @@ -47,7 +55,7 @@ func Tenancy(s string) *pbresource.Tenancy { v.Namespace = parts[1] return v default: - return &pbresource.Tenancy{Partition: "BAD", Namespace: "BAD", PeerName: "BAD"} + return &pbresource.Tenancy{Partition: "BAD", Namespace: "BAD"} } } @@ -64,3 +72,19 @@ func DefaultTenancyForType(t *testing.T, reg resource.Registration) *pbresource. return nil } } + +func AppendTenancyInfoSubtest(name string, subtestName string, tenancy *pbresource.Tenancy) string { + return fmt.Sprintf("%s_%s_Namespace_%s_Partition/%s", name, tenancy.Namespace, tenancy.Partition, subtestName) +} + +func AppendTenancyInfo(name string, tenancy *pbresource.Tenancy) string { + return fmt.Sprintf("%s_%s_Namespace_%s_Partition", name, tenancy.Namespace, tenancy.Partition) +} + +func RunWithTenancies(testFunc func(tenancy *pbresource.Tenancy), t *testing.T) { + for _, tenancy := range TestTenancies() { + t.Run(AppendTenancyInfo(t.Name(), tenancy), func(t *testing.T) { + testFunc(tenancy) + }) + } +} diff --git a/internal/resource/resourcetest/testing.go b/internal/resource/resourcetest/testing.go index 1be9947226bd..6ea5ce910365 100644 --- a/internal/resource/resourcetest/testing.go +++ b/internal/resource/resourcetest/testing.go @@ -3,14 +3,10 @@ package resourcetest +import "github.com/hashicorp/consul/sdk/testutil" + // T represents the subset of testing.T methods that will be used // by the various functionality in this package type T interface { - Helper() - Log(args ...interface{}) - Logf(format string, args ...interface{}) - Errorf(format string, args ...interface{}) - Fatalf(format string, args ...interface{}) - FailNow() - Cleanup(func()) + testutil.TestingTB } diff --git a/internal/resource/sort.go b/internal/resource/sort.go index 1373f08e1421..88d4e0d08dde 100644 --- a/internal/resource/sort.go +++ b/internal/resource/sort.go @@ -52,10 +52,6 @@ func compareTenancy(a, b *pbresource.Tenancy) int { if diff != 0 { return diff } - diff = compareString(a.PeerName, b.PeerName) - if diff != 0 { - return diff - } return compareString(a.Namespace, b.Namespace) } diff --git a/internal/resource/sort_test.go b/internal/resource/sort_test.go index e319266d9a92..0cc17d28daff 100644 --- a/internal/resource/sort_test.go +++ b/internal/resource/sort_test.go @@ -17,16 +17,18 @@ import ( ) func TestLessReference(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } parseTenancy := func(s string) *pbresource.Tenancy { - // format is: .. + // format is: . parts := strings.Split(s, ".") - if len(parts) != 3 { + if len(parts) != 2 { panic("bad tenancy") } return &pbresource.Tenancy{ Partition: parts[0], - PeerName: parts[1], - Namespace: parts[2], + Namespace: parts[1], } } @@ -36,7 +38,7 @@ func TestLessReference(t *testing.T) { // - // // // type = (gvk style) - // tenancy = .. + // tenancy = . parts := strings.Split(s, "/") require.Len(t, parts, 3) @@ -68,22 +70,20 @@ func TestLessReference(t *testing.T) { for _, version := range vals { for _, kind := range vals { for _, partition := range vals { - for _, peer := range vals { - for _, namespace := range vals { - for _, name := range vals { - for _, section := range sectionVals { - if section != "" { - section = "@" + section - } - inputs = append(inputs, makeRef( - fmt.Sprintf( - "%s.%s.%s/%s.%s.%s/%s%s", - group, version, kind, - partition, peer, namespace, - name, section, - ), - )) + for _, namespace := range vals { + for _, name := range vals { + for _, section := range sectionVals { + if section != "" { + section = "@" + section } + inputs = append(inputs, makeRef( + fmt.Sprintf( + "%s.%s.%s/%s.%s/%s%s", + group, version, kind, + partition, namespace, + name, section, + ), + )) } } } diff --git a/internal/resource/stringer.go b/internal/resource/stringer.go index 075c08ac0d9c..da27ef52f02b 100644 --- a/internal/resource/stringer.go +++ b/internal/resource/stringer.go @@ -49,7 +49,7 @@ func ReferenceToString(ref *pbresource.Reference) string { // should not be relied upon nor parsed and is provided just for debugging and // logging reasons. func TenancyToString(tenancy *pbresource.Tenancy) string { - return fmt.Sprintf("%s.%s.%s", tenancy.Partition, tenancy.PeerName, tenancy.Namespace) + return fmt.Sprintf("%s.%s", tenancy.Partition, tenancy.Namespace) } // TypeToString returns a string representation of pbresource.Type. This should diff --git a/internal/resource/tenancy.go b/internal/resource/tenancy.go index 597253aa8dc1..e46322557dfc 100644 --- a/internal/resource/tenancy.go +++ b/internal/resource/tenancy.go @@ -54,18 +54,13 @@ func (s Scope) String() string { // DefaultClusteredTenancy returns the default tenancy for a cluster scoped resource. func DefaultClusteredTenancy() *pbresource.Tenancy { - return &pbresource.Tenancy{ - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - PeerName: DefaultPeerName, - } + return &pbresource.Tenancy{} } // DefaultPartitionedTenancy returns the default tenancy for a partition scoped resource. func DefaultPartitionedTenancy() *pbresource.Tenancy { return &pbresource.Tenancy{ Partition: DefaultPartitionName, - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - PeerName: DefaultPeerName, } } @@ -74,8 +69,6 @@ func DefaultNamespacedTenancy() *pbresource.Tenancy { return &pbresource.Tenancy{ Partition: DefaultPartitionName, Namespace: DefaultNamespaceName, - // TODO(spatel): NET-5475 - Remove as part of peer_name moving to PeerTenancy - PeerName: DefaultPeerName, } } @@ -129,10 +122,6 @@ func defaultTenancy(itemTenancy, parentTenancy, scopeTenancy *pbresource.Tenancy panic("scope tenancy is required") } - if itemTenancy.PeerName == "" { - itemTenancy.PeerName = DefaultPeerName - } - if parentTenancy != nil { // Recursively normalize this tenancy as well. defaultTenancy(parentTenancy, nil, scopeTenancy) @@ -143,16 +132,6 @@ func defaultTenancy(itemTenancy, parentTenancy, scopeTenancy *pbresource.Tenancy parentTenancy = scopeTenancy } - if !equalOrEmpty(itemTenancy.PeerName, DefaultPeerName) { - panic("peering is not supported yet for resource tenancies") - } - if !equalOrEmpty(parentTenancy.PeerName, DefaultPeerName) { - panic("peering is not supported yet for parent tenancies") - } - if !equalOrEmpty(scopeTenancy.PeerName, DefaultPeerName) { - panic("peering is not supported yet for scopes") - } - // Only retain the parts of the parent that apply to this resource. if scopeTenancy.Partition == "" { parentTenancy.Partition = "" diff --git a/internal/resource/tenancy_test.go b/internal/resource/tenancy_test.go index 654ebb183d1d..be3445a2aa14 100644 --- a/internal/resource/tenancy_test.go +++ b/internal/resource/tenancy_test.go @@ -232,6 +232,6 @@ func newTestTenancy(s string) *pbresource.Tenancy { v.Namespace = parts[1] return v default: - return &pbresource.Tenancy{Partition: "BAD", Namespace: "BAD", PeerName: "BAD"} + return &pbresource.Tenancy{Partition: "BAD", Namespace: "BAD"} } } diff --git a/internal/resourcehcl/testdata/destinations.golden b/internal/resourcehcl/testdata/destinations.golden deleted file mode 100644 index b6ffce953751..000000000000 --- a/internal/resourcehcl/testdata/destinations.golden +++ /dev/null @@ -1 +0,0 @@ -{"id":{"name":"api","type":{"group":"mesh","groupVersion":"v2beta1","kind":"Destinations"}},"data":{"@type":"hashicorp.consul.mesh.v2beta1.Destinations","workloads":{"prefixes":["api"]},"destinations":[{"destinationRef":{"name":"db","type":{"group":"catalog","groupVersion":"v2beta1","kind":"Service"}},"destinationPort":"tcp","ipPort":{"port":1234}}]}} diff --git a/internal/resourcehcl/testdata/destinations.hcl b/internal/resourcehcl/testdata/destinations.hcl deleted file mode 100644 index fa62538abb44..000000000000 --- a/internal/resourcehcl/testdata/destinations.hcl +++ /dev/null @@ -1,25 +0,0 @@ -ID { - Type = gvk("mesh.v2beta1.Destinations") - Name = "api" -} - -Data { - Workloads { - Prefixes = ["api"] - } - - Destinations = [ - { - DestinationRef = { - Type = gvk("catalog.v2beta1.Service") - Name = "db" - } - - DestinationPort = "tcp" - - IpPort = { - Port = 1234 - } - } - ] -} diff --git a/internal/resourcehcl/testdata/no-blocks.golden b/internal/resourcehcl/testdata/no-blocks.golden deleted file mode 100644 index 5e3bff82bd88..000000000000 --- a/internal/resourcehcl/testdata/no-blocks.golden +++ /dev/null @@ -1 +0,0 @@ -{"id":{"type":{"group":"mesh","groupVersion":"v2beta1","kind":"Destinations"}},"data":{"@type":"hashicorp.consul.mesh.v2beta1.Destinations","workloads":{"prefixes":["api"]},"destinations":[{"destinationRef":{"name":"db","type":{"group":"catalog","groupVersion":"v2beta1","kind":"Service"}},"destinationPort":"tcp","ipPort":{"port":1234}}]}} diff --git a/internal/resourcehcl/testdata/no-blocks.hcl b/internal/resourcehcl/testdata/no-blocks.hcl deleted file mode 100644 index 197fd43f8776..000000000000 --- a/internal/resourcehcl/testdata/no-blocks.hcl +++ /dev/null @@ -1,33 +0,0 @@ -ID = { - Type = { - Group = "mesh" - GroupVersion = "v2beta1" - Kind = "Destinations" - } -} - -Data = { - Workloads = { - Prefixes = ["api"] - } - - Destinations = [ - { - DestinationRef = { - Type = { - Group = "catalog" - GroupVersion = "v2beta1" - Kind = "Service" - } - - Name = "db" - } - - DestinationPort = "tcp" - - IpPort = { - Port = 1234 - } - } - ] -} diff --git a/internal/resourcehcl/unmarshal_test.go b/internal/resourcehcl/unmarshal_test.go index e5b650674472..6caad55ff867 100644 --- a/internal/resourcehcl/unmarshal_test.go +++ b/internal/resourcehcl/unmarshal_test.go @@ -13,7 +13,6 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/protobuf/encoding/protojson" - "github.com/hashicorp/consul/internal/mesh" "github.com/hashicorp/consul/internal/resource" "github.com/hashicorp/consul/internal/resource/demo" "github.com/hashicorp/consul/internal/resourcehcl" @@ -52,7 +51,6 @@ func FuzzUnmarshall(f *testing.F) { } registry := resource.NewRegistry() demo.RegisterTypes(registry) - mesh.RegisterTypes(registry) f.Fuzz(func(t *testing.T, input []byte) { got, err := resourcehcl.Unmarshal(input, registry) @@ -104,7 +102,6 @@ func TestUnmarshal(t *testing.T) { registry := resource.NewRegistry() demo.RegisterTypes(registry) - mesh.RegisterTypes(registry) output, err := resourcehcl.UnmarshalOptions{SourceFileName: name}. Unmarshal(input, registry) diff --git a/internal/storage/conformance/conformance.go b/internal/storage/conformance/conformance.go index 543a574fb5a6..0b815a847b0d 100644 --- a/internal/storage/conformance/conformance.go +++ b/internal/storage/conformance/conformance.go @@ -29,6 +29,15 @@ type TestOptions struct { // SupportsStronglyConsistentList indicates whether the given storage backend // supports strongly consistent list operations. SupportsStronglyConsistentList bool + + // IgnoreWatchListSnapshotOperations indicates whether a given storage + // backend is expected to be consistent enough with reads to emit + // WatchEvent_Upsert after the initial sync. + // + // For instance, a replicated copy of the state store will have stale data + // and may return an initial snapshot of nothing, and follow it up by an + // upsert. + IgnoreWatchListSnapshotOperations bool } // Test runs a suite of tests against a storage.Backend implementation to check @@ -314,7 +323,6 @@ func testListWatch(t *testing.T, opts TestOptions) { resourceType: storage.UnversionedTypeFrom(typeAv1), tenancy: &pbresource.Tenancy{ Partition: storage.Wildcard, - PeerName: storage.Wildcard, Namespace: storage.Wildcard, }, namePrefix: "", @@ -324,30 +332,12 @@ func testListWatch(t *testing.T, opts TestOptions) { seedData[2], seedData[3], seedData[5], - seedData[6], }, }, - "fixed partition, wildcard peer, wildcard namespace": { + "fixed partition, wildcard namespace": { resourceType: storage.UnversionedTypeFrom(typeAv1), tenancy: &pbresource.Tenancy{ Partition: "default", - PeerName: storage.Wildcard, - Namespace: storage.Wildcard, - }, - namePrefix: "", - results: []*pbresource.Resource{ - seedData[0], - seedData[1], - seedData[2], - seedData[5], - seedData[6], - }, - }, - "wildcard partition, fixed peer, wildcard namespace": { - resourceType: storage.UnversionedTypeFrom(typeAv1), - tenancy: &pbresource.Tenancy{ - Partition: storage.Wildcard, - PeerName: "local", Namespace: storage.Wildcard, }, namePrefix: "", @@ -355,15 +345,13 @@ func testListWatch(t *testing.T, opts TestOptions) { seedData[0], seedData[1], seedData[2], - seedData[3], seedData[5], }, }, - "wildcard partition, wildcard peer, fixed namespace": { + "wildcard partition, fixed namespace": { resourceType: storage.UnversionedTypeFrom(typeAv1), tenancy: &pbresource.Tenancy{ Partition: storage.Wildcard, - PeerName: storage.Wildcard, Namespace: "default", }, namePrefix: "", @@ -371,29 +359,12 @@ func testListWatch(t *testing.T, opts TestOptions) { seedData[0], seedData[1], seedData[2], - seedData[6], - }, - }, - "fixed partition, fixed peer, wildcard namespace": { - resourceType: storage.UnversionedTypeFrom(typeAv1), - tenancy: &pbresource.Tenancy{ - Partition: "default", - PeerName: "local", - Namespace: storage.Wildcard, - }, - namePrefix: "", - results: []*pbresource.Resource{ - seedData[0], - seedData[1], - seedData[2], - seedData[5], }, }, "wildcard tenancy, name prefix": { resourceType: storage.UnversionedTypeFrom(typeAv1), tenancy: &pbresource.Tenancy{ Partition: storage.Wildcard, - PeerName: storage.Wildcard, Namespace: storage.Wildcard, }, namePrefix: "a", @@ -402,9 +373,9 @@ func testListWatch(t *testing.T, opts TestOptions) { seedData[1], seedData[3], seedData[5], - seedData[6], }, }, + // TODO(peering/v2) add tests for peer tenancy } t.Run("List", func(t *testing.T) { @@ -454,15 +425,22 @@ func testListWatch(t *testing.T, opts TestOptions) { require.NoError(t, err) t.Cleanup(watch.Close) - for i := 0; i < len(tc.results); i++ { + expectNum := len(tc.results) + 1 + for i := 0; i < expectNum; i++ { ctx, cancel := context.WithTimeout(ctx, 5*time.Second) t.Cleanup(cancel) event, err := watch.Next(ctx) require.NoError(t, err) - require.Equal(t, pbresource.WatchEvent_OPERATION_UPSERT, event.Operation) - prototest.AssertContainsElement(t, tc.results, event.Resource, ignoreVersion) + if opts.IgnoreWatchListSnapshotOperations && event.GetEndOfSnapshot() != nil { + continue // ignore + } else if !opts.IgnoreWatchListSnapshotOperations && i == expectNum-1 { + require.NotNil(t, event.GetEndOfSnapshot(), "expected EndOfSnapshot got %T", event.GetEvent()) + continue + } + require.NotNil(t, event.GetUpsert(), "index=%d", i) + prototest.AssertContainsElement(t, tc.results, event.GetUpsert().Resource, ignoreVersion) } }) @@ -474,6 +452,15 @@ func testListWatch(t *testing.T, opts TestOptions) { require.NoError(t, err) t.Cleanup(watch.Close) + { // read snapshot end + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + t.Cleanup(cancel) + event, err := watch.Next(ctx) + require.NoError(t, err) + + require.NotNil(t, event.GetEndOfSnapshot()) + } + // Write the seed data after the watch has been established. for _, r := range seedData { _, err := backend.WriteCAS(ctx, r) @@ -487,13 +474,13 @@ func testListWatch(t *testing.T, opts TestOptions) { event, err := watch.Next(ctx) require.NoError(t, err) - require.Equal(t, pbresource.WatchEvent_OPERATION_UPSERT, event.Operation) - prototest.AssertContainsElement(t, tc.results, event.Resource, ignoreVersion) + require.NotNil(t, event.GetUpsert()) + prototest.AssertContainsElement(t, tc.results, event.GetUpsert().Resource, ignoreVersion) // Check that Read implements "monotonic reads" with Watch. - readRes, err := backend.Read(ctx, storage.EventualConsistency, event.Resource.Id) + readRes, err := backend.Read(ctx, storage.EventualConsistency, event.GetUpsert().Resource.Id) require.NoError(t, err) - prototest.AssertDeepEqual(t, event.Resource, readRes) + prototest.AssertDeepEqual(t, event.GetUpsert().Resource, readRes) } // Delete a random resource to check we get an event. @@ -507,8 +494,8 @@ func testListWatch(t *testing.T, opts TestOptions) { event, err := watch.Next(ctx) require.NoError(t, err) - require.Equal(t, pbresource.WatchEvent_OPERATION_DELETE, event.Operation) - prototest.AssertDeepEqual(t, del, event.Resource) + require.NotNil(t, event.GetDelete()) + prototest.AssertDeepEqual(t, del, event.GetDelete().Resource) // Check that Read implements "monotonic reads" with Watch. _, err = backend.Read(ctx, storage.EventualConsistency, del.Id) @@ -610,23 +597,15 @@ var ( } tenancyDefault = &pbresource.Tenancy{ Partition: "default", - PeerName: "local", Namespace: "default", } tenancyDefaultOtherNamespace = &pbresource.Tenancy{ Partition: "default", - PeerName: "local", Namespace: "other", } - tenancyDefaultOtherPeer = &pbresource.Tenancy{ - Partition: "default", - PeerName: "remote", - Namespace: "default", - } tenancyOther = &pbresource.Tenancy{ Partition: "billing", - PeerName: "local", Namespace: "payments", } @@ -637,7 +616,6 @@ var ( resource(typeAv1, tenancyOther, "api"), // 3 resource(typeB, tenancyDefault, "admin"), // 4 resource(typeAv1, tenancyDefaultOtherNamespace, "autoscaler"), // 5 - resource(typeAv1, tenancyDefaultOtherPeer, "amplifier"), // 6 } ignoreVersion = protocmp.IgnoreFields(&pbresource.Resource{}, "version") diff --git a/internal/storage/inmem/backend_test.go b/internal/storage/inmem/backend_test.go index 7978dcdf2993..c1aa13b70e4c 100644 --- a/internal/storage/inmem/backend_test.go +++ b/internal/storage/inmem/backend_test.go @@ -15,6 +15,9 @@ import ( ) func TestBackend_Conformance(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } conformance.Test(t, conformance.TestOptions{ NewBackend: func(t *testing.T) storage.Backend { backend, err := inmem.NewBackend() diff --git a/internal/storage/inmem/schema.go b/internal/storage/inmem/schema.go index 37e39dbc5707..0565d58b2f9f 100644 --- a/internal/storage/inmem/schema.go +++ b/internal/storage/inmem/schema.go @@ -142,7 +142,6 @@ func indexFromType(t storage.UnversionedType) []byte { func indexFromTenancy(t *pbresource.Tenancy) []byte { var b indexBuilder b.String(t.Partition) - b.String(t.PeerName) b.String(t.Namespace) return b.Bytes() } @@ -151,6 +150,7 @@ func indexFromID(id *pbresource.ID, includeUid bool) []byte { var b indexBuilder b.Raw(indexFromType(storage.UnversionedTypeFrom(id.Type))) b.Raw(indexFromTenancy(id.Tenancy)) + // TODO(peering/v2) handle peer tenancy for indexing b.String(id.Name) if includeUid { b.String(id.Uid) @@ -184,14 +184,14 @@ type query struct { // // Our radix tree keys are structured like so: // -// +// // // Where each segment is followed by a NULL terminator. // // In order to handle wildcard queries, we return a prefix up to the wildcarded // field. For example: // -// Query: type={mesh,v1,service}, partition=default, peer=*, namespace=default +// Query: type={mesh,v1,service}, partition=default, namespace=default // Prefix: mesh[NULL]v1[NULL]service[NULL]default[NULL] // // Which means that we must manually apply filters after the wildcard (i.e. @@ -206,18 +206,14 @@ func (q query) indexPrefix() []byte { b.String(v) } - if v := q.tenancy.PeerName; v == storage.Wildcard { - return b.Bytes() - } else { - b.String(v) - } - if v := q.tenancy.Namespace; v == storage.Wildcard { return b.Bytes() } else { b.String(v) } + // TODO(peering/v2) handle peer tenancies + if q.namePrefix != "" { b.Raw([]byte(q.namePrefix)) } @@ -234,14 +230,12 @@ func (q query) matches(res *pbresource.Resource) bool { return false } - if q.tenancy.PeerName != storage.Wildcard && res.Id.Tenancy.PeerName != q.tenancy.PeerName { - return false - } - if q.tenancy.Namespace != storage.Wildcard && res.Id.Tenancy.Namespace != q.tenancy.Namespace { return false } + // TODO(peering/v2) handle peer tenancies + if len(q.namePrefix) != 0 && !strings.HasPrefix(res.Id.Name, q.namePrefix) { return false } diff --git a/internal/storage/inmem/snapshot_test.go b/internal/storage/inmem/snapshot_test.go index f3e1bdbaa79e..d19d5b13ee2c 100644 --- a/internal/storage/inmem/snapshot_test.go +++ b/internal/storage/inmem/snapshot_test.go @@ -28,7 +28,6 @@ func TestSnapshotRestore(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "default", - PeerName: "local", Namespace: "default", }, Name: "billing", @@ -51,7 +50,6 @@ func TestSnapshotRestore(t *testing.T) { }, Tenancy: &pbresource.Tenancy{ Partition: "default", - PeerName: "local", Namespace: "default", }, Name: "api", @@ -72,8 +70,14 @@ func TestSnapshotRestore(t *testing.T) { t.Cleanup(cancel) // Expect the initial state on the watch. - _, err = watch.Next(ctx) + got, err := watch.Next(ctx) + require.NoError(t, err) + require.NotNil(t, got.GetUpsert()) + + // expect to get snapshot end op + got, err = watch.Next(ctx) require.NoError(t, err) + require.NotNil(t, got.GetEndOfSnapshot()) restore, err := newStore.Restore() require.NoError(t, err) diff --git a/internal/storage/inmem/store.go b/internal/storage/inmem/store.go index d9c27d339fa3..99f4ddc3d5e4 100644 --- a/internal/storage/inmem/store.go +++ b/internal/storage/inmem/store.go @@ -141,7 +141,13 @@ func (s *Store) WriteCAS(res *pbresource.Resource, vsn string) error { } tx.Commit() - s.publishEvent(idx, pbresource.WatchEvent_OPERATION_UPSERT, res) + s.publishEvent(idx, &pbresource.WatchEvent{ + Event: &pbresource.WatchEvent_Upsert_{ + Upsert: &pbresource.WatchEvent_Upsert{ + Resource: res, + }, + }, + }) return nil } @@ -188,7 +194,13 @@ func (s *Store) DeleteCAS(id *pbresource.ID, vsn string) error { } tx.Commit() - s.publishEvent(idx, pbresource.WatchEvent_OPERATION_DELETE, res) + s.publishEvent(idx, &pbresource.WatchEvent{ + Event: &pbresource.WatchEvent_Delete_{ + Delete: &pbresource.WatchEvent_Delete{ + Resource: res, + }, + }, + }) return nil } @@ -234,8 +246,8 @@ func (s *Store) WatchList(typ storage.UnversionedType, ten *pbresource.Tenancy, // relevant resources only, which is far more efficient. var sub stream.Subject if ten.Partition == storage.Wildcard || - ten.PeerName == storage.Wildcard || ten.Namespace == storage.Wildcard { + // TODO(peering/v2) update conditional to handle peer tenancy wildcards sub = wildcardSubject{typ} } else { sub = tenancySubject{typ, ten} diff --git a/internal/storage/inmem/watch.go b/internal/storage/inmem/watch.go index bdab0fc5ee86..d0157abf0805 100644 --- a/internal/storage/inmem/watch.go +++ b/internal/storage/inmem/watch.go @@ -36,7 +36,20 @@ func (w *Watch) Next(ctx context.Context) (*pbresource.WatchEvent, error) { } event := e.Payload.(eventPayload).event - if w.query.matches(event.Resource) { + + var resource *pbresource.Resource + switch { + case event.GetUpsert() != nil: + resource = event.GetUpsert().GetResource() + case event.GetDelete() != nil: + resource = event.GetDelete().GetResource() + case event.GetEndOfSnapshot() != nil: + return event, nil + default: + return nil, fmt.Errorf("unexpected resource event type: %T", event.GetEvent()) + } + + if w.query.matches(resource) { return event, nil } } @@ -108,7 +121,8 @@ type eventPayload struct { func (p eventPayload) Subject() stream.Subject { return p.subject } // These methods are required by the stream.Payload interface, but we don't use them. -func (eventPayload) HasReadPermission(acl.Authorizer) bool { return false } +func (eventPayload) HasReadPermission(acl.Authorizer) bool { return false } + func (eventPayload) ToSubscriptionEvent(uint64) *pbsubscribe.Event { return nil } type wildcardSubject struct { @@ -122,6 +136,7 @@ func (s wildcardSubject) String() string { } type tenancySubject struct { + // TODO(peering/v2) update tenancy subject to account for peer tenancies resourceType storage.UnversionedType tenancy *pbresource.Tenancy } @@ -130,15 +145,22 @@ func (s tenancySubject) String() string { return s.resourceType.Group + indexSeparator + s.resourceType.Kind + indexSeparator + s.tenancy.Partition + indexSeparator + - s.tenancy.PeerName + indexSeparator + + s.tenancy.Namespace } // publishEvent sends the event to the relevant Watches. -func (s *Store) publishEvent(idx uint64, op pbresource.WatchEvent_Operation, res *pbresource.Resource) { - id := res.Id +func (s *Store) publishEvent(idx uint64, event *pbresource.WatchEvent) { + var id *pbresource.ID + switch { + case event.GetUpsert() != nil: + id = event.GetUpsert().GetResource().GetId() + case event.GetDelete() != nil: + id = event.GetDelete().GetResource().GetId() + default: + panic(fmt.Sprintf("(*Store).publishEvent cannot handle events of type %T", event.GetEvent())) + } resourceType := storage.UnversionedTypeFrom(id.Type) - event := &pbresource.WatchEvent{Operation: op, Resource: res} // We publish two copies of the event: one to the tenancy-specific subject and // another to a wildcard subject. Ideally, we'd be able to put the type in the @@ -179,9 +201,9 @@ func (s *Store) watchSnapshot(req stream.SubscribeRequest, snap stream.SnapshotA q.resourceType = t.resourceType q.tenancy = &pbresource.Tenancy{ Partition: storage.Wildcard, - PeerName: storage.Wildcard, Namespace: storage.Wildcard, } + // TODO(peering/v2) maybe handle wildcards in peer tenancy default: return 0, fmt.Errorf("unhandled subject type: %T", req.Subject) } @@ -199,20 +221,32 @@ func (s *Store) watchSnapshot(req stream.SubscribeRequest, snap stream.SnapshotA return 0, nil } - events := make([]stream.Event, len(results)) - for i, r := range results { - events[i] = stream.Event{ + events := make([]stream.Event, 0, len(results)+1) + addEvent := func(event *pbresource.WatchEvent) { + events = append(events, stream.Event{ Topic: eventTopic, Index: idx, Payload: eventPayload{ subject: req.Subject, - event: &pbresource.WatchEvent{ - Operation: pbresource.WatchEvent_OPERATION_UPSERT, - Resource: r, + event: event, + }, + }) + } + + for _, r := range results { + addEvent(&pbresource.WatchEvent{ + Event: &pbresource.WatchEvent_Upsert_{ + Upsert: &pbresource.WatchEvent_Upsert{ + Resource: r, }, }, - } + }) } + addEvent(&pbresource.WatchEvent{ + Event: &pbresource.WatchEvent_EndOfSnapshot_{ + EndOfSnapshot: &pbresource.WatchEvent_EndOfSnapshot{}, + }, + }) snap.Append(events) return idx, nil diff --git a/internal/storage/raft/conformance_test.go b/internal/storage/raft/conformance_test.go index 6c75e462d21c..21802ca67128 100644 --- a/internal/storage/raft/conformance_test.go +++ b/internal/storage/raft/conformance_test.go @@ -23,6 +23,9 @@ import ( ) func TestBackend_Conformance(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } t.Run("Leader", func(t *testing.T) { conformance.Test(t, conformance.TestOptions{ NewBackend: func(t *testing.T) storage.Backend { @@ -39,7 +42,8 @@ func TestBackend_Conformance(t *testing.T) { _, follower := newRaftCluster(t) return follower }, - SupportsStronglyConsistentList: true, + SupportsStronglyConsistentList: true, + IgnoreWatchListSnapshotOperations: true, }) }) } diff --git a/internal/tenancy/exports.go b/internal/tenancy/exports.go deleted file mode 100644 index 18340ce03924..000000000000 --- a/internal/tenancy/exports.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tenancy - -import ( - "github.com/hashicorp/consul/internal/controller" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/internal/tenancy/internal/bridge" - "github.com/hashicorp/consul/internal/tenancy/internal/controllers" - "github.com/hashicorp/consul/internal/tenancy/internal/types" -) - -type ( - V2TenancyBridge = bridge.V2TenancyBridge -) - -// RegisterTypes adds all resource types within the "tenancy" API group -// to the given type registry -func RegisterTypes(r resource.Registry) { - types.Register(r) -} - -// RegisterControllers registers controllers for the tenancy types with -// the given controller manager. -func RegisterControllers(mgr *controller.Manager, deps Dependencies) { - controllers.Register(mgr, deps) -} - -func NewV2TenancyBridge() *V2TenancyBridge { - return bridge.NewV2TenancyBridge() -} - -type Dependencies = controllers.Dependencies diff --git a/internal/tenancy/internal/bridge/tenancy_bridge.go b/internal/tenancy/internal/bridge/tenancy_bridge.go deleted file mode 100644 index db6a4dd53a17..000000000000 --- a/internal/tenancy/internal/bridge/tenancy_bridge.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package bridge - -import ( - "context" - - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" -) - -// V2TenancyBridge is used by the resource service to access V2 implementations of -// partitions and namespaces. -type V2TenancyBridge struct { - client pbresource.ResourceServiceClient -} - -// WithClient inject a ResourceServiceClient in the V2TenancyBridge. -// This is needed to break a circular dependency between -// the ResourceServiceServer, ResourceServiceClient and the TenancyBridge -func (b *V2TenancyBridge) WithClient(client pbresource.ResourceServiceClient) *V2TenancyBridge { - b.client = client - return b -} - -func NewV2TenancyBridge() *V2TenancyBridge { - return &V2TenancyBridge{} -} - -func (b *V2TenancyBridge) NamespaceExists(partition, namespace string) (bool, error) { - read, err := b.client.Read(context.Background(), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Name: namespace, - Tenancy: &pbresource.Tenancy{ - Partition: partition, - }, - Type: pbtenancy.NamespaceType, - }, - }) - return read != nil && read.Resource != nil, err -} - -func (b *V2TenancyBridge) IsNamespaceMarkedForDeletion(partition, namespace string) (bool, error) { - read, err := b.client.Read(context.Background(), &pbresource.ReadRequest{ - Id: &pbresource.ID{ - Name: namespace, - Tenancy: &pbresource.Tenancy{ - Partition: partition, - }, - Type: pbtenancy.NamespaceType, - }, - }) - return read.Resource != nil, err -} diff --git a/internal/tenancy/internal/bridge/tenancy_bridge_ce.go b/internal/tenancy/internal/bridge/tenancy_bridge_ce.go deleted file mode 100644 index dcf4df663cc7..000000000000 --- a/internal/tenancy/internal/bridge/tenancy_bridge_ce.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent - -package bridge - -func (b *V2TenancyBridge) PartitionExists(partition string) (bool, error) { - if partition == "default" { - return true, nil - } - return false, nil -} - -func (b *V2TenancyBridge) IsPartitionMarkedForDeletion(partition string) (bool, error) { - return false, nil -} diff --git a/internal/tenancy/internal/controllers/register.go b/internal/tenancy/internal/controllers/register.go deleted file mode 100644 index 94b4255baeb5..000000000000 --- a/internal/tenancy/internal/controllers/register.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package controllers - -import ( - "github.com/hashicorp/consul/internal/resource" -) - -type Dependencies struct { - Registry resource.Registry -} diff --git a/internal/tenancy/internal/controllers/register_ce.go b/internal/tenancy/internal/controllers/register_ce.go deleted file mode 100644 index a1623e5e95b5..000000000000 --- a/internal/tenancy/internal/controllers/register_ce.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent - -package controllers - -import ( - "github.com/hashicorp/consul/internal/controller" -) - -func Register(mgr *controller.Manager, deps Dependencies) { - //mgr.Register(namespace.NamespaceController()) -} diff --git a/internal/tenancy/internal/types/errors.go b/internal/tenancy/internal/types/errors.go deleted file mode 100644 index 42df9b319fb7..000000000000 --- a/internal/tenancy/internal/types/errors.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import "errors" - -var ( - errInvalidName = errors.New("invalid namespace name provided") - errOwnerNonEmpty = errors.New("namespace should not have an owner") -) diff --git a/internal/tenancy/internal/types/namespace.go b/internal/tenancy/internal/types/namespace.go deleted file mode 100644 index c45b405e8b32..000000000000 --- a/internal/tenancy/internal/types/namespace.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "fmt" - "strings" - - "github.com/hashicorp/consul/agent/dns" - "github.com/hashicorp/consul/internal/resource" - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" -) - -func RegisterNamespace(r resource.Registry) { - r.Register(resource.Registration{ - Type: pbtenancy.NamespaceType, - Proto: &pbtenancy.Namespace{}, - Scope: resource.ScopePartition, - Validate: ValidateNamespace, - // ACLs: TODO - }) -} - -func ValidateNamespace(res *pbresource.Resource) error { - var ns pbtenancy.Namespace - - if err := res.Data.UnmarshalTo(&ns); err != nil { - return resource.NewErrDataParse(&ns, err) - } - if res.Owner != nil { - return errOwnerNonEmpty - } - - // it's not allowed to create default/default tenancy - if res.Id.Name == resource.DefaultNamespaceName && res.Id.Tenancy.Partition == resource.DefaultPartitionName { - return errInvalidName - } - - if !dns.IsValidLabel(res.Id.Name) { - return fmt.Errorf("namespace name %q is not a valid DNS hostname", res.Id.Name) - } - - switch strings.ToLower(res.Id.Name) { - case "system", "universal", "operator", "root": - return fmt.Errorf("namespace %q is reserved for future internal use", res.Id.Name) - default: - - return nil - } -} diff --git a/internal/tenancy/internal/types/types.go b/internal/tenancy/internal/types/types.go deleted file mode 100644 index 5955ade8a5d7..000000000000 --- a/internal/tenancy/internal/types/types.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -const ( - GroupName = "tenancy" - VersionV2Beta1 = "v2beta1" - CurrentVersion = VersionV2Beta1 -) diff --git a/internal/tenancy/internal/types/types_ce.go b/internal/tenancy/internal/types/types_ce.go deleted file mode 100644 index 8d475789710c..000000000000 --- a/internal/tenancy/internal/types/types_ce.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -//go:build !consulent - -package types - -import "github.com/hashicorp/consul/internal/resource" - -func Register(r resource.Registry) { - RegisterNamespace(r) -} diff --git a/internal/tenancy/internal/types/types_test.go b/internal/tenancy/internal/types/types_test.go deleted file mode 100644 index df22b71f13a2..000000000000 --- a/internal/tenancy/internal/types/types_test.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/known/anypb" - - "github.com/hashicorp/consul/internal/resource" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" -) - -func createNamespaceResource(t *testing.T, data protoreflect.ProtoMessage) *pbresource.Resource { - res := &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbtenancy.NamespaceType, - Tenancy: resource.DefaultPartitionedTenancy(), - Name: "ns1234", - }, - } - - var err error - res.Data, err = anypb.New(data) - require.NoError(t, err) - return res -} - -func TestValidateNamespace_Ok(t *testing.T) { - res := createNamespaceResource(t, validNamespace()) - - err := ValidateNamespace(res) - require.NoError(t, err) -} - -func TestValidateNamespace_defaultNamespace(t *testing.T) { - res := createNamespaceResource(t, validNamespace()) - res.Id.Name = resource.DefaultNamespaceName - - err := ValidateNamespace(res) - require.Error(t, err) - require.ErrorAs(t, err, &errInvalidName) -} - -func TestValidateNamespace_defaultNamespaceNonDefaultPartition(t *testing.T) { - res := createNamespaceResource(t, validNamespace()) - res.Id.Name = resource.DefaultNamespaceName - res.Id.Tenancy.Partition = "foo" - - err := ValidateNamespace(res) - require.NoError(t, err) -} - -func TestValidateNamespace_InvalidName(t *testing.T) { - res := createNamespaceResource(t, validNamespace()) - res.Id.Name = "-invalid" - - err := ValidateNamespace(res) - require.Error(t, err) - require.ErrorAs(t, err, &errInvalidName) -} - -func TestValidateNamespace_InvalidOwner(t *testing.T) { - res := createNamespaceResource(t, validNamespace()) - res.Owner = &pbresource.ID{} - err := ValidateNamespace(res) - - require.Error(t, err) - require.ErrorAs(t, err, &errOwnerNonEmpty) -} - -func TestValidateNamespace_ParseError(t *testing.T) { - // Any type other than the Namespace type would work - // to cause the error we are expecting - data := &pbcatalog.IP{Address: "198.18.0.1"} - - res := createNamespaceResource(t, data) - - err := ValidateNamespace(res) - require.Error(t, err) - require.ErrorAs(t, err, &resource.ErrDataParse{}) -} - -func TestValidateNamespace(t *testing.T) { - tests := []struct { - name string - namespaceName string - err string - }{ - {"system", "System", "namespace \"System\" is reserved for future internal use"}, - {"invalid", "-inval", "namespace name \"-inval\" is not a valid DNS hostname"}, - {"valid", "ns1", ""}, - {"space prefix", " foo", "namespace name \" foo\" is not a valid DNS hostname"}, - {"space suffix", "bar ", "namespace name \"bar \" is not a valid DNS hostname"}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - a, err := anypb.New(&pbtenancy.Namespace{}) - require.NoError(t, err) - res := &pbresource.Resource{Id: &pbresource.ID{Name: tt.namespaceName}, Data: a} - err = ValidateNamespace(res) - if tt.err == "" { - require.NoError(t, err) - } else { - require.Equal(t, err.Error(), tt.err) - } - - }) - } -} - -func validNamespace() *pbtenancy.Namespace { - return &pbtenancy.Namespace{ - Description: "ns namespace", - } -} diff --git a/internal/tenancy/tenancytest/namespace_test.go b/internal/tenancy/tenancytest/namespace_test.go deleted file mode 100644 index e2461c254cd2..000000000000 --- a/internal/tenancy/tenancytest/namespace_test.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package tenancytest - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - svc "github.com/hashicorp/consul/agent/grpc-external/services/resource" - svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" - "github.com/hashicorp/consul/internal/resource" - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - "github.com/hashicorp/consul/internal/tenancy" - "github.com/hashicorp/consul/proto-public/pbresource" - pbtenancy "github.com/hashicorp/consul/proto-public/pbtenancy/v2beta1" - "github.com/hashicorp/consul/proto/private/prototest" -) - -func TestWriteNamespace_Success(t *testing.T) { - v2TenancyBridge := tenancy.NewV2TenancyBridge() - config := svc.Config{TenancyBridge: v2TenancyBridge, UseV2Tenancy: true} - client := svctest.RunResourceServiceWithConfig(t, config, tenancy.RegisterTypes) - cl := rtest.NewClient(client) - - res := rtest.Resource(pbtenancy.NamespaceType, "ns1"). - WithTenancy(resource.DefaultPartitionedTenancy()). - WithData(t, validNamespace()). - Build() - - writeRsp, err := cl.Write(context.Background(), &pbresource.WriteRequest{Resource: res}) - require.NoError(t, err) - prototest.AssertDeepEqual(t, res.Id.Type, writeRsp.Resource.Id.Type) - prototest.AssertDeepEqual(t, res.Id.Tenancy, writeRsp.Resource.Id.Tenancy) - prototest.AssertDeepEqual(t, res.Id.Name, writeRsp.Resource.Id.Name) - prototest.AssertDeepEqual(t, res.Data, writeRsp.Resource.Data) -} - -func TestReadNamespace_Success(t *testing.T) { - v2TenancyBridge := tenancy.NewV2TenancyBridge() - config := svc.Config{TenancyBridge: v2TenancyBridge, UseV2Tenancy: true} - client := svctest.RunResourceServiceWithConfig(t, config, tenancy.RegisterTypes) - cl := rtest.NewClient(client) - - res := rtest.Resource(pbtenancy.NamespaceType, "ns1"). - WithData(t, validNamespace()). - Write(t, cl) - - cases := []struct { - name string - resource *pbresource.Resource - errMsg string - }{ - { - name: "read namespace", - resource: rtest.Resource(pbtenancy.NamespaceType, "ns1"). - WithData(t, validNamespace()). - Build(), - }, - } - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - readRsp, err := cl.Read(context.Background(), &pbresource.ReadRequest{Id: tc.resource.Id}) - require.NoError(t, err) - prototest.AssertDeepEqual(t, res.Id, readRsp.Resource.Id) - prototest.AssertDeepEqual(t, res.Data, readRsp.Resource.Data) - }) - } -} - -func TestDeleteNamespace_Success(t *testing.T) { - v2TenancyBridge := tenancy.NewV2TenancyBridge() - config := svc.Config{TenancyBridge: v2TenancyBridge, UseV2Tenancy: true} - client := svctest.RunResourceServiceWithConfig(t, config, tenancy.RegisterTypes) - cl := rtest.NewClient(client) - - res := rtest.Resource(pbtenancy.NamespaceType, "ns1"). - WithData(t, validNamespace()).Write(t, cl) - - readRsp, err := cl.Read(context.Background(), &pbresource.ReadRequest{Id: res.Id}) - require.NoError(t, err) - prototest.AssertDeepEqual(t, res.Id, readRsp.Resource.Id) - - _, err = cl.Delete(context.Background(), &pbresource.DeleteRequest{Id: res.Id}) - require.NoError(t, err) - - _, err = cl.Read(context.Background(), &pbresource.ReadRequest{Id: res.Id}) - require.Error(t, err) - require.Equal(t, codes.NotFound.String(), status.Code(err).String()) - -} - -func TestListNamespace_Success(t *testing.T) { - v2TenancyBridge := tenancy.NewV2TenancyBridge() - config := svc.Config{TenancyBridge: v2TenancyBridge, UseV2Tenancy: true} - client := svctest.RunResourceServiceWithConfig(t, config, tenancy.RegisterTypes) - cl := rtest.NewClient(client) - - res := rtest.Resource(pbtenancy.NamespaceType, "ns1"). - WithData(t, validNamespace()).Write(t, cl) - - require.NotNil(t, res) - res = rtest.Resource(pbtenancy.NamespaceType, "ns2"). - WithData(t, validNamespace()).Write(t, cl) - - require.NotNil(t, res) - - listRsp, err := cl.List(context.Background(), &pbresource.ListRequest{Type: pbtenancy.NamespaceType, Tenancy: resource.DefaultPartitionedTenancy()}) - require.NoError(t, err) - require.Len(t, listRsp.Resources, 3) - names := []string{ - listRsp.Resources[0].Id.Name, - listRsp.Resources[1].Id.Name, - listRsp.Resources[2].Id.Name, - } - require.Contains(t, names, "default") - require.Contains(t, names, "ns1") - require.Contains(t, names, "ns2") -} - -func validNamespace() *pbtenancy.Namespace { - return &pbtenancy.Namespace{ - Description: "ns namespace", - } -} diff --git a/internal/testing/errors/errors.go b/internal/testing/errors/errors.go new file mode 100644 index 000000000000..c56d927c1882 --- /dev/null +++ b/internal/testing/errors/errors.go @@ -0,0 +1,41 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package errors + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/internal/testing/golden" +) + +func goldenError(t *testing.T, name string, actual string) { + t.Helper() + + expected := golden.Get(t, actual, name+".golden") + require.Equal(t, expected, actual) +} + +func TestErrorStrings(t *testing.T, cases map[string]error) { + for name, err := range cases { + t.Run(name, func(t *testing.T) { + goldenError(t, name, err.Error()) + }) + } +} + +type UnwrapErrorTestCase struct { + Err error + Expected error +} + +func TestErrorUnwrap(t *testing.T, cases map[string]UnwrapErrorTestCase) { + for name, tcase := range cases { + t.Run(name, func(t *testing.T) { + require.Equal(t, tcase.Expected, errors.Unwrap(tcase.Err)) + }) + } +} diff --git a/internal/testing/golden/golden.go b/internal/testing/golden/golden.go index a4d971d0d096..7146261a7eb7 100644 --- a/internal/testing/golden/golden.go +++ b/internal/testing/golden/golden.go @@ -22,7 +22,7 @@ var update = flag.Bool("update", false, "update golden files") // to the value of actual. func Get(t *testing.T, actual, filename string) string { t.Helper() - return string(GetBytes(t, actual, filename)) + return string(GetBytes(t, []byte(actual), filename)) } // GetBytes reads the expected value from the file at filename and returns the @@ -30,7 +30,7 @@ func Get(t *testing.T, actual, filename string) string { // // If the `-update` flag is used with `go test`, the golden file will be updated // to the value of actual. -func GetBytes(t *testing.T, actual, filename string) []byte { +func GetBytes(t *testing.T, actual []byte, filename string) []byte { t.Helper() path := filepath.Join("testdata", filename) @@ -38,7 +38,7 @@ func GetBytes(t *testing.T, actual, filename string) []byte { if dir := filepath.Dir(path); dir != "." { require.NoError(t, os.MkdirAll(dir, 0755)) } - err := os.WriteFile(path, []byte(actual), 0644) + err := os.WriteFile(path, actual, 0644) require.NoError(t, err) } diff --git a/internal/tools/proto-gen-rpc-glue/go.mod b/internal/tools/proto-gen-rpc-glue/go.mod index 0dc54c62dfeb..61d5a7ac53e7 100644 --- a/internal/tools/proto-gen-rpc-glue/go.mod +++ b/internal/tools/proto-gen-rpc-glue/go.mod @@ -2,7 +2,7 @@ module github.com/hashicorp/consul/internal/tools/proto-gen-rpc-glue go 1.17 -require github.com/stretchr/testify v1.8.3 +require github.com/stretchr/testify v1.8.4 require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect diff --git a/internal/tools/proto-gen-rpc-glue/go.sum b/internal/tools/proto-gen-rpc-glue/go.sum index 5135bf7e717a..22d891596901 100644 --- a/internal/tools/proto-gen-rpc-glue/go.sum +++ b/internal/tools/proto-gen-rpc-glue/go.sum @@ -23,8 +23,8 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/internal/tools/protoc-gen-consul-rate-limit/go.mod b/internal/tools/protoc-gen-consul-rate-limit/go.mod index 1337ca7371eb..efaf0bd81323 100644 --- a/internal/tools/protoc-gen-consul-rate-limit/go.mod +++ b/internal/tools/protoc-gen-consul-rate-limit/go.mod @@ -6,7 +6,7 @@ replace github.com/hashicorp/consul/proto-public => ../../../proto-public require ( github.com/hashicorp/consul/proto-public v0.0.0-00010101000000-000000000000 - google.golang.org/protobuf v1.30.0 + google.golang.org/protobuf v1.33.0 ) require github.com/google/go-cmp v0.5.9 // indirect diff --git a/internal/tools/protoc-gen-consul-rate-limit/go.sum b/internal/tools/protoc-gen-consul-rate-limit/go.sum index a3ed1d4569d7..6c0bbb169295 100644 --- a/internal/tools/protoc-gen-consul-rate-limit/go.sum +++ b/internal/tools/protoc-gen-consul-rate-limit/go.sum @@ -1,8 +1,4 @@ -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/internal/tools/protoc-gen-consul-rate-limit/main.go b/internal/tools/protoc-gen-consul-rate-limit/main.go index 61d46dd8c77c..f07cb741cc82 100644 --- a/internal/tools/protoc-gen-consul-rate-limit/main.go +++ b/internal/tools/protoc-gen-consul-rate-limit/main.go @@ -62,7 +62,7 @@ const ( rpc %s(...) returns (...) { option (hashicorp.consul.internal.ratelimit.spec) = { operation_type: OPERATION_TYPE_READ | OPERATION_TYPE_WRITE | OPERATION_TYPE_EXEMPT, - operation_category: OPERATION_CATEGORY_ACL | OPERATION_CATEGORY_PEER_STREAM | OPERATION_CATEGORY_CONNECT_CA | OPERATION_CATEGORY_PARTITION | OPERATION_CATEGORY_PEERING | OPERATION_CATEGORY_SERVER_DISCOVERY | OPERATION_CATEGORY_DATAPLANE | OPERATION_CATEGORY_DNS | OPERATION_CATEGORY_SUBSCRIBE | OPERATION_CATEGORY_OPERATOR | OPERATION_CATEGORY_RESOURCE, + operation_category: OPERATION_CATEGORY_ACL | OPERATION_CATEGORY_PEER_STREAM | OPERATION_CATEGORY_CONNECT_CA | OPERATION_CATEGORY_PARTITION | OPERATION_CATEGORY_PEERING | OPERATION_CATEGORY_SERVER_DISCOVERY | OPERATION_CATEGORY_DATAPLANE | OPERATION_CATEGORY_DNS | OPERATION_CATEGORY_SUBSCRIBE | OPERATION_CATEGORY_OPERATOR | OPERATION_CATEGORY_RESOURCE | OPERATION_CATEGORY_CONFIGENTRY, }; } } diff --git a/internal/tools/protoc-gen-consul-rate-limit/postprocess/main.go b/internal/tools/protoc-gen-consul-rate-limit/postprocess/main.go index 570e2ebdac72..c90fa573210e 100644 --- a/internal/tools/protoc-gen-consul-rate-limit/postprocess/main.go +++ b/internal/tools/protoc-gen-consul-rate-limit/postprocess/main.go @@ -128,6 +128,8 @@ func (s spec) GoOperationCategory() string { return "rate.OperationCategoryPartition" case "OPERATION_CATEGORY_PEERING": return "rate.OperationCategoryPeering" + case "OPERATION_CATEGORY_CONFIGENTRY": + return "rate.OperationCategoryConfigEntry" case "OPERATION_CATEGORY_SERVER_DISCOVERY": return "rate.OperationCategoryServerDiscovery" case "OPERATION_CATEGORY_DATAPLANE": diff --git a/internal/tools/protoc-gen-grpc-clone/e2e/.mockery.yaml b/internal/tools/protoc-gen-grpc-clone/e2e/.mockery.yaml new file mode 100644 index 000000000000..b2e1235cfbf7 --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/e2e/.mockery.yaml @@ -0,0 +1,15 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +with-expecter: true +all: false +recursive: false +dir: . +outpkg: "e2e" +mockname: "{{.InterfaceName}}" +filename: "mock_{{.InterfaceName}}_test.go" +packages: + github.com/hashicorp/consul/internal/tools/protoc-gen-grpc-clone/e2e/proto: + interfaces: + SimpleClient: + Simple_FlowClient: diff --git a/internal/tools/protoc-gen-grpc-clone/e2e/e2e_test.go b/internal/tools/protoc-gen-grpc-clone/e2e/e2e_test.go new file mode 100644 index 000000000000..52cf22fe40ab --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/e2e/e2e_test.go @@ -0,0 +1,72 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package e2e + +import ( + context "context" + "testing" + + proto "github.com/hashicorp/consul/internal/tools/protoc-gen-grpc-clone/e2e/proto" + "github.com/hashicorp/consul/proto/private/prototest" + mock "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + grpc "google.golang.org/grpc" +) + +func TestCloningClient_Unary(t *testing.T) { + mclient := NewSimpleClient(t) + + expectedRequest := &proto.Req{Foo: "foo"} + expectedResponse := &proto.Resp{Bar: "bar"} + + mclient.EXPECT(). + Something(mock.Anything, mock.Anything). + RunAndReturn(func(_ context.Context, actualRequest *proto.Req, _ ...grpc.CallOption) (*proto.Resp, error) { + // The request object should have been cloned + prototest.AssertDeepEqual(t, expectedRequest, actualRequest) + require.NotSame(t, expectedRequest, actualRequest) + return expectedResponse, nil + }). + Once() + + cloner := proto.NewCloningSimpleClient(mclient) + + actualResponse, err := cloner.Something(context.Background(), expectedRequest) + require.NoError(t, err) + prototest.AssertDeepEqual(t, expectedResponse, actualResponse) + require.NotSame(t, expectedResponse, actualResponse) +} + +func TestCloningClient_StreamFromServer(t *testing.T) { + expectedRequest := &proto.Req{Foo: "foo"} + expectedResponse := &proto.Resp{Bar: "bar"} + + mstream := NewSimple_FlowClient(t) + mclient := NewSimpleClient(t) + + mclient.EXPECT(). + Flow(mock.Anything, mock.Anything). + RunAndReturn(func(_ context.Context, actualRequest *proto.Req, _ ...grpc.CallOption) (proto.Simple_FlowClient, error) { + // The request object should have been cloned + prototest.AssertDeepEqual(t, expectedRequest, actualRequest) + require.NotSame(t, expectedRequest, actualRequest) + + return mstream, nil + }). + Once() + mstream.EXPECT(). + Recv(). + Return(expectedResponse, nil) + + cloner := proto.NewCloningSimpleClient(mclient) + + stream, err := cloner.Flow(context.Background(), expectedRequest) + require.NoError(t, err) + require.NotNil(t, stream) + + actualResponse, err := stream.Recv() + require.NoError(t, err) + prototest.AssertDeepEqual(t, expectedResponse, actualResponse) + require.NotSame(t, expectedResponse, actualResponse) +} diff --git a/internal/tools/protoc-gen-grpc-clone/e2e/mock_SimpleClient_test.go b/internal/tools/protoc-gen-grpc-clone/e2e/mock_SimpleClient_test.go new file mode 100644 index 000000000000..29a427757d4c --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/e2e/mock_SimpleClient_test.go @@ -0,0 +1,180 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package e2e + +import ( + context "context" + + grpc "google.golang.org/grpc" + + mock "github.com/stretchr/testify/mock" + + proto "github.com/hashicorp/consul/internal/tools/protoc-gen-grpc-clone/e2e/proto" +) + +// SimpleClient is an autogenerated mock type for the SimpleClient type +type SimpleClient struct { + mock.Mock +} + +type SimpleClient_Expecter struct { + mock *mock.Mock +} + +func (_m *SimpleClient) EXPECT() *SimpleClient_Expecter { + return &SimpleClient_Expecter{mock: &_m.Mock} +} + +// Flow provides a mock function with given fields: ctx, in, opts +func (_m *SimpleClient) Flow(ctx context.Context, in *proto.Req, opts ...grpc.CallOption) (proto.Simple_FlowClient, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 proto.Simple_FlowClient + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *proto.Req, ...grpc.CallOption) (proto.Simple_FlowClient, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *proto.Req, ...grpc.CallOption) proto.Simple_FlowClient); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(proto.Simple_FlowClient) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *proto.Req, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SimpleClient_Flow_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Flow' +type SimpleClient_Flow_Call struct { + *mock.Call +} + +// Flow is a helper method to define mock.On call +// - ctx context.Context +// - in *proto.Req +// - opts ...grpc.CallOption +func (_e *SimpleClient_Expecter) Flow(ctx interface{}, in interface{}, opts ...interface{}) *SimpleClient_Flow_Call { + return &SimpleClient_Flow_Call{Call: _e.mock.On("Flow", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *SimpleClient_Flow_Call) Run(run func(ctx context.Context, in *proto.Req, opts ...grpc.CallOption)) *SimpleClient_Flow_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*proto.Req), variadicArgs...) + }) + return _c +} + +func (_c *SimpleClient_Flow_Call) Return(_a0 proto.Simple_FlowClient, _a1 error) *SimpleClient_Flow_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SimpleClient_Flow_Call) RunAndReturn(run func(context.Context, *proto.Req, ...grpc.CallOption) (proto.Simple_FlowClient, error)) *SimpleClient_Flow_Call { + _c.Call.Return(run) + return _c +} + +// Something provides a mock function with given fields: ctx, in, opts +func (_m *SimpleClient) Something(ctx context.Context, in *proto.Req, opts ...grpc.CallOption) (*proto.Resp, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *proto.Resp + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *proto.Req, ...grpc.CallOption) (*proto.Resp, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *proto.Req, ...grpc.CallOption) *proto.Resp); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*proto.Resp) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *proto.Req, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SimpleClient_Something_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Something' +type SimpleClient_Something_Call struct { + *mock.Call +} + +// Something is a helper method to define mock.On call +// - ctx context.Context +// - in *proto.Req +// - opts ...grpc.CallOption +func (_e *SimpleClient_Expecter) Something(ctx interface{}, in interface{}, opts ...interface{}) *SimpleClient_Something_Call { + return &SimpleClient_Something_Call{Call: _e.mock.On("Something", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *SimpleClient_Something_Call) Run(run func(ctx context.Context, in *proto.Req, opts ...grpc.CallOption)) *SimpleClient_Something_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*proto.Req), variadicArgs...) + }) + return _c +} + +func (_c *SimpleClient_Something_Call) Return(_a0 *proto.Resp, _a1 error) *SimpleClient_Something_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SimpleClient_Something_Call) RunAndReturn(run func(context.Context, *proto.Req, ...grpc.CallOption) (*proto.Resp, error)) *SimpleClient_Something_Call { + _c.Call.Return(run) + return _c +} + +// NewSimpleClient creates a new instance of SimpleClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewSimpleClient(t interface { + mock.TestingT + Cleanup(func()) +}) *SimpleClient { + mock := &SimpleClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/tools/protoc-gen-grpc-clone/e2e/mock_Simple_FlowClient_test.go b/internal/tools/protoc-gen-grpc-clone/e2e/mock_Simple_FlowClient_test.go new file mode 100644 index 000000000000..2d3bbc4b09d0 --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/e2e/mock_Simple_FlowClient_test.go @@ -0,0 +1,356 @@ +// Code generated by mockery v2.37.1. DO NOT EDIT. + +package e2e + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + metadata "google.golang.org/grpc/metadata" + + proto "github.com/hashicorp/consul/internal/tools/protoc-gen-grpc-clone/e2e/proto" +) + +// Simple_FlowClient is an autogenerated mock type for the Simple_FlowClient type +type Simple_FlowClient struct { + mock.Mock +} + +type Simple_FlowClient_Expecter struct { + mock *mock.Mock +} + +func (_m *Simple_FlowClient) EXPECT() *Simple_FlowClient_Expecter { + return &Simple_FlowClient_Expecter{mock: &_m.Mock} +} + +// CloseSend provides a mock function with given fields: +func (_m *Simple_FlowClient) CloseSend() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Simple_FlowClient_CloseSend_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CloseSend' +type Simple_FlowClient_CloseSend_Call struct { + *mock.Call +} + +// CloseSend is a helper method to define mock.On call +func (_e *Simple_FlowClient_Expecter) CloseSend() *Simple_FlowClient_CloseSend_Call { + return &Simple_FlowClient_CloseSend_Call{Call: _e.mock.On("CloseSend")} +} + +func (_c *Simple_FlowClient_CloseSend_Call) Run(run func()) *Simple_FlowClient_CloseSend_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Simple_FlowClient_CloseSend_Call) Return(_a0 error) *Simple_FlowClient_CloseSend_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Simple_FlowClient_CloseSend_Call) RunAndReturn(run func() error) *Simple_FlowClient_CloseSend_Call { + _c.Call.Return(run) + return _c +} + +// Context provides a mock function with given fields: +func (_m *Simple_FlowClient) Context() context.Context { + ret := _m.Called() + + var r0 context.Context + if rf, ok := ret.Get(0).(func() context.Context); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(context.Context) + } + } + + return r0 +} + +// Simple_FlowClient_Context_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Context' +type Simple_FlowClient_Context_Call struct { + *mock.Call +} + +// Context is a helper method to define mock.On call +func (_e *Simple_FlowClient_Expecter) Context() *Simple_FlowClient_Context_Call { + return &Simple_FlowClient_Context_Call{Call: _e.mock.On("Context")} +} + +func (_c *Simple_FlowClient_Context_Call) Run(run func()) *Simple_FlowClient_Context_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Simple_FlowClient_Context_Call) Return(_a0 context.Context) *Simple_FlowClient_Context_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Simple_FlowClient_Context_Call) RunAndReturn(run func() context.Context) *Simple_FlowClient_Context_Call { + _c.Call.Return(run) + return _c +} + +// Header provides a mock function with given fields: +func (_m *Simple_FlowClient) Header() (metadata.MD, error) { + ret := _m.Called() + + var r0 metadata.MD + var r1 error + if rf, ok := ret.Get(0).(func() (metadata.MD, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() metadata.MD); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(metadata.MD) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Simple_FlowClient_Header_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Header' +type Simple_FlowClient_Header_Call struct { + *mock.Call +} + +// Header is a helper method to define mock.On call +func (_e *Simple_FlowClient_Expecter) Header() *Simple_FlowClient_Header_Call { + return &Simple_FlowClient_Header_Call{Call: _e.mock.On("Header")} +} + +func (_c *Simple_FlowClient_Header_Call) Run(run func()) *Simple_FlowClient_Header_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Simple_FlowClient_Header_Call) Return(_a0 metadata.MD, _a1 error) *Simple_FlowClient_Header_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Simple_FlowClient_Header_Call) RunAndReturn(run func() (metadata.MD, error)) *Simple_FlowClient_Header_Call { + _c.Call.Return(run) + return _c +} + +// Recv provides a mock function with given fields: +func (_m *Simple_FlowClient) Recv() (*proto.Resp, error) { + ret := _m.Called() + + var r0 *proto.Resp + var r1 error + if rf, ok := ret.Get(0).(func() (*proto.Resp, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() *proto.Resp); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*proto.Resp) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Simple_FlowClient_Recv_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Recv' +type Simple_FlowClient_Recv_Call struct { + *mock.Call +} + +// Recv is a helper method to define mock.On call +func (_e *Simple_FlowClient_Expecter) Recv() *Simple_FlowClient_Recv_Call { + return &Simple_FlowClient_Recv_Call{Call: _e.mock.On("Recv")} +} + +func (_c *Simple_FlowClient_Recv_Call) Run(run func()) *Simple_FlowClient_Recv_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Simple_FlowClient_Recv_Call) Return(_a0 *proto.Resp, _a1 error) *Simple_FlowClient_Recv_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Simple_FlowClient_Recv_Call) RunAndReturn(run func() (*proto.Resp, error)) *Simple_FlowClient_Recv_Call { + _c.Call.Return(run) + return _c +} + +// RecvMsg provides a mock function with given fields: m +func (_m *Simple_FlowClient) RecvMsg(m interface{}) error { + ret := _m.Called(m) + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Simple_FlowClient_RecvMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RecvMsg' +type Simple_FlowClient_RecvMsg_Call struct { + *mock.Call +} + +// RecvMsg is a helper method to define mock.On call +// - m interface{} +func (_e *Simple_FlowClient_Expecter) RecvMsg(m interface{}) *Simple_FlowClient_RecvMsg_Call { + return &Simple_FlowClient_RecvMsg_Call{Call: _e.mock.On("RecvMsg", m)} +} + +func (_c *Simple_FlowClient_RecvMsg_Call) Run(run func(m interface{})) *Simple_FlowClient_RecvMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *Simple_FlowClient_RecvMsg_Call) Return(_a0 error) *Simple_FlowClient_RecvMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Simple_FlowClient_RecvMsg_Call) RunAndReturn(run func(interface{}) error) *Simple_FlowClient_RecvMsg_Call { + _c.Call.Return(run) + return _c +} + +// SendMsg provides a mock function with given fields: m +func (_m *Simple_FlowClient) SendMsg(m interface{}) error { + ret := _m.Called(m) + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(m) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Simple_FlowClient_SendMsg_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendMsg' +type Simple_FlowClient_SendMsg_Call struct { + *mock.Call +} + +// SendMsg is a helper method to define mock.On call +// - m interface{} +func (_e *Simple_FlowClient_Expecter) SendMsg(m interface{}) *Simple_FlowClient_SendMsg_Call { + return &Simple_FlowClient_SendMsg_Call{Call: _e.mock.On("SendMsg", m)} +} + +func (_c *Simple_FlowClient_SendMsg_Call) Run(run func(m interface{})) *Simple_FlowClient_SendMsg_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(interface{})) + }) + return _c +} + +func (_c *Simple_FlowClient_SendMsg_Call) Return(_a0 error) *Simple_FlowClient_SendMsg_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Simple_FlowClient_SendMsg_Call) RunAndReturn(run func(interface{}) error) *Simple_FlowClient_SendMsg_Call { + _c.Call.Return(run) + return _c +} + +// Trailer provides a mock function with given fields: +func (_m *Simple_FlowClient) Trailer() metadata.MD { + ret := _m.Called() + + var r0 metadata.MD + if rf, ok := ret.Get(0).(func() metadata.MD); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(metadata.MD) + } + } + + return r0 +} + +// Simple_FlowClient_Trailer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Trailer' +type Simple_FlowClient_Trailer_Call struct { + *mock.Call +} + +// Trailer is a helper method to define mock.On call +func (_e *Simple_FlowClient_Expecter) Trailer() *Simple_FlowClient_Trailer_Call { + return &Simple_FlowClient_Trailer_Call{Call: _e.mock.On("Trailer")} +} + +func (_c *Simple_FlowClient_Trailer_Call) Run(run func()) *Simple_FlowClient_Trailer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Simple_FlowClient_Trailer_Call) Return(_a0 metadata.MD) *Simple_FlowClient_Trailer_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Simple_FlowClient_Trailer_Call) RunAndReturn(run func() metadata.MD) *Simple_FlowClient_Trailer_Call { + _c.Call.Return(run) + return _c +} + +// NewSimple_FlowClient creates a new instance of Simple_FlowClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewSimple_FlowClient(t interface { + mock.TestingT + Cleanup(func()) +}) *Simple_FlowClient { + mock := &Simple_FlowClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/tools/protoc-gen-grpc-clone/e2e/proto/buf.gen.yaml b/internal/tools/protoc-gen-grpc-clone/e2e/proto/buf.gen.yaml new file mode 100644 index 000000000000..fca6a8b23b18 --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/e2e/proto/buf.gen.yaml @@ -0,0 +1,22 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +version: v1 +managed: + enabled: true + go_package_prefix: + default: github.com/hashicorp/consul/internal/tools/protoc-gen-grpc-clone/e2e/proto +plugins: + - name: go + out: . + opt: + - paths=source_relative + - name: go-grpc + out: . + opt: + - paths=source_relative + - require_unimplemented_servers=false + - name: grpc-clone + out: . + opt: + - paths=source_relative diff --git a/internal/tools/protoc-gen-grpc-clone/e2e/proto/cloning_stream.pb.go b/internal/tools/protoc-gen-grpc-clone/e2e/proto/cloning_stream.pb.go new file mode 100644 index 000000000000..69f03db94d7b --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/e2e/proto/cloning_stream.pb.go @@ -0,0 +1,31 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package proto + +import ( + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +type serverStream[T proto.Message] interface { + Recv() (T, error) + grpc.ClientStream +} + +type cloningStream[T proto.Message] struct { + serverStream[T] +} + +func newCloningStream[T proto.Message](stream serverStream[T]) cloningStream[T] { + return cloningStream[T]{serverStream: stream} +} + +func (st cloningStream[T]) Recv() (T, error) { + var zero T + val, err := st.serverStream.Recv() + if err != nil { + return zero, err + } + + return proto.Clone(val).(T), nil +} diff --git a/internal/tools/protoc-gen-grpc-clone/e2e/proto/service.pb.go b/internal/tools/protoc-gen-grpc-clone/e2e/proto/service.pb.go new file mode 100644 index 000000000000..4703ce28cb8d --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/e2e/proto/service.pb.go @@ -0,0 +1,258 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL + +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc (unknown) +// source: service.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Req struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Foo string `protobuf:"bytes,1,opt,name=Foo,proto3" json:"Foo,omitempty"` +} + +func (x *Req) Reset() { + *x = Req{} + if protoimpl.UnsafeEnabled { + mi := &file_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Req) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Req) ProtoMessage() {} + +func (x *Req) ProtoReflect() protoreflect.Message { + mi := &file_service_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Req.ProtoReflect.Descriptor instead. +func (*Req) Descriptor() ([]byte, []int) { + return file_service_proto_rawDescGZIP(), []int{0} +} + +func (x *Req) GetFoo() string { + if x != nil { + return x.Foo + } + return "" +} + +type Resp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Bar string `protobuf:"bytes,1,opt,name=Bar,proto3" json:"Bar,omitempty"` +} + +func (x *Resp) Reset() { + *x = Resp{} + if protoimpl.UnsafeEnabled { + mi := &file_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Resp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Resp) ProtoMessage() {} + +func (x *Resp) ProtoReflect() protoreflect.Message { + mi := &file_service_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Resp.ProtoReflect.Descriptor instead. +func (*Resp) Descriptor() ([]byte, []int) { + return file_service_proto_rawDescGZIP(), []int{1} +} + +func (x *Resp) GetBar() string { + if x != nil { + return x.Bar + } + return "" +} + +var File_service_proto protoreflect.FileDescriptor + +var file_service_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x37, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x63, 0x6c, 0x6f, 0x6e, 0x65, + 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x17, 0x0a, 0x03, 0x52, 0x65, 0x71, 0x12, + 0x10, 0x0a, 0x03, 0x46, 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x46, 0x6f, + 0x6f, 0x22, 0x18, 0x0a, 0x04, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x42, 0x61, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x42, 0x61, 0x72, 0x32, 0x9f, 0x02, 0x0a, 0x06, + 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x8a, 0x01, 0x0a, 0x09, 0x53, 0x6f, 0x6d, 0x65, 0x74, + 0x68, 0x69, 0x6e, 0x67, 0x12, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x67, 0x72, 0x70, 0x63, + 0x5f, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x52, + 0x65, 0x71, 0x1a, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x63, + 0x6c, 0x6f, 0x6e, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x65, 0x73, + 0x70, 0x22, 0x00, 0x12, 0x87, 0x01, 0x0a, 0x04, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x3c, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, + 0x67, 0x65, 0x6e, 0x5f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x1a, 0x3d, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x2e, 0x74, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x30, 0x01, 0x42, 0x8d, 0x03, + 0x0a, 0x3b, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x67, 0x72, 0x70, 0x63, 0x5f, + 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x0c, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x4a, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x2f, + 0x65, 0x32, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x49, 0x50, + 0x54, 0xaa, 0x02, 0x34, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x47, 0x65, 0x6e, 0x47, 0x72, 0x70, 0x63, 0x43, 0x6c, 0x6f, 0x6e, 0x65, + 0x2e, 0x54, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0xca, 0x02, 0x34, 0x48, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x47, 0x65, 0x6e, 0x47, 0x72, + 0x70, 0x63, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x5c, 0x54, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0xe2, + 0x02, 0x40, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x47, 0x65, 0x6e, 0x47, 0x72, 0x70, 0x63, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x5c, 0x54, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0xea, 0x02, 0x38, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x3a, 0x3a, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x47, 0x65, 0x6e, 0x47, 0x72, 0x70, 0x63, 0x43, + 0x6c, 0x6f, 0x6e, 0x65, 0x3a, 0x3a, 0x54, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_service_proto_rawDescOnce sync.Once + file_service_proto_rawDescData = file_service_proto_rawDesc +) + +func file_service_proto_rawDescGZIP() []byte { + file_service_proto_rawDescOnce.Do(func() { + file_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_proto_rawDescData) + }) + return file_service_proto_rawDescData +} + +var file_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_service_proto_goTypes = []interface{}{ + (*Req)(nil), // 0: hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Req + (*Resp)(nil), // 1: hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Resp +} +var file_service_proto_depIdxs = []int32{ + 0, // 0: hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Simple.Something:input_type -> hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Req + 0, // 1: hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Simple.Flow:input_type -> hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Req + 1, // 2: hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Simple.Something:output_type -> hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Resp + 1, // 3: hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Simple.Flow:output_type -> hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Resp + 2, // [2:4] is the sub-list for method output_type + 0, // [0:2] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_service_proto_init() } +func file_service_proto_init() { + if File_service_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Req); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Resp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_service_proto_goTypes, + DependencyIndexes: file_service_proto_depIdxs, + MessageInfos: file_service_proto_msgTypes, + }.Build() + File_service_proto = out.File + file_service_proto_rawDesc = nil + file_service_proto_goTypes = nil + file_service_proto_depIdxs = nil +} diff --git a/internal/tools/protoc-gen-grpc-clone/e2e/proto/service.proto b/internal/tools/protoc-gen-grpc-clone/e2e/proto/service.proto new file mode 100644 index 000000000000..2aabf1d7a182 --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/e2e/proto/service.proto @@ -0,0 +1,22 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL + +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +syntax = "proto3"; + +package hashicorp.consul.internal.protoc_gen_grpc_clone.testing; + +service Simple { + rpc Something(Req) returns (Resp) {} + rpc Flow(Req) returns (stream Resp) {} +} + +message Req { + string Foo = 1; +} + +message Resp { + string Bar = 1; +} diff --git a/internal/tools/protoc-gen-grpc-clone/e2e/proto/service_cloning_grpc.pb.go b/internal/tools/protoc-gen-grpc-clone/e2e/proto/service_cloning_grpc.pb.go new file mode 100644 index 000000000000..e255db7110dc --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/e2e/proto/service_cloning_grpc.pb.go @@ -0,0 +1,69 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package proto + +import ( + "context" + + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +// compile-time check to ensure that the generator is implementing all +// of the grpc client interfaces methods. +var _ SimpleClient = CloningSimpleClient{} + +// IsCloningSimpleClient is an interface that can be used to detect +// that a SimpleClient is using the in-memory transport and has already +// been wrapped with a with a CloningSimpleClient. +type IsCloningSimpleClient interface { + IsCloningSimpleClient() bool +} + +// CloningSimpleClient implements the SimpleClient interface by wrapping +// another implementation and copying all protobuf messages that pass through the client. +// This is mainly useful to wrap the an in-process client to insulate users of that +// client from having to care about potential immutability of data they receive or having +// the server implementation mutate their internal memory. +type CloningSimpleClient struct { + SimpleClient +} + +func NewCloningSimpleClient(client SimpleClient) SimpleClient { + if cloner, ok := client.(IsCloningSimpleClient); ok && cloner.IsCloningSimpleClient() { + // prevent a double clone if the underlying client is already the cloning client. + return client + } + + return CloningSimpleClient{ + SimpleClient: client, + } +} + +// IsCloningSimpleClient implements the IsCloningSimpleClient interface. This +// is only used to detect wrapped clients that would be double cloning data and prevent that. +func (c CloningSimpleClient) IsCloningSimpleClient() bool { + return true +} + +func (c CloningSimpleClient) Something(ctx context.Context, in *Req, opts ...grpc.CallOption) (*Resp, error) { + in = proto.Clone(in).(*Req) + + out, err := c.SimpleClient.Something(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*Resp), nil +} + +func (c CloningSimpleClient) Flow(ctx context.Context, in *Req, opts ...grpc.CallOption) (Simple_FlowClient, error) { + in = proto.Clone(in).(*Req) + + st, err := c.SimpleClient.Flow(ctx, in) + if err != nil { + return nil, err + } + + return newCloningStream[*Resp](st), nil +} diff --git a/internal/tools/protoc-gen-grpc-clone/e2e/proto/service_grpc.pb.go b/internal/tools/protoc-gen-grpc-clone/e2e/proto/service_grpc.pb.go new file mode 100644 index 000000000000..33344e287a1b --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/e2e/proto/service_grpc.pb.go @@ -0,0 +1,167 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc (unknown) +// source: service.proto + +package proto + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// SimpleClient is the client API for Simple service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type SimpleClient interface { + Something(ctx context.Context, in *Req, opts ...grpc.CallOption) (*Resp, error) + Flow(ctx context.Context, in *Req, opts ...grpc.CallOption) (Simple_FlowClient, error) +} + +type simpleClient struct { + cc grpc.ClientConnInterface +} + +func NewSimpleClient(cc grpc.ClientConnInterface) SimpleClient { + return &simpleClient{cc} +} + +func (c *simpleClient) Something(ctx context.Context, in *Req, opts ...grpc.CallOption) (*Resp, error) { + out := new(Resp) + err := c.cc.Invoke(ctx, "/hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Simple/Something", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *simpleClient) Flow(ctx context.Context, in *Req, opts ...grpc.CallOption) (Simple_FlowClient, error) { + stream, err := c.cc.NewStream(ctx, &Simple_ServiceDesc.Streams[0], "/hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Simple/Flow", opts...) + if err != nil { + return nil, err + } + x := &simpleFlowClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Simple_FlowClient interface { + Recv() (*Resp, error) + grpc.ClientStream +} + +type simpleFlowClient struct { + grpc.ClientStream +} + +func (x *simpleFlowClient) Recv() (*Resp, error) { + m := new(Resp) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// SimpleServer is the server API for Simple service. +// All implementations should embed UnimplementedSimpleServer +// for forward compatibility +type SimpleServer interface { + Something(context.Context, *Req) (*Resp, error) + Flow(*Req, Simple_FlowServer) error +} + +// UnimplementedSimpleServer should be embedded to have forward compatible implementations. +type UnimplementedSimpleServer struct { +} + +func (UnimplementedSimpleServer) Something(context.Context, *Req) (*Resp, error) { + return nil, status.Errorf(codes.Unimplemented, "method Something not implemented") +} +func (UnimplementedSimpleServer) Flow(*Req, Simple_FlowServer) error { + return status.Errorf(codes.Unimplemented, "method Flow not implemented") +} + +// UnsafeSimpleServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to SimpleServer will +// result in compilation errors. +type UnsafeSimpleServer interface { + mustEmbedUnimplementedSimpleServer() +} + +func RegisterSimpleServer(s grpc.ServiceRegistrar, srv SimpleServer) { + s.RegisterService(&Simple_ServiceDesc, srv) +} + +func _Simple_Something_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Req) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SimpleServer).Something(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Simple/Something", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SimpleServer).Something(ctx, req.(*Req)) + } + return interceptor(ctx, in, info, handler) +} + +func _Simple_Flow_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(Req) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(SimpleServer).Flow(m, &simpleFlowServer{stream}) +} + +type Simple_FlowServer interface { + Send(*Resp) error + grpc.ServerStream +} + +type simpleFlowServer struct { + grpc.ServerStream +} + +func (x *simpleFlowServer) Send(m *Resp) error { + return x.ServerStream.SendMsg(m) +} + +// Simple_ServiceDesc is the grpc.ServiceDesc for Simple service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Simple_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "hashicorp.consul.internal.protoc_gen_grpc_clone.testing.Simple", + HandlerType: (*SimpleServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Something", + Handler: _Simple_Something_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Flow", + Handler: _Simple_Flow_Handler, + ServerStreams: true, + }, + }, + Metadata: "service.proto", +} diff --git a/internal/tools/protoc-gen-grpc-clone/internal/generate/generate.go b/internal/tools/protoc-gen-grpc-clone/internal/generate/generate.go new file mode 100644 index 000000000000..a50604437d58 --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/internal/generate/generate.go @@ -0,0 +1,146 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package generate + +import ( + "embed" + "fmt" + "path/filepath" + "text/template" + + "google.golang.org/protobuf/compiler/protogen" +) + +func Generate(gp *protogen.Plugin) error { + g := newGenerator(gp) + return g.generate() +} + +type generator struct { + p *protogen.Plugin + directories map[string]pkgInfo +} + +func newGenerator(gp *protogen.Plugin) *generator { + return &generator{ + p: gp, + directories: make(map[string]pkgInfo), + } +} + +type pkgInfo struct { + impPath protogen.GoImportPath + pkgName protogen.GoPackageName +} + +func (g *generator) generate() error { + for _, file := range g.p.Files { + if !file.Generate { + continue + } + + if len(file.Services) < 1 { + continue + } + + err := g.generateFile(file) + if err != nil { + return fmt.Errorf("Failed to generate file %q: %w", file.Proto.GetName(), err) + } + } + + for dir, info := range g.directories { + genFile := g.p.NewGeneratedFile(filepath.Join(dir, "cloning_stream.pb.go"), info.impPath) + cloningTemplate.ExecuteTemplate(genFile, "cloning-stream.tmpl", map[string]string{"GoPackage": string(info.pkgName)}) + } + return nil +} + +func (g *generator) generateFile(file *protogen.File) error { + tdata := &templateData{ + PackageName: string(file.GoPackageName), + } + + filename := file.GeneratedFilenamePrefix + "_cloning_grpc.pb.go" + genFile := g.p.NewGeneratedFile(filename, file.GoImportPath) + + for _, svc := range file.Services { + svcTypes := &cloningServiceTypes{ + ClientTypeName: genFile.QualifiedGoIdent(protogen.GoIdent{GoName: svc.GoName + "Client", GoImportPath: file.GoImportPath}), + ServerTypeName: genFile.QualifiedGoIdent(protogen.GoIdent{GoName: svc.GoName + "Server", GoImportPath: file.GoImportPath}), + CloningClientTypeName: genFile.QualifiedGoIdent(protogen.GoIdent{GoName: "Cloning" + svc.GoName + "Client", GoImportPath: file.GoImportPath}), + ServiceName: svc.GoName, + } + + tsvc := cloningService{ + cloningServiceTypes: svcTypes, + } + + for _, method := range svc.Methods { + if method.Desc.IsStreamingClient() { + // when we need these we can implement this + panic("client streams are unsupported") + } + + if method.Desc.IsStreamingServer() { + tsvc.ServerStreamMethods = append(tsvc.ServerStreamMethods, &inmemMethod{ + cloningServiceTypes: svcTypes, + Method: method, + }) + + // record that we need to also generate the inmem stream client code + // into this directory + g.directories[filepath.Dir(filename)] = pkgInfo{impPath: file.GoImportPath, pkgName: file.GoPackageName} + } else { + tsvc.UnaryMethods = append(tsvc.UnaryMethods, &inmemMethod{ + cloningServiceTypes: svcTypes, + Method: method, + }) + } + } + + tdata.Services = append(tdata.Services, &tsvc) + } + + err := cloningTemplate.ExecuteTemplate(genFile, "file.tmpl", &tdata) + if err != nil { + return fmt.Errorf("Error rendering template: %w", err) + } + + return nil + +} + +type templateData struct { + PackageName string + Services []*cloningService + UsesStreaming bool +} + +type cloningService struct { + UnaryMethods []*inmemMethod + // ClientStreamMethods []*protogen.Method + ServerStreamMethods []*inmemMethod + // BidirectionStreamMethods []*protogen.Method + *cloningServiceTypes +} + +type cloningServiceTypes struct { + ClientTypeName string + ServerTypeName string + ServiceName string + CloningClientTypeName string +} + +type inmemMethod struct { + Method *protogen.Method + *cloningServiceTypes +} + +var ( + //go:embed templates + templates embed.FS + + cloningTemplate = template.Must(template.ParseFS(templates, "templates/*")) +) diff --git a/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/cloning-stream.tmpl b/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/cloning-stream.tmpl new file mode 100644 index 000000000000..cbbc180a7416 --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/cloning-stream.tmpl @@ -0,0 +1,31 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package {{.GoPackage}} + +import ( + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +type serverStream[T proto.Message] interface { + Recv() (T, error) + grpc.ClientStream +} + +type cloningStream[T proto.Message] struct { + serverStream[T] +} + +func newCloningStream[T proto.Message](stream serverStream[T]) cloningStream[T] { + return cloningStream[T]{serverStream: stream} +} + +func (st cloningStream[T]) Recv() (T, error) { + var zero T + val, err := st.serverStream.Recv() + if err != nil { + return zero, err + } + + return proto.Clone(val).(T), nil +} diff --git a/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/file.tmpl b/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/file.tmpl new file mode 100644 index 000000000000..d27c1a531952 --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/file.tmpl @@ -0,0 +1,14 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package {{ .PackageName }} + +import ( + "context" + + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +{{ range $service := .Services }} +{{ template "service.tmpl" $service }} +{{- end }} diff --git a/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/server-stream-method.tmpl b/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/server-stream-method.tmpl new file mode 100644 index 000000000000..e6a97bf08788 --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/server-stream-method.tmpl @@ -0,0 +1,10 @@ +func (c {{.CloningClientTypeName}}) {{.Method.GoName}}(ctx context.Context, in *{{.Method.Input.GoIdent.GoName}}, opts...grpc.CallOption) ({{.ServiceName}}_{{.Method.GoName}}Client, error) { + in = proto.Clone(in).(*{{.Method.Input.GoIdent.GoName}}) + + st, err := c.{{.ClientTypeName}}.{{.Method.GoName}}(ctx, in) + if err != nil { + return nil, err + } + + return newCloningStream[*{{.Method.Output.GoIdent.GoName}}](st), nil +} diff --git a/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/service.tmpl b/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/service.tmpl new file mode 100644 index 000000000000..ebdfbffe25a9 --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/service.tmpl @@ -0,0 +1,44 @@ +// compile-time check to ensure that the generator is implementing all +// of the grpc client interfaces methods. +var _ {{.ClientTypeName}} = {{.CloningClientTypeName}}{} + +// Is{{.CloningClientTypeName}} is an interface that can be used to detect +// that a {{.ClientTypeName}} is using the in-memory transport and has already +// been wrapped with a with a {{.CloningClientTypeName}}. +type Is{{.CloningClientTypeName}} interface { + Is{{.CloningClientTypeName}}() bool +} + +// {{.CloningClientTypeName}} implements the {{.ClientTypeName}} interface by wrapping +// another implementation and copying all protobuf messages that pass through the client. +// This is mainly useful to wrap the an in-process client to insulate users of that +// client from having to care about potential immutability of data they receive or having +// the server implementation mutate their internal memory. +type {{.CloningClientTypeName}} struct { + {{.ClientTypeName}} +} + +func New{{.CloningClientTypeName}}(client {{.ClientTypeName}}) {{.ClientTypeName}} { + if cloner, ok := client.(Is{{.CloningClientTypeName}}); ok && cloner.Is{{.CloningClientTypeName}}() { + // prevent a double clone if the underlying client is already the cloning client. + return client + } + + return {{.CloningClientTypeName}}{ + {{.ClientTypeName}}: client, + } +} + +// Is{{.CloningClientTypeName}} implements the Is{{.CloningClientTypeName}} interface. This +// is only used to detect wrapped clients that would be double cloning data and prevent that. +func (c {{.CloningClientTypeName}}) Is{{.CloningClientTypeName}}() bool { + return true +} + +{{ range $method := .UnaryMethods }} +{{ template "unary-method.tmpl" $method }} +{{ end }} + +{{ range $method := .ServerStreamMethods }} +{{ template "server-stream-method.tmpl" $method }} +{{- end}} diff --git a/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/unary-method.tmpl b/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/unary-method.tmpl new file mode 100644 index 000000000000..be67543ca56b --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/internal/generate/templates/unary-method.tmpl @@ -0,0 +1,10 @@ +func (c {{.CloningClientTypeName}}) {{.Method.GoName}}(ctx context.Context, in*{{.Method.Input.GoIdent.GoName}}, opts...grpc.CallOption) (*{{.Method.Output.GoIdent.GoName}}, error) { + in = proto.Clone(in).(*{{.Method.Input.GoIdent.GoName}}) + + out, err := c.{{.ClientTypeName}}.{{.Method.GoName}}(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*{{.Method.Output.GoIdent.GoName}}), nil +} diff --git a/internal/tools/protoc-gen-grpc-clone/main.go b/internal/tools/protoc-gen-grpc-clone/main.go new file mode 100644 index 000000000000..d7a4d75c06bb --- /dev/null +++ b/internal/tools/protoc-gen-grpc-clone/main.go @@ -0,0 +1,27 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package main + +import ( + "flag" + + "github.com/hashicorp/consul/internal/tools/protoc-gen-grpc-clone/internal/generate" + "google.golang.org/protobuf/compiler/protogen" + plugin "google.golang.org/protobuf/types/pluginpb" +) + +var ( + file = flag.String("file", "-", "where to load data from") +) + +func main() { + flag.Parse() + + protogen.Options{ + ParamFunc: flag.CommandLine.Set, + }.Run(func(gp *protogen.Plugin) error { + gp.SupportedFeatures = uint64(plugin.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) + return generate.Generate(gp) + }) +} diff --git a/lib/channels/deliver_latest.go b/lib/channels/deliver_latest.go new file mode 100644 index 000000000000..2e43c135e9e1 --- /dev/null +++ b/lib/channels/deliver_latest.go @@ -0,0 +1,35 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 +package channels + +import "fmt" + +// DeliverLatest will drain the channel discarding any messages if there are any and sends the current message. +func DeliverLatest[T any](val T, ch chan T) error { + // Send if chan is empty + select { + case ch <- val: + return nil + default: + } + + // If it falls through to here, the channel is not empty. + // Drain the channel. + done := false + for !done { + select { + case <-ch: + continue + default: + done = true + } + } + + // Attempt to send again. If it is not empty, throw an error + select { + case ch <- val: + return nil + default: + return fmt.Errorf("failed to deliver latest event: chan full again after draining") + } +} diff --git a/lib/hoststats/collector.go b/lib/hoststats/collector.go index fb316e0dce38..97b0bd5770f2 100644 --- a/lib/hoststats/collector.go +++ b/lib/hoststats/collector.go @@ -87,7 +87,7 @@ func (c *Collector) collect() { // Determine up-time uptime, err := host.Uptime() if err != nil { - c.logger.Error("failed to collect uptime stats", "error", err) + c.logger.Debug("failed to collect uptime stats", "error", err) uptime = 0 } hs.Uptime = uptime @@ -95,7 +95,7 @@ func (c *Collector) collect() { // Collect memory stats mstats, err := c.collectMemoryStats() if err != nil { - c.logger.Error("failed to collect memory stats", "error", err) + c.logger.Debug("failed to collect memory stats", "error", err) mstats = &MemoryStats{} } hs.Memory = mstats @@ -103,17 +103,19 @@ func (c *Collector) collect() { // Collect cpu stats cpus, err := c.collectCPUStats() if err != nil { - c.logger.Error("failed to collect cpu stats", "error", err) + c.logger.Debug("failed to collect cpu stats", "error", err) cpus = []*CPUStats{} } hs.CPU = cpus // Collect disk stats - diskStats, err := c.collectDiskStats(c.dataDir) - if err != nil { - c.logger.Error("failed to collect dataDir disk stats", "error", err) + if c.dataDir != "" { + diskStats, err := c.collectDiskStats(c.dataDir) + if err != nil { + c.logger.Debug("failed to collect dataDir disk stats", "error", err) + } + hs.DataDirStats = diskStats } - hs.DataDirStats = diskStats // Update the collected status object. c.hostStatsLock.Lock() diff --git a/lib/hoststats/collector_test.go b/lib/hoststats/collector_test.go new file mode 100644 index 000000000000..359046b660ed --- /dev/null +++ b/lib/hoststats/collector_test.go @@ -0,0 +1,48 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package hoststats + +import ( + "testing" + + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/sdk/testutil" +) + +// TestCollector_collect validates that metrics for host resource usage +// are collected as expected. +func TestCollector_collect(t *testing.T) { + testcases := map[string]struct { + skipDataDir bool + }{ + "WithDataDirectory": {}, + "NoDataDirectory": { + skipDataDir: true, + }, + } + for name, tc := range testcases { + t.Run(name, func(t *testing.T) { + dataDir := "" + if !tc.skipDataDir { + dataDir = testutil.TempDir(t, "consul-config") + } + + collector := initCollector(hclog.NewNullLogger(), dataDir) + collector.collect() + + hs := collector.hostStats + require.NotNil(t, hs) + require.Greater(t, hs.Uptime, uint64(0)) + require.NotNil(t, hs.Memory) + require.NotNil(t, hs.CPU) + if !tc.skipDataDir { + require.NotNil(t, hs.DataDirStats) + } else { + require.Nil(t, hs.DataDirStats) + } + }) + } +} diff --git a/lib/telemetry.go b/lib/telemetry.go index e06341eefb05..91b9d39a4d97 100644 --- a/lib/telemetry.go +++ b/lib/telemetry.go @@ -146,9 +146,14 @@ type TelemetryConfig struct { // DisableHostname will disable hostname prefixing for all metrics. // - // hcl: telemetry { disable_hostname = (true|false) + // hcl: telemetry { disable_hostname = (true|false) } DisableHostname bool `json:"disable_hostname,omitempty" mapstructure:"disable_hostname"` + // DisablePerTenancyUsageMetrics will disable setting tenancy labels on usage metrics. + // + // hcl: telemetry { disable_per_tenancy_usage_metrics = (true|false) } + DisablePerTenancyUsageMetrics bool `json:"disable_per_tenancy_usage_metrics,omitempty" mapstructure:"disable_per_tenancy_usage_metrics"` + // DogStatsdAddr is the address of a dogstatsd instance. If provided, // metrics will be sent to that instance // @@ -360,13 +365,9 @@ func configureSinks(cfg TelemetryConfig, memSink metrics.MetricSink, extraSinks } } - if len(sinks) > 0 { - sinks = append(sinks, memSink) - metrics.NewGlobal(metricsConf, sinks) - } else { - metricsConf.EnableHostname = false - metrics.NewGlobal(metricsConf, memSink) - } + sinks = append(sinks, memSink) + metrics.NewGlobal(metricsConf, sinks) + return sinks, errors } diff --git a/lib/testhelpers/testhelpers.go b/lib/testhelpers/testhelpers.go new file mode 100644 index 000000000000..0dfc07b549da --- /dev/null +++ b/lib/testhelpers/testhelpers.go @@ -0,0 +1,14 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 +package testhelpers + +import ( + "os" + "testing" +) + +func SkipFlake(t *testing.T) { + if os.Getenv("RUN_FLAKEY_TESTS") != "true" { + t.Skip("Skipped because marked as flake.") + } +} diff --git a/logging/logfile_bsd.go b/logging/logfile_bsd.go index df599358d047..21e579424563 100644 --- a/logging/logfile_bsd.go +++ b/logging/logfile_bsd.go @@ -14,5 +14,5 @@ import ( func (l *LogFile) createTime(stat os.FileInfo) time.Time { stat_t := stat.Sys().(*syscall.Stat_t) createTime := stat_t.Ctimespec - return time.Unix(int64(createTime.Sec), int64(createTime.Nsec)) + return time.Unix(int64(createTime.Sec), int64(createTime.Nsec)) //nolint:unconvert } diff --git a/logging/names.go b/logging/names.go index 69a859443cfb..b3bf817217a8 100644 --- a/logging/names.go +++ b/logging/names.go @@ -17,6 +17,7 @@ const ( CentralConfig string = "central_config" ConfigEntry string = "config_entry" Connect string = "connect" + ConnectCA string = "connect-ca" Consul string = "consul" ConsulClient string = "client" ConsulServer string = "server" @@ -57,6 +58,7 @@ const ( Snapshot string = "snapshot" Partition string = "partition" Peering string = "peering" + PeerStream string = "peerstream" PeeringMetrics string = "peering_metrics" TCPRouteController string = "tcp_route_controller" TerminatingGateway string = "terminating_gateway" @@ -70,5 +72,10 @@ const ( XDS string = "xds" XDSCapacityController string = "xds_capacity_controller" Vault string = "vault" + V2ExportsShim string = "v2_exports_shim" Health string = "health" + GRPCAPI string = "grpc-api" + Resource string = "resource" + Dataplane string = "dataplane" + ServerDiscovery string = "server-discovery" ) diff --git a/proto-public/.copywrite.hcl b/proto-public/.copywrite.hcl new file mode 100644 index 000000000000..60270bbeb95d --- /dev/null +++ b/proto-public/.copywrite.hcl @@ -0,0 +1,14 @@ +schema_version = 1 + +project { + license = "MPL-2.0" + copyright_year = 2024 + + # (OPTIONAL) A list of globs that should not have copyright/license headers. + # Supports doublestar glob patterns for more flexibility in defining which + # files or folders should be ignored + header_ignore = [ + # "vendor/**", + # "**autogen**", + ] +} diff --git a/proto-public/annotations/ratelimit/ratelimit.pb.go b/proto-public/annotations/ratelimit/ratelimit.pb.go index 3514d47ceb29..085507402aea 100644 --- a/proto-public/annotations/ratelimit/ratelimit.pb.go +++ b/proto-public/annotations/ratelimit/ratelimit.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: annotations/ratelimit/ratelimit.proto @@ -93,6 +93,7 @@ const ( OperationCategory_OPERATION_CATEGORY_SUBSCRIBE OperationCategory = 9 OperationCategory_OPERATION_CATEGORY_OPERATOR OperationCategory = 10 OperationCategory_OPERATION_CATEGORY_RESOURCE OperationCategory = 11 + OperationCategory_OPERATION_CATEGORY_CONFIGENTRY OperationCategory = 12 ) // Enum value maps for OperationCategory. @@ -110,6 +111,7 @@ var ( 9: "OPERATION_CATEGORY_SUBSCRIBE", 10: "OPERATION_CATEGORY_OPERATOR", 11: "OPERATION_CATEGORY_RESOURCE", + 12: "OPERATION_CATEGORY_CONFIGENTRY", } OperationCategory_value = map[string]int32{ "OPERATION_CATEGORY_UNSPECIFIED": 0, @@ -124,6 +126,7 @@ var ( "OPERATION_CATEGORY_SUBSCRIBE": 9, "OPERATION_CATEGORY_OPERATOR": 10, "OPERATION_CATEGORY_RESOURCE": 11, + "OPERATION_CATEGORY_CONFIGENTRY": 12, } ) @@ -257,7 +260,7 @@ var file_annotations_ratelimit_ratelimit_proto_rawDesc = []byte{ 0x4d, 0x50, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x03, 0x2a, 0xa7, 0x03, 0x0a, 0x11, 0x4f, 0x70, 0x65, + 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x03, 0x2a, 0xcb, 0x03, 0x0a, 0x11, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x22, 0x0a, 0x1e, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x41, 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, @@ -284,32 +287,34 @@ var file_annotations_ratelimit_ratelimit_proto_rawDesc = []byte{ 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x4f, 0x52, 0x10, 0x0a, 0x12, 0x1f, 0x0a, 0x1b, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x41, 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, - 0x10, 0x0b, 0x3a, 0x5e, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xec, 0x40, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x72, 0x61, - 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, - 0x65, 0x63, 0x42, 0xa9, 0x02, 0x0a, 0x27, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x42, 0x0e, - 0x52, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x52, 0xaa, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0xca, 0x02, 0x23, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x52, 0x61, 0x74, 0x65, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0xe2, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, - 0x52, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x26, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x52, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x10, 0x0b, 0x12, 0x22, 0x0a, 0x1e, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x43, 0x41, 0x54, 0x45, 0x47, 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x45, + 0x4e, 0x54, 0x52, 0x59, 0x10, 0x0c, 0x3a, 0x5e, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x1e, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xec, + 0x40, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x53, 0x70, 0x65, 0x63, + 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x42, 0xa9, 0x02, 0x0a, 0x27, 0x63, 0x6f, 0x6d, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x42, 0x0e, 0x52, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x61, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x72, 0x61, 0x74, 0x65, 0x6c, + 0x69, 0x6d, 0x69, 0x74, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x52, 0xaa, 0x02, 0x23, 0x48, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0xca, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x52, 0x61, + 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0xe2, 0x02, 0x2f, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x5c, 0x52, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x26, 0x48, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x52, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto-public/annotations/ratelimit/ratelimit.proto b/proto-public/annotations/ratelimit/ratelimit.proto index 9869d86f8538..27ba9c6041f2 100644 --- a/proto-public/annotations/ratelimit/ratelimit.proto +++ b/proto-public/annotations/ratelimit/ratelimit.proto @@ -29,6 +29,7 @@ enum OperationCategory { OPERATION_CATEGORY_SUBSCRIBE = 9; OPERATION_CATEGORY_OPERATOR = 10; OPERATION_CATEGORY_RESOURCE = 11; + OPERATION_CATEGORY_CONFIGENTRY = 12; } // Spec describes the kind of rate limit that will be applied to this RPC. diff --git a/proto-public/buf.gen.yaml b/proto-public/buf.gen.yaml index a58bd2511935..cc6c91041267 100644 --- a/proto-public/buf.gen.yaml +++ b/proto-public/buf.gen.yaml @@ -6,6 +6,9 @@ managed: enabled: true go_package_prefix: default: github.com/hashicorp/consul/proto-public + except: + - buf.build/k8s/api + plugins: - name: go out: . @@ -34,3 +37,9 @@ plugins: - name: json-shim out: . opt: paths=source_relative + # Generate cloning clients that can be used in conjunction with github.com/fullstorydev/grpchan/inprocgrpc + # to safely do gRPC in-process + - name: grpc-clone + out: . + opt: + - paths=source_relative diff --git a/proto-public/buf.lock b/proto-public/buf.lock new file mode 100644 index 000000000000..8efc15e857d5 --- /dev/null +++ b/proto-public/buf.lock @@ -0,0 +1,8 @@ +# Generated by buf. DO NOT EDIT. +version: v1 +deps: + - remote: buf.build + owner: k8s + repository: api + commit: 8f68e41b943c4de8a5e9c9a921c889a7 + digest: shake256:38ab77d24cf737d1204719a0ffc654056c29499f26b1546cc5af9ddb34e33799930d79d1f5a4a04b0f5c149097eabbeed37a5d2abf9552169a7d52011f6a8d6f diff --git a/proto-public/buf.yaml b/proto-public/buf.yaml index 878225723ea3..514843327354 100644 --- a/proto-public/buf.yaml +++ b/proto-public/buf.yaml @@ -2,6 +2,8 @@ # SPDX-License-Identifier: MPL-2.0 version: v1 +deps: + - buf.build/k8s/api name: buf.build/hashicorp/consul lint: use: @@ -19,3 +21,4 @@ lint: breaking: use: - FILE + diff --git a/proto-public/go.mod b/proto-public/go.mod index ab00c6c62e2c..f81687d5339a 100644 --- a/proto-public/go.mod +++ b/proto-public/go.mod @@ -3,23 +3,14 @@ module github.com/hashicorp/consul/proto-public go 1.19 require ( - github.com/stretchr/testify v1.8.3 - golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 google.golang.org/grpc v1.56.3 - google.golang.org/protobuf v1.30.0 + google.golang.org/protobuf v1.33.0 ) require ( - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/kr/pretty v0.3.0 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/proto-public/go.sum b/proto-public/go.sum index f11647a8490e..567126cd158e 100644 --- a/proto-public/go.sum +++ b/proto-public/go.sum @@ -1,57 +1,15 @@ -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/proto-public/pbacl/acl.pb.go b/proto-public/pbacl/acl.pb.go index f85a9e0b48e8..e8f18d870f72 100644 --- a/proto-public/pbacl/acl.pb.go +++ b/proto-public/pbacl/acl.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: pbacl/acl.proto diff --git a/proto-public/pbacl/acl_cloning_grpc.pb.go b/proto-public/pbacl/acl_cloning_grpc.pb.go new file mode 100644 index 000000000000..efd1cf0b52ff --- /dev/null +++ b/proto-public/pbacl/acl_cloning_grpc.pb.go @@ -0,0 +1,69 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package pbacl + +import ( + "context" + + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +// compile-time check to ensure that the generator is implementing all +// of the grpc client interfaces methods. +var _ ACLServiceClient = CloningACLServiceClient{} + +// IsCloningACLServiceClient is an interface that can be used to detect +// that a ACLServiceClient is using the in-memory transport and has already +// been wrapped with a with a CloningACLServiceClient. +type IsCloningACLServiceClient interface { + IsCloningACLServiceClient() bool +} + +// CloningACLServiceClient implements the ACLServiceClient interface by wrapping +// another implementation and copying all protobuf messages that pass through the client. +// This is mainly useful to wrap the an in-process client to insulate users of that +// client from having to care about potential immutability of data they receive or having +// the server implementation mutate their internal memory. +type CloningACLServiceClient struct { + ACLServiceClient +} + +func NewCloningACLServiceClient(client ACLServiceClient) ACLServiceClient { + if cloner, ok := client.(IsCloningACLServiceClient); ok && cloner.IsCloningACLServiceClient() { + // prevent a double clone if the underlying client is already the cloning client. + return client + } + + return CloningACLServiceClient{ + ACLServiceClient: client, + } +} + +// IsCloningACLServiceClient implements the IsCloningACLServiceClient interface. This +// is only used to detect wrapped clients that would be double cloning data and prevent that. +func (c CloningACLServiceClient) IsCloningACLServiceClient() bool { + return true +} + +func (c CloningACLServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) { + in = proto.Clone(in).(*LoginRequest) + + out, err := c.ACLServiceClient.Login(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*LoginResponse), nil +} + +func (c CloningACLServiceClient) Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*LogoutResponse, error) { + in = proto.Clone(in).(*LogoutRequest) + + out, err := c.ACLServiceClient.Logout(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*LogoutResponse), nil +} diff --git a/proto-public/pbauth/v2beta1/computed_traffic_permissions.pb.binary.go b/proto-public/pbauth/v2beta1/computed_traffic_permissions.pb.binary.go deleted file mode 100644 index 2e1f9bd89964..000000000000 --- a/proto-public/pbauth/v2beta1/computed_traffic_permissions.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbauth/v2beta1/computed_traffic_permissions.proto - -package authv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedTrafficPermissions) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedTrafficPermissions) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbauth/v2beta1/computed_traffic_permissions.pb.go b/proto-public/pbauth/v2beta1/computed_traffic_permissions.pb.go deleted file mode 100644 index b88c2e86bd03..000000000000 --- a/proto-public/pbauth/v2beta1/computed_traffic_permissions.pb.go +++ /dev/null @@ -1,201 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbauth/v2beta1/computed_traffic_permissions.proto - -package authv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ComputedTrafficPermissions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AllowPermissions []*Permission `protobuf:"bytes,1,rep,name=allow_permissions,json=allowPermissions,proto3" json:"allow_permissions,omitempty"` - DenyPermissions []*Permission `protobuf:"bytes,2,rep,name=deny_permissions,json=denyPermissions,proto3" json:"deny_permissions,omitempty"` - IsDefault bool `protobuf:"varint,3,opt,name=is_default,json=isDefault,proto3" json:"is_default,omitempty"` -} - -func (x *ComputedTrafficPermissions) Reset() { - *x = ComputedTrafficPermissions{} - if protoimpl.UnsafeEnabled { - mi := &file_pbauth_v2beta1_computed_traffic_permissions_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedTrafficPermissions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedTrafficPermissions) ProtoMessage() {} - -func (x *ComputedTrafficPermissions) ProtoReflect() protoreflect.Message { - mi := &file_pbauth_v2beta1_computed_traffic_permissions_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedTrafficPermissions.ProtoReflect.Descriptor instead. -func (*ComputedTrafficPermissions) Descriptor() ([]byte, []int) { - return file_pbauth_v2beta1_computed_traffic_permissions_proto_rawDescGZIP(), []int{0} -} - -func (x *ComputedTrafficPermissions) GetAllowPermissions() []*Permission { - if x != nil { - return x.AllowPermissions - } - return nil -} - -func (x *ComputedTrafficPermissions) GetDenyPermissions() []*Permission { - if x != nil { - return x.DenyPermissions - } - return nil -} - -func (x *ComputedTrafficPermissions) GetIsDefault() bool { - if x != nil { - return x.IsDefault - } - return false -} - -var File_pbauth_v2beta1_computed_traffic_permissions_proto protoreflect.FileDescriptor - -var file_pbauth_v2beta1_computed_traffic_permissions_proto_rawDesc = []byte{ - 0x0a, 0x31, 0x70, 0x62, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, - 0x63, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x1a, 0x28, 0x70, 0x62, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf1, 0x01, 0x0a, 0x1a, 0x43, - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x56, 0x0a, 0x11, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x10, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x54, 0x0a, 0x10, 0x64, 0x65, 0x6e, 0x79, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, - 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x64, 0x65, 0x6e, 0x79, 0x50, 0x65, 0x72, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x44, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x42, 0xa0, - 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x42, 0x1f, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, 0x72, - 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x2f, 0x70, 0x62, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x3b, 0x61, 0x75, 0x74, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, - 0x43, 0x41, 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x3a, 0x3a, 0x41, 0x75, 0x74, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbauth_v2beta1_computed_traffic_permissions_proto_rawDescOnce sync.Once - file_pbauth_v2beta1_computed_traffic_permissions_proto_rawDescData = file_pbauth_v2beta1_computed_traffic_permissions_proto_rawDesc -) - -func file_pbauth_v2beta1_computed_traffic_permissions_proto_rawDescGZIP() []byte { - file_pbauth_v2beta1_computed_traffic_permissions_proto_rawDescOnce.Do(func() { - file_pbauth_v2beta1_computed_traffic_permissions_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbauth_v2beta1_computed_traffic_permissions_proto_rawDescData) - }) - return file_pbauth_v2beta1_computed_traffic_permissions_proto_rawDescData -} - -var file_pbauth_v2beta1_computed_traffic_permissions_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbauth_v2beta1_computed_traffic_permissions_proto_goTypes = []interface{}{ - (*ComputedTrafficPermissions)(nil), // 0: hashicorp.consul.auth.v2beta1.ComputedTrafficPermissions - (*Permission)(nil), // 1: hashicorp.consul.auth.v2beta1.Permission -} -var file_pbauth_v2beta1_computed_traffic_permissions_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.auth.v2beta1.ComputedTrafficPermissions.allow_permissions:type_name -> hashicorp.consul.auth.v2beta1.Permission - 1, // 1: hashicorp.consul.auth.v2beta1.ComputedTrafficPermissions.deny_permissions:type_name -> hashicorp.consul.auth.v2beta1.Permission - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_pbauth_v2beta1_computed_traffic_permissions_proto_init() } -func file_pbauth_v2beta1_computed_traffic_permissions_proto_init() { - if File_pbauth_v2beta1_computed_traffic_permissions_proto != nil { - return - } - file_pbauth_v2beta1_traffic_permissions_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbauth_v2beta1_computed_traffic_permissions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedTrafficPermissions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbauth_v2beta1_computed_traffic_permissions_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbauth_v2beta1_computed_traffic_permissions_proto_goTypes, - DependencyIndexes: file_pbauth_v2beta1_computed_traffic_permissions_proto_depIdxs, - MessageInfos: file_pbauth_v2beta1_computed_traffic_permissions_proto_msgTypes, - }.Build() - File_pbauth_v2beta1_computed_traffic_permissions_proto = out.File - file_pbauth_v2beta1_computed_traffic_permissions_proto_rawDesc = nil - file_pbauth_v2beta1_computed_traffic_permissions_proto_goTypes = nil - file_pbauth_v2beta1_computed_traffic_permissions_proto_depIdxs = nil -} diff --git a/proto-public/pbauth/v2beta1/computed_traffic_permissions.proto b/proto-public/pbauth/v2beta1/computed_traffic_permissions.proto deleted file mode 100644 index 24127cc6a468..000000000000 --- a/proto-public/pbauth/v2beta1/computed_traffic_permissions.proto +++ /dev/null @@ -1,14 +0,0 @@ -syntax = "proto3"; - -package hashicorp.consul.auth.v2beta1; - -import "pbauth/v2beta1/traffic_permissions.proto"; -import "pbresource/annotations.proto"; - -message ComputedTrafficPermissions { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - repeated Permission allow_permissions = 1; - repeated Permission deny_permissions = 2; - bool is_default = 3; -} diff --git a/proto-public/pbauth/v2beta1/computed_traffic_permissions_deepcopy.gen.go b/proto-public/pbauth/v2beta1/computed_traffic_permissions_deepcopy.gen.go deleted file mode 100644 index 7c22d2285c2d..000000000000 --- a/proto-public/pbauth/v2beta1/computed_traffic_permissions_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package authv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ComputedTrafficPermissions within kubernetes types, where deepcopy-gen is used. -func (in *ComputedTrafficPermissions) DeepCopyInto(out *ComputedTrafficPermissions) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedTrafficPermissions. Required by controller-gen. -func (in *ComputedTrafficPermissions) DeepCopy() *ComputedTrafficPermissions { - if in == nil { - return nil - } - out := new(ComputedTrafficPermissions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedTrafficPermissions. Required by controller-gen. -func (in *ComputedTrafficPermissions) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbauth/v2beta1/computed_traffic_permissions_json.gen.go b/proto-public/pbauth/v2beta1/computed_traffic_permissions_json.gen.go deleted file mode 100644 index cc81cf5ce2b2..000000000000 --- a/proto-public/pbauth/v2beta1/computed_traffic_permissions_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package authv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ComputedTrafficPermissions -func (this *ComputedTrafficPermissions) MarshalJSON() ([]byte, error) { - str, err := ComputedTrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedTrafficPermissions -func (this *ComputedTrafficPermissions) UnmarshalJSON(b []byte) error { - return ComputedTrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -var ( - ComputedTrafficPermissionsMarshaler = &protojson.MarshalOptions{} - ComputedTrafficPermissionsUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbauth/v2beta1/resource_types.gen.go b/proto-public/pbauth/v2beta1/resource_types.gen.go deleted file mode 100644 index 850dcaa9d661..000000000000 --- a/proto-public/pbauth/v2beta1/resource_types.gen.go +++ /dev/null @@ -1,50 +0,0 @@ -// Code generated by protoc-gen-resource-types. DO NOT EDIT. - -package authv2beta1 - -import ( - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - GroupName = "auth" - Version = "v2beta1" - - ComputedTrafficPermissionsKind = "ComputedTrafficPermissions" - NamespaceTrafficPermissionsKind = "NamespaceTrafficPermissions" - PartitionTrafficPermissionsKind = "PartitionTrafficPermissions" - TrafficPermissionsKind = "TrafficPermissions" - WorkloadIdentityKind = "WorkloadIdentity" -) - -var ( - ComputedTrafficPermissionsType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: ComputedTrafficPermissionsKind, - } - - NamespaceTrafficPermissionsType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: NamespaceTrafficPermissionsKind, - } - - PartitionTrafficPermissionsType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: PartitionTrafficPermissionsKind, - } - - TrafficPermissionsType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: TrafficPermissionsKind, - } - - WorkloadIdentityType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: WorkloadIdentityKind, - } -) diff --git a/proto-public/pbauth/v2beta1/traffic_permissions.pb.binary.go b/proto-public/pbauth/v2beta1/traffic_permissions.pb.binary.go deleted file mode 100644 index c1af15492ae7..000000000000 --- a/proto-public/pbauth/v2beta1/traffic_permissions.pb.binary.go +++ /dev/null @@ -1,108 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbauth/v2beta1/traffic_permissions.proto - -package authv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TrafficPermissions) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TrafficPermissions) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *NamespaceTrafficPermissions) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *NamespaceTrafficPermissions) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *PartitionTrafficPermissions) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *PartitionTrafficPermissions) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Destination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Destination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Permission) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Permission) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Source) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Source) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ExcludeSource) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ExcludeSource) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ExcludePermissionRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ExcludePermissionRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationRuleHeader) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationRuleHeader) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbauth/v2beta1/traffic_permissions.pb.go b/proto-public/pbauth/v2beta1/traffic_permissions.pb.go deleted file mode 100644 index 4226925386ac..000000000000 --- a/proto-public/pbauth/v2beta1/traffic_permissions.pb.go +++ /dev/null @@ -1,1182 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbauth/v2beta1/traffic_permissions.proto - -package authv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=ACTION_ALLOW;ACTION_DENY;ACTION_UNKNOWN -// +kubebuilder:validation:Type=string -type Action int32 - -const ( - Action_ACTION_UNSPECIFIED Action = 0 - Action_ACTION_DENY Action = 1 - Action_ACTION_ALLOW Action = 2 -) - -// Enum value maps for Action. -var ( - Action_name = map[int32]string{ - 0: "ACTION_UNSPECIFIED", - 1: "ACTION_DENY", - 2: "ACTION_ALLOW", - } - Action_value = map[string]int32{ - "ACTION_UNSPECIFIED": 0, - "ACTION_DENY": 1, - "ACTION_ALLOW": 2, - } -) - -func (x Action) Enum() *Action { - p := new(Action) - *p = x - return p -} - -func (x Action) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Action) Descriptor() protoreflect.EnumDescriptor { - return file_pbauth_v2beta1_traffic_permissions_proto_enumTypes[0].Descriptor() -} - -func (Action) Type() protoreflect.EnumType { - return &file_pbauth_v2beta1_traffic_permissions_proto_enumTypes[0] -} - -func (x Action) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Action.Descriptor instead. -func (Action) EnumDescriptor() ([]byte, []int) { - return file_pbauth_v2beta1_traffic_permissions_proto_rawDescGZIP(), []int{0} -} - -type TrafficPermissions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Destination is a configuration of the destination proxies - // where these traffic permissions should apply. - Destination *Destination `protobuf:"bytes,1,opt,name=destination,proto3" json:"destination,omitempty"` - // Action can be either allow or deny for the entire object. It will default to allow. - // - // If action is allow, we will allow the connection if one of the rules in Rules matches, in other words, we will deny - // all requests except for the ones that match Rules. If Consul is in default allow mode, then allow - // actions have no effect without a deny permission as everything is allowed by default. - // - // If action is deny, we will deny the connection if one of the rules in Rules match, in other words, - // we will allow all requests except for the ones that match Rules. If Consul is default deny mode, - // then deny permissions have no effect without an allow permission as everything is denied by default. - // - // Action unspecified is reserved for compatibility with the addition of future actions. - Action Action `protobuf:"varint,2,opt,name=action,proto3,enum=hashicorp.consul.auth.v2beta1.Action" json:"action,omitempty"` - // Permissions is a list of permissions to match on. They are applied using OR semantics. - Permissions []*Permission `protobuf:"bytes,3,rep,name=permissions,proto3" json:"permissions,omitempty"` -} - -func (x *TrafficPermissions) Reset() { - *x = TrafficPermissions{} - if protoimpl.UnsafeEnabled { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TrafficPermissions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TrafficPermissions) ProtoMessage() {} - -func (x *TrafficPermissions) ProtoReflect() protoreflect.Message { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TrafficPermissions.ProtoReflect.Descriptor instead. -func (*TrafficPermissions) Descriptor() ([]byte, []int) { - return file_pbauth_v2beta1_traffic_permissions_proto_rawDescGZIP(), []int{0} -} - -func (x *TrafficPermissions) GetDestination() *Destination { - if x != nil { - return x.Destination - } - return nil -} - -func (x *TrafficPermissions) GetAction() Action { - if x != nil { - return x.Action - } - return Action_ACTION_UNSPECIFIED -} - -func (x *TrafficPermissions) GetPermissions() []*Permission { - if x != nil { - return x.Permissions - } - return nil -} - -type NamespaceTrafficPermissions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Action Action `protobuf:"varint,1,opt,name=action,proto3,enum=hashicorp.consul.auth.v2beta1.Action" json:"action,omitempty"` - Permissions []*Permission `protobuf:"bytes,2,rep,name=permissions,proto3" json:"permissions,omitempty"` -} - -func (x *NamespaceTrafficPermissions) Reset() { - *x = NamespaceTrafficPermissions{} - if protoimpl.UnsafeEnabled { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NamespaceTrafficPermissions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NamespaceTrafficPermissions) ProtoMessage() {} - -func (x *NamespaceTrafficPermissions) ProtoReflect() protoreflect.Message { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NamespaceTrafficPermissions.ProtoReflect.Descriptor instead. -func (*NamespaceTrafficPermissions) Descriptor() ([]byte, []int) { - return file_pbauth_v2beta1_traffic_permissions_proto_rawDescGZIP(), []int{1} -} - -func (x *NamespaceTrafficPermissions) GetAction() Action { - if x != nil { - return x.Action - } - return Action_ACTION_UNSPECIFIED -} - -func (x *NamespaceTrafficPermissions) GetPermissions() []*Permission { - if x != nil { - return x.Permissions - } - return nil -} - -type PartitionTrafficPermissions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Action Action `protobuf:"varint,1,opt,name=action,proto3,enum=hashicorp.consul.auth.v2beta1.Action" json:"action,omitempty"` - Permissions []*Permission `protobuf:"bytes,2,rep,name=permissions,proto3" json:"permissions,omitempty"` -} - -func (x *PartitionTrafficPermissions) Reset() { - *x = PartitionTrafficPermissions{} - if protoimpl.UnsafeEnabled { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PartitionTrafficPermissions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PartitionTrafficPermissions) ProtoMessage() {} - -func (x *PartitionTrafficPermissions) ProtoReflect() protoreflect.Message { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PartitionTrafficPermissions.ProtoReflect.Descriptor instead. -func (*PartitionTrafficPermissions) Descriptor() ([]byte, []int) { - return file_pbauth_v2beta1_traffic_permissions_proto_rawDescGZIP(), []int{2} -} - -func (x *PartitionTrafficPermissions) GetAction() Action { - if x != nil { - return x.Action - } - return Action_ACTION_UNSPECIFIED -} - -func (x *PartitionTrafficPermissions) GetPermissions() []*Permission { - if x != nil { - return x.Permissions - } - return nil -} - -// Destination contains the name or name-prefix of the WorkloadIdentity. -// The WorkloadIdentity resource must be in the same tenancy as the TrafficPermissions resource. -type Destination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - IdentityName string `protobuf:"bytes,1,opt,name=identity_name,json=identityName,proto3" json:"identity_name,omitempty"` -} - -func (x *Destination) Reset() { - *x = Destination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Destination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Destination) ProtoMessage() {} - -func (x *Destination) ProtoReflect() protoreflect.Message { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Destination.ProtoReflect.Descriptor instead. -func (*Destination) Descriptor() ([]byte, []int) { - return file_pbauth_v2beta1_traffic_permissions_proto_rawDescGZIP(), []int{3} -} - -func (x *Destination) GetIdentityName() string { - if x != nil { - return x.IdentityName - } - return "" -} - -// Permissions is a list of permissions to match on. -type Permission struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Sources is a list of sources in this traffic permission. - Sources []*Source `protobuf:"bytes,1,rep,name=sources,proto3" json:"sources,omitempty"` - // DestinationRules is a list of rules to apply for matching sources in this Permission. - // These rules are specific to the request or connection that is going to the destination(s) - // selected by the TrafficPermissions resource. - DestinationRules []*DestinationRule `protobuf:"bytes,2,rep,name=destination_rules,json=destinationRules,proto3" json:"destination_rules,omitempty"` -} - -func (x *Permission) Reset() { - *x = Permission{} - if protoimpl.UnsafeEnabled { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Permission) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Permission) ProtoMessage() {} - -func (x *Permission) ProtoReflect() protoreflect.Message { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Permission.ProtoReflect.Descriptor instead. -func (*Permission) Descriptor() ([]byte, []int) { - return file_pbauth_v2beta1_traffic_permissions_proto_rawDescGZIP(), []int{4} -} - -func (x *Permission) GetSources() []*Source { - if x != nil { - return x.Sources - } - return nil -} - -func (x *Permission) GetDestinationRules() []*DestinationRule { - if x != nil { - return x.DestinationRules - } - return nil -} - -// Source represents the source identity. -// To specify any of the wildcard sources, the specific fields need to be omitted. -// For example, for a wildcard namespace, identity_name should be omitted. -type Source struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - IdentityName string `protobuf:"bytes,1,opt,name=identity_name,json=identityName,proto3" json:"identity_name,omitempty"` - Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` - Partition string `protobuf:"bytes,3,opt,name=partition,proto3" json:"partition,omitempty"` - Peer string `protobuf:"bytes,4,opt,name=peer,proto3" json:"peer,omitempty"` - SamenessGroup string `protobuf:"bytes,5,opt,name=sameness_group,json=samenessGroup,proto3" json:"sameness_group,omitempty"` - // Exclude is a list of sources to exclude from this source. - Exclude []*ExcludeSource `protobuf:"bytes,6,rep,name=exclude,proto3" json:"exclude,omitempty"` -} - -func (x *Source) Reset() { - *x = Source{} - if protoimpl.UnsafeEnabled { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Source) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Source) ProtoMessage() {} - -func (x *Source) ProtoReflect() protoreflect.Message { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Source.ProtoReflect.Descriptor instead. -func (*Source) Descriptor() ([]byte, []int) { - return file_pbauth_v2beta1_traffic_permissions_proto_rawDescGZIP(), []int{5} -} - -func (x *Source) GetIdentityName() string { - if x != nil { - return x.IdentityName - } - return "" -} - -func (x *Source) GetNamespace() string { - if x != nil { - return x.Namespace - } - return "" -} - -func (x *Source) GetPartition() string { - if x != nil { - return x.Partition - } - return "" -} - -func (x *Source) GetPeer() string { - if x != nil { - return x.Peer - } - return "" -} - -func (x *Source) GetSamenessGroup() string { - if x != nil { - return x.SamenessGroup - } - return "" -} - -func (x *Source) GetExclude() []*ExcludeSource { - if x != nil { - return x.Exclude - } - return nil -} - -// ExcludeSource is almost the same as source but it prevents the addition of -// matching sources. -type ExcludeSource struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - IdentityName string `protobuf:"bytes,1,opt,name=identity_name,json=identityName,proto3" json:"identity_name,omitempty"` - Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` - Partition string `protobuf:"bytes,3,opt,name=partition,proto3" json:"partition,omitempty"` - Peer string `protobuf:"bytes,4,opt,name=peer,proto3" json:"peer,omitempty"` - SamenessGroup string `protobuf:"bytes,5,opt,name=sameness_group,json=samenessGroup,proto3" json:"sameness_group,omitempty"` -} - -func (x *ExcludeSource) Reset() { - *x = ExcludeSource{} - if protoimpl.UnsafeEnabled { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExcludeSource) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExcludeSource) ProtoMessage() {} - -func (x *ExcludeSource) ProtoReflect() protoreflect.Message { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExcludeSource.ProtoReflect.Descriptor instead. -func (*ExcludeSource) Descriptor() ([]byte, []int) { - return file_pbauth_v2beta1_traffic_permissions_proto_rawDescGZIP(), []int{6} -} - -func (x *ExcludeSource) GetIdentityName() string { - if x != nil { - return x.IdentityName - } - return "" -} - -func (x *ExcludeSource) GetNamespace() string { - if x != nil { - return x.Namespace - } - return "" -} - -func (x *ExcludeSource) GetPartition() string { - if x != nil { - return x.Partition - } - return "" -} - -func (x *ExcludeSource) GetPeer() string { - if x != nil { - return x.Peer - } - return "" -} - -func (x *ExcludeSource) GetSamenessGroup() string { - if x != nil { - return x.SamenessGroup - } - return "" -} - -// DestinationRule contains rules rules to apply to the incoming connection. -type DestinationRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PathExact string `protobuf:"bytes,1,opt,name=path_exact,json=pathExact,proto3" json:"path_exact,omitempty"` - PathPrefix string `protobuf:"bytes,2,opt,name=path_prefix,json=pathPrefix,proto3" json:"path_prefix,omitempty"` - PathRegex string `protobuf:"bytes,3,opt,name=path_regex,json=pathRegex,proto3" json:"path_regex,omitempty"` - // Methods is the list of HTTP methods. If no methods are specified, - // this rule will apply to all methods. - Methods []string `protobuf:"bytes,4,rep,name=methods,proto3" json:"methods,omitempty"` - Header *DestinationRuleHeader `protobuf:"bytes,5,opt,name=header,proto3" json:"header,omitempty"` - PortNames []string `protobuf:"bytes,6,rep,name=port_names,json=portNames,proto3" json:"port_names,omitempty"` - // Exclude contains a list of rules to exclude when evaluating rules for the incoming connection. - Exclude []*ExcludePermissionRule `protobuf:"bytes,7,rep,name=exclude,proto3" json:"exclude,omitempty"` -} - -func (x *DestinationRule) Reset() { - *x = DestinationRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationRule) ProtoMessage() {} - -func (x *DestinationRule) ProtoReflect() protoreflect.Message { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DestinationRule.ProtoReflect.Descriptor instead. -func (*DestinationRule) Descriptor() ([]byte, []int) { - return file_pbauth_v2beta1_traffic_permissions_proto_rawDescGZIP(), []int{7} -} - -func (x *DestinationRule) GetPathExact() string { - if x != nil { - return x.PathExact - } - return "" -} - -func (x *DestinationRule) GetPathPrefix() string { - if x != nil { - return x.PathPrefix - } - return "" -} - -func (x *DestinationRule) GetPathRegex() string { - if x != nil { - return x.PathRegex - } - return "" -} - -func (x *DestinationRule) GetMethods() []string { - if x != nil { - return x.Methods - } - return nil -} - -func (x *DestinationRule) GetHeader() *DestinationRuleHeader { - if x != nil { - return x.Header - } - return nil -} - -func (x *DestinationRule) GetPortNames() []string { - if x != nil { - return x.PortNames - } - return nil -} - -func (x *DestinationRule) GetExclude() []*ExcludePermissionRule { - if x != nil { - return x.Exclude - } - return nil -} - -type ExcludePermissionRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PathExact string `protobuf:"bytes,1,opt,name=path_exact,json=pathExact,proto3" json:"path_exact,omitempty"` - PathPrefix string `protobuf:"bytes,2,opt,name=path_prefix,json=pathPrefix,proto3" json:"path_prefix,omitempty"` - PathRegex string `protobuf:"bytes,3,opt,name=path_regex,json=pathRegex,proto3" json:"path_regex,omitempty"` - // Methods is the list of HTTP methods. - Methods []string `protobuf:"bytes,4,rep,name=methods,proto3" json:"methods,omitempty"` - Header *DestinationRuleHeader `protobuf:"bytes,5,opt,name=header,proto3" json:"header,omitempty"` - // PortNames is a list of workload ports to apply this rule to. The ports specified here - // must be the ports used in the connection. - PortNames []string `protobuf:"bytes,6,rep,name=port_names,json=portNames,proto3" json:"port_names,omitempty"` -} - -func (x *ExcludePermissionRule) Reset() { - *x = ExcludePermissionRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExcludePermissionRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExcludePermissionRule) ProtoMessage() {} - -func (x *ExcludePermissionRule) ProtoReflect() protoreflect.Message { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExcludePermissionRule.ProtoReflect.Descriptor instead. -func (*ExcludePermissionRule) Descriptor() ([]byte, []int) { - return file_pbauth_v2beta1_traffic_permissions_proto_rawDescGZIP(), []int{8} -} - -func (x *ExcludePermissionRule) GetPathExact() string { - if x != nil { - return x.PathExact - } - return "" -} - -func (x *ExcludePermissionRule) GetPathPrefix() string { - if x != nil { - return x.PathPrefix - } - return "" -} - -func (x *ExcludePermissionRule) GetPathRegex() string { - if x != nil { - return x.PathRegex - } - return "" -} - -func (x *ExcludePermissionRule) GetMethods() []string { - if x != nil { - return x.Methods - } - return nil -} - -func (x *ExcludePermissionRule) GetHeader() *DestinationRuleHeader { - if x != nil { - return x.Header - } - return nil -} - -func (x *ExcludePermissionRule) GetPortNames() []string { - if x != nil { - return x.PortNames - } - return nil -} - -type DestinationRuleHeader struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Present bool `protobuf:"varint,2,opt,name=present,proto3" json:"present,omitempty"` - Exact string `protobuf:"bytes,3,opt,name=exact,proto3" json:"exact,omitempty"` - Prefix string `protobuf:"bytes,4,opt,name=prefix,proto3" json:"prefix,omitempty"` - Suffix string `protobuf:"bytes,5,opt,name=suffix,proto3" json:"suffix,omitempty"` - Regex string `protobuf:"bytes,6,opt,name=regex,proto3" json:"regex,omitempty"` - Invert bool `protobuf:"varint,7,opt,name=invert,proto3" json:"invert,omitempty"` -} - -func (x *DestinationRuleHeader) Reset() { - *x = DestinationRuleHeader{} - if protoimpl.UnsafeEnabled { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationRuleHeader) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationRuleHeader) ProtoMessage() {} - -func (x *DestinationRuleHeader) ProtoReflect() protoreflect.Message { - mi := &file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DestinationRuleHeader.ProtoReflect.Descriptor instead. -func (*DestinationRuleHeader) Descriptor() ([]byte, []int) { - return file_pbauth_v2beta1_traffic_permissions_proto_rawDescGZIP(), []int{9} -} - -func (x *DestinationRuleHeader) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *DestinationRuleHeader) GetPresent() bool { - if x != nil { - return x.Present - } - return false -} - -func (x *DestinationRuleHeader) GetExact() string { - if x != nil { - return x.Exact - } - return "" -} - -func (x *DestinationRuleHeader) GetPrefix() string { - if x != nil { - return x.Prefix - } - return "" -} - -func (x *DestinationRuleHeader) GetSuffix() string { - if x != nil { - return x.Suffix - } - return "" -} - -func (x *DestinationRuleHeader) GetRegex() string { - if x != nil { - return x.Regex - } - return "" -} - -func (x *DestinationRuleHeader) GetInvert() bool { - if x != nil { - return x.Invert - } - return false -} - -var File_pbauth_v2beta1_traffic_permissions_proto protoreflect.FileDescriptor - -var file_pbauth_v2beta1_traffic_permissions_proto_rawDesc = []byte{ - 0x0a, 0x28, 0x70, 0x62, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf6, 0x01, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x66, - 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4c, - 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x06, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4b, 0x0a, 0x0b, 0x70, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x70, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, - 0x22, 0xb1, 0x01, 0x0a, 0x1b, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, - 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x3d, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x25, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x4b, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x06, 0xa2, 0x93, - 0x04, 0x02, 0x08, 0x03, 0x22, 0xb1, 0x01, 0x0a, 0x1b, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3d, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x4b, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x02, 0x22, 0x32, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xaa, 0x01, 0x0a, - 0x0a, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x07, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x5b, 0x0a, 0x11, - 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x75, 0x6c, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, 0xec, 0x01, 0x0a, 0x06, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x61, 0x6d, - 0x65, 0x6e, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x12, 0x46, 0x0a, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, - 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x22, 0xab, 0x01, 0x0a, 0x0d, 0x45, 0x78, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, - 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x65, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x12, - 0x25, 0x0a, 0x0e, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, - 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0xc7, 0x02, 0x0a, 0x0f, 0x44, 0x65, 0x73, 0x74, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, - 0x74, 0x68, 0x5f, 0x65, 0x78, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x70, 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x74, - 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x70, 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, - 0x74, 0x68, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x70, 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x73, 0x12, 0x4c, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x75, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x12, 0x4e, 0x0a, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x07, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x22, 0xfd, 0x01, 0x0a, 0x15, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x65, 0x72, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, - 0x74, 0x68, 0x5f, 0x65, 0x78, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x70, 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x74, - 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x70, 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, - 0x74, 0x68, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x70, 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x73, 0x12, 0x4c, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x75, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x22, 0xb9, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x75, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x78, 0x61, 0x63, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x78, 0x61, 0x63, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x12, 0x14, - 0x0a, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, - 0x65, 0x67, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x2a, 0x43, 0x0a, 0x06, - 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, - 0x0a, 0x0b, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4e, 0x59, 0x10, 0x01, 0x12, - 0x10, 0x0a, 0x0c, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x10, - 0x02, 0x42, 0x98, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x17, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x61, - 0x75, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x61, 0x75, 0x74, 0x68, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x41, 0xaa, 0x02, 0x1d, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x41, 0x75, 0x74, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x41, - 0x75, 0x74, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbauth_v2beta1_traffic_permissions_proto_rawDescOnce sync.Once - file_pbauth_v2beta1_traffic_permissions_proto_rawDescData = file_pbauth_v2beta1_traffic_permissions_proto_rawDesc -) - -func file_pbauth_v2beta1_traffic_permissions_proto_rawDescGZIP() []byte { - file_pbauth_v2beta1_traffic_permissions_proto_rawDescOnce.Do(func() { - file_pbauth_v2beta1_traffic_permissions_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbauth_v2beta1_traffic_permissions_proto_rawDescData) - }) - return file_pbauth_v2beta1_traffic_permissions_proto_rawDescData -} - -var file_pbauth_v2beta1_traffic_permissions_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbauth_v2beta1_traffic_permissions_proto_msgTypes = make([]protoimpl.MessageInfo, 10) -var file_pbauth_v2beta1_traffic_permissions_proto_goTypes = []interface{}{ - (Action)(0), // 0: hashicorp.consul.auth.v2beta1.Action - (*TrafficPermissions)(nil), // 1: hashicorp.consul.auth.v2beta1.TrafficPermissions - (*NamespaceTrafficPermissions)(nil), // 2: hashicorp.consul.auth.v2beta1.NamespaceTrafficPermissions - (*PartitionTrafficPermissions)(nil), // 3: hashicorp.consul.auth.v2beta1.PartitionTrafficPermissions - (*Destination)(nil), // 4: hashicorp.consul.auth.v2beta1.Destination - (*Permission)(nil), // 5: hashicorp.consul.auth.v2beta1.Permission - (*Source)(nil), // 6: hashicorp.consul.auth.v2beta1.Source - (*ExcludeSource)(nil), // 7: hashicorp.consul.auth.v2beta1.ExcludeSource - (*DestinationRule)(nil), // 8: hashicorp.consul.auth.v2beta1.DestinationRule - (*ExcludePermissionRule)(nil), // 9: hashicorp.consul.auth.v2beta1.ExcludePermissionRule - (*DestinationRuleHeader)(nil), // 10: hashicorp.consul.auth.v2beta1.DestinationRuleHeader -} -var file_pbauth_v2beta1_traffic_permissions_proto_depIdxs = []int32{ - 4, // 0: hashicorp.consul.auth.v2beta1.TrafficPermissions.destination:type_name -> hashicorp.consul.auth.v2beta1.Destination - 0, // 1: hashicorp.consul.auth.v2beta1.TrafficPermissions.action:type_name -> hashicorp.consul.auth.v2beta1.Action - 5, // 2: hashicorp.consul.auth.v2beta1.TrafficPermissions.permissions:type_name -> hashicorp.consul.auth.v2beta1.Permission - 0, // 3: hashicorp.consul.auth.v2beta1.NamespaceTrafficPermissions.action:type_name -> hashicorp.consul.auth.v2beta1.Action - 5, // 4: hashicorp.consul.auth.v2beta1.NamespaceTrafficPermissions.permissions:type_name -> hashicorp.consul.auth.v2beta1.Permission - 0, // 5: hashicorp.consul.auth.v2beta1.PartitionTrafficPermissions.action:type_name -> hashicorp.consul.auth.v2beta1.Action - 5, // 6: hashicorp.consul.auth.v2beta1.PartitionTrafficPermissions.permissions:type_name -> hashicorp.consul.auth.v2beta1.Permission - 6, // 7: hashicorp.consul.auth.v2beta1.Permission.sources:type_name -> hashicorp.consul.auth.v2beta1.Source - 8, // 8: hashicorp.consul.auth.v2beta1.Permission.destination_rules:type_name -> hashicorp.consul.auth.v2beta1.DestinationRule - 7, // 9: hashicorp.consul.auth.v2beta1.Source.exclude:type_name -> hashicorp.consul.auth.v2beta1.ExcludeSource - 10, // 10: hashicorp.consul.auth.v2beta1.DestinationRule.header:type_name -> hashicorp.consul.auth.v2beta1.DestinationRuleHeader - 9, // 11: hashicorp.consul.auth.v2beta1.DestinationRule.exclude:type_name -> hashicorp.consul.auth.v2beta1.ExcludePermissionRule - 10, // 12: hashicorp.consul.auth.v2beta1.ExcludePermissionRule.header:type_name -> hashicorp.consul.auth.v2beta1.DestinationRuleHeader - 13, // [13:13] is the sub-list for method output_type - 13, // [13:13] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name -} - -func init() { file_pbauth_v2beta1_traffic_permissions_proto_init() } -func file_pbauth_v2beta1_traffic_permissions_proto_init() { - if File_pbauth_v2beta1_traffic_permissions_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TrafficPermissions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NamespaceTrafficPermissions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PartitionTrafficPermissions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Destination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Permission); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Source); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExcludeSource); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExcludePermissionRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbauth_v2beta1_traffic_permissions_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationRuleHeader); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbauth_v2beta1_traffic_permissions_proto_rawDesc, - NumEnums: 1, - NumMessages: 10, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbauth_v2beta1_traffic_permissions_proto_goTypes, - DependencyIndexes: file_pbauth_v2beta1_traffic_permissions_proto_depIdxs, - EnumInfos: file_pbauth_v2beta1_traffic_permissions_proto_enumTypes, - MessageInfos: file_pbauth_v2beta1_traffic_permissions_proto_msgTypes, - }.Build() - File_pbauth_v2beta1_traffic_permissions_proto = out.File - file_pbauth_v2beta1_traffic_permissions_proto_rawDesc = nil - file_pbauth_v2beta1_traffic_permissions_proto_goTypes = nil - file_pbauth_v2beta1_traffic_permissions_proto_depIdxs = nil -} diff --git a/proto-public/pbauth/v2beta1/traffic_permissions.proto b/proto-public/pbauth/v2beta1/traffic_permissions.proto deleted file mode 100644 index c36da643f4d1..000000000000 --- a/proto-public/pbauth/v2beta1/traffic_permissions.proto +++ /dev/null @@ -1,129 +0,0 @@ -syntax = "proto3"; - -package hashicorp.consul.auth.v2beta1; - -import "pbresource/annotations.proto"; - -message TrafficPermissions { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // Destination is a configuration of the destination proxies - // where these traffic permissions should apply. - Destination destination = 1; - - // Action can be either allow or deny for the entire object. It will default to allow. - // - // If action is allow, we will allow the connection if one of the rules in Rules matches, in other words, we will deny - // all requests except for the ones that match Rules. If Consul is in default allow mode, then allow - // actions have no effect without a deny permission as everything is allowed by default. - // - // If action is deny, we will deny the connection if one of the rules in Rules match, in other words, - // we will allow all requests except for the ones that match Rules. If Consul is default deny mode, - // then deny permissions have no effect without an allow permission as everything is denied by default. - // - // Action unspecified is reserved for compatibility with the addition of future actions. - Action action = 2; - - // Permissions is a list of permissions to match on. They are applied using OR semantics. - repeated Permission permissions = 3; -} - -message NamespaceTrafficPermissions { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - Action action = 1; - repeated Permission permissions = 2; -} - -message PartitionTrafficPermissions { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_PARTITION}; - - Action action = 1; - repeated Permission permissions = 2; -} - -// Destination contains the name or name-prefix of the WorkloadIdentity. -// The WorkloadIdentity resource must be in the same tenancy as the TrafficPermissions resource. -message Destination { - string identity_name = 1; -} - -// +kubebuilder:validation:Enum=ACTION_ALLOW;ACTION_DENY;ACTION_UNKNOWN -// +kubebuilder:validation:Type=string -enum Action { - ACTION_UNSPECIFIED = 0; - ACTION_DENY = 1; - ACTION_ALLOW = 2; -} - -// Permissions is a list of permissions to match on. -message Permission { - // Sources is a list of sources in this traffic permission. - repeated Source sources = 1; - // DestinationRules is a list of rules to apply for matching sources in this Permission. - // These rules are specific to the request or connection that is going to the destination(s) - // selected by the TrafficPermissions resource. - repeated DestinationRule destination_rules = 2; -} - -// Source represents the source identity. -// To specify any of the wildcard sources, the specific fields need to be omitted. -// For example, for a wildcard namespace, identity_name should be omitted. -message Source { - string identity_name = 1; - string namespace = 2; - string partition = 3; - string peer = 4; - string sameness_group = 5; - - // Exclude is a list of sources to exclude from this source. - repeated ExcludeSource exclude = 6; -} - -// ExcludeSource is almost the same as source but it prevents the addition of -// matching sources. -message ExcludeSource { - string identity_name = 1; - string namespace = 2; - string partition = 3; - string peer = 4; - string sameness_group = 5; -} - -// DestinationRule contains rules rules to apply to the incoming connection. -message DestinationRule { - string path_exact = 1; - string path_prefix = 2; - string path_regex = 3; - // Methods is the list of HTTP methods. If no methods are specified, - // this rule will apply to all methods. - repeated string methods = 4; - DestinationRuleHeader header = 5; - repeated string port_names = 6; - // Exclude contains a list of rules to exclude when evaluating rules for the incoming connection. - repeated ExcludePermissionRule exclude = 7; -} - -message ExcludePermissionRule { - string path_exact = 1; - string path_prefix = 2; - string path_regex = 3; - // Methods is the list of HTTP methods. - repeated string methods = 4; - - DestinationRuleHeader header = 5; - - // PortNames is a list of workload ports to apply this rule to. The ports specified here - // must be the ports used in the connection. - repeated string port_names = 6; -} - -message DestinationRuleHeader { - string name = 1; - bool present = 2; - string exact = 3; - string prefix = 4; - string suffix = 5; - string regex = 6; - bool invert = 7; -} diff --git a/proto-public/pbauth/v2beta1/traffic_permissions_addon.go b/proto-public/pbauth/v2beta1/traffic_permissions_addon.go deleted file mode 100644 index 9f778504f757..000000000000 --- a/proto-public/pbauth/v2beta1/traffic_permissions_addon.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package authv2beta1 - -import "github.com/hashicorp/consul/proto-public/pbresource" - -type SourceToSpiffe interface { - GetIdentityName() string - GetPartition() string - GetNamespace() string - GetPeer() string - GetSamenessGroup() string -} - -var _ SourceToSpiffe = (*Source)(nil) -var _ SourceToSpiffe = (*ExcludeSource)(nil) - -func SourceToTenancy(s SourceToSpiffe) *pbresource.Tenancy { - return &pbresource.Tenancy{ - Partition: s.GetPartition(), - Namespace: s.GetNamespace(), - PeerName: s.GetPeer(), - } -} diff --git a/proto-public/pbauth/v2beta1/traffic_permissions_deepcopy.gen.go b/proto-public/pbauth/v2beta1/traffic_permissions_deepcopy.gen.go deleted file mode 100644 index b954d00b407f..000000000000 --- a/proto-public/pbauth/v2beta1/traffic_permissions_deepcopy.gen.go +++ /dev/null @@ -1,216 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package authv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using TrafficPermissions within kubernetes types, where deepcopy-gen is used. -func (in *TrafficPermissions) DeepCopyInto(out *TrafficPermissions) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficPermissions. Required by controller-gen. -func (in *TrafficPermissions) DeepCopy() *TrafficPermissions { - if in == nil { - return nil - } - out := new(TrafficPermissions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TrafficPermissions. Required by controller-gen. -func (in *TrafficPermissions) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using NamespaceTrafficPermissions within kubernetes types, where deepcopy-gen is used. -func (in *NamespaceTrafficPermissions) DeepCopyInto(out *NamespaceTrafficPermissions) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceTrafficPermissions. Required by controller-gen. -func (in *NamespaceTrafficPermissions) DeepCopy() *NamespaceTrafficPermissions { - if in == nil { - return nil - } - out := new(NamespaceTrafficPermissions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceTrafficPermissions. Required by controller-gen. -func (in *NamespaceTrafficPermissions) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using PartitionTrafficPermissions within kubernetes types, where deepcopy-gen is used. -func (in *PartitionTrafficPermissions) DeepCopyInto(out *PartitionTrafficPermissions) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PartitionTrafficPermissions. Required by controller-gen. -func (in *PartitionTrafficPermissions) DeepCopy() *PartitionTrafficPermissions { - if in == nil { - return nil - } - out := new(PartitionTrafficPermissions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new PartitionTrafficPermissions. Required by controller-gen. -func (in *PartitionTrafficPermissions) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Destination within kubernetes types, where deepcopy-gen is used. -func (in *Destination) DeepCopyInto(out *Destination) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Destination. Required by controller-gen. -func (in *Destination) DeepCopy() *Destination { - if in == nil { - return nil - } - out := new(Destination) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Destination. Required by controller-gen. -func (in *Destination) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Permission within kubernetes types, where deepcopy-gen is used. -func (in *Permission) DeepCopyInto(out *Permission) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Permission. Required by controller-gen. -func (in *Permission) DeepCopy() *Permission { - if in == nil { - return nil - } - out := new(Permission) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Permission. Required by controller-gen. -func (in *Permission) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Source within kubernetes types, where deepcopy-gen is used. -func (in *Source) DeepCopyInto(out *Source) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Source. Required by controller-gen. -func (in *Source) DeepCopy() *Source { - if in == nil { - return nil - } - out := new(Source) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Source. Required by controller-gen. -func (in *Source) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ExcludeSource within kubernetes types, where deepcopy-gen is used. -func (in *ExcludeSource) DeepCopyInto(out *ExcludeSource) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExcludeSource. Required by controller-gen. -func (in *ExcludeSource) DeepCopy() *ExcludeSource { - if in == nil { - return nil - } - out := new(ExcludeSource) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ExcludeSource. Required by controller-gen. -func (in *ExcludeSource) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DestinationRule within kubernetes types, where deepcopy-gen is used. -func (in *DestinationRule) DeepCopyInto(out *DestinationRule) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationRule. Required by controller-gen. -func (in *DestinationRule) DeepCopy() *DestinationRule { - if in == nil { - return nil - } - out := new(DestinationRule) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DestinationRule. Required by controller-gen. -func (in *DestinationRule) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ExcludePermissionRule within kubernetes types, where deepcopy-gen is used. -func (in *ExcludePermissionRule) DeepCopyInto(out *ExcludePermissionRule) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExcludePermissionRule. Required by controller-gen. -func (in *ExcludePermissionRule) DeepCopy() *ExcludePermissionRule { - if in == nil { - return nil - } - out := new(ExcludePermissionRule) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ExcludePermissionRule. Required by controller-gen. -func (in *ExcludePermissionRule) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DestinationRuleHeader within kubernetes types, where deepcopy-gen is used. -func (in *DestinationRuleHeader) DeepCopyInto(out *DestinationRuleHeader) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationRuleHeader. Required by controller-gen. -func (in *DestinationRuleHeader) DeepCopy() *DestinationRuleHeader { - if in == nil { - return nil - } - out := new(DestinationRuleHeader) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DestinationRuleHeader. Required by controller-gen. -func (in *DestinationRuleHeader) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbauth/v2beta1/traffic_permissions_json.gen.go b/proto-public/pbauth/v2beta1/traffic_permissions_json.gen.go deleted file mode 100644 index 7f6ddde2904d..000000000000 --- a/proto-public/pbauth/v2beta1/traffic_permissions_json.gen.go +++ /dev/null @@ -1,121 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package authv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for TrafficPermissions -func (this *TrafficPermissions) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TrafficPermissions -func (this *TrafficPermissions) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for NamespaceTrafficPermissions -func (this *NamespaceTrafficPermissions) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for NamespaceTrafficPermissions -func (this *NamespaceTrafficPermissions) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for PartitionTrafficPermissions -func (this *PartitionTrafficPermissions) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for PartitionTrafficPermissions -func (this *PartitionTrafficPermissions) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Destination -func (this *Destination) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Destination -func (this *Destination) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Permission -func (this *Permission) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Permission -func (this *Permission) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Source -func (this *Source) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Source -func (this *Source) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ExcludeSource -func (this *ExcludeSource) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ExcludeSource -func (this *ExcludeSource) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DestinationRule -func (this *DestinationRule) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DestinationRule -func (this *DestinationRule) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ExcludePermissionRule -func (this *ExcludePermissionRule) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ExcludePermissionRule -func (this *ExcludePermissionRule) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DestinationRuleHeader -func (this *DestinationRuleHeader) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DestinationRuleHeader -func (this *DestinationRuleHeader) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -var ( - TrafficPermissionsMarshaler = &protojson.MarshalOptions{} - TrafficPermissionsUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbauth/v2beta1/workload_identity.pb.binary.go b/proto-public/pbauth/v2beta1/workload_identity.pb.binary.go deleted file mode 100644 index 5161f35d9562..000000000000 --- a/proto-public/pbauth/v2beta1/workload_identity.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbauth/v2beta1/workload_identity.proto - -package authv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *WorkloadIdentity) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *WorkloadIdentity) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbauth/v2beta1/workload_identity.pb.go b/proto-public/pbauth/v2beta1/workload_identity.pb.go deleted file mode 100644 index c24f45c776ea..000000000000 --- a/proto-public/pbauth/v2beta1/workload_identity.pb.go +++ /dev/null @@ -1,155 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbauth/v2beta1/workload_identity.proto - -package authv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type WorkloadIdentity struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *WorkloadIdentity) Reset() { - *x = WorkloadIdentity{} - if protoimpl.UnsafeEnabled { - mi := &file_pbauth_v2beta1_workload_identity_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WorkloadIdentity) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WorkloadIdentity) ProtoMessage() {} - -func (x *WorkloadIdentity) ProtoReflect() protoreflect.Message { - mi := &file_pbauth_v2beta1_workload_identity_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WorkloadIdentity.ProtoReflect.Descriptor instead. -func (*WorkloadIdentity) Descriptor() ([]byte, []int) { - return file_pbauth_v2beta1_workload_identity_proto_rawDescGZIP(), []int{0} -} - -var File_pbauth_v2beta1_workload_identity_proto protoreflect.FileDescriptor - -var file_pbauth_v2beta1_workload_identity_proto_rawDesc = []byte{ - 0x0a, 0x26, 0x70, 0x62, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1a, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, - 0x64, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, - 0x03, 0x42, 0x96, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, - 0x64, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x61, 0x75, 0x74, - 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x61, 0x75, 0x74, 0x68, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x41, 0xaa, 0x02, 0x1d, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x41, - 0x75, 0x74, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x41, - 0x75, 0x74, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x41, - 0x75, 0x74, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x41, 0x75, 0x74, - 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_pbauth_v2beta1_workload_identity_proto_rawDescOnce sync.Once - file_pbauth_v2beta1_workload_identity_proto_rawDescData = file_pbauth_v2beta1_workload_identity_proto_rawDesc -) - -func file_pbauth_v2beta1_workload_identity_proto_rawDescGZIP() []byte { - file_pbauth_v2beta1_workload_identity_proto_rawDescOnce.Do(func() { - file_pbauth_v2beta1_workload_identity_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbauth_v2beta1_workload_identity_proto_rawDescData) - }) - return file_pbauth_v2beta1_workload_identity_proto_rawDescData -} - -var file_pbauth_v2beta1_workload_identity_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbauth_v2beta1_workload_identity_proto_goTypes = []interface{}{ - (*WorkloadIdentity)(nil), // 0: hashicorp.consul.auth.v2beta1.WorkloadIdentity -} -var file_pbauth_v2beta1_workload_identity_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbauth_v2beta1_workload_identity_proto_init() } -func file_pbauth_v2beta1_workload_identity_proto_init() { - if File_pbauth_v2beta1_workload_identity_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbauth_v2beta1_workload_identity_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkloadIdentity); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbauth_v2beta1_workload_identity_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbauth_v2beta1_workload_identity_proto_goTypes, - DependencyIndexes: file_pbauth_v2beta1_workload_identity_proto_depIdxs, - MessageInfos: file_pbauth_v2beta1_workload_identity_proto_msgTypes, - }.Build() - File_pbauth_v2beta1_workload_identity_proto = out.File - file_pbauth_v2beta1_workload_identity_proto_rawDesc = nil - file_pbauth_v2beta1_workload_identity_proto_goTypes = nil - file_pbauth_v2beta1_workload_identity_proto_depIdxs = nil -} diff --git a/proto-public/pbauth/v2beta1/workload_identity.proto b/proto-public/pbauth/v2beta1/workload_identity.proto deleted file mode 100644 index 32347810182f..000000000000 --- a/proto-public/pbauth/v2beta1/workload_identity.proto +++ /dev/null @@ -1,9 +0,0 @@ -syntax = "proto3"; - -package hashicorp.consul.auth.v2beta1; - -import "pbresource/annotations.proto"; - -message WorkloadIdentity { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; -} diff --git a/proto-public/pbauth/v2beta1/workload_identity_deepcopy.gen.go b/proto-public/pbauth/v2beta1/workload_identity_deepcopy.gen.go deleted file mode 100644 index 7a25aba74a48..000000000000 --- a/proto-public/pbauth/v2beta1/workload_identity_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package authv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using WorkloadIdentity within kubernetes types, where deepcopy-gen is used. -func (in *WorkloadIdentity) DeepCopyInto(out *WorkloadIdentity) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadIdentity. Required by controller-gen. -func (in *WorkloadIdentity) DeepCopy() *WorkloadIdentity { - if in == nil { - return nil - } - out := new(WorkloadIdentity) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadIdentity. Required by controller-gen. -func (in *WorkloadIdentity) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbauth/v2beta1/workload_identity_json.gen.go b/proto-public/pbauth/v2beta1/workload_identity_json.gen.go deleted file mode 100644 index 8c49cd53e140..000000000000 --- a/proto-public/pbauth/v2beta1/workload_identity_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package authv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for WorkloadIdentity -func (this *WorkloadIdentity) MarshalJSON() ([]byte, error) { - str, err := WorkloadIdentityMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for WorkloadIdentity -func (this *WorkloadIdentity) UnmarshalJSON(b []byte) error { - return WorkloadIdentityUnmarshaler.Unmarshal(b, this) -} - -var ( - WorkloadIdentityMarshaler = &protojson.MarshalOptions{} - WorkloadIdentityUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbcatalog/v2beta1/dns.pb.binary.go b/proto-public/pbcatalog/v2beta1/dns.pb.binary.go deleted file mode 100644 index 41ad32c0ef6d..000000000000 --- a/proto-public/pbcatalog/v2beta1/dns.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbcatalog/v2beta1/dns.proto - -package catalogv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DNSPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DNSPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Weights) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Weights) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbcatalog/v2beta1/dns.pb.go b/proto-public/pbcatalog/v2beta1/dns.pb.go deleted file mode 100644 index 446e788d3e95..000000000000 --- a/proto-public/pbcatalog/v2beta1/dns.pb.go +++ /dev/null @@ -1,262 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbcatalog/v2beta1/dns.proto - -package catalogv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type DNSPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Workloads *WorkloadSelector `protobuf:"bytes,1,opt,name=workloads,proto3" json:"workloads,omitempty"` - Weights *Weights `protobuf:"bytes,2,opt,name=weights,proto3" json:"weights,omitempty"` -} - -func (x *DNSPolicy) Reset() { - *x = DNSPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_dns_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DNSPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DNSPolicy) ProtoMessage() {} - -func (x *DNSPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_dns_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DNSPolicy.ProtoReflect.Descriptor instead. -func (*DNSPolicy) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_dns_proto_rawDescGZIP(), []int{0} -} - -func (x *DNSPolicy) GetWorkloads() *WorkloadSelector { - if x != nil { - return x.Workloads - } - return nil -} - -func (x *DNSPolicy) GetWeights() *Weights { - if x != nil { - return x.Weights - } - return nil -} - -type Weights struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Passing uint32 `protobuf:"varint,1,opt,name=passing,proto3" json:"passing,omitempty"` - Warning uint32 `protobuf:"varint,2,opt,name=warning,proto3" json:"warning,omitempty"` -} - -func (x *Weights) Reset() { - *x = Weights{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_dns_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Weights) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Weights) ProtoMessage() {} - -func (x *Weights) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_dns_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Weights.ProtoReflect.Descriptor instead. -func (*Weights) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_dns_proto_rawDescGZIP(), []int{1} -} - -func (x *Weights) GetPassing() uint32 { - if x != nil { - return x.Passing - } - return 0 -} - -func (x *Weights) GetWarning() uint32 { - if x != nil { - return x.Warning - } - return 0 -} - -var File_pbcatalog_v2beta1_dns_proto protoreflect.FileDescriptor - -var file_pbcatalog_v2beta1_dns_proto_rawDesc = []byte{ - 0x0a, 0x1b, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x64, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, - 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, - 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xaa, 0x01, 0x0a, 0x09, 0x44, 0x4e, 0x53, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x50, 0x0a, - 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, - 0x43, 0x0a, 0x07, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x52, 0x07, 0x77, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0x3d, 0x0a, 0x07, - 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x73, 0x73, 0x69, - 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x70, 0x61, 0x73, 0x73, 0x69, 0x6e, - 0x67, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x42, 0x9e, 0x02, 0x0a, 0x24, - 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x42, 0x08, 0x44, 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, - 0x43, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x43, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbcatalog_v2beta1_dns_proto_rawDescOnce sync.Once - file_pbcatalog_v2beta1_dns_proto_rawDescData = file_pbcatalog_v2beta1_dns_proto_rawDesc -) - -func file_pbcatalog_v2beta1_dns_proto_rawDescGZIP() []byte { - file_pbcatalog_v2beta1_dns_proto_rawDescOnce.Do(func() { - file_pbcatalog_v2beta1_dns_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbcatalog_v2beta1_dns_proto_rawDescData) - }) - return file_pbcatalog_v2beta1_dns_proto_rawDescData -} - -var file_pbcatalog_v2beta1_dns_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbcatalog_v2beta1_dns_proto_goTypes = []interface{}{ - (*DNSPolicy)(nil), // 0: hashicorp.consul.catalog.v2beta1.DNSPolicy - (*Weights)(nil), // 1: hashicorp.consul.catalog.v2beta1.Weights - (*WorkloadSelector)(nil), // 2: hashicorp.consul.catalog.v2beta1.WorkloadSelector -} -var file_pbcatalog_v2beta1_dns_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.catalog.v2beta1.DNSPolicy.workloads:type_name -> hashicorp.consul.catalog.v2beta1.WorkloadSelector - 1, // 1: hashicorp.consul.catalog.v2beta1.DNSPolicy.weights:type_name -> hashicorp.consul.catalog.v2beta1.Weights - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_pbcatalog_v2beta1_dns_proto_init() } -func file_pbcatalog_v2beta1_dns_proto_init() { - if File_pbcatalog_v2beta1_dns_proto != nil { - return - } - file_pbcatalog_v2beta1_selector_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbcatalog_v2beta1_dns_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DNSPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_dns_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Weights); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbcatalog_v2beta1_dns_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbcatalog_v2beta1_dns_proto_goTypes, - DependencyIndexes: file_pbcatalog_v2beta1_dns_proto_depIdxs, - MessageInfos: file_pbcatalog_v2beta1_dns_proto_msgTypes, - }.Build() - File_pbcatalog_v2beta1_dns_proto = out.File - file_pbcatalog_v2beta1_dns_proto_rawDesc = nil - file_pbcatalog_v2beta1_dns_proto_goTypes = nil - file_pbcatalog_v2beta1_dns_proto_depIdxs = nil -} diff --git a/proto-public/pbcatalog/v2beta1/dns.proto b/proto-public/pbcatalog/v2beta1/dns.proto deleted file mode 100644 index b62cc8e10e90..000000000000 --- a/proto-public/pbcatalog/v2beta1/dns.proto +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.catalog.v2beta1; - -import "pbcatalog/v2beta1/selector.proto"; -import "pbresource/annotations.proto"; - -message DNSPolicy { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - WorkloadSelector workloads = 1; - Weights weights = 2; -} - -message Weights { - uint32 passing = 1; - uint32 warning = 2; -} diff --git a/proto-public/pbcatalog/v2beta1/dns_deepcopy.gen.go b/proto-public/pbcatalog/v2beta1/dns_deepcopy.gen.go deleted file mode 100644 index 9a3d883b8cec..000000000000 --- a/proto-public/pbcatalog/v2beta1/dns_deepcopy.gen.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package catalogv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using DNSPolicy within kubernetes types, where deepcopy-gen is used. -func (in *DNSPolicy) DeepCopyInto(out *DNSPolicy) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSPolicy. Required by controller-gen. -func (in *DNSPolicy) DeepCopy() *DNSPolicy { - if in == nil { - return nil - } - out := new(DNSPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DNSPolicy. Required by controller-gen. -func (in *DNSPolicy) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Weights within kubernetes types, where deepcopy-gen is used. -func (in *Weights) DeepCopyInto(out *Weights) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Weights. Required by controller-gen. -func (in *Weights) DeepCopy() *Weights { - if in == nil { - return nil - } - out := new(Weights) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Weights. Required by controller-gen. -func (in *Weights) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbcatalog/v2beta1/dns_json.gen.go b/proto-public/pbcatalog/v2beta1/dns_json.gen.go deleted file mode 100644 index fd320300a309..000000000000 --- a/proto-public/pbcatalog/v2beta1/dns_json.gen.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package catalogv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for DNSPolicy -func (this *DNSPolicy) MarshalJSON() ([]byte, error) { - str, err := DnsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DNSPolicy -func (this *DNSPolicy) UnmarshalJSON(b []byte) error { - return DnsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Weights -func (this *Weights) MarshalJSON() ([]byte, error) { - str, err := DnsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Weights -func (this *Weights) UnmarshalJSON(b []byte) error { - return DnsUnmarshaler.Unmarshal(b, this) -} - -var ( - DnsMarshaler = &protojson.MarshalOptions{} - DnsUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbcatalog/v2beta1/failover_policy.pb.binary.go b/proto-public/pbcatalog/v2beta1/failover_policy.pb.binary.go deleted file mode 100644 index d6733fa87698..000000000000 --- a/proto-public/pbcatalog/v2beta1/failover_policy.pb.binary.go +++ /dev/null @@ -1,38 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbcatalog/v2beta1/failover_policy.proto - -package catalogv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *FailoverPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *FailoverPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *FailoverConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *FailoverConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *FailoverDestination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *FailoverDestination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbcatalog/v2beta1/failover_policy.pb.go b/proto-public/pbcatalog/v2beta1/failover_policy.pb.go deleted file mode 100644 index 844e9e7a0af7..000000000000 --- a/proto-public/pbcatalog/v2beta1/failover_policy.pb.go +++ /dev/null @@ -1,460 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbcatalog/v2beta1/failover_policy.proto - -package catalogv2beta1 - -import ( - pbresource "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=FAILOVER_MODE_UNSPECIFIED;FAILOVER_MODE_SEQUENTIAL;FAILOVER_MODE_ORDER_BY_LOCALITY -// +kubebuilder:validation:Type=string -type FailoverMode int32 - -const ( - FailoverMode_FAILOVER_MODE_UNSPECIFIED FailoverMode = 0 - FailoverMode_FAILOVER_MODE_SEQUENTIAL FailoverMode = 1 - FailoverMode_FAILOVER_MODE_ORDER_BY_LOCALITY FailoverMode = 2 -) - -// Enum value maps for FailoverMode. -var ( - FailoverMode_name = map[int32]string{ - 0: "FAILOVER_MODE_UNSPECIFIED", - 1: "FAILOVER_MODE_SEQUENTIAL", - 2: "FAILOVER_MODE_ORDER_BY_LOCALITY", - } - FailoverMode_value = map[string]int32{ - "FAILOVER_MODE_UNSPECIFIED": 0, - "FAILOVER_MODE_SEQUENTIAL": 1, - "FAILOVER_MODE_ORDER_BY_LOCALITY": 2, - } -) - -func (x FailoverMode) Enum() *FailoverMode { - p := new(FailoverMode) - *p = x - return p -} - -func (x FailoverMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (FailoverMode) Descriptor() protoreflect.EnumDescriptor { - return file_pbcatalog_v2beta1_failover_policy_proto_enumTypes[0].Descriptor() -} - -func (FailoverMode) Type() protoreflect.EnumType { - return &file_pbcatalog_v2beta1_failover_policy_proto_enumTypes[0] -} - -func (x FailoverMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use FailoverMode.Descriptor instead. -func (FailoverMode) EnumDescriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_failover_policy_proto_rawDescGZIP(), []int{0} -} - -// This is a Resource type. -type FailoverPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Config defines failover for any named port not present in PortConfigs. - Config *FailoverConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - // PortConfigs defines failover for a specific port on this service and takes - // precedence over Config. - PortConfigs map[string]*FailoverConfig `protobuf:"bytes,2,rep,name=port_configs,json=portConfigs,proto3" json:"port_configs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *FailoverPolicy) Reset() { - *x = FailoverPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_failover_policy_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FailoverPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FailoverPolicy) ProtoMessage() {} - -func (x *FailoverPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_failover_policy_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FailoverPolicy.ProtoReflect.Descriptor instead. -func (*FailoverPolicy) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_failover_policy_proto_rawDescGZIP(), []int{0} -} - -func (x *FailoverPolicy) GetConfig() *FailoverConfig { - if x != nil { - return x.Config - } - return nil -} - -func (x *FailoverPolicy) GetPortConfigs() map[string]*FailoverConfig { - if x != nil { - return x.PortConfigs - } - return nil -} - -type FailoverConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Destinations specifies a fixed list of failover destinations to try. We - // never try a destination multiple times, so those are subtracted from this - // list before proceeding. - Destinations []*FailoverDestination `protobuf:"bytes,1,rep,name=destinations,proto3" json:"destinations,omitempty"` - // Mode specifies the type of failover that will be performed. Valid values are - // "sequential", "" (equivalent to "sequential") and "order-by-locality". - Mode FailoverMode `protobuf:"varint,2,opt,name=mode,proto3,enum=hashicorp.consul.catalog.v2beta1.FailoverMode" json:"mode,omitempty"` - Regions []string `protobuf:"bytes,3,rep,name=regions,proto3" json:"regions,omitempty"` - // SamenessGroup specifies the sameness group to failover to. - SamenessGroup string `protobuf:"bytes,4,opt,name=sameness_group,json=samenessGroup,proto3" json:"sameness_group,omitempty"` -} - -func (x *FailoverConfig) Reset() { - *x = FailoverConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_failover_policy_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FailoverConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FailoverConfig) ProtoMessage() {} - -func (x *FailoverConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_failover_policy_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FailoverConfig.ProtoReflect.Descriptor instead. -func (*FailoverConfig) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_failover_policy_proto_rawDescGZIP(), []int{1} -} - -func (x *FailoverConfig) GetDestinations() []*FailoverDestination { - if x != nil { - return x.Destinations - } - return nil -} - -func (x *FailoverConfig) GetMode() FailoverMode { - if x != nil { - return x.Mode - } - return FailoverMode_FAILOVER_MODE_UNSPECIFIED -} - -func (x *FailoverConfig) GetRegions() []string { - if x != nil { - return x.Regions - } - return nil -} - -func (x *FailoverConfig) GetSamenessGroup() string { - if x != nil { - return x.SamenessGroup - } - return "" -} - -type FailoverDestination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // This must be a Service. - Ref *pbresource.Reference `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` - // TODO: what should an empty port mean? - Port string `protobuf:"bytes,2,opt,name=port,proto3" json:"port,omitempty"` - Datacenter string `protobuf:"bytes,3,opt,name=datacenter,proto3" json:"datacenter,omitempty"` -} - -func (x *FailoverDestination) Reset() { - *x = FailoverDestination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_failover_policy_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FailoverDestination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FailoverDestination) ProtoMessage() {} - -func (x *FailoverDestination) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_failover_policy_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FailoverDestination.ProtoReflect.Descriptor instead. -func (*FailoverDestination) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_failover_policy_proto_rawDescGZIP(), []int{2} -} - -func (x *FailoverDestination) GetRef() *pbresource.Reference { - if x != nil { - return x.Ref - } - return nil -} - -func (x *FailoverDestination) GetPort() string { - if x != nil { - return x.Port - } - return "" -} - -func (x *FailoverDestination) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - -var File_pbcatalog_v2beta1_failover_policy_proto protoreflect.FileDescriptor - -var file_pbcatalog_v2beta1_failover_policy_proto_rawDesc = []byte{ - 0x0a, 0x27, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1c, 0x70, 0x62, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x70, 0x62, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xba, 0x02, 0x0a, 0x0e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, - 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x48, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, - 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x64, 0x0a, 0x0c, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, - 0x76, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x70, 0x6f, 0x72, 0x74, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x1a, 0x70, 0x0a, 0x10, 0x50, 0x6f, 0x72, 0x74, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x46, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, - 0x03, 0x22, 0xf0, 0x01, 0x0a, 0x0e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x59, 0x0a, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, - 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x46, 0x61, - 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x42, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, - 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, - 0x0e, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x22, 0x81, 0x01, 0x0a, 0x13, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, - 0x72, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x03, - 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, - 0x03, 0x72, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, - 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, - 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x2a, 0x70, 0x0a, 0x0c, 0x46, 0x61, 0x69, 0x6c, - 0x6f, 0x76, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x41, 0x49, 0x4c, - 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x46, 0x41, 0x49, 0x4c, 0x4f, - 0x56, 0x45, 0x52, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x45, 0x51, 0x55, 0x45, 0x4e, 0x54, - 0x49, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x46, 0x41, 0x49, 0x4c, 0x4f, 0x56, 0x45, - 0x52, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x42, 0x59, 0x5f, - 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x49, 0x54, 0x59, 0x10, 0x02, 0x42, 0xa9, 0x02, 0x0a, 0x24, 0x63, - 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x42, 0x13, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x43, 0xaa, 0x02, 0x20, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x43, - 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, - 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x3a, 0x3a, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbcatalog_v2beta1_failover_policy_proto_rawDescOnce sync.Once - file_pbcatalog_v2beta1_failover_policy_proto_rawDescData = file_pbcatalog_v2beta1_failover_policy_proto_rawDesc -) - -func file_pbcatalog_v2beta1_failover_policy_proto_rawDescGZIP() []byte { - file_pbcatalog_v2beta1_failover_policy_proto_rawDescOnce.Do(func() { - file_pbcatalog_v2beta1_failover_policy_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbcatalog_v2beta1_failover_policy_proto_rawDescData) - }) - return file_pbcatalog_v2beta1_failover_policy_proto_rawDescData -} - -var file_pbcatalog_v2beta1_failover_policy_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbcatalog_v2beta1_failover_policy_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_pbcatalog_v2beta1_failover_policy_proto_goTypes = []interface{}{ - (FailoverMode)(0), // 0: hashicorp.consul.catalog.v2beta1.FailoverMode - (*FailoverPolicy)(nil), // 1: hashicorp.consul.catalog.v2beta1.FailoverPolicy - (*FailoverConfig)(nil), // 2: hashicorp.consul.catalog.v2beta1.FailoverConfig - (*FailoverDestination)(nil), // 3: hashicorp.consul.catalog.v2beta1.FailoverDestination - nil, // 4: hashicorp.consul.catalog.v2beta1.FailoverPolicy.PortConfigsEntry - (*pbresource.Reference)(nil), // 5: hashicorp.consul.resource.Reference -} -var file_pbcatalog_v2beta1_failover_policy_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.catalog.v2beta1.FailoverPolicy.config:type_name -> hashicorp.consul.catalog.v2beta1.FailoverConfig - 4, // 1: hashicorp.consul.catalog.v2beta1.FailoverPolicy.port_configs:type_name -> hashicorp.consul.catalog.v2beta1.FailoverPolicy.PortConfigsEntry - 3, // 2: hashicorp.consul.catalog.v2beta1.FailoverConfig.destinations:type_name -> hashicorp.consul.catalog.v2beta1.FailoverDestination - 0, // 3: hashicorp.consul.catalog.v2beta1.FailoverConfig.mode:type_name -> hashicorp.consul.catalog.v2beta1.FailoverMode - 5, // 4: hashicorp.consul.catalog.v2beta1.FailoverDestination.ref:type_name -> hashicorp.consul.resource.Reference - 2, // 5: hashicorp.consul.catalog.v2beta1.FailoverPolicy.PortConfigsEntry.value:type_name -> hashicorp.consul.catalog.v2beta1.FailoverConfig - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name -} - -func init() { file_pbcatalog_v2beta1_failover_policy_proto_init() } -func file_pbcatalog_v2beta1_failover_policy_proto_init() { - if File_pbcatalog_v2beta1_failover_policy_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbcatalog_v2beta1_failover_policy_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FailoverPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_failover_policy_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FailoverConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_failover_policy_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FailoverDestination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbcatalog_v2beta1_failover_policy_proto_rawDesc, - NumEnums: 1, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbcatalog_v2beta1_failover_policy_proto_goTypes, - DependencyIndexes: file_pbcatalog_v2beta1_failover_policy_proto_depIdxs, - EnumInfos: file_pbcatalog_v2beta1_failover_policy_proto_enumTypes, - MessageInfos: file_pbcatalog_v2beta1_failover_policy_proto_msgTypes, - }.Build() - File_pbcatalog_v2beta1_failover_policy_proto = out.File - file_pbcatalog_v2beta1_failover_policy_proto_rawDesc = nil - file_pbcatalog_v2beta1_failover_policy_proto_goTypes = nil - file_pbcatalog_v2beta1_failover_policy_proto_depIdxs = nil -} diff --git a/proto-public/pbcatalog/v2beta1/failover_policy.proto b/proto-public/pbcatalog/v2beta1/failover_policy.proto deleted file mode 100644 index abbeb46a3ae8..000000000000 --- a/proto-public/pbcatalog/v2beta1/failover_policy.proto +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.catalog.v2beta1; - -import "pbresource/annotations.proto"; -import "pbresource/resource.proto"; - -// This is a Resource type. -message FailoverPolicy { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // Config defines failover for any named port not present in PortConfigs. - FailoverConfig config = 1; - - // PortConfigs defines failover for a specific port on this service and takes - // precedence over Config. - map port_configs = 2; -} - -message FailoverConfig { - // Destinations specifies a fixed list of failover destinations to try. We - // never try a destination multiple times, so those are subtracted from this - // list before proceeding. - repeated FailoverDestination destinations = 1; - - // Mode specifies the type of failover that will be performed. Valid values are - // "sequential", "" (equivalent to "sequential") and "order-by-locality". - FailoverMode mode = 2; - repeated string regions = 3; - - // SamenessGroup specifies the sameness group to failover to. - string sameness_group = 4; -} - -message FailoverDestination { - // This must be a Service. - hashicorp.consul.resource.Reference ref = 1; - // TODO: what should an empty port mean? - string port = 2; - string datacenter = 3; -} - -// +kubebuilder:validation:Enum=FAILOVER_MODE_UNSPECIFIED;FAILOVER_MODE_SEQUENTIAL;FAILOVER_MODE_ORDER_BY_LOCALITY -// +kubebuilder:validation:Type=string -enum FailoverMode { - FAILOVER_MODE_UNSPECIFIED = 0; - FAILOVER_MODE_SEQUENTIAL = 1; - FAILOVER_MODE_ORDER_BY_LOCALITY = 2; -} diff --git a/proto-public/pbcatalog/v2beta1/failover_policy_deepcopy.gen.go b/proto-public/pbcatalog/v2beta1/failover_policy_deepcopy.gen.go deleted file mode 100644 index fabe3f9e30a6..000000000000 --- a/proto-public/pbcatalog/v2beta1/failover_policy_deepcopy.gen.go +++ /dev/null @@ -1,69 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package catalogv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using FailoverPolicy within kubernetes types, where deepcopy-gen is used. -func (in *FailoverPolicy) DeepCopyInto(out *FailoverPolicy) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FailoverPolicy. Required by controller-gen. -func (in *FailoverPolicy) DeepCopy() *FailoverPolicy { - if in == nil { - return nil - } - out := new(FailoverPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new FailoverPolicy. Required by controller-gen. -func (in *FailoverPolicy) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using FailoverConfig within kubernetes types, where deepcopy-gen is used. -func (in *FailoverConfig) DeepCopyInto(out *FailoverConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FailoverConfig. Required by controller-gen. -func (in *FailoverConfig) DeepCopy() *FailoverConfig { - if in == nil { - return nil - } - out := new(FailoverConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new FailoverConfig. Required by controller-gen. -func (in *FailoverConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using FailoverDestination within kubernetes types, where deepcopy-gen is used. -func (in *FailoverDestination) DeepCopyInto(out *FailoverDestination) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FailoverDestination. Required by controller-gen. -func (in *FailoverDestination) DeepCopy() *FailoverDestination { - if in == nil { - return nil - } - out := new(FailoverDestination) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new FailoverDestination. Required by controller-gen. -func (in *FailoverDestination) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbcatalog/v2beta1/failover_policy_extras.go b/proto-public/pbcatalog/v2beta1/failover_policy_extras.go deleted file mode 100644 index 1187e93d7ae7..000000000000 --- a/proto-public/pbcatalog/v2beta1/failover_policy_extras.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package catalogv2beta1 - -import "github.com/hashicorp/consul/proto-public/pbresource" - -// GetUnderlyingDestinations will collect FailoverDestinations from all -// internal fields and bundle them up in one slice. -// -// NOTE: no deduplication occurs. -func (x *FailoverPolicy) GetUnderlyingDestinations() []*FailoverDestination { - if x == nil { - return nil - } - - estimate := 0 - if x.Config != nil { - estimate += len(x.Config.Destinations) - } - for _, pc := range x.PortConfigs { - estimate += len(pc.Destinations) - } - - out := make([]*FailoverDestination, 0, estimate) - if x.Config != nil { - out = append(out, x.Config.Destinations...) - } - for _, pc := range x.PortConfigs { - out = append(out, pc.Destinations...) - } - return out -} - -// GetUnderlyingDestinationRefs is like GetUnderlyingDestinations except it -// returns a slice of References. -// -// NOTE: no deduplication occurs. -func (x *FailoverPolicy) GetUnderlyingDestinationRefs() []*pbresource.Reference { - if x == nil { - return nil - } - - dests := x.GetUnderlyingDestinations() - - out := make([]*pbresource.Reference, 0, len(dests)) - for _, dest := range dests { - if dest.Ref != nil { - out = append(out, dest.Ref) - } - } - - return out -} - -// IsEmpty returns true if a config has no definition. -func (x *FailoverConfig) IsEmpty() bool { - if x == nil { - return true - } - return len(x.Destinations) == 0 && - x.Mode == 0 && - len(x.Regions) == 0 && - x.SamenessGroup == "" -} diff --git a/proto-public/pbcatalog/v2beta1/failover_policy_extras_test.go b/proto-public/pbcatalog/v2beta1/failover_policy_extras_test.go deleted file mode 100644 index 073573e857ff..000000000000 --- a/proto-public/pbcatalog/v2beta1/failover_policy_extras_test.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package catalogv2beta1 - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func TestFailoverPolicy_IsEmpty(t *testing.T) { - t.Run("nil", func(t *testing.T) { - var fc *FailoverConfig - require.True(t, fc.IsEmpty()) - }) - t.Run("empty", func(t *testing.T) { - fc := &FailoverConfig{} - require.True(t, fc.IsEmpty()) - }) - t.Run("dest", func(t *testing.T) { - fc := &FailoverConfig{ - Destinations: []*FailoverDestination{ - newFailoverDestination("foo"), - }, - } - require.False(t, fc.IsEmpty()) - }) - t.Run("regions", func(t *testing.T) { - fc := &FailoverConfig{ - Regions: []string{"us-east"}, - } - require.False(t, fc.IsEmpty()) - }) - t.Run("regions", func(t *testing.T) { - fc := &FailoverConfig{ - SamenessGroup: "blah", - } - require.False(t, fc.IsEmpty()) - }) -} - -func TestFailoverPolicy_GetUnderlyingDestinations_AndRefs(t *testing.T) { - type testcase struct { - failover *FailoverPolicy - expectDests []*FailoverDestination - expectRefs []*pbresource.Reference - } - - run := func(t *testing.T, tc testcase) { - assertSliceEquals(t, tc.expectDests, tc.failover.GetUnderlyingDestinations()) - assertSliceEquals(t, tc.expectRefs, tc.failover.GetUnderlyingDestinationRefs()) - } - - cases := map[string]testcase{ - "nil": {}, - "kitchen sink dests": { - failover: &FailoverPolicy{ - Config: &FailoverConfig{ - Destinations: []*FailoverDestination{ - newFailoverDestination("foo"), - newFailoverDestination("bar"), - }, - }, - PortConfigs: map[string]*FailoverConfig{ - "admin": { - Destinations: []*FailoverDestination{ - newFailoverDestination("admin"), - }, - }, - "web": { - Destinations: []*FailoverDestination{ - newFailoverDestination("foo"), // duplicated - newFailoverDestination("www"), - }, - }, - }, - }, - expectDests: []*FailoverDestination{ - newFailoverDestination("foo"), - newFailoverDestination("bar"), - newFailoverDestination("admin"), - newFailoverDestination("foo"), // duplicated - newFailoverDestination("www"), - }, - expectRefs: []*pbresource.Reference{ - newFailoverRef("foo"), - newFailoverRef("bar"), - newFailoverRef("admin"), - newFailoverRef("foo"), // duplicated - newFailoverRef("www"), - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func assertSliceEquals[V proto.Message](t *testing.T, expect, got []V) { - t.Helper() - - require.Len(t, got, len(expect)) - - // O(N*M) scan - var expectedMissing []string - for _, expectVal := range expect { - found := false - for j, gotVal := range got { - if proto.Equal(expectVal, gotVal) { - found = true - got = append(got[:j], got[j+1:]...) // remove found item - break - } - } - - if !found { - expectedMissing = append(expectedMissing, protoToString(t, expectVal)) - } - } - - if len(expectedMissing) > 0 || len(got) > 0 { - var gotMissing []string - for _, gotVal := range got { - gotMissing = append(gotMissing, protoToString(t, gotVal)) - } - - t.Fatalf("assertion failed: unmatched values\n\texpected: %s\n\tactual: %s", - expectedMissing, - gotMissing, - ) - } -} - -func protoToString[V proto.Message](t *testing.T, pb V) string { - m := protojson.MarshalOptions{ - Indent: " ", - } - gotJSON, err := m.Marshal(pb) - require.NoError(t, err) - return string(gotJSON) -} - -func newFailoverRef(name string) *pbresource.Reference { - return &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "fake", - GroupVersion: "v1alpha1", - Kind: "fake", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: name, - } -} - -func newFailoverDestination(name string) *FailoverDestination { - return &FailoverDestination{ - Ref: newFailoverRef(name), - } -} diff --git a/proto-public/pbcatalog/v2beta1/failover_policy_json.gen.go b/proto-public/pbcatalog/v2beta1/failover_policy_json.gen.go deleted file mode 100644 index 85998288a031..000000000000 --- a/proto-public/pbcatalog/v2beta1/failover_policy_json.gen.go +++ /dev/null @@ -1,44 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package catalogv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for FailoverPolicy -func (this *FailoverPolicy) MarshalJSON() ([]byte, error) { - str, err := FailoverPolicyMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for FailoverPolicy -func (this *FailoverPolicy) UnmarshalJSON(b []byte) error { - return FailoverPolicyUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for FailoverConfig -func (this *FailoverConfig) MarshalJSON() ([]byte, error) { - str, err := FailoverPolicyMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for FailoverConfig -func (this *FailoverConfig) UnmarshalJSON(b []byte) error { - return FailoverPolicyUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for FailoverDestination -func (this *FailoverDestination) MarshalJSON() ([]byte, error) { - str, err := FailoverPolicyMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for FailoverDestination -func (this *FailoverDestination) UnmarshalJSON(b []byte) error { - return FailoverPolicyUnmarshaler.Unmarshal(b, this) -} - -var ( - FailoverPolicyMarshaler = &protojson.MarshalOptions{} - FailoverPolicyUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbcatalog/v2beta1/health.pb.binary.go b/proto-public/pbcatalog/v2beta1/health.pb.binary.go deleted file mode 100644 index b5592db6c464..000000000000 --- a/proto-public/pbcatalog/v2beta1/health.pb.binary.go +++ /dev/null @@ -1,98 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbcatalog/v2beta1/health.proto - -package catalogv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HealthStatus) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HealthStatus) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HealthChecks) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HealthChecks) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HealthCheck) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HealthCheck) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPCheck) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPCheck) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TCPCheck) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TCPCheck) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *UDPCheck) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *UDPCheck) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCCheck) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCCheck) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *OSServiceCheck) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *OSServiceCheck) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *CheckTLSConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *CheckTLSConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbcatalog/v2beta1/health.pb.go b/proto-public/pbcatalog/v2beta1/health.pb.go deleted file mode 100644 index 154a183831b2..000000000000 --- a/proto-public/pbcatalog/v2beta1/health.pb.go +++ /dev/null @@ -1,1057 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbcatalog/v2beta1/health.proto - -package catalogv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=HEALTH_ANY;HEALTH_PASSING;HEALTH_WARNING;HEALTH_CRITICAL;HEALTH_MAINTENANCE -// +kubebuilder:validation:Type=string -type Health int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - Health_HEALTH_ANY Health = 0 - Health_HEALTH_PASSING Health = 1 - Health_HEALTH_WARNING Health = 2 - Health_HEALTH_CRITICAL Health = 3 - Health_HEALTH_MAINTENANCE Health = 4 -) - -// Enum value maps for Health. -var ( - Health_name = map[int32]string{ - 0: "HEALTH_ANY", - 1: "HEALTH_PASSING", - 2: "HEALTH_WARNING", - 3: "HEALTH_CRITICAL", - 4: "HEALTH_MAINTENANCE", - } - Health_value = map[string]int32{ - "HEALTH_ANY": 0, - "HEALTH_PASSING": 1, - "HEALTH_WARNING": 2, - "HEALTH_CRITICAL": 3, - "HEALTH_MAINTENANCE": 4, - } -) - -func (x Health) Enum() *Health { - p := new(Health) - *p = x - return p -} - -func (x Health) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Health) Descriptor() protoreflect.EnumDescriptor { - return file_pbcatalog_v2beta1_health_proto_enumTypes[0].Descriptor() -} - -func (Health) Type() protoreflect.EnumType { - return &file_pbcatalog_v2beta1_health_proto_enumTypes[0] -} - -func (x Health) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Health.Descriptor instead. -func (Health) EnumDescriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_health_proto_rawDescGZIP(), []int{0} -} - -// This resource will belong to a workload or a node and will have an ownership relationship. -type HealthStatus struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Type is the type of this health check, such as http, tcp, or kubernetes-readiness - Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` - // Health is the status. This maps to existing health check statuses. - Status Health `protobuf:"varint,2,opt,name=status,proto3,enum=hashicorp.consul.catalog.v2beta1.Health" json:"status,omitempty"` - // Description is the description for this status. - Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - // Output is the output from running the check that resulted in this status - Output string `protobuf:"bytes,4,opt,name=output,proto3" json:"output,omitempty"` -} - -func (x *HealthStatus) Reset() { - *x = HealthStatus{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthStatus) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthStatus) ProtoMessage() {} - -func (x *HealthStatus) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthStatus.ProtoReflect.Descriptor instead. -func (*HealthStatus) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_health_proto_rawDescGZIP(), []int{0} -} - -func (x *HealthStatus) GetType() string { - if x != nil { - return x.Type - } - return "" -} - -func (x *HealthStatus) GetStatus() Health { - if x != nil { - return x.Status - } - return Health_HEALTH_ANY -} - -func (x *HealthStatus) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -func (x *HealthStatus) GetOutput() string { - if x != nil { - return x.Output - } - return "" -} - -type HealthChecks struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Workloads *WorkloadSelector `protobuf:"bytes,1,opt,name=workloads,proto3" json:"workloads,omitempty"` - HealthChecks []*HealthCheck `protobuf:"bytes,2,rep,name=health_checks,json=healthChecks,proto3" json:"health_checks,omitempty"` -} - -func (x *HealthChecks) Reset() { - *x = HealthChecks{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthChecks) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthChecks) ProtoMessage() {} - -func (x *HealthChecks) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthChecks.ProtoReflect.Descriptor instead. -func (*HealthChecks) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_health_proto_rawDescGZIP(), []int{1} -} - -func (x *HealthChecks) GetWorkloads() *WorkloadSelector { - if x != nil { - return x.Workloads - } - return nil -} - -func (x *HealthChecks) GetHealthChecks() []*HealthCheck { - if x != nil { - return x.HealthChecks - } - return nil -} - -type HealthCheck struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Types that are assignable to Definition: - // - // *HealthCheck_Http - // *HealthCheck_Tcp - // *HealthCheck_Udp - // *HealthCheck_Grpc - // *HealthCheck_OsService - Definition isHealthCheck_Definition `protobuf_oneof:"definition"` - // +kubebuilder:validation:Format=duration - Interval *durationpb.Duration `protobuf:"bytes,7,opt,name=interval,proto3" json:"interval,omitempty"` - // +kubebuilder:validation:Format=duration - Timeout *durationpb.Duration `protobuf:"bytes,8,opt,name=timeout,proto3" json:"timeout,omitempty"` - // +kubebuilder:validation:Format=duration - DeregisterCriticalAfter *durationpb.Duration `protobuf:"bytes,9,opt,name=deregister_critical_after,json=deregisterCriticalAfter,proto3" json:"deregister_critical_after,omitempty"` -} - -func (x *HealthCheck) Reset() { - *x = HealthCheck{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthCheck) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthCheck) ProtoMessage() {} - -func (x *HealthCheck) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthCheck.ProtoReflect.Descriptor instead. -func (*HealthCheck) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_health_proto_rawDescGZIP(), []int{2} -} - -func (x *HealthCheck) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (m *HealthCheck) GetDefinition() isHealthCheck_Definition { - if m != nil { - return m.Definition - } - return nil -} - -func (x *HealthCheck) GetHttp() *HTTPCheck { - if x, ok := x.GetDefinition().(*HealthCheck_Http); ok { - return x.Http - } - return nil -} - -func (x *HealthCheck) GetTcp() *TCPCheck { - if x, ok := x.GetDefinition().(*HealthCheck_Tcp); ok { - return x.Tcp - } - return nil -} - -func (x *HealthCheck) GetUdp() *UDPCheck { - if x, ok := x.GetDefinition().(*HealthCheck_Udp); ok { - return x.Udp - } - return nil -} - -func (x *HealthCheck) GetGrpc() *GRPCCheck { - if x, ok := x.GetDefinition().(*HealthCheck_Grpc); ok { - return x.Grpc - } - return nil -} - -func (x *HealthCheck) GetOsService() *OSServiceCheck { - if x, ok := x.GetDefinition().(*HealthCheck_OsService); ok { - return x.OsService - } - return nil -} - -func (x *HealthCheck) GetInterval() *durationpb.Duration { - if x != nil { - return x.Interval - } - return nil -} - -func (x *HealthCheck) GetTimeout() *durationpb.Duration { - if x != nil { - return x.Timeout - } - return nil -} - -func (x *HealthCheck) GetDeregisterCriticalAfter() *durationpb.Duration { - if x != nil { - return x.DeregisterCriticalAfter - } - return nil -} - -type isHealthCheck_Definition interface { - isHealthCheck_Definition() -} - -type HealthCheck_Http struct { - Http *HTTPCheck `protobuf:"bytes,2,opt,name=http,proto3,oneof"` -} - -type HealthCheck_Tcp struct { - Tcp *TCPCheck `protobuf:"bytes,3,opt,name=tcp,proto3,oneof"` -} - -type HealthCheck_Udp struct { - Udp *UDPCheck `protobuf:"bytes,4,opt,name=udp,proto3,oneof"` -} - -type HealthCheck_Grpc struct { - Grpc *GRPCCheck `protobuf:"bytes,5,opt,name=grpc,proto3,oneof"` -} - -type HealthCheck_OsService struct { - OsService *OSServiceCheck `protobuf:"bytes,6,opt,name=os_service,json=osService,proto3,oneof"` -} - -func (*HealthCheck_Http) isHealthCheck_Definition() {} - -func (*HealthCheck_Tcp) isHealthCheck_Definition() {} - -func (*HealthCheck_Udp) isHealthCheck_Definition() {} - -func (*HealthCheck_Grpc) isHealthCheck_Definition() {} - -func (*HealthCheck_OsService) isHealthCheck_Definition() {} - -type HTTPCheck struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` - Header map[string]string `protobuf:"bytes,2,rep,name=header,proto3" json:"header,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Method string `protobuf:"bytes,3,opt,name=method,proto3" json:"method,omitempty"` - Body string `protobuf:"bytes,4,opt,name=body,proto3" json:"body,omitempty"` - DisableRedirects bool `protobuf:"varint,5,opt,name=disable_redirects,json=disableRedirects,proto3" json:"disable_redirects,omitempty"` - Tls *CheckTLSConfig `protobuf:"bytes,6,opt,name=tls,proto3" json:"tls,omitempty"` -} - -func (x *HTTPCheck) Reset() { - *x = HTTPCheck{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPCheck) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPCheck) ProtoMessage() {} - -func (x *HTTPCheck) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPCheck.ProtoReflect.Descriptor instead. -func (*HTTPCheck) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_health_proto_rawDescGZIP(), []int{3} -} - -func (x *HTTPCheck) GetUrl() string { - if x != nil { - return x.Url - } - return "" -} - -func (x *HTTPCheck) GetHeader() map[string]string { - if x != nil { - return x.Header - } - return nil -} - -func (x *HTTPCheck) GetMethod() string { - if x != nil { - return x.Method - } - return "" -} - -func (x *HTTPCheck) GetBody() string { - if x != nil { - return x.Body - } - return "" -} - -func (x *HTTPCheck) GetDisableRedirects() bool { - if x != nil { - return x.DisableRedirects - } - return false -} - -func (x *HTTPCheck) GetTls() *CheckTLSConfig { - if x != nil { - return x.Tls - } - return nil -} - -type TCPCheck struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` -} - -func (x *TCPCheck) Reset() { - *x = TCPCheck{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TCPCheck) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TCPCheck) ProtoMessage() {} - -func (x *TCPCheck) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TCPCheck.ProtoReflect.Descriptor instead. -func (*TCPCheck) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_health_proto_rawDescGZIP(), []int{4} -} - -func (x *TCPCheck) GetAddress() string { - if x != nil { - return x.Address - } - return "" -} - -type UDPCheck struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` -} - -func (x *UDPCheck) Reset() { - *x = UDPCheck{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UDPCheck) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UDPCheck) ProtoMessage() {} - -func (x *UDPCheck) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UDPCheck.ProtoReflect.Descriptor instead. -func (*UDPCheck) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_health_proto_rawDescGZIP(), []int{5} -} - -func (x *UDPCheck) GetAddress() string { - if x != nil { - return x.Address - } - return "" -} - -type GRPCCheck struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` - Tls *CheckTLSConfig `protobuf:"bytes,2,opt,name=tls,proto3" json:"tls,omitempty"` -} - -func (x *GRPCCheck) Reset() { - *x = GRPCCheck{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCCheck) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCCheck) ProtoMessage() {} - -func (x *GRPCCheck) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GRPCCheck.ProtoReflect.Descriptor instead. -func (*GRPCCheck) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_health_proto_rawDescGZIP(), []int{6} -} - -func (x *GRPCCheck) GetAddress() string { - if x != nil { - return x.Address - } - return "" -} - -func (x *GRPCCheck) GetTls() *CheckTLSConfig { - if x != nil { - return x.Tls - } - return nil -} - -type OSServiceCheck struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` -} - -func (x *OSServiceCheck) Reset() { - *x = OSServiceCheck{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OSServiceCheck) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OSServiceCheck) ProtoMessage() {} - -func (x *OSServiceCheck) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OSServiceCheck.ProtoReflect.Descriptor instead. -func (*OSServiceCheck) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_health_proto_rawDescGZIP(), []int{7} -} - -func (x *OSServiceCheck) GetAddress() string { - if x != nil { - return x.Address - } - return "" -} - -type CheckTLSConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TlsServerName string `protobuf:"bytes,1,opt,name=tls_server_name,json=tlsServerName,proto3" json:"tls_server_name,omitempty"` - TlsSkipVerify bool `protobuf:"varint,2,opt,name=tls_skip_verify,json=tlsSkipVerify,proto3" json:"tls_skip_verify,omitempty"` - UseTls bool `protobuf:"varint,3,opt,name=use_tls,json=useTls,proto3" json:"use_tls,omitempty"` -} - -func (x *CheckTLSConfig) Reset() { - *x = CheckTLSConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CheckTLSConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CheckTLSConfig) ProtoMessage() {} - -func (x *CheckTLSConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_health_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CheckTLSConfig.ProtoReflect.Descriptor instead. -func (*CheckTLSConfig) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_health_proto_rawDescGZIP(), []int{8} -} - -func (x *CheckTLSConfig) GetTlsServerName() string { - if x != nil { - return x.TlsServerName - } - return "" -} - -func (x *CheckTLSConfig) GetTlsSkipVerify() bool { - if x != nil { - return x.TlsSkipVerify - } - return false -} - -func (x *CheckTLSConfig) GetUseTls() bool { - if x != nil { - return x.UseTls - } - return false -} - -var File_pbcatalog_v2beta1_health_proto protoreflect.FileDescriptor - -var file_pbcatalog_v2beta1_health_proto_rawDesc = []byte{ - 0x0a, 0x1e, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x20, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0xa6, 0x01, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x40, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x6f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0xbc, 0x01, 0x0a, 0x0c, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, 0x50, 0x0a, 0x09, - 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, 0x52, - 0x0a, 0x0d, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x52, 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0xcb, 0x04, 0x0a, 0x0b, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x41, - 0x0a, 0x04, 0x68, 0x74, 0x74, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x48, 0x54, 0x54, 0x50, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x04, 0x68, 0x74, 0x74, - 0x70, 0x12, 0x3e, 0x0a, 0x03, 0x74, 0x63, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x54, 0x43, 0x50, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x03, 0x74, 0x63, - 0x70, 0x12, 0x3e, 0x0a, 0x03, 0x75, 0x64, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x55, 0x44, 0x50, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x03, 0x75, 0x64, - 0x70, 0x12, 0x41, 0x0a, 0x04, 0x67, 0x72, 0x70, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x04, - 0x67, 0x72, 0x70, 0x63, 0x12, 0x51, 0x0a, 0x0a, 0x6f, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4f, 0x53, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x09, 0x6f, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x76, 0x61, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x33, - 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x12, 0x55, 0x0a, 0x19, 0x64, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x5f, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x17, 0x64, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, - 0x74, 0x69, 0x63, 0x61, 0x6c, 0x41, 0x66, 0x74, 0x65, 0x72, 0x42, 0x0c, 0x0a, 0x0a, 0x64, 0x65, - 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xc6, 0x02, 0x0a, 0x09, 0x48, 0x54, 0x54, - 0x50, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x4f, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, - 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x10, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x73, 0x12, 0x42, 0x0a, 0x03, 0x74, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x03, 0x74, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0x24, 0x0a, 0x08, 0x54, 0x43, 0x50, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x18, 0x0a, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x24, 0x0a, 0x08, 0x55, 0x44, 0x50, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x69, 0x0a, - 0x09, 0x47, 0x52, 0x50, 0x43, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x12, 0x42, 0x0a, 0x03, 0x74, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x03, 0x74, 0x6c, 0x73, 0x22, 0x2a, 0x0a, 0x0e, 0x4f, 0x53, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x22, 0x79, 0x0a, 0x0e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x4c, 0x53, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x6c, 0x73, 0x5f, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x74, 0x6c, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, - 0x0a, 0x0f, 0x74, 0x6c, 0x73, 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x74, 0x6c, 0x73, 0x53, 0x6b, 0x69, 0x70, - 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x5f, 0x74, 0x6c, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, 0x73, 0x65, 0x54, 0x6c, 0x73, 0x2a, - 0x6d, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x0e, 0x0a, 0x0a, 0x48, 0x45, 0x41, - 0x4c, 0x54, 0x48, 0x5f, 0x41, 0x4e, 0x59, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x48, 0x45, 0x41, - 0x4c, 0x54, 0x48, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x12, 0x0a, - 0x0e, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, - 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x52, 0x49, 0x54, - 0x49, 0x43, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, - 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x04, 0x42, 0xa1, - 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x2f, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x43, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, - 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2c, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x3a, 0x3a, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbcatalog_v2beta1_health_proto_rawDescOnce sync.Once - file_pbcatalog_v2beta1_health_proto_rawDescData = file_pbcatalog_v2beta1_health_proto_rawDesc -) - -func file_pbcatalog_v2beta1_health_proto_rawDescGZIP() []byte { - file_pbcatalog_v2beta1_health_proto_rawDescOnce.Do(func() { - file_pbcatalog_v2beta1_health_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbcatalog_v2beta1_health_proto_rawDescData) - }) - return file_pbcatalog_v2beta1_health_proto_rawDescData -} - -var file_pbcatalog_v2beta1_health_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbcatalog_v2beta1_health_proto_msgTypes = make([]protoimpl.MessageInfo, 10) -var file_pbcatalog_v2beta1_health_proto_goTypes = []interface{}{ - (Health)(0), // 0: hashicorp.consul.catalog.v2beta1.Health - (*HealthStatus)(nil), // 1: hashicorp.consul.catalog.v2beta1.HealthStatus - (*HealthChecks)(nil), // 2: hashicorp.consul.catalog.v2beta1.HealthChecks - (*HealthCheck)(nil), // 3: hashicorp.consul.catalog.v2beta1.HealthCheck - (*HTTPCheck)(nil), // 4: hashicorp.consul.catalog.v2beta1.HTTPCheck - (*TCPCheck)(nil), // 5: hashicorp.consul.catalog.v2beta1.TCPCheck - (*UDPCheck)(nil), // 6: hashicorp.consul.catalog.v2beta1.UDPCheck - (*GRPCCheck)(nil), // 7: hashicorp.consul.catalog.v2beta1.GRPCCheck - (*OSServiceCheck)(nil), // 8: hashicorp.consul.catalog.v2beta1.OSServiceCheck - (*CheckTLSConfig)(nil), // 9: hashicorp.consul.catalog.v2beta1.CheckTLSConfig - nil, // 10: hashicorp.consul.catalog.v2beta1.HTTPCheck.HeaderEntry - (*WorkloadSelector)(nil), // 11: hashicorp.consul.catalog.v2beta1.WorkloadSelector - (*durationpb.Duration)(nil), // 12: google.protobuf.Duration -} -var file_pbcatalog_v2beta1_health_proto_depIdxs = []int32{ - 0, // 0: hashicorp.consul.catalog.v2beta1.HealthStatus.status:type_name -> hashicorp.consul.catalog.v2beta1.Health - 11, // 1: hashicorp.consul.catalog.v2beta1.HealthChecks.workloads:type_name -> hashicorp.consul.catalog.v2beta1.WorkloadSelector - 3, // 2: hashicorp.consul.catalog.v2beta1.HealthChecks.health_checks:type_name -> hashicorp.consul.catalog.v2beta1.HealthCheck - 4, // 3: hashicorp.consul.catalog.v2beta1.HealthCheck.http:type_name -> hashicorp.consul.catalog.v2beta1.HTTPCheck - 5, // 4: hashicorp.consul.catalog.v2beta1.HealthCheck.tcp:type_name -> hashicorp.consul.catalog.v2beta1.TCPCheck - 6, // 5: hashicorp.consul.catalog.v2beta1.HealthCheck.udp:type_name -> hashicorp.consul.catalog.v2beta1.UDPCheck - 7, // 6: hashicorp.consul.catalog.v2beta1.HealthCheck.grpc:type_name -> hashicorp.consul.catalog.v2beta1.GRPCCheck - 8, // 7: hashicorp.consul.catalog.v2beta1.HealthCheck.os_service:type_name -> hashicorp.consul.catalog.v2beta1.OSServiceCheck - 12, // 8: hashicorp.consul.catalog.v2beta1.HealthCheck.interval:type_name -> google.protobuf.Duration - 12, // 9: hashicorp.consul.catalog.v2beta1.HealthCheck.timeout:type_name -> google.protobuf.Duration - 12, // 10: hashicorp.consul.catalog.v2beta1.HealthCheck.deregister_critical_after:type_name -> google.protobuf.Duration - 10, // 11: hashicorp.consul.catalog.v2beta1.HTTPCheck.header:type_name -> hashicorp.consul.catalog.v2beta1.HTTPCheck.HeaderEntry - 9, // 12: hashicorp.consul.catalog.v2beta1.HTTPCheck.tls:type_name -> hashicorp.consul.catalog.v2beta1.CheckTLSConfig - 9, // 13: hashicorp.consul.catalog.v2beta1.GRPCCheck.tls:type_name -> hashicorp.consul.catalog.v2beta1.CheckTLSConfig - 14, // [14:14] is the sub-list for method output_type - 14, // [14:14] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name -} - -func init() { file_pbcatalog_v2beta1_health_proto_init() } -func file_pbcatalog_v2beta1_health_proto_init() { - if File_pbcatalog_v2beta1_health_proto != nil { - return - } - file_pbcatalog_v2beta1_selector_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbcatalog_v2beta1_health_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthStatus); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_health_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthChecks); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_health_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheck); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_health_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPCheck); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_health_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TCPCheck); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_health_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UDPCheck); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_health_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCCheck); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_health_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OSServiceCheck); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_health_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CheckTLSConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbcatalog_v2beta1_health_proto_msgTypes[2].OneofWrappers = []interface{}{ - (*HealthCheck_Http)(nil), - (*HealthCheck_Tcp)(nil), - (*HealthCheck_Udp)(nil), - (*HealthCheck_Grpc)(nil), - (*HealthCheck_OsService)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbcatalog_v2beta1_health_proto_rawDesc, - NumEnums: 1, - NumMessages: 10, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbcatalog_v2beta1_health_proto_goTypes, - DependencyIndexes: file_pbcatalog_v2beta1_health_proto_depIdxs, - EnumInfos: file_pbcatalog_v2beta1_health_proto_enumTypes, - MessageInfos: file_pbcatalog_v2beta1_health_proto_msgTypes, - }.Build() - File_pbcatalog_v2beta1_health_proto = out.File - file_pbcatalog_v2beta1_health_proto_rawDesc = nil - file_pbcatalog_v2beta1_health_proto_goTypes = nil - file_pbcatalog_v2beta1_health_proto_depIdxs = nil -} diff --git a/proto-public/pbcatalog/v2beta1/health.proto b/proto-public/pbcatalog/v2beta1/health.proto deleted file mode 100644 index 29b4f5bf4cdd..000000000000 --- a/proto-public/pbcatalog/v2beta1/health.proto +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.catalog.v2beta1; - -import "google/protobuf/duration.proto"; -import "pbcatalog/v2beta1/selector.proto"; -import "pbresource/annotations.proto"; - -// This resource will belong to a workload or a node and will have an ownership relationship. -message HealthStatus { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // Type is the type of this health check, such as http, tcp, or kubernetes-readiness - string type = 1; - // Health is the status. This maps to existing health check statuses. - Health status = 2; - // Description is the description for this status. - string description = 3; - // Output is the output from running the check that resulted in this status - string output = 4; -} - -// +kubebuilder:validation:Enum=HEALTH_ANY;HEALTH_PASSING;HEALTH_WARNING;HEALTH_CRITICAL;HEALTH_MAINTENANCE -// +kubebuilder:validation:Type=string -enum Health { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - HEALTH_ANY = 0; - HEALTH_PASSING = 1; - HEALTH_WARNING = 2; - HEALTH_CRITICAL = 3; - HEALTH_MAINTENANCE = 4; -} - -message HealthChecks { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - WorkloadSelector workloads = 1; - repeated HealthCheck health_checks = 2; -} - -message HealthCheck { - string name = 1; - oneof definition { - HTTPCheck http = 2; - TCPCheck tcp = 3; - UDPCheck udp = 4; - GRPCCheck grpc = 5; - OSServiceCheck os_service = 6; - } - // +kubebuilder:validation:Format=duration - google.protobuf.Duration interval = 7; - // +kubebuilder:validation:Format=duration - google.protobuf.Duration timeout = 8; - // +kubebuilder:validation:Format=duration - google.protobuf.Duration deregister_critical_after = 9; -} - -message HTTPCheck { - string url = 1; - map header = 2; - string method = 3; - string body = 4; - bool disable_redirects = 5; - CheckTLSConfig tls = 6; -} - -message TCPCheck { - string address = 1; -} - -message UDPCheck { - string address = 1; -} - -message GRPCCheck { - string address = 1; - CheckTLSConfig tls = 2; -} - -message OSServiceCheck { - string address = 1; -} - -message CheckTLSConfig { - string tls_server_name = 1; - bool tls_skip_verify = 2; - bool use_tls = 3; -} diff --git a/proto-public/pbcatalog/v2beta1/health_deepcopy.gen.go b/proto-public/pbcatalog/v2beta1/health_deepcopy.gen.go deleted file mode 100644 index 677a1af1056d..000000000000 --- a/proto-public/pbcatalog/v2beta1/health_deepcopy.gen.go +++ /dev/null @@ -1,195 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package catalogv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using HealthStatus within kubernetes types, where deepcopy-gen is used. -func (in *HealthStatus) DeepCopyInto(out *HealthStatus) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthStatus. Required by controller-gen. -func (in *HealthStatus) DeepCopy() *HealthStatus { - if in == nil { - return nil - } - out := new(HealthStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HealthStatus. Required by controller-gen. -func (in *HealthStatus) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HealthChecks within kubernetes types, where deepcopy-gen is used. -func (in *HealthChecks) DeepCopyInto(out *HealthChecks) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthChecks. Required by controller-gen. -func (in *HealthChecks) DeepCopy() *HealthChecks { - if in == nil { - return nil - } - out := new(HealthChecks) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HealthChecks. Required by controller-gen. -func (in *HealthChecks) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HealthCheck within kubernetes types, where deepcopy-gen is used. -func (in *HealthCheck) DeepCopyInto(out *HealthCheck) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthCheck. Required by controller-gen. -func (in *HealthCheck) DeepCopy() *HealthCheck { - if in == nil { - return nil - } - out := new(HealthCheck) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HealthCheck. Required by controller-gen. -func (in *HealthCheck) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HTTPCheck within kubernetes types, where deepcopy-gen is used. -func (in *HTTPCheck) DeepCopyInto(out *HTTPCheck) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPCheck. Required by controller-gen. -func (in *HTTPCheck) DeepCopy() *HTTPCheck { - if in == nil { - return nil - } - out := new(HTTPCheck) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPCheck. Required by controller-gen. -func (in *HTTPCheck) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using TCPCheck within kubernetes types, where deepcopy-gen is used. -func (in *TCPCheck) DeepCopyInto(out *TCPCheck) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPCheck. Required by controller-gen. -func (in *TCPCheck) DeepCopy() *TCPCheck { - if in == nil { - return nil - } - out := new(TCPCheck) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TCPCheck. Required by controller-gen. -func (in *TCPCheck) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using UDPCheck within kubernetes types, where deepcopy-gen is used. -func (in *UDPCheck) DeepCopyInto(out *UDPCheck) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UDPCheck. Required by controller-gen. -func (in *UDPCheck) DeepCopy() *UDPCheck { - if in == nil { - return nil - } - out := new(UDPCheck) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new UDPCheck. Required by controller-gen. -func (in *UDPCheck) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using GRPCCheck within kubernetes types, where deepcopy-gen is used. -func (in *GRPCCheck) DeepCopyInto(out *GRPCCheck) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCCheck. Required by controller-gen. -func (in *GRPCCheck) DeepCopy() *GRPCCheck { - if in == nil { - return nil - } - out := new(GRPCCheck) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GRPCCheck. Required by controller-gen. -func (in *GRPCCheck) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using OSServiceCheck within kubernetes types, where deepcopy-gen is used. -func (in *OSServiceCheck) DeepCopyInto(out *OSServiceCheck) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSServiceCheck. Required by controller-gen. -func (in *OSServiceCheck) DeepCopy() *OSServiceCheck { - if in == nil { - return nil - } - out := new(OSServiceCheck) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new OSServiceCheck. Required by controller-gen. -func (in *OSServiceCheck) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using CheckTLSConfig within kubernetes types, where deepcopy-gen is used. -func (in *CheckTLSConfig) DeepCopyInto(out *CheckTLSConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheckTLSConfig. Required by controller-gen. -func (in *CheckTLSConfig) DeepCopy() *CheckTLSConfig { - if in == nil { - return nil - } - out := new(CheckTLSConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new CheckTLSConfig. Required by controller-gen. -func (in *CheckTLSConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbcatalog/v2beta1/health_json.gen.go b/proto-public/pbcatalog/v2beta1/health_json.gen.go deleted file mode 100644 index 7c0065d922b4..000000000000 --- a/proto-public/pbcatalog/v2beta1/health_json.gen.go +++ /dev/null @@ -1,110 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package catalogv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for HealthStatus -func (this *HealthStatus) MarshalJSON() ([]byte, error) { - str, err := HealthMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HealthStatus -func (this *HealthStatus) UnmarshalJSON(b []byte) error { - return HealthUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HealthChecks -func (this *HealthChecks) MarshalJSON() ([]byte, error) { - str, err := HealthMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HealthChecks -func (this *HealthChecks) UnmarshalJSON(b []byte) error { - return HealthUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HealthCheck -func (this *HealthCheck) MarshalJSON() ([]byte, error) { - str, err := HealthMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HealthCheck -func (this *HealthCheck) UnmarshalJSON(b []byte) error { - return HealthUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HTTPCheck -func (this *HTTPCheck) MarshalJSON() ([]byte, error) { - str, err := HealthMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPCheck -func (this *HTTPCheck) UnmarshalJSON(b []byte) error { - return HealthUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for TCPCheck -func (this *TCPCheck) MarshalJSON() ([]byte, error) { - str, err := HealthMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TCPCheck -func (this *TCPCheck) UnmarshalJSON(b []byte) error { - return HealthUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for UDPCheck -func (this *UDPCheck) MarshalJSON() ([]byte, error) { - str, err := HealthMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for UDPCheck -func (this *UDPCheck) UnmarshalJSON(b []byte) error { - return HealthUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for GRPCCheck -func (this *GRPCCheck) MarshalJSON() ([]byte, error) { - str, err := HealthMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for GRPCCheck -func (this *GRPCCheck) UnmarshalJSON(b []byte) error { - return HealthUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for OSServiceCheck -func (this *OSServiceCheck) MarshalJSON() ([]byte, error) { - str, err := HealthMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for OSServiceCheck -func (this *OSServiceCheck) UnmarshalJSON(b []byte) error { - return HealthUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for CheckTLSConfig -func (this *CheckTLSConfig) MarshalJSON() ([]byte, error) { - str, err := HealthMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for CheckTLSConfig -func (this *CheckTLSConfig) UnmarshalJSON(b []byte) error { - return HealthUnmarshaler.Unmarshal(b, this) -} - -var ( - HealthMarshaler = &protojson.MarshalOptions{} - HealthUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbcatalog/v2beta1/node.pb.binary.go b/proto-public/pbcatalog/v2beta1/node.pb.binary.go deleted file mode 100644 index 984bc57b71d0..000000000000 --- a/proto-public/pbcatalog/v2beta1/node.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbcatalog/v2beta1/node.proto - -package catalogv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Node) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Node) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *NodeAddress) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *NodeAddress) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbcatalog/v2beta1/node.pb.go b/proto-public/pbcatalog/v2beta1/node.pb.go deleted file mode 100644 index fc6d57f7fc22..000000000000 --- a/proto-public/pbcatalog/v2beta1/node.pb.go +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbcatalog/v2beta1/node.proto - -package catalogv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Node struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Addresses []*NodeAddress `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"` -} - -func (x *Node) Reset() { - *x = Node{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_node_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Node) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Node) ProtoMessage() {} - -func (x *Node) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_node_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Node.ProtoReflect.Descriptor instead. -func (*Node) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_node_proto_rawDescGZIP(), []int{0} -} - -func (x *Node) GetAddresses() []*NodeAddress { - if x != nil { - return x.Addresses - } - return nil -} - -type NodeAddress struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // host can be an IP or DNS name.Í - Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` - // external indicates whether this address should be used for external communication - // (aka a WAN address). - External bool `protobuf:"varint,3,opt,name=external,proto3" json:"external,omitempty"` -} - -func (x *NodeAddress) Reset() { - *x = NodeAddress{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_node_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NodeAddress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NodeAddress) ProtoMessage() {} - -func (x *NodeAddress) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_node_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NodeAddress.ProtoReflect.Descriptor instead. -func (*NodeAddress) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_node_proto_rawDescGZIP(), []int{1} -} - -func (x *NodeAddress) GetHost() string { - if x != nil { - return x.Host - } - return "" -} - -func (x *NodeAddress) GetExternal() bool { - if x != nil { - return x.External - } - return false -} - -var File_pbcatalog_v2beta1_node_proto protoreflect.FileDescriptor - -var file_pbcatalog_v2beta1_node_proto_rawDesc = []byte{ - 0x0a, 0x1c, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5b, - 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x4b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4e, 0x6f, 0x64, - 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x65, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0x3d, 0x0a, 0x0b, 0x4e, - 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, - 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x1a, - 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x42, 0x9f, 0x02, 0x0a, 0x24, 0x63, - 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x42, 0x09, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, - 0x43, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x43, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbcatalog_v2beta1_node_proto_rawDescOnce sync.Once - file_pbcatalog_v2beta1_node_proto_rawDescData = file_pbcatalog_v2beta1_node_proto_rawDesc -) - -func file_pbcatalog_v2beta1_node_proto_rawDescGZIP() []byte { - file_pbcatalog_v2beta1_node_proto_rawDescOnce.Do(func() { - file_pbcatalog_v2beta1_node_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbcatalog_v2beta1_node_proto_rawDescData) - }) - return file_pbcatalog_v2beta1_node_proto_rawDescData -} - -var file_pbcatalog_v2beta1_node_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbcatalog_v2beta1_node_proto_goTypes = []interface{}{ - (*Node)(nil), // 0: hashicorp.consul.catalog.v2beta1.Node - (*NodeAddress)(nil), // 1: hashicorp.consul.catalog.v2beta1.NodeAddress -} -var file_pbcatalog_v2beta1_node_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.catalog.v2beta1.Node.addresses:type_name -> hashicorp.consul.catalog.v2beta1.NodeAddress - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_pbcatalog_v2beta1_node_proto_init() } -func file_pbcatalog_v2beta1_node_proto_init() { - if File_pbcatalog_v2beta1_node_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbcatalog_v2beta1_node_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Node); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_node_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NodeAddress); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbcatalog_v2beta1_node_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbcatalog_v2beta1_node_proto_goTypes, - DependencyIndexes: file_pbcatalog_v2beta1_node_proto_depIdxs, - MessageInfos: file_pbcatalog_v2beta1_node_proto_msgTypes, - }.Build() - File_pbcatalog_v2beta1_node_proto = out.File - file_pbcatalog_v2beta1_node_proto_rawDesc = nil - file_pbcatalog_v2beta1_node_proto_goTypes = nil - file_pbcatalog_v2beta1_node_proto_depIdxs = nil -} diff --git a/proto-public/pbcatalog/v2beta1/node.proto b/proto-public/pbcatalog/v2beta1/node.proto deleted file mode 100644 index 99c54ae48b74..000000000000 --- a/proto-public/pbcatalog/v2beta1/node.proto +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.catalog.v2beta1; - -import "pbresource/annotations.proto"; - -message Node { - option (hashicorp.consul.resource.spec) = { - // TODO: This should eventually be SCOPE_PARTITION but that will require further changes to code - scope: SCOPE_NAMESPACE, - }; - - repeated NodeAddress addresses = 1; -} - -message NodeAddress { - // host can be an IP or DNS name.Í - string host = 1; - - // external indicates whether this address should be used for external communication - // (aka a WAN address). - bool external = 3; -} diff --git a/proto-public/pbcatalog/v2beta1/node_deepcopy.gen.go b/proto-public/pbcatalog/v2beta1/node_deepcopy.gen.go deleted file mode 100644 index d864f7858fe6..000000000000 --- a/proto-public/pbcatalog/v2beta1/node_deepcopy.gen.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package catalogv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using Node within kubernetes types, where deepcopy-gen is used. -func (in *Node) DeepCopyInto(out *Node) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Node. Required by controller-gen. -func (in *Node) DeepCopy() *Node { - if in == nil { - return nil - } - out := new(Node) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Node. Required by controller-gen. -func (in *Node) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using NodeAddress within kubernetes types, where deepcopy-gen is used. -func (in *NodeAddress) DeepCopyInto(out *NodeAddress) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeAddress. Required by controller-gen. -func (in *NodeAddress) DeepCopy() *NodeAddress { - if in == nil { - return nil - } - out := new(NodeAddress) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new NodeAddress. Required by controller-gen. -func (in *NodeAddress) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbcatalog/v2beta1/node_json.gen.go b/proto-public/pbcatalog/v2beta1/node_json.gen.go deleted file mode 100644 index f599ddb50164..000000000000 --- a/proto-public/pbcatalog/v2beta1/node_json.gen.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package catalogv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for Node -func (this *Node) MarshalJSON() ([]byte, error) { - str, err := NodeMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Node -func (this *Node) UnmarshalJSON(b []byte) error { - return NodeUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for NodeAddress -func (this *NodeAddress) MarshalJSON() ([]byte, error) { - str, err := NodeMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for NodeAddress -func (this *NodeAddress) UnmarshalJSON(b []byte) error { - return NodeUnmarshaler.Unmarshal(b, this) -} - -var ( - NodeMarshaler = &protojson.MarshalOptions{} - NodeUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbcatalog/v2beta1/protocol.pb.go b/proto-public/pbcatalog/v2beta1/protocol.pb.go deleted file mode 100644 index a1bdc899d92c..000000000000 --- a/proto-public/pbcatalog/v2beta1/protocol.pb.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbcatalog/v2beta1/protocol.proto - -package catalogv2beta1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=PROTOCOL_UNSPECIFIED;PROTOCOL_TCP;PROTOCOL_HTTP;PROTOCOL_HTTP2;PROTOCOL_GRPC -// +kubebuilder:validation:Type=string -type Protocol int32 - -const ( - Protocol_PROTOCOL_UNSPECIFIED Protocol = 0 - Protocol_PROTOCOL_TCP Protocol = 1 - Protocol_PROTOCOL_HTTP Protocol = 2 - Protocol_PROTOCOL_HTTP2 Protocol = 3 - Protocol_PROTOCOL_GRPC Protocol = 4 - // Protocol Mesh indicates that this port can speak Consul's mTLS based mesh protocol. - Protocol_PROTOCOL_MESH Protocol = 5 -) - -// Enum value maps for Protocol. -var ( - Protocol_name = map[int32]string{ - 0: "PROTOCOL_UNSPECIFIED", - 1: "PROTOCOL_TCP", - 2: "PROTOCOL_HTTP", - 3: "PROTOCOL_HTTP2", - 4: "PROTOCOL_GRPC", - 5: "PROTOCOL_MESH", - } - Protocol_value = map[string]int32{ - "PROTOCOL_UNSPECIFIED": 0, - "PROTOCOL_TCP": 1, - "PROTOCOL_HTTP": 2, - "PROTOCOL_HTTP2": 3, - "PROTOCOL_GRPC": 4, - "PROTOCOL_MESH": 5, - } -) - -func (x Protocol) Enum() *Protocol { - p := new(Protocol) - *p = x - return p -} - -func (x Protocol) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Protocol) Descriptor() protoreflect.EnumDescriptor { - return file_pbcatalog_v2beta1_protocol_proto_enumTypes[0].Descriptor() -} - -func (Protocol) Type() protoreflect.EnumType { - return &file_pbcatalog_v2beta1_protocol_proto_enumTypes[0] -} - -func (x Protocol) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Protocol.Descriptor instead. -func (Protocol) EnumDescriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_protocol_proto_rawDescGZIP(), []int{0} -} - -var File_pbcatalog_v2beta1_protocol_proto protoreflect.FileDescriptor - -var file_pbcatalog_v2beta1_protocol_proto_rawDesc = []byte{ - 0x0a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2a, 0x83, 0x01, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x50, - 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x01, 0x12, 0x11, 0x0a, - 0x0d, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x10, 0x02, - 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, - 0x50, 0x32, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, - 0x5f, 0x47, 0x52, 0x50, 0x43, 0x10, 0x04, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x54, 0x4f, - 0x43, 0x4f, 0x4c, 0x5f, 0x4d, 0x45, 0x53, 0x48, 0x10, 0x05, 0x42, 0xa3, 0x02, 0x0a, 0x24, 0x63, - 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x42, 0x0d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, - 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x3b, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, - 0x02, 0x03, 0x48, 0x43, 0x43, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2c, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, - 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, - 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbcatalog_v2beta1_protocol_proto_rawDescOnce sync.Once - file_pbcatalog_v2beta1_protocol_proto_rawDescData = file_pbcatalog_v2beta1_protocol_proto_rawDesc -) - -func file_pbcatalog_v2beta1_protocol_proto_rawDescGZIP() []byte { - file_pbcatalog_v2beta1_protocol_proto_rawDescOnce.Do(func() { - file_pbcatalog_v2beta1_protocol_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbcatalog_v2beta1_protocol_proto_rawDescData) - }) - return file_pbcatalog_v2beta1_protocol_proto_rawDescData -} - -var file_pbcatalog_v2beta1_protocol_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbcatalog_v2beta1_protocol_proto_goTypes = []interface{}{ - (Protocol)(0), // 0: hashicorp.consul.catalog.v2beta1.Protocol -} -var file_pbcatalog_v2beta1_protocol_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbcatalog_v2beta1_protocol_proto_init() } -func file_pbcatalog_v2beta1_protocol_proto_init() { - if File_pbcatalog_v2beta1_protocol_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbcatalog_v2beta1_protocol_proto_rawDesc, - NumEnums: 1, - NumMessages: 0, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbcatalog_v2beta1_protocol_proto_goTypes, - DependencyIndexes: file_pbcatalog_v2beta1_protocol_proto_depIdxs, - EnumInfos: file_pbcatalog_v2beta1_protocol_proto_enumTypes, - }.Build() - File_pbcatalog_v2beta1_protocol_proto = out.File - file_pbcatalog_v2beta1_protocol_proto_rawDesc = nil - file_pbcatalog_v2beta1_protocol_proto_goTypes = nil - file_pbcatalog_v2beta1_protocol_proto_depIdxs = nil -} diff --git a/proto-public/pbcatalog/v2beta1/protocol.proto b/proto-public/pbcatalog/v2beta1/protocol.proto deleted file mode 100644 index faebe9f0b040..000000000000 --- a/proto-public/pbcatalog/v2beta1/protocol.proto +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.catalog.v2beta1; - -// +kubebuilder:validation:Enum=PROTOCOL_UNSPECIFIED;PROTOCOL_TCP;PROTOCOL_HTTP;PROTOCOL_HTTP2;PROTOCOL_GRPC -// +kubebuilder:validation:Type=string -enum Protocol { - PROTOCOL_UNSPECIFIED = 0; - PROTOCOL_TCP = 1; - PROTOCOL_HTTP = 2; - PROTOCOL_HTTP2 = 3; - PROTOCOL_GRPC = 4; - - // Protocol Mesh indicates that this port can speak Consul's mTLS based mesh protocol. - PROTOCOL_MESH = 5; -} diff --git a/proto-public/pbcatalog/v2beta1/resource_types.gen.go b/proto-public/pbcatalog/v2beta1/resource_types.gen.go deleted file mode 100644 index c71a38ac70cd..000000000000 --- a/proto-public/pbcatalog/v2beta1/resource_types.gen.go +++ /dev/null @@ -1,78 +0,0 @@ -// Code generated by protoc-gen-resource-types. DO NOT EDIT. - -package catalogv2beta1 - -import ( - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - GroupName = "catalog" - Version = "v2beta1" - - DNSPolicyKind = "DNSPolicy" - FailoverPolicyKind = "FailoverPolicy" - HealthChecksKind = "HealthChecks" - HealthStatusKind = "HealthStatus" - NodeKind = "Node" - ServiceKind = "Service" - ServiceEndpointsKind = "ServiceEndpoints" - VirtualIPsKind = "VirtualIPs" - WorkloadKind = "Workload" -) - -var ( - DNSPolicyType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: DNSPolicyKind, - } - - FailoverPolicyType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: FailoverPolicyKind, - } - - HealthChecksType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: HealthChecksKind, - } - - HealthStatusType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: HealthStatusKind, - } - - NodeType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: NodeKind, - } - - ServiceType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: ServiceKind, - } - - ServiceEndpointsType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: ServiceEndpointsKind, - } - - VirtualIPsType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: VirtualIPsKind, - } - - WorkloadType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: WorkloadKind, - } -) diff --git a/proto-public/pbcatalog/v2beta1/selector.pb.binary.go b/proto-public/pbcatalog/v2beta1/selector.pb.binary.go deleted file mode 100644 index cb55c9be5be6..000000000000 --- a/proto-public/pbcatalog/v2beta1/selector.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbcatalog/v2beta1/selector.proto - -package catalogv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *WorkloadSelector) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *WorkloadSelector) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbcatalog/v2beta1/selector.pb.go b/proto-public/pbcatalog/v2beta1/selector.pb.go deleted file mode 100644 index be51858d72c6..000000000000 --- a/proto-public/pbcatalog/v2beta1/selector.pb.go +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbcatalog/v2beta1/selector.proto - -package catalogv2beta1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// WorkloadSelector represents criteria for selecting a subset of workloads. -type WorkloadSelector struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Prefixes []string `protobuf:"bytes,1,rep,name=prefixes,proto3" json:"prefixes,omitempty"` - Names []string `protobuf:"bytes,2,rep,name=names,proto3" json:"names,omitempty"` - Filter string `protobuf:"bytes,3,opt,name=filter,proto3" json:"filter,omitempty"` -} - -func (x *WorkloadSelector) Reset() { - *x = WorkloadSelector{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_selector_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WorkloadSelector) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WorkloadSelector) ProtoMessage() {} - -func (x *WorkloadSelector) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_selector_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WorkloadSelector.ProtoReflect.Descriptor instead. -func (*WorkloadSelector) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_selector_proto_rawDescGZIP(), []int{0} -} - -func (x *WorkloadSelector) GetPrefixes() []string { - if x != nil { - return x.Prefixes - } - return nil -} - -func (x *WorkloadSelector) GetNames() []string { - if x != nil { - return x.Names - } - return nil -} - -func (x *WorkloadSelector) GetFilter() string { - if x != nil { - return x.Filter - } - return "" -} - -var File_pbcatalog_v2beta1_selector_proto protoreflect.FileDescriptor - -var file_pbcatalog_v2beta1_selector_proto_rawDesc = []byte{ - 0x0a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x22, 0x5c, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, - 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x42, 0xa3, 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0d, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x43, 0xaa, 0x02, 0x20, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, 0x56, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x3a, - 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbcatalog_v2beta1_selector_proto_rawDescOnce sync.Once - file_pbcatalog_v2beta1_selector_proto_rawDescData = file_pbcatalog_v2beta1_selector_proto_rawDesc -) - -func file_pbcatalog_v2beta1_selector_proto_rawDescGZIP() []byte { - file_pbcatalog_v2beta1_selector_proto_rawDescOnce.Do(func() { - file_pbcatalog_v2beta1_selector_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbcatalog_v2beta1_selector_proto_rawDescData) - }) - return file_pbcatalog_v2beta1_selector_proto_rawDescData -} - -var file_pbcatalog_v2beta1_selector_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbcatalog_v2beta1_selector_proto_goTypes = []interface{}{ - (*WorkloadSelector)(nil), // 0: hashicorp.consul.catalog.v2beta1.WorkloadSelector -} -var file_pbcatalog_v2beta1_selector_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbcatalog_v2beta1_selector_proto_init() } -func file_pbcatalog_v2beta1_selector_proto_init() { - if File_pbcatalog_v2beta1_selector_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbcatalog_v2beta1_selector_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkloadSelector); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbcatalog_v2beta1_selector_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbcatalog_v2beta1_selector_proto_goTypes, - DependencyIndexes: file_pbcatalog_v2beta1_selector_proto_depIdxs, - MessageInfos: file_pbcatalog_v2beta1_selector_proto_msgTypes, - }.Build() - File_pbcatalog_v2beta1_selector_proto = out.File - file_pbcatalog_v2beta1_selector_proto_rawDesc = nil - file_pbcatalog_v2beta1_selector_proto_goTypes = nil - file_pbcatalog_v2beta1_selector_proto_depIdxs = nil -} diff --git a/proto-public/pbcatalog/v2beta1/selector.proto b/proto-public/pbcatalog/v2beta1/selector.proto deleted file mode 100644 index 6786e7faf986..000000000000 --- a/proto-public/pbcatalog/v2beta1/selector.proto +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.catalog.v2beta1; - -// WorkloadSelector represents criteria for selecting a subset of workloads. -message WorkloadSelector { - repeated string prefixes = 1; - repeated string names = 2; - string filter = 3; -} diff --git a/proto-public/pbcatalog/v2beta1/selector_deepcopy.gen.go b/proto-public/pbcatalog/v2beta1/selector_deepcopy.gen.go deleted file mode 100644 index 7e59d5588081..000000000000 --- a/proto-public/pbcatalog/v2beta1/selector_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package catalogv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using WorkloadSelector within kubernetes types, where deepcopy-gen is used. -func (in *WorkloadSelector) DeepCopyInto(out *WorkloadSelector) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadSelector. Required by controller-gen. -func (in *WorkloadSelector) DeepCopy() *WorkloadSelector { - if in == nil { - return nil - } - out := new(WorkloadSelector) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadSelector. Required by controller-gen. -func (in *WorkloadSelector) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbcatalog/v2beta1/selector_json.gen.go b/proto-public/pbcatalog/v2beta1/selector_json.gen.go deleted file mode 100644 index 047e8d4c96dc..000000000000 --- a/proto-public/pbcatalog/v2beta1/selector_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package catalogv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for WorkloadSelector -func (this *WorkloadSelector) MarshalJSON() ([]byte, error) { - str, err := SelectorMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for WorkloadSelector -func (this *WorkloadSelector) UnmarshalJSON(b []byte) error { - return SelectorUnmarshaler.Unmarshal(b, this) -} - -var ( - SelectorMarshaler = &protojson.MarshalOptions{} - SelectorUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbcatalog/v2beta1/service.pb.binary.go b/proto-public/pbcatalog/v2beta1/service.pb.binary.go deleted file mode 100644 index a017a7bf3721..000000000000 --- a/proto-public/pbcatalog/v2beta1/service.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbcatalog/v2beta1/service.proto - -package catalogv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Service) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Service) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ServicePort) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ServicePort) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbcatalog/v2beta1/service.pb.go b/proto-public/pbcatalog/v2beta1/service.pb.go deleted file mode 100644 index 99d51a9783b5..000000000000 --- a/proto-public/pbcatalog/v2beta1/service.pb.go +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbcatalog/v2beta1/service.proto - -package catalogv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Service struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // workloads is a selector for the workloads this service should represent. - Workloads *WorkloadSelector `protobuf:"bytes,1,opt,name=workloads,proto3" json:"workloads,omitempty"` - // ports is the list of mappings of workload ports that this service - // represents. - Ports []*ServicePort `protobuf:"bytes,2,rep,name=ports,proto3" json:"ports,omitempty"` - // virtual_ips is a list of virtual IPs for this service. This is useful when you need to set - // an IP from an external system (like Kubernetes). This can be an IPv4 or IPv6 string. - VirtualIps []string `protobuf:"bytes,3,rep,name=virtual_ips,json=virtualIps,proto3" json:"virtual_ips,omitempty"` -} - -func (x *Service) Reset() { - *x = Service{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Service) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Service) ProtoMessage() {} - -func (x *Service) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Service.ProtoReflect.Descriptor instead. -func (*Service) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_service_proto_rawDescGZIP(), []int{0} -} - -func (x *Service) GetWorkloads() *WorkloadSelector { - if x != nil { - return x.Workloads - } - return nil -} - -func (x *Service) GetPorts() []*ServicePort { - if x != nil { - return x.Ports - } - return nil -} - -func (x *Service) GetVirtualIps() []string { - if x != nil { - return x.VirtualIps - } - return nil -} - -type ServicePort struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // virtual_port is the port that could only be used when transparent - // proxy is used alongside a virtual IP or a virtual DNS address. - // This value is ignored in other cases. Whether or not using transparent - // proxy, this value is optional. - VirtualPort uint32 `protobuf:"varint,1,opt,name=virtual_port,json=virtualPort,proto3" json:"virtual_port,omitempty"` - // target_port is the name of the workload port. - TargetPort string `protobuf:"bytes,2,opt,name=target_port,json=targetPort,proto3" json:"target_port,omitempty"` - // protocol is the port's protocol. This should be set to "mesh" - // if the target port is the proxy's inbound port. - Protocol Protocol `protobuf:"varint,3,opt,name=protocol,proto3,enum=hashicorp.consul.catalog.v2beta1.Protocol" json:"protocol,omitempty"` -} - -func (x *ServicePort) Reset() { - *x = ServicePort{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ServicePort) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ServicePort) ProtoMessage() {} - -func (x *ServicePort) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ServicePort.ProtoReflect.Descriptor instead. -func (*ServicePort) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_service_proto_rawDescGZIP(), []int{1} -} - -func (x *ServicePort) GetVirtualPort() uint32 { - if x != nil { - return x.VirtualPort - } - return 0 -} - -func (x *ServicePort) GetTargetPort() string { - if x != nil { - return x.TargetPort - } - return "" -} - -func (x *ServicePort) GetProtocol() Protocol { - if x != nil { - return x.Protocol - } - return Protocol_PROTOCOL_UNSPECIFIED -} - -var File_pbcatalog_v2beta1_service_proto protoreflect.FileDescriptor - -var file_pbcatalog_v2beta1_service_proto_rawDesc = []byte{ - 0x0a, 0x1f, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x1a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc9, 0x01, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x50, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, - 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, - 0x61, 0x64, 0x73, 0x12, 0x43, 0x0a, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, - 0x74, 0x52, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x69, 0x72, 0x74, - 0x75, 0x61, 0x6c, 0x5f, 0x69, 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x76, - 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x49, 0x70, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, - 0x03, 0x22, 0x99, 0x01, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, - 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x72, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, - 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x70, - 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x46, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x42, 0xa2, 0x02, - 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x2f, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x43, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, - 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2c, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x3a, 0x3a, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbcatalog_v2beta1_service_proto_rawDescOnce sync.Once - file_pbcatalog_v2beta1_service_proto_rawDescData = file_pbcatalog_v2beta1_service_proto_rawDesc -) - -func file_pbcatalog_v2beta1_service_proto_rawDescGZIP() []byte { - file_pbcatalog_v2beta1_service_proto_rawDescOnce.Do(func() { - file_pbcatalog_v2beta1_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbcatalog_v2beta1_service_proto_rawDescData) - }) - return file_pbcatalog_v2beta1_service_proto_rawDescData -} - -var file_pbcatalog_v2beta1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbcatalog_v2beta1_service_proto_goTypes = []interface{}{ - (*Service)(nil), // 0: hashicorp.consul.catalog.v2beta1.Service - (*ServicePort)(nil), // 1: hashicorp.consul.catalog.v2beta1.ServicePort - (*WorkloadSelector)(nil), // 2: hashicorp.consul.catalog.v2beta1.WorkloadSelector - (Protocol)(0), // 3: hashicorp.consul.catalog.v2beta1.Protocol -} -var file_pbcatalog_v2beta1_service_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.catalog.v2beta1.Service.workloads:type_name -> hashicorp.consul.catalog.v2beta1.WorkloadSelector - 1, // 1: hashicorp.consul.catalog.v2beta1.Service.ports:type_name -> hashicorp.consul.catalog.v2beta1.ServicePort - 3, // 2: hashicorp.consul.catalog.v2beta1.ServicePort.protocol:type_name -> hashicorp.consul.catalog.v2beta1.Protocol - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_pbcatalog_v2beta1_service_proto_init() } -func file_pbcatalog_v2beta1_service_proto_init() { - if File_pbcatalog_v2beta1_service_proto != nil { - return - } - file_pbcatalog_v2beta1_protocol_proto_init() - file_pbcatalog_v2beta1_selector_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbcatalog_v2beta1_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Service); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServicePort); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbcatalog_v2beta1_service_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbcatalog_v2beta1_service_proto_goTypes, - DependencyIndexes: file_pbcatalog_v2beta1_service_proto_depIdxs, - MessageInfos: file_pbcatalog_v2beta1_service_proto_msgTypes, - }.Build() - File_pbcatalog_v2beta1_service_proto = out.File - file_pbcatalog_v2beta1_service_proto_rawDesc = nil - file_pbcatalog_v2beta1_service_proto_goTypes = nil - file_pbcatalog_v2beta1_service_proto_depIdxs = nil -} diff --git a/proto-public/pbcatalog/v2beta1/service.proto b/proto-public/pbcatalog/v2beta1/service.proto deleted file mode 100644 index fd03768b907f..000000000000 --- a/proto-public/pbcatalog/v2beta1/service.proto +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.catalog.v2beta1; - -import "pbcatalog/v2beta1/protocol.proto"; -import "pbcatalog/v2beta1/selector.proto"; -import "pbresource/annotations.proto"; - -message Service { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // workloads is a selector for the workloads this service should represent. - WorkloadSelector workloads = 1; - // ports is the list of mappings of workload ports that this service - // represents. - repeated ServicePort ports = 2; - - // virtual_ips is a list of virtual IPs for this service. This is useful when you need to set - // an IP from an external system (like Kubernetes). This can be an IPv4 or IPv6 string. - repeated string virtual_ips = 3; -} - -message ServicePort { - // virtual_port is the port that could only be used when transparent - // proxy is used alongside a virtual IP or a virtual DNS address. - // This value is ignored in other cases. Whether or not using transparent - // proxy, this value is optional. - uint32 virtual_port = 1; - - // target_port is the name of the workload port. - string target_port = 2; - - // protocol is the port's protocol. This should be set to "mesh" - // if the target port is the proxy's inbound port. - Protocol protocol = 3; -} diff --git a/proto-public/pbcatalog/v2beta1/service_addon.go b/proto-public/pbcatalog/v2beta1/service_addon.go deleted file mode 100644 index 9f19296cc5f6..000000000000 --- a/proto-public/pbcatalog/v2beta1/service_addon.go +++ /dev/null @@ -1,19 +0,0 @@ -package catalogv2beta1 - -func (s *Service) IsMeshEnabled() bool { - for _, port := range s.GetPorts() { - if port.Protocol == Protocol_PROTOCOL_MESH { - return true - } - } - return false -} - -func (s *Service) FindServicePort(name string) *ServicePort { - for _, port := range s.GetPorts() { - if port.TargetPort == name { - return port - } - } - return nil -} diff --git a/proto-public/pbcatalog/v2beta1/service_addon_test.go b/proto-public/pbcatalog/v2beta1/service_addon_test.go deleted file mode 100644 index 19c07a5901aa..000000000000 --- a/proto-public/pbcatalog/v2beta1/service_addon_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package catalogv2beta1 - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestServiceIsMeshEnabled(t *testing.T) { - cases := map[string]struct { - service *Service - exp bool - }{ - "nil": {service: nil, exp: false}, - "no ports": { - service: &Service{}, - exp: false, - }, - "no mesh ports": { - service: &Service{ - Ports: []*ServicePort{ - { - TargetPort: "foo", - Protocol: Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "bar", - Protocol: Protocol_PROTOCOL_TCP, - }, - }, - }, - exp: false, - }, - "with mesh ports": { - service: &Service{ - Ports: []*ServicePort{ - { - TargetPort: "foo", - Protocol: Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "bar", - Protocol: Protocol_PROTOCOL_TCP, - }, - { - TargetPort: "baz", - Protocol: Protocol_PROTOCOL_MESH, - }, - }, - }, - exp: true, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - require.Equal(t, c.exp, c.service.IsMeshEnabled()) - }) - } -} - -func TestFindServicePort(t *testing.T) { - cases := map[string]struct { - service *Service - port string - exp *ServicePort - }{ - "nil": {service: nil, port: "foo", exp: nil}, - "no ports": { - service: &Service{}, - port: "foo", - exp: nil, - }, - "non-existing port": { - service: &Service{ - Ports: []*ServicePort{ - { - TargetPort: "foo", - Protocol: Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "bar", - Protocol: Protocol_PROTOCOL_TCP, - }, - }, - }, - port: "not-found", - exp: nil, - }, - "existing port": { - service: &Service{ - Ports: []*ServicePort{ - { - TargetPort: "foo", - Protocol: Protocol_PROTOCOL_HTTP, - }, - { - TargetPort: "bar", - Protocol: Protocol_PROTOCOL_TCP, - }, - { - TargetPort: "baz", - Protocol: Protocol_PROTOCOL_MESH, - }, - }, - }, - port: "bar", - exp: &ServicePort{ - TargetPort: "bar", - Protocol: Protocol_PROTOCOL_TCP, - }, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - require.Equal(t, c.exp, c.service.FindServicePort(c.port)) - }) - } -} diff --git a/proto-public/pbcatalog/v2beta1/service_deepcopy.gen.go b/proto-public/pbcatalog/v2beta1/service_deepcopy.gen.go deleted file mode 100644 index fa578cc34464..000000000000 --- a/proto-public/pbcatalog/v2beta1/service_deepcopy.gen.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package catalogv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using Service within kubernetes types, where deepcopy-gen is used. -func (in *Service) DeepCopyInto(out *Service) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Service. Required by controller-gen. -func (in *Service) DeepCopy() *Service { - if in == nil { - return nil - } - out := new(Service) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Service. Required by controller-gen. -func (in *Service) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ServicePort within kubernetes types, where deepcopy-gen is used. -func (in *ServicePort) DeepCopyInto(out *ServicePort) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePort. Required by controller-gen. -func (in *ServicePort) DeepCopy() *ServicePort { - if in == nil { - return nil - } - out := new(ServicePort) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ServicePort. Required by controller-gen. -func (in *ServicePort) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbcatalog/v2beta1/service_endpoints.pb.binary.go b/proto-public/pbcatalog/v2beta1/service_endpoints.pb.binary.go deleted file mode 100644 index 1e5fd4a834cd..000000000000 --- a/proto-public/pbcatalog/v2beta1/service_endpoints.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbcatalog/v2beta1/service_endpoints.proto - -package catalogv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ServiceEndpoints) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ServiceEndpoints) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Endpoint) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Endpoint) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbcatalog/v2beta1/service_endpoints.pb.go b/proto-public/pbcatalog/v2beta1/service_endpoints.pb.go deleted file mode 100644 index fe98e95b2f27..000000000000 --- a/proto-public/pbcatalog/v2beta1/service_endpoints.pb.go +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbcatalog/v2beta1/service_endpoints.proto - -package catalogv2beta1 - -import ( - pbresource "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ServiceEndpoints struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Endpoints []*Endpoint `protobuf:"bytes,1,rep,name=endpoints,proto3" json:"endpoints,omitempty"` -} - -func (x *ServiceEndpoints) Reset() { - *x = ServiceEndpoints{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_service_endpoints_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ServiceEndpoints) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ServiceEndpoints) ProtoMessage() {} - -func (x *ServiceEndpoints) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_service_endpoints_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ServiceEndpoints.ProtoReflect.Descriptor instead. -func (*ServiceEndpoints) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_service_endpoints_proto_rawDescGZIP(), []int{0} -} - -func (x *ServiceEndpoints) GetEndpoints() []*Endpoint { - if x != nil { - return x.Endpoints - } - return nil -} - -type Endpoint struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // target_ref is the reference to the resource - // for this endpoint endpoint. This currently must be a workload. - TargetRef *pbresource.ID `protobuf:"bytes,1,opt,name=target_ref,json=targetRef,proto3" json:"target_ref,omitempty"` - // addresses is the list of addresses for this endpoint. - // This has the same structure as the workload addresses. - Addresses []*WorkloadAddress `protobuf:"bytes,2,rep,name=addresses,proto3" json:"addresses,omitempty"` - // ports is the map of ports for this endpoint. - // This has the same structure as the workload ports but - // will be filtered to just the ports selected by the service. - Ports map[string]*WorkloadPort `protobuf:"bytes,3,rep,name=ports,proto3" json:"ports,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // health_status is the aggregated health status of this endpoint. - HealthStatus Health `protobuf:"varint,4,opt,name=health_status,json=healthStatus,proto3,enum=hashicorp.consul.catalog.v2beta1.Health" json:"health_status,omitempty"` - // identity is the name of the workload identity for this endpoint. - Identity string `protobuf:"bytes,5,opt,name=identity,proto3" json:"identity,omitempty"` -} - -func (x *Endpoint) Reset() { - *x = Endpoint{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_service_endpoints_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Endpoint) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Endpoint) ProtoMessage() {} - -func (x *Endpoint) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_service_endpoints_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Endpoint.ProtoReflect.Descriptor instead. -func (*Endpoint) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_service_endpoints_proto_rawDescGZIP(), []int{1} -} - -func (x *Endpoint) GetTargetRef() *pbresource.ID { - if x != nil { - return x.TargetRef - } - return nil -} - -func (x *Endpoint) GetAddresses() []*WorkloadAddress { - if x != nil { - return x.Addresses - } - return nil -} - -func (x *Endpoint) GetPorts() map[string]*WorkloadPort { - if x != nil { - return x.Ports - } - return nil -} - -func (x *Endpoint) GetHealthStatus() Health { - if x != nil { - return x.HealthStatus - } - return Health_HEALTH_ANY -} - -func (x *Endpoint) GetIdentity() string { - if x != nil { - return x.Identity - } - return "" -} - -var File_pbcatalog_v2beta1_service_endpoints_proto protoreflect.FileDescriptor - -var file_pbcatalog_v2beta1_service_endpoints_proto_rawDesc = []byte{ - 0x0a, 0x29, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, - 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1e, 0x70, - 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, - 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x70, - 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x64, 0x0a, 0x10, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x48, 0x0a, 0x09, - 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x09, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0xbb, - 0x03, 0x0a, 0x08, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x3c, 0x0a, 0x0a, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, 0x09, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x66, 0x12, 0x4f, 0x0a, 0x09, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, - 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x05, 0x70, 0x6f, - 0x72, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x4d, 0x0a, 0x0d, 0x68, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x1a, 0x68, 0x0a, 0x0a, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x44, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x72, - 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0xab, 0x02, 0x0a, - 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x43, 0xaa, - 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, 0x56, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, - 0x67, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_pbcatalog_v2beta1_service_endpoints_proto_rawDescOnce sync.Once - file_pbcatalog_v2beta1_service_endpoints_proto_rawDescData = file_pbcatalog_v2beta1_service_endpoints_proto_rawDesc -) - -func file_pbcatalog_v2beta1_service_endpoints_proto_rawDescGZIP() []byte { - file_pbcatalog_v2beta1_service_endpoints_proto_rawDescOnce.Do(func() { - file_pbcatalog_v2beta1_service_endpoints_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbcatalog_v2beta1_service_endpoints_proto_rawDescData) - }) - return file_pbcatalog_v2beta1_service_endpoints_proto_rawDescData -} - -var file_pbcatalog_v2beta1_service_endpoints_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_pbcatalog_v2beta1_service_endpoints_proto_goTypes = []interface{}{ - (*ServiceEndpoints)(nil), // 0: hashicorp.consul.catalog.v2beta1.ServiceEndpoints - (*Endpoint)(nil), // 1: hashicorp.consul.catalog.v2beta1.Endpoint - nil, // 2: hashicorp.consul.catalog.v2beta1.Endpoint.PortsEntry - (*pbresource.ID)(nil), // 3: hashicorp.consul.resource.ID - (*WorkloadAddress)(nil), // 4: hashicorp.consul.catalog.v2beta1.WorkloadAddress - (Health)(0), // 5: hashicorp.consul.catalog.v2beta1.Health - (*WorkloadPort)(nil), // 6: hashicorp.consul.catalog.v2beta1.WorkloadPort -} -var file_pbcatalog_v2beta1_service_endpoints_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.catalog.v2beta1.ServiceEndpoints.endpoints:type_name -> hashicorp.consul.catalog.v2beta1.Endpoint - 3, // 1: hashicorp.consul.catalog.v2beta1.Endpoint.target_ref:type_name -> hashicorp.consul.resource.ID - 4, // 2: hashicorp.consul.catalog.v2beta1.Endpoint.addresses:type_name -> hashicorp.consul.catalog.v2beta1.WorkloadAddress - 2, // 3: hashicorp.consul.catalog.v2beta1.Endpoint.ports:type_name -> hashicorp.consul.catalog.v2beta1.Endpoint.PortsEntry - 5, // 4: hashicorp.consul.catalog.v2beta1.Endpoint.health_status:type_name -> hashicorp.consul.catalog.v2beta1.Health - 6, // 5: hashicorp.consul.catalog.v2beta1.Endpoint.PortsEntry.value:type_name -> hashicorp.consul.catalog.v2beta1.WorkloadPort - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name -} - -func init() { file_pbcatalog_v2beta1_service_endpoints_proto_init() } -func file_pbcatalog_v2beta1_service_endpoints_proto_init() { - if File_pbcatalog_v2beta1_service_endpoints_proto != nil { - return - } - file_pbcatalog_v2beta1_health_proto_init() - file_pbcatalog_v2beta1_workload_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbcatalog_v2beta1_service_endpoints_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceEndpoints); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_service_endpoints_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Endpoint); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbcatalog_v2beta1_service_endpoints_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbcatalog_v2beta1_service_endpoints_proto_goTypes, - DependencyIndexes: file_pbcatalog_v2beta1_service_endpoints_proto_depIdxs, - MessageInfos: file_pbcatalog_v2beta1_service_endpoints_proto_msgTypes, - }.Build() - File_pbcatalog_v2beta1_service_endpoints_proto = out.File - file_pbcatalog_v2beta1_service_endpoints_proto_rawDesc = nil - file_pbcatalog_v2beta1_service_endpoints_proto_goTypes = nil - file_pbcatalog_v2beta1_service_endpoints_proto_depIdxs = nil -} diff --git a/proto-public/pbcatalog/v2beta1/service_endpoints.proto b/proto-public/pbcatalog/v2beta1/service_endpoints.proto deleted file mode 100644 index cd205a001e40..000000000000 --- a/proto-public/pbcatalog/v2beta1/service_endpoints.proto +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.catalog.v2beta1; - -import "pbcatalog/v2beta1/health.proto"; -import "pbcatalog/v2beta1/workload.proto"; -import "pbresource/annotations.proto"; -import "pbresource/resource.proto"; - -message ServiceEndpoints { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - repeated Endpoint endpoints = 1; -} - -message Endpoint { - // target_ref is the reference to the resource - // for this endpoint endpoint. This currently must be a workload. - hashicorp.consul.resource.ID target_ref = 1; - - // addresses is the list of addresses for this endpoint. - // This has the same structure as the workload addresses. - repeated WorkloadAddress addresses = 2; - - // ports is the map of ports for this endpoint. - // This has the same structure as the workload ports but - // will be filtered to just the ports selected by the service. - map ports = 3; - - // health_status is the aggregated health status of this endpoint. - Health health_status = 4; - - // identity is the name of the workload identity for this endpoint. - string identity = 5; -} diff --git a/proto-public/pbcatalog/v2beta1/service_endpoints_addon.go b/proto-public/pbcatalog/v2beta1/service_endpoints_addon.go deleted file mode 100644 index bd55db6c8236..000000000000 --- a/proto-public/pbcatalog/v2beta1/service_endpoints_addon.go +++ /dev/null @@ -1,26 +0,0 @@ -package catalogv2beta1 - -import ( - "golang.org/x/exp/maps" - "golang.org/x/exp/slices" -) - -// GetIdentities returns a list of unique identities that this service endpoints points to. -func (s *ServiceEndpoints) GetIdentities() []string { - uniqueIdentities := make(map[string]struct{}) - - for _, ep := range s.GetEndpoints() { - if ep.GetIdentity() != "" { - uniqueIdentities[ep.GetIdentity()] = struct{}{} - } - } - - if len(uniqueIdentities) == 0 { - return nil - } - - identities := maps.Keys(uniqueIdentities) - slices.Sort(identities) - - return identities -} diff --git a/proto-public/pbcatalog/v2beta1/service_endpoints_addon_test.go b/proto-public/pbcatalog/v2beta1/service_endpoints_addon_test.go deleted file mode 100644 index 5d3c54786ea9..000000000000 --- a/proto-public/pbcatalog/v2beta1/service_endpoints_addon_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package catalogv2beta1 - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestServiceEndpoints_GetIdentities(t *testing.T) { - cases := map[string]struct { - endpoints []*Endpoint - expIdentities []string - }{ - "no endpoints": { - endpoints: nil, - expIdentities: nil, - }, - "no identities": { - endpoints: []*Endpoint{ - {}, - {}, - }, - expIdentities: nil, - }, - "single identity": { - endpoints: []*Endpoint{ - {Identity: "foo"}, - {Identity: "foo"}, - {Identity: "foo"}, - }, - expIdentities: []string{"foo"}, - }, - "multiple identities": { - endpoints: []*Endpoint{ - {Identity: "foo"}, - {Identity: "foo"}, - {Identity: "bar"}, - }, - expIdentities: []string{"bar", "foo"}, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - se := &ServiceEndpoints{Endpoints: c.endpoints} - require.Equal(t, c.expIdentities, se.GetIdentities()) - }) - } -} diff --git a/proto-public/pbcatalog/v2beta1/service_endpoints_deepcopy.gen.go b/proto-public/pbcatalog/v2beta1/service_endpoints_deepcopy.gen.go deleted file mode 100644 index f3634c091be7..000000000000 --- a/proto-public/pbcatalog/v2beta1/service_endpoints_deepcopy.gen.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package catalogv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ServiceEndpoints within kubernetes types, where deepcopy-gen is used. -func (in *ServiceEndpoints) DeepCopyInto(out *ServiceEndpoints) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceEndpoints. Required by controller-gen. -func (in *ServiceEndpoints) DeepCopy() *ServiceEndpoints { - if in == nil { - return nil - } - out := new(ServiceEndpoints) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ServiceEndpoints. Required by controller-gen. -func (in *ServiceEndpoints) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Endpoint within kubernetes types, where deepcopy-gen is used. -func (in *Endpoint) DeepCopyInto(out *Endpoint) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Endpoint. Required by controller-gen. -func (in *Endpoint) DeepCopy() *Endpoint { - if in == nil { - return nil - } - out := new(Endpoint) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Endpoint. Required by controller-gen. -func (in *Endpoint) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbcatalog/v2beta1/service_endpoints_json.gen.go b/proto-public/pbcatalog/v2beta1/service_endpoints_json.gen.go deleted file mode 100644 index 2eef380ae654..000000000000 --- a/proto-public/pbcatalog/v2beta1/service_endpoints_json.gen.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package catalogv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ServiceEndpoints -func (this *ServiceEndpoints) MarshalJSON() ([]byte, error) { - str, err := ServiceEndpointsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ServiceEndpoints -func (this *ServiceEndpoints) UnmarshalJSON(b []byte) error { - return ServiceEndpointsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Endpoint -func (this *Endpoint) MarshalJSON() ([]byte, error) { - str, err := ServiceEndpointsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Endpoint -func (this *Endpoint) UnmarshalJSON(b []byte) error { - return ServiceEndpointsUnmarshaler.Unmarshal(b, this) -} - -var ( - ServiceEndpointsMarshaler = &protojson.MarshalOptions{} - ServiceEndpointsUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbcatalog/v2beta1/service_json.gen.go b/proto-public/pbcatalog/v2beta1/service_json.gen.go deleted file mode 100644 index 6b9850f3a1f3..000000000000 --- a/proto-public/pbcatalog/v2beta1/service_json.gen.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package catalogv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for Service -func (this *Service) MarshalJSON() ([]byte, error) { - str, err := ServiceMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Service -func (this *Service) UnmarshalJSON(b []byte) error { - return ServiceUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ServicePort -func (this *ServicePort) MarshalJSON() ([]byte, error) { - str, err := ServiceMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ServicePort -func (this *ServicePort) UnmarshalJSON(b []byte) error { - return ServiceUnmarshaler.Unmarshal(b, this) -} - -var ( - ServiceMarshaler = &protojson.MarshalOptions{} - ServiceUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbcatalog/v2beta1/vip.pb.binary.go b/proto-public/pbcatalog/v2beta1/vip.pb.binary.go deleted file mode 100644 index 2702cdae21e0..000000000000 --- a/proto-public/pbcatalog/v2beta1/vip.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbcatalog/v2beta1/vip.proto - -package catalogv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *VirtualIPs) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *VirtualIPs) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *IP) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *IP) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbcatalog/v2beta1/vip.pb.go b/proto-public/pbcatalog/v2beta1/vip.pb.go deleted file mode 100644 index f0774f08b333..000000000000 --- a/proto-public/pbcatalog/v2beta1/vip.pb.go +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbcatalog/v2beta1/vip.proto - -package catalogv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type VirtualIPs struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Ips []*IP `protobuf:"bytes,1,rep,name=ips,proto3" json:"ips,omitempty"` -} - -func (x *VirtualIPs) Reset() { - *x = VirtualIPs{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_vip_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *VirtualIPs) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*VirtualIPs) ProtoMessage() {} - -func (x *VirtualIPs) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_vip_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use VirtualIPs.ProtoReflect.Descriptor instead. -func (*VirtualIPs) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_vip_proto_rawDescGZIP(), []int{0} -} - -func (x *VirtualIPs) GetIps() []*IP { - if x != nil { - return x.Ips - } - return nil -} - -type IP struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // address is the string IPv4 address. - // This could also store IPv6 in the future. - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` - // generated indicates whether Consul generated or it is user-provided - // (e.g. a ClusterIP of the Kubernetes service). - Generated bool `protobuf:"varint,2,opt,name=generated,proto3" json:"generated,omitempty"` -} - -func (x *IP) Reset() { - *x = IP{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_vip_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IP) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IP) ProtoMessage() {} - -func (x *IP) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_vip_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IP.ProtoReflect.Descriptor instead. -func (*IP) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_vip_proto_rawDescGZIP(), []int{1} -} - -func (x *IP) GetAddress() string { - if x != nil { - return x.Address - } - return "" -} - -func (x *IP) GetGenerated() bool { - if x != nil { - return x.Generated - } - return false -} - -var File_pbcatalog_v2beta1_vip_proto protoreflect.FileDescriptor - -var file_pbcatalog_v2beta1_vip_proto_rawDesc = []byte{ - 0x0a, 0x1b, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x76, 0x69, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, - 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4c, 0x0a, - 0x0a, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x49, 0x50, 0x73, 0x12, 0x36, 0x0a, 0x03, 0x69, - 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x50, 0x52, 0x03, - 0x69, 0x70, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0x3c, 0x0a, 0x02, 0x49, - 0x50, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x42, 0x9e, 0x02, 0x0a, 0x24, 0x63, 0x6f, - 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x42, 0x08, 0x56, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x43, 0xaa, - 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, 0x56, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, - 0x67, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_pbcatalog_v2beta1_vip_proto_rawDescOnce sync.Once - file_pbcatalog_v2beta1_vip_proto_rawDescData = file_pbcatalog_v2beta1_vip_proto_rawDesc -) - -func file_pbcatalog_v2beta1_vip_proto_rawDescGZIP() []byte { - file_pbcatalog_v2beta1_vip_proto_rawDescOnce.Do(func() { - file_pbcatalog_v2beta1_vip_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbcatalog_v2beta1_vip_proto_rawDescData) - }) - return file_pbcatalog_v2beta1_vip_proto_rawDescData -} - -var file_pbcatalog_v2beta1_vip_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbcatalog_v2beta1_vip_proto_goTypes = []interface{}{ - (*VirtualIPs)(nil), // 0: hashicorp.consul.catalog.v2beta1.VirtualIPs - (*IP)(nil), // 1: hashicorp.consul.catalog.v2beta1.IP -} -var file_pbcatalog_v2beta1_vip_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.catalog.v2beta1.VirtualIPs.ips:type_name -> hashicorp.consul.catalog.v2beta1.IP - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_pbcatalog_v2beta1_vip_proto_init() } -func file_pbcatalog_v2beta1_vip_proto_init() { - if File_pbcatalog_v2beta1_vip_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbcatalog_v2beta1_vip_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*VirtualIPs); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_vip_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IP); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbcatalog_v2beta1_vip_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbcatalog_v2beta1_vip_proto_goTypes, - DependencyIndexes: file_pbcatalog_v2beta1_vip_proto_depIdxs, - MessageInfos: file_pbcatalog_v2beta1_vip_proto_msgTypes, - }.Build() - File_pbcatalog_v2beta1_vip_proto = out.File - file_pbcatalog_v2beta1_vip_proto_rawDesc = nil - file_pbcatalog_v2beta1_vip_proto_goTypes = nil - file_pbcatalog_v2beta1_vip_proto_depIdxs = nil -} diff --git a/proto-public/pbcatalog/v2beta1/vip.proto b/proto-public/pbcatalog/v2beta1/vip.proto deleted file mode 100644 index 386ce58f16b9..000000000000 --- a/proto-public/pbcatalog/v2beta1/vip.proto +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.catalog.v2beta1; - -import "pbresource/annotations.proto"; - -message VirtualIPs { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - repeated IP ips = 1; -} - -message IP { - // address is the string IPv4 address. - // This could also store IPv6 in the future. - string address = 1; - - // generated indicates whether Consul generated or it is user-provided - // (e.g. a ClusterIP of the Kubernetes service). - bool generated = 2; -} diff --git a/proto-public/pbcatalog/v2beta1/vip_deepcopy.gen.go b/proto-public/pbcatalog/v2beta1/vip_deepcopy.gen.go deleted file mode 100644 index 8308240c52b0..000000000000 --- a/proto-public/pbcatalog/v2beta1/vip_deepcopy.gen.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package catalogv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using VirtualIPs within kubernetes types, where deepcopy-gen is used. -func (in *VirtualIPs) DeepCopyInto(out *VirtualIPs) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualIPs. Required by controller-gen. -func (in *VirtualIPs) DeepCopy() *VirtualIPs { - if in == nil { - return nil - } - out := new(VirtualIPs) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new VirtualIPs. Required by controller-gen. -func (in *VirtualIPs) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using IP within kubernetes types, where deepcopy-gen is used. -func (in *IP) DeepCopyInto(out *IP) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IP. Required by controller-gen. -func (in *IP) DeepCopy() *IP { - if in == nil { - return nil - } - out := new(IP) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new IP. Required by controller-gen. -func (in *IP) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbcatalog/v2beta1/vip_json.gen.go b/proto-public/pbcatalog/v2beta1/vip_json.gen.go deleted file mode 100644 index b464c310739b..000000000000 --- a/proto-public/pbcatalog/v2beta1/vip_json.gen.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package catalogv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for VirtualIPs -func (this *VirtualIPs) MarshalJSON() ([]byte, error) { - str, err := VipMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for VirtualIPs -func (this *VirtualIPs) UnmarshalJSON(b []byte) error { - return VipUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for IP -func (this *IP) MarshalJSON() ([]byte, error) { - str, err := VipMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for IP -func (this *IP) UnmarshalJSON(b []byte) error { - return VipUnmarshaler.Unmarshal(b, this) -} - -var ( - VipMarshaler = &protojson.MarshalOptions{} - VipUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbcatalog/v2beta1/workload.pb.binary.go b/proto-public/pbcatalog/v2beta1/workload.pb.binary.go deleted file mode 100644 index cb083b46e796..000000000000 --- a/proto-public/pbcatalog/v2beta1/workload.pb.binary.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbcatalog/v2beta1/workload.proto - -package catalogv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Workload) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Workload) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *WorkloadAddress) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *WorkloadAddress) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *WorkloadPort) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *WorkloadPort) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Locality) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Locality) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbcatalog/v2beta1/workload.pb.go b/proto-public/pbcatalog/v2beta1/workload.pb.go deleted file mode 100644 index fb2ffa773e46..000000000000 --- a/proto-public/pbcatalog/v2beta1/workload.pb.go +++ /dev/null @@ -1,523 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbcatalog/v2beta1/workload.proto - -package catalogv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Workload is the representation of a unit of addressable work. This could -// represent a process on a VM, a Kubernetes pod or something else entirely. -type Workload struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // addresses has a list of all workload addresses. This should include - // LAN and WAN addresses as well as any addresses a proxy would need - // to bind to (if different from the default address). - Addresses []*WorkloadAddress `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"` - // ports is a map from port name to workload port’s number and protocol. - Ports map[string]*WorkloadPort `protobuf:"bytes,2,rep,name=ports,proto3" json:"ports,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // node_name is the name of the node this workload belongs to. - NodeName string `protobuf:"bytes,3,opt,name=node_name,json=nodeName,proto3" json:"node_name,omitempty"` - // identity is the name of the workload identity this workload is associated with. - Identity string `protobuf:"bytes,4,opt,name=identity,proto3" json:"identity,omitempty"` - // Locality specifies workload locality. - Locality *Locality `protobuf:"bytes,5,opt,name=locality,proto3" json:"locality,omitempty"` - // deprecated: tags correspond to service tags that you can add to a service for DNS resolution. - // - // Deprecated: Marked as deprecated in pbcatalog/v2beta1/workload.proto. - Tags []string `protobuf:"bytes,6,rep,name=tags,proto3" json:"tags,omitempty"` - // deprecated: enable_tag_override indicates whether agents should be overriding tags during anti-entropy syncs. - // - // Deprecated: Marked as deprecated in pbcatalog/v2beta1/workload.proto. - EnableTagOverride bool `protobuf:"varint,7,opt,name=enable_tag_override,json=enableTagOverride,proto3" json:"enable_tag_override,omitempty"` - // deprecated: connect_native indicates whether this workload is connect native which will allow it to be - // part of MeshEndpoints without having the corresponding Proxy resource. - // - // Deprecated: Marked as deprecated in pbcatalog/v2beta1/workload.proto. - ConnectNative bool `protobuf:"varint,8,opt,name=connect_native,json=connectNative,proto3" json:"connect_native,omitempty"` -} - -func (x *Workload) Reset() { - *x = Workload{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_workload_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Workload) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Workload) ProtoMessage() {} - -func (x *Workload) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_workload_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Workload.ProtoReflect.Descriptor instead. -func (*Workload) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_workload_proto_rawDescGZIP(), []int{0} -} - -func (x *Workload) GetAddresses() []*WorkloadAddress { - if x != nil { - return x.Addresses - } - return nil -} - -func (x *Workload) GetPorts() map[string]*WorkloadPort { - if x != nil { - return x.Ports - } - return nil -} - -func (x *Workload) GetNodeName() string { - if x != nil { - return x.NodeName - } - return "" -} - -func (x *Workload) GetIdentity() string { - if x != nil { - return x.Identity - } - return "" -} - -func (x *Workload) GetLocality() *Locality { - if x != nil { - return x.Locality - } - return nil -} - -// Deprecated: Marked as deprecated in pbcatalog/v2beta1/workload.proto. -func (x *Workload) GetTags() []string { - if x != nil { - return x.Tags - } - return nil -} - -// Deprecated: Marked as deprecated in pbcatalog/v2beta1/workload.proto. -func (x *Workload) GetEnableTagOverride() bool { - if x != nil { - return x.EnableTagOverride - } - return false -} - -// Deprecated: Marked as deprecated in pbcatalog/v2beta1/workload.proto. -func (x *Workload) GetConnectNative() bool { - if x != nil { - return x.ConnectNative - } - return false -} - -type WorkloadAddress struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // host can be an IP, DNS name or a unix socket. - // If it's a unix socket, only one port can be provided. - Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` - // ports is a list of names of ports that this host binds to. - // If no ports are provided, we will assume all ports from the ports map. - Ports []string `protobuf:"bytes,2,rep,name=ports,proto3" json:"ports,omitempty"` - // external indicates whether this address should be used for external communication - // (aka a WAN address). - External bool `protobuf:"varint,3,opt,name=external,proto3" json:"external,omitempty"` -} - -func (x *WorkloadAddress) Reset() { - *x = WorkloadAddress{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_workload_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WorkloadAddress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WorkloadAddress) ProtoMessage() {} - -func (x *WorkloadAddress) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_workload_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WorkloadAddress.ProtoReflect.Descriptor instead. -func (*WorkloadAddress) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_workload_proto_rawDescGZIP(), []int{1} -} - -func (x *WorkloadAddress) GetHost() string { - if x != nil { - return x.Host - } - return "" -} - -func (x *WorkloadAddress) GetPorts() []string { - if x != nil { - return x.Ports - } - return nil -} - -func (x *WorkloadAddress) GetExternal() bool { - if x != nil { - return x.External - } - return false -} - -type WorkloadPort struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Port uint32 `protobuf:"varint,1,opt,name=port,proto3" json:"port,omitempty"` - Protocol Protocol `protobuf:"varint,2,opt,name=protocol,proto3,enum=hashicorp.consul.catalog.v2beta1.Protocol" json:"protocol,omitempty"` -} - -func (x *WorkloadPort) Reset() { - *x = WorkloadPort{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_workload_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WorkloadPort) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WorkloadPort) ProtoMessage() {} - -func (x *WorkloadPort) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_workload_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WorkloadPort.ProtoReflect.Descriptor instead. -func (*WorkloadPort) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_workload_proto_rawDescGZIP(), []int{2} -} - -func (x *WorkloadPort) GetPort() uint32 { - if x != nil { - return x.Port - } - return 0 -} - -func (x *WorkloadPort) GetProtocol() Protocol { - if x != nil { - return x.Protocol - } - return Protocol_PROTOCOL_UNSPECIFIED -} - -type Locality struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Region is region the zone belongs to. - Region string `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` - // Zone is the zone the entity is running in. - Zone string `protobuf:"bytes,2,opt,name=zone,proto3" json:"zone,omitempty"` -} - -func (x *Locality) Reset() { - *x = Locality{} - if protoimpl.UnsafeEnabled { - mi := &file_pbcatalog_v2beta1_workload_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Locality) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Locality) ProtoMessage() {} - -func (x *Locality) ProtoReflect() protoreflect.Message { - mi := &file_pbcatalog_v2beta1_workload_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Locality.ProtoReflect.Descriptor instead. -func (*Locality) Descriptor() ([]byte, []int) { - return file_pbcatalog_v2beta1_workload_proto_rawDescGZIP(), []int{3} -} - -func (x *Locality) GetRegion() string { - if x != nil { - return x.Region - } - return "" -} - -func (x *Locality) GetZone() string { - if x != nil { - return x.Zone - } - return "" -} - -var File_pbcatalog_v2beta1_workload_proto protoreflect.FileDescriptor - -var file_pbcatalog_v2beta1_workload_proto_rawDesc = []byte{ - 0x0a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x1a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x92, 0x04, 0x0a, 0x08, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, - 0x64, 0x12, 0x4f, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x50, 0x6f, - 0x72, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x12, - 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x46, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, - 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, - 0x12, 0x16, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x42, 0x02, - 0x18, 0x01, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x32, 0x0a, 0x13, 0x65, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x67, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x11, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x54, 0x61, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x0e, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x4e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x1a, 0x68, 0x0a, 0x0a, 0x50, 0x6f, 0x72, 0x74, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, - 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, - 0x61, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0x57, 0x0a, 0x0f, 0x57, 0x6f, 0x72, - 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, - 0x12, 0x14, 0x0a, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x22, 0x6a, 0x0a, 0x0c, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, - 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x46, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x36, - 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, - 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, - 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x7a, 0x6f, 0x6e, 0x65, 0x42, 0xa3, 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, - 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x63, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, - 0x43, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5c, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x43, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x43, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbcatalog_v2beta1_workload_proto_rawDescOnce sync.Once - file_pbcatalog_v2beta1_workload_proto_rawDescData = file_pbcatalog_v2beta1_workload_proto_rawDesc -) - -func file_pbcatalog_v2beta1_workload_proto_rawDescGZIP() []byte { - file_pbcatalog_v2beta1_workload_proto_rawDescOnce.Do(func() { - file_pbcatalog_v2beta1_workload_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbcatalog_v2beta1_workload_proto_rawDescData) - }) - return file_pbcatalog_v2beta1_workload_proto_rawDescData -} - -var file_pbcatalog_v2beta1_workload_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_pbcatalog_v2beta1_workload_proto_goTypes = []interface{}{ - (*Workload)(nil), // 0: hashicorp.consul.catalog.v2beta1.Workload - (*WorkloadAddress)(nil), // 1: hashicorp.consul.catalog.v2beta1.WorkloadAddress - (*WorkloadPort)(nil), // 2: hashicorp.consul.catalog.v2beta1.WorkloadPort - (*Locality)(nil), // 3: hashicorp.consul.catalog.v2beta1.Locality - nil, // 4: hashicorp.consul.catalog.v2beta1.Workload.PortsEntry - (Protocol)(0), // 5: hashicorp.consul.catalog.v2beta1.Protocol -} -var file_pbcatalog_v2beta1_workload_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.catalog.v2beta1.Workload.addresses:type_name -> hashicorp.consul.catalog.v2beta1.WorkloadAddress - 4, // 1: hashicorp.consul.catalog.v2beta1.Workload.ports:type_name -> hashicorp.consul.catalog.v2beta1.Workload.PortsEntry - 3, // 2: hashicorp.consul.catalog.v2beta1.Workload.locality:type_name -> hashicorp.consul.catalog.v2beta1.Locality - 5, // 3: hashicorp.consul.catalog.v2beta1.WorkloadPort.protocol:type_name -> hashicorp.consul.catalog.v2beta1.Protocol - 2, // 4: hashicorp.consul.catalog.v2beta1.Workload.PortsEntry.value:type_name -> hashicorp.consul.catalog.v2beta1.WorkloadPort - 5, // [5:5] is the sub-list for method output_type - 5, // [5:5] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name -} - -func init() { file_pbcatalog_v2beta1_workload_proto_init() } -func file_pbcatalog_v2beta1_workload_proto_init() { - if File_pbcatalog_v2beta1_workload_proto != nil { - return - } - file_pbcatalog_v2beta1_protocol_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbcatalog_v2beta1_workload_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Workload); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_workload_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkloadAddress); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_workload_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkloadPort); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbcatalog_v2beta1_workload_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Locality); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbcatalog_v2beta1_workload_proto_rawDesc, - NumEnums: 0, - NumMessages: 5, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbcatalog_v2beta1_workload_proto_goTypes, - DependencyIndexes: file_pbcatalog_v2beta1_workload_proto_depIdxs, - MessageInfos: file_pbcatalog_v2beta1_workload_proto_msgTypes, - }.Build() - File_pbcatalog_v2beta1_workload_proto = out.File - file_pbcatalog_v2beta1_workload_proto_rawDesc = nil - file_pbcatalog_v2beta1_workload_proto_goTypes = nil - file_pbcatalog_v2beta1_workload_proto_depIdxs = nil -} diff --git a/proto-public/pbcatalog/v2beta1/workload.proto b/proto-public/pbcatalog/v2beta1/workload.proto deleted file mode 100644 index 67dd8b72d272..000000000000 --- a/proto-public/pbcatalog/v2beta1/workload.proto +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.catalog.v2beta1; - -import "pbcatalog/v2beta1/protocol.proto"; -import "pbresource/annotations.proto"; - -// Workload is the representation of a unit of addressable work. This could -// represent a process on a VM, a Kubernetes pod or something else entirely. -message Workload { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // addresses has a list of all workload addresses. This should include - // LAN and WAN addresses as well as any addresses a proxy would need - // to bind to (if different from the default address). - repeated WorkloadAddress addresses = 1; - - // ports is a map from port name to workload port’s number and protocol. - map ports = 2; - - // node_name is the name of the node this workload belongs to. - string node_name = 3; - - // identity is the name of the workload identity this workload is associated with. - string identity = 4; - - // Locality specifies workload locality. - Locality locality = 5; - - // Below fields are deprecated but kept here for backward compatibility reasons. - - // deprecated: tags correspond to service tags that you can add to a service for DNS resolution. - repeated string tags = 6 [deprecated = true]; - // deprecated: enable_tag_override indicates whether agents should be overriding tags during anti-entropy syncs. - bool enable_tag_override = 7 [deprecated = true]; - // deprecated: connect_native indicates whether this workload is connect native which will allow it to be - // part of MeshEndpoints without having the corresponding Proxy resource. - bool connect_native = 8 [deprecated = true]; -} - -message WorkloadAddress { - // host can be an IP, DNS name or a unix socket. - // If it's a unix socket, only one port can be provided. - string host = 1; - - // ports is a list of names of ports that this host binds to. - // If no ports are provided, we will assume all ports from the ports map. - repeated string ports = 2; - - // external indicates whether this address should be used for external communication - // (aka a WAN address). - bool external = 3; -} - -message WorkloadPort { - uint32 port = 1; - Protocol protocol = 2; -} - -message Locality { - // Region is region the zone belongs to. - string region = 1; - - // Zone is the zone the entity is running in. - string zone = 2; -} diff --git a/proto-public/pbcatalog/v2beta1/workload_addon.go b/proto-public/pbcatalog/v2beta1/workload_addon.go deleted file mode 100644 index d09ef6145451..000000000000 --- a/proto-public/pbcatalog/v2beta1/workload_addon.go +++ /dev/null @@ -1,77 +0,0 @@ -package catalogv2beta1 - -import "golang.org/x/exp/slices" - -func (w *Workload) GetMeshPortName() (string, bool) { - var meshPort string - - for portName, port := range w.GetPorts() { - if port.Protocol == Protocol_PROTOCOL_MESH { - meshPort = portName - return meshPort, true - } - } - - return "", false -} - -func (w *Workload) IsMeshEnabled() bool { - _, ok := w.GetMeshPortName() - return ok -} - -func (w *Workload) GetNonExternalAddressesForPort(portName string) []*WorkloadAddress { - var addresses []*WorkloadAddress - - // If this port doesn't exist on a workload, return nil. - if _, ok := w.GetPorts()[portName]; !ok { - return nil - } - - for _, address := range w.GetAddresses() { - if address.GetExternal() { - // Skip external addresses. - continue - } - - // If there are no ports, that means this port is selected. - // Otherwise, check if the port is explicitly selected by this address - if len(address.Ports) == 0 || slices.Contains(address.GetPorts(), portName) { - addresses = append(addresses, address) - } - } - - return addresses -} - -func (w *Workload) GetFirstNonExternalMeshAddress() *WorkloadAddress { - // Find mesh port. - meshPort, ok := w.GetMeshPortName() - if !ok { - return nil - } - - // Check if the workload has a specific address for the mesh port. - meshAddresses := w.GetNonExternalAddressesForPort(meshPort) - - // If there are no mesh addresses, return. This should be impossible. - if len(meshAddresses) == 0 { - return nil - } - - // If there are more than one mesh address, use the first one in the list. - return meshAddresses[0] -} - -func (w *Workload) GetPortsByProtocol() map[Protocol][]string { - if w == nil { - return nil - } - - out := make(map[Protocol][]string, len(w.GetPorts())) - for name, port := range w.GetPorts() { - out[port.GetProtocol()] = append(out[port.GetProtocol()], name) - } - - return out -} diff --git a/proto-public/pbcatalog/v2beta1/workload_addon_test.go b/proto-public/pbcatalog/v2beta1/workload_addon_test.go deleted file mode 100644 index 0a40f77d1eaa..000000000000 --- a/proto-public/pbcatalog/v2beta1/workload_addon_test.go +++ /dev/null @@ -1,259 +0,0 @@ -package catalogv2beta1 - -import ( - "sort" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestGetMeshPort(t *testing.T) { - cases := map[string]struct { - ports map[string]*WorkloadPort - exp string - }{ - "nil ports": { - ports: nil, - exp: "", - }, - "empty ports": { - ports: make(map[string]*WorkloadPort), - exp: "", - }, - "no mesh ports": { - ports: map[string]*WorkloadPort{ - "p1": {Port: 1000, Protocol: Protocol_PROTOCOL_HTTP}, - "p2": {Port: 2000, Protocol: Protocol_PROTOCOL_TCP}, - }, - exp: "", - }, - "one mesh port": { - ports: map[string]*WorkloadPort{ - "p1": {Port: 1000, Protocol: Protocol_PROTOCOL_HTTP}, - "p2": {Port: 2000, Protocol: Protocol_PROTOCOL_TCP}, - "p3": {Port: 3000, Protocol: Protocol_PROTOCOL_MESH}, - }, - exp: "p3", - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - workload := Workload{ - Ports: c.ports, - } - meshPort, ok := workload.GetMeshPortName() - if c.exp != "" { - require.True(t, ok) - require.Equal(t, c.exp, meshPort) - } - }) - } -} - -func TestWorkloadIsMeshEnabled(t *testing.T) { - cases := map[string]struct { - ports map[string]*WorkloadPort - exp bool - }{ - "no ports": { - ports: nil, - exp: false, - }, - "no mesh": { - ports: map[string]*WorkloadPort{ - "p1": {Port: 8080}, - "p2": {Port: 8081}, - }, - exp: false, - }, - "with mesh": { - ports: map[string]*WorkloadPort{ - "p1": {Port: 8080}, - "p2": {Port: 8081, Protocol: Protocol_PROTOCOL_MESH}, - }, - exp: false, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - w := &Workload{ - Ports: c.ports, - } - require.Equal(t, c.exp, w.IsMeshEnabled()) - }) - } -} - -func TestGetAddressesForPort(t *testing.T) { - cases := map[string]struct { - addresses []*WorkloadAddress - ports map[string]*WorkloadPort - portName string - expAddresses []*WorkloadAddress - }{ - "empty addresses": { - addresses: nil, - ports: nil, - portName: "doesn't matter", - expAddresses: nil, - }, - "addresses without selected port": { - addresses: []*WorkloadAddress{{Host: "1.1.1.1"}}, - ports: nil, - portName: "not-found", - expAddresses: nil, - }, - "single selected address": { - addresses: []*WorkloadAddress{ - {Host: "1.1.1.1", Ports: []string{"p1", "p2"}}, - {Host: "2.2.2.2", Ports: []string{"p3", "p4"}}, - }, - ports: map[string]*WorkloadPort{ - "p1": {Port: 8080}, - "p2": {Port: 8081}, - "p3": {Port: 8082}, - "p4": {Port: 8083}, - }, - portName: "p1", - expAddresses: []*WorkloadAddress{ - {Host: "1.1.1.1", Ports: []string{"p1", "p2"}}, - }, - }, - "multiple selected addresses": { - addresses: []*WorkloadAddress{ - {Host: "1.1.1.1", Ports: []string{"p1", "p2"}}, - {Host: "2.2.2.2", Ports: []string{"p3", "p4"}}, - {Host: "3.3.3.3"}, - {Host: "3.3.3.3", Ports: []string{"p1"}, External: true}, - }, - ports: map[string]*WorkloadPort{ - "p1": {Port: 8080}, - "p2": {Port: 8081}, - "p3": {Port: 8082}, - "p4": {Port: 8083}, - }, - portName: "p1", - expAddresses: []*WorkloadAddress{ - {Host: "1.1.1.1", Ports: []string{"p1", "p2"}}, - {Host: "3.3.3.3"}, - }, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - workload := Workload{ - Addresses: c.addresses, - Ports: c.ports, - } - - actualAddresses := workload.GetNonExternalAddressesForPort(c.portName) - require.Equal(t, c.expAddresses, actualAddresses) - }) - } -} - -func TestGetFirstNonExternalMeshAddress(t *testing.T) { - cases := map[string]struct { - workload *Workload - expAddress *WorkloadAddress - }{ - "empty addresses": { - workload: &Workload{}, - expAddress: nil, - }, - "no mesh port": { - workload: &Workload{ - Addresses: []*WorkloadAddress{{Host: "1.1.1.1"}}, - Ports: map[string]*WorkloadPort{ - "tcp": {Port: 8080}, - }, - }, - expAddress: nil, - }, - "only external mesh ports": { - workload: &Workload{ - Addresses: []*WorkloadAddress{{Host: "1.1.1.1", External: true}}, - Ports: map[string]*WorkloadPort{ - "mesh": {Port: 8080, Protocol: Protocol_PROTOCOL_MESH}, - }, - }, - expAddress: nil, - }, - "only external and internal mesh ports": { - workload: &Workload{ - Addresses: []*WorkloadAddress{ - {Host: "1.1.1.1"}, - {Host: "2.2.2.2", External: true}, - }, - Ports: map[string]*WorkloadPort{ - "mesh": {Port: 8080, Protocol: Protocol_PROTOCOL_MESH}, - }, - }, - expAddress: &WorkloadAddress{Host: "1.1.1.1"}, - }, - "multiple internal addresses for mesh port": { - workload: &Workload{ - Addresses: []*WorkloadAddress{ - {Host: "1.1.1.1"}, - {Host: "2.2.2.2", External: true}, - {Host: "3.3.3.3"}, - }, - Ports: map[string]*WorkloadPort{ - "mesh": {Port: 8080, Protocol: Protocol_PROTOCOL_MESH}, - }, - }, - expAddress: &WorkloadAddress{Host: "1.1.1.1"}, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - actualAddress := c.workload.GetFirstNonExternalMeshAddress() - require.Equal(t, actualAddress, c.expAddress) - }) - } -} - -func TestGetPortsByProtocol(t *testing.T) { - cases := map[string]struct { - w *Workload - exp map[Protocol][]string - }{ - "nil": { - w: nil, - exp: nil, - }, - "ports with protocols": { - w: &Workload{ - Ports: map[string]*WorkloadPort{ - "p1": {Port: 8080, Protocol: Protocol_PROTOCOL_TCP}, - "p2": {Port: 8081, Protocol: Protocol_PROTOCOL_HTTP}, - "p3": {Port: 8082, Protocol: Protocol_PROTOCOL_HTTP2}, - "p4": {Port: 8083, Protocol: Protocol_PROTOCOL_TCP}, - "p5": {Port: 8084, Protocol: Protocol_PROTOCOL_MESH}, - "p6": {Port: 8085, Protocol: Protocol_PROTOCOL_MESH}, - }, - }, - exp: map[Protocol][]string{ - Protocol_PROTOCOL_TCP: {"p1", "p4"}, - Protocol_PROTOCOL_HTTP: {"p2"}, - Protocol_PROTOCOL_HTTP2: {"p3"}, - Protocol_PROTOCOL_MESH: {"p5", "p6"}, - }, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - portsByProtocol := c.w.GetPortsByProtocol() - for protocol, ports := range portsByProtocol { - sort.Strings(ports) - portsByProtocol[protocol] = ports - } - require.Equal(t, c.exp, portsByProtocol) - }) - } -} diff --git a/proto-public/pbcatalog/v2beta1/workload_deepcopy.gen.go b/proto-public/pbcatalog/v2beta1/workload_deepcopy.gen.go deleted file mode 100644 index 10d71872bf6d..000000000000 --- a/proto-public/pbcatalog/v2beta1/workload_deepcopy.gen.go +++ /dev/null @@ -1,90 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package catalogv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using Workload within kubernetes types, where deepcopy-gen is used. -func (in *Workload) DeepCopyInto(out *Workload) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Workload. Required by controller-gen. -func (in *Workload) DeepCopy() *Workload { - if in == nil { - return nil - } - out := new(Workload) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Workload. Required by controller-gen. -func (in *Workload) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using WorkloadAddress within kubernetes types, where deepcopy-gen is used. -func (in *WorkloadAddress) DeepCopyInto(out *WorkloadAddress) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadAddress. Required by controller-gen. -func (in *WorkloadAddress) DeepCopy() *WorkloadAddress { - if in == nil { - return nil - } - out := new(WorkloadAddress) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadAddress. Required by controller-gen. -func (in *WorkloadAddress) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using WorkloadPort within kubernetes types, where deepcopy-gen is used. -func (in *WorkloadPort) DeepCopyInto(out *WorkloadPort) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadPort. Required by controller-gen. -func (in *WorkloadPort) DeepCopy() *WorkloadPort { - if in == nil { - return nil - } - out := new(WorkloadPort) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadPort. Required by controller-gen. -func (in *WorkloadPort) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Locality within kubernetes types, where deepcopy-gen is used. -func (in *Locality) DeepCopyInto(out *Locality) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Locality. Required by controller-gen. -func (in *Locality) DeepCopy() *Locality { - if in == nil { - return nil - } - out := new(Locality) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Locality. Required by controller-gen. -func (in *Locality) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbcatalog/v2beta1/workload_json.gen.go b/proto-public/pbcatalog/v2beta1/workload_json.gen.go deleted file mode 100644 index 98592bbd45e9..000000000000 --- a/proto-public/pbcatalog/v2beta1/workload_json.gen.go +++ /dev/null @@ -1,55 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package catalogv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for Workload -func (this *Workload) MarshalJSON() ([]byte, error) { - str, err := WorkloadMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Workload -func (this *Workload) UnmarshalJSON(b []byte) error { - return WorkloadUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for WorkloadAddress -func (this *WorkloadAddress) MarshalJSON() ([]byte, error) { - str, err := WorkloadMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for WorkloadAddress -func (this *WorkloadAddress) UnmarshalJSON(b []byte) error { - return WorkloadUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for WorkloadPort -func (this *WorkloadPort) MarshalJSON() ([]byte, error) { - str, err := WorkloadMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for WorkloadPort -func (this *WorkloadPort) UnmarshalJSON(b []byte) error { - return WorkloadUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Locality -func (this *Locality) MarshalJSON() ([]byte, error) { - str, err := WorkloadMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Locality -func (this *Locality) UnmarshalJSON(b []byte) error { - return WorkloadUnmarshaler.Unmarshal(b, this) -} - -var ( - WorkloadMarshaler = &protojson.MarshalOptions{} - WorkloadUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbconnectca/ca.pb.go b/proto-public/pbconnectca/ca.pb.go index b4312816f310..69d2307565c5 100644 --- a/proto-public/pbconnectca/ca.pb.go +++ b/proto-public/pbconnectca/ca.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: pbconnectca/ca.proto diff --git a/proto-public/pbconnectca/ca_cloning_grpc.pb.go b/proto-public/pbconnectca/ca_cloning_grpc.pb.go new file mode 100644 index 000000000000..d8abc412f590 --- /dev/null +++ b/proto-public/pbconnectca/ca_cloning_grpc.pb.go @@ -0,0 +1,69 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package pbconnectca + +import ( + "context" + + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +// compile-time check to ensure that the generator is implementing all +// of the grpc client interfaces methods. +var _ ConnectCAServiceClient = CloningConnectCAServiceClient{} + +// IsCloningConnectCAServiceClient is an interface that can be used to detect +// that a ConnectCAServiceClient is using the in-memory transport and has already +// been wrapped with a with a CloningConnectCAServiceClient. +type IsCloningConnectCAServiceClient interface { + IsCloningConnectCAServiceClient() bool +} + +// CloningConnectCAServiceClient implements the ConnectCAServiceClient interface by wrapping +// another implementation and copying all protobuf messages that pass through the client. +// This is mainly useful to wrap the an in-process client to insulate users of that +// client from having to care about potential immutability of data they receive or having +// the server implementation mutate their internal memory. +type CloningConnectCAServiceClient struct { + ConnectCAServiceClient +} + +func NewCloningConnectCAServiceClient(client ConnectCAServiceClient) ConnectCAServiceClient { + if cloner, ok := client.(IsCloningConnectCAServiceClient); ok && cloner.IsCloningConnectCAServiceClient() { + // prevent a double clone if the underlying client is already the cloning client. + return client + } + + return CloningConnectCAServiceClient{ + ConnectCAServiceClient: client, + } +} + +// IsCloningConnectCAServiceClient implements the IsCloningConnectCAServiceClient interface. This +// is only used to detect wrapped clients that would be double cloning data and prevent that. +func (c CloningConnectCAServiceClient) IsCloningConnectCAServiceClient() bool { + return true +} + +func (c CloningConnectCAServiceClient) Sign(ctx context.Context, in *SignRequest, opts ...grpc.CallOption) (*SignResponse, error) { + in = proto.Clone(in).(*SignRequest) + + out, err := c.ConnectCAServiceClient.Sign(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*SignResponse), nil +} + +func (c CloningConnectCAServiceClient) WatchRoots(ctx context.Context, in *WatchRootsRequest, opts ...grpc.CallOption) (ConnectCAService_WatchRootsClient, error) { + in = proto.Clone(in).(*WatchRootsRequest) + + st, err := c.ConnectCAServiceClient.WatchRoots(ctx, in) + if err != nil { + return nil, err + } + + return newCloningStream[*WatchRootsResponse](st), nil +} diff --git a/proto-public/pbconnectca/cloning_stream.pb.go b/proto-public/pbconnectca/cloning_stream.pb.go new file mode 100644 index 000000000000..fe7fca3821e1 --- /dev/null +++ b/proto-public/pbconnectca/cloning_stream.pb.go @@ -0,0 +1,31 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package pbconnectca + +import ( + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +type serverStream[T proto.Message] interface { + Recv() (T, error) + grpc.ClientStream +} + +type cloningStream[T proto.Message] struct { + serverStream[T] +} + +func newCloningStream[T proto.Message](stream serverStream[T]) cloningStream[T] { + return cloningStream[T]{serverStream: stream} +} + +func (st cloningStream[T]) Recv() (T, error) { + var zero T + val, err := st.serverStream.Recv() + if err != nil { + return zero, err + } + + return proto.Clone(val).(T), nil +} diff --git a/proto-public/pbdataplane/dataplane.pb.go b/proto-public/pbdataplane/dataplane.pb.go index faa826994768..aa4b70c794df 100644 --- a/proto-public/pbdataplane/dataplane.pb.go +++ b/proto-public/pbdataplane/dataplane.pb.go @@ -5,7 +5,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: pbdataplane/dataplane.proto @@ -13,7 +13,6 @@ package pbdataplane import ( _ "github.com/hashicorp/consul/proto-public/annotations/ratelimit" - v2beta1 "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" structpb "google.golang.org/protobuf/types/known/structpb" @@ -438,15 +437,13 @@ type GetEnvoyBootstrapParamsResponse struct { // If the service is a connect proxy it will be the name of // the proxy's destination service, for gateways it will be the gateway // service's name. - // For v2, this should be the workload identity name. - Identity string `protobuf:"bytes,10,opt,name=identity,proto3" json:"identity,omitempty"` - Namespace string `protobuf:"bytes,3,opt,name=namespace,proto3" json:"namespace,omitempty"` - Partition string `protobuf:"bytes,4,opt,name=partition,proto3" json:"partition,omitempty"` - Datacenter string `protobuf:"bytes,5,opt,name=datacenter,proto3" json:"datacenter,omitempty"` - Config *structpb.Struct `protobuf:"bytes,6,opt,name=config,proto3" json:"config,omitempty"` - BootstrapConfig *v2beta1.BootstrapConfig `protobuf:"bytes,11,opt,name=bootstrap_config,json=bootstrapConfig,proto3" json:"bootstrap_config,omitempty"` - NodeName string `protobuf:"bytes,8,opt,name=node_name,json=nodeName,proto3" json:"node_name,omitempty"` - AccessLogs []string `protobuf:"bytes,9,rep,name=access_logs,json=accessLogs,proto3" json:"access_logs,omitempty"` + Identity string `protobuf:"bytes,10,opt,name=identity,proto3" json:"identity,omitempty"` + Namespace string `protobuf:"bytes,3,opt,name=namespace,proto3" json:"namespace,omitempty"` + Partition string `protobuf:"bytes,4,opt,name=partition,proto3" json:"partition,omitempty"` + Datacenter string `protobuf:"bytes,5,opt,name=datacenter,proto3" json:"datacenter,omitempty"` + Config *structpb.Struct `protobuf:"bytes,6,opt,name=config,proto3" json:"config,omitempty"` + NodeName string `protobuf:"bytes,8,opt,name=node_name,json=nodeName,proto3" json:"node_name,omitempty"` + AccessLogs []string `protobuf:"bytes,9,rep,name=access_logs,json=accessLogs,proto3" json:"access_logs,omitempty"` } func (x *GetEnvoyBootstrapParamsResponse) Reset() { @@ -524,13 +521,6 @@ func (x *GetEnvoyBootstrapParamsResponse) GetConfig() *structpb.Struct { return nil } -func (x *GetEnvoyBootstrapParamsResponse) GetBootstrapConfig() *v2beta1.BootstrapConfig { - if x != nil { - return x.BootstrapConfig - } - return nil -} - func (x *GetEnvoyBootstrapParamsResponse) GetNodeName() string { if x != nil { return x.NodeName @@ -555,138 +545,130 @@ var file_pbdataplane_dataplane_proto_rawDesc = []byte{ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x2f, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x28, - 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x26, 0x0a, 0x24, 0x47, 0x65, 0x74, 0x53, - 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x22, 0x89, 0x01, 0x0a, 0x17, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x50, 0x0a, 0x0c, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x26, + 0x0a, 0x24, 0x47, 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, + 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x89, 0x01, 0x0a, 0x17, 0x44, 0x61, 0x74, 0x61, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x75, 0x70, 0x70, 0x6f, + 0x72, 0x74, 0x12, 0x50, 0x0a, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x0b, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x22, 0x9e, 0x01, 0x0a, 0x25, 0x47, 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1c, + 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x52, 0x0b, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, - 0x0a, 0x09, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x09, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x22, 0x9e, 0x01, 0x0a, - 0x25, 0x47, 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, - 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1c, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, - 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x5f, 0x66, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, - 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, - 0x74, 0x52, 0x1a, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0xe1, 0x01, - 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, - 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x19, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x09, 0x6e, - 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, - 0x18, 0x01, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x19, 0x0a, - 0x08, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x73, 0x70, 0x65, - 0x63, 0x22, 0x8d, 0x03, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, - 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, - 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, - 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x64, - 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x59, 0x0a, 0x10, - 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0f, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, - 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, - 0x6f, 0x67, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x07, 0x10, - 0x08, 0x2a, 0xe4, 0x01, 0x0a, 0x11, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x1e, 0x44, 0x41, 0x54, 0x41, 0x50, - 0x4c, 0x41, 0x4e, 0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x53, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, 0x44, - 0x41, 0x54, 0x41, 0x50, 0x4c, 0x41, 0x4e, 0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, - 0x53, 0x5f, 0x57, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x53, 0x10, - 0x01, 0x12, 0x32, 0x0a, 0x2e, 0x44, 0x41, 0x54, 0x41, 0x50, 0x4c, 0x41, 0x4e, 0x45, 0x5f, 0x46, - 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x53, 0x5f, 0x45, 0x44, 0x47, 0x45, 0x5f, 0x43, 0x45, 0x52, - 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x4d, 0x41, 0x4e, 0x41, 0x47, 0x45, 0x4d, - 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x34, 0x0a, 0x30, 0x44, 0x41, 0x54, 0x41, 0x50, 0x4c, 0x41, - 0x4e, 0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x53, 0x5f, 0x45, 0x4e, 0x56, 0x4f, - 0x59, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54, 0x52, 0x41, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x46, - 0x49, 0x47, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x44, - 0x41, 0x54, 0x41, 0x50, 0x4c, 0x41, 0x4e, 0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, - 0x53, 0x5f, 0x46, 0x49, 0x50, 0x53, 0x10, 0x04, 0x2a, 0xea, 0x01, 0x0a, 0x0b, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x45, 0x52, 0x56, - 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, - 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x01, - 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, - 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x10, 0x02, - 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, - 0x5f, 0x4d, 0x45, 0x53, 0x48, 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x03, 0x12, - 0x24, 0x0a, 0x20, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, - 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x41, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x41, 0x54, 0x45, - 0x57, 0x41, 0x59, 0x10, 0x04, 0x12, 0x20, 0x0a, 0x1c, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, - 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x49, 0x4e, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x47, 0x41, - 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x05, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x45, 0x52, 0x56, 0x49, - 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x47, 0x41, 0x54, 0x45, - 0x57, 0x41, 0x59, 0x10, 0x06, 0x32, 0xe2, 0x02, 0x0a, 0x10, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, - 0x61, 0x6e, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xae, 0x01, 0x0a, 0x1d, 0x47, - 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x40, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x41, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, - 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x07, 0x12, 0x9c, 0x01, 0x0a, 0x17, - 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, - 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, - 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, - 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, - 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x07, 0x42, 0xf0, 0x01, 0x0a, 0x1e, 0x63, - 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x42, 0x0e, 0x44, - 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x64, 0x61, 0x74, 0x61, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x44, 0xaa, 0x02, 0x1a, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x44, - 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xca, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x44, 0x61, 0x74, 0x61, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xe2, 0x02, 0x26, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x1c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x3a, 0x3a, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x1a, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x73, 0x22, 0xe1, 0x01, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, + 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, + 0x64, 0x12, 0x1d, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x21, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x69, 0x64, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x64, 0x12, 0x1c, + 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x6e, 0x6f, + 0x64, 0x65, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x22, 0xb8, 0x02, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x45, + 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x07, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, + 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, + 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x09, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, + 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x0b, 0x10, 0x0c, 0x4a, 0x04, 0x08, 0x07, + 0x10, 0x08, 0x2a, 0xe4, 0x01, 0x0a, 0x11, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x1e, 0x44, 0x41, 0x54, 0x41, + 0x50, 0x4c, 0x41, 0x4e, 0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x53, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, + 0x44, 0x41, 0x54, 0x41, 0x50, 0x4c, 0x41, 0x4e, 0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, + 0x45, 0x53, 0x5f, 0x57, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x53, + 0x10, 0x01, 0x12, 0x32, 0x0a, 0x2e, 0x44, 0x41, 0x54, 0x41, 0x50, 0x4c, 0x41, 0x4e, 0x45, 0x5f, + 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x53, 0x5f, 0x45, 0x44, 0x47, 0x45, 0x5f, 0x43, 0x45, + 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x4d, 0x41, 0x4e, 0x41, 0x47, 0x45, + 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x34, 0x0a, 0x30, 0x44, 0x41, 0x54, 0x41, 0x50, 0x4c, + 0x41, 0x4e, 0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x53, 0x5f, 0x45, 0x4e, 0x56, + 0x4f, 0x59, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54, 0x52, 0x41, 0x50, 0x5f, 0x43, 0x4f, 0x4e, + 0x46, 0x49, 0x47, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, + 0x44, 0x41, 0x54, 0x41, 0x50, 0x4c, 0x41, 0x4e, 0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, + 0x45, 0x53, 0x5f, 0x46, 0x49, 0x50, 0x53, 0x10, 0x04, 0x2a, 0xea, 0x01, 0x0a, 0x0b, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x45, 0x52, + 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x45, 0x52, 0x56, 0x49, + 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x49, 0x43, 0x41, 0x4c, 0x10, + 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, + 0x44, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x10, + 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, + 0x44, 0x5f, 0x4d, 0x45, 0x53, 0x48, 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x03, + 0x12, 0x24, 0x0a, 0x20, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, + 0x5f, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x41, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x41, 0x54, + 0x45, 0x57, 0x41, 0x59, 0x10, 0x04, 0x12, 0x20, 0x0a, 0x1c, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, + 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x49, 0x4e, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x47, + 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x05, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x45, 0x52, 0x56, + 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x47, 0x41, 0x54, + 0x45, 0x57, 0x41, 0x59, 0x10, 0x06, 0x32, 0xe2, 0x02, 0x0a, 0x10, 0x44, 0x61, 0x74, 0x61, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xae, 0x01, 0x0a, 0x1d, + 0x47, 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x40, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, + 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, + 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x07, 0x12, 0x9c, 0x01, 0x0a, + 0x17, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, + 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, + 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, + 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x07, 0x42, 0xf0, 0x01, 0x0a, 0x1e, + 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x42, 0x0e, + 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x64, 0x61, 0x74, + 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x44, 0xaa, 0x02, 0x1a, 0x48, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xca, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x44, 0x61, 0x74, + 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xe2, 0x02, 0x26, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, + 0x02, 0x1c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -712,22 +694,20 @@ var file_pbdataplane_dataplane_proto_goTypes = []interface{}{ (*GetEnvoyBootstrapParamsRequest)(nil), // 5: hashicorp.consul.dataplane.GetEnvoyBootstrapParamsRequest (*GetEnvoyBootstrapParamsResponse)(nil), // 6: hashicorp.consul.dataplane.GetEnvoyBootstrapParamsResponse (*structpb.Struct)(nil), // 7: google.protobuf.Struct - (*v2beta1.BootstrapConfig)(nil), // 8: hashicorp.consul.mesh.v2beta1.BootstrapConfig } var file_pbdataplane_dataplane_proto_depIdxs = []int32{ 0, // 0: hashicorp.consul.dataplane.DataplaneFeatureSupport.feature_name:type_name -> hashicorp.consul.dataplane.DataplaneFeatures 3, // 1: hashicorp.consul.dataplane.GetSupportedDataplaneFeaturesResponse.supported_dataplane_features:type_name -> hashicorp.consul.dataplane.DataplaneFeatureSupport 7, // 2: hashicorp.consul.dataplane.GetEnvoyBootstrapParamsResponse.config:type_name -> google.protobuf.Struct - 8, // 3: hashicorp.consul.dataplane.GetEnvoyBootstrapParamsResponse.bootstrap_config:type_name -> hashicorp.consul.mesh.v2beta1.BootstrapConfig - 2, // 4: hashicorp.consul.dataplane.DataplaneService.GetSupportedDataplaneFeatures:input_type -> hashicorp.consul.dataplane.GetSupportedDataplaneFeaturesRequest - 5, // 5: hashicorp.consul.dataplane.DataplaneService.GetEnvoyBootstrapParams:input_type -> hashicorp.consul.dataplane.GetEnvoyBootstrapParamsRequest - 4, // 6: hashicorp.consul.dataplane.DataplaneService.GetSupportedDataplaneFeatures:output_type -> hashicorp.consul.dataplane.GetSupportedDataplaneFeaturesResponse - 6, // 7: hashicorp.consul.dataplane.DataplaneService.GetEnvoyBootstrapParams:output_type -> hashicorp.consul.dataplane.GetEnvoyBootstrapParamsResponse - 6, // [6:8] is the sub-list for method output_type - 4, // [4:6] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 2, // 3: hashicorp.consul.dataplane.DataplaneService.GetSupportedDataplaneFeatures:input_type -> hashicorp.consul.dataplane.GetSupportedDataplaneFeaturesRequest + 5, // 4: hashicorp.consul.dataplane.DataplaneService.GetEnvoyBootstrapParams:input_type -> hashicorp.consul.dataplane.GetEnvoyBootstrapParamsRequest + 4, // 5: hashicorp.consul.dataplane.DataplaneService.GetSupportedDataplaneFeatures:output_type -> hashicorp.consul.dataplane.GetSupportedDataplaneFeaturesResponse + 6, // 6: hashicorp.consul.dataplane.DataplaneService.GetEnvoyBootstrapParams:output_type -> hashicorp.consul.dataplane.GetEnvoyBootstrapParamsResponse + 5, // [5:7] is the sub-list for method output_type + 3, // [3:5] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } func init() { file_pbdataplane_dataplane_proto_init() } diff --git a/proto-public/pbdataplane/dataplane.proto b/proto-public/pbdataplane/dataplane.proto index 8faad919726e..24def695e8ab 100644 --- a/proto-public/pbdataplane/dataplane.proto +++ b/proto-public/pbdataplane/dataplane.proto @@ -9,7 +9,6 @@ package hashicorp.consul.dataplane; import "annotations/ratelimit/ratelimit.proto"; import "google/protobuf/struct.proto"; -import "pbmesh/v2beta1/proxy_configuration.proto"; message GetSupportedDataplaneFeaturesRequest {} @@ -92,13 +91,12 @@ message GetEnvoyBootstrapParamsResponse { // If the service is a connect proxy it will be the name of // the proxy's destination service, for gateways it will be the gateway // service's name. - // For v2, this should be the workload identity name. string identity = 10; string namespace = 3; string partition = 4; string datacenter = 5; google.protobuf.Struct config = 6; - hashicorp.consul.mesh.v2beta1.BootstrapConfig bootstrap_config = 11; + reserved 11; // formerly v2 bootstrap_config reserved 7; diff --git a/proto-public/pbdataplane/dataplane_cloning_grpc.pb.go b/proto-public/pbdataplane/dataplane_cloning_grpc.pb.go new file mode 100644 index 000000000000..c5a5b8b10bd8 --- /dev/null +++ b/proto-public/pbdataplane/dataplane_cloning_grpc.pb.go @@ -0,0 +1,69 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package pbdataplane + +import ( + "context" + + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +// compile-time check to ensure that the generator is implementing all +// of the grpc client interfaces methods. +var _ DataplaneServiceClient = CloningDataplaneServiceClient{} + +// IsCloningDataplaneServiceClient is an interface that can be used to detect +// that a DataplaneServiceClient is using the in-memory transport and has already +// been wrapped with a with a CloningDataplaneServiceClient. +type IsCloningDataplaneServiceClient interface { + IsCloningDataplaneServiceClient() bool +} + +// CloningDataplaneServiceClient implements the DataplaneServiceClient interface by wrapping +// another implementation and copying all protobuf messages that pass through the client. +// This is mainly useful to wrap the an in-process client to insulate users of that +// client from having to care about potential immutability of data they receive or having +// the server implementation mutate their internal memory. +type CloningDataplaneServiceClient struct { + DataplaneServiceClient +} + +func NewCloningDataplaneServiceClient(client DataplaneServiceClient) DataplaneServiceClient { + if cloner, ok := client.(IsCloningDataplaneServiceClient); ok && cloner.IsCloningDataplaneServiceClient() { + // prevent a double clone if the underlying client is already the cloning client. + return client + } + + return CloningDataplaneServiceClient{ + DataplaneServiceClient: client, + } +} + +// IsCloningDataplaneServiceClient implements the IsCloningDataplaneServiceClient interface. This +// is only used to detect wrapped clients that would be double cloning data and prevent that. +func (c CloningDataplaneServiceClient) IsCloningDataplaneServiceClient() bool { + return true +} + +func (c CloningDataplaneServiceClient) GetSupportedDataplaneFeatures(ctx context.Context, in *GetSupportedDataplaneFeaturesRequest, opts ...grpc.CallOption) (*GetSupportedDataplaneFeaturesResponse, error) { + in = proto.Clone(in).(*GetSupportedDataplaneFeaturesRequest) + + out, err := c.DataplaneServiceClient.GetSupportedDataplaneFeatures(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*GetSupportedDataplaneFeaturesResponse), nil +} + +func (c CloningDataplaneServiceClient) GetEnvoyBootstrapParams(ctx context.Context, in *GetEnvoyBootstrapParamsRequest, opts ...grpc.CallOption) (*GetEnvoyBootstrapParamsResponse, error) { + in = proto.Clone(in).(*GetEnvoyBootstrapParamsRequest) + + out, err := c.DataplaneServiceClient.GetEnvoyBootstrapParams(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*GetEnvoyBootstrapParamsResponse), nil +} diff --git a/proto-public/pbdns/dns.pb.go b/proto-public/pbdns/dns.pb.go index c3825d68e9e4..3bce69909a68 100644 --- a/proto-public/pbdns/dns.pb.go +++ b/proto-public/pbdns/dns.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: pbdns/dns.proto diff --git a/proto-public/pbdns/dns_cloning_grpc.pb.go b/proto-public/pbdns/dns_cloning_grpc.pb.go new file mode 100644 index 000000000000..4b32b80f5872 --- /dev/null +++ b/proto-public/pbdns/dns_cloning_grpc.pb.go @@ -0,0 +1,58 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package pbdns + +import ( + "context" + + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +// compile-time check to ensure that the generator is implementing all +// of the grpc client interfaces methods. +var _ DNSServiceClient = CloningDNSServiceClient{} + +// IsCloningDNSServiceClient is an interface that can be used to detect +// that a DNSServiceClient is using the in-memory transport and has already +// been wrapped with a with a CloningDNSServiceClient. +type IsCloningDNSServiceClient interface { + IsCloningDNSServiceClient() bool +} + +// CloningDNSServiceClient implements the DNSServiceClient interface by wrapping +// another implementation and copying all protobuf messages that pass through the client. +// This is mainly useful to wrap the an in-process client to insulate users of that +// client from having to care about potential immutability of data they receive or having +// the server implementation mutate their internal memory. +type CloningDNSServiceClient struct { + DNSServiceClient +} + +func NewCloningDNSServiceClient(client DNSServiceClient) DNSServiceClient { + if cloner, ok := client.(IsCloningDNSServiceClient); ok && cloner.IsCloningDNSServiceClient() { + // prevent a double clone if the underlying client is already the cloning client. + return client + } + + return CloningDNSServiceClient{ + DNSServiceClient: client, + } +} + +// IsCloningDNSServiceClient implements the IsCloningDNSServiceClient interface. This +// is only used to detect wrapped clients that would be double cloning data and prevent that. +func (c CloningDNSServiceClient) IsCloningDNSServiceClient() bool { + return true +} + +func (c CloningDNSServiceClient) Query(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error) { + in = proto.Clone(in).(*QueryRequest) + + out, err := c.DNSServiceClient.Query(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*QueryResponse), nil +} diff --git a/proto-public/pbdns/mock_DNSServiceClient.go b/proto-public/pbdns/mock_DNSServiceClient.go deleted file mode 100644 index d9fffda65aef..000000000000 --- a/proto-public/pbdns/mock_DNSServiceClient.go +++ /dev/null @@ -1,64 +0,0 @@ -// Code generated by mockery v2.20.0. DO NOT EDIT. - -package pbdns - -import ( - context "context" - - grpc "google.golang.org/grpc" - - mock "github.com/stretchr/testify/mock" -) - -// MockDNSServiceClient is an autogenerated mock type for the DNSServiceClient type -type MockDNSServiceClient struct { - mock.Mock -} - -// Query provides a mock function with given fields: ctx, in, opts -func (_m *MockDNSServiceClient) Query(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 *QueryResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *QueryRequest, ...grpc.CallOption) (*QueryResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *QueryRequest, ...grpc.CallOption) *QueryResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*QueryResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *QueryRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -type mockConstructorTestingTNewMockDNSServiceClient interface { - mock.TestingT - Cleanup(func()) -} - -// NewMockDNSServiceClient creates a new instance of MockDNSServiceClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewMockDNSServiceClient(t mockConstructorTestingTNewMockDNSServiceClient) *MockDNSServiceClient { - mock := &MockDNSServiceClient{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/proto-public/pbdns/mock_DNSServiceServer.go b/proto-public/pbdns/mock_DNSServiceServer.go deleted file mode 100644 index e78c7d4c304b..000000000000 --- a/proto-public/pbdns/mock_DNSServiceServer.go +++ /dev/null @@ -1,55 +0,0 @@ -// Code generated by mockery v2.20.0. DO NOT EDIT. - -package pbdns - -import ( - context "context" - - mock "github.com/stretchr/testify/mock" -) - -// MockDNSServiceServer is an autogenerated mock type for the DNSServiceServer type -type MockDNSServiceServer struct { - mock.Mock -} - -// Query provides a mock function with given fields: _a0, _a1 -func (_m *MockDNSServiceServer) Query(_a0 context.Context, _a1 *QueryRequest) (*QueryResponse, error) { - ret := _m.Called(_a0, _a1) - - var r0 *QueryResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *QueryRequest) (*QueryResponse, error)); ok { - return rf(_a0, _a1) - } - if rf, ok := ret.Get(0).(func(context.Context, *QueryRequest) *QueryResponse); ok { - r0 = rf(_a0, _a1) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*QueryResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *QueryRequest) error); ok { - r1 = rf(_a0, _a1) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -type mockConstructorTestingTNewMockDNSServiceServer interface { - mock.TestingT - Cleanup(func()) -} - -// NewMockDNSServiceServer creates a new instance of MockDNSServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewMockDNSServiceServer(t mockConstructorTestingTNewMockDNSServiceServer) *MockDNSServiceServer { - mock := &MockDNSServiceServer{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/proto-public/pbdns/mock_UnsafeDNSServiceServer.go b/proto-public/pbdns/mock_UnsafeDNSServiceServer.go deleted file mode 100644 index 43a9e1e461ae..000000000000 --- a/proto-public/pbdns/mock_UnsafeDNSServiceServer.go +++ /dev/null @@ -1,30 +0,0 @@ -// Code generated by mockery v2.20.0. DO NOT EDIT. - -package pbdns - -import mock "github.com/stretchr/testify/mock" - -// MockUnsafeDNSServiceServer is an autogenerated mock type for the UnsafeDNSServiceServer type -type MockUnsafeDNSServiceServer struct { - mock.Mock -} - -// mustEmbedUnimplementedDNSServiceServer provides a mock function with given fields: -func (_m *MockUnsafeDNSServiceServer) mustEmbedUnimplementedDNSServiceServer() { - _m.Called() -} - -type mockConstructorTestingTNewMockUnsafeDNSServiceServer interface { - mock.TestingT - Cleanup(func()) -} - -// NewMockUnsafeDNSServiceServer creates a new instance of MockUnsafeDNSServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewMockUnsafeDNSServiceServer(t mockConstructorTestingTNewMockUnsafeDNSServiceServer) *MockUnsafeDNSServiceServer { - mock := &MockUnsafeDNSServiceServer{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/proto-public/pbhcp/v2/hcp_config.pb.binary.go b/proto-public/pbhcp/v2/hcp_config.pb.binary.go new file mode 100644 index 000000000000..66197e55b6b5 --- /dev/null +++ b/proto-public/pbhcp/v2/hcp_config.pb.binary.go @@ -0,0 +1,18 @@ +// Code generated by protoc-gen-go-binary. DO NOT EDIT. +// source: pbhcp/v2/hcp_config.proto + +package hcpv2 + +import ( + "google.golang.org/protobuf/proto" +) + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *HCPConfig) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *HCPConfig) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} diff --git a/proto-public/pbhcp/v2/hcp_config.pb.go b/proto-public/pbhcp/v2/hcp_config.pb.go new file mode 100644 index 000000000000..66e63187920c --- /dev/null +++ b/proto-public/pbhcp/v2/hcp_config.pb.go @@ -0,0 +1,199 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc (unknown) +// source: pbhcp/v2/hcp_config.proto + +package hcpv2 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// HCPConfig is used to configure the HCP SDK for communicating with +// the HashiCorp Cloud Platform. All configuration is optional with default +// values provided by the SDK. +type HCPConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // AuthUrl is the URL which will be used to authenticate. + AuthUrl string `protobuf:"bytes,1,opt,name=auth_url,json=authUrl,proto3" json:"auth_url,omitempty"` + // ApiAddress is the address ([:port]) of the HCP api. + ApiAddress string `protobuf:"bytes,2,opt,name=api_address,json=apiAddress,proto3" json:"api_address,omitempty"` + // ScadaAddress is the address ([:port]) of the HCP SCADA endpoint. + ScadaAddress string `protobuf:"bytes,3,opt,name=scada_address,json=scadaAddress,proto3" json:"scada_address,omitempty"` + // TlsInsecureSkipVerify if true will ignore server name verification when making HTTPS requests + TlsInsecureSkipVerify bool `protobuf:"varint,4,opt,name=tls_insecure_skip_verify,json=tlsInsecureSkipVerify,proto3" json:"tls_insecure_skip_verify,omitempty"` +} + +func (x *HCPConfig) Reset() { + *x = HCPConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_pbhcp_v2_hcp_config_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HCPConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HCPConfig) ProtoMessage() {} + +func (x *HCPConfig) ProtoReflect() protoreflect.Message { + mi := &file_pbhcp_v2_hcp_config_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HCPConfig.ProtoReflect.Descriptor instead. +func (*HCPConfig) Descriptor() ([]byte, []int) { + return file_pbhcp_v2_hcp_config_proto_rawDescGZIP(), []int{0} +} + +func (x *HCPConfig) GetAuthUrl() string { + if x != nil { + return x.AuthUrl + } + return "" +} + +func (x *HCPConfig) GetApiAddress() string { + if x != nil { + return x.ApiAddress + } + return "" +} + +func (x *HCPConfig) GetScadaAddress() string { + if x != nil { + return x.ScadaAddress + } + return "" +} + +func (x *HCPConfig) GetTlsInsecureSkipVerify() bool { + if x != nil { + return x.TlsInsecureSkipVerify + } + return false +} + +var File_pbhcp_v2_hcp_config_proto protoreflect.FileDescriptor + +var file_pbhcp_v2_hcp_config_proto_rawDesc = []byte{ + 0x0a, 0x19, 0x70, 0x62, 0x68, 0x63, 0x70, 0x2f, 0x76, 0x32, 0x2f, 0x68, 0x63, 0x70, 0x5f, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, + 0x70, 0x2e, 0x76, 0x32, 0x22, 0xa5, 0x01, 0x0a, 0x09, 0x48, 0x43, 0x50, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x75, 0x74, 0x68, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, + 0x0b, 0x61, 0x70, 0x69, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x23, + 0x0a, 0x0d, 0x73, 0x63, 0x61, 0x64, 0x61, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x63, 0x61, 0x64, 0x61, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x74, 0x6c, 0x73, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x74, 0x6c, 0x73, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x42, 0xe5, 0x01, 0x0a, + 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x42, 0x0e, 0x48, 0x63, + 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x68, 0x63, 0x70, 0x2f, 0x76, + 0x32, 0x3b, 0x68, 0x63, 0x70, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x48, 0xaa, 0x02, 0x17, + 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x48, 0x63, 0x70, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x17, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x48, 0x63, 0x70, 0x5c, 0x56, + 0x32, 0xe2, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x48, 0x63, 0x70, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x48, 0x63, 0x70, + 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pbhcp_v2_hcp_config_proto_rawDescOnce sync.Once + file_pbhcp_v2_hcp_config_proto_rawDescData = file_pbhcp_v2_hcp_config_proto_rawDesc +) + +func file_pbhcp_v2_hcp_config_proto_rawDescGZIP() []byte { + file_pbhcp_v2_hcp_config_proto_rawDescOnce.Do(func() { + file_pbhcp_v2_hcp_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbhcp_v2_hcp_config_proto_rawDescData) + }) + return file_pbhcp_v2_hcp_config_proto_rawDescData +} + +var file_pbhcp_v2_hcp_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_pbhcp_v2_hcp_config_proto_goTypes = []interface{}{ + (*HCPConfig)(nil), // 0: hashicorp.consul.hcp.v2.HCPConfig +} +var file_pbhcp_v2_hcp_config_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_pbhcp_v2_hcp_config_proto_init() } +func file_pbhcp_v2_hcp_config_proto_init() { + if File_pbhcp_v2_hcp_config_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pbhcp_v2_hcp_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HCPConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pbhcp_v2_hcp_config_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbhcp_v2_hcp_config_proto_goTypes, + DependencyIndexes: file_pbhcp_v2_hcp_config_proto_depIdxs, + MessageInfos: file_pbhcp_v2_hcp_config_proto_msgTypes, + }.Build() + File_pbhcp_v2_hcp_config_proto = out.File + file_pbhcp_v2_hcp_config_proto_rawDesc = nil + file_pbhcp_v2_hcp_config_proto_goTypes = nil + file_pbhcp_v2_hcp_config_proto_depIdxs = nil +} diff --git a/proto-public/pbhcp/v2/hcp_config.proto b/proto-public/pbhcp/v2/hcp_config.proto new file mode 100644 index 000000000000..a61585a3d2db --- /dev/null +++ b/proto-public/pbhcp/v2/hcp_config.proto @@ -0,0 +1,23 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +syntax = "proto3"; + +package hashicorp.consul.hcp.v2; + +// HCPConfig is used to configure the HCP SDK for communicating with +// the HashiCorp Cloud Platform. All configuration is optional with default +// values provided by the SDK. +message HCPConfig { + // AuthUrl is the URL which will be used to authenticate. + string auth_url = 1; + + // ApiAddress is the address ([:port]) of the HCP api. + string api_address = 2; + + // ScadaAddress is the address ([:port]) of the HCP SCADA endpoint. + string scada_address = 3; + + // TlsInsecureSkipVerify if true will ignore server name verification when making HTTPS requests + bool tls_insecure_skip_verify = 4; +} diff --git a/proto-public/pbhcp/v2/hcp_config_deepcopy.gen.go b/proto-public/pbhcp/v2/hcp_config_deepcopy.gen.go new file mode 100644 index 000000000000..56e40830df09 --- /dev/null +++ b/proto-public/pbhcp/v2/hcp_config_deepcopy.gen.go @@ -0,0 +1,27 @@ +// Code generated by protoc-gen-deepcopy. DO NOT EDIT. +package hcpv2 + +import ( + proto "google.golang.org/protobuf/proto" +) + +// DeepCopyInto supports using HCPConfig within kubernetes types, where deepcopy-gen is used. +func (in *HCPConfig) DeepCopyInto(out *HCPConfig) { + proto.Reset(out) + proto.Merge(out, proto.Clone(in)) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HCPConfig. Required by controller-gen. +func (in *HCPConfig) DeepCopy() *HCPConfig { + if in == nil { + return nil + } + out := new(HCPConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HCPConfig. Required by controller-gen. +func (in *HCPConfig) DeepCopyInterface() interface{} { + return in.DeepCopy() +} diff --git a/proto-public/pbhcp/v2/hcp_config_json.gen.go b/proto-public/pbhcp/v2/hcp_config_json.gen.go new file mode 100644 index 000000000000..efe1d13b8525 --- /dev/null +++ b/proto-public/pbhcp/v2/hcp_config_json.gen.go @@ -0,0 +1,22 @@ +// Code generated by protoc-json-shim. DO NOT EDIT. +package hcpv2 + +import ( + protojson "google.golang.org/protobuf/encoding/protojson" +) + +// MarshalJSON is a custom marshaler for HCPConfig +func (this *HCPConfig) MarshalJSON() ([]byte, error) { + str, err := HcpConfigMarshaler.Marshal(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for HCPConfig +func (this *HCPConfig) UnmarshalJSON(b []byte) error { + return HcpConfigUnmarshaler.Unmarshal(b, this) +} + +var ( + HcpConfigMarshaler = &protojson.MarshalOptions{} + HcpConfigUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} +) diff --git a/proto-public/pbhcp/v2/link.pb.binary.go b/proto-public/pbhcp/v2/link.pb.binary.go new file mode 100644 index 000000000000..7dbfbebae5b2 --- /dev/null +++ b/proto-public/pbhcp/v2/link.pb.binary.go @@ -0,0 +1,18 @@ +// Code generated by protoc-gen-go-binary. DO NOT EDIT. +// source: pbhcp/v2/link.proto + +package hcpv2 + +import ( + "google.golang.org/protobuf/proto" +) + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *Link) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *Link) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} diff --git a/proto-public/pbhcp/v2/link.pb.go b/proto-public/pbhcp/v2/link.pb.go new file mode 100644 index 000000000000..25b2478458c7 --- /dev/null +++ b/proto-public/pbhcp/v2/link.pb.go @@ -0,0 +1,283 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc (unknown) +// source: pbhcp/v2/link.proto + +package hcpv2 + +import ( + _ "github.com/hashicorp/consul/proto-public/pbresource" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type AccessLevel int32 + +const ( + AccessLevel_ACCESS_LEVEL_UNSPECIFIED AccessLevel = 0 + AccessLevel_ACCESS_LEVEL_GLOBAL_READ_WRITE AccessLevel = 1 + AccessLevel_ACCESS_LEVEL_GLOBAL_READ_ONLY AccessLevel = 2 +) + +// Enum value maps for AccessLevel. +var ( + AccessLevel_name = map[int32]string{ + 0: "ACCESS_LEVEL_UNSPECIFIED", + 1: "ACCESS_LEVEL_GLOBAL_READ_WRITE", + 2: "ACCESS_LEVEL_GLOBAL_READ_ONLY", + } + AccessLevel_value = map[string]int32{ + "ACCESS_LEVEL_UNSPECIFIED": 0, + "ACCESS_LEVEL_GLOBAL_READ_WRITE": 1, + "ACCESS_LEVEL_GLOBAL_READ_ONLY": 2, + } +) + +func (x AccessLevel) Enum() *AccessLevel { + p := new(AccessLevel) + *p = x + return p +} + +func (x AccessLevel) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AccessLevel) Descriptor() protoreflect.EnumDescriptor { + return file_pbhcp_v2_link_proto_enumTypes[0].Descriptor() +} + +func (AccessLevel) Type() protoreflect.EnumType { + return &file_pbhcp_v2_link_proto_enumTypes[0] +} + +func (x AccessLevel) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AccessLevel.Descriptor instead. +func (AccessLevel) EnumDescriptor() ([]byte, []int) { + return file_pbhcp_v2_link_proto_rawDescGZIP(), []int{0} +} + +type Link struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ResourceId string `protobuf:"bytes,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + ClientSecret string `protobuf:"bytes,3,opt,name=client_secret,json=clientSecret,proto3" json:"client_secret,omitempty"` + HcpClusterUrl string `protobuf:"bytes,4,opt,name=hcp_cluster_url,json=hcpClusterUrl,proto3" json:"hcp_cluster_url,omitempty"` + AccessLevel AccessLevel `protobuf:"varint,5,opt,name=access_level,json=accessLevel,proto3,enum=hashicorp.consul.hcp.v2.AccessLevel" json:"access_level,omitempty"` + HcpConfig *HCPConfig `protobuf:"bytes,6,opt,name=hcp_config,json=hcpConfig,proto3" json:"hcp_config,omitempty"` +} + +func (x *Link) Reset() { + *x = Link{} + if protoimpl.UnsafeEnabled { + mi := &file_pbhcp_v2_link_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Link) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Link) ProtoMessage() {} + +func (x *Link) ProtoReflect() protoreflect.Message { + mi := &file_pbhcp_v2_link_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Link.ProtoReflect.Descriptor instead. +func (*Link) Descriptor() ([]byte, []int) { + return file_pbhcp_v2_link_proto_rawDescGZIP(), []int{0} +} + +func (x *Link) GetResourceId() string { + if x != nil { + return x.ResourceId + } + return "" +} + +func (x *Link) GetClientId() string { + if x != nil { + return x.ClientId + } + return "" +} + +func (x *Link) GetClientSecret() string { + if x != nil { + return x.ClientSecret + } + return "" +} + +func (x *Link) GetHcpClusterUrl() string { + if x != nil { + return x.HcpClusterUrl + } + return "" +} + +func (x *Link) GetAccessLevel() AccessLevel { + if x != nil { + return x.AccessLevel + } + return AccessLevel_ACCESS_LEVEL_UNSPECIFIED +} + +func (x *Link) GetHcpConfig() *HCPConfig { + if x != nil { + return x.HcpConfig + } + return nil +} + +var File_pbhcp_v2_link_proto protoreflect.FileDescriptor + +var file_pbhcp_v2_link_proto_rawDesc = []byte{ + 0x0a, 0x13, 0x70, 0x62, 0x68, 0x63, 0x70, 0x2f, 0x76, 0x32, 0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x1a, 0x19, + 0x70, 0x62, 0x68, 0x63, 0x70, 0x2f, 0x76, 0x32, 0x2f, 0x68, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa5, 0x02, 0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x6b, + 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23, + 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x68, 0x63, 0x70, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x68, 0x63, + 0x70, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x47, 0x0a, 0x0c, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x12, 0x41, 0x0a, 0x0a, 0x68, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, + 0x76, 0x32, 0x2e, 0x48, 0x43, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x68, 0x63, + 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x01, 0x2a, + 0x72, 0x0a, 0x0b, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1c, + 0x0a, 0x18, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e, + 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x5f, 0x47, 0x4c, 0x4f, + 0x42, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x01, + 0x12, 0x21, 0x0a, 0x1d, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, + 0x5f, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, + 0x59, 0x10, 0x02, 0x42, 0xe0, 0x01, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, + 0x2e, 0x76, 0x32, 0x42, 0x09, 0x4c, 0x69, 0x6e, 0x6b, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x68, 0x63, 0x70, + 0x2f, 0x76, 0x32, 0x3b, 0x68, 0x63, 0x70, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x48, 0xaa, + 0x02, 0x17, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x48, 0x63, 0x70, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x17, 0x48, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x48, 0x63, 0x70, + 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x48, 0x63, 0x70, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x48, + 0x63, 0x70, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pbhcp_v2_link_proto_rawDescOnce sync.Once + file_pbhcp_v2_link_proto_rawDescData = file_pbhcp_v2_link_proto_rawDesc +) + +func file_pbhcp_v2_link_proto_rawDescGZIP() []byte { + file_pbhcp_v2_link_proto_rawDescOnce.Do(func() { + file_pbhcp_v2_link_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbhcp_v2_link_proto_rawDescData) + }) + return file_pbhcp_v2_link_proto_rawDescData +} + +var file_pbhcp_v2_link_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_pbhcp_v2_link_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_pbhcp_v2_link_proto_goTypes = []interface{}{ + (AccessLevel)(0), // 0: hashicorp.consul.hcp.v2.AccessLevel + (*Link)(nil), // 1: hashicorp.consul.hcp.v2.Link + (*HCPConfig)(nil), // 2: hashicorp.consul.hcp.v2.HCPConfig +} +var file_pbhcp_v2_link_proto_depIdxs = []int32{ + 0, // 0: hashicorp.consul.hcp.v2.Link.access_level:type_name -> hashicorp.consul.hcp.v2.AccessLevel + 2, // 1: hashicorp.consul.hcp.v2.Link.hcp_config:type_name -> hashicorp.consul.hcp.v2.HCPConfig + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_pbhcp_v2_link_proto_init() } +func file_pbhcp_v2_link_proto_init() { + if File_pbhcp_v2_link_proto != nil { + return + } + file_pbhcp_v2_hcp_config_proto_init() + if !protoimpl.UnsafeEnabled { + file_pbhcp_v2_link_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Link); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pbhcp_v2_link_proto_rawDesc, + NumEnums: 1, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbhcp_v2_link_proto_goTypes, + DependencyIndexes: file_pbhcp_v2_link_proto_depIdxs, + EnumInfos: file_pbhcp_v2_link_proto_enumTypes, + MessageInfos: file_pbhcp_v2_link_proto_msgTypes, + }.Build() + File_pbhcp_v2_link_proto = out.File + file_pbhcp_v2_link_proto_rawDesc = nil + file_pbhcp_v2_link_proto_goTypes = nil + file_pbhcp_v2_link_proto_depIdxs = nil +} diff --git a/proto-public/pbhcp/v2/link.proto b/proto-public/pbhcp/v2/link.proto new file mode 100644 index 000000000000..ac11ca34b5b9 --- /dev/null +++ b/proto-public/pbhcp/v2/link.proto @@ -0,0 +1,26 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +syntax = "proto3"; + +package hashicorp.consul.hcp.v2; + +import "pbhcp/v2/hcp_config.proto"; +import "pbresource/annotations.proto"; + +enum AccessLevel { + ACCESS_LEVEL_UNSPECIFIED = 0; + ACCESS_LEVEL_GLOBAL_READ_WRITE = 1; + ACCESS_LEVEL_GLOBAL_READ_ONLY = 2; +} + +message Link { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_CLUSTER}; + + string resource_id = 1; + string client_id = 2; + string client_secret = 3; + string hcp_cluster_url = 4; + AccessLevel access_level = 5; + HCPConfig hcp_config = 6; +} diff --git a/proto-public/pbhcp/v2/link_deepcopy.gen.go b/proto-public/pbhcp/v2/link_deepcopy.gen.go new file mode 100644 index 000000000000..9432d81b1eac --- /dev/null +++ b/proto-public/pbhcp/v2/link_deepcopy.gen.go @@ -0,0 +1,27 @@ +// Code generated by protoc-gen-deepcopy. DO NOT EDIT. +package hcpv2 + +import ( + proto "google.golang.org/protobuf/proto" +) + +// DeepCopyInto supports using Link within kubernetes types, where deepcopy-gen is used. +func (in *Link) DeepCopyInto(out *Link) { + proto.Reset(out) + proto.Merge(out, proto.Clone(in)) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Link. Required by controller-gen. +func (in *Link) DeepCopy() *Link { + if in == nil { + return nil + } + out := new(Link) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Link. Required by controller-gen. +func (in *Link) DeepCopyInterface() interface{} { + return in.DeepCopy() +} diff --git a/proto-public/pbhcp/v2/link_json.gen.go b/proto-public/pbhcp/v2/link_json.gen.go new file mode 100644 index 000000000000..cd476920dd17 --- /dev/null +++ b/proto-public/pbhcp/v2/link_json.gen.go @@ -0,0 +1,22 @@ +// Code generated by protoc-json-shim. DO NOT EDIT. +package hcpv2 + +import ( + protojson "google.golang.org/protobuf/encoding/protojson" +) + +// MarshalJSON is a custom marshaler for Link +func (this *Link) MarshalJSON() ([]byte, error) { + str, err := LinkMarshaler.Marshal(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for Link +func (this *Link) UnmarshalJSON(b []byte) error { + return LinkUnmarshaler.Unmarshal(b, this) +} + +var ( + LinkMarshaler = &protojson.MarshalOptions{} + LinkUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} +) diff --git a/proto-public/pbhcp/v2/resources.rtypes.go b/proto-public/pbhcp/v2/resources.rtypes.go new file mode 100644 index 000000000000..7ef93d0ee252 --- /dev/null +++ b/proto-public/pbhcp/v2/resources.rtypes.go @@ -0,0 +1,29 @@ +// Code generated by protoc-gen-resource-types. DO NOT EDIT. + +package hcpv2 + +import ( + "github.com/hashicorp/consul/proto-public/pbresource" +) + +const ( + GroupName = "hcp" + Version = "v2" + + LinkKind = "Link" + TelemetryStateKind = "TelemetryState" +) + +var ( + LinkType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: LinkKind, + } + + TelemetryStateType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: TelemetryStateKind, + } +) diff --git a/proto-public/pbhcp/v2/telemetry_state.pb.binary.go b/proto-public/pbhcp/v2/telemetry_state.pb.binary.go new file mode 100644 index 000000000000..278fe7c2bdc4 --- /dev/null +++ b/proto-public/pbhcp/v2/telemetry_state.pb.binary.go @@ -0,0 +1,38 @@ +// Code generated by protoc-gen-go-binary. DO NOT EDIT. +// source: pbhcp/v2/telemetry_state.proto + +package hcpv2 + +import ( + "google.golang.org/protobuf/proto" +) + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *TelemetryState) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *TelemetryState) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *MetricsConfig) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *MetricsConfig) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ProxyConfig) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ProxyConfig) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} diff --git a/proto-public/pbhcp/v2/telemetry_state.pb.go b/proto-public/pbhcp/v2/telemetry_state.pb.go new file mode 100644 index 000000000000..10c48ab9b602 --- /dev/null +++ b/proto-public/pbhcp/v2/telemetry_state.pb.go @@ -0,0 +1,426 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc (unknown) +// source: pbhcp/v2/telemetry_state.proto + +package hcpv2 + +import ( + _ "github.com/hashicorp/consul/proto-public/pbresource" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// TelemetryState describes configuration required to forward telemetry to the HashiCorp Cloud Platform. +// This resource is managed internally and is only written if the cluster is linked to HCP. Any +// manual changes to the resource will be reconciled and overwritten with the internally computed +// state. +type TelemetryState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // ResourceId is the identifier for the cluster linked with HCP. + ResourceId string `protobuf:"bytes,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + // ClientId is the oauth client identifier for cluster. + // This client has capabilities limited to writing telemetry data for this cluster. + ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + // ClientSecret is the oauth secret used to authenticate requests to send telemetry data to HCP. + ClientSecret string `protobuf:"bytes,3,opt,name=client_secret,json=clientSecret,proto3" json:"client_secret,omitempty"` + HcpConfig *HCPConfig `protobuf:"bytes,4,opt,name=hcp_config,json=hcpConfig,proto3" json:"hcp_config,omitempty"` + Proxy *ProxyConfig `protobuf:"bytes,5,opt,name=proxy,proto3" json:"proxy,omitempty"` + Metrics *MetricsConfig `protobuf:"bytes,6,opt,name=metrics,proto3" json:"metrics,omitempty"` +} + +func (x *TelemetryState) Reset() { + *x = TelemetryState{} + if protoimpl.UnsafeEnabled { + mi := &file_pbhcp_v2_telemetry_state_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TelemetryState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryState) ProtoMessage() {} + +func (x *TelemetryState) ProtoReflect() protoreflect.Message { + mi := &file_pbhcp_v2_telemetry_state_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TelemetryState.ProtoReflect.Descriptor instead. +func (*TelemetryState) Descriptor() ([]byte, []int) { + return file_pbhcp_v2_telemetry_state_proto_rawDescGZIP(), []int{0} +} + +func (x *TelemetryState) GetResourceId() string { + if x != nil { + return x.ResourceId + } + return "" +} + +func (x *TelemetryState) GetClientId() string { + if x != nil { + return x.ClientId + } + return "" +} + +func (x *TelemetryState) GetClientSecret() string { + if x != nil { + return x.ClientSecret + } + return "" +} + +func (x *TelemetryState) GetHcpConfig() *HCPConfig { + if x != nil { + return x.HcpConfig + } + return nil +} + +func (x *TelemetryState) GetProxy() *ProxyConfig { + if x != nil { + return x.Proxy + } + return nil +} + +func (x *TelemetryState) GetMetrics() *MetricsConfig { + if x != nil { + return x.Metrics + } + return nil +} + +// MetricsConfig configures metric specific collection details +type MetricsConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Endpoint is the HTTPS address and path to forward metrics to + Endpoint string `protobuf:"bytes,1,opt,name=endpoint,proto3" json:"endpoint,omitempty"` + // IncludeList contains patterns to match against metric names. Only matched metrics are forwarded. + IncludeList []string `protobuf:"bytes,2,rep,name=include_list,json=includeList,proto3" json:"include_list,omitempty"` + // Labels contains key value pairs that are associated with all metrics collected and fowarded. + Labels map[string]string `protobuf:"bytes,3,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // Disabled toggles metric forwarding. If true, metric forwarding will stop until disabled is set to false. + Disabled bool `protobuf:"varint,4,opt,name=disabled,proto3" json:"disabled,omitempty"` +} + +func (x *MetricsConfig) Reset() { + *x = MetricsConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_pbhcp_v2_telemetry_state_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetricsConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetricsConfig) ProtoMessage() {} + +func (x *MetricsConfig) ProtoReflect() protoreflect.Message { + mi := &file_pbhcp_v2_telemetry_state_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetricsConfig.ProtoReflect.Descriptor instead. +func (*MetricsConfig) Descriptor() ([]byte, []int) { + return file_pbhcp_v2_telemetry_state_proto_rawDescGZIP(), []int{1} +} + +func (x *MetricsConfig) GetEndpoint() string { + if x != nil { + return x.Endpoint + } + return "" +} + +func (x *MetricsConfig) GetIncludeList() []string { + if x != nil { + return x.IncludeList + } + return nil +} + +func (x *MetricsConfig) GetLabels() map[string]string { + if x != nil { + return x.Labels + } + return nil +} + +func (x *MetricsConfig) GetDisabled() bool { + if x != nil { + return x.Disabled + } + return false +} + +// ProxyConfig describes configuration for forwarding requests through an http proxy +type ProxyConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // HttpProxy configures the http proxy to use for HTTP (non-TLS) requests. + HttpProxy string `protobuf:"bytes,1,opt,name=http_proxy,json=httpProxy,proto3" json:"http_proxy,omitempty"` + // HttpsProxy configures the http proxy to use for HTTPS (TLS) requests. + HttpsProxy string `protobuf:"bytes,2,opt,name=https_proxy,json=httpsProxy,proto3" json:"https_proxy,omitempty"` + // NoProxy can be configured to include domains which should NOT be forwarded through the configured http proxy + NoProxy []string `protobuf:"bytes,3,rep,name=no_proxy,json=noProxy,proto3" json:"no_proxy,omitempty"` +} + +func (x *ProxyConfig) Reset() { + *x = ProxyConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_pbhcp_v2_telemetry_state_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ProxyConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProxyConfig) ProtoMessage() {} + +func (x *ProxyConfig) ProtoReflect() protoreflect.Message { + mi := &file_pbhcp_v2_telemetry_state_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ProxyConfig.ProtoReflect.Descriptor instead. +func (*ProxyConfig) Descriptor() ([]byte, []int) { + return file_pbhcp_v2_telemetry_state_proto_rawDescGZIP(), []int{2} +} + +func (x *ProxyConfig) GetHttpProxy() string { + if x != nil { + return x.HttpProxy + } + return "" +} + +func (x *ProxyConfig) GetHttpsProxy() string { + if x != nil { + return x.HttpsProxy + } + return "" +} + +func (x *ProxyConfig) GetNoProxy() []string { + if x != nil { + return x.NoProxy + } + return nil +} + +var File_pbhcp_v2_telemetry_state_proto protoreflect.FileDescriptor + +var file_pbhcp_v2_telemetry_state_proto_rawDesc = []byte{ + 0x0a, 0x1e, 0x70, 0x62, 0x68, 0x63, 0x70, 0x2f, 0x76, 0x32, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, + 0x65, 0x74, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x17, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x1a, 0x19, 0x70, 0x62, 0x68, 0x63, 0x70, + 0x2f, 0x76, 0x32, 0x2f, 0x68, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0xbc, 0x02, 0x0a, 0x0e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, + 0x63, 0x72, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x41, 0x0a, 0x0a, 0x68, 0x63, 0x70, 0x5f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x48, 0x43, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x09, 0x68, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x05, 0x70, + 0x72, 0x6f, 0x78, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, + 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x40, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, + 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, + 0x01, 0x22, 0xf1, 0x01, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x69, + 0x73, 0x74, 0x12, 0x4a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1a, + 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x68, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x70, 0x72, 0x6f, + 0x78, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x68, 0x74, 0x74, 0x70, 0x50, 0x72, + 0x6f, 0x78, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x74, 0x74, 0x70, 0x73, 0x5f, 0x70, 0x72, 0x6f, + 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x73, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x42, + 0xea, 0x01, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x68, 0x63, 0x70, 0x2e, 0x76, 0x32, 0x42, + 0x13, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x2f, 0x70, 0x62, 0x68, 0x63, 0x70, 0x2f, 0x76, 0x32, 0x3b, 0x68, 0x63, 0x70, 0x76, 0x32, 0xa2, + 0x02, 0x03, 0x48, 0x43, 0x48, 0xaa, 0x02, 0x17, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x48, 0x63, 0x70, 0x2e, 0x56, 0x32, 0xca, + 0x02, 0x17, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x5c, 0x48, 0x63, 0x70, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x48, 0x63, 0x70, + 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, + 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x48, 0x63, 0x70, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pbhcp_v2_telemetry_state_proto_rawDescOnce sync.Once + file_pbhcp_v2_telemetry_state_proto_rawDescData = file_pbhcp_v2_telemetry_state_proto_rawDesc +) + +func file_pbhcp_v2_telemetry_state_proto_rawDescGZIP() []byte { + file_pbhcp_v2_telemetry_state_proto_rawDescOnce.Do(func() { + file_pbhcp_v2_telemetry_state_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbhcp_v2_telemetry_state_proto_rawDescData) + }) + return file_pbhcp_v2_telemetry_state_proto_rawDescData +} + +var file_pbhcp_v2_telemetry_state_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_pbhcp_v2_telemetry_state_proto_goTypes = []interface{}{ + (*TelemetryState)(nil), // 0: hashicorp.consul.hcp.v2.TelemetryState + (*MetricsConfig)(nil), // 1: hashicorp.consul.hcp.v2.MetricsConfig + (*ProxyConfig)(nil), // 2: hashicorp.consul.hcp.v2.ProxyConfig + nil, // 3: hashicorp.consul.hcp.v2.MetricsConfig.LabelsEntry + (*HCPConfig)(nil), // 4: hashicorp.consul.hcp.v2.HCPConfig +} +var file_pbhcp_v2_telemetry_state_proto_depIdxs = []int32{ + 4, // 0: hashicorp.consul.hcp.v2.TelemetryState.hcp_config:type_name -> hashicorp.consul.hcp.v2.HCPConfig + 2, // 1: hashicorp.consul.hcp.v2.TelemetryState.proxy:type_name -> hashicorp.consul.hcp.v2.ProxyConfig + 1, // 2: hashicorp.consul.hcp.v2.TelemetryState.metrics:type_name -> hashicorp.consul.hcp.v2.MetricsConfig + 3, // 3: hashicorp.consul.hcp.v2.MetricsConfig.labels:type_name -> hashicorp.consul.hcp.v2.MetricsConfig.LabelsEntry + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_pbhcp_v2_telemetry_state_proto_init() } +func file_pbhcp_v2_telemetry_state_proto_init() { + if File_pbhcp_v2_telemetry_state_proto != nil { + return + } + file_pbhcp_v2_hcp_config_proto_init() + if !protoimpl.UnsafeEnabled { + file_pbhcp_v2_telemetry_state_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TelemetryState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbhcp_v2_telemetry_state_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricsConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbhcp_v2_telemetry_state_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ProxyConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pbhcp_v2_telemetry_state_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbhcp_v2_telemetry_state_proto_goTypes, + DependencyIndexes: file_pbhcp_v2_telemetry_state_proto_depIdxs, + MessageInfos: file_pbhcp_v2_telemetry_state_proto_msgTypes, + }.Build() + File_pbhcp_v2_telemetry_state_proto = out.File + file_pbhcp_v2_telemetry_state_proto_rawDesc = nil + file_pbhcp_v2_telemetry_state_proto_goTypes = nil + file_pbhcp_v2_telemetry_state_proto_depIdxs = nil +} diff --git a/proto-public/pbhcp/v2/telemetry_state.proto b/proto-public/pbhcp/v2/telemetry_state.proto new file mode 100644 index 000000000000..bc9521a5ffd5 --- /dev/null +++ b/proto-public/pbhcp/v2/telemetry_state.proto @@ -0,0 +1,55 @@ +syntax = "proto3"; + +package hashicorp.consul.hcp.v2; + +import "pbhcp/v2/hcp_config.proto"; +import "pbresource/annotations.proto"; + +// TelemetryState describes configuration required to forward telemetry to the HashiCorp Cloud Platform. +// This resource is managed internally and is only written if the cluster is linked to HCP. Any +// manual changes to the resource will be reconciled and overwritten with the internally computed +// state. +message TelemetryState { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_CLUSTER}; + + // ResourceId is the identifier for the cluster linked with HCP. + string resource_id = 1; + + // ClientId is the oauth client identifier for cluster. + // This client has capabilities limited to writing telemetry data for this cluster. + string client_id = 2; + + // ClientSecret is the oauth secret used to authenticate requests to send telemetry data to HCP. + string client_secret = 3; + + HCPConfig hcp_config = 4; + ProxyConfig proxy = 5; + MetricsConfig metrics = 6; +} + +// MetricsConfig configures metric specific collection details +message MetricsConfig { + // Endpoint is the HTTPS address and path to forward metrics to + string endpoint = 1; + + // IncludeList contains patterns to match against metric names. Only matched metrics are forwarded. + repeated string include_list = 2; + + // Labels contains key value pairs that are associated with all metrics collected and fowarded. + map labels = 3; + + // Disabled toggles metric forwarding. If true, metric forwarding will stop until disabled is set to false. + bool disabled = 4; +} + +// ProxyConfig describes configuration for forwarding requests through an http proxy +message ProxyConfig { + // HttpProxy configures the http proxy to use for HTTP (non-TLS) requests. + string http_proxy = 1; + + // HttpsProxy configures the http proxy to use for HTTPS (TLS) requests. + string https_proxy = 2; + + // NoProxy can be configured to include domains which should NOT be forwarded through the configured http proxy + repeated string no_proxy = 3; +} diff --git a/proto-public/pbhcp/v2/telemetry_state_deepcopy.gen.go b/proto-public/pbhcp/v2/telemetry_state_deepcopy.gen.go new file mode 100644 index 000000000000..7d71330de6a9 --- /dev/null +++ b/proto-public/pbhcp/v2/telemetry_state_deepcopy.gen.go @@ -0,0 +1,69 @@ +// Code generated by protoc-gen-deepcopy. DO NOT EDIT. +package hcpv2 + +import ( + proto "google.golang.org/protobuf/proto" +) + +// DeepCopyInto supports using TelemetryState within kubernetes types, where deepcopy-gen is used. +func (in *TelemetryState) DeepCopyInto(out *TelemetryState) { + proto.Reset(out) + proto.Merge(out, proto.Clone(in)) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TelemetryState. Required by controller-gen. +func (in *TelemetryState) DeepCopy() *TelemetryState { + if in == nil { + return nil + } + out := new(TelemetryState) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TelemetryState. Required by controller-gen. +func (in *TelemetryState) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using MetricsConfig within kubernetes types, where deepcopy-gen is used. +func (in *MetricsConfig) DeepCopyInto(out *MetricsConfig) { + proto.Reset(out) + proto.Merge(out, proto.Clone(in)) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricsConfig. Required by controller-gen. +func (in *MetricsConfig) DeepCopy() *MetricsConfig { + if in == nil { + return nil + } + out := new(MetricsConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new MetricsConfig. Required by controller-gen. +func (in *MetricsConfig) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using ProxyConfig within kubernetes types, where deepcopy-gen is used. +func (in *ProxyConfig) DeepCopyInto(out *ProxyConfig) { + proto.Reset(out) + proto.Merge(out, proto.Clone(in)) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyConfig. Required by controller-gen. +func (in *ProxyConfig) DeepCopy() *ProxyConfig { + if in == nil { + return nil + } + out := new(ProxyConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ProxyConfig. Required by controller-gen. +func (in *ProxyConfig) DeepCopyInterface() interface{} { + return in.DeepCopy() +} diff --git a/proto-public/pbhcp/v2/telemetry_state_json.gen.go b/proto-public/pbhcp/v2/telemetry_state_json.gen.go new file mode 100644 index 000000000000..a07647002fb3 --- /dev/null +++ b/proto-public/pbhcp/v2/telemetry_state_json.gen.go @@ -0,0 +1,44 @@ +// Code generated by protoc-json-shim. DO NOT EDIT. +package hcpv2 + +import ( + protojson "google.golang.org/protobuf/encoding/protojson" +) + +// MarshalJSON is a custom marshaler for TelemetryState +func (this *TelemetryState) MarshalJSON() ([]byte, error) { + str, err := TelemetryStateMarshaler.Marshal(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for TelemetryState +func (this *TelemetryState) UnmarshalJSON(b []byte) error { + return TelemetryStateUnmarshaler.Unmarshal(b, this) +} + +// MarshalJSON is a custom marshaler for MetricsConfig +func (this *MetricsConfig) MarshalJSON() ([]byte, error) { + str, err := TelemetryStateMarshaler.Marshal(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for MetricsConfig +func (this *MetricsConfig) UnmarshalJSON(b []byte) error { + return TelemetryStateUnmarshaler.Unmarshal(b, this) +} + +// MarshalJSON is a custom marshaler for ProxyConfig +func (this *ProxyConfig) MarshalJSON() ([]byte, error) { + str, err := TelemetryStateMarshaler.Marshal(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for ProxyConfig +func (this *ProxyConfig) UnmarshalJSON(b []byte) error { + return TelemetryStateUnmarshaler.Unmarshal(b, this) +} + +var ( + TelemetryStateMarshaler = &protojson.MarshalOptions{} + TelemetryStateUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} +) diff --git a/proto-public/pbmesh/v2beta1/common.pb.binary.go b/proto-public/pbmesh/v2beta1/common.pb.binary.go deleted file mode 100644 index eb62aa3358e3..000000000000 --- a/proto-public/pbmesh/v2beta1/common.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/common.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ParentReference) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ParentReference) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *BackendReference) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *BackendReference) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/common.pb.go b/proto-public/pbmesh/v2beta1/common.pb.go deleted file mode 100644 index c960d7c92388..000000000000 --- a/proto-public/pbmesh/v2beta1/common.pb.go +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/common.proto - -package meshv2beta1 - -import ( - pbresource "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// NOTE: roughly equivalent to structs.ResourceReference -type ParentReference struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // For east/west configuration, this should point to a Service. - // For north/south it should point to a Gateway. - Ref *pbresource.Reference `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` - // For east/west this is the name of the Consul Service port to direct traffic to - // or empty to imply all. - // For north/south this is TBD. - Port string `protobuf:"bytes,2,opt,name=port,proto3" json:"port,omitempty"` -} - -func (x *ParentReference) Reset() { - *x = ParentReference{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_common_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ParentReference) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ParentReference) ProtoMessage() {} - -func (x *ParentReference) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_common_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ParentReference.ProtoReflect.Descriptor instead. -func (*ParentReference) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_common_proto_rawDescGZIP(), []int{0} -} - -func (x *ParentReference) GetRef() *pbresource.Reference { - if x != nil { - return x.Ref - } - return nil -} - -func (x *ParentReference) GetPort() string { - if x != nil { - return x.Port - } - return "" -} - -type BackendReference struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // For east/west configuration, this should point to a Service. - Ref *pbresource.Reference `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` - // For east/west this is the name of the Consul Service port to direct traffic to - // or empty to imply using the same value as the parent ref. - // - // For north/south this is TBD. - Port string `protobuf:"bytes,2,opt,name=port,proto3" json:"port,omitempty"` - Datacenter string `protobuf:"bytes,3,opt,name=datacenter,proto3" json:"datacenter,omitempty"` -} - -func (x *BackendReference) Reset() { - *x = BackendReference{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_common_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BackendReference) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BackendReference) ProtoMessage() {} - -func (x *BackendReference) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_common_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BackendReference.ProtoReflect.Descriptor instead. -func (*BackendReference) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_common_proto_rawDescGZIP(), []int{1} -} - -func (x *BackendReference) GetRef() *pbresource.Reference { - if x != nil { - return x.Ref - } - return nil -} - -func (x *BackendReference) GetPort() string { - if x != nil { - return x.Port - } - return "" -} - -func (x *BackendReference) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - -var File_pbmesh_v2beta1_common_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_common_proto_rawDesc = []byte{ - 0x0a, 0x1b, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x19, 0x70, 0x62, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5d, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x03, 0x72, 0x65, - 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x03, 0x72, - 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x7e, 0x0a, 0x10, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, - 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x03, 0x72, 0x65, - 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x03, 0x72, - 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, - 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, - 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x42, 0x8c, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0b, 0x43, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_common_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_common_proto_rawDescData = file_pbmesh_v2beta1_common_proto_rawDesc -) - -func file_pbmesh_v2beta1_common_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_common_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_common_proto_rawDescData) - }) - return file_pbmesh_v2beta1_common_proto_rawDescData -} - -var file_pbmesh_v2beta1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbmesh_v2beta1_common_proto_goTypes = []interface{}{ - (*ParentReference)(nil), // 0: hashicorp.consul.mesh.v2beta1.ParentReference - (*BackendReference)(nil), // 1: hashicorp.consul.mesh.v2beta1.BackendReference - (*pbresource.Reference)(nil), // 2: hashicorp.consul.resource.Reference -} -var file_pbmesh_v2beta1_common_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.mesh.v2beta1.ParentReference.ref:type_name -> hashicorp.consul.resource.Reference - 2, // 1: hashicorp.consul.mesh.v2beta1.BackendReference.ref:type_name -> hashicorp.consul.resource.Reference - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_common_proto_init() } -func file_pbmesh_v2beta1_common_proto_init() { - if File_pbmesh_v2beta1_common_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_common_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ParentReference); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_common_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BackendReference); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_common_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_common_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_common_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_common_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_common_proto = out.File - file_pbmesh_v2beta1_common_proto_rawDesc = nil - file_pbmesh_v2beta1_common_proto_goTypes = nil - file_pbmesh_v2beta1_common_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/common.proto b/proto-public/pbmesh/v2beta1/common.proto deleted file mode 100644 index 02ab5de3400d..000000000000 --- a/proto-public/pbmesh/v2beta1/common.proto +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "pbresource/resource.proto"; - -// NOTE: roughly equivalent to structs.ResourceReference -message ParentReference { - // For east/west configuration, this should point to a Service. - // For north/south it should point to a Gateway. - hashicorp.consul.resource.Reference ref = 1; - - // For east/west this is the name of the Consul Service port to direct traffic to - // or empty to imply all. - // For north/south this is TBD. - string port = 2; -} - -message BackendReference { - // For east/west configuration, this should point to a Service. - hashicorp.consul.resource.Reference ref = 1; - - // For east/west this is the name of the Consul Service port to direct traffic to - // or empty to imply using the same value as the parent ref. - // - // For north/south this is TBD. - string port = 2; - string datacenter = 3; -} diff --git a/proto-public/pbmesh/v2beta1/common_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/common_deepcopy.gen.go deleted file mode 100644 index f9aa662c4182..000000000000 --- a/proto-public/pbmesh/v2beta1/common_deepcopy.gen.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ParentReference within kubernetes types, where deepcopy-gen is used. -func (in *ParentReference) DeepCopyInto(out *ParentReference) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParentReference. Required by controller-gen. -func (in *ParentReference) DeepCopy() *ParentReference { - if in == nil { - return nil - } - out := new(ParentReference) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ParentReference. Required by controller-gen. -func (in *ParentReference) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using BackendReference within kubernetes types, where deepcopy-gen is used. -func (in *BackendReference) DeepCopyInto(out *BackendReference) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendReference. Required by controller-gen. -func (in *BackendReference) DeepCopy() *BackendReference { - if in == nil { - return nil - } - out := new(BackendReference) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new BackendReference. Required by controller-gen. -func (in *BackendReference) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/common_json.gen.go b/proto-public/pbmesh/v2beta1/common_json.gen.go deleted file mode 100644 index f5bc4a962703..000000000000 --- a/proto-public/pbmesh/v2beta1/common_json.gen.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ParentReference -func (this *ParentReference) MarshalJSON() ([]byte, error) { - str, err := CommonMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ParentReference -func (this *ParentReference) UnmarshalJSON(b []byte) error { - return CommonUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for BackendReference -func (this *BackendReference) MarshalJSON() ([]byte, error) { - str, err := CommonMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for BackendReference -func (this *BackendReference) UnmarshalJSON(b []byte) error { - return CommonUnmarshaler.Unmarshal(b, this) -} - -var ( - CommonMarshaler = &protojson.MarshalOptions{} - CommonUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/computed_explicit_destinations.pb.binary.go b/proto-public/pbmesh/v2beta1/computed_explicit_destinations.pb.binary.go deleted file mode 100644 index d9aab9ad3733..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_explicit_destinations.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/computed_explicit_destinations.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedExplicitDestinations) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedExplicitDestinations) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/computed_explicit_destinations.pb.go b/proto-public/pbmesh/v2beta1/computed_explicit_destinations.pb.go deleted file mode 100644 index 407fd7d31d41..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_explicit_destinations.pb.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/computed_explicit_destinations.proto - -package meshv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ComputedExplicitDestinations struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // destinations is the list of explicit destinations to define for the selected workloads. - Destinations []*Destination `protobuf:"bytes,1,rep,name=destinations,proto3" json:"destinations,omitempty"` -} - -func (x *ComputedExplicitDestinations) Reset() { - *x = ComputedExplicitDestinations{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_explicit_destinations_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedExplicitDestinations) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedExplicitDestinations) ProtoMessage() {} - -func (x *ComputedExplicitDestinations) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_explicit_destinations_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedExplicitDestinations.ProtoReflect.Descriptor instead. -func (*ComputedExplicitDestinations) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_explicit_destinations_proto_rawDescGZIP(), []int{0} -} - -func (x *ComputedExplicitDestinations) GetDestinations() []*Destination { - if x != nil { - return x.Destinations - } - return nil -} - -var File_pbmesh_v2beta1_computed_explicit_destinations_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_computed_explicit_destinations_proto_rawDesc = []byte{ - 0x0a, 0x33, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, - 0x69, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x1a, 0x21, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x76, 0x0a, 0x1c, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x45, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4e, 0x0a, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x42, 0xa2, 0x02, - 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x42, 0x21, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, - 0x6c, 0x69, 0x63, 0x69, 0x74, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, - 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_computed_explicit_destinations_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_computed_explicit_destinations_proto_rawDescData = file_pbmesh_v2beta1_computed_explicit_destinations_proto_rawDesc -) - -func file_pbmesh_v2beta1_computed_explicit_destinations_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_computed_explicit_destinations_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_computed_explicit_destinations_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_computed_explicit_destinations_proto_rawDescData) - }) - return file_pbmesh_v2beta1_computed_explicit_destinations_proto_rawDescData -} - -var file_pbmesh_v2beta1_computed_explicit_destinations_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmesh_v2beta1_computed_explicit_destinations_proto_goTypes = []interface{}{ - (*ComputedExplicitDestinations)(nil), // 0: hashicorp.consul.mesh.v2beta1.ComputedExplicitDestinations - (*Destination)(nil), // 1: hashicorp.consul.mesh.v2beta1.Destination -} -var file_pbmesh_v2beta1_computed_explicit_destinations_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.mesh.v2beta1.ComputedExplicitDestinations.destinations:type_name -> hashicorp.consul.mesh.v2beta1.Destination - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_computed_explicit_destinations_proto_init() } -func file_pbmesh_v2beta1_computed_explicit_destinations_proto_init() { - if File_pbmesh_v2beta1_computed_explicit_destinations_proto != nil { - return - } - file_pbmesh_v2beta1_destinations_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_computed_explicit_destinations_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedExplicitDestinations); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_computed_explicit_destinations_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_computed_explicit_destinations_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_computed_explicit_destinations_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_computed_explicit_destinations_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_computed_explicit_destinations_proto = out.File - file_pbmesh_v2beta1_computed_explicit_destinations_proto_rawDesc = nil - file_pbmesh_v2beta1_computed_explicit_destinations_proto_goTypes = nil - file_pbmesh_v2beta1_computed_explicit_destinations_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/computed_explicit_destinations.proto b/proto-public/pbmesh/v2beta1/computed_explicit_destinations.proto deleted file mode 100644 index f3e84c484898..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_explicit_destinations.proto +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "pbmesh/v2beta1/destinations.proto"; -import "pbresource/annotations.proto"; - -message ComputedExplicitDestinations { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // destinations is the list of explicit destinations to define for the selected workloads. - repeated Destination destinations = 1; -} diff --git a/proto-public/pbmesh/v2beta1/computed_explicit_destinations_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/computed_explicit_destinations_deepcopy.gen.go deleted file mode 100644 index 7a14e57454f2..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_explicit_destinations_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ComputedExplicitDestinations within kubernetes types, where deepcopy-gen is used. -func (in *ComputedExplicitDestinations) DeepCopyInto(out *ComputedExplicitDestinations) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedExplicitDestinations. Required by controller-gen. -func (in *ComputedExplicitDestinations) DeepCopy() *ComputedExplicitDestinations { - if in == nil { - return nil - } - out := new(ComputedExplicitDestinations) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedExplicitDestinations. Required by controller-gen. -func (in *ComputedExplicitDestinations) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/computed_explicit_destinations_json.gen.go b/proto-public/pbmesh/v2beta1/computed_explicit_destinations_json.gen.go deleted file mode 100644 index d483944a11da..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_explicit_destinations_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ComputedExplicitDestinations -func (this *ComputedExplicitDestinations) MarshalJSON() ([]byte, error) { - str, err := ComputedExplicitDestinationsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedExplicitDestinations -func (this *ComputedExplicitDestinations) UnmarshalJSON(b []byte) error { - return ComputedExplicitDestinationsUnmarshaler.Unmarshal(b, this) -} - -var ( - ComputedExplicitDestinationsMarshaler = &protojson.MarshalOptions{} - ComputedExplicitDestinationsUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/computed_proxy_configuration.pb.binary.go b/proto-public/pbmesh/v2beta1/computed_proxy_configuration.pb.binary.go deleted file mode 100644 index 25fe0e577bc4..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_proxy_configuration.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/computed_proxy_configuration.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedProxyConfiguration) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedProxyConfiguration) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/computed_proxy_configuration.pb.go b/proto-public/pbmesh/v2beta1/computed_proxy_configuration.pb.go deleted file mode 100644 index a35764664e3c..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_proxy_configuration.pb.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/computed_proxy_configuration.proto - -package meshv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ComputedProxyConfiguration struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // dynamic_config is the configuration that could be changed - // dynamically (i.e. without needing restart). - DynamicConfig *DynamicConfig `protobuf:"bytes,2,opt,name=dynamic_config,json=dynamicConfig,proto3" json:"dynamic_config,omitempty"` - // bootstrap_config is the configuration that requires proxies - // to be restarted to be applied. - BootstrapConfig *BootstrapConfig `protobuf:"bytes,3,opt,name=bootstrap_config,json=bootstrapConfig,proto3" json:"bootstrap_config,omitempty"` -} - -func (x *ComputedProxyConfiguration) Reset() { - *x = ComputedProxyConfiguration{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_proxy_configuration_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedProxyConfiguration) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedProxyConfiguration) ProtoMessage() {} - -func (x *ComputedProxyConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_proxy_configuration_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedProxyConfiguration.ProtoReflect.Descriptor instead. -func (*ComputedProxyConfiguration) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_proxy_configuration_proto_rawDescGZIP(), []int{0} -} - -func (x *ComputedProxyConfiguration) GetDynamicConfig() *DynamicConfig { - if x != nil { - return x.DynamicConfig - } - return nil -} - -func (x *ComputedProxyConfiguration) GetBootstrapConfig() *BootstrapConfig { - if x != nil { - return x.BootstrapConfig - } - return nil -} - -var File_pbmesh_v2beta1_computed_proxy_configuration_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_computed_proxy_configuration_proto_rawDesc = []byte{ - 0x0a, 0x31, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x1a, 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd4, 0x01, 0x0a, 0x1a, 0x43, - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x53, 0x0a, 0x0e, 0x64, 0x79, 0x6e, - 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x0d, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x59, - 0x0a, 0x10, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, - 0x61, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0f, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, - 0x72, 0x61, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, - 0x03, 0x42, 0xa0, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x1f, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, - 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_computed_proxy_configuration_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_computed_proxy_configuration_proto_rawDescData = file_pbmesh_v2beta1_computed_proxy_configuration_proto_rawDesc -) - -func file_pbmesh_v2beta1_computed_proxy_configuration_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_computed_proxy_configuration_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_computed_proxy_configuration_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_computed_proxy_configuration_proto_rawDescData) - }) - return file_pbmesh_v2beta1_computed_proxy_configuration_proto_rawDescData -} - -var file_pbmesh_v2beta1_computed_proxy_configuration_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmesh_v2beta1_computed_proxy_configuration_proto_goTypes = []interface{}{ - (*ComputedProxyConfiguration)(nil), // 0: hashicorp.consul.mesh.v2beta1.ComputedProxyConfiguration - (*DynamicConfig)(nil), // 1: hashicorp.consul.mesh.v2beta1.DynamicConfig - (*BootstrapConfig)(nil), // 2: hashicorp.consul.mesh.v2beta1.BootstrapConfig -} -var file_pbmesh_v2beta1_computed_proxy_configuration_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.mesh.v2beta1.ComputedProxyConfiguration.dynamic_config:type_name -> hashicorp.consul.mesh.v2beta1.DynamicConfig - 2, // 1: hashicorp.consul.mesh.v2beta1.ComputedProxyConfiguration.bootstrap_config:type_name -> hashicorp.consul.mesh.v2beta1.BootstrapConfig - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_computed_proxy_configuration_proto_init() } -func file_pbmesh_v2beta1_computed_proxy_configuration_proto_init() { - if File_pbmesh_v2beta1_computed_proxy_configuration_proto != nil { - return - } - file_pbmesh_v2beta1_proxy_configuration_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_computed_proxy_configuration_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedProxyConfiguration); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_computed_proxy_configuration_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_computed_proxy_configuration_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_computed_proxy_configuration_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_computed_proxy_configuration_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_computed_proxy_configuration_proto = out.File - file_pbmesh_v2beta1_computed_proxy_configuration_proto_rawDesc = nil - file_pbmesh_v2beta1_computed_proxy_configuration_proto_goTypes = nil - file_pbmesh_v2beta1_computed_proxy_configuration_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/computed_proxy_configuration.proto b/proto-public/pbmesh/v2beta1/computed_proxy_configuration.proto deleted file mode 100644 index 52ce0c6ad562..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_proxy_configuration.proto +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "pbmesh/v2beta1/proxy_configuration.proto"; -import "pbresource/annotations.proto"; - -message ComputedProxyConfiguration { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // dynamic_config is the configuration that could be changed - // dynamically (i.e. without needing restart). - DynamicConfig dynamic_config = 2; - - // bootstrap_config is the configuration that requires proxies - // to be restarted to be applied. - BootstrapConfig bootstrap_config = 3; -} diff --git a/proto-public/pbmesh/v2beta1/computed_proxy_configuration_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/computed_proxy_configuration_deepcopy.gen.go deleted file mode 100644 index d6eb5723030b..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_proxy_configuration_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ComputedProxyConfiguration within kubernetes types, where deepcopy-gen is used. -func (in *ComputedProxyConfiguration) DeepCopyInto(out *ComputedProxyConfiguration) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedProxyConfiguration. Required by controller-gen. -func (in *ComputedProxyConfiguration) DeepCopy() *ComputedProxyConfiguration { - if in == nil { - return nil - } - out := new(ComputedProxyConfiguration) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedProxyConfiguration. Required by controller-gen. -func (in *ComputedProxyConfiguration) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/computed_proxy_configuration_json.gen.go b/proto-public/pbmesh/v2beta1/computed_proxy_configuration_json.gen.go deleted file mode 100644 index 614a75c36577..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_proxy_configuration_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ComputedProxyConfiguration -func (this *ComputedProxyConfiguration) MarshalJSON() ([]byte, error) { - str, err := ComputedProxyConfigurationMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedProxyConfiguration -func (this *ComputedProxyConfiguration) UnmarshalJSON(b []byte) error { - return ComputedProxyConfigurationUnmarshaler.Unmarshal(b, this) -} - -var ( - ComputedProxyConfigurationMarshaler = &protojson.MarshalOptions{} - ComputedProxyConfigurationUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/computed_routes.pb.binary.go b/proto-public/pbmesh/v2beta1/computed_routes.pb.binary.go deleted file mode 100644 index f0f24154692e..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_routes.pb.binary.go +++ /dev/null @@ -1,148 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/computed_routes.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedRoutes) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedRoutes) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedPortRoutes) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedPortRoutes) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedHTTPRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedHTTPRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedHTTPRouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedHTTPRouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedHTTPBackendRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedHTTPBackendRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedGRPCRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedGRPCRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedGRPCRouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedGRPCRouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedGRPCBackendRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedGRPCBackendRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedTCPRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedTCPRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedTCPRouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedTCPRouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedTCPBackendRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedTCPBackendRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *BackendTargetDetails) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *BackendTargetDetails) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedFailoverConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedFailoverConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedFailoverDestination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedFailoverDestination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/computed_routes.pb.go b/proto-public/pbmesh/v2beta1/computed_routes.pb.go deleted file mode 100644 index 612da01c249b..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_routes.pb.go +++ /dev/null @@ -1,1635 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/computed_routes.proto - -package meshv2beta1 - -import ( - v2beta1 "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbresource "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=BACKEND_TARGET_DETAILS_TYPE_UNSPECIFIED;BACKEND_TARGET_DETAILS_TYPE_DIRECT;BACKEND_TARGET_DETAILS_TYPE_INDIRECT -// +kubebuilder:validation:Type=string -type BackendTargetDetailsType int32 - -const ( - BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_UNSPECIFIED BackendTargetDetailsType = 0 - // Direct means that the target is directly routable from a route. This does - // not mean that the target is not also indirect though. - BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT BackendTargetDetailsType = 1 - // Indirect means that the target is not directly routable from a route. - // - // One example would be for a FailoverPolicy destination. - BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_INDIRECT BackendTargetDetailsType = 2 -) - -// Enum value maps for BackendTargetDetailsType. -var ( - BackendTargetDetailsType_name = map[int32]string{ - 0: "BACKEND_TARGET_DETAILS_TYPE_UNSPECIFIED", - 1: "BACKEND_TARGET_DETAILS_TYPE_DIRECT", - 2: "BACKEND_TARGET_DETAILS_TYPE_INDIRECT", - } - BackendTargetDetailsType_value = map[string]int32{ - "BACKEND_TARGET_DETAILS_TYPE_UNSPECIFIED": 0, - "BACKEND_TARGET_DETAILS_TYPE_DIRECT": 1, - "BACKEND_TARGET_DETAILS_TYPE_INDIRECT": 2, - } -) - -func (x BackendTargetDetailsType) Enum() *BackendTargetDetailsType { - p := new(BackendTargetDetailsType) - *p = x - return p -} - -func (x BackendTargetDetailsType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (BackendTargetDetailsType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_computed_routes_proto_enumTypes[0].Descriptor() -} - -func (BackendTargetDetailsType) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_computed_routes_proto_enumTypes[0] -} - -func (x BackendTargetDetailsType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use BackendTargetDetailsType.Descriptor instead. -func (BackendTargetDetailsType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{0} -} - -// This is a Resource type. -type ComputedRoutes struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PortedConfigs map[string]*ComputedPortRoutes `protobuf:"bytes,1,rep,name=ported_configs,json=portedConfigs,proto3" json:"ported_configs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // BoundReferences is a slice of mixed type references of resources that were - // involved in the formulation of this resource. - BoundReferences []*pbresource.Reference `protobuf:"bytes,2,rep,name=bound_references,json=boundReferences,proto3" json:"bound_references,omitempty"` -} - -func (x *ComputedRoutes) Reset() { - *x = ComputedRoutes{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedRoutes) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedRoutes) ProtoMessage() {} - -func (x *ComputedRoutes) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedRoutes.ProtoReflect.Descriptor instead. -func (*ComputedRoutes) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{0} -} - -func (x *ComputedRoutes) GetPortedConfigs() map[string]*ComputedPortRoutes { - if x != nil { - return x.PortedConfigs - } - return nil -} - -func (x *ComputedRoutes) GetBoundReferences() []*pbresource.Reference { - if x != nil { - return x.BoundReferences - } - return nil -} - -type ComputedPortRoutes struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Config: - // - // *ComputedPortRoutes_Http - // *ComputedPortRoutes_Grpc - // *ComputedPortRoutes_Tcp - Config isComputedPortRoutes_Config `protobuf_oneof:"config"` - UsingDefaultConfig bool `protobuf:"varint,4,opt,name=using_default_config,json=usingDefaultConfig,proto3" json:"using_default_config,omitempty"` // TODO - ParentRef *ParentReference `protobuf:"bytes,5,opt,name=parent_ref,json=parentRef,proto3" json:"parent_ref,omitempty"` - // Protocol is the ParentRef.Port's protocol. It is based on the value in the - // Service object, but may differ depending upon which xRoutes are actually - // in use. - Protocol v2beta1.Protocol `protobuf:"varint,6,opt,name=protocol,proto3,enum=hashicorp.consul.catalog.v2beta1.Protocol" json:"protocol,omitempty"` - // map key is an opaque string; like disco chain target name - Targets map[string]*BackendTargetDetails `protobuf:"bytes,7,rep,name=targets,proto3" json:"targets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *ComputedPortRoutes) Reset() { - *x = ComputedPortRoutes{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedPortRoutes) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedPortRoutes) ProtoMessage() {} - -func (x *ComputedPortRoutes) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedPortRoutes.ProtoReflect.Descriptor instead. -func (*ComputedPortRoutes) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{1} -} - -func (m *ComputedPortRoutes) GetConfig() isComputedPortRoutes_Config { - if m != nil { - return m.Config - } - return nil -} - -func (x *ComputedPortRoutes) GetHttp() *ComputedHTTPRoute { - if x, ok := x.GetConfig().(*ComputedPortRoutes_Http); ok { - return x.Http - } - return nil -} - -func (x *ComputedPortRoutes) GetGrpc() *ComputedGRPCRoute { - if x, ok := x.GetConfig().(*ComputedPortRoutes_Grpc); ok { - return x.Grpc - } - return nil -} - -func (x *ComputedPortRoutes) GetTcp() *ComputedTCPRoute { - if x, ok := x.GetConfig().(*ComputedPortRoutes_Tcp); ok { - return x.Tcp - } - return nil -} - -func (x *ComputedPortRoutes) GetUsingDefaultConfig() bool { - if x != nil { - return x.UsingDefaultConfig - } - return false -} - -func (x *ComputedPortRoutes) GetParentRef() *ParentReference { - if x != nil { - return x.ParentRef - } - return nil -} - -func (x *ComputedPortRoutes) GetProtocol() v2beta1.Protocol { - if x != nil { - return x.Protocol - } - return v2beta1.Protocol(0) -} - -func (x *ComputedPortRoutes) GetTargets() map[string]*BackendTargetDetails { - if x != nil { - return x.Targets - } - return nil -} - -type isComputedPortRoutes_Config interface { - isComputedPortRoutes_Config() -} - -type ComputedPortRoutes_Http struct { - Http *ComputedHTTPRoute `protobuf:"bytes,1,opt,name=http,proto3,oneof"` -} - -type ComputedPortRoutes_Grpc struct { - Grpc *ComputedGRPCRoute `protobuf:"bytes,2,opt,name=grpc,proto3,oneof"` -} - -type ComputedPortRoutes_Tcp struct { - Tcp *ComputedTCPRoute `protobuf:"bytes,3,opt,name=tcp,proto3,oneof"` -} - -func (*ComputedPortRoutes_Http) isComputedPortRoutes_Config() {} - -func (*ComputedPortRoutes_Grpc) isComputedPortRoutes_Config() {} - -func (*ComputedPortRoutes_Tcp) isComputedPortRoutes_Config() {} - -type ComputedHTTPRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Rules []*ComputedHTTPRouteRule `protobuf:"bytes,2,rep,name=rules,proto3" json:"rules,omitempty"` -} - -func (x *ComputedHTTPRoute) Reset() { - *x = ComputedHTTPRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedHTTPRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedHTTPRoute) ProtoMessage() {} - -func (x *ComputedHTTPRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedHTTPRoute.ProtoReflect.Descriptor instead. -func (*ComputedHTTPRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{2} -} - -func (x *ComputedHTTPRoute) GetRules() []*ComputedHTTPRouteRule { - if x != nil { - return x.Rules - } - return nil -} - -type ComputedHTTPRouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Matches []*HTTPRouteMatch `protobuf:"bytes,1,rep,name=matches,proto3" json:"matches,omitempty"` - Filters []*HTTPRouteFilter `protobuf:"bytes,2,rep,name=filters,proto3" json:"filters,omitempty"` - BackendRefs []*ComputedHTTPBackendRef `protobuf:"bytes,3,rep,name=backend_refs,json=backendRefs,proto3" json:"backend_refs,omitempty"` - Timeouts *HTTPRouteTimeouts `protobuf:"bytes,4,opt,name=timeouts,proto3" json:"timeouts,omitempty"` - Retries *HTTPRouteRetries `protobuf:"bytes,5,opt,name=retries,proto3" json:"retries,omitempty"` -} - -func (x *ComputedHTTPRouteRule) Reset() { - *x = ComputedHTTPRouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedHTTPRouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedHTTPRouteRule) ProtoMessage() {} - -func (x *ComputedHTTPRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedHTTPRouteRule.ProtoReflect.Descriptor instead. -func (*ComputedHTTPRouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{3} -} - -func (x *ComputedHTTPRouteRule) GetMatches() []*HTTPRouteMatch { - if x != nil { - return x.Matches - } - return nil -} - -func (x *ComputedHTTPRouteRule) GetFilters() []*HTTPRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -func (x *ComputedHTTPRouteRule) GetBackendRefs() []*ComputedHTTPBackendRef { - if x != nil { - return x.BackendRefs - } - return nil -} - -func (x *ComputedHTTPRouteRule) GetTimeouts() *HTTPRouteTimeouts { - if x != nil { - return x.Timeouts - } - return nil -} - -func (x *ComputedHTTPRouteRule) GetRetries() *HTTPRouteRetries { - if x != nil { - return x.Retries - } - return nil -} - -type ComputedHTTPBackendRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // BackendTarget indicates which key in the targets map provides - // the rest of the configuration. - // - // If this field is set to the empty string, or is the sentinel value - // "NULL-ROUTE" is an indication that all of the traffic destined for this - // backend reference should be null routed in a format appropriate for the - // protocol (i.e. for HTTP use 5xx). - BackendTarget string `protobuf:"bytes,1,opt,name=backend_target,json=backendTarget,proto3" json:"backend_target,omitempty"` - Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` - Filters []*HTTPRouteFilter `protobuf:"bytes,3,rep,name=filters,proto3" json:"filters,omitempty"` -} - -func (x *ComputedHTTPBackendRef) Reset() { - *x = ComputedHTTPBackendRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedHTTPBackendRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedHTTPBackendRef) ProtoMessage() {} - -func (x *ComputedHTTPBackendRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedHTTPBackendRef.ProtoReflect.Descriptor instead. -func (*ComputedHTTPBackendRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{4} -} - -func (x *ComputedHTTPBackendRef) GetBackendTarget() string { - if x != nil { - return x.BackendTarget - } - return "" -} - -func (x *ComputedHTTPBackendRef) GetWeight() uint32 { - if x != nil { - return x.Weight - } - return 0 -} - -func (x *ComputedHTTPBackendRef) GetFilters() []*HTTPRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -type ComputedGRPCRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Rules []*ComputedGRPCRouteRule `protobuf:"bytes,2,rep,name=rules,proto3" json:"rules,omitempty"` -} - -func (x *ComputedGRPCRoute) Reset() { - *x = ComputedGRPCRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedGRPCRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedGRPCRoute) ProtoMessage() {} - -func (x *ComputedGRPCRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedGRPCRoute.ProtoReflect.Descriptor instead. -func (*ComputedGRPCRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{5} -} - -func (x *ComputedGRPCRoute) GetRules() []*ComputedGRPCRouteRule { - if x != nil { - return x.Rules - } - return nil -} - -type ComputedGRPCRouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Matches []*GRPCRouteMatch `protobuf:"bytes,1,rep,name=matches,proto3" json:"matches,omitempty"` - Filters []*GRPCRouteFilter `protobuf:"bytes,2,rep,name=filters,proto3" json:"filters,omitempty"` - BackendRefs []*ComputedGRPCBackendRef `protobuf:"bytes,3,rep,name=backend_refs,json=backendRefs,proto3" json:"backend_refs,omitempty"` - Timeouts *HTTPRouteTimeouts `protobuf:"bytes,4,opt,name=timeouts,proto3" json:"timeouts,omitempty"` - Retries *HTTPRouteRetries `protobuf:"bytes,5,opt,name=retries,proto3" json:"retries,omitempty"` -} - -func (x *ComputedGRPCRouteRule) Reset() { - *x = ComputedGRPCRouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedGRPCRouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedGRPCRouteRule) ProtoMessage() {} - -func (x *ComputedGRPCRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedGRPCRouteRule.ProtoReflect.Descriptor instead. -func (*ComputedGRPCRouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{6} -} - -func (x *ComputedGRPCRouteRule) GetMatches() []*GRPCRouteMatch { - if x != nil { - return x.Matches - } - return nil -} - -func (x *ComputedGRPCRouteRule) GetFilters() []*GRPCRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -func (x *ComputedGRPCRouteRule) GetBackendRefs() []*ComputedGRPCBackendRef { - if x != nil { - return x.BackendRefs - } - return nil -} - -func (x *ComputedGRPCRouteRule) GetTimeouts() *HTTPRouteTimeouts { - if x != nil { - return x.Timeouts - } - return nil -} - -func (x *ComputedGRPCRouteRule) GetRetries() *HTTPRouteRetries { - if x != nil { - return x.Retries - } - return nil -} - -type ComputedGRPCBackendRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // BackendTarget indicates which key in the targets map provides - // the rest of the configuration. - // - // If this field is set to the empty string, or is the sentinel value - // "NULL-ROUTE" is an indication that all of the traffic destined for this - // backend reference should be null routed in a format appropriate for the - // protocol (i.e. for HTTP use 5xx). - BackendTarget string `protobuf:"bytes,1,opt,name=backend_target,json=backendTarget,proto3" json:"backend_target,omitempty"` - Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` - Filters []*GRPCRouteFilter `protobuf:"bytes,3,rep,name=filters,proto3" json:"filters,omitempty"` -} - -func (x *ComputedGRPCBackendRef) Reset() { - *x = ComputedGRPCBackendRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedGRPCBackendRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedGRPCBackendRef) ProtoMessage() {} - -func (x *ComputedGRPCBackendRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedGRPCBackendRef.ProtoReflect.Descriptor instead. -func (*ComputedGRPCBackendRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{7} -} - -func (x *ComputedGRPCBackendRef) GetBackendTarget() string { - if x != nil { - return x.BackendTarget - } - return "" -} - -func (x *ComputedGRPCBackendRef) GetWeight() uint32 { - if x != nil { - return x.Weight - } - return 0 -} - -func (x *ComputedGRPCBackendRef) GetFilters() []*GRPCRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -type ComputedTCPRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Rules []*ComputedTCPRouteRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` -} - -func (x *ComputedTCPRoute) Reset() { - *x = ComputedTCPRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedTCPRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedTCPRoute) ProtoMessage() {} - -func (x *ComputedTCPRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedTCPRoute.ProtoReflect.Descriptor instead. -func (*ComputedTCPRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{8} -} - -func (x *ComputedTCPRoute) GetRules() []*ComputedTCPRouteRule { - if x != nil { - return x.Rules - } - return nil -} - -type ComputedTCPRouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BackendRefs []*ComputedTCPBackendRef `protobuf:"bytes,1,rep,name=backend_refs,json=backendRefs,proto3" json:"backend_refs,omitempty"` -} - -func (x *ComputedTCPRouteRule) Reset() { - *x = ComputedTCPRouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedTCPRouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedTCPRouteRule) ProtoMessage() {} - -func (x *ComputedTCPRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedTCPRouteRule.ProtoReflect.Descriptor instead. -func (*ComputedTCPRouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{9} -} - -func (x *ComputedTCPRouteRule) GetBackendRefs() []*ComputedTCPBackendRef { - if x != nil { - return x.BackendRefs - } - return nil -} - -// TODO: look into smuggling the target through a different typeURL, or just skip in favor of letting the caller do their own lookups? -type ComputedTCPBackendRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // BackendTarget indicates which key in the targets map provides - // the rest of the configuration. - // - // If this field is set to the empty string, or is the sentinel value - // "NULL-ROUTE" is an indication that all of the traffic destined for this - // backend reference should be null routed in a format appropriate for the - // protocol (i.e. for HTTP use 5xx). - BackendTarget string `protobuf:"bytes,1,opt,name=backend_target,json=backendTarget,proto3" json:"backend_target,omitempty"` - Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` -} - -func (x *ComputedTCPBackendRef) Reset() { - *x = ComputedTCPBackendRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedTCPBackendRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedTCPBackendRef) ProtoMessage() {} - -func (x *ComputedTCPBackendRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedTCPBackendRef.ProtoReflect.Descriptor instead. -func (*ComputedTCPBackendRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{10} -} - -func (x *ComputedTCPBackendRef) GetBackendTarget() string { - if x != nil { - return x.BackendTarget - } - return "" -} - -func (x *ComputedTCPBackendRef) GetWeight() uint32 { - if x != nil { - return x.Weight - } - return 0 -} - -type BackendTargetDetails struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Type BackendTargetDetailsType `protobuf:"varint,1,opt,name=type,proto3,enum=hashicorp.consul.mesh.v2beta1.BackendTargetDetailsType" json:"type,omitempty"` - BackendRef *BackendReference `protobuf:"bytes,2,opt,name=backend_ref,json=backendRef,proto3" json:"backend_ref,omitempty"` - MeshPort string `protobuf:"bytes,3,opt,name=mesh_port,json=meshPort,proto3" json:"mesh_port,omitempty"` - FailoverConfig *ComputedFailoverConfig `protobuf:"bytes,4,opt,name=failover_config,json=failoverConfig,proto3" json:"failover_config,omitempty"` - DestinationConfig *DestinationConfig `protobuf:"bytes,5,opt,name=destination_config,json=destinationConfig,proto3" json:"destination_config,omitempty"` - // ServiceEndpointsID is not populated naturally and the field exists only for - // downstream consumers. - ServiceEndpointsId *pbresource.ID `protobuf:"bytes,21,opt,name=service_endpoints_id,json=serviceEndpointsId,proto3" json:"service_endpoints_id,omitempty"` - // ServiceEndpoints is not populated naturally and the field exists only for - // downstream consumers. - ServiceEndpoints *v2beta1.ServiceEndpoints `protobuf:"bytes,22,opt,name=service_endpoints,json=serviceEndpoints,proto3" json:"service_endpoints,omitempty"` - // IdentityRefs are not populated naturally and the field exists only for - // downstream consumers. - IdentityRefs []*pbresource.Reference `protobuf:"bytes,23,rep,name=identity_refs,json=identityRefs,proto3" json:"identity_refs,omitempty"` -} - -func (x *BackendTargetDetails) Reset() { - *x = BackendTargetDetails{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BackendTargetDetails) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BackendTargetDetails) ProtoMessage() {} - -func (x *BackendTargetDetails) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BackendTargetDetails.ProtoReflect.Descriptor instead. -func (*BackendTargetDetails) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{11} -} - -func (x *BackendTargetDetails) GetType() BackendTargetDetailsType { - if x != nil { - return x.Type - } - return BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_UNSPECIFIED -} - -func (x *BackendTargetDetails) GetBackendRef() *BackendReference { - if x != nil { - return x.BackendRef - } - return nil -} - -func (x *BackendTargetDetails) GetMeshPort() string { - if x != nil { - return x.MeshPort - } - return "" -} - -func (x *BackendTargetDetails) GetFailoverConfig() *ComputedFailoverConfig { - if x != nil { - return x.FailoverConfig - } - return nil -} - -func (x *BackendTargetDetails) GetDestinationConfig() *DestinationConfig { - if x != nil { - return x.DestinationConfig - } - return nil -} - -func (x *BackendTargetDetails) GetServiceEndpointsId() *pbresource.ID { - if x != nil { - return x.ServiceEndpointsId - } - return nil -} - -func (x *BackendTargetDetails) GetServiceEndpoints() *v2beta1.ServiceEndpoints { - if x != nil { - return x.ServiceEndpoints - } - return nil -} - -func (x *BackendTargetDetails) GetIdentityRefs() []*pbresource.Reference { - if x != nil { - return x.IdentityRefs - } - return nil -} - -type ComputedFailoverConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Destinations []*ComputedFailoverDestination `protobuf:"bytes,1,rep,name=destinations,proto3" json:"destinations,omitempty"` - Mode v2beta1.FailoverMode `protobuf:"varint,2,opt,name=mode,proto3,enum=hashicorp.consul.catalog.v2beta1.FailoverMode" json:"mode,omitempty"` - Regions []string `protobuf:"bytes,3,rep,name=regions,proto3" json:"regions,omitempty"` - // SamenessGroup specifies the sameness group to failover to. - SamenessGroup string `protobuf:"bytes,4,opt,name=sameness_group,json=samenessGroup,proto3" json:"sameness_group,omitempty"` -} - -func (x *ComputedFailoverConfig) Reset() { - *x = ComputedFailoverConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedFailoverConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedFailoverConfig) ProtoMessage() {} - -func (x *ComputedFailoverConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedFailoverConfig.ProtoReflect.Descriptor instead. -func (*ComputedFailoverConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{12} -} - -func (x *ComputedFailoverConfig) GetDestinations() []*ComputedFailoverDestination { - if x != nil { - return x.Destinations - } - return nil -} - -func (x *ComputedFailoverConfig) GetMode() v2beta1.FailoverMode { - if x != nil { - return x.Mode - } - return v2beta1.FailoverMode(0) -} - -func (x *ComputedFailoverConfig) GetRegions() []string { - if x != nil { - return x.Regions - } - return nil -} - -func (x *ComputedFailoverConfig) GetSamenessGroup() string { - if x != nil { - return x.SamenessGroup - } - return "" -} - -type ComputedFailoverDestination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // BackendTarget must be a Service. - BackendTarget string `protobuf:"bytes,1,opt,name=backend_target,json=backendTarget,proto3" json:"backend_target,omitempty"` -} - -func (x *ComputedFailoverDestination) Reset() { - *x = ComputedFailoverDestination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedFailoverDestination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedFailoverDestination) ProtoMessage() {} - -func (x *ComputedFailoverDestination) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_computed_routes_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedFailoverDestination.ProtoReflect.Descriptor instead. -func (*ComputedFailoverDestination) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP(), []int{13} -} - -func (x *ComputedFailoverDestination) GetBackendTarget() string { - if x != nil { - return x.BackendTarget - } - return "" -} - -var File_pbmesh_v2beta1_computed_routes_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_computed_routes_proto_rawDesc = []byte{ - 0x0a, 0x24, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x27, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, - 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, - 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x29, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x70, 0x62, 0x6d, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, - 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x1f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x1f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, - 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x28, 0x70, 0x62, - 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x68, 0x74, 0x74, - 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xc7, 0x02, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x73, 0x12, 0x67, 0x0a, 0x0e, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x65, 0x64, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x70, 0x6f, - 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x4f, 0x0a, 0x10, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0f, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x1a, 0x73, 0x0a, 0x12, - 0x50, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x47, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0x87, 0x05, 0x0a, 0x12, 0x43, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, - 0x12, 0x46, 0x0a, 0x04, 0x68, 0x74, 0x74, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x48, 0x00, 0x52, 0x04, 0x68, 0x74, 0x74, 0x70, 0x12, 0x46, 0x0a, 0x04, 0x67, 0x72, 0x70, 0x63, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, - 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x00, 0x52, 0x04, 0x67, 0x72, 0x70, 0x63, - 0x12, 0x43, 0x0a, 0x03, 0x74, 0x63, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x00, - 0x52, 0x03, 0x74, 0x63, 0x70, 0x12, 0x30, 0x0a, 0x14, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x12, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4d, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x09, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x12, 0x46, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x58, - 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x73, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x1a, 0x6f, 0x0a, 0x0c, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x49, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, - 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x22, 0x65, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x48, - 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4a, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, - 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, - 0x75, 0x6c, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x9d, 0x03, 0x0a, 0x15, 0x43, - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x52, 0x75, 0x6c, 0x65, 0x12, 0x47, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x48, 0x0a, - 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, - 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, - 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x58, 0x0a, 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x65, - 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, - 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, - 0x73, 0x12, 0x4c, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x12, - 0x49, 0x0a, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, - 0x73, 0x52, 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0xa1, 0x01, 0x0a, 0x16, 0x43, - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x48, 0x54, 0x54, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, - 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, - 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x77, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x12, 0x48, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0x65, - 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x12, 0x4a, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x4a, - 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x9d, 0x03, 0x0a, 0x15, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, - 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, - 0x47, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, - 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x73, 0x12, 0x58, 0x0a, 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, - 0x66, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x47, 0x52, 0x50, 0x43, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, - 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x73, 0x12, 0x4c, 0x0a, 0x08, - 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, - 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, - 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x12, 0x49, 0x0a, 0x07, 0x72, 0x65, - 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x07, 0x72, 0x65, - 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0xa1, 0x01, 0x0a, 0x16, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, - 0x65, 0x64, 0x47, 0x52, 0x50, 0x43, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, - 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, - 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, - 0x48, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0x5d, 0x0a, 0x10, 0x43, 0x6f, 0x6d, - 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x49, 0x0a, - 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, - 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, - 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x6f, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, - 0x12, 0x57, 0x0a, 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, - 0x43, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, - 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x73, 0x22, 0x56, 0x0a, 0x15, 0x43, 0x6f, 0x6d, - 0x70, 0x75, 0x74, 0x65, 0x64, 0x54, 0x43, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, - 0x65, 0x66, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x61, 0x63, 0x6b, - 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x22, 0x96, 0x05, 0x0a, 0x14, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4b, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x54, 0x79, 0x70, - 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x50, 0x0a, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, - 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x61, 0x63, - 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x62, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x73, - 0x68, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x65, - 0x73, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5e, 0x0a, 0x0f, 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, - 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5f, 0x0a, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x14, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x5f, 0x69, 0x64, 0x18, - 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2e, 0x49, 0x44, 0x52, 0x12, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x49, 0x64, 0x12, 0x5f, 0x0a, 0x11, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x16, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x10, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x49, 0x0a, 0x0d, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x17, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x52, 0x65, 0x66, 0x73, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x15, 0x22, 0xfd, 0x01, 0x0a, 0x16, 0x43, - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5e, 0x0a, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x4d, - 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x67, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x67, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x5f, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x61, 0x6d, - 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x44, 0x0a, 0x1b, 0x43, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x61, 0x63, - 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x2a, 0x99, 0x01, 0x0a, 0x18, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2b, 0x0a, - 0x27, 0x42, 0x41, 0x43, 0x4b, 0x45, 0x4e, 0x44, 0x5f, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, - 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x26, 0x0a, 0x22, 0x42, 0x41, - 0x43, 0x4b, 0x45, 0x4e, 0x44, 0x5f, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x44, 0x45, 0x54, - 0x41, 0x49, 0x4c, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, - 0x10, 0x01, 0x12, 0x28, 0x0a, 0x24, 0x42, 0x41, 0x43, 0x4b, 0x45, 0x4e, 0x44, 0x5f, 0x54, 0x41, - 0x52, 0x47, 0x45, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x53, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x49, 0x4e, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x02, 0x42, 0x94, 0x02, 0x0a, - 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x42, 0x13, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, - 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_computed_routes_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_computed_routes_proto_rawDescData = file_pbmesh_v2beta1_computed_routes_proto_rawDesc -) - -func file_pbmesh_v2beta1_computed_routes_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_computed_routes_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_computed_routes_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_computed_routes_proto_rawDescData) - }) - return file_pbmesh_v2beta1_computed_routes_proto_rawDescData -} - -var file_pbmesh_v2beta1_computed_routes_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v2beta1_computed_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 16) -var file_pbmesh_v2beta1_computed_routes_proto_goTypes = []interface{}{ - (BackendTargetDetailsType)(0), // 0: hashicorp.consul.mesh.v2beta1.BackendTargetDetailsType - (*ComputedRoutes)(nil), // 1: hashicorp.consul.mesh.v2beta1.ComputedRoutes - (*ComputedPortRoutes)(nil), // 2: hashicorp.consul.mesh.v2beta1.ComputedPortRoutes - (*ComputedHTTPRoute)(nil), // 3: hashicorp.consul.mesh.v2beta1.ComputedHTTPRoute - (*ComputedHTTPRouteRule)(nil), // 4: hashicorp.consul.mesh.v2beta1.ComputedHTTPRouteRule - (*ComputedHTTPBackendRef)(nil), // 5: hashicorp.consul.mesh.v2beta1.ComputedHTTPBackendRef - (*ComputedGRPCRoute)(nil), // 6: hashicorp.consul.mesh.v2beta1.ComputedGRPCRoute - (*ComputedGRPCRouteRule)(nil), // 7: hashicorp.consul.mesh.v2beta1.ComputedGRPCRouteRule - (*ComputedGRPCBackendRef)(nil), // 8: hashicorp.consul.mesh.v2beta1.ComputedGRPCBackendRef - (*ComputedTCPRoute)(nil), // 9: hashicorp.consul.mesh.v2beta1.ComputedTCPRoute - (*ComputedTCPRouteRule)(nil), // 10: hashicorp.consul.mesh.v2beta1.ComputedTCPRouteRule - (*ComputedTCPBackendRef)(nil), // 11: hashicorp.consul.mesh.v2beta1.ComputedTCPBackendRef - (*BackendTargetDetails)(nil), // 12: hashicorp.consul.mesh.v2beta1.BackendTargetDetails - (*ComputedFailoverConfig)(nil), // 13: hashicorp.consul.mesh.v2beta1.ComputedFailoverConfig - (*ComputedFailoverDestination)(nil), // 14: hashicorp.consul.mesh.v2beta1.ComputedFailoverDestination - nil, // 15: hashicorp.consul.mesh.v2beta1.ComputedRoutes.PortedConfigsEntry - nil, // 16: hashicorp.consul.mesh.v2beta1.ComputedPortRoutes.TargetsEntry - (*pbresource.Reference)(nil), // 17: hashicorp.consul.resource.Reference - (*ParentReference)(nil), // 18: hashicorp.consul.mesh.v2beta1.ParentReference - (v2beta1.Protocol)(0), // 19: hashicorp.consul.catalog.v2beta1.Protocol - (*HTTPRouteMatch)(nil), // 20: hashicorp.consul.mesh.v2beta1.HTTPRouteMatch - (*HTTPRouteFilter)(nil), // 21: hashicorp.consul.mesh.v2beta1.HTTPRouteFilter - (*HTTPRouteTimeouts)(nil), // 22: hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts - (*HTTPRouteRetries)(nil), // 23: hashicorp.consul.mesh.v2beta1.HTTPRouteRetries - (*GRPCRouteMatch)(nil), // 24: hashicorp.consul.mesh.v2beta1.GRPCRouteMatch - (*GRPCRouteFilter)(nil), // 25: hashicorp.consul.mesh.v2beta1.GRPCRouteFilter - (*BackendReference)(nil), // 26: hashicorp.consul.mesh.v2beta1.BackendReference - (*DestinationConfig)(nil), // 27: hashicorp.consul.mesh.v2beta1.DestinationConfig - (*pbresource.ID)(nil), // 28: hashicorp.consul.resource.ID - (*v2beta1.ServiceEndpoints)(nil), // 29: hashicorp.consul.catalog.v2beta1.ServiceEndpoints - (v2beta1.FailoverMode)(0), // 30: hashicorp.consul.catalog.v2beta1.FailoverMode -} -var file_pbmesh_v2beta1_computed_routes_proto_depIdxs = []int32{ - 15, // 0: hashicorp.consul.mesh.v2beta1.ComputedRoutes.ported_configs:type_name -> hashicorp.consul.mesh.v2beta1.ComputedRoutes.PortedConfigsEntry - 17, // 1: hashicorp.consul.mesh.v2beta1.ComputedRoutes.bound_references:type_name -> hashicorp.consul.resource.Reference - 3, // 2: hashicorp.consul.mesh.v2beta1.ComputedPortRoutes.http:type_name -> hashicorp.consul.mesh.v2beta1.ComputedHTTPRoute - 6, // 3: hashicorp.consul.mesh.v2beta1.ComputedPortRoutes.grpc:type_name -> hashicorp.consul.mesh.v2beta1.ComputedGRPCRoute - 9, // 4: hashicorp.consul.mesh.v2beta1.ComputedPortRoutes.tcp:type_name -> hashicorp.consul.mesh.v2beta1.ComputedTCPRoute - 18, // 5: hashicorp.consul.mesh.v2beta1.ComputedPortRoutes.parent_ref:type_name -> hashicorp.consul.mesh.v2beta1.ParentReference - 19, // 6: hashicorp.consul.mesh.v2beta1.ComputedPortRoutes.protocol:type_name -> hashicorp.consul.catalog.v2beta1.Protocol - 16, // 7: hashicorp.consul.mesh.v2beta1.ComputedPortRoutes.targets:type_name -> hashicorp.consul.mesh.v2beta1.ComputedPortRoutes.TargetsEntry - 4, // 8: hashicorp.consul.mesh.v2beta1.ComputedHTTPRoute.rules:type_name -> hashicorp.consul.mesh.v2beta1.ComputedHTTPRouteRule - 20, // 9: hashicorp.consul.mesh.v2beta1.ComputedHTTPRouteRule.matches:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteMatch - 21, // 10: hashicorp.consul.mesh.v2beta1.ComputedHTTPRouteRule.filters:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteFilter - 5, // 11: hashicorp.consul.mesh.v2beta1.ComputedHTTPRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v2beta1.ComputedHTTPBackendRef - 22, // 12: hashicorp.consul.mesh.v2beta1.ComputedHTTPRouteRule.timeouts:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts - 23, // 13: hashicorp.consul.mesh.v2beta1.ComputedHTTPRouteRule.retries:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteRetries - 21, // 14: hashicorp.consul.mesh.v2beta1.ComputedHTTPBackendRef.filters:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteFilter - 7, // 15: hashicorp.consul.mesh.v2beta1.ComputedGRPCRoute.rules:type_name -> hashicorp.consul.mesh.v2beta1.ComputedGRPCRouteRule - 24, // 16: hashicorp.consul.mesh.v2beta1.ComputedGRPCRouteRule.matches:type_name -> hashicorp.consul.mesh.v2beta1.GRPCRouteMatch - 25, // 17: hashicorp.consul.mesh.v2beta1.ComputedGRPCRouteRule.filters:type_name -> hashicorp.consul.mesh.v2beta1.GRPCRouteFilter - 8, // 18: hashicorp.consul.mesh.v2beta1.ComputedGRPCRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v2beta1.ComputedGRPCBackendRef - 22, // 19: hashicorp.consul.mesh.v2beta1.ComputedGRPCRouteRule.timeouts:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts - 23, // 20: hashicorp.consul.mesh.v2beta1.ComputedGRPCRouteRule.retries:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteRetries - 25, // 21: hashicorp.consul.mesh.v2beta1.ComputedGRPCBackendRef.filters:type_name -> hashicorp.consul.mesh.v2beta1.GRPCRouteFilter - 10, // 22: hashicorp.consul.mesh.v2beta1.ComputedTCPRoute.rules:type_name -> hashicorp.consul.mesh.v2beta1.ComputedTCPRouteRule - 11, // 23: hashicorp.consul.mesh.v2beta1.ComputedTCPRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v2beta1.ComputedTCPBackendRef - 0, // 24: hashicorp.consul.mesh.v2beta1.BackendTargetDetails.type:type_name -> hashicorp.consul.mesh.v2beta1.BackendTargetDetailsType - 26, // 25: hashicorp.consul.mesh.v2beta1.BackendTargetDetails.backend_ref:type_name -> hashicorp.consul.mesh.v2beta1.BackendReference - 13, // 26: hashicorp.consul.mesh.v2beta1.BackendTargetDetails.failover_config:type_name -> hashicorp.consul.mesh.v2beta1.ComputedFailoverConfig - 27, // 27: hashicorp.consul.mesh.v2beta1.BackendTargetDetails.destination_config:type_name -> hashicorp.consul.mesh.v2beta1.DestinationConfig - 28, // 28: hashicorp.consul.mesh.v2beta1.BackendTargetDetails.service_endpoints_id:type_name -> hashicorp.consul.resource.ID - 29, // 29: hashicorp.consul.mesh.v2beta1.BackendTargetDetails.service_endpoints:type_name -> hashicorp.consul.catalog.v2beta1.ServiceEndpoints - 17, // 30: hashicorp.consul.mesh.v2beta1.BackendTargetDetails.identity_refs:type_name -> hashicorp.consul.resource.Reference - 14, // 31: hashicorp.consul.mesh.v2beta1.ComputedFailoverConfig.destinations:type_name -> hashicorp.consul.mesh.v2beta1.ComputedFailoverDestination - 30, // 32: hashicorp.consul.mesh.v2beta1.ComputedFailoverConfig.mode:type_name -> hashicorp.consul.catalog.v2beta1.FailoverMode - 2, // 33: hashicorp.consul.mesh.v2beta1.ComputedRoutes.PortedConfigsEntry.value:type_name -> hashicorp.consul.mesh.v2beta1.ComputedPortRoutes - 12, // 34: hashicorp.consul.mesh.v2beta1.ComputedPortRoutes.TargetsEntry.value:type_name -> hashicorp.consul.mesh.v2beta1.BackendTargetDetails - 35, // [35:35] is the sub-list for method output_type - 35, // [35:35] is the sub-list for method input_type - 35, // [35:35] is the sub-list for extension type_name - 35, // [35:35] is the sub-list for extension extendee - 0, // [0:35] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_computed_routes_proto_init() } -func file_pbmesh_v2beta1_computed_routes_proto_init() { - if File_pbmesh_v2beta1_computed_routes_proto != nil { - return - } - file_pbmesh_v2beta1_common_proto_init() - file_pbmesh_v2beta1_destination_policy_proto_init() - file_pbmesh_v2beta1_grpc_route_proto_init() - file_pbmesh_v2beta1_http_route_proto_init() - file_pbmesh_v2beta1_http_route_retries_proto_init() - file_pbmesh_v2beta1_http_route_timeouts_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedRoutes); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedPortRoutes); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedHTTPRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedHTTPRouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedHTTPBackendRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedGRPCRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedGRPCRouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedGRPCBackendRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedTCPRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedTCPRouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedTCPBackendRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BackendTargetDetails); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedFailoverConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedFailoverDestination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v2beta1_computed_routes_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*ComputedPortRoutes_Http)(nil), - (*ComputedPortRoutes_Grpc)(nil), - (*ComputedPortRoutes_Tcp)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_computed_routes_proto_rawDesc, - NumEnums: 1, - NumMessages: 16, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_computed_routes_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_computed_routes_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_computed_routes_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_computed_routes_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_computed_routes_proto = out.File - file_pbmesh_v2beta1_computed_routes_proto_rawDesc = nil - file_pbmesh_v2beta1_computed_routes_proto_goTypes = nil - file_pbmesh_v2beta1_computed_routes_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/computed_routes.proto b/proto-public/pbmesh/v2beta1/computed_routes.proto deleted file mode 100644 index f9243bff4bc1..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_routes.proto +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "pbcatalog/v2beta1/failover_policy.proto"; -import "pbcatalog/v2beta1/protocol.proto"; -import "pbcatalog/v2beta1/service_endpoints.proto"; -import "pbmesh/v2beta1/common.proto"; -import "pbmesh/v2beta1/destination_policy.proto"; -import "pbmesh/v2beta1/grpc_route.proto"; -import "pbmesh/v2beta1/http_route.proto"; -import "pbmesh/v2beta1/http_route_retries.proto"; -import "pbmesh/v2beta1/http_route_timeouts.proto"; -import "pbresource/annotations.proto"; -import "pbresource/resource.proto"; - -// This is a Resource type. -message ComputedRoutes { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - map ported_configs = 1; - - // BoundReferences is a slice of mixed type references of resources that were - // involved in the formulation of this resource. - repeated hashicorp.consul.resource.Reference bound_references = 2; -} - -message ComputedPortRoutes { - oneof config { - ComputedHTTPRoute http = 1; - ComputedGRPCRoute grpc = 2; - ComputedTCPRoute tcp = 3; - } - bool using_default_config = 4; // TODO - - ParentReference parent_ref = 5; - // Protocol is the ParentRef.Port's protocol. It is based on the value in the - // Service object, but may differ depending upon which xRoutes are actually - // in use. - hashicorp.consul.catalog.v2beta1.Protocol protocol = 6; - - // map key is an opaque string; like disco chain target name - map targets = 7; -} - -message ComputedHTTPRoute { - reserved 1; // hostnames - repeated ComputedHTTPRouteRule rules = 2; -} - -message ComputedHTTPRouteRule { - repeated HTTPRouteMatch matches = 1; - repeated HTTPRouteFilter filters = 2; - repeated ComputedHTTPBackendRef backend_refs = 3; - HTTPRouteTimeouts timeouts = 4; - HTTPRouteRetries retries = 5; -} - -message ComputedHTTPBackendRef { - // BackendTarget indicates which key in the targets map provides - // the rest of the configuration. - // - // If this field is set to the empty string, or is the sentinel value - // "NULL-ROUTE" is an indication that all of the traffic destined for this - // backend reference should be null routed in a format appropriate for the - // protocol (i.e. for HTTP use 5xx). - string backend_target = 1; - uint32 weight = 2; - repeated HTTPRouteFilter filters = 3; -} - -message ComputedGRPCRoute { - reserved 1; // hostnames - repeated ComputedGRPCRouteRule rules = 2; -} - -message ComputedGRPCRouteRule { - repeated GRPCRouteMatch matches = 1; - repeated GRPCRouteFilter filters = 2; - repeated ComputedGRPCBackendRef backend_refs = 3; - HTTPRouteTimeouts timeouts = 4; - HTTPRouteRetries retries = 5; -} - -message ComputedGRPCBackendRef { - // BackendTarget indicates which key in the targets map provides - // the rest of the configuration. - // - // If this field is set to the empty string, or is the sentinel value - // "NULL-ROUTE" is an indication that all of the traffic destined for this - // backend reference should be null routed in a format appropriate for the - // protocol (i.e. for HTTP use 5xx). - string backend_target = 1; - uint32 weight = 2; - repeated GRPCRouteFilter filters = 3; -} - -message ComputedTCPRoute { - repeated ComputedTCPRouteRule rules = 1; -} - -message ComputedTCPRouteRule { - repeated ComputedTCPBackendRef backend_refs = 1; -} - -// TODO: look into smuggling the target through a different typeURL, or just skip in favor of letting the caller do their own lookups? -message ComputedTCPBackendRef { - // BackendTarget indicates which key in the targets map provides - // the rest of the configuration. - // - // If this field is set to the empty string, or is the sentinel value - // "NULL-ROUTE" is an indication that all of the traffic destined for this - // backend reference should be null routed in a format appropriate for the - // protocol (i.e. for HTTP use 5xx). - string backend_target = 1; - uint32 weight = 2; -} - -message BackendTargetDetails { - BackendTargetDetailsType type = 1; - BackendReference backend_ref = 2; - - string mesh_port = 3; - ComputedFailoverConfig failover_config = 4; - DestinationConfig destination_config = 5; - - reserved 6 to 20; // leaving a gap between computed and retroactively added fields. - - // ServiceEndpointsID is not populated naturally and the field exists only for - // downstream consumers. - hashicorp.consul.resource.ID service_endpoints_id = 21; - - // ServiceEndpoints is not populated naturally and the field exists only for - // downstream consumers. - hashicorp.consul.catalog.v2beta1.ServiceEndpoints service_endpoints = 22; - - // IdentityRefs are not populated naturally and the field exists only for - // downstream consumers. - repeated hashicorp.consul.resource.Reference identity_refs = 23; -} - -// +kubebuilder:validation:Enum=BACKEND_TARGET_DETAILS_TYPE_UNSPECIFIED;BACKEND_TARGET_DETAILS_TYPE_DIRECT;BACKEND_TARGET_DETAILS_TYPE_INDIRECT -// +kubebuilder:validation:Type=string -enum BackendTargetDetailsType { - BACKEND_TARGET_DETAILS_TYPE_UNSPECIFIED = 0; - - // Direct means that the target is directly routable from a route. This does - // not mean that the target is not also indirect though. - BACKEND_TARGET_DETAILS_TYPE_DIRECT = 1; - - // Indirect means that the target is not directly routable from a route. - // - // One example would be for a FailoverPolicy destination. - BACKEND_TARGET_DETAILS_TYPE_INDIRECT = 2; -} - -message ComputedFailoverConfig { - repeated ComputedFailoverDestination destinations = 1; - hashicorp.consul.catalog.v2beta1.FailoverMode mode = 2; - repeated string regions = 3; - - // SamenessGroup specifies the sameness group to failover to. - string sameness_group = 4; -} - -message ComputedFailoverDestination { - // BackendTarget must be a Service. - string backend_target = 1; -} diff --git a/proto-public/pbmesh/v2beta1/computed_routes_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/computed_routes_deepcopy.gen.go deleted file mode 100644 index d63358455892..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_routes_deepcopy.gen.go +++ /dev/null @@ -1,300 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ComputedRoutes within kubernetes types, where deepcopy-gen is used. -func (in *ComputedRoutes) DeepCopyInto(out *ComputedRoutes) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedRoutes. Required by controller-gen. -func (in *ComputedRoutes) DeepCopy() *ComputedRoutes { - if in == nil { - return nil - } - out := new(ComputedRoutes) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedRoutes. Required by controller-gen. -func (in *ComputedRoutes) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedPortRoutes within kubernetes types, where deepcopy-gen is used. -func (in *ComputedPortRoutes) DeepCopyInto(out *ComputedPortRoutes) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedPortRoutes. Required by controller-gen. -func (in *ComputedPortRoutes) DeepCopy() *ComputedPortRoutes { - if in == nil { - return nil - } - out := new(ComputedPortRoutes) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedPortRoutes. Required by controller-gen. -func (in *ComputedPortRoutes) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedHTTPRoute within kubernetes types, where deepcopy-gen is used. -func (in *ComputedHTTPRoute) DeepCopyInto(out *ComputedHTTPRoute) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedHTTPRoute. Required by controller-gen. -func (in *ComputedHTTPRoute) DeepCopy() *ComputedHTTPRoute { - if in == nil { - return nil - } - out := new(ComputedHTTPRoute) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedHTTPRoute. Required by controller-gen. -func (in *ComputedHTTPRoute) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedHTTPRouteRule within kubernetes types, where deepcopy-gen is used. -func (in *ComputedHTTPRouteRule) DeepCopyInto(out *ComputedHTTPRouteRule) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedHTTPRouteRule. Required by controller-gen. -func (in *ComputedHTTPRouteRule) DeepCopy() *ComputedHTTPRouteRule { - if in == nil { - return nil - } - out := new(ComputedHTTPRouteRule) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedHTTPRouteRule. Required by controller-gen. -func (in *ComputedHTTPRouteRule) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedHTTPBackendRef within kubernetes types, where deepcopy-gen is used. -func (in *ComputedHTTPBackendRef) DeepCopyInto(out *ComputedHTTPBackendRef) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedHTTPBackendRef. Required by controller-gen. -func (in *ComputedHTTPBackendRef) DeepCopy() *ComputedHTTPBackendRef { - if in == nil { - return nil - } - out := new(ComputedHTTPBackendRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedHTTPBackendRef. Required by controller-gen. -func (in *ComputedHTTPBackendRef) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedGRPCRoute within kubernetes types, where deepcopy-gen is used. -func (in *ComputedGRPCRoute) DeepCopyInto(out *ComputedGRPCRoute) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedGRPCRoute. Required by controller-gen. -func (in *ComputedGRPCRoute) DeepCopy() *ComputedGRPCRoute { - if in == nil { - return nil - } - out := new(ComputedGRPCRoute) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedGRPCRoute. Required by controller-gen. -func (in *ComputedGRPCRoute) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedGRPCRouteRule within kubernetes types, where deepcopy-gen is used. -func (in *ComputedGRPCRouteRule) DeepCopyInto(out *ComputedGRPCRouteRule) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedGRPCRouteRule. Required by controller-gen. -func (in *ComputedGRPCRouteRule) DeepCopy() *ComputedGRPCRouteRule { - if in == nil { - return nil - } - out := new(ComputedGRPCRouteRule) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedGRPCRouteRule. Required by controller-gen. -func (in *ComputedGRPCRouteRule) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedGRPCBackendRef within kubernetes types, where deepcopy-gen is used. -func (in *ComputedGRPCBackendRef) DeepCopyInto(out *ComputedGRPCBackendRef) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedGRPCBackendRef. Required by controller-gen. -func (in *ComputedGRPCBackendRef) DeepCopy() *ComputedGRPCBackendRef { - if in == nil { - return nil - } - out := new(ComputedGRPCBackendRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedGRPCBackendRef. Required by controller-gen. -func (in *ComputedGRPCBackendRef) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedTCPRoute within kubernetes types, where deepcopy-gen is used. -func (in *ComputedTCPRoute) DeepCopyInto(out *ComputedTCPRoute) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedTCPRoute. Required by controller-gen. -func (in *ComputedTCPRoute) DeepCopy() *ComputedTCPRoute { - if in == nil { - return nil - } - out := new(ComputedTCPRoute) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedTCPRoute. Required by controller-gen. -func (in *ComputedTCPRoute) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedTCPRouteRule within kubernetes types, where deepcopy-gen is used. -func (in *ComputedTCPRouteRule) DeepCopyInto(out *ComputedTCPRouteRule) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedTCPRouteRule. Required by controller-gen. -func (in *ComputedTCPRouteRule) DeepCopy() *ComputedTCPRouteRule { - if in == nil { - return nil - } - out := new(ComputedTCPRouteRule) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedTCPRouteRule. Required by controller-gen. -func (in *ComputedTCPRouteRule) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedTCPBackendRef within kubernetes types, where deepcopy-gen is used. -func (in *ComputedTCPBackendRef) DeepCopyInto(out *ComputedTCPBackendRef) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedTCPBackendRef. Required by controller-gen. -func (in *ComputedTCPBackendRef) DeepCopy() *ComputedTCPBackendRef { - if in == nil { - return nil - } - out := new(ComputedTCPBackendRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedTCPBackendRef. Required by controller-gen. -func (in *ComputedTCPBackendRef) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using BackendTargetDetails within kubernetes types, where deepcopy-gen is used. -func (in *BackendTargetDetails) DeepCopyInto(out *BackendTargetDetails) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTargetDetails. Required by controller-gen. -func (in *BackendTargetDetails) DeepCopy() *BackendTargetDetails { - if in == nil { - return nil - } - out := new(BackendTargetDetails) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new BackendTargetDetails. Required by controller-gen. -func (in *BackendTargetDetails) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedFailoverConfig within kubernetes types, where deepcopy-gen is used. -func (in *ComputedFailoverConfig) DeepCopyInto(out *ComputedFailoverConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedFailoverConfig. Required by controller-gen. -func (in *ComputedFailoverConfig) DeepCopy() *ComputedFailoverConfig { - if in == nil { - return nil - } - out := new(ComputedFailoverConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedFailoverConfig. Required by controller-gen. -func (in *ComputedFailoverConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ComputedFailoverDestination within kubernetes types, where deepcopy-gen is used. -func (in *ComputedFailoverDestination) DeepCopyInto(out *ComputedFailoverDestination) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedFailoverDestination. Required by controller-gen. -func (in *ComputedFailoverDestination) DeepCopy() *ComputedFailoverDestination { - if in == nil { - return nil - } - out := new(ComputedFailoverDestination) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedFailoverDestination. Required by controller-gen. -func (in *ComputedFailoverDestination) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/computed_routes_json.gen.go b/proto-public/pbmesh/v2beta1/computed_routes_json.gen.go deleted file mode 100644 index e1a60cf42281..000000000000 --- a/proto-public/pbmesh/v2beta1/computed_routes_json.gen.go +++ /dev/null @@ -1,165 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ComputedRoutes -func (this *ComputedRoutes) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedRoutes -func (this *ComputedRoutes) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedPortRoutes -func (this *ComputedPortRoutes) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedPortRoutes -func (this *ComputedPortRoutes) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedHTTPRoute -func (this *ComputedHTTPRoute) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedHTTPRoute -func (this *ComputedHTTPRoute) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedHTTPRouteRule -func (this *ComputedHTTPRouteRule) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedHTTPRouteRule -func (this *ComputedHTTPRouteRule) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedHTTPBackendRef -func (this *ComputedHTTPBackendRef) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedHTTPBackendRef -func (this *ComputedHTTPBackendRef) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedGRPCRoute -func (this *ComputedGRPCRoute) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedGRPCRoute -func (this *ComputedGRPCRoute) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedGRPCRouteRule -func (this *ComputedGRPCRouteRule) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedGRPCRouteRule -func (this *ComputedGRPCRouteRule) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedGRPCBackendRef -func (this *ComputedGRPCBackendRef) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedGRPCBackendRef -func (this *ComputedGRPCBackendRef) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedTCPRoute -func (this *ComputedTCPRoute) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedTCPRoute -func (this *ComputedTCPRoute) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedTCPRouteRule -func (this *ComputedTCPRouteRule) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedTCPRouteRule -func (this *ComputedTCPRouteRule) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedTCPBackendRef -func (this *ComputedTCPBackendRef) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedTCPBackendRef -func (this *ComputedTCPBackendRef) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for BackendTargetDetails -func (this *BackendTargetDetails) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for BackendTargetDetails -func (this *BackendTargetDetails) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedFailoverConfig -func (this *ComputedFailoverConfig) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedFailoverConfig -func (this *ComputedFailoverConfig) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ComputedFailoverDestination -func (this *ComputedFailoverDestination) MarshalJSON() ([]byte, error) { - str, err := ComputedRoutesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ComputedFailoverDestination -func (this *ComputedFailoverDestination) UnmarshalJSON(b []byte) error { - return ComputedRoutesUnmarshaler.Unmarshal(b, this) -} - -var ( - ComputedRoutesMarshaler = &protojson.MarshalOptions{} - ComputedRoutesUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/connection.pb.binary.go b/proto-public/pbmesh/v2beta1/connection.pb.binary.go deleted file mode 100644 index 4ea017a273fb..000000000000 --- a/proto-public/pbmesh/v2beta1/connection.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/connection.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ConnectionConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ConnectionConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InboundConnectionsConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InboundConnectionsConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/connection.pb.go b/proto-public/pbmesh/v2beta1/connection.pb.go deleted file mode 100644 index 591df222fc93..000000000000 --- a/proto-public/pbmesh/v2beta1/connection.pb.go +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/connection.proto - -package meshv2beta1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=BALANCE_CONNECTIONS_DEFAULT;BALANCE_CONNECTIONS_EXACT -// +kubebuilder:validation:Type=string -type BalanceConnections int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - BalanceConnections_BALANCE_CONNECTIONS_DEFAULT BalanceConnections = 0 - BalanceConnections_BALANCE_CONNECTIONS_EXACT BalanceConnections = 1 -) - -// Enum value maps for BalanceConnections. -var ( - BalanceConnections_name = map[int32]string{ - 0: "BALANCE_CONNECTIONS_DEFAULT", - 1: "BALANCE_CONNECTIONS_EXACT", - } - BalanceConnections_value = map[string]int32{ - "BALANCE_CONNECTIONS_DEFAULT": 0, - "BALANCE_CONNECTIONS_EXACT": 1, - } -) - -func (x BalanceConnections) Enum() *BalanceConnections { - p := new(BalanceConnections) - *p = x - return p -} - -func (x BalanceConnections) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (BalanceConnections) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_connection_proto_enumTypes[0].Descriptor() -} - -func (BalanceConnections) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_connection_proto_enumTypes[0] -} - -func (x BalanceConnections) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use BalanceConnections.Descriptor instead. -func (BalanceConnections) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_connection_proto_rawDescGZIP(), []int{0} -} - -// Referenced by ProxyConfiguration -type ConnectionConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // +kubebuilder:validation:Format=duration - ConnectTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` - // +kubebuilder:validation:Format=duration - RequestTimeout *durationpb.Duration `protobuf:"bytes,2,opt,name=request_timeout,json=requestTimeout,proto3" json:"request_timeout,omitempty"` -} - -func (x *ConnectionConfig) Reset() { - *x = ConnectionConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_connection_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConnectionConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConnectionConfig) ProtoMessage() {} - -func (x *ConnectionConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_connection_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ConnectionConfig.ProtoReflect.Descriptor instead. -func (*ConnectionConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_connection_proto_rawDescGZIP(), []int{0} -} - -func (x *ConnectionConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -func (x *ConnectionConfig) GetRequestTimeout() *durationpb.Duration { - if x != nil { - return x.RequestTimeout - } - return nil -} - -// Referenced by ProxyConfiguration -type InboundConnectionsConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MaxInboundConnections uint32 `protobuf:"varint,1,opt,name=max_inbound_connections,json=maxInboundConnections,proto3" json:"max_inbound_connections,omitempty"` - BalanceInboundConnections BalanceConnections `protobuf:"varint,2,opt,name=balance_inbound_connections,json=balanceInboundConnections,proto3,enum=hashicorp.consul.mesh.v2beta1.BalanceConnections" json:"balance_inbound_connections,omitempty"` -} - -func (x *InboundConnectionsConfig) Reset() { - *x = InboundConnectionsConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_connection_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InboundConnectionsConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InboundConnectionsConfig) ProtoMessage() {} - -func (x *InboundConnectionsConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_connection_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use InboundConnectionsConfig.ProtoReflect.Descriptor instead. -func (*InboundConnectionsConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_connection_proto_rawDescGZIP(), []int{1} -} - -func (x *InboundConnectionsConfig) GetMaxInboundConnections() uint32 { - if x != nil { - return x.MaxInboundConnections - } - return 0 -} - -func (x *InboundConnectionsConfig) GetBalanceInboundConnections() BalanceConnections { - if x != nil { - return x.BalanceInboundConnections - } - return BalanceConnections_BALANCE_CONNECTIONS_DEFAULT -} - -var File_pbmesh_v2beta1_connection_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_connection_proto_rawDesc = []byte{ - 0x0a, 0x1f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0x9a, 0x01, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x42, 0x0a, 0x0f, 0x72, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0xc5, 0x01, - 0x0a, 0x18, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x6d, 0x61, - 0x78, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x6d, 0x61, 0x78, - 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x71, 0x0a, 0x1b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x6e, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x19, 0x62, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2a, 0x54, 0x0a, 0x12, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x42, - 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, - 0x4e, 0x53, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, - 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x53, 0x5f, 0x45, 0x58, 0x41, 0x43, 0x54, 0x10, 0x01, 0x42, 0x90, 0x02, 0x0a, 0x21, - 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x42, 0x0f, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, - 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, - 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, - 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, - 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, - 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, - 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_connection_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_connection_proto_rawDescData = file_pbmesh_v2beta1_connection_proto_rawDesc -) - -func file_pbmesh_v2beta1_connection_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_connection_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_connection_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_connection_proto_rawDescData) - }) - return file_pbmesh_v2beta1_connection_proto_rawDescData -} - -var file_pbmesh_v2beta1_connection_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v2beta1_connection_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbmesh_v2beta1_connection_proto_goTypes = []interface{}{ - (BalanceConnections)(0), // 0: hashicorp.consul.mesh.v2beta1.BalanceConnections - (*ConnectionConfig)(nil), // 1: hashicorp.consul.mesh.v2beta1.ConnectionConfig - (*InboundConnectionsConfig)(nil), // 2: hashicorp.consul.mesh.v2beta1.InboundConnectionsConfig - (*durationpb.Duration)(nil), // 3: google.protobuf.Duration -} -var file_pbmesh_v2beta1_connection_proto_depIdxs = []int32{ - 3, // 0: hashicorp.consul.mesh.v2beta1.ConnectionConfig.connect_timeout:type_name -> google.protobuf.Duration - 3, // 1: hashicorp.consul.mesh.v2beta1.ConnectionConfig.request_timeout:type_name -> google.protobuf.Duration - 0, // 2: hashicorp.consul.mesh.v2beta1.InboundConnectionsConfig.balance_inbound_connections:type_name -> hashicorp.consul.mesh.v2beta1.BalanceConnections - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_connection_proto_init() } -func file_pbmesh_v2beta1_connection_proto_init() { - if File_pbmesh_v2beta1_connection_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_connection_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConnectionConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_connection_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InboundConnectionsConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_connection_proto_rawDesc, - NumEnums: 1, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_connection_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_connection_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_connection_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_connection_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_connection_proto = out.File - file_pbmesh_v2beta1_connection_proto_rawDesc = nil - file_pbmesh_v2beta1_connection_proto_goTypes = nil - file_pbmesh_v2beta1_connection_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/connection.proto b/proto-public/pbmesh/v2beta1/connection.proto deleted file mode 100644 index 65cb21e586dd..000000000000 --- a/proto-public/pbmesh/v2beta1/connection.proto +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "google/protobuf/duration.proto"; - -// Referenced by ProxyConfiguration -message ConnectionConfig { - // +kubebuilder:validation:Format=duration - google.protobuf.Duration connect_timeout = 1; - // +kubebuilder:validation:Format=duration - google.protobuf.Duration request_timeout = 2; -} - -// Referenced by ProxyConfiguration -message InboundConnectionsConfig { - uint32 max_inbound_connections = 1; - BalanceConnections balance_inbound_connections = 2; -} - -// +kubebuilder:validation:Enum=BALANCE_CONNECTIONS_DEFAULT;BALANCE_CONNECTIONS_EXACT -// +kubebuilder:validation:Type=string -enum BalanceConnections { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - BALANCE_CONNECTIONS_DEFAULT = 0; - BALANCE_CONNECTIONS_EXACT = 1; -} diff --git a/proto-public/pbmesh/v2beta1/connection_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/connection_deepcopy.gen.go deleted file mode 100644 index a0cfa7775756..000000000000 --- a/proto-public/pbmesh/v2beta1/connection_deepcopy.gen.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ConnectionConfig within kubernetes types, where deepcopy-gen is used. -func (in *ConnectionConfig) DeepCopyInto(out *ConnectionConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConnectionConfig. Required by controller-gen. -func (in *ConnectionConfig) DeepCopy() *ConnectionConfig { - if in == nil { - return nil - } - out := new(ConnectionConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ConnectionConfig. Required by controller-gen. -func (in *ConnectionConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using InboundConnectionsConfig within kubernetes types, where deepcopy-gen is used. -func (in *InboundConnectionsConfig) DeepCopyInto(out *InboundConnectionsConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InboundConnectionsConfig. Required by controller-gen. -func (in *InboundConnectionsConfig) DeepCopy() *InboundConnectionsConfig { - if in == nil { - return nil - } - out := new(InboundConnectionsConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new InboundConnectionsConfig. Required by controller-gen. -func (in *InboundConnectionsConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/connection_json.gen.go b/proto-public/pbmesh/v2beta1/connection_json.gen.go deleted file mode 100644 index 15649a3f2542..000000000000 --- a/proto-public/pbmesh/v2beta1/connection_json.gen.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ConnectionConfig -func (this *ConnectionConfig) MarshalJSON() ([]byte, error) { - str, err := ConnectionMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ConnectionConfig -func (this *ConnectionConfig) UnmarshalJSON(b []byte) error { - return ConnectionUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for InboundConnectionsConfig -func (this *InboundConnectionsConfig) MarshalJSON() ([]byte, error) { - str, err := ConnectionMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for InboundConnectionsConfig -func (this *InboundConnectionsConfig) UnmarshalJSON(b []byte) error { - return ConnectionUnmarshaler.Unmarshal(b, this) -} - -var ( - ConnectionMarshaler = &protojson.MarshalOptions{} - ConnectionUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/destination_policy.pb.binary.go b/proto-public/pbmesh/v2beta1/destination_policy.pb.binary.go deleted file mode 100644 index 777d8a8cc03b..000000000000 --- a/proto-public/pbmesh/v2beta1/destination_policy.pb.binary.go +++ /dev/null @@ -1,88 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/destination_policy.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LocalityPrioritization) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LocalityPrioritization) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LoadBalancer) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LoadBalancer) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RingHashConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RingHashConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LeastRequestConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LeastRequestConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HashPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HashPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *CookieConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *CookieConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/destination_policy.pb.go b/proto-public/pbmesh/v2beta1/destination_policy.pb.go deleted file mode 100644 index 99d7c7eaeaee..000000000000 --- a/proto-public/pbmesh/v2beta1/destination_policy.pb.go +++ /dev/null @@ -1,1102 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/destination_policy.proto - -package meshv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED;LOCALITY_PRIORITIZATION_MODE_NONE;LOCALITY_PRIORITIZATION_MODE_FAILOVER -// +kubebuilder:validation:Type=string -type LocalityPrioritizationMode int32 - -const ( - LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED LocalityPrioritizationMode = 0 - LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_NONE LocalityPrioritizationMode = 1 - LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_FAILOVER LocalityPrioritizationMode = 2 -) - -// Enum value maps for LocalityPrioritizationMode. -var ( - LocalityPrioritizationMode_name = map[int32]string{ - 0: "LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED", - 1: "LOCALITY_PRIORITIZATION_MODE_NONE", - 2: "LOCALITY_PRIORITIZATION_MODE_FAILOVER", - } - LocalityPrioritizationMode_value = map[string]int32{ - "LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED": 0, - "LOCALITY_PRIORITIZATION_MODE_NONE": 1, - "LOCALITY_PRIORITIZATION_MODE_FAILOVER": 2, - } -) - -func (x LocalityPrioritizationMode) Enum() *LocalityPrioritizationMode { - p := new(LocalityPrioritizationMode) - *p = x - return p -} - -func (x LocalityPrioritizationMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (LocalityPrioritizationMode) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_destination_policy_proto_enumTypes[0].Descriptor() -} - -func (LocalityPrioritizationMode) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_destination_policy_proto_enumTypes[0] -} - -func (x LocalityPrioritizationMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use LocalityPrioritizationMode.Descriptor instead. -func (LocalityPrioritizationMode) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destination_policy_proto_rawDescGZIP(), []int{0} -} - -// +kubebuilder:validation:Enum=LOAD_BALANCER_POLICY_UNSPECIFIED;LOAD_BALANCER_POLICY_RANDOM;LOAD_BALANCER_POLICY_ROUND_ROBIN;LOAD_BALANCER_POLICY_LEAST_REQUEST;LOAD_BALANCER_POLICY_MAGLEV;LOAD_BALANCER_POLICY_RING_HASH -// +kubebuilder:validation:Type=string -type LoadBalancerPolicy int32 - -const ( - LoadBalancerPolicy_LOAD_BALANCER_POLICY_UNSPECIFIED LoadBalancerPolicy = 0 - LoadBalancerPolicy_LOAD_BALANCER_POLICY_RANDOM LoadBalancerPolicy = 1 - LoadBalancerPolicy_LOAD_BALANCER_POLICY_ROUND_ROBIN LoadBalancerPolicy = 2 - LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST LoadBalancerPolicy = 3 - LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV LoadBalancerPolicy = 4 - LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH LoadBalancerPolicy = 5 -) - -// Enum value maps for LoadBalancerPolicy. -var ( - LoadBalancerPolicy_name = map[int32]string{ - 0: "LOAD_BALANCER_POLICY_UNSPECIFIED", - 1: "LOAD_BALANCER_POLICY_RANDOM", - 2: "LOAD_BALANCER_POLICY_ROUND_ROBIN", - 3: "LOAD_BALANCER_POLICY_LEAST_REQUEST", - 4: "LOAD_BALANCER_POLICY_MAGLEV", - 5: "LOAD_BALANCER_POLICY_RING_HASH", - } - LoadBalancerPolicy_value = map[string]int32{ - "LOAD_BALANCER_POLICY_UNSPECIFIED": 0, - "LOAD_BALANCER_POLICY_RANDOM": 1, - "LOAD_BALANCER_POLICY_ROUND_ROBIN": 2, - "LOAD_BALANCER_POLICY_LEAST_REQUEST": 3, - "LOAD_BALANCER_POLICY_MAGLEV": 4, - "LOAD_BALANCER_POLICY_RING_HASH": 5, - } -) - -func (x LoadBalancerPolicy) Enum() *LoadBalancerPolicy { - p := new(LoadBalancerPolicy) - *p = x - return p -} - -func (x LoadBalancerPolicy) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (LoadBalancerPolicy) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_destination_policy_proto_enumTypes[1].Descriptor() -} - -func (LoadBalancerPolicy) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_destination_policy_proto_enumTypes[1] -} - -func (x LoadBalancerPolicy) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use LoadBalancerPolicy.Descriptor instead. -func (LoadBalancerPolicy) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destination_policy_proto_rawDescGZIP(), []int{1} -} - -// +kubebuilder:validation:Enum=HASH_POLICY_FIELD_UNSPECIFIED;HASH_POLICY_FIELD_HEADER;HASH_POLICY_FIELD_COOKIE;HASH_POLICY_FIELD_QUERY_PARAMETER -// +kubebuilder:validation:Type=string -type HashPolicyField int32 - -const ( - HashPolicyField_HASH_POLICY_FIELD_UNSPECIFIED HashPolicyField = 0 - HashPolicyField_HASH_POLICY_FIELD_HEADER HashPolicyField = 1 - HashPolicyField_HASH_POLICY_FIELD_COOKIE HashPolicyField = 2 - HashPolicyField_HASH_POLICY_FIELD_QUERY_PARAMETER HashPolicyField = 3 -) - -// Enum value maps for HashPolicyField. -var ( - HashPolicyField_name = map[int32]string{ - 0: "HASH_POLICY_FIELD_UNSPECIFIED", - 1: "HASH_POLICY_FIELD_HEADER", - 2: "HASH_POLICY_FIELD_COOKIE", - 3: "HASH_POLICY_FIELD_QUERY_PARAMETER", - } - HashPolicyField_value = map[string]int32{ - "HASH_POLICY_FIELD_UNSPECIFIED": 0, - "HASH_POLICY_FIELD_HEADER": 1, - "HASH_POLICY_FIELD_COOKIE": 2, - "HASH_POLICY_FIELD_QUERY_PARAMETER": 3, - } -) - -func (x HashPolicyField) Enum() *HashPolicyField { - p := new(HashPolicyField) - *p = x - return p -} - -func (x HashPolicyField) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (HashPolicyField) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_destination_policy_proto_enumTypes[2].Descriptor() -} - -func (HashPolicyField) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_destination_policy_proto_enumTypes[2] -} - -func (x HashPolicyField) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use HashPolicyField.Descriptor instead. -func (HashPolicyField) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destination_policy_proto_rawDescGZIP(), []int{2} -} - -// DestinationPolicy is the destination-controlled set of defaults that -// are used when similar controls defined in an UpstreamConfig are left -// unspecified. -// -// Users may wish to share commonly configured settings for communicating with -// a service in one place, but yet retain the ability to tweak those on a -// client-by-client basis, which is why there are separate resources to control -// the definition of these values from either end of the connection. -// -// This is a Resource type. -type DestinationPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PortConfigs map[string]*DestinationConfig `protobuf:"bytes,1,rep,name=port_configs,json=portConfigs,proto3" json:"port_configs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *DestinationPolicy) Reset() { - *x = DestinationPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationPolicy) ProtoMessage() {} - -func (x *DestinationPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DestinationPolicy.ProtoReflect.Descriptor instead. -func (*DestinationPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destination_policy_proto_rawDescGZIP(), []int{0} -} - -func (x *DestinationPolicy) GetPortConfigs() map[string]*DestinationConfig { - if x != nil { - return x.PortConfigs - } - return nil -} - -type DestinationConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ConnectTimeout is the timeout for establishing new network connections - // to this service. - // +kubebuilder:validation:Format=duration - ConnectTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` - // RequestTimeout is the timeout for an HTTP request to complete before the - // connection is automatically terminated. If unspecified, defaults to 15 - // seconds. - // +kubebuilder:validation:Format=duration - RequestTimeout *durationpb.Duration `protobuf:"bytes,2,opt,name=request_timeout,json=requestTimeout,proto3" json:"request_timeout,omitempty"` - // LoadBalancer determines the load balancing policy and configuration for - // services issuing requests to this upstream service. - LoadBalancer *LoadBalancer `protobuf:"bytes,3,opt,name=load_balancer,json=loadBalancer,proto3" json:"load_balancer,omitempty"` - // LocalityPrioritization controls whether the locality of services within the - // local partition will be used to prioritize connectivity. - LocalityPrioritization *LocalityPrioritization `protobuf:"bytes,4,opt,name=locality_prioritization,json=localityPrioritization,proto3" json:"locality_prioritization,omitempty"` -} - -func (x *DestinationConfig) Reset() { - *x = DestinationConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationConfig) ProtoMessage() {} - -func (x *DestinationConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DestinationConfig.ProtoReflect.Descriptor instead. -func (*DestinationConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destination_policy_proto_rawDescGZIP(), []int{1} -} - -func (x *DestinationConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -func (x *DestinationConfig) GetRequestTimeout() *durationpb.Duration { - if x != nil { - return x.RequestTimeout - } - return nil -} - -func (x *DestinationConfig) GetLoadBalancer() *LoadBalancer { - if x != nil { - return x.LoadBalancer - } - return nil -} - -func (x *DestinationConfig) GetLocalityPrioritization() *LocalityPrioritization { - if x != nil { - return x.LocalityPrioritization - } - return nil -} - -type LocalityPrioritization struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Mode specifies the type of prioritization that will be performed - // when selecting nodes in the local partition. - // Valid values are: "" (default "none"), "none", and "failover". - Mode LocalityPrioritizationMode `protobuf:"varint,1,opt,name=mode,proto3,enum=hashicorp.consul.mesh.v2beta1.LocalityPrioritizationMode" json:"mode,omitempty"` -} - -func (x *LocalityPrioritization) Reset() { - *x = LocalityPrioritization{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LocalityPrioritization) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LocalityPrioritization) ProtoMessage() {} - -func (x *LocalityPrioritization) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LocalityPrioritization.ProtoReflect.Descriptor instead. -func (*LocalityPrioritization) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destination_policy_proto_rawDescGZIP(), []int{2} -} - -func (x *LocalityPrioritization) GetMode() LocalityPrioritizationMode { - if x != nil { - return x.Mode - } - return LocalityPrioritizationMode_LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED -} - -// LoadBalancer determines the load balancing policy and configuration -// for services issuing requests to this upstream service. -type LoadBalancer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Policy is the load balancing policy used to select a host - Policy LoadBalancerPolicy `protobuf:"varint,1,opt,name=policy,proto3,enum=hashicorp.consul.mesh.v2beta1.LoadBalancerPolicy" json:"policy,omitempty"` - // HashPolicies is a list of hash policies to use for hashing load balancing - // algorithms. Hash policies are evaluated individually and combined such - // that identical lists result in the same hash. - // - // If no hash policies are present, or none are successfully evaluated, - // then a random backend host will be selected. - HashPolicies []*HashPolicy `protobuf:"bytes,2,rep,name=hash_policies,json=hashPolicies,proto3" json:"hash_policies,omitempty"` - // Types that are assignable to Config: - // - // *LoadBalancer_RingHashConfig - // *LoadBalancer_LeastRequestConfig - Config isLoadBalancer_Config `protobuf_oneof:"config"` -} - -func (x *LoadBalancer) Reset() { - *x = LoadBalancer{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LoadBalancer) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LoadBalancer) ProtoMessage() {} - -func (x *LoadBalancer) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LoadBalancer.ProtoReflect.Descriptor instead. -func (*LoadBalancer) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destination_policy_proto_rawDescGZIP(), []int{3} -} - -func (x *LoadBalancer) GetPolicy() LoadBalancerPolicy { - if x != nil { - return x.Policy - } - return LoadBalancerPolicy_LOAD_BALANCER_POLICY_UNSPECIFIED -} - -func (x *LoadBalancer) GetHashPolicies() []*HashPolicy { - if x != nil { - return x.HashPolicies - } - return nil -} - -func (m *LoadBalancer) GetConfig() isLoadBalancer_Config { - if m != nil { - return m.Config - } - return nil -} - -func (x *LoadBalancer) GetRingHashConfig() *RingHashConfig { - if x, ok := x.GetConfig().(*LoadBalancer_RingHashConfig); ok { - return x.RingHashConfig - } - return nil -} - -func (x *LoadBalancer) GetLeastRequestConfig() *LeastRequestConfig { - if x, ok := x.GetConfig().(*LoadBalancer_LeastRequestConfig); ok { - return x.LeastRequestConfig - } - return nil -} - -type isLoadBalancer_Config interface { - isLoadBalancer_Config() -} - -type LoadBalancer_RingHashConfig struct { - // RingHashConfig contains configuration for the "ring_hash" policy type - RingHashConfig *RingHashConfig `protobuf:"bytes,3,opt,name=ring_hash_config,json=ringHashConfig,proto3,oneof"` -} - -type LoadBalancer_LeastRequestConfig struct { - // LeastRequestConfig contains configuration for the "least_request" policy type - LeastRequestConfig *LeastRequestConfig `protobuf:"bytes,4,opt,name=least_request_config,json=leastRequestConfig,proto3,oneof"` -} - -func (*LoadBalancer_RingHashConfig) isLoadBalancer_Config() {} - -func (*LoadBalancer_LeastRequestConfig) isLoadBalancer_Config() {} - -// RingHashConfig contains configuration for the "ring_hash" policy type -type RingHashConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // MinimumRingSize determines the minimum number of entries in the hash ring - MinimumRingSize uint64 `protobuf:"varint,1,opt,name=minimum_ring_size,json=minimumRingSize,proto3" json:"minimum_ring_size,omitempty"` - // MaximumRingSize determines the maximum number of entries in the hash ring - MaximumRingSize uint64 `protobuf:"varint,2,opt,name=maximum_ring_size,json=maximumRingSize,proto3" json:"maximum_ring_size,omitempty"` -} - -func (x *RingHashConfig) Reset() { - *x = RingHashConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RingHashConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RingHashConfig) ProtoMessage() {} - -func (x *RingHashConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RingHashConfig.ProtoReflect.Descriptor instead. -func (*RingHashConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destination_policy_proto_rawDescGZIP(), []int{4} -} - -func (x *RingHashConfig) GetMinimumRingSize() uint64 { - if x != nil { - return x.MinimumRingSize - } - return 0 -} - -func (x *RingHashConfig) GetMaximumRingSize() uint64 { - if x != nil { - return x.MaximumRingSize - } - return 0 -} - -// LeastRequestConfig contains configuration for the "least_request" policy type -type LeastRequestConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ChoiceCount determines the number of random healthy hosts from which to select the one with the least requests. - ChoiceCount uint32 `protobuf:"varint,1,opt,name=choice_count,json=choiceCount,proto3" json:"choice_count,omitempty"` -} - -func (x *LeastRequestConfig) Reset() { - *x = LeastRequestConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LeastRequestConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LeastRequestConfig) ProtoMessage() {} - -func (x *LeastRequestConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LeastRequestConfig.ProtoReflect.Descriptor instead. -func (*LeastRequestConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destination_policy_proto_rawDescGZIP(), []int{5} -} - -func (x *LeastRequestConfig) GetChoiceCount() uint32 { - if x != nil { - return x.ChoiceCount - } - return 0 -} - -// HashPolicy defines which attributes will be hashed by hash-based LB algorithms -type HashPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Field is the attribute type to hash on. - // Must be one of "header","cookie", or "query_parameter". - // Cannot be specified along with SourceIP. - Field HashPolicyField `protobuf:"varint,1,opt,name=field,proto3,enum=hashicorp.consul.mesh.v2beta1.HashPolicyField" json:"field,omitempty"` - // FieldValue is the value to hash. - // ie. header name, cookie name, URL query parameter name - // Cannot be specified along with SourceIP. - FieldValue string `protobuf:"bytes,2,opt,name=field_value,json=fieldValue,proto3" json:"field_value,omitempty"` - // CookieConfig contains configuration for the "cookie" hash policy type. - CookieConfig *CookieConfig `protobuf:"bytes,3,opt,name=cookie_config,json=cookieConfig,proto3" json:"cookie_config,omitempty"` - // SourceIP determines whether the hash should be of the source IP rather than of a field and field value. - // Cannot be specified along with Field or FieldValue. - SourceIp bool `protobuf:"varint,4,opt,name=source_ip,json=sourceIp,proto3" json:"source_ip,omitempty"` - // Terminal will short circuit the computation of the hash when multiple hash policies are present. - // If a hash is computed when a Terminal policy is evaluated, - // then that hash will be used and subsequent hash policies will be ignored. - Terminal bool `protobuf:"varint,5,opt,name=terminal,proto3" json:"terminal,omitempty"` -} - -func (x *HashPolicy) Reset() { - *x = HashPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HashPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HashPolicy) ProtoMessage() {} - -func (x *HashPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HashPolicy.ProtoReflect.Descriptor instead. -func (*HashPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destination_policy_proto_rawDescGZIP(), []int{6} -} - -func (x *HashPolicy) GetField() HashPolicyField { - if x != nil { - return x.Field - } - return HashPolicyField_HASH_POLICY_FIELD_UNSPECIFIED -} - -func (x *HashPolicy) GetFieldValue() string { - if x != nil { - return x.FieldValue - } - return "" -} - -func (x *HashPolicy) GetCookieConfig() *CookieConfig { - if x != nil { - return x.CookieConfig - } - return nil -} - -func (x *HashPolicy) GetSourceIp() bool { - if x != nil { - return x.SourceIp - } - return false -} - -func (x *HashPolicy) GetTerminal() bool { - if x != nil { - return x.Terminal - } - return false -} - -// CookieConfig contains configuration for the "cookie" hash policy type. -// This is specified to have Envoy generate a cookie for a client on its first request. -type CookieConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Generates a session cookie with no expiration. - Session bool `protobuf:"varint,1,opt,name=session,proto3" json:"session,omitempty"` - // TTL for generated cookies. Cannot be specified for session cookies. - // +kubebuilder:validation:Format=duration - Ttl *durationpb.Duration `protobuf:"bytes,2,opt,name=ttl,proto3" json:"ttl,omitempty"` - // The path to set for the cookie - Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"` -} - -func (x *CookieConfig) Reset() { - *x = CookieConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CookieConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CookieConfig) ProtoMessage() {} - -func (x *CookieConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destination_policy_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CookieConfig.ProtoReflect.Descriptor instead. -func (*CookieConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destination_policy_proto_rawDescGZIP(), []int{7} -} - -func (x *CookieConfig) GetSession() bool { - if x != nil { - return x.Session - } - return false -} - -func (x *CookieConfig) GetTtl() *durationpb.Duration { - if x != nil { - return x.Ttl - } - return nil -} - -func (x *CookieConfig) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -var File_pbmesh_v2beta1_destination_policy_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_destination_policy_proto_rawDesc = []byte{ - 0x0a, 0x27, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf3, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x73, 0x74, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x64, 0x0a, 0x0c, - 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x73, 0x1a, 0x70, 0x0a, 0x10, 0x50, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0xdd, 0x02, 0x0a, - 0x11, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x42, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x50, 0x0a, 0x0d, 0x6c, 0x6f, - 0x61, 0x64, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x52, 0x0c, - 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x6e, 0x0a, 0x17, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, - 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x16, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, - 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x67, 0x0a, 0x16, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x69, - 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x52, - 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0xf5, 0x02, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x49, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x12, 0x4e, 0x0a, 0x0d, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x52, 0x0c, 0x68, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, - 0x73, 0x12, 0x59, 0x0a, 0x10, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x69, 0x6e, 0x67, - 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x69, - 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x65, 0x0a, 0x14, - 0x6c, 0x65, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, - 0x12, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x42, 0x08, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x68, 0x0a, - 0x0e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, - 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x69, - 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x6d, - 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x52, - 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x37, 0x0a, 0x12, 0x4c, 0x65, 0x61, 0x73, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x21, 0x0a, - 0x0c, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x22, 0xfe, 0x01, 0x0a, 0x0a, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, - 0x44, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, - 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x05, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x50, 0x0a, 0x0d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, - 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x63, 0x6f, 0x6f, 0x6b, - 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x49, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, - 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, - 0x6c, 0x22, 0x69, 0x0a, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x03, 0x74, - 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x2a, 0x9c, 0x01, 0x0a, - 0x1a, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, - 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x2c, 0x0a, 0x28, 0x4c, - 0x4f, 0x43, 0x41, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x49, - 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x25, 0x0a, 0x21, 0x4c, 0x4f, 0x43, - 0x41, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x49, 0x5a, 0x41, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, - 0x12, 0x29, 0x0a, 0x25, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x52, 0x49, - 0x4f, 0x52, 0x49, 0x54, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, - 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x4f, 0x56, 0x45, 0x52, 0x10, 0x02, 0x2a, 0xee, 0x01, 0x0a, 0x12, - 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x12, 0x24, 0x0a, 0x20, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, - 0x43, 0x45, 0x52, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x4c, 0x4f, 0x41, 0x44, - 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x52, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, - 0x5f, 0x52, 0x41, 0x4e, 0x44, 0x4f, 0x4d, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x4c, 0x4f, 0x41, - 0x44, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x52, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, - 0x59, 0x5f, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x52, 0x4f, 0x42, 0x49, 0x4e, 0x10, 0x02, 0x12, - 0x26, 0x0a, 0x22, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x52, - 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x4c, 0x45, 0x41, 0x53, 0x54, 0x5f, 0x52, 0x45, - 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x03, 0x12, 0x1f, 0x0a, 0x1b, 0x4c, 0x4f, 0x41, 0x44, 0x5f, - 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x52, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, - 0x4d, 0x41, 0x47, 0x4c, 0x45, 0x56, 0x10, 0x04, 0x12, 0x22, 0x0a, 0x1e, 0x4c, 0x4f, 0x41, 0x44, - 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x52, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, - 0x5f, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x05, 0x2a, 0x97, 0x01, 0x0a, - 0x0f, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x12, 0x21, 0x0a, 0x1d, 0x48, 0x41, 0x53, 0x48, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, - 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x48, 0x41, 0x53, 0x48, 0x5f, 0x50, 0x4f, 0x4c, 0x49, - 0x43, 0x59, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x10, - 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x48, 0x41, 0x53, 0x48, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, - 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x43, 0x4f, 0x4f, 0x4b, 0x49, 0x45, 0x10, 0x02, 0x12, - 0x25, 0x0a, 0x21, 0x48, 0x41, 0x53, 0x48, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x46, - 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x59, 0x5f, 0x50, 0x41, 0x52, 0x41, 0x4d, - 0x45, 0x54, 0x45, 0x52, 0x10, 0x03, 0x42, 0x97, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x16, 0x44, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, - 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, - 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_destination_policy_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_destination_policy_proto_rawDescData = file_pbmesh_v2beta1_destination_policy_proto_rawDesc -) - -func file_pbmesh_v2beta1_destination_policy_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_destination_policy_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_destination_policy_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_destination_policy_proto_rawDescData) - }) - return file_pbmesh_v2beta1_destination_policy_proto_rawDescData -} - -var file_pbmesh_v2beta1_destination_policy_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_pbmesh_v2beta1_destination_policy_proto_msgTypes = make([]protoimpl.MessageInfo, 9) -var file_pbmesh_v2beta1_destination_policy_proto_goTypes = []interface{}{ - (LocalityPrioritizationMode)(0), // 0: hashicorp.consul.mesh.v2beta1.LocalityPrioritizationMode - (LoadBalancerPolicy)(0), // 1: hashicorp.consul.mesh.v2beta1.LoadBalancerPolicy - (HashPolicyField)(0), // 2: hashicorp.consul.mesh.v2beta1.HashPolicyField - (*DestinationPolicy)(nil), // 3: hashicorp.consul.mesh.v2beta1.DestinationPolicy - (*DestinationConfig)(nil), // 4: hashicorp.consul.mesh.v2beta1.DestinationConfig - (*LocalityPrioritization)(nil), // 5: hashicorp.consul.mesh.v2beta1.LocalityPrioritization - (*LoadBalancer)(nil), // 6: hashicorp.consul.mesh.v2beta1.LoadBalancer - (*RingHashConfig)(nil), // 7: hashicorp.consul.mesh.v2beta1.RingHashConfig - (*LeastRequestConfig)(nil), // 8: hashicorp.consul.mesh.v2beta1.LeastRequestConfig - (*HashPolicy)(nil), // 9: hashicorp.consul.mesh.v2beta1.HashPolicy - (*CookieConfig)(nil), // 10: hashicorp.consul.mesh.v2beta1.CookieConfig - nil, // 11: hashicorp.consul.mesh.v2beta1.DestinationPolicy.PortConfigsEntry - (*durationpb.Duration)(nil), // 12: google.protobuf.Duration -} -var file_pbmesh_v2beta1_destination_policy_proto_depIdxs = []int32{ - 11, // 0: hashicorp.consul.mesh.v2beta1.DestinationPolicy.port_configs:type_name -> hashicorp.consul.mesh.v2beta1.DestinationPolicy.PortConfigsEntry - 12, // 1: hashicorp.consul.mesh.v2beta1.DestinationConfig.connect_timeout:type_name -> google.protobuf.Duration - 12, // 2: hashicorp.consul.mesh.v2beta1.DestinationConfig.request_timeout:type_name -> google.protobuf.Duration - 6, // 3: hashicorp.consul.mesh.v2beta1.DestinationConfig.load_balancer:type_name -> hashicorp.consul.mesh.v2beta1.LoadBalancer - 5, // 4: hashicorp.consul.mesh.v2beta1.DestinationConfig.locality_prioritization:type_name -> hashicorp.consul.mesh.v2beta1.LocalityPrioritization - 0, // 5: hashicorp.consul.mesh.v2beta1.LocalityPrioritization.mode:type_name -> hashicorp.consul.mesh.v2beta1.LocalityPrioritizationMode - 1, // 6: hashicorp.consul.mesh.v2beta1.LoadBalancer.policy:type_name -> hashicorp.consul.mesh.v2beta1.LoadBalancerPolicy - 9, // 7: hashicorp.consul.mesh.v2beta1.LoadBalancer.hash_policies:type_name -> hashicorp.consul.mesh.v2beta1.HashPolicy - 7, // 8: hashicorp.consul.mesh.v2beta1.LoadBalancer.ring_hash_config:type_name -> hashicorp.consul.mesh.v2beta1.RingHashConfig - 8, // 9: hashicorp.consul.mesh.v2beta1.LoadBalancer.least_request_config:type_name -> hashicorp.consul.mesh.v2beta1.LeastRequestConfig - 2, // 10: hashicorp.consul.mesh.v2beta1.HashPolicy.field:type_name -> hashicorp.consul.mesh.v2beta1.HashPolicyField - 10, // 11: hashicorp.consul.mesh.v2beta1.HashPolicy.cookie_config:type_name -> hashicorp.consul.mesh.v2beta1.CookieConfig - 12, // 12: hashicorp.consul.mesh.v2beta1.CookieConfig.ttl:type_name -> google.protobuf.Duration - 4, // 13: hashicorp.consul.mesh.v2beta1.DestinationPolicy.PortConfigsEntry.value:type_name -> hashicorp.consul.mesh.v2beta1.DestinationConfig - 14, // [14:14] is the sub-list for method output_type - 14, // [14:14] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_destination_policy_proto_init() } -func file_pbmesh_v2beta1_destination_policy_proto_init() { - if File_pbmesh_v2beta1_destination_policy_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_destination_policy_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destination_policy_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destination_policy_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LocalityPrioritization); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destination_policy_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LoadBalancer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destination_policy_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RingHashConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destination_policy_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LeastRequestConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destination_policy_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HashPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destination_policy_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CookieConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v2beta1_destination_policy_proto_msgTypes[3].OneofWrappers = []interface{}{ - (*LoadBalancer_RingHashConfig)(nil), - (*LoadBalancer_LeastRequestConfig)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_destination_policy_proto_rawDesc, - NumEnums: 3, - NumMessages: 9, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_destination_policy_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_destination_policy_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_destination_policy_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_destination_policy_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_destination_policy_proto = out.File - file_pbmesh_v2beta1_destination_policy_proto_rawDesc = nil - file_pbmesh_v2beta1_destination_policy_proto_goTypes = nil - file_pbmesh_v2beta1_destination_policy_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/destination_policy.proto b/proto-public/pbmesh/v2beta1/destination_policy.proto deleted file mode 100644 index 0a18fd8c49b6..000000000000 --- a/proto-public/pbmesh/v2beta1/destination_policy.proto +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "google/protobuf/duration.proto"; -import "pbresource/annotations.proto"; - -// DestinationPolicy is the destination-controlled set of defaults that -// are used when similar controls defined in an UpstreamConfig are left -// unspecified. -// -// Users may wish to share commonly configured settings for communicating with -// a service in one place, but yet retain the ability to tweak those on a -// client-by-client basis, which is why there are separate resources to control -// the definition of these values from either end of the connection. -// -// This is a Resource type. -message DestinationPolicy { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - map port_configs = 1; -} - -message DestinationConfig { - // ConnectTimeout is the timeout for establishing new network connections - // to this service. - // +kubebuilder:validation:Format=duration - google.protobuf.Duration connect_timeout = 1; - - // RequestTimeout is the timeout for an HTTP request to complete before the - // connection is automatically terminated. If unspecified, defaults to 15 - // seconds. - // +kubebuilder:validation:Format=duration - google.protobuf.Duration request_timeout = 2; - - // LoadBalancer determines the load balancing policy and configuration for - // services issuing requests to this upstream service. - LoadBalancer load_balancer = 3; - - // LocalityPrioritization controls whether the locality of services within the - // local partition will be used to prioritize connectivity. - LocalityPrioritization locality_prioritization = 4; -} - -message LocalityPrioritization { - // Mode specifies the type of prioritization that will be performed - // when selecting nodes in the local partition. - // Valid values are: "" (default "none"), "none", and "failover". - LocalityPrioritizationMode mode = 1; -} - -// +kubebuilder:validation:Enum=LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED;LOCALITY_PRIORITIZATION_MODE_NONE;LOCALITY_PRIORITIZATION_MODE_FAILOVER -// +kubebuilder:validation:Type=string -enum LocalityPrioritizationMode { - LOCALITY_PRIORITIZATION_MODE_UNSPECIFIED = 0; - LOCALITY_PRIORITIZATION_MODE_NONE = 1; - LOCALITY_PRIORITIZATION_MODE_FAILOVER = 2; -} - -// LoadBalancer determines the load balancing policy and configuration -// for services issuing requests to this upstream service. -// -message LoadBalancer { - // Policy is the load balancing policy used to select a host - LoadBalancerPolicy policy = 1; - - // HashPolicies is a list of hash policies to use for hashing load balancing - // algorithms. Hash policies are evaluated individually and combined such - // that identical lists result in the same hash. - // - // If no hash policies are present, or none are successfully evaluated, - // then a random backend host will be selected. - repeated HashPolicy hash_policies = 2; - - oneof config { - // RingHashConfig contains configuration for the "ring_hash" policy type - RingHashConfig ring_hash_config = 3; - - // LeastRequestConfig contains configuration for the "least_request" policy type - LeastRequestConfig least_request_config = 4; - } -} - -// +kubebuilder:validation:Enum=LOAD_BALANCER_POLICY_UNSPECIFIED;LOAD_BALANCER_POLICY_RANDOM;LOAD_BALANCER_POLICY_ROUND_ROBIN;LOAD_BALANCER_POLICY_LEAST_REQUEST;LOAD_BALANCER_POLICY_MAGLEV;LOAD_BALANCER_POLICY_RING_HASH -// +kubebuilder:validation:Type=string -enum LoadBalancerPolicy { - LOAD_BALANCER_POLICY_UNSPECIFIED = 0; - LOAD_BALANCER_POLICY_RANDOM = 1; - LOAD_BALANCER_POLICY_ROUND_ROBIN = 2; - LOAD_BALANCER_POLICY_LEAST_REQUEST = 3; - LOAD_BALANCER_POLICY_MAGLEV = 4; - LOAD_BALANCER_POLICY_RING_HASH = 5; -} - -// RingHashConfig contains configuration for the "ring_hash" policy type -message RingHashConfig { - // MinimumRingSize determines the minimum number of entries in the hash ring - uint64 minimum_ring_size = 1; - - // MaximumRingSize determines the maximum number of entries in the hash ring - uint64 maximum_ring_size = 2; -} - -// LeastRequestConfig contains configuration for the "least_request" policy type -message LeastRequestConfig { - // ChoiceCount determines the number of random healthy hosts from which to select the one with the least requests. - uint32 choice_count = 1; -} - -// HashPolicy defines which attributes will be hashed by hash-based LB algorithms -message HashPolicy { - // Field is the attribute type to hash on. - // Must be one of "header","cookie", or "query_parameter". - // Cannot be specified along with SourceIP. - HashPolicyField field = 1; - - // FieldValue is the value to hash. - // ie. header name, cookie name, URL query parameter name - // Cannot be specified along with SourceIP. - string field_value = 2; - - // CookieConfig contains configuration for the "cookie" hash policy type. - CookieConfig cookie_config = 3; - - // SourceIP determines whether the hash should be of the source IP rather than of a field and field value. - // Cannot be specified along with Field or FieldValue. - bool source_ip = 4; - - // Terminal will short circuit the computation of the hash when multiple hash policies are present. - // If a hash is computed when a Terminal policy is evaluated, - // then that hash will be used and subsequent hash policies will be ignored. - bool terminal = 5; -} - -// +kubebuilder:validation:Enum=HASH_POLICY_FIELD_UNSPECIFIED;HASH_POLICY_FIELD_HEADER;HASH_POLICY_FIELD_COOKIE;HASH_POLICY_FIELD_QUERY_PARAMETER -// +kubebuilder:validation:Type=string -enum HashPolicyField { - HASH_POLICY_FIELD_UNSPECIFIED = 0; - HASH_POLICY_FIELD_HEADER = 1; - HASH_POLICY_FIELD_COOKIE = 2; - HASH_POLICY_FIELD_QUERY_PARAMETER = 3; -} - -// CookieConfig contains configuration for the "cookie" hash policy type. -// This is specified to have Envoy generate a cookie for a client on its first request. -message CookieConfig { - // Generates a session cookie with no expiration. - bool session = 1; - - // TTL for generated cookies. Cannot be specified for session cookies. - // +kubebuilder:validation:Format=duration - google.protobuf.Duration ttl = 2; - - // The path to set for the cookie - string path = 3; -} diff --git a/proto-public/pbmesh/v2beta1/destination_policy_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/destination_policy_deepcopy.gen.go deleted file mode 100644 index 1935359729e5..000000000000 --- a/proto-public/pbmesh/v2beta1/destination_policy_deepcopy.gen.go +++ /dev/null @@ -1,174 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using DestinationPolicy within kubernetes types, where deepcopy-gen is used. -func (in *DestinationPolicy) DeepCopyInto(out *DestinationPolicy) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationPolicy. Required by controller-gen. -func (in *DestinationPolicy) DeepCopy() *DestinationPolicy { - if in == nil { - return nil - } - out := new(DestinationPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DestinationPolicy. Required by controller-gen. -func (in *DestinationPolicy) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DestinationConfig within kubernetes types, where deepcopy-gen is used. -func (in *DestinationConfig) DeepCopyInto(out *DestinationConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationConfig. Required by controller-gen. -func (in *DestinationConfig) DeepCopy() *DestinationConfig { - if in == nil { - return nil - } - out := new(DestinationConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DestinationConfig. Required by controller-gen. -func (in *DestinationConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using LocalityPrioritization within kubernetes types, where deepcopy-gen is used. -func (in *LocalityPrioritization) DeepCopyInto(out *LocalityPrioritization) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalityPrioritization. Required by controller-gen. -func (in *LocalityPrioritization) DeepCopy() *LocalityPrioritization { - if in == nil { - return nil - } - out := new(LocalityPrioritization) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new LocalityPrioritization. Required by controller-gen. -func (in *LocalityPrioritization) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using LoadBalancer within kubernetes types, where deepcopy-gen is used. -func (in *LoadBalancer) DeepCopyInto(out *LoadBalancer) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancer. Required by controller-gen. -func (in *LoadBalancer) DeepCopy() *LoadBalancer { - if in == nil { - return nil - } - out := new(LoadBalancer) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancer. Required by controller-gen. -func (in *LoadBalancer) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using RingHashConfig within kubernetes types, where deepcopy-gen is used. -func (in *RingHashConfig) DeepCopyInto(out *RingHashConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RingHashConfig. Required by controller-gen. -func (in *RingHashConfig) DeepCopy() *RingHashConfig { - if in == nil { - return nil - } - out := new(RingHashConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new RingHashConfig. Required by controller-gen. -func (in *RingHashConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using LeastRequestConfig within kubernetes types, where deepcopy-gen is used. -func (in *LeastRequestConfig) DeepCopyInto(out *LeastRequestConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LeastRequestConfig. Required by controller-gen. -func (in *LeastRequestConfig) DeepCopy() *LeastRequestConfig { - if in == nil { - return nil - } - out := new(LeastRequestConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new LeastRequestConfig. Required by controller-gen. -func (in *LeastRequestConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HashPolicy within kubernetes types, where deepcopy-gen is used. -func (in *HashPolicy) DeepCopyInto(out *HashPolicy) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HashPolicy. Required by controller-gen. -func (in *HashPolicy) DeepCopy() *HashPolicy { - if in == nil { - return nil - } - out := new(HashPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HashPolicy. Required by controller-gen. -func (in *HashPolicy) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using CookieConfig within kubernetes types, where deepcopy-gen is used. -func (in *CookieConfig) DeepCopyInto(out *CookieConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CookieConfig. Required by controller-gen. -func (in *CookieConfig) DeepCopy() *CookieConfig { - if in == nil { - return nil - } - out := new(CookieConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new CookieConfig. Required by controller-gen. -func (in *CookieConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/destination_policy_json.gen.go b/proto-public/pbmesh/v2beta1/destination_policy_json.gen.go deleted file mode 100644 index fc1c98b08d1e..000000000000 --- a/proto-public/pbmesh/v2beta1/destination_policy_json.gen.go +++ /dev/null @@ -1,99 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for DestinationPolicy -func (this *DestinationPolicy) MarshalJSON() ([]byte, error) { - str, err := DestinationPolicyMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DestinationPolicy -func (this *DestinationPolicy) UnmarshalJSON(b []byte) error { - return DestinationPolicyUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DestinationConfig -func (this *DestinationConfig) MarshalJSON() ([]byte, error) { - str, err := DestinationPolicyMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DestinationConfig -func (this *DestinationConfig) UnmarshalJSON(b []byte) error { - return DestinationPolicyUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for LocalityPrioritization -func (this *LocalityPrioritization) MarshalJSON() ([]byte, error) { - str, err := DestinationPolicyMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for LocalityPrioritization -func (this *LocalityPrioritization) UnmarshalJSON(b []byte) error { - return DestinationPolicyUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for LoadBalancer -func (this *LoadBalancer) MarshalJSON() ([]byte, error) { - str, err := DestinationPolicyMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for LoadBalancer -func (this *LoadBalancer) UnmarshalJSON(b []byte) error { - return DestinationPolicyUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for RingHashConfig -func (this *RingHashConfig) MarshalJSON() ([]byte, error) { - str, err := DestinationPolicyMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for RingHashConfig -func (this *RingHashConfig) UnmarshalJSON(b []byte) error { - return DestinationPolicyUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for LeastRequestConfig -func (this *LeastRequestConfig) MarshalJSON() ([]byte, error) { - str, err := DestinationPolicyMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for LeastRequestConfig -func (this *LeastRequestConfig) UnmarshalJSON(b []byte) error { - return DestinationPolicyUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HashPolicy -func (this *HashPolicy) MarshalJSON() ([]byte, error) { - str, err := DestinationPolicyMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HashPolicy -func (this *HashPolicy) UnmarshalJSON(b []byte) error { - return DestinationPolicyUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for CookieConfig -func (this *CookieConfig) MarshalJSON() ([]byte, error) { - str, err := DestinationPolicyMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for CookieConfig -func (this *CookieConfig) UnmarshalJSON(b []byte) error { - return DestinationPolicyUnmarshaler.Unmarshal(b, this) -} - -var ( - DestinationPolicyMarshaler = &protojson.MarshalOptions{} - DestinationPolicyUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/destinations.pb.binary.go b/proto-public/pbmesh/v2beta1/destinations.pb.binary.go deleted file mode 100644 index 6716785708c0..000000000000 --- a/proto-public/pbmesh/v2beta1/destinations.pb.binary.go +++ /dev/null @@ -1,58 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/destinations.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Destinations) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Destinations) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Destination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Destination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *IPPortAddress) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *IPPortAddress) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *UnixSocketAddress) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *UnixSocketAddress) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *PreparedQueryDestination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *PreparedQueryDestination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/destinations.pb.go b/proto-public/pbmesh/v2beta1/destinations.pb.go deleted file mode 100644 index 623920c5145e..000000000000 --- a/proto-public/pbmesh/v2beta1/destinations.pb.go +++ /dev/null @@ -1,670 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/destinations.proto - -package meshv2beta1 - -import ( - v2beta1 "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbresource "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Destinations struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Selection of workloads these destinations should apply to. - // These can be prefixes or specific workload names. - Workloads *v2beta1.WorkloadSelector `protobuf:"bytes,1,opt,name=workloads,proto3" json:"workloads,omitempty"` - // Destinations is the list of explicit destinations to define for the selected workloads. - Destinations []*Destination `protobuf:"bytes,2,rep,name=destinations,proto3" json:"destinations,omitempty"` - // PQDestinations is the list of prepared query destinations. This field is not supported directly in v2 - // and should only be used for migration reasons. - PqDestinations []*PreparedQueryDestination `protobuf:"bytes,3,rep,name=pq_destinations,json=pqDestinations,proto3" json:"pq_destinations,omitempty"` -} - -func (x *Destinations) Reset() { - *x = Destinations{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destinations_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Destinations) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Destinations) ProtoMessage() {} - -func (x *Destinations) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destinations_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Destinations.ProtoReflect.Descriptor instead. -func (*Destinations) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destinations_proto_rawDescGZIP(), []int{0} -} - -func (x *Destinations) GetWorkloads() *v2beta1.WorkloadSelector { - if x != nil { - return x.Workloads - } - return nil -} - -func (x *Destinations) GetDestinations() []*Destination { - if x != nil { - return x.Destinations - } - return nil -} - -func (x *Destinations) GetPqDestinations() []*PreparedQueryDestination { - if x != nil { - return x.PqDestinations - } - return nil -} - -type Destination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // DestinationRef is the reference to an destination service. This has to be pbcatalog.Service type. - DestinationRef *pbresource.Reference `protobuf:"bytes,1,opt,name=destination_ref,json=destinationRef,proto3" json:"destination_ref,omitempty"` - // DestinationPort is the port name of the destination service. This should be the name - // of the service's target port. - DestinationPort string `protobuf:"bytes,2,opt,name=destination_port,json=destinationPort,proto3" json:"destination_port,omitempty"` - // Datacenter is the datacenter for where this destination service lives. - Datacenter string `protobuf:"bytes,3,opt,name=datacenter,proto3" json:"datacenter,omitempty"` - // ListenAddr is the address where Envoy will listen for requests to this destination. - // It can provided either as an ip:port or as a Unix domain socket. - // - // Types that are assignable to ListenAddr: - // - // *Destination_IpPort - // *Destination_Unix - ListenAddr isDestination_ListenAddr `protobuf_oneof:"listen_addr"` -} - -func (x *Destination) Reset() { - *x = Destination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destinations_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Destination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Destination) ProtoMessage() {} - -func (x *Destination) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destinations_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Destination.ProtoReflect.Descriptor instead. -func (*Destination) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destinations_proto_rawDescGZIP(), []int{1} -} - -func (x *Destination) GetDestinationRef() *pbresource.Reference { - if x != nil { - return x.DestinationRef - } - return nil -} - -func (x *Destination) GetDestinationPort() string { - if x != nil { - return x.DestinationPort - } - return "" -} - -func (x *Destination) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - -func (m *Destination) GetListenAddr() isDestination_ListenAddr { - if m != nil { - return m.ListenAddr - } - return nil -} - -func (x *Destination) GetIpPort() *IPPortAddress { - if x, ok := x.GetListenAddr().(*Destination_IpPort); ok { - return x.IpPort - } - return nil -} - -func (x *Destination) GetUnix() *UnixSocketAddress { - if x, ok := x.GetListenAddr().(*Destination_Unix); ok { - return x.Unix - } - return nil -} - -type isDestination_ListenAddr interface { - isDestination_ListenAddr() -} - -type Destination_IpPort struct { - IpPort *IPPortAddress `protobuf:"bytes,4,opt,name=ip_port,json=ipPort,proto3,oneof"` -} - -type Destination_Unix struct { - Unix *UnixSocketAddress `protobuf:"bytes,5,opt,name=unix,proto3,oneof"` -} - -func (*Destination_IpPort) isDestination_ListenAddr() {} - -func (*Destination_Unix) isDestination_ListenAddr() {} - -type IPPortAddress struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ip is an IPv4 or an IPv6 address. - Ip string `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"` - // port is the port number. - Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` -} - -func (x *IPPortAddress) Reset() { - *x = IPPortAddress{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destinations_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IPPortAddress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IPPortAddress) ProtoMessage() {} - -func (x *IPPortAddress) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destinations_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IPPortAddress.ProtoReflect.Descriptor instead. -func (*IPPortAddress) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destinations_proto_rawDescGZIP(), []int{2} -} - -func (x *IPPortAddress) GetIp() string { - if x != nil { - return x.Ip - } - return "" -} - -func (x *IPPortAddress) GetPort() uint32 { - if x != nil { - return x.Port - } - return 0 -} - -type UnixSocketAddress struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Path is the file system path at which to bind a Unix domain socket listener. - Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - // Mode is the Unix file mode for the socket file. It should be provided - // in the numeric notation, for example, "0600". - Mode string `protobuf:"bytes,2,opt,name=mode,proto3" json:"mode,omitempty"` -} - -func (x *UnixSocketAddress) Reset() { - *x = UnixSocketAddress{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destinations_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UnixSocketAddress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UnixSocketAddress) ProtoMessage() {} - -func (x *UnixSocketAddress) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destinations_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UnixSocketAddress.ProtoReflect.Descriptor instead. -func (*UnixSocketAddress) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destinations_proto_rawDescGZIP(), []int{3} -} - -func (x *UnixSocketAddress) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (x *UnixSocketAddress) GetMode() string { - if x != nil { - return x.Mode - } - return "" -} - -type PreparedQueryDestination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Name is the name of the prepared query to use as an destination. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Datacenter is the datacenter for where this destination service lives. - Datacenter string `protobuf:"bytes,2,opt,name=datacenter,proto3" json:"datacenter,omitempty"` - // ListenAddr is the address where Envoy will listen for requests to this destination. - // It can provided either as an ip:port or as a Unix domain socket. - // - // Types that are assignable to ListenAddr: - // - // *PreparedQueryDestination_Tcp - // *PreparedQueryDestination_Unix - ListenAddr isPreparedQueryDestination_ListenAddr `protobuf_oneof:"listen_addr"` - DestinationConfig *DestinationConfiguration `protobuf:"bytes,6,opt,name=destination_config,json=destinationConfig,proto3" json:"destination_config,omitempty"` -} - -func (x *PreparedQueryDestination) Reset() { - *x = PreparedQueryDestination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destinations_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PreparedQueryDestination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PreparedQueryDestination) ProtoMessage() {} - -func (x *PreparedQueryDestination) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destinations_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PreparedQueryDestination.ProtoReflect.Descriptor instead. -func (*PreparedQueryDestination) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destinations_proto_rawDescGZIP(), []int{4} -} - -func (x *PreparedQueryDestination) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *PreparedQueryDestination) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - -func (m *PreparedQueryDestination) GetListenAddr() isPreparedQueryDestination_ListenAddr { - if m != nil { - return m.ListenAddr - } - return nil -} - -func (x *PreparedQueryDestination) GetTcp() *IPPortAddress { - if x, ok := x.GetListenAddr().(*PreparedQueryDestination_Tcp); ok { - return x.Tcp - } - return nil -} - -func (x *PreparedQueryDestination) GetUnix() *UnixSocketAddress { - if x, ok := x.GetListenAddr().(*PreparedQueryDestination_Unix); ok { - return x.Unix - } - return nil -} - -func (x *PreparedQueryDestination) GetDestinationConfig() *DestinationConfiguration { - if x != nil { - return x.DestinationConfig - } - return nil -} - -type isPreparedQueryDestination_ListenAddr interface { - isPreparedQueryDestination_ListenAddr() -} - -type PreparedQueryDestination_Tcp struct { - Tcp *IPPortAddress `protobuf:"bytes,4,opt,name=tcp,proto3,oneof"` -} - -type PreparedQueryDestination_Unix struct { - Unix *UnixSocketAddress `protobuf:"bytes,5,opt,name=unix,proto3,oneof"` -} - -func (*PreparedQueryDestination_Tcp) isPreparedQueryDestination_ListenAddr() {} - -func (*PreparedQueryDestination_Unix) isPreparedQueryDestination_ListenAddr() {} - -var File_pbmesh_v2beta1_destinations_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_destinations_proto_rawDesc = []byte{ - 0x0a, 0x21, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x1a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9a, - 0x02, 0x0a, 0x0c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x50, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, - 0x73, 0x12, 0x4e, 0x0a, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x60, 0x0a, 0x0f, 0x70, 0x71, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, - 0x72, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x70, 0x71, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0xc7, 0x02, 0x0a, 0x0b, - 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x0f, 0x64, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0e, 0x64, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, - 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, - 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x47, 0x0a, 0x07, 0x69, 0x70, 0x5f, 0x70, 0x6f, 0x72, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x50, 0x50, 0x6f, 0x72, 0x74, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x06, 0x69, 0x70, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x46, - 0x0a, 0x04, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x6e, 0x69, - 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, - 0x52, 0x04, 0x75, 0x6e, 0x69, 0x78, 0x42, 0x0d, 0x0a, 0x0b, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x22, 0x33, 0x0a, 0x0d, 0x49, 0x50, 0x50, 0x6f, 0x72, 0x74, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x3b, 0x0a, 0x11, 0x55, 0x6e, - 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, - 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0xcf, 0x02, 0x0a, 0x18, 0x50, 0x72, 0x65, 0x70, - 0x61, 0x72, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, - 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, - 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x03, 0x74, 0x63, 0x70, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x50, 0x50, 0x6f, 0x72, 0x74, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x03, 0x74, 0x63, 0x70, 0x12, 0x46, 0x0a, 0x04, 0x75, 0x6e, - 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x04, 0x75, 0x6e, - 0x69, 0x78, 0x12, 0x66, 0x0a, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x0d, 0x0a, 0x0b, 0x6c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x42, 0x92, 0x02, 0x0a, 0x21, 0x63, 0x6f, - 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, - 0x11, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, - 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, - 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, - 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, - 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, - 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, - 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_destinations_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_destinations_proto_rawDescData = file_pbmesh_v2beta1_destinations_proto_rawDesc -) - -func file_pbmesh_v2beta1_destinations_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_destinations_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_destinations_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_destinations_proto_rawDescData) - }) - return file_pbmesh_v2beta1_destinations_proto_rawDescData -} - -var file_pbmesh_v2beta1_destinations_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_pbmesh_v2beta1_destinations_proto_goTypes = []interface{}{ - (*Destinations)(nil), // 0: hashicorp.consul.mesh.v2beta1.Destinations - (*Destination)(nil), // 1: hashicorp.consul.mesh.v2beta1.Destination - (*IPPortAddress)(nil), // 2: hashicorp.consul.mesh.v2beta1.IPPortAddress - (*UnixSocketAddress)(nil), // 3: hashicorp.consul.mesh.v2beta1.UnixSocketAddress - (*PreparedQueryDestination)(nil), // 4: hashicorp.consul.mesh.v2beta1.PreparedQueryDestination - (*v2beta1.WorkloadSelector)(nil), // 5: hashicorp.consul.catalog.v2beta1.WorkloadSelector - (*pbresource.Reference)(nil), // 6: hashicorp.consul.resource.Reference - (*DestinationConfiguration)(nil), // 7: hashicorp.consul.mesh.v2beta1.DestinationConfiguration -} -var file_pbmesh_v2beta1_destinations_proto_depIdxs = []int32{ - 5, // 0: hashicorp.consul.mesh.v2beta1.Destinations.workloads:type_name -> hashicorp.consul.catalog.v2beta1.WorkloadSelector - 1, // 1: hashicorp.consul.mesh.v2beta1.Destinations.destinations:type_name -> hashicorp.consul.mesh.v2beta1.Destination - 4, // 2: hashicorp.consul.mesh.v2beta1.Destinations.pq_destinations:type_name -> hashicorp.consul.mesh.v2beta1.PreparedQueryDestination - 6, // 3: hashicorp.consul.mesh.v2beta1.Destination.destination_ref:type_name -> hashicorp.consul.resource.Reference - 2, // 4: hashicorp.consul.mesh.v2beta1.Destination.ip_port:type_name -> hashicorp.consul.mesh.v2beta1.IPPortAddress - 3, // 5: hashicorp.consul.mesh.v2beta1.Destination.unix:type_name -> hashicorp.consul.mesh.v2beta1.UnixSocketAddress - 2, // 6: hashicorp.consul.mesh.v2beta1.PreparedQueryDestination.tcp:type_name -> hashicorp.consul.mesh.v2beta1.IPPortAddress - 3, // 7: hashicorp.consul.mesh.v2beta1.PreparedQueryDestination.unix:type_name -> hashicorp.consul.mesh.v2beta1.UnixSocketAddress - 7, // 8: hashicorp.consul.mesh.v2beta1.PreparedQueryDestination.destination_config:type_name -> hashicorp.consul.mesh.v2beta1.DestinationConfiguration - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_destinations_proto_init() } -func file_pbmesh_v2beta1_destinations_proto_init() { - if File_pbmesh_v2beta1_destinations_proto != nil { - return - } - file_pbmesh_v2beta1_destinations_configuration_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_destinations_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Destinations); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destinations_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Destination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destinations_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IPPortAddress); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destinations_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnixSocketAddress); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destinations_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PreparedQueryDestination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v2beta1_destinations_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*Destination_IpPort)(nil), - (*Destination_Unix)(nil), - } - file_pbmesh_v2beta1_destinations_proto_msgTypes[4].OneofWrappers = []interface{}{ - (*PreparedQueryDestination_Tcp)(nil), - (*PreparedQueryDestination_Unix)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_destinations_proto_rawDesc, - NumEnums: 0, - NumMessages: 5, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_destinations_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_destinations_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_destinations_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_destinations_proto = out.File - file_pbmesh_v2beta1_destinations_proto_rawDesc = nil - file_pbmesh_v2beta1_destinations_proto_goTypes = nil - file_pbmesh_v2beta1_destinations_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/destinations.proto b/proto-public/pbmesh/v2beta1/destinations.proto deleted file mode 100644 index 33c7ea919597..000000000000 --- a/proto-public/pbmesh/v2beta1/destinations.proto +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "pbcatalog/v2beta1/selector.proto"; -import "pbmesh/v2beta1/destinations_configuration.proto"; -import "pbresource/annotations.proto"; -import "pbresource/resource.proto"; - -message Destinations { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // Selection of workloads these destinations should apply to. - // These can be prefixes or specific workload names. - hashicorp.consul.catalog.v2beta1.WorkloadSelector workloads = 1; - - // Destinations is the list of explicit destinations to define for the selected workloads. - repeated Destination destinations = 2; - - // PQDestinations is the list of prepared query destinations. This field is not supported directly in v2 - // and should only be used for migration reasons. - repeated PreparedQueryDestination pq_destinations = 3; -} - -message Destination { - // DestinationRef is the reference to an destination service. This has to be pbcatalog.Service type. - hashicorp.consul.resource.Reference destination_ref = 1; - - // DestinationPort is the port name of the destination service. This should be the name - // of the service's target port. - string destination_port = 2; - - // Datacenter is the datacenter for where this destination service lives. - string datacenter = 3; - - // ListenAddr is the address where Envoy will listen for requests to this destination. - // It can provided either as an ip:port or as a Unix domain socket. - oneof listen_addr { - IPPortAddress ip_port = 4; - UnixSocketAddress unix = 5; - } -} - -message IPPortAddress { - // ip is an IPv4 or an IPv6 address. - string ip = 1; - - // port is the port number. - uint32 port = 2; -} - -message UnixSocketAddress { - // Path is the file system path at which to bind a Unix domain socket listener. - string path = 1; - - // Mode is the Unix file mode for the socket file. It should be provided - // in the numeric notation, for example, "0600". - string mode = 2; -} - -message PreparedQueryDestination { - // Name is the name of the prepared query to use as an destination. - string name = 1; - - // Datacenter is the datacenter for where this destination service lives. - string datacenter = 2; - - // ListenAddr is the address where Envoy will listen for requests to this destination. - // It can provided either as an ip:port or as a Unix domain socket. - oneof listen_addr { - IPPortAddress tcp = 4; - UnixSocketAddress unix = 5; - } - - DestinationConfiguration destination_config = 6; -} diff --git a/proto-public/pbmesh/v2beta1/destinations_configuration.pb.binary.go b/proto-public/pbmesh/v2beta1/destinations_configuration.pb.binary.go deleted file mode 100644 index 7aa00d90651d..000000000000 --- a/proto-public/pbmesh/v2beta1/destinations_configuration.pb.binary.go +++ /dev/null @@ -1,58 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/destinations_configuration.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationsConfiguration) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationsConfiguration) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationConfigOverrides) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationConfigOverrides) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationConfiguration) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationConfiguration) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationLimits) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationLimits) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *PassiveHealthCheck) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *PassiveHealthCheck) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/destinations_configuration.pb.go b/proto-public/pbmesh/v2beta1/destinations_configuration.pb.go deleted file mode 100644 index 2e6a8f5e969d..000000000000 --- a/proto-public/pbmesh/v2beta1/destinations_configuration.pb.go +++ /dev/null @@ -1,701 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/destinations_configuration.proto - -package meshv2beta1 - -import ( - v2beta1 "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbresource "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type DestinationsConfiguration struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Selection of workloads these destinations should apply to. - // These can be prefixes or specific workload names. - Workloads *v2beta1.WorkloadSelector `protobuf:"bytes,1,opt,name=workloads,proto3" json:"workloads,omitempty"` - // DefaultConfig applies to all destinations for the workloads selected by this resource. - DefaultConfig *DestinationConfiguration `protobuf:"bytes,2,opt,name=default_config,json=defaultConfig,proto3" json:"default_config,omitempty"` - // ConfigOverrides provides per-destination or per-destination-port config overrides. - ConfigOverrides []*DestinationConfigOverrides `protobuf:"bytes,3,rep,name=config_overrides,json=configOverrides,proto3" json:"config_overrides,omitempty"` -} - -func (x *DestinationsConfiguration) Reset() { - *x = DestinationsConfiguration{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationsConfiguration) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationsConfiguration) ProtoMessage() {} - -func (x *DestinationsConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DestinationsConfiguration.ProtoReflect.Descriptor instead. -func (*DestinationsConfiguration) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destinations_configuration_proto_rawDescGZIP(), []int{0} -} - -func (x *DestinationsConfiguration) GetWorkloads() *v2beta1.WorkloadSelector { - if x != nil { - return x.Workloads - } - return nil -} - -func (x *DestinationsConfiguration) GetDefaultConfig() *DestinationConfiguration { - if x != nil { - return x.DefaultConfig - } - return nil -} - -func (x *DestinationsConfiguration) GetConfigOverrides() []*DestinationConfigOverrides { - if x != nil { - return x.ConfigOverrides - } - return nil -} - -// UpstreamConfigOverrides allow to override destination configuration per destination_ref/port/datacenter. -// In that sense, those three fields (destination_ref, destination_port and datacenter) are treated -// sort of like map keys and config is a like a map value for that key. -type DestinationConfigOverrides struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // DestinationRef is the reference to an destination service that this configuration applies to. - // This has to be pbcatalog.Service type. - DestinationRef *pbresource.Reference `protobuf:"bytes,1,opt,name=destination_ref,json=destinationRef,proto3" json:"destination_ref,omitempty"` - // DestinationPort is the port name of the destination service. This should be the name - // of the service's target port. If not provided, this configuration will apply to all ports of an destination. - DestinationPort string `protobuf:"bytes,2,opt,name=destination_port,json=destinationPort,proto3" json:"destination_port,omitempty"` - // Datacenter is the datacenter for where this destination service lives. - Datacenter string `protobuf:"bytes,3,opt,name=datacenter,proto3" json:"datacenter,omitempty"` - // Config is the configuration that should apply to this destination. - Config *DestinationConfiguration `protobuf:"bytes,4,opt,name=config,proto3" json:"config,omitempty"` -} - -func (x *DestinationConfigOverrides) Reset() { - *x = DestinationConfigOverrides{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationConfigOverrides) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationConfigOverrides) ProtoMessage() {} - -func (x *DestinationConfigOverrides) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DestinationConfigOverrides.ProtoReflect.Descriptor instead. -func (*DestinationConfigOverrides) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destinations_configuration_proto_rawDescGZIP(), []int{1} -} - -func (x *DestinationConfigOverrides) GetDestinationRef() *pbresource.Reference { - if x != nil { - return x.DestinationRef - } - return nil -} - -func (x *DestinationConfigOverrides) GetDestinationPort() string { - if x != nil { - return x.DestinationPort - } - return "" -} - -func (x *DestinationConfigOverrides) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - -func (x *DestinationConfigOverrides) GetConfig() *DestinationConfiguration { - if x != nil { - return x.Config - } - return nil -} - -type DestinationConfiguration struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Protocol overrides destination's port protocol. If no port for an destination is specified - // or if used in the default configuration, this protocol will be used for all ports - // or for all ports of all destinations respectively. - Protocol v2beta1.Protocol `protobuf:"varint,1,opt,name=protocol,proto3,enum=hashicorp.consul.catalog.v2beta1.Protocol" json:"protocol,omitempty"` - // ConnectTimeout is the timeout used when making a new - // connection to this destination. Defaults to 5 seconds if not set. - // +kubebuilder:validation:Format=duration - ConnectTimeout *durationpb.Duration `protobuf:"bytes,2,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` - // Limits are the set of limits that are applied to the proxy for a specific destination. - Limits *DestinationLimits `protobuf:"bytes,3,opt,name=limits,proto3" json:"limits,omitempty"` - // PassiveHealthCheck configuration determines how destination proxy instances will - // be monitored for removal from the load balancing pool. - PassiveHealthCheck *PassiveHealthCheck `protobuf:"bytes,4,opt,name=passive_health_check,json=passiveHealthCheck,proto3" json:"passive_health_check,omitempty"` - // BalanceOutboundConnections indicates how the proxy should attempt to distribute - // connections across worker threads. - BalanceOutboundConnections BalanceConnections `protobuf:"varint,5,opt,name=balance_outbound_connections,json=balanceOutboundConnections,proto3,enum=hashicorp.consul.mesh.v2beta1.BalanceConnections" json:"balance_outbound_connections,omitempty"` - // MeshGatewayMode is the Mesh Gateway routing mode. - MeshGatewayMode MeshGatewayMode `protobuf:"varint,6,opt,name=mesh_gateway_mode,json=meshGatewayMode,proto3,enum=hashicorp.consul.mesh.v2beta1.MeshGatewayMode" json:"mesh_gateway_mode,omitempty"` -} - -func (x *DestinationConfiguration) Reset() { - *x = DestinationConfiguration{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationConfiguration) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationConfiguration) ProtoMessage() {} - -func (x *DestinationConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DestinationConfiguration.ProtoReflect.Descriptor instead. -func (*DestinationConfiguration) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destinations_configuration_proto_rawDescGZIP(), []int{2} -} - -func (x *DestinationConfiguration) GetProtocol() v2beta1.Protocol { - if x != nil { - return x.Protocol - } - return v2beta1.Protocol(0) -} - -func (x *DestinationConfiguration) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -func (x *DestinationConfiguration) GetLimits() *DestinationLimits { - if x != nil { - return x.Limits - } - return nil -} - -func (x *DestinationConfiguration) GetPassiveHealthCheck() *PassiveHealthCheck { - if x != nil { - return x.PassiveHealthCheck - } - return nil -} - -func (x *DestinationConfiguration) GetBalanceOutboundConnections() BalanceConnections { - if x != nil { - return x.BalanceOutboundConnections - } - return BalanceConnections_BALANCE_CONNECTIONS_DEFAULT -} - -func (x *DestinationConfiguration) GetMeshGatewayMode() MeshGatewayMode { - if x != nil { - return x.MeshGatewayMode - } - return MeshGatewayMode_MESH_GATEWAY_MODE_UNSPECIFIED -} - -// UpstreamLimits describes the limits that are associated with a specific -// destination of a service instance. -type DestinationLimits struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // MaxConnections is the maximum number of connections the local proxy can - // make to the destination service. - MaxConnections *wrapperspb.UInt32Value `protobuf:"bytes,1,opt,name=max_connections,json=maxConnections,proto3" json:"max_connections,omitempty"` - // MaxPendingRequests is the maximum number of requests that will be queued - // waiting for an available connection. This is mostly applicable to HTTP/1.1 - // clusters since all HTTP/2 requests are streamed over a single - // connection. - MaxPendingRequests *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=max_pending_requests,json=maxPendingRequests,proto3" json:"max_pending_requests,omitempty"` - // MaxConcurrentRequests is the maximum number of in-flight requests that will be allowed - // to the destination cluster at a point in time. This is mostly applicable to HTTP/2 - // clusters since all HTTP/1.1 requests are limited by MaxConnections. - MaxConcurrentRequests *wrapperspb.UInt32Value `protobuf:"bytes,3,opt,name=max_concurrent_requests,json=maxConcurrentRequests,proto3" json:"max_concurrent_requests,omitempty"` -} - -func (x *DestinationLimits) Reset() { - *x = DestinationLimits{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationLimits) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationLimits) ProtoMessage() {} - -func (x *DestinationLimits) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DestinationLimits.ProtoReflect.Descriptor instead. -func (*DestinationLimits) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destinations_configuration_proto_rawDescGZIP(), []int{3} -} - -func (x *DestinationLimits) GetMaxConnections() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxConnections - } - return nil -} - -func (x *DestinationLimits) GetMaxPendingRequests() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxPendingRequests - } - return nil -} - -func (x *DestinationLimits) GetMaxConcurrentRequests() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxConcurrentRequests - } - return nil -} - -type PassiveHealthCheck struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Interval between health check analysis sweeps. Each sweep may remove - // hosts or return hosts to the pool. - // +kubebuilder:validation:Format=duration - Interval *durationpb.Duration `protobuf:"bytes,1,opt,name=interval,proto3" json:"interval,omitempty"` - // MaxFailures is the count of consecutive failures that results in a host - // being removed from the pool. - MaxFailures uint32 `protobuf:"varint,2,opt,name=max_failures,json=maxFailures,proto3" json:"max_failures,omitempty"` - // EnforcingConsecutive5XX is 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. - EnforcingConsecutive_5Xx uint32 `protobuf:"varint,3,opt,name=enforcing_consecutive_5xx,json=enforcingConsecutive5xx,proto3" json:"enforcing_consecutive_5xx,omitempty"` -} - -func (x *PassiveHealthCheck) Reset() { - *x = PassiveHealthCheck{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PassiveHealthCheck) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PassiveHealthCheck) ProtoMessage() {} - -func (x *PassiveHealthCheck) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PassiveHealthCheck.ProtoReflect.Descriptor instead. -func (*PassiveHealthCheck) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_destinations_configuration_proto_rawDescGZIP(), []int{4} -} - -func (x *PassiveHealthCheck) GetInterval() *durationpb.Duration { - if x != nil { - return x.Interval - } - return nil -} - -func (x *PassiveHealthCheck) GetMaxFailures() uint32 { - if x != nil { - return x.MaxFailures - } - return 0 -} - -func (x *PassiveHealthCheck) GetEnforcingConsecutive_5Xx() uint32 { - if x != nil { - return x.EnforcingConsecutive_5Xx - } - return 0 -} - -var File_pbmesh_v2beta1_destinations_configuration_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_destinations_configuration_proto_rawDesc = []byte{ - 0x0a, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2f, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, - 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x19, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbb, 0x02, 0x0a, - 0x19, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x09, 0x77, 0x6f, - 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, 0x5e, 0x0a, 0x0e, - 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x64, 0x0a, 0x10, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x73, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0x87, 0x02, 0x0a, 0x1a, 0x44, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x4d, 0x0a, 0x0f, 0x64, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0e, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, - 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, - 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, - 0x74, 0x65, 0x72, 0x12, 0x4f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x22, 0xa6, 0x04, 0x0a, 0x18, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x46, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, - 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x48, 0x0a, - 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, - 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x63, 0x0a, 0x14, 0x70, 0x61, 0x73, 0x73, 0x69, - 0x76, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x12, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, - 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x73, 0x0a, 0x1c, - 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x1a, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x4f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x5a, 0x0a, 0x11, 0x6d, 0x65, 0x73, 0x68, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x65, 0x73, - 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0f, 0x6d, 0x65, - 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x80, 0x02, - 0x0a, 0x11, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4e, 0x0a, 0x14, 0x6d, 0x61, - 0x78, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, - 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x6d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x17, 0x6d, 0x61, - 0x78, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x43, 0x6f, - 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, - 0x22, 0xaa, 0x01, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x35, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x21, - 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, - 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x63, - 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x35, 0x78, 0x78, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x17, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x43, - 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, 0x78, 0x42, 0x9f, 0x02, - 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x42, 0x1e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, - 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, - 0x65, 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, - 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_destinations_configuration_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_destinations_configuration_proto_rawDescData = file_pbmesh_v2beta1_destinations_configuration_proto_rawDesc -) - -func file_pbmesh_v2beta1_destinations_configuration_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_destinations_configuration_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_destinations_configuration_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_destinations_configuration_proto_rawDescData) - }) - return file_pbmesh_v2beta1_destinations_configuration_proto_rawDescData -} - -var file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_pbmesh_v2beta1_destinations_configuration_proto_goTypes = []interface{}{ - (*DestinationsConfiguration)(nil), // 0: hashicorp.consul.mesh.v2beta1.DestinationsConfiguration - (*DestinationConfigOverrides)(nil), // 1: hashicorp.consul.mesh.v2beta1.DestinationConfigOverrides - (*DestinationConfiguration)(nil), // 2: hashicorp.consul.mesh.v2beta1.DestinationConfiguration - (*DestinationLimits)(nil), // 3: hashicorp.consul.mesh.v2beta1.DestinationLimits - (*PassiveHealthCheck)(nil), // 4: hashicorp.consul.mesh.v2beta1.PassiveHealthCheck - (*v2beta1.WorkloadSelector)(nil), // 5: hashicorp.consul.catalog.v2beta1.WorkloadSelector - (*pbresource.Reference)(nil), // 6: hashicorp.consul.resource.Reference - (v2beta1.Protocol)(0), // 7: hashicorp.consul.catalog.v2beta1.Protocol - (*durationpb.Duration)(nil), // 8: google.protobuf.Duration - (BalanceConnections)(0), // 9: hashicorp.consul.mesh.v2beta1.BalanceConnections - (MeshGatewayMode)(0), // 10: hashicorp.consul.mesh.v2beta1.MeshGatewayMode - (*wrapperspb.UInt32Value)(nil), // 11: google.protobuf.UInt32Value -} -var file_pbmesh_v2beta1_destinations_configuration_proto_depIdxs = []int32{ - 5, // 0: hashicorp.consul.mesh.v2beta1.DestinationsConfiguration.workloads:type_name -> hashicorp.consul.catalog.v2beta1.WorkloadSelector - 2, // 1: hashicorp.consul.mesh.v2beta1.DestinationsConfiguration.default_config:type_name -> hashicorp.consul.mesh.v2beta1.DestinationConfiguration - 1, // 2: hashicorp.consul.mesh.v2beta1.DestinationsConfiguration.config_overrides:type_name -> hashicorp.consul.mesh.v2beta1.DestinationConfigOverrides - 6, // 3: hashicorp.consul.mesh.v2beta1.DestinationConfigOverrides.destination_ref:type_name -> hashicorp.consul.resource.Reference - 2, // 4: hashicorp.consul.mesh.v2beta1.DestinationConfigOverrides.config:type_name -> hashicorp.consul.mesh.v2beta1.DestinationConfiguration - 7, // 5: hashicorp.consul.mesh.v2beta1.DestinationConfiguration.protocol:type_name -> hashicorp.consul.catalog.v2beta1.Protocol - 8, // 6: hashicorp.consul.mesh.v2beta1.DestinationConfiguration.connect_timeout:type_name -> google.protobuf.Duration - 3, // 7: hashicorp.consul.mesh.v2beta1.DestinationConfiguration.limits:type_name -> hashicorp.consul.mesh.v2beta1.DestinationLimits - 4, // 8: hashicorp.consul.mesh.v2beta1.DestinationConfiguration.passive_health_check:type_name -> hashicorp.consul.mesh.v2beta1.PassiveHealthCheck - 9, // 9: hashicorp.consul.mesh.v2beta1.DestinationConfiguration.balance_outbound_connections:type_name -> hashicorp.consul.mesh.v2beta1.BalanceConnections - 10, // 10: hashicorp.consul.mesh.v2beta1.DestinationConfiguration.mesh_gateway_mode:type_name -> hashicorp.consul.mesh.v2beta1.MeshGatewayMode - 11, // 11: hashicorp.consul.mesh.v2beta1.DestinationLimits.max_connections:type_name -> google.protobuf.UInt32Value - 11, // 12: hashicorp.consul.mesh.v2beta1.DestinationLimits.max_pending_requests:type_name -> google.protobuf.UInt32Value - 11, // 13: hashicorp.consul.mesh.v2beta1.DestinationLimits.max_concurrent_requests:type_name -> google.protobuf.UInt32Value - 8, // 14: hashicorp.consul.mesh.v2beta1.PassiveHealthCheck.interval:type_name -> google.protobuf.Duration - 15, // [15:15] is the sub-list for method output_type - 15, // [15:15] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_destinations_configuration_proto_init() } -func file_pbmesh_v2beta1_destinations_configuration_proto_init() { - if File_pbmesh_v2beta1_destinations_configuration_proto != nil { - return - } - file_pbmesh_v2beta1_connection_proto_init() - file_pbmesh_v2beta1_routing_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationsConfiguration); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationConfigOverrides); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationConfiguration); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationLimits); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PassiveHealthCheck); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_destinations_configuration_proto_rawDesc, - NumEnums: 0, - NumMessages: 5, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_destinations_configuration_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_destinations_configuration_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_destinations_configuration_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_destinations_configuration_proto = out.File - file_pbmesh_v2beta1_destinations_configuration_proto_rawDesc = nil - file_pbmesh_v2beta1_destinations_configuration_proto_goTypes = nil - file_pbmesh_v2beta1_destinations_configuration_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/destinations_configuration.proto b/proto-public/pbmesh/v2beta1/destinations_configuration.proto deleted file mode 100644 index facdde6e1f5a..000000000000 --- a/proto-public/pbmesh/v2beta1/destinations_configuration.proto +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "google/protobuf/duration.proto"; -import "google/protobuf/wrappers.proto"; -import "pbcatalog/v2beta1/protocol.proto"; -import "pbcatalog/v2beta1/selector.proto"; -import "pbmesh/v2beta1/connection.proto"; -import "pbmesh/v2beta1/routing.proto"; -import "pbresource/annotations.proto"; -import "pbresource/resource.proto"; - -message DestinationsConfiguration { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // Selection of workloads these destinations should apply to. - // These can be prefixes or specific workload names. - hashicorp.consul.catalog.v2beta1.WorkloadSelector workloads = 1; - - // DefaultConfig applies to all destinations for the workloads selected by this resource. - DestinationConfiguration default_config = 2; - - // ConfigOverrides provides per-destination or per-destination-port config overrides. - repeated DestinationConfigOverrides config_overrides = 3; -} - -// UpstreamConfigOverrides allow to override destination configuration per destination_ref/port/datacenter. -// In that sense, those three fields (destination_ref, destination_port and datacenter) are treated -// sort of like map keys and config is a like a map value for that key. -message DestinationConfigOverrides { - // DestinationRef is the reference to an destination service that this configuration applies to. - // This has to be pbcatalog.Service type. - hashicorp.consul.resource.Reference destination_ref = 1; - - // DestinationPort is the port name of the destination service. This should be the name - // of the service's target port. If not provided, this configuration will apply to all ports of an destination. - string destination_port = 2; - - // Datacenter is the datacenter for where this destination service lives. - string datacenter = 3; - - // Config is the configuration that should apply to this destination. - DestinationConfiguration config = 4; -} - -message DestinationConfiguration { - // Protocol overrides destination's port protocol. If no port for an destination is specified - // or if used in the default configuration, this protocol will be used for all ports - // or for all ports of all destinations respectively. - hashicorp.consul.catalog.v2beta1.Protocol protocol = 1; - - // ConnectTimeout is the timeout used when making a new - // connection to this destination. Defaults to 5 seconds if not set. - // +kubebuilder:validation:Format=duration - google.protobuf.Duration connect_timeout = 2; - - // Limits are the set of limits that are applied to the proxy for a specific destination. - DestinationLimits limits = 3; - - // PassiveHealthCheck configuration determines how destination proxy instances will - // be monitored for removal from the load balancing pool. - PassiveHealthCheck passive_health_check = 4; - - // BalanceOutboundConnections indicates how the proxy should attempt to distribute - // connections across worker threads. - BalanceConnections balance_outbound_connections = 5; - - // MeshGatewayMode is the Mesh Gateway routing mode. - MeshGatewayMode mesh_gateway_mode = 6; -} - -// UpstreamLimits describes the limits that are associated with a specific -// destination of a service instance. -message DestinationLimits { - // MaxConnections is the maximum number of connections the local proxy can - // make to the destination service. - google.protobuf.UInt32Value max_connections = 1; - - // MaxPendingRequests is the maximum number of requests that will be queued - // waiting for an available connection. This is mostly applicable to HTTP/1.1 - // clusters since all HTTP/2 requests are streamed over a single - // connection. - google.protobuf.UInt32Value max_pending_requests = 2; - - // MaxConcurrentRequests is the maximum number of in-flight requests that will be allowed - // to the destination cluster at a point in time. This is mostly applicable to HTTP/2 - // clusters since all HTTP/1.1 requests are limited by MaxConnections. - google.protobuf.UInt32Value max_concurrent_requests = 3; -} - -message PassiveHealthCheck { - // Interval between health check analysis sweeps. Each sweep may remove - // hosts or return hosts to the pool. - // +kubebuilder:validation:Format=duration - google.protobuf.Duration interval = 1; - - // MaxFailures is the count of consecutive failures that results in a host - // being removed from the pool. - uint32 max_failures = 2; - - // EnforcingConsecutive5XX is 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. - uint32 enforcing_consecutive_5xx = 3; -} diff --git a/proto-public/pbmesh/v2beta1/destinations_configuration_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/destinations_configuration_deepcopy.gen.go deleted file mode 100644 index 1c7f04e7f23a..000000000000 --- a/proto-public/pbmesh/v2beta1/destinations_configuration_deepcopy.gen.go +++ /dev/null @@ -1,111 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using DestinationsConfiguration within kubernetes types, where deepcopy-gen is used. -func (in *DestinationsConfiguration) DeepCopyInto(out *DestinationsConfiguration) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationsConfiguration. Required by controller-gen. -func (in *DestinationsConfiguration) DeepCopy() *DestinationsConfiguration { - if in == nil { - return nil - } - out := new(DestinationsConfiguration) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DestinationsConfiguration. Required by controller-gen. -func (in *DestinationsConfiguration) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DestinationConfigOverrides within kubernetes types, where deepcopy-gen is used. -func (in *DestinationConfigOverrides) DeepCopyInto(out *DestinationConfigOverrides) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationConfigOverrides. Required by controller-gen. -func (in *DestinationConfigOverrides) DeepCopy() *DestinationConfigOverrides { - if in == nil { - return nil - } - out := new(DestinationConfigOverrides) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DestinationConfigOverrides. Required by controller-gen. -func (in *DestinationConfigOverrides) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DestinationConfiguration within kubernetes types, where deepcopy-gen is used. -func (in *DestinationConfiguration) DeepCopyInto(out *DestinationConfiguration) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationConfiguration. Required by controller-gen. -func (in *DestinationConfiguration) DeepCopy() *DestinationConfiguration { - if in == nil { - return nil - } - out := new(DestinationConfiguration) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DestinationConfiguration. Required by controller-gen. -func (in *DestinationConfiguration) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DestinationLimits within kubernetes types, where deepcopy-gen is used. -func (in *DestinationLimits) DeepCopyInto(out *DestinationLimits) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationLimits. Required by controller-gen. -func (in *DestinationLimits) DeepCopy() *DestinationLimits { - if in == nil { - return nil - } - out := new(DestinationLimits) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DestinationLimits. Required by controller-gen. -func (in *DestinationLimits) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using PassiveHealthCheck within kubernetes types, where deepcopy-gen is used. -func (in *PassiveHealthCheck) DeepCopyInto(out *PassiveHealthCheck) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PassiveHealthCheck. Required by controller-gen. -func (in *PassiveHealthCheck) DeepCopy() *PassiveHealthCheck { - if in == nil { - return nil - } - out := new(PassiveHealthCheck) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new PassiveHealthCheck. Required by controller-gen. -func (in *PassiveHealthCheck) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/destinations_configuration_json.gen.go b/proto-public/pbmesh/v2beta1/destinations_configuration_json.gen.go deleted file mode 100644 index f8daafdbeb51..000000000000 --- a/proto-public/pbmesh/v2beta1/destinations_configuration_json.gen.go +++ /dev/null @@ -1,66 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for DestinationsConfiguration -func (this *DestinationsConfiguration) MarshalJSON() ([]byte, error) { - str, err := DestinationsConfigurationMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DestinationsConfiguration -func (this *DestinationsConfiguration) UnmarshalJSON(b []byte) error { - return DestinationsConfigurationUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DestinationConfigOverrides -func (this *DestinationConfigOverrides) MarshalJSON() ([]byte, error) { - str, err := DestinationsConfigurationMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DestinationConfigOverrides -func (this *DestinationConfigOverrides) UnmarshalJSON(b []byte) error { - return DestinationsConfigurationUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DestinationConfiguration -func (this *DestinationConfiguration) MarshalJSON() ([]byte, error) { - str, err := DestinationsConfigurationMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DestinationConfiguration -func (this *DestinationConfiguration) UnmarshalJSON(b []byte) error { - return DestinationsConfigurationUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DestinationLimits -func (this *DestinationLimits) MarshalJSON() ([]byte, error) { - str, err := DestinationsConfigurationMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DestinationLimits -func (this *DestinationLimits) UnmarshalJSON(b []byte) error { - return DestinationsConfigurationUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for PassiveHealthCheck -func (this *PassiveHealthCheck) MarshalJSON() ([]byte, error) { - str, err := DestinationsConfigurationMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for PassiveHealthCheck -func (this *PassiveHealthCheck) UnmarshalJSON(b []byte) error { - return DestinationsConfigurationUnmarshaler.Unmarshal(b, this) -} - -var ( - DestinationsConfigurationMarshaler = &protojson.MarshalOptions{} - DestinationsConfigurationUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/destinations_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/destinations_deepcopy.gen.go deleted file mode 100644 index 3f513b7d861d..000000000000 --- a/proto-public/pbmesh/v2beta1/destinations_deepcopy.gen.go +++ /dev/null @@ -1,111 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using Destinations within kubernetes types, where deepcopy-gen is used. -func (in *Destinations) DeepCopyInto(out *Destinations) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Destinations. Required by controller-gen. -func (in *Destinations) DeepCopy() *Destinations { - if in == nil { - return nil - } - out := new(Destinations) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Destinations. Required by controller-gen. -func (in *Destinations) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Destination within kubernetes types, where deepcopy-gen is used. -func (in *Destination) DeepCopyInto(out *Destination) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Destination. Required by controller-gen. -func (in *Destination) DeepCopy() *Destination { - if in == nil { - return nil - } - out := new(Destination) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Destination. Required by controller-gen. -func (in *Destination) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using IPPortAddress within kubernetes types, where deepcopy-gen is used. -func (in *IPPortAddress) DeepCopyInto(out *IPPortAddress) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPPortAddress. Required by controller-gen. -func (in *IPPortAddress) DeepCopy() *IPPortAddress { - if in == nil { - return nil - } - out := new(IPPortAddress) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new IPPortAddress. Required by controller-gen. -func (in *IPPortAddress) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using UnixSocketAddress within kubernetes types, where deepcopy-gen is used. -func (in *UnixSocketAddress) DeepCopyInto(out *UnixSocketAddress) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UnixSocketAddress. Required by controller-gen. -func (in *UnixSocketAddress) DeepCopy() *UnixSocketAddress { - if in == nil { - return nil - } - out := new(UnixSocketAddress) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new UnixSocketAddress. Required by controller-gen. -func (in *UnixSocketAddress) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using PreparedQueryDestination within kubernetes types, where deepcopy-gen is used. -func (in *PreparedQueryDestination) DeepCopyInto(out *PreparedQueryDestination) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PreparedQueryDestination. Required by controller-gen. -func (in *PreparedQueryDestination) DeepCopy() *PreparedQueryDestination { - if in == nil { - return nil - } - out := new(PreparedQueryDestination) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new PreparedQueryDestination. Required by controller-gen. -func (in *PreparedQueryDestination) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/destinations_json.gen.go b/proto-public/pbmesh/v2beta1/destinations_json.gen.go deleted file mode 100644 index 989540524ef0..000000000000 --- a/proto-public/pbmesh/v2beta1/destinations_json.gen.go +++ /dev/null @@ -1,66 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for Destinations -func (this *Destinations) MarshalJSON() ([]byte, error) { - str, err := DestinationsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Destinations -func (this *Destinations) UnmarshalJSON(b []byte) error { - return DestinationsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Destination -func (this *Destination) MarshalJSON() ([]byte, error) { - str, err := DestinationsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Destination -func (this *Destination) UnmarshalJSON(b []byte) error { - return DestinationsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for IPPortAddress -func (this *IPPortAddress) MarshalJSON() ([]byte, error) { - str, err := DestinationsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for IPPortAddress -func (this *IPPortAddress) UnmarshalJSON(b []byte) error { - return DestinationsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for UnixSocketAddress -func (this *UnixSocketAddress) MarshalJSON() ([]byte, error) { - str, err := DestinationsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for UnixSocketAddress -func (this *UnixSocketAddress) UnmarshalJSON(b []byte) error { - return DestinationsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for PreparedQueryDestination -func (this *PreparedQueryDestination) MarshalJSON() ([]byte, error) { - str, err := DestinationsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for PreparedQueryDestination -func (this *PreparedQueryDestination) UnmarshalJSON(b []byte) error { - return DestinationsUnmarshaler.Unmarshal(b, this) -} - -var ( - DestinationsMarshaler = &protojson.MarshalOptions{} - DestinationsUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/expose.pb.binary.go b/proto-public/pbmesh/v2beta1/expose.pb.binary.go deleted file mode 100644 index 69154fab8fb2..000000000000 --- a/proto-public/pbmesh/v2beta1/expose.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/expose.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ExposeConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ExposeConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ExposePath) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ExposePath) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/expose.pb.go b/proto-public/pbmesh/v2beta1/expose.pb.go deleted file mode 100644 index 63958a4b4f21..000000000000 --- a/proto-public/pbmesh/v2beta1/expose.pb.go +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/expose.proto - -package meshv2beta1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=EXPOSE_PATH_PROTOCOL_HTTP;EXPOSE_PATH_PROTOCOL_HTTP2 -// +kubebuilder:validation:Type=string -type ExposePathProtocol int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - ExposePathProtocol_EXPOSE_PATH_PROTOCOL_HTTP ExposePathProtocol = 0 - ExposePathProtocol_EXPOSE_PATH_PROTOCOL_HTTP2 ExposePathProtocol = 1 -) - -// Enum value maps for ExposePathProtocol. -var ( - ExposePathProtocol_name = map[int32]string{ - 0: "EXPOSE_PATH_PROTOCOL_HTTP", - 1: "EXPOSE_PATH_PROTOCOL_HTTP2", - } - ExposePathProtocol_value = map[string]int32{ - "EXPOSE_PATH_PROTOCOL_HTTP": 0, - "EXPOSE_PATH_PROTOCOL_HTTP2": 1, - } -) - -func (x ExposePathProtocol) Enum() *ExposePathProtocol { - p := new(ExposePathProtocol) - *p = x - return p -} - -func (x ExposePathProtocol) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ExposePathProtocol) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_expose_proto_enumTypes[0].Descriptor() -} - -func (ExposePathProtocol) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_expose_proto_enumTypes[0] -} - -func (x ExposePathProtocol) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ExposePathProtocol.Descriptor instead. -func (ExposePathProtocol) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_expose_proto_rawDescGZIP(), []int{0} -} - -type ExposeConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ExposePaths []*ExposePath `protobuf:"bytes,1,rep,name=expose_paths,json=exposePaths,proto3" json:"expose_paths,omitempty"` -} - -func (x *ExposeConfig) Reset() { - *x = ExposeConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_expose_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExposeConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExposeConfig) ProtoMessage() {} - -func (x *ExposeConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_expose_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExposeConfig.ProtoReflect.Descriptor instead. -func (*ExposeConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_expose_proto_rawDescGZIP(), []int{0} -} - -func (x *ExposeConfig) GetExposePaths() []*ExposePath { - if x != nil { - return x.ExposePaths - } - return nil -} - -type ExposePath struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ListenerPort uint32 `protobuf:"varint,1,opt,name=listener_port,json=listenerPort,proto3" json:"listener_port,omitempty"` - Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` - LocalPathPort uint32 `protobuf:"varint,3,opt,name=local_path_port,json=localPathPort,proto3" json:"local_path_port,omitempty"` - Protocol ExposePathProtocol `protobuf:"varint,4,opt,name=protocol,proto3,enum=hashicorp.consul.mesh.v2beta1.ExposePathProtocol" json:"protocol,omitempty"` -} - -func (x *ExposePath) Reset() { - *x = ExposePath{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_expose_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExposePath) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExposePath) ProtoMessage() {} - -func (x *ExposePath) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_expose_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExposePath.ProtoReflect.Descriptor instead. -func (*ExposePath) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_expose_proto_rawDescGZIP(), []int{1} -} - -func (x *ExposePath) GetListenerPort() uint32 { - if x != nil { - return x.ListenerPort - } - return 0 -} - -func (x *ExposePath) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (x *ExposePath) GetLocalPathPort() uint32 { - if x != nil { - return x.LocalPathPort - } - return 0 -} - -func (x *ExposePath) GetProtocol() ExposePathProtocol { - if x != nil { - return x.Protocol - } - return ExposePathProtocol_EXPOSE_PATH_PROTOCOL_HTTP -} - -var File_pbmesh_v2beta1_expose_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_expose_proto_rawDesc = []byte{ - 0x0a, 0x1b, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x22, 0x5c, 0x0a, 0x0c, - 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4c, 0x0a, 0x0c, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x0b, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x22, 0xbc, 0x01, 0x0a, 0x0a, 0x45, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x0c, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, - 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6c, 0x6f, 0x63, - 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x4d, 0x0a, 0x08, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, - 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2a, 0x53, 0x0a, 0x12, 0x45, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, - 0x1d, 0x0a, 0x19, 0x45, 0x58, 0x50, 0x4f, 0x53, 0x45, 0x5f, 0x50, 0x41, 0x54, 0x48, 0x5f, 0x50, - 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x1e, - 0x0a, 0x1a, 0x45, 0x58, 0x50, 0x4f, 0x53, 0x45, 0x5f, 0x50, 0x41, 0x54, 0x48, 0x5f, 0x50, 0x52, - 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x32, 0x10, 0x01, 0x42, 0x8c, - 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x42, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, - 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, - 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, - 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, - 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, - 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, - 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_expose_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_expose_proto_rawDescData = file_pbmesh_v2beta1_expose_proto_rawDesc -) - -func file_pbmesh_v2beta1_expose_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_expose_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_expose_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_expose_proto_rawDescData) - }) - return file_pbmesh_v2beta1_expose_proto_rawDescData -} - -var file_pbmesh_v2beta1_expose_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v2beta1_expose_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbmesh_v2beta1_expose_proto_goTypes = []interface{}{ - (ExposePathProtocol)(0), // 0: hashicorp.consul.mesh.v2beta1.ExposePathProtocol - (*ExposeConfig)(nil), // 1: hashicorp.consul.mesh.v2beta1.ExposeConfig - (*ExposePath)(nil), // 2: hashicorp.consul.mesh.v2beta1.ExposePath -} -var file_pbmesh_v2beta1_expose_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.mesh.v2beta1.ExposeConfig.expose_paths:type_name -> hashicorp.consul.mesh.v2beta1.ExposePath - 0, // 1: hashicorp.consul.mesh.v2beta1.ExposePath.protocol:type_name -> hashicorp.consul.mesh.v2beta1.ExposePathProtocol - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_expose_proto_init() } -func file_pbmesh_v2beta1_expose_proto_init() { - if File_pbmesh_v2beta1_expose_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_expose_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExposeConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_expose_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExposePath); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_expose_proto_rawDesc, - NumEnums: 1, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_expose_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_expose_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_expose_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_expose_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_expose_proto = out.File - file_pbmesh_v2beta1_expose_proto_rawDesc = nil - file_pbmesh_v2beta1_expose_proto_goTypes = nil - file_pbmesh_v2beta1_expose_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/expose.proto b/proto-public/pbmesh/v2beta1/expose.proto deleted file mode 100644 index cf5c67d37015..000000000000 --- a/proto-public/pbmesh/v2beta1/expose.proto +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -message ExposeConfig { - repeated ExposePath expose_paths = 1; -} - -message ExposePath { - uint32 listener_port = 1; - string path = 2; - uint32 local_path_port = 3; - ExposePathProtocol protocol = 4; -} - -// +kubebuilder:validation:Enum=EXPOSE_PATH_PROTOCOL_HTTP;EXPOSE_PATH_PROTOCOL_HTTP2 -// +kubebuilder:validation:Type=string -enum ExposePathProtocol { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - EXPOSE_PATH_PROTOCOL_HTTP = 0; - EXPOSE_PATH_PROTOCOL_HTTP2 = 1; -} diff --git a/proto-public/pbmesh/v2beta1/expose_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/expose_deepcopy.gen.go deleted file mode 100644 index 2b75adbbcd34..000000000000 --- a/proto-public/pbmesh/v2beta1/expose_deepcopy.gen.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ExposeConfig within kubernetes types, where deepcopy-gen is used. -func (in *ExposeConfig) DeepCopyInto(out *ExposeConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExposeConfig. Required by controller-gen. -func (in *ExposeConfig) DeepCopy() *ExposeConfig { - if in == nil { - return nil - } - out := new(ExposeConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ExposeConfig. Required by controller-gen. -func (in *ExposeConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ExposePath within kubernetes types, where deepcopy-gen is used. -func (in *ExposePath) DeepCopyInto(out *ExposePath) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExposePath. Required by controller-gen. -func (in *ExposePath) DeepCopy() *ExposePath { - if in == nil { - return nil - } - out := new(ExposePath) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ExposePath. Required by controller-gen. -func (in *ExposePath) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/expose_json.gen.go b/proto-public/pbmesh/v2beta1/expose_json.gen.go deleted file mode 100644 index 14f04649c1f8..000000000000 --- a/proto-public/pbmesh/v2beta1/expose_json.gen.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ExposeConfig -func (this *ExposeConfig) MarshalJSON() ([]byte, error) { - str, err := ExposeMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ExposeConfig -func (this *ExposeConfig) UnmarshalJSON(b []byte) error { - return ExposeUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ExposePath -func (this *ExposePath) MarshalJSON() ([]byte, error) { - str, err := ExposeMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ExposePath -func (this *ExposePath) UnmarshalJSON(b []byte) error { - return ExposeUnmarshaler.Unmarshal(b, this) -} - -var ( - ExposeMarshaler = &protojson.MarshalOptions{} - ExposeUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/grpc_route.pb.binary.go b/proto-public/pbmesh/v2beta1/grpc_route.pb.binary.go deleted file mode 100644 index 3a5d3ac5a2cd..000000000000 --- a/proto-public/pbmesh/v2beta1/grpc_route.pb.binary.go +++ /dev/null @@ -1,78 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/grpc_route.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCRouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCRouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCRouteMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCRouteMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCMethodMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCMethodMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCHeaderMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCHeaderMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCRouteFilter) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCRouteFilter) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *GRPCBackendRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *GRPCBackendRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/grpc_route.pb.go b/proto-public/pbmesh/v2beta1/grpc_route.pb.go deleted file mode 100644 index e0b4f364810a..000000000000 --- a/proto-public/pbmesh/v2beta1/grpc_route.pb.go +++ /dev/null @@ -1,908 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/grpc_route.proto - -package meshv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=GRPC_METHOD_MATCH_TYPE_UNSPECIFIED;GRPC_METHOD_MATCH_TYPE_EXACT;GRPC_METHOD_MATCH_TYPE_REGEX -// +kubebuilder:validation:Type=string -type GRPCMethodMatchType int32 - -const ( - GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_UNSPECIFIED GRPCMethodMatchType = 0 - GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT GRPCMethodMatchType = 1 - GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_REGEX GRPCMethodMatchType = 2 -) - -// Enum value maps for GRPCMethodMatchType. -var ( - GRPCMethodMatchType_name = map[int32]string{ - 0: "GRPC_METHOD_MATCH_TYPE_UNSPECIFIED", - 1: "GRPC_METHOD_MATCH_TYPE_EXACT", - 2: "GRPC_METHOD_MATCH_TYPE_REGEX", - } - GRPCMethodMatchType_value = map[string]int32{ - "GRPC_METHOD_MATCH_TYPE_UNSPECIFIED": 0, - "GRPC_METHOD_MATCH_TYPE_EXACT": 1, - "GRPC_METHOD_MATCH_TYPE_REGEX": 2, - } -) - -func (x GRPCMethodMatchType) Enum() *GRPCMethodMatchType { - p := new(GRPCMethodMatchType) - *p = x - return p -} - -func (x GRPCMethodMatchType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (GRPCMethodMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_grpc_route_proto_enumTypes[0].Descriptor() -} - -func (GRPCMethodMatchType) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_grpc_route_proto_enumTypes[0] -} - -func (x GRPCMethodMatchType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use GRPCMethodMatchType.Descriptor instead. -func (GRPCMethodMatchType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_grpc_route_proto_rawDescGZIP(), []int{0} -} - -// NOTE: this should align to the GAMMA/gateway-api version, or at least be -// easily translatable. -// -// https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRoute -// -// This is a Resource type. -type GRPCRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ParentRefs references the resources (usually Services) that a Route wants - // to be attached to. - // - // It is invalid to reference an identical parent more than once. It is valid - // to reference multiple distinct sections within the same parent resource. - ParentRefs []*ParentReference `protobuf:"bytes,1,rep,name=parent_refs,json=parentRefs,proto3" json:"parent_refs,omitempty"` - // Hostnames are the hostnames for which this GRPCRoute should respond to requests. - // - // This is only valid for north/south. - Hostnames []string `protobuf:"bytes,2,rep,name=hostnames,proto3" json:"hostnames,omitempty"` - // Rules are a list of GRPC matchers, filters and actions. - Rules []*GRPCRouteRule `protobuf:"bytes,3,rep,name=rules,proto3" json:"rules,omitempty"` -} - -func (x *GRPCRoute) Reset() { - *x = GRPCRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCRoute) ProtoMessage() {} - -func (x *GRPCRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GRPCRoute.ProtoReflect.Descriptor instead. -func (*GRPCRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_grpc_route_proto_rawDescGZIP(), []int{0} -} - -func (x *GRPCRoute) GetParentRefs() []*ParentReference { - if x != nil { - return x.ParentRefs - } - return nil -} - -func (x *GRPCRoute) GetHostnames() []string { - if x != nil { - return x.Hostnames - } - return nil -} - -func (x *GRPCRoute) GetRules() []*GRPCRouteRule { - if x != nil { - return x.Rules - } - return nil -} - -type GRPCRouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Matches []*GRPCRouteMatch `protobuf:"bytes,1,rep,name=matches,proto3" json:"matches,omitempty"` - Filters []*GRPCRouteFilter `protobuf:"bytes,2,rep,name=filters,proto3" json:"filters,omitempty"` - // BackendRefs defines the backend(s) where matching requests should be sent. - // Failure behavior here depends on how many BackendRefs are specified and - // how many are invalid. - // - // If all entries in BackendRefs are invalid, and there are also no filters - // specified in this route rule, all traffic which matches this rule MUST - // receive a 500 status code. - // - // See the GRPCBackendRef definition for the rules about what makes a single - // GRPCBackendRef invalid. - // - // When a GRPCBackendRef is invalid, 500 status codes MUST be returned for - // requests that would have otherwise been routed to an invalid backend. If - // multiple backends are specified, and some are invalid, the proportion of - // requests that would otherwise have been routed to an invalid backend MUST - // receive a 500 status code. - // - // For example, if two backends are specified with equal weights, and one is - // invalid, 50 percent of traffic must receive a 500. Implementations may - // choose how that 50 percent is determined. - BackendRefs []*GRPCBackendRef `protobuf:"bytes,3,rep,name=backend_refs,json=backendRefs,proto3" json:"backend_refs,omitempty"` - Timeouts *HTTPRouteTimeouts `protobuf:"bytes,4,opt,name=timeouts,proto3" json:"timeouts,omitempty"` - Retries *HTTPRouteRetries `protobuf:"bytes,5,opt,name=retries,proto3" json:"retries,omitempty"` -} - -func (x *GRPCRouteRule) Reset() { - *x = GRPCRouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCRouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCRouteRule) ProtoMessage() {} - -func (x *GRPCRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GRPCRouteRule.ProtoReflect.Descriptor instead. -func (*GRPCRouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_grpc_route_proto_rawDescGZIP(), []int{1} -} - -func (x *GRPCRouteRule) GetMatches() []*GRPCRouteMatch { - if x != nil { - return x.Matches - } - return nil -} - -func (x *GRPCRouteRule) GetFilters() []*GRPCRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -func (x *GRPCRouteRule) GetBackendRefs() []*GRPCBackendRef { - if x != nil { - return x.BackendRefs - } - return nil -} - -func (x *GRPCRouteRule) GetTimeouts() *HTTPRouteTimeouts { - if x != nil { - return x.Timeouts - } - return nil -} - -func (x *GRPCRouteRule) GetRetries() *HTTPRouteRetries { - if x != nil { - return x.Retries - } - return nil -} - -type GRPCRouteMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Method specifies a gRPC request service/method matcher. If this field is - // not specified, all services and methods will match. - Method *GRPCMethodMatch `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"` - // Headers specifies gRPC request header matchers. Multiple match values are - // ANDed together, meaning, a request MUST match all the specified headers to - // select the route. - Headers []*GRPCHeaderMatch `protobuf:"bytes,2,rep,name=headers,proto3" json:"headers,omitempty"` -} - -func (x *GRPCRouteMatch) Reset() { - *x = GRPCRouteMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCRouteMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCRouteMatch) ProtoMessage() {} - -func (x *GRPCRouteMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GRPCRouteMatch.ProtoReflect.Descriptor instead. -func (*GRPCRouteMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_grpc_route_proto_rawDescGZIP(), []int{2} -} - -func (x *GRPCRouteMatch) GetMethod() *GRPCMethodMatch { - if x != nil { - return x.Method - } - return nil -} - -func (x *GRPCRouteMatch) GetHeaders() []*GRPCHeaderMatch { - if x != nil { - return x.Headers - } - return nil -} - -type GRPCMethodMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Type specifies how to match against the service and/or method. Support: - // Core (Exact with service and method specified) - Type GRPCMethodMatchType `protobuf:"varint,1,opt,name=type,proto3,enum=hashicorp.consul.mesh.v2beta1.GRPCMethodMatchType" json:"type,omitempty"` - // Value of the service to match against. If left empty or omitted, will - // match any service. - // - // At least one of Service and Method MUST be a non-empty string. - Service string `protobuf:"bytes,2,opt,name=service,proto3" json:"service,omitempty"` - // Value of the method to match against. If left empty or omitted, will match - // all services. - // - // At least one of Service and Method MUST be a non-empty string.} - Method string `protobuf:"bytes,3,opt,name=method,proto3" json:"method,omitempty"` -} - -func (x *GRPCMethodMatch) Reset() { - *x = GRPCMethodMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCMethodMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCMethodMatch) ProtoMessage() {} - -func (x *GRPCMethodMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GRPCMethodMatch.ProtoReflect.Descriptor instead. -func (*GRPCMethodMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_grpc_route_proto_rawDescGZIP(), []int{3} -} - -func (x *GRPCMethodMatch) GetType() GRPCMethodMatchType { - if x != nil { - return x.Type - } - return GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_UNSPECIFIED -} - -func (x *GRPCMethodMatch) GetService() string { - if x != nil { - return x.Service - } - return "" -} - -func (x *GRPCMethodMatch) GetMethod() string { - if x != nil { - return x.Method - } - return "" -} - -type GRPCHeaderMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Type HeaderMatchType `protobuf:"varint,1,opt,name=type,proto3,enum=hashicorp.consul.mesh.v2beta1.HeaderMatchType" json:"type,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *GRPCHeaderMatch) Reset() { - *x = GRPCHeaderMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCHeaderMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCHeaderMatch) ProtoMessage() {} - -func (x *GRPCHeaderMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GRPCHeaderMatch.ProtoReflect.Descriptor instead. -func (*GRPCHeaderMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_grpc_route_proto_rawDescGZIP(), []int{4} -} - -func (x *GRPCHeaderMatch) GetType() HeaderMatchType { - if x != nil { - return x.Type - } - return HeaderMatchType_HEADER_MATCH_TYPE_UNSPECIFIED -} - -func (x *GRPCHeaderMatch) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *GRPCHeaderMatch) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -type GRPCRouteFilter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // RequestHeaderModifier defines a schema for a filter that modifies request - // headers. - RequestHeaderModifier *HTTPHeaderFilter `protobuf:"bytes,1,opt,name=request_header_modifier,json=requestHeaderModifier,proto3" json:"request_header_modifier,omitempty"` - // ResponseHeaderModifier defines a schema for a filter that modifies - // response headers. - ResponseHeaderModifier *HTTPHeaderFilter `protobuf:"bytes,2,opt,name=response_header_modifier,json=responseHeaderModifier,proto3" json:"response_header_modifier,omitempty"` - // URLRewrite defines a schema for a filter that modifies a request during - // forwarding. - UrlRewrite *HTTPURLRewriteFilter `protobuf:"bytes,5,opt,name=url_rewrite,json=urlRewrite,proto3" json:"url_rewrite,omitempty"` -} - -func (x *GRPCRouteFilter) Reset() { - *x = GRPCRouteFilter{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCRouteFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCRouteFilter) ProtoMessage() {} - -func (x *GRPCRouteFilter) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GRPCRouteFilter.ProtoReflect.Descriptor instead. -func (*GRPCRouteFilter) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_grpc_route_proto_rawDescGZIP(), []int{5} -} - -func (x *GRPCRouteFilter) GetRequestHeaderModifier() *HTTPHeaderFilter { - if x != nil { - return x.RequestHeaderModifier - } - return nil -} - -func (x *GRPCRouteFilter) GetResponseHeaderModifier() *HTTPHeaderFilter { - if x != nil { - return x.ResponseHeaderModifier - } - return nil -} - -func (x *GRPCRouteFilter) GetUrlRewrite() *HTTPURLRewriteFilter { - if x != nil { - return x.UrlRewrite - } - return nil -} - -type GRPCBackendRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BackendRef *BackendReference `protobuf:"bytes,1,opt,name=backend_ref,json=backendRef,proto3" json:"backend_ref,omitempty"` - // Weight specifies the proportion of requests forwarded to the referenced - // backend. This is computed as weight/(sum of all weights in this - // BackendRefs list). For non-zero values, there may be some epsilon from the - // exact proportion defined here depending on the precision an implementation - // supports. Weight is not a percentage and the sum of weights does not need - // to equal 100. - // - // If only one backend is specified and it has a weight greater than 0, 100% - // of the traffic is forwarded to that backend. If weight is set to 0, no - // traffic should be forwarded for this entry. If unspecified, weight defaults - // to 1. - Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` - // Filters defined at this level should be executed if and only if the - // request is being forwarded to the backend defined here. - Filters []*GRPCRouteFilter `protobuf:"bytes,3,rep,name=filters,proto3" json:"filters,omitempty"` -} - -func (x *GRPCBackendRef) Reset() { - *x = GRPCBackendRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GRPCBackendRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GRPCBackendRef) ProtoMessage() {} - -func (x *GRPCBackendRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_grpc_route_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GRPCBackendRef.ProtoReflect.Descriptor instead. -func (*GRPCBackendRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_grpc_route_proto_rawDescGZIP(), []int{6} -} - -func (x *GRPCBackendRef) GetBackendRef() *BackendReference { - if x != nil { - return x.BackendRef - } - return nil -} - -func (x *GRPCBackendRef) GetWeight() uint32 { - if x != nil { - return x.Weight - } - return 0 -} - -func (x *GRPCBackendRef) GetFilters() []*GRPCRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -var File_pbmesh_v2beta1_grpc_route_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_grpc_route_proto_rawDesc = []byte{ - 0x0a, 0x1f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x1a, 0x1b, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x70, - 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x68, 0x74, - 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, - 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x68, - 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, - 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, - 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xc6, 0x01, 0x0a, 0x09, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4f, 0x0a, - 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, 0x12, 0x1c, - 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x05, - 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, - 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0x8d, 0x03, 0x0a, 0x0d, 0x47, 0x52, 0x50, - 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x47, 0x0a, 0x07, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x6d, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x50, 0x0a, - 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, - 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x73, 0x12, - 0x4c, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x73, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x12, 0x49, 0x0a, - 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, - 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, - 0x07, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0xa2, 0x01, 0x0a, 0x0e, 0x47, 0x52, 0x50, - 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x46, 0x0a, 0x06, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, - 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x06, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x12, 0x48, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0x8b, 0x01, - 0x0a, 0x0f, 0x47, 0x52, 0x50, 0x43, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x12, 0x46, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x47, 0x52, 0x50, 0x43, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, - 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0x7f, 0x0a, 0x0f, 0x47, - 0x52, 0x50, 0x43, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x42, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xbb, 0x02, 0x0a, - 0x0f, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x12, 0x67, 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x52, 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x69, 0x0a, 0x18, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x16, 0x72, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x0b, 0x75, 0x72, 0x6c, 0x5f, 0x72, 0x65, 0x77, 0x72, - 0x69, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x55, 0x52, - 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0a, - 0x75, 0x72, 0x6c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, 0xc4, 0x01, 0x0a, 0x0e, 0x47, - 0x52, 0x50, 0x43, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x50, 0x0a, - 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, - 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x48, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x73, 0x2a, 0x81, 0x01, 0x0a, 0x13, 0x47, 0x52, 0x50, 0x43, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x22, 0x47, 0x52, 0x50, - 0x43, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x47, 0x52, 0x50, 0x43, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, - 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x41, 0x43, - 0x54, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x47, 0x52, 0x50, 0x43, 0x5f, 0x4d, 0x45, 0x54, 0x48, - 0x4f, 0x44, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, - 0x47, 0x45, 0x58, 0x10, 0x02, 0x42, 0x8f, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0e, 0x47, 0x72, 0x70, - 0x63, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, - 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_grpc_route_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_grpc_route_proto_rawDescData = file_pbmesh_v2beta1_grpc_route_proto_rawDesc -) - -func file_pbmesh_v2beta1_grpc_route_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_grpc_route_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_grpc_route_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_grpc_route_proto_rawDescData) - }) - return file_pbmesh_v2beta1_grpc_route_proto_rawDescData -} - -var file_pbmesh_v2beta1_grpc_route_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v2beta1_grpc_route_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_pbmesh_v2beta1_grpc_route_proto_goTypes = []interface{}{ - (GRPCMethodMatchType)(0), // 0: hashicorp.consul.mesh.v2beta1.GRPCMethodMatchType - (*GRPCRoute)(nil), // 1: hashicorp.consul.mesh.v2beta1.GRPCRoute - (*GRPCRouteRule)(nil), // 2: hashicorp.consul.mesh.v2beta1.GRPCRouteRule - (*GRPCRouteMatch)(nil), // 3: hashicorp.consul.mesh.v2beta1.GRPCRouteMatch - (*GRPCMethodMatch)(nil), // 4: hashicorp.consul.mesh.v2beta1.GRPCMethodMatch - (*GRPCHeaderMatch)(nil), // 5: hashicorp.consul.mesh.v2beta1.GRPCHeaderMatch - (*GRPCRouteFilter)(nil), // 6: hashicorp.consul.mesh.v2beta1.GRPCRouteFilter - (*GRPCBackendRef)(nil), // 7: hashicorp.consul.mesh.v2beta1.GRPCBackendRef - (*ParentReference)(nil), // 8: hashicorp.consul.mesh.v2beta1.ParentReference - (*HTTPRouteTimeouts)(nil), // 9: hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts - (*HTTPRouteRetries)(nil), // 10: hashicorp.consul.mesh.v2beta1.HTTPRouteRetries - (HeaderMatchType)(0), // 11: hashicorp.consul.mesh.v2beta1.HeaderMatchType - (*HTTPHeaderFilter)(nil), // 12: hashicorp.consul.mesh.v2beta1.HTTPHeaderFilter - (*HTTPURLRewriteFilter)(nil), // 13: hashicorp.consul.mesh.v2beta1.HTTPURLRewriteFilter - (*BackendReference)(nil), // 14: hashicorp.consul.mesh.v2beta1.BackendReference -} -var file_pbmesh_v2beta1_grpc_route_proto_depIdxs = []int32{ - 8, // 0: hashicorp.consul.mesh.v2beta1.GRPCRoute.parent_refs:type_name -> hashicorp.consul.mesh.v2beta1.ParentReference - 2, // 1: hashicorp.consul.mesh.v2beta1.GRPCRoute.rules:type_name -> hashicorp.consul.mesh.v2beta1.GRPCRouteRule - 3, // 2: hashicorp.consul.mesh.v2beta1.GRPCRouteRule.matches:type_name -> hashicorp.consul.mesh.v2beta1.GRPCRouteMatch - 6, // 3: hashicorp.consul.mesh.v2beta1.GRPCRouteRule.filters:type_name -> hashicorp.consul.mesh.v2beta1.GRPCRouteFilter - 7, // 4: hashicorp.consul.mesh.v2beta1.GRPCRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v2beta1.GRPCBackendRef - 9, // 5: hashicorp.consul.mesh.v2beta1.GRPCRouteRule.timeouts:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts - 10, // 6: hashicorp.consul.mesh.v2beta1.GRPCRouteRule.retries:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteRetries - 4, // 7: hashicorp.consul.mesh.v2beta1.GRPCRouteMatch.method:type_name -> hashicorp.consul.mesh.v2beta1.GRPCMethodMatch - 5, // 8: hashicorp.consul.mesh.v2beta1.GRPCRouteMatch.headers:type_name -> hashicorp.consul.mesh.v2beta1.GRPCHeaderMatch - 0, // 9: hashicorp.consul.mesh.v2beta1.GRPCMethodMatch.type:type_name -> hashicorp.consul.mesh.v2beta1.GRPCMethodMatchType - 11, // 10: hashicorp.consul.mesh.v2beta1.GRPCHeaderMatch.type:type_name -> hashicorp.consul.mesh.v2beta1.HeaderMatchType - 12, // 11: hashicorp.consul.mesh.v2beta1.GRPCRouteFilter.request_header_modifier:type_name -> hashicorp.consul.mesh.v2beta1.HTTPHeaderFilter - 12, // 12: hashicorp.consul.mesh.v2beta1.GRPCRouteFilter.response_header_modifier:type_name -> hashicorp.consul.mesh.v2beta1.HTTPHeaderFilter - 13, // 13: hashicorp.consul.mesh.v2beta1.GRPCRouteFilter.url_rewrite:type_name -> hashicorp.consul.mesh.v2beta1.HTTPURLRewriteFilter - 14, // 14: hashicorp.consul.mesh.v2beta1.GRPCBackendRef.backend_ref:type_name -> hashicorp.consul.mesh.v2beta1.BackendReference - 6, // 15: hashicorp.consul.mesh.v2beta1.GRPCBackendRef.filters:type_name -> hashicorp.consul.mesh.v2beta1.GRPCRouteFilter - 16, // [16:16] is the sub-list for method output_type - 16, // [16:16] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_grpc_route_proto_init() } -func file_pbmesh_v2beta1_grpc_route_proto_init() { - if File_pbmesh_v2beta1_grpc_route_proto != nil { - return - } - file_pbmesh_v2beta1_common_proto_init() - file_pbmesh_v2beta1_http_route_proto_init() - file_pbmesh_v2beta1_http_route_retries_proto_init() - file_pbmesh_v2beta1_http_route_timeouts_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_grpc_route_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_grpc_route_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCRouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_grpc_route_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCRouteMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_grpc_route_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCMethodMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_grpc_route_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCHeaderMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_grpc_route_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCRouteFilter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_grpc_route_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GRPCBackendRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_grpc_route_proto_rawDesc, - NumEnums: 1, - NumMessages: 7, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_grpc_route_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_grpc_route_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_grpc_route_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_grpc_route_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_grpc_route_proto = out.File - file_pbmesh_v2beta1_grpc_route_proto_rawDesc = nil - file_pbmesh_v2beta1_grpc_route_proto_goTypes = nil - file_pbmesh_v2beta1_grpc_route_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/grpc_route.proto b/proto-public/pbmesh/v2beta1/grpc_route.proto deleted file mode 100644 index a971bb061099..000000000000 --- a/proto-public/pbmesh/v2beta1/grpc_route.proto +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "pbmesh/v2beta1/common.proto"; -import "pbmesh/v2beta1/http_route.proto"; -import "pbmesh/v2beta1/http_route_retries.proto"; -import "pbmesh/v2beta1/http_route_timeouts.proto"; -import "pbresource/annotations.proto"; - -// NOTE: this should align to the GAMMA/gateway-api version, or at least be -// easily translatable. -// -// https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRoute -// -// This is a Resource type. -message GRPCRoute { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // ParentRefs references the resources (usually Services) that a Route wants - // to be attached to. - // - // It is invalid to reference an identical parent more than once. It is valid - // to reference multiple distinct sections within the same parent resource. - repeated ParentReference parent_refs = 1; - - // Hostnames are the hostnames for which this GRPCRoute should respond to requests. - // - // This is only valid for north/south. - repeated string hostnames = 2; - - // Rules are a list of GRPC matchers, filters and actions. - repeated GRPCRouteRule rules = 3; -} - -message GRPCRouteRule { - repeated GRPCRouteMatch matches = 1; - repeated GRPCRouteFilter filters = 2; - - // BackendRefs defines the backend(s) where matching requests should be sent. - // Failure behavior here depends on how many BackendRefs are specified and - // how many are invalid. - // - // If all entries in BackendRefs are invalid, and there are also no filters - // specified in this route rule, all traffic which matches this rule MUST - // receive a 500 status code. - // - // See the GRPCBackendRef definition for the rules about what makes a single - // GRPCBackendRef invalid. - // - // When a GRPCBackendRef is invalid, 500 status codes MUST be returned for - // requests that would have otherwise been routed to an invalid backend. If - // multiple backends are specified, and some are invalid, the proportion of - // requests that would otherwise have been routed to an invalid backend MUST - // receive a 500 status code. - // - // For example, if two backends are specified with equal weights, and one is - // invalid, 50 percent of traffic must receive a 500. Implementations may - // choose how that 50 percent is determined. - repeated GRPCBackendRef backend_refs = 3; - - HTTPRouteTimeouts timeouts = 4; - HTTPRouteRetries retries = 5; -} - -message GRPCRouteMatch { - // Method specifies a gRPC request service/method matcher. If this field is - // not specified, all services and methods will match. - GRPCMethodMatch method = 1; - - // Headers specifies gRPC request header matchers. Multiple match values are - // ANDed together, meaning, a request MUST match all the specified headers to - // select the route. - repeated GRPCHeaderMatch headers = 2; -} - -message GRPCMethodMatch { - // Type specifies how to match against the service and/or method. Support: - // Core (Exact with service and method specified) - GRPCMethodMatchType type = 1; - - // Value of the service to match against. If left empty or omitted, will - // match any service. - // - // At least one of Service and Method MUST be a non-empty string. - string service = 2; - - // Value of the method to match against. If left empty or omitted, will match - // all services. - // - // At least one of Service and Method MUST be a non-empty string.} - string method = 3; -} - -// +kubebuilder:validation:Enum=GRPC_METHOD_MATCH_TYPE_UNSPECIFIED;GRPC_METHOD_MATCH_TYPE_EXACT;GRPC_METHOD_MATCH_TYPE_REGEX -// +kubebuilder:validation:Type=string -enum GRPCMethodMatchType { - GRPC_METHOD_MATCH_TYPE_UNSPECIFIED = 0; - GRPC_METHOD_MATCH_TYPE_EXACT = 1; - GRPC_METHOD_MATCH_TYPE_REGEX = 2; -} - -message GRPCHeaderMatch { - HeaderMatchType type = 1; - string name = 2; - string value = 3; -} - -message GRPCRouteFilter { - // RequestHeaderModifier defines a schema for a filter that modifies request - // headers. - HTTPHeaderFilter request_header_modifier = 1; - - // ResponseHeaderModifier defines a schema for a filter that modifies - // response headers. - HTTPHeaderFilter response_header_modifier = 2; - - // URLRewrite defines a schema for a filter that modifies a request during - // forwarding. - HTTPURLRewriteFilter url_rewrite = 5; -} - -message GRPCBackendRef { - BackendReference backend_ref = 1; - - // Weight specifies the proportion of requests forwarded to the referenced - // backend. This is computed as weight/(sum of all weights in this - // BackendRefs list). For non-zero values, there may be some epsilon from the - // exact proportion defined here depending on the precision an implementation - // supports. Weight is not a percentage and the sum of weights does not need - // to equal 100. - // - //If only one backend is specified and it has a weight greater than 0, 100% - //of the traffic is forwarded to that backend. If weight is set to 0, no - //traffic should be forwarded for this entry. If unspecified, weight defaults - //to 1. - uint32 weight = 2; - - // Filters defined at this level should be executed if and only if the - // request is being forwarded to the backend defined here. - repeated GRPCRouteFilter filters = 3; -} diff --git a/proto-public/pbmesh/v2beta1/grpc_route_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/grpc_route_deepcopy.gen.go deleted file mode 100644 index ea7e1dc8ed26..000000000000 --- a/proto-public/pbmesh/v2beta1/grpc_route_deepcopy.gen.go +++ /dev/null @@ -1,153 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using GRPCRoute within kubernetes types, where deepcopy-gen is used. -func (in *GRPCRoute) DeepCopyInto(out *GRPCRoute) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRoute. Required by controller-gen. -func (in *GRPCRoute) DeepCopy() *GRPCRoute { - if in == nil { - return nil - } - out := new(GRPCRoute) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRoute. Required by controller-gen. -func (in *GRPCRoute) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using GRPCRouteRule within kubernetes types, where deepcopy-gen is used. -func (in *GRPCRouteRule) DeepCopyInto(out *GRPCRouteRule) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteRule. Required by controller-gen. -func (in *GRPCRouteRule) DeepCopy() *GRPCRouteRule { - if in == nil { - return nil - } - out := new(GRPCRouteRule) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteRule. Required by controller-gen. -func (in *GRPCRouteRule) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using GRPCRouteMatch within kubernetes types, where deepcopy-gen is used. -func (in *GRPCRouteMatch) DeepCopyInto(out *GRPCRouteMatch) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteMatch. Required by controller-gen. -func (in *GRPCRouteMatch) DeepCopy() *GRPCRouteMatch { - if in == nil { - return nil - } - out := new(GRPCRouteMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteMatch. Required by controller-gen. -func (in *GRPCRouteMatch) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using GRPCMethodMatch within kubernetes types, where deepcopy-gen is used. -func (in *GRPCMethodMatch) DeepCopyInto(out *GRPCMethodMatch) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCMethodMatch. Required by controller-gen. -func (in *GRPCMethodMatch) DeepCopy() *GRPCMethodMatch { - if in == nil { - return nil - } - out := new(GRPCMethodMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GRPCMethodMatch. Required by controller-gen. -func (in *GRPCMethodMatch) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using GRPCHeaderMatch within kubernetes types, where deepcopy-gen is used. -func (in *GRPCHeaderMatch) DeepCopyInto(out *GRPCHeaderMatch) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCHeaderMatch. Required by controller-gen. -func (in *GRPCHeaderMatch) DeepCopy() *GRPCHeaderMatch { - if in == nil { - return nil - } - out := new(GRPCHeaderMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GRPCHeaderMatch. Required by controller-gen. -func (in *GRPCHeaderMatch) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using GRPCRouteFilter within kubernetes types, where deepcopy-gen is used. -func (in *GRPCRouteFilter) DeepCopyInto(out *GRPCRouteFilter) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteFilter. Required by controller-gen. -func (in *GRPCRouteFilter) DeepCopy() *GRPCRouteFilter { - if in == nil { - return nil - } - out := new(GRPCRouteFilter) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GRPCRouteFilter. Required by controller-gen. -func (in *GRPCRouteFilter) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using GRPCBackendRef within kubernetes types, where deepcopy-gen is used. -func (in *GRPCBackendRef) DeepCopyInto(out *GRPCBackendRef) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCBackendRef. Required by controller-gen. -func (in *GRPCBackendRef) DeepCopy() *GRPCBackendRef { - if in == nil { - return nil - } - out := new(GRPCBackendRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GRPCBackendRef. Required by controller-gen. -func (in *GRPCBackendRef) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/grpc_route_json.gen.go b/proto-public/pbmesh/v2beta1/grpc_route_json.gen.go deleted file mode 100644 index f995efcfa849..000000000000 --- a/proto-public/pbmesh/v2beta1/grpc_route_json.gen.go +++ /dev/null @@ -1,88 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for GRPCRoute -func (this *GRPCRoute) MarshalJSON() ([]byte, error) { - str, err := GrpcRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for GRPCRoute -func (this *GRPCRoute) UnmarshalJSON(b []byte) error { - return GrpcRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for GRPCRouteRule -func (this *GRPCRouteRule) MarshalJSON() ([]byte, error) { - str, err := GrpcRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for GRPCRouteRule -func (this *GRPCRouteRule) UnmarshalJSON(b []byte) error { - return GrpcRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for GRPCRouteMatch -func (this *GRPCRouteMatch) MarshalJSON() ([]byte, error) { - str, err := GrpcRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for GRPCRouteMatch -func (this *GRPCRouteMatch) UnmarshalJSON(b []byte) error { - return GrpcRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for GRPCMethodMatch -func (this *GRPCMethodMatch) MarshalJSON() ([]byte, error) { - str, err := GrpcRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for GRPCMethodMatch -func (this *GRPCMethodMatch) UnmarshalJSON(b []byte) error { - return GrpcRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for GRPCHeaderMatch -func (this *GRPCHeaderMatch) MarshalJSON() ([]byte, error) { - str, err := GrpcRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for GRPCHeaderMatch -func (this *GRPCHeaderMatch) UnmarshalJSON(b []byte) error { - return GrpcRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for GRPCRouteFilter -func (this *GRPCRouteFilter) MarshalJSON() ([]byte, error) { - str, err := GrpcRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for GRPCRouteFilter -func (this *GRPCRouteFilter) UnmarshalJSON(b []byte) error { - return GrpcRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for GRPCBackendRef -func (this *GRPCBackendRef) MarshalJSON() ([]byte, error) { - str, err := GrpcRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for GRPCBackendRef -func (this *GRPCBackendRef) UnmarshalJSON(b []byte) error { - return GrpcRouteUnmarshaler.Unmarshal(b, this) -} - -var ( - GrpcRouteMarshaler = &protojson.MarshalOptions{} - GrpcRouteUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/http_route.pb.binary.go b/proto-public/pbmesh/v2beta1/http_route.pb.binary.go deleted file mode 100644 index b8b4b08a9cc3..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route.pb.binary.go +++ /dev/null @@ -1,118 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/http_route.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPRouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPRouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPRouteMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPRouteMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPPathMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPPathMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPHeaderMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPHeaderMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPQueryParamMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPQueryParamMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPRouteFilter) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPRouteFilter) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPHeaderFilter) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPHeaderFilter) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPHeader) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPHeader) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPURLRewriteFilter) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPURLRewriteFilter) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPBackendRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPBackendRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/http_route.pb.go b/proto-public/pbmesh/v2beta1/http_route.pb.go deleted file mode 100644 index 383308f1ad00..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route.pb.go +++ /dev/null @@ -1,1445 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/http_route.proto - -package meshv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// PathMatchType specifies the semantics of how HTTP paths should be compared. -// Valid PathMatchType values, along with their support levels, are: -// -// PathPrefix and Exact paths must be syntactically valid: -// -// - Must begin with the / character -// - Must not contain consecutive / characters (e.g. /foo///, //). -// - Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the Accepted -// Condition for the Route to status: False, with a Reason of UnsupportedValue. -// -// +kubebuilder:validation:Enum=PATH_MATCH_TYPE_UNSPECIFIED;PATH_MATCH_TYPE_EXACT;PATH_MATCH_TYPE_PREFIX;PATH_MATCH_TYPE_REGEX -// +kubebuilder:validation:Type=string -type PathMatchType int32 - -const ( - PathMatchType_PATH_MATCH_TYPE_UNSPECIFIED PathMatchType = 0 - PathMatchType_PATH_MATCH_TYPE_EXACT PathMatchType = 1 - PathMatchType_PATH_MATCH_TYPE_PREFIX PathMatchType = 2 - PathMatchType_PATH_MATCH_TYPE_REGEX PathMatchType = 3 -) - -// Enum value maps for PathMatchType. -var ( - PathMatchType_name = map[int32]string{ - 0: "PATH_MATCH_TYPE_UNSPECIFIED", - 1: "PATH_MATCH_TYPE_EXACT", - 2: "PATH_MATCH_TYPE_PREFIX", - 3: "PATH_MATCH_TYPE_REGEX", - } - PathMatchType_value = map[string]int32{ - "PATH_MATCH_TYPE_UNSPECIFIED": 0, - "PATH_MATCH_TYPE_EXACT": 1, - "PATH_MATCH_TYPE_PREFIX": 2, - "PATH_MATCH_TYPE_REGEX": 3, - } -) - -func (x PathMatchType) Enum() *PathMatchType { - p := new(PathMatchType) - *p = x - return p -} - -func (x PathMatchType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (PathMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_http_route_proto_enumTypes[0].Descriptor() -} - -func (PathMatchType) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_http_route_proto_enumTypes[0] -} - -func (x PathMatchType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use PathMatchType.Descriptor instead. -func (PathMatchType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{0} -} - -// HeaderMatchType specifies the semantics of how HTTP header values should be -// compared. Valid HeaderMatchType values, along with their conformance levels, -// are: -// -// Note that values may be added to this enum, implementations must ensure that -// unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the Accepted -// Condition for the Route to status: False, with a Reason of UnsupportedValue. -// -// +kubebuilder:validation:Enum=HEADER_MATCH_TYPE_UNSPECIFIED;HEADER_MATCH_TYPE_EXACT;HEADER_MATCH_TYPE_REGEX;HEADER_MATCH_TYPE_PRESENT;HEADER_MATCH_TYPE_PREFIX;HEADER_MATCH_TYPE_SUFFIX -// +kubebuilder:validation:Type=string -type HeaderMatchType int32 - -const ( - HeaderMatchType_HEADER_MATCH_TYPE_UNSPECIFIED HeaderMatchType = 0 - HeaderMatchType_HEADER_MATCH_TYPE_EXACT HeaderMatchType = 1 - HeaderMatchType_HEADER_MATCH_TYPE_REGEX HeaderMatchType = 2 - // consul only after this point (service-router compat) - HeaderMatchType_HEADER_MATCH_TYPE_PRESENT HeaderMatchType = 3 - HeaderMatchType_HEADER_MATCH_TYPE_PREFIX HeaderMatchType = 4 - HeaderMatchType_HEADER_MATCH_TYPE_SUFFIX HeaderMatchType = 5 -) - -// Enum value maps for HeaderMatchType. -var ( - HeaderMatchType_name = map[int32]string{ - 0: "HEADER_MATCH_TYPE_UNSPECIFIED", - 1: "HEADER_MATCH_TYPE_EXACT", - 2: "HEADER_MATCH_TYPE_REGEX", - 3: "HEADER_MATCH_TYPE_PRESENT", - 4: "HEADER_MATCH_TYPE_PREFIX", - 5: "HEADER_MATCH_TYPE_SUFFIX", - } - HeaderMatchType_value = map[string]int32{ - "HEADER_MATCH_TYPE_UNSPECIFIED": 0, - "HEADER_MATCH_TYPE_EXACT": 1, - "HEADER_MATCH_TYPE_REGEX": 2, - "HEADER_MATCH_TYPE_PRESENT": 3, - "HEADER_MATCH_TYPE_PREFIX": 4, - "HEADER_MATCH_TYPE_SUFFIX": 5, - } -) - -func (x HeaderMatchType) Enum() *HeaderMatchType { - p := new(HeaderMatchType) - *p = x - return p -} - -func (x HeaderMatchType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (HeaderMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_http_route_proto_enumTypes[1].Descriptor() -} - -func (HeaderMatchType) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_http_route_proto_enumTypes[1] -} - -func (x HeaderMatchType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use HeaderMatchType.Descriptor instead. -func (HeaderMatchType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{1} -} - -// +kubebuilder:validation:Enum=QUERY_PARAM_MATCH_TYPE_UNSPECIFIED;QUERY_PARAM_MATCH_TYPE_EXACT;QUERY_PARAM_MATCH_TYPE_REGEX;QUERY_PARAM_MATCH_TYPE_PRESENT -// +kubebuilder:validation:Type=string -type QueryParamMatchType int32 - -const ( - QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_UNSPECIFIED QueryParamMatchType = 0 - QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_EXACT QueryParamMatchType = 1 - QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_REGEX QueryParamMatchType = 2 - // consul only after this point (service-router compat) - QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_PRESENT QueryParamMatchType = 3 -) - -// Enum value maps for QueryParamMatchType. -var ( - QueryParamMatchType_name = map[int32]string{ - 0: "QUERY_PARAM_MATCH_TYPE_UNSPECIFIED", - 1: "QUERY_PARAM_MATCH_TYPE_EXACT", - 2: "QUERY_PARAM_MATCH_TYPE_REGEX", - 3: "QUERY_PARAM_MATCH_TYPE_PRESENT", - } - QueryParamMatchType_value = map[string]int32{ - "QUERY_PARAM_MATCH_TYPE_UNSPECIFIED": 0, - "QUERY_PARAM_MATCH_TYPE_EXACT": 1, - "QUERY_PARAM_MATCH_TYPE_REGEX": 2, - "QUERY_PARAM_MATCH_TYPE_PRESENT": 3, - } -) - -func (x QueryParamMatchType) Enum() *QueryParamMatchType { - p := new(QueryParamMatchType) - *p = x - return p -} - -func (x QueryParamMatchType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (QueryParamMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_http_route_proto_enumTypes[2].Descriptor() -} - -func (QueryParamMatchType) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_http_route_proto_enumTypes[2] -} - -func (x QueryParamMatchType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use QueryParamMatchType.Descriptor instead. -func (QueryParamMatchType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{2} -} - -// NOTE: this should align to the GAMMA/gateway-api version, or at least be -// easily translatable. -// -// https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.HTTPRoute -// -// This is a Resource type. -type HTTPRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ParentRefs references the resources (usually Services) that a Route wants - // to be attached to. - // - // It is invalid to reference an identical parent more than once. It is valid - // to reference multiple distinct sections within the same parent resource. - ParentRefs []*ParentReference `protobuf:"bytes,1,rep,name=parent_refs,json=parentRefs,proto3" json:"parent_refs,omitempty"` - // Hostnames are the hostnames for which this HTTPRoute should respond to requests. - // - // This is only valid for north/south. - Hostnames []string `protobuf:"bytes,2,rep,name=hostnames,proto3" json:"hostnames,omitempty"` - // Rules are a list of HTTP-based routing rules that this route should - // use for constructing a routing table. - Rules []*HTTPRouteRule `protobuf:"bytes,3,rep,name=rules,proto3" json:"rules,omitempty"` -} - -func (x *HTTPRoute) Reset() { - *x = HTTPRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPRoute) ProtoMessage() {} - -func (x *HTTPRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPRoute.ProtoReflect.Descriptor instead. -func (*HTTPRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{0} -} - -func (x *HTTPRoute) GetParentRefs() []*ParentReference { - if x != nil { - return x.ParentRefs - } - return nil -} - -func (x *HTTPRoute) GetHostnames() []string { - if x != nil { - return x.Hostnames - } - return nil -} - -func (x *HTTPRoute) GetRules() []*HTTPRouteRule { - if x != nil { - return x.Rules - } - return nil -} - -// HTTPRouteRule specifies the routing rules used to determine what upstream -// service an HTTP request is routed to. -type HTTPRouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Matches []*HTTPRouteMatch `protobuf:"bytes,1,rep,name=matches,proto3" json:"matches,omitempty"` - Filters []*HTTPRouteFilter `protobuf:"bytes,2,rep,name=filters,proto3" json:"filters,omitempty"` - // BackendRefs defines the backend(s) where matching requests should be sent. - // - // Failure behavior here depends on how many BackendRefs are specified and - // how many are invalid. - // - // If all entries in BackendRefs are invalid, and there are also no filters - // specified in this route rule, all traffic which matches this rule MUST - // receive a 500 status code. - // - // See the HTTPBackendRef definition for the rules about what makes a single - // HTTPBackendRef invalid. - // - // When a HTTPBackendRef is invalid, 500 status codes MUST be returned for - // requests that would have otherwise been routed to an invalid backend. If - // multiple backends are specified, and some are invalid, the proportion of - // requests that would otherwise have been routed to an invalid backend MUST - // receive a 500 status code. - // - // For example, if two backends are specified with equal weights, and one is - // invalid, 50 percent of traffic must receive a 500. Implementations may - // choose how that 50 percent is determined. - BackendRefs []*HTTPBackendRef `protobuf:"bytes,3,rep,name=backend_refs,json=backendRefs,proto3" json:"backend_refs,omitempty"` - Timeouts *HTTPRouteTimeouts `protobuf:"bytes,4,opt,name=timeouts,proto3" json:"timeouts,omitempty"` - Retries *HTTPRouteRetries `protobuf:"bytes,5,opt,name=retries,proto3" json:"retries,omitempty"` -} - -func (x *HTTPRouteRule) Reset() { - *x = HTTPRouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPRouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPRouteRule) ProtoMessage() {} - -func (x *HTTPRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPRouteRule.ProtoReflect.Descriptor instead. -func (*HTTPRouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{1} -} - -func (x *HTTPRouteRule) GetMatches() []*HTTPRouteMatch { - if x != nil { - return x.Matches - } - return nil -} - -func (x *HTTPRouteRule) GetFilters() []*HTTPRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -func (x *HTTPRouteRule) GetBackendRefs() []*HTTPBackendRef { - if x != nil { - return x.BackendRefs - } - return nil -} - -func (x *HTTPRouteRule) GetTimeouts() *HTTPRouteTimeouts { - if x != nil { - return x.Timeouts - } - return nil -} - -func (x *HTTPRouteRule) GetRetries() *HTTPRouteRetries { - if x != nil { - return x.Retries - } - return nil -} - -type HTTPRouteMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Path specifies a HTTP request path matcher. If this field is not - // specified, a default prefix match on the “/” path is provided. - Path *HTTPPathMatch `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - // Headers specifies HTTP request header matchers. Multiple match values are - // ANDed together, meaning, a request must match all the specified headers to - // select the route. - Headers []*HTTPHeaderMatch `protobuf:"bytes,2,rep,name=headers,proto3" json:"headers,omitempty"` - // QueryParams specifies HTTP query parameter matchers. Multiple match values - // are ANDed together, meaning, a request must match all the specified query - // parameters to select the route. - QueryParams []*HTTPQueryParamMatch `protobuf:"bytes,3,rep,name=query_params,json=queryParams,proto3" json:"query_params,omitempty"` - // Method specifies HTTP method matcher. When specified, this route will be - // matched only if the request has the specified method. - Method string `protobuf:"bytes,4,opt,name=method,proto3" json:"method,omitempty"` -} - -func (x *HTTPRouteMatch) Reset() { - *x = HTTPRouteMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPRouteMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPRouteMatch) ProtoMessage() {} - -func (x *HTTPRouteMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPRouteMatch.ProtoReflect.Descriptor instead. -func (*HTTPRouteMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{2} -} - -func (x *HTTPRouteMatch) GetPath() *HTTPPathMatch { - if x != nil { - return x.Path - } - return nil -} - -func (x *HTTPRouteMatch) GetHeaders() []*HTTPHeaderMatch { - if x != nil { - return x.Headers - } - return nil -} - -func (x *HTTPRouteMatch) GetQueryParams() []*HTTPQueryParamMatch { - if x != nil { - return x.QueryParams - } - return nil -} - -func (x *HTTPRouteMatch) GetMethod() string { - if x != nil { - return x.Method - } - return "" -} - -type HTTPPathMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Type specifies how to match against the path Value. - Type PathMatchType `protobuf:"varint,1,opt,name=type,proto3,enum=hashicorp.consul.mesh.v2beta1.PathMatchType" json:"type,omitempty"` - // Value of the HTTP path to match against. - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *HTTPPathMatch) Reset() { - *x = HTTPPathMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPPathMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPPathMatch) ProtoMessage() {} - -func (x *HTTPPathMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPPathMatch.ProtoReflect.Descriptor instead. -func (*HTTPPathMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{3} -} - -func (x *HTTPPathMatch) GetType() PathMatchType { - if x != nil { - return x.Type - } - return PathMatchType_PATH_MATCH_TYPE_UNSPECIFIED -} - -func (x *HTTPPathMatch) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -type HTTPHeaderMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Type specifies how to match against the value of the header. - Type HeaderMatchType `protobuf:"varint,1,opt,name=type,proto3,enum=hashicorp.consul.mesh.v2beta1.HeaderMatchType" json:"type,omitempty"` - // Name is the name of the HTTP Header to be matched. Name matching MUST be - // case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - // - // If multiple entries specify equivalent header names, only the first entry - // with an equivalent name MUST be considered for a match. Subsequent entries - // with an equivalent header name MUST be ignored. Due to the - // case-insensitivity of header names, “foo” and “Foo” are considered - // equivalent. - // - // When a header is repeated in an HTTP request, it is - // implementation-specific behavior as to how this is represented. Generally, - // proxies should follow the guidance from the RFC: - // https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - // processing a repeated header, with special handling for “Set-Cookie”. - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - // Value is the value of HTTP Header to be matched. - Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` - // NOTE: not in gamma; service-router compat - Invert bool `protobuf:"varint,4,opt,name=invert,proto3" json:"invert,omitempty"` -} - -func (x *HTTPHeaderMatch) Reset() { - *x = HTTPHeaderMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPHeaderMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPHeaderMatch) ProtoMessage() {} - -func (x *HTTPHeaderMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPHeaderMatch.ProtoReflect.Descriptor instead. -func (*HTTPHeaderMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{4} -} - -func (x *HTTPHeaderMatch) GetType() HeaderMatchType { - if x != nil { - return x.Type - } - return HeaderMatchType_HEADER_MATCH_TYPE_UNSPECIFIED -} - -func (x *HTTPHeaderMatch) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *HTTPHeaderMatch) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -func (x *HTTPHeaderMatch) GetInvert() bool { - if x != nil { - return x.Invert - } - return false -} - -type HTTPQueryParamMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Type specifies how to match against the value of the query parameter. - Type QueryParamMatchType `protobuf:"varint,1,opt,name=type,proto3,enum=hashicorp.consul.mesh.v2beta1.QueryParamMatchType" json:"type,omitempty"` - // Name is the name of the HTTP query param to be matched. This must be an - // exact string match. (See - // https://tools.ietf.org/html/rfc7230#section-2.7.3). - // - // If multiple entries specify equivalent query param names, only the first - // entry with an equivalent name MUST be considered for a match. Subsequent - // entries with an equivalent query param name MUST be ignored. - // - // If a query param is repeated in an HTTP request, the behavior is purposely - // left undefined, since different data planes have different capabilities. - // However, it is recommended that implementations should match against the - // first value of the param if the data plane supports it, as this behavior - // is expected in other load balancing contexts outside of the Gateway API. - // - // Users SHOULD NOT route traffic based on repeated query params to guard - // themselves against potential differences in the implementations. - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - // Value is the value of HTTP query param to be matched. - Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *HTTPQueryParamMatch) Reset() { - *x = HTTPQueryParamMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPQueryParamMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPQueryParamMatch) ProtoMessage() {} - -func (x *HTTPQueryParamMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPQueryParamMatch.ProtoReflect.Descriptor instead. -func (*HTTPQueryParamMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{5} -} - -func (x *HTTPQueryParamMatch) GetType() QueryParamMatchType { - if x != nil { - return x.Type - } - return QueryParamMatchType_QUERY_PARAM_MATCH_TYPE_UNSPECIFIED -} - -func (x *HTTPQueryParamMatch) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *HTTPQueryParamMatch) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -type HTTPRouteFilter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // RequestHeaderModifier defines a schema for a filter that modifies request - // headers. - RequestHeaderModifier *HTTPHeaderFilter `protobuf:"bytes,1,opt,name=request_header_modifier,json=requestHeaderModifier,proto3" json:"request_header_modifier,omitempty"` - // ResponseHeaderModifier defines a schema for a filter that modifies - // response headers. - ResponseHeaderModifier *HTTPHeaderFilter `protobuf:"bytes,2,opt,name=response_header_modifier,json=responseHeaderModifier,proto3" json:"response_header_modifier,omitempty"` - // URLRewrite defines a schema for a filter that modifies a request during - // forwarding. - UrlRewrite *HTTPURLRewriteFilter `protobuf:"bytes,5,opt,name=url_rewrite,json=urlRewrite,proto3" json:"url_rewrite,omitempty"` -} - -func (x *HTTPRouteFilter) Reset() { - *x = HTTPRouteFilter{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPRouteFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPRouteFilter) ProtoMessage() {} - -func (x *HTTPRouteFilter) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPRouteFilter.ProtoReflect.Descriptor instead. -func (*HTTPRouteFilter) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{6} -} - -func (x *HTTPRouteFilter) GetRequestHeaderModifier() *HTTPHeaderFilter { - if x != nil { - return x.RequestHeaderModifier - } - return nil -} - -func (x *HTTPRouteFilter) GetResponseHeaderModifier() *HTTPHeaderFilter { - if x != nil { - return x.ResponseHeaderModifier - } - return nil -} - -func (x *HTTPRouteFilter) GetUrlRewrite() *HTTPURLRewriteFilter { - if x != nil { - return x.UrlRewrite - } - return nil -} - -type HTTPHeaderFilter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Set overwrites the request with the given header (name, value) before the - // action. - Set []*HTTPHeader `protobuf:"bytes,1,rep,name=set,proto3" json:"set,omitempty"` - // Add adds the given header(s) (name, value) to the request before the - // action. It appends to any existing values associated with the header name. - Add []*HTTPHeader `protobuf:"bytes,2,rep,name=add,proto3" json:"add,omitempty"` - // Remove the given header(s) from the HTTP request before the action. The - // value of Remove is a list of HTTP header names. Note that the header names - // are case-insensitive (see - // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - Remove []string `protobuf:"bytes,3,rep,name=remove,proto3" json:"remove,omitempty"` -} - -func (x *HTTPHeaderFilter) Reset() { - *x = HTTPHeaderFilter{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPHeaderFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPHeaderFilter) ProtoMessage() {} - -func (x *HTTPHeaderFilter) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPHeaderFilter.ProtoReflect.Descriptor instead. -func (*HTTPHeaderFilter) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{7} -} - -func (x *HTTPHeaderFilter) GetSet() []*HTTPHeader { - if x != nil { - return x.Set - } - return nil -} - -func (x *HTTPHeaderFilter) GetAdd() []*HTTPHeader { - if x != nil { - return x.Add - } - return nil -} - -func (x *HTTPHeaderFilter) GetRemove() []string { - if x != nil { - return x.Remove - } - return nil -} - -type HTTPHeader struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *HTTPHeader) Reset() { - *x = HTTPHeader{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPHeader) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPHeader) ProtoMessage() {} - -func (x *HTTPHeader) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPHeader.ProtoReflect.Descriptor instead. -func (*HTTPHeader) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{8} -} - -func (x *HTTPHeader) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *HTTPHeader) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -type HTTPURLRewriteFilter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PathPrefix string `protobuf:"bytes,1,opt,name=path_prefix,json=pathPrefix,proto3" json:"path_prefix,omitempty"` -} - -func (x *HTTPURLRewriteFilter) Reset() { - *x = HTTPURLRewriteFilter{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPURLRewriteFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPURLRewriteFilter) ProtoMessage() {} - -func (x *HTTPURLRewriteFilter) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPURLRewriteFilter.ProtoReflect.Descriptor instead. -func (*HTTPURLRewriteFilter) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{9} -} - -func (x *HTTPURLRewriteFilter) GetPathPrefix() string { - if x != nil { - return x.PathPrefix - } - return "" -} - -type HTTPBackendRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BackendRef *BackendReference `protobuf:"bytes,1,opt,name=backend_ref,json=backendRef,proto3" json:"backend_ref,omitempty"` - // Weight specifies the proportion of requests forwarded to the referenced - // backend. This is computed as weight/(sum of all weights in this - // BackendRefs list). For non-zero values, there may be some epsilon from the - // exact proportion defined here depending on the precision an implementation - // supports. Weight is not a percentage and the sum of weights does not need - // to equal 100. - // - // If only one backend is specified and it has a weight greater than 0, 100% - // of the traffic is forwarded to that backend. If weight is set to 0, no - // traffic should be forwarded for this entry. If unspecified, weight defaults - // to 1. - Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` - // Filters defined at this level should be executed if and only if the - // request is being forwarded to the backend defined here. - Filters []*HTTPRouteFilter `protobuf:"bytes,3,rep,name=filters,proto3" json:"filters,omitempty"` -} - -func (x *HTTPBackendRef) Reset() { - *x = HTTPBackendRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPBackendRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPBackendRef) ProtoMessage() {} - -func (x *HTTPBackendRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPBackendRef.ProtoReflect.Descriptor instead. -func (*HTTPBackendRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_proto_rawDescGZIP(), []int{10} -} - -func (x *HTTPBackendRef) GetBackendRef() *BackendReference { - if x != nil { - return x.BackendRef - } - return nil -} - -func (x *HTTPBackendRef) GetWeight() uint32 { - if x != nil { - return x.Weight - } - return 0 -} - -func (x *HTTPBackendRef) GetFilters() []*HTTPRouteFilter { - if x != nil { - return x.Filters - } - return nil -} - -var File_pbmesh_v2beta1_http_route_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_http_route_proto_rawDesc = []byte{ - 0x0a, 0x1f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x1a, 0x1b, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x70, - 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x68, 0x74, - 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc6, - 0x01, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4f, 0x0a, 0x0b, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, 0x12, 0x1c, 0x0a, - 0x09, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x05, 0x72, - 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x3a, - 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0x8d, 0x03, 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x47, 0x0a, 0x07, 0x6d, 0x61, 0x74, - 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, - 0x65, 0x73, 0x12, 0x48, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x50, 0x0a, 0x0c, - 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, - 0x66, 0x52, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x73, 0x12, 0x4c, - 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x73, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x12, 0x49, 0x0a, 0x07, - 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, - 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x07, - 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0x8b, 0x02, 0x0a, 0x0e, 0x48, 0x54, 0x54, 0x50, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x40, 0x0a, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, - 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x07, - 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, - 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x55, 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, - 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, - 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x52, 0x0b, 0x71, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x16, 0x0a, - 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0x67, 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, - 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x40, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x97, - 0x01, 0x0a, 0x0f, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, - 0x63, 0x68, 0x12, 0x42, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x06, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x22, 0x87, 0x01, 0x0a, 0x13, 0x48, 0x54, 0x54, - 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x12, 0x46, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x22, 0xbb, 0x02, 0x0a, 0x0f, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x67, 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, - 0x69, 0x0a, 0x18, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x52, 0x16, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x0b, 0x75, 0x72, - 0x6c, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x48, 0x54, 0x54, 0x50, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x75, 0x72, 0x6c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, - 0x22, 0xa4, 0x01, 0x0a, 0x10, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x03, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x03, 0x73, - 0x65, 0x74, 0x12, 0x3b, 0x0a, 0x03, 0x61, 0x64, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x03, 0x61, 0x64, 0x64, 0x12, - 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x22, 0x36, 0x0a, 0x0a, 0x48, 0x54, 0x54, 0x50, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, - 0x37, 0x0a, 0x14, 0x48, 0x54, 0x54, 0x50, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, - 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x74, 0x68, 0x5f, - 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, - 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0xc4, 0x01, 0x0a, 0x0e, 0x48, 0x54, 0x54, - 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x50, 0x0a, 0x0b, 0x62, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x52, 0x0a, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x16, 0x0a, - 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x77, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x48, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x2a, - 0x82, 0x01, 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x41, 0x54, 0x48, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x50, 0x41, 0x54, 0x48, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x41, 0x43, 0x54, 0x10, 0x01, 0x12, 0x1a, 0x0a, - 0x16, 0x50, 0x41, 0x54, 0x48, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x50, 0x41, 0x54, - 0x48, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x47, - 0x45, 0x58, 0x10, 0x03, 0x2a, 0xc9, 0x01, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x48, 0x45, 0x41, 0x44, - 0x45, 0x52, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x48, - 0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x45, 0x58, 0x41, 0x43, 0x54, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x44, - 0x45, 0x52, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, - 0x47, 0x45, 0x58, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, - 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x52, 0x45, 0x53, 0x45, - 0x4e, 0x54, 0x10, 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x4d, - 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, - 0x10, 0x04, 0x12, 0x1c, 0x0a, 0x18, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x4d, 0x41, 0x54, - 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x46, 0x46, 0x49, 0x58, 0x10, 0x05, - 0x2a, 0xa5, 0x01, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x22, 0x51, 0x55, 0x45, 0x52, - 0x59, 0x5f, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, - 0x12, 0x20, 0x0a, 0x1c, 0x51, 0x55, 0x45, 0x52, 0x59, 0x5f, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x5f, - 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x41, 0x43, 0x54, - 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x51, 0x55, 0x45, 0x52, 0x59, 0x5f, 0x50, 0x41, 0x52, 0x41, - 0x4d, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x47, - 0x45, 0x58, 0x10, 0x02, 0x12, 0x22, 0x0a, 0x1e, 0x51, 0x55, 0x45, 0x52, 0x59, 0x5f, 0x50, 0x41, - 0x52, 0x41, 0x4d, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, - 0x52, 0x45, 0x53, 0x45, 0x4e, 0x54, 0x10, 0x03, 0x42, 0x8f, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0e, - 0x48, 0x74, 0x74, 0x70, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, - 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, - 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, - 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, - 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, - 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_http_route_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_http_route_proto_rawDescData = file_pbmesh_v2beta1_http_route_proto_rawDesc -) - -func file_pbmesh_v2beta1_http_route_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_http_route_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_http_route_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_http_route_proto_rawDescData) - }) - return file_pbmesh_v2beta1_http_route_proto_rawDescData -} - -var file_pbmesh_v2beta1_http_route_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_pbmesh_v2beta1_http_route_proto_msgTypes = make([]protoimpl.MessageInfo, 11) -var file_pbmesh_v2beta1_http_route_proto_goTypes = []interface{}{ - (PathMatchType)(0), // 0: hashicorp.consul.mesh.v2beta1.PathMatchType - (HeaderMatchType)(0), // 1: hashicorp.consul.mesh.v2beta1.HeaderMatchType - (QueryParamMatchType)(0), // 2: hashicorp.consul.mesh.v2beta1.QueryParamMatchType - (*HTTPRoute)(nil), // 3: hashicorp.consul.mesh.v2beta1.HTTPRoute - (*HTTPRouteRule)(nil), // 4: hashicorp.consul.mesh.v2beta1.HTTPRouteRule - (*HTTPRouteMatch)(nil), // 5: hashicorp.consul.mesh.v2beta1.HTTPRouteMatch - (*HTTPPathMatch)(nil), // 6: hashicorp.consul.mesh.v2beta1.HTTPPathMatch - (*HTTPHeaderMatch)(nil), // 7: hashicorp.consul.mesh.v2beta1.HTTPHeaderMatch - (*HTTPQueryParamMatch)(nil), // 8: hashicorp.consul.mesh.v2beta1.HTTPQueryParamMatch - (*HTTPRouteFilter)(nil), // 9: hashicorp.consul.mesh.v2beta1.HTTPRouteFilter - (*HTTPHeaderFilter)(nil), // 10: hashicorp.consul.mesh.v2beta1.HTTPHeaderFilter - (*HTTPHeader)(nil), // 11: hashicorp.consul.mesh.v2beta1.HTTPHeader - (*HTTPURLRewriteFilter)(nil), // 12: hashicorp.consul.mesh.v2beta1.HTTPURLRewriteFilter - (*HTTPBackendRef)(nil), // 13: hashicorp.consul.mesh.v2beta1.HTTPBackendRef - (*ParentReference)(nil), // 14: hashicorp.consul.mesh.v2beta1.ParentReference - (*HTTPRouteTimeouts)(nil), // 15: hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts - (*HTTPRouteRetries)(nil), // 16: hashicorp.consul.mesh.v2beta1.HTTPRouteRetries - (*BackendReference)(nil), // 17: hashicorp.consul.mesh.v2beta1.BackendReference -} -var file_pbmesh_v2beta1_http_route_proto_depIdxs = []int32{ - 14, // 0: hashicorp.consul.mesh.v2beta1.HTTPRoute.parent_refs:type_name -> hashicorp.consul.mesh.v2beta1.ParentReference - 4, // 1: hashicorp.consul.mesh.v2beta1.HTTPRoute.rules:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteRule - 5, // 2: hashicorp.consul.mesh.v2beta1.HTTPRouteRule.matches:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteMatch - 9, // 3: hashicorp.consul.mesh.v2beta1.HTTPRouteRule.filters:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteFilter - 13, // 4: hashicorp.consul.mesh.v2beta1.HTTPRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v2beta1.HTTPBackendRef - 15, // 5: hashicorp.consul.mesh.v2beta1.HTTPRouteRule.timeouts:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts - 16, // 6: hashicorp.consul.mesh.v2beta1.HTTPRouteRule.retries:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteRetries - 6, // 7: hashicorp.consul.mesh.v2beta1.HTTPRouteMatch.path:type_name -> hashicorp.consul.mesh.v2beta1.HTTPPathMatch - 7, // 8: hashicorp.consul.mesh.v2beta1.HTTPRouteMatch.headers:type_name -> hashicorp.consul.mesh.v2beta1.HTTPHeaderMatch - 8, // 9: hashicorp.consul.mesh.v2beta1.HTTPRouteMatch.query_params:type_name -> hashicorp.consul.mesh.v2beta1.HTTPQueryParamMatch - 0, // 10: hashicorp.consul.mesh.v2beta1.HTTPPathMatch.type:type_name -> hashicorp.consul.mesh.v2beta1.PathMatchType - 1, // 11: hashicorp.consul.mesh.v2beta1.HTTPHeaderMatch.type:type_name -> hashicorp.consul.mesh.v2beta1.HeaderMatchType - 2, // 12: hashicorp.consul.mesh.v2beta1.HTTPQueryParamMatch.type:type_name -> hashicorp.consul.mesh.v2beta1.QueryParamMatchType - 10, // 13: hashicorp.consul.mesh.v2beta1.HTTPRouteFilter.request_header_modifier:type_name -> hashicorp.consul.mesh.v2beta1.HTTPHeaderFilter - 10, // 14: hashicorp.consul.mesh.v2beta1.HTTPRouteFilter.response_header_modifier:type_name -> hashicorp.consul.mesh.v2beta1.HTTPHeaderFilter - 12, // 15: hashicorp.consul.mesh.v2beta1.HTTPRouteFilter.url_rewrite:type_name -> hashicorp.consul.mesh.v2beta1.HTTPURLRewriteFilter - 11, // 16: hashicorp.consul.mesh.v2beta1.HTTPHeaderFilter.set:type_name -> hashicorp.consul.mesh.v2beta1.HTTPHeader - 11, // 17: hashicorp.consul.mesh.v2beta1.HTTPHeaderFilter.add:type_name -> hashicorp.consul.mesh.v2beta1.HTTPHeader - 17, // 18: hashicorp.consul.mesh.v2beta1.HTTPBackendRef.backend_ref:type_name -> hashicorp.consul.mesh.v2beta1.BackendReference - 9, // 19: hashicorp.consul.mesh.v2beta1.HTTPBackendRef.filters:type_name -> hashicorp.consul.mesh.v2beta1.HTTPRouteFilter - 20, // [20:20] is the sub-list for method output_type - 20, // [20:20] is the sub-list for method input_type - 20, // [20:20] is the sub-list for extension type_name - 20, // [20:20] is the sub-list for extension extendee - 0, // [0:20] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_http_route_proto_init() } -func file_pbmesh_v2beta1_http_route_proto_init() { - if File_pbmesh_v2beta1_http_route_proto != nil { - return - } - file_pbmesh_v2beta1_common_proto_init() - file_pbmesh_v2beta1_http_route_retries_proto_init() - file_pbmesh_v2beta1_http_route_timeouts_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_http_route_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_http_route_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_http_route_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRouteMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_http_route_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPPathMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_http_route_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPHeaderMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_http_route_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPQueryParamMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_http_route_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRouteFilter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_http_route_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPHeaderFilter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_http_route_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPHeader); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_http_route_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPURLRewriteFilter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_http_route_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPBackendRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_http_route_proto_rawDesc, - NumEnums: 3, - NumMessages: 11, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_http_route_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_http_route_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_http_route_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_http_route_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_http_route_proto = out.File - file_pbmesh_v2beta1_http_route_proto_rawDesc = nil - file_pbmesh_v2beta1_http_route_proto_goTypes = nil - file_pbmesh_v2beta1_http_route_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/http_route.proto b/proto-public/pbmesh/v2beta1/http_route.proto deleted file mode 100644 index b651921c48c0..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route.proto +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "pbmesh/v2beta1/common.proto"; -import "pbmesh/v2beta1/http_route_retries.proto"; -import "pbmesh/v2beta1/http_route_timeouts.proto"; -import "pbresource/annotations.proto"; - -// NOTE: this should align to the GAMMA/gateway-api version, or at least be -// easily translatable. -// -// https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.HTTPRoute -// -// This is a Resource type. -message HTTPRoute { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // ParentRefs references the resources (usually Services) that a Route wants - // to be attached to. - // - // It is invalid to reference an identical parent more than once. It is valid - // to reference multiple distinct sections within the same parent resource. - repeated ParentReference parent_refs = 1; - - // Hostnames are the hostnames for which this HTTPRoute should respond to requests. - // - // This is only valid for north/south. - repeated string hostnames = 2; - - // Rules are a list of HTTP-based routing rules that this route should - // use for constructing a routing table. - repeated HTTPRouteRule rules = 3; -} - -// HTTPRouteRule specifies the routing rules used to determine what upstream -// service an HTTP request is routed to. -message HTTPRouteRule { - repeated HTTPRouteMatch matches = 1; - repeated HTTPRouteFilter filters = 2; - - // BackendRefs defines the backend(s) where matching requests should be sent. - // - // Failure behavior here depends on how many BackendRefs are specified and - // how many are invalid. - // - // If all entries in BackendRefs are invalid, and there are also no filters - // specified in this route rule, all traffic which matches this rule MUST - // receive a 500 status code. - // - // See the HTTPBackendRef definition for the rules about what makes a single - // HTTPBackendRef invalid. - // - // When a HTTPBackendRef is invalid, 500 status codes MUST be returned for - // requests that would have otherwise been routed to an invalid backend. If - // multiple backends are specified, and some are invalid, the proportion of - // requests that would otherwise have been routed to an invalid backend MUST - // receive a 500 status code. - // - // For example, if two backends are specified with equal weights, and one is - // invalid, 50 percent of traffic must receive a 500. Implementations may - // choose how that 50 percent is determined. - repeated HTTPBackendRef backend_refs = 3; - - HTTPRouteTimeouts timeouts = 4; - HTTPRouteRetries retries = 5; -} - -message HTTPRouteMatch { - // Path specifies a HTTP request path matcher. If this field is not - // specified, a default prefix match on the “/” path is provided. - HTTPPathMatch path = 1; - - // Headers specifies HTTP request header matchers. Multiple match values are - // ANDed together, meaning, a request must match all the specified headers to - // select the route. - repeated HTTPHeaderMatch headers = 2; - - // QueryParams specifies HTTP query parameter matchers. Multiple match values - // are ANDed together, meaning, a request must match all the specified query - // parameters to select the route. - repeated HTTPQueryParamMatch query_params = 3; - - // Method specifies HTTP method matcher. When specified, this route will be - // matched only if the request has the specified method. - string method = 4; -} - -message HTTPPathMatch { - // Type specifies how to match against the path Value. - PathMatchType type = 1; - // Value of the HTTP path to match against. - string value = 2; -} - -// PathMatchType specifies the semantics of how HTTP paths should be compared. -// Valid PathMatchType values, along with their support levels, are: -// -// PathPrefix and Exact paths must be syntactically valid: -// -// - Must begin with the / character -// - Must not contain consecutive / characters (e.g. /foo///, //). -// - Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the Accepted -// Condition for the Route to status: False, with a Reason of UnsupportedValue. -// -// +kubebuilder:validation:Enum=PATH_MATCH_TYPE_UNSPECIFIED;PATH_MATCH_TYPE_EXACT;PATH_MATCH_TYPE_PREFIX;PATH_MATCH_TYPE_REGEX -// +kubebuilder:validation:Type=string -enum PathMatchType { - PATH_MATCH_TYPE_UNSPECIFIED = 0; - PATH_MATCH_TYPE_EXACT = 1; - PATH_MATCH_TYPE_PREFIX = 2; - PATH_MATCH_TYPE_REGEX = 3; -} - -message HTTPHeaderMatch { - // Type specifies how to match against the value of the header. - HeaderMatchType type = 1; - - // Name is the name of the HTTP Header to be matched. Name matching MUST be - // case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - // - // If multiple entries specify equivalent header names, only the first entry - // with an equivalent name MUST be considered for a match. Subsequent entries - // with an equivalent header name MUST be ignored. Due to the - // case-insensitivity of header names, “foo” and “Foo” are considered - // equivalent. - // - // When a header is repeated in an HTTP request, it is - // implementation-specific behavior as to how this is represented. Generally, - // proxies should follow the guidance from the RFC: - // https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - // processing a repeated header, with special handling for “Set-Cookie”. - string name = 2; - - // Value is the value of HTTP Header to be matched. - string value = 3; - - // NOTE: not in gamma; service-router compat - bool invert = 4; -} - -// HeaderMatchType specifies the semantics of how HTTP header values should be -// compared. Valid HeaderMatchType values, along with their conformance levels, -// are: -// -// Note that values may be added to this enum, implementations must ensure that -// unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the Accepted -// Condition for the Route to status: False, with a Reason of UnsupportedValue. -// -// +kubebuilder:validation:Enum=HEADER_MATCH_TYPE_UNSPECIFIED;HEADER_MATCH_TYPE_EXACT;HEADER_MATCH_TYPE_REGEX;HEADER_MATCH_TYPE_PRESENT;HEADER_MATCH_TYPE_PREFIX;HEADER_MATCH_TYPE_SUFFIX -// +kubebuilder:validation:Type=string -enum HeaderMatchType { - HEADER_MATCH_TYPE_UNSPECIFIED = 0; - HEADER_MATCH_TYPE_EXACT = 1; - HEADER_MATCH_TYPE_REGEX = 2; - // consul only after this point (service-router compat) - HEADER_MATCH_TYPE_PRESENT = 3; - HEADER_MATCH_TYPE_PREFIX = 4; - HEADER_MATCH_TYPE_SUFFIX = 5; -} - -message HTTPQueryParamMatch { - // Type specifies how to match against the value of the query parameter. - QueryParamMatchType type = 1; - - // Name is the name of the HTTP query param to be matched. This must be an - // exact string match. (See - // https://tools.ietf.org/html/rfc7230#section-2.7.3). - // - // If multiple entries specify equivalent query param names, only the first - // entry with an equivalent name MUST be considered for a match. Subsequent - // entries with an equivalent query param name MUST be ignored. - // - // If a query param is repeated in an HTTP request, the behavior is purposely - // left undefined, since different data planes have different capabilities. - // However, it is recommended that implementations should match against the - // first value of the param if the data plane supports it, as this behavior - // is expected in other load balancing contexts outside of the Gateway API. - // - // Users SHOULD NOT route traffic based on repeated query params to guard - // themselves against potential differences in the implementations. - string name = 2; - - // Value is the value of HTTP query param to be matched. - string value = 3; -} - -// +kubebuilder:validation:Enum=QUERY_PARAM_MATCH_TYPE_UNSPECIFIED;QUERY_PARAM_MATCH_TYPE_EXACT;QUERY_PARAM_MATCH_TYPE_REGEX;QUERY_PARAM_MATCH_TYPE_PRESENT -// +kubebuilder:validation:Type=string -enum QueryParamMatchType { - QUERY_PARAM_MATCH_TYPE_UNSPECIFIED = 0; - QUERY_PARAM_MATCH_TYPE_EXACT = 1; - QUERY_PARAM_MATCH_TYPE_REGEX = 2; - // consul only after this point (service-router compat) - QUERY_PARAM_MATCH_TYPE_PRESENT = 3; -} - -message HTTPRouteFilter { - // RequestHeaderModifier defines a schema for a filter that modifies request - // headers. - HTTPHeaderFilter request_header_modifier = 1; - - // ResponseHeaderModifier defines a schema for a filter that modifies - // response headers. - HTTPHeaderFilter response_header_modifier = 2; - - // URLRewrite defines a schema for a filter that modifies a request during - // forwarding. - HTTPURLRewriteFilter url_rewrite = 5; -} - -message HTTPHeaderFilter { - // Set overwrites the request with the given header (name, value) before the - // action. - repeated HTTPHeader set = 1; - - // Add adds the given header(s) (name, value) to the request before the - // action. It appends to any existing values associated with the header name. - repeated HTTPHeader add = 2; - - // Remove the given header(s) from the HTTP request before the action. The - // value of Remove is a list of HTTP header names. Note that the header names - // are case-insensitive (see - // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - repeated string remove = 3; -} - -message HTTPHeader { - string name = 1; - string value = 2; -} - -message HTTPURLRewriteFilter { - string path_prefix = 1; -} - -message HTTPBackendRef { - BackendReference backend_ref = 1; - - // Weight specifies the proportion of requests forwarded to the referenced - // backend. This is computed as weight/(sum of all weights in this - // BackendRefs list). For non-zero values, there may be some epsilon from the - // exact proportion defined here depending on the precision an implementation - // supports. Weight is not a percentage and the sum of weights does not need - // to equal 100. - // - // If only one backend is specified and it has a weight greater than 0, 100% - // of the traffic is forwarded to that backend. If weight is set to 0, no - // traffic should be forwarded for this entry. If unspecified, weight defaults - // to 1. - uint32 weight = 2; - - // Filters defined at this level should be executed if and only if the - // request is being forwarded to the backend defined here. - repeated HTTPRouteFilter filters = 3; -} diff --git a/proto-public/pbmesh/v2beta1/http_route_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/http_route_deepcopy.gen.go deleted file mode 100644 index 6d339e5afde2..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route_deepcopy.gen.go +++ /dev/null @@ -1,237 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using HTTPRoute within kubernetes types, where deepcopy-gen is used. -func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRoute. Required by controller-gen. -func (in *HTTPRoute) DeepCopy() *HTTPRoute { - if in == nil { - return nil - } - out := new(HTTPRoute) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRoute. Required by controller-gen. -func (in *HTTPRoute) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HTTPRouteRule within kubernetes types, where deepcopy-gen is used. -func (in *HTTPRouteRule) DeepCopyInto(out *HTTPRouteRule) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteRule. Required by controller-gen. -func (in *HTTPRouteRule) DeepCopy() *HTTPRouteRule { - if in == nil { - return nil - } - out := new(HTTPRouteRule) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteRule. Required by controller-gen. -func (in *HTTPRouteRule) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HTTPRouteMatch within kubernetes types, where deepcopy-gen is used. -func (in *HTTPRouteMatch) DeepCopyInto(out *HTTPRouteMatch) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteMatch. Required by controller-gen. -func (in *HTTPRouteMatch) DeepCopy() *HTTPRouteMatch { - if in == nil { - return nil - } - out := new(HTTPRouteMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteMatch. Required by controller-gen. -func (in *HTTPRouteMatch) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HTTPPathMatch within kubernetes types, where deepcopy-gen is used. -func (in *HTTPPathMatch) DeepCopyInto(out *HTTPPathMatch) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPPathMatch. Required by controller-gen. -func (in *HTTPPathMatch) DeepCopy() *HTTPPathMatch { - if in == nil { - return nil - } - out := new(HTTPPathMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPPathMatch. Required by controller-gen. -func (in *HTTPPathMatch) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HTTPHeaderMatch within kubernetes types, where deepcopy-gen is used. -func (in *HTTPHeaderMatch) DeepCopyInto(out *HTTPHeaderMatch) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeaderMatch. Required by controller-gen. -func (in *HTTPHeaderMatch) DeepCopy() *HTTPHeaderMatch { - if in == nil { - return nil - } - out := new(HTTPHeaderMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeaderMatch. Required by controller-gen. -func (in *HTTPHeaderMatch) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HTTPQueryParamMatch within kubernetes types, where deepcopy-gen is used. -func (in *HTTPQueryParamMatch) DeepCopyInto(out *HTTPQueryParamMatch) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPQueryParamMatch. Required by controller-gen. -func (in *HTTPQueryParamMatch) DeepCopy() *HTTPQueryParamMatch { - if in == nil { - return nil - } - out := new(HTTPQueryParamMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPQueryParamMatch. Required by controller-gen. -func (in *HTTPQueryParamMatch) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HTTPRouteFilter within kubernetes types, where deepcopy-gen is used. -func (in *HTTPRouteFilter) DeepCopyInto(out *HTTPRouteFilter) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteFilter. Required by controller-gen. -func (in *HTTPRouteFilter) DeepCopy() *HTTPRouteFilter { - if in == nil { - return nil - } - out := new(HTTPRouteFilter) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteFilter. Required by controller-gen. -func (in *HTTPRouteFilter) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HTTPHeaderFilter within kubernetes types, where deepcopy-gen is used. -func (in *HTTPHeaderFilter) DeepCopyInto(out *HTTPHeaderFilter) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeaderFilter. Required by controller-gen. -func (in *HTTPHeaderFilter) DeepCopy() *HTTPHeaderFilter { - if in == nil { - return nil - } - out := new(HTTPHeaderFilter) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeaderFilter. Required by controller-gen. -func (in *HTTPHeaderFilter) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HTTPHeader within kubernetes types, where deepcopy-gen is used. -func (in *HTTPHeader) DeepCopyInto(out *HTTPHeader) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeader. Required by controller-gen. -func (in *HTTPHeader) DeepCopy() *HTTPHeader { - if in == nil { - return nil - } - out := new(HTTPHeader) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeader. Required by controller-gen. -func (in *HTTPHeader) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HTTPURLRewriteFilter within kubernetes types, where deepcopy-gen is used. -func (in *HTTPURLRewriteFilter) DeepCopyInto(out *HTTPURLRewriteFilter) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPURLRewriteFilter. Required by controller-gen. -func (in *HTTPURLRewriteFilter) DeepCopy() *HTTPURLRewriteFilter { - if in == nil { - return nil - } - out := new(HTTPURLRewriteFilter) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPURLRewriteFilter. Required by controller-gen. -func (in *HTTPURLRewriteFilter) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HTTPBackendRef within kubernetes types, where deepcopy-gen is used. -func (in *HTTPBackendRef) DeepCopyInto(out *HTTPBackendRef) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPBackendRef. Required by controller-gen. -func (in *HTTPBackendRef) DeepCopy() *HTTPBackendRef { - if in == nil { - return nil - } - out := new(HTTPBackendRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPBackendRef. Required by controller-gen. -func (in *HTTPBackendRef) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/http_route_json.gen.go b/proto-public/pbmesh/v2beta1/http_route_json.gen.go deleted file mode 100644 index 2860a5a356cc..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route_json.gen.go +++ /dev/null @@ -1,132 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for HTTPRoute -func (this *HTTPRoute) MarshalJSON() ([]byte, error) { - str, err := HttpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPRoute -func (this *HTTPRoute) UnmarshalJSON(b []byte) error { - return HttpRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HTTPRouteRule -func (this *HTTPRouteRule) MarshalJSON() ([]byte, error) { - str, err := HttpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPRouteRule -func (this *HTTPRouteRule) UnmarshalJSON(b []byte) error { - return HttpRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HTTPRouteMatch -func (this *HTTPRouteMatch) MarshalJSON() ([]byte, error) { - str, err := HttpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPRouteMatch -func (this *HTTPRouteMatch) UnmarshalJSON(b []byte) error { - return HttpRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HTTPPathMatch -func (this *HTTPPathMatch) MarshalJSON() ([]byte, error) { - str, err := HttpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPPathMatch -func (this *HTTPPathMatch) UnmarshalJSON(b []byte) error { - return HttpRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HTTPHeaderMatch -func (this *HTTPHeaderMatch) MarshalJSON() ([]byte, error) { - str, err := HttpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPHeaderMatch -func (this *HTTPHeaderMatch) UnmarshalJSON(b []byte) error { - return HttpRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HTTPQueryParamMatch -func (this *HTTPQueryParamMatch) MarshalJSON() ([]byte, error) { - str, err := HttpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPQueryParamMatch -func (this *HTTPQueryParamMatch) UnmarshalJSON(b []byte) error { - return HttpRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HTTPRouteFilter -func (this *HTTPRouteFilter) MarshalJSON() ([]byte, error) { - str, err := HttpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPRouteFilter -func (this *HTTPRouteFilter) UnmarshalJSON(b []byte) error { - return HttpRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HTTPHeaderFilter -func (this *HTTPHeaderFilter) MarshalJSON() ([]byte, error) { - str, err := HttpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPHeaderFilter -func (this *HTTPHeaderFilter) UnmarshalJSON(b []byte) error { - return HttpRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HTTPHeader -func (this *HTTPHeader) MarshalJSON() ([]byte, error) { - str, err := HttpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPHeader -func (this *HTTPHeader) UnmarshalJSON(b []byte) error { - return HttpRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HTTPURLRewriteFilter -func (this *HTTPURLRewriteFilter) MarshalJSON() ([]byte, error) { - str, err := HttpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPURLRewriteFilter -func (this *HTTPURLRewriteFilter) UnmarshalJSON(b []byte) error { - return HttpRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HTTPBackendRef -func (this *HTTPBackendRef) MarshalJSON() ([]byte, error) { - str, err := HttpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPBackendRef -func (this *HTTPBackendRef) UnmarshalJSON(b []byte) error { - return HttpRouteUnmarshaler.Unmarshal(b, this) -} - -var ( - HttpRouteMarshaler = &protojson.MarshalOptions{} - HttpRouteUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/http_route_retries.pb.binary.go b/proto-public/pbmesh/v2beta1/http_route_retries.pb.binary.go deleted file mode 100644 index 390641d255ec..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route_retries.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/http_route_retries.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPRouteRetries) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPRouteRetries) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/http_route_retries.pb.go b/proto-public/pbmesh/v2beta1/http_route_retries.pb.go deleted file mode 100644 index 49f1501fc78e..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route_retries.pb.go +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/http_route_retries.proto - -package meshv2beta1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type HTTPRouteRetries struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Number is the number of times to retry the request when a retryable - // result occurs. - Number *wrapperspb.UInt32Value `protobuf:"bytes,1,opt,name=number,proto3" json:"number,omitempty"` - // RetryOnConnectFailure allows for connection failure errors to trigger a - // retry. - OnConnectFailure bool `protobuf:"varint,2,opt,name=on_connect_failure,json=onConnectFailure,proto3" json:"on_connect_failure,omitempty"` - // RetryOn allows setting envoy specific conditions when a request should - // be automatically retried. - OnConditions []string `protobuf:"bytes,3,rep,name=on_conditions,json=onConditions,proto3" json:"on_conditions,omitempty"` - // RetryOnStatusCodes is a flat list of http response status codes that are - // eligible for retry. This again should be feasible in any reasonable proxy. - OnStatusCodes []uint32 `protobuf:"varint,4,rep,packed,name=on_status_codes,json=onStatusCodes,proto3" json:"on_status_codes,omitempty"` -} - -func (x *HTTPRouteRetries) Reset() { - *x = HTTPRouteRetries{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_retries_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPRouteRetries) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPRouteRetries) ProtoMessage() {} - -func (x *HTTPRouteRetries) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_retries_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPRouteRetries.ProtoReflect.Descriptor instead. -func (*HTTPRouteRetries) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_retries_proto_rawDescGZIP(), []int{0} -} - -func (x *HTTPRouteRetries) GetNumber() *wrapperspb.UInt32Value { - if x != nil { - return x.Number - } - return nil -} - -func (x *HTTPRouteRetries) GetOnConnectFailure() bool { - if x != nil { - return x.OnConnectFailure - } - return false -} - -func (x *HTTPRouteRetries) GetOnConditions() []string { - if x != nil { - return x.OnConditions - } - return nil -} - -func (x *HTTPRouteRetries) GetOnStatusCodes() []uint32 { - if x != nil { - return x.OnStatusCodes - } - return nil -} - -var File_pbmesh_v2beta1_http_route_retries_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_http_route_retries_proto_rawDesc = []byte{ - 0x0a, 0x27, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, - 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc3, 0x01, 0x0a, 0x10, 0x48, 0x54, 0x54, - 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x34, 0x0a, - 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x10, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, - 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, - 0x0d, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x42, 0x96, - 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x42, 0x15, 0x48, 0x74, 0x74, 0x70, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, - 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_http_route_retries_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_http_route_retries_proto_rawDescData = file_pbmesh_v2beta1_http_route_retries_proto_rawDesc -) - -func file_pbmesh_v2beta1_http_route_retries_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_http_route_retries_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_http_route_retries_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_http_route_retries_proto_rawDescData) - }) - return file_pbmesh_v2beta1_http_route_retries_proto_rawDescData -} - -var file_pbmesh_v2beta1_http_route_retries_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmesh_v2beta1_http_route_retries_proto_goTypes = []interface{}{ - (*HTTPRouteRetries)(nil), // 0: hashicorp.consul.mesh.v2beta1.HTTPRouteRetries - (*wrapperspb.UInt32Value)(nil), // 1: google.protobuf.UInt32Value -} -var file_pbmesh_v2beta1_http_route_retries_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.mesh.v2beta1.HTTPRouteRetries.number:type_name -> google.protobuf.UInt32Value - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_http_route_retries_proto_init() } -func file_pbmesh_v2beta1_http_route_retries_proto_init() { - if File_pbmesh_v2beta1_http_route_retries_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_http_route_retries_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRouteRetries); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_http_route_retries_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_http_route_retries_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_http_route_retries_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_http_route_retries_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_http_route_retries_proto = out.File - file_pbmesh_v2beta1_http_route_retries_proto_rawDesc = nil - file_pbmesh_v2beta1_http_route_retries_proto_goTypes = nil - file_pbmesh_v2beta1_http_route_retries_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/http_route_retries.proto b/proto-public/pbmesh/v2beta1/http_route_retries.proto deleted file mode 100644 index 7eae2545866a..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route_retries.proto +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "google/protobuf/wrappers.proto"; - -message HTTPRouteRetries { - // Number is the number of times to retry the request when a retryable - // result occurs. - google.protobuf.UInt32Value number = 1; - - // RetryOnConnectFailure allows for connection failure errors to trigger a - // retry. - bool on_connect_failure = 2; - - // RetryOn allows setting envoy specific conditions when a request should - // be automatically retried. - repeated string on_conditions = 3; - - // RetryOnStatusCodes is a flat list of http response status codes that are - // eligible for retry. This again should be feasible in any reasonable proxy. - repeated uint32 on_status_codes = 4; -} diff --git a/proto-public/pbmesh/v2beta1/http_route_retries_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/http_route_retries_deepcopy.gen.go deleted file mode 100644 index abd2a515332d..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route_retries_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using HTTPRouteRetries within kubernetes types, where deepcopy-gen is used. -func (in *HTTPRouteRetries) DeepCopyInto(out *HTTPRouteRetries) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteRetries. Required by controller-gen. -func (in *HTTPRouteRetries) DeepCopy() *HTTPRouteRetries { - if in == nil { - return nil - } - out := new(HTTPRouteRetries) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteRetries. Required by controller-gen. -func (in *HTTPRouteRetries) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/http_route_retries_json.gen.go b/proto-public/pbmesh/v2beta1/http_route_retries_json.gen.go deleted file mode 100644 index 5dfe2a5061f6..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route_retries_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for HTTPRouteRetries -func (this *HTTPRouteRetries) MarshalJSON() ([]byte, error) { - str, err := HttpRouteRetriesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPRouteRetries -func (this *HTTPRouteRetries) UnmarshalJSON(b []byte) error { - return HttpRouteRetriesUnmarshaler.Unmarshal(b, this) -} - -var ( - HttpRouteRetriesMarshaler = &protojson.MarshalOptions{} - HttpRouteRetriesUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/http_route_timeouts.pb.binary.go b/proto-public/pbmesh/v2beta1/http_route_timeouts.pb.binary.go deleted file mode 100644 index a85a09cf2fe2..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route_timeouts.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/http_route_timeouts.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HTTPRouteTimeouts) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HTTPRouteTimeouts) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/http_route_timeouts.pb.go b/proto-public/pbmesh/v2beta1/http_route_timeouts.pb.go deleted file mode 100644 index 87e5ec3f578a..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route_timeouts.pb.go +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/http_route_timeouts.proto - -package meshv2beta1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute -// or GRPCRoute. -type HTTPRouteTimeouts struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // RequestTimeout is the total amount of time permitted for the entire - // downstream request (and retries) to be processed. - // +kubebuilder:validation:Format=duration - Request *durationpb.Duration `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"` - // Idle specifies the total amount of time permitted for the request stream to be idle. - // +kubebuilder:validation:Format=duration - Idle *durationpb.Duration `protobuf:"bytes,2,opt,name=idle,proto3" json:"idle,omitempty"` -} - -func (x *HTTPRouteTimeouts) Reset() { - *x = HTTPRouteTimeouts{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_http_route_timeouts_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HTTPRouteTimeouts) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HTTPRouteTimeouts) ProtoMessage() {} - -func (x *HTTPRouteTimeouts) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_http_route_timeouts_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HTTPRouteTimeouts.ProtoReflect.Descriptor instead. -func (*HTTPRouteTimeouts) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_http_route_timeouts_proto_rawDescGZIP(), []int{0} -} - -func (x *HTTPRouteTimeouts) GetRequest() *durationpb.Duration { - if x != nil { - return x.Request - } - return nil -} - -func (x *HTTPRouteTimeouts) GetIdle() *durationpb.Duration { - if x != nil { - return x.Idle - } - return nil -} - -var File_pbmesh_v2beta1_http_route_timeouts_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_http_route_timeouts_proto_rawDesc = []byte{ - 0x0a, 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x77, 0x0a, 0x11, 0x48, 0x54, 0x54, - 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x12, 0x33, - 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x04, 0x69, 0x64, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x69, 0x64, - 0x6c, 0x65, 0x42, 0x97, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x16, 0x48, 0x74, 0x74, 0x70, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1d, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, - 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_http_route_timeouts_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_http_route_timeouts_proto_rawDescData = file_pbmesh_v2beta1_http_route_timeouts_proto_rawDesc -) - -func file_pbmesh_v2beta1_http_route_timeouts_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_http_route_timeouts_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_http_route_timeouts_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_http_route_timeouts_proto_rawDescData) - }) - return file_pbmesh_v2beta1_http_route_timeouts_proto_rawDescData -} - -var file_pbmesh_v2beta1_http_route_timeouts_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmesh_v2beta1_http_route_timeouts_proto_goTypes = []interface{}{ - (*HTTPRouteTimeouts)(nil), // 0: hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts - (*durationpb.Duration)(nil), // 1: google.protobuf.Duration -} -var file_pbmesh_v2beta1_http_route_timeouts_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts.request:type_name -> google.protobuf.Duration - 1, // 1: hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts.idle:type_name -> google.protobuf.Duration - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_http_route_timeouts_proto_init() } -func file_pbmesh_v2beta1_http_route_timeouts_proto_init() { - if File_pbmesh_v2beta1_http_route_timeouts_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_http_route_timeouts_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HTTPRouteTimeouts); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_http_route_timeouts_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_http_route_timeouts_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_http_route_timeouts_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_http_route_timeouts_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_http_route_timeouts_proto = out.File - file_pbmesh_v2beta1_http_route_timeouts_proto_rawDesc = nil - file_pbmesh_v2beta1_http_route_timeouts_proto_goTypes = nil - file_pbmesh_v2beta1_http_route_timeouts_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/http_route_timeouts.proto b/proto-public/pbmesh/v2beta1/http_route_timeouts.proto deleted file mode 100644 index 246971251d5f..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route_timeouts.proto +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "google/protobuf/duration.proto"; - -// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute -// or GRPCRoute. -message HTTPRouteTimeouts { - // RequestTimeout is the total amount of time permitted for the entire - // downstream request (and retries) to be processed. - // +kubebuilder:validation:Format=duration - google.protobuf.Duration request = 1; - - // Idle specifies the total amount of time permitted for the request stream to be idle. - // +kubebuilder:validation:Format=duration - google.protobuf.Duration idle = 2; -} diff --git a/proto-public/pbmesh/v2beta1/http_route_timeouts_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/http_route_timeouts_deepcopy.gen.go deleted file mode 100644 index c131310e5e26..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route_timeouts_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using HTTPRouteTimeouts within kubernetes types, where deepcopy-gen is used. -func (in *HTTPRouteTimeouts) DeepCopyInto(out *HTTPRouteTimeouts) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteTimeouts. Required by controller-gen. -func (in *HTTPRouteTimeouts) DeepCopy() *HTTPRouteTimeouts { - if in == nil { - return nil - } - out := new(HTTPRouteTimeouts) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteTimeouts. Required by controller-gen. -func (in *HTTPRouteTimeouts) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/http_route_timeouts_json.gen.go b/proto-public/pbmesh/v2beta1/http_route_timeouts_json.gen.go deleted file mode 100644 index c81461d22546..000000000000 --- a/proto-public/pbmesh/v2beta1/http_route_timeouts_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for HTTPRouteTimeouts -func (this *HTTPRouteTimeouts) MarshalJSON() ([]byte, error) { - str, err := HttpRouteTimeoutsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HTTPRouteTimeouts -func (this *HTTPRouteTimeouts) UnmarshalJSON(b []byte) error { - return HttpRouteTimeoutsUnmarshaler.Unmarshal(b, this) -} - -var ( - HttpRouteTimeoutsMarshaler = &protojson.MarshalOptions{} - HttpRouteTimeoutsUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/mesh_gateway.pb.binary.go b/proto-public/pbmesh/v2beta1/mesh_gateway.pb.binary.go deleted file mode 100644 index 7cd36afdb3c0..000000000000 --- a/proto-public/pbmesh/v2beta1/mesh_gateway.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/mesh_gateway.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *MeshGateway) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *MeshGateway) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/mesh_gateway.pb.go b/proto-public/pbmesh/v2beta1/mesh_gateway.pb.go deleted file mode 100644 index 7eb247ded34a..000000000000 --- a/proto-public/pbmesh/v2beta1/mesh_gateway.pb.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/mesh_gateway.proto - -package meshv2beta1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type MeshGateway struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *MeshGateway) Reset() { - *x = MeshGateway{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_mesh_gateway_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MeshGateway) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MeshGateway) ProtoMessage() {} - -func (x *MeshGateway) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_mesh_gateway_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MeshGateway.ProtoReflect.Descriptor instead. -func (*MeshGateway) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_mesh_gateway_proto_rawDescGZIP(), []int{0} -} - -var File_pbmesh_v2beta1_mesh_gateway_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_mesh_gateway_proto_rawDesc = []byte{ - 0x0a, 0x21, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x6d, 0x65, 0x73, 0x68, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x22, 0x0d, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x42, 0x91, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x10, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_mesh_gateway_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_mesh_gateway_proto_rawDescData = file_pbmesh_v2beta1_mesh_gateway_proto_rawDesc -) - -func file_pbmesh_v2beta1_mesh_gateway_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_mesh_gateway_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_mesh_gateway_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_mesh_gateway_proto_rawDescData) - }) - return file_pbmesh_v2beta1_mesh_gateway_proto_rawDescData -} - -var file_pbmesh_v2beta1_mesh_gateway_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmesh_v2beta1_mesh_gateway_proto_goTypes = []interface{}{ - (*MeshGateway)(nil), // 0: hashicorp.consul.mesh.v2beta1.MeshGateway -} -var file_pbmesh_v2beta1_mesh_gateway_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_mesh_gateway_proto_init() } -func file_pbmesh_v2beta1_mesh_gateway_proto_init() { - if File_pbmesh_v2beta1_mesh_gateway_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_mesh_gateway_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MeshGateway); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_mesh_gateway_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_mesh_gateway_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_mesh_gateway_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_mesh_gateway_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_mesh_gateway_proto = out.File - file_pbmesh_v2beta1_mesh_gateway_proto_rawDesc = nil - file_pbmesh_v2beta1_mesh_gateway_proto_goTypes = nil - file_pbmesh_v2beta1_mesh_gateway_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/mesh_gateway.proto b/proto-public/pbmesh/v2beta1/mesh_gateway.proto deleted file mode 100644 index 1d976d7e22a3..000000000000 --- a/proto-public/pbmesh/v2beta1/mesh_gateway.proto +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -message MeshGateway {} diff --git a/proto-public/pbmesh/v2beta1/mesh_gateway_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/mesh_gateway_deepcopy.gen.go deleted file mode 100644 index b14ad33a815a..000000000000 --- a/proto-public/pbmesh/v2beta1/mesh_gateway_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using MeshGateway within kubernetes types, where deepcopy-gen is used. -func (in *MeshGateway) DeepCopyInto(out *MeshGateway) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshGateway. Required by controller-gen. -func (in *MeshGateway) DeepCopy() *MeshGateway { - if in == nil { - return nil - } - out := new(MeshGateway) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new MeshGateway. Required by controller-gen. -func (in *MeshGateway) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/mesh_gateway_json.gen.go b/proto-public/pbmesh/v2beta1/mesh_gateway_json.gen.go deleted file mode 100644 index 548da69f08cd..000000000000 --- a/proto-public/pbmesh/v2beta1/mesh_gateway_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for MeshGateway -func (this *MeshGateway) MarshalJSON() ([]byte, error) { - str, err := MeshGatewayMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for MeshGateway -func (this *MeshGateway) UnmarshalJSON(b []byte) error { - return MeshGatewayUnmarshaler.Unmarshal(b, this) -} - -var ( - MeshGatewayMarshaler = &protojson.MarshalOptions{} - MeshGatewayUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/access_logs.pb.binary.go b/proto-public/pbmesh/v2beta1/pbproxystate/access_logs.pb.binary.go deleted file mode 100644 index 1f08bf73b608..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/access_logs.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/pbproxystate/access_logs.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *AccessLogs) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *AccessLogs) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/access_logs.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/access_logs.pb.go deleted file mode 100644 index c1c30af893c6..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/access_logs.pb.go +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/access_logs.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=LOG_SINK_TYPE_DEFAULT;LOG_SINK_TYPE_FILE;LOG_SINK_TYPE_STDERR;LOG_SINK_TYPE_STDOUT -// +kubebuilder:validation:Type=string -type LogSinkType int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - LogSinkType_LOG_SINK_TYPE_DEFAULT LogSinkType = 0 - LogSinkType_LOG_SINK_TYPE_FILE LogSinkType = 1 - LogSinkType_LOG_SINK_TYPE_STDERR LogSinkType = 2 - LogSinkType_LOG_SINK_TYPE_STDOUT LogSinkType = 3 -) - -// Enum value maps for LogSinkType. -var ( - LogSinkType_name = map[int32]string{ - 0: "LOG_SINK_TYPE_DEFAULT", - 1: "LOG_SINK_TYPE_FILE", - 2: "LOG_SINK_TYPE_STDERR", - 3: "LOG_SINK_TYPE_STDOUT", - } - LogSinkType_value = map[string]int32{ - "LOG_SINK_TYPE_DEFAULT": 0, - "LOG_SINK_TYPE_FILE": 1, - "LOG_SINK_TYPE_STDERR": 2, - "LOG_SINK_TYPE_STDOUT": 3, - } -) - -func (x LogSinkType) Enum() *LogSinkType { - p := new(LogSinkType) - *p = x - return p -} - -func (x LogSinkType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (LogSinkType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_pbproxystate_access_logs_proto_enumTypes[0].Descriptor() -} - -func (LogSinkType) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_pbproxystate_access_logs_proto_enumTypes[0] -} - -func (x LogSinkType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use LogSinkType.Descriptor instead. -func (LogSinkType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDescGZIP(), []int{0} -} - -type AccessLogs struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // enabled enables access logging. - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - // disable_listener_logs turns off just listener logs for connections rejected by Envoy because they don't - // have a matching listener filter. - DisableListenerLogs bool `protobuf:"varint,2,opt,name=disable_listener_logs,json=disableListenerLogs,proto3" json:"disable_listener_logs,omitempty"` - // type selects the output for logs: "file", "stderr". "stdout" - Type LogSinkType `protobuf:"varint,3,opt,name=type,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.LogSinkType" json:"type,omitempty"` - // path is the output file to write logs - Path string `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"` - // The presence of one format string or the other implies the access log string encoding. - // Defining both is invalid. - // - // Types that are assignable to Format: - // - // *AccessLogs_Json - // *AccessLogs_Text - Format isAccessLogs_Format `protobuf_oneof:"format"` -} - -func (x *AccessLogs) Reset() { - *x = AccessLogs{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_access_logs_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AccessLogs) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AccessLogs) ProtoMessage() {} - -func (x *AccessLogs) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_access_logs_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AccessLogs.ProtoReflect.Descriptor instead. -func (*AccessLogs) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDescGZIP(), []int{0} -} - -func (x *AccessLogs) GetEnabled() bool { - if x != nil { - return x.Enabled - } - return false -} - -func (x *AccessLogs) GetDisableListenerLogs() bool { - if x != nil { - return x.DisableListenerLogs - } - return false -} - -func (x *AccessLogs) GetType() LogSinkType { - if x != nil { - return x.Type - } - return LogSinkType_LOG_SINK_TYPE_DEFAULT -} - -func (x *AccessLogs) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (m *AccessLogs) GetFormat() isAccessLogs_Format { - if m != nil { - return m.Format - } - return nil -} - -func (x *AccessLogs) GetJson() string { - if x, ok := x.GetFormat().(*AccessLogs_Json); ok { - return x.Json - } - return "" -} - -func (x *AccessLogs) GetText() string { - if x, ok := x.GetFormat().(*AccessLogs_Text); ok { - return x.Text - } - return "" -} - -type isAccessLogs_Format interface { - isAccessLogs_Format() -} - -type AccessLogs_Json struct { - Json string `protobuf:"bytes,5,opt,name=json,proto3,oneof"` -} - -type AccessLogs_Text struct { - Text string `protobuf:"bytes,6,opt,name=text,proto3,oneof"` -} - -func (*AccessLogs_Json) isAccessLogs_Format() {} - -func (*AccessLogs_Text) isAccessLogs_Format() {} - -var File_pbmesh_v2beta1_pbproxystate_access_logs_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDesc = []byte{ - 0x0a, 0x2d, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x2a, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0xf1, 0x01, 0x0a, 0x0a, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, - 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x53, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x04, 0x6a, 0x73, 0x6f, - 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x12, - 0x14, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, - 0x04, 0x74, 0x65, 0x78, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2a, - 0x74, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x53, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, - 0x0a, 0x15, 0x4c, 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x4f, 0x47, - 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, - 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4c, 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x53, 0x54, 0x44, 0x45, 0x52, 0x52, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x4c, - 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x44, - 0x4f, 0x55, 0x54, 0x10, 0x03, 0x42, 0xd5, 0x02, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0f, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x4c, 0x6f, 0x67, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, - 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0xe2, 0x02, 0x36, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2e, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3a, - 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_access_logs_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v2beta1_pbproxystate_access_logs_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmesh_v2beta1_pbproxystate_access_logs_proto_goTypes = []interface{}{ - (LogSinkType)(0), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.LogSinkType - (*AccessLogs)(nil), // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.AccessLogs -} -var file_pbmesh_v2beta1_pbproxystate_access_logs_proto_depIdxs = []int32{ - 0, // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.AccessLogs.type:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.LogSinkType - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_access_logs_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_access_logs_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_access_logs_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_pbproxystate_access_logs_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AccessLogs); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v2beta1_pbproxystate_access_logs_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*AccessLogs_Json)(nil), - (*AccessLogs_Text)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDesc, - NumEnums: 1, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_access_logs_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_access_logs_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_pbproxystate_access_logs_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_pbproxystate_access_logs_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_access_logs_proto = out.File - file_pbmesh_v2beta1_pbproxystate_access_logs_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_access_logs_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_access_logs_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/access_logs.proto b/proto-public/pbmesh/v2beta1/pbproxystate/access_logs.proto deleted file mode 100644 index 92249a80b2ff..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/access_logs.proto +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1.pbproxystate; - -message AccessLogs { - // enabled enables access logging. - bool enabled = 1; - // disable_listener_logs turns off just listener logs for connections rejected by Envoy because they don't - // have a matching listener filter. - bool disable_listener_logs = 2; - // type selects the output for logs: "file", "stderr". "stdout" - LogSinkType type = 3; - // path is the output file to write logs - string path = 4; - // The presence of one format string or the other implies the access log string encoding. - // Defining both is invalid. - oneof format { - string json = 5; - string text = 6; - } -} - -// +kubebuilder:validation:Enum=LOG_SINK_TYPE_DEFAULT;LOG_SINK_TYPE_FILE;LOG_SINK_TYPE_STDERR;LOG_SINK_TYPE_STDOUT -// +kubebuilder:validation:Type=string -enum LogSinkType { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - LOG_SINK_TYPE_DEFAULT = 0; - LOG_SINK_TYPE_FILE = 1; - LOG_SINK_TYPE_STDERR = 2; - LOG_SINK_TYPE_STDOUT = 3; -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/access_logs_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/access_logs_deepcopy.gen.go deleted file mode 100644 index f4c5c96039d5..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/access_logs_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package pbproxystate - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using AccessLogs within kubernetes types, where deepcopy-gen is used. -func (in *AccessLogs) DeepCopyInto(out *AccessLogs) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AccessLogs. Required by controller-gen. -func (in *AccessLogs) DeepCopy() *AccessLogs { - if in == nil { - return nil - } - out := new(AccessLogs) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new AccessLogs. Required by controller-gen. -func (in *AccessLogs) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/access_logs_json.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/access_logs_json.gen.go deleted file mode 100644 index 09e5ffb28473..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/access_logs_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package pbproxystate - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for AccessLogs -func (this *AccessLogs) MarshalJSON() ([]byte, error) { - str, err := AccessLogsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for AccessLogs -func (this *AccessLogs) UnmarshalJSON(b []byte) error { - return AccessLogsUnmarshaler.Unmarshal(b, this) -} - -var ( - AccessLogsMarshaler = &protojson.MarshalOptions{} - AccessLogsUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/address.pb.binary.go b/proto-public/pbmesh/v2beta1/pbproxystate/address.pb.binary.go deleted file mode 100644 index 4b509e9ed98c..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/address.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/pbproxystate/address.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HostPortAddress) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HostPortAddress) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *UnixSocketAddress) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *UnixSocketAddress) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/address.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/address.pb.go deleted file mode 100644 index 6c814f3c8f2d..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/address.pb.go +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/address.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type HostPortAddress struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` - Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` -} - -func (x *HostPortAddress) Reset() { - *x = HostPortAddress{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_address_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HostPortAddress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HostPortAddress) ProtoMessage() {} - -func (x *HostPortAddress) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_address_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HostPortAddress.ProtoReflect.Descriptor instead. -func (*HostPortAddress) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_address_proto_rawDescGZIP(), []int{0} -} - -func (x *HostPortAddress) GetHost() string { - if x != nil { - return x.Host - } - return "" -} - -func (x *HostPortAddress) GetPort() uint32 { - if x != nil { - return x.Port - } - return 0 -} - -type UnixSocketAddress struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // path is the file system path at which to bind a Unix domain socket listener. - Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - // mode is the Unix file mode for the socket file. It should be provided - // in the numeric notation, for example, "0600". - Mode string `protobuf:"bytes,2,opt,name=mode,proto3" json:"mode,omitempty"` -} - -func (x *UnixSocketAddress) Reset() { - *x = UnixSocketAddress{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_address_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UnixSocketAddress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UnixSocketAddress) ProtoMessage() {} - -func (x *UnixSocketAddress) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_address_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UnixSocketAddress.ProtoReflect.Descriptor instead. -func (*UnixSocketAddress) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_address_proto_rawDescGZIP(), []int{1} -} - -func (x *UnixSocketAddress) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (x *UnixSocketAddress) GetMode() string { - if x != nil { - return x.Mode - } - return "" -} - -var File_pbmesh_v2beta1_pbproxystate_address_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_address_proto_rawDesc = []byte{ - 0x0a, 0x29, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x39, 0x0a, 0x0f, 0x48, 0x6f, 0x73, 0x74, 0x50, - 0x6f, 0x72, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, - 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, - 0x72, 0x74, 0x22, 0x3b, 0x0a, 0x11, 0x55, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, - 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x42, - 0xd2, 0x02, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x42, 0x0c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, - 0xaa, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2a, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x36, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, - 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0xea, 0x02, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, - 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_address_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_address_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_address_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_address_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_address_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_address_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_address_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_address_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_address_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbmesh_v2beta1_pbproxystate_address_proto_goTypes = []interface{}{ - (*HostPortAddress)(nil), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.HostPortAddress - (*UnixSocketAddress)(nil), // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.UnixSocketAddress -} -var file_pbmesh_v2beta1_pbproxystate_address_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_address_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_address_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_address_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_pbproxystate_address_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HostPortAddress); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_address_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnixSocketAddress); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_address_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_address_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_address_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_pbproxystate_address_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_address_proto = out.File - file_pbmesh_v2beta1_pbproxystate_address_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_address_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_address_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/address.proto b/proto-public/pbmesh/v2beta1/pbproxystate/address.proto deleted file mode 100644 index e13bdba9bb5a..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/address.proto +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1.pbproxystate; - -message HostPortAddress { - string host = 1; - uint32 port = 2; -} - -message UnixSocketAddress { - // path is the file system path at which to bind a Unix domain socket listener. - string path = 1; - - // mode is the Unix file mode for the socket file. It should be provided - // in the numeric notation, for example, "0600". - string mode = 2; -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/address_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/address_deepcopy.gen.go deleted file mode 100644 index b2700f704eff..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/address_deepcopy.gen.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package pbproxystate - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using HostPortAddress within kubernetes types, where deepcopy-gen is used. -func (in *HostPortAddress) DeepCopyInto(out *HostPortAddress) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPortAddress. Required by controller-gen. -func (in *HostPortAddress) DeepCopy() *HostPortAddress { - if in == nil { - return nil - } - out := new(HostPortAddress) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HostPortAddress. Required by controller-gen. -func (in *HostPortAddress) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using UnixSocketAddress within kubernetes types, where deepcopy-gen is used. -func (in *UnixSocketAddress) DeepCopyInto(out *UnixSocketAddress) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UnixSocketAddress. Required by controller-gen. -func (in *UnixSocketAddress) DeepCopy() *UnixSocketAddress { - if in == nil { - return nil - } - out := new(UnixSocketAddress) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new UnixSocketAddress. Required by controller-gen. -func (in *UnixSocketAddress) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/address_json.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/address_json.gen.go deleted file mode 100644 index c4de5d527048..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/address_json.gen.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package pbproxystate - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for HostPortAddress -func (this *HostPortAddress) MarshalJSON() ([]byte, error) { - str, err := AddressMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HostPortAddress -func (this *HostPortAddress) UnmarshalJSON(b []byte) error { - return AddressUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for UnixSocketAddress -func (this *UnixSocketAddress) MarshalJSON() ([]byte, error) { - str, err := AddressMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for UnixSocketAddress -func (this *UnixSocketAddress) UnmarshalJSON(b []byte) error { - return AddressUnmarshaler.Unmarshal(b, this) -} - -var ( - AddressMarshaler = &protojson.MarshalOptions{} - AddressUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/cluster.pb.binary.go b/proto-public/pbmesh/v2beta1/pbproxystate/cluster.pb.binary.go deleted file mode 100644 index eab6e1626c72..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/cluster.pb.binary.go +++ /dev/null @@ -1,268 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/pbproxystate/cluster.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Cluster) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Cluster) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *FailoverGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *FailoverGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *FailoverGroupConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *FailoverGroupConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *EndpointGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *EndpointGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DynamicEndpointGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DynamicEndpointGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *PassthroughEndpointGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *PassthroughEndpointGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DNSEndpointGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DNSEndpointGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *StaticEndpointGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *StaticEndpointGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationCluster) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationCluster) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L4WeightedClusterGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L4WeightedClusterGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L7WeightedClusterGroup) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L7WeightedClusterGroup) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L4WeightedDestinationCluster) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L4WeightedDestinationCluster) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L7WeightedDestinationCluster) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L7WeightedDestinationCluster) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DynamicEndpointGroupConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DynamicEndpointGroupConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LBPolicyLeastRequest) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LBPolicyLeastRequest) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LBPolicyRoundRobin) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LBPolicyRoundRobin) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LBPolicyRandom) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LBPolicyRandom) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LBPolicyRingHash) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LBPolicyRingHash) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LBPolicyMaglev) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LBPolicyMaglev) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *CircuitBreakers) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *CircuitBreakers) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *UpstreamLimits) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *UpstreamLimits) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *OutlierDetection) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *OutlierDetection) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *UpstreamConnectionOptions) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *UpstreamConnectionOptions) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *PassthroughEndpointGroupConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *PassthroughEndpointGroupConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DNSEndpointGroupConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DNSEndpointGroupConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *StaticEndpointGroupConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *StaticEndpointGroupConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/cluster.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/cluster.pb.go deleted file mode 100644 index ba7386f527e0..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/cluster.pb.go +++ /dev/null @@ -1,2643 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/cluster.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=DISCOVERY_TYPE_LOGICAL;DISCOVERY_TYPE_STRICT -// +kubebuilder:validation:Type=string -type DiscoveryType int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - DiscoveryType_DISCOVERY_TYPE_LOGICAL DiscoveryType = 0 - DiscoveryType_DISCOVERY_TYPE_STRICT DiscoveryType = 1 -) - -// Enum value maps for DiscoveryType. -var ( - DiscoveryType_name = map[int32]string{ - 0: "DISCOVERY_TYPE_LOGICAL", - 1: "DISCOVERY_TYPE_STRICT", - } - DiscoveryType_value = map[string]int32{ - "DISCOVERY_TYPE_LOGICAL": 0, - "DISCOVERY_TYPE_STRICT": 1, - } -) - -func (x DiscoveryType) Enum() *DiscoveryType { - p := new(DiscoveryType) - *p = x - return p -} - -func (x DiscoveryType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (DiscoveryType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_enumTypes[0].Descriptor() -} - -func (DiscoveryType) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_pbproxystate_cluster_proto_enumTypes[0] -} - -func (x DiscoveryType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use DiscoveryType.Descriptor instead. -func (DiscoveryType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{0} -} - -type Cluster struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is the name of the cluster. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // group is either a failover group or endpoint group. If this cluster needs to failover to other clusters, use the failover group. If this cluster routes directly to endpoints, use the endpoint group. - // - // Types that are assignable to Group: - // - // *Cluster_FailoverGroup - // *Cluster_EndpointGroup - Group isCluster_Group `protobuf_oneof:"group"` - // escape_hatch_cluster_json configures a user configured escape hatch cluster. - EscapeHatchClusterJson string `protobuf:"bytes,4,opt,name=escape_hatch_cluster_json,json=escapeHatchClusterJson,proto3" json:"escape_hatch_cluster_json,omitempty"` - // alt_stat_name is the name used for observability in place of cluster name if provided. - AltStatName string `protobuf:"bytes,5,opt,name=alt_stat_name,json=altStatName,proto3" json:"alt_stat_name,omitempty"` - // protocol is the local path protocol or the service protocol. - Protocol Protocol `protobuf:"varint,6,opt,name=protocol,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.Protocol" json:"protocol,omitempty"` -} - -func (x *Cluster) Reset() { - *x = Cluster{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Cluster) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Cluster) ProtoMessage() {} - -func (x *Cluster) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Cluster.ProtoReflect.Descriptor instead. -func (*Cluster) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{0} -} - -func (x *Cluster) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (m *Cluster) GetGroup() isCluster_Group { - if m != nil { - return m.Group - } - return nil -} - -func (x *Cluster) GetFailoverGroup() *FailoverGroup { - if x, ok := x.GetGroup().(*Cluster_FailoverGroup); ok { - return x.FailoverGroup - } - return nil -} - -func (x *Cluster) GetEndpointGroup() *EndpointGroup { - if x, ok := x.GetGroup().(*Cluster_EndpointGroup); ok { - return x.EndpointGroup - } - return nil -} - -func (x *Cluster) GetEscapeHatchClusterJson() string { - if x != nil { - return x.EscapeHatchClusterJson - } - return "" -} - -func (x *Cluster) GetAltStatName() string { - if x != nil { - return x.AltStatName - } - return "" -} - -func (x *Cluster) GetProtocol() Protocol { - if x != nil { - return x.Protocol - } - return Protocol_PROTOCOL_UNSPECIFIED -} - -type isCluster_Group interface { - isCluster_Group() -} - -type Cluster_FailoverGroup struct { - FailoverGroup *FailoverGroup `protobuf:"bytes,2,opt,name=failover_group,json=failoverGroup,proto3,oneof"` -} - -type Cluster_EndpointGroup struct { - EndpointGroup *EndpointGroup `protobuf:"bytes,3,opt,name=endpoint_group,json=endpointGroup,proto3,oneof"` -} - -func (*Cluster_FailoverGroup) isCluster_Group() {} - -func (*Cluster_EndpointGroup) isCluster_Group() {} - -type FailoverGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // endpoint_groups is an ordered list of which groups to failover to. - EndpointGroups []*EndpointGroup `protobuf:"bytes,1,rep,name=endpoint_groups,json=endpointGroups,proto3" json:"endpoint_groups,omitempty"` - Config *FailoverGroupConfig `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` -} - -func (x *FailoverGroup) Reset() { - *x = FailoverGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FailoverGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FailoverGroup) ProtoMessage() {} - -func (x *FailoverGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FailoverGroup.ProtoReflect.Descriptor instead. -func (*FailoverGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{1} -} - -func (x *FailoverGroup) GetEndpointGroups() []*EndpointGroup { - if x != nil { - return x.EndpointGroups - } - return nil -} - -func (x *FailoverGroup) GetConfig() *FailoverGroupConfig { - if x != nil { - return x.Config - } - return nil -} - -type FailoverGroupConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - UseAltStatName bool `protobuf:"varint,1,opt,name=use_alt_stat_name,json=useAltStatName,proto3" json:"use_alt_stat_name,omitempty"` - // +kubebuilder:validation:Type=string - ConnectTimeout *durationpb.Duration `protobuf:"bytes,2,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` -} - -func (x *FailoverGroupConfig) Reset() { - *x = FailoverGroupConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FailoverGroupConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FailoverGroupConfig) ProtoMessage() {} - -func (x *FailoverGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FailoverGroupConfig.ProtoReflect.Descriptor instead. -func (*FailoverGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{2} -} - -func (x *FailoverGroupConfig) GetUseAltStatName() bool { - if x != nil { - return x.UseAltStatName - } - return false -} - -func (x *FailoverGroupConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -type EndpointGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is used to name the cluster created. This is only required when used inside of a FailoverGroup. - Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` - // Types that are assignable to Group: - // - // *EndpointGroup_Dynamic - // *EndpointGroup_Static - // *EndpointGroup_Dns - // *EndpointGroup_Passthrough - Group isEndpointGroup_Group `protobuf_oneof:"group"` -} - -func (x *EndpointGroup) Reset() { - *x = EndpointGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EndpointGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EndpointGroup) ProtoMessage() {} - -func (x *EndpointGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EndpointGroup.ProtoReflect.Descriptor instead. -func (*EndpointGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{3} -} - -func (x *EndpointGroup) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (m *EndpointGroup) GetGroup() isEndpointGroup_Group { - if m != nil { - return m.Group - } - return nil -} - -func (x *EndpointGroup) GetDynamic() *DynamicEndpointGroup { - if x, ok := x.GetGroup().(*EndpointGroup_Dynamic); ok { - return x.Dynamic - } - return nil -} - -func (x *EndpointGroup) GetStatic() *StaticEndpointGroup { - if x, ok := x.GetGroup().(*EndpointGroup_Static); ok { - return x.Static - } - return nil -} - -func (x *EndpointGroup) GetDns() *DNSEndpointGroup { - if x, ok := x.GetGroup().(*EndpointGroup_Dns); ok { - return x.Dns - } - return nil -} - -func (x *EndpointGroup) GetPassthrough() *PassthroughEndpointGroup { - if x, ok := x.GetGroup().(*EndpointGroup_Passthrough); ok { - return x.Passthrough - } - return nil -} - -type isEndpointGroup_Group interface { - isEndpointGroup_Group() -} - -type EndpointGroup_Dynamic struct { - // dynamic endpoint group is used to reach mesh destinations that are dynamically configured from Consul's catalog. - Dynamic *DynamicEndpointGroup `protobuf:"bytes,1,opt,name=dynamic,proto3,oneof"` -} - -type EndpointGroup_Static struct { - // static endpoint group is used to reach local app ports. - Static *StaticEndpointGroup `protobuf:"bytes,2,opt,name=static,proto3,oneof"` -} - -type EndpointGroup_Dns struct { - // dns is used to reach mesh and non-mesh destinations using a hostname. - Dns *DNSEndpointGroup `protobuf:"bytes,3,opt,name=dns,proto3,oneof"` -} - -type EndpointGroup_Passthrough struct { - // passthrough is used to reach destinations that don't have endpoints saved in Consul. - Passthrough *PassthroughEndpointGroup `protobuf:"bytes,4,opt,name=passthrough,proto3,oneof"` -} - -func (*EndpointGroup_Dynamic) isEndpointGroup_Group() {} - -func (*EndpointGroup_Static) isEndpointGroup_Group() {} - -func (*EndpointGroup_Dns) isEndpointGroup_Group() {} - -func (*EndpointGroup_Passthrough) isEndpointGroup_Group() {} - -type DynamicEndpointGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // config configures how to connect to the endpoints. - Config *DynamicEndpointGroupConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - // outbound_tls will configure what TLS information to use when connecting to an upstream. - OutboundTls *TransportSocket `protobuf:"bytes,2,opt,name=outbound_tls,json=outboundTls,proto3" json:"outbound_tls,omitempty"` -} - -func (x *DynamicEndpointGroup) Reset() { - *x = DynamicEndpointGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DynamicEndpointGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DynamicEndpointGroup) ProtoMessage() {} - -func (x *DynamicEndpointGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DynamicEndpointGroup.ProtoReflect.Descriptor instead. -func (*DynamicEndpointGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{4} -} - -func (x *DynamicEndpointGroup) GetConfig() *DynamicEndpointGroupConfig { - if x != nil { - return x.Config - } - return nil -} - -func (x *DynamicEndpointGroup) GetOutboundTls() *TransportSocket { - if x != nil { - return x.OutboundTls - } - return nil -} - -type PassthroughEndpointGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // config configures how to connect to the endpoints. - Config *PassthroughEndpointGroupConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - // outbound_tls will configure what TLS information to use when connecting to an upstream. - OutboundTls *TransportSocket `protobuf:"bytes,2,opt,name=outbound_tls,json=outboundTls,proto3" json:"outbound_tls,omitempty"` -} - -func (x *PassthroughEndpointGroup) Reset() { - *x = PassthroughEndpointGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PassthroughEndpointGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PassthroughEndpointGroup) ProtoMessage() {} - -func (x *PassthroughEndpointGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PassthroughEndpointGroup.ProtoReflect.Descriptor instead. -func (*PassthroughEndpointGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{5} -} - -func (x *PassthroughEndpointGroup) GetConfig() *PassthroughEndpointGroupConfig { - if x != nil { - return x.Config - } - return nil -} - -func (x *PassthroughEndpointGroup) GetOutboundTls() *TransportSocket { - if x != nil { - return x.OutboundTls - } - return nil -} - -type DNSEndpointGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // config configures how to connect to the endpoints. - Config *DNSEndpointGroupConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - // outbound_tls will configure what TLS information to use when connecting to an upstream. - OutboundTls *TransportSocket `protobuf:"bytes,2,opt,name=outbound_tls,json=outboundTls,proto3" json:"outbound_tls,omitempty"` -} - -func (x *DNSEndpointGroup) Reset() { - *x = DNSEndpointGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DNSEndpointGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DNSEndpointGroup) ProtoMessage() {} - -func (x *DNSEndpointGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DNSEndpointGroup.ProtoReflect.Descriptor instead. -func (*DNSEndpointGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{6} -} - -func (x *DNSEndpointGroup) GetConfig() *DNSEndpointGroupConfig { - if x != nil { - return x.Config - } - return nil -} - -func (x *DNSEndpointGroup) GetOutboundTls() *TransportSocket { - if x != nil { - return x.OutboundTls - } - return nil -} - -// StaticEndpointGroup is used to reach local app ports. -type StaticEndpointGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // config configures how to connect to the endpoints. - Config *StaticEndpointGroupConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` -} - -func (x *StaticEndpointGroup) Reset() { - *x = StaticEndpointGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StaticEndpointGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StaticEndpointGroup) ProtoMessage() {} - -func (x *StaticEndpointGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StaticEndpointGroup.ProtoReflect.Descriptor instead. -func (*StaticEndpointGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{7} -} - -func (x *StaticEndpointGroup) GetConfig() *StaticEndpointGroupConfig { - if x != nil { - return x.Config - } - return nil -} - -type DestinationCluster struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *DestinationCluster) Reset() { - *x = DestinationCluster{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationCluster) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationCluster) ProtoMessage() {} - -func (x *DestinationCluster) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DestinationCluster.ProtoReflect.Descriptor instead. -func (*DestinationCluster) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{8} -} - -func (x *DestinationCluster) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -type L4WeightedClusterGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // clusters to route to by weight. - Clusters []*L4WeightedDestinationCluster `protobuf:"bytes,1,rep,name=clusters,proto3" json:"clusters,omitempty"` -} - -func (x *L4WeightedClusterGroup) Reset() { - *x = L4WeightedClusterGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L4WeightedClusterGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L4WeightedClusterGroup) ProtoMessage() {} - -func (x *L4WeightedClusterGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use L4WeightedClusterGroup.ProtoReflect.Descriptor instead. -func (*L4WeightedClusterGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{9} -} - -func (x *L4WeightedClusterGroup) GetClusters() []*L4WeightedDestinationCluster { - if x != nil { - return x.Clusters - } - return nil -} - -type L7WeightedClusterGroup struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // clusters to route to by weight. - Clusters []*L7WeightedDestinationCluster `protobuf:"bytes,1,rep,name=clusters,proto3" json:"clusters,omitempty"` -} - -func (x *L7WeightedClusterGroup) Reset() { - *x = L7WeightedClusterGroup{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L7WeightedClusterGroup) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L7WeightedClusterGroup) ProtoMessage() {} - -func (x *L7WeightedClusterGroup) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use L7WeightedClusterGroup.ProtoReflect.Descriptor instead. -func (*L7WeightedClusterGroup) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{10} -} - -func (x *L7WeightedClusterGroup) GetClusters() []*L7WeightedDestinationCluster { - if x != nil { - return x.Clusters - } - return nil -} - -type L4WeightedDestinationCluster struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Weight *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=weight,proto3" json:"weight,omitempty"` -} - -func (x *L4WeightedDestinationCluster) Reset() { - *x = L4WeightedDestinationCluster{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L4WeightedDestinationCluster) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L4WeightedDestinationCluster) ProtoMessage() {} - -func (x *L4WeightedDestinationCluster) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use L4WeightedDestinationCluster.ProtoReflect.Descriptor instead. -func (*L4WeightedDestinationCluster) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{11} -} - -func (x *L4WeightedDestinationCluster) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *L4WeightedDestinationCluster) GetWeight() *wrapperspb.UInt32Value { - if x != nil { - return x.Weight - } - return nil -} - -type L7WeightedDestinationCluster struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Weight *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=weight,proto3" json:"weight,omitempty"` - HeaderMutations []*HeaderMutation `protobuf:"bytes,3,rep,name=header_mutations,json=headerMutations,proto3" json:"header_mutations,omitempty"` -} - -func (x *L7WeightedDestinationCluster) Reset() { - *x = L7WeightedDestinationCluster{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L7WeightedDestinationCluster) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L7WeightedDestinationCluster) ProtoMessage() {} - -func (x *L7WeightedDestinationCluster) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use L7WeightedDestinationCluster.ProtoReflect.Descriptor instead. -func (*L7WeightedDestinationCluster) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{12} -} - -func (x *L7WeightedDestinationCluster) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *L7WeightedDestinationCluster) GetWeight() *wrapperspb.UInt32Value { - if x != nil { - return x.Weight - } - return nil -} - -func (x *L7WeightedDestinationCluster) GetHeaderMutations() []*HeaderMutation { - if x != nil { - return x.HeaderMutations - } - return nil -} - -type DynamicEndpointGroupConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // +kubebuilder:validation:Format=duration - ConnectTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` - DisablePanicThreshold bool `protobuf:"varint,2,opt,name=disable_panic_threshold,json=disablePanicThreshold,proto3" json:"disable_panic_threshold,omitempty"` - // Types that are assignable to LbPolicy: - // - // *DynamicEndpointGroupConfig_LeastRequest - // *DynamicEndpointGroupConfig_RoundRobin - // *DynamicEndpointGroupConfig_Random - // *DynamicEndpointGroupConfig_RingHash - // *DynamicEndpointGroupConfig_Maglev - LbPolicy isDynamicEndpointGroupConfig_LbPolicy `protobuf_oneof:"lb_policy"` - CircuitBreakers *CircuitBreakers `protobuf:"bytes,8,opt,name=circuit_breakers,json=circuitBreakers,proto3" json:"circuit_breakers,omitempty"` - OutlierDetection *OutlierDetection `protobuf:"bytes,9,opt,name=outlier_detection,json=outlierDetection,proto3" json:"outlier_detection,omitempty"` - UpstreamConnectionOptions *UpstreamConnectionOptions `protobuf:"bytes,10,opt,name=upstream_connection_options,json=upstreamConnectionOptions,proto3" json:"upstream_connection_options,omitempty"` - UseAltStatName bool `protobuf:"varint,11,opt,name=use_alt_stat_name,json=useAltStatName,proto3" json:"use_alt_stat_name,omitempty"` -} - -func (x *DynamicEndpointGroupConfig) Reset() { - *x = DynamicEndpointGroupConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DynamicEndpointGroupConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DynamicEndpointGroupConfig) ProtoMessage() {} - -func (x *DynamicEndpointGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DynamicEndpointGroupConfig.ProtoReflect.Descriptor instead. -func (*DynamicEndpointGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{13} -} - -func (x *DynamicEndpointGroupConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetDisablePanicThreshold() bool { - if x != nil { - return x.DisablePanicThreshold - } - return false -} - -func (m *DynamicEndpointGroupConfig) GetLbPolicy() isDynamicEndpointGroupConfig_LbPolicy { - if m != nil { - return m.LbPolicy - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetLeastRequest() *LBPolicyLeastRequest { - if x, ok := x.GetLbPolicy().(*DynamicEndpointGroupConfig_LeastRequest); ok { - return x.LeastRequest - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetRoundRobin() *LBPolicyRoundRobin { - if x, ok := x.GetLbPolicy().(*DynamicEndpointGroupConfig_RoundRobin); ok { - return x.RoundRobin - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetRandom() *LBPolicyRandom { - if x, ok := x.GetLbPolicy().(*DynamicEndpointGroupConfig_Random); ok { - return x.Random - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetRingHash() *LBPolicyRingHash { - if x, ok := x.GetLbPolicy().(*DynamicEndpointGroupConfig_RingHash); ok { - return x.RingHash - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetMaglev() *LBPolicyMaglev { - if x, ok := x.GetLbPolicy().(*DynamicEndpointGroupConfig_Maglev); ok { - return x.Maglev - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetCircuitBreakers() *CircuitBreakers { - if x != nil { - return x.CircuitBreakers - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetOutlierDetection() *OutlierDetection { - if x != nil { - return x.OutlierDetection - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetUpstreamConnectionOptions() *UpstreamConnectionOptions { - if x != nil { - return x.UpstreamConnectionOptions - } - return nil -} - -func (x *DynamicEndpointGroupConfig) GetUseAltStatName() bool { - if x != nil { - return x.UseAltStatName - } - return false -} - -type isDynamicEndpointGroupConfig_LbPolicy interface { - isDynamicEndpointGroupConfig_LbPolicy() -} - -type DynamicEndpointGroupConfig_LeastRequest struct { - LeastRequest *LBPolicyLeastRequest `protobuf:"bytes,3,opt,name=least_request,json=leastRequest,proto3,oneof"` -} - -type DynamicEndpointGroupConfig_RoundRobin struct { - RoundRobin *LBPolicyRoundRobin `protobuf:"bytes,4,opt,name=round_robin,json=roundRobin,proto3,oneof"` -} - -type DynamicEndpointGroupConfig_Random struct { - Random *LBPolicyRandom `protobuf:"bytes,5,opt,name=random,proto3,oneof"` -} - -type DynamicEndpointGroupConfig_RingHash struct { - RingHash *LBPolicyRingHash `protobuf:"bytes,6,opt,name=ring_hash,json=ringHash,proto3,oneof"` -} - -type DynamicEndpointGroupConfig_Maglev struct { - Maglev *LBPolicyMaglev `protobuf:"bytes,7,opt,name=maglev,proto3,oneof"` -} - -func (*DynamicEndpointGroupConfig_LeastRequest) isDynamicEndpointGroupConfig_LbPolicy() {} - -func (*DynamicEndpointGroupConfig_RoundRobin) isDynamicEndpointGroupConfig_LbPolicy() {} - -func (*DynamicEndpointGroupConfig_Random) isDynamicEndpointGroupConfig_LbPolicy() {} - -func (*DynamicEndpointGroupConfig_RingHash) isDynamicEndpointGroupConfig_LbPolicy() {} - -func (*DynamicEndpointGroupConfig_Maglev) isDynamicEndpointGroupConfig_LbPolicy() {} - -type LBPolicyLeastRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ChoiceCount *wrapperspb.UInt32Value `protobuf:"bytes,1,opt,name=choice_count,json=choiceCount,proto3" json:"choice_count,omitempty"` -} - -func (x *LBPolicyLeastRequest) Reset() { - *x = LBPolicyLeastRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LBPolicyLeastRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LBPolicyLeastRequest) ProtoMessage() {} - -func (x *LBPolicyLeastRequest) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LBPolicyLeastRequest.ProtoReflect.Descriptor instead. -func (*LBPolicyLeastRequest) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{14} -} - -func (x *LBPolicyLeastRequest) GetChoiceCount() *wrapperspb.UInt32Value { - if x != nil { - return x.ChoiceCount - } - return nil -} - -type LBPolicyRoundRobin struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *LBPolicyRoundRobin) Reset() { - *x = LBPolicyRoundRobin{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LBPolicyRoundRobin) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LBPolicyRoundRobin) ProtoMessage() {} - -func (x *LBPolicyRoundRobin) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LBPolicyRoundRobin.ProtoReflect.Descriptor instead. -func (*LBPolicyRoundRobin) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{15} -} - -type LBPolicyRandom struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *LBPolicyRandom) Reset() { - *x = LBPolicyRandom{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LBPolicyRandom) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LBPolicyRandom) ProtoMessage() {} - -func (x *LBPolicyRandom) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LBPolicyRandom.ProtoReflect.Descriptor instead. -func (*LBPolicyRandom) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{16} -} - -type LBPolicyRingHash struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MinimumRingSize *wrapperspb.UInt64Value `protobuf:"bytes,1,opt,name=minimum_ring_size,json=minimumRingSize,proto3" json:"minimum_ring_size,omitempty"` - MaximumRingSize *wrapperspb.UInt64Value `protobuf:"bytes,2,opt,name=maximum_ring_size,json=maximumRingSize,proto3" json:"maximum_ring_size,omitempty"` -} - -func (x *LBPolicyRingHash) Reset() { - *x = LBPolicyRingHash{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LBPolicyRingHash) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LBPolicyRingHash) ProtoMessage() {} - -func (x *LBPolicyRingHash) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LBPolicyRingHash.ProtoReflect.Descriptor instead. -func (*LBPolicyRingHash) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{17} -} - -func (x *LBPolicyRingHash) GetMinimumRingSize() *wrapperspb.UInt64Value { - if x != nil { - return x.MinimumRingSize - } - return nil -} - -func (x *LBPolicyRingHash) GetMaximumRingSize() *wrapperspb.UInt64Value { - if x != nil { - return x.MaximumRingSize - } - return nil -} - -type LBPolicyMaglev struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *LBPolicyMaglev) Reset() { - *x = LBPolicyMaglev{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LBPolicyMaglev) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LBPolicyMaglev) ProtoMessage() {} - -func (x *LBPolicyMaglev) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LBPolicyMaglev.ProtoReflect.Descriptor instead. -func (*LBPolicyMaglev) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{18} -} - -type CircuitBreakers struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - UpstreamLimits *UpstreamLimits `protobuf:"bytes,1,opt,name=upstream_limits,json=upstreamLimits,proto3" json:"upstream_limits,omitempty"` -} - -func (x *CircuitBreakers) Reset() { - *x = CircuitBreakers{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CircuitBreakers) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CircuitBreakers) ProtoMessage() {} - -func (x *CircuitBreakers) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CircuitBreakers.ProtoReflect.Descriptor instead. -func (*CircuitBreakers) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{19} -} - -func (x *CircuitBreakers) GetUpstreamLimits() *UpstreamLimits { - if x != nil { - return x.UpstreamLimits - } - return nil -} - -type UpstreamLimits struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MaxConnections *wrapperspb.UInt32Value `protobuf:"bytes,1,opt,name=max_connections,json=maxConnections,proto3" json:"max_connections,omitempty"` - MaxPendingRequests *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=max_pending_requests,json=maxPendingRequests,proto3" json:"max_pending_requests,omitempty"` - MaxConcurrentRequests *wrapperspb.UInt32Value `protobuf:"bytes,3,opt,name=max_concurrent_requests,json=maxConcurrentRequests,proto3" json:"max_concurrent_requests,omitempty"` -} - -func (x *UpstreamLimits) Reset() { - *x = UpstreamLimits{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpstreamLimits) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpstreamLimits) ProtoMessage() {} - -func (x *UpstreamLimits) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpstreamLimits.ProtoReflect.Descriptor instead. -func (*UpstreamLimits) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{20} -} - -func (x *UpstreamLimits) GetMaxConnections() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxConnections - } - return nil -} - -func (x *UpstreamLimits) GetMaxPendingRequests() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxPendingRequests - } - return nil -} - -func (x *UpstreamLimits) GetMaxConcurrentRequests() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxConcurrentRequests - } - return nil -} - -type OutlierDetection struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // +kubebuilder:validation:Format=duration - Interval *durationpb.Duration `protobuf:"bytes,1,opt,name=interval,proto3" json:"interval,omitempty"` - Consecutive_5Xx *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=consecutive_5xx,json=consecutive5xx,proto3" json:"consecutive_5xx,omitempty"` - EnforcingConsecutive_5Xx *wrapperspb.UInt32Value `protobuf:"bytes,3,opt,name=enforcing_consecutive_5xx,json=enforcingConsecutive5xx,proto3" json:"enforcing_consecutive_5xx,omitempty"` - MaxEjectionPercent *wrapperspb.UInt32Value `protobuf:"bytes,4,opt,name=max_ejection_percent,json=maxEjectionPercent,proto3" json:"max_ejection_percent,omitempty"` - // +kubebuilder:validation:Format=duration - BaseEjectionTime *durationpb.Duration `protobuf:"bytes,5,opt,name=base_ejection_time,json=baseEjectionTime,proto3" json:"base_ejection_time,omitempty"` -} - -func (x *OutlierDetection) Reset() { - *x = OutlierDetection{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OutlierDetection) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OutlierDetection) ProtoMessage() {} - -func (x *OutlierDetection) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OutlierDetection.ProtoReflect.Descriptor instead. -func (*OutlierDetection) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{21} -} - -func (x *OutlierDetection) GetInterval() *durationpb.Duration { - if x != nil { - return x.Interval - } - return nil -} - -func (x *OutlierDetection) GetConsecutive_5Xx() *wrapperspb.UInt32Value { - if x != nil { - return x.Consecutive_5Xx - } - return nil -} - -func (x *OutlierDetection) GetEnforcingConsecutive_5Xx() *wrapperspb.UInt32Value { - if x != nil { - return x.EnforcingConsecutive_5Xx - } - return nil -} - -func (x *OutlierDetection) GetMaxEjectionPercent() *wrapperspb.UInt32Value { - if x != nil { - return x.MaxEjectionPercent - } - return nil -} - -func (x *OutlierDetection) GetBaseEjectionTime() *durationpb.Duration { - if x != nil { - return x.BaseEjectionTime - } - return nil -} - -type UpstreamConnectionOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TcpKeepaliveTime *wrapperspb.UInt32Value `protobuf:"bytes,1,opt,name=tcp_keepalive_time,json=tcpKeepaliveTime,proto3" json:"tcp_keepalive_time,omitempty"` - TcpKeepaliveInterval *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=tcp_keepalive_interval,json=tcpKeepaliveInterval,proto3" json:"tcp_keepalive_interval,omitempty"` - TcpKeepaliveProbes *wrapperspb.UInt32Value `protobuf:"bytes,3,opt,name=tcp_keepalive_probes,json=tcpKeepaliveProbes,proto3" json:"tcp_keepalive_probes,omitempty"` -} - -func (x *UpstreamConnectionOptions) Reset() { - *x = UpstreamConnectionOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpstreamConnectionOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpstreamConnectionOptions) ProtoMessage() {} - -func (x *UpstreamConnectionOptions) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UpstreamConnectionOptions.ProtoReflect.Descriptor instead. -func (*UpstreamConnectionOptions) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{22} -} - -func (x *UpstreamConnectionOptions) GetTcpKeepaliveTime() *wrapperspb.UInt32Value { - if x != nil { - return x.TcpKeepaliveTime - } - return nil -} - -func (x *UpstreamConnectionOptions) GetTcpKeepaliveInterval() *wrapperspb.UInt32Value { - if x != nil { - return x.TcpKeepaliveInterval - } - return nil -} - -func (x *UpstreamConnectionOptions) GetTcpKeepaliveProbes() *wrapperspb.UInt32Value { - if x != nil { - return x.TcpKeepaliveProbes - } - return nil -} - -type PassthroughEndpointGroupConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // +kubebuilder:validation:Format=duration - ConnectTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` -} - -func (x *PassthroughEndpointGroupConfig) Reset() { - *x = PassthroughEndpointGroupConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PassthroughEndpointGroupConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PassthroughEndpointGroupConfig) ProtoMessage() {} - -func (x *PassthroughEndpointGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PassthroughEndpointGroupConfig.ProtoReflect.Descriptor instead. -func (*PassthroughEndpointGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{23} -} - -func (x *PassthroughEndpointGroupConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -type DNSEndpointGroupConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // +kubebuilder:validation:Format=duration - ConnectTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` - DisablePanicThreshold bool `protobuf:"varint,2,opt,name=disable_panic_threshold,json=disablePanicThreshold,proto3" json:"disable_panic_threshold,omitempty"` - DiscoveryType DiscoveryType `protobuf:"varint,3,opt,name=discovery_type,json=discoveryType,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.DiscoveryType" json:"discovery_type,omitempty"` - CircuitBreakers *CircuitBreakers `protobuf:"bytes,4,opt,name=circuit_breakers,json=circuitBreakers,proto3" json:"circuit_breakers,omitempty"` - OutlierDetection *OutlierDetection `protobuf:"bytes,5,opt,name=outlier_detection,json=outlierDetection,proto3" json:"outlier_detection,omitempty"` - UpstreamConnectionOptions *UpstreamConnectionOptions `protobuf:"bytes,6,opt,name=upstream_connection_options,json=upstreamConnectionOptions,proto3" json:"upstream_connection_options,omitempty"` - UseAltStatName bool `protobuf:"varint,7,opt,name=use_alt_stat_name,json=useAltStatName,proto3" json:"use_alt_stat_name,omitempty"` -} - -func (x *DNSEndpointGroupConfig) Reset() { - *x = DNSEndpointGroupConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DNSEndpointGroupConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DNSEndpointGroupConfig) ProtoMessage() {} - -func (x *DNSEndpointGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DNSEndpointGroupConfig.ProtoReflect.Descriptor instead. -func (*DNSEndpointGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{24} -} - -func (x *DNSEndpointGroupConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -func (x *DNSEndpointGroupConfig) GetDisablePanicThreshold() bool { - if x != nil { - return x.DisablePanicThreshold - } - return false -} - -func (x *DNSEndpointGroupConfig) GetDiscoveryType() DiscoveryType { - if x != nil { - return x.DiscoveryType - } - return DiscoveryType_DISCOVERY_TYPE_LOGICAL -} - -func (x *DNSEndpointGroupConfig) GetCircuitBreakers() *CircuitBreakers { - if x != nil { - return x.CircuitBreakers - } - return nil -} - -func (x *DNSEndpointGroupConfig) GetOutlierDetection() *OutlierDetection { - if x != nil { - return x.OutlierDetection - } - return nil -} - -func (x *DNSEndpointGroupConfig) GetUpstreamConnectionOptions() *UpstreamConnectionOptions { - if x != nil { - return x.UpstreamConnectionOptions - } - return nil -} - -func (x *DNSEndpointGroupConfig) GetUseAltStatName() bool { - if x != nil { - return x.UseAltStatName - } - return false -} - -type StaticEndpointGroupConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // +kubebuilder:validation:Format=duration - ConnectTimeout *durationpb.Duration `protobuf:"bytes,1,opt,name=connect_timeout,json=connectTimeout,proto3" json:"connect_timeout,omitempty"` - CircuitBreakers *CircuitBreakers `protobuf:"bytes,2,opt,name=circuit_breakers,json=circuitBreakers,proto3" json:"circuit_breakers,omitempty"` -} - -func (x *StaticEndpointGroupConfig) Reset() { - *x = StaticEndpointGroupConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StaticEndpointGroupConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StaticEndpointGroupConfig) ProtoMessage() {} - -func (x *StaticEndpointGroupConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StaticEndpointGroupConfig.ProtoReflect.Descriptor instead. -func (*StaticEndpointGroupConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP(), []int{25} -} - -func (x *StaticEndpointGroupConfig) GetConnectTimeout() *durationpb.Duration { - if x != nil { - return x.ConnectTimeout - } - return nil -} - -func (x *StaticEndpointGroupConfig) GetCircuitBreakers() *CircuitBreakers { - if x != nil { - return x.CircuitBreakers - } - return nil -} - -var File_pbmesh_v2beta1_pbproxystate_cluster_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDesc = []byte{ - 0x0a, 0x29, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x32, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x70, 0x62, 0x6d, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x32, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9f, 0x03, 0x0a, 0x07, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x62, 0x0a, 0x0e, 0x66, - 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, - 0x52, 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, - 0x62, 0x0a, 0x0e, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x48, 0x00, 0x52, 0x0d, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x12, 0x39, 0x0a, 0x19, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x68, 0x61, - 0x74, 0x63, 0x68, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, - 0x74, 0x63, 0x68, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x22, - 0x0a, 0x0d, 0x61, 0x6c, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x50, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0xcc, 0x01, - 0x0a, 0x0d, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, - 0x62, 0x0a, 0x0f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x52, 0x0e, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x73, 0x12, 0x57, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x84, 0x01, 0x0a, - 0x13, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x74, 0x5f, - 0x73, 0x74, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0e, 0x75, 0x73, 0x65, 0x41, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x42, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x22, 0xa1, 0x03, 0x0a, 0x0d, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x5c, 0x0a, 0x07, 0x64, 0x79, 0x6e, - 0x61, 0x6d, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x45, - 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x07, - 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x12, 0x59, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x63, 0x12, 0x50, 0x0a, 0x03, 0x64, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x4e, 0x53, - 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, - 0x03, 0x64, 0x6e, 0x73, 0x12, 0x68, 0x0a, 0x0b, 0x70, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, - 0x75, 0x67, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, - 0x67, 0x68, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, - 0x00, 0x52, 0x0b, 0x70, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x42, 0x07, - 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0xd6, 0x01, 0x0a, 0x14, 0x44, 0x79, 0x6e, 0x61, - 0x6d, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x12, 0x5e, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x79, - 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x5e, 0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6c, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x6c, 0x73, - 0x22, 0xde, 0x01, 0x0a, 0x18, 0x50, 0x61, 0x73, 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, - 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x62, 0x0a, - 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4a, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x74, - 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x5e, 0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6c, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x6f, - 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x6c, - 0x73, 0x22, 0xce, 0x01, 0x0a, 0x10, 0x44, 0x4e, 0x53, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x5a, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x2e, 0x44, 0x4e, 0x53, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x5e, 0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, - 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, - 0x6c, 0x73, 0x22, 0x74, 0x0a, 0x13, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x5d, 0x0a, 0x06, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x28, 0x0a, 0x12, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x22, 0x7e, 0x0a, 0x16, 0x4c, 0x34, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x64, 0x0a, 0x08, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x48, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x34, 0x57, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x73, 0x22, 0x7e, 0x0a, 0x16, 0x4c, 0x37, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x64, 0x0a, 0x08, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x48, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x37, 0x57, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x73, 0x22, 0x68, 0x0a, 0x1c, 0x4c, 0x34, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, - 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0xcf, 0x01, 0x0a, - 0x1c, 0x4c, 0x37, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x34, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x65, 0x0a, 0x10, 0x68, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x80, - 0x08, 0x0a, 0x1a, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, - 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x6e, - 0x69, 0x63, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x6e, 0x69, 0x63, - 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x67, 0x0a, 0x0d, 0x6c, 0x65, 0x61, - 0x73, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x61, 0x0a, 0x0b, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x72, 0x6f, 0x62, 0x69, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x6f, 0x75, - 0x6e, 0x64, 0x52, 0x6f, 0x62, 0x69, 0x6e, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, - 0x52, 0x6f, 0x62, 0x69, 0x6e, 0x12, 0x54, 0x0a, 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x61, 0x6e, 0x64, 0x6f, - 0x6d, 0x48, 0x00, 0x52, 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x12, 0x5b, 0x0a, 0x09, 0x72, - 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x48, 0x00, 0x52, 0x08, - 0x72, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x12, 0x54, 0x0a, 0x06, 0x6d, 0x61, 0x67, 0x6c, - 0x65, 0x76, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4d, 0x61, - 0x67, 0x6c, 0x65, 0x76, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x12, 0x66, - 0x0a, 0x10, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, - 0x72, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, - 0x61, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, - 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x69, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x65, - 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4f, - 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x10, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x85, 0x01, 0x0a, 0x1b, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x19, - 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x11, 0x75, 0x73, 0x65, - 0x5f, 0x61, 0x6c, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x41, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, - 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x6c, 0x62, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x22, 0x57, 0x0a, 0x14, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x65, 0x61, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x0c, 0x63, 0x68, 0x6f, - 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0b, 0x63, - 0x68, 0x6f, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x14, 0x0a, 0x12, 0x4c, 0x42, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x62, 0x69, 0x6e, - 0x22, 0x10, 0x0a, 0x0e, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x61, 0x6e, 0x64, - 0x6f, 0x6d, 0x22, 0xa6, 0x01, 0x0a, 0x10, 0x4c, 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, - 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x12, 0x48, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x69, 0x6d, - 0x75, 0x6d, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, - 0x65, 0x12, 0x48, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x72, 0x69, 0x6e, - 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, - 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x69, - 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x10, 0x0a, 0x0e, 0x4c, - 0x42, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4d, 0x61, 0x67, 0x6c, 0x65, 0x76, 0x22, 0x76, 0x0a, - 0x0f, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, - 0x12, 0x63, 0x0a, 0x0f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x6c, 0x69, 0x6d, - 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, - 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x0e, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, - 0x69, 0x6d, 0x69, 0x74, 0x73, 0x22, 0xfd, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x4e, 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x6d, 0x61, 0x78, - 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, - 0x54, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x15, - 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0x83, 0x03, 0x0a, 0x10, 0x4f, 0x75, 0x74, 0x6c, 0x69, 0x65, - 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x08, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, - 0x6c, 0x12, 0x45, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, - 0x5f, 0x35, 0x78, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, - 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, 0x78, 0x12, 0x58, 0x0a, 0x19, 0x65, 0x6e, 0x66, 0x6f, - 0x72, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, - 0x65, 0x5f, 0x35, 0x78, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x17, 0x65, 0x6e, 0x66, 0x6f, 0x72, - 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, - 0x78, 0x78, 0x12, 0x4e, 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, - 0x6d, 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, - 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x12, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x65, 0x6a, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x62, 0x61, 0x73, 0x65, 0x45, - 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x8b, 0x02, 0x0a, 0x19, - 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4a, 0x0a, 0x12, 0x74, 0x63, 0x70, - 0x5f, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x10, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, - 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x52, 0x0a, 0x16, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65, 0x65, - 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x14, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, - 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x4e, 0x0a, 0x14, 0x74, 0x63, 0x70, - 0x5f, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x62, 0x65, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x12, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x61, 0x6c, - 0x69, 0x76, 0x65, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x1e, 0x50, 0x61, 0x73, - 0x73, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, - 0xfc, 0x04, 0x0a, 0x16, 0x44, 0x4e, 0x53, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x36, - 0x0a, 0x17, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x5f, - 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x54, 0x68, 0x72, - 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x60, 0x0a, 0x0e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x66, 0x0a, 0x10, 0x63, 0x69, 0x72, 0x63, - 0x75, 0x69, 0x74, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, - 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x52, - 0x0f, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, - 0x12, 0x69, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, - 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x6c, 0x69, - 0x65, 0x72, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x85, 0x01, 0x0a, 0x1b, - 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x45, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x55, - 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x19, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x74, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, - 0x75, 0x73, 0x65, 0x41, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xc7, - 0x01, 0x0a, 0x19, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0f, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x12, 0x66, 0x0a, 0x10, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x5f, 0x62, 0x72, 0x65, 0x61, - 0x6b, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x42, - 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, - 0x42, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x73, 0x2a, 0x46, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x44, 0x49, 0x53, - 0x43, 0x4f, 0x56, 0x45, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x4f, 0x47, 0x49, - 0x43, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, - 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x43, 0x54, 0x10, 0x01, - 0x42, 0xd2, 0x02, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x42, 0x0c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, - 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, - 0x50, 0xaa, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, - 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x36, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, - 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_cluster_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes = make([]protoimpl.MessageInfo, 26) -var file_pbmesh_v2beta1_pbproxystate_cluster_proto_goTypes = []interface{}{ - (DiscoveryType)(0), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.DiscoveryType - (*Cluster)(nil), // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.Cluster - (*FailoverGroup)(nil), // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.FailoverGroup - (*FailoverGroupConfig)(nil), // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.FailoverGroupConfig - (*EndpointGroup)(nil), // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.EndpointGroup - (*DynamicEndpointGroup)(nil), // 5: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroup - (*PassthroughEndpointGroup)(nil), // 6: hashicorp.consul.mesh.v2beta1.pbproxystate.PassthroughEndpointGroup - (*DNSEndpointGroup)(nil), // 7: hashicorp.consul.mesh.v2beta1.pbproxystate.DNSEndpointGroup - (*StaticEndpointGroup)(nil), // 8: hashicorp.consul.mesh.v2beta1.pbproxystate.StaticEndpointGroup - (*DestinationCluster)(nil), // 9: hashicorp.consul.mesh.v2beta1.pbproxystate.DestinationCluster - (*L4WeightedClusterGroup)(nil), // 10: hashicorp.consul.mesh.v2beta1.pbproxystate.L4WeightedClusterGroup - (*L7WeightedClusterGroup)(nil), // 11: hashicorp.consul.mesh.v2beta1.pbproxystate.L7WeightedClusterGroup - (*L4WeightedDestinationCluster)(nil), // 12: hashicorp.consul.mesh.v2beta1.pbproxystate.L4WeightedDestinationCluster - (*L7WeightedDestinationCluster)(nil), // 13: hashicorp.consul.mesh.v2beta1.pbproxystate.L7WeightedDestinationCluster - (*DynamicEndpointGroupConfig)(nil), // 14: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroupConfig - (*LBPolicyLeastRequest)(nil), // 15: hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyLeastRequest - (*LBPolicyRoundRobin)(nil), // 16: hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyRoundRobin - (*LBPolicyRandom)(nil), // 17: hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyRandom - (*LBPolicyRingHash)(nil), // 18: hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyRingHash - (*LBPolicyMaglev)(nil), // 19: hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyMaglev - (*CircuitBreakers)(nil), // 20: hashicorp.consul.mesh.v2beta1.pbproxystate.CircuitBreakers - (*UpstreamLimits)(nil), // 21: hashicorp.consul.mesh.v2beta1.pbproxystate.UpstreamLimits - (*OutlierDetection)(nil), // 22: hashicorp.consul.mesh.v2beta1.pbproxystate.OutlierDetection - (*UpstreamConnectionOptions)(nil), // 23: hashicorp.consul.mesh.v2beta1.pbproxystate.UpstreamConnectionOptions - (*PassthroughEndpointGroupConfig)(nil), // 24: hashicorp.consul.mesh.v2beta1.pbproxystate.PassthroughEndpointGroupConfig - (*DNSEndpointGroupConfig)(nil), // 25: hashicorp.consul.mesh.v2beta1.pbproxystate.DNSEndpointGroupConfig - (*StaticEndpointGroupConfig)(nil), // 26: hashicorp.consul.mesh.v2beta1.pbproxystate.StaticEndpointGroupConfig - (Protocol)(0), // 27: hashicorp.consul.mesh.v2beta1.pbproxystate.Protocol - (*durationpb.Duration)(nil), // 28: google.protobuf.Duration - (*TransportSocket)(nil), // 29: hashicorp.consul.mesh.v2beta1.pbproxystate.TransportSocket - (*wrapperspb.UInt32Value)(nil), // 30: google.protobuf.UInt32Value - (*HeaderMutation)(nil), // 31: hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderMutation - (*wrapperspb.UInt64Value)(nil), // 32: google.protobuf.UInt64Value -} -var file_pbmesh_v2beta1_pbproxystate_cluster_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.Cluster.failover_group:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.FailoverGroup - 4, // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.Cluster.endpoint_group:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.EndpointGroup - 27, // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.Cluster.protocol:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Protocol - 4, // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.FailoverGroup.endpoint_groups:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.EndpointGroup - 3, // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.FailoverGroup.config:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.FailoverGroupConfig - 28, // 5: hashicorp.consul.mesh.v2beta1.pbproxystate.FailoverGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 5, // 6: hashicorp.consul.mesh.v2beta1.pbproxystate.EndpointGroup.dynamic:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroup - 8, // 7: hashicorp.consul.mesh.v2beta1.pbproxystate.EndpointGroup.static:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.StaticEndpointGroup - 7, // 8: hashicorp.consul.mesh.v2beta1.pbproxystate.EndpointGroup.dns:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.DNSEndpointGroup - 6, // 9: hashicorp.consul.mesh.v2beta1.pbproxystate.EndpointGroup.passthrough:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.PassthroughEndpointGroup - 14, // 10: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroup.config:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroupConfig - 29, // 11: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroup.outbound_tls:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TransportSocket - 24, // 12: hashicorp.consul.mesh.v2beta1.pbproxystate.PassthroughEndpointGroup.config:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.PassthroughEndpointGroupConfig - 29, // 13: hashicorp.consul.mesh.v2beta1.pbproxystate.PassthroughEndpointGroup.outbound_tls:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TransportSocket - 25, // 14: hashicorp.consul.mesh.v2beta1.pbproxystate.DNSEndpointGroup.config:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.DNSEndpointGroupConfig - 29, // 15: hashicorp.consul.mesh.v2beta1.pbproxystate.DNSEndpointGroup.outbound_tls:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TransportSocket - 26, // 16: hashicorp.consul.mesh.v2beta1.pbproxystate.StaticEndpointGroup.config:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.StaticEndpointGroupConfig - 12, // 17: hashicorp.consul.mesh.v2beta1.pbproxystate.L4WeightedClusterGroup.clusters:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.L4WeightedDestinationCluster - 13, // 18: hashicorp.consul.mesh.v2beta1.pbproxystate.L7WeightedClusterGroup.clusters:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.L7WeightedDestinationCluster - 30, // 19: hashicorp.consul.mesh.v2beta1.pbproxystate.L4WeightedDestinationCluster.weight:type_name -> google.protobuf.UInt32Value - 30, // 20: hashicorp.consul.mesh.v2beta1.pbproxystate.L7WeightedDestinationCluster.weight:type_name -> google.protobuf.UInt32Value - 31, // 21: hashicorp.consul.mesh.v2beta1.pbproxystate.L7WeightedDestinationCluster.header_mutations:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderMutation - 28, // 22: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 15, // 23: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroupConfig.least_request:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyLeastRequest - 16, // 24: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroupConfig.round_robin:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyRoundRobin - 17, // 25: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroupConfig.random:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyRandom - 18, // 26: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroupConfig.ring_hash:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyRingHash - 19, // 27: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroupConfig.maglev:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyMaglev - 20, // 28: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroupConfig.circuit_breakers:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.CircuitBreakers - 22, // 29: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroupConfig.outlier_detection:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.OutlierDetection - 23, // 30: hashicorp.consul.mesh.v2beta1.pbproxystate.DynamicEndpointGroupConfig.upstream_connection_options:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.UpstreamConnectionOptions - 30, // 31: hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyLeastRequest.choice_count:type_name -> google.protobuf.UInt32Value - 32, // 32: hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyRingHash.minimum_ring_size:type_name -> google.protobuf.UInt64Value - 32, // 33: hashicorp.consul.mesh.v2beta1.pbproxystate.LBPolicyRingHash.maximum_ring_size:type_name -> google.protobuf.UInt64Value - 21, // 34: hashicorp.consul.mesh.v2beta1.pbproxystate.CircuitBreakers.upstream_limits:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.UpstreamLimits - 30, // 35: hashicorp.consul.mesh.v2beta1.pbproxystate.UpstreamLimits.max_connections:type_name -> google.protobuf.UInt32Value - 30, // 36: hashicorp.consul.mesh.v2beta1.pbproxystate.UpstreamLimits.max_pending_requests:type_name -> google.protobuf.UInt32Value - 30, // 37: hashicorp.consul.mesh.v2beta1.pbproxystate.UpstreamLimits.max_concurrent_requests:type_name -> google.protobuf.UInt32Value - 28, // 38: hashicorp.consul.mesh.v2beta1.pbproxystate.OutlierDetection.interval:type_name -> google.protobuf.Duration - 30, // 39: hashicorp.consul.mesh.v2beta1.pbproxystate.OutlierDetection.consecutive_5xx:type_name -> google.protobuf.UInt32Value - 30, // 40: hashicorp.consul.mesh.v2beta1.pbproxystate.OutlierDetection.enforcing_consecutive_5xx:type_name -> google.protobuf.UInt32Value - 30, // 41: hashicorp.consul.mesh.v2beta1.pbproxystate.OutlierDetection.max_ejection_percent:type_name -> google.protobuf.UInt32Value - 28, // 42: hashicorp.consul.mesh.v2beta1.pbproxystate.OutlierDetection.base_ejection_time:type_name -> google.protobuf.Duration - 30, // 43: hashicorp.consul.mesh.v2beta1.pbproxystate.UpstreamConnectionOptions.tcp_keepalive_time:type_name -> google.protobuf.UInt32Value - 30, // 44: hashicorp.consul.mesh.v2beta1.pbproxystate.UpstreamConnectionOptions.tcp_keepalive_interval:type_name -> google.protobuf.UInt32Value - 30, // 45: hashicorp.consul.mesh.v2beta1.pbproxystate.UpstreamConnectionOptions.tcp_keepalive_probes:type_name -> google.protobuf.UInt32Value - 28, // 46: hashicorp.consul.mesh.v2beta1.pbproxystate.PassthroughEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 28, // 47: hashicorp.consul.mesh.v2beta1.pbproxystate.DNSEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 0, // 48: hashicorp.consul.mesh.v2beta1.pbproxystate.DNSEndpointGroupConfig.discovery_type:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.DiscoveryType - 20, // 49: hashicorp.consul.mesh.v2beta1.pbproxystate.DNSEndpointGroupConfig.circuit_breakers:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.CircuitBreakers - 22, // 50: hashicorp.consul.mesh.v2beta1.pbproxystate.DNSEndpointGroupConfig.outlier_detection:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.OutlierDetection - 23, // 51: hashicorp.consul.mesh.v2beta1.pbproxystate.DNSEndpointGroupConfig.upstream_connection_options:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.UpstreamConnectionOptions - 28, // 52: hashicorp.consul.mesh.v2beta1.pbproxystate.StaticEndpointGroupConfig.connect_timeout:type_name -> google.protobuf.Duration - 20, // 53: hashicorp.consul.mesh.v2beta1.pbproxystate.StaticEndpointGroupConfig.circuit_breakers:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.CircuitBreakers - 54, // [54:54] is the sub-list for method output_type - 54, // [54:54] is the sub-list for method input_type - 54, // [54:54] is the sub-list for extension type_name - 54, // [54:54] is the sub-list for extension extendee - 0, // [0:54] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_cluster_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_cluster_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_cluster_proto != nil { - return - } - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_init() - file_pbmesh_v2beta1_pbproxystate_protocol_proto_init() - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Cluster); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FailoverGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FailoverGroupConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EndpointGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DynamicEndpointGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PassthroughEndpointGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DNSEndpointGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StaticEndpointGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationCluster); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L4WeightedClusterGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L7WeightedClusterGroup); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L4WeightedDestinationCluster); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L7WeightedDestinationCluster); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DynamicEndpointGroupConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyLeastRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyRoundRobin); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyRandom); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyRingHash); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LBPolicyMaglev); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CircuitBreakers); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamLimits); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OutlierDetection); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpstreamConnectionOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PassthroughEndpointGroupConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DNSEndpointGroupConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StaticEndpointGroupConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*Cluster_FailoverGroup)(nil), - (*Cluster_EndpointGroup)(nil), - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[3].OneofWrappers = []interface{}{ - (*EndpointGroup_Dynamic)(nil), - (*EndpointGroup_Static)(nil), - (*EndpointGroup_Dns)(nil), - (*EndpointGroup_Passthrough)(nil), - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes[13].OneofWrappers = []interface{}{ - (*DynamicEndpointGroupConfig_LeastRequest)(nil), - (*DynamicEndpointGroupConfig_RoundRobin)(nil), - (*DynamicEndpointGroupConfig_Random)(nil), - (*DynamicEndpointGroupConfig_RingHash)(nil), - (*DynamicEndpointGroupConfig_Maglev)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDesc, - NumEnums: 1, - NumMessages: 26, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_cluster_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_cluster_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_pbproxystate_cluster_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_pbproxystate_cluster_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_cluster_proto = out.File - file_pbmesh_v2beta1_pbproxystate_cluster_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_cluster_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_cluster_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/cluster.proto b/proto-public/pbmesh/v2beta1/pbproxystate/cluster.proto deleted file mode 100644 index a84a3755c99b..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/cluster.proto +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1.pbproxystate; - -import "google/protobuf/duration.proto"; -import "google/protobuf/wrappers.proto"; -import "pbmesh/v2beta1/pbproxystate/header_mutations.proto"; -import "pbmesh/v2beta1/pbproxystate/protocol.proto"; -import "pbmesh/v2beta1/pbproxystate/transport_socket.proto"; - -message Cluster { - // name is the name of the cluster. - string name = 1; - // group is either a failover group or endpoint group. If this cluster needs to failover to other clusters, use the failover group. If this cluster routes directly to endpoints, use the endpoint group. - oneof group { - FailoverGroup failover_group = 2; - EndpointGroup endpoint_group = 3; - } - // escape_hatch_cluster_json configures a user configured escape hatch cluster. - string escape_hatch_cluster_json = 4; - // alt_stat_name is the name used for observability in place of cluster name if provided. - string alt_stat_name = 5; - // protocol is the local path protocol or the service protocol. - Protocol protocol = 6; -} - -message FailoverGroup { - // endpoint_groups is an ordered list of which groups to failover to. - repeated EndpointGroup endpoint_groups = 1; - FailoverGroupConfig config = 2; -} - -message FailoverGroupConfig { - bool use_alt_stat_name = 1; - // +kubebuilder:validation:Type=string - google.protobuf.Duration connect_timeout = 2; -} - -message EndpointGroup { - // name is used to name the cluster created. This is only required when used inside of a FailoverGroup. - string name = 5; - oneof group { - // dynamic endpoint group is used to reach mesh destinations that are dynamically configured from Consul's catalog. - DynamicEndpointGroup dynamic = 1; - // static endpoint group is used to reach local app ports. - StaticEndpointGroup static = 2; - // dns is used to reach mesh and non-mesh destinations using a hostname. - DNSEndpointGroup dns = 3; - // passthrough is used to reach destinations that don't have endpoints saved in Consul. - PassthroughEndpointGroup passthrough = 4; - } -} - -message DynamicEndpointGroup { - // config configures how to connect to the endpoints. - DynamicEndpointGroupConfig config = 1; - // outbound_tls will configure what TLS information to use when connecting to an upstream. - TransportSocket outbound_tls = 2; -} - -message PassthroughEndpointGroup { - // config configures how to connect to the endpoints. - PassthroughEndpointGroupConfig config = 1; - // outbound_tls will configure what TLS information to use when connecting to an upstream. - TransportSocket outbound_tls = 2; -} - -message DNSEndpointGroup { - // config configures how to connect to the endpoints. - DNSEndpointGroupConfig config = 1; - // outbound_tls will configure what TLS information to use when connecting to an upstream. - TransportSocket outbound_tls = 2; -} - -// StaticEndpointGroup is used to reach local app ports. -message StaticEndpointGroup { - // config configures how to connect to the endpoints. - StaticEndpointGroupConfig config = 1; -} - -message DestinationCluster { - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - string name = 1; -} - -message L4WeightedClusterGroup { - // clusters to route to by weight. - repeated L4WeightedDestinationCluster clusters = 1; -} - -message L7WeightedClusterGroup { - // clusters to route to by weight. - repeated L7WeightedDestinationCluster clusters = 1; -} - -message L4WeightedDestinationCluster { - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - string name = 1; - google.protobuf.UInt32Value weight = 2; -} - -message L7WeightedDestinationCluster { - // name is the name of the cluster. This will be used to look up a cluster in the clusters map. - string name = 1; - google.protobuf.UInt32Value weight = 2; - repeated HeaderMutation header_mutations = 3; -} - -message DynamicEndpointGroupConfig { - // +kubebuilder:validation:Format=duration - google.protobuf.Duration connect_timeout = 1; - bool disable_panic_threshold = 2; - oneof lb_policy { - LBPolicyLeastRequest least_request = 3; - LBPolicyRoundRobin round_robin = 4; - LBPolicyRandom random = 5; - LBPolicyRingHash ring_hash = 6; - LBPolicyMaglev maglev = 7; - } - CircuitBreakers circuit_breakers = 8; - OutlierDetection outlier_detection = 9; - UpstreamConnectionOptions upstream_connection_options = 10; - bool use_alt_stat_name = 11; -} - -message LBPolicyLeastRequest { - google.protobuf.UInt32Value choice_count = 1; -} -message LBPolicyRoundRobin {} - -message LBPolicyRandom {} - -message LBPolicyRingHash { - google.protobuf.UInt64Value minimum_ring_size = 1; - google.protobuf.UInt64Value maximum_ring_size = 2; -} - -message LBPolicyMaglev {} - -message CircuitBreakers { - UpstreamLimits upstream_limits = 1; -} - -message UpstreamLimits { - google.protobuf.UInt32Value max_connections = 1; - google.protobuf.UInt32Value max_pending_requests = 2; - google.protobuf.UInt32Value max_concurrent_requests = 3; -} - -message OutlierDetection { - // +kubebuilder:validation:Format=duration - google.protobuf.Duration interval = 1; - google.protobuf.UInt32Value consecutive_5xx = 2; - google.protobuf.UInt32Value enforcing_consecutive_5xx = 3; - google.protobuf.UInt32Value max_ejection_percent = 4; - // +kubebuilder:validation:Format=duration - google.protobuf.Duration base_ejection_time = 5; -} - -message UpstreamConnectionOptions { - google.protobuf.UInt32Value tcp_keepalive_time = 1; - google.protobuf.UInt32Value tcp_keepalive_interval = 2; - google.protobuf.UInt32Value tcp_keepalive_probes = 3; -} - -message PassthroughEndpointGroupConfig { - // +kubebuilder:validation:Format=duration - google.protobuf.Duration connect_timeout = 1; -} - -message DNSEndpointGroupConfig { - // +kubebuilder:validation:Format=duration - google.protobuf.Duration connect_timeout = 1; - bool disable_panic_threshold = 2; - DiscoveryType discovery_type = 3; - CircuitBreakers circuit_breakers = 4; - OutlierDetection outlier_detection = 5; - UpstreamConnectionOptions upstream_connection_options = 6; - bool use_alt_stat_name = 7; -} - -// +kubebuilder:validation:Enum=DISCOVERY_TYPE_LOGICAL;DISCOVERY_TYPE_STRICT -// +kubebuilder:validation:Type=string -enum DiscoveryType { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - DISCOVERY_TYPE_LOGICAL = 0; - DISCOVERY_TYPE_STRICT = 1; -} - -message StaticEndpointGroupConfig { - // +kubebuilder:validation:Format=duration - google.protobuf.Duration connect_timeout = 1; - CircuitBreakers circuit_breakers = 2; -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/cluster_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/cluster_deepcopy.gen.go deleted file mode 100644 index 1818a349bd45..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/cluster_deepcopy.gen.go +++ /dev/null @@ -1,552 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package pbproxystate - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using Cluster within kubernetes types, where deepcopy-gen is used. -func (in *Cluster) DeepCopyInto(out *Cluster) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Cluster. Required by controller-gen. -func (in *Cluster) DeepCopy() *Cluster { - if in == nil { - return nil - } - out := new(Cluster) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Cluster. Required by controller-gen. -func (in *Cluster) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using FailoverGroup within kubernetes types, where deepcopy-gen is used. -func (in *FailoverGroup) DeepCopyInto(out *FailoverGroup) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FailoverGroup. Required by controller-gen. -func (in *FailoverGroup) DeepCopy() *FailoverGroup { - if in == nil { - return nil - } - out := new(FailoverGroup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new FailoverGroup. Required by controller-gen. -func (in *FailoverGroup) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using FailoverGroupConfig within kubernetes types, where deepcopy-gen is used. -func (in *FailoverGroupConfig) DeepCopyInto(out *FailoverGroupConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FailoverGroupConfig. Required by controller-gen. -func (in *FailoverGroupConfig) DeepCopy() *FailoverGroupConfig { - if in == nil { - return nil - } - out := new(FailoverGroupConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new FailoverGroupConfig. Required by controller-gen. -func (in *FailoverGroupConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using EndpointGroup within kubernetes types, where deepcopy-gen is used. -func (in *EndpointGroup) DeepCopyInto(out *EndpointGroup) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointGroup. Required by controller-gen. -func (in *EndpointGroup) DeepCopy() *EndpointGroup { - if in == nil { - return nil - } - out := new(EndpointGroup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new EndpointGroup. Required by controller-gen. -func (in *EndpointGroup) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DynamicEndpointGroup within kubernetes types, where deepcopy-gen is used. -func (in *DynamicEndpointGroup) DeepCopyInto(out *DynamicEndpointGroup) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DynamicEndpointGroup. Required by controller-gen. -func (in *DynamicEndpointGroup) DeepCopy() *DynamicEndpointGroup { - if in == nil { - return nil - } - out := new(DynamicEndpointGroup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DynamicEndpointGroup. Required by controller-gen. -func (in *DynamicEndpointGroup) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using PassthroughEndpointGroup within kubernetes types, where deepcopy-gen is used. -func (in *PassthroughEndpointGroup) DeepCopyInto(out *PassthroughEndpointGroup) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PassthroughEndpointGroup. Required by controller-gen. -func (in *PassthroughEndpointGroup) DeepCopy() *PassthroughEndpointGroup { - if in == nil { - return nil - } - out := new(PassthroughEndpointGroup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new PassthroughEndpointGroup. Required by controller-gen. -func (in *PassthroughEndpointGroup) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DNSEndpointGroup within kubernetes types, where deepcopy-gen is used. -func (in *DNSEndpointGroup) DeepCopyInto(out *DNSEndpointGroup) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpointGroup. Required by controller-gen. -func (in *DNSEndpointGroup) DeepCopy() *DNSEndpointGroup { - if in == nil { - return nil - } - out := new(DNSEndpointGroup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpointGroup. Required by controller-gen. -func (in *DNSEndpointGroup) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using StaticEndpointGroup within kubernetes types, where deepcopy-gen is used. -func (in *StaticEndpointGroup) DeepCopyInto(out *StaticEndpointGroup) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StaticEndpointGroup. Required by controller-gen. -func (in *StaticEndpointGroup) DeepCopy() *StaticEndpointGroup { - if in == nil { - return nil - } - out := new(StaticEndpointGroup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new StaticEndpointGroup. Required by controller-gen. -func (in *StaticEndpointGroup) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DestinationCluster within kubernetes types, where deepcopy-gen is used. -func (in *DestinationCluster) DeepCopyInto(out *DestinationCluster) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationCluster. Required by controller-gen. -func (in *DestinationCluster) DeepCopy() *DestinationCluster { - if in == nil { - return nil - } - out := new(DestinationCluster) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DestinationCluster. Required by controller-gen. -func (in *DestinationCluster) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using L4WeightedClusterGroup within kubernetes types, where deepcopy-gen is used. -func (in *L4WeightedClusterGroup) DeepCopyInto(out *L4WeightedClusterGroup) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new L4WeightedClusterGroup. Required by controller-gen. -func (in *L4WeightedClusterGroup) DeepCopy() *L4WeightedClusterGroup { - if in == nil { - return nil - } - out := new(L4WeightedClusterGroup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new L4WeightedClusterGroup. Required by controller-gen. -func (in *L4WeightedClusterGroup) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using L7WeightedClusterGroup within kubernetes types, where deepcopy-gen is used. -func (in *L7WeightedClusterGroup) DeepCopyInto(out *L7WeightedClusterGroup) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new L7WeightedClusterGroup. Required by controller-gen. -func (in *L7WeightedClusterGroup) DeepCopy() *L7WeightedClusterGroup { - if in == nil { - return nil - } - out := new(L7WeightedClusterGroup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new L7WeightedClusterGroup. Required by controller-gen. -func (in *L7WeightedClusterGroup) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using L4WeightedDestinationCluster within kubernetes types, where deepcopy-gen is used. -func (in *L4WeightedDestinationCluster) DeepCopyInto(out *L4WeightedDestinationCluster) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new L4WeightedDestinationCluster. Required by controller-gen. -func (in *L4WeightedDestinationCluster) DeepCopy() *L4WeightedDestinationCluster { - if in == nil { - return nil - } - out := new(L4WeightedDestinationCluster) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new L4WeightedDestinationCluster. Required by controller-gen. -func (in *L4WeightedDestinationCluster) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using L7WeightedDestinationCluster within kubernetes types, where deepcopy-gen is used. -func (in *L7WeightedDestinationCluster) DeepCopyInto(out *L7WeightedDestinationCluster) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new L7WeightedDestinationCluster. Required by controller-gen. -func (in *L7WeightedDestinationCluster) DeepCopy() *L7WeightedDestinationCluster { - if in == nil { - return nil - } - out := new(L7WeightedDestinationCluster) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new L7WeightedDestinationCluster. Required by controller-gen. -func (in *L7WeightedDestinationCluster) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DynamicEndpointGroupConfig within kubernetes types, where deepcopy-gen is used. -func (in *DynamicEndpointGroupConfig) DeepCopyInto(out *DynamicEndpointGroupConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DynamicEndpointGroupConfig. Required by controller-gen. -func (in *DynamicEndpointGroupConfig) DeepCopy() *DynamicEndpointGroupConfig { - if in == nil { - return nil - } - out := new(DynamicEndpointGroupConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DynamicEndpointGroupConfig. Required by controller-gen. -func (in *DynamicEndpointGroupConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using LBPolicyLeastRequest within kubernetes types, where deepcopy-gen is used. -func (in *LBPolicyLeastRequest) DeepCopyInto(out *LBPolicyLeastRequest) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LBPolicyLeastRequest. Required by controller-gen. -func (in *LBPolicyLeastRequest) DeepCopy() *LBPolicyLeastRequest { - if in == nil { - return nil - } - out := new(LBPolicyLeastRequest) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new LBPolicyLeastRequest. Required by controller-gen. -func (in *LBPolicyLeastRequest) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using LBPolicyRoundRobin within kubernetes types, where deepcopy-gen is used. -func (in *LBPolicyRoundRobin) DeepCopyInto(out *LBPolicyRoundRobin) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LBPolicyRoundRobin. Required by controller-gen. -func (in *LBPolicyRoundRobin) DeepCopy() *LBPolicyRoundRobin { - if in == nil { - return nil - } - out := new(LBPolicyRoundRobin) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new LBPolicyRoundRobin. Required by controller-gen. -func (in *LBPolicyRoundRobin) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using LBPolicyRandom within kubernetes types, where deepcopy-gen is used. -func (in *LBPolicyRandom) DeepCopyInto(out *LBPolicyRandom) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LBPolicyRandom. Required by controller-gen. -func (in *LBPolicyRandom) DeepCopy() *LBPolicyRandom { - if in == nil { - return nil - } - out := new(LBPolicyRandom) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new LBPolicyRandom. Required by controller-gen. -func (in *LBPolicyRandom) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using LBPolicyRingHash within kubernetes types, where deepcopy-gen is used. -func (in *LBPolicyRingHash) DeepCopyInto(out *LBPolicyRingHash) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LBPolicyRingHash. Required by controller-gen. -func (in *LBPolicyRingHash) DeepCopy() *LBPolicyRingHash { - if in == nil { - return nil - } - out := new(LBPolicyRingHash) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new LBPolicyRingHash. Required by controller-gen. -func (in *LBPolicyRingHash) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using LBPolicyMaglev within kubernetes types, where deepcopy-gen is used. -func (in *LBPolicyMaglev) DeepCopyInto(out *LBPolicyMaglev) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LBPolicyMaglev. Required by controller-gen. -func (in *LBPolicyMaglev) DeepCopy() *LBPolicyMaglev { - if in == nil { - return nil - } - out := new(LBPolicyMaglev) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new LBPolicyMaglev. Required by controller-gen. -func (in *LBPolicyMaglev) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using CircuitBreakers within kubernetes types, where deepcopy-gen is used. -func (in *CircuitBreakers) DeepCopyInto(out *CircuitBreakers) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CircuitBreakers. Required by controller-gen. -func (in *CircuitBreakers) DeepCopy() *CircuitBreakers { - if in == nil { - return nil - } - out := new(CircuitBreakers) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new CircuitBreakers. Required by controller-gen. -func (in *CircuitBreakers) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using UpstreamLimits within kubernetes types, where deepcopy-gen is used. -func (in *UpstreamLimits) DeepCopyInto(out *UpstreamLimits) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpstreamLimits. Required by controller-gen. -func (in *UpstreamLimits) DeepCopy() *UpstreamLimits { - if in == nil { - return nil - } - out := new(UpstreamLimits) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new UpstreamLimits. Required by controller-gen. -func (in *UpstreamLimits) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using OutlierDetection within kubernetes types, where deepcopy-gen is used. -func (in *OutlierDetection) DeepCopyInto(out *OutlierDetection) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OutlierDetection. Required by controller-gen. -func (in *OutlierDetection) DeepCopy() *OutlierDetection { - if in == nil { - return nil - } - out := new(OutlierDetection) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new OutlierDetection. Required by controller-gen. -func (in *OutlierDetection) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using UpstreamConnectionOptions within kubernetes types, where deepcopy-gen is used. -func (in *UpstreamConnectionOptions) DeepCopyInto(out *UpstreamConnectionOptions) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpstreamConnectionOptions. Required by controller-gen. -func (in *UpstreamConnectionOptions) DeepCopy() *UpstreamConnectionOptions { - if in == nil { - return nil - } - out := new(UpstreamConnectionOptions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new UpstreamConnectionOptions. Required by controller-gen. -func (in *UpstreamConnectionOptions) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using PassthroughEndpointGroupConfig within kubernetes types, where deepcopy-gen is used. -func (in *PassthroughEndpointGroupConfig) DeepCopyInto(out *PassthroughEndpointGroupConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PassthroughEndpointGroupConfig. Required by controller-gen. -func (in *PassthroughEndpointGroupConfig) DeepCopy() *PassthroughEndpointGroupConfig { - if in == nil { - return nil - } - out := new(PassthroughEndpointGroupConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new PassthroughEndpointGroupConfig. Required by controller-gen. -func (in *PassthroughEndpointGroupConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DNSEndpointGroupConfig within kubernetes types, where deepcopy-gen is used. -func (in *DNSEndpointGroupConfig) DeepCopyInto(out *DNSEndpointGroupConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpointGroupConfig. Required by controller-gen. -func (in *DNSEndpointGroupConfig) DeepCopy() *DNSEndpointGroupConfig { - if in == nil { - return nil - } - out := new(DNSEndpointGroupConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpointGroupConfig. Required by controller-gen. -func (in *DNSEndpointGroupConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using StaticEndpointGroupConfig within kubernetes types, where deepcopy-gen is used. -func (in *StaticEndpointGroupConfig) DeepCopyInto(out *StaticEndpointGroupConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StaticEndpointGroupConfig. Required by controller-gen. -func (in *StaticEndpointGroupConfig) DeepCopy() *StaticEndpointGroupConfig { - if in == nil { - return nil - } - out := new(StaticEndpointGroupConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new StaticEndpointGroupConfig. Required by controller-gen. -func (in *StaticEndpointGroupConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/cluster_json.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/cluster_json.gen.go deleted file mode 100644 index 570c801c000f..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/cluster_json.gen.go +++ /dev/null @@ -1,297 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package pbproxystate - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for Cluster -func (this *Cluster) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Cluster -func (this *Cluster) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for FailoverGroup -func (this *FailoverGroup) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for FailoverGroup -func (this *FailoverGroup) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for FailoverGroupConfig -func (this *FailoverGroupConfig) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for FailoverGroupConfig -func (this *FailoverGroupConfig) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for EndpointGroup -func (this *EndpointGroup) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for EndpointGroup -func (this *EndpointGroup) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DynamicEndpointGroup -func (this *DynamicEndpointGroup) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DynamicEndpointGroup -func (this *DynamicEndpointGroup) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for PassthroughEndpointGroup -func (this *PassthroughEndpointGroup) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for PassthroughEndpointGroup -func (this *PassthroughEndpointGroup) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DNSEndpointGroup -func (this *DNSEndpointGroup) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DNSEndpointGroup -func (this *DNSEndpointGroup) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for StaticEndpointGroup -func (this *StaticEndpointGroup) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for StaticEndpointGroup -func (this *StaticEndpointGroup) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DestinationCluster -func (this *DestinationCluster) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DestinationCluster -func (this *DestinationCluster) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for L4WeightedClusterGroup -func (this *L4WeightedClusterGroup) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for L4WeightedClusterGroup -func (this *L4WeightedClusterGroup) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for L7WeightedClusterGroup -func (this *L7WeightedClusterGroup) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for L7WeightedClusterGroup -func (this *L7WeightedClusterGroup) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for L4WeightedDestinationCluster -func (this *L4WeightedDestinationCluster) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for L4WeightedDestinationCluster -func (this *L4WeightedDestinationCluster) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for L7WeightedDestinationCluster -func (this *L7WeightedDestinationCluster) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for L7WeightedDestinationCluster -func (this *L7WeightedDestinationCluster) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DynamicEndpointGroupConfig -func (this *DynamicEndpointGroupConfig) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DynamicEndpointGroupConfig -func (this *DynamicEndpointGroupConfig) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for LBPolicyLeastRequest -func (this *LBPolicyLeastRequest) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for LBPolicyLeastRequest -func (this *LBPolicyLeastRequest) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for LBPolicyRoundRobin -func (this *LBPolicyRoundRobin) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for LBPolicyRoundRobin -func (this *LBPolicyRoundRobin) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for LBPolicyRandom -func (this *LBPolicyRandom) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for LBPolicyRandom -func (this *LBPolicyRandom) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for LBPolicyRingHash -func (this *LBPolicyRingHash) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for LBPolicyRingHash -func (this *LBPolicyRingHash) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for LBPolicyMaglev -func (this *LBPolicyMaglev) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for LBPolicyMaglev -func (this *LBPolicyMaglev) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for CircuitBreakers -func (this *CircuitBreakers) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for CircuitBreakers -func (this *CircuitBreakers) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for UpstreamLimits -func (this *UpstreamLimits) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for UpstreamLimits -func (this *UpstreamLimits) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for OutlierDetection -func (this *OutlierDetection) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for OutlierDetection -func (this *OutlierDetection) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for UpstreamConnectionOptions -func (this *UpstreamConnectionOptions) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for UpstreamConnectionOptions -func (this *UpstreamConnectionOptions) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for PassthroughEndpointGroupConfig -func (this *PassthroughEndpointGroupConfig) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for PassthroughEndpointGroupConfig -func (this *PassthroughEndpointGroupConfig) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DNSEndpointGroupConfig -func (this *DNSEndpointGroupConfig) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DNSEndpointGroupConfig -func (this *DNSEndpointGroupConfig) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for StaticEndpointGroupConfig -func (this *StaticEndpointGroupConfig) MarshalJSON() ([]byte, error) { - str, err := ClusterMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for StaticEndpointGroupConfig -func (this *StaticEndpointGroupConfig) UnmarshalJSON(b []byte) error { - return ClusterUnmarshaler.Unmarshal(b, this) -} - -var ( - ClusterMarshaler = &protojson.MarshalOptions{} - ClusterUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/endpoints.pb.binary.go b/proto-public/pbmesh/v2beta1/pbproxystate/endpoints.pb.binary.go deleted file mode 100644 index 82ab22a39db0..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/endpoints.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/pbproxystate/endpoints.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Endpoints) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Endpoints) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Endpoint) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Endpoint) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/endpoints.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/endpoints.pb.go deleted file mode 100644 index 5986ad83a12e..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/endpoints.pb.go +++ /dev/null @@ -1,387 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/endpoints.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=HEALTH_STATUS_UNKNOWN;HEALTH_STATUS_HEALTHY;HEALTH_STATUS_UNHEALTHY -// +kubebuilder:validation:Type=string -type HealthStatus int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - HealthStatus_HEALTH_STATUS_UNKNOWN HealthStatus = 0 - HealthStatus_HEALTH_STATUS_HEALTHY HealthStatus = 1 - HealthStatus_HEALTH_STATUS_UNHEALTHY HealthStatus = 2 -) - -// Enum value maps for HealthStatus. -var ( - HealthStatus_name = map[int32]string{ - 0: "HEALTH_STATUS_UNKNOWN", - 1: "HEALTH_STATUS_HEALTHY", - 2: "HEALTH_STATUS_UNHEALTHY", - } - HealthStatus_value = map[string]int32{ - "HEALTH_STATUS_UNKNOWN": 0, - "HEALTH_STATUS_HEALTHY": 1, - "HEALTH_STATUS_UNHEALTHY": 2, - } -) - -func (x HealthStatus) Enum() *HealthStatus { - p := new(HealthStatus) - *p = x - return p -} - -func (x HealthStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (HealthStatus) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_pbproxystate_endpoints_proto_enumTypes[0].Descriptor() -} - -func (HealthStatus) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_pbproxystate_endpoints_proto_enumTypes[0] -} - -func (x HealthStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use HealthStatus.Descriptor instead. -func (HealthStatus) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDescGZIP(), []int{0} -} - -type Endpoints struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Endpoints []*Endpoint `protobuf:"bytes,1,rep,name=endpoints,proto3" json:"endpoints,omitempty"` -} - -func (x *Endpoints) Reset() { - *x = Endpoints{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_endpoints_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Endpoints) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Endpoints) ProtoMessage() {} - -func (x *Endpoints) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_endpoints_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Endpoints.ProtoReflect.Descriptor instead. -func (*Endpoints) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDescGZIP(), []int{0} -} - -func (x *Endpoints) GetEndpoints() []*Endpoint { - if x != nil { - return x.Endpoints - } - return nil -} - -type Endpoint struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Address: - // - // *Endpoint_HostPort - // *Endpoint_UnixSocket - Address isEndpoint_Address `protobuf_oneof:"address"` - HealthStatus HealthStatus `protobuf:"varint,3,opt,name=health_status,json=healthStatus,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.HealthStatus" json:"health_status,omitempty"` - LoadBalancingWeight *wrapperspb.UInt32Value `protobuf:"bytes,4,opt,name=load_balancing_weight,json=loadBalancingWeight,proto3" json:"load_balancing_weight,omitempty"` -} - -func (x *Endpoint) Reset() { - *x = Endpoint{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_endpoints_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Endpoint) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Endpoint) ProtoMessage() {} - -func (x *Endpoint) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_endpoints_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Endpoint.ProtoReflect.Descriptor instead. -func (*Endpoint) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDescGZIP(), []int{1} -} - -func (m *Endpoint) GetAddress() isEndpoint_Address { - if m != nil { - return m.Address - } - return nil -} - -func (x *Endpoint) GetHostPort() *HostPortAddress { - if x, ok := x.GetAddress().(*Endpoint_HostPort); ok { - return x.HostPort - } - return nil -} - -func (x *Endpoint) GetUnixSocket() *UnixSocketAddress { - if x, ok := x.GetAddress().(*Endpoint_UnixSocket); ok { - return x.UnixSocket - } - return nil -} - -func (x *Endpoint) GetHealthStatus() HealthStatus { - if x != nil { - return x.HealthStatus - } - return HealthStatus_HEALTH_STATUS_UNKNOWN -} - -func (x *Endpoint) GetLoadBalancingWeight() *wrapperspb.UInt32Value { - if x != nil { - return x.LoadBalancingWeight - } - return nil -} - -type isEndpoint_Address interface { - isEndpoint_Address() -} - -type Endpoint_HostPort struct { - HostPort *HostPortAddress `protobuf:"bytes,1,opt,name=host_port,json=hostPort,proto3,oneof"` -} - -type Endpoint_UnixSocket struct { - UnixSocket *UnixSocketAddress `protobuf:"bytes,2,opt,name=unix_socket,json=unixSocket,proto3,oneof"` -} - -func (*Endpoint_HostPort) isEndpoint_Address() {} - -func (*Endpoint_UnixSocket) isEndpoint_Address() {} - -var File_pbmesh_v2beta1_pbproxystate_endpoints_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDesc = []byte{ - 0x0a, 0x2b, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x65, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, - 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x70, 0x62, 0x6d, 0x65, 0x73, - 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5f, 0x0a, 0x09, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x12, 0x52, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x84, 0x03, 0x0a, 0x08, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x12, 0x5a, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x48, 0x00, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x60, - 0x0a, 0x0b, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x75, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, - 0x12, 0x5d, 0x0a, 0x0d, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x50, 0x0a, 0x15, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, - 0x67, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x13, 0x6c, 0x6f, - 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x57, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x42, 0x09, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2a, 0x61, 0x0a, 0x0c, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x15, - 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, - 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x45, 0x41, 0x4c, 0x54, - 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, - 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x53, 0x54, 0x41, - 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x02, 0x42, - 0xd4, 0x02, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x42, 0x0e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, - 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, - 0x56, 0x50, 0xaa, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, - 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, - 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x36, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, - 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_endpoints_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v2beta1_pbproxystate_endpoints_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbmesh_v2beta1_pbproxystate_endpoints_proto_goTypes = []interface{}{ - (HealthStatus)(0), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.HealthStatus - (*Endpoints)(nil), // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.Endpoints - (*Endpoint)(nil), // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.Endpoint - (*HostPortAddress)(nil), // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.HostPortAddress - (*UnixSocketAddress)(nil), // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.UnixSocketAddress - (*wrapperspb.UInt32Value)(nil), // 5: google.protobuf.UInt32Value -} -var file_pbmesh_v2beta1_pbproxystate_endpoints_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.Endpoints.endpoints:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Endpoint - 3, // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.Endpoint.host_port:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.HostPortAddress - 4, // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.Endpoint.unix_socket:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.UnixSocketAddress - 0, // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.Endpoint.health_status:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.HealthStatus - 5, // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.Endpoint.load_balancing_weight:type_name -> google.protobuf.UInt32Value - 5, // [5:5] is the sub-list for method output_type - 5, // [5:5] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_endpoints_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_endpoints_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_endpoints_proto != nil { - return - } - file_pbmesh_v2beta1_pbproxystate_address_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_pbproxystate_endpoints_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Endpoints); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_endpoints_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Endpoint); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v2beta1_pbproxystate_endpoints_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*Endpoint_HostPort)(nil), - (*Endpoint_UnixSocket)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDesc, - NumEnums: 1, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_endpoints_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_endpoints_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_pbproxystate_endpoints_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_pbproxystate_endpoints_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_endpoints_proto = out.File - file_pbmesh_v2beta1_pbproxystate_endpoints_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_endpoints_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_endpoints_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/endpoints.proto b/proto-public/pbmesh/v2beta1/pbproxystate/endpoints.proto deleted file mode 100644 index 0612c4eb11f5..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/endpoints.proto +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1.pbproxystate; - -import "google/protobuf/wrappers.proto"; -import "pbmesh/v2beta1/pbproxystate/address.proto"; - -message Endpoints { - repeated Endpoint endpoints = 1; -} - -message Endpoint { - oneof address { - HostPortAddress host_port = 1; - UnixSocketAddress unix_socket = 2; - } - HealthStatus health_status = 3; - google.protobuf.UInt32Value load_balancing_weight = 4; -} - -// +kubebuilder:validation:Enum=HEALTH_STATUS_UNKNOWN;HEALTH_STATUS_HEALTHY;HEALTH_STATUS_UNHEALTHY -// +kubebuilder:validation:Type=string -enum HealthStatus { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - HEALTH_STATUS_UNKNOWN = 0; - HEALTH_STATUS_HEALTHY = 1; - HEALTH_STATUS_UNHEALTHY = 2; -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/endpoints_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/endpoints_deepcopy.gen.go deleted file mode 100644 index eeb1daa5d23c..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/endpoints_deepcopy.gen.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package pbproxystate - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using Endpoints within kubernetes types, where deepcopy-gen is used. -func (in *Endpoints) DeepCopyInto(out *Endpoints) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Endpoints. Required by controller-gen. -func (in *Endpoints) DeepCopy() *Endpoints { - if in == nil { - return nil - } - out := new(Endpoints) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Endpoints. Required by controller-gen. -func (in *Endpoints) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Endpoint within kubernetes types, where deepcopy-gen is used. -func (in *Endpoint) DeepCopyInto(out *Endpoint) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Endpoint. Required by controller-gen. -func (in *Endpoint) DeepCopy() *Endpoint { - if in == nil { - return nil - } - out := new(Endpoint) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Endpoint. Required by controller-gen. -func (in *Endpoint) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/endpoints_json.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/endpoints_json.gen.go deleted file mode 100644 index 45b9fbf321e9..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/endpoints_json.gen.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package pbproxystate - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for Endpoints -func (this *Endpoints) MarshalJSON() ([]byte, error) { - str, err := EndpointsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Endpoints -func (this *Endpoints) UnmarshalJSON(b []byte) error { - return EndpointsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Endpoint -func (this *Endpoint) MarshalJSON() ([]byte, error) { - str, err := EndpointsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Endpoint -func (this *Endpoint) UnmarshalJSON(b []byte) error { - return EndpointsUnmarshaler.Unmarshal(b, this) -} - -var ( - EndpointsMarshaler = &protojson.MarshalOptions{} - EndpointsUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches.pb.binary.go b/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches.pb.binary.go deleted file mode 100644 index e266a07be25d..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/pbproxystate/escape_hatches.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *EscapeHatches) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *EscapeHatches) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches.pb.go deleted file mode 100644 index 91e549564ced..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches.pb.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/escape_hatches.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type EscapeHatches struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // listener_tracing_json contains user provided tracing configuration. - ListenerTracingJson string `protobuf:"bytes,1,opt,name=listener_tracing_json,json=listenerTracingJson,proto3" json:"listener_tracing_json,omitempty"` -} - -func (x *EscapeHatches) Reset() { - *x = EscapeHatches{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EscapeHatches) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EscapeHatches) ProtoMessage() {} - -func (x *EscapeHatches) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EscapeHatches.ProtoReflect.Descriptor instead. -func (*EscapeHatches) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_rawDescGZIP(), []int{0} -} - -func (x *EscapeHatches) GetListenerTracingJson() string { - if x != nil { - return x.ListenerTracingJson - } - return "" -} - -var File_pbmesh_v2beta1_pbproxystate_escape_hatches_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_rawDesc = []byte{ - 0x0a, 0x30, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x65, 0x73, - 0x63, 0x61, 0x70, 0x65, 0x5f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x2a, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x43, - 0x0a, 0x0d, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, - 0x32, 0x0a, 0x15, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x61, 0x63, - 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, - 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x4a, - 0x73, 0x6f, 0x6e, 0x42, 0xd8, 0x02, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x12, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2a, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, - 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x36, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2e, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_goTypes = []interface{}{ - (*EscapeHatches)(nil), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.EscapeHatches -} -var file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_escape_hatches_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EscapeHatches); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_escape_hatches_proto = out.File - file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_escape_hatches_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches.proto b/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches.proto deleted file mode 100644 index 566fc4f06bf6..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches.proto +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1.pbproxystate; - -message EscapeHatches { - // listener_tracing_json contains user provided tracing configuration. - string listener_tracing_json = 1; -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches_deepcopy.gen.go deleted file mode 100644 index 41fcb73d4662..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package pbproxystate - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using EscapeHatches within kubernetes types, where deepcopy-gen is used. -func (in *EscapeHatches) DeepCopyInto(out *EscapeHatches) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EscapeHatches. Required by controller-gen. -func (in *EscapeHatches) DeepCopy() *EscapeHatches { - if in == nil { - return nil - } - out := new(EscapeHatches) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new EscapeHatches. Required by controller-gen. -func (in *EscapeHatches) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches_json.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches_json.gen.go deleted file mode 100644 index ecda76eb2284..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/escape_hatches_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package pbproxystate - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for EscapeHatches -func (this *EscapeHatches) MarshalJSON() ([]byte, error) { - str, err := EscapeHatchesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for EscapeHatches -func (this *EscapeHatches) UnmarshalJSON(b []byte) error { - return EscapeHatchesUnmarshaler.Unmarshal(b, this) -} - -var ( - EscapeHatchesMarshaler = &protojson.MarshalOptions{} - EscapeHatchesUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations.pb.binary.go b/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations.pb.binary.go deleted file mode 100644 index 35b0b8969eaf..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations.pb.binary.go +++ /dev/null @@ -1,68 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/pbproxystate/header_mutations.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HeaderMutation) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HeaderMutation) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RequestHeaderAdd) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RequestHeaderAdd) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RequestHeaderRemove) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RequestHeaderRemove) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ResponseHeaderAdd) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ResponseHeaderAdd) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ResponseHeaderRemove) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ResponseHeaderRemove) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Header) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Header) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations.pb.go deleted file mode 100644 index 54bc797892fd..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations.pb.go +++ /dev/null @@ -1,694 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/header_mutations.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD;APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD -// +kubebuilder:validation:Type=string -type AppendAction int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD AppendAction = 0 - AppendAction_APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD AppendAction = 1 -) - -// Enum value maps for AppendAction. -var ( - AppendAction_name = map[int32]string{ - 0: "APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD", - 1: "APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD", - } - AppendAction_value = map[string]int32{ - "APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD": 0, - "APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD": 1, - } -) - -func (x AppendAction) Enum() *AppendAction { - p := new(AppendAction) - *p = x - return p -} - -func (x AppendAction) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (AppendAction) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_enumTypes[0].Descriptor() -} - -func (AppendAction) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_enumTypes[0] -} - -func (x AppendAction) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use AppendAction.Descriptor instead. -func (AppendAction) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{0} -} - -// Note: it's nice to have this list of header mutations as opposed to configuration similar to Envoy because it -// translates more nicely from GAMMA HTTPRoute, and our existing service router config. Then xds code can handle turning -// it into envoy xds. -type HeaderMutation struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Action: - // - // *HeaderMutation_RequestHeaderAdd - // *HeaderMutation_RequestHeaderRemove - // *HeaderMutation_ResponseHeaderAdd - // *HeaderMutation_ResponseHeaderRemove - Action isHeaderMutation_Action `protobuf_oneof:"action"` -} - -func (x *HeaderMutation) Reset() { - *x = HeaderMutation{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HeaderMutation) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HeaderMutation) ProtoMessage() {} - -func (x *HeaderMutation) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HeaderMutation.ProtoReflect.Descriptor instead. -func (*HeaderMutation) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{0} -} - -func (m *HeaderMutation) GetAction() isHeaderMutation_Action { - if m != nil { - return m.Action - } - return nil -} - -func (x *HeaderMutation) GetRequestHeaderAdd() *RequestHeaderAdd { - if x, ok := x.GetAction().(*HeaderMutation_RequestHeaderAdd); ok { - return x.RequestHeaderAdd - } - return nil -} - -func (x *HeaderMutation) GetRequestHeaderRemove() *RequestHeaderRemove { - if x, ok := x.GetAction().(*HeaderMutation_RequestHeaderRemove); ok { - return x.RequestHeaderRemove - } - return nil -} - -func (x *HeaderMutation) GetResponseHeaderAdd() *ResponseHeaderAdd { - if x, ok := x.GetAction().(*HeaderMutation_ResponseHeaderAdd); ok { - return x.ResponseHeaderAdd - } - return nil -} - -func (x *HeaderMutation) GetResponseHeaderRemove() *ResponseHeaderRemove { - if x, ok := x.GetAction().(*HeaderMutation_ResponseHeaderRemove); ok { - return x.ResponseHeaderRemove - } - return nil -} - -type isHeaderMutation_Action interface { - isHeaderMutation_Action() -} - -type HeaderMutation_RequestHeaderAdd struct { - RequestHeaderAdd *RequestHeaderAdd `protobuf:"bytes,1,opt,name=request_header_add,json=requestHeaderAdd,proto3,oneof"` -} - -type HeaderMutation_RequestHeaderRemove struct { - RequestHeaderRemove *RequestHeaderRemove `protobuf:"bytes,2,opt,name=request_header_remove,json=requestHeaderRemove,proto3,oneof"` -} - -type HeaderMutation_ResponseHeaderAdd struct { - ResponseHeaderAdd *ResponseHeaderAdd `protobuf:"bytes,3,opt,name=response_header_add,json=responseHeaderAdd,proto3,oneof"` -} - -type HeaderMutation_ResponseHeaderRemove struct { - ResponseHeaderRemove *ResponseHeaderRemove `protobuf:"bytes,4,opt,name=response_header_remove,json=responseHeaderRemove,proto3,oneof"` -} - -func (*HeaderMutation_RequestHeaderAdd) isHeaderMutation_Action() {} - -func (*HeaderMutation_RequestHeaderRemove) isHeaderMutation_Action() {} - -func (*HeaderMutation_ResponseHeaderAdd) isHeaderMutation_Action() {} - -func (*HeaderMutation_ResponseHeaderRemove) isHeaderMutation_Action() {} - -type RequestHeaderAdd struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Header *Header `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` - AppendAction AppendAction `protobuf:"varint,2,opt,name=append_action,json=appendAction,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.AppendAction" json:"append_action,omitempty"` -} - -func (x *RequestHeaderAdd) Reset() { - *x = RequestHeaderAdd{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RequestHeaderAdd) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RequestHeaderAdd) ProtoMessage() {} - -func (x *RequestHeaderAdd) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RequestHeaderAdd.ProtoReflect.Descriptor instead. -func (*RequestHeaderAdd) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{1} -} - -func (x *RequestHeaderAdd) GetHeader() *Header { - if x != nil { - return x.Header - } - return nil -} - -func (x *RequestHeaderAdd) GetAppendAction() AppendAction { - if x != nil { - return x.AppendAction - } - return AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD -} - -type RequestHeaderRemove struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - HeaderKeys []string `protobuf:"bytes,1,rep,name=header_keys,json=headerKeys,proto3" json:"header_keys,omitempty"` -} - -func (x *RequestHeaderRemove) Reset() { - *x = RequestHeaderRemove{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RequestHeaderRemove) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RequestHeaderRemove) ProtoMessage() {} - -func (x *RequestHeaderRemove) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RequestHeaderRemove.ProtoReflect.Descriptor instead. -func (*RequestHeaderRemove) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{2} -} - -func (x *RequestHeaderRemove) GetHeaderKeys() []string { - if x != nil { - return x.HeaderKeys - } - return nil -} - -type ResponseHeaderAdd struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Header *Header `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` - AppendAction AppendAction `protobuf:"varint,2,opt,name=append_action,json=appendAction,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.AppendAction" json:"append_action,omitempty"` -} - -func (x *ResponseHeaderAdd) Reset() { - *x = ResponseHeaderAdd{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ResponseHeaderAdd) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ResponseHeaderAdd) ProtoMessage() {} - -func (x *ResponseHeaderAdd) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ResponseHeaderAdd.ProtoReflect.Descriptor instead. -func (*ResponseHeaderAdd) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{3} -} - -func (x *ResponseHeaderAdd) GetHeader() *Header { - if x != nil { - return x.Header - } - return nil -} - -func (x *ResponseHeaderAdd) GetAppendAction() AppendAction { - if x != nil { - return x.AppendAction - } - return AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD -} - -type ResponseHeaderRemove struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - HeaderKeys []string `protobuf:"bytes,1,rep,name=header_keys,json=headerKeys,proto3" json:"header_keys,omitempty"` -} - -func (x *ResponseHeaderRemove) Reset() { - *x = ResponseHeaderRemove{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ResponseHeaderRemove) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ResponseHeaderRemove) ProtoMessage() {} - -func (x *ResponseHeaderRemove) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ResponseHeaderRemove.ProtoReflect.Descriptor instead. -func (*ResponseHeaderRemove) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{4} -} - -func (x *ResponseHeaderRemove) GetHeaderKeys() []string { - if x != nil { - return x.HeaderKeys - } - return nil -} - -type Header struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *Header) Reset() { - *x = Header{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Header) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Header) ProtoMessage() {} - -func (x *Header) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Header.ProtoReflect.Descriptor instead. -func (*Header) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescGZIP(), []int{5} -} - -func (x *Header) GetKey() string { - if x != nil { - return x.Key - } - return "" -} - -func (x *Header) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -var File_pbmesh_v2beta1_pbproxystate_header_mutations_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDesc = []byte{ - 0x0a, 0x32, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x22, 0xea, 0x03, 0x0a, 0x0e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x6c, 0x0a, 0x12, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x48, 0x00, 0x52, - 0x10, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x64, - 0x64, 0x12, 0x75, 0x0a, 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x48, 0x00, 0x52, 0x13, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x6f, 0x0a, 0x13, 0x72, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x41, 0x64, 0x64, 0x48, 0x00, 0x52, 0x11, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x12, 0x78, 0x0a, 0x16, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x48, 0x00, 0x52, 0x14, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xbd, 0x01, - 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, - 0x64, 0x64, 0x12, 0x4a, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x5d, - 0x0a, 0x0d, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0c, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x36, 0x0a, - 0x13, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6b, - 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x4b, 0x65, 0x79, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x12, 0x4a, 0x0a, 0x06, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, - 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x5d, 0x0a, 0x0d, 0x61, 0x70, 0x70, 0x65, 0x6e, - 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x65, - 0x6e, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, - 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x37, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x1f, - 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x73, 0x22, - 0x30, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x2a, 0x67, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x29, 0x0a, 0x25, 0x41, 0x50, 0x50, 0x45, 0x4e, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x41, 0x50, 0x50, 0x45, 0x4e, 0x44, 0x5f, 0x49, 0x46, 0x5f, 0x45, 0x58, 0x49, - 0x53, 0x54, 0x53, 0x5f, 0x4f, 0x52, 0x5f, 0x41, 0x44, 0x44, 0x10, 0x00, 0x12, 0x2c, 0x0a, 0x28, - 0x41, 0x50, 0x50, 0x45, 0x4e, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x56, - 0x45, 0x52, 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x49, 0x46, 0x5f, 0x45, 0x58, 0x49, 0x53, 0x54, - 0x53, 0x5f, 0x4f, 0x52, 0x5f, 0x41, 0x44, 0x44, 0x10, 0x01, 0x42, 0xda, 0x02, 0x0a, 0x2e, 0x63, - 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x14, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, - 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, - 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0xca, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x36, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, - 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes = make([]protoimpl.MessageInfo, 6) -var file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_goTypes = []interface{}{ - (AppendAction)(0), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.AppendAction - (*HeaderMutation)(nil), // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderMutation - (*RequestHeaderAdd)(nil), // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.RequestHeaderAdd - (*RequestHeaderRemove)(nil), // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.RequestHeaderRemove - (*ResponseHeaderAdd)(nil), // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.ResponseHeaderAdd - (*ResponseHeaderRemove)(nil), // 5: hashicorp.consul.mesh.v2beta1.pbproxystate.ResponseHeaderRemove - (*Header)(nil), // 6: hashicorp.consul.mesh.v2beta1.pbproxystate.Header -} -var file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderMutation.request_header_add:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.RequestHeaderAdd - 3, // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderMutation.request_header_remove:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.RequestHeaderRemove - 4, // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderMutation.response_header_add:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.ResponseHeaderAdd - 5, // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderMutation.response_header_remove:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.ResponseHeaderRemove - 6, // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.RequestHeaderAdd.header:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Header - 0, // 5: hashicorp.consul.mesh.v2beta1.pbproxystate.RequestHeaderAdd.append_action:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.AppendAction - 6, // 6: hashicorp.consul.mesh.v2beta1.pbproxystate.ResponseHeaderAdd.header:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Header - 0, // 7: hashicorp.consul.mesh.v2beta1.pbproxystate.ResponseHeaderAdd.append_action:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.AppendAction - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_header_mutations_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HeaderMutation); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RequestHeaderAdd); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RequestHeaderRemove); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResponseHeaderAdd); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResponseHeaderRemove); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Header); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*HeaderMutation_RequestHeaderAdd)(nil), - (*HeaderMutation_RequestHeaderRemove)(nil), - (*HeaderMutation_ResponseHeaderAdd)(nil), - (*HeaderMutation_ResponseHeaderRemove)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDesc, - NumEnums: 1, - NumMessages: 6, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_header_mutations_proto = out.File - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations.proto b/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations.proto deleted file mode 100644 index 63a4bf83f6cc..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations.proto +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1.pbproxystate; - -// Note: it's nice to have this list of header mutations as opposed to configuration similar to Envoy because it -// translates more nicely from GAMMA HTTPRoute, and our existing service router config. Then xds code can handle turning -// it into envoy xds. -message HeaderMutation { - oneof action { - RequestHeaderAdd request_header_add = 1; - RequestHeaderRemove request_header_remove = 2; - ResponseHeaderAdd response_header_add = 3; - ResponseHeaderRemove response_header_remove = 4; - } -} - -message RequestHeaderAdd { - Header header = 1; - AppendAction append_action = 2; -} - -message RequestHeaderRemove { - repeated string header_keys = 1; -} - -message ResponseHeaderAdd { - Header header = 1; - AppendAction append_action = 2; -} - -message ResponseHeaderRemove { - repeated string header_keys = 1; -} - -message Header { - string key = 1; - string value = 2; -} - -// +kubebuilder:validation:Enum=APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD;APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD -// +kubebuilder:validation:Type=string -enum AppendAction { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD = 0; - APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD = 1; -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations_deepcopy.gen.go deleted file mode 100644 index 97a77c7fc402..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations_deepcopy.gen.go +++ /dev/null @@ -1,132 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package pbproxystate - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using HeaderMutation within kubernetes types, where deepcopy-gen is used. -func (in *HeaderMutation) DeepCopyInto(out *HeaderMutation) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderMutation. Required by controller-gen. -func (in *HeaderMutation) DeepCopy() *HeaderMutation { - if in == nil { - return nil - } - out := new(HeaderMutation) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HeaderMutation. Required by controller-gen. -func (in *HeaderMutation) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using RequestHeaderAdd within kubernetes types, where deepcopy-gen is used. -func (in *RequestHeaderAdd) DeepCopyInto(out *RequestHeaderAdd) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestHeaderAdd. Required by controller-gen. -func (in *RequestHeaderAdd) DeepCopy() *RequestHeaderAdd { - if in == nil { - return nil - } - out := new(RequestHeaderAdd) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new RequestHeaderAdd. Required by controller-gen. -func (in *RequestHeaderAdd) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using RequestHeaderRemove within kubernetes types, where deepcopy-gen is used. -func (in *RequestHeaderRemove) DeepCopyInto(out *RequestHeaderRemove) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestHeaderRemove. Required by controller-gen. -func (in *RequestHeaderRemove) DeepCopy() *RequestHeaderRemove { - if in == nil { - return nil - } - out := new(RequestHeaderRemove) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new RequestHeaderRemove. Required by controller-gen. -func (in *RequestHeaderRemove) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ResponseHeaderAdd within kubernetes types, where deepcopy-gen is used. -func (in *ResponseHeaderAdd) DeepCopyInto(out *ResponseHeaderAdd) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResponseHeaderAdd. Required by controller-gen. -func (in *ResponseHeaderAdd) DeepCopy() *ResponseHeaderAdd { - if in == nil { - return nil - } - out := new(ResponseHeaderAdd) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ResponseHeaderAdd. Required by controller-gen. -func (in *ResponseHeaderAdd) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ResponseHeaderRemove within kubernetes types, where deepcopy-gen is used. -func (in *ResponseHeaderRemove) DeepCopyInto(out *ResponseHeaderRemove) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResponseHeaderRemove. Required by controller-gen. -func (in *ResponseHeaderRemove) DeepCopy() *ResponseHeaderRemove { - if in == nil { - return nil - } - out := new(ResponseHeaderRemove) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ResponseHeaderRemove. Required by controller-gen. -func (in *ResponseHeaderRemove) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Header within kubernetes types, where deepcopy-gen is used. -func (in *Header) DeepCopyInto(out *Header) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Header. Required by controller-gen. -func (in *Header) DeepCopy() *Header { - if in == nil { - return nil - } - out := new(Header) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Header. Required by controller-gen. -func (in *Header) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations_json.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations_json.gen.go deleted file mode 100644 index 53c422f75278..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/header_mutations_json.gen.go +++ /dev/null @@ -1,77 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package pbproxystate - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for HeaderMutation -func (this *HeaderMutation) MarshalJSON() ([]byte, error) { - str, err := HeaderMutationsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HeaderMutation -func (this *HeaderMutation) UnmarshalJSON(b []byte) error { - return HeaderMutationsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for RequestHeaderAdd -func (this *RequestHeaderAdd) MarshalJSON() ([]byte, error) { - str, err := HeaderMutationsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for RequestHeaderAdd -func (this *RequestHeaderAdd) UnmarshalJSON(b []byte) error { - return HeaderMutationsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for RequestHeaderRemove -func (this *RequestHeaderRemove) MarshalJSON() ([]byte, error) { - str, err := HeaderMutationsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for RequestHeaderRemove -func (this *RequestHeaderRemove) UnmarshalJSON(b []byte) error { - return HeaderMutationsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ResponseHeaderAdd -func (this *ResponseHeaderAdd) MarshalJSON() ([]byte, error) { - str, err := HeaderMutationsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ResponseHeaderAdd -func (this *ResponseHeaderAdd) UnmarshalJSON(b []byte) error { - return HeaderMutationsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ResponseHeaderRemove -func (this *ResponseHeaderRemove) MarshalJSON() ([]byte, error) { - str, err := HeaderMutationsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ResponseHeaderRemove -func (this *ResponseHeaderRemove) UnmarshalJSON(b []byte) error { - return HeaderMutationsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Header -func (this *Header) MarshalJSON() ([]byte, error) { - str, err := HeaderMutationsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Header -func (this *Header) UnmarshalJSON(b []byte) error { - return HeaderMutationsUnmarshaler.Unmarshal(b, this) -} - -var ( - HeaderMutationsMarshaler = &protojson.MarshalOptions{} - HeaderMutationsUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/intentions.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/intentions.pb.go deleted file mode 100644 index 96ca59240fa4..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/intentions.pb.go +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/intentions.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type L7Intention struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *L7Intention) Reset() { - *x = L7Intention{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_intentions_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L7Intention) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L7Intention) ProtoMessage() {} - -func (x *L7Intention) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_intentions_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use L7Intention.ProtoReflect.Descriptor instead. -func (*L7Intention) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDescGZIP(), []int{0} -} - -type L4Intention struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *L4Intention) Reset() { - *x = L4Intention{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_intentions_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L4Intention) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L4Intention) ProtoMessage() {} - -func (x *L4Intention) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_intentions_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use L4Intention.ProtoReflect.Descriptor instead. -func (*L4Intention) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDescGZIP(), []int{1} -} - -var File_pbmesh_v2beta1_pbproxystate_intentions_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDesc = []byte{ - 0x0a, 0x2c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x69, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x0d, 0x0a, 0x0b, 0x4c, 0x37, - 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x0d, 0x0a, 0x0b, 0x4c, 0x34, 0x49, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0xd5, 0x02, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0f, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2a, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, - 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x36, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_intentions_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_pbmesh_v2beta1_pbproxystate_intentions_proto_goTypes = []interface{}{ - (*L7Intention)(nil), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.L7Intention - (*L4Intention)(nil), // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.L4Intention -} -var file_pbmesh_v2beta1_pbproxystate_intentions_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_intentions_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_intentions_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_intentions_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_pbproxystate_intentions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L7Intention); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_intentions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L4Intention); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_intentions_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_intentions_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_pbproxystate_intentions_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_intentions_proto = out.File - file_pbmesh_v2beta1_pbproxystate_intentions_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_intentions_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_intentions_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/listener.pb.binary.go b/proto-public/pbmesh/v2beta1/pbproxystate/listener.pb.binary.go deleted file mode 100644 index f463b8049c3d..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/listener.pb.binary.go +++ /dev/null @@ -1,88 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/pbproxystate/listener.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Listener) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Listener) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Router) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Router) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Match) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Match) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *CidrRange) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *CidrRange) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L4Destination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L4Destination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L7DestinationRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L7DestinationRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *L7Destination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *L7Destination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *SNIDestination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *SNIDestination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/listener.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/listener.pb.go deleted file mode 100644 index a7d7273163da..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/listener.pb.go +++ /dev/null @@ -1,1500 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/listener.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=DIRECTION_UNSPECIFIED;DIRECTION_INBOUND;DIRECTION_OUTBOUND -// +kubebuilder:validation:Type=string -type Direction int32 - -const ( - // DIRECTION_UNSPECIFIED is used by mesh gateway listeners. - Direction_DIRECTION_UNSPECIFIED Direction = 0 - Direction_DIRECTION_INBOUND Direction = 1 - Direction_DIRECTION_OUTBOUND Direction = 2 -) - -// Enum value maps for Direction. -var ( - Direction_name = map[int32]string{ - 0: "DIRECTION_UNSPECIFIED", - 1: "DIRECTION_INBOUND", - 2: "DIRECTION_OUTBOUND", - } - Direction_value = map[string]int32{ - "DIRECTION_UNSPECIFIED": 0, - "DIRECTION_INBOUND": 1, - "DIRECTION_OUTBOUND": 2, - } -) - -func (x Direction) Enum() *Direction { - p := new(Direction) - *p = x - return p -} - -func (x Direction) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Direction) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_enumTypes[0].Descriptor() -} - -func (Direction) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_pbproxystate_listener_proto_enumTypes[0] -} - -func (x Direction) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Direction.Descriptor instead. -func (Direction) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{0} -} - -// +kubebuilder:validation:Enum=BALANCE_CONNECTIONS_DEFAULT;BALANCE_CONNECTIONS_EXACT -// +kubebuilder:validation:Type=string -type BalanceConnections int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - BalanceConnections_BALANCE_CONNECTIONS_DEFAULT BalanceConnections = 0 - BalanceConnections_BALANCE_CONNECTIONS_EXACT BalanceConnections = 1 -) - -// Enum value maps for BalanceConnections. -var ( - BalanceConnections_name = map[int32]string{ - 0: "BALANCE_CONNECTIONS_DEFAULT", - 1: "BALANCE_CONNECTIONS_EXACT", - } - BalanceConnections_value = map[string]int32{ - "BALANCE_CONNECTIONS_DEFAULT": 0, - "BALANCE_CONNECTIONS_EXACT": 1, - } -) - -func (x BalanceConnections) Enum() *BalanceConnections { - p := new(BalanceConnections) - *p = x - return p -} - -func (x BalanceConnections) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (BalanceConnections) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_enumTypes[1].Descriptor() -} - -func (BalanceConnections) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_pbproxystate_listener_proto_enumTypes[1] -} - -func (x BalanceConnections) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use BalanceConnections.Descriptor instead. -func (BalanceConnections) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{1} -} - -// Capabilities map to proxy functionality to enable. These enable tproxy, l7 protocol/alpn inspection, or l4 sni/alpn inspection. -// -// +kubebuilder:validation:Enum=CAPABILITY_TRANSPARENT;CAPABILITY_L7_PROTOCOL_INSPECTION;CAPABILITY_L4_TLS_INSPECTION -// +kubebuilder:validation:Type=string -type Capability int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - Capability_CAPABILITY_TRANSPARENT Capability = 0 - Capability_CAPABILITY_L7_PROTOCOL_INSPECTION Capability = 1 - Capability_CAPABILITY_L4_TLS_INSPECTION Capability = 2 -) - -// Enum value maps for Capability. -var ( - Capability_name = map[int32]string{ - 0: "CAPABILITY_TRANSPARENT", - 1: "CAPABILITY_L7_PROTOCOL_INSPECTION", - 2: "CAPABILITY_L4_TLS_INSPECTION", - } - Capability_value = map[string]int32{ - "CAPABILITY_TRANSPARENT": 0, - "CAPABILITY_L7_PROTOCOL_INSPECTION": 1, - "CAPABILITY_L4_TLS_INSPECTION": 2, - } -) - -func (x Capability) Enum() *Capability { - p := new(Capability) - *p = x - return p -} - -func (x Capability) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Capability) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_enumTypes[2].Descriptor() -} - -func (Capability) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_pbproxystate_listener_proto_enumTypes[2] -} - -func (x Capability) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Capability.Descriptor instead. -func (Capability) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{2} -} - -// +kubebuilder:validation:Enum=XFCC_POLICY_SANITIZE;XFCC_POLICY_FORWARD_ONLY;XFCC_POLICY_APPEND_FORWARD;XFCC_POLICY_SANITIZE_SET;XFCC_POLICY_ALWAYS_FORWARD_ONLY -// +kubebuilder:validation:Type=string -type XFCCPolicy int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - // Do not send the XFCC header to the next hop. This is the default value. - XFCCPolicy_XFCC_POLICY_SANITIZE XFCCPolicy = 0 - // When the client connection is mTLS (Mutual TLS), forward the XFCC header - // in the request. - XFCCPolicy_XFCC_POLICY_FORWARD_ONLY XFCCPolicy = 1 - // When the client connection is mTLS, append the client certificate - // information to the request’s XFCC header and forward it. - XFCCPolicy_XFCC_POLICY_APPEND_FORWARD XFCCPolicy = 2 - // When the client connection is mTLS, reset the XFCC header with the client - // certificate information and send it to the next hop. - XFCCPolicy_XFCC_POLICY_SANITIZE_SET XFCCPolicy = 3 - // Always forward the XFCC header in the request, regardless of whether the - // client connection is mTLS. - XFCCPolicy_XFCC_POLICY_ALWAYS_FORWARD_ONLY XFCCPolicy = 4 -) - -// Enum value maps for XFCCPolicy. -var ( - XFCCPolicy_name = map[int32]string{ - 0: "XFCC_POLICY_SANITIZE", - 1: "XFCC_POLICY_FORWARD_ONLY", - 2: "XFCC_POLICY_APPEND_FORWARD", - 3: "XFCC_POLICY_SANITIZE_SET", - 4: "XFCC_POLICY_ALWAYS_FORWARD_ONLY", - } - XFCCPolicy_value = map[string]int32{ - "XFCC_POLICY_SANITIZE": 0, - "XFCC_POLICY_FORWARD_ONLY": 1, - "XFCC_POLICY_APPEND_FORWARD": 2, - "XFCC_POLICY_SANITIZE_SET": 3, - "XFCC_POLICY_ALWAYS_FORWARD_ONLY": 4, - } -) - -func (x XFCCPolicy) Enum() *XFCCPolicy { - p := new(XFCCPolicy) - *p = x - return p -} - -func (x XFCCPolicy) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (XFCCPolicy) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_enumTypes[3].Descriptor() -} - -func (XFCCPolicy) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_pbproxystate_listener_proto_enumTypes[3] -} - -func (x XFCCPolicy) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use XFCCPolicy.Descriptor instead. -func (XFCCPolicy) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{3} -} - -// +kubebuilder:validation:Enum=L7_PROTOCOL_HTTP;L7_PROTOCOL_HTTP2;L7_PROTOCOL_GRPC -// +kubebuilder:validation:Type=string -type L7Protocol int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - L7Protocol_L7_PROTOCOL_HTTP L7Protocol = 0 - L7Protocol_L7_PROTOCOL_HTTP2 L7Protocol = 1 - L7Protocol_L7_PROTOCOL_GRPC L7Protocol = 2 -) - -// Enum value maps for L7Protocol. -var ( - L7Protocol_name = map[int32]string{ - 0: "L7_PROTOCOL_HTTP", - 1: "L7_PROTOCOL_HTTP2", - 2: "L7_PROTOCOL_GRPC", - } - L7Protocol_value = map[string]int32{ - "L7_PROTOCOL_HTTP": 0, - "L7_PROTOCOL_HTTP2": 1, - "L7_PROTOCOL_GRPC": 2, - } -) - -func (x L7Protocol) Enum() *L7Protocol { - p := new(L7Protocol) - *p = x - return p -} - -func (x L7Protocol) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (L7Protocol) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_enumTypes[4].Descriptor() -} - -func (L7Protocol) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_pbproxystate_listener_proto_enumTypes[4] -} - -func (x L7Protocol) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use L7Protocol.Descriptor instead. -func (L7Protocol) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{4} -} - -type Listener struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is the name of the listener. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // direction tells the listener the direction of traffic. - Direction Direction `protobuf:"varint,2,opt,name=direction,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.Direction" json:"direction,omitempty"` - // bind_address describes where to listen. - // - // Types that are assignable to BindAddress: - // - // *Listener_HostPort - // *Listener_UnixSocket - BindAddress isListener_BindAddress `protobuf_oneof:"bind_address"` - // routers describes how to route traffic from this listener. - Routers []*Router `protobuf:"bytes,5,rep,name=routers,proto3" json:"routers,omitempty"` - // default_router describes where to route if none of the other router matches match the connection. - DefaultRouter *Router `protobuf:"bytes,6,opt,name=default_router,json=defaultRouter,proto3" json:"default_router,omitempty"` - // capabilities describe Envoy proxy functionality to enable. These map closely to Envoy listener filters. - Capabilities []Capability `protobuf:"varint,7,rep,packed,name=capabilities,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.Capability" json:"capabilities,omitempty"` - // balance_connections configures how the listener should balance connections. - BalanceConnections BalanceConnections `protobuf:"varint,8,opt,name=balance_connections,json=balanceConnections,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.BalanceConnections" json:"balance_connections,omitempty"` - // escape_hatch_listener_json configures a user configured escape hatch listener. - EscapeHatchListener string `protobuf:"bytes,9,opt,name=escape_hatch_listener,json=escapeHatchListener,proto3" json:"escape_hatch_listener,omitempty"` - // use_escape_hatch_tracing configures whether to use the top level user configured tracing escape hatch for this listener. - UseEscapeHatchTracing bool `protobuf:"varint,10,opt,name=use_escape_hatch_tracing,json=useEscapeHatchTracing,proto3" json:"use_escape_hatch_tracing,omitempty"` -} - -func (x *Listener) Reset() { - *x = Listener{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Listener) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Listener) ProtoMessage() {} - -func (x *Listener) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Listener.ProtoReflect.Descriptor instead. -func (*Listener) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{0} -} - -func (x *Listener) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Listener) GetDirection() Direction { - if x != nil { - return x.Direction - } - return Direction_DIRECTION_UNSPECIFIED -} - -func (m *Listener) GetBindAddress() isListener_BindAddress { - if m != nil { - return m.BindAddress - } - return nil -} - -func (x *Listener) GetHostPort() *HostPortAddress { - if x, ok := x.GetBindAddress().(*Listener_HostPort); ok { - return x.HostPort - } - return nil -} - -func (x *Listener) GetUnixSocket() *UnixSocketAddress { - if x, ok := x.GetBindAddress().(*Listener_UnixSocket); ok { - return x.UnixSocket - } - return nil -} - -func (x *Listener) GetRouters() []*Router { - if x != nil { - return x.Routers - } - return nil -} - -func (x *Listener) GetDefaultRouter() *Router { - if x != nil { - return x.DefaultRouter - } - return nil -} - -func (x *Listener) GetCapabilities() []Capability { - if x != nil { - return x.Capabilities - } - return nil -} - -func (x *Listener) GetBalanceConnections() BalanceConnections { - if x != nil { - return x.BalanceConnections - } - return BalanceConnections_BALANCE_CONNECTIONS_DEFAULT -} - -func (x *Listener) GetEscapeHatchListener() string { - if x != nil { - return x.EscapeHatchListener - } - return "" -} - -func (x *Listener) GetUseEscapeHatchTracing() bool { - if x != nil { - return x.UseEscapeHatchTracing - } - return false -} - -type isListener_BindAddress interface { - isListener_BindAddress() -} - -type Listener_HostPort struct { - HostPort *HostPortAddress `protobuf:"bytes,3,opt,name=host_port,json=hostPort,proto3,oneof"` -} - -type Listener_UnixSocket struct { - UnixSocket *UnixSocketAddress `protobuf:"bytes,4,opt,name=unix_socket,json=unixSocket,proto3,oneof"` -} - -func (*Listener_HostPort) isListener_BindAddress() {} - -func (*Listener_UnixSocket) isListener_BindAddress() {} - -type Router struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // match specifies how to match traffic coming into this listener. If the traffic matches, it will be routed to the - // destination. - Match *Match `protobuf:"bytes,1,opt,name=match,proto3" json:"match,omitempty"` - // Types that are assignable to Destination: - // - // *Router_L4 - // *Router_L7 - // *Router_Sni - Destination isRouter_Destination `protobuf_oneof:"destination"` - // inbound_tls is used by inbound listeners that terminate TLS. - InboundTls *TransportSocket `protobuf:"bytes,5,opt,name=inbound_tls,json=inboundTls,proto3" json:"inbound_tls,omitempty"` -} - -func (x *Router) Reset() { - *x = Router{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Router) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Router) ProtoMessage() {} - -func (x *Router) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Router.ProtoReflect.Descriptor instead. -func (*Router) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{1} -} - -func (x *Router) GetMatch() *Match { - if x != nil { - return x.Match - } - return nil -} - -func (m *Router) GetDestination() isRouter_Destination { - if m != nil { - return m.Destination - } - return nil -} - -func (x *Router) GetL4() *L4Destination { - if x, ok := x.GetDestination().(*Router_L4); ok { - return x.L4 - } - return nil -} - -func (x *Router) GetL7() *L7Destination { - if x, ok := x.GetDestination().(*Router_L7); ok { - return x.L7 - } - return nil -} - -func (x *Router) GetSni() *SNIDestination { - if x, ok := x.GetDestination().(*Router_Sni); ok { - return x.Sni - } - return nil -} - -func (x *Router) GetInboundTls() *TransportSocket { - if x != nil { - return x.InboundTls - } - return nil -} - -type isRouter_Destination interface { - isRouter_Destination() -} - -type Router_L4 struct { - // l4 is an l4 destination to route to, which will have a reference to a cluster. - L4 *L4Destination `protobuf:"bytes,2,opt,name=l4,proto3,oneof"` -} - -type Router_L7 struct { - // l7 is an l7 destination to route to, which will have a reference to a route. - L7 *L7Destination `protobuf:"bytes,3,opt,name=l7,proto3,oneof"` -} - -type Router_Sni struct { - // sni is an SNI destination, which means there will be no references, but the SNI name will be tied to the cluster - // name, so we should generate all clusters. - Sni *SNIDestination `protobuf:"bytes,4,opt,name=sni,proto3,oneof"` -} - -func (*Router_L4) isRouter_Destination() {} - -func (*Router_L7) isRouter_Destination() {} - -func (*Router_Sni) isRouter_Destination() {} - -type Match struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AlpnProtocols []string `protobuf:"bytes,1,rep,name=alpn_protocols,json=alpnProtocols,proto3" json:"alpn_protocols,omitempty"` - DestinationPort *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=destination_port,json=destinationPort,proto3" json:"destination_port,omitempty"` - PrefixRanges []*CidrRange `protobuf:"bytes,3,rep,name=prefix_ranges,json=prefixRanges,proto3" json:"prefix_ranges,omitempty"` - SourcePrefixRanges []*CidrRange `protobuf:"bytes,4,rep,name=source_prefix_ranges,json=sourcePrefixRanges,proto3" json:"source_prefix_ranges,omitempty"` - // server_names matches based on SNI of the incoming request. - ServerNames []string `protobuf:"bytes,5,rep,name=server_names,json=serverNames,proto3" json:"server_names,omitempty"` -} - -func (x *Match) Reset() { - *x = Match{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Match) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Match) ProtoMessage() {} - -func (x *Match) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Match.ProtoReflect.Descriptor instead. -func (*Match) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{2} -} - -func (x *Match) GetAlpnProtocols() []string { - if x != nil { - return x.AlpnProtocols - } - return nil -} - -func (x *Match) GetDestinationPort() *wrapperspb.UInt32Value { - if x != nil { - return x.DestinationPort - } - return nil -} - -func (x *Match) GetPrefixRanges() []*CidrRange { - if x != nil { - return x.PrefixRanges - } - return nil -} - -func (x *Match) GetSourcePrefixRanges() []*CidrRange { - if x != nil { - return x.SourcePrefixRanges - } - return nil -} - -func (x *Match) GetServerNames() []string { - if x != nil { - return x.ServerNames - } - return nil -} - -type CidrRange struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AddressPrefix string `protobuf:"bytes,1,opt,name=address_prefix,json=addressPrefix,proto3" json:"address_prefix,omitempty"` - PrefixLen *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=prefix_len,json=prefixLen,proto3" json:"prefix_len,omitempty"` -} - -func (x *CidrRange) Reset() { - *x = CidrRange{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CidrRange) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CidrRange) ProtoMessage() {} - -func (x *CidrRange) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CidrRange.ProtoReflect.Descriptor instead. -func (*CidrRange) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{3} -} - -func (x *CidrRange) GetAddressPrefix() string { - if x != nil { - return x.AddressPrefix - } - return "" -} - -func (x *CidrRange) GetPrefixLen() *wrapperspb.UInt32Value { - if x != nil { - return x.PrefixLen - } - return nil -} - -type L4Destination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // destination is one or more clusters to route to. - // - // Types that are assignable to Destination: - // - // *L4Destination_Cluster - // *L4Destination_WeightedClusters - Destination isL4Destination_Destination `protobuf_oneof:"destination"` - // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - StatPrefix string `protobuf:"bytes,3,opt,name=stat_prefix,json=statPrefix,proto3" json:"stat_prefix,omitempty"` - // traffic_permissions is a list of traffic permissions for this destination. - TrafficPermissions *TrafficPermissions `protobuf:"bytes,4,opt,name=traffic_permissions,json=trafficPermissions,proto3" json:"traffic_permissions,omitempty"` - // max_inbound_connections specifies how many connections this destination can accept. - MaxInboundConnections uint64 `protobuf:"varint,5,opt,name=max_inbound_connections,json=maxInboundConnections,proto3" json:"max_inbound_connections,omitempty"` -} - -func (x *L4Destination) Reset() { - *x = L4Destination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L4Destination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L4Destination) ProtoMessage() {} - -func (x *L4Destination) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use L4Destination.ProtoReflect.Descriptor instead. -func (*L4Destination) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{4} -} - -func (m *L4Destination) GetDestination() isL4Destination_Destination { - if m != nil { - return m.Destination - } - return nil -} - -func (x *L4Destination) GetCluster() *DestinationCluster { - if x, ok := x.GetDestination().(*L4Destination_Cluster); ok { - return x.Cluster - } - return nil -} - -func (x *L4Destination) GetWeightedClusters() *L4WeightedClusterGroup { - if x, ok := x.GetDestination().(*L4Destination_WeightedClusters); ok { - return x.WeightedClusters - } - return nil -} - -func (x *L4Destination) GetStatPrefix() string { - if x != nil { - return x.StatPrefix - } - return "" -} - -func (x *L4Destination) GetTrafficPermissions() *TrafficPermissions { - if x != nil { - return x.TrafficPermissions - } - return nil -} - -func (x *L4Destination) GetMaxInboundConnections() uint64 { - if x != nil { - return x.MaxInboundConnections - } - return 0 -} - -type isL4Destination_Destination interface { - isL4Destination_Destination() -} - -type L4Destination_Cluster struct { - Cluster *DestinationCluster `protobuf:"bytes,1,opt,name=cluster,proto3,oneof"` -} - -type L4Destination_WeightedClusters struct { - WeightedClusters *L4WeightedClusterGroup `protobuf:"bytes,2,opt,name=weighted_clusters,json=weightedClusters,proto3,oneof"` -} - -func (*L4Destination_Cluster) isL4Destination_Destination() {} - -func (*L4Destination_WeightedClusters) isL4Destination_Destination() {} - -type L7DestinationRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name is a key in the top level routes map. This specifies which route to go to in this L7 destination. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *L7DestinationRoute) Reset() { - *x = L7DestinationRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L7DestinationRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L7DestinationRoute) ProtoMessage() {} - -func (x *L7DestinationRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use L7DestinationRoute.ProtoReflect.Descriptor instead. -func (*L7DestinationRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{5} -} - -func (x *L7DestinationRoute) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -type L7Destination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // route specifies which route to go to in this L7 destination. - Route *L7DestinationRoute `protobuf:"bytes,1,opt,name=route,proto3" json:"route,omitempty"` - // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - StatPrefix string `protobuf:"bytes,2,opt,name=stat_prefix,json=statPrefix,proto3" json:"stat_prefix,omitempty"` - // protocol for the destination. - Protocol L7Protocol `protobuf:"varint,3,opt,name=protocol,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.L7Protocol" json:"protocol,omitempty"` - // traffic_permissions is a list of intentions for this destination. - TrafficPermissions *TrafficPermissions `protobuf:"bytes,4,opt,name=traffic_permissions,json=trafficPermissions,proto3" json:"traffic_permissions,omitempty"` - // include_xfcc specifies whether to add an xfcc policy for handling xfcc headers. - IncludeXfccPolicy bool `protobuf:"varint,5,opt,name=include_xfcc_policy,json=includeXfccPolicy,proto3" json:"include_xfcc_policy,omitempty"` - // xfcc_policy determines how to handle xfcc headers. - XfccPolicy XFCCPolicy `protobuf:"varint,6,opt,name=xfcc_policy,json=xfccPolicy,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.XFCCPolicy" json:"xfcc_policy,omitempty"` - // parse_xfcc_headers determines whether to add filters to parse xfcc headers on incoming connections. - ParseXfccHeaders bool `protobuf:"varint,7,opt,name=parse_xfcc_headers,json=parseXfccHeaders,proto3" json:"parse_xfcc_headers,omitempty"` - // static_route specifies whether this is a static route that is inlined in the listener filter. This is required to - // match existing xds config. - StaticRoute bool `protobuf:"varint,8,opt,name=static_route,json=staticRoute,proto3" json:"static_route,omitempty"` - // max_inbound_connections specifies how many connections this destination can accept. - MaxInboundConnections uint64 `protobuf:"varint,9,opt,name=max_inbound_connections,json=maxInboundConnections,proto3" json:"max_inbound_connections,omitempty"` -} - -func (x *L7Destination) Reset() { - *x = L7Destination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *L7Destination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*L7Destination) ProtoMessage() {} - -func (x *L7Destination) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use L7Destination.ProtoReflect.Descriptor instead. -func (*L7Destination) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{6} -} - -func (x *L7Destination) GetRoute() *L7DestinationRoute { - if x != nil { - return x.Route - } - return nil -} - -func (x *L7Destination) GetStatPrefix() string { - if x != nil { - return x.StatPrefix - } - return "" -} - -func (x *L7Destination) GetProtocol() L7Protocol { - if x != nil { - return x.Protocol - } - return L7Protocol_L7_PROTOCOL_HTTP -} - -func (x *L7Destination) GetTrafficPermissions() *TrafficPermissions { - if x != nil { - return x.TrafficPermissions - } - return nil -} - -func (x *L7Destination) GetIncludeXfccPolicy() bool { - if x != nil { - return x.IncludeXfccPolicy - } - return false -} - -func (x *L7Destination) GetXfccPolicy() XFCCPolicy { - if x != nil { - return x.XfccPolicy - } - return XFCCPolicy_XFCC_POLICY_SANITIZE -} - -func (x *L7Destination) GetParseXfccHeaders() bool { - if x != nil { - return x.ParseXfccHeaders - } - return false -} - -func (x *L7Destination) GetStaticRoute() bool { - if x != nil { - return x.StaticRoute - } - return false -} - -func (x *L7Destination) GetMaxInboundConnections() uint64 { - if x != nil { - return x.MaxInboundConnections - } - return 0 -} - -type SNIDestination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - StatPrefix string `protobuf:"bytes,1,opt,name=stat_prefix,json=statPrefix,proto3" json:"stat_prefix,omitempty"` -} - -func (x *SNIDestination) Reset() { - *x = SNIDestination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SNIDestination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SNIDestination) ProtoMessage() {} - -func (x *SNIDestination) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SNIDestination.ProtoReflect.Descriptor instead. -func (*SNIDestination) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP(), []int{7} -} - -func (x *SNIDestination) GetStatPrefix() string { - if x != nil { - return x.StatPrefix - } - return "" -} - -var File_pbmesh_v2beta1_pbproxystate_listener_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDesc = []byte{ - 0x0a, 0x2a, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x6c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, - 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, - 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x66, - 0x66, 0x69, 0x63, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x32, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa4, 0x06, 0x0a, 0x08, 0x4c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x53, 0x0a, 0x09, 0x64, 0x69, - 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x5a, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, - 0x48, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, - 0x00, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x60, 0x0a, 0x0b, 0x75, - 0x6e, 0x69, 0x78, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x6e, - 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, - 0x00, 0x52, 0x0a, 0x75, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x4c, 0x0a, - 0x07, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x72, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x73, 0x12, 0x59, 0x0a, 0x0e, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, - 0x65, 0x73, 0x12, 0x6f, 0x0a, 0x13, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x12, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x68, 0x61, - 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x13, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, 0x74, 0x63, 0x68, 0x4c, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x18, 0x75, 0x73, 0x65, 0x5f, 0x65, - 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x74, 0x72, 0x61, 0x63, - 0x69, 0x6e, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x75, 0x73, 0x65, 0x45, 0x73, - 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, 0x74, 0x63, 0x68, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, - 0x42, 0x0e, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x22, 0xa8, 0x03, 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x47, 0x0a, 0x05, 0x6d, - 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x6d, - 0x61, 0x74, 0x63, 0x68, 0x12, 0x4b, 0x0a, 0x02, 0x6c, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x34, - 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x02, 0x6c, - 0x34, 0x12, 0x4b, 0x0a, 0x02, 0x6c, 0x37, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x37, 0x44, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x02, 0x6c, 0x37, 0x12, 0x4e, - 0x0a, 0x03, 0x73, 0x6e, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x4e, 0x49, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x03, 0x73, 0x6e, 0x69, 0x12, 0x5c, - 0x0a, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6c, 0x73, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, - 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x6c, 0x73, 0x42, 0x0d, 0x0a, 0x0b, - 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xdf, 0x02, 0x0a, 0x05, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x70, 0x6e, 0x5f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x61, - 0x6c, 0x70, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12, 0x47, 0x0a, 0x10, - 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x72, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5a, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, - 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, - 0x6e, 0x67, 0x65, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x61, 0x6e, 0x67, 0x65, - 0x73, 0x12, 0x67, 0x0a, 0x14, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x69, 0x64, - 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x12, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x6f, 0x0a, - 0x09, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, - 0x78, 0x12, 0x3b, 0x0a, 0x0a, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x09, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, 0x65, 0x6e, 0x22, 0xb7, - 0x03, 0x0a, 0x0d, 0x4c, 0x34, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x5a, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x71, 0x0a, 0x11, - 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x34, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x10, 0x77, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, - 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, - 0x12, 0x6f, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x70, 0x65, 0x72, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x66, 0x66, - 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x74, - 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x36, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x0d, 0x0a, 0x0b, 0x64, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x28, 0x0a, 0x12, 0x4c, 0x37, 0x44, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x22, 0xdd, 0x04, 0x0a, 0x0d, 0x4c, 0x37, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x54, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x4c, 0x37, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, - 0x61, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x73, 0x74, 0x61, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x52, 0x0a, 0x08, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x37, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, - 0x6f, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, - 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x74, 0x72, - 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x2e, 0x0a, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x78, 0x66, 0x63, 0x63, - 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x58, 0x66, 0x63, 0x63, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x12, 0x57, 0x0a, 0x0b, 0x78, 0x66, 0x63, 0x63, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x58, 0x46, 0x43, 0x43, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0a, 0x78, - 0x66, 0x63, 0x63, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x61, 0x72, - 0x73, 0x65, 0x5f, 0x78, 0x66, 0x63, 0x63, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x70, 0x61, 0x72, 0x73, 0x65, 0x58, 0x66, 0x63, 0x63, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x63, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x6d, 0x61, - 0x78, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x6d, 0x61, 0x78, - 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x22, 0x31, 0x0a, 0x0e, 0x53, 0x4e, 0x49, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x70, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x50, - 0x72, 0x65, 0x66, 0x69, 0x78, 0x2a, 0x55, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, - 0x11, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x42, 0x4f, 0x55, - 0x4e, 0x44, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x4f, 0x55, 0x54, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x2a, 0x54, 0x0a, 0x12, - 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x43, 0x4f, - 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, - 0x54, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x43, - 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x45, 0x58, 0x41, 0x43, 0x54, - 0x10, 0x01, 0x2a, 0x71, 0x0a, 0x0a, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, - 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x54, - 0x52, 0x41, 0x4e, 0x53, 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x25, 0x0a, 0x21, - 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x4c, 0x37, 0x5f, 0x50, 0x52, - 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, 0x49, 0x4f, - 0x4e, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, - 0x59, 0x5f, 0x4c, 0x34, 0x5f, 0x54, 0x4c, 0x53, 0x5f, 0x49, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x2a, 0xa7, 0x01, 0x0a, 0x0a, 0x58, 0x46, 0x43, 0x43, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x12, 0x18, 0x0a, 0x14, 0x58, 0x46, 0x43, 0x43, 0x5f, 0x50, 0x4f, 0x4c, - 0x49, 0x43, 0x59, 0x5f, 0x53, 0x41, 0x4e, 0x49, 0x54, 0x49, 0x5a, 0x45, 0x10, 0x00, 0x12, 0x1c, - 0x0a, 0x18, 0x58, 0x46, 0x43, 0x43, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x46, 0x4f, - 0x52, 0x57, 0x41, 0x52, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, - 0x58, 0x46, 0x43, 0x43, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x50, 0x50, 0x45, - 0x4e, 0x44, 0x5f, 0x46, 0x4f, 0x52, 0x57, 0x41, 0x52, 0x44, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, - 0x58, 0x46, 0x43, 0x43, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x53, 0x41, 0x4e, 0x49, - 0x54, 0x49, 0x5a, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x10, 0x03, 0x12, 0x23, 0x0a, 0x1f, 0x58, 0x46, - 0x43, 0x43, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x41, 0x4c, 0x57, 0x41, 0x59, 0x53, - 0x5f, 0x46, 0x4f, 0x52, 0x57, 0x41, 0x52, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x04, 0x2a, - 0x4f, 0x0a, 0x0a, 0x4c, 0x37, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x14, 0x0a, - 0x10, 0x4c, 0x37, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, - 0x50, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4c, 0x37, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, - 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x32, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x37, - 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x47, 0x52, 0x50, 0x43, 0x10, 0x02, - 0x42, 0xd3, 0x02, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x42, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, - 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, - 0x56, 0x50, 0xaa, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, - 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, - 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x36, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, - 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_listener_proto_enumTypes = make([]protoimpl.EnumInfo, 5) -var file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes = make([]protoimpl.MessageInfo, 8) -var file_pbmesh_v2beta1_pbproxystate_listener_proto_goTypes = []interface{}{ - (Direction)(0), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.Direction - (BalanceConnections)(0), // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.BalanceConnections - (Capability)(0), // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.Capability - (XFCCPolicy)(0), // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.XFCCPolicy - (L7Protocol)(0), // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.L7Protocol - (*Listener)(nil), // 5: hashicorp.consul.mesh.v2beta1.pbproxystate.Listener - (*Router)(nil), // 6: hashicorp.consul.mesh.v2beta1.pbproxystate.Router - (*Match)(nil), // 7: hashicorp.consul.mesh.v2beta1.pbproxystate.Match - (*CidrRange)(nil), // 8: hashicorp.consul.mesh.v2beta1.pbproxystate.CidrRange - (*L4Destination)(nil), // 9: hashicorp.consul.mesh.v2beta1.pbproxystate.L4Destination - (*L7DestinationRoute)(nil), // 10: hashicorp.consul.mesh.v2beta1.pbproxystate.L7DestinationRoute - (*L7Destination)(nil), // 11: hashicorp.consul.mesh.v2beta1.pbproxystate.L7Destination - (*SNIDestination)(nil), // 12: hashicorp.consul.mesh.v2beta1.pbproxystate.SNIDestination - (*HostPortAddress)(nil), // 13: hashicorp.consul.mesh.v2beta1.pbproxystate.HostPortAddress - (*UnixSocketAddress)(nil), // 14: hashicorp.consul.mesh.v2beta1.pbproxystate.UnixSocketAddress - (*TransportSocket)(nil), // 15: hashicorp.consul.mesh.v2beta1.pbproxystate.TransportSocket - (*wrapperspb.UInt32Value)(nil), // 16: google.protobuf.UInt32Value - (*DestinationCluster)(nil), // 17: hashicorp.consul.mesh.v2beta1.pbproxystate.DestinationCluster - (*L4WeightedClusterGroup)(nil), // 18: hashicorp.consul.mesh.v2beta1.pbproxystate.L4WeightedClusterGroup - (*TrafficPermissions)(nil), // 19: hashicorp.consul.mesh.v2beta1.pbproxystate.TrafficPermissions -} -var file_pbmesh_v2beta1_pbproxystate_listener_proto_depIdxs = []int32{ - 0, // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.Listener.direction:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Direction - 13, // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.Listener.host_port:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.HostPortAddress - 14, // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.Listener.unix_socket:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.UnixSocketAddress - 6, // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.Listener.routers:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Router - 6, // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.Listener.default_router:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Router - 2, // 5: hashicorp.consul.mesh.v2beta1.pbproxystate.Listener.capabilities:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Capability - 1, // 6: hashicorp.consul.mesh.v2beta1.pbproxystate.Listener.balance_connections:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.BalanceConnections - 7, // 7: hashicorp.consul.mesh.v2beta1.pbproxystate.Router.match:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Match - 9, // 8: hashicorp.consul.mesh.v2beta1.pbproxystate.Router.l4:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.L4Destination - 11, // 9: hashicorp.consul.mesh.v2beta1.pbproxystate.Router.l7:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.L7Destination - 12, // 10: hashicorp.consul.mesh.v2beta1.pbproxystate.Router.sni:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.SNIDestination - 15, // 11: hashicorp.consul.mesh.v2beta1.pbproxystate.Router.inbound_tls:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TransportSocket - 16, // 12: hashicorp.consul.mesh.v2beta1.pbproxystate.Match.destination_port:type_name -> google.protobuf.UInt32Value - 8, // 13: hashicorp.consul.mesh.v2beta1.pbproxystate.Match.prefix_ranges:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.CidrRange - 8, // 14: hashicorp.consul.mesh.v2beta1.pbproxystate.Match.source_prefix_ranges:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.CidrRange - 16, // 15: hashicorp.consul.mesh.v2beta1.pbproxystate.CidrRange.prefix_len:type_name -> google.protobuf.UInt32Value - 17, // 16: hashicorp.consul.mesh.v2beta1.pbproxystate.L4Destination.cluster:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.DestinationCluster - 18, // 17: hashicorp.consul.mesh.v2beta1.pbproxystate.L4Destination.weighted_clusters:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.L4WeightedClusterGroup - 19, // 18: hashicorp.consul.mesh.v2beta1.pbproxystate.L4Destination.traffic_permissions:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TrafficPermissions - 10, // 19: hashicorp.consul.mesh.v2beta1.pbproxystate.L7Destination.route:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.L7DestinationRoute - 4, // 20: hashicorp.consul.mesh.v2beta1.pbproxystate.L7Destination.protocol:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.L7Protocol - 19, // 21: hashicorp.consul.mesh.v2beta1.pbproxystate.L7Destination.traffic_permissions:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TrafficPermissions - 3, // 22: hashicorp.consul.mesh.v2beta1.pbproxystate.L7Destination.xfcc_policy:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.XFCCPolicy - 23, // [23:23] is the sub-list for method output_type - 23, // [23:23] is the sub-list for method input_type - 23, // [23:23] is the sub-list for extension type_name - 23, // [23:23] is the sub-list for extension extendee - 0, // [0:23] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_listener_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_listener_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_listener_proto != nil { - return - } - file_pbmesh_v2beta1_pbproxystate_address_proto_init() - file_pbmesh_v2beta1_pbproxystate_cluster_proto_init() - file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_init() - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Listener); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Router); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Match); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CidrRange); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L4Destination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L7DestinationRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*L7Destination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SNIDestination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*Listener_HostPort)(nil), - (*Listener_UnixSocket)(nil), - } - file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*Router_L4)(nil), - (*Router_L7)(nil), - (*Router_Sni)(nil), - } - file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes[4].OneofWrappers = []interface{}{ - (*L4Destination_Cluster)(nil), - (*L4Destination_WeightedClusters)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDesc, - NumEnums: 5, - NumMessages: 8, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_listener_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_listener_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_pbproxystate_listener_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_pbproxystate_listener_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_listener_proto = out.File - file_pbmesh_v2beta1_pbproxystate_listener_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_listener_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_listener_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/listener.proto b/proto-public/pbmesh/v2beta1/pbproxystate/listener.proto deleted file mode 100644 index 95ba97556b9d..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/listener.proto +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1.pbproxystate; - -import "google/protobuf/wrappers.proto"; -import "pbmesh/v2beta1/pbproxystate/address.proto"; -import "pbmesh/v2beta1/pbproxystate/cluster.proto"; -import "pbmesh/v2beta1/pbproxystate/traffic_permissions.proto"; -import "pbmesh/v2beta1/pbproxystate/transport_socket.proto"; - -message Listener { - // name is the name of the listener. - string name = 1; - // direction tells the listener the direction of traffic. - Direction direction = 2; - // bind_address describes where to listen. - oneof bind_address { - HostPortAddress host_port = 3; - UnixSocketAddress unix_socket = 4; - } - - // routers describes how to route traffic from this listener. - repeated Router routers = 5; - // default_router describes where to route if none of the other router matches match the connection. - Router default_router = 6; - // capabilities describe Envoy proxy functionality to enable. These map closely to Envoy listener filters. - repeated Capability capabilities = 7; - // balance_connections configures how the listener should balance connections. - BalanceConnections balance_connections = 8; - // escape_hatch_listener_json configures a user configured escape hatch listener. - string escape_hatch_listener = 9; - // use_escape_hatch_tracing configures whether to use the top level user configured tracing escape hatch for this listener. - bool use_escape_hatch_tracing = 10; -} - -// +kubebuilder:validation:Enum=DIRECTION_UNSPECIFIED;DIRECTION_INBOUND;DIRECTION_OUTBOUND -// +kubebuilder:validation:Type=string -enum Direction { - // DIRECTION_UNSPECIFIED is used by mesh gateway listeners. - DIRECTION_UNSPECIFIED = 0; - DIRECTION_INBOUND = 1; - DIRECTION_OUTBOUND = 2; -} - -// +kubebuilder:validation:Enum=BALANCE_CONNECTIONS_DEFAULT;BALANCE_CONNECTIONS_EXACT -// +kubebuilder:validation:Type=string -enum BalanceConnections { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - BALANCE_CONNECTIONS_DEFAULT = 0; - BALANCE_CONNECTIONS_EXACT = 1; -} - -// Capabilities map to proxy functionality to enable. These enable tproxy, l7 protocol/alpn inspection, or l4 sni/alpn inspection. -// -// +kubebuilder:validation:Enum=CAPABILITY_TRANSPARENT;CAPABILITY_L7_PROTOCOL_INSPECTION;CAPABILITY_L4_TLS_INSPECTION -// +kubebuilder:validation:Type=string -enum Capability { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - CAPABILITY_TRANSPARENT = 0; - CAPABILITY_L7_PROTOCOL_INSPECTION = 1; - CAPABILITY_L4_TLS_INSPECTION = 2; -} - -message Router { - // match specifies how to match traffic coming into this listener. If the traffic matches, it will be routed to the - // destination. - Match match = 1; - oneof destination { - // l4 is an l4 destination to route to, which will have a reference to a cluster. - L4Destination l4 = 2; - // l7 is an l7 destination to route to, which will have a reference to a route. - L7Destination l7 = 3; - // sni is an SNI destination, which means there will be no references, but the SNI name will be tied to the cluster - // name, so we should generate all clusters. - SNIDestination sni = 4; - } - // inbound_tls is used by inbound listeners that terminate TLS. - TransportSocket inbound_tls = 5; -} - -message Match { - repeated string alpn_protocols = 1; - google.protobuf.UInt32Value destination_port = 2; - repeated CidrRange prefix_ranges = 3; - repeated CidrRange source_prefix_ranges = 4; - // server_names matches based on SNI of the incoming request. - repeated string server_names = 5; -} - -message CidrRange { - string address_prefix = 1; - google.protobuf.UInt32Value prefix_len = 2; -} - -message L4Destination { - // destination is one or more clusters to route to. - oneof destination { - DestinationCluster cluster = 1; - L4WeightedClusterGroup weighted_clusters = 2; - } - // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - string stat_prefix = 3; - // traffic_permissions is a list of traffic permissions for this destination. - TrafficPermissions traffic_permissions = 4; - // max_inbound_connections specifies how many connections this destination can accept. - uint64 max_inbound_connections = 5; -} - -message L7DestinationRoute { - // name is a key in the top level routes map. This specifies which route to go to in this L7 destination. - string name = 1; -} - -message L7Destination { - // route specifies which route to go to in this L7 destination. - L7DestinationRoute route = 1; - // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - string stat_prefix = 2; - // protocol for the destination. - L7Protocol protocol = 3; - // traffic_permissions is a list of intentions for this destination. - TrafficPermissions traffic_permissions = 4; - // include_xfcc specifies whether to add an xfcc policy for handling xfcc headers. - bool include_xfcc_policy = 5; - // xfcc_policy determines how to handle xfcc headers. - XFCCPolicy xfcc_policy = 6; - // parse_xfcc_headers determines whether to add filters to parse xfcc headers on incoming connections. - bool parse_xfcc_headers = 7; - // static_route specifies whether this is a static route that is inlined in the listener filter. This is required to - // match existing xds config. - bool static_route = 8; - // max_inbound_connections specifies how many connections this destination can accept. - uint64 max_inbound_connections = 9; -} - -// +kubebuilder:validation:Enum=XFCC_POLICY_SANITIZE;XFCC_POLICY_FORWARD_ONLY;XFCC_POLICY_APPEND_FORWARD;XFCC_POLICY_SANITIZE_SET;XFCC_POLICY_ALWAYS_FORWARD_ONLY -// +kubebuilder:validation:Type=string -enum XFCCPolicy { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - // Do not send the XFCC header to the next hop. This is the default value. - XFCC_POLICY_SANITIZE = 0; - // When the client connection is mTLS (Mutual TLS), forward the XFCC header - // in the request. - XFCC_POLICY_FORWARD_ONLY = 1; - // When the client connection is mTLS, append the client certificate - // information to the request’s XFCC header and forward it. - XFCC_POLICY_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. - XFCC_POLICY_SANITIZE_SET = 3; - // Always forward the XFCC header in the request, regardless of whether the - // client connection is mTLS. - XFCC_POLICY_ALWAYS_FORWARD_ONLY = 4; -} - -// +kubebuilder:validation:Enum=L7_PROTOCOL_HTTP;L7_PROTOCOL_HTTP2;L7_PROTOCOL_GRPC -// +kubebuilder:validation:Type=string -enum L7Protocol { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - L7_PROTOCOL_HTTP = 0; - L7_PROTOCOL_HTTP2 = 1; - L7_PROTOCOL_GRPC = 2; -} - -message SNIDestination { - // stat_prefix is for compatibility with v1 xds configuration, so it is generated in exactly the same way. - string stat_prefix = 1; -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/listener_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/listener_deepcopy.gen.go deleted file mode 100644 index c721f40cbb91..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/listener_deepcopy.gen.go +++ /dev/null @@ -1,174 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package pbproxystate - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using Listener within kubernetes types, where deepcopy-gen is used. -func (in *Listener) DeepCopyInto(out *Listener) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Listener. Required by controller-gen. -func (in *Listener) DeepCopy() *Listener { - if in == nil { - return nil - } - out := new(Listener) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Listener. Required by controller-gen. -func (in *Listener) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Router within kubernetes types, where deepcopy-gen is used. -func (in *Router) DeepCopyInto(out *Router) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Router. Required by controller-gen. -func (in *Router) DeepCopy() *Router { - if in == nil { - return nil - } - out := new(Router) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Router. Required by controller-gen. -func (in *Router) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Match within kubernetes types, where deepcopy-gen is used. -func (in *Match) DeepCopyInto(out *Match) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Match. Required by controller-gen. -func (in *Match) DeepCopy() *Match { - if in == nil { - return nil - } - out := new(Match) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Match. Required by controller-gen. -func (in *Match) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using CidrRange within kubernetes types, where deepcopy-gen is used. -func (in *CidrRange) DeepCopyInto(out *CidrRange) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CidrRange. Required by controller-gen. -func (in *CidrRange) DeepCopy() *CidrRange { - if in == nil { - return nil - } - out := new(CidrRange) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new CidrRange. Required by controller-gen. -func (in *CidrRange) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using L4Destination within kubernetes types, where deepcopy-gen is used. -func (in *L4Destination) DeepCopyInto(out *L4Destination) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new L4Destination. Required by controller-gen. -func (in *L4Destination) DeepCopy() *L4Destination { - if in == nil { - return nil - } - out := new(L4Destination) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new L4Destination. Required by controller-gen. -func (in *L4Destination) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using L7DestinationRoute within kubernetes types, where deepcopy-gen is used. -func (in *L7DestinationRoute) DeepCopyInto(out *L7DestinationRoute) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new L7DestinationRoute. Required by controller-gen. -func (in *L7DestinationRoute) DeepCopy() *L7DestinationRoute { - if in == nil { - return nil - } - out := new(L7DestinationRoute) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new L7DestinationRoute. Required by controller-gen. -func (in *L7DestinationRoute) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using L7Destination within kubernetes types, where deepcopy-gen is used. -func (in *L7Destination) DeepCopyInto(out *L7Destination) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new L7Destination. Required by controller-gen. -func (in *L7Destination) DeepCopy() *L7Destination { - if in == nil { - return nil - } - out := new(L7Destination) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new L7Destination. Required by controller-gen. -func (in *L7Destination) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using SNIDestination within kubernetes types, where deepcopy-gen is used. -func (in *SNIDestination) DeepCopyInto(out *SNIDestination) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SNIDestination. Required by controller-gen. -func (in *SNIDestination) DeepCopy() *SNIDestination { - if in == nil { - return nil - } - out := new(SNIDestination) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new SNIDestination. Required by controller-gen. -func (in *SNIDestination) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/listener_json.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/listener_json.gen.go deleted file mode 100644 index fe77b7be1ffd..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/listener_json.gen.go +++ /dev/null @@ -1,99 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package pbproxystate - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for Listener -func (this *Listener) MarshalJSON() ([]byte, error) { - str, err := ListenerMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Listener -func (this *Listener) UnmarshalJSON(b []byte) error { - return ListenerUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Router -func (this *Router) MarshalJSON() ([]byte, error) { - str, err := ListenerMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Router -func (this *Router) UnmarshalJSON(b []byte) error { - return ListenerUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Match -func (this *Match) MarshalJSON() ([]byte, error) { - str, err := ListenerMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Match -func (this *Match) UnmarshalJSON(b []byte) error { - return ListenerUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for CidrRange -func (this *CidrRange) MarshalJSON() ([]byte, error) { - str, err := ListenerMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for CidrRange -func (this *CidrRange) UnmarshalJSON(b []byte) error { - return ListenerUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for L4Destination -func (this *L4Destination) MarshalJSON() ([]byte, error) { - str, err := ListenerMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for L4Destination -func (this *L4Destination) UnmarshalJSON(b []byte) error { - return ListenerUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for L7DestinationRoute -func (this *L7DestinationRoute) MarshalJSON() ([]byte, error) { - str, err := ListenerMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for L7DestinationRoute -func (this *L7DestinationRoute) UnmarshalJSON(b []byte) error { - return ListenerUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for L7Destination -func (this *L7Destination) MarshalJSON() ([]byte, error) { - str, err := ListenerMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for L7Destination -func (this *L7Destination) UnmarshalJSON(b []byte) error { - return ListenerUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for SNIDestination -func (this *SNIDestination) MarshalJSON() ([]byte, error) { - str, err := ListenerMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for SNIDestination -func (this *SNIDestination) UnmarshalJSON(b []byte) error { - return ListenerUnmarshaler.Unmarshal(b, this) -} - -var ( - ListenerMarshaler = &protojson.MarshalOptions{} - ListenerUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/protocol.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/protocol.pb.go deleted file mode 100644 index a14cdf986de6..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/protocol.pb.go +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/protocol.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=PROTOCOL_UNSPECIFIED;PROTOCOL_TCP;PROTOCOL_HTTP;PROTOCOL_HTTP2;PROTOCOL_GRPC -// +kubebuilder:validation:Type=string -type Protocol int32 - -const ( - Protocol_PROTOCOL_UNSPECIFIED Protocol = 0 - Protocol_PROTOCOL_TCP Protocol = 1 - Protocol_PROTOCOL_HTTP Protocol = 2 - Protocol_PROTOCOL_HTTP2 Protocol = 3 - Protocol_PROTOCOL_GRPC Protocol = 4 - // Protocol Mesh indicates that this port can speak Consul's mTLS based mesh protocol. - Protocol_PROTOCOL_MESH Protocol = 5 -) - -// Enum value maps for Protocol. -var ( - Protocol_name = map[int32]string{ - 0: "PROTOCOL_UNSPECIFIED", - 1: "PROTOCOL_TCP", - 2: "PROTOCOL_HTTP", - 3: "PROTOCOL_HTTP2", - 4: "PROTOCOL_GRPC", - 5: "PROTOCOL_MESH", - } - Protocol_value = map[string]int32{ - "PROTOCOL_UNSPECIFIED": 0, - "PROTOCOL_TCP": 1, - "PROTOCOL_HTTP": 2, - "PROTOCOL_HTTP2": 3, - "PROTOCOL_GRPC": 4, - "PROTOCOL_MESH": 5, - } -) - -func (x Protocol) Enum() *Protocol { - p := new(Protocol) - *p = x - return p -} - -func (x Protocol) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Protocol) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_pbproxystate_protocol_proto_enumTypes[0].Descriptor() -} - -func (Protocol) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_pbproxystate_protocol_proto_enumTypes[0] -} - -func (x Protocol) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Protocol.Descriptor instead. -func (Protocol) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_protocol_proto_rawDescGZIP(), []int{0} -} - -var File_pbmesh_v2beta1_pbproxystate_protocol_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_protocol_proto_rawDesc = []byte{ - 0x0a, 0x2a, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2a, 0x83, 0x01, 0x0a, 0x08, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, - 0x4c, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x54, 0x43, 0x50, 0x10, - 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, - 0x54, 0x50, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, - 0x5f, 0x48, 0x54, 0x54, 0x50, 0x32, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x54, - 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x47, 0x52, 0x50, 0x43, 0x10, 0x04, 0x12, 0x11, 0x0a, 0x0d, 0x50, - 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x4d, 0x45, 0x53, 0x48, 0x10, 0x05, 0x42, 0xd3, - 0x02, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x42, 0x0d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, - 0xaa, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2a, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x36, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, - 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0xea, 0x02, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, - 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_protocol_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_protocol_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_protocol_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_protocol_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_protocol_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_protocol_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_protocol_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_protocol_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_protocol_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v2beta1_pbproxystate_protocol_proto_goTypes = []interface{}{ - (Protocol)(0), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.Protocol -} -var file_pbmesh_v2beta1_pbproxystate_protocol_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_protocol_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_protocol_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_protocol_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_protocol_proto_rawDesc, - NumEnums: 1, - NumMessages: 0, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_protocol_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_protocol_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_pbproxystate_protocol_proto_enumTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_protocol_proto = out.File - file_pbmesh_v2beta1_pbproxystate_protocol_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_protocol_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_protocol_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/protocol.proto b/proto-public/pbmesh/v2beta1/pbproxystate/protocol.proto deleted file mode 100644 index afe3ff17523e..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/protocol.proto +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1.pbproxystate; - -// +kubebuilder:validation:Enum=PROTOCOL_UNSPECIFIED;PROTOCOL_TCP;PROTOCOL_HTTP;PROTOCOL_HTTP2;PROTOCOL_GRPC -// +kubebuilder:validation:Type=string -enum Protocol { - PROTOCOL_UNSPECIFIED = 0; - PROTOCOL_TCP = 1; - PROTOCOL_HTTP = 2; - PROTOCOL_HTTP2 = 3; - PROTOCOL_GRPC = 4; - - // Protocol Mesh indicates that this port can speak Consul's mTLS based mesh protocol. - PROTOCOL_MESH = 5; -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/protocol_test.go b/proto-public/pbmesh/v2beta1/pbproxystate/protocol_test.go deleted file mode 100644 index 683f84452f13..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/protocol_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package pbproxystate - -import ( - "testing" - - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/stretchr/testify/require" -) - -// TestMirrorsCatalogProtocol ensures that there is no unintended drift between pbcatalog.Protocol and -// pbproxystate.Protocol. -func TestMirrorsCatalogProtocol(t *testing.T) { - require.Equal(t, pbcatalog.Protocol_value, Protocol_value, "pbcatalog.Protocol and pbproxystate.Protocol have diverged") - for i := range pbcatalog.Protocol_name { - require.Equal(t, pbcatalog.Protocol_name[i], Protocol_name[i], - "pbcatalog.Protocol and pbproxystate.Protocol ordinals do not match;"+ - " ordinals for equivalent values must match so that casting between them produces expected results") - } -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/references.pb.binary.go b/proto-public/pbmesh/v2beta1/pbproxystate/references.pb.binary.go deleted file mode 100644 index ddcc32fc5617..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/references.pb.binary.go +++ /dev/null @@ -1,38 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/pbproxystate/references.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LeafCertificateRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LeafCertificateRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TrustBundleRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TrustBundleRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *EndpointRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *EndpointRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/references.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/references.pb.go deleted file mode 100644 index c544d2803095..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/references.pb.go +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/references.proto - -package pbproxystate - -import ( - pbresource "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type LeafCertificateRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` - Partition string `protobuf:"bytes,3,opt,name=partition,proto3" json:"partition,omitempty"` - Host string `protobuf:"bytes,4,opt,name=host,proto3" json:"host,omitempty"` - Datacenter string `protobuf:"bytes,5,opt,name=datacenter,proto3" json:"datacenter,omitempty"` - DnsSan []string `protobuf:"bytes,6,rep,name=dns_san,json=dnsSan,proto3" json:"dns_san,omitempty"` -} - -func (x *LeafCertificateRef) Reset() { - *x = LeafCertificateRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_references_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LeafCertificateRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LeafCertificateRef) ProtoMessage() {} - -func (x *LeafCertificateRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_references_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LeafCertificateRef.ProtoReflect.Descriptor instead. -func (*LeafCertificateRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_references_proto_rawDescGZIP(), []int{0} -} - -func (x *LeafCertificateRef) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *LeafCertificateRef) GetNamespace() string { - if x != nil { - return x.Namespace - } - return "" -} - -func (x *LeafCertificateRef) GetPartition() string { - if x != nil { - return x.Partition - } - return "" -} - -func (x *LeafCertificateRef) GetHost() string { - if x != nil { - return x.Host - } - return "" -} - -func (x *LeafCertificateRef) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - -func (x *LeafCertificateRef) GetDnsSan() []string { - if x != nil { - return x.DnsSan - } - return nil -} - -type TrustBundleRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Peer string `protobuf:"bytes,1,opt,name=peer,proto3" json:"peer,omitempty"` - TrustDomain string `protobuf:"bytes,2,opt,name=trust_domain,json=trustDomain,proto3" json:"trust_domain,omitempty"` -} - -func (x *TrustBundleRef) Reset() { - *x = TrustBundleRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_references_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TrustBundleRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TrustBundleRef) ProtoMessage() {} - -func (x *TrustBundleRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_references_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TrustBundleRef.ProtoReflect.Descriptor instead. -func (*TrustBundleRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_references_proto_rawDescGZIP(), []int{1} -} - -func (x *TrustBundleRef) GetPeer() string { - if x != nil { - return x.Peer - } - return "" -} - -func (x *TrustBundleRef) GetTrustDomain() string { - if x != nil { - return x.TrustDomain - } - return "" -} - -type EndpointRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // id is the ServiceEndpoints resource id. - Id *pbresource.ID `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - // port is the name of the port in the ServiceEndpoints to generate the Endpoints from. - Port string `protobuf:"bytes,2,opt,name=port,proto3" json:"port,omitempty"` -} - -func (x *EndpointRef) Reset() { - *x = EndpointRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_references_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EndpointRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EndpointRef) ProtoMessage() {} - -func (x *EndpointRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_references_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EndpointRef.ProtoReflect.Descriptor instead. -func (*EndpointRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_references_proto_rawDescGZIP(), []int{2} -} - -func (x *EndpointRef) GetId() *pbresource.ID { - if x != nil { - return x.Id - } - return nil -} - -func (x *EndpointRef) GetPort() string { - if x != nil { - return x.Port - } - return "" -} - -var File_pbmesh_v2beta1_pbproxystate_references_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_references_proto_rawDesc = []byte{ - 0x0a, 0x2c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x72, 0x65, - 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x19, 0x70, 0x62, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb1, 0x01, 0x0a, 0x12, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, - 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, - 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, - 0x68, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, - 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x12, 0x17, 0x0a, 0x07, 0x64, 0x6e, 0x73, 0x5f, 0x73, 0x61, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x06, 0x64, 0x6e, 0x73, 0x53, 0x61, 0x6e, 0x22, 0x47, 0x0a, 0x0e, 0x54, 0x72, 0x75, - 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x12, - 0x21, 0x0a, 0x0c, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x72, 0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x22, 0x50, 0x0a, 0x0b, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, - 0x66, 0x12, 0x2d, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x70, 0x6f, 0x72, 0x74, 0x42, 0xd5, 0x02, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0f, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, - 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0xe2, 0x02, 0x36, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2e, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, - 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3a, 0x3a, - 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_references_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_references_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_references_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_references_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_references_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_references_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_references_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_references_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_references_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_pbmesh_v2beta1_pbproxystate_references_proto_goTypes = []interface{}{ - (*LeafCertificateRef)(nil), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.LeafCertificateRef - (*TrustBundleRef)(nil), // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.TrustBundleRef - (*EndpointRef)(nil), // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.EndpointRef - (*pbresource.ID)(nil), // 3: hashicorp.consul.resource.ID -} -var file_pbmesh_v2beta1_pbproxystate_references_proto_depIdxs = []int32{ - 3, // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.EndpointRef.id:type_name -> hashicorp.consul.resource.ID - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_references_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_references_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_references_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_pbproxystate_references_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LeafCertificateRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_references_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TrustBundleRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_references_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EndpointRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_references_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_references_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_references_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_pbproxystate_references_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_references_proto = out.File - file_pbmesh_v2beta1_pbproxystate_references_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_references_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_references_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/references.proto b/proto-public/pbmesh/v2beta1/pbproxystate/references.proto deleted file mode 100644 index b169019c603e..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/references.proto +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1.pbproxystate; - -import "pbresource/resource.proto"; - -message LeafCertificateRef { - string name = 1; - string namespace = 2; - string partition = 3; - string host = 4; - string datacenter = 5; - repeated string dns_san = 6; -} - -message TrustBundleRef { - string peer = 1; - string trust_domain = 2; -} - -message EndpointRef { - // id is the ServiceEndpoints resource id. - hashicorp.consul.resource.ID id = 1; - // port is the name of the port in the ServiceEndpoints to generate the Endpoints from. - string port = 2; -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/references_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/references_deepcopy.gen.go deleted file mode 100644 index 2cbe25a91750..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/references_deepcopy.gen.go +++ /dev/null @@ -1,69 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package pbproxystate - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using LeafCertificateRef within kubernetes types, where deepcopy-gen is used. -func (in *LeafCertificateRef) DeepCopyInto(out *LeafCertificateRef) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LeafCertificateRef. Required by controller-gen. -func (in *LeafCertificateRef) DeepCopy() *LeafCertificateRef { - if in == nil { - return nil - } - out := new(LeafCertificateRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new LeafCertificateRef. Required by controller-gen. -func (in *LeafCertificateRef) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using TrustBundleRef within kubernetes types, where deepcopy-gen is used. -func (in *TrustBundleRef) DeepCopyInto(out *TrustBundleRef) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustBundleRef. Required by controller-gen. -func (in *TrustBundleRef) DeepCopy() *TrustBundleRef { - if in == nil { - return nil - } - out := new(TrustBundleRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TrustBundleRef. Required by controller-gen. -func (in *TrustBundleRef) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using EndpointRef within kubernetes types, where deepcopy-gen is used. -func (in *EndpointRef) DeepCopyInto(out *EndpointRef) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointRef. Required by controller-gen. -func (in *EndpointRef) DeepCopy() *EndpointRef { - if in == nil { - return nil - } - out := new(EndpointRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new EndpointRef. Required by controller-gen. -func (in *EndpointRef) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/references_json.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/references_json.gen.go deleted file mode 100644 index 91a178b9b366..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/references_json.gen.go +++ /dev/null @@ -1,44 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package pbproxystate - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for LeafCertificateRef -func (this *LeafCertificateRef) MarshalJSON() ([]byte, error) { - str, err := ReferencesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for LeafCertificateRef -func (this *LeafCertificateRef) UnmarshalJSON(b []byte) error { - return ReferencesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for TrustBundleRef -func (this *TrustBundleRef) MarshalJSON() ([]byte, error) { - str, err := ReferencesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TrustBundleRef -func (this *TrustBundleRef) UnmarshalJSON(b []byte) error { - return ReferencesUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for EndpointRef -func (this *EndpointRef) MarshalJSON() ([]byte, error) { - str, err := ReferencesMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for EndpointRef -func (this *EndpointRef) UnmarshalJSON(b []byte) error { - return ReferencesUnmarshaler.Unmarshal(b, this) -} - -var ( - ReferencesMarshaler = &protojson.MarshalOptions{} - ReferencesUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/route.pb.binary.go b/proto-public/pbmesh/v2beta1/pbproxystate/route.pb.binary.go deleted file mode 100644 index d6b057e379f1..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/route.pb.binary.go +++ /dev/null @@ -1,168 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/pbproxystate/route.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Route) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Route) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *VirtualHost) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *VirtualHost) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RouteMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RouteMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *PathMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *PathMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *QueryParameterMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *QueryParameterMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HeaderMatch) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HeaderMatch) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RouteDestination) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RouteDestination) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DestinationConfiguration) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DestinationConfiguration) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *RetryPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *RetryPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TimeoutConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TimeoutConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LoadBalancerHashPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LoadBalancerHashPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *CookiePolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *CookiePolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *HeaderPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *HeaderPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *QueryParameterPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *QueryParameterPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ConnectionPropertiesPolicy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ConnectionPropertiesPolicy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/route.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/route.pb.go deleted file mode 100644 index 0d88a016eb6f..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/route.pb.go +++ /dev/null @@ -1,1830 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/route.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Route struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // virtual_hosts is a list of virtual hosts. A virtual host is selected based on an incoming request's host header. - VirtualHosts []*VirtualHost `protobuf:"bytes,1,rep,name=virtual_hosts,json=virtualHosts,proto3" json:"virtual_hosts,omitempty"` -} - -func (x *Route) Reset() { - *x = Route{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Route) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Route) ProtoMessage() {} - -func (x *Route) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Route.ProtoReflect.Descriptor instead. -func (*Route) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{0} -} - -func (x *Route) GetVirtualHosts() []*VirtualHost { - if x != nil { - return x.VirtualHosts - } - return nil -} - -type VirtualHost struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // domains are used to match an incoming request's host header and determine which virtual host to use. - Domains []string `protobuf:"bytes,2,rep,name=domains,proto3" json:"domains,omitempty"` - // header_mutations to apply to the request when it matches this virtual host. These are applied after any headers in - // the RouteRule. - HeaderMutations []*HeaderMutation `protobuf:"bytes,3,rep,name=header_mutations,json=headerMutations,proto3" json:"header_mutations,omitempty"` - // route_rules are a list of rules to use for what to do next with this request. The first rule with a match will be - // used. - RouteRules []*RouteRule `protobuf:"bytes,4,rep,name=route_rules,json=routeRules,proto3" json:"route_rules,omitempty"` -} - -func (x *VirtualHost) Reset() { - *x = VirtualHost{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *VirtualHost) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*VirtualHost) ProtoMessage() {} - -func (x *VirtualHost) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use VirtualHost.ProtoReflect.Descriptor instead. -func (*VirtualHost) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{1} -} - -func (x *VirtualHost) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *VirtualHost) GetDomains() []string { - if x != nil { - return x.Domains - } - return nil -} - -func (x *VirtualHost) GetHeaderMutations() []*HeaderMutation { - if x != nil { - return x.HeaderMutations - } - return nil -} - -func (x *VirtualHost) GetRouteRules() []*RouteRule { - if x != nil { - return x.RouteRules - } - return nil -} - -type RouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // match determines how to match the request. The first match determines which destination the request will go to. - Match *RouteMatch `protobuf:"bytes,1,opt,name=match,proto3" json:"match,omitempty"` - // destination is where to send the request to. - Destination *RouteDestination `protobuf:"bytes,2,opt,name=destination,proto3" json:"destination,omitempty"` - // header_mutations to apply to the request. These are applied before the VirtualHost header mutations. - HeaderMutations []*HeaderMutation `protobuf:"bytes,3,rep,name=header_mutations,json=headerMutations,proto3" json:"header_mutations,omitempty"` -} - -func (x *RouteRule) Reset() { - *x = RouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RouteRule) ProtoMessage() {} - -func (x *RouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RouteRule.ProtoReflect.Descriptor instead. -func (*RouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{2} -} - -func (x *RouteRule) GetMatch() *RouteMatch { - if x != nil { - return x.Match - } - return nil -} - -func (x *RouteRule) GetDestination() *RouteDestination { - if x != nil { - return x.Destination - } - return nil -} - -func (x *RouteRule) GetHeaderMutations() []*HeaderMutation { - if x != nil { - return x.HeaderMutations - } - return nil -} - -// RouteMatch has configuration to match a request. -type RouteMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PathMatch *PathMatch `protobuf:"bytes,1,opt,name=path_match,json=pathMatch,proto3" json:"path_match,omitempty"` - HeaderMatches []*HeaderMatch `protobuf:"bytes,2,rep,name=header_matches,json=headerMatches,proto3" json:"header_matches,omitempty"` - MethodMatches []string `protobuf:"bytes,3,rep,name=method_matches,json=methodMatches,proto3" json:"method_matches,omitempty"` - QueryParameterMatches []*QueryParameterMatch `protobuf:"bytes,4,rep,name=query_parameter_matches,json=queryParameterMatches,proto3" json:"query_parameter_matches,omitempty"` -} - -func (x *RouteMatch) Reset() { - *x = RouteMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RouteMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RouteMatch) ProtoMessage() {} - -func (x *RouteMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RouteMatch.ProtoReflect.Descriptor instead. -func (*RouteMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{3} -} - -func (x *RouteMatch) GetPathMatch() *PathMatch { - if x != nil { - return x.PathMatch - } - return nil -} - -func (x *RouteMatch) GetHeaderMatches() []*HeaderMatch { - if x != nil { - return x.HeaderMatches - } - return nil -} - -func (x *RouteMatch) GetMethodMatches() []string { - if x != nil { - return x.MethodMatches - } - return nil -} - -func (x *RouteMatch) GetQueryParameterMatches() []*QueryParameterMatch { - if x != nil { - return x.QueryParameterMatches - } - return nil -} - -type PathMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to PathMatch: - // - // *PathMatch_Exact - // *PathMatch_Prefix - // *PathMatch_Regex - PathMatch isPathMatch_PathMatch `protobuf_oneof:"path_match"` -} - -func (x *PathMatch) Reset() { - *x = PathMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PathMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PathMatch) ProtoMessage() {} - -func (x *PathMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PathMatch.ProtoReflect.Descriptor instead. -func (*PathMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{4} -} - -func (m *PathMatch) GetPathMatch() isPathMatch_PathMatch { - if m != nil { - return m.PathMatch - } - return nil -} - -func (x *PathMatch) GetExact() string { - if x, ok := x.GetPathMatch().(*PathMatch_Exact); ok { - return x.Exact - } - return "" -} - -func (x *PathMatch) GetPrefix() string { - if x, ok := x.GetPathMatch().(*PathMatch_Prefix); ok { - return x.Prefix - } - return "" -} - -func (x *PathMatch) GetRegex() string { - if x, ok := x.GetPathMatch().(*PathMatch_Regex); ok { - return x.Regex - } - return "" -} - -type isPathMatch_PathMatch interface { - isPathMatch_PathMatch() -} - -type PathMatch_Exact struct { - Exact string `protobuf:"bytes,1,opt,name=exact,proto3,oneof"` -} - -type PathMatch_Prefix struct { - Prefix string `protobuf:"bytes,2,opt,name=prefix,proto3,oneof"` -} - -type PathMatch_Regex struct { - Regex string `protobuf:"bytes,3,opt,name=regex,proto3,oneof"` -} - -func (*PathMatch_Exact) isPathMatch_PathMatch() {} - -func (*PathMatch_Prefix) isPathMatch_PathMatch() {} - -func (*PathMatch_Regex) isPathMatch_PathMatch() {} - -type QueryParameterMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Types that are assignable to Match: - // - // *QueryParameterMatch_Exact - // *QueryParameterMatch_Regex - // *QueryParameterMatch_Present - Match isQueryParameterMatch_Match `protobuf_oneof:"match"` -} - -func (x *QueryParameterMatch) Reset() { - *x = QueryParameterMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryParameterMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryParameterMatch) ProtoMessage() {} - -func (x *QueryParameterMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryParameterMatch.ProtoReflect.Descriptor instead. -func (*QueryParameterMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{5} -} - -func (x *QueryParameterMatch) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (m *QueryParameterMatch) GetMatch() isQueryParameterMatch_Match { - if m != nil { - return m.Match - } - return nil -} - -func (x *QueryParameterMatch) GetExact() string { - if x, ok := x.GetMatch().(*QueryParameterMatch_Exact); ok { - return x.Exact - } - return "" -} - -func (x *QueryParameterMatch) GetRegex() string { - if x, ok := x.GetMatch().(*QueryParameterMatch_Regex); ok { - return x.Regex - } - return "" -} - -func (x *QueryParameterMatch) GetPresent() bool { - if x, ok := x.GetMatch().(*QueryParameterMatch_Present); ok { - return x.Present - } - return false -} - -type isQueryParameterMatch_Match interface { - isQueryParameterMatch_Match() -} - -type QueryParameterMatch_Exact struct { - Exact string `protobuf:"bytes,2,opt,name=exact,proto3,oneof"` -} - -type QueryParameterMatch_Regex struct { - Regex string `protobuf:"bytes,3,opt,name=regex,proto3,oneof"` -} - -type QueryParameterMatch_Present struct { - Present bool `protobuf:"varint,4,opt,name=present,proto3,oneof"` -} - -func (*QueryParameterMatch_Exact) isQueryParameterMatch_Match() {} - -func (*QueryParameterMatch_Regex) isQueryParameterMatch_Match() {} - -func (*QueryParameterMatch_Present) isQueryParameterMatch_Match() {} - -type HeaderMatch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Types that are assignable to Match: - // - // *HeaderMatch_Exact - // *HeaderMatch_Prefix - // *HeaderMatch_Suffix - // *HeaderMatch_Regex - // *HeaderMatch_Present - Match isHeaderMatch_Match `protobuf_oneof:"match"` - InvertMatch bool `protobuf:"varint,7,opt,name=invert_match,json=invertMatch,proto3" json:"invert_match,omitempty"` -} - -func (x *HeaderMatch) Reset() { - *x = HeaderMatch{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HeaderMatch) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HeaderMatch) ProtoMessage() {} - -func (x *HeaderMatch) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HeaderMatch.ProtoReflect.Descriptor instead. -func (*HeaderMatch) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{6} -} - -func (x *HeaderMatch) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (m *HeaderMatch) GetMatch() isHeaderMatch_Match { - if m != nil { - return m.Match - } - return nil -} - -func (x *HeaderMatch) GetExact() string { - if x, ok := x.GetMatch().(*HeaderMatch_Exact); ok { - return x.Exact - } - return "" -} - -func (x *HeaderMatch) GetPrefix() string { - if x, ok := x.GetMatch().(*HeaderMatch_Prefix); ok { - return x.Prefix - } - return "" -} - -func (x *HeaderMatch) GetSuffix() string { - if x, ok := x.GetMatch().(*HeaderMatch_Suffix); ok { - return x.Suffix - } - return "" -} - -func (x *HeaderMatch) GetRegex() string { - if x, ok := x.GetMatch().(*HeaderMatch_Regex); ok { - return x.Regex - } - return "" -} - -func (x *HeaderMatch) GetPresent() bool { - if x, ok := x.GetMatch().(*HeaderMatch_Present); ok { - return x.Present - } - return false -} - -func (x *HeaderMatch) GetInvertMatch() bool { - if x != nil { - return x.InvertMatch - } - return false -} - -type isHeaderMatch_Match interface { - isHeaderMatch_Match() -} - -type HeaderMatch_Exact struct { - Exact string `protobuf:"bytes,2,opt,name=exact,proto3,oneof"` -} - -type HeaderMatch_Prefix struct { - Prefix string `protobuf:"bytes,3,opt,name=prefix,proto3,oneof"` -} - -type HeaderMatch_Suffix struct { - Suffix string `protobuf:"bytes,4,opt,name=suffix,proto3,oneof"` -} - -type HeaderMatch_Regex struct { - Regex string `protobuf:"bytes,5,opt,name=regex,proto3,oneof"` -} - -type HeaderMatch_Present struct { - Present bool `protobuf:"varint,6,opt,name=present,proto3,oneof"` -} - -func (*HeaderMatch_Exact) isHeaderMatch_Match() {} - -func (*HeaderMatch_Prefix) isHeaderMatch_Match() {} - -func (*HeaderMatch_Suffix) isHeaderMatch_Match() {} - -func (*HeaderMatch_Regex) isHeaderMatch_Match() {} - -func (*HeaderMatch_Present) isHeaderMatch_Match() {} - -// RouteDestination has configuration for where to send a request. -type RouteDestination struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // destination is one or more clusters to route to. - // - // Types that are assignable to Destination: - // - // *RouteDestination_Cluster - // *RouteDestination_WeightedClusters - Destination isRouteDestination_Destination `protobuf_oneof:"destination"` - DestinationConfiguration *DestinationConfiguration `protobuf:"bytes,3,opt,name=destination_configuration,json=destinationConfiguration,proto3" json:"destination_configuration,omitempty"` -} - -func (x *RouteDestination) Reset() { - *x = RouteDestination{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RouteDestination) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RouteDestination) ProtoMessage() {} - -func (x *RouteDestination) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RouteDestination.ProtoReflect.Descriptor instead. -func (*RouteDestination) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{7} -} - -func (m *RouteDestination) GetDestination() isRouteDestination_Destination { - if m != nil { - return m.Destination - } - return nil -} - -func (x *RouteDestination) GetCluster() *DestinationCluster { - if x, ok := x.GetDestination().(*RouteDestination_Cluster); ok { - return x.Cluster - } - return nil -} - -func (x *RouteDestination) GetWeightedClusters() *L7WeightedClusterGroup { - if x, ok := x.GetDestination().(*RouteDestination_WeightedClusters); ok { - return x.WeightedClusters - } - return nil -} - -func (x *RouteDestination) GetDestinationConfiguration() *DestinationConfiguration { - if x != nil { - return x.DestinationConfiguration - } - return nil -} - -type isRouteDestination_Destination interface { - isRouteDestination_Destination() -} - -type RouteDestination_Cluster struct { - Cluster *DestinationCluster `protobuf:"bytes,1,opt,name=cluster,proto3,oneof"` -} - -type RouteDestination_WeightedClusters struct { - WeightedClusters *L7WeightedClusterGroup `protobuf:"bytes,2,opt,name=weighted_clusters,json=weightedClusters,proto3,oneof"` -} - -func (*RouteDestination_Cluster) isRouteDestination_Destination() {} - -func (*RouteDestination_WeightedClusters) isRouteDestination_Destination() {} - -type DestinationConfiguration struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AutoHostRewrite *wrapperspb.BoolValue `protobuf:"bytes,1,opt,name=auto_host_rewrite,json=autoHostRewrite,proto3" json:"auto_host_rewrite,omitempty"` - HashPolicies []*LoadBalancerHashPolicy `protobuf:"bytes,2,rep,name=hash_policies,json=hashPolicies,proto3" json:"hash_policies,omitempty"` - TimeoutConfig *TimeoutConfig `protobuf:"bytes,3,opt,name=timeout_config,json=timeoutConfig,proto3" json:"timeout_config,omitempty"` - PrefixRewrite string `protobuf:"bytes,4,opt,name=prefix_rewrite,json=prefixRewrite,proto3" json:"prefix_rewrite,omitempty"` - RetryPolicy *RetryPolicy `protobuf:"bytes,5,opt,name=retry_policy,json=retryPolicy,proto3" json:"retry_policy,omitempty"` -} - -func (x *DestinationConfiguration) Reset() { - *x = DestinationConfiguration{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DestinationConfiguration) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DestinationConfiguration) ProtoMessage() {} - -func (x *DestinationConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DestinationConfiguration.ProtoReflect.Descriptor instead. -func (*DestinationConfiguration) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{8} -} - -func (x *DestinationConfiguration) GetAutoHostRewrite() *wrapperspb.BoolValue { - if x != nil { - return x.AutoHostRewrite - } - return nil -} - -func (x *DestinationConfiguration) GetHashPolicies() []*LoadBalancerHashPolicy { - if x != nil { - return x.HashPolicies - } - return nil -} - -func (x *DestinationConfiguration) GetTimeoutConfig() *TimeoutConfig { - if x != nil { - return x.TimeoutConfig - } - return nil -} - -func (x *DestinationConfiguration) GetPrefixRewrite() string { - if x != nil { - return x.PrefixRewrite - } - return "" -} - -func (x *DestinationConfiguration) GetRetryPolicy() *RetryPolicy { - if x != nil { - return x.RetryPolicy - } - return nil -} - -type RetryPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RetryOn string `protobuf:"bytes,1,opt,name=retry_on,json=retryOn,proto3" json:"retry_on,omitempty"` - NumRetries *wrapperspb.UInt32Value `protobuf:"bytes,2,opt,name=num_retries,json=numRetries,proto3" json:"num_retries,omitempty"` - RetriableStatusCodes []uint32 `protobuf:"varint,3,rep,packed,name=retriable_status_codes,json=retriableStatusCodes,proto3" json:"retriable_status_codes,omitempty"` -} - -func (x *RetryPolicy) Reset() { - *x = RetryPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RetryPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RetryPolicy) ProtoMessage() {} - -func (x *RetryPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RetryPolicy.ProtoReflect.Descriptor instead. -func (*RetryPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{9} -} - -func (x *RetryPolicy) GetRetryOn() string { - if x != nil { - return x.RetryOn - } - return "" -} - -func (x *RetryPolicy) GetNumRetries() *wrapperspb.UInt32Value { - if x != nil { - return x.NumRetries - } - return nil -} - -func (x *RetryPolicy) GetRetriableStatusCodes() []uint32 { - if x != nil { - return x.RetriableStatusCodes - } - return nil -} - -type TimeoutConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // +kubebuilder:validation:Format=duration - Timeout *durationpb.Duration `protobuf:"bytes,1,opt,name=timeout,proto3" json:"timeout,omitempty"` - // +kubebuilder:validation:Format=duration - IdleTimeout *durationpb.Duration `protobuf:"bytes,2,opt,name=idle_timeout,json=idleTimeout,proto3" json:"idle_timeout,omitempty"` -} - -func (x *TimeoutConfig) Reset() { - *x = TimeoutConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TimeoutConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TimeoutConfig) ProtoMessage() {} - -func (x *TimeoutConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TimeoutConfig.ProtoReflect.Descriptor instead. -func (*TimeoutConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{10} -} - -func (x *TimeoutConfig) GetTimeout() *durationpb.Duration { - if x != nil { - return x.Timeout - } - return nil -} - -func (x *TimeoutConfig) GetIdleTimeout() *durationpb.Duration { - if x != nil { - return x.IdleTimeout - } - return nil -} - -type LoadBalancerHashPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Policy: - // - // *LoadBalancerHashPolicy_Cookie - // *LoadBalancerHashPolicy_Header - // *LoadBalancerHashPolicy_QueryParameter - // *LoadBalancerHashPolicy_ConnectionProperties - Policy isLoadBalancerHashPolicy_Policy `protobuf_oneof:"policy"` -} - -func (x *LoadBalancerHashPolicy) Reset() { - *x = LoadBalancerHashPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LoadBalancerHashPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LoadBalancerHashPolicy) ProtoMessage() {} - -func (x *LoadBalancerHashPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LoadBalancerHashPolicy.ProtoReflect.Descriptor instead. -func (*LoadBalancerHashPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{11} -} - -func (m *LoadBalancerHashPolicy) GetPolicy() isLoadBalancerHashPolicy_Policy { - if m != nil { - return m.Policy - } - return nil -} - -func (x *LoadBalancerHashPolicy) GetCookie() *CookiePolicy { - if x, ok := x.GetPolicy().(*LoadBalancerHashPolicy_Cookie); ok { - return x.Cookie - } - return nil -} - -func (x *LoadBalancerHashPolicy) GetHeader() *HeaderPolicy { - if x, ok := x.GetPolicy().(*LoadBalancerHashPolicy_Header); ok { - return x.Header - } - return nil -} - -func (x *LoadBalancerHashPolicy) GetQueryParameter() *QueryParameterPolicy { - if x, ok := x.GetPolicy().(*LoadBalancerHashPolicy_QueryParameter); ok { - return x.QueryParameter - } - return nil -} - -func (x *LoadBalancerHashPolicy) GetConnectionProperties() *ConnectionPropertiesPolicy { - if x, ok := x.GetPolicy().(*LoadBalancerHashPolicy_ConnectionProperties); ok { - return x.ConnectionProperties - } - return nil -} - -type isLoadBalancerHashPolicy_Policy interface { - isLoadBalancerHashPolicy_Policy() -} - -type LoadBalancerHashPolicy_Cookie struct { - Cookie *CookiePolicy `protobuf:"bytes,1,opt,name=cookie,proto3,oneof"` -} - -type LoadBalancerHashPolicy_Header struct { - Header *HeaderPolicy `protobuf:"bytes,2,opt,name=header,proto3,oneof"` -} - -type LoadBalancerHashPolicy_QueryParameter struct { - QueryParameter *QueryParameterPolicy `protobuf:"bytes,3,opt,name=query_parameter,json=queryParameter,proto3,oneof"` -} - -type LoadBalancerHashPolicy_ConnectionProperties struct { - ConnectionProperties *ConnectionPropertiesPolicy `protobuf:"bytes,4,opt,name=connection_properties,json=connectionProperties,proto3,oneof"` -} - -func (*LoadBalancerHashPolicy_Cookie) isLoadBalancerHashPolicy_Policy() {} - -func (*LoadBalancerHashPolicy_Header) isLoadBalancerHashPolicy_Policy() {} - -func (*LoadBalancerHashPolicy_QueryParameter) isLoadBalancerHashPolicy_Policy() {} - -func (*LoadBalancerHashPolicy_ConnectionProperties) isLoadBalancerHashPolicy_Policy() {} - -type CookiePolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // +kubebuilder:validation:Format=duration - Ttl *durationpb.Duration `protobuf:"bytes,2,opt,name=ttl,proto3" json:"ttl,omitempty"` - Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"` - Terminal bool `protobuf:"varint,4,opt,name=terminal,proto3" json:"terminal,omitempty"` -} - -func (x *CookiePolicy) Reset() { - *x = CookiePolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CookiePolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CookiePolicy) ProtoMessage() {} - -func (x *CookiePolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CookiePolicy.ProtoReflect.Descriptor instead. -func (*CookiePolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{12} -} - -func (x *CookiePolicy) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *CookiePolicy) GetTtl() *durationpb.Duration { - if x != nil { - return x.Ttl - } - return nil -} - -func (x *CookiePolicy) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (x *CookiePolicy) GetTerminal() bool { - if x != nil { - return x.Terminal - } - return false -} - -type HeaderPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Terminal bool `protobuf:"varint,2,opt,name=terminal,proto3" json:"terminal,omitempty"` -} - -func (x *HeaderPolicy) Reset() { - *x = HeaderPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HeaderPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HeaderPolicy) ProtoMessage() {} - -func (x *HeaderPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HeaderPolicy.ProtoReflect.Descriptor instead. -func (*HeaderPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{13} -} - -func (x *HeaderPolicy) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *HeaderPolicy) GetTerminal() bool { - if x != nil { - return x.Terminal - } - return false -} - -type QueryParameterPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Terminal bool `protobuf:"varint,2,opt,name=terminal,proto3" json:"terminal,omitempty"` -} - -func (x *QueryParameterPolicy) Reset() { - *x = QueryParameterPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryParameterPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryParameterPolicy) ProtoMessage() {} - -func (x *QueryParameterPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryParameterPolicy.ProtoReflect.Descriptor instead. -func (*QueryParameterPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{14} -} - -func (x *QueryParameterPolicy) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *QueryParameterPolicy) GetTerminal() bool { - if x != nil { - return x.Terminal - } - return false -} - -type ConnectionPropertiesPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SourceIp bool `protobuf:"varint,1,opt,name=source_ip,json=sourceIp,proto3" json:"source_ip,omitempty"` - Terminal bool `protobuf:"varint,2,opt,name=terminal,proto3" json:"terminal,omitempty"` -} - -func (x *ConnectionPropertiesPolicy) Reset() { - *x = ConnectionPropertiesPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConnectionPropertiesPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConnectionPropertiesPolicy) ProtoMessage() {} - -func (x *ConnectionPropertiesPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ConnectionPropertiesPolicy.ProtoReflect.Descriptor instead. -func (*ConnectionPropertiesPolicy) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP(), []int{15} -} - -func (x *ConnectionPropertiesPolicy) GetSourceIp() bool { - if x != nil { - return x.SourceIp - } - return false -} - -func (x *ConnectionPropertiesPolicy) GetTerminal() bool { - if x != nil { - return x.Terminal - } - return false -} - -var File_pbmesh_v2beta1_pbproxystate_route_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_route_proto_rawDesc = []byte{ - 0x0a, 0x27, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x72, 0x6f, - 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x32, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x65, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x5c, 0x0a, - 0x0d, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2e, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x0c, 0x76, - 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x0b, - 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x65, 0x0a, 0x10, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x56, 0x0a, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0a, 0x72, 0x6f, - 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, 0xa0, 0x02, 0x0a, 0x09, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x4c, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x6d, - 0x61, 0x74, 0x63, 0x68, 0x12, 0x5e, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x65, 0x0a, 0x10, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, - 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe2, 0x02, 0x0a, 0x0a, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x54, 0x0a, 0x0a, 0x70, 0x61, - 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x61, 0x74, 0x68, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x09, 0x70, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x12, 0x5e, 0x0a, 0x0e, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x52, 0x0d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, - 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, - 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x77, 0x0a, 0x17, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x65, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x15, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, - 0x22, 0x63, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x16, 0x0a, - 0x05, 0x65, 0x78, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, - 0x65, 0x78, 0x61, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, - 0x16, 0x0a, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x70, 0x61, 0x74, 0x68, 0x5f, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x22, 0x7e, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x16, 0x0a, 0x05, 0x65, 0x78, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x00, 0x52, 0x05, 0x65, 0x78, 0x61, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x72, 0x65, 0x67, 0x65, - 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, - 0x12, 0x1a, 0x0a, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x08, 0x48, 0x00, 0x52, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x22, 0xcd, 0x01, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x78, 0x61, - 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x78, 0x61, 0x63, - 0x74, 0x12, 0x18, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x18, 0x0a, 0x06, 0x73, - 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x73, - 0x75, 0x66, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x12, 0x1a, 0x0a, - 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, - 0x52, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x76, - 0x65, 0x72, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0b, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x42, 0x07, 0x0a, 0x05, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x22, 0xf4, 0x02, 0x0a, 0x10, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5a, 0x0a, 0x07, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x48, 0x00, 0x52, 0x07, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x71, 0x0a, 0x11, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, - 0x37, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x10, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, - 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x81, 0x01, 0x0a, 0x19, 0x64, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x44, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0d, 0x0a, - 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb0, 0x03, 0x0a, - 0x18, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x11, 0x61, 0x75, 0x74, - 0x6f, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x0f, 0x61, 0x75, 0x74, 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, - 0x65, 0x12, 0x67, 0x0a, 0x0d, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x72, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0c, 0x68, 0x61, - 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x60, 0x0a, 0x0e, 0x74, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, - 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x77, 0x72, - 0x69, 0x74, 0x65, 0x12, 0x5a, 0x0a, 0x0c, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x52, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, - 0x9d, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, - 0x19, 0x0a, 0x08, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x72, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x12, 0x3d, 0x0a, 0x0b, 0x6e, 0x75, - 0x6d, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x6e, - 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x74, - 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, - 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x14, 0x72, 0x65, 0x74, 0x72, 0x69, - 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x22, - 0x82, 0x01, 0x0a, 0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x3c, 0x0a, 0x0c, 0x69, 0x64, 0x6c, 0x65, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x69, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x22, 0xb6, 0x03, 0x0a, 0x16, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x72, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, - 0x52, 0x0a, 0x06, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6f, 0x6f, - 0x6b, 0x69, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, 0x6f, - 0x6b, 0x69, 0x65, 0x12, 0x52, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x48, 0x00, 0x52, - 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x6b, 0x0a, 0x0f, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x48, 0x00, 0x52, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x65, 0x74, 0x65, 0x72, 0x12, 0x7d, 0x0a, 0x15, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, - 0x72, 0x74, 0x69, 0x65, 0x73, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x48, 0x00, 0x52, 0x14, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, - 0x69, 0x65, 0x73, 0x42, 0x08, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x7f, 0x0a, - 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x3e, - 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x46, - 0x0a, 0x14, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x55, 0x0a, 0x1a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, - 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, - 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x42, 0xd0, 0x02, - 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x42, 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2a, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, - 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x36, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_route_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_route_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes = make([]protoimpl.MessageInfo, 16) -var file_pbmesh_v2beta1_pbproxystate_route_proto_goTypes = []interface{}{ - (*Route)(nil), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.Route - (*VirtualHost)(nil), // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.VirtualHost - (*RouteRule)(nil), // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.RouteRule - (*RouteMatch)(nil), // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.RouteMatch - (*PathMatch)(nil), // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.PathMatch - (*QueryParameterMatch)(nil), // 5: hashicorp.consul.mesh.v2beta1.pbproxystate.QueryParameterMatch - (*HeaderMatch)(nil), // 6: hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderMatch - (*RouteDestination)(nil), // 7: hashicorp.consul.mesh.v2beta1.pbproxystate.RouteDestination - (*DestinationConfiguration)(nil), // 8: hashicorp.consul.mesh.v2beta1.pbproxystate.DestinationConfiguration - (*RetryPolicy)(nil), // 9: hashicorp.consul.mesh.v2beta1.pbproxystate.RetryPolicy - (*TimeoutConfig)(nil), // 10: hashicorp.consul.mesh.v2beta1.pbproxystate.TimeoutConfig - (*LoadBalancerHashPolicy)(nil), // 11: hashicorp.consul.mesh.v2beta1.pbproxystate.LoadBalancerHashPolicy - (*CookiePolicy)(nil), // 12: hashicorp.consul.mesh.v2beta1.pbproxystate.CookiePolicy - (*HeaderPolicy)(nil), // 13: hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderPolicy - (*QueryParameterPolicy)(nil), // 14: hashicorp.consul.mesh.v2beta1.pbproxystate.QueryParameterPolicy - (*ConnectionPropertiesPolicy)(nil), // 15: hashicorp.consul.mesh.v2beta1.pbproxystate.ConnectionPropertiesPolicy - (*HeaderMutation)(nil), // 16: hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderMutation - (*DestinationCluster)(nil), // 17: hashicorp.consul.mesh.v2beta1.pbproxystate.DestinationCluster - (*L7WeightedClusterGroup)(nil), // 18: hashicorp.consul.mesh.v2beta1.pbproxystate.L7WeightedClusterGroup - (*wrapperspb.BoolValue)(nil), // 19: google.protobuf.BoolValue - (*wrapperspb.UInt32Value)(nil), // 20: google.protobuf.UInt32Value - (*durationpb.Duration)(nil), // 21: google.protobuf.Duration -} -var file_pbmesh_v2beta1_pbproxystate_route_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.Route.virtual_hosts:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.VirtualHost - 16, // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.VirtualHost.header_mutations:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderMutation - 2, // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.VirtualHost.route_rules:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.RouteRule - 3, // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.RouteRule.match:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.RouteMatch - 7, // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.RouteRule.destination:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.RouteDestination - 16, // 5: hashicorp.consul.mesh.v2beta1.pbproxystate.RouteRule.header_mutations:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderMutation - 4, // 6: hashicorp.consul.mesh.v2beta1.pbproxystate.RouteMatch.path_match:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.PathMatch - 6, // 7: hashicorp.consul.mesh.v2beta1.pbproxystate.RouteMatch.header_matches:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderMatch - 5, // 8: hashicorp.consul.mesh.v2beta1.pbproxystate.RouteMatch.query_parameter_matches:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.QueryParameterMatch - 17, // 9: hashicorp.consul.mesh.v2beta1.pbproxystate.RouteDestination.cluster:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.DestinationCluster - 18, // 10: hashicorp.consul.mesh.v2beta1.pbproxystate.RouteDestination.weighted_clusters:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.L7WeightedClusterGroup - 8, // 11: hashicorp.consul.mesh.v2beta1.pbproxystate.RouteDestination.destination_configuration:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.DestinationConfiguration - 19, // 12: hashicorp.consul.mesh.v2beta1.pbproxystate.DestinationConfiguration.auto_host_rewrite:type_name -> google.protobuf.BoolValue - 11, // 13: hashicorp.consul.mesh.v2beta1.pbproxystate.DestinationConfiguration.hash_policies:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.LoadBalancerHashPolicy - 10, // 14: hashicorp.consul.mesh.v2beta1.pbproxystate.DestinationConfiguration.timeout_config:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TimeoutConfig - 9, // 15: hashicorp.consul.mesh.v2beta1.pbproxystate.DestinationConfiguration.retry_policy:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.RetryPolicy - 20, // 16: hashicorp.consul.mesh.v2beta1.pbproxystate.RetryPolicy.num_retries:type_name -> google.protobuf.UInt32Value - 21, // 17: hashicorp.consul.mesh.v2beta1.pbproxystate.TimeoutConfig.timeout:type_name -> google.protobuf.Duration - 21, // 18: hashicorp.consul.mesh.v2beta1.pbproxystate.TimeoutConfig.idle_timeout:type_name -> google.protobuf.Duration - 12, // 19: hashicorp.consul.mesh.v2beta1.pbproxystate.LoadBalancerHashPolicy.cookie:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.CookiePolicy - 13, // 20: hashicorp.consul.mesh.v2beta1.pbproxystate.LoadBalancerHashPolicy.header:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.HeaderPolicy - 14, // 21: hashicorp.consul.mesh.v2beta1.pbproxystate.LoadBalancerHashPolicy.query_parameter:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.QueryParameterPolicy - 15, // 22: hashicorp.consul.mesh.v2beta1.pbproxystate.LoadBalancerHashPolicy.connection_properties:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.ConnectionPropertiesPolicy - 21, // 23: hashicorp.consul.mesh.v2beta1.pbproxystate.CookiePolicy.ttl:type_name -> google.protobuf.Duration - 24, // [24:24] is the sub-list for method output_type - 24, // [24:24] is the sub-list for method input_type - 24, // [24:24] is the sub-list for extension type_name - 24, // [24:24] is the sub-list for extension extendee - 0, // [0:24] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_route_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_route_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_route_proto != nil { - return - } - file_pbmesh_v2beta1_pbproxystate_cluster_proto_init() - file_pbmesh_v2beta1_pbproxystate_header_mutations_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Route); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*VirtualHost); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RouteMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PathMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryParameterMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HeaderMatch); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RouteDestination); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DestinationConfiguration); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RetryPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TimeoutConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LoadBalancerHashPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CookiePolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HeaderPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryParameterPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConnectionPropertiesPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[4].OneofWrappers = []interface{}{ - (*PathMatch_Exact)(nil), - (*PathMatch_Prefix)(nil), - (*PathMatch_Regex)(nil), - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[5].OneofWrappers = []interface{}{ - (*QueryParameterMatch_Exact)(nil), - (*QueryParameterMatch_Regex)(nil), - (*QueryParameterMatch_Present)(nil), - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[6].OneofWrappers = []interface{}{ - (*HeaderMatch_Exact)(nil), - (*HeaderMatch_Prefix)(nil), - (*HeaderMatch_Suffix)(nil), - (*HeaderMatch_Regex)(nil), - (*HeaderMatch_Present)(nil), - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[7].OneofWrappers = []interface{}{ - (*RouteDestination_Cluster)(nil), - (*RouteDestination_WeightedClusters)(nil), - } - file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes[11].OneofWrappers = []interface{}{ - (*LoadBalancerHashPolicy_Cookie)(nil), - (*LoadBalancerHashPolicy_Header)(nil), - (*LoadBalancerHashPolicy_QueryParameter)(nil), - (*LoadBalancerHashPolicy_ConnectionProperties)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_route_proto_rawDesc, - NumEnums: 0, - NumMessages: 16, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_route_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_route_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_pbproxystate_route_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_route_proto = out.File - file_pbmesh_v2beta1_pbproxystate_route_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_route_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_route_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/route.proto b/proto-public/pbmesh/v2beta1/pbproxystate/route.proto deleted file mode 100644 index d9b9c8dcd642..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/route.proto +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1.pbproxystate; - -import "google/protobuf/duration.proto"; -import "google/protobuf/wrappers.proto"; -import "pbmesh/v2beta1/pbproxystate/cluster.proto"; -import "pbmesh/v2beta1/pbproxystate/header_mutations.proto"; - -message Route { - // virtual_hosts is a list of virtual hosts. A virtual host is selected based on an incoming request's host header. - repeated VirtualHost virtual_hosts = 1; -} - -message VirtualHost { - string name = 1; - // domains are used to match an incoming request's host header and determine which virtual host to use. - repeated string domains = 2; - // header_mutations to apply to the request when it matches this virtual host. These are applied after any headers in - // the RouteRule. - repeated HeaderMutation header_mutations = 3; - // route_rules are a list of rules to use for what to do next with this request. The first rule with a match will be - // used. - repeated RouteRule route_rules = 4; -} - -message RouteRule { - // match determines how to match the request. The first match determines which destination the request will go to. - RouteMatch match = 1; - // destination is where to send the request to. - RouteDestination destination = 2; - // header_mutations to apply to the request. These are applied before the VirtualHost header mutations. - repeated HeaderMutation header_mutations = 3; -} - -// RouteMatch has configuration to match a request. -message RouteMatch { - PathMatch path_match = 1; - repeated HeaderMatch header_matches = 2; - repeated string method_matches = 3; - repeated QueryParameterMatch query_parameter_matches = 4; -} - -message PathMatch { - oneof path_match { - string exact = 1; - string prefix = 2; - string regex = 3; - } -} - -message QueryParameterMatch { - string name = 1; - oneof match { - string exact = 2; - string regex = 3; - bool present = 4; - } -} - -message HeaderMatch { - string name = 1; - oneof match { - string exact = 2; - string prefix = 3; - string suffix = 4; - string regex = 5; - bool present = 6; - } - bool invert_match = 7; -} - -// RouteDestination has configuration for where to send a request. -message RouteDestination { - // destination is one or more clusters to route to. - oneof destination { - DestinationCluster cluster = 1; - L7WeightedClusterGroup weighted_clusters = 2; - } - DestinationConfiguration destination_configuration = 3; -} - -message DestinationConfiguration { - google.protobuf.BoolValue auto_host_rewrite = 1; - repeated LoadBalancerHashPolicy hash_policies = 2; - TimeoutConfig timeout_config = 3; - string prefix_rewrite = 4; - RetryPolicy retry_policy = 5; -} - -message RetryPolicy { - string retry_on = 1; - google.protobuf.UInt32Value num_retries = 2; - repeated uint32 retriable_status_codes = 3; -} - -message TimeoutConfig { - // +kubebuilder:validation:Format=duration - google.protobuf.Duration timeout = 1; - // +kubebuilder:validation:Format=duration - google.protobuf.Duration idle_timeout = 2; -} - -message LoadBalancerHashPolicy { - oneof policy { - CookiePolicy cookie = 1; - HeaderPolicy header = 2; - QueryParameterPolicy query_parameter = 3; - ConnectionPropertiesPolicy connection_properties = 4; - } -} - -message CookiePolicy { - string name = 1; - // +kubebuilder:validation:Format=duration - google.protobuf.Duration ttl = 2; - string path = 3; - bool terminal = 4; -} -message HeaderPolicy { - string name = 1; - bool terminal = 2; -} -message QueryParameterPolicy { - string name = 1; - bool terminal = 2; -} -message ConnectionPropertiesPolicy { - bool source_ip = 1; - bool terminal = 2; -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/route_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/route_deepcopy.gen.go deleted file mode 100644 index e2eea4e78b5e..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/route_deepcopy.gen.go +++ /dev/null @@ -1,342 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package pbproxystate - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using Route within kubernetes types, where deepcopy-gen is used. -func (in *Route) DeepCopyInto(out *Route) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Route. Required by controller-gen. -func (in *Route) DeepCopy() *Route { - if in == nil { - return nil - } - out := new(Route) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Route. Required by controller-gen. -func (in *Route) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using VirtualHost within kubernetes types, where deepcopy-gen is used. -func (in *VirtualHost) DeepCopyInto(out *VirtualHost) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualHost. Required by controller-gen. -func (in *VirtualHost) DeepCopy() *VirtualHost { - if in == nil { - return nil - } - out := new(VirtualHost) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new VirtualHost. Required by controller-gen. -func (in *VirtualHost) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using RouteRule within kubernetes types, where deepcopy-gen is used. -func (in *RouteRule) DeepCopyInto(out *RouteRule) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteRule. Required by controller-gen. -func (in *RouteRule) DeepCopy() *RouteRule { - if in == nil { - return nil - } - out := new(RouteRule) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new RouteRule. Required by controller-gen. -func (in *RouteRule) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using RouteMatch within kubernetes types, where deepcopy-gen is used. -func (in *RouteMatch) DeepCopyInto(out *RouteMatch) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteMatch. Required by controller-gen. -func (in *RouteMatch) DeepCopy() *RouteMatch { - if in == nil { - return nil - } - out := new(RouteMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new RouteMatch. Required by controller-gen. -func (in *RouteMatch) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using PathMatch within kubernetes types, where deepcopy-gen is used. -func (in *PathMatch) DeepCopyInto(out *PathMatch) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PathMatch. Required by controller-gen. -func (in *PathMatch) DeepCopy() *PathMatch { - if in == nil { - return nil - } - out := new(PathMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new PathMatch. Required by controller-gen. -func (in *PathMatch) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using QueryParameterMatch within kubernetes types, where deepcopy-gen is used. -func (in *QueryParameterMatch) DeepCopyInto(out *QueryParameterMatch) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QueryParameterMatch. Required by controller-gen. -func (in *QueryParameterMatch) DeepCopy() *QueryParameterMatch { - if in == nil { - return nil - } - out := new(QueryParameterMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new QueryParameterMatch. Required by controller-gen. -func (in *QueryParameterMatch) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HeaderMatch within kubernetes types, where deepcopy-gen is used. -func (in *HeaderMatch) DeepCopyInto(out *HeaderMatch) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderMatch. Required by controller-gen. -func (in *HeaderMatch) DeepCopy() *HeaderMatch { - if in == nil { - return nil - } - out := new(HeaderMatch) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HeaderMatch. Required by controller-gen. -func (in *HeaderMatch) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using RouteDestination within kubernetes types, where deepcopy-gen is used. -func (in *RouteDestination) DeepCopyInto(out *RouteDestination) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteDestination. Required by controller-gen. -func (in *RouteDestination) DeepCopy() *RouteDestination { - if in == nil { - return nil - } - out := new(RouteDestination) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new RouteDestination. Required by controller-gen. -func (in *RouteDestination) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DestinationConfiguration within kubernetes types, where deepcopy-gen is used. -func (in *DestinationConfiguration) DeepCopyInto(out *DestinationConfiguration) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationConfiguration. Required by controller-gen. -func (in *DestinationConfiguration) DeepCopy() *DestinationConfiguration { - if in == nil { - return nil - } - out := new(DestinationConfiguration) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DestinationConfiguration. Required by controller-gen. -func (in *DestinationConfiguration) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using RetryPolicy within kubernetes types, where deepcopy-gen is used. -func (in *RetryPolicy) DeepCopyInto(out *RetryPolicy) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RetryPolicy. Required by controller-gen. -func (in *RetryPolicy) DeepCopy() *RetryPolicy { - if in == nil { - return nil - } - out := new(RetryPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new RetryPolicy. Required by controller-gen. -func (in *RetryPolicy) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using TimeoutConfig within kubernetes types, where deepcopy-gen is used. -func (in *TimeoutConfig) DeepCopyInto(out *TimeoutConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TimeoutConfig. Required by controller-gen. -func (in *TimeoutConfig) DeepCopy() *TimeoutConfig { - if in == nil { - return nil - } - out := new(TimeoutConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TimeoutConfig. Required by controller-gen. -func (in *TimeoutConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using LoadBalancerHashPolicy within kubernetes types, where deepcopy-gen is used. -func (in *LoadBalancerHashPolicy) DeepCopyInto(out *LoadBalancerHashPolicy) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancerHashPolicy. Required by controller-gen. -func (in *LoadBalancerHashPolicy) DeepCopy() *LoadBalancerHashPolicy { - if in == nil { - return nil - } - out := new(LoadBalancerHashPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancerHashPolicy. Required by controller-gen. -func (in *LoadBalancerHashPolicy) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using CookiePolicy within kubernetes types, where deepcopy-gen is used. -func (in *CookiePolicy) DeepCopyInto(out *CookiePolicy) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CookiePolicy. Required by controller-gen. -func (in *CookiePolicy) DeepCopy() *CookiePolicy { - if in == nil { - return nil - } - out := new(CookiePolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new CookiePolicy. Required by controller-gen. -func (in *CookiePolicy) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using HeaderPolicy within kubernetes types, where deepcopy-gen is used. -func (in *HeaderPolicy) DeepCopyInto(out *HeaderPolicy) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderPolicy. Required by controller-gen. -func (in *HeaderPolicy) DeepCopy() *HeaderPolicy { - if in == nil { - return nil - } - out := new(HeaderPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new HeaderPolicy. Required by controller-gen. -func (in *HeaderPolicy) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using QueryParameterPolicy within kubernetes types, where deepcopy-gen is used. -func (in *QueryParameterPolicy) DeepCopyInto(out *QueryParameterPolicy) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QueryParameterPolicy. Required by controller-gen. -func (in *QueryParameterPolicy) DeepCopy() *QueryParameterPolicy { - if in == nil { - return nil - } - out := new(QueryParameterPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new QueryParameterPolicy. Required by controller-gen. -func (in *QueryParameterPolicy) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ConnectionPropertiesPolicy within kubernetes types, where deepcopy-gen is used. -func (in *ConnectionPropertiesPolicy) DeepCopyInto(out *ConnectionPropertiesPolicy) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConnectionPropertiesPolicy. Required by controller-gen. -func (in *ConnectionPropertiesPolicy) DeepCopy() *ConnectionPropertiesPolicy { - if in == nil { - return nil - } - out := new(ConnectionPropertiesPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ConnectionPropertiesPolicy. Required by controller-gen. -func (in *ConnectionPropertiesPolicy) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/route_json.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/route_json.gen.go deleted file mode 100644 index 23682dc57277..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/route_json.gen.go +++ /dev/null @@ -1,187 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package pbproxystate - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for Route -func (this *Route) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Route -func (this *Route) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for VirtualHost -func (this *VirtualHost) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for VirtualHost -func (this *VirtualHost) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for RouteRule -func (this *RouteRule) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for RouteRule -func (this *RouteRule) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for RouteMatch -func (this *RouteMatch) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for RouteMatch -func (this *RouteMatch) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for PathMatch -func (this *PathMatch) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for PathMatch -func (this *PathMatch) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for QueryParameterMatch -func (this *QueryParameterMatch) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for QueryParameterMatch -func (this *QueryParameterMatch) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HeaderMatch -func (this *HeaderMatch) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HeaderMatch -func (this *HeaderMatch) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for RouteDestination -func (this *RouteDestination) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for RouteDestination -func (this *RouteDestination) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DestinationConfiguration -func (this *DestinationConfiguration) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DestinationConfiguration -func (this *DestinationConfiguration) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for RetryPolicy -func (this *RetryPolicy) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for RetryPolicy -func (this *RetryPolicy) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for TimeoutConfig -func (this *TimeoutConfig) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TimeoutConfig -func (this *TimeoutConfig) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for LoadBalancerHashPolicy -func (this *LoadBalancerHashPolicy) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for LoadBalancerHashPolicy -func (this *LoadBalancerHashPolicy) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for CookiePolicy -func (this *CookiePolicy) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for CookiePolicy -func (this *CookiePolicy) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for HeaderPolicy -func (this *HeaderPolicy) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for HeaderPolicy -func (this *HeaderPolicy) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for QueryParameterPolicy -func (this *QueryParameterPolicy) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for QueryParameterPolicy -func (this *QueryParameterPolicy) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ConnectionPropertiesPolicy -func (this *ConnectionPropertiesPolicy) MarshalJSON() ([]byte, error) { - str, err := RouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ConnectionPropertiesPolicy -func (this *ConnectionPropertiesPolicy) UnmarshalJSON(b []byte) error { - return RouteUnmarshaler.Unmarshal(b, this) -} - -var ( - RouteMarshaler = &protojson.MarshalOptions{} - RouteUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions.pb.binary.go b/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions.pb.binary.go deleted file mode 100644 index 403b64f4699e..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions.pb.binary.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/pbproxystate/traffic_permissions.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TrafficPermissions) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TrafficPermissions) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Permission) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Permission) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Principal) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Principal) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Spiffe) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Spiffe) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions.pb.go deleted file mode 100644 index def42e933f97..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions.pb.go +++ /dev/null @@ -1,429 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/traffic_permissions.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type TrafficPermissions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AllowPermissions []*Permission `protobuf:"bytes,1,rep,name=allow_permissions,json=allowPermissions,proto3" json:"allow_permissions,omitempty"` - DenyPermissions []*Permission `protobuf:"bytes,2,rep,name=deny_permissions,json=denyPermissions,proto3" json:"deny_permissions,omitempty"` - // default_allow determines if the workload is in default allow mode. This is determined - // by combining the cluster's default allow setting with the is_default property on - // computed traffic permissions. - DefaultAllow bool `protobuf:"varint,4,opt,name=default_allow,json=defaultAllow,proto3" json:"default_allow,omitempty"` -} - -func (x *TrafficPermissions) Reset() { - *x = TrafficPermissions{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TrafficPermissions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TrafficPermissions) ProtoMessage() {} - -func (x *TrafficPermissions) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TrafficPermissions.ProtoReflect.Descriptor instead. -func (*TrafficPermissions) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDescGZIP(), []int{0} -} - -func (x *TrafficPermissions) GetAllowPermissions() []*Permission { - if x != nil { - return x.AllowPermissions - } - return nil -} - -func (x *TrafficPermissions) GetDenyPermissions() []*Permission { - if x != nil { - return x.DenyPermissions - } - return nil -} - -func (x *TrafficPermissions) GetDefaultAllow() bool { - if x != nil { - return x.DefaultAllow - } - return false -} - -type Permission struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Principals []*Principal `protobuf:"bytes,1,rep,name=principals,proto3" json:"principals,omitempty"` -} - -func (x *Permission) Reset() { - *x = Permission{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Permission) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Permission) ProtoMessage() {} - -func (x *Permission) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Permission.ProtoReflect.Descriptor instead. -func (*Permission) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDescGZIP(), []int{1} -} - -func (x *Permission) GetPrincipals() []*Principal { - if x != nil { - return x.Principals - } - return nil -} - -type Principal struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Spiffe *Spiffe `protobuf:"bytes,1,opt,name=spiffe,proto3" json:"spiffe,omitempty"` - ExcludeSpiffes []*Spiffe `protobuf:"bytes,2,rep,name=exclude_spiffes,json=excludeSpiffes,proto3" json:"exclude_spiffes,omitempty"` -} - -func (x *Principal) Reset() { - *x = Principal{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Principal) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Principal) ProtoMessage() {} - -func (x *Principal) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Principal.ProtoReflect.Descriptor instead. -func (*Principal) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDescGZIP(), []int{2} -} - -func (x *Principal) GetSpiffe() *Spiffe { - if x != nil { - return x.Spiffe - } - return nil -} - -func (x *Principal) GetExcludeSpiffes() []*Spiffe { - if x != nil { - return x.ExcludeSpiffes - } - return nil -} - -type Spiffe struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // regex is the regular expression for matching spiffe ids. - Regex string `protobuf:"bytes,1,opt,name=regex,proto3" json:"regex,omitempty"` - // xfcc_regex specifies that Envoy needs to find the spiffe id in an xfcc header. - // It is currently unused, but considering this is important for to avoid breaking changes. - XfccRegex string `protobuf:"bytes,2,opt,name=xfcc_regex,json=xfccRegex,proto3" json:"xfcc_regex,omitempty"` -} - -func (x *Spiffe) Reset() { - *x = Spiffe{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Spiffe) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Spiffe) ProtoMessage() {} - -func (x *Spiffe) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Spiffe.ProtoReflect.Descriptor instead. -func (*Spiffe) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDescGZIP(), []int{3} -} - -func (x *Spiffe) GetRegex() string { - if x != nil { - return x.Regex - } - return "" -} - -func (x *Spiffe) GetXfccRegex() string { - if x != nil { - return x.XfccRegex - } - return "" -} - -var File_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDesc = []byte{ - 0x0a, 0x35, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x74, 0x72, - 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x22, 0x81, 0x02, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x63, 0x0a, 0x11, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x61, 0x0a, 0x10, 0x64, 0x65, 0x6e, 0x79, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x52, 0x0f, 0x64, 0x65, 0x6e, 0x79, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x22, 0x63, 0x0a, 0x0a, 0x50, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x55, 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, - 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, - 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x22, 0xb4, 0x01, 0x0a, - 0x09, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x70, - 0x69, 0x66, 0x66, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x70, 0x69, 0x66, 0x66, 0x65, 0x52, 0x06, - 0x73, 0x70, 0x69, 0x66, 0x66, 0x65, 0x12, 0x5b, 0x0a, 0x0f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, - 0x65, 0x5f, 0x73, 0x70, 0x69, 0x66, 0x66, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x70, 0x69, - 0x66, 0x66, 0x65, 0x52, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x53, 0x70, 0x69, 0x66, - 0x66, 0x65, 0x73, 0x22, 0x3d, 0x0a, 0x06, 0x53, 0x70, 0x69, 0x66, 0x66, 0x65, 0x12, 0x14, 0x0a, - 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x65, - 0x67, 0x65, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x78, 0x66, 0x63, 0x63, 0x5f, 0x72, 0x65, 0x67, 0x65, - 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x78, 0x66, 0x63, 0x63, 0x52, 0x65, 0x67, - 0x65, 0x78, 0x42, 0xdd, 0x02, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x17, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x50, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, - 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, - 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xca, 0x02, 0x2a, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, - 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, 0x36, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0xea, 0x02, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_goTypes = []interface{}{ - (*TrafficPermissions)(nil), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.TrafficPermissions - (*Permission)(nil), // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.Permission - (*Principal)(nil), // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.Principal - (*Spiffe)(nil), // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.Spiffe -} -var file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.TrafficPermissions.allow_permissions:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Permission - 1, // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.TrafficPermissions.deny_permissions:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Permission - 2, // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.Permission.principals:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Principal - 3, // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.Principal.spiffe:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Spiffe - 3, // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.Principal.exclude_spiffes:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Spiffe - 5, // [5:5] is the sub-list for method output_type - 5, // [5:5] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TrafficPermissions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Permission); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Principal); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Spiffe); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDesc, - NumEnums: 0, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto = out.File - file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_traffic_permissions_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions.proto b/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions.proto deleted file mode 100644 index 918b092c0a36..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions.proto +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1.pbproxystate; - -message TrafficPermissions { - repeated Permission allow_permissions = 1; - repeated Permission deny_permissions = 2; - // default_allow determines if the workload is in default allow mode. This is determined - // by combining the cluster's default allow setting with the is_default property on - // computed traffic permissions. - bool default_allow = 4; -} - -message Permission { - repeated Principal principals = 1; - - // We don't need destination rules here yet because they either apply to L7 features or multi-ports. - // In the case of multiple ports, the sidecar proxy controller is responsible for filtering - // per-port permissions. -} - -message Principal { - Spiffe spiffe = 1; - repeated Spiffe exclude_spiffes = 2; -} - -message Spiffe { - // regex is the regular expression for matching spiffe ids. - string regex = 1; - - // xfcc_regex specifies that Envoy needs to find the spiffe id in an xfcc header. - // It is currently unused, but considering this is important for to avoid breaking changes. - string xfcc_regex = 2; -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions_deepcopy.gen.go deleted file mode 100644 index b45d2a79261a..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions_deepcopy.gen.go +++ /dev/null @@ -1,90 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package pbproxystate - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using TrafficPermissions within kubernetes types, where deepcopy-gen is used. -func (in *TrafficPermissions) DeepCopyInto(out *TrafficPermissions) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficPermissions. Required by controller-gen. -func (in *TrafficPermissions) DeepCopy() *TrafficPermissions { - if in == nil { - return nil - } - out := new(TrafficPermissions) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TrafficPermissions. Required by controller-gen. -func (in *TrafficPermissions) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Permission within kubernetes types, where deepcopy-gen is used. -func (in *Permission) DeepCopyInto(out *Permission) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Permission. Required by controller-gen. -func (in *Permission) DeepCopy() *Permission { - if in == nil { - return nil - } - out := new(Permission) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Permission. Required by controller-gen. -func (in *Permission) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Principal within kubernetes types, where deepcopy-gen is used. -func (in *Principal) DeepCopyInto(out *Principal) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Principal. Required by controller-gen. -func (in *Principal) DeepCopy() *Principal { - if in == nil { - return nil - } - out := new(Principal) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Principal. Required by controller-gen. -func (in *Principal) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using Spiffe within kubernetes types, where deepcopy-gen is used. -func (in *Spiffe) DeepCopyInto(out *Spiffe) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spiffe. Required by controller-gen. -func (in *Spiffe) DeepCopy() *Spiffe { - if in == nil { - return nil - } - out := new(Spiffe) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Spiffe. Required by controller-gen. -func (in *Spiffe) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions_json.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions_json.gen.go deleted file mode 100644 index 3651fcabcabe..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/traffic_permissions_json.gen.go +++ /dev/null @@ -1,55 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package pbproxystate - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for TrafficPermissions -func (this *TrafficPermissions) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TrafficPermissions -func (this *TrafficPermissions) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Permission -func (this *Permission) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Permission -func (this *Permission) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Principal -func (this *Principal) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Principal -func (this *Principal) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for Spiffe -func (this *Spiffe) MarshalJSON() ([]byte, error) { - str, err := TrafficPermissionsMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Spiffe -func (this *Spiffe) UnmarshalJSON(b []byte) error { - return TrafficPermissionsUnmarshaler.Unmarshal(b, this) -} - -var ( - TrafficPermissionsMarshaler = &protojson.MarshalOptions{} - TrafficPermissionsUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket.pb.binary.go b/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket.pb.binary.go deleted file mode 100644 index 867d97441538..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket.pb.binary.go +++ /dev/null @@ -1,138 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/pbproxystate/transport_socket.proto - -package pbproxystate - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TLS) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TLS) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TransportSocket) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TransportSocket) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InboundMeshMTLS) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InboundMeshMTLS) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *OutboundMeshMTLS) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *OutboundMeshMTLS) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *InboundNonMeshTLS) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *InboundNonMeshTLS) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *OutboundNonMeshTLS) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *OutboundNonMeshTLS) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *MeshInboundValidationContext) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *MeshInboundValidationContext) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *MeshOutboundValidationContext) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *MeshOutboundValidationContext) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *NonMeshOutboundValidationContext) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *NonMeshOutboundValidationContext) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *SDSCertificate) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *SDSCertificate) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TLSParameters) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TLSParameters) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LeafCertificate) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LeafCertificate) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TrustBundle) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TrustBundle) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket.pb.go b/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket.pb.go deleted file mode 100644 index d3acedebd182..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket.pb.go +++ /dev/null @@ -1,1507 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/pbproxystate/transport_socket.proto - -package pbproxystate - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=TLS_VERSION_AUTO;TLS_VERSION_1_0;TLS_VERSION_1_1;TLS_VERSION_1_2;TLS_VERSION_1_3;TLS_VERSION_INVALID;TLS_VERSION_UNSPECIFIED -// +kubebuilder:validation:Type=string -type TLSVersion int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - TLSVersion_TLS_VERSION_AUTO TLSVersion = 0 - TLSVersion_TLS_VERSION_1_0 TLSVersion = 1 - TLSVersion_TLS_VERSION_1_1 TLSVersion = 2 - TLSVersion_TLS_VERSION_1_2 TLSVersion = 3 - TLSVersion_TLS_VERSION_1_3 TLSVersion = 4 - TLSVersion_TLS_VERSION_INVALID TLSVersion = 5 - TLSVersion_TLS_VERSION_UNSPECIFIED TLSVersion = 6 -) - -// Enum value maps for TLSVersion. -var ( - TLSVersion_name = map[int32]string{ - 0: "TLS_VERSION_AUTO", - 1: "TLS_VERSION_1_0", - 2: "TLS_VERSION_1_1", - 3: "TLS_VERSION_1_2", - 4: "TLS_VERSION_1_3", - 5: "TLS_VERSION_INVALID", - 6: "TLS_VERSION_UNSPECIFIED", - } - TLSVersion_value = map[string]int32{ - "TLS_VERSION_AUTO": 0, - "TLS_VERSION_1_0": 1, - "TLS_VERSION_1_1": 2, - "TLS_VERSION_1_2": 3, - "TLS_VERSION_1_3": 4, - "TLS_VERSION_INVALID": 5, - "TLS_VERSION_UNSPECIFIED": 6, - } -) - -func (x TLSVersion) Enum() *TLSVersion { - p := new(TLSVersion) - *p = x - return p -} - -func (x TLSVersion) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (TLSVersion) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_enumTypes[0].Descriptor() -} - -func (TLSVersion) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_enumTypes[0] -} - -func (x TLSVersion) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use TLSVersion.Descriptor instead. -func (TLSVersion) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{0} -} - -// +kubebuilder:validation:Enum=TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256;TLS_CIPHER_SUITE_AES256_SHA;TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305;TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256;TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305;TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA;TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA;TLS_CIPHER_SUITE_AES128_GCM_SHA256;TLS_CIPHER_SUITE_AES128_SHA;TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384;TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384;TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA;TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA;TLS_CIPHER_SUITE_AES256_GCM_SHA384 -// +kubebuilder:validation:Type=string -type TLSCipherSuite int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256 TLSCipherSuite = 0 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305 TLSCipherSuite = 1 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256 TLSCipherSuite = 2 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305 TLSCipherSuite = 3 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA TLSCipherSuite = 4 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA TLSCipherSuite = 5 - TLSCipherSuite_TLS_CIPHER_SUITE_AES128_GCM_SHA256 TLSCipherSuite = 6 - TLSCipherSuite_TLS_CIPHER_SUITE_AES128_SHA TLSCipherSuite = 7 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384 TLSCipherSuite = 8 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384 TLSCipherSuite = 9 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA TLSCipherSuite = 10 - TLSCipherSuite_TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA TLSCipherSuite = 11 - TLSCipherSuite_TLS_CIPHER_SUITE_AES256_GCM_SHA384 TLSCipherSuite = 12 - TLSCipherSuite_TLS_CIPHER_SUITE_AES256_SHA TLSCipherSuite = 13 -) - -// Enum value maps for TLSCipherSuite. -var ( - TLSCipherSuite_name = map[int32]string{ - 0: "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256", - 1: "TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305", - 2: "TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256", - 3: "TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305", - 4: "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA", - 5: "TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA", - 6: "TLS_CIPHER_SUITE_AES128_GCM_SHA256", - 7: "TLS_CIPHER_SUITE_AES128_SHA", - 8: "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384", - 9: "TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384", - 10: "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA", - 11: "TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA", - 12: "TLS_CIPHER_SUITE_AES256_GCM_SHA384", - 13: "TLS_CIPHER_SUITE_AES256_SHA", - } - TLSCipherSuite_value = map[string]int32{ - "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256": 0, - "TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305": 1, - "TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256": 2, - "TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305": 3, - "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA": 4, - "TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA": 5, - "TLS_CIPHER_SUITE_AES128_GCM_SHA256": 6, - "TLS_CIPHER_SUITE_AES128_SHA": 7, - "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384": 8, - "TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384": 9, - "TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA": 10, - "TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA": 11, - "TLS_CIPHER_SUITE_AES256_GCM_SHA384": 12, - "TLS_CIPHER_SUITE_AES256_SHA": 13, - } -) - -func (x TLSCipherSuite) Enum() *TLSCipherSuite { - p := new(TLSCipherSuite) - *p = x - return p -} - -func (x TLSCipherSuite) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (TLSCipherSuite) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_enumTypes[1].Descriptor() -} - -func (TLSCipherSuite) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_enumTypes[1] -} - -func (x TLSCipherSuite) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use TLSCipherSuite.Descriptor instead. -func (TLSCipherSuite) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{1} -} - -type TLS struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // inbound_tls_parameters has default TLS parameter configuration for inbound connections. These can be overridden per - // transport socket. - InboundTlsParameters *TLSParameters `protobuf:"bytes,1,opt,name=inbound_tls_parameters,json=inboundTlsParameters,proto3" json:"inbound_tls_parameters,omitempty"` - // outbound_tls_parameters has default TLS parameter configuration for inbound connections. These can be overridden per transport socket. - OutboundTlsParameters *TLSParameters `protobuf:"bytes,2,opt,name=outbound_tls_parameters,json=outboundTlsParameters,proto3" json:"outbound_tls_parameters,omitempty"` -} - -func (x *TLS) Reset() { - *x = TLS{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TLS) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TLS) ProtoMessage() {} - -func (x *TLS) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TLS.ProtoReflect.Descriptor instead. -func (*TLS) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{0} -} - -func (x *TLS) GetInboundTlsParameters() *TLSParameters { - if x != nil { - return x.InboundTlsParameters - } - return nil -} - -func (x *TLS) GetOutboundTlsParameters() *TLSParameters { - if x != nil { - return x.OutboundTlsParameters - } - return nil -} - -type TransportSocket struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // name of the transport socket - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // Types that are assignable to ConnectionTls: - // - // *TransportSocket_InboundMesh - // *TransportSocket_OutboundMesh - // *TransportSocket_InboundNonMesh - // *TransportSocket_OutboundNonMesh - ConnectionTls isTransportSocket_ConnectionTls `protobuf_oneof:"connection_tls"` - // tls_parameters can override any top level tls parameters that are configured. - TlsParameters *TLSParameters `protobuf:"bytes,6,opt,name=tls_parameters,json=tlsParameters,proto3" json:"tls_parameters,omitempty"` - AlpnProtocols []string `protobuf:"bytes,7,rep,name=alpn_protocols,json=alpnProtocols,proto3" json:"alpn_protocols,omitempty"` -} - -func (x *TransportSocket) Reset() { - *x = TransportSocket{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TransportSocket) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TransportSocket) ProtoMessage() {} - -func (x *TransportSocket) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TransportSocket.ProtoReflect.Descriptor instead. -func (*TransportSocket) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{1} -} - -func (x *TransportSocket) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (m *TransportSocket) GetConnectionTls() isTransportSocket_ConnectionTls { - if m != nil { - return m.ConnectionTls - } - return nil -} - -func (x *TransportSocket) GetInboundMesh() *InboundMeshMTLS { - if x, ok := x.GetConnectionTls().(*TransportSocket_InboundMesh); ok { - return x.InboundMesh - } - return nil -} - -func (x *TransportSocket) GetOutboundMesh() *OutboundMeshMTLS { - if x, ok := x.GetConnectionTls().(*TransportSocket_OutboundMesh); ok { - return x.OutboundMesh - } - return nil -} - -func (x *TransportSocket) GetInboundNonMesh() *InboundNonMeshTLS { - if x, ok := x.GetConnectionTls().(*TransportSocket_InboundNonMesh); ok { - return x.InboundNonMesh - } - return nil -} - -func (x *TransportSocket) GetOutboundNonMesh() *OutboundNonMeshTLS { - if x, ok := x.GetConnectionTls().(*TransportSocket_OutboundNonMesh); ok { - return x.OutboundNonMesh - } - return nil -} - -func (x *TransportSocket) GetTlsParameters() *TLSParameters { - if x != nil { - return x.TlsParameters - } - return nil -} - -func (x *TransportSocket) GetAlpnProtocols() []string { - if x != nil { - return x.AlpnProtocols - } - return nil -} - -type isTransportSocket_ConnectionTls interface { - isTransportSocket_ConnectionTls() -} - -type TransportSocket_InboundMesh struct { - // inbound_mesh is for incoming connections FROM the mesh. - InboundMesh *InboundMeshMTLS `protobuf:"bytes,2,opt,name=inbound_mesh,json=inboundMesh,proto3,oneof"` -} - -type TransportSocket_OutboundMesh struct { - // outbound_mesh is for outbound connections TO mesh destinations. - OutboundMesh *OutboundMeshMTLS `protobuf:"bytes,3,opt,name=outbound_mesh,json=outboundMesh,proto3,oneof"` -} - -type TransportSocket_InboundNonMesh struct { - // inbound_non_mesh is for incoming connections FROM non mesh. - InboundNonMesh *InboundNonMeshTLS `protobuf:"bytes,4,opt,name=inbound_non_mesh,json=inboundNonMesh,proto3,oneof"` -} - -type TransportSocket_OutboundNonMesh struct { - // outbound_non_mesh is for outbound connections TO non mesh destinations. - OutboundNonMesh *OutboundNonMeshTLS `protobuf:"bytes,5,opt,name=outbound_non_mesh,json=outboundNonMesh,proto3,oneof"` -} - -func (*TransportSocket_InboundMesh) isTransportSocket_ConnectionTls() {} - -func (*TransportSocket_OutboundMesh) isTransportSocket_ConnectionTls() {} - -func (*TransportSocket_InboundNonMesh) isTransportSocket_ConnectionTls() {} - -func (*TransportSocket_OutboundNonMesh) isTransportSocket_ConnectionTls() {} - -type InboundMeshMTLS struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // identity_key is UUID key to use to look up the leaf certificate in ProxyState to present for incoming connections. - IdentityKey string `protobuf:"bytes,1,opt,name=identity_key,json=identityKey,proto3" json:"identity_key,omitempty"` - // validation_context has what is needed to validate incoming connections. - ValidationContext *MeshInboundValidationContext `protobuf:"bytes,2,opt,name=validation_context,json=validationContext,proto3" json:"validation_context,omitempty"` -} - -func (x *InboundMeshMTLS) Reset() { - *x = InboundMeshMTLS{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InboundMeshMTLS) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InboundMeshMTLS) ProtoMessage() {} - -func (x *InboundMeshMTLS) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use InboundMeshMTLS.ProtoReflect.Descriptor instead. -func (*InboundMeshMTLS) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{2} -} - -func (x *InboundMeshMTLS) GetIdentityKey() string { - if x != nil { - return x.IdentityKey - } - return "" -} - -func (x *InboundMeshMTLS) GetValidationContext() *MeshInboundValidationContext { - if x != nil { - return x.ValidationContext - } - return nil -} - -type OutboundMeshMTLS struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // identity_key is UUID key to use to look up the leaf certificate in ProxyState when connecting to destinations. - IdentityKey string `protobuf:"bytes,1,opt,name=identity_key,json=identityKey,proto3" json:"identity_key,omitempty"` - // validation_context has what is needed to validate the destination. - ValidationContext *MeshOutboundValidationContext `protobuf:"bytes,2,opt,name=validation_context,json=validationContext,proto3" json:"validation_context,omitempty"` - // sni to use when connecting to the destination. - Sni string `protobuf:"bytes,3,opt,name=sni,proto3" json:"sni,omitempty"` -} - -func (x *OutboundMeshMTLS) Reset() { - *x = OutboundMeshMTLS{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OutboundMeshMTLS) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OutboundMeshMTLS) ProtoMessage() {} - -func (x *OutboundMeshMTLS) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OutboundMeshMTLS.ProtoReflect.Descriptor instead. -func (*OutboundMeshMTLS) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{3} -} - -func (x *OutboundMeshMTLS) GetIdentityKey() string { - if x != nil { - return x.IdentityKey - } - return "" -} - -func (x *OutboundMeshMTLS) GetValidationContext() *MeshOutboundValidationContext { - if x != nil { - return x.ValidationContext - } - return nil -} - -func (x *OutboundMeshMTLS) GetSni() string { - if x != nil { - return x.Sni - } - return "" -} - -type InboundNonMeshTLS struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // identity is the reference to the leaf certificate to present for incoming connections. - // - // Types that are assignable to Identity: - // - // *InboundNonMeshTLS_LeafKey - // *InboundNonMeshTLS_Sds - Identity isInboundNonMeshTLS_Identity `protobuf_oneof:"identity"` -} - -func (x *InboundNonMeshTLS) Reset() { - *x = InboundNonMeshTLS{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InboundNonMeshTLS) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InboundNonMeshTLS) ProtoMessage() {} - -func (x *InboundNonMeshTLS) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use InboundNonMeshTLS.ProtoReflect.Descriptor instead. -func (*InboundNonMeshTLS) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{4} -} - -func (m *InboundNonMeshTLS) GetIdentity() isInboundNonMeshTLS_Identity { - if m != nil { - return m.Identity - } - return nil -} - -func (x *InboundNonMeshTLS) GetLeafKey() string { - if x, ok := x.GetIdentity().(*InboundNonMeshTLS_LeafKey); ok { - return x.LeafKey - } - return "" -} - -func (x *InboundNonMeshTLS) GetSds() *SDSCertificate { - if x, ok := x.GetIdentity().(*InboundNonMeshTLS_Sds); ok { - return x.Sds - } - return nil -} - -type isInboundNonMeshTLS_Identity interface { - isInboundNonMeshTLS_Identity() -} - -type InboundNonMeshTLS_LeafKey struct { - // leaf_key is the UUID key to use to look up the leaf certificate in the ProxyState leaf certificate map. - LeafKey string `protobuf:"bytes,1,opt,name=leaf_key,json=leafKey,proto3,oneof"` -} - -type InboundNonMeshTLS_Sds struct { - // sds refers to certificates retrieved via Envoy SDS. - Sds *SDSCertificate `protobuf:"bytes,2,opt,name=sds,proto3,oneof"` -} - -func (*InboundNonMeshTLS_LeafKey) isInboundNonMeshTLS_Identity() {} - -func (*InboundNonMeshTLS_Sds) isInboundNonMeshTLS_Identity() {} - -type OutboundNonMeshTLS struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // cert_file is a filename for a certificate to present for outbound connections. - CertFile string `protobuf:"bytes,1,opt,name=cert_file,json=certFile,proto3" json:"cert_file,omitempty"` - // key_file is a filename for a key for outbound connections. - KeyFile string `protobuf:"bytes,2,opt,name=key_file,json=keyFile,proto3" json:"key_file,omitempty"` - // validation_context has what is needed to validate the destination. - ValidationContext *NonMeshOutboundValidationContext `protobuf:"bytes,3,opt,name=validation_context,json=validationContext,proto3" json:"validation_context,omitempty"` -} - -func (x *OutboundNonMeshTLS) Reset() { - *x = OutboundNonMeshTLS{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OutboundNonMeshTLS) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OutboundNonMeshTLS) ProtoMessage() {} - -func (x *OutboundNonMeshTLS) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OutboundNonMeshTLS.ProtoReflect.Descriptor instead. -func (*OutboundNonMeshTLS) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{5} -} - -func (x *OutboundNonMeshTLS) GetCertFile() string { - if x != nil { - return x.CertFile - } - return "" -} - -func (x *OutboundNonMeshTLS) GetKeyFile() string { - if x != nil { - return x.KeyFile - } - return "" -} - -func (x *OutboundNonMeshTLS) GetValidationContext() *NonMeshOutboundValidationContext { - if x != nil { - return x.ValidationContext - } - return nil -} - -type MeshInboundValidationContext struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // trust_bundle_peer_name_keys is which trust bundles to use for validating incoming connections. If this workload is exported - // to peers, the incoming connection could be from a different peer, requiring that trust bundle to validate the - // connection. These could be local or peered trust bundles. This will be a key in the trust bundle map. - TrustBundlePeerNameKeys []string `protobuf:"bytes,1,rep,name=trust_bundle_peer_name_keys,json=trustBundlePeerNameKeys,proto3" json:"trust_bundle_peer_name_keys,omitempty"` -} - -func (x *MeshInboundValidationContext) Reset() { - *x = MeshInboundValidationContext{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MeshInboundValidationContext) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MeshInboundValidationContext) ProtoMessage() {} - -func (x *MeshInboundValidationContext) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MeshInboundValidationContext.ProtoReflect.Descriptor instead. -func (*MeshInboundValidationContext) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{6} -} - -func (x *MeshInboundValidationContext) GetTrustBundlePeerNameKeys() []string { - if x != nil { - return x.TrustBundlePeerNameKeys - } - return nil -} - -type MeshOutboundValidationContext struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // trust_bundle_peer_name_key is which trust bundle to use for the destination. It could be the local or a peer's trust bundle. - // This will be a key in the trust bundle map. - TrustBundlePeerNameKey string `protobuf:"bytes,1,opt,name=trust_bundle_peer_name_key,json=trustBundlePeerNameKey,proto3" json:"trust_bundle_peer_name_key,omitempty"` - // spiffe_ids is one or more spiffe IDs to validate. - SpiffeIds []string `protobuf:"bytes,2,rep,name=spiffe_ids,json=spiffeIds,proto3" json:"spiffe_ids,omitempty"` -} - -func (x *MeshOutboundValidationContext) Reset() { - *x = MeshOutboundValidationContext{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MeshOutboundValidationContext) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MeshOutboundValidationContext) ProtoMessage() {} - -func (x *MeshOutboundValidationContext) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MeshOutboundValidationContext.ProtoReflect.Descriptor instead. -func (*MeshOutboundValidationContext) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{7} -} - -func (x *MeshOutboundValidationContext) GetTrustBundlePeerNameKey() string { - if x != nil { - return x.TrustBundlePeerNameKey - } - return "" -} - -func (x *MeshOutboundValidationContext) GetSpiffeIds() []string { - if x != nil { - return x.SpiffeIds - } - return nil -} - -type NonMeshOutboundValidationContext struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ca_file is a filename for a ca for outbound connections to validate the destination. - CaFile string `protobuf:"bytes,1,opt,name=ca_file,json=caFile,proto3" json:"ca_file,omitempty"` -} - -func (x *NonMeshOutboundValidationContext) Reset() { - *x = NonMeshOutboundValidationContext{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NonMeshOutboundValidationContext) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NonMeshOutboundValidationContext) ProtoMessage() {} - -func (x *NonMeshOutboundValidationContext) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NonMeshOutboundValidationContext.ProtoReflect.Descriptor instead. -func (*NonMeshOutboundValidationContext) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{8} -} - -func (x *NonMeshOutboundValidationContext) GetCaFile() string { - if x != nil { - return x.CaFile - } - return "" -} - -type SDSCertificate struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ClusterName string `protobuf:"bytes,1,opt,name=cluster_name,json=clusterName,proto3" json:"cluster_name,omitempty"` - CertResource string `protobuf:"bytes,2,opt,name=cert_resource,json=certResource,proto3" json:"cert_resource,omitempty"` -} - -func (x *SDSCertificate) Reset() { - *x = SDSCertificate{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SDSCertificate) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SDSCertificate) ProtoMessage() {} - -func (x *SDSCertificate) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SDSCertificate.ProtoReflect.Descriptor instead. -func (*SDSCertificate) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{9} -} - -func (x *SDSCertificate) GetClusterName() string { - if x != nil { - return x.ClusterName - } - return "" -} - -func (x *SDSCertificate) GetCertResource() string { - if x != nil { - return x.CertResource - } - return "" -} - -type TLSParameters struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MinVersion TLSVersion `protobuf:"varint,1,opt,name=min_version,json=minVersion,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.TLSVersion" json:"min_version,omitempty"` - MaxVersion TLSVersion `protobuf:"varint,2,opt,name=max_version,json=maxVersion,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.TLSVersion" json:"max_version,omitempty"` - CipherSuites []TLSCipherSuite `protobuf:"varint,3,rep,packed,name=cipher_suites,json=cipherSuites,proto3,enum=hashicorp.consul.mesh.v2beta1.pbproxystate.TLSCipherSuite" json:"cipher_suites,omitempty"` -} - -func (x *TLSParameters) Reset() { - *x = TLSParameters{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TLSParameters) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TLSParameters) ProtoMessage() {} - -func (x *TLSParameters) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TLSParameters.ProtoReflect.Descriptor instead. -func (*TLSParameters) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{10} -} - -func (x *TLSParameters) GetMinVersion() TLSVersion { - if x != nil { - return x.MinVersion - } - return TLSVersion_TLS_VERSION_AUTO -} - -func (x *TLSParameters) GetMaxVersion() TLSVersion { - if x != nil { - return x.MaxVersion - } - return TLSVersion_TLS_VERSION_AUTO -} - -func (x *TLSParameters) GetCipherSuites() []TLSCipherSuite { - if x != nil { - return x.CipherSuites - } - return nil -} - -type LeafCertificate struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Cert string `protobuf:"bytes,1,opt,name=cert,proto3" json:"cert,omitempty"` - Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` -} - -func (x *LeafCertificate) Reset() { - *x = LeafCertificate{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LeafCertificate) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LeafCertificate) ProtoMessage() {} - -func (x *LeafCertificate) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LeafCertificate.ProtoReflect.Descriptor instead. -func (*LeafCertificate) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{11} -} - -func (x *LeafCertificate) GetCert() string { - if x != nil { - return x.Cert - } - return "" -} - -func (x *LeafCertificate) GetKey() string { - if x != nil { - return x.Key - } - return "" -} - -type TrustBundle struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TrustDomain string `protobuf:"bytes,1,opt,name=trust_domain,json=trustDomain,proto3" json:"trust_domain,omitempty"` - Roots []string `protobuf:"bytes,2,rep,name=roots,proto3" json:"roots,omitempty"` -} - -func (x *TrustBundle) Reset() { - *x = TrustBundle{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TrustBundle) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TrustBundle) ProtoMessage() {} - -func (x *TrustBundle) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TrustBundle.ProtoReflect.Descriptor instead. -func (*TrustBundle) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP(), []int{12} -} - -func (x *TrustBundle) GetTrustDomain() string { - if x != nil { - return x.TrustDomain - } - return "" -} - -func (x *TrustBundle) GetRoots() []string { - if x != nil { - return x.Roots - } - return nil -} - -var File_pbmesh_v2beta1_pbproxystate_transport_socket_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDesc = []byte{ - 0x0a, 0x32, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x22, 0xe9, 0x01, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x6f, 0x0a, 0x16, 0x69, 0x6e, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x4c, 0x53, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x73, 0x52, 0x14, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x6c, 0x73, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x71, 0x0a, 0x17, 0x6f, 0x75, 0x74, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x4c, 0x53, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x15, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, - 0x6c, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x22, 0xe0, 0x04, 0x0a, - 0x0f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x60, 0x0a, 0x0c, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, - 0x6d, 0x65, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4d, - 0x65, 0x73, 0x68, 0x4d, 0x54, 0x4c, 0x53, 0x48, 0x00, 0x52, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x12, 0x63, 0x0a, 0x0d, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x4d, 0x54, 0x4c, 0x53, 0x48, 0x00, 0x52, 0x0c, 0x6f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x12, 0x69, 0x0a, 0x10, 0x69, - 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x6e, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x73, 0x68, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4e, 0x6f, 0x6e, 0x4d, 0x65, 0x73, - 0x68, 0x54, 0x4c, 0x53, 0x48, 0x00, 0x52, 0x0e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4e, - 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x12, 0x6c, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x5f, 0x6e, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4e, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x4c, - 0x53, 0x48, 0x00, 0x52, 0x0f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4e, 0x6f, 0x6e, - 0x4d, 0x65, 0x73, 0x68, 0x12, 0x60, 0x0a, 0x0e, 0x74, 0x6c, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x4c, 0x53, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0d, 0x74, 0x6c, 0x73, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x70, 0x6e, 0x5f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, - 0x61, 0x6c, 0x70, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x10, 0x0a, - 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6c, 0x73, 0x22, - 0xad, 0x01, 0x0a, 0x0f, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x4d, - 0x54, 0x4c, 0x53, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x12, 0x77, 0x0a, 0x12, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, - 0x4d, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x11, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, - 0xc1, 0x01, 0x0a, 0x10, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, - 0x4d, 0x54, 0x4c, 0x53, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x12, 0x78, 0x0a, 0x12, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x11, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x6e, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x73, 0x6e, 0x69, 0x22, 0x8c, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4e, - 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x4c, 0x53, 0x12, 0x1b, 0x0a, 0x08, 0x6c, 0x65, 0x61, - 0x66, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x6c, - 0x65, 0x61, 0x66, 0x4b, 0x65, 0x79, 0x12, 0x4e, 0x0a, 0x03, 0x73, 0x64, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x53, 0x44, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x48, - 0x00, 0x52, 0x03, 0x73, 0x64, 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x22, 0xc9, 0x01, 0x0a, 0x12, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4e, - 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x4c, 0x53, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x65, 0x72, - 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x65, - 0x72, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, - 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x46, 0x69, 0x6c, - 0x65, 0x12, 0x7b, 0x0a, 0x12, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4c, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4e, 0x6f, 0x6e, 0x4d, 0x65, - 0x73, 0x68, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x11, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x5c, - 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x3c, - 0x0a, 0x1b, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x70, - 0x65, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x17, 0x74, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x22, 0x7a, 0x0a, 0x1d, - 0x4d, 0x65, 0x73, 0x68, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x3a, 0x0a, - 0x1a, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x70, 0x65, - 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x16, 0x74, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x65, - 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x70, 0x69, - 0x66, 0x66, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x73, - 0x70, 0x69, 0x66, 0x66, 0x65, 0x49, 0x64, 0x73, 0x22, 0x3b, 0x0a, 0x20, 0x4e, 0x6f, 0x6e, 0x4d, - 0x65, 0x73, 0x68, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x17, 0x0a, 0x07, - 0x63, 0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, - 0x61, 0x46, 0x69, 0x6c, 0x65, 0x22, 0x58, 0x0a, 0x0e, 0x53, 0x44, 0x53, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x65, - 0x72, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x63, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, - 0xa2, 0x02, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x73, 0x12, 0x57, 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x2e, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, - 0x6d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x57, 0x0a, 0x0b, 0x6d, 0x61, - 0x78, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x4c, 0x53, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x5f, 0x0a, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, - 0x69, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x4c, 0x53, 0x43, 0x69, 0x70, 0x68, 0x65, - 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x52, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, - 0x69, 0x74, 0x65, 0x73, 0x22, 0x37, 0x0a, 0x0f, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x46, 0x0a, - 0x0b, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x0c, - 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x74, 0x72, 0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, - 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, - 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x2a, 0xac, 0x01, 0x0a, 0x0a, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, - 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x55, 0x54, 0x4f, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x4c, - 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x30, 0x10, 0x01, 0x12, - 0x13, 0x0a, 0x0f, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x31, - 0x5f, 0x31, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, - 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x32, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x4c, 0x53, - 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x33, 0x10, 0x04, 0x12, 0x17, - 0x0a, 0x13, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, - 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x05, 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x4c, 0x53, 0x5f, 0x56, - 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x06, 0x2a, 0x84, 0x05, 0x0a, 0x0e, 0x54, 0x4c, 0x53, 0x43, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x12, 0x32, 0x0a, 0x2e, 0x54, 0x4c, 0x53, 0x5f, 0x43, - 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, - 0x45, 0x5f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x41, 0x45, 0x53, 0x31, 0x32, 0x38, 0x5f, 0x47, - 0x43, 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x00, 0x12, 0x32, 0x0a, 0x2e, 0x54, - 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, - 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x43, 0x48, 0x41, 0x43, - 0x48, 0x41, 0x32, 0x30, 0x5f, 0x50, 0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, 0x35, 0x10, 0x01, 0x12, - 0x30, 0x0a, 0x2c, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, - 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x41, 0x45, - 0x53, 0x31, 0x32, 0x38, 0x5f, 0x47, 0x43, 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, - 0x02, 0x12, 0x30, 0x0a, 0x2c, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, - 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, - 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x50, 0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, - 0x35, 0x10, 0x03, 0x12, 0x2b, 0x0a, 0x27, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, - 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x45, 0x43, - 0x44, 0x53, 0x41, 0x5f, 0x41, 0x45, 0x53, 0x31, 0x32, 0x38, 0x5f, 0x53, 0x48, 0x41, 0x10, 0x04, - 0x12, 0x29, 0x0a, 0x25, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, - 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x41, - 0x45, 0x53, 0x31, 0x32, 0x38, 0x5f, 0x53, 0x48, 0x41, 0x10, 0x05, 0x12, 0x26, 0x0a, 0x22, 0x54, - 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, - 0x41, 0x45, 0x53, 0x31, 0x32, 0x38, 0x5f, 0x47, 0x43, 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, - 0x36, 0x10, 0x06, 0x12, 0x1f, 0x0a, 0x1b, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, - 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x41, 0x45, 0x53, 0x31, 0x32, 0x38, 0x5f, 0x53, - 0x48, 0x41, 0x10, 0x07, 0x12, 0x32, 0x0a, 0x2e, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, - 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x45, - 0x43, 0x44, 0x53, 0x41, 0x5f, 0x41, 0x45, 0x53, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, 0x4d, 0x5f, - 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x08, 0x12, 0x30, 0x0a, 0x2c, 0x54, 0x4c, 0x53, 0x5f, - 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, - 0x48, 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x41, 0x45, 0x53, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, - 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x09, 0x12, 0x2b, 0x0a, 0x27, 0x54, 0x4c, - 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, - 0x43, 0x44, 0x48, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x41, 0x45, 0x53, 0x32, 0x35, - 0x36, 0x5f, 0x53, 0x48, 0x41, 0x10, 0x0a, 0x12, 0x29, 0x0a, 0x25, 0x54, 0x4c, 0x53, 0x5f, 0x43, - 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, - 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x41, 0x45, 0x53, 0x32, 0x35, 0x36, 0x5f, 0x53, 0x48, 0x41, - 0x10, 0x0b, 0x12, 0x26, 0x0a, 0x22, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, - 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x41, 0x45, 0x53, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, - 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x0c, 0x12, 0x1f, 0x0a, 0x1b, 0x54, 0x4c, - 0x53, 0x5f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x41, - 0x45, 0x53, 0x32, 0x35, 0x36, 0x5f, 0x53, 0x48, 0x41, 0x10, 0x0d, 0x42, 0xda, 0x02, 0x0a, 0x2e, - 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x14, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, - 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xa2, 0x02, 0x05, 0x48, - 0x43, 0x4d, 0x56, 0x50, 0xaa, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0xca, 0x02, 0x2a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x5c, 0x50, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0xe2, 0x02, - 0x36, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x50, - 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, - 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3a, 0x3a, 0x50, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescData = file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDesc -) - -func file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescData) - }) - return file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDescData -} - -var file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes = make([]protoimpl.MessageInfo, 13) -var file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_goTypes = []interface{}{ - (TLSVersion)(0), // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.TLSVersion - (TLSCipherSuite)(0), // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.TLSCipherSuite - (*TLS)(nil), // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.TLS - (*TransportSocket)(nil), // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.TransportSocket - (*InboundMeshMTLS)(nil), // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.InboundMeshMTLS - (*OutboundMeshMTLS)(nil), // 5: hashicorp.consul.mesh.v2beta1.pbproxystate.OutboundMeshMTLS - (*InboundNonMeshTLS)(nil), // 6: hashicorp.consul.mesh.v2beta1.pbproxystate.InboundNonMeshTLS - (*OutboundNonMeshTLS)(nil), // 7: hashicorp.consul.mesh.v2beta1.pbproxystate.OutboundNonMeshTLS - (*MeshInboundValidationContext)(nil), // 8: hashicorp.consul.mesh.v2beta1.pbproxystate.MeshInboundValidationContext - (*MeshOutboundValidationContext)(nil), // 9: hashicorp.consul.mesh.v2beta1.pbproxystate.MeshOutboundValidationContext - (*NonMeshOutboundValidationContext)(nil), // 10: hashicorp.consul.mesh.v2beta1.pbproxystate.NonMeshOutboundValidationContext - (*SDSCertificate)(nil), // 11: hashicorp.consul.mesh.v2beta1.pbproxystate.SDSCertificate - (*TLSParameters)(nil), // 12: hashicorp.consul.mesh.v2beta1.pbproxystate.TLSParameters - (*LeafCertificate)(nil), // 13: hashicorp.consul.mesh.v2beta1.pbproxystate.LeafCertificate - (*TrustBundle)(nil), // 14: hashicorp.consul.mesh.v2beta1.pbproxystate.TrustBundle -} -var file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_depIdxs = []int32{ - 12, // 0: hashicorp.consul.mesh.v2beta1.pbproxystate.TLS.inbound_tls_parameters:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TLSParameters - 12, // 1: hashicorp.consul.mesh.v2beta1.pbproxystate.TLS.outbound_tls_parameters:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TLSParameters - 4, // 2: hashicorp.consul.mesh.v2beta1.pbproxystate.TransportSocket.inbound_mesh:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.InboundMeshMTLS - 5, // 3: hashicorp.consul.mesh.v2beta1.pbproxystate.TransportSocket.outbound_mesh:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.OutboundMeshMTLS - 6, // 4: hashicorp.consul.mesh.v2beta1.pbproxystate.TransportSocket.inbound_non_mesh:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.InboundNonMeshTLS - 7, // 5: hashicorp.consul.mesh.v2beta1.pbproxystate.TransportSocket.outbound_non_mesh:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.OutboundNonMeshTLS - 12, // 6: hashicorp.consul.mesh.v2beta1.pbproxystate.TransportSocket.tls_parameters:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TLSParameters - 8, // 7: hashicorp.consul.mesh.v2beta1.pbproxystate.InboundMeshMTLS.validation_context:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.MeshInboundValidationContext - 9, // 8: hashicorp.consul.mesh.v2beta1.pbproxystate.OutboundMeshMTLS.validation_context:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.MeshOutboundValidationContext - 11, // 9: hashicorp.consul.mesh.v2beta1.pbproxystate.InboundNonMeshTLS.sds:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.SDSCertificate - 10, // 10: hashicorp.consul.mesh.v2beta1.pbproxystate.OutboundNonMeshTLS.validation_context:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.NonMeshOutboundValidationContext - 0, // 11: hashicorp.consul.mesh.v2beta1.pbproxystate.TLSParameters.min_version:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TLSVersion - 0, // 12: hashicorp.consul.mesh.v2beta1.pbproxystate.TLSParameters.max_version:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TLSVersion - 1, // 13: hashicorp.consul.mesh.v2beta1.pbproxystate.TLSParameters.cipher_suites:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TLSCipherSuite - 14, // [14:14] is the sub-list for method output_type - 14, // [14:14] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_init() } -func file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_init() { - if File_pbmesh_v2beta1_pbproxystate_transport_socket_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TLS); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransportSocket); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InboundMeshMTLS); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OutboundMeshMTLS); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InboundNonMeshTLS); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OutboundNonMeshTLS); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MeshInboundValidationContext); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MeshOutboundValidationContext); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NonMeshOutboundValidationContext); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SDSCertificate); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TLSParameters); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LeafCertificate); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TrustBundle); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*TransportSocket_InboundMesh)(nil), - (*TransportSocket_OutboundMesh)(nil), - (*TransportSocket_InboundNonMesh)(nil), - (*TransportSocket_OutboundNonMesh)(nil), - } - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes[4].OneofWrappers = []interface{}{ - (*InboundNonMeshTLS_LeafKey)(nil), - (*InboundNonMeshTLS_Sds)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDesc, - NumEnums: 2, - NumMessages: 13, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_pbproxystate_transport_socket_proto = out.File - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_rawDesc = nil - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_goTypes = nil - file_pbmesh_v2beta1_pbproxystate_transport_socket_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket.proto b/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket.proto deleted file mode 100644 index 9ff4f001de9d..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket.proto +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1.pbproxystate; - -message TLS { - // inbound_tls_parameters has default TLS parameter configuration for inbound connections. These can be overridden per - // transport socket. - TLSParameters inbound_tls_parameters = 1; - // outbound_tls_parameters has default TLS parameter configuration for inbound connections. These can be overridden per transport socket. - TLSParameters outbound_tls_parameters = 2; -} - -message TransportSocket { - // name of the transport socket - string name = 1; - oneof connection_tls { - // inbound_mesh is for incoming connections FROM the mesh. - InboundMeshMTLS inbound_mesh = 2; - // outbound_mesh is for outbound connections TO mesh destinations. - OutboundMeshMTLS outbound_mesh = 3; - // inbound_non_mesh is for incoming connections FROM non mesh. - InboundNonMeshTLS inbound_non_mesh = 4; - // outbound_non_mesh is for outbound connections TO non mesh destinations. - OutboundNonMeshTLS outbound_non_mesh = 5; - } - // tls_parameters can override any top level tls parameters that are configured. - TLSParameters tls_parameters = 6; - repeated string alpn_protocols = 7; -} - -message InboundMeshMTLS { - // identity_key is UUID key to use to look up the leaf certificate in ProxyState to present for incoming connections. - string identity_key = 1; - // validation_context has what is needed to validate incoming connections. - MeshInboundValidationContext validation_context = 2; -} - -message OutboundMeshMTLS { - // identity_key is UUID key to use to look up the leaf certificate in ProxyState when connecting to destinations. - string identity_key = 1; - // validation_context has what is needed to validate the destination. - MeshOutboundValidationContext validation_context = 2; - // sni to use when connecting to the destination. - string sni = 3; -} - -message InboundNonMeshTLS { - // identity is the reference to the leaf certificate to present for incoming connections. - oneof identity { - // leaf_key is the UUID key to use to look up the leaf certificate in the ProxyState leaf certificate map. - string leaf_key = 1; - // sds refers to certificates retrieved via Envoy SDS. - SDSCertificate sds = 2; - } -} - -message OutboundNonMeshTLS { - // cert_file is a filename for a certificate to present for outbound connections. - string cert_file = 1; - // key_file is a filename for a key for outbound connections. - string key_file = 2; - // validation_context has what is needed to validate the destination. - NonMeshOutboundValidationContext validation_context = 3; -} - -message MeshInboundValidationContext { - // trust_bundle_peer_name_keys is which trust bundles to use for validating incoming connections. If this workload is exported - // to peers, the incoming connection could be from a different peer, requiring that trust bundle to validate the - // connection. These could be local or peered trust bundles. This will be a key in the trust bundle map. - repeated string trust_bundle_peer_name_keys = 1; -} - -message MeshOutboundValidationContext { - // trust_bundle_peer_name_key is which trust bundle to use for the destination. It could be the local or a peer's trust bundle. - // This will be a key in the trust bundle map. - string trust_bundle_peer_name_key = 1; - // spiffe_ids is one or more spiffe IDs to validate. - repeated string spiffe_ids = 2; -} - -message NonMeshOutboundValidationContext { - // ca_file is a filename for a ca for outbound connections to validate the destination. - string ca_file = 1; -} - -message SDSCertificate { - string cluster_name = 1; - string cert_resource = 2; -} - -message TLSParameters { - TLSVersion min_version = 1; - TLSVersion max_version = 2; - repeated TLSCipherSuite cipher_suites = 3; -} - -message LeafCertificate { - string cert = 1; - string key = 2; -} - -message TrustBundle { - string trust_domain = 1; - repeated string roots = 2; -} - -// +kubebuilder:validation:Enum=TLS_VERSION_AUTO;TLS_VERSION_1_0;TLS_VERSION_1_1;TLS_VERSION_1_2;TLS_VERSION_1_3;TLS_VERSION_INVALID;TLS_VERSION_UNSPECIFIED -// +kubebuilder:validation:Type=string -enum TLSVersion { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - TLS_VERSION_AUTO = 0; - TLS_VERSION_1_0 = 1; - TLS_VERSION_1_1 = 2; - TLS_VERSION_1_2 = 3; - TLS_VERSION_1_3 = 4; - TLS_VERSION_INVALID = 5; - TLS_VERSION_UNSPECIFIED = 6; -} - -// +kubebuilder:validation:Enum=TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256;TLS_CIPHER_SUITE_AES256_SHA;TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305;TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256;TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305;TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA;TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA;TLS_CIPHER_SUITE_AES128_GCM_SHA256;TLS_CIPHER_SUITE_AES128_SHA;TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384;TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384;TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA;TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA;TLS_CIPHER_SUITE_AES256_GCM_SHA384 -// +kubebuilder:validation:Type=string -enum TLSCipherSuite { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256 = 0; - TLS_CIPHER_SUITE_ECDHE_ECDSA_CHACHA20_POLY1305 = 1; - TLS_CIPHER_SUITE_ECDHE_RSA_AES128_GCM_SHA256 = 2; - TLS_CIPHER_SUITE_ECDHE_RSA_CHACHA20_POLY1305 = 3; - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES128_SHA = 4; - TLS_CIPHER_SUITE_ECDHE_RSA_AES128_SHA = 5; - TLS_CIPHER_SUITE_AES128_GCM_SHA256 = 6; - TLS_CIPHER_SUITE_AES128_SHA = 7; - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384 = 8; - TLS_CIPHER_SUITE_ECDHE_RSA_AES256_GCM_SHA384 = 9; - TLS_CIPHER_SUITE_ECDHE_ECDSA_AES256_SHA = 10; - TLS_CIPHER_SUITE_ECDHE_RSA_AES256_SHA = 11; - TLS_CIPHER_SUITE_AES256_GCM_SHA384 = 12; - TLS_CIPHER_SUITE_AES256_SHA = 13; -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket_deepcopy.gen.go deleted file mode 100644 index 0d0520e328b5..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket_deepcopy.gen.go +++ /dev/null @@ -1,279 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package pbproxystate - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using TLS within kubernetes types, where deepcopy-gen is used. -func (in *TLS) DeepCopyInto(out *TLS) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLS. Required by controller-gen. -func (in *TLS) DeepCopy() *TLS { - if in == nil { - return nil - } - out := new(TLS) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TLS. Required by controller-gen. -func (in *TLS) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using TransportSocket within kubernetes types, where deepcopy-gen is used. -func (in *TransportSocket) DeepCopyInto(out *TransportSocket) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TransportSocket. Required by controller-gen. -func (in *TransportSocket) DeepCopy() *TransportSocket { - if in == nil { - return nil - } - out := new(TransportSocket) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TransportSocket. Required by controller-gen. -func (in *TransportSocket) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using InboundMeshMTLS within kubernetes types, where deepcopy-gen is used. -func (in *InboundMeshMTLS) DeepCopyInto(out *InboundMeshMTLS) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InboundMeshMTLS. Required by controller-gen. -func (in *InboundMeshMTLS) DeepCopy() *InboundMeshMTLS { - if in == nil { - return nil - } - out := new(InboundMeshMTLS) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new InboundMeshMTLS. Required by controller-gen. -func (in *InboundMeshMTLS) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using OutboundMeshMTLS within kubernetes types, where deepcopy-gen is used. -func (in *OutboundMeshMTLS) DeepCopyInto(out *OutboundMeshMTLS) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OutboundMeshMTLS. Required by controller-gen. -func (in *OutboundMeshMTLS) DeepCopy() *OutboundMeshMTLS { - if in == nil { - return nil - } - out := new(OutboundMeshMTLS) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new OutboundMeshMTLS. Required by controller-gen. -func (in *OutboundMeshMTLS) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using InboundNonMeshTLS within kubernetes types, where deepcopy-gen is used. -func (in *InboundNonMeshTLS) DeepCopyInto(out *InboundNonMeshTLS) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InboundNonMeshTLS. Required by controller-gen. -func (in *InboundNonMeshTLS) DeepCopy() *InboundNonMeshTLS { - if in == nil { - return nil - } - out := new(InboundNonMeshTLS) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new InboundNonMeshTLS. Required by controller-gen. -func (in *InboundNonMeshTLS) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using OutboundNonMeshTLS within kubernetes types, where deepcopy-gen is used. -func (in *OutboundNonMeshTLS) DeepCopyInto(out *OutboundNonMeshTLS) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OutboundNonMeshTLS. Required by controller-gen. -func (in *OutboundNonMeshTLS) DeepCopy() *OutboundNonMeshTLS { - if in == nil { - return nil - } - out := new(OutboundNonMeshTLS) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new OutboundNonMeshTLS. Required by controller-gen. -func (in *OutboundNonMeshTLS) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using MeshInboundValidationContext within kubernetes types, where deepcopy-gen is used. -func (in *MeshInboundValidationContext) DeepCopyInto(out *MeshInboundValidationContext) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshInboundValidationContext. Required by controller-gen. -func (in *MeshInboundValidationContext) DeepCopy() *MeshInboundValidationContext { - if in == nil { - return nil - } - out := new(MeshInboundValidationContext) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new MeshInboundValidationContext. Required by controller-gen. -func (in *MeshInboundValidationContext) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using MeshOutboundValidationContext within kubernetes types, where deepcopy-gen is used. -func (in *MeshOutboundValidationContext) DeepCopyInto(out *MeshOutboundValidationContext) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshOutboundValidationContext. Required by controller-gen. -func (in *MeshOutboundValidationContext) DeepCopy() *MeshOutboundValidationContext { - if in == nil { - return nil - } - out := new(MeshOutboundValidationContext) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new MeshOutboundValidationContext. Required by controller-gen. -func (in *MeshOutboundValidationContext) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using NonMeshOutboundValidationContext within kubernetes types, where deepcopy-gen is used. -func (in *NonMeshOutboundValidationContext) DeepCopyInto(out *NonMeshOutboundValidationContext) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonMeshOutboundValidationContext. Required by controller-gen. -func (in *NonMeshOutboundValidationContext) DeepCopy() *NonMeshOutboundValidationContext { - if in == nil { - return nil - } - out := new(NonMeshOutboundValidationContext) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new NonMeshOutboundValidationContext. Required by controller-gen. -func (in *NonMeshOutboundValidationContext) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using SDSCertificate within kubernetes types, where deepcopy-gen is used. -func (in *SDSCertificate) DeepCopyInto(out *SDSCertificate) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SDSCertificate. Required by controller-gen. -func (in *SDSCertificate) DeepCopy() *SDSCertificate { - if in == nil { - return nil - } - out := new(SDSCertificate) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new SDSCertificate. Required by controller-gen. -func (in *SDSCertificate) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using TLSParameters within kubernetes types, where deepcopy-gen is used. -func (in *TLSParameters) DeepCopyInto(out *TLSParameters) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSParameters. Required by controller-gen. -func (in *TLSParameters) DeepCopy() *TLSParameters { - if in == nil { - return nil - } - out := new(TLSParameters) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TLSParameters. Required by controller-gen. -func (in *TLSParameters) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using LeafCertificate within kubernetes types, where deepcopy-gen is used. -func (in *LeafCertificate) DeepCopyInto(out *LeafCertificate) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LeafCertificate. Required by controller-gen. -func (in *LeafCertificate) DeepCopy() *LeafCertificate { - if in == nil { - return nil - } - out := new(LeafCertificate) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new LeafCertificate. Required by controller-gen. -func (in *LeafCertificate) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using TrustBundle within kubernetes types, where deepcopy-gen is used. -func (in *TrustBundle) DeepCopyInto(out *TrustBundle) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustBundle. Required by controller-gen. -func (in *TrustBundle) DeepCopy() *TrustBundle { - if in == nil { - return nil - } - out := new(TrustBundle) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TrustBundle. Required by controller-gen. -func (in *TrustBundle) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket_json.gen.go b/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket_json.gen.go deleted file mode 100644 index 4c83b4d87d9a..000000000000 --- a/proto-public/pbmesh/v2beta1/pbproxystate/transport_socket_json.gen.go +++ /dev/null @@ -1,154 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package pbproxystate - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for TLS -func (this *TLS) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TLS -func (this *TLS) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for TransportSocket -func (this *TransportSocket) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TransportSocket -func (this *TransportSocket) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for InboundMeshMTLS -func (this *InboundMeshMTLS) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for InboundMeshMTLS -func (this *InboundMeshMTLS) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for OutboundMeshMTLS -func (this *OutboundMeshMTLS) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for OutboundMeshMTLS -func (this *OutboundMeshMTLS) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for InboundNonMeshTLS -func (this *InboundNonMeshTLS) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for InboundNonMeshTLS -func (this *InboundNonMeshTLS) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for OutboundNonMeshTLS -func (this *OutboundNonMeshTLS) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for OutboundNonMeshTLS -func (this *OutboundNonMeshTLS) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for MeshInboundValidationContext -func (this *MeshInboundValidationContext) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for MeshInboundValidationContext -func (this *MeshInboundValidationContext) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for MeshOutboundValidationContext -func (this *MeshOutboundValidationContext) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for MeshOutboundValidationContext -func (this *MeshOutboundValidationContext) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for NonMeshOutboundValidationContext -func (this *NonMeshOutboundValidationContext) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for NonMeshOutboundValidationContext -func (this *NonMeshOutboundValidationContext) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for SDSCertificate -func (this *SDSCertificate) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for SDSCertificate -func (this *SDSCertificate) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for TLSParameters -func (this *TLSParameters) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TLSParameters -func (this *TLSParameters) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for LeafCertificate -func (this *LeafCertificate) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for LeafCertificate -func (this *LeafCertificate) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for TrustBundle -func (this *TrustBundle) MarshalJSON() ([]byte, error) { - str, err := TransportSocketMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TrustBundle -func (this *TrustBundle) UnmarshalJSON(b []byte) error { - return TransportSocketUnmarshaler.Unmarshal(b, this) -} - -var ( - TransportSocketMarshaler = &protojson.MarshalOptions{} - TransportSocketUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/proxy_configuration.pb.binary.go b/proto-public/pbmesh/v2beta1/proxy_configuration.pb.binary.go deleted file mode 100644 index cb786967202d..000000000000 --- a/proto-public/pbmesh/v2beta1/proxy_configuration.pb.binary.go +++ /dev/null @@ -1,68 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/proxy_configuration.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ProxyConfiguration) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ProxyConfiguration) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *DynamicConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *DynamicConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TransparentProxy) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TransparentProxy) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *BootstrapConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *BootstrapConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *AccessLogsConfig) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *AccessLogsConfig) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *EnvoyExtension) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *EnvoyExtension) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/proxy_configuration.pb.go b/proto-public/pbmesh/v2beta1/proxy_configuration.pb.go deleted file mode 100644 index a374848fd20e..000000000000 --- a/proto-public/pbmesh/v2beta1/proxy_configuration.pb.go +++ /dev/null @@ -1,1227 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/proxy_configuration.proto - -package meshv2beta1 - -import ( - v2beta1 "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - structpb "google.golang.org/protobuf/types/known/structpb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=PROXY_MODE_DEFAULT;PROXY_MODE_TRANSPARENT;PROXY_MODE_DIRECT -// +kubebuilder:validation:Type=string -type ProxyMode int32 - -const ( - // ProxyModeDefault represents no specific mode and should - // be used to indicate that a different layer of the configuration - // chain should take precedence - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - ProxyMode_PROXY_MODE_DEFAULT ProxyMode = 0 - // ProxyModeTransparent represents that inbound and outbound application - // traffic is being captured and redirected through the proxy. - ProxyMode_PROXY_MODE_TRANSPARENT ProxyMode = 1 - // ProxyModeDirect represents that the proxy's listeners must be dialed directly - // by the local application and other proxies. - ProxyMode_PROXY_MODE_DIRECT ProxyMode = 2 -) - -// Enum value maps for ProxyMode. -var ( - ProxyMode_name = map[int32]string{ - 0: "PROXY_MODE_DEFAULT", - 1: "PROXY_MODE_TRANSPARENT", - 2: "PROXY_MODE_DIRECT", - } - ProxyMode_value = map[string]int32{ - "PROXY_MODE_DEFAULT": 0, - "PROXY_MODE_TRANSPARENT": 1, - "PROXY_MODE_DIRECT": 2, - } -) - -func (x ProxyMode) Enum() *ProxyMode { - p := new(ProxyMode) - *p = x - return p -} - -func (x ProxyMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ProxyMode) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_proxy_configuration_proto_enumTypes[0].Descriptor() -} - -func (ProxyMode) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_proxy_configuration_proto_enumTypes[0] -} - -func (x ProxyMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ProxyMode.Descriptor instead. -func (ProxyMode) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_proxy_configuration_proto_rawDescGZIP(), []int{0} -} - -// +kubebuilder:validation:Enum=LOG_SINK_TYPE_DEFAULT;LOG_SINK_TYPE_FILE;LOG_SINK_TYPE_STDERR;LOG_SINK_TYPE_STDOUT -// +kubebuilder:validation:Type=string -type LogSinkType int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - LogSinkType_LOG_SINK_TYPE_DEFAULT LogSinkType = 0 - LogSinkType_LOG_SINK_TYPE_FILE LogSinkType = 1 - LogSinkType_LOG_SINK_TYPE_STDERR LogSinkType = 2 - LogSinkType_LOG_SINK_TYPE_STDOUT LogSinkType = 3 -) - -// Enum value maps for LogSinkType. -var ( - LogSinkType_name = map[int32]string{ - 0: "LOG_SINK_TYPE_DEFAULT", - 1: "LOG_SINK_TYPE_FILE", - 2: "LOG_SINK_TYPE_STDERR", - 3: "LOG_SINK_TYPE_STDOUT", - } - LogSinkType_value = map[string]int32{ - "LOG_SINK_TYPE_DEFAULT": 0, - "LOG_SINK_TYPE_FILE": 1, - "LOG_SINK_TYPE_STDERR": 2, - "LOG_SINK_TYPE_STDOUT": 3, - } -) - -func (x LogSinkType) Enum() *LogSinkType { - p := new(LogSinkType) - *p = x - return p -} - -func (x LogSinkType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (LogSinkType) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_proxy_configuration_proto_enumTypes[1].Descriptor() -} - -func (LogSinkType) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_proxy_configuration_proto_enumTypes[1] -} - -func (x LogSinkType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use LogSinkType.Descriptor instead. -func (LogSinkType) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_proxy_configuration_proto_rawDescGZIP(), []int{1} -} - -// +kubebuilder:validation:Enum=MUTUAL_TLS_MODE_DEFAULT;MUTUAL_TLS_MODE_STRICT;MUTUAL_TLS_MODE_PERMISSIVE -// +kubebuilder:validation:Type=string -type MutualTLSMode int32 - -const ( - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - MutualTLSMode_MUTUAL_TLS_MODE_DEFAULT MutualTLSMode = 0 - MutualTLSMode_MUTUAL_TLS_MODE_STRICT MutualTLSMode = 1 - MutualTLSMode_MUTUAL_TLS_MODE_PERMISSIVE MutualTLSMode = 2 -) - -// Enum value maps for MutualTLSMode. -var ( - MutualTLSMode_name = map[int32]string{ - 0: "MUTUAL_TLS_MODE_DEFAULT", - 1: "MUTUAL_TLS_MODE_STRICT", - 2: "MUTUAL_TLS_MODE_PERMISSIVE", - } - MutualTLSMode_value = map[string]int32{ - "MUTUAL_TLS_MODE_DEFAULT": 0, - "MUTUAL_TLS_MODE_STRICT": 1, - "MUTUAL_TLS_MODE_PERMISSIVE": 2, - } -) - -func (x MutualTLSMode) Enum() *MutualTLSMode { - p := new(MutualTLSMode) - *p = x - return p -} - -func (x MutualTLSMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (MutualTLSMode) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_proxy_configuration_proto_enumTypes[2].Descriptor() -} - -func (MutualTLSMode) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_proxy_configuration_proto_enumTypes[2] -} - -func (x MutualTLSMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use MutualTLSMode.Descriptor instead. -func (MutualTLSMode) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_proxy_configuration_proto_rawDescGZIP(), []int{2} -} - -// This is a Resource type. -type ProxyConfiguration struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Selection of workloads this proxy configuration should apply to. - // These can be prefixes or specific workload names. - Workloads *v2beta1.WorkloadSelector `protobuf:"bytes,1,opt,name=workloads,proto3" json:"workloads,omitempty"` - // dynamic_config is the configuration that could be changed - // dynamically (i.e. without needing restart). - DynamicConfig *DynamicConfig `protobuf:"bytes,2,opt,name=dynamic_config,json=dynamicConfig,proto3" json:"dynamic_config,omitempty"` - // bootstrap_config is the configuration that requires proxies - // to be restarted to be applied. - BootstrapConfig *BootstrapConfig `protobuf:"bytes,3,opt,name=bootstrap_config,json=bootstrapConfig,proto3" json:"bootstrap_config,omitempty"` - // deprecated: prevent usage when using v2 APIs directly. - // needed for backwards compatibility - // - // +kubebuilder:validation:Type=object - // +kubebuilder:validation:Schemaless - // +kubebuilder:pruning:PreserveUnknownFields - // - // Deprecated: Marked as deprecated in pbmesh/v2beta1/proxy_configuration.proto. - OpaqueConfig *structpb.Struct `protobuf:"bytes,4,opt,name=opaque_config,json=opaqueConfig,proto3" json:"opaque_config,omitempty"` -} - -func (x *ProxyConfiguration) Reset() { - *x = ProxyConfiguration{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProxyConfiguration) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProxyConfiguration) ProtoMessage() {} - -func (x *ProxyConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProxyConfiguration.ProtoReflect.Descriptor instead. -func (*ProxyConfiguration) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_proxy_configuration_proto_rawDescGZIP(), []int{0} -} - -func (x *ProxyConfiguration) GetWorkloads() *v2beta1.WorkloadSelector { - if x != nil { - return x.Workloads - } - return nil -} - -func (x *ProxyConfiguration) GetDynamicConfig() *DynamicConfig { - if x != nil { - return x.DynamicConfig - } - return nil -} - -func (x *ProxyConfiguration) GetBootstrapConfig() *BootstrapConfig { - if x != nil { - return x.BootstrapConfig - } - return nil -} - -// Deprecated: Marked as deprecated in pbmesh/v2beta1/proxy_configuration.proto. -func (x *ProxyConfiguration) GetOpaqueConfig() *structpb.Struct { - if x != nil { - return x.OpaqueConfig - } - return nil -} - -type DynamicConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // mode indicates the proxy's mode. This will default to 'transparent'. - Mode ProxyMode `protobuf:"varint,1,opt,name=mode,proto3,enum=hashicorp.consul.mesh.v2beta1.ProxyMode" json:"mode,omitempty"` - TransparentProxy *TransparentProxy `protobuf:"bytes,2,opt,name=transparent_proxy,json=transparentProxy,proto3" json:"transparent_proxy,omitempty"` - MutualTlsMode MutualTLSMode `protobuf:"varint,3,opt,name=mutual_tls_mode,json=mutualTlsMode,proto3,enum=hashicorp.consul.mesh.v2beta1.MutualTLSMode" json:"mutual_tls_mode,omitempty"` - // local_connection is the configuration that should be used - // to connect to the local application provided per-port. - // The map keys should correspond to port names on the workload. - LocalConnection map[string]*ConnectionConfig `protobuf:"bytes,4,rep,name=local_connection,json=localConnection,proto3" json:"local_connection,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // inbound_connections configures inbound connections to the proxy. - InboundConnections *InboundConnectionsConfig `protobuf:"bytes,5,opt,name=inbound_connections,json=inboundConnections,proto3" json:"inbound_connections,omitempty"` - MeshGatewayMode MeshGatewayMode `protobuf:"varint,6,opt,name=mesh_gateway_mode,json=meshGatewayMode,proto3,enum=hashicorp.consul.mesh.v2beta1.MeshGatewayMode" json:"mesh_gateway_mode,omitempty"` - ExposeConfig *ExposeConfig `protobuf:"bytes,7,opt,name=expose_config,json=exposeConfig,proto3" json:"expose_config,omitempty"` - // AccessLogs configures the output and format of Envoy access logs - AccessLogs *AccessLogsConfig `protobuf:"bytes,8,opt,name=access_logs,json=accessLogs,proto3" json:"access_logs,omitempty"` - PublicListenerJson string `protobuf:"bytes,9,opt,name=public_listener_json,json=publicListenerJson,proto3" json:"public_listener_json,omitempty"` - ListenerTracingJson string `protobuf:"bytes,10,opt,name=listener_tracing_json,json=listenerTracingJson,proto3" json:"listener_tracing_json,omitempty"` - LocalClusterJson string `protobuf:"bytes,11,opt,name=local_cluster_json,json=localClusterJson,proto3" json:"local_cluster_json,omitempty"` - // deprecated: - // local_workload_address, local_workload_port, and local_workload_socket_path - // are deprecated and are only needed for migration of existing resources. - // - // Deprecated: Marked as deprecated in pbmesh/v2beta1/proxy_configuration.proto. - LocalWorkloadAddress string `protobuf:"bytes,12,opt,name=local_workload_address,json=localWorkloadAddress,proto3" json:"local_workload_address,omitempty"` - // Deprecated: Marked as deprecated in pbmesh/v2beta1/proxy_configuration.proto. - LocalWorkloadPort uint32 `protobuf:"varint,13,opt,name=local_workload_port,json=localWorkloadPort,proto3" json:"local_workload_port,omitempty"` - // Deprecated: Marked as deprecated in pbmesh/v2beta1/proxy_configuration.proto. - LocalWorkloadSocketPath string `protobuf:"bytes,14,opt,name=local_workload_socket_path,json=localWorkloadSocketPath,proto3" json:"local_workload_socket_path,omitempty"` -} - -func (x *DynamicConfig) Reset() { - *x = DynamicConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DynamicConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DynamicConfig) ProtoMessage() {} - -func (x *DynamicConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DynamicConfig.ProtoReflect.Descriptor instead. -func (*DynamicConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_proxy_configuration_proto_rawDescGZIP(), []int{1} -} - -func (x *DynamicConfig) GetMode() ProxyMode { - if x != nil { - return x.Mode - } - return ProxyMode_PROXY_MODE_DEFAULT -} - -func (x *DynamicConfig) GetTransparentProxy() *TransparentProxy { - if x != nil { - return x.TransparentProxy - } - return nil -} - -func (x *DynamicConfig) GetMutualTlsMode() MutualTLSMode { - if x != nil { - return x.MutualTlsMode - } - return MutualTLSMode_MUTUAL_TLS_MODE_DEFAULT -} - -func (x *DynamicConfig) GetLocalConnection() map[string]*ConnectionConfig { - if x != nil { - return x.LocalConnection - } - return nil -} - -func (x *DynamicConfig) GetInboundConnections() *InboundConnectionsConfig { - if x != nil { - return x.InboundConnections - } - return nil -} - -func (x *DynamicConfig) GetMeshGatewayMode() MeshGatewayMode { - if x != nil { - return x.MeshGatewayMode - } - return MeshGatewayMode_MESH_GATEWAY_MODE_UNSPECIFIED -} - -func (x *DynamicConfig) GetExposeConfig() *ExposeConfig { - if x != nil { - return x.ExposeConfig - } - return nil -} - -func (x *DynamicConfig) GetAccessLogs() *AccessLogsConfig { - if x != nil { - return x.AccessLogs - } - return nil -} - -func (x *DynamicConfig) GetPublicListenerJson() string { - if x != nil { - return x.PublicListenerJson - } - return "" -} - -func (x *DynamicConfig) GetListenerTracingJson() string { - if x != nil { - return x.ListenerTracingJson - } - return "" -} - -func (x *DynamicConfig) GetLocalClusterJson() string { - if x != nil { - return x.LocalClusterJson - } - return "" -} - -// Deprecated: Marked as deprecated in pbmesh/v2beta1/proxy_configuration.proto. -func (x *DynamicConfig) GetLocalWorkloadAddress() string { - if x != nil { - return x.LocalWorkloadAddress - } - return "" -} - -// Deprecated: Marked as deprecated in pbmesh/v2beta1/proxy_configuration.proto. -func (x *DynamicConfig) GetLocalWorkloadPort() uint32 { - if x != nil { - return x.LocalWorkloadPort - } - return 0 -} - -// Deprecated: Marked as deprecated in pbmesh/v2beta1/proxy_configuration.proto. -func (x *DynamicConfig) GetLocalWorkloadSocketPath() string { - if x != nil { - return x.LocalWorkloadSocketPath - } - return "" -} - -type TransparentProxy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // outbound_listener_port is the port for the proxy's outbound listener. - // This defaults to 15001. - OutboundListenerPort uint32 `protobuf:"varint,1,opt,name=outbound_listener_port,json=outboundListenerPort,proto3" json:"outbound_listener_port,omitempty"` - // dialed_directly indicates whether this proxy should be dialed using original destination IP - // in the connection rather than load balance between all endpoints. - DialedDirectly bool `protobuf:"varint,2,opt,name=dialed_directly,json=dialedDirectly,proto3" json:"dialed_directly,omitempty"` -} - -func (x *TransparentProxy) Reset() { - *x = TransparentProxy{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TransparentProxy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TransparentProxy) ProtoMessage() {} - -func (x *TransparentProxy) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TransparentProxy.ProtoReflect.Descriptor instead. -func (*TransparentProxy) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_proxy_configuration_proto_rawDescGZIP(), []int{2} -} - -func (x *TransparentProxy) GetOutboundListenerPort() uint32 { - if x != nil { - return x.OutboundListenerPort - } - return 0 -} - -func (x *TransparentProxy) GetDialedDirectly() bool { - if x != nil { - return x.DialedDirectly - } - return false -} - -// BootstrapConfig is equivalent to configuration defined -// in our docs. -type BootstrapConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - StatsdUrl string `protobuf:"bytes,1,opt,name=statsd_url,json=statsdUrl,proto3" json:"statsd_url,omitempty"` - DogstatsdUrl string `protobuf:"bytes,2,opt,name=dogstatsd_url,json=dogstatsdUrl,proto3" json:"dogstatsd_url,omitempty"` - StatsTags []string `protobuf:"bytes,3,rep,name=stats_tags,json=statsTags,proto3" json:"stats_tags,omitempty"` - PrometheusBindAddr string `protobuf:"bytes,4,opt,name=prometheus_bind_addr,json=prometheusBindAddr,proto3" json:"prometheus_bind_addr,omitempty"` - StatsBindAddr string `protobuf:"bytes,5,opt,name=stats_bind_addr,json=statsBindAddr,proto3" json:"stats_bind_addr,omitempty"` - ReadyBindAddr string `protobuf:"bytes,6,opt,name=ready_bind_addr,json=readyBindAddr,proto3" json:"ready_bind_addr,omitempty"` - OverrideJsonTpl string `protobuf:"bytes,7,opt,name=override_json_tpl,json=overrideJsonTpl,proto3" json:"override_json_tpl,omitempty"` - StaticClustersJson string `protobuf:"bytes,8,opt,name=static_clusters_json,json=staticClustersJson,proto3" json:"static_clusters_json,omitempty"` - StaticListenersJson string `protobuf:"bytes,9,opt,name=static_listeners_json,json=staticListenersJson,proto3" json:"static_listeners_json,omitempty"` - StatsSinksJson string `protobuf:"bytes,10,opt,name=stats_sinks_json,json=statsSinksJson,proto3" json:"stats_sinks_json,omitempty"` - StatsConfigJson string `protobuf:"bytes,11,opt,name=stats_config_json,json=statsConfigJson,proto3" json:"stats_config_json,omitempty"` - StatsFlushInterval string `protobuf:"bytes,12,opt,name=stats_flush_interval,json=statsFlushInterval,proto3" json:"stats_flush_interval,omitempty"` - TracingConfigJson string `protobuf:"bytes,13,opt,name=tracing_config_json,json=tracingConfigJson,proto3" json:"tracing_config_json,omitempty"` - TelemetryCollectorBindSocketDir string `protobuf:"bytes,14,opt,name=telemetry_collector_bind_socket_dir,json=telemetryCollectorBindSocketDir,proto3" json:"telemetry_collector_bind_socket_dir,omitempty"` -} - -func (x *BootstrapConfig) Reset() { - *x = BootstrapConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BootstrapConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BootstrapConfig) ProtoMessage() {} - -func (x *BootstrapConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BootstrapConfig.ProtoReflect.Descriptor instead. -func (*BootstrapConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_proxy_configuration_proto_rawDescGZIP(), []int{3} -} - -func (x *BootstrapConfig) GetStatsdUrl() string { - if x != nil { - return x.StatsdUrl - } - return "" -} - -func (x *BootstrapConfig) GetDogstatsdUrl() string { - if x != nil { - return x.DogstatsdUrl - } - return "" -} - -func (x *BootstrapConfig) GetStatsTags() []string { - if x != nil { - return x.StatsTags - } - return nil -} - -func (x *BootstrapConfig) GetPrometheusBindAddr() string { - if x != nil { - return x.PrometheusBindAddr - } - return "" -} - -func (x *BootstrapConfig) GetStatsBindAddr() string { - if x != nil { - return x.StatsBindAddr - } - return "" -} - -func (x *BootstrapConfig) GetReadyBindAddr() string { - if x != nil { - return x.ReadyBindAddr - } - return "" -} - -func (x *BootstrapConfig) GetOverrideJsonTpl() string { - if x != nil { - return x.OverrideJsonTpl - } - return "" -} - -func (x *BootstrapConfig) GetStaticClustersJson() string { - if x != nil { - return x.StaticClustersJson - } - return "" -} - -func (x *BootstrapConfig) GetStaticListenersJson() string { - if x != nil { - return x.StaticListenersJson - } - return "" -} - -func (x *BootstrapConfig) GetStatsSinksJson() string { - if x != nil { - return x.StatsSinksJson - } - return "" -} - -func (x *BootstrapConfig) GetStatsConfigJson() string { - if x != nil { - return x.StatsConfigJson - } - return "" -} - -func (x *BootstrapConfig) GetStatsFlushInterval() string { - if x != nil { - return x.StatsFlushInterval - } - return "" -} - -func (x *BootstrapConfig) GetTracingConfigJson() string { - if x != nil { - return x.TracingConfigJson - } - return "" -} - -func (x *BootstrapConfig) GetTelemetryCollectorBindSocketDir() string { - if x != nil { - return x.TelemetryCollectorBindSocketDir - } - return "" -} - -// AccessLogsConfig contains the associated default settings for all Envoy -// instances within the datacenter or partition -type AccessLogsConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Enabled turns off all access logging - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - // DisableListenerLogs turns off just listener logs for connections rejected by Envoy because they don't - // have a matching listener filter. - DisableListenerLogs bool `protobuf:"varint,2,opt,name=disable_listener_logs,json=disableListenerLogs,proto3" json:"disable_listener_logs,omitempty"` - // Type selects the output for logs: "file", "stderr". "stdout" - Type LogSinkType `protobuf:"varint,3,opt,name=type,proto3,enum=hashicorp.consul.mesh.v2beta1.LogSinkType" json:"type,omitempty"` - // Path is the output file to write logs - Path string `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"` - // The presence of one format string or the other implies the access log string encoding. - // Defining both is invalid. - JsonFormat string `protobuf:"bytes,5,opt,name=json_format,json=jsonFormat,proto3" json:"json_format,omitempty"` - TextFormat string `protobuf:"bytes,6,opt,name=text_format,json=textFormat,proto3" json:"text_format,omitempty"` -} - -func (x *AccessLogsConfig) Reset() { - *x = AccessLogsConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AccessLogsConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AccessLogsConfig) ProtoMessage() {} - -func (x *AccessLogsConfig) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AccessLogsConfig.ProtoReflect.Descriptor instead. -func (*AccessLogsConfig) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_proxy_configuration_proto_rawDescGZIP(), []int{4} -} - -func (x *AccessLogsConfig) GetEnabled() bool { - if x != nil { - return x.Enabled - } - return false -} - -func (x *AccessLogsConfig) GetDisableListenerLogs() bool { - if x != nil { - return x.DisableListenerLogs - } - return false -} - -func (x *AccessLogsConfig) GetType() LogSinkType { - if x != nil { - return x.Type - } - return LogSinkType_LOG_SINK_TYPE_DEFAULT -} - -func (x *AccessLogsConfig) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (x *AccessLogsConfig) GetJsonFormat() string { - if x != nil { - return x.JsonFormat - } - return "" -} - -func (x *AccessLogsConfig) GetTextFormat() string { - if x != nil { - return x.TextFormat - } - return "" -} - -// EnvoyExtension has configuration for an extension that patches Envoy resources. -type EnvoyExtension struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Required bool `protobuf:"varint,2,opt,name=required,proto3" json:"required,omitempty"` - // +kubebuilder:validation:Type=object - // +kubebuilder:validation:Schemaless - // +kubebuilder:pruning:PreserveUnknownFields - Arguments *structpb.Struct `protobuf:"bytes,3,opt,name=arguments,proto3" json:"arguments,omitempty"` - ConsulVersion string `protobuf:"bytes,4,opt,name=consul_version,json=consulVersion,proto3" json:"consul_version,omitempty"` - EnvoyVersion string `protobuf:"bytes,5,opt,name=envoy_version,json=envoyVersion,proto3" json:"envoy_version,omitempty"` -} - -func (x *EnvoyExtension) Reset() { - *x = EnvoyExtension{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EnvoyExtension) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EnvoyExtension) ProtoMessage() {} - -func (x *EnvoyExtension) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EnvoyExtension.ProtoReflect.Descriptor instead. -func (*EnvoyExtension) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_proxy_configuration_proto_rawDescGZIP(), []int{5} -} - -func (x *EnvoyExtension) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *EnvoyExtension) GetRequired() bool { - if x != nil { - return x.Required - } - return false -} - -func (x *EnvoyExtension) GetArguments() *structpb.Struct { - if x != nil { - return x.Arguments - } - return nil -} - -func (x *EnvoyExtension) GetConsulVersion() string { - if x != nil { - return x.ConsulVersion - } - return "" -} - -func (x *EnvoyExtension) GetEnvoyVersion() string { - if x != nil { - return x.EnvoyVersion - } - return "" -} - -var File_pbmesh_v2beta1_proxy_configuration_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_proxy_configuration_proto_rawDesc = []byte{ - 0x0a, 0x28, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, 0x62, 0x63, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x70, 0x62, 0x6d, 0x65, 0x73, - 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x70, 0x62, 0x6d, 0x65, - 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0xe0, 0x02, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x09, 0x77, 0x6f, - 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, 0x53, 0x0a, 0x0e, - 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x0d, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x59, 0x0a, 0x10, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x74, - 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0f, 0x62, 0x6f, 0x6f, - 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x40, 0x0a, 0x0d, - 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x02, 0x18, 0x01, - 0x52, 0x0c, 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x3a, 0x06, - 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0x91, 0x09, 0x0a, 0x0d, 0x44, 0x79, 0x6e, 0x61, 0x6d, - 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, - 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x5c, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, - 0x72, 0x6f, 0x78, 0x79, 0x12, 0x54, 0x0a, 0x0f, 0x6d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x74, - 0x6c, 0x73, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x75, - 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0d, 0x6d, 0x75, 0x74, - 0x75, 0x61, 0x6c, 0x54, 0x6c, 0x73, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x6c, 0x0a, 0x10, 0x6c, 0x6f, - 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, 0x13, 0x69, 0x6e, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x12, - 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x11, 0x6d, 0x65, 0x73, 0x68, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x65, - 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0f, 0x6d, - 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x50, - 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x50, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, - 0x67, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6c, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x65, 0x72, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x12, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, - 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, - 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x13, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x54, 0x72, 0x61, - 0x63, 0x69, 0x6e, 0x67, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x16, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, - 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x14, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x32, 0x0a, 0x13, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, - 0x61, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x02, 0x18, - 0x01, 0x52, 0x11, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, - 0x50, 0x6f, 0x72, 0x74, 0x12, 0x3f, 0x0a, 0x1a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x77, 0x6f, - 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x17, 0x6c, 0x6f, - 0x63, 0x61, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x6f, 0x63, 0x6b, 0x65, - 0x74, 0x50, 0x61, 0x74, 0x68, 0x1a, 0x73, 0x0a, 0x14, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x45, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x71, 0x0a, 0x10, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x34, - 0x0a, 0x16, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x65, - 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, - 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, - 0x50, 0x6f, 0x72, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x64, - 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x22, 0x8e, 0x05, - 0x0a, 0x0f, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x55, 0x72, 0x6c, - 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x6f, 0x67, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x5f, 0x75, 0x72, - 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x6f, 0x67, 0x73, 0x74, 0x61, 0x74, - 0x73, 0x64, 0x55, 0x72, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x74, - 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x73, - 0x54, 0x61, 0x67, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, - 0x75, 0x73, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x12, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x42, 0x69, - 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, - 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x12, 0x26, - 0x0a, 0x0f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, - 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x61, 0x64, 0x79, 0x42, 0x69, - 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x74, 0x70, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x4a, 0x73, 0x6f, 0x6e, 0x54, - 0x70, 0x6c, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x12, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, - 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x6c, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x4c, 0x69, 0x73, 0x74, 0x65, - 0x6e, 0x65, 0x72, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x74, 0x61, 0x74, - 0x73, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x53, 0x69, 0x6e, 0x6b, 0x73, 0x4a, 0x73, - 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, - 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x30, - 0x0a, 0x14, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x74, - 0x61, 0x74, 0x73, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, - 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x74, - 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, 0x73, 0x6f, 0x6e, - 0x12, 0x4c, 0x0a, 0x23, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, - 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x73, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1f, 0x74, - 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x42, 0x69, 0x6e, 0x64, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x44, 0x69, 0x72, 0x22, 0xf6, - 0x01, 0x0a, 0x10, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x32, 0x0a, - 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, - 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x69, - 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4c, 0x6f, 0x67, - 0x73, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x4c, 0x6f, 0x67, 0x53, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6a, 0x73, 0x6f, 0x6e, - 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x66, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x65, 0x78, - 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0xc3, 0x01, 0x0a, 0x0e, 0x45, 0x6e, 0x76, 0x6f, - 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, - 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x09, 0x61, 0x72, - 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x6e, 0x76, 0x6f, - 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2a, 0x56, 0x0a, - 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, - 0x4f, 0x58, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, - 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, - 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x15, - 0x0a, 0x11, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x49, 0x52, - 0x45, 0x43, 0x54, 0x10, 0x02, 0x2a, 0x74, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x53, 0x69, 0x6e, 0x6b, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, - 0x16, 0x0a, 0x12, 0x4c, 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4c, 0x4f, 0x47, 0x5f, 0x53, - 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x44, 0x45, 0x52, 0x52, 0x10, - 0x02, 0x12, 0x18, 0x0a, 0x14, 0x4c, 0x4f, 0x47, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x53, 0x54, 0x44, 0x4f, 0x55, 0x54, 0x10, 0x03, 0x2a, 0x68, 0x0a, 0x0d, 0x4d, - 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x17, - 0x4d, 0x55, 0x54, 0x55, 0x41, 0x4c, 0x5f, 0x54, 0x4c, 0x53, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, - 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x4d, 0x55, 0x54, - 0x55, 0x41, 0x4c, 0x5f, 0x54, 0x4c, 0x53, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x54, 0x52, - 0x49, 0x43, 0x54, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, 0x55, 0x54, 0x55, 0x41, 0x4c, 0x5f, - 0x54, 0x4c, 0x53, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, - 0x49, 0x56, 0x45, 0x10, 0x02, 0x42, 0x98, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x17, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, - 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, - 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_proxy_configuration_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_proxy_configuration_proto_rawDescData = file_pbmesh_v2beta1_proxy_configuration_proto_rawDesc -) - -func file_pbmesh_v2beta1_proxy_configuration_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_proxy_configuration_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_proxy_configuration_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_proxy_configuration_proto_rawDescData) - }) - return file_pbmesh_v2beta1_proxy_configuration_proto_rawDescData -} - -var file_pbmesh_v2beta1_proxy_configuration_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_pbmesh_v2beta1_proxy_configuration_proto_goTypes = []interface{}{ - (ProxyMode)(0), // 0: hashicorp.consul.mesh.v2beta1.ProxyMode - (LogSinkType)(0), // 1: hashicorp.consul.mesh.v2beta1.LogSinkType - (MutualTLSMode)(0), // 2: hashicorp.consul.mesh.v2beta1.MutualTLSMode - (*ProxyConfiguration)(nil), // 3: hashicorp.consul.mesh.v2beta1.ProxyConfiguration - (*DynamicConfig)(nil), // 4: hashicorp.consul.mesh.v2beta1.DynamicConfig - (*TransparentProxy)(nil), // 5: hashicorp.consul.mesh.v2beta1.TransparentProxy - (*BootstrapConfig)(nil), // 6: hashicorp.consul.mesh.v2beta1.BootstrapConfig - (*AccessLogsConfig)(nil), // 7: hashicorp.consul.mesh.v2beta1.AccessLogsConfig - (*EnvoyExtension)(nil), // 8: hashicorp.consul.mesh.v2beta1.EnvoyExtension - nil, // 9: hashicorp.consul.mesh.v2beta1.DynamicConfig.LocalConnectionEntry - (*v2beta1.WorkloadSelector)(nil), // 10: hashicorp.consul.catalog.v2beta1.WorkloadSelector - (*structpb.Struct)(nil), // 11: google.protobuf.Struct - (*InboundConnectionsConfig)(nil), // 12: hashicorp.consul.mesh.v2beta1.InboundConnectionsConfig - (MeshGatewayMode)(0), // 13: hashicorp.consul.mesh.v2beta1.MeshGatewayMode - (*ExposeConfig)(nil), // 14: hashicorp.consul.mesh.v2beta1.ExposeConfig - (*ConnectionConfig)(nil), // 15: hashicorp.consul.mesh.v2beta1.ConnectionConfig -} -var file_pbmesh_v2beta1_proxy_configuration_proto_depIdxs = []int32{ - 10, // 0: hashicorp.consul.mesh.v2beta1.ProxyConfiguration.workloads:type_name -> hashicorp.consul.catalog.v2beta1.WorkloadSelector - 4, // 1: hashicorp.consul.mesh.v2beta1.ProxyConfiguration.dynamic_config:type_name -> hashicorp.consul.mesh.v2beta1.DynamicConfig - 6, // 2: hashicorp.consul.mesh.v2beta1.ProxyConfiguration.bootstrap_config:type_name -> hashicorp.consul.mesh.v2beta1.BootstrapConfig - 11, // 3: hashicorp.consul.mesh.v2beta1.ProxyConfiguration.opaque_config:type_name -> google.protobuf.Struct - 0, // 4: hashicorp.consul.mesh.v2beta1.DynamicConfig.mode:type_name -> hashicorp.consul.mesh.v2beta1.ProxyMode - 5, // 5: hashicorp.consul.mesh.v2beta1.DynamicConfig.transparent_proxy:type_name -> hashicorp.consul.mesh.v2beta1.TransparentProxy - 2, // 6: hashicorp.consul.mesh.v2beta1.DynamicConfig.mutual_tls_mode:type_name -> hashicorp.consul.mesh.v2beta1.MutualTLSMode - 9, // 7: hashicorp.consul.mesh.v2beta1.DynamicConfig.local_connection:type_name -> hashicorp.consul.mesh.v2beta1.DynamicConfig.LocalConnectionEntry - 12, // 8: hashicorp.consul.mesh.v2beta1.DynamicConfig.inbound_connections:type_name -> hashicorp.consul.mesh.v2beta1.InboundConnectionsConfig - 13, // 9: hashicorp.consul.mesh.v2beta1.DynamicConfig.mesh_gateway_mode:type_name -> hashicorp.consul.mesh.v2beta1.MeshGatewayMode - 14, // 10: hashicorp.consul.mesh.v2beta1.DynamicConfig.expose_config:type_name -> hashicorp.consul.mesh.v2beta1.ExposeConfig - 7, // 11: hashicorp.consul.mesh.v2beta1.DynamicConfig.access_logs:type_name -> hashicorp.consul.mesh.v2beta1.AccessLogsConfig - 1, // 12: hashicorp.consul.mesh.v2beta1.AccessLogsConfig.type:type_name -> hashicorp.consul.mesh.v2beta1.LogSinkType - 11, // 13: hashicorp.consul.mesh.v2beta1.EnvoyExtension.arguments:type_name -> google.protobuf.Struct - 15, // 14: hashicorp.consul.mesh.v2beta1.DynamicConfig.LocalConnectionEntry.value:type_name -> hashicorp.consul.mesh.v2beta1.ConnectionConfig - 15, // [15:15] is the sub-list for method output_type - 15, // [15:15] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_proxy_configuration_proto_init() } -func file_pbmesh_v2beta1_proxy_configuration_proto_init() { - if File_pbmesh_v2beta1_proxy_configuration_proto != nil { - return - } - file_pbmesh_v2beta1_connection_proto_init() - file_pbmesh_v2beta1_expose_proto_init() - file_pbmesh_v2beta1_routing_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProxyConfiguration); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DynamicConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransparentProxy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BootstrapConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AccessLogsConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EnvoyExtension); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_proxy_configuration_proto_rawDesc, - NumEnums: 3, - NumMessages: 7, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_proxy_configuration_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_proxy_configuration_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_proxy_configuration_proto_enumTypes, - MessageInfos: file_pbmesh_v2beta1_proxy_configuration_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_proxy_configuration_proto = out.File - file_pbmesh_v2beta1_proxy_configuration_proto_rawDesc = nil - file_pbmesh_v2beta1_proxy_configuration_proto_goTypes = nil - file_pbmesh_v2beta1_proxy_configuration_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/proxy_configuration.proto b/proto-public/pbmesh/v2beta1/proxy_configuration.proto deleted file mode 100644 index 9a2d410d868d..000000000000 --- a/proto-public/pbmesh/v2beta1/proxy_configuration.proto +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "google/protobuf/struct.proto"; -import "pbcatalog/v2beta1/selector.proto"; -import "pbmesh/v2beta1/connection.proto"; -import "pbmesh/v2beta1/expose.proto"; -import "pbmesh/v2beta1/routing.proto"; -import "pbresource/annotations.proto"; - -// This is a Resource type. -message ProxyConfiguration { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // Selection of workloads this proxy configuration should apply to. - // These can be prefixes or specific workload names. - hashicorp.consul.catalog.v2beta1.WorkloadSelector workloads = 1; - - // dynamic_config is the configuration that could be changed - // dynamically (i.e. without needing restart). - DynamicConfig dynamic_config = 2; - - // bootstrap_config is the configuration that requires proxies - // to be restarted to be applied. - BootstrapConfig bootstrap_config = 3; - - // deprecated: prevent usage when using v2 APIs directly. - // needed for backwards compatibility - // - // +kubebuilder:validation:Type=object - // +kubebuilder:validation:Schemaless - // +kubebuilder:pruning:PreserveUnknownFields - google.protobuf.Struct opaque_config = 4 [deprecated = true]; -} - -message DynamicConfig { - // mode indicates the proxy's mode. This will default to 'transparent'. - ProxyMode mode = 1; - - TransparentProxy transparent_proxy = 2; - - MutualTLSMode mutual_tls_mode = 3; - - // local_connection is the configuration that should be used - // to connect to the local application provided per-port. - // The map keys should correspond to port names on the workload. - map local_connection = 4; - - // inbound_connections configures inbound connections to the proxy. - InboundConnectionsConfig inbound_connections = 5; - - MeshGatewayMode mesh_gateway_mode = 6; - - ExposeConfig expose_config = 7; - - // AccessLogs configures the output and format of Envoy access logs - AccessLogsConfig access_logs = 8; - - string public_listener_json = 9; - string listener_tracing_json = 10; - string local_cluster_json = 11; - - // deprecated: - // local_workload_address, local_workload_port, and local_workload_socket_path - // are deprecated and are only needed for migration of existing resources. - string local_workload_address = 12 [deprecated = true]; - uint32 local_workload_port = 13 [deprecated = true]; - string local_workload_socket_path = 14 [deprecated = true]; -} - -message TransparentProxy { - // outbound_listener_port is the port for the proxy's outbound listener. - // This defaults to 15001. - uint32 outbound_listener_port = 1; - - // dialed_directly indicates whether this proxy should be dialed using original destination IP - // in the connection rather than load balance between all endpoints. - bool dialed_directly = 2; -} - -// BootstrapConfig is equivalent to configuration defined -// in our docs. -message BootstrapConfig { - string statsd_url = 1; - string dogstatsd_url = 2; - repeated string stats_tags = 3; - string prometheus_bind_addr = 4; - string stats_bind_addr = 5; - string ready_bind_addr = 6; - string override_json_tpl = 7; - string static_clusters_json = 8; - string static_listeners_json = 9; - string stats_sinks_json = 10; - string stats_config_json = 11; - string stats_flush_interval = 12; - string tracing_config_json = 13; - string telemetry_collector_bind_socket_dir = 14; -} - -// +kubebuilder:validation:Enum=PROXY_MODE_DEFAULT;PROXY_MODE_TRANSPARENT;PROXY_MODE_DIRECT -// +kubebuilder:validation:Type=string -enum ProxyMode { - // ProxyModeDefault represents no specific mode and should - // be used to indicate that a different layer of the configuration - // chain should take precedence - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - PROXY_MODE_DEFAULT = 0; - - // ProxyModeTransparent represents that inbound and outbound application - // traffic is being captured and redirected through the proxy. - PROXY_MODE_TRANSPARENT = 1; - - // ProxyModeDirect represents that the proxy's listeners must be dialed directly - // by the local application and other proxies. - PROXY_MODE_DIRECT = 2; -} - -// AccessLogsConfig contains the associated default settings for all Envoy -// instances within the datacenter or partition -message AccessLogsConfig { - // Enabled turns off all access logging - bool enabled = 1; - - // DisableListenerLogs turns off just listener logs for connections rejected by Envoy because they don't - // have a matching listener filter. - bool disable_listener_logs = 2; - - // Type selects the output for logs: "file", "stderr". "stdout" - LogSinkType type = 3; - - // Path is the output file to write logs - string path = 4; - - // The presence of one format string or the other implies the access log string encoding. - // Defining both is invalid. - string json_format = 5; - string text_format = 6; -} - -// +kubebuilder:validation:Enum=LOG_SINK_TYPE_DEFAULT;LOG_SINK_TYPE_FILE;LOG_SINK_TYPE_STDERR;LOG_SINK_TYPE_STDOUT -// +kubebuilder:validation:Type=string -enum LogSinkType { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - LOG_SINK_TYPE_DEFAULT = 0; - LOG_SINK_TYPE_FILE = 1; - LOG_SINK_TYPE_STDERR = 2; - LOG_SINK_TYPE_STDOUT = 3; -} - -// EnvoyExtension has configuration for an extension that patches Envoy resources. -message EnvoyExtension { - string name = 1; - bool required = 2; - // +kubebuilder:validation:Type=object - // +kubebuilder:validation:Schemaless - // +kubebuilder:pruning:PreserveUnknownFields - google.protobuf.Struct arguments = 3; - string consul_version = 4; - string envoy_version = 5; -} - -// +kubebuilder:validation:Enum=MUTUAL_TLS_MODE_DEFAULT;MUTUAL_TLS_MODE_STRICT;MUTUAL_TLS_MODE_PERMISSIVE -// +kubebuilder:validation:Type=string -enum MutualTLSMode { - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - MUTUAL_TLS_MODE_DEFAULT = 0; - MUTUAL_TLS_MODE_STRICT = 1; - MUTUAL_TLS_MODE_PERMISSIVE = 2; -} diff --git a/proto-public/pbmesh/v2beta1/proxy_configuration_addon.go b/proto-public/pbmesh/v2beta1/proxy_configuration_addon.go deleted file mode 100644 index 22f013c1a7e0..000000000000 --- a/proto-public/pbmesh/v2beta1/proxy_configuration_addon.go +++ /dev/null @@ -1,11 +0,0 @@ -package meshv2beta1 - -func (p *ComputedProxyConfiguration) IsTransparentProxy() bool { - return p.GetDynamicConfig() != nil && - p.DynamicConfig.Mode == ProxyMode_PROXY_MODE_TRANSPARENT -} - -func (p *ProxyConfiguration) IsTransparentProxy() bool { - return p.GetDynamicConfig() != nil && - p.DynamicConfig.Mode == ProxyMode_PROXY_MODE_TRANSPARENT -} diff --git a/proto-public/pbmesh/v2beta1/proxy_configuration_addon_test.go b/proto-public/pbmesh/v2beta1/proxy_configuration_addon_test.go deleted file mode 100644 index ab2dfd2dd2dd..000000000000 --- a/proto-public/pbmesh/v2beta1/proxy_configuration_addon_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package meshv2beta1 - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestIsTransparentProxy(t *testing.T) { - cases := map[string]struct { - dynamicConfig *DynamicConfig - exp bool - }{ - "nil dynamic config": { - dynamicConfig: nil, - exp: false, - }, - "default mode": { - dynamicConfig: &DynamicConfig{ - Mode: ProxyMode_PROXY_MODE_DEFAULT, - }, - exp: false, - }, - "direct mode": { - dynamicConfig: &DynamicConfig{ - Mode: ProxyMode_PROXY_MODE_DEFAULT, - }, - exp: false, - }, - "transparent mode": { - dynamicConfig: &DynamicConfig{ - Mode: ProxyMode_PROXY_MODE_TRANSPARENT, - }, - exp: true, - }, - } - - for name, c := range cases { - t.Run(name, func(t *testing.T) { - proxyCfg := &ProxyConfiguration{ - DynamicConfig: c.dynamicConfig, - } - compProxyCfg := &ComputedProxyConfiguration{ - DynamicConfig: c.dynamicConfig, - } - require.Equal(t, c.exp, proxyCfg.IsTransparentProxy()) - require.Equal(t, c.exp, compProxyCfg.IsTransparentProxy()) - }) - } -} diff --git a/proto-public/pbmesh/v2beta1/proxy_configuration_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/proxy_configuration_deepcopy.gen.go deleted file mode 100644 index bc5b81a9a6fb..000000000000 --- a/proto-public/pbmesh/v2beta1/proxy_configuration_deepcopy.gen.go +++ /dev/null @@ -1,132 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ProxyConfiguration within kubernetes types, where deepcopy-gen is used. -func (in *ProxyConfiguration) DeepCopyInto(out *ProxyConfiguration) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyConfiguration. Required by controller-gen. -func (in *ProxyConfiguration) DeepCopy() *ProxyConfiguration { - if in == nil { - return nil - } - out := new(ProxyConfiguration) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ProxyConfiguration. Required by controller-gen. -func (in *ProxyConfiguration) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using DynamicConfig within kubernetes types, where deepcopy-gen is used. -func (in *DynamicConfig) DeepCopyInto(out *DynamicConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DynamicConfig. Required by controller-gen. -func (in *DynamicConfig) DeepCopy() *DynamicConfig { - if in == nil { - return nil - } - out := new(DynamicConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new DynamicConfig. Required by controller-gen. -func (in *DynamicConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using TransparentProxy within kubernetes types, where deepcopy-gen is used. -func (in *TransparentProxy) DeepCopyInto(out *TransparentProxy) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TransparentProxy. Required by controller-gen. -func (in *TransparentProxy) DeepCopy() *TransparentProxy { - if in == nil { - return nil - } - out := new(TransparentProxy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TransparentProxy. Required by controller-gen. -func (in *TransparentProxy) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using BootstrapConfig within kubernetes types, where deepcopy-gen is used. -func (in *BootstrapConfig) DeepCopyInto(out *BootstrapConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapConfig. Required by controller-gen. -func (in *BootstrapConfig) DeepCopy() *BootstrapConfig { - if in == nil { - return nil - } - out := new(BootstrapConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapConfig. Required by controller-gen. -func (in *BootstrapConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using AccessLogsConfig within kubernetes types, where deepcopy-gen is used. -func (in *AccessLogsConfig) DeepCopyInto(out *AccessLogsConfig) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AccessLogsConfig. Required by controller-gen. -func (in *AccessLogsConfig) DeepCopy() *AccessLogsConfig { - if in == nil { - return nil - } - out := new(AccessLogsConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new AccessLogsConfig. Required by controller-gen. -func (in *AccessLogsConfig) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using EnvoyExtension within kubernetes types, where deepcopy-gen is used. -func (in *EnvoyExtension) DeepCopyInto(out *EnvoyExtension) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyExtension. Required by controller-gen. -func (in *EnvoyExtension) DeepCopy() *EnvoyExtension { - if in == nil { - return nil - } - out := new(EnvoyExtension) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyExtension. Required by controller-gen. -func (in *EnvoyExtension) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/proxy_configuration_json.gen.go b/proto-public/pbmesh/v2beta1/proxy_configuration_json.gen.go deleted file mode 100644 index 41fcdd5ed2f6..000000000000 --- a/proto-public/pbmesh/v2beta1/proxy_configuration_json.gen.go +++ /dev/null @@ -1,77 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ProxyConfiguration -func (this *ProxyConfiguration) MarshalJSON() ([]byte, error) { - str, err := ProxyConfigurationMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ProxyConfiguration -func (this *ProxyConfiguration) UnmarshalJSON(b []byte) error { - return ProxyConfigurationUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for DynamicConfig -func (this *DynamicConfig) MarshalJSON() ([]byte, error) { - str, err := ProxyConfigurationMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for DynamicConfig -func (this *DynamicConfig) UnmarshalJSON(b []byte) error { - return ProxyConfigurationUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for TransparentProxy -func (this *TransparentProxy) MarshalJSON() ([]byte, error) { - str, err := ProxyConfigurationMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TransparentProxy -func (this *TransparentProxy) UnmarshalJSON(b []byte) error { - return ProxyConfigurationUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for BootstrapConfig -func (this *BootstrapConfig) MarshalJSON() ([]byte, error) { - str, err := ProxyConfigurationMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for BootstrapConfig -func (this *BootstrapConfig) UnmarshalJSON(b []byte) error { - return ProxyConfigurationUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for AccessLogsConfig -func (this *AccessLogsConfig) MarshalJSON() ([]byte, error) { - str, err := ProxyConfigurationMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for AccessLogsConfig -func (this *AccessLogsConfig) UnmarshalJSON(b []byte) error { - return ProxyConfigurationUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for EnvoyExtension -func (this *EnvoyExtension) MarshalJSON() ([]byte, error) { - str, err := ProxyConfigurationMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for EnvoyExtension -func (this *EnvoyExtension) UnmarshalJSON(b []byte) error { - return ProxyConfigurationUnmarshaler.Unmarshal(b, this) -} - -var ( - ProxyConfigurationMarshaler = &protojson.MarshalOptions{} - ProxyConfigurationUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/proxy_state.pb.binary.go b/proto-public/pbmesh/v2beta1/proxy_state.pb.binary.go deleted file mode 100644 index d259ba66fc79..000000000000 --- a/proto-public/pbmesh/v2beta1/proxy_state.pb.binary.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/proxy_state.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ProxyStateTemplate) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ProxyStateTemplate) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ProxyState) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ProxyState) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/proxy_state.pb.go b/proto-public/pbmesh/v2beta1/proxy_state.pb.go deleted file mode 100644 index 5f26294a5d1c..000000000000 --- a/proto-public/pbmesh/v2beta1/proxy_state.pb.go +++ /dev/null @@ -1,551 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/proxy_state.proto - -package meshv2beta1 - -import ( - pbproxystate "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate" - pbresource "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ProxyStateTemplate struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ProxyState is the partially filled out ProxyState resource. The Endpoints, LeafCertificates and TrustBundles fields will need filling in after the resource is stored. - ProxyState *ProxyState `protobuf:"bytes,1,opt,name=proxy_state,json=proxyState,proto3" json:"proxy_state,omitempty"` - // RequiredEndpoints is a map of arbitrary string names to endpoint refs that need fetching by the proxy state controller. - RequiredEndpoints map[string]*pbproxystate.EndpointRef `protobuf:"bytes,2,rep,name=required_endpoints,json=requiredEndpoints,proto3" json:"required_endpoints,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // RequiredLeafCertificates is a map of arbitrary string names to leaf certificates that need fetching/generation by the proxy state controller. - RequiredLeafCertificates map[string]*pbproxystate.LeafCertificateRef `protobuf:"bytes,3,rep,name=required_leaf_certificates,json=requiredLeafCertificates,proto3" json:"required_leaf_certificates,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // RequiredTrustBundles is a map of arbitrary string names to trust bundle refs that need fetching by the proxy state controller. - RequiredTrustBundles map[string]*pbproxystate.TrustBundleRef `protobuf:"bytes,4,rep,name=required_trust_bundles,json=requiredTrustBundles,proto3" json:"required_trust_bundles,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *ProxyStateTemplate) Reset() { - *x = ProxyStateTemplate{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_proxy_state_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProxyStateTemplate) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProxyStateTemplate) ProtoMessage() {} - -func (x *ProxyStateTemplate) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_proxy_state_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProxyStateTemplate.ProtoReflect.Descriptor instead. -func (*ProxyStateTemplate) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_proxy_state_proto_rawDescGZIP(), []int{0} -} - -func (x *ProxyStateTemplate) GetProxyState() *ProxyState { - if x != nil { - return x.ProxyState - } - return nil -} - -func (x *ProxyStateTemplate) GetRequiredEndpoints() map[string]*pbproxystate.EndpointRef { - if x != nil { - return x.RequiredEndpoints - } - return nil -} - -func (x *ProxyStateTemplate) GetRequiredLeafCertificates() map[string]*pbproxystate.LeafCertificateRef { - if x != nil { - return x.RequiredLeafCertificates - } - return nil -} - -func (x *ProxyStateTemplate) GetRequiredTrustBundles() map[string]*pbproxystate.TrustBundleRef { - if x != nil { - return x.RequiredTrustBundles - } - return nil -} - -type ProxyState struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Identity is a reference to the identity of the workload this proxy is for. - Identity *pbresource.Reference `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` - // Listeners is a list of listeners for this proxy. - Listeners []*pbproxystate.Listener `protobuf:"bytes,2,rep,name=listeners,proto3" json:"listeners,omitempty"` - // Clusters is a map from cluster name to clusters. The keys are referenced from listeners or routes. - Clusters map[string]*pbproxystate.Cluster `protobuf:"bytes,3,rep,name=clusters,proto3" json:"clusters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // Routes is a map from route name to routes. The keys are referenced from listeners. - Routes map[string]*pbproxystate.Route `protobuf:"bytes,4,rep,name=routes,proto3" json:"routes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // Endpoints is a map from cluster name to endpoints. - Endpoints map[string]*pbproxystate.Endpoints `protobuf:"bytes,5,rep,name=endpoints,proto3" json:"endpoints,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // LeafCertificates is a map from UUID to leaf certificates. - LeafCertificates map[string]*pbproxystate.LeafCertificate `protobuf:"bytes,6,rep,name=leaf_certificates,json=leafCertificates,proto3" json:"leaf_certificates,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // TrustBundles is a map from peer name to trust bundles. - TrustBundles map[string]*pbproxystate.TrustBundle `protobuf:"bytes,7,rep,name=trust_bundles,json=trustBundles,proto3" json:"trust_bundles,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // TLS has TLS configuration for this proxy. - Tls *pbproxystate.TLS `protobuf:"bytes,8,opt,name=tls,proto3" json:"tls,omitempty"` - // Escape defines top level escape hatches. These are user configured json strings that configure an entire piece of listener or cluster Envoy configuration. - Escape *pbproxystate.EscapeHatches `protobuf:"bytes,9,opt,name=escape,proto3" json:"escape,omitempty"` - // AccessLogs configures access logging for this proxy. - AccessLogs *pbproxystate.AccessLogs `protobuf:"bytes,10,opt,name=access_logs,json=accessLogs,proto3" json:"access_logs,omitempty"` -} - -func (x *ProxyState) Reset() { - *x = ProxyState{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_proxy_state_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProxyState) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProxyState) ProtoMessage() {} - -func (x *ProxyState) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_proxy_state_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProxyState.ProtoReflect.Descriptor instead. -func (*ProxyState) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_proxy_state_proto_rawDescGZIP(), []int{1} -} - -func (x *ProxyState) GetIdentity() *pbresource.Reference { - if x != nil { - return x.Identity - } - return nil -} - -func (x *ProxyState) GetListeners() []*pbproxystate.Listener { - if x != nil { - return x.Listeners - } - return nil -} - -func (x *ProxyState) GetClusters() map[string]*pbproxystate.Cluster { - if x != nil { - return x.Clusters - } - return nil -} - -func (x *ProxyState) GetRoutes() map[string]*pbproxystate.Route { - if x != nil { - return x.Routes - } - return nil -} - -func (x *ProxyState) GetEndpoints() map[string]*pbproxystate.Endpoints { - if x != nil { - return x.Endpoints - } - return nil -} - -func (x *ProxyState) GetLeafCertificates() map[string]*pbproxystate.LeafCertificate { - if x != nil { - return x.LeafCertificates - } - return nil -} - -func (x *ProxyState) GetTrustBundles() map[string]*pbproxystate.TrustBundle { - if x != nil { - return x.TrustBundles - } - return nil -} - -func (x *ProxyState) GetTls() *pbproxystate.TLS { - if x != nil { - return x.Tls - } - return nil -} - -func (x *ProxyState) GetEscape() *pbproxystate.EscapeHatches { - if x != nil { - return x.Escape - } - return nil -} - -func (x *ProxyState) GetAccessLogs() *pbproxystate.AccessLogs { - if x != nil { - return x.AccessLogs - } - return nil -} - -var File_pbmesh_v2beta1_proxy_state_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_proxy_state_proto_rawDesc = []byte{ - 0x0a, 0x20, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x1a, 0x2d, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x29, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2b, 0x70, 0x62, 0x6d, - 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x5f, 0x68, 0x61, 0x74, - 0x63, 0x68, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x70, 0x62, 0x6d, 0x65, - 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x2f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x32, 0x70, - 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x62, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, - 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x19, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x88, 0x07, 0x0a, 0x12, 0x50, - 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x12, 0x4a, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x77, 0x0a, - 0x12, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x11, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x1a, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4f, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, - 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x52, - 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x18, 0x72, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x81, 0x01, 0x0a, 0x16, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x54, 0x72, - 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x1a, 0x7d, 0x0a, 0x16, 0x52, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x8b, 0x01, 0x0a, 0x1d, 0x52, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x54, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, - 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x66, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x83, 0x01, 0x0a, 0x19, 0x52, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x50, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, - 0x65, 0x66, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x3a, 0x06, 0xa2, - 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0xaf, 0x0b, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x52, 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, - 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, - 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x53, 0x0a, 0x08, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, - 0x4d, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x56, - 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x6c, 0x0a, 0x11, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x63, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x65, 0x61, - 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x10, 0x6c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x73, 0x12, 0x60, 0x0a, 0x0d, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x62, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, - 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x78, - 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x74, 0x72, 0x75, 0x73, 0x74, 0x42, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x03, 0x74, 0x6c, 0x73, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x54, 0x4c, 0x53, 0x52, 0x03, 0x74, 0x6c, 0x73, 0x12, 0x51, 0x0a, 0x06, 0x65, 0x73, 0x63, - 0x61, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x48, 0x61, 0x74, - 0x63, 0x68, 0x65, 0x73, 0x52, 0x06, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x12, 0x57, 0x0a, 0x0b, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x1a, 0x70, 0x0a, 0x0d, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x49, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6c, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x47, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x73, 0x0a, 0x0e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4b, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x80, 0x01, 0x0a, 0x15, 0x4c, - 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x51, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2e, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x78, 0x0a, - 0x11, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x70, 0x62, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x90, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0f, 0x50, - 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, - 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, - 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, - 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, - 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, - 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_proxy_state_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_proxy_state_proto_rawDescData = file_pbmesh_v2beta1_proxy_state_proto_rawDesc -) - -func file_pbmesh_v2beta1_proxy_state_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_proxy_state_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_proxy_state_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_proxy_state_proto_rawDescData) - }) - return file_pbmesh_v2beta1_proxy_state_proto_rawDescData -} - -var file_pbmesh_v2beta1_proxy_state_proto_msgTypes = make([]protoimpl.MessageInfo, 10) -var file_pbmesh_v2beta1_proxy_state_proto_goTypes = []interface{}{ - (*ProxyStateTemplate)(nil), // 0: hashicorp.consul.mesh.v2beta1.ProxyStateTemplate - (*ProxyState)(nil), // 1: hashicorp.consul.mesh.v2beta1.ProxyState - nil, // 2: hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.RequiredEndpointsEntry - nil, // 3: hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.RequiredLeafCertificatesEntry - nil, // 4: hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.RequiredTrustBundlesEntry - nil, // 5: hashicorp.consul.mesh.v2beta1.ProxyState.ClustersEntry - nil, // 6: hashicorp.consul.mesh.v2beta1.ProxyState.RoutesEntry - nil, // 7: hashicorp.consul.mesh.v2beta1.ProxyState.EndpointsEntry - nil, // 8: hashicorp.consul.mesh.v2beta1.ProxyState.LeafCertificatesEntry - nil, // 9: hashicorp.consul.mesh.v2beta1.ProxyState.TrustBundlesEntry - (*pbresource.Reference)(nil), // 10: hashicorp.consul.resource.Reference - (*pbproxystate.Listener)(nil), // 11: hashicorp.consul.mesh.v2beta1.pbproxystate.Listener - (*pbproxystate.TLS)(nil), // 12: hashicorp.consul.mesh.v2beta1.pbproxystate.TLS - (*pbproxystate.EscapeHatches)(nil), // 13: hashicorp.consul.mesh.v2beta1.pbproxystate.EscapeHatches - (*pbproxystate.AccessLogs)(nil), // 14: hashicorp.consul.mesh.v2beta1.pbproxystate.AccessLogs - (*pbproxystate.EndpointRef)(nil), // 15: hashicorp.consul.mesh.v2beta1.pbproxystate.EndpointRef - (*pbproxystate.LeafCertificateRef)(nil), // 16: hashicorp.consul.mesh.v2beta1.pbproxystate.LeafCertificateRef - (*pbproxystate.TrustBundleRef)(nil), // 17: hashicorp.consul.mesh.v2beta1.pbproxystate.TrustBundleRef - (*pbproxystate.Cluster)(nil), // 18: hashicorp.consul.mesh.v2beta1.pbproxystate.Cluster - (*pbproxystate.Route)(nil), // 19: hashicorp.consul.mesh.v2beta1.pbproxystate.Route - (*pbproxystate.Endpoints)(nil), // 20: hashicorp.consul.mesh.v2beta1.pbproxystate.Endpoints - (*pbproxystate.LeafCertificate)(nil), // 21: hashicorp.consul.mesh.v2beta1.pbproxystate.LeafCertificate - (*pbproxystate.TrustBundle)(nil), // 22: hashicorp.consul.mesh.v2beta1.pbproxystate.TrustBundle -} -var file_pbmesh_v2beta1_proxy_state_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.proxy_state:type_name -> hashicorp.consul.mesh.v2beta1.ProxyState - 2, // 1: hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.required_endpoints:type_name -> hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.RequiredEndpointsEntry - 3, // 2: hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.required_leaf_certificates:type_name -> hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.RequiredLeafCertificatesEntry - 4, // 3: hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.required_trust_bundles:type_name -> hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.RequiredTrustBundlesEntry - 10, // 4: hashicorp.consul.mesh.v2beta1.ProxyState.identity:type_name -> hashicorp.consul.resource.Reference - 11, // 5: hashicorp.consul.mesh.v2beta1.ProxyState.listeners:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Listener - 5, // 6: hashicorp.consul.mesh.v2beta1.ProxyState.clusters:type_name -> hashicorp.consul.mesh.v2beta1.ProxyState.ClustersEntry - 6, // 7: hashicorp.consul.mesh.v2beta1.ProxyState.routes:type_name -> hashicorp.consul.mesh.v2beta1.ProxyState.RoutesEntry - 7, // 8: hashicorp.consul.mesh.v2beta1.ProxyState.endpoints:type_name -> hashicorp.consul.mesh.v2beta1.ProxyState.EndpointsEntry - 8, // 9: hashicorp.consul.mesh.v2beta1.ProxyState.leaf_certificates:type_name -> hashicorp.consul.mesh.v2beta1.ProxyState.LeafCertificatesEntry - 9, // 10: hashicorp.consul.mesh.v2beta1.ProxyState.trust_bundles:type_name -> hashicorp.consul.mesh.v2beta1.ProxyState.TrustBundlesEntry - 12, // 11: hashicorp.consul.mesh.v2beta1.ProxyState.tls:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TLS - 13, // 12: hashicorp.consul.mesh.v2beta1.ProxyState.escape:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.EscapeHatches - 14, // 13: hashicorp.consul.mesh.v2beta1.ProxyState.access_logs:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.AccessLogs - 15, // 14: hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.RequiredEndpointsEntry.value:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.EndpointRef - 16, // 15: hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.RequiredLeafCertificatesEntry.value:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.LeafCertificateRef - 17, // 16: hashicorp.consul.mesh.v2beta1.ProxyStateTemplate.RequiredTrustBundlesEntry.value:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TrustBundleRef - 18, // 17: hashicorp.consul.mesh.v2beta1.ProxyState.ClustersEntry.value:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Cluster - 19, // 18: hashicorp.consul.mesh.v2beta1.ProxyState.RoutesEntry.value:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Route - 20, // 19: hashicorp.consul.mesh.v2beta1.ProxyState.EndpointsEntry.value:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.Endpoints - 21, // 20: hashicorp.consul.mesh.v2beta1.ProxyState.LeafCertificatesEntry.value:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.LeafCertificate - 22, // 21: hashicorp.consul.mesh.v2beta1.ProxyState.TrustBundlesEntry.value:type_name -> hashicorp.consul.mesh.v2beta1.pbproxystate.TrustBundle - 22, // [22:22] is the sub-list for method output_type - 22, // [22:22] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_proxy_state_proto_init() } -func file_pbmesh_v2beta1_proxy_state_proto_init() { - if File_pbmesh_v2beta1_proxy_state_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_proxy_state_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProxyStateTemplate); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_proxy_state_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProxyState); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_proxy_state_proto_rawDesc, - NumEnums: 0, - NumMessages: 10, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_proxy_state_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_proxy_state_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_proxy_state_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_proxy_state_proto = out.File - file_pbmesh_v2beta1_proxy_state_proto_rawDesc = nil - file_pbmesh_v2beta1_proxy_state_proto_goTypes = nil - file_pbmesh_v2beta1_proxy_state_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/proxy_state.proto b/proto-public/pbmesh/v2beta1/proxy_state.proto deleted file mode 100644 index cd70dbbd5f19..000000000000 --- a/proto-public/pbmesh/v2beta1/proxy_state.proto +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "pbmesh/v2beta1/pbproxystate/access_logs.proto"; -import "pbmesh/v2beta1/pbproxystate/cluster.proto"; -import "pbmesh/v2beta1/pbproxystate/endpoints.proto"; -import "pbmesh/v2beta1/pbproxystate/escape_hatches.proto"; -import "pbmesh/v2beta1/pbproxystate/listener.proto"; -import "pbmesh/v2beta1/pbproxystate/references.proto"; -import "pbmesh/v2beta1/pbproxystate/route.proto"; -import "pbmesh/v2beta1/pbproxystate/transport_socket.proto"; -import "pbresource/annotations.proto"; -import "pbresource/resource.proto"; - -message ProxyStateTemplate { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // ProxyState is the partially filled out ProxyState resource. The Endpoints, LeafCertificates and TrustBundles fields will need filling in after the resource is stored. - ProxyState proxy_state = 1; - - // RequiredEndpoints is a map of arbitrary string names to endpoint refs that need fetching by the proxy state controller. - map required_endpoints = 2; - - // RequiredLeafCertificates is a map of arbitrary string names to leaf certificates that need fetching/generation by the proxy state controller. - map required_leaf_certificates = 3; - - // RequiredTrustBundles is a map of arbitrary string names to trust bundle refs that need fetching by the proxy state controller. - map required_trust_bundles = 4; -} - -message ProxyState { - // Identity is a reference to the identity of the workload this proxy is for. - hashicorp.consul.resource.Reference identity = 1; - // Listeners is a list of listeners for this proxy. - repeated pbproxystate.Listener listeners = 2; - // Clusters is a map from cluster name to clusters. The keys are referenced from listeners or routes. - map clusters = 3; - // Routes is a map from route name to routes. The keys are referenced from listeners. - map routes = 4; - // Endpoints is a map from cluster name to endpoints. - map endpoints = 5; - // LeafCertificates is a map from UUID to leaf certificates. - map leaf_certificates = 6; - // TrustBundles is a map from peer name to trust bundles. - map trust_bundles = 7; - // TLS has TLS configuration for this proxy. - pbproxystate.TLS tls = 8; - // Escape defines top level escape hatches. These are user configured json strings that configure an entire piece of listener or cluster Envoy configuration. - pbproxystate.EscapeHatches escape = 9; - // AccessLogs configures access logging for this proxy. - pbproxystate.AccessLogs access_logs = 10; -} diff --git a/proto-public/pbmesh/v2beta1/proxy_state_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/proxy_state_deepcopy.gen.go deleted file mode 100644 index fbc6ed842098..000000000000 --- a/proto-public/pbmesh/v2beta1/proxy_state_deepcopy.gen.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using ProxyStateTemplate within kubernetes types, where deepcopy-gen is used. -func (in *ProxyStateTemplate) DeepCopyInto(out *ProxyStateTemplate) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyStateTemplate. Required by controller-gen. -func (in *ProxyStateTemplate) DeepCopy() *ProxyStateTemplate { - if in == nil { - return nil - } - out := new(ProxyStateTemplate) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ProxyStateTemplate. Required by controller-gen. -func (in *ProxyStateTemplate) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using ProxyState within kubernetes types, where deepcopy-gen is used. -func (in *ProxyState) DeepCopyInto(out *ProxyState) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyState. Required by controller-gen. -func (in *ProxyState) DeepCopy() *ProxyState { - if in == nil { - return nil - } - out := new(ProxyState) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ProxyState. Required by controller-gen. -func (in *ProxyState) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/proxy_state_json.gen.go b/proto-public/pbmesh/v2beta1/proxy_state_json.gen.go deleted file mode 100644 index 8449f8bbd8f7..000000000000 --- a/proto-public/pbmesh/v2beta1/proxy_state_json.gen.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for ProxyStateTemplate -func (this *ProxyStateTemplate) MarshalJSON() ([]byte, error) { - str, err := ProxyStateMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ProxyStateTemplate -func (this *ProxyStateTemplate) UnmarshalJSON(b []byte) error { - return ProxyStateUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for ProxyState -func (this *ProxyState) MarshalJSON() ([]byte, error) { - str, err := ProxyStateMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for ProxyState -func (this *ProxyState) UnmarshalJSON(b []byte) error { - return ProxyStateUnmarshaler.Unmarshal(b, this) -} - -var ( - ProxyStateMarshaler = &protojson.MarshalOptions{} - ProxyStateUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/resource_types.gen.go b/proto-public/pbmesh/v2beta1/resource_types.gen.go deleted file mode 100644 index 68406c5d1e88..000000000000 --- a/proto-public/pbmesh/v2beta1/resource_types.gen.go +++ /dev/null @@ -1,92 +0,0 @@ -// Code generated by protoc-gen-resource-types. DO NOT EDIT. - -package meshv2beta1 - -import ( - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - GroupName = "mesh" - Version = "v2beta1" - - ComputedExplicitDestinationsKind = "ComputedExplicitDestinations" - ComputedProxyConfigurationKind = "ComputedProxyConfiguration" - ComputedRoutesKind = "ComputedRoutes" - DestinationPolicyKind = "DestinationPolicy" - DestinationsKind = "Destinations" - DestinationsConfigurationKind = "DestinationsConfiguration" - GRPCRouteKind = "GRPCRoute" - HTTPRouteKind = "HTTPRoute" - ProxyConfigurationKind = "ProxyConfiguration" - ProxyStateTemplateKind = "ProxyStateTemplate" - TCPRouteKind = "TCPRoute" -) - -var ( - ComputedExplicitDestinationsType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: ComputedExplicitDestinationsKind, - } - - ComputedProxyConfigurationType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: ComputedProxyConfigurationKind, - } - - ComputedRoutesType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: ComputedRoutesKind, - } - - DestinationPolicyType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: DestinationPolicyKind, - } - - DestinationsType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: DestinationsKind, - } - - DestinationsConfigurationType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: DestinationsConfigurationKind, - } - - GRPCRouteType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: GRPCRouteKind, - } - - HTTPRouteType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: HTTPRouteKind, - } - - ProxyConfigurationType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: ProxyConfigurationKind, - } - - ProxyStateTemplateType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: ProxyStateTemplateKind, - } - - TCPRouteType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: TCPRouteKind, - } -) diff --git a/proto-public/pbmesh/v2beta1/routing.pb.go b/proto-public/pbmesh/v2beta1/routing.pb.go deleted file mode 100644 index 4b1f64877431..000000000000 --- a/proto-public/pbmesh/v2beta1/routing.pb.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/routing.proto - -package meshv2beta1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// +kubebuilder:validation:Enum=MESH_GATEWAY_MODE_UNSPECIFIED;MESH_GATEWAY_MODE_NONE;MESH_GATEWAY_MODE_LOCAL;MESH_GATEWAY_MODE_REMOTE -// +kubebuilder:validation:Type=string -type MeshGatewayMode int32 - -const ( - // MESH_GATEWAY_MODE_UNSPECIFIED represents no specific mode and should be - // used to indicate that the decision on the mode will be made by other - // configuration or default settings. - MeshGatewayMode_MESH_GATEWAY_MODE_UNSPECIFIED MeshGatewayMode = 0 - // MESH_GATEWAY_MODE_NONE is the mode to use when traffic should not be - // routed through any gateway but instead be routed directly to the - // destination. - MeshGatewayMode_MESH_GATEWAY_MODE_NONE MeshGatewayMode = 1 - // MESH_GATEWAY_MODE_LOCAL is the mode to use when traffic should be routed - // to the local gateway. The local gateway will then ensure that the - // connection is proxied correctly to its final destination. This mode will - // most often be needed for workloads that are prevented from making outbound - // requests outside of their local network/environment. In this case a - // gateway will sit at the edge of sit at the edge of the network and will - // proxy outbound connections potentially to other gateways in remote - // environments. - MeshGatewayMode_MESH_GATEWAY_MODE_LOCAL MeshGatewayMode = 2 - // MESH_GATEWAY_MODE_REMOTE is the mode to use when traffic should be routed - // to a remote mesh gateway. This mode will most often be used when workloads - // can make outbound requests destined for a remote network/environment but - // where the remote network/environment will not allow direct addressing. The - // mesh gateway in the remote environment will sit at the edge and proxy - // requests into that environment. - MeshGatewayMode_MESH_GATEWAY_MODE_REMOTE MeshGatewayMode = 3 -) - -// Enum value maps for MeshGatewayMode. -var ( - MeshGatewayMode_name = map[int32]string{ - 0: "MESH_GATEWAY_MODE_UNSPECIFIED", - 1: "MESH_GATEWAY_MODE_NONE", - 2: "MESH_GATEWAY_MODE_LOCAL", - 3: "MESH_GATEWAY_MODE_REMOTE", - } - MeshGatewayMode_value = map[string]int32{ - "MESH_GATEWAY_MODE_UNSPECIFIED": 0, - "MESH_GATEWAY_MODE_NONE": 1, - "MESH_GATEWAY_MODE_LOCAL": 2, - "MESH_GATEWAY_MODE_REMOTE": 3, - } -) - -func (x MeshGatewayMode) Enum() *MeshGatewayMode { - p := new(MeshGatewayMode) - *p = x - return p -} - -func (x MeshGatewayMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (MeshGatewayMode) Descriptor() protoreflect.EnumDescriptor { - return file_pbmesh_v2beta1_routing_proto_enumTypes[0].Descriptor() -} - -func (MeshGatewayMode) Type() protoreflect.EnumType { - return &file_pbmesh_v2beta1_routing_proto_enumTypes[0] -} - -func (x MeshGatewayMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use MeshGatewayMode.Descriptor instead. -func (MeshGatewayMode) EnumDescriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_routing_proto_rawDescGZIP(), []int{0} -} - -var File_pbmesh_v2beta1_routing_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_routing_proto_rawDesc = []byte{ - 0x0a, 0x1c, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2a, 0x8b, 0x01, - 0x0a, 0x0f, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x4d, 0x45, 0x53, 0x48, 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, - 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x4d, 0x45, 0x53, 0x48, 0x5f, 0x47, 0x41, 0x54, - 0x45, 0x57, 0x41, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, - 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x45, 0x53, 0x48, 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, - 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x1c, 0x0a, - 0x18, 0x4d, 0x45, 0x53, 0x48, 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x5f, 0x4d, 0x4f, - 0x44, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x10, 0x03, 0x42, 0x8d, 0x02, 0x0a, 0x21, - 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x42, 0x0c, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, - 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1d, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, - 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_routing_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_routing_proto_rawDescData = file_pbmesh_v2beta1_routing_proto_rawDesc -) - -func file_pbmesh_v2beta1_routing_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_routing_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_routing_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_routing_proto_rawDescData) - }) - return file_pbmesh_v2beta1_routing_proto_rawDescData -} - -var file_pbmesh_v2beta1_routing_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pbmesh_v2beta1_routing_proto_goTypes = []interface{}{ - (MeshGatewayMode)(0), // 0: hashicorp.consul.mesh.v2beta1.MeshGatewayMode -} -var file_pbmesh_v2beta1_routing_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_routing_proto_init() } -func file_pbmesh_v2beta1_routing_proto_init() { - if File_pbmesh_v2beta1_routing_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_routing_proto_rawDesc, - NumEnums: 1, - NumMessages: 0, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_routing_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_routing_proto_depIdxs, - EnumInfos: file_pbmesh_v2beta1_routing_proto_enumTypes, - }.Build() - File_pbmesh_v2beta1_routing_proto = out.File - file_pbmesh_v2beta1_routing_proto_rawDesc = nil - file_pbmesh_v2beta1_routing_proto_goTypes = nil - file_pbmesh_v2beta1_routing_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/routing.proto b/proto-public/pbmesh/v2beta1/routing.proto deleted file mode 100644 index b09d28a6458a..000000000000 --- a/proto-public/pbmesh/v2beta1/routing.proto +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -// +kubebuilder:validation:Enum=MESH_GATEWAY_MODE_UNSPECIFIED;MESH_GATEWAY_MODE_NONE;MESH_GATEWAY_MODE_LOCAL;MESH_GATEWAY_MODE_REMOTE -// +kubebuilder:validation:Type=string -enum MeshGatewayMode { - // MESH_GATEWAY_MODE_UNSPECIFIED represents no specific mode and should be - // used to indicate that the decision on the mode will be made by other - // configuration or default settings. - MESH_GATEWAY_MODE_UNSPECIFIED = 0; - - // MESH_GATEWAY_MODE_NONE is the mode to use when traffic should not be - // routed through any gateway but instead be routed directly to the - // destination. - MESH_GATEWAY_MODE_NONE = 1; - - // MESH_GATEWAY_MODE_LOCAL is the mode to use when traffic should be routed - // to the local gateway. The local gateway will then ensure that the - // connection is proxied correctly to its final destination. This mode will - // most often be needed for workloads that are prevented from making outbound - // requests outside of their local network/environment. In this case a - // gateway will sit at the edge of sit at the edge of the network and will - // proxy outbound connections potentially to other gateways in remote - // environments. - MESH_GATEWAY_MODE_LOCAL = 2; - - // MESH_GATEWAY_MODE_REMOTE is the mode to use when traffic should be routed - // to a remote mesh gateway. This mode will most often be used when workloads - // can make outbound requests destined for a remote network/environment but - // where the remote network/environment will not allow direct addressing. The - // mesh gateway in the remote environment will sit at the edge and proxy - // requests into that environment. - MESH_GATEWAY_MODE_REMOTE = 3; -} diff --git a/proto-public/pbmesh/v2beta1/tcp_route.pb.binary.go b/proto-public/pbmesh/v2beta1/tcp_route.pb.binary.go deleted file mode 100644 index 4c10deae5375..000000000000 --- a/proto-public/pbmesh/v2beta1/tcp_route.pb.binary.go +++ /dev/null @@ -1,38 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmesh/v2beta1/tcp_route.proto - -package meshv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TCPRoute) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TCPRoute) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TCPRouteRule) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TCPRouteRule) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *TCPBackendRef) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *TCPBackendRef) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbmesh/v2beta1/tcp_route.pb.go b/proto-public/pbmesh/v2beta1/tcp_route.pb.go deleted file mode 100644 index 5a2c401846af..000000000000 --- a/proto-public/pbmesh/v2beta1/tcp_route.pb.go +++ /dev/null @@ -1,362 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmesh/v2beta1/tcp_route.proto - -package meshv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// NOTE: this should align to the GAMMA/gateway-api version, or at least be -// easily translatable. -// -// https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.TCPRoute -// -// This is a Resource type. -type TCPRoute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ParentRefs references the resources (usually Services) that a Route wants - // to be attached to. - // - // It is invalid to reference an identical parent more than once. It is valid - // to reference multiple distinct sections within the same parent resource. - ParentRefs []*ParentReference `protobuf:"bytes,1,rep,name=parent_refs,json=parentRefs,proto3" json:"parent_refs,omitempty"` - // Rules are a list of TCP matchers and actions. - Rules []*TCPRouteRule `protobuf:"bytes,2,rep,name=rules,proto3" json:"rules,omitempty"` -} - -func (x *TCPRoute) Reset() { - *x = TCPRoute{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_tcp_route_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TCPRoute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TCPRoute) ProtoMessage() {} - -func (x *TCPRoute) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_tcp_route_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TCPRoute.ProtoReflect.Descriptor instead. -func (*TCPRoute) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_tcp_route_proto_rawDescGZIP(), []int{0} -} - -func (x *TCPRoute) GetParentRefs() []*ParentReference { - if x != nil { - return x.ParentRefs - } - return nil -} - -func (x *TCPRoute) GetRules() []*TCPRouteRule { - if x != nil { - return x.Rules - } - return nil -} - -type TCPRouteRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // BackendRefs defines the backend(s) where matching requests should be sent. - // If unspecified or invalid (refers to a non-existent resource or a Service - // with no endpoints), the underlying implementation MUST actively reject - // connection attempts to this backend. Connection rejections must respect - // weight; if an invalid backend is requested to have 80% of connections, - // then 80% of connections must be rejected instead. - BackendRefs []*TCPBackendRef `protobuf:"bytes,1,rep,name=backend_refs,json=backendRefs,proto3" json:"backend_refs,omitempty"` -} - -func (x *TCPRouteRule) Reset() { - *x = TCPRouteRule{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_tcp_route_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TCPRouteRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TCPRouteRule) ProtoMessage() {} - -func (x *TCPRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_tcp_route_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TCPRouteRule.ProtoReflect.Descriptor instead. -func (*TCPRouteRule) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_tcp_route_proto_rawDescGZIP(), []int{1} -} - -func (x *TCPRouteRule) GetBackendRefs() []*TCPBackendRef { - if x != nil { - return x.BackendRefs - } - return nil -} - -type TCPBackendRef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BackendRef *BackendReference `protobuf:"bytes,1,opt,name=backend_ref,json=backendRef,proto3" json:"backend_ref,omitempty"` - // Weight specifies the proportion of requests forwarded to the referenced - // backend. This is computed as weight/(sum of all weights in this - // BackendRefs list). For non-zero values, there may be some epsilon from the - // exact proportion defined here depending on the precision an implementation - // supports. Weight is not a percentage and the sum of weights does not need - // to equal 100. - // - // If only one backend is specified and it has a weight greater than 0, 100% - // of the traffic is forwarded to that backend. If weight is set to 0, no - // traffic should be forwarded for this entry. If unspecified, weight defaults - // to 1. - Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` -} - -func (x *TCPBackendRef) Reset() { - *x = TCPBackendRef{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmesh_v2beta1_tcp_route_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TCPBackendRef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TCPBackendRef) ProtoMessage() {} - -func (x *TCPBackendRef) ProtoReflect() protoreflect.Message { - mi := &file_pbmesh_v2beta1_tcp_route_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TCPBackendRef.ProtoReflect.Descriptor instead. -func (*TCPBackendRef) Descriptor() ([]byte, []int) { - return file_pbmesh_v2beta1_tcp_route_proto_rawDescGZIP(), []int{2} -} - -func (x *TCPBackendRef) GetBackendRef() *BackendReference { - if x != nil { - return x.BackendRef - } - return nil -} - -func (x *TCPBackendRef) GetWeight() uint32 { - if x != nil { - return x.Weight - } - return 0 -} - -var File_pbmesh_v2beta1_tcp_route_proto protoreflect.FileDescriptor - -var file_pbmesh_v2beta1_tcp_route_proto_rawDesc = []byte{ - 0x0a, 0x1e, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x74, 0x63, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x1d, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, - 0x1b, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa6, 0x01, 0x0a, 0x08, 0x54, - 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x5f, 0x72, 0x65, 0x66, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, - 0x02, 0x08, 0x03, 0x22, 0x5f, 0x0a, 0x0c, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, - 0x75, 0x6c, 0x65, 0x12, 0x4f, 0x0a, 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f, 0x72, - 0x65, 0x66, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, - 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x43, 0x50, 0x42, 0x61, 0x63, - 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x52, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, - 0x52, 0x65, 0x66, 0x73, 0x22, 0x79, 0x0a, 0x0d, 0x54, 0x43, 0x50, 0x42, 0x61, 0x63, 0x6b, 0x65, - 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x50, 0x0a, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, - 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, - 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, - 0x6e, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x62, 0x61, 0x63, - 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x42, - 0x8e, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0d, 0x54, 0x63, 0x70, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, - 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, - 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, - 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmesh_v2beta1_tcp_route_proto_rawDescOnce sync.Once - file_pbmesh_v2beta1_tcp_route_proto_rawDescData = file_pbmesh_v2beta1_tcp_route_proto_rawDesc -) - -func file_pbmesh_v2beta1_tcp_route_proto_rawDescGZIP() []byte { - file_pbmesh_v2beta1_tcp_route_proto_rawDescOnce.Do(func() { - file_pbmesh_v2beta1_tcp_route_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmesh_v2beta1_tcp_route_proto_rawDescData) - }) - return file_pbmesh_v2beta1_tcp_route_proto_rawDescData -} - -var file_pbmesh_v2beta1_tcp_route_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_pbmesh_v2beta1_tcp_route_proto_goTypes = []interface{}{ - (*TCPRoute)(nil), // 0: hashicorp.consul.mesh.v2beta1.TCPRoute - (*TCPRouteRule)(nil), // 1: hashicorp.consul.mesh.v2beta1.TCPRouteRule - (*TCPBackendRef)(nil), // 2: hashicorp.consul.mesh.v2beta1.TCPBackendRef - (*ParentReference)(nil), // 3: hashicorp.consul.mesh.v2beta1.ParentReference - (*BackendReference)(nil), // 4: hashicorp.consul.mesh.v2beta1.BackendReference -} -var file_pbmesh_v2beta1_tcp_route_proto_depIdxs = []int32{ - 3, // 0: hashicorp.consul.mesh.v2beta1.TCPRoute.parent_refs:type_name -> hashicorp.consul.mesh.v2beta1.ParentReference - 1, // 1: hashicorp.consul.mesh.v2beta1.TCPRoute.rules:type_name -> hashicorp.consul.mesh.v2beta1.TCPRouteRule - 2, // 2: hashicorp.consul.mesh.v2beta1.TCPRouteRule.backend_refs:type_name -> hashicorp.consul.mesh.v2beta1.TCPBackendRef - 4, // 3: hashicorp.consul.mesh.v2beta1.TCPBackendRef.backend_ref:type_name -> hashicorp.consul.mesh.v2beta1.BackendReference - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name -} - -func init() { file_pbmesh_v2beta1_tcp_route_proto_init() } -func file_pbmesh_v2beta1_tcp_route_proto_init() { - if File_pbmesh_v2beta1_tcp_route_proto != nil { - return - } - file_pbmesh_v2beta1_common_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmesh_v2beta1_tcp_route_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TCPRoute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_tcp_route_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TCPRouteRule); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmesh_v2beta1_tcp_route_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TCPBackendRef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmesh_v2beta1_tcp_route_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmesh_v2beta1_tcp_route_proto_goTypes, - DependencyIndexes: file_pbmesh_v2beta1_tcp_route_proto_depIdxs, - MessageInfos: file_pbmesh_v2beta1_tcp_route_proto_msgTypes, - }.Build() - File_pbmesh_v2beta1_tcp_route_proto = out.File - file_pbmesh_v2beta1_tcp_route_proto_rawDesc = nil - file_pbmesh_v2beta1_tcp_route_proto_goTypes = nil - file_pbmesh_v2beta1_tcp_route_proto_depIdxs = nil -} diff --git a/proto-public/pbmesh/v2beta1/tcp_route.proto b/proto-public/pbmesh/v2beta1/tcp_route.proto deleted file mode 100644 index d3637febf6da..000000000000 --- a/proto-public/pbmesh/v2beta1/tcp_route.proto +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -syntax = "proto3"; - -package hashicorp.consul.mesh.v2beta1; - -import "pbmesh/v2beta1/common.proto"; -import "pbresource/annotations.proto"; - -// NOTE: this should align to the GAMMA/gateway-api version, or at least be -// easily translatable. -// -// https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.TCPRoute -// -// This is a Resource type. -message TCPRoute { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - // ParentRefs references the resources (usually Services) that a Route wants - // to be attached to. - // - // It is invalid to reference an identical parent more than once. It is valid - // to reference multiple distinct sections within the same parent resource. - repeated ParentReference parent_refs = 1; - - // Rules are a list of TCP matchers and actions. - repeated TCPRouteRule rules = 2; -} - -message TCPRouteRule { - // BackendRefs defines the backend(s) where matching requests should be sent. - // If unspecified or invalid (refers to a non-existent resource or a Service - // with no endpoints), the underlying implementation MUST actively reject - // connection attempts to this backend. Connection rejections must respect - // weight; if an invalid backend is requested to have 80% of connections, - // then 80% of connections must be rejected instead. - repeated TCPBackendRef backend_refs = 1; -} - -message TCPBackendRef { - BackendReference backend_ref = 1; - - // Weight specifies the proportion of requests forwarded to the referenced - // backend. This is computed as weight/(sum of all weights in this - // BackendRefs list). For non-zero values, there may be some epsilon from the - // exact proportion defined here depending on the precision an implementation - // supports. Weight is not a percentage and the sum of weights does not need - // to equal 100. - // - // If only one backend is specified and it has a weight greater than 0, 100% - // of the traffic is forwarded to that backend. If weight is set to 0, no - // traffic should be forwarded for this entry. If unspecified, weight defaults - // to 1. - uint32 weight = 2; -} diff --git a/proto-public/pbmesh/v2beta1/tcp_route_deepcopy.gen.go b/proto-public/pbmesh/v2beta1/tcp_route_deepcopy.gen.go deleted file mode 100644 index 487209766f96..000000000000 --- a/proto-public/pbmesh/v2beta1/tcp_route_deepcopy.gen.go +++ /dev/null @@ -1,69 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package meshv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using TCPRoute within kubernetes types, where deepcopy-gen is used. -func (in *TCPRoute) DeepCopyInto(out *TCPRoute) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPRoute. Required by controller-gen. -func (in *TCPRoute) DeepCopy() *TCPRoute { - if in == nil { - return nil - } - out := new(TCPRoute) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TCPRoute. Required by controller-gen. -func (in *TCPRoute) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using TCPRouteRule within kubernetes types, where deepcopy-gen is used. -func (in *TCPRouteRule) DeepCopyInto(out *TCPRouteRule) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPRouteRule. Required by controller-gen. -func (in *TCPRouteRule) DeepCopy() *TCPRouteRule { - if in == nil { - return nil - } - out := new(TCPRouteRule) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TCPRouteRule. Required by controller-gen. -func (in *TCPRouteRule) DeepCopyInterface() interface{} { - return in.DeepCopy() -} - -// DeepCopyInto supports using TCPBackendRef within kubernetes types, where deepcopy-gen is used. -func (in *TCPBackendRef) DeepCopyInto(out *TCPBackendRef) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPBackendRef. Required by controller-gen. -func (in *TCPBackendRef) DeepCopy() *TCPBackendRef { - if in == nil { - return nil - } - out := new(TCPBackendRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TCPBackendRef. Required by controller-gen. -func (in *TCPBackendRef) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbmesh/v2beta1/tcp_route_json.gen.go b/proto-public/pbmesh/v2beta1/tcp_route_json.gen.go deleted file mode 100644 index eef880044034..000000000000 --- a/proto-public/pbmesh/v2beta1/tcp_route_json.gen.go +++ /dev/null @@ -1,44 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package meshv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for TCPRoute -func (this *TCPRoute) MarshalJSON() ([]byte, error) { - str, err := TcpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TCPRoute -func (this *TCPRoute) UnmarshalJSON(b []byte) error { - return TcpRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for TCPRouteRule -func (this *TCPRouteRule) MarshalJSON() ([]byte, error) { - str, err := TcpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TCPRouteRule -func (this *TCPRouteRule) UnmarshalJSON(b []byte) error { - return TcpRouteUnmarshaler.Unmarshal(b, this) -} - -// MarshalJSON is a custom marshaler for TCPBackendRef -func (this *TCPBackendRef) MarshalJSON() ([]byte, error) { - str, err := TcpRouteMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for TCPBackendRef -func (this *TCPBackendRef) UnmarshalJSON(b []byte) error { - return TcpRouteUnmarshaler.Unmarshal(b, this) -} - -var ( - TcpRouteMarshaler = &protojson.MarshalOptions{} - TcpRouteUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbmesh/v2beta1/xroute_addons.go b/proto-public/pbmesh/v2beta1/xroute_addons.go deleted file mode 100644 index c060aea6dd33..000000000000 --- a/proto-public/pbmesh/v2beta1/xroute_addons.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package meshv2beta1 - -// GetUnderlyingBackendRefs will collect BackendReferences from all rules and -// bundle them up in one slice, unwrapping the HTTP-specifics in the process. -// -// This implements an XRouteWithRefs interface in the internal/mesh package. -// -// NOTE: no deduplication occurs. -func (x *HTTPRoute) GetUnderlyingBackendRefs() []*BackendReference { - if x == nil { - return nil - } - - estimate := 0 - for _, rule := range x.Rules { - estimate += len(rule.BackendRefs) - } - - backendRefs := make([]*BackendReference, 0, estimate) - for _, rule := range x.Rules { - for _, backendRef := range rule.BackendRefs { - backendRefs = append(backendRefs, backendRef.BackendRef) - } - } - return backendRefs -} - -// GetUnderlyingBackendRefs will collect BackendReferences from all rules and -// bundle them up in one slice, unwrapping the GRPC-specifics in the process. -// -// This implements an XRouteWithRefs interface in the internal/mesh package. -// -// NOTE: no deduplication occurs. -func (x *GRPCRoute) GetUnderlyingBackendRefs() []*BackendReference { - if x == nil { - return nil - } - - estimate := 0 - for _, rule := range x.Rules { - estimate += len(rule.BackendRefs) - } - - backendRefs := make([]*BackendReference, 0, estimate) - for _, rule := range x.Rules { - for _, backendRef := range rule.BackendRefs { - backendRefs = append(backendRefs, backendRef.BackendRef) - } - } - return backendRefs -} - -// GetUnderlyingBackendRefs will collect BackendReferences from all rules and -// bundle them up in one slice, unwrapping the TCP-specifics in the process. -// -// This implements an XRouteWithRefs interface in the internal/mesh package. -// -// NOTE: no deduplication occurs. -func (x *TCPRoute) GetUnderlyingBackendRefs() []*BackendReference { - if x == nil { - return nil - } - - estimate := 0 - for _, rule := range x.Rules { - estimate += len(rule.BackendRefs) - } - - backendRefs := make([]*BackendReference, 0, estimate) - - for _, rule := range x.Rules { - for _, backendRef := range rule.BackendRefs { - backendRefs = append(backendRefs, backendRef.BackendRef) - } - } - return backendRefs -} - -// IsHashBased returns true if the policy is a hash-based policy such as maglev -// or ring hash. -func (p LoadBalancerPolicy) IsHashBased() bool { - switch p { - case LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV, - LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH: - return true - } - return false -} diff --git a/proto-public/pbmesh/v2beta1/xroute_addons_test.go b/proto-public/pbmesh/v2beta1/xroute_addons_test.go deleted file mode 100644 index fac04a601422..000000000000 --- a/proto-public/pbmesh/v2beta1/xroute_addons_test.go +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package meshv2beta1 - -import ( - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/proto" - - "github.com/hashicorp/consul/proto-public/pbresource" -) - -type routeWithAddons interface { - proto.Message - GetUnderlyingBackendRefs() []*BackendReference -} - -func TestXRoute_GetUnderlyingBackendRefs(t *testing.T) { - type testcase struct { - route routeWithAddons - expect []*BackendReference - } - - run := func(t *testing.T, tc testcase) { - got := tc.route.GetUnderlyingBackendRefs() - require.ElementsMatch(t, stringifyList(tc.expect), stringifyList(got)) - } - - cases := map[string]testcase{ - "http: nil": { - route: (*HTTPRoute)(nil), - }, - "grpc: nil": { - route: (*GRPCRoute)(nil), - }, - "tcp: nil": { - route: (*TCPRoute)(nil), - }, - "http: kitchen sink": { - route: &HTTPRoute{ - Rules: []*HTTPRouteRule{ - {BackendRefs: []*HTTPBackendRef{ - {BackendRef: newBackendRef("aa")}, - }}, - {BackendRefs: []*HTTPBackendRef{ - {BackendRef: newBackendRef("bb")}, - }}, - {BackendRefs: []*HTTPBackendRef{ - {BackendRef: newBackendRef("cc")}, - {BackendRef: newBackendRef("dd")}, - }}, - {BackendRefs: []*HTTPBackendRef{ - {BackendRef: newBackendRef("ee")}, - {BackendRef: newBackendRef("ff")}, - }}, - }, - }, - expect: []*BackendReference{ - newBackendRef("aa"), - newBackendRef("bb"), - newBackendRef("cc"), - newBackendRef("dd"), - newBackendRef("ee"), - newBackendRef("ff"), - }, - }, - "grpc: kitchen sink": { - route: &GRPCRoute{ - Rules: []*GRPCRouteRule{ - {BackendRefs: []*GRPCBackendRef{ - {BackendRef: newBackendRef("aa")}, - }}, - {BackendRefs: []*GRPCBackendRef{ - {BackendRef: newBackendRef("bb")}, - }}, - {BackendRefs: []*GRPCBackendRef{ - {BackendRef: newBackendRef("cc")}, - {BackendRef: newBackendRef("dd")}, - }}, - {BackendRefs: []*GRPCBackendRef{ - {BackendRef: newBackendRef("ee")}, - {BackendRef: newBackendRef("ff")}, - }}, - }, - }, - expect: []*BackendReference{ - newBackendRef("aa"), - newBackendRef("bb"), - newBackendRef("cc"), - newBackendRef("dd"), - newBackendRef("ee"), - newBackendRef("ff"), - }, - }, - "tcp: kitchen sink": { - route: &TCPRoute{ - Rules: []*TCPRouteRule{ - {BackendRefs: []*TCPBackendRef{ - {BackendRef: newBackendRef("aa")}, - }}, - {BackendRefs: []*TCPBackendRef{ - {BackendRef: newBackendRef("bb")}, - }}, - {BackendRefs: []*TCPBackendRef{ - {BackendRef: newBackendRef("cc")}, - {BackendRef: newBackendRef("dd")}, - }}, - {BackendRefs: []*TCPBackendRef{ - {BackendRef: newBackendRef("ee")}, - {BackendRef: newBackendRef("ff")}, - }}, - }, - }, - expect: []*BackendReference{ - newBackendRef("aa"), - newBackendRef("bb"), - newBackendRef("cc"), - newBackendRef("dd"), - newBackendRef("ee"), - newBackendRef("ff"), - }, - }, - } - - for name, tc := range cases { - t.Run(name, func(t *testing.T) { - run(t, tc) - }) - } -} - -func protoToString[V proto.Message](pb V) string { - m := protojson.MarshalOptions{ - Indent: " ", - } - gotJSON, err := m.Marshal(pb) - if err != nil { - return "" - } - return string(gotJSON) -} - -func newRouteRef(name string) *pbresource.Reference { - return &pbresource.Reference{ - Type: &pbresource.Type{ - Group: "fake", - GroupVersion: "v1alpha1", - Kind: "fake", - }, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: name, - } -} - -func newBackendRef(name string) *BackendReference { - return &BackendReference{ - Ref: newRouteRef(name), - } -} - -func stringifyList[V proto.Message](list []V) []string { - out := make([]string, 0, len(list)) - for _, item := range list { - out = append(out, protoToString(item)) - } - return out -} diff --git a/proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.binary.go b/proto-public/pbmulticluster/v2/computed_exported_services.pb.binary.go similarity index 78% rename from proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.binary.go rename to proto-public/pbmulticluster/v2/computed_exported_services.pb.binary.go index f5b389089f42..ab72f9be12a7 100644 --- a/proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.binary.go +++ b/proto-public/pbmulticluster/v2/computed_exported_services.pb.binary.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmulticluster/v2beta1/computed_exported_services.proto +// source: pbmulticluster/v2/computed_exported_services.proto -package multiclusterv2beta1 +package multiclusterv2 import ( "google.golang.org/protobuf/proto" @@ -28,11 +28,11 @@ func (msg *ComputedExportedService) UnmarshalBinary(b []byte) error { } // MarshalBinary implements encoding.BinaryMarshaler -func (msg *ComputedExportedServicesConsumer) MarshalBinary() ([]byte, error) { +func (msg *ComputedExportedServiceConsumer) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) } // UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ComputedExportedServicesConsumer) UnmarshalBinary(b []byte) error { +func (msg *ComputedExportedServiceConsumer) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } diff --git a/proto-public/pbmulticluster/v2/computed_exported_services.pb.go b/proto-public/pbmulticluster/v2/computed_exported_services.pb.go new file mode 100644 index 000000000000..91319c44c2c5 --- /dev/null +++ b/proto-public/pbmulticluster/v2/computed_exported_services.pb.go @@ -0,0 +1,367 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc (unknown) +// source: pbmulticluster/v2/computed_exported_services.proto + +package multiclusterv2 + +import ( + pbresource "github.com/hashicorp/consul/proto-public/pbresource" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ComputedExportedServices struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Services []*ComputedExportedService `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` +} + +func (x *ComputedExportedServices) Reset() { + *x = ComputedExportedServices{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmulticluster_v2_computed_exported_services_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComputedExportedServices) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComputedExportedServices) ProtoMessage() {} + +func (x *ComputedExportedServices) ProtoReflect() protoreflect.Message { + mi := &file_pbmulticluster_v2_computed_exported_services_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComputedExportedServices.ProtoReflect.Descriptor instead. +func (*ComputedExportedServices) Descriptor() ([]byte, []int) { + return file_pbmulticluster_v2_computed_exported_services_proto_rawDescGZIP(), []int{0} +} + +func (x *ComputedExportedServices) GetServices() []*ComputedExportedService { + if x != nil { + return x.Services + } + return nil +} + +type ComputedExportedService struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TargetRef *pbresource.Reference `protobuf:"bytes,1,opt,name=target_ref,json=targetRef,proto3" json:"target_ref,omitempty"` + Consumers []*ComputedExportedServiceConsumer `protobuf:"bytes,2,rep,name=consumers,proto3" json:"consumers,omitempty"` +} + +func (x *ComputedExportedService) Reset() { + *x = ComputedExportedService{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmulticluster_v2_computed_exported_services_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComputedExportedService) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComputedExportedService) ProtoMessage() {} + +func (x *ComputedExportedService) ProtoReflect() protoreflect.Message { + mi := &file_pbmulticluster_v2_computed_exported_services_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComputedExportedService.ProtoReflect.Descriptor instead. +func (*ComputedExportedService) Descriptor() ([]byte, []int) { + return file_pbmulticluster_v2_computed_exported_services_proto_rawDescGZIP(), []int{1} +} + +func (x *ComputedExportedService) GetTargetRef() *pbresource.Reference { + if x != nil { + return x.TargetRef + } + return nil +} + +func (x *ComputedExportedService) GetConsumers() []*ComputedExportedServiceConsumer { + if x != nil { + return x.Consumers + } + return nil +} + +type ComputedExportedServiceConsumer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // no sameness group + // + // Types that are assignable to Tenancy: + // + // *ComputedExportedServiceConsumer_Peer + // *ComputedExportedServiceConsumer_Partition + Tenancy isComputedExportedServiceConsumer_Tenancy `protobuf_oneof:"tenancy"` +} + +func (x *ComputedExportedServiceConsumer) Reset() { + *x = ComputedExportedServiceConsumer{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmulticluster_v2_computed_exported_services_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComputedExportedServiceConsumer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComputedExportedServiceConsumer) ProtoMessage() {} + +func (x *ComputedExportedServiceConsumer) ProtoReflect() protoreflect.Message { + mi := &file_pbmulticluster_v2_computed_exported_services_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComputedExportedServiceConsumer.ProtoReflect.Descriptor instead. +func (*ComputedExportedServiceConsumer) Descriptor() ([]byte, []int) { + return file_pbmulticluster_v2_computed_exported_services_proto_rawDescGZIP(), []int{2} +} + +func (m *ComputedExportedServiceConsumer) GetTenancy() isComputedExportedServiceConsumer_Tenancy { + if m != nil { + return m.Tenancy + } + return nil +} + +func (x *ComputedExportedServiceConsumer) GetPeer() string { + if x, ok := x.GetTenancy().(*ComputedExportedServiceConsumer_Peer); ok { + return x.Peer + } + return "" +} + +func (x *ComputedExportedServiceConsumer) GetPartition() string { + if x, ok := x.GetTenancy().(*ComputedExportedServiceConsumer_Partition); ok { + return x.Partition + } + return "" +} + +type isComputedExportedServiceConsumer_Tenancy interface { + isComputedExportedServiceConsumer_Tenancy() +} + +type ComputedExportedServiceConsumer_Peer struct { + Peer string `protobuf:"bytes,3,opt,name=peer,proto3,oneof"` +} + +type ComputedExportedServiceConsumer_Partition struct { + Partition string `protobuf:"bytes,4,opt,name=partition,proto3,oneof"` +} + +func (*ComputedExportedServiceConsumer_Peer) isComputedExportedServiceConsumer_Tenancy() {} + +func (*ComputedExportedServiceConsumer_Partition) isComputedExportedServiceConsumer_Tenancy() {} + +var File_pbmulticluster_v2_computed_exported_services_proto protoreflect.FileDescriptor + +var file_pbmulticluster_v2_computed_exported_services_proto_rawDesc = []byte{ + 0x0a, 0x32, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0x79, 0x0a, 0x18, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x55, 0x0a, 0x08, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, + 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, + 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x02, 0x22, 0xbf, 0x01, 0x0a, 0x17, 0x43, + 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x52, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x66, 0x12, 0x5f, 0x0a, 0x09, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, + 0x32, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, + 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x22, 0x62, 0x0a, 0x1f, + 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x12, + 0x14, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x04, 0x70, 0x65, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x09, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, + 0x42, 0xb3, 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x42, 0x1d, 0x43, 0x6f, 0x6d, 0x70, 0x75, + 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x3b, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x20, 0x48, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0xca, 0x02, + 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, + 0x32, 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pbmulticluster_v2_computed_exported_services_proto_rawDescOnce sync.Once + file_pbmulticluster_v2_computed_exported_services_proto_rawDescData = file_pbmulticluster_v2_computed_exported_services_proto_rawDesc +) + +func file_pbmulticluster_v2_computed_exported_services_proto_rawDescGZIP() []byte { + file_pbmulticluster_v2_computed_exported_services_proto_rawDescOnce.Do(func() { + file_pbmulticluster_v2_computed_exported_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2_computed_exported_services_proto_rawDescData) + }) + return file_pbmulticluster_v2_computed_exported_services_proto_rawDescData +} + +var file_pbmulticluster_v2_computed_exported_services_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_pbmulticluster_v2_computed_exported_services_proto_goTypes = []interface{}{ + (*ComputedExportedServices)(nil), // 0: hashicorp.consul.multicluster.v2.ComputedExportedServices + (*ComputedExportedService)(nil), // 1: hashicorp.consul.multicluster.v2.ComputedExportedService + (*ComputedExportedServiceConsumer)(nil), // 2: hashicorp.consul.multicluster.v2.ComputedExportedServiceConsumer + (*pbresource.Reference)(nil), // 3: hashicorp.consul.resource.Reference +} +var file_pbmulticluster_v2_computed_exported_services_proto_depIdxs = []int32{ + 1, // 0: hashicorp.consul.multicluster.v2.ComputedExportedServices.services:type_name -> hashicorp.consul.multicluster.v2.ComputedExportedService + 3, // 1: hashicorp.consul.multicluster.v2.ComputedExportedService.target_ref:type_name -> hashicorp.consul.resource.Reference + 2, // 2: hashicorp.consul.multicluster.v2.ComputedExportedService.consumers:type_name -> hashicorp.consul.multicluster.v2.ComputedExportedServiceConsumer + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_pbmulticluster_v2_computed_exported_services_proto_init() } +func file_pbmulticluster_v2_computed_exported_services_proto_init() { + if File_pbmulticluster_v2_computed_exported_services_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pbmulticluster_v2_computed_exported_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComputedExportedServices); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbmulticluster_v2_computed_exported_services_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComputedExportedService); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbmulticluster_v2_computed_exported_services_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComputedExportedServiceConsumer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_pbmulticluster_v2_computed_exported_services_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*ComputedExportedServiceConsumer_Peer)(nil), + (*ComputedExportedServiceConsumer_Partition)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pbmulticluster_v2_computed_exported_services_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbmulticluster_v2_computed_exported_services_proto_goTypes, + DependencyIndexes: file_pbmulticluster_v2_computed_exported_services_proto_depIdxs, + MessageInfos: file_pbmulticluster_v2_computed_exported_services_proto_msgTypes, + }.Build() + File_pbmulticluster_v2_computed_exported_services_proto = out.File + file_pbmulticluster_v2_computed_exported_services_proto_rawDesc = nil + file_pbmulticluster_v2_computed_exported_services_proto_goTypes = nil + file_pbmulticluster_v2_computed_exported_services_proto_depIdxs = nil +} diff --git a/proto-public/pbmulticluster/v2/computed_exported_services.proto b/proto-public/pbmulticluster/v2/computed_exported_services.proto new file mode 100644 index 000000000000..52daf8fe21ac --- /dev/null +++ b/proto-public/pbmulticluster/v2/computed_exported_services.proto @@ -0,0 +1,28 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +syntax = "proto3"; + +package hashicorp.consul.multicluster.v2; + +import "pbresource/annotations.proto"; +import "pbresource/resource.proto"; + +message ComputedExportedServices { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_PARTITION}; + + repeated ComputedExportedService services = 1; +} + +message ComputedExportedService { + hashicorp.consul.resource.Reference target_ref = 1; + repeated ComputedExportedServiceConsumer consumers = 2; +} + +message ComputedExportedServiceConsumer { + // no sameness group + oneof tenancy { + string peer = 3; + string partition = 4; + } +} diff --git a/proto-public/pbmulticluster/v2beta1/computed_exported_services_deepcopy.gen.go b/proto-public/pbmulticluster/v2/computed_exported_services_deepcopy.gen.go similarity index 75% rename from proto-public/pbmulticluster/v2beta1/computed_exported_services_deepcopy.gen.go rename to proto-public/pbmulticluster/v2/computed_exported_services_deepcopy.gen.go index b50f35a20bd9..45b94555b848 100644 --- a/proto-public/pbmulticluster/v2beta1/computed_exported_services_deepcopy.gen.go +++ b/proto-public/pbmulticluster/v2/computed_exported_services_deepcopy.gen.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package multiclusterv2beta1 +package multiclusterv2 import ( proto "google.golang.org/protobuf/proto" @@ -47,23 +47,23 @@ func (in *ComputedExportedService) DeepCopyInterface() interface{} { return in.DeepCopy() } -// DeepCopyInto supports using ComputedExportedServicesConsumer within kubernetes types, where deepcopy-gen is used. -func (in *ComputedExportedServicesConsumer) DeepCopyInto(out *ComputedExportedServicesConsumer) { +// DeepCopyInto supports using ComputedExportedServiceConsumer within kubernetes types, where deepcopy-gen is used. +func (in *ComputedExportedServiceConsumer) DeepCopyInto(out *ComputedExportedServiceConsumer) { proto.Reset(out) proto.Merge(out, proto.Clone(in)) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedExportedServicesConsumer. Required by controller-gen. -func (in *ComputedExportedServicesConsumer) DeepCopy() *ComputedExportedServicesConsumer { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComputedExportedServiceConsumer. Required by controller-gen. +func (in *ComputedExportedServiceConsumer) DeepCopy() *ComputedExportedServiceConsumer { if in == nil { return nil } - out := new(ComputedExportedServicesConsumer) + out := new(ComputedExportedServiceConsumer) in.DeepCopyInto(out) return out } -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedExportedServicesConsumer. Required by controller-gen. -func (in *ComputedExportedServicesConsumer) DeepCopyInterface() interface{} { +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ComputedExportedServiceConsumer. Required by controller-gen. +func (in *ComputedExportedServiceConsumer) DeepCopyInterface() interface{} { return in.DeepCopy() } diff --git a/proto-public/pbmulticluster/v2beta1/computed_exported_services_json.gen.go b/proto-public/pbmulticluster/v2/computed_exported_services_json.gen.go similarity index 87% rename from proto-public/pbmulticluster/v2beta1/computed_exported_services_json.gen.go rename to proto-public/pbmulticluster/v2/computed_exported_services_json.gen.go index 709a7e6ef6b2..603244efd470 100644 --- a/proto-public/pbmulticluster/v2beta1/computed_exported_services_json.gen.go +++ b/proto-public/pbmulticluster/v2/computed_exported_services_json.gen.go @@ -1,5 +1,5 @@ // Code generated by protoc-json-shim. DO NOT EDIT. -package multiclusterv2beta1 +package multiclusterv2 import ( protojson "google.golang.org/protobuf/encoding/protojson" @@ -27,14 +27,14 @@ func (this *ComputedExportedService) UnmarshalJSON(b []byte) error { return ComputedExportedServicesUnmarshaler.Unmarshal(b, this) } -// MarshalJSON is a custom marshaler for ComputedExportedServicesConsumer -func (this *ComputedExportedServicesConsumer) MarshalJSON() ([]byte, error) { +// MarshalJSON is a custom marshaler for ComputedExportedServiceConsumer +func (this *ComputedExportedServiceConsumer) MarshalJSON() ([]byte, error) { str, err := ComputedExportedServicesMarshaler.Marshal(this) return []byte(str), err } -// UnmarshalJSON is a custom unmarshaler for ComputedExportedServicesConsumer -func (this *ComputedExportedServicesConsumer) UnmarshalJSON(b []byte) error { +// UnmarshalJSON is a custom unmarshaler for ComputedExportedServiceConsumer +func (this *ComputedExportedServiceConsumer) UnmarshalJSON(b []byte) error { return ComputedExportedServicesUnmarshaler.Unmarshal(b, this) } diff --git a/proto-public/pbmulticluster/v2beta1/exported_services.pb.binary.go b/proto-public/pbmulticluster/v2/exported_services.pb.binary.go similarity index 82% rename from proto-public/pbmulticluster/v2beta1/exported_services.pb.binary.go rename to proto-public/pbmulticluster/v2/exported_services.pb.binary.go index 153029480412..aa087b1a8d0c 100644 --- a/proto-public/pbmulticluster/v2beta1/exported_services.pb.binary.go +++ b/proto-public/pbmulticluster/v2/exported_services.pb.binary.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmulticluster/v2beta1/exported_services.proto +// source: pbmulticluster/v2/exported_services.proto -package multiclusterv2beta1 +package multiclusterv2 import ( "google.golang.org/protobuf/proto" diff --git a/proto-public/pbmulticluster/v2/exported_services.pb.go b/proto-public/pbmulticluster/v2/exported_services.pb.go new file mode 100644 index 000000000000..796534e2c273 --- /dev/null +++ b/proto-public/pbmulticluster/v2/exported_services.pb.go @@ -0,0 +1,190 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc (unknown) +// source: pbmulticluster/v2/exported_services.proto + +package multiclusterv2 + +import ( + _ "github.com/hashicorp/consul/proto-public/pbresource" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ExportedServices struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Services []string `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` + Consumers []*ExportedServicesConsumer `protobuf:"bytes,2,rep,name=consumers,proto3" json:"consumers,omitempty"` +} + +func (x *ExportedServices) Reset() { + *x = ExportedServices{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmulticluster_v2_exported_services_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExportedServices) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExportedServices) ProtoMessage() {} + +func (x *ExportedServices) ProtoReflect() protoreflect.Message { + mi := &file_pbmulticluster_v2_exported_services_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExportedServices.ProtoReflect.Descriptor instead. +func (*ExportedServices) Descriptor() ([]byte, []int) { + return file_pbmulticluster_v2_exported_services_proto_rawDescGZIP(), []int{0} +} + +func (x *ExportedServices) GetServices() []string { + if x != nil { + return x.Services + } + return nil +} + +func (x *ExportedServices) GetConsumers() []*ExportedServicesConsumer { + if x != nil { + return x.Consumers + } + return nil +} + +var File_pbmulticluster_v2_exported_services_proto protoreflect.FileDescriptor + +var file_pbmulticluster_v2_exported_services_proto_rawDesc = []byte{ + 0x0a, 0x29, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x2f, 0x76, 0x32, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, + 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x1a, 0x32, 0x70, + 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, + 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0x90, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x12, 0x58, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, + 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, + 0x08, 0x03, 0x42, 0xab, 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, + 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x42, 0x15, 0x45, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, + 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, + 0x3b, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, 0x32, 0xa2, + 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, + 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x2c, 0x48, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, + 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x32, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pbmulticluster_v2_exported_services_proto_rawDescOnce sync.Once + file_pbmulticluster_v2_exported_services_proto_rawDescData = file_pbmulticluster_v2_exported_services_proto_rawDesc +) + +func file_pbmulticluster_v2_exported_services_proto_rawDescGZIP() []byte { + file_pbmulticluster_v2_exported_services_proto_rawDescOnce.Do(func() { + file_pbmulticluster_v2_exported_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2_exported_services_proto_rawDescData) + }) + return file_pbmulticluster_v2_exported_services_proto_rawDescData +} + +var file_pbmulticluster_v2_exported_services_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_pbmulticluster_v2_exported_services_proto_goTypes = []interface{}{ + (*ExportedServices)(nil), // 0: hashicorp.consul.multicluster.v2.ExportedServices + (*ExportedServicesConsumer)(nil), // 1: hashicorp.consul.multicluster.v2.ExportedServicesConsumer +} +var file_pbmulticluster_v2_exported_services_proto_depIdxs = []int32{ + 1, // 0: hashicorp.consul.multicluster.v2.ExportedServices.consumers:type_name -> hashicorp.consul.multicluster.v2.ExportedServicesConsumer + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_pbmulticluster_v2_exported_services_proto_init() } +func file_pbmulticluster_v2_exported_services_proto_init() { + if File_pbmulticluster_v2_exported_services_proto != nil { + return + } + file_pbmulticluster_v2_exported_services_consumer_proto_init() + if !protoimpl.UnsafeEnabled { + file_pbmulticluster_v2_exported_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExportedServices); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pbmulticluster_v2_exported_services_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbmulticluster_v2_exported_services_proto_goTypes, + DependencyIndexes: file_pbmulticluster_v2_exported_services_proto_depIdxs, + MessageInfos: file_pbmulticluster_v2_exported_services_proto_msgTypes, + }.Build() + File_pbmulticluster_v2_exported_services_proto = out.File + file_pbmulticluster_v2_exported_services_proto_rawDesc = nil + file_pbmulticluster_v2_exported_services_proto_goTypes = nil + file_pbmulticluster_v2_exported_services_proto_depIdxs = nil +} diff --git a/proto-public/pbmulticluster/v2/exported_services.proto b/proto-public/pbmulticluster/v2/exported_services.proto new file mode 100644 index 000000000000..792dafd9a962 --- /dev/null +++ b/proto-public/pbmulticluster/v2/exported_services.proto @@ -0,0 +1,16 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +syntax = "proto3"; + +package hashicorp.consul.multicluster.v2; + +import "pbmulticluster/v2/exported_services_consumer.proto"; +import "pbresource/annotations.proto"; + +message ExportedServices { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; + + repeated string services = 1; + repeated ExportedServicesConsumer consumers = 2; +} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.binary.go b/proto-public/pbmulticluster/v2/exported_services_consumer.pb.binary.go similarity index 81% rename from proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.binary.go rename to proto-public/pbmulticluster/v2/exported_services_consumer.pb.binary.go index 5f8eecd75158..4cb1267eacdb 100644 --- a/proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.binary.go +++ b/proto-public/pbmulticluster/v2/exported_services_consumer.pb.binary.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmulticluster/v2beta1/exported_services_consumer.proto +// source: pbmulticluster/v2/exported_services_consumer.proto -package multiclusterv2beta1 +package multiclusterv2 import ( "google.golang.org/protobuf/proto" diff --git a/proto-public/pbmulticluster/v2/exported_services_consumer.pb.go b/proto-public/pbmulticluster/v2/exported_services_consumer.pb.go new file mode 100644 index 000000000000..83817a0101bc --- /dev/null +++ b/proto-public/pbmulticluster/v2/exported_services_consumer.pb.go @@ -0,0 +1,230 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc (unknown) +// source: pbmulticluster/v2/exported_services_consumer.proto + +package multiclusterv2 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// +kubebuilder:validation:Type=object +// +kubebuilder:validation:Schemaless +// +kubebuilder:pruning:PreserveUnknownFields +type ExportedServicesConsumer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to ConsumerTenancy: + // + // *ExportedServicesConsumer_Peer + // *ExportedServicesConsumer_Partition + // *ExportedServicesConsumer_SamenessGroup + ConsumerTenancy isExportedServicesConsumer_ConsumerTenancy `protobuf_oneof:"consumer_tenancy"` +} + +func (x *ExportedServicesConsumer) Reset() { + *x = ExportedServicesConsumer{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmulticluster_v2_exported_services_consumer_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExportedServicesConsumer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExportedServicesConsumer) ProtoMessage() {} + +func (x *ExportedServicesConsumer) ProtoReflect() protoreflect.Message { + mi := &file_pbmulticluster_v2_exported_services_consumer_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExportedServicesConsumer.ProtoReflect.Descriptor instead. +func (*ExportedServicesConsumer) Descriptor() ([]byte, []int) { + return file_pbmulticluster_v2_exported_services_consumer_proto_rawDescGZIP(), []int{0} +} + +func (m *ExportedServicesConsumer) GetConsumerTenancy() isExportedServicesConsumer_ConsumerTenancy { + if m != nil { + return m.ConsumerTenancy + } + return nil +} + +func (x *ExportedServicesConsumer) GetPeer() string { + if x, ok := x.GetConsumerTenancy().(*ExportedServicesConsumer_Peer); ok { + return x.Peer + } + return "" +} + +func (x *ExportedServicesConsumer) GetPartition() string { + if x, ok := x.GetConsumerTenancy().(*ExportedServicesConsumer_Partition); ok { + return x.Partition + } + return "" +} + +func (x *ExportedServicesConsumer) GetSamenessGroup() string { + if x, ok := x.GetConsumerTenancy().(*ExportedServicesConsumer_SamenessGroup); ok { + return x.SamenessGroup + } + return "" +} + +type isExportedServicesConsumer_ConsumerTenancy interface { + isExportedServicesConsumer_ConsumerTenancy() +} + +type ExportedServicesConsumer_Peer struct { + Peer string `protobuf:"bytes,1,opt,name=peer,proto3,oneof"` +} + +type ExportedServicesConsumer_Partition struct { + Partition string `protobuf:"bytes,2,opt,name=partition,proto3,oneof"` +} + +type ExportedServicesConsumer_SamenessGroup struct { + SamenessGroup string `protobuf:"bytes,3,opt,name=sameness_group,json=samenessGroup,proto3,oneof"` +} + +func (*ExportedServicesConsumer_Peer) isExportedServicesConsumer_ConsumerTenancy() {} + +func (*ExportedServicesConsumer_Partition) isExportedServicesConsumer_ConsumerTenancy() {} + +func (*ExportedServicesConsumer_SamenessGroup) isExportedServicesConsumer_ConsumerTenancy() {} + +var File_pbmulticluster_v2_exported_services_consumer_proto protoreflect.FileDescriptor + +var file_pbmulticluster_v2_exported_services_consumer_proto_rawDesc = []byte{ + 0x0a, 0x32, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x2f, 0x76, 0x32, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x22, 0x8d, 0x01, 0x0a, 0x18, 0x45, 0x78, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6d, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x09, 0x70, 0x61, 0x72, + 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, + 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0e, 0x73, 0x61, 0x6d, + 0x65, 0x6e, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x42, 0x12, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x74, + 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x42, 0xb3, 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x42, + 0x1d, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x75, 0x6c, + 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x3b, 0x6d, 0x75, 0x6c, + 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x48, 0x43, + 0x4d, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x75, 0x6c, 0x74, + 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pbmulticluster_v2_exported_services_consumer_proto_rawDescOnce sync.Once + file_pbmulticluster_v2_exported_services_consumer_proto_rawDescData = file_pbmulticluster_v2_exported_services_consumer_proto_rawDesc +) + +func file_pbmulticluster_v2_exported_services_consumer_proto_rawDescGZIP() []byte { + file_pbmulticluster_v2_exported_services_consumer_proto_rawDescOnce.Do(func() { + file_pbmulticluster_v2_exported_services_consumer_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2_exported_services_consumer_proto_rawDescData) + }) + return file_pbmulticluster_v2_exported_services_consumer_proto_rawDescData +} + +var file_pbmulticluster_v2_exported_services_consumer_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_pbmulticluster_v2_exported_services_consumer_proto_goTypes = []interface{}{ + (*ExportedServicesConsumer)(nil), // 0: hashicorp.consul.multicluster.v2.ExportedServicesConsumer +} +var file_pbmulticluster_v2_exported_services_consumer_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_pbmulticluster_v2_exported_services_consumer_proto_init() } +func file_pbmulticluster_v2_exported_services_consumer_proto_init() { + if File_pbmulticluster_v2_exported_services_consumer_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pbmulticluster_v2_exported_services_consumer_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExportedServicesConsumer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_pbmulticluster_v2_exported_services_consumer_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*ExportedServicesConsumer_Peer)(nil), + (*ExportedServicesConsumer_Partition)(nil), + (*ExportedServicesConsumer_SamenessGroup)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pbmulticluster_v2_exported_services_consumer_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbmulticluster_v2_exported_services_consumer_proto_goTypes, + DependencyIndexes: file_pbmulticluster_v2_exported_services_consumer_proto_depIdxs, + MessageInfos: file_pbmulticluster_v2_exported_services_consumer_proto_msgTypes, + }.Build() + File_pbmulticluster_v2_exported_services_consumer_proto = out.File + file_pbmulticluster_v2_exported_services_consumer_proto_rawDesc = nil + file_pbmulticluster_v2_exported_services_consumer_proto_goTypes = nil + file_pbmulticluster_v2_exported_services_consumer_proto_depIdxs = nil +} diff --git a/proto-public/pbmulticluster/v2/exported_services_consumer.proto b/proto-public/pbmulticluster/v2/exported_services_consumer.proto new file mode 100644 index 000000000000..e0ff2c2936f9 --- /dev/null +++ b/proto-public/pbmulticluster/v2/exported_services_consumer.proto @@ -0,0 +1,17 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +syntax = "proto3"; + +package hashicorp.consul.multicluster.v2; + +// +kubebuilder:validation:Type=object +// +kubebuilder:validation:Schemaless +// +kubebuilder:pruning:PreserveUnknownFields +message ExportedServicesConsumer { + oneof consumer_tenancy { + string peer = 1; + string partition = 2; + string sameness_group = 3; + } +} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_consumer_deepcopy.gen.go b/proto-public/pbmulticluster/v2/exported_services_consumer_deepcopy.gen.go similarity index 97% rename from proto-public/pbmulticluster/v2beta1/exported_services_consumer_deepcopy.gen.go rename to proto-public/pbmulticluster/v2/exported_services_consumer_deepcopy.gen.go index 847fe0ec3e31..46433328704a 100644 --- a/proto-public/pbmulticluster/v2beta1/exported_services_consumer_deepcopy.gen.go +++ b/proto-public/pbmulticluster/v2/exported_services_consumer_deepcopy.gen.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package multiclusterv2beta1 +package multiclusterv2 import ( proto "google.golang.org/protobuf/proto" diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_consumer_json.gen.go b/proto-public/pbmulticluster/v2/exported_services_consumer_json.gen.go similarity index 96% rename from proto-public/pbmulticluster/v2beta1/exported_services_consumer_json.gen.go rename to proto-public/pbmulticluster/v2/exported_services_consumer_json.gen.go index 3f43f69932a1..9f980d5a9f2f 100644 --- a/proto-public/pbmulticluster/v2beta1/exported_services_consumer_json.gen.go +++ b/proto-public/pbmulticluster/v2/exported_services_consumer_json.gen.go @@ -1,5 +1,5 @@ // Code generated by protoc-json-shim. DO NOT EDIT. -package multiclusterv2beta1 +package multiclusterv2 import ( protojson "google.golang.org/protobuf/encoding/protojson" diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_deepcopy.gen.go b/proto-public/pbmulticluster/v2/exported_services_deepcopy.gen.go similarity index 96% rename from proto-public/pbmulticluster/v2beta1/exported_services_deepcopy.gen.go rename to proto-public/pbmulticluster/v2/exported_services_deepcopy.gen.go index f5897233ef8b..f8b6fb210f65 100644 --- a/proto-public/pbmulticluster/v2beta1/exported_services_deepcopy.gen.go +++ b/proto-public/pbmulticluster/v2/exported_services_deepcopy.gen.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package multiclusterv2beta1 +package multiclusterv2 import ( proto "google.golang.org/protobuf/proto" diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_json.gen.go b/proto-public/pbmulticluster/v2/exported_services_json.gen.go similarity index 95% rename from proto-public/pbmulticluster/v2beta1/exported_services_json.gen.go rename to proto-public/pbmulticluster/v2/exported_services_json.gen.go index 40a7cdc38b9b..a49f8d0b90e6 100644 --- a/proto-public/pbmulticluster/v2beta1/exported_services_json.gen.go +++ b/proto-public/pbmulticluster/v2/exported_services_json.gen.go @@ -1,5 +1,5 @@ // Code generated by protoc-json-shim. DO NOT EDIT. -package multiclusterv2beta1 +package multiclusterv2 import ( protojson "google.golang.org/protobuf/encoding/protojson" diff --git a/proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.binary.go b/proto-public/pbmulticluster/v2/namespace_exported_services.pb.binary.go similarity index 81% rename from proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.binary.go rename to proto-public/pbmulticluster/v2/namespace_exported_services.pb.binary.go index eb000381077b..7414e79daf28 100644 --- a/proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.binary.go +++ b/proto-public/pbmulticluster/v2/namespace_exported_services.pb.binary.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmulticluster/v2beta1/namespace_exported_services.proto +// source: pbmulticluster/v2/namespace_exported_services.proto -package multiclusterv2beta1 +package multiclusterv2 import ( "google.golang.org/protobuf/proto" diff --git a/proto-public/pbmulticluster/v2/namespace_exported_services.pb.go b/proto-public/pbmulticluster/v2/namespace_exported_services.pb.go new file mode 100644 index 000000000000..d156c7d70095 --- /dev/null +++ b/proto-public/pbmulticluster/v2/namespace_exported_services.pb.go @@ -0,0 +1,182 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc (unknown) +// source: pbmulticluster/v2/namespace_exported_services.proto + +package multiclusterv2 + +import ( + _ "github.com/hashicorp/consul/proto-public/pbresource" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type NamespaceExportedServices struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Consumers []*ExportedServicesConsumer `protobuf:"bytes,1,rep,name=consumers,proto3" json:"consumers,omitempty"` +} + +func (x *NamespaceExportedServices) Reset() { + *x = NamespaceExportedServices{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmulticluster_v2_namespace_exported_services_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NamespaceExportedServices) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NamespaceExportedServices) ProtoMessage() {} + +func (x *NamespaceExportedServices) ProtoReflect() protoreflect.Message { + mi := &file_pbmulticluster_v2_namespace_exported_services_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NamespaceExportedServices.ProtoReflect.Descriptor instead. +func (*NamespaceExportedServices) Descriptor() ([]byte, []int) { + return file_pbmulticluster_v2_namespace_exported_services_proto_rawDescGZIP(), []int{0} +} + +func (x *NamespaceExportedServices) GetConsumers() []*ExportedServicesConsumer { + if x != nil { + return x.Consumers + } + return nil +} + +var File_pbmulticluster_v2_namespace_exported_services_proto protoreflect.FileDescriptor + +var file_pbmulticluster_v2_namespace_exported_services_proto_rawDesc = []byte{ + 0x0a, 0x33, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x2f, 0x76, 0x32, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x65, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x1a, 0x32, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x7d, 0x0a, 0x19, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, + 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, + 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, + 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x42, 0xb4, 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, + 0x32, 0x42, 0x1e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x78, 0x70, 0x6f, + 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, + 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x3b, + 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, 0x32, 0xa2, 0x02, + 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, + 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x32, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pbmulticluster_v2_namespace_exported_services_proto_rawDescOnce sync.Once + file_pbmulticluster_v2_namespace_exported_services_proto_rawDescData = file_pbmulticluster_v2_namespace_exported_services_proto_rawDesc +) + +func file_pbmulticluster_v2_namespace_exported_services_proto_rawDescGZIP() []byte { + file_pbmulticluster_v2_namespace_exported_services_proto_rawDescOnce.Do(func() { + file_pbmulticluster_v2_namespace_exported_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2_namespace_exported_services_proto_rawDescData) + }) + return file_pbmulticluster_v2_namespace_exported_services_proto_rawDescData +} + +var file_pbmulticluster_v2_namespace_exported_services_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_pbmulticluster_v2_namespace_exported_services_proto_goTypes = []interface{}{ + (*NamespaceExportedServices)(nil), // 0: hashicorp.consul.multicluster.v2.NamespaceExportedServices + (*ExportedServicesConsumer)(nil), // 1: hashicorp.consul.multicluster.v2.ExportedServicesConsumer +} +var file_pbmulticluster_v2_namespace_exported_services_proto_depIdxs = []int32{ + 1, // 0: hashicorp.consul.multicluster.v2.NamespaceExportedServices.consumers:type_name -> hashicorp.consul.multicluster.v2.ExportedServicesConsumer + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_pbmulticluster_v2_namespace_exported_services_proto_init() } +func file_pbmulticluster_v2_namespace_exported_services_proto_init() { + if File_pbmulticluster_v2_namespace_exported_services_proto != nil { + return + } + file_pbmulticluster_v2_exported_services_consumer_proto_init() + if !protoimpl.UnsafeEnabled { + file_pbmulticluster_v2_namespace_exported_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NamespaceExportedServices); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pbmulticluster_v2_namespace_exported_services_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbmulticluster_v2_namespace_exported_services_proto_goTypes, + DependencyIndexes: file_pbmulticluster_v2_namespace_exported_services_proto_depIdxs, + MessageInfos: file_pbmulticluster_v2_namespace_exported_services_proto_msgTypes, + }.Build() + File_pbmulticluster_v2_namespace_exported_services_proto = out.File + file_pbmulticluster_v2_namespace_exported_services_proto_rawDesc = nil + file_pbmulticluster_v2_namespace_exported_services_proto_goTypes = nil + file_pbmulticluster_v2_namespace_exported_services_proto_depIdxs = nil +} diff --git a/proto-public/pbmulticluster/v2/namespace_exported_services.proto b/proto-public/pbmulticluster/v2/namespace_exported_services.proto new file mode 100644 index 000000000000..0529570bcf4c --- /dev/null +++ b/proto-public/pbmulticluster/v2/namespace_exported_services.proto @@ -0,0 +1,15 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +syntax = "proto3"; + +package hashicorp.consul.multicluster.v2; + +import "pbmulticluster/v2/exported_services_consumer.proto"; +import "pbresource/annotations.proto"; + +message NamespaceExportedServices { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; + + repeated ExportedServicesConsumer consumers = 1; +} diff --git a/proto-public/pbmulticluster/v2beta1/namespace_exported_services_deepcopy.gen.go b/proto-public/pbmulticluster/v2/namespace_exported_services_deepcopy.gen.go similarity index 97% rename from proto-public/pbmulticluster/v2beta1/namespace_exported_services_deepcopy.gen.go rename to proto-public/pbmulticluster/v2/namespace_exported_services_deepcopy.gen.go index 9d061a755bda..0199758f378b 100644 --- a/proto-public/pbmulticluster/v2beta1/namespace_exported_services_deepcopy.gen.go +++ b/proto-public/pbmulticluster/v2/namespace_exported_services_deepcopy.gen.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package multiclusterv2beta1 +package multiclusterv2 import ( proto "google.golang.org/protobuf/proto" diff --git a/proto-public/pbmulticluster/v2beta1/namespace_exported_services_json.gen.go b/proto-public/pbmulticluster/v2/namespace_exported_services_json.gen.go similarity index 96% rename from proto-public/pbmulticluster/v2beta1/namespace_exported_services_json.gen.go rename to proto-public/pbmulticluster/v2/namespace_exported_services_json.gen.go index 5d4ee1e42c7a..abcd7c4ee5ac 100644 --- a/proto-public/pbmulticluster/v2beta1/namespace_exported_services_json.gen.go +++ b/proto-public/pbmulticluster/v2/namespace_exported_services_json.gen.go @@ -1,5 +1,5 @@ // Code generated by protoc-json-shim. DO NOT EDIT. -package multiclusterv2beta1 +package multiclusterv2 import ( protojson "google.golang.org/protobuf/encoding/protojson" diff --git a/proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.binary.go b/proto-public/pbmulticluster/v2/partition_exported_services.pb.binary.go similarity index 81% rename from proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.binary.go rename to proto-public/pbmulticluster/v2/partition_exported_services.pb.binary.go index 5518b8a00405..a028467845c1 100644 --- a/proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.binary.go +++ b/proto-public/pbmulticluster/v2/partition_exported_services.pb.binary.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbmulticluster/v2beta1/partition_exported_services.proto +// source: pbmulticluster/v2/partition_exported_services.proto -package multiclusterv2beta1 +package multiclusterv2 import ( "google.golang.org/protobuf/proto" diff --git a/proto-public/pbmulticluster/v2/partition_exported_services.pb.go b/proto-public/pbmulticluster/v2/partition_exported_services.pb.go new file mode 100644 index 000000000000..3b8aa0e18f64 --- /dev/null +++ b/proto-public/pbmulticluster/v2/partition_exported_services.pb.go @@ -0,0 +1,182 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc (unknown) +// source: pbmulticluster/v2/partition_exported_services.proto + +package multiclusterv2 + +import ( + _ "github.com/hashicorp/consul/proto-public/pbresource" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type PartitionExportedServices struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Consumers []*ExportedServicesConsumer `protobuf:"bytes,1,rep,name=consumers,proto3" json:"consumers,omitempty"` +} + +func (x *PartitionExportedServices) Reset() { + *x = PartitionExportedServices{} + if protoimpl.UnsafeEnabled { + mi := &file_pbmulticluster_v2_partition_exported_services_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PartitionExportedServices) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PartitionExportedServices) ProtoMessage() {} + +func (x *PartitionExportedServices) ProtoReflect() protoreflect.Message { + mi := &file_pbmulticluster_v2_partition_exported_services_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PartitionExportedServices.ProtoReflect.Descriptor instead. +func (*PartitionExportedServices) Descriptor() ([]byte, []int) { + return file_pbmulticluster_v2_partition_exported_services_proto_rawDescGZIP(), []int{0} +} + +func (x *PartitionExportedServices) GetConsumers() []*ExportedServicesConsumer { + if x != nil { + return x.Consumers + } + return nil +} + +var File_pbmulticluster_v2_partition_exported_services_proto protoreflect.FileDescriptor + +var file_pbmulticluster_v2_partition_exported_services_proto_rawDesc = []byte{ + 0x0a, 0x33, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x1a, 0x32, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x7d, 0x0a, 0x19, 0x50, 0x61, 0x72, + 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, + 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, + 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, + 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x02, 0x42, 0xb4, 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, + 0x32, 0x42, 0x1e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x6f, + 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, + 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x3b, + 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, 0x32, 0xa2, 0x02, + 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, + 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x32, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pbmulticluster_v2_partition_exported_services_proto_rawDescOnce sync.Once + file_pbmulticluster_v2_partition_exported_services_proto_rawDescData = file_pbmulticluster_v2_partition_exported_services_proto_rawDesc +) + +func file_pbmulticluster_v2_partition_exported_services_proto_rawDescGZIP() []byte { + file_pbmulticluster_v2_partition_exported_services_proto_rawDescOnce.Do(func() { + file_pbmulticluster_v2_partition_exported_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2_partition_exported_services_proto_rawDescData) + }) + return file_pbmulticluster_v2_partition_exported_services_proto_rawDescData +} + +var file_pbmulticluster_v2_partition_exported_services_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_pbmulticluster_v2_partition_exported_services_proto_goTypes = []interface{}{ + (*PartitionExportedServices)(nil), // 0: hashicorp.consul.multicluster.v2.PartitionExportedServices + (*ExportedServicesConsumer)(nil), // 1: hashicorp.consul.multicluster.v2.ExportedServicesConsumer +} +var file_pbmulticluster_v2_partition_exported_services_proto_depIdxs = []int32{ + 1, // 0: hashicorp.consul.multicluster.v2.PartitionExportedServices.consumers:type_name -> hashicorp.consul.multicluster.v2.ExportedServicesConsumer + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_pbmulticluster_v2_partition_exported_services_proto_init() } +func file_pbmulticluster_v2_partition_exported_services_proto_init() { + if File_pbmulticluster_v2_partition_exported_services_proto != nil { + return + } + file_pbmulticluster_v2_exported_services_consumer_proto_init() + if !protoimpl.UnsafeEnabled { + file_pbmulticluster_v2_partition_exported_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PartitionExportedServices); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pbmulticluster_v2_partition_exported_services_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pbmulticluster_v2_partition_exported_services_proto_goTypes, + DependencyIndexes: file_pbmulticluster_v2_partition_exported_services_proto_depIdxs, + MessageInfos: file_pbmulticluster_v2_partition_exported_services_proto_msgTypes, + }.Build() + File_pbmulticluster_v2_partition_exported_services_proto = out.File + file_pbmulticluster_v2_partition_exported_services_proto_rawDesc = nil + file_pbmulticluster_v2_partition_exported_services_proto_goTypes = nil + file_pbmulticluster_v2_partition_exported_services_proto_depIdxs = nil +} diff --git a/proto-public/pbmulticluster/v2/partition_exported_services.proto b/proto-public/pbmulticluster/v2/partition_exported_services.proto new file mode 100644 index 000000000000..68337ab8dd18 --- /dev/null +++ b/proto-public/pbmulticluster/v2/partition_exported_services.proto @@ -0,0 +1,15 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +syntax = "proto3"; + +package hashicorp.consul.multicluster.v2; + +import "pbmulticluster/v2/exported_services_consumer.proto"; +import "pbresource/annotations.proto"; + +message PartitionExportedServices { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_PARTITION}; + + repeated ExportedServicesConsumer consumers = 1; +} diff --git a/proto-public/pbmulticluster/v2beta1/partition_exported_services_deepcopy.gen.go b/proto-public/pbmulticluster/v2/partition_exported_services_deepcopy.gen.go similarity index 97% rename from proto-public/pbmulticluster/v2beta1/partition_exported_services_deepcopy.gen.go rename to proto-public/pbmulticluster/v2/partition_exported_services_deepcopy.gen.go index 9f048e16d200..2c9483327539 100644 --- a/proto-public/pbmulticluster/v2beta1/partition_exported_services_deepcopy.gen.go +++ b/proto-public/pbmulticluster/v2/partition_exported_services_deepcopy.gen.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package multiclusterv2beta1 +package multiclusterv2 import ( proto "google.golang.org/protobuf/proto" diff --git a/proto-public/pbmulticluster/v2beta1/partition_exported_services_json.gen.go b/proto-public/pbmulticluster/v2/partition_exported_services_json.gen.go similarity index 96% rename from proto-public/pbmulticluster/v2beta1/partition_exported_services_json.gen.go rename to proto-public/pbmulticluster/v2/partition_exported_services_json.gen.go index e9dfafd70274..1ef3bb063969 100644 --- a/proto-public/pbmulticluster/v2beta1/partition_exported_services_json.gen.go +++ b/proto-public/pbmulticluster/v2/partition_exported_services_json.gen.go @@ -1,5 +1,5 @@ // Code generated by protoc-json-shim. DO NOT EDIT. -package multiclusterv2beta1 +package multiclusterv2 import ( protojson "google.golang.org/protobuf/encoding/protojson" diff --git a/proto-public/pbmulticluster/v2/resources.rtypes.go b/proto-public/pbmulticluster/v2/resources.rtypes.go new file mode 100644 index 000000000000..8ac6f6b860b4 --- /dev/null +++ b/proto-public/pbmulticluster/v2/resources.rtypes.go @@ -0,0 +1,43 @@ +// Code generated by protoc-gen-resource-types. DO NOT EDIT. + +package multiclusterv2 + +import ( + "github.com/hashicorp/consul/proto-public/pbresource" +) + +const ( + GroupName = "multicluster" + Version = "v2" + + ComputedExportedServicesKind = "ComputedExportedServices" + ExportedServicesKind = "ExportedServices" + NamespaceExportedServicesKind = "NamespaceExportedServices" + PartitionExportedServicesKind = "PartitionExportedServices" +) + +var ( + ComputedExportedServicesType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: ComputedExportedServicesKind, + } + + ExportedServicesType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: ExportedServicesKind, + } + + NamespaceExportedServicesType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: NamespaceExportedServicesKind, + } + + PartitionExportedServicesType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: PartitionExportedServicesKind, + } +) diff --git a/proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.go b/proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.go deleted file mode 100644 index 11ebe79f9dc6..000000000000 --- a/proto-public/pbmulticluster/v2beta1/computed_exported_services.pb.go +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmulticluster/v2beta1/computed_exported_services.proto - -package multiclusterv2beta1 - -import ( - pbresource "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ComputedExportedServices struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Consumers []*ComputedExportedService `protobuf:"bytes,1,rep,name=consumers,proto3" json:"consumers,omitempty"` -} - -func (x *ComputedExportedServices) Reset() { - *x = ComputedExportedServices{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedExportedServices) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedExportedServices) ProtoMessage() {} - -func (x *ComputedExportedServices) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedExportedServices.ProtoReflect.Descriptor instead. -func (*ComputedExportedServices) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescGZIP(), []int{0} -} - -func (x *ComputedExportedServices) GetConsumers() []*ComputedExportedService { - if x != nil { - return x.Consumers - } - return nil -} - -type ComputedExportedService struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TargetRef *pbresource.Reference `protobuf:"bytes,1,opt,name=target_ref,json=targetRef,proto3" json:"target_ref,omitempty"` - Consumers []*ComputedExportedServicesConsumer `protobuf:"bytes,2,rep,name=consumers,proto3" json:"consumers,omitempty"` -} - -func (x *ComputedExportedService) Reset() { - *x = ComputedExportedService{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedExportedService) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedExportedService) ProtoMessage() {} - -func (x *ComputedExportedService) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedExportedService.ProtoReflect.Descriptor instead. -func (*ComputedExportedService) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescGZIP(), []int{1} -} - -func (x *ComputedExportedService) GetTargetRef() *pbresource.Reference { - if x != nil { - return x.TargetRef - } - return nil -} - -func (x *ComputedExportedService) GetConsumers() []*ComputedExportedServicesConsumer { - if x != nil { - return x.Consumers - } - return nil -} - -type ComputedExportedServicesConsumer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // no sameness group - // - // Types that are assignable to ConsumerTenancy: - // - // *ComputedExportedServicesConsumer_Peer - // *ComputedExportedServicesConsumer_Partition - ConsumerTenancy isComputedExportedServicesConsumer_ConsumerTenancy `protobuf_oneof:"consumer_tenancy"` -} - -func (x *ComputedExportedServicesConsumer) Reset() { - *x = ComputedExportedServicesConsumer{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComputedExportedServicesConsumer) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComputedExportedServicesConsumer) ProtoMessage() {} - -func (x *ComputedExportedServicesConsumer) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComputedExportedServicesConsumer.ProtoReflect.Descriptor instead. -func (*ComputedExportedServicesConsumer) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescGZIP(), []int{2} -} - -func (m *ComputedExportedServicesConsumer) GetConsumerTenancy() isComputedExportedServicesConsumer_ConsumerTenancy { - if m != nil { - return m.ConsumerTenancy - } - return nil -} - -func (x *ComputedExportedServicesConsumer) GetPeer() string { - if x, ok := x.GetConsumerTenancy().(*ComputedExportedServicesConsumer_Peer); ok { - return x.Peer - } - return "" -} - -func (x *ComputedExportedServicesConsumer) GetPartition() string { - if x, ok := x.GetConsumerTenancy().(*ComputedExportedServicesConsumer_Partition); ok { - return x.Partition - } - return "" -} - -type isComputedExportedServicesConsumer_ConsumerTenancy interface { - isComputedExportedServicesConsumer_ConsumerTenancy() -} - -type ComputedExportedServicesConsumer_Peer struct { - Peer string `protobuf:"bytes,3,opt,name=peer,proto3,oneof"` -} - -type ComputedExportedServicesConsumer_Partition struct { - Partition string `protobuf:"bytes,4,opt,name=partition,proto3,oneof"` -} - -func (*ComputedExportedServicesConsumer_Peer) isComputedExportedServicesConsumer_ConsumerTenancy() {} - -func (*ComputedExportedServicesConsumer_Partition) isComputedExportedServicesConsumer_ConsumerTenancy() { -} - -var File_pbmulticluster_v2beta1_computed_exported_services_proto protoreflect.FileDescriptor - -var file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDesc = []byte{ - 0x0a, 0x37, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, - 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x80, 0x01, 0x0a, 0x18, 0x43, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x5c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, - 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6d, 0x65, 0x72, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x02, 0x22, 0xc5, 0x01, 0x0a, - 0x17, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x52, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x66, 0x12, 0x65, 0x0a, - 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x47, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6d, 0x65, 0x72, 0x73, 0x22, 0x6c, 0x0a, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x12, 0x1e, - 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x12, - 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x74, 0x65, 0x6e, 0x61, 0x6e, - 0x63, 0x79, 0x42, 0xd6, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x42, 0x1d, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x53, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x75, - 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x3b, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, - 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x25, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x31, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x28, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, -} - -var ( - file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescOnce sync.Once - file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescData = file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDesc -) - -func file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescGZIP() []byte { - file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescOnce.Do(func() { - file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescData) - }) - return file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDescData -} - -var file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_pbmulticluster_v2beta1_computed_exported_services_proto_goTypes = []interface{}{ - (*ComputedExportedServices)(nil), // 0: hashicorp.consul.multicluster.v2beta1.ComputedExportedServices - (*ComputedExportedService)(nil), // 1: hashicorp.consul.multicluster.v2beta1.ComputedExportedService - (*ComputedExportedServicesConsumer)(nil), // 2: hashicorp.consul.multicluster.v2beta1.ComputedExportedServicesConsumer - (*pbresource.Reference)(nil), // 3: hashicorp.consul.resource.Reference -} -var file_pbmulticluster_v2beta1_computed_exported_services_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.multicluster.v2beta1.ComputedExportedServices.consumers:type_name -> hashicorp.consul.multicluster.v2beta1.ComputedExportedService - 3, // 1: hashicorp.consul.multicluster.v2beta1.ComputedExportedService.target_ref:type_name -> hashicorp.consul.resource.Reference - 2, // 2: hashicorp.consul.multicluster.v2beta1.ComputedExportedService.consumers:type_name -> hashicorp.consul.multicluster.v2beta1.ComputedExportedServicesConsumer - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_pbmulticluster_v2beta1_computed_exported_services_proto_init() } -func file_pbmulticluster_v2beta1_computed_exported_services_proto_init() { - if File_pbmulticluster_v2beta1_computed_exported_services_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedExportedServices); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedExportedService); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComputedExportedServicesConsumer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes[2].OneofWrappers = []interface{}{ - (*ComputedExportedServicesConsumer_Peer)(nil), - (*ComputedExportedServicesConsumer_Partition)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmulticluster_v2beta1_computed_exported_services_proto_goTypes, - DependencyIndexes: file_pbmulticluster_v2beta1_computed_exported_services_proto_depIdxs, - MessageInfos: file_pbmulticluster_v2beta1_computed_exported_services_proto_msgTypes, - }.Build() - File_pbmulticluster_v2beta1_computed_exported_services_proto = out.File - file_pbmulticluster_v2beta1_computed_exported_services_proto_rawDesc = nil - file_pbmulticluster_v2beta1_computed_exported_services_proto_goTypes = nil - file_pbmulticluster_v2beta1_computed_exported_services_proto_depIdxs = nil -} diff --git a/proto-public/pbmulticluster/v2beta1/computed_exported_services.proto b/proto-public/pbmulticluster/v2beta1/computed_exported_services.proto deleted file mode 100644 index b8a619558451..000000000000 --- a/proto-public/pbmulticluster/v2beta1/computed_exported_services.proto +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -syntax = "proto3"; - -package hashicorp.consul.multicluster.v2beta1; - -import "pbresource/annotations.proto"; -import "pbresource/resource.proto"; - -message ComputedExportedServices { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_PARTITION}; - - repeated ComputedExportedService consumers = 1; -} - -message ComputedExportedService { - hashicorp.consul.resource.Reference target_ref = 1; - repeated ComputedExportedServicesConsumer consumers = 2; -} - -message ComputedExportedServicesConsumer { - // no sameness group - oneof consumer_tenancy { - string peer = 3; - string partition = 4; - } -} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services.pb.go b/proto-public/pbmulticluster/v2beta1/exported_services.pb.go deleted file mode 100644 index 7e776c3a94c1..000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services.pb.go +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmulticluster/v2beta1/exported_services.proto - -package multiclusterv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ExportedServices struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Services []string `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` - Consumers []*ExportedServicesConsumer `protobuf:"bytes,2,rep,name=consumers,proto3" json:"consumers,omitempty"` -} - -func (x *ExportedServices) Reset() { - *x = ExportedServices{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_exported_services_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExportedServices) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExportedServices) ProtoMessage() {} - -func (x *ExportedServices) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_exported_services_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExportedServices.ProtoReflect.Descriptor instead. -func (*ExportedServices) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_exported_services_proto_rawDescGZIP(), []int{0} -} - -func (x *ExportedServices) GetServices() []string { - if x != nil { - return x.Services - } - return nil -} - -func (x *ExportedServices) GetConsumers() []*ExportedServicesConsumer { - if x != nil { - return x.Consumers - } - return nil -} - -var File_pbmulticluster_v2beta1_exported_services_proto protoreflect.FileDescriptor - -var file_pbmulticluster_v2beta1_exported_services_proto_rawDesc = []byte{ - 0x0a, 0x2e, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x25, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, - 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x37, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, - 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x95, - 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, - 0x5d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, - 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6d, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x3a, 0x06, - 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x42, 0xce, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x42, 0x15, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x53, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x3a, 0x3a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x3a, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmulticluster_v2beta1_exported_services_proto_rawDescOnce sync.Once - file_pbmulticluster_v2beta1_exported_services_proto_rawDescData = file_pbmulticluster_v2beta1_exported_services_proto_rawDesc -) - -func file_pbmulticluster_v2beta1_exported_services_proto_rawDescGZIP() []byte { - file_pbmulticluster_v2beta1_exported_services_proto_rawDescOnce.Do(func() { - file_pbmulticluster_v2beta1_exported_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2beta1_exported_services_proto_rawDescData) - }) - return file_pbmulticluster_v2beta1_exported_services_proto_rawDescData -} - -var file_pbmulticluster_v2beta1_exported_services_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmulticluster_v2beta1_exported_services_proto_goTypes = []interface{}{ - (*ExportedServices)(nil), // 0: hashicorp.consul.multicluster.v2beta1.ExportedServices - (*ExportedServicesConsumer)(nil), // 1: hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer -} -var file_pbmulticluster_v2beta1_exported_services_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.multicluster.v2beta1.ExportedServices.consumers:type_name -> hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_pbmulticluster_v2beta1_exported_services_proto_init() } -func file_pbmulticluster_v2beta1_exported_services_proto_init() { - if File_pbmulticluster_v2beta1_exported_services_proto != nil { - return - } - file_pbmulticluster_v2beta1_exported_services_consumer_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmulticluster_v2beta1_exported_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExportedServices); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmulticluster_v2beta1_exported_services_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmulticluster_v2beta1_exported_services_proto_goTypes, - DependencyIndexes: file_pbmulticluster_v2beta1_exported_services_proto_depIdxs, - MessageInfos: file_pbmulticluster_v2beta1_exported_services_proto_msgTypes, - }.Build() - File_pbmulticluster_v2beta1_exported_services_proto = out.File - file_pbmulticluster_v2beta1_exported_services_proto_rawDesc = nil - file_pbmulticluster_v2beta1_exported_services_proto_goTypes = nil - file_pbmulticluster_v2beta1_exported_services_proto_depIdxs = nil -} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services.proto b/proto-public/pbmulticluster/v2beta1/exported_services.proto deleted file mode 100644 index 76cd98ad7a46..000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services.proto +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -syntax = "proto3"; - -package hashicorp.consul.multicluster.v2beta1; - -import "pbmulticluster/v2beta1/exported_services_consumer.proto"; -import "pbresource/annotations.proto"; - -message ExportedServices { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - repeated string services = 1; - repeated ExportedServicesConsumer consumers = 2; -} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.go b/proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.go deleted file mode 100644 index a254b81af0a6..000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services_consumer.pb.go +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmulticluster/v2beta1/exported_services_consumer.proto - -package multiclusterv2beta1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ExportedServicesConsumer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to ConsumerTenancy: - // - // *ExportedServicesConsumer_Peer - // *ExportedServicesConsumer_Partition - // *ExportedServicesConsumer_SamenessGroup - ConsumerTenancy isExportedServicesConsumer_ConsumerTenancy `protobuf_oneof:"consumer_tenancy"` -} - -func (x *ExportedServicesConsumer) Reset() { - *x = ExportedServicesConsumer{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_exported_services_consumer_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExportedServicesConsumer) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExportedServicesConsumer) ProtoMessage() {} - -func (x *ExportedServicesConsumer) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_exported_services_consumer_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExportedServicesConsumer.ProtoReflect.Descriptor instead. -func (*ExportedServicesConsumer) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescGZIP(), []int{0} -} - -func (m *ExportedServicesConsumer) GetConsumerTenancy() isExportedServicesConsumer_ConsumerTenancy { - if m != nil { - return m.ConsumerTenancy - } - return nil -} - -func (x *ExportedServicesConsumer) GetPeer() string { - if x, ok := x.GetConsumerTenancy().(*ExportedServicesConsumer_Peer); ok { - return x.Peer - } - return "" -} - -func (x *ExportedServicesConsumer) GetPartition() string { - if x, ok := x.GetConsumerTenancy().(*ExportedServicesConsumer_Partition); ok { - return x.Partition - } - return "" -} - -func (x *ExportedServicesConsumer) GetSamenessGroup() string { - if x, ok := x.GetConsumerTenancy().(*ExportedServicesConsumer_SamenessGroup); ok { - return x.SamenessGroup - } - return "" -} - -type isExportedServicesConsumer_ConsumerTenancy interface { - isExportedServicesConsumer_ConsumerTenancy() -} - -type ExportedServicesConsumer_Peer struct { - Peer string `protobuf:"bytes,1,opt,name=peer,proto3,oneof"` -} - -type ExportedServicesConsumer_Partition struct { - Partition string `protobuf:"bytes,2,opt,name=partition,proto3,oneof"` -} - -type ExportedServicesConsumer_SamenessGroup struct { - SamenessGroup string `protobuf:"bytes,3,opt,name=sameness_group,json=samenessGroup,proto3,oneof"` -} - -func (*ExportedServicesConsumer_Peer) isExportedServicesConsumer_ConsumerTenancy() {} - -func (*ExportedServicesConsumer_Partition) isExportedServicesConsumer_ConsumerTenancy() {} - -func (*ExportedServicesConsumer_SamenessGroup) isExportedServicesConsumer_ConsumerTenancy() {} - -var File_pbmulticluster_v2beta1_exported_services_consumer_proto protoreflect.FileDescriptor - -var file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDesc = []byte{ - 0x0a, 0x37, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x22, 0x8d, 0x01, 0x0a, 0x18, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x12, 0x14, 0x0a, - 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x70, - 0x65, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0e, 0x73, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x5f, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0d, 0x73, - 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x12, 0x0a, 0x10, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, - 0x42, 0xd6, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x1d, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x53, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x3b, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, 0x32, 0x62, - 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x75, - 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, - 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x28, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var ( - file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescOnce sync.Once - file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescData = file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDesc -) - -func file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescGZIP() []byte { - file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescOnce.Do(func() { - file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescData) - }) - return file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDescData -} - -var file_pbmulticluster_v2beta1_exported_services_consumer_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmulticluster_v2beta1_exported_services_consumer_proto_goTypes = []interface{}{ - (*ExportedServicesConsumer)(nil), // 0: hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer -} -var file_pbmulticluster_v2beta1_exported_services_consumer_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbmulticluster_v2beta1_exported_services_consumer_proto_init() } -func file_pbmulticluster_v2beta1_exported_services_consumer_proto_init() { - if File_pbmulticluster_v2beta1_exported_services_consumer_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbmulticluster_v2beta1_exported_services_consumer_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExportedServicesConsumer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_pbmulticluster_v2beta1_exported_services_consumer_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*ExportedServicesConsumer_Peer)(nil), - (*ExportedServicesConsumer_Partition)(nil), - (*ExportedServicesConsumer_SamenessGroup)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmulticluster_v2beta1_exported_services_consumer_proto_goTypes, - DependencyIndexes: file_pbmulticluster_v2beta1_exported_services_consumer_proto_depIdxs, - MessageInfos: file_pbmulticluster_v2beta1_exported_services_consumer_proto_msgTypes, - }.Build() - File_pbmulticluster_v2beta1_exported_services_consumer_proto = out.File - file_pbmulticluster_v2beta1_exported_services_consumer_proto_rawDesc = nil - file_pbmulticluster_v2beta1_exported_services_consumer_proto_goTypes = nil - file_pbmulticluster_v2beta1_exported_services_consumer_proto_depIdxs = nil -} diff --git a/proto-public/pbmulticluster/v2beta1/exported_services_consumer.proto b/proto-public/pbmulticluster/v2beta1/exported_services_consumer.proto deleted file mode 100644 index 1a110099dcf5..000000000000 --- a/proto-public/pbmulticluster/v2beta1/exported_services_consumer.proto +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -syntax = "proto3"; - -package hashicorp.consul.multicluster.v2beta1; - -message ExportedServicesConsumer { - oneof consumer_tenancy { - string peer = 1; - string partition = 2; - string sameness_group = 3; - } -} diff --git a/proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.go b/proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.go deleted file mode 100644 index 5936f86fda11..000000000000 --- a/proto-public/pbmulticluster/v2beta1/namespace_exported_services.pb.go +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmulticluster/v2beta1/namespace_exported_services.proto - -package multiclusterv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type NamespaceExportedServices struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Consumers []*ExportedServicesConsumer `protobuf:"bytes,1,rep,name=consumers,proto3" json:"consumers,omitempty"` -} - -func (x *NamespaceExportedServices) Reset() { - *x = NamespaceExportedServices{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_namespace_exported_services_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NamespaceExportedServices) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NamespaceExportedServices) ProtoMessage() {} - -func (x *NamespaceExportedServices) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_namespace_exported_services_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NamespaceExportedServices.ProtoReflect.Descriptor instead. -func (*NamespaceExportedServices) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescGZIP(), []int{0} -} - -func (x *NamespaceExportedServices) GetConsumers() []*ExportedServicesConsumer { - if x != nil { - return x.Consumers - } - return nil -} - -var File_pbmulticluster_v2beta1_namespace_exported_services_proto protoreflect.FileDescriptor - -var file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDesc = []byte{ - 0x0a, 0x38, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x1a, 0x37, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x01, 0x0a, 0x19, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x5d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, - 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x72, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x42, 0xd7, 0x02, - 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x1e, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x53, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x3a, 0x3a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x3a, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescOnce sync.Once - file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescData = file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDesc -) - -func file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescGZIP() []byte { - file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescOnce.Do(func() { - file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescData) - }) - return file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDescData -} - -var file_pbmulticluster_v2beta1_namespace_exported_services_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmulticluster_v2beta1_namespace_exported_services_proto_goTypes = []interface{}{ - (*NamespaceExportedServices)(nil), // 0: hashicorp.consul.multicluster.v2beta1.NamespaceExportedServices - (*ExportedServicesConsumer)(nil), // 1: hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer -} -var file_pbmulticluster_v2beta1_namespace_exported_services_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.multicluster.v2beta1.NamespaceExportedServices.consumers:type_name -> hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_pbmulticluster_v2beta1_namespace_exported_services_proto_init() } -func file_pbmulticluster_v2beta1_namespace_exported_services_proto_init() { - if File_pbmulticluster_v2beta1_namespace_exported_services_proto != nil { - return - } - file_pbmulticluster_v2beta1_exported_services_consumer_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmulticluster_v2beta1_namespace_exported_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NamespaceExportedServices); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmulticluster_v2beta1_namespace_exported_services_proto_goTypes, - DependencyIndexes: file_pbmulticluster_v2beta1_namespace_exported_services_proto_depIdxs, - MessageInfos: file_pbmulticluster_v2beta1_namespace_exported_services_proto_msgTypes, - }.Build() - File_pbmulticluster_v2beta1_namespace_exported_services_proto = out.File - file_pbmulticluster_v2beta1_namespace_exported_services_proto_rawDesc = nil - file_pbmulticluster_v2beta1_namespace_exported_services_proto_goTypes = nil - file_pbmulticluster_v2beta1_namespace_exported_services_proto_depIdxs = nil -} diff --git a/proto-public/pbmulticluster/v2beta1/namespace_exported_services.proto b/proto-public/pbmulticluster/v2beta1/namespace_exported_services.proto deleted file mode 100644 index 074d44d36063..000000000000 --- a/proto-public/pbmulticluster/v2beta1/namespace_exported_services.proto +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -syntax = "proto3"; - -package hashicorp.consul.multicluster.v2beta1; - -import "pbmulticluster/v2beta1/exported_services_consumer.proto"; -import "pbresource/annotations.proto"; - -message NamespaceExportedServices { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; - - repeated ExportedServicesConsumer consumers = 1; -} diff --git a/proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.go b/proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.go deleted file mode 100644 index 116e4784e6fe..000000000000 --- a/proto-public/pbmulticluster/v2beta1/partition_exported_services.pb.go +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbmulticluster/v2beta1/partition_exported_services.proto - -package multiclusterv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type PartitionExportedServices struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Consumers []*ExportedServicesConsumer `protobuf:"bytes,1,rep,name=consumers,proto3" json:"consumers,omitempty"` -} - -func (x *PartitionExportedServices) Reset() { - *x = PartitionExportedServices{} - if protoimpl.UnsafeEnabled { - mi := &file_pbmulticluster_v2beta1_partition_exported_services_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PartitionExportedServices) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PartitionExportedServices) ProtoMessage() {} - -func (x *PartitionExportedServices) ProtoReflect() protoreflect.Message { - mi := &file_pbmulticluster_v2beta1_partition_exported_services_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PartitionExportedServices.ProtoReflect.Descriptor instead. -func (*PartitionExportedServices) Descriptor() ([]byte, []int) { - return file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescGZIP(), []int{0} -} - -func (x *PartitionExportedServices) GetConsumers() []*ExportedServicesConsumer { - if x != nil { - return x.Consumers - } - return nil -} - -var File_pbmulticluster_v2beta1_partition_exported_services_proto protoreflect.FileDescriptor - -var file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDesc = []byte{ - 0x0a, 0x38, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x1a, 0x37, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x01, 0x0a, 0x19, 0x50, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x5d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, - 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x72, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x02, 0x42, 0xd7, 0x02, - 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x1e, 0x50, 0x61, 0x72, - 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x53, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x76, 0x32, 0x62, 0x65, 0x74, - 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x3a, 0x3a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x3a, - 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescOnce sync.Once - file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescData = file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDesc -) - -func file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescGZIP() []byte { - file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescOnce.Do(func() { - file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescData) - }) - return file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDescData -} - -var file_pbmulticluster_v2beta1_partition_exported_services_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbmulticluster_v2beta1_partition_exported_services_proto_goTypes = []interface{}{ - (*PartitionExportedServices)(nil), // 0: hashicorp.consul.multicluster.v2beta1.PartitionExportedServices - (*ExportedServicesConsumer)(nil), // 1: hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer -} -var file_pbmulticluster_v2beta1_partition_exported_services_proto_depIdxs = []int32{ - 1, // 0: hashicorp.consul.multicluster.v2beta1.PartitionExportedServices.consumers:type_name -> hashicorp.consul.multicluster.v2beta1.ExportedServicesConsumer - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_pbmulticluster_v2beta1_partition_exported_services_proto_init() } -func file_pbmulticluster_v2beta1_partition_exported_services_proto_init() { - if File_pbmulticluster_v2beta1_partition_exported_services_proto != nil { - return - } - file_pbmulticluster_v2beta1_exported_services_consumer_proto_init() - if !protoimpl.UnsafeEnabled { - file_pbmulticluster_v2beta1_partition_exported_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PartitionExportedServices); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbmulticluster_v2beta1_partition_exported_services_proto_goTypes, - DependencyIndexes: file_pbmulticluster_v2beta1_partition_exported_services_proto_depIdxs, - MessageInfos: file_pbmulticluster_v2beta1_partition_exported_services_proto_msgTypes, - }.Build() - File_pbmulticluster_v2beta1_partition_exported_services_proto = out.File - file_pbmulticluster_v2beta1_partition_exported_services_proto_rawDesc = nil - file_pbmulticluster_v2beta1_partition_exported_services_proto_goTypes = nil - file_pbmulticluster_v2beta1_partition_exported_services_proto_depIdxs = nil -} diff --git a/proto-public/pbmulticluster/v2beta1/partition_exported_services.proto b/proto-public/pbmulticluster/v2beta1/partition_exported_services.proto deleted file mode 100644 index b3cf249a0c90..000000000000 --- a/proto-public/pbmulticluster/v2beta1/partition_exported_services.proto +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -syntax = "proto3"; - -package hashicorp.consul.multicluster.v2beta1; - -import "pbmulticluster/v2beta1/exported_services_consumer.proto"; -import "pbresource/annotations.proto"; - -message PartitionExportedServices { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_PARTITION}; - - repeated ExportedServicesConsumer consumers = 1; -} diff --git a/proto-public/pbmulticluster/v2beta1/resource_types.gen.go b/proto-public/pbmulticluster/v2beta1/resource_types.gen.go deleted file mode 100644 index 910811b98f93..000000000000 --- a/proto-public/pbmulticluster/v2beta1/resource_types.gen.go +++ /dev/null @@ -1,43 +0,0 @@ -// Code generated by protoc-gen-resource-types. DO NOT EDIT. - -package multiclusterv2beta1 - -import ( - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - GroupName = "multicluster" - Version = "v2beta1" - - ComputedExportedServicesKind = "ComputedExportedServices" - ExportedServicesKind = "ExportedServices" - NamespaceExportedServicesKind = "NamespaceExportedServices" - PartitionExportedServicesKind = "PartitionExportedServices" -) - -var ( - ComputedExportedServicesType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: ComputedExportedServicesKind, - } - - ExportedServicesType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: ExportedServicesKind, - } - - NamespaceExportedServicesType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: NamespaceExportedServicesKind, - } - - PartitionExportedServicesType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: PartitionExportedServicesKind, - } -) diff --git a/proto-public/pbresource/annotations.pb.go b/proto-public/pbresource/annotations.pb.go index fa01056cf3d9..f7a670575898 100644 --- a/proto-public/pbresource/annotations.pb.go +++ b/proto-public/pbresource/annotations.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: pbresource/annotations.proto diff --git a/proto-public/pbresource/cloning_stream.pb.go b/proto-public/pbresource/cloning_stream.pb.go new file mode 100644 index 000000000000..09feb43ee02a --- /dev/null +++ b/proto-public/pbresource/cloning_stream.pb.go @@ -0,0 +1,31 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package pbresource + +import ( + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +type serverStream[T proto.Message] interface { + Recv() (T, error) + grpc.ClientStream +} + +type cloningStream[T proto.Message] struct { + serverStream[T] +} + +func newCloningStream[T proto.Message](stream serverStream[T]) cloningStream[T] { + return cloningStream[T]{serverStream: stream} +} + +func (st cloningStream[T]) Recv() (T, error) { + var zero T + val, err := st.serverStream.Recv() + if err != nil { + return zero, err + } + + return proto.Clone(val).(T), nil +} diff --git a/proto-public/pbresource/resource.pb.binary.go b/proto-public/pbresource/resource.pb.binary.go index 0548452feb75..5f2aabfbcc64 100644 --- a/proto-public/pbresource/resource.pb.binary.go +++ b/proto-public/pbresource/resource.pb.binary.go @@ -226,3 +226,53 @@ func (msg *WatchEvent) MarshalBinary() ([]byte, error) { func (msg *WatchEvent) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *WatchEvent_Upsert) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *WatchEvent_Upsert) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *WatchEvent_Delete) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *WatchEvent_Delete) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *WatchEvent_EndOfSnapshot) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *WatchEvent_EndOfSnapshot) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *MutateAndValidateRequest) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *MutateAndValidateRequest) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *MutateAndValidateResponse) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *MutateAndValidateResponse) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} diff --git a/proto-public/pbresource/resource.pb.go b/proto-public/pbresource/resource.pb.go index 889a0314af31..a0b65b349485 100644 --- a/proto-public/pbresource/resource.pb.go +++ b/proto-public/pbresource/resource.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: pbresource/resource.proto @@ -83,62 +83,6 @@ func (Condition_State) EnumDescriptor() ([]byte, []int) { return file_pbresource_resource_proto_rawDescGZIP(), []int{5, 0} } -// Operation describes the type of event. -type WatchEvent_Operation int32 - -const ( - // OPERATION_UNSPECIFIED is the default/zero value. You should not see it - // in practice. - WatchEvent_OPERATION_UNSPECIFIED WatchEvent_Operation = 0 - // OPERATION_UPSERT indicates that the resource was written (i.e. created or - // updated). All events from the initial state-of-the-world will be upsert - // events. - WatchEvent_OPERATION_UPSERT WatchEvent_Operation = 1 - // OPERATION_DELETED indicates that the resource was deleted. - WatchEvent_OPERATION_DELETE WatchEvent_Operation = 2 -) - -// Enum value maps for WatchEvent_Operation. -var ( - WatchEvent_Operation_name = map[int32]string{ - 0: "OPERATION_UNSPECIFIED", - 1: "OPERATION_UPSERT", - 2: "OPERATION_DELETE", - } - WatchEvent_Operation_value = map[string]int32{ - "OPERATION_UNSPECIFIED": 0, - "OPERATION_UPSERT": 1, - "OPERATION_DELETE": 2, - } -) - -func (x WatchEvent_Operation) Enum() *WatchEvent_Operation { - p := new(WatchEvent_Operation) - *p = x - return p -} - -func (x WatchEvent_Operation) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (WatchEvent_Operation) Descriptor() protoreflect.EnumDescriptor { - return file_pbresource_resource_proto_enumTypes[1].Descriptor() -} - -func (WatchEvent_Operation) Type() protoreflect.EnumType { - return &file_pbresource_resource_proto_enumTypes[1] -} - -func (x WatchEvent_Operation) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use WatchEvent_Operation.Descriptor instead. -func (WatchEvent_Operation) EnumDescriptor() ([]byte, []int) { - return file_pbresource_resource_proto_rawDescGZIP(), []int{21, 0} -} - // Type describes a resource's type. It follows the GVK (Group Version Kind) // [pattern](https://book.kubebuilder.io/cronjob-tutorial/gvks.html) established // by Kubernetes. @@ -228,12 +172,6 @@ type Tenancy struct { // When using the List and WatchList endpoints, provide the wildcard value "*" // to list resources across all namespaces. Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` - // PeerName identifies which peer the resource is imported from. - // https://developer.hashicorp.com/consul/docs/connect/cluster-peering - // - // When using the List and WatchList endpoints, provide the wildcard value "*" - // to list resources across all peers. - PeerName string `protobuf:"bytes,3,opt,name=peer_name,json=peerName,proto3" json:"peer_name,omitempty"` } func (x *Tenancy) Reset() { @@ -282,13 +220,6 @@ func (x *Tenancy) GetNamespace() string { return "" } -func (x *Tenancy) GetPeerName() string { - if x != nil { - return x.PeerName - } - return "" -} - // ID uniquely identifies a resource. type ID struct { state protoimpl.MessageState @@ -399,6 +330,7 @@ type Resource struct { // can treat its timestamp component as the resource's modification time. Generation string `protobuf:"bytes,4,opt,name=generation,proto3" json:"generation,omitempty"` // Metadata contains key/value pairs of arbitrary metadata about the resource. + // "deletionTimestamp" and "finalizers" keys are reserved for internal use. Metadata map[string]string `protobuf:"bytes,5,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // Status is used by controllers to communicate the result of attempting to // reconcile and apply the resource (e.g. surface semantic validation errors) @@ -1502,10 +1434,12 @@ type WatchEvent struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Operation describes the type of event. - Operation WatchEvent_Operation `protobuf:"varint,1,opt,name=operation,proto3,enum=hashicorp.consul.resource.WatchEvent_Operation" json:"operation,omitempty"` - // Resource the event relates to. - Resource *Resource `protobuf:"bytes,2,opt,name=resource,proto3" json:"resource,omitempty"` + // Types that are assignable to Event: + // + // *WatchEvent_Upsert_ + // *WatchEvent_Delete_ + // *WatchEvent_EndOfSnapshot_ + Event isWatchEvent_Event `protobuf_oneof:"event"` } func (x *WatchEvent) Reset() { @@ -1540,20 +1474,290 @@ func (*WatchEvent) Descriptor() ([]byte, []int) { return file_pbresource_resource_proto_rawDescGZIP(), []int{21} } -func (x *WatchEvent) GetOperation() WatchEvent_Operation { +func (m *WatchEvent) GetEvent() isWatchEvent_Event { + if m != nil { + return m.Event + } + return nil +} + +func (x *WatchEvent) GetUpsert() *WatchEvent_Upsert { + if x, ok := x.GetEvent().(*WatchEvent_Upsert_); ok { + return x.Upsert + } + return nil +} + +func (x *WatchEvent) GetDelete() *WatchEvent_Delete { + if x, ok := x.GetEvent().(*WatchEvent_Delete_); ok { + return x.Delete + } + return nil +} + +func (x *WatchEvent) GetEndOfSnapshot() *WatchEvent_EndOfSnapshot { + if x, ok := x.GetEvent().(*WatchEvent_EndOfSnapshot_); ok { + return x.EndOfSnapshot + } + return nil +} + +type isWatchEvent_Event interface { + isWatchEvent_Event() +} + +type WatchEvent_Upsert_ struct { + Upsert *WatchEvent_Upsert `protobuf:"bytes,1,opt,name=upsert,proto3,oneof"` +} + +type WatchEvent_Delete_ struct { + Delete *WatchEvent_Delete `protobuf:"bytes,2,opt,name=delete,proto3,oneof"` +} + +type WatchEvent_EndOfSnapshot_ struct { + EndOfSnapshot *WatchEvent_EndOfSnapshot `protobuf:"bytes,3,opt,name=end_of_snapshot,json=endOfSnapshot,proto3,oneof"` +} + +func (*WatchEvent_Upsert_) isWatchEvent_Event() {} + +func (*WatchEvent_Delete_) isWatchEvent_Event() {} + +func (*WatchEvent_EndOfSnapshot_) isWatchEvent_Event() {} + +// MutateAndValidateRequest contains the parameters to the MutateAndValidate endpoint. +type MutateAndValidateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` +} + +func (x *MutateAndValidateRequest) Reset() { + *x = MutateAndValidateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pbresource_resource_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MutateAndValidateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MutateAndValidateRequest) ProtoMessage() {} + +func (x *MutateAndValidateRequest) ProtoReflect() protoreflect.Message { + mi := &file_pbresource_resource_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MutateAndValidateRequest.ProtoReflect.Descriptor instead. +func (*MutateAndValidateRequest) Descriptor() ([]byte, []int) { + return file_pbresource_resource_proto_rawDescGZIP(), []int{22} +} + +func (x *MutateAndValidateRequest) GetResource() *Resource { + if x != nil { + return x.Resource + } + return nil +} + +// MutateAndValidateResponse contains the results of calling the MutateAndValidate endpoint. +type MutateAndValidateResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` +} + +func (x *MutateAndValidateResponse) Reset() { + *x = MutateAndValidateResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pbresource_resource_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MutateAndValidateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MutateAndValidateResponse) ProtoMessage() {} + +func (x *MutateAndValidateResponse) ProtoReflect() protoreflect.Message { + mi := &file_pbresource_resource_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MutateAndValidateResponse.ProtoReflect.Descriptor instead. +func (*MutateAndValidateResponse) Descriptor() ([]byte, []int) { + return file_pbresource_resource_proto_rawDescGZIP(), []int{23} +} + +func (x *MutateAndValidateResponse) GetResource() *Resource { if x != nil { - return x.Operation + return x.Resource } - return WatchEvent_OPERATION_UNSPECIFIED + return nil +} + +// Upsert indicates that the resource was written (i.e. created or +// updated). All events from the initial state-of-the-world will be upsert +// events. +type WatchEvent_Upsert struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` } -func (x *WatchEvent) GetResource() *Resource { +func (x *WatchEvent_Upsert) Reset() { + *x = WatchEvent_Upsert{} + if protoimpl.UnsafeEnabled { + mi := &file_pbresource_resource_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WatchEvent_Upsert) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchEvent_Upsert) ProtoMessage() {} + +func (x *WatchEvent_Upsert) ProtoReflect() protoreflect.Message { + mi := &file_pbresource_resource_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WatchEvent_Upsert.ProtoReflect.Descriptor instead. +func (*WatchEvent_Upsert) Descriptor() ([]byte, []int) { + return file_pbresource_resource_proto_rawDescGZIP(), []int{21, 0} +} + +func (x *WatchEvent_Upsert) GetResource() *Resource { if x != nil { return x.Resource } return nil } +// Delete indicates that the resource was deleted. +type WatchEvent_Delete struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` +} + +func (x *WatchEvent_Delete) Reset() { + *x = WatchEvent_Delete{} + if protoimpl.UnsafeEnabled { + mi := &file_pbresource_resource_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WatchEvent_Delete) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchEvent_Delete) ProtoMessage() {} + +func (x *WatchEvent_Delete) ProtoReflect() protoreflect.Message { + mi := &file_pbresource_resource_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WatchEvent_Delete.ProtoReflect.Descriptor instead. +func (*WatchEvent_Delete) Descriptor() ([]byte, []int) { + return file_pbresource_resource_proto_rawDescGZIP(), []int{21, 1} +} + +func (x *WatchEvent_Delete) GetResource() *Resource { + if x != nil { + return x.Resource + } + return nil +} + +// EndOfSnapshot is sent to indicate that the initial snapshot events have +// been sent and future events will modify that set. +type WatchEvent_EndOfSnapshot struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *WatchEvent_EndOfSnapshot) Reset() { + *x = WatchEvent_EndOfSnapshot{} + if protoimpl.UnsafeEnabled { + mi := &file_pbresource_resource_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WatchEvent_EndOfSnapshot) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchEvent_EndOfSnapshot) ProtoMessage() {} + +func (x *WatchEvent_EndOfSnapshot) ProtoReflect() protoreflect.Message { + mi := &file_pbresource_resource_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WatchEvent_EndOfSnapshot.ProtoReflect.Descriptor instead. +func (*WatchEvent_EndOfSnapshot) Descriptor() ([]byte, []int) { + return file_pbresource_resource_proto_rawDescGZIP(), []int{21, 2} +} + var File_pbresource_resource_proto protoreflect.FileDescriptor var file_pbresource_resource_proto_rawDesc = []byte{ @@ -1572,257 +1776,287 @@ var file_pbresource_resource_proto_rawDesc = []byte{ 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, - 0x22, 0x62, 0x0a, 0x07, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x70, + 0x22, 0x45, 0x0a, 0x07, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x65, 0x65, 0x72, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x65, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x9d, 0x01, 0x0a, 0x02, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x75, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x9d, 0x01, 0x0a, 0x02, 0x49, 0x44, 0x12, 0x10, + 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x07, 0x74, 0x65, 0x6e, + 0x61, 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x52, 0x07, + 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x22, 0x85, 0x04, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x12, 0x2d, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x33, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, + 0x44, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x12, 0x47, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x1a, 0x5c, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x37, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0xba, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2f, 0x0a, 0x13, 0x6f, 0x62, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x64, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0a, 0x63, + 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x92, 0x02, 0x0a, + 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x40, + 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x22, 0x3b, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x11, 0x0a, + 0x0d, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, + 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x52, 0x55, 0x45, 0x10, 0x01, + 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x10, + 0x02, 0x22, 0xac, 0x01, 0x0a, 0x09, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, + 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x52, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, + 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x40, 0x0a, 0x09, 0x54, 0x6f, 0x6d, 0x62, 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x12, 0x33, 0x0a, + 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, 0x05, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x22, 0x3c, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x2d, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, + 0x22, 0x4f, 0x0a, 0x0c, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x3f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x22, 0xa1, 0x01, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, - 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x52, 0x07, 0x74, 0x65, 0x6e, - 0x61, 0x6e, 0x63, 0x79, 0x22, 0x85, 0x04, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x12, 0x2d, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, + 0x61, 0x6e, 0x63, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x51, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x49, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, + 0x42, 0x79, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, + 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x33, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, 0x05, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x1e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x4d, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, 0x05, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x22, 0x58, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x4f, 0x77, 0x6e, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x4f, 0x0a, + 0x0c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, + 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x23, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x50, + 0x0a, 0x0d, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x47, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5c, - 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x37, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xba, 0x01, 0x0a, - 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2f, 0x0a, 0x13, 0x6f, 0x62, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x22, 0xaa, 0x01, 0x0a, 0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, + 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x39, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x56, 0x0a, + 0x13, 0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x58, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, + 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, + 0x10, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x10, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x07, 0x74, + 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x39, - 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x92, 0x02, 0x0a, 0x09, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x40, 0x0a, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, - 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x40, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, - 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x22, 0x3b, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x54, - 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0e, 0x0a, - 0x0a, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x52, 0x55, 0x45, 0x10, 0x01, 0x12, 0x0f, 0x0a, - 0x0b, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x10, 0x02, 0x22, 0xac, - 0x01, 0x0a, 0x09, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x12, 0x3c, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, - 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x52, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x40, 0x0a, - 0x09, 0x54, 0x6f, 0x6d, 0x62, 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x12, 0x33, 0x0a, 0x05, 0x6f, 0x77, - 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, + 0x52, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, + 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x6e, 0x61, 0x6d, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0xab, 0x03, 0x0a, 0x0a, 0x57, + 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x46, 0x0a, 0x06, 0x75, 0x70, 0x73, + 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x22, - 0x3c, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4f, 0x0a, - 0x0c, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x48, 0x00, 0x52, 0x06, 0x75, 0x70, 0x73, 0x65, 0x72, + 0x74, 0x12, 0x46, 0x0a, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, + 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, + 0x00, 0x52, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x5d, 0x0a, 0x0f, 0x65, 0x6e, 0x64, + 0x5f, 0x6f, 0x66, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, + 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x4f, 0x66, 0x53, + 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x65, 0x6e, 0x64, 0x4f, 0x66, + 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x1a, 0x49, 0x0a, 0x06, 0x55, 0x70, 0x73, 0x65, + 0x72, 0x74, 0x12, 0x3f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x1a, 0x49, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x3f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xa1, - 0x01, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x1a, 0x0f, + 0x0a, 0x0d, 0x45, 0x6e, 0x64, 0x4f, 0x66, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x42, + 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x5b, 0x0a, 0x18, 0x4d, 0x75, 0x74, 0x61, + 0x74, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x5c, 0x0a, 0x19, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x41, + 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x52, 0x07, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, - 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x50, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x22, 0x51, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x49, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x4f, - 0x77, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x05, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x22, 0x58, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, - 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x4f, 0x0a, 0x0c, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x08, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x32, 0x8e, 0x07, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x61, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, + 0x26, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x0b, 0x12, 0x64, 0x0a, 0x05, 0x57, 0x72, + 0x69, 0x74, 0x65, 0x12, 0x27, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, + 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x50, 0x0a, 0x0d, 0x57, - 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x08, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x03, 0x10, 0x0b, + 0x12, 0x76, 0x0a, 0x0b, 0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x72, 0x69, 0x74, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xaa, 0x01, - 0x0a, 0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x39, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x21, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x56, 0x0a, 0x13, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x22, 0x58, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x49, 0x44, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x10, 0x0a, 0x0e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa6, - 0x01, 0x0a, 0x10, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x07, 0x74, 0x65, 0x6e, 0x61, - 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x52, 0x07, 0x74, - 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, - 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x61, 0x6d, - 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0xf0, 0x01, 0x0a, 0x0a, 0x57, 0x61, 0x74, 0x63, - 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x4d, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, + 0xe2, 0x86, 0x04, 0x04, 0x08, 0x03, 0x10, 0x0b, 0x12, 0x61, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x26, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x0b, 0x12, 0x76, 0x0a, 0x0b, 0x4c, + 0x69, 0x73, 0x74, 0x42, 0x79, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x2d, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x4f, 0x77, 0x6e, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x4f, 0x77, 0x6e, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, + 0x02, 0x10, 0x0b, 0x12, 0x67, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x28, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x52, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, - 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x53, 0x45, - 0x52, 0x54, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x32, 0x83, 0x06, 0x0a, 0x0f, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x61, - 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, 0x26, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, - 0x0b, 0x12, 0x64, 0x0a, 0x05, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x27, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, - 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, - 0x86, 0x04, 0x04, 0x08, 0x03, 0x10, 0x0b, 0x12, 0x76, 0x0a, 0x0b, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x03, 0x10, 0x0b, 0x12, 0x6b, 0x0a, 0x09, + 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x03, 0x10, 0x0b, 0x12, - 0x61, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x26, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x27, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, - 0x10, 0x0b, 0x12, 0x76, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x4f, 0x77, 0x6e, 0x65, - 0x72, 0x12, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x42, 0x79, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x42, 0x79, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x0b, 0x12, 0x67, 0x0a, 0x06, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x12, 0x28, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x08, 0xe2, + 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x0b, 0x30, 0x01, 0x12, 0x88, 0x01, 0x0a, 0x11, 0x4d, 0x75, + 0x74, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x12, + 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4d, 0x75, 0x74, 0x61, + 0x74, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, - 0x03, 0x10, 0x0b, 0x12, 0x6b, 0x0a, 0x09, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, - 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x0b, 0x30, 0x01, - 0x42, 0xe9, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x42, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x52, 0xaa, 0x02, - 0x19, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0xca, 0x02, 0x19, 0x48, 0x61, 0x73, + 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, + 0x08, 0x02, 0x10, 0x0b, 0x42, 0xe9, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x2f, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0xa2, 0x02, 0x03, 0x48, + 0x43, 0x52, 0xaa, 0x02, 0x19, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0xca, 0x02, + 0x19, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x5c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0xe2, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0xe2, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x1b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x3a, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0xea, 0x02, 0x1b, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1837,90 +2071,101 @@ func file_pbresource_resource_proto_rawDescGZIP() []byte { return file_pbresource_resource_proto_rawDescData } -var file_pbresource_resource_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_pbresource_resource_proto_msgTypes = make([]protoimpl.MessageInfo, 24) +var file_pbresource_resource_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_pbresource_resource_proto_msgTypes = make([]protoimpl.MessageInfo, 29) var file_pbresource_resource_proto_goTypes = []interface{}{ - (Condition_State)(0), // 0: hashicorp.consul.resource.Condition.State - (WatchEvent_Operation)(0), // 1: hashicorp.consul.resource.WatchEvent.Operation - (*Type)(nil), // 2: hashicorp.consul.resource.Type - (*Tenancy)(nil), // 3: hashicorp.consul.resource.Tenancy - (*ID)(nil), // 4: hashicorp.consul.resource.ID - (*Resource)(nil), // 5: hashicorp.consul.resource.Resource - (*Status)(nil), // 6: hashicorp.consul.resource.Status - (*Condition)(nil), // 7: hashicorp.consul.resource.Condition - (*Reference)(nil), // 8: hashicorp.consul.resource.Reference - (*Tombstone)(nil), // 9: hashicorp.consul.resource.Tombstone - (*ReadRequest)(nil), // 10: hashicorp.consul.resource.ReadRequest - (*ReadResponse)(nil), // 11: hashicorp.consul.resource.ReadResponse - (*ListRequest)(nil), // 12: hashicorp.consul.resource.ListRequest - (*ListResponse)(nil), // 13: hashicorp.consul.resource.ListResponse - (*ListByOwnerRequest)(nil), // 14: hashicorp.consul.resource.ListByOwnerRequest - (*ListByOwnerResponse)(nil), // 15: hashicorp.consul.resource.ListByOwnerResponse - (*WriteRequest)(nil), // 16: hashicorp.consul.resource.WriteRequest - (*WriteResponse)(nil), // 17: hashicorp.consul.resource.WriteResponse - (*WriteStatusRequest)(nil), // 18: hashicorp.consul.resource.WriteStatusRequest - (*WriteStatusResponse)(nil), // 19: hashicorp.consul.resource.WriteStatusResponse - (*DeleteRequest)(nil), // 20: hashicorp.consul.resource.DeleteRequest - (*DeleteResponse)(nil), // 21: hashicorp.consul.resource.DeleteResponse - (*WatchListRequest)(nil), // 22: hashicorp.consul.resource.WatchListRequest - (*WatchEvent)(nil), // 23: hashicorp.consul.resource.WatchEvent - nil, // 24: hashicorp.consul.resource.Resource.MetadataEntry - nil, // 25: hashicorp.consul.resource.Resource.StatusEntry - (*anypb.Any)(nil), // 26: google.protobuf.Any - (*timestamppb.Timestamp)(nil), // 27: google.protobuf.Timestamp + (Condition_State)(0), // 0: hashicorp.consul.resource.Condition.State + (*Type)(nil), // 1: hashicorp.consul.resource.Type + (*Tenancy)(nil), // 2: hashicorp.consul.resource.Tenancy + (*ID)(nil), // 3: hashicorp.consul.resource.ID + (*Resource)(nil), // 4: hashicorp.consul.resource.Resource + (*Status)(nil), // 5: hashicorp.consul.resource.Status + (*Condition)(nil), // 6: hashicorp.consul.resource.Condition + (*Reference)(nil), // 7: hashicorp.consul.resource.Reference + (*Tombstone)(nil), // 8: hashicorp.consul.resource.Tombstone + (*ReadRequest)(nil), // 9: hashicorp.consul.resource.ReadRequest + (*ReadResponse)(nil), // 10: hashicorp.consul.resource.ReadResponse + (*ListRequest)(nil), // 11: hashicorp.consul.resource.ListRequest + (*ListResponse)(nil), // 12: hashicorp.consul.resource.ListResponse + (*ListByOwnerRequest)(nil), // 13: hashicorp.consul.resource.ListByOwnerRequest + (*ListByOwnerResponse)(nil), // 14: hashicorp.consul.resource.ListByOwnerResponse + (*WriteRequest)(nil), // 15: hashicorp.consul.resource.WriteRequest + (*WriteResponse)(nil), // 16: hashicorp.consul.resource.WriteResponse + (*WriteStatusRequest)(nil), // 17: hashicorp.consul.resource.WriteStatusRequest + (*WriteStatusResponse)(nil), // 18: hashicorp.consul.resource.WriteStatusResponse + (*DeleteRequest)(nil), // 19: hashicorp.consul.resource.DeleteRequest + (*DeleteResponse)(nil), // 20: hashicorp.consul.resource.DeleteResponse + (*WatchListRequest)(nil), // 21: hashicorp.consul.resource.WatchListRequest + (*WatchEvent)(nil), // 22: hashicorp.consul.resource.WatchEvent + (*MutateAndValidateRequest)(nil), // 23: hashicorp.consul.resource.MutateAndValidateRequest + (*MutateAndValidateResponse)(nil), // 24: hashicorp.consul.resource.MutateAndValidateResponse + nil, // 25: hashicorp.consul.resource.Resource.MetadataEntry + nil, // 26: hashicorp.consul.resource.Resource.StatusEntry + (*WatchEvent_Upsert)(nil), // 27: hashicorp.consul.resource.WatchEvent.Upsert + (*WatchEvent_Delete)(nil), // 28: hashicorp.consul.resource.WatchEvent.Delete + (*WatchEvent_EndOfSnapshot)(nil), // 29: hashicorp.consul.resource.WatchEvent.EndOfSnapshot + (*anypb.Any)(nil), // 30: google.protobuf.Any + (*timestamppb.Timestamp)(nil), // 31: google.protobuf.Timestamp } var file_pbresource_resource_proto_depIdxs = []int32{ - 2, // 0: hashicorp.consul.resource.ID.type:type_name -> hashicorp.consul.resource.Type - 3, // 1: hashicorp.consul.resource.ID.tenancy:type_name -> hashicorp.consul.resource.Tenancy - 4, // 2: hashicorp.consul.resource.Resource.id:type_name -> hashicorp.consul.resource.ID - 4, // 3: hashicorp.consul.resource.Resource.owner:type_name -> hashicorp.consul.resource.ID - 24, // 4: hashicorp.consul.resource.Resource.metadata:type_name -> hashicorp.consul.resource.Resource.MetadataEntry - 25, // 5: hashicorp.consul.resource.Resource.status:type_name -> hashicorp.consul.resource.Resource.StatusEntry - 26, // 6: hashicorp.consul.resource.Resource.data:type_name -> google.protobuf.Any - 7, // 7: hashicorp.consul.resource.Status.conditions:type_name -> hashicorp.consul.resource.Condition - 27, // 8: hashicorp.consul.resource.Status.updated_at:type_name -> google.protobuf.Timestamp + 1, // 0: hashicorp.consul.resource.ID.type:type_name -> hashicorp.consul.resource.Type + 2, // 1: hashicorp.consul.resource.ID.tenancy:type_name -> hashicorp.consul.resource.Tenancy + 3, // 2: hashicorp.consul.resource.Resource.id:type_name -> hashicorp.consul.resource.ID + 3, // 3: hashicorp.consul.resource.Resource.owner:type_name -> hashicorp.consul.resource.ID + 25, // 4: hashicorp.consul.resource.Resource.metadata:type_name -> hashicorp.consul.resource.Resource.MetadataEntry + 26, // 5: hashicorp.consul.resource.Resource.status:type_name -> hashicorp.consul.resource.Resource.StatusEntry + 30, // 6: hashicorp.consul.resource.Resource.data:type_name -> google.protobuf.Any + 6, // 7: hashicorp.consul.resource.Status.conditions:type_name -> hashicorp.consul.resource.Condition + 31, // 8: hashicorp.consul.resource.Status.updated_at:type_name -> google.protobuf.Timestamp 0, // 9: hashicorp.consul.resource.Condition.state:type_name -> hashicorp.consul.resource.Condition.State - 8, // 10: hashicorp.consul.resource.Condition.resource:type_name -> hashicorp.consul.resource.Reference - 2, // 11: hashicorp.consul.resource.Reference.type:type_name -> hashicorp.consul.resource.Type - 3, // 12: hashicorp.consul.resource.Reference.tenancy:type_name -> hashicorp.consul.resource.Tenancy - 4, // 13: hashicorp.consul.resource.Tombstone.owner:type_name -> hashicorp.consul.resource.ID - 4, // 14: hashicorp.consul.resource.ReadRequest.id:type_name -> hashicorp.consul.resource.ID - 5, // 15: hashicorp.consul.resource.ReadResponse.resource:type_name -> hashicorp.consul.resource.Resource - 2, // 16: hashicorp.consul.resource.ListRequest.type:type_name -> hashicorp.consul.resource.Type - 3, // 17: hashicorp.consul.resource.ListRequest.tenancy:type_name -> hashicorp.consul.resource.Tenancy - 5, // 18: hashicorp.consul.resource.ListResponse.resources:type_name -> hashicorp.consul.resource.Resource - 4, // 19: hashicorp.consul.resource.ListByOwnerRequest.owner:type_name -> hashicorp.consul.resource.ID - 5, // 20: hashicorp.consul.resource.ListByOwnerResponse.resources:type_name -> hashicorp.consul.resource.Resource - 5, // 21: hashicorp.consul.resource.WriteRequest.resource:type_name -> hashicorp.consul.resource.Resource - 5, // 22: hashicorp.consul.resource.WriteResponse.resource:type_name -> hashicorp.consul.resource.Resource - 4, // 23: hashicorp.consul.resource.WriteStatusRequest.id:type_name -> hashicorp.consul.resource.ID - 6, // 24: hashicorp.consul.resource.WriteStatusRequest.status:type_name -> hashicorp.consul.resource.Status - 5, // 25: hashicorp.consul.resource.WriteStatusResponse.resource:type_name -> hashicorp.consul.resource.Resource - 4, // 26: hashicorp.consul.resource.DeleteRequest.id:type_name -> hashicorp.consul.resource.ID - 2, // 27: hashicorp.consul.resource.WatchListRequest.type:type_name -> hashicorp.consul.resource.Type - 3, // 28: hashicorp.consul.resource.WatchListRequest.tenancy:type_name -> hashicorp.consul.resource.Tenancy - 1, // 29: hashicorp.consul.resource.WatchEvent.operation:type_name -> hashicorp.consul.resource.WatchEvent.Operation - 5, // 30: hashicorp.consul.resource.WatchEvent.resource:type_name -> hashicorp.consul.resource.Resource - 6, // 31: hashicorp.consul.resource.Resource.StatusEntry.value:type_name -> hashicorp.consul.resource.Status - 10, // 32: hashicorp.consul.resource.ResourceService.Read:input_type -> hashicorp.consul.resource.ReadRequest - 16, // 33: hashicorp.consul.resource.ResourceService.Write:input_type -> hashicorp.consul.resource.WriteRequest - 18, // 34: hashicorp.consul.resource.ResourceService.WriteStatus:input_type -> hashicorp.consul.resource.WriteStatusRequest - 12, // 35: hashicorp.consul.resource.ResourceService.List:input_type -> hashicorp.consul.resource.ListRequest - 14, // 36: hashicorp.consul.resource.ResourceService.ListByOwner:input_type -> hashicorp.consul.resource.ListByOwnerRequest - 20, // 37: hashicorp.consul.resource.ResourceService.Delete:input_type -> hashicorp.consul.resource.DeleteRequest - 22, // 38: hashicorp.consul.resource.ResourceService.WatchList:input_type -> hashicorp.consul.resource.WatchListRequest - 11, // 39: hashicorp.consul.resource.ResourceService.Read:output_type -> hashicorp.consul.resource.ReadResponse - 17, // 40: hashicorp.consul.resource.ResourceService.Write:output_type -> hashicorp.consul.resource.WriteResponse - 19, // 41: hashicorp.consul.resource.ResourceService.WriteStatus:output_type -> hashicorp.consul.resource.WriteStatusResponse - 13, // 42: hashicorp.consul.resource.ResourceService.List:output_type -> hashicorp.consul.resource.ListResponse - 15, // 43: hashicorp.consul.resource.ResourceService.ListByOwner:output_type -> hashicorp.consul.resource.ListByOwnerResponse - 21, // 44: hashicorp.consul.resource.ResourceService.Delete:output_type -> hashicorp.consul.resource.DeleteResponse - 23, // 45: hashicorp.consul.resource.ResourceService.WatchList:output_type -> hashicorp.consul.resource.WatchEvent - 39, // [39:46] is the sub-list for method output_type - 32, // [32:39] is the sub-list for method input_type - 32, // [32:32] is the sub-list for extension type_name - 32, // [32:32] is the sub-list for extension extendee - 0, // [0:32] is the sub-list for field type_name + 7, // 10: hashicorp.consul.resource.Condition.resource:type_name -> hashicorp.consul.resource.Reference + 1, // 11: hashicorp.consul.resource.Reference.type:type_name -> hashicorp.consul.resource.Type + 2, // 12: hashicorp.consul.resource.Reference.tenancy:type_name -> hashicorp.consul.resource.Tenancy + 3, // 13: hashicorp.consul.resource.Tombstone.owner:type_name -> hashicorp.consul.resource.ID + 3, // 14: hashicorp.consul.resource.ReadRequest.id:type_name -> hashicorp.consul.resource.ID + 4, // 15: hashicorp.consul.resource.ReadResponse.resource:type_name -> hashicorp.consul.resource.Resource + 1, // 16: hashicorp.consul.resource.ListRequest.type:type_name -> hashicorp.consul.resource.Type + 2, // 17: hashicorp.consul.resource.ListRequest.tenancy:type_name -> hashicorp.consul.resource.Tenancy + 4, // 18: hashicorp.consul.resource.ListResponse.resources:type_name -> hashicorp.consul.resource.Resource + 3, // 19: hashicorp.consul.resource.ListByOwnerRequest.owner:type_name -> hashicorp.consul.resource.ID + 4, // 20: hashicorp.consul.resource.ListByOwnerResponse.resources:type_name -> hashicorp.consul.resource.Resource + 4, // 21: hashicorp.consul.resource.WriteRequest.resource:type_name -> hashicorp.consul.resource.Resource + 4, // 22: hashicorp.consul.resource.WriteResponse.resource:type_name -> hashicorp.consul.resource.Resource + 3, // 23: hashicorp.consul.resource.WriteStatusRequest.id:type_name -> hashicorp.consul.resource.ID + 5, // 24: hashicorp.consul.resource.WriteStatusRequest.status:type_name -> hashicorp.consul.resource.Status + 4, // 25: hashicorp.consul.resource.WriteStatusResponse.resource:type_name -> hashicorp.consul.resource.Resource + 3, // 26: hashicorp.consul.resource.DeleteRequest.id:type_name -> hashicorp.consul.resource.ID + 1, // 27: hashicorp.consul.resource.WatchListRequest.type:type_name -> hashicorp.consul.resource.Type + 2, // 28: hashicorp.consul.resource.WatchListRequest.tenancy:type_name -> hashicorp.consul.resource.Tenancy + 27, // 29: hashicorp.consul.resource.WatchEvent.upsert:type_name -> hashicorp.consul.resource.WatchEvent.Upsert + 28, // 30: hashicorp.consul.resource.WatchEvent.delete:type_name -> hashicorp.consul.resource.WatchEvent.Delete + 29, // 31: hashicorp.consul.resource.WatchEvent.end_of_snapshot:type_name -> hashicorp.consul.resource.WatchEvent.EndOfSnapshot + 4, // 32: hashicorp.consul.resource.MutateAndValidateRequest.resource:type_name -> hashicorp.consul.resource.Resource + 4, // 33: hashicorp.consul.resource.MutateAndValidateResponse.resource:type_name -> hashicorp.consul.resource.Resource + 5, // 34: hashicorp.consul.resource.Resource.StatusEntry.value:type_name -> hashicorp.consul.resource.Status + 4, // 35: hashicorp.consul.resource.WatchEvent.Upsert.resource:type_name -> hashicorp.consul.resource.Resource + 4, // 36: hashicorp.consul.resource.WatchEvent.Delete.resource:type_name -> hashicorp.consul.resource.Resource + 9, // 37: hashicorp.consul.resource.ResourceService.Read:input_type -> hashicorp.consul.resource.ReadRequest + 15, // 38: hashicorp.consul.resource.ResourceService.Write:input_type -> hashicorp.consul.resource.WriteRequest + 17, // 39: hashicorp.consul.resource.ResourceService.WriteStatus:input_type -> hashicorp.consul.resource.WriteStatusRequest + 11, // 40: hashicorp.consul.resource.ResourceService.List:input_type -> hashicorp.consul.resource.ListRequest + 13, // 41: hashicorp.consul.resource.ResourceService.ListByOwner:input_type -> hashicorp.consul.resource.ListByOwnerRequest + 19, // 42: hashicorp.consul.resource.ResourceService.Delete:input_type -> hashicorp.consul.resource.DeleteRequest + 21, // 43: hashicorp.consul.resource.ResourceService.WatchList:input_type -> hashicorp.consul.resource.WatchListRequest + 23, // 44: hashicorp.consul.resource.ResourceService.MutateAndValidate:input_type -> hashicorp.consul.resource.MutateAndValidateRequest + 10, // 45: hashicorp.consul.resource.ResourceService.Read:output_type -> hashicorp.consul.resource.ReadResponse + 16, // 46: hashicorp.consul.resource.ResourceService.Write:output_type -> hashicorp.consul.resource.WriteResponse + 18, // 47: hashicorp.consul.resource.ResourceService.WriteStatus:output_type -> hashicorp.consul.resource.WriteStatusResponse + 12, // 48: hashicorp.consul.resource.ResourceService.List:output_type -> hashicorp.consul.resource.ListResponse + 14, // 49: hashicorp.consul.resource.ResourceService.ListByOwner:output_type -> hashicorp.consul.resource.ListByOwnerResponse + 20, // 50: hashicorp.consul.resource.ResourceService.Delete:output_type -> hashicorp.consul.resource.DeleteResponse + 22, // 51: hashicorp.consul.resource.ResourceService.WatchList:output_type -> hashicorp.consul.resource.WatchEvent + 24, // 52: hashicorp.consul.resource.ResourceService.MutateAndValidate:output_type -> hashicorp.consul.resource.MutateAndValidateResponse + 45, // [45:53] is the sub-list for method output_type + 37, // [37:45] is the sub-list for method input_type + 37, // [37:37] is the sub-list for extension type_name + 37, // [37:37] is the sub-list for extension extendee + 0, // [0:37] is the sub-list for field type_name } func init() { file_pbresource_resource_proto_init() } @@ -2193,14 +2438,79 @@ func file_pbresource_resource_proto_init() { return nil } } + file_pbresource_resource_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MutateAndValidateRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbresource_resource_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MutateAndValidateResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbresource_resource_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WatchEvent_Upsert); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbresource_resource_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WatchEvent_Delete); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pbresource_resource_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WatchEvent_EndOfSnapshot); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_pbresource_resource_proto_msgTypes[21].OneofWrappers = []interface{}{ + (*WatchEvent_Upsert_)(nil), + (*WatchEvent_Delete_)(nil), + (*WatchEvent_EndOfSnapshot_)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pbresource_resource_proto_rawDesc, - NumEnums: 2, - NumMessages: 24, + NumEnums: 1, + NumMessages: 29, NumExtensions: 0, NumServices: 1, }, diff --git a/proto-public/pbresource/resource.proto b/proto-public/pbresource/resource.proto index 9e65647587b7..29328e587aa3 100644 --- a/proto-public/pbresource/resource.proto +++ b/proto-public/pbresource/resource.proto @@ -41,13 +41,6 @@ message Tenancy { // When using the List and WatchList endpoints, provide the wildcard value "*" // to list resources across all namespaces. string namespace = 2; - - // PeerName identifies which peer the resource is imported from. - // https://developer.hashicorp.com/consul/docs/connect/cluster-peering - // - // When using the List and WatchList endpoints, provide the wildcard value "*" - // to list resources across all peers. - string peer_name = 3; } // ID uniquely identifies a resource. @@ -99,6 +92,7 @@ message Resource { string generation = 4; // Metadata contains key/value pairs of arbitrary metadata about the resource. + // "deletionTimestamp" and "finalizers" keys are reserved for internal use. map metadata = 5; // Status is used by controllers to communicate the result of attempting to @@ -350,6 +344,19 @@ service ResourceService { operation_category: OPERATION_CATEGORY_RESOURCE }; } + + // MutateAndValidate a resource. + // + // Applies a resource type's registered mutation and validation hooks to + // a resource. This is useful for filling in defaults and validating inputs before + // doing a Write. It's not a pre-requisite since the Write endpoint will also apply + // the hooks. + rpc MutateAndValidate(MutateAndValidateRequest) returns (MutateAndValidateResponse) { + option (hashicorp.consul.internal.ratelimit.spec) = { + operation_type: OPERATION_TYPE_READ, + operation_category: OPERATION_CATEGORY_RESOURCE + }; + } } // ReadRequest contains the parameters to the Read endpoint. @@ -466,24 +473,35 @@ message WatchListRequest { // WatchEvent is emitted on the WatchList stream when a resource changes. message WatchEvent { - // Operation describes the type of event. - enum Operation { - // OPERATION_UNSPECIFIED is the default/zero value. You should not see it - // in practice. - OPERATION_UNSPECIFIED = 0; - - // OPERATION_UPSERT indicates that the resource was written (i.e. created or - // updated). All events from the initial state-of-the-world will be upsert - // events. - OPERATION_UPSERT = 1; - - // OPERATION_DELETED indicates that the resource was deleted. - OPERATION_DELETE = 2; + // Upsert indicates that the resource was written (i.e. created or + // updated). All events from the initial state-of-the-world will be upsert + // events. + message Upsert { + Resource resource = 1; } - // Operation describes the type of event. - Operation operation = 1; + // Delete indicates that the resource was deleted. + message Delete { + Resource resource = 1; + } + + // EndOfSnapshot is sent to indicate that the initial snapshot events have + // been sent and future events will modify that set. + message EndOfSnapshot {} + + oneof event { + Upsert upsert = 1; + Delete delete = 2; + EndOfSnapshot end_of_snapshot = 3; + } +} - // Resource the event relates to. - Resource resource = 2; +// MutateAndValidateRequest contains the parameters to the MutateAndValidate endpoint. +message MutateAndValidateRequest { + Resource resource = 1; +} + +// MutateAndValidateResponse contains the results of calling the MutateAndValidate endpoint. +message MutateAndValidateResponse { + Resource resource = 1; } diff --git a/proto-public/pbresource/resource_cloning_grpc.pb.go b/proto-public/pbresource/resource_cloning_grpc.pb.go new file mode 100644 index 000000000000..3f278bd1fab2 --- /dev/null +++ b/proto-public/pbresource/resource_cloning_grpc.pb.go @@ -0,0 +1,135 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package pbresource + +import ( + "context" + + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +// compile-time check to ensure that the generator is implementing all +// of the grpc client interfaces methods. +var _ ResourceServiceClient = CloningResourceServiceClient{} + +// IsCloningResourceServiceClient is an interface that can be used to detect +// that a ResourceServiceClient is using the in-memory transport and has already +// been wrapped with a with a CloningResourceServiceClient. +type IsCloningResourceServiceClient interface { + IsCloningResourceServiceClient() bool +} + +// CloningResourceServiceClient implements the ResourceServiceClient interface by wrapping +// another implementation and copying all protobuf messages that pass through the client. +// This is mainly useful to wrap the an in-process client to insulate users of that +// client from having to care about potential immutability of data they receive or having +// the server implementation mutate their internal memory. +type CloningResourceServiceClient struct { + ResourceServiceClient +} + +func NewCloningResourceServiceClient(client ResourceServiceClient) ResourceServiceClient { + if cloner, ok := client.(IsCloningResourceServiceClient); ok && cloner.IsCloningResourceServiceClient() { + // prevent a double clone if the underlying client is already the cloning client. + return client + } + + return CloningResourceServiceClient{ + ResourceServiceClient: client, + } +} + +// IsCloningResourceServiceClient implements the IsCloningResourceServiceClient interface. This +// is only used to detect wrapped clients that would be double cloning data and prevent that. +func (c CloningResourceServiceClient) IsCloningResourceServiceClient() bool { + return true +} + +func (c CloningResourceServiceClient) Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (*ReadResponse, error) { + in = proto.Clone(in).(*ReadRequest) + + out, err := c.ResourceServiceClient.Read(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*ReadResponse), nil +} + +func (c CloningResourceServiceClient) Write(ctx context.Context, in *WriteRequest, opts ...grpc.CallOption) (*WriteResponse, error) { + in = proto.Clone(in).(*WriteRequest) + + out, err := c.ResourceServiceClient.Write(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*WriteResponse), nil +} + +func (c CloningResourceServiceClient) WriteStatus(ctx context.Context, in *WriteStatusRequest, opts ...grpc.CallOption) (*WriteStatusResponse, error) { + in = proto.Clone(in).(*WriteStatusRequest) + + out, err := c.ResourceServiceClient.WriteStatus(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*WriteStatusResponse), nil +} + +func (c CloningResourceServiceClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) { + in = proto.Clone(in).(*ListRequest) + + out, err := c.ResourceServiceClient.List(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*ListResponse), nil +} + +func (c CloningResourceServiceClient) ListByOwner(ctx context.Context, in *ListByOwnerRequest, opts ...grpc.CallOption) (*ListByOwnerResponse, error) { + in = proto.Clone(in).(*ListByOwnerRequest) + + out, err := c.ResourceServiceClient.ListByOwner(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*ListByOwnerResponse), nil +} + +func (c CloningResourceServiceClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) { + in = proto.Clone(in).(*DeleteRequest) + + out, err := c.ResourceServiceClient.Delete(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*DeleteResponse), nil +} + +func (c CloningResourceServiceClient) MutateAndValidate(ctx context.Context, in *MutateAndValidateRequest, opts ...grpc.CallOption) (*MutateAndValidateResponse, error) { + in = proto.Clone(in).(*MutateAndValidateRequest) + + out, err := c.ResourceServiceClient.MutateAndValidate(ctx, in) + if err != nil { + return nil, err + } + + return proto.Clone(out).(*MutateAndValidateResponse), nil +} + +func (c CloningResourceServiceClient) WatchList(ctx context.Context, in *WatchListRequest, opts ...grpc.CallOption) (ResourceService_WatchListClient, error) { + in = proto.Clone(in).(*WatchListRequest) + + st, err := c.ResourceServiceClient.WatchList(ctx, in) + if err != nil { + return nil, err + } + + return newCloningStream[*WatchEvent](st), nil +} diff --git a/proto-public/pbresource/resource_deepcopy.gen.go b/proto-public/pbresource/resource_deepcopy.gen.go index 5b81e6f9dfed..e9a0b01bc123 100644 --- a/proto-public/pbresource/resource_deepcopy.gen.go +++ b/proto-public/pbresource/resource_deepcopy.gen.go @@ -466,3 +466,108 @@ func (in *WatchEvent) DeepCopy() *WatchEvent { func (in *WatchEvent) DeepCopyInterface() interface{} { return in.DeepCopy() } + +// DeepCopyInto supports using WatchEvent_Upsert within kubernetes types, where deepcopy-gen is used. +func (in *WatchEvent_Upsert) DeepCopyInto(out *WatchEvent_Upsert) { + proto.Reset(out) + proto.Merge(out, proto.Clone(in)) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatchEvent_Upsert. Required by controller-gen. +func (in *WatchEvent_Upsert) DeepCopy() *WatchEvent_Upsert { + if in == nil { + return nil + } + out := new(WatchEvent_Upsert) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new WatchEvent_Upsert. Required by controller-gen. +func (in *WatchEvent_Upsert) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using WatchEvent_Delete within kubernetes types, where deepcopy-gen is used. +func (in *WatchEvent_Delete) DeepCopyInto(out *WatchEvent_Delete) { + proto.Reset(out) + proto.Merge(out, proto.Clone(in)) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatchEvent_Delete. Required by controller-gen. +func (in *WatchEvent_Delete) DeepCopy() *WatchEvent_Delete { + if in == nil { + return nil + } + out := new(WatchEvent_Delete) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new WatchEvent_Delete. Required by controller-gen. +func (in *WatchEvent_Delete) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using WatchEvent_EndOfSnapshot within kubernetes types, where deepcopy-gen is used. +func (in *WatchEvent_EndOfSnapshot) DeepCopyInto(out *WatchEvent_EndOfSnapshot) { + proto.Reset(out) + proto.Merge(out, proto.Clone(in)) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatchEvent_EndOfSnapshot. Required by controller-gen. +func (in *WatchEvent_EndOfSnapshot) DeepCopy() *WatchEvent_EndOfSnapshot { + if in == nil { + return nil + } + out := new(WatchEvent_EndOfSnapshot) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new WatchEvent_EndOfSnapshot. Required by controller-gen. +func (in *WatchEvent_EndOfSnapshot) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using MutateAndValidateRequest within kubernetes types, where deepcopy-gen is used. +func (in *MutateAndValidateRequest) DeepCopyInto(out *MutateAndValidateRequest) { + proto.Reset(out) + proto.Merge(out, proto.Clone(in)) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MutateAndValidateRequest. Required by controller-gen. +func (in *MutateAndValidateRequest) DeepCopy() *MutateAndValidateRequest { + if in == nil { + return nil + } + out := new(MutateAndValidateRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new MutateAndValidateRequest. Required by controller-gen. +func (in *MutateAndValidateRequest) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using MutateAndValidateResponse within kubernetes types, where deepcopy-gen is used. +func (in *MutateAndValidateResponse) DeepCopyInto(out *MutateAndValidateResponse) { + proto.Reset(out) + proto.Merge(out, proto.Clone(in)) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MutateAndValidateResponse. Required by controller-gen. +func (in *MutateAndValidateResponse) DeepCopy() *MutateAndValidateResponse { + if in == nil { + return nil + } + out := new(MutateAndValidateResponse) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new MutateAndValidateResponse. Required by controller-gen. +func (in *MutateAndValidateResponse) DeepCopyInterface() interface{} { + return in.DeepCopy() +} diff --git a/proto-public/pbresource/resource_grpc.pb.go b/proto-public/pbresource/resource_grpc.pb.go index d15b677a270e..2def37458739 100644 --- a/proto-public/pbresource/resource_grpc.pb.go +++ b/proto-public/pbresource/resource_grpc.pb.go @@ -107,6 +107,13 @@ type ResourceServiceClient interface { // // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME WatchList(ctx context.Context, in *WatchListRequest, opts ...grpc.CallOption) (ResourceService_WatchListClient, error) + // MutateAndValidate a resource. + // + // Applies a resource type's registered mutation and validation hooks to + // a resource. This is useful for filling in defaults and validating inputs before + // doing a Write. It's not a pre-requisite since the Write endpoint will also apply + // the hooks. + MutateAndValidate(ctx context.Context, in *MutateAndValidateRequest, opts ...grpc.CallOption) (*MutateAndValidateResponse, error) } type resourceServiceClient struct { @@ -203,6 +210,15 @@ func (x *resourceServiceWatchListClient) Recv() (*WatchEvent, error) { return m, nil } +func (c *resourceServiceClient) MutateAndValidate(ctx context.Context, in *MutateAndValidateRequest, opts ...grpc.CallOption) (*MutateAndValidateResponse, error) { + out := new(MutateAndValidateResponse) + err := c.cc.Invoke(ctx, "/hashicorp.consul.resource.ResourceService/MutateAndValidate", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ResourceServiceServer is the server API for ResourceService service. // All implementations should embed UnimplementedResourceServiceServer // for forward compatibility @@ -292,6 +308,13 @@ type ResourceServiceServer interface { // // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME WatchList(*WatchListRequest, ResourceService_WatchListServer) error + // MutateAndValidate a resource. + // + // Applies a resource type's registered mutation and validation hooks to + // a resource. This is useful for filling in defaults and validating inputs before + // doing a Write. It's not a pre-requisite since the Write endpoint will also apply + // the hooks. + MutateAndValidate(context.Context, *MutateAndValidateRequest) (*MutateAndValidateResponse, error) } // UnimplementedResourceServiceServer should be embedded to have forward compatible implementations. @@ -319,6 +342,9 @@ func (UnimplementedResourceServiceServer) Delete(context.Context, *DeleteRequest func (UnimplementedResourceServiceServer) WatchList(*WatchListRequest, ResourceService_WatchListServer) error { return status.Errorf(codes.Unimplemented, "method WatchList not implemented") } +func (UnimplementedResourceServiceServer) MutateAndValidate(context.Context, *MutateAndValidateRequest) (*MutateAndValidateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method MutateAndValidate not implemented") +} // UnsafeResourceServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ResourceServiceServer will @@ -460,6 +486,24 @@ func (x *resourceServiceWatchListServer) Send(m *WatchEvent) error { return x.ServerStream.SendMsg(m) } +func _ResourceService_MutateAndValidate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MutateAndValidateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ResourceServiceServer).MutateAndValidate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/hashicorp.consul.resource.ResourceService/MutateAndValidate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ResourceServiceServer).MutateAndValidate(ctx, req.(*MutateAndValidateRequest)) + } + return interceptor(ctx, in, info, handler) +} + // ResourceService_ServiceDesc is the grpc.ServiceDesc for ResourceService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -491,6 +535,10 @@ var ResourceService_ServiceDesc = grpc.ServiceDesc{ MethodName: "Delete", Handler: _ResourceService_Delete_Handler, }, + { + MethodName: "MutateAndValidate", + Handler: _ResourceService_MutateAndValidate_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/proto-public/pbresource/resource_json.gen.go b/proto-public/pbresource/resource_json.gen.go index 80c62deba9a4..b30b535ff7ef 100644 --- a/proto-public/pbresource/resource_json.gen.go +++ b/proto-public/pbresource/resource_json.gen.go @@ -247,6 +247,61 @@ func (this *WatchEvent) UnmarshalJSON(b []byte) error { return ResourceUnmarshaler.Unmarshal(b, this) } +// MarshalJSON is a custom marshaler for WatchEvent_Upsert +func (this *WatchEvent_Upsert) MarshalJSON() ([]byte, error) { + str, err := ResourceMarshaler.Marshal(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for WatchEvent_Upsert +func (this *WatchEvent_Upsert) UnmarshalJSON(b []byte) error { + return ResourceUnmarshaler.Unmarshal(b, this) +} + +// MarshalJSON is a custom marshaler for WatchEvent_Delete +func (this *WatchEvent_Delete) MarshalJSON() ([]byte, error) { + str, err := ResourceMarshaler.Marshal(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for WatchEvent_Delete +func (this *WatchEvent_Delete) UnmarshalJSON(b []byte) error { + return ResourceUnmarshaler.Unmarshal(b, this) +} + +// MarshalJSON is a custom marshaler for WatchEvent_EndOfSnapshot +func (this *WatchEvent_EndOfSnapshot) MarshalJSON() ([]byte, error) { + str, err := ResourceMarshaler.Marshal(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for WatchEvent_EndOfSnapshot +func (this *WatchEvent_EndOfSnapshot) UnmarshalJSON(b []byte) error { + return ResourceUnmarshaler.Unmarshal(b, this) +} + +// MarshalJSON is a custom marshaler for MutateAndValidateRequest +func (this *MutateAndValidateRequest) MarshalJSON() ([]byte, error) { + str, err := ResourceMarshaler.Marshal(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for MutateAndValidateRequest +func (this *MutateAndValidateRequest) UnmarshalJSON(b []byte) error { + return ResourceUnmarshaler.Unmarshal(b, this) +} + +// MarshalJSON is a custom marshaler for MutateAndValidateResponse +func (this *MutateAndValidateResponse) MarshalJSON() ([]byte, error) { + str, err := ResourceMarshaler.Marshal(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for MutateAndValidateResponse +func (this *MutateAndValidateResponse) UnmarshalJSON(b []byte) error { + return ResourceUnmarshaler.Unmarshal(b, this) +} + var ( ResourceMarshaler = &protojson.MarshalOptions{} ResourceUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} diff --git a/proto-public/pbserverdiscovery/cloning_stream.pb.go b/proto-public/pbserverdiscovery/cloning_stream.pb.go new file mode 100644 index 000000000000..4acd4356c4d1 --- /dev/null +++ b/proto-public/pbserverdiscovery/cloning_stream.pb.go @@ -0,0 +1,31 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package pbserverdiscovery + +import ( + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +type serverStream[T proto.Message] interface { + Recv() (T, error) + grpc.ClientStream +} + +type cloningStream[T proto.Message] struct { + serverStream[T] +} + +func newCloningStream[T proto.Message](stream serverStream[T]) cloningStream[T] { + return cloningStream[T]{serverStream: stream} +} + +func (st cloningStream[T]) Recv() (T, error) { + var zero T + val, err := st.serverStream.Recv() + if err != nil { + return zero, err + } + + return proto.Clone(val).(T), nil +} diff --git a/proto-public/pbserverdiscovery/serverdiscovery.pb.go b/proto-public/pbserverdiscovery/serverdiscovery.pb.go index 37b3b592e7d8..28bdff035183 100644 --- a/proto-public/pbserverdiscovery/serverdiscovery.pb.go +++ b/proto-public/pbserverdiscovery/serverdiscovery.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: pbserverdiscovery/serverdiscovery.proto diff --git a/proto-public/pbserverdiscovery/serverdiscovery_cloning_grpc.pb.go b/proto-public/pbserverdiscovery/serverdiscovery_cloning_grpc.pb.go new file mode 100644 index 000000000000..ed8d3173d27f --- /dev/null +++ b/proto-public/pbserverdiscovery/serverdiscovery_cloning_grpc.pb.go @@ -0,0 +1,58 @@ +// Code generated by protoc-gen-grpc-inmem. DO NOT EDIT. + +package pbserverdiscovery + +import ( + "context" + + grpc "google.golang.org/grpc" + "google.golang.org/protobuf/proto" +) + +// compile-time check to ensure that the generator is implementing all +// of the grpc client interfaces methods. +var _ ServerDiscoveryServiceClient = CloningServerDiscoveryServiceClient{} + +// IsCloningServerDiscoveryServiceClient is an interface that can be used to detect +// that a ServerDiscoveryServiceClient is using the in-memory transport and has already +// been wrapped with a with a CloningServerDiscoveryServiceClient. +type IsCloningServerDiscoveryServiceClient interface { + IsCloningServerDiscoveryServiceClient() bool +} + +// CloningServerDiscoveryServiceClient implements the ServerDiscoveryServiceClient interface by wrapping +// another implementation and copying all protobuf messages that pass through the client. +// This is mainly useful to wrap the an in-process client to insulate users of that +// client from having to care about potential immutability of data they receive or having +// the server implementation mutate their internal memory. +type CloningServerDiscoveryServiceClient struct { + ServerDiscoveryServiceClient +} + +func NewCloningServerDiscoveryServiceClient(client ServerDiscoveryServiceClient) ServerDiscoveryServiceClient { + if cloner, ok := client.(IsCloningServerDiscoveryServiceClient); ok && cloner.IsCloningServerDiscoveryServiceClient() { + // prevent a double clone if the underlying client is already the cloning client. + return client + } + + return CloningServerDiscoveryServiceClient{ + ServerDiscoveryServiceClient: client, + } +} + +// IsCloningServerDiscoveryServiceClient implements the IsCloningServerDiscoveryServiceClient interface. This +// is only used to detect wrapped clients that would be double cloning data and prevent that. +func (c CloningServerDiscoveryServiceClient) IsCloningServerDiscoveryServiceClient() bool { + return true +} + +func (c CloningServerDiscoveryServiceClient) WatchServers(ctx context.Context, in *WatchServersRequest, opts ...grpc.CallOption) (ServerDiscoveryService_WatchServersClient, error) { + in = proto.Clone(in).(*WatchServersRequest) + + st, err := c.ServerDiscoveryServiceClient.WatchServers(ctx, in) + if err != nil { + return nil, err + } + + return newCloningStream[*WatchServersResponse](st), nil +} diff --git a/proto-public/pbtenancy/v2beta1/namespace.pb.binary.go b/proto-public/pbtenancy/v2beta1/namespace.pb.binary.go deleted file mode 100644 index 1884a0943b0d..000000000000 --- a/proto-public/pbtenancy/v2beta1/namespace.pb.binary.go +++ /dev/null @@ -1,18 +0,0 @@ -// Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: pbtenancy/v2beta1/namespace.proto - -package tenancyv2beta1 - -import ( - "google.golang.org/protobuf/proto" -) - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *Namespace) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *Namespace) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto-public/pbtenancy/v2beta1/namespace.pb.go b/proto-public/pbtenancy/v2beta1/namespace.pb.go deleted file mode 100644 index 2118814a68a7..000000000000 --- a/proto-public/pbtenancy/v2beta1/namespace.pb.go +++ /dev/null @@ -1,171 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc (unknown) -// source: pbtenancy/v2beta1/namespace.proto - -package tenancyv2beta1 - -import ( - _ "github.com/hashicorp/consul/proto-public/pbresource" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// The name of the Namespace is in the outer Resource.ID.Name. -// It must be unique within a partition and must be a -// DNS hostname. There are also other reserved names that may not be used. -type Namespace struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Description is where the user puts any information they want - // about the namespace. It is not used internally. - Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` -} - -func (x *Namespace) Reset() { - *x = Namespace{} - if protoimpl.UnsafeEnabled { - mi := &file_pbtenancy_v2beta1_namespace_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Namespace) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Namespace) ProtoMessage() {} - -func (x *Namespace) ProtoReflect() protoreflect.Message { - mi := &file_pbtenancy_v2beta1_namespace_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Namespace.ProtoReflect.Descriptor instead. -func (*Namespace) Descriptor() ([]byte, []int) { - return file_pbtenancy_v2beta1_namespace_proto_rawDescGZIP(), []int{0} -} - -func (x *Namespace) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -var File_pbtenancy_v2beta1_namespace_proto protoreflect.FileDescriptor - -var file_pbtenancy_v2beta1_namespace_proto_rawDesc = []byte{ - 0x0a, 0x21, 0x70, 0x62, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2f, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x20, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2e, 0x76, 0x32, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x35, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x02, 0x42, 0xa4, 0x02, 0x0a, 0x24, 0x63, - 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2e, 0x76, 0x32, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x42, 0x0e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, - 0x70, 0x62, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x3b, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, - 0xa2, 0x02, 0x03, 0x48, 0x43, 0x54, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, - 0x79, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x54, 0x65, 0x6e, - 0x61, 0x6e, 0x63, 0x79, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2c, 0x48, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, - 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, - 0x3a, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x79, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pbtenancy_v2beta1_namespace_proto_rawDescOnce sync.Once - file_pbtenancy_v2beta1_namespace_proto_rawDescData = file_pbtenancy_v2beta1_namespace_proto_rawDesc -) - -func file_pbtenancy_v2beta1_namespace_proto_rawDescGZIP() []byte { - file_pbtenancy_v2beta1_namespace_proto_rawDescOnce.Do(func() { - file_pbtenancy_v2beta1_namespace_proto_rawDescData = protoimpl.X.CompressGZIP(file_pbtenancy_v2beta1_namespace_proto_rawDescData) - }) - return file_pbtenancy_v2beta1_namespace_proto_rawDescData -} - -var file_pbtenancy_v2beta1_namespace_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pbtenancy_v2beta1_namespace_proto_goTypes = []interface{}{ - (*Namespace)(nil), // 0: hashicorp.consul.tenancy.v2beta1.Namespace -} -var file_pbtenancy_v2beta1_namespace_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pbtenancy_v2beta1_namespace_proto_init() } -func file_pbtenancy_v2beta1_namespace_proto_init() { - if File_pbtenancy_v2beta1_namespace_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pbtenancy_v2beta1_namespace_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Namespace); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pbtenancy_v2beta1_namespace_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pbtenancy_v2beta1_namespace_proto_goTypes, - DependencyIndexes: file_pbtenancy_v2beta1_namespace_proto_depIdxs, - MessageInfos: file_pbtenancy_v2beta1_namespace_proto_msgTypes, - }.Build() - File_pbtenancy_v2beta1_namespace_proto = out.File - file_pbtenancy_v2beta1_namespace_proto_rawDesc = nil - file_pbtenancy_v2beta1_namespace_proto_goTypes = nil - file_pbtenancy_v2beta1_namespace_proto_depIdxs = nil -} diff --git a/proto-public/pbtenancy/v2beta1/namespace.proto b/proto-public/pbtenancy/v2beta1/namespace.proto deleted file mode 100644 index 6d4a739f6e21..000000000000 --- a/proto-public/pbtenancy/v2beta1/namespace.proto +++ /dev/null @@ -1,16 +0,0 @@ -syntax = "proto3"; - -package hashicorp.consul.tenancy.v2beta1; - -import "pbresource/annotations.proto"; - -// The name of the Namespace is in the outer Resource.ID.Name. -// It must be unique within a partition and must be a -// DNS hostname. There are also other reserved names that may not be used. -message Namespace { - option (hashicorp.consul.resource.spec) = {scope: SCOPE_PARTITION}; - - // Description is where the user puts any information they want - // about the namespace. It is not used internally. - string description = 1; -} diff --git a/proto-public/pbtenancy/v2beta1/namespace_deepcopy.gen.go b/proto-public/pbtenancy/v2beta1/namespace_deepcopy.gen.go deleted file mode 100644 index 2384004c869f..000000000000 --- a/proto-public/pbtenancy/v2beta1/namespace_deepcopy.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by protoc-gen-deepcopy. DO NOT EDIT. -package tenancyv2beta1 - -import ( - proto "google.golang.org/protobuf/proto" -) - -// DeepCopyInto supports using Namespace within kubernetes types, where deepcopy-gen is used. -func (in *Namespace) DeepCopyInto(out *Namespace) { - proto.Reset(out) - proto.Merge(out, proto.Clone(in)) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Namespace. Required by controller-gen. -func (in *Namespace) DeepCopy() *Namespace { - if in == nil { - return nil - } - out := new(Namespace) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Namespace. Required by controller-gen. -func (in *Namespace) DeepCopyInterface() interface{} { - return in.DeepCopy() -} diff --git a/proto-public/pbtenancy/v2beta1/namespace_json.gen.go b/proto-public/pbtenancy/v2beta1/namespace_json.gen.go deleted file mode 100644 index 4ad7901c16c3..000000000000 --- a/proto-public/pbtenancy/v2beta1/namespace_json.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-json-shim. DO NOT EDIT. -package tenancyv2beta1 - -import ( - protojson "google.golang.org/protobuf/encoding/protojson" -) - -// MarshalJSON is a custom marshaler for Namespace -func (this *Namespace) MarshalJSON() ([]byte, error) { - str, err := NamespaceMarshaler.Marshal(this) - return []byte(str), err -} - -// UnmarshalJSON is a custom unmarshaler for Namespace -func (this *Namespace) UnmarshalJSON(b []byte) error { - return NamespaceUnmarshaler.Unmarshal(b, this) -} - -var ( - NamespaceMarshaler = &protojson.MarshalOptions{} - NamespaceUnmarshaler = &protojson.UnmarshalOptions{DiscardUnknown: false} -) diff --git a/proto-public/pbtenancy/v2beta1/resource_types.gen.go b/proto-public/pbtenancy/v2beta1/resource_types.gen.go deleted file mode 100644 index b0c304040823..000000000000 --- a/proto-public/pbtenancy/v2beta1/resource_types.gen.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by protoc-gen-resource-types. DO NOT EDIT. - -package tenancyv2beta1 - -import ( - "github.com/hashicorp/consul/proto-public/pbresource" -) - -const ( - GroupName = "tenancy" - Version = "v2beta1" - - NamespaceKind = "Namespace" -) - -var ( - NamespaceType = &pbresource.Type{ - Group: GroupName, - GroupVersion: Version, - Kind: NamespaceKind, - } -) diff --git a/proto/buf.gen.yaml b/proto/buf.gen.yaml index efb9703b10ba..4f599505ba64 100644 --- a/proto/buf.gen.yaml +++ b/proto/buf.gen.yaml @@ -26,3 +26,8 @@ plugins: out: . opt: - paths=source_relative + - name: resource-types + out: . + opt: + - paths=source_relative + strategy: all diff --git a/proto/private/pbacl/acl.pb.go b/proto/private/pbacl/acl.pb.go index f6aa5c3418cf..323aa44cb5a8 100644 --- a/proto/private/pbacl/acl.pb.go +++ b/proto/private/pbacl/acl.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbacl/acl.proto diff --git a/proto/private/pbautoconf/auto_config.pb.go b/proto/private/pbautoconf/auto_config.pb.go index a9b4c2c89168..f68f679255c0 100644 --- a/proto/private/pbautoconf/auto_config.pb.go +++ b/proto/private/pbautoconf/auto_config.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbautoconf/auto_config.proto diff --git a/proto/private/pbcommon/common.pb.go b/proto/private/pbcommon/common.pb.go index fc6928184132..cd6dbe1d3a31 100644 --- a/proto/private/pbcommon/common.pb.go +++ b/proto/private/pbcommon/common.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbcommon/common.proto diff --git a/proto/private/pbconfig/config.pb.go b/proto/private/pbconfig/config.pb.go index ce8e43c7ce91..06f53e7edcf0 100644 --- a/proto/private/pbconfig/config.pb.go +++ b/proto/private/pbconfig/config.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbconfig/config.proto diff --git a/proto/private/pbconfigentry/config_entry.gen.go b/proto/private/pbconfigentry/config_entry.gen.go index 6f9b53e01db7..bfd258249b39 100644 --- a/proto/private/pbconfigentry/config_entry.gen.go +++ b/proto/private/pbconfigentry/config_entry.gen.go @@ -20,6 +20,7 @@ func APIGatewayToStructs(s *APIGateway, t *structs.APIGatewayConfigEntry) { StatusToStructs(s.Status, &t.Status) } t.Meta = s.Meta + t.Hash = s.Hash } func APIGatewayFromStructs(t *structs.APIGatewayConfigEntry, s *APIGateway) { if s == nil { @@ -41,6 +42,7 @@ func APIGatewayFromStructs(t *structs.APIGatewayConfigEntry, s *APIGateway) { s.Status = &x } s.Meta = t.Meta + s.Hash = t.Hash } func APIGatewayListenerToStructs(s *APIGatewayListener, t *structs.APIGatewayListener) { if s == nil { @@ -146,7 +148,9 @@ func BoundAPIGatewayToStructs(s *BoundAPIGateway, t *structs.BoundAPIGatewayConf } } } + t.Services = serviceRefsToStructs(s.Services) t.Meta = s.Meta + t.Hash = s.Hash } func BoundAPIGatewayFromStructs(t *structs.BoundAPIGatewayConfigEntry, s *BoundAPIGateway) { if s == nil { @@ -162,7 +166,9 @@ func BoundAPIGatewayFromStructs(t *structs.BoundAPIGatewayConfigEntry, s *BoundA } } } + s.Services = serviceRefFromStructs(t.Services) s.Meta = t.Meta + s.Hash = t.Hash } func BoundAPIGatewayListenerToStructs(s *BoundAPIGatewayListener, t *structs.BoundAPIGatewayListener) { if s == nil { @@ -272,6 +278,86 @@ func DestinationConfigFromStructs(t *structs.DestinationConfig, s *DestinationCo s.Addresses = t.Addresses s.Port = int32(t.Port) } +func ExportedServicesToStructs(s *ExportedServices, t *structs.ExportedServicesConfigEntry) { + if s == nil { + return + } + { + t.Services = make([]structs.ExportedService, len(s.Services)) + for i := range s.Services { + if s.Services[i] != nil { + ExportedServicesServiceToStructs(s.Services[i], &t.Services[i]) + } + } + } + t.Meta = s.Meta + t.Hash = s.Hash +} +func ExportedServicesFromStructs(t *structs.ExportedServicesConfigEntry, s *ExportedServices) { + if s == nil { + return + } + { + s.Services = make([]*ExportedServicesService, len(t.Services)) + for i := range t.Services { + { + var x ExportedServicesService + ExportedServicesServiceFromStructs(&t.Services[i], &x) + s.Services[i] = &x + } + } + } + s.Meta = t.Meta + s.Hash = t.Hash +} +func ExportedServicesConsumerToStructs(s *ExportedServicesConsumer, t *structs.ServiceConsumer) { + if s == nil { + return + } + t.Partition = s.Partition + t.Peer = s.Peer + t.SamenessGroup = s.SamenessGroup +} +func ExportedServicesConsumerFromStructs(t *structs.ServiceConsumer, s *ExportedServicesConsumer) { + if s == nil { + return + } + s.Partition = t.Partition + s.Peer = t.Peer + s.SamenessGroup = t.SamenessGroup +} +func ExportedServicesServiceToStructs(s *ExportedServicesService, t *structs.ExportedService) { + if s == nil { + return + } + t.Name = s.Name + t.Namespace = s.Namespace + { + t.Consumers = make([]structs.ServiceConsumer, len(s.Consumers)) + for i := range s.Consumers { + if s.Consumers[i] != nil { + ExportedServicesConsumerToStructs(s.Consumers[i], &t.Consumers[i]) + } + } + } +} +func ExportedServicesServiceFromStructs(t *structs.ExportedService, s *ExportedServicesService) { + if s == nil { + return + } + s.Name = t.Name + s.Namespace = t.Namespace + { + s.Consumers = make([]*ExportedServicesConsumer, len(t.Consumers)) + for i := range t.Consumers { + { + var x ExportedServicesConsumer + ExportedServicesConsumerFromStructs(&t.Consumers[i], &x) + s.Consumers[i] = &x + } + } + } +} func ExposeConfigToStructs(s *ExposeConfig, t *structs.ExposeConfig) { if s == nil { return @@ -322,6 +408,24 @@ func ExposePathFromStructs(t *structs.ExposePath, s *ExposePath) { s.Protocol = t.Protocol s.ParsedFromCheck = t.ParsedFromCheck } +func FileSystemCertificateToStructs(s *FileSystemCertificate, t *structs.FileSystemCertificateConfigEntry) { + if s == nil { + return + } + t.Certificate = s.Certificate + t.PrivateKey = s.PrivateKey + t.Meta = s.Meta + t.Hash = s.Hash +} +func FileSystemCertificateFromStructs(t *structs.FileSystemCertificateConfigEntry, s *FileSystemCertificate) { + if s == nil { + return + } + s.Certificate = t.Certificate + s.PrivateKey = t.PrivateKey + s.Meta = t.Meta + s.Hash = t.Hash +} func GatewayServiceTLSConfigToStructs(s *GatewayServiceTLSConfig, t *structs.GatewayServiceTLSConfig) { if s == nil { return @@ -631,6 +735,7 @@ func HTTPRouteToStructs(s *HTTPRoute, t *structs.HTTPRouteConfigEntry) { if s.Status != nil { StatusToStructs(s.Status, &t.Status) } + t.Hash = s.Hash } func HTTPRouteFromStructs(t *structs.HTTPRouteConfigEntry, s *HTTPRoute) { if s == nil { @@ -663,6 +768,7 @@ func HTTPRouteFromStructs(t *structs.HTTPRouteConfigEntry, s *HTTPRoute) { StatusFromStructs(&t.Status, &x) s.Status = &x } + s.Hash = t.Hash } func HTTPRouteRuleToStructs(s *HTTPRouteRule, t *structs.HTTPRouteRule) { if s == nil { @@ -807,6 +913,7 @@ func IngressGatewayToStructs(s *IngressGateway, t *structs.IngressGatewayConfigE t.Defaults = &x } t.Meta = s.Meta + t.Hash = s.Hash } func IngressGatewayFromStructs(t *structs.IngressGatewayConfigEntry, s *IngressGateway) { if s == nil { @@ -833,6 +940,7 @@ func IngressGatewayFromStructs(t *structs.IngressGatewayConfigEntry, s *IngressG s.Defaults = &x } s.Meta = t.Meta + s.Hash = t.Hash } func IngressListenerToStructs(s *IngressListener, t *structs.IngressListener) { if s == nil { @@ -973,6 +1081,7 @@ func InlineCertificateToStructs(s *InlineCertificate, t *structs.InlineCertifica t.Certificate = s.Certificate t.PrivateKey = s.PrivateKey t.Meta = s.Meta + t.Hash = s.Hash } func InlineCertificateFromStructs(t *structs.InlineCertificateConfigEntry, s *InlineCertificate) { if s == nil { @@ -981,6 +1090,7 @@ func InlineCertificateFromStructs(t *structs.InlineCertificateConfigEntry, s *In s.Certificate = t.Certificate s.PrivateKey = t.PrivateKey s.Meta = t.Meta + s.Hash = t.Hash } func InstanceLevelRateLimitsToStructs(s *InstanceLevelRateLimits, t *structs.InstanceLevelRateLimits) { if s == nil { @@ -1043,8 +1153,10 @@ func IntentionHTTPHeaderPermissionToStructs(s *IntentionHTTPHeaderPermission, t t.Exact = s.Exact t.Prefix = s.Prefix t.Suffix = s.Suffix + t.Contains = s.Contains t.Regex = s.Regex t.Invert = s.Invert + t.IgnoreCase = s.IgnoreCase } func IntentionHTTPHeaderPermissionFromStructs(t *structs.IntentionHTTPHeaderPermission, s *IntentionHTTPHeaderPermission) { if s == nil { @@ -1055,8 +1167,10 @@ func IntentionHTTPHeaderPermissionFromStructs(t *structs.IntentionHTTPHeaderPerm s.Exact = t.Exact s.Prefix = t.Prefix s.Suffix = t.Suffix + s.Contains = t.Contains s.Regex = t.Regex s.Invert = t.Invert + s.IgnoreCase = t.IgnoreCase } func IntentionHTTPPermissionToStructs(s *IntentionHTTPPermission, t *structs.IntentionHTTPPermission) { if s == nil { @@ -1479,6 +1593,7 @@ func JWTProviderToStructs(s *JWTProvider, t *structs.JWTProviderConfigEntry) { t.CacheConfig = &x } t.Meta = s.Meta + t.Hash = s.Hash } func JWTProviderFromStructs(t *structs.JWTProviderConfigEntry, s *JWTProvider) { if s == nil { @@ -1513,6 +1628,7 @@ func JWTProviderFromStructs(t *structs.JWTProviderConfigEntry, s *JWTProvider) { s.CacheConfig = &x } s.Meta = t.Meta + s.Hash = t.Hash } func LeastRequestConfigToStructs(s *LeastRequestConfig, t *structs.LeastRequestConfig) { if s == nil { @@ -1598,6 +1714,7 @@ func MeshConfigToStructs(s *MeshConfig, t *structs.MeshConfigEntry) { TransparentProxyMeshConfigToStructs(s.TransparentProxy, &t.TransparentProxy) } t.AllowEnablingPermissiveMutualTLS = s.AllowEnablingPermissiveMutualTLS + t.ValidateClusters = s.ValidateClusters if s.TLS != nil { var x structs.MeshTLSConfig MeshTLSConfigToStructs(s.TLS, &x) @@ -1614,6 +1731,7 @@ func MeshConfigToStructs(s *MeshConfig, t *structs.MeshConfigEntry) { t.Peering = &x } t.Meta = s.Meta + t.Hash = s.Hash } func MeshConfigFromStructs(t *structs.MeshConfigEntry, s *MeshConfig) { if s == nil { @@ -1625,6 +1743,7 @@ func MeshConfigFromStructs(t *structs.MeshConfigEntry, s *MeshConfig) { s.TransparentProxy = &x } s.AllowEnablingPermissiveMutualTLS = t.AllowEnablingPermissiveMutualTLS + s.ValidateClusters = t.ValidateClusters if t.TLS != nil { var x MeshTLSConfig MeshTLSConfigFromStructs(t.TLS, &x) @@ -1641,6 +1760,27 @@ func MeshConfigFromStructs(t *structs.MeshConfigEntry, s *MeshConfig) { s.Peering = &x } s.Meta = t.Meta + s.Hash = t.Hash +} +func MeshDirectionalHTTPConfigToStructs(s *MeshDirectionalHTTPConfig, t *structs.MeshDirectionalHTTPConfig) { + if s == nil { + return + } + if s.RequestNormalization != nil { + var x structs.RequestNormalizationMeshConfig + RequestNormalizationMeshConfigToStructs(s.RequestNormalization, &x) + t.RequestNormalization = &x + } +} +func MeshDirectionalHTTPConfigFromStructs(t *structs.MeshDirectionalHTTPConfig, s *MeshDirectionalHTTPConfig) { + if s == nil { + return + } + if t.RequestNormalization != nil { + var x RequestNormalizationMeshConfig + RequestNormalizationMeshConfigFromStructs(t.RequestNormalization, &x) + s.RequestNormalization = &x + } } func MeshDirectionalTLSConfigToStructs(s *MeshDirectionalTLSConfig, t *structs.MeshDirectionalTLSConfig) { if s == nil { @@ -1675,12 +1815,22 @@ func MeshHTTPConfigToStructs(s *MeshHTTPConfig, t *structs.MeshHTTPConfig) { return } t.SanitizeXForwardedClientCert = s.SanitizeXForwardedClientCert + if s.Incoming != nil { + var x structs.MeshDirectionalHTTPConfig + MeshDirectionalHTTPConfigToStructs(s.Incoming, &x) + t.Incoming = &x + } } func MeshHTTPConfigFromStructs(t *structs.MeshHTTPConfig, s *MeshHTTPConfig) { if s == nil { return } s.SanitizeXForwardedClientCert = t.SanitizeXForwardedClientCert + if t.Incoming != nil { + var x MeshDirectionalHTTPConfig + MeshDirectionalHTTPConfigFromStructs(t.Incoming, &x) + s.Incoming = &x + } } func MeshTLSConfigToStructs(s *MeshTLSConfig, t *structs.MeshTLSConfig) { if s == nil { @@ -1800,6 +1950,24 @@ func RemoteJWKSFromStructs(t *structs.RemoteJWKS, s *RemoteJWKS) { s.JWKSCluster = &x } } +func RequestNormalizationMeshConfigToStructs(s *RequestNormalizationMeshConfig, t *structs.RequestNormalizationMeshConfig) { + if s == nil { + return + } + t.InsecureDisablePathNormalization = s.InsecureDisablePathNormalization + t.MergeSlashes = s.MergeSlashes + t.PathWithEscapedSlashesAction = pathWithEscapedSlashesActionToStructs(s.PathWithEscapedSlashesAction) + t.HeadersWithUnderscoresAction = headersWithUnderscoresActionToStructs(s.HeadersWithUnderscoresAction) +} +func RequestNormalizationMeshConfigFromStructs(t *structs.RequestNormalizationMeshConfig, s *RequestNormalizationMeshConfig) { + if s == nil { + return + } + s.InsecureDisablePathNormalization = t.InsecureDisablePathNormalization + s.MergeSlashes = t.MergeSlashes + s.PathWithEscapedSlashesAction = pathWithEscapedSlashesActionFromStructs(t.PathWithEscapedSlashesAction) + s.HeadersWithUnderscoresAction = headersWithUnderscoresActionFromStructs(t.HeadersWithUnderscoresAction) +} func ResourceReferenceToStructs(s *ResourceReference, t *structs.ResourceReference) { if s == nil { return @@ -1880,6 +2048,7 @@ func SamenessGroupToStructs(s *SamenessGroup, t *structs.SamenessGroupConfigEntr } } t.Meta = s.Meta + t.Hash = s.Hash t.EnterpriseMeta = enterpriseMetaToStructs(s.EnterpriseMeta) } func SamenessGroupFromStructs(t *structs.SamenessGroupConfigEntry, s *SamenessGroup) { @@ -1900,6 +2069,7 @@ func SamenessGroupFromStructs(t *structs.SamenessGroupConfigEntry, s *SamenessGr } } s.Meta = t.Meta + s.Hash = t.Hash s.EnterpriseMeta = enterpriseMetaFromStructs(t.EnterpriseMeta) } func SamenessGroupMemberToStructs(s *SamenessGroupMember, t *structs.SamenessGroupMember) { @@ -1954,6 +2124,7 @@ func ServiceDefaultsToStructs(s *ServiceDefaults, t *structs.ServiceConfigEntry) } t.EnvoyExtensions = EnvoyExtensionsToStructs(s.EnvoyExtensions) t.Meta = s.Meta + t.Hash = s.Hash } func ServiceDefaultsFromStructs(t *structs.ServiceConfigEntry, s *ServiceDefaults) { if s == nil { @@ -1999,6 +2170,7 @@ func ServiceDefaultsFromStructs(t *structs.ServiceConfigEntry, s *ServiceDefault } s.EnvoyExtensions = EnvoyExtensionsFromStructs(t.EnvoyExtensions) s.Meta = t.Meta + s.Hash = t.Hash } func ServiceIntentionsToStructs(s *ServiceIntentions, t *structs.ServiceIntentionsConfigEntry) { if s == nil { @@ -2020,6 +2192,7 @@ func ServiceIntentionsToStructs(s *ServiceIntentions, t *structs.ServiceIntentio t.JWT = &x } t.Meta = s.Meta + t.Hash = s.Hash } func ServiceIntentionsFromStructs(t *structs.ServiceIntentionsConfigEntry, s *ServiceIntentions) { if s == nil { @@ -2041,6 +2214,7 @@ func ServiceIntentionsFromStructs(t *structs.ServiceIntentionsConfigEntry, s *Se s.JWT = &x } s.Meta = t.Meta + s.Hash = t.Hash } func ServiceResolverToStructs(s *ServiceResolver, t *structs.ServiceResolverConfigEntry) { if s == nil { @@ -2085,6 +2259,7 @@ func ServiceResolverToStructs(s *ServiceResolver, t *structs.ServiceResolverConf t.LoadBalancer = &x } t.Meta = s.Meta + t.Hash = s.Hash } func ServiceResolverFromStructs(t *structs.ServiceResolverConfigEntry, s *ServiceResolver) { if s == nil { @@ -2133,6 +2308,7 @@ func ServiceResolverFromStructs(t *structs.ServiceResolverConfigEntry, s *Servic s.LoadBalancer = &x } s.Meta = t.Meta + s.Hash = t.Hash } func ServiceResolverFailoverToStructs(s *ServiceResolverFailover, t *structs.ServiceResolverFailover) { if s == nil { @@ -2374,6 +2550,7 @@ func TCPRouteToStructs(s *TCPRoute, t *structs.TCPRouteConfigEntry) { if s.Status != nil { StatusToStructs(s.Status, &t.Status) } + t.Hash = s.Hash } func TCPRouteFromStructs(t *structs.TCPRouteConfigEntry, s *TCPRoute) { if s == nil { @@ -2405,6 +2582,7 @@ func TCPRouteFromStructs(t *structs.TCPRouteConfigEntry, s *TCPRoute) { StatusFromStructs(&t.Status, &x) s.Status = &x } + s.Hash = t.Hash } func TCPServiceToStructs(s *TCPService, t *structs.TCPService) { if s == nil { diff --git a/proto/private/pbconfigentry/config_entry.go b/proto/private/pbconfigentry/config_entry.go index 8ddfde8cccfb..1b62542d9fd5 100644 --- a/proto/private/pbconfigentry/config_entry.go +++ b/proto/private/pbconfigentry/config_entry.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/proto/private/pbcommon" "github.com/hashicorp/consul/types" ) @@ -84,6 +85,14 @@ func ConfigEntryToStructs(s *ConfigEntry) structs.ConfigEntry { pbcommon.RaftIndexToStructs(s.RaftIndex, &target.RaftIndex) pbcommon.EnterpriseMetaToStructs(s.EnterpriseMeta, &target.EnterpriseMeta) return &target + case Kind_KindFileSystemCertificate: + var target structs.FileSystemCertificateConfigEntry + target.Name = s.Name + + FileSystemCertificateToStructs(s.GetFileSystemCertificate(), &target) + pbcommon.RaftIndexToStructs(s.RaftIndex, &target.RaftIndex) + pbcommon.EnterpriseMetaToStructs(s.EnterpriseMeta, &target.EnterpriseMeta) + return &target case Kind_KindInlineCertificate: var target structs.InlineCertificateConfigEntry target.Name = s.Name @@ -116,6 +125,14 @@ func ConfigEntryToStructs(s *ConfigEntry) structs.ConfigEntry { pbcommon.RaftIndexToStructs(s.RaftIndex, &target.RaftIndex) pbcommon.EnterpriseMetaToStructs(s.EnterpriseMeta, &target.EnterpriseMeta) return &target + case Kind_KindExportedServices: + var target structs.ExportedServicesConfigEntry + target.Name = s.Name + + ExportedServicesToStructs(s.GetExportedServices(), &target) + pbcommon.RaftIndexToStructs(s.RaftIndex, &target.RaftIndex) + pbcommon.EnterpriseMetaToStructs(s.EnterpriseMeta, &target.EnterpriseMeta) + return &target default: panic(fmt.Sprintf("unable to convert ConfigEntry of kind %s to structs", s.Kind)) } @@ -204,6 +221,14 @@ func ConfigEntryFromStructs(s structs.ConfigEntry) *ConfigEntry { configEntry.Entry = &ConfigEntry_HTTPRoute{ HTTPRoute: &route, } + case *structs.FileSystemCertificateConfigEntry: + var cert FileSystemCertificate + FileSystemCertificateFromStructs(v, &cert) + + configEntry.Kind = Kind_KindFileSystemCertificate + configEntry.Entry = &ConfigEntry_FileSystemCertificate{ + FileSystemCertificate: &cert, + } case *structs.InlineCertificateConfigEntry: var cert InlineCertificate InlineCertificateFromStructs(v, &cert) @@ -227,6 +252,14 @@ func ConfigEntryFromStructs(s structs.ConfigEntry) *ConfigEntry { configEntry.Entry = &ConfigEntry_JWTProvider{ JWTProvider: &jwtProvider, } + case *structs.ExportedServicesConfigEntry: + var es ExportedServices + ExportedServicesFromStructs(v, &es) + + configEntry.Kind = Kind_KindExportedServices + configEntry.Entry = &ConfigEntry_ExportedServices{ + ExportedServices: &es, + } default: panic(fmt.Sprintf("unable to convert %T to proto", s)) } @@ -258,6 +291,66 @@ func cipherSuitesFromStructs(cs []types.TLSCipherSuite) []string { return cipherSuites } +func pathWithEscapedSlashesActionFromStructs(a structs.PathWithEscapedSlashesAction) PathWithEscapedSlashesAction { + switch a { + case structs.PathWithEscapedSlashesActionDefault: + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionDefault + case structs.PathWithEscapedSlashesActionKeep: + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionKeep + case structs.PathWithEscapedSlashesActionReject: + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionReject + case structs.PathWithEscapedSlashesActionUnescapeAndRedirect: + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionUnescapeAndRedirect + case structs.PathWithEscapedSlashesActionUnescapeAndForward: + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionUnescapeAndForward + default: + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionDefault + } +} + +func pathWithEscapedSlashesActionToStructs(a PathWithEscapedSlashesAction) structs.PathWithEscapedSlashesAction { + switch a { + case PathWithEscapedSlashesAction_PathWithEscapedSlashesActionDefault: + return structs.PathWithEscapedSlashesActionDefault + case PathWithEscapedSlashesAction_PathWithEscapedSlashesActionKeep: + return structs.PathWithEscapedSlashesActionKeep + case PathWithEscapedSlashesAction_PathWithEscapedSlashesActionReject: + return structs.PathWithEscapedSlashesActionReject + case PathWithEscapedSlashesAction_PathWithEscapedSlashesActionUnescapeAndRedirect: + return structs.PathWithEscapedSlashesActionUnescapeAndRedirect + case PathWithEscapedSlashesAction_PathWithEscapedSlashesActionUnescapeAndForward: + return structs.PathWithEscapedSlashesActionUnescapeAndForward + default: + return structs.PathWithEscapedSlashesActionDefault + } +} + +func headersWithUnderscoresActionFromStructs(a structs.HeadersWithUnderscoresAction) HeadersWithUnderscoresAction { + switch a { + case structs.HeadersWithUnderscoresActionAllow: + return HeadersWithUnderscoresAction_HeadersWithUnderscoresActionAllow + case structs.HeadersWithUnderscoresActionRejectRequest: + return HeadersWithUnderscoresAction_HeadersWithUnderscoresActionRejectRequest + case structs.HeadersWithUnderscoresActionDropHeader: + return HeadersWithUnderscoresAction_HeadersWithUnderscoresActionDropHeader + default: + return HeadersWithUnderscoresAction_HeadersWithUnderscoresActionAllow + } +} + +func headersWithUnderscoresActionToStructs(a HeadersWithUnderscoresAction) structs.HeadersWithUnderscoresAction { + switch a { + case HeadersWithUnderscoresAction_HeadersWithUnderscoresActionAllow: + return structs.HeadersWithUnderscoresActionAllow + case HeadersWithUnderscoresAction_HeadersWithUnderscoresActionRejectRequest: + return structs.HeadersWithUnderscoresActionRejectRequest + case HeadersWithUnderscoresAction_HeadersWithUnderscoresActionDropHeader: + return structs.HeadersWithUnderscoresActionDropHeader + default: + return structs.HeadersWithUnderscoresActionAllow + } +} + func enterpriseMetaToStructs(m *pbcommon.EnterpriseMeta) acl.EnterpriseMeta { var entMeta acl.EnterpriseMeta pbcommon.EnterpriseMetaToStructs(m, &entMeta) @@ -572,3 +665,49 @@ func httpQueryMatchToStructs(a HTTPQueryMatchType) structs.HTTPQueryMatchType { return structs.HTTPQueryMatchExact } } + +// mog: func-to=serviceRefsToStructs func-from=serviceRefFromStructs +func serviceRefsToStructs(a map[string]*ListOfResourceReference) structs.ServiceRouteReferences { + m := make(structs.ServiceRouteReferences, len(a)) + + for key, refs := range a { + serviceName := structs.ServiceNameFromString(key) + m[serviceName] = make([]structs.ResourceReference, 0, len(refs.Ref)) + for _, ref := range refs.Ref { + structsRef := structs.ResourceReference{} + ResourceReferenceToStructs(ref, &structsRef) + m[serviceName] = append(m[serviceName], structsRef) + } + } + return m +} + +func serviceRefFromStructs(a structs.ServiceRouteReferences) map[string]*ListOfResourceReference { + m := make(map[string]*ListOfResourceReference, len(a)) + + for serviceName, refs := range a { + name := serviceName.String() + m[name] = &ListOfResourceReference{Ref: make([]*ResourceReference, len(refs))} + for _, ref := range refs { + resourceRef := &ResourceReference{} + ResourceReferenceFromStructs(&ref, resourceRef) + m[name].Ref = append(m[name].Ref, resourceRef) + } + } + return m +} + +func (r *ResolvedExportedService) ToAPI() *api.ResolvedExportedService { + var t api.ResolvedExportedService + + t.Service = r.Service + if r.EnterpriseMeta != nil { + t.Namespace = r.EnterpriseMeta.Namespace + t.Partition = r.EnterpriseMeta.Partition + } + + t.Consumers.Peers = r.Consumers.Peers + t.Consumers.Partitions = r.Consumers.Partitions + + return &t +} diff --git a/proto/private/pbconfigentry/config_entry.pb.binary.go b/proto/private/pbconfigentry/config_entry.pb.binary.go index a1b70cabcb65..194d02a85eb3 100644 --- a/proto/private/pbconfigentry/config_entry.pb.binary.go +++ b/proto/private/pbconfigentry/config_entry.pb.binary.go @@ -7,6 +7,46 @@ import ( "google.golang.org/protobuf/proto" ) +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *GetResolvedExportedServicesRequest) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *GetResolvedExportedServicesRequest) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *GetResolvedExportedServicesResponse) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *GetResolvedExportedServicesResponse) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ResolvedExportedService) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ResolvedExportedService) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *Consumers) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *Consumers) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + // MarshalBinary implements encoding.BinaryMarshaler func (msg *ConfigEntry) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) @@ -67,6 +107,16 @@ func (msg *MeshHTTPConfig) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *MeshDirectionalHTTPConfig) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *MeshDirectionalHTTPConfig) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + // MarshalBinary implements encoding.BinaryMarshaler func (msg *PeeringMeshConfig) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) @@ -77,6 +127,16 @@ func (msg *PeeringMeshConfig) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *RequestNormalizationMeshConfig) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *RequestNormalizationMeshConfig) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + // MarshalBinary implements encoding.BinaryMarshaler func (msg *ServiceResolver) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) @@ -597,6 +657,16 @@ func (msg *BoundAPIGateway) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ListOfResourceReference) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ListOfResourceReference) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + // MarshalBinary implements encoding.BinaryMarshaler func (msg *BoundAPIGatewayListener) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) @@ -607,6 +677,16 @@ func (msg *BoundAPIGatewayListener) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *FileSystemCertificate) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *FileSystemCertificate) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + // MarshalBinary implements encoding.BinaryMarshaler func (msg *InlineCertificate) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) @@ -956,3 +1036,33 @@ func (msg *JWTCacheConfig) MarshalBinary() ([]byte, error) { func (msg *JWTCacheConfig) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ExportedServices) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ExportedServices) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ExportedServicesService) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ExportedServicesService) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ExportedServicesConsumer) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ExportedServicesConsumer) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} diff --git a/proto/private/pbconfigentry/config_entry.pb.go b/proto/private/pbconfigentry/config_entry.pb.go index 3d68e7376389..508cdc7cfa3c 100644 --- a/proto/private/pbconfigentry/config_entry.pb.go +++ b/proto/private/pbconfigentry/config_entry.pb.go @@ -3,13 +3,14 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbconfigentry/config_entry.proto package pbconfigentry import ( + _ "github.com/hashicorp/consul/proto-public/annotations/ratelimit" pbcommon "github.com/hashicorp/consul/proto/private/pbcommon" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" @@ -29,19 +30,21 @@ const ( type Kind int32 const ( - Kind_KindUnknown Kind = 0 - Kind_KindMeshConfig Kind = 1 - Kind_KindServiceResolver Kind = 2 - Kind_KindIngressGateway Kind = 3 - Kind_KindServiceIntentions Kind = 4 - Kind_KindServiceDefaults Kind = 5 - Kind_KindInlineCertificate Kind = 6 - Kind_KindAPIGateway Kind = 7 - Kind_KindBoundAPIGateway Kind = 8 - Kind_KindHTTPRoute Kind = 9 - Kind_KindTCPRoute Kind = 10 - Kind_KindSamenessGroup Kind = 11 - Kind_KindJWTProvider Kind = 12 + Kind_KindUnknown Kind = 0 + Kind_KindMeshConfig Kind = 1 + Kind_KindServiceResolver Kind = 2 + Kind_KindIngressGateway Kind = 3 + Kind_KindServiceIntentions Kind = 4 + Kind_KindServiceDefaults Kind = 5 + Kind_KindInlineCertificate Kind = 6 + Kind_KindAPIGateway Kind = 7 + Kind_KindBoundAPIGateway Kind = 8 + Kind_KindHTTPRoute Kind = 9 + Kind_KindTCPRoute Kind = 10 + Kind_KindSamenessGroup Kind = 11 + Kind_KindJWTProvider Kind = 12 + Kind_KindExportedServices Kind = 13 + Kind_KindFileSystemCertificate Kind = 14 ) // Enum value maps for Kind. @@ -60,21 +63,25 @@ var ( 10: "KindTCPRoute", 11: "KindSamenessGroup", 12: "KindJWTProvider", + 13: "KindExportedServices", + 14: "KindFileSystemCertificate", } Kind_value = map[string]int32{ - "KindUnknown": 0, - "KindMeshConfig": 1, - "KindServiceResolver": 2, - "KindIngressGateway": 3, - "KindServiceIntentions": 4, - "KindServiceDefaults": 5, - "KindInlineCertificate": 6, - "KindAPIGateway": 7, - "KindBoundAPIGateway": 8, - "KindHTTPRoute": 9, - "KindTCPRoute": 10, - "KindSamenessGroup": 11, - "KindJWTProvider": 12, + "KindUnknown": 0, + "KindMeshConfig": 1, + "KindServiceResolver": 2, + "KindIngressGateway": 3, + "KindServiceIntentions": 4, + "KindServiceDefaults": 5, + "KindInlineCertificate": 6, + "KindAPIGateway": 7, + "KindBoundAPIGateway": 8, + "KindHTTPRoute": 9, + "KindTCPRoute": 10, + "KindSamenessGroup": 11, + "KindJWTProvider": 12, + "KindExportedServices": 13, + "KindFileSystemCertificate": 14, } ) @@ -105,6 +112,110 @@ func (Kind) EnumDescriptor() ([]byte, []int) { return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{0} } +type PathWithEscapedSlashesAction int32 + +const ( + PathWithEscapedSlashesAction_PathWithEscapedSlashesActionDefault PathWithEscapedSlashesAction = 0 + PathWithEscapedSlashesAction_PathWithEscapedSlashesActionKeep PathWithEscapedSlashesAction = 1 + PathWithEscapedSlashesAction_PathWithEscapedSlashesActionReject PathWithEscapedSlashesAction = 2 + PathWithEscapedSlashesAction_PathWithEscapedSlashesActionUnescapeAndRedirect PathWithEscapedSlashesAction = 3 + PathWithEscapedSlashesAction_PathWithEscapedSlashesActionUnescapeAndForward PathWithEscapedSlashesAction = 4 +) + +// Enum value maps for PathWithEscapedSlashesAction. +var ( + PathWithEscapedSlashesAction_name = map[int32]string{ + 0: "PathWithEscapedSlashesActionDefault", + 1: "PathWithEscapedSlashesActionKeep", + 2: "PathWithEscapedSlashesActionReject", + 3: "PathWithEscapedSlashesActionUnescapeAndRedirect", + 4: "PathWithEscapedSlashesActionUnescapeAndForward", + } + PathWithEscapedSlashesAction_value = map[string]int32{ + "PathWithEscapedSlashesActionDefault": 0, + "PathWithEscapedSlashesActionKeep": 1, + "PathWithEscapedSlashesActionReject": 2, + "PathWithEscapedSlashesActionUnescapeAndRedirect": 3, + "PathWithEscapedSlashesActionUnescapeAndForward": 4, + } +) + +func (x PathWithEscapedSlashesAction) Enum() *PathWithEscapedSlashesAction { + p := new(PathWithEscapedSlashesAction) + *p = x + return p +} + +func (x PathWithEscapedSlashesAction) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PathWithEscapedSlashesAction) Descriptor() protoreflect.EnumDescriptor { + return file_private_pbconfigentry_config_entry_proto_enumTypes[1].Descriptor() +} + +func (PathWithEscapedSlashesAction) Type() protoreflect.EnumType { + return &file_private_pbconfigentry_config_entry_proto_enumTypes[1] +} + +func (x PathWithEscapedSlashesAction) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PathWithEscapedSlashesAction.Descriptor instead. +func (PathWithEscapedSlashesAction) EnumDescriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{1} +} + +type HeadersWithUnderscoresAction int32 + +const ( + HeadersWithUnderscoresAction_HeadersWithUnderscoresActionAllow HeadersWithUnderscoresAction = 0 + HeadersWithUnderscoresAction_HeadersWithUnderscoresActionRejectRequest HeadersWithUnderscoresAction = 1 + HeadersWithUnderscoresAction_HeadersWithUnderscoresActionDropHeader HeadersWithUnderscoresAction = 2 +) + +// Enum value maps for HeadersWithUnderscoresAction. +var ( + HeadersWithUnderscoresAction_name = map[int32]string{ + 0: "HeadersWithUnderscoresActionAllow", + 1: "HeadersWithUnderscoresActionRejectRequest", + 2: "HeadersWithUnderscoresActionDropHeader", + } + HeadersWithUnderscoresAction_value = map[string]int32{ + "HeadersWithUnderscoresActionAllow": 0, + "HeadersWithUnderscoresActionRejectRequest": 1, + "HeadersWithUnderscoresActionDropHeader": 2, + } +) + +func (x HeadersWithUnderscoresAction) Enum() *HeadersWithUnderscoresAction { + p := new(HeadersWithUnderscoresAction) + *p = x + return p +} + +func (x HeadersWithUnderscoresAction) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HeadersWithUnderscoresAction) Descriptor() protoreflect.EnumDescriptor { + return file_private_pbconfigentry_config_entry_proto_enumTypes[2].Descriptor() +} + +func (HeadersWithUnderscoresAction) Type() protoreflect.EnumType { + return &file_private_pbconfigentry_config_entry_proto_enumTypes[2] +} + +func (x HeadersWithUnderscoresAction) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use HeadersWithUnderscoresAction.Descriptor instead. +func (HeadersWithUnderscoresAction) EnumDescriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{2} +} + type IntentionAction int32 const ( @@ -135,11 +246,11 @@ func (x IntentionAction) String() string { } func (IntentionAction) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[1].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[3].Descriptor() } func (IntentionAction) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[1] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[3] } func (x IntentionAction) Number() protoreflect.EnumNumber { @@ -148,7 +259,7 @@ func (x IntentionAction) Number() protoreflect.EnumNumber { // Deprecated: Use IntentionAction.Descriptor instead. func (IntentionAction) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{1} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{3} } type IntentionSourceType int32 @@ -178,11 +289,11 @@ func (x IntentionSourceType) String() string { } func (IntentionSourceType) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[2].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[4].Descriptor() } func (IntentionSourceType) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[2] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[4] } func (x IntentionSourceType) Number() protoreflect.EnumNumber { @@ -191,7 +302,7 @@ func (x IntentionSourceType) Number() protoreflect.EnumNumber { // Deprecated: Use IntentionSourceType.Descriptor instead. func (IntentionSourceType) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{2} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{4} } type ProxyMode int32 @@ -227,11 +338,11 @@ func (x ProxyMode) String() string { } func (ProxyMode) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[3].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[5].Descriptor() } func (ProxyMode) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[3] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[5] } func (x ProxyMode) Number() protoreflect.EnumNumber { @@ -240,7 +351,7 @@ func (x ProxyMode) Number() protoreflect.EnumNumber { // Deprecated: Use ProxyMode.Descriptor instead. func (ProxyMode) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{3} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{5} } type MutualTLSMode int32 @@ -276,11 +387,11 @@ func (x MutualTLSMode) String() string { } func (MutualTLSMode) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[4].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[6].Descriptor() } func (MutualTLSMode) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[4] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[6] } func (x MutualTLSMode) Number() protoreflect.EnumNumber { @@ -289,7 +400,7 @@ func (x MutualTLSMode) Number() protoreflect.EnumNumber { // Deprecated: Use MutualTLSMode.Descriptor instead. func (MutualTLSMode) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{4} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{6} } type MeshGatewayMode int32 @@ -328,11 +439,11 @@ func (x MeshGatewayMode) String() string { } func (MeshGatewayMode) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[5].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[7].Descriptor() } func (MeshGatewayMode) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[5] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[7] } func (x MeshGatewayMode) Number() protoreflect.EnumNumber { @@ -341,7 +452,7 @@ func (x MeshGatewayMode) Number() protoreflect.EnumNumber { // Deprecated: Use MeshGatewayMode.Descriptor instead. func (MeshGatewayMode) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{5} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{7} } type APIGatewayListenerProtocol int32 @@ -374,11 +485,11 @@ func (x APIGatewayListenerProtocol) String() string { } func (APIGatewayListenerProtocol) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[6].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[8].Descriptor() } func (APIGatewayListenerProtocol) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[6] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[8] } func (x APIGatewayListenerProtocol) Number() protoreflect.EnumNumber { @@ -387,7 +498,7 @@ func (x APIGatewayListenerProtocol) Number() protoreflect.EnumNumber { // Deprecated: Use APIGatewayListenerProtocol.Descriptor instead. func (APIGatewayListenerProtocol) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{6} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{8} } type HTTPMatchMethod int32 @@ -444,11 +555,11 @@ func (x HTTPMatchMethod) String() string { } func (HTTPMatchMethod) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[7].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[9].Descriptor() } func (HTTPMatchMethod) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[7] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[9] } func (x HTTPMatchMethod) Number() protoreflect.EnumNumber { @@ -457,7 +568,7 @@ func (x HTTPMatchMethod) Number() protoreflect.EnumNumber { // Deprecated: Use HTTPMatchMethod.Descriptor instead. func (HTTPMatchMethod) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{7} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{9} } type HTTPHeaderMatchType int32 @@ -499,11 +610,11 @@ func (x HTTPHeaderMatchType) String() string { } func (HTTPHeaderMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[8].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[10].Descriptor() } func (HTTPHeaderMatchType) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[8] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[10] } func (x HTTPHeaderMatchType) Number() protoreflect.EnumNumber { @@ -512,7 +623,7 @@ func (x HTTPHeaderMatchType) Number() protoreflect.EnumNumber { // Deprecated: Use HTTPHeaderMatchType.Descriptor instead. func (HTTPHeaderMatchType) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{8} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{10} } type HTTPPathMatchType int32 @@ -548,11 +659,11 @@ func (x HTTPPathMatchType) String() string { } func (HTTPPathMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[9].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[11].Descriptor() } func (HTTPPathMatchType) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[9] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[11] } func (x HTTPPathMatchType) Number() protoreflect.EnumNumber { @@ -561,7 +672,7 @@ func (x HTTPPathMatchType) Number() protoreflect.EnumNumber { // Deprecated: Use HTTPPathMatchType.Descriptor instead. func (HTTPPathMatchType) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{9} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{11} } type HTTPQueryMatchType int32 @@ -597,11 +708,11 @@ func (x HTTPQueryMatchType) String() string { } func (HTTPQueryMatchType) Descriptor() protoreflect.EnumDescriptor { - return file_private_pbconfigentry_config_entry_proto_enumTypes[10].Descriptor() + return file_private_pbconfigentry_config_entry_proto_enumTypes[12].Descriptor() } func (HTTPQueryMatchType) Type() protoreflect.EnumType { - return &file_private_pbconfigentry_config_entry_proto_enumTypes[10] + return &file_private_pbconfigentry_config_entry_proto_enumTypes[12] } func (x HTTPQueryMatchType) Number() protoreflect.EnumNumber { @@ -610,37 +721,19 @@ func (x HTTPQueryMatchType) Number() protoreflect.EnumNumber { // Deprecated: Use HTTPQueryMatchType.Descriptor instead. func (HTTPQueryMatchType) EnumDescriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{10} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{12} } -type ConfigEntry struct { +type GetResolvedExportedServicesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Kind Kind `protobuf:"varint,1,opt,name=Kind,proto3,enum=hashicorp.consul.internal.configentry.Kind" json:"Kind,omitempty"` - Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` - EnterpriseMeta *pbcommon.EnterpriseMeta `protobuf:"bytes,3,opt,name=EnterpriseMeta,proto3" json:"EnterpriseMeta,omitempty"` - RaftIndex *pbcommon.RaftIndex `protobuf:"bytes,4,opt,name=RaftIndex,proto3" json:"RaftIndex,omitempty"` - // Types that are assignable to Entry: - // - // *ConfigEntry_MeshConfig - // *ConfigEntry_ServiceResolver - // *ConfigEntry_IngressGateway - // *ConfigEntry_ServiceIntentions - // *ConfigEntry_ServiceDefaults - // *ConfigEntry_APIGateway - // *ConfigEntry_BoundAPIGateway - // *ConfigEntry_TCPRoute - // *ConfigEntry_HTTPRoute - // *ConfigEntry_InlineCertificate - // *ConfigEntry_SamenessGroup - // *ConfigEntry_JWTProvider - Entry isConfigEntry_Entry `protobuf_oneof:"Entry"` + Partition string `protobuf:"bytes,1,opt,name=Partition,proto3" json:"Partition,omitempty"` } -func (x *ConfigEntry) Reset() { - *x = ConfigEntry{} +func (x *GetResolvedExportedServicesRequest) Reset() { + *x = GetResolvedExportedServicesRequest{} if protoimpl.UnsafeEnabled { mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -648,13 +741,13 @@ func (x *ConfigEntry) Reset() { } } -func (x *ConfigEntry) String() string { +func (x *GetResolvedExportedServicesRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ConfigEntry) ProtoMessage() {} +func (*GetResolvedExportedServicesRequest) ProtoMessage() {} -func (x *ConfigEntry) ProtoReflect() protoreflect.Message { +func (x *GetResolvedExportedServicesRequest) ProtoReflect() protoreflect.Message { mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -666,130 +759,376 @@ func (x *ConfigEntry) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ConfigEntry.ProtoReflect.Descriptor instead. -func (*ConfigEntry) Descriptor() ([]byte, []int) { +// Deprecated: Use GetResolvedExportedServicesRequest.ProtoReflect.Descriptor instead. +func (*GetResolvedExportedServicesRequest) Descriptor() ([]byte, []int) { return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{0} } -func (x *ConfigEntry) GetKind() Kind { - if x != nil { - return x.Kind - } - return Kind_KindUnknown -} - -func (x *ConfigEntry) GetName() string { +func (x *GetResolvedExportedServicesRequest) GetPartition() string { if x != nil { - return x.Name + return x.Partition } return "" } -func (x *ConfigEntry) GetEnterpriseMeta() *pbcommon.EnterpriseMeta { - if x != nil { - return x.EnterpriseMeta - } - return nil +type GetResolvedExportedServicesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Services []*ResolvedExportedService `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` } -func (x *ConfigEntry) GetRaftIndex() *pbcommon.RaftIndex { - if x != nil { - return x.RaftIndex +func (x *GetResolvedExportedServicesResponse) Reset() { + *x = GetResolvedExportedServicesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return nil } -func (m *ConfigEntry) GetEntry() isConfigEntry_Entry { - if m != nil { - return m.Entry - } - return nil +func (x *GetResolvedExportedServicesResponse) String() string { + return protoimpl.X.MessageStringOf(x) } -func (x *ConfigEntry) GetMeshConfig() *MeshConfig { - if x, ok := x.GetEntry().(*ConfigEntry_MeshConfig); ok { - return x.MeshConfig +func (*GetResolvedExportedServicesResponse) ProtoMessage() {} + +func (x *GetResolvedExportedServicesResponse) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return nil + return mi.MessageOf(x) } -func (x *ConfigEntry) GetServiceResolver() *ServiceResolver { - if x, ok := x.GetEntry().(*ConfigEntry_ServiceResolver); ok { - return x.ServiceResolver - } - return nil +// Deprecated: Use GetResolvedExportedServicesResponse.ProtoReflect.Descriptor instead. +func (*GetResolvedExportedServicesResponse) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{1} } -func (x *ConfigEntry) GetIngressGateway() *IngressGateway { - if x, ok := x.GetEntry().(*ConfigEntry_IngressGateway); ok { - return x.IngressGateway +func (x *GetResolvedExportedServicesResponse) GetServices() []*ResolvedExportedService { + if x != nil { + return x.Services } return nil } -func (x *ConfigEntry) GetServiceIntentions() *ServiceIntentions { - if x, ok := x.GetEntry().(*ConfigEntry_ServiceIntentions); ok { - return x.ServiceIntentions - } - return nil +type ResolvedExportedService struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Service string `protobuf:"bytes,1,opt,name=Service,proto3" json:"Service,omitempty"` + EnterpriseMeta *pbcommon.EnterpriseMeta `protobuf:"bytes,2,opt,name=EnterpriseMeta,proto3" json:"EnterpriseMeta,omitempty"` + Consumers *Consumers `protobuf:"bytes,3,opt,name=Consumers,proto3" json:"Consumers,omitempty"` } -func (x *ConfigEntry) GetServiceDefaults() *ServiceDefaults { - if x, ok := x.GetEntry().(*ConfigEntry_ServiceDefaults); ok { - return x.ServiceDefaults +func (x *ResolvedExportedService) Reset() { + *x = ResolvedExportedService{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return nil } -func (x *ConfigEntry) GetAPIGateway() *APIGateway { - if x, ok := x.GetEntry().(*ConfigEntry_APIGateway); ok { - return x.APIGateway - } - return nil +func (x *ResolvedExportedService) String() string { + return protoimpl.X.MessageStringOf(x) } -func (x *ConfigEntry) GetBoundAPIGateway() *BoundAPIGateway { - if x, ok := x.GetEntry().(*ConfigEntry_BoundAPIGateway); ok { - return x.BoundAPIGateway +func (*ResolvedExportedService) ProtoMessage() {} + +func (x *ResolvedExportedService) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return nil + return mi.MessageOf(x) } -func (x *ConfigEntry) GetTCPRoute() *TCPRoute { - if x, ok := x.GetEntry().(*ConfigEntry_TCPRoute); ok { - return x.TCPRoute - } - return nil +// Deprecated: Use ResolvedExportedService.ProtoReflect.Descriptor instead. +func (*ResolvedExportedService) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{2} } -func (x *ConfigEntry) GetHTTPRoute() *HTTPRoute { - if x, ok := x.GetEntry().(*ConfigEntry_HTTPRoute); ok { - return x.HTTPRoute +func (x *ResolvedExportedService) GetService() string { + if x != nil { + return x.Service } - return nil + return "" } -func (x *ConfigEntry) GetInlineCertificate() *InlineCertificate { - if x, ok := x.GetEntry().(*ConfigEntry_InlineCertificate); ok { - return x.InlineCertificate +func (x *ResolvedExportedService) GetEnterpriseMeta() *pbcommon.EnterpriseMeta { + if x != nil { + return x.EnterpriseMeta } return nil } -func (x *ConfigEntry) GetSamenessGroup() *SamenessGroup { - if x, ok := x.GetEntry().(*ConfigEntry_SamenessGroup); ok { - return x.SamenessGroup +func (x *ResolvedExportedService) GetConsumers() *Consumers { + if x != nil { + return x.Consumers } return nil } -func (x *ConfigEntry) GetJWTProvider() *JWTProvider { +type Consumers struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Peers []string `protobuf:"bytes,1,rep,name=Peers,proto3" json:"Peers,omitempty"` + Partitions []string `protobuf:"bytes,2,rep,name=Partitions,proto3" json:"Partitions,omitempty"` +} + +func (x *Consumers) Reset() { + *x = Consumers{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Consumers) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Consumers) ProtoMessage() {} + +func (x *Consumers) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Consumers.ProtoReflect.Descriptor instead. +func (*Consumers) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{3} +} + +func (x *Consumers) GetPeers() []string { + if x != nil { + return x.Peers + } + return nil +} + +func (x *Consumers) GetPartitions() []string { + if x != nil { + return x.Partitions + } + return nil +} + +type ConfigEntry struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Kind Kind `protobuf:"varint,1,opt,name=Kind,proto3,enum=hashicorp.consul.internal.configentry.Kind" json:"Kind,omitempty"` + Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` + EnterpriseMeta *pbcommon.EnterpriseMeta `protobuf:"bytes,3,opt,name=EnterpriseMeta,proto3" json:"EnterpriseMeta,omitempty"` + RaftIndex *pbcommon.RaftIndex `protobuf:"bytes,4,opt,name=RaftIndex,proto3" json:"RaftIndex,omitempty"` + // Types that are assignable to Entry: + // + // *ConfigEntry_MeshConfig + // *ConfigEntry_ServiceResolver + // *ConfigEntry_IngressGateway + // *ConfigEntry_ServiceIntentions + // *ConfigEntry_ServiceDefaults + // *ConfigEntry_APIGateway + // *ConfigEntry_BoundAPIGateway + // *ConfigEntry_TCPRoute + // *ConfigEntry_HTTPRoute + // *ConfigEntry_InlineCertificate + // *ConfigEntry_SamenessGroup + // *ConfigEntry_JWTProvider + // *ConfigEntry_ExportedServices + // *ConfigEntry_FileSystemCertificate + Entry isConfigEntry_Entry `protobuf_oneof:"Entry"` +} + +func (x *ConfigEntry) Reset() { + *x = ConfigEntry{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ConfigEntry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfigEntry) ProtoMessage() {} + +func (x *ConfigEntry) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfigEntry.ProtoReflect.Descriptor instead. +func (*ConfigEntry) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{4} +} + +func (x *ConfigEntry) GetKind() Kind { + if x != nil { + return x.Kind + } + return Kind_KindUnknown +} + +func (x *ConfigEntry) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ConfigEntry) GetEnterpriseMeta() *pbcommon.EnterpriseMeta { + if x != nil { + return x.EnterpriseMeta + } + return nil +} + +func (x *ConfigEntry) GetRaftIndex() *pbcommon.RaftIndex { + if x != nil { + return x.RaftIndex + } + return nil +} + +func (m *ConfigEntry) GetEntry() isConfigEntry_Entry { + if m != nil { + return m.Entry + } + return nil +} + +func (x *ConfigEntry) GetMeshConfig() *MeshConfig { + if x, ok := x.GetEntry().(*ConfigEntry_MeshConfig); ok { + return x.MeshConfig + } + return nil +} + +func (x *ConfigEntry) GetServiceResolver() *ServiceResolver { + if x, ok := x.GetEntry().(*ConfigEntry_ServiceResolver); ok { + return x.ServiceResolver + } + return nil +} + +func (x *ConfigEntry) GetIngressGateway() *IngressGateway { + if x, ok := x.GetEntry().(*ConfigEntry_IngressGateway); ok { + return x.IngressGateway + } + return nil +} + +func (x *ConfigEntry) GetServiceIntentions() *ServiceIntentions { + if x, ok := x.GetEntry().(*ConfigEntry_ServiceIntentions); ok { + return x.ServiceIntentions + } + return nil +} + +func (x *ConfigEntry) GetServiceDefaults() *ServiceDefaults { + if x, ok := x.GetEntry().(*ConfigEntry_ServiceDefaults); ok { + return x.ServiceDefaults + } + return nil +} + +func (x *ConfigEntry) GetAPIGateway() *APIGateway { + if x, ok := x.GetEntry().(*ConfigEntry_APIGateway); ok { + return x.APIGateway + } + return nil +} + +func (x *ConfigEntry) GetBoundAPIGateway() *BoundAPIGateway { + if x, ok := x.GetEntry().(*ConfigEntry_BoundAPIGateway); ok { + return x.BoundAPIGateway + } + return nil +} + +func (x *ConfigEntry) GetTCPRoute() *TCPRoute { + if x, ok := x.GetEntry().(*ConfigEntry_TCPRoute); ok { + return x.TCPRoute + } + return nil +} + +func (x *ConfigEntry) GetHTTPRoute() *HTTPRoute { + if x, ok := x.GetEntry().(*ConfigEntry_HTTPRoute); ok { + return x.HTTPRoute + } + return nil +} + +func (x *ConfigEntry) GetInlineCertificate() *InlineCertificate { + if x, ok := x.GetEntry().(*ConfigEntry_InlineCertificate); ok { + return x.InlineCertificate + } + return nil +} + +func (x *ConfigEntry) GetSamenessGroup() *SamenessGroup { + if x, ok := x.GetEntry().(*ConfigEntry_SamenessGroup); ok { + return x.SamenessGroup + } + return nil +} + +func (x *ConfigEntry) GetJWTProvider() *JWTProvider { if x, ok := x.GetEntry().(*ConfigEntry_JWTProvider); ok { return x.JWTProvider } return nil } +func (x *ConfigEntry) GetExportedServices() *ExportedServices { + if x, ok := x.GetEntry().(*ConfigEntry_ExportedServices); ok { + return x.ExportedServices + } + return nil +} + +func (x *ConfigEntry) GetFileSystemCertificate() *FileSystemCertificate { + if x, ok := x.GetEntry().(*ConfigEntry_FileSystemCertificate); ok { + return x.FileSystemCertificate + } + return nil +} + type isConfigEntry_Entry interface { isConfigEntry_Entry() } @@ -842,6 +1181,14 @@ type ConfigEntry_JWTProvider struct { JWTProvider *JWTProvider `protobuf:"bytes,16,opt,name=JWTProvider,proto3,oneof"` } +type ConfigEntry_ExportedServices struct { + ExportedServices *ExportedServices `protobuf:"bytes,17,opt,name=ExportedServices,proto3,oneof"` +} + +type ConfigEntry_FileSystemCertificate struct { + FileSystemCertificate *FileSystemCertificate `protobuf:"bytes,18,opt,name=FileSystemCertificate,proto3,oneof"` +} + func (*ConfigEntry_MeshConfig) isConfigEntry_Entry() {} func (*ConfigEntry_ServiceResolver) isConfigEntry_Entry() {} @@ -866,6 +1213,10 @@ func (*ConfigEntry_SamenessGroup) isConfigEntry_Entry() {} func (*ConfigEntry_JWTProvider) isConfigEntry_Entry() {} +func (*ConfigEntry_ExportedServices) isConfigEntry_Entry() {} + +func (*ConfigEntry_FileSystemCertificate) isConfigEntry_Entry() {} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.MeshConfigEntry @@ -883,12 +1234,14 @@ type MeshConfig struct { Meta map[string]string `protobuf:"bytes,4,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Peering *PeeringMeshConfig `protobuf:"bytes,5,opt,name=Peering,proto3" json:"Peering,omitempty"` AllowEnablingPermissiveMutualTLS bool `protobuf:"varint,6,opt,name=AllowEnablingPermissiveMutualTLS,proto3" json:"AllowEnablingPermissiveMutualTLS,omitempty"` + Hash uint64 `protobuf:"varint,7,opt,name=Hash,proto3" json:"Hash,omitempty"` + ValidateClusters bool `protobuf:"varint,8,opt,name=ValidateClusters,proto3" json:"ValidateClusters,omitempty"` } func (x *MeshConfig) Reset() { *x = MeshConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[1] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -901,7 +1254,7 @@ func (x *MeshConfig) String() string { func (*MeshConfig) ProtoMessage() {} func (x *MeshConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[1] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -914,7 +1267,7 @@ func (x *MeshConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use MeshConfig.ProtoReflect.Descriptor instead. func (*MeshConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{1} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{5} } func (x *MeshConfig) GetTransparentProxy() *TransparentProxyMeshConfig { @@ -959,6 +1312,20 @@ func (x *MeshConfig) GetAllowEnablingPermissiveMutualTLS() bool { return false } +func (x *MeshConfig) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + +func (x *MeshConfig) GetValidateClusters() bool { + if x != nil { + return x.ValidateClusters + } + return false +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.TransparentProxyMeshConfig @@ -975,7 +1342,7 @@ type TransparentProxyMeshConfig struct { func (x *TransparentProxyMeshConfig) Reset() { *x = TransparentProxyMeshConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[2] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -988,7 +1355,7 @@ func (x *TransparentProxyMeshConfig) String() string { func (*TransparentProxyMeshConfig) ProtoMessage() {} func (x *TransparentProxyMeshConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[2] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1001,7 +1368,7 @@ func (x *TransparentProxyMeshConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use TransparentProxyMeshConfig.ProtoReflect.Descriptor instead. func (*TransparentProxyMeshConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{2} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{6} } func (x *TransparentProxyMeshConfig) GetMeshDestinationsOnly() bool { @@ -1028,7 +1395,7 @@ type MeshTLSConfig struct { func (x *MeshTLSConfig) Reset() { *x = MeshTLSConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[3] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1041,7 +1408,7 @@ func (x *MeshTLSConfig) String() string { func (*MeshTLSConfig) ProtoMessage() {} func (x *MeshTLSConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[3] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1054,7 +1421,7 @@ func (x *MeshTLSConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use MeshTLSConfig.ProtoReflect.Descriptor instead. func (*MeshTLSConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{3} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{7} } func (x *MeshTLSConfig) GetIncoming() *MeshDirectionalTLSConfig { @@ -1092,7 +1459,7 @@ type MeshDirectionalTLSConfig struct { func (x *MeshDirectionalTLSConfig) Reset() { *x = MeshDirectionalTLSConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[4] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1105,7 +1472,7 @@ func (x *MeshDirectionalTLSConfig) String() string { func (*MeshDirectionalTLSConfig) ProtoMessage() {} func (x *MeshDirectionalTLSConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[4] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1118,7 +1485,7 @@ func (x *MeshDirectionalTLSConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use MeshDirectionalTLSConfig.ProtoReflect.Descriptor instead. func (*MeshDirectionalTLSConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{4} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{8} } func (x *MeshDirectionalTLSConfig) GetTLSMinVersion() string { @@ -1152,13 +1519,14 @@ type MeshHTTPConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SanitizeXForwardedClientCert bool `protobuf:"varint,1,opt,name=SanitizeXForwardedClientCert,proto3" json:"SanitizeXForwardedClientCert,omitempty"` + SanitizeXForwardedClientCert bool `protobuf:"varint,1,opt,name=SanitizeXForwardedClientCert,proto3" json:"SanitizeXForwardedClientCert,omitempty"` + Incoming *MeshDirectionalHTTPConfig `protobuf:"bytes,2,opt,name=Incoming,proto3" json:"Incoming,omitempty"` } func (x *MeshHTTPConfig) Reset() { *x = MeshHTTPConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[5] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1171,7 +1539,7 @@ func (x *MeshHTTPConfig) String() string { func (*MeshHTTPConfig) ProtoMessage() {} func (x *MeshHTTPConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[5] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1184,7 +1552,7 @@ func (x *MeshHTTPConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use MeshHTTPConfig.ProtoReflect.Descriptor instead. func (*MeshHTTPConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{5} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{9} } func (x *MeshHTTPConfig) GetSanitizeXForwardedClientCert() bool { @@ -1194,6 +1562,65 @@ func (x *MeshHTTPConfig) GetSanitizeXForwardedClientCert() bool { return false } +func (x *MeshHTTPConfig) GetIncoming() *MeshDirectionalHTTPConfig { + if x != nil { + return x.Incoming + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.MeshDirectionalHTTPConfig +// output=config_entry.gen.go +// name=Structs +type MeshDirectionalHTTPConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestNormalization *RequestNormalizationMeshConfig `protobuf:"bytes,1,opt,name=RequestNormalization,proto3" json:"RequestNormalization,omitempty"` +} + +func (x *MeshDirectionalHTTPConfig) Reset() { + *x = MeshDirectionalHTTPConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MeshDirectionalHTTPConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MeshDirectionalHTTPConfig) ProtoMessage() {} + +func (x *MeshDirectionalHTTPConfig) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MeshDirectionalHTTPConfig.ProtoReflect.Descriptor instead. +func (*MeshDirectionalHTTPConfig) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{10} +} + +func (x *MeshDirectionalHTTPConfig) GetRequestNormalization() *RequestNormalizationMeshConfig { + if x != nil { + return x.RequestNormalization + } + return nil +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.PeeringMeshConfig @@ -1210,7 +1637,7 @@ type PeeringMeshConfig struct { func (x *PeeringMeshConfig) Reset() { *x = PeeringMeshConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[6] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1223,7 +1650,7 @@ func (x *PeeringMeshConfig) String() string { func (*PeeringMeshConfig) ProtoMessage() {} func (x *PeeringMeshConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[6] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1236,7 +1663,7 @@ func (x *PeeringMeshConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use PeeringMeshConfig.ProtoReflect.Descriptor instead. func (*PeeringMeshConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{6} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{11} } func (x *PeeringMeshConfig) GetPeerThroughMeshGateways() bool { @@ -1246,6 +1673,84 @@ func (x *PeeringMeshConfig) GetPeerThroughMeshGateways() bool { return false } +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.RequestNormalizationMeshConfig +// output=config_entry.gen.go +// name=Structs +type RequestNormalizationMeshConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + InsecureDisablePathNormalization bool `protobuf:"varint,1,opt,name=InsecureDisablePathNormalization,proto3" json:"InsecureDisablePathNormalization,omitempty"` + MergeSlashes bool `protobuf:"varint,2,opt,name=MergeSlashes,proto3" json:"MergeSlashes,omitempty"` + // mog: func-to=pathWithEscapedSlashesActionToStructs func-from=pathWithEscapedSlashesActionFromStructs + PathWithEscapedSlashesAction PathWithEscapedSlashesAction `protobuf:"varint,3,opt,name=PathWithEscapedSlashesAction,proto3,enum=hashicorp.consul.internal.configentry.PathWithEscapedSlashesAction" json:"PathWithEscapedSlashesAction,omitempty"` + // mog: func-to=headersWithUnderscoresActionToStructs func-from=headersWithUnderscoresActionFromStructs + HeadersWithUnderscoresAction HeadersWithUnderscoresAction `protobuf:"varint,4,opt,name=HeadersWithUnderscoresAction,proto3,enum=hashicorp.consul.internal.configentry.HeadersWithUnderscoresAction" json:"HeadersWithUnderscoresAction,omitempty"` +} + +func (x *RequestNormalizationMeshConfig) Reset() { + *x = RequestNormalizationMeshConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestNormalizationMeshConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestNormalizationMeshConfig) ProtoMessage() {} + +func (x *RequestNormalizationMeshConfig) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestNormalizationMeshConfig.ProtoReflect.Descriptor instead. +func (*RequestNormalizationMeshConfig) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{12} +} + +func (x *RequestNormalizationMeshConfig) GetInsecureDisablePathNormalization() bool { + if x != nil { + return x.InsecureDisablePathNormalization + } + return false +} + +func (x *RequestNormalizationMeshConfig) GetMergeSlashes() bool { + if x != nil { + return x.MergeSlashes + } + return false +} + +func (x *RequestNormalizationMeshConfig) GetPathWithEscapedSlashesAction() PathWithEscapedSlashesAction { + if x != nil { + return x.PathWithEscapedSlashesAction + } + return PathWithEscapedSlashesAction_PathWithEscapedSlashesActionDefault +} + +func (x *RequestNormalizationMeshConfig) GetHeadersWithUnderscoresAction() HeadersWithUnderscoresAction { + if x != nil { + return x.HeadersWithUnderscoresAction + } + return HeadersWithUnderscoresAction_HeadersWithUnderscoresActionAllow +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.ServiceResolverConfigEntry @@ -1268,12 +1773,13 @@ type ServiceResolver struct { // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto RequestTimeout *durationpb.Duration `protobuf:"bytes,8,opt,name=RequestTimeout,proto3" json:"RequestTimeout,omitempty"` PrioritizeByLocality *ServiceResolverPrioritizeByLocality `protobuf:"bytes,9,opt,name=PrioritizeByLocality,proto3" json:"PrioritizeByLocality,omitempty"` + Hash uint64 `protobuf:"varint,10,opt,name=Hash,proto3" json:"Hash,omitempty"` } func (x *ServiceResolver) Reset() { *x = ServiceResolver{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[7] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1286,7 +1792,7 @@ func (x *ServiceResolver) String() string { func (*ServiceResolver) ProtoMessage() {} func (x *ServiceResolver) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[7] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1299,7 +1805,7 @@ func (x *ServiceResolver) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceResolver.ProtoReflect.Descriptor instead. func (*ServiceResolver) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{7} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{13} } func (x *ServiceResolver) GetDefaultSubset() string { @@ -1365,6 +1871,13 @@ func (x *ServiceResolver) GetPrioritizeByLocality() *ServiceResolverPrioritizeBy return nil } +func (x *ServiceResolver) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.ServiceResolverSubset @@ -1382,7 +1895,7 @@ type ServiceResolverSubset struct { func (x *ServiceResolverSubset) Reset() { *x = ServiceResolverSubset{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[8] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1395,7 +1908,7 @@ func (x *ServiceResolverSubset) String() string { func (*ServiceResolverSubset) ProtoMessage() {} func (x *ServiceResolverSubset) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[8] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1408,7 +1921,7 @@ func (x *ServiceResolverSubset) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceResolverSubset.ProtoReflect.Descriptor instead. func (*ServiceResolverSubset) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{8} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{14} } func (x *ServiceResolverSubset) GetFilter() string { @@ -1447,7 +1960,7 @@ type ServiceResolverRedirect struct { func (x *ServiceResolverRedirect) Reset() { *x = ServiceResolverRedirect{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[9] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1460,7 +1973,7 @@ func (x *ServiceResolverRedirect) String() string { func (*ServiceResolverRedirect) ProtoMessage() {} func (x *ServiceResolverRedirect) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[9] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1473,7 +1986,7 @@ func (x *ServiceResolverRedirect) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceResolverRedirect.ProtoReflect.Descriptor instead. func (*ServiceResolverRedirect) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{9} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{15} } func (x *ServiceResolverRedirect) GetService() string { @@ -1547,7 +2060,7 @@ type ServiceResolverFailover struct { func (x *ServiceResolverFailover) Reset() { *x = ServiceResolverFailover{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[10] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1560,7 +2073,7 @@ func (x *ServiceResolverFailover) String() string { func (*ServiceResolverFailover) ProtoMessage() {} func (x *ServiceResolverFailover) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[10] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1573,7 +2086,7 @@ func (x *ServiceResolverFailover) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceResolverFailover.ProtoReflect.Descriptor instead. func (*ServiceResolverFailover) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{10} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{16} } func (x *ServiceResolverFailover) GetService() string { @@ -1642,7 +2155,7 @@ type ServiceResolverFailoverPolicy struct { func (x *ServiceResolverFailoverPolicy) Reset() { *x = ServiceResolverFailoverPolicy{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[11] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1655,7 +2168,7 @@ func (x *ServiceResolverFailoverPolicy) String() string { func (*ServiceResolverFailoverPolicy) ProtoMessage() {} func (x *ServiceResolverFailoverPolicy) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[11] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1668,7 +2181,7 @@ func (x *ServiceResolverFailoverPolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceResolverFailoverPolicy.ProtoReflect.Descriptor instead. func (*ServiceResolverFailoverPolicy) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{11} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{17} } func (x *ServiceResolverFailoverPolicy) GetMode() string { @@ -1701,7 +2214,7 @@ type ServiceResolverPrioritizeByLocality struct { func (x *ServiceResolverPrioritizeByLocality) Reset() { *x = ServiceResolverPrioritizeByLocality{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[12] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1714,7 +2227,7 @@ func (x *ServiceResolverPrioritizeByLocality) String() string { func (*ServiceResolverPrioritizeByLocality) ProtoMessage() {} func (x *ServiceResolverPrioritizeByLocality) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[12] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1727,7 +2240,7 @@ func (x *ServiceResolverPrioritizeByLocality) ProtoReflect() protoreflect.Messag // Deprecated: Use ServiceResolverPrioritizeByLocality.ProtoReflect.Descriptor instead. func (*ServiceResolverPrioritizeByLocality) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{12} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{18} } func (x *ServiceResolverPrioritizeByLocality) GetMode() string { @@ -1758,7 +2271,7 @@ type ServiceResolverFailoverTarget struct { func (x *ServiceResolverFailoverTarget) Reset() { *x = ServiceResolverFailoverTarget{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[13] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1771,7 +2284,7 @@ func (x *ServiceResolverFailoverTarget) String() string { func (*ServiceResolverFailoverTarget) ProtoMessage() {} func (x *ServiceResolverFailoverTarget) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[13] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1784,7 +2297,7 @@ func (x *ServiceResolverFailoverTarget) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceResolverFailoverTarget.ProtoReflect.Descriptor instead. func (*ServiceResolverFailoverTarget) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{13} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{19} } func (x *ServiceResolverFailoverTarget) GetService() string { @@ -1848,7 +2361,7 @@ type LoadBalancer struct { func (x *LoadBalancer) Reset() { *x = LoadBalancer{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[14] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1861,7 +2374,7 @@ func (x *LoadBalancer) String() string { func (*LoadBalancer) ProtoMessage() {} func (x *LoadBalancer) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[14] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1874,7 +2387,7 @@ func (x *LoadBalancer) ProtoReflect() protoreflect.Message { // Deprecated: Use LoadBalancer.ProtoReflect.Descriptor instead. func (*LoadBalancer) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{14} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{20} } func (x *LoadBalancer) GetPolicy() string { @@ -1922,7 +2435,7 @@ type RingHashConfig struct { func (x *RingHashConfig) Reset() { *x = RingHashConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[15] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1935,7 +2448,7 @@ func (x *RingHashConfig) String() string { func (*RingHashConfig) ProtoMessage() {} func (x *RingHashConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[15] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1948,7 +2461,7 @@ func (x *RingHashConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use RingHashConfig.ProtoReflect.Descriptor instead. func (*RingHashConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{15} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{21} } func (x *RingHashConfig) GetMinimumRingSize() uint64 { @@ -1981,7 +2494,7 @@ type LeastRequestConfig struct { func (x *LeastRequestConfig) Reset() { *x = LeastRequestConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[16] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1994,7 +2507,7 @@ func (x *LeastRequestConfig) String() string { func (*LeastRequestConfig) ProtoMessage() {} func (x *LeastRequestConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[16] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2007,7 +2520,7 @@ func (x *LeastRequestConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use LeastRequestConfig.ProtoReflect.Descriptor instead. func (*LeastRequestConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{16} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{22} } func (x *LeastRequestConfig) GetChoiceCount() uint32 { @@ -2037,7 +2550,7 @@ type HashPolicy struct { func (x *HashPolicy) Reset() { *x = HashPolicy{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[17] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2050,7 +2563,7 @@ func (x *HashPolicy) String() string { func (*HashPolicy) ProtoMessage() {} func (x *HashPolicy) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[17] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2063,7 +2576,7 @@ func (x *HashPolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use HashPolicy.ProtoReflect.Descriptor instead. func (*HashPolicy) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{17} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{23} } func (x *HashPolicy) GetField() string { @@ -2120,7 +2633,7 @@ type CookieConfig struct { func (x *CookieConfig) Reset() { *x = CookieConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[18] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2133,7 +2646,7 @@ func (x *CookieConfig) String() string { func (*CookieConfig) ProtoMessage() {} func (x *CookieConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[18] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2146,7 +2659,7 @@ func (x *CookieConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use CookieConfig.ProtoReflect.Descriptor instead. func (*CookieConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{18} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{24} } func (x *CookieConfig) GetSession() bool { @@ -2185,12 +2698,13 @@ type IngressGateway struct { Listeners []*IngressListener `protobuf:"bytes,2,rep,name=Listeners,proto3" json:"Listeners,omitempty"` Meta map[string]string `protobuf:"bytes,3,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Defaults *IngressServiceConfig `protobuf:"bytes,4,opt,name=Defaults,proto3" json:"Defaults,omitempty"` + Hash uint64 `protobuf:"varint,5,opt,name=Hash,proto3" json:"Hash,omitempty"` } func (x *IngressGateway) Reset() { *x = IngressGateway{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[19] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2203,7 +2717,7 @@ func (x *IngressGateway) String() string { func (*IngressGateway) ProtoMessage() {} func (x *IngressGateway) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[19] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2216,7 +2730,7 @@ func (x *IngressGateway) ProtoReflect() protoreflect.Message { // Deprecated: Use IngressGateway.ProtoReflect.Descriptor instead. func (*IngressGateway) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{19} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{25} } func (x *IngressGateway) GetTLS() *GatewayTLSConfig { @@ -2247,6 +2761,13 @@ func (x *IngressGateway) GetDefaults() *IngressServiceConfig { return nil } +func (x *IngressGateway) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.IngressServiceConfig @@ -2266,7 +2787,7 @@ type IngressServiceConfig struct { func (x *IngressServiceConfig) Reset() { *x = IngressServiceConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[20] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2279,7 +2800,7 @@ func (x *IngressServiceConfig) String() string { func (*IngressServiceConfig) ProtoMessage() {} func (x *IngressServiceConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[20] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2292,7 +2813,7 @@ func (x *IngressServiceConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use IngressServiceConfig.ProtoReflect.Descriptor instead. func (*IngressServiceConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{20} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{26} } func (x *IngressServiceConfig) GetMaxConnections() uint32 { @@ -2346,7 +2867,7 @@ type GatewayTLSConfig struct { func (x *GatewayTLSConfig) Reset() { *x = GatewayTLSConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[21] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2359,7 +2880,7 @@ func (x *GatewayTLSConfig) String() string { func (*GatewayTLSConfig) ProtoMessage() {} func (x *GatewayTLSConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[21] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2372,7 +2893,7 @@ func (x *GatewayTLSConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use GatewayTLSConfig.ProtoReflect.Descriptor instead. func (*GatewayTLSConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{21} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{27} } func (x *GatewayTLSConfig) GetEnabled() bool { @@ -2427,7 +2948,7 @@ type GatewayTLSSDSConfig struct { func (x *GatewayTLSSDSConfig) Reset() { *x = GatewayTLSSDSConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[22] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2440,7 +2961,7 @@ func (x *GatewayTLSSDSConfig) String() string { func (*GatewayTLSSDSConfig) ProtoMessage() {} func (x *GatewayTLSSDSConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[22] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2453,7 +2974,7 @@ func (x *GatewayTLSSDSConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use GatewayTLSSDSConfig.ProtoReflect.Descriptor instead. func (*GatewayTLSSDSConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{22} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{28} } func (x *GatewayTLSSDSConfig) GetClusterName() string { @@ -2490,7 +3011,7 @@ type IngressListener struct { func (x *IngressListener) Reset() { *x = IngressListener{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[23] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2503,7 +3024,7 @@ func (x *IngressListener) String() string { func (*IngressListener) ProtoMessage() {} func (x *IngressListener) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[23] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2516,7 +3037,7 @@ func (x *IngressListener) ProtoReflect() protoreflect.Message { // Deprecated: Use IngressListener.ProtoReflect.Descriptor instead. func (*IngressListener) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{23} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{29} } func (x *IngressListener) GetPort() int32 { @@ -2574,7 +3095,7 @@ type IngressService struct { func (x *IngressService) Reset() { *x = IngressService{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[24] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2587,7 +3108,7 @@ func (x *IngressService) String() string { func (*IngressService) ProtoMessage() {} func (x *IngressService) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[24] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2600,7 +3121,7 @@ func (x *IngressService) ProtoReflect() protoreflect.Message { // Deprecated: Use IngressService.ProtoReflect.Descriptor instead. func (*IngressService) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{24} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{30} } func (x *IngressService) GetName() string { @@ -2696,7 +3217,7 @@ type GatewayServiceTLSConfig struct { func (x *GatewayServiceTLSConfig) Reset() { *x = GatewayServiceTLSConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[25] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2709,7 +3230,7 @@ func (x *GatewayServiceTLSConfig) String() string { func (*GatewayServiceTLSConfig) ProtoMessage() {} func (x *GatewayServiceTLSConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[25] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2722,7 +3243,7 @@ func (x *GatewayServiceTLSConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use GatewayServiceTLSConfig.ProtoReflect.Descriptor instead. func (*GatewayServiceTLSConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{25} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{31} } func (x *GatewayServiceTLSConfig) GetSDS() *GatewayTLSSDSConfig { @@ -2750,7 +3271,7 @@ type HTTPHeaderModifiers struct { func (x *HTTPHeaderModifiers) Reset() { *x = HTTPHeaderModifiers{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[26] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2763,7 +3284,7 @@ func (x *HTTPHeaderModifiers) String() string { func (*HTTPHeaderModifiers) ProtoMessage() {} func (x *HTTPHeaderModifiers) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[26] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2776,7 +3297,7 @@ func (x *HTTPHeaderModifiers) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPHeaderModifiers.ProtoReflect.Descriptor instead. func (*HTTPHeaderModifiers) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{26} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{32} } func (x *HTTPHeaderModifiers) GetAdd() map[string]string { @@ -2814,12 +3335,13 @@ type ServiceIntentions struct { Sources []*SourceIntention `protobuf:"bytes,1,rep,name=Sources,proto3" json:"Sources,omitempty"` Meta map[string]string `protobuf:"bytes,2,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` JWT *IntentionJWTRequirement `protobuf:"bytes,3,opt,name=JWT,proto3" json:"JWT,omitempty"` + Hash uint64 `protobuf:"varint,4,opt,name=Hash,proto3" json:"Hash,omitempty"` } func (x *ServiceIntentions) Reset() { *x = ServiceIntentions{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[27] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2832,7 +3354,7 @@ func (x *ServiceIntentions) String() string { func (*ServiceIntentions) ProtoMessage() {} func (x *ServiceIntentions) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[27] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2845,7 +3367,7 @@ func (x *ServiceIntentions) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceIntentions.ProtoReflect.Descriptor instead. func (*ServiceIntentions) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{27} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{33} } func (x *ServiceIntentions) GetSources() []*SourceIntention { @@ -2869,6 +3391,13 @@ func (x *ServiceIntentions) GetJWT() *IntentionJWTRequirement { return nil } +func (x *ServiceIntentions) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.IntentionJWTRequirement @@ -2885,7 +3414,7 @@ type IntentionJWTRequirement struct { func (x *IntentionJWTRequirement) Reset() { *x = IntentionJWTRequirement{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[28] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2898,7 +3427,7 @@ func (x *IntentionJWTRequirement) String() string { func (*IntentionJWTRequirement) ProtoMessage() {} func (x *IntentionJWTRequirement) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[28] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2911,7 +3440,7 @@ func (x *IntentionJWTRequirement) ProtoReflect() protoreflect.Message { // Deprecated: Use IntentionJWTRequirement.ProtoReflect.Descriptor instead. func (*IntentionJWTRequirement) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{28} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{34} } func (x *IntentionJWTRequirement) GetProviders() []*IntentionJWTProvider { @@ -2938,7 +3467,7 @@ type IntentionJWTProvider struct { func (x *IntentionJWTProvider) Reset() { *x = IntentionJWTProvider{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[29] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2951,7 +3480,7 @@ func (x *IntentionJWTProvider) String() string { func (*IntentionJWTProvider) ProtoMessage() {} func (x *IntentionJWTProvider) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[29] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2964,7 +3493,7 @@ func (x *IntentionJWTProvider) ProtoReflect() protoreflect.Message { // Deprecated: Use IntentionJWTProvider.ProtoReflect.Descriptor instead. func (*IntentionJWTProvider) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{29} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{35} } func (x *IntentionJWTProvider) GetName() string { @@ -2998,7 +3527,7 @@ type IntentionJWTClaimVerification struct { func (x *IntentionJWTClaimVerification) Reset() { *x = IntentionJWTClaimVerification{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[30] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3011,7 +3540,7 @@ func (x *IntentionJWTClaimVerification) String() string { func (*IntentionJWTClaimVerification) ProtoMessage() {} func (x *IntentionJWTClaimVerification) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[30] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3024,7 +3553,7 @@ func (x *IntentionJWTClaimVerification) ProtoReflect() protoreflect.Message { // Deprecated: Use IntentionJWTClaimVerification.ProtoReflect.Descriptor instead. func (*IntentionJWTClaimVerification) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{30} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{36} } func (x *IntentionJWTClaimVerification) GetPath() []string { @@ -3075,7 +3604,7 @@ type SourceIntention struct { func (x *SourceIntention) Reset() { *x = SourceIntention{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[31] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3088,7 +3617,7 @@ func (x *SourceIntention) String() string { func (*SourceIntention) ProtoMessage() {} func (x *SourceIntention) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[31] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3101,7 +3630,7 @@ func (x *SourceIntention) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceIntention.ProtoReflect.Descriptor instead. func (*SourceIntention) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{31} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{37} } func (x *SourceIntention) GetName() string { @@ -3214,7 +3743,7 @@ type IntentionPermission struct { func (x *IntentionPermission) Reset() { *x = IntentionPermission{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[32] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3227,7 +3756,7 @@ func (x *IntentionPermission) String() string { func (*IntentionPermission) ProtoMessage() {} func (x *IntentionPermission) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[32] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3240,7 +3769,7 @@ func (x *IntentionPermission) ProtoReflect() protoreflect.Message { // Deprecated: Use IntentionPermission.ProtoReflect.Descriptor instead. func (*IntentionPermission) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{32} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{38} } func (x *IntentionPermission) GetAction() IntentionAction { @@ -3284,7 +3813,7 @@ type IntentionHTTPPermission struct { func (x *IntentionHTTPPermission) Reset() { *x = IntentionHTTPPermission{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[33] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3297,7 +3826,7 @@ func (x *IntentionHTTPPermission) String() string { func (*IntentionHTTPPermission) ProtoMessage() {} func (x *IntentionHTTPPermission) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[33] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3310,7 +3839,7 @@ func (x *IntentionHTTPPermission) ProtoReflect() protoreflect.Message { // Deprecated: Use IntentionHTTPPermission.ProtoReflect.Descriptor instead. func (*IntentionHTTPPermission) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{33} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{39} } func (x *IntentionHTTPPermission) GetPathExact() string { @@ -3358,19 +3887,21 @@ type IntentionHTTPHeaderPermission struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` - Present bool `protobuf:"varint,2,opt,name=Present,proto3" json:"Present,omitempty"` - Exact string `protobuf:"bytes,3,opt,name=Exact,proto3" json:"Exact,omitempty"` - Prefix string `protobuf:"bytes,4,opt,name=Prefix,proto3" json:"Prefix,omitempty"` - Suffix string `protobuf:"bytes,5,opt,name=Suffix,proto3" json:"Suffix,omitempty"` - Regex string `protobuf:"bytes,6,opt,name=Regex,proto3" json:"Regex,omitempty"` - Invert bool `protobuf:"varint,7,opt,name=Invert,proto3" json:"Invert,omitempty"` + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + Present bool `protobuf:"varint,2,opt,name=Present,proto3" json:"Present,omitempty"` + Exact string `protobuf:"bytes,3,opt,name=Exact,proto3" json:"Exact,omitempty"` + Prefix string `protobuf:"bytes,4,opt,name=Prefix,proto3" json:"Prefix,omitempty"` + Suffix string `protobuf:"bytes,5,opt,name=Suffix,proto3" json:"Suffix,omitempty"` + Regex string `protobuf:"bytes,6,opt,name=Regex,proto3" json:"Regex,omitempty"` + Invert bool `protobuf:"varint,7,opt,name=Invert,proto3" json:"Invert,omitempty"` + Contains string `protobuf:"bytes,8,opt,name=Contains,proto3" json:"Contains,omitempty"` + IgnoreCase bool `protobuf:"varint,9,opt,name=IgnoreCase,proto3" json:"IgnoreCase,omitempty"` } func (x *IntentionHTTPHeaderPermission) Reset() { *x = IntentionHTTPHeaderPermission{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[34] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3383,7 +3914,7 @@ func (x *IntentionHTTPHeaderPermission) String() string { func (*IntentionHTTPHeaderPermission) ProtoMessage() {} func (x *IntentionHTTPHeaderPermission) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[34] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3396,7 +3927,7 @@ func (x *IntentionHTTPHeaderPermission) ProtoReflect() protoreflect.Message { // Deprecated: Use IntentionHTTPHeaderPermission.ProtoReflect.Descriptor instead. func (*IntentionHTTPHeaderPermission) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{34} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{40} } func (x *IntentionHTTPHeaderPermission) GetName() string { @@ -3448,6 +3979,20 @@ func (x *IntentionHTTPHeaderPermission) GetInvert() bool { return false } +func (x *IntentionHTTPHeaderPermission) GetContains() string { + if x != nil { + return x.Contains + } + return "" +} + +func (x *IntentionHTTPHeaderPermission) GetIgnoreCase() bool { + if x != nil { + return x.IgnoreCase + } + return false +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.ServiceConfigEntry @@ -3481,12 +4026,13 @@ type ServiceDefaults struct { EnvoyExtensions []*pbcommon.EnvoyExtension `protobuf:"bytes,14,rep,name=EnvoyExtensions,proto3" json:"EnvoyExtensions,omitempty"` // mog: func-to=mutualTLSModeToStructs func-from=mutualTLSModeFromStructs MutualTLSMode MutualTLSMode `protobuf:"varint,15,opt,name=MutualTLSMode,proto3,enum=hashicorp.consul.internal.configentry.MutualTLSMode" json:"MutualTLSMode,omitempty"` + Hash uint64 `protobuf:"varint,17,opt,name=Hash,proto3" json:"Hash,omitempty"` } func (x *ServiceDefaults) Reset() { *x = ServiceDefaults{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[35] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3499,7 +4045,7 @@ func (x *ServiceDefaults) String() string { func (*ServiceDefaults) ProtoMessage() {} func (x *ServiceDefaults) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[35] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3512,7 +4058,7 @@ func (x *ServiceDefaults) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceDefaults.ProtoReflect.Descriptor instead. func (*ServiceDefaults) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{35} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{41} } func (x *ServiceDefaults) GetProtocol() string { @@ -3627,6 +4173,13 @@ func (x *ServiceDefaults) GetMutualTLSMode() MutualTLSMode { return MutualTLSMode_MutualTLSModeDefault } +func (x *ServiceDefaults) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.TransparentProxyConfig @@ -3645,7 +4198,7 @@ type TransparentProxyConfig struct { func (x *TransparentProxyConfig) Reset() { *x = TransparentProxyConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[36] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3658,7 +4211,7 @@ func (x *TransparentProxyConfig) String() string { func (*TransparentProxyConfig) ProtoMessage() {} func (x *TransparentProxyConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[36] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3671,7 +4224,7 @@ func (x *TransparentProxyConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use TransparentProxyConfig.ProtoReflect.Descriptor instead. func (*TransparentProxyConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{36} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{42} } func (x *TransparentProxyConfig) GetOutboundListenerPort() int32 { @@ -3705,7 +4258,7 @@ type MeshGatewayConfig struct { func (x *MeshGatewayConfig) Reset() { *x = MeshGatewayConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[37] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3718,7 +4271,7 @@ func (x *MeshGatewayConfig) String() string { func (*MeshGatewayConfig) ProtoMessage() {} func (x *MeshGatewayConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[37] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3731,7 +4284,7 @@ func (x *MeshGatewayConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use MeshGatewayConfig.ProtoReflect.Descriptor instead. func (*MeshGatewayConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{37} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{43} } func (x *MeshGatewayConfig) GetMode() MeshGatewayMode { @@ -3758,7 +4311,7 @@ type ExposeConfig struct { func (x *ExposeConfig) Reset() { *x = ExposeConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[38] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3771,7 +4324,7 @@ func (x *ExposeConfig) String() string { func (*ExposeConfig) ProtoMessage() {} func (x *ExposeConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[38] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3784,7 +4337,7 @@ func (x *ExposeConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use ExposeConfig.ProtoReflect.Descriptor instead. func (*ExposeConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{38} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{44} } func (x *ExposeConfig) GetChecks() bool { @@ -3823,7 +4376,7 @@ type ExposePath struct { func (x *ExposePath) Reset() { *x = ExposePath{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[39] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3836,7 +4389,7 @@ func (x *ExposePath) String() string { func (*ExposePath) ProtoMessage() {} func (x *ExposePath) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[39] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3849,7 +4402,7 @@ func (x *ExposePath) ProtoReflect() protoreflect.Message { // Deprecated: Use ExposePath.ProtoReflect.Descriptor instead. func (*ExposePath) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{39} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{45} } func (x *ExposePath) GetListenerPort() int32 { @@ -3904,7 +4457,7 @@ type UpstreamConfiguration struct { func (x *UpstreamConfiguration) Reset() { *x = UpstreamConfiguration{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[40] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3917,7 +4470,7 @@ func (x *UpstreamConfiguration) String() string { func (*UpstreamConfiguration) ProtoMessage() {} func (x *UpstreamConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[40] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3930,7 +4483,7 @@ func (x *UpstreamConfiguration) ProtoReflect() protoreflect.Message { // Deprecated: Use UpstreamConfiguration.ProtoReflect.Descriptor instead. func (*UpstreamConfiguration) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{40} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{46} } func (x *UpstreamConfiguration) GetOverrides() []*UpstreamConfig { @@ -3975,7 +4528,7 @@ type UpstreamConfig struct { func (x *UpstreamConfig) Reset() { *x = UpstreamConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[41] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3988,7 +4541,7 @@ func (x *UpstreamConfig) String() string { func (*UpstreamConfig) ProtoMessage() {} func (x *UpstreamConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[41] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4001,7 +4554,7 @@ func (x *UpstreamConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use UpstreamConfig.ProtoReflect.Descriptor instead. func (*UpstreamConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{41} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{47} } func (x *UpstreamConfig) GetName() string { @@ -4102,7 +4655,7 @@ type UpstreamLimits struct { func (x *UpstreamLimits) Reset() { *x = UpstreamLimits{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[42] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4115,7 +4668,7 @@ func (x *UpstreamLimits) String() string { func (*UpstreamLimits) ProtoMessage() {} func (x *UpstreamLimits) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[42] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4128,7 +4681,7 @@ func (x *UpstreamLimits) ProtoReflect() protoreflect.Message { // Deprecated: Use UpstreamLimits.ProtoReflect.Descriptor instead. func (*UpstreamLimits) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{42} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{48} } func (x *UpstreamLimits) GetMaxConnections() int32 { @@ -4176,7 +4729,7 @@ type PassiveHealthCheck struct { func (x *PassiveHealthCheck) Reset() { *x = PassiveHealthCheck{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[43] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4189,7 +4742,7 @@ func (x *PassiveHealthCheck) String() string { func (*PassiveHealthCheck) ProtoMessage() {} func (x *PassiveHealthCheck) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[43] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4202,7 +4755,7 @@ func (x *PassiveHealthCheck) ProtoReflect() protoreflect.Message { // Deprecated: Use PassiveHealthCheck.ProtoReflect.Descriptor instead. func (*PassiveHealthCheck) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{43} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{49} } func (x *PassiveHealthCheck) GetInterval() *durationpb.Duration { @@ -4258,7 +4811,7 @@ type DestinationConfig struct { func (x *DestinationConfig) Reset() { *x = DestinationConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[44] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4271,7 +4824,7 @@ func (x *DestinationConfig) String() string { func (*DestinationConfig) ProtoMessage() {} func (x *DestinationConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[44] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4284,7 +4837,7 @@ func (x *DestinationConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use DestinationConfig.ProtoReflect.Descriptor instead. func (*DestinationConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{44} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{50} } func (x *DestinationConfig) GetAddresses() []string { @@ -4317,7 +4870,7 @@ type RateLimits struct { func (x *RateLimits) Reset() { *x = RateLimits{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[45] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4330,7 +4883,7 @@ func (x *RateLimits) String() string { func (*RateLimits) ProtoMessage() {} func (x *RateLimits) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[45] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4343,7 +4896,7 @@ func (x *RateLimits) ProtoReflect() protoreflect.Message { // Deprecated: Use RateLimits.ProtoReflect.Descriptor instead. func (*RateLimits) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{45} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{51} } func (x *RateLimits) GetInstanceLevel() *InstanceLevelRateLimits { @@ -4373,7 +4926,7 @@ type InstanceLevelRateLimits struct { func (x *InstanceLevelRateLimits) Reset() { *x = InstanceLevelRateLimits{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[46] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4386,7 +4939,7 @@ func (x *InstanceLevelRateLimits) String() string { func (*InstanceLevelRateLimits) ProtoMessage() {} func (x *InstanceLevelRateLimits) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[46] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4399,7 +4952,7 @@ func (x *InstanceLevelRateLimits) ProtoReflect() protoreflect.Message { // Deprecated: Use InstanceLevelRateLimits.ProtoReflect.Descriptor instead. func (*InstanceLevelRateLimits) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{46} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{52} } func (x *InstanceLevelRateLimits) GetRequestsPerSecond() uint32 { @@ -4445,7 +4998,7 @@ type InstanceLevelRouteRateLimits struct { func (x *InstanceLevelRouteRateLimits) Reset() { *x = InstanceLevelRouteRateLimits{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[47] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4458,7 +5011,7 @@ func (x *InstanceLevelRouteRateLimits) String() string { func (*InstanceLevelRouteRateLimits) ProtoMessage() {} func (x *InstanceLevelRouteRateLimits) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[47] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4471,7 +5024,7 @@ func (x *InstanceLevelRouteRateLimits) ProtoReflect() protoreflect.Message { // Deprecated: Use InstanceLevelRouteRateLimits.ProtoReflect.Descriptor instead. func (*InstanceLevelRouteRateLimits) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{47} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{53} } func (x *InstanceLevelRouteRateLimits) GetPathExact() string { @@ -4523,12 +5076,13 @@ type APIGateway struct { Meta map[string]string `protobuf:"bytes,1,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Listeners []*APIGatewayListener `protobuf:"bytes,2,rep,name=Listeners,proto3" json:"Listeners,omitempty"` Status *Status `protobuf:"bytes,3,opt,name=Status,proto3" json:"Status,omitempty"` + Hash uint64 `protobuf:"varint,4,opt,name=Hash,proto3" json:"Hash,omitempty"` } func (x *APIGateway) Reset() { *x = APIGateway{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[48] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4541,7 +5095,7 @@ func (x *APIGateway) String() string { func (*APIGateway) ProtoMessage() {} func (x *APIGateway) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[48] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4554,7 +5108,7 @@ func (x *APIGateway) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGateway.ProtoReflect.Descriptor instead. func (*APIGateway) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{48} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{54} } func (x *APIGateway) GetMeta() map[string]string { @@ -4578,6 +5132,13 @@ func (x *APIGateway) GetStatus() *Status { return nil } +func (x *APIGateway) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.Status @@ -4594,7 +5155,7 @@ type Status struct { func (x *Status) Reset() { *x = Status{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[49] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4607,7 +5168,7 @@ func (x *Status) String() string { func (*Status) ProtoMessage() {} func (x *Status) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[49] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4620,7 +5181,7 @@ func (x *Status) ProtoReflect() protoreflect.Message { // Deprecated: Use Status.ProtoReflect.Descriptor instead. func (*Status) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{49} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{55} } func (x *Status) GetConditions() []*Condition { @@ -4652,7 +5213,7 @@ type Condition struct { func (x *Condition) Reset() { *x = Condition{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[50] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4665,7 +5226,7 @@ func (x *Condition) String() string { func (*Condition) ProtoMessage() {} func (x *Condition) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[50] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4678,7 +5239,7 @@ func (x *Condition) ProtoReflect() protoreflect.Message { // Deprecated: Use Condition.ProtoReflect.Descriptor instead. func (*Condition) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{50} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{56} } func (x *Condition) GetType() string { @@ -4747,7 +5308,7 @@ type APIGatewayListener struct { func (x *APIGatewayListener) Reset() { *x = APIGatewayListener{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[51] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4760,7 +5321,7 @@ func (x *APIGatewayListener) String() string { func (*APIGatewayListener) ProtoMessage() {} func (x *APIGatewayListener) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[51] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4773,7 +5334,7 @@ func (x *APIGatewayListener) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayListener.ProtoReflect.Descriptor instead. func (*APIGatewayListener) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{51} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{57} } func (x *APIGatewayListener) GetName() string { @@ -4847,7 +5408,7 @@ type APIGatewayTLSConfiguration struct { func (x *APIGatewayTLSConfiguration) Reset() { *x = APIGatewayTLSConfiguration{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[52] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4860,7 +5421,7 @@ func (x *APIGatewayTLSConfiguration) String() string { func (*APIGatewayTLSConfiguration) ProtoMessage() {} func (x *APIGatewayTLSConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[52] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4873,7 +5434,7 @@ func (x *APIGatewayTLSConfiguration) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayTLSConfiguration.ProtoReflect.Descriptor instead. func (*APIGatewayTLSConfiguration) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{52} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{58} } func (x *APIGatewayTLSConfiguration) GetCertificates() []*ResourceReference { @@ -4921,7 +5482,7 @@ type APIGatewayPolicy struct { func (x *APIGatewayPolicy) Reset() { *x = APIGatewayPolicy{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[53] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4934,7 +5495,7 @@ func (x *APIGatewayPolicy) String() string { func (*APIGatewayPolicy) ProtoMessage() {} func (x *APIGatewayPolicy) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[53] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4947,7 +5508,7 @@ func (x *APIGatewayPolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayPolicy.ProtoReflect.Descriptor instead. func (*APIGatewayPolicy) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{53} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{59} } func (x *APIGatewayPolicy) GetJWT() *APIGatewayJWTRequirement { @@ -4968,7 +5529,7 @@ type APIGatewayJWTRequirement struct { func (x *APIGatewayJWTRequirement) Reset() { *x = APIGatewayJWTRequirement{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[54] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4981,7 +5542,7 @@ func (x *APIGatewayJWTRequirement) String() string { func (*APIGatewayJWTRequirement) ProtoMessage() {} func (x *APIGatewayJWTRequirement) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[54] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4994,7 +5555,7 @@ func (x *APIGatewayJWTRequirement) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayJWTRequirement.ProtoReflect.Descriptor instead. func (*APIGatewayJWTRequirement) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{54} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{60} } func (x *APIGatewayJWTRequirement) GetProviders() []*APIGatewayJWTProvider { @@ -5016,7 +5577,7 @@ type APIGatewayJWTProvider struct { func (x *APIGatewayJWTProvider) Reset() { *x = APIGatewayJWTProvider{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[55] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5029,7 +5590,7 @@ func (x *APIGatewayJWTProvider) String() string { func (*APIGatewayJWTProvider) ProtoMessage() {} func (x *APIGatewayJWTProvider) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[55] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5042,7 +5603,7 @@ func (x *APIGatewayJWTProvider) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayJWTProvider.ProtoReflect.Descriptor instead. func (*APIGatewayJWTProvider) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{55} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{61} } func (x *APIGatewayJWTProvider) GetName() string { @@ -5071,7 +5632,7 @@ type APIGatewayJWTClaimVerification struct { func (x *APIGatewayJWTClaimVerification) Reset() { *x = APIGatewayJWTClaimVerification{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[56] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5084,7 +5645,7 @@ func (x *APIGatewayJWTClaimVerification) String() string { func (*APIGatewayJWTClaimVerification) ProtoMessage() {} func (x *APIGatewayJWTClaimVerification) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[56] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5097,7 +5658,7 @@ func (x *APIGatewayJWTClaimVerification) ProtoReflect() protoreflect.Message { // Deprecated: Use APIGatewayJWTClaimVerification.ProtoReflect.Descriptor instead. func (*APIGatewayJWTClaimVerification) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{56} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{62} } func (x *APIGatewayJWTClaimVerification) GetPath() []string { @@ -5134,7 +5695,7 @@ type ResourceReference struct { func (x *ResourceReference) Reset() { *x = ResourceReference{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[57] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5147,7 +5708,7 @@ func (x *ResourceReference) String() string { func (*ResourceReference) ProtoMessage() {} func (x *ResourceReference) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[57] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5160,7 +5721,7 @@ func (x *ResourceReference) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceReference.ProtoReflect.Descriptor instead. func (*ResourceReference) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{57} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{63} } func (x *ResourceReference) GetKind() string { @@ -5204,12 +5765,15 @@ type BoundAPIGateway struct { Meta map[string]string `protobuf:"bytes,1,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Listeners []*BoundAPIGatewayListener `protobuf:"bytes,2,rep,name=Listeners,proto3" json:"Listeners,omitempty"` + // mog: func-to=serviceRefsToStructs func-from=serviceRefFromStructs + Services map[string]*ListOfResourceReference `protobuf:"bytes,3,rep,name=Services,proto3" json:"Services,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Hash uint64 `protobuf:"varint,4,opt,name=Hash,proto3" json:"Hash,omitempty"` } func (x *BoundAPIGateway) Reset() { *x = BoundAPIGateway{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[58] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5222,7 +5786,7 @@ func (x *BoundAPIGateway) String() string { func (*BoundAPIGateway) ProtoMessage() {} func (x *BoundAPIGateway) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[58] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[64] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5235,7 +5799,7 @@ func (x *BoundAPIGateway) ProtoReflect() protoreflect.Message { // Deprecated: Use BoundAPIGateway.ProtoReflect.Descriptor instead. func (*BoundAPIGateway) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{58} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{64} } func (x *BoundAPIGateway) GetMeta() map[string]string { @@ -5252,38 +5816,45 @@ func (x *BoundAPIGateway) GetListeners() []*BoundAPIGatewayListener { return nil } -// mog annotation: -// -// target=github.com/hashicorp/consul/agent/structs.BoundAPIGatewayListener -// output=config_entry.gen.go -// name=Structs -type BoundAPIGatewayListener struct { +func (x *BoundAPIGateway) GetServices() map[string]*ListOfResourceReference { + if x != nil { + return x.Services + } + return nil +} + +func (x *BoundAPIGateway) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + +type ListOfResourceReference struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` - Certificates []*ResourceReference `protobuf:"bytes,2,rep,name=Certificates,proto3" json:"Certificates,omitempty"` - Routes []*ResourceReference `protobuf:"bytes,3,rep,name=Routes,proto3" json:"Routes,omitempty"` + Ref []*ResourceReference `protobuf:"bytes,1,rep,name=Ref,proto3" json:"Ref,omitempty"` } -func (x *BoundAPIGatewayListener) Reset() { - *x = BoundAPIGatewayListener{} +func (x *ListOfResourceReference) Reset() { + *x = ListOfResourceReference{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[59] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *BoundAPIGatewayListener) String() string { +func (x *ListOfResourceReference) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BoundAPIGatewayListener) ProtoMessage() {} +func (*ListOfResourceReference) ProtoMessage() {} -func (x *BoundAPIGatewayListener) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[59] +func (x *ListOfResourceReference) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[65] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5294,35 +5865,166 @@ func (x *BoundAPIGatewayListener) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BoundAPIGatewayListener.ProtoReflect.Descriptor instead. -func (*BoundAPIGatewayListener) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{59} -} - -func (x *BoundAPIGatewayListener) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *BoundAPIGatewayListener) GetCertificates() []*ResourceReference { - if x != nil { - return x.Certificates - } - return nil +// Deprecated: Use ListOfResourceReference.ProtoReflect.Descriptor instead. +func (*ListOfResourceReference) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{65} } -func (x *BoundAPIGatewayListener) GetRoutes() []*ResourceReference { +func (x *ListOfResourceReference) GetRef() []*ResourceReference { if x != nil { - return x.Routes + return x.Ref } return nil } // mog annotation: // -// target=github.com/hashicorp/consul/agent/structs.InlineCertificateConfigEntry +// target=github.com/hashicorp/consul/agent/structs.BoundAPIGatewayListener +// output=config_entry.gen.go +// name=Structs +type BoundAPIGatewayListener struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + Certificates []*ResourceReference `protobuf:"bytes,2,rep,name=Certificates,proto3" json:"Certificates,omitempty"` + Routes []*ResourceReference `protobuf:"bytes,3,rep,name=Routes,proto3" json:"Routes,omitempty"` +} + +func (x *BoundAPIGatewayListener) Reset() { + *x = BoundAPIGatewayListener{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[66] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BoundAPIGatewayListener) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BoundAPIGatewayListener) ProtoMessage() {} + +func (x *BoundAPIGatewayListener) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[66] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BoundAPIGatewayListener.ProtoReflect.Descriptor instead. +func (*BoundAPIGatewayListener) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{66} +} + +func (x *BoundAPIGatewayListener) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *BoundAPIGatewayListener) GetCertificates() []*ResourceReference { + if x != nil { + return x.Certificates + } + return nil +} + +func (x *BoundAPIGatewayListener) GetRoutes() []*ResourceReference { + if x != nil { + return x.Routes + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.FileSystemCertificateConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +type FileSystemCertificate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta map[string]string `protobuf:"bytes,1,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Certificate string `protobuf:"bytes,2,opt,name=Certificate,proto3" json:"Certificate,omitempty"` + PrivateKey string `protobuf:"bytes,3,opt,name=PrivateKey,proto3" json:"PrivateKey,omitempty"` + Hash uint64 `protobuf:"varint,4,opt,name=Hash,proto3" json:"Hash,omitempty"` +} + +func (x *FileSystemCertificate) Reset() { + *x = FileSystemCertificate{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[67] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FileSystemCertificate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FileSystemCertificate) ProtoMessage() {} + +func (x *FileSystemCertificate) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[67] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FileSystemCertificate.ProtoReflect.Descriptor instead. +func (*FileSystemCertificate) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{67} +} + +func (x *FileSystemCertificate) GetMeta() map[string]string { + if x != nil { + return x.Meta + } + return nil +} + +func (x *FileSystemCertificate) GetCertificate() string { + if x != nil { + return x.Certificate + } + return "" +} + +func (x *FileSystemCertificate) GetPrivateKey() string { + if x != nil { + return x.PrivateKey + } + return "" +} + +func (x *FileSystemCertificate) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.InlineCertificateConfigEntry // output=config_entry.gen.go // name=Structs // ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta @@ -5334,12 +6036,13 @@ type InlineCertificate struct { Meta map[string]string `protobuf:"bytes,1,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Certificate string `protobuf:"bytes,2,opt,name=Certificate,proto3" json:"Certificate,omitempty"` PrivateKey string `protobuf:"bytes,3,opt,name=PrivateKey,proto3" json:"PrivateKey,omitempty"` + Hash uint64 `protobuf:"varint,4,opt,name=Hash,proto3" json:"Hash,omitempty"` } func (x *InlineCertificate) Reset() { *x = InlineCertificate{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[60] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5352,7 +6055,7 @@ func (x *InlineCertificate) String() string { func (*InlineCertificate) ProtoMessage() {} func (x *InlineCertificate) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[60] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[68] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5365,7 +6068,7 @@ func (x *InlineCertificate) ProtoReflect() protoreflect.Message { // Deprecated: Use InlineCertificate.ProtoReflect.Descriptor instead. func (*InlineCertificate) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{60} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{68} } func (x *InlineCertificate) GetMeta() map[string]string { @@ -5389,6 +6092,13 @@ func (x *InlineCertificate) GetPrivateKey() string { return "" } +func (x *InlineCertificate) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.HTTPRouteConfigEntry @@ -5405,12 +6115,13 @@ type HTTPRoute struct { Rules []*HTTPRouteRule `protobuf:"bytes,3,rep,name=Rules,proto3" json:"Rules,omitempty"` Hostnames []string `protobuf:"bytes,4,rep,name=Hostnames,proto3" json:"Hostnames,omitempty"` Status *Status `protobuf:"bytes,5,opt,name=Status,proto3" json:"Status,omitempty"` + Hash uint64 `protobuf:"varint,6,opt,name=Hash,proto3" json:"Hash,omitempty"` } func (x *HTTPRoute) Reset() { *x = HTTPRoute{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[61] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5423,7 +6134,7 @@ func (x *HTTPRoute) String() string { func (*HTTPRoute) ProtoMessage() {} func (x *HTTPRoute) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[61] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[69] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5436,7 +6147,7 @@ func (x *HTTPRoute) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPRoute.ProtoReflect.Descriptor instead. func (*HTTPRoute) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{61} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{69} } func (x *HTTPRoute) GetMeta() map[string]string { @@ -5474,6 +6185,13 @@ func (x *HTTPRoute) GetStatus() *Status { return nil } +func (x *HTTPRoute) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.HTTPRouteRule @@ -5493,7 +6211,7 @@ type HTTPRouteRule struct { func (x *HTTPRouteRule) Reset() { *x = HTTPRouteRule{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[62] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5506,7 +6224,7 @@ func (x *HTTPRouteRule) String() string { func (*HTTPRouteRule) ProtoMessage() {} func (x *HTTPRouteRule) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[62] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[70] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5519,7 +6237,7 @@ func (x *HTTPRouteRule) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPRouteRule.ProtoReflect.Descriptor instead. func (*HTTPRouteRule) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{62} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{70} } func (x *HTTPRouteRule) GetFilters() *HTTPFilters { @@ -5570,7 +6288,7 @@ type HTTPMatch struct { func (x *HTTPMatch) Reset() { *x = HTTPMatch{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[63] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5583,7 +6301,7 @@ func (x *HTTPMatch) String() string { func (*HTTPMatch) ProtoMessage() {} func (x *HTTPMatch) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[63] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[71] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5596,7 +6314,7 @@ func (x *HTTPMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPMatch.ProtoReflect.Descriptor instead. func (*HTTPMatch) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{63} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{71} } func (x *HTTPMatch) GetHeaders() []*HTTPHeaderMatch { @@ -5646,7 +6364,7 @@ type HTTPHeaderMatch struct { func (x *HTTPHeaderMatch) Reset() { *x = HTTPHeaderMatch{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[64] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5659,7 +6377,7 @@ func (x *HTTPHeaderMatch) String() string { func (*HTTPHeaderMatch) ProtoMessage() {} func (x *HTTPHeaderMatch) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[64] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[72] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5672,7 +6390,7 @@ func (x *HTTPHeaderMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPHeaderMatch.ProtoReflect.Descriptor instead. func (*HTTPHeaderMatch) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{64} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{72} } func (x *HTTPHeaderMatch) GetMatch() HTTPHeaderMatchType { @@ -5714,7 +6432,7 @@ type HTTPPathMatch struct { func (x *HTTPPathMatch) Reset() { *x = HTTPPathMatch{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[65] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5727,7 +6445,7 @@ func (x *HTTPPathMatch) String() string { func (*HTTPPathMatch) ProtoMessage() {} func (x *HTTPPathMatch) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[65] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[73] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5740,7 +6458,7 @@ func (x *HTTPPathMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPPathMatch.ProtoReflect.Descriptor instead. func (*HTTPPathMatch) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{65} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{73} } func (x *HTTPPathMatch) GetMatch() HTTPPathMatchType { @@ -5776,7 +6494,7 @@ type HTTPQueryMatch struct { func (x *HTTPQueryMatch) Reset() { *x = HTTPQueryMatch{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[66] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5789,7 +6507,7 @@ func (x *HTTPQueryMatch) String() string { func (*HTTPQueryMatch) ProtoMessage() {} func (x *HTTPQueryMatch) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[66] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[74] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5802,7 +6520,7 @@ func (x *HTTPQueryMatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPQueryMatch.ProtoReflect.Descriptor instead. func (*HTTPQueryMatch) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{66} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{74} } func (x *HTTPQueryMatch) GetMatch() HTTPQueryMatchType { @@ -5847,7 +6565,7 @@ type HTTPFilters struct { func (x *HTTPFilters) Reset() { *x = HTTPFilters{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[67] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5860,7 +6578,7 @@ func (x *HTTPFilters) String() string { func (*HTTPFilters) ProtoMessage() {} func (x *HTTPFilters) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[67] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[75] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5873,7 +6591,7 @@ func (x *HTTPFilters) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPFilters.ProtoReflect.Descriptor instead. func (*HTTPFilters) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{67} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{75} } func (x *HTTPFilters) GetHeaders() []*HTTPHeaderFilter { @@ -5927,7 +6645,7 @@ type HTTPResponseFilters struct { func (x *HTTPResponseFilters) Reset() { *x = HTTPResponseFilters{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[68] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5940,7 +6658,7 @@ func (x *HTTPResponseFilters) String() string { func (*HTTPResponseFilters) ProtoMessage() {} func (x *HTTPResponseFilters) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[68] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[76] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5953,7 +6671,7 @@ func (x *HTTPResponseFilters) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPResponseFilters.ProtoReflect.Descriptor instead. func (*HTTPResponseFilters) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{68} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{76} } func (x *HTTPResponseFilters) GetHeaders() []*HTTPHeaderFilter { @@ -5979,7 +6697,7 @@ type URLRewrite struct { func (x *URLRewrite) Reset() { *x = URLRewrite{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[69] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5992,7 +6710,7 @@ func (x *URLRewrite) String() string { func (*URLRewrite) ProtoMessage() {} func (x *URLRewrite) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[69] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[77] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6005,7 +6723,7 @@ func (x *URLRewrite) ProtoReflect() protoreflect.Message { // Deprecated: Use URLRewrite.ProtoReflect.Descriptor instead. func (*URLRewrite) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{69} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{77} } func (x *URLRewrite) GetPath() string { @@ -6034,7 +6752,7 @@ type RetryFilter struct { func (x *RetryFilter) Reset() { *x = RetryFilter{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[70] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6047,7 +6765,7 @@ func (x *RetryFilter) String() string { func (*RetryFilter) ProtoMessage() {} func (x *RetryFilter) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[70] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[78] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6060,7 +6778,7 @@ func (x *RetryFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryFilter.ProtoReflect.Descriptor instead. func (*RetryFilter) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{70} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{78} } func (x *RetryFilter) GetNumRetries() uint32 { @@ -6110,7 +6828,7 @@ type TimeoutFilter struct { func (x *TimeoutFilter) Reset() { *x = TimeoutFilter{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[71] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6123,7 +6841,7 @@ func (x *TimeoutFilter) String() string { func (*TimeoutFilter) ProtoMessage() {} func (x *TimeoutFilter) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[71] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[79] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6136,7 +6854,7 @@ func (x *TimeoutFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use TimeoutFilter.ProtoReflect.Descriptor instead. func (*TimeoutFilter) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{71} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{79} } func (x *TimeoutFilter) GetRequestTimeout() *durationpb.Duration { @@ -6164,7 +6882,7 @@ type JWTFilter struct { func (x *JWTFilter) Reset() { *x = JWTFilter{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[72] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6177,7 +6895,7 @@ func (x *JWTFilter) String() string { func (*JWTFilter) ProtoMessage() {} func (x *JWTFilter) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[72] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[80] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6190,7 +6908,7 @@ func (x *JWTFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTFilter.ProtoReflect.Descriptor instead. func (*JWTFilter) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{72} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{80} } func (x *JWTFilter) GetProviders() []*APIGatewayJWTProvider { @@ -6218,7 +6936,7 @@ type HTTPHeaderFilter struct { func (x *HTTPHeaderFilter) Reset() { *x = HTTPHeaderFilter{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[73] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6231,7 +6949,7 @@ func (x *HTTPHeaderFilter) String() string { func (*HTTPHeaderFilter) ProtoMessage() {} func (x *HTTPHeaderFilter) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[73] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[81] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6244,7 +6962,7 @@ func (x *HTTPHeaderFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPHeaderFilter.ProtoReflect.Descriptor instead. func (*HTTPHeaderFilter) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{73} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{81} } func (x *HTTPHeaderFilter) GetAdd() map[string]string { @@ -6290,7 +7008,7 @@ type HTTPService struct { func (x *HTTPService) Reset() { *x = HTTPService{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[74] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6303,7 +7021,7 @@ func (x *HTTPService) String() string { func (*HTTPService) ProtoMessage() {} func (x *HTTPService) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[74] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[82] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6316,7 +7034,7 @@ func (x *HTTPService) ProtoReflect() protoreflect.Message { // Deprecated: Use HTTPService.ProtoReflect.Descriptor instead. func (*HTTPService) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{74} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{82} } func (x *HTTPService) GetName() string { @@ -6369,12 +7087,13 @@ type TCPRoute struct { Parents []*ResourceReference `protobuf:"bytes,2,rep,name=Parents,proto3" json:"Parents,omitempty"` Services []*TCPService `protobuf:"bytes,3,rep,name=Services,proto3" json:"Services,omitempty"` Status *Status `protobuf:"bytes,4,opt,name=Status,proto3" json:"Status,omitempty"` + Hash uint64 `protobuf:"varint,5,opt,name=Hash,proto3" json:"Hash,omitempty"` } func (x *TCPRoute) Reset() { *x = TCPRoute{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[75] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6387,7 +7106,7 @@ func (x *TCPRoute) String() string { func (*TCPRoute) ProtoMessage() {} func (x *TCPRoute) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[75] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[83] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6400,7 +7119,7 @@ func (x *TCPRoute) ProtoReflect() protoreflect.Message { // Deprecated: Use TCPRoute.ProtoReflect.Descriptor instead. func (*TCPRoute) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{75} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{83} } func (x *TCPRoute) GetMeta() map[string]string { @@ -6431,6 +7150,13 @@ func (x *TCPRoute) GetStatus() *Status { return nil } +func (x *TCPRoute) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.TCPService @@ -6449,7 +7175,7 @@ type TCPService struct { func (x *TCPService) Reset() { *x = TCPService{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[76] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6462,7 +7188,7 @@ func (x *TCPService) String() string { func (*TCPService) ProtoMessage() {} func (x *TCPService) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[76] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[84] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6475,7 +7201,7 @@ func (x *TCPService) ProtoReflect() protoreflect.Message { // Deprecated: Use TCPService.ProtoReflect.Descriptor instead. func (*TCPService) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{76} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{84} } func (x *TCPService) GetName() string { @@ -6510,12 +7236,13 @@ type SamenessGroup struct { Meta map[string]string `protobuf:"bytes,5,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // mog: func-to=enterpriseMetaToStructs func-from=enterpriseMetaFromStructs EnterpriseMeta *pbcommon.EnterpriseMeta `protobuf:"bytes,6,opt,name=EnterpriseMeta,proto3" json:"EnterpriseMeta,omitempty"` + Hash uint64 `protobuf:"varint,7,opt,name=Hash,proto3" json:"Hash,omitempty"` } func (x *SamenessGroup) Reset() { *x = SamenessGroup{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[77] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6528,7 +7255,7 @@ func (x *SamenessGroup) String() string { func (*SamenessGroup) ProtoMessage() {} func (x *SamenessGroup) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[77] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[85] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6541,7 +7268,7 @@ func (x *SamenessGroup) ProtoReflect() protoreflect.Message { // Deprecated: Use SamenessGroup.ProtoReflect.Descriptor instead. func (*SamenessGroup) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{77} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{85} } func (x *SamenessGroup) GetName() string { @@ -6586,8 +7313,15 @@ func (x *SamenessGroup) GetEnterpriseMeta() *pbcommon.EnterpriseMeta { return nil } -// mog annotation: -// +func (x *SamenessGroup) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + +// mog annotation: +// // target=github.com/hashicorp/consul/agent/structs.SamenessGroupMember // output=config_entry.gen.go // name=Structs @@ -6603,7 +7337,7 @@ type SamenessGroupMember struct { func (x *SamenessGroupMember) Reset() { *x = SamenessGroupMember{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[78] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6616,7 +7350,7 @@ func (x *SamenessGroupMember) String() string { func (*SamenessGroupMember) ProtoMessage() {} func (x *SamenessGroupMember) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[78] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[86] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6629,7 +7363,7 @@ func (x *SamenessGroupMember) ProtoReflect() protoreflect.Message { // Deprecated: Use SamenessGroupMember.ProtoReflect.Descriptor instead. func (*SamenessGroupMember) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{78} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{86} } func (x *SamenessGroupMember) GetPartition() string { @@ -6665,13 +7399,14 @@ type JWTProvider struct { CacheConfig *JWTCacheConfig `protobuf:"bytes,6,opt,name=CacheConfig,proto3" json:"CacheConfig,omitempty"` Meta map[string]string `protobuf:"bytes,7,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // mog: func-to=int func-from=int32 - ClockSkewSeconds int32 `protobuf:"varint,8,opt,name=ClockSkewSeconds,proto3" json:"ClockSkewSeconds,omitempty"` + ClockSkewSeconds int32 `protobuf:"varint,8,opt,name=ClockSkewSeconds,proto3" json:"ClockSkewSeconds,omitempty"` + Hash uint64 `protobuf:"varint,9,opt,name=Hash,proto3" json:"Hash,omitempty"` } func (x *JWTProvider) Reset() { *x = JWTProvider{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[79] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6684,7 +7419,7 @@ func (x *JWTProvider) String() string { func (*JWTProvider) ProtoMessage() {} func (x *JWTProvider) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[79] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[87] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6697,7 +7432,7 @@ func (x *JWTProvider) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTProvider.ProtoReflect.Descriptor instead. func (*JWTProvider) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{79} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{87} } func (x *JWTProvider) GetJSONWebKeySet() *JSONWebKeySet { @@ -6756,6 +7491,13 @@ func (x *JWTProvider) GetClockSkewSeconds() int32 { return 0 } +func (x *JWTProvider) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.JSONWebKeySet @@ -6773,7 +7515,7 @@ type JSONWebKeySet struct { func (x *JSONWebKeySet) Reset() { *x = JSONWebKeySet{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[80] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6786,7 +7528,7 @@ func (x *JSONWebKeySet) String() string { func (*JSONWebKeySet) ProtoMessage() {} func (x *JSONWebKeySet) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[80] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[88] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6799,7 +7541,7 @@ func (x *JSONWebKeySet) ProtoReflect() protoreflect.Message { // Deprecated: Use JSONWebKeySet.ProtoReflect.Descriptor instead. func (*JSONWebKeySet) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{80} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{88} } func (x *JSONWebKeySet) GetLocal() *LocalJWKS { @@ -6833,7 +7575,7 @@ type LocalJWKS struct { func (x *LocalJWKS) Reset() { *x = LocalJWKS{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[81] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6846,7 +7588,7 @@ func (x *LocalJWKS) String() string { func (*LocalJWKS) ProtoMessage() {} func (x *LocalJWKS) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[81] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[89] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6859,7 +7601,7 @@ func (x *LocalJWKS) ProtoReflect() protoreflect.Message { // Deprecated: Use LocalJWKS.ProtoReflect.Descriptor instead. func (*LocalJWKS) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{81} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{89} } func (x *LocalJWKS) GetJWKS() string { @@ -6899,7 +7641,7 @@ type RemoteJWKS struct { func (x *RemoteJWKS) Reset() { *x = RemoteJWKS{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[82] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6912,7 +7654,7 @@ func (x *RemoteJWKS) String() string { func (*RemoteJWKS) ProtoMessage() {} func (x *RemoteJWKS) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[82] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[90] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6925,7 +7667,7 @@ func (x *RemoteJWKS) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoteJWKS.ProtoReflect.Descriptor instead. func (*RemoteJWKS) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{82} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{90} } func (x *RemoteJWKS) GetURI() string { @@ -6989,7 +7731,7 @@ type JWKSCluster struct { func (x *JWKSCluster) Reset() { *x = JWKSCluster{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[83] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7002,7 +7744,7 @@ func (x *JWKSCluster) String() string { func (*JWKSCluster) ProtoMessage() {} func (x *JWKSCluster) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[83] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[91] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7015,7 +7757,7 @@ func (x *JWKSCluster) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSCluster.ProtoReflect.Descriptor instead. func (*JWKSCluster) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{83} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{91} } func (x *JWKSCluster) GetDiscoveryType() string { @@ -7056,7 +7798,7 @@ type JWKSTLSCertificate struct { func (x *JWKSTLSCertificate) Reset() { *x = JWKSTLSCertificate{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[84] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7069,7 +7811,7 @@ func (x *JWKSTLSCertificate) String() string { func (*JWKSTLSCertificate) ProtoMessage() {} func (x *JWKSTLSCertificate) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[84] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[92] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7082,7 +7824,7 @@ func (x *JWKSTLSCertificate) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSTLSCertificate.ProtoReflect.Descriptor instead. func (*JWKSTLSCertificate) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{84} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{92} } func (x *JWKSTLSCertificate) GetCaCertificateProviderInstance() *JWKSTLSCertProviderInstance { @@ -7116,7 +7858,7 @@ type JWKSTLSCertProviderInstance struct { func (x *JWKSTLSCertProviderInstance) Reset() { *x = JWKSTLSCertProviderInstance{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[85] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7129,7 +7871,7 @@ func (x *JWKSTLSCertProviderInstance) String() string { func (*JWKSTLSCertProviderInstance) ProtoMessage() {} func (x *JWKSTLSCertProviderInstance) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[85] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[93] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7142,7 +7884,7 @@ func (x *JWKSTLSCertProviderInstance) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSTLSCertProviderInstance.ProtoReflect.Descriptor instead. func (*JWKSTLSCertProviderInstance) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{85} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{93} } func (x *JWKSTLSCertProviderInstance) GetInstanceName() string { @@ -7178,7 +7920,7 @@ type JWKSTLSCertTrustedCA struct { func (x *JWKSTLSCertTrustedCA) Reset() { *x = JWKSTLSCertTrustedCA{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[86] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7191,7 +7933,7 @@ func (x *JWKSTLSCertTrustedCA) String() string { func (*JWKSTLSCertTrustedCA) ProtoMessage() {} func (x *JWKSTLSCertTrustedCA) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[86] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[94] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7204,7 +7946,7 @@ func (x *JWKSTLSCertTrustedCA) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSTLSCertTrustedCA.ProtoReflect.Descriptor instead. func (*JWKSTLSCertTrustedCA) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{86} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{94} } func (x *JWKSTLSCertTrustedCA) GetFilename() string { @@ -7253,7 +7995,7 @@ type JWKSRetryPolicy struct { func (x *JWKSRetryPolicy) Reset() { *x = JWKSRetryPolicy{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[87] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7266,7 +8008,7 @@ func (x *JWKSRetryPolicy) String() string { func (*JWKSRetryPolicy) ProtoMessage() {} func (x *JWKSRetryPolicy) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[87] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[95] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7279,7 +8021,7 @@ func (x *JWKSRetryPolicy) ProtoReflect() protoreflect.Message { // Deprecated: Use JWKSRetryPolicy.ProtoReflect.Descriptor instead. func (*JWKSRetryPolicy) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{87} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{95} } func (x *JWKSRetryPolicy) GetNumRetries() int32 { @@ -7315,7 +8057,7 @@ type RetryPolicyBackOff struct { func (x *RetryPolicyBackOff) Reset() { *x = RetryPolicyBackOff{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[88] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7328,7 +8070,7 @@ func (x *RetryPolicyBackOff) String() string { func (*RetryPolicyBackOff) ProtoMessage() {} func (x *RetryPolicyBackOff) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[88] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[96] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7341,7 +8083,7 @@ func (x *RetryPolicyBackOff) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryPolicyBackOff.ProtoReflect.Descriptor instead. func (*RetryPolicyBackOff) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{88} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{96} } func (x *RetryPolicyBackOff) GetBaseInterval() *durationpb.Duration { @@ -7376,7 +8118,7 @@ type JWTLocation struct { func (x *JWTLocation) Reset() { *x = JWTLocation{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[89] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7389,7 +8131,7 @@ func (x *JWTLocation) String() string { func (*JWTLocation) ProtoMessage() {} func (x *JWTLocation) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[89] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[97] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7402,7 +8144,7 @@ func (x *JWTLocation) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTLocation.ProtoReflect.Descriptor instead. func (*JWTLocation) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{89} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{97} } func (x *JWTLocation) GetHeader() *JWTLocationHeader { @@ -7444,7 +8186,7 @@ type JWTLocationHeader struct { func (x *JWTLocationHeader) Reset() { *x = JWTLocationHeader{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[90] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7457,7 +8199,7 @@ func (x *JWTLocationHeader) String() string { func (*JWTLocationHeader) ProtoMessage() {} func (x *JWTLocationHeader) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[90] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[98] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7470,7 +8212,7 @@ func (x *JWTLocationHeader) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTLocationHeader.ProtoReflect.Descriptor instead. func (*JWTLocationHeader) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{90} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{98} } func (x *JWTLocationHeader) GetName() string { @@ -7510,7 +8252,7 @@ type JWTLocationQueryParam struct { func (x *JWTLocationQueryParam) Reset() { *x = JWTLocationQueryParam{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[91] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7523,7 +8265,7 @@ func (x *JWTLocationQueryParam) String() string { func (*JWTLocationQueryParam) ProtoMessage() {} func (x *JWTLocationQueryParam) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[91] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[99] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7536,7 +8278,7 @@ func (x *JWTLocationQueryParam) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTLocationQueryParam.ProtoReflect.Descriptor instead. func (*JWTLocationQueryParam) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{91} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{99} } func (x *JWTLocationQueryParam) GetName() string { @@ -7562,7 +8304,7 @@ type JWTLocationCookie struct { func (x *JWTLocationCookie) Reset() { *x = JWTLocationCookie{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[92] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7575,7 +8317,7 @@ func (x *JWTLocationCookie) String() string { func (*JWTLocationCookie) ProtoMessage() {} func (x *JWTLocationCookie) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[92] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[100] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7588,7 +8330,7 @@ func (x *JWTLocationCookie) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTLocationCookie.ProtoReflect.Descriptor instead. func (*JWTLocationCookie) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{92} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{100} } func (x *JWTLocationCookie) GetName() string { @@ -7615,7 +8357,7 @@ type JWTForwardingConfig struct { func (x *JWTForwardingConfig) Reset() { *x = JWTForwardingConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[93] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7628,7 +8370,7 @@ func (x *JWTForwardingConfig) String() string { func (*JWTForwardingConfig) ProtoMessage() {} func (x *JWTForwardingConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[93] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[101] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7641,7 +8383,7 @@ func (x *JWTForwardingConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTForwardingConfig.ProtoReflect.Descriptor instead. func (*JWTForwardingConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{93} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{101} } func (x *JWTForwardingConfig) GetHeaderName() string { @@ -7675,7 +8417,7 @@ type JWTCacheConfig struct { func (x *JWTCacheConfig) Reset() { *x = JWTCacheConfig{} if protoimpl.UnsafeEnabled { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[94] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7688,7 +8430,7 @@ func (x *JWTCacheConfig) String() string { func (*JWTCacheConfig) ProtoMessage() {} func (x *JWTCacheConfig) ProtoReflect() protoreflect.Message { - mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[94] + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[102] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7701,7 +8443,7 @@ func (x *JWTCacheConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use JWTCacheConfig.ProtoReflect.Descriptor instead. func (*JWTCacheConfig) Descriptor() ([]byte, []int) { - return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{94} + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{102} } func (x *JWTCacheConfig) GetSize() int32 { @@ -7711,6 +8453,228 @@ func (x *JWTCacheConfig) GetSize() int32 { return 0 } +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.ExportedServicesConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +type ExportedServices struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + // mog: func-to=enterpriseMetaToStructs func-from=enterpriseMetaFromStructs + EnterpriseMeta *pbcommon.EnterpriseMeta `protobuf:"bytes,2,opt,name=EnterpriseMeta,proto3" json:"EnterpriseMeta,omitempty"` + Meta map[string]string `protobuf:"bytes,3,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Hash uint64 `protobuf:"varint,4,opt,name=Hash,proto3" json:"Hash,omitempty"` + Services []*ExportedServicesService `protobuf:"bytes,5,rep,name=Services,proto3" json:"Services,omitempty"` +} + +func (x *ExportedServices) Reset() { + *x = ExportedServices{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[103] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExportedServices) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExportedServices) ProtoMessage() {} + +func (x *ExportedServices) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[103] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExportedServices.ProtoReflect.Descriptor instead. +func (*ExportedServices) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{103} +} + +func (x *ExportedServices) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ExportedServices) GetEnterpriseMeta() *pbcommon.EnterpriseMeta { + if x != nil { + return x.EnterpriseMeta + } + return nil +} + +func (x *ExportedServices) GetMeta() map[string]string { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ExportedServices) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + +func (x *ExportedServices) GetServices() []*ExportedServicesService { + if x != nil { + return x.Services + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.ExportedService +// output=config_entry.gen.go +// name=Structs +type ExportedServicesService struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=Namespace,proto3" json:"Namespace,omitempty"` + Consumers []*ExportedServicesConsumer `protobuf:"bytes,3,rep,name=Consumers,proto3" json:"Consumers,omitempty"` +} + +func (x *ExportedServicesService) Reset() { + *x = ExportedServicesService{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[104] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExportedServicesService) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExportedServicesService) ProtoMessage() {} + +func (x *ExportedServicesService) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[104] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExportedServicesService.ProtoReflect.Descriptor instead. +func (*ExportedServicesService) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{104} +} + +func (x *ExportedServicesService) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ExportedServicesService) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *ExportedServicesService) GetConsumers() []*ExportedServicesConsumer { + if x != nil { + return x.Consumers + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.ServiceConsumer +// output=config_entry.gen.go +// name=Structs +type ExportedServicesConsumer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Partition string `protobuf:"bytes,1,opt,name=Partition,proto3" json:"Partition,omitempty"` + Peer string `protobuf:"bytes,2,opt,name=Peer,proto3" json:"Peer,omitempty"` + SamenessGroup string `protobuf:"bytes,3,opt,name=SamenessGroup,proto3" json:"SamenessGroup,omitempty"` +} + +func (x *ExportedServicesConsumer) Reset() { + *x = ExportedServicesConsumer{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[105] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExportedServicesConsumer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExportedServicesConsumer) ProtoMessage() {} + +func (x *ExportedServicesConsumer) ProtoReflect() protoreflect.Message { + mi := &file_private_pbconfigentry_config_entry_proto_msgTypes[105] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExportedServicesConsumer.ProtoReflect.Descriptor instead. +func (*ExportedServicesConsumer) Descriptor() ([]byte, []int) { + return file_private_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{105} +} + +func (x *ExportedServicesConsumer) GetPartition() string { + if x != nil { + return x.Partition + } + return "" +} + +func (x *ExportedServicesConsumer) GetPeer() string { + if x != nil { + return x.Peer + } + return "" +} + +func (x *ExportedServicesConsumer) GetSamenessGroup() string { + if x != nil { + return x.SamenessGroup + } + return "" +} + var File_private_pbconfigentry_config_entry_proto protoreflect.FileDescriptor var file_private_pbconfigentry_config_entry_proto_rawDesc = []byte{ @@ -7719,1599 +8683,1832 @@ var file_private_pbconfigentry_config_entry_proto_rawDesc = []byte{ 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x1d, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0xf2, 0x0a, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x3f, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x4b, 0x69, - 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x79, 0x1a, 0x25, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x72, + 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x2f, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x70, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x42, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, + 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x81, 0x01, 0x0a, + 0x23, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, + 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x22, 0xdd, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x45, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, + 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x12, 0x49, 0x0a, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x12, 0x4e, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x52, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x53, 0x0a, 0x0a, 0x4d, - 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x48, 0x00, 0x52, 0x0a, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x62, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, - 0x72, 0x48, 0x00, 0x52, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x12, 0x5f, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, - 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x48, 0x00, 0x52, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x68, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x11, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x62, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, - 0x48, 0x00, 0x52, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x73, 0x12, 0x53, 0x0a, 0x0a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x48, 0x00, 0x52, 0x0a, 0x41, 0x50, - 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x62, 0x0a, 0x0f, 0x42, 0x6f, 0x75, 0x6e, - 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6d, 0x65, 0x72, 0x73, 0x52, 0x09, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, + 0x22, 0x41, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x12, 0x14, 0x0a, + 0x05, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x50, 0x65, + 0x65, 0x72, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x22, 0xcf, 0x0c, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x3f, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, - 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x48, 0x00, 0x52, 0x0f, 0x42, 0x6f, 0x75, - 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4d, 0x0a, 0x08, - 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, - 0x00, 0x52, 0x08, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x50, 0x0a, 0x09, 0x48, - 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x48, 0x00, 0x52, 0x09, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x68, 0x0a, - 0x11, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x48, 0x00, 0x52, 0x11, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x5c, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, - 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, + 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, + 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x12, 0x49, 0x0a, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, + 0x65, 0x78, 0x52, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x53, 0x0a, + 0x0a, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x0a, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x62, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, + 0x76, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x5f, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, + 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x56, 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x48, 0x00, 0x52, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x68, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x11, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x62, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x48, 0x00, - 0x52, 0x0b, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x42, 0x07, 0x0a, - 0x05, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xb8, 0x04, 0x0a, 0x0a, 0x4d, 0x65, 0x73, 0x68, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x6d, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, - 0x72, 0x6f, 0x78, 0x79, 0x12, 0x46, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x4c, - 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x49, 0x0a, 0x04, - 0x48, 0x54, 0x54, 0x50, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, + 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x73, 0x48, 0x00, 0x52, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x53, 0x0a, 0x0a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x48, 0x00, 0x52, 0x0a, + 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x62, 0x0a, 0x0f, 0x42, 0x6f, + 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, + 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x48, 0x00, 0x52, 0x0f, 0x42, + 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4d, + 0x0a, 0x08, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x48, 0x00, 0x52, 0x08, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x50, 0x0a, + 0x09, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x48, 0x00, 0x52, 0x09, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, + 0x68, 0x0a, 0x11, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x48, 0x54, 0x54, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x4f, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x11, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x5c, 0x0a, 0x0d, 0x53, 0x61, 0x6d, + 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, + 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, + 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x56, 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x48, 0x00, 0x52, 0x0b, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, + 0x65, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x48, 0x00, 0x52, 0x10, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x74, 0x0a, 0x15, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, + 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, - 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x52, 0x0a, 0x07, 0x50, 0x65, 0x65, 0x72, - 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x46, 0x69, + 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x15, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x42, 0x07, 0x0a, 0x05, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xf8, 0x04, 0x0a, 0x0a, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x6d, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, + 0x6f, 0x78, 0x79, 0x12, 0x46, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x4c, 0x53, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x49, 0x0a, 0x04, 0x48, + 0x54, 0x54, 0x50, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x4a, 0x0a, 0x20, - 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x76, 0x65, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6e, 0x61, - 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x76, 0x65, 0x4d, - 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0x50, 0x0a, 0x1a, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x32, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x68, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x4d, - 0x65, 0x73, 0x68, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4f, - 0x6e, 0x6c, 0x79, 0x22, 0xc9, 0x01, 0x0a, 0x0d, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x4c, 0x53, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5b, 0x0a, 0x08, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, - 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x4d, 0x65, 0x73, 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x54, - 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, - 0x6e, 0x67, 0x12, 0x5b, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x48, 0x54, 0x54, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x4f, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, - 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x22, - 0x8a, 0x01, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24, 0x0a, 0x0d, - 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, - 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, - 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x54, 0x0a, 0x0e, + 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x52, 0x0a, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, + 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x4a, 0x0a, 0x20, 0x41, + 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x76, 0x65, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x76, 0x65, 0x4d, 0x75, + 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x10, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0x50, 0x0a, 0x1a, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, + 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x68, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x4d, 0x65, + 0x73, 0x68, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4f, 0x6e, + 0x6c, 0x79, 0x22, 0xc9, 0x01, 0x0a, 0x0d, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x4c, 0x53, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5b, 0x0a, 0x08, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, + 0x65, 0x73, 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x54, 0x4c, + 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, + 0x67, 0x12, 0x5b, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, + 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x22, 0x8a, + 0x01, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24, 0x0a, 0x0d, 0x54, + 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, + 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, + 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0xb2, 0x01, 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x68, 0x48, 0x54, 0x54, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x1c, 0x53, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x58, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x53, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x58, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, - 0x72, 0x74, 0x22, 0x4d, 0x0a, 0x11, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x73, - 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x0a, 0x17, 0x50, 0x65, 0x65, 0x72, 0x54, - 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x50, 0x65, 0x65, 0x72, 0x54, 0x68, - 0x72, 0x6f, 0x75, 0x67, 0x68, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x73, 0x22, 0xb9, 0x08, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x44, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x5d, 0x0a, 0x07, 0x53, - 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, + 0x72, 0x74, 0x12, 0x5c, 0x0a, 0x08, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, + 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x48, 0x54, 0x54, 0x50, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, + 0x22, 0x96, 0x01, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x48, 0x54, 0x54, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x79, + 0x0a, 0x14, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x07, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x12, 0x5a, 0x0a, 0x08, 0x52, 0x65, - 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x72, 0x6d, + 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x14, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x72, 0x6d, + 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4d, 0x0a, 0x11, 0x50, 0x65, 0x65, + 0x72, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, + 0x0a, 0x17, 0x50, 0x65, 0x65, 0x72, 0x54, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x4d, 0x65, 0x73, + 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x17, 0x50, 0x65, 0x65, 0x72, 0x54, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x4d, 0x65, 0x73, 0x68, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x22, 0xa4, 0x03, 0x0a, 0x1e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4a, 0x0a, 0x20, 0x49, + 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, + 0x74, 0x68, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x20, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x44, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x4d, 0x65, 0x72, 0x67, 0x65, + 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x4d, + 0x65, 0x72, 0x67, 0x65, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x87, 0x01, 0x0a, 0x1c, + 0x50, 0x61, 0x74, 0x68, 0x57, 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x53, + 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x57, + 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, + 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x1c, 0x50, 0x61, 0x74, 0x68, 0x57, 0x69, 0x74, + 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x87, 0x01, 0x0a, 0x1c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x73, 0x57, 0x69, 0x74, 0x68, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x08, 0x52, 0x65, - 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x60, 0x0a, 0x08, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, - 0x65, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, - 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, - 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x57, 0x69, 0x74, 0x68, + 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x1c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x57, 0x69, 0x74, 0x68, 0x55, 0x6e, + 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, + 0xcd, 0x08, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, + 0x76, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x75, + 0x62, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x44, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x5d, 0x0a, 0x07, 0x53, 0x75, 0x62, + 0x73, 0x65, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x72, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x07, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x12, 0x5a, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x08, 0x52, 0x65, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x12, 0x60, 0x0a, 0x08, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, 0x46, + 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x46, 0x61, + 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x57, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, + 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x72, 0x52, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x72, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x57, 0x0a, 0x0c, 0x4c, - 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x52, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x0e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x7e, 0x0a, - 0x14, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4a, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x14, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, - 0x69, 0x7a, 0x65, 0x42, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x1a, 0x78, 0x0a, - 0x0c, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x52, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x7b, 0x0a, 0x0d, 0x46, 0x61, 0x69, 0x6c, 0x6f, - 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x54, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x7e, 0x0a, 0x14, 0x50, + 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, - 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x51, 0x0a, - 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, - 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x20, - 0x0a, 0x0b, 0x4f, 0x6e, 0x6c, 0x79, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0b, 0x4f, 0x6e, 0x6c, 0x79, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, - 0x22, 0xef, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x1c, 0x0a, 0x09, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, - 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, - 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, - 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, - 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, - 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x22, 0xfd, 0x02, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x18, + 0x72, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x14, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, + 0x65, 0x42, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x48, + 0x61, 0x73, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, + 0x78, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x52, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x7b, 0x0a, 0x0d, 0x46, 0x61, 0x69, + 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x54, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, + 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0x51, 0x0a, 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x72, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x12, 0x20, 0x0a, 0x0b, 0x4f, 0x6e, 0x6c, 0x79, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x4f, 0x6e, 0x6c, 0x79, 0x50, 0x61, 0x73, 0x73, 0x69, + 0x6e, 0x67, 0x22, 0xef, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, - 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x5e, - 0x0a, 0x07, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x5c, - 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x44, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x24, 0x0a, 0x0d, - 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x22, 0x4d, 0x0a, 0x1d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, - 0x73, 0x22, 0x39, 0x0a, 0x23, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x42, 0x79, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0xcf, 0x01, 0x0a, - 0x1d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, - 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x18, - 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x1c, - 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, + 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, - 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x22, 0xc7, - 0x02, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, - 0x16, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x5d, 0x0a, 0x0e, 0x52, 0x69, 0x6e, 0x67, 0x48, - 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x69, 0x0a, 0x12, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x12, 0x4c, - 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x55, 0x0a, 0x0c, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0c, 0x48, 0x61, 0x73, 0x68, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x0e, 0x52, 0x69, 0x6e, 0x67, - 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, 0x0f, 0x4d, 0x69, - 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x0f, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, - 0x53, 0x69, 0x7a, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x52, - 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x4d, - 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x36, - 0x0a, 0x12, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x43, 0x68, 0x6f, 0x69, 0x63, - 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xd3, 0x01, 0x0a, 0x0a, 0x48, 0x61, 0x73, 0x68, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x43, - 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x24, + 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x22, 0xfd, 0x02, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, + 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, + 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x73, + 0x12, 0x5e, 0x0a, 0x07, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x50, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x50, - 0x12, 0x1a, 0x0a, 0x08, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x08, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x69, 0x0a, 0x0c, - 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, - 0x54, 0x54, 0x4c, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x22, 0x98, 0x03, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, - 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x49, 0x0a, 0x03, 0x54, 0x4c, - 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x54, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, - 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, - 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x53, 0x0a, 0x04, 0x4d, - 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, + 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, + 0x12, 0x5c, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x24, + 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x22, 0x4d, 0x0a, 0x1d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, + 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x52, 0x65, 0x67, 0x69, + 0x6f, 0x6e, 0x73, 0x22, 0x39, 0x0a, 0x23, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, + 0x42, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x4d, 0x6f, + 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0xcf, + 0x01, 0x0a, 0x1d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, + 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, + 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, + 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, + 0x50, 0x65, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, + 0x22, 0xc7, 0x02, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x72, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x5d, 0x0a, 0x0e, 0x52, 0x69, 0x6e, + 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, + 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, + 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x69, 0x0a, 0x12, 0x4c, 0x65, 0x61, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x65, 0x61, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x12, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x55, 0x0a, 0x0c, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, - 0x12, 0x57, 0x0a, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, - 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x8f, 0x02, 0x0a, 0x14, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x26, 0x0a, 0x0e, 0x4d, - 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x12, 0x50, 0x61, 0x73, - 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x61, - 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x22, 0xea, 0x01, 0x0a, 0x10, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x45, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x45, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x12, 0x4c, 0x0a, 0x03, 0x53, 0x44, 0x53, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x53, 0x44, - 0x53, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, - 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, - 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, - 0x73, 0x22, 0x5b, 0x0a, 0x13, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, - 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x65, - 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xdf, - 0x01, 0x0a, 0x0f, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, - 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x79, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0c, 0x48, 0x61, + 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x0e, 0x52, 0x69, + 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, 0x0f, + 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, + 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, + 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0f, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x52, 0x69, 0x6e, 0x67, 0x53, 0x69, 0x7a, 0x65, + 0x22, 0x36, 0x0a, 0x12, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x43, 0x68, 0x6f, + 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xd3, 0x01, 0x0a, 0x0a, 0x48, 0x61, 0x73, + 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1e, 0x0a, + 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x57, 0x0a, + 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6f, 0x6b, + 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x50, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x50, 0x12, 0x1a, 0x0a, 0x08, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x69, + 0x0a, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, + 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x03, 0x54, 0x54, 0x4c, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x22, 0xac, 0x03, 0x0a, 0x0e, 0x49, 0x6e, + 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x49, 0x0a, 0x03, + 0x54, 0x4c, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x54, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, + 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, + 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x53, 0x0a, + 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, + 0x74, 0x61, 0x12, 0x57, 0x0a, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, - 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, - 0x22, 0xb7, 0x06, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x50, 0x0a, - 0x03, 0x54, 0x4c, 0x53, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, + 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, + 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, + 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8f, 0x02, 0x0a, 0x14, 0x49, 0x6e, 0x67, + 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x26, 0x0a, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, + 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, + 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, + 0x69, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0xea, 0x01, 0x0a, 0x10, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x18, 0x0a, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x4c, 0x0a, 0x03, 0x53, 0x44, 0x53, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x03, 0x53, 0x44, 0x53, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x69, + 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, + 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, + 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, + 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, + 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x13, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, + 0x0a, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x22, 0xdf, 0x01, 0x0a, 0x0f, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, - 0x62, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x73, 0x52, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x73, 0x12, 0x64, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, - 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x53, 0x0a, 0x04, 0x4d, 0x65, 0x74, - 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, - 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x58, - 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x26, 0x0a, 0x0e, 0x4d, 0x61, 0x78, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x4d, 0x61, - 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, - 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, - 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, - 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x12, 0x50, - 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x67, 0x0a, 0x17, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x4c, 0x53, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4c, 0x0a, 0x03, 0x53, 0x44, 0x53, 0x18, 0x01, 0x20, 0x01, + 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x03, 0x54, + 0x4c, 0x53, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x22, 0xb7, 0x06, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x48, 0x6f, + 0x73, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x62, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x64, 0x0a, 0x0f, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, - 0x53, 0x44, 0x53, 0x22, 0xcb, 0x02, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x12, 0x55, 0x0a, 0x03, 0x41, - 0x64, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, 0x0f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, + 0x53, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, + 0x4d, 0x65, 0x74, 0x61, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, + 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, + 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x26, + 0x0a, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x12, + 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, - 0x69, 0x65, 0x72, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x41, - 0x64, 0x64, 0x12, 0x55, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x2e, 0x53, 0x65, 0x74, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x53, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x1a, 0x36, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x36, 0x0a, 0x08, 0x53, 0x65, 0x74, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0xc8, 0x02, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x50, 0x0a, 0x07, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0x67, 0x0a, 0x17, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4c, 0x0a, 0x03, 0x53, + 0x44, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x07, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x56, 0x0a, 0x04, 0x4d, 0x65, 0x74, - 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, - 0x61, 0x12, 0x50, 0x0a, 0x03, 0x4a, 0x57, 0x54, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, + 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x53, 0x44, 0x53, 0x22, 0xcb, 0x02, 0x0a, 0x13, 0x48, 0x54, + 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x73, 0x12, 0x55, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, - 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, - 0x4a, 0x57, 0x54, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x74, 0x0a, 0x17, - 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x59, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x73, 0x22, 0x94, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, - 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x68, 0x0a, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x03, 0x41, 0x64, 0x64, 0x12, 0x55, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, - 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x56, 0x65, 0x72, - 0x69, 0x66, 0x79, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x22, 0x49, 0x0a, 0x1d, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, - 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, - 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, - 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0xcc, 0x06, 0x0a, 0x0f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x06, - 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x0b, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x50, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x72, - 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, - 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x4c, 0x65, - 0x67, 0x61, 0x63, 0x79, 0x49, 0x44, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x4c, 0x65, - 0x67, 0x61, 0x63, 0x79, 0x49, 0x44, 0x12, 0x4e, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, + 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x73, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x53, 0x65, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x1a, 0x36, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, + 0x36, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdc, 0x02, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x50, 0x0a, + 0x07, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, + 0x56, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x50, 0x0a, 0x03, 0x4a, 0x57, 0x54, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x66, 0x0a, 0x0a, 0x4c, 0x65, 0x67, 0x61, - 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, - 0x12, 0x46, 0x0a, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x54, 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x4c, 0x65, 0x67, 0x61, - 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, - 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, - 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, - 0x74, 0x61, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, - 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x24, - 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, - 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x1a, 0x3d, 0x0a, 0x0f, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, - 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0x8b, 0x02, 0x0a, 0x13, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x06, 0x41, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x04, 0x48, - 0x54, 0x54, 0x50, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x50, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, - 0x50, 0x0a, 0x03, 0x4a, 0x57, 0x54, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, - 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, 0x4a, 0x57, - 0x54, 0x22, 0xed, 0x01, 0x0a, 0x17, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, - 0x54, 0x54, 0x50, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, - 0x09, 0x50, 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x50, - 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x50, - 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x5c, 0x0a, 0x06, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x73, 0x22, 0xc1, 0x01, 0x0a, 0x1d, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, - 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x72, 0x65, 0x73, 0x65, - 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, - 0x74, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x78, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x45, 0x78, 0x61, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x72, 0x65, 0x66, 0x69, - 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, - 0x16, 0x0a, 0x06, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x16, 0x0a, - 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x49, - 0x6e, 0x76, 0x65, 0x72, 0x74, 0x22, 0xe5, 0x09, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x44, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, - 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x5a, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x12, 0x4b, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x12, - 0x20, 0x0a, 0x0b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x4e, 0x49, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x4e, - 0x49, 0x12, 0x64, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x15, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x4d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, - 0x34, 0x0a, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x3c, 0x0a, 0x19, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x51, 0x0a, 0x0a, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, - 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x0a, 0x52, 0x61, 0x74, 0x65, - 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0d, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, + 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, + 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x74, 0x0a, 0x17, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x12, 0x59, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x5a, 0x0a, 0x0f, - 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, - 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, - 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x0d, 0x4d, 0x75, 0x74, 0x75, - 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0x94, 0x01, 0x0a, + 0x14, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x68, 0x0a, 0x0c, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, - 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, - 0x4d, 0x6f, 0x64, 0x65, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x74, 0x0a, - 0x16, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, - 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x0a, 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x44, - 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0e, 0x44, 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x6c, 0x79, 0x22, 0x5f, 0x0a, 0x11, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4a, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, + 0x6e, 0x4a, 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, 0x61, + 0x69, 0x6d, 0x73, 0x22, 0x49, 0x0a, 0x1d, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, + 0x4a, 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xcc, + 0x06, 0x0a, 0x0f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, - 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, - 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x6f, 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, 0x47, 0x0a, 0x05, - 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x0b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, - 0x50, 0x61, 0x74, 0x68, 0x73, 0x22, 0xb0, 0x01, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x50, 0x61, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, - 0x50, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x4c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, - 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x28, - 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, - 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0xbf, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x73, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x53, 0x0a, 0x09, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, + 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, + 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x44, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x44, + 0x12, 0x4e, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x66, 0x0a, 0x0a, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, + 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4c, + 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, + 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x46, 0x0a, 0x10, 0x4c, 0x65, + 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, + 0x6d, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, + 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x1a, 0x3d, + 0x0a, 0x0f, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8b, 0x02, + 0x0a, 0x13, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, - 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x8a, 0x05, 0x0a, 0x0e, 0x55, - 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x50, 0x0a, 0x03, 0x4a, 0x57, 0x54, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x57, 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x22, 0xed, 0x01, 0x0a, 0x17, + 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x45, + 0x78, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, + 0x45, 0x78, 0x61, 0x63, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, + 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, + 0x67, 0x65, 0x78, 0x12, 0x5c, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x22, 0xfd, 0x01, 0x0a, 0x1d, + 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, - 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x45, + 0x78, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x78, 0x61, 0x63, + 0x74, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x75, 0x66, + 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x75, 0x66, 0x66, 0x69, + 0x78, 0x12, 0x14, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, + 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x12, + 0x1a, 0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x49, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, 0x73, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, 0x73, 0x65, 0x22, 0xf9, 0x09, 0x0a, 0x0f, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, + 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x44, 0x0a, 0x04, 0x4d, + 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x11, 0x45, - 0x6e, 0x76, 0x6f, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4c, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x2a, 0x0a, 0x10, 0x45, 0x6e, 0x76, - 0x6f, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x10, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x12, 0x2a, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x4d, 0x0a, - 0x06, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x12, - 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x4d, 0x6f, 0x64, + 0x65, 0x12, 0x69, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x5a, 0x0a, 0x0b, + 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x4d, 0x65, 0x73, + 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4b, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x6f, + 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x52, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x5a, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, - 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x12, 0x3e, 0x0a, 0x1a, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x4f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x22, 0x9e, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x4d, 0x61, - 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, - 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x15, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0x9e, 0x02, 0x0a, 0x12, 0x50, 0x61, 0x73, - 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, - 0x35, 0x0a, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x61, 0x78, 0x46, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x4d, 0x61, 0x78, - 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x45, 0x6e, 0x66, 0x6f, - 0x72, 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, - 0x35, 0x78, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x17, 0x45, 0x6e, 0x66, 0x6f, 0x72, - 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, - 0x78, 0x78, 0x12, 0x2e, 0x0a, 0x12, 0x4d, 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, - 0x4d, 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, - 0x6e, 0x74, 0x12, 0x45, 0x0a, 0x10, 0x42, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x42, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x45, 0x0a, 0x11, 0x44, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, - 0x0a, 0x09, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x09, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, - 0x22, 0x72, 0x0a, 0x0a, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x64, - 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x61, 0x74, 0x65, 0x4c, - 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, - 0x65, 0x76, 0x65, 0x6c, 0x22, 0xd0, 0x01, 0x0a, 0x17, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, - 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, - 0x12, 0x2c, 0x0a, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, - 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, - 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, 0x12, 0x5b, 0x0a, 0x06, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, + 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x45, + 0x78, 0x70, 0x6f, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x53, 0x4e, 0x49, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x45, 0x78, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x4e, 0x49, 0x12, 0x64, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x55, + 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5a, 0x0a, + 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x44, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x15, 0x4d, 0x61, 0x78, + 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x34, 0x0a, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, + 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x3c, 0x0a, 0x19, 0x42, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x51, 0x0a, 0x0a, 0x52, 0x61, 0x74, + 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, + 0x52, 0x0a, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x04, + 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, - 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x1c, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x61, - 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, - 0x45, 0x78, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, - 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x61, 0x74, 0x68, - 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, - 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, - 0x65, 0x67, 0x65, 0x78, 0x12, 0x2c, 0x0a, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, - 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, - 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, 0x22, 0xb6, - 0x02, 0x0a, 0x0a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4f, 0x0a, - 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, + 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, + 0x74, 0x61, 0x12, 0x5a, 0x0a, 0x0f, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x4d, - 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x57, - 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x37, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, + 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x45, + 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, + 0x0a, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x18, + 0x0f, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x75, + 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0d, 0x4d, 0x75, 0x74, + 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, + 0x73, 0x68, 0x18, 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5a, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x50, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x74, 0x0a, 0x16, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x32, 0x0a, 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, + 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x44, 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x44, + 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x22, 0x5f, 0x0a, + 0x11, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x4a, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x6f, + 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, + 0x0a, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, 0x47, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x22, 0x8b, 0x02, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, - 0x06, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x52, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x54, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x45, 0x78, + 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x22, + 0xb0, 0x01, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x22, + 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, + 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, + 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x28, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x73, + 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0f, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x22, 0xbf, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x53, 0x0a, 0x09, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x73, 0x12, 0x51, 0x0a, 0x08, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x70, 0x73, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x44, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x73, 0x22, 0x8a, 0x05, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x11, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4c, 0x69, + 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x11, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4a, + 0x53, 0x4f, 0x4e, 0x12, 0x2a, 0x0a, 0x10, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x45, + 0x6e, 0x76, 0x6f, 0x79, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4a, 0x53, 0x4f, 0x4e, 0x12, + 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x2a, 0x0a, 0x10, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x4d, 0x0a, 0x06, 0x4c, 0x69, 0x6d, 0x69, 0x74, + 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, + 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, + 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x69, + 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x12, 0x50, + 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x12, 0x5a, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, + 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x3e, 0x0a, + 0x1a, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x1a, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, + 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, + 0x72, 0x22, 0x9e, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x69, + 0x6d, 0x69, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x4d, 0x61, + 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x12, + 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x4d, 0x61, 0x78, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x15, + 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x4d, 0x61, 0x78, + 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x73, 0x22, 0x9e, 0x02, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x35, 0x0a, 0x08, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, + 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x61, 0x78, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x4d, 0x61, 0x78, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, + 0x65, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x45, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x43, + 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, 0x78, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x17, 0x45, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x43, 0x6f, + 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x35, 0x78, 0x78, 0x12, 0x2e, 0x0a, 0x12, + 0x4d, 0x61, 0x78, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, + 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x4d, 0x61, 0x78, 0x45, 0x6a, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x45, 0x0a, 0x10, + 0x42, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x10, 0x42, 0x61, 0x73, 0x65, 0x45, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, + 0x69, 0x6d, 0x65, 0x22, 0x45, 0x0a, 0x11, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x72, 0x0a, 0x0a, 0x52, 0x61, + 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x64, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, + 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0xd0, + 0x01, 0x0a, 0x17, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, + 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x10, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, + 0x75, 0x72, 0x73, 0x74, 0x12, 0x5b, 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, + 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x1c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x65, + 0x76, 0x65, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, + 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, + 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x2c, + 0x0a, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x10, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, + 0x4d, 0x61, 0x78, 0x42, 0x75, 0x72, 0x73, 0x74, 0x22, 0xca, 0x02, 0x0a, 0x0a, 0x41, 0x50, 0x49, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4f, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, + 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x57, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, + 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, + 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, + 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x4c, 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x12, 0x4c, - 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, - 0x65, 0x22, 0xb4, 0x03, 0x0a, 0x12, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5d, 0x0a, 0x08, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x41, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x53, 0x0a, 0x03, 0x54, - 0x4c, 0x53, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, + 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5a, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x50, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x22, 0x8b, 0x02, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x52, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x54, 0x0a, + 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x4c, 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x12, 0x4c, 0x61, 0x73, + 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, + 0xb4, 0x03, 0x0a, 0x12, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, + 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x48, 0x6f, + 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x48, 0x6f, + 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5d, 0x0a, 0x08, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x41, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, + 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x53, 0x0a, 0x03, 0x54, 0x4c, 0x53, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, + 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x53, + 0x0a, 0x08, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x12, 0x51, 0x0a, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x07, 0x44, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0xde, 0x01, 0x0a, 0x1a, 0x41, 0x50, 0x49, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, + 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, + 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x65, 0x0a, 0x10, 0x41, 0x50, 0x49, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x51, 0x0a, 0x03, 0x4a, + 0x57, 0x54, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x4c, 0x53, - 0x12, 0x53, 0x0a, 0x08, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x51, 0x0a, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, - 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, - 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0xde, 0x01, 0x0a, 0x1a, 0x41, 0x50, 0x49, - 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, + 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, 0x52, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x22, 0x76, + 0x0a, 0x18, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, 0x52, + 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x5a, 0x0a, 0x09, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, - 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, 0x69, 0x6e, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, 0x61, 0x78, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, - 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, 0x70, - 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x65, 0x0a, 0x10, 0x41, 0x50, 0x49, - 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x51, 0x0a, - 0x03, 0x4a, 0x57, 0x54, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x09, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x15, 0x41, 0x50, 0x49, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x69, 0x0a, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, + 0x61, 0x69, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, - 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x03, 0x4a, 0x57, 0x54, - 0x22, 0x76, 0x0a, 0x18, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, - 0x54, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x5a, 0x0a, 0x09, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x22, + 0x4a, 0x0a, 0x1e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, + 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb7, 0x01, 0x0a, 0x11, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xf1, 0x03, 0x0a, 0x0f, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, + 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, + 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, + 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, + 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, + 0x5c, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, + 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, + 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x60, 0x0a, + 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x44, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x09, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x15, 0x41, 0x50, 0x49, - 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x69, 0x0a, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, - 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, - 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6c, 0x61, 0x69, 0x6d, - 0x73, 0x22, 0x4a, 0x0a, 0x1e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, - 0x57, 0x54, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb7, 0x01, - 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x53, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, - 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xfe, 0x01, 0x0a, 0x0f, 0x42, 0x6f, 0x75, 0x6e, - 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x54, 0x0a, 0x04, 0x4d, - 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, - 0x61, 0x12, 0x5c, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, - 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x1a, - 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdd, 0x01, 0x0a, 0x17, 0x42, 0x6f, 0x75, - 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5c, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, + 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, + 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x7b, 0x0a, 0x0d, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x54, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x66, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x65, 0x0a, 0x17, 0x4c, 0x69, 0x73, + 0x74, 0x4f, 0x66, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x03, 0x52, 0x65, 0x66, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x03, 0x52, 0x65, 0x66, + 0x22, 0xdd, 0x01, 0x0a, 0x17, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, + 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x5c, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, - 0x52, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0xe6, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x56, - 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x50, + 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, + 0x22, 0x82, 0x02, 0x0a, 0x15, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x5a, 0x0a, 0x04, 0x4d, 0x65, + 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x72, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0x99, 0x03, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, - 0x4e, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, - 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, - 0x52, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, + 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xfa, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x56, 0x0a, 0x04, 0x4d, + 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, + 0x65, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, + 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x22, 0xad, 0x03, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x12, 0x4e, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, + 0x12, 0x52, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x50, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x05, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x12, 0x1c, 0x0a, 0x09, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x09, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x45, + 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, + 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x22, 0xdf, 0x02, 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x52, 0x75, 0x6c, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, + 0x54, 0x50, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x73, 0x12, 0x4a, 0x0a, 0x07, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x4e, + 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x50, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x05, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x64, + 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, + 0x48, 0x54, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x73, 0x52, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x73, 0x22, 0xc4, 0x02, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, + 0x63, 0x68, 0x12, 0x50, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x73, 0x12, 0x4e, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, + 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x06, 0x4d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x12, 0x48, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, - 0x1c, 0x0a, 0x09, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x09, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x45, 0x0a, - 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x50, + 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x4b, + 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdf, 0x02, - 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, - 0x4c, 0x0a, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x73, 0x52, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x4a, 0x0a, - 0x07, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x22, 0x8d, 0x01, 0x0a, 0x0f, + 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, + 0x50, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x52, 0x07, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x4e, 0x0a, 0x08, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, + 0x68, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x75, 0x0a, 0x0d, 0x48, + 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x4e, 0x0a, 0x05, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, - 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x64, 0x0a, 0x0f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0f, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, - 0xc4, 0x02, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x50, 0x0a, - 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, - 0x4e, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, - 0x48, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, + 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, + 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x0e, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x4f, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, + 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x22, 0xa9, 0x03, 0x0a, 0x0b, 0x48, 0x54, 0x54, 0x50, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, + 0x12, 0x51, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, + 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x52, 0x0a, 0x55, 0x52, 0x4c, 0x52, + 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, + 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x0d, + 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, + 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x03, 0x4a, 0x57, 0x54, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, + 0x54, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x22, 0x68, 0x0a, 0x13, + 0x48, 0x54, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, + 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0x20, 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, + 0x72, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x22, 0xad, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x74, + 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x4e, 0x75, 0x6d, 0x52, + 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x4e, 0x75, + 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x65, 0x74, 0x72, + 0x79, 0x4f, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x52, 0x65, 0x74, 0x72, 0x79, + 0x4f, 0x6e, 0x12, 0x2e, 0x0a, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x12, + 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, + 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x15, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x22, 0x8f, 0x01, 0x0a, 0x0d, 0x54, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x3b, 0x0a, + 0x0b, 0x49, 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x49, + 0x64, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x67, 0x0a, 0x09, 0x4a, 0x57, + 0x54, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x73, 0x22, 0xc2, 0x02, 0x0a, 0x10, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, + 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x41, + 0x64, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x41, 0x64, 0x64, 0x12, 0x16, 0x0a, 0x06, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x52, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x03, 0x53, 0x65, 0x74, 0x1a, 0x36, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x1a, 0x36, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc7, 0x02, 0x0a, 0x0b, 0x48, 0x54, 0x54, + 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x57, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x12, 0x4c, 0x0a, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, + 0x54, 0x50, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x73, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x64, 0x0a, 0x0f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, + 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x73, 0x52, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x73, 0x22, 0x90, 0x03, 0x0a, 0x08, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, + 0x4d, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, - 0x74, 0x63, 0x68, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x4b, 0x0a, 0x05, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, - 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x22, 0x8d, 0x01, 0x0a, 0x0f, 0x48, 0x54, 0x54, 0x50, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x50, 0x0a, 0x05, 0x4d, 0x61, - 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, - 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x75, 0x0a, 0x0d, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, - 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x4e, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, - 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x8b, 0x01, - 0x0a, 0x0e, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x12, 0x4f, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x4d, + 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x52, + 0x0a, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa9, 0x03, 0x0a, 0x0b, - 0x48, 0x54, 0x54, 0x50, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x51, 0x0a, 0x07, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x68, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x73, 0x12, 0x4d, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, + 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x7a, 0x0a, 0x0a, 0x54, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x22, 0xc8, 0x03, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x44, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x46, 0x6f, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x12, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6f, 0x72, 0x46, + 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x49, + 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x54, 0x0a, 0x07, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x51, - 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x55, 0x52, 0x4c, 0x52, 0x65, - 0x77, 0x72, 0x69, 0x74, 0x65, 0x52, 0x0a, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, - 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, - 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x52, 0x65, 0x74, 0x72, - 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x03, 0x4a, 0x57, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x22, 0x68, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x51, - 0x0a, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x12, 0x52, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x73, 0x22, 0x20, 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, - 0x61, 0x74, 0x68, 0x22, 0xad, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x12, 0x2e, 0x0a, - 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, - 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, - 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x34, 0x0a, - 0x15, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x46, - 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x52, 0x65, - 0x74, 0x72, 0x79, 0x4f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x46, 0x61, 0x69, 0x6c, - 0x75, 0x72, 0x65, 0x22, 0x8f, 0x01, 0x0a, 0x0d, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x3b, 0x0a, 0x0b, 0x49, 0x64, 0x6c, 0x65, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x49, 0x64, 0x6c, 0x65, 0x54, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x67, 0x0a, 0x09, 0x4a, 0x57, 0x54, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, - 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0xc2, - 0x02, 0x0a, 0x10, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x03, 0x41, 0x64, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, - 0x52, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, + 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, + 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, + 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, + 0x61, 0x73, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x47, 0x0a, 0x13, + 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x50, 0x65, 0x65, 0x72, 0x22, 0xf1, 0x04, 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, + 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, - 0x53, 0x65, 0x74, 0x1a, 0x36, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x36, 0x0a, 0x08, 0x53, - 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0xc7, 0x02, 0x0a, 0x0b, 0x48, 0x54, 0x54, 0x50, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x57, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, - 0x4c, 0x0a, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x73, 0x52, 0x07, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x58, 0x0a, - 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x64, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0xfc, 0x02, - 0x0a, 0x08, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x4d, 0x65, - 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x2e, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x52, 0x0a, 0x07, 0x50, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, + 0x65, 0x74, 0x52, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, + 0x74, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x75, 0x64, + 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x41, 0x75, + 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4d, 0x0a, - 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x06, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, + 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, + 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x0a, 0x46, 0x6f, 0x72, + 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, + 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x46, 0x6f, 0x72, 0x77, 0x61, + 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x57, 0x0a, 0x0b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x0b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x50, + 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x7a, 0x0a, 0x0a, - 0x54, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, - 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xb4, 0x03, 0x0a, 0x0d, 0x53, 0x61, 0x6d, - 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, - 0x0a, 0x12, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6f, 0x72, 0x46, 0x61, 0x69, 0x6c, - 0x6f, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x44, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x46, 0x6f, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x22, - 0x0a, 0x0c, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x12, 0x54, 0x0a, 0x07, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, + 0x12, 0x2a, 0x0a, 0x10, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6b, 0x65, 0x77, 0x53, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x43, 0x6c, 0x6f, 0x63, + 0x6b, 0x53, 0x6b, 0x65, 0x77, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, + 0x48, 0x61, 0x73, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x48, 0x61, 0x73, 0x68, + 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa2, 0x01, 0x0a, 0x0d, 0x4a, 0x53, + 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x12, 0x46, 0x0a, 0x05, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x05, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x12, 0x49, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x61, 0x6d, 0x65, - 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, - 0x07, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x52, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, - 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x4d, 0x65, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x58, 0x0a, 0x0e, - 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, - 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, - 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0x47, 0x0a, 0x13, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x22, 0xdd, 0x04, 0x0a, 0x0b, 0x4a, 0x57, 0x54, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, - 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, - 0x65, 0x79, 0x53, 0x65, 0x74, 0x52, 0x0d, 0x4a, 0x53, 0x4f, 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, - 0x79, 0x53, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, - 0x41, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x09, 0x41, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x09, 0x4c, 0x6f, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x0a, - 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x22, 0x3b, + 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x4a, + 0x57, 0x4b, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4a, 0x57, 0x4b, 0x53, 0x12, + 0x1a, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xed, 0x02, 0x0a, 0x0a, + 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x52, + 0x49, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x52, 0x49, 0x12, 0x2a, 0x0a, 0x10, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x3f, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x13, 0x46, 0x65, 0x74, + 0x63, 0x68, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x6f, 0x75, 0x73, 0x6c, 0x79, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x79, + 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x12, 0x58, 0x0a, 0x0b, 0x52, + 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x46, 0x6f, 0x72, 0x77, - 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x46, 0x6f, - 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x57, 0x0a, 0x0b, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x50, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, - 0x65, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x10, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6b, 0x65, 0x77, - 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x43, - 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6b, 0x65, 0x77, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x1a, - 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa2, 0x01, 0x0a, 0x0d, 0x4a, 0x53, 0x4f, - 0x4e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x12, 0x46, 0x0a, 0x05, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x05, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x12, 0x49, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, - 0x65, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x22, 0x3b, 0x0a, - 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x4a, 0x57, - 0x4b, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x1a, - 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xed, 0x02, 0x0a, 0x0a, 0x52, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4a, 0x57, 0x4b, 0x53, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x52, 0x49, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x52, 0x49, 0x12, 0x2a, 0x0a, 0x10, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x3f, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x65, 0x74, + 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x54, 0x0a, 0x0b, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x0b, + 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0xdb, 0x01, 0x0a, 0x0b, + 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x63, 0x0a, 0x0f, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0f, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x13, 0x46, 0x65, 0x74, 0x63, - 0x68, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x46, 0x65, 0x74, 0x63, 0x68, 0x41, 0x73, 0x79, 0x6e, - 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x12, 0x58, 0x0a, 0x0b, 0x52, 0x65, - 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x65, 0x74, 0x72, - 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x12, 0x54, 0x0a, 0x0b, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x4a, - 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0xdb, 0x01, 0x0a, 0x0b, 0x4a, - 0x57, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x69, - 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x63, 0x0a, 0x0f, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x52, 0x0f, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0xfa, 0x01, 0x0a, 0x12, 0x4a, 0x57, 0x4b, - 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, - 0x88, 0x01, 0x0a, 0x1d, 0x43, 0x61, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0xfa, 0x01, 0x0a, 0x12, 0x4a, 0x57, + 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x12, 0x88, 0x01, 0x0a, 0x1d, 0x43, 0x61, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x1d, 0x43, 0x61, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x09, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, + 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x52, 0x09, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x22, 0x6b, 0x0a, 0x1b, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, + 0x53, 0x43, 0x65, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x22, 0xaa, 0x01, 0x0a, 0x14, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, + 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x12, 0x1a, 0x0a, 0x08, + 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x45, 0x6e, 0x76, 0x69, + 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x20, + 0x0a, 0x0b, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x22, 0x9c, 0x01, 0x0a, 0x0f, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, + 0x72, 0x69, 0x65, 0x73, 0x12, 0x69, 0x0a, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x52, 0x12, 0x52, 0x65, 0x74, + 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x22, + 0x90, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, + 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x12, 0x3d, 0x0a, 0x0c, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x0b, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, + 0x61, 0x6c, 0x22, 0x8f, 0x02, 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x5c, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x12, 0x50, 0x0a, 0x06, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x52, 0x06, 0x43, 0x6f, + 0x6f, 0x6b, 0x69, 0x65, 0x22, 0x63, 0x0a, 0x11, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, + 0x0b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, + 0x18, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x22, 0x2b, 0x0a, 0x15, 0x4a, 0x57, 0x54, + 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x27, 0x0a, 0x11, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, + 0x6f, 0x0a, 0x13, 0x4a, 0x57, 0x54, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x17, 0x50, 0x61, 0x64, 0x46, 0x6f, 0x72, + 0x77, 0x61, 0x72, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x50, 0x61, 0x64, 0x46, 0x6f, 0x72, 0x77, + 0x61, 0x72, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x22, 0x24, 0x0a, 0x0e, 0x4a, 0x57, 0x54, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x80, 0x03, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x4e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x1d, 0x43, 0x61, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x09, 0x54, 0x72, - 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, - 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x52, 0x09, 0x54, 0x72, 0x75, 0x73, - 0x74, 0x65, 0x64, 0x43, 0x41, 0x22, 0x6b, 0x0a, 0x1b, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, - 0x43, 0x65, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x22, 0xaa, 0x01, 0x0a, 0x14, 0x4a, 0x57, 0x4b, 0x53, 0x54, 0x4c, 0x53, 0x43, 0x65, - 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x41, 0x12, 0x1a, 0x0a, 0x08, 0x46, - 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x46, - 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, - 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x20, 0x0a, - 0x0b, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0b, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, - 0x9c, 0x01, 0x0a, 0x0f, 0x4a, 0x57, 0x4b, 0x53, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x12, 0x69, 0x0a, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x52, 0x12, 0x52, 0x65, 0x74, 0x72, - 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x22, 0x90, - 0x01, 0x0a, 0x12, 0x52, 0x65, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x61, - 0x63, 0x6b, 0x4f, 0x66, 0x66, 0x12, 0x3d, 0x0a, 0x0c, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x76, 0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x0b, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, - 0x6c, 0x22, 0x8f, 0x02, 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x50, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x12, 0x5c, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x55, 0x0a, 0x04, 0x4d, 0x65, 0x74, + 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x52, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x12, 0x50, 0x0a, 0x06, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x52, 0x06, 0x43, 0x6f, 0x6f, - 0x6b, 0x69, 0x65, 0x22, 0x63, 0x0a, 0x11, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x18, - 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x07, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x22, 0x2b, 0x0a, 0x15, 0x4a, 0x57, 0x54, 0x4c, - 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x27, 0x0a, 0x11, 0x4a, 0x57, 0x54, 0x4c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x6f, - 0x0a, 0x13, 0x4a, 0x57, 0x54, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x17, 0x50, 0x61, 0x64, 0x46, 0x6f, 0x72, 0x77, - 0x61, 0x72, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x50, 0x61, 0x64, 0x46, 0x6f, 0x72, 0x77, 0x61, - 0x72, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, - 0x24, 0x0a, 0x0e, 0x4a, 0x57, 0x54, 0x43, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x12, 0x0a, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x04, 0x53, 0x69, 0x7a, 0x65, 0x2a, 0xa9, 0x02, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0f, - 0x0a, 0x0b, 0x4b, 0x69, 0x6e, 0x64, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, - 0x12, 0x0a, 0x0e, 0x4b, 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, - 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x04, 0x12, - 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x4b, 0x69, 0x6e, 0x64, - 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x10, 0x06, 0x12, 0x12, 0x0a, 0x0e, 0x4b, 0x69, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x07, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x42, - 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x08, - 0x12, 0x11, 0x0a, 0x0d, 0x4b, 0x69, 0x6e, 0x64, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x10, 0x09, 0x12, 0x10, 0x0a, 0x0c, 0x4b, 0x69, 0x6e, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x10, 0x0a, 0x12, 0x15, 0x0a, 0x11, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x61, 0x6d, - 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x10, 0x0b, 0x12, 0x13, 0x0a, 0x0f, - 0x4b, 0x69, 0x6e, 0x64, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x10, - 0x0c, 0x2a, 0x26, 0x0a, 0x0f, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x65, 0x6e, 0x79, 0x10, 0x00, 0x12, 0x09, - 0x0a, 0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x10, 0x01, 0x2a, 0x21, 0x0a, 0x13, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x10, 0x00, 0x2a, 0x50, 0x0a, 0x09, - 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, - 0x18, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x5f, - 0x0a, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x12, - 0x18, 0x0a, 0x14, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, - 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x75, 0x74, - 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x69, 0x63, 0x74, - 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, - 0x6f, 0x64, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x76, 0x65, 0x10, 0x02, 0x2a, - 0x7b, 0x0a, 0x0f, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, - 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x17, - 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, - 0x65, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x68, 0x47, - 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x10, - 0x02, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x10, 0x03, 0x2a, 0x4f, 0x0a, 0x1a, - 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, - 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x14, 0x4c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x48, 0x54, - 0x54, 0x50, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x54, 0x43, 0x50, 0x10, 0x01, 0x2a, 0x92, 0x02, - 0x0a, 0x0f, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x41, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x54, 0x54, - 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, - 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x10, 0x02, - 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x47, 0x65, 0x74, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x48, 0x65, 0x61, 0x64, 0x10, - 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x05, 0x12, 0x18, 0x0a, - 0x14, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x50, 0x61, 0x74, 0x63, 0x68, 0x10, 0x06, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x6f, 0x73, 0x74, 0x10, 0x07, - 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x50, 0x75, 0x74, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x48, 0x54, 0x54, 0x50, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x54, 0x72, 0x61, 0x63, 0x65, - 0x10, 0x09, 0x2a, 0xa7, 0x01, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x48, 0x54, - 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x61, - 0x63, 0x74, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x10, 0x01, 0x12, - 0x1a, 0x0a, 0x16, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, - 0x63, 0x68, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x48, - 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, - 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, - 0x03, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x10, 0x04, 0x2a, 0x68, 0x0a, 0x11, - 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, - 0x63, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, - 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, - 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, - 0x74, 0x63, 0x68, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x2a, 0x6d, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, - 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, - 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x10, 0x01, - 0x12, 0x23, 0x0a, 0x1f, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, - 0x63, 0x68, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x42, 0xae, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x42, 0x10, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x43, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xca, - 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, - 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, + 0x12, 0x12, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, + 0x48, 0x61, 0x73, 0x68, 0x12, 0x5a, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x45, + 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xaa, 0x01, 0x0a, 0x17, 0x45, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6d, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, 0x09, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x22, 0x72, 0x0a, 0x18, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, + 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x50, 0x65, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x61, 0x6d, + 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2a, 0xe2, 0x02, 0x0a, 0x04, 0x4b, + 0x69, 0x6e, 0x64, 0x12, 0x0f, 0x0a, 0x0b, 0x4b, 0x69, 0x6e, 0x64, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, + 0x77, 0x6e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4b, 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x10, + 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x4b, 0x69, 0x6e, + 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x10, 0x05, 0x12, 0x19, 0x0a, + 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x10, 0x06, 0x12, 0x12, 0x0a, 0x0e, 0x4b, 0x69, 0x6e, 0x64, + 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x07, 0x12, 0x17, 0x0a, 0x13, + 0x4b, 0x69, 0x6e, 0x64, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x4b, 0x69, 0x6e, 0x64, 0x48, 0x54, 0x54, + 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0x09, 0x12, 0x10, 0x0a, 0x0c, 0x4b, 0x69, 0x6e, 0x64, + 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0x0a, 0x12, 0x15, 0x0a, 0x11, 0x4b, 0x69, + 0x6e, 0x64, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x10, + 0x0b, 0x12, 0x13, 0x0a, 0x0f, 0x4b, 0x69, 0x6e, 0x64, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x10, 0x0c, 0x12, 0x18, 0x0a, 0x14, 0x4b, 0x69, 0x6e, 0x64, 0x45, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x10, 0x0d, + 0x12, 0x1d, 0x0a, 0x19, 0x4b, 0x69, 0x6e, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x10, 0x0e, 0x2a, + 0xfe, 0x01, 0x0a, 0x1c, 0x50, 0x61, 0x74, 0x68, 0x57, 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, + 0x70, 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x27, 0x0a, 0x23, 0x50, 0x61, 0x74, 0x68, 0x57, 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, + 0x70, 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, 0x50, 0x61, 0x74, + 0x68, 0x57, 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, + 0x68, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x65, 0x70, 0x10, 0x01, 0x12, + 0x26, 0x0a, 0x22, 0x50, 0x61, 0x74, 0x68, 0x57, 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, + 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x6a, 0x65, 0x63, 0x74, 0x10, 0x02, 0x12, 0x33, 0x0a, 0x2f, 0x50, 0x61, 0x74, 0x68, 0x57, + 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, + 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x41, + 0x6e, 0x64, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x03, 0x12, 0x32, 0x0a, 0x2e, + 0x50, 0x61, 0x74, 0x68, 0x57, 0x69, 0x74, 0x68, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x53, + 0x6c, 0x61, 0x73, 0x68, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x65, 0x73, + 0x63, 0x61, 0x70, 0x65, 0x41, 0x6e, 0x64, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x10, 0x04, + 0x2a, 0xa0, 0x01, 0x0a, 0x1c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x57, 0x69, 0x74, 0x68, + 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x25, 0x0a, 0x21, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x57, 0x69, 0x74, 0x68, + 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x10, 0x00, 0x12, 0x2d, 0x0a, 0x29, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x73, 0x57, 0x69, 0x74, 0x68, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, + 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x01, 0x12, 0x2a, 0x0a, 0x26, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x73, 0x57, 0x69, 0x74, 0x68, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x72, 0x6f, 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x10, 0x02, 0x2a, 0x26, 0x0a, 0x0f, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x65, 0x6e, 0x79, 0x10, 0x00, + 0x12, 0x09, 0x0a, 0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x10, 0x01, 0x2a, 0x21, 0x0a, 0x13, 0x49, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x10, 0x00, 0x2a, 0x50, + 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, + 0x00, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, + 0x2a, 0x5f, 0x0a, 0x0d, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, + 0x65, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, + 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4d, + 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x69, + 0x63, 0x74, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x54, 0x4c, + 0x53, 0x4d, 0x6f, 0x64, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x76, 0x65, 0x10, + 0x02, 0x2a, 0x7b, 0x0a, 0x0f, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, + 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, + 0x6f, 0x64, 0x65, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x65, 0x73, + 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x10, 0x03, 0x2a, 0x4f, + 0x0a, 0x1a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, + 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x14, + 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, + 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x54, 0x43, 0x50, 0x10, 0x01, 0x2a, + 0x92, 0x02, 0x0a, 0x0f, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, + 0x68, 0x6f, 0x64, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x48, + 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x47, 0x65, 0x74, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, + 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x48, 0x65, 0x61, + 0x64, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x05, 0x12, + 0x18, 0x0a, 0x14, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x50, 0x61, 0x74, 0x63, 0x68, 0x10, 0x06, 0x12, 0x17, 0x0a, 0x13, 0x48, 0x54, 0x54, + 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x6f, 0x73, 0x74, + 0x10, 0x07, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x75, 0x74, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x48, 0x54, + 0x54, 0x50, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x54, 0x72, 0x61, + 0x63, 0x65, 0x10, 0x09, 0x2a, 0xa7, 0x01, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, + 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x45, + 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x10, + 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x10, 0x02, 0x12, 0x24, 0x0a, + 0x20, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x10, 0x04, 0x2a, 0x68, + 0x0a, 0x11, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x48, + 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x61, 0x74, 0x68, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x2a, 0x6d, 0x0a, 0x12, 0x48, 0x54, 0x54, 0x50, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, + 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, + 0x45, 0x78, 0x61, 0x63, 0x74, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x54, 0x54, 0x50, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, + 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x48, 0x54, 0x54, 0x50, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x45, 0x78, 0x70, 0x72, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x32, 0xd5, 0x01, 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xbe, + 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x45, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x49, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x64, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x4a, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x45, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x0c, 0x42, + 0xae, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x10, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, + 0x43, 0xaa, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xca, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0xe2, 0x02, 0x31, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -9326,318 +10523,353 @@ func file_private_pbconfigentry_config_entry_proto_rawDescGZIP() []byte { return file_private_pbconfigentry_config_entry_proto_rawDescData } -var file_private_pbconfigentry_config_entry_proto_enumTypes = make([]protoimpl.EnumInfo, 11) -var file_private_pbconfigentry_config_entry_proto_msgTypes = make([]protoimpl.MessageInfo, 115) +var file_private_pbconfigentry_config_entry_proto_enumTypes = make([]protoimpl.EnumInfo, 13) +var file_private_pbconfigentry_config_entry_proto_msgTypes = make([]protoimpl.MessageInfo, 129) var file_private_pbconfigentry_config_entry_proto_goTypes = []interface{}{ (Kind)(0), // 0: hashicorp.consul.internal.configentry.Kind - (IntentionAction)(0), // 1: hashicorp.consul.internal.configentry.IntentionAction - (IntentionSourceType)(0), // 2: hashicorp.consul.internal.configentry.IntentionSourceType - (ProxyMode)(0), // 3: hashicorp.consul.internal.configentry.ProxyMode - (MutualTLSMode)(0), // 4: hashicorp.consul.internal.configentry.MutualTLSMode - (MeshGatewayMode)(0), // 5: hashicorp.consul.internal.configentry.MeshGatewayMode - (APIGatewayListenerProtocol)(0), // 6: hashicorp.consul.internal.configentry.APIGatewayListenerProtocol - (HTTPMatchMethod)(0), // 7: hashicorp.consul.internal.configentry.HTTPMatchMethod - (HTTPHeaderMatchType)(0), // 8: hashicorp.consul.internal.configentry.HTTPHeaderMatchType - (HTTPPathMatchType)(0), // 9: hashicorp.consul.internal.configentry.HTTPPathMatchType - (HTTPQueryMatchType)(0), // 10: hashicorp.consul.internal.configentry.HTTPQueryMatchType - (*ConfigEntry)(nil), // 11: hashicorp.consul.internal.configentry.ConfigEntry - (*MeshConfig)(nil), // 12: hashicorp.consul.internal.configentry.MeshConfig - (*TransparentProxyMeshConfig)(nil), // 13: hashicorp.consul.internal.configentry.TransparentProxyMeshConfig - (*MeshTLSConfig)(nil), // 14: hashicorp.consul.internal.configentry.MeshTLSConfig - (*MeshDirectionalTLSConfig)(nil), // 15: hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig - (*MeshHTTPConfig)(nil), // 16: hashicorp.consul.internal.configentry.MeshHTTPConfig - (*PeeringMeshConfig)(nil), // 17: hashicorp.consul.internal.configentry.PeeringMeshConfig - (*ServiceResolver)(nil), // 18: hashicorp.consul.internal.configentry.ServiceResolver - (*ServiceResolverSubset)(nil), // 19: hashicorp.consul.internal.configentry.ServiceResolverSubset - (*ServiceResolverRedirect)(nil), // 20: hashicorp.consul.internal.configentry.ServiceResolverRedirect - (*ServiceResolverFailover)(nil), // 21: hashicorp.consul.internal.configentry.ServiceResolverFailover - (*ServiceResolverFailoverPolicy)(nil), // 22: hashicorp.consul.internal.configentry.ServiceResolverFailoverPolicy - (*ServiceResolverPrioritizeByLocality)(nil), // 23: hashicorp.consul.internal.configentry.ServiceResolverPrioritizeByLocality - (*ServiceResolverFailoverTarget)(nil), // 24: hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget - (*LoadBalancer)(nil), // 25: hashicorp.consul.internal.configentry.LoadBalancer - (*RingHashConfig)(nil), // 26: hashicorp.consul.internal.configentry.RingHashConfig - (*LeastRequestConfig)(nil), // 27: hashicorp.consul.internal.configentry.LeastRequestConfig - (*HashPolicy)(nil), // 28: hashicorp.consul.internal.configentry.HashPolicy - (*CookieConfig)(nil), // 29: hashicorp.consul.internal.configentry.CookieConfig - (*IngressGateway)(nil), // 30: hashicorp.consul.internal.configentry.IngressGateway - (*IngressServiceConfig)(nil), // 31: hashicorp.consul.internal.configentry.IngressServiceConfig - (*GatewayTLSConfig)(nil), // 32: hashicorp.consul.internal.configentry.GatewayTLSConfig - (*GatewayTLSSDSConfig)(nil), // 33: hashicorp.consul.internal.configentry.GatewayTLSSDSConfig - (*IngressListener)(nil), // 34: hashicorp.consul.internal.configentry.IngressListener - (*IngressService)(nil), // 35: hashicorp.consul.internal.configentry.IngressService - (*GatewayServiceTLSConfig)(nil), // 36: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig - (*HTTPHeaderModifiers)(nil), // 37: hashicorp.consul.internal.configentry.HTTPHeaderModifiers - (*ServiceIntentions)(nil), // 38: hashicorp.consul.internal.configentry.ServiceIntentions - (*IntentionJWTRequirement)(nil), // 39: hashicorp.consul.internal.configentry.IntentionJWTRequirement - (*IntentionJWTProvider)(nil), // 40: hashicorp.consul.internal.configentry.IntentionJWTProvider - (*IntentionJWTClaimVerification)(nil), // 41: hashicorp.consul.internal.configentry.IntentionJWTClaimVerification - (*SourceIntention)(nil), // 42: hashicorp.consul.internal.configentry.SourceIntention - (*IntentionPermission)(nil), // 43: hashicorp.consul.internal.configentry.IntentionPermission - (*IntentionHTTPPermission)(nil), // 44: hashicorp.consul.internal.configentry.IntentionHTTPPermission - (*IntentionHTTPHeaderPermission)(nil), // 45: hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission - (*ServiceDefaults)(nil), // 46: hashicorp.consul.internal.configentry.ServiceDefaults - (*TransparentProxyConfig)(nil), // 47: hashicorp.consul.internal.configentry.TransparentProxyConfig - (*MeshGatewayConfig)(nil), // 48: hashicorp.consul.internal.configentry.MeshGatewayConfig - (*ExposeConfig)(nil), // 49: hashicorp.consul.internal.configentry.ExposeConfig - (*ExposePath)(nil), // 50: hashicorp.consul.internal.configentry.ExposePath - (*UpstreamConfiguration)(nil), // 51: hashicorp.consul.internal.configentry.UpstreamConfiguration - (*UpstreamConfig)(nil), // 52: hashicorp.consul.internal.configentry.UpstreamConfig - (*UpstreamLimits)(nil), // 53: hashicorp.consul.internal.configentry.UpstreamLimits - (*PassiveHealthCheck)(nil), // 54: hashicorp.consul.internal.configentry.PassiveHealthCheck - (*DestinationConfig)(nil), // 55: hashicorp.consul.internal.configentry.DestinationConfig - (*RateLimits)(nil), // 56: hashicorp.consul.internal.configentry.RateLimits - (*InstanceLevelRateLimits)(nil), // 57: hashicorp.consul.internal.configentry.InstanceLevelRateLimits - (*InstanceLevelRouteRateLimits)(nil), // 58: hashicorp.consul.internal.configentry.InstanceLevelRouteRateLimits - (*APIGateway)(nil), // 59: hashicorp.consul.internal.configentry.APIGateway - (*Status)(nil), // 60: hashicorp.consul.internal.configentry.Status - (*Condition)(nil), // 61: hashicorp.consul.internal.configentry.Condition - (*APIGatewayListener)(nil), // 62: hashicorp.consul.internal.configentry.APIGatewayListener - (*APIGatewayTLSConfiguration)(nil), // 63: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration - (*APIGatewayPolicy)(nil), // 64: hashicorp.consul.internal.configentry.APIGatewayPolicy - (*APIGatewayJWTRequirement)(nil), // 65: hashicorp.consul.internal.configentry.APIGatewayJWTRequirement - (*APIGatewayJWTProvider)(nil), // 66: hashicorp.consul.internal.configentry.APIGatewayJWTProvider - (*APIGatewayJWTClaimVerification)(nil), // 67: hashicorp.consul.internal.configentry.APIGatewayJWTClaimVerification - (*ResourceReference)(nil), // 68: hashicorp.consul.internal.configentry.ResourceReference - (*BoundAPIGateway)(nil), // 69: hashicorp.consul.internal.configentry.BoundAPIGateway - (*BoundAPIGatewayListener)(nil), // 70: hashicorp.consul.internal.configentry.BoundAPIGatewayListener - (*InlineCertificate)(nil), // 71: hashicorp.consul.internal.configentry.InlineCertificate - (*HTTPRoute)(nil), // 72: hashicorp.consul.internal.configentry.HTTPRoute - (*HTTPRouteRule)(nil), // 73: hashicorp.consul.internal.configentry.HTTPRouteRule - (*HTTPMatch)(nil), // 74: hashicorp.consul.internal.configentry.HTTPMatch - (*HTTPHeaderMatch)(nil), // 75: hashicorp.consul.internal.configentry.HTTPHeaderMatch - (*HTTPPathMatch)(nil), // 76: hashicorp.consul.internal.configentry.HTTPPathMatch - (*HTTPQueryMatch)(nil), // 77: hashicorp.consul.internal.configentry.HTTPQueryMatch - (*HTTPFilters)(nil), // 78: hashicorp.consul.internal.configentry.HTTPFilters - (*HTTPResponseFilters)(nil), // 79: hashicorp.consul.internal.configentry.HTTPResponseFilters - (*URLRewrite)(nil), // 80: hashicorp.consul.internal.configentry.URLRewrite - (*RetryFilter)(nil), // 81: hashicorp.consul.internal.configentry.RetryFilter - (*TimeoutFilter)(nil), // 82: hashicorp.consul.internal.configentry.TimeoutFilter - (*JWTFilter)(nil), // 83: hashicorp.consul.internal.configentry.JWTFilter - (*HTTPHeaderFilter)(nil), // 84: hashicorp.consul.internal.configentry.HTTPHeaderFilter - (*HTTPService)(nil), // 85: hashicorp.consul.internal.configentry.HTTPService - (*TCPRoute)(nil), // 86: hashicorp.consul.internal.configentry.TCPRoute - (*TCPService)(nil), // 87: hashicorp.consul.internal.configentry.TCPService - (*SamenessGroup)(nil), // 88: hashicorp.consul.internal.configentry.SamenessGroup - (*SamenessGroupMember)(nil), // 89: hashicorp.consul.internal.configentry.SamenessGroupMember - (*JWTProvider)(nil), // 90: hashicorp.consul.internal.configentry.JWTProvider - (*JSONWebKeySet)(nil), // 91: hashicorp.consul.internal.configentry.JSONWebKeySet - (*LocalJWKS)(nil), // 92: hashicorp.consul.internal.configentry.LocalJWKS - (*RemoteJWKS)(nil), // 93: hashicorp.consul.internal.configentry.RemoteJWKS - (*JWKSCluster)(nil), // 94: hashicorp.consul.internal.configentry.JWKSCluster - (*JWKSTLSCertificate)(nil), // 95: hashicorp.consul.internal.configentry.JWKSTLSCertificate - (*JWKSTLSCertProviderInstance)(nil), // 96: hashicorp.consul.internal.configentry.JWKSTLSCertProviderInstance - (*JWKSTLSCertTrustedCA)(nil), // 97: hashicorp.consul.internal.configentry.JWKSTLSCertTrustedCA - (*JWKSRetryPolicy)(nil), // 98: hashicorp.consul.internal.configentry.JWKSRetryPolicy - (*RetryPolicyBackOff)(nil), // 99: hashicorp.consul.internal.configentry.RetryPolicyBackOff - (*JWTLocation)(nil), // 100: hashicorp.consul.internal.configentry.JWTLocation - (*JWTLocationHeader)(nil), // 101: hashicorp.consul.internal.configentry.JWTLocationHeader - (*JWTLocationQueryParam)(nil), // 102: hashicorp.consul.internal.configentry.JWTLocationQueryParam - (*JWTLocationCookie)(nil), // 103: hashicorp.consul.internal.configentry.JWTLocationCookie - (*JWTForwardingConfig)(nil), // 104: hashicorp.consul.internal.configentry.JWTForwardingConfig - (*JWTCacheConfig)(nil), // 105: hashicorp.consul.internal.configentry.JWTCacheConfig - nil, // 106: hashicorp.consul.internal.configentry.MeshConfig.MetaEntry - nil, // 107: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry - nil, // 108: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry - nil, // 109: hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry - nil, // 110: hashicorp.consul.internal.configentry.IngressGateway.MetaEntry - nil, // 111: hashicorp.consul.internal.configentry.IngressService.MetaEntry - nil, // 112: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry - nil, // 113: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry - nil, // 114: hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry - nil, // 115: hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry - nil, // 116: hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry - nil, // 117: hashicorp.consul.internal.configentry.APIGateway.MetaEntry - nil, // 118: hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry - nil, // 119: hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry - nil, // 120: hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry - nil, // 121: hashicorp.consul.internal.configentry.HTTPHeaderFilter.AddEntry - nil, // 122: hashicorp.consul.internal.configentry.HTTPHeaderFilter.SetEntry - nil, // 123: hashicorp.consul.internal.configentry.TCPRoute.MetaEntry - nil, // 124: hashicorp.consul.internal.configentry.SamenessGroup.MetaEntry - nil, // 125: hashicorp.consul.internal.configentry.JWTProvider.MetaEntry - (*pbcommon.EnterpriseMeta)(nil), // 126: hashicorp.consul.internal.common.EnterpriseMeta - (*pbcommon.RaftIndex)(nil), // 127: hashicorp.consul.internal.common.RaftIndex - (*durationpb.Duration)(nil), // 128: google.protobuf.Duration - (*timestamppb.Timestamp)(nil), // 129: google.protobuf.Timestamp - (*pbcommon.EnvoyExtension)(nil), // 130: hashicorp.consul.internal.common.EnvoyExtension + (PathWithEscapedSlashesAction)(0), // 1: hashicorp.consul.internal.configentry.PathWithEscapedSlashesAction + (HeadersWithUnderscoresAction)(0), // 2: hashicorp.consul.internal.configentry.HeadersWithUnderscoresAction + (IntentionAction)(0), // 3: hashicorp.consul.internal.configentry.IntentionAction + (IntentionSourceType)(0), // 4: hashicorp.consul.internal.configentry.IntentionSourceType + (ProxyMode)(0), // 5: hashicorp.consul.internal.configentry.ProxyMode + (MutualTLSMode)(0), // 6: hashicorp.consul.internal.configentry.MutualTLSMode + (MeshGatewayMode)(0), // 7: hashicorp.consul.internal.configentry.MeshGatewayMode + (APIGatewayListenerProtocol)(0), // 8: hashicorp.consul.internal.configentry.APIGatewayListenerProtocol + (HTTPMatchMethod)(0), // 9: hashicorp.consul.internal.configentry.HTTPMatchMethod + (HTTPHeaderMatchType)(0), // 10: hashicorp.consul.internal.configentry.HTTPHeaderMatchType + (HTTPPathMatchType)(0), // 11: hashicorp.consul.internal.configentry.HTTPPathMatchType + (HTTPQueryMatchType)(0), // 12: hashicorp.consul.internal.configentry.HTTPQueryMatchType + (*GetResolvedExportedServicesRequest)(nil), // 13: hashicorp.consul.internal.configentry.GetResolvedExportedServicesRequest + (*GetResolvedExportedServicesResponse)(nil), // 14: hashicorp.consul.internal.configentry.GetResolvedExportedServicesResponse + (*ResolvedExportedService)(nil), // 15: hashicorp.consul.internal.configentry.ResolvedExportedService + (*Consumers)(nil), // 16: hashicorp.consul.internal.configentry.Consumers + (*ConfigEntry)(nil), // 17: hashicorp.consul.internal.configentry.ConfigEntry + (*MeshConfig)(nil), // 18: hashicorp.consul.internal.configentry.MeshConfig + (*TransparentProxyMeshConfig)(nil), // 19: hashicorp.consul.internal.configentry.TransparentProxyMeshConfig + (*MeshTLSConfig)(nil), // 20: hashicorp.consul.internal.configentry.MeshTLSConfig + (*MeshDirectionalTLSConfig)(nil), // 21: hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig + (*MeshHTTPConfig)(nil), // 22: hashicorp.consul.internal.configentry.MeshHTTPConfig + (*MeshDirectionalHTTPConfig)(nil), // 23: hashicorp.consul.internal.configentry.MeshDirectionalHTTPConfig + (*PeeringMeshConfig)(nil), // 24: hashicorp.consul.internal.configentry.PeeringMeshConfig + (*RequestNormalizationMeshConfig)(nil), // 25: hashicorp.consul.internal.configentry.RequestNormalizationMeshConfig + (*ServiceResolver)(nil), // 26: hashicorp.consul.internal.configentry.ServiceResolver + (*ServiceResolverSubset)(nil), // 27: hashicorp.consul.internal.configentry.ServiceResolverSubset + (*ServiceResolverRedirect)(nil), // 28: hashicorp.consul.internal.configentry.ServiceResolverRedirect + (*ServiceResolverFailover)(nil), // 29: hashicorp.consul.internal.configentry.ServiceResolverFailover + (*ServiceResolverFailoverPolicy)(nil), // 30: hashicorp.consul.internal.configentry.ServiceResolverFailoverPolicy + (*ServiceResolverPrioritizeByLocality)(nil), // 31: hashicorp.consul.internal.configentry.ServiceResolverPrioritizeByLocality + (*ServiceResolverFailoverTarget)(nil), // 32: hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget + (*LoadBalancer)(nil), // 33: hashicorp.consul.internal.configentry.LoadBalancer + (*RingHashConfig)(nil), // 34: hashicorp.consul.internal.configentry.RingHashConfig + (*LeastRequestConfig)(nil), // 35: hashicorp.consul.internal.configentry.LeastRequestConfig + (*HashPolicy)(nil), // 36: hashicorp.consul.internal.configentry.HashPolicy + (*CookieConfig)(nil), // 37: hashicorp.consul.internal.configentry.CookieConfig + (*IngressGateway)(nil), // 38: hashicorp.consul.internal.configentry.IngressGateway + (*IngressServiceConfig)(nil), // 39: hashicorp.consul.internal.configentry.IngressServiceConfig + (*GatewayTLSConfig)(nil), // 40: hashicorp.consul.internal.configentry.GatewayTLSConfig + (*GatewayTLSSDSConfig)(nil), // 41: hashicorp.consul.internal.configentry.GatewayTLSSDSConfig + (*IngressListener)(nil), // 42: hashicorp.consul.internal.configentry.IngressListener + (*IngressService)(nil), // 43: hashicorp.consul.internal.configentry.IngressService + (*GatewayServiceTLSConfig)(nil), // 44: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig + (*HTTPHeaderModifiers)(nil), // 45: hashicorp.consul.internal.configentry.HTTPHeaderModifiers + (*ServiceIntentions)(nil), // 46: hashicorp.consul.internal.configentry.ServiceIntentions + (*IntentionJWTRequirement)(nil), // 47: hashicorp.consul.internal.configentry.IntentionJWTRequirement + (*IntentionJWTProvider)(nil), // 48: hashicorp.consul.internal.configentry.IntentionJWTProvider + (*IntentionJWTClaimVerification)(nil), // 49: hashicorp.consul.internal.configentry.IntentionJWTClaimVerification + (*SourceIntention)(nil), // 50: hashicorp.consul.internal.configentry.SourceIntention + (*IntentionPermission)(nil), // 51: hashicorp.consul.internal.configentry.IntentionPermission + (*IntentionHTTPPermission)(nil), // 52: hashicorp.consul.internal.configentry.IntentionHTTPPermission + (*IntentionHTTPHeaderPermission)(nil), // 53: hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission + (*ServiceDefaults)(nil), // 54: hashicorp.consul.internal.configentry.ServiceDefaults + (*TransparentProxyConfig)(nil), // 55: hashicorp.consul.internal.configentry.TransparentProxyConfig + (*MeshGatewayConfig)(nil), // 56: hashicorp.consul.internal.configentry.MeshGatewayConfig + (*ExposeConfig)(nil), // 57: hashicorp.consul.internal.configentry.ExposeConfig + (*ExposePath)(nil), // 58: hashicorp.consul.internal.configentry.ExposePath + (*UpstreamConfiguration)(nil), // 59: hashicorp.consul.internal.configentry.UpstreamConfiguration + (*UpstreamConfig)(nil), // 60: hashicorp.consul.internal.configentry.UpstreamConfig + (*UpstreamLimits)(nil), // 61: hashicorp.consul.internal.configentry.UpstreamLimits + (*PassiveHealthCheck)(nil), // 62: hashicorp.consul.internal.configentry.PassiveHealthCheck + (*DestinationConfig)(nil), // 63: hashicorp.consul.internal.configentry.DestinationConfig + (*RateLimits)(nil), // 64: hashicorp.consul.internal.configentry.RateLimits + (*InstanceLevelRateLimits)(nil), // 65: hashicorp.consul.internal.configentry.InstanceLevelRateLimits + (*InstanceLevelRouteRateLimits)(nil), // 66: hashicorp.consul.internal.configentry.InstanceLevelRouteRateLimits + (*APIGateway)(nil), // 67: hashicorp.consul.internal.configentry.APIGateway + (*Status)(nil), // 68: hashicorp.consul.internal.configentry.Status + (*Condition)(nil), // 69: hashicorp.consul.internal.configentry.Condition + (*APIGatewayListener)(nil), // 70: hashicorp.consul.internal.configentry.APIGatewayListener + (*APIGatewayTLSConfiguration)(nil), // 71: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration + (*APIGatewayPolicy)(nil), // 72: hashicorp.consul.internal.configentry.APIGatewayPolicy + (*APIGatewayJWTRequirement)(nil), // 73: hashicorp.consul.internal.configentry.APIGatewayJWTRequirement + (*APIGatewayJWTProvider)(nil), // 74: hashicorp.consul.internal.configentry.APIGatewayJWTProvider + (*APIGatewayJWTClaimVerification)(nil), // 75: hashicorp.consul.internal.configentry.APIGatewayJWTClaimVerification + (*ResourceReference)(nil), // 76: hashicorp.consul.internal.configentry.ResourceReference + (*BoundAPIGateway)(nil), // 77: hashicorp.consul.internal.configentry.BoundAPIGateway + (*ListOfResourceReference)(nil), // 78: hashicorp.consul.internal.configentry.ListOfResourceReference + (*BoundAPIGatewayListener)(nil), // 79: hashicorp.consul.internal.configentry.BoundAPIGatewayListener + (*FileSystemCertificate)(nil), // 80: hashicorp.consul.internal.configentry.FileSystemCertificate + (*InlineCertificate)(nil), // 81: hashicorp.consul.internal.configentry.InlineCertificate + (*HTTPRoute)(nil), // 82: hashicorp.consul.internal.configentry.HTTPRoute + (*HTTPRouteRule)(nil), // 83: hashicorp.consul.internal.configentry.HTTPRouteRule + (*HTTPMatch)(nil), // 84: hashicorp.consul.internal.configentry.HTTPMatch + (*HTTPHeaderMatch)(nil), // 85: hashicorp.consul.internal.configentry.HTTPHeaderMatch + (*HTTPPathMatch)(nil), // 86: hashicorp.consul.internal.configentry.HTTPPathMatch + (*HTTPQueryMatch)(nil), // 87: hashicorp.consul.internal.configentry.HTTPQueryMatch + (*HTTPFilters)(nil), // 88: hashicorp.consul.internal.configentry.HTTPFilters + (*HTTPResponseFilters)(nil), // 89: hashicorp.consul.internal.configentry.HTTPResponseFilters + (*URLRewrite)(nil), // 90: hashicorp.consul.internal.configentry.URLRewrite + (*RetryFilter)(nil), // 91: hashicorp.consul.internal.configentry.RetryFilter + (*TimeoutFilter)(nil), // 92: hashicorp.consul.internal.configentry.TimeoutFilter + (*JWTFilter)(nil), // 93: hashicorp.consul.internal.configentry.JWTFilter + (*HTTPHeaderFilter)(nil), // 94: hashicorp.consul.internal.configentry.HTTPHeaderFilter + (*HTTPService)(nil), // 95: hashicorp.consul.internal.configentry.HTTPService + (*TCPRoute)(nil), // 96: hashicorp.consul.internal.configentry.TCPRoute + (*TCPService)(nil), // 97: hashicorp.consul.internal.configentry.TCPService + (*SamenessGroup)(nil), // 98: hashicorp.consul.internal.configentry.SamenessGroup + (*SamenessGroupMember)(nil), // 99: hashicorp.consul.internal.configentry.SamenessGroupMember + (*JWTProvider)(nil), // 100: hashicorp.consul.internal.configentry.JWTProvider + (*JSONWebKeySet)(nil), // 101: hashicorp.consul.internal.configentry.JSONWebKeySet + (*LocalJWKS)(nil), // 102: hashicorp.consul.internal.configentry.LocalJWKS + (*RemoteJWKS)(nil), // 103: hashicorp.consul.internal.configentry.RemoteJWKS + (*JWKSCluster)(nil), // 104: hashicorp.consul.internal.configentry.JWKSCluster + (*JWKSTLSCertificate)(nil), // 105: hashicorp.consul.internal.configentry.JWKSTLSCertificate + (*JWKSTLSCertProviderInstance)(nil), // 106: hashicorp.consul.internal.configentry.JWKSTLSCertProviderInstance + (*JWKSTLSCertTrustedCA)(nil), // 107: hashicorp.consul.internal.configentry.JWKSTLSCertTrustedCA + (*JWKSRetryPolicy)(nil), // 108: hashicorp.consul.internal.configentry.JWKSRetryPolicy + (*RetryPolicyBackOff)(nil), // 109: hashicorp.consul.internal.configentry.RetryPolicyBackOff + (*JWTLocation)(nil), // 110: hashicorp.consul.internal.configentry.JWTLocation + (*JWTLocationHeader)(nil), // 111: hashicorp.consul.internal.configentry.JWTLocationHeader + (*JWTLocationQueryParam)(nil), // 112: hashicorp.consul.internal.configentry.JWTLocationQueryParam + (*JWTLocationCookie)(nil), // 113: hashicorp.consul.internal.configentry.JWTLocationCookie + (*JWTForwardingConfig)(nil), // 114: hashicorp.consul.internal.configentry.JWTForwardingConfig + (*JWTCacheConfig)(nil), // 115: hashicorp.consul.internal.configentry.JWTCacheConfig + (*ExportedServices)(nil), // 116: hashicorp.consul.internal.configentry.ExportedServices + (*ExportedServicesService)(nil), // 117: hashicorp.consul.internal.configentry.ExportedServicesService + (*ExportedServicesConsumer)(nil), // 118: hashicorp.consul.internal.configentry.ExportedServicesConsumer + nil, // 119: hashicorp.consul.internal.configentry.MeshConfig.MetaEntry + nil, // 120: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry + nil, // 121: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry + nil, // 122: hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry + nil, // 123: hashicorp.consul.internal.configentry.IngressGateway.MetaEntry + nil, // 124: hashicorp.consul.internal.configentry.IngressService.MetaEntry + nil, // 125: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry + nil, // 126: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry + nil, // 127: hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry + nil, // 128: hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry + nil, // 129: hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry + nil, // 130: hashicorp.consul.internal.configentry.APIGateway.MetaEntry + nil, // 131: hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry + nil, // 132: hashicorp.consul.internal.configentry.BoundAPIGateway.ServicesEntry + nil, // 133: hashicorp.consul.internal.configentry.FileSystemCertificate.MetaEntry + nil, // 134: hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry + nil, // 135: hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry + nil, // 136: hashicorp.consul.internal.configentry.HTTPHeaderFilter.AddEntry + nil, // 137: hashicorp.consul.internal.configentry.HTTPHeaderFilter.SetEntry + nil, // 138: hashicorp.consul.internal.configentry.TCPRoute.MetaEntry + nil, // 139: hashicorp.consul.internal.configentry.SamenessGroup.MetaEntry + nil, // 140: hashicorp.consul.internal.configentry.JWTProvider.MetaEntry + nil, // 141: hashicorp.consul.internal.configentry.ExportedServices.MetaEntry + (*pbcommon.EnterpriseMeta)(nil), // 142: hashicorp.consul.internal.common.EnterpriseMeta + (*pbcommon.RaftIndex)(nil), // 143: hashicorp.consul.internal.common.RaftIndex + (*durationpb.Duration)(nil), // 144: google.protobuf.Duration + (*timestamppb.Timestamp)(nil), // 145: google.protobuf.Timestamp + (*pbcommon.EnvoyExtension)(nil), // 146: hashicorp.consul.internal.common.EnvoyExtension } var file_private_pbconfigentry_config_entry_proto_depIdxs = []int32{ - 0, // 0: hashicorp.consul.internal.configentry.ConfigEntry.Kind:type_name -> hashicorp.consul.internal.configentry.Kind - 126, // 1: hashicorp.consul.internal.configentry.ConfigEntry.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 127, // 2: hashicorp.consul.internal.configentry.ConfigEntry.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex - 12, // 3: hashicorp.consul.internal.configentry.ConfigEntry.MeshConfig:type_name -> hashicorp.consul.internal.configentry.MeshConfig - 18, // 4: hashicorp.consul.internal.configentry.ConfigEntry.ServiceResolver:type_name -> hashicorp.consul.internal.configentry.ServiceResolver - 30, // 5: hashicorp.consul.internal.configentry.ConfigEntry.IngressGateway:type_name -> hashicorp.consul.internal.configentry.IngressGateway - 38, // 6: hashicorp.consul.internal.configentry.ConfigEntry.ServiceIntentions:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions - 46, // 7: hashicorp.consul.internal.configentry.ConfigEntry.ServiceDefaults:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults - 59, // 8: hashicorp.consul.internal.configentry.ConfigEntry.APIGateway:type_name -> hashicorp.consul.internal.configentry.APIGateway - 69, // 9: hashicorp.consul.internal.configentry.ConfigEntry.BoundAPIGateway:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway - 86, // 10: hashicorp.consul.internal.configentry.ConfigEntry.TCPRoute:type_name -> hashicorp.consul.internal.configentry.TCPRoute - 72, // 11: hashicorp.consul.internal.configentry.ConfigEntry.HTTPRoute:type_name -> hashicorp.consul.internal.configentry.HTTPRoute - 71, // 12: hashicorp.consul.internal.configentry.ConfigEntry.InlineCertificate:type_name -> hashicorp.consul.internal.configentry.InlineCertificate - 88, // 13: hashicorp.consul.internal.configentry.ConfigEntry.SamenessGroup:type_name -> hashicorp.consul.internal.configentry.SamenessGroup - 90, // 14: hashicorp.consul.internal.configentry.ConfigEntry.JWTProvider:type_name -> hashicorp.consul.internal.configentry.JWTProvider - 13, // 15: hashicorp.consul.internal.configentry.MeshConfig.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyMeshConfig - 14, // 16: hashicorp.consul.internal.configentry.MeshConfig.TLS:type_name -> hashicorp.consul.internal.configentry.MeshTLSConfig - 16, // 17: hashicorp.consul.internal.configentry.MeshConfig.HTTP:type_name -> hashicorp.consul.internal.configentry.MeshHTTPConfig - 106, // 18: hashicorp.consul.internal.configentry.MeshConfig.Meta:type_name -> hashicorp.consul.internal.configentry.MeshConfig.MetaEntry - 17, // 19: hashicorp.consul.internal.configentry.MeshConfig.Peering:type_name -> hashicorp.consul.internal.configentry.PeeringMeshConfig - 15, // 20: hashicorp.consul.internal.configentry.MeshTLSConfig.Incoming:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig - 15, // 21: hashicorp.consul.internal.configentry.MeshTLSConfig.Outgoing:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig - 107, // 22: hashicorp.consul.internal.configentry.ServiceResolver.Subsets:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry - 20, // 23: hashicorp.consul.internal.configentry.ServiceResolver.Redirect:type_name -> hashicorp.consul.internal.configentry.ServiceResolverRedirect - 108, // 24: hashicorp.consul.internal.configentry.ServiceResolver.Failover:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry - 128, // 25: hashicorp.consul.internal.configentry.ServiceResolver.ConnectTimeout:type_name -> google.protobuf.Duration - 25, // 26: hashicorp.consul.internal.configentry.ServiceResolver.LoadBalancer:type_name -> hashicorp.consul.internal.configentry.LoadBalancer - 109, // 27: hashicorp.consul.internal.configentry.ServiceResolver.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry - 128, // 28: hashicorp.consul.internal.configentry.ServiceResolver.RequestTimeout:type_name -> google.protobuf.Duration - 23, // 29: hashicorp.consul.internal.configentry.ServiceResolver.PrioritizeByLocality:type_name -> hashicorp.consul.internal.configentry.ServiceResolverPrioritizeByLocality - 24, // 30: hashicorp.consul.internal.configentry.ServiceResolverFailover.Targets:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget - 22, // 31: hashicorp.consul.internal.configentry.ServiceResolverFailover.Policy:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailoverPolicy - 26, // 32: hashicorp.consul.internal.configentry.LoadBalancer.RingHashConfig:type_name -> hashicorp.consul.internal.configentry.RingHashConfig - 27, // 33: hashicorp.consul.internal.configentry.LoadBalancer.LeastRequestConfig:type_name -> hashicorp.consul.internal.configentry.LeastRequestConfig - 28, // 34: hashicorp.consul.internal.configentry.LoadBalancer.HashPolicies:type_name -> hashicorp.consul.internal.configentry.HashPolicy - 29, // 35: hashicorp.consul.internal.configentry.HashPolicy.CookieConfig:type_name -> hashicorp.consul.internal.configentry.CookieConfig - 128, // 36: hashicorp.consul.internal.configentry.CookieConfig.TTL:type_name -> google.protobuf.Duration - 32, // 37: hashicorp.consul.internal.configentry.IngressGateway.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig - 34, // 38: hashicorp.consul.internal.configentry.IngressGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.IngressListener - 110, // 39: hashicorp.consul.internal.configentry.IngressGateway.Meta:type_name -> hashicorp.consul.internal.configentry.IngressGateway.MetaEntry - 31, // 40: hashicorp.consul.internal.configentry.IngressGateway.Defaults:type_name -> hashicorp.consul.internal.configentry.IngressServiceConfig - 54, // 41: hashicorp.consul.internal.configentry.IngressServiceConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck - 33, // 42: hashicorp.consul.internal.configentry.GatewayTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig - 35, // 43: hashicorp.consul.internal.configentry.IngressListener.Services:type_name -> hashicorp.consul.internal.configentry.IngressService - 32, // 44: hashicorp.consul.internal.configentry.IngressListener.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig - 36, // 45: hashicorp.consul.internal.configentry.IngressService.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayServiceTLSConfig - 37, // 46: hashicorp.consul.internal.configentry.IngressService.RequestHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers - 37, // 47: hashicorp.consul.internal.configentry.IngressService.ResponseHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers - 111, // 48: hashicorp.consul.internal.configentry.IngressService.Meta:type_name -> hashicorp.consul.internal.configentry.IngressService.MetaEntry - 126, // 49: hashicorp.consul.internal.configentry.IngressService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 54, // 50: hashicorp.consul.internal.configentry.IngressService.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck - 33, // 51: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig - 112, // 52: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry - 113, // 53: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry - 42, // 54: hashicorp.consul.internal.configentry.ServiceIntentions.Sources:type_name -> hashicorp.consul.internal.configentry.SourceIntention - 114, // 55: hashicorp.consul.internal.configentry.ServiceIntentions.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry - 39, // 56: hashicorp.consul.internal.configentry.ServiceIntentions.JWT:type_name -> hashicorp.consul.internal.configentry.IntentionJWTRequirement - 40, // 57: hashicorp.consul.internal.configentry.IntentionJWTRequirement.Providers:type_name -> hashicorp.consul.internal.configentry.IntentionJWTProvider - 41, // 58: hashicorp.consul.internal.configentry.IntentionJWTProvider.VerifyClaims:type_name -> hashicorp.consul.internal.configentry.IntentionJWTClaimVerification - 1, // 59: hashicorp.consul.internal.configentry.SourceIntention.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction - 43, // 60: hashicorp.consul.internal.configentry.SourceIntention.Permissions:type_name -> hashicorp.consul.internal.configentry.IntentionPermission - 2, // 61: hashicorp.consul.internal.configentry.SourceIntention.Type:type_name -> hashicorp.consul.internal.configentry.IntentionSourceType - 115, // 62: hashicorp.consul.internal.configentry.SourceIntention.LegacyMeta:type_name -> hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry - 129, // 63: hashicorp.consul.internal.configentry.SourceIntention.LegacyCreateTime:type_name -> google.protobuf.Timestamp - 129, // 64: hashicorp.consul.internal.configentry.SourceIntention.LegacyUpdateTime:type_name -> google.protobuf.Timestamp - 126, // 65: hashicorp.consul.internal.configentry.SourceIntention.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 1, // 66: hashicorp.consul.internal.configentry.IntentionPermission.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction - 44, // 67: hashicorp.consul.internal.configentry.IntentionPermission.HTTP:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPPermission - 39, // 68: hashicorp.consul.internal.configentry.IntentionPermission.JWT:type_name -> hashicorp.consul.internal.configentry.IntentionJWTRequirement - 45, // 69: hashicorp.consul.internal.configentry.IntentionHTTPPermission.Header:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission - 3, // 70: hashicorp.consul.internal.configentry.ServiceDefaults.Mode:type_name -> hashicorp.consul.internal.configentry.ProxyMode - 47, // 71: hashicorp.consul.internal.configentry.ServiceDefaults.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyConfig - 48, // 72: hashicorp.consul.internal.configentry.ServiceDefaults.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig - 49, // 73: hashicorp.consul.internal.configentry.ServiceDefaults.Expose:type_name -> hashicorp.consul.internal.configentry.ExposeConfig - 51, // 74: hashicorp.consul.internal.configentry.ServiceDefaults.UpstreamConfig:type_name -> hashicorp.consul.internal.configentry.UpstreamConfiguration - 55, // 75: hashicorp.consul.internal.configentry.ServiceDefaults.Destination:type_name -> hashicorp.consul.internal.configentry.DestinationConfig - 56, // 76: hashicorp.consul.internal.configentry.ServiceDefaults.RateLimits:type_name -> hashicorp.consul.internal.configentry.RateLimits - 116, // 77: hashicorp.consul.internal.configentry.ServiceDefaults.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry - 130, // 78: hashicorp.consul.internal.configentry.ServiceDefaults.EnvoyExtensions:type_name -> hashicorp.consul.internal.common.EnvoyExtension - 4, // 79: hashicorp.consul.internal.configentry.ServiceDefaults.MutualTLSMode:type_name -> hashicorp.consul.internal.configentry.MutualTLSMode - 5, // 80: hashicorp.consul.internal.configentry.MeshGatewayConfig.Mode:type_name -> hashicorp.consul.internal.configentry.MeshGatewayMode - 50, // 81: hashicorp.consul.internal.configentry.ExposeConfig.Paths:type_name -> hashicorp.consul.internal.configentry.ExposePath - 52, // 82: hashicorp.consul.internal.configentry.UpstreamConfiguration.Overrides:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig - 52, // 83: hashicorp.consul.internal.configentry.UpstreamConfiguration.Defaults:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig - 126, // 84: hashicorp.consul.internal.configentry.UpstreamConfig.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 53, // 85: hashicorp.consul.internal.configentry.UpstreamConfig.Limits:type_name -> hashicorp.consul.internal.configentry.UpstreamLimits - 54, // 86: hashicorp.consul.internal.configentry.UpstreamConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck - 48, // 87: hashicorp.consul.internal.configentry.UpstreamConfig.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig - 128, // 88: hashicorp.consul.internal.configentry.PassiveHealthCheck.Interval:type_name -> google.protobuf.Duration - 128, // 89: hashicorp.consul.internal.configentry.PassiveHealthCheck.BaseEjectionTime:type_name -> google.protobuf.Duration - 57, // 90: hashicorp.consul.internal.configentry.RateLimits.InstanceLevel:type_name -> hashicorp.consul.internal.configentry.InstanceLevelRateLimits - 58, // 91: hashicorp.consul.internal.configentry.InstanceLevelRateLimits.Routes:type_name -> hashicorp.consul.internal.configentry.InstanceLevelRouteRateLimits - 117, // 92: hashicorp.consul.internal.configentry.APIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.APIGateway.MetaEntry - 62, // 93: hashicorp.consul.internal.configentry.APIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.APIGatewayListener - 60, // 94: hashicorp.consul.internal.configentry.APIGateway.Status:type_name -> hashicorp.consul.internal.configentry.Status - 61, // 95: hashicorp.consul.internal.configentry.Status.Conditions:type_name -> hashicorp.consul.internal.configentry.Condition - 68, // 96: hashicorp.consul.internal.configentry.Condition.Resource:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 129, // 97: hashicorp.consul.internal.configentry.Condition.LastTransitionTime:type_name -> google.protobuf.Timestamp - 6, // 98: hashicorp.consul.internal.configentry.APIGatewayListener.Protocol:type_name -> hashicorp.consul.internal.configentry.APIGatewayListenerProtocol - 63, // 99: hashicorp.consul.internal.configentry.APIGatewayListener.TLS:type_name -> hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration - 64, // 100: hashicorp.consul.internal.configentry.APIGatewayListener.Override:type_name -> hashicorp.consul.internal.configentry.APIGatewayPolicy - 64, // 101: hashicorp.consul.internal.configentry.APIGatewayListener.Default:type_name -> hashicorp.consul.internal.configentry.APIGatewayPolicy - 68, // 102: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 65, // 103: hashicorp.consul.internal.configentry.APIGatewayPolicy.JWT:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTRequirement - 66, // 104: hashicorp.consul.internal.configentry.APIGatewayJWTRequirement.Providers:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTProvider - 67, // 105: hashicorp.consul.internal.configentry.APIGatewayJWTProvider.VerifyClaims:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTClaimVerification - 126, // 106: hashicorp.consul.internal.configentry.ResourceReference.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 118, // 107: hashicorp.consul.internal.configentry.BoundAPIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry - 70, // 108: hashicorp.consul.internal.configentry.BoundAPIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.BoundAPIGatewayListener - 68, // 109: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 68, // 110: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Routes:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 119, // 111: hashicorp.consul.internal.configentry.InlineCertificate.Meta:type_name -> hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry - 120, // 112: hashicorp.consul.internal.configentry.HTTPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry - 68, // 113: hashicorp.consul.internal.configentry.HTTPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 73, // 114: hashicorp.consul.internal.configentry.HTTPRoute.Rules:type_name -> hashicorp.consul.internal.configentry.HTTPRouteRule - 60, // 115: hashicorp.consul.internal.configentry.HTTPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status - 78, // 116: hashicorp.consul.internal.configentry.HTTPRouteRule.Filters:type_name -> hashicorp.consul.internal.configentry.HTTPFilters - 74, // 117: hashicorp.consul.internal.configentry.HTTPRouteRule.Matches:type_name -> hashicorp.consul.internal.configentry.HTTPMatch - 85, // 118: hashicorp.consul.internal.configentry.HTTPRouteRule.Services:type_name -> hashicorp.consul.internal.configentry.HTTPService - 79, // 119: hashicorp.consul.internal.configentry.HTTPRouteRule.ResponseFilters:type_name -> hashicorp.consul.internal.configentry.HTTPResponseFilters - 75, // 120: hashicorp.consul.internal.configentry.HTTPMatch.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderMatch - 7, // 121: hashicorp.consul.internal.configentry.HTTPMatch.Method:type_name -> hashicorp.consul.internal.configentry.HTTPMatchMethod - 76, // 122: hashicorp.consul.internal.configentry.HTTPMatch.Path:type_name -> hashicorp.consul.internal.configentry.HTTPPathMatch - 77, // 123: hashicorp.consul.internal.configentry.HTTPMatch.Query:type_name -> hashicorp.consul.internal.configentry.HTTPQueryMatch - 8, // 124: hashicorp.consul.internal.configentry.HTTPHeaderMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderMatchType - 9, // 125: hashicorp.consul.internal.configentry.HTTPPathMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPPathMatchType - 10, // 126: hashicorp.consul.internal.configentry.HTTPQueryMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPQueryMatchType - 84, // 127: hashicorp.consul.internal.configentry.HTTPFilters.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter - 80, // 128: hashicorp.consul.internal.configentry.HTTPFilters.URLRewrite:type_name -> hashicorp.consul.internal.configentry.URLRewrite - 81, // 129: hashicorp.consul.internal.configentry.HTTPFilters.RetryFilter:type_name -> hashicorp.consul.internal.configentry.RetryFilter - 82, // 130: hashicorp.consul.internal.configentry.HTTPFilters.TimeoutFilter:type_name -> hashicorp.consul.internal.configentry.TimeoutFilter - 83, // 131: hashicorp.consul.internal.configentry.HTTPFilters.JWT:type_name -> hashicorp.consul.internal.configentry.JWTFilter - 84, // 132: hashicorp.consul.internal.configentry.HTTPResponseFilters.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter - 128, // 133: hashicorp.consul.internal.configentry.TimeoutFilter.RequestTimeout:type_name -> google.protobuf.Duration - 128, // 134: hashicorp.consul.internal.configentry.TimeoutFilter.IdleTimeout:type_name -> google.protobuf.Duration - 66, // 135: hashicorp.consul.internal.configentry.JWTFilter.Providers:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTProvider - 121, // 136: hashicorp.consul.internal.configentry.HTTPHeaderFilter.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter.AddEntry - 122, // 137: hashicorp.consul.internal.configentry.HTTPHeaderFilter.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter.SetEntry - 78, // 138: hashicorp.consul.internal.configentry.HTTPService.Filters:type_name -> hashicorp.consul.internal.configentry.HTTPFilters - 126, // 139: hashicorp.consul.internal.configentry.HTTPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 79, // 140: hashicorp.consul.internal.configentry.HTTPService.ResponseFilters:type_name -> hashicorp.consul.internal.configentry.HTTPResponseFilters - 123, // 141: hashicorp.consul.internal.configentry.TCPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.TCPRoute.MetaEntry - 68, // 142: hashicorp.consul.internal.configentry.TCPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference - 87, // 143: hashicorp.consul.internal.configentry.TCPRoute.Services:type_name -> hashicorp.consul.internal.configentry.TCPService - 60, // 144: hashicorp.consul.internal.configentry.TCPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status - 126, // 145: hashicorp.consul.internal.configentry.TCPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 89, // 146: hashicorp.consul.internal.configentry.SamenessGroup.Members:type_name -> hashicorp.consul.internal.configentry.SamenessGroupMember - 124, // 147: hashicorp.consul.internal.configentry.SamenessGroup.Meta:type_name -> hashicorp.consul.internal.configentry.SamenessGroup.MetaEntry - 126, // 148: hashicorp.consul.internal.configentry.SamenessGroup.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 91, // 149: hashicorp.consul.internal.configentry.JWTProvider.JSONWebKeySet:type_name -> hashicorp.consul.internal.configentry.JSONWebKeySet - 100, // 150: hashicorp.consul.internal.configentry.JWTProvider.Locations:type_name -> hashicorp.consul.internal.configentry.JWTLocation - 104, // 151: hashicorp.consul.internal.configentry.JWTProvider.Forwarding:type_name -> hashicorp.consul.internal.configentry.JWTForwardingConfig - 105, // 152: hashicorp.consul.internal.configentry.JWTProvider.CacheConfig:type_name -> hashicorp.consul.internal.configentry.JWTCacheConfig - 125, // 153: hashicorp.consul.internal.configentry.JWTProvider.Meta:type_name -> hashicorp.consul.internal.configentry.JWTProvider.MetaEntry - 92, // 154: hashicorp.consul.internal.configentry.JSONWebKeySet.Local:type_name -> hashicorp.consul.internal.configentry.LocalJWKS - 93, // 155: hashicorp.consul.internal.configentry.JSONWebKeySet.Remote:type_name -> hashicorp.consul.internal.configentry.RemoteJWKS - 128, // 156: hashicorp.consul.internal.configentry.RemoteJWKS.CacheDuration:type_name -> google.protobuf.Duration - 98, // 157: hashicorp.consul.internal.configentry.RemoteJWKS.RetryPolicy:type_name -> hashicorp.consul.internal.configentry.JWKSRetryPolicy - 94, // 158: hashicorp.consul.internal.configentry.RemoteJWKS.JWKSCluster:type_name -> hashicorp.consul.internal.configentry.JWKSCluster - 95, // 159: hashicorp.consul.internal.configentry.JWKSCluster.TLSCertificates:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertificate - 128, // 160: hashicorp.consul.internal.configentry.JWKSCluster.ConnectTimeout:type_name -> google.protobuf.Duration - 96, // 161: hashicorp.consul.internal.configentry.JWKSTLSCertificate.CaCertificateProviderInstance:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertProviderInstance - 97, // 162: hashicorp.consul.internal.configentry.JWKSTLSCertificate.TrustedCA:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertTrustedCA - 99, // 163: hashicorp.consul.internal.configentry.JWKSRetryPolicy.RetryPolicyBackOff:type_name -> hashicorp.consul.internal.configentry.RetryPolicyBackOff - 128, // 164: hashicorp.consul.internal.configentry.RetryPolicyBackOff.BaseInterval:type_name -> google.protobuf.Duration - 128, // 165: hashicorp.consul.internal.configentry.RetryPolicyBackOff.MaxInterval:type_name -> google.protobuf.Duration - 101, // 166: hashicorp.consul.internal.configentry.JWTLocation.Header:type_name -> hashicorp.consul.internal.configentry.JWTLocationHeader - 102, // 167: hashicorp.consul.internal.configentry.JWTLocation.QueryParam:type_name -> hashicorp.consul.internal.configentry.JWTLocationQueryParam - 103, // 168: hashicorp.consul.internal.configentry.JWTLocation.Cookie:type_name -> hashicorp.consul.internal.configentry.JWTLocationCookie - 19, // 169: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverSubset - 21, // 170: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailover - 171, // [171:171] is the sub-list for method output_type - 171, // [171:171] is the sub-list for method input_type - 171, // [171:171] is the sub-list for extension type_name - 171, // [171:171] is the sub-list for extension extendee - 0, // [0:171] is the sub-list for field type_name + 15, // 0: hashicorp.consul.internal.configentry.GetResolvedExportedServicesResponse.services:type_name -> hashicorp.consul.internal.configentry.ResolvedExportedService + 142, // 1: hashicorp.consul.internal.configentry.ResolvedExportedService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 16, // 2: hashicorp.consul.internal.configentry.ResolvedExportedService.Consumers:type_name -> hashicorp.consul.internal.configentry.Consumers + 0, // 3: hashicorp.consul.internal.configentry.ConfigEntry.Kind:type_name -> hashicorp.consul.internal.configentry.Kind + 142, // 4: hashicorp.consul.internal.configentry.ConfigEntry.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 143, // 5: hashicorp.consul.internal.configentry.ConfigEntry.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex + 18, // 6: hashicorp.consul.internal.configentry.ConfigEntry.MeshConfig:type_name -> hashicorp.consul.internal.configentry.MeshConfig + 26, // 7: hashicorp.consul.internal.configentry.ConfigEntry.ServiceResolver:type_name -> hashicorp.consul.internal.configentry.ServiceResolver + 38, // 8: hashicorp.consul.internal.configentry.ConfigEntry.IngressGateway:type_name -> hashicorp.consul.internal.configentry.IngressGateway + 46, // 9: hashicorp.consul.internal.configentry.ConfigEntry.ServiceIntentions:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions + 54, // 10: hashicorp.consul.internal.configentry.ConfigEntry.ServiceDefaults:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults + 67, // 11: hashicorp.consul.internal.configentry.ConfigEntry.APIGateway:type_name -> hashicorp.consul.internal.configentry.APIGateway + 77, // 12: hashicorp.consul.internal.configentry.ConfigEntry.BoundAPIGateway:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway + 96, // 13: hashicorp.consul.internal.configentry.ConfigEntry.TCPRoute:type_name -> hashicorp.consul.internal.configentry.TCPRoute + 82, // 14: hashicorp.consul.internal.configentry.ConfigEntry.HTTPRoute:type_name -> hashicorp.consul.internal.configentry.HTTPRoute + 81, // 15: hashicorp.consul.internal.configentry.ConfigEntry.InlineCertificate:type_name -> hashicorp.consul.internal.configentry.InlineCertificate + 98, // 16: hashicorp.consul.internal.configentry.ConfigEntry.SamenessGroup:type_name -> hashicorp.consul.internal.configentry.SamenessGroup + 100, // 17: hashicorp.consul.internal.configentry.ConfigEntry.JWTProvider:type_name -> hashicorp.consul.internal.configentry.JWTProvider + 116, // 18: hashicorp.consul.internal.configentry.ConfigEntry.ExportedServices:type_name -> hashicorp.consul.internal.configentry.ExportedServices + 80, // 19: hashicorp.consul.internal.configentry.ConfigEntry.FileSystemCertificate:type_name -> hashicorp.consul.internal.configentry.FileSystemCertificate + 19, // 20: hashicorp.consul.internal.configentry.MeshConfig.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyMeshConfig + 20, // 21: hashicorp.consul.internal.configentry.MeshConfig.TLS:type_name -> hashicorp.consul.internal.configentry.MeshTLSConfig + 22, // 22: hashicorp.consul.internal.configentry.MeshConfig.HTTP:type_name -> hashicorp.consul.internal.configentry.MeshHTTPConfig + 119, // 23: hashicorp.consul.internal.configentry.MeshConfig.Meta:type_name -> hashicorp.consul.internal.configentry.MeshConfig.MetaEntry + 24, // 24: hashicorp.consul.internal.configentry.MeshConfig.Peering:type_name -> hashicorp.consul.internal.configentry.PeeringMeshConfig + 21, // 25: hashicorp.consul.internal.configentry.MeshTLSConfig.Incoming:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig + 21, // 26: hashicorp.consul.internal.configentry.MeshTLSConfig.Outgoing:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig + 23, // 27: hashicorp.consul.internal.configentry.MeshHTTPConfig.Incoming:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalHTTPConfig + 25, // 28: hashicorp.consul.internal.configentry.MeshDirectionalHTTPConfig.RequestNormalization:type_name -> hashicorp.consul.internal.configentry.RequestNormalizationMeshConfig + 1, // 29: hashicorp.consul.internal.configentry.RequestNormalizationMeshConfig.PathWithEscapedSlashesAction:type_name -> hashicorp.consul.internal.configentry.PathWithEscapedSlashesAction + 2, // 30: hashicorp.consul.internal.configentry.RequestNormalizationMeshConfig.HeadersWithUnderscoresAction:type_name -> hashicorp.consul.internal.configentry.HeadersWithUnderscoresAction + 120, // 31: hashicorp.consul.internal.configentry.ServiceResolver.Subsets:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry + 28, // 32: hashicorp.consul.internal.configentry.ServiceResolver.Redirect:type_name -> hashicorp.consul.internal.configentry.ServiceResolverRedirect + 121, // 33: hashicorp.consul.internal.configentry.ServiceResolver.Failover:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry + 144, // 34: hashicorp.consul.internal.configentry.ServiceResolver.ConnectTimeout:type_name -> google.protobuf.Duration + 33, // 35: hashicorp.consul.internal.configentry.ServiceResolver.LoadBalancer:type_name -> hashicorp.consul.internal.configentry.LoadBalancer + 122, // 36: hashicorp.consul.internal.configentry.ServiceResolver.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry + 144, // 37: hashicorp.consul.internal.configentry.ServiceResolver.RequestTimeout:type_name -> google.protobuf.Duration + 31, // 38: hashicorp.consul.internal.configentry.ServiceResolver.PrioritizeByLocality:type_name -> hashicorp.consul.internal.configentry.ServiceResolverPrioritizeByLocality + 32, // 39: hashicorp.consul.internal.configentry.ServiceResolverFailover.Targets:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget + 30, // 40: hashicorp.consul.internal.configentry.ServiceResolverFailover.Policy:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailoverPolicy + 34, // 41: hashicorp.consul.internal.configentry.LoadBalancer.RingHashConfig:type_name -> hashicorp.consul.internal.configentry.RingHashConfig + 35, // 42: hashicorp.consul.internal.configentry.LoadBalancer.LeastRequestConfig:type_name -> hashicorp.consul.internal.configentry.LeastRequestConfig + 36, // 43: hashicorp.consul.internal.configentry.LoadBalancer.HashPolicies:type_name -> hashicorp.consul.internal.configentry.HashPolicy + 37, // 44: hashicorp.consul.internal.configentry.HashPolicy.CookieConfig:type_name -> hashicorp.consul.internal.configentry.CookieConfig + 144, // 45: hashicorp.consul.internal.configentry.CookieConfig.TTL:type_name -> google.protobuf.Duration + 40, // 46: hashicorp.consul.internal.configentry.IngressGateway.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig + 42, // 47: hashicorp.consul.internal.configentry.IngressGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.IngressListener + 123, // 48: hashicorp.consul.internal.configentry.IngressGateway.Meta:type_name -> hashicorp.consul.internal.configentry.IngressGateway.MetaEntry + 39, // 49: hashicorp.consul.internal.configentry.IngressGateway.Defaults:type_name -> hashicorp.consul.internal.configentry.IngressServiceConfig + 62, // 50: hashicorp.consul.internal.configentry.IngressServiceConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck + 41, // 51: hashicorp.consul.internal.configentry.GatewayTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig + 43, // 52: hashicorp.consul.internal.configentry.IngressListener.Services:type_name -> hashicorp.consul.internal.configentry.IngressService + 40, // 53: hashicorp.consul.internal.configentry.IngressListener.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig + 44, // 54: hashicorp.consul.internal.configentry.IngressService.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayServiceTLSConfig + 45, // 55: hashicorp.consul.internal.configentry.IngressService.RequestHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers + 45, // 56: hashicorp.consul.internal.configentry.IngressService.ResponseHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers + 124, // 57: hashicorp.consul.internal.configentry.IngressService.Meta:type_name -> hashicorp.consul.internal.configentry.IngressService.MetaEntry + 142, // 58: hashicorp.consul.internal.configentry.IngressService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 62, // 59: hashicorp.consul.internal.configentry.IngressService.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck + 41, // 60: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig + 125, // 61: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry + 126, // 62: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry + 50, // 63: hashicorp.consul.internal.configentry.ServiceIntentions.Sources:type_name -> hashicorp.consul.internal.configentry.SourceIntention + 127, // 64: hashicorp.consul.internal.configentry.ServiceIntentions.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry + 47, // 65: hashicorp.consul.internal.configentry.ServiceIntentions.JWT:type_name -> hashicorp.consul.internal.configentry.IntentionJWTRequirement + 48, // 66: hashicorp.consul.internal.configentry.IntentionJWTRequirement.Providers:type_name -> hashicorp.consul.internal.configentry.IntentionJWTProvider + 49, // 67: hashicorp.consul.internal.configentry.IntentionJWTProvider.VerifyClaims:type_name -> hashicorp.consul.internal.configentry.IntentionJWTClaimVerification + 3, // 68: hashicorp.consul.internal.configentry.SourceIntention.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction + 51, // 69: hashicorp.consul.internal.configentry.SourceIntention.Permissions:type_name -> hashicorp.consul.internal.configentry.IntentionPermission + 4, // 70: hashicorp.consul.internal.configentry.SourceIntention.Type:type_name -> hashicorp.consul.internal.configentry.IntentionSourceType + 128, // 71: hashicorp.consul.internal.configentry.SourceIntention.LegacyMeta:type_name -> hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry + 145, // 72: hashicorp.consul.internal.configentry.SourceIntention.LegacyCreateTime:type_name -> google.protobuf.Timestamp + 145, // 73: hashicorp.consul.internal.configentry.SourceIntention.LegacyUpdateTime:type_name -> google.protobuf.Timestamp + 142, // 74: hashicorp.consul.internal.configentry.SourceIntention.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 3, // 75: hashicorp.consul.internal.configentry.IntentionPermission.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction + 52, // 76: hashicorp.consul.internal.configentry.IntentionPermission.HTTP:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPPermission + 47, // 77: hashicorp.consul.internal.configentry.IntentionPermission.JWT:type_name -> hashicorp.consul.internal.configentry.IntentionJWTRequirement + 53, // 78: hashicorp.consul.internal.configentry.IntentionHTTPPermission.Header:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission + 5, // 79: hashicorp.consul.internal.configentry.ServiceDefaults.Mode:type_name -> hashicorp.consul.internal.configentry.ProxyMode + 55, // 80: hashicorp.consul.internal.configentry.ServiceDefaults.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyConfig + 56, // 81: hashicorp.consul.internal.configentry.ServiceDefaults.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig + 57, // 82: hashicorp.consul.internal.configentry.ServiceDefaults.Expose:type_name -> hashicorp.consul.internal.configentry.ExposeConfig + 59, // 83: hashicorp.consul.internal.configentry.ServiceDefaults.UpstreamConfig:type_name -> hashicorp.consul.internal.configentry.UpstreamConfiguration + 63, // 84: hashicorp.consul.internal.configentry.ServiceDefaults.Destination:type_name -> hashicorp.consul.internal.configentry.DestinationConfig + 64, // 85: hashicorp.consul.internal.configentry.ServiceDefaults.RateLimits:type_name -> hashicorp.consul.internal.configentry.RateLimits + 129, // 86: hashicorp.consul.internal.configentry.ServiceDefaults.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry + 146, // 87: hashicorp.consul.internal.configentry.ServiceDefaults.EnvoyExtensions:type_name -> hashicorp.consul.internal.common.EnvoyExtension + 6, // 88: hashicorp.consul.internal.configentry.ServiceDefaults.MutualTLSMode:type_name -> hashicorp.consul.internal.configentry.MutualTLSMode + 7, // 89: hashicorp.consul.internal.configentry.MeshGatewayConfig.Mode:type_name -> hashicorp.consul.internal.configentry.MeshGatewayMode + 58, // 90: hashicorp.consul.internal.configentry.ExposeConfig.Paths:type_name -> hashicorp.consul.internal.configentry.ExposePath + 60, // 91: hashicorp.consul.internal.configentry.UpstreamConfiguration.Overrides:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig + 60, // 92: hashicorp.consul.internal.configentry.UpstreamConfiguration.Defaults:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig + 142, // 93: hashicorp.consul.internal.configentry.UpstreamConfig.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 61, // 94: hashicorp.consul.internal.configentry.UpstreamConfig.Limits:type_name -> hashicorp.consul.internal.configentry.UpstreamLimits + 62, // 95: hashicorp.consul.internal.configentry.UpstreamConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck + 56, // 96: hashicorp.consul.internal.configentry.UpstreamConfig.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig + 144, // 97: hashicorp.consul.internal.configentry.PassiveHealthCheck.Interval:type_name -> google.protobuf.Duration + 144, // 98: hashicorp.consul.internal.configentry.PassiveHealthCheck.BaseEjectionTime:type_name -> google.protobuf.Duration + 65, // 99: hashicorp.consul.internal.configentry.RateLimits.InstanceLevel:type_name -> hashicorp.consul.internal.configentry.InstanceLevelRateLimits + 66, // 100: hashicorp.consul.internal.configentry.InstanceLevelRateLimits.Routes:type_name -> hashicorp.consul.internal.configentry.InstanceLevelRouteRateLimits + 130, // 101: hashicorp.consul.internal.configentry.APIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.APIGateway.MetaEntry + 70, // 102: hashicorp.consul.internal.configentry.APIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.APIGatewayListener + 68, // 103: hashicorp.consul.internal.configentry.APIGateway.Status:type_name -> hashicorp.consul.internal.configentry.Status + 69, // 104: hashicorp.consul.internal.configentry.Status.Conditions:type_name -> hashicorp.consul.internal.configentry.Condition + 76, // 105: hashicorp.consul.internal.configentry.Condition.Resource:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 145, // 106: hashicorp.consul.internal.configentry.Condition.LastTransitionTime:type_name -> google.protobuf.Timestamp + 8, // 107: hashicorp.consul.internal.configentry.APIGatewayListener.Protocol:type_name -> hashicorp.consul.internal.configentry.APIGatewayListenerProtocol + 71, // 108: hashicorp.consul.internal.configentry.APIGatewayListener.TLS:type_name -> hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration + 72, // 109: hashicorp.consul.internal.configentry.APIGatewayListener.Override:type_name -> hashicorp.consul.internal.configentry.APIGatewayPolicy + 72, // 110: hashicorp.consul.internal.configentry.APIGatewayListener.Default:type_name -> hashicorp.consul.internal.configentry.APIGatewayPolicy + 76, // 111: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 73, // 112: hashicorp.consul.internal.configentry.APIGatewayPolicy.JWT:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTRequirement + 74, // 113: hashicorp.consul.internal.configentry.APIGatewayJWTRequirement.Providers:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTProvider + 75, // 114: hashicorp.consul.internal.configentry.APIGatewayJWTProvider.VerifyClaims:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTClaimVerification + 142, // 115: hashicorp.consul.internal.configentry.ResourceReference.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 131, // 116: hashicorp.consul.internal.configentry.BoundAPIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry + 79, // 117: hashicorp.consul.internal.configentry.BoundAPIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.BoundAPIGatewayListener + 132, // 118: hashicorp.consul.internal.configentry.BoundAPIGateway.Services:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway.ServicesEntry + 76, // 119: hashicorp.consul.internal.configentry.ListOfResourceReference.Ref:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 76, // 120: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 76, // 121: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Routes:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 133, // 122: hashicorp.consul.internal.configentry.FileSystemCertificate.Meta:type_name -> hashicorp.consul.internal.configentry.FileSystemCertificate.MetaEntry + 134, // 123: hashicorp.consul.internal.configentry.InlineCertificate.Meta:type_name -> hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry + 135, // 124: hashicorp.consul.internal.configentry.HTTPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry + 76, // 125: hashicorp.consul.internal.configentry.HTTPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 83, // 126: hashicorp.consul.internal.configentry.HTTPRoute.Rules:type_name -> hashicorp.consul.internal.configentry.HTTPRouteRule + 68, // 127: hashicorp.consul.internal.configentry.HTTPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status + 88, // 128: hashicorp.consul.internal.configentry.HTTPRouteRule.Filters:type_name -> hashicorp.consul.internal.configentry.HTTPFilters + 84, // 129: hashicorp.consul.internal.configentry.HTTPRouteRule.Matches:type_name -> hashicorp.consul.internal.configentry.HTTPMatch + 95, // 130: hashicorp.consul.internal.configentry.HTTPRouteRule.Services:type_name -> hashicorp.consul.internal.configentry.HTTPService + 89, // 131: hashicorp.consul.internal.configentry.HTTPRouteRule.ResponseFilters:type_name -> hashicorp.consul.internal.configentry.HTTPResponseFilters + 85, // 132: hashicorp.consul.internal.configentry.HTTPMatch.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderMatch + 9, // 133: hashicorp.consul.internal.configentry.HTTPMatch.Method:type_name -> hashicorp.consul.internal.configentry.HTTPMatchMethod + 86, // 134: hashicorp.consul.internal.configentry.HTTPMatch.Path:type_name -> hashicorp.consul.internal.configentry.HTTPPathMatch + 87, // 135: hashicorp.consul.internal.configentry.HTTPMatch.Query:type_name -> hashicorp.consul.internal.configentry.HTTPQueryMatch + 10, // 136: hashicorp.consul.internal.configentry.HTTPHeaderMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderMatchType + 11, // 137: hashicorp.consul.internal.configentry.HTTPPathMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPPathMatchType + 12, // 138: hashicorp.consul.internal.configentry.HTTPQueryMatch.Match:type_name -> hashicorp.consul.internal.configentry.HTTPQueryMatchType + 94, // 139: hashicorp.consul.internal.configentry.HTTPFilters.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter + 90, // 140: hashicorp.consul.internal.configentry.HTTPFilters.URLRewrite:type_name -> hashicorp.consul.internal.configentry.URLRewrite + 91, // 141: hashicorp.consul.internal.configentry.HTTPFilters.RetryFilter:type_name -> hashicorp.consul.internal.configentry.RetryFilter + 92, // 142: hashicorp.consul.internal.configentry.HTTPFilters.TimeoutFilter:type_name -> hashicorp.consul.internal.configentry.TimeoutFilter + 93, // 143: hashicorp.consul.internal.configentry.HTTPFilters.JWT:type_name -> hashicorp.consul.internal.configentry.JWTFilter + 94, // 144: hashicorp.consul.internal.configentry.HTTPResponseFilters.Headers:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter + 144, // 145: hashicorp.consul.internal.configentry.TimeoutFilter.RequestTimeout:type_name -> google.protobuf.Duration + 144, // 146: hashicorp.consul.internal.configentry.TimeoutFilter.IdleTimeout:type_name -> google.protobuf.Duration + 74, // 147: hashicorp.consul.internal.configentry.JWTFilter.Providers:type_name -> hashicorp.consul.internal.configentry.APIGatewayJWTProvider + 136, // 148: hashicorp.consul.internal.configentry.HTTPHeaderFilter.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter.AddEntry + 137, // 149: hashicorp.consul.internal.configentry.HTTPHeaderFilter.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderFilter.SetEntry + 88, // 150: hashicorp.consul.internal.configentry.HTTPService.Filters:type_name -> hashicorp.consul.internal.configentry.HTTPFilters + 142, // 151: hashicorp.consul.internal.configentry.HTTPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 89, // 152: hashicorp.consul.internal.configentry.HTTPService.ResponseFilters:type_name -> hashicorp.consul.internal.configentry.HTTPResponseFilters + 138, // 153: hashicorp.consul.internal.configentry.TCPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.TCPRoute.MetaEntry + 76, // 154: hashicorp.consul.internal.configentry.TCPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 97, // 155: hashicorp.consul.internal.configentry.TCPRoute.Services:type_name -> hashicorp.consul.internal.configentry.TCPService + 68, // 156: hashicorp.consul.internal.configentry.TCPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status + 142, // 157: hashicorp.consul.internal.configentry.TCPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 99, // 158: hashicorp.consul.internal.configentry.SamenessGroup.Members:type_name -> hashicorp.consul.internal.configentry.SamenessGroupMember + 139, // 159: hashicorp.consul.internal.configentry.SamenessGroup.Meta:type_name -> hashicorp.consul.internal.configentry.SamenessGroup.MetaEntry + 142, // 160: hashicorp.consul.internal.configentry.SamenessGroup.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 101, // 161: hashicorp.consul.internal.configentry.JWTProvider.JSONWebKeySet:type_name -> hashicorp.consul.internal.configentry.JSONWebKeySet + 110, // 162: hashicorp.consul.internal.configentry.JWTProvider.Locations:type_name -> hashicorp.consul.internal.configentry.JWTLocation + 114, // 163: hashicorp.consul.internal.configentry.JWTProvider.Forwarding:type_name -> hashicorp.consul.internal.configentry.JWTForwardingConfig + 115, // 164: hashicorp.consul.internal.configentry.JWTProvider.CacheConfig:type_name -> hashicorp.consul.internal.configentry.JWTCacheConfig + 140, // 165: hashicorp.consul.internal.configentry.JWTProvider.Meta:type_name -> hashicorp.consul.internal.configentry.JWTProvider.MetaEntry + 102, // 166: hashicorp.consul.internal.configentry.JSONWebKeySet.Local:type_name -> hashicorp.consul.internal.configentry.LocalJWKS + 103, // 167: hashicorp.consul.internal.configentry.JSONWebKeySet.Remote:type_name -> hashicorp.consul.internal.configentry.RemoteJWKS + 144, // 168: hashicorp.consul.internal.configentry.RemoteJWKS.CacheDuration:type_name -> google.protobuf.Duration + 108, // 169: hashicorp.consul.internal.configentry.RemoteJWKS.RetryPolicy:type_name -> hashicorp.consul.internal.configentry.JWKSRetryPolicy + 104, // 170: hashicorp.consul.internal.configentry.RemoteJWKS.JWKSCluster:type_name -> hashicorp.consul.internal.configentry.JWKSCluster + 105, // 171: hashicorp.consul.internal.configentry.JWKSCluster.TLSCertificates:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertificate + 144, // 172: hashicorp.consul.internal.configentry.JWKSCluster.ConnectTimeout:type_name -> google.protobuf.Duration + 106, // 173: hashicorp.consul.internal.configentry.JWKSTLSCertificate.CaCertificateProviderInstance:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertProviderInstance + 107, // 174: hashicorp.consul.internal.configentry.JWKSTLSCertificate.TrustedCA:type_name -> hashicorp.consul.internal.configentry.JWKSTLSCertTrustedCA + 109, // 175: hashicorp.consul.internal.configentry.JWKSRetryPolicy.RetryPolicyBackOff:type_name -> hashicorp.consul.internal.configentry.RetryPolicyBackOff + 144, // 176: hashicorp.consul.internal.configentry.RetryPolicyBackOff.BaseInterval:type_name -> google.protobuf.Duration + 144, // 177: hashicorp.consul.internal.configentry.RetryPolicyBackOff.MaxInterval:type_name -> google.protobuf.Duration + 111, // 178: hashicorp.consul.internal.configentry.JWTLocation.Header:type_name -> hashicorp.consul.internal.configentry.JWTLocationHeader + 112, // 179: hashicorp.consul.internal.configentry.JWTLocation.QueryParam:type_name -> hashicorp.consul.internal.configentry.JWTLocationQueryParam + 113, // 180: hashicorp.consul.internal.configentry.JWTLocation.Cookie:type_name -> hashicorp.consul.internal.configentry.JWTLocationCookie + 142, // 181: hashicorp.consul.internal.configentry.ExportedServices.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 141, // 182: hashicorp.consul.internal.configentry.ExportedServices.Meta:type_name -> hashicorp.consul.internal.configentry.ExportedServices.MetaEntry + 117, // 183: hashicorp.consul.internal.configentry.ExportedServices.Services:type_name -> hashicorp.consul.internal.configentry.ExportedServicesService + 118, // 184: hashicorp.consul.internal.configentry.ExportedServicesService.Consumers:type_name -> hashicorp.consul.internal.configentry.ExportedServicesConsumer + 27, // 185: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverSubset + 29, // 186: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailover + 78, // 187: hashicorp.consul.internal.configentry.BoundAPIGateway.ServicesEntry.value:type_name -> hashicorp.consul.internal.configentry.ListOfResourceReference + 13, // 188: hashicorp.consul.internal.configentry.ConfigEntryService.GetResolvedExportedServices:input_type -> hashicorp.consul.internal.configentry.GetResolvedExportedServicesRequest + 14, // 189: hashicorp.consul.internal.configentry.ConfigEntryService.GetResolvedExportedServices:output_type -> hashicorp.consul.internal.configentry.GetResolvedExportedServicesResponse + 189, // [189:190] is the sub-list for method output_type + 188, // [188:189] is the sub-list for method input_type + 188, // [188:188] is the sub-list for extension type_name + 188, // [188:188] is the sub-list for extension extendee + 0, // [0:188] is the sub-list for field type_name } func init() { file_private_pbconfigentry_config_entry_proto_init() } @@ -9647,6 +10879,54 @@ func file_private_pbconfigentry_config_entry_proto_init() { } if !protoimpl.UnsafeEnabled { file_private_pbconfigentry_config_entry_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetResolvedExportedServicesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_private_pbconfigentry_config_entry_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetResolvedExportedServicesResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_private_pbconfigentry_config_entry_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResolvedExportedService); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_private_pbconfigentry_config_entry_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Consumers); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_private_pbconfigentry_config_entry_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ConfigEntry); i { case 0: return &v.state @@ -9658,7 +10938,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MeshConfig); i { case 0: return &v.state @@ -9670,7 +10950,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TransparentProxyMeshConfig); i { case 0: return &v.state @@ -9682,7 +10962,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MeshTLSConfig); i { case 0: return &v.state @@ -9694,7 +10974,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MeshDirectionalTLSConfig); i { case 0: return &v.state @@ -9706,7 +10986,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MeshHTTPConfig); i { case 0: return &v.state @@ -9718,7 +10998,19 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MeshDirectionalHTTPConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_private_pbconfigentry_config_entry_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeeringMeshConfig); i { case 0: return &v.state @@ -9730,7 +11022,19 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RequestNormalizationMeshConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_private_pbconfigentry_config_entry_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceResolver); i { case 0: return &v.state @@ -9742,7 +11046,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceResolverSubset); i { case 0: return &v.state @@ -9754,7 +11058,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceResolverRedirect); i { case 0: return &v.state @@ -9766,7 +11070,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceResolverFailover); i { case 0: return &v.state @@ -9778,7 +11082,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceResolverFailoverPolicy); i { case 0: return &v.state @@ -9790,7 +11094,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceResolverPrioritizeByLocality); i { case 0: return &v.state @@ -9802,7 +11106,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceResolverFailoverTarget); i { case 0: return &v.state @@ -9814,7 +11118,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LoadBalancer); i { case 0: return &v.state @@ -9826,7 +11130,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RingHashConfig); i { case 0: return &v.state @@ -9838,7 +11142,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LeastRequestConfig); i { case 0: return &v.state @@ -9850,7 +11154,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HashPolicy); i { case 0: return &v.state @@ -9862,7 +11166,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CookieConfig); i { case 0: return &v.state @@ -9874,7 +11178,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*IngressGateway); i { case 0: return &v.state @@ -9886,7 +11190,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*IngressServiceConfig); i { case 0: return &v.state @@ -9898,7 +11202,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GatewayTLSConfig); i { case 0: return &v.state @@ -9910,7 +11214,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GatewayTLSSDSConfig); i { case 0: return &v.state @@ -9922,7 +11226,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*IngressListener); i { case 0: return &v.state @@ -9934,7 +11238,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*IngressService); i { case 0: return &v.state @@ -9946,7 +11250,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GatewayServiceTLSConfig); i { case 0: return &v.state @@ -9958,7 +11262,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPHeaderModifiers); i { case 0: return &v.state @@ -9970,7 +11274,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceIntentions); i { case 0: return &v.state @@ -9982,7 +11286,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*IntentionJWTRequirement); i { case 0: return &v.state @@ -9994,7 +11298,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*IntentionJWTProvider); i { case 0: return &v.state @@ -10006,7 +11310,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*IntentionJWTClaimVerification); i { case 0: return &v.state @@ -10018,7 +11322,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SourceIntention); i { case 0: return &v.state @@ -10030,7 +11334,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*IntentionPermission); i { case 0: return &v.state @@ -10042,7 +11346,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*IntentionHTTPPermission); i { case 0: return &v.state @@ -10054,7 +11358,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*IntentionHTTPHeaderPermission); i { case 0: return &v.state @@ -10066,7 +11370,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceDefaults); i { case 0: return &v.state @@ -10078,7 +11382,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TransparentProxyConfig); i { case 0: return &v.state @@ -10090,7 +11394,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MeshGatewayConfig); i { case 0: return &v.state @@ -10102,7 +11406,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExposeConfig); i { case 0: return &v.state @@ -10114,7 +11418,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExposePath); i { case 0: return &v.state @@ -10126,7 +11430,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UpstreamConfiguration); i { case 0: return &v.state @@ -10138,7 +11442,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UpstreamConfig); i { case 0: return &v.state @@ -10150,7 +11454,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UpstreamLimits); i { case 0: return &v.state @@ -10162,7 +11466,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PassiveHealthCheck); i { case 0: return &v.state @@ -10174,7 +11478,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DestinationConfig); i { case 0: return &v.state @@ -10186,7 +11490,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RateLimits); i { case 0: return &v.state @@ -10198,7 +11502,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*InstanceLevelRateLimits); i { case 0: return &v.state @@ -10210,7 +11514,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*InstanceLevelRouteRateLimits); i { case 0: return &v.state @@ -10222,7 +11526,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*APIGateway); i { case 0: return &v.state @@ -10234,7 +11538,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Status); i { case 0: return &v.state @@ -10246,7 +11550,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Condition); i { case 0: return &v.state @@ -10258,7 +11562,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*APIGatewayListener); i { case 0: return &v.state @@ -10270,7 +11574,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*APIGatewayTLSConfiguration); i { case 0: return &v.state @@ -10282,7 +11586,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*APIGatewayPolicy); i { case 0: return &v.state @@ -10294,7 +11598,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*APIGatewayJWTRequirement); i { case 0: return &v.state @@ -10306,7 +11610,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*APIGatewayJWTProvider); i { case 0: return &v.state @@ -10318,7 +11622,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*APIGatewayJWTClaimVerification); i { case 0: return &v.state @@ -10330,7 +11634,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ResourceReference); i { case 0: return &v.state @@ -10342,7 +11646,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BoundAPIGateway); i { case 0: return &v.state @@ -10354,7 +11658,19 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListOfResourceReference); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_private_pbconfigentry_config_entry_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BoundAPIGatewayListener); i { case 0: return &v.state @@ -10366,7 +11682,19 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FileSystemCertificate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_private_pbconfigentry_config_entry_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*InlineCertificate); i { case 0: return &v.state @@ -10378,7 +11706,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPRoute); i { case 0: return &v.state @@ -10390,7 +11718,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPRouteRule); i { case 0: return &v.state @@ -10402,7 +11730,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPMatch); i { case 0: return &v.state @@ -10414,7 +11742,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPHeaderMatch); i { case 0: return &v.state @@ -10426,7 +11754,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPPathMatch); i { case 0: return &v.state @@ -10438,7 +11766,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPQueryMatch); i { case 0: return &v.state @@ -10450,7 +11778,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPFilters); i { case 0: return &v.state @@ -10462,7 +11790,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPResponseFilters); i { case 0: return &v.state @@ -10474,7 +11802,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*URLRewrite); i { case 0: return &v.state @@ -10486,7 +11814,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RetryFilter); i { case 0: return &v.state @@ -10498,7 +11826,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TimeoutFilter); i { case 0: return &v.state @@ -10510,7 +11838,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTFilter); i { case 0: return &v.state @@ -10522,7 +11850,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPHeaderFilter); i { case 0: return &v.state @@ -10534,7 +11862,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HTTPService); i { case 0: return &v.state @@ -10546,7 +11874,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TCPRoute); i { case 0: return &v.state @@ -10558,7 +11886,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TCPService); i { case 0: return &v.state @@ -10570,7 +11898,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SamenessGroup); i { case 0: return &v.state @@ -10582,7 +11910,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SamenessGroupMember); i { case 0: return &v.state @@ -10594,7 +11922,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTProvider); i { case 0: return &v.state @@ -10606,7 +11934,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JSONWebKeySet); i { case 0: return &v.state @@ -10618,7 +11946,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[89].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LocalJWKS); i { case 0: return &v.state @@ -10630,7 +11958,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[90].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RemoteJWKS); i { case 0: return &v.state @@ -10642,7 +11970,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[91].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWKSCluster); i { case 0: return &v.state @@ -10654,7 +11982,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[92].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWKSTLSCertificate); i { case 0: return &v.state @@ -10666,7 +11994,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[93].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWKSTLSCertProviderInstance); i { case 0: return &v.state @@ -10678,7 +12006,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[94].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWKSTLSCertTrustedCA); i { case 0: return &v.state @@ -10690,7 +12018,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[95].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWKSRetryPolicy); i { case 0: return &v.state @@ -10702,7 +12030,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[96].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RetryPolicyBackOff); i { case 0: return &v.state @@ -10714,7 +12042,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[89].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[97].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTLocation); i { case 0: return &v.state @@ -10726,7 +12054,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[90].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[98].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTLocationHeader); i { case 0: return &v.state @@ -10738,7 +12066,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[91].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[99].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTLocationQueryParam); i { case 0: return &v.state @@ -10750,7 +12078,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[92].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[100].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTLocationCookie); i { case 0: return &v.state @@ -10762,7 +12090,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[93].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[101].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTForwardingConfig); i { case 0: return &v.state @@ -10774,7 +12102,7 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } - file_private_pbconfigentry_config_entry_proto_msgTypes[94].Exporter = func(v interface{}, i int) interface{} { + file_private_pbconfigentry_config_entry_proto_msgTypes[102].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JWTCacheConfig); i { case 0: return &v.state @@ -10786,8 +12114,44 @@ func file_private_pbconfigentry_config_entry_proto_init() { return nil } } + file_private_pbconfigentry_config_entry_proto_msgTypes[103].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExportedServices); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_private_pbconfigentry_config_entry_proto_msgTypes[104].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExportedServicesService); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_private_pbconfigentry_config_entry_proto_msgTypes[105].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExportedServicesConsumer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } - file_private_pbconfigentry_config_entry_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_private_pbconfigentry_config_entry_proto_msgTypes[4].OneofWrappers = []interface{}{ (*ConfigEntry_MeshConfig)(nil), (*ConfigEntry_ServiceResolver)(nil), (*ConfigEntry_IngressGateway)(nil), @@ -10800,16 +12164,18 @@ func file_private_pbconfigentry_config_entry_proto_init() { (*ConfigEntry_InlineCertificate)(nil), (*ConfigEntry_SamenessGroup)(nil), (*ConfigEntry_JWTProvider)(nil), + (*ConfigEntry_ExportedServices)(nil), + (*ConfigEntry_FileSystemCertificate)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_private_pbconfigentry_config_entry_proto_rawDesc, - NumEnums: 11, - NumMessages: 115, + NumEnums: 13, + NumMessages: 129, NumExtensions: 0, - NumServices: 0, + NumServices: 1, }, GoTypes: file_private_pbconfigentry_config_entry_proto_goTypes, DependencyIndexes: file_private_pbconfigentry_config_entry_proto_depIdxs, diff --git a/proto/private/pbconfigentry/config_entry.proto b/proto/private/pbconfigentry/config_entry.proto index b5143774eeb6..39e37909b992 100644 --- a/proto/private/pbconfigentry/config_entry.proto +++ b/proto/private/pbconfigentry/config_entry.proto @@ -5,10 +5,40 @@ syntax = "proto3"; package hashicorp.consul.internal.configentry; +import "annotations/ratelimit/ratelimit.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; import "private/pbcommon/common.proto"; +// ConfigEntryService handles operations related to config entries +service ConfigEntryService { + rpc GetResolvedExportedServices(GetResolvedExportedServicesRequest) returns (GetResolvedExportedServicesResponse) { + option (hashicorp.consul.internal.ratelimit.spec) = { + operation_type: OPERATION_TYPE_READ, + operation_category: OPERATION_CATEGORY_CONFIGENTRY + }; + } +} + +message GetResolvedExportedServicesRequest { + string Partition = 1; +} + +message GetResolvedExportedServicesResponse { + repeated ResolvedExportedService services = 1; +} + +message ResolvedExportedService { + string Service = 1; + common.EnterpriseMeta EnterpriseMeta = 2; + Consumers Consumers = 3; +} + +message Consumers { + repeated string Peers = 1; + repeated string Partitions = 2; +} + enum Kind { KindUnknown = 0; KindMeshConfig = 1; @@ -23,6 +53,8 @@ enum Kind { KindTCPRoute = 10; KindSamenessGroup = 11; KindJWTProvider = 12; + KindExportedServices = 13; + KindFileSystemCertificate = 14; } message ConfigEntry { @@ -45,6 +77,8 @@ message ConfigEntry { InlineCertificate InlineCertificate = 14; SamenessGroup SamenessGroup = 15; JWTProvider JWTProvider = 16; + ExportedServices ExportedServices = 17; + FileSystemCertificate FileSystemCertificate = 18; } } @@ -61,6 +95,8 @@ message MeshConfig { map Meta = 4; PeeringMeshConfig Peering = 5; bool AllowEnablingPermissiveMutualTLS = 6; + uint64 Hash = 7; + bool ValidateClusters = 8; } // mog annotation: @@ -103,6 +139,16 @@ message MeshDirectionalTLSConfig { // name=Structs message MeshHTTPConfig { bool SanitizeXForwardedClientCert = 1; + MeshDirectionalHTTPConfig Incoming = 2; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.MeshDirectionalHTTPConfig +// output=config_entry.gen.go +// name=Structs +message MeshDirectionalHTTPConfig { + RequestNormalizationMeshConfig RequestNormalization = 1; } // mog annotation: @@ -114,6 +160,34 @@ message PeeringMeshConfig { bool PeerThroughMeshGateways = 1; } +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.RequestNormalizationMeshConfig +// output=config_entry.gen.go +// name=Structs +message RequestNormalizationMeshConfig { + bool InsecureDisablePathNormalization = 1; + bool MergeSlashes = 2; + // mog: func-to=pathWithEscapedSlashesActionToStructs func-from=pathWithEscapedSlashesActionFromStructs + PathWithEscapedSlashesAction PathWithEscapedSlashesAction = 3; + // mog: func-to=headersWithUnderscoresActionToStructs func-from=headersWithUnderscoresActionFromStructs + HeadersWithUnderscoresAction HeadersWithUnderscoresAction = 4; +} + +enum PathWithEscapedSlashesAction { + PathWithEscapedSlashesActionDefault = 0; + PathWithEscapedSlashesActionKeep = 1; + PathWithEscapedSlashesActionReject = 2; + PathWithEscapedSlashesActionUnescapeAndRedirect = 3; + PathWithEscapedSlashesActionUnescapeAndForward = 4; +} + +enum HeadersWithUnderscoresAction { + HeadersWithUnderscoresActionAllow = 0; + HeadersWithUnderscoresActionRejectRequest = 1; + HeadersWithUnderscoresActionDropHeader = 2; +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.ServiceResolverConfigEntry @@ -132,6 +206,7 @@ message ServiceResolver { // mog: func-to=structs.DurationFromProto func-from=structs.DurationToProto google.protobuf.Duration RequestTimeout = 8; ServiceResolverPrioritizeByLocality PrioritizeByLocality = 9; + uint64 Hash = 10; } // mog annotation: @@ -274,6 +349,7 @@ message IngressGateway { repeated IngressListener Listeners = 2; map Meta = 3; IngressServiceConfig Defaults = 4; + uint64 Hash = 5; } // mog annotation: @@ -377,6 +453,7 @@ message ServiceIntentions { repeated SourceIntention Sources = 1; map Meta = 2; IntentionJWTRequirement JWT = 3; + uint64 Hash = 4; } // mog annotation: @@ -482,6 +559,8 @@ message IntentionHTTPHeaderPermission { string Suffix = 5; string Regex = 6; bool Invert = 7; + string Contains = 8; + bool IgnoreCase = 9; } // mog annotation: @@ -513,6 +592,7 @@ message ServiceDefaults { repeated hashicorp.consul.internal.common.EnvoyExtension EnvoyExtensions = 14; // mog: func-to=mutualTLSModeToStructs func-from=mutualTLSModeFromStructs MutualTLSMode MutualTLSMode = 15; + uint64 Hash = 17; } enum ProxyMode { @@ -700,6 +780,7 @@ message APIGateway { map Meta = 1; repeated APIGatewayListener Listeners = 2; Status Status = 3; + uint64 Hash = 4; } // mog annotation: @@ -809,6 +890,13 @@ message ResourceReference { message BoundAPIGateway { map Meta = 1; repeated BoundAPIGatewayListener Listeners = 2; + // mog: func-to=serviceRefsToStructs func-from=serviceRefFromStructs + map Services = 3; + uint64 Hash = 4; +} + +message ListOfResourceReference { + repeated ResourceReference Ref = 1; } // mog annotation: @@ -822,6 +910,19 @@ message BoundAPIGatewayListener { repeated ResourceReference Routes = 3; } +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.FileSystemCertificateConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +message FileSystemCertificate { + map Meta = 1; + string Certificate = 2; + string PrivateKey = 3; + uint64 Hash = 4; +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.InlineCertificateConfigEntry @@ -832,6 +933,7 @@ message InlineCertificate { map Meta = 1; string Certificate = 2; string PrivateKey = 3; + uint64 Hash = 4; } // mog annotation: @@ -846,6 +948,7 @@ message HTTPRoute { repeated HTTPRouteRule Rules = 3; repeated string Hostnames = 4; Status Status = 5; + uint64 Hash = 6; } // mog annotation: @@ -1038,6 +1141,7 @@ message TCPRoute { repeated ResourceReference Parents = 2; repeated TCPService Services = 3; Status Status = 4; + uint64 Hash = 5; } // mog annotation: @@ -1065,6 +1169,7 @@ message SamenessGroup { map Meta = 5; // mog: func-to=enterpriseMetaToStructs func-from=enterpriseMetaFromStructs common.EnterpriseMeta EnterpriseMeta = 6; + uint64 Hash = 7; } // mog annotation: @@ -1093,6 +1198,7 @@ message JWTProvider { map Meta = 7; // mog: func-to=int func-from=int32 int32 ClockSkewSeconds = 8; + uint64 Hash = 9; } // mog annotation: @@ -1257,3 +1363,40 @@ message JWTCacheConfig { // mog: func-to=int func-from=int32 int32 Size = 1; } + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.ExportedServicesConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +message ExportedServices { + string Name = 1; + // mog: func-to=enterpriseMetaToStructs func-from=enterpriseMetaFromStructs + common.EnterpriseMeta EnterpriseMeta = 2; + map Meta = 3; + uint64 Hash = 4; + repeated ExportedServicesService Services = 5; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.ExportedService +// output=config_entry.gen.go +// name=Structs +message ExportedServicesService { + string Name = 1; + string Namespace = 2; + repeated ExportedServicesConsumer Consumers = 3; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.ServiceConsumer +// output=config_entry.gen.go +// name=Structs +message ExportedServicesConsumer { + string Partition = 1; + string Peer = 2; + string SamenessGroup = 3; +} diff --git a/proto/private/pbconfigentry/config_entry_grpc.pb.go b/proto/private/pbconfigentry/config_entry_grpc.pb.go new file mode 100644 index 000000000000..b7c203190bad --- /dev/null +++ b/proto/private/pbconfigentry/config_entry_grpc.pb.go @@ -0,0 +1,103 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc (unknown) +// source: private/pbconfigentry/config_entry.proto + +package pbconfigentry + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// ConfigEntryServiceClient is the client API for ConfigEntryService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type ConfigEntryServiceClient interface { + GetResolvedExportedServices(ctx context.Context, in *GetResolvedExportedServicesRequest, opts ...grpc.CallOption) (*GetResolvedExportedServicesResponse, error) +} + +type configEntryServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewConfigEntryServiceClient(cc grpc.ClientConnInterface) ConfigEntryServiceClient { + return &configEntryServiceClient{cc} +} + +func (c *configEntryServiceClient) GetResolvedExportedServices(ctx context.Context, in *GetResolvedExportedServicesRequest, opts ...grpc.CallOption) (*GetResolvedExportedServicesResponse, error) { + out := new(GetResolvedExportedServicesResponse) + err := c.cc.Invoke(ctx, "/hashicorp.consul.internal.configentry.ConfigEntryService/GetResolvedExportedServices", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ConfigEntryServiceServer is the server API for ConfigEntryService service. +// All implementations should embed UnimplementedConfigEntryServiceServer +// for forward compatibility +type ConfigEntryServiceServer interface { + GetResolvedExportedServices(context.Context, *GetResolvedExportedServicesRequest) (*GetResolvedExportedServicesResponse, error) +} + +// UnimplementedConfigEntryServiceServer should be embedded to have forward compatible implementations. +type UnimplementedConfigEntryServiceServer struct { +} + +func (UnimplementedConfigEntryServiceServer) GetResolvedExportedServices(context.Context, *GetResolvedExportedServicesRequest) (*GetResolvedExportedServicesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetResolvedExportedServices not implemented") +} + +// UnsafeConfigEntryServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ConfigEntryServiceServer will +// result in compilation errors. +type UnsafeConfigEntryServiceServer interface { + mustEmbedUnimplementedConfigEntryServiceServer() +} + +func RegisterConfigEntryServiceServer(s grpc.ServiceRegistrar, srv ConfigEntryServiceServer) { + s.RegisterService(&ConfigEntryService_ServiceDesc, srv) +} + +func _ConfigEntryService_GetResolvedExportedServices_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetResolvedExportedServicesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ConfigEntryServiceServer).GetResolvedExportedServices(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/hashicorp.consul.internal.configentry.ConfigEntryService/GetResolvedExportedServices", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ConfigEntryServiceServer).GetResolvedExportedServices(ctx, req.(*GetResolvedExportedServicesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// ConfigEntryService_ServiceDesc is the grpc.ServiceDesc for ConfigEntryService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ConfigEntryService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "hashicorp.consul.internal.configentry.ConfigEntryService", + HandlerType: (*ConfigEntryServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetResolvedExportedServices", + Handler: _ConfigEntryService_GetResolvedExportedServices_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "private/pbconfigentry/config_entry.proto", +} diff --git a/proto/private/pbconnect/connect.gen.go b/proto/private/pbconnect/connect.gen.go index 5d961d54df08..abecd9b4cf4f 100644 --- a/proto/private/pbconnect/connect.gen.go +++ b/proto/private/pbconnect/connect.gen.go @@ -89,8 +89,6 @@ func IssuedCertToStructsIssuedCert(s *IssuedCert, t *structs.IssuedCert) { t.SerialNumber = s.SerialNumber t.CertPEM = s.CertPEM t.PrivateKeyPEM = s.PrivateKeyPEM - t.WorkloadIdentity = s.WorkloadIdentity - t.WorkloadIdentityURI = s.WorkloadIdentityURI t.Service = s.Service t.ServiceURI = s.ServiceURI t.Agent = s.Agent @@ -110,8 +108,6 @@ func IssuedCertFromStructsIssuedCert(t *structs.IssuedCert, s *IssuedCert) { s.SerialNumber = t.SerialNumber s.CertPEM = t.CertPEM s.PrivateKeyPEM = t.PrivateKeyPEM - s.WorkloadIdentity = t.WorkloadIdentity - s.WorkloadIdentityURI = t.WorkloadIdentityURI s.Service = t.Service s.ServiceURI = t.ServiceURI s.Agent = t.Agent diff --git a/proto/private/pbconnect/connect.pb.go b/proto/private/pbconnect/connect.pb.go index 72fce82238c9..7b50d9a683b2 100644 --- a/proto/private/pbconnect/connect.pb.go +++ b/proto/private/pbconnect/connect.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbconnect/connect.proto @@ -383,10 +383,6 @@ type IssuedCert struct { // ServerURI is the URI value of a cert issued for a server agent. // The same URI is shared by all servers in a Consul datacenter. ServerURI string `protobuf:"bytes,14,opt,name=ServerURI,proto3" json:"ServerURI,omitempty"` - // WorkloadIdentity is the name of the workload identity for which the cert was issued. - WorkloadIdentity string `protobuf:"bytes,15,opt,name=WorkloadIdentity,proto3" json:"WorkloadIdentity,omitempty"` - // WorkloadIdentityURI is the cert URI value. - WorkloadIdentityURI string `protobuf:"bytes,16,opt,name=WorkloadIdentityURI,proto3" json:"WorkloadIdentityURI,omitempty"` // ValidAfter and ValidBefore are the validity periods for the // certificate. // mog: func-to=structs.TimeFromProto func-from=structs.TimeToProto @@ -502,20 +498,6 @@ func (x *IssuedCert) GetServerURI() string { return "" } -func (x *IssuedCert) GetWorkloadIdentity() string { - if x != nil { - return x.WorkloadIdentity - } - return "" -} - -func (x *IssuedCert) GetWorkloadIdentityURI() string { - if x != nil { - return x.WorkloadIdentityURI - } - return "" -} - func (x *IssuedCert) GetValidAfter() *timestamppb.Timestamp { if x != nil { return x.ValidAfter @@ -610,7 +592,7 @@ var file_private_pbconnect_connect_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x52, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0xa5, 0x05, 0x0a, + 0x78, 0x52, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0xd3, 0x04, 0x0a, 0x0a, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, @@ -629,49 +611,43 @@ var file_private_pbconnect_connect_proto_rawDesc = []byte{ 0x18, 0x0a, 0x07, 0x4b, 0x69, 0x6e, 0x64, 0x55, 0x52, 0x49, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4b, 0x69, 0x6e, 0x64, 0x55, 0x52, 0x49, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x55, 0x52, 0x49, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x55, 0x52, 0x49, 0x12, 0x2a, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x6c, - 0x6f, 0x61, 0x64, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x12, 0x30, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x52, 0x49, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x55, 0x52, 0x49, 0x12, 0x3a, 0x0a, 0x0a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x41, 0x66, - 0x74, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x41, 0x66, 0x74, 0x65, - 0x72, 0x12, 0x3c, 0x0a, 0x0b, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x0b, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, - 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x49, 0x0a, 0x09, 0x52, 0x61, 0x66, - 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, - 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x42, 0x92, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x42, 0x0c, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x43, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0xca, 0x02, - 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x24, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x72, 0x76, 0x65, 0x72, 0x55, 0x52, 0x49, 0x12, 0x3a, 0x0a, 0x0a, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x41, 0x66, 0x74, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x41, 0x66, + 0x74, 0x65, 0x72, 0x12, 0x3c, 0x0a, 0x0b, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x42, 0x65, 0x66, 0x6f, + 0x72, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x42, 0x65, 0x66, 0x6f, 0x72, + 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, + 0x65, 0x74, 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, + 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, + 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x49, 0x0a, 0x09, 0x52, + 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x09, 0x52, 0x61, 0x66, + 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4a, 0x04, 0x08, 0x0f, 0x10, 0x10, 0x4a, 0x04, 0x08, 0x10, + 0x10, 0x11, 0x42, 0x92, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x42, 0x0c, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x43, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0xca, 0x02, 0x21, 0x48, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x24, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/private/pbconnect/connect.proto b/proto/private/pbconnect/connect.proto index 4a6d08d220fd..143a0f2eff5c 100644 --- a/proto/private/pbconnect/connect.proto +++ b/proto/private/pbconnect/connect.proto @@ -172,10 +172,8 @@ message IssuedCert { // The same URI is shared by all servers in a Consul datacenter. string ServerURI = 14; - // WorkloadIdentity is the name of the workload identity for which the cert was issued. - string WorkloadIdentity = 15; - // WorkloadIdentityURI is the cert URI value. - string WorkloadIdentityURI = 16; + // 15 & 16 were formerly used for workload identity certs + reserved 15, 16; // ValidAfter and ValidBefore are the validity periods for the // certificate. diff --git a/proto/private/pbdemo/v1/demo.pb.go b/proto/private/pbdemo/v1/demo.pb.go index cb3e2b8cd3ff..e46c589ffcd1 100644 --- a/proto/private/pbdemo/v1/demo.pb.go +++ b/proto/private/pbdemo/v1/demo.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbdemo/v1/demo.proto @@ -13,6 +13,7 @@ package demov1 import ( + _ "github.com/hashicorp/consul/proto-public/pbresource" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -153,7 +154,7 @@ func (x *Executive) GetPosition() string { return "" } -// Partition scoped resource. +// Partition scoped resource type RecordLabel struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -397,66 +398,71 @@ var file_private_pbdemo_v1_demo_proto_rawDesc = []byte{ 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, - 0x31, 0x22, 0x27, 0x0a, 0x09, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x12, 0x1a, - 0x0a, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x43, 0x0a, 0x0b, 0x52, 0x65, - 0x63, 0x6f, 0x72, 0x64, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0xa3, 0x01, 0x0a, 0x06, 0x41, 0x72, 0x74, 0x69, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, - 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x3e, 0x0a, 0x05, 0x67, 0x65, 0x6e, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x28, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x72, 0x65, 0x52, 0x05, 0x67, 0x65, 0x6e, 0x72, 0x65, - 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x05, 0x41, 0x6c, 0x62, 0x75, 0x6d, 0x12, + 0x31, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0x2f, 0x0a, 0x09, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x12, 0x1a, 0x0a, 0x08, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x01, + 0x22, 0x4b, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x79, 0x65, 0x61, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x72, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x79, 0x65, - 0x61, 0x72, 0x4f, 0x66, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x14, 0x63, - 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x6c, 0x61, 0x69, - 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x63, 0x72, 0x69, 0x74, 0x69, - 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x41, 0x63, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x12, 0x16, - 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, - 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x22, 0x09, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x63, 0x65, 0x70, - 0x74, 0x2a, 0xe9, 0x01, 0x0a, 0x05, 0x47, 0x65, 0x6e, 0x72, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x47, - 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x4a, 0x41, 0x5a, 0x5a, - 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x46, 0x4f, 0x4c, 0x4b, - 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x50, 0x4f, 0x50, 0x10, - 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x4c, - 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x50, 0x55, 0x4e, 0x4b, - 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x42, 0x4c, 0x55, 0x45, - 0x53, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x52, 0x5f, 0x41, - 0x4e, 0x44, 0x5f, 0x42, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, - 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x52, 0x59, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, - 0x52, 0x45, 0x5f, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x10, 0x09, 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x45, - 0x4e, 0x52, 0x45, 0x5f, 0x53, 0x4b, 0x41, 0x10, 0x0a, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, - 0x52, 0x45, 0x5f, 0x48, 0x49, 0x50, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x0b, 0x12, 0x0f, 0x0a, 0x0b, - 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x44, 0x49, 0x45, 0x10, 0x0c, 0x42, 0x97, 0x02, - 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x44, 0x65, 0x6d, 0x6f, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, - 0x70, 0x62, 0x64, 0x65, 0x6d, 0x6f, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x65, 0x6d, 0x6f, 0x76, 0x31, - 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x44, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x44, 0x65, 0x6d, 0x6f, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x21, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x44, 0x65, 0x6d, 0x6f, 0x5c, 0x56, 0x31, 0xe2, - 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x44, 0x65, 0x6d, 0x6f, - 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x44, - 0x65, 0x6d, 0x6f, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x02, 0x22, 0xab, 0x01, + 0x0a, 0x06, 0x41, 0x72, 0x74, 0x69, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, + 0x0a, 0x05, 0x67, 0x65, 0x6e, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x72, 0x65, 0x52, 0x05, 0x67, 0x65, 0x6e, 0x72, 0x65, 0x12, 0x23, + 0x0a, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0x96, 0x01, 0x0a, 0x05, + 0x41, 0x6c, 0x62, 0x75, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x79, 0x65, 0x61, + 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0d, 0x79, 0x65, 0x61, 0x72, 0x4f, 0x66, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x12, 0x31, 0x0a, 0x14, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x5f, + 0x61, 0x63, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x13, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x41, 0x63, 0x63, 0x6c, 0x61, + 0x69, 0x6d, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x3a, 0x06, 0xa2, 0x93, + 0x04, 0x02, 0x08, 0x03, 0x22, 0x11, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x3a, + 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x2a, 0xe9, 0x01, 0x0a, 0x05, 0x47, 0x65, 0x6e, 0x72, + 0x65, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, + 0x45, 0x5f, 0x4a, 0x41, 0x5a, 0x5a, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, + 0x45, 0x5f, 0x46, 0x4f, 0x4c, 0x4b, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x45, 0x4e, 0x52, + 0x45, 0x5f, 0x50, 0x4f, 0x50, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, + 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x4c, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, + 0x45, 0x5f, 0x50, 0x55, 0x4e, 0x4b, 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, + 0x45, 0x5f, 0x42, 0x4c, 0x55, 0x45, 0x53, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, + 0x52, 0x45, 0x5f, 0x52, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x42, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, + 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x52, 0x59, 0x10, 0x08, 0x12, + 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x10, 0x09, + 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x53, 0x4b, 0x41, 0x10, 0x0a, 0x12, + 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x48, 0x49, 0x50, 0x5f, 0x48, 0x4f, 0x50, + 0x10, 0x0b, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x44, 0x49, + 0x45, 0x10, 0x0c, 0x42, 0x97, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x44, + 0x65, 0x6d, 0x6f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x64, 0x65, 0x6d, 0x6f, 0x2f, 0x76, 0x31, 0x3b, + 0x64, 0x65, 0x6d, 0x6f, 0x76, 0x31, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x44, 0xaa, 0x02, 0x21, + 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x44, 0x65, 0x6d, 0x6f, 0x2e, 0x56, + 0x31, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x44, 0x65, + 0x6d, 0x6f, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x5c, 0x44, 0x65, 0x6d, 0x6f, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x44, 0x65, 0x6d, 0x6f, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/private/pbdemo/v1/demo.proto b/proto/private/pbdemo/v1/demo.proto index be2f393aafde..effe61fb2840 100644 --- a/proto/private/pbdemo/v1/demo.proto +++ b/proto/private/pbdemo/v1/demo.proto @@ -7,19 +7,27 @@ syntax = "proto3"; // Consul's generic storage APIs. package hashicorp.consul.internal.demo.v1; +import "pbresource/annotations.proto"; + // Cluster scoped resource. message Executive { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_CLUSTER}; + string position = 1; } -// Partition scoped resource. +// Partition scoped resource message RecordLabel { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_PARTITION}; + string name = 1; string description = 2; } // Namespace scoped resource. message Artist { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; + string name = 1; string description = 2; Genre genre = 3; @@ -43,10 +51,14 @@ enum Genre { } message Album { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; + string name = 1; int32 year_of_release = 2; bool critically_acclaimed = 3; repeated string tracks = 4; } -message Concept {} +message Concept { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; +} diff --git a/proto/private/pbdemo/v1/resources.rtypes.go b/proto/private/pbdemo/v1/resources.rtypes.go new file mode 100644 index 000000000000..b6832318d2cd --- /dev/null +++ b/proto/private/pbdemo/v1/resources.rtypes.go @@ -0,0 +1,50 @@ +// Code generated by protoc-gen-resource-types. DO NOT EDIT. + +package demov1 + +import ( + "github.com/hashicorp/consul/proto-public/pbresource" +) + +const ( + GroupName = "demo" + Version = "v1" + + AlbumKind = "Album" + ArtistKind = "Artist" + ConceptKind = "Concept" + ExecutiveKind = "Executive" + RecordLabelKind = "RecordLabel" +) + +var ( + AlbumType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: AlbumKind, + } + + ArtistType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: ArtistKind, + } + + ConceptType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: ConceptKind, + } + + ExecutiveType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: ExecutiveKind, + } + + RecordLabelType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: RecordLabelKind, + } +) diff --git a/proto/private/pbdemo/v2/demo.pb.binary.go b/proto/private/pbdemo/v2/demo.pb.binary.go index 084f70d5b7c2..a1ad58b3aecb 100644 --- a/proto/private/pbdemo/v2/demo.pb.binary.go +++ b/proto/private/pbdemo/v2/demo.pb.binary.go @@ -26,3 +26,13 @@ func (msg *Album) MarshalBinary() ([]byte, error) { func (msg *Album) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *Festival) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *Festival) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} diff --git a/proto/private/pbdemo/v2/demo.pb.go b/proto/private/pbdemo/v2/demo.pb.go index a4c52a99d6a6..ea11aceef625 100644 --- a/proto/private/pbdemo/v2/demo.pb.go +++ b/proto/private/pbdemo/v2/demo.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbdemo/v2/demo.proto @@ -13,6 +13,7 @@ package demov2 import ( + pbresource "github.com/hashicorp/consul/proto-public/pbresource" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -42,6 +43,7 @@ const ( Genre_GENRE_SKA Genre = 10 Genre_GENRE_HIP_HOP Genre = 11 Genre_GENRE_INDIE Genre = 12 + Genre_GENRE_ROCK Genre = 13 ) // Enum value maps for Genre. @@ -60,6 +62,7 @@ var ( 10: "GENRE_SKA", 11: "GENRE_HIP_HOP", 12: "GENRE_INDIE", + 13: "GENRE_ROCK", } Genre_value = map[string]int32{ "GENRE_UNSPECIFIED": 0, @@ -75,6 +78,7 @@ var ( "GENRE_SKA": 10, "GENRE_HIP_HOP": 11, "GENRE_INDIE": 12, + "GENRE_ROCK": 13, } ) @@ -239,6 +243,77 @@ func (x *Album) GetTracks() []string { return nil } +type Festival struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Genres []Genre `protobuf:"varint,2,rep,packed,name=genres,proto3,enum=hashicorp.consul.internal.demo.v2.Genre" json:"genres,omitempty"` + Artists []*Artist `protobuf:"bytes,3,rep,name=artists,proto3" json:"artists,omitempty"` + BoundReferences []*pbresource.Reference `protobuf:"bytes,4,rep,name=bound_references,json=boundReferences,proto3" json:"bound_references,omitempty"` +} + +func (x *Festival) Reset() { + *x = Festival{} + if protoimpl.UnsafeEnabled { + mi := &file_private_pbdemo_v2_demo_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Festival) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Festival) ProtoMessage() {} + +func (x *Festival) ProtoReflect() protoreflect.Message { + mi := &file_private_pbdemo_v2_demo_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Festival.ProtoReflect.Descriptor instead. +func (*Festival) Descriptor() ([]byte, []int) { + return file_private_pbdemo_v2_demo_proto_rawDescGZIP(), []int{2} +} + +func (x *Festival) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Festival) GetGenres() []Genre { + if x != nil { + return x.Genres + } + return nil +} + +func (x *Festival) GetArtists() []*Artist { + if x != nil { + return x.Artists + } + return nil +} + +func (x *Festival) GetBoundReferences() []*pbresource.Reference { + if x != nil { + return x.BoundReferences + } + return nil +} + var File_private_pbdemo_v2_demo_proto protoreflect.FileDescriptor var file_private_pbdemo_v2_demo_proto_rawDesc = []byte{ @@ -246,65 +321,86 @@ var file_private_pbdemo_v2_demo_proto_rawDesc = []byte{ 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, - 0x32, 0x22, 0xff, 0x01, 0x0a, 0x06, 0x41, 0x72, 0x74, 0x69, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x3e, 0x0a, 0x05, 0x67, 0x65, 0x6e, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x28, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, - 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x6e, 0x72, 0x65, 0x52, 0x05, 0x67, 0x65, 0x6e, 0x72, 0x65, - 0x12, 0x60, 0x0a, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x41, 0x72, 0x74, 0x69, - 0x73, 0x74, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x73, 0x1a, 0x3f, 0x0a, 0x11, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0x8e, 0x01, 0x0a, 0x05, 0x41, 0x6c, 0x62, 0x75, 0x6d, 0x12, 0x14, 0x0a, - 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, - 0x74, 0x6c, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x79, 0x65, 0x61, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x72, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x79, 0x65, - 0x61, 0x72, 0x4f, 0x66, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x13, 0x63, - 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x61, 0x63, 0x6c, 0x61, 0x69, 0x6d, - 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, - 0x61, 0x6c, 0x6c, 0x79, 0x41, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, - 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, - 0x61, 0x63, 0x6b, 0x73, 0x2a, 0xe9, 0x01, 0x0a, 0x05, 0x47, 0x65, 0x6e, 0x72, 0x65, 0x12, 0x15, - 0x0a, 0x11, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x4a, - 0x41, 0x5a, 0x5a, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x46, - 0x4f, 0x4c, 0x4b, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x50, - 0x4f, 0x50, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x4d, 0x45, - 0x54, 0x41, 0x4c, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x50, - 0x55, 0x4e, 0x4b, 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x42, - 0x4c, 0x55, 0x45, 0x53, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, - 0x52, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x42, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, - 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x52, 0x59, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b, - 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x10, 0x09, 0x12, 0x0d, 0x0a, - 0x09, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x53, 0x4b, 0x41, 0x10, 0x0a, 0x12, 0x11, 0x0a, 0x0d, - 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x48, 0x49, 0x50, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x0b, 0x12, - 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x44, 0x49, 0x45, 0x10, 0x0c, - 0x42, 0x97, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, 0x32, 0x42, 0x09, 0x44, 0x65, 0x6d, 0x6f, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x2f, 0x70, 0x62, 0x64, 0x65, 0x6d, 0x6f, 0x2f, 0x76, 0x32, 0x3b, 0x64, 0x65, 0x6d, - 0x6f, 0x76, 0x32, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x44, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x44, 0x65, 0x6d, 0x6f, 0x2e, 0x56, 0x32, 0xca, 0x02, - 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x44, 0x65, 0x6d, 0x6f, 0x5c, - 0x56, 0x32, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x44, - 0x65, 0x6d, 0x6f, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x25, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x3a, 0x3a, 0x44, 0x65, 0x6d, 0x6f, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x32, 0x1a, 0x1c, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x19, 0x70, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2f, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x87, 0x02, 0x0a, 0x06, 0x41, + 0x72, 0x74, 0x69, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x05, 0x67, 0x65, 0x6e, + 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x6e, + 0x72, 0x65, 0x52, 0x05, 0x67, 0x65, 0x6e, 0x72, 0x65, 0x12, 0x60, 0x0a, 0x0d, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, + 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x73, 0x74, 0x2e, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x1a, 0x3f, 0x0a, 0x11, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x3a, 0x06, 0xa2, 0x93, + 0x04, 0x02, 0x08, 0x03, 0x22, 0x96, 0x01, 0x0a, 0x05, 0x41, 0x6c, 0x62, 0x75, 0x6d, 0x12, 0x14, + 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, + 0x69, 0x74, 0x6c, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x79, 0x65, 0x61, 0x72, 0x5f, 0x6f, 0x66, 0x5f, + 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x79, + 0x65, 0x61, 0x72, 0x4f, 0x66, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x13, + 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x61, 0x63, 0x6c, 0x61, 0x69, + 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x63, 0x72, 0x69, 0x74, 0x69, + 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x41, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x12, 0x16, 0x0a, + 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, + 0x72, 0x61, 0x63, 0x6b, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x22, 0xfe, 0x01, + 0x0a, 0x08, 0x46, 0x65, 0x73, 0x74, 0x69, 0x76, 0x61, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, + 0x0a, 0x06, 0x67, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x28, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, + 0x76, 0x32, 0x2e, 0x47, 0x65, 0x6e, 0x72, 0x65, 0x52, 0x06, 0x67, 0x65, 0x6e, 0x72, 0x65, 0x73, + 0x12, 0x43, 0x0a, 0x07, 0x61, 0x72, 0x74, 0x69, 0x73, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, + 0x6d, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x73, 0x74, 0x52, 0x07, 0x61, 0x72, + 0x74, 0x69, 0x73, 0x74, 0x73, 0x12, 0x4f, 0x0a, 0x10, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x72, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x3a, 0x06, 0xa2, 0x93, 0x04, 0x02, 0x08, 0x03, 0x2a, 0xf9, + 0x01, 0x0a, 0x05, 0x47, 0x65, 0x6e, 0x72, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x45, 0x4e, 0x52, + 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x4a, 0x41, 0x5a, 0x5a, 0x10, 0x01, 0x12, + 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x46, 0x4f, 0x4c, 0x4b, 0x10, 0x02, 0x12, + 0x0d, 0x0a, 0x09, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x50, 0x4f, 0x50, 0x10, 0x03, 0x12, 0x0f, + 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x4c, 0x10, 0x04, 0x12, + 0x0e, 0x0a, 0x0a, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x50, 0x55, 0x4e, 0x4b, 0x10, 0x05, 0x12, + 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x42, 0x4c, 0x55, 0x45, 0x53, 0x10, 0x06, + 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x52, 0x5f, 0x41, 0x4e, 0x44, 0x5f, + 0x42, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, 0x43, 0x4f, 0x55, + 0x4e, 0x54, 0x52, 0x59, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, + 0x44, 0x49, 0x53, 0x43, 0x4f, 0x10, 0x09, 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x45, 0x4e, 0x52, 0x45, + 0x5f, 0x53, 0x4b, 0x41, 0x10, 0x0a, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x52, 0x45, 0x5f, + 0x48, 0x49, 0x50, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x0b, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x45, 0x4e, + 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x44, 0x49, 0x45, 0x10, 0x0c, 0x12, 0x0e, 0x0a, 0x0a, 0x47, 0x45, + 0x4e, 0x52, 0x45, 0x5f, 0x52, 0x4f, 0x43, 0x4b, 0x10, 0x0d, 0x42, 0x97, 0x02, 0x0a, 0x25, 0x63, + 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x64, 0x65, 0x6d, + 0x6f, 0x2e, 0x76, 0x32, 0x42, 0x09, 0x44, 0x65, 0x6d, 0x6f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x64, + 0x65, 0x6d, 0x6f, 0x2f, 0x76, 0x32, 0x3b, 0x64, 0x65, 0x6d, 0x6f, 0x76, 0x32, 0xa2, 0x02, 0x04, + 0x48, 0x43, 0x49, 0x44, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x44, 0x65, 0x6d, 0x6f, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x44, 0x65, 0x6d, 0x6f, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x2d, 0x48, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x44, 0x65, 0x6d, 0x6f, 0x5c, 0x56, 0x32, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x25, 0x48, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x44, 0x65, 0x6d, 0x6f, + 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -320,21 +416,26 @@ func file_private_pbdemo_v2_demo_proto_rawDescGZIP() []byte { } var file_private_pbdemo_v2_demo_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_private_pbdemo_v2_demo_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_private_pbdemo_v2_demo_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_private_pbdemo_v2_demo_proto_goTypes = []interface{}{ - (Genre)(0), // 0: hashicorp.consul.internal.demo.v2.Genre - (*Artist)(nil), // 1: hashicorp.consul.internal.demo.v2.Artist - (*Album)(nil), // 2: hashicorp.consul.internal.demo.v2.Album - nil, // 3: hashicorp.consul.internal.demo.v2.Artist.GroupMembersEntry + (Genre)(0), // 0: hashicorp.consul.internal.demo.v2.Genre + (*Artist)(nil), // 1: hashicorp.consul.internal.demo.v2.Artist + (*Album)(nil), // 2: hashicorp.consul.internal.demo.v2.Album + (*Festival)(nil), // 3: hashicorp.consul.internal.demo.v2.Festival + nil, // 4: hashicorp.consul.internal.demo.v2.Artist.GroupMembersEntry + (*pbresource.Reference)(nil), // 5: hashicorp.consul.resource.Reference } var file_private_pbdemo_v2_demo_proto_depIdxs = []int32{ 0, // 0: hashicorp.consul.internal.demo.v2.Artist.genre:type_name -> hashicorp.consul.internal.demo.v2.Genre - 3, // 1: hashicorp.consul.internal.demo.v2.Artist.group_members:type_name -> hashicorp.consul.internal.demo.v2.Artist.GroupMembersEntry - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 4, // 1: hashicorp.consul.internal.demo.v2.Artist.group_members:type_name -> hashicorp.consul.internal.demo.v2.Artist.GroupMembersEntry + 0, // 2: hashicorp.consul.internal.demo.v2.Festival.genres:type_name -> hashicorp.consul.internal.demo.v2.Genre + 1, // 3: hashicorp.consul.internal.demo.v2.Festival.artists:type_name -> hashicorp.consul.internal.demo.v2.Artist + 5, // 4: hashicorp.consul.internal.demo.v2.Festival.bound_references:type_name -> hashicorp.consul.resource.Reference + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_private_pbdemo_v2_demo_proto_init() } @@ -367,6 +468,18 @@ func file_private_pbdemo_v2_demo_proto_init() { return nil } } + file_private_pbdemo_v2_demo_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Festival); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -374,7 +487,7 @@ func file_private_pbdemo_v2_demo_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_private_pbdemo_v2_demo_proto_rawDesc, NumEnums: 1, - NumMessages: 3, + NumMessages: 4, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/private/pbdemo/v2/demo.proto b/proto/private/pbdemo/v2/demo.proto index 546cfe697261..e8c3d2fd7369 100644 --- a/proto/private/pbdemo/v2/demo.proto +++ b/proto/private/pbdemo/v2/demo.proto @@ -7,7 +7,12 @@ syntax = "proto3"; // Consul's generic storage APIs. package hashicorp.consul.internal.demo.v2; +import "pbresource/annotations.proto"; +import "pbresource/resource.proto"; + message Artist { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; + string name = 1; Genre genre = 2; map group_members = 3; @@ -27,11 +32,24 @@ enum Genre { GENRE_SKA = 10; GENRE_HIP_HOP = 11; GENRE_INDIE = 12; + GENRE_ROCK = 13; } message Album { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; + string title = 1; int32 year_of_release = 2; bool critically_aclaimed = 3; repeated string tracks = 4; } + +message Festival { + option (hashicorp.consul.resource.spec) = {scope: SCOPE_NAMESPACE}; + + string name = 1; + repeated Genre genres = 2; + repeated Artist artists = 3; + + repeated hashicorp.consul.resource.Reference bound_references = 4; +} diff --git a/proto/private/pbdemo/v2/resources.rtypes.go b/proto/private/pbdemo/v2/resources.rtypes.go new file mode 100644 index 000000000000..3eaf79d6c223 --- /dev/null +++ b/proto/private/pbdemo/v2/resources.rtypes.go @@ -0,0 +1,36 @@ +// Code generated by protoc-gen-resource-types. DO NOT EDIT. + +package demov2 + +import ( + "github.com/hashicorp/consul/proto-public/pbresource" +) + +const ( + GroupName = "demo" + Version = "v2" + + AlbumKind = "Album" + ArtistKind = "Artist" + FestivalKind = "Festival" +) + +var ( + AlbumType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: AlbumKind, + } + + ArtistType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: ArtistKind, + } + + FestivalType = &pbresource.Type{ + Group: GroupName, + GroupVersion: Version, + Kind: FestivalKind, + } +) diff --git a/proto/private/pboperator/operator.pb.go b/proto/private/pboperator/operator.pb.go index e7e457bc7389..18a800e66341 100644 --- a/proto/private/pboperator/operator.pb.go +++ b/proto/private/pboperator/operator.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pboperator/operator.proto diff --git a/proto/private/pbpeering/peering.pb.go b/proto/private/pbpeering/peering.pb.go index a0c7bd21676d..373f316317a2 100644 --- a/proto/private/pbpeering/peering.pb.go +++ b/proto/private/pbpeering/peering.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbpeering/peering.proto diff --git a/proto/private/pbpeerstream/peerstream.pb.go b/proto/private/pbpeerstream/peerstream.pb.go index aeb1bdb22082..97b03c3a6f0e 100644 --- a/proto/private/pbpeerstream/peerstream.pb.go +++ b/proto/private/pbpeerstream/peerstream.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbpeerstream/peerstream.proto diff --git a/proto/private/pbservice/healthcheck.pb.go b/proto/private/pbservice/healthcheck.pb.go index 0392fd77455b..252459957b91 100644 --- a/proto/private/pbservice/healthcheck.pb.go +++ b/proto/private/pbservice/healthcheck.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbservice/healthcheck.proto diff --git a/proto/private/pbservice/node.pb.go b/proto/private/pbservice/node.pb.go index 3d562fe31f71..0d02640a7d9e 100644 --- a/proto/private/pbservice/node.pb.go +++ b/proto/private/pbservice/node.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbservice/node.proto diff --git a/proto/private/pbservice/service.pb.go b/proto/private/pbservice/service.pb.go index 871b6a04118c..b913357adfbc 100644 --- a/proto/private/pbservice/service.pb.go +++ b/proto/private/pbservice/service.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbservice/service.proto diff --git a/proto/private/pbstatus/status.pb.go b/proto/private/pbstatus/status.pb.go index ce1658b68cc0..f381fc385328 100644 --- a/proto/private/pbstatus/status.pb.go +++ b/proto/private/pbstatus/status.pb.go @@ -14,7 +14,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbstatus/status.proto diff --git a/proto/private/pbstorage/raft.pb.go b/proto/private/pbstorage/raft.pb.go index 6efa5c8f8fb1..7871faef0f46 100644 --- a/proto/private/pbstorage/raft.pb.go +++ b/proto/private/pbstorage/raft.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbstorage/raft.proto diff --git a/proto/private/pbsubscribe/subscribe.pb.go b/proto/private/pbsubscribe/subscribe.pb.go index 93dcf9c21c23..0aee8eb364fb 100644 --- a/proto/private/pbsubscribe/subscribe.pb.go +++ b/proto/private/pbsubscribe/subscribe.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: private/pbsubscribe/subscribe.proto @@ -78,6 +78,10 @@ const ( Topic_SamenessGroup Topic = 15 // JWTProvider topic contains events for changes to jwt-provider Topic_JWTProvider Topic = 16 + // ExportedServices topic contains events for changes to exported-services. + Topic_ExportedServices Topic = 17 + // FileSystemCertificate topic contains events for changes to file-system-certificates. + Topic_FileSystemCertificate Topic = 18 ) // Enum value maps for Topic. @@ -100,25 +104,29 @@ var ( 14: "IPRateLimit", 15: "SamenessGroup", 16: "JWTProvider", + 17: "ExportedServices", + 18: "FileSystemCertificate", } Topic_value = map[string]int32{ - "Unknown": 0, - "ServiceHealth": 1, - "ServiceHealthConnect": 2, - "MeshConfig": 3, - "ServiceResolver": 4, - "IngressGateway": 5, - "ServiceIntentions": 6, - "ServiceList": 7, - "ServiceDefaults": 8, - "APIGateway": 9, - "TCPRoute": 10, - "HTTPRoute": 11, - "InlineCertificate": 12, - "BoundAPIGateway": 13, - "IPRateLimit": 14, - "SamenessGroup": 15, - "JWTProvider": 16, + "Unknown": 0, + "ServiceHealth": 1, + "ServiceHealthConnect": 2, + "MeshConfig": 3, + "ServiceResolver": 4, + "IngressGateway": 5, + "ServiceIntentions": 6, + "ServiceList": 7, + "ServiceDefaults": 8, + "APIGateway": 9, + "TCPRoute": 10, + "HTTPRoute": 11, + "InlineCertificate": 12, + "BoundAPIGateway": 13, + "IPRateLimit": 14, + "SamenessGroup": 15, + "JWTProvider": 16, + "ExportedServices": 17, + "FileSystemCertificate": 18, } ) @@ -1000,7 +1008,7 @@ var file_private_pbsubscribe_subscribe_proto_rawDesc = []byte{ 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x2a, 0xc5, 0x02, 0x0a, 0x05, 0x54, 0x6f, + 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x2a, 0xf6, 0x02, 0x0a, 0x05, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, @@ -1021,26 +1029,29 @@ var file_private_pbsubscribe_subscribe_proto_rawDesc = []byte{ 0x49, 0x50, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x61, 0x6d, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x10, 0x0f, 0x12, 0x0f, 0x0a, 0x0b, 0x4a, 0x57, 0x54, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x10, - 0x10, 0x2a, 0x29, 0x0a, 0x09, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x4f, 0x70, 0x12, 0x0c, - 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, - 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x01, 0x32, 0x61, 0x0a, 0x17, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x62, 0x65, 0x12, 0x1b, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, - 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x10, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x09, 0x30, 0x01, 0x42, - 0x9a, 0x01, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x42, 0x0e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, - 0x62, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xa2, 0x02, 0x03, 0x53, 0x58, 0x58, - 0xaa, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xca, 0x02, 0x09, 0x53, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xe2, 0x02, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x62, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x10, 0x12, 0x14, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x10, 0x11, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x69, 0x6c, 0x65, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x10, 0x12, 0x2a, 0x29, 0x0a, 0x09, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x4f, 0x70, 0x12, + 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x00, 0x12, 0x0e, 0x0a, + 0x0a, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x01, 0x32, 0x61, 0x0a, + 0x17, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x1b, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, + 0x65, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x09, 0x30, 0x01, + 0x42, 0x9a, 0x01, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0x42, 0x0e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, + 0x70, 0x62, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xa2, 0x02, 0x03, 0x53, 0x58, + 0x58, 0xaa, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xca, 0x02, 0x09, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xe2, 0x02, 0x15, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x62, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0xea, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/private/pbsubscribe/subscribe.proto b/proto/private/pbsubscribe/subscribe.proto index c327c92c7f02..0ce015cc6f49 100644 --- a/proto/private/pbsubscribe/subscribe.proto +++ b/proto/private/pbsubscribe/subscribe.proto @@ -106,6 +106,12 @@ enum Topic { // JWTProvider topic contains events for changes to jwt-provider JWTProvider = 16; + + // ExportedServices topic contains events for changes to exported-services. + ExportedServices = 17; + + // FileSystemCertificate topic contains events for changes to file-system-certificates. + FileSystemCertificate = 18; } message NamedSubject { diff --git a/scan.hcl b/scan.hcl new file mode 100644 index 000000000000..0da769efb473 --- /dev/null +++ b/scan.hcl @@ -0,0 +1,44 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +# Configuration for security scanner. +# Run on PRs and pushes to `main` and `release/**` branches. +# See .github/workflows/security-scan.yml for CI config. + +# To run manually, install scanner and then run `scan repository .` + +# Scan results are triaged via the GitHub Security tab for this repo. +# See `security-scanner` docs for more information on how to add `triage` config +# for specific results or to exclude paths. + +# .release/security-scan.hcl controls scanner config for release artifacts, which +# unlike the scans configured here, will block releases in CRT. + +repository { + go_modules = true + npm = true + osv = true + go_stdlib_version_file = ".go-version" + + secrets { + all = true + } + + # Triage items that are _safe_ to ignore here. Note that this list should be + # periodically cleaned up to remove items that are no longer found by the scanner. + triage { + suppress { + # N.b. `vulnerabilites` is the correct spelling for this tool. + vulnerabilites = [ + ] + paths = [ + "internal/tools/proto-gen-rpc-glue/e2e/consul/*", + "test/integration/connect/envoy/test-sds-server/*", + "test/integration/consul-container/*", + "testing/deployer/*", + "test-integ/*", + "agent/uiserver/dist/assets/vendor-*.js", + ] + } + } +} diff --git a/sdk/.copywrite.hcl b/sdk/.copywrite.hcl index 34d99ba25e12..7e4c0b58a8a3 100644 --- a/sdk/.copywrite.hcl +++ b/sdk/.copywrite.hcl @@ -2,7 +2,7 @@ schema_version = 1 project { license = "MPL-2.0" - copyright_year = 2023 + copyright_year = 2024 header_ignore = [] } diff --git a/sdk/go.mod b/sdk/go.mod index f4adaf73ba79..d7f7a4441d72 100644 --- a/sdk/go.mod +++ b/sdk/go.mod @@ -8,16 +8,16 @@ require ( github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.2.1 github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.8.3 - golang.org/x/sys v0.13.0 + github.com/stretchr/testify v1.8.4 + golang.org/x/sys v0.19.0 ) require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/fatih/color v1.14.1 // indirect + github.com/fatih/color v1.16.0 // indirect github.com/kr/pretty v0.3.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/sdk/go.sum b/sdk/go.sum index 490559d90093..e2ef238da125 100644 --- a/sdk/go.sum +++ b/sdk/go.sum @@ -4,8 +4,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= @@ -29,8 +29,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -41,16 +41,17 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/sdk/iptables/iptables.go b/sdk/iptables/iptables.go index 32f089a6c9a8..7ebd07b8c5a6 100644 --- a/sdk/iptables/iptables.go +++ b/sdk/iptables/iptables.go @@ -71,6 +71,16 @@ type Config struct { IptablesProvider Provider } +// AdditionalRulesFn can be implemented by the caller to +// add environment specific rules (like ECS) that needs to +// be executed for traffic redirection to work properly. +// +// This gets called by the Setup function after all the +// first class iptable rules are added. The implemented +// function should only call the `AddRule` and optionally +// the `Rules` method of the provider. +type AdditionalRulesFn func(iptablesProvider Provider) + // Provider is an interface for executing iptables rules. type Provider interface { // AddRule adds a rule without executing it. @@ -78,16 +88,25 @@ type Provider interface { // ApplyRules executes rules that have been added via AddRule. // This operation is currently not atomic, and if there's an error applying rules, // you may be left in a state where partial rules were applied. + // ApplyRules should not be called twice on the same instance in order to avoid + // duplicate rule application. ApplyRules() error - // Rules returns the list of rules that have been added but not applied yet. + // Rules returns the list of rules that have been added (including those not yet + // applied). Rules() []string } // Setup will set up iptables interception and redirection rules // based on the configuration provided in cfg. -// This implementation was inspired by -// https://github.com/openservicemesh/osm/blob/650a1a1dcf081ae90825f3b5dba6f30a0e532725/pkg/injector/iptables.go func Setup(cfg Config) error { + return SetupWithAdditionalRules(cfg, nil) +} + +// SetupWithAdditionalRules will set up iptables interception and redirection rules +// based on the configuration provided in cfg. The additionalRulesFn will be applied +// after the normal set of rules. This implementation was inspired by +// https://github.com/openservicemesh/osm/blob/650a1a1dcf081ae90825f3b5dba6f30a0e532725/pkg/injector/iptables.go +func SetupWithAdditionalRules(cfg Config, additionalRulesFn AdditionalRulesFn) error { if cfg.IptablesProvider == nil { cfg.IptablesProvider = &iptablesExecutor{cfg: cfg} } @@ -179,6 +198,11 @@ func Setup(cfg Config) error { } } + // Call function to add any additional rules passed on by the caller + if additionalRulesFn != nil { + additionalRulesFn(cfg.IptablesProvider) + } + return cfg.IptablesProvider.ApplyRules() } diff --git a/sdk/iptables/iptables_test.go b/sdk/iptables/iptables_test.go index 20a3e193523c..0bd740fd8154 100644 --- a/sdk/iptables/iptables_test.go +++ b/sdk/iptables/iptables_test.go @@ -12,9 +12,10 @@ import ( func TestSetup(t *testing.T) { cases := []struct { - name string - cfg Config - expectedRules []string + name string + cfg Config + additionalRules [][]string + expectedRules []string }{ { "no proxy outbound port provided", @@ -23,6 +24,7 @@ func TestSetup(t *testing.T) { ProxyInboundPort: 20000, IptablesProvider: &fakeIptablesProvider{}, }, + nil, []string{ "iptables -t nat -N CONSUL_PROXY_INBOUND", "iptables -t nat -N CONSUL_PROXY_IN_REDIRECT", @@ -47,6 +49,7 @@ func TestSetup(t *testing.T) { ConsulDNSIP: "10.0.34.16", IptablesProvider: &fakeIptablesProvider{}, }, + nil, []string{ "iptables -t nat -N CONSUL_PROXY_INBOUND", "iptables -t nat -N CONSUL_PROXY_IN_REDIRECT", @@ -75,6 +78,7 @@ func TestSetup(t *testing.T) { ConsulDNSPort: 8600, IptablesProvider: &fakeIptablesProvider{}, }, + nil, []string{ "iptables -t nat -N CONSUL_PROXY_INBOUND", "iptables -t nat -N CONSUL_PROXY_IN_REDIRECT", @@ -104,6 +108,7 @@ func TestSetup(t *testing.T) { ConsulDNSPort: 8600, IptablesProvider: &fakeIptablesProvider{}, }, + nil, []string{ "iptables -t nat -N CONSUL_PROXY_INBOUND", "iptables -t nat -N CONSUL_PROXY_IN_REDIRECT", @@ -132,6 +137,7 @@ func TestSetup(t *testing.T) { ProxyOutboundPort: 21000, IptablesProvider: &fakeIptablesProvider{}, }, + nil, []string{ "iptables -t nat -N CONSUL_PROXY_INBOUND", "iptables -t nat -N CONSUL_PROXY_IN_REDIRECT", @@ -157,6 +163,7 @@ func TestSetup(t *testing.T) { ExcludeInboundPorts: []string{"22000", "22500"}, IptablesProvider: &fakeIptablesProvider{}, }, + nil, []string{ "iptables -t nat -N CONSUL_PROXY_INBOUND", "iptables -t nat -N CONSUL_PROXY_IN_REDIRECT", @@ -184,6 +191,7 @@ func TestSetup(t *testing.T) { ExcludeOutboundPorts: []string{"22000", "22500"}, IptablesProvider: &fakeIptablesProvider{}, }, + nil, []string{ "iptables -t nat -N CONSUL_PROXY_INBOUND", "iptables -t nat -N CONSUL_PROXY_IN_REDIRECT", @@ -211,6 +219,7 @@ func TestSetup(t *testing.T) { ExcludeOutboundCIDRs: []string{"1.1.1.1", "2.2.2.2/24"}, IptablesProvider: &fakeIptablesProvider{}, }, + nil, []string{ "iptables -t nat -N CONSUL_PROXY_INBOUND", "iptables -t nat -N CONSUL_PROXY_IN_REDIRECT", @@ -238,6 +247,7 @@ func TestSetup(t *testing.T) { ExcludeUIDs: []string{"456", "789"}, IptablesProvider: &fakeIptablesProvider{}, }, + nil, []string{ "iptables -t nat -N CONSUL_PROXY_INBOUND", "iptables -t nat -N CONSUL_PROXY_IN_REDIRECT", @@ -256,11 +266,53 @@ func TestSetup(t *testing.T) { "iptables -t nat -A CONSUL_PROXY_INBOUND -p tcp -j CONSUL_PROXY_IN_REDIRECT", }, }, + { + "additional rules are passed", + Config{ + ProxyUserID: "123", + ProxyInboundPort: 20000, + ProxyOutboundPort: 21000, + ExcludeUIDs: []string{"456", "789"}, + IptablesProvider: &fakeIptablesProvider{}, + }, + [][]string{ + {"iptables", "-t", "nat", "--policy", "POSTROUTING", "ACCEPT"}, + {"iptables", "-t", "nat", "--policy", "PREROUTING", "ACCEPT"}, + }, + []string{ + "iptables -t nat -N CONSUL_PROXY_INBOUND", + "iptables -t nat -N CONSUL_PROXY_IN_REDIRECT", + "iptables -t nat -N CONSUL_PROXY_OUTPUT", + "iptables -t nat -N CONSUL_PROXY_REDIRECT", + "iptables -t nat -N CONSUL_DNS_REDIRECT", + "iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 21000", + "iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT", + "iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN", + "iptables -t nat -A CONSUL_PROXY_OUTPUT -d 127.0.0.1/32 -j RETURN", + "iptables -t nat -A CONSUL_PROXY_OUTPUT -j CONSUL_PROXY_REDIRECT", + "iptables -t nat -I CONSUL_PROXY_OUTPUT -m owner --uid-owner 456 -j RETURN", + "iptables -t nat -I CONSUL_PROXY_OUTPUT -m owner --uid-owner 789 -j RETURN", + "iptables -t nat -A CONSUL_PROXY_IN_REDIRECT -p tcp -j REDIRECT --to-port 20000", + "iptables -t nat -A PREROUTING -p tcp -j CONSUL_PROXY_INBOUND", + "iptables -t nat -A CONSUL_PROXY_INBOUND -p tcp -j CONSUL_PROXY_IN_REDIRECT", + "iptables -t nat --policy POSTROUTING ACCEPT", + "iptables -t nat --policy PREROUTING ACCEPT", + }, + }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { - err := Setup(c.cfg) + var fn AdditionalRulesFn + if c.additionalRules != nil { + fn = func(provider Provider) { + for _, rule := range c.additionalRules { + provider.AddRule(rule[0], rule[1:]...) + } + } + } + + err := SetupWithAdditionalRules(c.cfg, fn) require.NoError(t, err) require.Equal(t, c.expectedRules, c.cfg.IptablesProvider.Rules()) }) diff --git a/sdk/testutil/io.go b/sdk/testutil/io.go index 7b446339728b..38722cc98159 100644 --- a/sdk/testutil/io.go +++ b/sdk/testutil/io.go @@ -16,7 +16,7 @@ var saveSnapshot = strings.ToLower(os.Getenv("TEST_SAVE_SNAPSHOT")) == "true" // If the directory cannot be created t.Fatal is called. // The directory will be removed when the test ends. Set TEST_NOCLEANUP env var // to prevent the directory from being removed. -func TempDir(t testing.TB, name string) string { +func TempDir(t TestingTB, name string) string { if t == nil { panic("argument t must be non-nil") } diff --git a/sdk/testutil/retry/doc.go b/sdk/testutil/retry/doc.go new file mode 100644 index 000000000000..4afaac062bb2 --- /dev/null +++ b/sdk/testutil/retry/doc.go @@ -0,0 +1,22 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Package retry provides support for repeating operations in tests. +// +// A sample retry operation looks like this: +// +// func TestX(t *testing.T) { +// retry.Run(t, func(r *retry.R) { +// if err := foo(); err != nil { +// r.Errorf("foo: %s", err) +// return +// } +// }) +// } +// +// Run uses the DefaultFailer, which is a Timer with a Timeout of 7s, +// and a Wait of 25ms. To customize, use RunWith. +// +// WARNING: unlike *testing.T, *retry.R#Fatal and FailNow *do not* +// fail the test function entirely, only the current run the retry func +package retry diff --git a/sdk/testutil/retry/interface.go b/sdk/testutil/retry/interface.go new file mode 100644 index 000000000000..78d2d948ffe1 --- /dev/null +++ b/sdk/testutil/retry/interface.go @@ -0,0 +1,35 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package retry + +import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var nilInf TestingTB = nil + +// Assertion that our TestingTB can be passed to +var _ require.TestingT = nilInf +var _ assert.TestingT = nilInf + +// TestingTB is an interface that describes the implementation of the testing object. +// Using an interface that describes testing.TB instead of the actual implementation +// makes testutil usable in a wider variety of contexts (e.g. use with ginkgo : https://godoc.org/github.com/onsi/ginkgo#GinkgoT) +type TestingTB interface { + Cleanup(func()) + Error(args ...any) + Errorf(format string, args ...any) + Fail() + FailNow() + Failed() bool + Fatal(args ...any) + Fatalf(format string, args ...any) + Helper() + Log(args ...any) + Logf(format string, args ...any) + Name() string + Setenv(key, value string) + TempDir() string +} diff --git a/sdk/testutil/retry/output.go b/sdk/testutil/retry/output.go new file mode 100644 index 000000000000..6d4006f42d02 --- /dev/null +++ b/sdk/testutil/retry/output.go @@ -0,0 +1,42 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package retry + +import ( + "bytes" + "fmt" + "runtime" + "strings" +) + +func dedup(a []string) string { + if len(a) == 0 { + return "" + } + seen := map[string]struct{}{} + var b bytes.Buffer + for _, s := range a { + if _, ok := seen[s]; ok { + continue + } + seen[s] = struct{}{} + b.WriteString(s) + b.WriteRune('\n') + } + return b.String() +} + +func decorate(s string) string { + _, file, line, ok := runtime.Caller(3) + if ok { + n := strings.LastIndex(file, "/") + if n >= 0 { + file = file[n+1:] + } + } else { + file = "???" + line = 1 + } + return fmt.Sprintf("%s:%d: %s", file, line, s) +} diff --git a/sdk/testutil/retry/retry.go b/sdk/testutil/retry/retry.go index af468460d592..a8a8ac5d6fe4 100644 --- a/sdk/testutil/retry/retry.go +++ b/sdk/testutil/retry/retry.go @@ -1,263 +1,232 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -// Package retry provides support for repeating operations in tests. -// -// A sample retry operation looks like this: -// -// func TestX(t *testing.T) { -// retry.Run(t, func(r *retry.R) { -// if err := foo(); err != nil { -// r.Errorf("foo: %s", err) -// return -// } -// }) -// } -// -// Run uses the DefaultFailer, which is a Timer with a Timeout of 7s, -// and a Wait of 25ms. To customize, use RunWith. -// -// WARNING: unlike *testing.T, *retry.R#Fatal and FailNow *do not* -// fail the test function entirely, only the current run the retry func package retry import ( - "bytes" "fmt" - "runtime" - "strings" - "time" + "os" ) -// Failer is an interface compatible with testing.T. -type Failer interface { - Helper() +var _ TestingTB = &R{} - // Log is called for the final test output - Log(args ...interface{}) +type R struct { + wrapped TestingTB + retryer Retryer - // FailNow is called when the retrying is abandoned. - FailNow() -} + done bool + fullOutput bool + immediateCleanup bool -// R provides context for the retryer. -// -// Logs from Logf, (Error|Fatal)(f) are gathered in an internal buffer -// and printed only if the retryer fails. Printed logs are deduped and -// prefixed with source code line numbers -type R struct { - // fail is set by FailNow and (Fatal|Error)(f). It indicates the pass - // did not succeed, and should be retried - fail bool - // done is set by Stop. It indicates the entire run was a failure, - // and triggers t.FailNow() - done bool - output []string + attempts []*attempt +} - cleanups []func() +func (r *R) Cleanup(clean func()) { + if r.immediateCleanup { + a := r.getCurrentAttempt() + a.cleanups = append(a.cleanups, clean) + } else { + r.wrapped.Cleanup(clean) + } } -func (r *R) Logf(format string, args ...interface{}) { - r.log(fmt.Sprintf(format, args...)) +func (r *R) Error(args ...any) { + r.Log(args...) + r.Fail() } -func (r *R) Log(args ...interface{}) { - r.log(fmt.Sprintln(args...)) +func (r *R) Errorf(format string, args ...any) { + r.Logf(format, args...) + r.Fail() } -func (r *R) Helper() {} +func (r *R) Fail() { + r.getCurrentAttempt().failed = true +} -// Cleanup register a function to be run to cleanup resources that -// were allocated during the retry attempt. These functions are executed -// after a retry attempt. If they panic, it will not stop further retry -// attempts but will be cause for the overall test failure. -func (r *R) Cleanup(fn func()) { - r.cleanups = append(r.cleanups, fn) +func (r *R) FailNow() { + r.Fail() + panic(attemptFailed{}) } -func (r *R) runCleanup() { +func (r *R) Failed() bool { + return r.getCurrentAttempt().failed +} - // Make sure that if a cleanup function panics, - // we still run the remaining cleanup functions. - defer func() { - err := recover() - if err != nil { - r.Stop(fmt.Errorf("error when performing test cleanup: %v", err)) - } - if len(r.cleanups) > 0 { - r.runCleanup() - } - }() +func (r *R) Fatal(args ...any) { + r.Log(args...) + r.FailNow() +} - for len(r.cleanups) > 0 { - var cleanup func() - if len(r.cleanups) > 0 { - last := len(r.cleanups) - 1 - cleanup = r.cleanups[last] - r.cleanups = r.cleanups[:last] - } - if cleanup != nil { - cleanup() - } - } +func (r *R) Fatalf(format string, args ...any) { + r.Logf(format, args...) + r.FailNow() } -// runFailed is a sentinel value to indicate that the func itself -// didn't panic, rather that `FailNow` was called. -type runFailed struct{} - -// FailNow stops run execution. It is roughly equivalent to: -// -// r.Error("") -// return -// -// inside the function being run. -func (r *R) FailNow() { - r.fail = true - panic(runFailed{}) +func (r *R) Helper() { + // *testing.T will just record which functions are helpers by their addresses and + // it doesn't much matter where where we record that they are helpers + r.wrapped.Helper() } -// Fatal is equivalent to r.Logf(args) followed by r.FailNow(), i.e. the run -// function should be exited. Retries on the next run are allowed. Fatal is -// equivalent to -// -// r.Error(args) -// return -// -// inside the function being run. -func (r *R) Fatal(args ...interface{}) { - r.log(fmt.Sprint(args...)) - r.FailNow() +func (r *R) Log(args ...any) { + r.log(fmt.Sprintln(args...)) } -// Fatalf is like Fatal but allows a format string -func (r *R) Fatalf(format string, args ...interface{}) { +func (r *R) Logf(format string, args ...any) { r.log(fmt.Sprintf(format, args...)) - r.FailNow() } -// Error indicates the current run encountered an error and should be retried. -// It *does not* stop execution of the rest of the run function. -func (r *R) Error(args ...interface{}) { - r.log(fmt.Sprint(args...)) - r.fail = true +// Name will return the name of the underlying TestingT. +func (r *R) Name() string { + return r.wrapped.Name() } -// Errorf is like Error but allows a format string -func (r *R) Errorf(format string, args ...interface{}) { - r.log(fmt.Sprintf(format, args...)) - r.fail = true +// Setenv will save the current value of the specified env var, set it to the +// specified value and then restore it to the original value in a cleanup function +// once the retry attempt has finished. +func (r *R) Setenv(key, value string) { + prevValue, ok := os.LookupEnv(key) + + if err := os.Setenv(key, value); err != nil { + r.wrapped.Fatalf("cannot set environment variable: %v", err) + } + + if ok { + r.Cleanup(func() { + os.Setenv(key, prevValue) + }) + } else { + r.Cleanup(func() { + os.Unsetenv(key) + }) + } } -// If err is non-nil, equivalent to r.Fatal(err.Error()) followed by -// r.FailNow(). Otherwise a no-op. +// TempDir will use the wrapped TestingT to create a temporary directory +// that will be cleaned up when ALL RETRYING has finished. +func (r *R) TempDir() string { + return r.wrapped.TempDir() +} + +// Check will call r.Fatal(err) if err is not nil func (r *R) Check(err error) { if err != nil { - r.log(err.Error()) - r.FailNow() + r.Fatal(err) } } -func (r *R) log(s string) { - r.output = append(r.output, decorate(s)) -} - -// Stop retrying, and fail the test, logging the specified error. -// Does not stop execution, so return should be called after. func (r *R) Stop(err error) { r.log(err.Error()) r.done = true } -func decorate(s string) string { - _, file, line, ok := runtime.Caller(3) - if ok { - n := strings.LastIndex(file, "/") - if n >= 0 { - file = file[n+1:] - } - } else { - file = "???" - line = 1 - } - return fmt.Sprintf("%s:%d: %s", file, line, s) +func (r *R) failCurrentAttempt() { + r.getCurrentAttempt().failed = true } -func Run(t Failer, f func(r *R)) { - t.Helper() - run(DefaultFailer(), t, f) +func (r *R) log(s string) { + a := r.getCurrentAttempt() + a.output = append(a.output, decorate(s)) } -func RunWith(r Retryer, t Failer, f func(r *R)) { - t.Helper() - run(r, t, f) +func (r *R) getCurrentAttempt() *attempt { + if len(r.attempts) == 0 { + panic("no retry attempts have been started yet") + } + + return r.attempts[len(r.attempts)-1] } -func dedup(a []string) string { - if len(a) == 0 { - return "" - } - seen := map[string]struct{}{} - var b bytes.Buffer - for _, s := range a { - if _, ok := seen[s]; ok { - continue +// cleanupAttempt will perform all the register cleanup operations recorded +// during execution of the single round of the test function. +func (r *R) cleanupAttempt(a *attempt) { + // Make sure that if a cleanup function panics, + // we still run the remaining cleanup functions. + defer func() { + err := recover() + if err != nil { + r.Stop(fmt.Errorf("error when performing test cleanup: %v", err)) + } + if len(a.cleanups) > 0 { + r.cleanupAttempt(a) + } + }() + + for len(a.cleanups) > 0 { + var cleanup func() + if len(a.cleanups) > 0 { + last := len(a.cleanups) - 1 + cleanup = a.cleanups[last] + a.cleanups = a.cleanups[:last] + } + if cleanup != nil { + cleanup() } - seen[s] = struct{}{} - b.WriteString(s) - b.WriteRune('\n') } - return b.String() } -func run(r Retryer, t Failer, f func(r *R)) { - t.Helper() - rr := &R{} +// runAttempt will execute one round of the test function and handle cleanups and panic recovery +// of a failed attempt that should not stop retrying. +func (r *R) runAttempt(f func(r *R)) { + r.Helper() + + a := &attempt{} + r.attempts = append(r.attempts, a) - fail := func() { - t.Helper() - out := dedup(rr.output) - if out != "" { - t.Log(out) + defer r.cleanupAttempt(a) + defer func() { + if p := recover(); p != nil && p != (attemptFailed{}) { + panic(p) } - t.FailNow() - } + }() + f(r) +} + +func (r *R) run(f func(r *R)) { + r.Helper() - for r.Continue() { - // run f(rr), but if recover yields a runFailed value, we know - // FailNow was called. - func() { - defer rr.runCleanup() - defer func() { - if p := recover(); p != nil && p != (runFailed{}) { - panic(p) - } - }() - f(rr) - }() + for r.retryer.Continue() { + r.runAttempt(f) switch { - case rr.done: - fail() + case r.done: + r.recordRetryFailure() return - case !rr.fail: + case !r.Failed(): + // the current attempt did not fail so we can go ahead and return return } - rr.fail = false } - fail() + + // We cannot retry any more and no attempt has succeeded yet. + r.recordRetryFailure() } -// DefaultFailer provides default retry.Run() behavior for unit tests, namely -// 7s timeout with a wait of 25ms -func DefaultFailer() *Timer { - return &Timer{Timeout: 7 * time.Second, Wait: 25 * time.Millisecond} +func (r *R) recordRetryFailure() { + r.Helper() + output := r.getCurrentAttempt().output + if r.fullOutput { + var combined []string + for _, attempt := range r.attempts { + combined = append(combined, attempt.output...) + } + output = combined + } + + out := dedup(output) + if out != "" { + r.wrapped.Log(out) + } + r.wrapped.FailNow() } -// Retryer provides an interface for repeating operations -// until they succeed or an exit condition is met. -type Retryer interface { - // Continue returns true if the operation should be repeated, otherwise it - // returns false to indicate retrying should stop. - Continue() bool +type attempt struct { + failed bool + output []string + cleanups []func() } + +// attemptFailed is a sentinel value to indicate that the func itself +// didn't panic, rather that `FailNow` was called. +type attemptFailed struct{} diff --git a/sdk/testutil/retry/retry_test.go b/sdk/testutil/retry/retry_test.go index 77bc2d4d9f96..ecc8e5608232 100644 --- a/sdk/testutil/retry/retry_test.go +++ b/sdk/testutil/retry/retry_test.go @@ -62,7 +62,7 @@ func TestBasics(t *testing.T) { t.Run("Fatal returns from func, but does not fail test", func(t *testing.T) { i := 0 gotHere := false - ft := &fakeT{} + ft := &fakeT{T: t} Run(ft, func(r *R) { i++ t.Logf("i: %d; r: %#v", i, r) @@ -97,7 +97,7 @@ func TestBasics(t *testing.T) { func TestRunWith(t *testing.T) { t.Run("calls FailNow after exceeding retries", func(t *testing.T) { - ft := &fakeT{} + ft := &fakeT{T: t} iter := 0 RunWith(&Counter{Count: 3, Wait: time.Millisecond}, ft, func(r *R) { iter++ @@ -109,7 +109,7 @@ func TestRunWith(t *testing.T) { }) t.Run("Stop ends the retrying", func(t *testing.T) { - ft := &fakeT{} + ft := &fakeT{T: t} iter := 0 RunWith(&Counter{Count: 5, Wait: time.Millisecond}, ft, func(r *R) { iter++ @@ -128,38 +128,54 @@ func TestRunWith(t *testing.T) { }) } +func TestCleanup_Passthrough(t *testing.T) { + +} + func TestCleanup(t *testing.T) { + t.Run("basic", func(t *testing.T) { - ft := &fakeT{} + ft := &fakeT{T: t} cleanupsExecuted := 0 - RunWith(&Counter{Count: 2, Wait: time.Millisecond}, ft, func(r *R) { - r.Cleanup(func() { - cleanupsExecuted += 1 - }) - }) + + Run( + ft, + func(r *R) { + r.Cleanup(func() { + cleanupsExecuted += 1 + }) + }, + WithImmediateCleanup(), + WithRetryer(&Counter{Count: 2, Wait: time.Millisecond}), + ) require.Equal(t, 0, ft.fails) require.Equal(t, 1, cleanupsExecuted) }) t.Run("cleanup-panic-recovery", func(t *testing.T) { - ft := &fakeT{} + ft := &fakeT{T: t} cleanupsExecuted := 0 - RunWith(&Counter{Count: 2, Wait: time.Millisecond}, ft, func(r *R) { - r.Cleanup(func() { - cleanupsExecuted += 1 - }) + Run( + ft, + func(r *R) { + r.Cleanup(func() { + cleanupsExecuted += 1 + }) - r.Cleanup(func() { - cleanupsExecuted += 1 - panic(fmt.Errorf("fake test error")) - }) + r.Cleanup(func() { + cleanupsExecuted += 1 + panic(fmt.Errorf("fake test error")) + }) - r.Cleanup(func() { - cleanupsExecuted += 1 - }) + r.Cleanup(func() { + cleanupsExecuted += 1 + }) - // test is successful but should fail due to the cleanup panicing - }) + // test is successful but should fail due to the cleanup panicing + }, + WithRetryer(&Counter{Count: 2, Wait: time.Millisecond}), + WithImmediateCleanup(), + ) require.Equal(t, 3, cleanupsExecuted) require.Equal(t, 1, ft.fails) @@ -167,33 +183,71 @@ func TestCleanup(t *testing.T) { }) t.Run("cleanup-per-retry", func(t *testing.T) { - ft := &fakeT{} + ft := &fakeT{T: t} iter := 0 cleanupsExecuted := 0 - RunWith(&Counter{Count: 3, Wait: time.Millisecond}, ft, func(r *R) { - if cleanupsExecuted != iter { - r.Stop(fmt.Errorf("cleanups not executed between retries")) - return - } - iter += 1 + Run( + ft, + func(r *R) { + if cleanupsExecuted != iter { + r.Stop(fmt.Errorf("cleanups not executed between retries")) + return + } + iter += 1 - r.Cleanup(func() { - cleanupsExecuted += 1 - }) + r.Cleanup(func() { + cleanupsExecuted += 1 + }) - r.FailNow() - }) + r.FailNow() + }, + WithRetryer(&Counter{Count: 3, Wait: time.Millisecond}), + WithImmediateCleanup(), + ) require.Equal(t, 3, cleanupsExecuted) // ensure that r.Stop hadn't been called. If it was then we would // have log output require.Len(t, ft.out, 0) }) + + t.Run("passthrough-to-t", func(t *testing.T) { + cleanupsExecuted := 0 + + require.True(t, t.Run("internal", func(t *testing.T) { + iter := 0 + Run( + t, + func(r *R) { + iter++ + + r.Cleanup(func() { + cleanupsExecuted += 1 + }) + + // fail all but the last one to ensure the right number of cleanups + // are eventually executed + if iter < 3 { + r.FailNow() + } + }, + WithRetryer(&Counter{Count: 3, Wait: time.Millisecond}), + ) + + // at this point nothing should be cleaned up + require.Equal(t, 0, cleanupsExecuted) + })) + + // now since the subtest finished the test cleanup funcs + // should have been executed. + require.Equal(t, 3, cleanupsExecuted) + }) } type fakeT struct { fails int out []string + *testing.T } func (f *fakeT) Helper() {} @@ -206,4 +260,4 @@ func (f *fakeT) FailNow() { f.fails++ } -var _ Failer = &fakeT{} +var _ TestingTB = &fakeT{} diff --git a/sdk/testutil/retry/retryer.go b/sdk/testutil/retry/retryer.go new file mode 100644 index 000000000000..45f41988f21e --- /dev/null +++ b/sdk/testutil/retry/retryer.go @@ -0,0 +1,36 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package retry + +import "time" + +// Retryer provides an interface for repeating operations +// until they succeed or an exit condition is met. +type Retryer interface { + // Continue returns true if the operation should be repeated, otherwise it + // returns false to indicate retrying should stop. + Continue() bool +} + +// DefaultRetryer provides default retry.Run() behavior for unit tests, namely +// 7s timeout with a wait of 25ms +func DefaultRetryer() Retryer { + return &Timer{Timeout: 7 * time.Second, Wait: 25 * time.Millisecond} +} + +// ThirtySeconds repeats an operation for thirty seconds and waits 500ms in between. +// Best for known slower operations like waiting on eventually consistent state. +func ThirtySeconds() *Timer { + return &Timer{Timeout: 30 * time.Second, Wait: 500 * time.Millisecond} +} + +// TwoSeconds repeats an operation for two seconds and waits 25ms in between. +func TwoSeconds() *Timer { + return &Timer{Timeout: 2 * time.Second, Wait: 25 * time.Millisecond} +} + +// ThreeTimes repeats an operation three times and waits 25ms in between. +func ThreeTimes() *Counter { + return &Counter{Count: 3, Wait: 25 * time.Millisecond} +} diff --git a/sdk/testutil/retry/run.go b/sdk/testutil/retry/run.go new file mode 100644 index 000000000000..51dad9f4e4d3 --- /dev/null +++ b/sdk/testutil/retry/run.go @@ -0,0 +1,48 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package retry + +type Option func(r *R) + +func WithRetryer(retryer Retryer) Option { + return func(r *R) { + r.retryer = retryer + } +} + +func WithFullOutput() Option { + return func(r *R) { + r.fullOutput = true + } +} + +// WithImmediateCleanup will cause all cleanup operations added +// by calling the Cleanup method on *R to be performed after +// the retry attempt completes (regardless of pass/fail status) +// Use this only if all resources created during the retry loop should +// not persist after the retry has finished. +func WithImmediateCleanup() Option { + return func(r *R) { + r.immediateCleanup = true + } +} + +func Run(t TestingTB, f func(r *R), opts ...Option) { + t.Helper() + r := &R{ + wrapped: t, + retryer: DefaultRetryer(), + } + + for _, opt := range opts { + opt(r) + } + + r.run(f) +} + +func RunWith(r Retryer, t TestingTB, f func(r *R)) { + t.Helper() + Run(t, f, WithRetryer(r)) +} diff --git a/sdk/testutil/retry/timer.go b/sdk/testutil/retry/timer.go index be4f5e92f407..6c65d38ba0e6 100644 --- a/sdk/testutil/retry/timer.go +++ b/sdk/testutil/retry/timer.go @@ -5,22 +5,6 @@ package retry import "time" -// ThirtySeconds repeats an operation for thirty seconds and waits 500ms in between. -// Best for known slower operations like waiting on eventually consistent state. -func ThirtySeconds() *Timer { - return &Timer{Timeout: 30 * time.Second, Wait: 500 * time.Millisecond} -} - -// TwoSeconds repeats an operation for two seconds and waits 25ms in between. -func TwoSeconds() *Timer { - return &Timer{Timeout: 2 * time.Second, Wait: 25 * time.Millisecond} -} - -// ThreeTimes repeats an operation three times and waits 25ms in between. -func ThreeTimes() *Counter { - return &Counter{Count: 3, Wait: 25 * time.Millisecond} -} - // Timer repeats an operation for a given amount // of time and waits between subsequent operations. type Timer struct { diff --git a/sdk/testutil/types.go b/sdk/testutil/types.go index e5721d3c9647..33cc3002997d 100644 --- a/sdk/testutil/types.go +++ b/sdk/testutil/types.go @@ -3,14 +3,33 @@ package testutil +import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var nilInf TestingTB = nil + +// Assertion that our TestingTB can be passed to +var _ require.TestingT = nilInf +var _ assert.TestingT = nilInf + // TestingTB is an interface that describes the implementation of the testing object. // Using an interface that describes testing.TB instead of the actual implementation // makes testutil usable in a wider variety of contexts (e.g. use with ginkgo : https://godoc.org/github.com/onsi/ginkgo#GinkgoT) type TestingTB interface { Cleanup(func()) + Error(args ...any) + Errorf(format string, args ...any) + Fail() + FailNow() Failed() bool - Logf(format string, args ...interface{}) - Name() string - Fatalf(fmt string, args ...interface{}) + Fatal(args ...any) + Fatalf(format string, args ...any) Helper() + Log(args ...any) + Logf(format string, args ...any) + Name() string + Setenv(key, value string) + TempDir() string } diff --git a/solace_version.txt b/solace_version.txt new file mode 100644 index 000000000000..6b67b1eb6ce1 --- /dev/null +++ b/solace_version.txt @@ -0,0 +1 @@ +Mon Aug 28 09:42:29 EDT 2023 diff --git a/test-integ/Makefile b/test-integ/Makefile index 0fd35d4eda7e..d3d3e3871942 100644 --- a/test-integ/Makefile +++ b/test-integ/Makefile @@ -1,7 +1,7 @@ SHELL := /bin/bash .PHONY: noop -noop: +noop: help ##@ Build diff --git a/test-integ/README.md b/test-integ/README.md index ebc611efa2bc..048e377aeb54 100644 --- a/test-integ/README.md +++ b/test-integ/README.md @@ -1,3 +1,189 @@ # test-integ -Go integration tests for consul. `/test/integration` also holds integration tests; they need migrating. \ No newline at end of file +Go integration tests for consul. `/test/integration` also holds integration tests; they need migrating. + +These should use the [testing/deployer framework](../testing/deployer) to bring +up some local testing infrastructure and fixtures to run test assertions against. + +Where reasonably possible, try to bring up infrastructure interesting enough to +be able to run many related sorts of tests against it, rather than waiting for +many similar clusters to be provisioned and torn down. This will help ensure +that the integration tests do not consume CPU cycles needlessly. + +## Prerequisites + +Before you can run these tests, a fresh dev build should be created and tagged +for automatic use by tests using `utils.TargetImages()`. This can be done by +the toplevel consul make target: + + make test-deployer-setup + +You can run the entire set of deployer integration tests using: + + make test-deployer # everything except peering_commontopo + make test-deployer-peering # just peering_commontopo + +You can also run them one by one if you like: + + go test ./connect/ -run Test_Snapshot_Restore_Agentless -v + +You can have the logs stream unbuffered directly to your terminal which can +help diagnose stuck tests that would otherwise need to fully timeout before the +logs would print by also setting the `NOLOGBUFFER=1` environment variable. + +## Getting started + +Deployer tests have three main parts: + +1. Declarative topology description. +2. Launching the infrastructure defined by that description. +3. Making test assertions about the infrastructure. + +Some tests may also have an optional _mutation_ phase followed by additional +assertions. These are only needed if the test needs to observe a reaction in +the system to a change in the environment or configuration. + +### Topology description + +Test authors craft a declarative description of the infrastructure necessary to exist for the test. +These are also referred to as a "topology". + +These are comprised of 4 main parts: + +- **Images**: The set of docker images and specific versions that will be used + by default if not overridden on each Cluster or Node. + + - Consul CE + - Consul Enterprise + - Consul Dataplane + - Envoy Proxy + +- **Networks**: The non-overlapping networks that should exist for use by the Clusters. + +- **Clusters**: The unique Consul clusters that should exist. + + - **Nodes**: A "box with ip address(es)". This should feel a bit like a VM or + a Kubernetes Pod as an enclosing entity. + + - **Workloads**: The list of service instances that will execute on the given node. + + - **InitialConfigEntries**: Config entries that should be created as + part of the fixture and that make sense to + include as part of the test definition, rather + than something created during the test assertion + phase. + + - **InitialResources**: Resources that should be created as part of + the fixture and that make sense to include as part of + the test definition, rather than something created + during the test assertion phase. + +- **Peerings**: The peering relationships between Clusters to establish. + +In the [topoutil](./topoutil) package there are some helpers for defining +common sets of nodes or workloads like Consul Servers, Mesh Gateways, or [fortio +servers](https://github.com/fortio/fortio) + +#### Useful topology concepts + +Consul has a lot of independent configurables that can greatly increase the +testing configuration space required to flush out any bugs. The topology +definition was designed to be easily "exploded" to create testing microcosms on +a variety of axes: + +- agentful (clients) vs agentless (dataplane) +- tenancies (partitions, namespaces) +- locally or across a peering + +Since the topology is just a declarative struct, a test author could rewrite +any one of these attributes with a single field (such as `Node.Kind`) and cause +the identical test to run against the other configuration. With the addition of +a few `if enterprise {}` blocks and `for` loops, a test author could easily +write one test of a behavior and execute it to cover agentless, agentful, and +non-default tenancy in a few extra lines of code. + +#### Non-optional security settings + +The test framework always enables ACLs in default deny mode and provisions +minimal-permission tokens automatically to the various containers that need +them. + +TLS certificates are similarly minted and distributed to all components that +need them. + +### Launching a topology + +There is a [sprawltest](../testing/deployer/sprawl/sprawltest) package that has +utilities to bring up a topology in the context of a Go test. This is basically a one-liner: + + sp := sprawltest.Launch(t, config) + +After this line returns you will have a handle (`sp`) to the running cluster +and can use it to get ready-made api clients, http clients, gRPC resource +client, or test sockets open to a variety of the topology components for use in +authoring test code. + +This helper will rig up a `t.Cleanup` handler that will destroy all resources +created during the test. This can be opted-out of by setting the +`SPRAWL_KEEP_RUNNING=1` environment variable before running the tests. + +### Upgrade test +We are migrating upgrade tests from consul-container(`/test/integration`) to +this directory using the [testing/deployer framework](../testing/deployer). + +The current implementation supports two upgrade strategies: [standard upgrade](https://developer.hashicorp.com/consul/docs/upgrading/instructions/general-process) +and [autopilot upgrade](https://developer.hashicorp.com/consul/tutorials/datacenter-operations/upgrade-automation). The basic test scenario can be found in `./test-integ/upgrade/basic`. + + +### Test assertions + +Typical service mesh tests want to ensure that use of a service from another +service behaves in a certain way. Because the entire set of components is known +declaratively, we can process it into a flat list of known source/destination +relationships: + + ships := topology.ComputeRelationships() + +This works hand-in-hand with the topology concepts mentioned above to +programmatically verify independent subunits of a topology that may exist (this +is helpful for things like testing multiple tenancy configurations without +duplicating all of the assertion code). + +This can also be pretty printed to the log for diagnostic purposes with: + + t.Log(topology.RenderRelationships(ships)) + +Which looks like this: + + $ NOLOGBUFFER=1 go test ./catalogv2/ -run TestBasicL4ExplicitDestinations -v + ...(skipping a bunch of output)... + 2023-11-08T11:48:04.395-0600 [INFO] TestBasicL4ExplicitDestinations: topology is ready for use: elapsed=33.510298357s + explicit_destinations_test.go:55: DOWN |node |service |port |UP |service | + dc1 |default/dc1-box2 |default/default/single-client |5000 |dc1 |default/default/single-server | + dc1 |default/dc1-box4 |default/default/multi-client |5000 |dc1 |default/default/multi-server | + dc1 |default/dc1-box4 |default/default/multi-client |5001 |dc1 |default/default/multi-server | + | | | | | | + + === RUN TestBasicL4ExplicitDestinations/relationship:_default/default/single-client_on_default/dc1-box2_in_dc1_via_:5000_=>_default/default/single-server_in_dc1_port_http + service.go:224: making call to http://10.238.170.5:5000 + service.go:245: ...got response code 200 + === RUN TestBasicL4ExplicitDestinations/relationship:_default/default/multi-client_on_default/dc1-box4_in_dc1_via_:5000_=>_default/default/multi-server_in_dc1_port_http + service.go:224: making call to http://10.238.170.7:5000 + service.go:245: ...got response code 200 + === RUN TestBasicL4ExplicitDestinations/relationship:_default/default/multi-client_on_default/dc1-box4_in_dc1_via_:5001_=>_default/default/multi-server_in_dc1_port_http-alt + service.go:224: making call to http://10.238.170.7:5001 + service.go:245: ...got response code 200 + 2023-11-08T11:48:04.420-0600 [INFO] TestBasicL4ExplicitDestinations.tfgen: Running 'terraform destroy'... + --- PASS: TestBasicL4ExplicitDestinations (40.60s) + --- PASS: TestBasicL4ExplicitDestinations/relationship:_default/default/single-client_on_default/dc1-box2_in_dc1_via_:5000_=>_default/default/single-server_in_dc1_port_http (0.01s) + --- PASS: TestBasicL4ExplicitDestinations/relationship:_default/default/multi-client_on_default/dc1-box4_in_dc1_via_:5000_=>_default/default/multi-server_in_dc1_port_http (0.01s) + --- PASS: TestBasicL4ExplicitDestinations/relationship:_default/default/multi-client_on_default/dc1-box4_in_dc1_via_:5001_=>_default/default/multi-server_in_dc1_port_http-alt (0.01s) + PASS + ok github.com/hashicorp/consul/test-integ/catalogv2 40.612s + +There is a ready-made helper to assist with making common inquiries to Consul +and Envoy that you can create in your test: + + asserter := topoutil.NewAsserter(sp) + + asserter.UpstreamEndpointStatus(t, svc, clusterPrefix+".", "HEALTHY", 1) diff --git a/test-integ/catalogv2/explicit_destinations_test.go b/test-integ/catalogv2/explicit_destinations_test.go deleted file mode 100644 index 9c86e0595261..000000000000 --- a/test-integ/catalogv2/explicit_destinations_test.go +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package catalogv2 - -import ( - "fmt" - "testing" - - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" - "github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest" - "github.com/hashicorp/consul/testing/deployer/topology" - - "github.com/hashicorp/consul/test-integ/topoutil" -) - -// TestBasicL4ExplicitDestinations sets up the following: -// -// - 1 cluster (no peering / no wanfed) -// - 3 servers in that cluster -// - v2 arch is activated -// - for each tenancy, only using v2 constructs: -// - a client with one explicit destination to a single port service -// - a client with multiple explicit destinations to multiple ports of the -// same multiport service -// -// When this test is executed in CE it will only use the default/default -// tenancy. -// -// When this test is executed in Enterprise it will additionally test the same -// things within these tenancies: -// -// - part1/default -// - default/nsa -// - part1/nsa -func TestBasicL4ExplicitDestinations(t *testing.T) { - cfg := testBasicL4ExplicitDestinationsCreator{}.NewConfig(t) - - sp := sprawltest.Launch(t, cfg) - - var ( - asserter = topoutil.NewAsserter(sp) - - topo = sp.Topology() - cluster = topo.Clusters["dc1"] - - ships = topo.ComputeRelationships() - ) - - clientV2 := sp.ResourceServiceClientForCluster(cluster.Name) - - t.Log(topology.RenderRelationships(ships)) - - // Make sure things are in v2. - for _, name := range []string{ - "single-server", - "single-client", - "multi-server", - "multi-client", - } { - libassert.CatalogV2ServiceHasEndpointCount(t, clientV2, name, nil, 1) - } - - // Check relationships - for _, ship := range ships { - t.Run("relationship: "+ship.String(), func(t *testing.T) { - var ( - svc = ship.Caller - u = ship.Upstream - ) - - clusterPrefix := clusterPrefixForUpstream(u) - - asserter.UpstreamEndpointStatus(t, svc, clusterPrefix+".", "HEALTHY", 1) - asserter.HTTPServiceEchoes(t, svc, u.LocalPort, "") - asserter.FortioFetch2FortioName(t, svc, u, cluster.Name, u.ID) - }) - } -} - -type testBasicL4ExplicitDestinationsCreator struct{} - -func (c testBasicL4ExplicitDestinationsCreator) NewConfig(t *testing.T) *topology.Config { - const clusterName = "dc1" - - servers := topoutil.NewTopologyServerSet(clusterName+"-server", 3, []string{clusterName, "wan"}, nil) - - cluster := &topology.Cluster{ - Enterprise: utils.IsEnterprise(), - Name: clusterName, - Nodes: servers, - } - - lastNode := 0 - nodeName := func() string { - lastNode++ - return fmt.Sprintf("%s-box%d", clusterName, lastNode) - } - - c.topologyConfigAddNodes(t, cluster, nodeName, "default", "default") - if cluster.Enterprise { - c.topologyConfigAddNodes(t, cluster, nodeName, "part1", "default") - c.topologyConfigAddNodes(t, cluster, nodeName, "part1", "nsa") - c.topologyConfigAddNodes(t, cluster, nodeName, "default", "nsa") - } - - return &topology.Config{ - Images: topoutil.TargetImages(), - Networks: []*topology.Network{ - {Name: clusterName}, - {Name: "wan", Type: "wan"}, - }, - Clusters: []*topology.Cluster{ - cluster, - }, - } -} - -func (c testBasicL4ExplicitDestinationsCreator) topologyConfigAddNodes( - t *testing.T, - cluster *topology.Cluster, - nodeName func() string, - partition, - namespace string, -) { - clusterName := cluster.Name - - newServiceID := func(name string) topology.ServiceID { - return topology.ServiceID{ - Partition: partition, - Namespace: namespace, - Name: name, - } - } - - tenancy := &pbresource.Tenancy{ - Partition: partition, - Namespace: namespace, - PeerName: "local", - } - - singleportServerNode := &topology.Node{ - Kind: topology.NodeKindDataplane, - Version: topology.NodeVersionV2, - Partition: partition, - Name: nodeName(), - Services: []*topology.Service{ - topoutil.NewFortioServiceWithDefaults( - clusterName, - newServiceID("single-server"), - topology.NodeVersionV2, - nil, - ), - }, - } - singleportClientNode := &topology.Node{ - Kind: topology.NodeKindDataplane, - Version: topology.NodeVersionV2, - Partition: partition, - Name: nodeName(), - Services: []*topology.Service{ - topoutil.NewFortioServiceWithDefaults( - clusterName, - newServiceID("single-client"), - topology.NodeVersionV2, - func(svc *topology.Service) { - delete(svc.Ports, "grpc") // v2 mode turns this on, so turn it off - delete(svc.Ports, "http-alt") // v2 mode turns this on, so turn it off - svc.Upstreams = []*topology.Upstream{{ - ID: newServiceID("single-server"), - PortName: "http", - LocalAddress: "0.0.0.0", // needed for an assertion - LocalPort: 5000, - }} - }, - ), - }, - } - singleportTrafficPerms := sprawltest.MustSetResourceData(t, &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbauth.TrafficPermissionsType, - Name: "single-server-perms", - Tenancy: tenancy, - }, - }, &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "single-server", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{{ - Sources: []*pbauth.Source{{ - IdentityName: "single-client", - Namespace: namespace, - }}, - }}, - }) - - multiportServerNode := &topology.Node{ - Kind: topology.NodeKindDataplane, - Version: topology.NodeVersionV2, - Partition: partition, - Name: nodeName(), - Services: []*topology.Service{ - topoutil.NewFortioServiceWithDefaults( - clusterName, - newServiceID("multi-server"), - topology.NodeVersionV2, - nil, - ), - }, - } - multiportClientNode := &topology.Node{ - Kind: topology.NodeKindDataplane, - Version: topology.NodeVersionV2, - Partition: partition, - Name: nodeName(), - Services: []*topology.Service{ - topoutil.NewFortioServiceWithDefaults( - clusterName, - newServiceID("multi-client"), - topology.NodeVersionV2, - func(svc *topology.Service) { - svc.Upstreams = []*topology.Upstream{ - { - ID: newServiceID("multi-server"), - PortName: "http", - LocalAddress: "0.0.0.0", // needed for an assertion - LocalPort: 5000, - }, - { - ID: newServiceID("multi-server"), - PortName: "http-alt", - LocalAddress: "0.0.0.0", // needed for an assertion - LocalPort: 5001, - }, - } - }, - ), - }, - } - multiportTrafficPerms := sprawltest.MustSetResourceData(t, &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbauth.TrafficPermissionsType, - Name: "multi-server-perms", - Tenancy: tenancy, - }, - }, &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "multi-server", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{{ - Sources: []*pbauth.Source{{ - IdentityName: "multi-client", - Namespace: namespace, - }}, - }}, - }) - - cluster.Nodes = append(cluster.Nodes, - singleportClientNode, - singleportServerNode, - multiportClientNode, - multiportServerNode, - ) - - cluster.InitialResources = append(cluster.InitialResources, - singleportTrafficPerms, - multiportTrafficPerms, - ) -} diff --git a/test-integ/catalogv2/helpers_test.go b/test-integ/catalogv2/helpers_test.go deleted file mode 100644 index f5e352779a29..000000000000 --- a/test-integ/catalogv2/helpers_test.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package catalogv2 - -import ( - "strings" - - "github.com/hashicorp/consul/testing/deployer/topology" -) - -func clusterPrefixForUpstream(u *topology.Upstream) string { - if u.Peer == "" { - if u.ID.PartitionOrDefault() == "default" { - return strings.Join([]string{u.PortName, u.ID.Name, u.ID.Namespace, u.Cluster, "internal"}, ".") - } else { - return strings.Join([]string{u.PortName, u.ID.Name, u.ID.Namespace, u.ID.Partition, u.Cluster, "internal-v1"}, ".") - } - } else { - return strings.Join([]string{u.ID.Name, u.ID.Namespace, u.Peer, "external"}, ".") - } -} diff --git a/test-integ/catalogv2/implicit_destinations_test.go b/test-integ/catalogv2/implicit_destinations_test.go deleted file mode 100644 index daf19945a9e3..000000000000 --- a/test-integ/catalogv2/implicit_destinations_test.go +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package catalogv2 - -import ( - "fmt" - "testing" - - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" - "github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest" - "github.com/hashicorp/consul/testing/deployer/topology" - - "github.com/hashicorp/consul/test-integ/topoutil" -) - -// TestBasicL4ImplicitDestinations sets up the following: -// -// - 1 cluster (no peering / no wanfed) -// - 3 servers in that cluster -// - v2 arch is activated -// - for each tenancy, only using v2 constructs: -// - a server exposing 2 tcp ports -// - a client with transparent proxy enabled and no explicit upstreams -// - a traffic permission granting the client access to the service on all ports -// -// When this test is executed in CE it will only use the default/default -// tenancy. -// -// When this test is executed in Enterprise it will additionally test the same -// things within these tenancies: -// -// - part1/default -// - default/nsa -// - part1/nsa -func TestBasicL4ImplicitDestinations(t *testing.T) { - cfg := testBasicL4ImplicitDestinationsCreator{}.NewConfig(t) - - sp := sprawltest.Launch(t, cfg) - - var ( - asserter = topoutil.NewAsserter(sp) - - topo = sp.Topology() - cluster = topo.Clusters["dc1"] - - ships = topo.ComputeRelationships() - ) - - clientV2 := sp.ResourceServiceClientForCluster(cluster.Name) - - t.Log(topology.RenderRelationships(ships)) - - // Make sure things are truly in v2 not v1. - for _, name := range []string{ - "static-server", - "static-client", - } { - libassert.CatalogV2ServiceHasEndpointCount(t, clientV2, name, nil, 1) - } - - // Check relationships - for _, ship := range ships { - t.Run("relationship: "+ship.String(), func(t *testing.T) { - var ( - svc = ship.Caller - u = ship.Upstream - ) - - clusterPrefix := clusterPrefixForUpstream(u) - - asserter.UpstreamEndpointStatus(t, svc, clusterPrefix+".", "HEALTHY", 1) - if u.LocalPort > 0 { - asserter.HTTPServiceEchoes(t, svc, u.LocalPort, "") - } - asserter.FortioFetch2FortioName(t, svc, u, cluster.Name, u.ID) - }) - } -} - -type testBasicL4ImplicitDestinationsCreator struct{} - -func (c testBasicL4ImplicitDestinationsCreator) NewConfig(t *testing.T) *topology.Config { - const clusterName = "dc1" - - servers := topoutil.NewTopologyServerSet(clusterName+"-server", 3, []string{clusterName, "wan"}, nil) - - cluster := &topology.Cluster{ - Enterprise: utils.IsEnterprise(), - Name: clusterName, - Nodes: servers, - } - - lastNode := 0 - nodeName := func() string { - lastNode++ - return fmt.Sprintf("%s-box%d", clusterName, lastNode) - } - - c.topologyConfigAddNodes(t, cluster, nodeName, "default", "default") - if cluster.Enterprise { - c.topologyConfigAddNodes(t, cluster, nodeName, "part1", "default") - c.topologyConfigAddNodes(t, cluster, nodeName, "part1", "nsa") - c.topologyConfigAddNodes(t, cluster, nodeName, "default", "nsa") - } - - return &topology.Config{ - Images: topoutil.TargetImages(), - Networks: []*topology.Network{ - {Name: clusterName}, - {Name: "wan", Type: "wan"}, - }, - Clusters: []*topology.Cluster{ - cluster, - }, - } -} - -func (c testBasicL4ImplicitDestinationsCreator) topologyConfigAddNodes( - t *testing.T, - cluster *topology.Cluster, - nodeName func() string, - partition, - namespace string, -) { - clusterName := cluster.Name - - newServiceID := func(name string) topology.ServiceID { - return topology.ServiceID{ - Partition: partition, - Namespace: namespace, - Name: name, - } - } - - tenancy := &pbresource.Tenancy{ - Partition: partition, - Namespace: namespace, - PeerName: "local", - } - - serverNode := &topology.Node{ - Kind: topology.NodeKindDataplane, - Version: topology.NodeVersionV2, - Partition: partition, - Name: nodeName(), - Services: []*topology.Service{ - topoutil.NewFortioServiceWithDefaults( - clusterName, - newServiceID("static-server"), - topology.NodeVersionV2, - func(svc *topology.Service) { - svc.EnableTransparentProxy = true - }, - ), - }, - } - clientNode := &topology.Node{ - Kind: topology.NodeKindDataplane, - Version: topology.NodeVersionV2, - Partition: partition, - Name: nodeName(), - Services: []*topology.Service{ - topoutil.NewFortioServiceWithDefaults( - clusterName, - newServiceID("static-client"), - topology.NodeVersionV2, - func(svc *topology.Service) { - svc.EnableTransparentProxy = true - svc.ImpliedUpstreams = []*topology.Upstream{ - { - ID: newServiceID("static-server"), - PortName: "http", - }, - { - ID: newServiceID("static-server"), - PortName: "http-alt", - }, - } - }, - ), - }, - } - trafficPerms := sprawltest.MustSetResourceData(t, &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbauth.TrafficPermissionsType, - Name: "static-server-perms", - Tenancy: tenancy, - }, - }, &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "static-server", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{{ - Sources: []*pbauth.Source{{ - IdentityName: "static-client", - Namespace: namespace, - }}, - }}, - }) - - cluster.Nodes = append(cluster.Nodes, - clientNode, - serverNode, - ) - - cluster.InitialResources = append(cluster.InitialResources, - trafficPerms, - ) -} diff --git a/test-integ/connect/snapshot_test.go b/test-integ/connect/snapshot_test.go index 469562a16074..423fa2534026 100644 --- a/test-integ/connect/snapshot_test.go +++ b/test-integ/connect/snapshot_test.go @@ -4,24 +4,19 @@ package connect import ( - "fmt" - "io" - "net/http" - "net/url" "testing" - "time" "github.com/stretchr/testify/require" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil/retry" + "github.com/hashicorp/consul/test-integ/topoutil" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" "github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest" "github.com/hashicorp/consul/testing/deployer/topology" ) // Test_Snapshot_Restore_Agentless verifies consul agent can continue -// to push envoy confgi after restoring from a snapshot. +// to push envoy config after restoring from a snapshot. // // - This test is to detect server agent frozen after restoring from a snapshot // (https://github.com/hashicorp/consul/pull/18636) @@ -37,8 +32,8 @@ import ( func Test_Snapshot_Restore_Agentless(t *testing.T) { t.Parallel() - staticServerSID := topology.NewServiceID("static-server", "default", "default") - staticClientSID := topology.NewServiceID("static-client", "default", "default") + staticServerSID := topology.NewID("static-server", "default", "default") + staticClientSID := topology.NewID("static-client", "default", "default") clu := &topology.Config{ Images: utils.TargetImages(), @@ -60,10 +55,11 @@ func Test_Snapshot_Restore_Agentless(t *testing.T) { {Network: "dc1"}, }, }, + // Static-server { Kind: topology.NodeKindDataplane, Name: "dc1-client1", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { ID: staticServerSID, Image: "docker.mirror.hashicorp.services/fortio/fortio", @@ -81,7 +77,7 @@ func Test_Snapshot_Restore_Agentless(t *testing.T) { { Kind: topology.NodeKindDataplane, Name: "dc1-client2", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { ID: staticClientSID, Image: "docker.mirror.hashicorp.services/fortio/fortio", @@ -107,7 +103,7 @@ func Test_Snapshot_Restore_Agentless(t *testing.T) { Kind: topology.NodeKindDataplane, Name: "dc1-client3", Disabled: true, - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { ID: staticServerSID, Image: "docker.mirror.hashicorp.services/fortio/fortio", @@ -151,47 +147,24 @@ func Test_Snapshot_Restore_Agentless(t *testing.T) { }, } sp := sprawltest.Launch(t, clu) + asserter := topoutil.NewAsserter(sp) - client, err := sp.HTTPClientForCluster("dc1") - require.NoError(t, err) - - staticClient := sp.Topology().Clusters["dc1"].ServiceByID( + staticClient := sp.Topology().Clusters["dc1"].WorkloadByID( topology.NewNodeID("dc1-client2", "default"), staticClientSID, ) - staticClientAddress := fmt.Sprintf("%s:%d", staticClient.Node.LocalAddress(), staticClient.Port) - - // The following url causes the static-client's fortio server to - // fetch the ?url= param (the upstream static-server in our case). - url := fmt.Sprintf("http://%s/fortio/fetch2?url=%s", staticClientAddress, - url.QueryEscape("http://localhost:5000"), + asserter.FortioFetch2HeaderEcho(t, staticClient, &topology.Upstream{ + ID: staticServerSID, + LocalPort: 5000, + }) + staticServer := sp.Topology().Clusters["dc1"].WorkloadByID( + topology.NewNodeID("dc1-client1", "default"), + staticServerSID, ) - - // We retry the first request until we get 200 OK since it may take a while - // for the server to be available. - // Use a custom retry.Timer since the default one usually times out too early. - retrySendRequest := func(isSuccess bool) { - t.Log("static-client sending requests to static-server...") - retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - resp, err := client.Post(url, "text/plain", nil) - require.NoError(r, err) - defer resp.Body.Close() - - if isSuccess { - require.Equal(r, http.StatusOK, resp.StatusCode) - } else { - require.NotEqual(r, http.StatusOK, resp.StatusCode) - } - body, err := io.ReadAll(resp.Body) - require.NoError(r, err) - fmt.Println("Body: ", string(body), resp.StatusCode) - }) - } - retrySendRequest(true) - t.Log("...ok, got 200 responses") + asserter.HTTPStatus(t, staticServer, staticServer.Port, 200) t.Log("Take a snapshot of the cluster and restore ...") - err = sp.SnapshotSave("dc1") + err := sp.SnapshotSaveAndRestore("dc1") require.NoError(t, err) // Shutdown existing static-server @@ -199,14 +172,18 @@ func Test_Snapshot_Restore_Agentless(t *testing.T) { cluster := cfg.Cluster("dc1") cluster.Nodes[1].Disabled = true // client 1 -- static-server require.NoError(t, sp.Relaunch(cfg)) - retrySendRequest(false) + // verify static-server is down + asserter.HTTPStatus(t, staticServer, staticServer.Port, 504) // Add a new static-server cfg = sp.Config() cluster = cfg.Cluster("dc1") - cluster.Nodes[3].Disabled = false // client 3 -- static-server + cluster.Nodes[3].Disabled = false // client 3 -- new static-server require.NoError(t, sp.Relaunch(cfg)) - // Ensure the static-client connected to static-server - retrySendRequest(true) + // Ensure the static-client connected to the new static-server + asserter.FortioFetch2HeaderEcho(t, staticClient, &topology.Upstream{ + ID: staticServerSID, + LocalPort: 5000, + }) } diff --git a/test-integ/go.mod b/test-integ/go.mod index 44dc740f756b..7a91a5a20e5c 100644 --- a/test-integ/go.mod +++ b/test-integ/go.mod @@ -1,17 +1,23 @@ module github.com/hashicorp/consul/test-integ -go 1.20 +go 1.22 + +toolchain go1.22.5 require ( - github.com/hashicorp/consul/api v1.26.1 - github.com/hashicorp/consul/proto-public v0.5.1 - github.com/hashicorp/consul/sdk v0.15.0 + github.com/google/go-cmp v0.5.9 + github.com/hashicorp/consul/api v1.29.4 + github.com/hashicorp/consul/proto-public v0.6.2 + github.com/hashicorp/consul/sdk v0.16.1 github.com/hashicorp/consul/test/integration/consul-container v0.0.0-20230628201853-bdf4fad7c5a5 github.com/hashicorp/consul/testing/deployer v0.0.0-20230811171106-4a0afb5d1373 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/itchyny/gojq v0.12.13 github.com/mitchellh/copystructure v1.2.0 + github.com/rboyer/blankspace v0.2.1 github.com/stretchr/testify v1.8.4 + golang.org/x/net v0.24.0 + google.golang.org/grpc v1.58.3 ) require ( @@ -38,18 +44,17 @@ require ( github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect - github.com/fatih/color v1.14.1 // indirect - github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/go-jose/go-jose/v3 v3.0.3 // indirect github.com/go-test/deep v1.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.0.1 // indirect - github.com/google/go-cmp v0.5.9 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/hashicorp/consul v1.16.1 // indirect github.com/hashicorp/consul-server-connection-manager v0.1.4 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-msgpack v1.1.5 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -67,7 +72,7 @@ require ( github.com/klauspost/compress v1.16.7 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/miekg/dns v1.1.50 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -85,7 +90,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.14.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/rboyer/safeio v0.2.3 // indirect @@ -94,16 +99,14 @@ require ( github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 // indirect github.com/testcontainers/testcontainers-go v0.22.0 // indirect github.com/zclconf/go-cty v1.12.1 // indirect - golang.org/x/crypto v0.14.0 // indirect + golang.org/x/crypto v0.22.0 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect - google.golang.org/grpc v1.57.2 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/test-integ/go.sum b/test-integ/go.sum index d5338549f7d7..a7b09dfb8318 100644 --- a/test-integ/go.sum +++ b/test-integ/go.sum @@ -1,6 +1,7 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= fortio.org/assert v1.1.4 h1:Za1RaG+OjsTMpQS3J3UCvTF6wc4+IOHCz+jAOU37Y4o= +fortio.org/assert v1.1.4/go.mod h1:039mG+/iYDPO8Ibx8TrNuJCm2T2SuhwRI3uL9nHTTls= fortio.org/dflag v1.5.2 h1:F9XVRj4Qr2IbJP7BMj7XZc9wB0Q/RZ61Ool+4YPVad8= fortio.org/dflag v1.5.2/go.mod h1:ppb/A8u+KKg+qUUYZNYuvRnXuVb8IsdHb/XGzsmjkN8= fortio.org/fortio v1.54.0 h1:2jn8yTd6hcIEoKY4CjI0lI6XxTWVxsMYF2bMiWOmv+Y= @@ -12,12 +13,14 @@ fortio.org/sets v1.0.2/go.mod h1:xVjulHr0FhlmReSymI+AhDtQ4FgjiazQ3JmuNpYFMs8= fortio.org/version v1.0.2 h1:8NwxdX58aoeKx7T5xAPO0xlUu1Hpk42nRz5s6e6eKZ0= fortio.org/version v1.0.2/go.mod h1:2JQp9Ax+tm6QKiGuzR5nJY63kFeANcgrZ0osoQFDVm0= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= +github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -51,7 +54,9 @@ github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+ github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -69,10 +74,10 @@ github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQL github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= -github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= -github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= +github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -86,21 +91,18 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/consul-server-connection-manager v0.1.4 h1:wrcSRV6WGXFBNpNbN6XsdoGgBOyso7ZbN5VaWPEX1jY= github.com/hashicorp/consul-server-connection-manager v0.1.4/go.mod h1:LMqHkALoLP0HUQKOG21xXYr0YPUayIQIHNTlmxG100E= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -109,8 +111,8 @@ github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -164,10 +166,13 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -183,8 +188,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -228,6 +233,7 @@ github.com/opencontainers/runc v1.1.8/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh github.com/otiai10/copy v1.10.0 h1:znyI7l134wNg/wDktoVQPxPkgvhDfGCYUasey+h0rDQ= github.com/otiai10/copy v1.10.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= +github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -248,8 +254,8 @@ github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQg github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= @@ -259,14 +265,18 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/rboyer/blankspace v0.2.1 h1:GzFPETXKOhuwS/jPRUTFIYo9I+RhafEIhnbPByg8S+c= +github.com/rboyer/blankspace v0.2.1/go.mod h1:GhnCkDlx1SYD6m4XCde73ncQ8pFTLSJvlCNmCMg2moQ= github.com/rboyer/safeio v0.2.3 h1:gUybicx1kp8nuM4vO0GA5xTBX58/OBd8MQuErBfDxP8= github.com/rboyer/safeio v0.2.3/go.mod h1:d7RMmt7utQBJZ4B7f0H/cU/EdZibQAU1Y8NWepK2dS8= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= @@ -274,10 +284,10 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= @@ -290,21 +300,25 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY= github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -319,15 +333,21 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -347,24 +367,38 @@ golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -372,6 +406,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -380,16 +416,15 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 h1:eSaPbMR4T7WfH9FvABk36NBMacoTUKdWCvV0dx+KfOg= google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= -google.golang.org/grpc v1.57.2 h1:uw37EN34aMFFXB2QPW7Tq6tdTbind1GpRxw5aOX3a5k= -google.golang.org/grpc v1.57.2/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -398,3 +433,4 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= +gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/test-integ/peering_commontopo/README.md b/test-integ/peering_commontopo/README.md index 96466bb29b86..16044512709c 100644 --- a/test-integ/peering_commontopo/README.md +++ b/test-integ/peering_commontopo/README.md @@ -5,7 +5,7 @@ These peering tests all use a `commonTopo` (read: "common topology") to enable s To run these tests, you will need to have docker installed. Next, make sure that you have all the required consul containers built: ``` -make test-compat-integ-setup +make test-deployer-setup ``` ## Non-Shared CommonTopo Tests diff --git a/test-integ/peering_commontopo/ac1_basic_test.go b/test-integ/peering_commontopo/ac1_basic_test.go index ae729732e745..c09bd3d53772 100644 --- a/test-integ/peering_commontopo/ac1_basic_test.go +++ b/test-integ/peering_commontopo/ac1_basic_test.go @@ -7,9 +7,8 @@ import ( "fmt" "testing" - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/testing/deployer/topology" ) type ac1BasicSuite struct { @@ -18,17 +17,17 @@ type ac1BasicSuite struct { Peer string // test points - sidServerHTTP topology.ServiceID - sidServerTCP topology.ServiceID + sidServerHTTP topology.ID + sidServerTCP topology.ID nodeServerHTTP topology.NodeID nodeServerTCP topology.NodeID // 1.1 - sidClientTCP topology.ServiceID + sidClientTCP topology.ID nodeClientTCP topology.NodeID // 1.2 - sidClientHTTP topology.ServiceID + sidClientHTTP topology.ID nodeClientHTTP topology.NodeID upstreamHTTP *topology.Upstream @@ -58,16 +57,16 @@ func (s *ac1BasicSuite) setup(t *testing.T, ct *commonTopo) { cluPeerName := LocalPeerName(clu, "default") const prefix = "ac1-" - tcpServerSID := topology.ServiceID{ + tcpServerSID := topology.ID{ Name: prefix + "server-tcp", Partition: partition, } - httpServerSID := topology.ServiceID{ + httpServerSID := topology.ID{ Name: prefix + "server-http", Partition: partition, } upstreamHTTP := &topology.Upstream{ - ID: topology.ServiceID{ + ID: topology.ID{ Name: httpServerSID.Name, Partition: partition, }, @@ -75,7 +74,7 @@ func (s *ac1BasicSuite) setup(t *testing.T, ct *commonTopo) { Peer: peer, } upstreamTCP := &topology.Upstream{ - ID: topology.ServiceID{ + ID: topology.ID{ Name: tcpServerSID.Name, Partition: partition, }, @@ -85,15 +84,15 @@ func (s *ac1BasicSuite) setup(t *testing.T, ct *commonTopo) { // Make clients which have server upstreams setupClientServiceAndConfigs := func(protocol string) (serviceExt, *topology.Node) { - sid := topology.ServiceID{ + sid := topology.ID{ Name: prefix + "client-" + protocol, Partition: partition, } svc := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( clu.Datacenter, sid, - func(s *topology.Service) { + func(s *topology.Workload) { s.Upstreams = []*topology.Upstream{ upstreamTCP, upstreamHTTP, @@ -123,7 +122,7 @@ func (s *ac1BasicSuite) setup(t *testing.T, ct *commonTopo) { httpClient, httpClientNode := setupClientServiceAndConfigs("http") httpServer := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( peerClu.Datacenter, httpServerSID, nil, @@ -154,7 +153,7 @@ func (s *ac1BasicSuite) setup(t *testing.T, ct *commonTopo) { }, } tcpServer := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( peerClu.Datacenter, tcpServerSID, nil, @@ -209,20 +208,20 @@ func (s *ac1BasicSuite) test(t *testing.T, ct *commonTopo) { ac := s // refresh this from Topology - svcClientTCP := dc.ServiceByID( + svcClientTCP := dc.WorkloadByID( ac.nodeClientTCP, ac.sidClientTCP, ) - svcClientHTTP := dc.ServiceByID( + svcClientHTTP := dc.WorkloadByID( ac.nodeClientHTTP, ac.sidClientHTTP, ) // our ac has the node/sid for server in the peer DC - svcServerHTTP := peer.ServiceByID( + svcServerHTTP := peer.WorkloadByID( ac.nodeServerHTTP, ac.sidServerHTTP, ) - svcServerTCP := peer.ServiceByID( + svcServerTCP := peer.WorkloadByID( ac.nodeServerTCP, ac.sidServerTCP, ) @@ -236,7 +235,7 @@ func (s *ac1BasicSuite) test(t *testing.T, ct *commonTopo) { tcs := []struct { acSub int proto string - svc *topology.Service + svc *topology.Workload }{ {1, "tcp", svcClientTCP}, {2, "http", svcClientHTTP}, diff --git a/test-integ/peering_commontopo/ac2_disco_chain_test.go b/test-integ/peering_commontopo/ac2_disco_chain_test.go index 448ab2840bfe..0c0f05ae458f 100644 --- a/test-integ/peering_commontopo/ac2_disco_chain_test.go +++ b/test-integ/peering_commontopo/ac2_disco_chain_test.go @@ -7,17 +7,17 @@ import ( "fmt" "testing" - "github.com/hashicorp/consul/testing/deployer/topology" "github.com/stretchr/testify/require" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/testing/deployer/topology" ) type ac2DiscoChainSuite struct { DC string Peer string - clientSID topology.ServiceID + clientSID topology.ID } var ac2DiscoChainSuites []sharedTopoSuite = []sharedTopoSuite{ @@ -42,7 +42,7 @@ func (s *ac2DiscoChainSuite) setup(t *testing.T, ct *commonTopo) { // Make an HTTP server with discovery chain config entries server := NewFortioServiceWithDefaults( clu.Datacenter, - topology.ServiceID{ + topology.ID{ Name: "ac2-disco-chain-svc", Partition: partition, }, @@ -82,11 +82,11 @@ func (s *ac2DiscoChainSuite) setup(t *testing.T, ct *commonTopo) { }, }, ) - ct.AddServiceNode(clu, serviceExt{Service: server}) + ct.AddServiceNode(clu, serviceExt{Workload: server}) // Define server as upstream for client upstream := &topology.Upstream{ - ID: topology.ServiceID{ + ID: topology.ID{ Name: server.ID.Name, Partition: partition, // TODO: iterate over all possible partitions }, @@ -98,14 +98,14 @@ func (s *ac2DiscoChainSuite) setup(t *testing.T, ct *commonTopo) { } // Make client which will dial server - clientSID := topology.ServiceID{ + clientSID := topology.ID{ Name: "ac2-client", Partition: partition, } client := NewFortioServiceWithDefaults( clu.Datacenter, clientSID, - func(s *topology.Service) { + func(s *topology.Workload) { s.Upstreams = []*topology.Upstream{ upstream, } @@ -121,7 +121,7 @@ func (s *ac2DiscoChainSuite) setup(t *testing.T, ct *commonTopo) { }, }, ) - ct.AddServiceNode(clu, serviceExt{Service: client}) + ct.AddServiceNode(clu, serviceExt{Workload: client}) clu.InitialConfigEntries = append(clu.InitialConfigEntries, &api.ServiceConfigEntry{ @@ -161,7 +161,7 @@ func (s *ac2DiscoChainSuite) setup(t *testing.T, ct *commonTopo) { func (s *ac2DiscoChainSuite) test(t *testing.T, ct *commonTopo) { dc := ct.Sprawl.Topology().Clusters[s.DC] - svcs := dc.ServicesByID(s.clientSID) + svcs := dc.WorkloadsByID(s.clientSID) require.Len(t, svcs, 1, "expected exactly one client in datacenter") client := svcs[0] diff --git a/test-integ/peering_commontopo/ac3_service_defaults_upstream_test.go b/test-integ/peering_commontopo/ac3_service_defaults_upstream_test.go index 770e0ff90cc8..30b4b1948053 100644 --- a/test-integ/peering_commontopo/ac3_service_defaults_upstream_test.go +++ b/test-integ/peering_commontopo/ac3_service_defaults_upstream_test.go @@ -11,13 +11,15 @@ import ( "testing" "time" + "github.com/itchyny/gojq" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil/retry" libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/go-cleanhttp" - "github.com/itchyny/gojq" - "github.com/stretchr/testify/require" ) var ac3SvcDefaultsSuites []sharedTopoSuite = []sharedTopoSuite{ @@ -35,9 +37,9 @@ type ac3SvcDefaultsSuite struct { Peer string // test points - sidServer topology.ServiceID + sidServer topology.ID nodeServer topology.NodeID - sidClient topology.ServiceID + sidClient topology.ID nodeClient topology.NodeID upstream *topology.Upstream @@ -56,12 +58,12 @@ func (s *ac3SvcDefaultsSuite) setup(t *testing.T, ct *commonTopo) { peer := LocalPeerName(peerClu, "default") cluPeerName := LocalPeerName(clu, "default") - serverSID := topology.ServiceID{ + serverSID := topology.ID{ Name: "ac3-server", Partition: partition, } upstream := &topology.Upstream{ - ID: topology.ServiceID{ + ID: topology.ID{ Name: serverSID.Name, Partition: partition, }, @@ -69,15 +71,15 @@ func (s *ac3SvcDefaultsSuite) setup(t *testing.T, ct *commonTopo) { Peer: peer, } - sid := topology.ServiceID{ + sid := topology.ID{ Name: "ac3-client", Partition: partition, } client := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( clu.Datacenter, sid, - func(s *topology.Service) { + func(s *topology.Workload) { s.Upstreams = []*topology.Upstream{ upstream, } @@ -112,7 +114,7 @@ func (s *ac3SvcDefaultsSuite) setup(t *testing.T, ct *commonTopo) { clientNode := ct.AddServiceNode(clu, client) server := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( peerClu.Datacenter, serverSID, nil, @@ -158,12 +160,12 @@ func (s *ac3SvcDefaultsSuite) test(t *testing.T, ct *commonTopo) { peer := ct.Sprawl.Topology().Clusters[s.Peer] // refresh this from Topology - svcClient := dc.ServiceByID( + svcClient := dc.WorkloadByID( s.nodeClient, s.sidClient, ) // our ac has the node/sid for server in the peer DC - svcServer := peer.ServiceByID( + svcServer := peer.WorkloadByID( s.nodeServer, s.sidServer, ) @@ -183,7 +185,7 @@ func (s *ac3SvcDefaultsSuite) test(t *testing.T, ct *commonTopo) { // TODO: what is default? namespace? partition? clusterName := fmt.Sprintf("%s.default.%s.external", s.upstream.ID.Name, s.upstream.Peer) nonceStatus := http.StatusInsufficientStorage - url507 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", svcClient.ExposedPort(""), + url507 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", svcClient.ExposedPort(), url.QueryEscape(fmt.Sprintf("http://localhost:%d/?status=%d", s.upstream.LocalPort, nonceStatus)), ) @@ -219,7 +221,7 @@ func (s *ac3SvcDefaultsSuite) test(t *testing.T, ct *commonTopo) { require.True(r, resultAsBool) }) - url200 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", svcClient.ExposedPort(""), + url200 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", svcClient.ExposedPort(), url.QueryEscape(fmt.Sprintf("http://localhost:%d/", s.upstream.LocalPort)), ) retry.RunWith(&retry.Timer{Timeout: time.Minute * 1, Wait: time.Millisecond * 500}, t, func(r *retry.R) { diff --git a/test-integ/peering_commontopo/ac4_proxy_defaults_test.go b/test-integ/peering_commontopo/ac4_proxy_defaults_test.go index 28df1c3d4c67..c27057a07a4e 100644 --- a/test-integ/peering_commontopo/ac4_proxy_defaults_test.go +++ b/test-integ/peering_commontopo/ac4_proxy_defaults_test.go @@ -9,10 +9,12 @@ import ( "net/url" "testing" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/go-cleanhttp" - "github.com/stretchr/testify/require" ) type ac4ProxyDefaultsSuite struct { @@ -22,8 +24,8 @@ type ac4ProxyDefaultsSuite struct { nodeClient topology.NodeID nodeServer topology.NodeID - serverSID topology.ServiceID - clientSID topology.ServiceID + serverSID topology.ID + clientSID topology.ID upstream *topology.Upstream } @@ -49,7 +51,7 @@ func (s *ac4ProxyDefaultsSuite) setup(t *testing.T, ct *commonTopo) { peer := LocalPeerName(peerClu, "default") cluPeerName := LocalPeerName(clu, "default") - serverSID := topology.ServiceID{ + serverSID := topology.ID{ Name: "ac4-server-http", Partition: partition, } @@ -61,15 +63,15 @@ func (s *ac4ProxyDefaultsSuite) setup(t *testing.T, ct *commonTopo) { } // Make client which will dial server - clientSID := topology.ServiceID{ + clientSID := topology.ID{ Name: "ac4-http-client", Partition: partition, } client := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( clu.Datacenter, clientSID, - func(s *topology.Service) { + func(s *topology.Workload) { s.Upstreams = []*topology.Upstream{ upstream, } @@ -92,7 +94,7 @@ func (s *ac4ProxyDefaultsSuite) setup(t *testing.T, ct *commonTopo) { clientNode := ct.AddServiceNode(clu, client) server := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( peerClu.Datacenter, serverSID, nil, @@ -143,16 +145,16 @@ func (s *ac4ProxyDefaultsSuite) setup(t *testing.T, ct *commonTopo) { } func (s *ac4ProxyDefaultsSuite) test(t *testing.T, ct *commonTopo) { - var client *topology.Service + var client *topology.Workload dc := ct.Sprawl.Topology().Clusters[s.DC] peer := ct.Sprawl.Topology().Clusters[s.Peer] - clientSVC := dc.ServiceByID( + clientSVC := dc.WorkloadByID( s.nodeClient, s.clientSID, ) - serverSVC := peer.ServiceByID( + serverSVC := peer.WorkloadByID( s.nodeServer, s.serverSID, ) @@ -162,12 +164,12 @@ func (s *ac4ProxyDefaultsSuite) test(t *testing.T, ct *commonTopo) { ct.Assert.FortioFetch2HeaderEcho(t, clientSVC, s.upstream) t.Run("Validate services exist in catalog", func(t *testing.T) { - dcSvcs := dc.ServicesByID(s.clientSID) + dcSvcs := dc.WorkloadsByID(s.clientSID) require.Len(t, dcSvcs, 1, "expected exactly one client") client = dcSvcs[0] require.Len(t, client.Upstreams, 1, "expected exactly one upstream for client") - server := dc.ServicesByID(s.serverSID) + server := dc.WorkloadsByID(s.serverSID) require.Len(t, server, 1, "expected exactly one server") require.Len(t, server[0].Upstreams, 0, "expected no upstream for server") }) @@ -179,11 +181,11 @@ func (s *ac4ProxyDefaultsSuite) test(t *testing.T, ct *commonTopo) { }) t.Run("HTTP service fails due to connection timeout", func(t *testing.T) { - url504 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", client.ExposedPort(""), + url504 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", client.ExposedPort(), url.QueryEscape(fmt.Sprintf("http://localhost:%d/?delay=1000ms", s.upstream.LocalPort)), ) - url200 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", client.ExposedPort(""), + url200 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", client.ExposedPort(), url.QueryEscape(fmt.Sprintf("http://localhost:%d/", s.upstream.LocalPort)), ) diff --git a/test-integ/peering_commontopo/ac5_1_no_svc_mesh_test.go b/test-integ/peering_commontopo/ac5_1_no_svc_mesh_test.go index d564261ed878..aeebda56e1a6 100644 --- a/test-integ/peering_commontopo/ac5_1_no_svc_mesh_test.go +++ b/test-integ/peering_commontopo/ac5_1_no_svc_mesh_test.go @@ -5,7 +5,6 @@ package peering import ( "fmt" - "testing" "github.com/hashicorp/consul/api" @@ -19,8 +18,8 @@ type ac5_1NoSvcMeshSuite struct { DC string Peer string - serverSID topology.ServiceID - clientSID topology.ServiceID + serverSID topology.ID + clientSID topology.ID } var ( @@ -47,23 +46,23 @@ func (s *ac5_1NoSvcMeshSuite) setup(t *testing.T, ct *commonTopo) { partition := "default" peer := LocalPeerName(peerClu, partition) - serverSID := topology.ServiceID{ + serverSID := topology.ID{ Name: "ac5-server-http", Partition: partition, } // Make client which will dial server - clientSID := topology.ServiceID{ + clientSID := topology.ID{ Name: "ac5-http-client", Partition: partition, } // disable service mesh for client in s.DC client := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( clu.Datacenter, clientSID, - func(s *topology.Service) { + func(s *topology.Workload) { s.EnvoyAdminPort = 0 s.DisableServiceMesh = true }, @@ -79,7 +78,7 @@ func (s *ac5_1NoSvcMeshSuite) setup(t *testing.T, ct *commonTopo) { ct.AddServiceNode(clu, client) server := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( clu.Datacenter, serverSID, nil, diff --git a/test-integ/peering_commontopo/ac5_2_pq_failover_test.go b/test-integ/peering_commontopo/ac5_2_pq_failover_test.go index dec0de3ea1f9..8a65fcef8851 100644 --- a/test-integ/peering_commontopo/ac5_2_pq_failover_test.go +++ b/test-integ/peering_commontopo/ac5_2_pq_failover_test.go @@ -5,9 +5,8 @@ package peering import ( "fmt" - "time" - "testing" + "time" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil/retry" @@ -26,10 +25,11 @@ import ( // 9. Delete failing health check from step 3 // 10. Repeat step 2 type ac5_2PQFailoverSuite struct { - clientSID topology.ServiceID - serverSID topology.ServiceID + clientSID topology.ID + serverSID topology.ID nodeServer topology.NodeID } + type nodeKey struct { dc string partition string @@ -56,21 +56,21 @@ func (s *ac5_2PQFailoverSuite) setupDC(ct *commonTopo, clu, peerClu *topology.Cl partition := "default" peer := LocalPeerName(peerClu, partition) - serverSID := topology.ServiceID{ + serverSID := topology.ID{ Name: "ac5-server-http", Partition: partition, } - clientSID := topology.ServiceID{ + clientSID := topology.ID{ Name: "ac5-client-http", Partition: partition, } client := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( clu.Datacenter, clientSID, - func(s *topology.Service) { + func(s *topology.Workload) { s.EnvoyAdminPort = 0 s.DisableServiceMesh = true }, @@ -87,10 +87,10 @@ func (s *ac5_2PQFailoverSuite) setupDC(ct *commonTopo, clu, peerClu *topology.Cl ct.AddServiceNode(clu, client) server := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( clu.Datacenter, serverSID, - func(s *topology.Service) { + func(s *topology.Workload) { s.EnvoyAdminPort = 0 s.DisableServiceMesh = true }, @@ -113,22 +113,22 @@ func (s *ac5_2PQFailoverSuite) setupDC3(ct *commonTopo, clu, peer1, peer2 *topol ) peers = append(peers, LocalPeerName(peer1, partition), LocalPeerName(peer2, partition)) - serverSID := topology.ServiceID{ + serverSID := topology.ID{ Name: "ac5-server-http", Partition: partition, } - clientSID := topology.ServiceID{ + clientSID := topology.ID{ Name: "ac5-client-http", Partition: partition, } // disable service mesh for client in DC3 client := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( clu.Datacenter, clientSID, - func(s *topology.Service) { + func(s *topology.Workload) { s.EnvoyAdminPort = 0 s.DisableServiceMesh = true }, @@ -153,10 +153,10 @@ func (s *ac5_2PQFailoverSuite) setupDC3(ct *commonTopo, clu, peer1, peer2 *topol ct.AddServiceNode(clu, client) server := serviceExt{ - Service: NewFortioServiceWithDefaults( + Workload: NewFortioServiceWithDefaults( clu.Datacenter, serverSID, - func(s *topology.Service) { + func(s *topology.Workload) { s.EnvoyAdminPort = 0 s.DisableServiceMesh = true }, diff --git a/test-integ/peering_commontopo/ac6_failovers_test.go b/test-integ/peering_commontopo/ac6_failovers_test.go index 71fedc7342bc..4b37d1095510 100644 --- a/test-integ/peering_commontopo/ac6_failovers_test.go +++ b/test-integ/peering_commontopo/ac6_failovers_test.go @@ -7,10 +7,12 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" + "github.com/hashicorp/consul/testing/deployer/sprawl" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/require" ) type ac6FailoversSuite struct { @@ -37,12 +39,12 @@ type ac6FailoversSuite struct { FarInNSAlt bool // launch outputs, for querying during test - clientSID topology.ServiceID + clientSID topology.ID // near = same DC as client; far = other DC - nearServerSID topology.ServiceID + nearServerSID topology.ID // used to remove the node and trigger failover nearServerNode topology.NodeID - farServerSID topology.ServiceID + farServerSID topology.ID farServerNode topology.NodeID } @@ -217,7 +219,7 @@ func (s *ac6FailoversSuite) setup(t *testing.T, ct *commonTopo) { } // - server in clientPartition/DC (main target) - nearServerSID := topology.ServiceID{ + nearServerSID := topology.ID{ Name: "ac6-server", Partition: defaultToEmptyForCE("default"), Namespace: defaultToEmptyForCE("default"), @@ -233,7 +235,7 @@ func (s *ac6FailoversSuite) setup(t *testing.T, ct *commonTopo) { nearServerSID, nil, ) - nearServerNode := ct.AddServiceNode(nearClu, serviceExt{Service: nearServer}) + nearServerNode := ct.AddServiceNode(nearClu, serviceExt{Workload: nearServer}) nearClu.InitialConfigEntries = append(nearClu.InitialConfigEntries, &api.ServiceConfigEntry{ @@ -245,7 +247,7 @@ func (s *ac6FailoversSuite) setup(t *testing.T, ct *commonTopo) { }, ) // - server in otherPartition/otherDC - farServerSID := topology.ServiceID{ + farServerSID := topology.ID{ Name: nearServerSID.Name, Partition: defaultToEmptyForCE("default"), Namespace: defaultToEmptyForCE("default"), @@ -261,7 +263,7 @@ func (s *ac6FailoversSuite) setup(t *testing.T, ct *commonTopo) { farServerSID, nil, ) - farServerNode := ct.AddServiceNode(farClu, serviceExt{Service: farServer}) + farServerNode := ct.AddServiceNode(farClu, serviceExt{Workload: farServer}) if nearClu != farClu { ct.ExportService(farClu, farServerSID.Partition, api.ExportedService{ @@ -337,7 +339,7 @@ func (s *ac6FailoversSuite) setup(t *testing.T, ct *commonTopo) { }, ) - clientSID := topology.ServiceID{ + clientSID := topology.ID{ Name: "ac6-client", Partition: defaultToEmptyForCE(nearServerSID.Partition), Namespace: defaultToEmptyForCE(nearServerSID.Namespace), @@ -345,11 +347,11 @@ func (s *ac6FailoversSuite) setup(t *testing.T, ct *commonTopo) { client := NewFortioServiceWithDefaults( nearClu.Datacenter, clientSID, - func(s *topology.Service) { + func(s *topology.Workload) { // Upstream per partition s.Upstreams = []*topology.Upstream{ { - ID: topology.ServiceID{ + ID: topology.ID{ Name: nearServerSID.Name, Partition: defaultToEmptyForCE(nearServerSID.Partition), Namespace: defaultToEmptyForCE(nearServerSID.Namespace), @@ -362,7 +364,7 @@ func (s *ac6FailoversSuite) setup(t *testing.T, ct *commonTopo) { } }, ) - ct.AddServiceNode(nearClu, serviceExt{Service: client}) + ct.AddServiceNode(nearClu, serviceExt{Workload: client}) nearClu.InitialConfigEntries = append(nearClu.InitialConfigEntries, &api.ServiceConfigEntry{ Kind: api.ServiceDefaults, @@ -432,7 +434,7 @@ func (s *ac6FailoversSuite) test(t *testing.T, ct *commonTopo) { farClu = ct.Sprawl.Topology().Clusters["dc1"] } - svcs := nearClu.ServicesByID(s.clientSID) + svcs := nearClu.WorkloadsByID(s.clientSID) require.Len(t, svcs, 1, "expected exactly one client in datacenter") client := svcs[0] @@ -459,7 +461,7 @@ func (s *ac6FailoversSuite) test(t *testing.T, ct *commonTopo) { cfg := ct.Sprawl.Config() DisableNode(t, cfg, nearClu.Name, s.nearServerNode) - require.NoError(t, ct.Sprawl.RelaunchWithPhase(cfg, "failover")) + require.NoError(t, ct.Sprawl.RelaunchWithPhase(cfg, sprawl.LaunchPhaseRegular)) // Clusters for imported services rely on outlier detection for // failovers, NOT eds_health_status. This means that killing the // node above does not actually make the envoy cluster UNHEALTHY diff --git a/test-integ/peering_commontopo/ac7_1_rotate_gw_test.go b/test-integ/peering_commontopo/ac7_1_rotate_gw_test.go index a492b95dc05f..e901c7c305cb 100644 --- a/test-integ/peering_commontopo/ac7_1_rotate_gw_test.go +++ b/test-integ/peering_commontopo/ac7_1_rotate_gw_test.go @@ -8,9 +8,10 @@ import ( "strings" "testing" + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/require" ) // TestRotateGW ensures that peered services continue to be able to talk to their @@ -21,10 +22,10 @@ type suiteRotateGW struct { DC string Peer string - sidServer topology.ServiceID + sidServer topology.ID nodeServer topology.NodeID - sidClient topology.ServiceID + sidClient topology.ID nodeClient topology.NodeID upstream *topology.Upstream @@ -62,7 +63,7 @@ func (s *suiteRotateGW) setup(t *testing.T, ct *commonTopo) { server := NewFortioServiceWithDefaults( peerClu.Datacenter, - topology.ServiceID{ + topology.ID{ Name: prefix + "server-http", Partition: partition, }, @@ -71,7 +72,7 @@ func (s *suiteRotateGW) setup(t *testing.T, ct *commonTopo) { // Make clients which have server upstreams upstream := &topology.Upstream{ - ID: topology.ServiceID{ + ID: topology.ID{ Name: server.ID.Name, Partition: partition, }, @@ -83,17 +84,17 @@ func (s *suiteRotateGW) setup(t *testing.T, ct *commonTopo) { // create client in us client := NewFortioServiceWithDefaults( clu.Datacenter, - topology.ServiceID{ + topology.ID{ Name: prefix + "client", Partition: partition, }, - func(s *topology.Service) { + func(s *topology.Workload) { s.Upstreams = []*topology.Upstream{ upstream, } }, ) - clientNode := ct.AddServiceNode(clu, serviceExt{Service: client, + clientNode := ct.AddServiceNode(clu, serviceExt{Workload: client, Config: &api.ServiceConfigEntry{ Kind: api.ServiceDefaults, Name: client.ID.Name, @@ -110,7 +111,7 @@ func (s *suiteRotateGW) setup(t *testing.T, ct *commonTopo) { }) // actually to be used by the other pairing serverNode := ct.AddServiceNode(peerClu, serviceExt{ - Service: server, + Workload: server, Config: &api.ServiceConfigEntry{ Kind: api.ServiceDefaults, Name: server.ID.Name, @@ -161,11 +162,11 @@ func (s *suiteRotateGW) test(t *testing.T, ct *commonTopo) { dc := ct.Sprawl.Topology().Clusters[s.DC] peer := ct.Sprawl.Topology().Clusters[s.Peer] - svcHTTPServer := peer.ServiceByID( + svcHTTPServer := peer.WorkloadByID( s.nodeServer, s.sidServer, ) - svcHTTPClient := dc.ServiceByID( + svcHTTPClient := dc.WorkloadByID( s.nodeClient, s.sidClient, ) diff --git a/test-integ/peering_commontopo/ac7_2_rotate_leader_test.go b/test-integ/peering_commontopo/ac7_2_rotate_leader_test.go index 36e3c0ced3f5..0f6fe439e2ac 100644 --- a/test-integ/peering_commontopo/ac7_2_rotate_leader_test.go +++ b/test-integ/peering_commontopo/ac7_2_rotate_leader_test.go @@ -12,11 +12,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil/retry" + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" + "github.com/hashicorp/consul/testing/deployer/topology" ) // TestAC7_2RotateLeader ensures that after a leader rotation, information continues to replicate to peers @@ -25,10 +24,10 @@ type ac7_2RotateLeaderSuite struct { DC string Peer string - sidServer topology.ServiceID + sidServer topology.ID nodeServer topology.NodeID - sidClient topology.ServiceID + sidClient topology.ID nodeClient topology.NodeID upstream *topology.Upstream @@ -65,7 +64,7 @@ func (s *ac7_2RotateLeaderSuite) setup(t *testing.T, ct *commonTopo) { server := NewFortioServiceWithDefaults( peerClu.Datacenter, - topology.ServiceID{ + topology.ID{ Name: prefix + "server-http", Partition: partition, }, @@ -74,7 +73,7 @@ func (s *ac7_2RotateLeaderSuite) setup(t *testing.T, ct *commonTopo) { // Make clients which have server upstreams upstream := &topology.Upstream{ - ID: topology.ServiceID{ + ID: topology.ID{ Name: server.ID.Name, Partition: partition, }, @@ -84,17 +83,17 @@ func (s *ac7_2RotateLeaderSuite) setup(t *testing.T, ct *commonTopo) { // create client in us client := NewFortioServiceWithDefaults( clu.Datacenter, - topology.ServiceID{ + topology.ID{ Name: prefix + "client", Partition: partition, }, - func(s *topology.Service) { + func(s *topology.Workload) { s.Upstreams = []*topology.Upstream{ upstream, } }, ) - clientNode := ct.AddServiceNode(clu, serviceExt{Service: client, + clientNode := ct.AddServiceNode(clu, serviceExt{Workload: client, Config: &api.ServiceConfigEntry{ Kind: api.ServiceDefaults, Name: client.ID.Name, @@ -111,7 +110,7 @@ func (s *ac7_2RotateLeaderSuite) setup(t *testing.T, ct *commonTopo) { }) // actually to be used by the other pairing serverNode := ct.AddServiceNode(peerClu, serviceExt{ - Service: server, + Workload: server, Config: &api.ServiceConfigEntry{ Kind: api.ServiceDefaults, Name: server.ID.Name, @@ -146,8 +145,8 @@ func (s *ac7_2RotateLeaderSuite) test(t *testing.T, ct *commonTopo) { clDC := ct.APIClientForCluster(t, dc) clPeer := ct.APIClientForCluster(t, peer) - svcServer := peer.ServiceByID(s.nodeServer, s.sidServer) - svcClient := dc.ServiceByID(s.nodeClient, s.sidClient) + svcServer := peer.WorkloadByID(s.nodeServer, s.sidServer) + svcClient := dc.WorkloadByID(s.nodeClient, s.sidClient) ct.Assert.HealthyWithPeer(t, dc.Name, svcServer.ID, LocalPeerName(peer, "default")) ct.Assert.FortioFetch2HeaderEcho(t, svcClient, s.upstream) diff --git a/test-integ/peering_commontopo/commontopo.go b/test-integ/peering_commontopo/commontopo.go index 253bddb2eb61..c4360932557a 100644 --- a/test-integ/peering_commontopo/commontopo.go +++ b/test-integ/peering_commontopo/commontopo.go @@ -9,16 +9,16 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil/retry" + "github.com/hashicorp/consul/test-integ/topoutil" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" "github.com/hashicorp/consul/testing/deployer/sprawl" "github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/test-integ/topoutil" ) // commonTopo helps create a shareable topology configured to represent @@ -48,7 +48,7 @@ type commonTopo struct { Assert *topoutil.Asserter // track per-DC services to prevent duplicates - services map[string]map[topology.ServiceID]struct{} + services map[string]map[topology.ID]struct{} // if zero, no DCs are agentless agentlessDC string @@ -107,9 +107,9 @@ func newCommonTopo(t *testing.T, agentlessDC string, includeDC3 bool, peerThroug injectTenancies(dc2) // dc3 doesn't get tenancies - ct.services = map[string]map[topology.ServiceID]struct{}{} + ct.services = map[string]map[topology.ID]struct{}{} for _, dc := range clusters { - ct.services[dc.Datacenter] = map[topology.ServiceID]struct{}{} + ct.services[dc.Datacenter] = map[topology.ID]struct{}{} } peerings := addPeerings(dc1, dc2) @@ -230,7 +230,7 @@ func LocalPeerName(clu *topology.Cluster, partition string) string { // TODO: move these to topology // TODO: alternatively, delete it: we only use it in one place, to bundle up args type serviceExt struct { - *topology.Service + *topology.Workload Exports []api.ServiceConsumer Config *api.ServiceConfigEntry @@ -245,7 +245,7 @@ func (ct *commonTopo) AddServiceNode(clu *topology.Cluster, svc serviceExt) *top ct.services[clusterName][svc.ID] = struct{}{} // TODO: inline - serviceHostnameString := func(dc string, id topology.ServiceID) string { + serviceHostnameString := func(dc string, id topology.ID) string { n := id.Name // prepend - and - if they are not default/empty // avoids hostname limit of 63 chars in most cases @@ -279,8 +279,8 @@ func (ct *commonTopo) AddServiceNode(clu *topology.Cluster, svc serviceExt) *top Addresses: []*topology.Address{ {Network: clu.Datacenter}, }, - Services: []*topology.Service{ - svc.Service, + Workloads: []*topology.Workload{ + svc.Workload, }, Cluster: clusterName, } @@ -506,10 +506,10 @@ func injectTenancies(clu *topology.Cluster) { // Deprecated: topoutil.NewFortioServiceWithDefaults func NewFortioServiceWithDefaults( cluster string, - sid topology.ServiceID, - mut func(s *topology.Service), -) *topology.Service { - return topoutil.NewFortioServiceWithDefaults(cluster, sid, topology.NodeVersionV1, mut) + sid topology.ID, + mut func(s *topology.Workload), +) *topology.Workload { + return topoutil.NewFortioServiceWithDefaults(cluster, sid, mut) } func newTopologyMeshGatewaySet( @@ -519,8 +519,8 @@ func newTopologyMeshGatewaySet( num int, networks []string, mutateFn func(i int, node *topology.Node), -) (topology.ServiceID, []*topology.Node) { +) (topology.ID, []*topology.Node) { nodes := topoutil.NewTopologyMeshGatewaySet(nodeKind, partition, namePrefix, num, networks, mutateFn) - sid := nodes[0].Services[0].ID + sid := nodes[0].Workloads[0].ID return sid, nodes } diff --git a/test-integ/topoutil/asserter.go b/test-integ/topoutil/asserter.go index dd0500922c69..0ba842ad07a6 100644 --- a/test-integ/topoutil/asserter.go +++ b/test-integ/topoutil/asserter.go @@ -4,22 +4,28 @@ package topoutil import ( + "encoding/json" "fmt" "io" "net/http" "net/url" + "os" "regexp" + "strings" "testing" "time" + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // Asserter is a utility to help in reducing boilerplate in invoking test @@ -52,13 +58,13 @@ func NewAsserter(sp SprawlLite) *Asserter { } } -func (a *Asserter) mustGetHTTPClient(t *testing.T, cluster string) *http.Client { +func (a *Asserter) mustGetHTTPClient(t testutil.TestingTB, cluster string) *http.Client { client, err := a.httpClientFor(cluster) require.NoError(t, err) return client } -func (a *Asserter) mustGetAPIClient(t *testing.T, cluster string) *api.Client { +func (a *Asserter) mustGetAPIClient(t testutil.TestingTB, cluster string) *api.Client { clu := a.sp.Topology().Clusters[cluster] cl, err := a.sp.APIClientForCluster(clu.Name, "") require.NoError(t, err) @@ -85,21 +91,80 @@ func (a *Asserter) httpClientFor(cluster string) (*http.Client, error) { // NOTE: this doesn't take a port b/c you always want to use the envoy admin port. func (a *Asserter) UpstreamEndpointStatus( t *testing.T, - service *topology.Service, + workload *topology.Workload, clusterName string, healthStatus string, count int, ) { t.Helper() - node := service.Node + node := workload.Node ip := node.LocalAddress() - port := service.EnvoyAdminPort + port := workload.EnvoyAdminPort addr := fmt.Sprintf("%s:%d", ip, port) client := a.mustGetHTTPClient(t, node.Cluster) libassert.AssertUpstreamEndpointStatusWithClient(t, client, addr, clusterName, healthStatus, count) } +func (a *Asserter) getEnvoyClient(t *testing.T, workload *topology.Workload) (client *http.Client, addr string) { + node := workload.Node + ip := node.LocalAddress() + port := workload.EnvoyAdminPort + addr = fmt.Sprintf("%s:%d", ip, port) + client = a.mustGetHTTPClient(t, node.Cluster) + return client, addr +} + +// AssertEnvoyRunningWithClient asserts that envoy is running by querying its stats page +func (a *Asserter) AssertEnvoyRunningWithClient(t *testing.T, workload *topology.Workload) { + t.Helper() + client, addr := a.getEnvoyClient(t, workload) + libassert.AssertEnvoyRunningWithClient(t, client, addr) +} + +// AssertEnvoyPresentsCertURIWithClient makes GET request to /certs endpoint and validates that +// two certificates URI is available in the response +func (a *Asserter) AssertEnvoyPresentsCertURIWithClient(t *testing.T, workload *topology.Workload) { + t.Helper() + client, addr := a.getEnvoyClient(t, workload) + libassert.AssertEnvoyPresentsCertURIWithClient(t, client, addr, workload.ID.Name) +} + +func (a *Asserter) AssertEnvoyHTTPrbacFiltersContainIntentions(t *testing.T, workload *topology.Workload) { + t.Helper() + client, addr := a.getEnvoyClient(t, workload) + var ( + dump string + err error + ) + failer := func() *retry.Timer { + return &retry.Timer{Timeout: 30 * time.Second, Wait: 1 * time.Second} + } + + retry.RunWith(failer(), t, func(r *retry.R) { + dump, _, err = libassert.GetEnvoyOutputWithClient(client, addr, "config_dump", map[string]string{}) + if err != nil { + r.Fatal("could not fetch envoy configuration") + } + }) + // the steps below validate that the json result from envoy config dump configured active listeners with rbac and http filters + filter := `.configs[2].dynamic_listeners[].active_state.listener | "\(.name) \( .filter_chains[].filters[] | select(.name == "envoy.filters.network.http_connection_manager") | .typed_config.http_filters | map(.name) | join(","))"` + errorStateFilter := `.configs[2].dynamic_listeners[].error_state"` + configErrorStates, _ := utils.JQFilter(dump, errorStateFilter) + require.Nil(t, configErrorStates, "there should not be any error states on listener configuration") + results, err := utils.JQFilter(dump, filter) + require.NoError(t, err, "could not parse envoy configuration") + var filteredResult []string + for _, result := range results { + parts := strings.Split(strings.ReplaceAll(result, `,`, " "), " ") + sanitizedResult := append(parts[:0], parts[1:]...) + filteredResult = append(filteredResult, sanitizedResult...) + } + require.Contains(t, filteredResult, "envoy.filters.http.rbac") + require.Contains(t, filteredResult, "envoy.filters.http.router") + require.Contains(t, dump, "intentions") +} + // HTTPServiceEchoes verifies that a post to the given ip/port combination // returns the data in the response body. Optional path can be provided to // differentiate requests. @@ -109,14 +174,14 @@ func (a *Asserter) UpstreamEndpointStatus( // NOTE: this takes a port b/c you may want to reach this via your choice of upstream. func (a *Asserter) HTTPServiceEchoes( t *testing.T, - service *topology.Service, + workload *topology.Workload, port int, path string, ) { t.Helper() require.True(t, port > 0) - node := service.Node + node := workload.Node ip := node.LocalAddress() addr := fmt.Sprintf("%s:%d", ip, port) @@ -133,7 +198,7 @@ func (a *Asserter) HTTPServiceEchoes( // NOTE: this takes a port b/c you may want to reach this via your choice of upstream. func (a *Asserter) HTTPServiceEchoesResHeader( t *testing.T, - service *topology.Service, + workload *topology.Workload, port int, path string, expectedResHeader map[string]string, @@ -141,7 +206,7 @@ func (a *Asserter) HTTPServiceEchoesResHeader( t.Helper() require.True(t, port > 0) - node := service.Node + node := workload.Node ip := node.LocalAddress() addr := fmt.Sprintf("%s:%d", ip, port) @@ -151,14 +216,14 @@ func (a *Asserter) HTTPServiceEchoesResHeader( func (a *Asserter) HTTPStatus( t *testing.T, - service *topology.Service, + workload *topology.Workload, port int, status int, ) { t.Helper() require.True(t, port > 0) - node := service.Node + node := workload.Node ip := node.LocalAddress() addr := fmt.Sprintf("%s:%d", ip, port) @@ -179,7 +244,7 @@ func (a *Asserter) HTTPStatus( } // asserts that the service sid in cluster and exported by peer localPeerName is passing health checks, -func (a *Asserter) HealthyWithPeer(t *testing.T, cluster string, sid topology.ServiceID, peerName string) { +func (a *Asserter) HealthyWithPeer(t *testing.T, cluster string, sid topology.ID, peerName string) { t.Helper() cl := a.mustGetAPIClient(t, cluster) retry.RunWith(&retry.Timer{Timeout: time.Minute * 1, Wait: time.Millisecond * 500}, t, func(r *retry.R) { @@ -208,35 +273,15 @@ type testingT interface { // // We treat 400, 503, and 504s as retryable errors func (a *Asserter) fortioFetch2Upstream( - t testingT, + t testutil.TestingTB, client *http.Client, addr string, - upstream *topology.Upstream, + us *topology.Upstream, path string, ) (body []byte, res *http.Response) { t.Helper() - var actualURL string - if upstream.Implied { - actualURL = fmt.Sprintf("http://%s--%s--%s.virtual.consul:%d/%s", - upstream.ID.Name, - upstream.ID.Namespace, - upstream.ID.Partition, - upstream.VirtualPort, - path, - ) - } else { - actualURL = fmt.Sprintf("http://localhost:%d/%s", upstream.LocalPort, path) - } - - url := fmt.Sprintf("http://%s/fortio/fetch2?url=%s", addr, - url.QueryEscape(actualURL), - ) - - req, err := http.NewRequest(http.MethodPost, url, nil) - require.NoError(t, err) - - res, err = client.Do(req) + err, res := getFortioFetch2UpstreamResponse(t, client, addr, us, path, nil) require.NoError(t, err) defer res.Body.Close() @@ -251,21 +296,39 @@ func (a *Asserter) fortioFetch2Upstream( return body, res } +func getFortioFetch2UpstreamResponse(t testutil.TestingTB, client *http.Client, addr string, us *topology.Upstream, path string, headers map[string]string) (error, *http.Response) { + actualURL := fmt.Sprintf("http://localhost:%d/%s", us.LocalPort, path) + + url := fmt.Sprintf("http://%s/fortio/fetch2?url=%s", addr, + url.QueryEscape(actualURL), + ) + + req, err := http.NewRequest(http.MethodPost, url, nil) + require.NoError(t, err) + + for h, v := range headers { + req.Header.Set(h, v) + } + res, err := client.Do(req) + require.NoError(t, err) + return err, res +} + // uses the /fortio/fetch2 endpoint to do a header echo check against an // upstream fortio -func (a *Asserter) FortioFetch2HeaderEcho(t *testing.T, fortioSvc *topology.Service, upstream *topology.Upstream) { +func (a *Asserter) FortioFetch2HeaderEcho(t *testing.T, fortioWrk *topology.Workload, us *topology.Upstream) { const kPassphrase = "x-passphrase" const passphrase = "hello" path := (fmt.Sprintf("/?header=%s:%s", kPassphrase, passphrase)) var ( - node = fortioSvc.Node - addr = fmt.Sprintf("%s:%d", node.LocalAddress(), fortioSvc.PortOrDefault("http")) + node = fortioWrk.Node + addr = fmt.Sprintf("%s:%d", node.LocalAddress(), fortioWrk.Port) client = a.mustGetHTTPClient(t, node.Cluster) ) retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - _, res := a.fortioFetch2Upstream(r, client, addr, upstream, path) + _, res := a.fortioFetch2Upstream(r, client, addr, us, path) require.Equal(r, http.StatusOK, res.StatusCode) v := res.Header.Get(kPassphrase) require.Equal(r, passphrase, v) @@ -277,16 +340,16 @@ func (a *Asserter) FortioFetch2HeaderEcho(t *testing.T, fortioSvc *topology.Serv // and assert that the FORTIO_NAME == name func (a *Asserter) FortioFetch2FortioName( t *testing.T, - fortioSvc *topology.Service, - upstream *topology.Upstream, + fortioWrk *topology.Workload, + us *topology.Upstream, clusterName string, - sid topology.ServiceID, + sid topology.ID, ) { t.Helper() var ( - node = fortioSvc.Node - addr = fmt.Sprintf("%s:%d", node.LocalAddress(), fortioSvc.PortOrDefault("http")) + node = fortioWrk.Node + addr = fmt.Sprintf("%s:%d", node.LocalAddress(), fortioWrk.Port) client = a.mustGetHTTPClient(t, node.Cluster) ) @@ -294,7 +357,7 @@ func (a *Asserter) FortioFetch2FortioName( path := "/debug?env=dump" retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - body, res := a.fortioFetch2Upstream(r, client, addr, upstream, path) + body, res := a.fortioFetch2Upstream(r, client, addr, us, path) require.Equal(r, http.StatusOK, res.StatusCode) @@ -306,6 +369,29 @@ func (a *Asserter) FortioFetch2FortioName( }) } +func (a *Asserter) FortioFetch2ServiceUnavailable(t *testing.T, fortioWrk *topology.Workload, us *topology.Upstream) { + const kPassphrase = "x-passphrase" + const passphrase = "hello" + path := (fmt.Sprintf("/?header=%s:%s", kPassphrase, passphrase)) + a.FortioFetch2ServiceStatusCodes(t, fortioWrk, us, path, nil, []int{http.StatusServiceUnavailable}) +} + +// FortioFetch2ServiceStatusCodes uses the /fortio/fetch2 endpoint to do a header echo check against a upstream +// fortio and asserts that the returned status code matches the desired one(s) +func (a *Asserter) FortioFetch2ServiceStatusCodes(t *testing.T, fortioWrk *topology.Workload, us *topology.Upstream, path string, headers map[string]string, statuses []int) { + var ( + node = fortioWrk.Node + addr = fmt.Sprintf("%s:%d", node.LocalAddress(), fortioWrk.Port) + client = a.mustGetHTTPClient(t, node.Cluster) + ) + + retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 500}, t, func(r *retry.R) { + _, res := getFortioFetch2UpstreamResponse(r, client, addr, us, path, headers) + defer res.Body.Close() + require.Contains(r, statuses, res.StatusCode) + }) +} + // CatalogServiceExists is the same as libassert.CatalogServiceExists, except that it uses // a proxied API client func (a *Asserter) CatalogServiceExists(t *testing.T, cluster string, svc string, opts *api.QueryOptions) { @@ -313,3 +399,135 @@ func (a *Asserter) CatalogServiceExists(t *testing.T, cluster string, svc string cl := a.mustGetAPIClient(t, cluster) libassert.CatalogServiceExists(t, cl, svc, opts) } + +// HealthServiceEntries asserts the service has the expected number of instances and checks +func (a *Asserter) HealthServiceEntries(t *testing.T, cluster string, node *topology.Node, svc string, passingOnly bool, opts *api.QueryOptions, expectedInstance int, expectedChecks int) []*api.ServiceEntry { + t.Helper() + cl, err := a.sp.APIClientForNode(cluster, node.ID(), "") + require.NoError(t, err) + health := cl.Health() + + var serviceEntries []*api.ServiceEntry + retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 500}, t, func(r *retry.R) { + serviceEntries, _, err = health.Service(svc, "", passingOnly, opts) + require.NoError(r, err) + require.Equalf(r, expectedInstance, len(serviceEntries), "dc: %s, service: %s", cluster, serviceEntries[0].Service.Service) + require.Equalf(r, expectedChecks, len(serviceEntries[0].Checks), "dc: %s, service: %s", cluster, serviceEntries[0].Service.Service) + }) + + return serviceEntries +} + +// TokenExist asserts the token exists in the cluster and identical to the expected token +func (a *Asserter) TokenExist(t *testing.T, cluster string, node *topology.Node, expectedToken *api.ACLToken) { + t.Helper() + cl, err := a.sp.APIClientForNode(cluster, node.ID(), "") + require.NoError(t, err) + acl := cl.ACL() + retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 500}, t, func(r *retry.R) { + retrievedToken, _, err := acl.TokenRead(expectedToken.AccessorID, &api.QueryOptions{}) + require.NoError(r, err) + require.True(r, cmp.Equal(expectedToken, retrievedToken), "token %s", expectedToken.Description) + }) +} + +// AutopilotHealth asserts the autopilot health endpoint return expected state +func (a *Asserter) AutopilotHealth(t *testing.T, cluster *topology.Cluster, leaderName string, expectedHealthy bool) { + t.Helper() + + retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 10}, t, func(r *retry.R) { + var out *api.OperatorHealthReply + for _, node := range cluster.Nodes { + if node.Name == leaderName { + client, err := a.sp.APIClientForNode(cluster.Name, node.ID(), "") + if err != nil { + r.Log("err at node", node.Name, err) + continue + } + operator := client.Operator() + out, err = operator.AutopilotServerHealth(&api.QueryOptions{}) + if err != nil { + r.Log("err at node", node.Name, err) + continue + } + + // Got the Autopilot server health response, break the loop + r.Log("Got response at node", node.Name) + break + } + } + r.Log("out", out, "health", out.Healthy) + require.Equal(r, expectedHealthy, out.Healthy) + }) + return +} + +type AuditEntry struct { + CreatedAt time.Time `json:"created_at"` + EventType string `json:"event_type"` + Payload Payload `json:"payload"` +} + +type Payload struct { + ID string `json:"id"` + Version string `json:"version"` + Type string `json:"type"` + Timestamp time.Time `json:"timestamp"` + Auth Auth `json:"auth"` + Request Request `json:"request"` + Response Response `json:"response,omitempty"` // Response is not present in OperationStart log + Stage string `json:"stage"` +} + +type Auth struct { + AccessorID string `json:"accessor_id"` + Description string `json:"description"` + CreateTime time.Time `json:"create_time"` +} + +type Request struct { + Operation string `json:"operation"` + Endpoint string `json:"endpoint"` + RemoteAddr string `json:"remote_addr"` + UserAgent string `json:"user_agent"` + Host string `json:"host"` + QueryParams map[string]string `json:"query_params,omitempty"` // QueryParams might not be present in all cases +} + +type Response struct { + Status string `json:"status"` + Error string `json:"error,omitempty"` // Error field is optional,shows up only with the status is non 2xx +} + +func (a *Asserter) ValidateHealthEndpointAuditLog(t *testing.T, filePath string) { + boolIsErrorJSON := false + jsonData, err := os.ReadFile(filePath) + require.NoError(t, err) + + // Print details of each AuditEntry + var entry AuditEntry + events := strings.Split(strings.TrimSpace(string(jsonData)), "\n") + + // function to validate the error object when the health endpoint is returning 429 + isErrorJSONObject := func(errorString string) error { + // Attempt to unmarshal the error string into a map[string]interface{} + var m map[string]interface{} + err := json.Unmarshal([]byte(errorString), &m) + return err + } + + for _, event := range events { + if strings.Contains(event, "/v1/operator/autopilot/health") && strings.Contains(event, "OperationComplete") { + err = json.Unmarshal([]byte(event), &entry) + require.NoError(t, err, "Error unmarshalling JSON: %v\", err") + if entry.Payload.Response.Status == "429" { + boolIsErrorJSON = true + errResponse := entry.Payload.Response.Error + err = isErrorJSONObject(errResponse) + require.NoError(t, err, "Autopilot Health endpoint error response in the audit log is in unexpected format: %v\", err") + break + } + } + } + require.Equal(t, boolIsErrorJSON, true, "Unable to verify audit log health endpoint error message") +} diff --git a/test-integ/topoutil/asserter_blankspace.go b/test-integ/topoutil/asserter_blankspace.go new file mode 100644 index 000000000000..ed6d76b9b3fd --- /dev/null +++ b/test-integ/topoutil/asserter_blankspace.go @@ -0,0 +1,291 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package topoutil + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/sdk/testutil/retry" + "github.com/hashicorp/consul/testing/deployer/topology" +) + +// CheckBlankspaceNameViaHTTP calls a copy of blankspace and asserts it arrived +// on the correct instance using HTTP1 or HTTP2. +func (a *Asserter) CheckBlankspaceNameViaHTTP( + t *testing.T, + workload *topology.Workload, + us *topology.Upstream, + useHTTP2 bool, + path string, + clusterName string, + sid topology.ID, +) { + t.Helper() + + a.checkBlankspaceNameViaHTTPWithCallback(t, workload, us, useHTTP2, path, 1, func(_ *retry.R) {}, func(r *retry.R, remoteName string) { + require.Equal(r, fmt.Sprintf("%s::%s", clusterName, sid.String()), remoteName) + }, func(r *retry.R) {}) +} + +// CheckBlankspaceNameTrafficSplitViaHTTP is like CheckBlankspaceNameViaHTTP +// but it is verifying a relative traffic split. +func (a *Asserter) CheckBlankspaceNameTrafficSplitViaHTTP( + t *testing.T, + workload *topology.Workload, + us *topology.Upstream, + useHTTP2 bool, + path string, + expect map[string]int, +) { + t.Helper() + + got := make(map[string]int) + a.checkBlankspaceNameViaHTTPWithCallback(t, workload, us, useHTTP2, path, 100, func(_ *retry.R) { + got = make(map[string]int) + }, func(_ *retry.R, name string) { + got[name]++ + }, func(r *retry.R) { + assertTrafficSplitFor100Requests(r, got, expect) + }) +} + +func (a *Asserter) checkBlankspaceNameViaHTTPWithCallback( + t *testing.T, + workload *topology.Workload, + us *topology.Upstream, + useHTTP2 bool, + path string, + count int, + resetFn func(r *retry.R), + attemptFn func(r *retry.R, remoteName string), + checkFn func(r *retry.R), +) { + t.Helper() + + var ( + node = workload.Node + internalPort = workload.Port + addr = fmt.Sprintf("%s:%d", node.LocalAddress(), internalPort) + client = a.mustGetHTTPClient(t, node.Cluster) + ) + + if useHTTP2 { + // We can't use the forward proxy for http2, so use the exposed port on localhost instead. + exposedPort := node.ExposedPort(internalPort) + require.True(t, exposedPort > 0) + + addr = fmt.Sprintf("%s:%d", "127.0.0.1", exposedPort) + + // This will clear the proxy field on the transport. + client = EnableHTTP2(client) + } + + actualURL := fmt.Sprintf("http://localhost:%d/%s", us.LocalPort, path) + + multiassert(t, count, resetFn, func(r *retry.R) { + name, err := GetBlankspaceNameViaHTTP(context.Background(), client, addr, actualURL) + require.NoError(r, err) + attemptFn(r, name) + }, func(r *retry.R) { + checkFn(r) + }) +} + +// CheckBlankspaceNameViaTCP calls a copy of blankspace and asserts it arrived +// on the correct instance using plain tcp sockets. +func (a *Asserter) CheckBlankspaceNameViaTCP( + t *testing.T, + workload *topology.Workload, + us *topology.Upstream, + clusterName string, + sid topology.ID, +) { + t.Helper() + + a.checkBlankspaceNameViaTCPWithCallback(t, workload, us, 1, func(_ *retry.R) {}, func(r *retry.R, remoteName string) { + require.Equal(r, fmt.Sprintf("%s::%s", clusterName, sid.String()), remoteName) + }, func(r *retry.R) {}) +} + +// CheckBlankspaceNameTrafficSplitViaTCP is like CheckBlankspaceNameViaTCP +// but it is verifying a relative traffic split. +func (a *Asserter) CheckBlankspaceNameTrafficSplitViaTCP( + t *testing.T, + workload *topology.Workload, + us *topology.Upstream, + expect map[string]int, +) { + t.Helper() + + got := make(map[string]int) + a.checkBlankspaceNameViaTCPWithCallback(t, workload, us, 100, func(_ *retry.R) { + got = make(map[string]int) + }, func(_ *retry.R, name string) { + got[name]++ + }, func(r *retry.R) { + assertTrafficSplitFor100Requests(r, got, expect) + }) +} + +func (a *Asserter) checkBlankspaceNameViaTCPWithCallback( + t *testing.T, + workload *topology.Workload, + us *topology.Upstream, + count int, + resetFn func(r *retry.R), + attemptFn func(r *retry.R, remoteName string), + checkFn func(r *retry.R), +) { + t.Helper() + + port := us.LocalPort + require.True(t, port > 0) + + node := workload.Node + + // We can't use the forward proxy for TCP yet, so use the exposed port on localhost instead. + exposedPort := node.ExposedPort(port) + require.True(t, exposedPort > 0) + + addr := fmt.Sprintf("%s:%d", "127.0.0.1", exposedPort) + + multiassert(t, count, resetFn, func(r *retry.R) { + name, err := GetBlankspaceNameViaTCP(context.Background(), addr) + require.NoError(r, err) + attemptFn(r, name) + }, func(r *retry.R) { + checkFn(r) + }) +} + +// CheckBlankspaceNameViaGRPC calls a copy of blankspace and asserts it arrived +// on the correct instance using gRPC. +func (a *Asserter) CheckBlankspaceNameViaGRPC( + t *testing.T, + workload *topology.Workload, + us *topology.Upstream, + clusterName string, + sid topology.ID, +) { + t.Helper() + + a.checkBlankspaceNameViaGRPCWithCallback(t, workload, us, 1, func(_ *retry.R) {}, func(r *retry.R, remoteName string) { + require.Equal(r, fmt.Sprintf("%s::%s", clusterName, sid.String()), remoteName) + }, func(_ *retry.R) {}) +} + +// CheckBlankspaceNameTrafficSplitViaGRPC is like CheckBlankspaceNameViaGRPC +// but it is verifying a relative traffic split. +func (a *Asserter) CheckBlankspaceNameTrafficSplitViaGRPC( + t *testing.T, + workload *topology.Workload, + us *topology.Upstream, + expect map[string]int, +) { + t.Helper() + + got := make(map[string]int) + a.checkBlankspaceNameViaGRPCWithCallback(t, workload, us, 100, func(_ *retry.R) { + got = make(map[string]int) + }, func(_ *retry.R, name string) { + got[name]++ + }, func(r *retry.R) { + assertTrafficSplitFor100Requests(r, got, expect) + }) +} + +func (a *Asserter) checkBlankspaceNameViaGRPCWithCallback( + t *testing.T, + workload *topology.Workload, + us *topology.Upstream, + count int, + resetFn func(r *retry.R), + attemptFn func(r *retry.R, remoteName string), + checkFn func(r *retry.R), +) { + t.Helper() + + port := us.LocalPort + require.True(t, port > 0) + + node := workload.Node + + // We can't use the forward proxy for gRPC yet, so use the exposed port on localhost instead. + exposedPort := node.ExposedPort(port) + require.True(t, exposedPort > 0) + + addr := fmt.Sprintf("%s:%d", "127.0.0.1", exposedPort) + + multiassert(t, count, resetFn, func(r *retry.R) { + name, err := GetBlankspaceNameViaGRPC(context.Background(), addr) + require.NoError(r, err) + attemptFn(r, name) + }, func(r *retry.R) { + checkFn(r) + }) +} + +// assertTrafficSplitFor100Requests compares the counts of 100 requests that +// did reach an observed set of upstreams (nameCounts) against the expected +// counts of those same services is the same within a fixed difference of 2. +func assertTrafficSplitFor100Requests(t require.TestingT, nameCounts map[string]int, expect map[string]int) { + const ( + numRequests = 100 + allowedDelta = 2 + ) + require.Equal(t, numRequests, sumMapValues(nameCounts), "measured traffic was not %d requests", numRequests) + require.Equal(t, numRequests, sumMapValues(expect), "expected traffic was not %d requests", numRequests) + assertTrafficSplit(t, nameCounts, expect, allowedDelta) +} + +func sumMapValues(m map[string]int) int { + sum := 0 + for _, v := range m { + sum += v + } + return sum +} + +// assertTrafficSplit compares the counts of requests that did reach an +// observed set of upstreams (nameCounts) against the expected counts of +// those same services is the same within the provided allowedDelta value. +// +// When doing random traffic splits it'll never be perfect so we need the +// wiggle room to avoid having a flaky test. +func assertTrafficSplit(t require.TestingT, nameCounts map[string]int, expect map[string]int, allowedDelta int) { + require.Len(t, nameCounts, len(expect)) + for name, expectCount := range expect { + gotCount, ok := nameCounts[name] + require.True(t, ok) + if len(expect) == 1 { + require.Equal(t, expectCount, gotCount) + } else { + require.InDelta(t, expectCount, gotCount, float64(allowedDelta), + "expected %q side of split to have %d requests not %d (e=%d)", + name, expectCount, gotCount, allowedDelta, + ) + } + } +} + +// multiassert will retry in bulk calling attemptFn count times and following +// that with one last call to checkFn. +// +// It's primary use at the time it was written was to execute a set of requests +// repeatedly to witness where the requests went, and then at the end doing a +// verification of traffic splits (a bit like MAP/REDUCE). +func multiassert(t *testing.T, count int, resetFn, attemptFn, checkFn func(r *retry.R)) { + retry.RunWith(&retry.Timer{Timeout: 30 * time.Second, Wait: 500 * time.Millisecond}, t, func(r *retry.R) { + resetFn(r) + for i := 0; i < count; i++ { + attemptFn(r) + } + checkFn(r) + }) +} diff --git a/test-integ/topoutil/blankspace.go b/test-integ/topoutil/blankspace.go new file mode 100644 index 000000000000..000853b94278 --- /dev/null +++ b/test-integ/topoutil/blankspace.go @@ -0,0 +1,124 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package topoutil + +import ( + "bufio" + "context" + "encoding/json" + "fmt" + "io" + "net" + "net/http" + "net/url" + "strings" + "time" + + "github.com/rboyer/blankspace/blankpb" + "golang.org/x/net/http2" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +// GetBlankspaceNameViaHTTP calls a copy of blankspace once via HTTP and +// retrieves the self-identified name of the instance. +func GetBlankspaceNameViaHTTP( + ctx context.Context, + client *http.Client, + serverAddr string, + actualURL string, +) (string, error) { + url := fmt.Sprintf("http://%s/fetch?url=%s", serverAddr, + url.QueryEscape(actualURL), + ) + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + return "", err + } + + res, err := client.Do(req) + if err != nil { + return "", err + } + defer res.Body.Close() + + if res.StatusCode != http.StatusOK { + return "", fmt.Errorf("status code is not 200: %d", res.StatusCode) + } + + body, err := io.ReadAll(res.Body) + if err != nil { + return "", err + } + + var v struct { + Name string + } + if err := json.Unmarshal(body, &v); err != nil { + return "", err + } + + if _, useHTTP2 := client.Transport.(*http2.Transport); useHTTP2 { + if res.ProtoMajor < 2 { + return "", fmt.Errorf("should be using http > 1.x not %d", res.ProtoMajor) + } + } + + return v.Name, nil +} + +// GetBlankspaceNameViaGRPC calls a copy of blankspace once via gRPC and +// retrieves the self-identified name of the instance. +func GetBlankspaceNameViaGRPC(ctx context.Context, serverAddr string) (string, error) { + ctx, cancel := context.WithTimeout(ctx, 1*time.Second) + defer cancel() + + conn, err := grpc.DialContext(ctx, serverAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return "", err + } + defer conn.Close() + + client := blankpb.NewServerClient(conn) + + resp, err := client.Describe(ctx, &blankpb.DescribeRequest{}) + if err != nil { + return "", fmt.Errorf("grpc error from Describe: %w", err) + } + + return resp.GetName(), nil +} + +// GetBlankspaceNameViaTCP calls a copy of blankspace once via tcp and +// retrieves the self-identified name of the instance. +func GetBlankspaceNameViaTCP(ctx context.Context, serverAddr string) (string, error) { + ctx, cancel := context.WithTimeout(ctx, 1*time.Second) + defer cancel() + + d := net.Dialer{ + Timeout: 5 * time.Second, + KeepAlive: 250 * time.Millisecond, + } + + conn, err := d.DialContext(ctx, "tcp", serverAddr) + if err != nil { + return "", fmt.Errorf("tcp error dialing: %w", err) + } + defer conn.Close() + + if _, err := conn.Write([]byte("describe\n")); err != nil { + return "", fmt.Errorf("error sending tcp request: %w", err) + } + + scan := bufio.NewScanner(conn) + + if !scan.Scan() { + return "", fmt.Errorf("server did not reply") + } + + name := strings.TrimSpace(scan.Text()) + + return name, nil +} diff --git a/test-integ/topoutil/fixtures.go b/test-integ/topoutil/fixtures.go index 9b1f958f4451..49daac947c74 100644 --- a/test-integ/topoutil/fixtures.go +++ b/test-integ/topoutil/fixtures.go @@ -4,6 +4,7 @@ package topoutil import ( + "fmt" "strconv" "github.com/hashicorp/consul/testing/deployer/topology" @@ -11,23 +12,24 @@ import ( const HashicorpDockerProxy = "docker.mirror.hashicorp.services" -func NewFortioServiceWithDefaults( +func NewFortioWorkloadWithDefaults( cluster string, - sid topology.ServiceID, - nodeVersion topology.NodeVersion, - mut func(s *topology.Service), -) *topology.Service { + sid topology.ID, + mut func(*topology.Workload), +) *topology.Workload { const ( httpPort = 8080 grpcPort = 8079 + tcpPort = 8078 adminPort = 19000 ) sid.Normalize() - svc := &topology.Service{ + wrk := &topology.Workload{ ID: sid, Image: HashicorpDockerProxy + "/fortio/fortio", EnvoyAdminPort: adminPort, + Port: httpPort, CheckTCP: "127.0.0.1:" + strconv.Itoa(httpPort), Env: []string{ "FORTIO_NAME=" + cluster + "::" + sid.String(), @@ -36,28 +38,48 @@ func NewFortioServiceWithDefaults( "server", "-http-port", strconv.Itoa(httpPort), "-grpc-port", strconv.Itoa(grpcPort), + "-tcp-port", strconv.Itoa(tcpPort), "-redirect-port", "-disabled", }, } - if nodeVersion == topology.NodeVersionV2 { - svc.Ports = map[string]*topology.Port{ - // TODO(rb/v2): once L7 works in v2 switch these back - "http": {Number: httpPort, Protocol: "tcp"}, - "http-alt": {Number: httpPort, Protocol: "tcp"}, - "grpc": {Number: grpcPort, Protocol: "tcp"}, - // "http": {Number: httpPort, Protocol: "http"}, - // "http-alt": {Number: httpPort, Protocol: "http"}, - // "grpc": {Number: grpcPort, Protocol: "grpc"}, - } - } else { - svc.Port = httpPort + if mut != nil { + mut(wrk) + } + return wrk +} + +func NewBlankspaceWorkloadWithDefaults( + cluster string, + sid topology.ID, + mut func(*topology.Workload), +) *topology.Workload { + const ( + httpPort = 8080 + grpcPort = 8079 + tcpPort = 8078 + adminPort = 19000 + ) + sid.Normalize() + + wrk := &topology.Workload{ + ID: sid, + Image: HashicorpDockerProxy + "/rboyer/blankspace", + EnvoyAdminPort: adminPort, + Port: httpPort, + CheckTCP: "127.0.0.1:" + strconv.Itoa(httpPort), + Command: []string{ + "-name", cluster + "::" + sid.String(), + "-http-addr", fmt.Sprintf(":%d", httpPort), + "-grpc-addr", fmt.Sprintf(":%d", grpcPort), + "-tcp-addr", fmt.Sprintf(":%d", tcpPort), + }, } if mut != nil { - mut(svc) + mut(wrk) } - return svc + return wrk } func NewTopologyServerSet( @@ -96,9 +118,9 @@ func NewTopologyMeshGatewaySet( mutateFn func(i int, node *topology.Node), ) []*topology.Node { var out []*topology.Node - sid := topology.ServiceID{ + sid := topology.ID{ Name: "mesh-gateway", - Partition: ConfigEntryPartition(partition), + Partition: topology.DefaultToEmpty(partition), } for i := 1; i <= num; i++ { name := namePrefix + strconv.Itoa(i) @@ -107,7 +129,7 @@ func NewTopologyMeshGatewaySet( Kind: nodeKind, Partition: sid.Partition, Name: name, - Services: []*topology.Service{{ + Workloads: []*topology.Workload{{ ID: sid, Port: 8443, EnvoyAdminPort: 19000, diff --git a/test-integ/topoutil/http2.go b/test-integ/topoutil/http2.go new file mode 100644 index 000000000000..148074e5638f --- /dev/null +++ b/test-integ/topoutil/http2.go @@ -0,0 +1,32 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package topoutil + +import ( + "context" + "crypto/tls" + "net" + "net/http" + + "golang.org/x/net/http2" +) + +// EnableHTTP2 returns a new shallow copy of client that has been tweaked to do +// h2c (cleartext http2). +// +// Note that this clears the Client.Transport.Proxy trick because http2 and +// http proxies are incompatible currently in Go. +func EnableHTTP2(client *http.Client) *http.Client { + // Shallow copy, and swap the transport + client2 := *client + client = &client2 + client.Transport = &http2.Transport{ + AllowHTTP: true, + DialTLSContext: func(ctx context.Context, network, addr string, _ *tls.Config) (net.Conn, error) { + var d net.Dialer + return d.DialContext(ctx, network, addr) + }, + } + return client +} diff --git a/test-integ/topoutil/http_consul.go b/test-integ/topoutil/http_consul.go new file mode 100644 index 000000000000..27abc0b090d5 --- /dev/null +++ b/test-integ/topoutil/http_consul.go @@ -0,0 +1,50 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package topoutil + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "net/url" +) + +// RequestRegisterService registers a service at the given node address +// using consul http request. +// +// The service definition must be a JSON string. +func RequestRegisterService(clusterHttpCli *http.Client, nodeAddress string, serviceDefinition string, token string) error { + var js json.RawMessage + if err := json.Unmarshal([]byte(serviceDefinition), &js); err != nil { + return fmt.Errorf("failed to unmarshal service definition: %s", err) + } + + u, err := url.Parse(nodeAddress) + if err != nil { + return fmt.Errorf("failed to parse node address: %s", err) + } + u.Path = "/v1/agent/service/register" + + req, err := http.NewRequest(http.MethodPut, u.String(), bytes.NewBuffer(js)) + if err != nil { + return fmt.Errorf("failed to create request: %s", err) + } + + if token != "" { + req.Header.Set("X-Consul-Token", token) + } + + resp, err := clusterHttpCli.Do(req) + if err != nil { + return fmt.Errorf("failed to send request: %s", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("failed to register service: %s", resp.Status) + } + + return nil +} diff --git a/test-integ/topoutil/images.go b/test-integ/topoutil/images.go deleted file mode 100644 index 855ba8c2a9a3..000000000000 --- a/test-integ/topoutil/images.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package topoutil - -import ( - "os" - - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" - "github.com/hashicorp/consul/testing/deployer/topology" -) - -func TargetImages() topology.Images { - // Start with no preferences. - var images topology.Images - if !runningInCI() { - // Until 1.17 GAs, we want the pre-release versions for these tests, - // run outside of CI for convenience. - images = topology.Images{ - ConsulCE: HashicorpDockerProxy + "/hashicorppreview/consul:1.17-dev", - ConsulEnterprise: HashicorpDockerProxy + "/hashicorppreview/consul-enterprise:1.17-dev", - Dataplane: HashicorpDockerProxy + "/hashicorppreview/consul-dataplane:1.3-dev", - } - } - - // We want the image overridden by the local build produced by - // 'make test-compat-integ-setup' or 'make dev-docker'. - testImages := utils.TargetImages() - images = images.OverrideWith(testImages) - - return images -} - -func runningInCI() bool { - return os.Getenv("GITHUB_ACTIONS") != "" || os.Getenv("CI") != "" -} diff --git a/test-integ/topoutil/naming_shim.go b/test-integ/topoutil/naming_shim.go new file mode 100644 index 000000000000..8a4edc8f9e8c --- /dev/null +++ b/test-integ/topoutil/naming_shim.go @@ -0,0 +1,26 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package topoutil + +import ( + "github.com/hashicorp/consul/testing/deployer/topology" +) + +// Deprecated: NewFortioWorkloadWithDefaults +func NewFortioServiceWithDefaults( + cluster string, + sid topology.ID, + mut func(*topology.Workload), +) *topology.Workload { + return NewFortioWorkloadWithDefaults(cluster, sid, mut) +} + +// Deprecated: NewBlankspaceWorkloadWithDefaults +func NewBlankspaceServiceWithDefaults( + cluster string, + sid topology.ID, + mut func(*topology.Workload), +) *topology.Workload { + return NewBlankspaceWorkloadWithDefaults(cluster, sid, mut) +} diff --git a/test-integ/upgrade/basic/common.go b/test-integ/upgrade/basic/common.go new file mode 100644 index 000000000000..0b4bff8bf1b8 --- /dev/null +++ b/test-integ/upgrade/basic/common.go @@ -0,0 +1,254 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package upgrade + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/test-integ/topoutil" + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" + "github.com/hashicorp/consul/testing/deployer/sprawl" + "github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest" + "github.com/hashicorp/consul/testing/deployer/topology" +) + +// The commonTopo comprises 3 agent servers and 3 nodes to run workload +// - workload node 1: static-server +// - workload node 2: static-client +// - workload node 3 (disabled initially): static-server +// +// The post upgrade validation enables workload node 3 to test upgraded +// cluster +type commonTopo struct { + Cfg *topology.Config + + Sprawl *sprawl.Sprawl + Assert *topoutil.Asserter + + StaticServerSID topology.ID + StaticClientSID topology.ID + + StaticServerWorkload *topology.Workload + StaticClientWorkload *topology.Workload + + // node index of static-server one + StaticServerInstOne int + // node index of static-server two + StaticServerInstTwo int +} + +func NewCommonTopo(t *testing.T) *commonTopo { + t.Helper() + return newCommonTopo(t) +} + +func newCommonTopo(t *testing.T) *commonTopo { + t.Helper() + + ct := &commonTopo{} + staticServerSID := topology.NewID("static-server", "default", "default") + staticClientSID := topology.NewID("static-client", "default", "default") + + cfg := &topology.Config{ + Images: topology.Images{ + // ConsulEnterprise: "hashicorp/consul-enterprise:local", + }, + Networks: []*topology.Network{ + {Name: "dc1"}, + }, + Clusters: []*topology.Cluster{ + { + Name: "dc1", + Nodes: []*topology.Node{ + { + Kind: topology.NodeKindServer, + Images: utils.LatestImages(), + Name: "dc1-server1", + Addresses: []*topology.Address{ + {Network: "dc1"}, + }, + Meta: map[string]string{ + "build": "0.0.1", + }, + }, + { + Kind: topology.NodeKindServer, + Images: utils.LatestImages(), + Name: "dc1-server2", + Addresses: []*topology.Address{ + {Network: "dc1"}, + }, + Meta: map[string]string{ + "build": "0.0.1", + }, + }, + { + Kind: topology.NodeKindServer, + Images: utils.LatestImages(), + Name: "dc1-server3", + Addresses: []*topology.Address{ + {Network: "dc1"}, + }, + Meta: map[string]string{ + "build": "0.0.1", + }, + }, + { + Kind: topology.NodeKindDataplane, + Name: "dc1-client1", + Workloads: []*topology.Workload{ + { + ID: staticServerSID, + Image: "docker.mirror.hashicorp.services/fortio/fortio", + Port: 8080, + EnvoyAdminPort: 19000, + CheckTCP: "127.0.0.1:8080", + Command: []string{ + "server", + "-http-port", "8080", + "-redirect-port", "-disabled", + }, + }, + }, + }, + { + Kind: topology.NodeKindDataplane, + Name: "dc1-client2", + Workloads: []*topology.Workload{ + { + ID: staticClientSID, + Image: "docker.mirror.hashicorp.services/fortio/fortio", + Port: 8080, + EnvoyAdminPort: 19000, + CheckTCP: "127.0.0.1:8080", + Command: []string{ + "server", + "-http-port", "8080", + "-redirect-port", "-disabled", + }, + Upstreams: []*topology.Upstream{ + { + ID: staticServerSID, + LocalPort: 5000, + }, + }, + }, + }, + }, + // Client3 for second static-server + { + Kind: topology.NodeKindDataplane, + Name: "dc1-client3", + Disabled: true, + Workloads: []*topology.Workload{ + { + ID: staticServerSID, + Image: "docker.mirror.hashicorp.services/fortio/fortio", + Port: 8080, + EnvoyAdminPort: 19000, + CheckTCP: "127.0.0.1:8080", + Command: []string{ + "server", + "-http-port", "8080", + "-redirect-port", "-disabled", + }, + }, + }, + }, + }, + Enterprise: utils.IsEnterprise(), + InitialConfigEntries: []api.ConfigEntry{ + &api.ProxyConfigEntry{ + Kind: api.ProxyDefaults, + Name: "global", + Partition: topoutil.ConfigEntryPartition("default"), + Config: map[string]any{ + "protocol": "http", + }, + }, + &api.ServiceConfigEntry{ + Kind: api.ServiceDefaults, + Name: "static-server", + Partition: topoutil.ConfigEntryPartition("default"), + }, + &api.ServiceIntentionsConfigEntry{ + Kind: api.ServiceIntentions, + Name: "static-server", + Partition: topoutil.ConfigEntryPartition("default"), + Sources: []*api.SourceIntention{ + { + Name: "static-client", + Action: api.IntentionActionAllow}, + }, + }, + }, + }, + }, + } + + ct.Cfg = cfg + ct.StaticClientSID = staticClientSID + ct.StaticServerSID = staticServerSID + + ct.StaticServerInstOne = 3 + ct.StaticServerInstTwo = 5 + return ct +} + +// PostUpgradeValidation - replace the existing static-server with a new +// instance; verify the connection between static-client and the new instance +func (ct *commonTopo) PostUpgradeValidation(t *testing.T) { + t.Helper() + t.Log("Take down old static-server") + cfg := ct.Sprawl.Config() + cluster := cfg.Cluster("dc1") + cluster.Nodes[ct.StaticServerInstOne].Disabled = true // client 1 -- static-server + require.NoError(t, ct.Sprawl.RelaunchWithPhase(cfg, sprawl.LaunchPhaseRegular)) + // verify static-server is down + ct.Assert.HTTPStatus(t, ct.StaticServerWorkload, ct.StaticServerWorkload.Port, 504) + + // Add a new static-server + t.Log("Add a new static server") + cfg = ct.Sprawl.Config() + cluster = cfg.Cluster("dc1") + cluster.Nodes[ct.StaticServerInstTwo].Disabled = false // client 3 -- new static-server + require.NoError(t, ct.Sprawl.RelaunchWithPhase(cfg, sprawl.LaunchPhaseRegular)) + // Ensure the static-client connected to the new static-server + ct.Assert.FortioFetch2HeaderEcho(t, ct.StaticClientWorkload, &topology.Upstream{ + ID: ct.StaticServerSID, + LocalPort: 5000, + }) +} + +// calls sprawltest.Launch followed by validating the connection between +// static-client and static-server +func (ct *commonTopo) Launch(t *testing.T) { + t.Helper() + if ct.Sprawl != nil { + t.Fatalf("Launch must only be called once") + } + ct.Sprawl = sprawltest.Launch(t, ct.Cfg) + ct.Assert = topoutil.NewAsserter(ct.Sprawl) + + staticServerWorkload := ct.Sprawl.Topology().Clusters["dc1"].WorkloadByID( + topology.NewNodeID("dc1-client1", "default"), + ct.StaticServerSID, + ) + ct.Assert.HTTPStatus(t, staticServerWorkload, staticServerWorkload.Port, 200) + + staticClientWorkload := ct.Sprawl.Topology().Clusters["dc1"].WorkloadByID( + topology.NewNodeID("dc1-client2", "default"), + ct.StaticClientSID, + ) + ct.Assert.FortioFetch2HeaderEcho(t, staticClientWorkload, &topology.Upstream{ + ID: ct.StaticServerSID, + LocalPort: 5000, + }) + + ct.StaticServerWorkload = staticServerWorkload + ct.StaticClientWorkload = staticClientWorkload +} diff --git a/test-integ/upgrade/basic/upgrade_basic_test.go b/test-integ/upgrade/basic/upgrade_basic_test.go new file mode 100644 index 000000000000..c3df91bb45d2 --- /dev/null +++ b/test-integ/upgrade/basic/upgrade_basic_test.go @@ -0,0 +1,39 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package upgrade + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" + "github.com/hashicorp/consul/testing/deployer/sprawl" +) + +// Test_Upgrade_Standard_Basic_Agentless tests upgrading the agent servers +// of a class and validate service mesh after upgrade +// +// Refer to common.go for the detail of the topology +func Test_Upgrade_Standard_Basic_Agentless(t *testing.T) { + t.Parallel() + + ct := NewCommonTopo(t) + ct.Launch(t) + + t.Log("Start standard upgrade ...") + sp := ct.Sprawl + cfg := sp.Config() + require.NoError(t, ct.Sprawl.LoadKVDataToCluster("dc1", 1, &api.WriteOptions{})) + require.NoError(t, sp.Upgrade(cfg, "dc1", sprawl.UpgradeTypeStandard, utils.TargetImages(), nil, nil)) + t.Log("Finished standard upgrade ...") + + // verify data is not lost + data, err := ct.Sprawl.GetKV("dc1", "key-0", &api.QueryOptions{}) + require.NoError(t, err) + require.NotNil(t, data) + + ct.PostUpgradeValidation(t) +} diff --git a/test-integ/upgrade/l7_traffic_management/common.go b/test-integ/upgrade/l7_traffic_management/common.go new file mode 100644 index 000000000000..f60e995b71a7 --- /dev/null +++ b/test-integ/upgrade/l7_traffic_management/common.go @@ -0,0 +1,228 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package l7_traffic_management + +import ( + "fmt" + "testing" + + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/test-integ/topoutil" + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" + "github.com/hashicorp/consul/testing/deployer/sprawl" + "github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest" + "github.com/hashicorp/consul/testing/deployer/topology" +) + +type commonTopo struct { + Cfg *topology.Config + + Sprawl *sprawl.Sprawl + Assert *topoutil.Asserter + + StaticServerSID topology.ID + StaticClientSID topology.ID + + StaticServerWorkload *topology.Workload + StaticClientWorkload *topology.Workload +} + +const ( + defaultNamespace = "default" + defaultPartition = "default" + dc1 = "dc1" +) + +var ( + staticServerSID = topology.NewID("static-server", defaultNamespace, defaultPartition) + staticClientSID = topology.NewID("static-client", defaultNamespace, defaultPartition) +) + +func NewCommonTopo(t *testing.T) *commonTopo { + t.Helper() + return newCommonTopo(t) +} + +// create below topology +// consul server +// - consul server on node dc1-server1 +// +// dataplane +// - workload(fortio) static-server on node dc1-client1 +// - workload(fortio) static-client on node dc1-client2 with upstream to static-server +// - static-client, static-server are registered at 2 agentless nodes. +// +// Intentions +// - static-client has upstream to static-server +func newCommonTopo(t *testing.T) *commonTopo { + t.Helper() + + ct := &commonTopo{} + + cfg := &topology.Config{ + Images: topology.Images{ + // ConsulEnterprise: "hashicorp/consul-enterprise:local", + }, + Networks: []*topology.Network{ + {Name: dc1}, + }, + Clusters: []*topology.Cluster{ + { + Name: dc1, + Nodes: []*topology.Node{ + // consul server on dc1-server1 + { + Kind: topology.NodeKindServer, + Images: utils.LatestImages(), + Name: "dc1-server1", + Addresses: []*topology.Address{ + {Network: dc1}, + }, + Meta: map[string]string{ + "build": "0.0.1", + }, + }, + // static-server-v1 on dc1-client1 + { + Kind: topology.NodeKindDataplane, + Name: "dc1-client1", + Workloads: []*topology.Workload{ + { + ID: staticServerSID, + Image: "docker.mirror.hashicorp.services/fortio/fortio", + Port: 8080, + EnvoyAdminPort: 19000, + CheckTCP: "127.0.0.1:8080", + Meta: map[string]string{"version": "v2"}, + Env: []string{ + "FORTIO_NAME=" + dc1 + "::" + staticServerSID.String(), + }, + Command: []string{ + "server", + "-http-port", "8080", + "-redirect-port", "-disabled", + }, + }, + }, + }, + // static-client on dc1-client2 with upstream to static-server + { + Kind: topology.NodeKindDataplane, + Name: "dc1-client2", + Workloads: []*topology.Workload{ + { + ID: staticClientSID, + Image: "docker.mirror.hashicorp.services/fortio/fortio", + Port: 8080, + EnvoyAdminPort: 19000, + CheckTCP: "127.0.0.1:8080", + Command: []string{ + "server", + "-http-port", "8080", + "-redirect-port", "-disabled", + }, + Upstreams: []*topology.Upstream{ + { + ID: staticServerSID, // static-server + LocalPort: 5000, + }, + }, + }, + }, + }, + }, + Enterprise: utils.IsEnterprise(), + InitialConfigEntries: []api.ConfigEntry{ + &api.ProxyConfigEntry{ + Kind: api.ProxyDefaults, + Name: "global", + Partition: topoutil.ConfigEntryPartition("default"), + Config: map[string]any{ + "protocol": "http", + }, + }, + &api.ServiceConfigEntry{ + Kind: api.ServiceDefaults, + Name: staticServerSID.Name, + Partition: topoutil.ConfigEntryPartition("default"), + }, + &api.ServiceIntentionsConfigEntry{ + Kind: api.ServiceIntentions, + Name: staticServerSID.Name, + Partition: topoutil.ConfigEntryPartition("default"), + Sources: []*api.SourceIntention{ + { + Name: staticClientSID.Name, + Action: api.IntentionActionAllow}, + }, + }, + }, + }, + }, + } + + ct.Cfg = cfg + ct.StaticClientSID = staticClientSID + ct.StaticServerSID = staticServerSID + + return ct +} + +func (ct *commonTopo) Launch(t *testing.T) { + t.Helper() + if ct.Sprawl != nil { + t.Fatalf("Launch must only be called once") + } + ct.Sprawl = sprawltest.Launch(t, ct.Cfg) + ct.ValidateWorkloads(t) +} + +// ValidateWorkloads validates below +// - static server, static client workloads are reachable and, static server, static client services are healthy +// - static client and its sidecar exists in catalog +// - envoy is running for static server, static client workloads +// - envoy cert uri is present in for static server, static client workloads +func (ct *commonTopo) ValidateWorkloads(t *testing.T) { + + t.Helper() + ct.Assert = topoutil.NewAsserter(ct.Sprawl) + cluster := ct.Sprawl.Topology().Clusters[dc1] + node := cluster.Nodes[0] + + staticServerWorkload := cluster.WorkloadByID( + topology.NewNodeID("dc1-client1", defaultPartition), + ct.StaticServerSID, + ) + ct.Assert.HTTPStatus(t, staticServerWorkload, staticServerWorkload.Port, 200) + ct.Assert.HealthServiceEntries(t, cluster.Name, node, ct.StaticServerSID.Name, true, &api.QueryOptions{}, 1, 0) + + staticClientWorkload := cluster.WorkloadByID( + topology.NewNodeID("dc1-client2", defaultPartition), + ct.StaticClientSID, + ) + + ct.Assert.HealthServiceEntries(t, cluster.Name, node, ct.StaticClientSID.Name, true, &api.QueryOptions{}, 1, 0) + + // check the service exists in catalog + svcs := cluster.WorkloadsByID(ct.StaticClientSID) + client := svcs[0] + upstream := client.Upstreams[0] + ct.Assert.CatalogServiceExists(t, cluster.Name, upstream.ID.Name, utils.CompatQueryOpts(&api.QueryOptions{ + Partition: upstream.ID.Partition, + Namespace: upstream.ID.Namespace, + })) + ct.Assert.CatalogServiceExists(t, cluster.Name, fmt.Sprintf("%s-sidecar-proxy", upstream.ID.Name), utils.CompatQueryOpts(&api.QueryOptions{ + Partition: upstream.ID.Partition, + Namespace: upstream.ID.Namespace, + })) + + ct.StaticServerWorkload = staticServerWorkload + ct.StaticClientWorkload = staticClientWorkload + + ct.Assert.AssertEnvoyRunningWithClient(t, ct.StaticServerWorkload) + ct.Assert.AssertEnvoyRunningWithClient(t, ct.StaticClientWorkload) + + ct.Assert.AssertEnvoyPresentsCertURIWithClient(t, ct.StaticServerWorkload) + ct.Assert.AssertEnvoyPresentsCertURIWithClient(t, ct.StaticClientWorkload) +} diff --git a/test-integ/upgrade/l7_traffic_management/resolver_test.go b/test-integ/upgrade/l7_traffic_management/resolver_test.go new file mode 100644 index 000000000000..17c4eefaf068 --- /dev/null +++ b/test-integ/upgrade/l7_traffic_management/resolver_test.go @@ -0,0 +1,116 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package l7_traffic_management + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" + "github.com/hashicorp/consul/testing/deployer/sprawl" + "github.com/hashicorp/consul/testing/deployer/topology" +) + +// TestTrafficManagement_ResolverDefaultSubset_Agentless tests resolver directs traffic to default subset - agentless +// - Create a topology with static-server (meta version V2) and static-client (with static-server upstream) +// - Create a service resolver for static-server with V2 as default subset +// - Resolver directs traffic to the default subset, which is V2 +// - Do a standard upgrade and validate the traffic is still directed to V2 +// - Change the default version in serviceResolver to v1 and the client to server request fails +// since we only have V2 instance +// - Change the default version in serviceResolver to v2 and the client to server request succeeds +// (V2 instance is available and traffic is directed to it) +func TestTrafficManagement_ResolverDefaultSubset_Agentless(t *testing.T) { + t.Parallel() + + ct := NewCommonTopo(t) + ct.Cfg.Clusters[0].InitialConfigEntries = append(ct.Cfg.Clusters[0].InitialConfigEntries, + newServiceResolver(staticServerSID.Name, "v2")) + + ct.Launch(t) + + resolverV2AssertFn := func() { + cluster := ct.Sprawl.Topology().Clusters[dc1] + staticClientWorkload := cluster.WorkloadByID( + topology.NewNodeID("dc1-client2", defaultPartition), + ct.StaticClientSID, + ) + ct.Assert.FortioFetch2HeaderEcho(t, staticClientWorkload, &topology.Upstream{ + ID: ct.StaticServerSID, + LocalPort: 5000, + }) + ct.Assert.FortioFetch2FortioName(t, staticClientWorkload, &topology.Upstream{ + ID: ct.StaticServerSID, + LocalPort: 5000, + }, dc1, staticServerSID) + ct.Assert.UpstreamEndpointStatus(t, staticClientWorkload, "v2.static-server.default", "HEALTHY", 1) + } + resolverV2AssertFn() + + t.Log("Start standard upgrade ...") + sp := ct.Sprawl + cfg := sp.Config() + require.NoError(t, ct.Sprawl.LoadKVDataToCluster("dc1", 1, &api.WriteOptions{})) + require.NoError(t, sp.Upgrade(cfg, "dc1", sprawl.UpgradeTypeStandard, utils.TargetImages(), nil, nil)) + t.Log("Finished standard upgrade ...") + + // verify data is not lost + data, err := ct.Sprawl.GetKV("dc1", "key-0", &api.QueryOptions{}) + require.NoError(t, err) + require.NotNil(t, data) + + ct.ValidateWorkloads(t) + resolverV2AssertFn() + + // Change the default version in serviceResolver to v1 and the client to server request fails + cluster := ct.Sprawl.Topology().Clusters[dc1] + cl, err := ct.Sprawl.APIClientForCluster(cluster.Name, "") + require.NoError(t, err) + configEntry := cl.ConfigEntries() + _, err = configEntry.Delete(api.ServiceResolver, staticServerSID.Name, nil) + require.NoError(t, err) + _, _, err = configEntry.Set(newServiceResolver(staticServerSID.Name, "v1"), nil) + require.NoError(t, err) + ct.ValidateWorkloads(t) + + resolverV1AssertFn := func() { + cluster := ct.Sprawl.Topology().Clusters[dc1] + staticClientWorkload := cluster.WorkloadByID( + topology.NewNodeID("dc1-client2", defaultPartition), + ct.StaticClientSID, + ) + ct.Assert.FortioFetch2ServiceUnavailable(t, staticClientWorkload, &topology.Upstream{ + ID: ct.StaticServerSID, + LocalPort: 5000, + }) + } + resolverV1AssertFn() + + // Change the default version in serviceResolver to v2 and the client to server request succeeds + configEntry = cl.ConfigEntries() + _, err = configEntry.Delete(api.ServiceResolver, staticServerSID.Name, nil) + require.NoError(t, err) + _, _, err = configEntry.Set(newServiceResolver(staticServerSID.Name, "v2"), nil) + require.NoError(t, err) + ct.ValidateWorkloads(t) + resolverV2AssertFn() +} + +func newServiceResolver(serviceResolverName string, defaultSubset string) api.ConfigEntry { + return &api.ServiceResolverConfigEntry{ + Kind: api.ServiceResolver, + Name: serviceResolverName, + DefaultSubset: defaultSubset, + Subsets: map[string]api.ServiceResolverSubset{ + "v1": { + Filter: "Service.Meta.version == v1", + }, + "v2": { + Filter: "Service.Meta.version == v2", + }, + }, + } +} diff --git a/test/CA-GENERATION.md b/test/CA-GENERATION.md index 2e278f2b0a55..686064df00b0 100644 --- a/test/CA-GENERATION.md +++ b/test/CA-GENERATION.md @@ -16,6 +16,22 @@ cd test/ca/ rm -rf *.pem *.crt *.key && ./generate.sh ``` +It also possible for the root CA to expire. +In this case, use the instructions [here](Instructions from https://langui.sh/2009/01/18/openssl-self-signed-ca/) to regenerate root.cer and privkey.pem. +Configure the cert as follows: + +``` +Country Name (2 letter code) [AU]:US +State or Province Name (full name) [Some-State]:CA +Locality Name (eg, city) []:San Francisco +Organization Name (eg, company) [Internet Widgits Pty Ltd]:HashiCorp Test Cert +Organizational Unit Name (eg, section) []:Dev +Common Name (e.g. server FQDN or YOUR name) []:test.internal +Email Address []:test@internal.com +``` + +Ensure that you run `./test/ca/generate.sh` after recreating the root CA. + ## Hostname certificates if tests like `TestNewDialer_WithALPNWrapper` (or any other test using certificates located in `./test/hostname` ) are failing because of expired certificates, use `./generate.sh` script to regenerate a new set of certificate. @@ -24,4 +40,22 @@ if tests like `TestNewDialer_WithALPNWrapper` (or any other test using certifica cd test/hostname/ # Avoid deleting CertAuth.crt and privkey.pem since they're referenced in myca.conf rm -rf "[Bonnie|Betty|Bob|Alice].crt" *.key && ./generate.sh +``` + +It also possible for the root CA to expire. +In this case, use the instructions [here](Instructions from https://langui.sh/2009/01/18/openssl-self-signed-ca/) to regenerate CertAuth.crt and privkey.pem. + +```bash +openssl req -newkey rsa:2048 -days 3650 -x509 -nodes -out CertAuth.crt +``` + +Configure the cert as follows: +``` +Country Name (2 letter code) [AU]:US +State or Province Name (full name) [Some-State]:CA +Locality Name (eg, city) []:San Francisco +Organization Name (eg, company) [Internet Widgits Pty Ltd]:HashiCorp Test Cert +Organizational Unit Name (eg, section) []:Test +Common Name (e.g. server FQDN or YOUR name) []:CertAuth +Email Address []:test@internal.com ``` \ No newline at end of file diff --git a/test/ca/certindex b/test/ca/certindex index 52333887dd37..5d31a191bec9 100644 --- a/test/ca/certindex +++ b/test/ca/certindex @@ -7,3 +7,25 @@ V 180606021919Z 0F unknown /CN=testco.internal/ST=California/C=US/emailAddress= V 21180418091009Z 10 unknown /CN=testco.internal/ST=California/C=US/emailAddress=james@hashicorp.com/O=End Point/OU=Testing V 21220322142538Z 11 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing V 21221008151329Z 12 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009155124Z 13 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009165428Z 14 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009165428Z 15 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009170507Z 16 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009170507Z 17 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009170704Z 18 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009170704Z 19 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009170742Z 1A unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009170742Z 1B unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009170931Z 1C unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009170932Z 1D unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009171405Z 1E unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009171405Z 1F unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009171500Z 20 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009171500Z 21 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009171525Z 22 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009171525Z 23 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009171817Z 24 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009171817Z 25 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009171908Z 26 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009171908Z 27 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009172016Z 28 unknown /CN=testco.internal/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing diff --git a/test/ca/generate.sh b/test/ca/generate.sh index 7159431f4c49..0c82d808aaf3 100755 --- a/test/ca/generate.sh +++ b/test/ca/generate.sh @@ -7,3 +7,7 @@ set -e openssl req -new -sha256 -nodes -out ../key/ourdomain.csr -newkey rsa:2048 -keyout ../key/ourdomain.key -config ../key/ourdomain.cfg openssl ca -batch -config myca.conf -notext -in ../key/ourdomain.csr -out ../key/ourdomain.cer rm ../key/ourdomain.csr + +openssl req -new -sha256 -nodes -out ../key/ourdomain_server.csr -newkey rsa:2048 -keyout ../key/ourdomain_server.key -config ../key/ourdomain_server.cfg +openssl ca -batch -config myca.conf -notext -in ../key/ourdomain_server.csr -out ../key/ourdomain_server.cer -extensions v3_req -extfile ../key/ourdomain_server.cfg +rm ../key/ourdomain_server.csr diff --git a/test/ca/privkey.pem b/test/ca/privkey.pem index 3f22711a1162..bc93012d42d4 100644 --- a/test/ca/privkey.pem +++ b/test/ca/privkey.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAxrs6JK4NpiOItxrpNR/1ppUUmH7p2BgLCBZ6eHdclle9J56i -68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsUd0HejRqfHRMtg2O+UQkv4Z66 -+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcGxcFZzTRFFZt2vPnyHj8cHcaF -o/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvgU2jQuC7Fhnl33Zd3B6d3mQH6 -O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/fpFIIcHSiHRfoqHLGsGg+3swI -d/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQIDAQABAoIBABreo6zj76p/8XM4 -a0GokZE1ZPR9bGawUYWFbIevM9CMCmI5+7M/RoHbBQJKDOapJsJviNkoSdpllxcz -4CpFhXAiVNEPEeUoLU1EE4pJSSkxwcySppsiTYNFi5rMomgwe2qeuiKhgZNl/AEt -82dubjwxW3QPgXHSWGjkfTht3wOhrczA8xyEjc9Bsad2ooA9IQk+VXYlPZXyXjs1 -WwLYHmcSfveauLliLXeVU2Ux5PPwyreKMhyAfSHVQCycxK008u8WPy8nkAlpxKMC -UwCN+JKl69WCCA3CxXgM83zz4pXvB4EyMr8aTiqmOID8RIIrPcjCmVJki6KbJ9WG -S2CQVG0CgYEA5kVACrnjLtov426ZNifF2zUXu9x//7D6GkbJxzZLwXP/BJFcEOdQ -Fnjcs3s7wYh/wdTnEcQVWSJSAqnRt98c9yAXVnG5z1M0DYpAsY8xrdhEitxOf2oB -2cbvi4+cvUuUxk1hgva18UCT23aLP+iY2+t/ydBXAZ9kq1zz5CcpEBMCgYEA3O/R -g1Y9O36XxBmSYnkoCF5yGrPunnKKNBJc/WA7pTkQFYHr64Y/h5EKubzHD/VEd1Li -nDuGYxVMewf+5pHUhqSdpZtTxv25hjOsqLf5o5wm18JThGifs2zEVCTJOPti5n2M -RHakxuq1I625/QHidLBTQYuEBS/vywhapfaSaD8CgYEAhd1OPK4R30PiQRIjqXL3 -t9ampISsOKXWz33FgbUT1zOq1in23rDKQzYh/4ktlPXYZ4NwjUhzrKyiBoBYtc7T -1OpoBs34Wgmhohl0QIThOZIXTq6CR9oFl2fqDDUBxp3wsFN905e+77A+BIBmtVFv -w7GlSVp/qibSbDiOZF1LptcCgYB8sJBi+jnmqOSIVRJLpysTxhHJxkDmhahACRkY -Gsau0cylBsUaEJMsNIyEFOmXtQml+k5QdDu9EdkvGm0evbDfKGqce1RF2w5okiNg -uSwXzVoSrOartMxk2/7VqkkycpX3lWWjgf4vEWmXsEVmaDjhOF5UgKPKtao0wQs/ -3S/1ywKBgAIGgOuvL/GBcGqLikHLC+cputMvBAuE/tJnFHPxFoobskocVsMKbDTy -NYF7uPlzSGGClZsjE6DQyyGf5E9/U+EdwDKZwHYGCkzVjplUBo0BT3EN0vcc9jB/ -ML9Ta4ETPyf66BhSVcD+eeNipPFAul0Q7uZhErH1zr1evTy8XXyI ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCIA00iG5IveRzZ +wf2P1Laih3eoiK2Wl1Re22cz2Pcpf6gb7agPguwU5Hco0DWzsnmek2Qyw9gloroX +1t7LbTW2rxbK1hP7PkFCwSxi9u8MZDaLF3a79bwbsYZzf3toeoz8DCBxo9bBSSAC +j4uI/S+lUjMctQrK1nFjGoNUHfxioXPwIJH+TS/76TiZPu3Zj6kN6taVFNe3ISBN +XW6Vg8E3koz+9Bwv0a6Ty7oFRoJXpsud1k/83Iy288jhYDuB56+ypUmcCNqGT+e0 +Bn/VXHx26GXTx97cXSLJE+o+JrHZaI1TcQUL2Z5DJZVJRUg/wtcXggoMLVI1O0en +Jm2jdmLXAgMBAAECggEAPSMSwFKZVsp/a+h1g/nu8EapRDHPqWGzdIH1tUoA63/s +vkUI5pQIb2m0oD1a7j+6yEtjXihHF7+6G24jrlgULV4thhZNXAFDT3DKdV+e2ziO +hd4RqnJOUDpvf6odfDyd88u1p68oILCweUYxx+1axdqZi/1a8QsMY6ouvxhNcr2N +MLOBMS9G/q4GKObggmTbBcZnZWYeNHqMv6CZXYlbY8NoOKiaI9Xw9dOQWKZFWgOh +zdiLgUPRmeugOLfJWI2iqHHmjXzsz3tNT1B7TuD8QitSXmqvAfc/HD+QmOJOJVN8 +eB2+nqY1hoE8tsTGhZpmHFKAfg5glWcswblDxIG7lQKBgQC/37gpaJaGFA8k7tDr +jrmvZXmPPozdj2kzio2GrYvEbfHBqWV7y9MapTIZjRURqa7rLXWtGYuv6+bLfwtD +HrkDGWsjlrvkUjZXCqyYx1HfRAdEsMr/0kVqIVJaAO9kJJA6izno2XRpKMj6+sdk +bGCbDveoDSY/vSWwd0ERqQFpVQKBgQC1eD7Ij96g2dJGQIJOQD1Efyxk9dJ+ocY6 +F+zZP7qgbED2nFysNtJ2wJyE6B4PnuUwpk5HkHuE+glgtcMUKsHPcynhaIRJBZfk +UQ+GyCKQItPzT6wa8sQXMQvsIk2opwj/uGkJn1vZ1jPIdLCIqqqhcQ53dMSPgEkf +PL1m4LmrewKBgDHgafL5qQc5d6ZWHiDdfQ9HBY5i6CNAAEzRm3CC9G4fVlTNQAAq +P7oRbzCNKAjrXvjrXEee+FzGqbwETl0oQ1e2587chAMaC94cfDlKttGe0XTdsCdH +9ZtdBhc3XwNdLdDKGEebH1OmsnfrcKF+Oq6T+XTJ1kODW6S/mz6H/EHxAoGAbsLr +Bz2Q8/qfdpOvNRXOj31T2neUOAiD1jd+MAfO4FXSvPMpOU/o2+SqZBDNMFmaqDwJ +sXKFgd+fU7D9VdTXIMi4+kTx4SQR1qCHaovDVNh9J5gsgvJEL6eXEFTLs7HoMzUa +n23uASLVzncyvOf2Z716x/y0cKYre252aFGn4fsCgYA+003BZnT9kMj1gpd/F3JS +JzFl10Yhj1hfyUu2pI6GLobj2VI3rEKL9UdzCTrEkLXyW1Js6DwT80mHIlJstzgZ +hJsBus6mSap+IZi/hKLS+xgculy0xlXzwNMmEid8GyzSPoHNXRQ233nANjKaRuvT +LG6wHDbfK+WVa3BlFKz8jA== +-----END PRIVATE KEY----- diff --git a/test/ca/root.cer b/test/ca/root.cer index ae9fb00b1c3c..2cdea8d2e9ee 100644 --- a/test/ca/root.cer +++ b/test/ca/root.cer @@ -1,28 +1,24 @@ -----BEGIN CERTIFICATE----- -MIIEtzCCA5+gAwIBAgIJAIewRMI8OnvTMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD -VQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHDAa -BgNVBAoTE0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsTA0RldjEWMBQGA1UE -AxMNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5j -b20wHhcNMTQwNDA3MTkwMTA4WhcNMjQwNDA0MTkwMTA4WjCBmDELMAkGA1UEBhMC -VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQK -ExNIYXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRl -c3QuaW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrs6JK4NpiOItxrpNR/1ppUU -mH7p2BgLCBZ6eHdclle9J56i68adt8J85zaqphCfz6VDP58DsFx+N50PZyjQaDsU -d0HejRqfHRMtg2O+UQkv4Z66+Vo+gc6uGuANi2xMtSYDVTAqqzF48OOPQDgYkzcG -xcFZzTRFFZt2vPnyHj8cHcaFo/NMNVh7C3yTXevRGNm9u2mrbxCEeiHzFC2WUnvg -U2jQuC7Fhnl33Zd3B6d3mQH6O23ncmwxTcPUJe6xZaIRrDuzwUcyhLj5Z3faag/f -pFIIcHSiHRfoqHLGsGg+3swId/zVJSSDHr7pJUu7Cre+vZa63FqDaooqvnisrQID -AQABo4IBADCB/TAdBgNVHQ4EFgQUo/nrOfqvbee2VklVKIFlyQEbuJUwgc0GA1Ud -IwSBxTCBwoAUo/nrOfqvbee2VklVKIFlyQEbuJWhgZ6kgZswgZgxCzAJBgNVBAYT -AlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEcMBoGA1UE -ChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMDRGV2MRYwFAYDVQQDEw10 -ZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFsLmNvbYIJ -AIewRMI8OnvTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADa9fV9h -gjapBlkNmu64WX0Ufub5dsJrdHS8672P30S7ILB7Mk0W8sL65IezRsZnG898yHf9 -2uzmz5OvNTM9K380g7xFlyobSVq+6yqmmSAlA/ptAcIIZT727P5jig/DB7fzJM3g -jctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp -lFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/ -POLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r -wlW975rYa1ZqEdA= +MIIEEzCCAvugAwIBAgIUIYIXKNRBFBPuuOit2D2CfVJAoDAwDQYJKoZIhvcNAQEL +BQAwgZgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZy +YW5jaXNjbzEcMBoGA1UECgwTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECwwD +RGV2MRYwFAYDVQQDDA10ZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0 +QGludGVybmFsLmNvbTAeFw0yMzExMDIxNTUwMjlaFw0zMzEwMzAxNTUwMjlaMIGY +MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFuY2lz +Y28xHDAaBgNVBAoME0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsMA0RldjEW +MBQGA1UEAwwNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRl +cm5hbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCIA00iG5Iv +eRzZwf2P1Laih3eoiK2Wl1Re22cz2Pcpf6gb7agPguwU5Hco0DWzsnmek2Qyw9gl +oroX1t7LbTW2rxbK1hP7PkFCwSxi9u8MZDaLF3a79bwbsYZzf3toeoz8DCBxo9bB +SSACj4uI/S+lUjMctQrK1nFjGoNUHfxioXPwIJH+TS/76TiZPu3Zj6kN6taVFNe3 +ISBNXW6Vg8E3koz+9Bwv0a6Ty7oFRoJXpsud1k/83Iy288jhYDuB56+ypUmcCNqG +T+e0Bn/VXHx26GXTx97cXSLJE+o+JrHZaI1TcQUL2Z5DJZVJRUg/wtcXggoMLVI1 +O0enJm2jdmLXAgMBAAGjUzBRMB0GA1UdDgQWBBTmrmqnZIdFOj6vhCUAJKLZNUDw +FDAfBgNVHSMEGDAWgBTmrmqnZIdFOj6vhCUAJKLZNUDwFDAPBgNVHRMBAf8EBTAD +AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB3j6gvalxq54hZSwVmVZPMzjdTVYRC11b0 +6C9pWKsLwu+WINcs59ui8wpYVjcw1AK4/2I1Q7P4RgpSarAxG5tYIMB1xcfFKqBn +f/dDXexONgwpW6SoBJ58c7OB/aH8CenDT8Vwk3fwjYslOywbFRqBjH+PB8uTlu0e +D1fzjpcQCrQeA5VD4pjJAaTmi7bLVuH5XIya3++f/N3xOn53GVMUDO1OdFz8ZMvJ +Wrrg7E/wMXB1b5Wo2n2ypVU4sejikSjg2nfdLojUWGMrZ8TuUnjFs88PeQ9CObAp +A36dLfs4JLF3sVOtqTd6BGwegDsmmllYO5Ky6I+laoLSHpGDEihS -----END CERTIFICATE----- diff --git a/test/ca/serialfile b/test/ca/serialfile index b1bd38b62a08..f04c001f3f7f 100644 --- a/test/ca/serialfile +++ b/test/ca/serialfile @@ -1 +1 @@ -13 +29 diff --git a/test/ca_path/cert2.crt b/test/ca_path/cert2.crt index ae9fb00b1c3c..167efa1d544c 100644 --- a/test/ca_path/cert2.crt +++ b/test/ca_path/cert2.crt @@ -25,4 +25,4 @@ jctDlEGOmEe50GQXc25VKpcpjAsNQi5ER5gowQ0v3IXNZs+yU+LvxLHc0rUJ/XSp lFCAMOqd5uRoMOejnT51G6krvLNzPaQ3N9jQfNVY4Q0zfs0M+6dRWvqfqB9Vyq8/ POLMld+HyAZEBk9zK3ZVIXx6XS4dkDnSNR91njLq7eouf6M7+7s/oMQZZRtAfQ6r wlW975rYa1ZqEdA= ------END CERTIFICATE----- +-----END CERTIFICATE----- \ No newline at end of file diff --git a/test/client_certs/client.crt b/test/client_certs/client.crt index e9b136f03ecb..1a3afec7a846 100644 --- a/test/client_certs/client.crt +++ b/test/client_certs/client.crt @@ -1,17 +1,17 @@ -----BEGIN CERTIFICATE----- -MIICnTCCAkOgAwIBAgIRAO78TJMhBu87zWa1WjcG5rkwCgYIKoZIzj0EAwIwgbkx -CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj -bzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw -FQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB -IDIwNjQxNTYyNDA1MDIyOTg4MjQzNTI2NTMwNzkwODU3NzAyMzg4OTAeFw0yMzEx -MDIxNDA2MDhaFw0yNDExMDExNDA2MDhaMBwxGjAYBgNVBAMTEWNsaWVudC5kYzEu -Y29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcSaUbB8GT/WlJjIvvbjE -dgs7hEJqUrU5POXv8N9tNAe/FRbb1yBFU2dBrHgBlJp+sp0gp3cRUCzQMkLO5acw -lqOBxzCBxDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG -AQUFBwMBMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEIGV49e7k/a39oKuJCrdyF0Hs -cgoZx+I2WwMGaT5soLG1MCsGA1UdIwQkMCKAIJqCAzNWlJBk68ytAJtnqLtvw2Vl -lImVNZXwhWrSbD5wMC0GA1UdEQQmMCSCEWNsaWVudC5kYzEuY29uc3Vsgglsb2Nh -bGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIhAPnAeouhL4lCbOuYj6REbJ2q -WZDLv5j7AY5uXoLOtMgLAiALUk1/M2oUO1y61qTMLdCGQh3g6gKpSEB1vo/el1hQ -VA== +MIICnjCCAkSgAwIBAgIQAxVHhSG0wSbdZm+3ToYAkDAKBggqhkjOPQQDAjCBuTEL +MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv +MRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV +BgNVBAoTDkhhc2hpQ29ycCBJbmMuMUAwPgYDVQQDEzdDb25zdWwgQWdlbnQgQ0Eg +MjgwNzE4MDMxODA1Mjk2OTA1NzQ4MzU3NjI1MTI5ODQ5NDA5NjI3MCAXDTIzMTEw +MjE1Mjk0NVoYDzIxMjMxMDA5MTUyOTQ1WjAcMRowGAYDVQQDExFjbGllbnQuZGMx +LmNvbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKvl1yhbsI9r7IxJxLrt +ZTNYXkCXuFy8q3gsokMqsl/MUynrIBrd9NrZEQA91ZArUYzF1+QlxM6D4hRJc5CR +3x6jgccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr +BgEFBQcDATAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCCvXve+zMFSJMXNS3l3YL9k +2QH8zF74wa+TlwFSaQEjGzArBgNVHSMEJDAigCBGa65jF6Wwq9OmdbgJIRCYv++x +HG8dRBUpwvSk0Mk1+jAtBgNVHREEJjAkghFjbGllbnQuZGMxLmNvbnN1bIIJbG9j +YWxob3N0hwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIBLqa1Zh3KUE0RiQzWdoYXkU +wZo5aBw9ujqzLyAqxToFAiEAihWmc4r6lDYRR35X4QB1nTT92POJRClsfLPOTRG5 +rsU= -----END CERTIFICATE----- diff --git a/test/client_certs/client.key b/test/client_certs/client.key index ef5f3a7e04fc..e7795e865e24 100644 --- a/test/client_certs/client.key +++ b/test/client_certs/client.key @@ -1,5 +1,5 @@ -----BEGIN EC PRIVATE KEY----- -MHcCAQEEILsRH87p2w58u2Re7XGAmPuI1grBy7ZMsxWDP7tJ/pL0oAoGCCqGSM49 -AwEHoUQDQgAEcSaUbB8GT/WlJjIvvbjEdgs7hEJqUrU5POXv8N9tNAe/FRbb1yBF -U2dBrHgBlJp+sp0gp3cRUCzQMkLO5acwlg== +MHcCAQEEINE2CQhnu7ipo67FGbEBRXoYRCTM4uJdHgNRTrdkAnHCoAoGCCqGSM49 +AwEHoUQDQgAEq+XXKFuwj2vsjEnEuu1lM1heQJe4XLyreCyiQyqyX8xTKesgGt30 +2tkRAD3VkCtRjMXX5CXEzoPiFElzkJHfHg== -----END EC PRIVATE KEY----- diff --git a/test/client_certs/consul-agent-ca-key.pem b/test/client_certs/consul-agent-ca-key.pem index f3b6cb6d57ac..6bf1b2f78aa9 100644 --- a/test/client_certs/consul-agent-ca-key.pem +++ b/test/client_certs/consul-agent-ca-key.pem @@ -1,5 +1,5 @@ -----BEGIN EC PRIVATE KEY----- -MHcCAQEEICDZ+CIUIyHeCulc0Av0afGc6iUrXp6LI+RMCtzXq2f/oAoGCCqGSM49 -AwEHoUQDQgAEdegVURrrCMAdJqm065wYxHwr1HgocnVd+NPABufHiTJPPY4EIucf -WfpCvVBd3a5quRkZRobnQYK4BHPMFPm2Qg== +MHcCAQEEIIH0PuHoVgBRUbkAGH/ZJ49GxWrX5fKws3z6LJJp1pw7oAoGCCqGSM49 +AwEHoUQDQgAE79JHKa+fr3Ird9hUoZLBK5GkvlUQ1dj2sXmn21q7PSDsnjy7r44l +X/rL1uVDpd/YJO6venDB6ApRgMVdZl/msw== -----END EC PRIVATE KEY----- diff --git a/test/client_certs/consul-agent-ca.pem b/test/client_certs/consul-agent-ca.pem index f57e1cb34f00..62de74af4ee6 100644 --- a/test/client_certs/consul-agent-ca.pem +++ b/test/client_certs/consul-agent-ca.pem @@ -1,18 +1,18 @@ -----BEGIN CERTIFICATE----- -MIIC7TCCApSgAwIBAgIRAJtKNACj8KAiBWSSqeYB15EwCgYIKoZIzj0EAwIwgbkx +MIIC8DCCApagAwIBAgIRANMwU4romcy9OnAAx7c9UFswCgYIKoZIzj0EAwIwgbkx CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj bzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw FQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB -IDIwNjQxNTYyNDA1MDIyOTg4MjQzNTI2NTMwNzkwODU3NzAyMzg4OTAeFw0yMzEx -MDIxNDA2MDhaFw0yODEwMzExNDA2MDhaMIG5MQswCQYDVQQGEwJVUzELMAkGA1UE -CBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xGjAYBgNVBAkTETEwMSBTZWNv -bmQgU3RyZWV0MQ4wDAYDVQQREwU5NDEwNTEXMBUGA1UEChMOSGFzaGlDb3JwIElu -Yy4xQDA+BgNVBAMTN0NvbnN1bCBBZ2VudCBDQSAyMDY0MTU2MjQwNTAyMjk4ODI0 -MzUyNjUzMDc5MDg1NzcwMjM4ODkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR1 -6BVRGusIwB0mqbTrnBjEfCvUeChydV3408AG58eJMk89jgQi5x9Z+kK9UF3drmq5 -GRlGhudBgrgEc8wU+bZCo3sweTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw -AwEB/zApBgNVHQ4EIgQgmoIDM1aUkGTrzK0Am2eou2/DZWWUiZU1lfCFatJsPnAw -KwYDVR0jBCQwIoAgmoIDM1aUkGTrzK0Am2eou2/DZWWUiZU1lfCFatJsPnAwCgYI -KoZIzj0EAwIDRwAwRAIgcoZwCzJGdL7LFL7Bbp+26OfNvnyhfchSDdN6YEukIVIC -IAd+GbxNZbSqTrIackV1/VkM0y1ZJ8si9IiecRNOKOMi +IDI4MDcxODAzMTgwNTI5NjkwNTc0ODM1NzYyNTEyOTg0OTQwOTYyNzAgFw0yMzEx +MDIxNTI5NDVaGA8yMTIzMTAwOTE1Mjk0NVowgbkxCzAJBgNVBAYTAlVTMQswCQYD +VQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEaMBgGA1UECRMRMTAxIFNl +Y29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcwFQYDVQQKEw5IYXNoaUNvcnAg +SW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENBIDI4MDcxODAzMTgwNTI5Njkw +NTc0ODM1NzYyNTEyOTg0OTQwOTYyNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BO/SRymvn69yK3fYVKGSwSuRpL5VENXY9rF5p9tauz0g7J48u6+OJV/6y9blQ6Xf +2CTur3pwwegKUYDFXWZf5rOjezB5MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E +BTADAQH/MCkGA1UdDgQiBCBGa65jF6Wwq9OmdbgJIRCYv++xHG8dRBUpwvSk0Mk1 ++jArBgNVHSMEJDAigCBGa65jF6Wwq9OmdbgJIRCYv++xHG8dRBUpwvSk0Mk1+jAK +BggqhkjOPQQDAgNIADBFAiEA1nklH0P2rsCNv/wMVKK9/07ICFTl18bpwzb7zycf +5+sCIEIfm6RK9e8WACmFGoaaeQjxwrCSMwGSDCw9FSU6BeZB -----END CERTIFICATE----- diff --git a/test/client_certs/dc1-client-consul-0-key.pem b/test/client_certs/dc1-client-consul-0-key.pem index ef5f3a7e04fc..e7795e865e24 100644 --- a/test/client_certs/dc1-client-consul-0-key.pem +++ b/test/client_certs/dc1-client-consul-0-key.pem @@ -1,5 +1,5 @@ -----BEGIN EC PRIVATE KEY----- -MHcCAQEEILsRH87p2w58u2Re7XGAmPuI1grBy7ZMsxWDP7tJ/pL0oAoGCCqGSM49 -AwEHoUQDQgAEcSaUbB8GT/WlJjIvvbjEdgs7hEJqUrU5POXv8N9tNAe/FRbb1yBF -U2dBrHgBlJp+sp0gp3cRUCzQMkLO5acwlg== +MHcCAQEEINE2CQhnu7ipo67FGbEBRXoYRCTM4uJdHgNRTrdkAnHCoAoGCCqGSM49 +AwEHoUQDQgAEq+XXKFuwj2vsjEnEuu1lM1heQJe4XLyreCyiQyqyX8xTKesgGt30 +2tkRAD3VkCtRjMXX5CXEzoPiFElzkJHfHg== -----END EC PRIVATE KEY----- diff --git a/test/client_certs/dc1-client-consul-0.pem b/test/client_certs/dc1-client-consul-0.pem index e9b136f03ecb..1a3afec7a846 100644 --- a/test/client_certs/dc1-client-consul-0.pem +++ b/test/client_certs/dc1-client-consul-0.pem @@ -1,17 +1,17 @@ -----BEGIN CERTIFICATE----- -MIICnTCCAkOgAwIBAgIRAO78TJMhBu87zWa1WjcG5rkwCgYIKoZIzj0EAwIwgbkx -CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj -bzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw -FQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB -IDIwNjQxNTYyNDA1MDIyOTg4MjQzNTI2NTMwNzkwODU3NzAyMzg4OTAeFw0yMzEx -MDIxNDA2MDhaFw0yNDExMDExNDA2MDhaMBwxGjAYBgNVBAMTEWNsaWVudC5kYzEu -Y29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcSaUbB8GT/WlJjIvvbjE -dgs7hEJqUrU5POXv8N9tNAe/FRbb1yBFU2dBrHgBlJp+sp0gp3cRUCzQMkLO5acw -lqOBxzCBxDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG -AQUFBwMBMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEIGV49e7k/a39oKuJCrdyF0Hs -cgoZx+I2WwMGaT5soLG1MCsGA1UdIwQkMCKAIJqCAzNWlJBk68ytAJtnqLtvw2Vl -lImVNZXwhWrSbD5wMC0GA1UdEQQmMCSCEWNsaWVudC5kYzEuY29uc3Vsgglsb2Nh -bGhvc3SHBH8AAAEwCgYIKoZIzj0EAwIDSAAwRQIhAPnAeouhL4lCbOuYj6REbJ2q -WZDLv5j7AY5uXoLOtMgLAiALUk1/M2oUO1y61qTMLdCGQh3g6gKpSEB1vo/el1hQ -VA== +MIICnjCCAkSgAwIBAgIQAxVHhSG0wSbdZm+3ToYAkDAKBggqhkjOPQQDAjCBuTEL +MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv +MRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV +BgNVBAoTDkhhc2hpQ29ycCBJbmMuMUAwPgYDVQQDEzdDb25zdWwgQWdlbnQgQ0Eg +MjgwNzE4MDMxODA1Mjk2OTA1NzQ4MzU3NjI1MTI5ODQ5NDA5NjI3MCAXDTIzMTEw +MjE1Mjk0NVoYDzIxMjMxMDA5MTUyOTQ1WjAcMRowGAYDVQQDExFjbGllbnQuZGMx +LmNvbnN1bDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKvl1yhbsI9r7IxJxLrt +ZTNYXkCXuFy8q3gsokMqsl/MUynrIBrd9NrZEQA91ZArUYzF1+QlxM6D4hRJc5CR +3x6jgccwgcQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr +BgEFBQcDATAMBgNVHRMBAf8EAjAAMCkGA1UdDgQiBCCvXve+zMFSJMXNS3l3YL9k +2QH8zF74wa+TlwFSaQEjGzArBgNVHSMEJDAigCBGa65jF6Wwq9OmdbgJIRCYv++x +HG8dRBUpwvSk0Mk1+jAtBgNVHREEJjAkghFjbGllbnQuZGMxLmNvbnN1bIIJbG9j +YWxob3N0hwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIBLqa1Zh3KUE0RiQzWdoYXkU +wZo5aBw9ujqzLyAqxToFAiEAihWmc4r6lDYRR35X4QB1nTT92POJRClsfLPOTRG5 +rsU= -----END CERTIFICATE----- diff --git a/test/client_certs/dc1-server-consul-0-key.pem b/test/client_certs/dc1-server-consul-0-key.pem index 9e79d6a32b68..fcce44af0a38 100644 --- a/test/client_certs/dc1-server-consul-0-key.pem +++ b/test/client_certs/dc1-server-consul-0-key.pem @@ -1,5 +1,5 @@ -----BEGIN EC PRIVATE KEY----- -MHcCAQEEIDBtgIlMLp68GuAx3GzgvqA6L4pzF7ra4U8KBAeAjYwroAoGCCqGSM49 -AwEHoUQDQgAE//3g7OUk49Wucef353sgAK2QAZJY5iiwYRHrKy8eGaEkBxJBFv0Z -QfXdtsFtJ3XuMk7OfDPEZ1g1VUYIRVPCbw== +MHcCAQEEIDFaDmSkx6Pnn7mQJAsAjl1XIg4YhHgUW2yclB9QoWI5oAoGCCqGSM49 +AwEHoUQDQgAEiFhfuej4FXqKjtxlto9o5dTnz8rMGRbzam7YULKN531XZnNbPsOw +PWFyWDVlNbOzkzY32CLVl7ObfDlCtL36gw== -----END EC PRIVATE KEY----- diff --git a/test/client_certs/dc1-server-consul-0.pem b/test/client_certs/dc1-server-consul-0.pem index a99eec5024d4..c7090b0a8ccc 100644 --- a/test/client_certs/dc1-server-consul-0.pem +++ b/test/client_certs/dc1-server-consul-0.pem @@ -1,17 +1,17 @@ -----BEGIN CERTIFICATE----- -MIICwzCCAmqgAwIBAgIQJeudmzJEAViQ9sIJfwC8RjAKBggqhkjOPQQDAjCBuTEL -MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv -MRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV -BgNVBAoTDkhhc2hpQ29ycCBJbmMuMUAwPgYDVQQDEzdDb25zdWwgQWdlbnQgQ0Eg -MjA2NDE1NjI0MDUwMjI5ODgyNDM1MjY1MzA3OTA4NTc3MDIzODg5MB4XDTIzMTEw -MjE0MDYwOFoXDTI0MTEwMTE0MDYwOFowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j -b25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT//eDs5STj1a5x5/fneyAA -rZABkljmKLBhEesrLx4ZoSQHEkEW/RlB9d22wW0nde4yTs58M8RnWDVVRghFU8Jv -o4HvMIHsMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB -BQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgakV8pQCroFdBBW0TyFgVDbHB -ZFlLvu9sXfk6+xBtqY8wKwYDVR0jBCQwIoAgmoIDM1aUkGTrzK0Am2eou2/DZWWU -iZU1lfCFatJsPnAwVQYDVR0RBE4wTIILY29uc3VsLnRlc3SCGXNlcnZlcjAuc2Vy -dmVyLmRjMS5jb25zdWyCEXNlcnZlci5kYzEuY29uc3Vsgglsb2NhbGhvc3SHBH8A -AAEwCgYIKoZIzj0EAwIDRwAwRAIgB5HA/sAnp5EWLpo+PjM1SAoU6uiE5trKTBPE -UB5+NOoCICuz1zsVEuCTRo7dbFK5d5+G2gM7dwOU0E5nGFqCW46I +MIICxjCCAm2gAwIBAgIRAP6e14CosD1ulIkguwrpihowCgYIKoZIzj0EAwIwgbkx +CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj +bzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw +FQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB +IDI4MDcxODAzMTgwNTI5NjkwNTc0ODM1NzYyNTEyOTg0OTQwOTYyNzAgFw0yMzEx +MDIxNTI5NDVaGA8yMTIzMTAwOTE1Mjk0NVowHDEaMBgGA1UEAxMRc2VydmVyLmRj +MS5jb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASIWF+56PgVeoqO3GW2 +j2jl1OfPyswZFvNqbthQso3nfVdmc1s+w7A9YXJYNWU1s7OTNjfYItWXs5t8OUK0 +vfqDo4HvMIHsMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI +KwYBBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgMO523nDhmf6DDJFSO9ly ++Y5UcgW1TKqCTt+yJkPWG2EwKwYDVR0jBCQwIoAgRmuuYxelsKvTpnW4CSEQmL/v +sRxvHUQVKcL0pNDJNfowVQYDVR0RBE4wTIILY29uc3VsLnRlc3SCGXNlcnZlcjAu +c2VydmVyLmRjMS5jb25zdWyCEXNlcnZlci5kYzEuY29uc3Vsgglsb2NhbGhvc3SH +BH8AAAEwCgYIKoZIzj0EAwIDRwAwRAIgRxmCHvcCJ0FoA/uelR2dNAasXkZa0pZr +bfCWeAUVf5QCIA587F7IqokthpSlbI3W9R3NyES2fffpjUtmxdrQ7cJS -----END CERTIFICATE----- diff --git a/test/client_certs/generate.sh b/test/client_certs/generate.sh index f5c645d7bbb7..3d1192fc9423 100755 --- a/test/client_certs/generate.sh +++ b/test/client_certs/generate.sh @@ -10,7 +10,7 @@ cd "$(dirname "$0")" if [[ ! -f consul-agent-ca-key.pem ]] || [[ ! -f consul-agent-ca.pem ]]; then echo "Regenerating CA..." rm -f consul-agent-ca-key.pem consul-agent-ca.pem - consul tls ca create + consul tls ca create -days 36500 fi rm -f rootca.crt rootca.key path/rootca.crt cp consul-agent-ca.pem rootca.crt @@ -20,7 +20,7 @@ cp rootca.crt path if [[ ! -f dc1-server-consul-0.pem ]] || [[ ! -f dc1-server-consul-0-key.pem ]]; then echo "Regenerating server..." rm -f dc1-server-consul-0.pem dc1-server-consul-0-key.pem - consul tls cert create -server -node=server0 -additional-dnsname=consul.test + consul tls cert create -days=36500 -server -node=server0 -additional-dnsname=consul.test fi rm -f server.crt server.key cp dc1-server-consul-0.pem server.crt @@ -29,7 +29,7 @@ cp dc1-server-consul-0-key.pem server.key if [[ ! -f dc1-client-consul-0.pem ]] || [[ ! -f dc1-client-consul-0-key.pem ]]; then echo "Regenerating client..." rm -f dc1-client-consul-0.pem dc1-client-consul-0-key.pem - consul tls cert create -client + consul tls cert create -days 36500 -client fi rm -f client.crt client.key cp dc1-client-consul-0.pem client.crt diff --git a/test/client_certs/path/rootca.crt b/test/client_certs/path/rootca.crt index f57e1cb34f00..62de74af4ee6 100644 --- a/test/client_certs/path/rootca.crt +++ b/test/client_certs/path/rootca.crt @@ -1,18 +1,18 @@ -----BEGIN CERTIFICATE----- -MIIC7TCCApSgAwIBAgIRAJtKNACj8KAiBWSSqeYB15EwCgYIKoZIzj0EAwIwgbkx +MIIC8DCCApagAwIBAgIRANMwU4romcy9OnAAx7c9UFswCgYIKoZIzj0EAwIwgbkx CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj bzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw FQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB -IDIwNjQxNTYyNDA1MDIyOTg4MjQzNTI2NTMwNzkwODU3NzAyMzg4OTAeFw0yMzEx -MDIxNDA2MDhaFw0yODEwMzExNDA2MDhaMIG5MQswCQYDVQQGEwJVUzELMAkGA1UE -CBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xGjAYBgNVBAkTETEwMSBTZWNv -bmQgU3RyZWV0MQ4wDAYDVQQREwU5NDEwNTEXMBUGA1UEChMOSGFzaGlDb3JwIElu -Yy4xQDA+BgNVBAMTN0NvbnN1bCBBZ2VudCBDQSAyMDY0MTU2MjQwNTAyMjk4ODI0 -MzUyNjUzMDc5MDg1NzcwMjM4ODkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR1 -6BVRGusIwB0mqbTrnBjEfCvUeChydV3408AG58eJMk89jgQi5x9Z+kK9UF3drmq5 -GRlGhudBgrgEc8wU+bZCo3sweTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw -AwEB/zApBgNVHQ4EIgQgmoIDM1aUkGTrzK0Am2eou2/DZWWUiZU1lfCFatJsPnAw -KwYDVR0jBCQwIoAgmoIDM1aUkGTrzK0Am2eou2/DZWWUiZU1lfCFatJsPnAwCgYI -KoZIzj0EAwIDRwAwRAIgcoZwCzJGdL7LFL7Bbp+26OfNvnyhfchSDdN6YEukIVIC -IAd+GbxNZbSqTrIackV1/VkM0y1ZJ8si9IiecRNOKOMi +IDI4MDcxODAzMTgwNTI5NjkwNTc0ODM1NzYyNTEyOTg0OTQwOTYyNzAgFw0yMzEx +MDIxNTI5NDVaGA8yMTIzMTAwOTE1Mjk0NVowgbkxCzAJBgNVBAYTAlVTMQswCQYD +VQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEaMBgGA1UECRMRMTAxIFNl +Y29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcwFQYDVQQKEw5IYXNoaUNvcnAg +SW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENBIDI4MDcxODAzMTgwNTI5Njkw +NTc0ODM1NzYyNTEyOTg0OTQwOTYyNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BO/SRymvn69yK3fYVKGSwSuRpL5VENXY9rF5p9tauz0g7J48u6+OJV/6y9blQ6Xf +2CTur3pwwegKUYDFXWZf5rOjezB5MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E +BTADAQH/MCkGA1UdDgQiBCBGa65jF6Wwq9OmdbgJIRCYv++xHG8dRBUpwvSk0Mk1 ++jArBgNVHSMEJDAigCBGa65jF6Wwq9OmdbgJIRCYv++xHG8dRBUpwvSk0Mk1+jAK +BggqhkjOPQQDAgNIADBFAiEA1nklH0P2rsCNv/wMVKK9/07ICFTl18bpwzb7zycf +5+sCIEIfm6RK9e8WACmFGoaaeQjxwrCSMwGSDCw9FSU6BeZB -----END CERTIFICATE----- diff --git a/test/client_certs/rootca.crt b/test/client_certs/rootca.crt index f57e1cb34f00..62de74af4ee6 100644 --- a/test/client_certs/rootca.crt +++ b/test/client_certs/rootca.crt @@ -1,18 +1,18 @@ -----BEGIN CERTIFICATE----- -MIIC7TCCApSgAwIBAgIRAJtKNACj8KAiBWSSqeYB15EwCgYIKoZIzj0EAwIwgbkx +MIIC8DCCApagAwIBAgIRANMwU4romcy9OnAAx7c9UFswCgYIKoZIzj0EAwIwgbkx CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj bzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw FQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB -IDIwNjQxNTYyNDA1MDIyOTg4MjQzNTI2NTMwNzkwODU3NzAyMzg4OTAeFw0yMzEx -MDIxNDA2MDhaFw0yODEwMzExNDA2MDhaMIG5MQswCQYDVQQGEwJVUzELMAkGA1UE -CBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xGjAYBgNVBAkTETEwMSBTZWNv -bmQgU3RyZWV0MQ4wDAYDVQQREwU5NDEwNTEXMBUGA1UEChMOSGFzaGlDb3JwIElu -Yy4xQDA+BgNVBAMTN0NvbnN1bCBBZ2VudCBDQSAyMDY0MTU2MjQwNTAyMjk4ODI0 -MzUyNjUzMDc5MDg1NzcwMjM4ODkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR1 -6BVRGusIwB0mqbTrnBjEfCvUeChydV3408AG58eJMk89jgQi5x9Z+kK9UF3drmq5 -GRlGhudBgrgEc8wU+bZCo3sweTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw -AwEB/zApBgNVHQ4EIgQgmoIDM1aUkGTrzK0Am2eou2/DZWWUiZU1lfCFatJsPnAw -KwYDVR0jBCQwIoAgmoIDM1aUkGTrzK0Am2eou2/DZWWUiZU1lfCFatJsPnAwCgYI -KoZIzj0EAwIDRwAwRAIgcoZwCzJGdL7LFL7Bbp+26OfNvnyhfchSDdN6YEukIVIC -IAd+GbxNZbSqTrIackV1/VkM0y1ZJ8si9IiecRNOKOMi +IDI4MDcxODAzMTgwNTI5NjkwNTc0ODM1NzYyNTEyOTg0OTQwOTYyNzAgFw0yMzEx +MDIxNTI5NDVaGA8yMTIzMTAwOTE1Mjk0NVowgbkxCzAJBgNVBAYTAlVTMQswCQYD +VQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEaMBgGA1UECRMRMTAxIFNl +Y29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcwFQYDVQQKEw5IYXNoaUNvcnAg +SW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENBIDI4MDcxODAzMTgwNTI5Njkw +NTc0ODM1NzYyNTEyOTg0OTQwOTYyNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BO/SRymvn69yK3fYVKGSwSuRpL5VENXY9rF5p9tauz0g7J48u6+OJV/6y9blQ6Xf +2CTur3pwwegKUYDFXWZf5rOjezB5MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E +BTADAQH/MCkGA1UdDgQiBCBGa65jF6Wwq9OmdbgJIRCYv++xHG8dRBUpwvSk0Mk1 ++jArBgNVHSMEJDAigCBGa65jF6Wwq9OmdbgJIRCYv++xHG8dRBUpwvSk0Mk1+jAK +BggqhkjOPQQDAgNIADBFAiEA1nklH0P2rsCNv/wMVKK9/07ICFTl18bpwzb7zycf +5+sCIEIfm6RK9e8WACmFGoaaeQjxwrCSMwGSDCw9FSU6BeZB -----END CERTIFICATE----- diff --git a/test/client_certs/rootca.key b/test/client_certs/rootca.key index f3b6cb6d57ac..6bf1b2f78aa9 100644 --- a/test/client_certs/rootca.key +++ b/test/client_certs/rootca.key @@ -1,5 +1,5 @@ -----BEGIN EC PRIVATE KEY----- -MHcCAQEEICDZ+CIUIyHeCulc0Av0afGc6iUrXp6LI+RMCtzXq2f/oAoGCCqGSM49 -AwEHoUQDQgAEdegVURrrCMAdJqm065wYxHwr1HgocnVd+NPABufHiTJPPY4EIucf -WfpCvVBd3a5quRkZRobnQYK4BHPMFPm2Qg== +MHcCAQEEIIH0PuHoVgBRUbkAGH/ZJ49GxWrX5fKws3z6LJJp1pw7oAoGCCqGSM49 +AwEHoUQDQgAE79JHKa+fr3Ird9hUoZLBK5GkvlUQ1dj2sXmn21q7PSDsnjy7r44l +X/rL1uVDpd/YJO6venDB6ApRgMVdZl/msw== -----END EC PRIVATE KEY----- diff --git a/test/client_certs/server.crt b/test/client_certs/server.crt index a99eec5024d4..c7090b0a8ccc 100644 --- a/test/client_certs/server.crt +++ b/test/client_certs/server.crt @@ -1,17 +1,17 @@ -----BEGIN CERTIFICATE----- -MIICwzCCAmqgAwIBAgIQJeudmzJEAViQ9sIJfwC8RjAKBggqhkjOPQQDAjCBuTEL -MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2Nv -MRowGAYDVQQJExExMDEgU2Vjb25kIFN0cmVldDEOMAwGA1UEERMFOTQxMDUxFzAV -BgNVBAoTDkhhc2hpQ29ycCBJbmMuMUAwPgYDVQQDEzdDb25zdWwgQWdlbnQgQ0Eg -MjA2NDE1NjI0MDUwMjI5ODgyNDM1MjY1MzA3OTA4NTc3MDIzODg5MB4XDTIzMTEw -MjE0MDYwOFoXDTI0MTEwMTE0MDYwOFowHDEaMBgGA1UEAxMRc2VydmVyLmRjMS5j -b25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT//eDs5STj1a5x5/fneyAA -rZABkljmKLBhEesrLx4ZoSQHEkEW/RlB9d22wW0nde4yTs58M8RnWDVVRghFU8Jv -o4HvMIHsMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB -BQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgakV8pQCroFdBBW0TyFgVDbHB -ZFlLvu9sXfk6+xBtqY8wKwYDVR0jBCQwIoAgmoIDM1aUkGTrzK0Am2eou2/DZWWU -iZU1lfCFatJsPnAwVQYDVR0RBE4wTIILY29uc3VsLnRlc3SCGXNlcnZlcjAuc2Vy -dmVyLmRjMS5jb25zdWyCEXNlcnZlci5kYzEuY29uc3Vsgglsb2NhbGhvc3SHBH8A -AAEwCgYIKoZIzj0EAwIDRwAwRAIgB5HA/sAnp5EWLpo+PjM1SAoU6uiE5trKTBPE -UB5+NOoCICuz1zsVEuCTRo7dbFK5d5+G2gM7dwOU0E5nGFqCW46I +MIICxjCCAm2gAwIBAgIRAP6e14CosD1ulIkguwrpihowCgYIKoZIzj0EAwIwgbkx +CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj +bzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcw +FQYDVQQKEw5IYXNoaUNvcnAgSW5jLjFAMD4GA1UEAxM3Q29uc3VsIEFnZW50IENB +IDI4MDcxODAzMTgwNTI5NjkwNTc0ODM1NzYyNTEyOTg0OTQwOTYyNzAgFw0yMzEx +MDIxNTI5NDVaGA8yMTIzMTAwOTE1Mjk0NVowHDEaMBgGA1UEAxMRc2VydmVyLmRj +MS5jb25zdWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASIWF+56PgVeoqO3GW2 +j2jl1OfPyswZFvNqbthQso3nfVdmc1s+w7A9YXJYNWU1s7OTNjfYItWXs5t8OUK0 +vfqDo4HvMIHsMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI +KwYBBQUHAwIwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgMO523nDhmf6DDJFSO9ly ++Y5UcgW1TKqCTt+yJkPWG2EwKwYDVR0jBCQwIoAgRmuuYxelsKvTpnW4CSEQmL/v +sRxvHUQVKcL0pNDJNfowVQYDVR0RBE4wTIILY29uc3VsLnRlc3SCGXNlcnZlcjAu +c2VydmVyLmRjMS5jb25zdWyCEXNlcnZlci5kYzEuY29uc3Vsgglsb2NhbGhvc3SH +BH8AAAEwCgYIKoZIzj0EAwIDRwAwRAIgRxmCHvcCJ0FoA/uelR2dNAasXkZa0pZr +bfCWeAUVf5QCIA587F7IqokthpSlbI3W9R3NyES2fffpjUtmxdrQ7cJS -----END CERTIFICATE----- diff --git a/test/client_certs/server.key b/test/client_certs/server.key index 9e79d6a32b68..fcce44af0a38 100644 --- a/test/client_certs/server.key +++ b/test/client_certs/server.key @@ -1,5 +1,5 @@ -----BEGIN EC PRIVATE KEY----- -MHcCAQEEIDBtgIlMLp68GuAx3GzgvqA6L4pzF7ra4U8KBAeAjYwroAoGCCqGSM49 -AwEHoUQDQgAE//3g7OUk49Wucef353sgAK2QAZJY5iiwYRHrKy8eGaEkBxJBFv0Z -QfXdtsFtJ3XuMk7OfDPEZ1g1VUYIRVPCbw== +MHcCAQEEIDFaDmSkx6Pnn7mQJAsAjl1XIg4YhHgUW2yclB9QoWI5oAoGCCqGSM49 +AwEHoUQDQgAEiFhfuej4FXqKjtxlto9o5dTnz8rMGRbzam7YULKN531XZnNbPsOw +PWFyWDVlNbOzkzY32CLVl7ObfDlCtL36gw== -----END EC PRIVATE KEY----- diff --git a/test/hostname/Alice.crt b/test/hostname/Alice.crt index 70583b8c8a96..f74838b1d6b5 100644 --- a/test/hostname/Alice.crt +++ b/test/hostname/Alice.crt @@ -1,24 +1,24 @@ -----BEGIN CERTIFICATE----- -MIIEEzCCAvugAwIBAgIBNjANBgkqhkiG9w0BAQ0FADCBmTELMAkGA1UEBhMCVVMx -EzARBgNVBAgTCkNhbGlmb3JuaWExFDASBgNVBAcTC0xvcyBBbmdlbGVzMRkwFwYD -VQQKExBIYWhpQ29ycCBUZXN0IENBMQ0wCwYDVQQLEwRUZXN0MREwDwYDVQQDEwhD -ZXJ0QXV0aDEiMCAGCSqGSIb3DQEJARYTamFtZXNAaGFzaGljb3JwLmNvbTAgFw0y -MzExMDIxNDE3MTZaGA8yMTIzMTAwOTE0MTcxNlowgYMxDjAMBgNVBAMMBUFsaWNl -MRMwEQYDVQQIDApDYWxpZm9ybmlhMQswCQYDVQQGEwJVUzEpMCcGCSqGSIb3DQEJ -ARYaZG8tbm90LXJlcGx5QGhhc2hpY29ycC5jb20xEjAQBgNVBAoMCUVuZCBQb2lu -dDEQMA4GA1UECwwHVGVzdGluZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAMJ12Q87/iDyvoGQ15aGtr9D9QlDi0+a+22k68e+uFNJExkdgz08i6diJZLj -OOlHX5w+nQjDtWE4km9hNp20MG1OUCTTGeuoe7e8CtwNrSj4p0eMKvM54pPNB2rB -166vL93dElHSLvjALjGN32lHb1v04xJY4QxBfRK+sihf/X0CdmMlf8ic9GkK6KE3 -neu9uBBMH7tcOSEKOetIwmSIA2vIdRK/dvAC2Y4sfIXgExaqk6aDCLr907ctsoBc -+I7t63PkeXwDsHSJRbJ8vhw568QWCpd5YenVH+RlakJ06QPDSIx4WhHQ1t8KctZQ -OfcBlXkABM8483NG9Pk4+kul5I8CAwEAAaN4MHYwCQYDVR0TBAIwADALBgNVHQ8E -BAMCBeAwHAYDVR0RBBUwE4IRc2VydmVyLmRjMS5jb25zdWwwHQYDVR0OBBYEFAPO -IGFQ8uNu3oQW/CUV5ROCyCE3MB8GA1UdIwQYMBaAFFV/pGmUd2WIZQKufC+r9DEX -i2MBMA0GCSqGSIb3DQEBDQUAA4IBAQCcUbkMg2l3mIbLZNalu4GHOaumCRHbUVtQ -OtienyzhLJ4MyCloRPzFQVk2woTHZl3BbAUO34acU574xebQKStTuY+RZQya0Rb0 -Bua346H4UYq+06TtTNxEzmqauXWZ74QYmkT3qJspzeyGZbYmstzDp7Q8fJbiV1WR -3d9maKP46RmF3vgFHuhYgXs3EwQegyeDzETZhyh1ul2pPz0F9E/zPMQthxvOfu7M -sLzbZ6O2kIGIlRMgsZ6d4Z7jMDqh7w6N08xfO4AtX1Xof17r/xlrQNYocvcpO4T5 -QXrfkKZrAKIlHaTm9WsYlx4Yk0gdRxE9vYa1tE6SomSSUEuuj3tm +MIIECTCCAvGgAwIBAgIBOjANBgkqhkiG9w0BAQ0FADCBjzELMAkGA1UEBhMCVVMx +CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJhbnNpc2NvMRcwFQYDVQQKDA5I +YXNoaUNvcnAgVGVzdDENMAsGA1UECwwEVGVzdDERMA8GA1UEAwwIQ2VydEF1dGgx +IDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMCAXDTIzMTEwMjE2MDcx +N1oYDzIxMjMxMDA5MTYwNzE3WjCBgzEOMAwGA1UEAwwFQWxpY2UxEzARBgNVBAgM +CkNhbGlmb3JuaWExCzAJBgNVBAYTAlVTMSkwJwYJKoZIhvcNAQkBFhpkby1ub3Qt +cmVwbHlAaGFzaGljb3JwLmNvbTESMBAGA1UECgwJRW5kIFBvaW50MRAwDgYDVQQL +DAdUZXN0aW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzjZrePTR +TuVQ7N7SbeHc0OUEDKezY/PZHTlDw7MK5p/1EICbWCL0IWq51t1N+F2NKN/Wi3Xv +PgTbdsJ5LIaTCZpKqgPzFrq5edYnbAVneaobPR5V8Fwxv+qn2QuNFULUq5SRliWy +sDqm3o5CMH+5K9ejOcFnQ/6+BVFGU0SiLISBHRm7aKjFPDQ6jkv9fTopvwmRNwrf +hjueMg5QD/JtlPRArBulwFaBCmB6/sIdO2Dw+5BzAuOKcGe+McMu0tX+whlx2Rgm +3cuNlTDGRsFdWQ3GNCYbk8xgw76l9bKOF9nE/vCesjzY4uMzfTmBwHsuVgCWzQnk +3L7h/dSkUwsZPwIDAQABo3gwdjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAcBgNV +HREEFTATghFzZXJ2ZXIuZGMxLmNvbnN1bDAdBgNVHQ4EFgQUaFqSFmBGU9+H8pdc +BkGCU2swEhIwHwYDVR0jBBgwFoAUITcAt4ctta2/yGsSFfNF/QmXkkYwDQYJKoZI +hvcNAQENBQADggEBANHHnsC/Gi9yAKp1AyWPLmqztdkn0ES9n1cDL0m3khpbxyW4 +/KnnjhncUNHu5Ozo1F8nV4sRnNZ+v3tbA4uWp/8ZUHz3F7epBfINBIvUGM4pQmAJ +nmTIs8nvLzqNt8hUy6hoOIQIzqljf/dscfZ9lT7mdxVWenLfsTJL0rOCJV+w8WAQ +LtIs86sxZca3tr7JnzX9D2KTVGJVPLTungYy3pdZfVhPdQfqCVnf0lG3KSiMBk62 +8tZC61KThJLyj7HTtT9QkTJGcZcfFJuLh+72aPoWVazWnSlid971zgTzj5NfNMPX +HdUvj9jEd4JhgcLvIeZEKFmu3wA5uxT8vTC5YwY= -----END CERTIFICATE----- diff --git a/test/hostname/Alice.key b/test/hostname/Alice.key index 34cc9e17ed84..190977331081 100644 --- a/test/hostname/Alice.key +++ b/test/hostname/Alice.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDCddkPO/4g8r6B -kNeWhra/Q/UJQ4tPmvttpOvHvrhTSRMZHYM9PIunYiWS4zjpR1+cPp0Iw7VhOJJv -YTadtDBtTlAk0xnrqHu3vArcDa0o+KdHjCrzOeKTzQdqwdeury/d3RJR0i74wC4x -jd9pR29b9OMSWOEMQX0SvrIoX/19AnZjJX/InPRpCuihN53rvbgQTB+7XDkhCjnr -SMJkiANryHUSv3bwAtmOLHyF4BMWqpOmgwi6/dO3LbKAXPiO7etz5Hl8A7B0iUWy -fL4cOevEFgqXeWHp1R/kZWpCdOkDw0iMeFoR0NbfCnLWUDn3AZV5AATPOPNzRvT5 -OPpLpeSPAgMBAAECggEANe/+Lu2TBYyPLt0AD256Tf8JfnJPt9rjFnyCMbtC4UcJ -lxPKjTe3/MuKZH3GEV6MtIfhgsbWDotkgqRSQ9fw/sCUFkK/k8/90O7FjFf2ycB+ -lafZWfGaWSirf/8YVgmdm0pwhGVqRfD4XyJc75Sy3KzGNxaUBZQ8nvBp9iz54KxL -WKPgSQB1uLivRYzvDS+naonBvco4GpOLDbTKin2dYWY7fRWE8UIdaUCzhIioiFLu -AQbf/b6FpDTUG24sWmoGanpseiDtmW+sExA8mX9rorRpa7e5vqj20bchyD5i033D -7aKGoZzdHLnVlJmSxNdKZaDBYDOajaYiMXTE8NXqEQKBgQD+R/BgfukZgpetBqu9 -Mj2BwjAmALX88WH16lAv00SOXPj1VK91K4Y9isbhheW0vFRbcbw7pu6tMrev1sbX -d06/dTQufgiZKoY3agth6tgMNZ/TvDUu/KZU6YoR1W2dkRa9BYhGrVql2WRLt+AV -mDX2c6+AwJFw2/Pg6yqF5wUhAwKBgQDDxmH6PMOPvKVssY4YLn36gZR+VzIxamNg -hK1PSgebQ8SWFm7XVrWUY6NkAK3+6bV42PiyXkwcMs0mvUU9ZAfTH9P+beuo7g97 -3b72Q6IwMZkcLnsEcoKfOopnVZ7Iu045veIS08CYezNCfXQfUqB7UlUCHUls4r5A -enQZkEXqhQKBgFPVlfvKe8GsW6NxKpgDA2JPip5M57NQRfLU4METz2t8XZxM4lgo -FGcf5PgftB8FZG6NrfigzdoOeZ8gmYgaTr0ywBR/+we8jGmircQHsFk+KMafK42l -QJWINbwxeKVVW4DQXSCoMNWzOaz5H4kfGNN7SqaRVqI18k76WZeyFe/PAoGAB1Yv -5cjRK1nOeTxOLunPHswsXG+4GdH612shc486qb7oZxeAH+HH/D+fp+e+nYb0ngrD -hyuxfn0I4yLErYBKKsdOkoJcCoChY+rzdRcjxNqW+k9jnM8NxhnThfvXb35VeCR9 -jGcTGKPFUACTkXjvOq/jL6kZT1NP/eqY3zxg4mECgYBWBojTb8n2hff3iRfWRyp8 -zoyteZrUz6apXM1dWQpmU9Qyu325CXFdMQuGCUBIAWNf8no38ZJvDZUAoLOky1Ni -fMnsVXEi69jRYQRVo2AjV+caBhW6k0KWlFn7mCdyh7bh2WXcvLtUnylc/7bPONyX -gxVKzytFZRegtcqJut742A== +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDONmt49NFO5VDs +3tJt4dzQ5QQMp7Nj89kdOUPDswrmn/UQgJtYIvQharnW3U34XY0o39aLde8+BNt2 +wnkshpMJmkqqA/MWurl51idsBWd5qhs9HlXwXDG/6qfZC40VQtSrlJGWJbKwOqbe +jkIwf7kr16M5wWdD/r4FUUZTRKIshIEdGbtoqMU8NDqOS/19Oim/CZE3Ct+GO54y +DlAP8m2U9ECsG6XAVoEKYHr+wh07YPD7kHMC44pwZ74xwy7S1f7CGXHZGCbdy42V +MMZGwV1ZDcY0JhuTzGDDvqX1so4X2cT+8J6yPNji4zN9OYHAey5WAJbNCeTcvuH9 +1KRTCxk/AgMBAAECggEAKyRJgcm+TII/Vv8bCTAasX1oRnmDV2L5xlpnqfa4Th2i ++KvfVCYj6yXX8XLlUBPKZ4XE7fJjdhcwDv2Kul0BQB4OhtlCrzureCjsoHXU+ygy +gKvrENlI8zzVltwKzSrpMWhouP/0DViH9sHOaTUfeWOo23lx8FDIUnZ5fww53ZQO +8QASgcyMeb2mBZZiwG4m8U4iPW1B1sAMOJKeq8pLWX+bLL7JGt6FH2/fUg54Rctt +0S/KYBl6coFMNO9hxateTkUhz8DSPH2mhx5TiNbwnsI2nE7r8IUv8kh7qPxKREbA +WW0Qoie/3vVjn8qYffrFj2kUDhVrQp1yPnQO+CigoQKBgQDv1hEzLeacrHzxDJwZ +5yj5qT2wUIqCuggpBK514cGrTu99t90s8pR2M5fjhqFfIul0fWKkpBjrdT4bsZdk +JQfncEr2Y7JC8Nl835Y//vOLisISZwOzJlRRP+rpgUVBZ1bSziZF3tT1iGlzJDUg +zuvtLfvvXzWIHWfBWf5xv1570QKBgQDcHD0jUH2Xx6vKRuvfgCrtqdHcnT7I1Cgz +FqeVDV4D3nzqmuJ7YwWmk2ZGI5uJWDv4TvLB6y65t+7AWfpDPM3/ig32bcl7ffdn +pYMGJ/ExWgicLC3i082aYdGlYx6m6qJp9m90auo7GDT0vE5d+5mIQKu7vX2Nwi8P +1nxhqVJYDwKBgFDGD9TkyJ5LmWi1jn1K1QoAbb5L4dpVPRpTcU5SUh+X3iDBI8RX +jpigl68RUJfx8h5BfE9m1N24Bsrc7NfVgOv5bcW9nfPdmeHsi3XSL8P3X5VDDIPx +jMQwerVZzDFS1HL66vjtK1vmLV2R/DKofdzLd+YOcsD85kzAOmmkwfWBAoGAOiWX +nRmpZAxSfKhJrYxtSsWe9BnyORma2Qw2DzEt0fXXqB5skE3zczLjRMopT5oolYs9 +pC7d9B/8CYJ7k4Gfpc8xqxULsfzv+8iEmX65v+DZ/2/IW3C6kvseaAOMWGoJp9Z7 +URThdeUKMFECnt9ViuISvBDt9yICTrvJtf8GCs8CgYEAije1UlRA498ZpzuGrlYs +xiPwasPxm82Dje5FzaNBmRUBD7/fkONsNIga9UdayKv+Mw/1L/f9oPOvaMkoiatQ +pD9XZt3vEjuEV6hoFMcb+aY+X0OOlUyTFg3MwtjpD8xYBCL9YWWsRp02OFeveUUl +N/P3yG9zG16Xk994XoAxOXQ= -----END PRIVATE KEY----- diff --git a/test/hostname/Betty.crt b/test/hostname/Betty.crt index a25066b01486..592ce1a5a231 100644 --- a/test/hostname/Betty.crt +++ b/test/hostname/Betty.crt @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -MIIELjCCAxagAwIBAgIBODANBgkqhkiG9w0BAQ0FADCBmTELMAkGA1UEBhMCVVMx -EzARBgNVBAgTCkNhbGlmb3JuaWExFDASBgNVBAcTC0xvcyBBbmdlbGVzMRkwFwYD -VQQKExBIYWhpQ29ycCBUZXN0IENBMQ0wCwYDVQQLEwRUZXN0MREwDwYDVQQDEwhD -ZXJ0QXV0aDEiMCAGCSqGSIb3DQEJARYTamFtZXNAaGFzaGljb3JwLmNvbTAgFw0y -MzExMDIxNDE3MTdaGA8yMTIzMTAwOTE0MTcxN1owgYMxDjAMBgNVBAMMBUJldHR5 -MRMwEQYDVQQIDApDYWxpZm9ybmlhMQswCQYDVQQGEwJVUzEpMCcGCSqGSIb3DQEJ -ARYaZG8tbm90LXJlcGx5QGhhc2hpY29ycC5jb20xEjAQBgNVBAoMCUVuZCBQb2lu -dDEQMA4GA1UECwwHVGVzdGluZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAKqNlGi1SLBzZFZQ4hK8ZlbPdHtg9iONOp1aMxL+eUs/uzpYJNzn4qo71r8o -EgUbaAP60PVDcdxz1VNxbSL9NPU80/fMevu5lpvRTtf1EQNJqh/FQGDFR52/1j0p -68m3MwpJ0EUlODI98c3E66Un5gGTGcnqNsTXotGWl4zzeY8CLy4ZWo5/ToGafMHT -Bk1s0VDx+g9ROnhMjscV6eLAwkPa0vNQtW1REY6kQ+feEUZPHEEYOEdM89RlPHm9 -U4pkGdXjP9j+lD6DRYyJ8GkSx4cGEsge4Gbn6Ynysd4j8umLZ3u0S7w7S9svEr5l -ZoOMiKI1lXP+0pwDOIEgdVYohncCAwEAAaOBkjCBjzAJBgNVHRMEAjAAMAsGA1Ud -DwQEAwIF4DA1BgNVHREELjAsghFzZXJ2ZXIuZGMyLmNvbnN1bIIXYmV0dHkuc2Vy -dmVyLmRjMi5jb25zdWwwHQYDVR0OBBYEFG/QJlW3De2DxyykpbmmQ+lCcMDqMB8G -A1UdIwQYMBaAFFV/pGmUd2WIZQKufC+r9DEXi2MBMA0GCSqGSIb3DQEBDQUAA4IB -AQA6/VQuwESOX0+v6ejLkHbw/1sER942WhmqIn0zMRIGkvpqJkYfo7uWQUIecpKN -gxrWrxEySpBbo1R/yCTVejWrDBhk29nNY4R6VSU3BrTJaqRbx2d7WoYK5IJm+JCP -G0Al7FjaR08rEiQxnan7pkFMKp6zF9m4DQYPsh+ZjfsV5ObV/y4f8o7Sq5l96yII -OwWErws9mTcjN20OM28zcy5H2VyJXegEMhkxz+4n5S7UowDpTUua0ytATtIZ/KXW -GDBEaA+p9Uz6nK01poEuKl4cWwADEjUJK2Kjvm7jVJP1ifrR7McBWcGksyto94Zh -lv3F4jH5AaQ25kE2WDnwxRjE +MIIEJDCCAwygAwIBAgIBPDANBgkqhkiG9w0BAQ0FADCBjzELMAkGA1UEBhMCVVMx +CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJhbnNpc2NvMRcwFQYDVQQKDA5I +YXNoaUNvcnAgVGVzdDENMAsGA1UECwwEVGVzdDERMA8GA1UEAwwIQ2VydEF1dGgx +IDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMCAXDTIzMTEwMjE2MDcx +N1oYDzIxMjMxMDA5MTYwNzE3WjCBgzEOMAwGA1UEAwwFQmV0dHkxEzARBgNVBAgM +CkNhbGlmb3JuaWExCzAJBgNVBAYTAlVTMSkwJwYJKoZIhvcNAQkBFhpkby1ub3Qt +cmVwbHlAaGFzaGljb3JwLmNvbTESMBAGA1UECgwJRW5kIFBvaW50MRAwDgYDVQQL +DAdUZXN0aW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Qrs3sGo +Xz5wsPXk+lkBzibzOiFr5i40wyzlh1C/sdRhoUTUrji2zbcBAmSuHFL5BkSxF1cl +8RmCE6kM+aEl5WET9nthVUuSxqz7q/Mi04ssFROMnGn6WL67YIwiIxkOWe3DOfaj +9gw+f4Sx3AhpTHBd3qxkY/P/8umjzIyWbK4dBSYIR4X7TGHEZ7m98pPUAPLeygvy +32ybh9nkU8Cdj2kHmW5CzHEhAJ2wdcclbhbXGBbyMxpRACKqtJS5WWYlFR+C0tMg +mFHRtK311NQ7L6QR9R7NNcX73LrP1fCzPMoI0Sb88WdlI0ZrmaA+ElLFIvw/7HQp +UwfvmANmNLR1eQIDAQABo4GSMIGPMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMDUG +A1UdEQQuMCyCEXNlcnZlci5kYzIuY29uc3VsghdiZXR0eS5zZXJ2ZXIuZGMyLmNv +bnN1bDAdBgNVHQ4EFgQUfNlec2HQa3T4QQiqvRjfMumuLpkwHwYDVR0jBBgwFoAU +ITcAt4ctta2/yGsSFfNF/QmXkkYwDQYJKoZIhvcNAQENBQADggEBAFcLpLMqVMcg +QY23LX3lYRKRZs3tT4aqjyZwQ3uP+k2BY8FlzXNapEGGBLJyy51W748AxT2JzkGU +DFp3DDawyN58z1RDWnRC7cfnNFsJAFC1HKvsuljjv9YR5Fbl+vyEKb4NOd4LoGYl +DSdpfihX63g7zkDAwCquYZ2IIWwQEXg+AlJ1hLj5YI4J9+OEJG5zun4F+LD921iI +cNO9RA9wKb7939eDsjKvU5rcdYb1edq5p/q5l+qw5DhyuN+kLFWhZjEmoTSRjy/4 +PwLOqNDOtLI4gpHdTzhjrnzq4lstRxv3pc4G1f0bFPcXzzD2snlg23tR9KP1NTmt +nlFALloJ0iE= -----END CERTIFICATE----- diff --git a/test/hostname/Betty.key b/test/hostname/Betty.key index a5cbe308370f..53896e41b2ef 100644 --- a/test/hostname/Betty.key +++ b/test/hostname/Betty.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCqjZRotUiwc2RW -UOISvGZWz3R7YPYjjTqdWjMS/nlLP7s6WCTc5+KqO9a/KBIFG2gD+tD1Q3Hcc9VT -cW0i/TT1PNP3zHr7uZab0U7X9REDSaofxUBgxUedv9Y9KevJtzMKSdBFJTgyPfHN -xOulJ+YBkxnJ6jbE16LRlpeM83mPAi8uGVqOf06BmnzB0wZNbNFQ8foPUTp4TI7H -FeniwMJD2tLzULVtURGOpEPn3hFGTxxBGDhHTPPUZTx5vVOKZBnV4z/Y/pQ+g0WM -ifBpEseHBhLIHuBm5+mJ8rHeI/Lpi2d7tEu8O0vbLxK+ZWaDjIiiNZVz/tKcAziB -IHVWKIZ3AgMBAAECggEAFUWfUwf5Tvi1dQaVi9yvrvglARZw3LJKs0GCyUWv/zCt -u3Mu9dZ+MNlRyXnH9ZcbfBOWaGDHHMXdv5CQGiMWrdeuYGPCmw7kt/59JPZN7ukL -LPc/NlKkwgohQHOwEvKkjQ3zygwAXFPZit6avXiieWPNfZ+WwSpcBmQP9uaPLMTW -XfDrU+5V9W+N3Ps5NffkDoq+dU43g3OQXFuxIVYJT+v8aqol4DaF2gZ+0nne2jiC -QOYqa+/XGf3ssLMXoYUwk4QPaVRQ4qK5EUtjx/FW3+kF+fPe9hGlBRG6o+PDTtaq -Y+HkLUm0bNQeWwD85x0cc5DeWmVLWhCHDkHhLlmGMQKBgQDvc3kCm0Ab2AXISsvP -H3KZy0WwvwwjxNlA9yhbVtZc27gu9Vp9QuTbondQgoCQnkYPRswKKSNEHaQOFh1D -WHs7W0tk7RXUxrNjoRcyMstyLyXCFWSN/Va9IwJ+C89HVRvvjQA4rjx0ChigmRXF -bXh7UjRVax84v95iHz45oqxWCwKBgQC2Vx4UhoS6p+eovCVmnyENKmKH0wk+fHvE -ExLnpc+hKhVZzwdNc4IhvG9R8seBp94RAUzD4ZWED4rqaGR8CaurSCZjrbfyTMrR -cgrLIuN2oJoKEzHOT73My3K/k/5hde6Fkf2r+pTegJTPwPxzC13qVuqT7fNG8qJ0 -FE8dcKDwxQKBgQC/K97qAM8fK8n6DhVHyOCy/sImCXGEwS1+m5Uhz2OXgWg8PXDA -Xv7eh4hgw8AnNeXTXn+agRuBz3RiNq+oS+UfD5VS/6IVXYptOXiOgFVDVXb8zB2a -6y8sE95yibU0SzPhfh42Io1rS4A7/9yM4gh11Lypkbu8kBrZFf6U/1Y93wKBgQCr -mzvtF1jtjr5guIn+lf72NBC9QeluTJvywfzF1PCe/ktP1Z9Kzk4H0B94oaQQK1u8 -51tG8xTTUAluaUdA0Z0mO2Yd482+FXXAPrNX0QMAj0/J8ZyrTbMUfdkF4pPDR8lv -HiH+7HuVGLB1AmzVHTqLJLfq90RBXnN0CfUXgPuG/QKBgQCaZgAERj8LTu6a43YB -s257Las2njADkSurWRDBqEz+lcxjpsPqZV7mguVrjWlXFmw2ztGbqIOG4gHAHFB8 -54fkRyHMORuPCGZ/wdh9xJtmsgunhA9caPADgoNbm39Ex2sKkAjk/DuqStAPm+Tc -8BaDnfawKGImBgocxWo4xDUyIg== +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDZCuzewahfPnCw +9eT6WQHOJvM6IWvmLjTDLOWHUL+x1GGhRNSuOLbNtwECZK4cUvkGRLEXVyXxGYIT +qQz5oSXlYRP2e2FVS5LGrPur8yLTiywVE4ycafpYvrtgjCIjGQ5Z7cM59qP2DD5/ +hLHcCGlMcF3erGRj8//y6aPMjJZsrh0FJghHhftMYcRnub3yk9QA8t7KC/LfbJuH +2eRTwJ2PaQeZbkLMcSEAnbB1xyVuFtcYFvIzGlEAIqq0lLlZZiUVH4LS0yCYUdG0 +rfXU1DsvpBH1Hs01xfvcus/V8LM8ygjRJvzxZ2UjRmuZoD4SUsUi/D/sdClTB++Y +A2Y0tHV5AgMBAAECggEAAtN27MTuFvoOfZS2ETcXeZey6GQxriLr4kleCQ+uxKH/ +ThpCAAK9CUYDaASSP8wqHJVzDjAUTmSxTOWRRa7TeikexBbXLZp4+XKcfvYA02r8 +fUnD4EWA/PwpdG20BBZPbtxUWReHtaxzI+CWcEcBF/2z5d0DcZ8RC23/Xqp19Z7z +SP7fUT2lkh73kzJxnprjTK388n1ShKpfpSSNlnMEnqLXIsJ3342fBePu6odfATD0 +bg4M0NrMeuq3zkPeMe4vyqme4kihPwWvzdXevznV0YOKf7Xy0UHzOUJ9wehBT2rc +L66tp4dXLicEeJyx8vCgOt7UDCZ5YVXH+kUqOXLgAQKBgQDsE7rtZhGdpydxmFjD +c1lc6hC6yNnArYv278eOmRqHe+Cqco0TlEQ7LA2tKUzpP283wznL1HRUZFztsaxp +X4DXWAAvjkWfstn+1HFtpmRMnSJP+PFMJ9UrKeZW5UMUqwGo3qKTitt7VBw2s6TP +DAHdrkYgp44CFViNI4yKXV8sxQKBgQDrW/iccl2FtxEDwsXu+3nk0bJz3IPkzGjz +I5y3OneQx7HVEmX+nO1TLUaSKP3Gad3voOt9GSn8fmm4t2fGPJTJe+YPskxxzPz5 +0bv1DXZrKuYnaNfyF7Xe74P3nt/aqu5+YnU18D+AKU44NaHdiL5aaDGlk1exsryX +PVJPdQDZJQKBgH+CsKZlSQKENHPQu7Dl7tCWxG5+6c5+bmj0Xi8RVxjyugiWUsjO +foQPaVusQRSC5MmTsvX7TNIAW4kvPFa19Ntbds445DY73i8cBCAbjXUsMkpLxdlC +cosb2IP61N6m9wCFL/7NM3tLlOme4lfKvn9EEDC3D6bkbK3fE5vwjuWZAoGAFrQu +jVjy8J0yRPya/2y+23XnEwoopv+Y+CttSLeZJRw+aWF2+VLGCgoKDrtpj6RSxnTt +gonU5QiExk7a8eKSL8WF8emvOiMeHDNBQGhmDfx7az3P5wimgLT2NALdcUif7Q0u +ZV+hoIlbhEyYKriwNCRs9Z37DadCTgyaThPpWwkCgYBxQ59hMALw+HDVmxwl/kgA +ETxq4RHwenbGiq8edsaFsnhEd7IPzsaWLrtHZev3Isn42hRATuf1D0+lsYkOIfmW ++xfoE7AepT9sHgjENHO1PfUowt6gENAzGL1jFx2Q6BKShEmGrs1R4A9r/f1jP7uI +ILk7XSEVQIalAmjW7INPSg== -----END PRIVATE KEY----- diff --git a/test/hostname/Bob.crt b/test/hostname/Bob.crt index 019030277798..fdf8a3a994b6 100644 --- a/test/hostname/Bob.crt +++ b/test/hostname/Bob.crt @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIBNzANBgkqhkiG9w0BAQ0FADCBmTELMAkGA1UEBhMCVVMx -EzARBgNVBAgTCkNhbGlmb3JuaWExFDASBgNVBAcTC0xvcyBBbmdlbGVzMRkwFwYD -VQQKExBIYWhpQ29ycCBUZXN0IENBMQ0wCwYDVQQLEwRUZXN0MREwDwYDVQQDEwhD -ZXJ0QXV0aDEiMCAGCSqGSIb3DQEJARYTamFtZXNAaGFzaGljb3JwLmNvbTAgFw0y -MzExMDIxNDE3MTdaGA8yMTIzMTAwOTE0MTcxN1owgYExDDAKBgNVBAMMA0JvYjET -MBEGA1UECAwKQ2FsaWZvcm5pYTELMAkGA1UEBhMCVVMxKTAnBgkqhkiG9w0BCQEW -GmRvLW5vdC1yZXBseUBoYXNoaWNvcnAuY29tMRIwEAYDVQQKDAlFbmQgUG9pbnQx -EDAOBgNVBAsMB1Rlc3RpbmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQC+03P5VbpuXbEqIE50XqovdLOvevcDR0JD4u5msdPSr3icZJRQDkpWzFEDzTx9 -yt31M2M+q1i3OE5hpjY+X5b3Fxl8oqCKwdAokBvI4Ban1c4rHYFIiXrMUgBz/rWo -og9nBKU5Wo67kfwUYK2UR+6w5DmeVQj181bspAwynCYMnMfa1zHPfWrw21IPVGiD -yWZcG+jd7iYuQpVfICy17Vdoor6Jq5sWthSNFUZD7zNo2W7vRRnuH6ooevmvOreU -VQZjMhUhTgODlNXMkKSXuicD0uyIZ1dFx7pIB7PGmtMxF15fzBYrBe4BqTFricL2 -UsBbUta7qz/pR/H2RzK0eE9pAgMBAAGjgZAwgY0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBeAwMwYDVR0RBCwwKoIRc2VydmVyLmRjMS5jb25zdWyCFWJvYi5zZXJ2ZXIu -ZGMxLmNvbnN1bDAdBgNVHQ4EFgQUQUj5bnFpu96q1GEXeMsYg1bVAbowHwYDVR0j -BBgwFoAUVX+kaZR3ZYhlAq58L6v0MReLYwEwDQYJKoZIhvcNAQENBQADggEBACuN -aAKSUX1zp1jXk1sUoyE5bLs/d3UUT5p68SiXK0McnAk+c23gbw6FQaaFNWVVdWI7 -xhteOvqTPiMTXfOq4t7jU2KnbNZkukthzH1b/OFblM1toO4s9I2jQ9DbxTkWlg6c -f81xqrLwD77Jd327WSrFwCUPC0+vDajASz2yEPnFPeeQ0o4qp44BCUFRkRATJ9Ij -Phh7O6LskRkZnkMDdCtaYyiEH8fgQLQRrPMFDVbJsdFtaHDdAVVWM7nM5Oi+K8IH -wRVZo0s1vl++tHmHNJXveNCGJ18ql2pyDyJs18LlX2tiotMepv5dGjS7oLQ7Bc+o -P2/pkGPk+B1dNVkZzNg= +MIIEIDCCAwigAwIBAgIBOzANBgkqhkiG9w0BAQ0FADCBjzELMAkGA1UEBhMCVVMx +CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJhbnNpc2NvMRcwFQYDVQQKDA5I +YXNoaUNvcnAgVGVzdDENMAsGA1UECwwEVGVzdDERMA8GA1UEAwwIQ2VydEF1dGgx +IDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMCAXDTIzMTEwMjE2MDcx +N1oYDzIxMjMxMDA5MTYwNzE3WjCBgTEMMAoGA1UEAwwDQm9iMRMwEQYDVQQIDApD +YWxpZm9ybmlhMQswCQYDVQQGEwJVUzEpMCcGCSqGSIb3DQEJARYaZG8tbm90LXJl +cGx5QGhhc2hpY29ycC5jb20xEjAQBgNVBAoMCUVuZCBQb2ludDEQMA4GA1UECwwH +VGVzdGluZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPfUJGiCFYYG +uDuhJw16HD0SMvL4FmWY/8GpRWsMceWyIzHpYtj7YYe7uSHTQPfLXUG0IjWMsGDd +CAo1VYfUlCzISZFcHKlOhdKESVzt27qzBLOM6oJFoarXYslZtKRljGauNHzC5oL3 +WpCnhJ/BOCzRoN7JXuP8zY8eFDCL+DhgWVBNAWfg3UKhv0pmCMSMLbw2UWhVw7Us +nfXRrsuQENyj3gbdssuwjWvYrEjMdUzeFp6ci3sfiyKKBxTF7yY3M/XWYF3+qecQ +IvkMbaojg5EuxY4Qrh0MP7yP1GLzT6Z0iGrGw/lkWyh7RGsRJ2yhhjeL7oQUIv71 +6EJ5XwS4aMsCAwEAAaOBkDCBjTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAzBgNV +HREELDAqghFzZXJ2ZXIuZGMxLmNvbnN1bIIVYm9iLnNlcnZlci5kYzEuY29uc3Vs +MB0GA1UdDgQWBBR5+mEpMR96/uIp6VKldIgn0XLrhjAfBgNVHSMEGDAWgBQhNwC3 +hy21rb/IaxIV80X9CZeSRjANBgkqhkiG9w0BAQ0FAAOCAQEAf/ChdsjyyA0qFguI +kyg+UucyJeRYgbn1QmGvT/Cw7Vwc0Cjdt6foOGZ8eUHprwiBIFJn/6uDR7VC7/Sl +tS+LXW12QYfEsiSNwXuPquZ0yB52bQB7epLZSvm+1mmgV3aj0AxTQwyEoYxCKAlE +UjuwZgkr0uduEm/xuUdkMqqO1YxiVyrjOd0lYo9qZjiRGNvq1VV/4DiBimzbWV7Q +Zwv6lCVYwbNUJ7K7y6ZADcQ0t1vrusowO4a5rQzH+C3YtgtwPsR/gj+rsBerJk0c +bso1DDsupqE7wEGRMohcUyOO7uSCHQksIF5Ej36dIKXHbiRrzMGs3LVOcdYUkqx/ +9Hgp1w== -----END CERTIFICATE----- diff --git a/test/hostname/Bob.key b/test/hostname/Bob.key index a70830f5c8e4..0c31ea1834a1 100644 --- a/test/hostname/Bob.key +++ b/test/hostname/Bob.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+03P5VbpuXbEq -IE50XqovdLOvevcDR0JD4u5msdPSr3icZJRQDkpWzFEDzTx9yt31M2M+q1i3OE5h -pjY+X5b3Fxl8oqCKwdAokBvI4Ban1c4rHYFIiXrMUgBz/rWoog9nBKU5Wo67kfwU -YK2UR+6w5DmeVQj181bspAwynCYMnMfa1zHPfWrw21IPVGiDyWZcG+jd7iYuQpVf -ICy17Vdoor6Jq5sWthSNFUZD7zNo2W7vRRnuH6ooevmvOreUVQZjMhUhTgODlNXM -kKSXuicD0uyIZ1dFx7pIB7PGmtMxF15fzBYrBe4BqTFricL2UsBbUta7qz/pR/H2 -RzK0eE9pAgMBAAECggEAMtd5vcOmgUM7MaMb5AtYwn4QZb+YUmpI8Hdk1z2n1ylj -NB/kGBRGoCudpiqnZEiJrIu9dHQIlgBNedzj9OhY+4pPAxL9PRr4T+ZdUL7Lqnnf -jUM2L9JZQljSwBTr53sOKX9mWgqTnsv9YpyDgs9LfBvCcjnrwkPMNA5dJZrO1Gr3 -QWwlS35Uzoyw7z/abTfkP87ojAJbH2f6O5XleBdi4dLFWoec7sj1Xkj5RmhEf+gx -SJelY33LsPo0apI2YKKjBX4TQ/lvi2AQ/aN3VFBQp+IOfZmPpnlMm6mgagggaa81 -JekSBaTDhHIHH0z6NlKJAJWsW2Vk29e7CEGXAQMjZQKBgQDmF93E0kQqxsbws2Of -ycS/bsfA7vKyH2BRPx3MpsnmlLCD8+kZIBOY+o2YPlK7kzM7A91051jbgv96bLUP -4PJJ6GY71Ci2SydRGvDmITHMMnkDqdrrPYmtbWxGfpMyjmneHm03qhz1RZF3XyXW -SuPQdf3Pp3TFlazxSUbVmoUdjwKBgQDUT8KnzPqdB8tYdexj9XcAvwp2nyN2QsS+ -YHzPfBpZ5QgZ0A2rSaIzr0pUM5h3ie2scCnZByPyilxST8+E6W1En0Hj21H3g3hC -eSvn7aGSklOk0R45c0yuUZvo2fH7IJ+XBcT4lxD61AbI4Xm0Hel8VYoWaeHR8E+W -R4HVVFQ3hwKBgQC8ATI+eQQj46l30UwMqsNtG6px9YwuiL6dhDHoHzwHgOS93JVQ -50m8DLWXeQ0GoR8SEHVp6QJM0jvHn31OTSILy62FIzRkxwGIHrhJgUP8Mh15Jddv -sSeGokr/SrshawYL7NaWzhO9QSu72u3CrAx7L33Ep3IdY9AckyAitpAf9wKBgGhD -92ui7dzabBG4b+wzK0sxhvj0dFzqs2ZvSjw3TVWiddT/aQcatU6+ojkx0Ym7Mf7C -YrrTl+LP8kD2Mwqp/GB7+cbl+Z4dcZzrlxVijTvHIs7JaBd8uUbOi0vSZNUYk2d+ -jNosjkkwgVh76uH64qSN+a/CNgV9CAjcezWCIY3XAoGBANdZR45FezT7bWp6Mfs9 -5s7RjYKC0Yp0hl2elV9I8IgFGu7faV64OodAVxhfLhzORIRrz2SSAHRDaJ4h1T0o -VfE8bflu4i/KmvYLc5TpKUeSKxxJGmfj/BJKiA/xMCVo9AEFme2jv0pMFHVPiBBa -GRqHbtRPZnaQim9+qGmWiBWc +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQD31CRoghWGBrg7 +oScNehw9EjLy+BZlmP/BqUVrDHHlsiMx6WLY+2GHu7kh00D3y11BtCI1jLBg3QgK +NVWH1JQsyEmRXBypToXShElc7du6swSzjOqCRaGq12LJWbSkZYxmrjR8wuaC91qQ +p4SfwTgs0aDeyV7j/M2PHhQwi/g4YFlQTQFn4N1Cob9KZgjEjC28NlFoVcO1LJ31 +0a7LkBDco94G3bLLsI1r2KxIzHVM3haenIt7H4siigcUxe8mNzP11mBd/qnnECL5 +DG2qI4ORLsWOEK4dDD+8j9Ri80+mdIhqxsP5ZFsoe0RrESdsoYY3i+6EFCL+9ehC +eV8EuGjLAgMBAAECggEAD6o2pO54CtE46vf8PnNV/pw8YTRCQijCHc0jyKjwOBsi +82AzsdBt8UTx5kvyotcVbXZD5UufyHegLvkBD4Vl2lDMqaX/X8pJVi2rb3bPeUUg +inLhTdu15NUZdu23J98NWV4wjiRJqsSU0mjsTqbJdLfJadujpliP67h0gT8PsQxy +MNIoFbhhHDukmLjehL0a5HhH89+aZVxOuvUU9HV8lkpCnNJuajJuwnu5gv/7RUZd +EG4lZLPTEb3ao9Bnm7/4q1IHQKGC9Cpwaegde3dYYSn5vxoOp87I6wnWxi8V7g0N +bdNglwCxE9d1hOQ4qefAq3UL6FyAL6wwbo4dNfl3bQKBgQD98vjIy6JdxSYnJOKm +VuG540uJykFqvqazgl85Vi1z4Ot6AVK1UvnWKWy4bHGiZr5H1R4afPDo/a+H9hoz +SXv8Vk8/AClcL/u2+czHqNipCssQIkhRfJ1hu3P7zDgVykSxJTrUCoTzHmKBtarn +kgGQnJC2M44hxFPI26FV0eyyzwKBgQD51IRGdfZT8jw7Bk6f6UFLXV8O7F/pDFs1 +HjUw6+sPselXUSaNk9pIlWr+uTEfwqTG66fLoTFlw0dMzjTejXBiZomZB4Pw0jdF +ccJj0FvTqi4C6VabHP3S7CSp9eDyaaUDEDn/a8fjG+R08crif+jwTwSHbBdaDbaq +CArRW6oZRQKBgBmGIUE1TmV0WkhW6bzkQJ3JXZ9Ex9xtux2RvfZqVfkuoxxJI8H7 +zAaddUL4C1fSUc+weO0an7AbR1g4ARwkh6SuHBrt7jpIzFjwtIdgzh33ar99Yp1m +E/9tstOdDAoMoWjYoBgN0p0I8cettba+sw+Q3O6jMebs76rhgE664bp7AoGAX458 +paK6/DLb/MuVyS5jrhrhoAijSrVSMYgDWlnyR8eJ877zWxWhWT/lc9aLxpUhh4Bd +ZtKZ3U2K+QKqUDGTOd/0Y1bvjW4qe+JeMuVgKh6eiLiNSrkVENcH0wZb6vyjg/9x +35NvGhvyDxTowCeihkADAHVEnUo/gtuen6NK9W0CgYAyLd3mTpPUEfvb3SA2oibJ +j0Z2z4QC85UjoKa/6XKvK31hHABlYdtJLDap5WiXBSGbfZSLRa6bKioQh3a7Skyj +rWjIFdeAG2M08C+fjD7gci2bEE2zA2juaWYjGlsaQ82uKIvL0YXnYPDFFrubPRhv +Ut1e3EKg0Ys3N9ngov6A2w== -----END PRIVATE KEY----- diff --git a/test/hostname/Bonnie.crt b/test/hostname/Bonnie.crt index 0c856e3be569..287a4b93d136 100644 --- a/test/hostname/Bonnie.crt +++ b/test/hostname/Bonnie.crt @@ -1,25 +1,25 @@ -----BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIBOTANBgkqhkiG9w0BAQ0FADCBmTELMAkGA1UEBhMCVVMx -EzARBgNVBAgTCkNhbGlmb3JuaWExFDASBgNVBAcTC0xvcyBBbmdlbGVzMRkwFwYD -VQQKExBIYWhpQ29ycCBUZXN0IENBMQ0wCwYDVQQLEwRUZXN0MREwDwYDVQQDEwhD -ZXJ0QXV0aDEiMCAGCSqGSIb3DQEJARYTamFtZXNAaGFzaGljb3JwLmNvbTAgFw0y -MzExMDIxNDE3MTdaGA8yMTIzMTAwOTE0MTcxN1owgYQxDzANBgNVBAMMBkJvbm5p -ZTETMBEGA1UECAwKQ2FsaWZvcm5pYTELMAkGA1UEBhMCVVMxKTAnBgkqhkiG9w0B -CQEWGmRvLW5vdC1yZXBseUBoYXNoaWNvcnAuY29tMRIwEAYDVQQKDAlFbmQgUG9p -bnQxEDAOBgNVBAsMB1Rlc3RpbmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQC8j0vJnP8Zhlhirq5DDOipl82Xl/Rwu+4gV+inNGc2EtUKJ+luzYQHBF85 -UqK3qJKM1ihKZ3QmAN5j4yxRusJgWAta/nfP2eR9F6DGJg65+7nBJzgfU/bU3/bT -p5LLFYx2C1WSDfG1sKkMEAR+ZjLacBzvgFATP4PSQzH+3XSLdaAw0B0J3yBtgFNX -LtgsXzEoAwZckNbV7ww2Jm3fI7ajQL9VCjNokbymeOH8+IA7go3nLcBOWK8OhB9W -ihOk7i/3D9ieySitEg7gQtl1OIfPW39Hj7Zypa+3v+8/ns0j3InztemvF35k2daa -1+/j/VpaPQaqEVvArGcKwYfKtt19AgMBAAGjgZMwgZAwCQYDVR0TBAIwADALBgNV -HQ8EBAMCBeAwNgYDVR0RBC8wLYIRc2VydmVyLmRjMy5jb25zdWyCGGJvbm5pZS5z -ZXJ2ZXIuZGMzLmNvbnN1bDAdBgNVHQ4EFgQU+JiThRiJsAqfmGVNnfKktsnM63ww -HwYDVR0jBBgwFoAUVX+kaZR3ZYhlAq58L6v0MReLYwEwDQYJKoZIhvcNAQENBQAD -ggEBAJQsSUep4bULTESb8C/nS4et9GW1e8yawiRlKJfHWURJRdQynJLSlc0QZk8i -Qj0QFeAFUD1TjbncJFgEgm8mTnNLiFl1jzvAFcqpGySv7uE1ET6GtP3TEnm81eut -rXx3gMxXoPQuPbtEfOqruV5sKp/MLUJ21NBFxpWIThQRALAoRZnhUUcIcGOwD3HM -8U6YC8sLN7M1Hes6VeNpKQ+oJqJMlofiCBkMHpg1qp+KZowdU06PDaDMpTi2ofV8 -8WvpUqDHPP1C1YvrpdvBSBG+bAPgPbgfUe5M2Q9dWTLBQ0TbXP/noX+hyRSVN5Oz -NqX2f02UOjgp0PkyCSq8Y3nHuxo= +MIIEJjCCAw6gAwIBAgIBPTANBgkqhkiG9w0BAQ0FADCBjzELMAkGA1UEBhMCVVMx +CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJhbnNpc2NvMRcwFQYDVQQKDA5I +YXNoaUNvcnAgVGVzdDENMAsGA1UECwwEVGVzdDERMA8GA1UEAwwIQ2VydEF1dGgx +IDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMCAXDTIzMTEwMjE2MDcx +N1oYDzIxMjMxMDA5MTYwNzE3WjCBhDEPMA0GA1UEAwwGQm9ubmllMRMwEQYDVQQI +DApDYWxpZm9ybmlhMQswCQYDVQQGEwJVUzEpMCcGCSqGSIb3DQEJARYaZG8tbm90 +LXJlcGx5QGhhc2hpY29ycC5jb20xEjAQBgNVBAoMCUVuZCBQb2ludDEQMA4GA1UE +CwwHVGVzdGluZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM8deDJn +eoCIa0P9rsOuVw9GED2wRZQZwxcWrG+JBtaLczAk1u2zjCG0g5wfQ0WqW8u3wJ3R +lT6NAcF7m/rMSOBIfja6f1vxzgo6798sp//XLKe5Z4RLO37P+94Mr22P5o3160IW +mO58jU93C72/oblV/PuToTId5cJjZbsOnRkOb6k+JzaCeXYWtieVhFINLwtxH6te +7Hv+tWts1mTEkU9xCbSRvmrWkK9AIjQWM0ioOxANLIt7Ca/LvMdw5UyYE1oxAc2X +2Wwg9EIufmGwyqBhTsKYglvP1qQ2Gsz+XPRDyD143h5yKd2QZLTRcZy8IIitbSTt +pnRNFy+GxDaMU8cCAwEAAaOBkzCBkDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DA2 +BgNVHREELzAtghFzZXJ2ZXIuZGMzLmNvbnN1bIIYYm9ubmllLnNlcnZlci5kYzMu +Y29uc3VsMB0GA1UdDgQWBBSWnibIDeJaLeIg8k1QKK1f/qtzUjAfBgNVHSMEGDAW +gBQhNwC3hy21rb/IaxIV80X9CZeSRjANBgkqhkiG9w0BAQ0FAAOCAQEA2CpX5bIl +qXXMsDGwoSvJiDRHYzVYIykyo56M8JpIJKca3xLDvb+FlgKKfHBKng5QCnqrSEaf +B1/1X+bRJBEr5ILmgQB76hCBPqnMDv835DoTkHEYHXqk9sdVjeXoTvMjPHeG+L27 +aL1zz3VAllsQp0aNr7UVDGh3Sny6Lez4G8DRo46zuZnOMgrIPVchfNetP4EkEt0s ++x8aEzbuSnBTw7kWXVBnrj0MMR6pKir/RQz+1YRCMog/FiSo18KgOoTyHSlInT64 +ym4G/NHbXycjxIDWz+wShdFq4BV4dbMtVZqx7InMoauc1+s4oIVXaPs7kXuGqDHW +AbzLfegInE5sbA== -----END CERTIFICATE----- diff --git a/test/hostname/Bonnie.key b/test/hostname/Bonnie.key index 235f0481fcc8..538da04b21dd 100644 --- a/test/hostname/Bonnie.key +++ b/test/hostname/Bonnie.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC8j0vJnP8Zhlhi -rq5DDOipl82Xl/Rwu+4gV+inNGc2EtUKJ+luzYQHBF85UqK3qJKM1ihKZ3QmAN5j -4yxRusJgWAta/nfP2eR9F6DGJg65+7nBJzgfU/bU3/bTp5LLFYx2C1WSDfG1sKkM -EAR+ZjLacBzvgFATP4PSQzH+3XSLdaAw0B0J3yBtgFNXLtgsXzEoAwZckNbV7ww2 -Jm3fI7ajQL9VCjNokbymeOH8+IA7go3nLcBOWK8OhB9WihOk7i/3D9ieySitEg7g -Qtl1OIfPW39Hj7Zypa+3v+8/ns0j3InztemvF35k2daa1+/j/VpaPQaqEVvArGcK -wYfKtt19AgMBAAECggEAUdMfMMDjxJhTj5M9BNS7vCina3Lh/O/YkImFaNWpOkJm -147lUhN2CTOA/Reai/dnjR08A7msIfe7if4hk9/nDLb4SoblyDlGWXBg8MvAFT4i -6CpUROgDU3JTIprz7RQPTYRyoDxT2SPt39GtmYpQ5BDFxbrZRNkJo7tMHUzNj9x9 -1v2EJEmryuU5/2Q+gm4GKfjWVBAY245Emax2O6BIZ6/JWw5RGuO34ze3FrNlPHx+ -mfwpvwoelH935Jmw5mLm5UDX1xUTHGOxgOmzFc1dtUPpD7IjtXRAQFhkFlScLXAE -ZI4vcqmHq88KCNuFMQuYAlJNxH6UonXeFbUqstmiQwKBgQD3qWzHfgGAG607KQ5p -B5qv4KLzaIRy6o0deiaEak4gSpzti3RMBUtylW+44GG3vcj88Ve8WKzC6tWtG20Q -47hELeTXlD9nfS//n6dVpG3D8dWsvSW35ukX8H7U3aa1w3U2eJ+OL3stVl2q6Xf+ -O/Q8HapE6TydpEpDMKV5nEdKcwKBgQDC6HnHQ89UvxOPZC70XqW5KkFV4qYn34a/ -X4fQW/Z+AsNlhuxElpAExehlijlEN/uw4nCTIwAKfLKNSfuv3PWxPP0tH1wHigIr -S7j7RnzqO7pA6+GUuiPe2EZlhpg+GdM5kbP72WbDaM8xilIs9m18LX4qO1I5KErb -amzHHACMTwKBgCSwn+HqA/TjpMVH7s+Whc8ae2mOCVkw8Fj2mLAzQ4G7LAZxC3ib -rDK8esGr1C4xWo5GftXzWRzDR4aOspi287x+BBH/72i4fhzjnRmt82j88cfWebkF -53BZe6CzeZgh7cJ1GkYpOJld2yCP1+v9G9CwIGJ3HzjHdwz/LvSWN2WLAoGAVmdy -3PhdqEcQp8eU3TY8J2rpDebtG84G0T3LWn36NwCImLCIext3+vW1QZZWLrzWsiKg -H0or0XpYOTRsBBljPdA4uFEnnhv7PDBUb+hepgQWXIN1PFaMYlTkWEujoBwYvHOw -I1zMJqKG/4I/Tbls7djJDnW/zKDlFoIGePob8BcCgYBFBatrej1BT0H3FDHbN967 -bt3AmxO6xLY3lB1rxqgBmoGpAvF3Prbus1fKgRezIM3zkuLxlCv7KbQVRbL3fx2H -n8jM34Gno/RPFtYULva04EDhXeclJxRWGwY/7xbm7k2zlEvWCKskoGAA3H3PkzUI -BSOKWoogqwXbRCfkuF6PfA== +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDPHXgyZ3qAiGtD +/a7DrlcPRhA9sEWUGcMXFqxviQbWi3MwJNbts4whtIOcH0NFqlvLt8Cd0ZU+jQHB +e5v6zEjgSH42un9b8c4KOu/fLKf/1yynuWeESzt+z/veDK9tj+aN9etCFpjufI1P +dwu9v6G5Vfz7k6EyHeXCY2W7Dp0ZDm+pPic2gnl2FrYnlYRSDS8LcR+rXux7/rVr +bNZkxJFPcQm0kb5q1pCvQCI0FjNIqDsQDSyLewmvy7zHcOVMmBNaMQHNl9lsIPRC +Ln5hsMqgYU7CmIJbz9akNhrM/lz0Q8g9eN4ecindkGS00XGcvCCIrW0k7aZ0TRcv +hsQ2jFPHAgMBAAECggEAK+I0m4ltXVqKT8eqhe+kpqnTux5kP7MNsRCuzJseBcta +RrMnjwniASo8UJIXMOWduZZfi5DirHQ4EQTd0dADCPKTO4lcfuDHJUfDl2fg2MaA +wbD5DADcxEvRNAVADljVIvMeO8yJ7s4ZKuMwa6302E4t4igvmWzYR83DulSoWKxi +uWvgGieOzo/+ke9bGoL84B4x2JrBCsZBil2kuTz2QPzzHcUtYAKRUT7X9pRttYro +HnegvpkcjHm6oyiSxQbzRL5JlDA+hB5oroNvEvblxLsRtGnO27DD80DoRExn1wqL +kKgQ7fFCTNkHXR4MRfDdQu35+Yk4EJZaVqEWDs6cwQKBgQDvZZVz3KfmXG26S7WP +7svDd/0ouksGaJ7EMjM8M2mjoFr8bmf9+YE1A07rr5yLRngy3Y4xxLnNBgHylpHx +NL3qkkvYtwFd2ONusRUWB50ACGIth59GrEb3GfwaeefLnCIBdnH0/MVVcrF+uOJ1 +tJsUGVj/vwBgdL0SYBT2WxPMtwKBgQDderv01aNlmS82cwNegb8p9f3BNHfT1Tja +PbOXMJ+hNofMjQ/YwZE2lQq+JGFjr5VvcxAe+u5PU/Ikzhsz/8e3z8s72N4vZD+u +stWulcXnp8ySGqVmgMBfJwal2ytJfdg00TXbHsI/asW/fMYkNSt/enE1GqZW9nwE +bGr4X0/BcQKBgDakmkNy90QGjuk6BLxQxmPcjIVyWFOjJ7Iivz0bgx5dKMd7r/Lx +s4NVOPtk/zdvI1qA5ccIX1yj5Wfo5HEJF9xl/jf+NaqlKeyHMQfxPu3V/ArmbP2l +ryER5lBoyPbZsY1h6sr/s084ubjyHIa/bbJdwsnFYCGkI9AA7Gf7C/7rAoGBAKTy +qJMinSuol4H8zHCRPvcYTqGa2vd4IHxhYaRjQS/GtgLAuCGdn/G/tJ2B6MpeVXQI +hOQdzGhmQ7vniFkE0RBzgJAU5vzys37/j6cTwq3RyciycabSkvMK1KengCiewews +N+j2koK6mYYQfl0vADNT1IZRT7sKnbiJqm1KRtLxAoGANamO5efOeb6suuwe3mU0 ++ti9OxNVOiq4W0sILMb5Lb3uKtipCyhjUzLjzlMwDAOLgrWb7QeHsNCFjhtjQ+K8 +lIf/wznCBzmxybEqB3QSvVMcyC9g5KBXMb0DVOJ3/dUC2p/N4Gednc8rwlxKmmd7 +z3kkUaDQlYWt6UPceWmKz7o= -----END PRIVATE KEY----- diff --git a/test/hostname/CertAuth.crt b/test/hostname/CertAuth.crt index 5293cd09241e..b80fe1c99ccc 100644 --- a/test/hostname/CertAuth.crt +++ b/test/hostname/CertAuth.crt @@ -1,28 +1,24 @@ -----BEGIN CERTIFICATE----- -MIIEujCCA6KgAwIBAgIJAPjcMEu1o/4sMA0GCSqGSIb3DQEBBQUAMIGZMQswCQYD -VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEUMBIGA1UEBxMLTG9zIEFuZ2Vs -ZXMxGTAXBgNVBAoTEEhhaGlDb3JwIFRlc3QgQ0ExDTALBgNVBAsTBFRlc3QxETAP -BgNVBAMTCENlcnRBdXRoMSIwIAYJKoZIhvcNAQkBFhNqYW1lc0BoYXNoaWNvcnAu -Y29tMB4XDTE3MDUxMjA1NTAzNloXDTI3MDUxMDA1NTAzNlowgZkxCzAJBgNVBAYT -AlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQHEwtMb3MgQW5nZWxlczEZ -MBcGA1UEChMQSGFoaUNvcnAgVGVzdCBDQTENMAsGA1UECxMEVGVzdDERMA8GA1UE -AxMIQ2VydEF1dGgxIjAgBgkqhkiG9w0BCQEWE2phbWVzQGhhc2hpY29ycC5jb20w -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAnc7C+h+HWU6RsC7dc0dT -GZp+sIkh/XQT17n8q7P852Epc97yuoIualLWtKih08MgipdGoBq5caPjq4WYKJzk -TIqXy0DAuuhCXoTfPaizNgS0jqpWMiufjbu7LRh3vaKL9dgtnAQnl2vwHu7IKya7 -VtfUb6kZAxBo5DxD2vGnX+Sgbe66GsvrqrrjDGM0z24d3Tjndq6Vap50ZF+Kz9+M -XDlu+MAymMipnN5I4SiJOmL1xUpvz49cuW3aKaumMicW3NRGu6lMeSVfxAjADIQW -oqqJjjqIBJksDoKYuowbJfn6QVd5uW02prEoxMHb8bxhUC6Dx0nkiYnp94Z4WOit -AgMBAAGjggEBMIH+MB0GA1UdDgQWBBRVf6RplHdliGUCrnwvq/QxF4tjATCBzgYD -VR0jBIHGMIHDgBRVf6RplHdliGUCrnwvq/QxF4tjAaGBn6SBnDCBmTELMAkGA1UE -BhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFDASBgNVBAcTC0xvcyBBbmdlbGVz -MRkwFwYDVQQKExBIYWhpQ29ycCBUZXN0IENBMQ0wCwYDVQQLEwRUZXN0MREwDwYD -VQQDEwhDZXJ0QXV0aDEiMCAGCSqGSIb3DQEJARYTamFtZXNAaGFzaGljb3JwLmNv -bYIJAPjcMEu1o/4sMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAEj2 -huhEXrFXMlm/HarFjZm0Di5mq9cmudF5Kq6pDZnfI39d1Y4EgeWMThBHjiCtBT3E -xQufEa7s7CNQdjAneUhJdYyUAQmnpOzCtl69qexqQHEQws8kBhE0xyzRFpmCSs39 -ZGt9A4Lc6+0XAeIl87oj6spCAbNZOAaNckKMenrZ/MbkPw7HRPoulex2rx1o9oox -G951WjEk7nJnKAsdQRFnz5DG83Gf8QZcWCnI3Gz3fa8dM1VVa5kuAhk10umDXyEA -UFEbTg8vR9tCvQHJJCnmCRSrIR53m4773WvxfEXlTT70ITn4FnS1F7kO0RkZ1Ylm -h8w/4nK2L6XBxgjweiw= +MIIEATCCAumgAwIBAgIUDkJm2djdx+Z3t1EE3x7sd7KqUAswDQYJKoZIhvcNAQEL +BQAwgY8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZy +YW5zaXNjbzEXMBUGA1UECgwOSGFzaGlDb3JwIFRlc3QxDTALBgNVBAsMBFRlc3Qx +ETAPBgNVBAMMCENlcnRBdXRoMSAwHgYJKoZIhvcNAQkBFhF0ZXN0QGludGVybmFs +LmNvbTAeFw0yMzExMDIxNjA2MzFaFw0zMzEwMzAxNjA2MzFaMIGPMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFuc2lzY28xFzAVBgNV +BAoMDkhhc2hpQ29ycCBUZXN0MQ0wCwYDVQQLDARUZXN0MREwDwYDVQQDDAhDZXJ0 +QXV0aDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRlcm5hbC5jb20wggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDmNX2YYxysQtt9hx5Vm2SGOmzWGj+rTxRM +9tFTyHOnnTi55j//+2Uv/o187X8vQgZLHu57C1c0sKuj07IHp2Ewoc/2xjyt3Pu/ +m2Y7wcLMh+ANYlcL2p7FBFaRnkmJ2r2l2Jl47BucUJyOa2KiZZ9eXsYaiMErgtI0 +lAoJBFXtc/w1bQVChrL8TONBmCWmC5Dsb0fxuJbMBthUfyKbaxObL6HWjtB4hHEf +ObgOLRXzGHhoFM0p4Pby5zb3DTBkb3AOLHwvYf896JeIkG8uK/QD5t+2bL6SP9xY +smjvq+8FyChRT3qXbekiWJHSaC8S6t6hKtJQ9+1RbaMXEXt16xQBAgMBAAGjUzBR +MB0GA1UdDgQWBBQhNwC3hy21rb/IaxIV80X9CZeSRjAfBgNVHSMEGDAWgBQhNwC3 +hy21rb/IaxIV80X9CZeSRjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA +A4IBAQAWzKhzVZ7VOyv4c9io+NetBUYRjne04n/TMG3X+hhc9o0Ce22cQlYqXGZ/ +MfmrOeNRSLwv6i7w9K5xBmXOucfXNlWh+L8CSjvcyQWMgsvpwB0NwihgZZphUxBq +GeU08D4AU1ssyr3mTbZkNdc/nVeFA0kpiAhGBnRaTxo/g52CGnRgJ8QHJx+p639s +Uif3JY9CPnH2B3PaeEDjqmwiRoJahNUNjT0qvxBkDOy/kqzm6hR3po2HfmzCgjBc +t39HKGOrrdnIINXkEaW7lXgQc+roKeMjpugFFtjHyzLekmaYUhk29gchEQtELXRm +4LOUhj7UvGjmqOgyIGeAzwe+49+b -----END CERTIFICATE----- diff --git a/test/hostname/certindex b/test/hostname/certindex index 28e4650a277e..f25c3d003292 100644 --- a/test/hostname/certindex +++ b/test/hostname/certindex @@ -10,3 +10,7 @@ V 21231009141716Z 36 unknown /CN=Alice/ST=California/C=US/emailAddress=do-not-r V 21231009141717Z 37 unknown /CN=Bob/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing V 21231009141717Z 38 unknown /CN=Betty/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing V 21231009141717Z 39 unknown /CN=Bonnie/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009160717Z 3A unknown /CN=Alice/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009160717Z 3B unknown /CN=Bob/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009160717Z 3C unknown /CN=Betty/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing +V 21231009160717Z 3D unknown /CN=Bonnie/ST=California/C=US/emailAddress=do-not-reply@hashicorp.com/O=End Point/OU=Testing diff --git a/test/hostname/privkey.pem b/test/hostname/privkey.pem index bbb51ef417b6..0de066fc18d7 100644 --- a/test/hostname/privkey.pem +++ b/test/hostname/privkey.pem @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAwJ3Owvofh1lOkbAu3XNHUxmafrCJIf10E9e5/Kuz/OdhKXPe -8rqCLmpS1rSoodPDIIqXRqAauXGj46uFmCic5EyKl8tAwLroQl6E3z2oszYEtI6q -VjIrn427uy0Yd72ii/XYLZwEJ5dr8B7uyCsmu1bX1G+pGQMQaOQ8Q9rxp1/koG3u -uhrL66q64wxjNM9uHd0453aulWqedGRfis/fjFw5bvjAMpjIqZzeSOEoiTpi9cVK -b8+PXLlt2imrpjInFtzURrupTHklX8QIwAyEFqKqiY46iASZLA6CmLqMGyX5+kFX -ebltNqaxKMTB2/G8YVAug8dJ5ImJ6feGeFjorQIDAQABAoIBACfixcUETHEXojhy -9lFvJK7ll2NypQL/3ACb5GyZFa1iMHGIB/vVeU2pQLwrLtxL4JUlfcvnLYGHMbvc -cc6fYlW4L97c/OysB5puvi8IMp3hqrnE7SrqOrRQgjZxUSbCgx1ebESNkSKtrXFM -xn92yA91HT5lXOvMAaLm2D/o36+bxN/VvSQnYQZFU8fJoMvUBNOdNUlJZock89PL -E9F1qXrqsex1q9jH7Uykpk9HMSznIhX8s5tMjREa1ZLllaSplP2uQO9DB2dVCqWV -zp11DQpZB4ukSVVu987OrW6Ic16RLi5jgd41GY792KQE/7ILqU/0iLBidCTXTbOm -ckBZJyECgYEA4OpVith3ty7YH7VS12hrxql3BaXKk+3rAvXiwdlHlVs9vB61Ugv3 -AiWao88xADt/9NGKQb7oX++7KogE/lZpkE5Gs3s45xcKZDCmfIqyI2ojXPEJR2MR -reCTAAfDnqiYQtmGRqbObNy/bSRY7urZ94Vv+2Q4NHMkxfBUQMf3lZUCgYEA2zy2 -3XECt4T/ieWx/VSqHeNklG7p2UMiXUlLID1I7Xcx0+7W+g4JscE4+M/d/OCiIknB -Logd3UfVX1avuvu0HAg6ZqNBlzYfSDLvqtG9ZyfKGZNkPZEu9TivXKo+hG7AaDDw -yOuvyt7ncUFNI1aXi5iEJrs4TO8+f+WQX2KikLkCgYEAkUnuzk09MED7bag1Bl82 -19MaxrQtY1faa0QpIe3Y1vtkqsPvfzupaWKfPVgXID5PTveY5xWKiIaVEklhaGar -tINMGp7ryCPTG5ttwJ/bqRLkGyK9SrcNcZPTgb6COFhSW0Sm/7a7PAlxQvCq3lMp -UEKLbwpzYDZNN+wikOJb5e0CgYAa3ZrPEg0yLgMeg95G2/wow3fM1LalYBuy8Mta -/QeVyfh6Lxd69wNrG/F+VAKw/VoA96bLq/R07FuSXk4UjMmqcbuuXi0oeYJl15AV -D7S1EmQqtCwhe0wU0shyg447rlK3sd+fz3nwU1ZrQ4RPY0oY2iy/jku86chv5dLG -TZD8SQKBgCwz5sHh+X8J5+PxQxBeWfY32Neo1LkWpswFjNYbk7mdzvtMqXmsTn/y -8CqnXumBYkm//lnigqyA+o8CRZK+NvZAqR5++t7U3R9plFhNWBLjuPVwi7KuWAKw -M7vyWgYYLTwnd7YwEJlVVGXzLlghs0mONhmgM3iQiOlIfd0DFBc3 ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDmNX2YYxysQtt9 +hx5Vm2SGOmzWGj+rTxRM9tFTyHOnnTi55j//+2Uv/o187X8vQgZLHu57C1c0sKuj +07IHp2Ewoc/2xjyt3Pu/m2Y7wcLMh+ANYlcL2p7FBFaRnkmJ2r2l2Jl47BucUJyO +a2KiZZ9eXsYaiMErgtI0lAoJBFXtc/w1bQVChrL8TONBmCWmC5Dsb0fxuJbMBthU +fyKbaxObL6HWjtB4hHEfObgOLRXzGHhoFM0p4Pby5zb3DTBkb3AOLHwvYf896JeI +kG8uK/QD5t+2bL6SP9xYsmjvq+8FyChRT3qXbekiWJHSaC8S6t6hKtJQ9+1RbaMX +EXt16xQBAgMBAAECggEAAwLfm/Lt8NXmC5gNHkcMU1In0swgmZPM+u2+krc8RgzB +LXNU0nseGXjdrmzn3T0imnBy46KkFyEZeaje+wkmNQ3ky8BPkmGh3GGCvpTcALNl +S5+F7naDXaXfIQP+R8KX+PeimEmUWeDXD2jZrzCfm0snkbjIuBI7wCrQj8oh+ptj +ro7GCLoERAJQccqCFdhAU1pkO6wHosxQO+/VcP1WJcxHlLZCWgby4GCyUXAESKTH +A5lHaK2YTRlyX6vgSCVAQ5E/8G7pKw4LQ0jsw8FQBMXFyR9sRqQN6CY7/xdNLGwE +Rvy9KTFXybX+ERcMzfOhbUu+qXi3BoLF6MKDYGy4fQKBgQD48fEcdTCfNUe55+WH +h0asZix3ZzzeRbSP62SlhCzbb/QEDCByvhPbAxT4+eTnfI+XfjO/b8+uNuiD36sV +RaK2DFgdMN2mswWDKh8tXkHmMxkiKODoTEeog1/iwMQ/O4ulDObgzD+E4m2XhXA5 +z7zV5CkM68ALetObym74P3juBQKBgQDsu574jgL8ZumNXBnUvRdprpX1B4fMSR4W +dvguwNsuy+rMdD/pBywnhQPp0V0YF7OcMPCnm8FoLoUXPwa9RQOzkPGPZGT1ob5T +9BMGVMgAzMKGQ1lmHnOr5Wf7X2sBLKcQXk9ShC5SnU4dSlIZ2BDhHgKa2cuOJ5ck +CFi12VGyzQKBgQDrfpQDw6hXM2PCrWgoKQPmGlF+Mp8V9QK2EouHN93nR6SiH4ai +hMTrraKtVFgB04dSXAQ/2FmyCCc0eOWynckqRcsk8hD7nOZeCf6sQDo+tZ/U/K6l +kWNIOd7+9jOvTXjwjZ/qj8yWvEvHxmc/iRCtlcRvgKSPN4XuHjWTiRewsQKBgQCQ +Y/uZdNzjYE3Rl7x1ooP2RLNYSaiNdIdygkvsEFtf1qa236zfkC1hSWNSqQ1UFZjK +ipsuT/UOe1lYDWwp4z9Xte9wW3asz2OMR1GXSfzXaAy54bhUbfx1ey4KB2/3vmmD +tVJCbTbn0uSDPwKGmt/ovuot0uuyH/my05hwCkYnfQKBgQDUWns1jJV+pLDMDUYw +d6wju9UkA7Mpo5zPOLQ3UsdfOJMKBC/xiB93WjJSGfaXkg+QoH2rOfea1l94W1rw +3xHWFcGR/UHO16UYsH4VGW7kucireMp/WDn4oYjVQJ8viBLdVXtgi7aIQmtMdinu +p17ypJ/0W7tKm0eowg1N7N1AnQ== +-----END PRIVATE KEY----- diff --git a/test/hostname/serialfile b/test/hostname/serialfile index 44442d2d7b0b..5c789eff7a40 100644 --- a/test/hostname/serialfile +++ b/test/hostname/serialfile @@ -1 +1 @@ -3A +3E diff --git a/test/integration/connect/envoy/Dockerfile-tcpdump b/test/integration/connect/envoy/Dockerfile-tcpdump index 658cd30a2330..ea076961cfb3 100644 --- a/test/integration/connect/envoy/Dockerfile-tcpdump +++ b/test/integration/connect/envoy/Dockerfile-tcpdump @@ -1,4 +1,4 @@ -FROM alpine:3.17 +FROM alpine:3.20 RUN apk add --no-cache tcpdump VOLUME [ "/data" ] diff --git a/test/integration/connect/envoy/case-cfg-router-features/setup.sh b/test/integration/connect/envoy/case-cfg-router-features/setup.sh index 577b3512b4fe..91f6770c65b5 100644 --- a/test/integration/connect/envoy/case-cfg-router-features/setup.sh +++ b/test/integration/connect/envoy/case-cfg-router-features/setup.sh @@ -59,6 +59,17 @@ routes = [ prefix_rewrite = "/" } }, + { + match { http { + path_prefix = "/prefix-case-insensitive/" + case_insensitive = true + } + } + destination { + service_subset = "v1" + prefix_rewrite = "/" + } + }, { match { http { path_regex = "/deb[ug]{2}" diff --git a/test/integration/connect/envoy/case-cfg-router-features/verify.bats b/test/integration/connect/envoy/case-cfg-router-features/verify.bats index 7af248f3ca0d..484209ad1228 100644 --- a/test/integration/connect/envoy/case-cfg-router-features/verify.bats +++ b/test/integration/connect/envoy/case-cfg-router-features/verify.bats @@ -56,6 +56,11 @@ load helpers assert_expected_fortio_name s2-v1 localhost 5000 /prefix-alt } +@test "test prefix path case insensitive" { + assert_expected_fortio_name s2-v1 localhost 5000 /prefix-case-Insensitive + assert_expected_fortio_name s2-v1 localhost 5000 /prefix-case-INSENSITIVE +} + @test "test regex path" { assert_expected_fortio_name s2-v2 localhost 5000 "" regex-path } diff --git a/test/integration/connect/envoy/case-ingress-gateway-sds/service_gateway.hcl b/test/integration/connect/envoy/case-ingress-gateway-sds/service_gateway.hcl index 1ffa476e6ff9..0448749cc8b9 100644 --- a/test/integration/connect/envoy/case-ingress-gateway-sds/service_gateway.hcl +++ b/test/integration/connect/envoy/case-ingress-gateway-sds/service_gateway.hcl @@ -7,22 +7,18 @@ services { proxy { config { - # Note that http2_protocol_options is a deprecated field and Envoy 1.17 - # and up would prefer: - # typed_extension_protocol_options: - # envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - # "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - # explicit_http_config: - # http2_protocol_options: - # - # But that breaks 1.15 and 1.16. For now use this which is supported by - # all our supported versions to avoid needing to setup different - # bootstrap based on the envoy version. envoy_extra_static_clusters_json = <' (curl -v output) to just '}'. + local json=$(echo "$output" | sed 's/}\*.*/}/' | sed -n -e '/^{$/,/^}$/{ p; }') + echo $json | jq -r '.' || echo "Output did not contain valid JSON: $output" >&3 +} + +# Gets the value of the raw request path from the echo service response. +# Requires SERVICE_CONTAINER=echo. +function get_echo_request_path { + get_echo_output | jq -r '.path' +} + +# Gets the value of a given request header from the echo service response. +# Requires SERVICE_CONTAINER=echo. +function get_echo_request_header_value { + get_echo_output | jq -r ".headers.$1" } function gen_envoy_bootstrap { diff --git a/test/integration/connect/envoy/main_test.go b/test/integration/connect/envoy/main_test.go index aa83bb6bbec1..1c4ab75f7bb0 100644 --- a/test/integration/connect/envoy/main_test.go +++ b/test/integration/connect/envoy/main_test.go @@ -19,8 +19,7 @@ import ( ) var ( - flagWin = flag.Bool("win", false, "Execute tests on windows") - flagResourceAPIs = flag.Bool("enable-resource-apis", false, "Execute tests with resource apis enabled.") + flagWin = flag.Bool("win", false, "Execute tests on windows") ) func TestEnvoy(t *testing.T) { @@ -31,14 +30,7 @@ func TestEnvoy(t *testing.T) { check_dir_files(dir) } - var testcases []string - var err error - if *flagResourceAPIs == true { - os.Setenv("USE_RESOURCE_APIS", "true") - testcases, err = discoverResourceAPICases() - } else { - testcases, err = discoverCases() - } + testcases, err := discoverCases() require.NoError(t, err) runCmd(t, "suite_setup") @@ -125,33 +117,6 @@ func discoverCases() ([]string, error) { return out, nil } -// discoverResourceAPICases will discover the Envoy tests case files but will contain -// a filter in it to only return those case for which functionality has been added -// to the V2 catalog resources. -func discoverResourceAPICases() ([]string, error) { - cwd, err := os.Getwd() - if err != nil { - return nil, err - } - - dirs, err := os.ReadDir(cwd) - if err != nil { - return nil, err - } - - var out []string - for _, fi := range dirs { - // TODO(proxystate): enable this to only include tests cases that are supported. - // Currently the work is in progress, so it is wired up in CI, but this excludes any tests from actually running. - if fi.IsDir() && strings.HasPrefix(fi.Name(), "case-don-match-me-on-anything-yet-because-i-am-not-ready") { - out = append(out, fi.Name()) - } - } - - sort.Strings(out) - return out, nil -} - // CRLF convert functions // Recursively iterates through the directory passed by parameter looking for the sh and bash files. // Upon finding them, it calls crlf_file_check. diff --git a/test/integration/connect/envoy/run-tests.sh b/test/integration/connect/envoy/run-tests.sh index 900d3cbfd33b..274f75f5db98 100755 --- a/test/integration/connect/envoy/run-tests.sh +++ b/test/integration/connect/envoy/run-tests.sh @@ -15,7 +15,10 @@ DEBUG=${DEBUG:-} XDS_TARGET=${XDS_TARGET:-server} # ENVOY_VERSION to run each test against -ENVOY_VERSION=${ENVOY_VERSION:-"1.27.0"} +if [[ -z "${ENVOY_VERSION:-}" ]]; then + echo "please set Envoy version via ENVOY_VERSION" + exit 1 +fi export ENVOY_VERSION export DOCKER_BUILDKIT=1 @@ -179,14 +182,6 @@ function start_consul { license=$(cat $CONSUL_LICENSE_PATH) fi - USE_RESOURCE_APIS=${USE_RESOURCE_APIS:-false} - - experiments="experiments=[]" - # set up consul to run in V1 or V2 catalog mode - if [[ "${USE_RESOURCE_APIS}" == true ]]; then - experiments="experiments=[\"resource-apis\"]" - fi - # We currently run these integration tests in two modes: one in which Envoy's # xDS sessions are served directly by a Consul server, and another in which it # goes through a client agent. @@ -227,7 +222,7 @@ function start_consul { docker_kill_rm consul-${DC}-server docker_kill_rm consul-${DC} - docker run -d --name envoy_consul-${DC}-server_1 \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name envoy_consul-${DC}-server_1 \ --net=envoy-tests \ $WORKDIR_SNIPPET \ --hostname "consul-${DC}-server" \ @@ -240,7 +235,7 @@ function start_consul { -client "0.0.0.0" \ -bind "0.0.0.0" >/dev/null - docker run -d --name envoy_consul-${DC}_1 \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name envoy_consul-${DC}_1 \ --net=envoy-tests \ $WORKDIR_SNIPPET \ --hostname "consul-${DC}-client" \ @@ -258,7 +253,7 @@ function start_consul { else docker_kill_rm consul-${DC} - docker run -d --name envoy_consul-${DC}_1 \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name envoy_consul-${DC}_1 \ --net=envoy-tests \ $WORKDIR_SNIPPET \ --hostname "consul-${DC}" \ @@ -270,7 +265,6 @@ function start_consul { agent -dev -datacenter "${DC}" \ -config-dir "/workdir/${DC}/consul" \ -config-dir "/workdir/${DC}/consul-server" \ - -hcl=${experiments} \ -client "0.0.0.0" >/dev/null fi } @@ -295,7 +289,7 @@ function start_partitioned_client { # Run consul and expose some ports to the host to make debugging locally a # bit easier. # - docker run -d --name envoy_consul-${PARTITION}_1 \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name envoy_consul-${PARTITION}_1 \ --net=envoy-tests \ $WORKDIR_SNIPPET \ --hostname "consul-${PARTITION}-client" \ @@ -351,7 +345,7 @@ function verify { # need to tell the PID 1 inside of the container that it won't be actual PID # 1 because we're using --pid=host so we use TINI_SUBREAPER - if docker run --name envoy_verify-${CLUSTER}_1 -t \ + if docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 --name envoy_verify-${CLUSTER}_1 -t \ -e TINI_SUBREAPER=1 \ -e ENVOY_VERSION \ $WORKDIR_SNIPPET \ @@ -442,7 +436,7 @@ function global_setup { } function wipe_volumes { - docker run --rm -i \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 --rm -i \ $WORKDIR_SNIPPET \ --net=none \ "${HASHICORP_DOCKER_PROXY}/alpine" \ @@ -556,18 +550,17 @@ function suite_setup { # This is a dummy container that we use to create volume and keep it # accessible while other containers are down. docker volume create envoy_workdir &>/dev/null - docker run -d --name envoy_workdir_1 \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name envoy_workdir_1 \ $WORKDIR_SNIPPET \ --net=none \ - k8s.gcr.io/pause &>/dev/null - # TODO(rb): switch back to "${HASHICORP_DOCKER_PROXY}/google/pause" once that is cached + registry.k8s.io/pause &>/dev/null # pre-build the verify container echo "Rebuilding 'bats-verify' image..." retry_default docker build -t bats-verify -f Dockerfile-bats . echo "Checking bats image..." - docker run --rm -t bats-verify -v + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 --rm -t bats-verify -v # pre-build the consul+envoy container echo "Rebuilding 'consul-dev-envoy:${ENVOY_VERSION}' image..." @@ -609,15 +602,43 @@ function run_container { "run_container_$1" } +# Run the common service container. By default, uses fortio/fortio. +# +# To use mendhak/http-https-echo, set SERVICE_CONTAINER=echo in vars.sh. +# +# To provide a custom docker run command for test containers, override +# common_run_container_service in vars.sh (which will be sourced prior to +# invocation). Use $(container_name_prev) in the custom function to get +# the correct effective container name. See common_run_container-fortio +# for the expected args list. function common_run_container_service { - local service="$1" - local CLUSTER="$2" - local httpPort="$3" - local grpcPort="$4" + local serviceContainer=${SERVICE_CONTAINER:-fortio} + local containerName=$(container_name_prev) + + case "$serviceContainer" in + fortio) + common_run_container-fortio "$containerName" "$@" + ;; + echo) + common_run_container-echo "$containerName" "$@" + ;; + *) + echo "Unknown common run container: $runContainer" + return 1 + ;; + esac +} - docker run -d --name $(container_name_prev) \ +function common_run_container-fortio { + local containerName="$1" + local service="$2" + local cluster="$3" + local httpPort="$4" + local grpcPort="$5" + + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $containerName \ -e "FORTIO_NAME=${service}" \ - $(network_snippet $CLUSTER) \ + $(network_snippet $cluster) \ "${HASHICORP_DOCKER_PROXY}/fortio/fortio" \ server \ -http-port ":$httpPort" \ @@ -625,6 +646,25 @@ function common_run_container_service { -redirect-port disabled >/dev/null } +# Alternative to Fortio, which has limited ability to echo back arbitrary +# requests (only one pre-determined debug path), and uses Go's net/http, which +# force-normalizes paths. Useful for verifying HTTP request parameters sent by +# Envoy to the upstream. +function common_run_container-echo { + local containerName="$1" + local cluster="$3" + local httpPort="$4" + + # HTTPS_PORT=0 will randomly assign a port number. It must be set, otherwise + # multiple containers on same network will fail due to using the same default port. + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $containerName \ + -e "HTTP_PORT=${httpPort}" \ + -e "HTTPS_PORT=0" \ + $(network_snippet $cluster) \ + ${HASHICORP_DOCKER_PROXY}/mendhak/http-https-echo:34 >/dev/null +} + + function run_container_s1 { common_run_container_service s1 primary 8080 8079 } @@ -696,7 +736,7 @@ function common_run_container_sidecar_proxy { # despite separate containers that don't share IPC namespace. Not quite # sure how this happens but may be due to unix socket being in some shared # location? - docker run -d --name $(container_name_prev) \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $(container_name_prev) \ $WORKDIR_SNIPPET \ $(network_snippet $CLUSTER) \ $(aws_snippet) \ @@ -717,7 +757,7 @@ function run_container_s1-ap1-sidecar-proxy { } function run_container_s1-sidecar-proxy-consul-exec { - docker run -d --name $(container_name) \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $(container_name) \ $(network_snippet primary) \ consul-dev-envoy:${ENVOY_VERSION} \ consul connect envoy -sidecar-for s1 \ @@ -783,7 +823,7 @@ function common_run_container_gateway { # despite separate containers that don't share IPC namespace. Not quite # sure how this happens but may be due to unix socket being in some shared # location? - docker run -d --name $(container_name_prev) \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $(container_name_prev) \ $WORKDIR_SNIPPET \ $(network_snippet $DC) \ $(aws_snippet) \ @@ -824,7 +864,7 @@ function run_container_fake-statsd { # This magic SYSTEM incantation is needed since Envoy doesn't add newlines and so # we need each packet to be passed to echo to add a new line before # appending. - docker run -d --name $(container_name) \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $(container_name) \ $WORKDIR_SNIPPET \ $(network_snippet primary) \ "${HASHICORP_DOCKER_PROXY}/alpine/socat:1.7.3.4-r1" \ @@ -833,14 +873,14 @@ function run_container_fake-statsd { } function run_container_zipkin { - docker run -d --name $(container_name) \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $(container_name) \ $WORKDIR_SNIPPET \ $(network_snippet primary) \ "${HASHICORP_DOCKER_PROXY}/openzipkin/zipkin" } function run_container_jaeger { - docker run -d --name $(container_name) \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $(container_name) \ $WORKDIR_SNIPPET \ $(network_snippet primary) \ "${HASHICORP_DOCKER_PROXY}/jaegertracing/all-in-one:1.11" \ @@ -848,7 +888,7 @@ function run_container_jaeger { } function run_container_test-sds-server { - docker run -d --name $(container_name) \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $(container_name) \ $WORKDIR_SNIPPET \ $(network_snippet primary) \ "test-sds-server" @@ -863,7 +903,7 @@ function container_name_prev { # This is a debugging tool. Run via './run-tests.sh debug_dump_volumes' function debug_dump_volumes { - docker run --rm -it \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 --rm -it \ $WORKDIR_SNIPPET \ -v ./:/cwd \ --net=none \ @@ -891,7 +931,7 @@ function common_run_container_tcpdump { retry_default docker build -t envoy-tcpdump -f Dockerfile-tcpdump . - docker run -d --name $(container_name_prev) \ + docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 -d --name $(container_name_prev) \ $(network_snippet $DC) \ -v $(pwd)/workdir/${DC}/envoy/:/data \ --privileged \ diff --git a/test/integration/connect/envoy/test-sds-server/go.mod b/test/integration/connect/envoy/test-sds-server/go.mod index 48bc8283bbf2..796196a3b535 100644 --- a/test/integration/connect/envoy/test-sds-server/go.mod +++ b/test/integration/connect/envoy/test-sds-server/go.mod @@ -3,11 +3,11 @@ module test-sds-server go 1.16 require ( - github.com/envoyproxy/go-control-plane v0.11.1 - github.com/fatih/color v1.14.1 // indirect - github.com/hashicorp/consul v1.15.2 + github.com/envoyproxy/go-control-plane v0.12.0 + github.com/fatih/color v1.16.0 // indirect + github.com/hashicorp/consul v1.18.1 + github.com/hashicorp/consul/sdk v0.16.0 // indirect github.com/hashicorp/go-hclog v1.5.0 - github.com/hashicorp/go-uuid v1.0.3 // indirect - golang.org/x/net v0.17.0 // indirect - google.golang.org/grpc v1.56.3 + golang.org/x/net v0.24.0 // indirect + google.golang.org/grpc v1.58.3 ) diff --git a/test/integration/connect/envoy/test-sds-server/go.sum b/test/integration/connect/envoy/test-sds-server/go.sum index 9a4f641fcfbb..1f0fba4baa62 100644 --- a/test/integration/connect/envoy/test-sds-server/go.sum +++ b/test/integration/connect/envoy/test-sds-server/go.sum @@ -1,7 +1,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.41.0/go.mod h1:OauMR7DV8fzvZIl2qg6rkaIhD/vmgk4iwEw/h6ercmg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= @@ -37,33 +36,43 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= +cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= +cloud.google.com/go/accessapproval v1.7.1/go.mod h1:JYczztsHRMK7NTXb6Xw+dwbs/WnOJxbo/2mTI+Kgg68= cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= +cloud.google.com/go/accesscontextmanager v1.8.0/go.mod h1:uI+AI/r1oyWK99NN8cQ3UK76AMelMzgZCvJfsi2c+ps= +cloud.google.com/go/accesscontextmanager v1.8.1/go.mod h1:JFJHfvuaTC+++1iL1coPiG1eu5D24db2wXCDWDjIrxo= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= +cloud.google.com/go/aiplatform v1.45.0/go.mod h1:Iu2Q7sC7QGhXUeOhAj/oCK9a+ULz1O4AotZiqjQ8MYA= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= +cloud.google.com/go/analytics v0.21.2/go.mod h1:U8dcUtmDmjrmUTnnnRnI4m6zKn/yaA5N9RlEkYFHpQo= cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= +cloud.google.com/go/apigateway v1.6.1/go.mod h1:ufAS3wpbRjqfZrzpvLC2oh0MFlpRJm2E/ts25yyqmXA= cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= +cloud.google.com/go/apigeeconnect v1.6.1/go.mod h1:C4awq7x0JpLtrlQCr8AzVIzAaYgngRqWf9S5Uhg+wWs= cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= +cloud.google.com/go/apigeeregistry v0.7.1/go.mod h1:1XgyjZye4Mqtw7T9TsY4NW10U7BojBvG4RMD+vRDrIw= cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= @@ -72,10 +81,12 @@ cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodC cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= +cloud.google.com/go/appengine v1.8.1/go.mod h1:6NJXGLVhZCN9aQ/AEDvmfzKEfoYBlfB80/BHiKVputY= cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= +cloud.google.com/go/area120 v0.8.1/go.mod h1:BVfZpGpB7KFVNxPiQBuHkX6Ed0rS51xIgmGyjrAfzsg= cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= @@ -84,6 +95,7 @@ cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1 cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= +cloud.google.com/go/artifactregistry v1.14.1/go.mod h1:nxVdG19jTaSTu7yA7+VbWL346r3rIdkZ142BSQqhn5E= cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= @@ -92,17 +104,20 @@ cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAt cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= +cloud.google.com/go/asset v1.14.1/go.mod h1:4bEJ3dnHCqWCDbWJ/6Vn7GVI9LerSi7Rfdi03hd+WTQ= cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= +cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= +cloud.google.com/go/automl v1.13.1/go.mod h1:1aowgAHWYZU27MybSCFiukPO7xnyawv7pt3zK4bheQE= cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= @@ -113,6 +128,7 @@ cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckm cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= +cloud.google.com/go/beyondcorp v0.6.1/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -126,38 +142,46 @@ cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/Zur cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= +cloud.google.com/go/bigquery v1.52.0/go.mod h1:3b/iXjRQGU4nKa87cXeg6/gogLjO8C6PmuM8i5Bi/u4= cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= +cloud.google.com/go/billing v1.16.0/go.mod h1:y8vx09JSSJG02k5QxbycNRrN7FGZB6F3CAcgum7jvGA= cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= +cloud.google.com/go/binaryauthorization v1.6.1/go.mod h1:TKt4pa8xhowwffiBmbrbcxijJRZED4zrqnwZ1lKH51U= cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= +cloud.google.com/go/certificatemanager v1.7.1/go.mod h1:iW8J3nG6SaRYImIa+wXQ0g8IgoofDFRp5UMzaNk1UqI= cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= +cloud.google.com/go/channel v1.16.0/go.mod h1:eN/q1PFSl5gyu0dYdmxNXscY/4Fi7ABmeHCJNf/oHmc= cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= +cloud.google.com/go/cloudbuild v1.10.1/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU= cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= +cloud.google.com/go/clouddms v1.6.1/go.mod h1:Ygo1vL52Ov4TBZQquhz5fiw2CQ58gvu+PlS6PVXCpZI= cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= +cloud.google.com/go/cloudtasks v1.11.1/go.mod h1:a9udmnou9KO2iulGscKR0qBYjreuX8oHwpmFsKspEvM= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= @@ -173,6 +197,9 @@ cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63 cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= +cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= @@ -180,15 +207,18 @@ cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2Aawl cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= +cloud.google.com/go/contactcenterinsights v1.9.1/go.mod h1:bsg/R7zGLYMVxFFzfh9ooLTruLRCG9fnzhH9KznHhbM= cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= +cloud.google.com/go/container v1.22.1/go.mod h1:lTNExE2R7f+DLbAN+rJiKTisauFCaoDq6NURZ83eVH4= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= +cloud.google.com/go/containeranalysis v0.10.1/go.mod h1:Ya2jiILITMY68ZLPaogjmOMNkwsDrWBSTyBubGXO7j0= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= @@ -197,44 +227,56 @@ cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOX cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= +cloud.google.com/go/datacatalog v1.14.0/go.mod h1:h0PrGtlihoutNMp/uvwhawLQ9+c63Kz65UFqh49Yo+E= +cloud.google.com/go/datacatalog v1.14.1/go.mod h1:d2CevwTG4yedZilwe+v3E3ZBDRMobQfSG/a6cCCN5R4= cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= +cloud.google.com/go/dataflow v0.9.1/go.mod h1:Wp7s32QjYuQDWqJPFFlnBKhkAtiFpMTdg00qGbnIHVw= cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= +cloud.google.com/go/dataform v0.8.1/go.mod h1:3BhPSiw8xmppbgzeBbmDvmSWlwouuJkXsXsb8UBih9M= cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= +cloud.google.com/go/datafusion v1.7.1/go.mod h1:KpoTBbFmoToDExJUso/fcCiguGDk7MEzOWXUsJo0wsI= cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= +cloud.google.com/go/datalabeling v0.8.1/go.mod h1:XS62LBSVPbYR54GfYQsPXZjTW8UxCK2fkDciSrpRFdY= cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= +cloud.google.com/go/dataplex v1.8.1/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE= cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= +cloud.google.com/go/dataqna v0.8.1/go.mod h1:zxZM0Bl6liMePWsHA8RMGAfmTG34vJMapbHAxQ5+WA8= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= +cloud.google.com/go/datastore v1.12.0/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70= +cloud.google.com/go/datastore v1.12.1/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70= cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= +cloud.google.com/go/datastream v1.9.1/go.mod h1:hqnmr8kdUBmrnk65k5wNRoHSCYksvpdZIcZIEl8h43Q= cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= +cloud.google.com/go/deploy v1.11.0/go.mod h1:tKuSUV5pXbn67KiubiUNUejqLs4f5cxxiCNCeyl0F2g= cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= @@ -243,35 +285,44 @@ cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFM cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= +cloud.google.com/go/dialogflow v1.38.0/go.mod h1:L7jnH+JL2mtmdChzAIcXQHXMvQkE3U4hTaNltEuxXn4= cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= +cloud.google.com/go/dlp v1.10.1/go.mod h1:IM8BWz1iJd8njcNcG0+Kyd9OPnqnRNkDV8j42VT5KOI= cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= +cloud.google.com/go/documentai v1.20.0/go.mod h1:yJkInoMcK0qNAEdRnqY/D5asy73tnPe88I1YTZT+a8E= cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= +cloud.google.com/go/domains v0.9.1/go.mod h1:aOp1c0MbejQQ2Pjf1iJvnVyT+z6R6s8pX66KaCSDYfE= cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= +cloud.google.com/go/edgecontainer v1.1.1/go.mod h1:O5bYcS//7MELQZs3+7mabRqoWQhXCzenBu0R8bz2rwk= cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= +cloud.google.com/go/essentialcontacts v1.6.2/go.mod h1:T2tB6tX+TRak7i88Fb2N9Ok3PvY3UNbUsMag9/BARh4= cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= +cloud.google.com/go/eventarc v1.12.1/go.mod h1:mAFCW6lukH5+IZjkvrEss+jmt2kOdYlN8aMx3sRJiAI= cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= +cloud.google.com/go/filestore v1.7.1/go.mod h1:y10jsorq40JJnjR/lQ8AfFbbcGlw3g+Dp8oN7i7FjV4= cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/firestore v1.11.0/go.mod h1:b38dKhgzlmNNGTNZZwe7ZRFEuRab1Hay3/DBsIGKKy4= cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= @@ -279,28 +330,35 @@ cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5Uwt cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= +cloud.google.com/go/functions v1.15.1/go.mod h1:P5yNWUTkyU+LvW/S9O6V+V423VZooALQlqoXdoPz5AE= cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= +cloud.google.com/go/gaming v1.10.1/go.mod h1:XQQvtfP8Rb9Rxnxm5wFVpAp9zCQkJi2bLIb7iHGwB3s= cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= +cloud.google.com/go/gkeconnect v0.8.1/go.mod h1:KWiK1g9sDLZqhxB2xEuPV8V9NYzrqTUmQR9shJHpOZw= cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= +cloud.google.com/go/gkehub v0.14.1/go.mod h1:VEXKIJZ2avzrbd7u+zeMtW00Y8ddk/4V9511C9CQGTY= cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= +cloud.google.com/go/gkemulticloud v0.6.1/go.mod h1:kbZ3HKyTsiwqKX7Yw56+wUGwwNZViRnxWK2DVknXWfw= cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/grafeas v0.3.0/go.mod h1:P7hgN24EyONOTMyeJH6DxG4zD7fwiYa5Q6GUgyFSOU8= cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= +cloud.google.com/go/gsuiteaddons v1.6.1/go.mod h1:CodrdOqRZcLp5WOwejHWYBjZvfY0kOphkAKpF/3qdZY= cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= @@ -310,18 +368,24 @@ cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGE cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.0.1/go.mod h1:yR3tmSL8BcZB4bxByRv2jkSIahVmCtfKZwLYGBalRE8= +cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk= +cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= +cloud.google.com/go/iap v1.8.1/go.mod h1:sJCbeqg3mvWLqjZNsI6dfAtbbV1DL2Rl7e1mTyXYREQ= cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= +cloud.google.com/go/ids v1.4.1/go.mod h1:np41ed8YMU8zOgv53MMMoCntLTn2lF+SUzlM+O3u/jw= cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= +cloud.google.com/go/iot v1.7.1/go.mod h1:46Mgw7ev1k9KqK1ao0ayW9h0lI+3hxeanz+L1zmbbbk= cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= @@ -329,91 +393,117 @@ cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4 cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= +cloud.google.com/go/kms v1.11.0/go.mod h1:hwdiYC0xjnWsKQQCQQmIQnS9asjYVSK6jtXm+zFqXLM= +cloud.google.com/go/kms v1.12.1/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= +cloud.google.com/go/language v1.10.1/go.mod h1:CPp94nsdVNiQEt1CNjF5WkTcisLiHPyIbMhvR8H2AW0= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= +cloud.google.com/go/lifesciences v0.9.1/go.mod h1:hACAOd1fFbCGLr/+weUKRAJas82Y4vrL3O5326N//Wc= cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/longrunning v0.4.2/go.mod h1:OHrnaYyLUV6oqwh0xiS7e5sLQhP1m0QU9R+WhGDMgIQ= +cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= +cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= +cloud.google.com/go/managedidentities v1.6.1/go.mod h1:h/irGhTN2SkZ64F43tfGPMbHnypMbu4RB3yl8YcuEak= cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= +cloud.google.com/go/mediatranslation v0.8.1/go.mod h1:L/7hBdEYbYHQJhX2sldtTO5SZZ1C1vkapubj0T2aGig= cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= +cloud.google.com/go/memcache v1.10.1/go.mod h1:47YRQIarv4I3QS5+hoETgKO40InqzLP6kpNLvyXuyaA= cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= +cloud.google.com/go/metastore v1.11.1/go.mod h1:uZuSo80U3Wd4zi6C22ZZliOUJ3XeM/MlYi/z5OAOWRA= cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= +cloud.google.com/go/monitoring v1.15.1/go.mod h1:lADlSAlFdbqQuwwpaImhsJXu1QSdd3ojypXrFSMr2rM= cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= +cloud.google.com/go/networkconnectivity v1.12.1/go.mod h1:PelxSWYM7Sh9/guf8CFhi6vIqf19Ir/sbfZRUwXh92E= cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= +cloud.google.com/go/networkmanagement v1.8.0/go.mod h1:Ho/BUGmtyEqrttTgWEe7m+8vDdK74ibQc+Be0q7Fof0= cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= +cloud.google.com/go/networksecurity v0.9.1/go.mod h1:MCMdxOKQ30wsBI1eI659f9kEp4wuuAueoC9AJKSPWZQ= cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= +cloud.google.com/go/notebooks v1.9.1/go.mod h1:zqG9/gk05JrzgBt4ghLzEepPHNwE5jgPcHZRKhlC1A8= cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= +cloud.google.com/go/optimization v1.4.1/go.mod h1:j64vZQP7h9bO49m2rVaTVoNM0vEBEN5eKPUPbZyXOrk= cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= +cloud.google.com/go/orchestration v1.8.1/go.mod h1:4sluRF3wgbYVRqz7zJ1/EUNc90TTprliq9477fGobD8= cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= +cloud.google.com/go/orgpolicy v1.11.0/go.mod h1:2RK748+FtVvnfuynxBzdnyu7sygtoZa1za/0ZfpOs1M= +cloud.google.com/go/orgpolicy v1.11.1/go.mod h1:8+E3jQcpZJQliP+zaFfayC2Pg5bmhuLK755wKhIIUCE= cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= +cloud.google.com/go/osconfig v1.12.0/go.mod h1:8f/PaYzoS3JMVfdfTubkowZYGmAhUCjjwnjqWI7NVBc= +cloud.google.com/go/osconfig v1.12.1/go.mod h1:4CjBxND0gswz2gfYRCUoUzCm9zCABp91EeTtWXyz0tE= cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= +cloud.google.com/go/oslogin v1.10.1/go.mod h1:x692z7yAue5nE7CsSnoG0aaMbNoRJRXO4sn73R+ZqAs= cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= +cloud.google.com/go/phishingprotection v0.8.1/go.mod h1:AxonW7GovcA8qdEk13NfHq9hNx5KPtfxXNeUxTDxB6I= cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= +cloud.google.com/go/policytroubleshooter v1.7.1/go.mod h1:0NaT5v3Ag1M7U5r0GfDCpUFkWd9YqpubBWsQlhanRv0= cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= +cloud.google.com/go/privatecatalog v0.9.1/go.mod h1:0XlDXW2unJXdf9zFz968Hp35gl/bhF4twwpXZAW50JA= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -422,9 +512,11 @@ cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcd cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= +cloud.google.com/go/pubsub v1.32.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc= cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= +cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= @@ -433,32 +525,39 @@ cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= +cloud.google.com/go/recaptchaenterprise/v2 v2.7.2/go.mod h1:kR0KjsJS7Jt1YSyWFkseQ756D45kaYNTlDPPaRAvDBU= cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= +cloud.google.com/go/recommendationengine v0.8.1/go.mod h1:MrZihWwtFYWDzE6Hz5nKcNz3gLizXVIDI/o3G1DLcrE= cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= +cloud.google.com/go/recommender v1.10.1/go.mod h1:XFvrE4Suqn5Cq0Lf+mCP6oBHD/yRMA8XxP5sb7Q7gpA= cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= +cloud.google.com/go/redis v1.13.1/go.mod h1:VP7DGLpE91M6bcsDdMuyCm2hIpB6Vp2hI090Mfd1tcg= cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= +cloud.google.com/go/resourcemanager v1.9.1/go.mod h1:dVCuosgrh1tINZ/RwBufr8lULmWGOkPS8gL5gqyjdT8= cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= +cloud.google.com/go/resourcesettings v1.6.1/go.mod h1:M7mk9PIZrC5Fgsu1kZJci6mpgN8o0IUzVx3eJU3y4Jw= cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= +cloud.google.com/go/retail v1.14.1/go.mod h1:y3Wv3Vr2k54dLNIrCzenyKG8g8dhvhncT2NcNjb/6gE= cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= @@ -469,10 +568,12 @@ cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRr cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= +cloud.google.com/go/scheduler v1.10.1/go.mod h1:R63Ldltd47Bs4gnhQkmNDse5w8gBRrhObZ54PxgR2Oo= cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= +cloud.google.com/go/secretmanager v1.11.1/go.mod h1:znq9JlXgTNdBeQk9TBW/FnR/W4uChEKGeqQWAJ8SXFw= cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= @@ -480,12 +581,14 @@ cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= +cloud.google.com/go/security v1.15.1/go.mod h1:MvTnnbsWnehoizHi09zoiZob0iCHVcL4AUBj76h9fXA= cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= +cloud.google.com/go/securitycenter v1.23.0/go.mod h1:8pwQ4n+Y9WCWM278R8W3nF65QtY172h4S8aXyI9/hsQ= cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= @@ -497,6 +600,7 @@ cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPj cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= +cloud.google.com/go/servicedirectory v1.10.1/go.mod h1:Xv0YVH8s4pVOwfM/1eMTl0XJ6bzIOSLDt8f8eLaGOxQ= cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= @@ -508,15 +612,18 @@ cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DR cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= +cloud.google.com/go/shell v1.7.1/go.mod h1:u1RaM+huXFaTojTbW4g9P5emOrrmLE69KrxqQahKn4g= cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= +cloud.google.com/go/spanner v1.47.0/go.mod h1:IXsJwVW2j4UKs0eYDqodab6HgGuA1bViSqW4uH9lfUI= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= +cloud.google.com/go/speech v1.17.1/go.mod h1:8rVNzU43tQvxDaGvqOhpDqgkJTFowBpDvCJ14kGlJYo= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= @@ -528,41 +635,50 @@ cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeL cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= +cloud.google.com/go/storagetransfer v1.10.0/go.mod h1:DM4sTlSmGiNczmV6iZyceIh2dbs+7z2Ayg6YAiQlYfA= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= +cloud.google.com/go/talent v1.6.2/go.mod h1:CbGvmKCG61mkdjcqTcLOkb2ZN1SrQI8MDyma2l7VD24= cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= +cloud.google.com/go/texttospeech v1.7.1/go.mod h1:m7QfG5IXxeneGqTapXNxv2ItxP/FS0hCZBwXYqucgSk= cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= +cloud.google.com/go/tpu v1.6.1/go.mod h1:sOdcHVIgDEEOKuqUoi6Fq53MKHJAtOwtz0GuKsWSH3E= cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= +cloud.google.com/go/trace v1.10.1/go.mod h1:gbtL94KE5AJLH3y+WVpfWILmqgc6dXcqgNXdOPAQTYk= cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/translate v1.8.1/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs= cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/video v1.17.1/go.mod h1:9qmqPqw/Ib2tLqaeHgtakU+l5TcJxCJbhFXM7UJjVzU= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= +cloud.google.com/go/videointelligence v1.11.1/go.mod h1:76xn/8InyQHarjTWsBR058SmlPCwQjgcvoW0aZykOvo= cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= @@ -570,143 +686,139 @@ cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= +cloud.google.com/go/vision/v2 v2.7.2/go.mod h1:jKa8oSYBWhYiXarHPvP4USxYANYUEdEsQrloLjrSwJU= cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= +cloud.google.com/go/vmmigration v1.7.1/go.mod h1:WD+5z7a/IpZ5bKK//YmT9E047AD+rjycCAvyMxGJbro= cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= +cloud.google.com/go/vmwareengine v0.4.1/go.mod h1:Px64x+BvjPZwWuc4HdmVhoygcXqEkGHXoa7uyfTgSI0= cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= +cloud.google.com/go/vpcaccess v1.7.1/go.mod h1:FogoD46/ZU+JUBX9D606X21EnxiszYi2tArQwLY4SXs= cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= +cloud.google.com/go/webrisk v1.9.1/go.mod h1:4GCmXKcOa2BZcZPn6DCEvE7HypmEJcJkr4mtM+sqYPc= cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= +cloud.google.com/go/websecurityscanner v1.6.1/go.mod h1:Njgaw3rttgRHXzwCB8kgCYqv5/rGpFCsBOvPbYgszpg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= -contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= +cloud.google.com/go/workflows v1.11.1/go.mod h1:Z+t10G1wF7h8LgdY/EmRcQY8ptBD/nvofaL6FqlET6g= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= -github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v32.6.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v44.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= -github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest v0.9.2/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= github.com/Azure/go-autorest/autorest v0.11.0/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= -github.com/Azure/go-autorest/autorest/adal v0.2.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= +github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= +github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/azure/auth v0.1.0/go.mod h1:Gf7/i2FUpyb/sGBLIFxTBzrNzBo7aPXXE3ZVeDRwdpM= -github.com/Azure/go-autorest/autorest/azure/auth v0.4.1/go.mod h1:5TgH20II424SXIV9YDBsO4rBCKsh39Vbx9DvhJZZ8rU= +github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/azure/auth v0.5.0/go.mod h1:QRTvSZQpxqm8mSErhnbI+tANIBAKP7B+UIE2z4ypUO0= -github.com/Azure/go-autorest/autorest/azure/cli v0.1.0/go.mod h1:Dk8CUAt/b/PzkfeRsWzVG9Yj3ps8mS8ECztu43rdU8U= -github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= github.com/Azure/go-autorest/autorest/azure/cli v0.4.0/go.mod h1:JljT387FplPzBA31vUcvsetLKF3pec5bdAxjVU4kI2s= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= +github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/zstd v1.3.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/DataDog/datadog-go v4.8.2+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/HdrHistogram/hdrhistogram-go v1.0.1/go.mod h1:BWJ+nMSHY3L41Zj7CA3uXnloDp7xxV0YvstAE7nKTaM= github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= -github.com/Microsoft/go-winio v0.4.3/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig/v3 v3.2.0/go.mod h1:tWhwTbUTndesPNeF0C900vKoq283u6zp4APT9vaF3SI= +github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/sarama v1.21.0/go.mod h1:yuqtN/pe8cXRWG5zPaO7hCfNJp5MwmkoJEoLjkm5tCQ= github.com/Shopify/sarama v1.26.1/go.mod h1:NbSGBSSndYaIhRcBtY9V0U7AyH+x71bG668AuWys/yU= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw= +github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= -github.com/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k= -github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ= -github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.146/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= +github.com/aliyun/alibaba-cloud-sdk-go v1.62.156/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/arrow/go/v12 v12.0.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= +github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= +github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= +github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= github.com/armon/go-metrics v0.3.8/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.25.41/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= github.com/aws/aws-sdk-go v1.42.34/go.mod h1:OGr6lGMAKGlG9CVrYnWYDKIyb829c6EVBRjxqjmPepc= -github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= +github.com/aws/aws-sdk-go v1.44.289/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/immutable v0.4.0/go.mod h1:iAr8OjJGLnLmVUr9MZ/rz4PWUy6Ouc2JLYuMArmvAJM= github.com/benmathews/bench v0.0.0-20210120214102-f7c75b9ef6e7/go.mod h1:peX7BEhSFSvvnxdido50pUMhlFi24dVgtTU1oZkHTUU= github.com/benmathews/hdrhistogram-writer v0.0.0-20180430173243-73b8d31ba571/go.mod h1:W24iTD3jetRjSLj2yz0IBNF6wKdbRUvBMG5oaw4ZbzM= @@ -720,26 +832,21 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/caddyserver/caddy v1.0.4/go.mod h1:uruyfVsyMcDb3IOzSKsi1x0wOjy1my/PxOSTcD+24jM= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= -github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -757,57 +864,51 @@ github.com/cncf/xds/go v0.0.0-20230428030218-4003588d1b74/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/coredns/coredns v1.6.6/go.mod h1:Bdcnka9HmKGYj12ZIDF3lpQSfDHSsMc85Wj9xEyZUts= -github.com/coredns/federation v0.0.0-20190818181423-e032b096babe/go.mod h1:MoqTEFX8GlnKkyq8eBCF94VzkNAOgjdlCJ+Pz/oCLPk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.27+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-oidc/v3 v3.9.0/go.mod h1:rTKz2PYwftcrtoCzV5g5kvfJoWcm0Mk8AF8y1iAQro4= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190212144455-93d5ec2c7f76/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok= +github.com/cosiner/argv v0.1.0/go.mod h1:EusR6TucWKX+zFgtdUsKT2Cvg45K5rtpCcWz4hK06d8= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g= +github.com/deckarep/golang-set/v2 v2.3.1/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= -github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/digitalocean/godo v1.7.5/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= github.com/digitalocean/godo v1.10.0/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= +github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= -github.com/dnstap/golang-dnstap v0.0.0-20170829151710-2cf77a2b5e11/go.mod h1:s1PfVYYVmTMgCSPtho4LKBDecEHJWtiVDPNv78Z985U= -github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -820,28 +921,28 @@ github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go. github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= -github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e/go.mod h1:/NGEcKqwNq3HAS2vCqHfsPx9sJZbkiNQ6dGx9gTE/NA= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/envoyproxy/protoc-gen-validate v1.0.1 h1:kt9FtLiooDc0vbwTLhdg3dyNX1K9Qwa1EK9LcD4jVUQ= github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs= -github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= -github.com/farsightsec/golang-framestream v0.0.0-20181102145529-8a0cb8ba8710/go.mod h1:eNde4IQyEiA5br02AouhEHCu3p3UzrCdFR4LuQHklMI= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= @@ -849,18 +950,17 @@ github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o= github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fullstorydev/grpchan v1.1.1/go.mod h1:f4HpiV8V6htfY/K44GWV1ESQzHBTq7DinhzqQ95lpgc= github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/go-acme/lego/v3 v3.1.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE= -github.com/go-acme/lego/v3 v3.2.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE= github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= @@ -869,11 +969,13 @@ github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmn github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ini/ini v1.44.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= @@ -882,6 +984,13 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -892,7 +1001,8 @@ github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2 github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ= github.com/go-openapi/analysis v0.19.16/go.mod h1:GLInF007N83Ad3m8a/CbQ5TPzdnGT7workfHwuVjNVk= github.com/go-openapi/analysis v0.20.0/go.mod h1:BMchjvaHDykmRMsK40iPtvyOfFdMMxlOmQr9FBZk+Og= -github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= +github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= +github.com/go-openapi/analysis v0.21.5/go.mod h1:25YcZosX9Lwz2wBsrFrrsL8bmjjXdlyP6zsr2AMy29M= github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= @@ -903,19 +1013,27 @@ github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpX github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= github.com/go-openapi/errors v0.20.1/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= +github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= +github.com/go-openapi/errors v0.21.0/go.mod h1:jxNTMUxRCKj65yb/okJGEtahVd7uvWnuWfj53bse4ho= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= +github.com/go-openapi/jsonpointer v0.20.1/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/jsonreference v0.20.3/go.mod h1:FviDZ46i9ivh810gqzFLl5NttD5q3tSlMLqLr6okedM= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= @@ -926,14 +1044,15 @@ github.com/go-openapi/loads v0.19.6/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hs github.com/go-openapi/loads v0.19.7/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hsKvYBNEGVc= github.com/go-openapi/loads v0.20.0/go.mod h1:2LhKquiE513rN5xC6Aan6lYOSddlL8Mp20AW9kpviM4= github.com/go-openapi/loads v0.20.2/go.mod h1:hTVUotJ+UonAMMZsvakEgmWKgtulweO9vYP2bQYKA/o= -github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= +github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= +github.com/go-openapi/loads v0.21.3/go.mod h1:Y3aMR24iHbKHppOj91nQ/SHc0cuPbAr4ndY4a02xydc= github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98= github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk= -github.com/go-openapi/runtime v0.24.1/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk= +github.com/go-openapi/runtime v0.26.2/go.mod h1:O034jyRZ557uJKzngbMDJXkcKJVzXJiymdSfgejrcRw= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= @@ -945,7 +1064,10 @@ github.com/go-openapi/spec v0.19.15/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFu github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU= github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ= github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= +github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/spec v0.20.11/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/spec v0.20.12/go.mod h1:iSCgnBcwbMW9SfzJb8iYynXvcY6C/QFrI7otzF7xGM4= github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= @@ -955,10 +1077,10 @@ github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= github.com/go-openapi/strfmt v0.19.11/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= github.com/go-openapi/strfmt v0.20.0/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= -github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= -github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.2/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= +github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew= +github.com/go-openapi/strfmt v0.21.8/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew= +github.com/go-openapi/strfmt v0.21.10/go.mod h1:vNDMwbilnl7xKiO/Ve/8H8Bb2JIInBnH+lqiw6QWgis= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= @@ -971,6 +1093,9 @@ github.com/go-openapi/swag v0.19.13/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/ github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.5/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo= @@ -979,14 +1104,16 @@ github.com/go-openapi/validate v0.19.12/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0 github.com/go-openapi/validate v0.19.15/go.mod h1:tbn/fdOwYHgrhPBzidZfJC2MIVvs9GA7monOmWBbeCI= github.com/go-openapi/validate v0.20.1/go.mod h1:b60iJT+xNNLfaQJUqLI7946tYiFEOuE9E4k54HpKcJ0= github.com/go-openapi/validate v0.20.2/go.mod h1:e7OJoKNgd0twXZwIn0A43tHbvIcr/rZIVCbJBpTUoY0= -github.com/go-openapi/validate v0.21.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= +github.com/go-openapi/validate v0.22.3/go.mod h1:kVxh31KbfsxU8ZyoHaDbLBWU5CnMdqBUEtadQ2G4d5M= +github.com/go-openapi/validate v0.22.4/go.mod h1:qm6O8ZIcPVdSY5219468Jv7kBdGvkiZLPOmqnqTUZ2A= github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= @@ -1014,14 +1141,14 @@ github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/V github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gocql/gocql v0.0.0-20200228163523-cd4b606dd2fb/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= @@ -1031,6 +1158,7 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -1041,8 +1169,8 @@ github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71 github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= @@ -1059,17 +1187,18 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -1088,7 +1217,6 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -1109,15 +1237,20 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= +github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2/go.mod h1:DavVbd41y+b7ukKDmlnPR4nGYmkWXR6vHUkjQNiHPBs= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= @@ -1134,44 +1267,41 @@ github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqE github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= +github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= -github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= -github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/gulducat/go-run-programs v0.1.0/go.mod h1:6BIzJV6kUmQC9oWm1umtjUN6x2+9xNe22suw1M9aq+A= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= -github.com/hashicorp/consul v1.15.2 h1:asG6/ZyA1Z5dw0SuhZ5sh/SG9605NI/L/PNJtCnl93M= -github.com/hashicorp/consul v1.15.2/go.mod h1:1pu3llMOz2pwT+KU3Hxqycm//67l9znFCxyhe2ufRHo= +github.com/hashi-derek/grpc-proxy v0.0.0-20231207191910-191266484d75/go.mod h1:5eEnHfK72jOkp4gC1dI/Q/E9MFNOM/ewE/vql5ijV3g= +github.com/hashicorp/consul v1.18.1 h1:SxdPLBVWI5NeGt07xixHO9/OU1Vfj6DFqaidgdVVn9c= +github.com/hashicorp/consul v1.18.1/go.mod h1:kyyrJcHYNqCbHsg97v91OJJ085ANzTsOPvREnHiVZEk= github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706/go.mod h1:1Cs8FlmD1BfSQXJGcFLSV5FuIx1AbJP+EJGdxosoS2g= github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69/go.mod h1:svUZZDvotY8zTODknUePc6mZ9pX8nN0ViGwWcUSOBEA= -github.com/hashicorp/consul/api v1.20.0/go.mod h1:nR64eD44KQ59Of/ECwt2vUmIK2DKsDzAwTmwmLl8Wpo= -github.com/hashicorp/consul/envoyextensions v0.1.2/go.mod h1:N94DQQkgITiA40zuTQ/UdPOLAAWobgHfVT5u7wxE/aU= -github.com/hashicorp/consul/proto-public v0.2.1/go.mod h1:iWNlBDJIZQJC3bBiCThoqg9i7uk/4RQZYkqH1wiQrss= -github.com/hashicorp/consul/sdk v0.13.1 h1:EygWVWWMczTzXGpO93awkHFzfUka6hLYJ0qhETd+6lY= -github.com/hashicorp/consul/sdk v0.13.1/go.mod h1:SW/mM4LbKfqmMvcFu8v+eiQQ7oitXEFeiBe9StxERb0= -github.com/hashicorp/consul/troubleshoot v0.1.2/go.mod h1:q35QOtN7K5kFLPm2SXHBDD+PzsuBekcqTZuuoOTzbWA= +github.com/hashicorp/consul/api v1.26.1/go.mod h1:B4sQTeaSO16NtynqrAdwOlahJ7IUDZM9cj2420xYL8A= +github.com/hashicorp/consul/envoyextensions v0.5.1/go.mod h1:M/VMPmhwjksu66pxQ6RBKkQEI7Qn6RM8hSnIoJUgskI= +github.com/hashicorp/consul/proto-public v0.5.1/go.mod h1:SayEhfXS3DQDnW/vKSZXvkwDObg7XK60KTfrJcp0wrg= +github.com/hashicorp/consul/sdk v0.15.0/go.mod h1:r/OmRRPbHOe0yxNahLw7G9x5WG17E1BIECMtCjcPSNo= +github.com/hashicorp/consul/sdk v0.16.0 h1:SE9m0W6DEfgIVCJX7xU+iv/hUl4m/nxqMTnCdMxDpJ8= +github.com/hashicorp/consul/sdk v0.16.0/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A= +github.com/hashicorp/consul/troubleshoot v0.4.1/go.mod h1:2Ca1f4r4HZkO8NwtGBJ/9YX6EUgwWrZtvUnxB3UZuAA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.2/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU= @@ -1184,15 +1314,17 @@ github.com/hashicorp/go-connlimit v0.3.0/go.mod h1:OUj9FGL1tPIhl/2RCfzYHrIiWj+VV github.com/hashicorp/go-discover v0.0.0-20220714221025-1c234a67149a/go.mod h1:1xfdKvc3pe5WKxfUUHHOGaKMk7NLGhHY1jkyhKo6098= github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw= github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0/go.mod h1:xvb32K2keAc+R8DSFG2IwDcydK9DBQE+fGA5fsw6hSk= github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= @@ -1218,6 +1350,7 @@ github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2T github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= +github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= @@ -1232,12 +1365,15 @@ github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pB github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.0/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcdiag v0.5.1/go.mod h1:RMC2KkffN9uJ+5mFSaL67ZFVj4CDeetPF2d/53XpwXo= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hcp-scada-provider v0.2.0/go.mod h1:Q0WpS2RyhBKOPD4X/8oW7AJe7jA2HXB09EwDzwRTao0= +github.com/hashicorp/hcl/v2 v2.11.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= +github.com/hashicorp/hcl/v2 v2.14.1/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0= +github.com/hashicorp/hcp-scada-provider v0.2.4/go.mod h1:ZFTgGwkzNv99PLQjTsulzaCplCzOTBh0IUQsPKzrQFo= github.com/hashicorp/hcp-sdk-go v0.23.0/go.mod h1:/9UoDY2FYYA8lFaKBb2HmM/jKYZGANmf65q9QRc/cVw= -github.com/hashicorp/hcp-sdk-go v0.23.1-0.20220921131124-49168300a7dc/go.mod h1:/9UoDY2FYYA8lFaKBb2HmM/jKYZGANmf65q9QRc/cVw= +github.com/hashicorp/hcp-sdk-go v0.80.0/go.mod h1:vQ4fzdL1AmhIAbCw+4zmFe5Hbpajj3NvRWkJoVuxmAk= github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= @@ -1248,39 +1384,47 @@ github.com/hashicorp/raft v1.1.0/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7H github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= github.com/hashicorp/raft v1.3.11/go.mod h1:J8naEwc6XaaCfts7+28whSeRvCqTd6e20BlCU3LtEO4= github.com/hashicorp/raft v1.4.0/go.mod h1:nz64BIjXphDLATfKGG5RzHtNUPioLeKFsXEm88yTVew= +github.com/hashicorp/raft v1.5.0/go.mod h1:pKHB2mf/Y25u3AHNSXVRv+yT+WAnmeTX0BwVppVQV+M= github.com/hashicorp/raft-autopilot v0.1.6/go.mod h1:Af4jZBwaNOI+tXfIqIdbcAnh/UyyqIMj/pOISIfhArw= github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= github.com/hashicorp/raft-boltdb v0.0.0-20210409134258-03c10cc3d4ea/go.mod h1:qRd6nFJYYS6Iqnc/8HcUmko2/2Gw8qTFEmxDLii6W5I= github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0= github.com/hashicorp/raft-boltdb/v2 v2.2.2/go.mod h1:N8YgaZgNJLpZC+h+by7vDu5rzsRgONThTEeUS3zWbfY= -github.com/hashicorp/raft-wal v0.3.0/go.mod h1:A6vP5o8hGOs1LHfC1Okh9xPwWDcmb6Vvuz/QyqUXlOE= +github.com/hashicorp/raft-wal v0.4.1/go.mod h1:A6vP5o8hGOs1LHfC1Okh9xPwWDcmb6Vvuz/QyqUXlOE= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= +github.com/hashicorp/vault-plugin-auth-alicloud v0.14.0/go.mod h1:We3fJplmALwK1VpjwrLuXr/4QCQHYMdnXLHmLUU6Ntg= github.com/hashicorp/vault/api v1.8.0/go.mod h1:uJrw6D3y9Rv7hhmS17JQC50jbPDAZdjZoTtrCCxxs7E= -github.com/hashicorp/vault/api v1.8.2/go.mod h1:ML8aYzBIhY5m1MD1B2Q0JV89cC85YVH4t5kBaZiyVaE= +github.com/hashicorp/vault/api v1.8.3/go.mod h1:4g/9lj9lmuJQMtT6CmVMHC5FW1yENaVv+Nv4ZfG8fAg= github.com/hashicorp/vault/api/auth/gcp v0.3.0/go.mod h1:gnNBFOASYUaFunedTHOzdir7vKcHL3skWBUzEn263bo= github.com/hashicorp/vault/sdk v0.6.0/go.mod h1:+DRpzoXIdMvKc88R4qxr+edwy/RvH5QK8itmxLiDHLc= +github.com/hashicorp/vault/sdk v0.7.0/go.mod h1:KyfArJkhooyba7gYCKSq8v66QdqJmnbAxtV/OX1+JTs= github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35nTu0ey1EXjwNwPjI9xErAsoOCmcMb9GKvyxo= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/strcase v0.1.3/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/infobloxopen/go-trees v0.0.0-20190313150506-2af4e13f9062/go.mod h1:PcNJqIlcX/dj3DTG/+QQnRvSgTMG6CLpRMjWcv4+J6w= github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= github.com/jackc/pgx v3.3.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= -github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8= +github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= @@ -1291,10 +1435,8 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f/go.mod h1:KDSfL7qe5ZfQqvlDMkVjCztbmcpp/c8M77vhQP8ZPvk= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -1302,7 +1444,6 @@ github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= @@ -1315,13 +1456,13 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1331,20 +1472,18 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= -github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= -github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/linode/linodego v0.7.1/go.mod h1:ga11n3ivecUrPCHN0rANxKmfWBJVkOXfLMZinAbj2sY= github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= -github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= -github.com/lucas-clemente/quic-go v0.13.1/go.mod h1:Vn3/Fb0/77b02SGhQk36KzOUmXgVpFfizUfW5WMaqyU= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= @@ -1360,9 +1499,6 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= -github.com/marten-seemann/chacha20 v0.2.0/go.mod h1:HSdjFau7GzYRj+ahFNwsO3ouVJr1HFkWoEwNDb4TMtE= -github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= -github.com/marten-seemann/qtls v0.4.1/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -1371,41 +1507,43 @@ github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mholt/certmagic v0.8.3/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaRaOZi6aQ= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/cli v1.1.4/go.mod h1:vTLESy5mRhKOs9KDp0/RATawxP1UqBmdrpVRMnpcvKQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.0/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -1414,11 +1552,11 @@ github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -1426,12 +1564,11 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= -github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= -github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:ifHPsLndGGzvgzcaXUvzmt6LxKT4pJ+uzEhtnMt+f7A= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/jwt v1.1.0/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M= github.com/nats-io/nats-server/v2 v2.1.9/go.mod h1:9qVyoewoYXzG1ME9ox0HwkkzyYvnlBDugfR4Gg/8uHU= @@ -1441,50 +1578,56 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nats-io/stan.go v0.8.1/go.mod h1:Ci6mUIpGQTjl++MqK2XzkWI/0vF+Bl72uScx7ejSYmU= -github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw= -github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ= -github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= github.com/nsqio/go-nsq v1.0.8/go.mod h1:vKq36oyeVXgsS5Q8YEO7WghqidAVXQlcFxzQbQTuDEY= +github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/olekukonko/tablewriter v0.0.0-20180130162743-b8a9be070da4/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= +github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= +github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= +github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.3.5/go.mod h1:uVHyebswE1cCXr2A73cRM2frx5ld1RJUCJkFNZ90ZiI= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= -github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= +github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c/go.mod h1:otzZQXgoO96RTzDB/Hycg0qZcXZsWJGJRSXbmEIJ+4M= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.4.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1499,45 +1642,37 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -1545,12 +1680,12 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= -github.com/rboyer/safeio v0.2.1/go.mod h1:Cq/cEPK+YXFn622lsQ0K4KsPZSPtaptHHEldsy7Fmig= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rboyer/safeio v0.2.3/go.mod h1:d7RMmt7utQBJZ4B7f0H/cU/EdZibQAU1Y8NWepK2dS8= github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03/go.mod h1:gRAiPF5C5Nd0eyyRdqIu9qTiFSoZzpTq727b5B8fkkU= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1558,36 +1693,34 @@ github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/zerolog v1.4.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3LDoToVTxDoQ= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/conswriter v0.0.0-20180208195008-f5ae3917a627/go.mod h1:7zjs06qF79/FKAJpBvFx3P8Ww4UTIMAe+lpNXDHziac= github.com/sean-/pager v0.0.0-20180208200047-666be9bf53b5/go.mod h1:BeybITEsBEg6qbIiqJ6/Bqeq25bCLbL7YFmpaFfJDuM= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil/v3 v3.22.8/go.mod h1:s648gW4IywYzUfE/KjXxUsqrqx/T2xO5VqOXxONeRfI= +github.com/shirou/gopsutil/v3 v3.22.9/go.mod h1:bBYl1kjgEJpWpxeHmLI+dVHWtyAwfcmSBLDsp2TNT8A= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -1598,15 +1731,18 @@ github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY52 github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/streadway/amqp v0.0.0-20200108173154-1c71cc93ed71/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -1624,37 +1760,42 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tencentcloud/tencentcloud-sdk-go v1.0.162/go.mod h1:asUz5BPXxgoPGaRgZaVm1iGcUAuHyYUo1nXqKa83cvI= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= -github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tklauser/numcpus v0.5.0/go.mod h1:OGzpTxpcIMNGYQdit2BYL1pvk/dSOaJWjKoflh+RQjo= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= +github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= +github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= @@ -1666,13 +1807,17 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= +github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.11.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd v0.5.0-alpha.5.0.20190917205325-a14579fbfb1a/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= @@ -1680,12 +1825,11 @@ go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS go.mongodb.org/mongo-driver v1.4.3/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= go.mongodb.org/mongo-driver v1.4.4/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= -go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= -go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= -go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= +go.mongodb.org/mongo-driver v1.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= +go.mongodb.org/mongo-driver v1.12.0/go.mod h1:AZkxhPnFJUoH7kZlFkVKucV20K387miPfm7oimrSmK0= +go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1694,26 +1838,32 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= +go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= +go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= +go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= +go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= +go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ= +go.opentelemetry.io/otel/sdk/metric v0.39.0/go.mod h1:piDIRgjcK7u0HCL5pCA4e74qpK/jk3NiUoAHATVAmiI= +go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= +go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1721,25 +1871,37 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1756,6 +1918,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20220518171630-0b5c67f07fdf/go.mod h1:yh0Ynu2b5ZUe3MQfp2nM0ecK7wsgouWTDN0FNeJuIys= golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/exp v0.0.0-20221215174704-0915cd710c24/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1796,14 +1960,18 @@ golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1812,10 +1980,7 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1827,10 +1992,8 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1842,6 +2005,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -1856,12 +2020,13 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -1878,7 +2043,9 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= @@ -1886,11 +2053,17 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1914,10 +2087,15 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1935,8 +2113,9 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1944,7 +2123,6 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1956,6 +2134,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1964,19 +2143,17 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2004,6 +2181,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2014,7 +2192,7 @@ golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2038,18 +2216,23 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2057,11 +2240,18 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= @@ -2069,12 +2259,17 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -2088,21 +2283,22 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2113,7 +2309,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -2126,8 +2321,6 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624190245-7f2218787638/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2154,6 +2347,7 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -2166,6 +2360,7 @@ golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -2175,13 +2370,18 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2199,7 +2399,6 @@ gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6d gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -2257,6 +2456,11 @@ google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/ google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= +google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjYK+5E= +google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= +google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4= +google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= +google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2264,14 +2468,13 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190626174449-989357319d63/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -2288,6 +2491,7 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -2298,6 +2502,7 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2309,6 +2514,7 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= @@ -2399,27 +2605,38 @@ google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVix google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= +google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= +google.golang.org/genproto v0.0.0-20230629202037-9506855d4529/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= +google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y= +google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= +google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e h1:AZX1ra8YbFMSb7+1pI8S9v4rrgRR7jU1FmuFSSjTVcQ= google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e h1:NumxXLPfHSndr3wBBdeKiVHjGVFzi9RX2HwwQke94iY= google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -2459,8 +2676,10 @@ google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5v google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= -google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= +google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2478,9 +2697,11 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/DataDog/dd-trace-go.v1 v1.19.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2488,26 +2709,19 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= -gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= -gopkg.in/mcuadros/go-syslog.v2 v2.2.1/go.mod h1:l5LPIyOOyIdQquNg+oU6Z3524YwrcqEm0aKH+5zpt2U= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/ns1/ns1-go.v2 v2.0.0-20190730140822-b51389932cbc/go.mod h1:VV+3haRsgDiVLxyifmMBrBIuCWFBPYKbRssXB9z67Hw= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= @@ -2526,8 +2740,7 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2536,35 +2749,43 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -k8s.io/api v0.0.0-20190620084959-7cf5895f2711/go.mod h1:TBhBqb1AWbBQbW3XRusr7n7E4v2+5ZY8r8sAMnyFC5A= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= -k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= +k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= -k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k= +k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= +k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= -k8s.io/kube-openapi v0.0.0-20190306001800-15615b16d372/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= -k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= -k8s.io/utils v0.0.0-20190529001817-6999998975a7/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.37.0/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= +modernc.org/ccgo/v3 v3.0.0-20220904174949-82d86e1b6d56/go.mod h1:YSXjPL62P2AMSxBphRHPn7IkzhVHqkvOnRKAKh+W6ZI= modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= +modernc.org/ccgo/v3 v3.16.13-0.20221017192402-261537637ce8/go.mod h1:fUB3Vn0nVPReA+7IG7yZDfjv1TMWjhQP8gCxrFAtL5g= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= @@ -2574,25 +2795,41 @@ modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= +modernc.org/libc v1.17.4/go.mod h1:WNg2ZH56rDEwdropAJeZPQkXmDwh+JCA1s/htl6r2fA= +modernc.org/libc v1.18.0/go.mod h1:vj6zehR5bfc98ipowQOM2nIDUZnVew/wNC/2tOGS+q0= +modernc.org/libc v1.20.3/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0= +modernc.org/libc v1.21.4/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI= +modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/memory v1.3.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= +modernc.org/sqlite v1.18.2/go.mod h1:kvrTLEWgxUcHa2GfHBQtanR1H9ht3hTJNtKpzH9k1u0= modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= +modernc.org/tcl v1.13.2/go.mod h1:7CLiGIPo1M8Rv1Mitpv5akc2+8fxUd2y2UzC/MfMzy0= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/test/integration/consul-container/go.mod b/test/integration/consul-container/go.mod index 18af2c9954bd..ce7a61ef253f 100644 --- a/test/integration/consul-container/go.mod +++ b/test/integration/consul-container/go.mod @@ -1,6 +1,8 @@ module github.com/hashicorp/consul/test/integration/consul-container -go 1.20 +go 1.22 + +toolchain go1.22.5 require ( fortio.org/fortio v1.54.0 @@ -8,12 +10,11 @@ require ( github.com/docker/docker v24.0.5+incompatible github.com/docker/go-connections v0.4.0 github.com/evanphx/json-patch v4.12.0+incompatible - github.com/go-jose/go-jose/v3 v3.0.0 + github.com/go-jose/go-jose/v3 v3.0.3 github.com/hashicorp/consul v1.16.1 - github.com/hashicorp/consul/api v1.26.1 - github.com/hashicorp/consul/envoyextensions v0.5.1 - github.com/hashicorp/consul/proto-public v0.5.1 - github.com/hashicorp/consul/sdk v0.15.0 + github.com/hashicorp/consul/api v1.29.4 + github.com/hashicorp/consul/envoyextensions v0.7.3 + github.com/hashicorp/consul/sdk v0.16.1 github.com/hashicorp/consul/testing/deployer v0.0.0-20230811171106-4a0afb5d1373 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-multierror v1.1.1 @@ -30,7 +31,7 @@ require ( github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 github.com/testcontainers/testcontainers-go v0.22.0 golang.org/x/mod v0.12.0 - google.golang.org/grpc v1.57.2 + google.golang.org/grpc v1.58.3 ) require ( @@ -40,91 +41,68 @@ require ( fortio.org/sets v1.0.2 // indirect fortio.org/version v1.0.2 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/DataDog/datadog-go v4.8.2+incompatible // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect - github.com/armon/go-radix v1.0.0 // indirect - github.com/aws/aws-sdk-go v1.44.289 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible // indirect - github.com/circonus-labs/circonusllhist v0.1.3 // indirect github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect github.com/containerd/containerd v1.7.3 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/deckarep/golang-set/v2 v2.3.1 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/envoyproxy/go-control-plane v0.11.1 // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.1 // indirect - github.com/fatih/color v1.14.1 // indirect + github.com/envoyproxy/go-control-plane v0.12.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect + github.com/fatih/color v1.16.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.0.1 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/hashicorp/consul-server-connection-manager v0.1.4 // indirect + github.com/hashicorp/consul/proto-public v0.6.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-bexpr v0.1.2 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-msgpack v1.1.5 // indirect github.com/hashicorp/go-netaddrs v0.1.0 // indirect - github.com/hashicorp/go-retryablehttp v0.6.7 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/memberlist v0.5.0 // indirect - github.com/hashicorp/raft v1.5.0 // indirect - github.com/hashicorp/raft-autopilot v0.1.6 // indirect - github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect github.com/itchyny/timefmt-go v0.1.5 // indirect github.com/klauspost/compress v1.16.7 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/miekg/dns v1.1.50 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.0 // indirect - github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect - github.com/oklog/ulid/v2 v2.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc4 // indirect github.com/opencontainers/runc v1.1.8 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.14.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect - github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect - github.com/xeipuuv/gojsonschema v1.2.0 // indirect - go.opentelemetry.io/proto/otlp v0.19.0 // indirect - golang.org/x/crypto v0.14.0 // indirect + golang.org/x/crypto v0.22.0 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - golang.org/x/time v0.3.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/test/integration/consul-container/go.sum b/test/integration/consul-container/go.sum index be31c2f43ab2..5a94cc2a42d9 100644 --- a/test/integration/consul-container/go.sum +++ b/test/integration/consul-container/go.sum @@ -1,39 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= fortio.org/assert v1.1.4 h1:Za1RaG+OjsTMpQS3J3UCvTF6wc4+IOHCz+jAOU37Y4o= +fortio.org/assert v1.1.4/go.mod h1:039mG+/iYDPO8Ibx8TrNuJCm2T2SuhwRI3uL9nHTTls= fortio.org/dflag v1.5.2 h1:F9XVRj4Qr2IbJP7BMj7XZc9wB0Q/RZ61Ool+4YPVad8= fortio.org/dflag v1.5.2/go.mod h1:ppb/A8u+KKg+qUUYZNYuvRnXuVb8IsdHb/XGzsmjkN8= fortio.org/fortio v1.54.0 h1:2jn8yTd6hcIEoKY4CjI0lI6XxTWVxsMYF2bMiWOmv+Y= @@ -45,65 +14,41 @@ fortio.org/sets v1.0.2/go.mod h1:xVjulHr0FhlmReSymI+AhDtQ4FgjiazQ3JmuNpYFMs8= fortio.org/version v1.0.2 h1:8NwxdX58aoeKx7T5xAPO0xlUu1Hpk42nRz5s6e6eKZ0= fortio.org/version v1.0.2/go.mod h1:2JQp9Ax+tm6QKiGuzR5nJY63kFeANcgrZ0osoQFDVm0= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/datadog-go v4.8.2+incompatible h1:qbcKSx29aBLD+5QLvlQZlGmRMF/FfGqFLFev/1TDzRo= -github.com/DataDog/datadog-go v4.8.2+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= -github.com/aws/aws-sdk-go v1.44.289 h1:5CVEjiHFvdiVlKPBzv0rjG4zH/21W/onT18R5AH/qx0= -github.com/aws/aws-sdk-go v1.44.289/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/containerd/containerd v1.7.3 h1:cKwYKkP1eTj54bP3wCdXXBymmKRQMrWjkLSWZZJDa8o= @@ -111,13 +56,13 @@ github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+ github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.3.1 h1:vjmkvJt/IV27WXPyYQpAh4bRyWJc5Y435D17XQ9QU5A= -github.com/deckarep/golang-set/v2 v2.3.1/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= @@ -127,29 +72,20 @@ github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5Xh github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= -github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.1 h1:kt9FtLiooDc0vbwTLhdg3dyNX1K9Qwa1EK9LcD4jVUQ= -github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= -github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= +github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -159,94 +95,39 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69 h1:wzWurXrxfSyG1PHskIZlfuXlTSCj1Tsyatp9DtaasuY= -github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69/go.mod h1:svUZZDvotY8zTODknUePc6mZ9pX8nN0ViGwWcUSOBEA= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/consul-server-connection-manager v0.1.4 h1:wrcSRV6WGXFBNpNbN6XsdoGgBOyso7ZbN5VaWPEX1jY= github.com/hashicorp/consul-server-connection-manager v0.1.4/go.mod h1:LMqHkALoLP0HUQKOG21xXYr0YPUayIQIHNTlmxG100E= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-bexpr v0.1.2 h1:ijMXI4qERbzxbCnkxmfUtwMyjrrk3y+Vt0MxojNCbBs= -github.com/hashicorp/go-bexpr v0.1.2/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs= github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= @@ -256,14 +137,11 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9 github.com/hashicorp/go-netaddrs v0.1.0 h1:TnlYvODD4C/wO+j7cX1z69kV5gOzI87u3OcUinANaW8= github.com/hashicorp/go-netaddrs v0.1.0/go.mod h1:33+a/emi5R5dqRspOuZKO0E+Tuz5WV1F84eRWALkedA= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo= -github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -272,38 +150,22 @@ github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038 h1:n9J0rwVWXDpNd5iZnwY7w4WZyq53/rROeI7OVvLW8Ok= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= -github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= -github.com/hashicorp/raft v1.5.0 h1:uNs9EfJ4FwiArZRxxfd/dQ5d33nV31/CdCHArH89hT8= -github.com/hashicorp/raft v1.5.0/go.mod h1:pKHB2mf/Y25u3AHNSXVRv+yT+WAnmeTX0BwVppVQV+M= -github.com/hashicorp/raft-autopilot v0.1.6 h1:C1q3RNF2FfXNZfHWbvVAu0QixaQK8K5pX4O5lh+9z4I= -github.com/hashicorp/raft-autopilot v0.1.6/go.mod h1:Af4jZBwaNOI+tXfIqIdbcAnh/UyyqIMj/pOISIfhArw= -github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I= -github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/itchyny/gojq v0.12.12 h1:x+xGI9BXqKoJQZkr95ibpe3cdrTbY8D9lonrK433rcA= github.com/itchyny/gojq v0.12.12/go.mod h1:j+3sVkjxwd7A7Z5jrbKibgOLn0ZfLWkV+Awxr/pyzJE= github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE= github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -312,10 +174,12 @@ github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQs github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -327,13 +191,12 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -347,15 +210,10 @@ github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa1 github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.14.0 h1:/x0XQ6h+3U3nAyk1yx+bHPURrKa9sVVvYbuqZ7pIAtI= -github.com/mitchellh/go-testing-interface v1.14.0/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452 h1:hOY53G+kBFhbYFpRVxHl5eS7laP6B1+Cq+Z9Dry1iMU= -github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= @@ -371,8 +229,6 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= -github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= @@ -382,10 +238,10 @@ github.com/opencontainers/runc v1.1.8/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh github.com/otiai10/copy v1.10.0 h1:znyI7l134wNg/wDktoVQPxPkgvhDfGCYUasey+h0rDQ= github.com/otiai10/copy v1.10.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= +github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -396,7 +252,6 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= @@ -405,22 +260,19 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1: github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= @@ -429,157 +281,78 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 h1:xzABM9let0HLLqFypcxvLmlvEciCHL7+Lv+4vwZqecI= github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569/go.mod h1:2Ly+NIftZN4de9zRmENdYbvPQeaVIYKWpLFStLFEBgI= github.com/testcontainers/testcontainers-go v0.22.0 h1:hOK4NzNu82VZcKEB1aP9LO1xYssVFMvlfeuDW9JMmV0= github.com/testcontainers/testcontainers-go v0.22.0/go.mod h1:k0YiPa26xJCRUbUkYqy5rY6NGvSbVCeUBXCvucscBR4= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -588,36 +361,14 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -634,194 +385,75 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 h1:eSaPbMR4T7WfH9FvABk36NBMacoTUKdWCvV0dx+KfOg= google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.57.2 h1:uw37EN34aMFFXB2QPW7Tq6tdTbind1GpRxw5aOX3a5k= -google.golang.org/grpc v1.57.2/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= +gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/test/integration/consul-container/libs/assert/envoy.go b/test/integration/consul-container/libs/assert/envoy.go index 076f2e1af62b..95e129760285 100644 --- a/test/integration/consul-container/libs/assert/envoy.go +++ b/test/integration/consul-container/libs/assert/envoy.go @@ -14,11 +14,12 @@ import ( "testing" "time" - "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/go-cleanhttp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/sdk/testutil/retry" + libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" ) @@ -197,10 +198,9 @@ func AssertEnvoyMetricAtLeast(t *testing.T, adminPort int, prefix, metric string }) } -// GetEnvoyHTTPrbacFilters validates that proxy was configured with an http connection manager -// AssertEnvoyHTTPrbacFilters validates that proxy was configured with an http connection manager -// this assertion is currently unused current tests use http protocol -func AssertEnvoyHTTPrbacFilters(t *testing.T, port int) { +// AssertEnvoyPresentsCertURI makes GET request to /certs endpoint and validates that +// two certificates URI is available in the response +func AssertEnvoyPresentsCertURI(t *testing.T, port int, serviceName string) { var ( dump string err error @@ -210,31 +210,16 @@ func AssertEnvoyHTTPrbacFilters(t *testing.T, port int) { } retry.RunWith(failer(), t, func(r *retry.R) { - dump, _, err = GetEnvoyOutput(port, "config_dump", map[string]string{}) + dump, _, err = GetEnvoyOutput(port, "certs", nil) if err != nil { r.Fatal("could not fetch envoy configuration") } + require.NotNil(r, dump) }) - - // the steps below validate that the json result from envoy config dump configured active listeners with rbac and http filters - filter := `.configs[2].dynamic_listeners[].active_state.listener | "\(.name) \( .filter_chains[0].filters[] | select(.name == "envoy.filters.network.http_connection_manager") | .typed_config.http_filters | map(.name) | join(","))"` - results, err := utils.JQFilter(dump, filter) - require.NoError(t, err, "could not parse envoy configuration") - require.Len(t, results, 1, "static-server proxy should have been configured with two listener filters.") - - var filteredResult []string - for _, result := range results { - sanitizedResult := sanitizeResult(result) - filteredResult = append(filteredResult, sanitizedResult...) - } - require.Contains(t, filteredResult, "envoy.filters.http.rbac") - assert.Contains(t, filteredResult, "envoy.filters.http.header_to_metadata") - assert.Contains(t, filteredResult, "envoy.filters.http.router") + validateEnvoyCertificateURI(t, dump, serviceName) } -// AssertEnvoyPresentsCertURI makes GET request to /certs endpoint and validates that -// two certificates URI is available in the response -func AssertEnvoyPresentsCertURI(t *testing.T, port int, serviceName string) { +func AssertEnvoyPresentsCertURIWithClient(t *testing.T, client *http.Client, addr string, serviceName string) { var ( dump string err error @@ -244,13 +229,16 @@ func AssertEnvoyPresentsCertURI(t *testing.T, port int, serviceName string) { } retry.RunWith(failer(), t, func(r *retry.R) { - dump, _, err = GetEnvoyOutput(port, "certs", nil) + dump, _, err = GetEnvoyOutputWithClient(client, addr, "certs", nil) if err != nil { r.Fatal("could not fetch envoy configuration") } require.NotNil(r, dump) }) + validateEnvoyCertificateURI(t, dump, serviceName) +} +func validateEnvoyCertificateURI(t *testing.T, dump string, serviceName string) { // Validate certificate uri filter := `.certificates[] | .cert_chain[].subject_alt_names[].uri` results, err := utils.JQFilter(dump, filter) @@ -283,6 +271,22 @@ func AssertEnvoyRunning(t *testing.T, port int) { }) } +func AssertEnvoyRunningWithClient(t *testing.T, client *http.Client, addr string) { + var ( + err error + ) + failer := func() *retry.Timer { + return &retry.Timer{Timeout: 10 * time.Second, Wait: 500 * time.Millisecond} + } + + retry.RunWith(failer(), t, func(r *retry.R) { + _, _, err = GetEnvoyOutputWithClient(client, addr, "stats", nil) + if err != nil { + r.Fatal("could not fetch envoy stats") + } + }) +} + func GetEnvoyOutput(port int, path string, query map[string]string) (string, int, error) { client := cleanhttp.DefaultClient() return GetEnvoyOutputWithClient(client, fmt.Sprintf("localhost:%d", port), path, query) @@ -318,6 +322,15 @@ func GetEnvoyOutputWithClient(client *http.Client, addr string, path string, que return string(body), statusCode, nil } +func ResetEnvoyCounters(client *http.Client, addr string) (int, error) { + var u url.URL + u.Host = addr + u.Scheme = "http" + + res, err := client.Post(fmt.Sprintf("%s/reset_counters", u.String()), "application/json", nil) + return res.StatusCode, err +} + // sanitizeResult takes the value returned from config_dump json and cleans it up to remove special characters // e.g public_listener:0.0.0.0:21001 envoy.filters.network.rbac,envoy.filters.network.tcp_proxy // returns [envoy.filters.network.rbac envoy.filters.network.tcp_proxy] diff --git a/test/integration/consul-container/libs/assert/grpc.go b/test/integration/consul-container/libs/assert/grpc.go index a41ef65af620..101d1c14109e 100644 --- a/test/integration/consul-container/libs/assert/grpc.go +++ b/test/integration/consul-container/libs/assert/grpc.go @@ -26,7 +26,7 @@ func GRPCPing(t *testing.T, addr string) { var msg *fgrpc.PingMessage retries := 0 retry.RunWith(&retry.Timer{Timeout: time.Minute, Wait: 25 * time.Millisecond}, t, func(r *retry.R) { - t.Logf("making grpc call to %s", addr) + r.Logf("making grpc call to %s", addr) retries += 1 msg, err = pingCl.Ping(context.Background(), &fgrpc.PingMessage{ // use addr as payload so we have something variable to check against diff --git a/test/integration/consul-container/libs/assert/service.go b/test/integration/consul-container/libs/assert/service.go index 7434a1d5e36f..cdb6f8c28451 100644 --- a/test/integration/consul-container/libs/assert/service.go +++ b/test/integration/consul-container/libs/assert/service.go @@ -12,16 +12,13 @@ import ( "testing" "time" - "github.com/hashicorp/consul/api" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" - "github.com/hashicorp/consul/testing/deployer/util" - "github.com/hashicorp/go-cleanhttp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/hashicorp/go-cleanhttp" + + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil/retry" libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service" ) @@ -30,64 +27,6 @@ const ( defaultHTTPWait = defaultWait ) -// CatalogV2ServiceExists verifies the service name exists in the Consul catalog -func CatalogV2ServiceExists(t *testing.T, client pbresource.ResourceServiceClient, svc string, tenancy *pbresource.Tenancy) { - t.Helper() - CatalogV2ServiceHasEndpointCount(t, client, svc, tenancy, -1) -} - -// CatalogV2ServiceDoesNotExist verifies the service name does not exist in the Consul catalog -func CatalogV2ServiceDoesNotExist(t *testing.T, client pbresource.ResourceServiceClient, svc string, tenancy *pbresource.Tenancy) { - t.Helper() - ctx := testutil.TestContext(t) - retry.Run(t, func(r *retry.R) { - got, err := util.GetDecodedResource[*pbcatalog.Service](ctx, client, &pbresource.ID{ - Type: pbcatalog.ServiceType, - Name: svc, - Tenancy: tenancy, - }) - require.NoError(r, err, "error reading service data") - require.Nil(r, got, "unexpectedly found Service resource for %q", svc) - - got2, err := util.GetDecodedResource[*pbcatalog.ServiceEndpoints](ctx, client, &pbresource.ID{ - Type: pbcatalog.ServiceEndpointsType, - Name: svc, - Tenancy: tenancy, - }) - require.NotNil(r, err, "error reading service data") - require.Nil(r, got2, "unexpectedly found ServiceEndpoints resource for %q", svc) - }) -} - -// CatalogV2ServiceHasEndpointCount verifies the service name exists in the Consul catalog and has the specified -// number of workload endpoints. -func CatalogV2ServiceHasEndpointCount(t *testing.T, client pbresource.ResourceServiceClient, svc string, tenancy *pbresource.Tenancy, count int) { - t.Helper() - - ctx := testutil.TestContext(t) - retry.Run(t, func(r *retry.R) { - got, err := util.GetDecodedResource[*pbcatalog.Service](ctx, client, &pbresource.ID{ - Type: pbcatalog.ServiceType, - Name: svc, - Tenancy: tenancy, - }) - require.NoError(r, err, "error reading service data") - require.NotNil(r, got, "did not find Service resource for %q", svc) - - got2, err := util.GetDecodedResource[*pbcatalog.ServiceEndpoints](ctx, client, &pbresource.ID{ - Type: pbcatalog.ServiceEndpointsType, - Name: svc, - Tenancy: tenancy, - }) - require.NoError(r, err, "error reading service data") - require.NotNil(r, got2, "did not find ServiceEndpoints resource for %q", svc) - require.NotEmpty(r, got2.Data.Endpoints, "did not find any workload data in the ServiceEndpoints resource for %q", svc) - if count > 0 { - require.Len(r, got2.Data.Endpoints, count) - } - }) -} - // CatalogServiceExists verifies the service name exists in the Consul catalog func CatalogServiceExists(t *testing.T, c *api.Client, svc string, opts *api.QueryOptions) { retry.Run(t, func(r *retry.R) { @@ -221,7 +160,7 @@ func doHTTPServiceEchoesWithClient( } retry.RunWith(failer(), t, func(r *retry.R) { - t.Logf("making call to %s", url) + r.Logf("making call to %s", url) reader := strings.NewReader(phrase) req, err := http.NewRequest("POST", url, reader) @@ -242,7 +181,7 @@ func doHTTPServiceEchoesWithClient( defer res.Body.Close() statusCode := res.StatusCode - t.Logf("...got response code %d", statusCode) + r.Logf("...got response code %d", statusCode) require.Equal(r, 200, statusCode) body, err := io.ReadAll(res.Body) @@ -342,7 +281,7 @@ func WaitForFortioNameWithClient(t *testing.T, r retry.Retryer, urlbase string, // It retries with timeout defaultHTTPTimeout and wait defaultHTTPWait. // // client must be a custom http.Client -func FortioNameWithClient(t retry.Failer, urlbase string, name string, reqHost string, client *http.Client) (string, error) { +func FortioNameWithClient(t retry.TestingTB, urlbase string, name string, reqHost string, client *http.Client) (string, error) { t.Helper() var fortioNameRE = regexp.MustCompile("\nFORTIO_NAME=(.+)\n") var body []byte diff --git a/test/integration/consul-container/libs/cluster/agent.go b/test/integration/consul-container/libs/cluster/agent.go index a6dcb546749e..e44f588c464b 100644 --- a/test/integration/consul-container/libs/cluster/agent.go +++ b/test/integration/consul-container/libs/cluster/agent.go @@ -29,6 +29,7 @@ type Agent interface { GetAgentName() string GetPartition() string GetPod() testcontainers.Container + GetConsulContainer() testcontainers.Container Logs(context.Context) (io.ReadCloser, error) ClaimAdminPort() (int, error) GetConfig() Config diff --git a/test/integration/consul-container/libs/cluster/container.go b/test/integration/consul-container/libs/cluster/container.go index 0ff9038c0e5d..45295bd91d07 100644 --- a/test/integration/consul-container/libs/cluster/container.go +++ b/test/integration/consul-container/libs/cluster/container.go @@ -13,6 +13,7 @@ import ( "os/exec" "path/filepath" "strconv" + "sync" "time" goretry "github.com/avast/retry-go" @@ -40,6 +41,16 @@ const ServiceUpstreamLocalBindPort = 5000 // local bind Port of service's upstr const ServiceUpstreamLocalBindPort2 = 5001 // local bind Port of service's upstream, for services with 2 upstreams const debugPort = "4000/tcp" +// containerLock prevents starting multiple containers concurrently. This has not been confirmed as being necessary, but +// it seems to help make the CICD pipeline pass without failures. These failures seem to be due to some form of docker +// socket contention with errors of the form: +// +// #1: error starting pod with image "docker.mirror.hashicorp.services/hashiderek/pause": Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.43/containers/9b0e568744793e558d318af908c1052ab3d4d2f5a74c67b15d47a0570f141b1c/start": context deadline exceeded: failed to start container +// +// It may purely be due to the fact that starting containers takes longer than expected, and this lock avoids starting +// the context cancel timer until after we have ensured the docker socket is freed up. +var containerLock sync.Mutex + // consulContainerNode implements the Agent interface by running a Consul agent // in a container. type consulContainerNode struct { @@ -77,6 +88,10 @@ func (c *consulContainerNode) GetPod() testcontainers.Container { return c.pod } +func (c *consulContainerNode) GetConsulContainer() testcontainers.Container { + return c.container +} + func (c *consulContainerNode) Logs(context context.Context) (io.ReadCloser, error) { return c.container.Logs(context) } @@ -600,6 +615,8 @@ func (c *consulContainerNode) DataDir() string { } func startContainer(ctx context.Context, req testcontainers.ContainerRequest) (testcontainers.Container, error) { + containerLock.Lock() + defer containerLock.Unlock() ctx, cancel := context.WithTimeout(ctx, time.Second*40) defer cancel() return testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ @@ -608,7 +625,7 @@ func startContainer(ctx context.Context, req testcontainers.ContainerRequest) (t }) } -const pauseImage = "registry.k8s.io/pause:3.3" +const pauseImage = "docker.mirror.hashicorp.services/hashiderek/pause" type containerOpts struct { configFile string diff --git a/test/integration/consul-container/libs/utils/version.go b/test/integration/consul-container/libs/utils/version.go index 1f62306f4479..d1adcd192859 100644 --- a/test/integration/consul-container/libs/utils/version.go +++ b/test/integration/consul-container/libs/utils/version.go @@ -57,6 +57,25 @@ func GetLatestImageName() string { return LatestImageName } +func LatestImages() topology.Images { + img := DockerImage(LatestImageName, LatestVersion) + + var set topology.Images + if IsEnterprise() { + set.ConsulEnterprise = img + } else { + set.ConsulCE = img + } + + // TODO: have a "latest" dataplane image for testing a service mesh + // complete upgrade of data plane + if cdp := os.Getenv("DEPLOYER_CONSUL_DATAPLANE_IMAGE"); cdp != "" { + set.Dataplane = cdp + } + + return set +} + func TargetImages() topology.Images { img := DockerImage(targetImageName, TargetVersion) @@ -67,6 +86,8 @@ func TargetImages() topology.Images { set.ConsulCE = img } + // TODO: have a "target" dataplane image for testing a service mesh + // complete upgrade of data plane if cdp := os.Getenv("DEPLOYER_CONSUL_DATAPLANE_IMAGE"); cdp != "" { set.Dataplane = cdp } diff --git a/test/integration/consul-container/test/catalog/catalog_test.go b/test/integration/consul-container/test/catalog/catalog_test.go deleted file mode 100644 index 5be52792d821..000000000000 --- a/test/integration/consul-container/test/catalog/catalog_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package catalog - -import ( - "testing" - - "github.com/stretchr/testify/require" - - libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" - libtopology "github.com/hashicorp/consul/test/integration/consul-container/libs/topology" - - "github.com/hashicorp/consul/internal/catalog/catalogtest" - "github.com/hashicorp/consul/proto-public/pbresource" -) - -func TestCatalog(t *testing.T) { - t.Parallel() - - cluster, _, _ := libtopology.NewCluster(t, &libtopology.ClusterConfig{ - NumServers: 3, - BuildOpts: &libcluster.BuildOptions{Datacenter: "dc1"}, - Cmd: `-hcl=experiments=["resource-apis"]`, - }) - - followers, err := cluster.Followers() - require.NoError(t, err) - client := pbresource.NewResourceServiceClient(followers[0].GetGRPCConn()) - - t.Run("one-shot", func(t *testing.T) { - catalogtest.RunCatalogV2Beta1IntegrationTest(t, client) - }) - - t.Run("lifecycle", func(t *testing.T) { - catalogtest.RunCatalogV2Beta1LifecycleIntegrationTest(t, client) - }) -} diff --git a/test/integration/consul-container/test/envoy_extensions/ext_authz_test.go b/test/integration/consul-container/test/envoy_extensions/ext_authz_test.go index cf00105345fa..ea2e874162c4 100644 --- a/test/integration/consul-container/test/envoy_extensions/ext_authz_test.go +++ b/test/integration/consul-container/test/envoy_extensions/ext_authz_test.go @@ -15,6 +15,7 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" @@ -87,8 +88,8 @@ func TestExtAuthzLocal(t *testing.T) { // Make requests to the static-server. We expect that all requests are rejected with 403 Forbidden // unless they are to the /allow path. baseURL := fmt.Sprintf("http://localhost:%d", port) - doRequest(t, baseURL, http.StatusForbidden) - doRequest(t, baseURL+"/allow", http.StatusOK) + retryRequest(t, baseURL, http.StatusForbidden) + retryRequest(t, baseURL+"/allow", http.StatusOK) } func createServices(t *testing.T, cluster *libcluster.Cluster) libservice.Service { @@ -161,10 +162,16 @@ func createLocalAuthzService(t *testing.T, cluster *libcluster.Cluster) { } } -func doRequest(t *testing.T, url string, expStatus int) { +func retryRequest(t *testing.T, url string, expStatus int) { + t.Helper() retry.RunWith(&retry.Timer{Timeout: 5 * time.Second, Wait: time.Second}, t, func(r *retry.R) { - resp, err := cleanhttp.DefaultClient().Get(url) - require.NoError(r, err) - require.Equal(r, expStatus, resp.StatusCode) + doRequest(r, url, expStatus) }) } + +func doRequest(t testutil.TestingTB, url string, expStatus int) { + t.Helper() + resp, err := cleanhttp.DefaultClient().Get(url) + require.NoError(t, err) + require.Equal(t, expStatus, resp.StatusCode) +} diff --git a/test/integration/consul-container/test/envoy_extensions/otel_access_logging_test.go b/test/integration/consul-container/test/envoy_extensions/otel_access_logging_test.go index 87bb7b4d6165..e684bdbcc832 100644 --- a/test/integration/consul-container/test/envoy_extensions/otel_access_logging_test.go +++ b/test/integration/consul-container/test/envoy_extensions/otel_access_logging_test.go @@ -40,8 +40,6 @@ import ( // - Make sure a call to the client sidecar local bind port results in Envoy access logs being sent to the // otel-collector. func TestOTELAccessLogging(t *testing.T) { - t.Parallel() - cluster, _, _ := topology.NewCluster(t, &topology.ClusterConfig{ NumServers: 1, NumClients: 1, @@ -87,8 +85,9 @@ func TestOTELAccessLogging(t *testing.T) { // Make requests from the static-client to the static-server and look for the access logs // to show up in the `otel-collector` container logs. - retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Second}, t, func(r *retry.R) { - doRequest(t, fmt.Sprintf("http://localhost:%d", port), http.StatusOK) + retry.Run(t, func(r *retry.R) { + doRequest(r, fmt.Sprintf("http://localhost:%d", port), http.StatusOK) + reader, err := launchInfo.Container.Logs(context.Background()) require.NoError(r, err) log, err := io.ReadAll(reader) @@ -96,7 +95,10 @@ func TestOTELAccessLogging(t *testing.T) { require.Contains(r, string(log), `log_name: Str(otel-integration-test)`) require.Contains(r, string(log), `cluster_name: Str(static-server)`) require.Contains(r, string(log), `node_name: Str(static-server-sidecar-proxy)`) - }) + }, + retry.WithFullOutput(), + retry.WithRetryer(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Second}), + ) } func createLocalOTELService(t *testing.T, cluster *libcluster.Cluster) *libcluster.LaunchInfo { diff --git a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.mod b/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.mod index 703b71414fae..52bdfcb621cd 100644 --- a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.mod +++ b/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.mod @@ -3,3 +3,5 @@ module main go 1.20 require github.com/tetratelabs/proxy-wasm-go-sdk v0.21.0 + +require github.com/stretchr/testify v1.8.4 // indirect diff --git a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.sum b/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.sum index e09133fbccbf..4d92115d8d39 100644 --- a/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.sum +++ b/test/integration/consul-container/test/envoy_extensions/testdata/wasm_test_files/go.sum @@ -1,6 +1,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tetratelabs/proxy-wasm-go-sdk v0.21.0 h1:sxuh1wxy/zz4vXwMEC+ESVpwJmej1f22eYsrJlgVn7c= github.com/tetratelabs/proxy-wasm-go-sdk v0.21.0/go.mod h1:jqQTUvJBI6WJ+sVCZON3A4GwmUfBDuiNnZ4kuxsvLCo= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/test/integration/consul-container/test/gateways/terminating_gateway_test.go b/test/integration/consul-container/test/gateways/terminating_gateway_test.go index ef8f95ab8292..f8ea01345c9b 100644 --- a/test/integration/consul-container/test/gateways/terminating_gateway_test.go +++ b/test/integration/consul-container/test/gateways/terminating_gateway_test.go @@ -22,7 +22,9 @@ import ( const externalServerName = libservice.StaticServerServiceName -var requestRetryTimer = &retry.Timer{Timeout: 120 * time.Second, Wait: 500 * time.Millisecond} +func requestRetryTimer() *retry.Timer { + return &retry.Timer{Timeout: 120 * time.Second, Wait: 500 * time.Millisecond} +} // TestTerminatingGateway Summary // This test makes sure an external service can be reached via and terminating gateway. External server @@ -171,14 +173,14 @@ func createTerminatingGatewayConfigEntry(t *testing.T, consulClient *api.Client, // in the response. func assertHTTPRequestToServiceAddress(t *testing.T, client *libservice.ConnectContainer, serviceName string, port int, expSuccess bool) { upstreamURL := fmt.Sprintf("http://localhost:%d/debug?env=dump", port) - retry.RunWith(requestRetryTimer, t, func(r *retry.R) { + retry.RunWith(requestRetryTimer(), t, func(r *retry.R) { out, err := client.Exec(context.Background(), []string{"curl", "-s", upstreamURL}) - t.Logf("curl request to upstream service address: url=%s\nerr = %v\nout = %s", upstreamURL, err, out) + r.Logf("curl request to upstream service address: url=%s\nerr = %v\nout = %s", upstreamURL, err, out) if expSuccess { require.NoError(r, err) require.Contains(r, out, fmt.Sprintf("FORTIO_NAME=%s", serviceName)) - t.Logf("successfuly messaged %s", serviceName) + r.Logf("successfuly messaged %s", serviceName) } else { require.Error(r, err) require.Contains(r, err.Error(), "exit code 52") diff --git a/test/integration/consul-container/test/multiport/explicit_destination_test.go b/test/integration/consul-container/test/multiport/explicit_destination_test.go deleted file mode 100644 index a65ff2095dbc..000000000000 --- a/test/integration/consul-container/test/multiport/explicit_destination_test.go +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package multiport - -import ( - "context" - "fmt" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" - "github.com/stretchr/testify/require" - "testing" - - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - "github.com/hashicorp/consul/proto-public/pbresource" - libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" - libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service" - "github.com/hashicorp/consul/test/integration/consul-container/libs/topology" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" -) - -// TestMultiportService_Explicit makes sure two services in the same datacenter have connectivity -// with transparent proxy enabled. -// -// Steps: -// - Create a single server cluster. -// - Create the example static-server and sidecar containers, then register them both with Consul -// - Create an example static-client sidecar, then register both the service and sidecar with Consul -// - Make sure a request from static-client to the virtual address (.virtual.consul) returns a -// response from the upstream. -func TestMultiportService_Explicit(t *testing.T) { - t.Parallel() - - cluster := createCluster(t) - followers, err := cluster.Followers() - require.NoError(t, err) - client := pbresource.NewResourceServiceClient(followers[0].GetGRPCConn()) - resourceClient := rtest.NewClient(client) - - serverIP := cluster.Agents[1].GetIP() - clientIP := cluster.Agents[2].GetIP() - - serverService := createServerServicesAndWorkloads(t, resourceClient, serverIP) - createClientResources(t, resourceClient, serverService, clientIP) - - _, clientDataplane := createServices(t, cluster) - - _, port := clientDataplane.GetAddr() - - assertDataplaneContainerState(t, clientDataplane, "running") - libassert.HTTPServiceEchoes(t, "localhost", port, "") - libassert.AssertFortioName(t, fmt.Sprintf("http://localhost:%d", port), "static-server", "") -} - -// createServices creates the static-client and static-server services with -// transparent proxy enabled. It returns a Service for the static-client. -func createServices(t *testing.T, cluster *libcluster.Cluster) (*libcluster.ConsulDataplaneContainer, *libcluster.ConsulDataplaneContainer) { - n1 := cluster.Agents[1] - - // Create a service and dataplane - serverDataplane, err := createServiceAndDataplane(t, n1, "static-server-workload", "static-server", 8080, 8079, []int{}) - require.NoError(t, err) - - n2 := cluster.Agents[2] - // Create a service and dataplane - clientDataplane, err := createServiceAndDataplane(t, n2, "static-client-workload", "static-client", 8080, 8079, []int{libcluster.ServiceUpstreamLocalBindPort}) - require.NoError(t, err) - - return serverDataplane, clientDataplane -} - -func createServiceAndDataplane(t *testing.T, node libcluster.Agent, proxyID, serviceName string, httpPort, grpcPort int, serviceBindPorts []int) (*libcluster.ConsulDataplaneContainer, error) { - // Do some trickery to ensure that partial completion is correctly torn - // down, but successful execution is not. - var deferClean utils.ResettableDefer - defer deferClean.Execute() - - // Create a service and proxy instance - svc, err := libservice.NewExampleService(context.Background(), serviceName, httpPort, grpcPort, node) - if err != nil { - return nil, err - } - deferClean.Add(func() { - _ = svc.Terminate() - }) - - // Create Consul Dataplane - dp, err := libcluster.NewConsulDataplane(context.Background(), proxyID, "0.0.0.0", 8502, serviceBindPorts, node, false, "") - require.NoError(t, err) - deferClean.Add(func() { - _ = dp.Terminate() - }) - - // disable cleanup functions now that we have an object with a Terminate() function - deferClean.Reset() - - return dp, nil -} - -func createServerServicesAndWorkloads(t *testing.T, resourceClient *rtest.Client, ipAddress string) *pbresource.Resource { - serverService := rtest.ResourceID(&pbresource.ID{ - Name: "static-server-service", - Type: pbcatalog.ServiceType, - }).WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"static-server"}}, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }).Write(t, resourceClient) - - workloadPortMap := map[string]*pbcatalog.WorkloadPort{ - "tcp": { - Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - "mesh": { - Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - } - - rtest.ResourceID(&pbresource.ID{ - Name: "static-server-identity", - Type: pbauth.WorkloadIdentityType, - }).Write(t, resourceClient) - - rtest.ResourceID(&pbresource.ID{ - Name: "static-server-workload", - Type: pbcatalog.WorkloadType, - }). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: ipAddress}, - }, - Ports: workloadPortMap, - Identity: "static-server-identity", - }). - Write(t, resourceClient) - return serverService -} - -func createClientResources(t *testing.T, resourceClient *rtest.Client, staticServerResource *pbresource.Resource, ipAddress string) { - rtest.ResourceID(&pbresource.ID{ - Name: "static-client-service", - Type: pbcatalog.ServiceType, - }).WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"static-client"}}, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }).Write(t, resourceClient) - - workloadPortMap := map[string]*pbcatalog.WorkloadPort{ - "tcp": { - Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - "mesh": { - Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - } - - rtest.ResourceID(&pbresource.ID{ - Name: "static-client-workload", - Type: pbcatalog.WorkloadType, - }). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: ipAddress}, - }, - Ports: workloadPortMap, - Identity: "static-client-identity", - }). - Write(t, resourceClient) - - destId := staticServerResource.GetId() - destRef := &pbresource.Reference{ - Type: destId.Type, - Tenancy: destId.Tenancy, - Name: destId.Name, - Section: "", - } - rtest.ResourceID(&pbresource.ID{ - Name: "static-client-upstreams", - Type: pbmesh.DestinationsType, - }). - WithData(t, &pbmesh.Destinations{ - Destinations: []*pbmesh.Destination{ - { - DestinationRef: destRef, - DestinationPort: "tcp", - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: "0.0.0.0", - Port: libcluster.ServiceUpstreamLocalBindPort, - }, - }, - }, - }, - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"static-client"}, - }, - }). - Write(t, resourceClient) -} - -func createCluster(t *testing.T) *libcluster.Cluster { - cluster, _, _ := topology.NewCluster(t, &topology.ClusterConfig{ - NumServers: 3, - BuildOpts: &libcluster.BuildOptions{ - Datacenter: "dc1", - InjectAutoEncryption: true, - InjectGossipEncryption: true, - AllowHTTPAnyway: true, - }, - Cmd: `-hcl=experiments=["resource-apis"] log_level="TRACE"`, - }) - - return cluster -} - -// assertDataplaneContainerState validates service container status -func assertDataplaneContainerState(t *testing.T, dataplane *libcluster.ConsulDataplaneContainer, state string) { - containerStatus, err := dataplane.GetStatus() - require.NoError(t, err) - require.Equal(t, containerStatus, state, fmt.Sprintf("Expected: %s. Got %s", state, containerStatus)) -} diff --git a/test/integration/consul-container/test/ratelimit/ratelimit_test.go b/test/integration/consul-container/test/ratelimit/ratelimit_test.go index 89293da7f8ee..e0b85a17d186 100644 --- a/test/integration/consul-container/test/ratelimit/ratelimit_test.go +++ b/test/integration/consul-container/test/ratelimit/ratelimit_test.go @@ -11,6 +11,7 @@ import ( "time" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/stretchr/testify/require" @@ -282,7 +283,7 @@ func setupClusterAndClient(t *testing.T, config *libtopology.ClusterConfig, isSe return cluster, client } -func checkForMetric(t require.TestingT, cluster *libcluster.Cluster, operationName string, expectedLimitType string, expectedMode string, expectMetric bool) { +func checkForMetric(t testutil.TestingTB, cluster *libcluster.Cluster, operationName string, expectedLimitType string, expectedMode string, expectMetric bool) { // validate metrics server, err := cluster.GetClient(nil, true) require.NoError(t, err) @@ -320,7 +321,7 @@ func checkForMetric(t require.TestingT, cluster *libcluster.Cluster, operationNa } } -func checkLogsForMessage(t require.TestingT, logs []string, msg string, operationName string, logType string, logShouldExist bool) { +func checkLogsForMessage(t testutil.TestingTB, logs []string, msg string, operationName string, logType string, logShouldExist bool) { if logShouldExist { found := false for _, log := range logs { diff --git a/test/integration/consul-container/test/tproxy/tproxy_test.go b/test/integration/consul-container/test/tproxy/tproxy_test.go index 15eae0c21090..1f962aeba277 100644 --- a/test/integration/consul-container/test/tproxy/tproxy_test.go +++ b/test/integration/consul-container/test/tproxy/tproxy_test.go @@ -136,7 +136,7 @@ func assertHTTPRequestToVirtualAddress(t *testing.T, clientService libservice.Se `, virtualHostname), }, ) - t.Logf("curl request to upstream virtual address\nerr = %v\nout = %s", err, out) + r.Logf("curl request to upstream virtual address\nerr = %v\nout = %s", err, out) require.NoError(r, err) require.Regexp(r, `Virtual IP: 240.0.0.\d+`, out) require.Contains(r, out, fmt.Sprintf("FORTIO_NAME=%s", serverName)) @@ -155,7 +155,7 @@ func assertHTTPRequestToServiceAddress(t *testing.T, client, server libcluster.A upstreamURL := fmt.Sprintf("http://%s:8080/debug?env=dump", server.GetIP()) retry.RunWith(requestRetryTimer, t, func(r *retry.R) { out, err := client.Exec(context.Background(), []string{"curl", "-s", upstreamURL}) - t.Logf("curl request to upstream service address: url=%s\nerr = %v\nout = %s", upstreamURL, err, out) + r.Logf("curl request to upstream service address: url=%s\nerr = %v\nout = %s", upstreamURL, err, out) if expSuccess { require.NoError(r, err) diff --git a/test/integration/consul-container/test/trafficpermissions/tcp_test.go b/test/integration/consul-container/test/trafficpermissions/tcp_test.go deleted file mode 100644 index 6175acdd5ac9..000000000000 --- a/test/integration/consul-container/test/trafficpermissions/tcp_test.go +++ /dev/null @@ -1,657 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package trafficpermissions - -import ( - "context" - "fmt" - "strings" - "testing" - - "github.com/hashicorp/consul/sdk/testutil/retry" - - rtest "github.com/hashicorp/consul/internal/resource/resourcetest" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" - libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service" - "github.com/hashicorp/consul/test/integration/consul-container/libs/topology" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" - "github.com/stretchr/testify/require" -) - -const ( - echoPort = 9999 - tcpPort = 8888 - staticServerVIP = "240.0.0.1" - staticServerReturnValue = "static-server" - staticServerIdentity = "static-server-identity" -) - -type trafficPermissionsCase struct { - tp1 *pbauth.TrafficPermissions - tp2 *pbauth.TrafficPermissions - client1TCPSuccess bool - client1EchoSuccess bool - client2TCPSuccess bool - client2EchoSuccess bool -} - -// We are using tproxy to test traffic permissions now because explicitly specifying destinations -// doesn't work when multiple downstreams specify the same destination yet. In the future, we will need -// to update this to use explicit destinations once we infer tproxy destinations from traffic permissions. -// -// This also explicitly uses virtual IPs and virtual ports because Consul DNS doesn't support v2 resources yet. -// We should update this to use Consul DNS when it is working. -func runTrafficPermissionsTests(t *testing.T, aclsEnabled bool, cases map[string]trafficPermissionsCase) { - t.Parallel() - cluster, resourceClient := createCluster(t, aclsEnabled) - - serverDataplane := createServerResources(t, resourceClient, cluster, cluster.Agents[1]) - client1Dataplane := createClientResources(t, resourceClient, cluster, cluster.Agents[2], 1) - client2Dataplane := createClientResources(t, resourceClient, cluster, cluster.Agents[3], 2) - - assertDataplaneContainerState(t, client1Dataplane, "running") - assertDataplaneContainerState(t, client2Dataplane, "running") - assertDataplaneContainerState(t, serverDataplane, "running") - - for n, tc := range cases { - t.Run(n, func(t *testing.T) { - storeStaticServerTrafficPermissions(t, resourceClient, tc.tp1, 1) - storeStaticServerTrafficPermissions(t, resourceClient, tc.tp2, 2) - - // We must establish a new TCP connection each time because TCP traffic permissions are - // enforced at the connection level. - retry.Run(t, func(r *retry.R) { - assertPassing(r, httpRequestToVirtualAddress, client1Dataplane, tc.client1TCPSuccess) - assertPassing(r, echoToVirtualAddress, client1Dataplane, tc.client1EchoSuccess) - assertPassing(r, httpRequestToVirtualAddress, client2Dataplane, tc.client2TCPSuccess) - assertPassing(r, echoToVirtualAddress, client2Dataplane, tc.client2EchoSuccess) - }) - }) - } -} - -func TestTrafficPermission_TCP_DefaultDeny(t *testing.T) { - cases := map[string]trafficPermissionsCase{ - "default deny": { - tp1: nil, - client1TCPSuccess: false, - client1EchoSuccess: false, - client2TCPSuccess: false, - client2EchoSuccess: false, - }, - "allow everything": { - tp1: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - // IdentityName: "static-client-1-identity", - Namespace: "default", - Partition: "default", - Peer: "local", - }, - }, - }, - }, - }, - client1TCPSuccess: true, - client1EchoSuccess: true, - client2TCPSuccess: true, - client2EchoSuccess: true, - }, - "allow tcp": { - tp1: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - // IdentityName: "static-client-1-identity", - Namespace: "default", - Partition: "default", - Peer: "local", - }, - }, - DestinationRules: []*pbauth.DestinationRule{ - { - PortNames: []string{"tcp"}, - }, - }, - }, - }, - }, - client1TCPSuccess: true, - client1EchoSuccess: false, - client2TCPSuccess: true, - client2EchoSuccess: false, - }, - "client 1 only": { - tp1: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - IdentityName: "static-client-1-identity", - Namespace: "default", - Partition: "default", - Peer: "local", - }, - }, - }, - }, - }, - client1TCPSuccess: true, - client1EchoSuccess: true, - client2TCPSuccess: false, - client2EchoSuccess: false, - }, - "allow all exclude client 1": { - tp1: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Namespace: "default", - Partition: "default", - Peer: "local", - Exclude: []*pbauth.ExcludeSource{ - { - IdentityName: "static-client-1-identity", - Namespace: "default", - Partition: "default", - Peer: "local", - }, - }, - }, - }, - }, - }, - }, - client1TCPSuccess: false, - client1EchoSuccess: false, - client2TCPSuccess: true, - client2EchoSuccess: true, - }, - "deny takes precedence over allow": { - tp1: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_DENY, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - IdentityName: "static-client-1-identity", - Namespace: "default", - Partition: "default", - Peer: "local", - }, - }, - }, - }, - }, - tp2: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - IdentityName: "static-client-1-identity", - Namespace: "default", - Partition: "default", - Peer: "local", - }, - }, - }, - }, - }, - client1TCPSuccess: false, - client1EchoSuccess: false, - client2TCPSuccess: false, - client2EchoSuccess: false, - }, - "deny all exclude service + allow on that service": { - tp1: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_DENY, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Namespace: "default", - Partition: "default", - Peer: "local", - Exclude: []*pbauth.ExcludeSource{ - { - IdentityName: "static-client-1-identity", - Namespace: "default", - Partition: "default", - Peer: "local", - }, - }, - }, - }, - }, - }, - }, - tp2: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - IdentityName: "static-client-1-identity", - Namespace: "default", - Partition: "default", - Peer: "local", - }, - }, - }, - }, - }, - client1TCPSuccess: true, - client1EchoSuccess: true, - client2TCPSuccess: false, - client2EchoSuccess: false, - }, - } - - runTrafficPermissionsTests(t, true, cases) -} - -func TestTrafficPermission_TCP_DefaultAllow(t *testing.T) { - cases := map[string]trafficPermissionsCase{ - "default allow": { - tp1: nil, - client1TCPSuccess: true, - client1EchoSuccess: true, - client2TCPSuccess: true, - client2EchoSuccess: true, - }, - "empty allow denies everything": { - tp1: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_ALLOW, - }, - client1TCPSuccess: false, - client1EchoSuccess: false, - client2TCPSuccess: false, - client2EchoSuccess: false, - }, - "empty deny denies everything": { - tp1: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_DENY, - }, - client1TCPSuccess: false, - client1EchoSuccess: false, - client2TCPSuccess: false, - client2EchoSuccess: false, - }, - "allow everything": { - tp1: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Namespace: "default", - Partition: "default", - Peer: "local", - }, - }, - }, - }, - }, - client1TCPSuccess: true, - client1EchoSuccess: true, - client2TCPSuccess: true, - client2EchoSuccess: true, - }, - "allow one protocol denies the other protocol": { - tp1: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - Namespace: "default", - Partition: "default", - Peer: "local", - }, - }, - DestinationRules: []*pbauth.DestinationRule{ - { - PortNames: []string{"tcp"}, - }, - }, - }, - }, - }, - client1TCPSuccess: true, - client1EchoSuccess: false, - client2TCPSuccess: true, - client2EchoSuccess: false, - }, - "allow something unrelated": { - tp1: &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: staticServerIdentity, - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{ - { - Sources: []*pbauth.Source{ - { - IdentityName: "something-else", - Namespace: "default", - Partition: "default", - Peer: "local", - }, - }, - }, - }, - }, - client1TCPSuccess: false, - client1EchoSuccess: false, - client2TCPSuccess: false, - client2EchoSuccess: false, - }, - } - - runTrafficPermissionsTests(t, false, cases) -} - -func createServiceAndDataplane(t *testing.T, node libcluster.Agent, cluster *libcluster.Cluster, proxyID, serviceName string, httpPort, grpcPort int, serviceBindPorts []int) (*libcluster.ConsulDataplaneContainer, error) { - leader, err := cluster.Leader() - require.NoError(t, err) - leaderIP := leader.GetIP() - - token := cluster.TokenBootstrap - - // Do some trickery to ensure that partial completion is correctly torn - // down, but successful execution is not. - var deferClean utils.ResettableDefer - defer deferClean.Execute() - - // Create a service and proxy instance - svc, err := libservice.NewExampleService(context.Background(), serviceName, httpPort, grpcPort, node) - if err != nil { - return nil, err - } - deferClean.Add(func() { - _ = svc.Terminate() - }) - - // Create Consul Dataplane - dp, err := libcluster.NewConsulDataplane(context.Background(), proxyID, leaderIP, 8502, serviceBindPorts, node, true, token) - require.NoError(t, err) - deferClean.Add(func() { - _ = dp.Terminate() - }) - - // disable cleanup functions now that we have an object with a Terminate() function - deferClean.Reset() - - return dp, nil -} - -func storeStaticServerTrafficPermissions(t *testing.T, resourceClient *rtest.Client, tp *pbauth.TrafficPermissions, i int) { - id := &pbresource.ID{ - Name: fmt.Sprintf("static-server-tp-%d", i), - Type: pbauth.TrafficPermissionsType, - } - if tp == nil { - resourceClient.Delete(resourceClient.Context(t), &pbresource.DeleteRequest{ - Id: id, - }) - } else { - rtest.ResourceID(id). - WithData(t, tp). - Write(t, resourceClient) - } -} - -func createServerResources(t *testing.T, resourceClient *rtest.Client, cluster *libcluster.Cluster, node libcluster.Agent) *libcluster.ConsulDataplaneContainer { - rtest.ResourceID(&pbresource.ID{ - Name: "static-server-service", - Type: pbcatalog.ServiceType, - }). - WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{"static-server"}}, - Ports: []*pbcatalog.ServicePort{ - { - TargetPort: "tcp", - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - VirtualPort: 8888, - }, - { - TargetPort: "echo", - Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - VirtualPort: 9999, - }, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - VirtualIps: []string{"240.0.0.1"}, - }).Write(t, resourceClient) - - workloadPortMap := map[string]*pbcatalog.WorkloadPort{ - "tcp": { - Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - "echo": { - Port: 8078, Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - "mesh": { - Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - } - - rtest.ResourceID(&pbresource.ID{ - Name: "static-server-workload", - Type: pbcatalog.WorkloadType, - }). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: node.GetIP()}, - }, - Ports: workloadPortMap, - Identity: staticServerIdentity, - }). - Write(t, resourceClient) - - rtest.ResourceID(&pbresource.ID{ - Name: staticServerIdentity, - Type: pbauth.WorkloadIdentityType, - }). - Write(t, resourceClient) - - serverDataplane, err := createServiceAndDataplane(t, node, cluster, "static-server-workload", "static-server", 8080, 8079, []int{}) - require.NoError(t, err) - - return serverDataplane -} - -func createClientResources(t *testing.T, resourceClient *rtest.Client, cluster *libcluster.Cluster, node libcluster.Agent, idx int) *libcluster.ConsulDataplaneContainer { - prefix := fmt.Sprintf("static-client-%d", idx) - rtest.ResourceID(&pbresource.ID{ - Name: prefix + "-service", - Type: pbcatalog.ServiceType, - }). - WithData(t, &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{Prefixes: []string{prefix}}, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "tcp", Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }).Write(t, resourceClient) - - workloadPortMap := map[string]*pbcatalog.WorkloadPort{ - "tcp": { - Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP, - }, - "mesh": { - Port: 20000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH, - }, - } - - rtest.ResourceID(&pbresource.ID{ - Name: prefix + "-workload", - Type: pbcatalog.WorkloadType, - }). - WithData(t, &pbcatalog.Workload{ - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: node.GetIP()}, - }, - Ports: workloadPortMap, - Identity: prefix + "-identity", - }). - Write(t, resourceClient) - - rtest.ResourceID(&pbresource.ID{ - Name: prefix + "-identity", - Type: pbauth.WorkloadIdentityType, - }). - Write(t, resourceClient) - - rtest.ResourceID(&pbresource.ID{ - Name: prefix + "-proxy-configuration", - Type: pbmesh.ProxyConfigurationType, - }). - WithData(t, &pbmesh.ProxyConfiguration{ - Workloads: &pbcatalog.WorkloadSelector{ - Prefixes: []string{"static-client"}, - }, - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - }, - }). - Write(t, resourceClient) - - dp, err := createServiceAndDataplane(t, node, cluster, fmt.Sprintf("static-client-%d-workload", idx), "static-client", 8080, 8079, []int{}) - require.NoError(t, err) - - return dp -} - -func createCluster(t *testing.T, aclsEnabled bool) (*libcluster.Cluster, *rtest.Client) { - cluster, _, _ := topology.NewCluster(t, &topology.ClusterConfig{ - NumServers: 1, - NumClients: 3, - BuildOpts: &libcluster.BuildOptions{ - Datacenter: "dc1", - InjectAutoEncryption: true, - InjectGossipEncryption: true, - AllowHTTPAnyway: true, - ACLEnabled: aclsEnabled, - }, - Cmd: `-hcl=experiments=["resource-apis"] log_level="TRACE"`, - }) - - leader, err := cluster.Leader() - require.NoError(t, err) - client := pbresource.NewResourceServiceClient(leader.GetGRPCConn()) - resourceClient := rtest.NewClientWithACLToken(client, cluster.TokenBootstrap) - - return cluster, resourceClient -} - -// assertDataplaneContainerState validates service container status -func assertDataplaneContainerState(t *testing.T, dataplane *libcluster.ConsulDataplaneContainer, state string) { - containerStatus, err := dataplane.GetStatus() - require.NoError(t, err) - require.Equal(t, containerStatus, state, fmt.Sprintf("Expected: %s. Got %s", state, containerStatus)) -} - -func httpRequestToVirtualAddress(dp *libcluster.ConsulDataplaneContainer) (string, error) { - addr := fmt.Sprintf("%s:%d", staticServerVIP, tcpPort) - - out, err := dp.Exec( - context.Background(), - []string{"sudo", "sh", "-c", fmt.Sprintf(` - set -e - curl -s "%s/debug?env=dump" - `, addr), - }, - ) - - if err != nil { - return out, fmt.Errorf("curl request to upstream virtual address %q\nerr = %v\nout = %s\nservice=%s", addr, err, out, dp.GetServiceName()) - } - - expected := fmt.Sprintf("FORTIO_NAME=%s", staticServerReturnValue) - if !strings.Contains(out, expected) { - return out, fmt.Errorf("expected %q to contain %q", out, expected) - } - - return out, nil -} - -func echoToVirtualAddress(dp *libcluster.ConsulDataplaneContainer) (string, error) { - out, err := dp.Exec( - context.Background(), - []string{"sudo", "sh", "-c", fmt.Sprintf(` - set -e - echo foo | nc %s %d - `, staticServerVIP, echoPort), - }, - ) - - if err != nil { - return out, fmt.Errorf("nc request to upstream virtual address %s:%d\nerr = %v\nout = %s\nservice=%s", staticServerVIP, echoPort, err, out, dp.GetServiceName()) - } - - if !strings.Contains(out, "foo") { - return out, fmt.Errorf("expected %q to contain 'foo'", out) - } - - return out, err -} - -func assertPassing(t *retry.R, fn func(*libcluster.ConsulDataplaneContainer) (string, error), dp *libcluster.ConsulDataplaneContainer, success bool) { - _, err := fn(dp) - if success { - require.NoError(t, err) - } else { - require.Error(t, err) - } -} diff --git a/test/integration/consul-container/test/upgrade/README.md b/test/integration/consul-container/test/upgrade/README.md index 598bdfab3480..0577cf7ba59e 100644 --- a/test/integration/consul-container/test/upgrade/README.md +++ b/test/integration/consul-container/test/upgrade/README.md @@ -12,9 +12,11 @@ ## Introduction -The goal of upgrade tests is to ensure problem-free upgrades on supported upgrade paths. At any given time, Consul supports the latest minor release, and two older minor releases, e.g. 1.15, 1.14, and 1.13. Upgrades to any higher version are permitted, including skipping a minor version e.g. from 1.13 to 1.15. +The goal of upgrade tests is to ensure problem-free upgrades on supported upgrade paths. +At any given time, Consul supports the latest minor release, and two older minor releases, e.g. 1.15, 1.14, and 1.13. +Upgrades to any higher version are permitted, including skipping a minor version e.g. from 1.13 to 1.15. -The upgrade tests also aims to highlight errors that may occur as users attempt to upgrade their current version to a newer version. +The upgrade tests also aim to highlight errors that may occur as users attempt to upgrade their current version to a newer version. ### How it works @@ -49,7 +51,13 @@ To run the upgrade test, the following tools are required: ### Running Upgrade integration tests - run `make dev-docker` -- build a consul-envoy container image `cd test/integration/consul-container docker build -t consul-envoy:latest-version --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/consul:1.15 --build-arg ENVOY_VERSION=1.24.6 -f ./assets/Dockerfile-consul-envoy ./assets` +- build a consul-envoy container image + ```shell + cd test/integration/consul-container + docker build -t consul-envoy:latest-version \ + --build-arg CONSUL_IMAGE=docker.mirror.hashicorp.services/consul:1.20.0-rc1 \ + --build-arg ENVOY_VERSION=1.31.2 -f ./assets/Dockerfile-consul-envoy ./assets + ``` - run the single test `go test -v -timeout 30m -run ^TestACL_Upgrade_Node_Token$ ./.../upgrade/` - run all upgrade tests `go test -v -timeout 30m -run ./.../upgrade` @@ -66,13 +74,13 @@ this makes it hard to debug, when the test case creates many containers. To disable following container logs, run the test with `-follow-log false`. Below are the supported CLI options -| Flags | Default value | Description | +| Flags | Default value | Description | | ----------- | ----------- | ----------- | -| --latest-image | `consul` in CE, `hashicorp/consulenterprise` in ENT | Name of the Docker image to deploy initially. -| --latest-version | latest | Tag of the Docker image to deploy initially. -| --target-image | `consul` in Ce, `hashicorp/consulenterprise` in ENT | Name of the Docker image to upgrade to. -| --target-version | local | Tag of the Docker image to upgrade to. `local` is the tag built by `make dev-docker` above. -| -follow-log | true | Emit all container logs. These can be noisy, so we recommend `--follow-log=false` for local development. +| --latest-image | `consul` in CE, `hashicorp/consulenterprise` in ENT | Name of the Docker image to deploy initially. +| --latest-version | latest | Tag of the Docker image to deploy initially. +| --target-image | `consul` in Ce, `hashicorp/consulenterprise` in ENT | Name of the Docker image to upgrade to. +| --target-version | local | Tag of the Docker image to upgrade to. `local` is the tag built by `make dev-docker` above. +| -follow-log | true | Emit all container logs. These can be noisy, so we recommend `--follow-log=false` for local development. ## Adding a new upgrade integration test diff --git a/test/integration/consul-container/test/upgrade/basic/fullstopupgrade_test.go b/test/integration/consul-container/test/upgrade/basic/fullstopupgrade_test.go deleted file mode 100644 index 75ae754fd5b9..000000000000 --- a/test/integration/consul-container/test/upgrade/basic/fullstopupgrade_test.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package upgrade - -import ( - "context" - "fmt" - "testing" - "time" - - goretry "github.com/avast/retry-go" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/sdk/testutil/retry" - libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" - libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service" - "github.com/hashicorp/consul/test/integration/consul-container/libs/topology" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" -) - -type testcase struct { - oldVersion string - targetVersion string - expectErr bool -} - -var ( - tcs []testcase -) - -// Test upgrade a cluster of latest version to the target version -func TestStandardUpgradeToTarget_fromLatest(t *testing.T) { - const numServers = 1 - buildOpts := &libcluster.BuildOptions{ - ConsulImageName: utils.GetLatestImageName(), - ConsulVersion: utils.LatestVersion, - Datacenter: "dc1", - InjectAutoEncryption: true, - } - - cluster, _, _ := topology.NewCluster(t, &topology.ClusterConfig{ - NumServers: numServers, - BuildOpts: buildOpts, - ApplyDefaultProxySettings: true, - }) - client := cluster.APIClient(0) - - libcluster.WaitForLeader(t, cluster, client) - libcluster.WaitForMembers(t, client, numServers) - - // Create a service to be stored in the snapshot - const serviceName = "api" - index := libservice.ServiceCreate(t, client, serviceName) - - require.NoError(t, client.Agent().ServiceRegister( - &api.AgentServiceRegistration{Name: serviceName, Port: 9998}, - )) - err := goretry.Do( - func() error { - ch, errCh := libservice.ServiceHealthBlockingQuery(client, serviceName, index) - select { - case err := <-errCh: - require.NoError(t, err) - case service := <-ch: - index = service[0].Service.ModifyIndex - if len(service) != 1 { - return fmt.Errorf("service is %d, want 1", len(service)) - } - if serviceName != service[0].Service.Service { - return fmt.Errorf("service name is %s, want %s", service[0].Service.Service, serviceName) - } - if service[0].Service.Port != 9998 { - return fmt.Errorf("service is %d, want 9998", service[0].Service.Port) - } - } - return nil - }, - goretry.Attempts(5), - goretry.Delay(time.Second), - ) - require.NoError(t, err) - - // upgrade the cluster to the Target version - t.Logf("initiating standard upgrade to version=%q", utils.TargetVersion) - err = cluster.StandardUpgrade(t, context.Background(), utils.GetTargetImageName(), utils.TargetVersion) - - require.NoError(t, err) - libcluster.WaitForLeader(t, cluster, client) - libcluster.WaitForMembers(t, client, numServers) - - // Verify service is restored from the snapshot - retry.RunWith(&retry.Timer{Timeout: 5 * time.Second, Wait: 500 * time.Microsecond}, t, func(r *retry.R) { - service, _, err := client.Catalog().Service(serviceName, "", &api.QueryOptions{}) - require.NoError(r, err) - require.Len(r, service, 1) - require.Equal(r, serviceName, service[0].ServiceName) - }) -} diff --git a/test/integration/consul-container/test/upgrade/catalog/catalog_test.go b/test/integration/consul-container/test/upgrade/catalog/catalog_test.go deleted file mode 100644 index ae8ed0401a8f..000000000000 --- a/test/integration/consul-container/test/upgrade/catalog/catalog_test.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package catalog - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/hashicorp/go-version" - - "github.com/hashicorp/consul/internal/catalog/catalogtest" - "github.com/hashicorp/consul/proto-public/pbresource" - libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster" - "github.com/hashicorp/consul/test/integration/consul-container/libs/topology" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" -) - -var minCatalogResourceVersion = version.Must(version.NewVersion("v1.17.0")) - -const ( - versionUndetermined = ` -Cannot determine the actual version the starting image represents. -Scrutinze test failures to ensure that the starting version should -actually be able to be used for creating the initial data set. - ` -) - -func maybeSkipUpgradeTest(t *testing.T, minVersion *version.Version) { - t.Helper() - - image := utils.DockerImage(utils.GetLatestImageName(), utils.LatestVersion) - latestVersion, err := utils.DockerImageVersion(image) - - if latestVersion != nil && latestVersion.LessThan(minVersion) { - t.Skipf("Upgrade test isn't applicable with version %q as the starting version", latestVersion.String()) - } - - if err != nil || latestVersion == nil { - t.Log(versionUndetermined) - } -} - -// Test upgrade a cluster of latest version to the target version and ensure that the catalog still -// functions properly. Note -func TestCatalogUpgrade(t *testing.T) { - maybeSkipUpgradeTest(t, minCatalogResourceVersion) - t.Parallel() - - const numServers = 1 - buildOpts := &libcluster.BuildOptions{ - ConsulImageName: utils.GetLatestImageName(), - ConsulVersion: utils.LatestVersion, - Datacenter: "dc1", - InjectAutoEncryption: true, - } - - cluster, _, _ := topology.NewCluster(t, &topology.ClusterConfig{ - NumServers: 1, - BuildOpts: buildOpts, - ApplyDefaultProxySettings: false, - Cmd: `-hcl=experiments=["resource-apis"]`, - }) - - client := cluster.APIClient(0) - - libcluster.WaitForLeader(t, cluster, client) - libcluster.WaitForMembers(t, client, numServers) - - leader, err := cluster.Leader() - require.NoError(t, err) - rscClient := pbresource.NewResourceServiceClient(leader.GetGRPCConn()) - - // Initialize some data - catalogtest.PublishCatalogV2Beta1IntegrationTestData(t, rscClient) - - // upgrade the cluster to the Target version - t.Logf("initiating standard upgrade to version=%q", utils.TargetVersion) - err = cluster.StandardUpgrade(t, context.Background(), utils.GetTargetImageName(), utils.TargetVersion) - - require.NoError(t, err) - libcluster.WaitForLeader(t, cluster, client) - libcluster.WaitForMembers(t, client, numServers) - - catalogtest.VerifyCatalogV2Beta1IntegrationTestResults(t, rscClient) -} diff --git a/test/integration/consul-container/test/upgrade/ingress_gateway_sds_test.go b/test/integration/consul-container/test/upgrade/ingress_gateway_sds_test.go index a237bd98b230..bd810a9958f7 100644 --- a/test/integration/consul-container/test/upgrade/ingress_gateway_sds_test.go +++ b/test/integration/consul-container/test/upgrade/ingress_gateway_sds_test.go @@ -151,7 +151,14 @@ func TestIngressGateway_SDS_UpgradeToTarget_fromLatest(t *testing.T) { { "name": "%s", "connect_timeout": "5s", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "type": "LOGICAL_DNS", "load_assignment": { "cluster_name": "%s", diff --git a/test/integration/consul-container/test/upgrade/l7_traffic_management/resolver_default_subset_test.go b/test/integration/consul-container/test/upgrade/l7_traffic_management/resolver_default_subset_test.go index 9feb9d82092a..5c101bfa2a26 100644 --- a/test/integration/consul-container/test/upgrade/l7_traffic_management/resolver_default_subset_test.go +++ b/test/integration/consul-container/test/upgrade/l7_traffic_management/resolver_default_subset_test.go @@ -73,8 +73,8 @@ func TestTrafficManagement_ResolverDefaultSubset(t *testing.T) { assertionFn := func() { _, serverAdminPortV1 := serverConnectProxyV1.GetAdminAddr() _, serverAdminPortV2 := serverConnectProxyV2.GetAdminAddr() - _, adminPort := staticClientProxy.GetAdminAddr() // httpPort - _, port := staticClientProxy.GetAddr() // EnvoyAdminPort + _, adminPort := staticClientProxy.GetAdminAddr() // EnvoyAdminPort + _, port := staticClientProxy.GetAddr() // httpPort libassert.AssertEnvoyRunning(t, serverAdminPortV1) libassert.AssertEnvoyRunning(t, serverAdminPortV2) diff --git a/test/integration/consul-container/test/upgrade/peering/peering_http_test.go b/test/integration/consul-container/test/upgrade/peering/peering_http_test.go index 9c48727d83a6..a329fabfe324 100644 --- a/test/integration/consul-container/test/upgrade/peering/peering_http_test.go +++ b/test/integration/consul-container/test/upgrade/peering/peering_http_test.go @@ -95,7 +95,7 @@ func TestPeering_HTTPRouter(t *testing.T) { } // Verify resolver and failover can direct traffic to server in peered cluster -// In addtional to the basic topology, this case provisions the following +// In addition to the basic topology, this case provisions the following // services in the dialing cluster: // // - a new static-client at server_0 that has two upstreams: static-server (5000) @@ -313,6 +313,8 @@ func TestPeering_HTTPResolverAndSplitter(t *testing.T) { // TODO: restart static-server-2's sidecar } +// peeringUpgrade upgrades the accepting cluster, verifies that peering is still active, +// and then upgrades the dialing cluster and verifies that peering is still active. func peeringUpgrade(t *testing.T, accepting, dialing *libtopology.BuiltCluster, targetVersion string) { t.Helper() diff --git a/test/key/ourdomain.cer b/test/key/ourdomain.cer index 3d48f12e74f3..bc238b3cd145 100644 --- a/test/key/ourdomain.cer +++ b/test/key/ourdomain.cer @@ -1,26 +1,26 @@ -----BEGIN CERTIFICATE----- -MIIETTCCAzWgAwIBAgIBEjANBgkqhkiG9w0BAQ0FADCBmDELMAkGA1UEBhMCVVMx -CzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRwwGgYDVQQKExNI -YXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLEwNEZXYxFjAUBgNVBAMTDXRlc3Qu -aW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMCAXDTIy -MTEwMTE1MTMyOVoYDzIxMjIxMDA4MTUxMzI5WjCBjTEYMBYGA1UEAwwPdGVzdGNv +MIIETTCCAzWgAwIBAgIBKDANBgkqhkiG9w0BAQ0FADCBmDELMAkGA1UEBhMCVVMx +CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRwwGgYDVQQKDBNI +YXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLDANEZXYxFjAUBgNVBAMMDXRlc3Qu +aW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMCAXDTIz +MTEwMjE3MjAxNloYDzIxMjMxMDA5MTcyMDE2WjCBjTEYMBYGA1UEAwwPdGVzdGNv LmludGVybmFsMRMwEQYDVQQIDApDYWxpZm9ybmlhMQswCQYDVQQGEwJVUzEpMCcG CSqGSIb3DQEJARYaZG8tbm90LXJlcGx5QGhhc2hpY29ycC5jb20xEjAQBgNVBAoM CUVuZCBQb2ludDEQMA4GA1UECwwHVGVzdGluZzCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBANmKHQFznmOmtmvLSA2/f5xjUmJrscZkYa7ooy5bqkFxBKSa -cZn+rru0PjuUIElw2r6iOgVSTmWvBd78ej5qS9+xqfOpWUOBOnl2G6uit676Hlzb -/B/obEek8rmbTYHPT/Lz39oFbmJLc36Wdqp7hq/FMMJd7jEr3r5TIny1eHi1A8Iv -aTa/2vHpW79YMMkGifTO4NsdXgNXuomgnZgUWesDfDQ4zlQZeMrGT5JO6VcNICuR -MNCklBqWYONjdG62AePEu8hCePok3qec9ibhCWotqFpEPe+Myu0gCAxhKUVa6GNd -4iBle1eHbsOsYJcq7aLvujGyixd1EqigqizIvX8CAwEAAaOBqDCBpTAJBgNVHRME -AjAAMB0GA1UdDgQWBBRNjhD63/a2jm+hawLfWZXrJIBFTDAfBgNVHSMEGDAWgBSj -+es5+q9t57ZWSVUogWXJARu4lTALBgNVHQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYB +ggEPADCCAQoCggEBAOR5UJpDbgTsIgDNF6/fcafrPYTZlJnvMmYGxgPBH7lV2qqI +64yDE03++lLIOwPy8p0JHgCeoCsxRKhOXjaaBjOi3QGQFUU6rl/v8IZFsUo9NIyS +JJttiJaZCTjzgSZri3PdOHAClP5zF1/aAhTmNf326vAxqkn2MI8yglorOq+CSlOM +6p9nUGRAsoSvfjmz1vYDoyf4T0ZCUU+ieQ9KbcSVSrMip+r/CekfXglfIygfA+dx +dSK2Ivp0YjQbsnGEueDOaXMd2HX6Fh93K7IuvGKF2fAHHNl92uhnkbe63aJ7ZYgO +ftHKvVZFgq6cFFccAuI9qJlk6mo8P+m1ZNfv3dsCAwEAAaOBqDCBpTAJBgNVHRME +AjAAMB0GA1UdDgQWBBTxigs6/Ob0ULZZeeWqgTrxhfwQRDAfBgNVHSMEGDAWgBTm +rmqnZIdFOj6vhCUAJKLZNUDwFDALBgNVHQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYB BQUHAwEGCCsGAQUFBwMCMCwGA1UdHwQlMCMwIaAfoB2GG2h0dHA6Ly9wYXRoLnRv -LmNybC9teWNhLmNybDANBgkqhkiG9w0BAQ0FAAOCAQEAHQ5n79cM6G789AGKKjB9 -cbOld9SwzRUzb1MFrG3rs48ZaOp65mdm9zdI2Cmh9SkoT+lOK6+g1wAQ3p22p+2X -xY3BEFE9gpjdryvR0KFeGkS1fpvIrFAp/cDa67elQR1fX/ADvxSj8GA7gibpS3Ov -DfuUek8GP7HJEdwM+/0Q6g5qKZcZVb6UU/4WySGkuScukmIxbJTrdtctusthHBp9 -+WJtCHKGnziA0VlWTDCkfX04Mpyixzno4jk1QPdEiOB8PHonvJF7RUsLbuDVv5p2 -SXw4zUgFoTPQ5FuUVN0GInObUJ1IKZ3V4VuAIoTw5kZ165PjLiRRwQuFjLrCmVQR -AQ== +LmNybC9teWNhLmNybDANBgkqhkiG9w0BAQ0FAAOCAQEAXS69n70i8mdd2KpUtuVQ +TqCZPggLJ0ctSzSOVFz3ZFMTg50g3bvMZaK3jdwpL8GH7tMjEZANFaM/QNAJWMVb +pc0UD1UxdqahNj40I5V5RL/ocYZbzCVcNi6Y5Z9skROHS6/j4OsvCseYRkpVGMkE +x9bcWJ/cRfLmK9CO8MUrq8gCPYBA1av/uMAot7aT+2rLLcduF5bKuBGGTccVQ01x +5h+2bmFj8jxpju39HPGvZ7mnOqseVKhbKwE87vxirccM4UkwJDmWNuL7pX4CvwHi +aDtzDHJws/WPduT/r4eaXjMat7CF42tLP+w4FWNJH/P3UAzHPaPq2i2eHmCcuw4A +eA== -----END CERTIFICATE----- diff --git a/test/key/ourdomain.key b/test/key/ourdomain.key index 0550aac70d80..eeda2c3328f4 100644 --- a/test/key/ourdomain.key +++ b/test/key/ourdomain.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDZih0Bc55jprZr -y0gNv3+cY1Jia7HGZGGu6KMuW6pBcQSkmnGZ/q67tD47lCBJcNq+ojoFUk5lrwXe -/Ho+akvfsanzqVlDgTp5dhuroreu+h5c2/wf6GxHpPK5m02Bz0/y89/aBW5iS3N+ -lnaqe4avxTDCXe4xK96+UyJ8tXh4tQPCL2k2v9rx6Vu/WDDJBon0zuDbHV4DV7qJ -oJ2YFFnrA3w0OM5UGXjKxk+STulXDSArkTDQpJQalmDjY3RutgHjxLvIQnj6JN6n -nPYm4QlqLahaRD3vjMrtIAgMYSlFWuhjXeIgZXtXh27DrGCXKu2i77oxsosXdRKo -oKosyL1/AgMBAAECggEAI6qSUN+c82es9wVwPdjM2l4qbrqLfiSNI3k+7+XVhz85 -bKdpwr7P9TR7E5eYp5HaO3ErpB23ftJwWvv4Ku2QnQ9q9ukoGnpAlRN5O+3Ewep+ -OelTcAPSZPi1VxsQXR0ZVZMIe51yWKlYOUQAFrmD/qOM+AEggW1Y6smEmP/Dzb5K -cILo3+lEMXxc5ffZ8foS4l5ub3mdYvpjW30s+jzAzfPo2gj0CeMAYKQo+ndTlp6C -3sXPvpgjomq29EBijHCIehiYVj2D1sk0tkfqSzaFcypWfGC8oKTGpUb20aOrcMY2 -hBFGlU0yLntIerja9LhYlFrysa8NPByY1kPLtk6gGQKBgQD4Xnc7FINyn5xR6gN8 -2YjZXlCi4F2oBBsuH0Tkm5GYD6rqLiaEnk5KTEZVHqOgAKQVnGBeEzbx43z/+/EI -rEXEImjc8nGS/KiBkDiUBPA4QeEIFuUrKmz1cC1ryaTRLn3DQJL0uMuXuwn8Ufn8 -CvU1bVkqbkp6IxbGS/SBrNLxawKBgQDgOSjdCZ8QgiDbjqXgd/XXvuSTRnzKKaaD -pple5OH8I84CN5WiMztFqRwvL3+XDlxtF8mHg8AoetlmQ/muMBpm0I66AXF0E1UQ -dV3v10DswRgl1UVFSznR9fDGCRFHSDa4ZErsfE9yvGeNgl3MOHUok0eIYuW4rc13 -lXrpk1JlPQKBgQDAPDWit8Tp4hoW2L6sUp72R2a4OlqjIdJ7x14GZ1awUGgka2YK -vZCxNwo09csFm5lk1K1OAydC36WvaCxuXxB8t3lckhZQA1jVN3BjONNJZ8wp+7aS -y3qcGaA+TktQUOCsUH2uBp4mKXGYJ0cKytxx5tnd2pGwqRoGj2GHQOHgUwKBgQCP -X71jaW2Orsa33cTvfYVzyRp7mczdsDhLYlIbvZtLENH/1O8XYk76QiJFgcfCHWq4 -T0eMIZDT0YoFvF2BJj0blSxOf/G92UbBWWsRm8BmIyp/tpmur2VvfiXRW6byv5hN -28OU6AAdS5+jesLjfQ5dPZ+19BcUOf5yAuEvTgaXuQKBgQDM47vsNeStbvNvuW2w -LYCavmz1ci/H1LDStRwMn3kFVT6S30BQZW5WCa9JH1VJPLCZyAsXqMiMqVwbRkrP -ThY6k+OynaDaEKFURHFZ9TH7QnvAwq0fHRy7nVVUoh5A3I8hqx/lPTyBzJdfEZ/2 -yqxT1bclUFf59IlXukMf/pXxCw== +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDkeVCaQ24E7CIA +zRev33Gn6z2E2ZSZ7zJmBsYDwR+5VdqqiOuMgxNN/vpSyDsD8vKdCR4AnqArMUSo +Tl42mgYzot0BkBVFOq5f7/CGRbFKPTSMkiSbbYiWmQk484Ema4tz3ThwApT+cxdf +2gIU5jX99urwMapJ9jCPMoJaKzqvgkpTjOqfZ1BkQLKEr345s9b2A6Mn+E9GQlFP +onkPSm3ElUqzIqfq/wnpH14JXyMoHwPncXUitiL6dGI0G7JxhLngzmlzHdh1+hYf +dyuyLrxihdnwBxzZfdroZ5G3ut2ie2WIDn7Ryr1WRYKunBRXHALiPaiZZOpqPD/p +tWTX793bAgMBAAECggEAT6obWEbFwHKjoprgtQLY6v+j6kRBw/D7JkcbWWjICoQs +pETsuQhlPU94ck/9//EA9o+cxgOJfrYFphf5Utme6vdRT3+xYvvEnJAZ0n/Pgz7X +KWK13/ov468F37VMZZyfOe27hZbo49Y2osXt7uKcleq4Xbs7kOGGag/nEtC6/EHt +iFdHkRTJVehdYlkAY4XWaO4JFyksrnA9JW5wtYSlBPzwuW6IOUaDbz2+mYQzoUCu +c7KyAiO8TWBnxkikc83x0Op8yHTIJrLHoj6EM5X0HNwvuxonlhx1uLrtYbrLLK6z +M5wMiNYxu73AvRNpWtf3OpMHGhyv6UnYM1uaPVS75QKBgQD/TXTUEgnTefNwIP+/ +liUCbkvUiNYqthcV4ZAbF4lzm8UCHUPErfuogxApTS2m6uD7L1SPCps5Nk5fEFIv +QzI12avRmPmBdgG4Eo8po/QmP7+DfztGb/2uSmc59Oga2Cu3KzO90V/x4AWCW6LC +nUNRzMjC3p01VzjtCrA14cFanwKBgQDlGRiZTo2MerQE32TyX3zFp82m++lloKeW +Zm40rMOe4Lf6DMSxn5m5jlTSXzZrIhPl7iuRBx53D1EUYPSHRULaWMQrHmNzDUTF +qh5dTQvvmP0UNlSN0iDeXo2E0RloF8vtOqqdMAsMr2U9Tuwj1LrAZFaJMXV+3Uar +VOAj8cjvRQKBgQCNinXQ9Uc5VY0fh0wC/cz68gdch5ilCVr3KJzqSDxOOfgZWfwu +WH8DR9Z372/18JZW7ECnJSw1peQBVF0cEtcNf+aAR51cpv4A/VkdruY3JnSZBLrq +LECqlllwilT8PQjPfkYrYJ8ezCKBySgNWX7vJOfREfZ6kibfVGOpG8ZE5QKBgFv9 +TrZIJ2gP4PbP6I21r7kB3v68ygPHlWM7r+awtD+4Rcc+l0AnMKekMgTivEwaO9ko +YA/0xtPRr6G6KJWkRuq7l9Eke5Q38LRZ0aVvCWrkiEI0apEjnZUMbFC3UTdNztFr +rBQ/tUAbsVADv6fHhFE6ONEPrfkJypWDGBj2vdLtAoGBAKqnpHH8rp5GjIk/Kzcl +mesVx32MCYu8SIYRzgvnkpmrqlntNHE89c/oXIYZI/uDC/KsnZvcaTatlI2uc61K +WRkwTr7NELU8ZitFqUgfutJjmi2LuIVplYpILA+krQ73z089zDRXM1/QfyOUDPAF +Xh52im1jJlE68mHaq6bnrVaT -----END PRIVATE KEY----- diff --git a/test/key/ourdomain_server.cer b/test/key/ourdomain_server.cer index 728aefc77a23..2e0a073e019c 100644 --- a/test/key/ourdomain_server.cer +++ b/test/key/ourdomain_server.cer @@ -1,23 +1,24 @@ -----BEGIN CERTIFICATE----- -MIIDyTCCArGgAwIBAgIURPvvB7dOIjTd54ojjHIw2imSpEgwDQYJKoZIhvcNAQEL -BQAwgZgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZy -YW5jaXNjbzEcMBoGA1UEChMTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECxMD -RGV2MRYwFAYDVQQDEw10ZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0 -QGludGVybmFsLmNvbTAeFw0xOTA1MjAxMjE5MDBaFw0yOTA1MTcxMjE5MDBaMAAw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9G2dzg4w9ZqgiINgZJXDV -7ueWUE42wf6qS8WjdPZVci+ondLI4QTvbGE5wwy5EF/GTRTnVQup3VK8axaNqDqB -ThBrh7MUMeUgqhnElKxC7tgJOxvKE6JpyAz+e2jXwYMx8wFxDNd9Ve36yA1R6cc1 -T/lupisRl6ARgNOXb/l89fkpM8aHKpwWFFaoXxabsH2Jgnfai2wXLmf7vRnvAM7m -GwtioWRjt2UCOltZbh/AYL/HVpNeD/IVRaOUHdw72lpAwPHMhvEbqQQkklj4Aldz -/xs8U82XjyeDhAbeNqAWps2EjFwkmHy+dVSXK9a2hW+Qgw2CQq+By10DmR7rPZWl -AgMBAAGjgaEwgZ4wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMB -BggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTXwQO3LMRTMtINOYgD -sMREIqezCTAfBgNVHSMEGDAWgBSj+es5+q9t57ZWSVUogWXJARu4lTAfBgNVHREB -Af8EFTATghFzZXJ2ZXIuZGMxLmNvbnN1bDANBgkqhkiG9w0BAQsFAAOCAQEAHrvb -XYi87gpvyrXUCwihHCFDjKdvo+3b9a3MoFzn+/e3gcUwz9fLnup4kGq+Fh+iyitn -YtraUvFLb0QSZmROTRYRzGwmLLYYOguIcbadRKJkd3NkiJ5QDw4+S8OXE+1/hZpm -sjM3fnzQPhspxweSZZPtDvgI6JFA8IKCvh2jUfdKdWVfhBonEb/le2ox/7RfqQ+M -JZ7rorpvSCat+NOQKKIbIAlNcntflXGBE2ken/IHihtUREk5pYKpplMf4PqkyFkB -MuATqNoXuARYcN3u8HYWv6ewwHqBuUB86NurYArCw3Antl0hJBLDPQ7X8ukJZDoB -lhe56raXzfZxn9BIrw== +MIIEBDCCAuygAwIBAgIBJzANBgkqhkiG9w0BAQ0FADCBmDELMAkGA1UEBhMCVVMx +CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRwwGgYDVQQKDBNI +YXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLDANEZXYxFjAUBgNVBAMMDXRlc3Qu +aW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMCAXDTIz +MTEwMjE3MTkwOFoYDzIxMjMxMDA5MTcxOTA4WjCBjTEYMBYGA1UEAwwPdGVzdGNv +LmludGVybmFsMRMwEQYDVQQIDApDYWxpZm9ybmlhMQswCQYDVQQGEwJVUzEpMCcG +CSqGSIb3DQEJARYaZG8tbm90LXJlcGx5QGhhc2hpY29ycC5jb20xEjAQBgNVBAoM +CUVuZCBQb2ludDEQMA4GA1UECwwHVGVzdGluZzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKBYr0oa+qozTXeMoQOIWYxhPRfoLJk0YZbMTVoXzIpr0/Vu +CmMjVxPAzw1bz0mrQCgA66ftkEnn+ieIfrkhtKXeXtWNpvYwpDXlm1dXavAeccDm +Ik6BWM49WDuZYo7OWsrgh3ia4xRLzhlCyBhK8ckiEeym58nXKNK21KXQD/DKvxlA +I41WNHJ3hpIIYzxtTLvmv6tEZnmqocfDlbvT/wNVbsuXMVb+tzbwKS9iI7DdWMqe +IFv9G6h26WijVYcH4pTSAO54933oghguE+WZ8i9FPksCZvYjVKFosr0fALfAGScn +9kkbbpNM2VJ8s9qfsA1xoPn6Vpm058mc4WQ/rmkCAwEAAaNgMF4wHAYDVR0RBBUw +E4IRc2VydmVyLmRjMS5jb25zdWwwHQYDVR0OBBYEFNy73y5a0ZSJ8y1G5ujW6KGI +sEItMB8GA1UdIwQYMBaAFOauaqdkh0U6Pq+EJQAkotk1QPAUMA0GCSqGSIb3DQEB +DQUAA4IBAQAWc1KXB4fENj5oFgVV3B6U/F9nrxriMqJnYO7SXBlh8gBLIxqK7cBv +FBye4P35HBceOLUKCOqcIU/rtNzOvDBJkYmolCQ40OAP4QHolzl+dNrGC9ew5VdM +nACkcWLfYVAIPcaxtagVoR1+zuHq3r08Vf9opGXfUlhnKboHUVmCK8dIvujRzJcE +4mmgADRB+lDgC4dIX0E/JtY4RrDrd/DUiJ0WDrKKQEpOF3HRkbU9z17SsuniD6K9 +8Y84GchDBKFaCA0jydXF6uyIqfxqkv5DQgfi8CooPY6kEpM3m0DZCca4AwaLNlyt +rjfbJq847rcN0mvw7GYc8byw5uzoaKlK -----END CERTIFICATE----- diff --git a/test/key/ourdomain_server.cfg b/test/key/ourdomain_server.cfg new file mode 100644 index 000000000000..2f2d3c3214ae --- /dev/null +++ b/test/key/ourdomain_server.cfg @@ -0,0 +1,22 @@ +[ req ] +prompt = no +distinguished_name = dn +req_extensions = req_ext + + +[dn] +C = US +ST = California +L = Los Angeles +O = End Point +OU = Testing +emailAddress = do-not-reply@hashicorp.com +CN = testco.internal + +[ v3_req ] +basicConstraints = CA:false +extendedKeyUsage = serverAuth +subjectAltName = @alt_names + +[alt_names] +DNS.1 = server.dc1.consul \ No newline at end of file diff --git a/test/key/ourdomain_server.key b/test/key/ourdomain_server.key index 4278f1d01597..b9439ada88d0 100644 --- a/test/key/ourdomain_server.key +++ b/test/key/ourdomain_server.key @@ -1,27 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAvRtnc4OMPWaoIiDYGSVw1e7nllBONsH+qkvFo3T2VXIvqJ3S -yOEE72xhOcMMuRBfxk0U51ULqd1SvGsWjag6gU4Qa4ezFDHlIKoZxJSsQu7YCTsb -yhOiacgM/nto18GDMfMBcQzXfVXt+sgNUenHNU/5bqYrEZegEYDTl2/5fPX5KTPG -hyqcFhRWqF8Wm7B9iYJ32otsFy5n+70Z7wDO5hsLYqFkY7dlAjpbWW4fwGC/x1aT -Xg/yFUWjlB3cO9paQMDxzIbxG6kEJJJY+AJXc/8bPFPNl48ng4QG3jagFqbNhIxc -JJh8vnVUlyvWtoVvkIMNgkKvgctdA5ke6z2VpQIDAQABAoIBAEhSerYK0U+KOzMS -LJMxZn3q6FbsT31Ro/utDuD8klkLWn66HSsGI8UNRgG5PtxoDrjgMeZm+Bb2tfWp -Xu6+L+HT4SO+uhY3HtHnPAOaeGcAwU6GdJJMAAlEoPOSbv5U27/2l86Mgr1EZ8dJ -Sw7QwYb6FwLiOgZ4XpdTFZkNEfVf1CeZSlxTIpvlJMJJvVg7crhVnS4boI6d8z24 -b0LerEbvVC97N++sKhSGtSF/QX0wW7BkbTquruaRbWsL/e0o8Bydy1jRVFLTet4l -GO9MNcN8Cdt7eOptsK00Ma9S9AZfTvaXdrPERimJ0JDtqjMSyfly6M7fK7Yx2gUn -HcPSOAECgYEAy8IQ5+jw16qJDfAhc9jer5i0E/fj2xohYfUF6IniGFYT9Ih6D/2T -D55W1m8PSoNM5gfYkLZ6dvjzcF6kDCD5vppVr07B3RlS7caMkM1GGmLxOgX/YIa7 -OpEzaTr1kIefvsrR4c4b2wBzZm1XuGDE/lw5yCQmoBAbzyq4X2Mlr+UCgYEA7Zey -0vUxCPxBp+spdPuZuH5oW9b2L5D2c87em7+tObuf20wQic7vXfZ4TDTDojSkeEJk -S7aUKEivzMePdNJ+QYxK+/0w4klYUS62Xk5422zg90dvQ5P86aYHagrQ61jmpUIe -rthLgP+fHtXEJyb2Ud2fc+yx+Sn38ptWi52AcsECgYBIQe0O4Ouv/5kU6Uhjtc/a -w7NwtWMHiy+1dlf/DA6zBKuU92UaEJm7WzJ+Xuo0SXXWyYeCYkPxtv1VpypT5snK -Tx79yVc0mktvaQ7mNvWaW+Yh5oiW6ZCyB1YNBkyZUY9T8McXZak5M+K4uyP1jdOu -RHR1RmSwNKY4BHVX1mhCBQKBgQCNmuBFw0Uaad5nykzHID2aLBzev9uytd9tXlpm -0XLY+e5osYkZ2W/ovMEuCjSfNGjiFA/a4FKlP80na7kgk2QUhR0b2ueLttMgb4rZ -4kM95EKgnr69tDIEv6OjnBawbifpTuMiql813yRjKFzkSOB+ImyqluPr8QuKWPLX -+2NXAQKBgGAij1zH8M6vV486KA5l4PUyN9iaiakC262IH9bX3js93Wfwd1bGDtQA -rgxbhQNYifx3ID3HqxyJxWSennczHfEPTfkU4BooFzlqxhKPi+TT+Xd+N+fY5hGT -S8lS78V8hT8eOEIgGbsM5bckHQqNapGRCNsImIsNftLwmUCSQMDG ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCgWK9KGvqqM013 +jKEDiFmMYT0X6CyZNGGWzE1aF8yKa9P1bgpjI1cTwM8NW89Jq0AoAOun7ZBJ5/on +iH65IbSl3l7Vjab2MKQ15ZtXV2rwHnHA5iJOgVjOPVg7mWKOzlrK4Id4muMUS84Z +QsgYSvHJIhHspufJ1yjSttSl0A/wyr8ZQCONVjRyd4aSCGM8bUy75r+rRGZ5qqHH +w5W70/8DVW7LlzFW/rc28CkvYiOw3VjKniBb/Ruoduloo1WHB+KU0gDuePd96IIY +LhPlmfIvRT5LAmb2I1ShaLK9HwC3wBknJ/ZJG26TTNlSfLPan7ANcaD5+laZtOfJ +nOFkP65pAgMBAAECggEACF64v7iKzymgaJYprYKHkiFdTAstkM3ALlv5ybMmVS9t +wAj/d89Xc0uEQ2FAf8r1rWDm7DwlZQY786ZXXxiYUnQ6JRGg3ocJe1rB8hw5E9Gz +BGu+7LQpy5I+MdY+4893w9FWoQAMzHlsh7sJsOLwnhwuLVlFDi8yDVXH4ePrgRkv +DNJ1KFXvD2qJAKclFqQMmLShXy3iDjBQsYsYBZedzysakHhY8fQiQCcAKTnEwtJ1 +XpGF4pJh6o33ZQXVDhTvyaGTO6Sq2Qt+3pS1vMFSmKQFPG7iUnpsVi21a4ZMLFmq +B/PjTuDBmBSADUFHNRwLoUIrTu8opc5HoWFVp3TzgQKBgQDaIdZHQR40/nW+aa0W +4owgle9LqXCwwMESbwn7o8BAqVQkzu7C8g9OQ+fzkGVPjkBlQ/CC7zNz3d+/gb2/ +b5mL9ozBluJo37DfYehVSp2jC5SbfGmQanguwZ3ywBr3yM+RN8N4UkY6CJ+PB9I+ +199MjERu4Q6aIKXljRyIxHzLkQKBgQC8LsBK/VbMio/IEZjBLgSM2XiunWIsGd3l +HVMKNzv5HFmcVX1yVnyaPf6urqH706YkKjGoytTX/OLluxppbF2pHYhOl21c4FfR +2bMM2ES4WxgjQm2HWKb4oXQf58jdjqSfdgVvnS3rquwjnzODuT9l4GC2ZHdUPBN3 +TISb6d/ZWQKBgQCL8s+mkZnOyD9Etkot95WNxoRr178MN+7nY8RU5X+QPNNWdklr +W6AER78GXmsReqPIFKm3Z75sJTrLhHL34qLx0HIINkT2oiW5e/hy2FeA5womI9Ea +raSD4wbyWtwyg2zgr5VCmg6iZyvvuUXjud5zHz88oDodGrs1Jq7a9K1YcQKBgQCO +VcY4cjpO55ctOrIRm97xMiRn3r68oKwHehCvL2v7VggpiTgjXWtNtwqF0azPrxyB +SjDZfOFUpQBxxv2JM9/75EyPNVYQ49dI8KLPWl1QHAa71KjHsLRKZsRQxZ5WhmfZ +/QjLjVWIZXXK08XBIkLjqb089+ySGAaZO5Up4NHhsQKBgH6qHYHQ4x2Py1cZ1RiP +fwcMMlHA3+Ng1yuSvbwqY73XvIeN6Hhd5BtoFwe2xQJO0iBKI208pBDic1eDAr33 +1WID7atHLJI5eTZZzvnINUPnMi1D3ziohPknatca37cL/3i2JVaVELpmSmr92Tqu +TSNt6UCeZ2xyyGmUIPzRVmZB +-----END PRIVATE KEY----- diff --git a/test/key/ourdomain_with_intermediate.cer b/test/key/ourdomain_with_intermediate.cer new file mode 100644 index 000000000000..8aa55e500c8a --- /dev/null +++ b/test/key/ourdomain_with_intermediate.cer @@ -0,0 +1,50 @@ +-----BEGIN CERTIFICATE----- +MIIETTCCAzWgAwIBAgIBKDANBgkqhkiG9w0BAQ0FADCBmDELMAkGA1UEBhMCVVMx +CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRwwGgYDVQQKDBNI +YXNoaUNvcnAgVGVzdCBDZXJ0MQwwCgYDVQQLDANEZXYxFjAUBgNVBAMMDXRlc3Qu +aW50ZXJuYWwxIDAeBgkqhkiG9w0BCQEWEXRlc3RAaW50ZXJuYWwuY29tMCAXDTIz +MTEwMjE3MjAxNloYDzIxMjMxMDA5MTcyMDE2WjCBjTEYMBYGA1UEAwwPdGVzdGNv +LmludGVybmFsMRMwEQYDVQQIDApDYWxpZm9ybmlhMQswCQYDVQQGEwJVUzEpMCcG +CSqGSIb3DQEJARYaZG8tbm90LXJlcGx5QGhhc2hpY29ycC5jb20xEjAQBgNVBAoM +CUVuZCBQb2ludDEQMA4GA1UECwwHVGVzdGluZzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAOR5UJpDbgTsIgDNF6/fcafrPYTZlJnvMmYGxgPBH7lV2qqI +64yDE03++lLIOwPy8p0JHgCeoCsxRKhOXjaaBjOi3QGQFUU6rl/v8IZFsUo9NIyS +JJttiJaZCTjzgSZri3PdOHAClP5zF1/aAhTmNf326vAxqkn2MI8yglorOq+CSlOM +6p9nUGRAsoSvfjmz1vYDoyf4T0ZCUU+ieQ9KbcSVSrMip+r/CekfXglfIygfA+dx +dSK2Ivp0YjQbsnGEueDOaXMd2HX6Fh93K7IuvGKF2fAHHNl92uhnkbe63aJ7ZYgO +ftHKvVZFgq6cFFccAuI9qJlk6mo8P+m1ZNfv3dsCAwEAAaOBqDCBpTAJBgNVHRME +AjAAMB0GA1UdDgQWBBTxigs6/Ob0ULZZeeWqgTrxhfwQRDAfBgNVHSMEGDAWgBTm +rmqnZIdFOj6vhCUAJKLZNUDwFDALBgNVHQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYB +BQUHAwEGCCsGAQUFBwMCMCwGA1UdHwQlMCMwIaAfoB2GG2h0dHA6Ly9wYXRoLnRv +LmNybC9teWNhLmNybDANBgkqhkiG9w0BAQ0FAAOCAQEAXS69n70i8mdd2KpUtuVQ +TqCZPggLJ0ctSzSOVFz3ZFMTg50g3bvMZaK3jdwpL8GH7tMjEZANFaM/QNAJWMVb +pc0UD1UxdqahNj40I5V5RL/ocYZbzCVcNi6Y5Z9skROHS6/j4OsvCseYRkpVGMkE +x9bcWJ/cRfLmK9CO8MUrq8gCPYBA1av/uMAot7aT+2rLLcduF5bKuBGGTccVQ01x +5h+2bmFj8jxpju39HPGvZ7mnOqseVKhbKwE87vxirccM4UkwJDmWNuL7pX4CvwHi +aDtzDHJws/WPduT/r4eaXjMat7CF42tLP+w4FWNJH/P3UAzHPaPq2i2eHmCcuw4A +eA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEEzCCAvugAwIBAgIUIYIXKNRBFBPuuOit2D2CfVJAoDAwDQYJKoZIhvcNAQEL +BQAwgZgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZy +YW5jaXNjbzEcMBoGA1UECgwTSGFzaGlDb3JwIFRlc3QgQ2VydDEMMAoGA1UECwwD +RGV2MRYwFAYDVQQDDA10ZXN0LmludGVybmFsMSAwHgYJKoZIhvcNAQkBFhF0ZXN0 +QGludGVybmFsLmNvbTAeFw0yMzExMDIxNTUwMjlaFw0zMzEwMzAxNTUwMjlaMIGY +MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFuY2lz +Y28xHDAaBgNVBAoME0hhc2hpQ29ycCBUZXN0IENlcnQxDDAKBgNVBAsMA0RldjEW +MBQGA1UEAwwNdGVzdC5pbnRlcm5hbDEgMB4GCSqGSIb3DQEJARYRdGVzdEBpbnRl +cm5hbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCIA00iG5Iv +eRzZwf2P1Laih3eoiK2Wl1Re22cz2Pcpf6gb7agPguwU5Hco0DWzsnmek2Qyw9gl +oroX1t7LbTW2rxbK1hP7PkFCwSxi9u8MZDaLF3a79bwbsYZzf3toeoz8DCBxo9bB +SSACj4uI/S+lUjMctQrK1nFjGoNUHfxioXPwIJH+TS/76TiZPu3Zj6kN6taVFNe3 +ISBNXW6Vg8E3koz+9Bwv0a6Ty7oFRoJXpsud1k/83Iy288jhYDuB56+ypUmcCNqG +T+e0Bn/VXHx26GXTx97cXSLJE+o+JrHZaI1TcQUL2Z5DJZVJRUg/wtcXggoMLVI1 +O0enJm2jdmLXAgMBAAGjUzBRMB0GA1UdDgQWBBTmrmqnZIdFOj6vhCUAJKLZNUDw +FDAfBgNVHSMEGDAWgBTmrmqnZIdFOj6vhCUAJKLZNUDwFDAPBgNVHRMBAf8EBTAD +AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB3j6gvalxq54hZSwVmVZPMzjdTVYRC11b0 +6C9pWKsLwu+WINcs59ui8wpYVjcw1AK4/2I1Q7P4RgpSarAxG5tYIMB1xcfFKqBn +f/dDXexONgwpW6SoBJ58c7OB/aH8CenDT8Vwk3fwjYslOywbFRqBjH+PB8uTlu0e +D1fzjpcQCrQeA5VD4pjJAaTmi7bLVuH5XIya3++f/N3xOn53GVMUDO1OdFz8ZMvJ +Wrrg7E/wMXB1b5Wo2n2ypVU4sejikSjg2nfdLojUWGMrZ8TuUnjFs88PeQ9CObAp +A36dLfs4JLF3sVOtqTd6BGwegDsmmllYO5Ky6I+laoLSHpGDEihS +-----END CERTIFICATE----- diff --git a/test/notes.txt b/test/notes.txt deleted file mode 100644 index ae4f7098249f..000000000000 --- a/test/notes.txt +++ /dev/null @@ -1 +0,0 @@ -Instructions from https://langui.sh/2009/01/18/openssl-self-signed-ca/ diff --git a/testing/deployer/README.md b/testing/deployer/README.md index 604bbdb08781..513c6c6245ca 100644 --- a/testing/deployer/README.md +++ b/testing/deployer/README.md @@ -12,7 +12,7 @@ provider to manage a fleet of local docker containers and networks. The complete topology of Consul clusters is defined using a topology.Config which allows you to define a set of networks and reference those networks when -assigning nodes and services to clusters. Both Consul clients and +assigning nodes and workloads to clusters. Both Consul clients and `consul-dataplane` instances are supported. Here is an example configuration with two peered clusters: @@ -39,9 +39,9 @@ cfg := &topology.Config{ { Kind: topology.NodeKindClient, Name: "dc1-client1", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { - ID: topology.ServiceID{Name: "mesh-gateway"}, + ID: topology.ID{Name: "mesh-gateway"}, Port: 8443, EnvoyAdminPort: 19000, IsMeshGateway: true, @@ -51,9 +51,9 @@ cfg := &topology.Config{ { Kind: topology.NodeKindClient, Name: "dc1-client2", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { - ID: topology.ServiceID{Name: "ping"}, + ID: topology.ID{Name: "ping"}, Image: "rboyer/pingpong:latest", Port: 8080, EnvoyAdminPort: 19000, @@ -65,7 +65,7 @@ cfg := &topology.Config{ "-name", "ping", }, Upstreams: []*topology.Upstream{{ - ID: topology.ServiceID{Name: "pong"}, + ID: topology.ID{Name: "pong"}, LocalPort: 9090, Peer: "peer-dc2-default", }}, @@ -99,9 +99,9 @@ cfg := &topology.Config{ { Kind: topology.NodeKindClient, Name: "dc2-client1", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { - ID: topology.ServiceID{Name: "mesh-gateway"}, + ID: topology.ID{Name: "mesh-gateway"}, Port: 8443, EnvoyAdminPort: 19000, IsMeshGateway: true, @@ -111,9 +111,9 @@ cfg := &topology.Config{ { Kind: topology.NodeKindDataplane, Name: "dc2-client2", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { - ID: topology.ServiceID{Name: "pong"}, + ID: topology.ID{Name: "pong"}, Image: "rboyer/pingpong:latest", Port: 8080, EnvoyAdminPort: 19000, @@ -125,7 +125,7 @@ cfg := &topology.Config{ "-name", "pong", }, Upstreams: []*topology.Upstream{{ - ID: topology.ServiceID{Name: "ping"}, + ID: topology.ID{Name: "ping"}, LocalPort: 9090, Peer: "peer-dc1-default", }}, @@ -176,4 +176,4 @@ func TestSomething(t *testing.T) { sp := sprawltest.Launch(t, cfg) // do stuff with 'sp' } -``` \ No newline at end of file +``` diff --git a/testing/deployer/go.mod b/testing/deployer/go.mod index c7916a013c2e..e1bd6711a33a 100644 --- a/testing/deployer/go.mod +++ b/testing/deployer/go.mod @@ -3,23 +3,25 @@ module github.com/hashicorp/consul/testing/deployer go 1.20 require ( + github.com/avast/retry-go v3.0.0+incompatible github.com/google/go-cmp v0.5.9 github.com/hashicorp/consul-server-connection-manager v0.1.4 - github.com/hashicorp/consul/api v1.26.1 - github.com/hashicorp/consul/proto-public v0.5.1 - github.com/hashicorp/consul/sdk v0.15.0 + github.com/hashicorp/consul/api v1.29.4 + github.com/hashicorp/consul/proto-public v0.6.2 + github.com/hashicorp/consul/sdk v0.16.1 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-hclog v1.5.0 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-rootcerts v1.0.2 + github.com/hashicorp/go-version v1.2.1 github.com/hashicorp/hcl/v2 v2.16.2 github.com/mitchellh/copystructure v1.2.0 github.com/rboyer/safeio v0.2.2 - github.com/stretchr/testify v1.8.3 - golang.org/x/crypto v0.14.0 + github.com/stretchr/testify v1.8.4 + golang.org/x/crypto v0.22.0 golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 google.golang.org/grpc v1.56.3 - google.golang.org/protobuf v1.31.0 + google.golang.org/protobuf v1.33.0 ) require ( @@ -30,17 +32,16 @@ require ( github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/fatih/color v1.14.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-netaddrs v0.1.0 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/go-version v1.2.1 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/serf v0.10.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect @@ -53,9 +54,9 @@ require ( github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect github.com/zclconf/go-cty v1.12.1 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/testing/deployer/go.sum b/testing/deployer/go.sum index e632e8be7907..db7d88bffda4 100644 --- a/testing/deployer/go.sum +++ b/testing/deployer/go.sum @@ -15,6 +15,8 @@ github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJ github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= +github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -34,8 +36,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -55,9 +57,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -141,8 +142,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= @@ -216,8 +217,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY= github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= @@ -225,8 +226,8 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -239,8 +240,8 @@ golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -275,15 +276,16 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -300,9 +302,8 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/testing/deployer/sprawl/acl.go b/testing/deployer/sprawl/acl.go index 6196d94d46f9..d4098be251dd 100644 --- a/testing/deployer/sprawl/acl.go +++ b/testing/deployer/sprawl/acl.go @@ -146,6 +146,58 @@ func (s *Sprawl) createAnonymousPolicy(cluster *topology.Cluster) error { return nil } +// assignAgentJoinPolicyToAnonymousToken is used only for version prior to agent token +func (s *Sprawl) assignAgentJoinPolicyToAnonymousToken(cluster *topology.Cluster) error { + var ( + client = s.clients[cluster.Name] + ) + + acl := client.ACL() + anonymousTok, _, err := acl.TokenRead(anonymousTokenAccessorID, &api.QueryOptions{}) + if err != nil { + return nil + } + + rule := ` +service_prefix "" { + policy = "read" +} + +agent_prefix "" { + policy = "read" +} + +node_prefix "" { + policy = "write" +} + +operator = "write" +` + policy, _, err := acl.PolicyCreate( + &api.ACLPolicy{ + Name: "client-join-policy", + Rules: rule, + }, + &api.WriteOptions{}, + ) + + if err != nil { + return err + } + + anonymousTok.Policies = append(anonymousTok.Policies, + &api.ACLLink{ + Name: policy.Name, + }, + ) + _, _, err = acl.TokenUpdate(anonymousTok, &api.WriteOptions{}) + if err != nil { + return nil + } + + return nil +} + func (s *Sprawl) createAgentTokens(cluster *topology.Cluster) error { var ( client = s.clients[cluster.Name] @@ -158,18 +210,20 @@ func (s *Sprawl) createAgentTokens(cluster *topology.Cluster) error { continue } - if tok := s.secrets.ReadAgentToken(cluster.Name, node.ID()); tok == "" { - token, err := CreateOrUpdateToken(client, tokenForNode(node, cluster.Enterprise)) - if err != nil { - return err - } + if node.Images.GreaterThanVersion(topology.MinVersionAgentTokenPartition) { + if tok := s.secrets.ReadAgentToken(cluster.Name, node.ID()); tok == "" { + token, err := CreateOrUpdateToken(client, tokenForNode(node, cluster.Enterprise)) + if err != nil { + return fmt.Errorf("node %s: %w", node.Name, err) + } - logger.Debug("created agent token", - "node", node.ID(), - "token", token.SecretID, - ) + logger.Debug("created agent token", + "node", node.ID(), + "token", token.SecretID, + ) - s.secrets.SaveAgentToken(cluster.Name, node.ID(), token.SecretID) + s.secrets.SaveAgentToken(cluster.Name, node.ID(), token.SecretID) + } } } @@ -202,58 +256,56 @@ func (s *Sprawl) createCrossNamespaceCatalogReadPolicies(cluster *topology.Clust return nil } -func (s *Sprawl) createAllServiceTokens() error { +func (s *Sprawl) createAllWorkloadTokens() error { for _, cluster := range s.topology.Clusters { - if err := s.createServiceTokens(cluster); err != nil { - return fmt.Errorf("createServiceTokens[%s]: %w", cluster.Name, err) + if err := s.createWorkloadTokens(cluster); err != nil { + return fmt.Errorf("createWorkloadTokens[%s]: %w", cluster.Name, err) } } return nil } -func (s *Sprawl) createServiceTokens(cluster *topology.Cluster) error { +func (s *Sprawl) createWorkloadTokens(cluster *topology.Cluster) error { var ( client = s.clients[cluster.Name] logger = s.logger.With("cluster", cluster.Name) ) - sids := make(map[topology.ServiceID]struct{}) + workloadIDs := make(map[topology.ID]struct{}) for _, node := range cluster.Nodes { - if !node.RunsWorkloads() || len(node.Services) == 0 || node.Disabled { + if !node.RunsWorkloads() || len(node.Workloads) == 0 || node.Disabled { continue } - for _, svc := range node.Services { - sid := svc.ID - - if _, done := sids[sid]; done { + for _, wrk := range node.Workloads { + if _, done := workloadIDs[wrk.ID]; done { continue } var overridePolicy *api.ACLPolicy - if svc.IsMeshGateway { + if wrk.IsMeshGateway { var err error - overridePolicy, err = CreateOrUpdatePolicy(client, policyForMeshGateway(svc, cluster.Enterprise)) + overridePolicy, err = CreateOrUpdatePolicy(client, policyForMeshGateway(wrk, cluster.Enterprise)) if err != nil { return fmt.Errorf("could not create policy: %w", err) } } - token, err := CreateOrUpdateToken(client, tokenForService(svc, overridePolicy, cluster.Enterprise)) + token, err := CreateOrUpdateToken(client, tokenForWorkload(wrk, overridePolicy, cluster.Enterprise)) if err != nil { return fmt.Errorf("could not create token: %w", err) } - logger.Debug("created service token", - "service", svc.ID.Name, - "namespace", svc.ID.Namespace, - "partition", svc.ID.Partition, + logger.Debug("created workload token", + "workload", wrk.ID.Name, + "namespace", wrk.ID.Namespace, + "partition", wrk.ID.Partition, "token", token.SecretID, ) - s.secrets.SaveServiceToken(cluster.Name, sid, token.SecretID) + s.secrets.SaveWorkloadToken(cluster.Name, wrk.ID, token.SecretID) - sids[sid] = struct{}{} + workloadIDs[wrk.ID] = struct{}{} } } diff --git a/testing/deployer/sprawl/acl_rules.go b/testing/deployer/sprawl/acl_rules.go index 98910126b303..fd0033f24639 100644 --- a/testing/deployer/sprawl/acl_rules.go +++ b/testing/deployer/sprawl/acl_rules.go @@ -7,7 +7,6 @@ import ( "fmt" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/testing/deployer/topology" ) @@ -86,29 +85,27 @@ func tokenForNode(node *topology.Node, enterprise bool) *api.ACLToken { return token } -func tokenForService(svc *topology.Service, overridePolicy *api.ACLPolicy, enterprise bool) *api.ACLToken { +// Deprecated: tokenForWorkload +func tokenForService(wrk *topology.Workload, overridePolicy *api.ACLPolicy, enterprise bool) *api.ACLToken { + return tokenForWorkload(wrk, overridePolicy, enterprise) +} + +func tokenForWorkload(wrk *topology.Workload, overridePolicy *api.ACLPolicy, enterprise bool) *api.ACLToken { token := &api.ACLToken{ - Description: "service--" + svc.ID.ACLString(), + Description: "service--" + wrk.ID.ACLString(), Local: false, } if overridePolicy != nil { token.Policies = []*api.ACLTokenPolicyLink{{ID: overridePolicy.ID}} - } else if svc.IsV2() { - token.TemplatedPolicies = []*api.ACLTemplatedPolicy{{ - TemplateName: api.ACLTemplatedPolicyWorkloadIdentityName, - TemplateVariables: &api.ACLTemplatedPolicyVariables{ - Name: svc.ID.Name, - }, - }} } else { token.ServiceIdentities = []*api.ACLServiceIdentity{{ - ServiceName: svc.ID.Name, + ServiceName: wrk.ID.Name, }} } if enterprise { - token.Namespace = svc.ID.Namespace - token.Partition = svc.ID.Partition + token.Namespace = wrk.ID.Namespace + token.Partition = wrk.ID.Partition } return token @@ -176,20 +173,20 @@ mesh = "write" ` ) -func policyForMeshGateway(svc *topology.Service, enterprise bool) *api.ACLPolicy { - policyName := "mesh-gateway--" + svc.ID.ACLString() +func policyForMeshGateway(wrk *topology.Workload, enterprise bool) *api.ACLPolicy { + policyName := "mesh-gateway--" + wrk.ID.ACLString() policy := &api.ACLPolicy{ Name: policyName, Description: policyName, } if enterprise { - policy.Partition = svc.ID.Partition + policy.Partition = wrk.ID.Partition policy.Namespace = "default" } if enterprise { - if svc.ID.Partition == "default" { + if wrk.ID.Partition == "default" { policy.Rules = meshGatewayEntDefaultRules } else { policy.Rules = meshGatewayEntNonDefaultRules diff --git a/testing/deployer/sprawl/boot.go b/testing/deployer/sprawl/boot.go index 3bbb9e864e87..2840eaf76039 100644 --- a/testing/deployer/sprawl/boot.go +++ b/testing/deployer/sprawl/boot.go @@ -12,9 +12,11 @@ import ( "strings" "time" - "github.com/hashicorp/consul/api" + retry "github.com/avast/retry-go" + "github.com/hashicorp/go-multierror" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/testing/deployer/sprawl/internal/build" "github.com/hashicorp/consul/testing/deployer/sprawl/internal/secrets" "github.com/hashicorp/consul/testing/deployer/sprawl/internal/tfgen" @@ -29,15 +31,31 @@ const ( sharedAgentRecoveryToken = "22082b05-05c9-4a0a-b3da-b9685ac1d688" ) -func (s *Sprawl) launch() error { - return s.launchType(true) -} +type LaunchPhase int -func (s *Sprawl) relaunch() error { - return s.launchType(false) +const ( + LaunchPhaseRegular LaunchPhase = iota + LaunchPhaseUpgrade +) + +func (lp LaunchPhase) String() string { + phaseStr := "" + switch lp { + case LaunchPhaseRegular: + phaseStr = "regular" + case LaunchPhaseUpgrade: + phaseStr = "upgrade" + } + return phaseStr } -func (s *Sprawl) launchType(firstTime bool) (launchErr error) { +func (s *Sprawl) launch() error { + return s.launchType(true, LaunchPhaseRegular) +} +func (s *Sprawl) relaunch(launchPhase LaunchPhase) error { + return s.launchType(false, launchPhase) +} +func (s *Sprawl) launchType(firstTime bool, launchPhase LaunchPhase) (launchErr error) { if err := build.DockerImages(s.logger, s.runner, s.topology); err != nil { return fmt.Errorf("build.DockerImages: %w", err) } @@ -121,7 +139,7 @@ func (s *Sprawl) launchType(firstTime bool) (launchErr error) { s.generator.MarkLaunched() } else { - if err := s.updateExisting(); err != nil { + if err := s.updateExisting(firstTime, launchPhase); err != nil { return err } } @@ -130,6 +148,10 @@ func (s *Sprawl) launchType(firstTime bool) (launchErr error) { return fmt.Errorf("waitForPeeringEstablishment: %w", err) } + if err := s.waitForNetworkAreaEstablishment(); err != nil { + return fmt.Errorf("waitForNetworkAreaEstablishment: %w", err) + } + cleanupFuncs = nil // reset return nil @@ -182,7 +204,7 @@ func (s *Sprawl) assignIPAddresses() error { return fmt.Errorf("unknown network %q", addr.Network) } addr.IPAddress = net.IPByIndex(node.Index) - s.logger.Info("assign addr", "node", node.Name, "addr", addr.IPAddress) + s.logger.Info("assign addr", "node", node.Name, "addr", addr.IPAddress, "type", addr.Type, "enabled", !node.Disabled) } } } @@ -237,8 +259,8 @@ func (s *Sprawl) initConsulServers() error { return fmt.Errorf("error creating final client for cluster=%s: %v", cluster.Name, err) } - // Connect to gRPC as well. - if cluster.EnableV2 { + // Connect to gRPC as well for the resource service. + { s.grpcConns[cluster.Name], s.grpcConnCancel[cluster.Name], err = s.dialServerGRPC(cluster, node, mgmtToken) if err != nil { return fmt.Errorf("error creating gRPC client conn for cluster=%s: %w", cluster.Name, err) @@ -250,7 +272,7 @@ func (s *Sprawl) initConsulServers() error { s.waitForLocalWrites(cluster, mgmtToken) // Create tenancies so that the ACL tokens and clients have somewhere to go. - if cluster.Enterprise { + if cluster.Enterprise && node.Images.GreaterThanVersion(topology.MinVersionAgentTokenPartition) { if err := s.initTenancies(cluster); err != nil { return fmt.Errorf("initTenancies[%s]: %w", cluster.Name, err) } @@ -268,12 +290,19 @@ func (s *Sprawl) initConsulServers() error { return fmt.Errorf("createAnonymousToken[%s]: %w", cluster.Name, err) } - // Create tokens for all of the agents to use for anti-entropy. - // - // NOTE: this will cause the servers to roll to pick up the change to - // the acl{tokens{agent=XXX}}} section. - if err := s.createAgentTokens(cluster); err != nil { - return fmt.Errorf("createAgentTokens[%s]: %w", cluster.Name, err) + if node.Images.GreaterThanVersion(topology.MinVersionAgentTokenPartition) { + // Create tokens for all of the agents to use for anti-entropy. + // + // NOTE: this will cause the servers to roll to pick up the change to + // the acl{tokens{agent=XXX}}} section. + if err := s.createAgentTokens(cluster); err != nil { + return fmt.Errorf("createAgentTokens[%s]: %w", cluster.Name, err) + } + } else { + // Assign agent join policy to the anonymous token + if err := s.assignAgentJoinPolicyToAnonymousToken(cluster); err != nil { + return fmt.Errorf("assignAgentJoinPolicyToAnonymousToken[%s]: %w", cluster.Name, err) + } } } @@ -282,6 +311,9 @@ func (s *Sprawl) initConsulServers() error { func (s *Sprawl) createFirstTime() error { if err := s.initConsulServers(); err != nil { + if err := s.CaptureLogs(context.Background()); err != nil { + s.logger.Warn("container logs capture encountered failures", "error", err) + } return fmt.Errorf("initConsulServers: %w", err) } @@ -289,19 +321,29 @@ func (s *Sprawl) createFirstTime() error { return fmt.Errorf("generator[agents]: %w", err) } for _, cluster := range s.topology.Clusters { - if err := s.waitForClientAntiEntropyOnce(cluster); err != nil { - return fmt.Errorf("waitForClientAntiEntropyOnce[%s]: %w", cluster.Name, err) + err := retry.Do( + func() error { + if err := s.waitForClientAntiEntropyOnce(cluster); err != nil { + return fmt.Errorf("create first time - waitForClientAntiEntropyOnce[%s]: %w", cluster.Name, err) + } + return nil + }, + retry.MaxDelay(5*time.Second), + retry.Attempts(15), + ) + if err != nil { + return fmt.Errorf("create first time - waitForClientAntiEntropyOnce[%s]: %w", cluster.Name, err) } } // Ideally we start services WITH a token initially, so we pre-create them // before running terraform for them. - if err := s.createAllServiceTokens(); err != nil { - return fmt.Errorf("createAllServiceTokens: %w", err) + if err := s.createAllWorkloadTokens(); err != nil { + return fmt.Errorf("createAllWorkloadTokens: %w", err) } - if err := s.registerAllServicesForDataplaneInstances(); err != nil { - return fmt.Errorf("registerAllServicesForDataplaneInstances: %w", err) + if err := s.syncAllServicesForDataplaneInstances(); err != nil { + return fmt.Errorf("syncAllServicesForDataplaneInstances: %w", err) } // We can do this ahead, because we've incrementally run terraform as @@ -318,12 +360,25 @@ func (s *Sprawl) createFirstTime() error { if err := s.initPeerings(); err != nil { return fmt.Errorf("initPeerings: %w", err) } + + if err := s.initNetworkAreas(); err != nil { + return fmt.Errorf("initNetworkAreas: %w", err) + } return nil } -func (s *Sprawl) updateExisting() error { - if err := s.preRegenTasks(); err != nil { - return fmt.Errorf("preRegenTasks: %w", err) +func (s *Sprawl) updateExisting(firstTime bool, launchPhase LaunchPhase) error { + if launchPhase != LaunchPhaseUpgrade { + if err := s.preRegenTasks(); err != nil { + return fmt.Errorf("preRegenTasks: %w", err) + } + } else { + s.logger.Info("Upgrade - skip preRegenTasks") + for _, cluster := range s.topology.Clusters { + if err := s.createAgentTokens(cluster); err != nil { + return fmt.Errorf("createAgentTokens[%s]: %w", cluster.Name, err) + } + } } // We save all of the terraform to the end. Some of the containers will @@ -333,7 +388,7 @@ func (s *Sprawl) updateExisting() error { return fmt.Errorf("generator[relaunch]: %w", err) } - if err := s.postRegenTasks(); err != nil { + if err := s.postRegenTasks(firstTime); err != nil { return fmt.Errorf("postRegenTasks: %w", err) } @@ -364,20 +419,23 @@ func (s *Sprawl) preRegenTasks() error { // Ideally we start services WITH a token initially, so we pre-create them // before running terraform for them. - if err := s.createAllServiceTokens(); err != nil { - return fmt.Errorf("createAllServiceTokens: %w", err) + if err := s.createAllWorkloadTokens(); err != nil { + return fmt.Errorf("createAllWorkloadTokens: %w", err) } - if err := s.registerAllServicesForDataplaneInstances(); err != nil { - return fmt.Errorf("registerAllServicesForDataplaneInstances: %w", err) + if err := s.syncAllServicesForDataplaneInstances(); err != nil { + return fmt.Errorf("syncAllServicesForDataplaneInstances: %w", err) } return nil } -func (s *Sprawl) postRegenTasks() error { - if err := s.rejoinAllConsulServers(); err != nil { - return err +func (s *Sprawl) postRegenTasks(firstTime bool) error { + // rejoinAllConsulServers only for firstTime; otherwise all server agents have retry_join + if firstTime { + if err := s.rejoinAllConsulServers(); err != nil { + return err + } } for _, cluster := range s.topology.Clusters { @@ -387,6 +445,9 @@ func (s *Sprawl) postRegenTasks() error { // Reconfigure the clients to use a management token. node := cluster.FirstServer() + if node.Disabled { + continue + } s.clients[cluster.Name], err = util.ProxyAPIClient( node.LocalProxyPort(), node.LocalAddress(), @@ -406,7 +467,7 @@ func (s *Sprawl) postRegenTasks() error { for _, cluster := range s.topology.Clusters { if err := s.waitForClientAntiEntropyOnce(cluster); err != nil { - return fmt.Errorf("waitForClientAntiEntropyOnce[%s]: %w", cluster.Name, err) + return fmt.Errorf("post regenerate waitForClientAntiEntropyOnce[%s]: %w", cluster.Name, err) } } @@ -453,7 +514,8 @@ func (s *Sprawl) waitForLocalWrites(cluster *topology.Cluster, token string) { break } - if cluster.Enterprise { + serverNodes := cluster.ServerNodes() + if cluster.Enterprise && serverNodes[0].Images.GreaterThanVersion(topology.MinVersionAgentTokenPartition) { start = time.Now() for attempts := 0; ; attempts++ { if err := tryAP(); err != nil { @@ -471,9 +533,6 @@ func (s *Sprawl) waitForLocalWrites(cluster *topology.Cluster, token string) { } func (s *Sprawl) waitForClientAntiEntropyOnce(cluster *topology.Cluster) error { - if cluster.EnableV2 { - return nil // v1 catalog is disabled when v2 catalog is enabled - } var ( client = s.clients[cluster.Name] logger = s.logger.With("cluster", cluster.Name) @@ -509,7 +568,7 @@ func (s *Sprawl) waitForClientAntiEntropyOnce(cluster *topology.Cluster) error { nid := node.CatalogID() got, ok := current[nid] - if ok && len(got.TaggedAddresses) > 0 { + if ok && (len(got.TaggedAddresses) > 0 || got.Address != "") { // this is a field that is not updated just due to serf reconcile continue } diff --git a/testing/deployer/sprawl/catalog.go b/testing/deployer/sprawl/catalog.go index fdc95c9f6893..e8ec68b03d79 100644 --- a/testing/deployer/sprawl/catalog.go +++ b/testing/deployer/sprawl/catalog.go @@ -9,18 +9,16 @@ import ( "net/http" "time" - "github.com/hashicorp/consul/api" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/testing/deployer/topology" "github.com/hashicorp/consul/testing/deployer/util" ) +// registerAllServicesToAgents registers services in agent-ful mode func (s *Sprawl) registerAllServicesToAgents() error { for _, cluster := range s.topology.Clusters { if err := s.registerServicesToAgents(cluster); err != nil { @@ -30,10 +28,10 @@ func (s *Sprawl) registerAllServicesToAgents() error { return nil } -func (s *Sprawl) registerAllServicesForDataplaneInstances() error { +func (s *Sprawl) syncAllServicesForDataplaneInstances() error { for _, cluster := range s.topology.Clusters { - if err := s.registerServicesForDataplaneInstances(cluster); err != nil { - return fmt.Errorf("registerServicesForDataplaneInstances[%s]: %w", cluster.Name, err) + if err := s.syncWorkloadsForDataplaneInstances(cluster); err != nil { + return fmt.Errorf("syncWorkloadsForDataplaneInstances[%s]: %w", cluster.Name, err) } } return nil @@ -41,16 +39,13 @@ func (s *Sprawl) registerAllServicesForDataplaneInstances() error { func (s *Sprawl) registerServicesToAgents(cluster *topology.Cluster) error { for _, node := range cluster.Nodes { - if !node.RunsWorkloads() || len(node.Services) == 0 || node.Disabled { + if !node.RunsWorkloads() || len(node.Workloads) == 0 || node.Disabled { continue } if !node.IsAgent() { continue } - if node.IsV2() { - panic("don't call this") - } agentClient, err := util.ProxyAPIClient( node.LocalProxyPort(), @@ -62,8 +57,8 @@ func (s *Sprawl) registerServicesToAgents(cluster *topology.Cluster) error { return err } - for _, svc := range node.Services { - if err := s.registerAgentService(agentClient, cluster, node, svc); err != nil { + for _, wrk := range node.Workloads { + if err := s.registerAgentService(agentClient, cluster, node, wrk); err != nil { return err } } @@ -76,17 +71,14 @@ func (s *Sprawl) registerAgentService( agentClient *api.Client, cluster *topology.Cluster, node *topology.Node, - svc *topology.Service, + wrk *topology.Workload, ) error { if !node.IsAgent() { panic("called wrong method type") } - if node.IsV2() { - panic("don't call this") - } - if svc.IsMeshGateway { - return nil // handled at startup time for agent-full, but won't be for agent-less + if wrk.IsMeshGateway { + return nil // handled at startup time for agent-ful, but won't be for agent-less } var ( @@ -94,31 +86,31 @@ func (s *Sprawl) registerAgentService( ) reg := &api.AgentServiceRegistration{ - ID: svc.ID.Name, - Name: svc.ID.Name, - Port: svc.Port, - Meta: svc.Meta, + ID: wrk.ID.Name, + Name: wrk.ID.Name, + Port: wrk.Port, + Meta: wrk.Meta, } if cluster.Enterprise { - reg.Namespace = svc.ID.Namespace - reg.Partition = svc.ID.Partition + reg.Namespace = wrk.ID.Namespace + reg.Partition = wrk.ID.Partition } - if !svc.DisableServiceMesh { + if !wrk.DisableServiceMesh { var upstreams []api.Upstream - for _, u := range svc.Upstreams { + for _, us := range wrk.Upstreams { uAPI := api.Upstream{ - DestinationPeer: u.Peer, - DestinationName: u.ID.Name, - LocalBindAddress: u.LocalAddress, - LocalBindPort: u.LocalPort, + DestinationPeer: us.Peer, + DestinationName: us.ID.Name, + LocalBindAddress: us.LocalAddress, + LocalBindPort: us.LocalPort, // Config map[string]interface{} `json:",omitempty" bexpr:"-"` // MeshGateway MeshGatewayConfig `json:",omitempty"` } if cluster.Enterprise { - uAPI.DestinationNamespace = u.ID.Namespace - if u.Peer == "" { - uAPI.DestinationPartition = u.ID.Partition + uAPI.DestinationNamespace = us.ID.Namespace + if us.Peer == "" { + uAPI.DestinationPartition = us.ID.Partition } } upstreams = append(upstreams, uAPI) @@ -133,18 +125,18 @@ func (s *Sprawl) registerAgentService( } switch { - case svc.CheckTCP != "": + case wrk.CheckTCP != "": chk := &api.AgentServiceCheck{ Name: "up", - TCP: svc.CheckTCP, + TCP: wrk.CheckTCP, Interval: "5s", Timeout: "1s", } reg.Checks = append(reg.Checks, chk) - case svc.CheckHTTP != "": + case wrk.CheckHTTP != "": chk := &api.AgentServiceCheck{ Name: "up", - HTTP: svc.CheckHTTP, + HTTP: wrk.CheckHTTP, Method: "GET", Interval: "5s", Timeout: "1s", @@ -154,7 +146,7 @@ func (s *Sprawl) registerAgentService( // Switch token for every request. hdr := make(http.Header) - hdr.Set("X-Consul-Token", s.secrets.ReadServiceToken(cluster.Name, svc.ID)) + hdr.Set("X-Consul-Token", s.secrets.ReadWorkloadToken(cluster.Name, wrk.ID)) agentClient.SetHeaders(hdr) RETRY: @@ -163,130 +155,83 @@ RETRY: time.Sleep(50 * time.Millisecond) goto RETRY } - return fmt.Errorf("failed to register service %q to node %q: %w", svc.ID, node.ID(), err) + return fmt.Errorf("failed to register workload %q to node %q: %w", wrk.ID, node.ID(), err) } - logger.Debug("registered service to client agent", - "service", svc.ID.Name, + logger.Debug("registered workload to client agent", + "workload", wrk.ID.Name, "node", node.Name, - "namespace", svc.ID.Namespace, - "partition", svc.ID.Partition, + "namespace", wrk.ID.Namespace, + "partition", wrk.ID.Partition, ) return nil } -func (s *Sprawl) registerServicesForDataplaneInstances(cluster *topology.Cluster) error { - identityInfo := make(map[topology.ServiceID]*Resource[*pbauth.WorkloadIdentity]) - - for _, node := range cluster.Nodes { - if !node.RunsWorkloads() || len(node.Services) == 0 || node.Disabled { - continue +// syncWorkloadsForDataplaneInstances register/deregister services in the given cluster +func (s *Sprawl) syncWorkloadsForDataplaneInstances(cluster *topology.Cluster) error { + // registerWorkloadToNode is called when node is not disabled + registerWorkloadToNode := func(node *topology.Node, wrk *topology.Workload) error { + if err := s.registerCatalogServiceV1(cluster, node, wrk); err != nil { + return fmt.Errorf("error registering service: %w", err) } - - if !node.IsDataplane() { - continue + if !wrk.DisableServiceMesh { + if err := s.registerCatalogSidecarServiceV1(cluster, node, wrk); err != nil { + return fmt.Errorf("error registering sidecar service: %w", err) + } } + return nil + } - if err := s.registerCatalogNode(cluster, node); err != nil { - return fmt.Errorf("error registering virtual node: %w", err) + // deregisterWorkloadFromNode is called when node is disabled + deregisterWorkloadFromNode := func(node *topology.Node, wrk *topology.Workload) error { + if err := s.deregisterCatalogServiceV1(cluster, node, wrk); err != nil { + return fmt.Errorf("error deregistering service: %w", err) } - - for _, svc := range node.Services { - if node.IsV2() { - pending := serviceInstanceToResources(node, svc) - - workloadID := topology.NewServiceID(svc.WorkloadIdentity, svc.ID.Namespace, svc.ID.Partition) - if _, ok := identityInfo[workloadID]; !ok { - identityInfo[workloadID] = pending.WorkloadIdentity - } - - // Write workload - res, err := pending.Workload.Build() - if err != nil { - return fmt.Errorf("error serializing resource %s: %w", util.IDToString(pending.Workload.Resource.Id), err) - } - workload, err := s.writeResource(cluster, res) - if err != nil { - return err - } - // Write check linked to workload - for _, check := range pending.HealthStatuses { - check.Resource.Owner = workload.Id - res, err := check.Build() - if err != nil { - return fmt.Errorf("error serializing resource %s: %w", util.IDToString(check.Resource.Id), err) - } - if _, err := s.writeResource(cluster, res); err != nil { - return err - } - } - // maybe write destinations - if pending.Destinations != nil { - res, err := pending.Destinations.Build() - if err != nil { - return fmt.Errorf("error serializing resource %s: %w", util.IDToString(pending.Destinations.Resource.Id), err) - } - if _, err := s.writeResource(cluster, res); err != nil { - return err - } - } - if pending.ProxyConfiguration != nil { - res, err := pending.ProxyConfiguration.Build() - if err != nil { - return fmt.Errorf("error serializing resource %s: %w", util.IDToString(pending.ProxyConfiguration.Resource.Id), err) - } - if _, err := s.writeResource(cluster, res); err != nil { - return err - } - } - } else { - if err := s.registerCatalogServiceV1(cluster, node, svc); err != nil { - return fmt.Errorf("error registering service: %w", err) - } - if !svc.DisableServiceMesh { - if err := s.registerCatalogSidecarServiceV1(cluster, node, svc); err != nil { - return fmt.Errorf("error registering sidecar service: %w", err) - } - } + if !wrk.DisableServiceMesh { + if err := s.deregisterCatalogSidecarServiceV1(cluster, node, wrk); err != nil { + return fmt.Errorf("error deregistering sidecar service: %w", err) } } + return nil } - for _, identity := range identityInfo { - res, err := identity.Build() - if err != nil { - return fmt.Errorf("error serializing resource %s: %w", util.IDToString(identity.Resource.Id), err) + var syncWorkload func(node *topology.Node, wrk *topology.Workload) error + + for _, node := range cluster.Nodes { + if !node.RunsWorkloads() || len(node.Workloads) == 0 { + continue } - if _, err := s.writeResource(cluster, res); err != nil { - return err + + if !node.IsDataplane() { + continue } - } - if cluster.EnableV2 { - for id, svcData := range cluster.Services { - svcInfo := &Resource[*pbcatalog.Service]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.ServiceType, - Name: id.Name, - Tenancy: &pbresource.Tenancy{ - Partition: id.Partition, - Namespace: id.Namespace, - }, - }, - }, - Data: svcData, + // Register virtual node service first if node is not disabled + if !node.Disabled { + if err := s.registerCatalogNode(cluster, node); err != nil { + return fmt.Errorf("error registering virtual node: %w", err) } + } - res, err := svcInfo.Build() - if err != nil { - return fmt.Errorf("error serializing resource %s: %w", util.IDToString(svcInfo.Resource.Id), err) + // Register/deregister services on the node + for _, wrk := range node.Workloads { + if !node.Disabled { + syncWorkload = registerWorkloadToNode + } else { + syncWorkload = deregisterWorkloadFromNode } - if _, err := s.writeResource(cluster, res); err != nil { + if err := syncWorkload(node, wrk); err != nil { return err } } + + // Deregister the virtual node if node is disabled + if node.Disabled { + if err := s.deregisterCatalogNode(cluster, node); err != nil { + return fmt.Errorf("error deregistering virtual node: %w", err) + } + } } return nil @@ -296,57 +241,14 @@ func (s *Sprawl) registerCatalogNode( cluster *topology.Cluster, node *topology.Node, ) error { - if node.IsV2() { - - // TODO(rb): nodes are optional in v2 and won't be used in k8s by - // default. There are some scoping issues with the Node Type in 1.17 so - // disable it for now. - // - // To re-enable you also need to link it to the Workload by setting the - // NodeName field. - // - // return s.registerCatalogNodeV2(cluster, node) - return nil - } return s.registerCatalogNodeV1(cluster, node) } -func (s *Sprawl) registerCatalogNodeV2( +func (s *Sprawl) deregisterCatalogNode( cluster *topology.Cluster, node *topology.Node, ) error { - if !node.IsDataplane() { - panic("called wrong method type") - } - - nodeRes := &Resource[*pbcatalog.Node]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.NodeType, - Name: node.PodName(), - Tenancy: &pbresource.Tenancy{ - Partition: node.Partition, - Namespace: "default", // temporary requirement - }, - }, - Metadata: map[string]string{ - "dataplane-faux": "1", - }, - }, - Data: &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{ - {Host: node.LocalAddress()}, - }, - }, - } - - res, err := nodeRes.Build() - if err != nil { - return err - } - - _, err = s.writeResource(cluster, res) - return err + return s.deregisterCatalogNodeV1(cluster, node) } func (s *Sprawl) writeResource(cluster *topology.Cluster, res *pbresource.Resource) (*pbresource.Resource, error) { @@ -413,274 +315,220 @@ RETRY: return nil } -func (s *Sprawl) registerCatalogServiceV1( +func (s *Sprawl) deregisterCatalogNodeV1( cluster *topology.Cluster, node *topology.Node, - svc *topology.Service, ) error { if !node.IsDataplane() { panic("called wrong method type") } - if node.IsV2() { - panic("don't call this") - } var ( client = s.clients[cluster.Name] logger = s.logger.With("cluster", cluster.Name) ) - reg := serviceToCatalogRegistration(cluster, node, svc) + dereg := &api.CatalogDeregistration{ + Node: node.PodName(), + Address: node.LocalAddress(), + } + if cluster.Enterprise { + dereg.Partition = node.Partition + } + // deregister synthetic node RETRY: - if _, err := client.Catalog().Register(reg, nil); err != nil { + if _, err := client.Catalog().Deregister(dereg, nil); err != nil { if isACLNotFound(err) { time.Sleep(50 * time.Millisecond) goto RETRY } - return fmt.Errorf("error registering service %s to node %s: %w", svc.ID, node.ID(), err) + return fmt.Errorf("error deregistering virtual node %s: %w", node.ID(), err) } - logger.Debug("dataplane service created", - "service", svc.ID, + logger.Info("virtual node removed", "node", node.ID(), ) return nil } -func (s *Sprawl) registerCatalogSidecarServiceV1( +func (s *Sprawl) deregisterCatalogServiceV1( cluster *topology.Cluster, node *topology.Node, - svc *topology.Service, + wrk *topology.Workload, ) error { if !node.IsDataplane() { panic("called wrong method type") } - if svc.DisableServiceMesh { - panic("not valid") - } - if node.IsV2() { - panic("don't call this") - } var ( client = s.clients[cluster.Name] logger = s.logger.With("cluster", cluster.Name) ) - pid, reg := serviceToSidecarCatalogRegistration(cluster, node, svc) + dereg := &api.CatalogDeregistration{ + Node: node.PodName(), + ServiceID: wrk.ID.Name, + } RETRY: - if _, err := client.Catalog().Register(reg, nil); err != nil { + if _, err := client.Catalog().Deregister(dereg, nil); err != nil { if isACLNotFound(err) { time.Sleep(50 * time.Millisecond) goto RETRY } - return fmt.Errorf("error registering service %s to node %s: %w", svc.ID, node.ID(), err) + return fmt.Errorf("error deregistering service %s at node %s: %w", wrk.ID, node.ID(), err) } - logger.Debug("dataplane sidecar service created", - "service", pid, + logger.Info("dataplane service removed", + "service", wrk.ID, "node", node.ID(), ) return nil } -type Resource[V proto.Message] struct { - Resource *pbresource.Resource - Data V -} +func (s *Sprawl) registerCatalogServiceV1( + cluster *topology.Cluster, + node *topology.Node, + wrk *topology.Workload, +) error { + if !node.IsDataplane() { + panic("called wrong method type") + } -func (r *Resource[V]) Build() (*pbresource.Resource, error) { - anyData, err := anypb.New(r.Data) - if err != nil { - return nil, err + var ( + client = s.clients[cluster.Name] + logger = s.logger.With("cluster", cluster.Name) + ) + + reg := workloadToCatalogRegistration(cluster, node, wrk) + +RETRY: + if _, err := client.Catalog().Register(reg, nil); err != nil { + if isACLNotFound(err) { + time.Sleep(50 * time.Millisecond) + goto RETRY + } + return fmt.Errorf("error registering service %s to node %s: %w", wrk.ID, node.ID(), err) } - r.Resource.Data = anyData - return r.Resource, nil -} -type ServiceResources struct { - Workload *Resource[*pbcatalog.Workload] - HealthStatuses []*Resource[*pbcatalog.HealthStatus] - Destinations *Resource[*pbmesh.Destinations] - WorkloadIdentity *Resource[*pbauth.WorkloadIdentity] - ProxyConfiguration *Resource[*pbmesh.ProxyConfiguration] + logger.Debug("dataplane service created", + "service", wrk.ID, + "node", node.ID(), + ) + + return nil } -func serviceInstanceToResources( +func (s *Sprawl) deregisterCatalogSidecarServiceV1( + cluster *topology.Cluster, node *topology.Node, - svc *topology.Service, -) *ServiceResources { - if svc.IsMeshGateway { - panic("v2 does not yet support mesh gateways") + wrk *topology.Workload, +) error { + if !node.IsDataplane() { + panic("called wrong method type") } - - tenancy := &pbresource.Tenancy{ - Partition: svc.ID.Partition, - Namespace: svc.ID.Namespace, + if wrk.DisableServiceMesh { + panic("not valid") } var ( - wlPorts = map[string]*pbcatalog.WorkloadPort{} + client = s.clients[cluster.Name] + logger = s.logger.With("cluster", cluster.Name) ) - for name, port := range svc.Ports { - wlPorts[name] = &pbcatalog.WorkloadPort{ - Port: uint32(port.Number), - Protocol: port.ActualProtocol, - } - } - var ( - selector = &pbcatalog.WorkloadSelector{ - Names: []string{svc.Workload}, - } + pid := wrk.ID + pid.Name += "-sidecar-proxy" + dereg := &api.CatalogDeregistration{ + Node: node.PodName(), + ServiceID: pid.Name, + } - workloadRes = &Resource[*pbcatalog.Workload]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.WorkloadType, - Name: svc.Workload, - Tenancy: tenancy, - }, - Metadata: svc.Meta, - }, - Data: &pbcatalog.Workload{ - // TODO(rb): disabling this until node scoping makes sense again - // NodeName: node.PodName(), - Identity: svc.ID.Name, - Ports: wlPorts, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: node.LocalAddress()}, - }, - }, - } - workloadIdentityRes = &Resource[*pbauth.WorkloadIdentity]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbauth.WorkloadIdentityType, - Name: svc.WorkloadIdentity, - Tenancy: tenancy, - }, - }, - Data: &pbauth.WorkloadIdentity{}, +RETRY: + if _, err := client.Catalog().Deregister(dereg, nil); err != nil { + if isACLNotFound(err) { + time.Sleep(50 * time.Millisecond) + goto RETRY } + return fmt.Errorf("error deregistering service %s to node %s: %w", wrk.ID, node.ID(), err) + } - healthResList []*Resource[*pbcatalog.HealthStatus] - destinationsRes *Resource[*pbmesh.Destinations] - proxyConfigRes *Resource[*pbmesh.ProxyConfiguration] + logger.Info("dataplane sidecar service removed", + "service", pid, + "node", node.ID(), ) - if svc.HasCheck() { - // TODO: needs ownerId - checkRes := &Resource[*pbcatalog.HealthStatus]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.HealthStatusType, - Name: svc.Workload + "-check-0", - Tenancy: tenancy, - }, - }, - Data: &pbcatalog.HealthStatus{ - Type: "external-sync", - Status: pbcatalog.Health_HEALTH_PASSING, - }, - } + return nil +} - healthResList = []*Resource[*pbcatalog.HealthStatus]{checkRes} +func (s *Sprawl) registerCatalogSidecarServiceV1( + cluster *topology.Cluster, + node *topology.Node, + wrk *topology.Workload, +) error { + if !node.IsDataplane() { + panic("called wrong method type") } - - if node.HasPublicAddress() { - workloadRes.Data.Addresses = append(workloadRes.Data.Addresses, - &pbcatalog.WorkloadAddress{Host: node.PublicAddress(), External: true}, - ) + if wrk.DisableServiceMesh { + panic("not valid") } - if !svc.DisableServiceMesh { - destinationsRes = &Resource[*pbmesh.Destinations]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbmesh.DestinationsType, - Name: svc.Workload, - Tenancy: tenancy, - }, - }, - Data: &pbmesh.Destinations{ - Workloads: selector, - }, - } - - for _, u := range svc.Upstreams { - dest := &pbmesh.Destination{ - DestinationRef: &pbresource.Reference{ - Type: pbcatalog.ServiceType, - Name: u.ID.Name, - Tenancy: &pbresource.Tenancy{ - Partition: u.ID.Partition, - Namespace: u.ID.Namespace, - }, - }, - DestinationPort: u.PortName, - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: u.LocalAddress, - Port: uint32(u.LocalPort), - }, - }, - } - destinationsRes.Data.Destinations = append(destinationsRes.Data.Destinations, dest) - } + var ( + client = s.clients[cluster.Name] + logger = s.logger.With("cluster", cluster.Name) + ) - if svc.EnableTransparentProxy { - proxyConfigRes = &Resource[*pbmesh.ProxyConfiguration]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbmesh.ProxyConfigurationType, - Name: svc.Workload, - Tenancy: tenancy, - }, - }, - Data: &pbmesh.ProxyConfiguration{ - Workloads: selector, - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - }, - }, - } + pid, reg := workloadToSidecarCatalogRegistration(cluster, node, wrk) +RETRY: + if _, err := client.Catalog().Register(reg, nil); err != nil { + if isACLNotFound(err) { + time.Sleep(50 * time.Millisecond) + goto RETRY } + return fmt.Errorf("error registering service %s to node %s: %w", wrk.ID, node.ID(), err) } - return &ServiceResources{ - Workload: workloadRes, - HealthStatuses: healthResList, - Destinations: destinationsRes, - WorkloadIdentity: workloadIdentityRes, - ProxyConfiguration: proxyConfigRes, + logger.Debug("dataplane sidecar service created", + "service", pid, + "node", node.ID(), + ) + + return nil +} + +type Resource[V proto.Message] struct { + Resource *pbresource.Resource + Data V +} + +func (r *Resource[V]) Build() (*pbresource.Resource, error) { + anyData, err := anypb.New(r.Data) + if err != nil { + return nil, err } + r.Resource.Data = anyData + return r.Resource, nil } -func serviceToCatalogRegistration( +func workloadToCatalogRegistration( cluster *topology.Cluster, node *topology.Node, - svc *topology.Service, + wrk *topology.Workload, ) *api.CatalogRegistration { - if node.IsV2() { - panic("don't call this") - } reg := &api.CatalogRegistration{ Node: node.PodName(), SkipNodeUpdate: true, Service: &api.AgentService{ Kind: api.ServiceKindTypical, - ID: svc.ID.Name, - Service: svc.ID.Name, - Meta: svc.Meta, - Port: svc.Port, + ID: wrk.ID.Name, + Service: wrk.ID.Name, + Meta: wrk.Meta, + Port: wrk.Port, Address: node.LocalAddress(), }, } - if svc.IsMeshGateway { + if wrk.IsMeshGateway { reg.Service.Kind = api.ServiceKindMeshGateway reg.Service.Proxy = &api.AgentServiceConnectProxyConfig{ Config: map[string]interface{}{ @@ -704,46 +552,46 @@ func serviceToCatalogRegistration( reg.Service.TaggedAddresses = map[string]api.ServiceAddress{ "lan": { Address: node.LocalAddress(), - Port: svc.Port, + Port: wrk.Port, }, "lan_ipv4": { Address: node.LocalAddress(), - Port: svc.Port, + Port: wrk.Port, }, "wan": { Address: node.PublicAddress(), - Port: svc.Port, + Port: wrk.Port, }, "wan_ipv4": { Address: node.PublicAddress(), - Port: svc.Port, + Port: wrk.Port, }, } } if cluster.Enterprise { - reg.Partition = svc.ID.Partition - reg.Service.Namespace = svc.ID.Namespace - reg.Service.Partition = svc.ID.Partition + reg.Partition = wrk.ID.Partition + reg.Service.Namespace = wrk.ID.Namespace + reg.Service.Partition = wrk.ID.Partition } - if svc.HasCheck() { + if wrk.HasCheck() { chk := &api.HealthCheck{ Name: "external sync", // Type: "external-sync", Status: "passing", // TODO - ServiceID: svc.ID.Name, - ServiceName: svc.ID.Name, + ServiceID: wrk.ID.Name, + ServiceName: wrk.ID.Name, Output: "", } if cluster.Enterprise { - chk.Namespace = svc.ID.Namespace - chk.Partition = svc.ID.Partition + chk.Namespace = wrk.ID.Namespace + chk.Partition = wrk.ID.Partition } switch { - case svc.CheckTCP != "": - chk.Definition.TCP = svc.CheckTCP - case svc.CheckHTTP != "": - chk.Definition.HTTP = svc.CheckHTTP + case wrk.CheckTCP != "": + chk.Definition.TCP = wrk.CheckTCP + case wrk.CheckHTTP != "": + chk.Definition.HTTP = wrk.CheckHTTP chk.Definition.Method = "GET" } reg.Checks = append(reg.Checks, chk) @@ -751,15 +599,12 @@ func serviceToCatalogRegistration( return reg } -func serviceToSidecarCatalogRegistration( +func workloadToSidecarCatalogRegistration( cluster *topology.Cluster, node *topology.Node, - svc *topology.Service, -) (topology.ServiceID, *api.CatalogRegistration) { - if node.IsV2() { - panic("don't call this") - } - pid := svc.ID + wrk *topology.Workload, +) (topology.ID, *api.CatalogRegistration) { + pid := wrk.ID pid.Name += "-sidecar-proxy" reg := &api.CatalogRegistration{ Node: node.PodName(), @@ -768,13 +613,13 @@ func serviceToSidecarCatalogRegistration( Kind: api.ServiceKindConnectProxy, ID: pid.Name, Service: pid.Name, - Meta: svc.Meta, - Port: svc.EnvoyPublicListenerPort, + Meta: wrk.Meta, + Port: wrk.EnvoyPublicListenerPort, Address: node.LocalAddress(), Proxy: &api.AgentServiceConnectProxyConfig{ - DestinationServiceName: svc.ID.Name, - DestinationServiceID: svc.ID.Name, - LocalServicePort: svc.Port, + DestinationServiceName: wrk.ID.Name, + DestinationServiceID: wrk.ID.Name, + LocalServicePort: wrk.Port, }, }, Checks: []*api.HealthCheck{{ @@ -784,7 +629,7 @@ func serviceToSidecarCatalogRegistration( ServiceID: pid.Name, ServiceName: pid.Name, Definition: api.HealthCheckDefinition{ - TCP: fmt.Sprintf("%s:%d", node.LocalAddress(), svc.EnvoyPublicListenerPort), + TCP: fmt.Sprintf("%s:%d", node.LocalAddress(), wrk.EnvoyPublicListenerPort), }, Output: "", }}, @@ -805,17 +650,17 @@ func serviceToSidecarCatalogRegistration( reg.Checks[0].Partition = pid.Partition } - for _, u := range svc.Upstreams { + for _, us := range wrk.Upstreams { pu := api.Upstream{ - DestinationName: u.ID.Name, - DestinationPeer: u.Peer, - LocalBindAddress: u.LocalAddress, - LocalBindPort: u.LocalPort, + DestinationName: us.ID.Name, + DestinationPeer: us.Peer, + LocalBindAddress: us.LocalAddress, + LocalBindPort: us.LocalPort, } if cluster.Enterprise { - pu.DestinationNamespace = u.ID.Namespace - if u.Peer == "" { - pu.DestinationPartition = u.ID.Partition + pu.DestinationNamespace = us.ID.Namespace + if us.Peer == "" { + pu.DestinationPartition = us.ID.Partition } } reg.Service.Proxy.Upstreams = append(reg.Service.Proxy.Upstreams, pu) diff --git a/testing/deployer/sprawl/consul.go b/testing/deployer/sprawl/consul.go index 205fb0235f0e..a816cd7480c8 100644 --- a/testing/deployer/sprawl/consul.go +++ b/testing/deployer/sprawl/consul.go @@ -74,7 +74,12 @@ func (s *Sprawl) rejoinServers(cluster *topology.Cluster) error { servers := cluster.ServerNodes() - recoveryToken := s.secrets.ReadGeneric(cluster.Name, secrets.AgentRecovery) + var recoveryToken string + if servers[0].Images.GreaterThanVersion(topology.MinVersionAgentTokenPartition) { + recoveryToken = s.secrets.ReadGeneric(cluster.Name, secrets.AgentRecovery) + } else { + recoveryToken = s.secrets.ReadGeneric(cluster.Name, secrets.BootstrapToken) + } node0, rest := servers[0], servers[1:] client, err := util.ProxyNotPooledAPIClient( diff --git a/testing/deployer/sprawl/details.go b/testing/deployer/sprawl/details.go index a0c6c0c2a51e..f4f91f8d7475 100644 --- a/testing/deployer/sprawl/details.go +++ b/testing/deployer/sprawl/details.go @@ -10,6 +10,11 @@ import ( "strconv" "strings" "text/tabwriter" + "time" + + retry "github.com/avast/retry-go" + + "github.com/hashicorp/consul/api" ) // PrintDetails will dump relevant addressing and naming data to the logger for @@ -22,7 +27,19 @@ func (s *Sprawl) PrintDetails() error { for _, cluster := range s.topology.Clusters { client := s.clients[cluster.Name] - cfg, err := client.Operator().RaftGetConfiguration(nil) + var cfg *api.RaftConfiguration + var err error + err = retry.Do( + func() error { + cfg, err = client.Operator().RaftGetConfiguration(nil) + if err != nil { + return fmt.Errorf("error get raft config: %w", err) + } + return nil + }, + retry.MaxDelay(5*time.Second), + retry.Attempts(15), + ) if err != nil { return fmt.Errorf("could not get raft config for cluster %q: %w", cluster.Name, err) } @@ -59,29 +76,24 @@ func (s *Sprawl) PrintDetails() error { }) } - for _, svc := range node.Services { - if svc.IsMeshGateway { + for _, wrk := range node.Workloads { + if wrk.IsMeshGateway { cd.Apps = append(cd.Apps, appDetail{ Type: "mesh-gateway", Container: node.DockerName(), - ExposedPort: node.ExposedPort(svc.Port), - ExposedEnvoyAdminPort: node.ExposedPort(svc.EnvoyAdminPort), + ExposedPort: node.ExposedPort(wrk.Port), + ExposedEnvoyAdminPort: node.ExposedPort(wrk.EnvoyAdminPort), Addresses: addrs, - Service: svc.ID.String(), + Service: wrk.ID.String(), }) } else { - ports := make(map[string]int) - for name, port := range svc.Ports { - ports[name] = node.ExposedPort(port.Number) - } cd.Apps = append(cd.Apps, appDetail{ Type: "app", Container: node.DockerName(), - ExposedPort: node.ExposedPort(svc.Port), - ExposedPorts: ports, - ExposedEnvoyAdminPort: node.ExposedPort(svc.EnvoyAdminPort), + ExposedPort: node.ExposedPort(wrk.Port), + ExposedEnvoyAdminPort: node.ExposedPort(wrk.EnvoyAdminPort), Addresses: addrs, - Service: svc.ID.String(), + Service: wrk.ID.String(), }) } } @@ -126,17 +138,7 @@ func (s *Sprawl) PrintDetails() error { if d.Type == "server" && d.Container == cluster.Leader { d.Type = "leader" } - var portStr string - if len(d.ExposedPorts) > 0 { - var out []string - for name, exposed := range d.ExposedPorts { - out = append(out, fmt.Sprintf("app:%s=%d", name, exposed)) - } - sort.Strings(out) - portStr = strings.Join(out, " ") - } else { - portStr = "app=" + strconv.Itoa(d.ExposedPort) - } + portStr := "app=" + strconv.Itoa(d.ExposedPort) if d.ExposedEnvoyAdminPort > 0 { portStr += " envoy=" + strconv.Itoa(d.ExposedEnvoyAdminPort) } @@ -175,9 +177,8 @@ type appDetail struct { Type string // server|mesh-gateway|app Container string Addresses []string - ExposedPort int `json:",omitempty"` - ExposedPorts map[string]int `json:",omitempty"` - ExposedEnvoyAdminPort int `json:",omitempty"` + ExposedPort int `json:",omitempty"` + ExposedEnvoyAdminPort int `json:",omitempty"` // just services Service string `json:",omitempty"` } diff --git a/testing/deployer/sprawl/internal/build/docker.go b/testing/deployer/sprawl/internal/build/docker.go index 435fb0b50648..bb24047154a5 100644 --- a/testing/deployer/sprawl/internal/build/docker.go +++ b/testing/deployer/sprawl/internal/build/docker.go @@ -102,6 +102,8 @@ func DockerImages( built := make(map[string]struct{}) for _, c := range t.Clusters { for _, n := range c.Nodes { + const needsTproxy = false // TODO: see if we can bring this back for v1 CDP + joint := n.Images.EnvoyConsulImage() if _, ok := built[joint]; joint != "" && !ok { logger.Info("building envoy+consul image", "image", joint) @@ -145,7 +147,7 @@ func DockerImages( } cdpTproxy := n.Images.LocalDataplaneTProxyImage() - if _, ok := built[cdpTproxy]; cdpTproxy != "" && !ok { + if _, ok := built[cdpTproxy]; cdpTproxy != "" && !ok && needsTproxy { logger.Info("building image", "image", cdpTproxy) logw := logger.Named("docker_dataplane_tproxy").StandardWriter(&hclog.StandardLoggerOptions{ForceLevel: hclog.Debug}) err := run.DockerExecWithStderr(context.TODO(), []string{ diff --git a/testing/deployer/sprawl/internal/secrets/store.go b/testing/deployer/sprawl/internal/secrets/store.go index 85e2741e9fc0..6d3144f3f8d2 100644 --- a/testing/deployer/sprawl/internal/secrets/store.go +++ b/testing/deployer/sprawl/internal/secrets/store.go @@ -37,12 +37,22 @@ func (s *Store) ReadAgentToken(cluster string, nid topology.NodeID) string { return s.read(encode(cluster, "agent", nid.String())) } -func (s *Store) SaveServiceToken(cluster string, sid topology.ServiceID, value string) { - s.save(encode(cluster, "service", sid.String()), value) +// Deprecated: SaveWorkloadToken +func (s *Store) SaveServiceToken(cluster string, wid topology.ID, value string) { + s.SaveWorkloadToken(cluster, wid, value) } -func (s *Store) ReadServiceToken(cluster string, sid topology.ServiceID) string { - return s.read(encode(cluster, "service", sid.String())) +func (s *Store) SaveWorkloadToken(cluster string, wid topology.ID, value string) { + s.save(encode(cluster, "workload", wid.String()), value) +} + +// Deprecated: ReadWorkloadToken +func (s *Store) ReadServiceToken(cluster string, wid topology.ID) string { + return s.ReadWorkloadToken(cluster, wid) +} + +func (s *Store) ReadWorkloadToken(cluster string, wid topology.ID) string { + return s.read(encode(cluster, "workload", wid.String())) } func (s *Store) save(key, value string) { diff --git a/testing/deployer/sprawl/internal/tfgen/agent.go b/testing/deployer/sprawl/internal/tfgen/agent.go index ee77c09a58bc..efd8589525de 100644 --- a/testing/deployer/sprawl/internal/tfgen/agent.go +++ b/testing/deployer/sprawl/internal/tfgen/agent.go @@ -13,7 +13,7 @@ import ( "github.com/hashicorp/consul/testing/deployer/topology" ) -func (g *Generator) generateAgentHCL(node *topology.Node, enableV2 bool) string { +func (g *Generator) generateAgentHCL(node *topology.Node) string { if !node.IsAgent() { panic("generateAgentHCL only applies to agents") } @@ -25,6 +25,12 @@ func (g *Generator) generateAgentHCL(node *topology.Node, enableV2 bool) string var b HCLBuilder + // We first write ExtraConfig since it could be overwritten by specific + // configurations below + if node.ExtraConfig != "" { + b.format(node.ExtraConfig) + } + b.add("server", node.IsServer()) b.add("bind_addr", "0.0.0.0") b.add("client_addr", "0.0.0.0") @@ -35,13 +41,10 @@ func (g *Generator) generateAgentHCL(node *topology.Node, enableV2 bool) string b.add("enable_debug", true) b.add("use_streaming_backend", true) - if enableV2 { - b.addSlice("experiments", []string{"resource-apis"}) - } - // speed up leaves b.addBlock("performance", func() { b.add("leave_drain_time", "50ms") + b.add("raft_multiplier", 1) }) b.add("primary_datacenter", node.Datacenter) @@ -53,12 +56,24 @@ func (g *Generator) generateAgentHCL(node *topology.Node, enableV2 bool) string b.add("retry_interval", "1s") // } - if node.IsServer() { - b.addBlock("peering", func() { - b.add("enabled", true) + if node.Segment != nil { + if node.Kind != topology.NodeKindClient { + panic("segment only applies to client agent") + } + b.add("segment", node.Segment.Name) + b.addSlice("retry_join", []string{ + fmt.Sprintf("server.%s-consulcluster.lan:%d", node.Cluster, node.Segment.Port), }) } + if node.Images.GreaterThanVersion(topology.MinVersionPeering) { + if node.IsServer() { + b.addBlock("peering", func() { + b.add("enabled", true) + }) + } + } + b.addBlock("ui_config", func() { b.add("enabled", true) }) @@ -68,7 +83,9 @@ func (g *Generator) generateAgentHCL(node *topology.Node, enableV2 bool) string b.add("prometheus_retention_time", "168h") }) - b.add("encrypt", g.sec.ReadGeneric(node.Cluster, secrets.GossipKey)) + if !cluster.DisableGossipEncryption { + b.add("encrypt", g.sec.ReadGeneric(node.Cluster, secrets.GossipKey)) + } { var ( @@ -78,41 +95,45 @@ func (g *Generator) generateAgentHCL(node *topology.Node, enableV2 bool) string certKey = root + "/" + node.TLSCertPrefix + "-key.pem" ) - b.addBlock("tls", func() { - b.addBlock("internal_rpc", func() { - b.add("ca_file", caFile) - b.add("cert_file", certFile) - b.add("key_file", certKey) - b.add("verify_incoming", true) - b.add("verify_server_hostname", true) - b.add("verify_outgoing", true) - }) - // if cfg.EncryptionTLSAPI { - // b.addBlock("https", func() { - // b.add("ca_file", caFile) - // b.add("cert_file", certFile) - // b.add("key_file", certKey) - // // b.add("verify_incoming", true) - // }) - // } - if node.IsServer() { - b.addBlock("grpc", func() { + if node.Images.GreaterThanVersion(topology.MinVersionTLS) { + b.addBlock("tls", func() { + b.addBlock("internal_rpc", func() { b.add("ca_file", caFile) b.add("cert_file", certFile) b.add("key_file", certKey) - // b.add("verify_incoming", true) + b.add("verify_incoming", true) + b.add("verify_server_hostname", true) + b.add("verify_outgoing", true) }) - } - }) + // if cfg.EncryptionTLSAPI { + // b.addBlock("https", func() { + // b.add("ca_file", caFile) + // b.add("cert_file", certFile) + // b.add("key_file", certKey) + // // b.add("verify_incoming", true) + // }) + // } + if node.IsServer() { + b.addBlock("grpc", func() { + b.add("ca_file", caFile) + b.add("cert_file", certFile) + b.add("key_file", certKey) + // b.add("verify_incoming", true) + }) + } + }) + } } b.addBlock("ports", func() { - if node.IsServer() { - b.add("grpc_tls", 8503) - b.add("grpc", -1) - } else { - b.add("grpc", 8502) - b.add("grpc_tls", -1) + if node.Images.GreaterThanVersion(topology.MinVersionPeering) { + if node.IsServer() { + b.add("grpc_tls", 8503) + b.add("grpc", -1) + } else { + b.add("grpc", 8502) + b.add("grpc_tls", -1) + } } b.add("http", 8500) b.add("dns", 8600) @@ -125,17 +146,29 @@ func (g *Generator) generateAgentHCL(node *topology.Node, enableV2 bool) string b.add("default_policy", "deny") b.add("down_policy", "extend-cache") b.add("enable_token_persistence", true) - b.addBlock("tokens", func() { - if node.IsServer() { - b.add("initial_management", g.sec.ReadGeneric(node.Cluster, secrets.BootstrapToken)) - } - b.add("agent_recovery", g.sec.ReadGeneric(node.Cluster, secrets.AgentRecovery)) - b.add("agent", g.sec.ReadAgentToken(node.Cluster, node.ID())) - }) + + if node.Images.GreaterThanVersion(topology.MinVersionAgentTokenPartition) { + b.addBlock("tokens", func() { + if node.IsServer() { + b.add("initial_management", g.sec.ReadGeneric(node.Cluster, secrets.BootstrapToken)) + } + b.add("agent_recovery", g.sec.ReadGeneric(node.Cluster, secrets.AgentRecovery)) + b.add("agent", g.sec.ReadAgentToken(node.Cluster, node.ID())) + }) + } else { + b.addBlock("tokens", func() { + if node.IsServer() { + b.add("master", g.sec.ReadGeneric(node.Cluster, secrets.BootstrapToken)) + } + }) + } }) if node.IsServer() { - b.add("bootstrap_expect", len(cluster.ServerNodes())) + // bootstrap_expect is omitted if this node is a new server + if !node.IsNewServer { + b.add("bootstrap_expect", len(cluster.ServerNodes())) + } // b.add("translate_wan_addrs", true) b.addBlock("rpc", func() { b.add("enable_streaming", true) @@ -165,8 +198,38 @@ func (g *Generator) generateAgentHCL(node *topology.Node, enableV2 bool) string b.add("enabled", true) }) + // b.addBlock("autopilot", func() { + // b.add("upgrade_version_tag", "build") + // }) + + if node.AutopilotConfig != nil { + b.addBlock("autopilot", func() { + for k, v := range node.AutopilotConfig { + b.add(k, v) + } + }) + } + + if node.Meta != nil { + b.addBlock("node_meta", func() { + for k, v := range node.Meta { + b.add(k, v) + } + }) + } + + if cluster.Segments != nil { + b.format("segments = [") + for name, port := range cluster.Segments { + b.format("{") + b.add("name", name) + b.add("port", port) + b.format("},") + } + b.format("]") + } } else { - if cluster.Enterprise { + if cluster.Enterprise && node.Images.GreaterThanVersion(topology.MinVersionAgentTokenPartition) { b.add("partition", node.Partition) } } diff --git a/testing/deployer/sprawl/internal/tfgen/dns.go b/testing/deployer/sprawl/internal/tfgen/dns.go index 9b03693c8311..73ea5f388d28 100644 --- a/testing/deployer/sprawl/internal/tfgen/dns.go +++ b/testing/deployer/sprawl/internal/tfgen/dns.go @@ -8,11 +8,8 @@ import ( "fmt" "os" "path/filepath" - "sort" "strings" - "golang.org/x/exp/maps" - "github.com/hashicorp/consul/testing/deployer/topology" "github.com/hashicorp/consul/testing/deployer/util" ) @@ -66,22 +63,6 @@ func (g *Generator) writeCoreDNSFiles(net *topology.Network, dnsIPAddress string } } - // Until Consul DNS understands v2, simulate it. - // - // NOTE: this DNS is not quite what consul normally does. It's simpler - // to simulate this format here. - virtualNames := make(map[string][]string) - for id, svcData := range cluster.Services { - if len(svcData.VirtualIps) == 0 { - continue - } - vips := svcData.VirtualIps - - // ----.virtual. - name := fmt.Sprintf("%s--%s--%s", id.Name, id.Namespace, id.Partition) - virtualNames[name] = vips - } - var ( clusterDNSName = cluster.Name + "-consulcluster.lan" virtualDNSName = "virtual.consul" @@ -132,7 +113,6 @@ func (g *Generator) writeCoreDNSFiles(net *topology.Network, dnsIPAddress string generateCoreDNSVirtualZoneFile( dnsIPAddress, virtualDNSName, - virtualNames, ), virtualZonefilePath, 0644, @@ -230,7 +210,6 @@ server IN A %s ; Consul server func generateCoreDNSVirtualZoneFile( dnsIPAddress string, virtualDNSName string, - nameToAddr map[string][]string, ) []byte { var buf bytes.Buffer buf.WriteString(fmt.Sprintf(` @@ -247,17 +226,5 @@ $ORIGIN %[1]s. ns IN A %[2]s ; self `, virtualDNSName, dnsIPAddress)) - names := maps.Keys(nameToAddr) - sort.Strings(names) - - for _, name := range names { - vips := nameToAddr[name] - for _, vip := range vips { - buf.WriteString(fmt.Sprintf(` -%s IN A %s ; Consul server -`, name, vip)) - } - } - return buf.Bytes() } diff --git a/testing/deployer/sprawl/internal/tfgen/gen.go b/testing/deployer/sprawl/internal/tfgen/gen.go index 0f38714b0c99..0f5f74df2811 100644 --- a/testing/deployer/sprawl/internal/tfgen/gen.go +++ b/testing/deployer/sprawl/internal/tfgen/gen.go @@ -251,7 +251,7 @@ func (g *Generator) Generate(step Step) error { addVolume(c.TLSVolumeName) } - addImage("pause", "registry.k8s.io/pause:3.3") + addImage("pause", "docker.mirror.hashicorp.services/hashiderek/pause") if step.StartServers() { for _, c := range g.topology.SortedClusters() { @@ -262,14 +262,13 @@ func (g *Generator) Generate(step Step) error { addImage("", node.Images.Consul) addImage("", node.Images.EnvoyConsulImage()) addImage("", node.Images.LocalDataplaneImage()) - addImage("", node.Images.LocalDataplaneTProxyImage()) if node.IsAgent() { addVolume(node.DockerName()) } - for _, svc := range node.Services { - addImage("", svc.Image) + for _, wrk := range node.Workloads { + addImage("", wrk.Image) } myContainers, err := g.generateNodeContainers(step, c, node) diff --git a/testing/deployer/sprawl/internal/tfgen/nodes.go b/testing/deployer/sprawl/internal/tfgen/nodes.go index 4934482d7240..06f37453a491 100644 --- a/testing/deployer/sprawl/internal/tfgen/nodes.go +++ b/testing/deployer/sprawl/internal/tfgen/nodes.go @@ -67,57 +67,57 @@ func (g *Generator) generateNodeContainers( }{ terraformPod: pod, ImageResource: DockerImageResourceName(node.Images.Consul), - HCL: g.generateAgentHCL(node, cluster.EnableV2 && node.IsServer()), + HCL: g.generateAgentHCL(node), EnterpriseLicense: g.license, })) } } - svcContainers := []Resource{} - for _, svc := range node.SortedServices() { - token := g.sec.ReadServiceToken(node.Cluster, svc.ID) + wrkContainers := []Resource{} + for _, wrk := range node.SortedWorkloads() { + token := g.sec.ReadWorkloadToken(node.Cluster, wrk.ID) switch { - case svc.IsMeshGateway && !node.IsDataplane(): - svcContainers = append(svcContainers, Eval(tfMeshGatewayT, struct { + case wrk.IsMeshGateway && !node.IsDataplane(): + wrkContainers = append(wrkContainers, Eval(tfMeshGatewayT, struct { terraformPod ImageResource string Enterprise bool - Service *topology.Service + Workload *topology.Workload Token string }{ terraformPod: pod, ImageResource: DockerImageResourceName(node.Images.EnvoyConsulImage()), Enterprise: cluster.Enterprise, - Service: svc, + Workload: wrk, Token: token, })) - case svc.IsMeshGateway && node.IsDataplane(): - svcContainers = append(svcContainers, Eval(tfMeshGatewayDataplaneT, &struct { + case wrk.IsMeshGateway && node.IsDataplane(): + wrkContainers = append(wrkContainers, Eval(tfMeshGatewayDataplaneT, &struct { terraformPod ImageResource string Enterprise bool - Service *topology.Service + Workload *topology.Workload Token string }{ terraformPod: pod, ImageResource: DockerImageResourceName(node.Images.LocalDataplaneImage()), Enterprise: cluster.Enterprise, - Service: svc, + Workload: wrk, Token: token, })) - case !svc.IsMeshGateway: - svcContainers = append(svcContainers, Eval(tfAppT, struct { + case !wrk.IsMeshGateway: + wrkContainers = append(wrkContainers, Eval(tfAppT, struct { terraformPod ImageResource string - Service *topology.Service + Workload *topology.Workload }{ terraformPod: pod, - ImageResource: DockerImageResourceName(svc.Image), - Service: svc, + ImageResource: DockerImageResourceName(wrk.Image), + Workload: wrk, })) - if svc.DisableServiceMesh { + if wrk.DisableServiceMesh { break } @@ -125,31 +125,27 @@ func (g *Generator) generateNodeContainers( var img string if node.IsDataplane() { tmpl = tfAppDataplaneT - if svc.EnableTransparentProxy { - img = DockerImageResourceName(node.Images.LocalDataplaneTProxyImage()) - } else { - img = DockerImageResourceName(node.Images.LocalDataplaneImage()) - } + img = DockerImageResourceName(node.Images.LocalDataplaneImage()) } else { img = DockerImageResourceName(node.Images.EnvoyConsulImage()) } - svcContainers = append(svcContainers, Eval(tmpl, struct { + wrkContainers = append(wrkContainers, Eval(tmpl, struct { terraformPod ImageResource string - Service *topology.Service + Workload *topology.Workload Token string Enterprise bool }{ terraformPod: pod, ImageResource: img, - Service: svc, + Workload: wrk, Token: token, Enterprise: cluster.Enterprise, })) } if step.StartServices() { - containers = append(containers, svcContainers...) + containers = append(containers, wrkContainers...) } } diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-app-dataplane.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-app-dataplane.tf.tmpl index f706b6ad2d77..9a65c3426a30 100644 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-app-dataplane.tf.tmpl +++ b/testing/deployer/sprawl/internal/tfgen/templates/container-app-dataplane.tf.tmpl @@ -1,5 +1,5 @@ -resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}-sidecar" { - name = "{{.Node.DockerName}}-{{.Service.ID.TFString}}-sidecar" +resource "docker_container" "{{.Node.DockerName}}-{{.Workload.ID.TFString}}-sidecar" { + name = "{{.Node.DockerName}}-{{.Workload.ID.TFString}}-sidecar" network_mode = "container:${docker_container.{{.PodName}}.id}" image = docker_image.{{.ImageResource}}.image_id restart = "on-failure" @@ -17,28 +17,13 @@ resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}-sidec read_only = true } -{{ if .Service.EnableTransparentProxy }} - capabilities { - add = ["NET_ADMIN"] - } - entrypoint = [ "/bin/tproxy-startup.sh" ] -{{ end }} - env = [ "DP_CONSUL_ADDRESSES=server.{{.Node.Cluster}}-consulcluster.lan", -{{ if .Node.IsV2 }} - "DP_PROXY_ID={{.Service.Workload}}", -{{ if .Enterprise }} - "DP_PROXY_NAMESPACE={{.Service.ID.Namespace}}", - "DP_PROXY_PARTITION={{.Service.ID.Partition}}", -{{ end }} -{{ else }} "DP_SERVICE_NODE_NAME={{.Node.PodName}}", - "DP_PROXY_SERVICE_ID={{.Service.ID.Name}}-sidecar-proxy", + "DP_PROXY_SERVICE_ID={{.Workload.ID.Name}}-sidecar-proxy", {{ if .Enterprise }} - "DP_SERVICE_NAMESPACE={{.Service.ID.Namespace}}", - "DP_SERVICE_PARTITION={{.Service.ID.Partition}}", -{{ end }} + "DP_SERVICE_NAMESPACE={{.Workload.ID.Namespace}}", + "DP_SERVICE_PARTITION={{.Workload.ID.Partition}}", {{ end }} {{ if .Token }} @@ -46,10 +31,6 @@ resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}-sidec "DP_CREDENTIAL_STATIC_TOKEN={{.Token}}", {{ end }} -{{ if .Service.EnableTransparentProxy }} - "REDIRECT_TRAFFIC_ARGS=-exclude-inbound-port=19000", -{{ end }} - // for demo purposes "DP_ENVOY_ADMIN_BIND_ADDRESS=0.0.0.0", "DP_ENVOY_ADMIN_BIND_PORT=19000", diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-app-sidecar.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-app-sidecar.tf.tmpl index c368d161043c..6c9ef47c2813 100644 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-app-sidecar.tf.tmpl +++ b/testing/deployer/sprawl/internal/tfgen/templates/container-app-sidecar.tf.tmpl @@ -1,5 +1,5 @@ -resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}-sidecar" { - name = "{{.Node.DockerName}}-{{.Service.ID.TFString}}-sidecar" +resource "docker_container" "{{.Node.DockerName}}-{{.Workload.ID.TFString}}-sidecar" { + name = "{{.Node.DockerName}}-{{.Workload.ID.TFString}}-sidecar" network_mode = "container:${docker_container.{{.PodName}}.id}" image = docker_image.{{.ImageResource}}.image_id restart = "on-failure" @@ -19,13 +19,13 @@ resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}-sidec command = [ "consul", "connect", "envoy", - "-sidecar-for={{.Service.ID.Name}}", + "-sidecar-for={{.Workload.ID.Name}}", "-grpc-addr=http://127.0.0.1:8502", // for demo purposes (TODO: huh?) - "-admin-bind=0.0.0.0:{{.Service.EnvoyAdminPort}}", + "-admin-bind=0.0.0.0:{{.Workload.EnvoyAdminPort}}", {{if .Enterprise}} - "-partition={{.Service.ID.Partition}}", - "-namespace={{.Service.ID.Namespace}}", + "-partition={{.Workload.ID.Partition}}", + "-namespace={{.Workload.ID.Namespace}}", {{end}} {{if .Token }} "-token={{.Token}}", diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-app.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-app.tf.tmpl index 6cdd7705ea9f..51df4fa00597 100644 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-app.tf.tmpl +++ b/testing/deployer/sprawl/internal/tfgen/templates/container-app.tf.tmpl @@ -1,5 +1,5 @@ -resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}" { - name = "{{.Node.DockerName}}-{{.Service.ID.TFString}}" +resource "docker_container" "{{.Node.DockerName}}-{{.Workload.ID.TFString}}" { + name = "{{.Node.DockerName}}-{{.Workload.ID.TFString}}" network_mode = "container:${docker_container.{{.PodName}}.id}" image = docker_image.{{.ImageResource}}.image_id restart = "on-failure" @@ -12,13 +12,13 @@ resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}" { {{- end }} env = [ -{{- range .Service.Env }} +{{- range .Workload.Env }} "{{.}}", {{- end}} ] command = [ -{{- range .Service.Command }} +{{- range .Workload.Command }} "{{.}}", {{- end }} ] diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-coredns.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-coredns.tf.tmpl index 97c0d7011d3d..3dabd7d50e61 100644 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-coredns.tf.tmpl +++ b/testing/deployer/sprawl/internal/tfgen/templates/container-coredns.tf.tmpl @@ -4,6 +4,7 @@ resource "docker_container" "{{.DockerNetworkName}}-coredns" { restart = "always" dns = ["8.8.8.8"] + network_mode = "bridge" networks_advanced { name = docker_network.{{.DockerNetworkName}}.name ipv4_address = "{{.IPAddress}}" diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-mgw-dataplane.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-mgw-dataplane.tf.tmpl index 4aac9b5946f0..6dac0fd3ec9c 100644 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-mgw-dataplane.tf.tmpl +++ b/testing/deployer/sprawl/internal/tfgen/templates/container-mgw-dataplane.tf.tmpl @@ -1,5 +1,5 @@ -resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}" { - name = "{{.Node.DockerName}}-{{.Service.ID.TFString}}" +resource "docker_container" "{{.Node.DockerName}}-{{.Workload.ID.TFString}}" { + name = "{{.Node.DockerName}}-{{.Workload.ID.TFString}}" network_mode = "container:${docker_container.{{.PodName}}.id}" image = docker_image.{{.ImageResource}}.image_id restart = "on-failure" @@ -20,10 +20,10 @@ resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}" { env = [ "DP_CONSUL_ADDRESSES=server.{{.Node.Cluster}}-consulcluster.lan", "DP_SERVICE_NODE_NAME={{.Node.PodName}}", - "DP_PROXY_SERVICE_ID={{.Service.ID.Name}}", + "DP_PROXY_SERVICE_ID={{.Workload.ID.Name}}", {{ if .Enterprise }} - "DP_SERVICE_NAMESPACE={{.Service.ID.Namespace}}", - "DP_SERVICE_PARTITION={{.Service.ID.Partition}}", + "DP_SERVICE_NAMESPACE={{.Workload.ID.Namespace}}", + "DP_SERVICE_PARTITION={{.Workload.ID.Partition}}", {{ end }} {{ if .Token }} "DP_CREDENTIAL_TYPE=static", diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-mgw.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-mgw.tf.tmpl index 68ccbbd0f1a7..1892dfa047f0 100644 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-mgw.tf.tmpl +++ b/testing/deployer/sprawl/internal/tfgen/templates/container-mgw.tf.tmpl @@ -1,5 +1,5 @@ -resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}" { - name = "{{.Node.DockerName}}-{{.Service.ID.TFString}}" +resource "docker_container" "{{.Node.DockerName}}-{{.Workload.ID.TFString}}" { + name = "{{.Node.DockerName}}-{{.Workload.ID.TFString}}" network_mode = "container:${docker_container.{{.PodName}}.id}" image = docker_image.{{.ImageResource}}.image_id restart = "on-failure" @@ -21,13 +21,13 @@ resource "docker_container" "{{.Node.DockerName}}-{{.Service.ID.TFString}}" { "consul", "connect", "envoy", "-register", "-mesh-gateway", - "-address={{`{{ GetInterfaceIP \"eth0\" }}`}}:{{.Service.Port}}", - "-wan-address={{`{{ GetInterfaceIP \"eth1\" }}`}}:{{.Service.Port}}", + "-address={{`{{ GetInterfaceIP \"eth0\" }}`}}:{{.Workload.Port}}", + "-wan-address={{`{{ GetInterfaceIP \"eth1\" }}`}}:{{.Workload.Port}}", "-grpc-addr=http://127.0.0.1:8502", // for demo purposes (TODO: huh?) - "-admin-bind=0.0.0.0:{{.Service.EnvoyAdminPort}}", + "-admin-bind=0.0.0.0:{{.Workload.EnvoyAdminPort}}", {{ if .Enterprise }} - "-partition={{.Service.ID.Partition}}", + "-partition={{.Workload.ID.Partition}}", {{end}} {{ if .Token }} "-token={{.Token}}", diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-pause.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-pause.tf.tmpl index ef537f03522a..37a1370c6371 100644 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-pause.tf.tmpl +++ b/testing/deployer/sprawl/internal/tfgen/templates/container-pause.tf.tmpl @@ -23,6 +23,7 @@ ports { } {{- end }} +network_mode = "bridge" {{- range .Node.Addresses }} networks_advanced { name = docker_network.{{.DockerNetworkName}}.name diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-proxy.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-proxy.tf.tmpl index f4d7fe1d9439..64e09743e159 100644 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-proxy.tf.tmpl +++ b/testing/deployer/sprawl/internal/tfgen/templates/container-proxy.tf.tmpl @@ -8,6 +8,7 @@ resource "docker_container" "{{.DockerNetworkName}}-forwardproxy" { internal = {{.InternalPort}} } + network_mode = "bridge" networks_advanced { name = docker_network.{{.DockerNetworkName}}.name ipv4_address = "{{.IPAddress}}" diff --git a/testing/deployer/sprawl/network_area_ce.go b/testing/deployer/sprawl/network_area_ce.go new file mode 100644 index 000000000000..3b7a182a54bf --- /dev/null +++ b/testing/deployer/sprawl/network_area_ce.go @@ -0,0 +1,14 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +//go:build !consulent + +package sprawl + +func (s *Sprawl) initNetworkAreas() error { + return nil +} + +func (s *Sprawl) waitForNetworkAreaEstablishment() error { + return nil +} diff --git a/testing/deployer/sprawl/peering.go b/testing/deployer/sprawl/peering.go index 96791a9ae90d..375d424197b7 100644 --- a/testing/deployer/sprawl/peering.go +++ b/testing/deployer/sprawl/peering.go @@ -190,12 +190,12 @@ func (s *Sprawl) awaitMeshGateways() { startTime := time.Now() s.logger.Info("awaiting mesh gateways") // TODO: maybe a better way to do this - mgws := []*topology.Service{} + mgws := []*topology.Workload{} for _, clu := range s.topology.Clusters { for _, node := range clu.Nodes { - for _, svc := range node.Services { - if svc.IsMeshGateway { - mgws = append(mgws, svc) + for _, wrk := range node.Workloads { + if wrk.IsMeshGateway { + mgws = append(mgws, wrk) } } } diff --git a/testing/deployer/sprawl/sprawl.go b/testing/deployer/sprawl/sprawl.go index 2cf2c9371acd..67be4f2f2c05 100644 --- a/testing/deployer/sprawl/sprawl.go +++ b/testing/deployer/sprawl/sprawl.go @@ -7,6 +7,7 @@ import ( "bufio" "bytes" "context" + "crypto/rand" "fmt" "io" "net/http" @@ -15,13 +16,15 @@ import ( "strings" "time" - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/go-hclog" - "github.com/hashicorp/go-multierror" + retry "github.com/avast/retry-go" "github.com/mitchellh/copystructure" "google.golang.org/grpc" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-multierror" + + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/testing/deployer/sprawl/internal/runner" "github.com/hashicorp/consul/testing/deployer/sprawl/internal/secrets" "github.com/hashicorp/consul/testing/deployer/sprawl/internal/tfgen" @@ -52,6 +55,11 @@ type Sprawl struct { grpcConnCancel map[string]func() // one per cluster (when v2 enabled) } +const ( + UpgradeTypeStandard = "standard" + UpgradeTypeAutopilot = "autopilot" +) + // Topology allows access to the topology that defines the resources. Do not // write to any of these fields. func (s *Sprawl) Topology() *topology.Topology { @@ -92,6 +100,19 @@ func (s *Sprawl) HTTPClientForCluster(clusterName string) (*http.Client, error) return &http.Client{Transport: transport}, nil } +// LocalAddressForNode returns the local address for the given node in the cluster +func (s *Sprawl) LocalAddressForNode(clusterName string, nid topology.NodeID) (string, error) { + cluster, ok := s.topology.Clusters[clusterName] + if !ok { + return "", fmt.Errorf("no such cluster: %s", clusterName) + } + node := cluster.NodeByID(nid) + if !node.IsAgent() { + return "", fmt.Errorf("node is not an agent") + } + return node.LocalAddress(), nil +} + // APIClientForNode gets a pooled api.Client connected to the agent running on // the provided node. // @@ -130,7 +151,7 @@ func (s *Sprawl) APIClientForNode(clusterName string, nid topology.NodeID, token func (s *Sprawl) APIClientForCluster(clusterName, token string) (*api.Client, error) { clu := s.topology.Clusters[clusterName] // TODO: this always goes to the first client, but we might want to balance this - firstAgent := clu.FirstClient() + firstAgent := clu.FirstClient("") if firstAgent == nil { firstAgent = clu.FirstServer() } @@ -222,12 +243,193 @@ func Launch( func (s *Sprawl) Relaunch( cfg *topology.Config, ) error { - return s.RelaunchWithPhase(cfg, "") + return s.RelaunchWithPhase(cfg, LaunchPhaseRegular) } +// Upgrade upgrades the cluster to the targetImages version +// Parameters: +// - clusterName: the cluster to upgrade +// - upgradeType: the type of upgrade, standard or autopilot +// - targetImages: the target version to upgrade to +// - newServersInTopology: the number of new servers to add to the topology for autopilot upgrade only +// - validationFunc: the validation function to run during upgrade +func (s *Sprawl) Upgrade( + cfg *topology.Config, + clusterName string, + upgradeType string, + targetImages topology.Images, + newServersInTopology []int, + validationFunc func() error, +) error { + cluster := cfg.Cluster(clusterName) + if cluster == nil { + return fmt.Errorf("cluster %s not found in topology", clusterName) + } + + leader, err := s.Leader(cluster.Name) + if err != nil { + return fmt.Errorf("error get leader: %w", err) + } + s.logger.Info("Upgrade cluster", "cluster", cluster.Name, "type", upgradeType, "leader", leader.Name) + + switch upgradeType { + case UpgradeTypeAutopilot: + err = s.autopilotUpgrade(cfg, cluster, newServersInTopology, validationFunc) + case UpgradeTypeStandard: + err = s.standardUpgrade(cluster, targetImages, validationFunc) + default: + err = fmt.Errorf("upgrade type unsupported %s", upgradeType) + } + if err != nil { + return fmt.Errorf("error upgrading cluster: %w", err) + } + + s.logger.Info("After upgrade", "server_nodes", cluster.ServerNodes()) + return nil +} + +// standardUpgrade upgrades server agents in the cluster to the targetImages +// individually +func (s *Sprawl) standardUpgrade(cluster *topology.Cluster, + targetImages topology.Images, validationFunc func() error) error { + upgradeFn := func(nodeID topology.NodeID) error { + cfgUpgrade := s.Config() + clusterCopy := cfgUpgrade.Cluster(cluster.Name) + + // update the server node's image + node := clusterCopy.NodeByID(nodeID) + node.Images = targetImages + s.logger.Info("Upgrading", "node", nodeID.Name, "to_version", node.Images) + err := s.RelaunchWithPhase(cfgUpgrade, LaunchPhaseUpgrade) + if err != nil { + return fmt.Errorf("error relaunch for upgrade: %w", err) + } + s.logger.Info("Relaunch completed", "node", node.Name) + return nil + } + + s.logger.Info("Upgrade to", "version", targetImages) + + // upgrade servers one at a time + for _, node := range cluster.Nodes { + if node.Kind != topology.NodeKindServer { + s.logger.Info("Skip non-server node", "node", node.Name) + continue + } + if err := upgradeFn(node.ID()); err != nil { + return fmt.Errorf("error upgrading node %s: %w", node.Name, err) + } + + // run the validation function after upgrading each server agent + if validationFunc != nil { + if err := validationFunc(); err != nil { + return fmt.Errorf("error validating cluster: %w", err) + } + } + } + + // upgrade client agents one at a time + for _, node := range cluster.Nodes { + if node.Kind != topology.NodeKindClient { + s.logger.Info("Skip non-client node", "node", node.Name) + continue + } + if err := upgradeFn(node.ID()); err != nil { + return fmt.Errorf("error upgrading node %s: %w", node.Name, err) + } + + // run the validation function after upgrading each client agent + if validationFunc != nil { + if err := validationFunc(); err != nil { + return fmt.Errorf("error validating cluster: %w", err) + } + } + } + + return nil +} + +// autopilotUpgrade upgrades server agents by joining new servers with +// higher version. After upgrade completes, the number of server agents +// are doubled +func (s *Sprawl) autopilotUpgrade(cfg *topology.Config, cluster *topology.Cluster, newServersInTopology []int, validationFunc func() error) error { + leader, err := s.Leader(cluster.Name) + if err != nil { + return fmt.Errorf("error get leader: %w", err) + } + + // sanity check for autopilot upgrade + if len(newServersInTopology) < len(cluster.ServerNodes()) { + return fmt.Errorf("insufficient new nodes for autopilot upgrade, expect %d, got %d", + len(cluster.ServerNodes()), len(newServersInTopology)) + } + + for _, nodeIdx := range newServersInTopology { + node := cluster.Nodes[nodeIdx] + if node.Kind != topology.NodeKindServer { + return fmt.Errorf("node %s kind is not server", node.Name) + } + + if !node.Disabled { + return fmt.Errorf("node %s is already enabled", node.Name) + } + + node.Disabled = false + node.IsNewServer = true + + s.logger.Info("Joining new server", "node", node.Name) + } + + err = s.RelaunchWithPhase(cfg, LaunchPhaseUpgrade) + if err != nil { + return fmt.Errorf("error relaunch for upgrade: %w", err) + } + s.logger.Info("Relaunch completed for autopilot upgrade") + + // Verify leader is transferred - if upgrade type is autopilot + s.logger.Info("Waiting for leader transfer") + time.Sleep(20 * time.Second) + err = retry.Do( + func() error { + newLeader, err := s.Leader(cluster.Name) + if err != nil { + return fmt.Errorf("error get new leader: %w", err) + } + s.logger.Info("New leader", "addr", newLeader) + + if newLeader.Name == leader.Name { + return fmt.Errorf("waiting for leader transfer") + } + + return nil + }, + retry.MaxDelay(5*time.Second), + retry.Attempts(20), + ) + if err != nil { + return fmt.Errorf("Leader transfer failed: %w", err) + } + + // Nodes joined the cluster, so we can set all new servers to false + for _, node := range cluster.Nodes { + node.IsNewServer = false + } + + // Run the validation code + if validationFunc != nil { + if err := validationFunc(); err != nil { + return fmt.Errorf("error validating cluster: %w", err) + } + } + + return nil +} + +// RelaunchWithPhase relaunch the toplogy with the given phase +// and wait for the cluster to be ready (i.e, leadership is established) func (s *Sprawl) RelaunchWithPhase( cfg *topology.Config, - phase string, + launchPhase LaunchPhase, ) error { // Copy this BEFORE compiling so we capture the original definition, without denorms. var err error @@ -236,9 +438,7 @@ func (s *Sprawl) RelaunchWithPhase( return err } - if phase != "" { - s.logger = s.launchLogger.Named(phase) - } + s.logger = s.launchLogger.Named(launchPhase.String()) newTopology, err := topology.Recompile(s.logger.Named("recompile"), cfg, s.topology) if err != nil { @@ -250,7 +450,7 @@ func (s *Sprawl) RelaunchWithPhase( s.logger.Debug("compiled replacement topology", "ct", jd(s.topology)) // TODO start := time.Now() - if err := s.relaunch(); err != nil { + if err := s.relaunch(launchPhase); err != nil { return err } s.logger.Info("topology is ready for use", "elapsed", time.Since(start)) @@ -262,8 +462,8 @@ func (s *Sprawl) RelaunchWithPhase( return nil } -// SnapshotSave saves a snapshot of a cluster and restore with the snapshot -func (s *Sprawl) SnapshotSave(clusterName string) error { +// SnapshotSaveAndRestore saves a snapshot of a cluster and then restores the snapshot +func (s *Sprawl) SnapshotSaveAndRestore(clusterName string) error { cluster, ok := s.topology.Clusters[clusterName] if !ok { return fmt.Errorf("no such cluster: %s", clusterName) @@ -288,6 +488,36 @@ func (s *Sprawl) SnapshotSave(clusterName string) error { return nil } +func (s *Sprawl) GetKV(cluster string, key string, queryOpts *api.QueryOptions) ([]byte, error) { + client := s.clients[cluster] + kvClient := client.KV() + + data, _, err := kvClient.Get(key, queryOpts) + if err != nil { + return nil, fmt.Errorf("error getting key: %w", err) + } + return data.Value, nil +} + +func (s *Sprawl) LoadKVDataToCluster(cluster string, numberOfKeys int, writeOpts *api.WriteOptions) error { + client := s.clients[cluster] + kvClient := client.KV() + + for i := 0; i <= numberOfKeys; i++ { + p := &api.KVPair{ + Key: fmt.Sprintf("key-%d", i), + } + token := make([]byte, 131072) // 128K size of value + rand.Read(token) + p.Value = token + _, err := kvClient.Put(p, writeOpts) + if err != nil { + return fmt.Errorf("error writing kv: %w", err) + } + } + return nil +} + // Leader returns the cluster leader agent, or an error if no leader is // available. func (s *Sprawl) Leader(clusterName string) (*topology.Node, error) { @@ -390,11 +620,11 @@ func (s *Sprawl) SnapshotEnvoy(ctx context.Context) error { if n.Disabled { continue } - for _, s := range n.Services { - if s.Disabled || s.EnvoyAdminPort <= 0 { + for _, wrk := range n.Workloads { + if wrk.Disabled || wrk.EnvoyAdminPort <= 0 { continue } - prefix := fmt.Sprintf("http://%s:%d", n.LocalAddress(), s.EnvoyAdminPort) + prefix := fmt.Sprintf("http://%s:%d", n.LocalAddress(), wrk.EnvoyAdminPort) for fn, target := range targets { u := prefix + "/" + target @@ -402,23 +632,23 @@ func (s *Sprawl) SnapshotEnvoy(ctx context.Context) error { body, err := scrapeURL(client, u) if err != nil { merr = multierror.Append(merr, fmt.Errorf("could not scrape %q for %s on %s: %w", - target, s.ID.String(), n.ID().String(), err, + target, wrk.ID.String(), n.ID().String(), err, )) continue } - outFn := filepath.Join(snapDir, n.DockerName()+"--"+s.ID.TFString()+"."+fn) + outFn := filepath.Join(snapDir, n.DockerName()+"--"+wrk.ID.TFString()+"."+fn) if err := os.WriteFile(outFn+".tmp", body, 0644); err != nil { merr = multierror.Append(merr, fmt.Errorf("could not write output %q for %s on %s: %w", - target, s.ID.String(), n.ID().String(), err, + target, wrk.ID.String(), n.ID().String(), err, )) continue } if err := os.Rename(outFn+".tmp", outFn); err != nil { merr = multierror.Append(merr, fmt.Errorf("could not write output %q for %s on %s: %w", - target, s.ID.String(), n.ID().String(), err, + target, wrk.ID.String(), n.ID().String(), err, )) continue } @@ -533,3 +763,7 @@ func (s *Sprawl) dumpContainerLogs(ctx context.Context, containerName, outputRoo keep = true return nil } + +func (s *Sprawl) GetFileFromContainer(ctx context.Context, containerName string, filePath string) error { + return s.runner.DockerExec(ctx, []string{"cp", containerName + ":" + filePath, filePath}, nil, nil) +} diff --git a/testing/deployer/sprawl/sprawltest/test_test.go b/testing/deployer/sprawl/sprawltest/test_test.go index 8a098c92ab2b..5195716b2b12 100644 --- a/testing/deployer/sprawl/sprawltest/test_test.go +++ b/testing/deployer/sprawl/sprawltest/test_test.go @@ -1,166 +1,32 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 +//go:build integration + package sprawltest_test import ( "strconv" "testing" - "github.com/hashicorp/consul/api" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest" "github.com/hashicorp/consul/testing/deployer/topology" ) -func TestSprawl_CatalogV2(t *testing.T) { - serversDC1 := newTopologyServerSet("dc1-server", 3, []string{"dc1", "wan"}, nil) - - cfg := &topology.Config{ - Images: topology.Images{ - ConsulCE: "hashicorppreview/consul:1.17-dev", - ConsulEnterprise: "hashicorppreview/consul-enterprise:1.17-dev", - Dataplane: "hashicorppreview/consul-dataplane:1.3-dev", - }, - Networks: []*topology.Network{ - {Name: "dc1"}, - {Name: "wan", Type: "wan"}, - }, - Clusters: []*topology.Cluster{ - { - Enterprise: true, - Name: "dc1", - Nodes: topology.MergeSlices(serversDC1, []*topology.Node{ - { - Kind: topology.NodeKindDataplane, - Version: topology.NodeVersionV2, - Name: "dc1-client1", - Services: []*topology.Service{ - { - ID: topology.ServiceID{Name: "ping"}, - Image: "rboyer/pingpong:latest", - Port: 8080, - EnvoyAdminPort: 19000, - Command: []string{ - "-bind", "0.0.0.0:8080", - "-dial", "127.0.0.1:9090", - "-pong-chaos", - "-dialfreq", "250ms", - "-name", "ping", - }, - Upstreams: []*topology.Upstream{{ - ID: topology.ServiceID{Name: "pong"}, - LocalPort: 9090, - }}, - }, - }, - }, - { - Kind: topology.NodeKindDataplane, - Version: topology.NodeVersionV2, - Name: "dc1-client2", - Services: []*topology.Service{ - { - ID: topology.ServiceID{Name: "pong"}, - Image: "rboyer/pingpong:latest", - Port: 8080, - EnvoyAdminPort: 19000, - Command: []string{ - "-bind", "0.0.0.0:8080", - "-dial", "127.0.0.1:9090", - "-pong-chaos", - "-dialfreq", "250ms", - "-name", "pong", - }, - Upstreams: []*topology.Upstream{{ - ID: topology.ServiceID{Name: "ping"}, - LocalPort: 9090, - }}, - }, - }, - }, - }), - InitialResources: []*pbresource.Resource{ - sprawltest.MustSetResourceData(t, &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbmesh.HTTPRouteType, - Name: "test-http-route", - }, - }, &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{{ - Ref: &pbresource.Reference{ - Type: pbcatalog.ServiceType, - Name: "test", - }, - }}, - }), - sprawltest.MustSetResourceData(t, &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbauth.TrafficPermissionsType, - Name: "ping-perms", - }, - }, &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "ping", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{{ - Sources: []*pbauth.Source{{ - IdentityName: "pong", - }}, - }}, - }), - sprawltest.MustSetResourceData(t, &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbauth.TrafficPermissionsType, - Name: "pong-perms", - }, - }, &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "pong", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{{ - Sources: []*pbauth.Source{{ - IdentityName: "ping", - }}, - }}, - }), - }, - }, - }, - } - - sp := sprawltest.Launch(t, cfg) - - for _, cluster := range sp.Topology().Clusters { - leader, err := sp.Leader(cluster.Name) - require.NoError(t, err) - t.Logf("%s: leader = %s", cluster.Name, leader.ID()) - - followers, err := sp.Followers(cluster.Name) - require.NoError(t, err) - for _, f := range followers { - t.Logf("%s: follower = %s", cluster.Name, f.ID()) - } - } -} - func TestSprawl(t *testing.T) { serversDC1 := newTopologyServerSet("dc1-server", 3, []string{"dc1", "wan"}, nil) serversDC2 := newTopologyServerSet("dc2-server", 3, []string{"dc2", "wan"}, nil) cfg := &topology.Config{ Images: topology.Images{ + // TODO NOT HARDCODE // ConsulEnterprise: "consul-dev:latest", - ConsulCE: "hashicorppreview/consul:1.17-dev", - ConsulEnterprise: "hashicorppreview/consul-enterprise:1.17-dev", - Dataplane: "hashicorppreview/consul-dataplane:1.3-dev", + ConsulCE: "hashicorppreview/consul:1.20-dev", + ConsulEnterprise: "hashicorppreview/consul-enterprise:1.20-dev", + Dataplane: "hashicorppreview/consul-dataplane:1.6-dev", }, Networks: []*topology.Network{ {Name: "dc1"}, @@ -174,9 +40,9 @@ func TestSprawl(t *testing.T) { { Kind: topology.NodeKindClient, Name: "dc1-client1", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { - ID: topology.ServiceID{Name: "mesh-gateway"}, + ID: topology.ID{Name: "mesh-gateway"}, Port: 8443, EnvoyAdminPort: 19000, IsMeshGateway: true, @@ -186,9 +52,9 @@ func TestSprawl(t *testing.T) { { Kind: topology.NodeKindClient, Name: "dc1-client2", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { - ID: topology.ServiceID{Name: "ping"}, + ID: topology.ID{Name: "ping"}, Image: "rboyer/pingpong:latest", Port: 8080, EnvoyAdminPort: 19000, @@ -200,7 +66,7 @@ func TestSprawl(t *testing.T) { "-name", "ping", }, Upstreams: []*topology.Upstream{{ - ID: topology.ServiceID{Name: "pong"}, + ID: topology.ID{Name: "pong"}, LocalPort: 9090, Peer: "peer-dc2-default", }}, @@ -226,9 +92,9 @@ func TestSprawl(t *testing.T) { { Kind: topology.NodeKindClient, Name: "dc2-client1", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { - ID: topology.ServiceID{Name: "mesh-gateway"}, + ID: topology.ID{Name: "mesh-gateway"}, Port: 8443, EnvoyAdminPort: 19000, IsMeshGateway: true, @@ -238,34 +104,9 @@ func TestSprawl(t *testing.T) { { Kind: topology.NodeKindDataplane, Name: "dc2-client2", - Services: []*topology.Service{ - { - ID: topology.ServiceID{Name: "pong"}, - Image: "rboyer/pingpong:latest", - Port: 8080, - EnvoyAdminPort: 19000, - Command: []string{ - "-bind", "0.0.0.0:8080", - "-dial", "127.0.0.1:9090", - "-pong-chaos", - "-dialfreq", "250ms", - "-name", "pong", - }, - Upstreams: []*topology.Upstream{{ - ID: topology.ServiceID{Name: "ping"}, - LocalPort: 9090, - Peer: "peer-dc1-default", - }}, - }, - }, - }, - { - Kind: topology.NodeKindDataplane, - Version: topology.NodeVersionV2, - Name: "dc2-client3", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { - ID: topology.ServiceID{Name: "pong"}, + ID: topology.ID{Name: "pong"}, Image: "rboyer/pingpong:latest", Port: 8080, EnvoyAdminPort: 19000, @@ -277,7 +118,7 @@ func TestSprawl(t *testing.T) { "-name", "pong", }, Upstreams: []*topology.Upstream{{ - ID: topology.ServiceID{Name: "ping"}, + ID: topology.ID{Name: "ping"}, LocalPort: 9090, Peer: "peer-dc1-default", }}, diff --git a/testing/deployer/topology/compile.go b/testing/deployer/topology/compile.go index beaace3e145b..ffed56aaf36b 100644 --- a/testing/deployer/topology/compile.go +++ b/testing/deployer/topology/compile.go @@ -13,32 +13,39 @@ import ( "sort" "github.com/google/go-cmp/cmp" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/go-hclog" "golang.org/x/exp/maps" + "github.com/hashicorp/go-hclog" + + "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/testing/deployer/util" ) const DockerPrefix = "cslc" // ConSuLCluster func Compile(logger hclog.Logger, raw *Config) (*Topology, error) { - return compile(logger, raw, nil) + return compile(logger, raw, nil, "") } func Recompile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error) { if prev == nil { return nil, errors.New("missing previous topology") } - return compile(logger, raw, prev) + return compile(logger, raw, prev, "") } -func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error) { +func compile(logger hclog.Logger, raw *Config, prev *Topology, testingID string) (*Topology, error) { + if logger == nil { + return nil, errors.New("logger is required") + } + if raw == nil { + return nil, errors.New("config is required") + } + var id string - if prev == nil { + if testingID != "" { + id = testingID + } else if prev == nil { var err error id, err = newTopologyID() if err != nil { @@ -90,22 +97,17 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error nextIndex int // use a global index so any shared networks work properly with assignments ) - foundPeerNames := make(map[string]map[string]struct{}) - for _, c := range raw.Clusters { + compileCluster := func(c *Cluster) (map[string]struct{}, error) { if c.Name == "" { return nil, fmt.Errorf("cluster has no name") } - foundPeerNames[c.Name] = make(map[string]struct{}) + foundPeerNames := make(map[string]struct{}) if !IsValidLabel(c.Name) { return nil, fmt.Errorf("cluster name is not valid: %s", c.Name) } - if _, exists := clusters[c.Name]; exists { - return nil, fmt.Errorf("cannot have two clusters with the same name %q; use unique names and override the Datacenter field if that's what you want", c.Name) - } - if c.Datacenter == "" { c.Datacenter = c.Name } else { @@ -114,7 +116,6 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error } } - clusters[c.Name] = c if c.NetworkName == "" { c.NetworkName = c.Name } @@ -129,22 +130,6 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error return nil, fmt.Errorf("cluster %q has no nodes", c.Name) } - if len(c.Services) == 0 { // always initialize this regardless of v2-ness, because we might late-enable it below - c.Services = make(map[ServiceID]*pbcatalog.Service) - } - - var implicitV2Services bool - if len(c.Services) > 0 { - c.EnableV2 = true - for name, svc := range c.Services { - if svc.Workloads != nil { - return nil, fmt.Errorf("the workloads field for v2 service %q is not user settable", name) - } - } - } else { - implicitV2Services = true - } - if c.TLSVolumeName != "" { return nil, fmt.Errorf("user cannot specify the TLSVolumeName field") } @@ -158,6 +143,7 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error m = make(map[string]struct{}) tenancies[partition] = m } + m["default"] = struct{}{} m[namespace] = struct{}{} } @@ -172,41 +158,24 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error addTenancy(ce.GetPartition(), ce.GetNamespace()) } - if len(c.InitialResources) > 0 { - c.EnableV2 = true - } for _, res := range c.InitialResources { if res.Id.Tenancy == nil { res.Id.Tenancy = &pbresource.Tenancy{} } - switch res.Id.Tenancy.PeerName { - case "", "local": - default: - return nil, fmt.Errorf("resources cannot target non-local peers") - } res.Id.Tenancy.Partition = PartitionOrDefault(res.Id.Tenancy.Partition) - res.Id.Tenancy.Namespace = NamespaceOrDefault(res.Id.Tenancy.Namespace) - - switch { - case util.EqualType(pbauth.ComputedTrafficPermissionsType, res.Id.GetType()), - util.EqualType(pbauth.WorkloadIdentityType, res.Id.GetType()): - fallthrough - case util.EqualType(pbmesh.ComputedRoutesType, res.Id.GetType()), - util.EqualType(pbmesh.ProxyStateTemplateType, res.Id.GetType()): - fallthrough - case util.EqualType(pbcatalog.HealthChecksType, res.Id.GetType()), - util.EqualType(pbcatalog.HealthStatusType, res.Id.GetType()), - util.EqualType(pbcatalog.NodeType, res.Id.GetType()), - util.EqualType(pbcatalog.ServiceEndpointsType, res.Id.GetType()), - util.EqualType(pbcatalog.WorkloadType, res.Id.GetType()): + if !util.IsTypePartitionScoped(res.Id.Type) { + res.Id.Tenancy.Namespace = NamespaceOrDefault(res.Id.Tenancy.Namespace) + } + + // TODO: if we reintroduce new resources for v1, allow them here + if true { return nil, fmt.Errorf("you should not create a resource of type %q this way", util.TypeToString(res.Id.Type)) } addTenancy(res.Id.Tenancy.Partition, res.Id.Tenancy.Namespace) } - seenNodes := make(map[NodeID]struct{}) - for _, n := range c.Nodes { + compileClusterNode := func(n *Node) (map[string]struct{}, error) { if n.Name == "" { return nil, fmt.Errorf("cluster %q node has no name", c.Name) } @@ -220,30 +189,15 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error return nil, fmt.Errorf("cluster %q node %q has invalid kind: %s", c.Name, n.Name, n.Kind) } - if n.Version == NodeVersionUnknown { - n.Version = NodeVersionV1 - } - switch n.Version { - case NodeVersionV1: - case NodeVersionV2: - if n.Kind == NodeKindClient { - return nil, fmt.Errorf("v2 does not support client agents at this time") - } - c.EnableV2 = true - default: - return nil, fmt.Errorf("cluster %q node %q has invalid version: %s", c.Name, n.Name, n.Version) - } - n.Partition = PartitionOrDefault(n.Partition) if !IsValidLabel(n.Partition) { return nil, fmt.Errorf("node partition is not valid: %s", n.Partition) } addTenancy(n.Partition, "default") - if _, exists := seenNodes[n.ID()]; exists { - return nil, fmt.Errorf("cannot have two nodes in the same cluster %q with the same name %q", c.Name, n.ID()) + if n.IsServer() && n.Partition != "default" { + return nil, fmt.Errorf("server agents must always be in the default partition") } - seenNodes[n.ID()] = struct{}{} if len(n.usedPorts) != 0 { return nil, fmt.Errorf("user cannot specify the usedPorts field") @@ -317,53 +271,52 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error return nil, fmt.Errorf("cluster %q node %q has more than one public address", c.Name, n.Name) } - if n.IsDataplane() && len(n.Services) > 1 { + if n.IsDataplane() && len(n.Workloads) > 1 { // Our use of consul-dataplane here is supposed to mimic that // of consul-k8s, which ultimately has one IP per Service, so // we introduce the same limitation here. return nil, fmt.Errorf("cluster %q node %q uses dataplane, but has more than one service", c.Name, n.Name) } - seenServices := make(map[ServiceID]struct{}) - for _, svc := range n.Services { + var ( + foundPeerNames = make(map[string]struct{}) + seenServices = make(map[ID]struct{}) + ) + for _, wrk := range n.Workloads { if n.IsAgent() { // Default to that of the enclosing node. - svc.ID.Partition = n.Partition + wrk.ID.Partition = n.Partition } - svc.ID.Normalize() + wrk.ID.Normalize() // Denormalize - svc.Node = n - svc.NodeVersion = n.Version - if n.IsV2() { - svc.Workload = svc.ID.Name + "-" + n.PodName() - } + wrk.Node = n - if !IsValidLabel(svc.ID.Partition) { - return nil, fmt.Errorf("service partition is not valid: %s", svc.ID.Partition) + if !IsValidLabel(wrk.ID.Partition) { + return nil, fmt.Errorf("service partition is not valid: %s", wrk.ID.Partition) } - if !IsValidLabel(svc.ID.Namespace) { - return nil, fmt.Errorf("service namespace is not valid: %s", svc.ID.Namespace) + if !IsValidLabel(wrk.ID.Namespace) { + return nil, fmt.Errorf("service namespace is not valid: %s", wrk.ID.Namespace) } - if !IsValidLabel(svc.ID.Name) { - return nil, fmt.Errorf("service name is not valid: %s", svc.ID.Name) + if !IsValidLabel(wrk.ID.Name) { + return nil, fmt.Errorf("service name is not valid: %s", wrk.ID.Name) } - if svc.ID.Partition != n.Partition { + if wrk.ID.Partition != n.Partition { return nil, fmt.Errorf("service %s on node %s has mismatched partitions: %s != %s", - svc.ID.Name, n.Name, svc.ID.Partition, n.Partition) + wrk.ID.Name, n.Name, wrk.ID.Partition, n.Partition) } - addTenancy(svc.ID.Partition, svc.ID.Namespace) + addTenancy(wrk.ID.Partition, wrk.ID.Namespace) - if _, exists := seenServices[svc.ID]; exists { - return nil, fmt.Errorf("cannot have two services on the same node %q in the same cluster %q with the same name %q", n.ID(), c.Name, svc.ID) + if _, exists := seenServices[wrk.ID]; exists { + return nil, fmt.Errorf("cannot have two services on the same node %q in the same cluster %q with the same name %q", n.ID(), c.Name, wrk.ID) } - seenServices[svc.ID] = struct{}{} + seenServices[wrk.ID] = struct{}{} - if !svc.DisableServiceMesh && n.IsDataplane() { - if svc.EnvoyPublicListenerPort <= 0 { + if !wrk.DisableServiceMesh && n.IsDataplane() { + if wrk.EnvoyPublicListenerPort <= 0 { if _, ok := n.usedPorts[20000]; !ok { // For convenience the FIRST service on a node can get 20000 for free. - svc.EnvoyPublicListenerPort = 20000 + wrk.EnvoyPublicListenerPort = 20000 } else { return nil, fmt.Errorf("envoy public listener port is required") } @@ -371,176 +324,82 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error } // add all of the service ports - for _, port := range svc.ports() { + for _, port := range wrk.ports() { if ok := exposePort(port); !ok { return nil, fmt.Errorf("port used more than once on cluster %q node %q: %d", c.Name, n.ID(), port) } } // TODO(rb): re-expose? - // switch svc.Protocol { + // switch wrk.Protocol { // case "": - // svc.Protocol = "tcp" + // wrk.Protocol = "tcp" // fallthrough // case "tcp": - // if svc.CheckHTTP != "" { + // if wrk.CheckHTTP != "" { // return nil, fmt.Errorf("cannot set CheckHTTP for tcp service") // } // case "http": - // if svc.CheckTCP != "" { + // if wrk.CheckTCP != "" { // return nil, fmt.Errorf("cannot set CheckTCP for tcp service") // } // default: - // return nil, fmt.Errorf("service has invalid protocol: %s", svc.Protocol) + // return nil, fmt.Errorf("service has invalid protocol: %s", wrk.Protocol) // } - defaultUpstream := func(u *Upstream) error { + defaultUpstream := func(us *Upstream) error { // Default to that of the enclosing service. - if u.Peer == "" { - if u.ID.Partition == "" { - u.ID.Partition = svc.ID.Partition + if us.Peer == "" { + if us.ID.Partition == "" { + us.ID.Partition = wrk.ID.Partition } - if u.ID.Namespace == "" { - u.ID.Namespace = svc.ID.Namespace + if us.ID.Namespace == "" { + us.ID.Namespace = wrk.ID.Namespace } } else { - if u.ID.Partition != "" { - u.ID.Partition = "" // irrelevant here; we'll set it to the value of the OTHER side for plumbing purposes in tests + if us.ID.Partition != "" { + us.ID.Partition = "" // irrelevant here; we'll set it to the value of the OTHER side for plumbing purposes in tests } - u.ID.Namespace = NamespaceOrDefault(u.ID.Namespace) - foundPeerNames[c.Name][u.Peer] = struct{}{} + us.ID.Namespace = NamespaceOrDefault(us.ID.Namespace) + foundPeerNames[us.Peer] = struct{}{} } - addTenancy(u.ID.Partition, u.ID.Namespace) + addTenancy(us.ID.Partition, us.ID.Namespace) - if u.Implied { - if u.PortName == "" { - return fmt.Errorf("implicit upstreams must use port names in v2") - } - } else { - if u.LocalAddress == "" { - // v1 defaults to 127.0.0.1 but v2 does not. Safe to do this generally though. - u.LocalAddress = "127.0.0.1" - } - if u.PortName != "" && n.IsV1() { - return fmt.Errorf("explicit upstreams cannot use port names in v1") - } - if u.PortName == "" && n.IsV2() { - // Assume this is a v1->v2 conversion and name it. - u.PortName = "legacy" - } + if us.LocalAddress == "" { + // v1 consul code defaults this to 127.0.0.1, but safer to not rely upon that. + us.LocalAddress = "127.0.0.1" } return nil } - for _, u := range svc.Upstreams { - if err := defaultUpstream(u); err != nil { + for _, us := range wrk.Upstreams { + if err := defaultUpstream(us); err != nil { return nil, err } } - if n.IsV2() { - for _, u := range svc.ImpliedUpstreams { - u.Implied = true - if err := defaultUpstream(u); err != nil { - return nil, err - } - } - } else { - if len(svc.ImpliedUpstreams) > 0 { - return nil, fmt.Errorf("v1 does not support implied upstreams yet") - } - } - - if err := svc.Validate(); err != nil { - return nil, fmt.Errorf("cluster %q node %q service %q is not valid: %w", c.Name, n.Name, svc.ID.String(), err) - } - - if svc.EnableTransparentProxy && !n.IsDataplane() { - return nil, fmt.Errorf("cannot enable tproxy on a non-dataplane node") - } - - if n.IsV2() { - if implicitV2Services { - svc.V2Services = []string{svc.ID.Name} - - var svcPorts []*pbcatalog.ServicePort - for name, cfg := range svc.Ports { - svcPorts = append(svcPorts, &pbcatalog.ServicePort{ - TargetPort: name, - Protocol: cfg.ActualProtocol, - }) - } - - v2svc := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{}, - Ports: svcPorts, - } - - prev, ok := c.Services[svc.ID] - if !ok { - c.Services[svc.ID] = v2svc - prev = v2svc - } - if prev.Workloads == nil { - prev.Workloads = &pbcatalog.WorkloadSelector{} - } - prev.Workloads.Names = append(prev.Workloads.Names, svc.Workload) - - } else { - for _, name := range svc.V2Services { - v2ID := NewServiceID(name, svc.ID.Namespace, svc.ID.Partition) - - v2svc, ok := c.Services[v2ID] - if !ok { - return nil, fmt.Errorf("cluster %q node %q service %q has a v2 service reference that does not exist %q", - c.Name, n.Name, svc.ID.String(), name) - } - if v2svc.Workloads == nil { - v2svc.Workloads = &pbcatalog.WorkloadSelector{} - } - v2svc.Workloads.Names = append(v2svc.Workloads.Names, svc.Workload) - } - } - - if svc.WorkloadIdentity == "" { - svc.WorkloadIdentity = svc.ID.Name - } - } else { - if len(svc.V2Services) > 0 { - return nil, fmt.Errorf("cannot specify v2 services for v1") - } - if svc.WorkloadIdentity != "" { - return nil, fmt.Errorf("cannot specify workload identities for v1") - } + if err := wrk.Validate(); err != nil { + return nil, fmt.Errorf("cluster %q node %q service %q is not valid: %w", c.Name, n.Name, wrk.ID.String(), err) } } + return foundPeerNames, nil } - if err := assignVirtualIPs(c); err != nil { - return nil, err - } + seenNodes := make(map[NodeID]struct{}) + for _, n := range c.Nodes { + peerNames, err := compileClusterNode(n) + if err != nil { + return nil, fmt.Errorf("error compiling node %q: %w", n.Name, err) + } - if c.EnableV2 { - // Populate the VirtualPort field on all implied upstreams. - for _, n := range c.Nodes { - for _, svc := range n.Services { - for _, u := range svc.ImpliedUpstreams { - res, ok := c.Services[u.ID] - if ok { - for _, sp := range res.Ports { - if sp.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue - } - if sp.TargetPort == u.PortName { - u.VirtualPort = sp.VirtualPort - } - } - } - } - } + if _, exists := seenNodes[n.ID()]; exists { + return nil, fmt.Errorf("cannot have two nodes in the same cluster %q with the same name %q", c.Name, n.ID()) } + seenNodes[n.ID()] = struct{}{} + + maps.Copy(foundPeerNames, peerNames) } // Explode this into the explicit list based on stray references made. @@ -565,6 +424,24 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error return nil, fmt.Errorf("cluster %q references non-default partitions or namespaces but is CE", c.Name) } } + + return foundPeerNames, nil + } + + foundPeerNames := make(map[string]map[string]struct{}) + for _, c := range raw.Clusters { + peerNames, err := compileCluster(c) + if err != nil { + return nil, fmt.Errorf("error building cluster %q: %w", c.Name, err) + } + + foundPeerNames[c.Name] = peerNames + + if _, exists := clusters[c.Name]; exists { + return nil, fmt.Errorf("cannot have two clusters with the same name %q; use unique names and override the Datacenter field if that's what you want", c.Name) + } + + clusters[c.Name] = c } clusteredPeerings := make(map[string]map[string]*PeerCluster) // local-cluster -> local-peer -> info @@ -652,47 +529,33 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error for _, c := range clusters { c.Peerings = clusteredPeerings[c.Name] for _, n := range c.Nodes { - for _, svc := range n.Services { - for _, u := range svc.Upstreams { - if u.Peer == "" { - u.Cluster = c.Name - u.Peering = nil - continue - } - remotePeer, ok := c.Peerings[u.Peer] - if !ok { - return nil, fmt.Errorf("not possible") - } - u.Cluster = remotePeer.Link.Name - u.Peering = remotePeer.Link - // this helps in generating fortio assertions; otherwise field is ignored - u.ID.Partition = remotePeer.Link.Partition - } - for _, u := range svc.ImpliedUpstreams { - if u.Peer == "" { - u.Cluster = c.Name - u.Peering = nil + for _, wrk := range n.Workloads { + for _, us := range wrk.Upstreams { + if us.Peer == "" { + us.Cluster = c.Name + us.Peering = nil continue } - remotePeer, ok := c.Peerings[u.Peer] + remotePeer, ok := c.Peerings[us.Peer] if !ok { return nil, fmt.Errorf("not possible") } - u.Cluster = remotePeer.Link.Name - u.Peering = remotePeer.Link + us.Cluster = remotePeer.Link.Name + us.Peering = remotePeer.Link // this helps in generating fortio assertions; otherwise field is ignored - u.ID.Partition = remotePeer.Link.Partition + us.ID.Partition = remotePeer.Link.Partition } } } } t := &Topology{ - ID: id, - Networks: networks, - Clusters: clusters, - Images: images, - Peerings: raw.Peerings, + ID: id, + Networks: networks, + Clusters: clusters, + Images: images, + Peerings: raw.Peerings, + NetworkAreas: raw.NetworkAreas, } if prev != nil { @@ -749,51 +612,6 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology) (*Topology, error return t, nil } -func assignVirtualIPs(c *Cluster) error { - lastVIPIndex := 1 - for _, svcData := range c.Services { - lastVIPIndex++ - if lastVIPIndex > 250 { - return fmt.Errorf("too many ips using this approach to VIPs") - } - svcData.VirtualIps = []string{ - fmt.Sprintf("10.244.0.%d", lastVIPIndex), - } - - // populate virtual ports where we forgot them - var ( - usedPorts = make(map[uint32]struct{}) - next = uint32(8080) - ) - for _, sp := range svcData.Ports { - if sp.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue - } - if sp.VirtualPort > 0 { - usedPorts[sp.VirtualPort] = struct{}{} - } - } - for _, sp := range svcData.Ports { - if sp.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue - } - if sp.VirtualPort > 0 { - continue - } - RETRY: - attempt := next - next++ - _, used := usedPorts[attempt] - if used { - goto RETRY - } - usedPorts[attempt] = struct{}{} - sp.VirtualPort = attempt - } - } - return nil -} - const permutedWarning = "use the disabled node kind if you want to ignore a node" func inheritAndValidateNodes( @@ -817,7 +635,6 @@ func inheritAndValidateNodes( } if currNode.Node.Kind != node.Kind || - currNode.Node.Version != node.Version || currNode.Node.Partition != node.Partition || currNode.Node.Name != node.Name || currNode.Node.Index != node.Index || @@ -843,26 +660,25 @@ func inheritAndValidateNodes( currAddr.inheritFromExisting(prevAddr) } - svcMap := mapifyServices(currNode.Node.Services) + wrkMap := mapifyWorkloads(currNode.Node.Workloads) - for _, svc := range node.Services { - currSvc, ok := svcMap[svc.ID] + for _, wrk := range node.Workloads { + currWrk, ok := wrkMap[wrk.ID] if !ok { continue // service has vanished, this is ok } // don't care about index permutation - if currSvc.ID != svc.ID || - currSvc.Port != svc.Port || - !maps.Equal(currSvc.Ports, svc.Ports) || - currSvc.EnvoyAdminPort != svc.EnvoyAdminPort || - currSvc.EnvoyPublicListenerPort != svc.EnvoyPublicListenerPort || - isSame(currSvc.Command, svc.Command) != nil || - isSame(currSvc.Env, svc.Env) != nil { - return fmt.Errorf("cannot edit some address fields for %q", svc.ID) + if currWrk.ID != wrk.ID || + currWrk.Port != wrk.Port || + currWrk.EnvoyAdminPort != wrk.EnvoyAdminPort || + currWrk.EnvoyPublicListenerPort != wrk.EnvoyPublicListenerPort || + isSame(currWrk.Command, wrk.Command) != nil || + isSame(currWrk.Env, wrk.Env) != nil { + return fmt.Errorf("cannot edit some address fields for %q", wrk.ID) } - currSvc.inheritFromExisting(svc) + currWrk.inheritFromExisting(wrk) } } return nil @@ -935,10 +751,10 @@ type nodeWithPosition struct { Node *Node } -func mapifyServices(services []*Service) map[ServiceID]*Service { - m := make(map[ServiceID]*Service) - for _, svc := range services { - m[svc.ID] = svc +func mapifyWorkloads(workloads []*Service) map[ID]*Service { + m := make(map[ID]*Service) + for _, wrk := range workloads { + m[wrk.ID] = wrk } return m } diff --git a/testing/deployer/topology/compile_test.go b/testing/deployer/topology/compile_test.go new file mode 100644 index 000000000000..564906ae9693 --- /dev/null +++ b/testing/deployer/topology/compile_test.go @@ -0,0 +1,1378 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package topology + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/testing/protocmp" + + "github.com/hashicorp/go-hclog" + + "github.com/hashicorp/consul/sdk/testutil" +) + +func TestCompile_CE(t *testing.T) { + type testcase struct { + in *Config + expect *Topology + expectErr string + } + + logger := hclog.NewNullLogger() + + const clusterID = "87c82bd03dc89d4d" + + run := func(t *testing.T, tc testcase) { + got, err := compile(logger, tc.in, nil, clusterID) + if tc.expectErr == "" { + require.NotNil(t, tc.expect, "field must be set") + require.NoError(t, err) + + // Set recursive pointers on expectations. + for _, c := range tc.expect.Clusters { + for _, n := range c.Nodes { + for _, w := range n.Workloads { + w.Node = n + } + } + } + + assertDeepEqual(t, tc.expect, got) + } else { + require.Nil(t, tc.expect, "field cannot be set") + require.Nil(t, got) + testutil.RequireErrorContains(t, err, tc.expectErr) + } + } + + cases := map[string]testcase{ + "nil": { + in: nil, + expectErr: `config is required`, + }, + "consul image cannot be set at the top level": { + in: &Config{ + Images: DefaultImages().ChooseConsul(true), + }, + expectErr: `topology.images.consul cannot be set at this level`, + }, + "no networks": { + in: &Config{}, + expectErr: `topology.networks is empty`, + }, + "bad network/no name": { + in: &Config{ + Networks: []*Network{{ + // + }}, + }, + expectErr: `network name is not valid`, + }, + "bad network/invalid name": { + in: &Config{ + Networks: []*Network{{ + Name: "-123", + }}, + }, + expectErr: `network name is not valid`, + }, + "bad network/should not use DockerName": { + in: &Config{ + Networks: []*Network{{ + Name: "foo", + DockerName: "blah", + }}, + }, + expectErr: `network "foo" should not specify DockerName`, + }, + "bad network/duplicate names": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + {Name: "foo"}, + }, + }, + expectErr: `cannot have two networks with the same name "foo"`, + }, + "bad network/unknown type": { + in: &Config{ + Networks: []*Network{ + {Name: "foo", Type: "ext"}, + }, + }, + expectErr: `network "foo" has unknown type "ext"`, + }, + "good networks one server node": { + in: &Config{ + Networks: []*Network{ + {Name: "foo1"}, + {Name: "foo2", Type: "lan"}, + {Name: "foo3", Type: "wan"}, + }, + Clusters: []*Cluster{{ + Name: "foo2", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "node1", + Addresses: []*Address{ + {Network: "foo2"}, + {Network: "foo3"}, + }, + }}, + }}, + }, + expect: &Topology{ + ID: clusterID, + Images: DefaultImages(), + Networks: map[string]*Network{ + "foo1": {Name: "foo1", Type: "lan", DockerName: "cslc-foo1-" + clusterID}, + "foo2": {Name: "foo2", Type: "lan", DockerName: "cslc-foo2-" + clusterID}, + "foo3": {Name: "foo3", Type: "wan", DockerName: "cslc-foo3-" + clusterID}, + }, + Clusters: map[string]*Cluster{ + "foo2": { + Name: "foo2", + NetworkName: "foo2", + Datacenter: "foo2", + Images: DefaultImages().ChooseConsul(false), + Nodes: []*Node{{ + Kind: NodeKindServer, + Partition: "default", + Name: "node1", + Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindServer), + Addresses: []*Address{ + {Network: "foo2", Type: "lan", DockerNetworkName: "cslc-foo2-" + clusterID}, + {Network: "foo3", Type: "wan", DockerNetworkName: "cslc-foo3-" + clusterID}, + }, + Cluster: "foo2", + Datacenter: "foo2", + }}, + Partitions: []*Partition{{ + Name: "default", + Namespaces: []string{"default"}, + }}, + }, + }, + }, + }, + "no clusters": { + in: &Config{ + Networks: []*Network{ + {Name: "foo1"}, + }, + }, + expectErr: `topology.clusters is empty`, + }, + "bad cluster/no name": { + in: &Config{ + Networks: []*Network{ + {Name: "foo1"}, + }, + Clusters: []*Cluster{{}}, + }, + expectErr: `error building cluster "": cluster has no name`, + }, + "bad cluster/invalid name": { + in: &Config{ + Networks: []*Network{ + {Name: "foo1"}, + }, + Clusters: []*Cluster{{ + Name: "-123", + }}, + }, + expectErr: `error building cluster "-123": cluster name is not valid: -123`, + }, + "bad cluster/invalid dc": { + in: &Config{ + Networks: []*Network{ + {Name: "foo1"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Datacenter: "-123", + }}, + }, + expectErr: `error building cluster "foo": datacenter name is not valid: -123`, + }, + "bad cluster/missing network": { + in: &Config{ + Networks: []*Network{ + {Name: "foo1"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + NetworkName: "bar", + }}, + }, + expectErr: `error building cluster "foo": cluster "foo" uses network name "bar" that does not exist`, + }, + "bad cluster/no nodes": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + }}, + }, + expectErr: `error building cluster "foo": cluster "foo" has no nodes`, + }, + "colliding clusters": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{ + { + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "node1", + }}, + }, + { + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "node1", + }}, + }, + }, + }, + expectErr: `cannot have two clusters with the same name "foo"; use unique names and override the Datacenter field if that's what you want`, + }, + // TODO: ERR: partitions in CE + // TODO: ERR: namespaces in CE + // TODO: ERR: servers in a non-default partition + "tenancy collection": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Enterprise: true, + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + }, + { + Kind: NodeKindClient, + Name: "mesh1", + Partition: "ap1", + Addresses: []*Address{ + {Network: "foo"}, + }, + Workloads: []*Workload{ + { + ID: NewID("zim", "ns1", ""), + Image: "busybox", + Port: 8888, + EnvoyAdminPort: 19000, + }, + { + ID: NewID("gir", "ns2", ""), + Image: "busybox", + Port: 8877, + EnvoyAdminPort: 19001, + Upstreams: []*Upstream{{ + ID: NewID("gaz", "ns3", "ap3"), + LocalAddress: "127.0.0.1", + LocalPort: 5000, + }}, + }, + }, + }, + }, + }}, + }, + expect: &Topology{ + ID: clusterID, + Images: DefaultImages(), + Networks: map[string]*Network{ + "foo": {Name: "foo", Type: "lan", DockerName: "cslc-foo-" + clusterID}, + }, + Clusters: map[string]*Cluster{ + "foo": { + Name: "foo", + NetworkName: "foo", + Datacenter: "foo", + Enterprise: true, + Images: DefaultImages().ChooseConsul(true), + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Partition: "default", + Images: DefaultImages().ChooseConsul(true).ChooseNode(NodeKindServer), + Addresses: []*Address{ + {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, + }, + Cluster: "foo", + Datacenter: "foo", + }, + { + Kind: NodeKindClient, + Name: "mesh1", + Partition: "ap1", + Images: DefaultImages().ChooseConsul(true).ChooseNode(NodeKindClient), + Addresses: []*Address{ + {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, + }, + Cluster: "foo", + Datacenter: "foo", + Index: 1, + Workloads: []*Workload{ + { + ID: NewID("zim", "ns1", "ap1"), + Image: "busybox", + Port: 8888, + EnvoyAdminPort: 19000, + }, + { + ID: NewID("gir", "ns2", "ap1"), + Image: "busybox", + Port: 8877, + EnvoyAdminPort: 19001, + Upstreams: []*Upstream{{ + ID: NewID("gaz", "ns3", "ap3"), + Cluster: "foo", + LocalAddress: "127.0.0.1", + LocalPort: 5000, + }}, + }, + }, + }, + }, + Partitions: []*Partition{ + { + Name: "ap1", + Namespaces: []string{"default", "ns1", "ns2"}, + }, + { + Name: "ap3", + Namespaces: []string{"default", "ns3"}, + }, + { + Name: "default", + Namespaces: []string{"default"}, + }, + }, + }, + }, + }, + }, + "tls volume errantly set": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "node1", + }}, + TLSVolumeName: "foo", + }}, + }, + expectErr: `error building cluster "foo": user cannot specify the TLSVolumeName field`, + }, + "node/no name": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + }}, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "": cluster "foo" node has no name`, + }, + "node/invalid name": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "-123", + }}, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "-123": node name is not valid: -123`, + }, + "node/bad kind": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{{ + Name: "zim", + }}, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "zim": cluster "foo" node "zim" has invalid kind`, + }, + "node/invalid partition": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "zim", + Partition: "-123", + }}, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "zim": node partition is not valid: -123`, + }, + "node/invalid usedPorts": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "zim", + usedPorts: map[int]int{5: 6}, + }}, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "zim": user cannot specify the usedPorts field`, + }, + "node/invalid index": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "zim", + Index: 99, + }}, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "zim": user cannot specify the node index`, + }, + "node/missing address network": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "zim", + Addresses: []*Address{{ + // + }}, + }}, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "zim": cluster "foo" node "zim" has invalid address`, + }, + "node/invalid address type": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "zim", + Addresses: []*Address{{ + Network: "foo", + Type: "lan", + }}, + }}, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "zim": user cannot specify the address type directly`, + }, + "node/address network does not exist": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "zim", + Addresses: []*Address{{ + Network: "bar", + }}, + }}, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "zim": cluster "foo" node "zim" uses network name "bar" that does not exist`, + }, + "node/no local addresses": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + {Name: "bar", Type: "wan"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "zim", + Addresses: []*Address{{ + Network: "bar", + }}, + }}, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "zim": cluster "foo" node "zim" has no local addresses`, + }, + "node/too many public addresses": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + {Name: "bar", Type: "wan"}, + {Name: "baz", Type: "wan"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{{ + Kind: NodeKindServer, + Name: "zim", + Addresses: []*Address{ + {Network: "foo"}, + {Network: "bar"}, + {Network: "baz"}, + }, + }}, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "zim": cluster "foo" node "zim" has more than one public address`, + }, + "node/dataplane with more than one workload": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{ + {Network: "foo"}, + }, + Workloads: []*Workload{ + {ID: NewID("zim", "default", "default")}, + {ID: NewID("gir", "default", "default")}, + }, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" uses dataplane, but has more than one service`, + }, + "workload/invalid partition": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: ID{ + Name: "zim", + Namespace: "default", + Partition: "-123", + }, + Image: "busybox", + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": service partition is not valid: -123`, + }, + "workload/invalid namespace": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: ID{ + Name: "zim", + Namespace: "-123", + Partition: "default", + }, + Image: "busybox", + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": service namespace is not valid: -123`, + }, + "workload/invalid name": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: ID{ + Name: "-123", + Namespace: "default", + Partition: "default", + }, + Image: "busybox", + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": service name is not valid: -123`, + }, + "workload/mismatched partitions": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: ID{ + Name: "zim", + Namespace: "default", + Partition: "ap1", + }, + Image: "busybox", + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": service zim on node mesh1 has mismatched partitions: ap1 != default`, + }, + "workload/node collision": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindClient, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{ + { + ID: NewID("zim", "", ""), + Image: "busybox", + Port: 8080, + EnvoyAdminPort: 19000, + }, + { + ID: NewID("zim", "", ""), + Image: "busybox", + Port: 9090, + EnvoyAdminPort: 19001, + }, + }, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cannot have two services on the same node "default/mesh1" in the same cluster "foo" with the same name "default/default/zim"`, + }, + "workload/default-upstream/expl dest local address defaulting": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + Image: "busybox", + Port: 8080, + EnvoyAdminPort: 19000, + Upstreams: []*Upstream{{ + ID: NewID("gir", "", ""), + LocalPort: 5000, + }}, + }}, + }, + }, + }}, + }, + expect: &Topology{ + ID: clusterID, + Images: DefaultImages(), + Networks: map[string]*Network{ + "foo": {Name: "foo", Type: "lan", DockerName: "cslc-foo-" + clusterID}, + }, + Clusters: map[string]*Cluster{ + "foo": { + Name: "foo", + NetworkName: "foo", + Datacenter: "foo", + Images: DefaultImages().ChooseConsul(false), + Nodes: []*Node{ + { + Kind: NodeKindServer, + Partition: "default", + Name: "server1", + Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindServer), + Addresses: []*Address{ + {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, + }, + Cluster: "foo", + Datacenter: "foo", + }, + { + Kind: NodeKindDataplane, + Partition: "default", + Name: "mesh1", + Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindDataplane), + Addresses: []*Address{ + {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, + }, + Cluster: "foo", + Datacenter: "foo", + Index: 1, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + Image: "busybox", + Port: 8080, + EnvoyAdminPort: 19000, + EnvoyPublicListenerPort: 20000, + Upstreams: []*Upstream{{ + ID: NewID("gir", "", ""), + LocalAddress: "127.0.0.1", // <--- this + LocalPort: 5000, + Cluster: "foo", + }}, + }}, + }, + }, + Partitions: []*Partition{{ + Name: "default", + Namespaces: []string{"default"}, + }}, + }, + }, + }, + }, + "workload/validate/no name": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindClient, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("", "", ""), + Image: "busybox", + Port: 8080, + EnvoyAdminPort: 19000, + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": service name is not valid`, + }, + "workload/validate/no image": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindClient, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + Port: 8080, + EnvoyAdminPort: 19000, + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: service image is required`, + }, + "workload/validate/no image mesh gateway": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindClient, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + Port: 8080, + EnvoyAdminPort: 19000, + IsMeshGateway: true, + }}, + }, + }, + }}, + }, + expect: &Topology{ + ID: clusterID, + Images: DefaultImages(), + Networks: map[string]*Network{ + "foo": {Name: "foo", Type: "lan", DockerName: "cslc-foo-" + clusterID}, + }, + Clusters: map[string]*Cluster{ + "foo": { + Name: "foo", + NetworkName: "foo", + Datacenter: "foo", + Images: DefaultImages().ChooseConsul(false), + Nodes: []*Node{ + { + Kind: NodeKindServer, + Partition: "default", + Name: "server1", + Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindServer), + Addresses: []*Address{ + {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, + }, + Cluster: "foo", + Datacenter: "foo", + }, + { + Kind: NodeKindClient, + Partition: "default", + Name: "mesh1", + Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindClient), + Addresses: []*Address{ + {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, + }, + Cluster: "foo", + Datacenter: "foo", + Index: 1, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + Port: 8080, + EnvoyAdminPort: 19000, + IsMeshGateway: true, + }}, + }, + }, + Partitions: []*Partition{{ + Name: "default", + Namespaces: []string{"default"}, + }}, + }, + }, + }, + }, + "workload/validate/singleport invalid port": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + Image: "busybox", + EnvoyAdminPort: 19000, + Port: -999, + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: service has invalid port`, + }, + "workload/validate/mesh with no admin port": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + Image: "busybox", + Port: 999, + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: envoy admin port is required`, + }, + "workload/validate/no mesh with admin port": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + EnvoyAdminPort: 19000, + DisableServiceMesh: true, + Image: "busybox", + Port: 999, + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: cannot use envoy admin port without a service mesh`, + }, + "workload/validate/expl dest with no name": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + EnvoyAdminPort: 19000, + Image: "busybox", + Port: 999, + Upstreams: []*Upstream{{ + ID: NewID("", "", ""), + }}, + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: upstream service name is required`, + }, + "workload/validate/expl dest with no local port": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + EnvoyAdminPort: 19000, + Image: "busybox", + Port: 999, + Upstreams: []*Upstream{{ + ID: NewID("dib", "", ""), + }}, + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: upstream local port is required`, + }, + "workload/validate/expl dest bad local address": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + EnvoyAdminPort: 19000, + Image: "busybox", + Port: 999, + Upstreams: []*Upstream{{ + ID: NewID("dib", "", ""), + LocalPort: 5000, + LocalAddress: "clown@address", + }}, + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: upstream local address is invalid: clown@address`, + }, + "workload/validate/disable-mesh/mgw": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + Image: "busybox", + EnvoyAdminPort: 19000, + IsMeshGateway: true, + Port: 8443, + DisableServiceMesh: true, + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: cannot disable service mesh and still run a mesh gateway`, + }, + "workload/validate/disable-mesh/expl dest": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + Image: "busybox", + EnvoyAdminPort: 19000, + Port: 8443, + DisableServiceMesh: true, + Upstreams: []*Upstream{{ + ID: NewID("gir", "", ""), + }}, + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: cannot disable service mesh and configure upstreams`, + }, + "workload/validate/disable-mesh/set admin port": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + Image: "busybox", + EnvoyAdminPort: 19000, + Port: 8443, + DisableServiceMesh: true, + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: cannot use envoy admin port without a service mesh`, + }, + "workload/validate/enable-mesh/unset admin port": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindDataplane, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + Image: "busybox", + Port: 8443, + }}, + }, + }, + }}, + }, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: envoy admin port is required`, + }, + + // TODO: OK: v2 mesh gateway port defaulting + + // TODO: collect tenancies from all places (cluster, initialconfigs, initialres, nodes, services, ...) + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + run(t, tc) + }) + } +} + +type testingT interface { + Helper() + Fatalf(format string, args ...interface{}) + require.TestingT +} + +var ignoreUnexportedTypes = []any{ + Cluster{}, + Images{}, + Node{}, + Workload{}, +} + +func assertDeepEqual[V any](t testingT, exp, got V, msgAndArgs ...any) { + t.Helper() + + if diff := cmp.Diff(exp, got, protocmp.Transform(), cmpopts.IgnoreUnexported(ignoreUnexportedTypes...)); diff != "" { + format := "assertion failed: values are not equal\n--- expected\n+++ actual\n%v" + args := []any{diff} + + if len(msgAndArgs) > 0 { + suffix, ok := msgAndArgs[0].(string) + require.True(t, ok) + require.NotEmpty(t, suffix) + format += "\n\nMessage: " + suffix + args = append(args, msgAndArgs[1:]...) + } + t.Fatalf(format, args...) + } +} diff --git a/testing/deployer/topology/default_versions.go b/testing/deployer/topology/default_versions.go index b35bb7ecfaa2..b29ff69e3d4f 100644 --- a/testing/deployer/topology/default_versions.go +++ b/testing/deployer/topology/default_versions.go @@ -5,9 +5,10 @@ package topology +//TODO @sarah.alsmiller figure out if we can delete this const ( - DefaultConsulImage = "hashicorp/consul:1.16.2" - DefaultConsulEnterpriseImage = "hashicorp/consul-enterprise:1.16.2-ent" - DefaultEnvoyImage = "envoyproxy/envoy:v1.26.4" - DefaultDataplaneImage = "hashicorp/consul-dataplane:1.2.2" + DefaultConsulCEImage = "hashicorp/consul:1.19.0" + DefaultConsulEnterpriseImage = "hashicorp/consul-enterprise:1.19.0-ent" + DefaultEnvoyImage = "envoyproxy/envoy:v1.28.5" + DefaultDataplaneImage = "hashicorp/consul-dataplane:1.5.0" ) diff --git a/testing/deployer/topology/ids.go b/testing/deployer/topology/ids.go index e1e109181bfd..b120a85856c2 100644 --- a/testing/deployer/topology/ids.go +++ b/testing/deployer/topology/ids.go @@ -9,41 +9,6 @@ import ( "github.com/hashicorp/consul/api" ) -type NodeServiceID struct { - Node string - Service string `json:",omitempty"` - Namespace string `json:",omitempty"` - Partition string `json:",omitempty"` -} - -func NewNodeServiceID(node, service, namespace, partition string) NodeServiceID { - id := NodeServiceID{ - Node: node, - Service: service, - Namespace: namespace, - Partition: partition, - } - id.Normalize() - return id -} - -func (id NodeServiceID) NodeID() NodeID { - return NewNodeID(id.Node, id.Partition) -} - -func (id NodeServiceID) ServiceID() ServiceID { - return NewServiceID(id.Service, id.Namespace, id.Partition) -} - -func (id *NodeServiceID) Normalize() { - id.Namespace = NamespaceOrDefault(id.Namespace) - id.Partition = PartitionOrDefault(id.Partition) -} - -func (id NodeServiceID) String() string { - return fmt.Sprintf("%s/%s/%s/%s", id.Partition, id.Node, id.Namespace, id.Service) -} - type NodeID struct { Name string `json:",omitempty"` Partition string `json:",omitempty"` @@ -74,14 +39,14 @@ func (id NodeID) TFString() string { return id.ACLString() } -type ServiceID struct { +type ID struct { Name string `json:",omitempty"` Namespace string `json:",omitempty"` Partition string `json:",omitempty"` } -func NewServiceID(name, namespace, partition string) ServiceID { - id := ServiceID{ +func NewID(name, namespace, partition string) ID { + id := ID{ Name: name, Namespace: namespace, Partition: partition, @@ -90,7 +55,7 @@ func NewServiceID(name, namespace, partition string) ServiceID { return id } -func (id ServiceID) Less(other ServiceID) bool { +func (id ID) Less(other ID) bool { if id.Partition != other.Partition { return id.Partition < other.Partition } @@ -100,32 +65,32 @@ func (id ServiceID) Less(other ServiceID) bool { return id.Name < other.Name } -func (id *ServiceID) Normalize() { +func (id *ID) Normalize() { id.Namespace = NamespaceOrDefault(id.Namespace) id.Partition = PartitionOrDefault(id.Partition) } -func (id ServiceID) String() string { +func (id ID) String() string { return fmt.Sprintf("%s/%s/%s", id.Partition, id.Namespace, id.Name) } -func (id ServiceID) ACLString() string { +func (id ID) ACLString() string { return fmt.Sprintf("%s--%s--%s", id.Partition, id.Namespace, id.Name) } -func (id ServiceID) TFString() string { +func (id ID) TFString() string { return id.ACLString() } -func (id ServiceID) PartitionOrDefault() string { +func (id ID) PartitionOrDefault() string { return PartitionOrDefault(id.Partition) } -func (id ServiceID) NamespaceOrDefault() string { +func (id ID) NamespaceOrDefault() string { return NamespaceOrDefault(id.Namespace) } -func (id ServiceID) QueryOptions() *api.QueryOptions { +func (id ID) QueryOptions() *api.QueryOptions { return &api.QueryOptions{ Partition: DefaultToEmpty(id.Partition), Namespace: DefaultToEmpty(id.Namespace), diff --git a/testing/deployer/topology/images.go b/testing/deployer/topology/images.go index 318154c5822c..5692e6bd78b6 100644 --- a/testing/deployer/topology/images.go +++ b/testing/deployer/topology/images.go @@ -5,6 +5,14 @@ package topology import ( "strings" + + goversion "github.com/hashicorp/go-version" +) + +var ( + MinVersionAgentTokenPartition = goversion.Must(goversion.NewVersion("v1.11.0")) + MinVersionPeering = goversion.Must(goversion.NewVersion("v1.13.0")) + MinVersionTLS = goversion.Must(goversion.NewVersion("v1.12.0")) ) type Images struct { @@ -13,6 +21,10 @@ type Images struct { Consul string `json:",omitempty"` // ConsulCE sets the CE image ConsulCE string `json:",omitempty"` + // consulVersion is the version part of Consul image, + // e.g., if Consul image is hashicorp/consul-enterprise:1.15.0-ent, + // consulVersion is 1.15.0-ent + consulVersion string // ConsulEnterprise sets the ent image ConsulEnterprise string `json:",omitempty"` Envoy string @@ -29,10 +41,7 @@ func (i Images) LocalDataplaneImage() string { tag = "latest" } - repo, name, ok := strings.Cut(img, "/") - if ok { - name = repo + "-" + name - } + name := strings.ReplaceAll(img, "/", "-") // ex: local/hashicorp-consul-dataplane:1.1.0 return "local/" + name + ":" + tag @@ -60,19 +69,8 @@ func spliceImageNamesAndTags(base1, base2, nameSuffix string) string { tag2 = "latest" } - repo1, name1, ok1 := strings.Cut(img1, "/") - repo2, name2, ok2 := strings.Cut(img2, "/") - - if ok1 { - name1 = repo1 + "-" + name1 - } else { - name1 = repo1 - } - if ok2 { - name2 = repo2 + "-" + name2 - } else { - name2 = repo2 - } + name1 := strings.ReplaceAll(img1, "/", "-") + name2 := strings.ReplaceAll(img2, "/", "-") if nameSuffix != "" { nameSuffix = "-" + nameSuffix @@ -107,9 +105,21 @@ func (i Images) ChooseConsul(enterprise bool) Images { } i.ConsulEnterprise = "" i.ConsulCE = "" + + // extract the version part of Consul + i.consulVersion = i.Consul[strings.Index(i.Consul, ":")+1:] return i } +// GreaterThanVersion compares the image version to a specified version +func (i Images) GreaterThanVersion(version *goversion.Version) bool { + if i.consulVersion == "local" { + return true + } + iVer := goversion.Must(goversion.NewVersion(i.consulVersion)) + return iVer.GreaterThanOrEqual(version) +} + func (i Images) OverrideWith(i2 Images) Images { if i2.Consul != "" { i.Consul = i2.Consul @@ -136,7 +146,7 @@ func (i Images) OverrideWith(i2 Images) Images { func DefaultImages() Images { return Images{ Consul: "", - ConsulCE: DefaultConsulImage, + ConsulCE: DefaultConsulCEImage, ConsulEnterprise: DefaultConsulEnterpriseImage, Envoy: DefaultEnvoyImage, Dataplane: DefaultDataplaneImage, diff --git a/testing/deployer/topology/naming_shim.go b/testing/deployer/topology/naming_shim.go new file mode 100644 index 000000000000..e307b3b6e2e8 --- /dev/null +++ b/testing/deployer/topology/naming_shim.go @@ -0,0 +1,43 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package topology + +// Deprecated: SortedWorkloads +func (n *Node) SortedServices() []*Workload { + return n.SortedWorkloads() +} + +// Deprecated: mapifyWorkloads +func mapifyServices(services []*Workload) map[ServiceID]*Workload { + return mapifyWorkloads(services) +} + +// Deprecated: WorkloadByID +func (c *Cluster) ServiceByID(nid NodeID, sid ServiceID) *Workload { + return c.WorkloadByID(nid, sid) +} + +// Deprecated: WorkloadsByID +func (c *Cluster) ServicesByID(sid ServiceID) []*Workload { + return c.WorkloadsByID(sid) +} + +// Deprecated: WorkloadByID +func (n *Node) ServiceByID(sid ServiceID) *Workload { + return n.WorkloadByID(sid) +} + +// Deprecated: Workload +type Service = Workload + +// Deprecated: ID +type ServiceID = ID + +// Deprecated: NewID +func NewServiceID(name, namespace, partition string) ID { + return NewID(name, namespace, partition) +} + +// Deprecated: +type Destination = Upstream diff --git a/testing/deployer/topology/relationships.go b/testing/deployer/topology/relationships.go index 8448451f3f07..b5fdc0b1f69c 100644 --- a/testing/deployer/topology/relationships.go +++ b/testing/deployer/topology/relationships.go @@ -10,22 +10,16 @@ import ( ) // ComputeRelationships will analyze a full topology and generate all of the -// downstream/upstream information for all of them. +// caller/upstream information for all of them. func (t *Topology) ComputeRelationships() []Relationship { var out []Relationship for _, cluster := range t.Clusters { for _, n := range cluster.Nodes { - for _, s := range n.Services { - for _, u := range s.Upstreams { + for _, w := range n.Workloads { + for _, us := range w.Upstreams { out = append(out, Relationship{ - Caller: s, - Upstream: u, - }) - } - for _, u := range s.ImpliedUpstreams { - out = append(out, Relationship{ - Caller: s, - Upstream: u, + Caller: w, + Upstream: us, }) } } @@ -39,20 +33,16 @@ func (t *Topology) ComputeRelationships() []Relationship { func RenderRelationships(ships []Relationship) string { var buf bytes.Buffer w := tabwriter.NewWriter(&buf, 0, 0, 3, ' ', tabwriter.Debug) - fmt.Fprintf(w, "DOWN\tnode\tservice\tport\tUP\tservice\t\n") + fmt.Fprintf(w, "CALLER\tnode\tservice\tport\tDEST\tservice\t\n") for _, r := range ships { - suffix := "" - if r.Upstream.Implied { - suffix = " (implied)" - } fmt.Fprintf(w, "%s\t%s\t%s\t%d\t%s\t%s\t\n", - r.downCluster(), + r.callingCluster(), r.Caller.Node.ID().String(), r.Caller.ID.String(), r.Upstream.LocalPort, - r.upCluster(), - r.Upstream.ID.String()+suffix, + r.upstreamCluster(), + r.Upstream.ID.String(), ) } fmt.Fprintf(w, "\t\t\t\t\t\t\n") @@ -62,31 +52,26 @@ func RenderRelationships(ships []Relationship) string { } type Relationship struct { - Caller *Service + Caller *Workload Upstream *Upstream } func (r Relationship) String() string { - suffix := "" - if r.Upstream.PortName != "" { - suffix = " port " + r.Upstream.PortName - } return fmt.Sprintf( - "%s on %s in %s via :%d => %s in %s%s", + "%s on %s in %s via :%d => %s in %s", r.Caller.ID.String(), r.Caller.Node.ID().String(), - r.downCluster(), + r.callingCluster(), r.Upstream.LocalPort, r.Upstream.ID.String(), - r.upCluster(), - suffix, + r.upstreamCluster(), ) } -func (r Relationship) downCluster() string { +func (r Relationship) callingCluster() string { return r.Caller.Node.Cluster } -func (r Relationship) upCluster() string { +func (r Relationship) upstreamCluster() string { return r.Upstream.Cluster } diff --git a/testing/deployer/topology/topology.go b/testing/deployer/topology/topology.go index b59045b564b4..a2feefca4b63 100644 --- a/testing/deployer/topology/topology.go +++ b/testing/deployer/topology/topology.go @@ -10,10 +10,8 @@ import ( "net/netip" "reflect" "sort" - "strings" "github.com/hashicorp/consul/api" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" "github.com/hashicorp/consul/proto-public/pbresource" ) @@ -35,6 +33,10 @@ type Topology struct { // Peerings defines the list of pairwise peerings that should be established // between clusters. Peerings []*Peering `json:",omitempty"` + + // NetworkAreas defines the list of pairwise network area that should be established + // between clusters. + NetworkAreas []*NetworkArea `json:",omitempty"` } func (t *Topology) DigestExposedProxyPort(netName string, proxyPort int) (bool, error) { @@ -100,6 +102,10 @@ type Config struct { // Peerings defines the list of pairwise peerings that should be established // between clusters. Peerings []*Peering + + // NetworkAreas defines the list of pairwise NetworkArea that should be established + // between clusters. + NetworkAreas []*NetworkArea } func (c *Config) Cluster(name string) *Cluster { @@ -240,14 +246,6 @@ type Cluster struct { // components. Enterprise bool `json:",omitempty"` - // Services is a forward declaration of V2 services. This goes in hand with - // the V2Services field on the Service (instance) struct. - // - // Use of this is optional. If you elect not to use it, then v2 Services - // definitions are inferred from the list of service instances defined on - // the nodes in this cluster. - Services map[ServiceID]*pbcatalog.Service `json:"omitempty"` - // Nodes is the definition of the nodes (agent-less and agent-ful). Nodes []*Node @@ -283,9 +281,12 @@ type Cluster struct { // Denormalized during compile. Peerings map[string]*PeerCluster `json:",omitempty"` - // EnableV2 activates V2 on the servers. If any node in the cluster needs - // V2 this will be turned on automatically. - EnableV2 bool `json:",omitempty"` + // Segments is a map of network segment name and the ports + Segments map[string]int + + // DisableGossipEncryption disables gossip encryption on the cluster + // Default is false to enable gossip encryption + DisableGossipEncryption bool `json:",omitempty"` } func (c *Cluster) inheritFromExisting(existing *Cluster) { @@ -321,7 +322,7 @@ func (c *Cluster) PartitionQueryOptionsList() []*api.QueryOptions { func (c *Cluster) ServerNodes() []*Node { var out []*Node for _, node := range c.SortedNodes() { - if node.Kind != NodeKindServer || node.Disabled { + if node.Kind != NodeKindServer || node.Disabled || node.IsNewServer { continue } out = append(out, node) @@ -357,12 +358,21 @@ func (c *Cluster) FirstServer() *Node { return nil } -func (c *Cluster) FirstClient() *Node { +// FirstClient returns the first client agent in the cluster. +// If segment is non-empty, it will return the first client agent in that segment. +func (c *Cluster) FirstClient(segment string) *Node { for _, node := range c.Nodes { if node.Kind != NodeKindClient || node.Disabled { continue } - return node + if segment == "" { + // return a client agent in default segment + return node + } else { + if node.Segment != nil && node.Segment.Name == segment { + return node + } + } } return nil } @@ -410,26 +420,18 @@ func (c *Cluster) SortedNodes() []*Node { return out } -func (c *Cluster) FindService(id NodeServiceID) *Service { - id.Normalize() - - nid := id.NodeID() - sid := id.ServiceID() - return c.ServiceByID(nid, sid) -} - -func (c *Cluster) ServiceByID(nid NodeID, sid ServiceID) *Service { - return c.NodeByID(nid).ServiceByID(sid) +func (c *Cluster) WorkloadByID(nid NodeID, sid ID) *Workload { + return c.NodeByID(nid).WorkloadByID(sid) } -func (c *Cluster) ServicesByID(sid ServiceID) []*Service { - sid.Normalize() +func (c *Cluster) WorkloadsByID(id ID) []*Workload { + id.Normalize() - var out []*Service + var out []*Workload for _, n := range c.Nodes { - for _, svc := range n.Services { - if svc.ID == sid { - out = append(out, svc) + for _, wrk := range n.Workloads { + if wrk.ID == id { + out = append(out, wrk) } } } @@ -481,18 +483,14 @@ const ( NodeKindDataplane NodeKind = "dataplane" ) -type NodeVersion string - -const ( - NodeVersionUnknown NodeVersion = "" - NodeVersionV1 NodeVersion = "v1" - NodeVersionV2 NodeVersion = "v2" -) +type NetworkSegment struct { + Name string + Port int +} // TODO: rename pod type Node struct { Kind NodeKind - Version NodeVersion Partition string // will be not empty Name string // logical name @@ -504,7 +502,7 @@ type Node struct { Disabled bool `json:",omitempty"` Addresses []*Address - Services []*Service + Workloads []*Workload // denormalized at topology compile Cluster string @@ -513,6 +511,9 @@ type Node struct { // computed at topology compile Index int + // IsNewServer is true if the server joins existing cluster + IsNewServer bool + // generated during network-and-tls TLSCertPrefix string `json:",omitempty"` @@ -523,6 +524,18 @@ type Node struct { // ports) and values initialized to zero until terraform creates the pods // and extracts the exposed port values from output variables. usedPorts map[int]int // keys are from compile / values are from terraform output vars + + // Meta is the node meta added to the node + Meta map[string]string + + // AutopilotConfig of the server agent + AutopilotConfig map[string]string + + // Network segment of the agent - applicable to client agent only + Segment *NetworkSegment + + // ExtraConfig is the extra config added to the node + ExtraConfig string } func (n *Node) DockerName() string { @@ -639,14 +652,6 @@ func (n *Node) PublicProxyPort() int { panic("node has no public network") } -func (n *Node) IsV2() bool { - return n.Version == NodeVersionV2 -} - -func (n *Node) IsV1() bool { - return !n.IsV2() -} - func (n *Node) IsServer() bool { return n.Kind == NodeKindServer } @@ -663,9 +668,9 @@ func (n *Node) IsDataplane() bool { return n.Kind == NodeKindDataplane } -func (n *Node) SortedServices() []*Service { - var out []*Service - out = append(out, n.Services...) +func (n *Node) SortedWorkloads() []*Workload { + var out []*Workload + out = append(out, n.Workloads...) sort.Slice(out, func(i, j int) bool { mi := out[i].IsMeshGateway mj := out[j].IsMeshGateway @@ -696,86 +701,29 @@ func (n *Node) DigestExposedPorts(ports map[int]int) bool { )) } } - for _, svc := range n.Services { + for _, svc := range n.Workloads { svc.DigestExposedPorts(ports) } return true } -func (n *Node) ServiceByID(sid ServiceID) *Service { - sid.Normalize() - for _, svc := range n.Services { - if svc.ID == sid { - return svc +func (n *Node) WorkloadByID(id ID) *Workload { + id.Normalize() + for _, wrk := range n.Workloads { + if wrk.ID == id { + return wrk } } - panic("service not found: " + sid.String()) -} - -type ServiceAndNode struct { - Service *Service - Node *Node -} - -// Protocol is a convenience function to use when authoring topology configs. -func Protocol(s string) (pbcatalog.Protocol, bool) { - switch strings.ToLower(s) { - case "tcp": - return pbcatalog.Protocol_PROTOCOL_TCP, true - case "http": - return pbcatalog.Protocol_PROTOCOL_HTTP, true - case "http2": - return pbcatalog.Protocol_PROTOCOL_HTTP2, true - case "grpc": - return pbcatalog.Protocol_PROTOCOL_GRPC, true - case "mesh": - return pbcatalog.Protocol_PROTOCOL_MESH, true - default: - return pbcatalog.Protocol_PROTOCOL_UNSPECIFIED, false - } + panic("workload not found: " + id.String()) } -type Port struct { - Number int - Protocol string `json:",omitempty"` - - // denormalized at topology compile - ActualProtocol pbcatalog.Protocol `json:",omitempty"` -} - -// TODO(rb): really this should now be called "workload" or "instance" -type Service struct { - ID ServiceID +type Workload struct { + ID ID Image string - // Port is the v1 single-port of this service. Port int `json:",omitempty"` - // Ports is the v2 multi-port list for this service. - // - // This only applies for multi-port (v2). - Ports map[string]*Port `json:",omitempty"` - - // V2Services contains service names (which are merged with the tenancy - // info from ID) to resolve services in the Services slice in the Cluster - // definition. - // - // If omitted it is inferred that the ID.Name field is the singular service - // for this workload. - // - // This only applies for multi-port (v2). - V2Services []string `json:",omitempty"` - - // WorkloadIdentity contains named WorkloadIdentity to assign to this - // workload. - // - // If omitted it is inferred that the ID.Name field is the singular - // identity for this workload. - // - // This only applies for multi-port (v2). - WorkloadIdentity string `json:",omitempty"` - Disabled bool `json:",omitempty"` // TODO // TODO: expose extra port here? @@ -793,225 +741,116 @@ type Service struct { Command []string `json:",omitempty"` // optional Env []string `json:",omitempty"` // optional - EnableTransparentProxy bool `json:",omitempty"` - DisableServiceMesh bool `json:",omitempty"` - IsMeshGateway bool `json:",omitempty"` - Upstreams []*Upstream `json:",omitempty"` - ImpliedUpstreams []*Upstream `json:",omitempty"` + DisableServiceMesh bool `json:",omitempty"` + IsMeshGateway bool `json:",omitempty"` + Upstreams []*Upstream `json:",omitempty"` // denormalized at topology compile - Node *Node `json:"-"` - NodeVersion NodeVersion `json:"-"` - Workload string `json:"-"` + Node *Node `json:"-"` } -func (s *Service) ExposedPort(name string) int { - if s.Node == nil { +func (w *Workload) ExposedPort() int { + if w.Node == nil { panic("ExposedPort cannot be called until after Compile") } - - var internalPort int - if name == "" { - internalPort = s.Port - } else { - port, ok := s.Ports[name] - if !ok { - panic("port with name " + name + " not present on service") - } - internalPort = port.Number - } - - return s.Node.ExposedPort(internalPort) + return w.Node.ExposedPort(w.Port) } -func (s *Service) PortOrDefault(name string) int { - if len(s.Ports) > 0 { - return s.Ports[name].Number - } - return s.Port +func (w *Workload) inheritFromExisting(existing *Workload) { + w.ExposedEnvoyAdminPort = existing.ExposedEnvoyAdminPort } -func (s *Service) IsV2() bool { - return s.NodeVersion == NodeVersionV2 -} - -func (s *Service) IsV1() bool { - return !s.IsV2() -} - -func (s *Service) inheritFromExisting(existing *Service) { - s.ExposedEnvoyAdminPort = existing.ExposedEnvoyAdminPort -} - -func (s *Service) ports() []int { +func (w *Workload) ports() []int { var out []int - if len(s.Ports) > 0 { - seen := make(map[int]struct{}) - for _, port := range s.Ports { - if _, ok := seen[port.Number]; !ok { - // It's totally fine to expose the same port twice in a workload. - seen[port.Number] = struct{}{} - out = append(out, port.Number) - } - } - } else if s.Port > 0 { - out = append(out, s.Port) + if w.Port > 0 { + out = append(out, w.Port) } - if s.EnvoyAdminPort > 0 { - out = append(out, s.EnvoyAdminPort) + if w.EnvoyAdminPort > 0 { + out = append(out, w.EnvoyAdminPort) } - if s.EnvoyPublicListenerPort > 0 { - out = append(out, s.EnvoyPublicListenerPort) + if w.EnvoyPublicListenerPort > 0 { + out = append(out, w.EnvoyPublicListenerPort) } - for _, u := range s.Upstreams { - if u.LocalPort > 0 { - out = append(out, u.LocalPort) + for _, us := range w.Upstreams { + if us.LocalPort > 0 { + out = append(out, us.LocalPort) } } return out } -func (s *Service) HasCheck() bool { - return s.CheckTCP != "" || s.CheckHTTP != "" +func (w *Workload) HasCheck() bool { + return w.CheckTCP != "" || w.CheckHTTP != "" } -func (s *Service) DigestExposedPorts(ports map[int]int) { - if s.EnvoyAdminPort > 0 { - s.ExposedEnvoyAdminPort = ports[s.EnvoyAdminPort] +func (w *Workload) DigestExposedPorts(ports map[int]int) { + if w.EnvoyAdminPort > 0 { + w.ExposedEnvoyAdminPort = ports[w.EnvoyAdminPort] } else { - s.ExposedEnvoyAdminPort = 0 + w.ExposedEnvoyAdminPort = 0 } } -func (s *Service) Validate() error { - if s.ID.Name == "" { +// Validate checks a bunch of stuff intrinsic to the definition of the workload +// itself. +func (w *Workload) Validate() error { + if w.ID.Name == "" { return fmt.Errorf("service name is required") } - if s.Image == "" && !s.IsMeshGateway { + if w.Image == "" && !w.IsMeshGateway { return fmt.Errorf("service image is required") } - if s.IsV2() { - if len(s.Ports) > 0 && s.Port > 0 { - return fmt.Errorf("cannot specify both singleport and multiport on service in v2") - } - if s.Port > 0 { - s.Ports = map[string]*Port{ - "legacy": { - Number: s.Port, - Protocol: "tcp", - }, - } - s.Port = 0 - } - - if !s.DisableServiceMesh && s.EnvoyPublicListenerPort > 0 { - s.Ports["mesh"] = &Port{ - Number: s.EnvoyPublicListenerPort, - Protocol: "mesh", - } - } - - for name, port := range s.Ports { - if port == nil { - return fmt.Errorf("cannot be nil") - } - if port.Number <= 0 { - return fmt.Errorf("service has invalid port number %q", name) - } - if port.ActualProtocol != pbcatalog.Protocol_PROTOCOL_UNSPECIFIED { - return fmt.Errorf("user cannot specify ActualProtocol field") - } - proto, valid := Protocol(port.Protocol) - if !valid { - return fmt.Errorf("service has invalid port protocol %q", port.Protocol) - } - port.ActualProtocol = proto - } - } else { - if len(s.Ports) > 0 { - return fmt.Errorf("cannot specify mulitport on service in v1") - } - if s.Port <= 0 { - return fmt.Errorf("service has invalid port") - } - if s.EnableTransparentProxy { - return fmt.Errorf("tproxy does not work with v1 yet") - } + if w.Port <= 0 { + return fmt.Errorf("service has invalid port") } - if s.DisableServiceMesh && s.IsMeshGateway { + if w.DisableServiceMesh && w.IsMeshGateway { return fmt.Errorf("cannot disable service mesh and still run a mesh gateway") } - if s.DisableServiceMesh && len(s.Upstreams) > 0 { + if w.DisableServiceMesh && len(w.Upstreams) > 0 { return fmt.Errorf("cannot disable service mesh and configure upstreams") } - if s.DisableServiceMesh && len(s.ImpliedUpstreams) > 0 { - return fmt.Errorf("cannot disable service mesh and configure implied upstreams") - } - if s.DisableServiceMesh && s.EnableTransparentProxy { - return fmt.Errorf("cannot disable service mesh and activate tproxy") - } - if s.DisableServiceMesh { - if s.EnvoyAdminPort != 0 { + if w.DisableServiceMesh { + if w.EnvoyAdminPort != 0 { return fmt.Errorf("cannot use envoy admin port without a service mesh") } } else { - if s.EnvoyAdminPort <= 0 { + if w.EnvoyAdminPort <= 0 { return fmt.Errorf("envoy admin port is required") } } - for _, u := range s.Upstreams { - if u.ID.Name == "" { + for _, us := range w.Upstreams { + if us.ID.Name == "" { return fmt.Errorf("upstream service name is required") } - if u.LocalPort <= 0 { + if us.LocalPort <= 0 { return fmt.Errorf("upstream local port is required") } - if u.LocalAddress != "" { - ip := net.ParseIP(u.LocalAddress) + if us.LocalAddress != "" { + ip := net.ParseIP(us.LocalAddress) if ip == nil { - return fmt.Errorf("upstream local address is invalid: %s", u.LocalAddress) + return fmt.Errorf("upstream local address is invalid: %s", us.LocalAddress) } } - if u.Implied { - return fmt.Errorf("implied field cannot be set") - } - } - for _, u := range s.ImpliedUpstreams { - if u.ID.Name == "" { - return fmt.Errorf("implied upstream service name is required") - } - if u.LocalPort > 0 { - return fmt.Errorf("implied upstream local port cannot be set") - } - if u.LocalAddress != "" { - return fmt.Errorf("implied upstream local address cannot be set") - } } return nil } type Upstream struct { - ID ServiceID + ID ID LocalAddress string `json:",omitempty"` // defaults to 127.0.0.1 LocalPort int Peer string `json:",omitempty"` - // PortName is the named port of this Upstream to route traffic to. - // - // This only applies for multi-port (v2). - PortName string `json:",omitempty"` // TODO: what about mesh gateway mode overrides? // computed at topology compile - Cluster string `json:",omitempty"` - Peering *PeerCluster `json:",omitempty"` // this will have Link!=nil - Implied bool `json:",omitempty"` - VirtualPort uint32 `json:",omitempty"` + Cluster string `json:",omitempty"` + Peering *PeerCluster `json:",omitempty"` // this will have Link!=nil } type Peering struct { @@ -1019,6 +858,13 @@ type Peering struct { Accepting PeerCluster } +// NetworkArea - a pair of clusters that are peered together +// through network area. PeerCluster type is reused here. +type NetworkArea struct { + Primary PeerCluster + Secondary PeerCluster +} + type PeerCluster struct { Name string Partition string diff --git a/testing/deployer/update-latest-versions.sh b/testing/deployer/update-latest-versions.sh index 16f023142274..10a7e1bfffeb 100755 --- a/testing/deployer/update-latest-versions.sh +++ b/testing/deployer/update-latest-versions.sh @@ -8,7 +8,7 @@ cd "$(dirname "$0")" ### # This script will update the default image names to the latest released versions of -# Consul, Consul Enterprise, and Consul Dataplane. +# Consul CE, Consul Enterprise, and Consul Dataplane. # # For Envoy, it will interrogate the latest version of Consul for it's maximum supported # Envoy version and use that. @@ -32,7 +32,9 @@ docker run -d --name consul-envoy-check "$consul_latest" envoy_version="" while true; do # We have to retry in case consul doesn't fully start up before we get here. + set +e envoy_version="$(docker exec consul-envoy-check sh -c 'wget -q localhost:8500/v1/agent/self -O -' | jq -r '.xDS.SupportedProxies.envoy[0]')" + set -e if [[ -n "$envoy_version" ]]; then break fi @@ -48,7 +50,7 @@ cat > topology/default_versions.go <= 2 is + // no longer valid. + + for _, server := range out.Servers { + if server.Leader { + return + } + } + r.Fatalf("No leader") + }) +} + // WaitUntilNoLeader ensures no leader is present, useful for testing lost leadership. func WaitUntilNoLeader(t *testing.T, rpc rpcFn, dc string, options ...waitOption) { t.Helper() @@ -108,6 +139,7 @@ func WaitForTestAgent(t *testing.T, rpc rpcFn, dc string, options ...waitOption) var checks structs.IndexedHealthChecks retry.Run(t, func(r *retry.R) { + r.Helper() dcReq := &structs.DCSpecificRequest{ Datacenter: dc, QueryOptions: structs.QueryOptions{Token: flat.Token}, diff --git a/tlsutil/config.go b/tlsutil/config.go index 5cba2597f19d..2e2adcad98c2 100644 --- a/tlsutil/config.go +++ b/tlsutil/config.go @@ -183,6 +183,18 @@ type protocolConfig struct { useAutoCert bool } +// ConfiguratorIface is the interface for the Configurator +type ConfiguratorIface interface { + Base() Config + Cert() *tls.Certificate + ManualCAPems() []string + + VerifyIncomingRPC() bool + VerifyServerHostname() bool +} + +var _ ConfiguratorIface = (*Configurator)(nil) + // Configurator provides tls.Config and net.Dial wrappers to enable TLS for // clients and servers, for internal RPC, and external gRPC and HTTPS connections. // diff --git a/tlsutil/config_test.go b/tlsutil/config_test.go index bc2ee36068a4..3721a75ff5b6 100644 --- a/tlsutil/config_test.go +++ b/tlsutil/config_test.go @@ -1484,7 +1484,7 @@ func TestConfigurator_AutoEncryptCert(t *testing.T) { cert, err = loadKeyPair("../test/key/ourdomain.cer", "../test/key/ourdomain.key") require.NoError(t, err) c.autoTLS.cert = cert - require.Equal(t, int64(4820915609), c.AutoEncryptCert().NotAfter.Unix()) + require.Equal(t, int64(4852545616), c.AutoEncryptCert().NotAfter.Unix()) } func TestConfigurator_AuthorizeInternalRPCServerConn(t *testing.T) { diff --git a/tlsutil/mock.go b/tlsutil/mock.go new file mode 100644 index 000000000000..55e98eec2669 --- /dev/null +++ b/tlsutil/mock.go @@ -0,0 +1,37 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package tlsutil + +import "crypto/tls" + +var _ ConfiguratorIface = (*MockConfigurator)(nil) + +// MockConfigurator is used for mocking the ConfiguratorIface in testing +type MockConfigurator struct { + BaseConfig Config + TlsCert *tls.Certificate + ManualCAPemsArr []string + VerifyIncomingRPCBool bool + VerifyServerHostnameBool bool +} + +func (m MockConfigurator) Base() Config { + return m.BaseConfig +} + +func (m MockConfigurator) Cert() *tls.Certificate { + return m.TlsCert +} + +func (m MockConfigurator) ManualCAPems() []string { + return m.ManualCAPemsArr +} + +func (m MockConfigurator) VerifyIncomingRPC() bool { + return m.VerifyIncomingRPCBool +} + +func (m MockConfigurator) VerifyServerHostname() bool { + return m.VerifyServerHostnameBool +} diff --git a/troubleshoot/go.mod b/troubleshoot/go.mod index 2da61ef3d885..753fd9e09955 100644 --- a/troubleshoot/go.mod +++ b/troubleshoot/go.mod @@ -5,6 +5,8 @@ go 1.19 replace ( github.com/hashicorp/consul/api => ../api github.com/hashicorp/consul/envoyextensions => ../envoyextensions + github.com/hashicorp/consul/proto-public => ../proto-public + github.com/hashicorp/consul/sdk => ../sdk ) exclude ( @@ -12,13 +14,20 @@ exclude ( github.com/hashicorp/go-msgpack v1.1.6 // contains retractions but same as v1.1.5 ) +retract ( + v0.6.4 // tag was mutated + v0.6.2 // tag has incorrect line of deps + v0.6.1 // tag has incorrect line of deps +) + require ( - github.com/envoyproxy/go-control-plane v0.11.1 + github.com/envoyproxy/go-control-plane v0.12.0 github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e - github.com/hashicorp/consul/api v1.26.1 - github.com/hashicorp/consul/envoyextensions v0.5.1 - github.com/stretchr/testify v1.8.3 - google.golang.org/protobuf v1.30.0 + github.com/hashicorp/consul/api v1.29.4 + github.com/hashicorp/consul/envoyextensions v0.7.3 + github.com/hashicorp/consul/sdk v0.16.1 + github.com/stretchr/testify v1.8.4 + google.golang.org/protobuf v1.33.0 ) require ( @@ -26,35 +35,34 @@ require ( github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.1 // indirect - github.com/fatih/color v1.14.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.2.1 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/serf v0.10.1 // indirect - github.com/kr/pretty v0.3.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect - go.opentelemetry.io/proto/otlp v0.19.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e // indirect - google.golang.org/grpc v1.56.3 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect + google.golang.org/grpc v1.58.3 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/troubleshoot/go.sum b/troubleshoot/go.sum index b487eb60a5f9..eb39bb30face 100644 --- a/troubleshoot/go.sum +++ b/troubleshoot/go.sum @@ -1,45 +1,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= @@ -53,50 +18,29 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= -github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e h1:g8euodkL4GdSpVAjfzhssb07KgVmOUqyF4QOmwFumTs= github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e/go.mod h1:/NGEcKqwNq3HAS2vCqHfsPx9sJZbkiNQ6dGx9gTE/NA= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.1 h1:kt9FtLiooDc0vbwTLhdg3dyNX1K9Qwa1EK9LcD4jVUQ= -github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -104,65 +48,19 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/hashicorp/consul/sdk v0.15.0 h1:2qK9nDrr4tiJKRoxPGhm6B7xJjLVIQqkjiab2M4aKjU= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -189,10 +87,10 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -201,23 +99,16 @@ github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -231,8 +122,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= @@ -254,6 +145,7 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -266,134 +158,59 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1: github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -401,217 +218,65 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= -google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e h1:AZX1ra8YbFMSb7+1pI8S9v4rrgRR7jU1FmuFSSjTVcQ= -google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e h1:NumxXLPfHSndr3wBBdeKiVHjGVFzi9RX2HwwQke94iY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= +google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= -google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/troubleshoot/ports/hostport.go b/troubleshoot/ports/hostport.go new file mode 100644 index 000000000000..1d09e34f0400 --- /dev/null +++ b/troubleshoot/ports/hostport.go @@ -0,0 +1,9 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package ports + +type hostPort struct { + host string + port string +} diff --git a/troubleshoot/ports/troubleshoot_ports.go b/troubleshoot/ports/troubleshoot_ports.go new file mode 100644 index 000000000000..ec1bfda5963f --- /dev/null +++ b/troubleshoot/ports/troubleshoot_ports.go @@ -0,0 +1,53 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package ports + +import ( + "fmt" + "strings" +) + +func TroubleshootDefaultPorts(host string) []string { + // Source - https://developer.hashicorp.com/consul/docs/install/ports + ports := []string{"8600", "8500", "8501", "8502", "8503", "8301", "8302", "8300"} + return troubleshootRun(ports, host) +} + +func TroubleShootCustomPorts(host string, ports string) []string { + portsArr := strings.Split(ports, ",") + return troubleshootRun(portsArr, host) +} + +func troubleshootRun(ports []string, host string) []string { + + resultsChannel := make(chan string) + defer close(resultsChannel) + + var counter = 0 + + for _, port := range ports { + counter += 1 + tcpTroubleShoot := troubleShootTcp{} + port := port + go func() { + err := tcpTroubleShoot.dialPort(&hostPort{host: host, port: port}) + var res string + if err != nil { + res = fmt.Sprintf("TCP: Port %s on %s is closed, unreachable, or the connection timed out.\n", port, host) + } else { + // If no error occurs, the connection was successful, and the port is open. + res = fmt.Sprintf("TCP: Port %s on %s is open.\n", port, host) + } + resultsChannel <- res + }() + } + + resultsArr := make([]string, counter) + for itr := 0; itr < counter; itr++ { + res := <-resultsChannel + fmt.Print(res) + resultsArr[itr] = res + } + return resultsArr +} diff --git a/troubleshoot/ports/troubleshoot_ports_test.go b/troubleshoot/ports/troubleshoot_ports_test.go new file mode 100644 index 000000000000..2358467e6853 --- /dev/null +++ b/troubleshoot/ports/troubleshoot_ports_test.go @@ -0,0 +1,55 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package ports + +import ( + "fmt" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/stretchr/testify/require" + "strconv" + "strings" + "testing" +) + +func TestTroubleShootCustom_Ports(t *testing.T) { + // Create a test Consul server + srv1, err := testutil.NewTestServerConfigT(t, nil) + if err != nil { + t.Fatal(err) + } + + results := TroubleShootCustomPorts("127.0.0.1", strings.Join([]string{ + strconv.Itoa(srv1.Config.Ports.HTTP), + strconv.Itoa(srv1.Config.Ports.DNS), + strconv.Itoa(srv1.Config.Ports.HTTPS), + strconv.Itoa(srv1.Config.Ports.GRPC), + strconv.Itoa(srv1.Config.Ports.SerfLan), + strconv.Itoa(srv1.Config.Ports.SerfWan), + strconv.Itoa(srv1.Config.Ports.Server)}, ",")) + expectedResults := []string{ + fmt.Sprintf("TCP: Port %s on 127.0.0.1 is open.\n", strconv.Itoa(srv1.Config.Ports.HTTP)), + fmt.Sprintf("TCP: Port %s on 127.0.0.1 is open.\n", strconv.Itoa(srv1.Config.Ports.GRPC)), + fmt.Sprintf("TCP: Port %s on 127.0.0.1 is open.\n", strconv.Itoa(srv1.Config.Ports.HTTPS)), + fmt.Sprintf("TCP: Port %s on 127.0.0.1 is open.\n", strconv.Itoa(srv1.Config.Ports.SerfLan)), + fmt.Sprintf("TCP: Port %s on 127.0.0.1 is open.\n", strconv.Itoa(srv1.Config.Ports.SerfWan)), + fmt.Sprintf("TCP: Port %s on 127.0.0.1 is open.\n", strconv.Itoa(srv1.Config.Ports.DNS)), + fmt.Sprintf("TCP: Port %s on 127.0.0.1 is open.\n", strconv.Itoa(srv1.Config.Ports.Server)), + } + for _, res := range expectedResults { + require.Contains(t, results, res) + } + defer srv1.Stop() +} + +func TestTroubleShootCustom_Ports_Not_Reachable(t *testing.T) { + results := TroubleShootCustomPorts("127.0.0.1", strings.Join([]string{"8777", "8888"}, ",")) + + expectedResults := []string{ + fmt.Sprintf("TCP: Port 8777 on 127.0.0.1 is closed, unreachable, or the connection timed out.\n"), + fmt.Sprintf("TCP: Port 8888 on 127.0.0.1 is closed, unreachable, or the connection timed out.\n"), + } + for _, res := range expectedResults { + require.Contains(t, results, res) + } +} diff --git a/troubleshoot/ports/troubleshoot_protocol.go b/troubleshoot/ports/troubleshoot_protocol.go new file mode 100644 index 000000000000..e0299adba7dd --- /dev/null +++ b/troubleshoot/ports/troubleshoot_protocol.go @@ -0,0 +1,8 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package ports + +type troubleShootProtocol interface { + dialPort(hostPort *hostPort) error +} diff --git a/troubleshoot/ports/troubleshoot_tcp.go b/troubleshoot/ports/troubleshoot_tcp.go new file mode 100644 index 000000000000..8ade64dfbed0 --- /dev/null +++ b/troubleshoot/ports/troubleshoot_tcp.go @@ -0,0 +1,24 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package ports + +import ( + "net" + "time" +) + +type troubleShootTcp struct { +} + +func (tcp *troubleShootTcp) dialPort(hostPort *hostPort) error { + address := net.JoinHostPort(hostPort.host, hostPort.port) + + // Attempt to establish a TCP connection with a timeout. + conn, err := net.DialTimeout("tcp", address, 5*time.Second) + if err != nil { + return err + } + defer conn.Close() + return nil +} diff --git a/troubleshoot/proxy/testdata/config.json b/troubleshoot/proxy/testdata/config.json index d3db1c09d026..bee06ec0253e 100644 --- a/troubleshoot/proxy/testdata/config.json +++ b/troubleshoot/proxy/testdata/config.json @@ -1711,7 +1711,14 @@ "name": "consul-dataplane", "type": "STATIC", "connect_timeout": "1s", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "load_assignment": { "cluster_name": "consul-dataplane", "endpoints": [ @@ -1761,7 +1768,15 @@ } }, "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -1880,7 +1895,14 @@ "name": "consul-dataplane", "type": "STATIC", "connect_timeout": "1s", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "load_assignment": { "cluster_name": "consul-dataplane", "endpoints": [ @@ -1940,9 +1962,12 @@ "trusted_ca": { "inline_string": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBCzAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktYWRk\najM4YWsuY29uc3VsLmNhLjc4MzhiNGJkLmNvbnN1bDAeFw0yMzAxMjcxNzI2MjVa\nFw0zMzAxMjQxNzI2MjVaMDExLzAtBgNVBAMTJnByaS1hZGRqMzhhay5jb25zdWwu\nY2EuNzgzOGI0YmQuY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkCV2\nZ+2bi4uRGjiUye4K5CO8IhF/7nqsTFG+f4dRio7JLOkAUDzlGLKbH+mLqce0YLzb\nS9hpIJjSk3ge+q8EPaOBvTCBujAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\nAwEB/zApBgNVHQ4EIgQgUYvu/s5FtHrW/Ilzfbe1QgkGOEKJjXvn7AiEQ8WS+pIw\nKwYDVR0jBCQwIoAgUYvu/s5FtHrW/Ilzfbe1QgkGOEKJjXvn7AiEQ8WS+pIwPwYD\nVR0RBDgwNoY0c3BpZmZlOi8vNzgzOGI0YmQtNThiMy04MTE3LTNkZjEtNjA1ODQ5\nMTA1NDFiLmNvbnN1bDAKBggqhkjOPQQDAgNHADBEAiAv+zXWDgQsI9dPeedNCvI6\ntSP0bFU6q1LiL2b6PPR55wIgftf6sS3lzp5dSwhm7VgksQRKzAV7ixmXP0nMWdwT\nbQo=\n-----END CERTIFICATE-----\n" }, - "match_subject_alt_names": [ + "match_typed_subject_alt_names": [ { - "exact": "spiffe://7838b4bd-58b3-8117-3df1-60584910541b.consul/ns/default/dc/dc1/svc/backend" + "san_type": "URI", + "matcher": { + "exact": "spiffe://7838b4bd-58b3-8117-3df1-60584910541b.consul/ns/default/dc/dc1/svc/backend" + } } ] } @@ -1992,9 +2017,12 @@ "trusted_ca": { "inline_string": "-----BEGIN CERTIFICATE-----\nMIICDjCCAbWgAwIBAgIBCzAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktYWRk\najM4YWsuY29uc3VsLmNhLjc4MzhiNGJkLmNvbnN1bDAeFw0yMzAxMjcxNzI2MjVa\nFw0zMzAxMjQxNzI2MjVaMDExLzAtBgNVBAMTJnByaS1hZGRqMzhhay5jb25zdWwu\nY2EuNzgzOGI0YmQuY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkCV2\nZ+2bi4uRGjiUye4K5CO8IhF/7nqsTFG+f4dRio7JLOkAUDzlGLKbH+mLqce0YLzb\nS9hpIJjSk3ge+q8EPaOBvTCBujAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\nAwEB/zApBgNVHQ4EIgQgUYvu/s5FtHrW/Ilzfbe1QgkGOEKJjXvn7AiEQ8WS+pIw\nKwYDVR0jBCQwIoAgUYvu/s5FtHrW/Ilzfbe1QgkGOEKJjXvn7AiEQ8WS+pIwPwYD\nVR0RBDgwNoY0c3BpZmZlOi8vNzgzOGI0YmQtNThiMy04MTE3LTNkZjEtNjA1ODQ5\nMTA1NDFiLmNvbnN1bDAKBggqhkjOPQQDAgNHADBEAiAv+zXWDgQsI9dPeedNCvI6\ntSP0bFU6q1LiL2b6PPR55wIgftf6sS3lzp5dSwhm7VgksQRKzAV7ixmXP0nMWdwT\nbQo=\n-----END CERTIFICATE-----\n" }, - "match_subject_alt_names": [ + "match_typed_subject_alt_names": [ { - "exact": "spiffe://7838b4bd-58b3-8117-3df1-60584910541b.consul/ns/default/dc/dc1/svc/backend2" + "san_type": "URI", + "matcher": { + "exact": "spiffe://7838b4bd-58b3-8117-3df1-60584910541b.consul/ns/default/dc/dc1/svc/backend" + } } ] } diff --git a/troubleshoot/proxy/testdata/upstreams/config.json b/troubleshoot/proxy/testdata/upstreams/config.json index 735e329597f8..62a8d2978764 100644 --- a/troubleshoot/proxy/testdata/upstreams/config.json +++ b/troubleshoot/proxy/testdata/upstreams/config.json @@ -174,8 +174,7 @@ "name": "backend2.default.dc1.internal.domain.consul", "weight": 5000 } - ], - "total_weight": 10000 + ] } } } diff --git a/ui/.yarnrc b/ui/.yarnrc new file mode 100644 index 000000000000..19bac4f6d1a8 --- /dev/null +++ b/ui/.yarnrc @@ -0,0 +1 @@ +registry: https://registry.npmjs.org/ diff --git a/ui/package.json b/ui/package.json index 7ed39b1595ac..2fe24dda1693 100644 --- a/ui/package.json +++ b/ui/package.json @@ -11,7 +11,7 @@ "scripts": { "doc:toc": "doctoc README.md", "compliance": "npm-run-all compliance:*", - "compliance:licenses": "license-checker --summary --onlyAllow 'Python-2.0;Apache*;Apache License, Version 2.0;Apache-2.0;Apache 2.0;Artistic-2.0;BSD;BSD-3-Clause;CC-BY-3.0;CC-BY-4.0;CC0-1.0;ISC;MIT;MPL-2.0;Public Domain;Unicode-TOU;Unlicense;WTFPL' --excludePackages 'consul-ui@2.2.0;consul-acls@0.1.0;consul-lock-sessions@0.1.0;consul-partitions@0.1.0;consul-nspaces@0.1.0;consul-hcp@0.1.0;consul-peerings@0.1.0'" + "compliance:licenses": "license-checker --summary --onlyAllow 'Python-2.0;Apache*;Apache License, Version 2.0;Apache-2.0;Apache 2.0;Artistic-2.0;BSD;BSD-3-Clause;CC-BY-3.0;CC-BY-4.0;CC0-1.0;ISC;MIT;MPL-2.0;Public Domain;Unicode-TOU;Unlicense;WTFPL' --excludePackages 'consul-ui@2.2.0;consul-acls@0.1.0;consul-lock-sessions@0.1.0;consul-partitions@0.1.0;consul-nspaces@0.1.0;consul-peerings@0.1.0'" }, "devDependencies": { @@ -21,7 +21,12 @@ }, "resolutions": { "xmlhttprequest-ssl": "^1.6.3", - "ember-basic-dropdown": "3.0.21" + "ember-basic-dropdown": "3.0.21", + "glob": "7.2.3", + "braces": "^3.0.0", + "markdown-it": "^12.3.2", + "codemirror": "5.58.2", + "ansi-html": "0.0.8" }, "engines": { "node": "18" diff --git a/ui/packages/consul-hcp/app/components/consul/hcp/home/index.hbs b/ui/packages/consul-hcp/app/components/consul/hcp/home/index.hbs deleted file mode 100644 index 5f8dfc5b5510..000000000000 --- a/ui/packages/consul-hcp/app/components/consul/hcp/home/index.hbs +++ /dev/null @@ -1,16 +0,0 @@ -{{! - Copyright (c) HashiCorp, Inc. - SPDX-License-Identifier: BUSL-1.1 -}} - -{{#let @list (env "CONSUL_HCP_URL") as |SNL hcpUrl|}} - {{log hcpUrl}} - {{#if (and SNL hcpUrl)}} - - {{/if}} -{{/let}} \ No newline at end of file diff --git a/ui/packages/consul-hcp/app/components/consul/hcp/home/index.test.js b/ui/packages/consul-hcp/app/components/consul/hcp/home/index.test.js deleted file mode 100644 index 0ffb7c48583f..000000000000 --- a/ui/packages/consul-hcp/app/components/consul/hcp/home/index.test.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; -import hbs from 'htmlbars-inline-precompile'; - -import ConsulHcpHome from 'consul-ui/components/consul/hcp/home'; - -module('Integration | Component | consul hcp home', function(hooks) { - setupRenderingTest(hooks); - - test('it prints the value of CONSUL_HCP_URL', async function(assert) { - // temporary registration until we are running as separate applications - this.owner.register( - 'component:consul/hcp/home', - ConsulHcpHome - ); - // - - const Helper = this.owner.resolveRegistration('helper:env'); - this.owner.register( - 'helper:env', - class extends Helper { - compute([name, def]) { - switch(name) { - case 'CONSUL_HCP_URL': - return 'http://hcp'; - } - return super.compute(...arguments); - } - } - ); - - await render(hbs` - - - - `); - - assert.dom('[data-test-back-to-hcp]').isVisible(); - assert.dom('a').hasAttribute('href', 'http://hcp'); - - }); - - test('it does not output the Back to HCP link if CONSUL_HCP_URL is not present', async function(assert) { - // temporary registration until we are running as separate applications - this.owner.register( - 'component:consul/hcp/home', - ConsulHcpHome - ); - // - - const Helper = this.owner.resolveRegistration('helper:env'); - this.owner.register( - 'helper:env', - class extends Helper { - compute([name, def]) { - switch(name) { - case 'CONSUL_HCP_URL': - return undefined; - } - return super.compute(...arguments); - } - } - ); - - await render(hbs` - - - - `); - - assert.dom('[data-test-back-to-hcp]').doesNotExist(); - assert.dom('a').doesNotExist(); - }); -}); diff --git a/ui/packages/consul-hcp/package.json b/ui/packages/consul-hcp/package.json deleted file mode 100644 index bb35cc6f6e11..000000000000 --- a/ui/packages/consul-hcp/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "consul-hcp", - "version": "0.1.0", - "private": true -} diff --git a/ui/packages/consul-hcp/vendor/consul-hcp/routes.js b/ui/packages/consul-hcp/vendor/consul-hcp/routes.js deleted file mode 100644 index ab573dea56ad..000000000000 --- a/ui/packages/consul-hcp/vendor/consul-hcp/routes.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -(routes => routes({ - dc: { - show: null - }, -}))( - (json, data = (typeof document !== 'undefined' ? document.currentScript.dataset : module.exports)) => { - data[`routes`] = JSON.stringify(json); - } -); diff --git a/ui/packages/consul-hcp/vendor/consul-hcp/services.js b/ui/packages/consul-hcp/vendor/consul-hcp/services.js deleted file mode 100644 index d1c7820f7da5..000000000000 --- a/ui/packages/consul-hcp/vendor/consul-hcp/services.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -(services => services({ - 'component:consul/hcp/home': { - class: 'consul-ui/components/consul/hcp/home', - }, -}))( - (json, data = (typeof document !== 'undefined' ? document.currentScript.dataset : module.exports)) => { - data[`services`] = JSON.stringify(json); - } -); diff --git a/ui/packages/consul-nspaces/app/components/consul/nspace/selector/index.hbs b/ui/packages/consul-nspaces/app/components/consul/nspace/selector/index.hbs index 5dec44b8f919..6c126b72181f 100644 --- a/ui/packages/consul-nspaces/app/components/consul/nspace/selector/index.hbs +++ b/ui/packages/consul-nspaces/app/components/consul/nspace/selector/index.hbs @@ -4,57 +4,57 @@ }} {{#if (and (can "use nspaces") (can "choose nspaces"))}} - {{#let @list (if @nspace (hash Name=@nspace) (hash Name="default")) (is-href "dc.nspaces" @dc.Name) as |SNL nspace isManaging| }} - {{t "components.hashicorp-consul.side-nav.nspaces.title"}} + {{t + "components.hashicorp-consul.side-nav.nspaces.title" + }} - + + + - {{item.Name}} - + {{Selector.item.Name}} + {{/let}} {{/if}} \ No newline at end of file diff --git a/ui/packages/consul-partitions/app/components/consul/partition/selector/index.hbs b/ui/packages/consul-partitions/app/components/consul/partition/selector/index.hbs index 9031fd0e8fff..0c59e93cc0c1 100644 --- a/ui/packages/consul-partitions/app/components/consul/partition/selector/index.hbs +++ b/ui/packages/consul-partitions/app/components/consul/partition/selector/index.hbs @@ -10,44 +10,49 @@ (can "choose partitions" dc=@dc) as |SNL partition isManaging canChoose| }} - - {{t "components.hashicorp-consul.side-nav.partitions.title"}} + {{t + "components.hashicorp-consul.side-nav.partitions.title" + }} + + + {{#if canChoose}} - - {{item.Name}} - + {{Selector.item.Name}} + {{/if}} -{{/let}} +{{/let}} \ No newline at end of file diff --git a/ui/packages/consul-peerings/app/templates/dc/peers/show/imported.hbs b/ui/packages/consul-peerings/app/templates/dc/peers/show/imported.hbs index c7d32b3b16db..763306cb70a4 100644 --- a/ui/packages/consul-peerings/app/templates/dc/peers/show/imported.hbs +++ b/ui/packages/consul-peerings/app/templates/dc/peers/show/imported.hbs @@ -83,6 +83,7 @@ diff --git a/ui/packages/consul-ui/app/components/code-editor/index.js b/ui/packages/consul-ui/app/components/code-editor/index.js index 65566d159b76..012f9698dde9 100644 --- a/ui/packages/consul-ui/app/components/code-editor/index.js +++ b/ui/packages/consul-ui/app/components/code-editor/index.js @@ -11,8 +11,6 @@ const DEFAULTS = { lineNumbers: true, theme: 'hashi', showCursorWhenSelecting: true, - gutters: ['CodeMirror-lint-markers'], - lint: true, }; export default Component.extend({ settings: service('settings'), @@ -51,7 +49,6 @@ export default Component.extend({ const editor = this.editor; editor.setOption('mode', mode.mime); - this.helper.lint(editor, mode.mode); set(this, 'mode', mode); } }, diff --git a/ui/packages/consul-ui/app/components/consul/datacenter/selector/index.hbs b/ui/packages/consul-ui/app/components/consul/datacenter/selector/index.hbs index 9fdd71c71956..e59d5cc13cae 100644 --- a/ui/packages/consul-ui/app/components/consul/datacenter/selector/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/datacenter/selector/index.hbs @@ -16,14 +16,14 @@ @description={{t "components.hashicorp-consul.side-nav.datacenters.description"}} class='consul-datacenter-selector' data-test-datacenter-menu - as |Dropdown item| + as |Selector| > - - {{item.Name}} + {{Selector.item.Name}} - {{#if (or item.Local item.Primary)}} + {{#if (or Selector.item.Local Selector.item.Primary)}} - {{#if item.Primary}} + {{#if Selector.item.Primary}} {{/if}} - {{#if item.Local}} + {{#if Selector.item.Local}} {{/if}} {{/if}} - + {{else}} diff --git a/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.hbs b/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.hbs index 3ae87f1be1b6..5164f8be1bb1 100644 --- a/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.hbs @@ -69,7 +69,20 @@ {{/if}} + {{#if shouldShowIgnoreCaseField}} + + Ignore Case + + + {{/if}} + - \ No newline at end of file + diff --git a/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.js b/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.js index ddbbc20eb5b0..11faf44befae 100644 --- a/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.js +++ b/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/index.js @@ -4,7 +4,7 @@ */ import Component from '@ember/component'; -import { get, set, computed } from '@ember/object'; +import { set, computed } from '@ember/object'; import { alias, equal, not } from '@ember/object/computed'; import { inject as service } from '@ember/service'; @@ -37,6 +37,7 @@ export default Component.extend({ Exact: 'Exactly Matching', Prefix: 'Prefixed by', Suffix: 'Suffixed by', + Contains: 'Containing', Regex: 'Regular Expression', Present: 'Is present', }; @@ -49,9 +50,14 @@ export default Component.extend({ headerTypeEqualsPresent: equal('headerType', 'Present'), shouldShowValueField: not('headerTypeEqualsPresent'), + shouldShowIgnoreCaseField: computed('headerType', function () { + return this.headerType !== 'Present' && this.headerType !== 'Regex'; + }), + actions: { change: function (name, changeset, e) { - const value = typeof get(e, 'target.value') !== 'undefined' ? e.target.value : e; + const valueIndicator = e.target?.type === 'checkbox' ? e.target?.checked : e.target?.value; + const value = typeof valueIndicator !== 'undefined' ? valueIndicator : e; switch (name) { default: changeset.set(name, value); @@ -65,6 +71,7 @@ export default Component.extend({ // Present is a boolean, whereas all other header types have a value const value = changeset.HeaderType === 'Present' ? true : changeset.Value; changeset.set(changeset.HeaderType, value); + changeset.set('IgnoreCase', changeset.IgnoreCase); // this will prevent the changeset from overwriting the // computed properties on the ED object diff --git a/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/pageobject.js b/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/pageobject.js index c142a4c8b7d6..4e309f1892cb 100644 --- a/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/pageobject.js +++ b/ui/packages/consul-ui/app/components/consul/intention/permission/header/form/pageobject.js @@ -11,7 +11,14 @@ export default (scope = '.consul-intention-permission-header-form') => { scope: scope, HeaderType: { scope: '[data-property="headertype"]', - ...powerSelect(['ExactlyMatching', 'PrefixedBy', 'SuffixedBy', 'RegEx', 'IsPresent']), + ...powerSelect([ + 'ExactlyMatching', + 'PrefixedBy', + 'SuffixedBy', + 'Containing', + 'RegEx', + 'IsPresent', + ]), }, Name: { scope: '[data-property="name"] input', diff --git a/ui/packages/consul-ui/app/components/consul/service/list/index.hbs b/ui/packages/consul-ui/app/components/consul/service/list/index.hbs index 2dc1b4742b04..36f5467c2106 100644 --- a/ui/packages/consul-ui/app/components/consul/service/list/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/service/list/index.hbs @@ -10,85 +10,5 @@ @linkable='linkable service' as |item index| > - -
      -
      - Health -
      -
      -
      - {{#if (gt item.InstanceCount 0)}} -
      - {{item.Name}} - - {{else}} -

      - {{item.Name}} -

      - {{/if}} - - - - - {{#if - (and - (not-eq item.InstanceCount 0) - (and (not-eq item.Kind 'terminating-gateway') (not-eq item.Kind 'ingress-gateway')) - ) - }} - - {{format-number item.InstanceCount}} - {{pluralize item.InstanceCount 'instance' without-count=true}} - - {{/if}} - {{! we are displaying imported-services - don't show bucket-list }} - {{#unless @isPeerDetail}} - - {{/unless}} - {{#if (eq item.Kind 'terminating-gateway')}} - - {{format-number item.GatewayConfig.AssociatedServiceCount}} - {{pluralize item.GatewayConfig.AssociatedServiceCount 'linked service' without-count=true}} - - {{else if (eq item.Kind 'ingress-gateway')}} - - {{format-number item.GatewayConfig.AssociatedServiceCount}} - {{pluralize item.GatewayConfig.AssociatedServiceCount 'upstream' without-count=true}} - - {{/if}} - {{#if (or item.ConnectedWithGateway item.ConnectedWithProxy)}} -
      -
      - - This service uses a proxy for the Consul service mesh - -
      - {{#if (and item.ConnectedWithGateway item.ConnectedWithProxy)}} -
      - in service mesh with proxy and gateway -
      - {{else if item.ConnectedWithProxy}} -
      - in service mesh with proxy -
      - {{else if item.ConnectedWithGateway}} -
      - in service mesh with gateway -
      - {{/if}} -
      - {{/if}} - -
      + diff --git a/ui/packages/consul-ui/app/components/consul/service/list/item/index.hbs b/ui/packages/consul-ui/app/components/consul/service/list/item/index.hbs new file mode 100644 index 000000000000..9f7f555ba60f --- /dev/null +++ b/ui/packages/consul-ui/app/components/consul/service/list/item/index.hbs @@ -0,0 +1,82 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + + +
      +
      + Health +
      +
      +
      + {{#if (gt @item.InstanceCount 0)}} + + {{@item.Name}} + + {{else}} +

      + {{@item.Name}} +

      + {{/if}} +
      + + + + {{#if + (and + (not-eq @item.InstanceCount 0) + (and (not-eq @item.Kind 'terminating-gateway') (not-eq @item.Kind 'ingress-gateway')) + ) + }} + + {{format-number @item.InstanceCount}} + {{pluralize @item.InstanceCount 'instance' without-count=true}} + + {{/if}} + {{! we are displaying imported-services - don't show bucket-list }} + {{#unless @isPeerDetail}} + + {{/unless}} + {{#if (eq @item.Kind 'terminating-gateway')}} + + {{format-number @item.GatewayConfig.AssociatedServiceCount}} + {{pluralize @item.GatewayConfig.AssociatedServiceCount 'linked service' without-count=true}} + + {{else if (eq @item.Kind 'ingress-gateway')}} + + {{format-number @item.GatewayConfig.AssociatedServiceCount}} + {{pluralize @item.GatewayConfig.AssociatedServiceCount 'upstream' without-count=true}} + + {{/if}} + {{#if (or @item.ConnectedWithGateway @item.ConnectedWithProxy)}} +
      +
      + + This service uses a proxy for the Consul service mesh + +
      + {{#if (and @item.ConnectedWithGateway @item.ConnectedWithProxy)}} +
      + in service mesh with proxy and gateway +
      + {{else if @item.ConnectedWithProxy}} +
      + in service mesh with proxy +
      + {{else if @item.ConnectedWithGateway}} +
      + in service mesh with gateway +
      + {{/if}} +
      + {{/if}} + +
      \ No newline at end of file diff --git a/ui/packages/consul-ui/app/components/consul/service/list/item/index.js b/ui/packages/consul-ui/app/components/consul/service/list/item/index.js new file mode 100644 index 000000000000..9bc75dbd45d0 --- /dev/null +++ b/ui/packages/consul-ui/app/components/consul/service/list/item/index.js @@ -0,0 +1,25 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; + +export default class ConsulServiceListItem extends Component { + get linkParams() { + const hash = {}; + + if (this.args.item.Partition && this.args.partition !== this.args.item.Partition) { + hash.partition = this.args.item.Partition; + hash.nspace = this.args.Namespace; + } else if (this.args.item.Namespace && this.args.nspace !== this.args.item.Namespace) { + hash.nspace = this.args.item.Namespace; + } + + if (this.args.item.PeerName) { + hash.peer = this.args.item.PeerName; + } + + return hash; + } +} diff --git a/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs b/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs index 10de36f0f3a4..fc508b17c6b5 100644 --- a/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs +++ b/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs @@ -73,7 +73,7 @@ <:side-nav> - + <:header> <:logo> @@ -122,7 +122,7 @@ class='hds-side-nav-hide-when-minimized consul-side-nav__selector-group' as |SNL| > - + - {{t "components.hashicorp-consul.side-nav.footer" version=(env 'CONSUL_VERSION')}} + {{t "components.hashicorp-consul.side-nav.footer" version=this.consulVersion}} {{{concat ''}}} diff --git a/ui/packages/consul-ui/app/components/hashicorp-consul/index.js b/ui/packages/consul-ui/app/components/hashicorp-consul/index.js index 6b5135a1bee4..e47ca22c6262 100644 --- a/ui/packages/consul-ui/app/components/hashicorp-consul/index.js +++ b/ui/packages/consul-ui/app/components/hashicorp-consul/index.js @@ -8,4 +8,10 @@ import { inject as service } from '@ember/service'; export default class HashiCorpConsul extends Component { @service('flashMessages') flashMessages; + @service('env') env; + + get consulVersion() { + const suffix = !['', 'oss'].includes(this.env.var('CONSUL_BINARY_TYPE')) ? '+ent' : ''; + return `${this.env.var('CONSUL_VERSION')}${suffix}`; + } } diff --git a/ui/packages/consul-ui/app/components/hcp-nav-item/index.hbs b/ui/packages/consul-ui/app/components/hcp-nav-item/index.hbs new file mode 100644 index 000000000000..b3b377f13c7c --- /dev/null +++ b/ui/packages/consul-ui/app/components/hcp-nav-item/index.hbs @@ -0,0 +1,15 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + +{{#let @list (env "CONSUL_HCP_URL") as |SNL hcpUrl|}} + {{#if this.shouldShowBackToHcpItem}} + + {{/if}} +{{/let}} \ No newline at end of file diff --git a/ui/packages/consul-ui/app/components/hcp-nav-item/index.js b/ui/packages/consul-ui/app/components/hcp-nav-item/index.js new file mode 100644 index 000000000000..487984511ed2 --- /dev/null +++ b/ui/packages/consul-ui/app/components/hcp-nav-item/index.js @@ -0,0 +1,21 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Component from '@glimmer/component'; +import { inject as service } from '@ember/service'; + +/** + * If the user has accessed consul from HCP managed consul, we do NOT want to display the + * "HCP Consul Central↗️" link in the nav bar. As we're already displaying a BackLink to HCP. + */ +export default class HcpLinkItemComponent extends Component { + @service env; + + get shouldShowBackToHcpItem() { + const isConsulHcpUrlDefined = !!this.env.var('CONSUL_HCP_URL'); + const isConsulHcpEnabled = !!this.env.var('CONSUL_HCP_ENABLED'); + return isConsulHcpEnabled && isConsulHcpUrlDefined; + } +} diff --git a/ui/packages/consul-ui/app/components/nav-selector/generic.hbs b/ui/packages/consul-ui/app/components/nav-selector/generic.hbs new file mode 100644 index 000000000000..8709fc4b8b77 --- /dev/null +++ b/ui/packages/consul-ui/app/components/nav-selector/generic.hbs @@ -0,0 +1,6 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + +{{yield}} \ No newline at end of file diff --git a/ui/packages/consul-ui/app/components/nav-selector/index.hbs b/ui/packages/consul-ui/app/components/nav-selector/index.hbs index ef00a038f185..145016e8edc4 100644 --- a/ui/packages/consul-ui/app/components/nav-selector/index.hbs +++ b/ui/packages/consul-ui/app/components/nav-selector/index.hbs @@ -20,6 +20,7 @@ disabled={{eq @disabled true}} /> + {{yield (hash Data=(component 'nav-selector/generic'))}} {{#if @description}}
      {{@description}} @@ -37,7 +38,10 @@ {{else}} {{#each this.filteredItems as |item|}} - {{yield DD item}} + {{yield (hash + Dropdown=DD + item=item + )}} {{/each}} {{/if}} {{#if @footerLink}} diff --git a/ui/packages/consul-ui/app/components/topology-metrics/index.hbs b/ui/packages/consul-ui/app/components/topology-metrics/index.hbs index 46f8dc9e01d0..760d3719c040 100644 --- a/ui/packages/consul-ui/app/components/topology-metrics/index.hbs +++ b/ui/packages/consul-ui/app/components/topology-metrics/index.hbs @@ -32,7 +32,7 @@ @hasMetricsProvider={{@hasMetricsProvider}} @noMetricsReason={{this.noMetricsReason}} > - {{#if (and @hasMetricsProvider this.mainNotIngressService (not-eq item.Kind 'ingress-gateway'))}} + {{#if (and @hasMetricsProvider this.mainNotIngressService (not-eq item.Kind 'ingress-gateway') this.mainNotAPIGatewayService (not-eq item.Kind 'api-gateway'))}} {{!-- One of the only places in the app where it's acceptable to default to 'default' namespace --}} {{@service.Service.Service}}
      - {{#if (not-eq @service.Service.Meta.external-source 'consul-api-gateway')}} + {{#if (not (and (eq @service.Service.Meta.external-source 'consul-api-gateway') (eq @service.Service.Kind 'ingress-gateway'))) }} {{#if @hasMetricsProvider}} - {{#if this.mainNotIngressService}} + {{#if (or (this.mainNotIngressService) (this.mainNotAPIGatewayService))}} typeof item[prop] !== 'undefined' ); + let invertPrefix = item.Invert ? 'NOT ' : ''; + let ignoreCaseSuffix = item.IgnoreCase ? ' (case-insensitive)' : ''; + switch (prop) { case 'Present': - return `${item.Invert ? `NOT ` : ``}present`; + return `${invertPrefix}present`; case 'Exact': - return `${item.Invert ? `NOT ` : ``}exactly matching "${item.Exact}"`; + return `${invertPrefix}exactly matching "${item.Exact}"${ignoreCaseSuffix}`; case 'Prefix': - return `${item.Invert ? `NOT ` : ``}prefixed by "${item.Prefix}"`; + return `${invertPrefix}prefixed by "${item.Prefix}"${ignoreCaseSuffix}`; case 'Suffix': - return `${item.Invert ? `NOT ` : ``}suffixed by "${item.Suffix}"`; + return `${invertPrefix}suffixed by "${item.Suffix}"${ignoreCaseSuffix}`; + case 'Contains': + return `${invertPrefix}containing "${item.Contains}"${ignoreCaseSuffix}`; case 'Regex': - return `${item.Invert ? `NOT ` : ``}matching the regex "${item.Regex}"`; + return `${invertPrefix}matching the regex "${item.Regex}"`; } return ''; }); diff --git a/ui/packages/consul-ui/app/locations/fsm-with-optional.js b/ui/packages/consul-ui/app/locations/fsm-with-optional.js index 9f096d18a037..f1ddec3f3c1c 100644 --- a/ui/packages/consul-ui/app/locations/fsm-with-optional.js +++ b/ui/packages/consul-ui/app/locations/fsm-with-optional.js @@ -149,7 +149,10 @@ export default class FSMWithOptionalLocation { url = this.getURLFrom(url) .split('/') .filter((item, i) => { - if (i < 3) { + // the max optional parameters we have is 3 (partition, namespace, peer). When we split the path + // by '/' it has a prefixed empty '' in the array. So we know we only have to check up to the 4th + // index for optional parameters. + if (i < 4) { let found = false; Object.entries(OPTIONAL).reduce((prev, [key, re]) => { const res = re.exec(item); diff --git a/ui/packages/consul-ui/app/models/intention-permission-http-header.js b/ui/packages/consul-ui/app/models/intention-permission-http-header.js index b327ff91ab1e..f17a0d2d96a6 100644 --- a/ui/packages/consul-ui/app/models/intention-permission-http-header.js +++ b/ui/packages/consul-ui/app/models/intention-permission-http-header.js @@ -13,7 +13,7 @@ export const schema = { required: true, }, HeaderType: { - allowedValues: ['Exact', 'Prefix', 'Suffix', 'Regex', 'Present'], + allowedValues: ['Exact', 'Prefix', 'Suffix', 'Contains', 'Regex', 'Present'], }, }; @@ -23,11 +23,13 @@ export default class IntentionPermission extends Fragment { @attr('string') Exact; @attr('string') Prefix; @attr('string') Suffix; + @attr('string') Contains; @attr('string') Regex; // this is a boolean but we don't want it to automatically be set to false @attr() Present; @or(...schema.HeaderType.allowedValues) Value; + @attr('boolean') IgnoreCase; @computed(...schema.HeaderType.allowedValues) get HeaderType() { diff --git a/ui/packages/consul-ui/app/routes/application.js b/ui/packages/consul-ui/app/routes/application.js index 40dce7153366..8cc6ce87e26d 100644 --- a/ui/packages/consul-ui/app/routes/application.js +++ b/ui/packages/consul-ui/app/routes/application.js @@ -13,13 +13,21 @@ export default class ApplicationRoute extends Route.extend(WithBlockingActions) @service('client/http') client; @service('env') env; @service() hcp; + @service() router; data; + beforeModel() { + if (this.env.var('CONSUL_V2_CATALOG_ENABLED')) { + this.router.replaceWith('unavailable'); + } + } + async model() { if (this.env.var('CONSUL_ACLS_ENABLED')) { await this.hcp.updateTokenIfNecessary(this.env.var('CONSUL_HTTP_TOKEN')); } + return {}; } diff --git a/ui/packages/consul-ui/app/routes/unavailable.js b/ui/packages/consul-ui/app/routes/unavailable.js new file mode 100644 index 000000000000..8bee82ffb2db --- /dev/null +++ b/ui/packages/consul-ui/app/routes/unavailable.js @@ -0,0 +1,18 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Route from 'consul-ui/routing/route'; +import { inject as service } from '@ember/service'; + +export default class UnavailableRoute extends Route { + @service('env') env; + @service() router; + + beforeModel() { + if (!this.env.var('CONSUL_V2_CATALOG_ENABLED')) { + this.router.replaceWith('index'); + } + } +} diff --git a/ui/packages/consul-ui/app/services/code-mirror/linter.js b/ui/packages/consul-ui/app/services/code-mirror/linter.js index 66b4a3dc4d36..74a0a45b0140 100644 --- a/ui/packages/consul-ui/app/services/code-mirror/linter.js +++ b/ui/packages/consul-ui/app/services/code-mirror/linter.js @@ -4,7 +4,6 @@ */ import Service, { inject as service } from '@ember/service'; -import lint from 'consul-ui/utils/editor/lint'; const MODES = [ { name: 'JSON', @@ -41,10 +40,6 @@ export default class LinterService extends Service { return MODES; } - lint() { - return lint(...arguments); - } - getEditor(element) { return this.dom.element('textarea + div', element).CodeMirror; } diff --git a/ui/packages/consul-ui/app/services/repository.js b/ui/packages/consul-ui/app/services/repository.js index 52180ce56a11..11c35739edf0 100644 --- a/ui/packages/consul-ui/app/services/repository.js +++ b/ui/packages/consul-ui/app/services/repository.js @@ -113,6 +113,17 @@ export default class RepositoryService extends Service { return false; } } + + // We were seeing issues where services were all being unloaded after visiting + // a peers imported services page. So if you viewes services -> peered imported services -> services + // only the peered services would remain as the others were all unloaded. Not certain if + // we should be doing any manual reconciling as it is. Not enough historical context + // to determine that at this time. + // + // https://hashicorp.atlassian.net/browse/NET-6900 + if (this.env.var('CONSUL_PEERINGS_ENABLED') && this.getModelName() === 'service') { + return false; + } return true; } diff --git a/ui/packages/consul-ui/app/templates/application.hbs b/ui/packages/consul-ui/app/templates/application.hbs index 7be739bf64b8..a999d9b562aa 100644 --- a/ui/packages/consul-ui/app/templates/application.hbs +++ b/ui/packages/consul-ui/app/templates/application.hbs @@ -7,41 +7,46 @@ {{! Add the a11y route announcer }} - {{! Tell CSS what we have enabled }} - {{#if (can 'use acls')}} - {{document-attrs class="has-acls"}} - {{/if}} - {{#if (can 'use nspaces')}} - {{document-attrs class="has-nspaces" }} - {{/if}} - {{#if (can 'use partitions')}} - {{document-attrs class="has-partitions" }} - {{/if}} - {{! Listen out for blocking query/client setting changes }} - - - {{! Tell CSS about our theme }} - - {{#each-in source.data as |key value|}} - {{#if (and value (includes key (array 'color-scheme' 'contrast')))}} - {{document-attrs class=(concat "prefers-" key "-" value) }} - {{/if}} - {{/each-in}} - + {{#unless (env 'CONSUL_V2_CATALOG_ENABLED')}} + {{! Tell CSS what we have enabled }} + {{#if (can 'use acls')}} + {{document-attrs class='has-acls'}} + {{/if}} + {{#if (can 'use nspaces')}} + {{document-attrs class='has-nspaces'}} + {{/if}} + {{#if (can 'use partitions')}} + {{document-attrs class='has-partitions'}} + {{/if}} - {{! If ACLs are enabled try get a token }} - {{#if (can 'use acls')}} + {{! Listen out for blocking query/client setting changes }} - {{/if}} - {{#if (not-eq route.currentName 'oauth-provider-debug')}} + {{! Tell CSS about our theme }} + + {{#each-in source.data as |key value|}} + {{#if (and value (includes key (array 'color-scheme' 'contrast')))}} + {{document-attrs class=(concat 'prefers-' key '-' value)}} + {{/if}} + {{/each-in}} + + + {{! If ACLs are enabled try get a token }} + {{#if (can 'use acls')}} + + {{/if}} + {{/unless}} + + {{#if + (and (not (env 'CONSUL_V2_CATALOG_ENABLED')) (not-eq route.currentName 'oauth-provider-debug')) + }} {{! redirect if we aren't on a URL with dc information }} {{#if (eq route.currentName 'index')}} @@ -140,4 +145,4 @@ {{outlet}} {{/if}} - + \ No newline at end of file diff --git a/ui/packages/consul-ui/app/templates/dc/acls/roles/-form.hbs b/ui/packages/consul-ui/app/templates/dc/acls/roles/-form.hbs index a703f1d571ac..bf205b2d6b23 100644 --- a/ui/packages/consul-ui/app/templates/dc/acls/roles/-form.hbs +++ b/ui/packages/consul-ui/app/templates/dc/acls/roles/-form.hbs @@ -18,7 +18,7 @@ partition=partition nspace=nspace dc=dc - id=(or id '') + id=(if item item.ID '') ) }} as |loader|> diff --git a/ui/packages/consul-ui/app/templates/dc/services/index.hbs b/ui/packages/consul-ui/app/templates/dc/services/index.hbs index 37a73c419f7f..100e7c2d9761 100644 --- a/ui/packages/consul-ui/app/templates/dc/services/index.hbs +++ b/ui/packages/consul-ui/app/templates/dc/services/index.hbs @@ -101,6 +101,7 @@ as |sort filters items partition nspace|}} diff --git a/ui/packages/consul-ui/app/templates/dc/services/show.hbs b/ui/packages/consul-ui/app/templates/dc/services/show.hbs index 18fa606c71f9..4639b76e3f01 100644 --- a/ui/packages/consul-ui/app/templates/dc/services/show.hbs +++ b/ui/packages/consul-ui/app/templates/dc/services/show.hbs @@ -98,7 +98,7 @@ as |items item dc|}} {{/if}} {{#let (hash - topology=(and dc.MeshEnabled item.IsMeshOrigin (or (gt proxies.length 0) (eq item.Service.Kind 'ingress-gateway')) (not item.Service.PeerName)) + topology=(and dc.MeshEnabled item.IsMeshOrigin (or (gt proxies.length 0) (eq item.Service.Kind 'ingress-gateway') (eq item.Service.Kind 'api-gateway')) (not item.Service.PeerName)) services=(and (eq item.Service.Kind 'terminating-gateway') (not item.Service.PeerName)) upstreams=(and (eq item.Service.Kind 'ingress-gateway') (not item.Service.PeerName)) instances=true diff --git a/ui/packages/consul-ui/app/templates/debug.hbs b/ui/packages/consul-ui/app/templates/debug.hbs index d301ba057177..f911d4e7178d 100644 --- a/ui/packages/consul-ui/app/templates/debug.hbs +++ b/ui/packages/consul-ui/app/templates/debug.hbs @@ -32,7 +32,7 @@ <:side-nav> - + <:header> <:logo> diff --git a/ui/packages/consul-ui/app/templates/unavailable.hbs b/ui/packages/consul-ui/app/templates/unavailable.hbs new file mode 100644 index 000000000000..8c591f8238da --- /dev/null +++ b/ui/packages/consul-ui/app/templates/unavailable.hbs @@ -0,0 +1,106 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + + + {{#if (env 'CONSUL_V2_CATALOG_ENABLED')}} +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + {{/if}} +
      \ No newline at end of file diff --git a/ui/packages/consul-ui/app/utils/editor/lint.js b/ui/packages/consul-ui/app/utils/editor/lint.js deleted file mode 100644 index 4c3e824e44bb..000000000000 --- a/ui/packages/consul-ui/app/utils/editor/lint.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -/*global CodeMirror*/ - -// CodeMirror doesn't seem to have anyway to hook into whether a mode -// has already loaded, or when a mode has finished loading -// follow more or less what CodeMirror does but doesn't expose -// see codemirror/addon/mode/loadmode.js - -export const createLoader = function ( - $$ = document.getElementsByTagName.bind(document), - CM = CodeMirror -) { - CM.registerHelper('lint', 'ruby', function (text) { - return []; - }); - return function (editor, mode, cb) { - let scripts = [...$$('script')]; - const loaded = scripts.find(function (item) { - return item.src.indexOf(`/codemirror/mode/${mode}/${mode}.js`) !== -1; - }); - CM.autoLoadMode(editor, mode); - if (loaded) { - cb(); - } else { - scripts = [...$$('script')]; - CM.on(scripts[0], 'load', function () { - cb(); - }); - } - }; -}; -const load = createLoader(); -export default function (editor, mode) { - load(editor, mode, function () { - if (editor.getValue().trim().length) { - editor.performLint(); - } - }); -} diff --git a/ui/packages/consul-ui/app/utils/get-environment.js b/ui/packages/consul-ui/app/utils/get-environment.js index a4284a24f7d4..ebfc1763e616 100644 --- a/ui/packages/consul-ui/app/utils/get-environment.js +++ b/ui/packages/consul-ui/app/utils/get-environment.js @@ -4,6 +4,19 @@ */ import { runInDebug } from '@ember/debug'; +import { htmlSafe } from '@ember/template'; + +function sanitizeString(str) { + return htmlSafe( + String(str) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + ); +} + // 'environment' getter // there are currently 3 levels of environment variables: // 1. Those that can be set by the user by setting localStorage values @@ -58,9 +71,16 @@ export default function (config = {}, win = window, doc = document) { } else { str = cookies(doc.cookie).join(';'); const tab = win.open('', '_blank'); - tab.document.write( - `
      ${location.href}#${str}

      Scenario` - ); + if (tab) { + const safeLocationHref = sanitizeString(location.href); + const safeStr = sanitizeString(str); + tab.document.write(` + +
      ${safeLocationHref}#${safeStr}

      + Scenario + + `); + } } }; @@ -146,7 +166,7 @@ export default function (config = {}, win = window, doc = document) { case 'CONSUL_API_PREFIX': // we want API prefix to look like an env var for if we ever change // operator config to be an API request, we need this variable before we - // make and API request so this specific variable should never be be + // make and API request so this specific variable should never be // retrived via an API request return operatorConfig.APIPrefix; case 'CONSUL_HCP_URL': @@ -197,6 +217,10 @@ export default function (config = {}, win = window, doc = document) { // reserve 1 for traffic that we can't manage return 5; } + case 'CONSUL_V2_CATALOG_ENABLED': + return operatorConfig.V2CatalogEnabled === 'undefined' + ? false + : operatorConfig.V2CatalogEnabled; } }; const ui = function (key) { @@ -244,6 +268,9 @@ export default function (config = {}, win = window, doc = document) { case 'TokenSecretID': prev['CONSUL_HTTP_TOKEN'] = value; break; + case 'CONSUL_V2_CATALOG_ENABLE': + prev['CONSUL_V2_CATALOG_ENABLED'] = JSON.parse(value); + break; default: prev[key] = value; } @@ -295,6 +322,7 @@ export default function (config = {}, win = window, doc = document) { case 'CONSUL_METRICS_PROXY_ENABLE': case 'CONSUL_SERVICE_DASHBOARD_URL': case 'CONSUL_BASE_UI_URL': + case 'CONSUL_V2_CATALOG_ENABLED': case 'CONSUL_HTTP_PROTOCOL': case 'CONSUL_HTTP_MAX_CONNECTIONS': { // We allow the operator to set these ones via various methods diff --git a/ui/packages/consul-ui/config/environment.js b/ui/packages/consul-ui/config/environment.js index b694f7e894ec..a2deafdd8c4a 100644 --- a/ui/packages/consul-ui/config/environment.js +++ b/ui/packages/consul-ui/config/environment.js @@ -94,6 +94,7 @@ module.exports = function (environment, $ = process.env) { LocalDatacenter: env('CONSUL_DATACENTER_LOCAL', 'dc1'), PrimaryDatacenter: env('CONSUL_DATACENTER_PRIMARY', 'dc1'), APIPrefix: env('CONSUL_API_PREFIX', ''), + V2CatalogEnabled: false, }, // Static variables used in multiple places throughout the UI @@ -122,6 +123,7 @@ module.exports = function (environment, $ = process.env) { LocalDatacenter: env('CONSUL_DATACENTER_LOCAL', 'dc1'), PrimaryDatacenter: env('CONSUL_DATACENTER_PRIMARY', 'dc1'), APIPrefix: env('CONSUL_API_PREFIX', ''), + V2CatalogEnabled: env('CONSUL_V2_CATALOG_ENABLED', false), }, '@hashicorp/ember-cli-api-double': { @@ -176,6 +178,7 @@ module.exports = function (environment, $ = process.env) { LocalDatacenter: env('CONSUL_DATACENTER_LOCAL', 'dc1'), PrimaryDatacenter: env('CONSUL_DATACENTER_PRIMARY', 'dc1'), APIPrefix: env('CONSUL_API_PREFIX', ''), + V2CatalogEnabled: env('CONSUL_V2_CATALOG_ENABLED', false), }, '@hashicorp/ember-cli-api-double': { diff --git a/ui/packages/consul-ui/ember-cli-build.js b/ui/packages/consul-ui/ember-cli-build.js index c483cbf678aa..ecfdc1b35ac6 100644 --- a/ui/packages/consul-ui/ember-cli-build.js +++ b/ui/packages/consul-ui/ember-cli-build.js @@ -39,7 +39,6 @@ module.exports = function (defaults, $ = process.env) { 'consul-peerings', 'consul-partitions', 'consul-nspaces', - 'consul-hcp', ].map((item) => { return { name: item, @@ -207,13 +206,7 @@ module.exports = function (defaults, $ = process.env) { }, codemirror: { keyMaps: ['sublime'], - addonFiles: [ - 'lint/lint.css', - 'lint/lint.js', - 'lint/json-lint.js', - 'lint/yaml-lint.js', - 'mode/loadmode.js', - ], + addonFiles: ['lint/lint.css', 'lint/yaml-lint.js', 'mode/loadmode.js'], }, sassOptions: { implementation: require('sass'), @@ -271,10 +264,7 @@ module.exports = function (defaults, $ = process.env) { // CSS.escape polyfill app.import('node_modules/css.escape/css.escape.js', { outputFile: 'assets/css.escape.js' }); - // JSON linting support. Possibly dynamically loaded via CodeMirror linting. See components/code-editor.js - app.import('node_modules/jsonlint/lib/jsonlint.js', { - outputFile: 'assets/codemirror/mode/javascript/javascript.js', - }); + // Possibly dynamically loaded via CodeMirror linting. See components/code-editor.js app.import('node_modules/codemirror/mode/javascript/javascript.js', { outputFile: 'assets/codemirror/mode/javascript/javascript.js', }); diff --git a/ui/packages/consul-ui/lib/startup/templates/body.html.js b/ui/packages/consul-ui/lib/startup/templates/body.html.js index 93d25f96018b..bf201960d253 100644 --- a/ui/packages/consul-ui/lib/startup/templates/body.html.js +++ b/ui/packages/consul-ui/lib/startup/templates/body.html.js @@ -75,10 +75,6 @@ ${ {{if .NamespacesEnabled}} {{end}} -{{if .HCPEnabled}} - - -{{end}} ` : ` diff --git a/ui/packages/consul-ui/mock-api/prefixed-api/api/hcp/v2/link/global b/ui/packages/consul-ui/mock-api/prefixed-api/api/hcp/v2/link/global new file mode 100644 index 000000000000..873f854c202d --- /dev/null +++ b/ui/packages/consul-ui/mock-api/prefixed-api/api/hcp/v2/link/global @@ -0,0 +1,16 @@ +{ + "status": { + "consul.io/hcp/link": { + "conditions": [ + { + "message": "Successfully linked to cluster 'organization/f53e5646-6529-4698-ae29-d74f8bd22a01/project/6994bb7a-5561-4d5c-8bb0-cf40177e5b77/hashicorp.consul.global-network-manager.cluster/mkam-vm'", + "reason": "SUCCESS", + "state": "STATE_FALSE", + "type": "linked" + } + ], + "observedGeneration":"01HMA2VPHVKNF6QR8TD07KDN5K", + "updatedAt":"2024-01-16T21:29:25.923140Z" + } + } +} \ No newline at end of file diff --git a/ui/packages/consul-ui/mock-api/v1/agent/services b/ui/packages/consul-ui/mock-api/v1/agent/services index 6397b362e9ea..9a7f5b4278dd 100644 --- a/ui/packages/consul-ui/mock-api/v1/agent/services +++ b/ui/packages/consul-ui/mock-api/v1/agent/services @@ -12,14 +12,16 @@ "ModifyIndex": 0, "ProxyDestination": "", "Connect": { - "Proxy": { - "ExecMode": "daemon", - "Command": [ - "/bin/consul", - "connect", - "proxy" - ], - "Config": null + "SidecarService": { + "Proxy": { + "ExecMode": "daemon", + "Command": [ + "/bin/consul", + "connect", + "proxy" + ], + "Config": null + } } } }, diff --git a/ui/packages/consul-ui/mock-api/v1/connect/_ b/ui/packages/consul-ui/mock-api/v1/connect/_ index 7ba49d725677..a87d00208154 100644 --- a/ui/packages/consul-ui/mock-api/v1/connect/_ +++ b/ui/packages/consul-ui/mock-api/v1/connect/_ @@ -78,11 +78,15 @@ ${range(headerCount).map(item => ` ${fake.random.boolean() ? ` "Invert": true, ` : ``} +${fake.random.boolean() ? ` + "IgnoreCase": true, +` : ``} ${fake.helpers.randomize([ '"Present": true', '"Exact": "abc"', '"Prefix": "abc"', '"Suffix": "xyz"', + '"Contains": "abc"', '"Regex": "[abc]"' ])} } diff --git a/ui/packages/consul-ui/mock-api/v1/connect/intentions/_ b/ui/packages/consul-ui/mock-api/v1/connect/intentions/_ index 26dd645f90c5..0349dd5211c5 100644 --- a/ui/packages/consul-ui/mock-api/v1/connect/intentions/_ +++ b/ui/packages/consul-ui/mock-api/v1/connect/intentions/_ @@ -63,11 +63,15 @@ ${range(headerCount).map(item => ` ${fake.random.boolean() ? ` "Invert": true, ` : ``} +${fake.random.boolean() ? ` + "IgnoreCase": true, +` : ``} ${fake.helpers.randomize([ '"Present": true', '"Exact": "abc"', '"Prefix": "abc"', '"Suffix": "xyz"', + '"Contains": "abc"', '"Regex": "[abc]"' ])} } diff --git a/ui/packages/consul-ui/mock-api/v1/connect/intentions/exact b/ui/packages/consul-ui/mock-api/v1/connect/intentions/exact index 9de0cf4b33c4..2b4142bf7437 100644 --- a/ui/packages/consul-ui/mock-api/v1/connect/intentions/exact +++ b/ui/packages/consul-ui/mock-api/v1/connect/intentions/exact @@ -69,11 +69,15 @@ ${range(headerCount).map(item => ` ${fake.random.boolean() ? ` "Invert": true, ` : ``} +${fake.random.boolean() ? ` + "IgnoreCase": true, +` : ``} ${fake.helpers.randomize([ '"Present": true', '"Exact": "abc"', '"Prefix": "abc"', '"Suffix": "xyz"', + '"Contains": "abc"', '"Regex": "[abc]"' ])} } diff --git a/ui/packages/consul-ui/node-tests/config/environment.js b/ui/packages/consul-ui/node-tests/config/environment.js index 4779500d63ac..1681c3d1b553 100644 --- a/ui/packages/consul-ui/node-tests/config/environment.js +++ b/ui/packages/consul-ui/node-tests/config/environment.js @@ -31,6 +31,7 @@ test('config has the correct environment settings', function (t) { LocalDatacenter: 'dc1', PrimaryDatacenter: 'dc1', APIPrefix: '', + V2CatalogEnabled: false, }, }, { @@ -49,6 +50,7 @@ test('config has the correct environment settings', function (t) { LocalDatacenter: 'dc1', PrimaryDatacenter: 'dc1', APIPrefix: '', + V2CatalogEnabled: false, }, }, { @@ -67,6 +69,7 @@ test('config has the correct environment settings', function (t) { LocalDatacenter: 'dc1', PrimaryDatacenter: 'dc1', APIPrefix: '', + V2CatalogEnabled: false, }, }, { @@ -82,6 +85,7 @@ test('config has the correct environment settings', function (t) { LocalDatacenter: 'dc1', PrimaryDatacenter: 'dc1', APIPrefix: '', + V2CatalogEnabled: false, }, }, ].forEach(function (item) { diff --git a/ui/packages/consul-ui/package.json b/ui/packages/consul-ui/package.json index 3d5bb8441e71..44149453e5e0 100644 --- a/ui/packages/consul-ui/package.json +++ b/ui/packages/consul-ui/package.json @@ -90,17 +90,16 @@ "broccoli-merge-trees": "^4.2.0", "chalk": "^4.1.0", "clipboard": "^2.0.11", - "consul-acls": "*", - "consul-hcp": "*", - "consul-lock-sessions": "*", - "consul-nspaces": "*", - "consul-partitions": "*", - "consul-peerings": "*", + "consul-acls": "file:../consul-acls", + "consul-lock-sessions": "file:../consul-lock-sessions", + "consul-nspaces": "file:../consul-nspaces", + "consul-partitions": "file:../consul-partitions", + "consul-peerings": "file:../consul-peerings", "css": "^3.0.0", "css.escape": "^1.5.1", "d3-array": "^2.8.0", - "d3-scale": "^3.2.3", - "d3-scale-chromatic": "^2.0.0", + "d3-scale": "^4.0.2", + "d3-scale-chromatic": "^3.1.0", "d3-selection": "^2.0.0", "d3-shape": "^2.0.0", "dayjs": "^1.9.3", @@ -171,7 +170,6 @@ "husky": "^4.2.5", "ivy-codemirror": "^2.1.0", "js-yaml": "^4.0.0", - "jsonlint": "^1.6.3", "lint-staged": "^10.2.11", "loader.js": "^4.7.0", "mnemonist": "^0.38.0", diff --git a/ui/packages/consul-ui/tests/acceptance/dc/acls/policies/as-many/add-existing.feature b/ui/packages/consul-ui/tests/acceptance/dc/acls/policies/as-many/add-existing.feature index bf9464e50709..bb7b14d539cc 100644 --- a/ui/packages/consul-ui/tests/acceptance/dc/acls/policies/as-many/add-existing.feature +++ b/ui/packages/consul-ui/tests/acceptance/dc/acls/policies/as-many/add-existing.feature @@ -46,6 +46,5 @@ Feature: dc / acls / policies / as many / add existing: Add existing policy Where: ------------- | Model | - | token | | role | ------------- diff --git a/ui/packages/consul-ui/tests/acceptance/dc/nodes/show.feature b/ui/packages/consul-ui/tests/acceptance/dc/nodes/show.feature index 9c041cd2a6e5..95f6a52126b9 100644 --- a/ui/packages/consul-ui/tests/acceptance/dc/nodes/show.feature +++ b/ui/packages/consul-ui/tests/acceptance/dc/nodes/show.feature @@ -23,25 +23,6 @@ Feature: dc / nodes / show: Show node When I click metadata on the tabs And I see metadataIsSelected on the tabs - Scenario: Given 1 node all the tabs are visible and clickable and the RTT one isn't there - Given 1 node models from yaml - --- - ID: node-0 - --- - When I visit the node page for yaml - --- - dc: dc1 - node: node-0 - --- - And I see healthChecksIsSelected on the tabs - - When I click serviceInstances on the tabs - And I see serviceInstancesIsSelected on the tabs - - And I don't see roundTripTime on the tabs - - When I click lockSessions on the tabs - And I see lockSessionsIsSelected on the tabs Scenario: Given 1 node with no checks all the tabs are visible but the serviceInstances tab is selected Given 1 node models from yaml --- diff --git a/ui/packages/consul-ui/tests/acceptance/dc/nspaces/manage.feature b/ui/packages/consul-ui/tests/acceptance/dc/nspaces/manage.feature index 67b282d12997..7eca5d924d97 100644 --- a/ui/packages/consul-ui/tests/acceptance/dc/nspaces/manage.feature +++ b/ui/packages/consul-ui/tests/acceptance/dc/nspaces/manage.feature @@ -43,7 +43,6 @@ Feature: dc / nspaces / manage : Managing Namespaces And I don't see manageNspacesIsVisible on the navigation When I click services on the navigation Then the url should be /dc-1/services - When I click nspace on the navigation And I click manageNspaces on the navigation Then the url should be /dc-1/namespaces And I don't see manageNspacesIsVisible on the navigation diff --git a/ui/packages/consul-ui/tests/acceptance/dc/services/dc-switch.feature b/ui/packages/consul-ui/tests/acceptance/dc/services/dc-switch.feature index be6849ef5c8c..f3e6f6a7e84d 100644 --- a/ui/packages/consul-ui/tests/acceptance/dc/services/dc-switch.feature +++ b/ui/packages/consul-ui/tests/acceptance/dc/services/dc-switch.feature @@ -32,11 +32,9 @@ Feature: dc / services / dc-switch : Switching Datacenters And I click dcs.1.name on the navigation Then the url should be /dc-2/services Then I see 6 service models - When I click dc on the navigation And I click dcs.0.name on the navigation Then the url should be /dc-1/services Then I see 6 service models - When I click dc on the navigation And I click dcs.1.name on the navigation Then the url should be /dc-2/services Then I see 6 service models diff --git a/ui/packages/consul-ui/tests/acceptance/dc/services/show/topology/metrics.feature b/ui/packages/consul-ui/tests/acceptance/dc/services/show/topology/metrics.feature index fdfc9c1d1db7..ad6c30210afd 100644 --- a/ui/packages/consul-ui/tests/acceptance/dc/services/show/topology/metrics.feature +++ b/ui/packages/consul-ui/tests/acceptance/dc/services/show/topology/metrics.feature @@ -53,20 +53,20 @@ Feature: dc / services / show / topology / metrics And the local datacenter is "datacenter" And 1 service model from yaml --- - - Service: + - Service: Name: web Kind: ~ Meta: - external-source: consul-api-gateway + external-source: consul-api-gateway --- And ui_config from yaml --- - metrics_proxy_enabled: true - metrics_provider: 'prometheus' + metrics_proxy_enabled: true + metrics_provider: 'prometheus' --- When I visit the service page for yaml --- dc: datacenter service: web --- - And I don't see the "[data-test-sparkline]" element + And I don't see the "[data-test-sparkline]" element \ No newline at end of file diff --git a/ui/packages/consul-ui/tests/acceptance/unavailable-test.js b/ui/packages/consul-ui/tests/acceptance/unavailable-test.js new file mode 100644 index 000000000000..9a983dc99415 --- /dev/null +++ b/ui/packages/consul-ui/tests/acceptance/unavailable-test.js @@ -0,0 +1,65 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { currentURL, visit } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import { setupTestEnv } from 'consul-ui/services/env'; + +const unavailableHeaderSelector = '[data-test-unavailable-header]'; +const unavailableBodySelector = '[data-test-unavailable-body]'; + +module('Acceptance | unavailable page', function (hooks) { + setupApplicationTest(hooks); + + test('it redirects to the unavailable page when the v2 catalog is enabled', async function (assert) { + assert.expect(3); + + setupTestEnv(this.owner, { + CONSUL_V2_CATALOG_ENABLED: true, + }); + + await visit('/'); + assert.equal(currentURL(), '/unavailable', 'It should redirect to the unavailable page'); + + // Expect the warning message to be visible + assert.dom(unavailableHeaderSelector).hasText('User Interface Unavailable'); + assert.dom(unavailableBodySelector).exists({ count: 1 }); + }); + + test('it does not redirect to the unavailable page', async function (assert) { + assert.expect(3); + + setupTestEnv(this.owner, { + CONSUL_V2_CATALOG_ENABLED: false, + }); + + await visit('/'); + assert.equal( + currentURL(), + '/dc1/services', + 'It should continue to the services page when v2 catalog is disabled' + ); + + // Expect the warning message to be not be visible + assert.dom(unavailableHeaderSelector).doesNotExist(); + assert.dom(unavailableBodySelector).doesNotExist(); + }); + + test('it redirects away from the unavailable page when v2 catalog is not enabled', async function (assert) { + assert.expect(3); + + setupTestEnv(this.owner, { + CONSUL_V2_CATALOG_ENABLED: false, + }); + + await visit('/unavailable'); + assert.equal(currentURL(), '/dc1/services', 'It should redirect to the services page'); + + // Expect the warning message to be not be visible + assert.dom(unavailableHeaderSelector).doesNotExist(); + assert.dom(unavailableBodySelector).doesNotExist(); + }); +}); diff --git a/ui/packages/consul-ui/tests/integration/components/consul/hcp/home-test.js b/ui/packages/consul-ui/tests/integration/components/consul/hcp/home-test.js deleted file mode 100644 index 99ac5e6e4a8d..000000000000 --- a/ui/packages/consul-ui/tests/integration/components/consul/hcp/home-test.js +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -// temporary import until we are running as separate applications -import 'consul-ui/components/consul/hcp/home/index.test'; diff --git a/ui/packages/consul-ui/tests/integration/components/hcp-nav-item-test.js b/ui/packages/consul-ui/tests/integration/components/hcp-nav-item-test.js new file mode 100644 index 000000000000..8fc7bfa97507 --- /dev/null +++ b/ui/packages/consul-ui/tests/integration/components/hcp-nav-item-test.js @@ -0,0 +1,76 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import hbs from 'htmlbars-inline-precompile'; +import { EnvStub } from 'consul-ui/services/env'; + +module('Integration | Component | hcp nav item', function (hooks) { + setupRenderingTest(hooks); + + test('it prints the value of CONSUL_HCP_URL', async function (assert) { + this.owner.register( + 'service:env', + class Stub extends EnvStub { + stubEnv = { + CONSUL_HCP_URL: 'http://hcp.com', + CONSUL_HCP_ENABLED: true, + }; + } + ); + + await render(hbs` + + + + `); + + assert.dom('[data-test-back-to-hcp]').isVisible(); + assert.dom('a').hasAttribute('href', 'http://hcp.com'); + }); + + test('it does not output the Back to HCP link if CONSUL_HCP_URL is not present', async function (assert) { + this.owner.register( + 'service:env', + class Stub extends EnvStub { + stubEnv = { + CONSUL_HCP_ENABLED: true, + CONSUL_HCP_URL: undefined, + }; + } + ); + + await render(hbs` + + + + `); + + assert.dom('[data-test-back-to-hcp]').doesNotExist(); + assert.dom('a').doesNotExist(); + }); + test('it does not output the Back to HCP link if CONSUL_HCP_ENABLED is not present', async function (assert) { + this.owner.register( + 'service:env', + class Stub extends EnvStub { + stubEnv = { + CONSUL_HCP_URL: 'http://hcp.com', + CONSUL_HCP_ENABLED: undefined, + }; + } + ); + + await render(hbs` + + + + `); + + assert.dom('[data-test-back-to-hcp]').doesNotExist(); + assert.dom('a').doesNotExist(); + }); +}); diff --git a/ui/packages/consul-ui/tests/integration/utils/dom/event-source/callable-test.js b/ui/packages/consul-ui/tests/integration/utils/dom/event-source/callable-test.js index f02b89830ae4..065264f7fd05 100644 --- a/ui/packages/consul-ui/tests/integration/utils/dom/event-source/callable-test.js +++ b/ui/packages/consul-ui/tests/integration/utils/dom/event-source/callable-test.js @@ -12,7 +12,7 @@ import sinon from 'sinon'; module('Integration | Utility | dom/event-source/callable', function (hooks) { setupTest(hooks); - test('it dispatches messages', function (assert) { + skip('it dispatches messages', function (assert) { assert.expect(1); const EventSource = domEventSourceCallable(EventTarget); const listener = sinon.stub(); diff --git a/ui/packages/consul-ui/vendor/consul-ui/routes.js b/ui/packages/consul-ui/vendor/consul-ui/routes.js index 07abd5c1b701..214b8fc8b815 100644 --- a/ui/packages/consul-ui/vendor/consul-ui/routes.js +++ b/ui/packages/consul-ui/vendor/consul-ui/routes.js @@ -439,6 +439,9 @@ redirect: '../settings', }, }, + unavailable: { + _options: { path: '/unavailable' }, + }, notfound: { _options: { path: '/*notfound' }, }, diff --git a/ui/yarn.lock b/ui/yarn.lock index 225993b749d2..10cbc0221d58 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -2,395 +2,349 @@ # yarn lockfile v1 +"@alloc/quick-lru@^5.2.0": + version "5.2.0" + resolved "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" + integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== + "@ampproject/remapping@^2.2.0": - version "2.2.0" - resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + version "2.3.0" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== dependencies: - "@jridgewell/gen-mapping" "^0.1.0" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" "@babel/code-frame@7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== dependencies: - "@babel/highlight" "^7.18.6" + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.1", "@babel/compat-data@^7.20.5": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz" - integrity sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g== +"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz#d23bbea508c3883ba8251fb4164982c36ea577ed" + integrity sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw== "@babel/core@^7.0.0", "@babel/core@^7.1.6", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.13.10", "@babel/core@^7.13.8", "@babel/core@^7.16.7", "@babel/core@^7.2.2", "@babel/core@^7.3.4": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz" - integrity sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA== + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz#b676450141e0b52a3d43bc91da86aa608f950ac4" + integrity sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.21.0" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-module-transforms" "^7.21.0" - "@babel/helpers" "^7.21.0" - "@babel/parser" "^7.21.0" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.0" - "@babel/types" "^7.21.0" - convert-source-map "^1.7.0" + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.7" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helpers" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/template" "^7.24.7" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.2.2" - semver "^6.3.0" + json5 "^2.2.3" + semver "^6.3.1" -"@babel/generator@^7.21.0", "@babel/generator@^7.21.1": - version "7.21.1" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz" - integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== +"@babel/generator@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz#1654d01de20ad66b4b4d99c135471bc654c55e6d" + integrity sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA== dependencies: - "@babel/types" "^7.21.0" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" + "@babel/types" "^7.24.7" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz" - integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== +"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab" + integrity sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.24.7" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz" - integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz#37d66feb012024f2422b762b9b2a7cfe27c7fba3" + integrity sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA== dependencies: - "@babel/helper-explode-assignable-expression" "^7.18.6" - "@babel/types" "^7.18.9" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" "@babel/helper-call-delegate@^7.10.1": version "7.12.13" - resolved "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.12.13.tgz" + resolved "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.12.13.tgz#119ef367451f90bed006c685816ba60fc33fee78" integrity sha512-K1kF0RXK/GpdS9OZDlBllG0+RQQtyzG/TC+nk0VkrUry4l4Xh2T7HdDsDOVlXQY/KcqvE/JQ84pKjKucdrg3FQ== dependencies: "@babel/helper-hoist-variables" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/helper-compilation-targets@^7.12.0", "@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0", "@babel/helper-compilation-targets@^7.20.7": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz" - integrity sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ== +"@babel/helper-compilation-targets@^7.12.0", "@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz#4eb6c4a80d6ffeac25ab8cd9a21b5dfa48d503a9" + integrity sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg== dependencies: - "@babel/compat-data" "^7.20.5" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.21.3" + "@babel/compat-data" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + browserslist "^4.22.2" lru-cache "^5.1.1" - semver "^6.3.0" - -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.5.5", "@babel/helper-create-class-features-plugin@^7.8.3": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz" - integrity sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.21.0" - "@babel/helper-member-expression-to-functions" "^7.21.0" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-replace-supers" "^7.20.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" - "@babel/helper-split-export-declaration" "^7.18.6" - -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.20.5": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.0.tgz" - integrity sha512-N+LaFW/auRSWdx7SHD/HiARwXQju1vXTW4fKr4u5SgBUTm51OKEjKgj+cs00ggW3kEvNqwErnlwuq7Y3xBe4eg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.24.7", "@babel/helper-create-class-features-plugin@^7.5.5", "@babel/helper-create-class-features-plugin@^7.8.3": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz#2eaed36b3a1c11c53bdf80d53838b293c52f5b3b" + integrity sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.7" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz#be4f435a80dc2b053c76eeb4b7d16dd22cfc89da" + integrity sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" regexpu-core "^5.3.1" + semver "^6.3.1" -"@babel/helper-define-polyfill-provider@^0.3.3": - version "0.3.3" - resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz" - integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== +"@babel/helper-define-polyfill-provider@^0.6.1", "@babel/helper-define-polyfill-provider@^0.6.2": + version "0.6.2" + resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" + integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== dependencies: - "@babel/helper-compilation-targets" "^7.17.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" debug "^4.1.1" lodash.debounce "^4.0.8" resolve "^1.14.2" - semver "^6.1.2" - -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== - -"@babel/helper-explode-assignable-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz" - integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0", "@babel/helper-function-name@^7.21.0": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz" - integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== - dependencies: - "@babel/template" "^7.20.7" - "@babel/types" "^7.21.0" - -"@babel/helper-hoist-variables@^7.12.13", "@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-member-expression-to-functions@^7.20.7", "@babel/helper-member-expression-to-functions@^7.21.0": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz" - integrity sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q== - dependencies: - "@babel/types" "^7.21.0" - -"@babel/helper-module-imports@^7.18.6", "@babel/helper-module-imports@^7.8.3": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.0", "@babel/helper-module-transforms@^7.21.2": - version "7.21.2" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz" - integrity sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.20.2" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.19.1" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.2" - "@babel/types" "^7.21.2" - -"@babel/helper-optimise-call-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz" - integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== - dependencies: - "@babel/types" "^7.18.6" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.22.5" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz" - integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== - -"@babel/helper-remap-async-to-generator@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz" - integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== +"@babel/helper-environment-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" + integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-wrap-function" "^7.18.9" - "@babel/types" "^7.18.9" + "@babel/types" "^7.24.7" -"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.20.7": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz" - integrity sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A== +"@babel/helper-function-name@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2" + integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA== dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-member-expression-to-functions" "^7.20.7" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.7" - "@babel/types" "^7.20.7" + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-hoist-variables@^7.12.13", "@babel/helper-hoist-variables@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz#b4ede1cde2fd89436397f30dc9376ee06b0f25ee" + integrity sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ== + dependencies: + "@babel/types" "^7.24.7" -"@babel/helper-simple-access@^7.20.2": - version "7.20.2" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz" - integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== - dependencies: - "@babel/types" "^7.20.2" +"@babel/helper-member-expression-to-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz#67613d068615a70e4ed5101099affc7a41c5225f" + integrity sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-module-imports@^7.24.7", "@babel/helper-module-imports@^7.8.3": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-module-transforms@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz#31b6c9a2930679498db65b685b1698bfd6c7daf8" + integrity sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" + +"@babel/helper-optimise-call-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz#8b0a0456c92f6b323d27cfd00d1d664e76692a0f" + integrity sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz#98c84fe6fe3d0d3ae7bfc3a5e166a46844feb2a0" + integrity sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg== + +"@babel/helper-remap-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz#b3f0f203628522713849d49403f1a414468be4c7" + integrity sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-wrap-function" "^7.24.7" + +"@babel/helper-replace-supers@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz#f933b7eed81a1c0265740edc91491ce51250f765" + integrity sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.7" + "@babel/helper-optimise-call-expression" "^7.24.7" + +"@babel/helper-simple-access@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz#5f8fa83b69ed5c27adc56044f8be2b3ea96669d9" + integrity sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-split-export-declaration@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856" + integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-string-parser@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz#4d2d0f14820ede3b9807ea5fc36dfc8cd7da07f2" + integrity sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg== + +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/helper-validator-option@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz#24c3bb77c7a425d1742eec8fb433b5a1b38e62f6" + integrity sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw== + +"@babel/helper-wrap-function@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz#52d893af7e42edca7c6d2c6764549826336aae1f" + integrity sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw== + dependencies: + "@babel/helper-function-name" "^7.24.7" + "@babel/template" "^7.24.7" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helpers@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz#aa2ccda29f62185acb5d42fb4a3a1b1082107416" + integrity sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg== + dependencies: + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/highlight@^7.10.4", "@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" -"@babel/helper-skip-transparent-expression-wrappers@^7.20.0": - version "7.20.0" - resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz" - integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== - dependencies: - "@babel/types" "^7.20.0" +"@babel/parser@^7.12.3", "@babel/parser@^7.14.7", "@babel/parser@^7.24.7", "@babel/parser@^7.4.5", "@babel/parser@^7.7.0": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85" + integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw== -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz#fd059fd27b184ea2b4c7e646868a9a381bbc3055" + integrity sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ== dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== - -"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": - version "7.19.1" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/helper-validator-option@^7.18.6": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz" - integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ== - -"@babel/helper-wrap-function@^7.18.9": - version "7.20.5" - resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz" - integrity sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz#468096ca44bbcbe8fcc570574e12eb1950e18107" + integrity sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg== dependencies: - "@babel/helper-function-name" "^7.19.0" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.5" - "@babel/types" "^7.20.5" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/helpers@^7.21.0": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz" - integrity sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz#e4eabdd5109acc399b38d7999b2ef66fc2022f89" + integrity sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ== dependencies: - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.0" - "@babel/types" "^7.21.0" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.7" -"@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz#71b21bb0286d5810e63a1538aa901c58e87375ec" + integrity sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg== dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/parser@^7.12.3", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.0", "@babel/parser@^7.21.2", "@babel/parser@^7.4.5", "@babel/parser@^7.7.0": - version "7.21.2" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz" - integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": +"@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.10.1", "@babel/plugin-proposal-class-properties@^7.16.5", "@babel/plugin-proposal-class-properties@^7.16.7": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz" - integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz" - integrity sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" - "@babel/plugin-proposal-optional-chaining" "^7.20.7" - -"@babel/plugin-proposal-async-generator-functions@^7.20.1": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz" - integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-remap-async-to-generator" "^7.18.9" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.10.1", "@babel/plugin-proposal-class-properties@^7.16.5", "@babel/plugin-proposal-class-properties@^7.16.7", "@babel/plugin-proposal-class-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-proposal-class-static-block@^7.18.6": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz" - integrity sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.21.0" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - -"@babel/plugin-proposal-decorators@^7.13.5", "@babel/plugin-proposal-decorators@^7.16.7": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.21.0.tgz" - integrity sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.21.0" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-replace-supers" "^7.20.7" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/plugin-syntax-decorators" "^7.21.0" - -"@babel/plugin-proposal-dynamic-import@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz" - integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - -"@babel/plugin-proposal-export-namespace-from@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz" - integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-json-strings@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz" - integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-json-strings" "^7.8.3" - -"@babel/plugin-proposal-logical-assignment-operators@^7.18.9": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz" - integrity sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug== +"@babel/plugin-proposal-decorators@^7.13.5", "@babel/plugin-proposal-decorators@^7.16.7", "@babel/plugin-proposal-decorators@^7.20.13": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.7.tgz#7e2dcfeda4a42596b57c4c9de1f5176bbfc532e3" + integrity sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-decorators" "^7.24.7" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6", "@babel/plugin-proposal-nullish-coalescing-operator@^7.4.4": +"@babel/plugin-proposal-nullish-coalescing-operator@^7.4.4": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz" - integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.20.2", "@babel/plugin-proposal-object-rest-spread@^7.5.5": +"@babel/plugin-proposal-object-rest-spread@^7.5.5": version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== dependencies: "@babel/compat-data" "^7.20.5" @@ -399,435 +353,567 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-transform-parameters" "^7.20.7" -"@babel/plugin-proposal-optional-catch-binding@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz" - integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-proposal-optional-chaining@^7.18.9", "@babel/plugin-proposal-optional-chaining@^7.20.7", "@babel/plugin-proposal-optional-chaining@^7.6.0": +"@babel/plugin-proposal-optional-chaining@^7.6.0": version "7.21.0" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea" integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== dependencies: "@babel/helper-plugin-utils" "^7.20.2" "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.16.5", "@babel/plugin-proposal-private-methods@^7.18.6": +"@babel/plugin-proposal-private-methods@^7.16.5", "@babel/plugin-proposal-private-methods@^7.16.7": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-proposal-private-property-in-object@^7.16.5", "@babel/plugin-proposal-private-property-in-object@^7.18.6": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz" - integrity sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw== +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== + +"@babel/plugin-proposal-private-property-in-object@^7.16.5", "@babel/plugin-proposal-private-property-in-object@^7.20.5": + version "7.21.11" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz#69d597086b6760c4126525cfa154f34631ff272c" + integrity sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" "@babel/helper-create-class-features-plugin" "^7.21.0" "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz" - integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-class-static-block@^7.14.5": version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-decorators@^7.21.0": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.21.0.tgz" - integrity sha512-tIoPpGBR8UuM4++ccWN3gifhVvQu7ZizuR1fklhRJrd5ewgbkUS+0KVFeWWxELtn18NTLoW32XV7zyOgIAiz+w== +"@babel/plugin-syntax-decorators@^7.23.3", "@babel/plugin-syntax-decorators@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.7.tgz#e4f8a0a8778ccec669611cd5aed1ed8e6e3a6fcf" + integrity sha512-Ui4uLJJrRV1lb38zg1yYTmRKmiZLiftDEvZN2iq3kd9kUFU+PttmzTbAFC2ucRk/XJmtek6G23gPsuZbhrT8fQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-import-assertions@^7.20.0": - version "7.20.0" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz" - integrity sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ== +"@babel/plugin-syntax-import-assertions@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz#2a0b406b5871a20a841240586b1300ce2088a778" + integrity sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz#b4f9ea95a79e6912480c4b626739f86a076624ca" + integrity sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== dependencies: - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-private-property-in-object@^7.14.5": version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-top-level-await@^7.14.5": version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.2.0", "@babel/plugin-syntax-typescript@^7.20.0", "@babel/plugin-syntax-typescript@^7.8.3": - version "7.20.0" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz" - integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== +"@babel/plugin-syntax-typescript@^7.2.0", "@babel/plugin-syntax-typescript@^7.24.7", "@babel/plugin-syntax-typescript@^7.8.3": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz#58d458271b4d3b6bb27ee6ac9525acbb259bad1c" + integrity sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA== dependencies: - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-arrow-functions@^7.18.6": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz" - integrity sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ== +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-async-to-generator@^7.18.6": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz" - integrity sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q== +"@babel/plugin-transform-arrow-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz#4f6886c11e423bd69f3ce51dbf42424a5f275514" + integrity sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ== dependencies: - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-remap-async-to-generator" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-block-scoped-functions@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz" - integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== +"@babel/plugin-transform-async-generator-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz#7330a5c50e05181ca52351b8fd01642000c96cfd" + integrity sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" + "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-transform-block-scoping@^7.20.2", "@babel/plugin-transform-block-scoping@^7.8.3": - version "7.23.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz" - integrity sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g== +"@babel/plugin-transform-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz#72a3af6c451d575842a7e9b5a02863414355bdcc" + integrity sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" -"@babel/plugin-transform-classes@^7.20.2": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz" - integrity sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ== +"@babel/plugin-transform-block-scoped-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz#a4251d98ea0c0f399dafe1a35801eaba455bbf1f" + integrity sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.21.0" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-replace-supers" "^7.20.7" - "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-block-scoping@^7.24.7", "@babel/plugin-transform-block-scoping@^7.8.3": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz#42063e4deb850c7bd7c55e626bf4e7ab48e6ce02" + integrity sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-class-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz#256879467b57b0b68c7ddfc5b76584f398cd6834" + integrity sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-class-static-block@^7.16.7", "@babel/plugin-transform-class-static-block@^7.22.11", "@babel/plugin-transform-class-static-block@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz#c82027ebb7010bc33c116d4b5044fbbf8c05484d" + integrity sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-transform-classes@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.7.tgz#4ae6ef43a12492134138c1e45913f7c46c41b4bf" + integrity sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.18.9": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz" - integrity sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ== +"@babel/plugin-transform-computed-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz#4cab3214e80bc71fae3853238d13d097b004c707" + integrity sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/template" "^7.20.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/template" "^7.24.7" -"@babel/plugin-transform-destructuring@^7.20.2": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz" - integrity sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA== +"@babel/plugin-transform-destructuring@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.7.tgz#a097f25292defb6e6cc16d6333a4cfc1e3c72d9e" + integrity sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz" - integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== +"@babel/plugin-transform-dotall-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz#5f8bf8a680f2116a7207e16288a5f974ad47a7a0" + integrity sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-duplicate-keys@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz" - integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== +"@babel/plugin-transform-duplicate-keys@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz#dd20102897c9a2324e5adfffb67ff3610359a8ee" + integrity sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-exponentiation-operator@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz" - integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== +"@babel/plugin-transform-dynamic-import@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz#4d8b95e3bae2b037673091aa09cd33fecd6419f4" + integrity sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-transform-for-of@^7.18.8": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz" - integrity sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ== +"@babel/plugin-transform-exponentiation-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz#b629ee22645f412024297d5245bce425c31f9b0d" + integrity sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-function-name@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz" - integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== +"@babel/plugin-transform-export-namespace-from@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz#176d52d8d8ed516aeae7013ee9556d540c53f197" + integrity sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA== dependencies: - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-function-name" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-transform-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz" - integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== +"@babel/plugin-transform-for-of@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz#f25b33f72df1d8be76399e1b8f3f9d366eb5bc70" + integrity sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" -"@babel/plugin-transform-member-expression-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz" - integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== +"@babel/plugin-transform-function-name@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz#6d8601fbffe665c894440ab4470bc721dd9131d6" + integrity sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-modules-amd@^7.12.1", "@babel/plugin-transform-modules-amd@^7.13.0", "@babel/plugin-transform-modules-amd@^7.19.6": - version "7.20.11" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz" - integrity sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g== +"@babel/plugin-transform-json-strings@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz#f3e9c37c0a373fee86e36880d45b3664cedaf73a" + integrity sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw== dependencies: - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-transform-modules-commonjs@^7.19.6": - version "7.21.2" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz" - integrity sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA== +"@babel/plugin-transform-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz#36b505c1e655151a9d7607799a9988fc5467d06c" + integrity sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ== dependencies: - "@babel/helper-module-transforms" "^7.21.2" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-modules-systemjs@^7.19.6": - version "7.20.11" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz" - integrity sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw== +"@babel/plugin-transform-logical-assignment-operators@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz#a58fb6eda16c9dc8f9ff1c7b1ba6deb7f4694cb0" + integrity sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw== dependencies: - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-validator-identifier" "^7.19.1" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-transform-modules-umd@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz" - integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== +"@babel/plugin-transform-member-expression-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz#3b4454fb0e302e18ba4945ba3246acb1248315df" + integrity sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw== dependencies: - "@babel/helper-module-transforms" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": - version "7.20.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz" - integrity sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA== +"@babel/plugin-transform-modules-amd@^7.12.1", "@babel/plugin-transform-modules-amd@^7.13.0", "@babel/plugin-transform-modules-amd@^7.20.11", "@babel/plugin-transform-modules-amd@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz#65090ed493c4a834976a3ca1cde776e6ccff32d7" + integrity sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.20.5" - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-new-target@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz" - integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== +"@babel/plugin-transform-modules-commonjs@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz#9fd5f7fdadee9085886b183f1ad13d1ab260f4ab" + integrity sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + +"@babel/plugin-transform-modules-systemjs@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz#f8012316c5098f6e8dee6ecd58e2bc6f003d0ce7" + integrity sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw== + dependencies: + "@babel/helper-hoist-variables" "^7.24.7" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" + +"@babel/plugin-transform-modules-umd@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz#edd9f43ec549099620df7df24e7ba13b5c76efc8" + integrity sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A== + dependencies: + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz#9042e9b856bc6b3688c0c2e4060e9e10b1460923" + integrity sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-new-target@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz#31ff54c4e0555cc549d5816e4ab39241dfb6ab00" + integrity sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz#1de4534c590af9596f53d67f52a92f12db984120" + integrity sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz#bea62b538c80605d8a0fac9b40f48e97efa7de63" + integrity sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-transform-object-assign@^7.8.3": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.18.6.tgz" - integrity sha512-mQisZ3JfqWh2gVXvfqYCAAyRs6+7oev+myBsTwW5RnPhYXOTuCEw2oe3YgxlXMViXUS53lG8koulI7mJ+8JE+A== + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.24.7.tgz#9d2cc7ee1482bd208fcc51974ca4f7649662c899" + integrity sha512-DOzAi77P9jSyPijHS7Z8vH0wLRcZH6wWxuIZgLAiy8FWOkcKMJmnyHjy2JM94k6A0QxlA/hlLh+R9T3GEryjNQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-object-super@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz" - integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== +"@babel/plugin-transform-object-rest-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz#d13a2b93435aeb8a197e115221cab266ba6e55d6" + integrity sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.24.7" -"@babel/plugin-transform-parameters@^7.20.1", "@babel/plugin-transform-parameters@^7.20.7": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz" - integrity sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA== +"@babel/plugin-transform-object-super@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz#66eeaff7830bba945dd8989b632a40c04ed625be" + integrity sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" -"@babel/plugin-transform-property-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz" - integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== +"@babel/plugin-transform-optional-catch-binding@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz#00eabd883d0dd6a60c1c557548785919b6e717b4" + integrity sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-transform-regenerator@^7.18.6": - version "7.20.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz" - integrity sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ== +"@babel/plugin-transform-optional-chaining@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.7.tgz#b8f6848a80cf2da98a8a204429bec04756c6d454" + integrity sha512-tK+0N9yd4j+x/4hxF3F0e0fu/VdcxU18y5SevtyM/PCFlQvXbR0Zmlo2eBrKtVipGNFzpq56o8WsIIKcJFUCRQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - regenerator-transform "^0.15.1" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-transform-reserved-words@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz" - integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== +"@babel/plugin-transform-parameters@^7.20.7", "@babel/plugin-transform-parameters@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz#5881f0ae21018400e320fc7eb817e529d1254b68" + integrity sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-private-methods@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz#e6318746b2ae70a59d023d5cc1344a2ba7a75f5e" + integrity sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-private-property-in-object@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz#4eec6bc701288c1fab5f72e6a4bbc9d67faca061" + integrity sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-transform-property-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz#f0d2ed8380dfbed949c42d4d790266525d63bbdc" + integrity sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-regenerator@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz#021562de4534d8b4b1851759fd7af4e05d2c47f8" + integrity sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + regenerator-transform "^0.15.2" + +"@babel/plugin-transform-reserved-words@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz#80037fe4fbf031fc1125022178ff3938bb3743a4" + integrity sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-transform-runtime@^7.12.1", "@babel/plugin-transform-runtime@^7.13.9": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.21.0.tgz" - integrity sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg== + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz#00a5bfaf8c43cf5c8703a8a6e82b59d9c58f38ca" + integrity sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw== dependencies: - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.20.2" - babel-plugin-polyfill-corejs2 "^0.3.3" - babel-plugin-polyfill-corejs3 "^0.6.0" - babel-plugin-polyfill-regenerator "^0.4.1" - semver "^6.3.0" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.1" + babel-plugin-polyfill-regenerator "^0.6.1" + semver "^6.3.1" -"@babel/plugin-transform-shorthand-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz" - integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== +"@babel/plugin-transform-shorthand-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz#85448c6b996e122fa9e289746140aaa99da64e73" + integrity sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-spread@^7.19.0": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz" - integrity sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw== +"@babel/plugin-transform-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz#e8a38c0fde7882e0fb8f160378f74bd885cc7bb3" + integrity sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" -"@babel/plugin-transform-sticky-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz" - integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== +"@babel/plugin-transform-sticky-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz#96ae80d7a7e5251f657b5cf18f1ea6bf926f5feb" + integrity sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-template-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz" - integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== +"@babel/plugin-transform-template-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz#a05debb4a9072ae8f985bcf77f3f215434c8f8c8" + integrity sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-typeof-symbol@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz" - integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== +"@babel/plugin-transform-typeof-symbol@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.7.tgz#f074be466580d47d6e6b27473a840c9f9ca08fb0" + integrity sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-typescript@^7.13.0": - version "7.21.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.0.tgz" - integrity sha512-xo///XTPp3mDzTtrqXoBlK9eiAYW3wv9JXglcn/u1bi60RW11dEUxIgA8cbnDhutS1zacjMRmAwxE0gMklLnZg== +"@babel/plugin-transform-typescript@^7.13.0", "@babel/plugin-transform-typescript@^7.20.13": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.7.tgz#b006b3e0094bf0813d505e0c5485679eeaf4a881" + integrity sha512-iLD3UNkgx2n/HrjBesVbYX6j0yqn/sJktvbtKKgcaLIQ4bTTQ8obAypc1VpyHPD2y4Phh9zHOaAt8e/L14wCpw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.21.0" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-typescript" "^7.20.0" + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-typescript" "^7.24.7" "@babel/plugin-transform-typescript@~7.4.0": version "7.4.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.4.5.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.4.5.tgz#ab3351ba35307b79981993536c93ff8be050ba28" integrity sha512-RPB/YeGr4ZrFKNwfuQRlMf2lxoCUaU01MTw39/OFE/RiL8HDjtn68BwEPft1P7JN4akyEmjGWAMNldOV7o9V2g== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -835,7 +921,7 @@ "@babel/plugin-transform-typescript@~7.5.0": version "7.5.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.5.5.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.5.5.tgz#6d862766f09b2da1cb1f7d505fe2aedab6b7d4b8" integrity sha512-pehKf4m640myZu5B2ZviLaiBlxMCjSZ1qTEO459AXKX5GnPueyulJeCqZFs1nz/Ya2dDzXQ1NxZ/kKNWyD4h6w== dependencies: "@babel/helper-create-class-features-plugin" "^7.5.5" @@ -844,68 +930,74 @@ "@babel/plugin-transform-typescript@~7.8.0": version "7.8.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.7.tgz" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.7.tgz#48bccff331108a7b3a28c3a4adc89e036dc3efda" integrity sha512-7O0UsPQVNKqpHeHLpfvOG4uXmlw+MOxYvUv6Otc9uH5SYMIxvF6eBdjkWvC3f9G+VXe0RsNExyAQBeTRug/wqQ== dependencies: "@babel/helper-create-class-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-typescript" "^7.8.3" -"@babel/plugin-transform-unicode-escapes@^7.18.10": - version "7.18.10" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz" - integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== +"@babel/plugin-transform-unicode-escapes@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz#2023a82ced1fb4971630a2e079764502c4148e0e" + integrity sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-unicode-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz" - integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== +"@babel/plugin-transform-unicode-property-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz#9073a4cd13b86ea71c3264659590ac086605bbcd" + integrity sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz#dfc3d4a51127108099b19817c0963be6a2adf19f" + integrity sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-sets-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz#d40705d67523803a576e29c63cef6e516b858ed9" + integrity sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/polyfill@^7.11.5": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz" + resolved "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz#1f2d6371d1261bbd961f3c5d5909150e12d0bd96" integrity sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g== dependencies: core-js "^2.6.5" regenerator-runtime "^0.13.4" -"@babel/preset-env@^7.10.2", "@babel/preset-env@^7.16.5", "@babel/preset-env@^7.16.7": - version "7.20.2" - resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz" - integrity sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg== - dependencies: - "@babel/compat-data" "^7.20.1" - "@babel/helper-compilation-targets" "^7.20.0" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-validator-option" "^7.18.6" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9" - "@babel/plugin-proposal-async-generator-functions" "^7.20.1" - "@babel/plugin-proposal-class-properties" "^7.18.6" - "@babel/plugin-proposal-class-static-block" "^7.18.6" - "@babel/plugin-proposal-dynamic-import" "^7.18.6" - "@babel/plugin-proposal-export-namespace-from" "^7.18.9" - "@babel/plugin-proposal-json-strings" "^7.18.6" - "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" - "@babel/plugin-proposal-numeric-separator" "^7.18.6" - "@babel/plugin-proposal-object-rest-spread" "^7.20.2" - "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" - "@babel/plugin-proposal-optional-chaining" "^7.18.9" - "@babel/plugin-proposal-private-methods" "^7.18.6" - "@babel/plugin-proposal-private-property-in-object" "^7.18.6" - "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" +"@babel/preset-env@^7.10.2", "@babel/preset-env@^7.16.5", "@babel/preset-env@^7.16.7", "@babel/preset-env@^7.20.2": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.7.tgz#ff067b4e30ba4a72f225f12f123173e77b987f37" + integrity sha512-1YZNsc+y6cTvWlDHidMBsQZrZfEFjRIo/BZCT906PMdzOyXtSLTgqGdrpcuTDCXyd11Am5uQULtDIcCfnTc8fQ== + dependencies: + "@babel/compat-data" "^7.24.7" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.7" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.7" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.20.0" + "@babel/plugin-syntax-import-assertions" "^7.24.7" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" @@ -915,113 +1007,127 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.18.6" - "@babel/plugin-transform-async-to-generator" "^7.18.6" - "@babel/plugin-transform-block-scoped-functions" "^7.18.6" - "@babel/plugin-transform-block-scoping" "^7.20.2" - "@babel/plugin-transform-classes" "^7.20.2" - "@babel/plugin-transform-computed-properties" "^7.18.9" - "@babel/plugin-transform-destructuring" "^7.20.2" - "@babel/plugin-transform-dotall-regex" "^7.18.6" - "@babel/plugin-transform-duplicate-keys" "^7.18.9" - "@babel/plugin-transform-exponentiation-operator" "^7.18.6" - "@babel/plugin-transform-for-of" "^7.18.8" - "@babel/plugin-transform-function-name" "^7.18.9" - "@babel/plugin-transform-literals" "^7.18.9" - "@babel/plugin-transform-member-expression-literals" "^7.18.6" - "@babel/plugin-transform-modules-amd" "^7.19.6" - "@babel/plugin-transform-modules-commonjs" "^7.19.6" - "@babel/plugin-transform-modules-systemjs" "^7.19.6" - "@babel/plugin-transform-modules-umd" "^7.18.6" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1" - "@babel/plugin-transform-new-target" "^7.18.6" - "@babel/plugin-transform-object-super" "^7.18.6" - "@babel/plugin-transform-parameters" "^7.20.1" - "@babel/plugin-transform-property-literals" "^7.18.6" - "@babel/plugin-transform-regenerator" "^7.18.6" - "@babel/plugin-transform-reserved-words" "^7.18.6" - "@babel/plugin-transform-shorthand-properties" "^7.18.6" - "@babel/plugin-transform-spread" "^7.19.0" - "@babel/plugin-transform-sticky-regex" "^7.18.6" - "@babel/plugin-transform-template-literals" "^7.18.9" - "@babel/plugin-transform-typeof-symbol" "^7.18.9" - "@babel/plugin-transform-unicode-escapes" "^7.18.10" - "@babel/plugin-transform-unicode-regex" "^7.18.6" - "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.20.2" - babel-plugin-polyfill-corejs2 "^0.3.3" - babel-plugin-polyfill-corejs3 "^0.6.0" - babel-plugin-polyfill-regenerator "^0.4.1" - core-js-compat "^3.25.1" - semver "^6.3.0" - -"@babel/preset-modules@^0.1.5": - version "0.1.5" - resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz" - integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.24.7" + "@babel/plugin-transform-async-generator-functions" "^7.24.7" + "@babel/plugin-transform-async-to-generator" "^7.24.7" + "@babel/plugin-transform-block-scoped-functions" "^7.24.7" + "@babel/plugin-transform-block-scoping" "^7.24.7" + "@babel/plugin-transform-class-properties" "^7.24.7" + "@babel/plugin-transform-class-static-block" "^7.24.7" + "@babel/plugin-transform-classes" "^7.24.7" + "@babel/plugin-transform-computed-properties" "^7.24.7" + "@babel/plugin-transform-destructuring" "^7.24.7" + "@babel/plugin-transform-dotall-regex" "^7.24.7" + "@babel/plugin-transform-duplicate-keys" "^7.24.7" + "@babel/plugin-transform-dynamic-import" "^7.24.7" + "@babel/plugin-transform-exponentiation-operator" "^7.24.7" + "@babel/plugin-transform-export-namespace-from" "^7.24.7" + "@babel/plugin-transform-for-of" "^7.24.7" + "@babel/plugin-transform-function-name" "^7.24.7" + "@babel/plugin-transform-json-strings" "^7.24.7" + "@babel/plugin-transform-literals" "^7.24.7" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.7" + "@babel/plugin-transform-member-expression-literals" "^7.24.7" + "@babel/plugin-transform-modules-amd" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.7" + "@babel/plugin-transform-modules-systemjs" "^7.24.7" + "@babel/plugin-transform-modules-umd" "^7.24.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.7" + "@babel/plugin-transform-new-target" "^7.24.7" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.7" + "@babel/plugin-transform-numeric-separator" "^7.24.7" + "@babel/plugin-transform-object-rest-spread" "^7.24.7" + "@babel/plugin-transform-object-super" "^7.24.7" + "@babel/plugin-transform-optional-catch-binding" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.7" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-private-methods" "^7.24.7" + "@babel/plugin-transform-private-property-in-object" "^7.24.7" + "@babel/plugin-transform-property-literals" "^7.24.7" + "@babel/plugin-transform-regenerator" "^7.24.7" + "@babel/plugin-transform-reserved-words" "^7.24.7" + "@babel/plugin-transform-shorthand-properties" "^7.24.7" + "@babel/plugin-transform-spread" "^7.24.7" + "@babel/plugin-transform-sticky-regex" "^7.24.7" + "@babel/plugin-transform-template-literals" "^7.24.7" + "@babel/plugin-transform-typeof-symbol" "^7.24.7" + "@babel/plugin-transform-unicode-escapes" "^7.24.7" + "@babel/plugin-transform-unicode-property-regex" "^7.24.7" + "@babel/plugin-transform-unicode-regex" "^7.24.7" + "@babel/plugin-transform-unicode-sets-regex" "^7.24.7" + "@babel/preset-modules" "0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.4" + babel-plugin-polyfill-regenerator "^0.6.1" + core-js-compat "^3.31.0" + semver "^6.3.1" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" "@babel/types" "^7.4.4" esutils "^2.0.2" "@babel/regjsgen@^0.8.0": version "0.8.0" - resolved "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz" + resolved "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@7.12.18", "@babel/runtime@^7.12.5", "@babel/runtime@^7.8.4": +"@babel/runtime@7.12.18": version "7.12.18" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.18.tgz" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.18.tgz#af137bd7e7d9705a412b3caaf991fe6aaa97831b" integrity sha512-BogPQ7ciE6SYAUPtlm9tWbgI9+2AgqSam6QivMgXgAT+fKbgppaj4ZX15MHeLC1PVF5sNk70huBu20XxWOs8Cg== dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.17.8": - version "7.23.2" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz" - integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg== +"@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.8.4": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" + integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.18.10", "@babel/template@^7.20.7": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz" - integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - -"@babel/traverse@^7.1.6", "@babel/traverse@^7.12.1", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0": - version "7.21.2" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz" - integrity sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.21.1" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.21.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.21.2" - "@babel/types" "^7.21.2" - debug "^4.1.0" +"@babel/template@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315" + integrity sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/traverse@^7.1.6", "@babel/traverse@^7.12.1", "@babel/traverse@^7.24.7", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz#de2b900163fa741721ba382163fe46a936c40cf5" + integrity sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-hoist-variables" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/types" "^7.24.7" + debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.1.6", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.7.2": - version "7.21.2" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz" - integrity sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw== +"@babel/types@^7.1.6", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.24.7", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.7.2": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz#6027fe12bc1aa724cd32ab113fb7f1988f1f66f2" + integrity sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q== dependencies: - "@babel/helper-string-parser" "^7.19.4" - "@babel/helper-validator-identifier" "^7.19.1" + "@babel/helper-string-parser" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" "@cnakazawa/watch@^1.0.3": version "1.0.4" - resolved "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz" + resolved "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ== dependencies: exec-sh "^0.3.2" @@ -1029,26 +1135,26 @@ "@colors/colors@1.5.0": version "1.5.0" - resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz" + resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== "@csstools/postcss-sass@^5.0.1": - version "5.0.1" - resolved "https://registry.npmjs.org/@csstools/postcss-sass/-/postcss-sass-5.0.1.tgz" - integrity sha512-GgQAOe6KfABEIHGh9KFqn/7sX2Dmx554PElvyhRFNADo2QV2N/CzlS+QHrrJmVJzaBn829f4JFcOd67mmYb5Eg== + version "5.1.1" + resolved "https://registry.npmjs.org/@csstools/postcss-sass/-/postcss-sass-5.1.1.tgz#135921df13bc56bee50c7470a66e4e9f3d5c89ae" + integrity sha512-La7bgTcM6YwPBLqlaXg7lMLry82iLv1a+S1RmgvHq2mH2Zd57L2anjZvJC8ACUHWc4M9fXws93dq6gaK0kZyAw== dependencies: "@csstools/sass-import-resolve" "^1.0.0" - sass "^1.49.7" - source-map "~0.7.3" + sass "^1.69.5" + source-map "~0.7.4" "@csstools/sass-import-resolve@^1.0.0": version "1.0.0" - resolved "https://registry.npmjs.org/@csstools/sass-import-resolve/-/sass-import-resolve-1.0.0.tgz" + resolved "https://registry.npmjs.org/@csstools/sass-import-resolve/-/sass-import-resolve-1.0.0.tgz#32c3cdb2f7af3cd8f0dca357b592e7271f3831b5" integrity sha512-pH4KCsbtBLLe7eqUrw8brcuFO8IZlN36JjdKlOublibVdAIPHCzEnpBWOVUXK5sCf+DpBi8ZtuWtjF0srybdeA== "@docfy/core@^0.4.4": version "0.4.4" - resolved "https://registry.npmjs.org/@docfy/core/-/core-0.4.4.tgz" + resolved "https://registry.npmjs.org/@docfy/core/-/core-0.4.4.tgz#041157870abcde99e64068cdbd79767b2c1a97b4" integrity sha512-m1q0KsRQZepXO5xZouOPXH9K8KJS7lnM6eDutHbYJsiUOG8e4ZpYYGJ+ckOTGzLKSXJGYFoRJRxO82Y9yaPhMA== dependencies: debug "^4.3.1" @@ -1074,7 +1180,7 @@ "@docfy/ember@^0.4.1": version "0.4.8" - resolved "https://registry.npmjs.org/@docfy/ember/-/ember-0.4.8.tgz" + resolved "https://registry.npmjs.org/@docfy/ember/-/ember-0.4.8.tgz#8fe3c525b0d44790bdc801bc3b5f588a27c840bd" integrity sha512-IxkLQJp4/pn4HvW6mxnd9ezErbrKM5i/maNUPCa3ixxFgPFMWRmwn05EP+6Y2ZAqOHaJXtkDMxllCg6tdFFFBQ== dependencies: "@docfy/core" "^0.4.4" @@ -1099,7 +1205,7 @@ "@ember-data/adapter@3.28.13": version "3.28.13" - resolved "https://registry.npmjs.org/@ember-data/adapter/-/adapter-3.28.13.tgz" + resolved "https://registry.npmjs.org/@ember-data/adapter/-/adapter-3.28.13.tgz#3b921365046a329f3eb1c72fc4964c6aff06e53b" integrity sha512-AwLJTs+GvxX72vfP3edV0hoMLD9oPWJNbnqxakXVN9xGTuk6/TeGQLMrVU3222GCoMMNrJ357Nip7kZeFo4IdA== dependencies: "@ember-data/private-build-infra" "3.28.13" @@ -1112,7 +1218,7 @@ "@ember-data/canary-features@3.28.13": version "3.28.13" - resolved "https://registry.npmjs.org/@ember-data/canary-features/-/canary-features-3.28.13.tgz" + resolved "https://registry.npmjs.org/@ember-data/canary-features/-/canary-features-3.28.13.tgz#59cd75b94bfff86f85affb42e66016c71f45f02e" integrity sha512-fgpcB0wmtUjZeqcIKkfP/MclQjY5r8ft8YZhPlvQh2MIx+3d3nCNRXB6lEUdRdQphFEag2towONFEIsiOAgs3Q== dependencies: ember-cli-babel "^7.26.6" @@ -1120,7 +1226,7 @@ "@ember-data/debug@3.28.13": version "3.28.13" - resolved "https://registry.npmjs.org/@ember-data/debug/-/debug-3.28.13.tgz" + resolved "https://registry.npmjs.org/@ember-data/debug/-/debug-3.28.13.tgz#eb20779de83429f5d493d3c8e81ced468fa5974d" integrity sha512-ofny/Grpqx1lM6KWy5q75/b2/B+zQ4B4Ynk7SrQ//sFvpX3gjuP8iN07SKTHSN07vedlC+7QNhNJdCQwyqK1Fg== dependencies: "@ember-data/private-build-infra" "3.28.13" @@ -1132,7 +1238,7 @@ "@ember-data/model@3.28.13": version "3.28.13" - resolved "https://registry.npmjs.org/@ember-data/model/-/model-3.28.13.tgz" + resolved "https://registry.npmjs.org/@ember-data/model/-/model-3.28.13.tgz#50ac1bd5783e7cc51344767d5ff46f84198f4d1a" integrity sha512-V5Hgzz5grNWTSrKGksY9xeOsTDLN/d3qsVMu26FWWHP5uqyWT0Cd4LSRpNxs14PsTFDcbrtGKaZv3YVksZfFEQ== dependencies: "@ember-data/canary-features" "3.28.13" @@ -1150,7 +1256,7 @@ "@ember-data/private-build-infra@3.28.13": version "3.28.13" - resolved "https://registry.npmjs.org/@ember-data/private-build-infra/-/private-build-infra-3.28.13.tgz" + resolved "https://registry.npmjs.org/@ember-data/private-build-infra/-/private-build-infra-3.28.13.tgz#828a27e724240b1ef70ae5dd8ab8be1f61275929" integrity sha512-8gT3/gnmbNgFIMVdHBpl3xFGJefJE26VUIidFHTF1/N1aumVUlEhnXH0BSPxvxTnFXz/klGSTOMs+sDsx3jw6A== dependencies: "@babel/plugin-transform-block-scoping" "^7.8.3" @@ -1182,7 +1288,7 @@ "@ember-data/record-data@3.28.13": version "3.28.13" - resolved "https://registry.npmjs.org/@ember-data/record-data/-/record-data-3.28.13.tgz" + resolved "https://registry.npmjs.org/@ember-data/record-data/-/record-data-3.28.13.tgz#2bf169404732e126489d3b3a8dc6c0dfca8b5f5f" integrity sha512-0qYOxQr901eZ0JoYVt/IiszZYuNefqO6yiwKw0VH2dmWhVniQSp+Da9YnoKN9U2KgR4NdxKiUs2j9ZLNZ+bH7g== dependencies: "@ember-data/canary-features" "3.28.13" @@ -1195,12 +1301,12 @@ "@ember-data/rfc395-data@^0.0.4": version "0.0.4" - resolved "https://registry.npmjs.org/@ember-data/rfc395-data/-/rfc395-data-0.0.4.tgz" + resolved "https://registry.npmjs.org/@ember-data/rfc395-data/-/rfc395-data-0.0.4.tgz#ecb86efdf5d7733a76ff14ea651a1b0ed1f8a843" integrity sha512-tGRdvgC9/QMQSuSuJV45xoyhI0Pzjm7A9o/MVVA3HakXIImJbbzx/k/6dO9CUEQXIyS2y0fW6C1XaYOG7rY0FQ== "@ember-data/serializer@3.28.13": version "3.28.13" - resolved "https://registry.npmjs.org/@ember-data/serializer/-/serializer-3.28.13.tgz" + resolved "https://registry.npmjs.org/@ember-data/serializer/-/serializer-3.28.13.tgz#6dfa8ba17c0ea192313134643dbe56adf45a722a" integrity sha512-BlYXi8ObH0B5G7QeWtkf9u8PrhdlfAxOAsOuOPZPCTzWsQlmyzV6M9KvBmIAvJtM2IQ3a5BX2o71eP6/7MJDUg== dependencies: "@ember-data/private-build-infra" "3.28.13" @@ -1211,7 +1317,7 @@ "@ember-data/store@3.28.13": version "3.28.13" - resolved "https://registry.npmjs.org/@ember-data/store/-/store-3.28.13.tgz" + resolved "https://registry.npmjs.org/@ember-data/store/-/store-3.28.13.tgz#be3c3fca03d155767af72422f6a3c6dcd6147be8" integrity sha512-y1ddWLfR20l3NN9fNfIAFWCmREnC6hjKCZERDgkvBgZOCAKcs+6bVJGyMmKBcsp4W7kanqKn71tX7Y63jp+jXQ== dependencies: "@ember-data/canary-features" "3.28.13" @@ -1225,7 +1331,7 @@ "@ember-decorators/component@^6.1.1": version "6.1.1" - resolved "https://registry.npmjs.org/@ember-decorators/component/-/component-6.1.1.tgz" + resolved "https://registry.npmjs.org/@ember-decorators/component/-/component-6.1.1.tgz#b360dc4fa8e576ee1c840879399ef1745fd96e06" integrity sha512-Cj8tY/c0MC/rsipqsiWLh3YVN72DK92edPYamD/HzvftwzC6oDwawWk8RmStiBnG9PG/vntAt41l3S7HSSA+1Q== dependencies: "@ember-decorators/utils" "^6.1.1" @@ -1233,7 +1339,7 @@ "@ember-decorators/object@^6.1.1": version "6.1.1" - resolved "https://registry.npmjs.org/@ember-decorators/object/-/object-6.1.1.tgz" + resolved "https://registry.npmjs.org/@ember-decorators/object/-/object-6.1.1.tgz#50c922f5ac9af3ddd381cb6a43a031dfd9a70c7a" integrity sha512-cb4CNR9sRoA31J3FCOFLDuR9ztM4wO9w1WlS4JeNRS7Z69SlB/XSXB/vplA3i9OOaXEy/zKWbu5ndZrHz0gvLw== dependencies: "@ember-decorators/utils" "^6.1.1" @@ -1241,31 +1347,31 @@ "@ember-decorators/utils@^6.1.0", "@ember-decorators/utils@^6.1.1": version "6.1.1" - resolved "https://registry.npmjs.org/@ember-decorators/utils/-/utils-6.1.1.tgz" + resolved "https://registry.npmjs.org/@ember-decorators/utils/-/utils-6.1.1.tgz#6b619814942b4fb3747cfa9f540c9f05283d7c5e" integrity sha512-0KqnoeoLKb6AyoSU65TRF5T85wmS4uDn06oARddwNPxxf/lt5jQlh41uX3W7V/fWL9tPu8x1L1Vvpc80MN1+YA== dependencies: ember-cli-babel "^7.1.3" "@ember/edition-utils@^1.2.0": version "1.2.0" - resolved "https://registry.npmjs.org/@ember/edition-utils/-/edition-utils-1.2.0.tgz" + resolved "https://registry.npmjs.org/@ember/edition-utils/-/edition-utils-1.2.0.tgz#a039f542dc14c8e8299c81cd5abba95e2459cfa6" integrity sha512-VmVq/8saCaPdesQmftPqbFtxJWrzxNGSQ+e8x8LLe3Hjm36pJ04Q8LeORGZkAeOhldoUX9seLGmSaHeXkIqoog== "@ember/optional-features@^2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/@ember/optional-features/-/optional-features-2.0.0.tgz" - integrity sha512-4gkvuGRYfpAh1nwAz306cmMeC1mG7wxZnbsBZ09mMaMX/W7IyKOKc/38JwrDPUFUalmNEM7q7JEPcmew2M3Dog== + version "2.1.0" + resolved "https://registry.npmjs.org/@ember/optional-features/-/optional-features-2.1.0.tgz#8e15672ca342b5ca6d4d8a00558dc696db0d6f16" + integrity sha512-IXjDpTFhsjPk9h3OXwXjlRfhM/Wjtw2E71Xos/81ZsTTwZMB9H+DWhsxePXOkzYy7Jvw4TIzKbMfcnT8mrtwWQ== dependencies: - chalk "^4.1.0" - ember-cli-version-checker "^5.1.1" - glob "^7.1.6" + chalk "^4.1.2" + ember-cli-version-checker "^5.1.2" + glob "^7.1.7" inquirer "^7.3.3" mkdirp "^1.0.4" silent-error "^1.1.1" "@ember/render-modifiers@^1.0.2": version "1.0.2" - resolved "https://registry.npmjs.org/@ember/render-modifiers/-/render-modifiers-1.0.2.tgz" + resolved "https://registry.npmjs.org/@ember/render-modifiers/-/render-modifiers-1.0.2.tgz#2e87c48db49d922ce4850d707215caaac60d8444" integrity sha512-6tEnHl5+62NTSAG2mwhGMFPhUrJQjoVqV+slsn+rlTknm2Zik+iwxBQEbwaiQOU1FUYxkS8RWcieovRNMR8inQ== dependencies: ember-cli-babel "^7.10.0" @@ -1273,24 +1379,24 @@ "@ember/render-modifiers@^2.0.0", "@ember/render-modifiers@^2.0.5": version "2.1.0" - resolved "https://registry.npmjs.org/@ember/render-modifiers/-/render-modifiers-2.1.0.tgz" + resolved "https://registry.npmjs.org/@ember/render-modifiers/-/render-modifiers-2.1.0.tgz#f4fff95a8b5cfbe947ec46644732d511711c5bf9" integrity sha512-LruhfoDv2itpk0fA0IC76Sxjcnq/7BC6txpQo40hOko8Dn6OxwQfxkPIbZGV0Cz7df+iX+VJrcYzNIvlc3w2EQ== dependencies: "@embroider/macros" "^1.0.0" ember-cli-babel "^7.26.11" ember-modifier-manager-polyfill "^1.2.0" -"@ember/string@^3.0.0": +"@ember/string@^3.0.0", "@ember/string@^3.1.1": version "3.1.1" - resolved "https://registry.npmjs.org/@ember/string/-/string-3.1.1.tgz" + resolved "https://registry.npmjs.org/@ember/string/-/string-3.1.1.tgz#0a5ac0d1e4925259e41d5c8d55ef616117d47ff0" integrity sha512-UbXJ+k3QOrYN4SRPHgXCqYIJ+yWWUg1+vr0H4DhdQPTy8LJfyqwZ2tc5uqpSSnEXE+/1KopHBE5J8GDagAg5cg== dependencies: ember-cli-babel "^7.26.6" "@ember/test-helpers@^2.6.0": - version "2.9.3" - resolved "https://registry.npmjs.org/@ember/test-helpers/-/test-helpers-2.9.3.tgz" - integrity sha512-ejVg4Dj+G/6zyLvQsYOvmGiOLU6AS94tY4ClaO1E2oVvjjtVJIRmVLFN61I+DuyBg9hS3cFoPjQRTZB9MRIbxQ== + version "2.9.4" + resolved "https://registry.npmjs.org/@ember/test-helpers/-/test-helpers-2.9.4.tgz#985022e9ba05cfc918bcf08b77cbb355f85b723e" + integrity sha512-z+Qs1NYWyIVDmrY6WdmOS5mdG1lJ5CFfzh6dRhLfs9lq45deDaDrVNcaCYhnNeJZTvUBK2XR2SvPcZm0RloXdA== dependencies: "@ember/test-waiters" "^3.0.0" "@embroider/macros" "^1.10.0" @@ -1301,36 +1407,29 @@ ember-cli-htmlbars "^6.1.1" ember-destroyable-polyfill "^2.0.3" -"@ember/test-waiters@^3.0.0", "@ember/test-waiters@^3.0.2": - version "3.0.2" - resolved "https://registry.npmjs.org/@ember/test-waiters/-/test-waiters-3.0.2.tgz" - integrity sha512-H8Q3Xy9rlqhDKnQpwt2pzAYDouww4TZIGSI1pZJhM7mQIGufQKuB0ijzn/yugA6Z+bNdjYp1HioP8Y4hn2zazQ== +"@ember/test-waiters@^3.0.0", "@ember/test-waiters@^3.1.0": + version "3.1.0" + resolved "https://registry.npmjs.org/@ember/test-waiters/-/test-waiters-3.1.0.tgz#61399919cbf793978da0b8bfdfdb7bca0cb80e9e" + integrity sha512-bb9h95ktG2wKY9+ja1sdsFBdOms2lB19VWs8wmNpzgHv1NCetonBoV5jHBV4DHt0uS1tg9z66cZqhUVlYs96KQ== dependencies: calculate-cache-key-for-tree "^2.0.0" ember-cli-babel "^7.26.6" ember-cli-version-checker "^5.1.2" semver "^7.3.5" -"@embroider/addon-shim@1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@embroider/addon-shim/-/addon-shim-1.8.3.tgz#2368510b8ce42d50d02cb3289c32e260dfa34bd9" - integrity sha512-7pyHwzT6ESXc3nZsB8rfnirLkUhQWdvj6CkYH+0MUPN74mX4rslf7pnBqZE/KZkW3uBIaBYvU8fxi0hcKC/Paw== - dependencies: - "@embroider/shared-internals" "^1.8.3" - semver "^7.3.5" - -"@embroider/addon-shim@^1.0.0", "@embroider/addon-shim@^1.2.0", "@embroider/addon-shim@^1.8.4": - version "1.8.4" - resolved "https://registry.npmjs.org/@embroider/addon-shim/-/addon-shim-1.8.4.tgz" - integrity sha512-sFhfWC0vI18KxVenmswQ/ShIvBg4juL8ubI+Q3NTSdkCTeaPQ/DIOUF6oR5DCQ8eO/TkIaw+kdG3FkTY6yNJqA== +"@embroider/addon-shim@^1.0.0", "@embroider/addon-shim@^1.2.0", "@embroider/addon-shim@^1.8.3", "@embroider/addon-shim@^1.8.4", "@embroider/addon-shim@^1.8.7": + version "1.8.9" + resolved "https://registry.npmjs.org/@embroider/addon-shim/-/addon-shim-1.8.9.tgz#ef37eba069d391b2d2a80aa62880c469051c4d43" + integrity sha512-qyN64T1jMHZ99ihlk7VFHCWHYZHLE1DOdHi0J7lmn5waV1DoW7gD8JLi1i7FregzXtKhbDc7shyEmTmWPTs8MQ== dependencies: - "@embroider/shared-internals" "^2.0.0" + "@embroider/shared-internals" "^2.6.0" broccoli-funnel "^3.0.8" + common-ancestor-path "^1.0.1" semver "^7.3.8" "@embroider/core@0.36.0": version "0.36.0" - resolved "https://registry.npmjs.org/@embroider/core/-/core-0.36.0.tgz" + resolved "https://registry.npmjs.org/@embroider/core/-/core-0.36.0.tgz#fbbd60d29c3fcbe02b4e3e63e6043a43de2b9ce3" integrity sha512-J6esENP+aNt+/r070cF1RCJyCi/Rn1I6uFp37vxyLWwvGDuT0E7wGcaPU29VBkBFqxi4Z1n4F796BaGHv+kX6w== dependencies: "@babel/core" "^7.12.3" @@ -1369,7 +1468,7 @@ "@embroider/macros@0.36.0", "@embroider/macros@^0.36.0": version "0.36.0" - resolved "https://registry.npmjs.org/@embroider/macros/-/macros-0.36.0.tgz" + resolved "https://registry.npmjs.org/@embroider/macros/-/macros-0.36.0.tgz#5330f1e6f12112f0f68e34b3e4855dc7dd3c69a5" integrity sha512-w37G4uXG+Wi3K3EHSFBSr/n6kGFXYG8nzZ9ptzDOC7LP3Oh5/MskBnVZW3+JkHXUPEqKsDGlxPxCVpPl1kQyjQ== dependencies: "@babel/core" "^7.12.3" @@ -1384,7 +1483,7 @@ "@embroider/macros@0.41.0", "@embroider/macros@^0.41.0": version "0.41.0" - resolved "https://registry.npmjs.org/@embroider/macros/-/macros-0.41.0.tgz" + resolved "https://registry.npmjs.org/@embroider/macros/-/macros-0.41.0.tgz#3e78b6f388d7229906abf4c75edfff8bb0208aca" integrity sha512-QISzwEEfLsskZeL0jyZDs1RoQSotwBWj+4upTogNHuxQP5j/9H3IMG/3QB1gh8GEpbudATb/cS4NDYK3UBxufw== dependencies: "@embroider/shared-internals" "0.41.0" @@ -1396,7 +1495,7 @@ "@embroider/macros@0.47.2", "@embroider/macros@^0.47.0": version "0.47.2" - resolved "https://registry.npmjs.org/@embroider/macros/-/macros-0.47.2.tgz" + resolved "https://registry.npmjs.org/@embroider/macros/-/macros-0.47.2.tgz#23cbe92cac3c24747f054e1eea2a22538bf7ebd0" integrity sha512-ViNWluJCeM5OPlM3rs8kdOz3RV5rpfXX5D2rDnc/q86xRS0xf4NFEjYRV7W6fBcD0b3v5jSHDTwrjq9Kee4rHg== dependencies: "@embroider/shared-internals" "0.47.2" @@ -1409,7 +1508,7 @@ "@embroider/macros@^0.42.3": version "0.42.3" - resolved "https://registry.npmjs.org/@embroider/macros/-/macros-0.42.3.tgz" + resolved "https://registry.npmjs.org/@embroider/macros/-/macros-0.42.3.tgz#eb4dc35c43f1cb1d14298219ba037f8cead06081" integrity sha512-4I+Sde8FU7QMwNQ3gYtj8fdBTqUeoPDn61XuV4Xng7p9LszQksGDXtyEhWrf9KWU3G+NtrZotY5LICd5P+E3tw== dependencies: "@embroider/shared-internals" "0.42.3" @@ -1419,12 +1518,12 @@ resolve "^1.20.0" semver "^7.3.2" -"@embroider/macros@^0.50.0 || ^1.0.0", "@embroider/macros@^1.13.0", "@embroider/macros@^1.2.0": - version "1.13.2" - resolved "https://registry.yarnpkg.com/@embroider/macros/-/macros-1.13.2.tgz#07dda11313a2539f403404881b729e622a80ca17" - integrity sha512-AUgJ71xG8kjuTx8XB1AQNBiebJuXRfhcHr318dCwnQz9VRXdYSnEEqf38XRvGYIoCvIyn/3c72LrSwzaJqknOA== +"@embroider/macros@^0.50.0 || ^1.0.0", "@embroider/macros@^1.0.0", "@embroider/macros@^1.10.0", "@embroider/macros@^1.16.1", "@embroider/macros@^1.2.0": + version "1.16.5" + resolved "https://registry.npmjs.org/@embroider/macros/-/macros-1.16.5.tgz#871addab2103b554c6b6a3a337c00e3f0a0462ac" + integrity sha512-Oz8bUZvZzOV1Gk3qSgIzZJJzs6acclSTcEFyB+KdKbKqjTC3uebn53aU2gAlLU7/YdTRZrg2gNbQuwAp+tGkGg== dependencies: - "@embroider/shared-internals" "2.5.0" + "@embroider/shared-internals" "2.6.2" assert-never "^1.2.1" babel-import-util "^2.0.0" ember-cli-babel "^7.26.6" @@ -1433,23 +1532,9 @@ resolve "^1.20.0" semver "^7.3.2" -"@embroider/macros@^1.0.0", "@embroider/macros@^1.10.0": - version "1.10.0" - resolved "https://registry.npmjs.org/@embroider/macros/-/macros-1.10.0.tgz" - integrity sha512-LMbfQGk/a+f6xtvAv5fq/wf2LRxETnbgSCLUf/z6ebzmuskOUxrke+uP55chF/loWrARi9g6erFQ7RDOUoBMSg== - dependencies: - "@embroider/shared-internals" "2.0.0" - assert-never "^1.2.1" - babel-import-util "^1.1.0" - ember-cli-babel "^7.26.6" - find-up "^5.0.0" - lodash "^4.17.21" - resolve "^1.20.0" - semver "^7.3.2" - "@embroider/shared-internals@0.41.0": version "0.41.0" - resolved "https://registry.npmjs.org/@embroider/shared-internals/-/shared-internals-0.41.0.tgz" + resolved "https://registry.npmjs.org/@embroider/shared-internals/-/shared-internals-0.41.0.tgz#2553f026d4f48ea1fd11235501feb63bf49fa306" integrity sha512-fiqUVB6cfh2UBEFE4yhT5EzagkZ1Q26+OhBV0nJszFEJZx4DqVIb3pxSSZ8P+HhpxuJsQ2XpMA/j02ZPFZfbdQ== dependencies: ember-rfc176-data "^0.3.17" @@ -1462,7 +1547,7 @@ "@embroider/shared-internals@0.42.3": version "0.42.3" - resolved "https://registry.npmjs.org/@embroider/shared-internals/-/shared-internals-0.42.3.tgz" + resolved "https://registry.npmjs.org/@embroider/shared-internals/-/shared-internals-0.42.3.tgz#65224fe86c55790417078b267add8f54148b59e3" integrity sha512-AIFRumaGxzhzzSswtk97Z0ttu0dyRhXoDuOi6kPYHoprUdtt7biRAksrsbutWWdFapve7vKHFZdYVuiG8IbX0A== dependencies: ember-rfc176-data "^0.3.17" @@ -1475,7 +1560,7 @@ "@embroider/shared-internals@0.47.2": version "0.47.2" - resolved "https://registry.npmjs.org/@embroider/shared-internals/-/shared-internals-0.47.2.tgz" + resolved "https://registry.npmjs.org/@embroider/shared-internals/-/shared-internals-0.47.2.tgz#24e9fa0dd9c529d5c996ee1325729ea08d1fa19f" integrity sha512-SxdZYjAE0fiM5zGDz+12euWIsQZ1tsfR1k+NKmiWMyLhA5T3pNgbR2/Djvx/cVIxOtEavGGSllYbzRKBtV4xMg== dependencies: babel-import-util "^0.2.0" @@ -1486,24 +1571,10 @@ semver "^7.3.5" typescript-memoize "^1.0.1" -"@embroider/shared-internals@2.0.0", "@embroider/shared-internals@^2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/@embroider/shared-internals/-/shared-internals-2.0.0.tgz" - integrity sha512-qZ2/xky9mWm5YC6noOa6AiAwgISEQ78YTZNv4SNu2PFgEK/H+Ha/3ddngzGSsnXkVnIHZyxIBzhxETonQYHY9g== - dependencies: - babel-import-util "^1.1.0" - ember-rfc176-data "^0.3.17" - fs-extra "^9.1.0" - js-string-escape "^1.0.1" - lodash "^4.17.21" - resolve-package-path "^4.0.1" - semver "^7.3.5" - typescript-memoize "^1.0.1" - -"@embroider/shared-internals@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@embroider/shared-internals/-/shared-internals-2.5.0.tgz#4a0b5127c589718fae60fc22f81374ed558b944a" - integrity sha512-7qzrb7GVIyNqeY0umxoeIvjDC+ay1b+wb2yCVuYTUYrFfLAkLEy9FNI3iWCi3RdQ9OFjgcAxAnwsAiPIMZZ3pQ== +"@embroider/shared-internals@2.6.2", "@embroider/shared-internals@^2.0.0", "@embroider/shared-internals@^2.6.0": + version "2.6.2" + resolved "https://registry.npmjs.org/@embroider/shared-internals/-/shared-internals-2.6.2.tgz#66297a8606587108f9dbcbaa1a9dcc6b4a4ca605" + integrity sha512-jL3Bjn8C73AUBlTex+VixP7YmqvPNN/BZFB85odTstzLFOuR8y2mmGiuWbq17qNuFyoxc6xtndMnAeqwCXBNkA== dependencies: babel-import-util "^2.0.0" debug "^4.3.2" @@ -1511,13 +1582,14 @@ fs-extra "^9.1.0" js-string-escape "^1.0.1" lodash "^4.17.21" + minimatch "^3.0.4" resolve-package-path "^4.0.1" semver "^7.3.5" typescript-memoize "^1.0.1" -"@embroider/shared-internals@^1.0.0", "@embroider/shared-internals@^1.8.3": +"@embroider/shared-internals@^1.0.0": version "1.8.3" - resolved "https://registry.npmjs.org/@embroider/shared-internals/-/shared-internals-1.8.3.tgz" + resolved "https://registry.npmjs.org/@embroider/shared-internals/-/shared-internals-1.8.3.tgz#52d868dc80016e9fe983552c0e516f437bf9b9f9" integrity sha512-N5Gho6Qk8z5u+mxLCcMYAoQMbN4MmH+z2jXwQHVs859bxuZTxwF6kKtsybDAASCtd2YGxEmzcc1Ja/wM28824w== dependencies: babel-import-util "^1.1.0" @@ -1531,43 +1603,34 @@ "@embroider/util@^0.39.1 || ^0.40.0 || ^0.41.0": version "0.41.0" - resolved "https://registry.npmjs.org/@embroider/util/-/util-0.41.0.tgz" + resolved "https://registry.npmjs.org/@embroider/util/-/util-0.41.0.tgz#5324cb4742aa4ed8d613c4f88a466f73e4e6acc1" integrity sha512-ytA3J/YfQh7FEUEBwz3ezTqQNm/S5et5rZw3INBIy4Ak4x0NXV/VXLjyL8mv3txL8fGknZTBdXEhDsHUKIq8SQ== dependencies: "@embroider/macros" "0.41.0" broccoli-funnel "^3.0.5" ember-cli-babel "^7.23.1" -"@embroider/util@^0.39.1 || ^0.40.0 || ^0.41.0 || ^1.0.0", "@embroider/util@^1.0.0": - version "1.12.0" - resolved "https://registry.yarnpkg.com/@embroider/util/-/util-1.12.0.tgz#4b7828650b55f8498f1e78bb63e27e77835e926f" - integrity sha512-P4M1QADEH9ceIYC9mwHeV+6DDgEIQQYFfZi728nVKqTAxakXoiLgu/BCyQmEGyow9fYEPYaC1boDCZxW2JQAXg== +"@embroider/util@^0.39.1 || ^0.40.0 || ^0.41.0 || ^1.0.0", "@embroider/util@^1.0.0", "@embroider/util@^1.9.0": + version "1.13.1" + resolved "https://registry.npmjs.org/@embroider/util/-/util-1.13.1.tgz#c6d4a569b331cbf805e68e7fa6602f248438bde6" + integrity sha512-MRbs2FPO4doQ31YHIYk+QKChEs7k15aTsMk8QmO4eKiuQq9OT0sr1oasObZyGB8cVVbr29WWRWmsNirxzQtHIg== dependencies: - "@embroider/macros" "^1.13.0" + "@embroider/macros" "^1.16.1" broccoli-funnel "^3.0.5" ember-cli-babel "^7.26.11" "@embroider/util@^0.47.0": version "0.47.2" - resolved "https://registry.npmjs.org/@embroider/util/-/util-0.47.2.tgz" + resolved "https://registry.npmjs.org/@embroider/util/-/util-0.47.2.tgz#d06497b4b84c07ed9c7b628293bb019c533f4556" integrity sha512-g9OqnFJPktGu9NS0Ug3Pxz1JE3jeDceeVE4IrlxDrVmBXMA/GrBvpwjolWgl6jh97cMJyExdz62jIvPHV4256Q== dependencies: "@embroider/macros" "0.47.2" broccoli-funnel "^3.0.5" ember-cli-babel "^7.23.1" -"@embroider/util@^1.9.0": - version "1.10.0" - resolved "https://registry.npmjs.org/@embroider/util/-/util-1.10.0.tgz" - integrity sha512-utAFKoq6ajI27jyqjvX3PiGL4m+ZyGVlVNbSbE/nOqi2llRyAkh5ltH1WkIK7jhdwQFJouo1NpOSj9J3/HDa3A== - dependencies: - "@embroider/macros" "^1.10.0" - broccoli-funnel "^3.0.5" - ember-cli-babel "^7.26.11" - "@eslint/eslintrc@^0.4.3": version "0.4.3" - resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== dependencies: ajv "^6.12.4" @@ -1582,7 +1645,7 @@ "@formatjs/ecma402-abstract@1.11.4": version "1.11.4" - resolved "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz" + resolved "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz#b962dfc4ae84361f9f08fbce411b4e4340930eda" integrity sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw== dependencies: "@formatjs/intl-localematcher" "0.2.25" @@ -1590,21 +1653,21 @@ "@formatjs/ecma402-abstract@1.6.4": version "1.6.4" - resolved "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.6.4.tgz" + resolved "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.6.4.tgz#cff5ef03837fb6bae70b16d04940213c17e87884" integrity sha512-ukFjGD9dLsxcD9D5AEshJqQElPQeUAlTALT/lzIV6OcYojyuU81gw/uXDUOrs6XW79jtOJwQDkLqHbCJBJMOTw== dependencies: tslib "^2.1.0" "@formatjs/fast-memoize@1.2.1": version "1.2.1" - resolved "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-1.2.1.tgz" + resolved "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-1.2.1.tgz#e6f5aee2e4fd0ca5edba6eba7668e2d855e0fc21" integrity sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg== dependencies: tslib "^2.1.0" "@formatjs/icu-messageformat-parser@2.1.0": version "2.1.0" - resolved "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.1.0.tgz" + resolved "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.1.0.tgz#a54293dd7f098d6a6f6a084ab08b6d54a3e8c12d" integrity sha512-Qxv/lmCN6hKpBSss2uQ8IROVnta2r9jd3ymUEIjm2UyIkUCHVcbUVRGL/KS/wv7876edvsPe+hjHVJ4z8YuVaw== dependencies: "@formatjs/ecma402-abstract" "1.11.4" @@ -1613,7 +1676,7 @@ "@formatjs/icu-skeleton-parser@1.3.6": version "1.3.6" - resolved "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.6.tgz" + resolved "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.6.tgz#4ce8c0737d6f07b735288177049e97acbf2e8964" integrity sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg== dependencies: "@formatjs/ecma402-abstract" "1.11.4" @@ -1621,14 +1684,14 @@ "@formatjs/intl-localematcher@0.2.25": version "0.2.25" - resolved "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz" + resolved "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz#60892fe1b271ec35ba07a2eb018a2dd7bca6ea3a" integrity sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA== dependencies: tslib "^2.1.0" "@glimmer/component@^1.0.0", "@glimmer/component@^1.0.4", "@glimmer/component@^1.1.2": version "1.1.2" - resolved "https://registry.npmjs.org/@glimmer/component/-/component-1.1.2.tgz" + resolved "https://registry.npmjs.org/@glimmer/component/-/component-1.1.2.tgz#892ec0c9f0b6b3e41c112be502fde073cf24d17c" integrity sha512-XyAsEEa4kWOPy+gIdMjJ8XlzA3qrGH55ZDv6nA16ibalCR17k74BI0CztxuRds+Rm6CtbUVgheCVlcCULuqD7A== dependencies: "@glimmer/di" "^0.1.9" @@ -1648,12 +1711,12 @@ "@glimmer/di@^0.1.9": version "0.1.11" - resolved "https://registry.npmjs.org/@glimmer/di/-/di-0.1.11.tgz" + resolved "https://registry.npmjs.org/@glimmer/di/-/di-0.1.11.tgz#a6878c07a13a2c2c76fcde598a5c97637bfc4280" integrity sha512-moRwafNDwHTnTHzyyZC9D+mUSvYrs1Ak0tRPjjmCghdoHHIvMshVbEnwKb/1WmW5CUlKc2eL9rlAV32n3GiItg== "@glimmer/encoder@^0.42.2": version "0.42.2" - resolved "https://registry.npmjs.org/@glimmer/encoder/-/encoder-0.42.2.tgz" + resolved "https://registry.npmjs.org/@glimmer/encoder/-/encoder-0.42.2.tgz#d3ba3dc9f1d4fa582d1d18b63da100fc5c664057" integrity sha512-8xkdly0i0BP5HMI0suPB9ly0AnEq8x9Z8j3Gee1HYIovM5VLNtmh7a8HsaHYRs/xHmBEZcqtr8JV89w6F59YMQ== dependencies: "@glimmer/interfaces" "^0.42.2" @@ -1661,43 +1724,43 @@ "@glimmer/env@0.1.7", "@glimmer/env@^0.1.7": version "0.1.7" - resolved "https://registry.npmjs.org/@glimmer/env/-/env-0.1.7.tgz" + resolved "https://registry.npmjs.org/@glimmer/env/-/env-0.1.7.tgz#fd2d2b55a9029c6b37a6c935e8c8871ae70dfa07" integrity sha512-JKF/a9I9jw6fGoz8kA7LEQslrwJ5jms5CXhu/aqkBWk+PmZ6pTl8mlb/eJ/5ujBGTiQzBhy5AIWF712iA+4/mw== "@glimmer/global-context@0.65.4": version "0.65.4" - resolved "https://registry.npmjs.org/@glimmer/global-context/-/global-context-0.65.4.tgz" + resolved "https://registry.npmjs.org/@glimmer/global-context/-/global-context-0.65.4.tgz#1da1d59dd4260ce912c40e474cd39c2e82de51b8" integrity sha512-RSYCPG/uVR5XCDcPREBclncU7R0zkjACbADP+n3FWAH1TfWbXRMDIkvO/ZlwHkjHoCZf6tIM6p5S/MoFzfJEJA== dependencies: "@glimmer/env" "^0.1.7" "@glimmer/interfaces@0.65.4": version "0.65.4" - resolved "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.65.4.tgz" + resolved "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.65.4.tgz#d298cc2b12b8ebcf269f39246ca7ab92816f6680" integrity sha512-R0kby79tGNKZOojVJa/7y0JH9Eq4SV+L1s6GcZy30QUZ1g1AAGS5XwCIXc9Sc09coGcv//q+6NLeSw7nlx1y4A== dependencies: "@simple-dom/interface" "^1.4.0" "@glimmer/interfaces@0.84.3": version "0.84.3" - resolved "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.84.3.tgz" + resolved "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.84.3.tgz#629777a4abe373b0785656f6c8d08989f5784805" integrity sha512-dk32ykoNojt0mvEaIW6Vli5MGTbQo58uy3Epj7ahCgTHmWOKuw/0G83f2UmFprRwFx689YTXG38I/vbpltEjzg== dependencies: "@simple-dom/interface" "^1.4.0" "@glimmer/interfaces@^0.42.2": version "0.42.2" - resolved "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.42.2.tgz" + resolved "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.42.2.tgz#9cf8d6f8f5eee6bfcfa36919ca68ae716e1f78db" integrity sha512-7LOuQd02cxxNNHChzdHMAU8/qOeQvTro141CU5tXITP7z6aOv2D2gkFdau97lLQiVxezGrh8J7h8GCuF7TEqtg== "@glimmer/low-level@^0.42.2": version "0.42.2" - resolved "https://registry.npmjs.org/@glimmer/low-level/-/low-level-0.42.2.tgz" + resolved "https://registry.npmjs.org/@glimmer/low-level/-/low-level-0.42.2.tgz#52c745414d1d04c4245c369bd132c0e786c816ef" integrity sha512-s+Q44SnKdTBTnkgX0deBlVNnNPVas+Pg8xEnwky9VrUqOHKsIZRrPgfVULeC6bIdFXtXOKm5CjTajhb9qnQbXQ== "@glimmer/program@^0.42.2": version "0.42.2" - resolved "https://registry.npmjs.org/@glimmer/program/-/program-0.42.2.tgz" + resolved "https://registry.npmjs.org/@glimmer/program/-/program-0.42.2.tgz#fe504679ca4df6251dd5fcf3003699bb51fa41fa" integrity sha512-XpQ6EYzA1VL9ESKoih5XW5JftFmlRvwy3bF/I1ABOa3yLIh8mApEwrRI/sIHK0Nv5s1j0uW4itVF196WxnJXgw== dependencies: "@glimmer/encoder" "^0.42.2" @@ -1706,14 +1769,14 @@ "@glimmer/reference@^0.42.1", "@glimmer/reference@^0.42.2": version "0.42.2" - resolved "https://registry.npmjs.org/@glimmer/reference/-/reference-0.42.2.tgz" + resolved "https://registry.npmjs.org/@glimmer/reference/-/reference-0.42.2.tgz#57874e27c825fb7041b5295b5eb153f3f3f92f8f" integrity sha512-XuhbRjr3M9Q/DP892jGxVfPE6jaGGHu5w9ppGMnuTY7Vm/x+A+68MCiaREhDcEwJlzGg4UkfVjU3fdgmUIrc5Q== dependencies: "@glimmer/util" "^0.42.2" "@glimmer/reference@^0.65.0": version "0.65.4" - resolved "https://registry.npmjs.org/@glimmer/reference/-/reference-0.65.4.tgz" + resolved "https://registry.npmjs.org/@glimmer/reference/-/reference-0.65.4.tgz#bbc8becd6a1bf01fc189b6489e27446437194711" integrity sha512-yuRVE4qyqrlCndDMrHKDWUbDmGDCjPzsFtlTmxxnhDMJAdQsnr2cRLITHvQRDm1tXfigVvyKnomeuYhRRbBqYQ== dependencies: "@glimmer/env" "^0.1.7" @@ -1724,7 +1787,7 @@ "@glimmer/runtime@^0.42.1": version "0.42.2" - resolved "https://registry.npmjs.org/@glimmer/runtime/-/runtime-0.42.2.tgz" + resolved "https://registry.npmjs.org/@glimmer/runtime/-/runtime-0.42.2.tgz#50e7da5d3cf9144248048a7478be3c489784a4bb" integrity sha512-52LVZJsLKM3GzI3TEmYcw2LdI9Uk0jotISc3w2ozQBWvkKoYxjDNvI/gsjyMpenj4s7FcG2ggOq0x4tNFqm1GA== dependencies: "@glimmer/interfaces" "^0.42.2" @@ -1737,7 +1800,7 @@ "@glimmer/syntax@^0.42.1": version "0.42.2" - resolved "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.42.2.tgz" + resolved "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.42.2.tgz#89bb3cb787285b84665dc0d8907d94b008e5be9a" integrity sha512-SR26SmF/Mb5o2cc4eLHpOyoX5kwwXP4KRhq4fbWfrvan74xVWA38PLspPCzwGhyVH/JsE7tUEPMjSo2DcJge/Q== dependencies: "@glimmer/interfaces" "^0.42.2" @@ -1747,7 +1810,7 @@ "@glimmer/syntax@^0.65.0": version "0.65.4" - resolved "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.65.4.tgz" + resolved "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.65.4.tgz#49164de5dc9e8b67084ec009bdd865e379d8a971" integrity sha512-y+/C3e8w96efk3a/Z5If9o4ztKJwrr8RtDpbhV2J8X+DUsn5ic2N3IIdlThbt/Zn6tkP1K3dY6uaFUx3pGTvVQ== dependencies: "@glimmer/interfaces" "0.65.4" @@ -1757,7 +1820,7 @@ "@glimmer/syntax@^0.84.3": version "0.84.3" - resolved "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.84.3.tgz" + resolved "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.84.3.tgz#4045a1708cef7fd810cff42fe6deeba40c7286d0" integrity sha512-ioVbTic6ZisLxqTgRBL2PCjYZTFIwobifCustrozRU2xGDiYvVIL0vt25h2c1ioDsX59UgVlDkIK4YTAQQSd2A== dependencies: "@glimmer/interfaces" "0.84.3" @@ -1767,7 +1830,7 @@ "@glimmer/tracking@^1.0.0", "@glimmer/tracking@^1.0.1", "@glimmer/tracking@^1.0.4": version "1.1.2" - resolved "https://registry.npmjs.org/@glimmer/tracking/-/tracking-1.1.2.tgz" + resolved "https://registry.npmjs.org/@glimmer/tracking/-/tracking-1.1.2.tgz#74e71be07b0a7066518d24044d2665d0cf8281eb" integrity sha512-cyV32zsHh+CnftuRX84ALZpd2rpbDrhLhJnTXn9W//QpqdRZ5rdMsxSY9fOsj0CKEc706tmEU299oNnDc0d7tA== dependencies: "@glimmer/env" "^0.1.7" @@ -1775,7 +1838,7 @@ "@glimmer/util@0.65.4": version "0.65.4" - resolved "https://registry.npmjs.org/@glimmer/util/-/util-0.65.4.tgz" + resolved "https://registry.npmjs.org/@glimmer/util/-/util-0.65.4.tgz#e464145078f3f40da9013ff2590a6016515455d2" integrity sha512-aofe+rdBhkREKP2GZta6jy1UcbRRMfWx7M18zxGxspPoeD08NscD04Kx+WiOKXmC1TcrfITr8jvqMfrKrMzYWQ== dependencies: "@glimmer/env" "0.1.7" @@ -1784,7 +1847,7 @@ "@glimmer/util@0.84.3": version "0.84.3" - resolved "https://registry.npmjs.org/@glimmer/util/-/util-0.84.3.tgz" + resolved "https://registry.npmjs.org/@glimmer/util/-/util-0.84.3.tgz#9ae0166982c0b48aa94b02d6ba8c2c81976ade4b" integrity sha512-qFkh6s16ZSRuu2rfz3T4Wp0fylFj3HBsONGXQcrAdZjdUaIS6v3pNj6mecJ71qRgcym9Hbaq/7/fefIwECUiKw== dependencies: "@glimmer/env" "0.1.7" @@ -1793,17 +1856,17 @@ "@glimmer/util@^0.42.2": version "0.42.2" - resolved "https://registry.npmjs.org/@glimmer/util/-/util-0.42.2.tgz" + resolved "https://registry.npmjs.org/@glimmer/util/-/util-0.42.2.tgz#9ca1631e42766ea6059f4b49d0bdfb6095aad2c4" integrity sha512-Heck0baFSaWDanCYtmOcLeaz7v+rSqI8ovS7twrp2/FWEteb3Ze5sWQ2BEuSAG23L/k/lzVwYM/MY7ZugxBpaA== "@glimmer/util@^0.44.0": version "0.44.0" - resolved "https://registry.npmjs.org/@glimmer/util/-/util-0.44.0.tgz" + resolved "https://registry.npmjs.org/@glimmer/util/-/util-0.44.0.tgz#45df98d73812440206ae7bda87cfe04aaae21ed9" integrity sha512-duAsm30uVK9jSysElCbLyU6QQYO2X9iLDLBIBUcCqck9qN1o3tK2qWiHbGK5d6g8E2AJ4H88UrfElkyaJlGrwg== "@glimmer/validator@0.65.4", "@glimmer/validator@^0.65.0": version "0.65.4" - resolved "https://registry.npmjs.org/@glimmer/validator/-/validator-0.65.4.tgz" + resolved "https://registry.npmjs.org/@glimmer/validator/-/validator-0.65.4.tgz#12c27a9a63706c60e6499fd687940e9d1affb32c" integrity sha512-0YUjAyo45DF5JkQxdv5kHn96nMNhvZiEwsAD4Jme0kk5Q9MQcPOUtN76pQAS4f+C6GdF9DeUr2yGXZLFMmb+LA== dependencies: "@glimmer/env" "^0.1.7" @@ -1811,19 +1874,19 @@ "@glimmer/validator@^0.44.0": version "0.44.0" - resolved "https://registry.npmjs.org/@glimmer/validator/-/validator-0.44.0.tgz" + resolved "https://registry.npmjs.org/@glimmer/validator/-/validator-0.44.0.tgz#03d127097dc9cb23052cdb7fcae59d0a9dca53e1" integrity sha512-i01plR0EgFVz69GDrEuFgq1NheIjZcyTy3c7q+w7d096ddPVeVcRzU3LKaqCfovvLJ+6lJx40j45ecycASUUyw== "@glimmer/vm-babel-plugins@0.80.3": version "0.80.3" - resolved "https://registry.npmjs.org/@glimmer/vm-babel-plugins/-/vm-babel-plugins-0.80.3.tgz" + resolved "https://registry.npmjs.org/@glimmer/vm-babel-plugins/-/vm-babel-plugins-0.80.3.tgz#434b62172318cac43830d3ac29818cf2c5f111c1" integrity sha512-9ej6xlm5MzHBJ5am2l0dbbn8Z0wJoYoMpM8FcrGMlUP6SPMLWxvxpMsApgQo8u6dvZRCjR3/bw3fdf7GOy0AFw== dependencies: babel-plugin-debug-macros "^0.3.4" "@glimmer/vm@^0.42.2": version "0.42.2" - resolved "https://registry.npmjs.org/@glimmer/vm/-/vm-0.42.2.tgz" + resolved "https://registry.npmjs.org/@glimmer/vm/-/vm-0.42.2.tgz#492a4f05eac587c3a37371b3c62593f20bef553d" integrity sha512-D2MNU5glICLqvet5SfVPrv+l6JNK2TR+CdQhch1Ew+btOoqlW+2LIJIF/5wLb1POjIMEkt+78t/7RN0mDFXGzw== dependencies: "@glimmer/interfaces" "^0.42.2" @@ -1831,7 +1894,7 @@ "@glimmer/wire-format@^0.42.2": version "0.42.2" - resolved "https://registry.npmjs.org/@glimmer/wire-format/-/wire-format-0.42.2.tgz" + resolved "https://registry.npmjs.org/@glimmer/wire-format/-/wire-format-0.42.2.tgz#b95062b594dddeb8bd11cba3a6a0accbfabc9930" integrity sha512-IqUo6mdJ7GRsK7KCyZxrc17ioSg9RBniEnb418ZMQxsV/WBv9NQ359MuClUck2M24z1AOXo4TerUw0U7+pb1/A== dependencies: "@glimmer/interfaces" "^0.42.2" @@ -1839,17 +1902,17 @@ "@handlebars/parser@^1.1.0": version "1.1.0" - resolved "https://registry.npmjs.org/@handlebars/parser/-/parser-1.1.0.tgz" + resolved "https://registry.npmjs.org/@handlebars/parser/-/parser-1.1.0.tgz#d6dbc7574774b238114582410e8fee0dc3532bdf" integrity sha512-rR7tJoSwJ2eooOpYGxGGW95sLq6GXUaS1UtWvN7pei6n2/okYvCGld9vsUTvkl2migxbkszsycwtMf/GEc1k1A== "@handlebars/parser@~2.0.0": version "2.0.0" - resolved "https://registry.npmjs.org/@handlebars/parser/-/parser-2.0.0.tgz" + resolved "https://registry.npmjs.org/@handlebars/parser/-/parser-2.0.0.tgz#5e8b7298f31ff8f7b260e6b7363c7e9ceed7d9c5" integrity sha512-EP9uEDZv/L5Qh9IWuMUGJRfwhXJ4h1dqKTT4/3+tY0eu7sPis7xh23j61SYUnNF4vqCQvvUXpDo9Bh/+q1zASA== "@hashicorp/api-double@^1.6.1": version "1.6.1" - resolved "https://registry.npmjs.org/@hashicorp/api-double/-/api-double-1.6.1.tgz" + resolved "https://registry.npmjs.org/@hashicorp/api-double/-/api-double-1.6.1.tgz#67c4c4c5cbf9f51f3b8bc992ab2df21acf63b318" integrity sha512-JkQZIsH/2B9T2oK5SQNDakvqlHjxQHu0I9ftmmrxqkxYvYoLN+Whp7dzQ8HswOp1vIJyqbvUhSw06XfH/eimZA== dependencies: array-range "^1.0.1" @@ -1861,39 +1924,40 @@ js-yaml "^3.13.1" "@hashicorp/design-system-components@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@hashicorp/design-system-components/-/design-system-components-3.0.2.tgz#f9bf18f0f20f6396d4afc2ed138056c27dff8a38" - integrity sha512-Pt3dgCxzutIJ3LDtVgT0NSU5oTV8OFzgK9Nx1tTzIpMOfbCRzZuBmJB06ZPCdyP9Vs7lQVrn/kKzZaKJejrXiQ== + version "3.6.0" + resolved "https://registry.npmjs.org/@hashicorp/design-system-components/-/design-system-components-3.6.0.tgz#e678123f9d88eef7df2edfdf1666997214fe3273" + integrity sha512-HV8Wa9fTFCfwCCze7gzg2+U3oSmwNkwYtnrrxln7MXzEKRWl1E2p4BM7ZdyaXu3n092R3wcjy04VwaVSmQqrLw== dependencies: "@ember/render-modifiers" "^2.0.5" - "@ember/test-waiters" "^3.0.2" - "@hashicorp/design-system-tokens" "^1.9.0" - "@hashicorp/ember-flight-icons" "^4.0.1" + "@ember/string" "^3.1.1" + "@ember/test-waiters" "^3.1.0" + "@hashicorp/design-system-tokens" "^1.11.0" + "@hashicorp/ember-flight-icons" "^4.1.0" dialog-polyfill "^0.5.6" ember-a11y-refocus "^3.0.2" ember-auto-import "^2.6.3" - ember-cached-decorator-polyfill "^0.1.4" - ember-cli-babel "^7.26.11" - ember-cli-htmlbars "^6.2.0" - ember-cli-sass "^10.0.1" - ember-composable-helpers "^4.5.0" + ember-cli-babel "^8.2.0" + ember-cli-htmlbars "^6.3.0" + ember-cli-sass "^11.0.1" + ember-composable-helpers "^5.0.0" ember-element-helper "^0.8.5" - ember-focus-trap "^1.0.2" - ember-keyboard "^8.2.0" + ember-focus-trap "^1.1.0" + ember-keyboard "^8.2.1" ember-stargate "^0.4.3" ember-style-modifier "^3.0.1" ember-truth-helpers "^3.1.1" - sass "^1.62.1" + prismjs "^1.29.0" + sass "^1.69.5" tippy.js "^6.3.7" -"@hashicorp/design-system-tokens@^1.9.0": - version "1.9.0" - resolved "https://registry.npmjs.org/@hashicorp/design-system-tokens/-/design-system-tokens-1.9.0.tgz" - integrity sha512-zmMpnKv4vulhVFVCpqf3oAAR5fQeDDnMxbeJIZllLFCgF2JFoL6C/Irghx4WnBAG8GkLs8CbxjPVtFjSYq+V8w== +"@hashicorp/design-system-tokens@^1.11.0", "@hashicorp/design-system-tokens@^1.9.0": + version "1.11.0" + resolved "https://registry.npmjs.org/@hashicorp/design-system-tokens/-/design-system-tokens-1.11.0.tgz#0ae68d06d4297e891ce4ba63465d1f6e742e5554" + integrity sha512-LPj8IAznpEEhKrrosg3+sW9ss6fVKt8zOC9Ic4Kt5/KZPWLFaP6S8pff5ytvede+cZrAzY3UzZF55u+ev5J9GQ== "@hashicorp/ember-cli-api-double@^4.0.0": version "4.0.0" - resolved "https://registry.npmjs.org/@hashicorp/ember-cli-api-double/-/ember-cli-api-double-4.0.0.tgz" + resolved "https://registry.npmjs.org/@hashicorp/ember-cli-api-double/-/ember-cli-api-double-4.0.0.tgz#fd6181229c589b4db93f1784d022db064c61ec76" integrity sha512-ana8k6MjyXgwflAgVJxrgab1vKz/v6212HOHO6Gsz6NaDwzQt0DUuT4dB3VpbiZ6K8D1M7xd0znsmnvR795goA== dependencies: "@hashicorp/api-double" "^1.6.1" @@ -1906,25 +1970,25 @@ pretender "^3.2.0" recursive-readdir-sync "^1.0.6" -"@hashicorp/ember-flight-icons@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@hashicorp/ember-flight-icons/-/ember-flight-icons-4.0.1.tgz#08499f495f8f9ff9eb9eb6c439f1861f8411c047" - integrity sha512-8xkU+2ATX/a5pofmwO51YXgwHamG6YUpxOXxcPbA+9/TKNn1HFbrk3TWJBuDIwz2kdk9hXRZBri2XIR18BFrTA== +"@hashicorp/ember-flight-icons@^4.0.1", "@hashicorp/ember-flight-icons@^4.1.0": + version "4.1.0" + resolved "https://registry.npmjs.org/@hashicorp/ember-flight-icons/-/ember-flight-icons-4.1.0.tgz#4f73fc6145c94ecd46ef38802722ea2d1fe0e876" + integrity sha512-X1AL475EPuGu6UkZiS/zqRFgymnIhGfgpY1HwPdavePARmgMr9CcPSwsTeZeV+OXq6yUxMzidijSJUAfEpLb5Q== dependencies: - "@hashicorp/flight-icons" "^2.20.0" + "@hashicorp/flight-icons" "^3.0.0" ember-auto-import "^2.6.3" - ember-cli-babel "^7.26.11" - ember-cli-htmlbars "^6.2.0" + ember-cli-babel "^8.2.0" + ember-cli-htmlbars "^6.3.0" ember-get-config "^2.1.1" -"@hashicorp/flight-icons@^2.20.0": - version "2.20.0" - resolved "https://registry.npmjs.org/@hashicorp/flight-icons/-/flight-icons-2.20.0.tgz" - integrity sha512-CYIY5yAkYzi8Q+w86Mk41IK1/1X+AoQUtxK3Yt48ZHzulsz3Wlvg91YvnOGntxjqcp7AGwpOYnq7xM2W4bummQ== +"@hashicorp/flight-icons@^3.0.0": + version "3.4.0" + resolved "https://registry.npmjs.org/@hashicorp/flight-icons/-/flight-icons-3.4.0.tgz#fbd30a9748c36d92934784623e93ce9af48ce957" + integrity sha512-ddbiKkaXW3LMlXE1MZz0fsaO0rJvpbLQ2Js+Qa1e2yWKQbtSvJluAu9V8mg5jvOlR3HFDskTm8knSxVRd0VjGw== "@html-next/vertical-collection@^4.0.0": version "4.0.2" - resolved "https://registry.npmjs.org/@html-next/vertical-collection/-/vertical-collection-4.0.2.tgz" + resolved "https://registry.npmjs.org/@html-next/vertical-collection/-/vertical-collection-4.0.2.tgz#7e9885423eb8c445bce0cc110ac3be281ca6ff87" integrity sha512-S8cgntEDdXrOwdylVGDh1BFe+nX5uuUzzb3teh1FE++/kbqsOfUpXOYRUsEzsqb0fRqcm6eLxvtNb282Zr67rQ== dependencies: babel6-plugin-strip-class-callcheck "^6.0.0" @@ -1938,7 +2002,7 @@ "@humanwhocodes/config-array@^0.5.0": version "0.5.0" - resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz" + resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== dependencies: "@humanwhocodes/object-schema" "^1.2.0" @@ -1947,12 +2011,12 @@ "@humanwhocodes/object-schema@^1.2.0": version "1.2.1" - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" + resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" - resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" + resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== dependencies: camelcase "^5.3.1" @@ -1963,72 +2027,79 @@ "@istanbuljs/schema@^0.1.2": version "0.1.3" - resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" + resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== +"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== dependencies: - "@jridgewell/set-array" "^1.0.0" + "@jridgewell/set-array" "^1.2.1" "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@3.1.0": - version "3.1.0" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== -"@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" -"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.17" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz" - integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== +"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" "@lit-labs/ssr-dom-shim@^1.0.0": - version "1.0.0" - resolved "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.0.0.tgz" - integrity sha512-ic93MBXfApIFTrup4a70M/+ddD8xdt2zxxj9sRwHQzhS9ag/syqkD8JPdTXsc1gUy2K8TTirhlCqyTEM/sifNw== + version "1.2.0" + resolved "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz#353ce4a76c83fadec272ea5674ede767650762fd" + integrity sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g== "@lit/reactive-element@^1.2.1": - version "1.6.1" - resolved "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.1.tgz" - integrity sha512-va15kYZr7KZNNPZdxONGQzpUr+4sxVu7V/VG7a8mRfPPXUyhEYj5RzXCQmGrlP3tAh0L3HHm5AjBMFYRqlM9SA== + version "1.6.3" + resolved "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz#25b4eece2592132845d303e091bad9b04cdcfe03" + integrity sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ== dependencies: "@lit-labs/ssr-dom-shim" "^1.0.0" +"@ljharb/resumer@^0.1.3": + version "0.1.3" + resolved "https://registry.npmjs.org/@ljharb/resumer/-/resumer-0.1.3.tgz#5ef4a4958da1b4e71ffea8ef33499cc622672d89" + integrity sha512-d+tsDgfkj9X5QTriqM4lKesCkMMJC3IrbPKHvayP00ELx2axdXvDfWkqjxrLXIzGcQzmj7VAUT1wopqARTvafw== + dependencies: + "@ljharb/through" "^2.3.13" + call-bind "^1.0.7" + +"@ljharb/through@^2.3.13": + version "2.3.13" + resolved "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz#b7e4766e0b65aa82e529be945ab078de79874edc" + integrity sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ== + dependencies: + call-bind "^1.0.7" + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" - resolved "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz" + resolved "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== dependencies: call-me-maybe "^1.0.1" @@ -2036,7 +2107,7 @@ "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -2044,49 +2115,49 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.stat@^1.1.2": version "1.1.3" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== "@nodelib/fs.walk@^1.2.3": version "1.2.8" - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" "@popperjs/core@^2.9.0": - version "2.11.6" - resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz" - integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw== + version "2.11.8" + resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" + integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== "@simple-dom/interface@^1.4.0": version "1.4.0" - resolved "https://registry.npmjs.org/@simple-dom/interface/-/interface-1.4.0.tgz" + resolved "https://registry.npmjs.org/@simple-dom/interface/-/interface-1.4.0.tgz#e8feea579232017f89b0138e2726facda6fbb71f" integrity sha512-l5qumKFWU0S+4ZzMaLXFU8tQZsicHEMEyAxI5kDFGhJsRqDwe0a7/iPA/GdxlGyDKseQQAgIz5kzU7eXTrlSpA== "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.1": version "1.8.6" - resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz" + resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== dependencies: type-detect "4.0.8" "@sinonjs/fake-timers@^6.0.0", "@sinonjs/fake-timers@^6.0.1": version "6.0.1" - resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz" + resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== dependencies: "@sinonjs/commons" "^1.7.0" "@sinonjs/samsam@^5.3.1": version "5.3.1" - resolved "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz" + resolved "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz#375a45fe6ed4e92fca2fb920e007c48232a6507f" integrity sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg== dependencies: "@sinonjs/commons" "^1.6.0" @@ -2095,22 +2166,22 @@ "@sinonjs/text-encoding@^0.7.1": version "0.7.2" - resolved "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz" + resolved "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== "@socket.io/component-emitter@~3.1.0": - version "3.1.0" - resolved "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz" - integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== + version "3.1.2" + resolved "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" + integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA== "@textlint/ast-node-types@^12.6.1": version "12.6.1" - resolved "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-12.6.1.tgz" + resolved "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-12.6.1.tgz#35ecefe74e701d7f632c083d4fda89cab1b89012" integrity sha512-uzlJ+ZsCAyJm+lBi7j0UeBbj+Oy6w/VWoGJ3iHRHE5eZ8Z4iK66mq+PG/spupmbllLtz77OJbY89BYqgFyjXmA== "@textlint/markdown-to-ast@^12.1.1": version "12.6.1" - resolved "https://registry.npmjs.org/@textlint/markdown-to-ast/-/markdown-to-ast-12.6.1.tgz" + resolved "https://registry.npmjs.org/@textlint/markdown-to-ast/-/markdown-to-ast-12.6.1.tgz#fcccb5733b3e76cd0db78a323763ab101f2d803b" integrity sha512-T0HO+VrU9VbLRiEx/kH4+gwGMHNMIGkp0Pok+p0I33saOOLyhfGvwOKQgvt2qkxzQEV2L5MtGB8EnW4r5d3CqQ== dependencies: "@textlint/ast-node-types" "^12.6.1" @@ -2125,89 +2196,90 @@ "@tootallnate/once@1": version "1.1.2" - resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz" + resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== "@types/body-parser@*": - version "1.19.2" - resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz" - integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + version "1.19.5" + resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" + integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== dependencies: "@types/connect" "*" "@types/node" "*" "@types/broccoli-plugin@^3.0.0": version "3.0.0" - resolved "https://registry.npmjs.org/@types/broccoli-plugin/-/broccoli-plugin-3.0.0.tgz" + resolved "https://registry.npmjs.org/@types/broccoli-plugin/-/broccoli-plugin-3.0.0.tgz#290fda2270c47a568edfd0cefab8bb840d8bb7b2" integrity sha512-f+TcsARR2PovfFRKFdCX0kfH/QoM3ZVD2h1rl2mNvrKO0fq2uBNCBsTU3JanfU4COCt5cXpTfARyUsERlC8vIw== dependencies: broccoli-plugin "*" "@types/chai-as-promised@^7.1.2": - version "7.1.5" - resolved "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz" - integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== + version "7.1.8" + resolved "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz#f2b3d82d53c59626b5d6bbc087667ccb4b677fe9" + integrity sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw== dependencies: "@types/chai" "*" "@types/chai@*", "@types/chai@^4.2.9": - version "4.3.4" - resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz" - integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== + version "4.3.16" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.16.tgz#b1572967f0b8b60bf3f87fe1d854a5604ea70c82" + integrity sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ== "@types/connect@*": - version "3.4.35" - resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + version "3.4.38" + resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== dependencies: "@types/node" "*" "@types/cookie@^0.4.1": version "0.4.1" - resolved "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz" + resolved "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== "@types/cors@^2.8.12": - version "2.8.13" - resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz" - integrity sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA== + version "2.8.17" + resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" + integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== dependencies: "@types/node" "*" "@types/eslint-scope@^3.7.3": - version "3.7.4" - resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz" - integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + version "3.7.7" + resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== dependencies: "@types/eslint" "*" "@types/estree" "*" "@types/eslint@*": - version "8.21.1" - resolved "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.1.tgz" - integrity sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ== + version "8.56.10" + resolved "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz#eb2370a73bf04a901eeba8f22595c7ee0f7eb58d" + integrity sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ== dependencies: "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== +"@types/estree@*", "@types/estree@^1.0.5": + version "1.0.5" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/express-serve-static-core@^4.17.33": - version "4.17.33" - resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz" - integrity sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA== + version "4.19.5" + resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz#218064e321126fcf9048d1ca25dd2465da55d9c6" + integrity sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg== dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" + "@types/send" "*" "@types/express@^4.17.2": - version "4.17.17" - resolved "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz" - integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== + version "4.17.21" + resolved "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^4.17.33" @@ -2216,21 +2288,21 @@ "@types/fs-extra@^5.0.5": version "5.1.0" - resolved "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.1.0.tgz" + resolved "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.1.0.tgz#2a325ef97901504a3828718c390d34b8426a10a1" integrity sha512-AInn5+UBFIK9FK5xc9yP5e3TQSPNNgjHByqYcj9g5elVBnDQcQL7PlO1CIRy2gWlbwK7UPYqi7vRvFA44dCmYQ== dependencies: "@types/node" "*" "@types/fs-extra@^8.1.0": - version "8.1.2" - resolved "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.2.tgz" - integrity sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg== + version "8.1.5" + resolved "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz#33aae2962d3b3ec9219b5aca2555ee00274f5927" + integrity sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ== dependencies: "@types/node" "*" "@types/glob@*": version "8.1.0" - resolved "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz" + resolved "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" integrity sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w== dependencies: "@types/minimatch" "^5.1.2" @@ -2238,190 +2310,206 @@ "@types/glob@^7.1.1": version "7.2.0" - resolved "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz" + resolved "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== dependencies: "@types/minimatch" "*" "@types/node" "*" "@types/hast@^2.0.0": - version "2.3.4" - resolved "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz" - integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + version "2.3.10" + resolved "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz#5c9d9e0b304bbb8879b857225c5ebab2d81d7643" + integrity sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw== dependencies: - "@types/unist" "*" + "@types/unist" "^2" + +"@types/http-errors@*": + version "2.0.4" + resolved "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== "@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + version "7.0.15" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/mdast@^3.0.0", "@types/mdast@^3.0.3": - version "3.0.10" - resolved "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz" - integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + version "3.0.15" + resolved "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" + integrity sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ== dependencies: - "@types/unist" "*" + "@types/unist" "^2" -"@types/mime@*": - version "3.0.1" - resolved "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz" - integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== - -"@types/minimatch@*", "@types/minimatch@^3.0.3", "@types/minimatch@^3.0.4": - version "3.0.5" - resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz" - integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== +"@types/mime@^1": + version "1.3.5" + resolved "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== -"@types/minimatch@^5.1.2": +"@types/minimatch@*", "@types/minimatch@^5.1.2": version "5.1.2" - resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz" + resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== +"@types/minimatch@^3.0.3", "@types/minimatch@^3.0.4": + version "3.0.5" + resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" + integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== + "@types/node@*", "@types/node@>=10.0.0": - version "18.15.0" - resolved "https://registry.npmjs.org/@types/node/-/node-18.15.0.tgz" - integrity sha512-z6nr0TTEOBGkzLGmbypWOGnpSpSIBorEhC4L+4HeQ2iezKCi4f77kyslRwvHeNitymGQ+oFyIWGP96l/DPSV9w== + version "20.14.10" + resolved "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz#a1a218290f1b6428682e3af044785e5874db469a" + integrity sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ== + dependencies: + undici-types "~5.26.4" "@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + version "4.0.2" + resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" + integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== "@types/qs@*": - version "6.9.7" - resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + version "6.9.15" + resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" + integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== "@types/range-parser@*": - version "1.2.4" - resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + version "1.2.7" + resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== "@types/rimraf@^2.0.2", "@types/rimraf@^2.0.3": version "2.0.5" - resolved "https://registry.npmjs.org/@types/rimraf/-/rimraf-2.0.5.tgz" + resolved "https://registry.npmjs.org/@types/rimraf/-/rimraf-2.0.5.tgz#368fb04d59630b727fc05a74d2ca557f64a8ef98" integrity sha512-YyP+VfeaqAyFmXoTh3HChxOQMyjByRMsHU7kc5KOJkSlXudhMhQIALbYV7rHh/l8d2lX3VUQzprrcAgWdRuU8g== dependencies: - "@types/glob" "*" + "@types/glob" "*" + "@types/node" "*" + +"@types/send@*": + version "0.17.4" + resolved "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" "@types/node" "*" "@types/serve-static@*": - version "1.15.1" - resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz" - integrity sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ== + version "1.15.7" + resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== dependencies: - "@types/mime" "*" + "@types/http-errors" "*" "@types/node" "*" + "@types/send" "*" "@types/symlink-or-copy@^1.2.0": - version "1.2.0" - resolved "https://registry.npmjs.org/@types/symlink-or-copy/-/symlink-or-copy-1.2.0.tgz" - integrity sha512-Lja2xYuuf2B3knEsga8ShbOdsfNOtzT73GyJmZyY7eGl2+ajOqrs8yM5ze0fsSoYwvA6bw7/Qr7OZ7PEEmYwWg== + version "1.2.2" + resolved "https://registry.npmjs.org/@types/symlink-or-copy/-/symlink-or-copy-1.2.2.tgz#51b1c00b516a5774ada5d611e65eb123f988ef8d" + integrity sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA== -"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": - version "2.0.6" - resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz" - integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== +"@types/unist@^2", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": + version "2.0.10" + resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc" + integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" "@webassemblyjs/ast@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== dependencies: "@webassemblyjs/helper-module-context" "1.9.0" "@webassemblyjs/helper-wasm-bytecode" "1.9.0" "@webassemblyjs/wast-parser" "1.9.0" -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== "@webassemblyjs/floating-point-hex-parser@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== "@webassemblyjs/helper-api-error@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== "@webassemblyjs/helper-buffer@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== "@webassemblyjs/helper-code-frame@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== dependencies: "@webassemblyjs/wast-printer" "1.9.0" "@webassemblyjs/helper-fsm@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== "@webassemblyjs/helper-module-context@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== dependencies: "@webassemblyjs/ast" "1.9.0" -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== "@webassemblyjs/helper-wasm-bytecode@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" "@webassemblyjs/helper-wasm-section@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -2429,61 +2517,47 @@ "@webassemblyjs/helper-wasm-bytecode" "1.9.0" "@webassemblyjs/wasm-gen" "1.9.0" -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== dependencies: "@xtuc/ieee754" "^1.2.0" "@webassemblyjs/ieee754@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== dependencies: "@xtuc/long" "4.2.2" "@webassemblyjs/leb128@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== "@webassemblyjs/utf8@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" - "@webassemblyjs/wasm-edit@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -2495,20 +2569,34 @@ "@webassemblyjs/wasm-parser" "1.9.0" "@webassemblyjs/wast-printer" "1.9.0" -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" "@webassemblyjs/wasm-gen@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -2517,19 +2605,19 @@ "@webassemblyjs/leb128" "1.9.0" "@webassemblyjs/utf8" "1.9.0" -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" "@webassemblyjs/wasm-opt@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -2537,21 +2625,21 @@ "@webassemblyjs/wasm-gen" "1.9.0" "@webassemblyjs/wasm-parser" "1.9.0" -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" "@webassemblyjs/wasm-parser@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -2563,7 +2651,7 @@ "@webassemblyjs/wast-parser@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -2573,17 +2661,17 @@ "@webassemblyjs/helper-fsm" "1.9.0" "@xtuc/long" "4.2.2" -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== dependencies: - "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/ast" "1.12.1" "@xtuc/long" "4.2.2" "@webassemblyjs/wast-printer@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz" + resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -2591,50 +2679,45 @@ "@xtuc/long" "4.2.2" "@xmldom/xmldom@^0.8.0": - version "0.8.6" - resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz" - integrity sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg== + version "0.8.10" + resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99" + integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw== "@xstate/fsm@^1.4.0": version "1.6.5" - resolved "https://registry.npmjs.org/@xstate/fsm/-/fsm-1.6.5.tgz" + resolved "https://registry.npmjs.org/@xstate/fsm/-/fsm-1.6.5.tgz#f599e301997ad7e3c572a0b1ff0696898081bea5" integrity sha512-b5o1I6aLNeYlU/3CPlj/Z91ybk1gUsKT+5NAJI+2W4UjvS5KLG28K9v5UvNoFVjHV8PajVZ00RH3vnjyQO7ZAw== "@xtuc/ieee754@^1.2.0": version "1.2.0" - resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" + resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== "@xtuc/long@4.2.2": version "4.2.2" - resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" + resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -JSV@^4.0.x: - version "4.0.2" - resolved "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz" - integrity sha512-ZJ6wx9xaKJ3yFUhq5/sk82PJMuUyLk277I8mQeyDgCTjGdjWJIvPfaU5LIXaMuaN2UO1X3kZH4+lgphublZUHw== - a11y-dialog@^6.0.1: - version "6.1.1" - resolved "https://registry.npmjs.org/a11y-dialog/-/a11y-dialog-6.1.1.tgz" - integrity sha512-bMvrxCupDFZJVHNVZFibO+qL6/BMmGI3d9oRIKpzwFpuidwe9czIrHXw256dieA0nCRadqm0GlMaK2JfqcLDkA== + version "6.1.2" + resolved "https://registry.npmjs.org/a11y-dialog/-/a11y-dialog-6.1.2.tgz#7c6a1d3720462db2f2fde6badba63478fd3cc871" + integrity sha512-mBKuYGXb3tZOztkQjdCXC+ryqbqGXHmIIqxdto/1jfDlSc7eBRGrS1XqL5KJpSCnG2VTSPsP4ONve1HPu4lmQw== dependencies: focusable-selectors "^0.3.0" abab@^2.0.3, abab@^2.0.5: version "2.0.6" - resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz" + resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== abbrev@1: version "1.1.1" - resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" + resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" - resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: mime-types "~2.1.34" @@ -2642,61 +2725,52 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: acorn-globals@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz" + resolved "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== dependencies: acorn "^7.1.1" acorn-walk "^7.1.1" -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== acorn-jsx@^5.3.1: version "5.3.2" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn-node@^1.8.2: - version "1.8.2" - resolved "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz" - integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== - dependencies: - acorn "^7.0.0" - acorn-walk "^7.0.0" - xtend "^4.0.2" - -acorn-walk@^7.0.0, acorn-walk@^7.1.1: +acorn-walk@^7.1.1: version "7.2.0" - resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== acorn@^6.4.1: version "6.4.2" - resolved "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz" + resolved "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== -acorn@^7.0.0, acorn@^7.1.1, acorn@^7.4.0: +acorn@^7.1.1, acorn@^7.4.0: version "7.4.1" - resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz" + resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.2.4, acorn@^8.5.0, acorn@^8.7.1: - version "8.8.2" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz" - integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== +acorn@^8.2.4, acorn@^8.7.1, acorn@^8.8.2: + version "8.12.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== agent-base@6: version "6.0.2" - resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" aggregate-error@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" + resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== dependencies: clean-stack "^2.0.0" @@ -2704,31 +2778,31 @@ aggregate-error@^3.0.0: ajv-errors@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz" + resolved "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== ajv-formats@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz" + resolved "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== dependencies: ajv "^8.0.0" ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: version "3.5.2" - resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" + resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv-keywords@^5.0.0: +ajv-keywords@^5.1.0: version "5.1.0" - resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz" + resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== dependencies: fast-deep-equal "^3.1.3" ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -2736,26 +2810,26 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.0.1, ajv@^8.8.0: - version "8.12.0" - resolved "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== +ajv@^8.0.0, ajv@^8.0.1, ajv@^8.9.0: + version "8.16.0" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz#22e2a92b94f005f7e0f9c9d39652ef0b8f6f0cb4" + integrity sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw== dependencies: - fast-deep-equal "^3.1.1" + fast-deep-equal "^3.1.3" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" - uri-js "^4.2.2" + uri-js "^4.4.1" amd-name-resolver@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/amd-name-resolver/-/amd-name-resolver-1.2.0.tgz" + resolved "https://registry.npmjs.org/amd-name-resolver/-/amd-name-resolver-1.2.0.tgz#fc41b3848824b557313897d71f8d5a0184fbe679" integrity sha512-hlSTWGS1t6/xq5YCed7YALg7tKZL3rkl7UwEZ/eCIkn8JxmM6fU6Qs/1hwtjQqfuYxlffuUcgYEm0f5xP4YKaA== dependencies: ensure-posix-path "^1.0.1" amd-name-resolver@^1.3.1: version "1.3.1" - resolved "https://registry.npmjs.org/amd-name-resolver/-/amd-name-resolver-1.3.1.tgz" + resolved "https://registry.npmjs.org/amd-name-resolver/-/amd-name-resolver-1.3.1.tgz#ffe71c683c6e7191fc4ae1bb3aaed15abea135d9" integrity sha512-26qTEWqZQ+cxSYygZ4Cf8tsjDBLceJahhtewxtKZA3SRa4PluuqYCuheemDQD+7Mf5B7sr+zhTDWAHDh02a1Dw== dependencies: ensure-posix-path "^1.0.1" @@ -2763,97 +2837,97 @@ amd-name-resolver@^1.3.1: amdefine@>=0.0.4: version "1.0.1" - resolved "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" + resolved "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== anchor-markdown-header@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/anchor-markdown-header/-/anchor-markdown-header-0.6.0.tgz" + resolved "https://registry.npmjs.org/anchor-markdown-header/-/anchor-markdown-header-0.6.0.tgz#908f2031281766f44ac350380ca0de77ab7065b8" integrity sha512-v7HJMtE1X7wTpNFseRhxsY/pivP4uAJbidVhPT+yhz4i/vV1+qx371IXuV9V7bN6KjFtheLJxqaSm0Y/8neJTA== dependencies: emoji-regex "~10.1.0" ansi-colors@^4.1.1: version "4.1.3" - resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== ansi-escapes@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: type-fest "^0.21.3" -ansi-html@^0.0.7: - version "0.0.7" - resolved "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz" - integrity sha512-JoAxEa1DfP9m2xfB/y2r/aKcwXNlltr4+0QSBC4TrLfcxyvepX2Pv0t/xpgGV5bGsDzCYV8SzjWgyCW0T9yYbA== +ansi-html@0.0.8, ansi-html@^0.0.7: + version "0.0.8" + resolved "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.8.tgz#e969db193b12bcdfa6727b29ffd8882dc13cc501" + integrity sha512-QROYz1I1Kj+8bTYgx0IlMBpRSCIU+7GjbE0oH+KF7QKc+qSF8YAlIutN59Db17tXN70Ono9upT9Ht0iG93W7ug== ansi-regex@^2.0.0: version "2.1.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== ansi-regex@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== ansi-regex@^4.1.0: version "4.1.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-styles@^2.2.1: version "2.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== ansi-styles@^3.0.0, ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" -ansi-styles@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz" - integrity sha512-3iF4FIKdxaVYT3JqQuY3Wat/T2t7TRbbQ94Fu50ZUCbLy4TFbTzr90NOHQodQkNqmeEGCw8WbeP78WNi6SKYUA== - ansi-to-html@^0.6.15, ansi-to-html@^0.6.6: version "0.6.15" - resolved "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.15.tgz" + resolved "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.15.tgz#ac6ad4798a00f6aa045535d7f6a9cb9294eebea7" integrity sha512-28ijx2aHJGdzbs+O5SNQF65r6rrKYnkuwTYm8lZlChuoJ9P1vVzIpWO20sQTqTPDXYp6NFwk326vApTtLVFXpQ== dependencies: entities "^2.0.0" ansicolors@~0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz" + resolved "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz#be089599097b74a5c9c4a84a0cdbcdb62bd87aef" integrity sha512-tOIuy1/SK/dr94ZA0ckDohKXNeBNqZ4us6PjMVLs5h1w2GBB6uPtOknp2+VF4F/zcy9LI70W+Z+pE2Soajky1w== +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + anymatch@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== dependencies: micromatch "^3.1.4" @@ -2861,7 +2935,7 @@ anymatch@^2.0.0: anymatch@~3.1.2: version "3.1.3" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" @@ -2869,19 +2943,24 @@ anymatch@~3.1.2: aot-test-generators@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/aot-test-generators/-/aot-test-generators-0.1.0.tgz" + resolved "https://registry.npmjs.org/aot-test-generators/-/aot-test-generators-0.1.0.tgz#43f0f615f97cb298d7919c1b0b4e6b7310b03cd0" integrity sha512-PKyBQsPgkrCbUZS0PexdnyS3pVfYe4U1dLLQOf3is5RcYSaxbA7fsnnj6i8hcubsz+iS0miGPSJlONv/tXjfiA== dependencies: jsesc "^2.5.0" -aproba@^1.0.3, "aproba@^1.0.3 || ^2.0.0", aproba@^1.1.1: +aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" - resolved "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz" + resolved "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + are-we-there-yet@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg== dependencies: delegates "^1.0.0" @@ -2889,7 +2968,7 @@ are-we-there-yet@^3.0.0: are-we-there-yet@~1.1.2: version "1.1.7" - resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== dependencies: delegates "^1.0.0" @@ -2897,134 +2976,151 @@ are-we-there-yet@~1.1.2: arg@^5.0.2: version "5.0.2" - resolved "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz" + resolved "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== argparse@^1.0.7: version "1.0.10" - resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" argparse@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== arr-diff@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz" + resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - arr-union@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz" + resolved "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== +array-buffer-byte-length@^1.0.0, array-buffer-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" + integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== + dependencies: + call-bind "^1.0.5" + is-array-buffer "^3.0.4" + array-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz" - integrity sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA== + version "1.0.2" + resolved "https://registry.npmjs.org/array-equal/-/array-equal-1.0.2.tgz#a8572e64e822358271250b9156d20d96ef5dec04" + integrity sha512-gUHx76KtnhEgB3HOuFYiCm3FIdEs6ocM2asHvNTkfu/Y09qQVrrVVaOKENmS2KkSaGoxgXNqC+ZVtR/n0MOkSA== array-find-index@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz" + resolved "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" integrity sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw== array-flatten@1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== array-range@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/array-range/-/array-range-1.0.1.tgz" + resolved "https://registry.npmjs.org/array-range/-/array-range-1.0.1.tgz#f56e46591843611c6a56f77ef02eda7c50089bfc" integrity sha512-shdaI1zT3CVNL2hnx9c0JMc0ZogGaxDs5e85akgHWKYa0yVbIyp06Ind3dVkTj/uuFrzaHBOyqFzo+VV6aXgtA== array-to-error@^1.0.0: version "1.1.1" - resolved "https://registry.npmjs.org/array-to-error/-/array-to-error-1.1.1.tgz" + resolved "https://registry.npmjs.org/array-to-error/-/array-to-error-1.1.1.tgz#d68812926d14097a205579a667eeaf1856a44c07" integrity sha512-kqcQ8s7uQfg3UViYON3kCMcck3A9exxgq+riVuKy08Mx00VN4EJhK30L2VpjE58LQHKhcE/GRpvbVUhqTvqzGQ== dependencies: array-to-sentence "^1.1.0" array-to-sentence@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/array-to-sentence/-/array-to-sentence-1.1.0.tgz" + resolved "https://registry.npmjs.org/array-to-sentence/-/array-to-sentence-1.1.0.tgz#c804956dafa53232495b205a9452753a258d39fc" integrity sha512-YkwkMmPA2+GSGvXj1s9NZ6cc2LBtR+uSeWTy2IGi5MR1Wag4DdrcjTxA/YV/Fw+qKlBeXomneZgThEbm/wvZbw== array-union@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== array-unique@^0.3.2: version "0.3.2" - resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz" + resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== -array.prototype.every@^1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/array.prototype.every/-/array.prototype.every-1.1.4.tgz" - integrity sha512-Aui35iRZk1HHLRAyF7QP0KAnOnduaQ6fo6k1NVWfRc0xTs2AZ70ytlXvOmkC6Di4JmUs2Wv3DYzGtCQFSk5uGg== +array.prototype.every@^1.1.6: + version "1.1.6" + resolved "https://registry.npmjs.org/array.prototype.every/-/array.prototype.every-1.1.6.tgz#1717b407d019913250317300d814a1b6660f10d7" + integrity sha512-gNEqZD97w6bfQRNmHkFv7rNnGM+VWyHZT+h/rf9C+22owcXuENr66Lfo0phItpU5KoXW6Owb34q2+8MnSIZ57w== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-object-atoms "^1.0.0" is-string "^1.0.7" +arraybuffer.prototype.slice@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" + integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.2.1" + get-intrinsic "^1.2.3" + is-array-buffer "^3.0.4" + is-shared-array-buffer "^1.0.2" + asap@^2.0.0: version "2.0.6" - resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" + resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== +asn1.js@^4.10.1: + version "4.10.1" + resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== dependencies: bn.js "^4.0.0" inherits "^2.0.1" minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" assert-never@^1.1.0, assert-never@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/assert-never/-/assert-never-1.2.1.tgz" - integrity sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw== + version "1.3.0" + resolved "https://registry.npmjs.org/assert-never/-/assert-never-1.3.0.tgz#c53cf3ad8fcdb67f400a941dea66dac7fe82dd2e" + integrity sha512-9Z3vxQ+berkL/JJo0dK+EY3Lp0s3NtSnP3VCLsh5HDcZPrh0M+KQRK5sWhUeyPPH+/RCxZqOxLMR+YC6vlviEQ== assert@^1.1.1: - version "1.5.0" - resolved "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + version "1.5.1" + resolved "https://registry.npmjs.org/assert/-/assert-1.5.1.tgz#038ab248e4ff078e7bc2485ba6e6388466c78f76" + integrity sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A== dependencies: - object-assign "^4.1.1" - util "0.10.3" + object.assign "^4.1.4" + util "^0.10.4" assign-symbols@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz" + resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== ast-types@0.13.3: version "0.13.3" - resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.13.3.tgz" + resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.13.3.tgz#50da3f28d17bdbc7969a3a2d83a0e4a72ae755a7" integrity sha512-XTZ7xGML849LkQP86sWdQzfhwbt3YwIO6MqbX9mUNYY98VKaaVZP7YNNm70IpwecbkkxmfC5IYAzOQ/2p29zRA== astral-regex@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz" + resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== async-disk-cache@^1.2.1: version "1.3.5" - resolved "https://registry.npmjs.org/async-disk-cache/-/async-disk-cache-1.3.5.tgz" + resolved "https://registry.npmjs.org/async-disk-cache/-/async-disk-cache-1.3.5.tgz#cc6206ed79bb6982b878fc52e0505e4f52b62a02" integrity sha512-VZpqfR0R7CEOJZ/0FOTgWq70lCrZyS1rkI8PXugDUkTKyyAUgZ2zQ09gLhMkEn+wN8LYeUTPxZdXtlX/kmbXKQ== dependencies: debug "^2.1.3" @@ -3037,7 +3133,7 @@ async-disk-cache@^1.2.1: async-disk-cache@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/async-disk-cache/-/async-disk-cache-2.1.0.tgz" + resolved "https://registry.npmjs.org/async-disk-cache/-/async-disk-cache-2.1.0.tgz#e0f37b187ed8c41a5991518a9556d206ae2843a2" integrity sha512-iH+boep2xivfD9wMaZWkywYIURSmsL96d6MoqrC94BnGSvXE4Quf8hnJiHGFYhw/nLeIa1XyRaf4vvcvkwAefg== dependencies: debug "^4.1.1" @@ -3050,12 +3146,12 @@ async-disk-cache@^2.0.0: async-each@^1.0.1: version "1.0.6" - resolved "https://registry.npmjs.org/async-each/-/async-each-1.0.6.tgz" + resolved "https://registry.npmjs.org/async-each/-/async-each-1.0.6.tgz#52f1d9403818c179b7561e11a5d1b77eb2160e77" integrity sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg== async-promise-queue@^1.0.3, async-promise-queue@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/async-promise-queue/-/async-promise-queue-1.0.5.tgz" + resolved "https://registry.npmjs.org/async-promise-queue/-/async-promise-queue-1.0.5.tgz#cb23bce9fce903a133946a700cc85f27f09ea49d" integrity sha512-xi0aQ1rrjPWYmqbwr18rrSKbSaXIeIwSd1J4KAgVfkq8utNbdZoht7GfvfY6swFUAMJ9obkc4WPJmtGwl+B8dw== dependencies: async "^2.4.1" @@ -3063,51 +3159,53 @@ async-promise-queue@^1.0.3, async-promise-queue@^1.0.5: async@^2.4.1, async@^2.6.4: version "2.6.4" - resolved "https://registry.npmjs.org/async/-/async-2.6.4.tgz" + resolved "https://registry.npmjs.org/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== dependencies: lodash "^4.17.14" async@~0.2.9: version "0.2.10" - resolved "https://registry.npmjs.org/async/-/async-0.2.10.tgz" + resolved "https://registry.npmjs.org/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" integrity sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ== asynckit@^0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== at-least-node@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" + resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== atob@^2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz" + resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== autoprefixer@^10.4.8: - version "10.4.14" - resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz" - integrity sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ== + version "10.4.19" + resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz#ad25a856e82ee9d7898c59583c1afeb3fa65f89f" + integrity sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew== dependencies: - browserslist "^4.21.5" - caniuse-lite "^1.0.30001464" - fraction.js "^4.2.0" + browserslist "^4.23.0" + caniuse-lite "^1.0.30001599" + fraction.js "^4.3.7" normalize-range "^0.1.2" picocolors "^1.0.0" postcss-value-parser "^4.2.0" -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" babel-code-frame@^6.26.0: version "6.26.0" - resolved "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz" + resolved "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== dependencies: chalk "^1.1.3" @@ -3116,7 +3214,7 @@ babel-code-frame@^6.26.0: babel-core@^6.26.0, babel-core@^6.26.3: version "6.26.3" - resolved "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz" + resolved "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== dependencies: babel-code-frame "^6.26.0" @@ -3141,7 +3239,7 @@ babel-core@^6.26.0, babel-core@^6.26.3: babel-eslint@^10.0.3: version "10.1.0" - resolved "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz" + resolved "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== dependencies: "@babel/code-frame" "^7.0.0" @@ -3153,7 +3251,7 @@ babel-eslint@^10.0.3: babel-generator@^6.26.0: version "6.26.1" - resolved "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz" + resolved "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== dependencies: babel-messages "^6.23.0" @@ -3167,7 +3265,7 @@ babel-generator@^6.26.0: babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: version "6.24.1" - resolved "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" integrity sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q== dependencies: babel-helper-explode-assignable-expression "^6.24.1" @@ -3176,7 +3274,7 @@ babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: babel-helper-call-delegate@^6.24.1: version "6.24.1" - resolved "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" integrity sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ== dependencies: babel-helper-hoist-variables "^6.24.1" @@ -3186,7 +3284,7 @@ babel-helper-call-delegate@^6.24.1: babel-helper-define-map@^6.24.1: version "6.26.0" - resolved "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz" + resolved "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" integrity sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA== dependencies: babel-helper-function-name "^6.24.1" @@ -3196,7 +3294,7 @@ babel-helper-define-map@^6.24.1: babel-helper-explode-assignable-expression@^6.24.1: version "6.24.1" - resolved "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" integrity sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ== dependencies: babel-runtime "^6.22.0" @@ -3205,7 +3303,7 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-helper-function-name@^6.24.1: version "6.24.1" - resolved "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" integrity sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q== dependencies: babel-helper-get-function-arity "^6.24.1" @@ -3216,7 +3314,7 @@ babel-helper-function-name@^6.24.1: babel-helper-get-function-arity@^6.24.1: version "6.24.1" - resolved "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" integrity sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng== dependencies: babel-runtime "^6.22.0" @@ -3224,7 +3322,7 @@ babel-helper-get-function-arity@^6.24.1: babel-helper-hoist-variables@^6.24.1: version "6.24.1" - resolved "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" integrity sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw== dependencies: babel-runtime "^6.22.0" @@ -3232,7 +3330,7 @@ babel-helper-hoist-variables@^6.24.1: babel-helper-optimise-call-expression@^6.24.1: version "6.24.1" - resolved "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" integrity sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA== dependencies: babel-runtime "^6.22.0" @@ -3240,7 +3338,7 @@ babel-helper-optimise-call-expression@^6.24.1: babel-helper-regex@^6.24.1: version "6.26.0" - resolved "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz" + resolved "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" integrity sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg== dependencies: babel-runtime "^6.26.0" @@ -3249,7 +3347,7 @@ babel-helper-regex@^6.24.1: babel-helper-remap-async-to-generator@^6.24.1: version "6.24.1" - resolved "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" integrity sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg== dependencies: babel-helper-function-name "^6.24.1" @@ -3260,7 +3358,7 @@ babel-helper-remap-async-to-generator@^6.24.1: babel-helper-replace-supers@^6.24.1: version "6.24.1" - resolved "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" integrity sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw== dependencies: babel-helper-optimise-call-expression "^6.24.1" @@ -3272,7 +3370,7 @@ babel-helper-replace-supers@^6.24.1: babel-helpers@^6.24.1: version "6.24.1" - resolved "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" integrity sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ== dependencies: babel-runtime "^6.22.0" @@ -3280,22 +3378,27 @@ babel-helpers@^6.24.1: babel-import-util@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/babel-import-util/-/babel-import-util-0.2.0.tgz" + resolved "https://registry.npmjs.org/babel-import-util/-/babel-import-util-0.2.0.tgz#b468bb679919601a3570f9e317536c54f2862e23" integrity sha512-CtWYYHU/MgK88rxMrLfkD356dApswtR/kWZ/c6JifG1m10e7tBBrs/366dFzWMAoqYmG5/JSh+94tUSpIwh+ag== babel-import-util@^1.1.0: - version "1.3.0" - resolved "https://registry.npmjs.org/babel-import-util/-/babel-import-util-1.3.0.tgz" - integrity sha512-PPzUT17eAI18zn6ek1R3sB4Krc/MbnmT1MkZQFmyhjoaEGBVwNABhfVU9+EKcDSKrrOm9OIpGhjxukx1GCiy1g== + version "1.4.1" + resolved "https://registry.npmjs.org/babel-import-util/-/babel-import-util-1.4.1.tgz#1df6fd679845df45494bac9ca12461d49497fdd4" + integrity sha512-TNdiTQdPhXlx02pzG//UyVPSKE7SNWjY0n4So/ZnjQpWwaM5LvWBLkWa1JKll5u06HNscHD91XZPuwrMg1kadQ== babel-import-util@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/babel-import-util/-/babel-import-util-2.0.1.tgz" - integrity sha512-N1ZfNprtf/37x0R05J0QCW/9pCAcuI+bjZIK9tlu0JEkwEST7ssdD++gxHRbD58AiG5QE5OuNYhRoEFsc1wESw== + version "2.1.1" + resolved "https://registry.npmjs.org/babel-import-util/-/babel-import-util-2.1.1.tgz#0f4905fe899abfb8cd835dd52f3df1966d1ffbb0" + integrity sha512-3qBQWRjzP9NreSH/YrOEU1Lj5F60+pWSLP0kIdCWxjFHH7pX2YPHIxQ67el4gnMNfYoDxSDGcT0zpVlZ+gVtQA== + +babel-import-util@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/babel-import-util/-/babel-import-util-3.0.0.tgz#5814c6a58e7b80e64156b48fdfd34d48e6e0b1df" + integrity sha512-4YNPkuVsxAW5lnSTa6cn4Wk49RX6GAB6vX+M6LqEtN0YePqoFczv1/x0EyLK/o+4E1j9jEuYj5Su7IEPab5JHQ== babel-loader@^8.0.6, babel-loader@^8.1.0: version "8.3.0" - resolved "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz" + resolved "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz#124936e841ba4fe8176786d6ff28add1f134d6a8" integrity sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q== dependencies: find-cache-dir "^3.3.1" @@ -3305,64 +3408,64 @@ babel-loader@^8.0.6, babel-loader@^8.1.0: babel-messages@^6.23.0: version "6.23.0" - resolved "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz" + resolved "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w== dependencies: babel-runtime "^6.22.0" babel-plugin-check-es2015-constants@^6.22.0: version "6.22.0" - resolved "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" integrity sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA== dependencies: babel-runtime "^6.22.0" babel-plugin-debug-macros@^0.2.0, babel-plugin-debug-macros@^0.2.0-beta.6: version "0.2.0" - resolved "https://registry.npmjs.org/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.2.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.2.0.tgz#0120ac20ce06ccc57bf493b667cf24b85c28da7a" integrity sha512-Wpmw4TbhR3Eq2t3W51eBAQSdKlr+uAyF0GI4GtPfMCD12Y4cIdpKC9l0RjNTH/P9isFypSqqewMPm7//fnZlNA== dependencies: semver "^5.3.0" babel-plugin-debug-macros@^0.3.3, babel-plugin-debug-macros@^0.3.4: version "0.3.4" - resolved "https://registry.npmjs.org/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.3.4.tgz" + resolved "https://registry.npmjs.org/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.3.4.tgz#22961d0cb851a80654cece807a8b4b73d85c6075" integrity sha512-wfel/vb3pXfwIDZUrkoDrn5FHmlWI96PCJ3UCDv2a86poJ3EQrnArNW5KfHSVJ9IOgxHbo748cQt7sDU+0KCEw== dependencies: semver "^5.3.0" babel-plugin-ember-data-packages-polyfill@^0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/babel-plugin-ember-data-packages-polyfill/-/babel-plugin-ember-data-packages-polyfill-0.1.2.tgz" + resolved "https://registry.npmjs.org/babel-plugin-ember-data-packages-polyfill/-/babel-plugin-ember-data-packages-polyfill-0.1.2.tgz#21154c095ddc703722b1fb8bb06c126c0b6d77dc" integrity sha512-kTHnOwoOXfPXi00Z8yAgyD64+jdSXk3pknnS7NlqnCKAU6YDkXZ4Y7irl66kaZjZn0FBBt0P4YOZFZk85jYOww== dependencies: "@ember-data/rfc395-data" "^0.0.4" babel-plugin-ember-modules-api-polyfill@^2.6.0: version "2.13.4" - resolved "https://registry.npmjs.org/babel-plugin-ember-modules-api-polyfill/-/babel-plugin-ember-modules-api-polyfill-2.13.4.tgz" + resolved "https://registry.npmjs.org/babel-plugin-ember-modules-api-polyfill/-/babel-plugin-ember-modules-api-polyfill-2.13.4.tgz#cf62bc9bfd808c48d810d5194f4329e9453bd603" integrity sha512-uxQPkEQAzCYdwhZk16O9m1R4xtCRNy4oEUTBrccOPfzlIahRZJic/JeP/ZEL0BC6Mfq6r55eOg6gMF/zdFoCvA== dependencies: ember-rfc176-data "^0.3.13" babel-plugin-ember-modules-api-polyfill@^3.2.0, babel-plugin-ember-modules-api-polyfill@^3.5.0: version "3.5.0" - resolved "https://registry.npmjs.org/babel-plugin-ember-modules-api-polyfill/-/babel-plugin-ember-modules-api-polyfill-3.5.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-ember-modules-api-polyfill/-/babel-plugin-ember-modules-api-polyfill-3.5.0.tgz#27b6087fac75661f779f32e60f94b14d0e9f6965" integrity sha512-pJajN/DkQUnStw0Az8c6khVcMQHgzqWr61lLNtVeu0g61LRW0k9jyK7vaedrHDWGe/Qe8sxG5wpiyW9NsMqFzA== dependencies: ember-rfc176-data "^0.3.17" babel-plugin-ember-template-compilation@^2.0.0, babel-plugin-ember-template-compilation@^2.0.1: - version "2.2.0" - resolved "https://registry.npmjs.org/babel-plugin-ember-template-compilation/-/babel-plugin-ember-template-compilation-2.2.0.tgz" - integrity sha512-1I7f5gf06h5wKdKUvaYEIaoSFur5RLUvTMQG4ak0c5Y11DWUxcoX9hrun1xe9fqfY2dtGFK+ZUM6sn6z8sqK/w== + version "2.2.5" + resolved "https://registry.npmjs.org/babel-plugin-ember-template-compilation/-/babel-plugin-ember-template-compilation-2.2.5.tgz#9f00cc88eeefdc7d228cfac63c2a40e59691fbf3" + integrity sha512-NQ2DT0DsYyHVrEpFQIy2U8S91JaKSE8NOSZzMd7KZFJVgA6KodJq3Uj852HcH9LsSfvwppnM+dRo1G8bzTnnFw== dependencies: "@glimmer/syntax" "^0.84.3" - babel-import-util "^2.0.0" + babel-import-util "^3.0.0" babel-plugin-filter-imports@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/babel-plugin-filter-imports/-/babel-plugin-filter-imports-4.0.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-filter-imports/-/babel-plugin-filter-imports-4.0.0.tgz#068f8da15236a96a9602c36dc6f4a6eeca70a4f4" integrity sha512-jDLlxI8QnfKd7PtieH6pl4tZJzymzfCDCPGdTq/grgbiYAikwDPp/oL0IlFJn0HQjLpcLkyYhPKkUVneRESw5w== dependencies: "@babel/types" "^7.7.2" @@ -3370,12 +3473,12 @@ babel-plugin-filter-imports@^4.0.0: babel-plugin-htmlbars-inline-precompile@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/babel-plugin-htmlbars-inline-precompile/-/babel-plugin-htmlbars-inline-precompile-3.2.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-htmlbars-inline-precompile/-/babel-plugin-htmlbars-inline-precompile-3.2.0.tgz#c4882ea875d0f5683f0d91c1f72e29a4f14b5606" integrity sha512-IUeZmgs9tMUGXYu1vfke5I18yYJFldFGdNFQOWslXTnDWXzpwPih7QFduUqvT+awDpDuNtXpdt5JAf43Q1Hhzg== babel-plugin-htmlbars-inline-precompile@^5.0.0, babel-plugin-htmlbars-inline-precompile@^5.2.1, babel-plugin-htmlbars-inline-precompile@^5.3.0: version "5.3.1" - resolved "https://registry.npmjs.org/babel-plugin-htmlbars-inline-precompile/-/babel-plugin-htmlbars-inline-precompile-5.3.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-htmlbars-inline-precompile/-/babel-plugin-htmlbars-inline-precompile-5.3.1.tgz#5ba272e2e4b6221522401f5f1d98a73b1de38787" integrity sha512-QWjjFgSKtSRIcsBhJmEwS2laIdrA6na8HAlc/pEAhjHgQsah/gMiBFRZvbQTy//hWxR4BMwV7/Mya7q5H8uHeA== dependencies: babel-plugin-ember-modules-api-polyfill "^3.5.0" @@ -3386,7 +3489,7 @@ babel-plugin-htmlbars-inline-precompile@^5.0.0, babel-plugin-htmlbars-inline-pre babel-plugin-istanbul@^6.0.0: version "6.1.1" - resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -3397,7 +3500,7 @@ babel-plugin-istanbul@^6.0.0: babel-plugin-module-resolver@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.2.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.2.0.tgz#ddfa5e301e3b9aa12d852a9979f18b37881ff5a7" integrity sha512-tjR0GvSndzPew/Iayf4uICWZqjBwnlMWjSx6brryfQ81F9rxBVqwDJtFCV8oOs0+vJeefK9TmdZtkIFdFe1UnA== dependencies: find-babel-config "^1.1.0" @@ -3408,7 +3511,7 @@ babel-plugin-module-resolver@^3.2.0: babel-plugin-module-resolver@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz#22a4f32f7441727ec1fbf4967b863e1e3e9f33e2" integrity sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA== dependencies: find-babel-config "^1.2.0" @@ -3417,58 +3520,69 @@ babel-plugin-module-resolver@^4.1.0: reselect "^4.0.0" resolve "^1.13.1" -babel-plugin-polyfill-corejs2@^0.3.3: - version "0.3.3" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz" - integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== +babel-plugin-module-resolver@^5.0.0: + version "5.0.2" + resolved "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.2.tgz#cdeac5d4aaa3b08dd1ac23ddbf516660ed2d293e" + integrity sha512-9KtaCazHee2xc0ibfqsDeamwDps6FZNo5S0Q81dUqEuFzVwPhcT4J5jOqIVvgCA3Q/wO9hKYxN/Ds3tIsp5ygg== dependencies: - "@babel/compat-data" "^7.17.7" - "@babel/helper-define-polyfill-provider" "^0.3.3" - semver "^6.1.1" + find-babel-config "^2.1.1" + glob "^9.3.3" + pkg-up "^3.1.0" + reselect "^4.1.7" + resolve "^1.22.8" -babel-plugin-polyfill-corejs3@^0.6.0: - version "0.6.0" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz" - integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.11" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" + integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" - core-js-compat "^3.25.1" + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.2" + semver "^6.3.1" -babel-plugin-polyfill-regenerator@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz" - integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== +babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4: + version "0.10.4" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77" + integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.1" + core-js-compat "^3.36.1" + +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.2" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" + integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" + "@babel/helper-define-polyfill-provider" "^0.6.2" babel-plugin-strip-function-call@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/babel-plugin-strip-function-call/-/babel-plugin-strip-function-call-1.0.2.tgz" + resolved "https://registry.npmjs.org/babel-plugin-strip-function-call/-/babel-plugin-strip-function-call-1.0.2.tgz#374a68b5648e16e2b6d1effd280c3abc88648e3a" integrity sha512-2K0dgOk0AMceFHEpizpQU35nVwZ3HdygyXDedVv88+UkxjAH88k7ns8giaRkc8Tfjw6fPDvHkTC40xbI3bpbUA== babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" - resolved "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" integrity sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw== babel-plugin-syntax-dynamic-import@^6.18.0: version "6.18.0" - resolved "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" integrity sha512-MioUE+LfjCEz65Wf7Z/Rm4XCP5k2c+TbMd2Z2JKc7U9uwjBhAfNPE48KC4GTGKhppMeYVepwDBNO/nGY6NYHBA== babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" - resolved "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" integrity sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ== babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" - resolved "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" integrity sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ== babel-plugin-transform-async-to-generator@^6.22.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" integrity sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw== dependencies: babel-helper-remap-async-to-generator "^6.24.1" @@ -3477,21 +3591,21 @@ babel-plugin-transform-async-to-generator@^6.22.0: babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" integrity sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg== dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: version "6.22.0" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" integrity sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A== dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoping@^6.23.0: version "6.26.0" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" integrity sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw== dependencies: babel-runtime "^6.26.0" @@ -3502,7 +3616,7 @@ babel-plugin-transform-es2015-block-scoping@^6.23.0: babel-plugin-transform-es2015-classes@^6.23.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" integrity sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag== dependencies: babel-helper-define-map "^6.24.1" @@ -3517,7 +3631,7 @@ babel-plugin-transform-es2015-classes@^6.23.0: babel-plugin-transform-es2015-computed-properties@^6.22.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" integrity sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw== dependencies: babel-runtime "^6.22.0" @@ -3525,14 +3639,14 @@ babel-plugin-transform-es2015-computed-properties@^6.22.0: babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" integrity sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA== dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-duplicate-keys@^6.22.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" integrity sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug== dependencies: babel-runtime "^6.22.0" @@ -3540,14 +3654,14 @@ babel-plugin-transform-es2015-duplicate-keys@^6.22.0: babel-plugin-transform-es2015-for-of@^6.23.0: version "6.23.0" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" integrity sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw== dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-function-name@^6.22.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" integrity sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg== dependencies: babel-helper-function-name "^6.24.1" @@ -3556,14 +3670,14 @@ babel-plugin-transform-es2015-function-name@^6.22.0: babel-plugin-transform-es2015-literals@^6.22.0: version "6.22.0" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" integrity sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ== dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" integrity sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA== dependencies: babel-plugin-transform-es2015-modules-commonjs "^6.24.1" @@ -3572,7 +3686,7 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: version "6.26.2" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== dependencies: babel-plugin-transform-strict-mode "^6.24.1" @@ -3582,7 +3696,7 @@ babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-systemjs@^6.23.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" integrity sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg== dependencies: babel-helper-hoist-variables "^6.24.1" @@ -3591,7 +3705,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.23.0: babel-plugin-transform-es2015-modules-umd@^6.23.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" integrity sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw== dependencies: babel-plugin-transform-es2015-modules-amd "^6.24.1" @@ -3600,7 +3714,7 @@ babel-plugin-transform-es2015-modules-umd@^6.23.0: babel-plugin-transform-es2015-object-super@^6.22.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" integrity sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA== dependencies: babel-helper-replace-supers "^6.24.1" @@ -3608,7 +3722,7 @@ babel-plugin-transform-es2015-object-super@^6.22.0: babel-plugin-transform-es2015-parameters@^6.23.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" integrity sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ== dependencies: babel-helper-call-delegate "^6.24.1" @@ -3620,7 +3734,7 @@ babel-plugin-transform-es2015-parameters@^6.23.0: babel-plugin-transform-es2015-shorthand-properties@^6.22.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" integrity sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw== dependencies: babel-runtime "^6.22.0" @@ -3628,14 +3742,14 @@ babel-plugin-transform-es2015-shorthand-properties@^6.22.0: babel-plugin-transform-es2015-spread@^6.22.0: version "6.22.0" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" integrity sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg== dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-sticky-regex@^6.22.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" integrity sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ== dependencies: babel-helper-regex "^6.24.1" @@ -3644,21 +3758,21 @@ babel-plugin-transform-es2015-sticky-regex@^6.22.0: babel-plugin-transform-es2015-template-literals@^6.22.0: version "6.22.0" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" integrity sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg== dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-typeof-symbol@^6.23.0: version "6.23.0" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" integrity sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw== dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-unicode-regex@^6.22.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" integrity sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ== dependencies: babel-helper-regex "^6.24.1" @@ -3667,7 +3781,7 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0: babel-plugin-transform-exponentiation-operator@^6.22.0: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" integrity sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ== dependencies: babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" @@ -3676,14 +3790,14 @@ babel-plugin-transform-exponentiation-operator@^6.22.0: babel-plugin-transform-regenerator@^6.22.0: version "6.26.0" - resolved "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" integrity sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg== dependencies: regenerator-transform "^0.10.0" babel-plugin-transform-strict-mode@^6.24.1: version "6.24.1" - resolved "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz" + resolved "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" integrity sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw== dependencies: babel-runtime "^6.22.0" @@ -3691,7 +3805,7 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-polyfill@^6.26.0: version "6.26.0" - resolved "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz" + resolved "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" integrity sha512-F2rZGQnAdaHWQ8YAoeRbukc7HS9QgdgeyJ0rQDd485v9opwuPvjpPFcOOT/WmkKTdgy9ESgSPXDcTNpzrGr6iQ== dependencies: babel-runtime "^6.26.0" @@ -3700,7 +3814,7 @@ babel-polyfill@^6.26.0: babel-preset-env@^1.7.0: version "1.7.0" - resolved "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz" + resolved "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== dependencies: babel-plugin-check-es2015-constants "^6.22.0" @@ -3736,7 +3850,7 @@ babel-preset-env@^1.7.0: babel-register@^6.26.0: version "6.26.0" - resolved "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz" + resolved "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" integrity sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A== dependencies: babel-core "^6.26.0" @@ -3749,7 +3863,7 @@ babel-register@^6.26.0: babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: version "6.26.0" - resolved "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" + resolved "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== dependencies: core-js "^2.4.0" @@ -3757,7 +3871,7 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: babel-template@^6.24.1, babel-template@^6.26.0: version "6.26.0" - resolved "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" + resolved "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" integrity sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg== dependencies: babel-runtime "^6.26.0" @@ -3768,7 +3882,7 @@ babel-template@^6.24.1, babel-template@^6.26.0: babel-traverse@^6.24.1, babel-traverse@^6.26.0: version "6.26.0" - resolved "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz" + resolved "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA== dependencies: babel-code-frame "^6.26.0" @@ -3783,7 +3897,7 @@ babel-traverse@^6.24.1, babel-traverse@^6.26.0: babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: version "6.26.0" - resolved "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" + resolved "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== dependencies: babel-runtime "^6.26.0" @@ -3793,49 +3907,49 @@ babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: babel6-plugin-strip-class-callcheck@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/babel6-plugin-strip-class-callcheck/-/babel6-plugin-strip-class-callcheck-6.0.0.tgz" + resolved "https://registry.npmjs.org/babel6-plugin-strip-class-callcheck/-/babel6-plugin-strip-class-callcheck-6.0.0.tgz#de841c1abebbd39f78de0affb2c9a52ee228fddf" integrity sha512-biNFJ7JAK4+9BwswDGL0dmYpvXHvswOFR/iKg3Q/f+pNxPEa5bWZkLHI1fW4spPytkHGMe7f/XtYyhzml9hiWg== babylon@^6.18.0: version "6.18.0" - resolved "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz" + resolved "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== backbone@^1.1.2: - version "1.4.1" - resolved "https://registry.npmjs.org/backbone/-/backbone-1.4.1.tgz" - integrity sha512-ADy1ztN074YkWbHi8ojJVFe3vAanO/lrzMGZWUClIP7oDD/Pjy2vrASraUP+2EVCfIiTtCW4FChVow01XneivA== + version "1.6.0" + resolved "https://registry.npmjs.org/backbone/-/backbone-1.6.0.tgz#5cdfa25257819b223109a77a74dde26d38995930" + integrity sha512-13PUjmsgw/49EowNcQvfG4gmczz1ximTMhUktj0Jfrjth0MVaTxehpU+qYYX4MxnuIuhmvBLC6/ayxuAGnOhbA== dependencies: underscore ">=1.8.3" backtick-template@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/backtick-template/-/backtick-template-0.2.0.tgz" + resolved "https://registry.npmjs.org/backtick-template/-/backtick-template-0.2.0.tgz#de33168260e70eff6435f565ad7aa8699d0b7fe9" integrity sha512-F5h0OHBy6gHJDA952velLcEuKQ+GTZHPsJEKyA1s+7aRTZ0i3V+gdLOxYenDKE19t0FDbMEFR3+Yvr64jtjShA== bail@^1.0.0: version "1.0.5" - resolved "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz" + resolved "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base64-js@^1.0.2, base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" - resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== base64id@2.0.0, base64id@~2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz" + resolved "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== base@^0.11.1: version "0.11.2" - resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz" + resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" @@ -3848,41 +3962,41 @@ base@^0.11.1: basic-auth@~2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz" + resolved "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== dependencies: safe-buffer "5.1.2" big.js@^5.2.2: version "5.2.2" - resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz" + resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== binary-extensions@^1.0.0: version "1.13.1" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + version "2.3.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== "binaryextensions@1 || 2", binaryextensions@^2.1.2: version "2.3.0" - resolved "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz" + resolved "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz#1d269cbf7e6243ea886aa41453c3651ccbe13c22" integrity sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg== bindings@^1.5.0: version "1.5.0" - resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz" + resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== dependencies: file-uri-to-path "1.0.0" bl@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" + resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== dependencies: buffer "^5.5.0" @@ -3891,50 +4005,32 @@ bl@^4.1.0: blank-object@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/blank-object/-/blank-object-1.0.2.tgz" + resolved "https://registry.npmjs.org/blank-object/-/blank-object-1.0.2.tgz#f990793fbe9a8c8dd013fb3219420bec81d5f4b9" integrity sha512-kXQ19Xhoghiyw66CUiGypnuRpWlbHAzY/+NyvqTEdTfhfQGH1/dbEMYiXju7fYKIFePpzp/y9dsu5Cu/PkmawQ== bluebird@^3.4.6, bluebird@^3.5.5, bluebird@^3.7.2: version "3.7.2" - resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" + resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== blueimp-md5@^2.10.0: version "2.19.0" - resolved "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz" + resolved "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz#b53feea5498dcb53dc6ec4b823adb84b729c4af0" integrity sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.0" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1: +bn.js@^5.0.0, bn.js@^5.2.1: version "5.2.1" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== -body-parser@1.20.1: - version "1.20.1" - resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz" - integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== - dependencies: - bytes "3.1.2" - content-type "~1.0.4" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.1" - type-is "~1.6.18" - unpipe "1.0.0" - -body-parser@^1.19.0: +body-parser@1.20.2, body-parser@^1.19.0: version "1.20.2" - resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== dependencies: bytes "3.1.2" @@ -3952,7 +4048,7 @@ body-parser@^1.19.0: body@^5.1.0: version "5.1.0" - resolved "https://registry.npmjs.org/body/-/body-5.1.0.tgz" + resolved "https://registry.npmjs.org/body/-/body-5.1.0.tgz#e4ba0ce410a46936323367609ecb4e6553125069" integrity sha512-chUsBxGRtuElD6fmw1gHLpvnKdVLK302peeFa9ZqAEk8TyzZ3fygLyUEDDPTJvL9+Bor0dIwn6ePOsRM2y0zQQ== dependencies: continuable-cache "^0.3.1" @@ -3962,7 +4058,7 @@ body@^5.1.0: bower-config@^1.4.3: version "1.4.3" - resolved "https://registry.npmjs.org/bower-config/-/bower-config-1.4.3.tgz" + resolved "https://registry.npmjs.org/bower-config/-/bower-config-1.4.3.tgz#3454fecdc5f08e7aa9cc6d556e492be0669689ae" integrity sha512-MVyyUk3d1S7d2cl6YISViwJBc2VXCkxF5AUFykvN0PQj5FsUiMNSgAYTso18oRFfyZ6XEtjrgg9MAaufHbOwNw== dependencies: graceful-fs "^4.1.3" @@ -3974,43 +4070,27 @@ bower-config@^1.4.3: bower-endpoint-parser@0.2.2: version "0.2.2" - resolved "https://registry.npmjs.org/bower-endpoint-parser/-/bower-endpoint-parser-0.2.2.tgz" + resolved "https://registry.npmjs.org/bower-endpoint-parser/-/bower-endpoint-parser-0.2.2.tgz#00b565adbfab6f2d35addde977e97962acbcb3f6" integrity sha512-YWZHhWkPdXtIfH3VRu3QIV95sa75O9vrQWBOHjexWCLBCTy5qJvRr36LXTqFwTchSXVlzy5piYJOjzHr7qhsNg== brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +braces@^2.3.1, braces@^2.3.2, braces@^3.0.0, braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" broccoli-amd-funnel@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/broccoli-amd-funnel/-/broccoli-amd-funnel-2.0.1.tgz" + resolved "https://registry.npmjs.org/broccoli-amd-funnel/-/broccoli-amd-funnel-2.0.1.tgz#dbdbfd28841731342d538126567c25bea3f15310" integrity sha512-VRE+0PYAN4jQfkIq3GKRj4U/4UV9rVpLan5ll6fVYV4ziVg4OEfR5GUnILEg++QtR4xSaugRxCPU5XJLDy3bNQ== dependencies: broccoli-plugin "^1.3.0" @@ -4018,7 +4098,7 @@ broccoli-amd-funnel@^2.0.1: broccoli-asset-rev@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/broccoli-asset-rev/-/broccoli-asset-rev-3.0.0.tgz" + resolved "https://registry.npmjs.org/broccoli-asset-rev/-/broccoli-asset-rev-3.0.0.tgz#65a28c8a062d6ee2cffd91ed2a8309e0f8253ac6" integrity sha512-gAHQZnwvtl74tGevUqGuWoyOdJUdMMv0TjGSMzbdyGImr9fZcnM6xmggDA8bUawrMto9NFi00ZtNUgA4dQiUBw== dependencies: broccoli-asset-rewrite "^2.0.0" @@ -4030,14 +4110,14 @@ broccoli-asset-rev@^3.0.0: broccoli-asset-rewrite@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/broccoli-asset-rewrite/-/broccoli-asset-rewrite-2.0.0.tgz" + resolved "https://registry.npmjs.org/broccoli-asset-rewrite/-/broccoli-asset-rewrite-2.0.0.tgz#603c4a52d4c8987a2f681254436923ac0a9c94ab" integrity sha512-dqhxdQpooNi7LHe8J9Jdxp6o3YPFWl4vQmint6zrsn2sVbOo+wpyiX3erUSt0IBtjNkAxqJjuvS375o2cLBHTA== dependencies: broccoli-filter "^1.2.3" broccoli-babel-transpiler@^6.5.0: version "6.5.1" - resolved "https://registry.npmjs.org/broccoli-babel-transpiler/-/broccoli-babel-transpiler-6.5.1.tgz" + resolved "https://registry.npmjs.org/broccoli-babel-transpiler/-/broccoli-babel-transpiler-6.5.1.tgz#a4afc8d3b59b441518eb9a07bd44149476e30738" integrity sha512-w6GcnkxvHcNCte5FcLGEG1hUdQvlfvSN/6PtGWU/otg69Ugk8rUk51h41R0Ugoc+TNxyeFG1opRt2RlA87XzNw== dependencies: babel-core "^6.26.0" @@ -4053,7 +4133,7 @@ broccoli-babel-transpiler@^6.5.0: broccoli-babel-transpiler@^7.8.0: version "7.8.1" - resolved "https://registry.npmjs.org/broccoli-babel-transpiler/-/broccoli-babel-transpiler-7.8.1.tgz" + resolved "https://registry.npmjs.org/broccoli-babel-transpiler/-/broccoli-babel-transpiler-7.8.1.tgz#a5dc04cf4f59de98124fc128683ab2b83e5d28c1" integrity sha512-6IXBgfRt7HZ61g67ssBc6lBb3Smw3DPZ9dEYirgtvXWpRZ2A9M22nxy6opEwJDgDJzlu/bB7ToppW33OFkA1gA== dependencies: "@babel/core" "^7.12.0" @@ -4069,9 +4149,23 @@ broccoli-babel-transpiler@^7.8.0: rsvp "^4.8.4" workerpool "^3.1.1" +broccoli-babel-transpiler@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/broccoli-babel-transpiler/-/broccoli-babel-transpiler-8.0.0.tgz#07576728a95b840a99d5f0f9b07b71a737f69319" + integrity sha512-3HEp3flvasUKJGWERcrPgM1SWvHJ0O/fmbEtY9L4kDyMSnqjY6hTYvNvgWCIgbwXAYAUlZP0vjAQsmyLNGLwFw== + dependencies: + broccoli-persistent-filter "^3.0.0" + clone "^2.1.2" + hash-for-dep "^1.4.7" + heimdalljs "^0.2.1" + heimdalljs-logger "^0.1.9" + json-stable-stringify "^1.0.1" + rsvp "^4.8.4" + workerpool "^6.0.2" + broccoli-bridge@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/broccoli-bridge/-/broccoli-bridge-1.0.0.tgz" + resolved "https://registry.npmjs.org/broccoli-bridge/-/broccoli-bridge-1.0.0.tgz#6223fd64b62062c31333539f0f3c42d0acd92fb1" integrity sha512-WvU6T6AJrtpFSScgyCVEFAajPAJTOYYIIpGvs/PbkSq9OUBvI3/IEUHg+Ipx376M/clGFwa7K9crEtpauqC66A== dependencies: broccoli-plugin "^1.3.0" @@ -4080,7 +4174,7 @@ broccoli-bridge@^1.0.0: broccoli-builder@^0.18.14: version "0.18.14" - resolved "https://registry.npmjs.org/broccoli-builder/-/broccoli-builder-0.18.14.tgz" + resolved "https://registry.npmjs.org/broccoli-builder/-/broccoli-builder-0.18.14.tgz#4b79e2f844de11a4e1b816c3f49c6df4776c312d" integrity sha512-YoUHeKnPi4xIGZ2XDVN9oHNA9k3xF5f5vlA+1wvrxIIDXqQU97gp2FxVAF503Zxdtt0C5CRB5n+47k2hlkaBzA== dependencies: broccoli-node-info "^1.1.0" @@ -4093,7 +4187,7 @@ broccoli-builder@^0.18.14: broccoli-caching-writer@^2.2.0: version "2.3.1" - resolved "https://registry.npmjs.org/broccoli-caching-writer/-/broccoli-caching-writer-2.3.1.tgz" + resolved "https://registry.npmjs.org/broccoli-caching-writer/-/broccoli-caching-writer-2.3.1.tgz#b93cf58f9264f003075868db05774f4e7f25bd07" integrity sha512-lfoDx98VaU8tG4mUXCxKdKyw2Lr+iSIGUjCgV83KC2zRC07SzYTGuSsMqpXFiOQlOGuoJxG3NRoyniBa1BWOqA== dependencies: broccoli-kitchen-sink-helpers "^0.2.5" @@ -4105,7 +4199,7 @@ broccoli-caching-writer@^2.2.0: broccoli-caching-writer@^3.0.3: version "3.0.3" - resolved "https://registry.npmjs.org/broccoli-caching-writer/-/broccoli-caching-writer-3.0.3.tgz" + resolved "https://registry.npmjs.org/broccoli-caching-writer/-/broccoli-caching-writer-3.0.3.tgz#0bd2c96a9738d6a6ab590f07ba35c5157d7db476" integrity sha512-g644Kb5uBPsy+6e2DvO3sOc+/cXZQQNgQt64QQzjA9TSdP0dl5qvetpoNIx4sy/XIjrPYG1smEidq9Z9r61INw== dependencies: broccoli-kitchen-sink-helpers "^0.3.1" @@ -4117,7 +4211,7 @@ broccoli-caching-writer@^3.0.3: broccoli-clean-css@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/broccoli-clean-css/-/broccoli-clean-css-1.1.0.tgz" + resolved "https://registry.npmjs.org/broccoli-clean-css/-/broccoli-clean-css-1.1.0.tgz#9db143d9af7e0ae79c26e3ac5a9bb2d720ea19fa" integrity sha512-S7/RWWX+lL42aGc5+fXVLnwDdMtS0QEWUFalDp03gJ9Na7zj1rWa351N2HZ687E2crM9g+eDWXKzD17cbcTepg== dependencies: broccoli-persistent-filter "^1.1.6" @@ -4127,7 +4221,7 @@ broccoli-clean-css@^1.1.0: broccoli-concat@^4.2.2, broccoli-concat@^4.2.4, broccoli-concat@^4.2.5: version "4.2.5" - resolved "https://registry.npmjs.org/broccoli-concat/-/broccoli-concat-4.2.5.tgz" + resolved "https://registry.npmjs.org/broccoli-concat/-/broccoli-concat-4.2.5.tgz#d578f00094048b5fc87195e82fbdbde20d838d29" integrity sha512-dFB5ATPwOyV8S2I7a07HxCoutoq23oY//LhM6Mou86cWUTB174rND5aQLR7Fu8FjFFLxoTbkk7y0VPITJ1IQrw== dependencies: broccoli-debug "^0.6.5" @@ -4144,14 +4238,14 @@ broccoli-concat@^4.2.2, broccoli-concat@^4.2.4, broccoli-concat@^4.2.5: broccoli-config-loader@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/broccoli-config-loader/-/broccoli-config-loader-1.0.1.tgz" + resolved "https://registry.npmjs.org/broccoli-config-loader/-/broccoli-config-loader-1.0.1.tgz#d10aaf8ebc0cb45c1da5baa82720e1d88d28c80a" integrity sha512-MDKYQ50rxhn+g17DYdfzfEM9DjTuSGu42Db37A8TQHQe8geYEcUZ4SQqZRgzdAI3aRQNlA1yBHJfOeGmOjhLIg== dependencies: broccoli-caching-writer "^3.0.3" broccoli-config-replace@^1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/broccoli-config-replace/-/broccoli-config-replace-1.1.2.tgz" + resolved "https://registry.npmjs.org/broccoli-config-replace/-/broccoli-config-replace-1.1.2.tgz#6ea879d92a5bad634d11329b51fc5f4aafda9c00" integrity sha512-qLlEY3V7p3ZWJNRPdPgwIM77iau1qR03S9BupMMFngjzBr7S6RSzcg96HbCYXmW9gfTbjRm9FC4CQT81SBusZg== dependencies: broccoli-kitchen-sink-helpers "^0.3.1" @@ -4161,7 +4255,7 @@ broccoli-config-replace@^1.1.2: broccoli-debug@^0.6.4, broccoli-debug@^0.6.5: version "0.6.5" - resolved "https://registry.npmjs.org/broccoli-debug/-/broccoli-debug-0.6.5.tgz" + resolved "https://registry.npmjs.org/broccoli-debug/-/broccoli-debug-0.6.5.tgz#164a5cdafd8936e525e702bf8f91f39d758e2e78" integrity sha512-RIVjHvNar9EMCLDW/FggxFRXqpjhncM/3qq87bn/y+/zR9tqEkHvTqbyOc4QnB97NO2m6342w4wGkemkaeOuWg== dependencies: broccoli-plugin "^1.2.1" @@ -4173,7 +4267,7 @@ broccoli-debug@^0.6.4, broccoli-debug@^0.6.5: broccoli-file-creator@^1.1.1: version "1.2.0" - resolved "https://registry.npmjs.org/broccoli-file-creator/-/broccoli-file-creator-1.2.0.tgz" + resolved "https://registry.npmjs.org/broccoli-file-creator/-/broccoli-file-creator-1.2.0.tgz#27f1b25b1b00e7bb7bf3d5d7abed5f4d5388df4d" integrity sha512-l9zthHg6bAtnOfRr/ieZ1srRQEsufMZID7xGYRW3aBDv3u/3Eux+Iawl10tAGYE5pL9YB4n5X4vxkp6iNOoZ9g== dependencies: broccoli-plugin "^1.1.0" @@ -4181,7 +4275,7 @@ broccoli-file-creator@^1.1.1: broccoli-file-creator@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/broccoli-file-creator/-/broccoli-file-creator-2.1.1.tgz" + resolved "https://registry.npmjs.org/broccoli-file-creator/-/broccoli-file-creator-2.1.1.tgz#7351dd2496c762cfce7736ce9b49e3fce0c7b7db" integrity sha512-YpjOExWr92C5vhnK0kmD81kM7U09kdIRZk9w4ZDCDHuHXW+VE/x6AGEOQQW3loBQQ6Jk+k+TSm8dESy4uZsnjw== dependencies: broccoli-plugin "^1.1.0" @@ -4189,7 +4283,7 @@ broccoli-file-creator@^2.1.1: broccoli-filter@^1.2.2, broccoli-filter@^1.2.3: version "1.3.0" - resolved "https://registry.npmjs.org/broccoli-filter/-/broccoli-filter-1.3.0.tgz" + resolved "https://registry.npmjs.org/broccoli-filter/-/broccoli-filter-1.3.0.tgz#71e3a8e32a17f309e12261919c5b1006d6766de6" integrity sha512-VXJXw7eBfG82CFxaBDjYmyN7V72D4In2zwLVQJd/h3mBfF3CMdRTsv2L20lmRTtCv1sAHcB+LgMso90e/KYiLw== dependencies: broccoli-kitchen-sink-helpers "^0.3.1" @@ -4204,12 +4298,12 @@ broccoli-filter@^1.2.2, broccoli-filter@^1.2.3: broccoli-funnel-reducer@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/broccoli-funnel-reducer/-/broccoli-funnel-reducer-1.0.0.tgz" + resolved "https://registry.npmjs.org/broccoli-funnel-reducer/-/broccoli-funnel-reducer-1.0.0.tgz#11365b2a785aec9b17972a36df87eef24c5cc0ea" integrity sha512-SaOCEdh+wnt2jFUV2Qb32m7LXyElvFwW3NKNaEJyi5PGQNwxfqpkc0KI6AbQANKgdj/40U2UC0WuGThFwuEUaA== broccoli-funnel@2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/broccoli-funnel/-/broccoli-funnel-2.0.1.tgz" + resolved "https://registry.npmjs.org/broccoli-funnel/-/broccoli-funnel-2.0.1.tgz#6823c73b675ef78fffa7ab800f083e768b51d449" integrity sha512-C8Lnp9TVsSSiZMGEF16C0dCiNg2oJqUKwuZ1K4kVC6qRPG/2Cj/rtB5kRCC9qEbwqhX71bDbfHROx0L3J7zXQg== dependencies: array-equal "^1.0.0" @@ -4228,7 +4322,7 @@ broccoli-funnel@2.0.1: broccoli-funnel@^1.0.1, broccoli-funnel@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/broccoli-funnel/-/broccoli-funnel-1.2.0.tgz" + resolved "https://registry.npmjs.org/broccoli-funnel/-/broccoli-funnel-1.2.0.tgz#cddc3afc5ff1685a8023488fff74ce6fb5a51296" integrity sha512-0pbFNUA5Ml+gPPd58Rj/M26OS21+bMiV0F+m6+9OVzAhAdppVLxylSsXfWAt2WOD3kS+D8UsDv6GSmnZhbw/dw== dependencies: array-equal "^1.0.0" @@ -4248,7 +4342,7 @@ broccoli-funnel@^1.0.1, broccoli-funnel@^1.1.0: broccoli-funnel@^2.0.0, broccoli-funnel@^2.0.1, broccoli-funnel@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/broccoli-funnel/-/broccoli-funnel-2.0.2.tgz" + resolved "https://registry.npmjs.org/broccoli-funnel/-/broccoli-funnel-2.0.2.tgz#0edf629569bc10bd02cc525f74b9a38e71366a75" integrity sha512-/vDTqtv7ipjEZQOVqO4vGDVAOZyuYzQ/EgGoyewfOgh1M7IQAToBKZI0oAQPgMBeFPPlIbfMuAngk+ohPBuaHQ== dependencies: array-equal "^1.0.0" @@ -4267,7 +4361,7 @@ broccoli-funnel@^2.0.0, broccoli-funnel@^2.0.1, broccoli-funnel@^2.0.2: broccoli-funnel@^3.0.0, broccoli-funnel@^3.0.2, broccoli-funnel@^3.0.3, broccoli-funnel@^3.0.5, broccoli-funnel@^3.0.8: version "3.0.8" - resolved "https://registry.npmjs.org/broccoli-funnel/-/broccoli-funnel-3.0.8.tgz" + resolved "https://registry.npmjs.org/broccoli-funnel/-/broccoli-funnel-3.0.8.tgz#f5b62e2763c3918026a15a3c833edc889971279b" integrity sha512-ng4eIhPYiXqMw6SyGoxPHR3YAwEd2lr9FgBI1CyTbspl4txZovOsmzFkMkGAlu88xyvYXJqHiM2crfLa65T1BQ== dependencies: array-equal "^1.0.0" @@ -4280,7 +4374,7 @@ broccoli-funnel@^3.0.0, broccoli-funnel@^3.0.2, broccoli-funnel@^3.0.3, broccoli broccoli-kitchen-sink-helpers@^0.2.5: version "0.2.9" - resolved "https://registry.npmjs.org/broccoli-kitchen-sink-helpers/-/broccoli-kitchen-sink-helpers-0.2.9.tgz" + resolved "https://registry.npmjs.org/broccoli-kitchen-sink-helpers/-/broccoli-kitchen-sink-helpers-0.2.9.tgz#a5e0986ed8d76fb5984b68c3f0450d3a96e36ecc" integrity sha512-C+oEqivDofZv/h80rgN4WJkbZkbfwkrIeu8vFn4bb4m4jPd3ICNNplhkXGl3ps439pzc2yjZ1qIwz0yy8uHcQg== dependencies: glob "^5.0.10" @@ -4288,7 +4382,7 @@ broccoli-kitchen-sink-helpers@^0.2.5: broccoli-kitchen-sink-helpers@^0.3.1: version "0.3.1" - resolved "https://registry.npmjs.org/broccoli-kitchen-sink-helpers/-/broccoli-kitchen-sink-helpers-0.3.1.tgz" + resolved "https://registry.npmjs.org/broccoli-kitchen-sink-helpers/-/broccoli-kitchen-sink-helpers-0.3.1.tgz#77c7c18194b9664163ec4fcee2793444926e0c06" integrity sha512-gqYnKSJxBSjj/uJqeuRAzYVbmjWhG0mOZ8jrp6+fnUIOgLN6MvI7XxBECDHkYMIFPJ8Smf4xaI066Q2FqQDnXg== dependencies: glob "^5.0.10" @@ -4296,7 +4390,7 @@ broccoli-kitchen-sink-helpers@^0.3.1: broccoli-merge-files@^0.8.0: version "0.8.0" - resolved "https://registry.npmjs.org/broccoli-merge-files/-/broccoli-merge-files-0.8.0.tgz" + resolved "https://registry.npmjs.org/broccoli-merge-files/-/broccoli-merge-files-0.8.0.tgz#65ed9d6888548d44bf95208bc7759ac1d10bd382" integrity sha512-S6dXHECbDkr7YMuCitAAQT8EZeW/kXom0Y8+QmQfiSkWspkKDGrr4vXgEZJjWqfa/FSx/Y18NEEOuMmbIW+XNQ== dependencies: broccoli-plugin "^1.3.0" @@ -4306,7 +4400,7 @@ broccoli-merge-files@^0.8.0: broccoli-merge-trees@^1.0.0, broccoli-merge-trees@^1.1.1: version "1.2.4" - resolved "https://registry.npmjs.org/broccoli-merge-trees/-/broccoli-merge-trees-1.2.4.tgz" + resolved "https://registry.npmjs.org/broccoli-merge-trees/-/broccoli-merge-trees-1.2.4.tgz#a001519bb5067f06589d91afa2942445a2d0fdb5" integrity sha512-RXJAleytlED0dxXGEo2EXwrg5cCesY8LQzzGRogwGQmluoz+ijzxajpyWAW6wu/AyuQZj1vgnIqnld8jvuuXtQ== dependencies: broccoli-plugin "^1.3.0" @@ -4320,7 +4414,7 @@ broccoli-merge-trees@^1.0.0, broccoli-merge-trees@^1.1.1: broccoli-merge-trees@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/broccoli-merge-trees/-/broccoli-merge-trees-2.0.1.tgz" + resolved "https://registry.npmjs.org/broccoli-merge-trees/-/broccoli-merge-trees-2.0.1.tgz#14d4b7fc1a90318c12b16f843e6ba2693808100c" integrity sha512-WjaexJ+I8BxP5V5RNn6um/qDRSmKoiBC/QkRi79FT9ClHfldxRyCDs9mcV7mmoaPlsshmmPaUz5jdtcKA6DClQ== dependencies: broccoli-plugin "^1.3.0" @@ -4328,7 +4422,7 @@ broccoli-merge-trees@^2.0.0: broccoli-merge-trees@^3.0.0, broccoli-merge-trees@^3.0.1, broccoli-merge-trees@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/broccoli-merge-trees/-/broccoli-merge-trees-3.0.2.tgz" + resolved "https://registry.npmjs.org/broccoli-merge-trees/-/broccoli-merge-trees-3.0.2.tgz#f33b451994225522b5c9bcf27d59decfd8ba537d" integrity sha512-ZyPAwrOdlCddduFbsMyyFzJUrvW6b04pMvDiAQZrCwghlvgowJDY+EfoXn+eR1RRA5nmGHJ+B68T63VnpRiT1A== dependencies: broccoli-plugin "^1.3.0" @@ -4336,7 +4430,7 @@ broccoli-merge-trees@^3.0.0, broccoli-merge-trees@^3.0.1, broccoli-merge-trees@^ broccoli-merge-trees@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/broccoli-merge-trees/-/broccoli-merge-trees-4.2.0.tgz" + resolved "https://registry.npmjs.org/broccoli-merge-trees/-/broccoli-merge-trees-4.2.0.tgz#692d3c163ecea08c5714a9434d664e628919f47c" integrity sha512-nTrQe5AQtCrW4enLRvbD/vTLHqyW2tz+vsLXQe4IEaUhepuMGVKJJr+I8n34Vu6fPjmPLwTjzNC8izMIDMtHPw== dependencies: broccoli-plugin "^4.0.2" @@ -4344,7 +4438,7 @@ broccoli-merge-trees@^4.2.0: broccoli-middleware@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/broccoli-middleware/-/broccoli-middleware-2.1.1.tgz" + resolved "https://registry.npmjs.org/broccoli-middleware/-/broccoli-middleware-2.1.1.tgz#183635bbef4dc1241533ee001a162f013d776cb9" integrity sha512-BK8aPhQpOLsHWiftrqXQr84XsvzUqeaN4PlCQOYg5yM0M+WKAHtX2WFXmicSQZOVgKDyh5aeoNTFkHjBAEBzwQ== dependencies: ansi-html "^0.0.7" @@ -4354,29 +4448,29 @@ broccoli-middleware@^2.1.1: broccoli-node-api@^1.6.0, broccoli-node-api@^1.7.0: version "1.7.0" - resolved "https://registry.npmjs.org/broccoli-node-api/-/broccoli-node-api-1.7.0.tgz" + resolved "https://registry.npmjs.org/broccoli-node-api/-/broccoli-node-api-1.7.0.tgz#391aa6edecd2a42c63c111b4162956b2fa288cb6" integrity sha512-QIqLSVJWJUVOhclmkmypJJH9u9s/aWH4+FH6Q6Ju5l+Io4dtwqdPUNmDfw40o6sxhbZHhqGujDJuHTML1wG8Yw== broccoli-node-info@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/broccoli-node-info/-/broccoli-node-info-1.1.0.tgz" + resolved "https://registry.npmjs.org/broccoli-node-info/-/broccoli-node-info-1.1.0.tgz#3aa2e31e07e5bdb516dd25214f7c45ba1c459412" integrity sha512-DUohSZCdfXli/3iN6SmxPbck1OVG8xCkrLx47R25his06xVc1ZmmrOsrThiM8BsCWirwyocODiYJqNP5W2Hg1A== broccoli-node-info@^2.1.0: version "2.2.0" - resolved "https://registry.npmjs.org/broccoli-node-info/-/broccoli-node-info-2.2.0.tgz" + resolved "https://registry.npmjs.org/broccoli-node-info/-/broccoli-node-info-2.2.0.tgz#feb01c13020792f429e01d7f7845dc5b3a7932b3" integrity sha512-VabSGRpKIzpmC+r+tJueCE5h8k6vON7EIMMWu6d/FyPdtijwLQ7QvzShEw+m3mHoDzUaj/kiZsDYrS8X2adsBg== broccoli-output-wrapper@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/broccoli-output-wrapper/-/broccoli-output-wrapper-2.0.0.tgz" + resolved "https://registry.npmjs.org/broccoli-output-wrapper/-/broccoli-output-wrapper-2.0.0.tgz#f1e0b9b2f259a67fd41a380141c3c20b096828e6" integrity sha512-V/ozejo+snzNf75i/a6iTmp71k+rlvqjE3+jYfimuMwR1tjNNRdtfno+NGNQB2An9bIAeqZnKhMDurAznHAdtA== dependencies: heimdalljs-logger "^0.1.10" broccoli-output-wrapper@^3.2.5: version "3.2.5" - resolved "https://registry.npmjs.org/broccoli-output-wrapper/-/broccoli-output-wrapper-3.2.5.tgz" + resolved "https://registry.npmjs.org/broccoli-output-wrapper/-/broccoli-output-wrapper-3.2.5.tgz#514b17801c92922a2c2f87fd145df2a25a11bc5f" integrity sha512-bQAtwjSrF4Nu0CK0JOy5OZqw9t5U0zzv2555EA/cF8/a8SLDTIetk9UgrtMVw7qKLKdSpOZ2liZNeZZDaKgayw== dependencies: fs-extra "^8.1.0" @@ -4385,7 +4479,7 @@ broccoli-output-wrapper@^3.2.5: broccoli-persistent-filter@^1.1.6, broccoli-persistent-filter@^1.4.3: version "1.4.6" - resolved "https://registry.npmjs.org/broccoli-persistent-filter/-/broccoli-persistent-filter-1.4.6.tgz" + resolved "https://registry.npmjs.org/broccoli-persistent-filter/-/broccoli-persistent-filter-1.4.6.tgz#80762d19000880a77da33c34373299c0f6a3e615" integrity sha512-0RejLwoC95kv4kta8KAa+FmECJCK78Qgm8SRDEK7YyU0N9Cx6KpY3UCDy9WELl3mCXLN8TokNxc7/hp3lL4lfw== dependencies: async-disk-cache "^1.2.1" @@ -4404,7 +4498,7 @@ broccoli-persistent-filter@^1.1.6, broccoli-persistent-filter@^1.4.3: broccoli-persistent-filter@^2.1.0, broccoli-persistent-filter@^2.2.1, broccoli-persistent-filter@^2.3.0, broccoli-persistent-filter@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/broccoli-persistent-filter/-/broccoli-persistent-filter-2.3.1.tgz" + resolved "https://registry.npmjs.org/broccoli-persistent-filter/-/broccoli-persistent-filter-2.3.1.tgz#4a052e0e0868b344c3a2977e35a3d497aa9eca72" integrity sha512-hVsmIgCDrl2NFM+3Gs4Cr2TA6UPaIZip99hN8mtkaUPgM8UeVnCbxelCvBjUBHo0oaaqP5jzqqnRVvb568Yu5g== dependencies: async-disk-cache "^1.2.1" @@ -4422,9 +4516,9 @@ broccoli-persistent-filter@^2.1.0, broccoli-persistent-filter@^2.2.1, broccoli-p sync-disk-cache "^1.3.3" walk-sync "^1.0.0" -broccoli-persistent-filter@^3.1.1, broccoli-persistent-filter@^3.1.2: +broccoli-persistent-filter@^3.0.0, broccoli-persistent-filter@^3.1.1, broccoli-persistent-filter@^3.1.2: version "3.1.3" - resolved "https://registry.npmjs.org/broccoli-persistent-filter/-/broccoli-persistent-filter-3.1.3.tgz" + resolved "https://registry.npmjs.org/broccoli-persistent-filter/-/broccoli-persistent-filter-3.1.3.tgz#aca815bf3e3b0247bd0a7b567fdb0d0e08c99cc2" integrity sha512-Q+8iezprZzL9voaBsDY3rQVl7c7H5h+bvv8SpzCZXPZgfBFCbx7KFQ2c3rZR6lW5k4Kwoqt7jG+rZMUg67Gwxw== dependencies: async-disk-cache "^2.0.0" @@ -4441,7 +4535,7 @@ broccoli-persistent-filter@^3.1.1, broccoli-persistent-filter@^3.1.2: broccoli-plugin@*, broccoli-plugin@^4.0.0, broccoli-plugin@^4.0.1, broccoli-plugin@^4.0.2, broccoli-plugin@^4.0.3, broccoli-plugin@^4.0.5, broccoli-plugin@^4.0.7: version "4.0.7" - resolved "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-4.0.7.tgz" + resolved "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-4.0.7.tgz#dd176a85efe915ed557d913744b181abe05047db" integrity sha512-a4zUsWtA1uns1K7p9rExYVYG99rdKeGRymW0qOCNkvDPHQxVi3yVyJHhQbM3EZwdt2E0mnhr5e0c/bPpJ7p3Wg== dependencies: broccoli-node-api "^1.7.0" @@ -4454,7 +4548,7 @@ broccoli-plugin@*, broccoli-plugin@^4.0.0, broccoli-plugin@^4.0.1, broccoli-plug broccoli-plugin@1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-1.1.0.tgz" + resolved "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-1.1.0.tgz#73e2cfa05f8ea1e3fc1420c40c3d9e7dc724bf02" integrity sha512-dY1QsA20of9wWEto8yhN7JQjpfjySmgeIMsvnQ9aBAv1wEJJCe04B0ekdgq7Bduyx9yWXdoC5CngGy81swmp2w== dependencies: promise-map-series "^0.2.1" @@ -4464,7 +4558,7 @@ broccoli-plugin@1.1.0: broccoli-plugin@^1.0.0, broccoli-plugin@^1.1.0, broccoli-plugin@^1.2.0, broccoli-plugin@^1.2.1, broccoli-plugin@^1.3.0: version "1.3.1" - resolved "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-1.3.1.tgz" + resolved "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-1.3.1.tgz#a26315732fb99ed2d9fb58f12a1e14e986b4fabd" integrity sha512-DW8XASZkmorp+q7J4EeDEZz+LoyKLAd2XZULXyD9l4m9/hAKV3vjHmB1kiUshcWAYMgTP1m2i4NnqCE/23h6AQ== dependencies: promise-map-series "^0.2.1" @@ -4474,7 +4568,7 @@ broccoli-plugin@^1.0.0, broccoli-plugin@^1.1.0, broccoli-plugin@^1.2.0, broccoli broccoli-plugin@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-2.1.0.tgz" + resolved "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-2.1.0.tgz#2fab6c578219cfcc64f773e9616073313fc8b334" integrity sha512-ElE4caljW4slapyEhSD9jU9Uayc8SoSABWdmY9SqbV8DHNxU6xg1jJsPcMm+cXOvggR3+G+OXAYQeFjWVnznaw== dependencies: promise-map-series "^0.2.1" @@ -4484,7 +4578,7 @@ broccoli-plugin@^2.1.0: broccoli-plugin@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-3.1.0.tgz" + resolved "https://registry.npmjs.org/broccoli-plugin/-/broccoli-plugin-3.1.0.tgz#54ba6dd90a42ec3db5624063292610e326b1e542" integrity sha512-7w7FP8WJYjLvb0eaw27LO678TGGaom++49O1VYIuzjhXjK5kn2+AMlDm7CaUFw4F7CLGoVQeZ84d8gICMJa4lA== dependencies: broccoli-node-api "^1.6.0" @@ -4497,7 +4591,7 @@ broccoli-plugin@^3.1.0: broccoli-postcss-single@^5.0.1: version "5.0.2" - resolved "https://registry.npmjs.org/broccoli-postcss-single/-/broccoli-postcss-single-5.0.2.tgz" + resolved "https://registry.npmjs.org/broccoli-postcss-single/-/broccoli-postcss-single-5.0.2.tgz#f23661b3011494d8a2dbd8ff39eb394e80313682" integrity sha512-r4eWtz/5uihtHwOszViWwV6weJr9VryvaqtVo1DOh4gL+TbTyU+NX+Y+t9TqUw99OtuivMz4uHLLH7zZECbZmw== dependencies: broccoli-caching-writer "^3.0.3" @@ -4509,7 +4603,7 @@ broccoli-postcss-single@^5.0.1: broccoli-postcss@^6.0.1: version "6.1.0" - resolved "https://registry.npmjs.org/broccoli-postcss/-/broccoli-postcss-6.1.0.tgz" + resolved "https://registry.npmjs.org/broccoli-postcss/-/broccoli-postcss-6.1.0.tgz#1e15c5e8a65a984544224f083cbd1e6763691b60" integrity sha512-I8+DHq5xcCBHU0PpCtDMayAmSUVx07CqAquUpdlNUHckXeD//cUFf4aFQllnZBhF8Z86YLhuA+j7qvCYYgBXRg== dependencies: broccoli-funnel "^3.0.0" @@ -4520,7 +4614,7 @@ broccoli-postcss@^6.0.1: broccoli-rollup@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/broccoli-rollup/-/broccoli-rollup-5.0.0.tgz" + resolved "https://registry.npmjs.org/broccoli-rollup/-/broccoli-rollup-5.0.0.tgz#a77b53bcef1b70e988913fee82265c0a4ca530da" integrity sha512-QdMuXHwsdz/LOS8zu4HP91Sfi4ofimrOXoYP/lrPdRh7lJYD87Lfq4WzzUhGHsxMfzANIEvl/7qVHKD3cFJ4tA== dependencies: "@types/broccoli-plugin" "^3.0.0" @@ -4534,9 +4628,9 @@ broccoli-rollup@^5.0.0: walk-sync "^2.2.0" broccoli-sass-source-maps@^4.0.0: - version "4.1.0" - resolved "https://registry.npmjs.org/broccoli-sass-source-maps/-/broccoli-sass-source-maps-4.1.0.tgz" - integrity sha512-So3gTlP9AEJTponlRoL9Ti+xaMX1LnJUWD52mVT0Oq6PI8nIjX97XMW91JfY/4CXsprIDyGe/7rkiauE+XHdPQ== + version "4.2.4" + resolved "https://registry.npmjs.org/broccoli-sass-source-maps/-/broccoli-sass-source-maps-4.2.4.tgz#14bdb5f23c05a38bec33d4953aaabdf3e93eca93" + integrity sha512-MHwqLkgYW24T9k2OzprdYtERCAaO3wuSGqKna8QcAzCjDxYyoojisg2lfSWj9k2G72PlACUjUg8O39jttE84og== dependencies: broccoli-caching-writer "^3.0.3" include-path-searcher "^0.1.0" @@ -4544,31 +4638,31 @@ broccoli-sass-source-maps@^4.0.0: broccoli-slow-trees@^3.0.1, broccoli-slow-trees@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/broccoli-slow-trees/-/broccoli-slow-trees-3.1.0.tgz" + resolved "https://registry.npmjs.org/broccoli-slow-trees/-/broccoli-slow-trees-3.1.0.tgz#8e48903f59e061bf1213963733b9e61dec2ee5d7" integrity sha512-FRI7mRTk2wjIDrdNJd6znS7Kmmne4VkAkl8Ix1R/VoePFMD0g0tEl671xswzFqaRjpT9Qu+CC4hdXDLDJBuzMw== dependencies: heimdalljs "^0.2.1" broccoli-source@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/broccoli-source/-/broccoli-source-1.1.0.tgz" + resolved "https://registry.npmjs.org/broccoli-source/-/broccoli-source-1.1.0.tgz#54f0e82c8b73f46580cbbc4f578f0b32fca8f809" integrity sha512-ahvqmwF6Yvh6l+sTJJdey4o4ynwSH8swSSBSGmUXGSPPCqBWvquWB/4rWN65ZArKilBFq/29O0yQnZNIf//sTg== broccoli-source@^2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/broccoli-source/-/broccoli-source-2.1.2.tgz" + resolved "https://registry.npmjs.org/broccoli-source/-/broccoli-source-2.1.2.tgz#e9ae834f143b607e9ec114ade66731500c38b90b" integrity sha512-1lLayO4wfS0c0Sj50VfHJXNWf94FYY0WUhxj0R77thbs6uWI7USiOWFqQV5dRmhAJnoKaGN4WyLGQbgjgiYFwQ== -broccoli-source@^3.0.0: +broccoli-source@^3.0.0, broccoli-source@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/broccoli-source/-/broccoli-source-3.0.1.tgz" + resolved "https://registry.npmjs.org/broccoli-source/-/broccoli-source-3.0.1.tgz#fd581b2f3877ca1338f724f6ef70acec8c7e1444" integrity sha512-ZbGVQjivWi0k220fEeIUioN6Y68xjMy0xiLAc0LdieHI99gw+tafU8w0CggBDYVNsJMKUr006AZaM7gNEwCxEg== dependencies: broccoli-node-api "^1.6.0" broccoli-sri-hash@^2.1.0: version "2.1.2" - resolved "https://registry.npmjs.org/broccoli-sri-hash/-/broccoli-sri-hash-2.1.2.tgz" + resolved "https://registry.npmjs.org/broccoli-sri-hash/-/broccoli-sri-hash-2.1.2.tgz#bc69905ed7a381ad325cc0d02ded071328ebf3f3" integrity sha512-toLD/v7ut2ajcH8JsdCMG2Bpq2qkwTcKM6CMzVMSAJjaz/KpK69fR+gSqe1dsjh+QTdxG0yVvkq3Sij/XMzV6A== dependencies: broccoli-caching-writer "^2.2.0" @@ -4579,7 +4673,7 @@ broccoli-sri-hash@^2.1.0: broccoli-stew@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/broccoli-stew/-/broccoli-stew-3.0.0.tgz" + resolved "https://registry.npmjs.org/broccoli-stew/-/broccoli-stew-3.0.0.tgz#fd1d19d162ad9490b42e5c563b78c26eb1e80b95" integrity sha512-NXfi+Vas24n3Ivo21GvENTI55qxKu7OwKRnCLWXld8MiLiQKQlWIq28eoARaFj0lTUFwUa4jKZeA7fW9PiWQeg== dependencies: broccoli-debug "^0.6.5" @@ -4598,24 +4692,24 @@ broccoli-stew@^3.0.0: walk-sync "^1.1.3" broccoli-terser-sourcemap@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/broccoli-terser-sourcemap/-/broccoli-terser-sourcemap-4.1.0.tgz" - integrity sha512-zkNnjsAbP+M5rG2aMM1EE4BmXPUSxFKmtLUkUs2D1DLTOJQoF1xlOjGWjjKYCFy5tw8t4+tgGJ+HVa2ucJZ8sw== + version "4.1.1" + resolved "https://registry.npmjs.org/broccoli-terser-sourcemap/-/broccoli-terser-sourcemap-4.1.1.tgz#4c26696e07a822e1fc91fb48c5b6d6c70d5ca9b2" + integrity sha512-8sbpRf0/+XeszBJQM7vph2UNj4Kal0lCI/yubcrBIzb2NvYj5gjTHJABXOdxx5mKNmlCMu2hx2kvOtMpQsxrfg== dependencies: async-promise-queue "^1.0.5" - broccoli-plugin "^4.0.3" - debug "^4.1.0" + broccoli-plugin "^4.0.7" + convert-source-map "^2.0.0" + debug "^4.3.1" lodash.defaultsdeep "^4.6.1" matcher-collection "^2.0.1" - source-map-url "^0.4.0" symlink-or-copy "^1.3.1" - terser "^5.3.0" + terser "^5.7.0" walk-sync "^2.2.0" - workerpool "^6.0.0" + workerpool "^6.1.5" broccoli@^3.5.1: version "3.5.2" - resolved "https://registry.npmjs.org/broccoli/-/broccoli-3.5.2.tgz" + resolved "https://registry.npmjs.org/broccoli/-/broccoli-3.5.2.tgz#60921167d57b43fb5bad527420d62fe532595ef4" integrity sha512-sWi3b3fTUSVPDsz5KsQ5eCQNVAtLgkIE/HYFkEZXR/07clqmd4E/gFiuwSaqa9b+QTXc1Uemfb7TVWbEIURWDg== dependencies: "@types/chai" "^4.2.9" @@ -4645,17 +4739,17 @@ broccoli@^3.5.1: brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" + resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== browser-process-hrtime@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz" + resolved "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browserify-aes@^1.0.0, browserify-aes@^1.0.4: +browserify-aes@^1.0.4, browserify-aes@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz" + resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: buffer-xor "^1.0.3" @@ -4667,7 +4761,7 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: browserify-cipher@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz" + resolved "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" @@ -4676,7 +4770,7 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz" + resolved "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" @@ -4684,74 +4778,75 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: +browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz" + resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== dependencies: bn.js "^5.0.0" randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + version "4.2.3" + resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz#7afe4c01ec7ee59a89a558a4b75bd85ae62d4208" + integrity sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw== dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" + bn.js "^5.2.1" + browserify-rsa "^4.1.0" create-hash "^1.2.0" create-hmac "^1.1.7" - elliptic "^6.5.3" + elliptic "^6.5.5" + hash-base "~3.0" inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + parse-asn1 "^5.1.7" + readable-stream "^2.3.8" + safe-buffer "^5.2.1" browserify-zlib@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz" + resolved "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" browserslist@^3.2.6: version "3.2.8" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== dependencies: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" -browserslist@^4.14.5, browserslist@^4.21.3, browserslist@^4.21.5: - version "4.21.5" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz" - integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== +browserslist@^4.21.10, browserslist@^4.22.2, browserslist@^4.23.0: + version "4.23.1" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz#ce4af0534b3d37db5c1a4ca98b9080f985041e96" + integrity sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw== dependencies: - caniuse-lite "^1.0.30001449" - electron-to-chromium "^1.4.284" - node-releases "^2.0.8" - update-browserslist-db "^1.0.10" + caniuse-lite "^1.0.30001629" + electron-to-chromium "^1.4.796" + node-releases "^2.0.14" + update-browserslist-db "^1.0.16" bser@2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" + resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== dependencies: node-int64 "^0.4.0" buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== buffer-xor@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz" + resolved "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== buffer@^4.3.0: version "4.9.2" - resolved "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz" + resolved "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== dependencies: base64-js "^1.0.2" @@ -4760,7 +4855,7 @@ buffer@^4.3.0: buffer@^5.5.0: version "5.7.1" - resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" + resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== dependencies: base64-js "^1.3.1" @@ -4768,32 +4863,32 @@ buffer@^5.5.0: builtin-status-codes@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz" + resolved "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== builtins@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz" + resolved "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ== bytes@1: version "1.0.0" - resolved "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz" + resolved "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8" integrity sha512-/x68VkHLeTl3/Ll8IvxdwzhrT+IyKc52e/oyHhA2RwqPqswSnjVbSddfPRwAsJtbilMAPSRWwAlpxdYsSWOTKQ== bytes@3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== bytes@3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cacache@^12.0.2: version "12.0.4" - resolved "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz" + resolved "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== dependencies: bluebird "^3.5.5" @@ -4814,7 +4909,7 @@ cacache@^12.0.2: cache-base@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz" + resolved "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" @@ -4829,68 +4924,71 @@ cache-base@^1.0.1: calculate-cache-key-for-tree@2.0.0, calculate-cache-key-for-tree@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/calculate-cache-key-for-tree/-/calculate-cache-key-for-tree-2.0.0.tgz" + resolved "https://registry.npmjs.org/calculate-cache-key-for-tree/-/calculate-cache-key-for-tree-2.0.0.tgz#7ac57f149a4188eacb0a45b210689215d3fef8d6" integrity sha512-Quw8a6y8CPmRd6eU+mwypktYCwUcf8yVFIRbNZ6tPQEckX9yd+EBVEPC/GSZZrMWH9e7Vz4pT7XhpmyApRByLQ== dependencies: json-stable-stringify "^1.0.1" calculate-cache-key-for-tree@^1.1.0: version "1.2.3" - resolved "https://registry.npmjs.org/calculate-cache-key-for-tree/-/calculate-cache-key-for-tree-1.2.3.tgz" + resolved "https://registry.npmjs.org/calculate-cache-key-for-tree/-/calculate-cache-key-for-tree-1.2.3.tgz#5a5e4fcfa2d374a63e47fe967593f179e8282825" integrity sha512-PPQorvdNw8K8k7UftCeradwOmKDSDJs8wcqYTtJPEt3fHbZyK8QsorybJA+lOmk0dgE61vX6R+5Kd3W9h4EMGg== dependencies: json-stable-stringify "^1.0.1" -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== +call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" call-me-maybe@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz" + resolved "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== callsites@^3.0.0, callsites@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase-css@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz" + resolved "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== can-symlink@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/can-symlink/-/can-symlink-1.0.0.tgz" + resolved "https://registry.npmjs.org/can-symlink/-/can-symlink-1.0.0.tgz#97b607d8a84bb6c6e228b902d864ecb594b9d219" integrity sha512-RbsNrFyhwkx+6psk/0fK/Q9orOUr9VMxohGd8vTa4djf4TGLfblBgUfqZChrZuW0Q+mz2eBPFLusw9Jfukzmhg== dependencies: tmp "0.0.28" -caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001464: - version "1.0.30001464" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001464.tgz" - integrity sha512-oww27MtUmusatpRpCGSOneQk2/l5czXANDSFvsc7VuOQ86s3ANhZetpwXNf1zY/zdfP63Xvjz325DAdAoES13g== +caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001599, caniuse-lite@^1.0.30001629: + version "1.0.30001640" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz#32c467d4bf1f1a0faa63fc793c2ba81169e7652f" + integrity sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA== capture-exit@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz" + resolved "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== dependencies: rsvp "^4.8.4" cardinal@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/cardinal/-/cardinal-1.0.0.tgz" + resolved "https://registry.npmjs.org/cardinal/-/cardinal-1.0.0.tgz#50e21c1b0aa37729f9377def196b5a9cec932ee9" integrity sha512-INsuF4GyiFLk8C91FPokbKTc/rwHqV4JnfatVZ6GPhguP1qmkRWX2dp5tepYboYdPpGWisLVLI+KsXoXFPRSMg== dependencies: ansicolors "~0.2.1" @@ -4898,17 +4996,17 @@ cardinal@^1.0.0: ccount@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz" + resolved "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== ceibo@~2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/ceibo/-/ceibo-2.0.0.tgz" + resolved "https://registry.npmjs.org/ceibo/-/ceibo-2.0.0.tgz#9a61eb054a91c09934588d4e45d9dd2c3bf04eee" integrity sha512-Zt+Nhkzd1s9hsOhEmCMkmzAn1AmjQ/RuEnXOF3H46NYlkrQoApA8PIiacz/YASdxeFse1F50B7eoppw4pPie6g== chalk@^1.0.0, chalk@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" + resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== dependencies: ansi-styles "^2.2.1" @@ -4917,9 +5015,9 @@ chalk@^1.0.0, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -4928,65 +5026,56 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4 chalk@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz" + resolved "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0, chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@~0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz" - integrity sha512-sQfYDlfv2DGVtjdoQqxS0cEZDroyG8h6TamA6rvxwlrU5BaSLDx9xhatBYl2pxZ7gmpNaPFVwBtdGdu5rQ+tYQ== - dependencies: - ansi-styles "~1.0.0" - has-color "~0.1.0" - strip-ansi "~0.1.0" - character-entities-html4@^1.0.0: version "1.1.4" - resolved "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz" + resolved "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz#0e64b0a3753ddbf1fdc044c5fd01d0199a02e125" integrity sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g== character-entities-legacy@^1.0.0: version "1.1.4" - resolved "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz" + resolved "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== character-entities@^1.0.0: version "1.2.4" - resolved "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz" + resolved "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== character-reference-invalid@^1.0.0: version "1.1.4" - resolved "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz" + resolved "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== chardet@^0.7.0: version "0.7.0" - resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz" + resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== charm@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/charm/-/charm-1.0.2.tgz" + resolved "https://registry.npmjs.org/charm/-/charm-1.0.2.tgz#8add367153a6d9a581331052c4090991da995e35" integrity sha512-wqW3VdPnlSWT4eRiYX+hcs+C6ViBPUWk1qTCd+37qw9kEm/a5n2qcyQDMBWvSYKN/ctqZzeXNQaeBjOetJJUkw== dependencies: inherits "^2.0.1" "chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.1, chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + version "3.6.0" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -5000,7 +5089,7 @@ charm@^1.0.0: chokidar@^2.1.8: version "2.1.8" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== dependencies: anymatch "^2.0.0" @@ -5019,22 +5108,22 @@ chokidar@^2.1.8: chownr@^1.1.1: version "1.1.4" - resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz" + resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + version "1.0.4" + resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== ci-info@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz" + resolved "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" @@ -5042,7 +5131,7 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: class-utils@^0.3.5: version "0.3.6" - resolved "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz" + resolved "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" @@ -5052,17 +5141,17 @@ class-utils@^0.3.5: cldr-core@^36.0.0: version "36.0.0" - resolved "https://registry.npmjs.org/cldr-core/-/cldr-core-36.0.0.tgz" + resolved "https://registry.npmjs.org/cldr-core/-/cldr-core-36.0.0.tgz#1d2148ed6802411845baeeb21432d7bbfde7d4f7" integrity sha512-QLnAjt20rZe38c8h8OJ9jPND+O4o5O8Nw0TK/P3KpNn1cmOhMu0rk6Kc3ap96c5OStQ9gAngs9+Be2sum26NOw== clean-base-url@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/clean-base-url/-/clean-base-url-1.0.0.tgz" + resolved "https://registry.npmjs.org/clean-base-url/-/clean-base-url-1.0.0.tgz#c901cf0a20b972435b0eccd52d056824a4351b7b" integrity sha512-9q6ZvUAhbKOSRFY7A/irCQ/rF0KIpa3uXpx6izm8+fp7b2H4hLeUJ+F1YYk9+gDQ/X8Q0MEyYs+tG3cht//HTg== clean-css-promise@^0.1.0: version "0.1.1" - resolved "https://registry.npmjs.org/clean-css-promise/-/clean-css-promise-0.1.1.tgz" + resolved "https://registry.npmjs.org/clean-css-promise/-/clean-css-promise-0.1.1.tgz#43f3d2c8dfcb2bf071481252cd9b76433c08eecb" integrity sha512-tzWkANXMD70ETa/wAu2TXAAxYWS0ZjVUFM2dVik8RQBoAbGMFJv4iVluz3RpcoEbo++fX4RV/BXfgGoOjp8o3Q== dependencies: array-to-error "^1.0.0" @@ -5071,7 +5160,7 @@ clean-css-promise@^0.1.0: clean-css@^3.4.5: version "3.4.28" - resolved "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz" + resolved "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz#bf1945e82fc808f55695e6ddeaec01400efd03ff" integrity sha512-aTWyttSdI2mYi07kWqHi24NUU9YlELFKGOAgFzZjDN1064DMAOy2FBuoyGmkKRlXkbpXd0EVHmiVkbKhKoirTw== dependencies: commander "2.8.x" @@ -5079,37 +5168,37 @@ clean-css@^3.4.5: clean-stack@^2.0.0, clean-stack@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" + resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== clean-up-path@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/clean-up-path/-/clean-up-path-1.0.0.tgz" + resolved "https://registry.npmjs.org/clean-up-path/-/clean-up-path-1.0.0.tgz#de9e8196519912e749c9eaf67c13d64fac72a3e5" integrity sha512-PHGlEF0Z6976qQyN6gM7kKH6EH0RdfZcc8V+QhFe36eRxV0SMH5OUBZG7Bxa9YcreNzyNbK63cGiZxdSZgosRw== cli-cursor@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz" + resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== dependencies: restore-cursor "^2.0.0" cli-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz" + resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== dependencies: restore-cursor "^3.1.0" cli-spinners@^2.0.0, cli-spinners@^2.5.0: - version "2.7.0" - resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz" - integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw== + version "2.9.2" + resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== cli-table3@^0.6.0: - version "0.6.3" - resolved "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz" - integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + version "0.6.5" + resolved "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" + integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== dependencies: string-width "^4.2.0" optionalDependencies: @@ -5117,14 +5206,14 @@ cli-table3@^0.6.0: cli-table@^0.3.1: version "0.3.11" - resolved "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz" + resolved "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz#ac69cdecbe81dccdba4889b9a18b7da312a9d3ee" integrity sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ== dependencies: colors "1.0.3" cli-truncate@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz" + resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== dependencies: slice-ansi "^3.0.0" @@ -5132,17 +5221,17 @@ cli-truncate@^2.1.0: cli-width@^2.0.0: version "2.2.1" - resolved "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz" + resolved "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== cli-width@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz" + resolved "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== clipboard@^2.0.11: version "2.0.11" - resolved "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz" + resolved "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz#62180360b97dd668b6b3a84ec226975762a70be5" integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw== dependencies: good-listener "^1.2.2" @@ -5151,7 +5240,7 @@ clipboard@^2.0.11: cliui@^7.0.2: version "7.0.4" - resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" + resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== dependencies: string-width "^4.2.0" @@ -5160,27 +5249,27 @@ cliui@^7.0.2: clone@^1.0.2: version "1.0.4" - resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" + resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== clone@^2.0.0, clone@^2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz" + resolved "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== code-point-at@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz" + resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== -codemirror@~5.15.0: - version "5.15.2" - resolved "https://registry.npmjs.org/codemirror/-/codemirror-5.15.2.tgz" - integrity sha512-QHZClCGimKVK86/+K1YcKwa2/9pzy5OfAsv0nsXlPxxoWOhGc+HxPWQISnIrYMHwA5QCtiObxo5O/tmV4fzOSQ== +codemirror@5.58.2, codemirror@~5.15.0: + version "5.58.2" + resolved "https://registry.npmjs.org/codemirror/-/codemirror-5.58.2.tgz#ed54a1796de1498688bea1cdd4e9eeb187565d1b" + integrity sha512-K/hOh24cCwRutd1Mk3uLtjWzNISOkm4fvXiMO7LucCrqbh6aJDdtqUziim3MZUI6wOY0rvY1SlL1Ork01uMy6w== collection-visit@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz" + resolved "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== dependencies: map-visit "^1.0.0" @@ -5188,117 +5277,122 @@ collection-visit@^1.0.0: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== -color-name@^1.1.4, color-name@~1.1.4: +color-name@~1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-support@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz" + resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== colorette@^2.0.16: - version "2.0.19" - resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz" - integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + version "2.0.20" + resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== colors@1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz" + resolved "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" integrity sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw== colors@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz" + resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== combined-stream@^1.0.8: version "1.0.8" - resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" comma-separated-tokens@^1.0.0: version "1.0.8" - resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz" + resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== commander@2.8.x: version "2.8.1" - resolved "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz" + resolved "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" integrity sha512-+pJLBFVk+9ZZdlAOB5WuIElVPPth47hILFkmGym57aq8kwxsowvByvB0DHs1vQAhyMZzdcpTtF0VDKGkSDR4ZQ== dependencies: graceful-readlink ">= 1.0.0" commander@7.2.0: version "7.2.0" - resolved "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz" + resolved "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== commander@^2.20.0, commander@^2.6.0: version "2.20.3" - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^4.1.1: +commander@^4.0.0, commander@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz" + resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== commander@^6.2.0, commander@^6.2.1: version "6.2.1" - resolved "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz" + resolved "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== +common-ancestor-path@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7" + integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w== + common-tags@^1.8.0: version "1.8.2" - resolved "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz" + resolved "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA== commondir@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" + resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== compare-versions@^3.6.0: version "3.6.0" - resolved "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz" + resolved "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + version "1.3.1" + resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17" + integrity sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== compressible@~2.0.16: version "2.0.18" - resolved "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz" + resolved "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== dependencies: mime-db ">= 1.43.0 < 2" compression@^1.7.4: version "1.7.4" - resolved "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz" + resolved "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== dependencies: accepts "~1.3.5" @@ -5311,12 +5405,12 @@ compression@^1.7.4: concat-map@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== concat-stream@^1.5.0: version "1.6.2" - resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz" + resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" @@ -5326,7 +5420,7 @@ concat-stream@^1.5.0: configstore@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz" + resolved "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== dependencies: dot-prop "^5.2.0" @@ -5338,7 +5432,7 @@ configstore@^5.0.1: connect@^3.6.6: version "3.7.0" - resolved "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz" + resolved "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== dependencies: debug "2.6.9" @@ -5348,17 +5442,17 @@ connect@^3.6.6: console-browserify@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz" + resolved "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" + resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== console-ui@^3.0.4, console-ui@^3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/console-ui/-/console-ui-3.1.2.tgz" + resolved "https://registry.npmjs.org/console-ui/-/console-ui-3.1.2.tgz#51aef616ff02013c85ccee6a6d77ef7a94202e7a" integrity sha512-+5j3R4wZJcEYZeXk30whc4ZU/+fWW9JMTNntVuMYpjZJ9n26Cxr0tUBXco1NRjVZRpRVvZ4DDKKKIHNYeUG9Dw== dependencies: chalk "^2.1.0" @@ -5369,41 +5463,61 @@ console-ui@^3.0.4, console-ui@^3.1.2: consolidate@^0.16.0: version "0.16.0" - resolved "https://registry.npmjs.org/consolidate/-/consolidate-0.16.0.tgz" + resolved "https://registry.npmjs.org/consolidate/-/consolidate-0.16.0.tgz#a11864768930f2f19431660a65906668f5fbdc16" integrity sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ== dependencies: bluebird "^3.7.2" constants-browserify@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz" + resolved "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== +"consul-acls@file:packages/consul-acls": + version "0.1.0" + +"consul-lock-sessions@file:packages/consul-lock-sessions": + version "0.1.0" + +"consul-nspaces@file:packages/consul-nspaces": + version "0.1.0" + +"consul-partitions@file:packages/consul-partitions": + version "0.1.0" + +"consul-peerings@file:packages/consul-peerings": + version "0.1.0" + content-disposition@0.5.4: version "0.5.4" - resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: safe-buffer "5.2.1" content-type@~1.0.4, content-type@~1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== continuable-cache@^0.3.1: version "0.3.1" - resolved "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz" + resolved "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz#bd727a7faed77e71ff3985ac93351a912733ad0f" integrity sha512-TF30kpKhTH8AGCG3dut0rdd/19B7Z+qCnrMoBLpyQu/2drZdNrrpcjPEoJeSVsQM+8KmWG5O56oPDjSSUsuTyA== -convert-source-map@^1.5.1, convert-source-map@^1.7.0: +convert-source-map@^1.5.1: version "1.9.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + cookie-parser@^1.4.4: version "1.4.6" - resolved "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz" + resolved "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz#3ac3a7d35a7a03bbc7e365073a26074824214594" integrity sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA== dependencies: cookie "0.4.1" @@ -5411,22 +5525,27 @@ cookie-parser@^1.4.4: cookie-signature@1.0.6: version "1.0.6" - resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.4.1, cookie@~0.4.1: +cookie@0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== + +cookie@~0.4.1: + version "0.4.2" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== copy-concurrently@^1.0.0: version "1.0.5" - resolved "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz" + resolved "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== dependencies: aproba "^1.1.1" @@ -5438,41 +5557,41 @@ copy-concurrently@^1.0.0: copy-dereference@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/copy-dereference/-/copy-dereference-1.0.0.tgz" + resolved "https://registry.npmjs.org/copy-dereference/-/copy-dereference-1.0.0.tgz#6b131865420fd81b413ba994b44d3655311152b6" integrity sha512-40TSLuhhbiKeszZhK9LfNdazC67Ue4kq/gGwN5sdxEUWPXTIMmKmGmgD9mPfNKVAeecEW+NfEIpBaZoACCQLLw== copy-descriptor@^0.1.0: version "0.1.1" - resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz" + resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== -core-js-compat@^3.25.1: - version "3.29.0" - resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.29.0.tgz" - integrity sha512-ScMn3uZNAFhK2DGoEfErguoiAHhV2Ju+oJo/jK08p7B3f3UhocUrCCkTvnZaiS+edl5nlIoiBXKcwMc6elv4KQ== +core-js-compat@^3.31.0, core-js-compat@^3.36.1: + version "3.37.1" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz#c844310c7852f4bdf49b8d339730b97e17ff09ee" + integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg== dependencies: - browserslist "^4.21.5" + browserslist "^4.23.0" core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.5: version "2.6.12" - resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz" + resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== core-object@^3.1.5: version "3.1.5" - resolved "https://registry.npmjs.org/core-object/-/core-object-3.1.5.tgz" + resolved "https://registry.npmjs.org/core-object/-/core-object-3.1.5.tgz#fa627b87502adc98045e44678e9a8ec3b9c0d2a9" integrity sha512-sA2/4+/PZ/KV6CKgjrVrrUVBKCkdDO02CUlQ0YKTQoYUwPYNOtOAcWlbYhd5v/1JqYaA6oZ4sDlOU4ppVw6Wbg== dependencies: chalk "^2.0.0" core-util-is@~1.0.0: version "1.0.3" - resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== cors@~2.8.5: version "2.8.5" - resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz" + resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== dependencies: object-assign "^4" @@ -5480,7 +5599,7 @@ cors@~2.8.5: cosmiconfig@^7.0.0: version "7.1.0" - resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz" + resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== dependencies: "@types/parse-json" "^4.0.0" @@ -5491,7 +5610,7 @@ cosmiconfig@^7.0.0: create-ecdh@^4.0.0: version "4.0.4" - resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz" + resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== dependencies: bn.js "^4.1.0" @@ -5499,7 +5618,7 @@ create-ecdh@^4.0.0: create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz" + resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" @@ -5510,7 +5629,7 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" - resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz" + resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" @@ -5522,7 +5641,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== dependencies: nice-try "^1.0.4" @@ -5533,7 +5652,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" @@ -5542,7 +5661,7 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: crypto-browserify@^3.11.0: version "3.12.0" - resolved "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz" + resolved "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" @@ -5559,12 +5678,12 @@ crypto-browserify@^3.11.0: crypto-random-string@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz" + resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== css-loader@^5.2.0: version "5.2.7" - resolved "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz" + resolved "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz#9b9f111edf6fb2be5dc62525644cbc9c232064ae" integrity sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg== dependencies: icss-utils "^5.1.0" @@ -5580,7 +5699,7 @@ css-loader@^5.2.0: css-tree@^2.0.4: version "2.3.1" - resolved "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz" + resolved "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz#10264ce1e5442e8572fc82fbe490644ff54b5c20" integrity sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw== dependencies: mdn-data "2.0.30" @@ -5588,12 +5707,12 @@ css-tree@^2.0.4: css.escape@^1.5.1: version "1.5.1" - resolved "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz" + resolved "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== css@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/css/-/css-3.0.0.tgz" + resolved "https://registry.npmjs.org/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d" integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ== dependencies: inherits "^2.0.4" @@ -5602,175 +5721,218 @@ css@^3.0.0: cssesc@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" + resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== cssom@^0.4.4: version "0.4.4" - resolved "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz" + resolved "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== cssom@~0.3.6: version "0.3.8" - resolved "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz" + resolved "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== cssstyle@^2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz" + resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== dependencies: cssom "~0.3.6" cyclist@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz" - integrity sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A== + version "1.0.2" + resolved "https://registry.npmjs.org/cyclist/-/cyclist-1.0.2.tgz#673b5f233bf34d8e602b949429f8171d9121bea3" + integrity sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA== + +"d3-array@2 - 3", "d3-array@2.10.0 - 3": + version "3.2.4" + resolved "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== + dependencies: + internmap "1 - 2" -d3-array@2, d3-array@^2.3.0, d3-array@^2.8.0: +d3-array@^2.8.0: version "2.12.1" - resolved "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz" + resolved "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81" integrity sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ== dependencies: internmap "^1.0.0" -"d3-color@1 - 2": - version "2.0.0" - resolved "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz" - integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ== +"d3-color@1 - 3": + version "3.1.0" + resolved "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== -"d3-format@1 - 2": - version "2.0.0" - resolved "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz" - integrity sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA== +"d3-format@1 - 3": + version "3.1.0" + resolved "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== -"d3-interpolate@1 - 2", "d3-interpolate@1.2.0 - 2": - version "2.0.1" - resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz" - integrity sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ== +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3": + version "3.0.1" + resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== dependencies: - d3-color "1 - 2" + d3-color "1 - 3" "d3-path@1 - 2": version "2.0.0" - resolved "https://registry.npmjs.org/d3-path/-/d3-path-2.0.0.tgz" + resolved "https://registry.npmjs.org/d3-path/-/d3-path-2.0.0.tgz#55d86ac131a0548adae241eebfb56b4582dd09d8" integrity sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA== -d3-scale-chromatic@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz" - integrity sha512-LLqy7dJSL8yDy7NRmf6xSlsFZ6zYvJ4BcWFE4zBrOPnQERv9zj24ohnXKRbyi9YHnYV+HN1oEO3iFK971/gkzA== +d3-scale-chromatic@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#34c39da298b23c20e02f1a4b239bd0f22e7f1314" + integrity sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ== dependencies: - d3-color "1 - 2" - d3-interpolate "1 - 2" + d3-color "1 - 3" + d3-interpolate "1 - 3" -d3-scale@^3.2.3: - version "3.3.0" - resolved "https://registry.npmjs.org/d3-scale/-/d3-scale-3.3.0.tgz" - integrity sha512-1JGp44NQCt5d1g+Yy+GeOnZP7xHo0ii8zsQp6PGzd+C1/dl0KGsp9A7Mxwp+1D1o4unbTTxVdU/ZOIEBoeZPbQ== +d3-scale@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== dependencies: - d3-array "^2.3.0" - d3-format "1 - 2" - d3-interpolate "1.2.0 - 2" - d3-time "^2.1.1" - d3-time-format "2 - 3" + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" d3-selection@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz" + resolved "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz#94a11638ea2141b7565f883780dabc7ef6a61066" integrity sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA== d3-shape@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-2.1.0.tgz" + resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-2.1.0.tgz#3b6a82ccafbc45de55b57fcf956c584ded3b666f" integrity sha512-PnjUqfM2PpskbSLTJvAzp2Wv4CZsnAgTfcVRTwW03QR3MkXF8Uo7B1y/lWkAsmbKwuecto++4NlsYcvYpXpTHA== dependencies: d3-path "1 - 2" -"d3-time-format@2 - 3": - version "3.0.0" - resolved "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz" - integrity sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag== +"d3-time-format@2 - 4": + version "4.1.0" + resolved "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== dependencies: - d3-time "1 - 2" + d3-time "1 - 3" -"d3-time@1 - 2", d3-time@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz" - integrity sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ== +"d3-time@1 - 3", "d3-time@2.1.1 - 3": + version "3.1.0" + resolved "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== dependencies: - d3-array "2" + d3-array "2 - 3" dag-map@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/dag-map/-/dag-map-2.0.2.tgz" + resolved "https://registry.npmjs.org/dag-map/-/dag-map-2.0.2.tgz#9714b472de82a1843de2fba9b6876938cab44c68" integrity sha512-xnsprIzYuDeiyu5zSKwilV/ajRHxnoMlAhEREfyfTgTSViMVY2fGP1ZcHJbtwup26oCkofySU/m6oKJ3HrkW7w== data-urls@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz" + resolved "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== dependencies: abab "^2.0.3" whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" +data-view-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" + integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" + integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" + integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + dayjs@^1.9.3: - version "1.11.7" - resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz" - integrity sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ== + version "1.11.11" + resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e" + integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg== debug@2.6.9, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" - resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: - version "4.3.4" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== +debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: + version "4.3.5" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== dependencies: ms "2.1.2" debug@^3.0.1, debug@^3.1.0, debug@^3.2.7: version "3.2.7" - resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" + resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" debuglog@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz" + resolved "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw== decimal.js@^10.2.1: version "10.4.3" - resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz" + resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== decode-uri-component@^0.2.0: version "0.2.2" - resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz" + resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== +decorator-transforms@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/decorator-transforms/-/decorator-transforms-2.0.0.tgz#4e9178a8905c81ff79f4078dc6dfb716244ecd37" + integrity sha512-ETfQccGcotK01YJsoB0AGTdUp7kS9jI93mBzrRY5Oyo+bOJfa2UKTSjCNf+iRNwAWBmBKlbiCcyL4tkY4C4dZQ== + dependencies: + "@babel/plugin-syntax-decorators" "^7.23.3" + babel-import-util "^3.0.0" + dedent@^0.7.0: version "0.7.0" - resolved "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz" + resolved "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== -deep-equal@^2.2.0: - version "2.2.0" - resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz" - integrity sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw== +deep-equal@^2.2.3: + version "2.2.3" + resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1" + integrity sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA== dependencies: - call-bind "^1.0.2" - es-get-iterator "^1.1.2" - get-intrinsic "^1.1.3" + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.5" + es-get-iterator "^1.1.3" + get-intrinsic "^1.2.2" is-arguments "^1.1.1" - is-array-buffer "^3.0.1" + is-array-buffer "^3.0.2" is-date-object "^1.0.5" is-regex "^1.1.4" is-shared-array-buffer "^1.0.2" @@ -5778,136 +5940,137 @@ deep-equal@^2.2.0: object-is "^1.1.5" object-keys "^1.1.1" object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" + regexp.prototype.flags "^1.5.1" side-channel "^1.0.4" which-boxed-primitive "^1.0.2" which-collection "^1.0.1" - which-typed-array "^1.1.9" + which-typed-array "^1.1.13" -deep-is@^0.1.3, deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.4" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== deepmerge@^4.2.2: - version "4.3.0" - resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz" - integrity sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og== + version "4.3.1" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== defaults@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz" + resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== dependencies: clone "^1.0.2" -define-properties@^1.1.3, define-properties@^1.1.4: - version "1.2.0" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz" - integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== +define-data-property@^1.0.1, define-data-property@^1.1.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-properties@^1.2.0, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" has-property-descriptors "^1.0.0" object-keys "^1.1.1" define-property@^0.2.5: version "0.2.5" - resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz" + resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz" + resolved "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz" + resolved "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" -defined@^1.0.0, defined@^1.0.1: +defined@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz" + resolved "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== delegate@^3.1.2: version "3.2.0" - resolved "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz" + resolved "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== delegates@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" + resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== depd@2.0.0, depd@~2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" + resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== depd@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" + resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + version "1.1.0" + resolved "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" + integrity sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg== dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" destroy@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detect-file@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz" + resolved "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q== detect-indent@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz" + resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" integrity sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A== dependencies: repeating "^2.0.0" detect-indent@^6.0.0: version "6.1.0" - resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz" + resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== detect-newline@3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" + resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== -detective@^5.2.1: - version "5.2.1" - resolved "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz" - integrity sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw== - dependencies: - acorn-node "^1.8.2" - defined "^1.0.0" - minimist "^1.2.6" - dezalgo@^1.0.0: version "1.0.4" - resolved "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz" + resolved "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== dependencies: asap "^2.0.0" @@ -5915,27 +6078,27 @@ dezalgo@^1.0.0: dialog-polyfill@^0.5.6: version "0.5.6" - resolved "https://registry.npmjs.org/dialog-polyfill/-/dialog-polyfill-0.5.6.tgz" + resolved "https://registry.npmjs.org/dialog-polyfill/-/dialog-polyfill-0.5.6.tgz#7507b4c745a82fcee0fa07ce64d835979719599a" integrity sha512-ZbVDJI9uvxPAKze6z146rmfUZjBqNEwcnFTVamQzXH+svluiV7swmVIGr7miwADgfgt1G2JQIytypM9fbyhX4w== didyoumean@^1.2.2: version "1.2.2" - resolved "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz" + resolved "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== diff@^4.0.2: version "4.0.2" - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== diff@^5.0.0: - version "5.1.0" - resolved "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz" - integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + version "5.2.0" + resolved "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== diffie-hellman@^5.0.0: version "5.0.3" - resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz" + resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== dependencies: bn.js "^4.1.0" @@ -5944,19 +6107,19 @@ diffie-hellman@^5.0.0: dir-glob@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: path-type "^4.0.0" dlv@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz" + resolved "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== doctoc@^2.0.0: version "2.2.1" - resolved "https://registry.npmjs.org/doctoc/-/doctoc-2.2.1.tgz" + resolved "https://registry.npmjs.org/doctoc/-/doctoc-2.2.1.tgz#83f6a6bf4df97defbe027c9a82d13091a138ffe2" integrity sha512-qNJ1gsuo7hH40vlXTVVrADm6pdg30bns/Mo7Nv1SxuXSM1bwF9b4xQ40a6EFT/L1cI+Yylbyi8MPI4G4y7XJzQ== dependencies: "@textlint/markdown-to-ast" "^12.1.1" @@ -5968,14 +6131,14 @@ doctoc@^2.0.0: doctrine@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" dom-serializer@^1.0.1: version "1.4.1" - resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz" + resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== dependencies: domelementtype "^2.0.1" @@ -5984,31 +6147,31 @@ dom-serializer@^1.0.1: domain-browser@^1.1.1: version "1.2.0" - resolved "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz" + resolved "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== domelementtype@^2.0.1, domelementtype@^2.2.0: version "2.3.0" - resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz" + resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== domexception@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz" + resolved "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== dependencies: webidl-conversions "^5.0.0" domhandler@^4.2.0, domhandler@^4.2.2: version "4.3.1" - resolved "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz" + resolved "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== dependencies: domelementtype "^2.2.0" domutils@^2.8.0: version "2.8.0" - resolved "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz" + resolved "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== dependencies: dom-serializer "^1.0.1" @@ -6017,7 +6180,7 @@ domutils@^2.8.0: dot-case@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz" + resolved "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== dependencies: no-case "^3.0.4" @@ -6025,21 +6188,21 @@ dot-case@^3.0.4: dot-prop@^5.2.0: version "5.3.0" - resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz" + resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== dependencies: is-obj "^2.0.0" dotignore@^0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz" + resolved "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== dependencies: minimatch "^3.0.4" duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" - resolved "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz" + resolved "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== dependencies: end-of-stream "^1.0.0" @@ -6049,12 +6212,12 @@ duplexify@^3.4.2, duplexify@^3.6.0: editions@^1.1.1: version "1.3.4" - resolved "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz" + resolved "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== editions@^2.2.0: version "2.3.1" - resolved "https://registry.npmjs.org/editions/-/editions-2.3.1.tgz" + resolved "https://registry.npmjs.org/editions/-/editions-2.3.1.tgz#3bc9962f1978e801312fbd0aebfed63b49bfe698" integrity sha512-ptGvkwTvGdGfC0hfhKg0MT+TRLRKGtUiWGBInxOm5pz7ssADezahjCUaYuZ8Dr+C05FW0AECIIPt4WBxVINEhA== dependencies: errlop "^2.0.0" @@ -6062,18 +6225,18 @@ editions@^2.2.0: ee-first@1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.3.47, electron-to-chromium@^1.4.284: - version "1.4.328" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.328.tgz" - integrity sha512-DE9tTy2PNmy1v55AZAO542ui+MLC2cvINMK4P2LXGsJdput/ThVG9t+QGecPuAZZSgC8XoI+Jh9M1OG9IoNSCw== +electron-to-chromium@^1.3.47, electron-to-chromium@^1.4.796: + version "1.4.818" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.818.tgz#7762c8bfd15a07c3833b7f5deed990e9e5a4c24f" + integrity sha512-eGvIk2V0dGImV9gWLq8fDfTTsCAeMDwZqEPMr+jMInxZdnp9Us8UpovYpRCf9NQ7VOFgrN2doNSgvISbsbNpxA== -elliptic@^6.5.3: - version "6.5.4" - resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== +elliptic@^6.5.3, elliptic@^6.5.5: + version "6.5.5" + resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.5.tgz#c715e09f78b6923977610d4c2346d6ce22e6dded" + integrity sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw== dependencies: bn.js "^4.11.9" brorand "^1.1.0" @@ -6085,7 +6248,7 @@ elliptic@^6.5.3: ember-a11y-refocus@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/ember-a11y-refocus/-/ember-a11y-refocus-3.0.2.tgz" + resolved "https://registry.npmjs.org/ember-a11y-refocus/-/ember-a11y-refocus-3.0.2.tgz#e648c491d3a8d84cb594679bafc8430cd22b2ed4" integrity sha512-5T9kAvl0RUBF6SSeaaWpVS2WC8MTktgqiGdLAbxVjT2f2NGrDDPmv7riDVNMsuL5sHRwSKm0EHCIzZ4M3aFMow== dependencies: ember-cli-babel "^7.26.11" @@ -6093,14 +6256,14 @@ ember-a11y-refocus@^3.0.2: ember-array-fns@^1.4.0: version "1.4.2" - resolved "https://registry.npmjs.org/ember-array-fns/-/ember-array-fns-1.4.2.tgz" + resolved "https://registry.npmjs.org/ember-array-fns/-/ember-array-fns-1.4.2.tgz#7087cbedcde195dcae25576832920499171b1749" integrity sha512-ceUebR8CeU/dOSLwyXIAfLsxvve8FTD9O8m8XQqdCpY1mUh43dAz5INaF/PGPA+Rkbxrq67Cidvr5AewjwQlPg== dependencies: ember-cli-babel "^7.7.3" ember-assign-helper@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/ember-assign-helper/-/ember-assign-helper-0.3.0.tgz" + resolved "https://registry.npmjs.org/ember-assign-helper/-/ember-assign-helper-0.3.0.tgz#7a023dd165ef56b28f77f70fd20e88261380aca7" integrity sha512-kDY0IRP6PUSJjghM2gIq24OD7d6XcZ1666zmZrywxEVjCenhaR0Oi/BXUU8JEATrIcXIExMIu34GKrHHlCLw0Q== dependencies: ember-cli-babel "^7.19.0" @@ -6108,7 +6271,7 @@ ember-assign-helper@^0.3.0: ember-auto-import@^1.10.1, ember-auto-import@^1.11.3, ember-auto-import@^1.5.3: version "1.12.2" - resolved "https://registry.npmjs.org/ember-auto-import/-/ember-auto-import-1.12.2.tgz" + resolved "https://registry.npmjs.org/ember-auto-import/-/ember-auto-import-1.12.2.tgz#cc7298ee5c0654b0249267de68fb27a2861c3579" integrity sha512-gLqML2k77AuUiXxWNon1FSzuG1DV7PEPpCLCU5aJvf6fdL6rmFfElsZRh+8ELEB/qP9dT+LHjNEunVzd2dYc8A== dependencies: "@babel/core" "^7.1.6" @@ -6141,50 +6304,16 @@ ember-auto-import@^1.10.1, ember-auto-import@^1.11.3, ember-auto-import@^1.5.3: walk-sync "^0.3.3" webpack "^4.43.0" -ember-auto-import@^2.2.3, ember-auto-import@^2.4.2, ember-auto-import@^2.5.0: - version "2.6.1" - resolved "https://registry.npmjs.org/ember-auto-import/-/ember-auto-import-2.6.1.tgz" - integrity sha512-3bCRi/pXp4QslmuCXGlSz9xwR7DF5oDx3zZO5OXKzNZihtkqAM1xvGuRIdQSl46pvbAXOkp8Odl5fOen1i0dRw== - dependencies: - "@babel/core" "^7.16.7" - "@babel/plugin-proposal-class-properties" "^7.16.7" - "@babel/plugin-proposal-decorators" "^7.16.7" - "@babel/preset-env" "^7.16.7" - "@embroider/macros" "^1.0.0" - "@embroider/shared-internals" "^2.0.0" - babel-loader "^8.0.6" - babel-plugin-ember-modules-api-polyfill "^3.5.0" - babel-plugin-htmlbars-inline-precompile "^5.2.1" - babel-plugin-syntax-dynamic-import "^6.18.0" - broccoli-debug "^0.6.4" - broccoli-funnel "^3.0.8" - broccoli-merge-trees "^4.2.0" - broccoli-plugin "^4.0.0" - broccoli-source "^3.0.0" - css-loader "^5.2.0" - debug "^4.3.1" - fs-extra "^10.0.0" - fs-tree-diff "^2.0.0" - handlebars "^4.3.1" - js-string-escape "^1.0.1" - lodash "^4.17.19" - mini-css-extract-plugin "^2.5.2" - parse5 "^6.0.1" - resolve "^1.20.0" - resolve-package-path "^4.0.3" - semver "^7.3.4" - style-loader "^2.0.0" - typescript-memoize "^1.0.0-alpha.3" - walk-sync "^3.0.0" - -ember-auto-import@^2.6.3: - version "2.6.3" - resolved "https://registry.npmjs.org/ember-auto-import/-/ember-auto-import-2.6.3.tgz" - integrity sha512-uLhrRDJYWCRvQ4JQ1e64XlSrqAKSd6PXaJ9ZsZI6Tlms9T4DtQFxNXasqji2ZRJBVrxEoLCRYX3RTldsQ0vNGQ== +ember-auto-import@^2.2.3, ember-auto-import@^2.4.2, ember-auto-import@^2.5.0, ember-auto-import@^2.6.3: + version "2.7.4" + resolved "https://registry.npmjs.org/ember-auto-import/-/ember-auto-import-2.7.4.tgz#ca99570eb3d6165968df797a4750aa58073852b5" + integrity sha512-6CdXSegJJc8nwwK7+1lIcBUnMVrJRNd4ZdMgcKbCAwPvcGxMgRVBddSzrX/+q/UuflvTEO26Dk1g7Z6KHMXUhw== dependencies: "@babel/core" "^7.16.7" "@babel/plugin-proposal-class-properties" "^7.16.7" "@babel/plugin-proposal-decorators" "^7.16.7" + "@babel/plugin-proposal-private-methods" "^7.16.7" + "@babel/plugin-transform-class-static-block" "^7.16.7" "@babel/preset-env" "^7.16.7" "@embroider/macros" "^1.0.0" "@embroider/shared-internals" "^2.0.0" @@ -6206,6 +6335,7 @@ ember-auto-import@^2.6.3: js-string-escape "^1.0.1" lodash "^4.17.19" mini-css-extract-plugin "^2.5.2" + minimatch "^3.0.0" parse5 "^6.0.1" resolve "^1.20.0" resolve-package-path "^4.0.3" @@ -6216,7 +6346,7 @@ ember-auto-import@^2.6.3: ember-basic-dropdown@3.0.21, ember-basic-dropdown@^3.0.21: version "3.0.21" - resolved "https://registry.yarnpkg.com/ember-basic-dropdown/-/ember-basic-dropdown-3.0.21.tgz#5711d071966919c9578d2d5ac2c6dcadbb5ea0e0" + resolved "https://registry.npmjs.org/ember-basic-dropdown/-/ember-basic-dropdown-3.0.21.tgz#5711d071966919c9578d2d5ac2c6dcadbb5ea0e0" integrity sha512-Wu9hJWyqorKo+ZT2PMSIO1BxAeAdaiIC2IjSic0+HcKjmMU47botvG0xbxlprimOWaS9vM+nHat6Pt3xPvcB0A== dependencies: "@ember/render-modifiers" "^2.0.0" @@ -6234,7 +6364,7 @@ ember-basic-dropdown@3.0.21, ember-basic-dropdown@^3.0.21: ember-cache-primitive-polyfill@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/ember-cache-primitive-polyfill/-/ember-cache-primitive-polyfill-1.0.1.tgz" + resolved "https://registry.npmjs.org/ember-cache-primitive-polyfill/-/ember-cache-primitive-polyfill-1.0.1.tgz#a27075443bd87e5af286c1cd8a7df24e3b9f6715" integrity sha512-hSPcvIKarA8wad2/b6jDd/eU+OtKmi6uP+iYQbzi5TQpjsqV6b4QdRqrLk7ClSRRKBAtdTuutx+m+X+WlEd2lw== dependencies: ember-cli-babel "^7.22.1" @@ -6244,7 +6374,7 @@ ember-cache-primitive-polyfill@^1.0.1: ember-cached-decorator-polyfill@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/ember-cached-decorator-polyfill/-/ember-cached-decorator-polyfill-0.1.4.tgz" + resolved "https://registry.npmjs.org/ember-cached-decorator-polyfill/-/ember-cached-decorator-polyfill-0.1.4.tgz#f1e2c65cc78d0d9c4ac0e047e643af477eb85ace" integrity sha512-JOK7kBCWsTVCzmCefK4nr9BACDJk0owt9oIUaVt6Q0UtQ4XeAHmoK5kQ/YtDcxQF1ZevHQFdGhsTR3JLaHNJgA== dependencies: "@glimmer/tracking" "^1.0.4" @@ -6254,7 +6384,7 @@ ember-cached-decorator-polyfill@^0.1.4: ember-can@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/ember-can/-/ember-can-4.2.0.tgz" + resolved "https://registry.npmjs.org/ember-can/-/ember-can-4.2.0.tgz#08bfec3b2b57aad3dc6e4dc36fe9692bd1794dab" integrity sha512-hiaWZspmI4zWeWmmFWgyw1+yEStSo6edGRHHUXCUPR+vBoqlT/hEfmndlfDGso2GFP8IV59DORMVY0KReMcO+w== dependencies: ember-cli-babel "^7.26.6" @@ -6263,7 +6393,7 @@ ember-can@^4.2.0: ember-changeset-validations@~3.15.2: version "3.15.2" - resolved "https://registry.npmjs.org/ember-changeset-validations/-/ember-changeset-validations-3.15.2.tgz" + resolved "https://registry.npmjs.org/ember-changeset-validations/-/ember-changeset-validations-3.15.2.tgz#c19a65661446c64088fd5daf4f95f0819ccc95af" integrity sha512-jPcX4aXRY9SLivHHRkrUZovL1xeEchAyoDR7lyOpverfjVJFr3p0qEp4L8pwKBeCQHnV0JcLM9r1DqpRoGLmkw== dependencies: ember-changeset "^3.14.1" @@ -6275,7 +6405,7 @@ ember-changeset-validations@~3.15.2: ember-changeset@^3.14.1: version "3.15.0" - resolved "https://registry.npmjs.org/ember-changeset/-/ember-changeset-3.15.0.tgz" + resolved "https://registry.npmjs.org/ember-changeset/-/ember-changeset-3.15.0.tgz#402bbb9b51dc44596415c1c7b0e3a4923b1d3e81" integrity sha512-yLyU3quV96EFjYzYUjIK4je5nnemZdbElYLFnXYJ5StXquCRjdFvL79gst/vs6ZjVFbkRKnLjsVP8YMkED0P2g== dependencies: "@embroider/macros" "^0.42.3" @@ -6286,7 +6416,7 @@ ember-changeset@^3.14.1: ember-cli-app-version@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/ember-cli-app-version/-/ember-cli-app-version-5.0.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-app-version/-/ember-cli-app-version-5.0.0.tgz#adad17c6f706f419b223707eec66dd1cd28530c3" integrity sha512-afhx/CXDOMNXzoe4NDPy5WUfxWmYYHUzMCiTyvPBxCDBXYcMrtxNWxvgaSaeqcoHVEmqzeyBj8V82tzmT1dcyw== dependencies: ember-cli-babel "^7.23.1" @@ -6294,12 +6424,12 @@ ember-cli-app-version@^5.0.0: ember-cli-babel-plugin-helpers@^1.0.0, ember-cli-babel-plugin-helpers@^1.1.0, ember-cli-babel-plugin-helpers@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/ember-cli-babel-plugin-helpers/-/ember-cli-babel-plugin-helpers-1.1.1.tgz" + resolved "https://registry.npmjs.org/ember-cli-babel-plugin-helpers/-/ember-cli-babel-plugin-helpers-1.1.1.tgz#5016b80cdef37036c4282eef2d863e1d73576879" integrity sha512-sKvOiPNHr5F/60NLd7SFzMpYPte/nnGkq/tMIfXejfKHIhaiIkYFqX8Z9UFTKWLLn+V7NOaby6niNPZUdvKCRw== ember-cli-babel@^6.0.0, ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.6.0, ember-cli-babel@^6.8.1, ember-cli-babel@^6.8.2: version "6.18.0" - resolved "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-6.18.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-6.18.0.tgz#3f6435fd275172edeff2b634ee7b29ce74318957" integrity sha512-7ceC8joNYxY2wES16iIBlbPSxwKDBhYwC8drU3ZEvuPDMwVv1KzxCNu1fvxyFEBWhwaRNTUxSCsEVoTd9nosGA== dependencies: amd-name-resolver "1.2.0" @@ -6316,9 +6446,9 @@ ember-cli-babel@^6.0.0, ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.6.0, e ember-cli-version-checker "^2.1.2" semver "^5.5.0" -ember-cli-babel@^7.0.0, ember-cli-babel@^7.1.3, ember-cli-babel@^7.10.0, ember-cli-babel@^7.12.0, ember-cli-babel@^7.13.0, ember-cli-babel@^7.13.2, ember-cli-babel@^7.17.2, ember-cli-babel@^7.18.0, ember-cli-babel@^7.19.0, ember-cli-babel@^7.20.0, ember-cli-babel@^7.21.0, ember-cli-babel@^7.22.1, ember-cli-babel@^7.23.0, ember-cli-babel@^7.23.1, ember-cli-babel@^7.26.0, ember-cli-babel@^7.26.1, ember-cli-babel@^7.26.10, ember-cli-babel@^7.26.11, ember-cli-babel@^7.26.3, ember-cli-babel@^7.26.4, ember-cli-babel@^7.26.5, ember-cli-babel@^7.26.6, ember-cli-babel@^7.7.3: +ember-cli-babel@^7.0.0, ember-cli-babel@^7.1.3, ember-cli-babel@^7.10.0, ember-cli-babel@^7.12.0, ember-cli-babel@^7.13.0, ember-cli-babel@^7.17.2, ember-cli-babel@^7.18.0, ember-cli-babel@^7.19.0, ember-cli-babel@^7.20.0, ember-cli-babel@^7.21.0, ember-cli-babel@^7.22.1, ember-cli-babel@^7.23.0, ember-cli-babel@^7.23.1, ember-cli-babel@^7.26.0, ember-cli-babel@^7.26.1, ember-cli-babel@^7.26.10, ember-cli-babel@^7.26.11, ember-cli-babel@^7.26.3, ember-cli-babel@^7.26.4, ember-cli-babel@^7.26.5, ember-cli-babel@^7.26.6, ember-cli-babel@^7.7.3: version "7.26.11" - resolved "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-7.26.11.tgz" + resolved "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-7.26.11.tgz#50da0fe4dcd99aada499843940fec75076249a9f" integrity sha512-JJYeYjiz/JTn34q7F5DSOjkkZqy8qwFOOxXfE6pe9yEJqWGu4qErKxlz8I22JoVEQ/aBUO+OcKTpmctvykM9YA== dependencies: "@babel/core" "^7.12.0" @@ -6337,24 +6467,57 @@ ember-cli-babel@^7.0.0, ember-cli-babel@^7.1.3, ember-cli-babel@^7.10.0, ember-c babel-plugin-debug-macros "^0.3.4" babel-plugin-ember-data-packages-polyfill "^0.1.2" babel-plugin-ember-modules-api-polyfill "^3.5.0" - babel-plugin-module-resolver "^3.2.0" - broccoli-babel-transpiler "^7.8.0" + babel-plugin-module-resolver "^3.2.0" + broccoli-babel-transpiler "^7.8.0" + broccoli-debug "^0.6.4" + broccoli-funnel "^2.0.2" + broccoli-source "^2.1.2" + calculate-cache-key-for-tree "^2.0.0" + clone "^2.1.2" + ember-cli-babel-plugin-helpers "^1.1.1" + ember-cli-version-checker "^4.1.0" + ensure-posix-path "^1.0.2" + fixturify-project "^1.10.0" + resolve-package-path "^3.1.0" + rimraf "^3.0.1" + semver "^5.5.0" + +ember-cli-babel@^8.2.0: + version "8.2.0" + resolved "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-8.2.0.tgz#91e14c22ac22956177002385947724174553d41c" + integrity sha512-8H4+jQElCDo6tA7CamksE66NqBXWs7VNpS3a738L9pZCjg2kXIX4zoyHzkORUqCtr0Au7YsCnrlAMi1v2ALo7A== + dependencies: + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/plugin-proposal-class-properties" "^7.16.5" + "@babel/plugin-proposal-decorators" "^7.20.13" + "@babel/plugin-proposal-private-methods" "^7.16.5" + "@babel/plugin-proposal-private-property-in-object" "^7.20.5" + "@babel/plugin-transform-class-static-block" "^7.22.11" + "@babel/plugin-transform-modules-amd" "^7.20.11" + "@babel/plugin-transform-runtime" "^7.13.9" + "@babel/plugin-transform-typescript" "^7.20.13" + "@babel/preset-env" "^7.20.2" + "@babel/runtime" "7.12.18" + amd-name-resolver "^1.3.1" + babel-plugin-debug-macros "^0.3.4" + babel-plugin-ember-data-packages-polyfill "^0.1.2" + babel-plugin-ember-modules-api-polyfill "^3.5.0" + babel-plugin-module-resolver "^5.0.0" + broccoli-babel-transpiler "^8.0.0" broccoli-debug "^0.6.4" - broccoli-funnel "^2.0.2" - broccoli-source "^2.1.2" + broccoli-funnel "^3.0.8" + broccoli-source "^3.0.1" calculate-cache-key-for-tree "^2.0.0" clone "^2.1.2" ember-cli-babel-plugin-helpers "^1.1.1" - ember-cli-version-checker "^4.1.0" + ember-cli-version-checker "^5.1.2" ensure-posix-path "^1.0.2" - fixturify-project "^1.10.0" - resolve-package-path "^3.1.0" - rimraf "^3.0.1" - semver "^5.5.0" + resolve-package-path "^4.0.3" + semver "^7.3.8" ember-cli-code-coverage@^1.0.0-beta.4: version "1.0.3" - resolved "https://registry.npmjs.org/ember-cli-code-coverage/-/ember-cli-code-coverage-1.0.3.tgz" + resolved "https://registry.npmjs.org/ember-cli-code-coverage/-/ember-cli-code-coverage-1.0.3.tgz#9a6e5e6350d70761eba749d68ebe2e0d9aa3492f" integrity sha512-tyWeQ22vxpDmfhIrRCMqZPq9Coppefg19hBgME4yb9Na2qslxCNK0USThigZhesb7hfw2ZgdrKJCrmCVNwkq7g== dependencies: babel-plugin-istanbul "^6.0.0" @@ -6368,29 +6531,29 @@ ember-cli-code-coverage@^1.0.0-beta.4: walk-sync "^2.1.0" ember-cli-dependency-checker@^3.2.0: - version "3.3.1" - resolved "https://registry.npmjs.org/ember-cli-dependency-checker/-/ember-cli-dependency-checker-3.3.1.tgz" - integrity sha512-Tg6OeijjXNKWkDm6057Tr0N9j9Vlz/ITewXWpn1A/+Wbt3EowBx5ZKfvoupqz05EznKgL1B/ecG0t+JN7Qm6MA== + version "3.3.2" + resolved "https://registry.npmjs.org/ember-cli-dependency-checker/-/ember-cli-dependency-checker-3.3.2.tgz#94ed7e8e3d47e494082eb9ccfaa489d603ab6017" + integrity sha512-PwkrW5oYsdPWwt+0Tojufmv/hxVETTjkrEdK7ANQB2VSnqpA5UcYubwpQM9ONuR2J8wyNDMwEHlqIrk/FYtBsQ== dependencies: - chalk "^2.3.0" - find-yarn-workspace-root "^1.1.0" + chalk "^2.4.2" + find-yarn-workspace-root "^1.2.1" is-git-url "^1.0.0" - resolve "^1.5.0" - semver "^5.3.0" + resolve "^1.22.0" + semver "^5.7.1" ember-cli-deprecation-workflow@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/ember-cli-deprecation-workflow/-/ember-cli-deprecation-workflow-2.1.0.tgz" - integrity sha512-Ay9P9iKMJdY4Gq5XPowh3HqqeAzLfwBRj1oB1ZKkDW1fryZQWBN4pZuRnjnB+3VWZjBnZif5e7Pacc7YNW9hWg== + version "2.2.0" + resolved "https://registry.npmjs.org/ember-cli-deprecation-workflow/-/ember-cli-deprecation-workflow-2.2.0.tgz#277d56bdafc15dbdb7a58dee598402cdf50e0d08" + integrity sha512-23bXZqZJBJSKBTfT0LK7qzSJX861TgafL6RVdMfn/iubpLnoZIWergYwEdgs24CNTUbuehVbHy2Q71o8jYfwfw== dependencies: + "@ember/string" "^3.0.0" broccoli-funnel "^3.0.3" broccoli-merge-trees "^4.2.0" broccoli-plugin "^4.0.5" - ember-cli-htmlbars "^5.3.2" ember-cli-flash@^2.1.1: version "2.2.2" - resolved "https://registry.npmjs.org/ember-cli-flash/-/ember-cli-flash-2.2.2.tgz" + resolved "https://registry.npmjs.org/ember-cli-flash/-/ember-cli-flash-2.2.2.tgz#19b47f7704cac91a21a790be220eb021ac37c80d" integrity sha512-cHjChy9jYtXiprHwAZCVh8FbsfxBvvqKmz+XlAX6kqf/9uBdrxHzGR0jE0PR8aabX9tWAmjdR0hpT2IbbAwwAg== dependencies: "@ember/render-modifiers" "^1.0.2" @@ -6399,12 +6562,12 @@ ember-cli-flash@^2.1.1: ember-cli-get-component-path-option@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/ember-cli-get-component-path-option/-/ember-cli-get-component-path-option-1.0.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-get-component-path-option/-/ember-cli-get-component-path-option-1.0.0.tgz#0d7b595559e2f9050abed804f1d8eff1b08bc771" integrity sha512-k47TDwcJ2zPideBCZE8sCiShSxQSpebY2BHcX2DdipMmBox5gsfyVrbKJWIHeSTTKyEUgmBIvQkqTOozEziCZA== ember-cli-htmlbars@^3.0.1: version "3.1.0" - resolved "https://registry.npmjs.org/ember-cli-htmlbars/-/ember-cli-htmlbars-3.1.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-htmlbars/-/ember-cli-htmlbars-3.1.0.tgz#87806c2a0bca2ab52d4fb8af8e2215c1ca718a99" integrity sha512-cgvRJM73IT0aePUG7oQ/afB7vSRBV3N0wu9BrWhHX2zkR7A7cUBI7KC9VPk6tbctCXoM7BRGsCC4aIjF7yrfXA== dependencies: broccoli-persistent-filter "^2.3.1" @@ -6414,7 +6577,7 @@ ember-cli-htmlbars@^3.0.1: ember-cli-htmlbars@^4.3.1: version "4.5.0" - resolved "https://registry.npmjs.org/ember-cli-htmlbars/-/ember-cli-htmlbars-4.5.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-htmlbars/-/ember-cli-htmlbars-4.5.0.tgz#d299e4f7eba6f30dc723ee086906cc550beb252e" integrity sha512-bYJpK1pqFu9AadDAGTw05g2LMNzY8xTCIqQm7dMJmKEoUpLRFbPf4SfHXrktzDh7Q5iggl6Skzf1M0bPlIxARw== dependencies: "@ember/edition-utils" "^1.2.0" @@ -6432,9 +6595,9 @@ ember-cli-htmlbars@^4.3.1: strip-bom "^4.0.0" walk-sync "^2.0.2" -ember-cli-htmlbars@^5.0.0, ember-cli-htmlbars@^5.1.0, ember-cli-htmlbars@^5.1.2, ember-cli-htmlbars@^5.3.1, ember-cli-htmlbars@^5.3.2, ember-cli-htmlbars@^5.7.1, ember-cli-htmlbars@^5.7.2: +ember-cli-htmlbars@^5.0.0, ember-cli-htmlbars@^5.1.0, ember-cli-htmlbars@^5.1.2, ember-cli-htmlbars@^5.3.1, ember-cli-htmlbars@^5.7.1, ember-cli-htmlbars@^5.7.2: version "5.7.2" - resolved "https://registry.npmjs.org/ember-cli-htmlbars/-/ember-cli-htmlbars-5.7.2.tgz" + resolved "https://registry.npmjs.org/ember-cli-htmlbars/-/ember-cli-htmlbars-5.7.2.tgz#e0cd2fb3c20d85fe4c3e228e6f0590ee1c645ba8" integrity sha512-Uj6R+3TtBV5RZoJY14oZn/sNPnc+UgmC8nb5rI4P3fR/gYoyTFIZSXiIM7zl++IpMoIrocxOrgt+mhonKphgGg== dependencies: "@ember/edition-utils" "^1.2.0" @@ -6454,10 +6617,10 @@ ember-cli-htmlbars@^5.0.0, ember-cli-htmlbars@^5.1.0, ember-cli-htmlbars@^5.1.2, strip-bom "^4.0.0" walk-sync "^2.2.0" -ember-cli-htmlbars@^6.0.0, ember-cli-htmlbars@^6.0.1, ember-cli-htmlbars@^6.1.1, ember-cli-htmlbars@^6.2.0: - version "6.2.0" - resolved "https://registry.npmjs.org/ember-cli-htmlbars/-/ember-cli-htmlbars-6.2.0.tgz" - integrity sha512-j5EGixjGau23HrqRiW/JjoAovg5UBHfjbyN7wX5ekE90knIEqUUj1z/Mo/cTx/J2VepQ2lE6HdXW9LWQ/WdMtw== +ember-cli-htmlbars@^6.0.0, ember-cli-htmlbars@^6.0.1, ember-cli-htmlbars@^6.1.1, ember-cli-htmlbars@^6.3.0: + version "6.3.0" + resolved "https://registry.npmjs.org/ember-cli-htmlbars/-/ember-cli-htmlbars-6.3.0.tgz#ac85f2bbd09788992ab7f9ca832cd044fb8e5798" + integrity sha512-N9Y80oZfcfWLsqickMfRd9YByVcTGyhYRnYQ2XVPVrp6jyUyOeRWmEAPh7ERSXpp8Ws4hr/JB9QVQrn/yZa+Ag== dependencies: "@ember/edition-utils" "^1.2.0" babel-plugin-ember-template-compilation "^2.0.0" @@ -6476,7 +6639,7 @@ ember-cli-htmlbars@^6.0.0, ember-cli-htmlbars@^6.0.1, ember-cli-htmlbars@^6.1.1, ember-cli-inject-live-reload@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/ember-cli-inject-live-reload/-/ember-cli-inject-live-reload-2.1.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-inject-live-reload/-/ember-cli-inject-live-reload-2.1.0.tgz#ef63c733c133024d5726405a3c247fa12e88a385" integrity sha512-YV5wYRD5PJHmxaxaJt18u6LE6Y+wo455BnmcpN+hGNlChy2piM9/GMvYgTAz/8Vin8RJ5KekqP/w/NEaRndc/A== dependencies: clean-base-url "^1.0.0" @@ -6484,17 +6647,17 @@ ember-cli-inject-live-reload@^2.1.0: ember-cli-is-package-missing@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/ember-cli-is-package-missing/-/ember-cli-is-package-missing-1.0.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-is-package-missing/-/ember-cli-is-package-missing-1.0.0.tgz#6e6184cafb92635dd93ca6c946b104292d4e3390" integrity sha512-9hEoZj6Au5onlSDdcoBqYEPT8ehlYntZPxH8pBKV0GO7LNel88otSAQsCfXvbi2eKE+MaSeLG/gNaCI5UdWm9g== ember-cli-lodash-subset@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/ember-cli-lodash-subset/-/ember-cli-lodash-subset-2.0.1.tgz" + resolved "https://registry.npmjs.org/ember-cli-lodash-subset/-/ember-cli-lodash-subset-2.0.1.tgz#20cb68a790fe0fde2488ddfd8efbb7df6fe766f2" integrity sha512-QkLGcYv1WRK35g4MWu/uIeJ5Suk2eJXKtZ+8s+qE7C9INmpCPyPxzaqZABquYzcWNzIdw6kYwz3NWAFdKYFxwg== ember-cli-node-assets@^0.2.2: version "0.2.2" - resolved "https://registry.npmjs.org/ember-cli-node-assets/-/ember-cli-node-assets-0.2.2.tgz" + resolved "https://registry.npmjs.org/ember-cli-node-assets/-/ember-cli-node-assets-0.2.2.tgz#d2d55626e7cc6619f882d7fe55751f9266022708" integrity sha512-pFyjlhzwx2FxAmkxSVJvP+i+MwHDhmgsmma1ZQbFLYwBeufo1GIzqSJUfStcpOE1NDg8fXm2yZVVzdZYf9lW2w== dependencies: broccoli-funnel "^1.0.1" @@ -6506,14 +6669,14 @@ ember-cli-node-assets@^0.2.2: ember-cli-normalize-entity-name@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/ember-cli-normalize-entity-name/-/ember-cli-normalize-entity-name-1.0.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-normalize-entity-name/-/ember-cli-normalize-entity-name-1.0.0.tgz#0b14f7bcbc599aa117b5fddc81e4fd03c4bad5b7" integrity sha512-rF4P1rW2P1gVX1ynZYPmuIf7TnAFDiJmIUFI1Xz16VYykUAyiOCme0Y22LeZq8rTzwBMiwBwoE3RO4GYWehXZA== dependencies: silent-error "^1.0.0" ember-cli-page-object@^1.17.11: version "1.17.12" - resolved "https://registry.npmjs.org/ember-cli-page-object/-/ember-cli-page-object-1.17.12.tgz" + resolved "https://registry.npmjs.org/ember-cli-page-object/-/ember-cli-page-object-1.17.12.tgz#bb5e3b01e81798cbea064d218bbff8cd52e4229b" integrity sha512-G5HCIp8Fp2ywrlBoaxdKNsAsJClnLyG+6Xg7liygnJxYpjc2e9BNcCXShxVsfkG3thlEFhNRWm5TY2TXNguOVA== dependencies: broccoli-file-creator "^2.1.1" @@ -6527,12 +6690,12 @@ ember-cli-page-object@^1.17.11: ember-cli-path-utils@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/ember-cli-path-utils/-/ember-cli-path-utils-1.0.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-path-utils/-/ember-cli-path-utils-1.0.0.tgz#4e39af8b55301cddc5017739b77a804fba2071ed" integrity sha512-Qq0vvquzf4cFHoDZavzkOy3Izc893r/5spspWgyzLCPTaG78fM3HsrjZm7UWEltbXUqwHHYrqZd/R0jS08NqSA== ember-cli-postcss@^8.1.0: version "8.2.0" - resolved "https://registry.npmjs.org/ember-cli-postcss/-/ember-cli-postcss-8.2.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-postcss/-/ember-cli-postcss-8.2.0.tgz#9cc1fee624d2d13c41633cf32d4e8cb8d5f88eff" integrity sha512-S2HQqmNtcezmLSt/OPZKCXg+aRV7yFoZp+tn1HCLSbR/eU95xl7MWxTjbj/wOIGMfhggy/hBT2+STDh8mGuVpw== dependencies: broccoli-merge-trees "^4.2.0" @@ -6543,7 +6706,7 @@ ember-cli-postcss@^8.1.0: ember-cli-preprocess-registry@^3.3.0: version "3.3.0" - resolved "https://registry.npmjs.org/ember-cli-preprocess-registry/-/ember-cli-preprocess-registry-3.3.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-preprocess-registry/-/ember-cli-preprocess-registry-3.3.0.tgz#685837a314fbe57224bd54b189f4b9c23907a2de" integrity sha512-60GYpw7VPeB7TvzTLZTuLTlHdOXvayxjAQ+IxM2T04Xkfyu75O2ItbWlftQW7NZVGkaCsXSRAmn22PG03VpLMA== dependencies: broccoli-clean-css "^1.1.0" @@ -6551,10 +6714,10 @@ ember-cli-preprocess-registry@^3.3.0: debug "^3.0.1" process-relative-require "^1.0.0" -ember-cli-sass@^10.0.1: - version "10.0.1" - resolved "https://registry.npmjs.org/ember-cli-sass/-/ember-cli-sass-10.0.1.tgz" - integrity sha512-dWVoX03O2Mot1dEB1AN3ofC8DDZb6iU4Kfkbr3WYi9S9bGVHrpR/ngsR7tuVBuTugTyG53FPtLLqYdqx7XjXdA== +ember-cli-sass@^11.0.1: + version "11.0.1" + resolved "https://registry.npmjs.org/ember-cli-sass/-/ember-cli-sass-11.0.1.tgz#dc565764213a76973a83c0db9583cb79ba187dc5" + integrity sha512-RMlFPMK4kaB+67seF/IIoY3EC4rRd+L58q+lyElrxB3FcQTgph/qmGwtqf9Up7m3SDbPiA7cccCOSmgReMgCXA== dependencies: broccoli-funnel "^2.0.1" broccoli-merge-trees "^3.0.1" @@ -6563,14 +6726,14 @@ ember-cli-sass@^10.0.1: ember-cli-sri@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/ember-cli-sri/-/ember-cli-sri-2.1.1.tgz" + resolved "https://registry.npmjs.org/ember-cli-sri/-/ember-cli-sri-2.1.1.tgz#971620934a4b9183cf7923cc03e178b83aa907fd" integrity sha512-YG/lojDxkur9Bnskt7xB6gUOtJ6aPl/+JyGYm9HNDk3GECVHB3SMN3rlGhDKHa1ndS5NK2W2TSLb9bzRbGlMdg== dependencies: broccoli-sri-hash "^2.1.0" ember-cli-string-helpers@^6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/ember-cli-string-helpers/-/ember-cli-string-helpers-6.1.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-string-helpers/-/ember-cli-string-helpers-6.1.0.tgz#aeb96112bb91c540b869ed8b9c680f7fd5859cb6" integrity sha512-Lw8B6MJx2n8CNF2TSIKs+hWLw0FqSYjr2/NRPyquyYA05qsl137WJSYW3ZqTsLgoinHat0DGF2qaCXocLhLmyA== dependencies: "@babel/core" "^7.13.10" @@ -6580,12 +6743,12 @@ ember-cli-string-helpers@^6.1.0: ember-cli-string-utils@^1.0.0, ember-cli-string-utils@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/ember-cli-string-utils/-/ember-cli-string-utils-1.1.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-string-utils/-/ember-cli-string-utils-1.1.0.tgz#39b677fc2805f55173735376fcef278eaa4452a1" integrity sha512-PlJt4fUDyBrC/0X+4cOpaGCiMawaaB//qD85AXmDRikxhxVzfVdpuoec02HSiTGTTB85qCIzWBIh8lDOiMyyFg== ember-cli-template-lint@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/ember-cli-template-lint/-/ember-cli-template-lint-2.0.2.tgz" + resolved "https://registry.npmjs.org/ember-cli-template-lint/-/ember-cli-template-lint-2.0.2.tgz#729436e71f45e31a9237bab4bbc9a9ef67401c24" integrity sha512-q/aXIYC9cxWRT3B+VX/45EPzYni5OuctxR9ePhZA1//bjaZtwcnKQtwYk7H4oEDrIKce5KMb0CMco2gvGYmAjA== dependencies: aot-test-generators "^0.1.0" @@ -6602,28 +6765,28 @@ ember-cli-template-lint@^2.0.1: ember-cli-terser@^4.0.2: version "4.0.2" - resolved "https://registry.npmjs.org/ember-cli-terser/-/ember-cli-terser-4.0.2.tgz" + resolved "https://registry.npmjs.org/ember-cli-terser/-/ember-cli-terser-4.0.2.tgz#c436a9e4159f76a615b051cba0584844652b7dcd" integrity sha512-Ej77K+YhCZImotoi/CU2cfsoZaswoPlGaM5TB3LvjvPDlVPRhxUHO2RsaUVC5lsGeRLRiHCOxVtoJ6GyqexzFA== dependencies: broccoli-terser-sourcemap "^4.1.0" ember-cli-test-info@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/ember-cli-test-info/-/ember-cli-test-info-1.0.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-test-info/-/ember-cli-test-info-1.0.0.tgz#ed4e960f249e97523cf891e4aed2072ce84577b4" integrity sha512-dEVTIpmUfCzweC97NGf6p7L6XKBwV2GmSM4elmzKvkttEp5P7AvGA9uGyN4GqFq+RwhW+2b0I2qlX00w+skm+A== dependencies: ember-cli-string-utils "^1.0.0" ember-cli-test-loader@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/ember-cli-test-loader/-/ember-cli-test-loader-3.0.0.tgz" - integrity sha512-wfFRBrfO9gaKScYcdQxTfklx9yp1lWK6zv1rZRpkas9z2SHyJojF7NOQRWQgSB3ypm7vfpiF8VsFFVVr7VBzAQ== + version "3.1.0" + resolved "https://registry.npmjs.org/ember-cli-test-loader/-/ember-cli-test-loader-3.1.0.tgz#13abd43b7e07e2266a9f0fc5b9dc5455883b18ff" + integrity sha512-0aocZV9SIoOHiU3hrH3IuLR6busWhTX6UVXgd490hmJkIymmOXNH2+jJoC7Ebkeo3PiOfAdjqhb765QDlHSJOw== dependencies: - ember-cli-babel "^7.13.2" + ember-cli-babel "^7.23.0" ember-cli-typescript@3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/ember-cli-typescript/-/ember-cli-typescript-3.0.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-typescript/-/ember-cli-typescript-3.0.0.tgz#3b838d1ce9e4d22a98e68da22ceac6dc0cfd9bfc" integrity sha512-lo5YArbJzJi5ssvaGqTt6+FnhTALnSvYVuxM7lfyL1UCMudyNJ94ovH5C7n5il7ATd6WsNiAPRUO/v+s5Jq/aA== dependencies: "@babel/plugin-transform-typescript" "~7.5.0" @@ -6640,7 +6803,7 @@ ember-cli-typescript@3.0.0: ember-cli-typescript@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/ember-cli-typescript/-/ember-cli-typescript-2.0.2.tgz" + resolved "https://registry.npmjs.org/ember-cli-typescript/-/ember-cli-typescript-2.0.2.tgz#464984131fbdc05655eb61d1c3cdd911d3137f0d" integrity sha512-7I5azCTxOgRDN8aSSnJZIKSqr+MGnT+jLTUbBYqF8wu6ojs2DUnTePxUcQMcvNh3Q3B1ySv7Q/uZFSjdU9gSjA== dependencies: "@babel/plugin-proposal-class-properties" "^7.1.0" @@ -6658,7 +6821,7 @@ ember-cli-typescript@^2.0.2: ember-cli-typescript@^3.1.3, ember-cli-typescript@^3.1.4: version "3.1.4" - resolved "https://registry.npmjs.org/ember-cli-typescript/-/ember-cli-typescript-3.1.4.tgz" + resolved "https://registry.npmjs.org/ember-cli-typescript/-/ember-cli-typescript-3.1.4.tgz#21d6ccd670d1f2e34c9cce68c6e32c442f46806b" integrity sha512-HJ73kL45OGRmIkPhBNFt31I1SGUvdZND+LCH21+qpq3pPlFpJG8GORyXpP+2ze8PbnITNLzwe5AwUrpyuRswdQ== dependencies: "@babel/plugin-proposal-nullish-coalescing-operator" "^7.4.4" @@ -6678,7 +6841,7 @@ ember-cli-typescript@^3.1.3, ember-cli-typescript@^3.1.4: ember-cli-typescript@^4.0.0, ember-cli-typescript@^4.1.0, ember-cli-typescript@^4.2.0, ember-cli-typescript@^4.2.1: version "4.2.1" - resolved "https://registry.npmjs.org/ember-cli-typescript/-/ember-cli-typescript-4.2.1.tgz" + resolved "https://registry.npmjs.org/ember-cli-typescript/-/ember-cli-typescript-4.2.1.tgz#54d08fc90318cc986f3ea562f93ce58a6cc4c24d" integrity sha512-0iKTZ+/wH6UB/VTWKvGuXlmwiE8HSIGcxHamwNhEC5x1mN3z8RfvsFZdQWYUzIWFN2Tek0gmepGRPTwWdBYl/A== dependencies: ansi-to-html "^0.6.15" @@ -6692,10 +6855,10 @@ ember-cli-typescript@^4.0.0, ember-cli-typescript@^4.1.0, ember-cli-typescript@^ stagehand "^1.0.0" walk-sync "^2.2.0" -ember-cli-typescript@^5.0.0, ember-cli-typescript@^5.1.0: - version "5.2.1" - resolved "https://registry.npmjs.org/ember-cli-typescript/-/ember-cli-typescript-5.2.1.tgz" - integrity sha512-qqp5TAIuPHxHiGXJKL+78Euyhy0zSKQMovPh8sJpN/ZBYx0H90pONufHR3anaMcp1snVfx4B+mb9+7ijOik8ZA== +ember-cli-typescript@^5.0.0: + version "5.3.0" + resolved "https://registry.npmjs.org/ember-cli-typescript/-/ember-cli-typescript-5.3.0.tgz#c0f726c61e4309aa9ff49b388219c6729ea986cd" + integrity sha512-gFA+ZwmsvvFwo2Jz/B9GMduEn+fPoGb69qWGP0Tp3+Tu5xypDtIKVSZ5086I3Cr19cLXD4HkrOR3YQvdUKzAkQ== dependencies: ansi-to-html "^0.6.15" broccoli-stew "^3.0.0" @@ -6710,7 +6873,7 @@ ember-cli-typescript@^5.0.0, ember-cli-typescript@^5.1.0: ember-cli-version-checker@^2.1.0, ember-cli-version-checker@^2.1.2: version "2.2.0" - resolved "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-2.2.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-2.2.0.tgz#47771b731fe0962705e27c8199a9e3825709f3b3" integrity sha512-G+KtYIVlSOWGcNaTFHk76xR4GdzDLzAS4uxZUKdASuFX0KJE43C6DaqL+y3VTpUFLI2FIkAS6HZ4I1YBi+S3hg== dependencies: resolve "^1.3.3" @@ -6718,7 +6881,7 @@ ember-cli-version-checker@^2.1.0, ember-cli-version-checker@^2.1.2: ember-cli-version-checker@^3.1.3: version "3.1.3" - resolved "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-3.1.3.tgz" + resolved "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-3.1.3.tgz#7c9b4f5ff30fdebcd480b1c06c4de43bb51c522c" integrity sha512-PZNSvpzwWgv68hcXxyjREpj3WWb81A7rtYNQq1lLEgrWIchF8ApKJjWP3NBpHjaatwILkZAV8klair5WFlXAKg== dependencies: resolve-package-path "^1.2.6" @@ -6726,7 +6889,7 @@ ember-cli-version-checker@^3.1.3: ember-cli-version-checker@^4.1.0: version "4.1.1" - resolved "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-4.1.1.tgz" + resolved "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-4.1.1.tgz#27b938228306cb0dbc4f74e95c536cdd6448e499" integrity sha512-bzEWsTMXUGEJfxcAGWPe6kI7oHEGD3jaxUWDYPTqzqGhNkgPwXTBgoWs9zG1RaSMaOPFnloWuxRcoHi4TrYS3Q== dependencies: resolve-package-path "^2.0.0" @@ -6735,7 +6898,7 @@ ember-cli-version-checker@^4.1.0: ember-cli-version-checker@^5.0.1, ember-cli-version-checker@^5.1.1, ember-cli-version-checker@^5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-5.1.2.tgz" + resolved "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-5.1.2.tgz#649c7b6404902e3b3d69c396e054cea964911ab0" integrity sha512-rk7GY+FmLn/2e22HsZs0Ycrz8HQ1W3Fv+2TFOuEFW9optnDXDgkntPBIl6gact/LHsfBM5RKbM3dHsIIeLgl0Q== dependencies: resolve-package-path "^3.1.0" @@ -6744,7 +6907,7 @@ ember-cli-version-checker@^5.0.1, ember-cli-version-checker@^5.1.1, ember-cli-ve ember-cli-yadda@^0.7.0: version "0.7.0" - resolved "https://registry.npmjs.org/ember-cli-yadda/-/ember-cli-yadda-0.7.0.tgz" + resolved "https://registry.npmjs.org/ember-cli-yadda/-/ember-cli-yadda-0.7.0.tgz#eff5583a886cd752343f74f485a4485ea6e37366" integrity sha512-NdolJAdNEOIHdTR8pbv8I6LUvP6QHAHvIdFSQP1kzqEqdFurFT7E7Vl5XqG45puNDty5FSTptdZkc+zrP9C8HQ== dependencies: broccoli-funnel "^3.0.8" @@ -6757,7 +6920,7 @@ ember-cli-yadda@^0.7.0: ember-cli@3.28.6: version "3.28.6" - resolved "https://registry.npmjs.org/ember-cli/-/ember-cli-3.28.6.tgz" + resolved "https://registry.npmjs.org/ember-cli/-/ember-cli-3.28.6.tgz#477a6a134501639d6cb03da6746158501c41efce" integrity sha512-aGHIDXM5KujhU+tHyfp1X5bUp3yj47sIWI0zgybyIw6vv6ErAu/eKWWMSib5PF8cQDdXG9vttBcXnvQ4QBNIPQ== dependencies: "@babel/core" "^7.13.8" @@ -6854,7 +7017,7 @@ ember-cli@3.28.6: ember-collection@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/ember-collection/-/ember-collection-1.0.0.tgz" + resolved "https://registry.npmjs.org/ember-collection/-/ember-collection-1.0.0.tgz#2ec570a49b70098ab68fbaaca940f9302b39af98" integrity sha512-Yb7ZoPBc9rdDv1m72PDQeqbKzKVejAetkqRWUEXRa6tV75ud46ozGhX/1kyVJz2tNYL5XlgnqP8hg5UA9YNR0w== dependencies: ember-cli-babel "^7.7.3" @@ -6862,9 +7025,9 @@ ember-collection@^1.0.0: layout-bin-packer "^1.4.0" ember-compatibility-helpers@^1.1.2, ember-compatibility-helpers@^1.2.0, ember-compatibility-helpers@^1.2.1, ember-compatibility-helpers@^1.2.4, ember-compatibility-helpers@^1.2.5: - version "1.2.6" - resolved "https://registry.npmjs.org/ember-compatibility-helpers/-/ember-compatibility-helpers-1.2.6.tgz" - integrity sha512-2UBUa5SAuPg8/kRVaiOfTwlXdeVweal1zdNPibwItrhR0IvPrXpaqwJDlEZnWKEoB+h33V0JIfiWleSG6hGkkA== + version "1.2.7" + resolved "https://registry.npmjs.org/ember-compatibility-helpers/-/ember-compatibility-helpers-1.2.7.tgz#b4f138bba844f8f38f0b8f4d7e928841cd5e6591" + integrity sha512-BtkjulweiXo9c3yVWrtexw2dTmBrvavD/xixNC6TKOBdrixUwU+6nuOO9dufDWsMxoid7MvtmDpzc9+mE8PdaA== dependencies: babel-plugin-debug-macros "^0.2.0" ember-cli-version-checker "^5.1.1" @@ -6872,19 +7035,9 @@ ember-compatibility-helpers@^1.1.2, ember-compatibility-helpers@^1.2.0, ember-co fs-extra "^9.1.0" semver "^5.4.1" -ember-composable-helpers@^4.5.0: - version "4.5.0" - resolved "https://registry.npmjs.org/ember-composable-helpers/-/ember-composable-helpers-4.5.0.tgz" - integrity sha512-XjpDLyVPsLCy6kd5dIxZonOECCO6AA5sY5Hr6tYUbJg3s5ghFAiFWaNcYraYC+fL2yPJQAswwpfwGlQORUJZkw== - dependencies: - "@babel/core" "^7.0.0" - broccoli-funnel "2.0.1" - ember-cli-babel "^7.26.3" - resolve "^1.10.0" - ember-composable-helpers@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/ember-composable-helpers/-/ember-composable-helpers-5.0.0.tgz" + resolved "https://registry.npmjs.org/ember-composable-helpers/-/ember-composable-helpers-5.0.0.tgz#055bab3a3e234ab2917499b1465e968c253ca885" integrity sha512-gyUrjiSju4QwNrsCLbBpP0FL6VDFZaELNW7Kbcp60xXhjvNjncYgzm4zzYXhT+i1lLA6WEgRZ3lOGgyBORYD0w== dependencies: "@babel/core" "^7.0.0" @@ -6894,7 +7047,7 @@ ember-composable-helpers@^5.0.0: ember-concurrency-decorators@^2.0.0: version "2.0.3" - resolved "https://registry.npmjs.org/ember-concurrency-decorators/-/ember-concurrency-decorators-2.0.3.tgz" + resolved "https://registry.npmjs.org/ember-concurrency-decorators/-/ember-concurrency-decorators-2.0.3.tgz#2816c9a0283b90ba5340fc5b4e0b92ea91f7d6e3" integrity sha512-r6O34YKI/slyYapVsuOPnmaKC4AsmBSwvgcadbdy+jHNj+mnryXPkm+3hhhRnFdlsKUKdEuXvl43lhjhYRLhhA== dependencies: "@ember-decorators/utils" "^6.1.0" @@ -6904,7 +7057,7 @@ ember-concurrency-decorators@^2.0.0: "ember-concurrency@>=1.0.0 <3": version "2.3.7" - resolved "https://registry.npmjs.org/ember-concurrency/-/ember-concurrency-2.3.7.tgz" + resolved "https://registry.npmjs.org/ember-concurrency/-/ember-concurrency-2.3.7.tgz#52d786e37704b9054da1952638797e23714ec0e1" integrity sha512-sz6sTIXN/CuLb5wdpauFa+rWXuvXXSnSHS4kuNzU5GSMDX1pLBWSuovoUk61FUe6CYRqBmT1/UushObwBGickQ== dependencies: "@babel/helper-plugin-utils" "^7.12.13" @@ -6918,14 +7071,14 @@ ember-concurrency-decorators@^2.0.0: ember-copy@2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/ember-copy/-/ember-copy-2.0.1.tgz" + resolved "https://registry.npmjs.org/ember-copy/-/ember-copy-2.0.1.tgz#13192b12a250324bb4a8b4547a680b113f4e3041" integrity sha512-N/XFvZszrzyyX4IcNoeK4mJvIItNuONumhPLqi64T8NDjJkxBj4Pq61rvMkJx/9eZ8alzE4I8vYKOLxT0FvRuQ== dependencies: ember-cli-babel "^7.22.1" ember-data-model-fragments@5.0.0-beta.8: version "5.0.0-beta.8" - resolved "https://registry.npmjs.org/ember-data-model-fragments/-/ember-data-model-fragments-5.0.0-beta.8.tgz" + resolved "https://registry.npmjs.org/ember-data-model-fragments/-/ember-data-model-fragments-5.0.0-beta.8.tgz#d29e0f59a8ba0157fd9d616d50b3faec731bbeac" integrity sha512-vOt2UXyhsWoZXCB9XAUqAobdRLr3ydUG6L36Rd7Qsg/1kj0jApQIEJS4qfA+xlBgirKEJ322PZqlBOv8zQSS8w== dependencies: broccoli-file-creator "^2.1.1" @@ -6939,7 +7092,7 @@ ember-data-model-fragments@5.0.0-beta.8: ember-data@~3.28.6: version "3.28.13" - resolved "https://registry.npmjs.org/ember-data/-/ember-data-3.28.13.tgz" + resolved "https://registry.npmjs.org/ember-data/-/ember-data-3.28.13.tgz#68668d84924453c2baeeb0cf7d25f75b2c07e8b9" integrity sha512-j1YjPl2JNHxQwQW6Bgfis44XSr4WCtdwMXr/SPpLsF1oVeTWIn3kwefcDnbuCI8Spmt1B9ab3ZLKzf2KkGN/7g== dependencies: "@ember-data/adapter" "3.28.13" @@ -6959,7 +7112,7 @@ ember-data@~3.28.6: ember-decorators@^6.1.1: version "6.1.1" - resolved "https://registry.npmjs.org/ember-decorators/-/ember-decorators-6.1.1.tgz" + resolved "https://registry.npmjs.org/ember-decorators/-/ember-decorators-6.1.1.tgz#6d770f8999cf5a413a1ee459afd520838c0fc470" integrity sha512-63vZPntPn1aqMyeNRLoYjJD+8A8obd+c2iZkJflswpDRNVIsp2m7aQdSCtPt4G0U/TEq2251g+N10maHX3rnJQ== dependencies: "@ember-decorators/component" "^6.1.1" @@ -6968,7 +7121,7 @@ ember-decorators@^6.1.1: ember-destroyable-polyfill@^2.0.2, ember-destroyable-polyfill@^2.0.3: version "2.0.3" - resolved "https://registry.npmjs.org/ember-destroyable-polyfill/-/ember-destroyable-polyfill-2.0.3.tgz" + resolved "https://registry.npmjs.org/ember-destroyable-polyfill/-/ember-destroyable-polyfill-2.0.3.tgz#1673ed66609a82268ef270a7d917ebd3647f11e1" integrity sha512-TovtNqCumzyAiW0/OisSkkVK93xnVF4NRU6+FN0ubpfwEOpRrmM2RqDwXI6YAChCgSHON1cz0DfQStpA1Gjuuw== dependencies: ember-cli-babel "^7.22.1" @@ -6977,7 +7130,7 @@ ember-destroyable-polyfill@^2.0.2, ember-destroyable-polyfill@^2.0.3: ember-element-helper@0.6.1: version "0.6.1" - resolved "https://registry.yarnpkg.com/ember-element-helper/-/ember-element-helper-0.6.1.tgz#a6fbc5be5f875b5c864ae61bf5c5f81d6de6d936" + resolved "https://registry.npmjs.org/ember-element-helper/-/ember-element-helper-0.6.1.tgz#a6fbc5be5f875b5c864ae61bf5c5f81d6de6d936" integrity sha512-YiOdAMlzYul4ulkIoNp8z7iHDfbT1fbut/9xGFRfxDwU/FmF8HtAUB2f1veu/w50HTeZNopa1OV2PCloZ76XlQ== dependencies: "@embroider/util" "^0.39.1 || ^0.40.0 || ^0.41.0 || ^1.0.0" @@ -6986,7 +7139,7 @@ ember-element-helper@0.6.1: ember-element-helper@^0.5.5: version "0.5.5" - resolved "https://registry.npmjs.org/ember-element-helper/-/ember-element-helper-0.5.5.tgz" + resolved "https://registry.npmjs.org/ember-element-helper/-/ember-element-helper-0.5.5.tgz#4a9ecb4dce57ee7f5ceb868a53c7b498c729f056" integrity sha512-Tu3hsI+/mjHBUvw62Qi+YDZtKkn59V66CjwbgfNTZZ7aHf4gFm1ow4zJ4WLnpnie8p9FvOmIUxwl5HvgPJIcFA== dependencies: "@embroider/util" "^0.39.1 || ^0.40.0 || ^0.41.0" @@ -6994,16 +7147,16 @@ ember-element-helper@^0.5.5: ember-cli-htmlbars "^5.1.0" ember-element-helper@^0.8.5: - version "0.8.5" - resolved "https://registry.yarnpkg.com/ember-element-helper/-/ember-element-helper-0.8.5.tgz#5a53d4e3aa8379694c2002a3097269aeb7c2621b" - integrity sha512-yZYzuasn6ZC8Nwv0MpaLYGtm68ZxIBSNSe/CYxNWkDdgcuAb2lAG1gx37XkwBIiwPQET0W2agwq7++/HwdMF8g== + version "0.8.6" + resolved "https://registry.npmjs.org/ember-element-helper/-/ember-element-helper-0.8.6.tgz#564d63dbbb6130e4c69ff06b3bd8fbfb9cb4787a" + integrity sha512-WcbkJKgBZypRGwujeiPrQfZRhETVFLR0wvH2UxDaNBhLWncapt6KK+M/2i/eODoAQwgGxziejhXC6Cbqa9zA8g== dependencies: - "@embroider/addon-shim" "1.8.3" + "@embroider/addon-shim" "^1.8.3" "@embroider/util" "^1.0.0" ember-exam@^6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/ember-exam/-/ember-exam-6.1.0.tgz" + resolved "https://registry.npmjs.org/ember-exam/-/ember-exam-6.1.0.tgz#1ea2c0ece27ac8ad6a80d959b1c207611b7dfdd7" integrity sha512-H9tg7eUgqkjAsr1/15UzxGyZobGLgsyTi56Ng0ySnkYGCRfvVpwtVc3xgcNOFnUaa9RExUFpxC0adjW3K87Uxw== dependencies: "@embroider/macros" "^0.36.0" @@ -7023,19 +7176,19 @@ ember-exam@^6.1.0: ember-export-application-global@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/ember-export-application-global/-/ember-export-application-global-2.0.1.tgz" + resolved "https://registry.npmjs.org/ember-export-application-global/-/ember-export-application-global-2.0.1.tgz#b120a70e322ab208defc9e2daebe8d0dfc2dcd46" integrity sha512-B7wiurPgsxsSGzJuPFkpBWnaeuCu2PGpG2BjyrfA1VcL7//o+5RSnZqiCEY326y7qmxb2GoCgo0ft03KBU0rRw== ember-factory-for-polyfill@^1.3.1: version "1.3.1" - resolved "https://registry.npmjs.org/ember-factory-for-polyfill/-/ember-factory-for-polyfill-1.3.1.tgz" + resolved "https://registry.npmjs.org/ember-factory-for-polyfill/-/ember-factory-for-polyfill-1.3.1.tgz#b446ed64916d293c847a4955240eb2c993b86eae" integrity sha512-y3iG2iCzH96lZMTWQw6LWNLAfOmDC4pXKbZP6FxG8lt7GGaNFkZjwsf+Z5GAe7kxfD7UG4lVkF7x37K82rySGA== dependencies: ember-cli-version-checker "^2.1.0" -ember-focus-trap@^1.0.2: +ember-focus-trap@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/ember-focus-trap/-/ember-focus-trap-1.1.0.tgz" + resolved "https://registry.npmjs.org/ember-focus-trap/-/ember-focus-trap-1.1.0.tgz#e3c47c6e916e838af3884b43e2794e87088d2bac" integrity sha512-KxbCKpAJaBVZm+bW4tHPoBJAZThmxa6pI+WQusL+bj0RtAnGUNkWsVy6UBMZ5QqTQzf4EvGHkCVACVp5lbAWMQ== dependencies: "@embroider/addon-shim" "^1.0.0" @@ -7043,7 +7196,7 @@ ember-focus-trap@^1.0.2: ember-get-config@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/ember-get-config/-/ember-get-config-0.3.0.tgz" + resolved "https://registry.npmjs.org/ember-get-config/-/ember-get-config-0.3.0.tgz#a73a1a87b48d9dde4c66a0e52ed5260b8a48cfbd" integrity sha512-0e2pKzwW5lBZ4oJnvu9qHOht4sP1MWz/m3hyz8kpSoMdrlZVf62LDKZ6qfKgy8drcv5YhCMYE6QV7MhnqlrzEQ== dependencies: broccoli-file-creator "^1.1.1" @@ -7051,7 +7204,7 @@ ember-get-config@^0.3.0: ember-get-config@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/ember-get-config/-/ember-get-config-2.1.1.tgz" + resolved "https://registry.npmjs.org/ember-get-config/-/ember-get-config-2.1.1.tgz#bede76c25d95dbefab8d30064abf7aa00bc19235" integrity sha512-uNmv1cPG/4qsac8oIf5txJ2FZ8p88LEpG4P3dNcjsJS98Y8hd0GPMFwVqpnzI78Lz7VYRGQWY4jnE4qm5R3j4g== dependencies: "@embroider/macros" "^0.50.0 || ^1.0.0" @@ -7059,7 +7212,7 @@ ember-get-config@^2.1.1: ember-getowner-polyfill@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/ember-getowner-polyfill/-/ember-getowner-polyfill-2.2.0.tgz" + resolved "https://registry.npmjs.org/ember-getowner-polyfill/-/ember-getowner-polyfill-2.2.0.tgz#38e7dccbcac69d5ec694000329ec0b2be651d2b2" integrity sha512-rwGMJgbGzxIAiWYjdpAh04Abvt0s3HuS/VjHzUFhVyVg2pzAuz45B9AzOxYXzkp88vFC7FPaiA4kE8NxNk4A4Q== dependencies: ember-cli-version-checker "^2.1.0" @@ -7067,7 +7220,7 @@ ember-getowner-polyfill@^2.0.0: ember-in-element-polyfill@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/ember-in-element-polyfill/-/ember-in-element-polyfill-1.0.1.tgz" + resolved "https://registry.npmjs.org/ember-in-element-polyfill/-/ember-in-element-polyfill-1.0.1.tgz#143504445bb4301656a2eaad42644d684f5164dd" integrity sha512-eHs+7D7PuQr8a1DPqsJTsEyo3FZ1XuH6WEZaEBPDa9s0xLlwByCNKl8hi1EbXOgvgEZNHHi9Rh0vjxyfakrlgg== dependencies: debug "^4.3.1" @@ -7077,14 +7230,14 @@ ember-in-element-polyfill@^1.0.0: ember-inflector@^4.0.1, ember-inflector@^4.0.2: version "4.0.2" - resolved "https://registry.npmjs.org/ember-inflector/-/ember-inflector-4.0.2.tgz" + resolved "https://registry.npmjs.org/ember-inflector/-/ember-inflector-4.0.2.tgz#4494f1a5f61c1aca7702d59d54024cc92211d8ec" integrity sha512-+oRstEa52mm0jAFzhr51/xtEWpCEykB3SEBr7vUg8YnXUZJ5hKNBppP938q8Zzr9XfJEbzrtDSGjhKwJCJv6FQ== dependencies: ember-cli-babel "^7.26.5" ember-intl@^5.7.0: version "5.7.2" - resolved "https://registry.npmjs.org/ember-intl/-/ember-intl-5.7.2.tgz" + resolved "https://registry.npmjs.org/ember-intl/-/ember-intl-5.7.2.tgz#76d933f974f041448b01247888bc3bcc9261e812" integrity sha512-gs17uY1ywzMaUpx1gxfBkFQYRTWTSa/zbkL13MVtffG9aBLP+998MibytZOUxIipMtLCm4sr/g6/1aaKRr9/+g== dependencies: broccoli-caching-writer "^3.0.3" @@ -7112,9 +7265,9 @@ ember-intl@^5.7.0: mkdirp "^1.0.4" silent-error "^1.1.1" -ember-keyboard@^8.2.0: +ember-keyboard@^8.2.1: version "8.2.1" - resolved "https://registry.npmjs.org/ember-keyboard/-/ember-keyboard-8.2.1.tgz" + resolved "https://registry.npmjs.org/ember-keyboard/-/ember-keyboard-8.2.1.tgz#945a8a71068d81c06ad26851008ef81061db2a59" integrity sha512-wT9xpt3GKsiodGZoifKU4OyeRjXWlmKV9ZHHsp6wJBwMFpl4wWPjTNdINxivk2qg/WFNIh8nUiwuG4+soWXPdw== dependencies: "@embroider/addon-shim" "^1.8.4" @@ -7124,7 +7277,7 @@ ember-keyboard@^8.2.0: ember-load-initializers@^2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/ember-load-initializers/-/ember-load-initializers-2.1.2.tgz" + resolved "https://registry.npmjs.org/ember-load-initializers/-/ember-load-initializers-2.1.2.tgz#8a47a656c1f64f9b10cecdb4e22a9d52ad9c7efa" integrity sha512-CYR+U/wRxLbrfYN3dh+0Tb6mFaxJKfdyz+wNql6cqTrA0BBi9k6J3AaKXj273TqvEpyyXegQFFkZEiuZdYtgJw== dependencies: ember-cli-babel "^7.13.0" @@ -7132,7 +7285,7 @@ ember-load-initializers@^2.1.2: ember-math-helpers@^2.4.0: version "2.18.2" - resolved "https://registry.npmjs.org/ember-math-helpers/-/ember-math-helpers-2.18.2.tgz" + resolved "https://registry.npmjs.org/ember-math-helpers/-/ember-math-helpers-2.18.2.tgz#5778f0aae08f3502be8defbacd383794f42b177e" integrity sha512-ikAXlIiT0wk8X8uuMtHkrRYt8HnDt9Wk+iNoY9IoBmt6IRZjCD5BmuxrIPj5Eop2/afMfKmNKnc4L1StkXM3wg== dependencies: broccoli-funnel "^3.0.8" @@ -7141,7 +7294,7 @@ ember-math-helpers@^2.4.0: ember-maybe-import-regenerator@^0.1.6: version "0.1.6" - resolved "https://registry.npmjs.org/ember-maybe-import-regenerator/-/ember-maybe-import-regenerator-0.1.6.tgz" + resolved "https://registry.npmjs.org/ember-maybe-import-regenerator/-/ember-maybe-import-regenerator-0.1.6.tgz#35d41828afa6d6a59bc0da3ce47f34c573d776ca" integrity sha512-aX9UINiUXIjzsCNNna1ioASB/2lbnFgSHI63bBcd4MOVE9AqoLdOL7h+ocyylYXyYoBj2JDRwCzjWNf2Xbp5wg== dependencies: broccoli-funnel "^1.0.1" @@ -7151,7 +7304,7 @@ ember-maybe-import-regenerator@^0.1.6: ember-maybe-in-element@^2.0.3: version "2.1.0" - resolved "https://registry.npmjs.org/ember-maybe-in-element/-/ember-maybe-in-element-2.1.0.tgz" + resolved "https://registry.npmjs.org/ember-maybe-in-element/-/ember-maybe-in-element-2.1.0.tgz#f7bd8e41ca90a4f8038d919a9c135cbe7a7f271b" integrity sha512-6WAzPbf4BNQIQzkur2+zRJJJ/PKQoujIYgFjrpj3fOPy8iRlxVUm0/B41qbFyg1LE6bVbg0cWbuESWEvJ9Rswg== dependencies: ember-cli-babel "^7.26.11" @@ -7160,7 +7313,7 @@ ember-maybe-in-element@^2.0.3: ember-modifier-manager-polyfill@^1.1.0, ember-modifier-manager-polyfill@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/ember-modifier-manager-polyfill/-/ember-modifier-manager-polyfill-1.2.0.tgz" + resolved "https://registry.npmjs.org/ember-modifier-manager-polyfill/-/ember-modifier-manager-polyfill-1.2.0.tgz#cf4444e11a42ac84f5c8badd85e635df57565dda" integrity sha512-bnaKF1LLKMkBNeDoetvIJ4vhwRPKIIumWr6dbVuW6W6p4QV8ZiO+GdF8J7mxDNlog9CeL9Z/7wam4YS86G8BYA== dependencies: ember-cli-babel "^7.10.0" @@ -7169,7 +7322,7 @@ ember-modifier-manager-polyfill@^1.1.0, ember-modifier-manager-polyfill@^1.2.0: ember-modifier@^2.1.0: version "2.1.2" - resolved "https://registry.npmjs.org/ember-modifier/-/ember-modifier-2.1.2.tgz" + resolved "https://registry.npmjs.org/ember-modifier/-/ember-modifier-2.1.2.tgz#62d18faedf972dcd9d34f90d5321fbc943d139b1" integrity sha512-3Lsu1fV1sIGa66HOW07RZc6EHISwKt5VA5AUnFss2HX6OTfpxTJ2qvPctt2Yt0XPQXJ4G6BQasr/F35CX7UGJA== dependencies: ember-cli-babel "^7.22.1" @@ -7181,17 +7334,18 @@ ember-modifier@^2.1.0: ember-modifier-manager-polyfill "^1.2.0" "ember-modifier@^2.1.2 || ^3.1.0 || ^4.0.0", "ember-modifier@^3.2.7 || ^4.0.0", ember-modifier@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/ember-modifier/-/ember-modifier-4.1.0.tgz" - integrity sha512-YFCNpEYj6jdyy3EjslRb2ehNiDvaOrXTilR9+ngq+iUqSHYto2zKV0rleiA1XJQ27ELM1q8RihT29U6Lq5EyqQ== + version "4.2.0" + resolved "https://registry.npmjs.org/ember-modifier/-/ember-modifier-4.2.0.tgz#f99cb817b9b85c5188c63f853cd06aa62e8dde57" + integrity sha512-BJ48eTEGxD8J7+lofwVmee7xDgNDgpr5dd6+MSu4gk+I6xb35099RMNorXY5hjjwMJEyi/IRR6Yn3M7iJMz8Zw== dependencies: - "@embroider/addon-shim" "^1.8.4" + "@embroider/addon-shim" "^1.8.7" + decorator-transforms "^2.0.0" ember-cli-normalize-entity-name "^1.0.0" ember-cli-string-utils "^1.1.0" ember-modifier@^3.2.7: version "3.2.7" - resolved "https://registry.npmjs.org/ember-modifier/-/ember-modifier-3.2.7.tgz" + resolved "https://registry.npmjs.org/ember-modifier/-/ember-modifier-3.2.7.tgz#f2d35b7c867cbfc549e1acd8d8903c5ecd02ea4b" integrity sha512-ezcPQhH8jUfcJQbbHji4/ZG/h0yyj1jRDknfYue/ypQS8fM8LrGcCMo0rjDZLzL1Vd11InjNs3BD7BdxFlzGoA== dependencies: ember-cli-babel "^7.26.6" @@ -7202,7 +7356,7 @@ ember-modifier@^3.2.7: ember-named-blocks-polyfill@^0.2.5: version "0.2.5" - resolved "https://registry.npmjs.org/ember-named-blocks-polyfill/-/ember-named-blocks-polyfill-0.2.5.tgz" + resolved "https://registry.npmjs.org/ember-named-blocks-polyfill/-/ember-named-blocks-polyfill-0.2.5.tgz#d5841406277026a221f479c815cfbac6cdcaeecb" integrity sha512-OVMxzkfqJrEvmiky7gFzmuTaImCGm7DOudHWTdMBPO7E+dQSunrcRsJMgO9ZZ56suqBIz/yXbEURrmGS+avHxA== dependencies: ember-cli-babel "^7.19.0" @@ -7210,7 +7364,7 @@ ember-named-blocks-polyfill@^0.2.5: ember-native-dom-helpers@^0.7.0: version "0.7.0" - resolved "https://registry.npmjs.org/ember-native-dom-helpers/-/ember-native-dom-helpers-0.7.0.tgz" + resolved "https://registry.npmjs.org/ember-native-dom-helpers/-/ember-native-dom-helpers-0.7.0.tgz#98a87c11a391cec5c12382a4857e59ea2fb4b00a" integrity sha512-ySJRGRhwYIWUAZKilB8xEcIatP9wKfEBX6JFG8bG4Ck7GvA0eau265hTGZz/+ntZuwcY4HrzSNkwimlHx4cM/A== dependencies: broccoli-funnel "^1.1.0" @@ -7218,14 +7372,14 @@ ember-native-dom-helpers@^0.7.0: ember-on-helper@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/ember-on-helper/-/ember-on-helper-0.1.0.tgz" + resolved "https://registry.npmjs.org/ember-on-helper/-/ember-on-helper-0.1.0.tgz#c8b1fef9173fc8546c4933b57ecd7ffbcebad99e" integrity sha512-jjafBnWfoA4VSSje476ft5G+urlvvuSDddwAJjKDCjKY9mbe3hAEsJiMBAaPObJRMm1FOglCuKjQZfwDDls6MQ== dependencies: ember-cli-babel "^7.7.3" ember-on-resize-modifier@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/ember-on-resize-modifier/-/ember-on-resize-modifier-2.0.2.tgz" + resolved "https://registry.npmjs.org/ember-on-resize-modifier/-/ember-on-resize-modifier-2.0.2.tgz#a1e2ab86e69c825a6851e63261263b1610ef9e15" integrity sha512-7mcD7CNbiCaZEIASWlRz/Wmn47afCMSFTdQJSSUe0WCgnXxn9DVoqZ39B7ZuddTHa0V6otTFrV/lIRYpggQ+eg== dependencies: ember-auto-import "^2.5.0" @@ -7236,14 +7390,14 @@ ember-on-resize-modifier@^2.0.2: ember-page-title@^6.2.2: version "6.2.2" - resolved "https://registry.npmjs.org/ember-page-title/-/ember-page-title-6.2.2.tgz" + resolved "https://registry.npmjs.org/ember-page-title/-/ember-page-title-6.2.2.tgz#980838c44e96cba1d00f42435d707936af627324" integrity sha512-YTXA+cylZrh9zO0zwjlaAGReT2MVOxAMnVO1OOygFrs1JBs4D6CKV3tImoilg3AvIXFBeJfFNNUbJOdRd9IGGg== dependencies: ember-cli-babel "^7.23.1" ember-power-select-with-create@^0.8.0: version "0.8.0" - resolved "https://registry.npmjs.org/ember-power-select-with-create/-/ember-power-select-with-create-0.8.0.tgz" + resolved "https://registry.npmjs.org/ember-power-select-with-create/-/ember-power-select-with-create-0.8.0.tgz#973e26db8f76c650a6d166ea1c03ec00453150be" integrity sha512-9xJTgaju4NyADJb6RjkUpIhLFx/5ORmAK3R/zuTyc2ILyOY7+SvDw8LuFNTnOVAFOcT3g+TJKEL8nzBuwnEi7g== dependencies: ember-cli-babel "^7.20.0" @@ -7252,7 +7406,7 @@ ember-power-select-with-create@^0.8.0: ember-power-select@^4.0.0, ember-power-select@^4.0.5: version "4.1.7" - resolved "https://registry.npmjs.org/ember-power-select/-/ember-power-select-4.1.7.tgz" + resolved "https://registry.npmjs.org/ember-power-select/-/ember-power-select-4.1.7.tgz#eb547dd37448357d8f3fa789db18ddbba43fb8ca" integrity sha512-Q4cjUudWb7JA6q7qe0jhcpLsipuFUHMwkYC05HxST5qm3MRMEzs6KfZ3Xd/TcrjBLSoWniw3Q61Quwcb41w5Jw== dependencies: "@glimmer/component" "^1.0.4" @@ -7269,7 +7423,7 @@ ember-power-select@^4.0.0, ember-power-select@^4.0.5: ember-qunit@^5.1.5: version "5.1.5" - resolved "https://registry.npmjs.org/ember-qunit/-/ember-qunit-5.1.5.tgz" + resolved "https://registry.npmjs.org/ember-qunit/-/ember-qunit-5.1.5.tgz#24a7850f052be24189ff597dfc31b923e684c444" integrity sha512-2cFA4oMygh43RtVcMaBrr086Tpdhgbn3fVZ2awLkzF/rnSN0D0PSRpd7hAD7OdBPerC/ZYRwzVyGXLoW/Zes4A== dependencies: broccoli-funnel "^3.0.8" @@ -7284,14 +7438,14 @@ ember-qunit@^5.1.5: ember-raf-scheduler@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/ember-raf-scheduler/-/ember-raf-scheduler-0.3.0.tgz" + resolved "https://registry.npmjs.org/ember-raf-scheduler/-/ember-raf-scheduler-0.3.0.tgz#7657ee5c1d54f852731e61e9d0e0750a9a22f5f4" integrity sha512-i8JWQidNCX7n5TOTIKRDR0bnsQN9aJh/GtOJKINz2Wr+I7L7sYVhli6MFqMYNGKC9j9e6iWsznfAIxddheyEow== dependencies: ember-cli-babel "^7.26.6" ember-ref-bucket@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/ember-ref-bucket/-/ember-ref-bucket-4.1.0.tgz" + resolved "https://registry.npmjs.org/ember-ref-bucket/-/ember-ref-bucket-4.1.0.tgz#2a52e72a395a14033d034c834fab648f26d74baa" integrity sha512-oEUU2mDtuYuMM039U9YEqrrOCVHH6rQfvbFOmh3WxOVEgubmLVyKEpGgU4P/6j0B/JxTqqTwM3ULTQyDto8dKg== dependencies: ember-cli-babel "^7.26.11" @@ -7300,7 +7454,7 @@ ember-ref-bucket@^4.1.0: ember-render-helpers@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/ember-render-helpers/-/ember-render-helpers-0.2.0.tgz" + resolved "https://registry.npmjs.org/ember-render-helpers/-/ember-render-helpers-0.2.0.tgz#5f7af8ee74ae29f85e0d156b2775edff23f6de21" integrity sha512-MnqGS8BnY3GJ+n5RZVVRqCwKjfXXMr5quKyqNu1vxft8oslOJuZ1f1dOesQouD+6LwD4Y9tWRVKNw+LOqM9ocw== dependencies: ember-cli-babel "^7.23.0" @@ -7308,7 +7462,7 @@ ember-render-helpers@^0.2.0: ember-resize-observer-service@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/ember-resize-observer-service/-/ember-resize-observer-service-1.1.0.tgz" + resolved "https://registry.npmjs.org/ember-resize-observer-service/-/ember-resize-observer-service-1.1.0.tgz#62729a9de656e8eade4b3e65bd9999840dc44f65" integrity sha512-/vbfxtHSyOGSNdjPKL8X3SyvUnYo3z88sJtD/bLJ0ZGhqVPaXCmtSkLyr/Fh75ckJDixRFxK4i4zEUSlrbk0PA== dependencies: ember-cli-babel "^7.26.6" @@ -7316,7 +7470,7 @@ ember-resize-observer-service@^1.1.0: ember-resolver@^8.0.3: version "8.1.0" - resolved "https://registry.npmjs.org/ember-resolver/-/ember-resolver-8.1.0.tgz" + resolved "https://registry.npmjs.org/ember-resolver/-/ember-resolver-8.1.0.tgz#8ada162746fde3e6ea6a703bbb9910fbe62ab1e5" integrity sha512-MGD7X2ztZVswGqs1mLgzhZJRhG7XiF6Mg4DgC7xJFWRYQQUHyGJpGdNWY9nXyrYnRIsCrQoL1do41zpxbrB/cg== dependencies: babel-plugin-debug-macros "^0.3.4" @@ -7328,7 +7482,7 @@ ember-resolver@^8.0.3: ember-resources@^5.0.1: version "5.6.4" - resolved "https://registry.npmjs.org/ember-resources/-/ember-resources-5.6.4.tgz" + resolved "https://registry.npmjs.org/ember-resources/-/ember-resources-5.6.4.tgz#1ae05bb5398ab0d8fab8c0925c5bf679ee86e327" integrity sha512-ShdosnruPm37jPpzPOgPVelymEDJT/27Jz/j5AGPVAfCaUhRIocTxNMtPx13ox890A2babuPF5M3Ur8UFidqtw== dependencies: "@babel/runtime" "^7.17.8" @@ -7337,12 +7491,12 @@ ember-resources@^5.0.1: ember-rfc176-data@^0.3.13, ember-rfc176-data@^0.3.15, ember-rfc176-data@^0.3.17: version "0.3.18" - resolved "https://registry.npmjs.org/ember-rfc176-data/-/ember-rfc176-data-0.3.18.tgz" + resolved "https://registry.npmjs.org/ember-rfc176-data/-/ember-rfc176-data-0.3.18.tgz#bb6fdcef49999981317ea81b6cc9210fb4108d65" integrity sha512-JtuLoYGSjay1W3MQAxt3eINWXNYYQliK90tLwtb8aeCuQK8zKGCRbBodVIrkcTqshULMnRuTOS6t1P7oQk3g6Q== ember-route-action-helper@^2.0.8: version "2.0.8" - resolved "https://registry.npmjs.org/ember-route-action-helper/-/ember-route-action-helper-2.0.8.tgz" + resolved "https://registry.npmjs.org/ember-route-action-helper/-/ember-route-action-helper-2.0.8.tgz#f227fcccb73e839b65e9b814e241b322fe8c02fc" integrity sha512-V+4uKwqaYveriVt2rl4e+9mzHJiQOr1B8dCPQQ2TS3iAcmi5RD2giRDFGtCK9d2XY9Arb/f9hJh0obP20iyt3A== dependencies: ember-cli-babel "^6.8.1" @@ -7350,7 +7504,7 @@ ember-route-action-helper@^2.0.8: ember-router-generator@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/ember-router-generator/-/ember-router-generator-2.0.0.tgz" + resolved "https://registry.npmjs.org/ember-router-generator/-/ember-router-generator-2.0.0.tgz#d04abfed4ba8b42d166477bbce47fccc672dbde0" integrity sha512-89oVHVJwmLDvGvAUWgS87KpBoRhy3aZ6U0Ql6HOmU4TrPkyaa8pM0W81wj9cIwjYprcQtN9EwzZMHnq46+oUyw== dependencies: "@babel/parser" "^7.4.5" @@ -7359,21 +7513,21 @@ ember-router-generator@^2.0.0: ember-router-helpers@^0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/ember-router-helpers/-/ember-router-helpers-0.4.0.tgz" + resolved "https://registry.npmjs.org/ember-router-helpers/-/ember-router-helpers-0.4.0.tgz#6ef86cc75e38c3455ab916c78d5a38293e94c12f" integrity sha512-DiPyncEAACKV/XcmYqUwh0iHBPvGW75Fw1uerDudblofXTtAH/+QzeE/0wK2G6MUBWKyn0HyIuLXE3pJm0zKFg== dependencies: ember-cli-babel "^7.20.0" ember-set-helper@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/ember-set-helper/-/ember-set-helper-2.0.1.tgz" + resolved "https://registry.npmjs.org/ember-set-helper/-/ember-set-helper-2.0.1.tgz#e39417531e25089b45ccb905b8c00eda7b3fbbde" integrity sha512-6IIimVGOdehZcncH1ilCY4p7hWBtZqWYMc1Xodr1ATOCuIk6ZO1yztKcUQhlmwl7fE82gL4wHD01T6XP5W59Ng== dependencies: ember-cli-babel "^7.18.0" ember-sinon-qunit@5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/ember-sinon-qunit/-/ember-sinon-qunit-5.0.0.tgz" + resolved "https://registry.npmjs.org/ember-sinon-qunit/-/ember-sinon-qunit-5.0.0.tgz#d6585ee691f73c5733783a0583f87840d1323cb1" integrity sha512-7Q938adhhHcUHFg41fwj6g5Q6Iyt8eyo7c0D1r7uOeKSFlobcm1FiD/dCmjNZx224KiI6KYh/0EwqoaIyWAawA== dependencies: broccoli-funnel "^3.0.2" @@ -7382,7 +7536,7 @@ ember-sinon-qunit@5.0.0: ember-sinon@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/ember-sinon/-/ember-sinon-5.0.0.tgz" + resolved "https://registry.npmjs.org/ember-sinon/-/ember-sinon-5.0.0.tgz#990bcafa65403d2b2e3e7f14bb547862197e97d5" integrity sha512-dTP2vhao1xWm3OlfpOALooso/OLM71SFg7PIBmZ6JdwKCC+CzcPb4BYRAXuoAFYzmhH8z28p8HdemjZBb0B3Bw== dependencies: broccoli-funnel "^2.0.0" @@ -7392,14 +7546,14 @@ ember-sinon@^5.0.0: ember-source-channel-url@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/ember-source-channel-url/-/ember-source-channel-url-3.0.0.tgz" + resolved "https://registry.npmjs.org/ember-source-channel-url/-/ember-source-channel-url-3.0.0.tgz#bcd5be72c63fa0b8c390b3121783b462063e2a1b" integrity sha512-vF/8BraOc66ZxIDo3VuNP7iiDrnXEINclJgSJmqwAAEpg84Zb1DHPI22XTXSDA+E8fW5btPUxu65c3ZXi8AQFA== dependencies: node-fetch "^2.6.0" ember-source@3.28.8: version "3.28.8" - resolved "https://registry.npmjs.org/ember-source/-/ember-source-3.28.8.tgz" + resolved "https://registry.npmjs.org/ember-source/-/ember-source-3.28.8.tgz#c58fd4a1538d6c4b9aebe76c764cabf5396c64d9" integrity sha512-hA15oYzbRdi9983HIemeVzzX2iLcMmSPp6akUiMQhFZYWPrKksbPyLrO6YpZ4hNM8yBjQSDXEkZ1V3yxBRKjUA== dependencies: "@babel/helper-module-imports" "^7.8.3" @@ -7431,7 +7585,7 @@ ember-source@3.28.8: ember-stargate@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/ember-stargate/-/ember-stargate-0.2.0.tgz" + resolved "https://registry.npmjs.org/ember-stargate/-/ember-stargate-0.2.0.tgz#3b4594e1745dcd49372e3a8d6d06dada1dc6bf9a" integrity sha512-AJxj4GVfW1pADk2Re6eKq5qhsWNEPWOy9jj0as3wnJFjUe0OeMvnOIqmyhwT2zpX6eLL+hIJ9cazP+j9/DvMQg== dependencies: "@ember/render-modifiers" "^1.0.2" @@ -7443,7 +7597,7 @@ ember-stargate@^0.2.0: ember-stargate@^0.4.3: version "0.4.3" - resolved "https://registry.npmjs.org/ember-stargate/-/ember-stargate-0.4.3.tgz" + resolved "https://registry.npmjs.org/ember-stargate/-/ember-stargate-0.4.3.tgz#93e92e4928d489557401d70e52b242b38f36f9ab" integrity sha512-GeT5n+TT3Lfl335f16fx9ms0Jap+v5LTs8otIaQEGtFbSP5Jj/hlT3JPB9Uo8IDLXdjejxJsKRpCEzRD43g5dg== dependencies: "@ember/render-modifiers" "^2.0.0" @@ -7454,23 +7608,23 @@ ember-stargate@^0.4.3: ember-string-fns@^1.4.0: version "1.4.1" - resolved "https://registry.npmjs.org/ember-string-fns/-/ember-string-fns-1.4.1.tgz" + resolved "https://registry.npmjs.org/ember-string-fns/-/ember-string-fns-1.4.1.tgz#3890c80e4d73db78a5d3027c0ec9a3e677b3813a" integrity sha512-PtMjvFq34+ygsIaug0QYW+0e/CsHHRfffFEMIR+R2MIgNYLz/FED4gRMwtPZsUXsrYVr0JMvvbwwAeFxpyxFFw== dependencies: ember-cli-babel "^7.7.3" ember-style-modifier@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/ember-style-modifier/-/ember-style-modifier-0.6.0.tgz" + resolved "https://registry.npmjs.org/ember-style-modifier/-/ember-style-modifier-0.6.0.tgz#cc5e58db7f6d6662028a7b4e3cf63cf25ba59a8f" integrity sha512-KqW4vyR80l/GMJsuFV+WLqTmGjXKLpoQ/HAmno+oMDrMt13p/5ImrvarQ6lFgXttFnLCxl6YpMY4YX27p1G54g== dependencies: ember-cli-babel "^7.21.0" ember-modifier "^2.1.0" ember-style-modifier@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/ember-style-modifier/-/ember-style-modifier-3.0.1.tgz" - integrity sha512-WHRVIiqY/dpwDtVWlnHW0P4Z+Jha8QEwfaQdIF2ckJL77ZKdjbV2j1XZymS0Nzj61EGx5BM+YEsGL16r3hLv2A== + version "3.1.1" + resolved "https://registry.npmjs.org/ember-style-modifier/-/ember-style-modifier-3.1.1.tgz#313269708552c42255806586160411840adc98c5" + integrity sha512-J91YLKVp3/m7LrcLEWNSG2sJlSFhE5Ny75empU048qYJtdJMe788Ks/EpKEi953o1mJujVRg792YGrwbrpTzNA== dependencies: ember-auto-import "^2.5.0" ember-cli-babel "^7.26.11" @@ -7478,7 +7632,7 @@ ember-style-modifier@^3.0.1: ember-template-lint@^2.0.1: version "2.21.0" - resolved "https://registry.npmjs.org/ember-template-lint/-/ember-template-lint-2.21.0.tgz" + resolved "https://registry.npmjs.org/ember-template-lint/-/ember-template-lint-2.21.0.tgz#7e120abf309a8810eeed26c52377943faf15a95b" integrity sha512-19QbEqJQdMfcRS7PsQsubflRowEtnkbD0tpYR4q/xq4lodmhU7hhOFvlTQgbxD/jwW5Ur+tkOwH4KFy9JwOyXA== dependencies: chalk "^4.0.0" @@ -7495,7 +7649,7 @@ ember-template-lint@^2.0.1: ember-template-recast@^5.0.1: version "5.0.3" - resolved "https://registry.npmjs.org/ember-template-recast/-/ember-template-recast-5.0.3.tgz" + resolved "https://registry.npmjs.org/ember-template-recast/-/ember-template-recast-5.0.3.tgz#79df27a70bdce7be17f14db13886afde1e9d02d6" integrity sha512-qsJYQhf29Dk6QMfviXhUPE+byMOs6iRQxUDHgkj8yqjeppvjHaFG96hZi/NAXJTm/M7o3PpfF5YlmeaKtI9UeQ== dependencies: "@glimmer/reference" "^0.65.0" @@ -7512,7 +7666,7 @@ ember-template-recast@^5.0.1: ember-test-selectors@^5.0.0: version "5.5.0" - resolved "https://registry.npmjs.org/ember-test-selectors/-/ember-test-selectors-5.5.0.tgz" + resolved "https://registry.npmjs.org/ember-test-selectors/-/ember-test-selectors-5.5.0.tgz#114bd29c4a33eee3a328c9ce32a57a018c27f5f6" integrity sha512-PiKhbPnidRYQ5ed/CTU3teJV3XmzkjYjsCGx1UTy7qEY/1dEqxezlZu1DtisoLJ9Y+BcjTVlE+596lo9cOXd3w== dependencies: calculate-cache-key-for-tree "^2.0.0" @@ -7521,7 +7675,7 @@ ember-test-selectors@^5.0.0: ember-text-measurer@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/ember-text-measurer/-/ember-text-measurer-0.6.0.tgz" + resolved "https://registry.npmjs.org/ember-text-measurer/-/ember-text-measurer-0.6.0.tgz#140eda044fd7d4d7f60f654dd30da79c06922b2e" integrity sha512-/aZs2x2i6kT4a5tAW+zenH2wg8AbRK9jKxLkbVsKl/1ublNl27idVRdov1gJ+zgWu3DNK7whcfVycXtlaybYQw== dependencies: ember-cli-babel "^7.19.0" @@ -7529,7 +7683,7 @@ ember-text-measurer@^0.6.0: ember-tracked-storage-polyfill@1.0.0, ember-tracked-storage-polyfill@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/ember-tracked-storage-polyfill/-/ember-tracked-storage-polyfill-1.0.0.tgz" + resolved "https://registry.npmjs.org/ember-tracked-storage-polyfill/-/ember-tracked-storage-polyfill-1.0.0.tgz#84d307a1e4badc5f84dca681db2cfea9bdee8a77" integrity sha512-eL7lZat68E6P/D7b9UoTB5bB5Oh/0aju0Z7PCMi3aTwhaydRaxloE7TGrTRYU+NdJuyNVZXeGyxFxn2frvd3TA== dependencies: ember-cli-babel "^7.26.3" @@ -7537,14 +7691,14 @@ ember-tracked-storage-polyfill@1.0.0, ember-tracked-storage-polyfill@^1.0.0: "ember-truth-helpers@^2.1.0 || ^3.0.0", ember-truth-helpers@^3.0.0, ember-truth-helpers@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/ember-truth-helpers/-/ember-truth-helpers-3.1.1.tgz" + resolved "https://registry.npmjs.org/ember-truth-helpers/-/ember-truth-helpers-3.1.1.tgz#434715926d72bcc63b8a115dec09745fda4474dc" integrity sha512-FHwJAx77aA5q27EhdaaiBFuy9No+8yaWNT5A7zs0sIFCmf14GbcLn69vJEp6mW7vkITezizGAWhw7gL0Wbk7DA== dependencies: ember-cli-babel "^7.22.1" ember-validators@~4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/ember-validators/-/ember-validators-4.0.1.tgz" + resolved "https://registry.npmjs.org/ember-validators/-/ember-validators-4.0.1.tgz#13beefdf185b00efd1b60e51b21380686d8994ba" integrity sha512-QVHzzYQn17Ikz8EZVxEtjKRyr6fmwSUbjYpxjcuoZKN5Ub1jjU2LzPOXT6FJQet691UlBs35e6EjPkBOb+xOuA== dependencies: "@embroider/macros" "^0.41.0" @@ -7553,40 +7707,40 @@ ember-validators@~4.0.0: emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== emoji-regex@~10.1.0: version "10.1.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.1.0.tgz" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.1.0.tgz#d50e383743c0f7a5945c47087295afc112e3cf66" integrity sha512-xAEnNCT3w2Tg6MA7ly6QqYJvEoY1tm9iIjJ3yMKK9JPlWuRHAMoe5iETwQnx3M9TVbFMfsrBgWKR+IsmswwNjg== emojis-list@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz" + resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== encodeurl@~1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.4" - resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" -engine.io-parser@~5.0.3: - version "5.0.6" - resolved "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz" - integrity sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw== +engine.io-parser@~5.2.1: + version "5.2.2" + resolved "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz#37b48e2d23116919a3453738c5720455e64e1c49" + integrity sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw== -engine.io@~6.4.1: - version "6.4.1" - resolved "https://registry.npmjs.org/engine.io/-/engine.io-6.4.1.tgz" - integrity sha512-JFYQurD/nbsA5BSPmbaOSLa3tSVj8L6o4srSwXXY3NqE+gGUNmmPTbhn8tjzcCtSqhFgIeqef81ngny8JM25hw== +engine.io@~6.5.2: + version "6.5.5" + resolved "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz#430b80d8840caab91a50e9e23cb551455195fc93" + integrity sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA== dependencies: "@types/cookie" "^0.4.1" "@types/cors" "^2.8.12" @@ -7596,126 +7750,147 @@ engine.io@~6.4.1: cookie "~0.4.1" cors "~2.8.5" debug "~4.3.1" - engine.io-parser "~5.0.3" - ws "~8.11.0" + engine.io-parser "~5.2.1" + ws "~8.17.1" enhanced-resolve@^4.0.0, enhanced-resolve@^4.5.0: version "4.5.0" - resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== dependencies: graceful-fs "^4.1.2" memory-fs "^0.5.0" tapable "^1.0.0" -enhanced-resolve@^5.10.0: - version "5.12.0" - resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz" - integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== +enhanced-resolve@^5.17.0: + version "5.17.0" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz#d037603789dd9555b89aaec7eb78845c49089bc5" + integrity sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" enquirer@^2.3.5, enquirer@^2.3.6: - version "2.3.6" - resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + version "2.4.1" + resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== dependencies: ansi-colors "^4.1.1" + strip-ansi "^6.0.1" ensure-posix-path@^1.0.0, ensure-posix-path@^1.0.1, ensure-posix-path@^1.0.2, ensure-posix-path@^1.1.0, ensure-posix-path@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz" + resolved "https://registry.npmjs.org/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz#3c62bdb19fa4681544289edb2b382adc029179ce" integrity sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw== entities@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" + resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== entities@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz" + resolved "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== -entities@~1.1.1: - version "1.1.2" - resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - entities@~2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz" + resolved "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== errlop@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/errlop/-/errlop-2.2.0.tgz" + resolved "https://registry.npmjs.org/errlop/-/errlop-2.2.0.tgz#1ff383f8f917ae328bebb802d6ca69666a42d21b" integrity sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw== errno@^0.1.3, errno@~0.1.7: version "0.1.8" - resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz" + resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== dependencies: prr "~1.0.1" error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" error@^7.0.0: version "7.2.1" - resolved "https://registry.npmjs.org/error/-/error-7.2.1.tgz" + resolved "https://registry.npmjs.org/error/-/error-7.2.1.tgz#eab21a4689b5f684fc83da84a0e390de82d94894" integrity sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA== dependencies: string-template "~0.2.1" -es-abstract@^1.19.0, es-abstract@^1.20.4: - version "1.21.1" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz" - integrity sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-set-tostringtag "^2.0.1" +es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2: + version "1.23.3" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" + integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + data-view-buffer "^1.0.1" + data-view-byte-length "^1.0.1" + data-view-byte-offset "^1.0.0" + es-define-property "^1.0.0" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-set-tostringtag "^2.0.3" es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.3" - get-symbol-description "^1.0.0" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.4" + get-symbol-description "^1.0.2" globalthis "^1.0.3" gopd "^1.0.1" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" has-symbols "^1.0.3" - internal-slot "^1.0.4" - is-array-buffer "^3.0.1" + hasown "^2.0.2" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" is-callable "^1.2.7" - is-negative-zero "^2.0.2" + is-data-view "^1.0.1" + is-negative-zero "^2.0.3" is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" + is-shared-array-buffer "^1.0.3" is-string "^1.0.7" - is-typed-array "^1.1.10" + is-typed-array "^1.1.13" is-weakref "^1.0.2" - object-inspect "^1.12.2" + object-inspect "^1.13.1" object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trimend "^1.0.6" - string.prototype.trimstart "^1.0.6" - typed-array-length "^1.0.4" + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.2" + safe-array-concat "^1.1.2" + safe-regex-test "^1.0.3" + string.prototype.trim "^1.2.9" + string.prototype.trimend "^1.0.8" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.2" + typed-array-byte-length "^1.0.1" + typed-array-byte-offset "^1.0.2" + typed-array-length "^1.0.6" unbox-primitive "^1.0.2" - which-typed-array "^1.1.9" + which-typed-array "^1.1.15" + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.2.1, es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es-get-iterator@^1.1.2: +es-get-iterator@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz" + resolved "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6" integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw== dependencies: call-bind "^1.0.2" @@ -7728,69 +7903,75 @@ es-get-iterator@^1.1.2: isarray "^2.0.5" stop-iteration-iterator "^1.0.0" -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-module-lexer@^1.2.1: + version "1.5.4" + resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" + integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== -es-set-tostringtag@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz" - integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== +es-object-atoms@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" + integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== dependencies: - get-intrinsic "^1.1.3" - has "^1.0.3" - has-tostringtag "^1.0.0" + es-errors "^1.3.0" + +es-set-tostringtag@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" + integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== + dependencies: + get-intrinsic "^1.2.4" + has-tostringtag "^1.0.2" + hasown "^2.0.1" es-to-primitive@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" + resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" is-symbol "^1.0.2" -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escalade@^3.1.1, escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== escape-html@~1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== escodegen@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz" - integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + version "2.1.0" + resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== dependencies: esprima "^4.0.1" estraverse "^5.2.0" esutils "^2.0.2" - optionator "^0.8.1" optionalDependencies: source-map "~0.6.1" eslint-config-prettier@^8.3.0: - version "8.7.0" - resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.7.0.tgz" - integrity sha512-HHVXLSlVUhMSmyW4ZzEuvjpwqamgmlfkutD53cYXLikh4pt/modINRcCIApJ84czDxM4GZInwUrromsDdTImTA== + version "8.10.0" + resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" + integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== eslint-plugin-ember@^10.5.8: version "10.6.1" - resolved "https://registry.npmjs.org/eslint-plugin-ember/-/eslint-plugin-ember-10.6.1.tgz" + resolved "https://registry.npmjs.org/eslint-plugin-ember/-/eslint-plugin-ember-10.6.1.tgz#04ea84cc82307f64a2faa4f2855b30e5ebf9f722" integrity sha512-R+TN3jwhYQ2ytZCA1VkfJDZSGgHFOHjsHU1DrBlRXYRepThe56PpuGxywAyDvQ7inhoAz3e6G6M60PzpvjzmNg== dependencies: "@ember-data/rfc395-data" "^0.0.4" @@ -7804,7 +7985,7 @@ eslint-plugin-ember@^10.5.8: eslint-plugin-es@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz" + resolved "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== dependencies: eslint-utils "^2.0.0" @@ -7812,7 +7993,7 @@ eslint-plugin-es@^3.0.0: eslint-plugin-node@^11.0.0: version "11.1.0" - resolved "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz" + resolved "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== dependencies: eslint-plugin-es "^3.0.0" @@ -7824,14 +8005,14 @@ eslint-plugin-node@^11.0.0: eslint-plugin-prettier@^3.4.1: version "3.4.1" - resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz" + resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== dependencies: prettier-linter-helpers "^1.0.0" eslint-plugin-qunit@^6.2.0: version "6.2.0" - resolved "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-6.2.0.tgz" + resolved "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-6.2.0.tgz#f4efda29da99523e560848d9592c39c0590c308d" integrity sha512-KvPmkIC2MHpfRxs/r8WUeeGkG6y+3qwSi2AZIBtjcM/YG6Z3k0GxW5Hbu3l7X0TDhljVCeBb9Q5puUkHzl83Mw== dependencies: eslint-utils "^3.0.0" @@ -7839,7 +8020,7 @@ eslint-plugin-qunit@^6.2.0: eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: esrecurse "^4.3.0" @@ -7847,7 +8028,7 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: eslint-scope@^4.0.3: version "4.0.3" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== dependencies: esrecurse "^4.1.0" @@ -7855,31 +8036,31 @@ eslint-scope@^4.0.3: eslint-utils@^2.0.0, eslint-utils@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz" + resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" eslint-utils@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" + resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== dependencies: eslint-visitor-keys "^2.0.0" eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== eslint-visitor-keys@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== eslint@^7.32.0: version "7.32.0" - resolved "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz" + resolved "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== dependencies: "@babel/code-frame" "7.12.11" @@ -7925,12 +8106,12 @@ eslint@^7.32.0: esm@^3.2.25, esm@^3.2.4: version "3.2.25" - resolved "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz" + resolved "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== espree@^7.3.0, espree@^7.3.1: version "7.3.1" - resolved "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz" + resolved "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== dependencies: acorn "^7.4.0" @@ -7939,71 +8120,71 @@ espree@^7.3.0, espree@^7.3.1: esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esprima@~3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz" + resolved "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz#53cf247acda77313e551c3aa2e73342d3fb4f7d9" integrity sha512-xoBq/MIShSydNZOkjkoCEjqod963yHNXTLC40ypBhop6yPqflPz/vTinmCfSrGcywVLnSftRf6a0kJLdFdzemw== esquery@^1.4.0: - version "1.5.0" - resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + version "1.6.0" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== dependencies: estraverse "^5.1.0" esrecurse@^4.1.0, esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^4.1.1: version "4.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.1.0, estraverse@^5.2.0: version "5.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== estree-walker@^0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz" + resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== etag@~1.8.1: version "1.8.1" - resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== eventemitter3@^4.0.0: version "4.0.7" - resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" + resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== events-to-array@^1.0.1: version "1.1.2" - resolved "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz" + resolved "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz#2d41f563e1fe400ed4962fe1a4d5c6a7539df7f6" integrity sha512-inRWzRY7nG+aXZxBzEqYKB3HPgwflZRopAjDCHv0whhRx+MTUr1ei0ICZUypdyE0HRm4L2d5VEcIqLD6yl+BFA== events@^3.0.0, events@^3.2.0: version "3.3.0" - resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" + resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz" + resolved "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" @@ -8011,12 +8192,12 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: exec-sh@^0.3.2: version "0.3.6" - resolved "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz" + resolved "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w== execa@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz" + resolved "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== dependencies: cross-spawn "^6.0.0" @@ -8029,7 +8210,7 @@ execa@^1.0.0: execa@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz" + resolved "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz#e5d3ecd837d2a60ec50f3da78fd39767747bbe99" integrity sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw== dependencies: cross-spawn "^7.0.0" @@ -8044,7 +8225,7 @@ execa@^2.0.0: execa@^3.0.0: version "3.4.0" - resolved "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz" + resolved "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz#c08ed4550ef65d858fac269ffc8572446f37eb89" integrity sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g== dependencies: cross-spawn "^7.0.0" @@ -8060,7 +8241,7 @@ execa@^3.0.0: execa@^4.0.0, execa@^4.0.3, execa@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz" + resolved "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== dependencies: cross-spawn "^7.0.0" @@ -8075,7 +8256,7 @@ execa@^4.0.0, execa@^4.0.3, execa@^4.1.0: execa@^5.0.0: version "5.1.1" - resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== dependencies: cross-spawn "^7.0.3" @@ -8090,17 +8271,17 @@ execa@^5.0.0: exists-sync@0.0.4: version "0.0.4" - resolved "https://registry.npmjs.org/exists-sync/-/exists-sync-0.0.4.tgz" + resolved "https://registry.npmjs.org/exists-sync/-/exists-sync-0.0.4.tgz#9744c2c428cc03b01060db454d4b12f0ef3c8879" integrity sha512-cy5z7K+05RFxHAWY37dSDkPWmuTi+VzrA/xLwPDHmwQPMnO/kVhu6jheGaItlnNRoOE6f5MAjxy3VEupfrHigQ== exit@^0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" + resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== expand-brackets@^2.1.4: version "2.1.4" - resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz" + resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== dependencies: debug "^2.3.3" @@ -8113,22 +8294,22 @@ expand-brackets@^2.1.4: expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz" + resolved "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw== dependencies: homedir-polyfill "^1.0.1" express@^4.10.7, express@^4.17.1: - version "4.18.2" - resolved "https://registry.npmjs.org/express/-/express-4.18.2.tgz" - integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + version "4.19.2" + resolved "https://registry.npmjs.org/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" + integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.1" + body-parser "1.20.2" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.5.0" + cookie "0.6.0" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" @@ -8157,14 +8338,14 @@ express@^4.10.7, express@^4.17.1: extend-shallow@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== dependencies: assign-symbols "^1.0.0" @@ -8172,12 +8353,12 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@^3.0.0, extend@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" + resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== external-editor@^3.0.3: version "3.1.0" - resolved "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz" + resolved "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== dependencies: chardet "^0.7.0" @@ -8186,7 +8367,7 @@ external-editor@^3.0.3: extglob@^2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz" + resolved "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" @@ -8200,37 +8381,37 @@ extglob@^2.0.4: extract-stack@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/extract-stack/-/extract-stack-2.0.0.tgz" + resolved "https://registry.npmjs.org/extract-stack/-/extract-stack-2.0.0.tgz#11367bc865bfcd9bc0db3123e5edb57786f11f9b" integrity sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ== fake-xml-http-request@^2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/fake-xml-http-request/-/fake-xml-http-request-2.1.2.tgz" + resolved "https://registry.npmjs.org/fake-xml-http-request/-/fake-xml-http-request-2.1.2.tgz#f1786720cae50bbb46273035a0173414f3e85e74" integrity sha512-HaFMBi7r+oEC9iJNpc3bvcW7Z7iLmM26hPDmlb0mFwyANSsOQAtJxbdWsXITKOzZUyMYK0zYCv3h5yDj9TsiXg== faker@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz" + resolved "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz#1e45bbbecc6774b3c195fad2835109c6d748cc3f" integrity sha512-ILKg69P6y/D8/wSmDXw35Ly0re8QzQ8pMfBCflsGiZG2ZjMUNLYNexA6lz5pkmJlepVdsiDFUxYAzPQ9/+iGLA== faker@^5.5.3: version "5.5.3" - resolved "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz" + resolved "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz#c57974ee484431b25205c2c8dc09fda861e51e0e" integrity sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g== fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + version "1.3.0" + resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== fast-glob@^2.2.6: version "2.2.7" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== dependencies: "@mrmlnc/readdir-enhanced" "^2.2.1" @@ -8240,10 +8421,10 @@ fast-glob@^2.2.6: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.0.3, fast-glob@^3.2.12, fast-glob@^3.2.5, fast-glob@^3.2.9: - version "3.2.12" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== +fast-glob@^3.0.3, fast-glob@^3.2.5, fast-glob@^3.2.9, fast-glob@^3.3.0: + version "3.3.2" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -8253,29 +8434,29 @@ fast-glob@^3.0.3, fast-glob@^3.2.12, fast-glob@^3.2.5, fast-glob@^3.2.9: fast-json-stable-stringify@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fast-memoize@^2.5.2: version "2.5.2" - resolved "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz" + resolved "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz#79e3bb6a4ec867ea40ba0e7146816f6cdce9b57e" integrity sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw== fast-ordered-set@^1.0.0, fast-ordered-set@^1.0.2: version "1.0.3" - resolved "https://registry.npmjs.org/fast-ordered-set/-/fast-ordered-set-1.0.3.tgz" + resolved "https://registry.npmjs.org/fast-ordered-set/-/fast-ordered-set-1.0.3.tgz#3fbb36634f7be79e4f7edbdb4a357dee25d184eb" integrity sha512-MxBW4URybFszOx1YlACEoK52P6lE3xiFcPaGCUZ7QQOZ6uJXKo++Se8wa31SjcZ+NC/fdAWX7UtKEfaGgHS2Vg== dependencies: blank-object "^1.0.1" fast-sourcemap-concat@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/fast-sourcemap-concat/-/fast-sourcemap-concat-1.4.0.tgz" + resolved "https://registry.npmjs.org/fast-sourcemap-concat/-/fast-sourcemap-concat-1.4.0.tgz#122c330d4a2afaff16ad143bc9674b87cd76c8ad" integrity sha512-x90Wlx/2C83lfyg7h4oguTZN4MyaVfaiUSJQNpU+YEA0Odf9u659Opo44b0LfoVg9G/bOE++GdID/dkyja+XcA== dependencies: chalk "^2.0.0" @@ -8288,9 +8469,9 @@ fast-sourcemap-concat@^1.4.0: sourcemap-validator "^1.1.0" fast-sourcemap-concat@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/fast-sourcemap-concat/-/fast-sourcemap-concat-2.1.0.tgz" - integrity sha512-L9uADEnnHOeF4U5Kc3gzEs3oFpNCFkiTJXvT+nKmR0zcFqHZJJbszWT7dv4t9558FJRGpCj8UxUpTgz2zwiIZA== + version "2.1.1" + resolved "https://registry.npmjs.org/fast-sourcemap-concat/-/fast-sourcemap-concat-2.1.1.tgz#3647fd5876deace53d9a1c418061199417911801" + integrity sha512-7h9/x25c6AQwdU3mA8MZDUMR3UCy50f237egBrBkuwjnUZSmfu4ptCf91PZSKzON2Uh5VvIHozYKWcPPgcjxIw== dependencies: chalk "^2.0.0" fs-extra "^5.0.0" @@ -8299,97 +8480,86 @@ fast-sourcemap-concat@^2.1.0: mkdirp "^0.5.0" source-map "^0.4.2" source-map-url "^0.3.0" - sourcemap-validator "^1.1.0" fastq@^1.6.0: - version "1.15.0" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz" - integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + version "1.17.1" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== dependencies: reusify "^1.0.4" fault@^1.0.0: version "1.0.4" - resolved "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz" + resolved "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== dependencies: format "^0.2.0" faye-websocket@^0.11.3: version "0.11.4" - resolved "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz" + resolved "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== dependencies: websocket-driver ">=0.5.1" fb-watchman@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz" + resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== dependencies: bser "2.1.1" figgy-pudding@^3.5.1: version "3.5.2" - resolved "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz" + resolved "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== figures@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz" + resolved "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== dependencies: escape-string-regexp "^1.0.5" figures@^3.0.0: version "3.2.0" - resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz" + resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== dependencies: escape-string-regexp "^1.0.5" file-entry-cache@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: flat-cache "^3.0.4" file-uri-to-path@1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" + resolved "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== filesize@^4.1.2: version "4.2.1" - resolved "https://registry.npmjs.org/filesize/-/filesize-4.2.1.tgz" + resolved "https://registry.npmjs.org/filesize/-/filesize-4.2.1.tgz#ab1cb2069db5d415911c1a13e144c0e743bc89bc" integrity sha512-bP82Hi8VRZX/TUBKfE24iiUGsB/sfm2WUrwTQyAzQrhO3V9IhcBBNBXMyzLY5orACxRyYJ3d2HeRVX+eFv4lmA== filesize@^6.1.0: version "6.4.0" - resolved "https://registry.npmjs.org/filesize/-/filesize-6.4.0.tgz" + resolved "https://registry.npmjs.org/filesize/-/filesize-6.4.0.tgz#914f50471dd66fdca3cefe628bd0cde4ef769bcd" integrity sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ== -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz" - integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" finalhandler@1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== dependencies: debug "2.6.9" @@ -8402,7 +8572,7 @@ finalhandler@1.1.2: finalhandler@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== dependencies: debug "2.6.9" @@ -8414,16 +8584,24 @@ finalhandler@1.2.0: unpipe "~1.0.0" find-babel-config@^1.1.0, find-babel-config@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz" - integrity sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA== + version "1.2.2" + resolved "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.2.tgz#41199b5cb9154dcb2fdc351cbe70eaf9198d5111" + integrity sha512-oK59njMyw2y3yxto1BCfVK7MQp/OYf4FleHu0RgosH3riFJ1aOuo/7naLDLAObfrgn3ueFhw5sAT/cp0QuJI3Q== dependencies: - json5 "^0.5.1" + json5 "^1.0.2" path-exists "^3.0.0" +find-babel-config@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.1.1.tgz#93703fc8e068db5e4c57592900c5715dd04b7e5b" + integrity sha512-5Ji+EAysHGe1OipH7GN4qDjok5Z1uw5KAwDCbicU/4wyTZY7CqOCzcWbG7J5ad9mazq67k89fXlbc1MuIfl9uA== + dependencies: + json5 "^2.2.3" + path-exists "^4.0.0" + find-cache-dir@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz" + resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== dependencies: commondir "^1.0.1" @@ -8432,7 +8610,7 @@ find-cache-dir@^2.1.0: find-cache-dir@^3.3.1: version "3.3.2" - resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz" + resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== dependencies: commondir "^1.0.1" @@ -8441,26 +8619,26 @@ find-cache-dir@^3.3.1: find-index@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/find-index/-/find-index-1.1.1.tgz" + resolved "https://registry.npmjs.org/find-index/-/find-index-1.1.1.tgz#4b221f8d46b7f8bea33d8faed953f3ca7a081cbc" integrity sha512-XYKutXMrIK99YMUPf91KX5QVJoG31/OsgftD6YoTPAObfQIxM4ziA9f0J1AsqKhJmo+IeaIPP0CFopTD4bdUBw== find-up@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" + resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== dependencies: locate-path "^2.0.0" find-up@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" + resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== dependencies: locate-path "^3.0.0" find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -8468,7 +8646,7 @@ find-up@^4.0.0, find-up@^4.1.0: find-up@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: locate-path "^6.0.0" @@ -8476,14 +8654,14 @@ find-up@^5.0.0: find-versions@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz" + resolved "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz#3c57e573bf97769b8cb8df16934b627915da4965" integrity sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ== dependencies: semver-regex "^3.1.2" -find-yarn-workspace-root@^1.1.0: +find-yarn-workspace-root@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz" + resolved "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== dependencies: fs-extra "^4.0.3" @@ -8491,14 +8669,14 @@ find-yarn-workspace-root@^1.1.0: find-yarn-workspace-root@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz" + resolved "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== dependencies: micromatch "^4.0.2" findup-sync@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz" + resolved "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz#956c9cdde804052b881b428512905c4a5f2cdef0" integrity sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ== dependencies: detect-file "^1.0.0" @@ -8506,9 +8684,9 @@ findup-sync@^4.0.0: micromatch "^4.0.2" resolve-dir "^1.0.1" -fireworm@^0.7.0: +fireworm@^0.7.2: version "0.7.2" - resolved "https://registry.npmjs.org/fireworm/-/fireworm-0.7.2.tgz" + resolved "https://registry.npmjs.org/fireworm/-/fireworm-0.7.2.tgz#bc5736515b48bd30bf3293a2062e0b0e0361537a" integrity sha512-GjebTzq+NKKhfmDxjKq3RXwQcN9xRmZWhnnuC9L+/x5wBQtR0aaQM50HsjrzJ2wc28v1vSdfOpELok0TKR4ddg== dependencies: async "~0.2.9" @@ -8519,7 +8697,7 @@ fireworm@^0.7.0: fixturify-project@^1.10.0: version "1.10.0" - resolved "https://registry.npmjs.org/fixturify-project/-/fixturify-project-1.10.0.tgz" + resolved "https://registry.npmjs.org/fixturify-project/-/fixturify-project-1.10.0.tgz#091c452a9bb15f09b6b9cc7cf5c0ad559f1d9aad" integrity sha512-L1k9uiBQuN0Yr8tA9Noy2VSQ0dfg0B8qMdvT7Wb5WQKc7f3dn3bzCbSrqlb+etLW+KDV4cBC7R1OvcMg3kcxmA== dependencies: fixturify "^1.2.0" @@ -8527,7 +8705,7 @@ fixturify-project@^1.10.0: fixturify-project@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/fixturify-project/-/fixturify-project-2.1.1.tgz" + resolved "https://registry.npmjs.org/fixturify-project/-/fixturify-project-2.1.1.tgz#a511dd26700c6b64ac271ef4393e7124f153c81f" integrity sha512-sP0gGMTr4iQ8Kdq5Ez0CVJOZOGWqzP5dv/veOTdFNywioKjkNWCHBi1q65DMpcNGUGeoOUWehyji274Q2wRgxA== dependencies: fixturify "^2.1.0" @@ -8536,7 +8714,7 @@ fixturify-project@^2.1.1: fixturify@^1.2.0: version "1.3.0" - resolved "https://registry.npmjs.org/fixturify/-/fixturify-1.3.0.tgz" + resolved "https://registry.npmjs.org/fixturify/-/fixturify-1.3.0.tgz#163c468093c7c4d90b70cde39fd6325f6528b25d" integrity sha512-tL0svlOy56pIMMUQ4bU1xRe6NZbFSa/ABTWMxW2mH38lFGc9TrNAKWcMBQ7eIjo3wqSS8f2ICabFaatFyFmrVQ== dependencies: "@types/fs-extra" "^5.0.5" @@ -8547,7 +8725,7 @@ fixturify@^1.2.0: fixturify@^2.1.0: version "2.1.1" - resolved "https://registry.npmjs.org/fixturify/-/fixturify-2.1.1.tgz" + resolved "https://registry.npmjs.org/fixturify/-/fixturify-2.1.1.tgz#e962d72f062600cb81a9651086f60d822c72d998" integrity sha512-SRgwIMXlxkb6AUgaVjIX+jCEqdhyXu9hah7mcK+lWynjKtX73Ux1TDv71B7XyaQ+LJxkYRHl5yCL8IycAvQRUw== dependencies: "@types/fs-extra" "^8.1.0" @@ -8558,26 +8736,27 @@ fixturify@^2.1.0: walk-sync "^2.0.2" flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + version "3.2.0" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== dependencies: - flatted "^3.1.0" + flatted "^3.2.9" + keyv "^4.5.3" rimraf "^3.0.2" flat@^5.0.0: version "5.0.2" - resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" + resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^3.1.0: - version "3.2.7" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== flush-write-stream@^1.0.0: version "1.1.1" - resolved "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz" + resolved "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== dependencies: inherits "^2.0.3" @@ -8585,36 +8764,36 @@ flush-write-stream@^1.0.0: focus-trap@^6.7.1: version "6.9.4" - resolved "https://registry.npmjs.org/focus-trap/-/focus-trap-6.9.4.tgz" + resolved "https://registry.npmjs.org/focus-trap/-/focus-trap-6.9.4.tgz#436da1a1d935c48b97da63cd8f361c6f3aa16444" integrity sha512-v2NTsZe2FF59Y+sDykKY+XjqZ0cPfhq/hikWVL88BqLivnNiEffAsac6rP6H45ff9wG9LL5ToiDqrLEP9GX9mw== dependencies: tabbable "^5.3.3" focusable-selectors@^0.3.0: version "0.3.1" - resolved "https://registry.npmjs.org/focusable-selectors/-/focusable-selectors-0.3.1.tgz" + resolved "https://registry.npmjs.org/focusable-selectors/-/focusable-selectors-0.3.1.tgz#7eacbca8dc6cc8d7f7563e5f5cc3699b91e20aaa" integrity sha512-5JLtr0e1YJIfmnVlpLiG+av07dd0Xkf/KfswsXcei5KmLfdwOysTQsjF058ynXniujb1fvev7nql1x+CkC5ikw== follow-redirects@^1.0.0: - version "1.15.2" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + version "1.15.6" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== for-each@^0.3.3: version "0.3.3" - resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" for-in@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" + resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== form-data@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz" + resolved "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== dependencies: asynckit "^0.4.0" @@ -8623,34 +8802,34 @@ form-data@^3.0.0: format@^0.2.0: version "0.2.2" - resolved "https://registry.npmjs.org/format/-/format-0.2.2.tgz" + resolved "https://registry.npmjs.org/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== forwarded@0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" + resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fraction.js@^4.2.0: - version "4.2.0" - resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz" - integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== +fraction.js@^4.3.7: + version "4.3.7" + resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" + integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== fragment-cache@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz" + resolved "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" - resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== from2@^2.1.0: version "2.3.0" - resolved "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz" + resolved "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" integrity sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g== dependencies: inherits "^2.0.1" @@ -8658,7 +8837,7 @@ from2@^2.1.0: fs-extra@^0.24.0: version "0.24.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-0.24.0.tgz" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-0.24.0.tgz#d4e4342a96675cb7846633a6099249332b539952" integrity sha512-w1RvhdLZdU9V3vQdL+RooGlo6b9R9WVoBanOfoJvosWlqSKvrjFlci2oVhwvLwZXBtM7khyPvZ8r3fwsim3o0A== dependencies: graceful-fs "^4.1.2" @@ -8668,7 +8847,7 @@ fs-extra@^0.24.0: fs-extra@^10.0.0: version "10.1.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: graceful-fs "^4.2.0" @@ -8677,7 +8856,7 @@ fs-extra@^10.0.0: fs-extra@^4.0.2, fs-extra@^4.0.3: version "4.0.3" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== dependencies: graceful-fs "^4.1.2" @@ -8686,7 +8865,7 @@ fs-extra@^4.0.2, fs-extra@^4.0.3: fs-extra@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== dependencies: graceful-fs "^4.1.2" @@ -8695,7 +8874,7 @@ fs-extra@^5.0.0: fs-extra@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" integrity sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA== dependencies: graceful-fs "^4.1.2" @@ -8704,7 +8883,7 @@ fs-extra@^6.0.1: fs-extra@^7.0.0, fs-extra@^7.0.1: version "7.0.1" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== dependencies: graceful-fs "^4.1.2" @@ -8713,7 +8892,7 @@ fs-extra@^7.0.0, fs-extra@^7.0.1: fs-extra@^8.0.0, fs-extra@^8.0.1, fs-extra@^8.1.0: version "8.1.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== dependencies: graceful-fs "^4.2.0" @@ -8722,7 +8901,7 @@ fs-extra@^8.0.0, fs-extra@^8.0.1, fs-extra@^8.1.0: fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0: version "9.1.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== dependencies: at-least-node "^1.0.0" @@ -8732,7 +8911,7 @@ fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0: fs-merger@^3.0.1, fs-merger@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/fs-merger/-/fs-merger-3.2.1.tgz" + resolved "https://registry.npmjs.org/fs-merger/-/fs-merger-3.2.1.tgz#a225b11ae530426138294b8fbb19e82e3d4e0b3b" integrity sha512-AN6sX12liy0JE7C2evclwoo0aCG3PFulLjrTLsJpWh/2mM+DinhpSGqYLbHBBbIW1PLRNcFhJG8Axtz8mQW3ug== dependencies: broccoli-node-api "^1.7.0" @@ -8743,7 +8922,7 @@ fs-merger@^3.0.1, fs-merger@^3.2.1: fs-tree-diff@^0.5.2, fs-tree-diff@^0.5.3, fs-tree-diff@^0.5.4, fs-tree-diff@^0.5.6: version "0.5.9" - resolved "https://registry.npmjs.org/fs-tree-diff/-/fs-tree-diff-0.5.9.tgz" + resolved "https://registry.npmjs.org/fs-tree-diff/-/fs-tree-diff-0.5.9.tgz#a4ec6182c2f5bd80b9b83c8e23e4522e6f5fd946" integrity sha512-872G8ax0kHh01m9n/2KDzgYwouKza0Ad9iFltBpNykvROvf2AGtoOzPJgGx125aolGPER3JuC7uZFrQ7bG1AZw== dependencies: heimdalljs-logger "^0.1.7" @@ -8753,7 +8932,7 @@ fs-tree-diff@^0.5.2, fs-tree-diff@^0.5.3, fs-tree-diff@^0.5.4, fs-tree-diff@^0.5 fs-tree-diff@^2.0.0, fs-tree-diff@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/fs-tree-diff/-/fs-tree-diff-2.0.1.tgz" + resolved "https://registry.npmjs.org/fs-tree-diff/-/fs-tree-diff-2.0.1.tgz#343e4745ab435ec39ebac5f9059ad919cd034afa" integrity sha512-x+CfAZ/lJHQqwlD64pYM5QxWjzWhSjroaVsr8PW831zOApL55qPibed0c+xebaLWVr2BnHFoHdrwOv8pzt8R5A== dependencies: "@types/symlink-or-copy" "^1.2.0" @@ -8764,7 +8943,7 @@ fs-tree-diff@^2.0.0, fs-tree-diff@^2.0.1: fs-updater@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/fs-updater/-/fs-updater-1.0.4.tgz" + resolved "https://registry.npmjs.org/fs-updater/-/fs-updater-1.0.4.tgz#2329980f99ae9176e9a0e84f7637538a182ce63b" integrity sha512-0pJX4mJF/qLsNEwTct8CdnnRdagfb+LmjRPJ8sO+nCnAZLW0cTmz4rTgU25n+RvTuWSITiLKrGVJceJPBIPlKg== dependencies: can-symlink "^1.0.0" @@ -8775,7 +8954,7 @@ fs-updater@^1.0.4: fs-write-stream-atomic@^1.0.8: version "1.0.10" - resolved "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz" + resolved "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" integrity sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA== dependencies: graceful-fs "^4.1.2" @@ -8785,55 +8964,55 @@ fs-write-stream-atomic@^1.0.8: fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^1.2.7: version "1.2.13" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== dependencies: bindings "^1.5.0" nan "^2.12.1" fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== +function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" functional-red-black-tree@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" + resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== -functions-have-names@^1.2.2: +functions-have-names@^1.2.3: version "1.2.3" - resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz" + resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== fuse.js@^6.4.6: version "6.6.2" - resolved "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz" + resolved "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz#fe463fed4b98c0226ac3da2856a415576dc9a111" integrity sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA== gauge@^4.0.3: version "4.0.4" - resolved "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz" + resolved "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== dependencies: aproba "^1.0.3 || ^2.0.0" @@ -8847,7 +9026,7 @@ gauge@^4.0.3: gauge@~2.7.3: version "2.7.4" - resolved "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz" + resolved "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== dependencies: aproba "^1.0.3" @@ -8861,93 +9040,96 @@ gauge@~2.7.3: gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz" - integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== +get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== dependencies: - function-bind "^1.1.1" - has "^1.0.3" + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" has-symbols "^1.0.3" + hasown "^2.0.0" get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" - resolved "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz" + resolved "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== get-package-type@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" + resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== get-stdin@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" + resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" integrity sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw== get-stdin@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz" + resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== get-stream@^4.0.0: version "4.1.0" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== dependencies: pump "^3.0.0" get-stream@^5.0.0: version "5.2.0" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" get-stream@^6.0.0: version "6.0.1" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== +get-symbol-description@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" + integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" + call-bind "^1.0.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" - resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz" + resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== git-hooks-list@1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz" + resolved "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz#be5baaf78203ce342f2f844a9d2b03dba1b45156" integrity sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ== git-repo-info@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/git-repo-info/-/git-repo-info-2.1.1.tgz" + resolved "https://registry.npmjs.org/git-repo-info/-/git-repo-info-2.1.1.tgz#220ffed8cbae74ef8a80e3052f2ccb5179aed058" integrity sha512-8aCohiDo4jwjOwma4FmYFd3i97urZulL8XL24nIPxuE+GZnfsAyy/g2Shqx6OjUiFKUXZM+Yy+KHnOmmA3FVcg== github-slugger@^1.0.0, github-slugger@^1.2.1, github-slugger@^1.3.0: version "1.5.0" - resolved "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz" + resolved "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz#17891bbc73232051474d68bd867a34625c955f7d" integrity sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw== glob-parent@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" integrity sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA== dependencies: is-glob "^3.1.0" @@ -8955,42 +9137,31 @@ glob-parent@^3.1.0: glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob-parent@^6.0.2: version "6.0.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== dependencies: is-glob "^4.0.3" glob-to-regexp@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz" + resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig== glob-to-regexp@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" + resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^5.0.10: - version "5.0.15" - resolved "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz" - integrity sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA== - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.4, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.3: +glob@7.2.3, glob@^10.3.10, glob@^5.0.10, glob@^7.0.4, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7, glob@^7.2.3, glob@^9.3.3: version "7.2.3" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -9002,7 +9173,7 @@ glob@^7.0.4, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, gl global-modules@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz" + resolved "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== dependencies: global-prefix "^1.0.1" @@ -9011,7 +9182,7 @@ global-modules@^1.0.0: global-prefix@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz" + resolved "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" integrity sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg== dependencies: expand-tilde "^2.0.2" @@ -9022,36 +9193,37 @@ global-prefix@^1.0.1: globals@^11.1.0: version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^13.6.0, globals@^13.9.0: - version "13.20.0" - resolved "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + version "13.24.0" + resolved "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== dependencies: type-fest "^0.20.2" globals@^9.18.0: version "9.18.0" - resolved "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz" + resolved "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== globalthis@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz" - integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + version "1.0.4" + resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== dependencies: - define-properties "^1.1.3" + define-properties "^1.2.1" + gopd "^1.0.1" globalyzer@0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz" + resolved "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465" integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q== globby@10.0.0: version "10.0.0" - resolved "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz" + resolved "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz#abfcd0630037ae174a88590132c2f6804e291072" integrity sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw== dependencies: "@types/glob" "^7.1.1" @@ -9065,7 +9237,7 @@ globby@10.0.0: globby@^11.0.2, globby@^11.0.3: version "11.1.0" - resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" @@ -9077,45 +9249,45 @@ globby@^11.0.2, globby@^11.0.3: globrex@^0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz" + resolved "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg== good-listener@^1.2.2: version "1.2.2" - resolved "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz" + resolved "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" integrity sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw== dependencies: delegate "^3.1.2" gopd@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: - version "4.2.10" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== "graceful-readlink@>= 1.0.0": version "1.0.1" - resolved "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" + resolved "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" integrity sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w== growly@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz" + resolved "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw== handlebars@^4.0.13, handlebars@^4.0.4, handlebars@^4.3.1, handlebars@^4.4.2, handlebars@^4.7.3: - version "4.7.7" - resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + version "4.7.8" + resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== dependencies: minimist "^1.2.5" - neo-async "^2.6.0" + neo-async "^2.6.2" source-map "^0.6.1" wordwrap "^1.0.0" optionalDependencies: @@ -9123,78 +9295,73 @@ handlebars@^4.0.13, handlebars@^4.0.4, handlebars@^4.3.1, handlebars@^4.4.2, han has-ansi@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz" + resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== dependencies: ansi-regex "^2.0.0" has-ansi@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-3.0.0.tgz" + resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-3.0.0.tgz#36077ef1d15f333484aa7fa77a28606f1c655b37" integrity sha512-5JRDTvNq6mVkaMHQVXrGnaCXHD6JfqxwCy8LA/DQSqLLqePR9uaJVm2u3Ek/UziJFQz+d1ul99RtfIhE2aorkQ== dependencies: ansi-regex "^3.0.0" has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz" + resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== -has-color@~0.1.0: - version "0.1.7" - resolved "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz" - integrity sha512-kaNz5OTAYYmt646Hkqw50/qyxP2vFnTVu5AQ1Zmk22Kk5+4Qx6BpO8+u7IKsML5fOsFk0ZT0AcCJNYwcvaLBvw== - -has-dynamic-import@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/has-dynamic-import/-/has-dynamic-import-2.0.1.tgz" - integrity sha512-X3fbtsZmwb6W7fJGR9o7x65fZoodygCrZ3TVycvghP62yYQfS0t4RS0Qcz+j5tQYUKeSWS09tHkWW6WhFV3XhQ== +has-dynamic-import@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/has-dynamic-import/-/has-dynamic-import-2.1.0.tgz#06359ad7672b9e764aea93a54bb9d6e17542d34c" + integrity sha512-su0anMkNEnJKZ/rB99jn3y6lV/J8Ro96hBJ28YAeVzj5rWxH+YL/AdCyiYYA1HDLV9YhmvqpWSJJj2KLo1MX6g== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" + call-bind "^1.0.5" + get-intrinsic "^1.2.2" has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: - get-intrinsic "^1.1.1" + es-define-property "^1.0.0" -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== +has-proto@^1.0.1, has-proto@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== +has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== dependencies: - has-symbols "^1.0.2" + has-symbols "^1.0.3" has-unicode@^2.0.0, has-unicode@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" + resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== has-value@^0.3.1: version "0.3.1" - resolved "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz" + resolved "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== dependencies: get-value "^2.0.3" @@ -9203,7 +9370,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz" + resolved "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== dependencies: get-value "^2.0.6" @@ -9212,36 +9379,37 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz" + resolved "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== has-values@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz" + resolved "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== dependencies: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - hash-base@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz" + resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== dependencies: inherits "^2.0.4" readable-stream "^3.6.0" safe-buffer "^5.2.0" +hash-base@~3.0: + version "3.0.4" + resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + hash-for-dep@^1.0.2, hash-for-dep@^1.2.3, hash-for-dep@^1.4.7, hash-for-dep@^1.5.0, hash-for-dep@^1.5.1: version "1.5.1" - resolved "https://registry.npmjs.org/hash-for-dep/-/hash-for-dep-1.5.1.tgz" + resolved "https://registry.npmjs.org/hash-for-dep/-/hash-for-dep-1.5.1.tgz#497754b39bee2f1c4ade4521bfd2af0a7c1196e3" integrity sha512-/dQ/A2cl7FBPI2pO0CANkvuuVi/IFS5oTyJ0PsOb6jW6WbVW1js5qJXMJTNbWHXBIPdFTWFbabjB+mE0d+gelw== dependencies: broccoli-kitchen-sink-helpers "^0.3.1" @@ -9253,25 +9421,32 @@ hash-for-dep@^1.0.2, hash-for-dep@^1.2.3, hash-for-dep@^1.4.7, hash-for-dep@^1.5 hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" - resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" + resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + hast-util-is-element@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz" + resolved "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz#3b3ed5159a2707c6137b48637fbfe068e175a425" integrity sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ== hast-util-parse-selector@^2.0.0: version "2.2.5" - resolved "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz" + resolved "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a" integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== hast-util-to-html@^7.1.1: version "7.1.3" - resolved "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-7.1.3.tgz" + resolved "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-7.1.3.tgz#9f339ca9bea71246e565fc79ff7dbfe98bb50f5e" integrity sha512-yk2+1p3EJTEE9ZEUkgHsUSVhIpCsL/bvT8E5GzmWc+N1Po5gBw+0F8bo7dpxXR0nu0bQVxVZGX2lBGF21CmeDw== dependencies: ccount "^1.0.0" @@ -9287,17 +9462,17 @@ hast-util-to-html@^7.1.1: hast-util-to-string@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-1.0.4.tgz" + resolved "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-1.0.4.tgz#9b24c114866bdb9478927d7e9c36a485ac728378" integrity sha512-eK0MxRX47AV2eZ+Lyr18DCpQgodvaS3fAQO2+b9Two9F5HEoRPhiUMNzoXArMJfZi2yieFzUBMRl3HNJ3Jus3w== hast-util-whitespace@^1.0.0: version "1.0.4" - resolved "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz" + resolved "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz#e4fe77c4a9ae1cb2e6c25e02df0043d0164f6e41" integrity sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A== hastscript@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz" + resolved "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" integrity sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w== dependencies: "@types/hast" "^2.0.0" @@ -9308,7 +9483,7 @@ hastscript@^6.0.0: heimdalljs-fs-monitor@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/heimdalljs-fs-monitor/-/heimdalljs-fs-monitor-1.1.1.tgz" + resolved "https://registry.npmjs.org/heimdalljs-fs-monitor/-/heimdalljs-fs-monitor-1.1.1.tgz#bb4021007e88484202402cdf594e3962d70dc4f4" integrity sha512-BHB8oOXLRlrIaON0MqJSEjGVPDyqt2Y6gu+w2PaEZjrCxeVtZG7etEZp7M4ZQ80HNvnr66KIQ2lot2qdeG8HgQ== dependencies: callsites "^3.1.0" @@ -9319,12 +9494,12 @@ heimdalljs-fs-monitor@^1.1.0: heimdalljs-graph@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/heimdalljs-graph/-/heimdalljs-graph-1.0.0.tgz" + resolved "https://registry.npmjs.org/heimdalljs-graph/-/heimdalljs-graph-1.0.0.tgz#0059857952988e54f3a74bb23edaf669f8eaf6af" integrity sha512-v2AsTERBss0ukm/Qv4BmXrkwsT5x6M1V5Om6E8NcDQ/ruGkERsfsuLi5T8jx8qWzKMGYlwzAd7c/idymxRaPzA== heimdalljs-logger@^0.1.10, heimdalljs-logger@^0.1.7, heimdalljs-logger@^0.1.9: version "0.1.10" - resolved "https://registry.npmjs.org/heimdalljs-logger/-/heimdalljs-logger-0.1.10.tgz" + resolved "https://registry.npmjs.org/heimdalljs-logger/-/heimdalljs-logger-0.1.10.tgz#90cad58aabb1590a3c7e640ddc6a4cd3a43faaf7" integrity sha512-pO++cJbhIufVI/fmB/u2Yty3KJD0TqNPecehFae0/eps0hkZ3b4Zc/PezUMOpYuHFQbA7FxHZxa305EhmjLj4g== dependencies: debug "^2.2.0" @@ -9332,14 +9507,14 @@ heimdalljs-logger@^0.1.10, heimdalljs-logger@^0.1.7, heimdalljs-logger@^0.1.9: heimdalljs@^0.2.0, heimdalljs@^0.2.1, heimdalljs@^0.2.3, heimdalljs@^0.2.5, heimdalljs@^0.2.6: version "0.2.6" - resolved "https://registry.npmjs.org/heimdalljs/-/heimdalljs-0.2.6.tgz" + resolved "https://registry.npmjs.org/heimdalljs/-/heimdalljs-0.2.6.tgz#b0eebabc412813aeb9542f9cc622cb58dbdcd9fe" integrity sha512-o9bd30+5vLBvBtzCPwwGqpry2+n0Hi6H1+qwt6y+0kwRHGGF8TFIhJPmnuM0xO97zaKrDZMwO/V56fAnn8m/tA== dependencies: rsvp "~3.2.1" hmac-drbg@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" + resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" @@ -9348,7 +9523,7 @@ hmac-drbg@^1.0.1: home-or-tmp@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz" + resolved "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" integrity sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg== dependencies: os-homedir "^1.0.0" @@ -9356,50 +9531,50 @@ home-or-tmp@^2.0.0: homedir-polyfill@^1.0.1: version "1.0.3" - resolved "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz" + resolved "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== dependencies: parse-passwd "^1.0.0" hosted-git-info@^2.1.4: version "2.8.9" - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz" + resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== hosted-git-info@^3.0.8: version "3.0.8" - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz" + resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz#6e35d4cc87af2c5f816e4cb9ce350ba87a3f370d" integrity sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw== dependencies: lru-cache "^6.0.0" hosted-git-info@^4.0.1: version "4.1.0" - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz" + resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== dependencies: lru-cache "^6.0.0" html-encoding-sniffer@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz" + resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== dependencies: whatwg-encoding "^1.0.5" html-escaper@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" + resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== html-void-elements@^1.0.0: version "1.0.5" - resolved "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz" + resolved "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== htmlparser2@^7.2.0: version "7.2.0" - resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz" + resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz#8817cdea38bbc324392a90b1990908e81a65f5a5" integrity sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog== dependencies: domelementtype "^2.0.1" @@ -9409,7 +9584,7 @@ htmlparser2@^7.2.0: http-errors@2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: depd "2.0.0" @@ -9420,7 +9595,7 @@ http-errors@2.0.0: http-errors@~1.6.2: version "1.6.3" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== dependencies: depd "~1.1.2" @@ -9430,12 +9605,12 @@ http-errors@~1.6.2: http-parser-js@>=0.5.1: version "0.5.8" - resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz" + resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== http-proxy-agent@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz" + resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== dependencies: "@tootallnate/once" "1" @@ -9444,7 +9619,7 @@ http-proxy-agent@^4.0.1: http-proxy@^1.13.1, http-proxy@^1.18.1: version "1.18.1" - resolved "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz" + resolved "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== dependencies: eventemitter3 "^4.0.0" @@ -9453,12 +9628,12 @@ http-proxy@^1.13.1, http-proxy@^1.18.1: https-browserify@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz" + resolved "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== https-proxy-agent@^5.0.0: version "5.0.1" - resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" @@ -9466,22 +9641,22 @@ https-proxy-agent@^5.0.0: https@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/https/-/https-1.0.0.tgz" + resolved "https://registry.npmjs.org/https/-/https-1.0.0.tgz#3c37c7ae1a8eeb966904a2ad1e975a194b7ed3a4" integrity sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg== human-signals@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz" + resolved "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== human-signals@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== husky@^4.2.5: version "4.3.8" - resolved "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz" + resolved "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz#31144060be963fd6850e5cc8f019a1dfe194296d" integrity sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow== dependencies: chalk "^4.0.0" @@ -9497,44 +9672,44 @@ husky@^4.2.5: iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" - resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" icss-utils@^5.0.0, icss-utils@^5.1.0: version "5.1.0" - resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz" + resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== ieee754@^1.1.13, ieee754@^1.1.4: version "1.2.1" - resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" + resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== iferr@^0.1.5: version "0.1.5" - resolved "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz" + resolved "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" integrity sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA== ignore@^4.0.6: version "4.0.6" - resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz" + resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== ignore@^5.1.1, ignore@^5.2.0: - version "5.2.4" - resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz" - integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + version "5.3.1" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== immutable@^4.0.0: - version "4.3.0" - resolved "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz" - integrity sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg== + version "4.3.6" + resolved "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz#6a05f7858213238e587fb83586ffa3b4b27f0447" + integrity sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ== import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" @@ -9542,32 +9717,32 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== include-path-searcher@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/include-path-searcher/-/include-path-searcher-0.1.0.tgz" + resolved "https://registry.npmjs.org/include-path-searcher/-/include-path-searcher-0.1.0.tgz#c0cf2ddfa164fb2eae07bc7ca43a7f191cb4d7bd" integrity sha512-KlpXnsZOrBGo4PPKqPFi3Ft6dcRyh8fTaqgzqDRi8jKAsngJEWWOxeFIWC8EfZtXKaZqlsNf9XRwcQ49DVgl/g== indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== infer-owner@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz" + resolved "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== inflection@^1.12.0, inflection@~1.13.1: version "1.13.4" - resolved "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz" + resolved "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz#65aa696c4e2da6225b148d7a154c449366633a32" integrity sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -9575,27 +9750,22 @@ inflight@^1.0.4: inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - integrity sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA== - inherits@2.0.3: version "2.0.3" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== ini@^1.3.4: version "1.3.8" - resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" + resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== inline-source-map-comment@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/inline-source-map-comment/-/inline-source-map-comment-1.0.5.tgz" + resolved "https://registry.npmjs.org/inline-source-map-comment/-/inline-source-map-comment-1.0.5.tgz#50a8a44c2a790dfac441b5c94eccd5462635faf6" integrity sha512-a3/m6XgooVCXkZCduOb7pkuvUtNKt4DaqaggKKJrMQHQsqt6JcJXEreExeZiiK4vWL/cM/uF6+chH05pz2/TdQ== dependencies: chalk "^1.0.0" @@ -9606,7 +9776,7 @@ inline-source-map-comment@^1.0.5: inquirer@^6: version "6.5.2" - resolved "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz" + resolved "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== dependencies: ansi-escapes "^3.2.0" @@ -9625,7 +9795,7 @@ inquirer@^6: inquirer@^7.3.3: version "7.3.3" - resolved "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz" + resolved "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== dependencies: ansi-escapes "^4.2.1" @@ -9642,23 +9812,28 @@ inquirer@^7.3.3: strip-ansi "^6.0.0" through "^2.3.6" -internal-slot@^1.0.3, internal-slot@^1.0.4: - version "1.0.5" - resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz" - integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== +internal-slot@^1.0.4, internal-slot@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" + integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== dependencies: - get-intrinsic "^1.2.0" - has "^1.0.3" + es-errors "^1.3.0" + hasown "^2.0.0" side-channel "^1.0.4" +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + internmap@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz" + resolved "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95" integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== intl-messageformat-parser@^6.0.5: version "6.4.4" - resolved "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-6.4.4.tgz" + resolved "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-6.4.4.tgz#abbd94e96dc4ff41607376bfab024553450cc1e0" integrity sha512-7AaFKNZEfzLQR6+jivOuz9e7yA8ka5KrmLebgY4QHTRLf8r64dp3LjnW98LkBWjdk8GK0sawD2dHDqW++A/pXA== dependencies: "@formatjs/ecma402-abstract" "1.6.4" @@ -9666,7 +9841,7 @@ intl-messageformat-parser@^6.0.5: intl-messageformat@^9.3.6: version "9.13.0" - resolved "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-9.13.0.tgz" + resolved "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-9.13.0.tgz#97360b73bd82212e4f6005c712a4a16053165468" integrity sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw== dependencies: "@formatjs/ecma402-abstract" "1.11.4" @@ -9676,38 +9851,31 @@ intl-messageformat@^9.3.6: invariant@^2.2.2: version "2.2.4" - resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz" + resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" ipaddr.js@1.9.1: version "1.9.1" - resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz" - integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== +is-accessor-descriptor@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz#3223b10628354644b86260db29b3e693f5ceedd4" + integrity sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA== dependencies: - kind-of "^6.0.0" + hasown "^2.0.0" is-alphabetical@^1.0.0: version "1.0.4" - resolved "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz" + resolved "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== is-alphanumerical@^1.0.0: version "1.0.4" - resolved "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz" + resolved "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== dependencies: is-alphabetical "^1.0.0" @@ -9715,50 +9883,49 @@ is-alphanumerical@^1.0.0: is-arguments@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" + resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== dependencies: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-array-buffer@^3.0.1: - version "3.0.2" - resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz" - integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== +is-array-buffer@^3.0.2, is-array-buffer@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" + integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== dependencies: call-bind "^1.0.2" - get-intrinsic "^1.2.0" - is-typed-array "^1.1.10" + get-intrinsic "^1.2.1" is-arrayish@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-bigint@^1.0.1: version "1.0.4" - resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" + resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== dependencies: has-bigints "^1.0.1" is-binary-path@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" integrity sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q== dependencies: binary-extensions "^1.0.0" is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" is-boolean-object@^1.1.0: version "1.1.2" - resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz" + resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== dependencies: call-bind "^1.0.2" @@ -9766,212 +9933,210 @@ is-boolean-object@^1.1.0: is-buffer@^1.1.5: version "1.1.6" - resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-buffer@^2.0.0: version "2.0.5" - resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" + resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" - resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.13.0, is-core-module@^2.9.0: - version "2.13.0" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz" - integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== +is-core-module@^2.13.0: + version "2.14.0" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" + integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== dependencies: - has "^1.0.3" + hasown "^2.0.2" -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz" - integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== +is-data-descriptor@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz#2109164426166d32ea38c405c1e0945d9e6a4eeb" + integrity sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw== dependencies: - kind-of "^3.0.2" + hasown "^2.0.0" -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== +is-data-view@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" + integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== dependencies: - kind-of "^6.0.0" + is-typed-array "^1.1.13" is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" + resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== dependencies: has-tostringtag "^1.0.0" is-decimal@^1.0.0: version "1.0.4" - resolved "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz" + resolved "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + version "0.1.7" + resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz#2727eb61fd789dcd5bdf0ed4569f551d2fe3be33" + integrity sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg== dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" + is-accessor-descriptor "^1.0.1" + is-data-descriptor "^1.0.1" is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + version "1.0.3" + resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz#92d27cb3cd311c4977a4db47df457234a13cb306" + integrity sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw== dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" + is-accessor-descriptor "^1.0.1" + is-data-descriptor "^1.0.1" is-docker@^2.0.0: version "2.2.1" - resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" + resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== is-extendable@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-finite@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz" + resolved "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== is-fullwidth-code-point@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-git-url@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-git-url/-/is-git-url-1.0.0.tgz" + resolved "https://registry.npmjs.org/is-git-url/-/is-git-url-1.0.0.tgz#53f684cd143285b52c3244b4e6f28253527af66b" integrity sha512-UCFta9F9rWFSavp9H3zHEHrARUfZbdJvmHKeEpds4BK3v7W2LdXoNypMtXXi5w5YBDEBCTYmbI+vsSwI8LYJaQ== is-glob@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" integrity sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw== dependencies: is-extglob "^2.1.0" is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-hexadecimal@^1.0.0: version "1.0.4" - resolved "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz" + resolved "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== is-interactive@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz" + resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== is-language-code@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/is-language-code/-/is-language-code-2.0.0.tgz" + resolved "https://registry.npmjs.org/is-language-code/-/is-language-code-2.0.0.tgz#6f4d59c551d73b98c45cf9f1d3ce65cee060e65b" integrity sha512-6xKmRRcP2YdmMBZMVS3uiJRPQgcMYolkD6hFw2Y4KjqyIyaJlCGxUt56tuu0iIV8q9r8kMEo0Gjd/GFwKrgjbw== -is-map@^2.0.1, is-map@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz" - integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== +is-map@^2.0.2, is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== +is-negative-zero@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== is-number-object@^1.0.4: version "1.0.7" - resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz" + resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== dependencies: has-tostringtag "^1.0.0" is-number@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz" + resolved "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== dependencies: kind-of "^3.0.2" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-obj@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz" + resolved "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== is-obj@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz" + resolved "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== is-plain-obj@2.1.0, is-plain-obj@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== is-plain-obj@^1.1: version "1.1.0" - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-potential-custom-element-name@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz" + resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== is-regex@^1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" + resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== dependencies: call-bind "^1.0.2" @@ -9979,155 +10144,151 @@ is-regex@^1.1.4: is-regexp@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz" + resolved "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== -is-set@^2.0.1, is-set@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz" - integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== +is-set@^2.0.2, is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== +is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" + integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== dependencies: - call-bind "^1.0.2" + call-bind "^1.0.7" is-stream@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== is-stream@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" + resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== dependencies: has-tostringtag "^1.0.0" is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz" + resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== dependencies: has-symbols "^1.0.2" is-type@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/is-type/-/is-type-0.0.1.tgz" + resolved "https://registry.npmjs.org/is-type/-/is-type-0.0.1.tgz#f651d85c365d44955d14a51d8d7061f3f6b4779c" integrity sha512-YwJh/zBVrcJ90aAnPBM0CbHvm7lG9ao7lIFeqTZ1UQj4iFLpM5CikdaU+dGGesrMJwxLqPGmjjrUrQ6Kn3Zh+w== dependencies: core-util-is "~1.0.0" -is-typed-array@^1.1.10, is-typed-array@^1.1.9: - version "1.1.10" - resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== +is-typed-array@^1.1.13: + version "1.1.13" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" + which-typed-array "^1.1.14" is-typedarray@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== is-unicode-supported@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-weakmap@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz" - integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== is-weakref@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz" + resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== dependencies: call-bind "^1.0.2" -is-weakset@^2.0.1: - version "2.0.2" - resolved "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz" - integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg== +is-weakset@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" + integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" + call-bind "^1.0.7" + get-intrinsic "^1.2.4" is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz" + resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== is-wsl@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz" + resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== is-wsl@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" + resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== dependencies: is-docker "^2.0.0" isarray@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isarray@^2.0.5: version "2.0.5" - resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" + resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== isbinaryfile@^4.0.6: version "4.0.10" - resolved "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz" + resolved "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== isexe@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isobject@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" + resolved "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.0" - resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + version "3.2.2" + resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== istanbul-lib-instrument@^5.0.4: version "5.2.1" - resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== dependencies: "@babel/core" "^7.12.3" @@ -10137,25 +10298,25 @@ istanbul-lib-instrument@^5.0.4: semver "^6.3.0" istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + version "3.0.1" + resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== dependencies: istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" + make-dir "^4.0.0" supports-color "^7.1.0" istanbul-reports@^3.0.2: - version "3.1.5" - resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz" - integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + version "3.1.7" + resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" istextorbinary@2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.1.0.tgz" + resolved "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.1.0.tgz#dbed2a6f51be2f7475b68f89465811141b758874" integrity sha512-kT1g2zxZ5Tdabtpp9VSdOzW9lb6LXImyWbzbQeTxoRtHhurC9Ej9Wckngr2+uepPL09ky/mJHmN9jeJPML5t6A== dependencies: binaryextensions "1 || 2" @@ -10164,7 +10325,7 @@ istextorbinary@2.1.0: istextorbinary@^2.5.1: version "2.6.0" - resolved "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.6.0.tgz" + resolved "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.6.0.tgz#60776315fb0fa3999add276c02c69557b9ca28ab" integrity sha512-+XRlFseT8B3L9KyjxxLjfXSLMuErKDsd8DBNrsaxoViABMEZlOSCstwmw0qpoFX3+U6yWU1yhLudAe6/lETGGA== dependencies: binaryextensions "^2.1.2" @@ -10173,7 +10334,7 @@ istextorbinary@^2.5.1: ivy-codemirror@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/ivy-codemirror/-/ivy-codemirror-2.1.0.tgz" + resolved "https://registry.npmjs.org/ivy-codemirror/-/ivy-codemirror-2.1.0.tgz#c06f1606c375610bf62b007a21a9e63f5854175e" integrity sha512-+Ha6Yf39fiK3dfQD5vlanrQ8GMIf/KVRbxzEzG+AsvAgUNSO8VECCfIRzdHQZcBfi9jNCaT+9q6VQd7mSqNalQ== dependencies: codemirror "~5.15.0" @@ -10182,36 +10343,41 @@ ivy-codemirror@^2.1.0: jest-worker@^27.4.5: version "27.5.1" - resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== dependencies: "@types/node" "*" merge-stream "^2.0.0" supports-color "^8.0.0" +jiti@^1.21.0: + version "1.21.6" + resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" + integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== + jquery@^3.4.1, jquery@^3.5.1: - version "3.6.4" - resolved "https://registry.npmjs.org/jquery/-/jquery-3.6.4.tgz" - integrity sha512-v28EW9DWDFpzcD9O5iyJXg3R3+q+mET5JhnjJzQUZMHOv67bpSIHq81GEYpPNZHG+XXHsfSme3nxp/hndKEcsQ== + version "3.7.1" + resolved "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" + integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== js-string-escape@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz" + resolved "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" integrity sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-tokens@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== js-yaml@^3.13.1, js-yaml@^3.14.0, js-yaml@^3.2.5, js-yaml@^3.2.7: version "3.14.1" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" @@ -10219,14 +10385,14 @@ js-yaml@^3.13.1, js-yaml@^3.14.0, js-yaml@^3.2.5, js-yaml@^3.2.7: js-yaml@^4.0.0: version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" jsdom@^16.4.0: version "16.7.0" - resolved "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz" + resolved "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== dependencies: abab "^2.0.5" @@ -10259,90 +10425,98 @@ jsdom@^16.4.0: jsesc@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA== jsesc@^2.5.0, jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== jsesc@~0.3.x: version "0.3.0" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.3.0.tgz" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.3.0.tgz#1bf5ee63b4539fe2e26d0c1e99c240b97a457972" integrity sha512-UHQmAeTXV+iwEk0aHheJRqo6Or90eDxI6KIYpHSjKLXKuKlPt1CQ7tGBerFcFA8uKU5mYxiPMlckmFptd5XZzA== jsesc@~0.5.0: version "0.5.0" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" + resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema-traverse@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" + resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz" - integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== + version "1.1.1" + resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz#52d4361b47d49168bcc4e564189a42e5a7439454" + integrity sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg== dependencies: + call-bind "^1.0.5" + isarray "^2.0.5" jsonify "^0.0.1" + object-keys "^1.1.1" json5@^0.5.1: version "0.5.1" - resolved "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz" + resolved "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw== -json5@^1.0.1: +json5@^1.0.1, json5@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz" + resolved "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" -json5@^2.1.2, json5@^2.2.2: +json5@^2.1.2, json5@^2.2.3: version "2.2.3" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonfile@^2.1.0: version "2.4.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== optionalDependencies: graceful-fs "^4.1.6" jsonfile@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== optionalDependencies: graceful-fs "^4.1.6" jsonfile@^6.0.1: version "6.1.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== dependencies: universalify "^2.0.0" @@ -10351,56 +10525,50 @@ jsonfile@^6.0.1: jsonify@^0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz" + resolved "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== -jsonlint@^1.6.3: - version "1.6.3" - resolved "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.3.tgz" - integrity sha512-jMVTMzP+7gU/IyC6hvKyWpUU8tmTkK5b3BPNuMI9U8Sit+YAWLlZwB6Y6YrdCxfg2kNz05p3XY3Bmm4m26Nv3A== - dependencies: - JSV "^4.0.x" - nomnom "^1.5.x" - just-extend@^4.0.2: version "4.2.1" - resolved "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz" + resolved "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744" integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg== -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +kind-of@^3.0.2, kind-of@^3.0.3: version "3.2.2" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== dependencies: is-buffer "^1.1.5" -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: +kind-of@^6.0.2: version "6.0.3" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== layout-bin-packer@^1.4.0: version "1.5.0" - resolved "https://registry.npmjs.org/layout-bin-packer/-/layout-bin-packer-1.5.0.tgz" + resolved "https://registry.npmjs.org/layout-bin-packer/-/layout-bin-packer-1.5.0.tgz#2e950456083621fe01f82007d896294f5e31e89c" integrity sha512-i0jmMwhB9SfPNoiMgZrjUiZoGY8TJzVrRAWuGnspEv4JJmULLEbAZ8VUwF9H9ITk2kzYR+tX5i1v/CMtxgpm4A== dependencies: ember-cli-babel "^6.8.2" leek@0.0.24: version "0.0.24" - resolved "https://registry.npmjs.org/leek/-/leek-0.0.24.tgz" + resolved "https://registry.npmjs.org/leek/-/leek-0.0.24.tgz#e400e57f0e60d8ef2bd4d068dc428a54345dbcda" integrity sha512-6PVFIYXxlYF0o6hrAsHtGpTmi06otkwNrMcmQ0K96SeSRHPREPa9J3nJZ1frliVH7XT0XFswoJFQoXsDukzGNQ== dependencies: debug "^2.1.0" @@ -10409,23 +10577,15 @@ leek@0.0.24: levn@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" + resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: prelude-ls "^1.2.1" type-check "~0.4.0" -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - license-checker@^25.0.1: version "25.0.1" - resolved "https://registry.npmjs.org/license-checker/-/license-checker-25.0.1.tgz" + resolved "https://registry.npmjs.org/license-checker/-/license-checker-25.0.1.tgz#4d14504478a5240a857bb3c21cd0491a00d761fa" integrity sha512-mET5AIwl7MR2IAKYYoVBBpV0OnkKQ1xGj2IMMeEFIs42QAkEVjRtFZGWmQ28WeU7MP779iAgOaOy93Mn44mn6g== dependencies: chalk "^2.4.1" @@ -10439,14 +10599,19 @@ license-checker@^25.0.1: spdx-satisfies "^4.0.0" treeify "^1.1.0" -lilconfig@^2.0.5, lilconfig@^2.0.6: +lilconfig@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz" + resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== +lilconfig@^3.0.0: + version "3.1.2" + resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" + integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== + line-column@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/line-column/-/line-column-1.0.2.tgz" + resolved "https://registry.npmjs.org/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2" integrity sha512-Ktrjk5noGYlHsVnYWh62FLVs4hTb8A3e+vucNZMgPeAOITdshMSgv4cCZQeRDjm7+goqmo6+liZwTXo+U3sVww== dependencies: isarray "^1.0.0" @@ -10454,26 +10619,19 @@ line-column@^1.0.2: lines-and-columns@^1.1.6: version "1.2.4" - resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -linkify-it@^2.0.0: - version "2.2.0" - resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz" - integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== - dependencies: - uc.micro "^1.0.1" - linkify-it@^3.0.1: version "3.0.3" - resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz" + resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ== dependencies: uc.micro "^1.0.1" lint-staged@^10.2.11: version "10.5.4" - resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-10.5.4.tgz" + resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-10.5.4.tgz#cd153b5f0987d2371fc1d2847a409a2fe705b665" integrity sha512-EechC3DdFic/TdOPgj/RB3FicqE6932LTHCUm0Y2fsD9KGlLB+RwJl2q1IYBIvEsKzDOgn0D4gll+YxG5RsrKg== dependencies: chalk "^4.1.0" @@ -10494,7 +10652,7 @@ lint-staged@^10.2.11: listr2@^3.2.2: version "3.14.0" - resolved "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz" + resolved "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e" integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g== dependencies: cli-truncate "^2.1.0" @@ -10508,12 +10666,12 @@ listr2@^3.2.2: livereload-js@^3.3.1: version "3.4.1" - resolved "https://registry.npmjs.org/livereload-js/-/livereload-js-3.4.1.tgz" + resolved "https://registry.npmjs.org/livereload-js/-/livereload-js-3.4.1.tgz#ba90fbc708ed1b9a024bb89c4ee12c96ea03d66f" integrity sha512-5MP0uUeVCec89ZbNOT/i97Mc+q3SxXmiUGhRFOTmhrGPn//uWVQdCvcLJDy64MSBR5MidFdOR7B9viumoavy6g== load-json-file@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz" + resolved "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw== dependencies: graceful-fs "^4.1.2" @@ -10523,17 +10681,17 @@ load-json-file@^4.0.0: loader-runner@^2.4.0: version "2.4.0" - resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz" + resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== loader-runner@^4.2.0: version "4.3.0" - resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz" + resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== loader-utils@^1.2.3: version "1.4.2" - resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== dependencies: big.js "^5.2.2" @@ -10542,7 +10700,7 @@ loader-utils@^1.2.3: loader-utils@^2.0.0: version "2.0.4" - resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== dependencies: big.js "^5.2.2" @@ -10551,17 +10709,17 @@ loader-utils@^2.0.0: loader.js@^4.7.0: version "4.7.0" - resolved "https://registry.npmjs.org/loader.js/-/loader.js-4.7.0.tgz" + resolved "https://registry.npmjs.org/loader.js/-/loader.js-4.7.0.tgz#a1a52902001c83631efde9688b8ab3799325ef1f" integrity sha512-9M2KvGT6duzGMgkOcTkWb+PR/Q2Oe54df/tLgHGVmFpAmtqJ553xJh6N63iFYI2yjo2PeJXbS5skHi/QpJq4vA== locale-emoji@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/locale-emoji/-/locale-emoji-0.3.0.tgz" + resolved "https://registry.npmjs.org/locale-emoji/-/locale-emoji-0.3.0.tgz#7f38262f7c877bd27659725570335b263f88742a" integrity sha512-JGm8+naU49CBDnH1jksS3LecPdfWQLxFgkLN6ZhYONKa850pJ0Xt8DPGJnYK0ZuJI8jTuiDDPCDtSL3nyacXwg== locate-path@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== dependencies: p-locate "^2.0.0" @@ -10569,7 +10727,7 @@ locate-path@^2.0.0: locate-path@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== dependencies: p-locate "^3.0.0" @@ -10577,21 +10735,21 @@ locate-path@^3.0.0: locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" locate-path@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: p-locate "^5.0.0" lodash._baseassign@^3.0.0: version "3.2.0" - resolved "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz" + resolved "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" integrity sha512-t3N26QR2IdSN+gqSy9Ds9pBu/J1EAFEshKlUHpJG3rvyJOYgcELIxcIeKKfZk7sjOz11cFfzJRsyFry/JyabJQ== dependencies: lodash._basecopy "^3.0.0" @@ -10599,12 +10757,12 @@ lodash._baseassign@^3.0.0: lodash._basecopy@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz" + resolved "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" integrity sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ== lodash._baseflatten@^3.0.0: version "3.1.4" - resolved "https://registry.npmjs.org/lodash._baseflatten/-/lodash._baseflatten-3.1.4.tgz" + resolved "https://registry.npmjs.org/lodash._baseflatten/-/lodash._baseflatten-3.1.4.tgz#0770ff80131af6e34f3b511796a7ba5214e65ff7" integrity sha512-fESngZd+X4k+GbTxdMutf8ohQa0s3sJEHIcwtu4/LsIQ2JTDzdRxDCMQjW+ezzwRitLmHnacVVmosCbxifefbw== dependencies: lodash.isarguments "^3.0.0" @@ -10612,12 +10770,12 @@ lodash._baseflatten@^3.0.0: lodash._bindcallback@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz" + resolved "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" integrity sha512-2wlI0JRAGX8WEf4Gm1p/mv/SZ+jLijpj0jyaE/AXeuQphzCgD8ZQW4oSpoN8JAopujOFGU3KMuq7qfHBWlGpjQ== lodash._createassigner@^3.0.0: version "3.1.1" - resolved "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz" + resolved "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11" integrity sha512-LziVL7IDnJjQeeV95Wvhw6G28Z8Q6da87LWKOPWmzBLv4u6FAT/x5v00pyGW0u38UoogNF2JnD3bGgZZDaNEBw== dependencies: lodash._bindcallback "^3.0.0" @@ -10626,22 +10784,22 @@ lodash._createassigner@^3.0.0: lodash._getnative@^3.0.0: version "3.9.1" - resolved "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz" + resolved "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" integrity sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA== lodash._isiterateecall@^3.0.0: version "3.0.9" - resolved "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz" + resolved "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" integrity sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ== lodash._reinterpolate@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz" + resolved "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA== lodash.assign@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz" + resolved "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa" integrity sha512-/VVxzgGBmbphasTg51FrztxQJ/VgAUpol6zmJuSVSGcNg4g7FA4z7rQV8Ovr9V3vFBNWZhvKWHfpAytjTVUfFA== dependencies: lodash._baseassign "^3.0.0" @@ -10650,49 +10808,49 @@ lodash.assign@^3.2.0: lodash.assignin@^4.1.0: version "4.2.0" - resolved "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz" + resolved "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" integrity sha512-yX/rx6d/UTVh7sSVWVSIMjfnz95evAgDFdb1ZozC35I9mSFCkmzptOzevxjgbQUsc78NR44LVHWjsoMQXy9FDg== lodash.castarray@^4.4.0: version "4.4.0" - resolved "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz" + resolved "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115" integrity sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q== lodash.clonedeep@^4.4.1: version "4.5.0" - resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz" + resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== lodash.debounce@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-3.1.1.tgz" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-3.1.1.tgz#812211c378a94cc29d5aa4e3346cf0bfce3a7df5" integrity sha512-lcmJwMpdPAtChA4hfiwxTtgFeNAaow701wWUgVUqeD0XJF7vMXIN+bu/2FJSGxT0NUbZy9g9VFrlOFfPjl+0Ew== dependencies: lodash._getnative "^3.0.0" lodash.debounce@^4.0.8: version "4.0.8" - resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== lodash.defaults@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz" + resolved "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== lodash.defaultsdeep@^4.6.1: version "4.6.1" - resolved "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz" + resolved "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz#512e9bd721d272d94e3d3a63653fa17516741ca6" integrity sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA== lodash.find@^4.5.1: version "4.6.0" - resolved "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz" + resolved "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1" integrity sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg== lodash.flatten@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-3.0.2.tgz" + resolved "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-3.0.2.tgz#de1cf57758f8f4479319d35c3e9cc60c4501938c" integrity sha512-jCXLoNcqQRbnT/KWZq2fIREHWeczrzpTR0vsycm96l/pu5hGeAntVBG0t7GuM/2wFqmnZs3d1eGptnAH2E8+xQ== dependencies: lodash._baseflatten "^3.0.0" @@ -10700,37 +10858,37 @@ lodash.flatten@^3.0.2: lodash.foreach@^4.5.0: version "4.5.0" - resolved "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz" + resolved "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" integrity sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ== lodash.get@^4.4.2: version "4.4.2" - resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz" + resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== lodash.isarguments@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz" + resolved "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== lodash.isarray@^3.0.0: version "3.0.4" - resolved "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz" + resolved "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" integrity sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ== -lodash.iteratee@^4.5.0: +lodash.iteratee@^4.7.0: version "4.7.0" - resolved "https://registry.npmjs.org/lodash.iteratee/-/lodash.iteratee-4.7.0.tgz" + resolved "https://registry.npmjs.org/lodash.iteratee/-/lodash.iteratee-4.7.0.tgz#be4177db289a8ccc3c0990f1db26b5b22fc1554c" integrity sha512-yv3cSQZmfpbIKo4Yo45B1taEvxjNvcpF1CEOc0Y6dEyvhPIfEJE3twDwPgWTPQubcSgXyBwBKG6wpQvWMDOf6Q== lodash.kebabcase@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz" + resolved "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" integrity sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g== lodash.keys@^3.0.0: version "3.1.2" - resolved "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz" + resolved "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" integrity sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ== dependencies: lodash._getnative "^3.0.0" @@ -10739,27 +10897,27 @@ lodash.keys@^3.0.0: lodash.last@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/lodash.last/-/lodash.last-3.0.0.tgz" + resolved "https://registry.npmjs.org/lodash.last/-/lodash.last-3.0.0.tgz#242f663112dd4c6e63728c60a3c909d1bdadbd4c" integrity sha512-14mq7rSkCxG4XMy9lF2FbIOqqgF0aH0NfPuQ3LPR3vIh0kHnUvIYP70dqa1Hf47zyXfQ8FzAg0MYOQeSuE1R7A== lodash.merge@^4.6.0, lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== lodash.omit@^4.1.0, lodash.omit@^4.5.0: version "4.5.0" - resolved "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz" + resolved "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60" integrity sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg== lodash.restparam@^3.0.0: version "3.6.1" - resolved "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz" + resolved "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" integrity sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw== lodash.template@^4.5.0: version "4.5.0" - resolved "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz" + resolved "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== dependencies: lodash._reinterpolate "^3.0.0" @@ -10767,41 +10925,41 @@ lodash.template@^4.5.0: lodash.templatesettings@^4.0.0: version "4.2.0" - resolved "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz" + resolved "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== dependencies: lodash._reinterpolate "^3.0.0" lodash.truncate@^4.4.2: version "4.4.2" - resolved "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz" + resolved "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== lodash.uniq@^4.2.0: version "4.5.0" - resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" + resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== lodash.uniqby@^4.7.0: version "4.7.0" - resolved "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz" + resolved "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" integrity sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww== lodash@^4.17.10, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.5.1, lodash@^4.7.0: version "4.17.21" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== log-symbols@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== dependencies: chalk "^2.0.1" log-symbols@^4.0.0, log-symbols@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== dependencies: chalk "^4.1.0" @@ -10809,7 +10967,7 @@ log-symbols@^4.0.0, log-symbols@^4.1.0: log-update@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz" + resolved "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== dependencies: ansi-escapes "^4.3.0" @@ -10819,47 +10977,47 @@ log-update@^4.0.0: longest-streak@^2.0.0: version "2.0.4" - resolved "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz" + resolved "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== loose-envify@^1.0.0: version "1.4.0" - resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" lower-case@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz" + resolved "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== dependencies: tslib "^2.0.3" lru-cache@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" magic-string@^0.25.7: version "0.25.9" - resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz" + resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== dependencies: sourcemap-codec "^1.4.8" make-dir@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== dependencies: pify "^4.0.1" @@ -10867,33 +11025,40 @@ make-dir@^2.0.0: make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + makeerror@1.0.12: version "1.0.12" - resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz" + resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== dependencies: tmpl "1.0.5" map-cache@^0.2.2: version "0.2.2" - resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" + resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== map-visit@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz" + resolved "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== dependencies: object-visit "^1.0.0" markdown-it-terminal@0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/markdown-it-terminal/-/markdown-it-terminal-0.2.1.tgz" + resolved "https://registry.npmjs.org/markdown-it-terminal/-/markdown-it-terminal-0.2.1.tgz#670fd5ea824a7dcaa1591dcbeef28bf70aff1705" integrity sha512-e8hbK9L+IyFac2qY05R7paP+Fqw1T4pSQW3miK3VeG9QmpqBjg5Qzjv/v6C7YNxSNRS2Kp8hUFtm5lWU9eK4lw== dependencies: ansi-styles "^3.0.0" @@ -10902,9 +11067,9 @@ markdown-it-terminal@0.2.1: lodash.merge "^4.6.2" markdown-it "^8.3.1" -markdown-it@^12.0.4: +markdown-it@^12.0.4, markdown-it@^12.3.2, markdown-it@^8.3.1: version "12.3.2" - resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz" + resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90" integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg== dependencies: argparse "^2.0.1" @@ -10913,34 +11078,23 @@ markdown-it@^12.0.4: mdurl "^1.0.1" uc.micro "^1.0.5" -markdown-it@^8.3.1: - version "8.4.2" - resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz" - integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ== - dependencies: - argparse "^1.0.7" - entities "~1.1.1" - linkify-it "^2.0.0" - mdurl "^1.0.1" - uc.micro "^1.0.5" - markdown-table@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz" + resolved "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz#194a90ced26d31fe753d8b9434430214c011865b" integrity sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A== dependencies: repeat-string "^1.0.0" matcher-collection@^1.0.0, matcher-collection@^1.1.1: version "1.1.2" - resolved "https://registry.npmjs.org/matcher-collection/-/matcher-collection-1.1.2.tgz" + resolved "https://registry.npmjs.org/matcher-collection/-/matcher-collection-1.1.2.tgz#1076f506f10ca85897b53d14ef54f90a5c426838" integrity sha512-YQ/teqaOIIfUHedRam08PB3NK7Mjct6BvzRnJmpGDm8uFXpNr1sbY4yuflI5JcEs6COpYA0FpRQhSDBf1tT95g== dependencies: minimatch "^3.0.2" matcher-collection@^2.0.0, matcher-collection@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/matcher-collection/-/matcher-collection-2.0.1.tgz" + resolved "https://registry.npmjs.org/matcher-collection/-/matcher-collection-2.0.1.tgz#90be1a4cf58d6f2949864f65bb3b0f3e41303b29" integrity sha512-daE62nS2ZQsDg9raM0IlZzLmI2u+7ZapXBwdoeBUKAYERPDDIc0qNqA8E0Rp2D+gspKR7BgIFP52GeujaGXWeQ== dependencies: "@types/minimatch" "^3.0.3" @@ -10948,14 +11102,14 @@ matcher-collection@^2.0.0, matcher-collection@^2.0.1: md5-hex@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz" + resolved "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz#be3741b510591434b2784d79e556eefc2c9a8e5c" integrity sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw== dependencies: blueimp-md5 "^2.10.0" md5.js@^1.3.4: version "1.3.5" - resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz" + resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" @@ -10964,21 +11118,21 @@ md5.js@^1.3.4: mdast-normalize-headings@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/mdast-normalize-headings/-/mdast-normalize-headings-2.0.0.tgz" + resolved "https://registry.npmjs.org/mdast-normalize-headings/-/mdast-normalize-headings-2.0.0.tgz#378c8161a9f57fcf52a6fd5628507af370c7f8c5" integrity sha512-PVuunQSsJNYiuZ56QypccTVPy8DowOkj61HtD78PSq1M8I49GwxzhdE2QmOp+j/TwaT1yq/K4b201388/ucV2g== dependencies: unist-util-visit "^2.0.0" mdast-util-definitions@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz" + resolved "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz#c5c1a84db799173b4dcf7643cda999e440c24db2" integrity sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ== dependencies: unist-util-visit "^2.0.0" mdast-util-find-and-replace@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-1.1.1.tgz" + resolved "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-1.1.1.tgz#b7db1e873f96f66588c321f1363069abf607d1b5" integrity sha512-9cKl33Y21lyckGzpSmEQnIDjEfeeWelN5s1kUW1LwdB0Fkuq2u+4GdqcGEygYxJE8GVqCl0741bYXHgamfWAZA== dependencies: escape-string-regexp "^4.0.0" @@ -10987,7 +11141,7 @@ mdast-util-find-and-replace@^1.1.0: mdast-util-footnote@^0.1.0: version "0.1.7" - resolved "https://registry.npmjs.org/mdast-util-footnote/-/mdast-util-footnote-0.1.7.tgz" + resolved "https://registry.npmjs.org/mdast-util-footnote/-/mdast-util-footnote-0.1.7.tgz#4b226caeab4613a3362c144c94af0fdd6f7e0ef0" integrity sha512-QxNdO8qSxqbO2e3m09KwDKfWiLgqyCurdWTQ198NpbZ2hxntdc+VKS4fDJCmNWbAroUdYnSthu+XbZ8ovh8C3w== dependencies: mdast-util-to-markdown "^0.6.0" @@ -10995,7 +11149,7 @@ mdast-util-footnote@^0.1.0: mdast-util-from-markdown@^0.8.0: version "0.8.5" - resolved "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz" + resolved "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz#d1ef2ca42bc377ecb0463a987910dae89bd9a28c" integrity sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ== dependencies: "@types/mdast" "^3.0.0" @@ -11006,14 +11160,14 @@ mdast-util-from-markdown@^0.8.0: mdast-util-frontmatter@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-0.2.0.tgz" + resolved "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-0.2.0.tgz#8bd5cd55e236c03e204a036f7372ebe9e6748240" integrity sha512-FHKL4w4S5fdt1KjJCwB0178WJ0evnyyQr5kXTM3wrOVpytD0hrkvd+AOOjU9Td8onOejCkmZ+HQRT3CZ3coHHQ== dependencies: micromark-extension-frontmatter "^0.2.0" mdast-util-gfm-autolink-literal@^0.1.0, mdast-util-gfm-autolink-literal@^0.1.3: version "0.1.3" - resolved "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-0.1.3.tgz" + resolved "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-0.1.3.tgz#9c4ff399c5ddd2ece40bd3b13e5447d84e385fb7" integrity sha512-GjmLjWrXg1wqMIO9+ZsRik/s7PLwTaeCHVB7vRxUwLntZc8mzmTsLVr6HW1yLokcnhfURsn5zmSVdi3/xWWu1A== dependencies: ccount "^1.0.0" @@ -11022,14 +11176,14 @@ mdast-util-gfm-autolink-literal@^0.1.0, mdast-util-gfm-autolink-literal@^0.1.3: mdast-util-gfm-strikethrough@^0.2.0: version "0.2.3" - resolved "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-0.2.3.tgz" + resolved "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-0.2.3.tgz#45eea337b7fff0755a291844fbea79996c322890" integrity sha512-5OQLXpt6qdbttcDG/UxYY7Yjj3e8P7X16LzvpX8pIQPYJ/C2Z1qFGMmcw+1PZMUM3Z8wt8NRfYTvCni93mgsgA== dependencies: mdast-util-to-markdown "^0.6.0" mdast-util-gfm-table@^0.1.0: version "0.1.6" - resolved "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-0.1.6.tgz" + resolved "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-0.1.6.tgz#af05aeadc8e5ee004eeddfb324b2ad8c029b6ecf" integrity sha512-j4yDxQ66AJSBwGkbpFEp9uG/LS1tZV3P33fN1gkyRB2LoRL+RR3f76m0HPHaby6F4Z5xr9Fv1URmATlRRUIpRQ== dependencies: markdown-table "^2.0.0" @@ -11037,14 +11191,14 @@ mdast-util-gfm-table@^0.1.0: mdast-util-gfm-task-list-item@^0.1.0: version "0.1.6" - resolved "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.6.tgz" + resolved "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.6.tgz#70c885e6b9f543ddd7e6b41f9703ee55b084af10" integrity sha512-/d51FFIfPsSmCIRNp7E6pozM9z1GYPIkSy1urQ8s/o4TC22BZ7DqfHFWiqBD23bc7J3vV1Fc9O4QIHBlfuit8A== dependencies: mdast-util-to-markdown "~0.6.0" mdast-util-gfm@^0.1.0: version "0.1.2" - resolved "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-0.1.2.tgz" + resolved "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-0.1.2.tgz#8ecddafe57d266540f6881f5c57ff19725bd351c" integrity sha512-NNkhDx/qYcuOWB7xHUGWZYVXvjPFFd6afg6/e2g+SV4r9q5XUcCbV4Wfa3DLYIiD+xAEZc6K4MGaE/m0KDcPwQ== dependencies: mdast-util-gfm-autolink-literal "^0.1.0" @@ -11055,7 +11209,7 @@ mdast-util-gfm@^0.1.0: mdast-util-to-hast@^10.2.0: version "10.2.0" - resolved "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.2.0.tgz" + resolved "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.2.0.tgz#61875526a017d8857b71abc9333942700b2d3604" integrity sha512-JoPBfJ3gBnHZ18icCwHR50orC9kNH81tiR1gs01D8Q5YpV6adHNO9nKNuFBCJQ941/32PT1a63UF/DitmS3amQ== dependencies: "@types/mdast" "^3.0.0" @@ -11069,7 +11223,7 @@ mdast-util-to-hast@^10.2.0: mdast-util-to-markdown@^0.6.0, mdast-util-to-markdown@^0.6.1, mdast-util-to-markdown@~0.6.0: version "0.6.5" - resolved "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz" + resolved "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe" integrity sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ== dependencies: "@types/unist" "^2.0.0" @@ -11081,17 +11235,17 @@ mdast-util-to-markdown@^0.6.0, mdast-util-to-markdown@^0.6.1, mdast-util-to-mark mdast-util-to-string@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz" + resolved "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz#27055500103f51637bd07d01da01eb1967a43527" integrity sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A== mdast-util-to-string@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz" + resolved "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== mdast-util-toc@^5.1.0: version "5.1.0" - resolved "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-5.1.0.tgz" + resolved "https://registry.npmjs.org/mdast-util-toc/-/mdast-util-toc-5.1.0.tgz#3af0f9c9a764b993538af03f1f79f4e3cec22736" integrity sha512-csimbRIVkiqc+PpFeKDGQ/Ck2N4f9FYH3zzBMMJzcxoKL8m+cM0n94xXm0I9eaxHnKdY9n145SGTdyJC7i273g== dependencies: "@types/mdast" "^3.0.3" @@ -11104,22 +11258,22 @@ mdast-util-toc@^5.1.0: mdn-data@2.0.30: version "2.0.30" - resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz" + resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc" integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA== mdurl@^1.0.0, mdurl@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz" + resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== media-typer@0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== memory-fs@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz" + resolved "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" integrity sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ== dependencies: errno "^0.1.3" @@ -11127,7 +11281,7 @@ memory-fs@^0.4.1: memory-fs@^0.5.0: version "0.5.0" - resolved "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz" + resolved "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== dependencies: errno "^0.1.3" @@ -11135,36 +11289,36 @@ memory-fs@^0.5.0: memory-streams@^0.1.3: version "0.1.3" - resolved "https://registry.npmjs.org/memory-streams/-/memory-streams-0.1.3.tgz" + resolved "https://registry.npmjs.org/memory-streams/-/memory-streams-0.1.3.tgz#d9b0017b4b87f1d92f55f2745c9caacb1dc93ceb" integrity sha512-qVQ/CjkMyMInPaaRMrwWNDvf6boRZXaT/DbQeMYcCWuXPEBf1v8qChOc9OlEVQp2uOvRXa1Qu30fLmKhY6NipA== dependencies: readable-stream "~1.0.2" memorystream@^0.3.1: version "0.3.1" - resolved "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz" + resolved "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== merge-descriptors@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== merge-options@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz" + resolved "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz#2a64b24457becd4e4dc608283247e94ce589aa32" integrity sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg== dependencies: is-plain-obj "^1.1" merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== merge-trees@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/merge-trees/-/merge-trees-1.0.1.tgz" + resolved "https://registry.npmjs.org/merge-trees/-/merge-trees-1.0.1.tgz#ccbe674569787f9def17fd46e6525f5700bbd23e" integrity sha512-O7TWwipLHhc9tErjq3WBvNP7I1g7Wgudl1ZkLqpT7F2MZy1yEdgnI9cpZZxBaqk+wJZu+2b9FE7D3ubUmGFHFA== dependencies: can-symlink "^1.0.0" @@ -11176,7 +11330,7 @@ merge-trees@^1.0.1: merge-trees@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/merge-trees/-/merge-trees-2.0.0.tgz" + resolved "https://registry.npmjs.org/merge-trees/-/merge-trees-2.0.0.tgz#a560d796e566c5d9b2c40472a2967cca48d85161" integrity sha512-5xBbmqYBalWqmhYm51XlohhkmVOua3VAUrrWh8t9iOkaLpS6ifqm/UVuUjQCeDVJ9Vx3g2l6ihfkbLSTeKsHbw== dependencies: fs-updater "^1.0.4" @@ -11184,69 +11338,69 @@ merge-trees@^2.0.0: merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== merge@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz" + resolved "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz#59ef4bf7e0b3e879186436e8481c06a6c162ca98" integrity sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w== methods@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== micromark-extension-footnote@^0.3.0: version "0.3.2" - resolved "https://registry.npmjs.org/micromark-extension-footnote/-/micromark-extension-footnote-0.3.2.tgz" + resolved "https://registry.npmjs.org/micromark-extension-footnote/-/micromark-extension-footnote-0.3.2.tgz#129b74ef4920ce96719b2c06102ee7abb2b88a20" integrity sha512-gr/BeIxbIWQoUm02cIfK7mdMZ/fbroRpLsck4kvFtjbzP4yi+OPVbnukTc/zy0i7spC2xYE/dbX1Sur8BEDJsQ== dependencies: micromark "~2.11.0" micromark-extension-frontmatter@^0.2.0: version "0.2.2" - resolved "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-0.2.2.tgz" + resolved "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-0.2.2.tgz#61b8e92e9213e1d3c13f5a59e7862f5ca98dfa53" integrity sha512-q6nPLFCMTLtfsctAuS0Xh4vaolxSFUWUWR6PZSrXXiRy+SANGllpcqdXFv2z07l0Xz/6Hl40hK0ffNCJPH2n1A== dependencies: fault "^1.0.0" micromark-extension-gfm-autolink-literal@~0.5.0: version "0.5.7" - resolved "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.7.tgz" + resolved "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.7.tgz#53866c1f0c7ef940ae7ca1f72c6faef8fed9f204" integrity sha512-ePiDGH0/lhcngCe8FtH4ARFoxKTUelMp4L7Gg2pujYD5CSMb9PbblnyL+AAMud/SNMyusbS2XDSiPIRcQoNFAw== dependencies: micromark "~2.11.3" micromark-extension-gfm-strikethrough@~0.6.5: version "0.6.5" - resolved "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.5.tgz" + resolved "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.5.tgz#96cb83356ff87bf31670eefb7ad7bba73e6514d1" integrity sha512-PpOKlgokpQRwUesRwWEp+fHjGGkZEejj83k9gU5iXCbDG+XBA92BqnRKYJdfqfkrRcZRgGuPuXb7DaK/DmxOhw== dependencies: micromark "~2.11.0" micromark-extension-gfm-table@~0.4.0: version "0.4.3" - resolved "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.3.tgz" + resolved "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.3.tgz#4d49f1ce0ca84996c853880b9446698947f1802b" integrity sha512-hVGvESPq0fk6ALWtomcwmgLvH8ZSVpcPjzi0AjPclB9FsVRgMtGZkUcpE0zgjOCFAznKepF4z3hX8z6e3HODdA== dependencies: micromark "~2.11.0" micromark-extension-gfm-tagfilter@~0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-0.3.0.tgz" + resolved "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-0.3.0.tgz#d9f26a65adee984c9ccdd7e182220493562841ad" integrity sha512-9GU0xBatryXifL//FJH+tAZ6i240xQuFrSL7mYi8f4oZSbc+NvXjkrHemeYP0+L4ZUT+Ptz3b95zhUZnMtoi/Q== micromark-extension-gfm-task-list-item@~0.3.0: version "0.3.3" - resolved "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-0.3.3.tgz" + resolved "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-0.3.3.tgz#d90c755f2533ed55a718129cee11257f136283b8" integrity sha512-0zvM5iSLKrc/NQl84pZSjGo66aTGd57C1idmlWmE87lkMcXrTxg1uXa/nXomxJytoje9trP0NDLvw4bZ/Z/XCQ== dependencies: micromark "~2.11.0" micromark-extension-gfm@^0.3.0: version "0.3.3" - resolved "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-0.3.3.tgz" + resolved "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-0.3.3.tgz#36d1a4c089ca8bdfd978c9bd2bf1a0cb24e2acfe" integrity sha512-oVN4zv5/tAIA+l3GbMi7lWeYpJ14oQyJ3uEim20ktYFAcfX1x3LNlFGGlmrZHt7u9YlKExmyJdDGaTt6cMSR/A== dependencies: micromark "~2.11.0" @@ -11258,7 +11412,7 @@ micromark-extension-gfm@^0.3.0: micromark@^2.11.3, micromark@~2.11.0, micromark@~2.11.3: version "2.11.4" - resolved "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz" + resolved "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a" integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA== dependencies: debug "^4.0.0" @@ -11266,7 +11420,7 @@ micromark@^2.11.3, micromark@~2.11.0, micromark@~2.11.3: micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" @@ -11284,16 +11438,16 @@ micromatch@^3.1.10, micromatch@^3.1.4: to-regex "^3.0.2" micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: - version "4.0.5" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + version "4.0.7" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" + integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" miller-rabin@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz" + resolved "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" @@ -11301,68 +11455,69 @@ miller-rabin@^4.0.0: mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": version "1.52.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.26, mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" mime@1.6.0: version "1.6.0" - resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mimic-fn@^1.0.0: version "1.2.0" - resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== mimic-fn@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== mini-css-extract-plugin@^2.5.2: - version "2.7.3" - resolved "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.3.tgz" - integrity sha512-CD9cXeKeXLcnMw8FZdtfrRrLaM7gwCl4nKuKn2YkY2Bw5wdlB8zU2cCzw+w2zS9RFvbrufTBkMCJACNPwqQA0w== + version "2.9.0" + resolved "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz#c73a1327ccf466f69026ac22a8e8fd707b78a235" + integrity sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA== dependencies: schema-utils "^4.0.0" + tapable "^2.2.1" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" + resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== minimalistic-crypto-utils@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" + resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1: +minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1: version "3.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimist@>=1.2.5, minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.7: +minimist@>=1.2.5, minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8: version "1.2.8" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== minimist@^0.2.1: version "0.2.4" - resolved "https://registry.npmjs.org/minimist/-/minimist-0.2.4.tgz" + resolved "https://registry.npmjs.org/minimist/-/minimist-0.2.4.tgz#0085d5501e29033748a2f2a4da0180142697a475" integrity sha512-Pkrrm8NjyQ8yVt8Am9M+yUt74zE3iokhzbG1bFVNjLB92vwM71hf40RkEsryg98BujhVOncKm/C1xROxZ030LQ== minipass@^2.2.0: version "2.9.0" - resolved "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz" + resolved "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== dependencies: safe-buffer "^5.1.2" @@ -11370,7 +11525,7 @@ minipass@^2.2.0: mississippi@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz" + resolved "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== dependencies: concat-stream "^1.5.0" @@ -11386,7 +11541,7 @@ mississippi@^3.0.0: mixin-deep@^1.2.0: version "1.3.2" - resolved "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz" + resolved "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== dependencies: for-in "^1.0.2" @@ -11394,31 +11549,48 @@ mixin-deep@^1.2.0: mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@^0.5.6: version "0.5.6" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: minimist "^1.2.6" mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mkdirp@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" + integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== + mktemp@~0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/mktemp/-/mktemp-0.4.0.tgz" + resolved "https://registry.npmjs.org/mktemp/-/mktemp-0.4.0.tgz#6d0515611c8a8c84e484aa2000129b98e981ff0b" integrity sha512-IXnMcJ6ZyTuhRmJSjzvHSRhlVPiN9Jwc6e59V0bEJ0ba6OBeX2L0E+mRN1QseeOF4mM+F1Rit6Nh7o+rl2Yn/A== mnemonist@^0.38.0: version "0.38.5" - resolved "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz" + resolved "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== dependencies: obliterator "^2.0.0" +mock-property@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/mock-property/-/mock-property-1.0.3.tgz#3e37c50a56609d548cabd56559fde3dd8767b10c" + integrity sha512-2emPTb1reeLLYwHxyVx993iYyCHEiRRO+y8NFXFPL5kl5q14sgTK76cXyEKkeKCHeRw35SfdkUJ10Q1KfHuiIQ== + dependencies: + define-data-property "^1.1.1" + functions-have-names "^1.2.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + hasown "^2.0.0" + isarray "^2.0.5" + morgan@^1.10.0: version "1.10.0" - resolved "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz" + resolved "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== dependencies: basic-auth "~2.0.1" @@ -11429,12 +11601,12 @@ morgan@^1.10.0: mout@^1.0.0: version "1.2.4" - resolved "https://registry.npmjs.org/mout/-/mout-1.2.4.tgz" + resolved "https://registry.npmjs.org/mout/-/mout-1.2.4.tgz#9ffd261c4d6509e7ebcbf6b641a89b36ecdf8155" integrity sha512-mZb9uOruMWgn/fw28DG4/yE3Kehfk1zKCLhuDU2O3vlKdnBBr4XaOCqVTflJ5aODavGUPqFHZgrFX3NJVuxGhQ== move-concurrently@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz" + resolved "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" integrity sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ== dependencies: aproba "^1.1.1" @@ -11446,52 +11618,61 @@ move-concurrently@^1.0.1: ms@2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.2, ms@^2.1.1: +ms@2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3: +ms@2.1.3, ms@^2.1.1: version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== mustache@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz" + resolved "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== mute-stream@0.0.7: version "0.0.7" - resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz" + resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== mute-stream@0.0.8: version "0.0.8" - resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz" + resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + nan@^2.12.1: - version "2.17.0" - resolved "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz" - integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== + version "2.20.0" + resolved "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz#08c5ea813dd54ed16e5bd6505bf42af4f7838ca3" + integrity sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw== nanoassert@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz" + resolved "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz#4f3152e09540fde28c76f44b19bbcd1d5a42478d" integrity sha512-C40jQ3NzfkP53NsO8kEOFd79p4b9kDXQMwgiY1z8ZwrDZgUyom0AHwGegF4Dm99L+YoYhuaB0ceerUcXmqr1rQ== -nanoid@^3.3.6: - version "3.3.6" - resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz" - integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== nanomatch@^1.2.9: version "1.2.13" - resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz" + resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" @@ -11508,39 +11689,39 @@ nanomatch@^1.2.9: natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== negotiator@0.6.3: version "0.6.3" - resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1, neo-async@^2.6.2: +neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2: version "2.6.2" - resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== ngraph.events@^1.2.1: version "1.2.2" - resolved "https://registry.npmjs.org/ngraph.events/-/ngraph.events-1.2.2.tgz" + resolved "https://registry.npmjs.org/ngraph.events/-/ngraph.events-1.2.2.tgz#3ceb92d676a04a4e7ce60a09fa8e17a4f0346d7f" integrity sha512-JsUbEOzANskax+WSYiAPETemLWYXmixuPAlmZmhIbIj6FH/WDgEGCGnRwUQBK0GjOnVm8Ui+e5IJ+5VZ4e32eQ== ngraph.graph@^19.1.0: version "19.1.0" - resolved "https://registry.npmjs.org/ngraph.graph/-/ngraph.graph-19.1.0.tgz" + resolved "https://registry.npmjs.org/ngraph.graph/-/ngraph.graph-19.1.0.tgz#88910ed53f6b4bc374f1b67296f4f81aab814e24" integrity sha512-9cws84qfPkrYa7BaBtT+KgZfLXrd6pNL9Gl5Do+MBO/0Hm6rOM7qK78MZaO1uEoIK6p2pgUs6lu29zn/6tP59w== dependencies: ngraph.events "^1.2.1" nice-try@^1.0.4: version "1.0.5" - resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz" + resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== nise@^4.0.4: version "4.1.0" - resolved "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz" + resolved "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz#8fb75a26e90b99202fa1e63f448f58efbcdedaf6" integrity sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA== dependencies: "@sinonjs/commons" "^1.7.0" @@ -11551,7 +11732,7 @@ nise@^4.0.4: no-case@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz" + resolved "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== dependencies: lower-case "^2.0.2" @@ -11559,26 +11740,26 @@ no-case@^3.0.4: node-dir@^0.1.17: version "0.1.17" - resolved "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz" + resolved "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" integrity sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg== dependencies: minimatch "^3.0.2" node-fetch@^2.6.0: - version "2.6.9" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz" - integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + version "2.7.0" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" node-int64@^0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" + resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== node-libs-browser@^2.2.1: version "2.2.1" - resolved "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz" + resolved "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== dependencies: assert "^1.1.1" @@ -11607,12 +11788,12 @@ node-libs-browser@^2.2.1: node-modules-path@^1.0.0, node-modules-path@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/node-modules-path/-/node-modules-path-1.0.2.tgz" + resolved "https://registry.npmjs.org/node-modules-path/-/node-modules-path-1.0.2.tgz#e3acede9b7baf4bc336e3496b58e5b40d517056e" integrity sha512-6Gbjq+d7uhkO7epaKi5DNgUJn7H0gEyA4Jg0Mo1uQOi3Rk50G83LtmhhFyw0LxnAFhtlspkiiw52ISP13qzcBg== node-notifier@^10.0.0: version "10.0.1" - resolved "https://registry.npmjs.org/node-notifier/-/node-notifier-10.0.1.tgz" + resolved "https://registry.npmjs.org/node-notifier/-/node-notifier-10.0.1.tgz#0e82014a15a8456c4cfcdb25858750399ae5f1c7" integrity sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ== dependencies: growly "^1.3.0" @@ -11622,34 +11803,26 @@ node-notifier@^10.0.0: uuid "^8.3.2" which "^2.0.2" -node-releases@^2.0.8: - version "2.0.10" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz" - integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== node-watch@0.7.3: version "0.7.3" - resolved "https://registry.npmjs.org/node-watch/-/node-watch-0.7.3.tgz" + resolved "https://registry.npmjs.org/node-watch/-/node-watch-0.7.3.tgz#6d4db88e39c8d09d3ea61d6568d80e5975abc7ab" integrity sha512-3l4E8uMPY1HdMMryPRUAl+oIHtXtyiTlIiESNSVSNxcPfzAFzeTbXFQkZfAwBbo0B1qMSG8nUABx+Gd+YrbKrQ== -nomnom@^1.5.x: - version "1.8.1" - resolved "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz" - integrity sha512-5s0JxqhDx9/rksG2BTMVN1enjWSvPidpoSgViZU4ZXULyTe+7jxcCRLB6f42Z0l1xYJpleCBtSyY6Lwg3uu5CQ== - dependencies: - chalk "~0.4.0" - underscore "~1.6.0" - nopt@^3.0.6: version "3.0.6" - resolved "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz" + resolved "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg== dependencies: abbrev "1" nopt@^4.0.1: version "4.0.3" - resolved "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz" + resolved "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== dependencies: abbrev "1" @@ -11657,7 +11830,7 @@ nopt@^4.0.1: normalize-package-data@^2.0.0, normalize-package-data@^2.3.2: version "2.5.0" - resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz" + resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== dependencies: hosted-git-info "^2.1.4" @@ -11667,34 +11840,34 @@ normalize-package-data@^2.0.0, normalize-package-data@^2.3.2: normalize-path@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== dependencies: remove-trailing-separator "^1.0.1" normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== normalize-range@^0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz" + resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== npm-git-info@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/npm-git-info/-/npm-git-info-1.0.3.tgz" + resolved "https://registry.npmjs.org/npm-git-info/-/npm-git-info-1.0.3.tgz#a933c42ec321e80d3646e0d6e844afe94630e1d5" integrity sha512-i5WBdj4F/ULl16z9ZhsJDMl1EQCMQhHZzBwNnKL2LOA+T8IHNeRkLCVz9uVV9SzUdGTbDq+1oXhIYMe+8148vw== npm-normalize-package-bin@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz" + resolved "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== npm-package-arg@^8.1.1: version "8.1.5" - resolved "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz" + resolved "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz#3369b2d5fe8fdc674baa7f1786514ddc15466e44" integrity sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q== dependencies: hosted-git-info "^4.0.1" @@ -11703,7 +11876,7 @@ npm-package-arg@^8.1.1: npm-run-all@^4.1.5: version "4.1.5" - resolved "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz" + resolved "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== dependencies: ansi-styles "^3.2.1" @@ -11718,28 +11891,28 @@ npm-run-all@^4.1.5: npm-run-path@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== dependencies: path-key "^2.0.0" npm-run-path@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz#7f91be317f6a466efed3c9f2980ad8a4ee8b0fa5" integrity sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg== dependencies: path-key "^3.0.0" npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: path-key "^3.0.0" npmlog@^4.1.2: version "4.1.2" - resolved "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" @@ -11749,7 +11922,7 @@ npmlog@^4.1.2: npmlog@^6.0.0: version "6.0.2" - resolved "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== dependencies: are-we-there-yet "^3.0.0" @@ -11759,22 +11932,22 @@ npmlog@^6.0.0: number-is-nan@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" + resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== nwsapi@^2.2.0: - version "2.2.2" - resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz" - integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw== + version "2.2.10" + resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz#0b77a68e21a0b483db70b11fad055906e867cda8" + integrity sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ== -object-assign@4.1.1, object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@4.1.1, object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-copy@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz" + resolved "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== dependencies: copy-descriptor "^0.1.0" @@ -11783,133 +11956,121 @@ object-copy@^0.1.0: object-hash@^1.3.1: version "1.3.1" - resolved "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz" + resolved "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df" integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== object-hash@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz" + resolved "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== -object-inspect@^1.12.2, object-inspect@^1.12.3, object-inspect@^1.9.0: - version "1.12.3" - resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz" - integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== -object-is@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== +object-is@^1.1.5, object-is@^1.1.6: + version "1.1.6" + resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" + call-bind "^1.0.7" + define-properties "^1.2.1" object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object-visit@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" + resolved "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== dependencies: isobject "^3.0.0" -object.assign@^4.1.4: - version "4.1.4" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== +object.assign@^4.1.4, object.assign@^4.1.5: + version "4.1.5" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" + integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" + call-bind "^1.0.5" + define-properties "^1.2.1" has-symbols "^1.0.3" object-keys "^1.1.1" object.pick@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz" + resolved "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== dependencies: isobject "^3.0.1" obliterator@^2.0.0: version "2.0.4" - resolved "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz" + resolved "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== on-finished@2.4.1: version "2.4.1" - resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== dependencies: ee-first "1.1.1" on-finished@~2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== dependencies: ee-first "1.1.1" on-headers@~1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" + resolved "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" onetime@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz" + resolved "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== dependencies: mimic-fn "^1.0.0" onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" opencollective-postinstall@^2.0.2: version "2.0.3" - resolved "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz" + resolved "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + version "0.9.4" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== dependencies: deep-is "^0.1.3" fast-levenshtein "^2.0.6" levn "^0.4.1" prelude-ls "^1.2.1" type-check "^0.4.0" - word-wrap "^1.2.3" + word-wrap "^1.2.5" ora@^3.4.0: version "3.4.0" - resolved "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz" + resolved "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg== dependencies: chalk "^2.4.2" @@ -11921,7 +12082,7 @@ ora@^3.4.0: ora@^5.4.0: version "5.4.1" - resolved "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz" + resolved "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== dependencies: bl "^4.1.0" @@ -11936,22 +12097,22 @@ ora@^5.4.0: os-browserify@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz" + resolved "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== os-homedir@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz" + resolved "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" + resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== osenv@^0.1.3, osenv@^0.1.4: version "0.1.5" - resolved "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz" + resolved "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== dependencies: os-homedir "^1.0.0" @@ -11959,107 +12120,107 @@ osenv@^0.1.3, osenv@^0.1.4: p-defer@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz" + resolved "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz#d1dceb4ee9b2b604b1d94ffec83760175d4e6f83" integrity sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw== p-event@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz" + resolved "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6" integrity sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA== dependencies: p-timeout "^2.0.1" p-finally@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz" + resolved "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== p-finally@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz" + resolved "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== p-limit@^1.1.0: version "1.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== dependencies: p-try "^1.0.0" p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-limit@^3.0.2: version "3.1.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" p-locate@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== dependencies: p-limit "^1.1.0" p-locate@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== dependencies: p-limit "^2.0.0" p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" p-locate@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== dependencies: p-limit "^3.0.2" p-map@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" + resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== dependencies: aggregate-error "^3.0.0" p-timeout@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz" + resolved "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" integrity sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA== dependencies: p-finally "^1.0.0" p-try@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" + resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== p-try@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== pako@~1.0.5: version "1.0.11" - resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz" + resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== parallel-transform@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz" + resolved "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== dependencies: cyclist "^1.0.1" @@ -12068,30 +12229,31 @@ parallel-transform@^1.1.0: parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== +parse-asn1@^5.0.0, parse-asn1@^5.1.7: + version "5.1.7" + resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz#73cdaaa822125f9647165625eb45f8a051d2df06" + integrity sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg== dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" + asn1.js "^4.10.1" + browserify-aes "^1.2.0" + evp_bytestokey "^1.0.3" + hash-base "~3.0" + pbkdf2 "^3.1.2" + safe-buffer "^5.2.1" parse-duration@^1.0.0: - version "1.0.3" - resolved "https://registry.npmjs.org/parse-duration/-/parse-duration-1.0.3.tgz" - integrity sha512-o6NAh12na5VvR6nFejkU0gpQ8jmOY9Y9sTU2ke3L3G/d/3z8jqmbBbeyBGHU73P4JLXfc7tJARygIK3WGIkloA== + version "1.1.0" + resolved "https://registry.npmjs.org/parse-duration/-/parse-duration-1.1.0.tgz#5192084c5d8f2a3fd676d04a451dbd2e05a1819c" + integrity sha512-z6t9dvSJYaPoQq7quMzdEagSFtpGu+utzHqqxmpVWNNZRIXnvqyCvn9XsTdh7c/w0Bqmdz3RB3YnRaKtpRtEXQ== parse-entities@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz" + resolved "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== dependencies: character-entities "^1.0.0" @@ -12103,7 +12265,7 @@ parse-entities@^2.0.0: parse-json@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== dependencies: error-ex "^1.3.1" @@ -12111,7 +12273,7 @@ parse-json@^4.0.0: parse-json@^5.0.0: version "5.2.0" - resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: "@babel/code-frame" "^7.0.0" @@ -12121,118 +12283,118 @@ parse-json@^5.0.0: parse-ms@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz" + resolved "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== parse-passwd@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz" + resolved "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== parse-static-imports@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/parse-static-imports/-/parse-static-imports-1.1.0.tgz" + resolved "https://registry.npmjs.org/parse-static-imports/-/parse-static-imports-1.1.0.tgz#ae2f18f18da1a993080ae406a5219455c0bbad5d" integrity sha512-HlxrZcISCblEV0lzXmAHheH/8qEkKgmqkdxyHTPbSqsTUV8GzqmN1L+SSti+VbNPfbBO3bYLPHDiUs2avbAdbA== parse5@6.0.1, parse5@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" + resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== parseurl@~1.3.3: version "1.3.3" - resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== pascalcase@^0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz" + resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== path-browserify@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz" + resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== path-dirname@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz" + resolved "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" integrity sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q== path-exists@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@1.0.1, path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" + resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-posix@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz" + resolved "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz#06b26113f56beab042545a23bfa88003ccac260f" integrity sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA== path-root-regex@^0.1.0: version "0.1.2" - resolved "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz" + resolved "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" integrity sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ== path-root@^0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz" + resolved "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" integrity sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg== dependencies: path-root-regex "^0.1.0" path-to-regexp@0.1.7: version "0.1.7" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== path-to-regexp@^1.7.0: version "1.8.0" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== dependencies: isarray "0.0.1" path-type@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz" + resolved "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== dependencies: pify "^3.0.0" path-type@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pbkdf2@^3.0.3: +pbkdf2@^3.0.3, pbkdf2@^3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz" + resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== dependencies: create-hash "^1.1.2" @@ -12241,93 +12403,98 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== pidtree@^0.3.0: version "0.3.1" - resolved "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz" + resolved "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA== pify@^2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" + resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== pify@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" + resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== pify@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" + resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== pinkie-promise@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + resolved "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" - resolved "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + resolved "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== +pirates@^4.0.1: + version "4.0.6" + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + pkg-dir@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== dependencies: find-up "^3.0.0" pkg-dir@^4.1.0: version "4.2.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" pkg-dir@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== dependencies: find-up "^5.0.0" pkg-up@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz" + resolved "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" integrity sha512-fjAPuiws93rm7mPUu21RdBnkeZNrbfCFCwfAhPWY+rR3zG0ubpe5cEReHOw5fIbfmsxEV/g2kSxGTATY3Bpnwg== dependencies: find-up "^2.1.0" pkg-up@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz" + resolved "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== dependencies: find-up "^3.0.0" please-upgrade-node@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz" + resolved "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== dependencies: semver-compare "^1.0.0" portfinder@^1.0.28: version "1.0.32" - resolved "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz" + resolved "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" integrity sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg== dependencies: async "^2.6.4" @@ -12336,103 +12503,103 @@ portfinder@^1.0.28: posix-character-classes@^0.1.0: version "0.1.1" - resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz" + resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== -postcss-import@^14.1.0: - version "14.1.0" - resolved "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz" - integrity sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw== +possible-typed-array-names@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" + integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + +postcss-import@^15.1.0: + version "15.1.0" + resolved "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" + integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew== dependencies: postcss-value-parser "^4.0.0" read-cache "^1.0.0" resolve "^1.1.7" -postcss-js@^4.0.0: +postcss-js@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz" + resolved "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2" integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw== dependencies: camelcase-css "^2.0.1" -postcss-load-config@^3.1.4: - version "3.1.4" - resolved "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz" - integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg== +postcss-load-config@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3" + integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== dependencies: - lilconfig "^2.0.5" - yaml "^1.10.2" + lilconfig "^3.0.0" + yaml "^2.3.4" postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== + version "3.1.0" + resolved "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== + version "4.0.5" + resolved "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz#f1b9bd757a8edf4d8556e8d0f4f894260e3df78f" + integrity sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw== dependencies: icss-utils "^5.0.0" postcss-selector-parser "^6.0.2" postcss-value-parser "^4.1.0" postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== + version "3.2.0" + resolved "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz#a43d28289a169ce2c15c00c4e64c0858e43457d5" + integrity sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ== dependencies: postcss-selector-parser "^6.0.4" postcss-modules-values@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz" + resolved "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== dependencies: icss-utils "^5.0.0" -postcss-nested@6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz" - integrity sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w== +postcss-nested@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c" + integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ== dependencies: - postcss-selector-parser "^6.0.10" + postcss-selector-parser "^6.0.11" -postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: - version "6.0.11" - resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz" - integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g== +postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: + version "6.1.0" + resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz#49694cb4e7c649299fea510a29fa6577104bcf53" + integrity sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" + resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.0.9, postcss@^8.1.4, postcss@^8.2.15: - version "8.4.31" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz" - integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== +postcss@^8.1.4, postcss@^8.2.15, postcss@^8.4.23: + version "8.4.39" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz#aa3c94998b61d3a9c259efa51db4b392e1bde0e3" + integrity sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw== dependencies: - nanoid "^3.3.6" - picocolors "^1.0.0" - source-map-js "^1.0.2" + nanoid "^3.3.7" + picocolors "^1.0.1" + source-map-js "^1.2.0" prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== - pretender@^3.2.0: version "3.4.7" - resolved "https://registry.npmjs.org/pretender/-/pretender-3.4.7.tgz" + resolved "https://registry.npmjs.org/pretender/-/pretender-3.4.7.tgz#34a2ae2d1fc9db440a990d50e6c0f5481d8755fc" integrity sha512-jkPAvt1BfRi0RKamweJdEcnjkeu7Es8yix3bJ+KgBC5VpG/Ln4JE3hYN6vJym4qprm8Xo5adhWpm3HCoft1dOw== dependencies: fake-xml-http-request "^2.1.2" @@ -12440,92 +12607,97 @@ pretender@^3.2.0: prettier-linter-helpers@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" + resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== dependencies: fast-diff "^1.1.2" prettier@^2.5.1: - version "2.8.4" - resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz" - integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw== + version "2.8.8" + resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== pretty-ms@^7.0.1: version "7.0.1" - resolved "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz" + resolved "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz#7d903eaab281f7d8e03c66f867e239dc32fb73e8" integrity sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q== dependencies: parse-ms "^2.1.0" printf@^0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/printf/-/printf-0.6.1.tgz" + resolved "https://registry.npmjs.org/printf/-/printf-0.6.1.tgz#b9afa3d3b55b7f2e8b1715272479fc756ed88650" integrity sha512-is0ctgGdPJ5951KulgfzvHGwJtZ5ck8l042vRkV6jrkpBzTmb/lueTqguWHy2JfVA+RY6gFVlaZgUS0j7S/dsw== +prismjs@^1.29.0: + version "1.29.0" + resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" + integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== + prismjs@~1.27.0: version "1.27.0" - resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz" + resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== private@^0.1.6, private@^0.1.8: version "0.1.8" - resolved "https://registry.npmjs.org/private/-/private-0.1.8.tgz" + resolved "https://registry.npmjs.org/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== process-relative-require@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/process-relative-require/-/process-relative-require-1.0.0.tgz" + resolved "https://registry.npmjs.org/process-relative-require/-/process-relative-require-1.0.0.tgz#1590dfcf5b8f2983ba53e398446b68240b4cc68a" integrity sha512-r8G5WJPozMJAiv8sDdVWKgJ4In/zBXqwJdMCGAXQt2Kd3HdbAuJVzWYM4JW150hWoaI9DjhtbjcsCCHIMxm8RA== dependencies: node-modules-path "^1.0.0" process@^0.11.10: version "0.11.10" - resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" + resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== progress@^2.0.0: version "2.0.3" - resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" + resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== promise-inflight@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz" + resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== promise-map-series@^0.2.1: version "0.2.3" - resolved "https://registry.npmjs.org/promise-map-series/-/promise-map-series-0.2.3.tgz" + resolved "https://registry.npmjs.org/promise-map-series/-/promise-map-series-0.2.3.tgz#c2d377afc93253f6bd03dbb77755eb88ab20a847" integrity sha512-wx9Chrutvqu1N/NHzTayZjE1BgIwt6SJykQoCOic4IZ9yUDjKyVYrpLa/4YCNsV61eRENfs29hrEquVuB13Zlw== dependencies: rsvp "^3.0.14" promise-map-series@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/promise-map-series/-/promise-map-series-0.3.0.tgz" + resolved "https://registry.npmjs.org/promise-map-series/-/promise-map-series-0.3.0.tgz#41873ca3652bb7a042b387d538552da9b576f8a1" integrity sha512-3npG2NGhTc8BWBolLLf8l/92OxMGaRLbqvIh9wjCHhDXNvk4zsxaTaCpiCunW09qWPrN2zeNSNwRLVBrQQtutA== promise.hash.helper@^1.0.7: version "1.0.8" - resolved "https://registry.npmjs.org/promise.hash.helper/-/promise.hash.helper-1.0.8.tgz" + resolved "https://registry.npmjs.org/promise.hash.helper/-/promise.hash.helper-1.0.8.tgz#8c5fa0570f6f96821f52364fd72292b2c5a114f7" integrity sha512-KYcnXctWUWyVD3W3Ye0ZDuA1N8Szrh85cVCxpG6xYrOk/0CttRtYCmU30nWsUch0NuExQQ63QXvzRE6FLimZmg== property-information@^5.0.0: version "5.6.0" - resolved "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz" + resolved "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== dependencies: xtend "^4.0.0" proxy-addr@~2.0.7: version "2.0.7" - resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" + resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== dependencies: forwarded "0.2.0" @@ -12533,17 +12705,17 @@ proxy-addr@~2.0.7: prr@~1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" + resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== psl@^1.1.33: version "1.9.0" - resolved "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz" + resolved "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== public-encrypt@^4.0.0: version "4.0.3" - resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz" + resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" @@ -12555,7 +12727,7 @@ public-encrypt@^4.0.0: pump@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz" + resolved "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== dependencies: end-of-stream "^1.1.0" @@ -12563,7 +12735,7 @@ pump@^2.0.0: pump@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" + resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== dependencies: end-of-stream "^1.1.0" @@ -12571,63 +12743,55 @@ pump@^3.0.0: pumpify@^1.3.3: version "1.5.1" - resolved "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz" + resolved "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== dependencies: duplexify "^3.6.0" inherits "^2.0.3" pump "^2.0.0" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" - integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== - -punycode@^1.2.4: +punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== punycode@^2.1.0, punycode@^2.1.1: - version "2.3.0" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz" - integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + version "2.3.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -qs@6.11.0, qs@^6.4.0: +qs@6.11.0: version "6.11.0" - resolved "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz" + resolved "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" +qs@^6.11.2, qs@^6.4.0: + version "6.12.2" + resolved "https://registry.npmjs.org/qs/-/qs-6.12.2.tgz#5443b587f3bf73ac68968de491e5b25bafe04478" + integrity sha512-x+NLUpx9SYrcwXtX7ob1gnkSems4i/mGZX5SlYxwIau6RrUSODO89TR/XDGGpn5RPWSYIB+aSfuSlV5+CmbTBg== + dependencies: + side-channel "^1.0.6" + querystring-es3@^0.2.0: version "0.2.1" - resolved "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz" + resolved "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" - integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== - querystringify@^2.1.1: version "2.2.0" - resolved "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz" + resolved "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -quick-lru@^5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz" - integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== - quick-temp@^0.1.2, quick-temp@^0.1.3, quick-temp@^0.1.5, quick-temp@^0.1.8: version "0.1.8" - resolved "https://registry.npmjs.org/quick-temp/-/quick-temp-0.1.8.tgz" + resolved "https://registry.npmjs.org/quick-temp/-/quick-temp-0.1.8.tgz#bab02a242ab8fb0dd758a3c9776b32f9a5d94408" integrity sha512-YsmIFfD9j2zaFwJkzI6eMG7y0lQP7YeWzgtFgNl38pGWZBSXJooZbOWwkcRot7Vt0Fg9L23pX0tqWU3VvLDsiA== dependencies: mktemp "~0.4.0" @@ -12636,7 +12800,7 @@ quick-temp@^0.1.2, quick-temp@^0.1.3, quick-temp@^0.1.5, quick-temp@^0.1.8: qunit-dom@^1.6.0: version "1.6.0" - resolved "https://registry.npmjs.org/qunit-dom/-/qunit-dom-1.6.0.tgz" + resolved "https://registry.npmjs.org/qunit-dom/-/qunit-dom-1.6.0.tgz#a4bea6a46329d221e4a317d712cb40709107b977" integrity sha512-YwSqcLjQcRI0fUFpaSWwU10KIJPFW5Qh+d3cT5DOgx81dypRuUSiPkKFmBY/CDs/R1KdHRadthkcXg2rqAon8Q== dependencies: broccoli-funnel "^3.0.3" @@ -12645,9 +12809,9 @@ qunit-dom@^1.6.0: ember-cli-version-checker "^5.1.1" qunit@^2.16.0, qunit@^2.17.2: - version "2.19.4" - resolved "https://registry.npmjs.org/qunit/-/qunit-2.19.4.tgz" - integrity sha512-aqUzzUeCqlleWYKlpgfdHHw9C6KxkB9H3wNfiBg5yHqQMzy0xw/pbCRHYFkjl8MsP/t8qkTQE+JTYL71azgiew== + version "2.21.0" + resolved "https://registry.npmjs.org/qunit/-/qunit-2.21.0.tgz#c3d35adb1c9df8176459665f2daf33170c0f8662" + integrity sha512-kJJ+uzx5xDWk0oRrbOZ3zsm+imPULE58ZMIrNl+3POZl4a1k6VXj2E4OiqTmZ9j6hh9egE3kNgnAti9Q+BG6Yw== dependencies: commander "7.2.0" node-watch "0.7.3" @@ -12655,14 +12819,14 @@ qunit@^2.16.0, qunit@^2.17.2: randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz" + resolved "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" @@ -12670,22 +12834,12 @@ randomfill@^1.0.3: range-parser@~1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.5.1: - version "2.5.1" - resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - raw-body@2.5.2: version "2.5.2" - resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" @@ -12695,7 +12849,7 @@ raw-body@2.5.2: raw-body@~1.1.0: version "1.1.7" - resolved "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz#1d027c2bfa116acc6623bca8f00016572a87d425" integrity sha512-WmJJU2e9Y6M5UzTOkHaM7xJGAPQD8PNzx3bAd2+uhZAim6wDk6dAZxPVYLF67XhbR4hmKGh33Lpmh4XWrCH5Mg== dependencies: bytes "1" @@ -12703,19 +12857,19 @@ raw-body@~1.1.0: react-is@^17.0.1: version "17.0.2" - resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" + resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== read-cache@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz" + resolved "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== dependencies: pify "^2.3.0" read-installed@~4.0.3: version "4.0.3" - resolved "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz" + resolved "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz#ff9b8b67f187d1e4c29b9feb31f6b223acd19067" integrity sha512-O03wg/IYuV/VtnK2h/KXEt9VIbMUFbk3ERG0Iu4FhLZw0EP0T9znqrYDGn6ncbEsXUFaUjiVAWXHzxwt3lhRPQ== dependencies: debuglog "^1.0.1" @@ -12729,7 +12883,7 @@ read-installed@~4.0.3: read-package-json@^2.0.0: version "2.1.2" - resolved "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz" + resolved "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz#6992b2b66c7177259feb8eaac73c3acd28b9222a" integrity sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA== dependencies: glob "^7.1.1" @@ -12739,48 +12893,48 @@ read-package-json@^2.0.0: read-pkg@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz" + resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" integrity sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA== dependencies: load-json-file "^4.0.0" normalize-package-data "^2.3.2" path-type "^3.0.0" -"readable-stream@1 || 2", readable-stream@~1.0.2: - version "1.0.34" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" - integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@^2.3.8, readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" "readable-stream@2 || 3", readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.2" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.8" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== +readable-stream@~1.0.2: + version "1.0.34" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== dependencies: core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" readdir-scoped-modules@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz" + resolved "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309" integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== dependencies: debuglog "^1.0.1" @@ -12790,7 +12944,7 @@ readdir-scoped-modules@^1.0.0: readdirp@^2.2.1: version "2.2.1" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" @@ -12799,14 +12953,14 @@ readdirp@^2.2.1: readdirp@~3.6.0: version "3.6.0" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: picomatch "^2.2.1" recast@^0.18.1: version "0.18.10" - resolved "https://registry.npmjs.org/recast/-/recast-0.18.10.tgz" + resolved "https://registry.npmjs.org/recast/-/recast-0.18.10.tgz#605ebbe621511eb89b6356a7e224bff66ed91478" integrity sha512-XNvYvkfdAN9QewbrxeTOjgINkdY/odTgTS56ZNEWL9Ml0weT4T3sFtvnTuF+Gxyu46ANcRm1ntrF6F5LAJPAaQ== dependencies: ast-types "0.13.3" @@ -12816,19 +12970,19 @@ recast@^0.18.1: recursive-readdir-sync@^1.0.6: version "1.0.6" - resolved "https://registry.npmjs.org/recursive-readdir-sync/-/recursive-readdir-sync-1.0.6.tgz" + resolved "https://registry.npmjs.org/recursive-readdir-sync/-/recursive-readdir-sync-1.0.6.tgz#1dbf6d32f3c5bb8d3cde97a6c588d547a9e13d56" integrity sha512-QhkBh/V7T3L2m8FrwZEZ/VnSZU35bv7DSy/VlKVfcq10zvwwuxeuDLH7DZYFGHFyXefHchZmsHFLELR7poGjog== redeyed@~1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/redeyed/-/redeyed-1.0.1.tgz" + resolved "https://registry.npmjs.org/redeyed/-/redeyed-1.0.1.tgz#e96c193b40c0816b00aec842698e61185e55498a" integrity sha512-8eEWsNCkV2rvwKLS1Cvp5agNjMhwRe2um+y32B2+3LqOzg4C9BBPs6vzAfV16Ivb8B9HPNKIqd8OrdBws8kNlQ== dependencies: esprima "~3.0.0" refractor@^3.5.0: version "3.6.0" - resolved "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz" + resolved "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a" integrity sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA== dependencies: hastscript "^6.0.0" @@ -12836,83 +12990,84 @@ refractor@^3.5.0: prismjs "~1.27.0" regenerate-unicode-properties@^10.1.0: - version "10.1.0" - resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz" - integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== + version "10.1.1" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" + integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== dependencies: regenerate "^1.4.2" regenerate@^1.2.1, regenerate@^1.4.2: version "1.4.2" - resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.10.5: version "0.10.5" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" integrity sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w== regenerator-runtime@^0.11.0: version "0.11.1" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-runtime@^0.13.4: version "0.13.11" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== regenerator-runtime@^0.14.0: - version "0.14.0" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz" - integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + version "0.14.1" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== regenerator-runtime@^0.9.5: version "0.9.6" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz#d33eb95d0d2001a4be39659707c51b0cb71ce029" integrity sha512-D0Y/JJ4VhusyMOd/o25a3jdUqN/bC85EFsaoL9Oqmy/O4efCh+xhp7yj2EEOsj974qvMkcW8AwUzJ1jB/MbxCw== regenerator-transform@^0.10.0: version "0.10.1" - resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== dependencies: babel-runtime "^6.18.0" babel-types "^6.19.0" private "^0.1.6" -regenerator-transform@^0.15.1: - version "0.15.1" - resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz" - integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg== +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== dependencies: "@babel/runtime" "^7.8.4" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz" + resolved "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== +regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2: + version "1.5.2" + resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" + integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" + call-bind "^1.0.6" + define-properties "^1.2.1" + es-errors "^1.3.0" + set-function-name "^2.0.1" regexpp@^3.0.0, regexpp@^3.1.0: version "3.2.0" - resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" + resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== regexpu-core@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" integrity sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ== dependencies: regenerate "^1.2.1" @@ -12921,7 +13076,7 @@ regexpu-core@^2.0.0: regexpu-core@^5.3.1: version "5.3.2" - resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== dependencies: "@babel/regjsgen" "^0.8.0" @@ -12933,33 +13088,33 @@ regexpu-core@^5.3.1: regjsgen@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz" + resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" integrity sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g== regjsparser@^0.1.4: version "0.1.5" - resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" integrity sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw== dependencies: jsesc "~0.5.0" regjsparser@^0.9.1: version "0.9.1" - resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== dependencies: jsesc "~0.5.0" rehype-stringify@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-8.0.0.tgz" + resolved "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-8.0.0.tgz#9b6afb599bcf3165f10f93fc8548f9a03d2ec2ba" integrity sha512-VkIs18G0pj2xklyllrPSvdShAV36Ff3yE5PUO9u36f6+2qJFnn22Z5gKwBOwgXviux4UC7K+/j13AnZfPICi/g== dependencies: hast-util-to-html "^7.1.1" remark-autolink-headings@^6.0.1: version "6.1.0" - resolved "https://registry.npmjs.org/remark-autolink-headings/-/remark-autolink-headings-6.1.0.tgz" + resolved "https://registry.npmjs.org/remark-autolink-headings/-/remark-autolink-headings-6.1.0.tgz#45fa1f8860e0fc6b78bcbc4b0f5d5dd696170e04" integrity sha512-oeMSIfjaNboWPDVKahQAjF8iJ8hsz5aI8KFzAmmBdznir7zBvkgUjYE/BrpWvd02DCf/mSQ1IklznLkl3dVvZQ== dependencies: "@types/hast" "^2.0.0" @@ -12969,12 +13124,12 @@ remark-autolink-headings@^6.0.1: remark-extract-frontmatter@^3.1.0: version "3.2.0" - resolved "https://registry.npmjs.org/remark-extract-frontmatter/-/remark-extract-frontmatter-3.2.0.tgz" + resolved "https://registry.npmjs.org/remark-extract-frontmatter/-/remark-extract-frontmatter-3.2.0.tgz#bab57f599114f233702dea819431eec28e708656" integrity sha512-PmYwNCo0cMAUV3oAGg5Hn6YSZgiSDwVdxLJmPIZ804aYuvE5mAzozo5AkO0C8ELroWrtN/f9zzb0jqFPBkMnwg== remark-footnotes@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-3.0.0.tgz" + resolved "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-3.0.0.tgz#5756b56f8464fa7ed80dbba0c966136305d8cb8d" integrity sha512-ZssAvH9FjGYlJ/PBVKdSmfyPc3Cz4rTWgZLI4iE/SX8Nt5l3o3oEjv3wwG5VD7xOjktzdwp5coac+kJV9l4jgg== dependencies: mdast-util-footnote "^0.1.0" @@ -12982,7 +13137,7 @@ remark-footnotes@^3.0.0: remark-frontmatter@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-3.0.0.tgz" + resolved "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-3.0.0.tgz#ca5d996361765c859bd944505f377d6b186a6ec6" integrity sha512-mSuDd3svCHs+2PyO29h7iijIZx4plX0fheacJcAoYAASfgzgVIcXGYSq9GFyYocFLftQs8IOmmkgtOovs6d4oA== dependencies: mdast-util-frontmatter "^0.2.0" @@ -12990,7 +13145,7 @@ remark-frontmatter@^3.0.0: remark-gfm@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/remark-gfm/-/remark-gfm-1.0.0.tgz" + resolved "https://registry.npmjs.org/remark-gfm/-/remark-gfm-1.0.0.tgz#9213643001be3f277da6256464d56fd28c3b3c0d" integrity sha512-KfexHJCiqvrdBZVbQ6RopMZGwaXz6wFJEfByIuEwGf0arvITHjiKKZ1dpXujjH9KZdm1//XJQwgfnJ3lmXaDPA== dependencies: mdast-util-gfm "^0.1.0" @@ -12998,7 +13153,7 @@ remark-gfm@^1.0.0: remark-hbs@^0.4.0: version "0.4.1" - resolved "https://registry.npmjs.org/remark-hbs/-/remark-hbs-0.4.1.tgz" + resolved "https://registry.npmjs.org/remark-hbs/-/remark-hbs-0.4.1.tgz#07f5ce6cc85d64c673fd4ef7cd5a51189a2abe20" integrity sha512-q1qnjA473z409IGqj3iu0Rex9YVN3cfwf6siPP+SQN9Yx66OxyL2cU4VHWK6IxWHSa/cughU2CBUbDPPsWxlfg== dependencies: unist-builder "^2.0.3" @@ -13006,28 +13161,28 @@ remark-hbs@^0.4.0: remark-normalize-headings@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/remark-normalize-headings/-/remark-normalize-headings-2.0.0.tgz" + resolved "https://registry.npmjs.org/remark-normalize-headings/-/remark-normalize-headings-2.0.0.tgz#2e7492f4935346dc5eca96ffdb5f588196233169" integrity sha512-nXeBQ7luKRWDcuUTnc0ffUYZ7+cO01FomSjnzpGTGCi7rcD9Wbis+z3adbNyqbYtsC+/+o1S+GLHTwh9crnZxA== dependencies: mdast-normalize-headings "^2.0.0" remark-parse@^9.0.0: version "9.0.0" - resolved "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz" + resolved "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640" integrity sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw== dependencies: mdast-util-from-markdown "^0.8.0" remark-rehype@^8.0.0: version "8.1.0" - resolved "https://registry.npmjs.org/remark-rehype/-/remark-rehype-8.1.0.tgz" + resolved "https://registry.npmjs.org/remark-rehype/-/remark-rehype-8.1.0.tgz#610509a043484c1e697437fa5eb3fd992617c945" integrity sha512-EbCu9kHgAxKmW1yEYjx3QafMyGY3q8noUbNUI5xyKbaFP89wbhDrKxyIQNukNYthzjNHZu6J7hwFg7hRm1svYA== dependencies: mdast-util-to-hast "^10.2.0" remark-slug@^6.0.0: version "6.1.0" - resolved "https://registry.npmjs.org/remark-slug/-/remark-slug-6.1.0.tgz" + resolved "https://registry.npmjs.org/remark-slug/-/remark-slug-6.1.0.tgz#0503268d5f0c4ecb1f33315c00465ccdd97923ce" integrity sha512-oGCxDF9deA8phWvxFuyr3oSJsdyUAxMFbA0mZ7Y1Sas+emILtO+e5WutF9564gDsEN4IXaQXm5pFo6MLH+YmwQ== dependencies: github-slugger "^1.0.0" @@ -13036,59 +13191,54 @@ remark-slug@^6.0.0: remove-trailing-separator@^1.0.1: version "1.1.0" - resolved "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz" + resolved "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.0.0, repeat-string@^1.6.1: +repeat-string@^1.0.0: version "1.6.1" - resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== repeating@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz" + resolved "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== dependencies: is-finite "^1.0.0" require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== require-from-string@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" + resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== requireindex@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz" + resolved "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz#3463cdb22ee151902635aa6c9535d4de9c2ef1ef" integrity sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww== requires-port@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== reselect@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz" + resolved "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147" integrity sha512-b/6tFZCmRhtBMa4xGqiiRp9jh9Aqi2A687Lo265cN0/QohJQEBPiQ52f4QB6i0eF3yp3hmLL21LSGBcML2dlxA== -reselect@^4.0.0: - version "4.1.7" - resolved "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz" - integrity sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A== +reselect@^4.0.0, reselect@^4.1.7: + version "4.1.8" + resolved "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" + integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== resolve-dir@^1.0.0, resolve-dir@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz" + resolved "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" integrity sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg== dependencies: expand-tilde "^2.0.0" @@ -13096,17 +13246,17 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1: resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-from@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve-package-path@^1.0.11, resolve-package-path@^1.2.2, resolve-package-path@^1.2.6: version "1.2.7" - resolved "https://registry.npmjs.org/resolve-package-path/-/resolve-package-path-1.2.7.tgz" + resolved "https://registry.npmjs.org/resolve-package-path/-/resolve-package-path-1.2.7.tgz#2a7bc37ad96865e239330e3102c31322847e652e" integrity sha512-fVEKHGeK85bGbVFuwO9o1aU0n3vqQGrezPc51JGu9UTXpFQfWq5qCeKxyaRUSvephs+06c5j5rPq/dzHGEo8+Q== dependencies: path-root "^0.1.1" @@ -13114,7 +13264,7 @@ resolve-package-path@^1.0.11, resolve-package-path@^1.2.2, resolve-package-path@ resolve-package-path@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/resolve-package-path/-/resolve-package-path-2.0.0.tgz" + resolved "https://registry.npmjs.org/resolve-package-path/-/resolve-package-path-2.0.0.tgz#7f258ab86ff074fff4ff8027a28f94d17d6fb1df" integrity sha512-/CLuzodHO2wyyHTzls5Qr+EFeG6RcW4u6//gjYvUfcfyuplIX1SSccU+A5A9A78Gmezkl3NBkFAMxLbzTY9TJA== dependencies: path-root "^0.1.1" @@ -13122,7 +13272,7 @@ resolve-package-path@^2.0.0: resolve-package-path@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/resolve-package-path/-/resolve-package-path-3.1.0.tgz" + resolved "https://registry.npmjs.org/resolve-package-path/-/resolve-package-path-3.1.0.tgz#35faaa5d54a9c7dd481eb7c4b2a44410c9c763d8" integrity sha512-2oC2EjWbMJwvSN6Z7DbDfJMnD8MYEouaLn5eIX0j8XwPsYCVIyY9bbnX88YHVkbr8XHqvZrYbxaLPibfTYKZMA== dependencies: path-root "^0.1.1" @@ -13130,14 +13280,14 @@ resolve-package-path@^3.1.0: resolve-package-path@^4.0.1, resolve-package-path@^4.0.3: version "4.0.3" - resolved "https://registry.npmjs.org/resolve-package-path/-/resolve-package-path-4.0.3.tgz" + resolved "https://registry.npmjs.org/resolve-package-path/-/resolve-package-path-4.0.3.tgz#31dab6897236ea6613c72b83658d88898a9040aa" integrity sha512-SRpNAPW4kewOaNUt8VPqhJ0UMxawMwzJD8V7m1cJfdSTK9ieZwS6K7Dabsm4bmLFM96Z5Y/UznrpG5kt1im8yA== dependencies: path-root "^0.1.1" resolve-path@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz" + resolved "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz#c4bda9f5efb2fce65247873ab36bb4d834fe16f7" integrity sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w== dependencies: http-errors "~1.6.2" @@ -13145,30 +13295,30 @@ resolve-path@^1.4.0: resolve-url@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz" + resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== -resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.3.3, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1: +resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.2, resolve@^1.22.8, resolve@^1.3.3, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1: version "1.22.8" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^2.0.0-next.4: - version "2.0.0-next.4" - resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz" - integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ== +resolve@^2.0.0-next.5: + version "2.0.0-next.5" + resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== dependencies: - is-core-module "^2.9.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" restore-cursor@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz" + resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== dependencies: onetime "^2.0.0" @@ -13176,58 +13326,51 @@ restore-cursor@^2.0.0: restore-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" + resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== dependencies: onetime "^5.1.0" signal-exit "^3.0.2" -resumer@^0.0.0: - version "0.0.0" - resolved "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz" - integrity sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w== - dependencies: - through "~2.3.4" - ret@~0.1.10: version "0.1.15" - resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz" + resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== reusify@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== rfdc@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz" - integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + version "1.4.1" + resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== rimraf@^2.2.8, rimraf@^2.3.4, rimraf@^2.4.3, rimraf@^2.5.3, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" rimraf@^3.0.0, rimraf@^3.0.1, rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" rimraf@~2.6.2: version "2.6.3" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz" + resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" @@ -13235,110 +13378,120 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: rollup-pluginutils@^2.8.1: version "2.8.2" - resolved "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz" + resolved "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== dependencies: estree-walker "^0.6.1" rollup@^2.50.0: version "2.79.1" - resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz" + resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== optionalDependencies: fsevents "~2.3.2" route-recognizer@^0.3.3: version "0.3.4" - resolved "https://registry.npmjs.org/route-recognizer/-/route-recognizer-0.3.4.tgz" + resolved "https://registry.npmjs.org/route-recognizer/-/route-recognizer-0.3.4.tgz#39ab1ffbce1c59e6d2bdca416f0932611e4f3ca3" integrity sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g== rsvp@^3.0.14, rsvp@^3.0.17, rsvp@^3.0.18, rsvp@^3.0.21, rsvp@^3.0.6, rsvp@^3.1.0: version "3.6.2" - resolved "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz" + resolved "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw== rsvp@^4.7.0, rsvp@^4.8.1, rsvp@^4.8.2, rsvp@^4.8.4, rsvp@^4.8.5: version "4.8.5" - resolved "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz" + resolved "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== rsvp@~3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/rsvp/-/rsvp-3.2.1.tgz" + resolved "https://registry.npmjs.org/rsvp/-/rsvp-3.2.1.tgz#07cb4a5df25add9e826ebc67dcc9fd89db27d84a" integrity sha512-Rf4YVNYpKjZ6ASAmibcwTNciQ5Co5Ztq6iZPEykHpkoflnD/K5ryE/rHehFsTm4NJj8nKDhbi3eKBWGogmNnkg== run-async@^2.2.0, run-async@^2.4.0: version "2.4.1" - resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz" + resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz" + resolved "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" integrity sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg== dependencies: aproba "^1.1.1" rxjs@^6.4.0, rxjs@^6.6.0: version "6.6.7" - resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz" + resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== dependencies: tslib "^1.9.0" rxjs@^7.5.1: - version "7.8.0" - resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz" - integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg== + version "7.8.1" + resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== dependencies: tslib "^2.1.0" -safe-buffer@5.1.2, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-array-concat@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" + integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" + has-symbols "^1.0.3" + isarray "^2.0.5" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-json-parse@~1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz" + resolved "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57" integrity sha512-o0JmTu17WGUaUOHa1l0FPGXKBfijbxK6qoHzlkihsDXxzBHvJcA7zgviKR92Xs841rX9pK16unfphLq0/KqX7A== -safe-regex-test@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz" - integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== +safe-regex-test@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" + integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" + call-bind "^1.0.6" + es-errors "^1.3.0" is-regex "^1.1.4" safe-regex@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz" + resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0: +"safer-buffer@>= 2.1.2 < 3": version "2.1.2" - resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sane@^4.0.0, sane@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz" + resolved "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== dependencies: "@cnakazawa/watch" "^1.0.3" @@ -13351,10 +13504,10 @@ sane@^4.0.0, sane@^4.1.0: minimist "^1.1.1" walker "~1.0.5" -sass@^1.28.0, sass@^1.49.7, sass@^1.62.1: - version "1.69.3" - resolved "https://registry.npmjs.org/sass/-/sass-1.69.3.tgz" - integrity sha512-X99+a2iGdXkdWn1akFPs0ZmelUzyAQfvqYc2P/MPTrJRuIRoTffGzT9W9nFqG00S+c8hXzVmgxhUuHFdrwxkhQ== +sass@^1.28.0, sass@^1.69.5: + version "1.77.6" + resolved "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz#898845c1348078c2e6d1b64f9ee06b3f8bd489e4" + integrity sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q== dependencies: chokidar ">=3.0.0 <4.0.0" immutable "^4.0.0" @@ -13362,14 +13515,14 @@ sass@^1.28.0, sass@^1.49.7, sass@^1.62.1: saxes@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz" + resolved "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== dependencies: xmlchars "^2.2.0" schema-utils@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== dependencies: ajv "^6.1.0" @@ -13378,67 +13531,65 @@ schema-utils@^1.0.0: schema-utils@^2.6.5: version "2.7.1" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== dependencies: "@types/json-schema" "^7.0.5" ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== +schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== dependencies: "@types/json-schema" "^7.0.8" ajv "^6.12.5" ajv-keywords "^3.5.2" schema-utils@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz" - integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + version "4.2.0" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" + integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== dependencies: "@types/json-schema" "^7.0.9" - ajv "^8.8.0" + ajv "^8.9.0" ajv-formats "^2.1.1" - ajv-keywords "^5.0.0" + ajv-keywords "^5.1.0" select@^1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/select/-/select-1.1.2.tgz" + resolved "https://registry.npmjs.org/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" integrity sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA== semver-compare@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz" + resolved "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow== semver-regex@^3.1.2: version "3.1.4" - resolved "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz" + resolved "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz#13053c0d4aa11d070a2f2872b6b1e3ae1e1971b4" integrity sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA== -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: + version "5.7.2" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^6.0.0, semver@^6.1.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.8: - version "7.3.8" - resolved "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== - dependencies: - lru-cache "^6.0.0" +semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.8, semver@^7.5.3: + version "7.6.2" + resolved "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== send@0.18.0: version "0.18.0" - resolved "https://registry.npmjs.org/send/-/send-0.18.0.tgz" + resolved "https://registry.npmjs.org/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" @@ -13457,21 +13608,21 @@ send@0.18.0: serialize-javascript@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== dependencies: randombytes "^2.1.0" serialize-javascript@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz" - integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== + version "6.0.2" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== dependencies: randombytes "^2.1.0" serve-static@1.15.0: version "1.15.0" - resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz" + resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== dependencies: encodeurl "~1.0.2" @@ -13481,12 +13632,34 @@ serve-static@1.15.0: set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +set-function-name@^2.0.1, set-function-name@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.2" + set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz" + resolved "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== dependencies: extend-shallow "^2.0.1" @@ -13496,22 +13669,22 @@ set-value@^2.0.0, set-value@^2.0.1: setimmediate@^1.0.4: version "1.0.5" - resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" + resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== setprototypeof@1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== setprototypeof@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" - resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz" + resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: inherits "^2.0.1" @@ -13519,67 +13692,68 @@ sha.js@^2.4.0, sha.js@^2.4.8: shebang-command@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== dependencies: shebang-regex "^1.0.0" shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.6.1: - version "1.8.0" - resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.0.tgz" - integrity sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ== + version "1.8.1" + resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== shellwords@^0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz" + resolved "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== +side-channel@^1.0.4, side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== silent-error@^1.0.0, silent-error@^1.0.1, silent-error@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/silent-error/-/silent-error-1.1.1.tgz" + resolved "https://registry.npmjs.org/silent-error/-/silent-error-1.1.1.tgz#f72af5b0d73682a2ba1778b7e32cd8aa7c2d8662" integrity sha512-n4iEKyNcg4v6/jpb3c0/iyH2G1nzUNl7Gpqtn/mHIJK9S/q/7MCfoO4rwVOoO59qPFIc0hVHvMbiOJ0NdtxKKw== dependencies: debug "^2.2.0" simple-html-tokenizer@^0.5.10, simple-html-tokenizer@^0.5.11, simple-html-tokenizer@^0.5.8: version "0.5.11" - resolved "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.11.tgz" + resolved "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.11.tgz#4c5186083c164ba22a7b477b7687ac056ad6b1d9" integrity sha512-C2WEK/Z3HoSFbYq8tI7ni3eOo/NneSPRoPpcM7WdLjFOArFuyXEjAoCdOC3DgMfRyziZQ1hCNR4mrNdWEvD0og== sinon@^9.0.0: version "9.2.4" - resolved "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz" + resolved "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz#e55af4d3b174a4443a8762fa8421c2976683752b" integrity sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg== dependencies: "@sinonjs/commons" "^1.8.1" @@ -13591,17 +13765,17 @@ sinon@^9.0.0: slash@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz" + resolved "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg== slash@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== slice-ansi@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== dependencies: ansi-styles "^4.0.0" @@ -13610,7 +13784,7 @@ slice-ansi@^3.0.0: slice-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== dependencies: ansi-styles "^4.0.0" @@ -13619,36 +13793,20 @@ slice-ansi@^4.0.0: slide@~1.1.3: version "1.1.6" - resolved "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz" + resolved "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" integrity sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw== snake-case@^3.0.3: version "3.0.4" - resolved "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz" + resolved "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== dependencies: dot-case "^3.0.4" tslib "^2.0.3" -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - snapdragon@^0.8.1: version "0.8.2" - resolved "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz" + resolved "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" @@ -13661,40 +13819,42 @@ snapdragon@^0.8.1: use "^3.1.0" socket.io-adapter@~2.5.2: - version "2.5.2" - resolved "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz" - integrity sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA== + version "2.5.5" + resolved "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz#c7a1f9c703d7756844751b6ff9abfc1780664082" + integrity sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg== dependencies: - ws "~8.11.0" + debug "~4.3.4" + ws "~8.17.1" -socket.io-parser@~4.2.1: - version "4.2.2" - resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz" - integrity sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw== +socket.io-parser@~4.2.4: + version "4.2.4" + resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" + integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== dependencies: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" -socket.io@^4.1.2: - version "4.6.1" - resolved "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz" - integrity sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA== +socket.io@^4.5.4: + version "4.7.5" + resolved "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz#56eb2d976aef9d1445f373a62d781a41c7add8f8" + integrity sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA== dependencies: accepts "~1.3.4" base64id "~2.0.0" + cors "~2.8.5" debug "~4.3.2" - engine.io "~6.4.1" + engine.io "~6.5.2" socket.io-adapter "~2.5.2" - socket.io-parser "~4.2.1" + socket.io-parser "~4.2.4" sort-object-keys@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz" + resolved "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg== sort-package-json@^1.49.0: version "1.57.0" - resolved "https://registry.npmjs.org/sort-package-json/-/sort-package-json-1.57.0.tgz" + resolved "https://registry.npmjs.org/sort-package-json/-/sort-package-json-1.57.0.tgz#e95fb44af8ede0bb6147e3f39258102d4bb23fc4" integrity sha512-FYsjYn2dHTRb41wqnv+uEqCUvBpK3jZcTp9rbz2qDTmel7Pmdtf+i2rLaaPMRZeSVM60V3Se31GyWFpmKs4Q5Q== dependencies: detect-indent "^6.0.0" @@ -13706,17 +13866,17 @@ sort-package-json@^1.49.0: source-list-map@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz" + resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== source-map-resolve@^0.5.0: version "0.5.3" - resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz" + resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: atob "^2.1.2" @@ -13727,7 +13887,7 @@ source-map-resolve@^0.5.0: source-map-resolve@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz" + resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2" integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== dependencies: atob "^2.1.2" @@ -13735,14 +13895,14 @@ source-map-resolve@^0.6.0: source-map-support@^0.4.15: version "0.4.18" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== dependencies: source-map "^0.5.6" source-map-support@~0.5.12, source-map-support@~0.5.20: version "0.5.21" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" @@ -13750,51 +13910,51 @@ source-map-support@~0.5.12, source-map-support@~0.5.20: source-map-url@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz" + resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" integrity sha512-QU4fa0D6aSOmrT+7OHpUXw+jS84T0MLaQNtFs8xzLNe6Arj44Magd7WEbyVW5LNYoAPVV35aKs4azxIfVJrToQ== source-map-url@^0.4.0: version "0.4.1" - resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz" + resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== source-map@0.4.x, source-map@^0.4.2: version "0.4.4" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" integrity sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A== dependencies: amdefine ">=0.0.4" source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@~0.1.x: version "0.1.43" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" integrity sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ== dependencies: amdefine ">=0.0.4" -source-map@~0.7.3: +source-map@~0.7.4: version "0.7.4" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== sourcemap-codec@^1.4.8: version "1.4.8" - resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" + resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== sourcemap-validator@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/sourcemap-validator/-/sourcemap-validator-1.1.1.tgz" + resolved "https://registry.npmjs.org/sourcemap-validator/-/sourcemap-validator-1.1.1.tgz#3d7d8a399ccab09c1fedc510d65436e25b1c386b" integrity sha512-pq6y03Vs6HUaKo9bE0aLoksAcpeOo9HZd7I8pI6O480W/zxNZ9U32GfzgtPP0Pgc/K1JHna569nAbOk3X8/Qtw== dependencies: jsesc "~0.3.x" @@ -13804,17 +13964,17 @@ sourcemap-validator@^1.1.0: space-separated-tokens@^1.0.0: version "1.1.5" - resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz" + resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== spawn-args@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/spawn-args/-/spawn-args-0.2.0.tgz" + resolved "https://registry.npmjs.org/spawn-args/-/spawn-args-0.2.0.tgz#fb7d0bd1d70fd4316bd9e3dec389e65f9d6361bb" integrity sha512-73BoniQDcRWgnLAf/suKH6V5H54gd1KLzwYN9FB6J/evqTV33htH9xwV/4BHek+++jzxpVlZQKKZkqstPQPmQg== spdx-compare@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz" + resolved "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz#2c55f117362078d7409e6d7b08ce70a857cd3ed7" integrity sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A== dependencies: array-find-index "^1.0.2" @@ -13823,83 +13983,83 @@ spdx-compare@^1.0.0: spdx-correct@^3.0.0: version "3.2.0" - resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz" + resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + version "2.5.0" + resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== spdx-expression-parse@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" + resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.13" - resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz" - integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w== + version "3.0.18" + resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" + integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== spdx-ranges@^2.0.0: version "2.1.1" - resolved "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz" + resolved "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz#87573927ba51e92b3f4550ab60bfc83dd07bac20" integrity sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA== spdx-satisfies@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/spdx-satisfies/-/spdx-satisfies-4.0.1.tgz" + resolved "https://registry.npmjs.org/spdx-satisfies/-/spdx-satisfies-4.0.1.tgz#9a09a68d80f5f1a31cfaebb384b0c6009e4969fe" integrity sha512-WVzZ/cXAzoNmjCWiEluEA3BjHp5tiUmmhn9MK+X0tBbR9sOqtC6UQwmgCNrAIZvNlMuBUYAaHYfb2oqlF9SwKA== dependencies: spdx-compare "^1.0.0" spdx-expression-parse "^3.0.0" spdx-ranges "^2.0.0" -split-string@^3.0.1, split-string@^3.0.2: +split-string@^3.0.1: version "3.1.0" - resolved "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz" + resolved "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" sprintf-js@^1.1.1: - version "1.1.2" - resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz" - integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== + version "1.1.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" + integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== sri-toolbox@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/sri-toolbox/-/sri-toolbox-0.2.0.tgz" + resolved "https://registry.npmjs.org/sri-toolbox/-/sri-toolbox-0.2.0.tgz#a7fea5c3fde55e675cf1c8c06f3ebb5c2935835e" integrity sha512-DQIMWCAr/M7phwo+d3bEfXwSBEwuaJL+SJx9cuqt1Ty7K96ZFoHpYnSbhrQZEr0+0/GtmpKECP8X/R4RyeTAfw== ssri@^6.0.1: version "6.0.2" - resolved "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz" + resolved "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== dependencies: figgy-pudding "^3.5.1" stagehand@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/stagehand/-/stagehand-1.0.1.tgz" + resolved "https://registry.npmjs.org/stagehand/-/stagehand-1.0.1.tgz#0cbca6f906e4a7be36c5830dc31d9cc7091a827e" integrity sha512-GqXBq2SPWv9hTXDFKS8WrKK1aISB0aKGHZzH+uD4ShAgs+Fz20ZfoerLOm8U+f62iRWLrw6nimOY/uYuTcVhvg== dependencies: debug "^4.1.0" static-extend@^0.1.1: version "0.1.2" - resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz" + resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== dependencies: define-property "^0.2.5" @@ -13907,24 +14067,24 @@ static-extend@^0.1.1: statuses@2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" + resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== "statuses@>= 1.4.0 < 2", statuses@~1.5.0: version "1.5.0" - resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== stop-iteration-iterator@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz" + resolved "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" integrity sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ== dependencies: internal-slot "^1.0.4" stream-browserify@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz" + resolved "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== dependencies: inherits "~2.0.1" @@ -13932,7 +14092,7 @@ stream-browserify@^2.0.1: stream-each@^1.1.0: version "1.2.3" - resolved "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz" + resolved "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== dependencies: end-of-stream "^1.1.0" @@ -13940,7 +14100,7 @@ stream-each@^1.1.0: stream-http@^2.7.2: version "2.8.3" - resolved "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz" + resolved "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== dependencies: builtin-status-codes "^3.0.0" @@ -13950,23 +14110,23 @@ stream-http@^2.7.2: xtend "^4.0.0" stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + version "1.0.3" + resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== string-argv@0.3.1: version "0.3.1" - resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz" + resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== string-template@~0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz" + resolved "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" integrity sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw== string-width@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" + resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== dependencies: code-point-at "^1.0.0" @@ -13975,7 +14135,7 @@ string-width@^1.0.1: "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -13984,84 +14144,90 @@ string-width@^1.0.1: string-width@^2.1.0: version "2.1.1" - resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" + resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" string.prototype.matchall@^4.0.5: - version "4.0.8" - resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz" - integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - get-intrinsic "^1.1.3" + version "4.0.11" + resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" + integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" + gopd "^1.0.1" has-symbols "^1.0.3" - internal-slot "^1.0.3" - regexp.prototype.flags "^1.4.3" - side-channel "^1.0.4" + internal-slot "^1.0.7" + regexp.prototype.flags "^1.5.2" + set-function-name "^2.0.2" + side-channel "^1.0.6" string.prototype.padend@^3.0.0: - version "3.1.4" - resolved "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz" - integrity sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -string.prototype.trim@^1.2.7: - version "1.2.7" - resolved "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz" - integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -string.prototype.trimend@^1.0.6: - version "1.0.6" - resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz" - integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== + version "3.1.6" + resolved "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz#ba79cf8992609a91c872daa47c6bb144ee7f62a5" + integrity sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + +string.prototype.trim@^1.2.9: + version "1.2.9" + resolved "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" + integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-object-atoms "^1.0.0" + +string.prototype.trimend@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" + integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" -string.prototype.trimstart@^1.0.6: - version "1.0.6" - resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz" - integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" string_decoder@0.10, string_decoder@~0.10.x: version "0.10.31" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" stringify-entities@^3.0.1: version "3.1.0" - resolved "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.1.0.tgz" + resolved "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.1.0.tgz#b8d3feac256d9ffcc9fa1fefdcf3ca70576ee903" integrity sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg== dependencies: character-entities-html4 "^1.0.0" @@ -14070,7 +14236,7 @@ stringify-entities@^3.0.1: stringify-object@^3.3.0: version "3.3.0" - resolved "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz" + resolved "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== dependencies: get-own-enumerable-property-symbols "^3.0.0" @@ -14079,65 +14245,60 @@ stringify-object@^3.3.0: strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== dependencies: ansi-regex "^3.0.0" strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" -strip-ansi@~0.1.0: - version "0.1.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz" - integrity sha512-behete+3uqxecWlDAm5lmskaSaISA+ThQ4oNNBDTBJt0x2ppR6IPqfZNuj6BLaLJ/Sji4TPZlcRyOis8wXQTLg== - strip-bom@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-bom@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== strip-eof@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz" + resolved "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== strip-final-newline@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== style-loader@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz" + resolved "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz#9669602fd4690740eaaec137799a03addbbc393c" integrity sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ== dependencies: loader-utils "^2.0.0" @@ -14145,60 +14306,73 @@ style-loader@^2.0.0: styled_string@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/styled_string/-/styled_string-0.0.1.tgz" + resolved "https://registry.npmjs.org/styled_string/-/styled_string-0.0.1.tgz#d22782bd81295459bc4f1df18c4bad8e94dd124a" integrity sha512-DU2KZiB6VbPkO2tGSqQ9n96ZstUPjW7X4sGO6V2m1myIQluX0p1Ol8BrA/l6/EesqhMqXOIXs3cJNOy1UuU2BA== +sucrase@^3.32.0: + version "3.35.0" + resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" + integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + glob "^10.3.10" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + ts-interface-checker "^0.1.9" + sum-up@^1.0.1: version "1.0.3" - resolved "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz" + resolved "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz#1c661f667057f63bcb7875aa1438bc162525156e" integrity sha512-zw5P8gnhiqokJUWRdR6F4kIIIke0+ubQSGyYUY506GCbJWtV7F6Xuy0j6S125eSX2oF+a8KdivsZ8PlVEH0Mcw== dependencies: chalk "^1.0.0" supports-color@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" supports-color@^8.0.0: version "8.1.1" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: has-flag "^4.0.0" supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== symbol-tree@^3.2.4: version "3.2.4" - resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz" + resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== symlink-or-copy@^1.0.0, symlink-or-copy@^1.0.1, symlink-or-copy@^1.1.8, symlink-or-copy@^1.2.0, symlink-or-copy@^1.3.1: version "1.3.1" - resolved "https://registry.npmjs.org/symlink-or-copy/-/symlink-or-copy-1.3.1.tgz" + resolved "https://registry.npmjs.org/symlink-or-copy/-/symlink-or-copy-1.3.1.tgz#9506dd64d8e98fa21dcbf4018d1eab23e77f71fe" integrity sha512-0K91MEXFpBUaywiwSSkmKjnGcasG/rVBXFLJz5DrgGabpYD6N+3yZrfD6uUIfpuTu65DZLHi7N8CizHc07BPZA== sync-disk-cache@^1.3.3: version "1.3.4" - resolved "https://registry.npmjs.org/sync-disk-cache/-/sync-disk-cache-1.3.4.tgz" + resolved "https://registry.npmjs.org/sync-disk-cache/-/sync-disk-cache-1.3.4.tgz#53a2c5a09d8f4bb53160bce182a456ad71574024" integrity sha512-GlkGeM81GPPEKz/lH7QUTbvqLq7K/IUTuaKDSMulP9XQ42glqNJIN/RKgSOw4y8vxL1gOVvj+W7ruEO4s36eCw== dependencies: debug "^2.1.3" @@ -14209,7 +14383,7 @@ sync-disk-cache@^1.3.3: sync-disk-cache@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/sync-disk-cache/-/sync-disk-cache-2.1.0.tgz" + resolved "https://registry.npmjs.org/sync-disk-cache/-/sync-disk-cache-2.1.0.tgz#01e879edc41c34a01fcdda5b39d47dd496e154a6" integrity sha512-vngT2JmkSapgq0z7uIoYtB9kWOOzMihAAYq/D3Pjm/ODOGMgS4r++B+OZ09U4hWR6EaOdy9eqQ7/8ygbH3wehA== dependencies: debug "^4.1.1" @@ -14220,13 +14394,13 @@ sync-disk-cache@^2.0.0: tabbable@^5.3.3: version "5.3.3" - resolved "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz" + resolved "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz#aac0ff88c73b22d6c3c5a50b1586310006b47fbf" integrity sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA== table@^6.0.9: - version "6.8.1" - resolved "https://registry.npmjs.org/table/-/table-6.8.1.tgz" - integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + version "6.8.2" + resolved "https://registry.npmjs.org/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58" + integrity sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA== dependencies: ajv "^8.0.1" lodash.truncate "^4.4.2" @@ -14235,37 +14409,36 @@ table@^6.0.9: strip-ansi "^6.0.1" tailwindcss@^3.1.8: - version "3.2.7" - resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.7.tgz" - integrity sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ== + version "3.4.4" + resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz#351d932273e6abfa75ce7d226b5bf3a6cb257c05" + integrity sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A== dependencies: + "@alloc/quick-lru" "^5.2.0" arg "^5.0.2" chokidar "^3.5.3" - color-name "^1.1.4" - detective "^5.2.1" didyoumean "^1.2.2" dlv "^1.1.3" - fast-glob "^3.2.12" + fast-glob "^3.3.0" glob-parent "^6.0.2" is-glob "^4.0.3" - lilconfig "^2.0.6" + jiti "^1.21.0" + lilconfig "^2.1.0" micromatch "^4.0.5" normalize-path "^3.0.0" object-hash "^3.0.0" picocolors "^1.0.0" - postcss "^8.0.9" - postcss-import "^14.1.0" - postcss-js "^4.0.0" - postcss-load-config "^3.1.4" - postcss-nested "6.0.0" + postcss "^8.4.23" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.1" + postcss-nested "^6.0.1" postcss-selector-parser "^6.0.11" - postcss-value-parser "^4.2.0" - quick-lru "^5.1.1" - resolve "^1.22.1" + resolve "^1.22.2" + sucrase "^3.32.0" tap-parser@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/tap-parser/-/tap-parser-7.0.0.tgz" + resolved "https://registry.npmjs.org/tap-parser/-/tap-parser-7.0.0.tgz#54db35302fda2c2ccc21954ad3be22b2cba42721" integrity sha512-05G8/LrzqOOFvZhhAk32wsGiPZ1lfUrl+iV7+OkKgfofZxiceZWMHkKmow71YsyVQ8IvGBP2EjcIjE5gL4l5lA== dependencies: events-to-array "^1.0.1" @@ -14274,44 +14447,45 @@ tap-parser@^7.0.0: tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz" + resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tapable@^2.1.1, tapable@^2.2.0: +tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" - resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" + resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== tape@^5.0.1: - version "5.6.3" - resolved "https://registry.npmjs.org/tape/-/tape-5.6.3.tgz" - integrity sha512-cUDDGSbyoSIpdUAqbqLI/r7i/S4BHuCB9M5j7E/LrLs/x/i4zeAJ798aqo+FGo+kr9seBZwr8AkZW6rjceyAMQ== - dependencies: - array.prototype.every "^1.1.4" - call-bind "^1.0.2" - deep-equal "^2.2.0" + version "5.8.1" + resolved "https://registry.npmjs.org/tape/-/tape-5.8.1.tgz#76fc0ddad652e9714355932fb56eb7c463d5232f" + integrity sha512-pUzADXBVYm5Jkneh9hfXnirADrzQrDA3vddKbPOc/ZLORj4dFQ6GR1KdGWX0/NvOLDcYkVgeMdw78Uf6BzO3KA== + dependencies: + "@ljharb/resumer" "^0.1.3" + "@ljharb/through" "^2.3.13" + array.prototype.every "^1.1.6" + call-bind "^1.0.7" + deep-equal "^2.2.3" defined "^1.0.1" dotignore "^0.1.2" for-each "^0.3.3" get-package-type "^0.1.0" glob "^7.2.3" - has "^1.0.3" - has-dynamic-import "^2.0.1" + has-dynamic-import "^2.1.0" + hasown "^2.0.2" inherits "^2.0.4" is-regex "^1.1.4" - minimist "^1.2.7" - object-inspect "^1.12.3" - object-is "^1.1.5" + minimist "^1.2.8" + mock-property "^1.0.3" + object-inspect "^1.13.1" + object-is "^1.1.6" object-keys "^1.1.1" - object.assign "^4.1.4" - resolve "^2.0.0-next.4" - resumer "^0.0.0" - string.prototype.trim "^1.2.7" - through "^2.3.8" + object.assign "^4.1.5" + resolve "^2.0.0-next.5" + string.prototype.trim "^1.2.9" temp@0.9.4: version "0.9.4" - resolved "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz" + resolved "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz#cd20a8580cb63635d0e4e9d4bd989d44286e7620" integrity sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA== dependencies: mkdirp "^0.5.1" @@ -14319,7 +14493,7 @@ temp@0.9.4: terser-webpack-plugin@^1.4.3: version "1.4.5" - resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz" + resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== dependencies: cacache "^12.0.2" @@ -14332,39 +14506,39 @@ terser-webpack-plugin@^1.4.3: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser-webpack-plugin@^5.1.3: - version "5.3.7" - resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz" - integrity sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw== +terser-webpack-plugin@^5.3.10: + version "5.3.10" + resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== dependencies: - "@jridgewell/trace-mapping" "^0.3.17" + "@jridgewell/trace-mapping" "^0.3.20" jest-worker "^27.4.5" schema-utils "^3.1.1" serialize-javascript "^6.0.1" - terser "^5.16.5" + terser "^5.26.0" terser@^4.1.2: version "4.8.1" - resolved "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz" + resolved "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz#a00e5634562de2239fd404c649051bf6fc21144f" integrity sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw== dependencies: commander "^2.20.0" source-map "~0.6.1" source-map-support "~0.5.12" -terser@^5.16.5, terser@^5.3.0: - version "5.16.6" - resolved "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz" - integrity sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg== +terser@^5.26.0, terser@^5.7.0: + version "5.31.1" + resolved "https://registry.npmjs.org/terser/-/terser-5.31.1.tgz#735de3c987dd671e95190e6b98cfe2f07f3cf0d4" + integrity sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg== dependencies: - "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" commander "^2.20.0" source-map-support "~0.5.20" test-exclude@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" + resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== dependencies: "@istanbuljs/schema" "^0.1.2" @@ -14372,9 +14546,9 @@ test-exclude@^6.0.0: minimatch "^3.0.4" testem@^3.2.0: - version "3.10.1" - resolved "https://registry.npmjs.org/testem/-/testem-3.10.1.tgz" - integrity sha512-42c4e7qlAelwMd8O3ogtVGRbgbr6fJnX6H51ACOIG1V1IjsKPlcQtxPyOwaL4iikH22Dfh+EyIuJnMG4yxieBQ== + version "3.15.0" + resolved "https://registry.npmjs.org/testem/-/testem-3.15.0.tgz#c1f66ff2f6d0e9606c77c4de6b62bca088632d1a" + integrity sha512-vI1oQsjJW4QdVaH6ZmfNErzH7nzs0KzHJluocnfvbz1XRYGJKkIMGKWfsbD8MGGJOg+uzXcEek0/2W7BmGR4ug== dependencies: "@xmldom/xmldom" "^0.8.0" backbone "^1.1.2" @@ -14385,7 +14559,7 @@ testem@^3.2.0: consolidate "^0.16.0" execa "^1.0.0" express "^4.10.7" - fireworm "^0.7.0" + fireworm "^0.7.2" glob "^7.0.4" http-proxy "^1.13.1" js-yaml "^3.2.5" @@ -14394,13 +14568,13 @@ testem@^3.2.0: lodash.clonedeep "^4.4.1" lodash.find "^4.5.1" lodash.uniqby "^4.7.0" - mkdirp "^1.0.4" + mkdirp "^3.0.1" mustache "^4.2.0" node-notifier "^10.0.0" npmlog "^6.0.0" printf "^0.6.1" rimraf "^3.0.2" - socket.io "^4.1.2" + socket.io "^4.5.4" spawn-args "^0.2.0" styled_string "0.0.1" tap-parser "^7.0.0" @@ -14408,22 +14582,36 @@ testem@^3.2.0: text-encoding@^0.7.0: version "0.7.0" - resolved "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz" + resolved "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz#f895e836e45990624086601798ea98e8f36ee643" integrity sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA== text-table@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== "textextensions@1 || 2", textextensions@^2.5.0: version "2.6.0" - resolved "https://registry.npmjs.org/textextensions/-/textextensions-2.6.0.tgz" + resolved "https://registry.npmjs.org/textextensions/-/textextensions-2.6.0.tgz#d7e4ab13fe54e32e08873be40d51b74229b00fc4" integrity sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ== +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + through2@^2.0.0: version "2.0.5" - resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz" + resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== dependencies: readable-stream "~2.3.6" @@ -14431,32 +14619,32 @@ through2@^2.0.0: through2@^3.0.1: version "3.0.2" - resolved "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz" + resolved "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ== dependencies: inherits "^2.0.4" readable-stream "2 || 3" -through@^2.3.6, through@^2.3.8, through@~2.3.4: +through@^2.3.6, through@^2.3.8: version "2.3.8" - resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== timers-browserify@^2.0.4: version "2.0.12" - resolved "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz" + resolved "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== dependencies: setimmediate "^1.0.4" tiny-emitter@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz" + resolved "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== tiny-glob@0.2.9: version "0.2.9" - resolved "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz" + resolved "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2" integrity sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg== dependencies: globalyzer "0.1.0" @@ -14464,7 +14652,7 @@ tiny-glob@0.2.9: tiny-lr@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/tiny-lr/-/tiny-lr-2.0.0.tgz" + resolved "https://registry.npmjs.org/tiny-lr/-/tiny-lr-2.0.0.tgz#863659d7ce1ed201a117d8197d7f8b9a27bdc085" integrity sha512-f6nh0VMRvhGx4KCeK1lQ/jaL0Zdb5WdR+Jk8q9OSUQnaSDxAEGH1fgqLZ+cMl5EW3F2MGnCsalBO1IsnnogW1Q== dependencies: body "^5.1.0" @@ -14476,84 +14664,74 @@ tiny-lr@^2.0.0: tippy.js@^6.2.7, tippy.js@^6.3.7: version "6.3.7" - resolved "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz" + resolved "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c" integrity sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ== dependencies: "@popperjs/core" "^2.9.0" tmp@0.0.28: version "0.0.28" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.28.tgz" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.28.tgz#172735b7f614ea7af39664fa84cf0de4e515d120" integrity sha512-c2mmfiBmND6SOVxzogm1oda0OJ1HZVIk/5n26N59dDTh80MUeavpiCls4PGAdkX1PFkKokLpcf7prSjCeXLsJg== dependencies: os-tmpdir "~1.0.1" tmp@0.0.33, tmp@^0.0.33: version "0.0.33" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" tmp@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== dependencies: rimraf "^2.6.3" tmp@^0.2.1: - version "0.2.1" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz" - integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== - dependencies: - rimraf "^3.0.0" + version "0.2.3" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== tmpl@1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" + resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== to-arraybuffer@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz" + resolved "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA== to-fast-properties@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-object-path@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" + resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== dependencies: kind-of "^3.0.2" -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz" - integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz" + resolved "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" @@ -14563,7 +14741,7 @@ to-regex@^3.0.1, to-regex@^3.0.2: to-vfile@^6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/to-vfile/-/to-vfile-6.1.0.tgz" + resolved "https://registry.npmjs.org/to-vfile/-/to-vfile-6.1.0.tgz#5f7a3f65813c2c4e34ee1f7643a5646344627699" integrity sha512-BxX8EkCxOAZe+D/ToHdDsJcVI4HqQfmw0tCkp31zf3dNP/XWIAjU4CmeuSwsSoOzOTqHPOL0KUzyZqJplkD0Qw== dependencies: is-buffer "^2.0.0" @@ -14571,21 +14749,21 @@ to-vfile@^6.1.0: toidentifier@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== torii@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.npmjs.org/torii/-/torii-1.0.0-beta.1.tgz" - integrity sha512-MtR0QB5YbcADa2eM2eQaWKAUTQuHgr9Biu9yJV0sQOXRMW9X0cdTPWhxYM3PSnSBRg28BAeMKjbsr2uPdayS+g== + version "1.0.0-beta.2" + resolved "https://registry.npmjs.org/torii/-/torii-1.0.0-beta.2.tgz#d6b58aeee1418ad3c1815533886bbbd9982234a8" + integrity sha512-LGKf1Ntr4Nb8ApqQ2gbvsLwaCIPTSz+V9pkrb5ul2BCH0DJCjT8rUJNRNu7SlCBU77ZlxZtDjxbX9ydhMqoCfA== dependencies: ember-cli-babel "^7.26.10" ember-cli-htmlbars "^5.7.2" tough-cookie@^4.0.0: - version "4.1.2" - resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz" - integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== + version "4.1.4" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== dependencies: psl "^1.1.33" punycode "^2.1.1" @@ -14594,28 +14772,27 @@ tough-cookie@^4.0.0: tr46@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz" + resolved "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== dependencies: punycode "^2.1.1" tr46@~0.0.3: version "0.0.3" - resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== tracked-built-ins@^3.1.0: - version "3.1.1" - resolved "https://registry.npmjs.org/tracked-built-ins/-/tracked-built-ins-3.1.1.tgz" - integrity sha512-W8qLBxZzeC2zhEDdbPKi2GTffsiFn8PRbgal/2Fl6E/84CMvnpS6cPMmkvUmSLgKbqcAxl/RhyjWnhIZ9iPQjQ== + version "3.3.0" + resolved "https://registry.npmjs.org/tracked-built-ins/-/tracked-built-ins-3.3.0.tgz#3c8d780550658fe180d0ec32754f1eef1966f2d9" + integrity sha512-ewKFrW/AQs05oLPM5isOUb/1aOwBRfHfmF408CCzTk21FLAhKrKVOP5Q5ebX+zCT4kvg81PGBGwrBiEGND1nWA== dependencies: - ember-cli-babel "^7.26.10" - ember-cli-typescript "^5.1.0" + "@embroider/addon-shim" "^1.8.3" ember-tracked-storage-polyfill "^1.0.0" tracked-maps-and-sets@^2.1.0: version "2.2.1" - resolved "https://registry.npmjs.org/tracked-maps-and-sets/-/tracked-maps-and-sets-2.2.1.tgz" + resolved "https://registry.npmjs.org/tracked-maps-and-sets/-/tracked-maps-and-sets-2.2.1.tgz#323dd40540c561e8b0ffdec8bf129c68ec5025f9" integrity sha512-XYrXh6L/GpGmVmG3KcN/qoDyi4FxHh8eZY/BA/RuoxynskV+GZSfwrX3R+5DR2CIkzkCx4zi4kkDRg1AMDfDhg== dependencies: "@glimmer/tracking" "^1.0.0" @@ -14623,7 +14800,7 @@ tracked-maps-and-sets@^2.1.0: tracked-maps-and-sets@^3.0.1: version "3.0.2" - resolved "https://registry.npmjs.org/tracked-maps-and-sets/-/tracked-maps-and-sets-3.0.2.tgz" + resolved "https://registry.npmjs.org/tracked-maps-and-sets/-/tracked-maps-and-sets-3.0.2.tgz#6ea1b9f2a367d24f2e9905b74b24437fbce76ea6" integrity sha512-UIRcWsX1kDOcC/Q2R58weYWlw01EnmWWBwUv3okWS+zMBvsgIfYoO6veHhuNE3hgzWCEImNp46QS5CyKnw5QUA== dependencies: "@glimmer/tracking" "^1.0.0" @@ -14632,13 +14809,17 @@ tracked-maps-and-sets@^3.0.1: ember-tracked-storage-polyfill "1.0.0" traverse@^0.6.7: - version "0.6.7" - resolved "https://registry.npmjs.org/traverse/-/traverse-0.6.7.tgz" - integrity sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg== + version "0.6.9" + resolved "https://registry.npmjs.org/traverse/-/traverse-0.6.9.tgz#76cfdbacf06382d460b76f8b735a44a6209d8b81" + integrity sha512-7bBrcF+/LQzSgFmT0X5YclVqQxtv7TDJ1f8Wj7ibBu/U6BMLeOpUxuZjV7rMc44UtKxlnMFigdhFAIszSX1DMg== + dependencies: + gopd "^1.0.1" + typedarray.prototype.slice "^1.0.3" + which-typed-array "^1.1.15" tree-sync@^1.2.2: version "1.4.0" - resolved "https://registry.npmjs.org/tree-sync/-/tree-sync-1.4.0.tgz" + resolved "https://registry.npmjs.org/tree-sync/-/tree-sync-1.4.0.tgz#314598d13abaf752547d9335b8f95d9a137100d6" integrity sha512-YvYllqh3qrR5TAYZZTXdspnIhlKAYezPYw11ntmweoceu4VK+keN356phHRIIo1d+RDmLpHZrUlmxga2gc9kSQ== dependencies: debug "^2.2.0" @@ -14649,7 +14830,7 @@ tree-sync@^1.2.2: tree-sync@^2.0.0, tree-sync@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/tree-sync/-/tree-sync-2.1.0.tgz" + resolved "https://registry.npmjs.org/tree-sync/-/tree-sync-2.1.0.tgz#31cbbd41f2936f5390b61e8c9d7cb27e75a212fe" integrity sha512-OLWW+Nd99NOM53aZ8ilT/YpEiOo6mXD3F4/wLbARqybSZ3Jb8IxHK5UGVbZaae0wtXAyQshVV+SeqVBik+Fbmw== dependencies: debug "^4.1.1" @@ -14660,115 +14841,160 @@ tree-sync@^2.0.0, tree-sync@^2.1.0: treeify@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz" + resolved "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== trim-right@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz" + resolved "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== trough@^1.0.0, trough@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz" + resolved "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + tslib@^1.9.0: version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.0.3, tslib@^2.1.0: - version "2.5.0" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz" - integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== + version "2.6.3" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== tty-browserify@0.0.0: version "0.0.0" - resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz" + resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw== type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: prelude-ls "^1.2.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" - type-detect@4.0.8, type-detect@^4.0.8: version "4.0.8" - resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== type-fest@^0.11.0: version "0.11.0" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== type-fest@^0.20.2: version "0.20.2" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== type-fest@^0.21.3: version "0.21.3" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== type-is@~1.6.18: version "1.6.18" - resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== dependencies: media-typer "0.3.0" mime-types "~2.1.24" -typed-array-length@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz" - integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== +typed-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" + integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== dependencies: - call-bind "^1.0.2" + call-bind "^1.0.7" + es-errors "^1.3.0" + is-typed-array "^1.1.13" + +typed-array-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" + integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + +typed-array-byte-offset@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" + integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + +typed-array-length@^1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" + integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== + dependencies: + call-bind "^1.0.7" for-each "^0.3.3" - is-typed-array "^1.1.9" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" typedarray-to-buffer@^3.1.5: version "3.1.5" - resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" + resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== dependencies: is-typedarray "^1.0.0" +typedarray.prototype.slice@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.3.tgz#bce2f685d3279f543239e4d595e0d021731d2d1a" + integrity sha512-8WbVAQAUlENo1q3c3zZYuy5k9VzBQvp8AX9WOtbvyWlLM1v5JaSRmjubLjzHF4JFtptjH/5c/i95yaElvcjC0A== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-errors "^1.3.0" + typed-array-buffer "^1.0.2" + typed-array-byte-offset "^1.0.2" + typedarray@^0.0.6: version "0.0.6" - resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" + resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== typescript-memoize@^1.0.0-alpha.3, typescript-memoize@^1.0.1: version "1.1.1" - resolved "https://registry.npmjs.org/typescript-memoize/-/typescript-memoize-1.1.1.tgz" + resolved "https://registry.npmjs.org/typescript-memoize/-/typescript-memoize-1.1.1.tgz#02737495d5df6ebf72c07ba0d002e8f4cf5ccfa0" integrity sha512-GQ90TcKpIH4XxYTI2F98yEQYZgjNMOGPpOgdjIBhaLaWji5HPWlRnZ4AeA1hfBxtY7bCGDJsqDDHk/KaHOl5bA== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" - resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz" + resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== uglify-js@^3.1.4: - version "3.17.4" - resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz" - integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== + version "3.18.0" + resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz#73b576a7e8fda63d2831e293aeead73e0a270deb" + integrity sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A== unbox-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz" + resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== dependencies: call-bind "^1.0.2" @@ -14778,7 +15004,7 @@ unbox-primitive@^1.0.2: underscore.string@^3.2.2, underscore.string@~3.3.4: version "3.3.6" - resolved "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.6.tgz" + resolved "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.6.tgz#ad8cf23d7423cb3b53b898476117588f4e2f9159" integrity sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ== dependencies: sprintf-js "^1.1.1" @@ -14786,22 +15012,22 @@ underscore.string@^3.2.2, underscore.string@~3.3.4: underscore@>=1.8.3, underscore@^1.13.2: version "1.13.6" - resolved "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz" + resolved "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== -underscore@~1.6.0: - version "1.6.0" - resolved "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz" - integrity sha512-z4o1fvKUojIWh9XuaVLUDdf86RQiq13AC1dmHbTpoyuu+bquHms76v16CjycCbec87J7z0k//SiQVk0sMdFmpQ== +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== unicode-match-property-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== dependencies: unicode-canonical-property-names-ecmascript "^2.0.0" @@ -14809,17 +15035,17 @@ unicode-match-property-ecmascript@^2.0.0: unicode-match-property-value-ecmascript@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== unicode-property-aliases-ecmascript@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== unified@^9.0.0, unified@^9.2.2: version "9.2.2" - resolved "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz" + resolved "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" integrity sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ== dependencies: bail "^1.0.0" @@ -14831,7 +15057,7 @@ unified@^9.0.0, unified@^9.2.2: union-value@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz" + resolved "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== dependencies: arr-union "^3.1.0" @@ -14841,90 +15067,71 @@ union-value@^1.0.0: unique-filename@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz" + resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== dependencies: unique-slug "^2.0.0" unique-slug@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz" + resolved "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== dependencies: imurmurhash "^0.1.4" unique-string@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz" + resolved "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== dependencies: crypto-random-string "^2.0.0" unist-builder@^2.0.0, unist-builder@^2.0.3: version "2.0.3" - resolved "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz" + resolved "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== unist-util-find@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/unist-util-find/-/unist-util-find-1.0.2.tgz" - integrity sha512-ft06UDYzqi9o9RmGP0sZWI/zvLLQiBW2/MD+rW6mDqbOWDcmknGX9orQPspfuGRYWr8eSJAmfsBcvOpfGRJseA== + version "1.0.4" + resolved "https://registry.npmjs.org/unist-util-find/-/unist-util-find-1.0.4.tgz#752e2c6fabf9d57e2c08e03d2f54aaee8c227ef3" + integrity sha512-T5vI7IkhroDj7KxAIy057VbIeGnCXfso4d4GoUsjbAmDLQUkzAeszlBtzx1+KHgdsYYBygaqUBvrbYCfePedZw== dependencies: - lodash.iteratee "^4.5.0" - unist-util-visit "^1.1.0" + lodash.iteratee "^4.7.0" + unist-util-visit "^2.0.0" unist-util-generated@^1.0.0: version "1.1.6" - resolved "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz" + resolved "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b" integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== -unist-util-is@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz" - integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== - unist-util-is@^4.0.0: version "4.1.0" - resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz" + resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== unist-util-position@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz" + resolved "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47" integrity sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA== unist-util-stringify-position@^2.0.0: version "2.0.3" - resolved "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz" + resolved "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== dependencies: "@types/unist" "^2.0.2" -unist-util-visit-parents@^2.0.0: - version "2.1.2" - resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz" - integrity sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g== - dependencies: - unist-util-is "^3.0.0" - unist-util-visit-parents@^3.0.0: version "3.1.1" - resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz" + resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== dependencies: "@types/unist" "^2.0.0" unist-util-is "^4.0.0" -unist-util-visit@^1.1.0: - version "1.4.1" - resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz" - integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw== - dependencies: - unist-util-visit-parents "^2.0.0" - unist-util-visit@^2.0.0, unist-util-visit@^2.0.2, unist-util-visit@^2.0.3: version "2.0.3" - resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz" + resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== dependencies: "@types/unist" "^2.0.0" @@ -14933,27 +15140,27 @@ unist-util-visit@^2.0.0, unist-util-visit@^2.0.2, unist-util-visit@^2.0.3: universalify@^0.1.0: version "0.1.2" - resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" + resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== universalify@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz" + resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + version "2.0.1" + resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== unset-value@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz" + resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== dependencies: has-value "^0.3.1" @@ -14961,109 +15168,109 @@ unset-value@^1.0.0: untildify@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz" + resolved "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz#17eb2807987f76952e9c0485fc311d06a826a2e0" integrity sha512-sJjbDp2GodvkB0FZZcn7k6afVisqX5BZD7Yq3xp4nN2O15BBK0cLm3Vwn2vQaF7UDS0UUsrQMkkplmDI5fskig== dependencies: os-homedir "^1.0.0" upath@^1.1.1: version "1.2.0" - resolved "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz" + resolved "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== -update-browserslist-db@^1.0.10: - version "1.0.10" - resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz" - integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== +update-browserslist-db@^1.0.16: + version "1.1.0" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" + escalade "^3.1.2" + picocolors "^1.0.1" update-section@^0.3.3: version "0.3.3" - resolved "https://registry.npmjs.org/update-section/-/update-section-0.3.3.tgz" + resolved "https://registry.npmjs.org/update-section/-/update-section-0.3.3.tgz#458f17820d37820dc60e20b86d94391b00123158" integrity sha512-BpRZMZpgXLuTiKeiu7kK0nIPwGdyrqrs6EDSaXtjD/aQ2T+qVo9a5hRC3HN3iJjCMxNT/VxoLGQ7E/OzE5ucnw== -uri-js@^4.2.2: +uri-js@^4.2.2, uri-js@^4.4.1: version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" + resolved "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== url-parse@^1.5.3: version "1.5.10" - resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz" + resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== dependencies: querystringify "^2.1.1" requires-port "^1.0.0" url@^0.11.0: - version "0.11.0" - resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz" - integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ== + version "0.11.3" + resolved "https://registry.npmjs.org/url/-/url-0.11.3.tgz#6f495f4b935de40ce4a0a52faee8954244f3d3ad" + integrity sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw== dependencies: - punycode "1.3.2" - querystring "0.2.0" + punycode "^1.4.1" + qs "^6.11.2" use@^3.1.0: version "3.1.1" - resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz" + resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== username-sync@^1.0.2: version "1.0.3" - resolved "https://registry.npmjs.org/username-sync/-/username-sync-1.0.3.tgz" + resolved "https://registry.npmjs.org/username-sync/-/username-sync-1.0.3.tgz#ae41c5c8a4c8c2ecc1443a7d0742742bd7e36732" integrity sha512-m/7/FSqjJNAzF2La448c/aEom0gJy7HY7Y509h6l0ePvEkFictAGptwWaj1msWJ38JbfEDOUoE8kqFee9EHKdA== util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== util-extend@^1.0.1: version "1.0.3" - resolved "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz" + resolved "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" integrity sha512-mLs5zAK+ctllYBj+iAQvlDCwoxU/WDOUaJkcFudeiAX6OajC6BKXJUa9a+tbtkC11dz2Ufb7h0lyvIOVn4LADA== -util@0.10.3: - version "0.10.3" - resolved "https://registry.npmjs.org/util/-/util-0.10.3.tgz" - integrity sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ== +util@^0.10.4: + version "0.10.4" + resolved "https://registry.npmjs.org/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== dependencies: - inherits "2.0.1" + inherits "2.0.3" util@^0.11.0: version "0.11.1" - resolved "https://registry.npmjs.org/util/-/util-0.11.1.tgz" + resolved "https://registry.npmjs.org/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== dependencies: inherits "2.0.3" utils-merge@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== uuid@^8.3.2: version "8.3.2" - resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0: - version "2.3.0" - resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" - integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + version "2.4.0" + resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" + integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== validate-npm-package-license@^3.0.1: version "3.0.4" - resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" + resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" @@ -15071,14 +15278,14 @@ validate-npm-package-license@^3.0.1: validate-npm-package-name@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz" + resolved "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" integrity sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw== dependencies: builtins "^1.0.3" validate-peer-dependencies@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/validate-peer-dependencies/-/validate-peer-dependencies-1.2.0.tgz" + resolved "https://registry.npmjs.org/validate-peer-dependencies/-/validate-peer-dependencies-1.2.0.tgz#22aab93c514f4fda457d36c80685e8b1160d2036" integrity sha512-nd2HUpKc6RWblPZQ2GDuI65sxJ2n/UqZwSBVtj64xlWjMx0m7ZB2m9b2JS3v1f+n9VWH/dd1CMhkHfP6pIdckA== dependencies: resolve-package-path "^3.1.0" @@ -15086,17 +15293,17 @@ validate-peer-dependencies@^1.2.0: validated-changeset@1.0.0, validated-changeset@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/validated-changeset/-/validated-changeset-1.0.0.tgz" + resolved "https://registry.npmjs.org/validated-changeset/-/validated-changeset-1.0.0.tgz#a961b4a87953b6b12858b0477436360332493f4d" integrity sha512-HeHGkC2BlmWTwtq5DTUMmFX18PAunuLbIs8A4CWoLc58QGKRF4jtR+F5XzP/19xysQXkMApazT2OphqJ+lKVwQ== vary@^1, vary@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== vfile-message@^2.0.0: version "2.0.4" - resolved "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz" + resolved "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== dependencies: "@types/unist" "^2.0.0" @@ -15104,7 +15311,7 @@ vfile-message@^2.0.0: vfile@^4.0.0: version "4.2.1" - resolved "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz" + resolved "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== dependencies: "@types/unist" "^2.0.0" @@ -15114,26 +15321,26 @@ vfile@^4.0.0: vm-browserify@^1.0.1: version "1.1.2" - resolved "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz" + resolved "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== w3c-hr-time@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz" + resolved "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== dependencies: browser-process-hrtime "^1.0.0" w3c-xmlserializer@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz" + resolved "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== dependencies: xml-name-validator "^3.0.0" walk-sync@^0.2.5: version "0.2.7" - resolved "https://registry.npmjs.org/walk-sync/-/walk-sync-0.2.7.tgz" + resolved "https://registry.npmjs.org/walk-sync/-/walk-sync-0.2.7.tgz#b49be4ee6867657aeb736978b56a29d10fa39969" integrity sha512-OH8GdRMowEFr0XSHQeX5fGweO6zSVHo7bG/0yJQx6LAj9Oukz0C8heI3/FYectT66gY0IPGe89kOvU410/UNpg== dependencies: ensure-posix-path "^1.0.0" @@ -15141,7 +15348,7 @@ walk-sync@^0.2.5: walk-sync@^0.3.0, walk-sync@^0.3.1, walk-sync@^0.3.3: version "0.3.4" - resolved "https://registry.npmjs.org/walk-sync/-/walk-sync-0.3.4.tgz" + resolved "https://registry.npmjs.org/walk-sync/-/walk-sync-0.3.4.tgz#cf78486cc567d3a96b5b2237c6108017a5ffb9a4" integrity sha512-ttGcuHA/OBnN2pcM6johpYlEms7XpO5/fyKIr48541xXedan4roO8cS1Q2S/zbbjGH/BarYDAMeS2Mi9HE5Tig== dependencies: ensure-posix-path "^1.0.0" @@ -15149,7 +15356,7 @@ walk-sync@^0.3.0, walk-sync@^0.3.1, walk-sync@^0.3.3: walk-sync@^1.0.0, walk-sync@^1.1.3: version "1.1.4" - resolved "https://registry.npmjs.org/walk-sync/-/walk-sync-1.1.4.tgz" + resolved "https://registry.npmjs.org/walk-sync/-/walk-sync-1.1.4.tgz#81049f3d8095479b49574cfa5f558d7a252b127d" integrity sha512-nowc9thB/Jg0KW4TgxoRjLLYRPvl3DB/98S89r4ZcJqq2B0alNcKDh6pzLkBSkPMzRSMsJghJHQi79qw0YWEkA== dependencies: "@types/minimatch" "^3.0.3" @@ -15158,7 +15365,7 @@ walk-sync@^1.0.0, walk-sync@^1.1.3: walk-sync@^2.0.0, walk-sync@^2.0.2, walk-sync@^2.1.0, walk-sync@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/walk-sync/-/walk-sync-2.2.0.tgz" + resolved "https://registry.npmjs.org/walk-sync/-/walk-sync-2.2.0.tgz#80786b0657fcc8c0e1c0b1a042a09eae2966387a" integrity sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg== dependencies: "@types/minimatch" "^3.0.3" @@ -15168,7 +15375,7 @@ walk-sync@^2.0.0, walk-sync@^2.0.2, walk-sync@^2.1.0, walk-sync@^2.2.0: walk-sync@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/walk-sync/-/walk-sync-3.0.0.tgz" + resolved "https://registry.npmjs.org/walk-sync/-/walk-sync-3.0.0.tgz#67f882925021e20569a1edd560b8da31da8d171c" integrity sha512-41TvKmDGVpm2iuH7o+DAOt06yyu/cSHpX3uzAwetzASvlNtVddgIjXIb2DfB/Wa20B1Jo86+1Dv1CraSU7hWdw== dependencies: "@types/minimatch" "^3.0.4" @@ -15178,14 +15385,14 @@ walk-sync@^3.0.0: walker@~1.0.5: version "1.0.8" - resolved "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz" + resolved "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== dependencies: makeerror "1.0.12" watch-detector@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/watch-detector/-/watch-detector-1.0.2.tgz" + resolved "https://registry.npmjs.org/watch-detector/-/watch-detector-1.0.2.tgz#95deb9189f8c89c0a9f211739cef6d01cffcf452" integrity sha512-MrJK9z7kD5Gl3jHBnnBVHvr1saVGAfmkyyrvuNzV/oe0Gr1nwZTy5VSA0Gw2j2Or0Mu8HcjUa44qlBvC2Ofnpg== dependencies: heimdalljs-logger "^0.1.10" @@ -15194,14 +15401,14 @@ watch-detector@^1.0.0: watchpack-chokidar2@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz" + resolved "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== dependencies: chokidar "^2.1.8" watchpack@^1.7.4: version "1.7.5" - resolved "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz" + resolved "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== dependencies: graceful-fs "^4.1.2" @@ -15210,46 +15417,46 @@ watchpack@^1.7.4: chokidar "^3.4.1" watchpack-chokidar2 "^2.0.1" -watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== +watchpack@^2.4.1: + version "2.4.1" + resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" wayfarer@^7.0.1: version "7.0.1" - resolved "https://registry.npmjs.org/wayfarer/-/wayfarer-7.0.1.tgz" + resolved "https://registry.npmjs.org/wayfarer/-/wayfarer-7.0.1.tgz#17a64d351d49f9d3d6c508155867df7658184ce3" integrity sha512-yf+kAlOYnJRjLxflLy+1+xEclb6222EAVvAjSY+Yz2qAIDrXeN5wLl/G302Mwv3E0KMg1HT/WDGsvSymX0U7Rw== dependencies: nanoassert "^1.1.0" wcwidth@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz" + resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== dependencies: defaults "^1.0.3" webidl-conversions@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== webidl-conversions@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== webidl-conversions@^6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== webpack-sources@^1.4.0, webpack-sources@^1.4.1: version "1.4.3" - resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz" + resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== dependencies: source-list-map "^2.0.0" @@ -15257,13 +15464,13 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1: webpack-sources@^3.2.3: version "3.2.3" - resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" + resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^4.43.0: - version "4.46.0" - resolved "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz" - integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== + version "4.47.0" + resolved "https://registry.npmjs.org/webpack/-/webpack-4.47.0.tgz#8b8a02152d7076aeb03b61b47dad2eeed9810ebc" + integrity sha512-td7fYwgLSrky3fI1EuU5cneU4+pbH6GgOfuKNS1tNPcfdGinGELAqsb/BP4nnvZyKSG2i/xFGU7+n2PvZA8HJQ== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -15290,38 +15497,38 @@ webpack@^4.43.0: webpack-sources "^1.4.1" webpack@^5.74.0: - version "5.76.1" - resolved "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz" - integrity sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ== + version "5.92.1" + resolved "https://registry.npmjs.org/webpack/-/webpack-5.92.1.tgz#eca5c1725b9e189cffbd86e8b6c3c7400efc5788" + integrity sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA== dependencies: "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" + acorn-import-attributes "^1.9.5" + browserslist "^4.21.10" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" + enhanced-resolve "^5.17.0" + es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" + graceful-fs "^4.2.11" json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.1.0" + schema-utils "^3.2.0" tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.4.0" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" webpack-sources "^3.2.3" websocket-driver@>=0.5.1: version "0.7.4" - resolved "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz" + resolved "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== dependencies: http-parser-js ">=0.5.1" @@ -15330,24 +15537,24 @@ websocket-driver@>=0.5.1: websocket-extensions@>=0.1.1: version "0.1.4" - resolved "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz" + resolved "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== whatwg-encoding@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz" + resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== dependencies: iconv-lite "0.4.24" whatwg-mimetype@^2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz" + resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== whatwg-url@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" @@ -15355,7 +15562,7 @@ whatwg-url@^5.0.0: whatwg-url@^8.0.0, whatwg-url@^8.5.0: version "8.7.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== dependencies: lodash "^4.7.0" @@ -15364,7 +15571,7 @@ whatwg-url@^8.0.0, whatwg-url@^8.5.0: which-boxed-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" + resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== dependencies: is-bigint "^1.0.1" @@ -15374,99 +15581,98 @@ which-boxed-primitive@^1.0.2: is-symbol "^1.0.3" which-collection@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz" - integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== + version "1.0.2" + resolved "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== dependencies: - is-map "^2.0.1" - is-set "^2.0.1" - is-weakmap "^2.0.1" - is-weakset "^2.0.1" + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" which-pm-runs@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz" + resolved "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz#35ccf7b1a0fce87bd8b92a478c9d045785d3bf35" integrity sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA== -which-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz" - integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== +which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" + integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" for-each "^0.3.3" gopd "^1.0.1" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" + has-tostringtag "^1.0.2" which@^1.2.14, which@^1.2.9: version "1.3.1" - resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" + resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" which@^2.0.1, which@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" wide-align@^1.1.0, wide-align@^1.1.5: version "1.1.5" - resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== dependencies: string-width "^1.0.2 || 2 || 3 || 4" -word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== wordwrap@^0.0.3: version "0.0.3" - resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" + resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" integrity sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw== wordwrap@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" + resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== worker-farm@^1.7.0: version "1.7.0" - resolved "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz" + resolved "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== dependencies: errno "~0.1.7" workerpool@^2.3.0: version "2.3.4" - resolved "https://registry.npmjs.org/workerpool/-/workerpool-2.3.4.tgz" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-2.3.4.tgz#661335ded59a08c01ca009e30cc96929a7b4b0aa" integrity sha512-c2EWrgB9IKHi1jbf4LG9sxKgHYOY+Ej5li6siEGtFecCXWG7eQOqATPEJ0rg1KFETXROEkErc1t5XiNrLG666Q== dependencies: object-assign "4.1.1" workerpool@^3.1.1: version "3.1.2" - resolved "https://registry.npmjs.org/workerpool/-/workerpool-3.1.2.tgz" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-3.1.2.tgz#b34e79243647decb174b7481ab5b351dc565c426" integrity sha512-WJFA0dGqIK7qj7xPTqciWBH5DlJQzoPjsANvc3Y4hNB0SScT+Emjvt0jPPkDBUjBNngX1q9hHgt1Gfwytu6pug== dependencies: "@babel/core" "^7.3.4" object-assign "4.1.1" rsvp "^4.8.4" -workerpool@^6.0.0, workerpool@^6.1.4: - version "6.4.0" - resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.4.0.tgz" - integrity sha512-i3KR1mQMNwY2wx20ozq2EjISGtQWDIfV56We+yGJ5yDs8jTwQiLLaqHlkBHITlCuJnYlVRmXegxFxZg7gqI++A== +workerpool@^6.0.2, workerpool@^6.1.4, workerpool@^6.1.5: + version "6.5.1" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" + integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== wrap-ansi@^6.2.0: version "6.2.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== dependencies: ansi-styles "^4.0.0" @@ -15475,7 +15681,7 @@ wrap-ansi@^6.2.0: wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -15484,7 +15690,7 @@ wrap-ansi@^7.0.0: wrap-legacy-hbs-plugin-if-needed@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/wrap-legacy-hbs-plugin-if-needed/-/wrap-legacy-hbs-plugin-if-needed-1.0.1.tgz" + resolved "https://registry.npmjs.org/wrap-legacy-hbs-plugin-if-needed/-/wrap-legacy-hbs-plugin-if-needed-1.0.1.tgz#6683eb74747f33e7caea54bb2ed85106ef9006b4" integrity sha512-aJjXe5WwrY0u0dcUgKW3m2SGnxosJ66LLm/QaG0YMHqgA6+J2xwAFZfhSLsQ2BmO5x8PTH+OIxoAXuGz3qBA7A== dependencies: "@glimmer/reference" "^0.42.1" @@ -15494,12 +15700,12 @@ wrap-legacy-hbs-plugin-if-needed@^1.0.1: wrappy@1: version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^3.0.0: version "3.0.3" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== dependencies: imurmurhash "^0.1.4" @@ -15508,86 +15714,91 @@ write-file-atomic@^3.0.0: typedarray-to-buffer "^3.1.5" ws@^7.4.6: - version "7.5.9" - resolved "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + version "7.5.10" + resolved "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== -ws@~8.11.0: - version "8.11.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz" - integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== +ws@~8.17.1: + version "8.17.1" + resolved "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== xdg-basedir@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz" + resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== xml-name-validator@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz" + resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== xmlchars@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz" + resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== xmlhttprequest-ssl@^1.6.3: version "1.6.3" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz#03b713873b01659dfa2c1c5d056065b27ddc2de6" + resolved "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz#03b713873b01659dfa2c1c5d056065b27ddc2de6" integrity sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q== -xtend@^4.0.0, xtend@^4.0.2, xtend@~4.0.1: +xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" - resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== y18n@^4.0.0: version "4.0.3" - resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz" + resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== y18n@^5.0.5: version "5.0.8" - resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yadda@*: version "2.2.0" - resolved "https://registry.npmjs.org/yadda/-/yadda-2.2.0.tgz" + resolved "https://registry.npmjs.org/yadda/-/yadda-2.2.0.tgz#748a2ae921a968aa5f914324898ccecb1fa5ee32" integrity sha512-TO5YH2XzFZjtInULMZHKTStTOaxRG5hB/nN8qxHOJedsd0HLeqRoP/TW1qKqTeGhIUzq7CVR7iIEFIwerbXIkg== yallist@^3.0.0, yallist@^3.0.2: version "3.1.1" - resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yallist@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yam@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/yam/-/yam-1.0.0.tgz" + resolved "https://registry.npmjs.org/yam/-/yam-1.0.0.tgz#7f6c91dc0f5de75a031e6da6b3907c3d25ab0de5" integrity sha512-Hv9xxHtsJ9228wNhk03xnlDReUuWVvHwM4rIbjdAXYvHLs17xjuyF50N6XXFMN6N0omBaqgOok/MCK3At9fTAg== dependencies: fs-extra "^4.0.2" lodash.merge "^4.6.0" -yaml@^1.10.0, yaml@^1.10.2, yaml@^1.9.2: +yaml@^1.10.0, yaml@^1.9.2: version "1.10.2" - resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" + resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yaml@^2.3.4: + version "2.4.5" + resolved "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz#60630b206dd6d84df97003d33fc1ddf6296cca5e" + integrity sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg== + yargs-parser@^20.2.2: version "20.2.9" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== yargs@^16.2.0: version "16.2.0" - resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" + resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: cliui "^7.0.2" @@ -15600,10 +15811,10 @@ yargs@^16.2.0: yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== zwitch@^1.0.0: version "1.0.5" - resolved "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz" + resolved "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== diff --git a/version/VERSION b/version/VERSION index ee017091ff37..1acb46a42ac8 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.18.0-dev +1.20.1 \ No newline at end of file diff --git a/version/versiontest/versiontest.go b/version/versiontest/versiontest.go new file mode 100644 index 000000000000..c13791f9ba0f --- /dev/null +++ b/version/versiontest/versiontest.go @@ -0,0 +1,13 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package versiontest + +import "github.com/hashicorp/consul/version" + +// IsEnterprise returns true if the current build is a Consul Enterprise build. +// +// This should only be called from test code. +func IsEnterprise() bool { + return version.VersionMetadata == "ent" +} diff --git a/website/.husky/pre-commit b/website/.husky/pre-commit new file mode 100644 index 000000000000..ed0b6423e4d4 --- /dev/null +++ b/website/.husky/pre-commit @@ -0,0 +1,3 @@ +cd website + +npx next-hashicorp precommit \ No newline at end of file diff --git a/website/.nvmrc b/website/.nvmrc index 958b5a36e1fa..0828ab79473b 100644 --- a/website/.nvmrc +++ b/website/.nvmrc @@ -1 +1 @@ -v14 +v18 \ No newline at end of file diff --git a/website/README.md b/website/README.md index 2babc35c2d53..0c0f6ee09bfa 100644 --- a/website/README.md +++ b/website/README.md @@ -62,7 +62,7 @@ The docker image is pre-built with all the website dependencies installed, which ### With Node -If your local development environment has a supported version (v10.0.0+) of [node installed](https://nodejs.org/en/) you can run: +If your local development environment has a supported version (v18.17.0+) of [node installed](https://nodejs.org/en/) you can run: - `npm install` - `npm start` diff --git a/website/content/api-docs/acl/auth-methods.mdx b/website/content/api-docs/acl/auth-methods.mdx index 805a9ee93c41..34f59cb866c5 100644 --- a/website/content/api-docs/acl/auth-methods.mdx +++ b/website/content/api-docs/acl/auth-methods.mdx @@ -107,6 +107,8 @@ The corresponding CLI command is [`consul acl auth-method create`](/consul/comma prefixed-${serviceaccount.name} ``` +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -175,9 +177,11 @@ The corresponding CLI command is [`consul acl auth-method read`](/consul/command ### Query Parameters -- `ns` `(string: "")` - Specifies the namespace of the auth method you lookup. +- `ns` `(string: "")` - Specifies the namespace of the auth method you look up. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -291,9 +295,11 @@ The corresponding CLI command is [`consul acl auth-method update`](/consul/comma same values that are usable by the `Selector` syntax. For example: ```text - prefixed-${serviceaccount.name} + prefixed-${serviceaccount.name} ``` +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -369,6 +375,8 @@ The corresponding CLI command is [`consul acl auth-method delete`](/consul/comma - `ns` `(string: "")` - Specifies the namespace of the auth method you delete. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -408,8 +416,9 @@ The corresponding CLI command is [`consul acl auth-method list`](/consul/command The namespace may be specified as '\*' to return results for all namespaces. You can also [specify the namespace through other methods](#methods-to-specify-namespace). -The namespace may be specified as '\*' and then - results will be returned for all namespaces. + The namespace may be specified as '\*' and then results are returned for all namespaces. + +@include 'http-api-query-parms-partition.mdx' ## Sample Request diff --git a/website/content/api-docs/acl/binding-rules.mdx b/website/content/api-docs/acl/binding-rules.mdx index 9894ce21c7bf..34edeadc4a95 100644 --- a/website/content/api-docs/acl/binding-rules.mdx +++ b/website/content/api-docs/acl/binding-rules.mdx @@ -172,6 +172,8 @@ The corresponding CLI command is [`consul acl binding-rule create`](/consul/comm This field takes precedence over the `ns` query parameter, one of several [other methods to specify the namespace](#methods-to-specify-namespace). +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -238,6 +240,8 @@ The corresponding CLI command is [`consul acl binding-rule read`](/consul/comman - `ns` `(string: "")` - Specifies the namespace of the binding rule you lookup. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -423,6 +427,8 @@ The corresponding CLI command is [`consul acl binding-rule update`](/consul/comm This field takes precedence over the `ns` query parameter, one of several [other methods to specify the namespace](#methods-to-specify-namespace). +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -489,6 +495,8 @@ The corresponding CLI command is [`consul acl binding-rule delete`](/consul/comm - `ns` `(string: "")` - Specifies the namespace of the binding rule you delete. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -522,7 +530,7 @@ The table below shows this endpoint's support for The corresponding CLI command is [`consul acl binding-rule list`](/consul/commands/acl/binding-rule/list). -## Query Parameters +### Query Parameters - `authmethod` `(string: "")` - Filters the binding rule list to those binding rules that are linked with the specific named auth method. @@ -531,7 +539,9 @@ The corresponding CLI command is [`consul acl binding-rule list`](/consul/comman The namespace may be specified as '\*' to return results for all namespaces. You can also [specify the namespace through other methods](#methods-to-specify-namespace). -## Sample Request +@include 'http-api-query-parms-partition.mdx' + +### Sample Request ```shell-session $ curl --request GET http://127.0.0.1:8500/v1/acl/binding-rules diff --git a/website/content/api-docs/acl/policies.mdx b/website/content/api-docs/acl/policies.mdx index c41583626b8c..1d46fa1b5125 100644 --- a/website/content/api-docs/acl/policies.mdx +++ b/website/content/api-docs/acl/policies.mdx @@ -57,6 +57,8 @@ The corresponding CLI command is [`consul acl policy create`](/consul/commands/a This field takes precedence over the `ns` query parameter, one of several [other methods to specify the namespace](#methods-to-specify-namespace). +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -170,6 +172,8 @@ The corresponding CLI command is [`consul acl policy read -name=`](/cons - `ns` `(string: "")` - Specifies the namespace of the policy you lookup. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -242,6 +246,8 @@ The corresponding CLI command is [`consul acl policy update`](/consul/commands/a This field takes precedence over the `ns` query parameter, one of several [other methods to specify the namespace](#methods-to-specify-namespace). +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -307,6 +313,8 @@ The corresponding CLI command is [`consul acl policy delete`](/consul/commands/a - `ns` `(string: "")` - Specifies the namespace of the policy you delete. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -346,7 +354,9 @@ The corresponding CLI command is [`consul acl policy list`](/consul/commands/acl The namespace may be specified as '\*' to return results for all namespaces. You can also [specify the namespace through other methods](#methods-to-specify-namespace). -## Sample Request +@include 'http-api-query-parms-partition.mdx' + +### Sample Request ```shell-session $ curl --request GET http://127.0.0.1:8500/v1/acl/policies diff --git a/website/content/api-docs/acl/roles.mdx b/website/content/api-docs/acl/roles.mdx index fbcb8d8b72b1..e54e9a54b07b 100644 --- a/website/content/api-docs/acl/roles.mdx +++ b/website/content/api-docs/acl/roles.mdx @@ -95,6 +95,8 @@ The corresponding CLI command is [`consul acl role create`](/consul/commands/acl This field takes precedence over the `ns` query parameter, one of several [other methods to specify the namespace](#methods-to-specify-namespace). +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -223,6 +225,8 @@ The corresponding CLI command is [`consul acl role read`](/consul/commands/acl/r - `ns` `(string: "")` - Specifies the namespace of the role you lookup. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -306,6 +310,8 @@ The corresponding CLI command is [`consul acl role read -name=`](/consul - `ns` `(string: "")` - Specifies the namespace of the role you lookup. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -418,6 +424,8 @@ The corresponding CLI command is [`consul acl role update`](/consul/commands/acl This field takes precedence over the `ns` query parameter, one of several [other methods to specify the namespace](#methods-to-specify-namespace). +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -523,6 +531,8 @@ The corresponding CLI command is [`consul acl role delete`](/consul/commands/acl - `ns` `(string: "")` - Specifies the namespace of the role you delete. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -565,6 +575,8 @@ The corresponding CLI command is [`consul acl role list`](/consul/commands/acl/r The namespace may be specified as '\*' to return results for all namespaces. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ## Sample Request ```shell-session diff --git a/website/content/api-docs/acl/templated-policies.mdx b/website/content/api-docs/acl/templated-policies.mdx index 5805449dd58f..de3a6b59aef8 100644 --- a/website/content/api-docs/acl/templated-policies.mdx +++ b/website/content/api-docs/acl/templated-policies.mdx @@ -87,6 +87,8 @@ The corresponding CLI command is [`consul acl templated-policy preview`](/consul - `Name` `(string: )` - Specifies the value of the `name` variable in the templated policy variables. +@include 'http-api-body-options-partition.mdx' + ### Sample payload ```json diff --git a/website/content/api-docs/acl/tokens.mdx b/website/content/api-docs/acl/tokens.mdx index a741ec3a708b..af629a3500cf 100644 --- a/website/content/api-docs/acl/tokens.mdx +++ b/website/content/api-docs/acl/tokens.mdx @@ -118,6 +118,8 @@ The corresponding CLI command is [`consul acl token create`](/consul/commands/ac This field takes precedence over the `ns` query parameter, one of several [other methods to specify the namespace](#methods-to-specify-namespace). +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -217,6 +219,8 @@ The corresponding CLI command is [`consul acl token read`](/consul/commands/acl/ - `expanded` `(bool: false)` - If this field is set, the contents of all policies and roles affecting the token will also be returned. +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -497,6 +501,8 @@ The corresponding CLI command is [`consul acl token update`](/consul/commands/ac This field takes precedence over the `ns` query parameter, one of several [other methods to specify the namespace](#methods-to-specify-namespace). +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -591,6 +597,8 @@ The corresponding CLI command is [`consul acl token clone`](/consul/commands/acl This field takes precedence over the `ns` query parameter, one of several [other methods to specify the namespace](#methods-to-specify-namespace). +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -668,6 +676,8 @@ The corresponding CLI command is [`consul acl token delete`](/consul/commands/ac - `ns` `(string: "")` - Specifies the namespace of the token you delete. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -723,6 +733,8 @@ The corresponding CLI command is [`consul acl token list`](/consul/commands/acl/ The namespace may be specified as '\*' to return results for all namespaces. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session diff --git a/website/content/api-docs/admin-partitions.mdx b/website/content/api-docs/admin-partitions.mdx index 4c728e85d333..f71fff17256e 100644 --- a/website/content/api-docs/admin-partitions.mdx +++ b/website/content/api-docs/admin-partitions.mdx @@ -128,6 +128,8 @@ This endpoint updates a partition description and has the following characterist - `Description` `(string: "")` - Free form partition description. +- `DisableGossip` `(bool: false)` - Disable gossip support for this partition. When set to `true` this will save on CPU and network resources on the servers but client agents will be unable to join the partition. + ### Sample Payload ```json @@ -237,6 +239,7 @@ $ curl --header "X-Consul-Token: 0137db51-5895-4c25-b6cd-d9ed992f4a52" \ { "Name": "na-west", "Description": "North America West Partition", + "DisableGossip": true, "CreateIndex": 55, "ModifyIndex": 55 } diff --git a/website/content/api-docs/agent/index.mdx b/website/content/api-docs/agent/index.mdx index d76cc1910775..749ea80f291d 100644 --- a/website/content/api-docs/agent/index.mdx +++ b/website/content/api-docs/agent/index.mdx @@ -261,6 +261,8 @@ The corresponding CLI command is [`consul members`](/consul/commands/members). network segment). When querying a server, setting this to the special string `_all` will show members in all segments. +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session diff --git a/website/content/api-docs/agent/service.mdx b/website/content/api-docs/agent/service.mdx index eee3dd471e3d..301827418270 100644 --- a/website/content/api-docs/agent/service.mdx +++ b/website/content/api-docs/agent/service.mdx @@ -684,6 +684,8 @@ The `/agent/service/register` endpoint supports camel case and _snake case_ for `false`. See [anti-entropy syncs](/consul/docs/architecture/anti-entropy) for additional information. +@include 'http-api-body-options-partition.mdx' + #### Connect Structure For the `Connect` field, the parameters are: @@ -769,6 +771,8 @@ The corresponding CLI command is [`consul services deregister`](/consul/commands - `ns` `(string: "")` - Specifies the namespace of the service you deregister. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session diff --git a/website/content/api-docs/api-structure.mdx b/website/content/api-docs/api-structure.mdx index 7a190894129a..32a8a2c17c49 100644 --- a/website/content/api-docs/api-structure.mdx +++ b/website/content/api-docs/api-structure.mdx @@ -41,14 +41,14 @@ $ curl \ ``` **Security Note:** Though you could pass the token through the `?token=` query parameter, -this method is highly discouraged because the token can show up in access logs as part of the URL. -The `?token=` query parameter is deprecated and will be removed in Consul 1.17. +this method is highly discouraged because the token can show up in access logs as part of the URL. +The `?token=` query parameter is deprecated and will be removed in a future Consul version. To learn more about the ACL system read the [documentation](/consul/docs/security/acl). ## Version Prefix -All API routes are prefixed with `/v1/`. This documentation is only for the v1 API. +Unless indicated otherwise, all API routes are prefixed with `/v1/`. ## Formatted JSON Output @@ -159,3 +159,8 @@ UUID-format identifiers generated by the Consul API use the These UUID-format strings are generated using high quality, purely random bytes. It is not intended to be RFC compliant, merely to use a well-understood string representation of a 128-bit value. + +## CORS HTTP Response Headers + +As of Consul 1.18, Consul adds an HTTP header `Access-Control-Expose-Headers: x-consul-default-acl-policy` to +all responses in order to support linking self-managed Enterprise clusters to HCP Consul Central. diff --git a/website/content/api-docs/catalog.mdx b/website/content/api-docs/catalog.mdx index 8af4a2f011d4..f773353483a2 100644 --- a/website/content/api-docs/catalog.mdx +++ b/website/content/api-docs/catalog.mdx @@ -212,6 +212,8 @@ The behavior of the endpoint depends on what keys are provided. You can also specify the namespace in the `Service` or `Check` fields; if namespaces are specified in multiple places, they must all be the same. +- `Partition` `(string: "")` - Specifies the admin partition of the service and checks you deregister. + ### Sample Payloads ```json @@ -221,6 +223,14 @@ The behavior of the endpoint depends on what keys are provided. } ``` +```json +{ + "Datacenter": "dc1", + "Node": "t2.320", + "Partition": "part-1" +} +``` + ```json { "Datacenter": "dc1", @@ -327,6 +337,8 @@ The corresponding CLI command is [`consul catalog nodes`](/consul/commands/catal - `filter` `(string: "")` - Specifies the expression used to filter the queries results prior to returning the data. +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -422,6 +434,8 @@ The corresponding CLI command is [`consul catalog services`](/consul/commands/ca - `filter` `(string: "")` - Specifies the expression used to filter the queries results prior to returning the data. +@include 'http-api-query-parms-partition.mdx' + ### Filtering The filter will be executed against each Service mapping within the catalog. diff --git a/website/content/api-docs/config.mdx b/website/content/api-docs/config.mdx index 2c550a25263a..49243da09456 100644 --- a/website/content/api-docs/config.mdx +++ b/website/content/api-docs/config.mdx @@ -39,23 +39,24 @@ The corresponding CLI command is [`consul config write`](/consul/commands/config The ACL required depends on the config entry being written: -| Config Entry Kind | Required ACLs | -| ------------------- | -------------------------------- | -| api-gateway | `mesh:write` or `operator:write` | -| bound-api-gateway | Not writable. | -| exported-services | `mesh:write` or `operator:write` | -| http-route | `mesh:write` or `operator:write` | -| ingress-gateway | `mesh:write` or `operator:write` | -| inline-certificate | `mesh:write` or `operator:write` | -| mesh | `mesh:write` or `operator:write` | -| proxy-defaults | `mesh:write` or `operator:write` | -| service-defaults | `service:write` | -| service-intentions | `intentions:write` | -| service-resolver | `service:write` | -| service-router | `service:write` | -| service-splitter | `service:write` | -| tcp-route | `mesh:write` or `operator:write` | -| terminating-gateway | `mesh:write` or `operator:write` | +| Config Entry Kind | Required ACLs | +| ----------------------- | -------------------------------- | +| api-gateway | `mesh:write` or `operator:write` | +| bound-api-gateway | Not writable. | +| exported-services | `mesh:write` or `operator:write` | +| file-system-certificate | `mesh:write` or `operator:write` | +| http-route | `mesh:write` or `operator:write` | +| ingress-gateway | `mesh:write` or `operator:write` | +| inline-certificate | `mesh:write` or `operator:write` | +| mesh | `mesh:write` or `operator:write` | +| proxy-defaults | `mesh:write` or `operator:write` | +| service-defaults | `service:write` | +| service-intentions | `intentions:write` | +| service-resolver | `service:write` | +| service-router | `service:write` | +| service-splitter | `service:write` | +| tcp-route | `mesh:write` or `operator:write` | +| terminating-gateway | `mesh:write` or `operator:write` | ### Query Parameters @@ -70,6 +71,8 @@ The ACL required depends on the config entry being written: - `ns` `(string: "")` - Specifies the namespace of the config entry you apply. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Payload ```json @@ -114,23 +117,24 @@ The corresponding CLI command is [`consul config read`](/consul/commands/config/ The ACL required depends on the config entry kind being read: -| Config Entry Kind | Required ACLs | -| ------------------- | -------------------------------- | -| api-gateway | `service:read` | -| bound-api-gateway | `service:read` | -| exported-services | `mesh:read` or `operator:read` | -| http-route | `mesh:read` or `operator:read` | -| ingress-gateway | `service:read` | -| inline-certificate | `mesh:read` or `operator:read` | -| mesh | No ACL required | -| proxy-defaults | No ACL required | -| service-defaults | `service:read` | -| service-intentions | `intentions:read` | -| service-resolver | `service:read` | -| service-router | `service:read` | -| service-splitter | `service:read` | -| tcp-route | `mesh:read` or `operator:read` | -| terminating-gateway | `service:read` | +| Config Entry Kind | Required ACLs | +| ----------------------- | -------------------------------- | +| api-gateway | `service:read` | +| bound-api-gateway | `service:read` | +| exported-services | `mesh:read` or `operator:read` | +| file-system-certificate | `mesh:read` or `operator:read` | +| http-route | `mesh:read` or `operator:read` | +| ingress-gateway | `service:read` | +| inline-certificate | `mesh:read` or `operator:read` | +| mesh | No ACL required | +| proxy-defaults | No ACL required | +| service-defaults | `service:read` | +| service-intentions | `intentions:read` | +| service-resolver | `service:read` | +| service-router | `service:read` | +| service-splitter | `service:read` | +| tcp-route | `mesh:read` or `operator:read` | +| terminating-gateway | `service:read` | ### Path Parameters @@ -148,6 +152,8 @@ The ACL required depends on the config entry kind being read: - `ns` `(string: "")` - Specifies the namespace of the config entry you lookup You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -192,23 +198,24 @@ The table below shows this endpoint's support for The ACL required depends on the config entry kind being read: -| Config Entry Kind | Required ACLs | -| ------------------- | -------------------------------- | -| api-gateway | `service:read` | -| bound-api-gateway | `service:read` | -| exported-services | `mesh:read` or `operator:read` | -| http-route | `mesh:read` or `operator:read` | -| ingress-gateway | `service:read` | -| inline-certificate | `mesh:read` or `operator:read` | -| mesh | No ACL required | -| proxy-defaults | No ACL required | -| service-defaults | `service:read` | -| service-intentions | `intentions:read` | -| service-resolver | `service:read` | -| service-router | `service:read` | -| service-splitter | `service:read` | -| tcp-route | `mesh:read` or `operator:read` | -| terminating-gateway | `service:read` | +| Config Entry Kind | Required ACLs | +| ----------------------- | -------------------------------- | +| api-gateway | `service:read` | +| bound-api-gateway | `service:read` | +| exported-services | `mesh:read` or `operator:read` | +| file-system-certificate | `mesh:read` or `operator:read` | +| http-route | `mesh:read` or `operator:read` | +| ingress-gateway | `service:read` | +| inline-certificate | `mesh:read` or `operator:read` | +| mesh | No ACL required | +| proxy-defaults | No ACL required | +| service-defaults | `service:read` | +| service-intentions | `intentions:read` | +| service-resolver | `service:read` | +| service-router | `service:read` | +| service-splitter | `service:read` | +| tcp-route | `mesh:read` or `operator:read` | +| terminating-gateway | `service:read` | The corresponding CLI command is [`consul config list`](/consul/commands/config/list). @@ -225,6 +232,8 @@ The corresponding CLI command is [`consul config list`](/consul/commands/config/ - `ns` `(string: "")` - Specifies the namespace of the config entries you lookup. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -276,23 +285,24 @@ The table below shows this endpoint's support for The ACL required depends on the config entry kind being deleted: -| Config Entry Kind | Required ACLs | -| ------------------- | -------------------------------- | -| api-gateway | `mesh:write` or `operator:write` | -| bound-api-gateway | Not writable. | -| exported-services | `mesh:write` or `operator:write` | -| http-route | `mesh:write` or `operator:write` | -| ingress-gateway | `mesh:write` or `operator:write` | -| inline-certificate | `mesh:write` or `operator:write` | -| mesh | `mesh:write` or `operator:write` | -| proxy-defaults | `mesh:write` or `operator:write` | -| service-defaults | `service:write` | -| service-intentions | `intentions:write` | -| service-resolver | `service:write` | -| service-router | `service:write` | -| service-splitter | `service:write` | -| tcp-route | `mesh:write` or `operator:write` | -| terminating-gateway | `mesh:write` or `operator:write` | +| Config Entry Kind | Required ACLs | +| ----------------------- | -------------------------------- | +| api-gateway | `mesh:write` or `operator:write` | +| bound-api-gateway | Not writable. | +| exported-services | `mesh:write` or `operator:write` | +| file-system-certificate | `mesh:write` or `operator:write` | +| http-route | `mesh:write` or `operator:write` | +| ingress-gateway | `mesh:write` or `operator:write` | +| inline-certificate | `mesh:write` or `operator:write` | +| mesh | `mesh:write` or `operator:write` | +| proxy-defaults | `mesh:write` or `operator:write` | +| service-defaults | `service:write` | +| service-intentions | `intentions:write` | +| service-resolver | `service:write` | +| service-router | `service:write` | +| service-splitter | `service:write` | +| tcp-route | `mesh:write` or `operator:write` | +| terminating-gateway | `mesh:write` or `operator:write` | The corresponding CLI command is [`consul config delete`](/consul/commands/config/delete). @@ -317,6 +327,8 @@ The corresponding CLI command is [`consul config delete`](/consul/commands/confi - `ns` `(string: "")` - Specifies the namespace of the config entry you delete. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session diff --git a/website/content/api-docs/connect/intentions.mdx b/website/content/api-docs/connect/intentions.mdx index ebe835ac905f..95a5cfca60a4 100644 --- a/website/content/api-docs/connect/intentions.mdx +++ b/website/content/api-docs/connect/intentions.mdx @@ -60,6 +60,8 @@ The corresponding CLI command is [`consul intention create -replace`](/consul/co as shown in the [source and destination naming conventions](/consul/commands/intention#source-and-destination-naming). You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### JSON Request Body Schema - `SourceType` `(string: "")` - The type for the `SourceName` value. @@ -151,6 +153,8 @@ The corresponding CLI command is [`consul intention create`](/consul/commands/in as shown in the [source and destination naming conventions](/consul/commands/intention#source-and-destination-naming). You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### JSON Request Body Schema - `SourceName` `(string: )` - The source of the intention. @@ -290,6 +294,8 @@ The corresponding CLI command is [`consul intention get`](/consul/commands/inten as shown in the [source and destination naming conventions](/consul/commands/intention#source-and-destination-naming). You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -404,6 +410,8 @@ The corresponding CLI command is [`consul intention list`](/consul/commands/inte The `*` wildcard may be used to list intentions from all namespaces. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -485,6 +493,8 @@ The corresponding CLI command is [`consul intention delete`](/consul/commands/in as shown in the [source and destination naming conventions](/consul/commands/intention#source-and-destination-naming). You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -628,6 +638,8 @@ The corresponding CLI command is [`consul intention match`](/consul/commands/int as shown in the [source and destination naming conventions](/consul/commands/intention#source-and-destination-naming). You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session diff --git a/website/content/api-docs/exported-services.mdx b/website/content/api-docs/exported-services.mdx new file mode 100644 index 000000000000..f7c89d4999a5 --- /dev/null +++ b/website/content/api-docs/exported-services.mdx @@ -0,0 +1,142 @@ +--- +layout: api +page_title: Exported Services - HTTP API +description: The /exported-services endpoint lists exported services and their consumers. +--- + +# Exported Services HTTP Endpoint + + + The exported services HTTP API endpoint requires Consul v1.17.3 or newer. + + +The `/exported-services` endpoint returns a list of exported services, as well as the admin partitions and cluster peers that consume the services. + +This list consists of the services that were exported using an [`exported-services` configuration entry](/consul/docs/connect/config-entries/exported-services). Sameness groups and wildcards in the configuration entry are expanded in the response. + +## List Exported Services + +This endpoint returns a list of exported services. + +| Method | Path | Produces | +| ------------------ | -------------------- | ------------------ | +| `GET` | `/exported-services` | `application/json` | + + +The table below shows this endpoint's support for +[blocking queries](/consul/api-docs/features/blocking), +[consistency modes](/consul/api-docs/features/consistency), +[agent caching](/consul/api-docs/features/caching), and +[required ACLs](/consul/api-docs/api-structure#authentication). + +| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | +| ---------------- | ----------------- | --------------- | ------------------------------ | +| `YES` | `none` | `none` | `mesh:read` or `operator:read` | + + +### Query Parameters + +@include 'http-api-query-parms-partition.mdx' + +### Sample Request + +```shell-session +$ curl --header "X-Consul-Token: 0137db51-5895-4c25-b6cd-d9ed992f4a52" \ + http://127.0.0.1:8500/v1/exported-services +``` + +### Sample Response + + + + + +```json +[ + { + "Service": "frontend", + "Consumers": { + "Peers": [ + "east", + "west", + ] + } + }, + { + "Service": "db", + "Consumers": { + "Peers": [ + "east", + ] + } + }, + { + "Service": "web", + "Consumers": { + "Peers": [ + "east", + "west" + ] + } + } +] +``` + + + + + +```json +[ + { + "Service": "frontend", + "Partition": "default", + "Namespace": "default", + "Consumers": { + "Peers": [ + "east", + "west" + ], + "Partitions": [ + "part1" + ] + } + }, + { + "Service": "frontend", + "Partition": "default", + "Namespace": "ns", + "Consumers": { + "Peers": [ + "east", + ] + } + }, + { + "Service": "web", + "Partition": "default", + "Namespace": "default", + "Consumers": { + "Peers": [ + "west" + ], + "Partitions": [ + "part1" + ] + } + }, + { + "Service": "db", + "Partition": "default", + "Namespace": "default", + "Consumers": { + "Partitions": [ + "part1" + ] + } + } +] +``` + + + \ No newline at end of file diff --git a/website/content/api-docs/hcp-link.mdx b/website/content/api-docs/hcp-link.mdx new file mode 100644 index 000000000000..7f543066912b --- /dev/null +++ b/website/content/api-docs/hcp-link.mdx @@ -0,0 +1,190 @@ +--- +layout: api +page_title: HCP Linking HTTP API +description: The Link resource allows for linking your cluster to HCP Consul Central. +--- + +# Link HTTP API + +-> **1.18.0+:** The Link API is available in Consul versions 1.18.0 and newer. + +-> **Note:** This endpoint does not use the `/v1/` prefix. + +The `/api/hcp/v2/link/global` endpoint allows you to link your Consul cluster to [HCP Consul Central](/hcp/docs/consul/concepts/consul-central). + +## Establish or update link to HCP Consul Central + +This endpoint creates or updates a Link, which establishes a connection with HCP Consul Central. + +| Method | Path | Produces | +| ------ | ----------------------------- | ------------------ | +| `PUT` | `/api/hcp/v2/link/global` | `application/json` | + +The table below shows this endpoint's support for +[blocking queries](/consul/api-docs/features/blocking), +[consistency modes](/consul/api-docs/features/consistency), +[agent caching](/consul/api-docs/features/caching), and +[required ACLs](/consul/api-docs/api-structure#authentication). + +| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | +| ---------------- | --------------------- | ------------- | ------------------------------ | +| `NO` | `stale`, `consistent` | `none` | `operator:write`, `acl:write` | + +### Link API vs. configuration-based linking + +The Link API described here is an alternative method to accomplish the same thing as [configuration-based linking](/consul/docs/agent/config/config-files#self-managed-hcp-parameters). You should generally only choose one method or the other for linking your cluster, not both. If you do use both methods, they interact in the following ways: + +* When Consul is started, values set in the `cloud` configuration will take precedence over what was previously set by the API or CLI. +* Clusters can only be unlinked from HCP Consul Central by the API or CLI, regardless of if they were established via configuration, API, or CLI. + +### JSON Request Body Schema + +- `data` `(object: )` + + - `resourceId` `(string: )` - The ID of the HCP Consul Central cluster to link to. Has the format of: + `organization//project//hashicorp.consul.global-network-manager.cluster/` + + - `clientId` `(string: )` - The ID used to authenticate to HCP, which is returned as part of the HCP + Consul Central cluster creation. It can also be obtained by fetching the HCP Consul Central cluster secrets. + + - `clientSecret` `(string: )` - The secret used to authenticate to HCP, which is returned as part of the + HCP Consul Central cluster creation. It can also be obtained by fetching the HCP Consul Central cluster secrets. + +### Sample Payload + +```json +{ + "data": { + "resourceId": "organization/c0bf7aac-7690-4905-a8aa-889df1510314/project/6e82a47b-79af-4920-ad42-c0f74421ab52/hashicorp.consul.global-network-manager.cluster/my-cluster", + "clientId": "3jz6zk2tlr802htzwquczlxlsrohlpm5", + "clientSecret": "07ywcvaqmg1f8ko9eq4julep2tfglnv4o18rz3py9dik4ywox0ytoscycn39o4vs" + } +} +``` + +### Sample Request + +```shell-session +$ curl --request PUT \ + --header "X-Consul-Token: 9cdjse6c-2dia-3720-81fe-5dae3k714a6e" \ + --data @payload.json \ + http://127.0.0.1:8500/api/hcp/v2/link/global +``` + +### Sample Response + +```json +{ + "data": { + "clientId": "3jz6zk2tlr802htzwquczlxlsrohlpm5", + "clientSecret": "07ywcvaqmg1f8ko9eq4julep2tfglnv4o18rz3py9dik4ywox0ytoscycn39o4vs", + "resourceId": "organization/c0bf7aac-7690-4905-a8aa-889df1510314/project/6e82a47b-79af-4920-ad42-c0f74421ab52/hashicorp.consul.global-network-manager.cluster/my-cluster" + }, + "generation": "01HMHTHZND8VJDXHHJBKDR4TTA", + "id": { + "name": "global", + "tenancy": { + "peerName": "local" + }, + "type": { + "group": "hcp", + "groupVersion": "v2", + "kind": "Link" + }, + "uid": "01HMHTHZND8VJDXHHJBGY1KG0F" + }, + "version": "60" +} +``` + +## Read Link + +This endpoint reads a Link so you can view information about your cluster's current linking status. + +| Method | Path | Produces | +| ------ | ----------------------------- | ------------------ | +| `GET` | `/api/hcp/v2/link/global` | `application/json` | + +The table below shows this endpoint's support for +[blocking queries](/consul/api-docs/features/blocking), +[consistency modes](/consul/api-docs/features/consistency), +[agent caching](/consul/api-docs/features/caching), and +[required ACLs](/consul/api-docs/api-structure#authentication). + +| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | +| ---------------- | --------------------- | ------------- | ---------------- | +| `NO` | `stale`, `consistent` | `none` | `operator:read` | + +### Sample Request + +```shell-session +$ curl --header "X-Consul-Token: 5cdcae6c-0cce-4210-86fe-5dff3b984a6e" \ + http://127.0.0.1:8500/api/hcp/v2/link/global +``` + +### Sample Response +```json +{ + "data": { + "accessLevel": "ACCESS_LEVEL_GLOBAL_READ_WRITE", + "clientId": "3jz6zk2tlr802htzwquczlxlsrohlpm5", + "clientSecret": "07ywcvaqmg1f8ko9eq4julep2tfglnv4o18rz3py9dik4ywox0ytoscycn39o4vs", + "hcpClusterUrl": "https://portal.cloud.hashicorp.com/services/consul/clusters/self-managed/my-cluster?project_id=6e82a47b-79af-4920-ad42-c0f74421ab52", + "resourceId": "organization/c0bf7aac-7690-4905-a8aa-889df1510314/project/6e82a47b-79af-4920-ad42-c0f74421ab52/hashicorp.consul.global-network-manager.cluster/my-cluster" + }, + "generation": "01HMHTF4K5V27T91FMVHGFE87F", + "id": { + "name": "global", + "tenancy": { + "peerName": "local" + }, + "type": { + "group": "hcp", + "groupVersion": "v2", + "kind": "Link" + }, + "uid": "01HMHS7DJ9FEQH5XK1VD0W0536" + }, + "status": { + "consul.io/hcp/link": { + "conditions": [ + { + "message": "Successfully linked to cluster 'organization/c0bf7aac-7690-4905-a8aa-889df1510314/project/6e82a47b-79af-4920-ad42-c0f74421ab52/hashicorp.consul.global-network-manager.cluster/my-cluster'", + "reason": "SUCCESS", + "state": "STATE_TRUE", + "type": "linked" + } + ], + "observedGeneration": "01HMHS7DN1C417JXJF7DBVS79F", + "updatedAt": "2024-01-19T21:14:59.707744Z" + } + }, + "version": "53" +} +``` + +## Delete Link + +This endpoint deletes a Link, which removes the cluster's connection with HCP Consul Central. + +| Method | Path | Produces | +| --------- | ----------------------------- | ------------------ | +| `DELETE` | `/api/hcp/v2/link/global` | `application/json` | + +The table below shows this endpoint's support for +[blocking queries](/consul/api-docs/features/blocking), +[consistency modes](/consul/api-docs/features/consistency), +[agent caching](/consul/api-docs/features/caching), and +[required ACLs](/consul/api-docs/api-structure#authentication). + +| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | +| ---------------- | ---------------------- | ------------- | -------------------------------- | +| `NO` | `stale`, `consistent` | `none` | `operator:write`, `acl:write` | + +### Sample Request + +```shell-session +$ curl --request DELETE \ + --header "X-Consul-Token: 5cdcae6c-0cce-4210-86fe-5dff3b984a6e" \ + http://127.0.0.1:8500/api/hcp/v2/link/global +``` diff --git a/website/content/api-docs/index.mdx b/website/content/api-docs/index.mdx index 20d0021e30cd..1b972e442523 100644 --- a/website/content/api-docs/index.mdx +++ b/website/content/api-docs/index.mdx @@ -49,6 +49,7 @@ The following API endpoints help you manage Consul operations. - [`/namespace`](/consul/api-docs/namespaces): Create and manage namespaces in Consul. Namespaces isolate groups of resources to lower operational overhead. - [`/snapshot`](/consul/api-docs/snapshot): Save and restore Consul server state in the event of a disaster. - [`/txn`](/consul/api-docs/txn): Apply multiple operations, such as updating the catalog and retrieving multiple KV entries, in a single transaction. +- [`/api/hcp/v2/link/global`](/consul/api-docs/hcp-link): Link cluster to [HCP Consul Central](/hcp/docs/consul/concepts/consul-central). HCP Consul Central is a management plane service hosted by HashiCorp that enables you to monitor and manage Consul clusters. ## Configure your services dynamically diff --git a/website/content/api-docs/kv.mdx b/website/content/api-docs/kv.mdx index 29aa32cbe6a3..3eef6eb27f71 100644 --- a/website/content/api-docs/kv.mdx +++ b/website/content/api-docs/kv.mdx @@ -79,6 +79,8 @@ The corresponding CLI command is [`consul kv get`](/consul/commands/kv/get). For recursive lookups, the namespace may be specified as '\*' to return results for all namespaces. +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -210,7 +212,7 @@ The corresponding CLI command is [`consul kv put`](/consul/commands/kv/put). session has locked the key.** For an example of how to use the lock feature, check the - [Leader Election tutorial](/consul/tutorials/developer-configuration/application-leader-elections). + [Leader Election tutorial](/consul/docs/dynamic-app-config/sessions/application-leader-election). - `release` `(string: "")` - Supply a session ID to use in a release operation. This is useful when paired with `?acquire=` as it allows clients to yield a lock. This @@ -220,6 +222,8 @@ The corresponding CLI command is [`consul kv put`](/consul/commands/kv/put). - `ns` `(string: "")` - Specifies the namespace to query. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Payload The payload is arbitrary, and is loaded directly into Consul as supplied. @@ -289,6 +293,8 @@ The corresponding CLI command is [`consul kv delete`](/consul/commands/kv/delete - `ns` `(string: "")` - Specifies the namespace to query. You can also [specify the namespace through other methods](#methods-to-specify-namespace). +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session diff --git a/website/content/api-docs/libraries-and-sdks.mdx b/website/content/api-docs/libraries-and-sdks.mdx index eb2e8bd775a2..5e65bfe53050 100644 --- a/website/content/api-docs/libraries-and-sdks.mdx +++ b/website/content/api-docs/libraries-and-sdks.mdx @@ -23,12 +23,8 @@ the community. the Consul HTTP API
    1. - python-consul - - Python client for the Consul HTTP API (unmaintained) -
    2. -
    3. - python-consul2 - - Python client for the Consul HTTP API (currently maintained) + py-consul - + Python client for the Consul HTTP API
    4. consul-kv - Python 3 client diff --git a/website/content/api-docs/namespaces.mdx b/website/content/api-docs/namespaces.mdx index 2dd41a7e9ba1..8c963d80a9f0 100644 --- a/website/content/api-docs/namespaces.mdx +++ b/website/content/api-docs/namespaces.mdx @@ -67,6 +67,8 @@ The corresponding CLI command is [`consul namespace create`](/consul/commands/na - `Meta` `(map: )` - Specifies arbitrary KV metadata to associate with the namespace. +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -169,6 +171,10 @@ The corresponding CLI command is [`consul namespace read`](/consul/commands/name - `name` `(string: )` - Specifies the namespace to read. +### Query Parameters + +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -272,6 +278,8 @@ The corresponding CLI command is [`consul namespace update`](/consul/commands/na - `Meta` `(map: )` - Specifies arbitrary KV metadata to associate with the namespace. +@include 'http-api-body-options-partition.mdx' + ### Sample Payload ```json @@ -348,18 +356,15 @@ $ curl --request PUT \ ## Delete a Namespace -This endpoint marks a Namespace for deletion. Once marked Consul will -deleted all the associated Namespaced data in the background. Only once -all associated data has been deleted will the Namespace actually disappear. -Until then, further reads can be performed on the namespace and a `DeletedAt` -field will now be populated with the timestamp of when the Namespace was -marked for deletion. +This endpoint marks a Namespace for deletion. Once marked, Consul deletes all the associated Namespaced data in the background. Only after all associated data has been deleted, Consul deletes the Namespace. +Until then, you can perform further reads on the namespace, and a `DeletedAt` +field is populated with the timestamp of when the Namespace was marked for deletion. | Method | Path | Produces | | -------- | ------------------ | -------- | | `DELETE` | `/namespace/:name` | N/A | -This endpoint will return no data. Success or failure is indicated by the status +This endpoint returns no data. Success or failure is indicated by the status code returned. The table below shows this endpoint's support for @@ -378,6 +383,10 @@ The corresponding CLI command is [`consul namespace delete`](/consul/commands/na - `name` `(string: )` - Specifies the namespace to delete. +### Query Parameters + +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session @@ -449,6 +458,10 @@ the request has been granted any access in the namespace (read, list or write). The corresponding CLI command is [`consul namespace list`](/consul/commands/namespace/list). +### Query Parameters + +@include 'http-api-query-parms-partition.mdx' + ### Sample Request ```shell-session diff --git a/website/content/api-docs/peering.mdx b/website/content/api-docs/peering.mdx index 9478af104cf8..f0e4d7767710 100644 --- a/website/content/api-docs/peering.mdx +++ b/website/content/api-docs/peering.mdx @@ -34,8 +34,7 @@ The table below shows this endpoint's support for and configuration entries such as `service-intentions`. This field must be a valid DNS hostname label. -- `Partition` `(string: "")` - The admin partition that the - peering token is generated from. Uses `default` when not specified. +@include 'http-api-body-options-partition.mdx' - `ServerExternalAddresses` `([]string: )` - The addresses for the cluster that generates the peering token. Addresses take the form `{host or IP}:port`. You can specify one or more load balancers or external IPs that route external traffic to this cluster's Consul servers. @@ -100,9 +99,7 @@ The table below shows this endpoint's support for and configuration entries such as `service-intentions`. This field must be a valid DNS hostname label. -- `Partition` `(string: "")` - The admin partition - that peers to the cluster that generated the peering token. Uses `default` - when not specified. +@include 'http-api-body-options-partition.mdx' - `PeeringToken` `(string: )` - The peering token fetched from the peer cluster. @@ -162,8 +159,7 @@ The table below shows this endpoint's support for ### Query Parameters -- `partition` `(string: "")` - Specifies the partition of the peering - to read. If not specified will default to `default`. +@include 'http-api-query-parms-partition.mdx' ### Sample Request @@ -184,8 +180,25 @@ $ curl --header "X-Consul-Token: b23b3cad-5ea1-4413-919e-c76884b9ad60" \ "PeerServerAddresses": [ "10.0.0.1:8300" ], + "StreamStatus": { + "ImportedServices": [ + "db", + ], + "ExportedServices": [ + "backend", + "frontend", + "web" + ], + "LastHeartbeat": "2023-12-13T06:31:28.227392Z", + "LastReceive": "2023-12-13T06:31:28.227392Z", + "LastSend": "2023-12-05T11:02:57.528676Z" + }, "CreateIndex": 89, - "ModifyIndex": 89 + "ModifyIndex": 89, + "Remote": { + "Partition": "", + "Datacenter": "east" + } } ``` @@ -218,8 +231,7 @@ The table below shows this endpoint's support for ### Query Parameters -- `partition` `(string: "")` - Specifies the partition of the peerings - to delete. If not specified will default to `default`. +@include 'http-api-query-parms-partition.mdx' ### Sample Request @@ -269,8 +281,7 @@ The table below shows this endpoint's support for ### Query Parameters -- `partition` `(string: "")` - Specifies the partition of the peerings - to list. If not specified will default to `default`. +@include 'http-api-query-parms-partition.mdx' ### Sample Request @@ -293,8 +304,25 @@ $ curl --header "X-Consul-Token: 0137db51-5895-4c25-b6cd-d9ed992f4a52" \ "PeerServerAddresses": [ "10.0.0.1:8300" ], + "StreamStatus": { + "ImportedServices": [ + "db", + ], + "ExportedServices": [ + "backend", + "frontend", + "web" + ], + "LastHeartbeat": "2023-12-13T06:31:28.227392Z", + "LastReceive": "2023-12-13T06:31:28.227392Z", + "LastSend": "2023-12-05T11:02:57.528676Z" + }, "CreateIndex": 89, - "ModifyIndex": 89 + "ModifyIndex": 89, + "Remote": { + "Partition": "", + "Datacenter": "east" + } }, { "ID": "1460ada9-26d2-f30d-3359-2968aa7dc47d", @@ -304,8 +332,22 @@ $ curl --header "X-Consul-Token: 0137db51-5895-4c25-b6cd-d9ed992f4a52" \ "Meta": { "env": "production" }, + "StreamStatus": { + "ImportedServices": null, + "ExportedServices": [ + "backend", + "frontend", + ], + "LastHeartbeat": "2023-12-13T06:31:28.227392Z", + "LastReceive": "2023-12-13T06:31:28.227392Z", + "LastSend": "2023-12-05T11:02:57.528676Z" + }, "CreateIndex": 109, - "ModifyIndex": 119 + "ModifyIndex": 119, + "Remote": { + "Partition": "", + "Datacenter": "east" + } } ] ``` diff --git a/website/content/api-docs/session.mdx b/website/content/api-docs/session.mdx index 30dd005a1c7e..3f13f178d711 100644 --- a/website/content/api-docs/session.mdx +++ b/website/content/api-docs/session.mdx @@ -77,7 +77,7 @@ The table below shows this endpoint's support for 86400s). If provided, the session is invalidated if it is not renewed before the TTL expires. The lowest practical TTL should be used to keep the number of managed sessions low. When locks are forcibly expired, such as when following - the [leader election pattern](/consul/tutorials/developer-configuration/application-leader-elections) in an application, + the [leader election pattern](/consul/docs/dynamic-app-config/sessions/application-leader-election) in an application, sessions may not be reaped for up to double this TTL, so long TTL values (> 1 hour) should be avoided. Valid time units include "s", "m" and "h". diff --git a/website/content/commands/acl/auth-method/create.mdx b/website/content/commands/acl/auth-method/create.mdx index 7a7ef7ea70ef..4f1015cfb61d 100644 --- a/website/content/commands/acl/auth-method/create.mdx +++ b/website/content/commands/acl/auth-method/create.mdx @@ -67,7 +67,7 @@ Usage: `consul acl auth-method create [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/auth-method/delete.mdx b/website/content/commands/acl/auth-method/delete.mdx index fc2e166d362c..acb095c5872b 100644 --- a/website/content/commands/acl/auth-method/delete.mdx +++ b/website/content/commands/acl/auth-method/delete.mdx @@ -31,7 +31,7 @@ Usage: `consul acl auth-method delete [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/auth-method/list.mdx b/website/content/commands/acl/auth-method/list.mdx index c7d2c0b9c2b4..42d7285ca76d 100644 --- a/website/content/commands/acl/auth-method/list.mdx +++ b/website/content/commands/acl/auth-method/list.mdx @@ -34,7 +34,7 @@ Usage: `consul acl auth-method list` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/auth-method/read.mdx b/website/content/commands/acl/auth-method/read.mdx index 928863846de5..015852f9684c 100644 --- a/website/content/commands/acl/auth-method/read.mdx +++ b/website/content/commands/acl/auth-method/read.mdx @@ -36,7 +36,7 @@ Usage: `consul acl auth-method read [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/auth-method/update.mdx b/website/content/commands/acl/auth-method/update.mdx index aef12ff351c9..d328ea999c2b 100644 --- a/website/content/commands/acl/auth-method/update.mdx +++ b/website/content/commands/acl/auth-method/update.mdx @@ -72,7 +72,7 @@ Usage: `consul acl auth-method update [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/binding-rule/create.mdx b/website/content/commands/acl/binding-rule/create.mdx index fd925e8d9359..b32b2ce934e5 100644 --- a/website/content/commands/acl/binding-rule/create.mdx +++ b/website/content/commands/acl/binding-rule/create.mdx @@ -30,7 +30,7 @@ Usage: `consul acl binding-rule create [options] [args]` - `-bind-name=` - Name to bind on match. Can use `${var}` interpolation. This flag is required. -- `-bind-type=` - Type of binding to perform (`"service"` or `"role"`). +- `-bind-type=` - Type of binding to perform (`"service"`, `"node"`, `"templated-policy"`, `"policy"` or `"role"`). - `-description=` - A description of the binding rule. @@ -47,7 +47,7 @@ Usage: `consul acl binding-rule create [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' @@ -90,3 +90,35 @@ BindType: role BindName: vault Selector: serviceaccount.namespace==default and serviceaccount.name==vault ``` + +Create a new binding rule that binds to a policy: + +```shell-session +$ consul acl binding-rule create -method 'nomad' \ + -description 'gets policy for nomad job' \ + -bind-type 'policy' \ + -bind-name 'nomad-${nomad.jobname}' \ + -selector 'nomad.jobname==billing-app' +ID: e21ae868-7b13-a230-0235-f8e83510642c +AuthMethod: nomad +Description: gets policy for nomad job +BindType: policy +BindName: nomad-billing-app +Selector: nomad.jobname==billing-app +``` + +Create a new binding rule that binds to a templated policy: + +```shell-session +$ consul acl binding-rule create -method 'remote-jwks' \ + -description 'gets templated policy for dns tokens' \ + -bind-type 'templated-policy' \ + -bind-name 'builtin/dns' \ + -selector 'serviceaccount.namespace==default' +ID: eaca9aa4-8913-c8ef-ba39-bfae64f66d99 +AuthMethod: remote-jwks +Description: gets templated policy for dns tokens +BindType: templated-policy +BindName: builtin/dns +Selector: serviceaccount.namespace==default +``` \ No newline at end of file diff --git a/website/content/commands/acl/binding-rule/delete.mdx b/website/content/commands/acl/binding-rule/delete.mdx index c78e36031040..9164f62a7c0e 100644 --- a/website/content/commands/acl/binding-rule/delete.mdx +++ b/website/content/commands/acl/binding-rule/delete.mdx @@ -32,7 +32,7 @@ Usage: `consul acl binding-rule delete [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/binding-rule/list.mdx b/website/content/commands/acl/binding-rule/list.mdx index 9d01e9d2b1b7..cbb9c184c821 100644 --- a/website/content/commands/acl/binding-rule/list.mdx +++ b/website/content/commands/acl/binding-rule/list.mdx @@ -34,7 +34,7 @@ Usage: `consul acl binding-rule list` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/binding-rule/read.mdx b/website/content/commands/acl/binding-rule/read.mdx index 86b8b4169c6c..50f1e8112f88 100644 --- a/website/content/commands/acl/binding-rule/read.mdx +++ b/website/content/commands/acl/binding-rule/read.mdx @@ -37,7 +37,7 @@ Usage: `consul acl binding-rule read [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/binding-rule/update.mdx b/website/content/commands/acl/binding-rule/update.mdx index 24f690129433..22ad67e0cfc9 100644 --- a/website/content/commands/acl/binding-rule/update.mdx +++ b/website/content/commands/acl/binding-rule/update.mdx @@ -33,7 +33,7 @@ Usage: `consul acl binding-rule update [options] [args]` - `-bind-name=` - Name to bind on match. Can use `${var}` interpolation. This flag is required. -- `-bind-type=` - Type of binding to perform (`"service"` or `"role"`). +- `-bind-type=` - Type of binding to perform (`"service"`, `"node"`, `"templated-policy"`, `"policy"` or `"role"`). - `-description=` - A description of the binding rule. @@ -54,7 +54,7 @@ Usage: `consul acl binding-rule update [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/policy/create.mdx b/website/content/commands/acl/policy/create.mdx index cbd4b8d8757d..e178536515e0 100644 --- a/website/content/commands/acl/policy/create.mdx +++ b/website/content/commands/acl/policy/create.mdx @@ -49,7 +49,7 @@ Usage: `consul acl policy create [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/policy/delete.mdx b/website/content/commands/acl/policy/delete.mdx index 074dfea607d1..2b611f5a78dc 100644 --- a/website/content/commands/acl/policy/delete.mdx +++ b/website/content/commands/acl/policy/delete.mdx @@ -34,7 +34,7 @@ Usage: `consul acl policy delete [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/policy/list.mdx b/website/content/commands/acl/policy/list.mdx index 7d56fd6f2137..ad3b114b9793 100644 --- a/website/content/commands/acl/policy/list.mdx +++ b/website/content/commands/acl/policy/list.mdx @@ -34,7 +34,7 @@ Usage: `consul acl policy list` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/policy/read.mdx b/website/content/commands/acl/policy/read.mdx index b84b5d3c3483..28e2f51a79d0 100644 --- a/website/content/commands/acl/policy/read.mdx +++ b/website/content/commands/acl/policy/read.mdx @@ -39,7 +39,7 @@ Usage: `consul acl policy read [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/policy/update.mdx b/website/content/commands/acl/policy/update.mdx index f64a1f79068e..edc529a5da9f 100644 --- a/website/content/commands/acl/policy/update.mdx +++ b/website/content/commands/acl/policy/update.mdx @@ -58,7 +58,7 @@ Usage: `consul acl policy update [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/role/create.mdx b/website/content/commands/acl/role/create.mdx index 44af92bd4e64..82989a2697a1 100644 --- a/website/content/commands/acl/role/create.mdx +++ b/website/content/commands/acl/role/create.mdx @@ -52,7 +52,7 @@ Usage: `consul acl role create [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/role/delete.mdx b/website/content/commands/acl/role/delete.mdx index bb2a179d92e1..9a39e97ab843 100644 --- a/website/content/commands/acl/role/delete.mdx +++ b/website/content/commands/acl/role/delete.mdx @@ -34,7 +34,7 @@ Usage: `consul acl role delete [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/role/list.mdx b/website/content/commands/acl/role/list.mdx index ed3699ce3fa7..afd8c75a41a9 100644 --- a/website/content/commands/acl/role/list.mdx +++ b/website/content/commands/acl/role/list.mdx @@ -34,7 +34,7 @@ Usage: `consul acl role list` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/role/read.mdx b/website/content/commands/acl/role/read.mdx index 7de17d5dcb2c..aa5008f57d5c 100644 --- a/website/content/commands/acl/role/read.mdx +++ b/website/content/commands/acl/role/read.mdx @@ -39,7 +39,7 @@ Usage: `consul acl role read [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/role/update.mdx b/website/content/commands/acl/role/update.mdx index d6991a21e0fb..1308e445ba7f 100644 --- a/website/content/commands/acl/role/update.mdx +++ b/website/content/commands/acl/role/update.mdx @@ -63,7 +63,7 @@ Usage: `consul acl role update [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/set-agent-token.mdx b/website/content/commands/acl/set-agent-token.mdx index 7279349dbbd9..c56b706871b2 100644 --- a/website/content/commands/acl/set-agent-token.mdx +++ b/website/content/commands/acl/set-agent-token.mdx @@ -32,21 +32,14 @@ Usage: `consul acl set-agent-token [options] token_type token_secret_id` The token types are: -- `default` - The default token is the token that the agent will use for - both internal agent operations and operations initiated by the HTTP - and DNS interfaces when no specific token is provided. If not set the - agent will use the anonymous token. - - `agent` - The token that the agent will use for internal agent operations. If not given then the default token is used for these operations. -- `recovery` - This sets the token that can be used to access the Agent APIs - in the event that the ACL datacenter cannot be reached. In Consul versions - prior to 1.11, this token type was called `agent_master`. - -- `replication` - This is the token that the agent will use for replication - operations. This token will need to be configured with read access to - whatever data is being replicated. +- `dns` - Specifies the token that agents use to request information needed to respond to DNS queries. + If the `dns` token is not set, Consul uses the `default` token by default. + Because the `default` token allows unauthenticated HTTP API access to list nodes and services, we + strongly recommend using the `dns` token. Create DNS tokens using the [templated policy](/consul/docs/security/acl/tokens/create/create-a-dns-token#create_a_dns_token) option + to ensure that the token has the permissions needed to respond to all DNS queries. - `config_file_service_registration` - This is the token that the agent uses to register services and checks defined in config files. This token needs to be @@ -55,6 +48,17 @@ The token types are: contains a `token` field, then that token is used to register that service or check instead of the `config_file_service_registration` token. +- `replication` - This is the token that the agent uses for replication + operations. This token must be configured with read access to + all data that the agent replicates. + +- `recovery` - This sets the token that allows access to the agent APIs when the ACL datacenter is unreachable. + +- `default` - The default token is the token that the agent uses for + both internal agent operations and operations initiated by the HTTP + and DNS interfaces when no specific token is provided. If not set the + agent uses the anonymous token. + ### API Options @include 'http_api_options_client.mdx' diff --git a/website/content/commands/acl/templated-policy/preview.mdx b/website/content/commands/acl/templated-policy/preview.mdx index 7e0c38d165c9..cfffa6db7e55 100644 --- a/website/content/commands/acl/templated-policy/preview.mdx +++ b/website/content/commands/acl/templated-policy/preview.mdx @@ -36,7 +36,7 @@ Usage: `consul acl templated-policy preview [options] [args]` ### Enterprise options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/token/clone.mdx b/website/content/commands/acl/token/clone.mdx index 7f2822d6c579..937097fb284d 100644 --- a/website/content/commands/acl/token/clone.mdx +++ b/website/content/commands/acl/token/clone.mdx @@ -38,7 +38,7 @@ Usage: `consul acl token clone [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/token/create.mdx b/website/content/commands/acl/token/create.mdx index f0622ace7ec8..8cd5fb6b948b 100644 --- a/website/content/commands/acl/token/create.mdx +++ b/website/content/commands/acl/token/create.mdx @@ -66,7 +66,7 @@ Usage: `consul acl token create [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/token/delete.mdx b/website/content/commands/acl/token/delete.mdx index 5ba65957589b..13a3ca26e6e3 100644 --- a/website/content/commands/acl/token/delete.mdx +++ b/website/content/commands/acl/token/delete.mdx @@ -32,7 +32,7 @@ Usage: `consul acl token delete [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/token/list.mdx b/website/content/commands/acl/token/list.mdx index 531b4cc68ed8..fd3b6c215114 100644 --- a/website/content/commands/acl/token/list.mdx +++ b/website/content/commands/acl/token/list.mdx @@ -34,7 +34,7 @@ Usage: `consul acl token list` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/token/read.mdx b/website/content/commands/acl/token/read.mdx index e339292d9663..dfcbea12d8e1 100644 --- a/website/content/commands/acl/token/read.mdx +++ b/website/content/commands/acl/token/read.mdx @@ -43,7 +43,7 @@ Usage: `consul acl token read [options] [args]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/acl/token/update.mdx b/website/content/commands/acl/token/update.mdx index 1a1703cb143b..1f89d828641c 100644 --- a/website/content/commands/acl/token/update.mdx +++ b/website/content/commands/acl/token/update.mdx @@ -93,7 +93,7 @@ instead. #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/catalog/nodes.mdx b/website/content/commands/catalog/nodes.mdx index f612627be23d..6efa3ad0716c 100644 --- a/website/content/commands/catalog/nodes.mdx +++ b/website/content/commands/catalog/nodes.mdx @@ -85,7 +85,7 @@ Usage: `consul catalog nodes [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' #### API Options diff --git a/website/content/commands/catalog/services.mdx b/website/content/commands/catalog/services.mdx index 9d05ecbf47ac..a57adcb4a927 100644 --- a/website/content/commands/catalog/services.mdx +++ b/website/content/commands/catalog/services.mdx @@ -69,7 +69,7 @@ Usage: `consul catalog services [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/config/delete.mdx b/website/content/commands/config/delete.mdx index 134d6885e666..085b0e34c411 100644 --- a/website/content/commands/config/delete.mdx +++ b/website/content/commands/config/delete.mdx @@ -61,7 +61,7 @@ config entry. This is used in combination with the -cas flag. @include 'http_api_namespace_options.mdx' -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' #### API Options diff --git a/website/content/commands/config/list.mdx b/website/content/commands/config/list.mdx index e453b1194319..5f55a7bcff72 100644 --- a/website/content/commands/config/list.mdx +++ b/website/content/commands/config/list.mdx @@ -48,7 +48,7 @@ Usage: `consul config list [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/config/read.mdx b/website/content/commands/config/read.mdx index 7a49482c5b3f..c54a60dfec16 100644 --- a/website/content/commands/config/read.mdx +++ b/website/content/commands/config/read.mdx @@ -52,7 +52,7 @@ Usage: `consul config read [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/config/write.mdx b/website/content/commands/config/write.mdx index bb98d8e49888..f466654c617f 100644 --- a/website/content/commands/config/write.mdx +++ b/website/content/commands/config/write.mdx @@ -53,7 +53,7 @@ Usage: `consul config write [options] FILE` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/connect/envoy.mdx b/website/content/commands/connect/envoy.mdx index 744873df5656..913adb981dff 100644 --- a/website/content/commands/connect/envoy.mdx +++ b/website/content/commands/connect/envoy.mdx @@ -199,7 +199,7 @@ compatibility with Envoy and prevent potential issues. Default is `false`. #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/connect/redirect-traffic.mdx b/website/content/commands/connect/redirect-traffic.mdx index af59baee56b7..d59fe7928cf6 100644 --- a/website/content/commands/connect/redirect-traffic.mdx +++ b/website/content/commands/connect/redirect-traffic.mdx @@ -60,7 +60,7 @@ Usage: `consul connect redirect-traffic [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/intention/check.mdx b/website/content/commands/intention/check.mdx index fadc8d224bd9..23ae56ceae4e 100644 --- a/website/content/commands/intention/check.mdx +++ b/website/content/commands/intention/check.mdx @@ -41,7 +41,7 @@ Usage: `consul intention check [options] SRC DST` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/intention/create.mdx b/website/content/commands/intention/create.mdx index 71c491b06ad8..bbaccc2be2f4 100644 --- a/website/content/commands/intention/create.mdx +++ b/website/content/commands/intention/create.mdx @@ -52,7 +52,7 @@ are not supported from commands, but may be from the corresponding HTTP endpoint #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/intention/delete.mdx b/website/content/commands/intention/delete.mdx index ad2fca1c97e2..2cfb97a966db 100644 --- a/website/content/commands/intention/delete.mdx +++ b/website/content/commands/intention/delete.mdx @@ -37,7 +37,7 @@ Usage: #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/intention/get.mdx b/website/content/commands/intention/get.mdx index 84b3a86065d0..b3db133fd44e 100644 --- a/website/content/commands/intention/get.mdx +++ b/website/content/commands/intention/get.mdx @@ -37,7 +37,7 @@ Usage: #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/intention/match.mdx b/website/content/commands/intention/match.mdx index 4c727b1fc21c..3d94939b38bf 100644 --- a/website/content/commands/intention/match.mdx +++ b/website/content/commands/intention/match.mdx @@ -40,7 +40,7 @@ Usage: `consul intention match [options] SRC_OR_DST` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/kv/delete.mdx b/website/content/commands/kv/delete.mdx index 90e2e54624bf..17216b0ca78b 100644 --- a/website/content/commands/kv/delete.mdx +++ b/website/content/commands/kv/delete.mdx @@ -40,7 +40,7 @@ Usage: `consul kv delete [options] KEY_OR_PREFIX` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/kv/export.mdx b/website/content/commands/kv/export.mdx index da063e9d826d..c05b2f80f895 100644 --- a/website/content/commands/kv/export.mdx +++ b/website/content/commands/kv/export.mdx @@ -28,7 +28,7 @@ Usage: `consul kv export [options] [PREFIX]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/kv/get.mdx b/website/content/commands/kv/get.mdx index 0e83b2facb52..6534fe35486b 100644 --- a/website/content/commands/kv/get.mdx +++ b/website/content/commands/kv/get.mdx @@ -56,7 +56,7 @@ Usage: `consul kv get [options] [KEY_OR_PREFIX]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/kv/import.mdx b/website/content/commands/kv/import.mdx index 574fdfbd87be..a960b1b738ce 100644 --- a/website/content/commands/kv/import.mdx +++ b/website/content/commands/kv/import.mdx @@ -31,7 +31,7 @@ Usage: `consul kv import [options] [DATA]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/kv/put.mdx b/website/content/commands/kv/put.mdx index efb045179fb8..dcde811fc01c 100644 --- a/website/content/commands/kv/put.mdx +++ b/website/content/commands/kv/put.mdx @@ -59,7 +59,7 @@ Usage: `consul kv put [options] KEY [DATA]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/lock.mdx b/website/content/commands/lock.mdx index d4f405324c13..85a15680516f 100644 --- a/website/content/commands/lock.mdx +++ b/website/content/commands/lock.mdx @@ -18,7 +18,7 @@ communication is disrupted, the child process is terminated. The number of lock holders is configurable with the `-n` flag. By default, a single holder is allowed, and a lock is used for mutual exclusion. This -uses the [leader election algorithm](/consul/tutorials/developer-configuration/application-leader-elections). +uses the [leader election algorithm](/consul/docs/dynamic-app-config/sessions/application-leader-election). If the lock holder count is more than one, then a semaphore is used instead. A semaphore allows more than a single holder, but this is less efficient than diff --git a/website/content/commands/members.mdx b/website/content/commands/members.mdx index ff1df561a6f4..6299f21e4c82 100644 --- a/website/content/commands/members.mdx +++ b/website/content/commands/members.mdx @@ -56,7 +56,7 @@ Usage: `consul members [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' #### API Options diff --git a/website/content/commands/namespace/create.mdx b/website/content/commands/namespace/create.mdx index f5d611a542e4..068666e5cafd 100644 --- a/website/content/commands/namespace/create.mdx +++ b/website/content/commands/namespace/create.mdx @@ -61,7 +61,7 @@ from the CLI arguments. #### API Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_options_client.mdx' diff --git a/website/content/commands/namespace/delete.mdx b/website/content/commands/namespace/delete.mdx index 8742af6f4d61..adc235be6062 100644 --- a/website/content/commands/namespace/delete.mdx +++ b/website/content/commands/namespace/delete.mdx @@ -30,7 +30,7 @@ Usage: `consul namespace delete ` #### API Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_options_client.mdx' diff --git a/website/content/commands/namespace/list.mdx b/website/content/commands/namespace/list.mdx index 5d15c1f1155c..1b043ed657d6 100644 --- a/website/content/commands/namespace/list.mdx +++ b/website/content/commands/namespace/list.mdx @@ -42,7 +42,7 @@ Usage: `consul namespace list` #### API Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_options_client.mdx' diff --git a/website/content/commands/namespace/read.mdx b/website/content/commands/namespace/read.mdx index 4a4621ef06bc..778f672ff5c8 100644 --- a/website/content/commands/namespace/read.mdx +++ b/website/content/commands/namespace/read.mdx @@ -41,7 +41,7 @@ Usage: `consul namespace read ` #### API Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_options_client.mdx' diff --git a/website/content/commands/namespace/update.mdx b/website/content/commands/namespace/update.mdx index 6349d307f638..4cce12235675 100644 --- a/website/content/commands/namespace/update.mdx +++ b/website/content/commands/namespace/update.mdx @@ -68,7 +68,7 @@ with the existing namespace definition. #### API Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_options_client.mdx' diff --git a/website/content/commands/namespace/write.mdx b/website/content/commands/namespace/write.mdx index 678c303a802f..f1a16ec006bd 100644 --- a/website/content/commands/namespace/write.mdx +++ b/website/content/commands/namespace/write.mdx @@ -40,7 +40,7 @@ or HCL format. See [here](/consul/docs/enterprise/namespaces#namespace-definitio #### API Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_options_client.mdx' diff --git a/website/content/commands/peering/delete.mdx b/website/content/commands/peering/delete.mdx index 81ba3439dbbc..1bd474dc306f 100644 --- a/website/content/commands/peering/delete.mdx +++ b/website/content/commands/peering/delete.mdx @@ -34,7 +34,7 @@ Usage: `consul peering delete [options] -name ` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' #### API Options diff --git a/website/content/commands/peering/establish.mdx b/website/content/commands/peering/establish.mdx index a00dc332180d..782fb9cda681 100644 --- a/website/content/commands/peering/establish.mdx +++ b/website/content/commands/peering/establish.mdx @@ -36,7 +36,7 @@ Usage: `consul peering establish [options] -name -peering-token ` + +#### Command Options + +- `-name=` - (Required) The name of the peer associated with a connection. + +- `-format={pretty|json}` - Command output format. The default value is `pretty`. + +#### Enterprise Options + +@include 'cli-http-api-partition-options.mdx' + +#### API Options + +@include 'http_api_options_client.mdx' + +## Examples + +The following example outputs the exported services to a peering connection locally referred to as "cluster-02": + +```shell-session hideClipboard +$ consul peering exported-services -name cluster-02 +backend +frontend +web +``` + diff --git a/website/content/commands/peering/generate-token.mdx b/website/content/commands/peering/generate-token.mdx index 92d007125c69..6ce3fb059cb5 100644 --- a/website/content/commands/peering/generate-token.mdx +++ b/website/content/commands/peering/generate-token.mdx @@ -43,7 +43,7 @@ You can specify one or more load balancers or external IPs that route external t #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' #### API Options diff --git a/website/content/commands/peering/index.mdx b/website/content/commands/peering/index.mdx index cd3a2b359c81..62af45d22b1c 100644 --- a/website/content/commands/peering/index.mdx +++ b/website/content/commands/peering/index.mdx @@ -22,11 +22,12 @@ Usage: consul peering [options] Subcommands: - delete Close and delete a peering connection - establish Consume a peering token and establish a connection with the accepting cluster - generate-token Generate a peering token for use by a dialing cluster - list List the local cluster's peering connections - read Read detailed information on a peering connection + delete Close and delete a peering connection + establish Consume a peering token and establish a connection with the accepting cluster + exported-services Lists the services exported to the peer + generate-token Generate a peering token for use by a dialing cluster + list List the local cluster's peering connections + read Read detailed information on a peering connection ``` For more information, examples, and usage about a subcommand, click on the name @@ -36,4 +37,5 @@ of the subcommand in the sidebar or one of the links below: - [establish](/consul/commands/peering/establish) - [generate-token](/consul/commands/peering/generate-token) - [list](/consul/commands/peering/list) -- [read](/consul/commands/peering/read) \ No newline at end of file +- [read](/consul/commands/peering/read) +- [exported-services](/consul/commands/peering/exported-services) \ No newline at end of file diff --git a/website/content/commands/peering/list.mdx b/website/content/commands/peering/list.mdx index f0b1c8377735..9838de3e7bc5 100644 --- a/website/content/commands/peering/list.mdx +++ b/website/content/commands/peering/list.mdx @@ -30,7 +30,7 @@ Usage: `consul peering list [options]` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' #### API Options diff --git a/website/content/commands/peering/read.mdx b/website/content/commands/peering/read.mdx index 596c514520bb..95a41b2701aa 100644 --- a/website/content/commands/peering/read.mdx +++ b/website/content/commands/peering/read.mdx @@ -31,7 +31,7 @@ Usage: `consul peering read [options] -name ` #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' #### API Options diff --git a/website/content/commands/services/deregister.mdx b/website/content/commands/services/deregister.mdx index edc493866e1c..138de2e763eb 100644 --- a/website/content/commands/services/deregister.mdx +++ b/website/content/commands/services/deregister.mdx @@ -43,7 +43,7 @@ This flexibility makes it easy to pair the command with the #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/services/export.mdx b/website/content/commands/services/export.mdx index 281d5f23e7d7..370f95dd6437 100644 --- a/website/content/commands/services/export.mdx +++ b/website/content/commands/services/export.mdx @@ -40,7 +40,7 @@ Usage: consul services export [options] -name -consumer-peers ` - A comma-separated list of admin partitions within the same datacenter to export the service to. This flag is optional when `-consumer-peers` is specified. -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/services/exported-services.mdx b/website/content/commands/services/exported-services.mdx new file mode 100644 index 000000000000..395ad2cb8b30 --- /dev/null +++ b/website/content/commands/services/exported-services.mdx @@ -0,0 +1,57 @@ +--- +layout: commands +page_title: 'Commands: Exported Services' +description: >- + The `consul services exported-services` command lists exported services and their consumers. +--- + +# Consul Exported Services + +Command: `consul services exported-services` + +Corresponding HTTP API Endpoint: [\[GET\] /v1/exported-services](/consul/api-docs/exported-services) + +The `exported-services` command displays the services that were exported using an [`exported-services` configuration entry](/consul/docs/connect/config-entries/exported-services). Sameness groups and wildcards in the configuration entry are expanded in the response. + + +The table below shows this command's [required ACLs](/consul/api-docs/api-structure#authentication). + +| ACL Required | +| ------------------------------ | +| `mesh:read` or `operator:read` | + +## Usage + +Usage: `consul services exported-services [options]` + +#### Command Options + +- `-format={pretty|json}` - Command output format. The default value is `pretty`. + +- `-filter` - Specifies an expression to use for filtering the results. `Consumers.Peers` and `Consumers.Partitions' selectors are supported. + +#### Enterprise Options + +@include 'cli-http-api-partition-options.mdx' + +#### API Options + +@include 'http_api_options_client.mdx' + +## Examples + +To list all exported services and consumers: + + $ consul services exported-services + Service Consumer Peers + backend east, west + db west + frontend east, east-eu + web east + +The following lists exported services with a filter expression: + + $ consul services exported-services -filter='"west" in Consumers.Peers' + Service Consumer Peers + backend east, west + db west diff --git a/website/content/commands/services/register.mdx b/website/content/commands/services/register.mdx index a1cbd8cf580e..01a09d19bfdb 100644 --- a/website/content/commands/services/register.mdx +++ b/website/content/commands/services/register.mdx @@ -78,7 +78,7 @@ The following fields specify identical parameters in a standard service definiti #### Enterprise Options -@include 'http_api_partition_options.mdx' +@include 'cli-http-api-partition-options.mdx' @include 'http_api_namespace_options.mdx' diff --git a/website/content/commands/snapshot/agent.mdx b/website/content/commands/snapshot/agent.mdx index fe5821dcf40f..e86c62809e48 100644 --- a/website/content/commands/snapshot/agent.mdx +++ b/website/content/commands/snapshot/agent.mdx @@ -2,7 +2,7 @@ layout: commands page_title: 'Commands: Snapshot Agent' description: | - The `consul snapshot agent` command starts a process that takes snapshots of the state of the Consul servers in Consul Enterprise. It can capture server state once or it can run as daemon that captures snapshots at defined intervals. + The `consul snapshot agent` command starts a process that takes snapshots of the state of the Consul servers in Consul Enterprise. It can capture server state once or it can run as a daemon that captures snapshots at defined intervals. --- # Consul Snapshot Agent @@ -17,8 +17,8 @@ version 0.7.1 and later. All other [snapshot subcommands](/consul/commands/snaps are available in the community edition of Consul. The `snapshot agent` subcommand starts a process that takes snapshots of the -state of the Consul servers and saves them locally, or pushes them to an -optional remote storage service. +state of the Consul servers and saves them locally, or pushes them to optional +remote storage services. The agent can be run as a long-running daemon process or in a one-shot mode from a batch job, based on the [`-interval`](#interval) argument. Snapshotting @@ -36,10 +36,10 @@ leader and starting saving snapshots. As snapshots are saved, they will be reported in the log produced by the agent: ```log -2016/11/16 21:21:13 [INFO] Snapshot agent running -2016/11/16 21:21:13 [INFO] Waiting to obtain leadership... -2016/11/16 21:21:13 [INFO] Obtained leadership -2016/11/16 21:21:13 [INFO] Saved snapshot 1479360073448728784 +2023/11/16 21:21:13 [INFO] Snapshot agent running +2023/11/16 21:21:13 [INFO] Waiting to obtain leadership... +2023/11/16 21:21:13 [INFO] Obtained leadership +2023/11/16 21:21:13 [INFO] Saved snapshot 1479360073448728784 ``` The number shown with the saved snapshot is its ID, which is based on a UNIX @@ -133,6 +133,8 @@ Usage: `consul snapshot agent [options]` Config files referenced using `-config-dir` and `-config-file` have the following format (shown populated with default values): +~> Top-level single snapshot destinations in a config file are deprecated and will be removed in a future version. Move top-level `local_storage`, `aws_storage`, `azure_blob_storage`, and `google_storage` config objects to `snapshot_agent -> backup_destinations` instead. + ```json { "snapshot_agent": { @@ -149,7 +151,7 @@ Usage: `consul snapshot agent [options]` "auth_method": "", "bearer_token": "", "bearer_token_file": "", - "meta": {}, + "meta": {} }, "log": { "level": "INFO", @@ -166,32 +168,40 @@ Usage: `consul snapshot agent [options]` "max_failures": 3, "local_scratch_path": "" }, - "local_storage": { - "path": "." - }, - "aws_storage": { - "access_key_id": "", - "secret_access_key": "", - "session_token": "", - "iam_endpoint": "", - "role_arn": "", - "role_session_name": "", - "web_identity_token_file": "", - "sts_endpoint": "", - "s3_region": "", - "s3_bucket": "", - "s3_key_prefix": "consul-snapshot", - "s3_server_side_encryption": false, - "s3_static_snapshot_name": "", - "s3_force_path_style": false - }, - "azure_blob_storage": { - "account_name": "", - "account_key": "", - "container_name": "" - }, - "google_storage": { - "bucket": "" + "backup_destinations": { + "local_storage": [ + { + "path": "." + } + ], + "aws_storage": [ + { + "access_key_id": "", + "secret_access_key": "", + "session_token": "", + "iam_endpoint": "", + "role_arn": "", + "role_session_name": "", + "web_identity_token_file": "", + "sts_endpoint": "", + "s3_region": "", + "s3_endpoint": "", + "s3_bucket": "", + "s3_key_prefix": "consul-snapshot" + } + ], + "azure_blob_storage": [ + { + "account_name": "", + "account_key": "", + "container_name": "" + } + ], + "google_storage": [ + { + "bucket": "" + } + ] } } } @@ -211,7 +221,7 @@ if desired. is useful for running snapshots via batch jobs. Defaults to "1h" - `-lock-key` - A prefix in Consul's KV store used to coordinate between - different instances of the snapshot agent order to only have one active instance + different instances of the snapshot agent in order to only have one active instance at a time. For highly available operation of the snapshot agent, simply run multiple instances. All instances must be configured with the same lock key in order to properly coordinate. Defaults to "consul-snapshot/lock". @@ -229,8 +239,7 @@ if desired. - `-local-scratch-path` - Location to store all temporary snapshots in prior to sending them off to the configured storage backend. If not configured the - system temporary directory will be used. When using the local storage backend - this is not configurable and `-local-path` will be used. + system temporary directory will be used. #### Agent Options @@ -242,7 +251,7 @@ if desired. - `-log-level` - Controls verbosity of snapshot agent logs. Valid options are "trace", "debug", "info", "warn", "error". Defaults to "info". -- `-service` - The service name to used when registering the agent with Consul. +- `-service` - The service name to use when registering the agent with Consul. Registering helps monitor running agents and the leader registers an additional health check to monitor that snapshots are taking place. Defaults to "consul-snapshot". @@ -264,13 +273,21 @@ if desired. #### Local Storage Options +~> This option is deprecated when used with a top-level `local_storage` object in a config file. Use `snapshot_agent -> backup_destinations -> local_storage[0]` in a config file instead. + +This option cannot be used when using `backup_destinations` in a config file. + - `-local-path` - Location to store snapshots locally. The default behavior of the snapshot agent is to store snapshots locally in this directory. Defaults - to "." to use the current working directory. If an alternate storage option is - configured, then local storage will be disabled and this option will be ignored. + to "." to use the current working directory. If an alternate remote storage + option is configured, then local storage will be disabled and this option will + be ignored. #### S3 Storage Options +~> These options are deprecated when used with a top-level `aws_storage` object in a config file. Use `snapshot_agent -> backup_destinations -> aws_storage[0]` in a config file instead. + +These options cannot be used when using `backup_destinations` in a config file. Note that despite the AWS references, any S3-compatible endpoint can be specified with `-aws-s3-endpoint`. - `-aws-access-key-id`, `-aws-secret-access-key` and `-aws-session-token` - These arguments supply static @@ -365,10 +382,14 @@ The following example IAM policy document assumes that the `aws-s3-bucket` is `c #### Azure Blob Storage options +~> These options are deprecated when used with a top-level `azure_blob_storage` object in a config file. Use `snapshot_agent -> backup_destinations -> azure_blob_storage[0]` in a config file instead. + ** Note: This currently only works on non-Solaris platforms due to library limitations ** From Consul Enterprise version `1.5.0` onwards, you can store snapshots in Azure Blob storage. +These options cannot be used when using `backup_destinations` in a config file. + - `-azure-blob-account-name` and `-azure-blob-account-key` - These arguments supply authentication information for connecting to Azure Blob storage. @@ -380,14 +401,19 @@ From Consul Enterprise version `1.5.0` onwards, you can store snapshots in Azure #### Google Cloud Storage options +~> This option is deprecated when used with a top-level `google_storage` object in a config file. Use `snapshot_agent -> backup_destinations -> google_storage[0]` in a config file instead. + From Consul Enterprise version `1.6.1` onwards, you can store snapshots in Google Cloud Storage. Authentication relies on automatic discovery through the sdk as described [here](https://cloud.google.com/docs/authentication/production): + - First, ADC checks to see if the environment variable GOOGLE_APPLICATION_CREDENTIALS is set. If the variable is set, ADC uses the service account file that the variable points to. The next section describes how to set the environment variable. - If the environment variable isn't set, ADC uses the default service account that Compute Engine, Kubernetes Engine, App Engine, and Cloud Functions provide, for applications that run on those services. - If ADC can't use either of the above credentials, an error occurs. +This option cannot be used when using `backup_destinations` in a config file. + This integration needs the following information: - `-gcs-bucket` supplies the bucket to use. diff --git a/website/content/commands/snapshot/decode.mdx b/website/content/commands/snapshot/decode.mdx new file mode 100644 index 000000000000..72e908da8279 --- /dev/null +++ b/website/content/commands/snapshot/decode.mdx @@ -0,0 +1,52 @@ +--- +layout: commands +page_title: 'Commands: Snapshot Decode' +description: | + The `consul snapshot decode` command outputs a stream of line delimited JSON objects for an atomic, point-in-time snapshot of the state of the Consul servers. Output includes key/value entries, registered services in the catalog, prepared queries, sessions, and ACLs. +--- + +# Consul Snapshot Decode + +Command: `consul snapshot decode` + +The `snapshot decode` command is used to decode an atomic, point-in-time +snapshot of the state of the Consul servers which includes key/value entries, +service catalog, prepared queries, sessions, and ACLs. The snapshot is read +from the given file and decode to `stdout` as JSON data for interpretation and +review. + +-> Typically this is used with Consul self-contained Snapshot files obtained +using the [`consul snapshot`](/consul/commands/snapshot) command or [Snapshot +API](/consul/api-docs/snapshot#generate-snapshot). + +The JSON stream information format: + +```json + {"Type": "SnapshotHeader", "Data": {""}} + {"Type": "","Data": {}} + {"Type": "","Data": {}} + ... +``` + +## Usage + +Usage: `consul snapshot decode FILE` + +## Examples + +To decode a snapshot from the file "backup.snap": + +```shell-session +$ consul snapshot decode backup.snap +{"Data":{"Version":1,"ID":"2-134-1713801971207","Index":134,"Term":2,"Peers":"ka4xMjcuMC4wLjE6ODMwMA==","Configuration":{"Servers":[{"Suffrage":0,"ID":"673f5fe3-0c2a-bef5-7719-c9ddbbc7a1c5","Address":"127.0.0.1:8300"}]},"ConfigurationIndex":1,"Size":20448157},"Type":"SnapshotHeader"} +{"Data":{"Name":"consul-support-namespace-1","Description":"Test namespace consul-support-namespace-1","CreateIndex":102,"ModifyIndex":102},"Type":"Namespace"} +{"Data":{"Name":"consul-support-namespace-10","Description":"Test namespace consul-support-namespace-10","CreateIndex":120,"ModifyIndex":120},"Type":"Namespace"} +{"Data":{"Name":"default","Description":"Builtin Default Partition","CreateIndex":4,"ModifyIndex":4},"Type":"Partition"} +{"Data":{"IP":"0.0.0.3","IsCounter":true},"Type":"FreeVirtualIP"} +{"Data":{"Datacenter":"dc2","ID":"df779ee7-c5ef-46d1-30cf-e46f0166cdf4","Node":"consul-server-dc2","Address":"127.0.0.2","TaggedAddresses":{"lan":"127.0.0.2","lan_ipv4":"127.0.0.2","wan":"127.0.0.2","wan_ipv4":"127.0.0.2"},"NodeMeta":{"consul-network-segment":"","consul-version":"1.18.0"},"Service":null,"Check":null,"Checks":null,"Locality":null,"SkipNodeUpdate":false,"PeerName":"dc2-peer","Partition":"default","Token":"","CreateIndex":40,"ModifyIndex":40},"Type":"Register"} +... +``` + + +Please see the [HTTP API](/consul/api-docs/snapshot) documentation for +more details about snapshot internals. diff --git a/website/content/commands/troubleshoot/index.mdx b/website/content/commands/troubleshoot/index.mdx index 0c992aab15c9..74d9d9cec32a 100644 --- a/website/content/commands/troubleshoot/index.mdx +++ b/website/content/commands/troubleshoot/index.mdx @@ -22,6 +22,7 @@ Subcommands: proxy Troubleshoots service mesh issues from the current Envoy instance upstreams Gets upstream Envoy identifiers and IPs configured for the proxy + ports Prints open and closed ports on the Consul server. ``` For more information, examples, and usage about a subcommand, click on the name @@ -29,3 +30,4 @@ of the subcommand in the sidebar or one of the links below: - [proxy](/consul/commands/troubleshoot/proxy) - [upstreams](/consul/commands/troubleshoot/upstreams) +- [ports](/consul/commands/troubleshoot/ports) diff --git a/website/content/commands/troubleshoot/ports.mdx b/website/content/commands/troubleshoot/ports.mdx new file mode 100644 index 000000000000..5a4d5faf5082 --- /dev/null +++ b/website/content/commands/troubleshoot/ports.mdx @@ -0,0 +1,47 @@ +--- +layout: commands +page_title: 'Commands: Troubleshoot Ports' +description: >- + The `consul troubleshoot ports` Helps troubleshoot TCP ports by printing if they are open or closed. +--- + +# Consul Troubleshoot Upstreams + +Command: `consul troubleshoot ports` + +The `troubleshoot ports` prints TCP port statuses to help you troubleshoot port connectivity. + +## Usage + +Usage: `consul troubleshoot ports [options]` + +#### Command Options + +- `-host=` - Host name to troubleshoot TCP ports for. You can also set the `CONSUL_HTTP_ADDR` environment variable instead of using the `-host` flag. +- `-ports=` - Specifies a comma-separated list of custom ports to check. + +## Examples + +The following example checks the default ports Consul server uses for TCP connectivity. Note that the `CONSUL_HTTP_ADDR` environment variable is set to `localhost`. As a result, the `-host` flag is not required. +Refer to [Required Ports](/consul/docs/install/ports) for additional information. + +```shell-session +$ export CONSUL_HTTP_ADDR=localhost +$ consul troubleshoot ports +TCP: Port 8501 on localhost is open. +TCP: Port 8502 on localhost is open. +TCP: Port 8503 on localhost is open. +TCP: Port 8302 on localhost is open. +TCP: Port 8300 on localhost is open. +TCP: Port 8600 on localhost is open. +TCP: Port 8301 on localhost is open. +TCP: Port 8500 on localhost is open. +``` + +The following example checks TCP ports status on the `hashicorp.com` host. + +```shell-session +$ consul troubleshoot ports -host hashicorp.com -ports 80,8077 +TCP: Port 80 on hashicorp.com is open. +TCP: Port 8077 on hashicorp.com is closed, unreachable, or the connection timed out. +``` diff --git a/website/content/docs/agent/config-entries.mdx b/website/content/docs/agent/config-entries.mdx index f4b7f97f14bf..9eb3f82f7f5f 100644 --- a/website/content/docs/agent/config-entries.mdx +++ b/website/content/docs/agent/config-entries.mdx @@ -56,7 +56,7 @@ See [Kubernetes Custom Resource Definitions](/consul/docs/k8s/crds). Configuration entries outside of Kubernetes should be managed with the Consul [CLI](/consul/commands/config) or [API](/consul/api-docs/config). Additionally, as a convenience for initial cluster bootstrapping, configuration entries can be -specified in all of the Consul servers's +specified in all of the Consul server [configuration files](/consul/docs/agent/config/config-files#config_entries_bootstrap) ### Managing Configuration Entries with the CLI diff --git a/website/content/docs/agent/config/cli-flags.mdx b/website/content/docs/agent/config/cli-flags.mdx index 3ec1e8ba12b3..a38ddff8cbb5 100644 --- a/website/content/docs/agent/config/cli-flags.mdx +++ b/website/content/docs/agent/config/cli-flags.mdx @@ -424,13 +424,13 @@ information. - `-log-file` ((#\_log_file)) - writes all the Consul agent log messages to a file at the path indicated by this flag. The filename defaults to `consul.log`. - When the log file rotates, this value is used as a prefix for the path to the log and the current timestamp is + When the log file rotates, this value is used as a prefix for the path to the log and the current timestamp is appended to the file name. If the value ends in a path separator, `consul-` will be appended to the value. If the file name is missing an extension, `.log` is appended. For example, setting `log-file` to `/var/log/` would result in a log file path of `/var/log/consul.log`. `log-file` can be combined with [`-log-rotate-bytes`](#_log_rotate_bytes) and [`-log-rotate-duration`](#_log_rotate_duration) - for a fine-grained log rotation experience. After rotation, the path and filename take the following form: + for a fine-grained log rotation experience. After rotation, the path and filename take the following form: `/var/log/consul-{timestamp}.log` - `-log-rotate-bytes` ((#\_log_rotate_bytes)) - to specify the number of @@ -554,13 +554,12 @@ information. specifying only the `-ui` flag is enough to enable the Web UI. Specifying both the '-ui' and '-ui-dir' flags will result in an error. - - `-ui-content-path` ((#\_ui\_content\_path)) - This flag provides the option to change the path the Consul UI loads from and will be displayed in the browser. By default, the path is `/ui/`, for example `http://localhost:8500/ui/`. Only alphanumerics, - `-`, and `_` are allowed in a custom path.`/v1/` is not allowed as it would overwrite + `-`, and `_` are allowed in a custom path. `/v1/` is not allowed as it would overwrite the API endpoint. - +{/* list of reference-style links */} [go-sockaddr]: https://godoc.org/github.com/hashicorp/go-sockaddr/template diff --git a/website/content/docs/agent/config/config-files.mdx b/website/content/docs/agent/config/config-files.mdx index e1e0d05376b2..63e8137c4f06 100644 --- a/website/content/docs/agent/config/config-files.mdx +++ b/website/content/docs/agent/config/config-files.mdx @@ -402,7 +402,7 @@ Refer to the [formatting specification](https://golang.org/pkg/time/#ParseDurati -- `cache` configuration for client agents. The configurable values are the following: +- `cache` configuration for client agents. When an `?index` query parameter is specified but '?cached' is not appended in a [streaming backend call](/consul/api-docs/features/blocking#streaming-backend), Consul bypasses these configuration values. The configurable values are the following: - `entry_fetch_max_burst` The size of the token bucket used to recharge the rate-limit per cache entry. The default value is 2 and means that when cache has not been updated @@ -447,6 +447,10 @@ Refer to the [formatting specification](https://golang.org/pkg/time/#ParseDurati - `data_dir` Equivalent to the [`-data-dir` command-line flag](/consul/docs/agent/config/cli-flags#_data_dir). +- `default_intention_policy` Controls how service-to-service traffic is authorized + in the absence of specific intentions. + Can be set to `allow`, `deny`, or left empty to default to [`acl.default_policy`](#acl_default_policy). + - `disable_anonymous_signature` Disables providing an anonymous signature for de-duplication with the update check. See [`disable_update_check`](#disable_update_check). @@ -957,7 +961,13 @@ Refer to the [formatting specification](https://golang.org/pkg/time/#ParseDurati additional policy rules or the `config_file_service_registration` token can be replaced using the [Set Agent Token](/consul/commands/acl/set-agent-token) CLI command. - - `replication` ((#acl_tokens_replication)) - The ACL token used to + - `dns` ((#acl_tokens_dns)) - Specifies the token that agents use to request information needed to respond to DNS queries. + If the `dns` token is not set, the `default` token is used instead. + Because the `default` token allows unauthenticated HTTP API access to list nodes and services, we + strongly recommend using the `dns` token. Create DNS tokens using the [templated policy](/consul/docs/security/acl/tokens/create/create-a-dns-token#create_a_dns_token) + option to ensure that the token has the permissions needed to respond to all DNS queries. + + - `replication` ((#acl_tokens_replication)) - Specifies the token that the agent uses to authorize secondary datacenters with the primary datacenter for replication operations. This token is required for servers outside the [`primary_datacenter`](#primary_datacenter) when ACLs are enabled. This token may be provided later using the [agent token API](/consul/api-docs/agent#update-acl-tokens) on each server. This token must have at least "read" permissions on ACL data but if ACL token replication is enabled then it must have "write" permissions. This also enables service mesh data replication, for which the token will require both operator "write" and intention "read" permissions for replicating CA and Intention data. @@ -1291,7 +1301,7 @@ subsystem that provides Consul's service mesh capabilities. ## DNS and Domain Parameters - `dns_config` This object allows a number of sub-keys - to be set which can tune how DNS queries are serviced. Check the tutorial on [DNS caching](/consul/tutorials/networking/dns-caching) for more detail. + to be set which can tune how DNS queries are serviced. Refer to [DNS caching](/consul/docs/services/discovery/dns-cache) for more information. The following sub-keys are available: @@ -1694,7 +1704,7 @@ subsystem that provides Consul's service mesh capabilities. because Consul must scan the database to find free space within the file. - - - `wal` ((#raft_logstore_wal)) - Object that configures the `wal` backend. + - `wal` ((#raft_logstore_wal)) - Object that configures the `wal` backend. Refer to [Experimental WAL LogStore backend](/consul/docs/agent/wal-logstore) for more information. @@ -1832,6 +1842,9 @@ subsystem that provides Consul's service mesh capabilities. - `disable_hostname` ((#telemetry-disable_hostname)) Set to `true` to stop prepending the machine's hostname to gauge-type metrics. Default is `false`. + - `disable_per_tenancy_usage_metrics` ((#telemetry-disable_per_tenancy_usage_metrics)) + Set to `true` to exclude tenancy labels from usage metrics. This significantly decreases CPU utilization in clusters with many admin partitions or namespaces. + - `dogstatsd_addr` ((#telemetry-dogstatsd_addr)) This provides the address of a DogStatsD instance in the format `host:port`. DogStatsD is a protocol-compatible flavor of statsd, with the added ability to decorate metrics with tags and event @@ -2147,7 +2160,7 @@ specially crafted certificate signed by the CA can be used to gain full access t will not make use of TLS for outgoing connections. This applies to clients and servers as both will make outgoing connections. This setting does not apply to the gRPC interface as Consul makes no outgoing connections on this - interface. + interface. When set to true for the HTTPS interface, this parameter applies to [watches](/consul/docs/dynamic-app-config/watches), which operate by making HTTPS requests to the local agent. - `grpc` ((#tls_grpc)) Provides settings for the gRPC/xDS interface. To enable the gRPC interface you must define a port via [`ports.grpc_tls`](#grpc_tls_port). diff --git a/website/content/docs/agent/index.mdx b/website/content/docs/agent/index.mdx index b5a06b39e640..468e9087c2ae 100644 --- a/website/content/docs/agent/index.mdx +++ b/website/content/docs/agent/index.mdx @@ -382,8 +382,8 @@ The `client_addr` configuration specifies IP addresses used for HTTP, HTTPS, DNS ```hcl -node_name = "consul-server" -server = true +node_name = "consul-client" +server = false bootstrap = true ui_config { enabled = true @@ -405,8 +405,8 @@ advertise_addr = "{{ GetInterfaceIP \"en0\" }}" ```json { - "node_name": "consul-server", - "server": true, + "node_name": "consul-client", + "server": false, "bootstrap": true, "ui_config": { "enabled": true diff --git a/website/content/docs/agent/monitor/alerts.mdx b/website/content/docs/agent/monitor/alerts.mdx new file mode 100644 index 000000000000..d8dcc902478c --- /dev/null +++ b/website/content/docs/agent/monitor/alerts.mdx @@ -0,0 +1,83 @@ +--- +layout: docs +page_title: Consul monitoring and alerts recommendations +description: >- + Apply best practices towards Consul monitoring and alerts. +--- + +# Consul monitoring and alerts recommendations + +This document will guide you through which host resources to monitor and how monitoring tools can help you set up alerts to notify you when your Consul cluster exceeds its limits. By monitoring Consul and setting up alerts, you can ensure Consul works as expected for all your service discovery and service mesh needs. + +## Instance level monitoring + +While each host environment and Consul deployment is unique, these recommendations can serve as a starting point for you to reference to meet the unique needs of your deployment. + +A Consul datacenter is the smallest unit of Consul infrastructure that can perform basic Consul operations like service discovery or service mesh. A datacenter contains at least one Consul server agent, but a real-world deployment contains three or five server agents and several Consul client agents. + +Consul server agents store all state information, including service and node IP addresses, health checks, and configuration. Consul clients report node and service health status to the Consul cluster. In a typical deployment, you must run client agents on every compute node in your datacenter. If you have Kubernetes workloads, you can also run Consul with an alternate service mesh configuration that deploys Envoy proxies but not client agents. Refer to [Simplified service mesh with Consul dataplanes](/consul/docs/connect/dataplane) for more information. + +We recommend monitoring the following parameters for Consul agents health: +- Disk space and file handles +- [RAM utilization](/consul/docs/agent/telemetry#memory-usage) +- CPU utilization +- Network activity and utilization + +We recommend using an [application performance monitoring (APM) system](#monitoring-tools) to track these metrics. For a full list of key metrics, visit the [Key metrics](/consul/docs/agent/telemetry#key-metrics) section of Telemetry documentation. + +## Recommendations for host-level alerts + +We recommend starting with a small cluster for most initial production deployments or for testing environments. For production environments with a consistently high workload, we recommend large clusters . Refer to the [Consul capacity planning](/well-architected-framework/reliability/reliability-consul-capacity-planning#minimum-hardware-requirements) article for more information. + +When collecting metrics, it is important to establish a baseline. This baseline ensures your Consul deployment is healthy, and serves as a reference point when troubleshooting abnormal Cluster behavior. Complete the [Monitor Consul datacenter health](/consul/tutorials/day-2-operations/monitor-datacenter-health#how-to-collect-metrics) tutorial to learn how to collect metrics. + +Once you have established a baseline for your metrics, use them and the following recommendations to configure reasonable alerts for your Consul agent. + +### Memory alert recommendations + +Consul uses RAM as the primary storage for data on its leader node, while periodically flushing it to disk. Reference the [Memory usage](/consul/docs/agent/telemetry#memory-usage) section of the Telemetry documentation for more details. The recommended instance type depends on your hosting provider. Refer to the [Hardware sizing for Consul servers](/consul/tutorials/production-deploy/reference-architecture#hardware-sizing-for-consul-servers) for recommended instance types for most cloud providers along with other up-to-date hardware recommendations. + +When determining how much RAM you should allocate, we recommend enough RAM for your server agents to contain between 2 to 4 times the working set size. You can determine the working set size by noting the value of `consul.runtime.alloc_bytes` in the telemetry data. + +Set up an alert if your RAM usage exceeds a reasonable threshold (for example, 90% of your allocated RAM). + +### CPU alert recommendations + +Your Consul servers should scale up to handle peak CPU load, not idle load. When idle, Consul servers are waiting to react to changes in service health, placement, or other configuration. If there are any service state changes, the Consul server has to notify all impacted Consul clients simultaneously. For example, if the Consul server has to notify hundreds or thousands of Consul clients of a service state update, the Consul server CPU may spike. + +If this happens, your monitoring dashboard will show a CPU spike on all servers immediately after a big registration/deregistration operation. This should not happen — you should be able to do a rollout or other high-change operation without taxing the Consul servers. + +Set up an alert to detect CPU spikes on your Consul server agents. When this happens, evaluate the size of your Consul servers and upgrade them accordingly. + +### Network recommendations + +The data sent between all Consul agents must follow latency requirements for total round trip time (RTT): + +Average RTT for all traffic cannot exceed 50ms. +RTT for 99 percent of traffic cannot exceed 100ms. + +Refer to the [Reference architecture](/consul/tutorials/production-deploy/reference-architecture#network-latency-and-bandwidth) to learn more about network latency and bandwidth guidance. + +Set an alert to detect when the RTT exceeds these values. When this happens, Therefore, you should monitor metrics related to the host's network latency so the RTT does not exceed these values. + +### Monitoring Consul using Prometheus and Grafana + +Time series based observability tools, such as Grafana and Prometheus, help you monitor the health of Consul clusters over long intervals of time. Refer to the +[Monitoring for Layer 7 observability with Prometheus, Grafana, and Kubernetes](/consul/tutorials/day-2-operations/kubernetes-layer7-observability) tutorial for additional information. + +### Monitoring Consul using Datadog + +Datadog is a SaaS-based monitoring and analytics platform for large-scale applications and infrastructure. It is one of the supported platforms for monitoring Consul. Datadogs agents run on your host reporting logs, metrics and traces. By configuring Datadog agents on your Consul server and client instances, you can monitor your Consul cluster's health. + +Refer to the following resources for more information: + +- [Setup Consul logging with DataDog](https://www.datadoghq.com/blog/consul-datadog/) +- [Datadog monitoring solutions brief](https://www.datocms-assets.com/2885/1576713622-datadog-consul.pdf) +- [Hashicorp partner portal for Consul support on Datadog](https://www.hashicorp.com/partners/tech/datadog#consul) + +## Next steps + +In this guide, you learned which host resources to monitor and how monitoring tools can help you set up alerts to notify you when your Consul cluster exceeds its limits. + +- To learn about monitoring the Consul control and data plane, visit our [Monitoring Consul components](/well-architected-framework/reliability/reliability-consul-monitoring-consul-components) documentation. +- Complete the [Monitor Consul datacenter health with Telegraf](/consul/tutorials/day-2-operations/monitor-health-telegraf) tutorial for additional metrics and alerting recommendations. diff --git a/website/content/docs/agent/monitor/components.mdx b/website/content/docs/agent/monitor/components.mdx new file mode 100644 index 000000000000..1c3d49270e42 --- /dev/null +++ b/website/content/docs/agent/monitor/components.mdx @@ -0,0 +1,121 @@ +--- +layout: docs +page_title: Monitoring Consul components +description: >- + Apply best practices monitoring your Consul control and data plane. +--- + +# Monitoring Consul components + +This document will guide you recommendations for monitoring your Consul control and data plane. By keeping track of these components and setting up alerts, you can better maintain the overall health and resilience of your service mesh. + +## Background + +A Consul datacenter is the smallest unit of Consul infrastructure that can perform basic Consul operations like service discovery or service mesh. A datacenter contains at least one Consul server agent, but a real-world deployment contains three or five server agents and several Consul client agents. + +The Consul control plane consists of server agents that store all state information, including service and node IP addresses, health checks, and configuration. In addition, the control plane is responsible for securing the mesh, facilitating service discovery, health checking, policy enforcement, and other similar operational concerns. In addition, the control plane contains client agents that report node and service health status to the Consul cluster. In a typical deployment, you must run client agents on every compute node in your datacenter. + +The Consul data plane consists of proxies deployed locally alongside each service instance. These proxies, called sidecar proxies, receive mesh configuration data from the control plane, and control network communication between their local service instance and other services in the network. The sidecar proxy handles inbound and outbound service connections, and ensures TLS connections between services are both verified and encrypted. + +If you have Kubernetes workloads, you can also run Consul with an alternate service mesh configuration that deploys Envoy proxies but not client agents. Refer to [Simplified service mesh with Consul dataplanes](/consul/docs/connect/dataplane) for more information. + +## Consul control plane monitoring + +The Consul control plane consists of the following components: + +- RPC Communication between Consul servers and clients. +- Data plane routing instructions for the Envoy Layer 7 proxy. +- Serf Traffic: LAN and WAN +- Consul cluster peering and server federation + +It is important to monitor and establish baseline and alert thresholds for Consul control plane components for abnormal behavior detection. Note that these alerts can also be triggered by some planned events like Consul cluster upgrades, configuration changes, or leadership change. + +To help monitor your Consul control plane, we recommend to establish a baseline and standard deviation for the following: + +- [Server health](/consul/docs/agent/telemetry#server-health) +- [Leadership changes](/consul/docs/agent/telemetry#leadership-changes) +- [Key metrics](/consul/docs/agent/telemetry#key-metrics) +- [Autopilot](/consul/docs/agent/telemetry#autopilot) +- [Network activity](/consul/docs/agent/telemetry#network-activity-rpc-count) +- [Certificate authority expiration](/consul/docs/agent/telemetry#certificate-authority-expiration) + +It is important to have a highly performant network with low network latency. Ensure network latency for gossip in all datacenters are within the 8ms latency budget for all Consul agents. View the [Production server requirements](/consul/docs/install/performance#production-server-requirements) for more information. + +### Raft recommendations + +Consul uses [Raft for consensus protocol](/consul/docs/architecture/consensus). High saturation of the Raft goroutines can lead to elevated latency in the rest of the system and may cause the Consul cluster to be unstable. As a result, it is important to monitor Raft to track your control plane health. We recommend the following actions to keep control plane healthy: +- Create an alert that notifies you when [Raft thread saturation](/consul/docs/agent/telemetry#raft-thread-saturation) exceeds 50%. +- Monitor [Raft replication capacity](/consul/docs/agent/telemetry#raft-replication-capacity-issues) when Consul is handling large amounts of data and high write throughput. +- Lower [`raft_multiplier`](/consul/docs/install/performance#production) to keep your Consul cluster stable. The value of `raft_multiplier` defines the scaling factor for Consul. Default value for raft_multiplier is 5. + + A short multiplier minimizes failure detection and election time but may trigger frequently in high latency situations. This can cause constant leadership churn and associated unavailability. A high multiplier reduces the chances that spurious failures will cause leadership churn but it does this at the expense of taking longer to detect real failures and thus takes longer to restore Consul cluster availability. + + Wide networks with higher latency will perform better with larger `raft_multiplier` values. + +Raft uses BoltDB for storing data and maintaining its own state. Refer to the [Bolt DB performance metrics](/consul/docs/agent/telemetry#bolt-db-performance) when you are troubleshooting Raft performance issues. + +## Consul data plane monitoring + +The data plane of Consul consists of Consul clients or [Connect proxies](/consul/docs/connect/proxies) interacting with each other through service-to-service communication. Service-to-service traffic always stays within the data plane, while the control plane only enforces traffic rules. Monitoring service-to-service communication is important but may become extremely complex in an enterprise setup with multiple services communicating to each other across federated Consul clusters through mesh, ingress and terminating gateways. + +### Service monitoring + +You can extract the following service-related information: + +- Use the [`catalog`](/consul/commands/catalog) command or the Consul UI to query all registered services in a Consul datacenter. +- Use the [`/agent/service/:service_id`](/consul/api-docs/agent/service#get-service-configuration) API endpoint to query individual services. Connect proxies use this endpoint to discover embedded configuration. + +### Proxy monitoring + +Envoy is the supported Connect proxy for Consul service mesh. For virtual machines (VMs), Envoy starts as a sidecar service process. For Kubernetes, Envoy starts as a sidecar container in a Kubernetes service pod. +Refer to the [Supported Envoy versions](/consul/docs/connect/proxies/envoy#supported-versions) documentation to find the compatible Envoy versions for your version of Consul. + +For troubleshooting service mesh issues, set Consul logs to `trace` or `debug`. The following example annotation sets Envoy logging to `debug`. + +```yaml +annotations: + consul.hashicorp.com/envoy-extra-args: '--log-level debug --disable-hot-restart' +``` + +Refer to the [Enable logging on Envoy sidecar pods](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-envoy-extra-args) documentation for more information. + +#### Envoy Admin Interface + +To troubleshoot service-to-service communication issues, monitor Envoy host statistics. Envoy exposes a local administration interface that can be used to query and modify different aspects of the server on port `19000` by default. Envoy also exposes a public listener port to receive mTLS connections from other proxies in the mesh on port `20000` by default. + +All endpoints exposed by Envoy are available at the node running Envoy on port `19000`. The node can either be a pod in Kubernetes or VM running Consul Service Mesh. For example, if you forward the Envoy port to your local machine, you can access the Envoy admin interface at `http://localhost:19000/`. + +The following Envoy admin interface endpoints are particularly useful: + +- The `listeners` endpoint lists all listeners running on `localhost`. This allows you to confirm whether the upstream services are binding correctly to Envoy. + +```shell-session +$ curl http://localhost:19000/listeners +public_listener:192.168.19.168:20000::192.168.19.168:20000 +Outbound_listener:127.0.0.1:15001::127.0.0.1:15001 +``` + +- The `/clusters` endpoint displays information about the xDS clusters, such as service requests and mTLS related data. The following example shows a truncated output. + +```shell-session +$ http://localhost:19000/clusters +`local_app::observability_name::local_app +local_app::default_priority::max_connections::1024 +local_app::default_priority::max_pending_requests::1024 +local_app::default_priority::max_requests::1024 +local_app::default_priority::max_retries::3 +local_app::high_priority::max_connections::1024 +local_app::high_priority::max_pending_requests::1024 +local_app::high_priority::max_requests::1024 +local_app::high_priority::max_retries::3 +local_app::added_via_api::true +## ... +``` + +Visit the main admin interface (`http://localhost:19000`) to find the full list of possible Consul admin endpoints. Refer to the [Envoy docs](https://www.envoyproxy.io/docs/envoy/latest/operations/admin) for more information. + +## Next steps + +In this guide, you learned recommendations for monitoring your Consul control and data plane. + +To learn about monitoring the Consul host and instance resources, visit our [Monitoring best practices](/well-architected-framework/reliability/reliability-monitoring-service-to-service-communication-with-envoy) documentation. diff --git a/website/content/docs/agent/telemetry.mdx b/website/content/docs/agent/monitor/telemetry.mdx similarity index 99% rename from website/content/docs/agent/telemetry.mdx rename to website/content/docs/agent/monitor/telemetry.mdx index 82594504bacb..322ec40997d1 100644 --- a/website/content/docs/agent/telemetry.mdx +++ b/website/content/docs/agent/monitor/telemetry.mdx @@ -595,7 +595,29 @@ These metrics are used to monitor the health of the Consul servers. ** Requirements: ** * Consul 1.12.0+ -Label based RPC metrics were added in Consul 1.12.0 as a Beta feature to better understand the workload on a Consul server and, where that workload is coming from. The following metric(s) provide that insight +The following label-based RPC metrics provide insight about the workload on a Consul server and the source of the workload. + +The [`prefix_filter`](/consul/docs/agent/config/config-files#telemetry-prefix_filter) telemetry configuration setting blocks or enables all RPC metric method calls. Specify the RPC metrics you want to allow in the `prefix_filter`: + + + +```hcl +telemetry { + prefix_filter = ["+consul.rpc.server.call"] +} +``` + +```json +{ + "telemetry": { + "prefix_filter": [ + "+consul.rpc.server.call" + ] + } +} +``` + + | Metric | Description | Unit | Type | | ------------------------------------- | --------------------------------------------------------- | ------ | --------- | @@ -644,7 +666,6 @@ Here is a Prometheus style example of an RPC metric and its labels: -Any metric in this section can be turned off with the [`prefix_filter`](/consul/docs/agent/config/config-files#telemetry-prefix_filter). ## Cluster Health diff --git a/website/content/docs/agent/wal-logstore/index.mdx b/website/content/docs/agent/wal-logstore/index.mdx index 77dc1dd05846..b215db158c8b 100644 --- a/website/content/docs/agent/wal-logstore/index.mdx +++ b/website/content/docs/agent/wal-logstore/index.mdx @@ -32,7 +32,7 @@ To mitigate risks associated with sudden bursts of log data, Consul tries to lim But the larger the file, the more likely it is to have a large freelist or suddenly form one after a burst of writes. For this reason, the many of Consul's default options associated with snapshots, truncating logs, and keeping the log history aggressively keep BoltDT small rather than using disk IO more efficiently. -Other reliability issues, such as [raft replication capacity issues](/consul/docs/agent/telemetry#raft-replication-capacity-issues), are much simpler to solve without the performance concerns caused by storing more logs in BoltDB. +Other reliability issues, such as [raft replication capacity issues](/consul/docs/agent/monitor/telemetry#raft-replication-capacity-issues), are much simpler to solve without the performance concerns caused by storing more logs in BoltDB. ### WAL approaches storage issues differently diff --git a/website/content/docs/architecture/capacity-planning.mdx b/website/content/docs/architecture/capacity-planning.mdx new file mode 100644 index 000000000000..2f80c4cf289a --- /dev/null +++ b/website/content/docs/architecture/capacity-planning.mdx @@ -0,0 +1,188 @@ +--- +layout: docs +page_title: Consul capacity planning +description: >- + Learn how to maintain your Consul cluster in a healthy state by provisioning the correct resources. +--- + +# Consul capacity planning + +This page describes our capacity planning recommendations when deploying and maintaining a Consul cluster in production. When your organization designs a production environment, you should consider your available resources and their impact on network capacity. + +## Introduction + +It is important to select the correct size for your server instances. Consul server environments have a standard set of minimum requirements. However, these requirements may vary depending on what you are using Consul for. + +Insufficient resource allocations may cause network issues or degraded performance in general. When a slowdown in performance results in a Consul leader node that is unable to respond to requests in sufficient time, the Consul cluster triggers a new leader election. Consul pauses all network requests and Raft updates until the election ends. + +## Hardware requirements + +The minimum hardware requirements for Consul servers in production clusters as recommended by the [reference architecture](/consul/tutorials/production-deploy/reference-architecture#hardware-sizing-for-consul-servers) are: + +| CPU | Memory | Disk Capacity | Disk IO | Disk Throughput | Avg Round-Trip-Time | 99% Round-Trip-Time | +| --------- | ------------ | ------------- | ----------- | --------------- | ------------------- | ------------------- | +| 8-16 core | 32-64 GB RAM | 200+ GB | 7500+ IOPS | 250+ MB/s | Lower than 50ms | Lower than 100ms | + +For the major cloud providers, we recommend starting with one of the following instances that meet the minimum requirements. Then scale up as needed. We also recommend avoiding "burstable" CPU and storage options where performance may drop after a consistent load. + +| Provider | Size | Instance/VM Types | Disk Volume Specs | +| --------- | ----- | ------------------------------------- | --------------------------------- | +| **AWS** | Large | `m5.2xlarge`, `m5.4xlarge` | 200+GB `gp3`, 10000 IOPS, 250MB/s | +| **Azure** | Large | `Standard_D8s_v3`, `Standard_D16s_v3` | 2048GB `Premium SSD`, 7500 IOPS, 200MB/s | +| **GCP** | Large | `n2-standard-8`, `n2-standard-16` | 1000GB `pd-ssd`, 30000 IOPS, 480MB/s | + + +For HCP Consul Dedicated, cluster size is measured in the number of service instances supported. Find out more information in the [HCP Consul Dedicated pricing page](https://cloud.hashicorp.com/products/consul/pricing). + +## Workload input and output requirements + +Workloads are any actions that interact with the Consul cluster. These actions consist of key/value reads and writes, service registrations and deregistrations, adding or removing Consul client agents, and more. + +Input/output operations per second (IOPS) is a unit of measurement for the amount of reads and writes to non-adjacent storage locations. +For high workloads, ensure that the Consul server disks support a [high number of IOPS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-io-characteristics.html#ebs-io-iops) to keep up with the rapid Raft log update rate. +Unlike bare-metal environments, IOPS for virtual instances in cloud environments is often tied to storage sizing. More storage GBs typically grants you more IOPS. Therefore, we recommend deploying on [IOPS-optimized instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/provisioned-iops.html). + +Consul server agents are generally I/O bound for writes and CPU bound for reads. For additional tuning recommendations, refer to [raft tuning](#raft-tuning). + +## Memory requirements + +You should allocate RAM for server agents so that they contain 2 to 4 times the working set size. You can determine the working set size of a running cluster by noting the value of `consul.runtime.alloc_bytes` in the leader node's telemetry data. Inspect your monitoring solution for the telemetry value, or run the following commands with the [jq](https://stedolan.github.io/jq/download/) tool installed on your Consul leader instance. + + + +For Kubernetes, execute the command from the leader pod. `jq` is available in the Consul server containers. + + + +Set `$CONSUL_HTTP_TOKEN` to an ACL token with valid permissions, then retrieve the working set size. + +```shell-session +$ curl --silent --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" http://127.0.0.1:8500/v1/agent/metrics | jq '.Gauges[] | select(.Name=="consul.runtime.alloc_bytes") | .Value'` +616017920 +``` + +## Kubernetes storage requirements + +When you set up persistent volumes (PV) resources, you should define the correct server storage class parameter because the defaults are likely insufficient in performance. To set the [storageClass Helm chart parameter](/consul/docs/k8s/helm#v-server-storageclass), refer to the [Kubernetes documentation on storageClasses](https://kubernetes.io/docs/concepts/storage/storage-classes/) for more information about your specific cloud provider. + +## Read and write heavy workload recommendations + +In production, your use case may lead to Consul performing read-heavy workloads, write-heavy workloads, or both. Refer to the following table for specific resource recommendations for these types of workloads. + +| Workload type | Instance Recommendations | Workload element examples | Enterprise Feature Recommendations | +| ------------- | ------------------------- | ------------------------ | ------------------------ | +| Read-heavy | Instances of type `m5.4xlarge (AWS)`, `Standard_D16s_v3 (Azure)`, `n2-standard-16 (GCP)` | Raft RPCs calls, DNS queries, key/value retrieval | [Read replicas](/consul/docs/enterprise/read-scale) | +| Write-heavy | IOPS performance of `10 000+` | Consul agent joins and leaves, services registration and deregistration, key/value writes | [Network segments](/consul/docs/enterprise/network-segments/network-segments-overview) | + +For recommendations on troubleshooting issues with read-heavy or write-heavy workloads, refer to [Consul at Scale](/consul/docs/architecture/scale#resource-usage-and-metrics-recommendations). + +## Monitor performance + +Monitoring is critical to ensure that your Consul datacenter has sufficient resources to continue operations. A proactive monitoring strategy helps you find problems in your network before they impact your deployments. + +We recommend completing the [Monitor Consul server health and performance with metrics and logs](/consul/tutorials/observe-your-network/server-metrics-and-logs) tutorial as a starting point for Consul metrics and telemetry. The following tutorials guide you through specific monitoring solutions for your Consul cluster. + +- [Monitor Consul server health and performance with metrics and logs](/consul/tutorials/observe-your-network/server-metrics-and-logs) +- [Observe Consul service mesh traffic](/consul/tutorials/get-started-kubernetes/kubernetes-gs-observability) + +### Important metrics + +In production environments, create baselines for your Consul cluster's metrics. After you discover the baselines, you will be able to define alerts and receive notifications when there are unexpected values. For a detailed explanation on the metrics and their values, refer to [Consul Agent telemetry](/consul/docs/agent/telemetry). + +### Transaction metrics + +These metrics indicate how long it takes to complete write operations in various parts of the Consul cluster. + +- [`consul.kvs.apply`](/consul/docs/agent/monitor/telemetry#transaction-timing) measures the time it takes to complete an update to the KV store. +- [`consul.txn.apply`](/consul/docs/agent/monitor/telemetry#transaction-timing) measures the time spent applying a transaction operation. +- [`consul.raft.apply`](/consul/docs/agent/monitor/telemetry#transaction-timing) counts the number of Raft transactions applied during the measurement interval. This metric is only reported on the leader. +- [`consul.raft.commitTime`](/consul/docs/agent/monitor/telemetry#transaction-timing) measures the time it takes to commit a new entry to the Raft log on disk on the leader. + +### Memory metrics + +These performance indicators can help you diagnose if the current instance sizing is unable to handle the workload. + +- [`consul.runtime.alloc_bytes`](/consul/docs/agent/monitor/telemetry#memory-usage) measures the number of bytes allocated by the Consul process. +- [`consul.runtime.sys_bytes`](/consul/docs/agent/monitor/telemetry#memory-usage) measures the total number of bytes of memory obtained from the OS. +- [`consul.runtime.heap_objects`](/consul/docs/agent/monitor/telemetry#metrics-reference) measures the number of objects allocated on the heap and is a general memory pressure indicator. + +### Leadership metrics + +Leadership changes are not a cause for concern but frequent changes may be a symptom of a deeper problem. Frequent elections or leadership changes may indicate network issues between the Consul servers, or the Consul servers are unable to keep up with the load. + +- [`consul.raft.leader.lastContact`](/consul/docs/agent/monitor/telemetry#leadership-changes) measures the time since the leader was last able to contact the follower nodes when checking its leader lease. +- [`consul.raft.state.candidate`](/consul/docs/agent/monitor/telemetry#leadership-changes) increments whenever a Consul server starts an election. +- [`consul.raft.state.leader`](/consul/docs/agent/monitor/telemetry#leadership-changes) increments whenever a Consul server becomes a leader. +- [`consul.server.isLeader`](/consul/docs/agent/monitor/telemetry#leadership-changes) tracks whether a server is a leader. + +### Network metrics + +Network activity and RPC count measurements indicate the current load created from a Consul agent, including when the load becomes high enough to be rate limited. If an unusually high RPC count occurs, you should investigate before it overloads the cluster. + +- [`consul.client.rpc`](/consul/docs/agent/monitor/telemetry#network-activity-rpc-count) increments whenever a Consul agent in client mode makes an RPC request to a Consul server. +- [`consul.client.rpc.exceeded`](/consul/docs/agent/monitor/telemetry#network-activity-rpc-count) increments whenever a Consul agent in client mode makes an RPC request to a Consul server gets rate limited by that agent's limits configuration. +- [`consul.client.rpc.failed`](/consul/docs/agent/monitor/telemetry#network-activity-rpc-count) increments whenever a Consul agent in client mode makes an RPC request to a Consul server and fails. + +## Network constraints and alternate approaches + +If it is impossible for you to allocate the required resources, you can make changes to Consul's performance so that it operates with lower speed or resilience. These changes ensure that your cluster remains within its resource capacity. + +- Soft limits prevent your cluster from degrading due to overload. +- Raft tuning lets you compensate for unfavorable environments. + +### Soft limits + +The recommended maximum size for a single datacenter is 5,000 Consul client agents. This recommendation is based on a standard, non-tuned environment and considers a blast radius's risk management factor. The maximum number of agents may be lower, depending on how you use Consul. + +If you require more than 5,000 client agents, you should break up the single Consul datacenter into multiple smaller datacenters. + +- When the nodes are spread across separate physical locations such as different regions, you can model multiple datacenter structures based on physical locations. +- Use [network segments](/consul/docs/enterprise/network-segments/network-segments-overview) in a single available zone or region to lower overall resource usage in a single datacenter. + +When deploying [Consul in Kubernetes](/consul/docs/k8s), we recommend you set both _requests_ and _limits_ in the Helm chart. Refer to the [Helm chart documentation](/consul/docs/k8s/helm#v-server-resources) for more information. + +- Requests allocate the required resources for your Consul workloads. +- Limits prevent your pods from being terminated and restarted if they consume more resources than requested and Kubernetes needs to reclaim these resources. Limits can prevent outage situations where the Consul leader's container gets terminated and redeployed due to resource constraints. + +The following is an example Helm configuration that allocates 16 CPU cores and 64 gigabytes of memory: + + + +```yaml +global: + image: "hashicorp/consul" +## ... +resources: + requests: + memory: '64G' + cpu: '16000m' + limits: + memory: '64G' + cpu: '16000m' +``` + + + +### Raft tuning + +Consul uses the [Raft consensus algorithm](/consul/docs/architecture/consensus) to provide consistency. +You may need to adjust Raft to suit your specific environment. Adjust the [`raft_multiplier` configuration](/consul/docs/agent/config/config-files#raft_multiplier) to define the trade-off between leader stability and time to recover from a leader failure. + +- A lower multiplier minimizes failure detection and election time, but it may trigger frequently in high latency situations. +- A higher multiplier reduces the chances that failures cause leadership churn, but your cluster takes longer to detect real failures and restore availability. + +The value of `raft_multiplier` has a default value of 5. It is a scaling factor setting that directly affects the following parameters: + +| Parameter name | Default value | Derived from | +| --- | --- | --- | +| HeartbeatTimeout | 5000ms | 5 x 1000ms | +| ElectionTimeout | 5000ms | 5 x 1000ms | +| LeaderLeaseTimeout | 2500ms | 5 x 500ms | + +You can use the telemetry from [`consul.raft.leader.lastContact`](/consul/docs/agent/telemetry#leadership-changes) to observe Raft timing performance. + +Wide networks with more latency perform better with larger values of `raft_multiplier`, but cluster failure detection will take longer. If your network operates with low latency, we recommend that you do not set the Raft multiplier higher than 5. Instead, you should either replace the servers with more powerful ones or minimize the network latency between nodes. + +We recommend you start from a baseline and perform [chaos engineering testing](/consul/tutorials/resiliency/introduction-chaos-engineering?in=consul%2Fresiliency) with different values for the Raft multiplier to find the acceptable time for problem detection and recovery for the cluster. Then scale the cluster and its dedicated resources with the number of workloads handled. This approach gives you the best balance between pure resource growth and pure Raft tuning strategies because it lets you use Raft tuning as a backup plan if you cannot scale your resources. + +The types of workloads the Consul cluster handles also play an important role in Raft tuning. For example, if your Consul clusters are mostly static and do not handle many events, you should increase your Raft multiplier instead of scaling your resources because the risk of an important event happening while the cluster is converging or re-electing a leader is lower. diff --git a/website/content/docs/architecture/catalog.mdx b/website/content/docs/architecture/catalog.mdx new file mode 100644 index 000000000000..dad1ef9aceb7 --- /dev/null +++ b/website/content/docs/architecture/catalog.mdx @@ -0,0 +1,39 @@ +--- +layout: docs +page_title: v1 Catalog API +description: Learn about version 1 of the Consul catalog, including what Consul servers record when they register a service. +--- + +# v1 Catalog API + +This topic provides conceptual information about version 1 (v1) of the Consul catalog API. The catalog tracks registered services and their locations for both service discovery and service mesh use cases. + +For more information about the information returned when querying the catalog, including filtering options when querying the catalog for a list of nodes, services, or gateways, refer to the [`/catalog` endpoint reference in the HTTP API documentation](/consul/api-docs/catalog). + +## Introduction + +Consul tracks information about registered services through its catalog API. This API records user-defined information about the external services, such as their partitions and required health checks. It also records information that Consul assigns for its own operations, such as an ID for each service instance and the [Raft indices](/consul/docs/architecture/consensus) when the instance is registered and modified. + +### v2 Catalog + +Consul introduced an experimental v2 Catalog API in v1.17.0. This API supported multi-port Service configurations on Kubernetes, and it was made available for testing and development purposes. The v2 catalog and its support for multiport Kubernetes Services were deprecated in the v1.19.0 release. + +## Catalog structure + +When Consul registers a service instance using the v1 catalog API, it records the following information about each instance: + +| v1 Catalog field | Description | Source | +| :--------------- | :---------- | :----- | +| ID | A unique identifier for a service instance. | Defined by user in [service definition](/consul/docs/services/configuration/services-configuration-reference#id). | +| Node | The connection point where the service is available. | On VMs, defined by user.

      On Kubernetes, computed by Consul according to [Kubernetes Nodes](https://kubernetes.io/docs/concepts/architecture/nodes/). | +| Address | The registered address of the service instance. | Defined by user in [service definition](/consul/docs/services/configuration/services-configuration-reference#address). | +| Tagged Addresses | User-defined labels for addresses. | Defined by user in [service definition](/consul/docs/services/configuration/services-configuration-reference#tagged_addresses). | +| NodeMeta | User-defined metadata about the node. | Defined by user | +| Datacenter | The name of the datacenter the service is registered in. | Defined by user | +| Service | The name of the service Consul registers the service instance under. | Defined by user | +| Agent Check | The health checks defined for a service instance managed by a Consul client agent. | Computed by Consul | +| Health Checks | The health checks defined for the service. Refer to [define health checks](/consul/docs/services/usage/checks) for more information. | Defined by user | +| Partition | The name of the admin partition the service is registered in. Refer to [admin partitions](/consul/docs/enterprise/admin-partitions) for more information. | Defined by user | +| Locality | Region and availability zone of the service. Refer to [`locality`](/consul/docs/agent/config/config-files#locality) for more information. | Defined by user | + +Depending on the configuration entries or custom resource definitions you apply to your Consul installation, additional information such as [proxy default behavior](/consul/docs/connect/config-entries/proxy-defaults) is automatically recorded to the catalog for services. You can return this information using the [`/catalog` HTTP API endpoint](/consul/api-docs/catalog). diff --git a/website/content/docs/architecture/coordinates.mdx b/website/content/docs/architecture/coordinates.mdx index ad8f7722e2ae..7bc37cc9c029 100644 --- a/website/content/docs/architecture/coordinates.mdx +++ b/website/content/docs/architecture/coordinates.mdx @@ -14,10 +14,10 @@ very simple calculation. This allows for many useful applications, such as findi the service node nearest a requesting node, or failing over to services in the next closest datacenter. -All of this is provided through the use of the [Serf library](https://www.serf.io/). +All of this is provided through the use of the [Serf library](https://github.com/hashicorp/serf/). Serf's network tomography is based on ["Vivaldi: A Decentralized Network Coordinate System"](http://www.cs.ucsb.edu/~ravenben/classes/276/papers/vivaldi-sigcomm04.pdf), with some enhancements based on other research. There are more details about -[Serf's network coordinates here](https://www.serf.io/docs/internals/coordinates.html). +[Serf's network coordinates here](https://github.com/hashicorp/serf/blob/master/docs/internals/coordinates.html.markdown). ## Network Coordinates in Consul diff --git a/website/content/docs/architecture/gossip.mdx b/website/content/docs/architecture/gossip.mdx index 09f85b19bd5c..12a4ef8de7ac 100644 --- a/website/content/docs/architecture/gossip.mdx +++ b/website/content/docs/architecture/gossip.mdx @@ -9,15 +9,15 @@ description: >- Consul uses a [gossip protocol](https://en.wikipedia.org/wiki/Gossip_protocol) to manage membership and broadcast messages to the cluster. The protocol, membership management, and message broadcasting is provided -through the [Serf library](https://www.serf.io/). The gossip protocol +through the [Serf library](https://github.com/hashicorp/serf/). The gossip protocol used by Serf is based on a modified version of the [SWIM (Scalable Weakly-consistent Infection-style Process Group Membership)](https://www.cs.cornell.edu/projects/Quicksilver/public_pdfs/SWIM.pdf) protocol. -Refer to the [Serf documentation](https://www.serf.io/docs/internals/gossip.html) for additional information about the gossip protocol. +Refer to the [Serf documentation](https://github.com/hashicorp/serf/blob/master/docs/internals/gossip.html.markdown) for additional information about the gossip protocol. ## Gossip in Consul Consul uses a LAN gossip pool and a WAN gossip pool to perform different functions. The pools -are able to perform their functions by leveraging an embedded [Serf](https://www.serf.io/) +are able to perform their functions by leveraging an embedded [Serf](https://github.com/hashicorp/serf/) library. The library is abstracted and masked by Consul to simplify the user experience, but developers may find it useful to understand how the library is leveraged. @@ -52,5 +52,5 @@ For more details about Lifeguard, please see the [Making Gossip More Robust with Lifeguard](https://www.hashicorp.com/blog/making-gossip-more-robust-with-lifeguard/) blog post, which provides a high level overview of the HashiCorp Research paper [Lifeguard : SWIM-ing with Situational Awareness](https://arxiv.org/abs/1707.00788). The -[Serf gossip protocol guide](https://www.serf.io/docs/internals/gossip.html#lifeguard) +[Serf gossip protocol guide](https://github.com/hashicorp/serf/blob/master/docs/internals/gossip.html.markdown#lifeguard-enhancements) also provides some lower-level details about the gossip protocol and Lifeguard. diff --git a/website/content/docs/architecture/improving-consul-resilience.mdx b/website/content/docs/architecture/improving-consul-resilience.mdx index bfcc9a8be478..aea40f3558e9 100644 --- a/website/content/docs/architecture/improving-consul-resilience.mdx +++ b/website/content/docs/architecture/improving-consul-resilience.mdx @@ -5,21 +5,19 @@ description: >- Fault tolerance is a system's ability to operate without interruption despite component failure. Learn how a set of Consul servers provide fault tolerance through use of a quorum, and how to further improve control plane resilience through use of infrastructure zones and Enterprise redundancy zones. --- -# Fault Tolerance +# Fault tolerance -Fault tolerance is the ability of a system to continue operating without interruption -despite the failure of one or more components. -The most basic production deployment of Consul has 3 server agents and can lose a single -server without interruption. -As you continue to use Consul, your circumstances may change. -Perhaps a datacenter becomes more business critical or risk management policies change, -necessitating an increase in fault tolerance. -The sections below discuss options for how to improve Consul's fault tolerance. +You must give careful consideration to reliability in the architecture frameworks that you build. When you build a resilient platform, it minimizes the remediation actions you need to take when a failure occurs. This document provides useful information on how to design and operate a resilient Consul cluster, including the methods and functionalities for this goal. + +Consul has many features that operate both locally and remotely that can help you offer a resilient service across multiple datacenters. -## Fault Tolerance in Consul -Consul's fault tolerance is determined by the configuration of its voting server agents. +## Introduction + +Fault tolerance is the ability of a system to continue operating without interruption +despite the failure of one or more components. In Consul, the number of server agents determines the fault tolerance. + Each Consul datacenter depends on a set of Consul voting server agents. The voting servers ensure Consul has a consistent, fault-tolerant state @@ -42,28 +40,25 @@ number of servers, quorum, and fault tolerance, refer to the [consensus protocol documentation](/consul/docs/architecture/consensus#deployment_table). Effectively mitigating your risk is more nuanced than just increasing the fault tolerance -metric described above. You must consider: - -### Correlated Risks +because the infrastructure costs can outweigh the improved resiliency. You must also consider correlated risks at the infrastructure-level. There are occasions when multiple servers fail at the same time. That means that a single failure could cause a Consul outage, even if your server-level fault tolerance is 2. -Are you protected against correlated risks? Infrastructure-level failures can cause multiple servers to fail at the same time. This means that a single infrastructure-level failure could cause a Consul outage, even if your server-level fault tolerance is 2. +Different options for your resilient datacenter present trade-offs between operational complexity, computing cost, and Consul request performance. Consider these factors when designing your resilient architecture. -### Mitigation Costs +## Fault tolerance -What are the costs of the mitigation? Different mitigation options present different trade-offs for operational complexity, computing cost, and Consul request performance. +The following sections explore several options for increasing Consul's fault tolerance. For enhanced reliability, we recommend taking a holistic approach by layering these multiple functionalities together. -## Strategies to Increase Fault Tolerance +- Spread servers across infrastructure [availability zones](#availability-zones). +- Use a [minimum quorum size](#quorum-size) to avoid performance impacts. +- Use [redundancy zones](#redundancy-zones) to improve fault tolerance. +- Use [Autopilot](#autopilot) to automatically prune failed servers and maintain quorum size. +- Use [cluster peering](#cluster-peering) to provide service redundancy. -The following sections explore several options for increasing Consul's fault tolerance. +### Availability zones -HashiCorp recommends all production deployments consider: -- [Spreading Consul servers across availability zones](#spread-servers-across-infrastructure-availability-zones) -- Using backup voting servers to replace lost voters -### Spread Servers Across Infrastructure Availability Zones +The cloud or on-premise infrastructure underlying your [Consul datacenter](/consul/docs/install/glossary#datacenter) can run across multiple availability zones. -The cloud or on-premise infrastructure underlying your [Consul datacenter](/consul/docs/install/glossary#datacenter) -may be split into several "availability zones". An availability zone is meant to share no points of failure with other zones by: - Having power, cooling, and networking systems independent from other zones - Being physically distant enough from other zones so that large-scale disruptions @@ -79,25 +74,25 @@ To distribute your Consul servers across availability zones, modify your infrast Additionally, you should leverage resources that can automatically restore your compute instance, such as autoscaling groups, virtual machine scale sets, or compute engine autoscaler. -The autoscaling resources can be customized to re-deploy servers into specific availability zones -and ensure the desired numbers of servers are available at all time. +Customize autoscaling resources to re-deploy servers into specific availability zones and ensure the desired numbers of servers are available at all times. -### Add More Voting Servers +### Quorum size -For most production use cases, we recommend using either 3 or 5 voting servers, +For most production use cases, we recommend using a minimum quorum of either 3 or 5 voting servers, yielding a server-level fault tolerance of 1 or 2 respectively. Even though it would improve fault tolerance, adding voting servers beyond 5 is **not recommended** because it decreases Consul's performance— it requires Consul to involve more servers in every state change or consistent read. -Consul Enterprise provides a way to improve fault tolerance without this performance penalty: -[using backup voting servers to replace lost voters](#use-backup-voting-servers-to-replace-lost-voters). +Consul Enterprise users can use redundancy zones to improve fault tolerance without this performance penalty. + +### Redundancy zones -### Use Backup Voting Servers to Replace Lost Voters +Use Consul Enterprise [redundancy zones](/consul/docs/enterprise/redundancy) to improve fault tolerance without the performance penalty of increasing the number of voting servers. -Consul Enterprise [redundancy zones](/consul/docs/enterprise/redundancy) -can be used to improve fault tolerance without the performance penalty of increasing the number of voting servers. +![Reference architecture diagram for Consul Redundancy zones](/img/architecture/consul-redundancy-zones-light.png#light-theme-only) +![Reference architecture diagram for Consul Redundancy zones](/img/architecture/consul-redundancy-zones-dark.png#dark-theme-only) Each redundancy zone should be assigned 2 or more Consul servers. If all servers are healthy, only one server per redundancy zone will be an active voter; @@ -132,3 +127,51 @@ For more information on redundancy zones, refer to: for a more detailed explanation - [Redundancy zone tutorial](/consul/tutorials/enterprise/redundancy-zones) to learn how to use them + +### Autopilot + +Autopilot is a set of functions that introduce servers to a cluster, cleans up dead servers, and monitors the state of the Raft protocol in the Consul cluster. + +When you enable Autopilot's dead server cleanup, Autopilot marks failed servers as `Left` and removes them from the Raft peer set to prevent them from interfering with the quorum size. Autopilot does that as soon as a replacement Consul server comes online. This behavior is beneficial when server nodes failed and have been redeployed but Consul considers them as new nodes because their IP address and hostnames have changed. Autopilot keeps the cluster peer set size correct and the quorum requirement simple. + +To illustrate the Autopilot advantage, consider a scenario where Consul has a cluster of five server nodes. The quorum is three, which means the cluster can lose two server nodes before the cluster fails. The following events happen: + +1. Two server nodes fail. +1. Two replacement nodes are deployed with new hostnames and IPs. +1. The two replacement nodes rejoin the Consul cluster. +1. Consul treats the replacement nodes as extra nodes, unrelated to the previously failed nodes. + +_With Autopilot not enabled_, the following happens: + +1. Consul does not immediately clean up the failed nodes when the replacement nodes join the cluster. +1. The cluster now has the three surviving nodes, the two failed nodes, and the two replacement nodes, for a total of seven nodes. + - The quorum is increased to four, which means the cluster can only afford to lose one node until after the two failed nodes are deleted in seventy-two hours. + - The redundancy level has decreased from its initial state. + +_With Autopilot enabled_, the following happens: + +1. Consul immediately cleans up the failed nodes when the replacement nodes join the cluster. +1. The cluster now has the three surviving nodes and the two replacement nodes, for a total of five nodes. + - The quorum stays at three, which means the cluster can afford to lose two nodes before it fails. + - The redundancy level remains the same. + +### Cluster peering + +Linking multiple Consul clusters together to provide service redundancy is the most effective method to prevent disruption from failure. This method is enhanced when you design individual Consul clusters with resilience in mind. Consul clusters interconnect in two ways: WAN federation and cluster peering. We recommend using cluster peering whenever possible. + +Cluster peering lets you connect two or more independent Consul clusters using mesh gateways, so that services can communicate between non-identical partitions in different datacenters. + +![Reference architecture diagram for Consul cluster peering](/img/architecture/cluster-peering-diagram-light.png#light-theme-only) +![Reference architecture diagram for Consul cluster peering](/img/architecture/cluster-peering-diagram-dark.png#dark-theme-only) + +Cluster peering is the preferred way to interconnect clusters because it is operationally easier to configure and manage than WAN federation. Cluster peering communication between two datacenters runs only on one port on the related Consul mesh gateway, which makes it operationally easy to expose for routing purposes. + +When you use cluster peering to connect admin partitions between datacenters, use Consul’s dynamic traffic management functionalities `service-splitter`, `service-router` and `service-failover` to configure your service mesh to automatically forward or failover service traffic between peer clusters. Consul can then manage the traffic intended for the service and do [failover](/consul/docs/connect/config-entries/service-resolver#spec-failover), [load-balancing](/consul/docs/connect/config-entries/service-resolver#spec-loadbalancer), or [redirection](/consul/docs/connect/config-entries/service-resolver#spec-redirect). + +Cluster peering also extends service discovery across different datacenters independent of service mesh functions. After you peer datacenters, you can refer to services between datacenters with `.virtual.peer.consul` in Consul DNS. For Consul Enterprise, your query string may need to include the namespace, partition, or both. Refer to the [Consul DNS documentation](/consul/docs/services/discovery/dns-static-lookups#service-virtual-ip-lookups) for details on building virtual service lookups. + +For more information on cluster peering, refer to: +- [Cluster peering documentation](/consul/docs/connect/cluster-peering) + for a more detailed explanation +- [Cluster peering tutorial](/consul/tutorials/implement-multi-tenancy/cluster-peering) + to learn how to implement cluster peering diff --git a/website/content/docs/architecture/index.mdx b/website/content/docs/architecture/index.mdx index a4656a7718b6..dc3f7954bdd0 100644 --- a/website/content/docs/architecture/index.mdx +++ b/website/content/docs/architecture/index.mdx @@ -25,7 +25,7 @@ The Consul control plane contains one or more _datacenters_. A datacenter is the ### Clusters -A collection of Consul agents that are aware of each other is called a _cluster_. The terms _datacenter_ and _cluster_ are often used interchangeably. In some cases, however, _cluster_ refers only to Consul server agents, such as in [HCP Consul](https://cloud.hashicorp.com/products/consul). In other contexts, such as the [_admin partitions_](/consul/docs/enterprise/admin-partitions) feature included with Consul Enterprise, a cluster may refer to collection of client agents. +A collection of Consul agents that are aware of each other is called a _cluster_. The terms _datacenter_ and _cluster_ are often used interchangeably. In some cases, however, _cluster_ refers only to Consul server agents, such as in [HCP Consul Dedicated](https://cloud.hashicorp.com/products/consul). In other contexts, such as the [_admin partitions_](/consul/docs/enterprise/admin-partitions) feature included with Consul Enterprise, a cluster may refer to collection of client agents. ## Agents diff --git a/website/content/docs/architecture/scale.mdx b/website/content/docs/architecture/scale.mdx index ba03f23c666d..119e05454abf 100644 --- a/website/content/docs/architecture/scale.mdx +++ b/website/content/docs/architecture/scale.mdx @@ -77,7 +77,7 @@ Consul server agents are an important part of Consul’s architecture. This sect Consul servers can be deployed on a few different runtimes: -- **HashiCorp Cloud Platform (HCP) Consul (Managed)**. These Consul servers are deployed in a hosted environment managed by HCP. To get started with HCP Consul servers in Kubernetes or VM deployments, refer to the [Deploy HCP Consul tutorial](/consul/tutorials/get-started-hcp/hcp-gs-deploy). +- **HashiCorp Cloud Platform (HCP) Consul Dedicated**. These Consul servers are deployed in a hosted environment managed by HCP. To get started with HCP Consul Dedicated servers in Kubernetes or VM deployments, refer to the [Deploy HCP Consul Dedicated tutorial](/consul/tutorials/get-started-hcp/hcp-gs-deploy). - **VMs or bare metal servers (Self-managed)**. To get started with Consul on VMs or bare metal servers, refer to the [Deploy Consul server tutorial](/consul/tutorials/get-started-vms/virtual-machine-gs-deploy). For a full list of configuration options, refer to [Agents Overview](/consul/docs/agent). - **Kubernetes (Self-managed)**. To get started with Consul on Kubernetes, refer to the [Deploy Consul on Kubernetes tutorial](/consul/tutorials/get-started-kubernetes/kubernetes-gs-deploy). - **Other container environments, including Docker, Rancher, and Mesos (Self-managed)**. @@ -126,7 +126,7 @@ We strongly recommend using [stale consistency mode for DNS lookups](/consul/api We also recommend that you do not configure [`dns_config.max_stale` to limit the staleness of DNS responses](/consul/api-docs/features/consistency#limiting-staleness-advanced-usage), as it may result in a prolonged outage if your Consul servers become overloaded. If bounded result consistency is required by a service, consider modifying the service to use consistent service discovery HTTP API queries instead of DNS lookups. -Avoid using [`dns_config.use_cache`](/consul/docs/agent/config/config-files#dns_use_cache) when operating Consul at scale. Because the Consul agent cache allocates memory for each requested route and each allocation can live up to 3 days, severe memory issues may occur. To implement DNS caching, we instead recommend that you [configure TTLs for services and nodes](/consul/tutorials/networking/dns-caching#ttl) to enable the DNS client to cache responses from Consul. +Avoid using [`dns_config.use_cache`](/consul/docs/agent/config/config-files#dns_use_cache) when operating Consul at scale. Because the Consul agent cache allocates memory for each requested route and each allocation can live up to 3 days, severe memory issues may occur. To implement DNS caching, we instead recommend that you [configure TTLs for services and nodes](/consul/docs/services/discovery/dns-cache#ttl) to enable the DNS client to cache responses from Consul. #### HTTP API diff --git a/website/content/docs/concepts/service-discovery.mdx b/website/content/docs/concepts/service-discovery.mdx index 4313ba3e1553..44c83b74147d 100644 --- a/website/content/docs/concepts/service-discovery.mdx +++ b/website/content/docs/concepts/service-discovery.mdx @@ -82,7 +82,7 @@ Consul's service discovery capabilities help you discover, track, and monitor th You can use Consul with virtual machines (VMs), containers, serverless technologies, or with container orchestration platforms, such as [Nomad](https://www.nomadproject.io/) and Kubernetes. Consul is platform agnostic which makes it a great fit for all environments, including legacy platforms. -Consul is available as a [self-managed](/consul/downloads) project or as a fully managed service mesh solution ([HCP Consul](https://portal.cloud.hashicorp.com/sign-in?utm_source=consul_docs)). HCP Consul enables users to discover and securely connect services without the added operational burden of maintaining a service mesh on their own. +Consul is available as a [self-managed](/consul/downloads) project or as a fully managed service mesh solution ([HCP Consul Dedicated](https://portal.cloud.hashicorp.com/sign-in?utm_source=consul_docs)). HCP Consul Dedicated enables users to discover and securely connect services without the added operational burden of maintaining a service mesh on their own. ## Next steps diff --git a/website/content/docs/concepts/service-mesh.mdx b/website/content/docs/concepts/service-mesh.mdx index 947984484e45..33ebf1478d83 100644 --- a/website/content/docs/concepts/service-mesh.mdx +++ b/website/content/docs/concepts/service-mesh.mdx @@ -107,12 +107,12 @@ In simple terms, Consul is the control plane of the service mesh. The data plane You can use Consul with virtual machines (VMs), containers, or with container orchestration platforms, such as [Nomad](https://www.nomadproject.io/) and Kubernetes. Consul is platform agnostic which makes it a great fit for all environments, including legacy platforms. -Consul is available as a [self-install](/consul/downloads) project or as a fully managed service mesh solution called [HCP Consul](https://portal.cloud.hashicorp.com/sign-in?utm_source=consul_docs). -HCP Consul enables users to discover and securely connect services without the added operational burden of maintaining a service mesh on their own. +Consul is available as a [self-install](/consul/downloads) project or as a fully managed service mesh solution called [HCP Consul Dedicated](https://portal.cloud.hashicorp.com/sign-in?utm_source=consul_docs). +HCP Consul Dedicated enables users to discover and securely connect services without the added operational burden of maintaining a service mesh on their own. You can learn more about Consul by visiting the Consul [tutorials](/consul/tutorials). ## Next -Get started today with a service mesh by leveraging [HCP Consul](https://portal.cloud.hashicorp.com/sign-in?utm_source=consul_docs). +Get started today with a service mesh by leveraging [HCP Consul Dedicated](https://portal.cloud.hashicorp.com/sign-in?utm_source=consul_docs). Prepare your organization for the future of multi-cloud and embrace a [zero-trust](https://www.hashicorp.com/solutions/zero-trust-security) architecture. diff --git a/website/content/docs/connect/cluster-peering/index.mdx b/website/content/docs/connect/cluster-peering/index.mdx index 864dadd41863..2aa5147235f3 100644 --- a/website/content/docs/connect/cluster-peering/index.mdx +++ b/website/content/docs/connect/cluster-peering/index.mdx @@ -45,7 +45,6 @@ Regardless of whether you connect your clusters through WAN federation or cluste | Replicates exported services for service discovery | ❌ | ✅ | | Gossip protocol: Requires LAN gossip only | ❌ | ✅ | | Forwards service requests for service discovery | ✅ | ❌ | -| Shares key/value stores | ✅ | ❌ | | Can replicate ACL tokens, policies, and roles | ✅ | ❌ | ## Guidance @@ -71,11 +70,11 @@ The following resources are available to help you use Consul's cluster peering f - [Manage L7 traffic with cluster peering on Kubernetes](/consul/docs/k8s/connect/cluster-peering/usage/l7-traffic) - [Create sameness groups on Kubernetes](/consul/docs/k8s/connect/cluster-peering/usage/create-sameness-groups) -### HCP Consul documentation +### HCP Consul Central documentation - [Cluster peering](/hcp/docs/consul/usage/cluster-peering) - [Cluster peering topologies](/hcp/docs/consul/usage/cluster-peering/topologies) -- [Establish cluster peering connections on HCP Consul](/hcp/docs/consul/usage/cluster-peering/create-connections) +- [Establish cluster peering connections on HCP Consul Central](/hcp/docs/consul/usage/cluster-peering/create-connections) - [Cluster peering with HCP Consul Central](/hcp/docs/extend/cluster-peering/establish) ### Reference documentation diff --git a/website/content/docs/connect/cluster-peering/usage/establish-cluster-peering.mdx b/website/content/docs/connect/cluster-peering/usage/establish-cluster-peering.mdx index 96e7815d75d9..4e0128bb3e68 100644 --- a/website/content/docs/connect/cluster-peering/usage/establish-cluster-peering.mdx +++ b/website/content/docs/connect/cluster-peering/usage/establish-cluster-peering.mdx @@ -16,7 +16,7 @@ This page details the process for establishing a cluster peering connection betw Cluster peering between services cannot be established until all four steps are complete. If you want to establish cluster peering connections and create sameness groups at the same time, refer to the guidance in [create sameness groups](/consul/docs/connect/cluster-peering/usage/create-sameness-groups). -For Kubernetes guidance, refer to [Establish cluster peering connections on Kubernetes](/consul/docs/k8s/connect/cluster-peering/usage/establish-peering). For HCP Consul guidance, refer to [Establish cluster peering connections on HCP Consul](/hcp/docs/consul/usage/cluster-peering/create-connections). +For Kubernetes guidance, refer to [Establish cluster peering connections on Kubernetes](/consul/docs/k8s/connect/cluster-peering/usage/establish-peering). For HCP Consul Central guidance, refer to [Establish cluster peering connections on HCP Consul Central](/hcp/docs/consul/usage/cluster-peering/create-connections). ## Requirements @@ -264,6 +264,6 @@ Read access to all imported services is granted using either of the following ru For Consul Enterprise, the permissions apply to all imported services in the service's partition. These permissions are satisfied when using a [service identity](/consul/docs/security/acl/acl-roles#service-identities). -Refer to [Reading servers](/consul/docs/connect/config-entries/exported-services#reading-services) in the `exported-services` configuration entry documentation for example rules. +Refer to [Reading services](/consul/docs/connect/config-entries/exported-services#reading-services) in the `exported-services` configuration entry documentation for example rules. -For additional information about how to configure and use ACLs, refer to [ACLs system overview](/consul/docs/security/acl). \ No newline at end of file +For additional information about how to configure and use ACLs, refer to [ACLs system overview](/consul/docs/security/acl). diff --git a/website/content/docs/connect/config-entries/api-gateway.mdx b/website/content/docs/connect/config-entries/api-gateway.mdx index 5f5b40902639..dc5d6f63e2a5 100644 --- a/website/content/docs/connect/config-entries/api-gateway.mdx +++ b/website/content/docs/connect/config-entries/api-gateway.mdx @@ -1,10 +1,10 @@ --- layout: docs -page_title: API Gateway Configuration Entry Reference +page_title: API Gateway configuration reference description: Learn how to configure a Consul API gateway on VMs. --- -# API gateway configuration entry reference +# API gateway configuration reference This topic provides reference information for the API gateway configuration entry that you can deploy to networks in virtual machine (VM) environments. For reference information about configuring Consul API gateways on Kubernetes, refer to [Gateway Resource Configuration](/consul/docs/connect/gateways/api-gateway/configuration/gateway). @@ -31,19 +31,19 @@ The following list outlines field hierarchy, language-specific data types, and r - [`MaxVersion`](#listeners-tls-maxversion): string | no default - [`CipherSuites`](#listeners-tls-ciphersuites): list of strings | Envoy default cipher suites - [`Certificates`](#listeners-tls-certificates): list of objects | no default - - [`Kind`](#listeners-tls-certificates-kind): string | must be `"inline-certificate"` + - [`Kind`](#listeners-tls-certificates-kind): string | no default - [`Name`](#listeners-tls-certificates-name): string | no default - [`Namespace`](#listeners-tls-certificates-namespace): string | no default - [`Partition`](#listeners-tls-certificates-partition): string | no default - [`default`](#listeners-default): map - - [`JWT`](#listeners-default-jwt): map + - [`JWT`](#listeners-default-jwt): map - [`Providers`](#listeners-default-jwt-providers): list - [`Name`](#listeners-default-jwt-providers): string - [`VerifyClaims`](#listeners-default-jwt-providers): map - [`Path`](#listeners-default-jwt-providers): list - [`Value`](#listeners-default-jwt-providers): string - [`override`](#listeners-override): map - - [`JWT`](#listeners-override-jwt): map + - [`JWT`](#listeners-override-jwt): map - [`Providers`](#listeners-override-jwt-providers): list - [`Name`](#listeners-override-jwt-providers): string - [`VerifyClaims`](#listeners-override-jwt-providers): map @@ -81,8 +81,8 @@ Listeners = [ ] Certificates = [ { - Kind = "inline-certificate" - Name = "" + Kind = "file-system-certificate" + Name = "" Namespace = "" Partition = "" } @@ -97,7 +97,7 @@ Listeners = [ Value = "" } ] - } + } } override = { JWT = { @@ -108,7 +108,7 @@ Listeners = [ Value = "" } ] - } + } } } ] @@ -136,8 +136,8 @@ Listeners = [ ], "Certificates": [ { - "Kind": "inline-certificate", - "Name": "", + "Kind": "file-system-certificate", + "Name": "", "Namespace": "", "Partition": "" } @@ -349,7 +349,7 @@ Specifies a list of cipher suites that the listener supports when negotiating co ### `Listeners[].TLS.Certificates[]` -The list of references to inline certificates that the listener uses for TLS termination. +The list of references to [file system](/consul/docs/connect/config-entries/file-system-certificate) or [inline certificates](/consul/docs/connect/config-entries/inline-certificate) that the listener uses for TLS termination. You should create the configuration entry for the certificate separately and then reference the configuration entry in the `Name` field. #### Values @@ -362,17 +362,17 @@ The list of references to inline certificates that the listener uses for TLS ter ### `Listeners[].TLS.Certificates[].Kind` -The list of references to inline-certificates that the listener uses for TLS termination. +The list of references to certificates that the listener uses for TLS termination. #### Values - Default: None -- This field is required and must be set to `"inline-certificate"`. -- Data type: string +- This field is required. +- The data type is one of the following string values: `"file-system-certificate"` or `"inline-certificate"`. ### `Listeners[].TLS.Certificates[].Name` -The list of references to inline certificates that the listener uses for TLS termination. +Specifies the name of the [file system certificate](/consul/docs/connect/config-entries/file-system-certificate) or [inline certificate](/consul/docs/connect/config-entries/inline-certificate) that the listener uses for TLS termination. #### Values @@ -400,7 +400,7 @@ Specifies the Enterprise [admin partition](/consul/docs/enterprise/admin-partiti ### `Listeners[].default` -Specifies a block of default configurations to apply to the gateway listener. All routes attached to the listener inherit the default configurations. You can specify override configurations that have precedence over default configurations in the [`override` block](#listeners-override) as well as in the `JWT` block in the [HTTP route configuration entry](/consul/docs/connect/config-entries/http-route). +Specifies a block of default configurations to apply to the gateway listener. All routes attached to the listener inherit the default configurations. You can specify override configurations that have precedence over default configurations in the [`override` block](#listeners-override) as well as in the `JWT` block in the [HTTP route configuration entry](/consul/docs/connect/config-entries/http-route). #### Values @@ -409,7 +409,7 @@ Specifies a block of default configurations to apply to the gateway listener. Al ### `Listeners[].default{}.JWT` -Specifies a block of default JWT verification configurations to apply to the gateway listener. Specify configurations that have precedence over the defaults in either the [`override.JWT` block](#listeners-override) or in the [`JWT` block](/consul/docs/connect/config-entries/http-route#rules-filters-jwt) in the HTTP route configuration. Refer to [Use JWTs to verify requests to API gateways](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms) for order of precedence and other details about using JWT verification in API gateways. +Specifies a block of default JWT verification configurations to apply to the gateway listener. Specify configurations that have precedence over the defaults in either the [`override.JWT` block](#listeners-override) or in the [`JWT` block](/consul/docs/connect/config-entries/http-route#rules-filters-jwt) in the HTTP route configuration. Refer to [Use JWTs to verify requests to API gateways](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms) for order of precedence and other details about using JWT verification in API gateways. #### Values @@ -418,7 +418,7 @@ Specifies a block of default JWT verification configurations to apply to the gat ### `Listeners[].default{}.JWT{}.Providers` -Specifies a list of default JWT provider configurations to apply to the gateway listener. A provider configuration contains the name of the provider and claims. Specify configurations that have precedence over the defaults in either the [`override.JWT.Providers` block](#listeners-override-providers) or in the [`JWT` block](/consul/docs/connect/config-entries/http-route#rules-filters-jwt-providers) of the HTTP route configuration. Refer to [Use JWTs to verify requests to API gateways](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms) for order of precedence and other details about using JWT verification in API gateways. +Specifies a list of default JWT provider configurations to apply to the gateway listener. A provider configuration contains the name of the provider and claims. Specify configurations that have precedence over the defaults in either the [`override.JWT.Providers` block](#listeners-override-providers) or in the [`JWT` block](/consul/docs/connect/config-entries/http-route#rules-filters-jwt-providers) of the HTTP route configuration. Refer to [Use JWTs to verify requests to API gateways](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms) for order of precedence and other details about using JWT verification in API gateways. #### Values @@ -432,7 +432,7 @@ The following table describes the parameters you can specify in a member of the | `Name` | Specifies the name of the provider. | String | None | | `VerifyClaims` | Specifies a list of paths and a value that define the claim that Consul verifies when it receives a request. The `VerifyClaims` map specifies the following settings:
      • `Path`: Specifies a list of one or more registered or custom claims.
      • `Value`: Specifies the expected value of the claim.
      | Map | None | -Refer to [Configure JWT verification settings](#configure-jwt-verification-settings) for an example configuration. +Refer to [Configure JWT verification settings](#configure-jwt-verification-settings) for an example configuration. ### `Listeners[].override` @@ -454,7 +454,7 @@ Specifies a block of JWT verification configurations to apply to the gateway lis ### `Listeners[].override{}.JWT{}.Providers` -Specifies a list of JWT provider configurations to apply to the gateway listener. A provider configuration contains the name of the provider and claims. The override settings have precedence over `Listeners[].defaults{}.JWT{}.Providers` as well as any listener-specific configuration. +Specifies a list of JWT provider configurations to apply to the gateway listener. A provider configuration contains the name of the provider and claims. The override settings have precedence over `Listeners[].defaults{}.JWT{}.Providers` as well as any listener-specific configuration. #### Values @@ -468,7 +468,7 @@ The following table describes the parameters you can specify in a member of the | `Name` | Specifies the name of the provider. | String | None | | `VerifyClaims` | Specifies a list of paths and a value that define the claim that Consul verifies when it receives a request. The `VerifyClaims` map specifies the following settings:
      • `Path`: Specifies a list of one or more registered or custom claims.
      • `Value`: Specifies the expected value of the claim.
      | Map | None | -Refer to [Configure JWT verification settings](#configure-jwt-verification-settings) for an example configuration. +Refer to [Configure JWT verification settings](#configure-jwt-verification-settings) for an example configuration. ## Examples @@ -530,7 +530,7 @@ Listeners = [ { "name": "listener-one", "port": 9001, - "protocol": "http", + "protocol": "http", "override": { "JWT": { "Providers": [{ @@ -559,4 +559,4 @@ Listeners = [ ``` - \ No newline at end of file + diff --git a/website/content/docs/connect/config-entries/control-plane-request-limit.mdx b/website/content/docs/connect/config-entries/control-plane-request-limit.mdx index d6e828e67028..53404c0d3f6a 100644 --- a/website/content/docs/connect/config-entries/control-plane-request-limit.mdx +++ b/website/content/docs/connect/config-entries/control-plane-request-limit.mdx @@ -1,10 +1,10 @@ --- layout: docs -page_title: Control Plane Request Limit Configuration Entry Configuration Reference +page_title: Control Plane Request Limit configuration reference description: Learn how to configure the control-plane-request-limit configuration entry, which defines how Consul agents limit read and request traffic rate limits. --- -# Control Plane Request Limit Configuration Entry Configuration Reference +# Control Plane Request Limit configuration reference This topic describes the configuration options for the `control-plane-request-limit` configuration entry. You can only write the `control-plane-request-limit` configuration entry to the `default` partition, but the configuration entry applies to all client requests that target any partition. diff --git a/website/content/docs/connect/config-entries/exported-services.mdx b/website/content/docs/connect/config-entries/exported-services.mdx index 7a268aeb77e8..ba783b48375d 100644 --- a/website/content/docs/connect/config-entries/exported-services.mdx +++ b/website/content/docs/connect/config-entries/exported-services.mdx @@ -1,11 +1,11 @@ --- layout: docs -page_title: Exported Services - Configuration Entry Reference +page_title: Exported Services configuration reference description: >- An exported services configuration entry defines the availability of a cluster's services to cluster peers and local admin partitions. Learn about `""exported-services""` config entry parameters and exporting services to other datacenters. --- -# Exported Services Configuration Entry +# Exported Services configuration reference This topic describes the `exported-services` configuration entry type. The `exported-services` configuration entry enables Consul to export service instances to other clusters from a single file and connect services across clusters. For additional information, refer to [Cluster Peering](/consul/docs/connect/cluster-peering) and [Admin Partitions](/consul/docs/enterprise/admin-partitions). diff --git a/website/content/docs/connect/config-entries/file-system-certificate.mdx b/website/content/docs/connect/config-entries/file-system-certificate.mdx new file mode 100644 index 000000000000..d633139a7760 --- /dev/null +++ b/website/content/docs/connect/config-entries/file-system-certificate.mdx @@ -0,0 +1,170 @@ +--- +layout: docs +page_title: File system certificate configuration reference +description: Learn how to configure a file system certificate bound to an API Gateway on VMs. +--- + +# File system certificate configuration reference + +This topic provides reference information for the file system certificate +configuration entry. The file system certificate is a more secure alternative to the [inline certificate configuration entry](/consul/docs/connect/config-entries/inline-certificate) when using Consul API Gateway on VMs because it references a local filepath instead of including sensitive information in the configuration entry itself. File system certificates also include a file system watch that implements certificate and key changes without restarting the gateway. + +Consul on Kubernetes deployments that use `consul-k8s` Helm chart v1.5.0 or later use file system certificates without additional configuration. To learn about configuring certificates for Kubernetes environments, refer to [Gateway Resource Configuration](/consul/docs/connect/gateways/api-gateway/configuration/gateway). + +## Configuration model + +The following list outlines field hierarchy, language-specific data types, and +requirements in a `file-system-certificate` configuration entry. Click on a property name +to view additional details, including default values. + +- [`Kind`](#kind): string | must be set to `"file-system-certificate"` +- [`Name`](#name): string | no default +- [`Namespace`](#namespace): string | no default +- [`Partition`](#partition): string | no default +- [`Meta`](#meta): map | no default +- [`Certificate`](#certificate): string | no default +- [`PrivateKey`](#privatekey): string | no default + +## Complete configuration + +When every field is defined, a `file-system-certificate` configuration entry has the following form: + + + + + +```hcl +Kind = "file-system-certificate" +Name = "" +Namespace = "ns" +Partition = "default" +Meta = { + "" = "" +} + +Certificate = "" +PrivateKey = "" +``` + + + + + +```json +{ + "Kind": "file-system-certificate", + "Name": "", + "Namespace": "ns", + "Partition": "default", + "Meta": { + "key": "value" + }, + "Certificate": "", + "PrivateKey": "" +} +``` + + + + +## Specification + +### `Kind` + +Specifies the type of configuration entry to implement. + +#### Values + +- Default: None +- This field is required. +- Data type: string that must equal `"file-system-certificate"` + +### `Name` + +Specifies a name for the configuration entry. The name is metadata that you can +use to reference the configuration entry when performing Consul operations, such +as applying a configuration entry to a specific cluster. + +#### Values + +- Default: None +- This field is required. +- Data type: string + +### `Namespace` + +Specifies the Enterprise [namespace](/consul/docs/enterprise/namespaces) to apply to the configuration entry. + +#### Values + +- Default: `"default"` in Enterprise +- Data type: string + +### `Partition` + +Specifies the Enterprise [admin partition](/consul/docs/enterprise/admin-partitions) to apply to the configuration entry. + +#### Values + +- Default: `"default"` in Enterprise +- Data type: string + +### `Meta` + +Specifies an arbitrary set of key-value pairs to associate with the gateway. + +#### Values + +- Default: None +- Data type: map containing one or more keys and string values. + +### `Certificate` + +Specifies the path to a file that contains a public certificate to use for TLS. This filepath must be accessible to the API gateway proxy at runtime. + +#### Values + +- Default: none +- This field is required. +- Data type: string value of the filepath to a public certificate + +### `PrivateKey` + +Specifies the path to a file that contains a private key to use for TLS. This filepath must be accessible to the API gateway proxy at runtime. + +#### Values + +- Default: none +- This field is required. +- Data type: string value of the filepath to a private key + +## Examples + +The following example demonstrates a file system certificate configuration. + + + + + +```hcl +Kind = "file-system-certificate" +Name = "tls-certificate" +Certificate = "/opt/consul/tls/api-gateway.crt" +PrivateKey = "/opt/consul/tls/api-gateway.key" +``` + + + + + +```json +{ + "Kind": "file-system-certificate", + "Name": "tls-certificate", + "Certificate": "opt/consul/tls/api-gateway.crt", + "PrivateKey": "/opt/consul/tls/api-gateway.key" +} +``` + + + \ No newline at end of file diff --git a/website/content/docs/connect/config-entries/http-route.mdx b/website/content/docs/connect/config-entries/http-route.mdx index 4aa807b47b70..6265930b3e57 100644 --- a/website/content/docs/connect/config-entries/http-route.mdx +++ b/website/content/docs/connect/config-entries/http-route.mdx @@ -1,6 +1,6 @@ --- layout: docs -page_title: HTTP Route Configuration +page_title: HTTP Route configuration reference description: Learn how to configure an HTTP Route bound to an API Gateway on VMs. --- @@ -86,6 +86,12 @@ to view additional details, including default values. - [`TimeoutFilter`](#rules-services-filters-timeoutfilter): map - [`IdleTimeout`](#rules-services-filters-timeoutfilter): number | `0` - [`RequestTimeout`](#rules-services-filters-timeoutfilter): number | `0` + - [`JWT`](#rules-filters-jwt): map + - [`Providers`](#rules-filters-jwt-providers): list + - [`Name`](#rules-filters-jwt-providers): string + - [`VerifyClaims`](#rules-filters-jwt-providers): map + - [`Path`](#rules-filters-jwt-providers): list + - [`Value`](#rules-filters-jwt-providers): string - [`ResponseFilters`](#rules-services-responsefilters) - [`Headers`](#rules-services-responsefilters-headers): list | no default - [`Add`](#rules-services-responsefilters-headers-add): map | no default diff --git a/website/content/docs/connect/config-entries/index.mdx b/website/content/docs/connect/config-entries/index.mdx index a27bca1c5d3f..309ea26b177a 100644 --- a/website/content/docs/connect/config-entries/index.mdx +++ b/website/content/docs/connect/config-entries/index.mdx @@ -11,6 +11,8 @@ Configuration entries can be used to configure the behavior of Consul service me The following configuration entries are supported: +- [API Gateway](/consul/docs/connect/config-entries/api-gateway) - defines the configuration for an API gateway + - [Ingress Gateway](/consul/docs/connect/config-entries/ingress-gateway) - defines the configuration for an ingress gateway diff --git a/website/content/docs/connect/config-entries/ingress-gateway.mdx b/website/content/docs/connect/config-entries/ingress-gateway.mdx index 7b5eb23e1779..cd8eaf326f1e 100644 --- a/website/content/docs/connect/config-entries/ingress-gateway.mdx +++ b/website/content/docs/connect/config-entries/ingress-gateway.mdx @@ -1,11 +1,11 @@ --- layout: docs -page_title: Ingress gateway configuration entry reference +page_title: Ingress gateway configuration reference description: >- The ingress gateway configuration entry kind defines behavior for securing incoming communication between the service mesh and external sources. Learn about `""ingress-gateway""` config entry parameters for exposing TCP and HTTP listeners. --- -# Ingress gateway configuration entry reference +# Ingress gateway configuration reference @@ -576,7 +576,7 @@ Specifies a list of cipher suites that gateway listeners support when negotiatin - Default: None - Data type: List of string values. Refer to the [Consul repository](https://github.com/hashicorp/consul/blob/v1.11.2/types/tls.go#L154-L169) for a list of supported ciphers. -### `TSL.SDS` +### `TLS.SDS` Specifies parameters for loading the TLS certificates from an external SDS service. Refer to [Serve custom TLS certificates from an external service](/consul/docs/connect/gateways/ingress-gateway/tls-external-service) for additional information. diff --git a/website/content/docs/connect/config-entries/inline-certificate.mdx b/website/content/docs/connect/config-entries/inline-certificate.mdx index 496650f85946..abf68dc9b2db 100644 --- a/website/content/docs/connect/config-entries/inline-certificate.mdx +++ b/website/content/docs/connect/config-entries/inline-certificate.mdx @@ -1,13 +1,15 @@ --- layout: docs -page_title: Inline Certificate Configuration Reference +page_title: Inline certificate configuration reference description: Learn how to configure an inline certificate bound to an API Gateway on VMs. --- # Inline certificate configuration reference -This topic provides reference information for the gateway inline certificate -configuration entry. For information about certificate configuration for Kubernetes environments, refer to [Gateway Resource Configuration](/consul/docs/connect/gateways/api-gateway/configuration/gateway). +This topic provides reference information for the inline certificate +configuration entry. The inline certificate secures TLS for the Consul API gateway on VMs. In production environments, we recommend you use the more secure [file system certificate configuration entry](/consul/docs/connect/config-entries/file-system-certificate) instead. + +The inline certificate configuration entry is not used for Consul on Kubernetes deployments. To learn about configuring certificates for Kubernetes environments, refer to [Gateway Resource Configuration](/consul/docs/connect/gateways/api-gateway/configuration/gateway). ## Configuration model @@ -27,9 +29,11 @@ to view additional details, including default values. When every field is defined, an `inline-certificate` configuration entry has the following form: - + + + -```HCL +```hcl Kind = "inline-certificate" Name = "" @@ -41,19 +45,24 @@ Certificate = "" PrivateKey = "" ``` -```JSON + + + + +```json { "Kind": "inline-certificate", "Name": "", "Meta": { "any key": "any value" - } + }, "Certificate": "", "PrivateKey": "" } ``` - + + ## Specification @@ -125,3 +134,34 @@ Specifies the inline private key to use for TLS. - Default: none - This field is required. - Data type: string value of the private key + +## Examples + +The following example demonstrates an inline certificate configuration. + + + + + +```hcl +Kind = "inline-certificate" +Name = "tls-certificate" +Certificate = "" +PrivateKey = "" +``` + + + + + +```json +{ + "Kind": "inline-certificate", + "Name": "tls-certificate", + "Certificate": "", + "PrivateKey": "" +} +``` + + + \ No newline at end of file diff --git a/website/content/docs/connect/config-entries/jwt-provider.mdx b/website/content/docs/connect/config-entries/jwt-provider.mdx index 9ea7ce40ba01..d1bedd935533 100644 --- a/website/content/docs/connect/config-entries/jwt-provider.mdx +++ b/website/content/docs/connect/config-entries/jwt-provider.mdx @@ -1,10 +1,10 @@ --- -page_title: JWT provider configuration entry reference +page_title: JWT provider configuration reference description: |- JWT provider configuration entries add JSON Web Token token validation to intentions in the service mesh. Learn how to write `jwt-provider` config entries in HCL or YAML with a specification reference, configuration model, a complete example, and example code by use case. --- -# JWT provider configuration entry reference +# JWT provider configuration reference This page provides reference information for the JWT provider configuration entry, which configures Consul to use a JSON Web Token (JWT) and JSON Web Key Set (JWKS) in order to add JWT validation to proxies in the service mesh. Refer to [Use JWT authorization with service intentions](/consul/docs/connect/intentions/jwt-authorization) for more information. diff --git a/website/content/docs/connect/config-entries/mesh.mdx b/website/content/docs/connect/config-entries/mesh.mdx index 4b5bb7ee2dfa..cf75c4bfa4ab 100644 --- a/website/content/docs/connect/config-entries/mesh.mdx +++ b/website/content/docs/connect/config-entries/mesh.mdx @@ -264,6 +264,60 @@ spec: Note that the Kubernetes example does not include a `partition` field. Configuration entries are applied on Kubernetes using [custom resource definitions (CRD)](/consul/docs/k8s/crds), which can only be scoped to their own partition. +### Request Normalization + +Enable options under `HTTP.Incoming.RequestNormalization` to apply normalization to all inbound traffic to mesh proxies. + +~> **Compatibility warning**: This feature is available as of Consul CE 1.20.1 and Consul Enterprise 1.20.1, 1.19.2, 1.18.3, and 1.15.15. We recommend upgrading to the latest version of Consul to take advantage of the latest features and improvements. + + + +```hcl +Kind = "mesh" +HTTP { + Incoming { + RequestNormalization { + InsecureDisablePathNormalization = false // default false, shown for completeness + MergeSlashes = true + PathWithEscapedSlashesAction = "UNESCAPE_AND_FORWARD" + HeadersWithUnderscoresAction = "REJECT_REQUEST" + } + } +} +``` + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: Mesh +metadata: + name: mesh +spec: + http: + incoming: + requestNormalization: + insecureDisablePathNormalization: false # default false, shown for completeness + mergeSlashes: true + pathWithEscapedSlashesAction: UNESCAPE_AND_FORWARD + headersWithUnderscoresAction: REJECT_REQUEST +``` + +```json +{ + "Kind": "mesh", + "HTTP": { + "Incoming": { + "RequestNormalization": { + "InsecureDisablePathNormalization": false, + "MergeSlashes": true, + "PathWithEscapedSlashesAction": "UNESCAPE_AND_FORWARD", + "HeadersWithUnderscoresAction": "REJECT_REQUEST" + } + } + } +} +``` + + ## Available Fields @@ -342,6 +396,17 @@ Note that the Kubernetes example does not include a `partition` field. Configura description: 'Controls whether `MutualTLSMode=permissive` can be set in the `proxy-defaults` and `service-defaults` configuration entries. ' }, + { + name: 'ValidateClusters', + type: 'bool: false', + description: + `Controls whether the clusters the route table refers to are validated. The default value is false. When set to + false and a route refers to a cluster that does not exist, the route table loads and routing to a non-existent + cluster results in a 404. When set to true and the route is set to a cluster that do not exist, the route table + will not load. For more information, refer to + [HTTP route configuration in the Envoy docs](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route.proto#envoy-v3-api-field-config-route-v3-routeconfiguration-validate-clusters) + for more details. `, + }, { name: 'TLS', type: 'TLSConfig: ', @@ -441,6 +506,57 @@ Note that the Kubernetes example does not include a `partition` field. Configura for all Envoy proxies. As a result, Consul will not include the \`x-forwarded-client-cert\` header in the next hop. If set to \`false\` (default), the XFCC header is propagated to upstream applications.`, }, + { + name: 'Incoming', + type: 'DirectionalHTTPConfig: ', + description: `HTTP configuration for inbound traffic to mesh proxies.`, + children: [ + { + name: 'RequestNormalization', + type: 'RequestNormalizationConfig: ', + description: `Request normalization configuration for inbound traffic to mesh proxies.`, + children: [ + { + name: 'InsecureDisablePathNormalization', + type: 'bool: false', + description: `Sets the value of the \`normalize_path\` option in the Envoy listener's \`HttpConnectionManager\`. The default value is \`false\`. + When set to \`true\` in Consul, \`normalize_path\` is set to \`false\` for the Envoy proxy. + This parameter disables the normalization of request URL paths according to RFC 3986, + conversion of \`\\\` to \`/\`, and decoding non-reserved %-encoded characters. When using L7 + intentions with path match rules, we recommend enabling path normalization in order + to avoid match rule circumvention with non-normalized path values.`, + }, + { + name: 'MergeSlashes', + type: 'bool: false', + description: `Sets the value of the \`merge_slashes\` option in the Envoy listener's \`HttpConnectionManager\`. The default value is \`false\`. + This option controls the normalization of request URL paths by merging consecutive \`/\` characters. This normalization is not part + of RFC 3986. When using L7 intentions with path match rules, we recommend enabling this setting to avoid match rule circumvention through non-normalized path values, unless legitimate service + traffic depends on allowing for repeat \`/\` characters, or upstream services are configured to + differentiate between single and multiple slashes.`, + }, + { + name: 'PathWithEscapedSlashesAction', + type: 'string: ""', + description: `Sets the value of the \`path_with_escaped_slashes_action\` option in the Envoy listener's + \`HttpConnectionManager\`. The default value of this option is empty, which is + equivalent to \`IMPLEMENTATION_SPECIFIC_DEFAULT\`. This parameter controls the action taken in response to request URL paths with escaped + slashes in the path. When using L7 intentions with path match rules, we recommend enabling this setting to avoid match rule circumvention through non-normalized path values, unless legitimate service + traffic depends on allowing for escaped \`/\` or \`\\\` characters, or upstream services are configured to + differentiate between escaped and unescaped slashes. Refer to the Envoy documentation for more information on available + options.`, + }, + { + name: 'HeadersWithUnderscoresAction', + type: 'string: ""', + description: `Sets the value of the \`headers_with_underscores_action\` option in the Envoy listener's + \`HttpConnectionManager\` under \`common_http_protocol_options\`. The default value of this option is + empty, which is equivalent to \`ALLOW\`. Refer to the Envoy documentation for more information on available options.`, + }, + ], + }, + ], + } ], }, { diff --git a/website/content/docs/connect/config-entries/proxy-defaults.mdx b/website/content/docs/connect/config-entries/proxy-defaults.mdx index 1c5714145978..824ce835998c 100644 --- a/website/content/docs/connect/config-entries/proxy-defaults.mdx +++ b/website/content/docs/connect/config-entries/proxy-defaults.mdx @@ -27,7 +27,7 @@ The following list outlines field hierarchy, language-specific data types, and r - [`Name`](#name): string | must be set to `global` - [`Namespace`](#namespace): string | `default` | - [`Partition`](#partition): string | `default` | -- [`Meta`](#meta): map +- [`Meta`](#meta): map - [`Config`](#meta): map - [`EnvoyExtensions`](#envoyextensions): list of maps - [`Name`](#envoyextensions): string @@ -39,16 +39,16 @@ The following list outlines field hierarchy, language-specific data types, and r - [`TransparentProxy`](#transparentproxy): map - [`OutboundListenerPort`](#transparentproxy): number | `15001` - [`DialedDirectly`](#transparentproxy): boolean | `false` -- [`MutualTLSMode`](#mutualtlsmode): string +- [`MutualTLSMode`](#mutualtlsmode): string - [`MeshGateway`](#meshgateway): map - [`Mode`](#meshgateway): string - [`Expose`](#expose): map - [`Checks`](#expose-checks): boolean | `false` - [`Paths`](#expose-paths): list of maps - - [`Path`](#expose-paths-path): string | must begin with `/` - - [`LocalPathPort`](#expose-paths): number | `0` - - [`ListenerPort`](#expose-paths): number | `0` - - [`Protocol`](#expose-paths): string | `http` + - [`Path`](#expose-paths-path): string | must begin with `/` + - [`LocalPathPort`](#expose-paths): number | `0` + - [`ListenerPort`](#expose-paths): number | `0` + - [`Protocol`](#expose-paths): string | `http` - [`PrioritizeByLocality`](#prioritizebylocality): map | - [`Mode`](#prioritizebylocality): string | `failover` - [`AccessLogs`](#accesslogs): map @@ -56,8 +56,8 @@ The following list outlines field hierarchy, language-specific data types, and r - [`DisableListenerLogs`](#accesslogs): boolean | `false` - [`Type`](#accesslogs): string | `stdout` - [`Path`](#accesslogs): string - - [`JSONFormat`](#accesslogs): string - - [`TextFormat`](#accesslogs): string + - [`JSONFormat`](#accesslogs): string + - [`TextFormat`](#accesslogs): string @@ -79,16 +79,16 @@ The following list outlines field hierarchy, language-specific data types, and r - [`transparentProxy`](#spec-transparentproxy): map - [`outboundListenerPort`](#spec-transparentproxy): number | `15001` - [`dialedDirectly`](#spec-transparentproxy): boolean | `false` - - [`mutualTLSMode`](#spec-mutualtlsmode): string + - [`mutualTLSMode`](#spec-mutualtlsmode): string - [`meshGateway`](#spec-meshgateway): map - [`mode`](#spec-meshgateway): string - [`expose`](#spec-expose): map - [`checks`](#spec-expose-checks): boolean | `false` - [`paths`](#spec-expose-paths): list - - [`path`](#spec-expose-paths): string | must begin with `/` - - [`localPathPort`](#spec-expose-paths): number | `0` - - [`listenerPort`](#spec-expose-paths): number | `0` - - [`protocol`](#spec-expose-paths): string | `http` + - [`path`](#spec-expose-paths): string | must begin with `/` + - [`localPathPort`](#spec-expose-paths): number | `0` + - [`listenerPort`](#spec-expose-paths): number | `0` + - [`protocol`](#spec-expose-paths): string | `http` - [`prioritizeByLocality`](#prioritizebylocality): map | - [`mode`](#prioritizebylocality): string | `failover` - [`accessLogs`](#spec-accesslogs): map @@ -96,8 +96,8 @@ The following list outlines field hierarchy, language-specific data types, and r - [`disableListenerLogs`](#spec-accesslogs): boolean | `false` - [`type`](#spec-accesslogs): string | `stdout` - [`path`](#spec-accesslogs): string - - [`jsonFormat`](#spec-accesslogs): string - - [`textFormat`](#spec-accesslogs): string + - [`jsonFormat`](#spec-accesslogs): string + - [`textFormat`](#spec-accesslogs): string @@ -121,15 +121,15 @@ Meta { Config { = } -EnvoyExtensions = [ - { +EnvoyExtensions = [ + { Name= "" Required = "required" Arguments = "" ConsulVersion = "" EnvoyVersion = "" } -] +] Mode = "" TransparentProxy { OutboundListenerPort = @@ -183,7 +183,7 @@ spec: required: required arguments: consulVersion: - envoyVersion: + envoyVersion: mode: transparentProxy: outboundListenerPort: @@ -296,7 +296,7 @@ Specifies a name for the configuration entry that is used to identify the config ### `Namespace` -Specifies the namespace that the proxy defaults apply to. You can only specify the `default` namespace. +Specifies the namespace that the proxy defaults apply to. You can only specify the `default` namespace. #### Values @@ -314,7 +314,7 @@ Specifies the local admin partition that the proxy defaults apply to. Refer to [ ### `Meta` -Specifies a set of custom key-value pairs to add the [Consul KV](#/consul/docs/dynamic-app-config/kv) store. +Specifies a set of custom key-value pairs to add the [Consul KV](#/consul/docs/dynamic-app-config/kv) store. #### Values @@ -328,7 +328,7 @@ Specifies a set of custom key-value pairs to add the [Consul KV](#/consul/docs/d Specifies an arbitrary map of configuration values used by service mesh proxies. The available configurations depend on the mesh proxy you use. You can configure any global values that your proxy allows in this field. Refer to the following topics for additional information: - [Envoy proxy configuration option](/consul/docs/connect/proxies/envoy#proxy-config-options) -- [Built-in proxy configuration options](/consul/docs/connect/proxies/built-in#proxy-config-key-reference) +- [Built-in proxy configuration options](/consul/docs/connect/proxies/built-in#proxy-config-key-reference) #### Values @@ -363,18 +363,18 @@ The following table describes how to configure values in the `EnvoyExtensions` m Specifies a mode for how proxies direct inbound and outbound traffic. You can specify one of the following values: -- `transparent`: In transparent mode, proxies capture and redirect inbound and outbound traffic. The mode does not enable traffic redirection, but directs Consul to configure Envoy as if traffic is already being redirected. +- `transparent`: In transparent mode, proxies capture and redirect inbound and outbound traffic. The mode does not enable traffic redirection, but directs Consul to configure Envoy as if traffic is already being redirected. -- `direct`: In this mode, the local application and other proxies must directly dial proxy listeners. +- `direct`: In this mode, the local application and other proxies must directly dial proxy listeners. #### Values - Default: None -- Data type: String +- Data type: String ### `TransparentProxy` -Contains configurations for proxies that are running in transparent proxy mode. This mode enables permissive mTLS for Consul so that you can use your Kubernetes cluster's DNS service instead of Consul DNS. Refer to [Transparent proxy mode](/consul/docs/k8s/connect/transparent-proxy) for additional information. +Contains configurations for proxies that are running in transparent proxy mode. This mode enables permissive mTLS for Consul so that you can use your Kubernetes cluster's DNS service instead of Consul DNS. Refer to [Transparent proxy mode](/consul/docs/k8s/connect/transparent-proxy) for additional information. #### Values @@ -392,11 +392,11 @@ The following table describes how to configure values in the `TransparentProxy` ### `MutualTLSMode` -Controls the default mutual TLS (mTLS) mode for all proxies. You can only set mutual TLS mode for services in transparent proxy mode. +Controls the default mutual TLS (mTLS) mode for all proxies. You can only set mutual TLS mode for services in transparent proxy mode. You can specify one of the following modes: -`strict`: The sidecar proxy requires mTLS for incoming traffic. +`strict`: The sidecar proxy requires mTLS for incoming traffic. `permissive`: The sidecar proxy accepts mTLS traffic on the sidecar proxy service port and accepts any traffic on the destination service port. We recommend only using permissive mode if necessary while onboarding services to the service mesh. #### Values @@ -421,7 +421,7 @@ Sets the default mesh gateway `mode` field for all proxies. You can specify the ### `Expose` -Specifies default configurations for exposing HTTP paths through Envoy. Exposing paths through Envoy enables services to protect themselves by only listening on `localhost`. Applications that are not Consul service mesh-enabled are still able to contact an HTTP endpoint. +Specifies default configurations for exposing HTTP paths through Envoy. Exposing paths through Envoy enables services to protect themselves by only listening on `localhost`. Applications that are not Consul service mesh-enabled are still able to contact an HTTP endpoint. Example use-cases include exposing the `/metrics` endpoint to a monitoring system, such as Prometheus, and exposing the `/healthz` endpoint to the kubelet for liveness checks. Refer to [Expose Paths Configuration Reference](/consul/docs/connect/proxy-config-reference#expose-paths-configuration-reference) for additional information. @@ -445,12 +445,12 @@ We recommend enabling the `Checks` configuration when a Consul client cannot rea ### `Expose{}.Paths[]` -Specifies a list of configuration maps that define paths to expose through Envoy when `Expose.Checks` is set to `true`. +Specifies a list of configuration maps that define paths to expose through Envoy when `Expose.Checks` is set to `true`. #### Values - Default: None -- Data type: List of maps +- Data type: List of maps The following table describes the parameters for each map you can define in the list: @@ -461,7 +461,7 @@ The following table describes the parameters for each map you can define in the | `ListenPort` | Specifies the port where the proxy listens for connections. The port must be available. If the port is unavailable, Envoy does not expose a listener for the path and the proxy registration still succeeds. | Integer | `0` | | `Protocol` | Specifies the protocol of the listener. You can configure one of the following values:
    5. `http`
    6. `http2`: Use with gRPC traffic
    7. | String | `http` | -### `PrioritizeByLocality` +### `PrioritizeByLocality` Sets a mode for the service that allows instances to prioritize upstream targets that are in the same network region and zone. You can specify the following string values for the `mode` field: @@ -479,7 +479,7 @@ Specifies [Envoy access logger](https://www.envoyproxy.io/docs/envoy/latest/intr #### Values - Default: None -- Data type: Map +- Data type: Map The following table describes the parameters you can define in the `AccessLogs` map: @@ -498,7 +498,7 @@ The following table describes the parameters you can define in the `AccessLogs` ### apiVersion -Specifies the verion of the Consul API to use to apply the configuration entry. This must be set to `consul.hashicorp.com/v1alpha1`. +Specifies the version of the Consul API to use to apply the configuration entry. This must be set to `consul.hashicorp.com/v1alpha1`. #### Values @@ -557,12 +557,12 @@ Map that contains the details about the ProxyDefaults configuration entry. The ` Specifies an arbitrary map of configuration values used by service mesh proxies. The available configurations depend on the mesh proxy you use. You can configure any global values that your proxy allows in this field. Refer to the following topics for additional information: - [Envoy proxy configuration option](/consul/docs/connect/proxies/envoy#proxy-config-options) -- [Built-in proxy configuration options](/consul/docs/connect/proxies/built-in#proxy-config-key-reference) +- [Built-in proxy configuration options](/consul/docs/connect/proxies/built-in#proxy-config-key-reference) #### Values - Default: None -- Data type: Map +- Data type: Map ### `spec.envoyExtensions` @@ -592,18 +592,18 @@ The following table describes how to configure values in the `EnvoyExtensions` m Specifies a mode for how proxies direct inbound and outbound traffic. You can specify one of the following values: -- `transparent`: In transparent mode, proxies capture and redirect inbound and outbound traffic. The mode does not enable traffic redirection, but directs Consul to configure Envoy as if traffic is already being redirected. +- `transparent`: In transparent mode, proxies capture and redirect inbound and outbound traffic. The mode does not enable traffic redirection, but directs Consul to configure Envoy as if traffic is already being redirected. -- `direct`: In this mode, the local application and other proxies must directly dial proxy listeners. +- `direct`: In this mode, the local application and other proxies must directly dial proxy listeners. #### Values - Default: None -- Data type: String +- Data type: String ### `spec.transparentProxy` -Contains configurations for proxies that are running in transparent proxy mode. This mode enables permissive mTLS for Consul so that you can use your Kubernetes cluster's DNS service instead of Consul DNS. Refer to [Transparent proxy mode](/consul/docs/k8s/connect/transparent-proxy) for additional information. +Contains configurations for proxies that are running in transparent proxy mode. This mode enables permissive mTLS for Consul so that you can use your Kubernetes cluster's DNS service instead of Consul DNS. Refer to [Transparent proxy mode](/consul/docs/k8s/connect/transparent-proxy) for additional information. #### Values @@ -621,11 +621,11 @@ The following table describes how to configure values in the `TransparentProxy` ### `spec.mutualTLSMode` -Controls the default mutual TLS (mTLS) mode for all proxies. You can only set mutual TLS mode for services in transparent proxy mode. +Controls the default mutual TLS (mTLS) mode for all proxies. You can only set mutual TLS mode for services in transparent proxy mode. You can specify one of the following modes: -`strict`: The sidecar proxy requires mTLS for incoming traffic. +`strict`: The sidecar proxy requires mTLS for incoming traffic. `permissive`: The sidecar proxy accepts mTLS traffic on the sidecar proxy service port and accepts any traffic on the destination service port. We recommend only using permissive mode if necessary while onboarding services to the service mesh. #### Values @@ -650,7 +650,7 @@ Sets the default mesh gateway `mode` field for all proxies. You can specify the ### `spec.expose` -Specifies default configurations for exposing HTTP paths through Envoy. Exposing paths through Envoy enables services to protect themselves by only listening on `localhost`. Applications that are not Consul service mesh-enabled are still able to contact an HTTP endpoint. +Specifies default configurations for exposing HTTP paths through Envoy. Exposing paths through Envoy enables services to protect themselves by only listening on `localhost`. Applications that are not Consul service mesh-enabled are still able to contact an HTTP endpoint. Example use-cases include exposing the `/metrics` endpoint to a monitoring system, such as Prometheus, and exposing the `/healthz` endpoint to the kubelet for liveness checks. Refer to [Expose Paths Configuration Reference](/consul/docs/connect/proxy-config-reference#expose-paths-configuration-reference) for additional information. @@ -659,7 +659,7 @@ Example use-cases include exposing the `/metrics` endpoint to a monitoring syste - Default: None - Data type: Map containing the following parameters: - [`checks`](#expose-checks) - - [`aths`](#expose-paths) + - [`paths`](#expose-paths) ### `spec.expose{}.checks` @@ -674,12 +674,12 @@ We recommend enabling the `Checks` configuration when a Consul client cannot rea ### `spec.expose{}.paths[]` -Specifies a list of configuration maps that define paths to expose through Envoy when `spec.expose.checks` is set to `true`. +Specifies a list of configuration maps that define paths to expose through Envoy when `spec.expose.checks` is set to `true`. #### Values - Default: None -- Data type: List of maps. +- Data type: List of maps. The following table describes the parameters for each map you can define in the list: @@ -708,7 +708,7 @@ Specifies [Envoy access logger](https://www.envoyproxy.io/docs/envoy/latest/intr #### Values - Default: None -- Data type: Map +- Data type: Map The following table describes the parameters you can define in the `accessLogs` map: diff --git a/website/content/docs/connect/config-entries/registration.mdx b/website/content/docs/connect/config-entries/registration.mdx new file mode 100644 index 000000000000..95740cb084f8 --- /dev/null +++ b/website/content/docs/connect/config-entries/registration.mdx @@ -0,0 +1,670 @@ +--- +layout: docs +page_title: Registration CRD configuration reference +description: The Registration CRD enables Consul on Kubernetes to register an external service without a terminating gateway. Learn how to configure a Registration CRD in YAML with a specification reference, configuration model, a complete example, and example code. +--- + +# Registration CRD configuration reference + +This topic provides reference information for `Registration` custom resource definitions (CRDs). You can use this CRD to register an external service with Consul on Kubernetes. For more information. Refer to [Register services running on external nodes to Consul on Kubernetes](/consul/docs/k8s/deployment-configurations/external-service) for more information. + +## Configuration model + +The following list outlines field hierarchy, language-specific data types, and requirements in a `Registration` CRD. Click on a property name to view additional details, including default values. + +- [`apiVersion`](#apiversion): string | required | must be set to `consul.hashicorp.com/v1alpha1` +- [`kind`](#kind): string | required | must be set to `Registration` +- [`metadata`](#metadata): map + - [`name`](#metadata-name): string +- [`spec`](#spec): map | required + - [`address`](#spec-address): string + - [`check`](#spec-check): map + - [`checkId`](#spec-check-checkid): string + - [`definition`](#spec-check-definition): map + - [`body`](#spec-check-definition): string + - [`deregisterCriticalServiceAfterDuration`](#spec-check-definition): string + - [`grpc`](#spec-check-definition): string + - [`grpcUseTLS`](#spec-check-definition): boolean | `false` + - [`header`](#spec-check-definition): map of strings + - [`http`](#spec-check-definition): string + - [`intervalDuration`](#spec-check-definition): string + - [`method`](#spec-check-definition): string + - [`osService`](#spec-check-definition): string + - [`tcp`](#spec-check-definition): string + - [`tcpUseTLS`](#spec-check-definition): boolean + - [`timeoutDuration`](#spec-check-definition): string + - [`tlsServerName`](#spec-check-definition): string + - [`tlsSkipVerify`](#spec-check-definition): boolean | `false` + - [`udp`](#spec-check-definition): string + - [`exposedPort`](#spec-check-exposed-port): integer + - [`name`](#spec-check-name): string + - [`namespace`](#spec-check-namespace): string + - [`node`](#spec-check-node): string + - [`notes`](#spec-check-notes): string + - [`output`](#spec-check-output): string + - [`partition`](#spec-check-partition): string + - [`serviceId`](#spec-check-serviceid): string + - [`serviceName`](#spec-check-servicename): string + - [`status`](#spec-check-status): string + - [`type`](#spec-check-type): string + - [`datacenter`](#spec-datacenter): string + - [`id`](#spec-id): string + - [`locality`](#spec-locality): map + - [`region`](#spec-locality): string + - [`zone`](#spec-locality): string + - [`node`](#spec-node): string + - [`nodeMeta`](#spec-nodemeta): map of strings + - [`partition`](#spec-partition): string + - [`service`](#spec-service): map + - [`address`](#spec-service-address): string + - [`enableTagOverride`](#spec-service-enabletagoverride): boolean | `false` + - [`id`](#spec-service-id): string + - [`locality`](#spec-service-locality): map + - [`region`](#spec-service-locality): string + - [`zone`](#spec-service-locality): string + - [`meta`](#spec-service-meta): map of strings + - [`name`](#spec-service-name): string + - [`namespace`](#spec-service-namespace): string + - [`partition`](#spec-service-partition): string + - [`port`](#spec-service-port): integer + - [`socketPath`](#spec-service-socketpath): string + - [`taggedAddresses`](#spec-service-taggedaddresses): map + - [`address`](#spec-service-taggedaddresses): string + - [`port`](#spec-service-port): integer + - [`tags`](#spec-service-tags): map of strings + - [`weights`](#spec-service-weights): map + - [`passing`](#spec-service-weights): integer | `1` + - [`warning`](#spec-service-weights): integer | `1` + - [`skipNodeUpdate`](#spec-skipnodeupdate): boolean | `false` + - [`taggedAddresses`](#spec-taggedaddresses): map of strings + +## Complete configuration + +When every field is defined, a `Registration` CRD has the following form: + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 # required +kind: Registration # required +metadata: + name: +spec: + address: 10.0.0.1 + check: + name: external-health-check + checkId: unique-id + definition: + body: "{\"custom\": \"json\"}" + deregisterCriticalServiceAfterDuration: false + grpc: 127.0.0.1:443 + grpcUseTLS: false + header: + name: + intervalDuration: "5s" + method: "GET" + osService: + tcp: 127.0.0.1:4242 + tcpUseTLS: false + timeoutDuration: 10s + tlsServerName: + tlsSkipVerify: false + udp: 127.0.0.1:80 + exposedPort: 200 + namespace: default + notes: "Human readable description" + output: "Human readable output" + partition: default + serviceId: + serviceName: + status: critical + type: HTTP + datacenter: dc1 + id: + locality: + region: us-east-1 + zone: us-east-1a + node: + nodeMeta: + - key: value + partition: default + service: + address: "10.0.0.1:8300" + enableTagOverride: false + id: + locality: + region: us-east-1 + zone: us-east-1a + meta: + key: value + name: + namespace: default + partition: default + port: 5400 + socketPath: /folder/socket + taggedAddresses: + lan: + address: 127.0.1.0 + port: 80 + tags: + - "v2" + - "primary" + weights: + passing: 1 + warning: 1 + skipNodeUpdate: false + taggedAddresses: + lan: "192.168.10.10" +``` + +## Specification + +This section provides details about the fields you can configure in the `Registration` CRD. + +### `apiVersion` + +Specifies the version of the Consul API for integrating with Kubernetes. The value must be `consul.hashicorp.com/v1alpha1`. + +#### Values + +- Default: None +- This field is required. +- String value that must be set to `consul.hashicorp.com/v1alpha1`. + +### `kind` + +Specifies the type of configuration entry to implement. Must be set to `Registration`. + +#### Values + +- Default: None +- This field is required. +- Data type: String value that must be set to `Registration`. + +### `metadata` + +Map that contains an arbitrary name for the configuration entry and the namespace it applies to. + +#### Values + +- Default: None +- Data type: Map + +### `metadata.name` + +Specifies a name for the configuration entry that is used to identify the sameness group. To ensure consistency, use descriptive names and make sure that the same name is used when creating configuration entries to add each member to the sameness group. + +#### Values + +- Default: None +- This field is required. +- Data type: String + +### `spec` + +Map that contains the details about the `Registration` CRD. The `apiVersion`, `kind`, and `metadata` fields are siblings of the spec field. All other configurations are children. + +#### Values + +- Default: None +- This field is required. +- Data type: Map + +### `spec.address` + +Specifies the IP address where the external service is available. + +#### Values + +- Default: None +- Data type: String + +### `spec.check` + +Specifies details for a health check. Health checks perform several safety functions, such as allowing a web balancer to gracefully remove failing nodes and allowing a database to replace a failed secondary. You can configure health checks to monitor the health of the entire node. + +For more information about configuring health checks for Consul, refer to [health check configuration reference](/consul/docs/services/configuration/checks-configuration-reference). + +#### Values + +- Default: None +- Data type: Map + +### `spec.check.checkId` + +Specifies an ID for the health check. When `name` values conflict, provide a unique identifier to avoid overwriting existing checks. + +#### Values + +- Default: None +- Data type: String + +### `spec.check.definition` + +Specifies additional configuration details for the health check. + +Requires child parameters `deregisterCriticalServiceAfterDuration`, `intervalDuration`, and `timeoutDuration`. + +#### Values + +- Default: None +- Data type: Map that can contain the following parameters: + +| Parameter | Description | Type | Default | +| :------------------------------------------------------------- | :---------- | :---------- | :---------- | +| `spec.check.definition.body` | Specifies JSON attributes to send in HTTP check requests. You must escape the quotation marks around the keys and values for each attribute. | String | None | +| `spec.check.definition.deregisterCriticalServiceAfterDuration` | Specifies how long a service and its associated checks are allowed to be in a `critical` state. Consul deregisters services if they are `critical` for the specified amount of time. This parameter is required to configure `spec.check.definition`. | String | `"30s"` | +| `spec.check.definition.grpc` | Specifies the gRPC endpoint, including port number, to send requests to. Append the endpoint with `:/` and a service identifier to check a specific service. The endpoint must support the [gRPC health checking protocol](https://github.com/grpc/grpc/blob/master/doc/health-checking.md). | String | None | +| `spec.check.definition.grpcUseTLS` | Enables TLS for gRPC checks when set to `true`. | Boolean | `false` | +| `spec.check.definition.header` | Specifies header fields to send in HTTP check requests. | Map of strings | None | +| `spec.check.definition.http` | Specifies an HTTP endpoint to send requests to. | String | None | +| `spec.check.definition.intervalDuration` | Specifies how frequently to run the health check. This parameter is required to configure `spec.check.definition`. | String | `"5s"` | +| `spec.check.definition.method` | Specifies the request method to send during HTTP checks. | String | `GET` | +| `spec.check.definition.osService` | Specifies the name of the name of a service to check during an OSService check. | String | None | +| `spec.check.definition.tcp` | Specifies an IP address or host and port number that the check establishes a TCP connection with. | String | None | +| `spec.check.definition.tcpUseTLS` | Enables TLS for TCP checks when set to `true`. | Boolean | `false` | +| `spec.check.definition.timeoutDuration` | Specifies how long unsuccessful requests take to end with a timeout. This parameter is required to configure `spec.check.definition`. | String | `"10s"` | +| `spec.check.definition.tlsServerName` | Specifies the server name used to verify the hostname on the returned certificates unless `tls_skip_verify` is configured. This value is also included in the client's handshake to support SNI. It is recommended that this field be left unspecified. Refer to [health check configuration reference](/consul/docs/services/configuration/checks-configuration-reference#check-block) for more information. | String | None | +| `spec.check.definition.tlsSkipVerify` | Determines if the check verifies the chain and hostname of the certificate that the server presents. Set to `true` to disable verification. We recommend setting to `false` in production environments. | Boolean | `false` | +| `spec.check.definition.udp` | Specifies an IP address or host and port number for the check to send UDP datagrams to. | String | None | + +### `spec.check.exposedPort` + +Specifies the port the service exposes to health checks. + +#### Values + +- Default: None +- Data type: Integer + +### `spec.check.name` + +Specifies a name for the health check. Defaults to [`spec.service.id`](#spec-service-id). + +#### Values + +- Default: None +- Data type: String + +### `spec.check.namespace` + +Specifies the Consul namespace the health check applies to. Refer to [namespaces](/consul/docs/enterprise/namespace) for more information. + +#### Values + +- Default: None +- Data type: String + +### `spec.check.node` + +Specifies the name of the node the health check applies to. + +#### Values + +- Default: None +- Data type: String + +### `spec.check.notes` + +Provides a human-readable description of the health check. The contents are not visible to Consul. + +#### Values + +- Default: None +- Data type: String + +### `spec.check.output` + +Specifies human readable output in response to a health check. + +#### Values + +- Default: None +- Data type: String + +### `spec.check.partition` + +Specifies the Consul admin partition the health check applies to. Refer to [admin partitions](/consul/docs/enterprise/admin-partitions) for more information. + +#### Values + +- Default: None +- Data type: String + +### `spec.check.serviceId` + +Specifies the ID of the service to perform the health check on. + +#### Values + +- Default: None +- Data type: String + +### `spec.check.serviceName` + +Specifies the name of the service to perform the health check on. + +#### Values + +- Default: None +- Data type: String + +### `spec.check.status` + +Specifies the initial status of the health check. The default value for this field is `critical`, which requires services to pass a health check before making them available for service disocvery. You can specify one the following values: + +- `critical` +- `warning` +- `passing` + +#### Values + +- Default: `critical` +- Data type: String + +### `spec.check.type` + +Specifies the type health check in the form of a Kubernetes probe. + +#### Values + +- Default: None +- Data type: String + +### `spec.datacenter` + +Specifies the datacenter to register the service's node in, which defaults to the agent's datacenter if not provided. + +#### Values + +- Default: None +- Data type: String + +### `spec.id` + +Specifies a unique ID for the node to register. This optional ID must be a 36-character UUID-formatted string. + +#### Values + +- Default: None +- Data type: String + +### `spec.locality` + +Specifies the cloud region and zone where the node is available. + +#### Values + +- Default: None +- Data type: Map that can contain the following parameters: + +| Parameter | Description | Data type | Default | +| :-------- | :---------- | :-------- | :------ | +| `spec.locality.region` | Specifies the region where the node is running. Consul assigns this value to services registered to that agent. When service proxy regions match, Consul is able to prioritize routes between service instances in the same region over instances in other regions. You must specify values that are consistent with how regions are defined in your network, for example `us-west-1` for networks in AWS. | String | None | +| `spec.locality.zone` | Specifies the availability zone where the node is running. Consul assigns this value to services registered to that agent. When service proxy regions match, Consul is able to prioritize routes between service instances in the same region and zone over instances in other regions and zones. When healthy service instances are available in multiple zones within the most-local region, Consul prioritizes instances that also match the downstream proxy's `zone`. You must specify values that are consistent with how zones are defined in your network, for example `us-west-1a` for networks in AWS. | String | None | + +### `spec.node` + +Specifies the name of the node to register. + +#### Values + +- Default: None +- Data type: String + +### `spec.nodeMeta` + +Specifies arbitrary KV metadata pairs for filtering purposes. + +#### Values + +- Default: None +- Data type: Map of strings + +### `spec.partition` + +Specifies the admin partition of the node to register. + +#### Values + +- Default: None +- Data type: String + +### `spec.service` + +Specifies the service to register. The `Service.Service` field is required. If `Service.ID` is not provided, the default is the `Service.Service`. + +You can only specify one service with a given `ID` per node. We recommend using valid DNS labels for service definition names. Refer to [Internet Engineering Task Force's RFC 1123](https://datatracker.ietf.org/doc/html/rfc1123#page-72) for additional information. Service names that conform to standard usage ensures compatibility with external DNSs. Refer to [Services Configuration Reference](/consul/docs/services/configuration/services-configuration-reference#name) for more information. + +#### Values + +- Default: None +- Data type: Map + +### `spec.service.address` + +Specifies a service-specific IP address or hostname. If no value is specified, the IP address of the agent node is used by default. There is no service-side validation of this parameter. + +#### Values + +- Default: None +- Data type: String + +### `spec.service.enableTagOverride` + +Setermines if the anti-entropy feature for the service is enabled. + +Set to `true` to allow external Consul agents to modify tags on the services in the Consul catalog. The local Consul agent ignores updated tags during subsequent sync operations. + +This parameter only applies to the locally-registered service. When multiple nodes register a service with the same name, the `enable_tag_override` configuration and all other service configuration items operate independently. + +Refer to [Modify anti-entropy synchronization](/consul/docs/services/usage/define-services#modify-anti-entropy-synchronization) for additional information. + +#### Values + +- Default: `false` +- Data type: Boolean + +### `spec.service.id` + +Specifies an ID for the service. Services on the same node must have unique IDs. We recommend specifying unique values if the default name conflicts with other services. + +#### Values + +- Default: None +- Data type: String + +### `spec.service.locality` + +Specifies the region and zone in the cloud service provider (CSP) where the service is available. Configure this field to enable Consul to route traffic to the nearest physical service instance. Services inherit the `locality` configuration of the Consul agent they are registered with, but you can explicitly define locality for your service instances if an override is needed. Refer to [Route traffic to local upstreams](/consul/docs/connect/manage-traffic/route-to-local-upstreams) for additional information. + +#### Values + +- Default: None +- Data type: Map that can contain the following parameters: + +| Parameter | Description | Data type | Default | +| :-------- | :---------- | :-------- | :------ | +| `spec.service.locality.region` | Specifies the region where the Consul agent is running. Consul assigns this value to services registered to that agent. When service proxy regions match, Consul is able to prioritize routes between service instances in the same region over instances in other regions. You must specify values that are consistent with how regions are defined in your network, for example `us-west-1` for networks in AWS. | String | None | +| `spec.service.locality.zone` | Specifies the availability zone where the Consul agent is running. Consul assigns this value to services registered to that agent. When service proxy regions match, Consul is able to prioritize routes between service instances in the same region and zone over instances in other regions and zones. When healthy service instances are available in multiple zones within the most-local region, Consul prioritizes instances that also match the downstream proxy's `zone`. You must specify values that are consistent with how zones are defined in your network, for example `us-west-1a` for networks in AWS. | String | None | + +### `spec.service.meta` + +Specifies custom key-value pairs that associate semantic metadata with the service. You can specify up to 64 pairs that meet the following requirements: + +- Keys and values must be strings. +- Keys can only contain ASCII characters (`A` -` Z`, `a`- `z`, `0` - `9`, `_`, and `-`). +- Keys can not have special characters. +- Keys are limited to 128 characters. +- Values are limited to 512 characters. + +#### Values + +- Default: None +- Data type: Map of strings + +### `spec.service.name` + +Specifies a name for the service. We recommend using valid DNS labels for service definition names for compatibility with external DNSs. The value of this parameter is also used as the service ID if the `spec.service.id` parameter is not specified. + +#### Values + +- Default: None +- Data type: String + +### `spec.service.namespace` + +Specifies the Consul namespace to register the service in. Refer to [namespaces](/consul/docs/enterprise/namespaces) for more information. + +#### Values + +- Default: None +- Data type: String + +### `spec.service.partition` + +Specifies the Consul admin partition to register the service in. Refer to [admin partitions](/consul/docs/enterprise/admin-partitions) for more information. + +#### Values + +- Default: None +- Data type: String + +### `spec.service.port` + +Specifies a port number for the service. To improve service discoverability, we recommend specifying the port number, as well as an address in the tagged_addresses parameter. + +#### Values + +- Default: None +- Data type: Integer + +### `spec.service.socketPath` + +Specifies the path to the service socket. Specify this parameter to expose the service to the mesh if the service listens on a Unix Domain socket. + +#### Values + +- Default: None +- Data type: String + +### `spec.service.taggedAddresses` + +Configures additional addresses for a node or service. Remote agents and services can communicate with the service using a tagged address as an alternative to the address specified in [`spec.service.address`](#spec-serviceaddress). You can configure multiple addresses for a node or service. The following tags are supported: + +- `lan`: IPv4 LAN address where the node or service is accessible. +- `lan_ipv4`: IPv4 LAN address where the node or service is accessible. +- `lan_ipv6`: IPv6 LAN address where the node or service is accessible. +- `virtual`: A fixed address for the instances of a given logical service. +- `wan`: IPv4 WAN address where the node or service is accessible when dialed from a remote data center. +- `wan_ipv4`: IPv4 WAN address where the node or service is accessible when dialed from a remote data center. +- `wan_ipv6`: IPv6 WAN address at which the node or service is accessible when being dialed from a remote data center. + +#### Values + +- Default: None +- Data type: Map that contains a supported tag and a child map containing the following fields: + +| Parameter | Description | Type | Default | +| :------------------------------------- | :---------------------------- | :---------- | :---------- | +| `spec.service.taggedAddresses.address` | The address saved in the tag. | String | None | +| `spec.service.taggedAddresses.port` | The port saved in the tag. | String | None | + +### `spec.service.tags` + +Specifies a list of string values that add service-level labels. Tag values are opaque to Consul. We recommend using valid DNS labels for service definition IDs for compatibility with external DNSs. In the following example, the service is tagged as `v2` and `primary`: + +```yaml +spec: + service: + tags: ["v2", "primary"] +``` + +Consul uses tags as an anti-entropy mechanism to maintain the state of the cluster. You can disable the anti-entropy feature for a service using [`spec.service.enable_tag_override`](#spec-service-enabletagoverride), which enables external agents to modify tags on services in the catalog. Refer to [Modify anti-entropy synchronization](/consul/docs/services/usage/define-services#modify-anti-entropy-synchronization) for additional usage information. + +#### Values + +- Default: None +- Data type: Map of strings + +### `spec.service.weights` + +Configures how a service instance is weighted in a DNS SRV request based on the service's health status. Configuring tells DNS clients to direct more traffic to instances with a higher weight. A use case would be adjusting the weight higher for an instance with large capacity. It could also be used to reduce the load on services with checks in `warning` status by favoring passing instances with a higher weight. + +Larger integer values increase the weight state. + +You can specify one or more of the following states and configure an integer value indicating its weight: + +- `passing` +- `warning` + +Services in a `critical` state are excluded from DNS responses. Services with `warning` checks are included in responses by default. + +#### Values + +- Default: None +- Data type: Map containing the following parameters: + +| Parameter | Description | Type | Default | +| :----------------------------- | :---------------------------- | :---------- | :---------- | +| `spec.service.weights.passing` | Higher values increases the likelihood that a request is routed to a service in a `passing` state. | Integer | `1` | +| `spec.service.weights.warning` | Higher values increases the likelihood that a request is routed to a service in a `warning` state. | Integer | `1` | + +### `spec.skipNodeUpdate` + +Specifies whether to skip updating the node's information in the registration. This field is useful in casew where only a health check or service entry on a node needs to be updated or when a register request is intended to update a service entry or health check. In both use cases, node information is not be overwritten, if the node is already registered. Note, if the parameter is enabled for a node that does not exist, it is still be created. + +#### Values + +- Default: `false` +- Data type: Boolean + +### `spec.taggedAddresses` + +Specifies tagged addresses for the node. Remote agents and services can communicate with the service using a tagged address as an alternative to the address specified in [`spec.address`](#spec-serviceaddress). You can configure multiple addresses for a node or service. The following tags are supported: + +- `lan`: IPv4 LAN address where the node or service is accessible. +- `lan_ipv4`: IPv4 LAN address where the node or service is accessible. +- `lan_ipv6`: IPv6 LAN address where the node or service is accessible. +- `virtual`: A fixed address for the instances of a given logical service. +- `wan`: IPv4 WAN address where the node or service is accessible when dialed from a remote data center. +- `wan_ipv4`: IPv4 WAN address where the node or service is accessible when dialed from a remote data center. +- `wan_ipv6`: IPv6 WAN address at which the node or service is accessible when being dialed from a remote data center. + +#### Values + +- Default: None +- Data type: Map of strings + +## Examples + +The following example demonstrates a common `Registration` CRD configuration pattern. In this example, Consul registers a database service available at the IP address `10.96.32.66` that runs outside of the Kubernetes cluster where Consul is deployed. Consul runs an HTTP health check on this service every 10 seconds. + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: Registration +metadata: + name: external-database +spec: + node: node-virtual + check: + node: node-virtual + checkId: db-check + name: db + serviceName: db + serviceId: db-external + notes: "Runs the external health check for the database." + status: "passing" + definition: + http: "10.96.32.66:8081/health" + intervalDuration: "10s" + timeoutDuration: "10s" + deregisterCriticalServiceAfterDuration: "30s" + service: + name: db + id: db-external + address: "10.96.32.66" + port: 8081 + weights: + passing: 1 + warning: 1 + address: 10.96.32.66 +``` \ No newline at end of file diff --git a/website/content/docs/connect/config-entries/sameness-group.mdx b/website/content/docs/connect/config-entries/sameness-group.mdx index 7a101b4f79c9..f9fdffcd7a64 100644 --- a/website/content/docs/connect/config-entries/sameness-group.mdx +++ b/website/content/docs/connect/config-entries/sameness-group.mdx @@ -1,10 +1,10 @@ --- -page_title: Sameness group configuration entry reference +page_title: Sameness group configuration reference description: |- Sameness groups enable Consul to associate service instances with the same name deployed to the same namespace as identical services. Learn how to configure a `sameness-group` configuration entry to enable failover between partitions and cluster peers in non-federated networks. --- -# Sameness groups configuration entry reference +# Sameness groups configuration reference This page provides reference information for sameness group configuration entries. Sameness groups associate identical admin partitions to facilitate traffic between identical services. When partitions are part of the same Consul datacenter, you can create a sameness group by listing them in the `Members[].Partition` field. When partitions are located on remote clusters, you must establish cluster peering connections between remote partitions in order to add them to a sameness group in the `Members[].Peer` field. @@ -75,7 +75,7 @@ Members = [ # required "Name": "", // required "Partition": "", "DefaultForFailover": false, - "IncludeLocal": true, + "IncludeLocal": true, "Members": [ // required { "Partition": "" @@ -152,6 +152,8 @@ When this field is set to `true`, upstream requests automatically fail over to s When this field is set to `false`, you can use a sameness group for failover by configuring the `Failover` block of a [service resolver configuration entry](/consul/docs/connect/config-entries/service-resolver). +When you [query Consul DNS](/consul/docs/services/discovery/dns-static-lookups) using sameness groups, `DefaultForFailover` must be set to `true`. Otherwise, Consul DNS returns an error. + #### Values - Default: `false` @@ -172,7 +174,7 @@ If you enable this parameter, you do not need to list the local partition as the Specifies the partitions and cluster peers that are members of the sameness group from the perspective of the local partition. -The local partition should be the first member listed unless `IncludeLocal=true`. The order of the members determines their precedence during failover scenarios. If a member is listed but Consul cannot connect to it, failover proceeds with the next healthy member in the list. For an example demonstrating how to configure this parameter, refer to [Failover between sameness groups](#failover-between-sameness-groups). +The local partition should be the first member listed unless `IncludeLocal=true`. The order of the members determines their precedence during failover scenarios. If a member is listed but Consul cannot connect to it, failover proceeds with the next healthy member in the list. For an example demonstrating how to configure this parameter, refer to [Failover between sameness groups](#failover-between-members-of-a-sameness-group). Each partition can belong to a single sameness group. You cannot associate a partition or cluster peer with multiple sameness groups. @@ -210,7 +212,7 @@ Cluster peering connections must be established before adding a remote partition ### `apiVersion` -Specifies the version of the Consul API for integrating with Kubernetes. The value must be `consul.hashicorp.com/v1alpha1`. +Specifies the version of the Consul API for integrating with Kubernetes. The value must be `consul.hashicorp.com/v1alpha1`. #### Values @@ -228,7 +230,7 @@ Specifies the type of configuration entry to implement. Must be set to `Sameness - This field is required. - Data type: String value that must be set to `SamenessGroup`. -## `metadata` +### `metadata` Map that contains an arbitrary name for the configuration entry and the namespace it applies to. @@ -292,7 +294,7 @@ Each partition can belong to a single sameness group. You cannot associate a par - Default: None - This field is required. - Data type: List that can contain maps of the following parameters: - + - [`partition`](#spec-members-partition) - [`peer`](#spec-members-peer) @@ -337,7 +339,7 @@ In the following example, the configuration entry defines a sameness group named ```hcl -Kind = "sameness-group" +Kind = "sameness-group" Name = "products-api" Partition = "store-east" Members = [ @@ -354,8 +356,8 @@ Members = [ ```json { - "Kind": "sameness-group", - "Name": "products-api", + "Kind": "sameness-group", + "Name": "products-api", "Partition": "store-east", "Members": [ { @@ -380,11 +382,11 @@ Members = [ ```yaml apiVersion: consul.hashicorp.com/v1alpha1 -kind: SamenessGroup +kind: SamenessGroup metadata: name: products-api spec: - members: + members: - partition: store-east - partition: inventory-east - peer: dc2-store-west diff --git a/website/content/docs/connect/config-entries/service-defaults.mdx b/website/content/docs/connect/config-entries/service-defaults.mdx index 95cfd3f89546..271256bbae93 100644 --- a/website/content/docs/connect/config-entries/service-defaults.mdx +++ b/website/content/docs/connect/config-entries/service-defaults.mdx @@ -1,6 +1,6 @@ --- layout: docs -page_title: Service defaults configuration entry reference +page_title: Service defaults configuration reference description: -> Use the service-defaults configuration entry to set default configurations for services, such as upstreams, protocols, and namespaces. Learn how to configure service-defaults. --- @@ -547,7 +547,7 @@ Specifies the Consul namespace that the configuration entry applies to. ### `Partition` -Specifies the name of the name of the Consul admin partition that the configuration entry applies to. Refer to [Admin Partitions](/consul/docs/enterprise/admin-partitions) for additional information. +Specifies the name of the Consul admin partition that the configuration entry applies to. Refer to [Admin Partitions](/consul/docs/enterprise/admin-partitions) for additional information. #### Values @@ -1737,16 +1737,15 @@ Proxy services must be in transparent proxy mode to configure destinations. Refe - ### Enable request rate limit for a service on all paths -The following example limits the request rate on all paths to `service-foo` to an average of `1000` requests per second but allows up to `1500` temporary concurrent requests. +The following example configures the default behavior for a service named `billing`. This configuration limits each instance of the billing service to an average of 1000 requests per second, but allows the service to accept up to 1500 concurrent requests. ```hcl Kind = "service-defaults" -Name = "service-foo" +Name = "billing" Protocol = "http" RateLimit { @@ -1756,21 +1755,21 @@ RateLimit { } } ``` + ```yaml kind: ServiceDefaults -name: service-foo +name: billing protocol: http rateLimit: instanceLevel: requestsPerSecond: 1000 requestsMaxBurst: 1500 - } -} ``` + ```json { "Kind": "service-defaults", - "Name": "service-foo", + "Name": "billing", "Protocol": "http", "RateLimit": { "InstanceLevel": { @@ -1780,6 +1779,7 @@ rateLimit: } } ``` + ### Enable request rate limit on a prefixed path @@ -1840,11 +1840,12 @@ rateLimit: } } ``` + ### Enable request rate limits on multiple paths -The following example limits the request rate to the `billing` service when requests begin with `/api` and `/login`. +The following example configures the default behavior for a service named `billing`. This configuration limits each instance of the billing service depending on the path it received the request on. The service is limited to an average of 500 requests when the request is made on an HTTP path with the `/api` prefix. When an instance of the billing service receives a request from the `/login` path, it is limited to an average of 100 requests per second and 500 concurrent connections. @@ -1883,6 +1884,7 @@ rateLimit: requestsPerSecond: 100 requestsMaxBurst: 500 ``` + ```json { "Kind": "service-defaults", @@ -1905,4 +1907,5 @@ rateLimit: } } ``` + diff --git a/website/content/docs/connect/config-entries/service-intentions.mdx b/website/content/docs/connect/config-entries/service-intentions.mdx index e2f78e488a53..47d980f9a820 100644 --- a/website/content/docs/connect/config-entries/service-intentions.mdx +++ b/website/content/docs/connect/config-entries/service-intentions.mdx @@ -1,11 +1,11 @@ --- layout: docs -page_title: Service intentions configuration entry reference +page_title: Service intentions configuration reference description: >- Use the service intentions configuration entry to allow or deny traffic to services in the mesh from specific sources. Learn how to configure `service-intention` config entries --- -# Service intentions configuration entry reference +# Service intentions configuration reference This topic provides reference information for the service intentions configuration entry. Intentions are configurations for controlling access between services in the service mesh. A single service intentions configuration entry specifies one destination service and one or more L4 traffic sources, L7 traffic sources, or combination of traffic sources. Refer to [Service mesh intentions overview](/consul/docs/connect/intentions) for additional information. @@ -48,7 +48,9 @@ The following outline shows how to format the service intentions configuration e - [`Exact`](#sources-permissions-http-header): string - [`Prefix`](#sources-permissions-http-header): string - [`Suffix`](#sources-permissions-http-header): string - - [`Regex`](#sources-permissions-http-header): string + - [`Contains`](#spec-sources-permissions-http-header): string + - [`Regex`](#spec-sources-permissions-http-header): string + - [`IgnoreCase`](#spec-sources-permissions-http-header): boolean | `false` - [`Invert`](#sources-permissions-http-header): boolean | `false` - [`Precedence`](#sources-precedence): number - [`Type`](#sources-type): string | `consul` @@ -96,7 +98,9 @@ The following outline shows how to format the service intentions configuration e - [`exact`](#spec-sources-permissions-http-header): string | no default - [`prefix`](#spec-sources-permissions-http-header): string | no default - [`suffix`](#spec-sources-permissions-http-header): string | no default + - [`contains`](#spec-sources-permissions-http-header): string | no default - [`regex`](#spec-sources-permissions-http-header): string | no default + - [`ignoreCase`](#spec-sources-permissions-http-header): boolean | `false` - [`invert`](#spec-sources-permissions-http-header): boolean | `false` - [`description`](#spec-sources-description): string @@ -156,18 +160,31 @@ Sources = [ { Name = "" # string Present = # boolean + Invert = # boolean }, { Name = "" # string Exact = "" # boolean + IgnoreCase = # boolean + Invert = # boolean }, { Name = "" # string Prefix = "" # string + IgnoreCase = # boolean + Invert = # boolean }, { Name = "" # string Suffix = "" # string + IgnoreCase = # boolean + Invert = # boolean + }, + { + Name = "" # string + Contains = "" # string + IgnoreCase = # boolean + Invert = # boolean }, { Name = "" # string @@ -227,12 +244,23 @@ spec: header: - name: present: true + invert: false - name: - exact: false + exact: + ignoreCase: false + invert: false - name: prefix: + ignoreCase: false + invert: false - name: suffix: + ignoreCase: false + invert: false + - name: + contains: + ignoreCase: false + invert: false - name: regex: invert: false @@ -287,19 +315,32 @@ spec: "Header":[ { "Name":"", - "Present":true + "Present":true, + "Invert":false + }, + { + "Name":"", + "Exact":"", + "IgnoreCase":false,, + "Invert":false }, { "Name":"", - "Exact":false + "Prefix":"", + "IgnoreCase":false, + "Invert":false }, { "Name":"", - "Prefix":"" + "Suffix":"", + "IgnoreCase":false, + "Invert":false }, { "Name":"", - "Suffix":"" + "Contains":"", + "IgnoreCase":false, + "Invert":false }, { "Name":"", @@ -437,7 +478,7 @@ Specifies the path to the claim in the JSON web token. For more information abou ### `JWT{}.Providers[].VerifyClaims.Value` -Specifies the value to match on when verifying the the claim designated in [`JWT{}.Providers[].VerifyClaims[].Path`](#jwt-providers-verifyclaims-path). +Specifies the value to match on when verifying the claim designated in [`JWT{}.Providers[].VerifyClaims[].Path`](#jwt-providers-verifyclaims-path). #### Values @@ -609,7 +650,9 @@ Each member of the `Header` list is a map that contains a `Name` field and at le | `Exact` | Specifies a value for the header key set in the `Name` field. If the request header value matches the `Exact` value, Consul applies the permission. Do not specify `Exact` if `Present`, `Prefix`, `Suffix`, or `Regex` are configured in the same `Header` configuration. | string | optional | | `Prefix` | Specifies a prefix value for the header key set in the `Name` field. If the request header value starts with the `Prefix` value, Consul applies the permission. Do not specify `Prefix` if `Present`, `Exact`, `Suffix`, or `Regex` are configured in the same `Header` configuration. | string | optional | | `Suffix` | Specifies a suffix value for the header key set in the `Name` field. If the request header value ends with the `Suffix` value, Consul applies the permission. Do not specify `Suffix` if `Present`, `Exact`, `Prefix`, or `Regex` are configured in the same `Header` configuration. | string | optional | -| `Regex` | Specifies a regular expression pattern as the value for the header key set in the `Name` field. If the request header value matches the regex, Consul applies the permission. Do not specify `Regex` if `Present`, `Exact`, `Prefix`, or `Suffix` are configured in the same `Header` configuration. The regex syntax is proxy-specific. If using Envoy, refer to the [re2 documentation](https://github.com/google/re2/wiki/Syntax) for details. | string | optional | +| `Contains` | Specifies a contains value for the header key set in the `Name` field. If the request header value includes the `Contains` value, Consul applies the permission. Do not specify `Contains` if `Present`, `Exact`, `Prefix`, `Suffix`, or `Regex` are configured in the same `header` configuration. | string | optional | +| `Regex` | Specifies a regular expression pattern as the value for the header key set in the `Name` field. If the request header value matches the regex, Consul applies the permission. Do not specify `Regex` if `Present`, `Exact`, `Prefix`, `Suffix`, or `Contains` are configured in the same `Header` configuration. The regex syntax is proxy-specific. If using Envoy, refer to the [re2 documentation](https://github.com/google/re2/wiki/Syntax) for details. | string | optional | +| `IgnoreCase` | Ignores the case of the provided header value when matching with `Exact`, `Prefix`, `Suffix`, or `Contains`. Default is `false`. | boolean | optional | | `Invert` | Inverts the matching logic configured in the `Header`. Default is `false`. | boolean | optional | ### `Sources[].Precedence` @@ -785,7 +828,7 @@ Specifies the path to the claim in the JSON web token. For more information abou ### `spec.jwt.providers[].verifyClaims[].value` -Specifies the value to match on when verifying the the claim designated in [`JWT{}.Providers[].VerifyClaims[].Path`](#jwt-providers-verifyclaims-path). +Specifies the value to match on when verifying the claim designated in [`JWT{}.Providers[].VerifyClaims[].Path`](#jwt-providers-verifyclaims-path). #### Values @@ -923,16 +966,22 @@ Specifies a set of criteria for matching HTTP request headers. The request heade - Default: None - Data type: List of maps -Each member of the `header` list is a map that contains a `name` field and at least one match criterion. The following table describes the parameters that each member of the `header` list may contain: +Each member of the `header` list is a map that contains a `name` field and at least one match criterion. + +~> **Warning**: If it is possible for a header to contain multiple values, we recommend using `contains` or `regex` rather than `exact`, `prefix`, or `suffix`. Envoy internally concatenates multiple header values into a single CSV value prior to applying match rules, which may result in match rules that depend on the beginning or end of a string vulnerable to circumvention. A more robust alternative is using `contains` or, if a stricter value match is required, configuring a regex pattern that is tolerant of comma-separated values. These options are available as of Consul CE 1.20.1 and Consul Enterprise 1.20.1, 1.19.2, 1.18.3, and 1.15.15. + +The following table describes the parameters that each member of the `header` list may contain: | Parameter | Description | Data type | Required | | --- | --- | --- | --- | | `name` | Specifies the name of the header to match. | string | required | -| `present` | Enables a match if the header configured in the `name` field appears in the request. Consul matches on any value as long as the header key appears in the request. Do not specify `present` if `exact`, `prefix`, `suffix`, or `regex` are configured in the same `header` configuration. | boolean | optional | -| `Exact` | Specifies a value for the header key set in the `Name` field. If the request header value matches the `exact` value, Consul applies the permission. Do not specify `exact` if `present`, `prefix`, `suffix`, or `regex` are configured in the same `header` configuration. | string | optional | -| `prefix` | Specifies a prefix value for the header key set in the `name` field. If the request header value starts with the `prefix` value, Consul applies the permission. Do not specify `prefix` if `present`, `exact`, `suffix`, or `regex` are configured in the same `header` configuration. | string | optional | -| `suffix` | Specifies a suffix value for the header key set in the `name` field. If the request header value ends with the `suffix` value, Consul applies the permission. Do not specify `suffix` if `present`, `exact`, `prefix`, or `regex` are configured in the same `header` configuration. | string | optional | -| `regex` | Specifies a regular expression pattern as the value for the header key set in the `name` field. If the request header value matches the regex, Consul applies the permission. Do not specify `regex` if `present`, `exact`, `prefix`, or `suffix` are configured in the same `header` configuration. The regex syntax is proxy-specific. If using Envoy, refer to the [re2 documentation](https://github.com/google/re2/wiki/Syntax) for details. | string | optional | +| `present` | Enables a match if the header configured in the `name` field appears in the request. Consul matches on any value as long as the header key appears in the request. Do not specify `present` if `exact`, `prefix`, `suffix`, `contains`, or `regex` are configured in the same `header` configuration. | boolean | optional | +| `Exact` | Specifies a value for the header key set in the `Name` field. If the request header value matches the `exact` value, Consul applies the permission. Do not specify `exact` if `present`, `prefix`, `suffix`, `contains`, or `regex` are configured in the same `header` configuration. | string | optional | +| `prefix` | Specifies a prefix value for the header key set in the `name` field. If the request header value starts with the `prefix` value, Consul applies the permission. Do not specify `prefix` if `present`, `exact`, `suffix`, `contains`, or `regex` are configured in the same `header` configuration. | string | optional | +| `suffix` | Specifies a suffix value for the header key set in the `name` field. If the request header value ends with the `suffix` value, Consul applies the permission. Do not specify `suffix` if `present`, `exact`, `prefix`, `contains`, or `regex` are configured in the same `header` configuration. | string | optional | +| `contains` | Specifies a contains value for the header key set in the `name` field. If the request header value includes the `contains` value, Consul applies the permission. Do not specify `contains` if `present`, `exact`, `prefix`, `suffix`, or `regex` are configured in the same `header` configuration. | string | optional | +| `regex` | Specifies a regular expression pattern as the value for the header key set in the `name` field. If the request header value matches the regex, Consul applies the permission. Do not specify `regex` if `present`, `exact`, `prefix`, `suffix`, or `contains` are configured in the same `header` configuration. The regex syntax is proxy-specific. If using Envoy, refer to the [re2 documentation](https://github.com/google/re2/wiki/Syntax) for details. | string | optional | +| `ignoreCase` | Ignores the case of the provided header value when matching with exact, prefix, suffix, or contains. Default is `false`. | boolean | optional | | `invert` | Inverts the matching logic configured in the `header`. Default is `false`. | boolean | optional | ### `spec.sources[].type` diff --git a/website/content/docs/connect/config-entries/service-resolver.mdx b/website/content/docs/connect/config-entries/service-resolver.mdx index fa92e08d6cef..bce568514d6c 100644 --- a/website/content/docs/connect/config-entries/service-resolver.mdx +++ b/website/content/docs/connect/config-entries/service-resolver.mdx @@ -1,11 +1,11 @@ --- layout: docs -page_title: Service Resolver Configuration Entry Reference +page_title: Service Resolver configuration reference description: >- Service resolver configuration entries are L7 traffic management tools for defining sets of service instances that resolve upstream requests and Consul’s behavior when resolving them. Learn how to write `service-resolver` config entries in HCL or YAML with a specification reference, configuration model, a complete example, and example code by use case. --- -# Service resolver configuration entry reference +# Service resolver configuration reference This page provides reference information for service resolver configuration entries. Configure and apply service resolvers to create named subsets of service instances and define their behavior when satisfying upstream requests. @@ -1113,7 +1113,7 @@ For examples, refer to the [failover example configurations](#service-failover). - [`namespace`](#spec-failover-targets-namespace) - [`partition`](#spec-failover-targets-partition) - [`datacenter`](#spec-failover-targets-datacenter) - - [`peer](#spec-failover-targets-peer) + - [`peer`](#spec-failover-targets-peer) ### `spec.failover.targets.service` diff --git a/website/content/docs/connect/config-entries/service-router.mdx b/website/content/docs/connect/config-entries/service-router.mdx index 2888bc3a79ec..d384b83be39c 100644 --- a/website/content/docs/connect/config-entries/service-router.mdx +++ b/website/content/docs/connect/config-entries/service-router.mdx @@ -1,11 +1,11 @@ --- layout: docs -page_title: Service Router Configuration Entry Reference +page_title: Service Router configuration reference description: >- Service router configuration entries are L7 traffic management tools for redirecting requests for a service to a particular instance or set of instances. Learn how to write `service-router` config entries in HCL or YAML with a specification reference, configuration model, a complete example, and example code by use case. --- -# Service router configuration entry reference +# Service router configuration reference This page provides reference information for service router configuration entries. Service routers use L7 network information to redirect a traffic request for a service to one or more specific service instances. @@ -30,6 +30,7 @@ The following list outlines field hierarchy, language-specific data types, and r - [`PathExact`](#routes-match-http-pathexact): string - [`PathPrefix`](#routes-match-http-pathprefix): string - [`PathRegex`](#routes-match-http-pathregex): string + - [`CaseInsensitive`](#routes-match-http-caseinsensitive): boolean | `false` - [`Methods`](#routes-match-http-methods): list - [`Header`](#routes-match-http-header): list - [`Name`](#routes-match-http-header-name): string @@ -456,6 +457,15 @@ Specifies the path prefix to match on the HTTP request path. When using this fie - Default: None - Data type: String +### `Routes[].Match{}.HTTP{}.CaseInsensitive` + +Specifies the path prefix to match on the HTTP request path must be case insensitive or not. + +#### Values + +- Default: `false` +- Data type: Boolean + ### `Routes[].Match{}.HTTP{}.PathRegex` Specifies a regular expression to match on the HTTP request path. When using this field, do not configure `PathExact` or `PathPrefix` in the same HTTP map. The syntax for the regular expression field is proxy-specific. When [using Envoy](/consul/docs/connect/proxies/envoy), refer to [the documentation for Envoy v1.11.2 or newer](https://github.com/google/re2/wiki/Syntax) or [the documentation for Envoy v1.11.1 or older](https://en.cppreference.com/w/cpp/regex/ecmascript), depending on the version of Envoy you use. @@ -1372,6 +1382,78 @@ spec: +### Path prefix matching with case insensitive + +The following example routes HTTP requests for the `web` service to a service named `admin` when they have `/admin` or `/Admin` at the start of their path. + + + + +```hcl +Kind = "service-router" +Name = "web" +Routes = [ + { + Match { + HTTP { + PathPrefix = "/Admin" + CaseInsensitive = true + } + } + + Destination { + Service = "admin" + } + }, +] +``` + + + + + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: ServiceRouter +metadata: + name: web +spec: + routes: + - match: + http: + pathPrefix: /Admin + caseInsensitive: true + destination: + service: admin +``` + + + + + +```json +{ + "Kind": "service-router", + "Name": "web", + "Routes": [ + { + "Match": { + "HTTP": { + "PathPrefix": "/Admin", + "CaseInsensitive": true + } + }, + "Destination": { + "Service": "admin" + } + } + ] +} +``` + + + + ### Match a header and query parameter The following example routes HTTP traffic to the `web` service to a subset of `canary` instances when the requests have `x-debug` in either the header or the URL parameter. diff --git a/website/content/docs/connect/config-entries/service-splitter.mdx b/website/content/docs/connect/config-entries/service-splitter.mdx index 5d94a4e38a22..f7247be924c2 100644 --- a/website/content/docs/connect/config-entries/service-splitter.mdx +++ b/website/content/docs/connect/config-entries/service-splitter.mdx @@ -1,13 +1,13 @@ --- layout: docs -page_title: Service Splitter Configuration Entry Reference +page_title: Service Splitter configuration reference description: >- Service splitter configuration entries are L7 traffic management tools for redirecting requests for a service to multiple instances. Learn how to write `service-splitter` config entries in HCL or YAML with a specification reference, configuration model, a complete example, and example code by use case. --- -# Service Splitter Configuration Reference +# Service Splitter configuration reference This reference page describes the structure and contents of service splitter configuration entries. Configure and apply service splitters to redirect a percentage of incoming traffic requests for a service to one or more specific service instances. diff --git a/website/content/docs/connect/config-entries/tcp-route.mdx b/website/content/docs/connect/config-entries/tcp-route.mdx index e573a0183a76..e7eda8c1ccb2 100644 --- a/website/content/docs/connect/config-entries/tcp-route.mdx +++ b/website/content/docs/connect/config-entries/tcp-route.mdx @@ -1,10 +1,10 @@ --- layout: docs -page_title: TCP Route Configuration Reference +page_title: TCP Route configuration reference description: Learn how to configure a TCP Route that is bound to an API gateway on VMs. --- -# TCP route configuration Reference +# TCP route configuration reference This topic provides reference information for the gateway TCP routes configuration entry. Refer to [Route Resource Configuration](/consul/docs/connect/gateways/api-gateway/configuration/routes) for information diff --git a/website/content/docs/connect/config-entries/terminating-gateway.mdx b/website/content/docs/connect/config-entries/terminating-gateway.mdx index 36b1a2dc2073..4512cf1a8148 100644 --- a/website/content/docs/connect/config-entries/terminating-gateway.mdx +++ b/website/content/docs/connect/config-entries/terminating-gateway.mdx @@ -679,6 +679,12 @@ spec: `An optional hostname or domain name to specify during the TLS handshake. This option will also configure [strict SAN matching](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#envoy-v3-api-field-extensions-transport-sockets-tls-v3-certificatevalidationcontext-match-typed-subject-alt-names), which requires the external services to have certificates with SANs, not having which will result in \`CERTIFICATE_VERIFY_FAILED\` error.`, }, + { + name: 'DisableAutoHostRewrite', + type: 'bool: ""', + description: + 'When set to true, Terminating Gateway will not modify the incoming requests host header for this service.', + }, ], }, ]} diff --git a/website/content/docs/connect/dataplane/index.mdx b/website/content/docs/connect/dataplane/index.mdx index f2eaa4eb7894..30996e347674 100644 --- a/website/content/docs/connect/dataplane/index.mdx +++ b/website/content/docs/connect/dataplane/index.mdx @@ -87,7 +87,7 @@ $ export VERSION=1.0.0 && \ Refer to the following documentation for Consul on ECS workloads: - [Deploy Consul with the Terraform module](/consul/docs/ecs/deploy/terraform) -- [Deploy Consul manually](/consul/ecs/install-manul) +- [Deploy Consul manually](/consul/docs/ecs/deploy/manual) @@ -121,7 +121,7 @@ Consul Dataplane on Kubernetes supports the following features: - Running Consul service mesh in AWS Fargate and GKE Autopilot is supported. - xDS load balancing is supported. - Servers running in Kubernetes and servers external to Kubernetes are both supported. -- HCP Consul is supported. +- HCP Consul Dedicated and HCP Consul Central are supported. - Consul API Gateway Consul Dataplane on ECS support the following features: @@ -130,7 +130,7 @@ Consul Dataplane on ECS support the following features: - Mesh gateways - Running Consul service mesh in AWS Fargate and EC2 - xDS load balancing -- Self-managed and HCP Consul managed servers +- Self-managed Enterprise and HCP Consul Dedicated servers ### Technical Constraints diff --git a/website/content/docs/connect/gateways/api-gateway/configuration/gateway.mdx b/website/content/docs/connect/gateways/api-gateway/configuration/gateway.mdx index 60825a3a91fd..2ea1d1e64eeb 100644 --- a/website/content/docs/connect/gateways/api-gateway/configuration/gateway.mdx +++ b/website/content/docs/connect/gateways/api-gateway/configuration/gateway.mdx @@ -221,10 +221,10 @@ The following example creates a `Gateway` named `example-gateway` in namespace ` - group: gateway.networking.k8s.io kind: Gateway namespace: gateway-namespace - to: - - group: "" - kind: Secret - name: cert + to: + - group: "" + kind: Secret + name: cert ``` diff --git a/website/content/docs/connect/gateways/api-gateway/configuration/gatewayclassconfig.mdx b/website/content/docs/connect/gateways/api-gateway/configuration/gatewayclassconfig.mdx index 2fa35a75521e..612875db4f78 100644 --- a/website/content/docs/connect/gateways/api-gateway/configuration/gatewayclassconfig.mdx +++ b/website/content/docs/connect/gateways/api-gateway/configuration/gatewayclassconfig.mdx @@ -28,8 +28,8 @@ The following outline shows how to format the configurations in the `GatewayClas * [`grpc`](#consul-ports-grpc): integer | optional * [`http`](#consul-ports-http): integer | optional * [`scheme`](#consul-scheme): string | optional -* [`copyAnnotations`](#copyAnnotations): object | optional - * [`service`](#copyAnnotations-service): array of strings | optional +* [`copyAnnotations`](#copyannotations): object | optional + * [`service`](#copyannotations-service): array of strings | optional * [`deployment`](#deployment): object | optional * [`defaultInstances`](#deployment-defaultinstances): integer | optional * [`maxInstances`](#deployment-maxinstances): integer | optional @@ -38,9 +38,9 @@ The following outline shows how to format the configurations in the `GatewayClas * [`consulAPIGateway`](#image-consulapigateway): string | optional * [`envoy`](#image-envoy): string | optional * [`logLevel`](#loglevel): string | optional -* [`matchPrivilegedContainerPorts`](#matchPrivilegedContainerPorts): integer | optional +* [`mapPrivilegedContainerPorts`](#mapprivilegedcontainerports): integer | optional * [`nodeSelector`](#nodeselector): string | optional -* [`openshiftSCCName`](#openshiftSCCName): string | optional +* [`openshiftSCCName`](#openshiftsccname): string | optional * [`serviceType`](#servicetype): string | optional * [`useHostPorts`](#usehostports): boolean | optional @@ -154,8 +154,8 @@ You can specify the following strings: * `debug` * `trace` -### matchPrivilegedContainerPorts -Specifies a value that Consul adds to privileged ports defined in the gateway. Privileged ports are port numbers less than 1024 and some platforms, such as Red Hat OpenShift, explicitly configure Kubernetes to avoid running containers on privileged ports. The total value of the configured port number and the `matchPriviledgedContainerPorts` value must not exceed 65535, which is the highest possible TCP port number allowed. +### mapPrivilegedContainerPorts +Specifies a value that Consul adds to privileged ports defined in the gateway. Privileged ports are port numbers less than 1024 and some platforms, such as Red Hat OpenShift, explicitly configure Kubernetes to avoid running containers on privileged ports. The total value of the configured port number and the `mapPrivilegedContainerPorts` value must not exceed 65535, which is the highest possible TCP port number allowed. for gateway containers * Type: Integer * Required: optional diff --git a/website/content/docs/connect/gateways/api-gateway/configuration/gatewaypolicy.mdx b/website/content/docs/connect/gateways/api-gateway/configuration/gatewaypolicy.mdx index dc638fbf7208..f74a9ed77cd8 100644 --- a/website/content/docs/connect/gateways/api-gateway/configuration/gatewaypolicy.mdx +++ b/website/content/docs/connect/gateways/api-gateway/configuration/gatewaypolicy.mdx @@ -1,7 +1,7 @@ --- layout: docs page_title: GatewayPolicy configuration reference -description: Learn about the configuration options for the GatewayPolicy configuration resource. GatewayPolicy resources define API gateway polcies for Consul service mesh on Kubernetes. +description: Learn about the configuration options for the GatewayPolicy configuration resource. GatewayPolicy resources define API gateway policies for Consul service mesh on Kubernetes. --- # GatewayPolicy @@ -15,33 +15,33 @@ The following list outlines field hierarchy, data types, and requirements in a g - [`apiVersion`](#apiversion): string | required | must be set to `consul.hashicorp.com/v1alpha1` - [`kind`](#kind): string | required | must be set to `GatewayPolicy` - [`metadata`](#metadata): map | required - - [`name`](#metadata-name): string | required + - [`name`](#metadata-name): string | required - [`namespace`](#metadata-namespace): string | `default` - [`spec`](#spec): map | required - [`targetRef`](#spec-targetref): map | required - - [`namespace`](#spec-targetref): string | `default` - - [`name`](#spec-targetref): string | required + - [`namespace`](#spec-targetref): string | `default` + - [`name`](#spec-targetref): string | required - [`kind`](#spec-targetref): string | required | must be set to `Gateway` - - [`group`](#spec-targetref): string | required - - [`sectionName`](#spec-targetref): string - - [`override`](#spec-override): map | required - - [`jwt`](#spec-override-jwt): map | required - - [`providers`](#spec-override-providers): list | required - - [`name`](#spec-override-providers): string | required - - [`verifyClaims`](#spec-override-providers): map | required - - [`path`](#spec-override-providers): list of strings | required - - [`value`](#spec-override-providers): string | required - - [`default`](#spec-default): map | required - - [`jwt`](#spec-default-jwt): map | required - - [`providers`](#spec-default-providers): list | required - - [`name`](#spec-default-providers): string | required - - [`verifyClaims`](#spec-default-providers): map | required - - [`path`](#spec-default-providers): list of strings | required - - [`value`](#spec-default-providers): string | required + - [`group`](#spec-targetref): string | required + - [`sectionName`](#spec-targetref): string + - [`override`](#spec-override): map | required + - [`jwt`](#spec-override-jwt): map | required + - [`providers`](#spec-override-providers): list | required + - [`name`](#spec-override-providers): string | required + - [`verifyClaims`](#spec-override-providers): map | required + - [`path`](#spec-override-providers): list of strings | required + - [`value`](#spec-override-providers): string | required + - [`default`](#spec-default): map | required + - [`jwt`](#spec-default-jwt): map | required + - [`providers`](#spec-default-providers): list | required + - [`name`](#spec-default-providers): string | required + - [`verifyClaims`](#spec-default-providers): map | required + - [`path`](#spec-default-providers): list of strings | required + - [`value`](#spec-default-providers): string | required ## Complete configuration -When every field is defined, a gateway policy has the following form: +When every field is defined, a gateway policy has the following form: ```yaml apiVersion: consul.hashicorp.com/v1alpha1 @@ -53,7 +53,7 @@ spec: targetRef: name: gateway kind: Gateway - group: gateway.networking.kuberenetes.io + group: gateway.networking.k8s.io/v1beta1 sectionName: override: jwt: @@ -109,7 +109,7 @@ Map that contains an arbitrary name for the resource and the namespace it applie ### `metadata.name` -Specifies a name for the resource. The name is metadata that you can use to reference the resource when performing Consul operations, such as applying the resource to a specific cluster. +Specifies a name for the resource. The name is metadata that you can use to reference the resource when performing Consul operations, such as applying the resource to a specific cluster. #### Values @@ -117,7 +117,7 @@ Specifies a name for the resource. The name is metadata that you can use to refe - This field is required. - Data type: String -### `metadata.namespace` +### `metadata.namespace` Specifies the namespace that the configuration applies to. Refer to [namespaces](/consul/docs/enterprise/namespaces) for more information. @@ -138,7 +138,7 @@ Map that contains the details about the gateway policy. The `apiVersion`, `kind` ### `targetRef` -Map that contains references to the gateway that the policy applies to. +Map that contains references to the gateway that the policy applies to. #### Values @@ -153,7 +153,7 @@ The following table describes the members of the `targetRef` map: | `namespace` | Specifies the namespace that the target reference is a member of. | String | `default` | | `name` | Specifies the name of the API gateway that the policy attaches to. | String | None | | `kind` | Specifies the type of resource that the policy attaches to. Must be set to `Gateway`. | String | None | -| `group` | Specifies the resource group. Must be set to `gateway.networking.kuberenetes.io`. | String | None | +| `group` | Specifies the resource group. Must be set to `gateway.networking.k8s.io/v1beta1`. | String | None | | `sectionName` | Specifies a part of the gateway that the policy applies to. | String | None | ### `spec.override` @@ -192,7 +192,7 @@ The following table describes the parameters you can specify in a member of the ### `spec.default` -Map that contains default configurations to apply to listeners when the policy is attached to the gateway. All routes attached to the gateway listener inherit the default configurations. You can specify override configurations that have precedence over default configurations. Refer to [`spec.override`](#spec-override) for details. +Map that contains default configurations to apply to listeners when the policy is attached to the gateway. All routes attached to the gateway listener inherit the default configurations. You can specify override configurations that have precedence over default configurations. Refer to [`spec.override`](#spec-override) for details. #### Values @@ -226,7 +226,7 @@ The following table describes the parameters you can specify in a member of the ## Example configuration -In the following example, all requests through the gateway must have the `api.apps.organization.com` audience claim. Additionally, requests through the gateway must have a `user` role by default. +In the following example, all requests through the gateway must have the `api.apps.organization.com` audience claim. Additionally, requests through the gateway must have a `user` role by default. ```yaml apiVersion: consul.hashicorp.com/v1alpha1 @@ -237,7 +237,7 @@ spec: targetRef: name: gateway kind: Gateway - group: gateway.networking.kuberenetes.io + group: gateway.networking.k8s.io/v1beta1 sectionName: to-server override: jwt: @@ -256,4 +256,4 @@ spec: - "roles" - "perm" value: "user" -``` \ No newline at end of file +``` diff --git a/website/content/docs/connect/gateways/api-gateway/configuration/index.mdx b/website/content/docs/connect/gateways/api-gateway/configuration/index.mdx index b73fec3b9fe3..f6fc99d05de8 100644 --- a/website/content/docs/connect/gateways/api-gateway/configuration/index.mdx +++ b/website/content/docs/connect/gateways/api-gateway/configuration/index.mdx @@ -7,7 +7,7 @@ description: >- # Consul API gateway configuration overview -This topic provides an overview of the configuration items you can use to create API gateways, configure listeners, define routes, and apply additional resources that may be necessary to operate Consul API gateways in your environment. +This topic provides an overview of the configuration items you can use to create API gateways, configure listeners, define routes, and apply additional resources that may be necessary to operate Consul API gateways in your environment. ## Configurations for virtual machines @@ -18,9 +18,10 @@ Apply the following configuration items if your network runs on virtual machines | [`api-gateway`](/consul/docs/connect/config-entries/api-gateway) | Defines the main infrastructure resource for declaring an API gateway and listeners on the gateway. | [Deploy API gateway listeners on virtual machines](/consul/docs/connect/gateways/api-gateway/deploy/listeners-vms) | | [`http-route`](/consul/docs/connect/config-entries/http-route) | Enables HTTP traffic to reach services in the mesh from a listener on the gateway.| [Define routes on virtual machines](/consul/docs/connect/gateways/api-gateway/define-routes/routes-vms) | | [`tcp-route`](/consul/docs/connect/config-entries/tcp-route) | Enables TCP traffic to reach services in the mesh from a listener on the gateway.| [Define routes on virtual machines](/consul/docs/connect/gateways/api-gateway/define-routes/routes-vms) | -| [`inline-certificate`](/consul/docs/connect/config-entries/inline-certificate) | Provides gateway artificats with a CA certificate so that requests between the user and the gateway endpoint are encrypted. | [Encrypt API gateway traffic on virtual machines](/consul/docs/connect/gateways/api-gateway/secure-traffic/encrypt-vms) | +| [`file-system-certificate`](/consul/docs/connect/config-entries/file-system-certificate) | Provides gateway with a CA certificate so that requests between the user and the gateway endpoint are encrypted. | [Encrypt API gateway traffic on virtual machines](/consul/docs/connect/gateways/api-gateway/secure-traffic/encrypt-vms) | +| [`inline-certificate`](/consul/docs/connect/config-entries/inline-certificate) | Provides gateway with a CA certificate so that requests between the user and the gateway endpoint are encrypted. | [Encrypt API gateway traffic on virtual machines](/consul/docs/connect/gateways/api-gateway/secure-traffic/encrypt-vms) | | [`service-intentions`](/consul/docs/connect/config-entries/service-intentions) | Specifies traffic communication rules between services in the mesh. Intentions also enforce rules for service-to-service traffic routed through a Consul API gateway. | General configuration for securing a service mesh | - + ## Configurations for Kubernetes Apply the following configuration items if your network runs on Kubernetes: @@ -32,7 +33,7 @@ Apply the following configuration items if your network runs on Kubernetes: | [`GatewayClassConfig`](/consul/docs/connect/gateways/api-gateway/configuration/gatewayclassconfig) | Describes additional gateway-related configuration parameters for the `GatewayClass` resource. | [Deploy listeners on Kubernetes](/consul/docs/connect/gateways/api-gateway/deploy/listeners-k8s) | | [`Routes`](/consul/docs/connect/gateways/api-gateway/configuration/routes) | Specifies paths from the gateway listener to backend services. | [Define routes on Kubernetes](/consul/docs/connect/gateways/api-gateway/define-routes/routes-k8s)

      [Reroute traffic in Kubernetes](/consul/docs/connect/gateways/api-gateway/define-routes/reroute-http-requests)

      [Route traffic to peered services in Kubernetes](/consul/docs/connect/gateways/api-gateway/define-routes/route-to-peered-services)

      | | [`MeshServices`](/consul/docs/connect/gateways/api-gateway/configuration/meshservices) | Enables routes to reference services in Consul. | [Route traffic to peered services in Kubernetes](/consul/docs/connect/gateways/api-gateway/define-routes/route-to-peered-services) | -| [`ServiceIntentions`](/consul/docs/connect/config-entries/service-intentions) | Specifies traffic communication rules between services in the mesh. Intentions also enforce rules for service-to-service traffic routed through a Consul API gateway. | General configuration for securing a service mesh | +| [`ServiceIntentions`](/consul/docs/connect/config-entries/service-intentions) | Specifies traffic communication rules between services in the mesh. Intentions also enforce rules for service-to-service traffic routed through a Consul API gateway. | General configuration for securing a service mesh | + [tech-specs]: /consul/docs/api-gateway/tech-specs [rel-notes]: /consul/docs/release-notes diff --git a/website/content/docs/connect/gateways/api-gateway/secure-traffic/encrypt-vms.mdx b/website/content/docs/connect/gateways/api-gateway/secure-traffic/encrypt-vms.mdx index 3520dfbc2ee5..fd1cdfe86cb0 100644 --- a/website/content/docs/connect/gateways/api-gateway/secure-traffic/encrypt-vms.mdx +++ b/website/content/docs/connect/gateways/api-gateway/secure-traffic/encrypt-vms.mdx @@ -1,7 +1,7 @@ --- layout: docs page_title: Encrypt API gateway traffic on virtual machines -description: Learn how to define inline certificate config entries and deploy them to Consul. Inline certificate configuration entries enable you to attach TLS certificates and keys to gateway listeners so that traffic between external clients and gateway listeners is encrypted. +description: Learn how to define inline certificate config entries and deploy them to Consul. Inline certificate and file system certificate configuration entries enable you to attach TLS certificates and keys to gateway listeners so that traffic between external clients and gateway listeners is encrypted. --- # Encrypt API gateway traffic on virtual machines @@ -10,8 +10,9 @@ This topic describes how to make TLS certificates available to API gateways so t ## Requirements -- Consul 1.15 or later -- You must have a certificate and key from your CA +- Consul v1.15 or later is required to use the Consul API gateway on VMs + - Consul v1.19 or later is required to use the [file system certificate configuration entry](/consul/docs/connect/config-entries/file-system-certificate) +- You must have a certificate and key from your CA - A Consul cluster with service mesh enabled. Refer to [`connect`](/consul/docs/agent/config/config-files#connect) - Network connectivity between the machine deploying the API gateway and a Consul cluster agent or server @@ -30,14 +31,20 @@ with Consul API gateway configurations. ## Define TLS certificates -1. Create an [`inline-certificate` configuration entry](/consul/docs/connect/gateways/api-gateway/configuration/inline-certificate) and specify the following fields: - - `Kind`: Specifies the type of configuration entry. This must be set to `inline-certificate`. +1. Create a [file system certificate](/consul/docs/connect/config-entries/file-system-certificate) or [inline certificate](/consul/docs/connect/config-entries/inline-certificate) and specify the following fields: + - `Kind`: Specifies the type of configuration entry. This must be set to `file-system-certificate` or `inline-certificate`. - `Name`: Specify the name in the [API gateway listener configuration](/consul/docs/connect/gateways/api-gateway/configuration/api-gateway#listeners) to bind the certificate to that listener. - - `Certificate`: Specifies the inline public certificate to use for TLS as plain text. - - `PrivateKey`: Specifies the inline private key to use for TLS as plain text. -1. Configure any additional fields necessary for your use case, such as the namespace or admin partition. Refer to the [`inline-certificate` configuration entry](/consul/docs/connect/gateways/api-gateway/configuration/inline-certificate) reference for additional information. + - `Certificate`: Specifies the filepath to the certificate on the local system or the inline public certificate as plain text. + - `PrivateKey`: Specifies the filepath to private key on the local system or the inline private key to as plain text. +1. Configure any additional fields necessary for your use case, such as the namespace or admin partition. Refer to the [file system certificate configuration reference](/consul/docs/connect/config-entries/file-system-certificate) or [inline certificate configuration reference](/consul/docs/connect/config-entries/inline-certificate) for more information. 1. Save the configuration. +### Examples + + + + + The following example defines a certificate named `my-certificate`. API gateway configurations that specify `inline-certificate` in the `Certificate.Kind` field and `my-certificate` in the `Certificate.Name` field are able to use the certificate. ```hcl @@ -57,6 +64,22 @@ PrivateKey = < + + + +The following example defines a certificate named `my-certificate`. API gateway configurations that specify `file-system-certificate` in the `Certificate.Kind` field and `my-certificate` in the `Certificate.Name` field are able to use the certificate. + +```hcl +Kind = "file-system-certificate" +Name = "my-certificate" +Certificate = "/opt/consul/tls/api-gateway.crt" +PrivateKey = "/opt/consul/tls/api-gateway.key" +``` + + + + ## Deploy the configuration to Consul Run the `consul config write` command to enable listeners to use the certificate. The following example writes a configuration called `my-certificate.hcl`: diff --git a/website/content/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-k8s.mdx b/website/content/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-k8s.mdx index 6c60302165d5..6bd8f28ccd84 100644 --- a/website/content/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-k8s.mdx +++ b/website/content/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-k8s.mdx @@ -6,25 +6,26 @@ description: Learn how to use JSON web tokens (JWT) to verify requests from exte # Use JWTs to verify requests to API gateways on Kubernetes -This topic describes how to use JSON web tokens (JWT) to verify requests to API gateways deployed to Kubernetes-orchestrated containers. If your API gateway is deployed to virtual machines, refer to [Use JWTs to verify requests to API gateways on VMs](/consu/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms). +This topic describes how to use JSON web tokens (JWT) to verify requests to API gateways deployed to Kubernetes-orchestrated containers. If your API gateway is deployed to virtual machines, refer to [Use JWTs to verify requests to API gateways on VMs](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms). This feature is available in Consul Enterprise. ## Overview - + You can configure API gateways to use JWTs to verify incoming requests so that you can stop unverified traffic at the gateway. You can configure JWT verification at different levels: -- Listener defaults: Define basic defaults that apply to all routes attached to a listener. -- HTTP route-specific settings: You can define JWT authentication settings for specific HTTP routes. Route-specific JWT settings override default listener configurations. -- Listener overrides: Define override settings that take precedence over default and route-specific configurations. This enables you to set enforceable policies for listeners. +- Listener defaults: Define basic defaults in a GatewayPolicy resource to apply them to all routes attached to a listener. +- HTTP route-specific settings: You can define JWT authentication settings for specific HTTP routes. Route-specific JWT settings override default listener configurations. +- Listener overrides: Define override settings in a GatewayPolicy resource that take precedence over default and route-specific configurations. Use override settings to set enforceable policies for listeners. Complete the following steps to use JWTs to verify requests: -1. Define a policy that specifies default and override settings for API gateway listeners and attach it to the gateway. -1. Define an HTTP route auth filter that specifies route-specific JWT verification settings. -1. Attach the auth filter to the HTTP route values file. -1. Apply the configurations. +1. Define a JWTProvider that specifies the JWT provider and claims used to verify requests to the gateway. +1. Define a GatewayPolicy that specifies default and override settings for API gateway listeners and attach it to the gateway. +1. Define a RouteAuthFilter that specifies route-specific JWT verification settings. +1. Reference the RouteAuthFilter from the HTTPRoute. +1. Apply the configurations. ## Requirements @@ -33,42 +34,193 @@ Complete the following steps to use JWTs to verify requests: - Consul on Kubernetes CLI or Helm chart v1.3.0+ - JWT details, such as claims and provider -## Define override and default settings -Create a `GatewayPolicy` values file and configure the following fields to define default and override settings for JWT verification. Refer to [`GatewayPolicy` configuration reference](/consul/docs/connect/gateways/api-gateway/configuration/gatewaypolicy) for details. +## Define a JWTProvider + +Create a `JWTProvider` CRD that defines the JWT provider to verify claims against. + +In the following example, the JWTProvider CRD contains a local JWKS. In production environments, use a production-grade JWKs endpoint instead. + + + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: JWTProvider +metadata: + name: local +spec: + issuer: local + jsonWebKeySet: + local: + jwks: "" +``` + + + +For more information about the fields you can configure in this CRD, refer to [`JWTProvider` configuration reference](/consul/docs/connect/config-entries/jwtprovider). + +## Define a GatewayPolicy + +Create a `GatewayPolicy` CRD that defines default and override settings for JWT verification. - `kind`: Must be set to `GatewayPolicy` - `metadata.name`: Specifies a name for the policy. - `spec.targetRef.name`: Specifies the name of the API gateway to attach the policy to. -- `spec.targetRef.kind`: Specifies the kind of resource to attach to the policy to. Must be set to `Gateway`. -- `spec.targetRef.group`: Specifies the resource group. Unless you have created a custom group, this should be set to `gateway.networking.kuberenetes.io`. +- `spec.targetRef.kind`: Specifies the kind of resource to attach to the policy to. Must be set to `Gateway`. +- `spec.targetRef.group`: Specifies the resource group. Unless you have created a custom group, this should be set to `gateway.networking.k8s.io/v1beta1`. - `spec.targetRef.sectionName`: Specifies a part of the gateway that the policy applies to. -- `spec.targetRef.override.jwt.providers`: Specifies a list of providers and claims used to verify requests to the gateway. The override settings take precedence over the default and route-specific JWT verification settings. -- `spec.targetRef.default.jwt.providers`: Specifies a list of default providers and claims used to verify requests to the gateway. +- `spec.targetRef.override.jwt.providers`: Specifies a list of providers and claims used to verify requests to the gateway. The override settings take precedence over the default and route-specific JWT verification settings. +- `spec.targetRef.default.jwt.providers`: Specifies a list of default providers and claims used to verify requests to the gateway. + +The following examples configure a Gateway and the GatewayPolicy being attached to it so that every request coming through the listener must meet these conditions: + +- The request must be signed by the `local` provider +- The request must have a claim of `role` with a value of `user` unless the HTTPRoute attached to the listener overrides it + + + + + + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: api-gateway +spec: + gatewayClassName: consul + listeners: + - protocol: HTTP + port: 30002 + name: listener-one +``` -## Define an HTTP route auth filter + + + + + + + + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: GatewayPolicy +metadata: + name: gw-policy +spec: + targetRef: + name: api-gateway + sectionName: listener-one + group: gateway.networking.k8s.io/v1beta1 + kind: Gateway + override: + jwt: + providers: + - name: "local" + default: + jwt: + providers: + - name: "local" + verifyClaims: + - path: + - role + value: user +``` + + + + + -Create an `RouteAuthFilter` values file and configure the following fields. Refer to [`RouteAuthFilter` configuration reference](/consul/docs/connect/gateways/api-gateway/configuration/routeauthfilter) for details. +For more information about the fields you can configure, refer to [`GatewayPolicy` configuration reference](/consul/docs/connect/gateways/api-gateway/configuration/gatewaypolicy). -- `kind`: Must be set to `HTTPRouteAuthFilter` +## Define a RouteAuthFilter + +Create an `RouteAuthFilter` CRD that defines overrides for the default JWT verification configured in the GatewayPolicy. + +- `kind`: Must be set to `RouteAuthFilter` - `metadata.name`: Specifies a name for the filter. - `metadata.namespace`: Specifies the Consul namespace the filter applies to. -- `spec.jwt.providers`: Specifies a list of providers and claims used to verify requests to the gateway. The override settings take precedence over the default and route-specific JWT verification settings. - -## Attach the auth filter to your HTTP routes +- `spec.jwt.providers`: Specifies a list of providers and claims used to verify requests to the gateway. The override settings take precedence over the default and route-specific JWT verification settings. + +In the following example, the RouteAuthFilter overrides default settings set in the GatewayPolicy so that every request coming through the listener must meet these conditions: + +- The request must be signed by the `local` provider +- The request must have a `role` claim +- The value of the claim must be `admin` + + + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: RouteAuthFilter +metadata: + name: auth-filter +spec: + jwt: + providers: + - name: local + verifyClaims: + - path: + - role + value: admin +``` -In the `filters` field of your HTTP route configuration, add the following fields. Refer to the [`extensionRef` configuration reference](/consul/docs/connect/gateways/api-gateway/configuration/routes#rules-filters-extensionref) for details: + -- `type: extensionRef`: Declare list of extension references. -- `extensionRef.group`: Specifies the resource group. Unless you have created a custom group, this should be set to `gateway.networking.kuberenetes.io`. -- `extensionRef.kind`: Specifies the type of extension reference to attach to the route. Must be `RouteAuthFilter` -- `extensionRef.name`: Specifies the name of the auth filter. +For more information about the fields you can configure, refer to [`RouteAuthFilter` configuration reference](/consul/docs/connect/gateways/api-gateway/configuration/routeauthfilter). -## Apply the configurations +## Attach the auth filter to your HTTP routes -Run the `kubectl apply` command and specify the values files to apply the configurations. The following example applies the values files stored in the `jwt-routes` directory: +In the `filters` field of your HTTPRoute configuration, define the filter behavior that results from JWT verification. -```shell-session -$ kubectl apply -f jwt-routes +- `type: extensionRef`: Declare list of extension references. +- `extensionRef.group`: Specifies the resource group. Unless you have created a custom group, this should be set to `gateway.networking.k8s.io/v1beta1`. +- `extensionRef.kind`: Specifies the type of extension reference to attach to the route. Must be `RouteAuthFilter` +- `extensionRef.name`: Specifies the name of the auth filter. + +The following example configures an HTTPRoute so that every request to `api-gateway-fqdn:3002/admin` must meet these conditions: + +- The request be signed by the `local` provider. +- The request must have a `role` claim. +- The value of the claim must be `admin`. + +Every other request must be signed by the `local` provider and have a claim of `role` with a value of `user`, as defined in the GatewayPolicy. + + + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: http-route +spec: + parentRefs: + - name: api-gateway + rules: + - matches: + - path: + type: PathPrefix + value: /admin + filters: + - type: ExtensionRef + extensionRef: + group: consul.hashicorp.com + kind: RouteAuthFilter + name: auth-filter + backendRefs: + - kind: Service + name: admin + port: 8080 + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - kind: Service + name: user-service + port: 8081 ``` + diff --git a/website/content/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms.mdx b/website/content/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms.mdx index bd10964887d3..fda579669fac 100644 --- a/website/content/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms.mdx +++ b/website/content/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms.mdx @@ -6,22 +6,23 @@ description: Learn how to use JSON web tokens (JWT) to verify requests from exte # Use JWTs to verify requests to API gateways on virtual machines -This topic describes how to use JSON web tokens (JWT) to verify requests to API gateways on virtual machines (VM). If your services are deployed to Kubernetes-orchestrated containers, refer to [Use JWTs to verify requests to API gateways on Kubernetes](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms). +This topic describes how to use JSON web tokens (JWT) to verify requests to API gateways on virtual machines (VM). If your services are deployed to Kubernetes-orchestrated containers, refer to [Use JWTs to verify requests to API gateways on Kubernetes](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-k8s). This feature is available in Consul Enterprise. ## Overview - + You can configure API gateways to use JWTs to verify incoming requests so that you can stop unverified traffic at the gateway. You can configure JWT verification at different levels: - Listener defaults: Define basic defaults that apply to all routes attached to a listener. -- HTTP route-specific settings: You can define JWT authentication settings for specific HTTP routes. Route-specific JWT settings override default configurations. +- HTTP route-specific settings: You can define JWT authentication settings for specific HTTP routes. Route-specific JWT settings override default configurations. - Listener overrides: Define override settings that take precedence over default and route-specific configurations. This enables you to set enforceable policies for listeners. Complete the following steps to use JWTs to verify requests: -1. Configure default and override settings for listeners in the API gateway configuration entry. -1. Define route-specific JWT verification settings as filters in the HTTP route configuration entries. +1. Define a JWTProvider that specifies the JWT provider and claims used to verify requests to the gateway. +1. Configure default and override settings for listeners in the API gateway configuration entry. +1. Define route-specific JWT verification settings as filters in the HTTP route configuration entries. 1. Write the configuration entries to Consul to begin verifying requests using JWTs. ## Requirements @@ -29,17 +30,155 @@ Complete the following steps to use JWTs to verify requests: - Consul 1.17 or later - JWT details, such as claims and provider +## Define a JWTProvider + +Create a JWTProvider config entry that defines the JWT provider to verify claims against. +In the following example, the JWTProvider CRD contains a local JWKS. In production environments, use a production-grade JWKs endpoint instead. + + + +```hcl +Kind = "jwt-provider" +Name = "local" + +Issuer = "local" + +JSONWebKeySet = { + Local = { + JWKS="" + } +} +``` + + + +For more information about the fields you can configure in this CRD, refer to [`JWTProvider` configuration reference](/consul/docs/connect/config-entries/jwtprovider). + ## Configure default and override settings -Define default and override settings for JWT verification in the [API gateway configuration entry](/consul/docs/connect/gateways/api-gateway/configuration/api-gateway). +Define default and override settings for JWT verification in the [API gateway configuration entry](/consul/docs/connect/gateways/api-gateway/configuration/api-gateway). -1. Add a `default.JWT` block to the listener that you want to apply JWT verification to. Consul applies these configurations to routes attached to the listener. Refer to the [`Listeners.default.JWT`](/consul/docs/connect/config-entries/api-gateway#listeners-default-jwt) configuration reference for details. -1. Add an `override.JWT` block to the listener that you want to apply JWT verification policies to. Consul applies these configurations to all routes attached to the listener, regardless of the `default` or route-specific settings. Refer to the [`Listeners.override.JWT`](/consul/docs/connect/config-entries/api-gateway#listeners-override-jwt) configuration reference for details. -1. Apply the settings in the API gateway configuration entry. You can use the [`/config` API endpoint](/consul/api-docs/config#apply-configuration) or the [`consul config write` command](/consul/commands/config/write). +1. Add a `default.JWT` block to the listener that you want to apply JWT verification to. Consul applies these configurations to routes attached to the listener. Refer to the [`Listeners.default.JWT`](/consul/docs/connect/config-entries/api-gateway#listeners-default-jwt) configuration reference for details. +1. Add an `override.JWT` block to the listener that you want to apply JWT verification policies to. Consul applies these configurations to all routes attached to the listener, regardless of the `default` or route-specific settings. Refer to the [`Listeners.override.JWT`](/consul/docs/connect/config-entries/api-gateway#listeners-override-jwt) configuration reference for details. +1. Apply the settings in the API gateway configuration entry. You can use the [`/config` API endpoint](/consul/api-docs/config#apply-configuration) or the [`consul config write` command](/consul/commands/config/write). + +The following examples configure a Gateway so that every request coming through the listener must meet these conditions: +- The request must be signed by the `local` provider +- The request must have a claim of `role` with a value of `user` unless the HTTPRoute attached to the listener overrides it + + + +```hcl +Kind = "api-gateway" +Name = "api-gateway" +Listeners = [ + { + Name = "listener-one" + Port = 9001 + Protocol = "http" + Override = { + JWT = { + Providers = [ + { + Name = "local" + } + ] + } + } + default = { + JWT = { + Providers = [ + { + Name = "local" + VerifyClaims = [ + { + Path = ["role"] + Value = "pet" + } + ] + } + ] + } + } + } +] +``` + + ## Configure verification for specific HTTP routes -Define filters to enable route-specific JWT verification settings in the [HTTP route configuration entry](/consul/docs/connect/config-entries/http-route). +Define filters to enable route-specific JWT verification settings in the [HTTP route configuration entry](/consul/docs/connect/config-entries/http-route). 1. Add a `JWT` configuration to the `rules.filter` block. Route-specific configurations that overlap the [default settings ](/consul/docs/connect/config-entries/api-gateway#listeners-default-jwt) in the API gateway configuration entry take precedence. Configurations defined in the [listener override settings](/consul/docs/connect/config-entries/api-gateway#listeners-override-jwt) take the highest precedence. -1. Apply the settings in the API gateway configuration entry. You can use the [`/config` API endpoint](/consul/api-docs/config#apply-configuration) or the [`consul config write` command](/consul/commands/config/write). +1. Apply the settings in the API gateway configuration entry. You can use the [`/config` API endpoint](/consul/api-docs/config#apply-configuration) or the [`consul config write` command](/consul/commands/config/write). + +The following example configures an HTTPRoute so that every request to `api-gateway-fqdn:3002/admin` must meet these conditions: +- The request be signed by the `local` provider. +- The request must have a `role` claim. +- The value of the claim must be `admin`. + +Every other request must be signed by the `local` provider and have a claim of `role` with a value of `user`, as defined in the Gateway listener. + + + +```hcl +Kind = "http-route" +Name = "api-gateway-route" +Parents = [ + { + SectionName = "listener-one" + Name = "api-gateway" + Kind = "api-gateway" + }, +] +Rules = [ + { + Matches = [ + { + Path = { + Match = "prefix" + Value = "/admin" + } + } + ] + Filters = { + JWT = { + Providers = [ + { + Name = "local" + VerifyClaims = [ + { + Path = ["role"] + Value = "admin" + } + ] + } + ] + } + } + Services = [ + { + Name = "admin-service" + } + ] + }, + { + Matches = [ + { + Path = { + Match = "prefix" + Value = "/" + } + } + ] + Services = [ + { + Name = "user-service" + } + ] + }, +] +``` + + diff --git a/website/content/docs/connect/gateways/api-gateway/tech-specs.mdx b/website/content/docs/connect/gateways/api-gateway/tech-specs.mdx index 98f5e28c0c1a..9a79f75ca122 100644 --- a/website/content/docs/connect/gateways/api-gateway/tech-specs.mdx +++ b/website/content/docs/connect/gateways/api-gateway/tech-specs.mdx @@ -40,7 +40,7 @@ Refer to the following topics for additional information: ### Security context constraints -OpenShift requires a security context constraint (SCC) configuration, which restricts pods to specific groups. You can create a custom SCC or use one of the default constraints. Refer to the [OpenShift documentation](https://docs.openshift.com/container-platform/4.13/authentication/managing-security-context-constraints.html) for additional information. +OpenShift requires a security context constraint (SCC) configuration, which restricts pods to specific groups. You can create a custom SCC or use one of the default constraints. Refer to the [OpenShift documentation](https://docs.openshift.com/container-platform/4.13/authentication/managing-security-context-constraints.html) for additional information. By default, the SCC is set to `restricted-v2` for the `managedGatewayClass` that Consul automatically creates. The `restricted-v2` SCC is one of OpenShifts default SCCs, but you can specify a different SCC in the `openshiftSCCName` parameter: @@ -52,12 +52,12 @@ connectInject: ``` ### Privileged container ports - + Containers cannot use privileged ports when OpenShift is enabled. Privileged ports are 1 through 1024, and serving applications from that range is a security risk. To allow gateway listeners to use privileged port numbers, specify an integer value in the `mapPrivilegedContainerPorts` field of your Consul values configuration. Consul adds the value to listener port numbers that are set to a number in the privileged container range. Consul maps the configured port number to the total port number so that traffic sent to the configured port number is correctly forwarded to the service. -For example, if a gateway listener is configured to port `80` and the `mapPrivilegedContainerPorts` field is configured to `2000`, then the actual port number on the underlying container is `2080`. +For example, if a gateway listener is configured to port `80` and the `mapPrivilegedContainerPorts` field is configured to `2000`, then the actual port number on the underlying container is `2080`. You can set the `mapPrivilegedContainerPorts` parameter in the following map in your Consul values file: @@ -74,29 +74,29 @@ Refer to the [release notes](/consul/docs/release-notes) for your version of Con ## Supported Kubernetes gateway specification features -Consul API gateways for Kuberentes support a subset of the Kubernetes Gateway API specification. For a complete list of features, including the list of gateway and route statuses and an explanation on how they -are used, refer to the [documentation in our GitHub repo](https://github.com/hashicorp/consul-api-gateway/blob/main/dev/docs/supported-features.md): +Consul API gateways for Kubernetes support a subset of the Kubernetes Gateway API specification. For a complete list of features, including the list of gateway and route statuses and an explanation on how they +are used, refer to the [documentation in our GitHub repo](https://github.com/hashicorp/consul-api-gateway/blob/main/dev/docs/supported-features.md): ### `GatewayClass` -The `GatewayClass` resource describes a class of gateway configurations to use a template for creating `Gateway` resources. You can also specify custom API gateway configurations in a `GatewayClassConfig` CRD and attach them to resource to the `GatewayClass` using the `parametersRef` field. +The `GatewayClass` resource describes a class of gateway configurations to use a template for creating `Gateway` resources. You can also specify custom API gateway configurations in a `GatewayClassConfig` CRD and attach them to resource to the `GatewayClass` using the `parametersRef` field. You must specify the `"hashicorp.com/consul-api-gateway-controller"` controller so that Consul can manage gateways generated by the `GatewayClass`. Refer to the [Kubernetes `GatewayClass` documentation](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.GatewayClass) for additional information. -### `Gateway` +### `Gateway` -The `Gateway` resource is the core API gateway component. Gateways have one or more listeners that can route `HTTP`, `HTTPS`, or `TCP` traffic. You can define header-based hostname matching for listeners, but SNI is not supported. +The `Gateway` resource is the core API gateway component. Gateways have one or more listeners that can route `HTTP`, `HTTPS`, or `TCP` traffic. You can define header-based hostname matching for listeners, but SNI is not supported. -You can apply filters to add, remove, and set header values on incoming requests. Gateways support the `terminate` TLS mode and `core/v1/Secret` TLS certificates. Extended option support includes TLS version and cipher constraints. Refer to the [Kubernetes `Gateway` documentation](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.Gateway) for additional information. +You can apply filters to add, remove, and set header values on incoming requests. Gateways support the `terminate` TLS mode and `core/v1/Secret` TLS certificates. Extended option support includes TLS version and cipher constraints. Refer to [Kubernetes `Gateway` resource configuration reference](/consul/docs/connect/gateways/api-gateway/configuration/gateway) for more information. ### `HTTPRoute` -`HTTPRoute` configurations determine HTTP paths between listeners defined on the gateway and services in the mesh. You can specify weights to load balance traffic, as well as define rules for matching request paths, headers, queries, and methods to ensure that traffic is routed appropriately. You can apply filters to add, remove, and set header values on requests sent through th route. +`HTTPRoute` configurations determine HTTP paths between listeners defined on the gateway and services in the mesh. You can specify weights to load balance traffic, as well as define rules for matching request paths, headers, queries, and methods to ensure that traffic is routed appropriately. You can apply filters to add, remove, and set header values on requests sent through th route. Routes support the following backend types: -- `core/v1/Service` backend types when the route maps to service registered with Consul. -- `api-gateway.consul.hashicorp.com/v1alpha1/MeshService`. +- `core/v1/Service` backend types when the route maps to service registered with Consul. +- `api-gateway.consul.hashicorp.com/v1alpha1/MeshService`. Refer to [Kubernetes `HTTPRoute` documentation](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.HTTPRoute) for additional information. @@ -104,8 +104,8 @@ Refer to [Kubernetes `HTTPRoute` documentation](https://gateway-api.sigs.k8s.io/ `TCPRoute` configurations determine TCP paths between listeners defined on the gateway and services in the mesh. Routes support the following backend types: -- `core/v1/Service` backend types when the route maps to service registered with Consul. -- `api-gateway.consul.hashicorp.com/v1alpha1/MeshService`. +- `core/v1/Service` backend types when the route maps to service registered with Consul. +- `api-gateway.consul.hashicorp.com/v1alpha1/MeshService`. Refer to [Kubernetes `TCPRoute` documentation](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.TCPRoute) for additional information. @@ -121,10 +121,10 @@ Refer to the [Kubernetes `ReferenceGrant` documentation](https://gateway-api.sig ## Consul server deployments -- Consul Enterprise and the free community edition are both supported. +- Consul Enterprise and the community edition are both supported. - Supported Consul Server deployment types: - Self-Managed - - HCP Consul + - HCP Consul Dedicated ### Consul feature support @@ -152,6 +152,3 @@ The following resources are allocated for each component of the API gateway. - **CPU**: None. Either the namespace or cluster default is allocated, depending on the Kubernetes cluster configuration. - **Memory**: None. Either the namespace or cluster default is allocated, depending on the Kubernetes cluster configuration. - - - diff --git a/website/content/docs/connect/gateways/ingress-gateway/tls-external-service.mdx b/website/content/docs/connect/gateways/ingress-gateway/tls-external-service.mdx index c214616853c4..d3d116761831 100644 --- a/website/content/docs/connect/gateways/ingress-gateway/tls-external-service.mdx +++ b/website/content/docs/connect/gateways/ingress-gateway/tls-external-service.mdx @@ -6,7 +6,7 @@ description: Learn how to configure ingress gateways to serve TLS certificates f # Serve custom TLS certificates from an external service -This is an advanced topic that describes how to configure ingress gateways to serve TLS certificates sourced from an external service to inbound traffic using secret discovery service (SDS). SDS is a low-level feature designed for developers building integrations with custom TLS management solutions. For instructions on more common ingress gateway implementations, refer to [Implement an ingress gateway](/consul/docs/connect/gateways/ingress-gateway/usage). +This is an advanced topic that describes how to configure ingress gateways to serve TLS certificates sourced from an external service to inbound traffic using secret discovery service (SDS). SDS is a low-level feature designed for developers building integrations with custom TLS management solutions. For instructions on more common ingress gateway implementations, refer to [Implement an ingress gateway](/consul/docs/connect/gateways/ingress-gateway/usage). ## Overview @@ -17,7 +17,7 @@ The following process describes the general procedure for configuring ingress ga 1. Configure TLS client authentication 1. Start Envoy. 1. Configure SDS settings in an ingress gateway configuration entry. -1. Register the ingress gateway configuration entry with Consul. +1. Register the ingress gateway configuration entry with Consul. ## Requirements @@ -30,7 +30,7 @@ The following process describes the general procedure for configuring ingress ga If ACLs are enabled, you must present a token when registering ingress gateways that grant the following permissions: -- `service:write` for the ingress gateway's service name +- `service:write` for the ingress gateway's service name - `service:read` for all services in the ingress gateway's configuration entry - `node:read` for all nodes of the services in the ingress gateway's configuration entry. @@ -40,11 +40,11 @@ These privileges authorize the token to route communications to other services i You must define one or more additional static clusters in the ingress gateway service definition for each Envoy proxy associated with the gateway. The additional clusters define how Envoy should connect to the required SDS services. -Configure the static clusters in the [`Proxy.Config.envoy_envoy_extra_static_clusters_json`](/consul/docs/connect/proxies/envoy#envoy_extra_static_clusters_json) parameter in the service definition. +Configure the static clusters in the [`Proxy.Config.envoy_envoy_extra_static_clusters_json`](/consul/docs/connect/proxies/envoy#envoy_extra_static_clusters_json) parameter in the service definition. The clusters must provide connection information and any necessary authentication information, such as mTLS credentials. -You must manually register the ingress gateway with Consul proxy to define extra clusters in Envoy's bootstrap configuration. You can not use the `-register` flag with `consul connect envoy -gateway=ingress` to automatically register the proxy to define static clusters. +You must manually register the ingress gateway with Consul proxy to define extra clusters in Envoy's bootstrap configuration. You can not use the `-register` flag with `consul connect envoy -gateway=ingress` to automatically register the proxy to define static clusters. In the following example, the `public-ingress` gateway includes a static cluster named `sds-cluster` that specifies paths to the SDS certificate and SDS certification validation files: @@ -62,7 +62,14 @@ Services { { "name": "sds-cluster", "connect_timeout": "5s", - "http2_protocol_options": {}, + "typed_extension_protocol_options": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicit_http_config": { + "http2_protocol_options": {} + } + } + }, "type": "LOGICAL_DNS", "transport_socket": { "name":"tls", @@ -114,9 +121,9 @@ EOF -Refer to the [Envoy documentation](https://www.envoyproxy.io/docs/envoy/v1.17.2/api-v3/config/bootstrap/v3/bootstrap.proto#envoy-v3-api-field-config-bootstrap-v3-bootstrap-staticresources-clusters) for details about configuration parameters for SDS clusters. +Refer to the [Envoy documentation](https://www.envoyproxy.io/docs/envoy/v1.17.2/api-v3/config/bootstrap/v3/bootstrap.proto#envoy-v3-api-field-config-bootstrap-v3-bootstrap-staticresources-clusters) for details about configuration parameters for SDS clusters. -## Register the ingress gateway service definition +## Register the ingress gateway service definition Issue the `consul services register` command on the Consul agent on the Envoy proxy's node to register the service. The following example command registers an ingress gateway proxy from a `public-ingress.hcl` file: @@ -193,19 +200,19 @@ Refer to [Consul Connect Envoy](/consul/commands/connect/envoy) for additional i Create an ingress gateway configuration entry that enables the gateway to use certificates from SDS. The configuration entry also maps downstream ingress listeners to upstream services. Configure the following fields: - [`Kind`](/consul/docs/connect/config-entries/ingress-gateway#kind): Set the value to `ingress-gateway`. -- [`Name`](/consul/docs/connect/config-entries/ingress-gateway#name): Consul applies the configuration entry settings to ingress gateway proxies with names that match the `Name` field. -- [`TLS`](/consul/docs/connect/config-entries/ingress-gateway#tls): The main `TLS` parameter for the configuration entry holds the SDS configuration. You can also specify TLS configurations per listener and per service. +- [`Name`](/consul/docs/connect/config-entries/ingress-gateway#name): Consul applies the configuration entry settings to ingress gateway proxies with names that match the `Name` field. +- [`TLS`](/consul/docs/connect/config-entries/ingress-gateway#tls): The main `TLS` parameter for the configuration entry holds the SDS configuration. You can also specify TLS configurations per listener and per service. - [`TLS.SDS`](/consul/docs/connect/config-entries/ingress-gateway#tls-sds): The `SDS` map includes the following configuration settings: - - [`ClusterName`](/consul/docs/connect/config-entries/ingress-gateway#tls-sds-clustername): Specifies the name of the cluster you specified when [configuring the SDS cluster](#configure-static-SDS-clusters). - - [`CertResource`](/consul/docs/connect/config-entries/ingress-gateway#tls-sds-certresource): Specifies the name of the certificate resource to load. + - [`ClusterName`](/consul/docs/connect/config-entries/ingress-gateway#tls-sds-clustername): Specifies the name of the cluster you specified when [configuring the SDS cluster](#configure-static-SDS-clusters). + - [`CertResource`](/consul/docs/connect/config-entries/ingress-gateway#tls-sds-certresource): Specifies the name of the certificate resource to load. - [`Listeners`](/consul/docs/connect/config-entries/ingress-gateway#listeners): Specify one or more listeners. - [`Listeners.Port`](/consul/docs/connect/config-entries/ingress-gateway#listeners-port): Specify a port for the listener. Each listener is uniquely identified by its port number. - [`Listeners.Protocol`](/consul/docs/connect/config-entries/ingress-gateway#listeners-protocol): The default protocol is `tcp`, but you must specify the protocol used by the services you want to allow traffic from. - - [`Listeners.Services`](/consul/docs/connect/config-entries/ingress-gateway#listeners-services): The `Services` field contains the services that you want to expose to upstream services. The field contains several options and sub-configurations that enable granular control over ingress traffic, such as health check and TLS configurations. + - [`Listeners.Services`](/consul/docs/connect/config-entries/ingress-gateway#listeners-services): The `Services` field contains the services that you want to expose to upstream services. The field contains several options and sub-configurations that enable granular control over ingress traffic, such as health check and TLS configurations. -For Consul Enterprise service meshes, you may also need to configure the [`Partition`](/consul/docs/connect/config-entries/ingress-gateway#partition) and [`Namespace`](/consul/docs/connect/config-entries/ingress-gateway#namespace) fields for the gateway and for each exposed service. +For Consul Enterprise service meshes, you may also need to configure the [`Partition`](/consul/docs/connect/config-entries/ingress-gateway#partition) and [`Namespace`](/consul/docs/connect/config-entries/ingress-gateway#namespace) fields for the gateway and for each exposed service. -Refer to [Ingress gateway configuration entry reference](/consul/docs/connect/config-entries/ingress-gateway) for details about the supported parameters. +Refer to [Ingress gateway configuration entry reference](/consul/docs/connect/config-entries/ingress-gateway) for details about the supported parameters. The following example directs Consul to retrieve `example.com-public-cert` certificates from an SDS cluster named `sds-cluster` and serve them to all listeners: @@ -243,4 +250,4 @@ The following example registers an ingress gateway configuration entry named `pu $ consul config write public-ingress-cfg.hcl ``` -The Envoy instance starts a listener on the port specified in the configuration entry and fetches the TLS certificate named from the SDS server. \ No newline at end of file +The Envoy instance starts a listener on the port specified in the configuration entry and fetches the TLS certificate named from the SDS server. diff --git a/website/content/docs/connect/intentions/index.mdx b/website/content/docs/connect/intentions/index.mdx index c9bbbabf2acc..8d6364638a0a 100644 --- a/website/content/docs/connect/intentions/index.mdx +++ b/website/content/docs/connect/intentions/index.mdx @@ -36,7 +36,11 @@ application](/consul/docs/connect/native) enforces intentions on inbound connect L4 intentions mediate the ability to establish new connections. Modifying an intention does not have an effect on existing connections. As a result, changing a connection from `allow` to `deny` does not sever the connection. -L7 intentions mediate the ability to issue new requests. When an intention is modified, requests received after the modification use the latest intention rules to enforce access. Changing a connection from `allow` to `deny` does not sever the connection, but doing so blocks new requests from being processed. +L7 intentions mediate the ability to issue new requests. When an intention is modified, requests received after the modification use the latest intention rules to enforce access. Changing a connection from `allow` to `deny` does not sever the connection, but doing so blocks new requests from being processed. + +When using L7 intentions, we recommend that you review and update the [Mesh request normalization configuration](/consul/docs/connect/security#request-normalization-and-configured) to avoid unintended match rule circumvention. More details are available in the [Mesh configuration entry reference](/consul/docs/connect/config-entries/mesh#request-normalization). + +When you use L7 intentions with header matching and it is possible for a header to contain multiple values, we recommend using `contains` or `regex` instead of `exact`, `prefix`, or `suffix`. For more information, refer to the [service intentions configuration entry reference](/consul/docs/connect/config-entries/service-intentions#spec-sources-permissions-http-header). ### Caching diff --git a/website/content/docs/connect/manage-traffic/failover/sameness.mdx b/website/content/docs/connect/manage-traffic/failover/sameness.mdx index 98117bd28335..ac8c8745fecc 100644 --- a/website/content/docs/connect/manage-traffic/failover/sameness.mdx +++ b/website/content/docs/connect/manage-traffic/failover/sameness.mdx @@ -6,13 +6,13 @@ description: You can configure sameness groups so that when a service instance f # Failover with sameness groups -This page describes how to use sameness groups to automatically redirect service traffic to healthy instances in failover scenarios. Sameness groups are a user-defined set of Consul admin partitions with identical registered services. These admin paritions typically belong to Consul datacenters in different cloud regions, which enables sameness groups to participate in several service failover configuration strategies. +This page describes how to use sameness groups to automatically redirect service traffic to healthy instances in failover scenarios. Sameness groups are a user-defined set of Consul admin partitions with identical registered services. These admin partitions typically belong to Consul datacenters in different cloud regions, which enables sameness groups to participate in several service failover configuration strategies. To create a sameness group and configure each Consul datacenter to allow traffic from other members of the group, refer to [create sameness groups](/consul/docs/connect/cluster-peering/usage/create-sameness-groups). ## Failover strategies -You can edit a sameness group configuration entry so that all services failover to healthy instances on other members of a sameness group by default. You can also reference the sameness group in other configuration entries to enact other failover strategies for your network. +You can edit a sameness group configuration entry so that all services failover to healthy instances on other members of a sameness group by default. You can also reference the sameness group in other configuration entries to enact other failover strategies for your network. You can establish a failover strategy by configuring sameness group behavior in the following locations: @@ -33,9 +33,9 @@ In the following example configuration entry, datacenter `dc1` has two partition ```hcl -Kind = "sameness-group" +Kind = "sameness-group" Name = "example-sg" -Partition = "partition-1" +Partition = "partition-1" DefaultForFailover = true Members = [ {Partition = "partition-1"}, @@ -50,8 +50,8 @@ Members = [ ``` { - "Kind": "sameness-group", - "Name": "example-sg", + "Kind": "sameness-group", + "Name": "example-sg", "Partition": "partition-1", "DefaultForFailover": true, "Members": [ @@ -74,12 +74,12 @@ Members = [ ```yaml apiVersion: consul.hashicorp.com/v1alpha1 -kind: SamenessGroup +kind: SamenessGroup metadata: name: example-sg spec: defaultForFailover: true - members: + members: - partition: partition-1 - partition: partition-2 - peer: dc2-partition-1 @@ -88,13 +88,11 @@ spec: -When a sameness group is configured as the failover default, sameness group fail over takes place when a service resolver configuration entry does not implement more specific failover behavior. When a service resolver is defined for an upstream, it is used instead of the sameness group for default failover behavior. +When a sameness group is configured as the failover default, sameness group failover takes place when a service resolver configuration entry does not implement more specific failover behavior. When a service resolver is defined for an upstream, it is used instead of the sameness group for default failover behavior. All services registered in the admin partition must failover to another member of the sameness group. You cannot choose subsets of services to use the sameness group as the failover default. If groups do not have identical services, or if a service is registered to some group members but not all members, this failover strategy may produce errors. -For more information about specifying sameness group members and failover, refer to [sameness group configuration entry reference](/consul/docs/connects/config-entries/sameness-group). - -All services registered in the admin partition must fail over to another member of the sameness group. You cannot choose subsets of services to use the sameness group as the failover default. If groups do not have identical services, or if a service is registered to some group members but not all members, this failover strategy may produce errors. +For more information about specifying sameness group members and failover, refer to [sameness group configuration entry reference](/consul/docs/connect/config-entries/sameness-group). ### Failover with a service resolver configuration entry @@ -134,8 +132,8 @@ Failover { ``` { - "Kind": "service-resolver", - "Name": "db", + "Kind": "service-resolver", + "Name": "db", "DefaultSubset": "v1", "Subsets": { "v1": { @@ -144,7 +142,7 @@ Failover { "v2": { "Filter": "Service.Meta.version == v2" } - }, + }, "Failover": { "v1": { "SamenessGroup": "product-group" @@ -202,4 +200,4 @@ The following example demonstrates a prepared query that can be referenced with } ``` -In prepared queries, the sameness group is mutually exclusive with the [`Failover`](/consul/api-docs/query#failover) field because the sameness group includes failover targets based on the sameness group’s members. For more information about using prepared queries, refer to [Enable dynamic DNS queries](/consul/docs/services/discovery/dns-dynamic-lookups). \ No newline at end of file +In prepared queries, the sameness group is mutually exclusive with the [`Failover`](/consul/api-docs/query#failover) field because the sameness group includes failover targets based on the sameness group’s members. For more information about using prepared queries, refer to [Enable dynamic DNS queries](/consul/docs/services/discovery/dns-dynamic-lookups). diff --git a/website/content/docs/connect/manage-traffic/fault-injection.mdx b/website/content/docs/connect/manage-traffic/fault-injection.mdx new file mode 100644 index 000000000000..2b81328466de --- /dev/null +++ b/website/content/docs/connect/manage-traffic/fault-injection.mdx @@ -0,0 +1,204 @@ +--- +layout: docs +page_title: Fault injection +description: Learn how to use fault injection in a Consul service mesh to inject artificial latency, response codes, or bandwidth limits for application testing. +--- + +# Fault Injection + +This topic describes the process to inject different types of faults into the services in Consul's service mesh to help you test your network's resilience. + + This feature is available in Consul Enterprise. + +## Introduction + +Consul allows you to configure fault injection filters to alter the responses from an upstream service. By injecting HTTP and gRPC statuses, bandwidth limits, or delays, users can test the resilience of their system to different unexpected issues. + +Consul applies fault injection filters to an upstream service as part of its service defaults. For example, to simulate that an upstream returned a 500 HTTP status code 50 percent of the time, add an `Abort` configuration to the Envoy extensions block in the service default configuration for the upstream service. + +The fault injection filters may be used individually, or in a combination of the three types by adding multiple blocks to the `Arguments.Config` section of the configuration. + +## Requirements + +Consul Enterprise v1.18.0 or later + +## Inject delays + +Specify the fault injection behavior in the [service defaults configuration entry](/consul/docs/connect/config-entries/service-defaults). + + + + +To inject a delay fault when Consul runs on virtual machines, configure the following parameters: + +1. `Arguments.Config.Delay.Duration`: The delay in milliseconds to use when injecting a delay type fault. +1. `Arguments.Config.Delay.Percentage`: The percentage of responses to inject the delay behavior into. + +The following example configures the default behavior for a service named `billing`. This configuration injects a 100 ms delay into 50 percent of responses from the billing service. + +```hcl +Kind = "service-defaults" +Name = "billing" +EnvoyExtensions = [ +{ + Name = "builtin/fault-injection" + Arguments = { + Config = { + Delay = { + Duration = 100 + Percentage = 50 + } + } + } +} +] +``` + + + + +To inject a delay fault when Consul runs on Kubernetes, configure the following parameters: + +1. `spec.arguments.config.delay.duration`: The delay in milliseconds to use when injecting a delay type fault. +1. `spec.arguments.config.delay.percentage`: The percentage of responses to inject the delay behavior into. + +The following example configures the default behavior for a service named `billing`. This configuration injects a 100 ms delay into 50 percent of responses from the billing service. + +```yaml +kind: ServiceDefaults +metadata: + name: billing +spec: + envoyExtensions: + - name: "builtin/fault-injection" + arguments: + config: + delay: + duration: 100 + percentage: 50 +``` + + + + + +Refer to the [service defaults configuration entry reference](/consul/docs/connect/config-entries/service-defaults) for additional specifications and example configurations. + +## Inject statuses + + + +To inject a status code when aborting a response, configure the following parameters: + +1. `Arguments.Config.Abort.HttpStatus`: The HTTP status code to inject into responses when injecting an abort type fault. You may specify either a HTTP status or a gRPC status but not both. +1. `Arguments.Config.Abort.GrpcStatus`: The gRPC status to inject into responses when injecting an abort type fault. You may specify either a HTTP status or a gRPC status but not both. +1. `Arguments.Config.Abort.Percentage`: The percentage of responses to inject the abort behavior into. + +The following example configures the default behavior for a service named `billing`. This configuration injects an HTTP status code of 503 into 5 percent of responses from the billing service. + +```hcl +Kind = "service-defaults" +Name = "billing" +EnvoyExtensions = [ +{ + Name = "builtin/fault-injection" + Arguments = { + Config = { + Abort = { + HttpStatus = 503 + Percentage = 5 + } + } + } +} +] +``` + + + + +To inject a status code when aborting a response, configure the following parameters: + +1. `spec.arguments.config.abort.httpStatus`: The HTTP status code to inject into responses when injecting an abort type fault. You may specify either a HTTP status or a gRPC status but not both. +1. `spec.arguments.config.abort.grpcStatus`: The gRPC status to inject into responses when injecting an abort type fault. You may specify either a HTTP status or a gRPC status but not both. +1. `spec.arguments.config.abort.percentage`: The percentage of responses to inject the abort behavior into. + +The following example configures the default behavior for a service named `billing`. This configuration injects an HTTP status code of 503 into 5 percent of responses from the billing service. + +```yaml +kind: ServiceDefaults +metadata: + name: billing +spec: + envoyExtensions: + - name: "builtin/fault-injection" + arguments: + config: + abort: + httpStatus: 503 + percentage: 5 +``` + + + + +Refer to the [service defaults configuration entry reference](/consul/docs/connect/config-entries/service-defaults) for additional specifications and example configurations. + +## Inject bandwidth limit + + + + +To inject a rate limit into a response, configure the following parameters: + +1. `Arguments.Config.Bandwidth.Limit`: The amount of data allowed through the filter when applied. This value is specified in KiB/s. When the limit is exceeded, requests, operations, or connections will be subjected to rate limiting. +1. `Arguments.Config.Bandwidth.Percentage`: The percent of responses to inject the bandwidth limit behavior into. + +The following example configures the default behavior for a service named `billing`. This configuration limits the bandwidth of outgoing requests to 100 KiB/s for 50 percent of responses from the billing service. + +```hcl +Kind = "service-defaults" +Name = "billing" +EnvoyExtensions = [ +{ + Name = "builtin/fault-injection" + Arguments = { + Config = { + Bandwidth = { + Limit = 100 + Percentage = 50 + } + } + } +} +] +``` + + + + +To inject a rate limit into a response, configure the following parameters: + +1. `spec.arguments.config.bandwidth.limit`: The amount of data allowed through the filter when applied. This value is specified in KiB/s. When the limit is exceeded, requests, operations, or connections will be subjected to rate limiting. +1. `spec.arguments.config.bandwidth.percentage`: The percent of responses to inject the bandwidth limit behavior into. + +The following example configures the default behavior for a service named `billing`. This configuration limits the bandwidth of outgoing requests to 100 KiB/s for 50 percent of responses from the billing service. + +```yaml +kind: ServiceDefaults +metadata: + name: billing +spec: + envoyExtensions: + - name: "builtin/fault-injection" + arguments: + config: + bandwidth: + limit: 100 + percentage: 50 +``` + + + + +Refer to the [service defaults configuration entry reference](/consul/docs/connect/config-entries/service-defaults) for additional specifications and example configurations. diff --git a/website/content/docs/connect/manage-traffic/limit-request-rates.mdx b/website/content/docs/connect/manage-traffic/limit-request-rates.mdx index 142f0f3d2108..adf2af5b706d 100644 --- a/website/content/docs/connect/manage-traffic/limit-request-rates.mdx +++ b/website/content/docs/connect/manage-traffic/limit-request-rates.mdx @@ -1,7 +1,7 @@ --- layout: docs page_title: Limit request rates to services in the mesh -description: Learn how to limit the rate of requests to services in a Consul service mesh. Rate limits on requests improves network resilience and availability +description: Learn how to limit the rate of requests to services in a Consul service mesh. Rate limits on requests improves network resilience and availability. --- # Limit request rates to services in the mesh @@ -32,12 +32,39 @@ Specify request rate limits in the service defaults configuration entry. Create 1. `RateLimits.InstanceLevel.RequestPerSecond`: Set an average number of requests per second that Consul should allow to the service. The number of requests may momentarily exceed this value up to the value specified in the `RequestsMaxBurst` parameter, but Consul temporarily lowers the speed of the transactions. 1. `RateLimits.InstanceLevel.RequestsMaxBurst`: Set the maximum number of concurrent requests that Consul momentarily allows to the service. Consul blocks any additional requests over this limit. +The following example configures the default behavior for a service named `billing`. This configuration limits each instance of the billing service to an average of 1000 requests per second, but allows the service to accept up to 1500 concurrent requests. + +```hcl +Kind = "service-defaults" +Name = "billing" +Protocol = "http" + +RateLimit { + InstanceLevel { + RequestsPerSecond = 1000 + RequestsMaxBurst = 1500 + } +} +``` + 1. `spec.rateLimits.instanceLevel.requestPerSecond`: Set an average number of requests per second that Consul should allow to the service. The number of requests may momentarily exceed this value up to the value specified in the `requestsMaxBurst` parameter, but Consul temporarily lowers the speed of the transactions. 1. `spec.rateLimits.instanceLevel.requestsMaxBurst`: Set the maximum number of concurrent requests that Consul momentarily allows to the service. Consul blocks any additional requests over this limit. +The following example configures the default behavior for a service named `billing`. This configuration limits each instance of the billing service to an average of 1000 requests per second, but allows the service to accept up to 1500 concurrent requests. + +```yaml +kind: ServiceDefaults +name: billing +protocol: http +rateLimit: + instanceLevel: + requestsPerSecond: 1000 + requestsMaxBurst: 1500 +``` + @@ -59,6 +86,30 @@ Specify request rate limits in the service defaults configuration entry. Create - `RequestsPerSecond`: Set an average number of requests per second that Consul should allow to the service through the matching path. The number of requests may momentarily exceed this value up to the value specified in the `RequestsMaxBurst` parameter, but Consul temporarily lowers the speed of the transactions. This configuration overrides the value specified in `RateLimits.InstanceLevel.RequestPerSecond` field of the configuration entry. - `RequestsMaxBurst`: Set the maximum number of concurrent requests that Consul momentarily allows to the service through the matching path. Consul blocks any additional requests over this limit. This configuration overrides the value specified in `RateLimits.InstanceLevel.RequestsMaxBurst` field of the configuration entry. +The following example configures the default behavior for a service named `billing`. This configuration limits each instance of the billing service depending on the path it received the request on. The service is limited to an average of 500 requests when the request is made on an HTTP path with the `/api` prefix. When an instance of the billing service receives a request from the `/login` path, it is limited to an average of 100 requests per second and 500 concurrent connections. + +```hcl +Kind = "service-defaults" +Name = "billing" +Protocol = "http" + +RateLimit { + InstanceLevel { + Routes = [ + { + PathPrefix = "/api" + RequestsPerSecond = 500 + }, + { + PathPrefix = "/login" + RequestsPerSecond = 100 + RequestsMaxBurst = 500 + } + ] + } +} +``` + @@ -71,8 +122,23 @@ Specify request rate limits in the service defaults configuration entry. Create - `requestsPerSecond`: Set an average number of requests per second that Consul should allow to the service through the matching path. The number of requests may momentarily exceed this value up to the value specified in the `requestsMaxBurst` parameter, but Consul temporarily lowers the speed of the transactions. This configuration overrides the value specified in `spec.rateLimits.instanceLevel.requestPerSecond` field of the CRD. - `requestsMaxBurst`: Set the maximum number of concurrent requests that Consul momentarily allows to the service through the matching path. Consul blocks any additional requests over this limit. This configuration overrides the value specified in `spec.rateLimits.instanceLevel.requestsMaxBurst` field of the CRD. +The following example configures the default behavior for a service named `billing`. This configuration limits each instance of the billing service depending on the path it received the request on. The service is limited to an average of 500 requests when the request is made on an HTTP path with the `/api` prefix. When an instance of the billing service receives a request from the `/login` path, it is limited to an average of 100 requests per second and 500 concurrent connections. + +```yaml +kind: service-defaults +name: billing +protocol: http +rateLimit: + instanceLevel: + routes: + - pathPrefix: /api + requestsPerSecond: 500 + - pathPrefix: /login + requestsPerSecond: 100 + requestsMaxBurst: 500 +``` + -Refer to the [service defaults configuration entry reference](/consul/docs/connect/config-entries/service-defaults) for additional specifications and example configurations. - +Refer to the [service defaults configuration entry reference](/consul/docs/connect/config-entries/service-defaults) for additional specifications and example configurations. \ No newline at end of file diff --git a/website/content/docs/connect/manage-traffic/route-to-local-upstreams.mdx b/website/content/docs/connect/manage-traffic/route-to-local-upstreams.mdx index baf36b8dc9b9..4d5be2e5b55d 100644 --- a/website/content/docs/connect/manage-traffic/route-to-local-upstreams.mdx +++ b/website/content/docs/connect/manage-traffic/route-to-local-upstreams.mdx @@ -10,10 +10,6 @@ This topic describes how to enable locality-aware routing so that Consul can pri This feature is available in Consul Enterprise. -!> **Warning**: Locality-aware routing is an advanced feature that may adversely impact service capacity if used incorrectly. By default, this feature routes 100% of traffic to the most local set of service instances, and failover only occurs when there are no healthy instances available in the most local set. You should only follow these instructions when every service within a zone has enough capacity to handle requests from downstream services within the same zone. - --> **Note**: It is possible to adjust the load balancing and failover behavior for this feature globally or per-service via the [Property Override Envoy extension](/consul/docs/connect/proxies/envoy-extensions/usage/property-override). Please familiarize with Envoy docs on [`overprovisioning_factor`](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/endpoint/v3/endpoint.proto#config-endpoint-v3-clusterloadassignment) and [outlier detection](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/outlier_detection.proto#config-cluster-v3-outlierdetection) before attempting to modify configuration. - ## Introduction By default, Consul balances traffic to all healthy upstream instances in the cluster, even if the instances are in different network zones. You can specify the cloud service provider (CSP) locality for Consul server agents and services registered to the service mesh, which enables several benefits: @@ -21,22 +17,32 @@ By default, Consul balances traffic to all healthy upstream instances in the clu - Consul prioritizes the nearest upstream instances when routing traffic through the mesh. - When upstream service instances becomes unhealthy, Consul prioritizes failing over to instances that are in the same region as the downstream service. Refer to [Failover](/consul/docs/connect/traffic-management/failover) for additional information about failover strategies in Consul. -When properly implemented, routing traffic to local upstreams can reduce latency and transfer costs associated with sending requests to other regions. +When properly implemented, routing traffic to local upstreams can reduce latency and transfer costs associated with sending requests to other regions. + ### Workflow For networks deployed to virtual machines, complete the following steps to route traffic to local upstream services: 1. Specify the region and zone for your Consul client agents. This allows services to inherit the region and zone configured for the Consul agent that the services are registered with. +1. Specify the localities of your service instances. This step is optional and is only necessary when defining a custom network topology or when your deployed environment requires explicitly set localities for certain service's instances. 1. Configure service mesh proxies to route traffic locally within the partition. -For Kubernetes-orchestrated networks using `consul-k8s`, Consul automatically populates geographic information about service instances using the `topology.kubernetes.io/region` and `topology.kubernetes.io/zone` annotations from the Kubernetes nodes. Similarly, when deploying on AWS ECS using `consul-ecs`, the `AWS_REGION` environment variable and `AvailabilityZone` attribute of the ECS task meta are used. As a result, you do not need to specify the regions and zones on these platforms unless you are implementing a custom deployment. +#### Container orchestration platforms + +If you deployed Consul to a Kubernetes or ECS environment using `consul-k8s` or `consul-ecs`, service instance locality information is inherited from the host machine. As a result, you do not need to specify the regions and zones on containerized platforms unless you are implementing a custom deployment. + +On Kubernetes, Consul automatically populates geographic information about service instances using the `topology.kubernetes.io/region` and `topology.kubernetes.io/zone` labels from the Kubernetes nodes. On AWS ECS, Consul uses the `AWS_REGION` environment variable and `AvailabilityZone` attribute of the ECS task meta. + +### Requirements + +You should only enable locality-aware routing when each set of external upstream instances within the same zone and region have enough capacity to handle requests from downstream service instances in their respective zones. Locality-aware routing is an advanced feature that may adversely impact service capacity if used incorrectly. When enabled, Consul routes all traffic to the nearest set of service instances and only fails over when no healthy instances are available in the nearest set. ## Specify the locality of your Consul agents The `locality` configuration on a Consul client applies to all services registered to the client. -1. Configure the `locality` block in your Consul client agent configuration files. The `locality` block is a map containing the `region` and `zone` parameters. +1. Configure the `locality` block in your Consul client agent configuration files. The `locality` block is a map containing the `region` and `zone` parameters. The parameters should match the values for regions and zones defined in your network. Refer to [`locality`](/consul/docs/agent/config/config-files#locality) in the agent configuration reference for additional information. @@ -53,9 +59,9 @@ locality = { ## Specify the localities of your service instances (optional) --> This step is not typically required and should only be used if defining a custom network topology or your deployed environment requires explicitly setting the locality of certain services instances. Otherwise, follow the instructions above for VM workloads. For Kubernetes and ECS deployments using `consul-k8s` / `consul-ecs`, locality information will be inherited from the host machine. +This step is optional in most scenarios. Refer to [Workflow](#workflow) for additional information. -1. Configure the `locality` block in your service definition. The `locality` block is a map containing the `region` and `zone` parameters. When you start a proxy for the service, Consul passes the locality to the proxy so that it can route traffic accordingly. +1. Configure the `locality` block in your service definition for both downstream (client) and upstream services. The `locality` block is a map containing the `region` and `zone` parameters. When you start a proxy for the service, Consul passes the locality to the proxy so that it can route traffic accordingly. The parameters should match the values for regions and zones defined in your network. Refer to [`locality`](/consul/docs/services/configuration/services-configuration-reference#locality) in the services configuration reference for additional information. @@ -64,7 +70,7 @@ Register or re-register the service to apply the configuration. Refer to [Regist In the following example, the `web` service is available in the `us-west-1` region and `us-west-1a` zone on AWS: -```hcl +```hcl service { id = "web" locality = { @@ -83,23 +89,273 @@ You can configure the default routing behavior for all proxies in the mesh as we ### Configure default routing behavior -1. Configure the `PrioritizeByLocality` block in the proxy defaults configuration entry and specify the `failover` mode. This configuration enables proxies in the mesh to use the region and zone defined in the service configuration to route traffic. Refer to [`PrioritizeByLocality`](/consul/docs/connect/config-entries/proxy-defaults#prioritizebylocality) in the proxy defaults reference for details about the configuration. -1. Apply the configuration by either calling the [`/config` HTTP API endpoint](/consul/api-docs/config) or running the [`consul config write` CLI command](/consul/commands/config/write). +Configure the `PrioritizeByLocality` block in the proxy defaults configuration entry and specify the `failover` mode. This configuration enables proxies in the mesh to use the region and zone defined in the service configuration to route traffic. Refer to [`PrioritizeByLocality`](/consul/docs/connect/config-entries/proxy-defaults#prioritizebylocality) in the proxy defaults reference for details about the configuration. - The following example writes a proxy defaults configuration entry from a local HCL file using the CLI: + + + - ```shell-session - $ consul config write proxy-defaults.hcl - ``` +```hcl +Kind = "proxy-defaults" +Name = "global" +PrioritizeByLocality = { + Mode = "failover" +} +``` + + + + + + +```json +{ + "kind": "proxy-defaults", + "name": "global", + "prioritizeByLocality": { + "mode": "failover" + } +} +``` + + + + + +```yaml +apiversion: consul.hashicorp.com/v1alpha1 +kind: ProxyDefaults +metadata: + name: global +spec: + prioritizeByLocality: + mode: failover +``` + + + + + +Apply the configuration by either running the [`consul config write` CLI command](/consul/commands/config/write), applying the Kubernetes CRD, or calling the [`/config` HTTP API endpoint](/consul/api-docs/config). + + + + + ```shell-session + $ consul config write proxy-defaults.hcl + ``` + + + + + + ```shell-session + $ kubectl apply -f proxy-defaults.yaml + ``` + + + + + ```shell-session + $ curl --request PUT --data @proxy-defaults.hcl http://127.0.0.1:8500/v1/config + ``` + + + ### Configure routing behavior for individual service 1. Create a service resolver configuration entry and specify the following fields: - - `Name`: Specify the name of the target upstream service for which downstream clients should use locality-aware routing. + - `Name`: The name of the target upstream service for which downstream clients should use locality-aware routing. - `PrioritizeByLocality`: This block enables proxies in the mesh to use the region and zone defined in the service configuration to route traffic. Set the `mode` inside the block to `failover`. Refer to [`PrioritizeByLocality`](/consul/docs/connect/config-entries/service-resolver#prioritizebylocality) in the service resolver reference for details about the configuration. -1. Apply the configuration by either calling the [`/config` HTTP API endpoint](/consul/api-docs/config) or running the [`consul config write` CLI command](/consul/commands/config/write). - The following example writes a proxy defaults configuration entry from a local HCL file using the CLI: - ```shell-session - $ consul config write web-resolver.hcl + + + + + ```hcl + Kind = "service-resolver" + Name = "api" + PrioritizeByLocality = { + Mode = "failover" + } + ``` + + + + + + + ```json + { + "kind": "service-resolver", + "name": "api", + "prioritizeByLocality": { + "mode": "failover" + } + } ``` + + + + + + ```yaml + apiversion: consul.hashicorp.com/v1alpha1 + kind: ServiceResolver + metadata: + name: api + spec: + prioritizeByLocality: + mode: failover + ``` + + + + + +1. Apply the configuration by either running the [`consul config write` CLI command](/consul/commands/config/write), applying the Kubernetes CRD, or calling the [`/config` HTTP API endpoint](/consul/api-docs/config). + + + + + ```shell-session + $ consul config write api-resolver.hcl + ``` + + + + + + ```shell-session + $ kubectl apply -f api-resolver.yaml + ``` + + + + + ```shell-session + $ curl --request PUT --data @api-resolver.hcl http://127.0.0.1:8500/v1/config + ``` + + + + +### Configure locality on Kubernetes test clusters explicitly + +You can explicitly configure locality for each Kubernetes node so that you can test locality-aware routing with a local Kubernetes cluster or in an environment where `topology.kubernetes.io` labels are not set. + +Run the `kubectl label node` command and specify the locality as arguments. The following example specifies the `us-east-1` region and `us-east-1a` zone for the node: + +```shell-session +kubectl label node $K8S_NODE topology.kubernetes.io/region="us-east-1" topology.kubernetes.io/zone="us-east-1a" +``` + +After setting these values, subsequent service and proxy registrations in your cluster inherit the values from their local Kubernetes node. + +## Verify routes + +The routes from each downstream service instance to the nearest set of healthy upstream instances are the most immediately observable routing changes. + +Consul configures Envoy's built-in [`overprovisioning_factor`](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/endpoint/v3/endpoint.proto#config-endpoint-v3-clusterloadassignment) and [outlier detection](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/outlier_detection.proto#config-cluster-v3-outlierdetection) settings to enforce failover behavior. However, Envoy does not provide granular metrics specific to failover or endpoint traffic within a cluster. As a result, using external observability tools that expose network traffic within your environment is the best method for observing route changes. + +To verify that locality-aware routing and failover configurations, you can inspect Envoy's xDS configuration dump for a downstream proxy. Refer to the [consul-k8s CLI docs](https://developer.hashicorp.com/consul/docs/k8s/k8s-cli#proxy-read) for details on how to obtain the xDS configuration dump on Kubernetes. For other workloads, use the Envoy [admin interface](https://www.envoyproxy.io/docs/envoy/latest/operations/admin) and ensure that you [include EDS](https://www.envoyproxy.io/docs/envoy/latest/operations/admin#get--config_dump?include_eds). + +Inspect the [priority](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/priority#arch-overview-load-balancing-priority-levels) on each set of endpoints under the upstream `ClusterLoadAssignment` in the `EndpointsConfigDump`. Alternatively, the same priorities should be visible within the output of the [`/clusters?format=json`](https://www.envoyproxy.io/docs/envoy/latest/operations/admin#get--clusters?format=json) admin endpoint. + +```json +{ + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "cluster_name": "web.default.dc1.internal.161d7b5a-bb5f-379c-7d5a-1fc7504f95da.consul", + "endpoints": [ + { + "lb_endpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "10.42.2.6", + "port_value": 20000 + } + }, + "health_check_config": {} + }, + ... + }, + ... + ], + "locality": {} + }, + { + "lb_endpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "10.42.3.6", + "port_value": 20000 + } + }, + "health_check_config": {} + }, + ... + }, + ... + ], + "locality": {}, + "priority": 1 + }, + { + "lb_endpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "10.42.0.6", + "port_value": 20000 + } + }, + "health_check_config": {} + }, + ... + }, + ... + ], + "locality": {}, + "priority": 2 + } + ], + ... +} +``` + +### Force an observable failover + +To force a failover for testing purposes, scale the upstream service instances in the downstream's local zone or region, if no local zone instances are available, to `0`. + +Note the following behaviors: + + - Consul prioritizes failovers in ascending order starting with `0`. The highest priority, `0`, is not explicitly visible in xDS output. This is because `0` is the default value for that field. + - After Envoy failover configuration is in place, the specific timing of failover is determined by the downstream Envoy proxy, not Consul. Consul health status may not directly correspond to Envoy's failover behavior, which is also dependent on outlier detection. + +Refer to [Troubleshooting](#troubleshooting) if you do not observe the expected behavior. + +## Adjust load balancing and failover behavior + +You can adjust the global or per-service load balancing and failover behaviors by applying the property override Envoy extension. The property override extension allows you to set and remove individual properties on the Envoy resources Consul generates. Refer to [Configure Envoy proxy properties](/consul/docs/connect/proxies/envoy-extensions/usage/property-override) for additional information. + +1. Add the `EnvoyExtensions` configuration block to the service defaults or proxy defaults configuration entry. +1. Configure the following settings in the `EnvoyExtensions` configuration: + - [`overprovisioning_factor`](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/endpoint/v3/endpoint.proto#config-endpoint-v3-clusterloadassignment) + - [outlier detection](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/outlier_detection.proto#config-cluster-v3-outlierdetection) configuration. +1. Apply the configuration. Refer to [Apply the configuration entry](/consul/docs/connect/proxies/envoy-extensions/usage/property-override#apply-the-configuration-entry) for details. + +By default, Consul sets `overprovisioning_factor` to `100000`, which enforces total failover, and `max_ejection_percent` to `100`. Refer to the Envoy documentation about these fields before attempting to modify them. + +## Troubleshooting + +If you do not see the expected priorities, verify that locality is configured in the Consul agent and that `PrioritizeByLocality` is enabled in your proxy defaults or service resolver configuration entry. When `PrioritizeByLocality` is enabled but the local proxy lacks locality configuration, Consul emits a warning log to indicate that the policy could not be applied: + +``` +`no local service locality provided, skipping locality failover policy` +``` diff --git a/website/content/docs/connect/observability/service.mdx b/website/content/docs/connect/observability/service.mdx new file mode 100644 index 000000000000..55b4580aff7a --- /dev/null +++ b/website/content/docs/connect/observability/service.mdx @@ -0,0 +1,212 @@ +--- +layout: docs +page_title: Monitoring service-to-service communication with Envoy +description: >- + Learn to monitor the appropriate metrics when using Envoy proxy. +--- + +# Monitoring service-to-service communication with Envoy + +When running a service mesh with Envoy as the proxy, there are a wide array of possible metrics produced from traffic flowing through the data plane. This document covers a set of scenarios and key baseline metrics and potential alerts that will help you maintain the overall health and resilience of the mesh for HTTP services. In addition, it provides examples of using these metrics in specific ways to generate a Grafana dashboard using a Prometheus backend to better understand how the metrics behave. + +When collecting metrics, it is important to establish a baseline. This baseline ensures your Consul deployment is healthy, and serves as a reference point when troubleshooting abnormal Cluster behavior. Once you have established a baseline for your metrics, use them and the following recommendations to configure reasonable alerts for your Consul agent. + + + + The following examples assume that the operator adds the cluster name (i.e. datacenter) using the label “cluster” and the node name (i.e. machine or pod) using the label “node” to all scrape targets. + + + +## General scenarios + +### Is Envoy's configuration growing stale? + +When Envoy connects to the Consul control plane over xDS, it will rapidly converge to the current configuration that the control plane expects it to have. If the xDS stream terminates and does not reconnect for an extended period, then the xDS configuration currently in the Envoy instances will “fail static” and slowly grow out of date. + +##### Metric + +`envoy_control_plane_connected_state` + +#### Alerting + +If the value for a given node/pod/machine was 0 for an extended period of time. + +#### Example dashboard (table) + +``` +group(last_over_time(envoy_control_plane_connected_state{cluster="$cluster"}[1m] ) == 0) by (node) +``` + +## Inbound traffic scenarios + +### Is this service being sent requests? + +Within a mesh, a request travels from one service to another. You may choose to measure many relevant metrics from the calling-side, the serving-side, or both. + +It is useful to track the perceived request rate of requests from the calling-side as that would include all requests, even those that fail to arrive at the serving-side due to any failures. + +Any measurement of the request rate is also generally useful for capacity planning purposes as increased traffic typically correlates with a need for a scale-up event in the near future. + +##### Metric + +`envoy_cluster_upstream_rq_total` + +#### Alerting + +If the value has a significant change, check if services are properly interacting with each other and if you need to increase your Consul agent resource requirements. + +#### Example dashboard (plot; rate) + +``` +sum(irate(envoy_cluster_upstream_rq_total{consul_destination_datacenter="$cluster", +consul_destination_service="$service"}[1m])) by (cluster, local_cluster) +``` + +### Are requests sent to this service mostly successful? + +A service mesh is about communication between services, so it is important to track the perceived success rate of requests witnessed by the calling services. + +##### Metric + +`envoy_cluster_upstream_rq_xx` + +#### Alerting + +If the value crosses a user defined baseline. + +#### Example dashboard (plot; %) + +``` +sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!="5",consul_destination_datacenter="$cluster",consul_destination_service="$service"}[1m])) by (cluster, local_cluster) / sum(irate(envoy_cluster_upstream_rq_xx{consul_destination_datacenter="$cluster",consul_destination_service="$service"}[1m])) by (cluster, local_cluster) +``` + +### Are requests sent to this service handled in a timely manner? + +If you undersize your infrastructure from a resource perspective, then you may expect a decline in response speed over time. You can track this by plotting the 95th percentile of the latency as experienced by the clients. + +##### Metric + +`envoy_cluster_upstream_rq_time_bucket` + +#### Alerting + +If the value crosses a user defined baseline. + +#### Example dashboard (plot; value) + +``` +histogram_quantile(0.95, sum(rate(envoy_cluster_upstream_rq_time_bucket{consul_destination_datacenter="$cluster",consul_destination_service="$service",local_cluster!=""}[1m])) by (le, cluster, local_cluster)) +``` + +### Is this service responding to requests that it receives? + +Unlike the perceived request rate, which is measured from the calling side, this is the real request rate measured on the serving-side. This is a serving-side parallel metric that can help clarify underlying causes of problems in the calling-side equivalent metric. Ideally this metric should roughly track the calling side values in a 1-1 manner. + +##### Metric + +`envoy_http_downstream_rq_total` + +#### Alerting + +If the value crosses a user defined baseline. + +#### Example dashboard (plot; rate) + +``` +sum(irate(envoy_http_downstream_rq_total{cluster="$cluster",local_cluster="$service",envoy_http_conn_manager_prefix="public_listener"}[1m])) +``` + +### Are responses from this service mostly successful? + +Unlike the perceived success rate of requests, which is measured from the calling side, this is the real success rate of requests measured on the serving-side. This is a serving-side parallel metric that can help clarify underlying causes of problems in the calling-side equivalent metric. Ideally this metric should roughly track the calling side values in a 1-1 manner. + +##### Metrics + +`envoy_http_downstream_rq_total` + +`envoy_http_downstream_rq_xx` + +#### Alerting + +If the value crosses a user defined baseline. + +#### Example dashboard (plot; %) + +##### Total + +``` +sum(increase(envoy_http_downstream_rq_total{cluster="$cluster",local_cluster="$service",envoy_http_conn_manager_prefix="public_listener"}[1m])) +``` + +##### BY STATUS CODE: + +``` +sum(increase(envoy_http_downstream_rq_xx{cluster="$cluster",local_cluster="$service",envoy_http_conn_manager_prefix="public_listener"}[1m])) by (envoy_response_code_class) +``` + +## Outbound traffic scenarios + +### Is this service sending traffic to its upstreams? + +Similar to the real request rate for requests arriving at a service, it may be helpful to view the perceived request rate departing from a service through its upstreams. + +##### Metric + +`envoy_cluster_upstream_rq_total` + +#### Alerting + +If the value crosses a user defined success threshold. + +#### Example dashboard (plot; rate) + +``` +sum(irate(envoy_cluster_upstream_rq_total{cluster="$cluster", +local_cluster="$service", +consul_destination_target!=""}[1m])) by (consul_destination_target) +``` + +### Are requests from this service to its upstreams mostly successful? + +Similar to the real success rate of requests arriving at a service, it is also important to track the perceived success rate of requests departing from a service through its upstreams. + +##### Metric + +`envoy_cluster_upstream_rq_xx` + +#### Alerting + +If the value crosses a user defined success threshold. + +#### Example dashboard (plot; value) + +``` +sum(irate(envoy_cluster_upstream_rq_xx{envoy_response_code_class!="5", +cluster="$cluster",local_cluster="$service", +consul_destination_target!=""}[1m])) by (consul_destination_target) / sum(irate(envoy_cluster_upstream_rq_xx{cluster="$cluster",local_cluster="$service",consul_destination_target!=""}[1m])) by (consul_destination_target) +``` + +### Are requests from this service to its upstreams handled in a timely manner? + +Similar to the latency of requests departing for a service, it is useful to track the 95th percentile of the latency of requests departing from a service through its upstreams. + +##### Metric + +`envoy_cluster_upstream_rq_time_bucket` + +#### Alerting + +If the value crosses a user defined success threshold. + +#### Example dashboard (plot; value) + +``` +histogram_quantile(0.95, sum(rate(envoy_cluster_upstream_rq_time_bucket{cluster="$cluster", +local_cluster="$service",consul_target!=""}[1m])) by (le, consul_destination_target)) +``` + +## Next steps + +In this guide, you learned recommendations for monitoring your Envoy metrics, and why monitoring these metrics is important for your Consul deployment. + +To learn about monitoring Consul components, visit our [Monitoring Consul components](/well-architected-framework/reliability/reliability-consul-monitoring-consul-components) documentation. diff --git a/website/content/docs/connect/proxies/built-in.mdx b/website/content/docs/connect/proxies/built-in.mdx index 284bfa9035e9..93ec90bcb4e3 100644 --- a/website/content/docs/connect/proxies/built-in.mdx +++ b/website/content/docs/connect/proxies/built-in.mdx @@ -24,23 +24,25 @@ for the built-in proxy. "service": { "name": "example-service", "connect": { - "proxy": { - "config": { - "bind_address": "0.0.0.0", - "bind_port": 20000, - "local_service_address": "127.0.0.1:1234", - "local_connect_timeout_ms": 1000, - "handshake_timeout_ms": 10000, - "upstreams": [] - }, - "upstreams": [ - { - "destination_name": "example-upstream", - "config": { - "connect_timeout_ms": 1000 + "sidecar_service": { + "proxy": { + "config": { + "bind_address": "0.0.0.0", + "bind_port": 20000, + "local_service_address": "127.0.0.1:1234", + "local_connect_timeout_ms": 1000, + "handshake_timeout_ms": 10000, + "upstreams": [] + }, + "upstreams": [ + { + "destination_name": "example-upstream", + "config": { + "connect_timeout_ms": 1000 + } } - } - ] + ] + } } } } diff --git a/website/content/docs/connect/proxies/deploy-service-mesh-proxies.mdx b/website/content/docs/connect/proxies/deploy-service-mesh-proxies.mdx index 630da4a131de..0bb3f7df0389 100644 --- a/website/content/docs/connect/proxies/deploy-service-mesh-proxies.mdx +++ b/website/content/docs/connect/proxies/deploy-service-mesh-proxies.mdx @@ -1,13 +1,13 @@ --- layout: docs page_title: Deploy service mesh proxies -description: >- +description: >- Envoy and other proxies in Consul service mesh enable service-to-service communication across your network. Learn how to deploy service mesh proxies in this topic. --- # Deploy service mesh proxies services -This topic describes how to create, register, and start service mesh proxies in Consul. Refer to [Service mesh proxies overview](/consul/docs/connect/proxies) for additional information about how proxies enable Consul functionalities. +This topic describes how to create, register, and start service mesh proxies in Consul. Refer to [Service mesh proxies overview](/consul/docs/connect/proxies) for additional information about how proxies enable Consul functionalities. For information about deploying proxies as sidecars for service instances, refer to [Deploy sidecar proxy services](/consul/docs/connect/proxies/deploy-sidecar-services). @@ -15,7 +15,7 @@ For information about deploying proxies as sidecars for service instances, refer Complete the following steps to deploy a service mesh proxy: -1. It is not required, but you can create a proxy defaults configuration entry that contains global passthrough settings for all Envoy proxies. +1. It is not required, but you can create a proxy defaults configuration entry that contains global passthrough settings for all Envoy proxies. 1. Create a service definition file and specify the proxy configurations in the `proxy` block. 1. Register the service using the API or CLI. 1. Start the proxy service. Proxies appear in the list of services registered to Consul, but they must be started before they begin to route traffic in your service mesh. @@ -31,29 +31,29 @@ If you want to define global passthrough settings for all Envoy proxies, create 1. Create a proxy defaults configuration entry and specify the following parameters: - `Kind`: Must be set to `proxy-defaults` - `Name`: Must be set to `global` -1. Configure any additional settings you want to apply to all proxies. Refer to [Proxy defaults configuration entry reference](/consul/docs/connect/config-entries/proxy-defaults) for details about all settings available in the configuraiton entry. +1. Configure any additional settings you want to apply to all proxies. Refer to [Proxy defaults configuration entry reference](/consul/docs/connect/config-entries/proxy-defaults) for details about all settings available in the configuration entry. 1. Apply the configuration by either calling the [`/config` HTTP API endpoint](/consul/api-docs/config) or running the [`consul config write` CLI command](/consul/commands/config/write). The following example writes a proxy defaults configuration entry from a local HCL file using the CLI: ```shell-session $ consul config write proxy-defaults.hcl ``` -## Define service mesh proxy +## Define service mesh proxy Create a service definition file and configure the following fields to define a service mesh proxy: 1. Set the `kind` field to `connect-proxy`. Refer to the [services configuration reference](/consul/docs/services/configuration/services-configuration-reference#kind) for information about other kinds of proxies you can declare. 1. Specify a name for the proxy service in the `name` field. Consul applies the configurations to any proxies you bootstrap with the same name. -1. In the `proxy.destination_service_name` field, specify the name of the service that the proxy represents. -1. Configure any additional proxy behaviors that you want to implement in the `proxy` block. Refer to the [Service mesh proxy configuration reference](/consul/docs/connect/proxies/proxy-config-reference) for information about all parameters. +1. In the `proxy.destination_service_name` field, specify the name of the service that the proxy represents. +1. Configure any additional proxy behaviors that you want to implement in the `proxy` block. Refer to the [Service mesh proxy configuration reference](/consul/docs/connect/proxies/proxy-config-reference) for information about all parameters. 1. Specify a port number where other services registered with Consul can discover and connect to the proxies service in the `port` field. To ensure that services only allow external connections established through the service mesh protocol, you should configure all services to only accept connections on a loopback address. Refer to the [Service mesh proxy configuration reference](/consul/docs/connect/proxies/proxy-config-reference) for example configurations. -## Register the service +## Register the service Provide the service definition to the Consul agent to register your proxy service. You can use the same methods for registering proxy services as you do for registering application services: - + - Place the service definition in a Consul agent's configuration directory and start, restart, or reload the agent. Use this method when implementing changes to an existing proxy service. - Use the `consul services register` command to register the proxy service with a running Consul agent. - Call the `/agent/service/register` HTTP API endpoint to register the proxy service with a running Consul agent. @@ -68,7 +68,7 @@ $ consul services register proxy.hcl ## Start the proxy -Envoy requires a bootstrap configuration file before it can start. Use the [`consul connect envoy` command](/consul/commands/connect/envoy) to create the Envoy bootstrap configuration and start the proxy service. Specify the ID of the proxy you want to start with the `-proxy-id` option. +Envoy requires a bootstrap configuration file before it can start. Use the [`consul connect envoy` command](/consul/commands/connect/envoy) to create the Envoy bootstrap configuration and start the proxy service. Specify the ID of the proxy you want to start with the `-proxy-id` option. The following example command starts an Envoy proxy for the `web-proxy` service: @@ -76,4 +76,4 @@ The following example command starts an Envoy proxy for the `web-proxy` service: $ consul connect envoy -proxy-id=web-proxy ``` -For details about operating an Envoy proxy in Consul, refer to the [Envoy proxy reference](/consul/docs/connect/proxies/envoy). +For details about operating an Envoy proxy in Consul, refer to the [Envoy proxy reference](/consul/docs/connect/proxies/envoy). diff --git a/website/content/docs/connect/proxies/deploy-sidecar-services.mdx b/website/content/docs/connect/proxies/deploy-sidecar-services.mdx index ad533b59468e..c42a5b2c7f5f 100644 --- a/website/content/docs/connect/proxies/deploy-sidecar-services.mdx +++ b/website/content/docs/connect/proxies/deploy-sidecar-services.mdx @@ -11,15 +11,15 @@ This topic describes how to create, register, and start sidecar proxy services i ## Overview -Sidecar proxies run on the same node as the single service instance that they handle traffic for. -They may be on the same VM or running as a separate container in the same network namespace. +Sidecar proxies run on the same node as the single service instance that they handle traffic for. +They may be on the same VM or running as a separate container in the same network namespace. You can attach a sidecar proxy to a service you want to deploy to your mesh: -1. It is not required, but you can create a proxy defaults configuration entry that contains global passthrough settings for all Envoy proxies. +1. It is not required, but you can create a proxy defaults configuration entry that contains global passthrough settings for all Envoy proxies. 1. Create the service definition and include the `connect` block. The `connect` block contains the sidecar proxy configurations that allow the service to interact with other services in the mesh. 1. Register the service using either the API or CLI. -1. Start the sidecar proxy service. +1. Start the sidecar proxy service. ## Requirements @@ -32,21 +32,21 @@ If you want to define global passthrough settings for all Envoy proxies, create 1. Create a proxy defaults configuration entry and specify the following parameters: - `Kind`: Must be set to `proxy-defaults` - `Name`: Must be set to `global` -1. Configure any additional settings you want to apply to all proxies. Refer to [Proxy defaults configuration entry reference](/consul/docs/connect/config-entries/proxy-defaults) for details about all settings available in the configuraiton entry. +1. Configure any additional settings you want to apply to all proxies. Refer to [Proxy defaults configuration entry reference](/consul/docs/connect/config-entries/proxy-defaults) for details about all settings available in the configuration entry. 1. Apply the configuration by either calling the [`/config` API endpoint](/consul/api-docs/config) or running the [`consul config write` CLI command](/consul/commands/config/write). The following example writes a proxy defaults configuration entry from a local HCL file using the CLI: ```shell-session $ consul config write proxy-defaults.hcl ``` -## Define service mesh proxy +## Define service mesh proxy -Create a service definition and configure the following fields: +Create a service definition and configure the following fields: -1. `name`: Specify a name for the service you want to attach a sidecar proxy to in the `name` field. This field is required for all services you want to register in Consul. +1. `name`: Specify a name for the service you want to attach a sidecar proxy to in the `name` field. This field is required for all services you want to register in Consul. 1. `port`: Specify a port number where other services registered with Consul can discover and connect to the service in the `port` field. This field is required for all services you want to register in Consul. 1. `connect`: Set the `connect` field to `{ sidecar_service: {} }`. The `{ sidecar_service: {} }` value is a macro that applies a set of default configurations that enable you to quickly implement a sidecar. Refer to [Sidecar service defaults](#sidecar-service-defaults) for additional information. -1. Configure any additional options for your service. Refer to [Services configuration reference](/consul/docs/services/configuration/services-configuration-reference) for details. +1. Configure any additional options for your service. Refer to [Services configuration reference](/consul/docs/services/configuration/services-configuration-reference) for details. In the following example, a service named `web` is configured with a sidecar proxy: @@ -60,7 +60,7 @@ service = { port = 8080 connect = { sidecar_service = {} } } -``` +``` @@ -89,7 +89,7 @@ When Consul processes the service definition, it generates the following configu ```hcl -services = [ +services = [ { name = "web" port = 8080 @@ -114,7 +114,7 @@ services = [ } ] -``` +``` @@ -156,12 +156,12 @@ services = [ - + -## Register the service +## Register the service Provide the service definition to the Consul agent to register your proxy service. You can use the same methods for registering proxy services as you do for registering application services: - + - Place the service definition in a Consul agent's configuration directory and start, restart, or reload the agent. Use this method when implementing changes to an existing proxy service. - Use the `consul services register` command to register the proxy service with a running Consul agent. - Call the `/agent/service/register` HTTP API endpoint to register the proxy service with a running Consul agent. @@ -176,7 +176,7 @@ $ consul services register proxy.hcl ## Start the proxy -Envoy requires a bootstrap configuration file before it can start. Use the [`consul connect envoy` command](/consul/commands/connect/envoy) to create the Envoy bootstrap configuration and start the proxy service. Specify the name of the service with the attached proxy with the `-sidecar-for` option. +Envoy requires a bootstrap configuration file before it can start. Use the [`consul connect envoy` command](/consul/commands/connect/envoy) to create the Envoy bootstrap configuration and start the proxy service. Specify the name of the service with the attached proxy with the `-sidecar-for` option. The following example command starts an Envoy sidecar proxy for the `web` service: @@ -184,11 +184,11 @@ The following example command starts an Envoy sidecar proxy for the `web` servic $ consul connect envoy -sidecar-for=web ``` -For details about operating an Envoy proxy in Consul, refer to [](/consul/docs/connect/proxies/envoy) +For details about operating an Envoy proxy in Consul, refer to [](/consul/docs/connect/proxies/envoy) ## Configuration reference -The `sidecar_service` block is a service definition that can contain most regular service definition fields. Refer to [Limitations](#limitations) for information about unsupported service definition fields for sidecar proxies. +The `sidecar_service` block is a service definition that can contain most regular service definition fields. Refer to [Limitations](#limitations) for information about unsupported service definition fields for sidecar proxies. Consul treats sidecar proxy service definitions as a root-level service definition. All fields are optional in nested definitions, which default to opinionated settings that are intended to reduce burden of setting up a sidecar proxy. @@ -224,7 +224,7 @@ proxy. In the following example, the `sidecar_service` macro sets baselines configurations for the proxy, but the [proxy upstreams](/consul/docs/connect/proxies/proxy-config-reference#upstream-configuration-reference) and [built-in proxy -configuration](/consul/docs/connect/proxies/built-in) fields contain custom values: +configuration](/consul/docs/connect/proxies/built-in) fields contain custom values: ```json { @@ -281,4 +281,4 @@ service's ID, which enables the following behavior. - When reloading the configuration files, if a service definition changes its ID, then a new service instance and a new sidecar instance are registered. The old instance and proxy are removed because they are no longer found in - the configuration files. \ No newline at end of file + the configuration files. diff --git a/website/content/docs/connect/proxies/envoy-extensions/index.mdx b/website/content/docs/connect/proxies/envoy-extensions/index.mdx index 79f1dbb1f37d..8fd19feed384 100644 --- a/website/content/docs/connect/proxies/envoy-extensions/index.mdx +++ b/website/content/docs/connect/proxies/envoy-extensions/index.mdx @@ -21,6 +21,7 @@ Instead of modifying Consul code, you can configure your services to use Envoy e Envoy extensions enable additional service mesh functionality in Consul by changing how the sidecar proxies behave. Extensions dynamically modify the configuration of Envoy proxies based on Consul configuration entries, enabling a wider set of use cases for the service mesh traffic that passes through an Envoy proxy. Consul supports the following extensions: - External authorization +- Fault injection - Lua - Lambda - OpenTelemetry Access Logging @@ -31,6 +32,10 @@ Envoy extensions enable additional service mesh functionality in Consul by chang The `ext-authz` extension lets you configure external authorization filters for Envoy proxy so that you can route requests to external authorization systems. Refer to the [external authorization documentation](/consul/docs/connect/proxies/envoy-extensions/usage/ext-authz) for more information. +### Fault injection + +The `fault-injection` extension lets you alter responses from an upstream service so that users can test the resilience of their system to different unexpected issues. Refer to the [fault injection documentation](/consul/docs/connect/manage-traffic/fault-injection) for more information. + ### Lambda The `lambda` Envoy extension enables services to make requests to AWS Lambda functions through the mesh as if they are a normal part of the Consul catalog. Refer to the [Lambda extension documentation](/consul/docs/connect/proxies/envoy-extensions/usage/lambda) for more information. diff --git a/website/content/docs/connect/proxies/envoy.mdx b/website/content/docs/connect/proxies/envoy.mdx index 890d980f4cb5..010986de2ce8 100644 --- a/website/content/docs/connect/proxies/envoy.mdx +++ b/website/content/docs/connect/proxies/envoy.mdx @@ -31,27 +31,115 @@ Envoy must be run with the `--max-obj-name-len` option set to `256` or greater f ## Supported Versions -The following matrix describes Envoy compatibility for the currently supported **n-2 major Consul releases**. For previous Consul version compatibility please view the respective versioned docs for this page. +The following matrix describes Envoy compatibility for the +currently supported major Consul releases: +- The latest (N) release of Consul community edition (CE) and Enterprise +- The 2 preceding major releases (N-1 and N-2) of Consul Enterprise +- The 2 latest [Consul Enterprise LTS](/consul/docs/enterprise/long-term-support) major releases + +For previous Consul version compatibility, +refer to the previous release's version of this page. ### Envoy and Consul Client Agent -Consul supports **four major Envoy releases** at the beginning of each major Consul release. Consul maintains compatibility with Envoy patch releases for each major version so that users can benefit from bug and security fixes in Envoy. As a policy, Consul will add support for a new major versions of Envoy in a Consul major release. Support for newer versions of Envoy will not be added to existing releases. +Every major Consul release initially supports **four major Envoy releases**. +However, [Consul Enterprise Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) +releases expand their Envoy version compatibility window in minor releases to +ensure compatibility with a maintained Envoy version. Standard (non-LTS) Consul +Enterprise releases may also expand support to a new major version of Envoy in +order to receive important security fixes, if the previous major Envoy version +has reached end-of-life. -| Consul Version | Compatible Envoy Versions | -| ------------------- | -----------------------------------------------------------------------------------| -| 1.17.x | 1.27.2, 1.26.6, 1.25.11, 1.24.12 | -| 1.16.x | 1.26.6, 1.25.11, 1.24.12, 1.23.12 | -| 1.15.x | 1.25.11, 1.24.12, 1.23.12, 1.22.11 | +Every major Consul release maintains and tests compatibility with specific Envoy +patch releases to ensure users can benefit from bug and security fixes in Envoy. -### Envoy and Consul Dataplane +#### Standard releases + +Unless otherwise noted, rows in the following compatibility table +apply to both Consul Enterprise and Consul community edition (CE). + +| Consul Version | Compatible Envoy Versions | +| -------------- | -------------------------------------- | +| 1.20.x CE | 1.31.x, 1.30.x, 1.29.x, 1.28.x | +| 1.19.x CE | 1.29.x, 1.28.x, 1.27.x, 1.26.x | +| 1.18.x CE | 1.28.x, 1.27.x, 1.26.x, 1.25.x | +| 1.17.x | 1.27.x, 1.26.x, 1.25.x, 1.24.x | +| 1.16.x | 1.26.x, 1.25.x, 1.24.x, 1.23.x | -The Consul dataplane component was introduced in Consul v1.14 as a way to manage Envoy proxies without the use of Consul clients. Each new minor version of Consul is released with a new minor version of Consul dataplane, which packages both Envoy and the `consul-dataplane` binary in a single container image. For backwards compatibility reasons, each new minor version of Consul will also support the previous minor version of Consul dataplane to allow for seamless upgrades. In addition, each minor version of Consul will support the next minor version of Consul dataplane to allow for extended dataplane support via newer versions of Envoy. +#### Enterprise Long Term Support releases -| Consul Version | Default `consul-dataplane` Version | Other compatible `consul-dataplane` Versions | -| ------------------- | ------------------------------------------------------------|----------------------------------------------| -| 1.17.x | 1.3.x (Envoy 1.27.x) | 1.2.x (Envoy 1.26.x) | -| 1.16.x | 1.2.x (Envoy 1.26.x) | 1.3.x (Envoy 1.27.x), 1.1.x (Envoy 1.25.x) | -| 1.15.x | 1.1.x (Envoy 1.25.x) | 1.2.x (Envoy 1.26.x), 1.0.x (Envoy 1.24.x) | +Active Consul Enterprise +[Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) +releases expand their Envoy version compatibility window +until the LTS release reaches its end of maintenance. + +| Consul Version | Compatible Envoy Versions | +| -------------- | -----------------------------------------------------------------------------------| +| 1.18.x Ent | 1.29.x, 1.28.x, 1.27.x, 1.26.x, 1.25.x | +| 1.15.x Ent | 1.29.x, 1.28.x, 1.27.x, 1.26.x, 1.25.x, 1.24.x, 1.23.x, 1.22.x | + +### Envoy and Consul Dataplane + +The Consul dataplane component was introduced in Consul v1.14 +as a way to manage Envoy proxies without the use of Consul clients. + +Each major version of Consul is released with a new major version of Consul dataplane, +which packages both Envoy and the `consul-dataplane` binary in a single container image. +To enable seamless upgrades, each major version of Consul also supports +the previous and next Consul dataplane versions. + +Compared to community edition releases, Consul Enterprise releases have +the following differences with Consul dataplane compatibility: +- [LTS-Only: Expanded compatibility window](#enterprise-long-term-support-releases): + Active Consul Enterprise LTS releases expand their Consul dataplane + version compatibility window to include the version of Consul dataplane + aligned with the next Consul LTS release. +- [Maintained Envoy version](#consul-dataplane-releases-that-span-envoy-major-versions): + Major versions of Consul dataplane aligned with a maintained Consul + Enterprise version may contain minor version updates that use a new + major version of Envoy. These minor version updates are necessary to + ensure that maintained versions of Consul dataplane use a maintained + version of Envoy. + +#### Standard releases + +Unless otherwise noted, rows in the following compatibility table +apply to both Consul Enterprise and Consul community edition (CE). + +| Consul Version | Default `consul-dataplane` Version | Other compatible `consul-dataplane` Versions | +| -------------- | -------------------------------------|----------------------------------------------| +| 1.20.x CE | 1.6.x (Envoy 1.31.x) | 1.5.x (Envoy 1.29.x) | +| 1.19.x CE | 1.5.x (Envoy 1.29.x) | 1.4.x (Envoy 1.28.x) | +| 1.18.x CE | 1.4.x (Envoy 1.28.x) | 1.3.x (Envoy 1.27.x) | +| 1.17.x | 1.3.x (Envoy 1.27.x) | 1.4.x (Envoy 1.28.x), 1.2.x (Envoy 1.26.x) | +| 1.16.x | 1.2.x (Envoy 1.26.x) | 1.3.x (Envoy 1.27.x), 1.1.x (Envoy 1.25.x) | + +#### Enterprise Long Term Support releases + +Active Consul Enterprise +[Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) +releases expand their Envoy version compatibility window +until the LTS release reaches its end of maintenance. + +| Consul Version | Default `consul-dataplane` Version | Other compatible `consul-dataplane` Versions | +| -------------- | -------------------------------------|----------------------------------------------| +| 1.19.x Ent | 1.5.x (Envoy 1.29.x) | 1.4.x (Envoy 1.28.x) | +| 1.18.x Ent | 1.4.x (Envoy 1.28.x) | 1.3.x (Envoy 1.27.x) | +| 1.15.x Ent | 1.1.x (Envoy 1.26.x) | 1.4.x (Envoy 1.28.x) - 1.0.x (Envoy 1.24.x) | + +#### Consul dataplane releases that span Envoy major versions + +Major versions of Consul dataplane aligned with active versions of Consul +may contain minor version updates that use a new major version of Envoy. +These minor version updates are necessary to ensure maintained versions +of Consul dataplane use a maintained version of Envoy including important +security fixes. + +| `consul-dataplane` Version Range | Associated Consul Enterprise version | Contained Envoy Binary Version | +| -------------------------------- | ---------------------------------------- | ------------------------------ | +| 1.1.11 - 1.1.latest | 1.15.x Ent | Envoy 1.27.x | +| 1.1.9 - 1.1.10 | 1.15.x Ent | Envoy 1.26.x | +| 1.1.0 - 1.1.8 | 1.15.x Ent | Envoy 1.25.x | ## Getting Started @@ -194,6 +282,7 @@ the [`sidecar_service`](/consul/docs/connect/proxies/deploy-sidecar-services) bl - `envoy_telemetry_collector_bind_socket_dir` - Specifies the directory where Envoy creates a Unix socket. Envoy sends metrics to the socket where a Consul telemetry collector can collect them. The socket is not configured by default. + Enabling this sets Envoy's [`stats_flush_interval`](https://www.envoyproxy.io/docs/envoy/v1.17.2/api-v3/config/bootstrap/v3/bootstrap.proto#envoy-v3-api-field-config-bootstrap-v3-bootstrap-stats-flush-interval) to one minute if `envoy_stats_flush_interval` is unset and if no other stats sinks are configured, like `envoy_dogstats_url`, for instance. The [Advanced Configuration](#advanced-configuration) section describes additional configurations that allow incremental or complete control over the bootstrap configuration generated. @@ -223,7 +312,15 @@ Then, open `bootstrap.json` and update the following sections with your ACL toke ```json { "admin": { - "access_log_path": "/dev/null", + "access_log": [ + { + "name": "envoy.access_loggers.file", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", + "path": "/dev/null" + } + } + ], "address": { "socket_address": { "address": "127.0.0.1", @@ -356,6 +453,8 @@ defaults that are inherited by all services. - `exact_balance` - Inbound connections to the service use the [Envoy Exact Balance Strategy.](https://cloudnative.to/envoy/api-v3/config/listener/v3/listener.proto.html#config-listener-v3-listener-connectionbalanceconfig-exactbalance) +- `xds_fetch_timeout_ms` - In milliseconds, the amount of time for Envoy to wait for EDS and RDS configuration before timing out. If not specified, this field uses Envoy's default value of `15000`, or 15 seconds. When an Envoy instance is configured with a large number of upstreams that take a significant amount of time to populate with data, setting this field to a higher value may prevent temporary disruption caused by unexpected timeouts. + ### Proxy Upstream Config Options The following configuration items may be overridden directly in the diff --git a/website/content/docs/connect/security.mdx b/website/content/docs/connect/security.mdx index 42ce8d0d1e49..cefcaa3be21d 100644 --- a/website/content/docs/connect/security.mdx +++ b/website/content/docs/connect/security.mdx @@ -26,12 +26,50 @@ of Consul. ## Checklist +### Default Intention Policy Set + +Consul should be configured with a default deny intention policy. This forces +all service-to-service communication to be explicitly +allowed via an allow [intention](/consul/docs/connect/intentions). + +One advantage of using a default deny policy in combination with specific "allow" rules +is that a failure of intentions due to misconfiguration always results in +_denied_ traffic, rather than unwanted _allowed_ traffic. + +In the absence of `default_intention_policy` Consul will fall back to the ACL +default policy when determining whether to allow or deny communications without +an explicit intention. + +### Request Normalization Configured for L7 Intentions + +~> **Compatibility warning**: This feature is available as of Consul CE 1.20.1 and Consul Enterprise 1.20.1, 1.19.2, 1.18.3, and 1.15.15. We recommend upgrading to the latest version of Consul to take advantage of the latest features and improvements. + +Atypical traffic patterns may interfere with the enforcement of L7 intentions. For +example, if a service makes request to a non-normalized URI path and Consul is not +configured to force path normalization, it becomes possible to circumvent path match rules. While a +default deny policy can limit the impact of this issue, we still recommend +that you review your current request normalization configuration. Normalization is critical to avoid unwanted +traffic, especially when using unrecommended security options such as a default allow intentions policy. + +Consul adopts a default normalization mode that adheres to [RFC 3986]( +https://tools.ietf.org/html/rfc3986#section-6), but additional options to enable stricter +normalization are available in the cluster-wide [Mesh configuration entry]( +/consul/docs/connect/config-entries/mesh). We recommend reviewing these options and +enabling the strictest set that does not interfere with application traffic. + +We also recommend that you review L7 intention header match rules for potential +issues with multiple header values. Refer to the [service intentions +configuration entry reference](/consul/docs/connect/config-entries/service-intentions#spec-sources-permissions-http-header) +for more information. + +You do not need to enable request normalization if you are not using L7 intentions. +However, normalization may also benefit the use of other service mesh features that +rely on L7 attribute matching, such as [service routers](/consul/docs/connect/manage-traffic#routing). + ### ACLs Enabled with Default Deny Consul must be configured to use ACLs with a default deny policy. This forces -all requests to have explicit anonymous access or provide an ACL token. The -configuration also forces all service-to-service communication to be explicitly -allowed via an allow [intention](/consul/docs/connect/intentions). +all requests to have explicit anonymous access or provide an ACL token. To learn how to enable ACLs, please see the [tutorial on ACLs](/consul/tutorials/security/access-control-setup-production). @@ -43,6 +81,10 @@ this. **If ACLs are not enabled**, deny intentions will still be enforced, but a may edit intentions. This renders the security of the created intentions effectively useless. +The advantage of a default deny policy in combination with specific "allow" rules +is that at worst, a failure of intentions due to misconfiguration will result in +_denied_ traffic, rather than unwanted _allowed_ traffic. + ### TCP and UDP Encryption Enabled TCP and UDP encryption must be enabled to prevent plaintext communication @@ -100,7 +142,7 @@ will not be encrypted or authorized via service mesh. Envoy exposes an **unauthenticated** [administration interface](https://www.envoyproxy.io/docs/envoy/latest/operations/admin) -that can be used to query and modify the proxy. This interface +that can be used to query and modify the proxy. This interface allows potentially sensitive information to be retrieved, such as: * Envoy configuration diff --git a/website/content/docs/dynamic-app-config/kv.mdx b/website/content/docs/dynamic-app-config/kv.mdx deleted file mode 100644 index 982c7729380d..000000000000 --- a/website/content/docs/dynamic-app-config/kv.mdx +++ /dev/null @@ -1,120 +0,0 @@ ---- -layout: docs -page_title: Key/Value (KV) Store Overview -description: >- - Consul includes a KV store for indexed objects, configuration parameters, and metadata that you can use to dynamically configure apps. Learn about accessing and using the KV store to extend Consul's functionality through watches, sessions, and Consul Template. ---- - -# Key/Value (KV) Store Overview - - -The Consul KV API, CLI, and UI are now considered feature complete and no new feature development is planned for future releases. - - -Consul KV is a core feature of Consul and is installed with the Consul agent. -Once installed with the agent, it will have reasonable defaults. Consul KV allows -users to store indexed objects, though its main uses are storing configuration -parameters and metadata. Please note that it is a simple KV store and is not -intended to be a full featured datastore (such as DynamoDB) but has some -similarities to one. - -The Consul KV datastore is located on the servers, but can be accessed by any -agent (client or server). The natively integrated [RPC -functionality](/consul/docs/architecture) allows clients to forward -requests to servers, including key/value reads and writes. Part of Consul's -core design allows data to be replicated automatically across all the servers. -Having a quorum of servers will decrease the risk of data loss if an outage -occurs. - -If you have not used Consul KV, complete this [Getting Started -tutorial](/consul/tutorials/interactive/get-started-key-value-store?utm_source=docs) on HashiCorp. - -## Accessing the KV store - -The KV store can be accessed by the [consul kv CLI -subcommands](/consul/commands/kv), [HTTP API](/consul/api-docs/kv), and Consul UI. -To restrict access, enable and configure -[ACLs](/consul/tutorials/security/access-control-setup-production). -Once the ACL system has been bootstrapped, users and services, will need a -valid token with KV [privileges](/consul/docs/security/acl/acl-rules#key-value-rules) to -access the data store, this includes even reads. We recommend creating a -token with limited privileges, for example, you could create a token with write -privileges on one key for developers to update the value related to their -application. - -The datastore itself is located on the Consul servers in the [data -directory](/consul/docs/agent/config/cli-flags#_data_dir). To ensure data is not lost in -the event of a complete outage, use the [`consul snapshot`](/consul/commands/snapshot/restore) feature to backup the data. - -## Using Consul KV - -Objects are opaque to Consul, meaning there are no restrictions on the type of -object stored in a key/value entry. The main restriction on an object is size - -the maximum is 512 KB. Due to the maximum object size and main use cases, you -should not need extra storage; the general [sizing -recommendations](/consul/docs/agent/config/config-files#kv_max_value_size) -are usually sufficient. - -Keys, like objects are not restricted by type and can include any character. -However, we recommend using URL-safe chars - `[a-zA-Z0-9-._~]` with the -exception of `/`, which can be used to help organize data. Note, `/` will be -treated like any other character and is not fixed to the file system. Meaning, -including `/` in a key does not fix it to a directory structure. This model is -similar to Amazon S3 buckets. However, `/` is still useful for organizing data -and when recursively searching within the data store. We also recommend that -you avoid the use of `*`, `?`, `'`, and `%` because they can cause issues when -using the API and in shell scripts. - -## Using Sentinel to apply policies for Consul KV - - - -This feature requires -HashiCorp Cloud Platform (HCP) or self-managed Consul Enterprise. - - - -You can also use Sentinel as a Policy-as-code framework for defining advanced key-value storage access control policies. Sentinel policies extend the ACL system in Consul beyond static "read", "write", -and "deny" policies to support full conditional logic and integration with -external systems. Reference the [Sentinel documentation](https://docs.hashicorp.com/sentinel/concepts) for high-level Sentinel concepts. - -To get started with Sentinel in Consul, -refer to the [Sentinel documentation](https://docs.hashicorp.com/sentinel/consul) or -[Consul documentation](/consul/docs/agent/sentinel). - - -## Extending Consul KV - -### Consul Template - -If you plan to use Consul KV as part of your configuration management process -review the [Consul -Template](/consul/tutorials/developer-configuration/consul-template?utm_source=docs) -tutorial on how to update configuration based on value updates in the KV. Consul -Template is based on Go Templates and allows for a series of scripted actions -to be initiated on value changes to a Consul key. - -### Watches - -Consul KV can also be extended with the use of watches. -[Watches](/consul/docs/dynamic-app-config/watches) are a way to monitor data for updates. When -an update is detected, an external handler is invoked. To use watches with the -KV store the [key](/consul/docs/dynamic-app-config/watches#key) watch type should be used. - -### Consul Sessions - -Consul sessions can be used to build distributed locks with Consul KV. Sessions -act as a binding layer between nodes, health checks, and key/value data. The KV -API supports an `acquire` and `release` operation. The `acquire` operation acts -like a Check-And-Set operation. On success, there is a key update and an -increment to the `LockIndex` and the session value is updated to reflect the -session holding the lock. Review the session documentation for more information -on the [integration](/consul/docs/dynamic-app-config/sessions#k-v-integration). - -Review the following tutorials to learn how to use Consul sessions for [application leader election](/consul/tutorials/developer-configuration/application-leader-elections) and -to [build distributed semaphores](/consul/tutorials/developer-configuration/distributed-semaphore). - -### Vault - -If you plan to use Consul KV as a backend for Vault, please review [this -tutorial](/vault/tutorials/day-one-consul/ha-with-consul?utm_source=docs). diff --git a/website/content/docs/dynamic-app-config/kv/index.mdx b/website/content/docs/dynamic-app-config/kv/index.mdx new file mode 100644 index 000000000000..677037321d67 --- /dev/null +++ b/website/content/docs/dynamic-app-config/kv/index.mdx @@ -0,0 +1,120 @@ +--- +layout: docs +page_title: Key/Value (KV) Store Overview +description: >- + Consul includes a KV store for indexed objects, configuration parameters, and metadata that you can use to dynamically configure apps. Learn about accessing and using the KV store to extend Consul's functionality through watches, sessions, and Consul Template. +--- + +# Key/Value (KV) Store Overview + + +The Consul KV API, CLI, and UI are now considered feature complete and no new feature development is planned for future releases. + + +Consul KV is a core feature of Consul and is installed with the Consul agent. +Once installed with the agent, it will have reasonable defaults. Consul KV allows +users to store indexed objects, though its main uses are storing configuration +parameters and metadata. Please note that it is a simple KV store and is not +intended to be a full featured datastore (such as DynamoDB) but has some +similarities to one. + +The Consul KV datastore is located on the servers, but can be accessed by any +agent (client or server). The natively integrated [RPC +functionality](/consul/docs/architecture) allows clients to forward +requests to servers, including key/value reads and writes. Part of Consul's +core design allows data to be replicated automatically across all the servers. +Having a quorum of servers will decrease the risk of data loss if an outage +occurs. + +If you have not used Consul KV, complete this [Getting Started +tutorial](/consul/tutorials/interactive/get-started-key-value-store?utm_source=docs) on HashiCorp. + +## Accessing the KV store + +The KV store can be accessed by the [consul kv CLI +subcommands](/consul/commands/kv), [HTTP API](/consul/api-docs/kv), and Consul UI. +To restrict access, enable and configure +[ACLs](/consul/tutorials/security/access-control-setup-production). +Once the ACL system has been bootstrapped, users and services, will need a +valid token with KV [privileges](/consul/docs/security/acl/acl-rules#key-value-rules) to +access the data store, this includes even reads. We recommend creating a +token with limited privileges, for example, you could create a token with write +privileges on one key for developers to update the value related to their +application. + +The datastore itself is located on the Consul servers in the [data +directory](/consul/docs/agent/config/cli-flags#_data_dir). To ensure data is not lost in +the event of a complete outage, use the [`consul snapshot`](/consul/commands/snapshot/restore) feature to backup the data. + +## Using Consul KV + +Objects are opaque to Consul, meaning there are no restrictions on the type of +object stored in a key/value entry. The main restriction on an object is size - +the maximum is 512 KB. Due to the maximum object size and main use cases, you +should not need extra storage; the general [sizing +recommendations](/consul/docs/agent/config/config-files#kv_max_value_size) +are usually sufficient. + +Keys, like objects are not restricted by type and can include any character. +However, we recommend using URL-safe chars - `[a-zA-Z0-9-._~]` with the +exception of `/`, which can be used to help organize data. Note, `/` will be +treated like any other character and is not fixed to the file system. Meaning, +including `/` in a key does not fix it to a directory structure. This model is +similar to Amazon S3 buckets. However, `/` is still useful for organizing data +and when recursively searching within the data store. We also recommend that +you avoid the use of `*`, `?`, `'`, and `%` because they can cause issues when +using the API and in shell scripts. + +## Using Sentinel to apply policies for Consul KV + + + +This feature requires +HashiCorp Cloud Platform (HCP) or self-managed Consul Enterprise. + + + +You can also use Sentinel as a Policy-as-code framework for defining advanced key-value storage access control policies. Sentinel policies extend the ACL system in Consul beyond static "read", "write", +and "deny" policies to support full conditional logic and integration with +external systems. Reference the [Sentinel documentation](https://docs.hashicorp.com/sentinel/concepts) for high-level Sentinel concepts. + +To get started with Sentinel in Consul, +refer to the [Sentinel documentation](https://docs.hashicorp.com/sentinel/consul) or +[Consul documentation](/consul/docs/agent/sentinel). + + +## Extending Consul KV + +### Consul Template + +If you plan to use Consul KV as part of your configuration management process +review the [Consul +Template](/consul/tutorials/developer-configuration/consul-template?utm_source=docs) +tutorial on how to update configuration based on value updates in the KV. Consul +Template is based on Go Templates and allows for a series of scripted actions +to be initiated on value changes to a Consul key. + +### Watches + +Consul KV can also be extended with the use of watches. +[Watches](/consul/docs/dynamic-app-config/watches) are a way to monitor data for updates. When +an update is detected, an external handler is invoked. To use watches with the +KV store the [key](/consul/docs/dynamic-app-config/watches#key) watch type should be used. + +### Consul Sessions + +Consul sessions can be used to build distributed locks with Consul KV. Sessions +act as a binding layer between nodes, health checks, and key/value data. The KV +API supports an `acquire` and `release` operation. The `acquire` operation acts +like a Check-And-Set operation. On success, there is a key update and an +increment to the `LockIndex` and the session value is updated to reflect the +session holding the lock. Review the session documentation for more information +on the [integration](/consul/docs/dynamic-app-config/sessions#k-v-integration). + +Review the following tutorials to learn how to use Consul sessions for [application leader election](/consul/docs/dynamic-app-config/sessions/application-leader-election) and +to [build distributed semaphores](/consul/tutorials/developer-configuration/distributed-semaphore). + +### Vault + +If you plan to use Consul KV as a backend for Vault, please review [this +tutorial](/vault/tutorials/day-one-consul/ha-with-consul?utm_source=docs). diff --git a/website/content/docs/dynamic-app-config/kv/store.mdx b/website/content/docs/dynamic-app-config/kv/store.mdx new file mode 100644 index 000000000000..b5e99cc4bde5 --- /dev/null +++ b/website/content/docs/dynamic-app-config/kv/store.mdx @@ -0,0 +1,89 @@ +--- +layout: docs +page_title: Store and access key/value data +description: >- + Consul includes a key/value store for that you can use to dynamically configure apps. Learn how to add and manage data in the Consul KV store using the Consul + command-line interface. +--- + +# Store and access key/value data + +This page describes the processes for interacting with Consul's KV store. You can interact with the KV store using the [`consul kv` CLI command](/consul/commands/kv) or the [`/kv` endpoint](/consul/api-docs/kv). + +## Add data to KV store + +To insert values into the KV store or update an existing value, use the `consul kv put` command. The first entry after the command is the key and the second entry is the value. + +```shell-session +$ consul kv put redis/config/minconns 1 +Success! Data written to: redis/config/minconns +``` + +In the following example, the key is `redis/config/maxconns` and the value is set to `25`. + +```shell-session +$ consul kv put redis/config/maxconns 25 +Success! Data written to: redis/config/maxconns +``` + +In the following example, the command includes a `flags` value of 42. Keys support setting a 64-bit integer flag value that is not used internally by Consul but can be used by clients to add metadata to a KV pair. + +```shell-session +$ consul kv put -flags=42 redis/config/users/admin zaphod +Success! Data written to: redis/config/users/admin +``` + +## Query data from KV store + +To query for the value of one of the keys in the KV store, use the `consul kv get` command. + +```shell-session +$ consul kv get redis/config/minconns +1 +``` + +To retrieve metadata you included as `flags`, using the `-detailed` command line flag. + +```shell-session +$ consul kv get -detailed redis/config/users/admin +``` + +```plaintext hideClipboard +CreateIndex 14 +Flags 42 +Key redis/config/users/admin +LockIndex 0 +ModifyIndex 14 +Session - +Value zaphod +``` + +To list all the keys in the store, use the `recurse` option. Results return in lexicographical order. + +```shell-session +$ consul kv get -recurse +``` + +```plaintext hideClipboard +redis/config/maxconns:25 +redis/config/minconns:1 +redis/config/users/admin:zaphod +``` + +## Delete data + +To delete the value of one of the keys in the KV store, use the `consul kv delete` command. + +```shell-session +$ consul kv delete redis/config/minconns +Success! Deleted key: redis/config/minconns +``` + +Although the keys in the KV store are stored in a flat structure, you can manipulate keys that share a prefix as a group, as if they were in folders or subfolders, by using the `-recurse` flag. + +The following example deletes all the keys with the `redis` prefix using the `-recurse` option. + +```shell-session +$ consul kv delete -recurse redis +Success! Deleted keys with prefix: redis +``` \ No newline at end of file diff --git a/website/content/docs/dynamic-app-config/sessions.mdx b/website/content/docs/dynamic-app-config/sessions.mdx deleted file mode 100644 index eb0c4cf49511..000000000000 --- a/website/content/docs/dynamic-app-config/sessions.mdx +++ /dev/null @@ -1,144 +0,0 @@ ---- -layout: docs -page_title: Sessions and Distributed Locks Overview -description: >- - Consul supports sessions that you can use to build distributed locks with granular locking. Learn about sessions, how they can prevent ""split-brain"" systems by ensuring consistency in deployments, and how they can integrate with the key/value (KV) store. ---- - -# Sessions and Distributed Locks Overview - -Consul provides a session mechanism which can be used to build distributed locks. -Sessions act as a binding layer between nodes, health checks, and key/value data. -They are designed to provide granular locking and are heavily inspired by -[The Chubby Lock Service for Loosely-Coupled Distributed Systems](http://research.google.com/archive/chubby.html). - -## Session Design - -A session in Consul represents a contract that has very specific semantics. -When a session is constructed, a node name, a list of health checks, a behavior, -a TTL, and a `lock-delay` may be provided. The newly constructed session is provided with -a named ID that can be used to identify it. This ID can be used with the KV -store to acquire locks: advisory mechanisms for mutual exclusion. - -Below is a diagram showing the relationship between these components: - -![Consul Sessions](/img/consul-sessions.png) - -The contract that Consul provides is that under any of the following -situations, the session will be _invalidated_: - -- Node is deregistered -- Any of the health checks are deregistered -- Any of the health checks go to the critical state -- Session is explicitly destroyed -- TTL expires, if applicable - -When a session is invalidated, it is destroyed and can no longer -be used. What happens to the associated locks depends on the -behavior specified at creation time. Consul supports a `release` -and `delete` behavior. The `release` behavior is the default -if none is specified. - -If the `release` behavior is being used, any of the locks held in -association with the session are released, and the `ModifyIndex` of -the key is incremented. Alternatively, if the `delete` behavior is -used, the key corresponding to any of the held locks is simply deleted. -This can be used to create ephemeral entries that are automatically -deleted by Consul. - -While this is a simple design, it enables a multitude of usage -patterns. By default, the -[gossip based failure detector](/consul/docs/architecture/gossip) -is used as the associated health check. This failure detector allows -Consul to detect when a node that is holding a lock has failed and -to automatically release the lock. This ability provides **liveness** to -Consul locks; that is, under failure the system can continue to make -progress. However, because there is no perfect failure detector, it's possible -to have a false positive (failure detected) which causes the lock to -be released even though the lock owner is still alive. This means -we are sacrificing some **safety**. - -Conversely, it is possible to create a session with no associated -health checks. This removes the possibility of a false positive -and trades liveness for safety. You can be absolutely certain Consul -will not release the lock even if the existing owner has failed. -Since Consul APIs allow a session to be force destroyed, this allows -systems to be built that require an operator to intervene in the -case of a failure while precluding the possibility of a split-brain. - -A third health checking mechanism is session TTLs. When creating -a session, a TTL can be specified. If the TTL interval expires without -being renewed, the session has expired and an invalidation is triggered. -This type of failure detector is also known as a heartbeat failure detector. -It is less scalable than the gossip based failure detector as it places -an increased burden on the servers but may be applicable in some cases. -The contract of a TTL is that it represents a lower bound for invalidation; -that is, Consul will not expire the session before the TTL is reached, but it -is allowed to delay the expiration past the TTL. The TTL is renewed on -session creation, on session renew, and on leader failover. When a TTL -is being used, clients should be aware of clock skew issues: namely, -time may not progress at the same rate on the client as on the Consul servers. -It is best to set conservative TTL values and to renew in advance of the TTL -to account for network delay and time skew. - -The final nuance is that sessions may provide a `lock-delay`. This -is a time duration, between 0 and 60 seconds. When a session invalidation -takes place, Consul prevents any of the previously held locks from -being re-acquired for the `lock-delay` interval; this is a safeguard -inspired by Google's Chubby. The purpose of this delay is to allow -the potentially still live leader to detect the invalidation and stop -processing requests that may lead to inconsistent state. While not a -bulletproof method, it does avoid the need to introduce sleep states -into application logic and can help mitigate many issues. While the -default is to use a 15 second delay, clients are able to disable this -mechanism by providing a zero delay value. - -## K/V Integration - -Integration between the KV store and sessions is the primary -place where sessions are used. A session must be created prior to use -and is then referred to by its ID. - -The KV API is extended to support an `acquire` and `release` operation. -The `acquire` operation acts like a Check-And-Set operation except it -can only succeed if there is no existing lock holder (the current lock holder -can re-`acquire`, see below). On success, there is a normal key update, but -there is also an increment to the `LockIndex`, and the `Session` value is -updated to reflect the session holding the lock. - -If the lock is already held by the given session during an `acquire`, then -the `LockIndex` is not incremented but the key contents are updated. This -lets the current lock holder update the key contents without having to give -up the lock and reacquire it. - -Once held, the lock can be released using a corresponding `release` operation, -providing the same session. Again, this acts like a Check-And-Set operation -since the request will fail if given an invalid session. A critical note is -that the lock can be released without being the creator of the session. -This is by design as it allows operators to intervene and force-terminate -a session if necessary. As mentioned above, a session invalidation will also -cause all held locks to be released or deleted. When a lock is released, the `LockIndex` -does not change; however, the `Session` is cleared and the `ModifyIndex` increments. - -These semantics (heavily borrowed from Chubby), allow the tuple of (Key, LockIndex, Session) -to act as a unique "sequencer". This `sequencer` can be passed around and used -to verify if the request belongs to the current lock holder. Because the `LockIndex` -is incremented on each `acquire`, even if the same session re-acquires a lock, -the `sequencer` will be able to detect a stale request. Similarly, if a session is -invalided, the Session corresponding to the given `LockIndex` will be blank. - -To be clear, this locking system is purely _advisory_. There is no enforcement -that clients must acquire a lock to perform any operation. Any client can -read, write, and delete a key without owning the corresponding lock. It is not -the goal of Consul to protect against misbehaving clients. - -## Leader Election - -The primitives provided by sessions and the locking mechanisms of the KV -store can be used to build client-side leader election algorithms. -These are covered in more detail in the [Leader Election guide](/consul/tutorials/developer-configuration/application-leader-elections). - -## Prepared Query Integration - -Prepared queries may be attached to a session in order to automatically delete -the prepared query when the session is invalidated. diff --git a/website/content/docs/dynamic-app-config/sessions/application-leader-election.mdx b/website/content/docs/dynamic-app-config/sessions/application-leader-election.mdx new file mode 100644 index 000000000000..5b14bcdc9e10 --- /dev/null +++ b/website/content/docs/dynamic-app-config/sessions/application-leader-election.mdx @@ -0,0 +1,396 @@ +--- +layout: docs +page_title: Application leader election +description: >- + Learn how to perform client-side leader elections using sessions and Consul key/value (KV) store. +--- + +# Application leader election + +This topic describes the process for building client-side leader elections for service instances using Consul's [session mechanism for building distributed locks](/consul/docs/dynamic-app-config/sessions) and the [Consul key/value store](/consul/docs/dynamic-app-config/kv), which is Consul's key/value datastore. + +This topic is not related to Consul's leader election. For more information about the Raft leader election used internally by Consul, refer to +[consensus protocol](/consul/docs/architecture/consensus) documentation. + +## Background + +Some distributed applications, like HDFS or ActiveMQ, require setting up one instance as a leader to ensure application data is current and stable. + +Consul's support for [sessions](/consul/docs/dynamic-app-config/sessions) and [watches](/consul/docs/dynamic-app-config/watches) allows you to build a client-side leader election process where clients use a lock on a key in the KV datastore to ensure mutual exclusion and to gracefully handle failures. + +All service instances that are participating should coordinate on a key format. We recommend the following pattern: + +```plaintext +service//leader +``` + +## Requirements + +- A running Consul server +- A path in the Consul KV datastore to acquire locks and to store information about the leader. The instructions on this page use the following key: `service/leader`. +- If ACLs are enabled, a token with the following permissions: + - `session:write` permissions over the service session name + - `key:write` permissions over the key + - The `curl` command + +Expose the token using the `CONSUL_HTTP_TOKEN` environment variable. + +## Client-side leader election procedure + +The workflow for building a client-side leader election process has the following steps: + +- For each client trying to acquire the lock: + 1. [Create a session](#create-a-new-session) associated with the client node. + 1. [Acquire the lock](#acquire-the-lock) on the designated key in the KV store using the `acquire` parameter. + 1. [Watch the KV key](#watch-the-kv-key-for-locks) to verify if the lock was released. If no lock is present, try to acquire a lock. + +- For the client that acquires the lock: + 1. Periodically, [renew the session](#renew-a-session) to avoid expiration. + 1. Optionally, [release the lock](#release-a-lock). + +- For other services: + 1. [Watch the KV key](#watch-the-kv-key-for-locks) to verify there is at least one process holding the lock. + 1. Use the values written under the KV path to identify the leader and update configurations accordingly. + +## Create a new session + +Create a configuration for the session. +The minimum viable configuration requires that you specify the session name. The following example demonstrates this configuration. + + + +```json +{ + "Name": "session_name" +} +``` + + + +Create a session using the [`/session` Consul HTTP API](/consul/api-docs/session) endpoint. In the following example, the node's `hostname` is the session name. + +```shell-session +$ curl --silent \ + --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ + --data '{"Name": "'`hostname`'"}' \ + --request PUT \ + http://127.0.0.1:8500/v1/session/create | jq +``` + + +The command returns a JSON object containing the ID of the newly created session. + +```json +{ + "ID": "d21d60ad-c2d2-b32a-7432-ca4048a4a7d6" +} +``` + +### Verify session + +Use the `/v1/session/list` endpoint to retrieve existing sessions. + +```shell-session +$ curl --silent \ + --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ + --request GET \ + http://127.0.0.1:8500/v1/session/list | jq +``` + +The command returns a JSON array containing all available sessions in the system. + + + +```json +[ + { + "ID": "d21d60ad-c2d2-b32a-7432-ca4048a4a7d6", + "Name": "hashicups-db-0", + "Node": "hashicups-db-0", + "LockDelay": 15000000000, + "Behavior": "release", + "TTL": "", + "NodeChecks": [ + "serfHealth" + ], + "ServiceChecks": null, + "CreateIndex": 11956, + "ModifyIndex": 11956 + } +] +``` + + + +You can verify from the output that the session is associated with the `hashicups-db-0` node, which is the client agent where the API request was made. + +With the exception of the `Name`, all parameters are set to their default values. The session is created without a `TTL` value, which means that it never expires and requires you to delete it explicitly. + +Depending on your needs you can create sessions specifying more parameters such as: + +- `TTL` - If provided, the session is invalidated and deleted if it is not renewed before the TTL expires. +- `ServiceChecks` - Specifies a list of service checks to monitor. The session is invalidated if the checks return a critical state. + +By setting these extra parameters, you can create a client-side leader election workflow that automatically releases the lock after a specified amount of time since the last renew, or that automatically releases locks when the service holding them fails. + +For a full list of parameters available refer to the [`/session/create` endpoint documentation](/consul/api-docs/session#create-session). + +## Acquire the lock + +Create the data object to associate to the lock request. + +The data of the request should be a JSON object representing the local instance. This value is opaque to Consul, but it should contain whatever information clients require to communicate with your application. For example, it could be a JSON object that contains the node's name and the application's port. + + + +```json +{ + "Node": "node-name", + "Port": "8080" +} +``` + + + + + + +Acquire a lock for a given key using the PUT method on a [KV entry](/consul/api-docs/kv) with the +`?acquire=` query parameter. + +```shell-session +$ curl --silent \ + --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ + --data '{"Node": "'`hostname`'"}' \ + --request PUT \ + http://localhost:8500/v1/kv/service/leader?acquire=d21d60ad-c2d2-b32a-7432-ca4048a4a7d6 | jq +``` + +This request returns either `true` or `false`. If `true`, the lock was acquired and +the local service instance is now the leader. If `false`, a different node acquired +the lock. + + + + + +```shell-session +$ consul kv put -acquire -session=d21d60ad-c2d2-b32a-7432-ca4048a4a7d6 /service/leader '{"Node": "'`hostname`'"}' +``` + +In case of success, the command exits with exit code `0` and outputs the following message. + + + +```plaintext +Success! Lock acquired on: service/leader +``` + + + +If the lock was already acquired by another node, the command exits with exit code `1` and outputs the following message. + + + +```plaintext +Error! Did not acquire lock +``` + + + + + + +This example used the node's `hostname` as the key data. This data can be used by the other services to create configuration files. + +Be aware that this locking system has no enforcement mechanism that requires clients to acquire a lock before they perform an operation. Any client can read, write, and delete a key without owning the corresponding lock. + +## Watch the KV key for locks + +Existing locks need to be monitored by all nodes involved in the client-side leader elections, as well as by the other nodes that need to know the identity of the leader. + + - Lock holders need to monitor the lock because the session might get invalidated by an operator. + - Other services that want to acquire the lock need to monitor it to check if the lock is released so they can try acquire the lock. + - Other nodes need to monitor the lock to see if the value of the key changed and update their configuration accordingly. + + + + +Monitor the lock using the GET method on a [KV entry](/consul/api-docs/kv) with the blocking query enabled. + +First, verify the latest index for the current value. + +```shell-session +$ curl --silent \ + --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ + --request GET \ + http://127.0.0.1:8500/v1/kv/service/leader?index=1 | jq +``` + +The command outputs the key data, including the `ModifyIndex` for the object. + + + +```json +[ + { + "LockIndex": 0, + "Key": "service/leader", + "Flags": 0, + "Value": "eyJOb2RlIjogImhhc2hpY3Vwcy1kYi0wIn0=", + "Session": "d21d60ad-c2d2-b32a-7432-ca4048a4a7d6", + "CreateIndex": 12399, + "ModifyIndex": 13061 + } +] +``` + + + +Using the value of the `ModifyIndex`, run a [blocking query](/consul/api-docs/features/blocking) against the lock. + +```shell-session +$ curl --silent \ + --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ + --request GET \ + http://127.0.0.1:8500/v1/kv/service/leader?index=13061 | jq +``` +The command hangs until a change is made on the KV path and after that the path data prints on the console. + + + +```json +[ + { + "LockIndex": 0, + "Key": "service/leader", + "Flags": 0, + "Value": "eyJOb2RlIjogImhhc2hpY3Vwcy1kYi0xIn0=", + "Session": "d21d60ad-c2d2-b32a-7432-ca4048a4a7d6", + "CreateIndex": 12399, + "ModifyIndex": 13329 + } +] +``` + + + +For automation purposes, add logic to the blocking query mechanism to trigger a command every time a change is returned. +A better approach is to use the CLI command `consul watch`. + + + + +Monitor the lock using the [`consul watch`](/consul/commands/watch) command. + +```shell-session +$ consul watch -type=key -key=service/leader cat | jq +``` + +In this example, the command output prints to the shell. However, it is possible to pass more complex option to the command as well as a script that contains more complex logic to react to the lock data change. + +An example output for the command is: + + + +```json +{ + "Key": "service/leader", + "CreateIndex": 12399, + "ModifyIndex": 13061, + "LockIndex": 0, + "Flags": 0, + "Value": "eyJOb2RlIjogImhhc2hpY3Vwcy1kYi0wIn0=", + "Session": "d21d60ad-c2d2-b32a-7432-ca4048a4a7d6" +} +``` + + + +The `consul watch` command polls the KV path for changes and runs the specified command on the output when a change is made. + + + + +From the output, notice that once the lock is acquired, the `Session` parameter contains the ID of the session that holds the lock. + +## Renew a session + +If a session is created with a `TTL` value set, you need to renew the session before the TTL expires. + +Use the [`/v1/session/renew`](/consul/api-docs/session#renew-session) endpoint to renew existing sessions. + +```shell-session +$ curl --silent \ + --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ + --request PUT \ + http://127.0.0.1:8500/v1/session/renew/f027470f-2759-6b53-542d-066ae4185e67 | jq +``` + +If the command succeeds, the session information in JSON format is printed. + + + +```json +[ + { + "ID": "f027470f-2759-6b53-542d-066ae4185e67", + "Name": "test", + "Node": "consul-server-0", + "LockDelay": 15000000000, + "Behavior": "release", + "TTL": "30s", + "NodeChecks": [ + "serfHealth" + ], + "ServiceChecks": null, + "CreateIndex": 11842, + "ModifyIndex": 11842 + } +] +``` + + + +## Release a lock + +A lock associated with a session with no `TTL` value set might never be released, even when the service holding it fails. + +In such cases, you need to manually release the lock. + + + + +```shell-session +$ curl --silent \ + --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ + --data '{"Node": "'`hostname`'"}' \ + --request PUT \ + http://localhost:8500/v1/kv/service/leader?release=d21d60ad-c2d2-b32a-7432-ca4048a4a7d6 | jq +``` + +The command prints `true` on success. + + + + +```shell-session +$ consul kv put -release -session=d21d60ad-c2d2-b32a-7432-ca4048a4a7d6 service/leader '{"Node": "'`hostname`'"}' +``` + +On success, the command outputs a success message. + + + +```plaintext +Success! Lock released on: service/leader +``` + + + + + + +After a lock is released, the key data do not show a value for `Session` in the results. +Other clients can use this as a way to coordinate their lock requests. + diff --git a/website/content/docs/dynamic-app-config/sessions/index.mdx b/website/content/docs/dynamic-app-config/sessions/index.mdx new file mode 100644 index 000000000000..3eb26f558f52 --- /dev/null +++ b/website/content/docs/dynamic-app-config/sessions/index.mdx @@ -0,0 +1,144 @@ +--- +layout: docs +page_title: Sessions and Distributed Locks Overview +description: >- + Consul supports sessions that you can use to build distributed locks with granular locking. Learn about sessions, how they can prevent ""split-brain"" systems by ensuring consistency in deployments, and how they can integrate with the key/value (KV) store. +--- + +# Sessions and Distributed Locks Overview + +Consul provides a session mechanism which can be used to build distributed locks. +Sessions act as a binding layer between nodes, health checks, and key/value data. +They are designed to provide granular locking and are heavily inspired by +[The Chubby Lock Service for Loosely-Coupled Distributed Systems](http://research.google.com/archive/chubby.html). + +## Session Design + +A session in Consul represents a contract that has very specific semantics. +When a session is constructed, a node name, a list of health checks, a behavior, +a TTL, and a `lock-delay` may be provided. The newly constructed session is provided with +a named ID that can be used to identify it. This ID can be used with the KV +store to acquire locks: advisory mechanisms for mutual exclusion. + +Below is a diagram showing the relationship between these components: + +![Consul Sessions](/img/consul-sessions.png) + +The contract that Consul provides is that under any of the following +situations, the session will be _invalidated_: + +- Node is deregistered +- Any of the health checks are deregistered +- Any of the health checks go to the critical state +- Session is explicitly destroyed +- TTL expires, if applicable + +When a session is invalidated, it is destroyed and can no longer +be used. What happens to the associated locks depends on the +behavior specified at creation time. Consul supports a `release` +and `delete` behavior. The `release` behavior is the default +if none is specified. + +If the `release` behavior is being used, any of the locks held in +association with the session are released, and the `ModifyIndex` of +the key is incremented. Alternatively, if the `delete` behavior is +used, the key corresponding to any of the held locks is simply deleted. +This can be used to create ephemeral entries that are automatically +deleted by Consul. + +While this is a simple design, it enables a multitude of usage +patterns. By default, the +[gossip based failure detector](/consul/docs/architecture/gossip) +is used as the associated health check. This failure detector allows +Consul to detect when a node that is holding a lock has failed and +to automatically release the lock. This ability provides **liveness** to +Consul locks; that is, under failure the system can continue to make +progress. However, because there is no perfect failure detector, it's possible +to have a false positive (failure detected) which causes the lock to +be released even though the lock owner is still alive. This means +we are sacrificing some **safety**. + +Conversely, it is possible to create a session with no associated +health checks. This removes the possibility of a false positive +and trades liveness for safety. You can be absolutely certain Consul +will not release the lock even if the existing owner has failed. +Since Consul APIs allow a session to be force destroyed, this allows +systems to be built that require an operator to intervene in the +case of a failure while precluding the possibility of a split-brain. + +A third health checking mechanism is session TTLs. When creating +a session, a TTL can be specified. If the TTL interval expires without +being renewed, the session has expired and an invalidation is triggered. +This type of failure detector is also known as a heartbeat failure detector. +It is less scalable than the gossip based failure detector as it places +an increased burden on the servers but may be applicable in some cases. +The contract of a TTL is that it represents a lower bound for invalidation; +that is, Consul will not expire the session before the TTL is reached, but it +is allowed to delay the expiration past the TTL. The TTL is renewed on +session creation, on session renew, and on leader failover. When a TTL +is being used, clients should be aware of clock skew issues: namely, +time may not progress at the same rate on the client as on the Consul servers. +It is best to set conservative TTL values and to renew in advance of the TTL +to account for network delay and time skew. + +The final nuance is that sessions may provide a `lock-delay`. This +is a time duration, between 0 and 60 seconds. When a session invalidation +takes place, Consul prevents any of the previously held locks from +being re-acquired for the `lock-delay` interval; this is a safeguard +inspired by Google's Chubby. The purpose of this delay is to allow +the potentially still live leader to detect the invalidation and stop +processing requests that may lead to inconsistent state. While not a +bulletproof method, it does avoid the need to introduce sleep states +into application logic and can help mitigate many issues. While the +default is to use a 15 second delay, clients are able to disable this +mechanism by providing a zero delay value. + +## K/V Integration + +Integration between the KV store and sessions is the primary +place where sessions are used. A session must be created prior to use +and is then referred to by its ID. + +The KV API is extended to support an `acquire` and `release` operation. +The `acquire` operation acts like a Check-And-Set operation except it +can only succeed if there is no existing lock holder (the current lock holder +can re-`acquire`, see below). On success, there is a normal key update, but +there is also an increment to the `LockIndex`, and the `Session` value is +updated to reflect the session holding the lock. + +If the lock is already held by the given session during an `acquire`, then +the `LockIndex` is not incremented but the key contents are updated. This +lets the current lock holder update the key contents without having to give +up the lock and reacquire it. + +Once held, the lock can be released using a corresponding `release` operation, +providing the same session. Again, this acts like a Check-And-Set operation +since the request will fail if given an invalid session. A critical note is +that the lock can be released without being the creator of the session. +This is by design as it allows operators to intervene and force-terminate +a session if necessary. As mentioned above, a session invalidation will also +cause all held locks to be released or deleted. When a lock is released, the `LockIndex` +does not change; however, the `Session` is cleared and the `ModifyIndex` increments. + +These semantics (heavily borrowed from Chubby), allow the tuple of (Key, LockIndex, Session) +to act as a unique "sequencer". This `sequencer` can be passed around and used +to verify if the request belongs to the current lock holder. Because the `LockIndex` +is incremented on each `acquire`, even if the same session re-acquires a lock, +the `sequencer` will be able to detect a stale request. Similarly, if a session is +invalided, the Session corresponding to the given `LockIndex` will be blank. + +To be clear, this locking system is purely _advisory_. There is no enforcement +that clients must acquire a lock to perform any operation. Any client can +read, write, and delete a key without owning the corresponding lock. It is not +the goal of Consul to protect against misbehaving clients. + +## Leader Election + +You can use the primitives provided by sessions and the locking mechanisms of the KV +store to build client-side leader election algorithms. +These are covered in more detail in the [Leader Election guide](/consul/docs/dynamic-app-config/sessions/application-leader-election). + +## Prepared Query Integration + +Prepared queries may be attached to a session in order to automatically delete +the prepared query when the session is invalidated. diff --git a/website/content/docs/ecs/architecture.mdx b/website/content/docs/ecs/architecture.mdx index 0f35b11b6dab..96823ae1bd6a 100644 --- a/website/content/docs/ecs/architecture.mdx +++ b/website/content/docs/ecs/architecture.mdx @@ -9,28 +9,40 @@ description: >- This topic provides reference information about the Consul's deployment architecture on AWS ECS. The following diagram shows the main components of the Consul architecture when deployed to an ECS cluster. -![Diagram that provides an overview of the Consul Architecture on ECS](/img/ecs/consul-on-ecs-architecture-dataplanes.jpg#light-theme-only) -![Diagram that provides an overview of the Consul Architecture on ECS ](/img/ecs/consul-on-ecs-architecture-dataplanes-dark.jpg#dark-theme-only) +![Diagram that provides an overview of the Consul Architecture on ECS](/img/ecs/consul-on-ecs-architecture-dataplanes.png#light-theme-only) +![Diagram that provides an overview of the Consul Architecture on ECS ](/img/ecs/consul-on-ecs-architecture-dataplanes-dark.png#dark-theme-only) ## Components -Consul starts several components and containers inside the ECS cluster. Refer to [Startup sequence](#startup-sequence) for details about the order of the startup procedure: + +Consul starts several components and containers inside the ECS cluster. Using a combination of short-lived containers (`mesh-init`) and long-lived containers (`health-sync`) ensures that any long running containers do not have root access to Consul. Refer to [Startup sequence](#startup-sequence) for details about the order of the startup procedure. -### Control-plane container +### `mesh-init` container -The control-plane container performs the following actions: +The `mesh-init` container is a short-lived container that performs the following actions: - Logs into Consul servers - Communicates directly with Consul server - Registers proxies and services - Creates a bootstrap configuration file for Consul dataplane container and stores it in a shared volume +- Invokes the `iptables` SDK to configure traffic redirection rules + +### `health-sync` container + +The `health-sync` container is a long-lived container that performs the following actions: + - Synchronizes ECS health checks - Watches the Consul server for changes -### Dataplane containers +When you stop the ECS task, it performs the following actions: + +- Deregisters service and proxy instances on receiving SIGTERM to support graceful shutdown +- Performs logout from [ACL auth method](/consul/docs/security/acl/auth-methods) + +### `dataplane` container The dataplane process runs in the same container as the Envoy proxy and performs the following actions: -- Consumes and configures itself according to the bootstrap configuration written by the control-plane container. +- Consumes and configures itself according to the bootstrap configuration written by the `mesh-init` container. - Contains and starts up the Envoy sidecar. ### ECS controller container @@ -48,13 +60,14 @@ One ECS task in the cluster contains the controller container, which performs th Deploying Consul to ECS starts the following process to build the architecture: -1. The control-plane container starts and logs into Consul. -1. The control-plane container registers services and proxies with the Consul servers. -1. The control-plane container writes the bootstrap configuration for the Consul dataplane process and stores it in a shared volume. -1. The dataplane container starts and configures itself using the bootstrap configuration generated by the control-plane container. -1. The dataplane container starts the Envoy sidecar proxy. -1. The control-plane container starts listening for ECS health checks. -1. When the ECS task indicates that the application instance is healthy, the control-plane container marks the service as healthy and starts allowing traffic to flow. +1. The `mesh-init` container starts and logs in to Consul. +1. The `mesh-init` container registers services and proxies with the Consul servers. +1. The `mesh-init` container writes the bootstrap configuration for the Consul dataplane process and stores it in a shared volume. +1. The `mesh-init` container configures Consul DNS and modifies traffic redirection rules. +1. The `dataplane` container starts and configures itself using the bootstrap configuration generated by the `mesh-init` container. +1. The `dataplane` container starts the Envoy sidecar proxy. +1. The `health-sync` container starts listening for ECS health checks. +1. When the ECS task indicates that the application instance is healthy, the `health-sync` container marks the service as healthy and allows traffic to flow. ## Consul security components diff --git a/website/content/docs/ecs/deploy/bind-addresses.mdx b/website/content/docs/ecs/deploy/bind-addresses.mdx index 0eea916687b8..acee9209ea70 100644 --- a/website/content/docs/ecs/deploy/bind-addresses.mdx +++ b/website/content/docs/ecs/deploy/bind-addresses.mdx @@ -17,8 +17,8 @@ Binding workloads to the loopback address ensures that your application only rec Consul service mesh must be deployed to ECS before you can bind a network address. For more information, refer to the following topics: -- [Deploy Consul to ECS using the Terraform module](/consul/docs/ecs/deploy/install-terraform) -- [Deploy Consul to ECS manually](/consul/docs/ecs/deploy/install-manual) +- [Deploy Consul to ECS using the Terraform module](/consul/docs/ecs/deploy/terraform) +- [Deploy Consul to ECS manually](/consul/docs/ecs/deploy/manual) ## Change the listening address diff --git a/website/content/docs/ecs/deploy/configure-routes.mdx b/website/content/docs/ecs/deploy/configure-routes.mdx index 11014f99a3ce..ed9b99610488 100644 --- a/website/content/docs/ecs/deploy/configure-routes.mdx +++ b/website/content/docs/ecs/deploy/configure-routes.mdx @@ -20,8 +20,8 @@ To enable tasks to call through the service mesh, complete the following steps: Consul service mesh must be deployed to ECS before you can bind a network address. For more information, refer to the following topics: -- [Deploy Consul to ECS using the Terraform module](/consul/docs/ecs/deploy/install-terraform) -- [Deploy Consul to ECS manually](/consul/docs/ecs/deploy/install-manual) +- [Deploy Consul to ECS using the Terraform module](/consul/docs/ecs/deploy/terraform) +- [Deploy Consul to ECS manually](/consul/docs/ecs/deploy/manual) ## Configure the sidecar proxy @@ -76,4 +76,4 @@ module "web" { ] ... } -``` \ No newline at end of file +``` diff --git a/website/content/docs/ecs/deploy/manual.mdx b/website/content/docs/ecs/deploy/manual.mdx index 708a49213ad1..9b54aa05792c 100644 --- a/website/content/docs/ecs/deploy/manual.mdx +++ b/website/content/docs/ecs/deploy/manual.mdx @@ -18,24 +18,24 @@ You should have some familiarity with AWS ECS. Refer to [What is Amazon Elastic You must meet the following requirements and prerequisites to enable security features in Consul service mesh: - Enable [TLS encryption](https://developer.hashicorp.com/consul/docs/security/encryption#rpc-encryption-with-tls) on your Consul servers so that they can communicate security with Consul dataplane containers over gRPC. -- Enable [access control lists (ACLs)](/consul/docs/security/acl) on your Consul servers. ALCs provide authentication and authorization for access to Consul servers on the mesh. +- Enable [access control lists (ACLs)](/consul/docs/security/acl) on your Consul servers. ACLs provide authentication and authorization for access to Consul servers on the mesh. - You should be familiar with specifying sensitive data on ECS. Refer to [Passing sensitive data to a container](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html) in the AWS documentation for additional information. You should be familiar with configuring Consul's secure features, including how to create ACL tokens and policies. Refer to the following resources: - [Create a service token](/consul/docs/security/acl/tokens/create/create-a-service-token) - [Day 1: Security tutorial](https://developer.hashicorp.com/consul/tutorials/security) for additional information. -Consul requires a unique IAM role for each ECS task family. Task IAM roles cannot be shared by different task families because the task family is unique to each Consul service. +Consul requires a unique IAM role for each ECS task family. Task IAM roles cannot be shared by different task families because the task family is unique to each Consul service. ## Configure ECS task definition file -Create a JSON file for the task definition. The task definition is the ECS blueprint for your software services on AWS. Refer to the [ECS task definitions in the AWS documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html) for additional information. +Create a JSON file for the task definition. The task definition is the ECS blueprint for your software services on AWS. Refer to the [ECS task definitions in the AWS documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html) for additional information. In addition to your application container, add configurations to your task definition that creates the following Consul containers: - Dataplane container - Control-plane container -- ECS controller container +- ECS controller container ## Top-level fields @@ -46,7 +46,7 @@ The following table describes the top-level fields you must include in the task | `family` | The task family name. This is used as the Consul service name by default. | string | | `networkMode` | Must be `awsvpc`, which is the only network mode supported by Consul on ECS. | string | | `volumes` | Volumes on the host for sharing configuration between containers for initial task setup. You must define a `consul_data` and `consul_binary` bind mount. Bind mounts can be mounted into one or more containers in order to share files among containers. For Consul on ECS, certain binaries and configuration are shared among containers during task startup. | list | -| `containerDefinitions` | Defines the application container that runs in the task. Refer to [Define your application container](#define-your-application-container). | list | +| `containerDefinitions` | Defines the application container that runs in the task. Refer to [Define your application container](#define-your-application-container). | list | The following example shows the top-level fields: @@ -81,7 +81,7 @@ The following example shows the top-level fields: The `tags` list must include the following tags if you are using the ECS controller in a [secure configuration](/consul/docs/ecs/deploy/manual#secure-configuration-requirements). Without these tags, the ACL controller is unable to provision a service token for the task. -| Tag | Description | Type | Default | +| Tag | Description | Type | Default | | --- | --- | --- | --- | | `consul.hashicorp.com/mesh` | Enables the ECS controller. Set to `false` to disable the ECS controller. | String | `true` | | `consul.hashicorp.com/service-name` | Specifies the name of the Consul service associated with this task. Required if the service name is different than the task `family`. | String | None | @@ -96,7 +96,7 @@ Specify your application container configurations in the `containerDefinitions` | --- | --- | --- | | `name` | The name of your application container. | string | | `image` | The container image used to run your application. | string | -| `essential` | Must be `true` to ensure the health of your application container affects the health status of the task. | boolean | +| `essential` | Must be `true` to ensure the health of your application container affects the health status of the task. | boolean | | `dependsOn` | Specifies container dependencies that ensure your application container starts after service mesh setup is complete. Refer to [Application container dependency configuration](#application-container-dependency-configuration) for details. | list | Refer to the [ECS Task Definition](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html) documentation for a complete reference. @@ -120,7 +120,7 @@ The `dependsOn` list must include the following maps: } ``` -## Configure the dataplane container +## Configure the dataplane container The dataplane container runs Envoy proxy for Consul service mesh. Specify the fields described in the following table to declare a dataplane container: @@ -174,7 +174,7 @@ Specify the fields described in the following table to declare the control-plane | --- | --- | --- | | `name` | Specifies the name of the container. This must be `control-plane`. | string | | `image` | Specifies the `consul-ecs` image. Specify the following public AWS registry to avoid rate limits: `public.ecr.aws/hashicorp/consul-ecs` | string | -| `mountPoints` | Specifies a shared volume to store the Envoy bootstrap configuration file that the dataplane container can access and consume. The keys and values in this configuration must be defined as described in [Control-plane shared volume configuration](#control-plane-shared-volume-configuration). | list | +| `mountPoints` | Specifies a shared volume to store the Envoy bootstrap configuration file that the dataplane container can access and consume. The keys and values in this configuration must be defined as described in [Control-plane shared volume configuration](#control-plane-shared-volume-configuration). | list | | `command` | Set to `["control-plane"]` so that the container runs the `control-plane` command. | list | | `environment` | Specifies the `CONSUL_ECS_CONFIG_JSON` environment variable, which configures the container to connect to the Consul servers. Refer to [Control-plane to Consul servers configuration](#control-plane-to-Consul-servers-configuration) for details. | list | @@ -199,7 +199,7 @@ The `mountPoints` configuration defines a volume and path where the control-plan ### Control-plane to Consul servers configuration -Provide Consul server connection settings to the mesh task module so that the module can configure the control-plane and ECS controller containers to connect to the servers. +Provide Consul server connection settings to the mesh task module so that the module can configure the control-plane and ECS controller containers to connect to the servers. 1. In your `variables.tf` file, define variables for the host URL and TLS settings for gRPC and HTTP traffic. Refer to the [mesh task module reference](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task?tab=inputs) for information about the variables you can define. In the following example, the Consul server address is defined in the `consul_server_hosts` variable: @@ -210,7 +210,7 @@ Provide Consul server connection settings to the mesh task module so that the mo } ``` -1. Add an `environment` block to the control-plane and ECS controller containers definition +1. Add an `environment` block to the control-plane and ECS controller containers definition. 1. Set the `environment.name` field to the `CONSUL_ECS_CONFIG_JSON` environment variable and the value to `local.encoded_config`. ```hcl @@ -223,7 +223,7 @@ Provide Consul server connection settings to the mesh task module so that the mo ``` When you apply the configuration, the mesh task module interpolates the server configuration variables, builds a `config.tf` file, and injects the settings into the appropriate containers. -For additional information about the `config.tf` file, refer to the [JSON schema reference documentation](/consul/docs/ecs/reference/config-json-schema). +For additional information about the `config.tf` file, refer to the [JSON schema reference documentation](/consul/docs/ecs/reference/config-json-schema). ## Register the task definition configuration @@ -245,9 +245,10 @@ Verify that you have completed the prerequisites described in [Secure configurat On the Consul server, create a policy that grants the following access for the controller: -- `acl:write` -- `operator:write` -- `node:write` +- `acl:write` +- `operator:write` +- `node:write` +- `service:write` The policy allows Consul to generate a token linked to the policy. Refer to [Create a service token](/consul/docs/security/acl/tokens/create/create-a-service-token) for instructions. @@ -259,7 +260,7 @@ The policy allows Consul to generate a token linked to the policy. Refer to [Cre ### Configure the auth method for service tokens -Run the `consul acl auth-method create` command on a Consul server to create an instance of the auth method for service tokens. +Run the `consul acl auth-method create` command on a Consul server to create an instance of the auth method for service tokens. The following example command configures the auth method to associate a service identity to each token created during login to this auth method instance. @@ -302,9 +303,9 @@ You must specify the following configuration in the `-config` flag: Refer to the [auth method configuration parameters documentation](/consul/docs/security/acl/auth-methods/aws-iam#config-parameters) for additional information. -### Create the binding rule +### Create the binding rule -Run the `consul acl binding-rule create` command on a Consul server to create a binding rule. The rule associates a service identity with each token created on successful login to this instance of the auth method. +Run the `consul acl binding-rule create` command on a Consul server to create a binding rule. The rule associates a service identity with each token created on successful login to this instance of the auth method. In the following example, Consul takes the service identity name from the `consul.hashicorp.com.service-name` tag specified for authenticating IAM role identity. @@ -335,7 +336,7 @@ You can reference stored secrets using their ARN. The examples show ARNs for sec You can configure Consul servers connected to your ECS workloads to capture a log of authenticated events. Refer to [Audit Logging](/consul/docs/enterprise/audit-logging) for details. ## Next steps - + After deploying the Consul service mesh infrastructure, you must still define routes between service instances as well as configure the bind address for your applications so that they only receive traffic through the mesh. Refer to the following topics: - [Configure routes between ECS tasks](/consul/docs/ecs/deploy/configure-routes) diff --git a/website/content/docs/ecs/deploy/migrate-existing-tasks.mdx b/website/content/docs/ecs/deploy/migrate-existing-tasks.mdx index 77ab4ded7f0b..cb405e518afc 100644 --- a/website/content/docs/ecs/deploy/migrate-existing-tasks.mdx +++ b/website/content/docs/ecs/deploy/migrate-existing-tasks.mdx @@ -5,13 +5,13 @@ description: >- You can migrate tasks in existing Amazon Web Services ECS deployments to a service mesh deployed with Terraform. Learn how to convert a task specified as an ECS task definition into a `mesh-task` Terraform module. --- -# Migrate existing tasks to Consul on ECS with Terraform +# Migrate existing tasks to Consul on ECS with Terraform -To migrate existing tasks to Consul, rewrite the existing Terraform code for your tasks so that the container definitions include the [`mesh-task` Terraform module](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task). +To migrate existing tasks to Consul, rewrite the existing Terraform code for your tasks so that the container definitions include the [`mesh-task` Terraform module](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task). Your tasks must already be defined in Terraform using the `ecs_task_definition` resource so that they can then be converted to use the `mesh-task` module. -## Example +## Example The following example shows an existing task definition configured in Terraform: @@ -93,7 +93,7 @@ module "my_task" { Note the following differences: - The `execution_role_arn` and `task_role_arn` fields are removed. The `mesh-task` module creates the task and execution roles by default. If you need to use existing IAM roles, set the `task_role` and `execution_role` fields to pass in existing roles. -- The `port` field specifes the port that your application listens on. If your application has no listening port, set `outbound_only = true` and remove the `port` field. +- The `port` field specifies the port that your application listens on. If your application has no listening port, set `outbound_only = true` and remove the `port` field. - The `jsonencode()` function is removed from the `container_definitions` field. -The `mesh-task` module creates a new version of your task definition with the necessary dataplane containers so you can delete your existing `aws_ecs_task_definition` resource. \ No newline at end of file +The `mesh-task` module creates a new version of your task definition with the necessary dataplane containers so you can delete your existing `aws_ecs_task_definition` resource. diff --git a/website/content/docs/ecs/deploy/terraform.mdx b/website/content/docs/ecs/deploy/terraform.mdx index 623fdb87e3d7..5d5574a967f3 100644 --- a/website/content/docs/ecs/deploy/terraform.mdx +++ b/website/content/docs/ecs/deploy/terraform.mdx @@ -11,17 +11,17 @@ This topic describes how to create a Terraform configuration that deploys Consul ## Overview -Create a Terraform configuration file that includes the ECS task definition and Terraform modules that build the Consul service mesh components. The task definition is the ECS blueprint for your software services on AWS. Refer to the [ECS task definitions documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html) for additional information. +Create a Terraform configuration file that includes the ECS task definition and Terraform modules that build the Consul service mesh components. The task definition is the ECS blueprint for your software services on AWS. Refer to the [ECS task definitions documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html) for additional information. You can add the following modules and resources to your Terraform configuration: -- `mesh-task` module: Adds the Consul ECS control-plane and Consul dataplane containers to the task definition along with your application container. Envoy runs as a subprocess within the Consul dataplane container. +- `mesh-task` module: Adds the Consul ECS control-plane and Consul dataplane containers to the task definition along with your application container. Envoy runs as a subprocess within the Consul dataplane container. - `aws_ecs_service` resource: Adds an ECS service to run and maintain your task instance. - `gateway-task` module: Adds mesh gateway containers to the cluster. Mesh gateways enable service-to-service communication across different types of network areas. -To enable Consul security features for your production workloads, you must also deploy the `controller` module, which provisions ACL tokens for service mesh tasks. +To enable Consul security features for your production workloads, you must also deploy the `controller` module, which provisions ACL tokens for service mesh tasks. -After defining your Terraform configuration, use `terraform apply` to deploy Consul to your ECS cluster. +After defining your Terraform configuration, use `terraform apply` to deploy Consul to your ECS cluster. ## Requirements @@ -34,10 +34,10 @@ After defining your Terraform configuration, use `terraform apply` to deploy Con You must meet the following requirements and prerequisites to enable security features in Consul service mesh: - Enable [TLS encryption](/consul/docs/security/encryption#rpc-encryption-with-tls) on your Consul servers so that they can communicate securely with Consul containers over gRPC. -- Enable [access control lists (ACLs)](/consul/docs/security/acl) on your Consul servers. ALCs provide authentication and authorization for access to Consul servers on the mesh. +- Enable [access control lists (ACLs)](/consul/docs/security/acl) on your Consul servers. ACLs provide authentication and authorization for access to Consul servers on the mesh. - You should be familiar with specifying sensitive data on ECS. Refer to [Passing sensitive data to a container](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html) in the AWS documentation for additional information. -Additionally, Consul requires a unique IAM role for each ECS task family. Task IAM roles cannot be shared by different task families because the task family is unique to each Consul service. +Additionally, Consul requires a unique IAM role for each ECS task family. Task IAM roles cannot be shared by different task families because the task family is unique to each Consul service. You should be familiar with configuring Consul's secure features, including how to create ACL tokens and policies. Refer to the following resources for additional information: @@ -53,7 +53,7 @@ Create a Terraform configuration file and add your ECS task definition. The task Add a `module` block to your Terraform configuration and specify the following fields: - `source`: Specifies the location of the `mesh-task` module. This field must be set to `hashicorp/consul-ecs/aws//modules/mesh-task`. The `mesh-task` module automatically adds the Consul service mesh infrastructure when you apply the Terraform configuration. -- `version`: Specifies the version of the `mesh-task` module to use. +- `version`: Specifies the version of the `mesh-task` module to use. - `family`: Specifies the [ECS task definition family](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#family). Consul also uses the `family` value as the Consul service name by default. - `container_definitions`: Specifies a list of [container definitions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definitions) for the task definition. This field is where you include your application containers. @@ -99,7 +99,7 @@ The following fields are required. Refer to the [module reference documentation] ## Configure Consul server settings -Provide Consul server connection settings to the mesh task module so that the module can configure the control-plane and ECS controller containers to connect to the servers. +Provide Consul server connection settings to the mesh task module so that the module can configure the control-plane and ECS controller containers to connect to the servers. 1. In your `variables.tf` file, define variables for the host URL and the TLS settings for gRPC and HTTP traffic. Refer to the [mesh task module reference](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/gateway-task?tab=inputs) for information about the variables you can define. In the following example, the Consul server address is defined in the `consul_server_hosts` variable: @@ -121,13 +121,13 @@ Provide Consul server connection settings to the mesh task module so that the mo ] ``` - When you apply the configuration, the mesh task module interpolates the server configuration variables, builds a `config.tf` file, and injects the settings into the appropriate containers. For additional information about the `config.tf` file, refer to the [JSON schema reference documentation](/consul/docs/ecs/reference/consul-server-json). + When you apply the configuration, the mesh task module interpolates the server configuration variables, builds a `config.tf` file, and injects the settings into the appropriate containers. For additional information about the `config.tf` file, refer to the [JSON schema reference documentation](/consul/docs/ecs/reference/consul-server-json). ## Configure an ECS service to run your task instances To start a task using the task definition, add the `aws_ecs_service` resource to your configuration to create an ECS service. [ECS services](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html) are one of the most common ways to start tasks using a task definition. -Reference the `mesh-task` module's `task_definition_arn` output value in your `aws_ecs_service` resource. The following example adds an ECS service for a task definition referenced in as `module.my_task.task_defintion_arn`: +Reference the `mesh-task` module's `task_definition_arn` output value in your `aws_ecs_service` resource. The following example adds an ECS service for a task definition referenced in as `module.my_task.task_definition_arn`: @@ -154,7 +154,7 @@ If you are deploying a test instance of your ECS application, you can apply your If you intend to leverage multi-datacenter Consul features, such as WAN federation and cluster peering, then you must add the `gateway-task` module for each Consul datacenter in your network. Refer to [Configure the gateway task module](#configure-the-gateway-task-module) for instructions. -## Configure the gateway task module +## Configure the gateway task module The `gateway-task` module deploys a mesh gateway, which enables service-to-service communication across network areas. Mesh gateways detect the server name indication (SNI) header from the service mesh session and route the connection to the appropriate destination. @@ -163,12 +163,12 @@ Refer to the following documentation for additional information: - [WAN Federation via Mesh Gateways](/consul/docs/connect/gateways/mesh-gateway/wan-federation-via-mesh-gateways) - [Service-to-service Traffic Across Datacenters](/consul/docs/connect/gateways/mesh-gateway/service-to-service-traffic-wan-datacenters) -To use mesh gateways, TLS must be enabled in your cluster. Refer to the [requirements section](#requirements) for additional information. +To use mesh gateways, TLS must be enabled in your cluster. Refer to the [requirements section](#requirements) for additional information. 1. Add a `module` block to your Terraform configuration file and specify a label. The label is a unique identifier for the gateway. 1. Add a `source` to the `module` and specify the location of the `gateway-task`. The value must be `hashicorp/consul-ecs/aws//modules/gateway-task`. 1. Specify the following required inputs: - - `ecs_cluster_arn`: The ARN of the ECS cluster for the gateway. + - `ecs_cluster_arn`: The ARN of the ECS cluster for the gateway. - `family`: Specifies a name for multiple versions of the task. Refer to the [AWS documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#family) for details. - `kind`: Set to `mesh-gateway` - `subnets`: Specifies a list of subnet IDs where the gateway task should be deployed. @@ -200,9 +200,9 @@ Refer to [gateway-task module in the Terraform registry](https://registry.terraf Refer to the [gateway task configuration examples](#gateway-task-configuration-examples) for additional example configurations. -## Configure the ECS controller +## Configure the ECS controller -Deploy the ECS controller container to its own ECS task in the cluster. Refer to [ECS controller container](/consul/docs/ecs/reference/architecture#ecs-controller) for details about the container. +Deploy the ECS controller container to its own ECS task in the cluster. Refer to [ECS controller container](/consul/docs/ecs/reference/architecture#ecs-controller) for details about the container. Verify that you have completed the prerequisites described in [Secure configuration requirements](#secure-configuration-requirements) and complete the following steps to configure the controller container. @@ -211,15 +211,16 @@ Verify that you have completed the prerequisites described in [Secure configurat 1. On the Consul server, create a policy that grants the following access for the controller: - `acl:write` - - `operator:write` - - `node:write` - + - `operator:write` + - `node:write` + - `service:write` + The policy allows Consul to generate a token linked to the policy. Refer to [Create a service token](/consul/docs/security/acl/tokens/create/create-a-service-token) for instructions. 1. Create a token and link it to the ACL controller policy. Refer to the [ACL tokens documentation](/consul/docs/security/acl/tokens) for instructions. ### Configure an AWS secrets manager secret -Add the `aws_secretsmanager_secret` resource to your Terraform configuration and specify values for retrieving the CA and TLS certificates. The resource enables services to communicate over TLS and present ACL tokens. The ECS controller also uses the secret manager to retrieve the value of the bootstrap token. +Add the `aws_secretsmanager_secret` resource to your Terraform configuration and specify values for retrieving the CA and TLS certificates. The resource enables services to communicate over TLS and present ACL tokens. The ECS controller also uses the secret manager to retrieve the value of the bootstrap token. In the following example, Terraform creates the CA certificates for gRPC and HTTPS in the secrets manager. Consul retrieves the CA certificate PEM file from the secret manager so that the mesh task can use TLS for HTTP and gRPC traffic: @@ -374,7 +375,7 @@ Terraform reads all files in the current directory that have a `.tf` file extens Refer to the [Terraform documentation](/terraform/docs) for more information and Terraform best practices. ## Next steps - + After deploying the Consul service mesh infrastructure, you must still define routes between service instances as well as configure the bind address for your applications so that they only receive traffic through the mesh. Refer to the following topics: - [Configure routes between ECS tasks](/consul/docs/ecs/deploy/configure-routes) diff --git a/website/content/docs/ecs/index.mdx b/website/content/docs/ecs/index.mdx index 7238765af266..992d7eb3df7b 100644 --- a/website/content/docs/ecs/index.mdx +++ b/website/content/docs/ecs/index.mdx @@ -30,7 +30,7 @@ Refer to the following documentation and tutorials for additional guidance. ### Tutorials -- [Integrate your AWS ECS services into Consul service mesh](/consul/tutorials/cloud-integrations/consul-ecs): Shows how to use Terraform to run Consul service mesh applications on ECS with self-managed Consul or HCP-managed Consul. +- [Integrate your AWS ECS services into Consul service mesh](/consul/tutorials/cloud-integrations/consul-ecs): Shows how to use Terraform to run Consul service mesh applications on ECS with self-managed Enterprise or HCP Consul Dedicated. You can also refer to the following example configurations: diff --git a/website/content/docs/ecs/reference/compatibility.mdx b/website/content/docs/ecs/reference/compatibility.mdx index c243a95878c7..cc99996866b4 100644 --- a/website/content/docs/ecs/reference/compatibility.mdx +++ b/website/content/docs/ecs/reference/compatibility.mdx @@ -11,8 +11,10 @@ For every release of Consul on ECS, the `consul-ecs` binary and `consul-ecs` Ter ## Supported Consul versions -| Consul Version | Compatible consul-ecs Version | +| `consul` version | Compatible `consul-ecs` version | |----------------------- | ----------------------------- | +| 1.18.x | 0.8.x | +| 1.16.x 1.17.x | 0.7.x | | 1.15.x, 1.14.x, 1.13.x | 0.6.x | | 1.14.x, 1.13.x, 1.12.x | 0.5.2+ | | 1.11.x | 0.3.0, 0.4.x | diff --git a/website/content/docs/ecs/reference/configuration-reference.mdx b/website/content/docs/ecs/reference/configuration-reference.mdx index 4c366d7795d3..3e283e6f12bc 100644 --- a/website/content/docs/ecs/reference/configuration-reference.mdx +++ b/website/content/docs/ecs/reference/configuration-reference.mdx @@ -7,20 +7,13 @@ description: >- # Consul on AWS Elastic Container Service (ECS) Configuration Reference -This topic describes configuration options for the JSON configuration format used -by the `consul-ecs` binary. This configuration is passed to the `consul-ecs` -binary as a string using the `CONSUL_ECS_CONFIG_JSON` environment variable. +This topic describes configuration options for the JSON configuration format used by the `consul-ecs` binary. This configuration is passed to the `consul-ecs` binary as a string using the `CONSUL_ECS_CONFIG_JSON` environment variable. -This configuration format follows a [JSON schema](https://github.com/hashicorp/consul-ecs/blob/main/config/schema.json) -that can be used for validation. +This configuration format follows a [JSON schema](https://github.com/hashicorp/consul-ecs/blob/main/config/schema.json) that can be used for validation. -## Terraform Mesh Task Module Configuration +## Terraform `mesh-task` module configuration -The `mesh-task` Terraform module provides input variables for commonly used fields. -The following table shows which Terraform input variables correspond to each field -of the Consul ECS configuration. Refer to the -[Terraform registry documentation](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task?tab=inputs) -for a complete reference of supported input variables for the `mesh-task` module. +The `mesh-task` Terraform module provides input variables for commonly used fields. The following table shows which Terraform input variables correspond to each field of the Consul ECS configuration. Refer to the [Terraform registry documentation](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task?tab=inputs) for a complete reference of supported input variables for the `mesh-task` module. | Terraform Input Variable | Consul ECS Config Field | | ------------------------ | ------------------------------------- | @@ -32,9 +25,7 @@ for a complete reference of supported input variables for the `mesh-task` module | `consul_namespace` | [`service.namespace`](#service) | | `consul_partition` | [`service.partition`](#service) | -Each of these Terraform input variables follow the Consul ECS config schema. -The remaining fields of the Consul ECS configuration not listed in this table can be passed -using the `consul_ecs_config` input variable. +Each of these Terraform input variables follows the Consul ECS configuration schema. The remaining fields of the Consul ECS configuration that are not listed in this table can be passed using the `consul_ecs_config` input variable. # Top-level fields diff --git a/website/content/docs/ecs/reference/consul-server-json.mdx b/website/content/docs/ecs/reference/consul-server-json.mdx index 30e41c207fa3..87401bbb2d3f 100644 --- a/website/content/docs/ecs/reference/consul-server-json.mdx +++ b/website/content/docs/ecs/reference/consul-server-json.mdx @@ -6,25 +6,25 @@ description: Learn about the fields available in the JSON scheme for configuring # Consul server configuration JSON schema reference -This topic provides reference information about the JSON schema used to build the `config.tf` file. Refer to [Configure Consul server settings](/consul/docs/ecs/deploy/terraform#configure-consul-server-settings) for information about how Consul on ECS uses the JSON schema. +This topic provides reference information about the JSON schema used to build the `config.tf` file. Refer to [Configure Consul server settings](/consul/docs/ecs/deploy/terraform#configure-consul-server-settings) for information about how Consul on ECS uses the JSON schema. ## Configuration model The following list describes the attributes, data types, and default values, if any, in the `config.tf` file. Click on a value to learn more about the attribute. -- [`consulServers`](#consulservers): map +- [`consulServers`](#consulservers): map - [`hosts`](#consulservers-hosts): string - [`skipServerWatch`](#consulservers-hosts): boolean | `false` - - [`defaults`](#consulservers-defaults): map - - [`caCertFile`](#consulservers-defaults): string - - [`tlsServerName`](#consulservers-defaults): string + - [`defaults`](#consulservers-defaults): map + - [`caCertFile`](#consulservers-defaults): string + - [`tlsServerName`](#consulservers-defaults): string - [`tls`](#consulservers-defaults): boolean | `false` - - [`grpc`](#consulservers-grpc): map - - [`port`](#consulservers-grpc): number - - [`caCertFile`](#consulservers-grpc): string - - [`tlsServerName`](#consulservers-grpc): string + - [`grpc`](#consulservers-grpc): map + - [`port`](#consulservers-grpc): number + - [`caCertFile`](#consulservers-grpc): string + - [`tlsServerName`](#consulservers-grpc): string - [`tls`](#consulservers-grpc): boolean | `false` - - [`http`](#consulservers-http): map + - [`http`](#consulservers-http): map - [`https`](#consulservers-http): boolean | `false` - [`port`](#consulservers-http): number - [`caCertFile`](#consulservers-http): string @@ -33,11 +33,11 @@ The following list describes the attributes, data types, and default values, if ## Specification -This section provides details about the attribes in the `config.tf` file. +This section provides details about the attributes in the `config.tf` file. ### `consulServers` -Parent-level attribute containing all of the server configurations. All other configuraitons in the file are children of the `consulServers` attribute. +Parent-level attribute containing all of the server configurations. All other configurations in the file are children of the `consulServers` attribute. #### Values @@ -47,7 +47,7 @@ Parent-level attribute containing all of the server configurations. All other co ### `consulServers.hosts` -Map that contains the `skipServerWatch` configuration for Consul server hosts. +Map that contains the `skipServerWatch` configuration for Consul server hosts. #### Values @@ -56,7 +56,7 @@ Map that contains the `skipServerWatch` configuration for Consul server hosts. ### `consulServers.hosts.skipServerWatch` -Boolean that disables watches on the Consul server. Set to `true` if the Consul server is already behind a load balancer. +Boolean that disables watches on the Consul server. Set to `true` if the Consul server is already behind a load balancer. #### Values @@ -65,7 +65,7 @@ Boolean that disables watches on the Consul server. Set to `true` if the Consul ### `consulServers.defaults` -Map of default server configurations. Defaults apply to gRPC and HTTP traffic. +Map of default server configurations. Defaults apply to gRPC and HTTP traffic. #### Values @@ -83,7 +83,7 @@ The following table describes the attributes available in the `defaults` configu ### `consulServers.grpc` -Map of server configuration for gRPC traffic that override attributes defined in `consulServers.defaults`. +Map of server configuration for gRPC traffic that override attributes defined in `consulServers.defaults`. #### Values @@ -101,7 +101,7 @@ The following table describes the attributes available in the `grpc` configurati ### `consulServers.http` -Map of server configuration for HTTP traffic that override attributes defined in `consulServers.defaults`. +Map of server configuration for HTTP traffic that override attributes defined in `consulServers.defaults`. #### Values diff --git a/website/content/docs/ecs/tech-specs.mdx b/website/content/docs/ecs/tech-specs.mdx index 2f70e5ed0dd4..d5fa5b399f58 100644 --- a/website/content/docs/ecs/tech-specs.mdx +++ b/website/content/docs/ecs/tech-specs.mdx @@ -11,18 +11,24 @@ This topic describes the supported runtimes and environments for using Consul se For requirements associated with using the Terraform `mesh-task` module to deploy Consul service mesh, refer [Deploy Consul with the Terraform module](/consul/docs/ecs/deploy/terraform). For requirements associated with manually deploying Consul service mesh to your ECS cluster, refer [Deploy Consul manually](/consul/docs/ecs/deploy/manual). -## Supported environments and runtimes - -Consul on ECS supports the following environments and runtimes: - -- **Launch Types**: Fargate and EC2 -- **Network Modes**: `awsvpc` -- **Subnets**: Private and public subnets. Tasks must have network access to Amazon ECR or other public container registries to pull images. -- **Consul servers**: You can use your own Consul servers running on virtual machines or [use HCP Consul to host the servers for you](/hcp/docs/consul/hcp-managed). -- **ECS controller**: The ECS controller assists with reconciling state back to Consul and facilitates Consul security features. -- **Admin partitions**: Enable ACLs and configure the ECS controller to use admin partitions. You must deploy one controller for each admin partition. -- **Namespaces**: Enable ACLs and configure the ECS controller to use namespaces. -- **Dataplane containers**: To manage proxies using Consul dataplane, you must use the Terraform `mesh-task` module to install Consul service mesh. +## Supported environments, runtimes, and capabilities + +Consul on ECS supports the following environments, runtimes, and capabilities: + +- **Launch Types:** Fargate and EC2 +- **Network Modes:** `awsvpc` +- **Subnets:** Private and public subnets. Tasks must have network access to Amazon ECR or other public container registries to pull images. +- **Consul servers:** You can use your own Consul servers running on virtual machines or [use HCP Consul Dedicated to host the servers for you](/hcp/docs/consul/dedicated). +- **ECS controller:** The ECS controller assists with reconciling state back to Consul and facilitates Consul security features. +- **Admin partitions:** Enable ACLs and configure the ECS controller to use admin partitions. You must deploy one controller for each admin partition. +- **Namespaces:** Enable ACLs and configure the ECS controller to use namespaces. +- **Dataplane containers:** To manage proxies using Consul dataplane, you must use the Terraform `mesh-task` module to install Consul service mesh. +- **Transparent proxy:** Consul on ECS 0.8.x supports transparent proxy for ECS on EC2 tasks. Transparent proxy in ECS requires the host to have `NET_ADMIN` capabilities, which ECS Fargate does not currently support. You can enable transparent proxy with the `enable_transparent_proxy` parameter in the `mesh-task` Terraform module or through `ecs_config_json`. The `enable_transparent_proxy` parameter has precedence over `ecs_config_json`. + + Refer to the [`terraform-aws-consul-ecs`](https://github.com/hashicorp/terraform-aws-consul-ecs/tree/main/examples/dev-server-ec2-transparent-proxy) for an example. +- **API Gateway:** Consul on ECS 0.8.x supports API gateway. Refer to the [`terraform-aws-consul-ecs`](https://github.com/hashicorp/terraform-aws-consul-ecs/tree/main/examples/api-gateway) for an example. + + Refer to the [Consul ECS GitHub repository](https://github.com/hashicorp/terraform-aws-consul-ecs/tree/main/examples/dev-server-ec2-transparent-proxy) for examples of how to use transparent proxy with Consul on ECS. ## Resource usage diff --git a/website/content/docs/enterprise/admin-partitions.mdx b/website/content/docs/enterprise/admin-partitions.mdx index 2d060c274be7..f9dc2f6b3509 100644 --- a/website/content/docs/enterprise/admin-partitions.mdx +++ b/website/content/docs/enterprise/admin-partitions.mdx @@ -60,6 +60,8 @@ the lookup uses the admin partition of the Consul agent that received the query. Server agents always exist within the `default` admin partition. Client agents are configured to operate within a specific admin partition. +By default, Consul on Kubernetes uses [Consul dataplanes](/consul/docs/connect/dataplane) instead of client agents to manage communication between service instances. But to use the Consul DNS for service discovery, you must start a Consul client in client admin partitions. + ### Service Mesh Configurations The partition in which [`proxy-defaults`](/consul/docs/connect/config-entries/proxy-defaults) and [`mesh`](/consul/docs/connect/config-entries/mesh) configurations are created define the scope of the configurations. Services registered in a partition will use the `proxy-defaults` and `mesh` configurations that have been created in the partition. @@ -89,9 +91,10 @@ All Consul clients must be able to initiate Gossip, HTTPS, and RPC connections t For Consul on Kubernetes, a dedicated `partition` Kubernetes `LoadBalancer` service is deployed to allow communication from clients to servers for admin partitions support (refer to [Kubernetes Requirements](#kubernetes-requirements) for additional information). For other runtimes, refer to the documentation for your infrastructure environment for instructions on how to allow communication on the following ports: +- 443 (HTTPS API requests) - 8300 (RPC) - 8301 (Gossip) -- 443 (HTTPS API requests) +- 8502 (gRPC from [Consul Dataplane](/consul/docs/connect/dataplane/consul-dataplane)) ### Security Configurations @@ -154,14 +157,14 @@ Verify that your Consul deployment meets the [Kubernetes Requirements](#kubernet 1. Create the license secret in server cluster. ```shell-session - $ kubectl create --context ${SERVER_CONTEXT} ns consul + $ kubectl create --context ${SERVER_CONTEXT} namespace consul $ kubectl create secret --context ${SERVER_CONTEXT} --namespace consul generic license --from-file=key=./path/to/license.hclic ``` 1. Create the license secret in the non-default partition cluster for your workloads. This step must be repeated for every additional non-default partition cluster. ```shell-session - $ kubectl create --context ${CLIENT_CONTEXT} ns consul + $ kubectl create --context ${CLIENT_CONTEXT} namespace consul $ kubectl create secret --context ${CLIENT_CONTEXT} --namespace consul generic license --from-file=key=./path/to/license.hclic ``` @@ -184,7 +187,7 @@ Verify that your Consul deployment meets the [Kubernetes Requirements](#kubernet enableConsulNamespaces: true tls: enabled: true - image: hashicorp/consul-enterprise:1.14.0-ent + image: hashicorp/consul-enterprise:1.16.3-ent adminPartitions: enabled: true acls: @@ -207,7 +210,7 @@ Verify that your Consul deployment meets the [Kubernetes Requirements](#kubernet $ helm install ${HELM_RELEASE_SERVER} hashicorp/consul --version "1.0.0" --create-namespace --namespace consul --values server.yaml ``` -1. After the server starts, get the external IP address for partition service so that it can be added to the client configuration. The IP address is used to bootstrap connectivity between servers and workload pods on the non-default partition cluster. +1. After the server starts, get the external IP address for partition service so that it can be added to the client configuration (`externalServers.hosts`). The IP address is used to bootstrap connectivity between servers and workload pods on the non-default partition cluster. ```shell-session $ kubectl get services --selector="app=consul,component=server" --namespace consul --output jsonpath="{range .items[*]}{@.status.loadBalancer.ingress[*].ip}{end}" @@ -220,7 +223,7 @@ Verify that your Consul deployment meets the [Kubernetes Requirements](#kubernet $ kubectl config view --output "jsonpath={.clusters[?(@.name=='${CLIENT_CONTEXT}')].cluster.server}" ``` - Use the IP address printed to the console to configure the `k8sAuthMethodHost` parameter in the workload configuration file for your non-default partition cluster running your workloads. + Use the IP address printed to the console to configure the `externalServers.k8sAuthMethodHost` parameter in the workload configuration file for your non-default partition cluster running your workloads. 1. Copy the server certificate to the non-default partition cluster running your workloads. @@ -228,13 +231,13 @@ Verify that your Consul deployment meets the [Kubernetes Requirements](#kubernet $ kubectl get secret ${HELM_RELEASE_SERVER}-consul-ca-cert --context ${SERVER_CONTEXT} -n consul --output yaml | kubectl apply --namespace consul --context ${CLIENT_CONTEXT} --filename - ``` -1. Copy the server key to the non-default partition cluster running your workloads. +1. Copy the server key to the non-default partition cluster running your workloads: ```shell-session $ kubectl get secret ${HELM_RELEASE_SERVER}-consul-ca-key --context ${SERVER_CONTEXT} --namespace consul --output yaml | kubectl apply --namespace consul --context ${CLIENT_CONTEXT} --filename - ``` -1. If ACLs were enabled in the server configuration values file, copy the token to the non-default partition cluster running your workloads. +1. If ACLs were enabled in the server configuration values file, copy the token to the non-default partition cluster running your workloads: ```shell-session $ kubectl get secret ${HELM_RELEASE_SERVER}-consul-partitions-acl-token --context ${SERVER_CONTEXT} --namespace consul --output yaml | kubectl apply --namespace consul --context ${CLIENT_CONTEXT} --filename - @@ -250,7 +253,7 @@ Verify that your Consul deployment meets the [Kubernetes Requirements](#kubernet 1. Create a configuration for each non-default admin partition. - + @@ -259,10 +262,10 @@ Verify that your Consul deployment meets the [Kubernetes Requirements](#kubernet name: consul enabled: false enableConsulNamespaces: true - image: hashicorp/consul-enterprise:1.14.0-ent + image: hashicorp/consul-enterprise:1.16.3-ent adminPartitions: enabled: true - name: partition-workload + name: clients tls: enabled: true caCert: @@ -310,12 +313,13 @@ You can log into the Consul UI to verify that the partitions appear as expected. 1. If ACLs are enabled, you will need the partitions ACL token, which can be read from the Kubernetes secret. The token is an encoded string that must be decoded in base64, e.g.: ```shell-session - $ kubectl get secret --namespace consul ${HELM_RELEASE_SERVER}-consul-bootstrap-acl-token --template "{{ .data.token | base64decode }}" + $ kubectl get secret --namespace consul --context ${SERVER_CONTEXT} --template "{{ .data.token | base64decode }}" ${HELM_RELEASE_SERVER}-consul-bootstrap-acl-token ``` - The example command gets the token using the secret name configured in the values file (`bootstrap.secretName`), decodes the secret, and prints the usable token to the console in JSON format. + The example command gets the secret from the default partition cluster, decodes the secret, and prints the token to the console. + +1. Open the Consul UI in a browser using the external IP address and port number described in a previous step (see [step 4](#get-external-ip-address)). -1. Open the Consul UI in a browser using the external IP address and port number described in a previous step (see [step 5](#get-external-ip-address)). 1. Click **Log in** and enter the decoded token when prompted. You will see the `default` and `clients` partitions available in the **Admin Partition** drop-down menu. diff --git a/website/content/docs/enterprise/ent-to-ce-downgrades.mdx b/website/content/docs/enterprise/ent-to-ce-downgrades.mdx new file mode 100644 index 000000000000..a5b6061f40a6 --- /dev/null +++ b/website/content/docs/enterprise/ent-to-ce-downgrades.mdx @@ -0,0 +1,208 @@ +--- +layout: docs +page_title: Downgrade from Consul Enterprise to the community edition +description: >- + Learn how to downgrade your installation of Consul Enterprise to the free Consul community edition (CE) +--- + +# Downgrade from Consul Enterprise to the community edition + +This document describes how to downgrade from Consul Enterprise to Consul community edition (CE). + +## Overview + +You can downgrade Consul editions if you no longer require Consul Enterprise features. Complete the following steps to downgrade to Consul CE: + +1. Download the CE binary. +1. Backup your Consul data and set appropriate log levels. +1. Complete the downgrade procedures. + +### Request-handling details + +During the downgrade process, the Consul CE server handles the raft replication logs in one of the following ways: + +- Drops the request. +- Filters out data from requests sent from non-default namespaces or partitions. +- Panics and stops the downgrade. + +The following examples describe scenarios where the server may drop the requests: + +- Registration requests in non-default namespace +- Services or health checks in non-default namespaces or partitions. + +- Write requests to peered clusters if the local partition connecting to the peer is non-default. + +The following examples describe scenarios where the server may filter out data from requests: + +- Intention sources that target non-default namespaces or partitions are filtered out of the configuration entry. +- Exports of services within non-default namespaces or partitions are filtered out of the configuration entry. + +The server may panic and stop the downgrade when Consul cannot safely filter configuration entries that route traffic. This is because Consul is unable to determine if the filtered configuration entries send traffic to services that are able to handle the traffic. Consul CE panics in order to prevent harm to existing service mesh routes. + +In these situations, you must first remove references to services within non-default namespaces or partitions from those configuration entries. + +The server may panic in the following cases: + +- Service splitter, service resolver, and service router configuration entry requests that have references to services located in non-default namespaces or partitions cause the server to panic. + +## Requirements + +You can only downgrade Consul editions for v1.18 and later. + +## Download the CE binary version + +First, download the binary for CE. + + + + +All current and past versions of the CE and Enterprise releases are +available on the [HashiCorp releases page](https://releases.hashicorp.com/consul) + +Example: +```shell-session +$ export VERSION=1.18.0 +$ curl https://releases.hashicorp.com/consul/${VERSION}/consul_${VERSION} _linux_amd64.zip +``` + + + + +To downgrade Consul edition on Kubernetes, modify the image version in your Helm chart and follow the upgrade process described in [Upgrade Consul version](/consul/docs/k8s/upgrade#upgrade-consul-version). + + + + + +## Prepare for the downgrade to CE + +1. Take a snapshot of the existing Consul state so that you have a safe fallback if an error occurs. + + ```shell-session + $ consul snapshot save backup.snap + ``` + +1. Run the following command to verify that the snapshot was successfully saved: + + ```shell-session + $ consul snapshot inspect backup.snap + ``` + + Example output: + + ``` + ID 2-1182-1542056499724 + Size 4115 + Index 1182 + Term 2 + Version 1 + ``` + +1. Store the snapshot in a safe location. Refer to the following documentation for additional information about using snapshots: + + - [Consul snapshot](/consul/commands/snapshot) + - [Backup Consul Data and State tutorial](/consul/tutorials/production-deploy/backup-and-restore) + +1. Temporarily modify your Consul configuration so that its [log_level](/consul/docs/agent/config/cli-flags#_log_level) + is set to `debug`. This enables Consul to report detailed information if an error occurs. +1. Issue the following command on your servers to reload the configuration: + + ```shell-session + $ consul reload + ``` + +1. If applicable, modify the following configuration entries: + - [Service resolver](/consul/docs/connect/config-entries/service-resolver): + 1. Remove services configured as failovers in non-default namespaces or services that belong to a sameness group. + 1. Remove services configured as redirects that belong to non-default namespaces or partitions. + - [Service splitter](/consul/docs/connect/config-entries/service-splitter): + 1. Remove services configured as splits that belong to non-default namespaces or partitions. + - [Service router](/consul/docs/connect/config-entries/service-router): + 1. Remove services configured as a destination that belong to non-default namespaces or partitions. + +## Perform the downgrade + +1. Restart or redeploy all Consul clients with a CE version of the binary. You can use a service management system, such as `systemd` or `upstart`, to restart the Consul service. If you are not using a service management system, you must restart the agent manually. The following example uses `systemctl` to restart the Consul service: + + ```shell-session + $ sudo systemctl restart consul + ``` + +1. Issue the following command to discover which server is currently the leader: + + ```shell-session + $ consul operator raft list-peers + ``` + + Consul prints the raft information. The format and content may differ based on your version of Consul: + + ```shell-session + Node ID Address State Voter RaftProtocol + dc1-node1 ae15858f-7f5f-4dcb-b7d5-710fdcdd2745 10.11.0.2:8300 leader true 3 + dc1-node2 20e6be1b-f1cb-4aab-929f-f7d2d43d9a96 10.11.0.3:8300 follower true 3 + dc1-node3 658c343b-8769-431f-a71a-236f9dbb17b3 10.11.0.4:8300 follower true 3 + ``` + +1. Make a note of the leader so that you can perform the downgrade on agents in the proper order. + +1. Update the server binaries to use the CE version. Complete the following steps in order for each server agent in the `follower` state. Then, repeat the steps for the `leader` agent. + + 1. Set an environment variable named `CONSUL_ENTERPRISE_DOWNGRADE_TO_CE` to `true`. The following example sets variable using `systemd`: + 1. Edit the Consul systemd service unit file: + ```shell-session + $ sudo vi /etc/systemd/system/consul.service + ``` + 1. Add the environment variables you want to set for Consul under the `[Service]` section of the unit file and save the changes: + ```shell-session + [Service] + Environment=CONSUL_ENTERPRISE_DOWNGRADE_TO_CE=true + ``` + 1. Reload `systemd`: + ```shell-session + $ sudo systemctl daemon-reload + ``` + 1. Restart the Consul service. You can use a service management system, such as `systemd` or `upstart`. If you are not using a service management system, you must restart the agent manually. The following example restarts Consul using `systemctl`: + ```shell-session + $ sudo systemctl restart consul + ``` + 1. To validate that the agent has rejoined the cluster and is in sync with the leader, issue the following command: + ```shell-session + $ consul info + ``` + Verify that the `commit_index` and `last_log_index` fields have the same value. Differing values may be result of an unexpected leadership election due to loss of quorum. + +1. Run the following command to verify that all servers appear in the cluster as expected and are on the correct version: + + ```shell-session + $ consul members + ``` + + Consul prints cluster membership information. The exact format and content depends on your Consul version: + + ```shell-session + Node Address Status Type Build Protocol DC + dc1-node1 10.11.0.2:8301 alive server 1.18.0 2 dc1 + dc1-node2 10.11.0.3:8301 alive server 1.18.0 2 dc1 + dc1-node3 10.11.0.4:8301 alive server 1.18.0 2 dc1 + ``` + +1. Verify the raft state to make sure there is a leader and sufficient voters: + + ```shell-session + $ consul operator raft list-peers + ``` + + Consul prints the raft information. The format and content may differ based on your version of Consul: + + ```shell-session + Node ID Address State Voter RaftProtocol + dc1-node1 ae15858f-7f5f-4dcb-b7d5-710fdcdd2745 10.11.0.2:8300 leader true 3 + dc1-node2 20e6be1b-f1cb-4aab-929f-f7d2d43d9a96 10.11.0.3:8300 follower true 3 + dc1-node3 658c343b-8769-431f-a71a-236f9dbb17b3 10.11.0.4:8300 follower true 3 + ``` + +1. Set your `log_level` back to its original value and issue the following command on your servers to reload the configuration: + + ```shell-session + $ consul reload + ``` \ No newline at end of file diff --git a/website/content/docs/enterprise/fips.mdx b/website/content/docs/enterprise/fips.mdx index 5f5cf281967a..dc4d2ed3bc9e 100644 --- a/website/content/docs/enterprise/fips.mdx +++ b/website/content/docs/enterprise/fips.mdx @@ -2,7 +2,7 @@ layout: docs page_title: FIPS 140-2 description: >- - A version of Consul compliant with FIPS 140-2 is available to Enterprise users. Learn about where to find FIPS-compliant versions of Consul, as well as usage restrictions and technical details. + A version of Consul compliant with FIPS 140-2 is available to Enterprise users. Learn about where to find FIPS-compliant versions of Consul, its usage restrictions, technical details, and Leidos validation. --- # FIPS 140-2 @@ -17,9 +17,9 @@ To use this feature, you must have an [active or trial license for Consul Enterp ## Using FIPS 140-2 Consul Enterprise -FIPS 140-2 builds of Consul Enterprise behave in the same way as non-FIPS builds. There are no restrictions on Consul algorithms and ensuring that Consul remains in a FIPS-compliant mode of operation is your responsibility. To maintain FIPS-compliant operation, you must [ensure that TLS is enabled](/consul/tutorials/security/tls-encryption-secure) so that communication is encrypted. Consul products surface some helpful warnings where settings are insecure. +FIPS 140-2 builds of Consul Enterprise behave in the same way as non-FIPS builds. There are no restrictions on Consul algorithms and ensuring that Consul remains in a FIPS-compliant mode of operation is your responsibility. To maintain FIPS-compliant operation, you must [ensure that TLS is enabled](/consul/tutorials/archive/tls-encryption-secure) so that communication is encrypted. Consul products surface some helpful warnings where settings are insecure. -Encryption is disabled in Consul Enterprise by default. As a result, Consul may transmit sensitive control plane information. You must ensure that gossip encryption and mTLS is enabled for all agents when running Consul with FIPS-compliant settings. In addition, be aware that TLSv1.3 does not work with FIPS 140-2, as HKDF is not a certified primitive. +Encryption is disabled in Consul Enterprise by default. As a result, Consul may transmit sensitive control plane information. You must ensure that gossip encryption and mTLS is enabled for all agents when running Consul with FIPS-compliant settings. In addition, be aware that TLS v1.3 does not work with FIPS 140-2, as HKDF is not a certified primitive. HashiCorp is not a NIST-certified testing laboratory and can only provide general guidance about using Consul Enterprise in a FIPS-compliant manner. We recommend consulting an approved auditor for further information. @@ -32,6 +32,10 @@ The FIPS 140-2 variant of Consul uses separate binaries that are available from The above naming conventions, which append `.fips1402` to binary names and tags, and `-fips` to registry names, also apply to `consul-k8s`, `consul-k8s-control-plane`, `consul-dataplane`, and `consul-ecs`, which are packaged separately from Consul Enterprise. +### Cluster peering support + +A Consul cluster running FIPS variants of Consul can peer with any combination of standard (non-FIPS) Consul clusters and FIPS Consul clusters. Consul supports all cluster peering features between FIPS clusters and non-FIPS clusters. + ### Usage restrictions When using Consul Enterprise with FIPS 140-2, be aware of the following operation restrictions: @@ -41,6 +45,7 @@ When using Consul Enterprise with FIPS 140-2, be aware of the following operatio We do not support in-place migrations from non-FIPS builds of Consul to FIPS builds of Consul, regardless of version. A fresh cluster installation is required to support FIPS 140-2. You cannot upgrade directly to a FIPS-compliant build. #### TLS restrictions + Consul Enterprise's FIPS modifications include restrictions to supported TLS cipher suites and key information. Only the following cipher suites are allowed: - `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256` @@ -121,7 +126,21 @@ Similarly, on a FIPS Windows binary, run `go tool nm` on the binary to get a sym On both Linux and Windows non-FIPS builds, the search output yields no results. -### Compliance validation +## Leidos validation + +In 2024, Leidos certified the integration of FIPS 140-2 cryptographic module [BoringCrypto Cert. #4407](https://csrc.nist.gov/Projects/Cryptographic-Module-Validation-Program/Certificate/4407) for the following Consul releases: -A Lab, authorized by the U.S. Government to certify FIPS 140-2 compliance, is in the process of verifying that Consul Enterprise and its related packages are compliant with the requirements of FIPS 140-2 Level 1. +- Consul Enterprise builds: + - [`consul_1.16.0+ent.fips1402`](https://releases.hashicorp.com/consul/1.16.0+ent.fips1402/) + - [`consul_1.16.1+ent.fips1402`](https://releases.hashicorp.com/consul/1.16.1+ent.fips1402/) +- Consul Dataplane builds: + - [`consul-dataplane_1.2.0+fips1402`](https://releases.hashicorp.com/consul-dataplane/1.2.0+fips1402/) + - [`consul-dataplane_1.2.1+fips1402`](https://releases.hashicorp.com/consul-dataplane/1.2.1+fips1402/) +- Consul K8s builds: + - [`consul-k8s_1.2.0+fips1402`](https://releases.hashicorp.com/consul-k8s/1.2.0+fips1402/) + - [`consul-k8s_1.2.1+fips1402`](https://releases.hashicorp.com/consul-k8s/1.2.1+fips1402/) +- Consul K8s Control Plane builds: + - [`consul-k8s-control-plane_1.2.0+fips1402`](https://releases.hashicorp.com/consul-k8s-control-plane/1.2.0+fips1402/) + - [`consul-k8s-control-plane_1.2.1+fips1402`](https://releases.hashicorp.com/consul-k8s-control-plane/1.2.2+fips1402/) +For more information about verified platform architectures and confirmed feature support, [review the Leidos certification letter](https://www.datocms-assets.com/2885/1715791547-boringcrypto_compliance_letter_signed.pdf). \ No newline at end of file diff --git a/website/content/docs/enterprise/index.mdx b/website/content/docs/enterprise/index.mdx index ea616f7d1f9a..b77df6969232 100644 --- a/website/content/docs/enterprise/index.mdx +++ b/website/content/docs/enterprise/index.mdx @@ -18,37 +18,39 @@ The following features are [available in several forms of Consul Enterprise](#co ### Multi-Tenancy -- [Admin Partitions](/consul/docs/enterprise/admin-partitions): Define administrative boundaries between tenants within a single Consul datacenter -- [Namespaces](/consul/docs/enterprise/namespaces): Define resource boundaries within a single admin partition for further organizational flexibility -- [Sameness Groups](/consul/docs/connect/config-entries/sameness-group): Define partitions and cluster peers as members of a group with identical services +- [Admin Partitions](/consul/docs/enterprise/admin-partitions): Define administrative boundaries between tenants within a single Consul datacenter. +- [Namespaces](/consul/docs/enterprise/namespaces): Define resource boundaries within a single admin partition for further organizational flexibility. +- [Sameness Groups](/consul/docs/connect/config-entries/sameness-group): Define partitions and cluster peers as members of a group with identical services. ### Resiliency -- [Automated Backups](/consul/docs/enterprise/backups): Configure the automatic backup of Consul state +- [Automated Backups](/consul/docs/enterprise/backups): Configure the automatic backup of Consul state. - [Redundancy Zones](/consul/docs/enterprise/redundancy): Deploy backup voting Consul servers to efficiently improve Consul fault tolerance - [Server request rate limits per source IP](/consul/docs/agent/limits/usage/limit-request-rates-from-ips): Limit gRPC and RPC traffic to servers for source IP addresses. -- [Traffic rate limiting for services](/consul/docs/connect/manage-traffic/limit-request-rates): Limit the rate of HTTP requests a service receives per service instance. +- [Traffic rate limiting for services](/consul/docs/connect/manage-traffic/limit-request-rates): Limit the rate of HTTP requests a service receives per service instance. - [Locality-aware routing](/consul/docs/connect/manage-traffic/route-to-local-upstreams): Prioritize upstream services in the same region and zone as the downstream service. +- [Fault injection](/consul/docs/connect/manage-traffic/fault-injection): Explore the resiliency of downstream services in response to problems with an upstream service, such as errors, latency, or response rate limits. ### Scalability -- [Read Replicas](/consul/docs/enterprise/read-scale): Deploy non-voting Consul servers to enhance the scalability of read requests +- [Read Replicas](/consul/docs/enterprise/read-scale): Deploy non-voting Consul servers to enhance the scalability of read requests. ### Operational simplification -- [Automated Upgrades](/consul/docs/enterprise/upgrades): Ease upgrades by automating the transition from existing to newly deployed Consul servers -- [Consul-Terraform-Sync Enterprise](/consul/docs/nia/enterprise): Leverage the enhanced network infrastructure automation capabilities of the enterprise version of Consul-Terraform-Sync +- [Long Term Support (LTS)](/consul/docs/enterprise/long-term-support): Reduce operational overhead and risk by using LTS releases that are maintained for longer than standard releases. +- [Automated Upgrades](/consul/docs/enterprise/upgrades): Ease upgrades by automating the transition from existing to newly deployed Consul servers. +- [Consul-Terraform-Sync Enterprise](/consul/docs/nia/enterprise): Leverage the enhanced network infrastructure automation capabilities of the enterprise version of Consul-Terraform-Sync. ### Complex network topology support -- [Network Areas](/consul/docs/enterprise/federation): Support complex network topologies between federated Consul datacenters with pairwise federation rather than full mesh federation -- [Network Segments](/consul/docs/enterprise/network-segments/network-segments-overview): Support complex network topologies within a Consul datacenter by enforcing boundaries in Consul client gossip traffic +- [Network Areas](/consul/docs/enterprise/federation): Support complex network topologies between federated Consul datacenters with pairwise federation rather than full mesh federation. +- [Network Segments](/consul/docs/enterprise/network-segments/network-segments-overview): Support complex network topologies within a Consul datacenter by enforcing boundaries in Consul client gossip traffic. ### Governance -- [OIDC Auth Method](/consul/docs/security/acl/auth-methods/oidc): Manage user access to Consul through an OIDC identity provider instead of Consul ACL tokens directly -- [Audit Logging](/consul/docs/enterprise/audit-logging): Understand Consul access and usage patterns by reviewing access to the Consul HTTP API -- JWT authentication and authorization for API gateway: Prevent unverified traffic at the API gateway using JWTs for authentication and authorization on [VMs](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms) and on [Kubernetes](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-k8s): +- [OIDC Auth Method](/consul/docs/security/acl/auth-methods/oidc): Manage user access to Consul through an OIDC identity provider instead of Consul ACL tokens directly. +- [Audit Logging](/consul/docs/enterprise/audit-logging): Understand Consul access and usage patterns by reviewing access to the Consul HTTP API. +- JWT authentication and authorization for API gateway: Prevent unverified traffic at the API gateway using JWTs for authentication and authorization on [VMs](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms) and on [Kubernetes](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-k8s). ### Regulatory compliance @@ -63,17 +65,17 @@ The following features are [available in several forms of Consul Enterprise](#co ## Access Consul Enterprise The method of accessing Consul Enterprise and its features depends on the whether using -HashiCorp Cloud Platform or self-managed Consul. +HashiCorp Cloud Platform or self-managed Consul Enterprise. -### HCP Consul +### HCP Consul Dedicated No action is required to access Consul Enterprise in a [HashiCorp Cloud Platform](https://cloud.hashicorp.com/products/consul) installation. -You can try out HCP Consul for free. Refer to the -[HCP Consul product page](https://cloud.hashicorp.com/products/consul) for more details. +You can try out HCP Consul Dedicated for free. Refer to the +[HCP Consul Dedicated product page](https://cloud.hashicorp.com/products/consul) for more details. -### Self-Managed Consul +### Self-managed Consul Enterprise To access Consul Enterprise in a self-managed installation, [apply a purchased license](/consul/docs/enterprise/license/overview) @@ -89,24 +91,28 @@ The Consul Enterprise features that are available depend on your license and the Available Enterprise features per Consul form and license include: -| Feature | [HashiCorp Cloud Platform (HCP) Consul] | [Consul Enterprise] | Legacy Consul Enterprise (module-based) | -| -------------------------------------------------------- | --------------------------------------- | ------------------- | ------------------------------------------------- | -| Consul servers as a managed service | Yes | No (self-managed) | No (self-managed) | -| [Admin Partitions](/consul/docs/enterprise/admin-partitions) | All tiers | Yes | With Governance and Policy module | -| [Audit Logging](/consul/docs/enterprise/audit-logging) | Standard tier and above | Yes | With Governance and Policy module | -| [Automated Server Backups](/consul/docs/enterprise/backups) | All tiers | Yes | Yes | -| [Automated Server Upgrades](/consul/docs/enterprise/upgrades) | All tiers | Yes | Yes | -| [Consul-Terraform-Sync Enterprise](/consul/docs/nia/enterprise) | All tiers | Yes | Yes | -| [Enhanced Read Scalability](/consul/docs/enterprise/read-scale) | No | Yes | With Global Visibility, Routing, and Scale module | -| [FIPS 140-2 Compliance](/consul/docs/enterprise/fips) | No | Yes | No | -| [Namespaces](/consul/docs/enterprise/namespaces) | All tiers | Yes | With Governance and Policy module | -| [Network Areas](/consul/docs/enterprise/federation) | No | Yes | With Global Visibility, Routing, and Scale module | -| [Network Segments](/consul/docs/enterprise/network-segments/network-segments-overview) | No | Yes | With Global Visibility, Routing, and Scale module | -| [OIDC Auth Method](/consul/docs/security/acl/auth-methods/oidc) | No | Yes | Yes | -| [Redundancy Zones](/consul/docs/enterprise/redundancy) | Not applicable | Yes | With Global Visibility, Routing, and Scale module | -| [Sameness Groups](/consul/docs/connect/config-entries/sameness-group) | No | Yes | N/A | -| [Server request rate limits per source IP](/consul/docs/agent/limits/usage/limit-request-rates-from-ips) | All tiers | Yes | With Governance and Policy module | - +| Feature | [HashiCorp Cloud Platform (HCP) Consul] | [Consul Enterprise] | Legacy Consul Enterprise (module-based) | +| ------------------------------------------------------------------------------------------------------------- | --------------------------------------- | ------------------- | ------------------------------------------------- | +| Consul servers as a managed service | Yes | No (self-managed) | No (self-managed) | +| [Admin Partitions](/consul/docs/enterprise/admin-partitions) | All tiers | Yes | With Governance and Policy module | +| [Audit Logging](/consul/docs/enterprise/audit-logging) | Standard tier and above | Yes | With Governance and Policy module | +| [Automated Server Backups](/consul/docs/enterprise/backups) | All tiers | Yes | Yes | +| [Automated Server Upgrades](/consul/docs/enterprise/upgrades) | All tiers | Yes | Yes | +| [Consul-Terraform-Sync Enterprise](/consul/docs/nia/enterprise) | All tiers | Yes | Yes | +| [Enhanced Read Scalability](/consul/docs/enterprise/read-scale) | No | Yes | With Global Visibility, Routing, and Scale module | +| [Fault injection](/consul/docs/connect/manage-traffic/fault-injection) | Yes | Yes | No | +| [FIPS 140-2 Compliance](/consul/docs/enterprise/fips) | No | Yes | No | +| [JWT verification for API gateways](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms) | Yes | Yes | Yes | +| [Locality-aware routing](/consul/docs/connect/manage-traffic/route-to-local-upstreams) | Yes | Yes | Yes | +| [Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) | Not applicable | Yes | Not applicable | +| [Namespaces](/consul/docs/enterprise/namespaces) | All tiers | Yes | With Governance and Policy module | +| [Network Areas](/consul/docs/enterprise/federation) | No | Yes | With Global Visibility, Routing, and Scale module | +| [Network Segments](/consul/docs/enterprise/network-segments/network-segments-overview) | No | Yes | With Global Visibility, Routing, and Scale module | +| [OIDC Auth Method](/consul/docs/security/acl/auth-methods/oidc) | No | Yes | Yes | +| [Redundancy Zones](/consul/docs/enterprise/redundancy) | Not applicable | Yes | With Global Visibility, Routing, and Scale module | +| [Sameness Groups](/consul/docs/connect/config-entries/sameness-group) | No | Yes | Not applicable | +| [Server request rate limits per source IP](/consul/docs/agent/limits/usage/limit-request-rates-from-ips) | All tiers | Yes | With Governance and Policy module | +| [Traffic rate limiting for services](/consul/docs/connect/manage-traffic/limit-request-rates) | Yes | Yes | Yes | [HashiCorp Cloud Platform (HCP) Consul]: https://cloud.hashicorp.com/products/consul [Consul Enterprise]: https://www.hashicorp.com/products/consul/ @@ -119,69 +125,75 @@ Consul Enterprise feature availability can change depending on your server and c -| Enterprise Feature | VM Client | K8s Client | ECS Client | -|----------------------------------------------------------------------------------------------------------|:---------:|:----------:| :--------: | -| [Admin Partitions](/consul/docs/enterprise/admin-partitions) | ✅ | ✅ | ✅ | -| [Audit Logging](/consul/docs/enterprise/audit-logging) | ✅ | ✅ | ✅ | -| [Automated Server Backups](/consul/docs/enterprise/backups) | ✅ | ✅ | ✅ | -| [Automated Server Upgrades](/consul/docs/enterprise/upgrades) | ✅ | ✅ | ✅ | -| [Enhanced Read Scalability](/consul/docs/enterprise/read-scale) | ✅ | ✅ | ✅ | -| [FIPS 140-2 Compliance](/consul/docs/enterprise/fips) | ✅ | ✅ | ✅ | -| [JWT verification for API gateways](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms) | ✅ | ✅ | ❌ | -| [Locality-aware routing](/consul/docs/connect/manage-traffic/route-to-local-upstreams) | ✅ | ✅ | ✅ | -| [Namespaces](/consul/docs/enterprise/namespaces) | ✅ | ✅ | ✅ | -| [Network Areas](/consul/docs/enterprise/federation) | ✅ | ✅ | ✅ | -| [Network Segments](/consul/docs/enterprise/network-segments/network-segments-overview) | ✅ | ❌ | ❌ | -| [OIDC Auth Method](/consul/docs/security/acl/auth-methods/oidc) | ✅ | ✅ | ✅ | -| [Redundancy Zones](/consul/docs/enterprise/redundancy) | ✅ | ✅ | ✅ | -| [Sameness Groups](/consul/docs/connect/config-entries/sameness-group) | ✅ | ✅ | ✅ | -| [Server request rate limits per source IP](/consul/docs/agent/limits/usage/limit-request-rates-from-ips) | ✅ | ✅ | ✅ | -| [Traffic rate limiting for services](/consul/docs/connect/manage-traffic/limit-request-rates) | ✅ | ✅ | ✅ | +| Enterprise Feature | VM Client | K8s Client | ECS Client | +|-------------------------------------------------------------------------------------------------------------- | :-------: | :--------: | :--------: | +| [Admin Partitions](/consul/docs/enterprise/admin-partitions) | ✅ | ✅ | ✅ | +| [Audit Logging](/consul/docs/enterprise/audit-logging) | ✅ | ✅ | ✅ | +| [Automated Server Backups](/consul/docs/enterprise/backups) | ✅ | ✅ | ✅ | +| [Automated Server Upgrades](/consul/docs/enterprise/upgrades) | ✅ | ✅ | ✅ | +| [Enhanced Read Scalability](/consul/docs/enterprise/read-scale) | ✅ | ✅ | ✅ | +| [Fault injection](/consul/docs/connect/manage-traffic/fault-injection) | ✅ | ✅ | ✅ | +| [FIPS 140-2 Compliance](/consul/docs/enterprise/fips) | ✅ | ✅ | ✅ | +| [JWT verification for API gateways](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms) | ✅ | ✅ | ❌ | +| [Locality-aware routing](/consul/docs/connect/manage-traffic/route-to-local-upstreams) | ✅ | ✅ | ✅ | +| [Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) | ✅ | ✅ | ❌ | +| [Namespaces](/consul/docs/enterprise/namespaces) | ✅ | ✅ | ✅ | +| [Network Areas](/consul/docs/enterprise/federation) | ✅ | ✅ | ✅ | +| [Network Segments](/consul/docs/enterprise/network-segments/network-segments-overview) | ✅ | ✅ | ❌ | +| [OIDC Auth Method](/consul/docs/security/acl/auth-methods/oidc) | ✅ | ✅ | ✅ | +| [Redundancy Zones](/consul/docs/enterprise/redundancy) | ✅ | ✅ | ✅ | +| [Sameness Groups](/consul/docs/connect/config-entries/sameness-group) | ✅ | ✅ | ✅ | +| [Server request rate limits per source IP](/consul/docs/agent/limits/usage/limit-request-rates-from-ips) | ✅ | ✅ | ✅ | +| [Traffic rate limiting for services](/consul/docs/connect/manage-traffic/limit-request-rates) | ✅ | ✅ | ✅ | | Enterprise Feature | VM Client | K8s Client | ECS Client | -|---------------------------------------------------------------------------------------------------------------| :-------: | :--------: | :--------: | -| [Admin Partitions](/consul/docs/enterprise/admin-partitions) | ✅ | ✅ | ✅ | -| [Audit Logging](/consul/docs/enterprise/audit-logging) | ✅ | ✅ | ✅ | -| [Automated Server Backups](/consul/docs/enterprise/backups) | ✅ | ✅ | ✅ | +|-------------------------------------------------------------------------------------------------------------- | :-------: | :--------: | :--------: | +| [Admin Partitions](/consul/docs/enterprise/admin-partitions) | ✅ | ✅ | ✅ | +| [Audit Logging](/consul/docs/enterprise/audit-logging) | ✅ | ✅ | ✅ | +| [Automated Server Backups](/consul/docs/enterprise/backups) | ✅ | ✅ | ✅ | | [Automated Server Upgrades](/consul/docs/enterprise/upgrades) | ❌ | ❌ | ❌ | | [Enhanced Read Scalability](/consul/docs/enterprise/read-scale) | ❌ | ❌ | ❌ | -| [FIPS 140-2 Compliance](/consul/docs/enterprise/fips) | ✅ | ✅ | ✅ | -| [JWT verification for API gateways](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-k8s) | ✅ | ✅ | ❌ | -| [Locality-aware routing](/consul/docs/connect/manage-traffic/route-to-local-upstreams) | ✅ | ✅ | ✅ | -| [Namespaces](/consul/docs/enterprise/namespaces) | ✅ | ✅ | ✅ | -| [Network Areas](/consul/docs/enterprise/federation) | ✅ | ✅ | ✅ | -| [Network Segments](/consul/docs/enterprise/network-segments/network-segments-overview) | ❌ | ❌ | ❌ | -| [OIDC Auth Method](/consul/docs/security/acl/auth-methods/oidc) | ✅ | ✅ | ✅ | +| [Fault injection](/consul/docs/connect/manage-traffic/fault-injection) | ✅ | ✅ | ✅ | +| [FIPS 140-2 Compliance](/consul/docs/enterprise/fips) | ✅ | ✅ | ✅ | +| [JWT verification for API gateways](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-k8s) | ✅ | ✅ | ❌ | +| [Locality-aware routing](/consul/docs/connect/manage-traffic/route-to-local-upstreams) | ✅ | ✅ | ✅ | +| [Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) | ✅ | ✅ | ❌ | +| [Namespaces](/consul/docs/enterprise/namespaces) | ✅ | ✅ | ✅ | +| [Network Areas](/consul/docs/enterprise/federation) | ✅ | ✅ | ✅ | +| [Network Segments](/consul/docs/enterprise/network-segments/network-segments-overview) | ✅ | ✅ | ❌ | +| [OIDC Auth Method](/consul/docs/security/acl/auth-methods/oidc) | ✅ | ✅ | ✅ | | [Redundancy Zones](/consul/docs/enterprise/redundancy) | ❌ | ❌ | ❌ | -| [Sameness Groups](/consul/docs/connect/config-entries/sameness-group) | ✅ | ✅ | ✅ | -| [Server request rate limits per source IP](/consul/docs/agent/limits/usage/limit-request-rates-from-ips) | ✅ | ✅ | ✅ | -| [Traffic rate limiting for services](/consul/docs/connect/manage-traffic/limit-request-rates) | ✅ | ✅ | ✅ | +| [Sameness Groups](/consul/docs/connect/config-entries/sameness-group) | ✅ | ✅ | ✅ | +| [Server request rate limits per source IP](/consul/docs/agent/limits/usage/limit-request-rates-from-ips) | ✅ | ✅ | ✅ | +| [Traffic rate limiting for services](/consul/docs/connect/manage-traffic/limit-request-rates) | ✅ | ✅ | ✅ | -| Enterprise Feature | VM Client | K8s Client | ECS Client | -| ----------------------------------------------------------------------- | :-------: | :--------: | :--------: | -| [Admin Partitions](/consul/docs/enterprise/admin-partitions) | ✅ | ✅ | ✅ | -| [Audit Logging](/consul/docs/enterprise/audit-logging) | ✅ | ✅ | ✅ | -| [Automated Server Backups](/consul/docs/enterprise/backups) | ✅ | ✅ | ✅ | -| [Automated Server Upgrades](/consul/docs/enterprise/upgrades) | ✅ | ✅ | ✅ | -| [Enhanced Read Scalability](/consul/docs/enterprise/read-scale) | ❌ | ❌ | ❌ | -| [FIPS 140-2 Compliance](/consul/docs/enterprise/fips) | ❌ | ❌ | ❌ | -| [JWT verification for API gateways](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms) | ✅ | ✅ | ❌ | -| [Locality-aware routing](/consul/docs/connect/manage-traffic/route-to-local-upstreams) | ✅ | ✅ | ✅ | -| [Namespaces](/consul/docs/enterprise/namespaces) | ✅ | ✅ | ✅ | -| [Network Areas](/consul/docs/enterprise/federation) | ❌ | ❌ | ❌ | -| [Network Segments](/consul/docs/enterprise/network-segments/network-segments-overview) | ❌ | ❌ | ❌ | -| [OIDC Auth Method](/consul/docs/security/acl/auth-methods/oidc) | ❌ | ❌ | ❌ | -| [Redundancy Zones](/consul/docs/enterprise/redundancy) | n/a | n/a | n/a | -| [Sameness Groups](/consul/docs/connect/config-entries/sameness-group) | ✅ | ✅ | ✅ | -| [Server request rate limits per source IP](/consul/docs/agent/limits/usage/limit-request-rates-from-ips) | ✅ | ✅ | ✅ | -| [Traffic rate limiting for services](/consul/docs/connect/manage-traffic/limit-request-rates) | ✅ | ✅ | ✅ | +| Enterprise Feature | VM Client | K8s Client | ECS Client | +| ------------------------------------------------------------------------------------------------------------- | :-------: | :--------: | :--------: | +| [Admin Partitions](/consul/docs/enterprise/admin-partitions) | ✅ | ✅ | ✅ | +| [Audit Logging](/consul/docs/enterprise/audit-logging) | ✅ | ✅ | ✅ | +| [Automated Server Backups](/consul/docs/enterprise/backups) | ✅ | ✅ | ✅ | +| [Automated Server Upgrades](/consul/docs/enterprise/upgrades) | ✅ | ✅ | ✅ | +| [Enhanced Read Scalability](/consul/docs/enterprise/read-scale) | ❌ | ❌ | ❌ | +| [Fault injection](/consul/docs/connect/manage-traffic/fault-injection) | ✅ | ✅ | ✅ | +| [FIPS 140-2 Compliance](/consul/docs/enterprise/fips) | ❌ | ❌ | ❌ | +| [JWT verification for API gateways](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms) | ✅ | ✅ | ❌ | +| [Locality-aware routing](/consul/docs/connect/manage-traffic/route-to-local-upstreams) | ✅ | ✅ | ✅ | +| [Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) | N/A | N/A | N/A | +| [Namespaces](/consul/docs/enterprise/namespaces) | ✅ | ✅ | ✅ | +| [Network Areas](/consul/docs/enterprise/federation) | ❌ | ❌ | ❌ | +| [Network Segments](/consul/docs/enterprise/network-segments/network-segments-overview) | ❌ | ❌ | ❌ | +| [OIDC Auth Method](/consul/docs/security/acl/auth-methods/oidc) | ❌ | ❌ | ❌ | +| [Redundancy Zones](/consul/docs/enterprise/redundancy) | N/A | N/A | N/A | +| [Sameness Groups](/consul/docs/connect/config-entries/sameness-group) | ✅ | ✅ | ✅ | +| [Server request rate limits per source IP](/consul/docs/agent/limits/usage/limit-request-rates-from-ips) | ✅ | ✅ | ✅ | +| [Traffic rate limiting for services](/consul/docs/connect/manage-traffic/limit-request-rates) | ✅ | ✅ | ✅ | diff --git a/website/content/docs/enterprise/license/faq.mdx b/website/content/docs/enterprise/license/faq.mdx index d8a46ee20934..4278f7ec5ebf 100644 --- a/website/content/docs/enterprise/license/faq.mdx +++ b/website/content/docs/enterprise/license/faq.mdx @@ -120,9 +120,9 @@ Contact your organization's [HashiCorp account team](https://support.hashicorp.c The license files are not locked to a specific cluster or cluster node. The above changes apply to all nodes in a cluster. -## Q: Will this impact HCP Consul? +## Q: Will this impact HCP Consul Dedicated? -This will not impact HCP Consul. +This will not impact HCP Consul Dedicated. ## Q: Does this need to happen every time a node restarts, or is this a one-time check? diff --git a/website/content/docs/enterprise/long-term-support.mdx b/website/content/docs/enterprise/long-term-support.mdx new file mode 100644 index 000000000000..ff73a4cc9254 --- /dev/null +++ b/website/content/docs/enterprise/long-term-support.mdx @@ -0,0 +1,122 @@ +--- +layout: docs +page_title: Long Term Support (LTS) +description: >- + Consul Enterprise offers a Long Term Support (LTS) release program. Learn about benefits and terms, including which versions receive extended support, for how long, and fix eligibility. +--- + +# Long Term Support (LTS) + + + This program requires Consul Enterprise. + + +Consul Enterprise offers annual Long Term Support (LTS) releases starting with version v1.15. LTS releases maintain longer fix eligibility and support larger upgrade jumps. + +This page describes the LTS program, its benefits for Enterprise users, and the support the program includes. + +## Overview + +Many Enterprise organizations want to minimize their operational risk by operating a maintained Consul version that is eligible for critical fixes and does not require frequent upgrades. + +Annual Consul Enterprise LTS releases enable organizations to receive critical fixes without upgrading their major version more than once per year. + +The following table lists the lifecycle for each existing LTS release, including expected end of maintenance (EOM). + +| LTS release | Release date | Estimated EOM date | +| ----------- | ------------- | --------------------------------- | +| v1.18 Ent | Feb 27, 2024 | Feb 28, 2026 (v1.24 Ent release) | +| v1.15 Ent | Feb 23, 2023 | Feb 28, 2025 (v1.21 Ent release) | + +## Release lifecycle + +Consul Enterprise LTS releases are maintained for longer than other Consul releases, +as described in the following sections. + +### Standard Term Support lifecycle + +All major releases of Consul Enterprise receive _Standard Term Support_ (STS) +for approximately one year, per HashiCorp's +[Support Period Policy](https://support.hashicorp.com/hc/en-us/articles/360021185113-Support-Period-and-End-of-Life-EOL-Policy). + +With STS, each major release branch is maintained until it is +three (3) releases from the latest major release. +For example, Consul v1.14.x is maintained until the release of Consul v1.17.0. + +### Long Term Support lifecycle + +Starting with Consul Enterprise v1.15, the first major release of the calendar year +receives _Long Term Support_ (LTS) for approximately 2 years. +The first major release of the calendar year typically occurs in late February. + +![Consul Enterprise Long Term Support lifecycle diagram](/img/long-term-support/consul-enterprise-long-term-support-lifecycle.png#light-theme-only) +![Consul Enterprise Long Term Support lifecycle diagram](/img/long-term-support/consul-enterprise-long-term-support-lifecycle-dark.png#dark-theme-only) + +An LTS release is maintained until it is six (6) releases from the latest major release. +For example, Consul Enterprise v1.15.x is maintained until the release of Consul Enterprise v1.21.0. + +During the LTS window, [eligible LTS fixes](#fix-eligibility) are provided through +a new minor release on the affected LTS release branch. + +## Annual upgrade to next LTS release + +We recommend upgrading your Consul LTS version once per year to the next LTS version +in order to receive the full benefit of LTS. This upgrade pattern ensures the +organization is always operating a maintained release with minimal upgrades. + +Only Consul Enterprise LTS versions support direct upgrades to the next 3 major versions, +enabling direct upgrades from one LTS release to the subsequent LTS release. +For example, Consul Enterprise v1.15.x supports upgrading directly to Consul Enterprise v1.18.x. + +Because Consul has 3 major version releases per year, +LTS enables you to catch up on a year's worth of Consul releases in a single upgrade. + +STS releases of Consul support direct upgrades to the next 2 major versions, +as described in the [standard upgrade instructions](/consul/docs/upgrading/instructions). +Without LTS, catching up on a year's worth of releases requires two upgrades. +For example, upgrading from Consul Enterprise v1.14.x to Consul Enterprise v1.17.x +requires an intermediate upgrade to v1.15.x or v1.16.x. + +## Fix eligibility + +Eligibility for an LTS fix is subject to the following criteria: +- A non-security bug must be a Severity 1 (Urgent) or Severity 2 (High) issue + as defined in [HashiCorp Support's Severity Definitions](https://support.hashicorp.com/hc/en-us/articles/115011286028). +- A security bug (CVE) is considered eligible in accordance with + HashiCorp's standard practices for security bugs on supported products. + Refer to the standard + [Support Period Policy](https://support.hashicorp.com/hc/en-us/articles/360021185113-Support-Period-and-End-of-Life-EOL-Policy) + for more information. +- The bug must be present in built artifacts intended for use in production + created from one of the following HashiCorp repositories: + - hashicorp/consul-enterprise + - hashicorp/consul-k8s + - hashicorp/consul-dataplane +- The bug must be applicable for at least one of the following + computer architecture and operating system combinations: + - linux_386 + - linux_amd64 + - linux_arm + - linux_arm64 + - windows_386 + - windows_amd64 + +Eligibility for a fix does not guarantee that a fix will be issued. +For example, some fixes may not be technically possible on a given release branch, +or they may present an undue burden or risk relative to the benefit of the fix. + +HashiCorp may, in its sole discretion, include fixes in a minor release +on an LTS release branch that do not meet the eligibility criteria above. + +## Version compatibility with dependencies + +Consul integrates with Envoy and Kubernetes releases that are maintained for less time +than Consul Enterprise LTS. + +HashiCorp will make a reasonable effort to keep each Consul Enterprise LTS release branch +compatible with a maintained release branch of Envoy and Kubernetes until the LTS release branch +approaches its end of maintenance. + +For more details on LTS version compatibility with dependencies, refer to the following topics: +- [Kubernetes version compatibility with Consul](/consul/docs/k8s/compatibility) +- [Envoy and Consul dataplane version compatibility with Consul](/consul/docs/connect/proxies/envoy) diff --git a/website/content/docs/enterprise/network-segments/network-segments-overview.mdx b/website/content/docs/enterprise/network-segments/network-segments-overview.mdx index 521bdf4e3e5a..f23358c4bed5 100644 --- a/website/content/docs/enterprise/network-segments/network-segments-overview.mdx +++ b/website/content/docs/enterprise/network-segments/network-segments-overview.mdx @@ -7,18 +7,18 @@ description: >- # Network Segments Overview -Network segmentation is the practice of dividing a network into multiple segments or subnets that act as independent networks. This topic provides an overview of concepts related to operating Consul in a segmented network. +Network segmentation is the practice of dividing a network into multiple segments or subnets that act as independent networks. This topic provides an overview of concepts related to operating Consul in a segmented network. -This feature requires Consul Enterprise version 0.9.3 or later. +This feature requires Consul Enterprise version 0.9.3 or later. Refer to the [enterprise feature matrix](/consul/docs/enterprise#consul-enterprise-feature-availability) for additional information. ## Segmented networks -Consul requires full connectivity between all agents in a datacenter within a LAN gossip pool. In some environments, however, business policies enforced through network rules or firewalls prevent full connectivity between all agents. These environments are called _segmented networks_. Network segments are isolated LAN gossip pools that only require full connectivity between agent members on the same segment. +Consul requires full connectivity between all agents in a datacenter within a LAN gossip pool. In some environments, however, business policies enforced through network rules or firewalls prevent full connectivity between all agents. These environments are called _segmented networks_. Network segments are isolated LAN gossip pools that only require full connectivity between agent members on the same segment. To use Consul in a segmented network, you must define the segments in your server agent configuration and direct client agents to join one of the segments. The Consul network segment configuration should match the LAN gossip pool boundaries. The following diagram shows how a network may be segmented: @@ -26,19 +26,17 @@ To use Consul in a segmented network, you must define the segments in your serve ## Default network segment -By default, all Consul agents are part of a shared Serf LAN gossip pool, referred to as the `` network segment. Because all agents are within the same segment, full mesh connectivity within the datacenter is required. The following diagram shows the `` network segment: +By default, all Consul agents are part of a shared Serf LAN gossip pool, referred to as the `` network segment. Because all agents are within the same segment, full mesh connectivity within the datacenter is required. The following diagram shows the `` network segment: ![Consul datacenter default agent connectivity: one network segment](/img/network-segments/consul-network-segments-single.png) ## Segment membership -Server agents are members of all segments. The datacenter includes the `` segment, as well as additional segments defined in the `segments` server agent configuration option. Refer to the [`segments`](/consul/docs/agent/config/config-files#segments) documentation for additional information. +Server agents are members of all segments. The datacenter includes the `` segment, as well as additional segments defined in the `segments` server agent configuration option. Refer to the [`segments`](/consul/docs/agent/config/config-files#segments) documentation for additional information. -Each client agent can only be a member of one segment at a time. Client agents are members of the `` segment unless they are configured to join a different segment. +Each client agent can only be a member of one segment at a time. Client agents are members of the `` segment unless they are configured to join a different segment. For a client agent to join the Consul datacenter, it must connect to another agent (client or server) within its configured segment. -Read the [Network Segments documentation](/consul/docs/enterprise/network-segments/network-segments-overview) to learn more about network segments. - -> **Info:** Network segments enable you to operate a Consul datacenter without full mesh (LAN) connectivity between agents. To federate multiple Consul datacenters without full mesh (WAN) connectivity between all server agents in all datacenters, diff --git a/website/content/docs/install/glossary.mdx b/website/content/docs/install/glossary.mdx index f11ae21e7be0..c8bee74d6d77 100644 --- a/website/content/docs/install/glossary.mdx +++ b/website/content/docs/install/glossary.mdx @@ -51,7 +51,7 @@ and our implementation is described [here](/consul/docs/architecture/consensus). ## Gossip -Consul is built on top of [Serf](https://www.serf.io/) which provides a full +Consul is built on top of [Serf](https://github.com/hashicorp/serf/) which provides a full [gossip protocol](https://en.wikipedia.org/wiki/Gossip_protocol) that is used for multiple purposes. Serf provides membership, failure detection, and event broadcast. Our use of these is described more in the [gossip documentation](/consul/docs/architecture/gossip). It is enough to know @@ -78,171 +78,171 @@ This section collects brief definitions of some of the terms used in the discuss ## Access Control List (ACL) -An Access Control List (ACL) is a list of user permissions for a file, folder, or -other object. It defines what users and groups can access the object and what +An Access Control List (ACL) is a list of user permissions for a file, folder, or +other object. It defines what users and groups can access the object and what operations they can perform. Consul uses Access Control Lists (ACLs) to secure the UI, API, CLI, service communications, and agent communications. Visit [Consul ACL Documentation and Guides](/consul/docs/security/acl) -## API Gateway -An Application Programming Interface (API) is a common software interface that -allows two applications to communicate. Most modern applications are built using -APIs. An API Gateway is a single point of entry into these modern applications +## API Gateway +An Application Programming Interface (API) is a common software interface that +allows two applications to communicate. Most modern applications are built using +APIs. An API Gateway is a single point of entry into these modern applications built using APIs. -## Application Security -Application Security is the process of making applications secure by detecting -and fixing any threats or information leaks. This can be done during or after -the app development lifecycle; although, it is easier for app teams and security -teams to incorporate security into an app even before the development process +## Application Security +Application Security is the process of making applications secure by detecting +and fixing any threats or information leaks. This can be done during or after +the app development lifecycle; although, it is easier for app teams and security +teams to incorporate security into an app even before the development process begins. -## Application Services -Application Services are a group of services, such as application performance -monitoring, load balancing, service discovery, service proxy, security, -autoscaling, etc. needed to deploy, run, and improve applications. +## Application Services +Application Services are a group of services, such as application performance +monitoring, load balancing, service discovery, service proxy, security, +autoscaling, etc. needed to deploy, run, and improve applications. -## Authentication and Authorization (AuthN and AuthZ) +## Authentication and Authorization (AuthN and AuthZ) Authentication (AuthN) deals with establishing user identity while Authorization (AuthZ) allows or denies access to the user based on user identity. -## Auto Scaling Groups -An Auto Scaling Group is an AWS specific term that represents a collection of -Amazon EC2 instances that are treated as a logical grouping for the purposes of -automatic scaling and management. -Learn more about Auto Scaling Groups +## Auto Scaling Groups +An Auto Scaling Group is an AWS specific term that represents a collection of +Amazon EC2 instances that are treated as a logical grouping for the purposes of +automatic scaling and management. +Learn more about Auto Scaling Groups [here](https://docs.aws.amazon.com/autoscaling/ec2/userguide/AutoScalingGroup.html). -## Autoscaling -Autoscaling is the process of automatically scaling computational resources based -on network traffic requirements. Autoscaling can be done either horizontally or -vertically. Horizontal scaling is done by adding more machines into the pool of -resources whereas vertical scaling means increasing the capacity of an existing +## Autoscaling +Autoscaling is the process of automatically scaling computational resources based +on network traffic requirements. Autoscaling can be done either horizontally or +vertically. Horizontal scaling is done by adding more machines into the pool of +resources whereas vertical scaling means increasing the capacity of an existing machine. -## Blue-Green Deployments -Blue-Green Deployment is a deployment method designed to reduce downtime by -running two identical production environments labeled Blue and Green. Blue is -the active while Green is the idle environment. +## Blue-Green Deployments +Blue-Green Deployment is a deployment method designed to reduce downtime by +running two identical production environments labeled Blue and Green. Blue is +the active while Green is the idle environment. -## Canary Deployments -Canary deployment is the pattern used for rolling out releases to a subset of -users or servers. The goal is deploy the updates to a subset of users, test it, -and then roll out the changes to everyone. +## Canary Deployments +Canary deployment is the pattern used for rolling out releases to a subset of +users or servers. The goal is deploy the updates to a subset of users, test it, +and then roll out the changes to everyone. -## Client-side Load Balancing -Client-side load balancing is a load balancing approach that relies on clients' -decision to call the right servers. As the name indicates, this approach is part -of the client application. Servers can still have their own load balancer +## Client-side Load Balancing +Client-side load balancing is a load balancing approach that relies on clients' +decision to call the right servers. As the name indicates, this approach is part +of the client application. Servers can still have their own load balancer alongside the client-side load balancer. -## Cloud Native Computing Foundation -The [Cloud Native Computing Foundation (CNCF)](https://github.com/cncf/foundation) -is a Linux Foundation project that was founded in 2015 to help advance +## Cloud Native Computing Foundation +The [Cloud Native Computing Foundation (CNCF)](https://github.com/cncf/foundation) +is a Linux Foundation project that was founded in 2015 to help advance container technology and align the tech industry around its evolution. -HashiCorp joined Cloud Native Computing Foundation to further HashiCorp -product integrations with CNCF projects and to work more closely with the -broader cloud-native community of cloud engineers. Read more +HashiCorp joined Cloud Native Computing Foundation to further HashiCorp +product integrations with CNCF projects and to work more closely with the +broader cloud-native community of cloud engineers. Read more [here](https://www.hashicorp.com/blog/hashicorp-joins-the-cncf/). -## Custom Resource Definition (CRD) -Custom resources are the extensions of the Kubernetes API. A Custom Resource -Definition (CRD) file allows users to define their own custom resources and +## Custom Resource Definition (CRD) +Custom resources are the extensions of the Kubernetes API. A Custom Resource +Definition (CRD) file allows users to define their own custom resources and allows the API server to handle the lifecycle. -## Egress Traffic -Egress traffic is network traffic that begins inside a network and proceeds +## Egress Traffic +Egress traffic is network traffic that begins inside a network and proceeds through its routers to a destination outside the network. -## Elastic Provisioning -Elastic Provisioning is the ability to provision computing resources +## Elastic Provisioning +Elastic Provisioning is the ability to provision computing resources dynamically to meet user demand. -## Envoy Proxy -[Envoy Proxy](https://www.envoyproxy.io/) is a modern, high performance, -small footprint edge and service proxy. Originally written and deployed at +## Envoy Proxy +[Envoy Proxy](https://www.envoyproxy.io/) is a modern, high performance, +small footprint edge and service proxy. Originally written and deployed at [Lyft](https://eng.lyft.com/announcing-envoy-c-l7-proxy-and-communication-bus-92520b6c8191), - Envoy Proxy is now an official project at [Cloud Native Computing Foundation - (CNCF)](https://www.cncf.io/cncf-envoy-project-journey/) + Envoy Proxy is now an official project at [Cloud Native Computing Foundation + (CNCF)](https://www.cncf.io/cncf-envoy-project-journey/) -## Forward Proxy -A forward proxy is used to forward outgoing requests from inside the network -to the Internet, usually through a firewall. The objective is to provide a level +## Forward Proxy +A forward proxy is used to forward outgoing requests from inside the network +to the Internet, usually through a firewall. The objective is to provide a level of security and to reduce network traffic. -## Hybrid Cloud Architecture -A hybrid cloud architecture is an IT architectural approach that mixes -on-premises, private cloud, and public cloud services. A hybrid cloud -environment incorporates workload portability, orchestration, and management +## Hybrid Cloud Architecture +A hybrid cloud architecture is an IT architectural approach that mixes +on-premises, private cloud, and public cloud services. A hybrid cloud +environment incorporates workload portability, orchestration, and management across the environments. -A private cloud, traditionally on-premises, is referred to an infrastructure +A private cloud, traditionally on-premises, is referred to an infrastructure environment managed by the user themselves. -A public cloud, traditionally off-premises, is referred to an infrastructure +A public cloud, traditionally off-premises, is referred to an infrastructure service provided by a third party. -## Identity-based authorization -Identity-based authorization is a security approach to restrict or allow access +## Identity-based authorization +Identity-based authorization is a security approach to restrict or allow access based on the authenticated identity of an individual. -## Infrastructure as a Service -Infrastructure as a Service, often referred to as IaaS, is a cloud computing -approach where the computing resources are delivered online via APIs. These +## Infrastructure as a Service +Infrastructure as a Service, often referred to as IaaS, is a cloud computing +approach where the computing resources are delivered online via APIs. These APIs communicate with underlying infrastructure like physical computing resources, - location, data partitioning, scaling, security, backup, etc. + location, data partitioning, scaling, security, backup, etc. -IaaS is one of the four types of cloud services along with SaaS +IaaS is one of the four types of cloud services along with SaaS (Software as a Service), PaaS (Platform as a Service), and Serverless. -## Infrastructure as Code -Infrastructure as Code (IaC) is the process of developers and operations teams' -ability of provisioning and managing computing resources automatically through +## Infrastructure as Code +Infrastructure as Code (IaC) is the process of developers and operations teams' +ability of provisioning and managing computing resources automatically through software, instead of using configuration tools. -## Ingress Controller -In Kubernetes, "ingress" is an object that allows access Kubernetes services -from outside the Kubernetes cluster. An ingress controller is responsible for -ingress, generally with a load balancer or an edge router that can help with +## Ingress Controller +In Kubernetes, "ingress" is an object that allows access Kubernetes services +from outside the Kubernetes cluster. An ingress controller is responsible for +ingress, generally with a load balancer or an edge router that can help with traffic management. -## Ingress Gateway -An Ingress Gateway is an edge of the mesh load balancer that provides secure and -reliable access from external networks to Kubernetes clusters. +## Ingress Gateway +An Ingress Gateway is an edge of the mesh load balancer that provides secure and +reliable access from external networks to Kubernetes clusters. -## Ingress Traffic -Ingress Traffic is the network traffic that originates outside the network and +## Ingress Traffic +Ingress Traffic is the network traffic that originates outside the network and has a destination inside the network. -## Key-Value Store -A Key-Value Store (or a KV Store) also referred to as a Key-Value Database is -a data model where each key is associated with one and only one value in +## Key-Value Store +A Key-Value Store (or a KV Store) also referred to as a Key-Value Database is +a data model where each key is associated with one and only one value in a collection. -## L4 - L7 Services -L4-L7 Services are a set of functions such as load balancing, web application -firewalls, service discovery, and monitoring for network layers within the +## L4 - L7 Services +L4-L7 Services are a set of functions such as load balancing, web application +firewalls, service discovery, and monitoring for network layers within the Open Systems Interconnection (OSI) model. -## Layer 7 Observability -Layer 7 Observability is a feature of Consul Service Mesh that enables a -unified workflow for metric collection, distributed tracking, and logging. -It also allows centralized configuration and management for a distributed -data plane. +## Layer 7 Observability +Layer 7 Observability is a feature of Consul Service Mesh that enables a +unified workflow for metric collection, distributed tracking, and logging. +It also allows centralized configuration and management for a distributed +data plane. -## Load Balancer -A load balancer is a network appliance that acts as a [reverse proxy](#reverse-proxy) +## Load Balancer +A load balancer is a network appliance that acts as a [reverse proxy](#reverse-proxy) and distributes network and application traffic across the servers. -## Load Balancing -Load Balancing is the process of distributing network and application traffic -across multiple servers. +## Load Balancing +Load Balancing is the process of distributing network and application traffic +across multiple servers. -## Load Balancing Algorithms -Load balancers follow an algorithm to determine how to route the traffic across +## Load Balancing Algorithms +Load balancers follow an algorithm to determine how to route the traffic across the server farm. Some of the commonly used algorithms are: 1. Round Robin 2. Least Connections @@ -251,127 +251,127 @@ the server farm. Some of the commonly used algorithms are: 5. Least Response Time Method 6. Least Bandwidth Method -## Multi-cloud -A multi-cloud environment generally uses two or more cloud computing services -from different vendors in a single architecture. This refers to the distribution -of compute resources, storage, and networking aspects across cloud environments. -A multi-cloud environment could be either all private cloud or all public cloud -or a combination of both. +## Multi-cloud +A multi-cloud environment generally uses two or more cloud computing services +from different vendors in a single architecture. This refers to the distribution +of compute resources, storage, and networking aspects across cloud environments. +A multi-cloud environment could be either all private cloud or all public cloud +or a combination of both. -## Multi-cloud Networking -Multi-cloud Networking provides network configuration and management across +## Multi-cloud Networking +Multi-cloud Networking provides network configuration and management across multiple cloud providers via APIs. -## Mutual Transport Layer Security (mTLS) -Mutual Transport Layer Security, also known as mTLS, is an authentication -mechanism that ensures network traffic security in both directions between -a client and server. +## Mutual Transport Layer Security (mTLS) +Mutual Transport Layer Security, also known as mTLS, is an authentication +mechanism that ensures network traffic security in both directions between +a client and server. -## Network Middleware Automation -The process of publishing service changes to network middleware such as -load balancers and firewalls and automating network tasks is called Network +## Network Middleware Automation +The process of publishing service changes to network middleware such as +load balancers and firewalls and automating network tasks is called Network Middleware Automation. -## Network security -Network security is the process of protecting data and network. It consists -of a set of policies and practices that are designed to prevent and monitor -unauthorized access, misuse, modification, or denial of a computer network +## Network security +Network security is the process of protecting data and network. It consists +of a set of policies and practices that are designed to prevent and monitor +unauthorized access, misuse, modification, or denial of a computer network and network-accessible resources. -## Network traffic management -Network Traffic Management is the process of ensuring optimal network operation -by using a set of network monitoring tools. Network traffic management also -focuses on traffic management techniques such as bandwidth monitoring, deep +## Network traffic management +Network Traffic Management is the process of ensuring optimal network operation +by using a set of network monitoring tools. Network traffic management also +focuses on traffic management techniques such as bandwidth monitoring, deep packet inspection, and application based routing. -## Network Visualization -Network Visualization is the process of visually displaying networks and -connected entities in a "boxes and lines" kind of a diagram. +## Network Visualization +Network Visualization is the process of visually displaying networks and +connected entities in a "boxes and lines" kind of a diagram. -In the context of microservices architecture, visualization can provide a clear -picture of how services are connected to each other, the service-to-service +In the context of microservices architecture, visualization can provide a clear +picture of how services are connected to each other, the service-to-service communication, and resource utilization of each service. -## Observability -Observability is the process of logging, monitoring, and alerting on the +## Observability +Observability is the process of logging, monitoring, and alerting on the events of a deployment or an instance. -## Elastic Scaling -Elastic Scaling is the ability to automatically add or remove compute or +## Elastic Scaling +Elastic Scaling is the ability to automatically add or remove compute or networking resources based on the changes in application traffic patterns. -## Platform as a Service -Platform-as-a-Service (PaaS) is a category of cloud computing that allows -users to develop, run, and manage applications without the complexity of -building and maintaining the infrastructure typically associated with -developing and launching the application. - -## Reverse Proxy -A reverse proxy handles requests coming from outside, to the internal -network. Reverse Proxy provides a level of security that prevents the -external clients from having direct access to data on the corporate servers. -The reverse proxy is usually placed between the web server and the external -traffic. - -## Role-based Access Controls -The act of restricting or provisioning access +## Platform as a Service +Platform-as-a-Service (PaaS) is a category of cloud computing that allows +users to develop, run, and manage applications without the complexity of +building and maintaining the infrastructure typically associated with +developing and launching the application. + +## Reverse Proxy +A reverse proxy handles requests coming from outside, to the internal +network. Reverse Proxy provides a level of security that prevents the +external clients from having direct access to data on the corporate servers. +The reverse proxy is usually placed between the web server and the external +traffic. + +## Role-based Access Controls +The act of restricting or provisioning access to a user based on their specific role in the organization. -## Server side load balancing -A Server-side Load Balancer sits between the client and the server farm, -accepts incoming traffic, and distributes the traffic across multiple backend +## Server side load balancing +A Server-side Load Balancer sits between the client and the server farm, +accepts incoming traffic, and distributes the traffic across multiple backend servers using various load balancing methods. -## Service configuration -A service configuration includes the name, description, and the specific -function of a service. In a microservices application architecture setting, +## Service configuration +A service configuration includes the name, description, and the specific +function of a service. In a microservices application architecture setting, a service configuration file includes a service definition. -## Service Catalog -A service catalog is an organized and curated collection of services that +## Service Catalog +A service catalog is an organized and curated collection of services that are available for developers to bind to their applications. -## Service Discovery -Service Discovery is the process of detecting services and devices on a -network. In a microservices context, service discovery is how applications +## Service Discovery +Service Discovery is the process of detecting services and devices on a +network. In a microservices context, service discovery is how applications and microservices locate each other on a network. -## Service Mesh -Service Mesh is the infrastructure layer that facilitates service-to-service -communication between microservices, often using a sidecar proxy. This -network of microservices make up microservice applications and the +## Service Mesh +Service Mesh is the infrastructure layer that facilitates service-to-service +communication between microservices, often using a sidecar proxy. This +network of microservices make up microservice applications and the interactions between them. -## Service Networking -Service networking brings several entities together to deliver a particular -service. Service Networking acts as the brain of an organization's +## Service Networking +Service networking brings several entities together to deliver a particular +service. Service Networking acts as the brain of an organization's networking and monitoring operations. -## Service Proxy -A service proxy is the client-side proxy for a microservice application. -It allows applications to send and receive messages over a proxy server. +## Service Proxy +A service proxy is the client-side proxy for a microservice application. +It allows applications to send and receive messages over a proxy server. -## Service Registration -Service registration is the process of letting clients (of the service) -and routers know about the available instances of the service. +## Service Registration +Service registration is the process of letting clients (of the service) +and routers know about the available instances of the service. Service instances are registered with a service registry on startup and deregistered at shutdown. -## Service Registry -Service Registry is a database of service instances and information on +## Service Registry +Service Registry is a database of service instances and information on how to send requests to these service instances. -## Microservice Segmentation -Microservice segmentation, sometimes visual, of microservices is the -segmentation in a microservices application architecture that enables +## Microservice Segmentation +Microservice segmentation, sometimes visual, of microservices is the +segmentation in a microservices application architecture that enables administrators to view their functions and interactions. -## Service-to-service communication -Service-to-service communication, sometimes referred to as -inter-service communication, is the ability of a microservice -application instance to communicate with another to collaborate and +## Service-to-service communication +Service-to-service communication, sometimes referred to as +inter-service communication, is the ability of a microservice +application instance to communicate with another to collaborate and handle client requests. -## Software as a Service -Software as a Service is a licensing and delivery approach to software -delivery where the software is hosted by a provider and licensed -to users on a subscription basis. +## Software as a Service +Software as a Service is a licensing and delivery approach to software +delivery where the software is hosted by a provider and licensed +to users on a subscription basis. diff --git a/website/content/docs/install/performance.mdx b/website/content/docs/install/performance.mdx index 778f4ad66989..c035cbf84041 100644 --- a/website/content/docs/install/performance.mdx +++ b/website/content/docs/install/performance.mdx @@ -110,9 +110,9 @@ Here are some general recommendations: - For DNS-heavy workloads, configuring all Consul agents in a cluster with the [`allow_stale`](/consul/docs/agent/config/config-files#allow_stale) configuration option will allow reads to scale across all Consul servers, not just the leader. Consul 0.7 and later enables stale reads - for DNS by default. See [Stale Reads](/consul/tutorials/networking/dns-caching#stale-reads) in the - [DNS Caching](/consul/tutorials/networking/dns-caching) guide for more details. It's also good to set - reasonable, non-zero [DNS TTL values](/consul/tutorials/networking/dns-caching#ttl-values) if your clients will + for DNS by default. See [Stale Reads](/consul/docs/services/discovery/dns-cache#stale-reads) in the + [DNS Caching](/consul/docs/services/discovery/dns-cache) guide for more details. It's also good to set + reasonable, non-zero [DNS TTL values](/consul/docs/services/discovery/dns-cache#ttl-values) if your clients will respect them. - In other applications that perform high volumes of reads against Consul, consider using the diff --git a/website/content/docs/install/ports.mdx b/website/content/docs/install/ports.mdx index 21254d9df58d..dea835f51be1 100644 --- a/website/content/docs/install/ports.mdx +++ b/website/content/docs/install/ports.mdx @@ -1,58 +1,243 @@ --- layout: docs -page_title: Required Ports -description: >- - Consul requires multiple ports for directing DNS, HTTP, gRPC, gossip, and sidecar proxy requests. Learn about required and optional ports, and how Consul uses them for specific communication functions. +page_title: Consul ports reference +description: Find information about the ports that Consul requires for its networking functions, including required ports for HCP Consul Dedicated. Required ports differ for Consul servers and clients. --- -# Required Ports +# Consul ports reference -Consul requires up to 6 different ports to work properly, some on -TCP, UDP, or both protocols. Below we document the requirements for each -port. +This page provides reference information about the required ports that Consul exposes for its operations. -## Ports Table +You can change or disable Consul's default ports in the [agent configuration file](/consul/docs/agent/config/config-files#ports) or using the [`consul agent` CLI command](/consul/docs/agent/config/cli-flags). -Before running Consul, you should ensure the following bind ports are accessible. +## Overview -| Use | Default Ports | -| ------------------------------------------------------------------------------------------------------------- | ----------------- | -| DNS: The DNS server (TCP and UDP) | 8600 | -| HTTP: The HTTP API (TCP Only) | 8500 | -| HTTPS: The HTTPs API | disabled (8501)\* | -| gRPC: The gRPC API | disabled (8502)\* | -| gRPC TLS: The gRPC API with TLS connections | disabled (8503)\* | -| LAN Serf: The Serf LAN port (TCP and UDP) | 8301 | -| Wan Serf: The Serf WAN port (TCP and UDP) | 8302 | -| server: Server RPC address (TCP Only) | 8300 | -| Sidecar Proxy Min: Inclusive min port number to use for automatically assigned sidecar service registrations. | 21000 | -| Sidecar Proxy Max: Inclusive max port number to use for automatically assigned sidecar service registrations. | 21255 | +The exact ports that Consul requires depend on your network's specific configuration. For example, the port for WAN serf communication is only required when using WAN federation. -\*For `HTTPS` and `gRPC` the ports specified in the table -are recommendations. +There are slight differences between the port requirements for Consul servers and clients. When a Consul server has services, proxies, or gateways registered to it, then it acts as both a server and client. -## Port Information +[HCP Consul Dedicated servers](/hcp/docs/consul) have distinct port assignments. For more information, refer to [cluster management in the HCP documentation](https://developer.hashicorp.com/hcp/docs/consul/concepts/cluster-management#hashicorp-managed-clusters). -**DNS Interface** Used to resolve DNS queries. +## Consul servers -**HTTP API** This is used by clients to talk to the HTTP -API. +The following table lists port names, their function, their network protocols, their default port numbers, whether they are enabled or disabled by default, port assignments for HCP Consul Dedicated server clusters, and the direction of traffic from the Consul server's perspective. -**HTTPS API** (Optional) Is off by default, but port 8501 is a convention -used by various tools as the default. +| Port name | Use | Protocol | Default port | Default status | HCP Consul Dedicated port | Direction | +| :------------------------ | :----------------------------------------- | :---------- | :----------- | :------------- | :--------------- | :-------------------- | +| [DNS](#dns) | The DNS server | TCP and UDP | `8600` | Enabled | Unsupported | Incoming | +| [HTTP](#http) | The HTTP API | TCP | `8500` | Enabled | Unsupported | Incoming | +| [HTTPS](#https) | The HTTPS API | TCP | `8501` | Disabled | `443` | Incoming | +| [gRPC](#grpc) | The gRPC API | TCP | `8502` | Disabled | Unsupported | Incoming | +| [gRPC TLS](#grpc-tls) | The gRPC API with TLS connections | TCP | `8503` | Enabled | `8502` | Incoming | +| [Server RPC](#server-rpc) | Consul internal communication with servers | TCP | `8300` | Enabled | `8300` | Incoming and outgoing | +| [LAN Serf](#lan-serf) | The Serf local area network port | TCP and UDP | `8301` | Enabled | `8301` | Incoming and outgoing | +| [WAN Serf](#wan-serf) | The Serf wide area network port | TCP and UDP | `8302` | Enabled | `8302` | Incoming and outgoing | -**gRPC API** (Optional). Currently gRPC is -only used to expose the xDS API to Envoy proxies. It is off by default, but port 8502 is a convention used by various tools as the default. Defaults to 8502 in `-dev` mode. +### DNS -**Serf LAN** This is used to handle gossip in the LAN. -Required by all agents. +The following table lists information about the server agent's DNS port defaults: -**Serf WAN** This is used by servers to gossip over the WAN, to -other servers. As of Consul 0.8 the WAN join flooding feature requires -the Serf WAN port (TCP/UDP) to be listening on both WAN and LAN interfaces. See also: -[Consul 0.8.0 CHANGELOG](https://github.com/hashicorp/consul/blob/main/CHANGELOG.md#080-april-5-2017) and [GH-3058](https://github.com/hashicorp/consul/issues/3058) +| Default port | Protocol | Default status | +| :----------- | :---------- | :----------------- | +| `8600` | TCP and UDP | Enabled by default | -**Server RPC** This is used by servers to handle incoming -requests from other agents. +This port receives incoming traffic from workloads to resolve Consul DNS requests. -Note, the default ports can be changed in the [agent configuration](/consul/docs/agent/config/config-files#ports). +The server's DNS port does not need to be open when DNS queries are sent to Consul clients. Consul does not use this port for internal communication between servers, clients, dataplanes, gateways, and Envoy proxies. + +If you configure recursors in Consul to upstream DNS servers, then you need outbound access to those servers on port `53`. + +To resolve Consul DNS requests when using HCP Consul Dedicated, we recommend running Consul clients and resolving DNS against the clients. If your use case cannot accommodate this recommendation, open a support ticket. + +### HTTP + +The following table lists information about the Consul server API's HTTP port defaults: + +| Default port | Protocol | Default status | +| :----------- | :------- | :----------------- | +| `8500` | TCP | Enabled by default | + +This port receives incoming traffic from workloads that make HTTP API calls. + +The server's HTTP port does not need to be open when Consul clients service all HTTP API calls. Consul does not use this port for internal communication between servers, clients, dataplanes, gateways, and Envoy proxies. + +The Consul CLI uses the HTTP port to interact with Consul by default. + +HCP Consul Dedicated does not support the HTTP port. + +### HTTPS + +The following table lists information about the Consul server API's HTTPS port defaults: + +| Default port | Protocol | Default status | HCP Consul Dedicated server port | +| :----------- | :------- | :------------------ | :---------------------------- | +| `8501` | TCP | Disabled by default | `443` | + +This port receives incoming traffic from workloads that make HTTPS API calls. + +The server HTTPS port does not need to be open when Consul clients service all HTTPS API calls. Consul does not use this port for internal communication between servers, clients, dataplanes, gateways, and Envoy proxies. + +This port is disabled by default. You can enable it in the [agent configuration file](/consul/docs/agent/config/config-files#ports) or using the [`consul agent` CLI command](/consul/docs/agent/config/cli-flags). + +HCP Consul Dedicated assigns port `443` to HCP Consul Dedicated clusters, instead of the default `8501`. + +### gRPC + +The following table lists information about the Consul API's gRPC port defaults: + +| Default port | Protocol | Default status | +| :----------- | :------- | :------------------ | +| `8502` | TCP | Disabled by default | + +When using [Consul Dataplane](/consul/docs/connect/dataplane), this port receives incoming traffic from the dataplanes. + +We recommend using gRPC TLS instead, so this port is disabled by default. You can enable it in the [agent configuration file](/consul/docs/agent/config/config-files#ports) or using the [`consul agent` CLI command](/consul/docs/agent/config/cli-flags). + +HCP Consul Dedicated does not support the gRPC port. + +### gRPC TLS + +The following table lists information about the Consul API's gRPC with TLS port defaults: + +| Default port | Protocol | Default status | HCP Consul Dedicated server port | +| :----------- | :------- | :------------------ | :---------------------------- | +| `8503` | TCP | Enabled by default | `8502` | + +This port receives incoming traffic from the dataplanes when using [Consul Dataplane](/consul/docs/connect/dataplane) instead of client agents. We recommend using `8503` as your conventional gRPC port number because it allows some tools to work automatically. + +In deployments with [cluster peering connections](/consul/docs/connect/cluster-peering), this port provides incoming and outgoing access between remote server peers. Specifically, the dialing peer needs outgoing access and the accepting peer needs incoming access. The address dialed depends on whether or not the cluster peering connection uses mesh gateways and whether the mesh gateway is in remote or local mode: + +- When not using mesh gateways, servers dial the remote server addresses directly. +- When using mesh gateways in local mode, servers dial the local mesh gateway. +- When using mesh gateways in remote mode, servers dial the remote mesh gateway. + +In both local and remote cases, incoming traffic comes from the mesh gateways. + +HCP Consul Dedicated assigns port `8502` to clusters, instead of the default `8503`. + +### Server RPC + +The following table lists information about the Server RPC port defaults: + +| Default port | Protocol | Default status | HCP Consul Dedicated server port | +| :----------- | :------- | :----------------- | :---------------------------- | +| `8300` | TCP | Enabled by default | `8300` | + +This port sends and receives traffic between Consul servers in the same datacenter. It also receives incoming traffic from Consul clients in the same datacenter. + +When using WAN federation without mesh gateways, incoming and outgoing traffic on this port is required between all federated servers. + +When using WAN federation with mesh gateways, Consul servers must accept server RPC requests from mesh gateways in the local datacenter. The mesh gateway mode determines the path that _outgoing_ traffic takes, either direct to `remote` gateways or first to `local` gateways, but _incoming_ traffic always comes through the local mesh gateways. + +### LAN serf + +The following table lists information about the LAN serf port defaults: + +| Default port | Protocol | Default status | HCP Consul Dedicated server port | +| :----------- | :-----------| :----------------- | :---------------------------- | +| `8301` | TCP and UDP | Enabled by default | `8301` | + +This port sends and receives traffic from Consul clients and other Consul servers in the same datacenter. Refer to [gossip protocol](/consul/docs/architecture/gossip) for more information. + +When running Enterprise deployments that use multiple admin partitions, all Consul clients across all partitions still require access to this port on all servers. Servers also require access to this port on all clients. + +### WAN serf + +The following table lists information about the WAN serf port defaults: + +| Default port | Protocol | Default status | HCP Consul Dedicated server port | +| :----------- | :---------- | :----------------- | :---------------------------- | +| `8302` | TCP and UDP | Enabled by default | `8302` | + +This port sends and receives traffic between Consul servers in a federated network. WAN-federated networks require one cluster to serve as the primary datacenter while the others function as secondary datacenters. Refer to [Enabling WAN Federation Control Plane Traffic](/consul/docs/connect/gateways/mesh-gateway/wan-federation-via-mesh-gateways) for additional information. + +When using WAN federation without mesh gateways, incoming and outgoing traffic on this port is required between all federated servers. + +When using WAN federation with mesh gateways, Consul servers must accept WAN Serf requests from mesh gateways in the local datacenter, regardless of which mesh gateway mode is used. As a result, traffic always comes from a local mesh gateway. + +## Consul clients + +The following table lists port names, their function, their network protocols, their default port numbers, whether they are enabled or disabled by default, and the direction of traffic from the Consul client's perspective. + +| Port name | Use | Protocol | Default port | Default status | Direction | +| :--------------------------- | :----------------------------------------- | :---------- | :----------- | :------------- | :-------------------- | +| [DNS](#client-dns) | The DNS server | TCP and UDP | `8600` | Enabled | Incoming | +| [HTTP](#client-http) | The HTTP API | TCP | `8500` | Enabled | Incoming | +| [HTTPS](#client-https) | The HTTPS API | TCP | `8501` | Disabled | Incoming | +| [gRPC](#client-grpc) | The gRPC API | TCP | `8502` | Disabled | Incoming | +| [gRPC TLS](#client-grpc-tls) | The gRPC API with TLS connections | TCP | `8503` | Disabled | Incoming | +| [LAN Serf](#client-lan-serf) | The Serf local area network port | TCP and UDP | `8301` | Enabled | Incoming and outgoing | + +### Client DNS + +The following table lists information about the client agent's DNS port defaults: + +| Default port | Protocol | Default status | +| :----------- | :---------- | :----------------- | +| `8600` | TCP and UDP | Enabled by default | + +This port receives incoming traffic from workloads to resolve Consul DNS requests. Consul does not use this port for internal communication between servers, clients, dataplanes, gateways, and Envoy proxies. + +If you configure recursors in Consul to upstream DNS servers, then you need outbound access to those servers on port `53`. + +### Client HTTP + +The following table lists information about the Consul client's HTTP port defaults: + +| Default port | Protocol | Default status | +| :----------- | :------- | :----------------- | +| `8500` | TCP | Enabled by default | + +This port receives incoming traffic from workloads that make HTTP API calls. Consul does not use this port for internal communication between servers, clients, dataplanes, gateways, and Envoy proxies. + +The Consul CLI uses the HTTP port to interact with Consul by default. + +### Client HTTPS + +The following table lists information about the Consul client's HTTPS port defaults: + +| Default port | Protocol | Default status | +| :----------- | :------- | :------------------ | +| `8501` | TCP | Disabled by default | + +This port receives incoming traffic from workloads that make HTTPS API calls. Consul does not use this port for internal communication between servers, clients, dataplanes, gateways, and Envoy proxies. + +This port is disabled by default. You can enable it in the [agent configuration file](/consul/docs/agent/config/config-files#ports) or using the [`consul agent` CLI command](/consul/docs/agent/config/cli-flags). + +When this port is enabled, the Consul CLI uses it to interact with Consul. + +### Client gRPC + +The following table lists information about the Consul client's gRPC port defaults: + +| Default port | Protocol | Default status | +| :----------- | :------- | :------------------ | +| `8502` | TCP | Disabled by default | + +This port receives incoming traffic from the gateways and Envoy proxies registered to this client. + +We recommend using gRPC TLS instead. + +### Client gRPC TLS + +The following table lists information about the Consul client's gRPC with TLS port defaults: + +| Default port | Protocol | Default status | +| :----------- | :------- | :------------------- | +| `8503` | TCP | Disabled by default | + +This port receives incoming traffic from the gateways and Envoy proxies registered to this client. We recommend using `8503` as your conventional gRPC port number, as it allows some tools to work automatically. + +This port is disabled by default. You can enable it in the [agent configuration file](/consul/docs/agent/config/config-files#ports) or using the [`consul agent` CLI command](/consul/docs/agent/config/cli-flags). + +### Client LAN serf + +The following table lists information about the Consul client's LAN serf port defaults: + +| Default port | Protocol | Default status | +| :----------- | :---------- | :----------------- | +| `8301` | TCP and UDP | Enabled by default | + +This port sends and receives traffic from Consul clients and Consul servers in the same datacenter. Refer to [gossip protocol](/consul/docs/architecture/gossip) for more information. + +When running Enterprise deployments that use network segments or admin partitions, Consul clients _within_ a segment or partition require access to each other's ports. Clients do not require port access _across_ segments or partitions. diff --git a/website/content/docs/integrate/partnerships.mdx b/website/content/docs/integrate/partnerships.mdx index 024ceeaefc77..024a5b5413d7 100644 --- a/website/content/docs/integrate/partnerships.mdx +++ b/website/content/docs/integrate/partnerships.mdx @@ -17,7 +17,7 @@ The program is intended to be largely self-service with links to resources, code ## Categories of Consul Integrations -By leveraging Consul's RESTful HTTP API system, prospective partners are able to build extensible integrations at the data plane, platform, and the infrastructure layer to extend Consul's functionalities. These integrations can be performed both with the community edition of Consul, Consul Enterprise, and HCP Consul. +By leveraging Consul's RESTful HTTP API system, prospective partners are able to build extensible integrations at the data plane, platform, and the infrastructure layer to extend Consul's functionalities. These integrations can be performed both with the community edition of Consul, Consul Enterprise, and HCP Consul Dedicated. **The Consul ecosystem of integrations:** @@ -37,9 +37,9 @@ By leveraging Consul's RESTful HTTP API system, prospective partners are able to -> **Network Infrastructure Automation (NIA)***: These integrations leverage Consul's service catalog to seamlessly integrate with Consul-Terraform-Sync (CTS) to automate changes in network infrastructure via a publisher-subscriber method. Refer to the [NIA documentation](/consul/docs/integrate/nia-integration) for details. -**HCP Consul**: HCP Consul is secure by default and offers an out-of-the-box service mesh solution to streamline operations without the hassle of managing Consul servers. [Sign up for a free HCP Consul account](https://cloud.hashicorp.com/products/consul). +**HCP Consul Dedicated**: HCP Consul Dedicated is secure by default and offers an out-of-the-box service mesh solution to streamline operations without the hassle of managing Consul servers. [Sign up for a free HCP Consul Dedicated account](https://cloud.hashicorp.com/products/consul). -**Consul integration verification badges**: Partners will be issued the Consul Enterprise badge for integrations that work with [Consul Enterprise features](/consul/docs/enterprise) such as namespaces. Partners will be issued the HCP Consul badge for integrations validated to work with [HCP Consul](/hcp/docs/consul#features). Each badge would be displayed on HashiCorp's partner page as well as be available for posting on the partner's own website to provide better visibility and differentiation of the integration for joint customers. +**Consul integration verification badges**: Partners will be issued the Consul Enterprise badge for integrations that work with [Consul Enterprise features](/consul/docs/enterprise) such as namespaces. Partners will be issued the HCP Consul Dedicated badge for integrations validated to work with [HCP Consul Dedicated](/hcp/docs/consul#features). Each badge would be displayed on HashiCorp's partner page as well as be available for posting on the partner's own website to provide better visibility and differentiation of the integration for joint customers. @@ -49,12 +49,12 @@ By leveraging Consul's RESTful HTTP API system, prospective partners are able to -![HCP Consul](/img/HCPc_badge.png) +![HCP Consul Dedicated](/img/HCPc_badge.png) -Developing a valid integration with either Consul Enterprise or HCP Consul also qualifies the partner for the Premier tier of the HashiCorp Technology Partners program. The process for verification of these integrations is detailed below. +Developing a valid integration with either Consul Enterprise or HCP Consul Dedicated also qualifies the partner for the Premier tier of the HashiCorp Technology Partners program. The process for verification of these integrations is detailed below. ## Development Process @@ -87,7 +87,7 @@ Here are links to resources, documentation, examples and best practices to guide - [Consul Telemetry Documentation](/consul/docs/agent/telemetry) - [Monitoring Consul with Datadog APM](https://www.datadoghq.com/blog/consul-datadog/) -- [Monitor HCP Consul with New Relic Instant Observability](https://github.com/newrelic-experimental/hashicorp-quickstart-annex/blob/main/hcp-consul/README.md) +- [Monitor HCP Consul Dedicated with New Relic Instant Observability](https://github.com/newrelic-experimental/hashicorp-quickstart-annex/blob/main/hcp-consul/README.md) - [HCP Consul and CloudFabrix AIOps Integration](https://bot-docs.cloudfabrix.io/Bots/consul/?h=consul) - [Consul and SnappyFlow Full Stack Observability](https://docs.snappyflow.io/docs/Integrations/hcp_consul) @@ -167,17 +167,17 @@ Here are links to resources, documentation, examples and best practices to guide The only knowledge necessary to write a plugin is basic command-line skills and knowledge of the [Go programming language](http://www.golang.org). Use the plugin interface to develop your integration. All integrations should contain unit and acceptance testing. -**HCP Consul**: As a managed service, minimal configuration is required to deploy HCP Consul server clusters. You only need to install Consul client agents. Furthermore, HashiCorp provides all new users an initial credit, which provides approximately two months worth of [development cluster](https://cloud.hashicorp.com/products/consul/pricing) access. When deployed with AWS or Azure free tier services, there should be no cost beyond the time spent by the designated tester. Refer to the [Deploy HCP Consul tutorial](/consul/tutorials/get-started-hcp/hcp-gs-deploy) for details on getting started. +**HCP Consul Dedicated**: As a managed service, minimal configuration is required to deploy HCP Consul Dedicated server clusters. You only need to install Consul client agents. Furthermore, HashiCorp provides all new users an initial credit, which provides approximately two months worth of [development cluster](https://cloud.hashicorp.com/products/consul/pricing) access. When deployed with AWS or Azure free tier services, there should be no cost beyond the time spent by the designated tester. Refer to the [Deploy HCP Consul Dedicated tutorial](/consul/tutorials/get-started-hcp/hcp-gs-deploy) for details on getting started. -HCP Consul is currently only deployed on AWS and Microsoft Azure, so your application can be deployed to or run in AWS or Azure. +HCP Consul Dedicated is currently only deployed on AWS and Microsoft Azure, so your application can be deployed to or run in AWS or Azure. -#### HCP Consul Resource Links: +#### HCP Consul Dedicated Resource Links: -- [Getting Started with HCP Consul](/consul/tutorials/get-started-hcp/hcp-gs-deploy) -- [HCP Consul End-to-End Deployment](/consul/tutorials/cloud-deploy-automation/consul-end-to-end-overview) -- [Deploy HCP Consul with EKS using Terraform](/consul/tutorials/cloud-deploy-automation/consul-end-to-end-eks) -- [HCP Consul Deployment Automation](/consul/tutorials/cloud-deploy-automation) -- [HCP Consul documentation](/hcp/docs/consul/usage) +- [Getting Started with HCP Consul Dedicated](/consul/tutorials/get-started-hcp/hcp-gs-deploy) +- [HCP Consul Dedicated End-to-End Deployment](/consul/tutorials/cloud-deploy-automation/consul-end-to-end-overview) +- [Deploy HCP Consul Dedicated with EKS using Terraform](/consul/tutorials/cloud-deploy-automation/consul-end-to-end-eks) +- [HCP Consul Dedicated Deployment Automation](/consul/tutorials/cloud-deploy-automation) +- [HCP Consul Dedicated documentation](/hcp/docs/consul/usage) **Consul Enterprise**: An integration qualifies for Consul Enterprise when it is tested and compatible with Consul Enterprise Namespaces. diff --git a/website/content/docs/intro/index.mdx b/website/content/docs/intro/index.mdx index 42655814cecb..1708f3d84b5d 100644 --- a/website/content/docs/intro/index.mdx +++ b/website/content/docs/intro/index.mdx @@ -7,7 +7,7 @@ description: >- # What is Consul? -HashiCorp Consul is a service networking solution that enables teams to manage secure network connectivity between services and across on-prem and multi-cloud environments and runtimes. Consul offers service discovery, service mesh, traffic management, and automated updates to network infrastructure device. You can use these features individually or together in a single Consul deployment. +HashiCorp Consul is a service networking solution that enables teams to manage secure network connectivity between services and across on-prem and multi-cloud environments and runtimes. Consul offers service discovery, service mesh, traffic management, and automated updates to network infrastructure devices. You can use these features individually or together in a single Consul deployment. > **Hands-on**: Complete the Getting Started tutorials to learn how to deploy Consul: - [Get Started on Kubernetes](/consul/tutorials/get-started-kubernetes) @@ -55,7 +55,7 @@ You can also schedule Consul workloads with [HashiCorp Nomad](https://www.nomadp ### Enable zero-trust network security -Microservice architectures are complex and difficult to secure against accidental discloser to malicious actors. Consul provides several mechanisms that enhance network security without any changes to your application code, including mutual transport layer security (mTLS) encryption on all traffic between services and Consul intentions, which are service-to-service permissions that you can manage through the Consul UI, API, and CLI. +Microservice architectures are complex and difficult to secure against accidental disclosure to malicious actors. Consul provides several mechanisms that enhance network security without any changes to your application code, including mutual transport layer security (mTLS) encryption on all traffic between services and Consul intentions, which are service-to-service permissions that you can manage through the Consul UI, API, and CLI. When you deploy Consul to Kubernetes clusters, you can also integrate with [HashiCorp Vault](https://www.vaultproject.io/) to manage sensitive data. By default, Consul on Kubernetes leverages Kubernetes secrets as the backend system. Kubernetes secrets are base64 encoded, unencrypted, and lack lease or time-to-live properties. By leveraging Vault as a secrets backend for Consul on Kubernetes, you can manage and store Consul related secrets within a centralized Vault cluster to use across one or many Consul on Kubernetes datacenters. Refer to [Vault as the Secrets Backend](/consul/docs/k8s/deployment-configurations/vault) for additional information. @@ -77,7 +77,7 @@ Rolling out changes can be risky, especially in complex network environments. Up HashiCorp offers core Consul functionality for free in the community edition, which is ideal for smaller businesses and teams that want to pilot Consul within their organizations. As your business grows, you can upgrade to Consul Enterprise, which offers additional capabilities designed to address organizational complexities of collaboration, operations, scale, and governance. -### HCP Consul +### HCP Consul Dedicated HashiCorp Cloud Platform (HCP) Consul is our SaaS that delivers Consul Enterprise capabilities and shifts the burden of managing the control plane to us. Create an HCP organization and leverage our expertise to simplify control plane maintenance and configuration. Learn more at [HashiCorp Cloud Platform](https://cloud.hashicorp.com/products/consul). diff --git a/website/content/docs/k8s/annotations-and-labels.mdx b/website/content/docs/k8s/annotations-and-labels.mdx index 4e4177bc7206..56e4c4c0fcd5 100644 --- a/website/content/docs/k8s/annotations-and-labels.mdx +++ b/website/content/docs/k8s/annotations-and-labels.mdx @@ -246,6 +246,9 @@ The following Kubernetes resource annotations could be used on a pod to control - `consul.hashicorp.com/sidecar-proxy-lifecycle-graceful-port` - Override the default Helm value [`connectInject.sidecarProxy.lifecycle.defaultGracefulPort`](/consul/docs/k8s/helm#v-connectinject-sidecarproxy-lifecycle-defaultgracefulport) - `consul.hashicorp.com/sidecar-proxy-lifecycle-graceful-shutdown-path` - Override the default Helm value [`connectInject.sidecarProxy.lifecycle.defaultGracefulShutdownPath`](/consul/docs/k8s/helm#v-connectinject-sidecarproxy-lifecycle-defaultgracefulshutdownpath) +- `consul.hashicorp.com/sidecar-proxy-startup-failure-seconds` - Override the default Helm value [`connectInject.sidecarProxy.defaultStartupFailureSeconds`](/consul/docs/k8s/helm#v-connectinject-sidecarproxy-defaultstartupfailureseconds) +- `consul.hashicorp.com/sidecar-proxy-liveness-failure-seconds` - Override the default Helm value [`connectInject.sidecarProxy.defaultLivenessFailureSeconds`](/consul/docs/k8s/helm#v-connectinject-sidecarproxy-defaultlivenessfailureseconds) + - `consul.hashicorp.com/enable-metrics` - Override the default Helm value [`connectInject.metrics.defaultEnabled`](/consul/docs/k8s/helm#v-connectinject-metrics-defaultenabled). - `consul.hashicorp.com/enable-metrics-merging` - Override the default Helm value [`connectInject.metrics.defaultEnableMerging`](/consul/docs/k8s/helm#v-connectinject-metrics-defaultenablemerging). - `consul.hashicorp.com/merged-metrics-port` - Override the default Helm value [`connectInject.metrics.defaultMergedMetricsPort`](/consul/docs/k8s/helm#v-connectinject-metrics-defaultmergedmetricsport). @@ -276,6 +279,11 @@ The following Kubernetes resource annotations could be used on a pod to control annotations: "consul.hashicorp.com/consul-sidecar-user-volume-mount": "[{\"name\": \"secrets-store-mount\", \"mountPath\": \"/mnt/secrets-store\"}]" ``` +- `consul.hashicorp.com/proxy-config-map` - JSON object specifying [Proxy Config Options](/consul/docs/connect/proxies/envoy#proxy-config-options). The proxy config map provides a low-level interface for setting configuration fields on a per-proxy basis during service registration. This configuration field is intended to be used in situations where a field does not exist in [service defaults configuration entries](/consul/docs/connect/config-entries/service-defaults) and another annotation does not provide explicit access to one of the Envoy configuration options. + ```yaml + annotations: + "consul.hashicorp.com/proxy-config-map": "{ \"xds_fetch_timeout_ms\": 30000 }" + ``` ### Labels diff --git a/website/content/docs/k8s/compatibility.mdx b/website/content/docs/k8s/compatibility.mdx index a2c17ae09b65..a786ed513ad1 100644 --- a/website/content/docs/k8s/compatibility.mdx +++ b/website/content/docs/k8s/compatibility.mdx @@ -11,13 +11,40 @@ For every release of Consul on Kubernetes, a Helm chart, `consul-k8s-control-pla ## Supported Consul and Kubernetes versions -Consul Kubernetes versions all of its components (`consul-k8s` CLI, `consul-k8s-control-plane`, and Helm chart) with a single semantic version. When installing or upgrading to a specific versions, ensure that you are using the correct Consul version with the compatible Helm chart or `consul-k8s` CLI. +Consul Kubernetes versions all of its components (`consul-k8s` CLI, `consul-k8s-control-plane`, and Helm chart) with a single semantic version. When installing or upgrading to a specific version, ensure that you are using the correct Consul version with the compatible Helm chart or `consul-k8s` CLI. -| Consul version | Compatible `consul-k8s` versions | Compatible Kubernetes versions | Compatible OpenShift versions | -| -------------- | -------------------------------- | -------------------------------| -------------------------------------- | -| 1.17.x | 1.3.x | 1.25.x - 1.28.x | 4.12.x - 4.14.x (4.15.x not available) | -| 1.16.x | 1.2.x | 1.24.x - 1.27.x | 4.11.x - 4.14.x | -| 1.15.x | 1.1.x | 1.23.x - 1.26.x | 4.10.x - 4.13.x | +### Compatibility matrix + +The following sections describe the compatibility matrix for +Consul Kubernetes components and dependencies. +Some releases of Consul Enterprise receive +[Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) +and have an [extended compatibility window](#enterprise-long-term-support-releases) +compared to non-LTS Enterprise and community edition releases. + +#### Standard releases + +Unless otherwise noted, rows in the following compatibility table +apply to both Consul Enterprise and Consul community edition (CE). + +| Consul version | Compatible `consul-k8s` versions | Compatible Kubernetes versions | Compatible OpenShift versions | +| -------------- | -------------------------------- | -------------------------------| ------------------------------| +| 1.20.x | 1.6.x | 1.28.x - 1.30.x | 4.13.x - 4.15.x | +| 1.19.x | 1.5.x | 1.27.x - 1.29.x | 4.13.x - 4.15.x | +| 1.18.x CE | 1.4.x | 1.26.x - 1.29.x | 4.13.x - 4.15.x | +| 1.17.x | 1.3.x | 1.25.x - 1.28.x | 4.12.x - 4.15.x | + +#### Enterprise Long Term Support releases + +Active Consul Enterprise +[Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) +releases expand their Kubernetes version compatibility window +until the LTS release reaches its end of maintenance. + +| Consul version | Compatible `consul-k8s` versions | Compatible Kubernetes versions | Compatible OpenShift versions | +| -------------- | -------------------------------- | -------------------------------| ------------------------------| +| 1.18.x Ent | 1.4.x | 1.26.x - 1.29.x | 4.13.x - 4.15.x | +| 1.15.x Ent | 1.1.x | 1.23.x - 1.28.x | 4.10.x - 4.15.x | ### Version-specific upgrade requirements @@ -41,7 +68,7 @@ Starting with Consul K8s 0.39.0 and Consul 1.11.x, Consul Kubernetes supports th ### Red Hat OpenShift -You can enable support for Red Hat OpenShift by setting `enabled: true` in the `global.openshift` stanza. Refer to the [Deploy Consul on RedHat OpenShift tutorial](https://developer.hashicorp.com/consul/tutorials/kubernetes/kubernetes-openshift-red-hat) for instructions on deploying to OpenShift. +You can enable support for Red Hat OpenShift by setting `enabled: true` in the `global.openshift` stanza. Refer to the [Deploy Consul on RedHat OpenShift tutorial](https://developer.hashicorp.com/consul/tutorials/kubernetes/kubernetes-openshift-red-hat) for instructions on deploying to OpenShift. ### VMware Tanzu Kubernetes Grid and Tanzu Kubernetes Grid Integrated Edition diff --git a/website/content/docs/k8s/connect/cluster-peering/tech-specs.mdx b/website/content/docs/k8s/connect/cluster-peering/tech-specs.mdx index 2d27a4f369fc..f6c0ae031633 100644 --- a/website/content/docs/k8s/connect/cluster-peering/tech-specs.mdx +++ b/website/content/docs/k8s/connect/cluster-peering/tech-specs.mdx @@ -158,12 +158,4 @@ To learn how to change the mesh gateway mode to `local` on your Kubernetes deplo The `exported-services` CRD is required in order for services to communicate across partitions with cluster peering connections. Basic guidance on using the `exported-services` configuration entry is included in [Establish cluster peering connections](/consul/docs/k8s/connect/cluster-peering/usage/establish-peering#export-services-between-clusters). -Refer to [`exported-services` configuration entry](/consul/docs/connect/config-entries/exported-services) for more information. - -## ACL specifications - -If ACLs are enabled, you must add tokens to grant the following permissions: - -- Grant `service:write` permissions to services that define mesh gateways in their server definition. -- Grant `service:read` permissions for all services on the partition. -- Grant `mesh:write` permissions to the mesh gateways that participate in cluster peering connections. This permission allows a leaf certificate to be issued for mesh gateways to terminate TLS sessions for HTTP requests. +Refer to [`exported-services` configuration entry](/consul/docs/connect/config-entries/exported-services) for more information. \ No newline at end of file diff --git a/website/content/docs/k8s/connect/cluster-peering/usage/create-sameness-groups.mdx b/website/content/docs/k8s/connect/cluster-peering/usage/create-sameness-groups.mdx index c81c3c2b11e6..0b3f1d43c29c 100644 --- a/website/content/docs/k8s/connect/cluster-peering/usage/create-sameness-groups.mdx +++ b/website/content/docs/k8s/connect/cluster-peering/usage/create-sameness-groups.mdx @@ -115,7 +115,7 @@ spec: members: - partition: partition-1 - peer: dc1-partition-1 - - peer: dc2-partition-2 + - peer: dc1-partition-2 ``` @@ -146,7 +146,7 @@ The following example demonstrates how to format three different `ExportedServic apiVersion: consul.hashicorp.com/v1alpha1 Kind: ExportedServices metadata: - name: product-group-export + name: partition-1 spec: services: - name: api @@ -163,7 +163,7 @@ spec: apiVersion: consul.hashicorp.com/v1alpha1 Kind: ExportedServices metadata: - name: product-group-export + name: partition-2 spec: services: - name: api @@ -180,7 +180,7 @@ spec: apiVersion: consul.hashicorp.com/v1alpha1 Kind: ExportedServices metadata: - name: product-group-export + name: partition-1 spec: services: - name: api @@ -291,4 +291,4 @@ If your goal for peering clusters is to create a sameness group, you can write a When `defaultForFailover=true` in a sameness group CRD, additional upstream configuration is not required. -After creating a sameness group, you can also set up failover between services in a sameness group. Refer to [Failover with sameness groups](/consul/docs/connect/manage-traffic/failover/sameness) for more information. \ No newline at end of file +After creating a sameness group, you can also set up failover between services in a sameness group. Refer to [Failover with sameness groups](/consul/docs/connect/manage-traffic/failover/sameness) for more information. diff --git a/website/content/docs/k8s/connect/cluster-peering/usage/establish-peering.mdx b/website/content/docs/k8s/connect/cluster-peering/usage/establish-peering.mdx index c784b5704713..bc82be872a1c 100644 --- a/website/content/docs/k8s/connect/cluster-peering/usage/establish-peering.mdx +++ b/website/content/docs/k8s/connect/cluster-peering/usage/establish-peering.mdx @@ -439,19 +439,4 @@ Before you can call services from peered clusters, you must set service intentio } ``` - - -### Authorize service reads with ACLs - -If ACLs are enabled on a Consul cluster, sidecar proxies that access exported services as an upstream must have an ACL token that grants read access. - -Read access to all imported services is granted using either of the following rules associated with an ACL token: - -- `service:write` permissions for any service in the sidecar's partition. -- `service:read` and `node:read` for all services and nodes, respectively, in sidecar's namespace and partition. - -For Consul Enterprise, the permissions apply to all imported services in the service's partition. These permissions are satisfied when using a [service identity](/consul/docs/security/acl/acl-roles#service-identities). - -Refer to [Reading servers](/consul/docs/connect/config-entries/exported-services#reading-services) in the `exported-services` configuration entry documentation for example rules. - -For additional information about how to configure and use ACLs, refer to [ACLs system overview](/consul/docs/security/acl). + \ No newline at end of file diff --git a/website/content/docs/k8s/connect/index.mdx b/website/content/docs/k8s/connect/index.mdx index a5ba50fcbb8e..0f320d343789 100644 --- a/website/content/docs/k8s/connect/index.mdx +++ b/website/content/docs/k8s/connect/index.mdx @@ -343,7 +343,7 @@ spec: `9090` and will also select the same pods. ~> Kubernetes 1.24+ only -In Kubernetes 1.24+ you need to [create a Kubernetes secret](https://kubernetes.io/docs/concepts/configuration/secret/#service-account-token-secrets) for each multi-port service that references the ServiceAccount, and the Kubernetes secret must have the same name as the ServiceAccount: +In Kubernetes 1.24+ you need to [create a Kubernetes secret](https://kubernetes.io/docs/concepts/configuration/secret/#service-account-token-secrets) for each additional Consul service associated with the pod in order to expose the Kubernetes ServiceAccount token to the Consul dataplane container running under the pod serviceAccount. The Kubernetes secret name must match the ServiceAccount name: @@ -354,7 +354,7 @@ metadata: name: web annotations: kubernetes.io/service-account.name: web - type: kubernetes.io/service-account-token +type: kubernetes.io/service-account-token --- apiVersion: v1 kind: Secret @@ -362,7 +362,7 @@ metadata: name: web-admin annotations: kubernetes.io/service-account.name: web-admin - type: kubernetes.io/service-account-token +type: kubernetes.io/service-account-token ``` @@ -698,7 +698,7 @@ annotations: 'consul.hashicorp.com/connect-service-upstreams': '[service-name].[namespace]:[port]:[optional datacenter]' ``` -See [consul.hashicorp.com/connect-service-upstreams](#consul-hashicorp-com-connect-service-upstreams) for more details. +See [consul.hashicorp.com/connect-service-upstreams](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-connect-service-upstreams) for more details. -> **Note:** When you specify upstreams via an upstreams annotation, you will need to use `localhost:` with the port from the upstreams annotation instead of KubeDNS to connect to your upstream diff --git a/website/content/docs/k8s/connect/onboarding-tproxy-mode.mdx b/website/content/docs/k8s/connect/onboarding-tproxy-mode.mdx index 8dd0ebb17c70..2cb7adfc9225 100644 --- a/website/content/docs/k8s/connect/onboarding-tproxy-mode.mdx +++ b/website/content/docs/k8s/connect/onboarding-tproxy-mode.mdx @@ -1,7 +1,7 @@ --- layout: docs page_title: Onboard services in transparent proxy mode -description: Learn how to enable permissive mutual transport layer security (permissive mTLS) so that you can safely add services to your service mesh when transparent proxy is enabled in Kubernetes deployments. +description: Learn how to enable permissive mutual transport layer security (permissive mTLS) so that you can safely add services to your service mesh when transparent proxy is enabled in Kubernetes deployments. --- # Onboard services while in transparent proxy mode @@ -14,7 +14,7 @@ When [transparent proxy mode](/consul/docs/k8s/connect/transparent-proxy) is ena You can enable the `permissive` mTLS mode to ensure existing non-mTLS service-to-service traffic is allowed during the onboarding phase. The `permissive` mTLS mode enables sidecar proxies to accept both mTLS and non-mTLS traffic to an application. Using this mode enables you to onboard without downtime and without being required to reconfigure or redeploy your application. -We recommend enabling permissive mTLS as a temporary operating mode. After onboarding is complete, you should reconfigure all services to `strict` mTLS mode to ensure all service-to-service communication is automatically secured by Consul service mesh. +We recommend enabling permissive mTLS as a temporary operating mode. After onboarding is complete, you should reconfigure all services to `strict` mTLS mode to ensure all service-to-service communication is automatically secured by Consul service mesh. !> **Security warning**: We recommend that you disable permissive mTLS mode after onboarding services to prevent non-mTLS connections to the service. Intentions are not enforced and encryption is not enabled for non-mTLS connections. @@ -24,14 +24,18 @@ The workflow to configure mTLS settings depends on the applications you are onbo 1. **Configure global settings**: Configure the mesh to allow services to send non-mTLS messages to services outside the mesh. Additionally, configure the mesh to let services in the mesh use permissive mTLS mode. 1. **Enable permissive mTLS mode**: If you are onboarding an upstream service prior to its related downstream services, then enable permissive mTLS mode in the service defaults configuration entry. This allows the upstream service to send encrypted messages from the mesh when you register the service with Consul. -1. **Configure intentions**: Intentions are controls that authorize traffic between services in the mesh. Transparent proxy uses intentions to infer traffic routes between Envoy proxies. Consul does not enforce intentions for non-mTLS connections made while proxies are in permissive mTLS mode, but intentions are necessary for completing the onboarding process. -1. **Register the service**: Create the service definition and configure and deploy its sidecar proxy. +1. **Configure intentions**: Intentions are controls that authorize traffic between services in the mesh. Transparent proxy uses intentions to infer traffic routes between Envoy proxies. Consul does not enforce intentions for non-mTLS connections made while proxies are in permissive mTLS mode, but intentions are necessary for completing the onboarding process. +1. **Register the service**: Create the service definition and configure and deploy its sidecar proxy. 1. **Re-secure the mesh**: If you enabled permissive mTLS mode, switch back to strict mTLS mode and revert the global settings to disable non-mTLS traffic in the service mesh. ## Requirements Permissive mTLS is only supported for services running in transparent proxy mode. Transparent proxy mode is only available on Kubernetes deployments. +## Limitations + +L7 Envoy features such as Intentions and some [Envoy extensions](/consul/docs/connect/proxies/envoy-extensions) are not supported for non-mTLS traffic. + ## Configure global settings Configure Consul to allow services that are already in the mesh to send non-mTLS messages to services outside the mesh. You can also Consul to allow services to run in permissive mTLS mode. Set both configurations in the mesh gateway configuration entry, which is the global configuration that defines service mesh proxy behavior. @@ -118,11 +122,11 @@ spec: -You can change this setting back to `false` at any time, even if there are services currently running in permissive mode. Doing so allows you to decide at which point during the onboarding process to stop allowing services to use permissive mTLS. When the `MeshDestinationOnly` is set to `false`, you must configure all new services added to the mesh with `MutualTLSMode=strict` for the Consul to securely route traffic throughout the mesh. +You can change this setting back to `false` at any time, even if there are services currently running in permissive mode. Doing so allows you to decide at which point during the onboarding process to stop allowing services to use permissive mTLS. When the `MeshDestinationOnly` is set to `false`, you must configure all new services added to the mesh with `MutualTLSMode=strict` for the Consul to securely route traffic throughout the mesh. -## Enable permissive mTLS mode +## Enable permissive mTLS mode -Depending on the services you are onboarding, you may not need to enable permissive mTLS mode. If the service does not accept incoming traffic or accepts traffic from downstream services that are already part of the service mesh, then permissive mTLS mode is not required to continue. +Depending on the services you are onboarding, you may not need to enable permissive mTLS mode. If the service does not accept incoming traffic or accepts traffic from downstream services that are already part of the service mesh, then permissive mTLS mode is not required to continue. To enable permissive mTLS mode for the service, set [`MutualTLSMode=permissive`](/consul/docs/connect/config-entries/service-defaults#mutualtlsmode) in the service defaults configuration entry for the service. The following example shows how to configure this setting for a service named `example-service`. @@ -160,7 +164,7 @@ You can change this setting back to `strict` at any time to ensure mTLS is requi ## Configure intentions -Service intentions are mechanisms in Consul that control traffic between services in the mesh. +Service intentions are mechanisms in Consul that control traffic between services in the mesh. We recommend creating intentions that restrict services to accepting only necessary traffic. You must identify the downstream services that send messages to the service you want to add to the mesh and then create an intention to allow traffic to the service from its downstreams. @@ -174,13 +178,13 @@ Register your service into the catalog and update your application to deploy a s ## Re-secure mesh traffic -If the newly added service was placed in permissive mTLS mode for onboarding, then you should switch to strict mode when it is safe to do so. You should also revert the global settings that allow services to send and receive non-mTLS traffic. +If the newly added service was placed in permissive mTLS mode for onboarding, then you should switch to strict mode when it is safe to do so. You should also revert the global settings that allow services to send and receive non-mTLS traffic. ### Disable permissive mTLS mode Configure the service to operate in strict mTLS mode after the service is no longer receiving incoming non-mTLS traffic. After the downstream services that send messages to this service are all onboarded to the mesh, this service should no longer receive non-mTLS traffic. -Check the following Envoy listener statistics for the sidecar proxy to determine if the sidecar is receiving non-mTLS traffic: +Check the following Envoy listener statistics for the sidecar proxy to determine if the sidecar is receiving non-mTLS traffic: - The `tcp.permissive_public_listener.*` statistics indicate non-mTLS traffic. If these metrics are static over a sufficient period of time, that indicates the sidecar is not receiving non-mTLS traffic. - The `tcp.public_listener.*` statistics indicate mTLS traffic. If incoming traffic is expected to this service and these statistics are changing, then the sidecar is receiving mTLS traffic. @@ -193,7 +197,7 @@ If your service is still receiving non-mTLS traffic, complete the following step 1. Verify that each downstream is onboarded to the service mesh. If a downstream is not onboarded, consider onboarding it next. 1. Verify that each downstream has an intention that allows it to send traffic to the upstream service. -After you determine it is safe to move the service to strict mode, set `MutualTLSMode=strict` in the service defaults configuration entry. +After you determine it is safe to move the service to strict mode, set `MutualTLSMode=strict` in the service defaults configuration entry. @@ -225,7 +229,7 @@ spec: ### Disable non-mTLS traffic -After all services are onboarded, revert the global settings that allow non-mTLS traffic and verify that permissive mTLS mode is not being used in the mesh. +After all services are onboarded, revert the global settings that allow non-mTLS traffic and verify that permissive mTLS mode is not being used in the mesh. Set `AllowEnablingPermissiveMutualTLS=false` and `MeshDestinationsOnly=true` in the mesh config entry. @@ -266,7 +270,7 @@ spec: -For each namespace, admin partition, and datacenter in your Consul deployment, run the `consul config list` and `consul config read` commands to verify that no services are using `permissive` mTLS mode. +For each namespace, admin partition, and datacenter in your Consul deployment, run the `consul config list` and `consul config read` commands to verify that no services are using `permissive` mTLS mode. The following command returns any service defaults configuration entries that contain `'MutualTLSMode = "permissive"'`: @@ -275,7 +279,7 @@ $ consul config list -kind service-defaults -filter 'MutualTLSMode == "permissiv ``` In each admin partition and datacenter, verify that `MutualTLSMode = "permissive"` is not set in the proxy defaults configuration entry . If `MutualTLSMode` is either empty or if the configuration entry is not found, then the mode is `strict` by default. - + The following command fetches the proxy defaults configuration entry: ```shell-session diff --git a/website/content/docs/k8s/connect/terminating-gateways.mdx b/website/content/docs/k8s/connect/terminating-gateways.mdx index 319fedf71dd3..4cac88da67b1 100644 --- a/website/content/docs/k8s/connect/terminating-gateways.mdx +++ b/website/content/docs/k8s/connect/terminating-gateways.mdx @@ -84,6 +84,12 @@ $ export CONSUL_HTTP_TOKEN=$(kubectl get secret consul-bootstrap-acl-token --tem ## Register external services with Consul + + +Consul on Kubernetes now supports the `Registration` CRD to register services running on external nodes with a terminating gateway. We recommend registering services with this CRD. For more information, refer to [Register services running on external nodes to Consul on Kubernetes](/consul/docs/k8s/deployment-configurations/external-service). + + + Registering the external services with Consul is a multi-step process: - Register external services with Consul @@ -96,7 +102,7 @@ Registering the external services with Consul is a multi-step process: You may register an external service with Consul using `ServiceDefaults` if [`TransparentProxy`](/consul/docs/connect/transparent-proxy) is enabled. Otherwise, -you may register the service as a node in the Consul catalog. +you may register the service as a node in the Consul catalog using the [`Registration` CRD](/consul/docs/connect/config-entries/registration). @@ -317,6 +323,57 @@ $ kubectl apply --filename service-intentions.yaml As a final step, you may define and deploy the external services as upstreams for the internal mesh services that wish to talk to them. An example deployment is provided which will serve as a static client for the terminating gateway service. + + + + + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: static-client +spec: + selector: + app: static-client + ports: + - port: 80 +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: static-client +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: static-client +spec: + replicas: 1 + selector: + matchLabels: + app: static-client + template: + metadata: + name: static-client + labels: + app: static-client + annotations: + 'consul.hashicorp.com/connect-inject': 'true' + spec: + containers: + - name: static-client + image: curlimages/curl:latest + command: ['/bin/sh', '-c', '--'] + args: ['while true; do sleep 30; done;'] + serviceAccountName: static-client +``` + + + + + + ```yaml @@ -363,6 +420,9 @@ spec: + + + Deploy the service with `kubectl apply`. ```shell-session diff --git a/website/content/docs/k8s/connect/transparent-proxy/enable-transparent-proxy.mdx b/website/content/docs/k8s/connect/transparent-proxy/enable-transparent-proxy.mdx index b2cc5dac0b46..ce3df409eb95 100644 --- a/website/content/docs/k8s/connect/transparent-proxy/enable-transparent-proxy.mdx +++ b/website/content/docs/k8s/connect/transparent-proxy/enable-transparent-proxy.mdx @@ -16,7 +16,7 @@ Your network must meet the following environment and software requirements to us * Transparent proxy is available for Kubernetes environments. * Consul 1.10.0+ * Consul Helm chart 0.32.0+. If you want to use the Consul CNI plugin to redirect traffic, Helm chart 0.48.0+ is required. Refer to [Enable the Consul CNI plugin](#enable-the-consul-cni-plugin) for additional information. -* You must create [service intentions](/consul/docs/connect/intentions) that explicitly allow communication between intended services so that Consul can infer upstream connections and use sidecar proxies to route messages appropriately. +* You must create [service intentions](/consul/docs/connect/intentions) that explicitly allow communication between services. Consul uses service intentions to infer upstream connections and route messages appropriately between sidecar proxies. * The `ip_tables` kernel module must be running on all worker nodes within a Kubernetes cluster. If you are using the `modprobe` Linux utility, for example, issue the following command: `$ modprobe ip_tables` @@ -25,7 +25,7 @@ Your network must meet the following environment and software requirements to us ## Enable transparent proxy -Transparent proxy mode is enabled for the entire cluster by default when you install Consul on Kubernetes using the Consul Helm chart. Refer to the [Consul Helm chart reference](/consul/docs/k8s/helm) for information about all default configurations. +Transparent proxy mode is enabled for the entire cluster by default when you install Consul on Kubernetes using the Consul Helm chart. Refer to the [Consul Helm chart reference](/consul/docs/k8s/helm) for information about all default configurations. You can explicitly enable transparent proxy for the entire cluster, individual namespaces, and individual services. @@ -242,7 +242,7 @@ spec: Additional services can query the [KubeDNS](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) at `sample-app.default.svc.cluster.local` to reach `sample-app`. If ACLs are enabled and configured with default `deny` policies, the configuration also requires a [`ServiceIntention`](/consul/docs/connect/config-entries/service-intentions) to allow it to talk to `sample-app`. -You can query the KubeDNS for a service that belongs to a sameness group at `sample-app.virtual.group-name.sg.consul`. This syntax is required when failover is desired and `spec.defaultForFailover` is set to `false` in the sameness group CRD. Refer to [sameness group configuration entry reference](/consul/docs/connect/config-entries/sameness-group) for more information. +You can query the KubeDNS for a service that belongs to a sameness group at `sample-app.virtual.group-name.sg.consul`. This syntax is required when failover is desired. To use KubeDNS with sameness groups, `spec.defaultForFailover` must be set to `true` in the sameness group CRD. Refer to [sameness group configuration entry reference](/consul/docs/connect/config-entries/sameness-group) for more information. ### Headless services For services that are not addressed using a virtual cluster IP, you must configure the upstream service using the [DialedDirectly](/consul/docs/connect/config-entries/service-defaults#dialeddirectly) option. Then, use DNS to discover individual instance addresses and dial them through the transparent proxy. When this mode is enabled on the upstream, services present service mesh certificates for mTLS and intentions are enforced at the destination. @@ -253,4 +253,4 @@ Note that when dialing individual instances, Consul ignores the HTTP routing rul - Deployment configurations with federation across or a single datacenter spanning multiple clusters must explicitly dial a service in another datacenter or cluster using annotations. -- When dialing headless services, the request is proxied using a plain TCP proxy. Consul does not take into consideration the upstream's protocol. \ No newline at end of file +- When dialing headless services, the request is proxied using a plain TCP proxy. Consul does not take into consideration the upstream's protocol. diff --git a/website/content/docs/k8s/crds/index.mdx b/website/content/docs/k8s/crds/index.mdx index b2ed48854fb1..3db8edaf2f45 100644 --- a/website/content/docs/k8s/crds/index.mdx +++ b/website/content/docs/k8s/crds/index.mdx @@ -19,6 +19,7 @@ You can specify the following values in the `kind` field. Click on a configurati - [`PeeringAcceptor`](/consul/docs/k8s/connect/cluster-peering/tech-specs#peeringacceptor) - [`PeeringDialer`](/consul/docs/k8s/connect/cluster-peering/tech-specs#peeringdialer) - [`ProxyDefaults`](/consul/docs/connect/config-entries/proxy-defaults) +- [`Registration`](/consul/docs/connect/config-entries/registration) - [`SamenessGroup`](/consul/docs/connect/config-entries/sameness-group) - [`ServiceDefaults`](/consul/docs/connect/config-entries/service-defaults) - [`ServiceSplitter`](/consul/docs/connect/config-entries/service-splitter) diff --git a/website/content/docs/k8s/deployment-configurations/argo-rollouts-configuration.mdx b/website/content/docs/k8s/deployment-configurations/argo-rollouts-configuration.mdx new file mode 100644 index 000000000000..5bd2a1e44d7a --- /dev/null +++ b/website/content/docs/k8s/deployment-configurations/argo-rollouts-configuration.mdx @@ -0,0 +1,262 @@ +--- +layout: docs +page_title: Argo Rollouts Progressive Delivery with Consul on Kubernetes +description: >- + Configure the Argo Rollouts Controller to enable Canary deployments for subset-based routing. Learn how k8s Rollouts integrate with Consul's service mesh. +--- + +# Argo Rollouts Progressive Delivery with Consul on Kubernetes + +This page describes the process to configure and use the [Argo Rollouts Controller](https://argo-rollouts.readthedocs.io/en/stable/) with Consul on Kubernetes to manage advanced subset-based routing for Canary deployments. + +Consul's support for Argo Rollouts is currently limited to subset-based routing. + +## Install Argo Rollouts Controller + +There are three methods for installing the Argo Rollouts Controller with Consul on Kubernetes: + +1. [Install Rollouts Using Helm and init containers](#install-rollouts-using-helm-and-binary). We recommend installing the Argo Rollouts Controllor using this method. +1. [Install Rollouts Using Helm and binary](#install-rollouts-using-helm-and-binary) +1. [Standalone installation](#stand-alone-installation) + +After installing the controller, you must [apply the RBAC CRD](https://raw.githubusercontent.com/argoproj-labs/rollouts-plugin-trafficrouter-consul/main/yaml/rbac.yaml) to your Kubernetes cluster. + +### Install Rollouts Using Helm and init containers + +We recommend using this method to install this plugin. + +Add the following code to your `values.yaml` file to configure the plugin: + +```yaml +controller: + initContainers: + - name: copy-consul-plugin + image: hashicorp/rollouts-plugin-trafficrouter-consul + command: ["/bin/sh", "-c"] + args: + # Copy the binary from the image to the rollout container + - cp /bin/rollouts-plugin-trafficrouter-consul /plugin-bin/hashicorp + volumeMounts: + - name: consul-plugin + mountPath: /plugin-bin/hashicorp + trafficRouterPlugins: + trafficRouterPlugins: |- + - name: "hashicorp/consul" + location: "file:///plugin-bin/hashicorp/rollouts-plugin-trafficrouter-consul" + volumes: + - name: consul-plugin + emptyDir: {} + volumeMounts: + - name: consul-plugin + mountPath: /plugin-bin/hashicorp +``` + +Then install the `argo-rollouts` and apply your updated values using Helm: + +```shell-session +$ helm install argo-rollouts argo/argo-rollouts -f values.yaml -n argo-rollouts +``` + +### Install Rollouts Using Helm and binary + +To build the binary and install Rollouts, complete the following steps: + +1. Build this plugin using your preferred tool. For example, `make build`. +1. Mount the built plugin onto the `argo-rollouts` container. +1. Add the following code to your `values.yaml` file to configure the plugin: + +```yaml +controller: + trafficRouterPlugins: + trafficRouterPlugins: |- + - name: "argoproj-labs/consul" + location: "file:///plugin-bin/hashicorp/rollouts-plugin-trafficrouter-consul" + volumes: + - name: consul-route-plugin + hostPath: + # The path being mounted to, change this depending on your mount path + path: /rollouts-plugin-trafficrouter-consul + type: DirectoryOrCreate + volumeMounts: + - name: consul-route-plugin + mountPath: /plugin-bin/hashicorp +``` + +Then install the `argo-rollouts` and apply your updated values using Helm: + +```shell-session + $ helm install argo-rollouts argo/argo-rollouts -f values.yaml -n argo-rollouts +``` + +### Stand-alone installation + +This section describes the process to create a stand-alone installation. These instructions are for illustrative purposes. We recommend using init containers to create and install this plugin. + +To create a stand-alone installation of the Rollouts plugin, complete the following steps: + +1. Build this plugin. +1. Put the plugin on the path and mount it to the `argo-rollouts`container. +1. Create a `ConfigMap` to configure `argo-rollouts` with the plugin's location. + +The following example schedules a Deployment and mounts it to the `argo-rollouts` container: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: argo-rollouts + namespace: argo-rollouts +spec: + selector: + matchLabels: + app.kubernetes.io/name: argo-rollouts + template: + spec: + # ... + volumes: + # ... + - name: consul-plugin + hostPath: + path: /plugin-bin/hashicorp/rollouts-plugin-trafficrouter-consul + type: DirectoryOrCreate + containers: + - name: argo-rollouts + # ... + volumeMounts: + - name: consul-route-plugin + mountPath: /plugin-bin/hashicorp + +``` + +The following example creates the `ConfigMap` with the location of the plugin: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: argo-rollouts-config + namespace: argo-rollouts +data: + trafficRouterPlugins: |- + - name: "argoproj-labs/consul" + location: "file:///plugin-bin/hashicorp/rollouts-plugin-trafficrouter-consul" +binaryData: {} +``` + +### Install the RBAC + +After either mounting the binary or using an init container, configure an RBAC using [Argo Rollout Consul plugin `rbac.yaml`](https://raw.githubusercontent.com/argoproj-labs/rollouts-plugin-trafficrouter-consul/main/yaml/rbac.yaml): + +```shell-session +$ kubectl apply -f https://raw.githubusercontent.com/argoproj-labs/rollouts-plugin-trafficrouter-consul/main/yaml/rbac.yaml +``` + +## Use the Argo Rollouts Consul plugin + +Schedule the Kubernetes Service utilized by the service being rolled out. Additionally, configure any service defaults and proxy defaults required for the service. + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: test-service +spec: + selector: + app: test-service + ports: + - name: http + port: 80 + targetPort: 8080 +``` + +Next, create the service resolver and service splitter CRDs for your stable service. Argo automatically modifies these CRDs during canary deployments. + +The following example demonstrates the configuration of the service resolver CRD, which creates service subsets and sets the stable subset as the default: + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: ServiceResolver +metadata: + name: test-service +spec: + subsets: + stable: + filter: Service.Meta.version == 1 + canary: + filter: "" + defaultSubset: stable +``` + +The following example demonstrates the configuration of the service splitter CRD, which initially sends 100% of traffic to the stable deployment: + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: ServiceSplitter +metadata: + name: test-service +spec: + splits: + - weight: 100 + serviceSubset: stable + - weight: 0 + serviceSubset: canary +``` + +Then configure your Argo Rollout resource to incrementally rollout the canary deployment: + +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: test-service +spec: + replicas: 3 + selector: + matchLabels: + app: test-service + template: + metadata: + labels: + app: test-service + annotations: + consul.hashicorp.com/connect-inject: "true" + consul.hashicorp.com/service-meta-version: "1" + consul.hashicorp.com/service-tags: "v1" + spec: + containers: + - name: test-service + # Using alpine vs latest as there is a build issue with M1s. Also other tests in multiport-app reference + # alpine so standardizing this. + image: docker.mirror.hashicorp.services/hashicorp/http-echo:alpine + args: + - -text="I am v1" + - -listen=:8080 + ports: + - containerPort: 8080 + name: http + serviceAccountName: test-service + terminationGracePeriodSeconds: 0 # so deletion is quick + strategy: + canary: + trafficRouting: + plugins: + hashicorp/consul: + stableSubsetName: stable # subset name of the stable service + canarySubsetName: canary # subset name of the canary service + serviceName: test-service + steps: + - setWeight: 20 + - pause: {} + - setWeight: 40 + - pause: {duration: 10} + - setWeight: 60 + - pause: {duration: 10} + - setWeight: 80 + - pause: {duration: 10} +``` + +Finally, perform the Rollout operation using the Argo Rollouts Kubectl plugin. + +```shell-session +$ kubectl argo rollouts promote test-service +``` diff --git a/website/content/docs/k8s/deployment-configurations/datadog.mdx b/website/content/docs/k8s/deployment-configurations/datadog.mdx new file mode 100644 index 000000000000..c3df799f4df4 --- /dev/null +++ b/website/content/docs/k8s/deployment-configurations/datadog.mdx @@ -0,0 +1,468 @@ +--- +layout: docs +page_title: Configure Datadog metrics collection for Consul on Kubernetes +description: >- + Consul can integrate with external platforms such as Datadog to stream metrics about its operations. Learn how to enable Consul monitoring with Datadog by configuring the `metrics.datadog` Helm value override options. +--- + +# Configure Datadog metrics collection for Consul on Kubernetes + +This page describes the processes for integrating Datadog metrics collection in your Consul on Kubernetes deployment. The Helm chart includes automated configuration options to simplify the integration process. + +## Datadog Metrics Integration Methods + +- [DogstatsD](#dogstatsd) +- [Datadog Checks: Official Consul Integration](#datadog-checks-official-consul-integration) +- [Openmetrics Prometheus](#openmetrics-prometheus) + +Users should choose **_one_** integration method from the three described below that best suites the intent for metrics collection. **[DogStatsD](https://docs.datadoghq.com/developers/dogstatsd/?tab=kubernetes)**, **[Consul Integration](https://docs.datadoghq.com/integrations/consul/?tab=containerized)**, and **[Openmetrics Prometheus](https://docs.datadoghq.com/containers/kubernetes/prometheus/?tab=kubernetesadv2)** methods of integration are **_mutually exclusive_**. + +**Reasoning:** _The consul-k8s helm chart automated configuration implements Datadog's [Consul Integration](https://docs.datadoghq.com/integrations/consul/?tab=containerized) method using the [`use_prometheus_endpoint`](https://github.com/DataDog/integrations-core/blob/07c04c5e9465ba1f3e0198830896d05923e81283/consul/datadog_checks/consul/data/conf.yaml.example#L59) configuration parameter. **DogstatsD**, **Consul Integration**, and **Openmetrics Prometheus** Metrics **by design** share the same [metric name](https://docs.datadoghq.com/integrations/consul/?tab=host#data-collected) syntax for collection, and would therefore cause a conflict. The [consul.py](https://github.com/DataDog/integrations-core/blob/07c04c5e9465ba1f3e0198830896d05923e81283/consul/datadog_checks/consul/consul.py#L55-L61) integration source code, as well as the [consul-k8s helm chart](https://github.com/hashicorp/consul-k8s/blob/4cac70496788f50354f96e9331003fcf338f419c/charts/consul/templates/_helpers.tpl#L595-L598) prohibit the enablement of more that one integration at a time._ + + +## DogstatsD + +This method of implementation leverages the [hashicorp/go-metrics DogstatsD client library](https://github.com/hashicorp/go-metrics/tree/master/datadog) to manage metrics collection. +Metrics are aggregated and sent via UDP or UDS transports to a Datadog Agent that runs on the same Kube Node as the Consul servers. + +Enabling this method of metrics collection allows Consul to control the delivery of metrics traffic directly to a Datadog agent rather +than a Datadog agent attempting to reach Consul and scrape the `/v1/agent/metrics` API endpoint. + +This is accomplished by updating each server agent's configuration telemetry stanza. + +### Helm Chart Configuration + + + + + Consul Helm Chart Overrides + + ```yaml + metrics: + enabled: true + enableAgentMetrics: true + datadog: + enabled: true + namespace: "datadog" + dogstatsd: + enabled: true + socketTransportType: "UDS" + dogstatsdAddr: "/var/run/datadog/dsd.socket" + ``` + + Resulting server agent telemetry configuration + + ```json + { + "telemetry": { + "dogstatsd_addr": "unix:///var/run/datadog/dsd.socket" + } + } + ``` + + + + + + Consul Helm Chart Overrides + + ```yaml + metrics: + enabled: true + enableAgentMetrics: true + datadog: + enabled: true + namespace: "datadog" + dogstatsd: + enabled: true + socketTransportType: "UDP" + # Set `dogstatsdPort` to `0` (default) to omit port number append to address. + dogstatsdPort: 0 + dogstatsdAddr: "datadog-agent.datadog.svc.cluster.local" + ``` + + Resulting server agent telemetry configuration + + ```json + { + "telemetry": { + "dogstatsd_addr": "datadog-agent.datadog.svc.cluster.local" + } + } + ``` + + + + + + Consul Helm Chart Overrides + + ```yaml + metrics: + enabled: true + enableAgentMetrics: true + datadog: + enabled: true + namespace: "datadog" + dogstatsd: + enabled: true + socketTransportType: "UDP" + dogstatsdPort: 8125 + dogstatsdAddr: "172.20.180.10" + ``` + + Resulting server agent telemetry configuration + + ```json + { + "telemetry": { + "dogstatsd_addr": "172.20.180.10:8125", + } + } + ``` + + + + +### UDS/UDP Advantages and Disadvantages + +This integration method accomplishes metrics collection by leveraging either [Unix Domain Sockets](https://docs.datadoghq.com/developers/dogstatsd/unix_socket/?tab=kubernetes) (**UDS**) or [User Datagram Protocol](https://docs.datadoghq.com/developers/dogstatsd/?tab=kubernetes#agent) (**UDP**) transport. +Practitioners who manage their Kubernetes infrastructure and/or service-mesh should take into account the implications outlined in the tables below. + +#### UDS + +**Packet Transport**: Unix Domain Socket File + +| Advantages | Disadvantages | +|-------------------------------------------------------|------------------------------------------------------------------------------------------------------| +| No IP or DNS resolution requirement for Datadog Agent | Requires [hostPath](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath) Volume attachment | +| Improved network performance | Datadog Agent must run on every host you send metrics from | +| Higher throughput capacity | | +| Packet error handling | | +| Automatic container ID tagging | | + +#### UDP + +**Packet Transport**: + * Kubernetes Service `IP:Port` + * Container Host Port + +| Advantages | Disadvantages | +|------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------| +| Does **not** require [hostPath](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath) Volume attachment | **No** packet error handling | +| (**_KubeDNS_**) Does **not** require Hostport exposure if accessible from cluster | (**_Hostport_**) Requires a networking provider that adheres to the CNI specification, such as Calico, Canal, or Flannel. | +| Similar `IP:Port` configuration as Virtual Machine hosts | (**_Hostport_**) Requires port to be exposed on host using `hostNetwork` | +| | (**_Hostport_**) Requires firewall access controls to permit access | +| | (**_Hostport_**) Network Namespace sharing is required | + + +#### Verifying DogstatsD Metric Collection + +To confirm you're Datadog agent is receiving traffic, the `status` subcommand can be ran from the Datadog Agent expecting to receive DogstatsD traffic from Consul. + +There should be an increase in either UDP or UDS traffic packet counts from the resultant output after the configuration has been properly established. + + + | Transport | Command | Pod | Container | + |:---------------|----------------------------------------------------------------------------|---------------|-----------| + | `UDP`\|\|`UDS` | `agent status` | datadog-agent | agent | + + + + + + ```shell + # Example: UDP Packet and Metric Packet Traffic Increase + ========= + DogStatsD + ========= + Event Packets: 0 + Event Parse Errors: 0 + Metric Packets: 5,908 + Metric Parse Errors: 0 + Service Check Packets: 0 + Service Check Parse Errors: 0 + Udp Bytes: 636,872 + Udp Packet Reading Errors: 0 + Udp Packets: 3,300 + Uds Bytes: 0 + Uds Origin Detection Errors: 0 + Uds Packet Reading Errors: 0 + Uds Packets: 0 + Unterminated Metric Errors: 0 + ``` + + + + ```shell + # Example: UDS Packet and Metric Packet Traffic Increase + ========= + DogStatsD + ========= + Event Packets: 0 + Event Parse Errors: 0 + Metric Packets: 30,523 + Metric Parse Errors: 0 + Service Check Packets: 0 + Service Check Parse Errors: 0 + Udp Bytes: 124,635 + Udp Packet Reading Errors: 0 + Udp Packets: 731 + Uds Bytes: 2,957,433 + Uds Origin Detection Errors: 0 + Uds Packet Reading Errors: 0 + Uds Packets: 11,563 + Unterminated Metric Errors: 0 + ``` + + + + +Traffic verification can also be accomplished using the `netstat` command line utility from a consul-server expected to be submitting +metrics data to Datadog. + + + Using netstat requires privileged container permissions to install open-bsd networking tools on the consul-server for testing. + + +| Transport | Command | Pod | Container | +|:-----------------|-----------|---------------|-----------| +| `UDP` \|\| `UDS` | `netstat` | consul-server | consul | + + + + + ```shell + $ netstat -nup | grep "172.28.13.12:8125.*ESTABLISHED + udp 0 0 127.0.0.1:53874 127.0.0.1:8125 ESTABLISHED 23176/consul + ``` + + + + + + ```shell + $ netstat -x + Active UNIX domain sockets (w/o servers) + Proto RefCnt Flags Type State I-Node Path + unix 2 [ ] DGRAM CONNECTED 15952473 + unix 2 [ ] DGRAM 15652537 @9d10c + ``` + + + + + +UDS provides the additional capability for verification by sending a test metrics packet to the Unix Socket configured. + + + Using netcat (nc) requires privileged container permissions to install open-bsd networking tools on the consul-server for testing. + + +| Transport | Command | Pod | Container | +|:----------|---------|---------------|-----------| +| `UDS` | `nc` | consul-server | consul | + + + + ```shell + $ echo -n "custom.metric.name:1|c" | nc -U -u -w1 /var/run/datadog/dsd.socket + Bound on /tmp/nc-IjJkoG/recv.sock + ``` + + + +#### Use Case + +DogstatsD integration provides full-scope metrics collection from Consul, and minimizes access control configuration requirements as traffic +flow is outbound (toward the Datadog Agent) as opposed to inbound (toward the `/v1/agent/metrics/` API endpoint). + + +#### Metrics Data Collected + + - Full list of metrics sent via DogstatsD consists of those listed in the [Agent Telemetry](https://developer.hashicorp.com/consul/docs/agent/telemetry) documentation. + + +## Datadog Checks: Official Consul Integration + +The Datadog Agent package includes official third-party integrations for built-in availability upon agent deployment. + +The Consul Integration Datadog checks provided some additional metric verification checks that leverage Consul's built-in feature-set, and help monitor Consul +during normal operation beyond that of Consul's available metrics. + +See the below [table](#additional-integration-checks-performed) for an outline of the features added by the official integration. + + + Currently, the annotations configured by the Helm overrides with Consul RPC TLS enabled + assume server and ca certificate secrets are shared with the Datadog agent release namespace and mount the valid tls.crt, tls.key, + and ca.crt secret volumes at the /etc/datadog-agent/conf.d/consul.d/certs path on the Datadog Agent, agent container. + + +### Helm Chart Configuration + + + + + Consul Helm Chart Overrides + + ```yaml + global: + tls: + enabled: true + enableAutoEncrypt: true + acls: + manageSystemACLs: true + metrics: + enabled: true + enableAgentMetrics: true + datadog: + enabled: true + namespace: "datadog" + ``` + + + Consul `server-statefulset.yaml` annotations + + ```yaml + "ad.datadoghq.com/consul.checks": | + { + "consul": { + "init_config": {}, + "instances": [ + { + "url": "https://consul-server.consul.svc:8501", + "tls_cert": "/etc/datadog-agent/conf.d/consul.d/certs/tls.crt", + "tls_private_key": "/etc/datadog-agent/conf.d/consul.d/certs/tls.key", + "tls_ca_cert": "/etc/datadog-agent/conf.d/consul.d/ca/tls.crt", + "use_prometheus_endpoint": true, + "acl_token": "ENC[k8s_secret@consul/consul-datadog-agent-metrics-acl-token/token]", + "new_leader_checks": true, + "network_latency_checks": true, + "catalog_checks": true, + "auth_type": "basic" + } + ] + } + } + ``` + + + + +### Additional Integration Checks Performed + +| Consul Component | Description | API Endpoint(s) | +|------------------|-----------------------------------------------------|----------------------------------------------------------------------| +| Agent | Agent Metadata (i.e., version) | `/v1/agent/self` | +| Metrics | Prometheus formatted metrics | `/v1/agent/metrics` | +| Serf | Events and Membership Flaps | `/v1/health/service/consul` `/v1/agent/self` | +| Raft | Monitors Raft peer information and leader elections | `/v1/status/leader` `/v1/status/peers` | +| Catalog Services | Service Health Status and Node Count | `/v1/catalog/services` `/v1/health/state/any` | +| Catalog Nodes | Node Service Count and Health Status | `/v1/health/state/any` `/v1/health/service/` | +| Consul Latency | Consul LAN + WAN Coordinate Latency Calculations | `/v1/agent/self` `/v1/coordinate/nodes` `/v1/coordinate/datacenters` | + +#### Use Case + +This integration is primarily for basic Consul monitoring with focus on the service discovery. + +#### Metrics Data Collected + +The list of Consul's Prometheus metrics scraped and mapped by this method are listed in the latest [metrics.py](https://github.com/DataDog/integrations-core/blob/master/consul/datadog_checks/consul/metrics.py) of the integration source code. + +To understand how Consul Latency metrics are calculated, review the [Consul Network Coordinates](https://developer.hashicorp.com/consul/docs/architecture/coordinates) documentation. + +Review the [Datadog Documentation](https://docs.datadoghq.com/integrations/consul/?tab=containerized#data-collected) for the full description of Metrics data collected. + +## Openmetrics Prometheus + +For Datadog agents at or above v6.5.0, OpenMetrics and Prometheus checks are available to scrape Kubernetes application Prometheus endpoints. + +This method implements the collection via Openmetrics as that is fully supported for Prometheus text format and is accomplished using pod annotations as demonstrated below. + + + Enabling OpenMetrics collection via Datadog by design removes the prometheus.io/path and prometheus.io/port annotations from the consul-server statefulset deployment to allow Datadog + to scrape the agent's metrics API endpoint using either RPC TLS and Consul ACLs as necessary. + + + + Currently, the annotations configured by the Helm overrides with Consul RPC TLS enabled + assume server and ca certificate secrets are shared with the Datadog agent release namespace and mount the valid tls.crt, tls.key, + and ca.crt secret volumes at the /etc/datadog-agent/conf.d/consul.d/certs path on the Datadog Agent, agent container. + + +### Helm Chart Configuration + + + + + Consul Helm Chart Overrides + + ```yaml + global: + tls: + enabled: true + enableAutoEncrypt: true + acls: + manageSystemACLs: true + metrics: + enabled: true + enableAgentMetrics: true + datadog: + enabled: true + namespace: "datadog" + openMetricsPrometheus: + enabled: true + ``` + + Consul `server-statefulset.yaml` annotations + + ```yaml + ad.datadoghq.com/consul.checks: | + { + "openmetrics": { + "init_config": {}, + "instances": [ + { + "openmetrics_endpoint": "https://consul-server.consul.svc:8501/v1/agent/metrics?format=prometheus", + "tls_cert": "/etc/datadog-agent/conf.d/consul.d/certs/tls.crt", + "tls_private_key": "/etc/datadog-agent/conf.d/consul.d/certs/tls.key", + "tls_ca_cert": "/etc/datadog-agent/conf.d/consul.d/ca/tls.crt", + "headers": { + "X-Consul-Token": "ENC[k8s_secret@consul/consul-datadog-agent-metrics-acl-token/token]" + }, + "namespace": "consul", + "metrics": [ ".*" ] + } + ] + } + } + ``` + + + + +#### Use Case + +This method of integration is useful for Prometheus-enabled scrapes with further customization of the collected data. + +By default, all metrics pulled using this method scrape Consul metrics using the `/v1/agent/metrics?format=prometheus` API query, and are considered to be custom metrics. + +Use of this method maps to Datadog as described in [Mapping Prometheus Metrics to Datadog Metrics](https://docs.datadoghq.com/integrations/guide/prometheus-metrics/?tab=latestversion). The following table summarizing how these metrics map to each other. + +| OpenMetrics metric type | Datadog metric type | +|:------------------------|:-----------------------------------| +| `Gauge` | `gauge` | +| `Counter` | `count` | +| Histogram: `_count ` | `count.count` | +| Histogram: `_sum` | `count.sum` | +| Histogram: `_bucket` | `count.bucket` \|\| `distribution` | +| Summary: `_count` | `count.count` | +| Summary: `_sum` | `count.sum` | +| Summary: `sample` | `gauge.quantile` | + + +#### Metrics Data Collected + +The integration, by default, uses a wildcard (`".*"`) to collect **_all_** metrics emitted from the `/v1/agent/metrics` endpoint. + +Please refer to the [Agent Telemetry](https://developer.hashicorp.com/consul/docs/agent/telemetry) documentation for a full list and description of the metrics data collected. diff --git a/website/content/docs/k8s/deployment-configurations/external-service.mdx b/website/content/docs/k8s/deployment-configurations/external-service.mdx new file mode 100644 index 000000000000..711f01640855 --- /dev/null +++ b/website/content/docs/k8s/deployment-configurations/external-service.mdx @@ -0,0 +1,38 @@ +--- +layout: docs +page_title: Register services running on external nodes to Consul on Kubernetes +description: >- + Learn how to register a service running on an external node to the Consul catalog when running Consul on Kubernetes. +--- + +# Register services running on external nodes to Consul on Kubernetes + +This page provides an overview for registering services in the Consul catalog when the service runs on a node that is not part of the Kubernetes cluster. + +## Introduction + +Because Kubernetes has built-in service discovery capabilities, Consul on Kubernetes includes components such as [Consul dataplanes](/consul/docs/connect/dataplane) and [service sync](/consul/docs/k8s/service-sync) so that operators can continue to use Kubernetes tools and processes. However, this approach to service networking still requires a service to run on a node that Consul is aware of, either through a local Consul client agent or the Kubernetes cluster. We call services that run on external nodes that Consul cannot automatically recognize _external services_. + +Previously, the only way to register an external service when running Consul on Kubernetes was using Consul's HTTP API. This approach requires additional ACLs and direct access to Consul's HTTP API endpoint. Consul now supports registering external services and their associated health checks in the Consul catalog using a [`Registration` custom resource definition (CRD)](/consul/docs/connect/config-entries/registration) that follows the format of [Consul's service definitions](/consul/docs/services/configuration/services-configuration-reference). + +## Workflows + +The process to register an external service in Consul on Kubernetes consists of the following steps: + +1. [Start Consul ESM](/consul/tutorials/connect-services/service-registration-external-services#monitor-the-external-service-with-consul-esm). You must use Consul ESM to run health checks on external services. +1. Define the external service and its health checks in a [`Registration` CRD](/consul/docs/connect/config-entries/registration). +1. Apply the CRD to your Kubernetes cluster. Internally, this action triggers an API call to Consul's [`/catalog/register` endpoint](/consul/api-docs/catalog#register-entity) to register the service. +1. When using Consul's service mesh, you should also: + - Deploy a [terminating gateway](/consul/docs/k8s/connect/terminating-gateways) so that downstream services can communicate with the external service. + - Define [service intentions](/consul/docs/connect/intentions) for the external service and the downstream services that communicate with it. + +## Guidance + +The following resources are available to help you register external services to Consul on Kubernetes. + +### Reference + +- [`Registration` custom resource definition (CRD) configuration reference](/consul/docs/connect/config-entries/registration) +- [`/catalog/register` HTTP API endpoint reference](/consul/api-docs/catalog#register-entity) +- [Service configuration reference](/consul/docs/services/configuration/services-configuration-reference) +- [Health check configuration reference](/consul/docs/services/configuration/checks-configuration-reference) \ No newline at end of file diff --git a/website/content/docs/k8s/deployment-configurations/vault/data-integration/bootstrap-token.mdx b/website/content/docs/k8s/deployment-configurations/vault/data-integration/bootstrap-token.mdx index 582f781c236b..ea63dc992428 100644 --- a/website/content/docs/k8s/deployment-configurations/vault/data-integration/bootstrap-token.mdx +++ b/website/content/docs/k8s/deployment-configurations/vault/data-integration/bootstrap-token.mdx @@ -29,7 +29,7 @@ Prior to setting up the data integration between Vault and Consul on Kubernetes, First, generate and store the ACL bootstrap token in Vault. You will only need to perform this action once: ```shell-session -$ vault kv put secret/consul/bootstrap-token token="$(uuidgen | tr '[:upper:]' '[:lower:]')" +$ vault kv put consul-kv/secret/bootstrap-token token="$(uuidgen | tr '[:upper:]' '[:lower:]')" ``` ## Create Vault policy @@ -41,7 +41,7 @@ The path to the secret referenced in the `path` resource is the same value that ```HCL -path "secret/data/consul/bootstrap-token" { +path "consul-kv/data/secret/bootstrap-token" { capabilities = ["read"] } ``` @@ -88,7 +88,7 @@ global: manageSystemACLsRole: consul-server-acl-init acls: bootstrapToken: - secretName: secret/data/consul/bootstrap-token + secretName: consul-kv/data/secret/bootstrap-token secretKey: token ``` diff --git a/website/content/docs/k8s/deployment-configurations/vault/data-integration/enterprise-license.mdx b/website/content/docs/k8s/deployment-configurations/vault/data-integration/enterprise-license.mdx index ef3ab8eaafcb..9b32cf468ebb 100644 --- a/website/content/docs/k8s/deployment-configurations/vault/data-integration/enterprise-license.mdx +++ b/website/content/docs/k8s/deployment-configurations/vault/data-integration/enterprise-license.mdx @@ -29,7 +29,7 @@ Prior to setting up the data integration between Vault and Consul on Kubernetes, First, store the enterprise license in Vault: ```shell-session -$ vault kv put secret/consul/license key="" +$ vault kv put consul-kv/secret/enterpriselicense key="" ``` ## Create Vault policy @@ -41,7 +41,7 @@ The path to the secret referenced in the `path` resource is the same value that ```HCL -path "secret/data/consul/license" { +path "consul-kv/data/secret/enterpriselicense" { capabilities = ["read"] } ``` @@ -103,7 +103,7 @@ global: consulServerRole: consul-server consulClientRole: consul-client enterpriseLicense: - secretName: secret/data/consul/enterpriselicense + secretName: consul-kv/data/secret/enterpriselicense secretKey: key ``` diff --git a/website/content/docs/k8s/deployment-configurations/vault/data-integration/gossip.mdx b/website/content/docs/k8s/deployment-configurations/vault/data-integration/gossip.mdx index 186ae3f7dc4f..c6c71875a56c 100644 --- a/website/content/docs/k8s/deployment-configurations/vault/data-integration/gossip.mdx +++ b/website/content/docs/k8s/deployment-configurations/vault/data-integration/gossip.mdx @@ -29,7 +29,7 @@ Prior to setting up the data integration between Vault and Consul on Kubernetes, First, generate and store the gossip key in Vault. You will only need to perform this action once: ```shell-session -$ vault kv put secret/consul/gossip key="$(consul keygen)" +$ vault kv put consul-kv/secret/gossip key="$(consul keygen)" ``` ## Create Vault policy @@ -40,7 +40,7 @@ The path to the secret referenced in the `path` resource is the same value that ```HCL -path "secret/data/consul/gossip" { +path "consul-kv/data/secret/gossip" { capabilities = ["read"] } ``` @@ -101,7 +101,7 @@ global: consulServerRole: consul-server consulClientRole: consul-client gossipEncryption: - secretName: secret/data/consul/gossip + secretName: consul-kv/data/secret/gossip secretKey: key ``` diff --git a/website/content/docs/k8s/deployment-configurations/vault/data-integration/index.mdx b/website/content/docs/k8s/deployment-configurations/vault/data-integration/index.mdx index 2ce631b9cec7..819d0e4a9751 100644 --- a/website/content/docs/k8s/deployment-configurations/vault/data-integration/index.mdx +++ b/website/content/docs/k8s/deployment-configurations/vault/data-integration/index.mdx @@ -92,10 +92,14 @@ For example, if your Consul on Kubernetes servers need access to [Consul Server 1. Enterprise License + + Vault API calls to version 2 of the Key-Value secrets engine require the `data` field in the path configuration. In the following example, the key-value data in `consul-kv/secret/enterpriselicense` becomes accessible for Vault API calls on the `consul-kv/data/secret/enterpriselicense` path. + + ```HCL - path "secret/data/consul/license" { + path "consul-kv/data/secret/enterpriselicense" { capabilities = ["read"] } ``` diff --git a/website/content/docs/k8s/deployment-configurations/vault/data-integration/partition-token.mdx b/website/content/docs/k8s/deployment-configurations/vault/data-integration/partition-token.mdx index b646a6f80302..329c96ebef09 100644 --- a/website/content/docs/k8s/deployment-configurations/vault/data-integration/partition-token.mdx +++ b/website/content/docs/k8s/deployment-configurations/vault/data-integration/partition-token.mdx @@ -30,7 +30,7 @@ Prior to setting up the data integration between Vault and Consul on Kubernetes, First, generate and store the ACL partition token in Vault. You will only need to perform this action once: ```shell-session -$ vault kv put secret/consul/partition-token token="$(uuidgen | tr '[:upper:]' '[:lower:]')" +$ vault kv put consul-kv/secret/partition-token token="$(uuidgen | tr '[:upper:]' '[:lower:]')" ``` ## Create Vault policy @@ -42,7 +42,7 @@ The path to the secret referenced in the `path` resource is the same value that ```HCL -path "secret/data/consul/partition-token" { +path "consul-kv/data/secret/consul/partition-token" { capabilities = ["read"] } ``` @@ -90,7 +90,7 @@ global: adminPartitionsRole: consul-partition-init acls: partitionToken: - secretName: secret/data/consul/partition-token + secretName: consul-kv/data/secret/partition-token secretKey: token ``` diff --git a/website/content/docs/k8s/deployment-configurations/vault/data-integration/replication-token.mdx b/website/content/docs/k8s/deployment-configurations/vault/data-integration/replication-token.mdx index a7f351d54a7e..6d6077facdac 100644 --- a/website/content/docs/k8s/deployment-configurations/vault/data-integration/replication-token.mdx +++ b/website/content/docs/k8s/deployment-configurations/vault/data-integration/replication-token.mdx @@ -29,7 +29,7 @@ Prior to setting up the data integration between Vault and Consul on Kubernetes, First, generate and store the ACL replication token in Vault. You will only need to perform this action once: ```shell-session -$ vault kv put secret/consul/replication-token token="$(uuidgen | tr '[:upper:]' '[:lower:]')" +$ vault kv put consul-kv/secret/replication-token token="$(uuidgen | tr '[:upper:]' '[:lower:]')" ``` ## Create Vault policy @@ -41,7 +41,7 @@ The path to the secret referenced in the `path` resource is the same value that ```HCL -path "secret/data/consul/replication-token" { +path "consul-kv/data/secret/replication-token" { capabilities = ["read"] } ``` @@ -88,7 +88,7 @@ global: manageSystemACLsRole: consul-server-acl-init acls: replicationToken: - secretName: secret/data/consul/replication-token + secretName: consul-kv/data/secret/replication-token secretKey: token ``` diff --git a/website/content/docs/k8s/deployment-configurations/vault/data-integration/snapshot-agent-config.mdx b/website/content/docs/k8s/deployment-configurations/vault/data-integration/snapshot-agent-config.mdx index 235ef68f8454..532b415b0954 100644 --- a/website/content/docs/k8s/deployment-configurations/vault/data-integration/snapshot-agent-config.mdx +++ b/website/content/docs/k8s/deployment-configurations/vault/data-integration/snapshot-agent-config.mdx @@ -29,7 +29,7 @@ Before you set up data integration between Vault and Consul on Kubernetes, compl First, store the snapshot agent config in Vault: ```shell-session -$ vault kv put secret/consul/snapshot-agent-config key="" +$ vault kv put consul-kv/secret/snapshot-agent-config key="" ``` ## Create Vault policy @@ -41,7 +41,7 @@ The path to the secret referenced in the `path` resource is the same values that ```HCL -path "secret/data/consul/snapshot-agent-config" { +path "consul-kv/data/secret/snapshot-agent-config" { capabilities = ["read"] } ``` @@ -91,7 +91,7 @@ global: client: snapshotAgent: configSecret: - secretName: secret/data/consul/snapshot-agent-config + secretName: consul-kv/data/secret/snapshot-agent-config secretKey: key ``` diff --git a/website/content/docs/k8s/deployment-configurations/vault/systems-integration.mdx b/website/content/docs/k8s/deployment-configurations/vault/systems-integration.mdx index 7c4de80bba61..a35a9969e24a 100644 --- a/website/content/docs/k8s/deployment-configurations/vault/systems-integration.mdx +++ b/website/content/docs/k8s/deployment-configurations/vault/systems-integration.mdx @@ -34,7 +34,7 @@ The following secrets can be stored in Vault KV secrets engine, which is meant t In order to store any of these secrets, we must enable the [Vault KV secrets engine - Version 2](/vault/docs/secrets/kv/kv-v2). ```shell-session -$ vault secrets enable -path=consul kv-v2 +$ vault secrets enable -path=consul-kv kv-v2 ``` ## Vault PKI Engine diff --git a/website/content/docs/k8s/deployment-configurations/vault/wan-federation.mdx b/website/content/docs/k8s/deployment-configurations/vault/wan-federation.mdx index 041b73033fc3..3afcbb7072c4 100644 --- a/website/content/docs/k8s/deployment-configurations/vault/wan-federation.mdx +++ b/website/content/docs/k8s/deployment-configurations/vault/wan-federation.mdx @@ -129,7 +129,7 @@ Repeat the following steps for each datacenter in the cluster: 1. Enable [Vault KV secrets engine - Version 2](/vault/docs/secrets/kv/kv-v2) in order to store the [Gossip Encryption Key](/consul/docs/k8s/helm#v-global-acls-replicationtoken) and the ACL Replication token ([`global.acls.replicationToken`](/consul/docs/k8s/helm#v-global-acls-replicationtoken)). ```shell-session - $ vault secrets enable -path=consul kv-v2 + $ vault secrets enable -path=consul-kv kv-v2 ``` 1. Enable Vault PKI Engine in order to leverage Vault for issuing Consul Server TLS certificates. @@ -314,15 +314,15 @@ Repeat the following steps for each datacenter in the cluster: 1. Store the ACL bootstrap and replication tokens, gossip encryption key, and root CA certificate secrets in Vault. ```shell-session - $ vault kv put consul/secret/gossip key="$(consul keygen)" + $ vault kv put consul-kv/secret/gossip key="$(consul keygen)" ``` ```shell-session - $ vault kv put consul/secret/bootstrap token="$(uuidgen | tr '[:upper:]' '[:lower:]')" + $ vault kv put consul-kv/secret/bootstrap token="$(uuidgen | tr '[:upper:]' '[:lower:]')" ``` ```shell-session - $ vault kv put consul/secret/replication token="$(uuidgen | tr '[:upper:]' '[:lower:]')" + $ vault kv put consul-kv/secret/replication token="$(uuidgen | tr '[:upper:]' '[:lower:]')" ``` ```shell-session $ vault write pki/root/generate/internal common_name="Consul CA" ttl=87600h @@ -332,7 +332,7 @@ Repeat the following steps for each datacenter in the cluster: ```shell-session $ vault policy write gossip - <- - Use a k8s ConfigMap to configure KubeDNS or CoreDNS so that you can use Consul's `.service.consul` syntax for queries and other DNS requests. In Kubernetes, this process uses either stub-domain or proxy configuration. ---- - -# Resolve Consul DNS Requests in Kubernetes - -One of the primary query interfaces to Consul is the -[DNS interface](/consul/docs/services/discovery/dns-overview). You can configure Consul DNS in -Kubernetes using a -[stub-domain configuration](https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/#configure-stub-domain-and-upstream-dns-servers) -if using KubeDNS or a [proxy configuration](https://coredns.io/plugins/forward/) if using CoreDNS. - -Once configured, DNS requests in the form `.service.consul` will -resolve for services in Consul. This will work from all Kubernetes namespaces. - --> **Note:** If you want requests to just `` (without the `.service.consul`) to resolve, then you'll need -to turn on [Consul to Kubernetes Service Sync](/consul/docs/k8s/service-sync#consul-to-kubernetes). - -## Consul DNS Cluster IP - -To configure KubeDNS or CoreDNS you'll first need the `ClusterIP` of the Consul -DNS service created by the [Helm chart](/consul/docs/k8s/helm). - -The default name of the Consul DNS service will be `consul-dns`. Use -that name to get the `ClusterIP`: - -```shell-session -$ kubectl get svc consul-dns --output jsonpath='{.spec.clusterIP}' -10.35.240.78% -``` - -For this installation the `ClusterIP` is `10.35.240.78`. - --> **Note:** If you've installed Consul using a different helm release name than `consul` -then the DNS service name will be `-consul-dns`. - -## KubeDNS - -If using KubeDNS, you need to create a `ConfigMap` that tells KubeDNS -to use the Consul DNS service to resolve all domains ending with `.consul`: - -Export the Consul DNS IP as an environment variable: - -```bash -export CONSUL_DNS_IP=10.35.240.78 -``` - -And create the `ConfigMap`: - -```shell-session -$ cat < **Note:** The `stubDomain` can only point to a static IP. If the cluster IP -of the Consul DNS service changes, then it must be updated in the config map to -match the new service IP for this to continue -working. This can happen if the service is deleted and recreated, such as -in full cluster rebuilds. - --> **Note:** If using a different zone than `.consul`, change the stub domain to -that zone. - -Now skip ahead to the [Verifying DNS Works](#verifying-dns-works) section. - -## CoreDNS Configuration - -If using CoreDNS instead of KubeDNS in your Kubernetes cluster, you will -need to update your existing `coredns` ConfigMap in the `kube-system` namespace to -include a `forward` definition for `consul` that points to the cluster IP of the -Consul DNS service. - -Edit the `ConfigMap`: - -```shell-session -$ kubectl edit configmap coredns --namespace kube-system -``` - -And add the `consul` block below the default `.:53` block and replace -`` with the DNS Service's IP address you -found previously. - -```diff -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - addonmanager.kubernetes.io/mode: EnsureExists - name: coredns - namespace: kube-system -data: - Corefile: | - .:53 { - - } -+ consul { -+ errors -+ cache 30 -+ forward . -+ } -``` - --> **Note:** The consul proxy can only point to a static IP. If the cluster IP -of the `consul-dns` service changes, then it must be updated to the new IP to continue -working. This can happen if the service is deleted and recreated, such as -in full cluster rebuilds. - --> **Note:** If using a different zone than `.consul`, change the key accordingly. - -## Verifying DNS Works - -To verify DNS works, run a simple job to query DNS. Save the following -job to the file `job.yaml` and run it: - - - -```yaml -apiVersion: batch/v1 -kind: Job -metadata: - name: dns -spec: - template: - spec: - containers: - - name: dns - image: anubhavmishra/tiny-tools - command: ['dig', 'consul.service.consul'] - restartPolicy: Never - backoffLimit: 4 -``` - - - -```shell-session -$ kubectl apply --filename job.yaml -``` - -Then query the pod name for the job and check the logs. You should see -output similar to the following showing a successful DNS query. If you see -any errors, then DNS is not configured properly. - -```shell-session -$ kubectl get pods --show-all | grep dns -dns-lkgzl 0/1 Completed 0 6m - -$ kubectl logs dns-lkgzl -; <<>> DiG 9.11.2-P1 <<>> consul.service.consul -;; global options: +cmd -;; Got answer: -;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4489 -;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 4 - -;; OPT PSEUDOSECTION: -; EDNS: version: 0, flags:; udp: 4096 -;; QUESTION SECTION: -;consul.service.consul. IN A - -;; ANSWER SECTION: -consul.service.consul. 0 IN A 10.36.2.23 -consul.service.consul. 0 IN A 10.36.4.12 -consul.service.consul. 0 IN A 10.36.0.11 - -;; ADDITIONAL SECTION: -consul.service.consul. 0 IN TXT "consul-network-segment=" -consul.service.consul. 0 IN TXT "consul-network-segment=" -consul.service.consul. 0 IN TXT "consul-network-segment=" - -;; Query time: 5 msec -;; SERVER: 10.39.240.10#53(10.39.240.10) -;; WHEN: Wed Sep 12 02:12:30 UTC 2018 -;; MSG SIZE rcvd: 206 -``` diff --git a/website/content/docs/k8s/dns/enable.mdx b/website/content/docs/k8s/dns/enable.mdx new file mode 100644 index 000000000000..708ca9241c26 --- /dev/null +++ b/website/content/docs/k8s/dns/enable.mdx @@ -0,0 +1,263 @@ +--- +layout: docs +page_title: Resolve Consul DNS requests in Kubernetes +description: >- + Use a k8s ConfigMap to configure KubeDNS or CoreDNS so that you can use Consul's `.service.consul` syntax for queries and other DNS requests. In Kubernetes, this process uses either stub-domain or proxy configuration. +--- + +# Resolve Consul DNS requests in Kubernetes + +This topic describes how to configure Consul DNS in +Kubernetes using a +[stub-domain configuration](https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/#configure-stub-domain-and-upstream-dns-servers) +if using KubeDNS or a [proxy configuration](https://coredns.io/plugins/forward/) if using CoreDNS. + +Once configured, DNS requests in the form `.service.consul` will +resolve for services in Consul. This works from all Kubernetes namespaces. + +-> **Note:** If you want requests to just `` (without the `.service.consul`) to resolve, then you'll need +to turn on [Consul to Kubernetes Service Sync](/consul/docs/k8s/service-sync#consul-to-kubernetes). + +## Consul DNS Cluster IP + +To configure KubeDNS or CoreDNS you'll first need the `ClusterIP` of the Consul +DNS service created by the [Helm chart](/consul/docs/k8s/helm). + +The default name of the Consul DNS service will be `consul-dns`. Use +that name to get the `ClusterIP`: + +```shell-session +$ kubectl get svc consul-dns --output jsonpath='{.spec.clusterIP}' +10.35.240.78% +``` + +For this installation the `ClusterIP` is `10.35.240.78`. + +-> **Note:** If you've installed Consul using a different helm release name than `consul` +then the DNS service name will be `-consul-dns`. + +## KubeDNS + +If using KubeDNS, you need to create a `ConfigMap` that tells KubeDNS +to use the Consul DNS service to resolve all domains ending with `.consul`: + +Export the Consul DNS IP as an environment variable: + +```bash +export CONSUL_DNS_IP=10.35.240.78 +``` + +And create the `ConfigMap`: + +```shell-session +$ cat < **Note:** The `stubDomain` can only point to a static IP. If the cluster IP +of the Consul DNS service changes, then it must be updated in the config map to +match the new service IP for this to continue +working. This can happen if the service is deleted and recreated, such as +in full cluster rebuilds. + +-> **Note:** If using a different zone than `.consul`, change the stub domain to +that zone. + +Now skip ahead to the [Verifying DNS Works](#verifying-dns-works) section. + +## CoreDNS Configuration + +If using CoreDNS instead of KubeDNS in your Kubernetes cluster, you will +need to update your existing `coredns` ConfigMap in the `kube-system` namespace to +include a `forward` definition for `consul` that points to the cluster IP of the +Consul DNS service. + +Edit the `ConfigMap`: + +```shell-session +$ kubectl edit configmap coredns --namespace kube-system +``` + +And add the `consul` block below the default `.:53` block and replace +`` with the DNS Service's IP address you +found previously. + +```diff +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + addonmanager.kubernetes.io/mode: EnsureExists + name: coredns + namespace: kube-system +data: + Corefile: | + .:53 { + + } ++ consul { ++ errors ++ cache 30 ++ forward . ++ } +``` + +-> **Note:** The consul proxy can only point to a static IP. If the cluster IP +of the `consul-dns` service changes, then it must be updated to the new IP to continue +working. This can happen if the service is deleted and recreated, such as +in full cluster rebuilds. + +-> **Note:** If using a different zone than `.consul`, change the key accordingly. + +## OpenShift DNS Operator + +-> **Note:** OpenShift CLI `oc` is utilized below complete the following steps. You can find more details on how to install OpenShift CLI from [Getting started with OpenShift CLI](https://docs.openshift.com/container-platform/latest/cli_reference/openshift_cli/getting-started-cli.html). + +You can use DNS forwarding to override the default forwarding configuration in the `/etc/resolv.conf` file by specifying +the `consul-dns` service for the `consul` subdomain (zone). + +Find `consul-dns` service clusterIP: + +```shell-session +$ oc get svc consul-dns --namespace consul --output jsonpath='{.spec.clusterIP}' +172.30.186.254 +``` + +Edit the `default` DNS Operator: + +```shell-session +$ oc edit edit dns.operator/default +``` + +Append the following `servers` section entry to the `spec` section of the DNS Operator configuration: + +```yaml +spec: + servers: + - name: consul-server + zones: + - consul + forwardPlugin: + policy: Random + upstreams: + - 172.30.186.254 # Set to clusterIP of consul-dns service +``` + +Save the configuration changes and verify the `dns-default` configmap has been updated: + +```shell-session +$ oc get configmap/dns-default -n openshift-dns -o yaml +``` + +Example output with updated `consul` forwarding zone: + +```yaml +... +data: + Corefile: | + # consul-server + consul:5353 { + prometheus 127.0.0.1:9153 + forward . 172.30.186.254 { + policy random + } + errors + log . { + class error + } + bufsize 1232 + cache 900 { + denial 9984 30 + } + } +... +``` + +## Verifying DNS Works + +To verify DNS works, run a simple job to query DNS. Save the following +job to the file `job.yaml` and run it: + + + +```yaml +apiVersion: batch/v1 +kind: Job +metadata: + name: dns +spec: + template: + spec: + containers: + - name: dns + image: anubhavmishra/tiny-tools + command: ['dig', 'consul.service.consul'] + restartPolicy: Never + backoffLimit: 4 +``` + + + +```shell-session +$ kubectl apply --filename job.yaml +``` + +Then query the pod name for the job and check the logs. You should see +output similar to the following showing a successful DNS query. If you see +any errors, then DNS is not configured properly. + +```shell-session +$ kubectl get pods --show-all | grep dns +dns-lkgzl 0/1 Completed 0 6m + +$ kubectl logs dns-lkgzl +; <<>> DiG 9.11.2-P1 <<>> consul.service.consul +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4489 +;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 4 + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 4096 +;; QUESTION SECTION: +;consul.service.consul. IN A + +;; ANSWER SECTION: +consul.service.consul. 0 IN A 10.36.2.23 +consul.service.consul. 0 IN A 10.36.4.12 +consul.service.consul. 0 IN A 10.36.0.11 + +;; ADDITIONAL SECTION: +consul.service.consul. 0 IN TXT "consul-network-segment=" +consul.service.consul. 0 IN TXT "consul-network-segment=" +consul.service.consul. 0 IN TXT "consul-network-segment=" + +;; Query time: 5 msec +;; SERVER: 10.39.240.10#53(10.39.240.10) +;; WHEN: Wed Sep 12 02:12:30 UTC 2018 +;; MSG SIZE rcvd: 206 +``` diff --git a/website/content/docs/k8s/dns/views/enable.mdx b/website/content/docs/k8s/dns/views/enable.mdx new file mode 100644 index 000000000000..3f29eac346c6 --- /dev/null +++ b/website/content/docs/k8s/dns/views/enable.mdx @@ -0,0 +1,102 @@ +--- +layout: docs +page_title: Enable Consul DNS proxy for Kubernetes +description: -> + Learn how to schedule a Consul DNS proxy for a Kubernetes Pod so that your services can return Consul DNS results for service discovery. +--- + +# Enable Consul DNS proxy for Kubernetes + +This page describes the process to deploy a Consul DNS proxy in a Kubernetes Pod so that Services can resolve Consul DNS requests. For more information, refer to [Consul DNS views for Kubernetes](/consul/docs/k8s/dns/views). + +## Prerequisites + +You must meet the following minimum application versions to enable the Consul DNS proxy for Kubernetes: + +- Consul v1.20.0 or higher +- Either Consul on Kubernetes or the Consul Helm chart, v1.6.0 or higher + +## Update Helm values + +To enable the Consul DNS proxy, add the required [Helm values](/consul/docs/k8s/helm) to your Consul on Kubernetes deployment. + +```yaml +connectInject: + enabled: true +dns: + enabled: true + proxy: true +``` + +### ACLs + +We recommend you create a dedicated [ACL token with DNS permissions](/consul/docs/security/acl/tokens/create/create-a-dns-token) for the Consul DNS proxy. The Consul DNS proxy requires these ACL permissions. + +```hcl +node_prefix "" { + policy = "read" +} + +service_prefix "" { + policy = "read" +} +``` + +You can manage ACL tokens with Consul on Kubernetes, or you can configure the DNS proxy to access a token stored in Kubernetes secret. To use a Kubernetes secret, add the following configuration to your Helm chart. + +```yaml +dns: + proxy: + aclToken: + secretName: + secretKey: +``` + +## Retrieve Consul DNS proxy's address + +To look up the IP address for the Consul DNS proxy in the Kubernetes Pod, run the following command. + +```shell-session +$ kubectl get services –-all-namespaces --selector="app=consul,component=dns-proxy" --output jsonpath='{.spec.clusterIP}' +10.96.148.46 +``` + +Use this address when you update the ConfigMap resource. + +## Update Kubernetes ConfigMap + +Create or update a [ConfigMap object in the Kubernetes cluster](https://kubernetes.io/docs/concepts/configuration/configmap/) so that Kubernetes forwards DNS requests with the `.consul` domain to the IP address of the Consul DNS proxy. + +The following example of a `coredns-custom` ConfigMap configures Kubernetes to forward Consul DNS requests in the cluster to the Consul DNS Proxy running on `10.96.148.46`. This resource modifies the CoreDNS without modifications to the original `Corefile`. + +```yaml +kind: ConfigMap +metadata: + name: coredns-custom + namespace: kube-system +data: + consul.server: | + consul:53 { + errors + cache 30 + forward . 10.96.148.46 + reload + } +``` + +After updating the DNS configuration, perform a rolling restart of the CoreDNS. + +```shell-session +kubectl -n kube-system rollout restart deployment coredns +``` + +For more information about using a `coredns-custom` resource, refer to the [Rewrite DNS guide in the Azure documentation](https://learn.microsoft.com/en-us/azure/aks/coredns-custom#rewrite-dns). For general information about modifying a ConfigMap, refer to [the Kubernetes documentation](https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/#coredns). + +## Next steps + +After you enable the Consul DNS proxy, services in the Kubernetes cluster can resolve Consul DNS addresses. + +- To learn more about Consul DNS for service discovery, refer to [DNS usage overview](/consul/docs/services/discovery/dns-overview). +- If your datacenter has ACLs enabled, create a [Consul ACL token](/consul/docs/security/acl/tokens) for the Consul DNS proxy and then restart the DNS proxy. +- To enable service discovery across admin partitions, [export services between partitions](/consul/docs/connect/config-entries/exported-services). +- To use Consul DNS for service discovery with other runtimes, across cloud regions, or between cloud providers, [establish a cluster peering connection](/consul/docs/k8s/connect/cluster-peering/usage/establish-peering). diff --git a/website/content/docs/k8s/dns/views/index.mdx b/website/content/docs/k8s/dns/views/index.mdx new file mode 100644 index 000000000000..7d482a9d3e84 --- /dev/null +++ b/website/content/docs/k8s/dns/views/index.mdx @@ -0,0 +1,48 @@ +--- +layout: docs +page_title: Consul DNS views for Kubernetes +description: -> + Kubernetes clusters can use the Consul DNS proxy to return service discovery results from the Consul catalog. Learn about how to configure your k8s cluster so that applications can resolve Consul DNS addresses without gossip communication. +--- + +# Consul DNS views for Kubernetes + +This topic describes how to schedule a dedicated Consul DNS proxy in a Kubernetes Pod so that applications in Kubernetes can resolve Consul DNS addresses. You can use the Consul DNS proxy to enable service discovery across admin partitions in Kubernetes deployments without needing to deploy Consul client agents. + +## Introduction + +Kubernetes operators typically choose networking tools such as [kube-dns](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) or [CoreDNS](https://kubernetes.io/docs/tasks/administer-cluster/coredns/) for their service discovery operations, and choose to bypass Consul DNS entirely. These DNS options are often sufficient for service networking operations within a single Kubernetes cluster. + +Consul on Kubernetes supports [configuring Kubernetes to resolve Consul DNS](/consul/docs/k8s/dns). However, two common challenges result when you rely on these configurations: + +- Kubernetes requires Consul to use gossip communication with agents or dataplanes in order to enable Consul DNS. +- Consul requires that admin partitions be included in the DNS address. Otherwise, DNS queries assume the `default` partition by default. + +The `consul-dns` proxy does not require the presence of Consul client agents or Consul dataplanes, removing gossip communication as a requirement for Consul DNS on Kubernetes. The proxy is also designed for deployment in a Kubernetes cluster with [external servers enabled](/consul/docs/k8s/deployment-configurations/servers-outside-kubernetes). When a cluster runs in a non-default admin partition and uses the proxy to query external servers, Consul automatically recognizes the admin partition that originated the request and returns service discovery results scoped to that specific admin partition. + +To use Consul DNS for service discovery on Kubernetes, deploy a `dns-proxy` service in each Kubernetes Pod that needs to resolve Consul DNS. Kubernetes sends all DNS requests to the Kubernetes controller first. The controller forwards requests for the `.consul` domain to the `dns-proxy` service, which then queries the Consul catalog and returns service discovery results. + +## Workflows + +The process to enable Consul DNS views for service discovery in Kubernetes deployments consists of the following steps: + +1. In a cluster configured to use [external Consul servers](/consul/docs/k8s/deployment-configurations/servers-outside-kubernetes), update the Helm values for your Consul on Kubernetes deployment so that `dns.proxy.enabled=true`. When you apply the updated configuration, Kubernetes deploys the Consul DNS proxy. +1. Look up the IP address for the Consul DNS proxy in the Kubernetes cluster. +1. Update the ConfigMap resource in the Kubernetes cluster so that it forwards requests for the `.consul` domain to the IP address of the Consul DNS proxy. + +For more information about the underlying concepts described in this workflow, refer to [DNS forwarding overview](/consul/docs/services/discovery/dns-forwarding). + +## Benefits + +Consul on Kubernetes currently uses [Consul dataplanes](/consul/docs/connect/dataplane) by default. These lightweight processes provide Consul access to the sidecar proxies in the service mesh, but leave Kubernetes in charge of most other service discovery and service mesh operations. + +- **Use Kubernetes DNS and Consul DNS in a single deployment**. The Consul DNS proxy enables any application in a Pod to resolve an address through Consul DNS without disrupting the underlying Kubernetes DNS functionality. +- **Consul service discovery using fewer resources**. When you use the Consul DNS proxy for service discovery, you do not need to schedule Consul client agents or dataplanes as sidecars. One Kubernetes Service that uses the same resources as a single Consul dataplane provides Pods access to the Consul service catalog. +- **Consul DNS without gossip communication**. The Consul DNS service runs on both Consul server and Consul client agents, which use [gossip communication](/consul/docs/security/encryption/gossip) to ensure that service discovery results are up-to-date. The Consul DNS proxy provides access to Consul DNS without the security overhead of agent-to-agent gossip. + +## Constraints and limitations + +If you experience issues using the Consul DNS proxy for Kubernetes, refer to the following list of technical constraints and limitations. + +- You must use Kubernetes as your runtime to use the Consul DNS proxy. You cannot schedule the Consul DNS proxy in other container-based environments. +- To perform DNS lookups on other admin partitions, you must [export services between partitions](/consul/docs/connect/config-entries/exported-services) before you can query them. \ No newline at end of file diff --git a/website/content/docs/k8s/helm.mdx b/website/content/docs/k8s/helm.mdx index 34bda9400cf2..42635dc2ca41 100644 --- a/website/content/docs/k8s/helm.mdx +++ b/website/content/docs/k8s/helm.mdx @@ -31,7 +31,6 @@ Use these links to navigate to a particular top-level stanza. - [`meshGateway`](#h-meshgateway) - [`ingressGateways`](#h-ingressgateways) - [`terminatingGateways`](#h-terminatinggateways) -- [`apiGateway`](#h-apigateway) - [`webhookCertManager`](#h-webhookcertmanager) - [`prometheus`](#h-prometheus) - [`tests`](#h-tests) @@ -109,6 +108,9 @@ Use these links to navigate to a particular top-level stanza. image that is used for functionality such as catalog sync. This can be overridden per component. + - `imagePullPolicy` ((#v-global-imagepullpolicy)) (`string: ""`) - The image pull policy used globally for images controlled by Consul (consul, consul-dataplane, consul-k8s, consul-telemetry-collector). + One of "IfNotPresent", "Always", "Never", and "". Refer to https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy + - `datacenter` ((#v-global-datacenter)) (`string: dc1`) - The name of the datacenter that the agents should register as. This can't be changed once the Consul cluster is up and running since Consul doesn't support an automatic way to change this value currently: @@ -134,6 +136,10 @@ Use these links to navigate to a particular top-level stanza. - `vault` ((#v-global-secretsbackend-vault)) + - `vaultNamespace` ((#v-global-secretsbackend-vault-vaultnamespace)) (`string: ""`) - Vault namespace (optional). This sets the Vault namespace for the `vault.hashicorp.com/namespace` + agent annotation and [Vault Connect CA namespace](/consul/docs/connect/ca/vault#namespace). + To override one of these values individually, see `agentAnnotations` and `connectCA.additionalConfig`. + - `enabled` ((#v-global-secretsbackend-vault-enabled)) (`boolean: false`) - Enabling the Vault secrets backend will replace Kubernetes secrets with referenced Vault secrets. - `consulServerRole` ((#v-global-secretsbackend-vault-consulserverrole)) (`string: ""`) - The Vault role for the Consul server. @@ -235,7 +241,6 @@ Use these links to navigate to a particular top-level stanza. { "connect": [{ "ca_config": [{ - "namespace": "my-vault-ns", "leaf_cert_ttl": "36h" }] }] @@ -288,6 +293,8 @@ Use these links to navigate to a particular top-level stanza. - `secretKey` ((#v-global-gossipencryption-secretkey)) (`string: ""`) - The key within the Kubernetes secret or Vault secret key that holds the gossip encryption key. + - `logLevel` ((#v-global-gossipencryption-loglevel)) (`string: ""`) - Override global log verbosity level for gossip-encryption-autogenerate-job pods. One of "trace", "debug", "info", "warn", or "error". + - `recursors` ((#v-global-recursors)) (`array: []`) - A list of addresses of upstream DNS servers that are used to recursively resolve DNS queries. These values are given as `-recursor` flags to Consul servers and clients. Refer to [`-recursor`](/consul/docs/agent/config/cli-flags#_recursor) for more details. @@ -302,6 +309,8 @@ Use these links to navigate to a particular top-level stanza. authority (optional) and server and client certificates. This setting is required for [Cluster Peering](/consul/docs/connect/cluster-peering/k8s). + - `logLevel` ((#v-global-tls-loglevel)) (`string: ""`) - Override global log verbosity level. One of "trace", "debug", "info", "warn", or "error". + - `enableAutoEncrypt` ((#v-global-tls-enableautoencrypt)) (`boolean: false`) - If true, turns on the auto-encrypt feature on clients and servers. It also switches consul-k8s-control-plane components to retrieve the CA from the servers via the API. Requires Consul 1.7.1+. @@ -383,6 +392,8 @@ Use these links to navigate to a particular top-level stanza. for all Consul and consul-k8s-control-plane components. This requires Consul >= 1.4. + - `logLevel` ((#v-global-acls-loglevel)) (`string: ""`) - Override global log verbosity level. One of "trace", "debug", "info", "warn", or "error". + - `bootstrapToken` ((#v-global-acls-bootstraptoken)) - A Kubernetes or Vault secret containing the bootstrap token to use for creating policies and tokens for all Consul and consul-k8s-control-plane components. If `secretName` and `secretKey` are unset, a default secret name and secret key are used. If the secret is populated, then @@ -440,7 +451,7 @@ Use these links to navigate to a particular top-level stanza. - `secretName` ((#v-global-acls-partitiontoken-secretname)) (`string: null`) - The name of the Vault secret that holds the partition token. - - `secretKey` ((#v-global-acls-partitiontoken-secretkey)) (`string: null`) - The key within the Vault secret that holds the partition token. + - `secretKey` ((#v-global-acls-partitiontoken-secretkey)) (`string: null`) - The key within the Vault secret that holds the parition token. - `tolerations` ((#v-global-acls-tolerations)) (`string: ""`) - tolerations configures the taints and tolerations for the server-acl-init and server-acl-init-cleanup jobs. This should be a multi-line string matching the @@ -465,6 +476,14 @@ Use these links to navigate to a particular top-level stanza. "sample/annotation2": "bar" ``` + - `argocd` ((#v-global-argocd)) - If argocd.enabled is set to true, following annotations are added to + job - server-acl-init-job + annotations - + argocd.argoproj.io/hook: Sync + argocd.argoproj.io/hook-delete-policy: HookSucceeded + + - `enabled` ((#v-global-argocd-enabled)) (`boolean: false`) + - `enterpriseLicense` ((#v-global-enterpriselicense)) - This value refers to a Kubernetes or Vault secret that you have created that contains your enterprise license. It is required if you are using an enterprise binary. Defining it here applies it to your cluster once a leader @@ -518,6 +537,8 @@ Use these links to navigate to a particular top-level stanza. -o jsonpath="{.clusters[?(@.name=='')].cluster.server}" ``` + - `logLevel` ((#v-global-federation-loglevel)) (`string: ""`) - Override global log verbosity level for the create-federation-secret-job pods. One of "trace", "debug", "info", "warn", or "error". + - `metrics` ((#v-global-metrics)) - Configures metrics for Consul service mesh - `enabled` ((#v-global-metrics-enabled)) (`boolean: false`) - Configures the Helm chart’s components @@ -527,6 +548,12 @@ Use these links to navigate to a particular top-level stanza. - `enableAgentMetrics` ((#v-global-metrics-enableagentmetrics)) (`boolean: false`) - Configures consul agent metrics. Only applicable if `global.metrics.enabled` is true. + - `disableAgentHostName` ((#v-global-metrics-disableagenthostname)) (`boolean: false`) - Set to true to stop prepending the machine's hostname to gauge-type metrics. Default is false. + Only applicable if `global.metrics.enabled` and `global.metrics.enableAgentMetrics` is true. + + - `enableHostMetrics` ((#v-global-metrics-enablehostmetrics)) (`boolean: false`) - Configures consul agent underlying host metrics. Default is false. + Only applicable if `global.metrics.enabled` and `global.metrics.enableAgentMetrics` is true. + - `agentMetricsRetentionTime` ((#v-global-metrics-agentmetricsretentiontime)) (`string: 1m`) - Configures the retention time for metrics in Consul clients and servers. This must be greater than 0 for Consul clients and servers to expose any metrics at all. @@ -539,6 +566,117 @@ Use these links to navigate to a particular top-level stanza. - `enableTelemetryCollector` ((#v-global-metrics-enabletelemetrycollector)) (`boolean: false`) - Configures the Helm chart’s components to forward envoy metrics for the Consul service mesh to the consul-telemetry-collector. This includes gateway metrics and sidecar metrics. + - `prefixFilter` ((#v-global-metrics-prefixfilter)) - Configures the list of filter rules to apply for allowing or blocking + metrics by prefix in the following format: + + A leading "+" will enable any metrics with the given prefix, and a leading "-" will block them. + If there is overlap between two rules, the more specific rule will take precedence. + Blocking will take priority if the same prefix is listed multiple times. + + - `allowList` ((#v-global-metrics-prefixfilter-allowlist)) (`array: []`) + + - `blockList` ((#v-global-metrics-prefixfilter-blocklist)) (`array: []`) + + - `datadog` ((#v-global-metrics-datadog)) - Configures consul integration configurations for datadog on kubernetes. + Only applicable if `global.metrics.enabled` and `global.metrics.enableAgentMetrics` is true. + + - `enabled` ((#v-global-metrics-datadog-enabled)) (`boolean: false`) - Enables datadog [Consul Autodiscovery Integration](https://docs.datadoghq.com/integrations/consul/?tab=containerized#metric-collection) + by configuring the required `ad.datadoghq.com/consul.checks` annotation. The following _Consul_ agent metrics/health statuses + are monitored by Datadog unless monitoring via OpenMetrics (Prometheus) or DogStatsD: + - Serf events and member flaps + - The Raft protocol + - DNS performance + - API Endpoints scraped: + - `/v1/agent/metrics?format=prometheus` + - `/v1/agent/self` + - `/v1/status/leader` + - `/v1/status/peers` + - `/v1/catalog/services` + - `/v1/health/service` + - `/v1/health/state/any` + - `/v1/coordinate/datacenters` + - `/v1/coordinate/nodes` + + Setting either `global.metrics.datadog.otlp.enabled=true` or `global.metrics.datadog.dogstatsd.enabled=true` disables the above checks + in lieu of metrics data collection via DogStatsD or by a customer OpenMetrics (Prometheus) collection endpoint. + + ~> **Note:** If you have a [dogstatsd_mapper_profile](https://docs.datadoghq.com/integrations/consul/?tab=host#dogstatsd) configured for Consul + residing on either your Datadog NodeAgent or ClusterAgent the default Consul agent metrics/health status checks will fail. If you do not desire + to utilize DogStatsD metrics emission from Consul, remove this configuration file, and restart your Datadog agent to permit the checks to run. + + - `openMetricsPrometheus` ((#v-global-metrics-datadog-openmetricsprometheus)) - Configures Kubernetes Prometheus/OpenMetrics auto-discovery annotations for use with Datadog. + This configuration is less common and more for advanced usage with custom metrics monitoring + configurations. Refer to the [Datadog documentation](https://docs.datadoghq.com/containers/kubernetes/prometheus/?tab=kubernetesadv2) for more details. + + - `enabled` ((#v-global-metrics-datadog-openmetricsprometheus-enabled)) (`boolean: false`) + + - `otlp` ((#v-global-metrics-datadog-otlp)) + + - `enabled` ((#v-global-metrics-datadog-otlp-enabled)) (`boolean: false`) - Enables forwarding of Consul's Telemetry Collector OTLP metrics for + ingestion by Datadog Agent. + + - `protocol` ((#v-global-metrics-datadog-otlp-protocol)) (`string: "http"`) - Protocol used for DataDog Endpoint OTLP ingestion. + + Valid protocol options are one of either: + + - "http": will forward to DataDog HTTP OTLP Node Agent Endpoint default - "0.0.0.0:4318" + - "grpc": will forward to DataDog gRPC OTLP Node Agent Endpoint default - "0.0.0.0:4317" + + - `dogstatsd` ((#v-global-metrics-datadog-dogstatsd)) - Configuration settings for DogStatsD metrics aggregation service + that is bundled with the Datadog Agent. + DogStatsD implements the StatsD protocol and adds a few Datadog-specific extensions: + - Histogram metric type + - Service checks + - Events + - Tagging + + - `enabled` ((#v-global-metrics-datadog-dogstatsd-enabled)) (`boolean: false`) + + - `socketTransportType` ((#v-global-metrics-datadog-dogstatsd-sockettransporttype)) (`string: "UDS"`) - Sets the socket transport type for dogstatsd: + - "UDS" (Unix Domain Socket): prefixes `unix://` to URL and appends path to socket (i.e., "unix:///var/run/datadog/dsd.socket") + If set, this will create the required [hostPath](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath) mount for + managing [DogStatsD with Unix Domain Socket on Kubernetes](https://docs.datadoghq.com/developers/dogstatsd/unix_socket/?tab=kubernetes). + The volume is mounted using the `DirectoryOrCreate` type, thereby setting `0755` permissions with the same kubelet group ownership. + + Applies the following `volumes` and `volumeMounts` to the consul-server stateful set consul containers: + + ```yaml + volumes: + - name: dsdsocket + hostPath: + path: /var/run/datadog + type: DirectoryOrCreate + volumeMounts: + - name: dsdsocket + mountPath: /var/run/datadog + readOnly: true + ``` + - "UDP" (User Datagram Protocol): assigns address to use `hostname/IP:Port` formatted URL for UDP transport to hostIP based + dogstatsd sink (i.e., 127.0.0.1:8125). HostIP of Datadog agent must be reachable and known to Consul server emitting metrics. + + - `dogstatsdAddr` ((#v-global-metrics-datadog-dogstatsd-dogstatsdaddr)) (`string: "/var/run/datadog/dsd.socket"`) - Sets URL path for dogstatsd: + + Can be either a path to unix domain socket or an IP Address or Hostname that's reachable from the + consul-server service, server containers. When using "UDS" the path will be appended. When using "UDP" + the path will be prepended to the specified `dogstatsdPort`. + + - `dogstatsdPort` ((#v-global-metrics-datadog-dogstatsd-dogstatsdport)) (`integer: 0`) - Configures IP based dogstatsd designated port that will be appended to "UDP" based transport socket IP/Hostname URL. + + If using a kubernetes service based address (i.e., datadog.default.svc.cluster.local), set this to 0 to + mitigate appending a port value to the dogstatsd address field. Resultant address would be "datadog.default.svc.cluster.local" with + default port setting, while appending a non-zero port would result in "172.10.23.6:8125" with a dogstatsdAddr value + of "172.10.23.6". + + - `dogstatsdTags` ((#v-global-metrics-datadog-dogstatsd-dogstatsdtags)) (`array: ["source:consul","consul_service:consul-server"]`) - Configures datadog [autodiscovery](https://docs.datadoghq.com/containers/kubernetes/log/?tab=operator#autodiscovery) + style [log integration](https://docs.datadoghq.com/integrations/consul/?tab=containerized#log-collection) + configuration for Consul. + + The default settings should handle most Consul Kubernetes deployment schemes. The resultant annotation + will reside on the consul-server statefulset as autodiscovery annotations. + (i.e., ad.datadoghq.com/consul.logs: ["source:consul","consul_service:consul-server", ""]) + + - `namespace` ((#v-global-metrics-datadog-namespace)) (`string: "default"`) - Namespace + - `imageConsulDataplane` ((#v-global-imageconsuldataplane)) (`string: hashicorp/consul-dataplane:`) - The name (and tag) of the consul-dataplane Docker image used for the connect-injected sidecar proxies and mesh, terminating, and ingress gateways. @@ -551,49 +689,53 @@ Use these links to navigate to a particular top-level stanza. - `consulAPITimeout` ((#v-global-consulapitimeout)) (`string: 5s`) - The time in seconds that the consul API client will wait for a response from the API before cancelling the request. - - `cloud` ((#v-global-cloud)) - Enables installing an HCP Consul self-managed cluster. + - `cloud` ((#v-global-cloud)) - Enables installing an HCP Consul Central self-managed cluster. Requires Consul v1.14+. - - `enabled` ((#v-global-cloud-enabled)) (`boolean: false`) - If true, the Helm chart will enable the installation of an HCP Consul - self-managed cluster. + - `enabled` ((#v-global-cloud-enabled)) (`boolean: false`) - If true, the Helm chart will link a [self-managed cluster to HCP](/hcp/docs/consul/self-managed). + This can either be used to [configure a new cluster](/hcp/docs/consul/self-managed/new) + or [link an existing one](/hcp/docs/consul/self-managed/existing). - - `resourceId` ((#v-global-cloud-resourceid)) - The name of the Kubernetes secret that holds the HCP resource id. + Note: this setting should not be enabled for [HCP Consul Dedicated clusters](/hcp/docs/consul/dedicated). + It is strictly for linking self-managed clusters. + + - `resourceId` ((#v-global-cloud-resourceid)) - The resource id of the HCP Consul Central cluster to link to. Eg: + organization/27109cd4-a309-4bf3-9986-e1d071914b18/project/fcef6c24-259d-4510-bb8d-1d812e120e34/hashicorp.consul.global-network-manager.cluster/consul-cluster This is required when global.cloud.enabled is true. - `secretName` ((#v-global-cloud-resourceid-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the resource id. - `secretKey` ((#v-global-cloud-resourceid-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the resource id. - - `clientId` ((#v-global-cloud-clientid)) - The name of the Kubernetes secret that holds the HCP cloud client id. + - `clientId` ((#v-global-cloud-clientid)) - The client id portion of a [service principal](/hcp/docs/hcp/admin/iam/service-principals#service-principals) with authorization to link the cluster + in global.cloud.resourceId to HCP Consul Central. This is required when global.cloud.enabled is true. - `secretName` ((#v-global-cloud-clientid-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the client id. - `secretKey` ((#v-global-cloud-clientid-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the client id. - - `clientSecret` ((#v-global-cloud-clientsecret)) - The name of the Kubernetes secret that holds the HCP cloud client secret. + - `clientSecret` ((#v-global-cloud-clientsecret)) - The client secret portion of a [service principal](/hcp/docs/hcp/admin/iam/service-principals#service-principals) with authorization to link the cluster + in global.cloud.resourceId to HCP Consul Central. This is required when global.cloud.enabled is true. - `secretName` ((#v-global-cloud-clientsecret-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the client secret. - `secretKey` ((#v-global-cloud-clientsecret-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the client secret. - - `apiHost` ((#v-global-cloud-apihost)) - The name of the Kubernetes secret that holds the HCP cloud client id. - This is optional when global.cloud.enabled is true. + - `apiHost` ((#v-global-cloud-apihost)) - The hostname of HCP's API. This setting is used for internal testing and validation. - `secretName` ((#v-global-cloud-apihost-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the api hostname. - `secretKey` ((#v-global-cloud-apihost-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the api hostname. - - `authUrl` ((#v-global-cloud-authurl)) - The name of the Kubernetes secret that holds the HCP cloud authorization url. - This is optional when global.cloud.enabled is true. + - `authUrl` ((#v-global-cloud-authurl)) - The URL of HCP's auth API. This setting is used for internal testing and validation. - `secretName` ((#v-global-cloud-authurl-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the authorization url. - `secretKey` ((#v-global-cloud-authurl-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the authorization url. - - `scadaAddress` ((#v-global-cloud-scadaaddress)) - The name of the Kubernetes secret that holds the HCP cloud scada address. - This is optional when global.cloud.enabled is true. + - `scadaAddress` ((#v-global-cloud-scadaaddress)) - The address of HCP's scada service. This setting is used for internal testing and validation. - `secretName` ((#v-global-cloud-scadaaddress-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the scada address. @@ -622,6 +764,15 @@ Use these links to navigate to a particular top-level stanza. ] ``` + - `experiments` ((#v-global-experiments)) (`array: []`) - Consul feature flags that will be enabled across components. + Supported feature flags: + + Example: + + ```yaml + experiments: [ "" ] + ``` + ### server ((#h-server)) - `server` ((#v-server)) - Server, when enabled, configures a server cluster to run. This should @@ -632,6 +783,8 @@ Use these links to navigate to a particular top-level stanza. Consul server cluster. If you're running Consul externally and want agents within Kubernetes to join that cluster, this should probably be false. + - `logLevel` ((#v-server-loglevel)) (`string: ""`) - Override global log verbosity level. One of "trace", "debug", "info", "warn", or "error". + - `image` ((#v-server-image)) (`string: null`) - The name of the Docker image (including any tag) for the containers running Consul server agents. @@ -723,12 +876,29 @@ Use these links to navigate to a particular top-level stanza. contains best practices and recommendations for selecting suitable hardware sizes for your Consul servers. + - `persistentVolumeClaimRetentionPolicy` ((#v-server-persistentvolumeclaimretentionpolicy)) (`map`) - The [Persistent Volume Claim (PVC) retention policy](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#persistentvolumeclaim-retention) + controls if and how PVCs are deleted during the lifecycle of a StatefulSet. + WhenDeleted specifies what happens to PVCs created from StatefulSet VolumeClaimTemplates when the StatefulSet is deleted, + and WhenScaled specifies what happens to PVCs created from StatefulSet VolumeClaimTemplates when the StatefulSet is scaled down. + + Example: + + ```yaml + persistentVolumeClaimRetentionPolicy: + whenDeleted: Retain + whenScaled: Retain + ``` + - `connect` ((#v-server-connect)) (`boolean: true`) - This will enable/disable [service mesh](/consul/docs/connect). Setting this to true _will not_ automatically secure pod communication, this setting will only enable usage of the feature. Consul will automatically initialize a new CA and set of certificates. Additional service mesh settings can be configured by setting the `server.extraConfig` value or by applying [configuration entries](/consul/docs/connect/config-entries). + - `enableAgentDebug` ((#v-server-enableagentdebug)) (`boolean: false`) - When set to true, enables Consul to report additional debugging information, including runtime profiling (pprof) data. + This setting is only required for clusters without ACL enabled. Sets `enable_debug` in server agent config to `true`. + If you change this setting, you must restart the agent for the change to take effect. Default is false. + - `serviceAccount` ((#v-server-serviceaccount)) - `annotations` ((#v-server-serviceaccount-annotations)) (`string: null`) - This value defines additional annotations for the server service account. This should be formatted as a multi-line @@ -789,8 +959,14 @@ Use these links to navigate to a particular top-level stanza. cluster. If enabled, it only registers the budget so long as the server cluster is enabled. To disable, set to `false`. - - `maxUnavailable` ((#v-server-disruptionbudget-maxunavailable)) (`integer: null`) - The maximum number of unavailable pods. By default, this will be - automatically computed based on the `server.replicas` value to be `(n/2)-1`. + - `maxUnavailable` ((#v-server-disruptionbudget-maxunavailable)) (`integer: null`) - The maximum number of unavailable pods. In most cases you should not change this as it is automatically set to + the correct number when left as null. This setting has been kept to preserve backwards compatibility. + + By default, this is set to 1 internally in the chart. When server pods are stopped gracefully, they leave the Raft + consensus pool. When running an odd number of servers, one server leaving the pool does not change the quorum + size, and so fault tolerance is not affected. However, if more than one server were to leave the pool, the quorum + size would change. That's why this is set to 1 internally and should not be changed in most cases. + If you need to set this to `0`, you will need to add a --set 'server.disruptionBudget.maxUnavailable=0'` flag to the helm chart installation command because of a limitation in the Helm templating language. @@ -1103,13 +1279,13 @@ Use these links to navigate to a particular top-level stanza. Note: If enabling clients, `client.join` must also be set to the hosts that should be used to join the cluster. In most cases, the `client.join` values should be the same, however, they may be different if you - wish to use separate hosts for the HTTPS connections. + wish to use separate hosts for the HTTPS connections. `tlsServerName` is required if TLS is enabled and 'hosts' is not a DNS name. - `httpsPort` ((#v-externalservers-httpsport)) (`integer: 8501`) - The HTTPS port of the Consul servers. - `grpcPort` ((#v-externalservers-grpcport)) (`integer: 8502`) - The GRPC port of the Consul servers. - - `tlsServerName` ((#v-externalservers-tlsservername)) (`string: null`) - The server name to use as the SNI host header when connecting with HTTPS. + - `tlsServerName` ((#v-externalservers-tlsservername)) (`string: null`) - The server name to use as the SNI host header when connecting with HTTPS. This name also appears as the hostname in the server certificate's subject field. - `useSystemRoots` ((#v-externalservers-usesystemroots)) (`boolean: false`) - If true, consul-k8s-control-plane components will ignore the CA set in `global.tls.caCert` when making HTTPS calls to Consul servers and @@ -1145,6 +1321,8 @@ Use these links to navigate to a particular top-level stanza. the resources necessary for a Consul client on every Kubernetes node. This _does not_ require `server.enabled`, since the agents can be configured to join an external cluster. + - `logLevel` ((#v-client-loglevel)) (`string: ""`) - Override global log verbosity level. One of "trace", "debug", "info", "warn", or "error". + - `image` ((#v-client-image)) (`string: null`) - The name of the Docker image (including any tag) for the containers running Consul client agents. @@ -1606,6 +1784,9 @@ Use these links to navigate to a particular top-level stanza. or may not be broadly accessible depending on your Kubernetes cluster. Set this to false to skip syncing ClusterIP services. + - `syncLoadBalancerEndpoints` ((#v-synccatalog-syncloadbalancerendpoints)) (`boolean: false`) - If true, LoadBalancer service endpoints instead of ingress addresses will be synced to Consul. + If false, LoadBalancer endpoints are not synced to Consul. + - `ingress` ((#v-synccatalog-ingress)) - `enabled` ((#v-synccatalog-ingress-enabled)) (`boolean: false`) - Syncs the hostname from a Kubernetes Ingress resource to service registrations @@ -1742,6 +1923,10 @@ Use these links to navigate to a particular top-level stanza. These CRDs can clash with existing Gateway API CRDs if they are already installed in your cluster. If this setting is false, you will need to install the Gateway API CRDs manually. + - `manageNonStandardCRDs` ((#v-connectinject-apigateway-managenonstandardcrds)) (`boolean: false`) - Enables Consul on Kubernets to manage only the non-standard CRDs used for Gateway API. If manageExternalCRDs is true + then all CRDs will be installed; otherwise, if manageNonStandardCRDs is true then only TCPRoute, GatewayClassConfig and MeshService + will be installed. + - `managedGatewayClass` ((#v-connectinject-apigateway-managedgatewayclass)) - Configuration settings for the GatewayClass installed by Consul on Kubernetes. - `nodeSelector` ((#v-connectinject-apigateway-managedgatewayclass-nodeselector)) (`string: null`) - This value defines [`nodeSelector`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) @@ -1772,6 +1957,17 @@ Use these links to navigate to a particular top-level stanza. - external-dns.alpha.kubernetes.io/hostname ``` + - `metrics` ((#v-connectinject-apigateway-managedgatewayclass-metrics)) - Metrics settings for gateways created with this gateway class configuration. + + - `enabled` ((#v-connectinject-apigateway-managedgatewayclass-metrics-enabled)) (`boolean: -`) - This value enables or disables metrics collection on a gateway, overriding the global gateway metrics collection settings. + + - `port` ((#v-connectinject-apigateway-managedgatewayclass-metrics-port)) (`int: null`) - This value sets the port to use for scraping gateway metrics via prometheus, defaults to 20200 if not set. Must be in the port + range of 1024-65535. + + - `path` ((#v-connectinject-apigateway-managedgatewayclass-metrics-path)) (`string: null`) - This value sets the path to use for scraping gateway metrics via prometheus, defaults to /metrics if not set. + + - `resources` ((#v-connectinject-apigateway-managedgatewayclass-resources)) (`map`) - The resource settings for Pods handling traffic for Gateway API. + - `deployment` ((#v-connectinject-apigateway-managedgatewayclass-deployment)) - This value defines the number of pods to deploy for each Gateway as well as a min and max number of pods for all Gateways - `defaultInstances` ((#v-connectinject-apigateway-managedgatewayclass-deployment-defaultinstances)) (`integer: 1`) @@ -1780,6 +1976,14 @@ Use these links to navigate to a particular top-level stanza. - `minInstances` ((#v-connectinject-apigateway-managedgatewayclass-deployment-mininstances)) (`integer: 1`) + - `openshiftSCCName` ((#v-connectinject-apigateway-managedgatewayclass-openshiftsccname)) (`string: restricted-v2`) - The name of the OpenShift SecurityContextConstraints resource to use for Gateways. + Only applicable if `global.openshift.enabled` is true. + + - `mapPrivilegedContainerPorts` ((#v-connectinject-apigateway-managedgatewayclass-mapprivilegedcontainerports)) (`integer: 0`) - This value defines the amount we will add to privileged container ports on gateways that use this class. + This is useful if you don't want to give your containers extra permissions to run privileged ports. + Example: The gateway listener is defined on port 80, but the underlying value of the port on the container + will be the 80 + the number defined below. + - `serviceAccount` ((#v-connectinject-apigateway-serviceaccount)) - Configuration for the ServiceAccount created for the api-gateway component - `annotations` ((#v-connectinject-apigateway-serviceaccount-annotations)) (`string: null`) - This value defines additional annotations for the client service account. This should be formatted as a multi-line @@ -1791,8 +1995,6 @@ Use these links to navigate to a particular top-level stanza. "sample/annotation2": "bar" ``` - - `resources` ((#v-connectinject-apigateway-resources)) (`map`) - The resource settings for Pods handling traffic for Gateway API. - - `cni` ((#v-connectinject-cni)) - Configures consul-cni plugin for Consul Service mesh services - `enabled` ((#v-connectinject-cni-enabled)) (`boolean: false`) - If true, then all traffic redirection setup uses the consul-cni plugin. @@ -1926,7 +2128,7 @@ Use these links to navigate to a particular top-level stanza. - `imageConsul` ((#v-connectinject-imageconsul)) (`string: null`) - The Docker image for Consul to use when performing Connect injection. Defaults to global.image. - - `logLevel` ((#v-connectinject-loglevel)) (`string: ""`) - Override global log verbosity level. One of "debug", "info", "warn", or "error". + - `logLevel` ((#v-connectinject-loglevel)) (`string: ""`) - Sets the `logLevel` for the `consul-dataplane` sidecar and the `consul-connect-inject-init` container. When set, this value overrides the global log verbosity level. One of "debug", "info", "warn", or "error". - `serviceAccount` ((#v-connectinject-serviceaccount)) @@ -2108,18 +2310,30 @@ Use these links to navigate to a particular top-level stanza. - `consul.hashicorp.com/enable-sidecar-proxy-lifecycle` - `consul.hashicorp.com/enable-sidecar-proxy-shutdown-drain-listeners` - `consul.hashicorp.com/sidecar-proxy-lifecycle-shutdown-grace-period-seconds` + - `consul.hashicorp.com/sidecar-proxy-lifecycle-startup-grace-period-seconds` - `consul.hashicorp.com/sidecar-proxy-lifecycle-graceful-port` - `consul.hashicorp.com/sidecar-proxy-lifecycle-graceful-shutdown-path` + - `consul.hashicorp.com/sidecar-proxy-lifecycle-graceful-startup-path` + + - `defaultEnabled` ((#v-connectinject-sidecarproxy-lifecycle-defaultenabled)) (`boolean: true`) - - `defaultEnabled` ((#v-connectinject-sidecarproxy-lifecycle-defaultenabled)) (`boolean: true`) + - `defaultEnableShutdownDrainListeners` ((#v-connectinject-sidecarproxy-lifecycle-defaultenableshutdowndrainlisteners)) (`boolean: true`) - - `defaultEnableShutdownDrainListeners` ((#v-connectinject-sidecarproxy-lifecycle-defaultenableshutdowndrainlisteners)) (`boolean: true`) + - `defaultShutdownGracePeriodSeconds` ((#v-connectinject-sidecarproxy-lifecycle-defaultshutdowngraceperiodseconds)) (`integer: 30`) - - `defaultShutdownGracePeriodSeconds` ((#v-connectinject-sidecarproxy-lifecycle-defaultshutdowngraceperiodseconds)) (`integer: 30`) + - `defaultStartupGracePeriodSeconds` ((#v-connectinject-sidecarproxy-lifecycle-defaultstartupgraceperiodseconds)) (`integer: 0`) - - `defaultGracefulPort` ((#v-connectinject-sidecarproxy-lifecycle-defaultgracefulport)) (`integer: 20600`) + - `defaultGracefulPort` ((#v-connectinject-sidecarproxy-lifecycle-defaultgracefulport)) (`integer: 20600`) - - `defaultGracefulShutdownPath` ((#v-connectinject-sidecarproxy-lifecycle-defaultgracefulshutdownpath)) (`string: /graceful_shutdown`) + - `defaultGracefulShutdownPath` ((#v-connectinject-sidecarproxy-lifecycle-defaultgracefulshutdownpath)) (`string: /graceful_shutdown`) + + - `defaultGracefulStartupPath` ((#v-connectinject-sidecarproxy-lifecycle-defaultgracefulstartuppath)) (`string: /graceful_startup`) + + - `defaultStartupFailureSeconds` ((#v-connectinject-sidecarproxy-defaultstartupfailureseconds)) (`integer: 0`) - Configures how long the k8s startup probe will wait before the proxy is considered to be unhealthy and the container is restarted. + A value of zero disables the probe. + + - `defaultLivenessFailureSeconds` ((#v-connectinject-sidecarproxy-defaultlivenessfailureseconds)) (`integer: 0`) - Configures how long the k8s liveness probe will wait before the proxy is considered to be unhealthy and the container is restarted. + A value of zero disables the probe. - `initContainer` ((#v-connectinject-initcontainer)) (`map`) - The resource settings for the Connect injected init container. If null, the resources won't be set for the initContainer. The defaults are optimized for developer instances of @@ -2148,6 +2362,8 @@ Use these links to navigate to a particular top-level stanza. This setting is required for [Cluster Peering](/consul/docs/connect/cluster-peering/k8s). Requirements: consul 1.6.0+ if using `global.acls.manageSystemACLs``. + - `logLevel` ((#v-meshgateway-loglevel)) (`string: ""`) - Override global log verbosity level for mesh-gateway-deployment pods. One of "trace", "debug", "info", "warn", or "error". + - `replicas` ((#v-meshgateway-replicas)) (`integer: 1`) - Number of replicas for the Deployment. - `wanAddress` ((#v-meshgateway-wanaddress)) - What gets registered as WAN address for the gateway. @@ -2311,6 +2527,8 @@ Use these links to navigate to a particular top-level stanza. - `enabled` ((#v-ingressgateways-enabled)) (`boolean: false`) - Enable ingress gateway deployment. Requires `connectInject.enabled=true`. + - `logLevel` ((#v-ingressgateways-loglevel)) (`string: ""`) - Override global log verbosity level for ingress-gateways-deployment pods. One of "trace", "debug", "info", "warn", or "error". + - `defaults` ((#v-ingressgateways-defaults)) - Defaults sets default values for all gateway fields. With the exception of annotations, defining any of these values in the `gateways` list will override the default values provided here. Annotations will @@ -2423,8 +2641,9 @@ Use these links to navigate to a particular top-level stanza. - `gateways` ((#v-ingressgateways-gateways)) (`array`) - Gateways is a list of gateway objects. The only required field for each is `name`, though they can also contain any of the fields in - `defaults`. Values defined here override the defaults except in the - case of annotations where both will be applied. + `defaults`. You must provide a unique name for each ingress gateway. These names + must be unique across different namespaces. + Values defined here override the defaults, except in the case of annotations where both will be applied. - `name` ((#v-ingressgateways-gateways-name)) (`string: ingress-gateway`) @@ -2440,6 +2659,8 @@ Use these links to navigate to a particular top-level stanza. - `enabled` ((#v-terminatinggateways-enabled)) (`boolean: false`) - Enable terminating gateway deployment. Requires `connectInject.enabled=true`. + - `logLevel` ((#v-terminatinggateways-loglevel)) (`string: ""`) - Override global log verbosity level. One of "trace", "debug", "info", "warn", or "error". + - `defaults` ((#v-terminatinggateways-defaults)) - Defaults sets default values for all gateway fields. With the exception of annotations, defining any of these values in the `gateways` list will override the default values provided here. Annotations will @@ -2543,119 +2764,6 @@ Use these links to navigate to a particular top-level stanza. - `name` ((#v-terminatinggateways-gateways-name)) (`string: terminating-gateway`) -### apiGateway ((#h-apigateway)) - -- `apiGateway` ((#v-apigateway)) - [DEPRECATED] Use connectInject.apiGateway instead. This stanza will be removed with the release of Consul 1.17 - Configuration settings for the Consul API Gateway integration - - - `enabled` ((#v-apigateway-enabled)) (`boolean: false`) - When true the helm chart will install the Consul API Gateway controller - - - `image` ((#v-apigateway-image)) (`string: null`) - Image to use for the api-gateway-controller pods and gateway instances - - ~> **Note:** Using API Gateway <= 0.4 with external servers requires setting `client.enabled: true`. - - - `imageEnvoy` ((#v-apigateway-imageenvoy)) (`string: envoyproxy/envoy:`) - The name (and tag) of the Envoy Docker image used for the - apiGateway. For other Consul compoenents, imageEnvoy has been replaced with Consul Dataplane. - - - `logLevel` ((#v-apigateway-loglevel)) (`string: info`) - Override global log verbosity level for api-gateway-controller pods. One of "debug", "info", "warn", or "error". - - - `managedGatewayClass` ((#v-apigateway-managedgatewayclass)) - Configuration settings for the optional GatewayClass installed by consul-k8s (enabled by default) - - - `enabled` ((#v-apigateway-managedgatewayclass-enabled)) (`boolean: true`) - When true a GatewayClass is configured to automatically work with Consul as installed by helm. - - - `nodeSelector` ((#v-apigateway-managedgatewayclass-nodeselector)) (`string: null`) - This value defines [`nodeSelector`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) - labels for gateway pod assignment, formatted as a multi-line string. - - Example: - - ```yaml - nodeSelector: | - beta.kubernetes.io/arch: amd64 - ``` - - - `tolerations` ((#v-apigateway-managedgatewayclass-tolerations)) (`string: null`) - Toleration settings for gateway pods created with the managed gateway class. - This should be a multi-line string matching the - [Tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. - - - `serviceType` ((#v-apigateway-managedgatewayclass-servicetype)) (`string: LoadBalancer`) - This value defines the type of service created for gateways (e.g. LoadBalancer, ClusterIP) - - - `useHostPorts` ((#v-apigateway-managedgatewayclass-usehostports)) (`boolean: false`) - This value toggles if the gateway ports should be mapped to host ports - - - `copyAnnotations` ((#v-apigateway-managedgatewayclass-copyannotations)) - Configuration settings for annotations to be copied from the Gateway to other child resources. - - - `service` ((#v-apigateway-managedgatewayclass-copyannotations-service)) (`string: null`) - This value defines a list of annotations to be copied from the Gateway to the Service created, formatted as a multi-line string. - - Example: - - ```yaml - service: - annotations: | - - external-dns.alpha.kubernetes.io/hostname - ``` - - - `deployment` ((#v-apigateway-managedgatewayclass-deployment)) (`map`) - This value defines the number of pods to deploy for each Gateway as well as a min and max number of pods for all Gateways - - Example: - - ```yaml - deployment: - defaultInstances: 3 - maxInstances: 8 - minInstances: 1 - ``` - - - `serviceAccount` ((#v-apigateway-serviceaccount)) - Configuration for the ServiceAccount created for the api-gateway component - - - `annotations` ((#v-apigateway-serviceaccount-annotations)) (`string: null`) - This value defines additional annotations for the client service account. This should be formatted as a multi-line - string. - - ```yaml - annotations: | - "sample/annotation1": "foo" - "sample/annotation2": "bar" - ``` - - - `controller` ((#v-apigateway-controller)) - Configuration for the api-gateway controller component - - - `replicas` ((#v-apigateway-controller-replicas)) (`integer: 1`) - This value sets the number of controller replicas to deploy. - - - `annotations` ((#v-apigateway-controller-annotations)) (`string: null`) - Annotations to apply to the api-gateway-controller pods. - - ```yaml - annotations: | - "annotation-key": "annotation-value" - ``` - - - `priorityClassName` ((#v-apigateway-controller-priorityclassname)) (`string: ""`) - This value references an existing - Kubernetes [`priorityClassName`](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#pod-priority) - that can be assigned to api-gateway-controller pods. - - - `nodeSelector` ((#v-apigateway-controller-nodeselector)) (`string: null`) - This value defines [`nodeSelector`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) - labels for api-gateway-controller pod assignment, formatted as a multi-line string. - - Example: - - ```yaml - nodeSelector: | - beta.kubernetes.io/arch: amd64 - ``` - - - `tolerations` ((#v-apigateway-controller-tolerations)) (`string: null`) - This value defines the tolerations for api-gateway-controller pod, this should be a multi-line string matching the - [Tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. - - - `service` ((#v-apigateway-controller-service)) - Configuration for the Service created for the api-gateway-controller - - - `annotations` ((#v-apigateway-controller-service-annotations)) (`string: null`) - Annotations to apply to the api-gateway-controller service. - - ```yaml - annotations: | - "annotation-key": "annotation-value" - ``` - - - `resources` ((#v-apigateway-resources)) (`map`) - The resource settings for api gateway pods. - - - `initCopyConsulContainer` ((#v-apigateway-initcopyconsulcontainer)) (`map`) - The resource settings for the `copy-consul-bin` init container. - ### webhookCertManager ((#h-webhookcertmanager)) - `webhookCertManager` ((#v-webhookcertmanager)) - Configuration settings for the webhook-cert-manager @@ -2696,7 +2804,9 @@ Use these links to navigate to a particular top-level stanza. - `enabled` ((#v-telemetrycollector-enabled)) (`boolean: false`) - Enables the consul-telemetry-collector deployment - - `image` ((#v-telemetrycollector-image)) (`string: hashicorp/consul-telemetry-collector:0.0.1`) - The name of the Docker image (including any tag) for the containers running + - `logLevel` ((#v-telemetrycollector-loglevel)) (`string: ""`) - Override global log verbosity level. One of "trace", "debug", "info", "warn", or "error". + + - `image` ((#v-telemetrycollector-image)) (`string: hashicorp/consul-telemetry-collector:0.0.2`) - The name of the Docker image (including any tag) for the containers running the consul-telemetry-collector - `resources` ((#v-telemetrycollector-resources)) (`map`) - The resource settings for consul-telemetry-collector pods. @@ -2713,7 +2823,7 @@ Use these links to navigate to a particular top-level stanza. - `service` ((#v-telemetrycollector-service)) - - `annotations` ((#v-telemetrycollector-service-annotations)) (`string: null`) - This value defines additional annotations for the server service account. This should be formatted as a multi-line + - `annotations` ((#v-telemetrycollector-service-annotations)) (`string: null`) - This value defines additional annotations for the telemetry-collector's service account. This should be formatted as a multi-line string. ```yaml @@ -2735,17 +2845,37 @@ Use these links to navigate to a particular top-level stanza. - `cloud` ((#v-telemetrycollector-cloud)) - - `clientId` ((#v-telemetrycollector-cloud-clientid)) + - `resourceId` ((#v-telemetrycollector-cloud-resourceid)) - The resource id of the HCP Consul Central cluster to push metrics for. Eg: + `organization/27109cd4-a309-4bf3-9986-e1d071914b18/project/fcef6c24-259d-4510-bb8d-1d812e120e34/hashicorp.consul.global-network-manager.cluster/consul-cluster` + + This is used for HCP Consul Central-linked or HCP Consul Dedicated clusters where global.cloud.resourceId is unset. For example, when using externalServers + with HCP Consul Dedicated clusters or HCP Consul Central-linked clusters in a different admin partition. + + If global.cloud.resourceId is set, this should either be unset (defaulting to global.cloud.resourceId) or be the same as global.cloud.resourceId. + + - `secretName` ((#v-telemetrycollector-cloud-resourceid-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the resource id. + + - `secretKey` ((#v-telemetrycollector-cloud-resourceid-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the resource id. + + - `clientId` ((#v-telemetrycollector-cloud-clientid)) - The client id portion of a [service principal](/hcp/docs/hcp/admin/iam/service-principals#service-principals) with authorization to push metrics to HCP + + This is set in two scenarios: + - the service principal in global.cloud is unset + - the HCP UI provides a service principal with more narrowly scoped permissions that the service principal used in global.cloud + + - `secretName` ((#v-telemetrycollector-cloud-clientid-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the client id. - - `secretName` ((#v-telemetrycollector-cloud-clientid-secretname)) (`string: null`) + - `secretKey` ((#v-telemetrycollector-cloud-clientid-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the client id. - - `secretKey` ((#v-telemetrycollector-cloud-clientid-secretkey)) (`string: null`) + - `clientSecret` ((#v-telemetrycollector-cloud-clientsecret)) - The client secret portion of a [service principal](/hcp/docs/hcp/admin/iam/service-principals#service-principals) with authorization to push metrics to HCP. - - `clientSecret` ((#v-telemetrycollector-cloud-clientsecret)) + This is set in two scenarios: + - the service principal in global.cloud is unset + - the HCP UI provides a service principal with more narrowly scoped permissions that the service principal used in global.cloud - - `secretName` ((#v-telemetrycollector-cloud-clientsecret-secretname)) (`string: null`) + - `secretName` ((#v-telemetrycollector-cloud-clientsecret-secretname)) (`string: null`) - The name of the Kubernetes secret that holds the client secret. - - `secretKey` ((#v-telemetrycollector-cloud-clientsecret-secretkey)) (`string: null`) + - `secretKey` ((#v-telemetrycollector-cloud-clientsecret-secretkey)) (`string: null`) - The key within the Kubernetes secret that holds the client secret. - `initContainer` ((#v-telemetrycollector-initcontainer)) @@ -2755,7 +2885,7 @@ Use these links to navigate to a particular top-level stanza. - `priorityClassName` ((#v-telemetrycollector-priorityclassname)) (`string: ""`) - Optional priorityClassName. - - `extraEnvironmentVars` ((#v-telemetrycollector-extraenvironmentvars)) (`map`) - A list of extra environment variables to set within the stateful set. + - `extraEnvironmentVars` ((#v-telemetrycollector-extraenvironmentvars)) (`map`) - A list of extra environment variables to set within the deployment. These could be used to include proxy settings required for cloud auto-join feature, in case kubernetes cluster is behind egress http proxies. Additionally, it could be used to configure custom consul parameters. diff --git a/website/content/docs/k8s/installation/install-cli.mdx b/website/content/docs/k8s/installation/install-cli.mdx index 0621b9459ae9..0665641755ed 100644 --- a/website/content/docs/k8s/installation/install-cli.mdx +++ b/website/content/docs/k8s/installation/install-cli.mdx @@ -263,7 +263,8 @@ $ consul-k8s install -f values.yaml global: openshift: enabled: true - +``` + Refer to [`openshift` in the Helm chart reference](/consul/docs/k8s/helm#v-global-openshift) for additional information. ## Check the Consul cluster status diff --git a/website/content/docs/k8s/installation/install.mdx b/website/content/docs/k8s/installation/install.mdx index 35eefff333ed..30dab8c19d8f 100644 --- a/website/content/docs/k8s/installation/install.mdx +++ b/website/content/docs/k8s/installation/install.mdx @@ -104,7 +104,7 @@ NAME: consul ... ``` -### Install Consul on OpenShift clusters +### Install Consul on Red Hat OpenShift [Red Hat OpenShift](https://www.redhat.com/en/technologies/cloud-computing/openshift) is a security-conscious, opinionated wrapper for Kubernetes. To install Consul on OpenShift-managed Kubernetes, set `global.openshift.enabled=true` in your [custom installation](#custom-installation) values file: @@ -114,7 +114,41 @@ global: enabled: true ``` -Refer to [`openshift` in the Helm chart reference](/consul/docs/k8s/helm#v-global-openshift) for additional information. +Refer to [`openshift` in the Helm chart reference](/consul/docs/k8s/helm#v-global-openshift) for additional information regarding the OpenShift stanza. In addition, refer to the [Deploy Consul on RedHat OpenShift tutorial](/consul/tutorials/kubernetes/kubernetes-openshift-red-hat) for a complete working example that deploys Consul Service Mesh using Red Hat Certified UBI images. + +### Install Consul on GKE Autopilot + +GKE Autopilot provides a fully managed environment for containerized workloads and requires the Consul CNI plugin to be installed. Refer to [Enable the Consul CNI plugin](#enable-the-consul-cni-plugin) for a full reference on how to enable the CNI plugin. + +By default, GKE Autopilot also installs [Gateway API resources](https://gateway-api.sigs.k8s.io), so we recommend customizing the `connectInject.apiGateway` stanza to accommodate for the pre-installed Gateway API CRDs. + +The following working example enables both Consul Service Mesh and Consul API Gateway on GKE Autopilot. Refer to [`connectInject.agiGateway` in the Helm chart reference](https://developer.hashicorp.com/consul/docs/k8s/helm#v-connectinject-apigateway) for additional information. + + + + ```yaml + global: + name: consul + connectInject: + enabled: true + apiGateway: + manageExternalCRDs: false + manageNonStandardCRDs: true + cni: + enabled: true + logLevel: debug + cniBinDir: "/home/kubernetes/bin" + cniNetDir: "/etc/cni/net.d" + server: + resources: + requests: + memory: "500Mi" + cpu: "500m" + limits: + memory: "500Mi" + cpu: "500m" + ``` + ### Enable the Consul CNI plugin diff --git a/website/content/docs/k8s/k8s-cli.mdx b/website/content/docs/k8s/k8s-cli.mdx index df986a5885ec..005363ec3cff 100644 --- a/website/content/docs/k8s/k8s-cli.mdx +++ b/website/content/docs/k8s/k8s-cli.mdx @@ -35,6 +35,7 @@ You can use the following commands with `consul-k8s`. - [`proxy list`](#proxy-list): List all Pods running proxies managed by Consul. - [`proxy read`](#proxy-read): Inspect the Envoy configuration for a given Pod. - [`proxy log`](#proxy-log): Inspect and modify the Envoy logging configuration for a given Pod. + - [`proxy stats`](#proxy-stats): View the Envoy cluster stats for a given Pod. - [`status`](#status): Check the status of a Consul installation on Kubernetes. - [`troubleshoot`](#troubleshoot): Troubleshoot Consul service mesh and networking issues from a given pod. - [`uninstall`](#uninstall): Uninstall Consul deployment. @@ -150,6 +151,7 @@ Consul in your Kubernetes Cluster. - [`proxy list`](#proxy-list): List all Pods running proxies managed by Consul. - [`proxy read`](#proxy-read): Inspect the Envoy configuration for a given Pod. - [`proxy log`](#proxy-log): Inspect and modify the Envoy logging configuration for a given Pod. +- [`proxy stats`](#proxy-stats): View the Envoy cluster stats for a given Pod. ### `proxy list` @@ -161,6 +163,7 @@ $ consul-k8s proxy list | ------------------------------------ | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | `-all-namespaces`, `-A` | `Boolean` List pods in all Kubernetes namespaces. | `false` | | `-namespace`, `-n` | `String` The Kubernetes namespace to list proxies in. | Current [kubeconfig](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) namespace. | +| `-output-format`, `-o` | `String` If set to json, outputs the result in json format, else table format | `table` Refer to the [Global Options](#global-options) for additional options that you can use when installing Consul on Kubernetes. @@ -229,6 +232,46 @@ default client-767ccfc8f9-ggrtx Sidecar default frontend-676564547c-v2mfq Sidecar ``` +Display all Pods across all namespaces that run proxies managed by Consul in JSON format + +```shell-session +$ consul-k8s proxy list -A -o json +Namespace: All namespaces + +[ + { + "Name": "frontend-6fd97b8fb5-spqb8", + "Namespace": "default", + "Type": "Sidecar" + }, + { + "Name": "nginx-6d7469694f-p5wrz", + "Namespace": "default", + "Type": "Sidecar" + }, + { + "Name": "payments-667d87bf95-ktb8n", + "Namespace": "default", + "Type": "Sidecar" + }, + { + "Name": "product-api-7c4d77c7c9-g4g2b", + "Namespace": "default", + "Type": "Sidecar" + }, + { + "Name": "product-api-db-685c844cb-k5l8f", + "Namespace": "default", + "Type": "Sidecar" + }, + { + "Name": "public-api-567d949866-cgksl", + "Namespace": "default", + "Type": "Sidecar" + } +] +``` + ### `proxy read` The `proxy read` command allows you to inspect the configuration of Envoy proxies running on a given Pod. @@ -781,6 +824,86 @@ file info kafka info lua info ``` + +### `proxy stats` + +The `proxy stats` command allows you to inspect the Envoy cluster stats for Envoy proxies running on a given Pod. + +```shell-session +$ consul-k8s proxy stats +``` +| Flag | Description | Default | +| ------------------------------------ | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | +| `-namespace`, `-n` | `String` The Kubernetes namespace to list proxies in. | Current [kubeconfig](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) namespace. | + +Refer to the [Global Options](#global-options) for additional options that you can use +when installing Consul on Kubernetes. + +#### Example Commands + +Display the Envoy cluster stats in a given pod in default namespace. + +```shell-session +$ consul-k8s proxy stats product-api-7c4d77c7c9-6slnl +cluster.frontend.default.dc1.internal.4b11bae3-b8ca-ee63-89bc-428cbfa6ef60.consul.version_text: "" +cluster.nginx.default.dc1.internal.4b11bae3-b8ca-ee63-89bc-428cbfa6ef60.consul.version_text: "" +cluster.payments.default.dc1.internal.4b11bae3-b8ca-ee63-89bc-428cbfa6ef60.consul.version_text: "" +cluster.product-api-db.default.dc1.internal.4b11bae3-b8ca-ee63-89bc-428cbfa6ef60.consul.version_text: "" +cluster.public-api.default.dc1.internal.4b11bae3-b8ca-ee63-89bc-428cbfa6ef60.consul.version_text: "" +cluster_manager.cds.version_text: "" +control_plane.identifier: "" +listener_manager.lds.version_text: "" +cluster.consul-dataplane.assignment_stale: 0 +cluster.consul-dataplane.assignment_timeout_received: 0 +cluster.consul-dataplane.bind_errors: 0 +cluster.consul-dataplane.circuit_breakers.default.cx_open: 0 +cluster.consul-dataplane.circuit_breakers.default.cx_pool_open: 0 +cluster.consul-dataplane.circuit_breakers.default.rq_open: 0 +cluster.consul-dataplane.circuit_breakers.default.rq_pending_open: 0 +cluster.consul-dataplane.circuit_breakers.default.rq_retry_open: 0 +cluster.consul-dataplane.circuit_breakers.high.cx_open: 0 +cluster.consul-dataplane.circuit_breakers.high.cx_pool_open: 0 +cluster.consul-dataplane.circuit_breakers.high.rq_open: 0 +cluster.consul-dataplane.circuit_breakers.high.rq_pending_open: 0 +cluster.consul-dataplane.circuit_breakers.high.rq_retry_open: 0 +cluster.consul-dataplane.default.total_match_count: 1 +cluster.consul-dataplane.http2.deferred_stream_close: 0 +cluster.consul-dataplane.http2.dropped_headers_with_underscores: 0 +cluster.consul-dataplane.http2.header_overflow: 0 +cluster.consul-dataplane.http2.headers_cb_no_stream: 0 +cluster.consul-dataplane.http2.inbound_empty_frames_flood: 0 +cluster.consul-dataplane.http2.inbound_priority_frames_flood: 0 +......... +``` + +Display the Envoy cluster stats in a given pod in different namespace. + +```shell-session +$ consul-k8s proxy stats public-api-567d949866-452xc -n consul +cluster.frontend.default.dc1.internal.4b11bae3-b8ca-ee63-89bc-428cbfa6ef60.consul.version_text: "" +cluster.nginx.default.dc1.internal.4b11bae3-b8ca-ee63-89bc-428cbfa6ef60.consul.version_text: "" +cluster.payments.default.dc1.internal.4b11bae3-b8ca-ee63-89bc-428cbfa6ef60.consul.version_text: "" +cluster.product-api-db.default.dc1.internal.4b11bae3-b8ca-ee63-89bc-428cbfa6ef60.consul.version_text: "" +cluster.product-api.default.dc1.internal.4b11bae3-b8ca-ee63-89bc-428cbfa6ef60.consul.version_text: "" +cluster_manager.cds.version_text: "" +control_plane.identifier: "" +listener_manager.lds.version_text: "" +cluster.consul-dataplane.assignment_stale: 0 +cluster.consul-dataplane.assignment_timeout_received: 0 +cluster.consul-dataplane.bind_errors: 0 +cluster.consul-dataplane.circuit_breakers.default.cx_open: 0 +cluster.consul-dataplane.circuit_breakers.default.cx_pool_open: 0 +cluster.consul-dataplane.circuit_breakers.default.rq_open: 0 +cluster.consul-dataplane.circuit_breakers.default.rq_pending_open: 0 +cluster.consul-dataplane.circuit_breakers.default.rq_retry_open: 0 +cluster.consul-dataplane.circuit_breakers.high.cx_open: 0 +cluster.consul-dataplane.circuit_breakers.high.cx_pool_open: 0 +cluster.consul-dataplane.circuit_breakers.high.rq_open: 0 +cluster.consul-dataplane.circuit_breakers.high.rq_pending_open: 0 +cluster.consul-dataplane.circuit_breakers.high.rq_retry_open: 0 +......... +``` + ### `status` The `status` command provides an overall status summary of the Consul on Kubernetes installation. It also provides the configuration that was used to deploy Consul K8s and information about the health of Consul servers and clients. This command does not take in any flags. diff --git a/website/content/docs/k8s/multiport/configure.mdx b/website/content/docs/k8s/multiport/configure.mdx deleted file mode 100644 index 8beaf8339d1c..000000000000 --- a/website/content/docs/k8s/multiport/configure.mdx +++ /dev/null @@ -1,489 +0,0 @@ ---- -layout: docs -page_title: Configure multi-port services -description: Learn how to enable the v2 catalog and configure services to support multiple ports in Consul on Kubernetes. You can configure multiple ports on a single service or multiple services and ports in a single container. ---- - -# Configure multi-port services - - - -Multi-port services are part of a beta release. This documentation supports testing and development scenarios. Do not use multi-port services or the v2 catalog API in secure production environments. - - - -This page describes the process for integrating a service that uses multiple ports in a single container when running Consul on Kubernetes deployments. It includes example configurations to demonstrate an end-to-end deployment test of Consul's multi-port features. - -## Prerequisites - -Registering multi-port services with Consul requires Kubernetes. Multi-port services are not supported on VM deployments. - -The following software versions are required: - -- Consul v1.17.0 -- `consul-k8s` CLI v1.3.0+ or `hashicorp/consul` Helm chart release v1.3.0+ - -For more information about upgrading versions for `consul-k8s` and Helm charts, refer to [Update the Consul K8s CLI](/consul/docs/k8s/upgrade/upgrade-cli) and [Upgrade Helm chart version](/consul/docs/k8s/upgrade#upgrade-helm-chart-version). - -There are additional requirements for service mesh proxies in transparent proxy mode. This mode enables queries through Kube DNS instead of Consul DNS over permissive mTLS settings. For more information about the steps to configure global settings and enable permissive mTLS mode before registering a service, refer to the [onboard services in transparent mode workflow](/consul/docs/k8s/connect/onboarding-tproxy-mode#workflow). - -## Enable the v2 catalog - -To enable the v2 catalog and its support for multi-port services, set `global.experiments: ["resource-apis"]` and `ui.enabled: false`. The following example includes these parameters in a Helm chart with minimal required configurations for the Consul installation: - - - -```yaml -global: - enabled: true - name: consul - image: hashicorp/consul:1.17.0-rc1 - datacenter: dc1 - tls: - enabled: true - experiments: ["resource-apis"] -server: - enabled: true - replicas: 1 -connectInject: - enabled: true -ui: - enabled: false -``` - - - -Then install Consul to your Kubernetes cluster using either the `consul-k8s` CLI or Helm. - - - - - -For platforms other than Mac OSX amd64, refer to [Install a previous version](/consul/docs/k8s/installation/install-cli#install-a-previous-version) for instructions on how to install a specific version of the `consul-k8s` CLI prior to running `consul-k8s install`. - -```shell-session -$ export VERSION=1.3.0-rc1 && \ - curl --location "https://releases.hashicorp.com/consul-k8s/${VERSION}/consul-k8s_${VERSION}_darwin_amd64.zip" --output consul-k8s-cli.zip -$ unzip -o consul-k8s-cli.zip -d ~/consul-k8s -$ export PATH=$PATH:$HOME/consul-k8s -$ consul-k8s install -config-file=values.yaml -``` - - - - - -```shell-session -$ helm install consul hashicorp/consul --create-namespace --namespace consul --version 1.3.0-rc1 --values values.yaml -``` - - - - -## Define the multi-port service - -Consul's v2 catalog supports two methods for defining multi-port services in Kubernetes: - -- **Method 1**: Define a single Kubernetes Service that exposes multiple ports -- **Method 2**: Define multiple Kubernetes Services that expose individual ports - -These methods affect how the Services are addressed in Kubernetes. - -Each tab in the following example contains a configuration that defines an `api` service using one of these methods. Both definitions schedule a Pod running two containers that each support traffic to one of the ports exposed by the Service. In `Method 1`, both services are addressed using `api` because both services are exposed by a single service. In `Method 2`, `api` and `api-admin` are defined as separate services and can be addressed using distinct names. - - - - - - - -```yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: api ---- -apiVersion: v1 -kind: Service -metadata: - name: api -spec: - selector: - app: api - ports: - - name: api - port: 80 - targetPort: api - - name: admin - port: 90 - targetPort: admin ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: api -spec: - replicas: 1 - selector: - matchLabels: - app: api - template: - metadata: - labels: - app: api - annotations: - "consul.hashicorp.com/mesh-inject": "true" - "consul.hashicorp.com/transparent-proxy": "true" - spec: - containers: - - name: api - image: docker.mirror.hashicorp.services/hashicorp/http-echo:latest - args: - - -text="hello world" - - -listen=:8080 - ports: - - containerPort: 8080 - name: api - - name: api-admin - image: docker.mirror.hashicorp.services/hashicorp/http-echo:latest - args: - - -text="hello world from 9090 admin" - - -listen=:9090 - ports: - - containerPort: 9090 - name: admin - serviceAccountName: api -``` - - - - - - - - -```yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: api ---- -apiVersion: v1 -kind: Service -metadata: - name: api -spec: - selector: - app: api - ports: - - name: api - port: 80 - targetPort: api ---- -apiVersion: v1 -kind: Service -metadata: - name: api-admin -spec: - selector: - app: api - ports: - - name: admin - port: 90 - targetPort: admin ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: api -spec: - replicas: 1 - selector: - matchLabels: - app: api - template: - metadata: - labels: - app: api - annotations: - "consul.hashicorp.com/mesh-inject": "true" - "consul.hashicorp.com/transparent-proxy": "true" - spec: - containers: - - name: api - image: docker.mirror.hashicorp.services/hashicorp/http-echo:latest - args: - - -text="hello world" - - -listen=:8080 - ports: - - containerPort: 8080 - name: api - - name: api-admin - image: docker.mirror.hashicorp.services/hashicorp/http-echo:latest - args: - - -text="hello world from 9090 admin" - - -listen=:9090 - ports: - - containerPort: 9090 - name: admin - serviceAccountName: api -``` - - - - - -For testing purposes, the following example defines a Service to function as a static client that you can use to verify that the multi-port services function correctly. - - - -```yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: web ---- -apiVersion: v1 -kind: Service -metadata: - name: web -spec: - selector: - app: web - ports: - - port: 80 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: web -spec: - replicas: 1 - selector: - matchLabels: - app: web - template: - metadata: - labels: - app: web - annotations: - "consul.hashicorp.com/mesh-inject": "true" - "consul.hashicorp.com/transparent-proxy": "true" - spec: - containers: - - name: web - image: curlimages/curl:latest - # Just spin & wait forever, we'll use `kubectl exec` to demo - command: ['/bin/sh', '-c', '--'] - args: ['while true; do sleep 30; done;'] - serviceAccountName: web -``` - - - -To apply these services to your Kubernetes deployment and register them with Consul, run the following command: - -```shell-session -$ kubectl apply -f api.yaml -f web.yaml -``` - -## Configure traffic permissions - -Consul uses traffic permissions to validate communication between services based on L4 identity. In the beta release of the v2 catalog API, traffic permissions allow all services by default. In order to verify that services function correctly on each port, create CRDs that deny traffic to each port. - -The following examples create Consul CRDs that allow traffic to only one port of the multi-port service. Each resource separately denies `web` permission when it is a source of traffic to one of the services. These traffic permissions work with either method for defining a multi-port service. When following the instructions on this page, apply these permissions individually when you validate the ports. - - - - - -```yaml -apiVersion: auth.consul.hashicorp.com/v2beta1 -kind: TrafficPermissions -metadata: - name: web-to-api-port-deny -spec: - destination: - identityName: api - action: deny - permissions: - - sources: - - identityName: web - destinationRules: - - portNames: ["api"] -``` - - - - - -```yaml -apiVersion: auth.consul.hashicorp.com/v2beta1 -kind: TrafficPermissions -metadata: - name: web-to-admin-port-deny -spec: - destination: - identityName: api - action: deny - permissions: - - sources: - - identityName: web - destinationRules: - - portNames: ["admin"] -``` - - - - -## Validate multi-port connection - -To open a shell to the `web` container, you need the name of the Pod it currently runs on. Run the following command to return a list of Pods: - -```shell-session -$ kubectl get pods -NAME READY STATUS RESTARTS AGE -api-5784b54bcc-tp98l 3/3 Running 0 6m55s -web-6dcbd684bc-gk8n5 2/2 Running 0 6m55s -``` - -Set environment variables to remember the pod name for the web workload for use in future commands. - -```shell-session -$ export WEB_POD=web-6dcbd684bc-gk8n5 -``` - -### Validate both ports - -Use the `web` Pod's name to open a shell session and test the `api` service on port 80. - - - - - -```shell-session -$ kubectl exec -it ${WEB_POD} -c web -- curl api:80 -hello world -``` - -Then test the `api` service on port 90. - -```shell-session -$ kubectl exec -it ${WEB_POD} -c web -- curl api:90 -hello world from 9090 admin -``` - - - - - -```shell-session -$ kubectl exec -it ${WEB_POD} -c web -- curl api:80 -hello world -``` - -Then test the `api-admin` service on port 90. - -```shell-session -$ kubectl exec -it ${WEB_POD} -c web --namespace consul -- curl api-admin:90 -hello world from 9090 admin -``` - - - - -### Validate port 80 - -Apply the CRD to allow traffic to port 80 only: - -```shell-session -$ kubectl apply -f deny-90.yaml -``` - - - - - -Then, open a shell session in the `web` container and test the `api` service on port 80. - -```shell-session -$ kubectl exec -it ${WEB_POD} -c web -- curl api:80 -hello world -``` - -Test the `api` service on port 90. This command should fail, indicating that the traffic permission is in effect. - -```shell-session -$ kubectl exec -it ${WEB_POD} -c web -- curl api:90 -``` - - - - - -Then, open a shell session in the `web` container and test the `api` service on port 80. - -```shell-session -$ kubectl exec -it ${WEB_POD} -c web -- curl api:80 -hello world -``` - -Test the `admin` service on port 90. This command should fail, indicating that the traffic permission is in effect. - -```shell-session -$ kubectl exec -it ${WEB_POD} -c web -- curl api-admin:90 -``` - - - - -Before testing the other port, remove the `TrafficPermissions` CRD. - -```shell-session -$ kubectl delete -f deny-90.yaml -``` - -### Validate port 90 - -Apply the CRD to allow traffic to port 90 only: - -```shell-session -$ kubectl apply -f deny-80.yaml -``` - - - - - -Then, open a shell session in the `web` container and test the `api` service on port 90. - -```shell-session -$ kubectl exec -it ${WEB_POD} -c web -- curl api:90 -hello world from 9090 admin -``` - -Test the `api` service on port 80. This command should fail, indicating that the traffic permission is in effect. - -```shell-session -$ kubectl exec -it ${WEB_POD} -c web -- curl api:80 -``` - - - - - -Then, open a shell session in the `web` container and test the `api-admin` service on port 90. - -```shell-session -$ kubectl exec -it ${WEB_POD} -c web -- curl api-admin:90 -hello world from 9090 admin -``` - -Test the `api` service on port 80. This command should fail, indicating that the traffic permission is in effect. - -```shell-session -$ kubectl exec -it ${WEB_POD} -c web -- curl api:80 -``` - - - diff --git a/website/content/docs/k8s/multiport/index.mdx b/website/content/docs/k8s/multiport/index.mdx deleted file mode 100644 index 0cdc6fca92aa..000000000000 --- a/website/content/docs/k8s/multiport/index.mdx +++ /dev/null @@ -1,69 +0,0 @@ ---- -layout: docs -page_title: Multi-port services for service mesh -description: Consul on Kubernetes supports multi-port services for both service discovery and service mesh scenarios. Learn about Consul’s v2 catalog changes to support multiple ports for a service running in a single container. ---- - -# Multi-port services for service mesh - - - -Multi-port services are part of a beta release. This documentation supports testing and development scenarios. Do not use multi-port services or the v2 catalog API in secure production environments. - - - -This topic describes changes to Consul's catalog that allow you to register a service with multiple ports on Kubernetes deployments. - -## Introduction - -When Consul registers services, v1 of its catalog API tracks the following information: - -- IDs of the specific _service instances_ that are registered -- Locations of the _nodes_ the instances run on -- Names of the _services_ the instances are associated with - -This catalog API was designed prior to the introduction of Consul’s service mesh features. The service mesh uses Consul's ACL system, which requires a Kubernetes ServiceAccount resource to match the Service name. As a result, only one service can represent a Kubernetes Workload in the Consul catalog. - -Since then, the cloud networking needs for applications have evolved and the Consul catalog adapted to support workarounds for these needs. For example, [Kubernetes Pods with multiple ports](/consul/docs/k8s/connect#kubernetes-pods-with-multiple-ports) demonstrates how you can schedule a service with multiple ports so that Consul registers it in the catalog as distinct services with their own service instances. However, this workaround results in additional resource consumption because Consul requires that each service and port use their own proxy and Consul dataplane so that it can recognize them as distinct services. - -### Catalog API v2 beta - -Consul v1.17 introduces a new version of the catalog API designed to bridge differences between the Consul and Kubernetes data models. The v2 catalog API still tracks services and nodes for Consul, but replaces service instances with _workloads_ and _workload identites_. - -- `Workload` is an application instance running in a set of one or more Pods scheduled according to a Kubernetes Workload resource such as a Deployment or StatefulSet. It is similar to [Kubernetes Workloads](https://kubernetes.io/docs/concepts/workloads/). -- `WorkloadIdentities` provide a distinct identity for a Workload to assume in a Kubernetes cluster. They are similar to [Kubernetes Service Accounts](https://kubernetes.io/docs/concepts/security/service-accounts/). - -This catalog structure enables Consul to associate a single Kubernetes Workload with multiple services in its catalog. - -The v2 catalog API also tracks the following information about services when they are registered with Consul: - -- `ServiceEndpoints` maps services to workload addresses and endpoints. This resource is computed by Consul. -- `HealthStatus` is a resource for reporting the health status of a workload. -- `HealthCheck` is a resource for defining the health checks for a workload. -- `ProxyConfiguration` represents a configuration for a sidecar or gateway proxy, similar to the `Proxy` field in the current service definition. -- `Destinations` represents explicit service upstreams. -- `TrafficPermissions` is a replacement for the `ServiceIntentions` custom resource definition (CRD). Traffic permissions replace service intentions for all services in the v2 catalog, which enables L4 traffic authorization according to workload identity instead of service identity. - -The v2 catalog API is available alongside the existing v1 catalog API, but the catalogs cannot be used simultaneously. The v2 catalog is disabled by default. This beta release is for testing and development purposes only. We do not recommend implementing v2 in production environments or migrating to v2 until the API is generally available. - -## Workflow - -To use a multi-port service in Consul on Kubernetes deployments, complete the following steps: - -1. Enable the v2 catalog. Add `global.experiments: ["resource-apis"]` and `ui.enabled: false` to a cluster's Helm chart before deploying Consul. -1. Use the `"consul.hashicorp.com/mesh-inject": "true"` annotation so that Consul registers the service automatically when Kubernetes deploys containers. -1. Configure traffic permissions. In the beta release, services registered to the v2 catalog allow all traffic by default. You can use the `TrafficPermissions` CRD to deny traffic to individual services for testing purposes. -1. Validate multi-port functionality. Send test traffic to each port to confirm that traffic is authorized and routed correctly. - -For an example configuration and instructions for each of the steps in this workflow, refer to [configure multi-port services](/consul/docs/k8s/multiport/configure). - -## Constraints and limitations - -Be aware of the following constraints and technical limitations on using multi-port services and the v2 catalog API: - -- The v2 catalog API beta does not support connections with client agents. It is only available for Kubernetes deployments, which use [Consul dataplanes](/consul/docs/connect/dataplane) instead of client agents. -- The v1 and v2 catalog APIs cannot run concurrently. -- The Consul UI does not support multi-port services or the v2 catalog API in this release. You must disable the UI in the Helm chart in order to use the v2 catalog API. -- HCP Consul does not support multi-port services or the v2 catalog API in this release. You cannot [link a self-managed cluster to HCP Consul](/hcp/docs/consul/self-managed) to access its UI or view observability metrics when it uses the v2 catalog. -- The v2 catalog API does not support ACLs in the beta release. -- We do not recommend updating existing clusters to enable the v2 catalog in this release. To use the v2 catalog, deploy a new Consul cluster. \ No newline at end of file diff --git a/website/content/docs/k8s/upgrade/index.mdx b/website/content/docs/k8s/upgrade/index.mdx index 26ef776e1b73..690ed380f36e 100644 --- a/website/content/docs/k8s/upgrade/index.mdx +++ b/website/content/docs/k8s/upgrade/index.mdx @@ -11,10 +11,12 @@ This topic describes considerations and strategies for upgrading Consul deployme ## Version-specific upgrade requirements -As of Consul v1.14.0, Kubernetes deployments use [Consul Dataplane](/consul/docs/connect/dataplane) instead of client agents. If you upgrade Consul from a version that uses client agents to a version that uses dataplanes, you must follow specific steps to update your Helm chart and remove client agents from the existing deployment. Refer to [Upgrading to Consul Dataplane](/consul/docs/k8s/upgrade#upgrading-to-consul-dataplane) for more information. +As of Consul v1.14.0 and the corresponding Helm chart version v1.0.0, Kubernetes deployments use [Consul Dataplane](/consul/docs/connect/dataplane) instead of client agents. If you upgrade Consul from a version that uses client agents to a version that uses dataplanes, you must follow specific steps to update your Helm chart and remove client agents from the existing deployment. Refer to [Upgrading to Consul Dataplane](/consul/docs/k8s/upgrade#upgrading-to-consul-dataplane) for more information. The v1.0.0 release of the Consul on Kubernetes Helm chart also introduced a change to the [`externalServers[].hosts` parameter](/consul/docs/k8s/helm#v-externalservers-hosts). Previously, you were able to enter a provider lookup as a string in this field. Now, you must include `exec=` at the start of a string containing a provider lookup. Otherwise, the string is treated as a DNS name. Refer to the [`go-netaddrs`](https://github.com/hashicorp/go-netaddrs) library and command line tool for more information. +If you configured your Consul agents to use [`ports.grpc_tls`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#grpc_tls_port) instead of [`ports.grpc`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#grpc_port) and you want to upgrade a multi-datacenter deployment with Consul servers running outside of the Kubernetes cluster to v1.0.0 or higher, set [`externalServers.tlsServerName`](/consul/docs/k8s/helm#v-externalservers-tlsservername) to `server..domain`. + ## Upgrade types We recommend updating Consul on Kubernetes when: @@ -23,13 +25,13 @@ We recommend updating Consul on Kubernetes when: - A new Helm chart is released - You want to upgrade your Consul version +The upgrade procedure you use depends on the type of upgrade you are performing. + ### Helm configuration changes If you make a change to your Helm values file, you need to perform a `helm upgrade` for those changes to take effect. -For example, if you installed Consul with `connectInject.enabled: false` and you want to change its value to `true`: - 1. Determine your current installed chart version. ```shell-session @@ -40,16 +42,13 @@ For example, if you installed Consul with `connectInject.enabled: false` and you In this example, version `0.40.0` (from `consul-k8s:0.40.0`) is being used, and Consul on Kubernetes is installed in the `consul` namespace. -1. Perform a `helm upgrade`: +1. Perform a `helm upgrade` and make sure that you specify the current chart version: ```shell-session $ helm upgrade consul hashicorp/consul --namespace consul --version 0.40.0 --values /path/to/my/values.yaml ``` - **Before performing the upgrade, be sure you read the other sections on this page, - continuing at [Determine scope of changes](#determine-scope-of-changes).** - -~> Note: You should always set the `--version` flag when upgrading Helm. Otherwise, Helm uses the most up-to-date version in its local cache, which may result in an unintended upgrade. +~> Note: If you don't pass the `--version` flag when upgrading a Helm chart, Helm uses the most up-to-date version of the chart in its local cache, which may result in an unintended version upgrade. ### Upgrade Helm chart version @@ -63,7 +62,7 @@ certain Helm chart version. $ helm repo update ``` -1. List all available versions. Here you can observe that the latest version of `0.40.0`. +1. List all available versions. The console lists version `0.40.0` in the following example. ```shell-session hideClipboard $ helm search repo hashicorp/consul --versions @@ -85,19 +84,27 @@ certain Helm chart version. In this example, version `0.39.0` (from `consul-k8s:0.39.0`) is being used. -If you want to upgrade to the latest `0.40.0` version, use the following procedure: - 1. Check the changelog for any breaking changes from that version and any versions in between: [CHANGELOG.md](https://github.com/hashicorp/consul-k8s/blob/main/CHANGELOG.md). -1. Upgrade by performing a `helm upgrade` with the `--version` flag: +1. Check the [Consul on Kubernetes Version Compatibility](/consul/docs/k8s/compatibility) matrix. Each 1.x version of + the chart corresponds to a specific 1.x version of Consul. You may need to upgrade your Consul version to match the + chart version you want to upgrade to. For example, chart version `1.3.1` must be used with Consul version `1.17.x`. + To set the Consul version, set `global.image` in your `values.yaml` file, for example: + + ``` + global: + image: "hashicorp/consul:1.17.5" + ``` + + You can leave the `global.image` value unset to use the latest supported version of Consul. + version automatically. + +1. Upgrade by performing a `helm upgrade` with the `--version` flag set to the version you want to upgrade to: ```shell-session $ helm upgrade consul hashicorp/consul --namespace consul --version 0.40.0 --values /path/to/my/values.yaml ``` - **Before performing the upgrade, be sure you've read the other sections on this page, - continuing at [Determine scope of changes](#determine-scope-of-changes).** - ### Upgrade Consul version If a new version of Consul is released, you need to perform a Helm upgrade @@ -115,12 +122,12 @@ to update to the new version. Before you upgrade to a new version: ```yaml global: - image: consul:1.11.2 + image: "hashicorp/consul:1.11.1" ``` -2. Determine the version of your existing Helm installation. In this example, version `0.39.0` (from `consul-k8s:0.39.0`) is being used. +1. Determine the version of your existing Helm installation. The following example shows that version `0.39.0` is installed. The version is derived from the `CHART` column. ```shell-session $ helm list --filter consul --namespace consul @@ -128,99 +135,22 @@ to update to the new version. Before you upgrade to a new version: consul consul 2 2022-02-02 21:49:45.647678 -0800 PST deployed consul-0.39.0 1.11.1 ``` +1. Check the [Consul on Kubernetes Version Compatibility](/consul/docs/k8s/compatibility) matrix. Each 1.x version of +the chart corresponds to a specific 1.x version of Consul. You may need to upgrade your chart version to match the +Consul version you want to upgrade to. + 1. Perform a `helm upgrade`: ```shell-session $ helm upgrade consul hashicorp/consul --namespace consul --version 0.39.0 --values /path/to/my/values.yaml ``` - **Before performing the upgrade, be sure you have read the other sections on this page, - continuing at [Determine scope of changes](#determine-scope-of-changes).** - -~> Note: You should always set the `--version` flag when upgrading Helm. Otherwise, Helm uses the most up-to-date version in its local cache, which may result in an unintended upgrade. - -## Determine scope of changes - -Before upgrading, it is important to understand the changes that affect your -cluster. For example, you need to take more care if your upgrade results -in the Consul server StatefulSet being redeployed. - -There is no built-in functionality in Helm that shows what a helm upgrade -changes. There is, however, a Helm plugin [helm-diff](https://github.com/databus23/helm-diff) -that can be used. - -1. Install `helm-diff` with: - - ```shell-session - $ helm plugin install https://github.com/databus23/helm-diff - ``` - -1. If you are updating your `values.yaml` file, do so now. -1. Take the same `helm upgrade` command you were planning to issue but perform `helm diff upgrade` instead of `helm upgrade`: - - ```shell-session - $ helm diff upgrade consul hashicorp/consul --namespace consul --version 0.40.0 --values /path/to/your/values.yaml - ``` - - This command prints out the manifests that will be updated and their diffs. - -1. To see only updated objects, add `| grep "has changed"`: - - ```shell-session - $ helm diff upgrade consul hashicorp/consul --namespace consul --version 0.40.0 --values /path/to/your/values.yaml | - grep "has changed" - ``` - -1. Take specific note if `consul-server, StatefulSet` is listed, as it means your Consul server statefulset will be redeployed. - - If your Consul server statefulset needs to be redeployed, follow the same pattern for upgrades as - on other platforms by redeploying servers one by one. Refer tp [Upgrading Consul](/consul/docs/upgrading) for more information. - - If neither the server statefulset is not being redeployed, - then you can continue with the Helm upgrade without any specific sequence to follow. - -## Upgrade Consul servers - -Initiate the server upgrade: - -1. Change the `global.image` value to the desired Consul version. -1. Set the `server.updatePartition` value to the number of server replicas. By default, there are 3 servers, so you would set this value to `3`. -1. Set the `updateStrategy` for clients to `OnDelete`. - - - - ```yaml - global: - image: 'consul:123.456' - server: - updatePartition: 3 - ``` - - - - The `updatePartition` value controls how many instances of the server - cluster are updated. Only instances with an index _greater than_ the - `updatePartition` value are updated (zero-indexed). Therefore, by setting - it equal to replicas, updates should not occur immediately. - -1. Next, perform the upgrade: - - ```shell-session - $ helm upgrade consul hashicorp/consul --namespace consul --version --values /path/to/your/values.yaml - ``` - - This command does not cause the servers to redeploy, although the resource is updated. If - everything is stable, decrease the `updatePartition` value by one - and performing `helm upgrade` again. This will cause the first Consul server - to be stopped and restarted with the new image. +~> Note: If you don't pass the `--version` flag when upgrading a Helm chart, Helm uses the most up-to-date version of the chart in its local cache, which may result in an unintended version upgrade. -1. Wait until the Consul server cluster is healthy again (30s to a few minutes). - This can be confirmed by issuing `consul members` on one of the previous servers, - and ensuring that all servers are listed and are `alive`. +## Consul server restarts and upgrades -1. Decrease `updatePartition` by one and upgrade again. Continue until - `updatePartition` is `0`. At this point, you may remove the - `updatePartition` configuration. Your server upgrade is complete. +Note that for versions of Consul on Kubernetes prior to `1.4.0`, we recommended using the `server.updatePartition` setting to gradually upgrade +Consul servers. Refer to an older version of the documentation for instructions on upgrading to a version of the chart older than `v1.4.0`. Use the version drop-down at the top of this page to select a version older than or equal to `v1.17.0`. Consul documentation versions correspond to the Consul version in your chart, not the chart version, that contains the instructions. ## Upgrading to Consul Dataplane diff --git a/website/content/docs/lambda/registration/automate.mdx b/website/content/docs/lambda/registration/automate.mdx index 781d37318a35..62f4aa700df9 100644 --- a/website/content/docs/lambda/registration/automate.mdx +++ b/website/content/docs/lambda/registration/automate.mdx @@ -134,7 +134,7 @@ The registrator also requires the following IAM permissions to access the parame ## Deploy the Lambda registrator -1. Create a Terraform configuration and specify the `lambda-registrator` module. In the following example, the Lambda registrator is deployed to `https://consul.example.com:8501`. Refer to [the Lambda registrator module documentation](https://registry.terraform.io/modules/hashicorp/consul-lambda-registrator/aws/0.1.0-beta1/submodules/lambda-registrator) for additional usage information: +1. Create a Terraform configuration and specify the `lambda-registrator` module. In the following example, the Lambda registrator is deployed to `https://consul.example.com:8501`. Refer to [the Lambda registrator module documentation](https://registry.terraform.io/modules/hashicorp/consul-lambda-registrator/aws/0.1.0-beta5/submodules/lambda-registrator) for additional usage information: ```hcl module "lambda-registrator" { source = "hashicorp/consul-lambda/consul-lambda-registrator" diff --git a/website/content/docs/nia/api/tasks.mdx b/website/content/docs/nia/api/tasks.mdx index 1f5ca51404a7..f45253c34310 100644 --- a/website/content/docs/nia/api/tasks.mdx +++ b/website/content/docs/nia/api/tasks.mdx @@ -400,5 +400,5 @@ The task object is used by the Task APIs as part of a request or response. It re | `providers` | list[string] | Optional | The list of provider names that the task's module uses. | none | | `variables` | map[string] | Optional | The map of variables that are provided to the task's module. | none | | `version` | string | Optional | The version of the configured module that the task uses. | The latest version. | -| `terraform_version` | string | Optional | **Deprecated in CTS 0.6.0 and will be removed in 0.8.0. Review `terraform_version` in `terraform_cloud_workspace` instead.** The version of Terraform to use for the Terraform Cloud workspace associated with the task. This is only available when used with the [Terraform Cloud driver](/consul/docs/nia/configuration#terraform-cloud-driver). | The latest compatible version supported by the organization. | -| `terraform_cloud_workspace` | object | Optional | The [configurable attributes of the Terraform Cloud workspace](/consul/docs/nia/configuration#terraform_cloud_workspace) associated with the task. This option is only available when used with the [Terraform Cloud driver](/consul/docs/nia/configuration#terraform-cloud-driver).| none | +| `terraform_version` | string | Optional | **Deprecated in CTS 0.6.0 and will be removed in 0.8.0. Review `terraform_version` in `terraform_cloud_workspace` instead.** The version of Terraform to use for the HCP Terraform workspace associated with the task. This is only available when used with the [HCP Terraform driver](/consul/docs/nia/configuration#hcp-terraform-driver). | The latest compatible version supported by the organization. | +| `terraform_cloud_workspace` | object | Optional | The [configurable attributes of the HCP Terraform workspace](/consul/docs/nia/configuration#terraform_cloud_workspace) associated with the task. This option is only available when used with the [HCP Terraform driver](/consul/docs/nia/configuration#hcp-terraform-driver).| none | diff --git a/website/content/docs/nia/architecture.mdx b/website/content/docs/nia/architecture.mdx index 1519bc82cbb8..14ff0da3c0c0 100644 --- a/website/content/docs/nia/architecture.mdx +++ b/website/content/docs/nia/architecture.mdx @@ -41,7 +41,7 @@ A driver encapsulates the resources required to communicate the updates to the network infrastructure. The following [drivers](/consul/docs/nia/network-drivers#terraform) are supported: - Terraform driver -- Terraform Cloud driver +- HCP Terraform driver Each driver includes a set of providers that [enables support](/consul/docs/nia/terraform-modules) for a wide variety of infrastructure applications. diff --git a/website/content/docs/nia/compatibility.mdx b/website/content/docs/nia/compatibility.mdx index f160fe644780..7e473bc3564d 100644 --- a/website/content/docs/nia/compatibility.mdx +++ b/website/content/docs/nia/compatibility.mdx @@ -13,7 +13,7 @@ This topic describes Consul-Terraform-Sync (CTS) cross-compatibility with Consul Below are CTS versions with supported Consul versions. The latest CTS binary supports the three most recent Consul minor versions, along with their latest patch versions. -| CTS Version | Consul Community Edition & Enterprise Version | HCP Consul Version | +| CTS Version | Consul Community Edition & Enterprise Version | HCP Consul Dedicated Version | | :--------------------- | :------------------------------ | :----------------- | | CTS Enterprise 0.6+ | 1.8+ | 1.9+ | | CTS Enterprise 0.3-0.5 | 1.8+ | N/A | @@ -24,7 +24,7 @@ Below are CTS versions with supported Consul versions. The latest CTS binary sup CTS integration with Terraform is supported for the following: -| CTS Version | Terraform CLI Version | Terraform Cloud Version | Terraform Enterprise Version | +| CTS Version | Terraform CLI Version | HCP Terraform Version | Terraform Enterprise Version | | :------------------ | :-------------------- | :---------------------- | :--------------------------- | | CTS Enterprise 0.7 | 0.13-1.2 | Latest | v202010-2 - Latest | | CTS Enterprise 0.4+ | 0.13 - 1.1 | Latest | v202010-2 - Latest | diff --git a/website/content/docs/nia/configuration.mdx b/website/content/docs/nia/configuration.mdx index ec53eccdada3..ec07f3474d3f 100644 --- a/website/content/docs/nia/configuration.mdx +++ b/website/content/docs/nia/configuration.mdx @@ -86,7 +86,7 @@ license { You can use the `auto_retrieval` block to configure the automatic license retrieval in CTS. When enabled, CTS attempts to retrieve a new license from its configured Consul Enterprise backend once a day. If CTS cannot retrieve a license and the current license is reaching its expiration date, CTS attempts to retrieve a license with increased frequency, as defined by the [License Expiration Date Handling](/consul/docs/nia/enterprise/license#license-expiration-handling). -~> Enabling `auto_retrieval` is recommended when using HCP Consul, as HCP Consul licenses expire more frequently than Consul Enterprise licenses. Without auto-retrieval enabled, you have to restart CTS every time you load a new license. +~> Enabling `auto_retrieval` is recommended when using HCP Consul Dedicated, as HCP Consul Dedicated licenses expire more frequently than Consul Enterprise licenses. Without auto-retrieval enabled, you have to restart CTS every time you load a new license. | Parameter | Required | Type | Description | Default | | --------- | -------- | ---- | ----------- | ------- | @@ -302,7 +302,7 @@ task { - `module` - (string: required) Module is the location the driver uses to discover the Terraform module used for automation. The module's source can be local or remote on the [Terraform Registry](https://registry.terraform.io/) or private module registry. Read more on [Terraform module source and other supported types here](/terraform/language/modules/sources). - To use a private module with the [`terraform` driver](#terraform-driver), run the command [`terraform login [hostname]`](/terraform/tutorials/cloud/cloud-login?utm_source=docs) to authenticate the local Terraform CLI prior to starting CTS. - - To use a private module with the [`terraform_cloud` driver](#terraform-cloud-driver), no extra steps are needed. + - To use a private module with the [`terraform_cloud` driver](#hcp-terraform-driver), no extra steps are needed. ```hcl // local module example: "./terraform-cts-hello" @@ -339,12 +339,12 @@ task { - `condition` - (obj: required) The requirement that, when met, triggers CTS to execute the task. Only one `condition` may be configured per task. CTS supports different types of conditions, which each have their own configuration options. See [Task Condition](#task-condition) configuration for full details on configuration options for each condition type. - `source_input` - (obj) **Deprecated in CTS 0.5.0 and will be removed in 0.8.0. See the `module_input` block instead.** - `module_input` - (obj) Specifies a Consul object containing values or metadata to be provided to the Terraform Module. The `module_input` block defines any extra module inputs needed for task execution. This is in addition to any module input provided by the `condition` block or `services` field (deprecated). Multiple `module_input` blocks can be configured per task. [Task Module Input](#task-module-input) configuration for full details on usage and restrictions. -- `terraform_version` - (string) **Deprecated in CTS 0.6.0 and will be removed in 0.8.0. Review `terraform_cloud_workspace.terraform_version` instead.** The version of Terraform to use for the Terraform Cloud workspace associated with the task. Defaults to the latest compatible version supported by the organization. This option is only available when used with the [Terraform Cloud driver](#terraform-cloud-driver); otherwise, set the version within the [Terraform driver](#terraform-driver). -- `terraform_cloud_workspace` - (obj) Configures attributes of the Terraform Cloud workspace associated with the task. This option is only available when used with the [Terraform Cloud driver](#terraform-cloud-driver). For global configurations of all workspaces, review [`driver.workspaces`](#workspaces). - - `execution_mode` - (string: "remote") The execution mode that determines whether to use Terraform Cloud as the Terraform execution platform. Only supports "remote" or "agent". +- `terraform_version` - (string) **Deprecated in CTS 0.6.0 and will be removed in 0.8.0. Review `terraform_cloud_workspace.terraform_version` instead.** The version of Terraform to use for the HCP Terraform workspace associated with the task. Defaults to the latest compatible version supported by the organization. This option is only available when used with the [HCP Terraform driver](#hcp-terraform-driver); otherwise, set the version within the [Terraform driver](#terraform-driver). +- `terraform_cloud_workspace` - (obj) Configures attributes of the HCP Terraform workspace associated with the task. This option is only available when used with the [HCP Terraform driver](#hcp-terraform-driver). For global configurations of all workspaces, review [`driver.workspaces`](#workspaces). + - `execution_mode` - (string: "remote") The execution mode that determines whether to use HCP Terraform as the Terraform execution platform. Only supports "remote" or "agent". - `agent_pool_id` - (string) Only supported if `execution_mode` is set to "agent". The ID of the agent pool that should run the Terraform workloads. Either `agent_pool_id` or `agent_pool_name` are required if `execution_mode` is set to "agent". `agent_pool_id` takes precedence over `agent_pool_name` if both are provided. - `agent_pool_name` - (string) Only supported if `execution_mode` is set to "agent". The name of the agent pool that should run the Terraform workloads. Only supported if `execution_mode` is set to "agent". Either `agent_pool_id` or `agent_pool_name` are required. `agent_pool_id` takes precedence over `agent_pool_name` if both are provided. - - `terraform_version` - (string) The version of Terraform to use for the Terraform Cloud workspace associated with the task. Defaults to the latest compatible version supported by the organization. + - `terraform_version` - (string) The version of Terraform to use for the HCP Terraform workspace associated with the task. Defaults to the latest compatible version supported by the organization. ### Task Condition @@ -653,7 +653,7 @@ driver "terraform" { - `backend` - (obj) The backend stores [Terraform state files](/terraform/language/state) for each task. This option is similar to the [Terraform backend configuration](/terraform/language/settings/backends/configuration). CTS supports Terraform backends used as a state store. - Supported backend options: [azurerm](/terraform/language/settings/backends/azurerm), [consul](/terraform/language/settings/backends/consul), [cos](/terraform/language/settings/backends/cos), [gcs](/terraform/language/settings/backends/gcs), [kubernetes](/terraform/language/settings/backends/kubernetes), [local](/terraform/language/settings/backends/local), [manta](/terraform/language/v1.2.x/settings/backends/manta), [pg](/terraform/language/settings/backends/pg) (Terraform v0.14+), [s3](/terraform/language/settings/backends/s3). Visit the Terraform documentation links for details on backend configuration options. - If omitted, CTS will generate default values and use configurations from the [`consul` block](#consul) to configure [Consul as the backend](/terraform/language/settings/backends/consul), which stores Terraform statefiles in the Consul KV. The [ACL token provided for Consul authentication](#consul) is used to read and write to the KV store and requires [Consul KV privileges](/consul/tutorials/network-infrastructure-automation/consul-terraform-sync-secure?utm_source=docs#configure-acl-privileges-for-consul-terraform-sync). The Consul KV path is the base path to store state files for tasks. The full path of each state file will have the task identifier appended to the end of the path, e.g. `consul-terraform-sync/terraform-env:task-name`. - - The remote enhanced backend is not supported with the Terraform driver to run operations in Terraform Cloud. Use the [Terraform Cloud driver](#terraform-cloud-driver) to integrate CTS with Terraform Cloud for remote workspaces and remote operations. + - The remote enhanced backend is not supported with the Terraform driver to run operations in HCP Terraform. Use the [HCP Terraform driver](#hcp-terraform-driver) to integrate CTS with HCP Terraform for remote workspaces and remote operations. - The `local` backend type is not supported with CTS instances configured for high availability. If high availability is configured and the Terraform backend type is `local`, CTS logs an error and exits. - `log` - (bool) Enable all Terraform output (stderr and stdout) to be included in the CTS log. This is useful for debugging and development purposes. It may be difficult to work with log aggregators that expect uniform log format. - `path` - (string) The file path to install Terraform or discover an existing Terraform binary. If omitted, Terraform will be installed in the same directory as the CTS daemon. To resolve an incompatible Terraform version or to change versions will require removing the existing binary or change to a different path. @@ -661,7 +661,7 @@ driver "terraform" { - `required_providers` - (obj: required) Declare each Terraform provider used across all tasks. This can be configured the same as how you would configure [Terraform `terraform.required_providers`](/terraform/language/providers/requirements#requiring-providers) field to specify the source and version for each provider. CTS will process these requirements when preparing each task that uses the provider. - `version` - (string) The Terraform version to install and run in automation for task execution. If omitted, the driver will install the latest [compatible release of Terraform](/consul/docs/nia/compatibility#terraform). To change versions, remove the existing binary or change the path to install the desired version. Verify that the desired Terraform version is compatible across all Terraform modules used for CTS automation. -## Terraform Cloud Driver +## HCP Terraform Driver This feature requires{' '} @@ -671,9 +671,9 @@ driver "terraform" { which is available with Consul Enterprise. -The Terraform Cloud driver enables CTS Enterprise to integrate with **Terraform Cloud**, including both the [self-hosted distribution](https://www.hashicorp.com/products/terraform/editions/enterprise) and the [managed service](https://www.hashicorp.com/products/terraform/editions/cloud). With this driver, CTS automates Terraform runs and remote operations for workspaces. +The HCP Terraform driver enables CTS Enterprise to integrate with HCP Terraform, including both the [self-hosted distribution](https://www.hashicorp.com/products/terraform/editions/enterprise) and the [managed service](https://www.hashicorp.com/products/terraform/editions/cloud). With this driver, CTS automates Terraform runs and remote operations for workspaces. -An overview of features enabled with Terraform Cloud can be viewed within the [Network Drivers](/consul/docs/nia/network-drivers) documentation. +An overview of features enabled with HCP Terraform can be viewed within the [Network Drivers](/consul/docs/nia/network-drivers) documentation. Only one network driver can be configured per deployment of CTS. @@ -701,16 +701,16 @@ driver "terraform-cloud" { } ``` -- `hostname` - (string) The Terraform Cloud hostname to connect to. Can be overridden with the `TFC_HOSTNAME` environment variable. -- `organization` - (string) The Terraform Cloud organization that hosts the managed workspaces by CTS. Can be overridden with the `TFC_ORGANIZATION` environment variable. -- `token` - (string) Required [Team API token](/terraform/cloud-docs/users-teams-organizations/api-tokens#team-api-tokens) used for authentication with Terraform Cloud and workspace management. Only workspace permissions are needed for CTS. The token can also be provided using the `TFC_TOKEN` environment variable. - - We recommend creating a dedicated team and team API token to isolate automation by CTS from other Terraform Cloud operations. +- `hostname` - (string) The HCP Terraform hostname to connect to. Can be overridden with the `TFC_HOSTNAME` environment variable. +- `organization` - (string) The HCP Terraform organization that hosts the managed workspaces by CTS. Can be overridden with the `TFC_ORGANIZATION` environment variable. +- `token` - (string) Required [Team API token](/terraform/cloud-docs/users-teams-organizations/api-tokens#team-api-tokens) used for authentication with HCP Terraform and workspace management. Only workspace permissions are needed for CTS. The token can also be provided using the `TFC_TOKEN` environment variable. + - We recommend creating a dedicated team and team API token to isolate automation by CTS from other HCP Terraform operations. - `workspace_prefix` - (string) **Deprecated in CTS 0.5.0**, use the [`workspaces.prefix`](#prefix) option instead. Specifies a prefix to prepend to the automatically-generated workspace names used for automation. This prefix will be used by all tasks that use this driver. By default, when no prefix is configured, the workspace name will be the task name. When a prefix is configured, the workspace name will be `-`, with the character '-' between the workspace prefix and task name. For example, if you configure the prefix as "cts", then a task with the name "task-firewall" will have the workspace name "cts-task-firewall". -- `workspaces` - Configure CTS management of Terraform Cloud workspaces. +- `workspaces` - Configure CTS management of HCP Terraform workspaces. - `prefix` - (string) Specifies a prefix to prepend to the workspace names used for CTS task automation. This prefix will be used by all tasks that use this driver. By default, when no prefix is configured, the workspace name will be the task name. When a prefix is configured, the workspace name will be ``. For example, if you configure the prefix as "cts_", then a task with the name "task_firewall" will have the workspace name "cts_task_firewall". - - `tags` - (list[string]) Tags for CTS to add to all automated workspaces when the workspace is first created or discovered. Tags are added to discovered workspaces only if the workspace meets [automation requirements](/consul/docs/nia/network-drivers/terraform-cloud#remote-workspaces) and satisfies the allowlist and denylist tag options. This option will not affect existing tags. Tags that were manually removed during runtime will be re-tagged when CTS restarts. Compatible with Terraform Cloud and Terraform Enterprise v202108-1+ - - `tags_allowlist` - (list[string]) Tag requirement to use as a provision check for CTS automation of workspaces. When configured, Terraform Cloud workspaces must have at least one tag from the allow list for CTS to automate the workspace and runs. Compatible with Terraform Cloud and Terraform Enterprise v202108-1+. - - `tags_denylist` - (list[string]) Tag restriction to use as a provision check for CTS automation of workspaces. When configured, Terraform Cloud workspaces must not have any tag from the deny list for CTS to automate the workspace and runs. Denied tags have higher priority than tags set in the `tags_allowlist` option. Compatible with Terraform Cloud and Terraform Enterprise v202108-1+. + - `tags` - (list[string]) Tags for CTS to add to all automated workspaces when the workspace is first created or discovered. Tags are added to discovered workspaces only if the workspace meets [automation requirements](/consul/docs/nia/network-drivers/hcp-terraform#remote-workspaces) and satisfies the allowlist and denylist tag options. This option will not affect existing tags. Tags that were manually removed during runtime will be re-tagged when CTS restarts. Compatible with HCP Terraform and Terraform Enterprise v202108-1+ + - `tags_allowlist` - (list[string]) Tag requirement to use as a provision check for CTS automation of workspaces. When configured, HCP Terraform workspaces must have at least one tag from the allow list for CTS to automate the workspace and runs. Compatible with HCP Terraform and Terraform Enterprise v202108-1+. + - `tags_denylist` - (list[string]) Tag restriction to use as a provision check for CTS automation of workspaces. When configured, HCP Terraform workspaces must not have any tag from the deny list for CTS to automate the workspace and runs. Denied tags have higher priority than tags set in the `tags_allowlist` option. Compatible with HCP Terraform and Terraform Enterprise v202108-1+. - `required_providers` - (obj: required) Declare each Terraform provider used across all tasks. This can be configured the same as how you would configure [Terraform `terraform.required_providers`](/terraform/language/providers/requirements#requiring-providers) field to specify the source and version for each provider. CTS will process these requirements when preparing each task that uses the provider. - `tls` - Configure TLS to allow HTTPS connections to [Terraform Enterprise](/terraform/enterprise/install/interactive/installer#tls-key-amp-cert). - `enabled` - (bool) Enable TLS. Providing a value for any of the TLS options will enable this parameter implicitly. @@ -727,7 +727,7 @@ driver "terraform-cloud" { } ``` -CTS generates local artifacts to prepare configuration versions used for workspace runs. The location of the files created can be set with the [`working_dir`](/consul/docs/nia/configuration#working_dir) option or configured per task. When a task is configured with a local module and is run with the Terraform Cloud driver, the local module is copied and uploaded as a part of the configuration version. +CTS generates local artifacts to prepare configuration versions used for workspace runs. The location of the files created can be set with the [`working_dir`](/consul/docs/nia/configuration#working_dir) option or configured per task. When a task is configured with a local module and is run with the HCP Terraform driver, the local module is copied and uploaded as a part of the configuration version. The version of Terraform to use for each workspace can also be set within the [task](#task) configuration. diff --git a/website/content/docs/nia/enterprise/index.mdx b/website/content/docs/nia/enterprise/index.mdx index 56bb16474843..94b42f6c902a 100644 --- a/website/content/docs/nia/enterprise/index.mdx +++ b/website/content/docs/nia/enterprise/index.mdx @@ -9,22 +9,22 @@ description: >- Consul-Terraform-Sync (CTS) Enterprise is available with [Consul Enterprise](https://www.hashicorp.com/products/consul) and requires a Consul [license](/consul/docs/nia/enterprise/license) to be applied. -Enterprise features of CTS address organization complexities of collaboration, operations, scale, and governance. CTS Enterprise supports an official integration with [Terraform Cloud](https://cloud.hashicorp.com/products/terraform) and [Terraform Enterprise](/terraform/enterprise), the self-hosted distribution, to extend insight into dynamic updates of your network infrastructure. +Enterprise features of CTS address organization complexities of collaboration, operations, scale, and governance. CTS Enterprise supports an official integration with [HCP Terraform](https://cloud.hashicorp.com/products/terraform) and [Terraform Enterprise](/terraform/enterprise), the self-hosted distribution, to extend insight into dynamic updates of your network infrastructure. | Features | Community Edition | Enterprise | |----------|-------------|------------| | Consul Namespace | Default namespace only | Filter task triggers by any namespace | -| Automation Driver | Terraform Community Edition | Terraform Community Edition, Terraform Cloud, or Terraform Enterprise | -| Terraform Workspaces | Local | Local workspaces with the Terraform driver or [remote workspaces](/terraform/cloud-docs/workspaces) with the Terraform Cloud driver | -| Terraform Backend Options | [azurerm](/terraform/language/settings/backends/azurerm), [consul](/terraform/language/settings/backends/consul), [cos](/terraform/language/settings/backends/cos), [gcs](/terraform/language/settings/backends/gcs), [kubernetes](/terraform/language/settings/backends/kubernetes), [local](/terraform/language/settings/backends/local), [manta](/terraform/language/v1.2.x/settings/backends/manta), [pg](/terraform/language/settings/backends/pg), and [s3](/terraform/language/settings/backends/s3) with the Terraform driver | The supported backends for CTS with the Terraform driver or Terraform Cloud with the Terraform Cloud driver | -| Terraform Version | One Terraform version for all tasks | Optional Terraform version per task when using the Terraform Cloud driver | -| Terraform Run Output | CTS logs | CTS logs or Terraform output organized by Terraform Cloud remote workspaces | +| Automation Driver | Terraform Community Edition | Terraform Community Edition, HCP Terraform, or Terraform Enterprise | +| Terraform Workspaces | Local | Local workspaces with the Terraform driver or [remote workspaces](/terraform/cloud-docs/workspaces) with the HCP Terraform driver | +| Terraform Backend Options | [azurerm](/terraform/language/settings/backends/azurerm), [consul](/terraform/language/settings/backends/consul), [cos](/terraform/language/settings/backends/cos), [gcs](/terraform/language/settings/backends/gcs), [kubernetes](/terraform/language/settings/backends/kubernetes), [local](/terraform/language/settings/backends/local), [manta](/terraform/language/v1.2.x/settings/backends/manta), [pg](/terraform/language/settings/backends/pg), and [s3](/terraform/language/settings/backends/s3) with the Terraform driver | The supported backends for CTS with the Terraform driver or HCP Terraform with the HCP Terraform driver | +| Terraform Version | One Terraform version for all tasks | Optional Terraform version per task when using the HCP Terraform driver | +| Terraform Run Output | CTS logs | CTS logs or Terraform output organized by HCP Terraform remote workspaces | | Credentials and secrets | On disk as `.tfvars` files or in shell environment | Secured variables stored in remote workspace | -| Audit | | Terraform audit logs ([Terraform Cloud](/terraform/cloud-docs/api-docs/audit-trails) or [Terraform Enterprise](/terraform/enterprise/admin/infrastructure/logging)) | -| Collaboration | | Run [history](/terraform/cloud-docs/run/manage), [triggers](/terraform/cloud-docs/workspaces/settings/run-triggers), and [notifications](/terraform/cloud-docs/workspaces/settings/notifications) supported on Terraform Cloud | +| Audit | | Terraform audit logs ([HCP Terraform](/terraform/cloud-docs/api-docs/audit-trails) or [Terraform Enterprise](/terraform/enterprise/admin/infrastructure/logging)) | +| Collaboration | | Run [history](/terraform/cloud-docs/run/manage), [triggers](/terraform/cloud-docs/workspaces/settings/run-triggers), and [notifications](/terraform/cloud-docs/workspaces/settings/notifications) supported on HCP Terraform | | Governance | | [Sentinel](/terraform/cloud-docs/policy-enforcement) to enforce governance policies as code | -The [Terraform Cloud driver](/consul/docs/nia/configuration#terraform-cloud-driver) enables CTS Enterprise to integrate with Terraform Cloud or Terraform Enterprise. The [Terraform Cloud driver](/consul/docs/nia/network-drivers/terraform-cloud) page provides an overview of how the integration works within CTS. +The [HCP Terraform driver](/consul/docs/nia/configuration#terraform-cloud-driver) enables CTS Enterprise to integrate with HCP Terraform or Terraform Enterprise. The [HCP Terraform driver](/consul/docs/nia/network-drivers/terraform-cloud) page provides an overview of how the integration works within CTS. ## Consul Admin Partition Support CTS subscribes to a Consul agent. Depending on the admin partition the Consul agent is a part of and the services within the admin partition, CTS will be able to subscribe to those services and support the automation workflow. As such, admin partitions are not relevant to the CTS workflow. We recommend deploying a single CTS instance that subscribes to services/KV within a single partition and using a different CTS instance (or instances) to subscribe to services/KV in another partition. diff --git a/website/content/docs/nia/enterprise/license.mdx b/website/content/docs/nia/enterprise/license.mdx index fd71d0104735..338e68134406 100644 --- a/website/content/docs/nia/enterprise/license.mdx +++ b/website/content/docs/nia/enterprise/license.mdx @@ -20,7 +20,7 @@ To get a trial license for CTS, you can sign-up for the [trial license for Consu ## Automatic License Retrieval CTS automatically retrieves a license from Consul on startup and then attempts to retrieve a new license once a day. If the current license is reaching its expiration date, CTS attempts to retrieve a license with increased frequency, as defined by the [License Expiration Date Handling](/consul/docs/nia/enterprise/license#license-expiration-handling). -~> Enabling automatic license retrieval is recommended when using HCP Consul, as HCP Consul licenses expire more frequently than Consul Enterprise licenses. Without auto-retrieval enabled, you have to restart CTS every time you load a new license. +~> Enabling automatic license retrieval is recommended when using HCP Consul Dedicated, as HCP Consul Dedicated licenses expire more frequently than Consul Enterprise licenses. Without auto-retrieval enabled, you have to restart CTS every time you load a new license. ## Setting the License Manually diff --git a/website/content/docs/nia/index.mdx b/website/content/docs/nia/index.mdx index f5368f036fa0..453a2beb83e7 100644 --- a/website/content/docs/nia/index.mdx +++ b/website/content/docs/nia/index.mdx @@ -53,7 +53,7 @@ CTS is available as an open source and enterprise distribution. Follow the [Auto - `Tasks` - A task is the translation of dynamic service information from the Consul Catalog into network infrastructure changes downstream. -- `Terraform Cloud` - Per the [Terraform documentation](/terraform/cloud-docs), "Terraform Cloud" describes both Terraform Cloud and Terraform Enterprise, which are different distributions of the same application. Documentation will apply to both distributions unless specifically stated otherwise. +- `HCP Terraform` - Per the [Terraform documentation](/terraform/cloud-docs), "HCP Terraform" describes both HCP Terraform and Terraform Enterprise, which are different distributions of the same application. Documentation will apply to both distributions unless specifically stated otherwise. - `Terraform Module` - A [Terraform module](/terraform/language/modules) is a container for multiple Terraform resources that are used together. diff --git a/website/content/docs/nia/network-drivers/hcp-terraform.mdx b/website/content/docs/nia/network-drivers/hcp-terraform.mdx new file mode 100644 index 000000000000..4deb27ead9cf --- /dev/null +++ b/website/content/docs/nia/network-drivers/hcp-terraform.mdx @@ -0,0 +1,138 @@ +--- +layout: docs +page_title: HCP Terraform Driver +description: >- + Consul-Terraform-Sync Network Drivers with HCP Terraform +--- + +# HCP Terraform Driver + + This feature requires{' '} + Consul-Terraform-Sync Enterprise{' '} + which is available with Consul Enterprise. +
      + +Consul-Terraform-Sync (CTS) is more powerful when you integrate it with [HCP Terraform](https://cloud.hashicorp.com/products/terraform). Integrating with HCP Terraform provides features, such as enhanced workspaces and insight into Terraform operations as CTS dynamically updates your network infrastructure. CTS is compatible with both the [self-hosted](https://www.hashicorp.com/products/terraform/editions/enterprise) and [managed service](https://www.hashicorp.com/products/terraform/editions/cloud) versions of HCP Terraform. It also supports all [tiers](https://www.hashicorp.com/products/terraform/pricing) of the HCP Terraform managed service. + +This page describes how the HCP Terraform driver operates within CTS. + +## Terraform Workspace Automation + +CTS manages Terraform runs following the [API-driven run workflow](/terraform/cloud-docs/run/api) for workspaces in HCP Terraform. + +On startup, CTS: +1. Creates or discovers HCP Terraform workspaces corresponding to the configured tasks. +2. Prepares the local environment and generates Terraform configuration files that make up the root module for each task. +3. Packages the generated files and uploads them as a configuration version for the task's workspace on HCP Terraform. + +Once all workspaces are set up, CTS monitors the Consul catalog for service changes. When relevant changes are detected, the HCP Terraform driver dynamically updates input variables for that task directly as [workspace variables](/terraform/cloud-docs/workspaces/variables) using the HCP Terraform API. The driver then queues a run on the workspace, with auto-apply enabled, to update your network infrastructure. + +~> **Note:** Although workspaces for tasks are executed in isolated environments, this does not guarantee the infrastructure changes from concurrent task executions are independent. Ensure that modules across all tasks are not modifying the same resource objects or have overlapping changes that may result in race conditions during automation. + +## Remote Workspaces + +CTS will discover or create a new workspaces based on your configured tasks. The task configuration [`name`](/consul/docs/nia/configuration#name-1) and [`description`](/consul/docs/nia/configuration#description) are used to set the workspace name and description. The task configuration [`terraform_cloud_workspace`](/consul/docs/nia/configuration#terraform_cloud_workspace) is used to set options like Terraform version, execution mode, and agent pool if relevant. CTS will also use any globally set workspace configurations, specified in the driver configuration [`workspaces`](/consul/docs/nia/configuration#workspaces). + +[![CTS Workspace Overview](/img/nia/cts-tfc-workspace.png)](/img/nia/cts-tfc-workspace.png) + +Workspace automation requirements for CTS are in place to avoid overriding other workspaces unintentionally. +* Must be set to remote or agent execution mode +* Cannot be connected to a VCS +* Cannot have an existing configuration version uploaded by another application +* Must satisfy workspace [tag requirements](/consul/docs/nia/configuration#tags_allowlist) and [tag restrictions](/consul/docs/nia/configuration#tags_denylist) set by the CTS operator + +Workspaces created by CTS will be configured with the following settings: + +| Setting | Value | +| ------- | ----- | +| Workspace name | CTS task name | +| Description | CTS task description | +| Execution mode | [`task.terraform_cloud_workspace.execution_mode`](/consul/docs/nia/configuration#execution_mode) or remote by default | +| Apply method | Auto apply | +| Terraform Version | [`task.terraform_cloud_workspace.terraform_version`](/consul/docs/nia/configuration#terraform_version-1), [`task.terraform_version`](/consul/docs/nia/configuration#terraform_version) (deprecated), or the latest [Terraform version compatible with CTS](/consul/docs/nia/compatibility#terraform) available for the organization. | +| Tags | `source:cts` and [additional tags](/consul/docs/nia/configuration#tags) set by the CTS operator | + +Other workspace settings can be pre-configured or updated, such as setting the workspace to [manual apply](#manual-apply) or adding a [run notification](/terraform/cloud-docs/workspaces/settings/notifications) to send messages to a Slack channel when CTS updates your network infrastructure. + +### Manual Apply + +CTS can automate remote workspaces with either auto apply or manual apply configured. Having CTS manage workspaces with manual apply is useful to add an approval stage to CTS automation. Operators can manually inspect and approve or discard runs that CTS had queued based on the task run condition. + +When CTS detects new changes for a workspace that already has a run pending on approval, CTS will discard the stale run and queue a new run with the latest values. The new run will go through plan and then again wait on an operator to approve it. Only once the run is approved will the infrastructure be updated with the latest Consul changes. + +There are two approaches to setup manual apply for a workspace managed by CTS based on how the workspace is created. +* For CTS created workspaces, update the apply method from auto to manual via the HCP Terraform web application or API. +* For pre-configured workspaces, create the workspace prior to CTS task automation via the HCP Terraform web application or API. + 1. Create a workspace with the same name as the desired task. + 1. Set the workspace to [API-driven run workflow](/terraform/cloud-docs/run/api) and the execution mode to remote. + 1. Ensure that the apply method for the workspace is set to manual apply. + 1. Configure the task for the workspace and run CTS. + +-> **Tip**: Setup [run notifications](/terraform/cloud-docs/workspaces/settings/notifications#creating-a-notification-configuration) for workspaces with manual apply to not miss automated runs by CTS. Look into setting the [buffer period](/consul/docs/nia/configuration#buffer_period-1) or a [schedule condition](/consul/docs/nia/configuration#schedule-condition) to group changes together and reduce runs requiring approval. + +## Configuration Version + +An example configuration version for a task named "cts-example" would have the folder structure below when running with the HCP Terraform driver and using the default working directory. + +```shell-session +$ tree sync-tasks/ + +sync-tasks/ +└── cts-example/ + ├── main.tf + └── variables.tf +``` + +- `main.tf` - The main file contains the terraform block, provider blocks, and a module block calling the module configured for the task. + - `terraform` block - The corresponding provider source and versions for the task from the configuration files are placed into this block for the root module. + - `provider` blocks - The provider blocks generated in the root module resemble the `terraform_provider` blocks from the configuration for CTS. They have identical arguments present and are set from the intermediate variable created per provider. + - `module` block - The module block is where the task's module is called as a [child module](/terraform/language/modules#calling-a-child-module). The child module contains the core logic for automation. Required and optional input variables are passed as arguments to the module. +- `variables.tf` - This file contains three types of variable declarations: + - `services` input variable (required) determines module compatibility with Consul-Terraform Sync (read more on [compatible Terraform modules](/consul/docs/nia/terraform-modules) for more details). + - Any additional [optional input variables](/consul/docs/nia/terraform-modules#optional-input-variables) provided by CTS that the module may use. + - Various intermediate variables used to configure providers. Intermediate provider variables are interpolated from the provider blocks and arguments configured in the CTS configuration. +- `variables.module.tf` - This file is created if there are [variables configured for the task](/consul/docs/nia/configuration#variable_files) and contains the interpolated variable declarations that match the variables from configuration. These are then used to proxy the configured variables to the module through explicit assignment in the module block. + +## Variables + +CTS uses Terraform input variables to reflect the latest Consul service information. They are used as parameters for your Terraform module. Input variables are dynamic and are updated by the driver throughout the runtime of CTS. + +You can view the latest service information in the Terraform UI by navigating to that workspace and clicking the "Variables" tab in the workspace navigation. + +[![CTS Workspace Variables](/img/nia/cts-tfc-workspace-variables.png)](/img/nia/cts-tfc-workspace-variables.png) + +~> **Caution:** Dynamic variables maintained by CTS are formatted for automation. Unexpected manual changes to these variables may result in automation errors. + +## Setting Up HCP Terraform Driver + +### Deployment + +Because a CTS instance can only be configured with one driver, an instance can only be associated with either a Terraform driver or a HCP Terraform driver. If there is a need to run both types of drivers, users will need to deploy a separate CTS instance for each type of driver. Relatedly, if there is a need to run CTS across multiple HCP Terraform organizations, users will need to deploy a separate instance for each organization. + +### Required Setup + +This section captures requirements for setting up CTS to integrate with your [HCP Terraform](https://cloud.hashicorp.com/products/terraform) solution. + +1. Hostname of your HCP Terraform, self-hosted distribution +1. Name of your organization +1. [Team API token](/terraform/cloud-docs/users-teams-organizations/api-tokens) used for authentication with HCP Terraform + +Prior to running CTS with an HCP Terraform driver, you will need an account and organization set up, as well as a dedicated token. We recommend using a team token that is restricted to [Manage Workspaces](/terraform/cloud-docs/users-teams-organizations/teams#managing-workspace-access)-level permissions. Below are the steps for the recommended setup. + +The first step is to create an account with your HCP Terraform service. After creating an account, create a new [organization](/terraform/cloud-docs/users-teams-organizations/organizations#creating-organizations) or select an existing organization. The address of your HCP Terraform service will be used to configure the [`hostname`](/consul/docs/nia/configuration#hostname), and the organization name will be used to configure the [`organization`](/consul/docs/nia/configuration#organization) on the HCP Terraform driver. + +Once you have an account and organization, the next step is to [create a team](/terraform/cloud-docs/users-teams-organizations/teams). We recommend using a dedicated team and team token to run and authenticate CTS. Using a team token has the benefits of restricting organization permissions as well as associating CTS automated actions with the team rather than an individual. + +After creating a dedicated team, update the team's permissions with "Manage Workspaces" organization access-level. CTS's main work revolves around creating and managing workspaces. Therefore restricting the dedicated team's permission to Manage Workspaces level is sufficient and reduces security risk. + +[![CTS Terraform Team Setup](/img/nia/cts-tfc-team-setup.png)](/img/nia/cts-tfc-team-setup.png) + +After setting the team's permissions, the final setup step is to [generate the associated team token](/terraform/cloud-docs/users-teams-organizations/api-tokens), which can be done on the same team management page. This token will be used by CTS for API authentication and will be used to configure the [`token`](/consul/docs/nia/configuration#token) on the HCP Terraform driver. + +### Recommendations + +We recommend configuring workspaces managed by CTS with [run notifications](/terraform/cloud-docs/workspaces/settings/notifications) through the Terraform web application. Run notifications notify external systems about the progress of runs and could help notify users of CTS events, particularly errored runs. + +[![CTS HCP Terraform Run Notifications](/img/nia/cts-tfc-run-notifications.png)](/img/nia/cts-tfc-run-notifications.png) + +In order to configure a run notification, users can [manually create a notification configuration](/terraform/cloud-docs/workspaces/settings/notifications#creating-a-notification-configuration) for workspaces automated by CTS. A workspace may already exist for a task if the workspace name is identical to the configured task's [`name`](/consul/docs/nia/configuration#name-2). This may occur if CTS has already already run and created the workspace for the task. This may also occur if the workspace is manually created for the task prior to CTS running. diff --git a/website/content/docs/nia/network-drivers/index.mdx b/website/content/docs/nia/network-drivers/index.mdx index 6bed69a7795b..dd89f448d9bd 100644 --- a/website/content/docs/nia/network-drivers/index.mdx +++ b/website/content/docs/nia/network-drivers/index.mdx @@ -2,7 +2,7 @@ layout: docs page_title: Network Drivers description: >- - Consul-Terraform-Sync Network Drivers with Terraform and Terraform Cloud + Consul-Terraform-Sync Network Drivers with Terraform and HCP Terraform --- # Network Drivers @@ -11,18 +11,18 @@ Consul-Terraform-Sync (CTS) uses network drivers to execute and update network i CTS is a HashiCorp solution to Network Infrastructure Automation. It bridges Consul's networking features and Terraform infrastructure management capabilities. The solution seamlessly embeds Terraform as network drivers to manage automation of Terraform modules. This expands the Consul ecosystem and taps into the rich features and community of Terraform and Terraform providers. -The following table highlights some of the additional features Terraform and Terraform Cloud offer when used as a network driver for CTS. Visit the [Terraform product page](https://www.hashicorp.com/products/terraform) or [contact our sales team](https://www.hashicorp.com/contact-sales) for a comprehensive list of features. +The following table highlights some of the additional features Terraform and HCP Terraform offer when used as a network driver for CTS. Visit the [Terraform product page](https://www.hashicorp.com/products/terraform) or [contact our sales team](https://www.hashicorp.com/contact-sales) for a comprehensive list of features. | Network Driver | Description | Features | | -------------- | ----------- | -------- | | [Terraform driver](/consul/docs/nia/network-drivers/terraform) | CTS automates a local installation of the [Terraform CLI](https://www.terraform.io/) | - Local Terraform execution
      - Local workspace directories
      - [Backend options](/consul/docs/nia/configuration#backend) available for state storage
      | -| [Terraform Cloud driver](/consul/docs/nia/network-drivers/terraform-cloud) | CTS Enterprise automates remote workspaces on [Terraform Cloud](/terraform/cloud-docs) | - [Remote Terraform execution](/terraform/cloud-docs/run/remote-operations)
      - Concurrent runs
      - [Secured variables](/terraform/cloud-docs/workspaces/variables)
      - [State versions](/terraform/cloud-docs/workspaces/state)
      - [Sentinel](/terraform/cloud-docs/policy-enforcement) to enforce governance policies as code
      - Audit [logs](/terraform/enterprise/admin/infrastructure/logging) and [trails](/terraform/cloud-docs/api-docs/audit-trails)
      - Run [history](/terraform/cloud-docs/run/manage), [triggers](/terraform/cloud-docs/workspaces/settings/run-triggers), and [notifications](/terraform/cloud-docs/workspaces/settings/notifications)
      - [Terraform Cloud Agents](/terraform/cloud-docs/agents) | +| [HCP Terraform driver](/consul/docs/nia/network-drivers/terraform-cloud) | CTS Enterprise automates remote workspaces on [HCP Terraform](/terraform/cloud-docs) | - [Remote Terraform execution](/terraform/cloud-docs/run/remote-operations)
      - Concurrent runs
      - [Secured variables](/terraform/cloud-docs/workspaces/variables)
      - [State versions](/terraform/cloud-docs/workspaces/state)
      - [Sentinel](/terraform/cloud-docs/policy-enforcement) to enforce governance policies as code
      - Audit [logs](/terraform/enterprise/admin/infrastructure/logging) and [trails](/terraform/cloud-docs/api-docs/audit-trails)
      - Run [history](/terraform/cloud-docs/run/manage), [triggers](/terraform/cloud-docs/workspaces/settings/run-triggers), and [notifications](/terraform/cloud-docs/workspaces/settings/notifications)
      - [Terraform Cloud Agents](/terraform/cloud-docs/agents) | ## Understanding Terraform Automation CTS automates Terraform execution using a templated configuration to carry out infrastructure changes. The auto-generated configuration leverages input variables sourced from Consul and builds on top of reusable Terraform modules published and maintained by HashiCorp partners and the community. CTS can also run your custom built modules that suit your team's specific network automation needs. -The network driver for CTS determines how the Terraform automation operates. Visit the driver pages to read more about the [Terraform driver](/consul/docs/nia/network-drivers/terraform) and the [Terraform Cloud driver](/consul/docs/nia/network-drivers/terraform-cloud). +The network driver for CTS determines how the Terraform automation operates. Visit the driver pages to read more about the [Terraform driver](/consul/docs/nia/network-drivers/terraform) and the [HCP Terraform driver](/consul/docs/nia/network-drivers/terraform-cloud). ### Upgrading Terraform diff --git a/website/content/docs/nia/network-drivers/terraform-cloud.mdx b/website/content/docs/nia/network-drivers/terraform-cloud.mdx deleted file mode 100644 index 2a9c3845078b..000000000000 --- a/website/content/docs/nia/network-drivers/terraform-cloud.mdx +++ /dev/null @@ -1,138 +0,0 @@ ---- -layout: docs -page_title: Terraform Cloud Driver -description: >- - Consul-Terraform-Sync Network Drivers with Terraform Cloud ---- - -# Terraform Cloud Driver - - This feature requires{' '} - Consul-Terraform-Sync Enterprise{' '} - which is available with Consul Enterprise. - - -Consul-Terraform-Sync (CTS) is more powerful when you integrate it with [Terraform Cloud](https://cloud.hashicorp.com/products/terraform). Integrating with Terraform Cloud provides features, such as enhanced workspaces and insight into Terraform operations as CTS dynamically updates your network infrastructure. CTS is compatible with both the [self-hosted](https://www.hashicorp.com/products/terraform/editions/enterprise) and [managed service](https://www.hashicorp.com/products/terraform/editions/cloud) versions of Terraform Cloud. It also supports all [tiers](https://www.hashicorp.com/products/terraform/pricing) of the Terraform Cloud managed service. - -This page describes how the Terraform Cloud driver operates within CTS. - -## Terraform Workspace Automation - -CTS manages Terraform runs following the [API-driven run workflow](/terraform/cloud-docs/run/api) for workspaces in Terraform Cloud. - -On startup, CTS: -1. Creates or discovers Terraform Cloud workspaces corresponding to the configured tasks. -2. Prepares the local environment and generates Terraform configuration files that make up the root module for each task. -3. Packages the generated files and uploads them as a configuration version for the task's workspace on Terraform Cloud. - -Once all workspaces are set up, CTS monitors the Consul catalog for service changes. When relevant changes are detected, the Terraform Cloud driver dynamically updates input variables for that task directly as [workspace variables](/terraform/cloud-docs/workspaces/variables) using the Terraform Cloud API. The driver then queues a run on the workspace, with auto-apply enabled, to update your network infrastructure. - -~> **Note:** Although workspaces for tasks are executed in isolated environments, this does not guarantee the infrastructure changes from concurrent task executions are independent. Ensure that modules across all tasks are not modifying the same resource objects or have overlapping changes that may result in race conditions during automation. - -## Remote Workspaces - -CTS will discover or create a new workspaces based on your configured tasks. The task configuration [`name`](/consul/docs/nia/configuration#name-1) and [`description`](/consul/docs/nia/configuration#description) are used to set the workspace name and description. The task configuration [`terraform_cloud_workspace`](/consul/docs/nia/configuration#terraform_cloud_workspace) is used to set options like Terraform version, execution mode, and agent pool if relevant. CTS will also use any globally set workspace configurations, specified in the driver configuration [`workspaces`](/consul/docs/nia/configuration#workspaces). - -[![CTS Workspace Overview](/img/nia/cts-tfc-workspace.png)](/img/nia/cts-tfc-workspace.png) - -Workspace automation requirements for CTS are in place to avoid overriding other workspaces unintentionally. -* Must be set to remote or agent execution mode -* Cannot be connected to a VCS -* Cannot have an existing configuration version uploaded by another application -* Must satisfy workspace [tag requirements](/consul/docs/nia/configuration#tags_allowlist) and [tag restrictions](/consul/docs/nia/configuration#tags_denylist) set by the CTS operator - -Workspaces created by CTS will be configured with the following settings: - -| Setting | Value | -| ------- | ----- | -| Workspace name | CTS task name | -| Description | CTS task description | -| Execution mode | [`task.terraform_cloud_workspace.execution_mode`](/consul/docs/nia/configuration#execution_mode) or remote by default | -| Apply method | Auto apply | -| Terraform Version | [`task.terraform_cloud_workspace.terraform_version`](/consul/docs/nia/configuration#terraform_version-1), [`task.terraform_version`](/consul/docs/nia/configuration#terraform_version) (deprecated), or the latest [Terraform version compatible with CTS](/consul/docs/nia/compatibility#terraform) available for the organization. | -| Tags | `source:cts` and [additional tags](/consul/docs/nia/configuration#tags) set by the CTS operator | - -Other workspace settings can be pre-configured or updated, such as setting the workspace to [manual apply](#manual-apply) or adding a [run notification](/terraform/cloud-docs/workspaces/settings/notifications) to send messages to a Slack channel when CTS updates your network infrastructure. - -### Manual Apply - -CTS can automate remote workspaces with either auto apply or manual apply configured. Having CTS manage workspaces with manual apply is useful to add an approval stage to CTS automation. Operators can manually inspect and approve or discard runs that CTS had queued based on the task run condition. - -When CTS detects new changes for a workspace that already has a run pending on approval, CTS will discard the stale run and queue a new run with the latest values. The new run will go through plan and then again wait on an operator to approve it. Only once the run is approved will the infrastructure be updated with the latest Consul changes. - -There are two approaches to setup manual apply for a workspace managed by CTS based on how the workspace is created. -* For CTS created workspaces, update the apply method from auto to manual via the Terraform Cloud web application or API. -* For pre-configured workspaces, create the workspace prior to CTS task automation via the Terraform Cloud web application or API. - 1. Create a workspace with the same name as the desired task. - 1. Set the workspace to [API-driven run workflow](/terraform/cloud-docs/run/api) and the execution mode to remote. - 1. Ensure that the apply method for the workspace is set to manual apply. - 1. Configure the task for the workspace and run CTS. - --> **Tip**: Setup [run notifications](/terraform/cloud-docs/workspaces/settings/notifications#creating-a-notification-configuration) for workspaces with manual apply to not miss automated runs by CTS. Look into setting the [buffer period](/consul/docs/nia/configuration#buffer_period-1) or a [schedule condition](/consul/docs/nia/configuration#schedule-condition) to group changes together and reduce runs requiring approval. - -## Configuration Version - -An example configuration version for a task named "cts-example" would have the folder structure below when running with the Terraform Cloud driver and using the default working directory. - -```shell-session -$ tree sync-tasks/ - -sync-tasks/ -└── cts-example/ - ├── main.tf - └── variables.tf -``` - -- `main.tf` - The main file contains the terraform block, provider blocks, and a module block calling the module configured for the task. - - `terraform` block - The corresponding provider source and versions for the task from the configuration files are placed into this block for the root module. - - `provider` blocks - The provider blocks generated in the root module resemble the `terraform_provider` blocks from the configuration for CTS. They have identical arguments present and are set from the intermediate variable created per provider. - - `module` block - The module block is where the task's module is called as a [child module](/terraform/language/modules#calling-a-child-module). The child module contains the core logic for automation. Required and optional input variables are passed as arguments to the module. -- `variables.tf` - This file contains three types of variable declarations: - - `services` input variable (required) determines module compatibility with Consul-Terraform Sync (read more on [compatible Terraform modules](/consul/docs/nia/terraform-modules) for more details). - - Any additional [optional input variables](/consul/docs/nia/terraform-modules#optional-input-variables) provided by CTS that the module may use. - - Various intermediate variables used to configure providers. Intermediate provider variables are interpolated from the provider blocks and arguments configured in the CTS configuration. -- `variables.module.tf` - This file is created if there are [variables configured for the task](/consul/docs/nia/configuration#variable_files) and contains the interpolated variable declarations that match the variables from configuration. These are then used to proxy the configured variables to the module through explicit assignment in the module block. - -## Variables - -CTS uses Terraform input variables to reflect the latest Consul service information. They are used as parameters for your Terraform module. Input variables are dynamic and are updated by the driver throughout the runtime of CTS. - -You can view the latest service information in the Terraform UI by navigating to that workspace and clicking the "Variables" tab in the workspace navigation. - -[![CTS Workspace Variables](/img/nia/cts-tfc-workspace-variables.png)](/img/nia/cts-tfc-workspace-variables.png) - -~> **Caution:** Dynamic variables maintained by CTS are formatted for automation. Unexpected manual changes to these variables may result in automation errors. - -## Setting Up Terraform Cloud Driver - -### Deployment - -Because a CTS instance can only be configured with one driver, an instance can only be associated with either a Terraform driver or a Terraform Cloud driver. If there is a need to run both types of drivers, users will need to deploy a separate CTS instance for each type of driver. Relatedly, if there is a need to run CTS across multiple Terraform Cloud organizations, users will need to deploy a separate instance for each organization. - -### Required Setup - -This section captures requirements for setting up CTS to integrate with your [Terraform Cloud](https://cloud.hashicorp.com/products/terraform) solution. - -1. Hostname of your Terraform Cloud, self-hosted distribution -1. Name of your organization -1. [Team API token](/terraform/cloud-docs/users-teams-organizations/api-tokens) used for authentication with Terraform Cloud - -Prior to running CTS with a Terraform Cloud driver, you will need an account and organization set up, as well as a dedicated token. We recommend using a team token that is restricted to [Manage Workspaces](/terraform/cloud-docs/users-teams-organizations/teams#managing-workspace-access)-level permissions. Below are the steps for the recommended setup. - -The first step is to create an account with your Terraform Cloud service. After creating an account, create a new [organization](/terraform/cloud-docs/users-teams-organizations/organizations#creating-organizations) or select an existing organization. The address of your Terraform Cloud service will be used to configure the [`hostname`](/consul/docs/nia/configuration#hostname), and the organization name will be used to configure the [`organization`](/consul/docs/nia/configuration#organization) on the Terraform Cloud driver. - -Once you have an account and organization, the next step is to [create a team](/terraform/cloud-docs/users-teams-organizations/teams). We recommend using a dedicated team and team token to run and authenticate CTS. Using a team token has the benefits of restricting organization permissions as well as associating CTS automated actions with the team rather than an individual. - -After creating a dedicated team, update the team's permissions with "Manage Workspaces" organization access-level. CTS's main work revolves around creating and managing workspaces. Therefore restricting the dedicated team's permission to Manage Workspaces level is sufficient and reduces security risk. - -[![CTS Terraform Team Setup](/img/nia/cts-tfc-team-setup.png)](/img/nia/cts-tfc-team-setup.png) - -After setting the team's permissions, the final setup step is to [generate the associated team token](/terraform/cloud-docs/users-teams-organizations/api-tokens), which can be done on the same team management page. This token will be used by CTS for API authentication and will be used to configure the [`token`](/consul/docs/nia/configuration#token) on the Terraform Cloud driver. - -### Recommendations - -We recommend configuring workspaces managed by CTS with [run notifications](/terraform/cloud-docs/workspaces/settings/notifications) through the Terraform web application. Run notifications notify external systems about the progress of runs and could help notify users of CTS events, particularly errored runs. - -[![CTS Terraform Cloud Run Notifications](/img/nia/cts-tfc-run-notifications.png)](/img/nia/cts-tfc-run-notifications.png) - -In order to configure a run notification, users can [manually create a notification configuration](/terraform/cloud-docs/workspaces/settings/notifications#creating-a-notification-configuration) for workspaces automated by CTS. A workspace may already exist for a task if the workspace name is identical to the configured task's [`name`](/consul/docs/nia/configuration#name-2). This may occur if CTS has already already run and created the workspace for the task. This may also occur if the workspace is manually created for the task prior to CTS running. diff --git a/website/content/docs/nia/usage/requirements.mdx b/website/content/docs/nia/usage/requirements.mdx index 0fcdf1645ac1..e7c5fe8c8798 100644 --- a/website/content/docs/nia/usage/requirements.mdx +++ b/website/content/docs/nia/usage/requirements.mdx @@ -15,7 +15,7 @@ The following components are required to run Consul-Terraform-Sync (CTS): You can add support for your network infrastructure through Terraform providers so that you can apply Terraform modules to implement network integrations. -The following guidance is for running CTS using the Terraform driver. The Terraform Cloud driver has [additional prerequisites](/consul/docs/nia/network-drivers/terraform-cloud#setting-up-terraform-cloud-driver). +The following guidance is for running CTS using the Terraform driver. The HCP Terraform driver has [additional prerequisites](/consul/docs/nia/network-drivers/terraform-cloud#setting-up-terraform-cloud-driver). ## Run a Consul cluster diff --git a/website/content/docs/nia/usage/run-ha.mdx b/website/content/docs/nia/usage/run-ha.mdx index 6152007255b7..7ef90e29d082 100644 --- a/website/content/docs/nia/usage/run-ha.mdx +++ b/website/content/docs/nia/usage/run-ha.mdx @@ -35,7 +35,7 @@ The following diagram shows the CTS cluster state after the leader stops. CTS In - The time it takes for a new leader to be elected is determined by the `high_availability.cluster.storage.session_ttl` configuration. The minimum failover time is equal to the `session_ttl` value. The maximum failover time is double the `session_ttl` value. - If failover occurs during task execution, a new leader is elected. The new leader will attempt to run all tasks once before continuing to monitor for changes. -- If using the [Terraform Cloud (TFC) driver](/consul/docs/nia/network-drivers/terraform-cloud), the task finishes and CTS starts a new leader that attempts to queue a run for each task in TFC in once-mode. +- If using the [HCP Terraform driver](/consul/docs/nia/network-drivers/terraform-cloud), the task finishes and CTS starts a new leader that attempts to queue a run for each task in HCP Terraform in once-mode. - If using [Terraform driver](/consul/docs/nia/network-drivers/terraform), the task may complete depending on the cause of the failover. The new leader starts and attempts to run each task in [once-mode](/consul/docs/nia/cli/start#modes). Depending on the module and provider, the task may require manual intervention to fix any inconsistencies between the infrastructure and Terraform state. - If failover occurs when no task is executing, CTS elects a new leader that attempts to run all tasks in once-mode. @@ -51,7 +51,7 @@ Verify that you have met the [basic requirements](/consul/docs/nia/usage/require You must configure appropriate ACL permissions for your cluster. Refer to [ACL permissions](#) for details. -We recommend specifying the [TFC driver](/consul/docs/nia/network-drivers/terraform-cloud) in your CTS configuration if you want to run in high availability mode. +We recommend specifying the [HCP Terraform driver](/consul/docs/nia/network-drivers/terraform-cloud) in your CTS configuration if you want to run in high availability mode. ## Configuration diff --git a/website/content/docs/nomad/index.mdx b/website/content/docs/nomad/index.mdx new file mode 100644 index 000000000000..a9ba57fb6a09 --- /dev/null +++ b/website/content/docs/nomad/index.mdx @@ -0,0 +1,58 @@ +--- +layout: docs +page_title: Consul on Nomad +description: >- + Consul is a service networking solution that you can run with Nomad. Learn more about Consul on Nomad and find documentation specific to the Nomad runtime. +--- + +# Consul on Nomad + +This topic provides an overview of the documentation available for users running Consul with Nomad. + +For more information about using Nomad to schedule clusters and applications, refer to the [Nomad documentation](/nomad/docs). + +## Introduction + +Nomad is HashiCorp’s workload orchestrator. It enables you to run containers, legacy, and batch applications together on the same infrastructure. Just like a Consul client runs as a system daemon on a worker node, Nomad is deployed in a similar fashion. In order to use Consul with Nomad, you must configure Nomad to access the Consul cluster. We recommend running a Consul client alongside each Nomad client. + +Consul and Nomad operate independently in their deployment and functions, but can integrate to simplify the other’s operations. For example, Nomad can register tasks as services in the Consul catalog and configure sidecar proxies. Furthermore, Nomad servers can also register themselves as a service in Consul, which helps with bootstrapping a Nomad cluster. + +Deployments in Nomad can take advantage of Consul service discovery, service mesh, or both. You can leverage Consul DNS and run the Nomad service workloads, or start a sidecar process for each service to abstract the networking layer within the service mesh environment. + +Nomad supports the following Consul features: + +- Automatic clustering +- Concurrent connections to multiple Consul clusters +- Service discovery +- Service mesh +- Key/value store for dynamic application configuration +- Consul access controls +- Namespaces +- Admin partitions + +## Tutorials + +If you are familiar with virtualized workloads in a Linux environment, we recommend you attempt the [Nomad getting started tutorials](/nomad/tutorials/get-started) to get acquainted with the basics of running workloads in Nomad. Then complete the [Consul getting started on VMs tutorials](/consul/tutorials/get-started-vms) to learn how to configure and deploy Consul. Then review the dedicated Consul and Nomad tutorials to understand how both systems interact together. + +To learn more about using Consul with Nomad, refer to the following tutorials in the Nomad documentation: + +- [Convert from Nomad service discovery to Consul service discovery](/nomad/tutorials/service-discovery/service-discovery-consul-conversion) +- [Secure Nomad jobs with Consul service mesh](/nomad/tutorials/integrate-consul/consul-service-mesh) +- [Consul ACL with Nomad Workload Identities](/nomad/tutorials/integrate-consul/consul-acl) +- [Use Consul to automatically cluster Nomad nodes](/nomad/tutorials/manage-clusters/clustering#use-consul-to-automatically-cluster-nodes) + +## Nomad documentation + +[Nomad Consul Service Integration](/nomad/docs/integrations/consul/service-mesh) enables Nomad users to automatically register services to Consul and deploy sidecar proxies alongside their services. The following resources are available in the Nomad documentation to help you define Consul jobs: + +- [consul Block specification](/nomad/docs/job-specification/consul) +- [connect Block specification](/nomad/docs/job-specification/connect) +- [check Block specification](/nomad/docs/job-specification/check) +- [check_restart Block specification](/nomad/docs/job-specification/check_restart) +- [gateway Block specification](/nomad/docs/job-specification/gateway) +- [identity Block specification](/nomad/docs/job-specification/identity) +- [proxy Block specification](/nomad/docs/job-specification/proxy) +- [service Block specification](/nomad/docs/job-specification/service) +- [sidecar_service Block specification](/nomad/docs/job-specification/sidecar_service) +- [sidecar_task Block specification](/nomad/docs/job-specification/sidecar_task) +- [upstreams Block specification](/nomad/docs/job-specification/upstreams) \ No newline at end of file diff --git a/website/content/docs/release-notes/consul-api-gateway/v0_1_x.mdx b/website/content/docs/release-notes/consul-api-gateway/v0_1_x.mdx index efb65ec71adf..6f20ae97aff7 100644 --- a/website/content/docs/release-notes/consul-api-gateway/v0_1_x.mdx +++ b/website/content/docs/release-notes/consul-api-gateway/v0_1_x.mdx @@ -36,7 +36,7 @@ This release includes the following features and capabilities: - Google GKE - Azure AKS. 1. Install via the HashiCorp Consul Helm chart. -1. Works with self-managed Consul servers and HCP Consul servers +1. Works with self-managed Consul Enterprise servers and HCP Consul Dedicated servers 1. Configure via Kubernetes Gateway API - v1alpha2 1. Deploy 1 or more logical API Gateways per Kubernetes cluster 1. Support for HTTP, HTTPS, TCP, and TCP+TLS diff --git a/website/content/docs/release-notes/consul-k8s/v1_2_x.mdx b/website/content/docs/release-notes/consul-k8s/v1_2_x.mdx index a606042f1f44..60c6597fd52a 100644 --- a/website/content/docs/release-notes/consul-k8s/v1_2_x.mdx +++ b/website/content/docs/release-notes/consul-k8s/v1_2_x.mdx @@ -51,7 +51,7 @@ We are pleased to announce the following Consul updates. Consul's API gateway is the recommended alternative to ingress gateway. For ingress gateway features not currently supported by API gateway, equivalent functionality will be added to API gateway over the next several releases of Consul. -- **Legacy API Gateway:** The Consul AP Gateway that was previously packaged (`consul-api-gateway`) and released separately from Consul K8s is now deprecated. This is referred to as the "legacy" API Gateway. +- **Legacy API Gateway:** The Consul API Gateway that was previously packaged (`consul-api-gateway`) and released separately from Consul K8s is now deprecated. This is referred to as the "legacy" API Gateway. The legacy API Gateway (v0.5.4) is supported with this version of Consul on Kubernetes in order to simplify the process of migrating from legacy to native API gateways. @@ -66,7 +66,7 @@ We are pleased to announce the following Consul updates. Consul 1.15.x and 1.14.x are not supported. Please refer to Supported Consul and Kubernetes versions for more detail on choosing the correct consul-k8s version. - Consul 1.16.x. -- Consul Dataplane v1.2.x. Refer to Envoy and Consul Dataplane for details about Consul Dataplane versions and the available packaged Envoy version. +- Consul Dataplane v1.2.x. Refer to [Envoy and Consul Dataplane](/consul/docs/v1.16.x/connect/proxies/envoy#envoy-and-consul-dataplane) for details about Consul Dataplane versions and the available packaged Envoy version. - Kubernetes 1.24.x - 1.27.x - kubectl 1.24.x - 1.27.x - Helm 3.6+ @@ -75,6 +75,14 @@ We are pleased to announce the following Consul updates. For more detailed information, please refer to the [upgrade details page](/consul/docs/upgrading/upgrade-specific) and the changelogs. +## Known Issues + +The following issues are known to exist in the v1.2.x releases. Refer to the changelog for more information. + +- v1.2.8 - Service-to-service networking is broken when deployed on OpenShift. OpenShift users are advised to avoid deploying this version of consul-k8s. + A fix is present in the v1.2.9 release [[GH-4038](https://github.com/hashicorp/consul-k8s/pull/4038)]. + + ## Changelogs The changelogs for this major release version and any maintenance versions are listed below. diff --git a/website/content/docs/release-notes/consul-k8s/v1_3_x.mdx b/website/content/docs/release-notes/consul-k8s/v1_3_x.mdx index 5282460674af..4ac0284255b0 100644 --- a/website/content/docs/release-notes/consul-k8s/v1_3_x.mdx +++ b/website/content/docs/release-notes/consul-k8s/v1_3_x.mdx @@ -11,27 +11,31 @@ We are pleased to announce the following Consul updates. ## Release highlights -- **Catalog v2:** This release provides the ability to preview Consul's v2 Catalog and Resource API. You must enable this feature. -Catalog v2 supports multi-port application deployments with a single Envoy proxy. Refer to the [v2 Catalog and Resource API](/consul/docs/v1.17.x/k8s/multiport) documentation for more information. +**Catalog v2:** This release provides the ability to preview Consul's v2 Catalog and Resource API. You must enable this feature. +Catalog v2 supports multi-port application deployments with a single Envoy proxy. Refer to the [v2 Catalog and Resource API](/consul/docs/k8s/multiport) documentation for more information. The v1 and v2 catalogs are not cross compatible, and not all Consul features are available within this v2 feature preview. + - The Consul UI must be disabled. It does not support multi-port services or the v2 catalog API in this release. + - HCP Consul Dedicated does not support multi-port services or the v2 catalog API in this release. + - The v2 API only supports transparent proxy mode where services that have permissions to connect to each other can use Kube DNS to connect. - - The Consul UI must be disabled. It does not support multi-port services or the v2 catalog API in this release. - - HCP Consul does not support multi-port services or the v2 catalog API in this release. - - The v2 API only supports transparent proxy mode where services that have permissions to connect to each other can use Kube DNS to connect. - - The v2 Catalog and Resources API is currently in feature preview for Consul on Kubernetes 1.3.0 and should not be used in production environments. + The v2 Catalog and Resources API is currently in feature preview for Consul on Kubernetes 1.3.0 and should not be used in production environments. ## Supported software Consul 1.15.x and 1.14.x are not supported. Please refer to Supported Consul and Kubernetes versions for more detail on choosing the correct consul-k8s version. - Consul 1.17.x. -- Consul Dataplane v1.2.x. Refer to Envoy and Consul Dataplane for details about Consul Dataplane versions and the available packaged Envoy version. +- Consul Dataplane v1.3.x. Refer to [Envoy and Consul Dataplane](/consul/docs/v1.17.x/connect/proxies/envoy#envoy-and-consul-dataplane) for details about Consul Dataplane versions and the available packaged Envoy version. - Kubernetes 1.24.x - 1.27.x - kubectl 1.24.x - 1.27.x - Helm 3.6+ + +## What's removed + +- **Legacy API Gateway support is removed**: The Consul API Gateway that was previously packaged as `consul-api-gateway`, released separately from Consul K8s, and deprecated in Consul v1.16.x is now removed. This gateway is referred to as the _legacy API Gateway_. As of Consul v1.17.0, you must [install](/consul/docs/connect/gateways/api-gateway/install-k8s) the _native API Gateway_ and configure it using the [`connectInject.apiGateway`](/consul/docs/k8s/helm#apigateway) stanza. + ## Upgrading For more detailed information, please refer to the [upgrade details page](/consul/docs/upgrading/upgrade-specific) and the changelogs. @@ -41,6 +45,8 @@ For more detailed information, please refer to the [upgrade details page](/consu The following issues are known to exist in the v1.3.x releases. Refer to the changelog for more information. - When using the v2 API with transparent proxy, Kubernetes pods cannot use L7 liveness, readiness, or startup probes. +- v1.3.5 - Service-to-service networking is broken when deployed on OpenShift. OpenShift users are advised to avoid deploying this version of consul-k8s. + A fix is present in the v1.3.6 release [[GH-4037](https://github.com/hashicorp/consul-k8s/pull/4037)]. ## Changelogs diff --git a/website/content/docs/release-notes/consul-k8s/v1_4_x.mdx b/website/content/docs/release-notes/consul-k8s/v1_4_x.mdx new file mode 100644 index 000000000000..ec264b135954 --- /dev/null +++ b/website/content/docs/release-notes/consul-k8s/v1_4_x.mdx @@ -0,0 +1,57 @@ +--- +layout: docs +page_title: 1.4.x +description: >- + Consul on Kubernetes release notes for version 1.4.x +--- + +# Consul on Kubernetes 1.4.0 + +We are pleased to announce the following Consul updates. + +## Release highlights + +- **Consul catalog v2 API updates:** Additional improvements were made to the v2 catalog API, which supports [registering a service with multiple ports or selecting a workload using multiple services on Kubernetes deployments](/consul/docs/k8s/multiport). End user facing changes include the ability to use a service's ports in xRoute configurations as opposed to the workload port for reference in the parentRef stanza of the xRoute configuration, and the change in Traffic Permissions to only allow `ACTION_DENY` for Consul Enterprise as it will enable future governance related workflows. + + The v2 catalog API is currently available for Consul on Kubernetes deployments only. Refer to [Consul v2 architecture](/consul/docs/architecture/v2) for more information. + +- **Consul Long Term Support (LTS) (Enterprise):** Consul Enterprise users can now receive Long Term Support for approximately 2 years on some Consul releases, starting with Consul Enterprise v1.15. During the LTS window, eligible fixes are provided through a new minor release on the affected LTS release branch. + + An LTS release is planned for every 3 releases, and it is maintained until it is 6 releases from the latest major release. For example, Consul Enterprise v1.15.x, v1.18x, and v1.21.x are the next three planned releases. The LTS period for Consul Enterprise v1.15.x ends when Consul Enterprise v1.21.0 releases. + + For more information, refer to [Consul Enterprise Long Term Support](/consul/docs/enterprise/long-term-support). + +- **Fault injection (Enterprise):** For Enterprise users, Consul’s service mesh now supports managing traffic with fault injection behavior that is defined in an upstream service’s service defaults CRD. Supported fault injection behavior includes delaying, aborting, and rate limiting traffic between services. You can use fault injection to test your network’s resilience under different conditions. + + For more information, refer to [fault injection](/consul/docs/connect/manage-traffic/fault-injection). + +## Supported software + +This version of Kubernetes supports the following software versions: + +- Consul 1.18.x +- Consul Dataplane v1.4.x. Refer to [Envoy and Consul Dataplane](/consul/docs/v1.18.x/connect/proxies/envoy#envoy-and-consul-dataplane) for details about Consul Dataplane versions and the available packaged Envoy version. +- Kubernetes 1.26.x - 1.29.x +- kubectl 1.26.x - 1.29.x +- Helm 3.11.3+ + +Refer to [Supported Consul and Kubernetes versions](/consul/docs/v1.18.x/k8s/compatibility#supported-consul-and-kubernetes-versions) for more information. + +## Upgrading + +For more detailed information, please refer to the [upgrade details page](/consul/docs/upgrading/upgrade-specific) and the changelogs. + +## Known issues + +The following issues are known to exist in the v1.4.x releases: + +- v1.4.2 - Service-to-service networking is broken when deployed on OpenShift. OpenShift users are advised to avoid deploying this version of consul-k8s. + A fix is present in the v1.4.3 release [[GH-4034](https://github.com/hashicorp/consul-k8s/pull/4034)]. + +## Changelogs + +The changelogs for this major release version and any maintenance versions are listed below. + + These links take you to the changelogs on the GitHub website. + +- [1.4.0](https://github.com/hashicorp/consul-k8s/releases/tag/v1.4.0) diff --git a/website/content/docs/release-notes/consul-k8s/v1_5_x.mdx b/website/content/docs/release-notes/consul-k8s/v1_5_x.mdx new file mode 100644 index 000000000000..005a21df37fc --- /dev/null +++ b/website/content/docs/release-notes/consul-k8s/v1_5_x.mdx @@ -0,0 +1,48 @@ +--- +layout: docs +page_title: 1.5.x +description: >- + Consul on Kubernetes release notes for version 1.5.x +--- + +# Consul on Kubernetes 1.5.0 + +We are pleased to announce the following Consul updates. + +## Release highlights + +- **External Services CRD**: You can now configure and register external services, including their health checks, alongside existing Kubernetes application manifests with the new [`Registration` Custom Resource Definition (CRD)](/consul/docs/connect/config-entries/registration). This CRD changes the workflow to register a service running on an external node with the Consul catalog. A terminating gateway is still required to enable downstream services in the service mesh to communicate with external services. Refer to [Register external services on Kubernetes overview](/consul/docs/k8s/deployment-configurations/external-service) for more information. + +- **File system certificate**: A new [`file-system-certificate` configuration entry](/consul/docs/connect/config-entries/file-system-certificate) for Consul API Gateway on VMs supports specifying a filepath to the certificate and private key on the local system. Consul on Kubernetes deployments that use `consul-k8s` Helm chart v1.5.0 or later use file system certificates instead of inline certificates without additional configuration. For information about certificate configuration for Kubernetes environments, refer to [Gateway Resource Configuration](/consul/docs/connect/gateways/api-gateway/configuration/gateway). + +- **v2 catalog API deprecation**: Consul introduced an experimental v2 Catalog API in v1.17.0. This API supported multi-port Service configurations on Kubernetes, and it was made available for testing and development purposes. The v2 catalog and its support for multiport Kubernetes Services were deprecated in the v1.19.0 release. + +- **Argo Rollouts Plugin**: A new Argo Rollouts plugin for progressive delivery is now available for `consul-k8s`. This plugin supports canary deployments by allowing you to incrementally release and test new versions of applications and roll back to previous versions by splitting traffic between subsets of services. Refer to [Argo Rollouts Progressive Delivery with Consul on Kubernetes](/consul/docs/k8s/deployment-configurations/argo-rollouts-configuration) for more information. + +## Supported software + +This version of Consul on Kubernetes supports the following software versions: + +- Consul v1.19.x +- Consul Dataplane v1.5.x. Refer to [Envoy and Consul Dataplane](/consul/docs/v1.19.x/connect/proxies/envoy#envoy-and-consul-dataplane) for details about Consul Dataplane versions and the available packaged Envoy version. +- Kubernetes 1.27.x - 1.30.x +- kubectl 1.27.x - 1.30.x +- Helm 3.11.3+ + +Refer to [Supported Consul and Kubernetes versions](/consul/docs/v1.19.x/k8s/compatibility#supported-consul-and-kubernetes-versions) for more information. + +## Upgrading + +For more detailed information, please refer to the [upgrade details page](/consul/docs/upgrading/upgrade-specific) and the changelogs. + +## Known issues + +The following issues are known to exist in the v1.5.x releases: + +## Changelogs + +The changelogs for this major release version and any maintenance versions are listed below. + + These links take you to the changelogs on the GitHub website. + +- [1.5.0](https://github.com/hashicorp/consul-k8s/releases/tag/v1.5.0) diff --git a/website/content/docs/release-notes/consul-k8s/v1_6_x.mdx b/website/content/docs/release-notes/consul-k8s/v1_6_x.mdx new file mode 100644 index 000000000000..98aab6df59ed --- /dev/null +++ b/website/content/docs/release-notes/consul-k8s/v1_6_x.mdx @@ -0,0 +1,51 @@ +--- +layout: docs +page_title: 1.6.x +description: >- + Consul on Kubernetes release notes for version 1.6.x +--- + +# Consul on Kubernetes 1.6.0 + +We are pleased to announce the following Consul updates. + +## Release highlights + + +- **Consul DNS views for Kubernetes**: Consul on Kubernetes now supports scheduling a dedicated Consul DNS proxy in a Kubernetes Pod instead of using client agents or dataplanes. The proxy is designed for deployment in a Kubernetes cluster with [external servers enabled](/consul/docs/k8s/deployment-configurations/servers-outside-kubernetes) to provide applications in Kubernetes the ability to resolve Consul DNS addresses. You can use the Consul DNS proxy to enable service discovery across admin partitions in Kubernetes deployments. For more information, refer to [Consul DNS views for Kubernetes](/consul/docs/k8s/dns/views). + +- **Catalog sync improvements**: Consul v1.20 includes improved metrics for Consul catalog sync. Consul catalog sync is a feature that automatically registers Kubernetes services with Consul’s catalog. Prior to this enhancement, operators had limited visibility into the status of Kubernetes services being synced to Consul and the performance of the sync catalog process. At scale, it was difficult to discern if the sync process was healthy and progressing normally. Catalog sync enhancements now provide more insights that include status and performance metrics of the sync process. New performance metrics include the rate of registered or deregistered services, the status and health of the sync process, and additional metadata related to registered services. + +- **OpenShift improvements**: Prior to this release, deploying Consul service mesh on Kubernetes required the transparent proxy to have elevated permissions through `anyuid` security context constraint (SCC) privileges. This requirement prevented users from deploying the transparent proxy in OpenShift environments where elevated pod permissions were prohibited. Consul v1.20 no longer requires elevated permissions for the transparent proxy in OpenShift deployments. + +- **Service dashboards for Grafana**: Consul v1.20 includes JSON templates for Grafana dashboards to help you monitor Consul services, service-to-service communication, and Consuld dataplane operations. You can [find these dashboards in the GitHub repo](https://github.com/hashicorp/consul/tree/main/grafana). For more information about configuring Consul to use Grafana, refer to [Configure Metrics for Consul on Kubernetes](/consul/docs/k8s/connect/observability/metrics). + +## Supported software + +This version of Consul on Kubernetes supports the following software versions: + +- Consul v1.20.x +- Consul Dataplane v1.6.x. Refer to [Envoy and Consul Dataplane](/consul/docs/v1.19.x/connect/proxies/envoy#envoy-and-consul-dataplane) for details about Consul Dataplane versions and the available packaged Envoy version. +- Kubernetes 1.28.x - 1.31.x +- kubectl 1.28.x - 1.31.x +- Helm 3.11.3+ + +Refer to [Supported Consul and Kubernetes versions](/consul/docs/v1.19.x/k8s/compatibility#supported-consul-and-kubernetes-versions) for more information. + +## Upgrading + +For more detailed information, please refer to the [upgrade details page](/consul/docs/upgrading/upgrade-specific) and the changelogs. + +## Known issues + +There are no known issues at this time. These release notes are updated as issues are discovered. + +[Report issues on Github](https://github.com/hashicorp/consul-k8s/issues). + +## Changelogs + +The changelogs for this major release version and any maintenance versions are listed below. + + These links take you to the changelogs on the GitHub website. + +- [1.6.0](https://github.com/hashicorp/consul-k8s/releases/tag/v1.6.0) diff --git a/website/content/docs/release-notes/consul-terraform-sync/v0_6_x.mdx b/website/content/docs/release-notes/consul-terraform-sync/v0_6_x.mdx index a4760fa7e402..9f71f17d6701 100644 --- a/website/content/docs/release-notes/consul-terraform-sync/v0_6_x.mdx +++ b/website/content/docs/release-notes/consul-terraform-sync/v0_6_x.mdx @@ -12,13 +12,13 @@ description: >- We have implemented the following features in this release: -### Per-task Execution Mode with Support for Terraform Cloud Agent +### Per-task Execution Mode with Support for HCP Terraform Agent You can now execute Terraform tasks in `remote` or `cloud agent` mode. For more information, refer to the [per-task execution mode documentation](/consul/docs/nia/network-drivers/terraform-cloud#remote-workspaces). -### HCP Consul Support +### HCP Consul Dedicated Support -CTS now supports interoperability with HCP Consul. CTS retrieves licenses from HCP Consul so that users can keep their HCP Consul license or Consul enterprise deployment license in sync. +CTS now supports interoperability with HCP Consul Dedicated. CTS retrieves licenses from HCP Consul Dedicated so that users can keep their HCP Consul Dedicated license or Consul enterprise deployment license in sync. ### Auto Service-registration with Consul and Health API Endpoint @@ -36,9 +36,9 @@ CTS includes a new [API endpoint](/consul/docs/nia/api/health#health) that provi ## Supported Software Versions - Consul: v1.9+ -- HCP Consul: Latest +- HCP Consul Dedicated: Latest - Terraform CLI: v0.13 - v1.1 -- Terraform Cloud: Latest +- HCP Terraform: Latest - Terraform Enterprise: v202010-2 - Latest diff --git a/website/content/docs/release-notes/consul/v1_16_x.mdx b/website/content/docs/release-notes/consul/v1_16_x.mdx index b623ba299c09..4696f7ed0ac6 100644 --- a/website/content/docs/release-notes/consul/v1_16_x.mdx +++ b/website/content/docs/release-notes/consul/v1_16_x.mdx @@ -51,6 +51,10 @@ We are pleased to announce the following Consul updates. Consul's API gateway is the recommended alternative to ingress gateway. For ingress gateway features not currently supported by API gateway, equivalent functionality will be added to API gateway over the next several releases of Consul. +- **Legacy API Gateway:** The Consul API Gateway that was previously packaged as `consul-api-gateway` and released separately from Consul K8s is now deprecated. This is referred to as the "legacy" API Gateway. + + This version of Consul supports v0.5.4 of the legacy API Gateway in order to simplify the process of migrating from legacy to native API gateways. + - **Connect Native Golang SDK:** The Connect Native [Golang SDK](https://github.com/hashicorp/consul/tree/main/connect) is deprecated and will be removed in a future release. No further enhancements or maintenance is expected in the future releases. We will remove the SDK when the long term replacement to native application integration (such as a proxyless gRPC service mesh integration) is delivered. Refer to [GH-10339](https://github.com/hashicorp/consul/issues/10339) for additional information and to track progress toward one potential solution that is tracked as replacement functionality. - **Connect Native APIs:** The following APIs for Connect Native are deprecated: @@ -68,6 +72,11 @@ For more detailed information, please refer to the [upgrade details page](/consu The following issues are known to exist in the v1.16.x releases: +- v1.16.5 - Excessively strict TLS SAN verification is performed by terminating gateways, + which prevents connections outside of the mesh to upstream services. Terminating gateway + users are advised to avoid deploying these Consul versions. A fix will be present in a future + release of Consul 1.16.6 [[GH-20360](https://github.com/hashicorp/consul/issues/20360)]. + - v1.16.0 - v1.16.1 may have issues when a snapshot restore is performed and the servers are hosting xDS streams. When this bug triggers, it will cause Envoy to incorrectly populate upstream endpoints. It is diff --git a/website/content/docs/release-notes/consul/v1_17_x.mdx b/website/content/docs/release-notes/consul/v1_17_x.mdx index ab8fb4a34b6e..378df6721e87 100644 --- a/website/content/docs/release-notes/consul/v1_17_x.mdx +++ b/website/content/docs/release-notes/consul/v1_17_x.mdx @@ -7,7 +7,7 @@ description: >- # Consul 1.17.0 -We are pleased to announce the following Consul updates. +We are pleased to announce the following Consul updates. ## Release highlights @@ -15,13 +15,13 @@ We are pleased to announce the following Consul updates. These APIs are the foundation for future versions of Consul and enable new functionalities, such as multi-port and host-name-based canary routing and routing traffic through headless services in native Kubernetes deployments. - For more information, refer to the [Catalog API v2](/consul/docs/k8s/multiport#catalog-api-v2-beta) section in the documentation. + For more information, refer to the [Catalog API v2](/consul/docs/v1.17.x/k8s/multiport#catalog-api-v2-beta) section in the documentation. These APIs are in beta and under active development, so we do not recommend using them in production. - **Multi-port services in Consul:** You can now register services with multiple ports per service. The v2 catalog API enables a single sidecar proxy to support workloads on different ports. This significantly reduces the operational overhead for managing Consul service mesh. Support for other runtimes outside of Kubernetes is planned for future releases of Consul. - Refer to the [Multi-port services for service mesh](/consul/docs/k8s/multiport#catalog-api-v2-beta) and [Configure multi-port services](/consul/docs/k8s/multiport/configure) for more information. + Refer to the [Multi-port services for service mesh](/consul/docs/v1.17.x/k8s/multiport#catalog-api-v2-beta) and [Configure multi-port services](/consul/docs/k8s/multiport/configure) for more information. Multi-port is currently a beta feature in Consul v1.17. @@ -31,21 +31,21 @@ We are pleased to announce the following Consul updates. Refer to the [locality-aware service mesh routing](/consul/docs/connect/manage-traffic/route-to-local-upstreams) documentation for more information. -- **Sameness groups (Enterprise):** Introduced in 1.16, sameness groups are a user-defined set of partitions that Consul uses to identify services that have the same name but are in different administrative partitions as being the same services. You can use sameness groups to create a blanket failover policy for deployments with cluster peering connections. Sameness group is generally available in Consul 1.17. +- **Sameness groups (Enterprise):** Introduced in 1.16, sameness groups are a user-defined set of partitions that Consul uses to identify services that have the same name but are in different administrative partitions as being the same services. You can use sameness groups to create a blanket failover policy for deployments with cluster peering connections. Sameness group is generally available in Consul 1.17. Enterprises can use sameness groups to simplify operations and increase service availability for multi-cluster or multi-region deployments. Refer to the documentation for [creating sameness groups](/consul/docs/connect/cluster-peering/usage/create-sameness-groups) or [creating sameness groups on Kubernetes](/consul/docs/k8s/connect/cluster-peering/usage/create-sameness-groups) for more information. -- **JWT-based authentication and authorization for API Gateway (Enterprise):** You can configure API gateway to use policies that control access to services based on JSON Web Tokens (JWT) embedded in the network traffic sent by external clients. These policies can control access to services, and even specific URLs, based on the claims contained in JWTs. +- **JWT-based authentication and authorization for API Gateway (Enterprise):** You can configure API gateway to use policies that control access to services based on JSON Web Tokens (JWT) embedded in the network traffic sent by external clients. These policies can control access to services, and even specific URLs, based on the claims contained in JWTs. Administrators can control access to services from outside the service mesh without having to modify services that do not support JWT-based authentication/authorization. Refer to the API gateway JWT documentation for [virtual machines](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-vms) and [Kubernetes-orchestrated](/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-k8s) networks for more information. -- **Traffic rate limiting for services (Enterprise):** You can now configure Consul service mesh to limit the rate of HTTP requests to services. Configure rate limiting per service and apply them per service instance. Operators can set HTTP request rate limits for the service instance or separate rate limits for specific URL paths. The rate limiting configuration includes settings for requests per second (RPS) as well as maximum request burst size. +- **Traffic rate limiting for services (Enterprise):** You can now configure Consul service mesh to limit the rate of HTTP requests to services. Configure rate limiting per service and apply them per service instance. Operators can set HTTP request rate limits for the service instance or separate rate limits for specific URL paths. The rate limiting configuration includes settings for requests per second (RPS) as well as maximum request burst size. - Rate limiting helps operators protect service instances from becoming overloaded with requests. They also enable operators to define criteria for allowing traffic to service instances and ensure service capacity is shared fairly. + Rate limiting helps operators protect service instances from becoming overloaded with requests. They also enable operators to define criteria for allowing traffic to service instances and ensure service capacity is shared fairly. For more information, refer to the [rate limiting](/consul/docs/connect/manage-traffic/limit-request-rates) documentation. @@ -53,13 +53,13 @@ We are pleased to announce the following Consul updates. For more information, refer to the [Consul ECS](/consul/docs/ecs) documentation. -- **ACL templated policies**: You can now configure Consul tokens for common use cases without needing to manually create a policy. Templated policies can be added to tokens and roles. Consul automatically generates a policy and attach it to the token or role. +- **ACL templated policies**: You can now configure Consul tokens for common use cases without needing to manually create a policy. Templated policies can be added to tokens and roles. Consul automatically generates a policy and attach it to the token or role. For more information, refer to the [templated policies](/consul/docs/security/acl#templated-policies) documentation. ## What's deprecated -- **Non DNS-compatible service names:** Starting with this release, non DNS-compatible service names are deprecated. Consul will only accept lowercase alphanumeric characters and `-` , and names that start and end with an alphanumeric character. All other characters will be considered incompatible. An example of what is not considered dns-compatible is listed below: +- **Non DNS-compatible service names:** Starting with this release, non DNS-compatible service names are deprecated. Consul will only accept lowercase alphanumeric characters and `-` , and names that start and end with an alphanumeric character. All other characters will be considered incompatible. An example of what is not considered dns-compatible is listed below: ```bash $ consul services register -name 'foo~bar%' @@ -68,11 +68,25 @@ We are pleased to announce the following Consul updates. consul foo~bar% ``` +- **`-admin-access-log-path` flag for the `consul connect envoy` command:** The `-admin-access-log-path` flag for the `consul connect envoy` command is deprecated and will be removed in a future release. `-admin-access-log-config` can be used to configure Envoy admin access logs. + +## What's removed + +- **Legacy API Gateway support is removed**: The Consul API Gateway that was previously packaged as `consul-api-gateway`, released separately from Consul K8s, and deprecated in Consul v1.16.x is now removed. This gateway is referred to as the _legacy API Gateway_. As of Consul v1.17.0, you must [install](/consul/docs/connect/gateways/api-gateway/install-k8s) the _native API Gateway_ and configure it using the [`connectInject.apiGateway`](/consul/docs/k8s/helm#apigateway) stanza. ## Upgrading For more detailed information, please refer to the [upgrade details page](/consul/docs/upgrading/upgrade-specific) and the changelogs. +## Known Issues + +The following issues are known to exist in the v1.17.x releases: + +- v1.17.2 - Excessively strict TLS SAN verification is performed by terminating gateways, + which prevents connections outside of the mesh to upstream services. Terminating gateway + users are advised to avoid deploying these Consul versions. A fix will be present in a future + release of Consul 1.17.3 [[GH-20360](https://github.com/hashicorp/consul/issues/20360)]. + ## Changelogs The changelogs for this major release version and any maintenance versions are listed below. diff --git a/website/content/docs/release-notes/consul/v1_18_x.mdx b/website/content/docs/release-notes/consul/v1_18_x.mdx new file mode 100644 index 000000000000..24c23d060860 --- /dev/null +++ b/website/content/docs/release-notes/consul/v1_18_x.mdx @@ -0,0 +1,58 @@ +--- +layout: docs +page_title: 1.18.x +description: >- + Consul release notes for version 1.18.x +--- + +# Consul 1.18.0 + +We are pleased to announce the following Consul updates. + +## Release highlights + +- **Consul v2 Catalog API and Traffic Permission API updates:** Additional improvements were made to the v2 catalog API, which enables support for [multi-port services on Kubernetes](/consul/docs/k8s/multiport). End user facing changes include the ability to use a service's ports in xRoute configurations as opposed to the workload port for reference in the parentRef stanza of the xRoute configuration. In addition, the Traffic Permissions API was changed to only allow `ACTION_DENY` for Consul Enterprise as it will enable future governance related workflows. + + The v2 Catalog API is currently available for Consul on Kubernetes deployments only. Refer to [Consul v2 architecture](/consul/docs/architecture/v2) for more information. + + The v2 Catalog API and the Traffic Permissions API are in beta and under active development, so we do not recommend using them in production. + +- **Consul Long Term Support (LTS) (Enterprise):** Consul Enterprise users can now receive Long Term Support for approximately 2 years on some Consul releases, starting with Consul Enterprise v1.15. During the LTS window, eligible fixes are provided through a new minor release on the affected LTS release branch. + + An LTS release is planned for every 3 releases, and it is maintained until it is 6 releases from the latest major release. For example, Consul Enterprise v1.15.x, v1.18x, and v1.21.x are the next three planned releases. The LTS period for Consul Enterprise v1.15.x ends when Consul Enterprise v1.21.0 releases. + + For more information, refer to [Consul Enterprise Long Term Support](/consul/docs/enterprise/long-term-support). + +- **Fault injection (Enterprise):** For Enterprise users, Consul’s service mesh now supports managing traffic with fault injection behavior that is defined in an upstream service’s service defaults configuration entry or CRD. Supported fault injection behavior includes delaying, aborting, and rate limiting traffic between services. You can use fault injection to test your network’s resilience under different conditions. + + For more information, refer to [fault injection](/consul/docs/connect/manage-traffic/fault-injection). + +- **Consul admin partition support for Nomad:** Nomad now supports configurations for a Consul datacenter’s admin partition when scheduling applications. Admin partitions are a Consul Enterprise feature that enable multi-tenancy for Consul servers so that several teams in your organization can use a single secure Consul datacenter. Admin partitions also enable cluster peering as a strategy for extending your service mesh east-west across regions in a single cloud provider or across multiple cloud providers. + + Refer to [admin partitions](/consul/docs/enterprise/admin-partitions) for more information. + +- **Transparent proxy for EC2 on ECS:** Consul now supports transparent proxy mode for deployments running on EC2 instances in AWS Elastic Container Service (ECS). When service mesh proxies are in transparent proxy mode, Consul service mesh uses IPtables to direct all inbound and outbound traffic to the sidecar. Consul also uses information configured in service intentions to infer routes, which eliminates the need to explicitly configure upstreams. + + Consul’s transparent proxy allows applications to communicate through Consul’s service mesh without modifying their underlying configurations to use Consul DNS. The transparent proxy also hardens application security by preventing direct inbound connections that bypass the mesh. + + Refer to [transparent proxy overview](/consul/docs/k8s/connect/transparent-proxy) and [Consul on ECS overview](/consul/docs/ecs) for more information. + +- **Downgrade from Consul Enterprise to Consul Community Edition**: Consul now provides the ability for enterprise users to migrate their deployments to Community edition and disable enterprise features for business continuity. Refer to [Downgrade from Consul Enterprise to the community edition](/consul/docs/enterprise/ent-to-ce-downgrades) for more information. + +- **Consul Snapshot Agent support for multiple destinations (Enterprise):** Consul Enterprise users can now specify [multiple local and remote destinations](/consul/commands/snapshot/agent) for Consul snapshot backups. + +## Upgrading + +For more detailed information, please refer to the [upgrade details page](/consul/docs/upgrading/upgrade-specific) and the changelogs. + +## Known issues + +The following issues are known to exist in the v1.18.x releases: + +## Changelogs + +The changelogs for this major release version and any maintenance versions are listed below. + + These links take you to the changelogs on the GitHub website. + +- [1.18.0](https://github.com/hashicorp/consul/releases/tag/v1.18.0) diff --git a/website/content/docs/release-notes/consul/v1_19_x.mdx b/website/content/docs/release-notes/consul/v1_19_x.mdx new file mode 100644 index 000000000000..f13ce1ca842e --- /dev/null +++ b/website/content/docs/release-notes/consul/v1_19_x.mdx @@ -0,0 +1,56 @@ +--- +layout: docs +page_title: 1.19.x +description: >- + Consul release notes for version 1.19.x +--- + +# Consul 1.19.0 + +We are pleased to announce the following Consul updates. + +## Release highlights + +- **External Services CRD**: You can now configure and register external services, including their health checks, alongside existing Kubernetes application manifests with the new [`Registration` Custom Resource Definition (CRD)](/consul/docs/connect/config-entries/registration). This CRD changes the workflow to register a service running on an external node with the Consul catalog. A terminating gateway is still required to enable downstream services in the service mesh to communicate with external services. Refer to [Register external services on Kubernetes overview](/consul/docs/k8s/deployment-configurations/external-service) for more information. + +- **Transparent Proxy on Nomad**: Consul’s CNI plugin enables the use of transparent proxy for seamlessly redirecting traffic through the Envoy proxy without requiring application changes, or elevated network privileges for the workload. As a result, you can onboard applications without additional configuration between a service and its upstreams. + +- **API Gateway metrics**: The Consul API Gateway now provides a Prometheus metrics endpoint you can use to gather information about the health of the gateway, as well as traffic for proxied connections or requests. + +- **File system certificate configuration entry**: A new [`file-system-certificate` configuration entry](/consul/docs/connect/config-entries/file-system-certificate) supports specifying a filepath to the certificate and private key for Consul API Gateway on VMs on the local system. Previously, the certificate and private key were specified directly in the `inline-certificate` configuration entry. When using the file system certificates, the Consul server never sees the contents of these files. + + File system certificates also include a file system watch that allows for changing the certificate and key without restarting the gateway. This feature requires that you have access to the gateway’s file system in order to place the certificate or update it. + + Consul on Kubernetes deployments that use `consul-k8s` Helm chart v1.5.0 or later use file system certificates without additional configuration. For more information, refer to [File system certificate configuration reference](/consul/docs/connect/config-entries/file-system-certificate). + +- **Argo Rollouts Plugin**: A new Argo Rollouts plugin for progressive delivery is now available for `consul-k8s`. This plugin supports canary deployments by allowing you to incrementally release and test new versions of applications and roll back to previous versions by splitting traffic between subsets of services. Refer to [Argo Rollouts Progressive Delivery with Consul on Kubernetes](/consul/docs/k8s/deployment-configurations/argo-rollouts-configuration) for more information. + +## What's deprecated + +- **Snapshot Agent (Enterprise):** Starting with this release, top level single snapshot destinations `local_storage`, `aws_storage`, `azure_blob_storage`, and `google_storage` in snapshot agent configuration files are deprecated. Use the [`backup_destinations`](/consul/commands/snapshot/agent#config-file) config object instead. + +## Upgrading + +For more detailed information, please refer to the [upgrade details page](/consul/docs/upgrading/upgrade-specific) and the changelogs. + +## Known issues + +The following issues are known to exist in the v1.19.x releases: + +- v1.19.0 & v1.19.1 - There are known issues with the DNS server implementation. +To revert to the old DNS behavior on 1.19.0 and 1.19.1, set `experiments: [ "v1dns" ]` in the agent configuration. +In v1.19.2, the modified DNS subsystem will be reverted and the old DNS behavior will be restored resolving these issues. + - DNS SRV records for registrations that specify a service address instead of a node address return identical `.service` hostnames instead of unique `.addr` addresses. + As a result, it is impossible to resolve the individual service addresses. + This bug can affect Nomad installations using Consul for service discovery because the service address field is always specified to Consul. + [[GH-21325](https://github.com/hashicorp/consul/issues/21325)]. + - DNS Tags are not resolved when using the Standard query format, `tag.name.service.consul`. + [[GH-21326](https://github.com/hashicorp/consul/issues/21336)]. + +## Changelogs + +The changelogs for this major release version and any maintenance versions are listed below. + + These links take you to the changelogs on the GitHub website. + +- [1.19.0](https://github.com/hashicorp/consul/releases/tag/v1.19.0) diff --git a/website/content/docs/release-notes/consul/v1_20_x.mdx b/website/content/docs/release-notes/consul/v1_20_x.mdx new file mode 100644 index 000000000000..17e19a3de573 --- /dev/null +++ b/website/content/docs/release-notes/consul/v1_20_x.mdx @@ -0,0 +1,38 @@ +--- +layout: docs +page_title: 1.20.x +description: >- + Consul release notes for version 1.20.x +--- + +# Consul 1.20.0 + +We are pleased to announce the following Consul updates. + +## Release highlights + +- **Consul DNS views for Kubernetes**: Consul on Kubernetes now supports scheduling a dedicated Consul DNS proxy in a Kubernetes Pod instead of using client agents or dataplanes. The proxy is designed for deployment in a Kubernetes cluster with [external servers enabled](/consul/docs/k8s/deployment-configurations/servers-outside-kubernetes) to provide applications in Kubernetes the ability to resolve Consul DNS addresses. You can use the Consul DNS proxy to enable service discovery across admin partitions in Kubernetes deployments. For more information, refer to [Consul DNS views for Kubernetes](/consul/docs/k8s/dns/views). + +- **Catalog sync improvements**: Consul v1.20 includes improved metrics for Consul catalog sync. Consul catalog sync is a feature that automatically registers Kubernetes services with Consul’s catalog. Prior to this enhancement, operators had limited visibility into the status of Kubernetes services being synced to Consul and the performance of the sync catalog process. At scale, it was difficult to discern if the sync process was healthy and progressing normally. Catalog sync enhancements now provide more insights that include status and performance metrics of the sync process. New performance metrics include the rate of registered or deregistered services, the status and health of the sync process, and additional metadata related to registered services. + +- **OpenShift improvements**: Prior to this release, deploying Consul service mesh on Kubernetes required the transparent proxy to have elevated permissions through `anyuid` security context constraint (SCC) privileges. This requirement prevented users from deploying the transparent proxy in OpenShift environments where elevated pod permissions were prohibited. Consul v1.20 no longer requires elevated permissions for the transparent proxy in OpenShift deployments. + +- **Service dashboards for Grafana**: Consul v1.20 includes JSON templates for Grafana dashboards to help you monitor Consul services, service-to-service communication, and Consuld dataplane operations. You can [find these dashboards in the GitHub repo](https://github.com/hashicorp/consul/tree/main/grafana). For more information about configuring Consul to use Grafana, refer to [Configure Metrics for Consul on Kubernetes](/consul/docs/k8s/connect/observability/metrics). + +## Upgrading + +For more detailed information, please refer to the [upgrade details page](/consul/docs/upgrading/upgrade-specific) and the changelogs. + +## Known issues + +There are no known issues at this time. These release notes are updated as issues are discovered. + +[Report issues on Github](https://github.com/hashicorp/consul/issues). + +## Changelogs + +The changelogs for this major release version and any maintenance versions are listed below. + + These links take you to the changelogs on the GitHub website. + +- [1.20.0](https://github.com/hashicorp/consul/releases/tag/v1.20.0) diff --git a/website/content/docs/security/acl/acl-roles.mdx b/website/content/docs/security/acl/acl-roles.mdx index 5812703831de..834e433349b6 100644 --- a/website/content/docs/security/acl/acl-roles.mdx +++ b/website/content/docs/security/acl/acl-roles.mdx @@ -62,7 +62,7 @@ Roles may contain the following attributes: - `Name`: A unique meaningful name for the role. You can specify the role `Name` when linking it to tokens. - `Description`: (Optional) A human-readable description of the role. - `Policies`: Specifies a the list of policies that are applicable for the role. The object can reference the policy `ID` or `Name` attribute. -- `TemplatedPolicies`: Specifies a list of templated polcicies that are applicable for the role. See [Templated Policies](#templated-policies) for details. +- `TemplatedPolicies`: Specifies a list of templated policies that are applicable for the role. See [Templated Policies](#templated-policies) for details. - `ServiceIdentities`: Specifies a list of services that are applicable for the role. See [Service Identities](#service-identities) for details. - `NodeIdentities`: Specifies a list of nodes that are applicable for the role. See [Node Identities](#node-identities) for details. - `Namespace`: The namespace that the policy resides in. Roles can only be linked to policies that are defined in the same namespace. See [Namespaces](/consul/docs/enterprise/namespaces) for additional information. Requires Consul Enterprise 1.7.0+ @@ -72,7 +72,7 @@ Roles may contain the following attributes: You can specify a templated policy when configuring roles or linking tokens to policies. Templated policies enable you to quickly construct policies for common Consul use cases, rather than creating identical policies for each use cases. -Consul uses templated policies during the authorization process to automatically generate a policy for the use case specified. Consul links the generated policy to the role or token so that it will have permission for the specific use case. +Consul uses templated policies during the authorization process to automatically generate a policy for the use case specified. Consul links the generated policy to the role or token so that it will have permission for the specific use case. ### Templated policy specification @@ -398,4 +398,4 @@ service_prefix "" { } ``` - \ No newline at end of file + diff --git a/website/content/docs/security/acl/acl-rules.mdx b/website/content/docs/security/acl/acl-rules.mdx index 6139ddeabbb9..a89985d528e6 100644 --- a/website/content/docs/security/acl/acl-rules.mdx +++ b/website/content/docs/security/acl/acl-rules.mdx @@ -592,13 +592,13 @@ These actions may required an ACL token to complete. Use the following methods t Nodes rules affect read access to nodes with services exported by [`exported-services` configuration entries](/consul/docs/connect/config-entries/exported-services#reading-services), including nodes imported from [cluster peerings](/consul/docs/connect/cluster-peering) or [admin partitions](/consul/docs/enterprise/admin-partitions) (Enterprise-only). Read access to all imported nodes is granted when either of the following rule sets are attached to a token: -- `service:write` is granted to any service. +- `service:write` is granted to any service. - `node:read` is granted to all nodes. -For Consul Enterprise, either set of rules must be scoped to the requesting services's partition and at least one namespace. +For Consul Enterprise, either set of rules must be scoped to the requesting service's partition and at least one namespace. You may need similarly scoped [Service Rules](#reading-imported-services) to read Consul data, depending on the endpoint (e.g. `/v1/health/service/:name`). -These permissions are satisfied when using a [service identity](/consul/docs/security/acl/acl-roles#service-identities). +These permissions are satisfied when using a [service identity](/consul/docs/security/acl/acl-roles#service-identities). Refer to [Reading Services](/consul/docs/connect/config-entries/exported-services#reading-services) for example ACL policies used to read imported services using the health endpoint. @@ -831,13 +831,13 @@ set to `true` in order to enable script checks. Service rules affect read access to services exported by [`exported-services` configuration entries](/consul/docs/connect/config-entries/exported-services#reading-services), including services exported between [cluster peerings](/consul/docs/connect/cluster-peering) or [admin partitions](/consul/docs/enterprise/admin-partitions) (Enterprise-only). Read access to all imported services is granted when either of the following rule sets are attached to a token: -- `service:write` is granted to any service. +- `service:write` is granted to any service. - `service:read` is granted to all services. -For Consul Enterprise, either set of rules must be scoped to the requesting services's partition and at least one namespace. +For Consul Enterprise, either set of rules must be scoped to the requesting service's partition and at least one namespace. You may need similarly scoped [Node Rules](#reading-imported-nodes) to read Consul data, depending on the endpoint (e.g. `/v1/health/service/:name`). -These permissions are satisfied when using a [service identity](/consul/docs/security/acl/acl-roles#service-identities). +These permissions are satisfied when using a [service identity](/consul/docs/security/acl/acl-roles#service-identities). Refer to [Reading Services](/consul/docs/connect/config-entries/exported-services#reading-services) for example ACL policies used to read imported services using the health endpoint. diff --git a/website/content/docs/security/acl/index.mdx b/website/content/docs/security/acl/index.mdx index b4f589447ed7..f8b8b97ec85c 100644 --- a/website/content/docs/security/acl/index.mdx +++ b/website/content/docs/security/acl/index.mdx @@ -9,20 +9,11 @@ description: >- This topic describes core concepts associated with the optional access control list (ACL) system shipped with Consul. ACLs authenticate requests and authorize access to resources. They also control access to the Consul UI, API, and CLI, as well as secure service-to-service and agent-to-agent communication. -Refer to the following tutorials for step-by-step instructions on how to get started using ACLs: - -- [Bootstrap and Explore ACLs] -- [Secure Consul with ACLs] -- [Troubleshoot the ACL System](/consul/tutorials/security/access-control-troubleshoot) - -[bootstrap and explore acls]: /consul/tutorials/security/access-control-setup-production?utm_source=docs -[secure consul with acls]: /consul/tutorials/security/access-control-setup-production - Refer to the [ACL API reference](/consul/api-docs/acl) and [ACL CLI reference](/consul/commands/acl) for additional usage information. ## Workflow overview -Implementations may vary depending on the needs of the organization, but the following procedure describes the basic workflow for for creating and implementing ACLs: +Implementations may vary depending on the needs of the organization, but the following procedure describes the basic workflow for creating and implementing ACLs: 1. The person responsible for administrating ACLs in your organization specifies one or more authentication rules to define a [policy](#policies). 1. The ACL administrator uses the Consul API to generate and link a [token](#tokens) to one or more policies. The following diagram illustrates the relationship between rules, policies, and tokens: diff --git a/website/content/docs/security/acl/tokens/create/create-a-dns-token.mdx b/website/content/docs/security/acl/tokens/create/create-a-dns-token.mdx index 4fde8bcf9e6f..3a59de03261d 100644 --- a/website/content/docs/security/acl/tokens/create/create-a-dns-token.mdx +++ b/website/content/docs/security/acl/tokens/create/create-a-dns-token.mdx @@ -29,304 +29,27 @@ The DNS token must be linked to policies that grant the following permissions: @include 'create-token-requirements.mdx' -## DNS token in Consul CE +## Create a DNS token -To create a token for DNS, you must define a policy, register the policy with Consul, and link the policy to a token. - -### Define a policy - -You can send policy definitions as command line or API arguments or define them in an external HCL or JSON file. Refer to [ACL Rules](/consul/docs/security/acl/acl-rules) for details about all of the rules you can use in your policies. - -The following example policy is defined in a file. The policy grants the appropriate permissions to enable a Consul agent to respond to DNS queries. - - - -```hcl -node_prefix "" { - policy = "read" -} -service_prefix "" { - policy = "read" -} -query_prefix "" { - policy = "read" -} -``` - -```json -{ - "node_prefix": { - "": [{ - "policy": "read" - }] - }, - "query_prefix": { - "": [{ - "policy": "read" - }] - }, - "service_prefix": { - "": [{ - "policy": "read" - }] - } -} -``` - - - -### Register the policy with Consul - -After defining the policy, you can register the policy with Consul using the command line or API endpoint. - - - - - -Run the `consul acl policy create` command and specify the policy rules to create a policy. Refer to [Consul ACL Policy Create](/consul/commands/acl/policy/create) for details about the `consul acl policy create` command. - -The following example registers a policy defined in `dns-access.hcl`. - -```shell-session -$ consul acl policy create \ - -name "dns-access" -rules @dns-access.hcl \ - -description "DNS Policy" -``` - - - - - -Send a PUT request to the `/acl/policy` endpoint and specify the policy rules in the request body to create a policy. Refer to [ACL Policy HTTP API](/consul/api-docs/acl/policies) for additional information about using the API endpoint. - -The following example registers the policy defined in `dns-access.hcl`. You must embed policy rules in the `Rules` field of the request body. - -```shell-session -$ curl --request PUT http://127.0.0.1:8500/v1/acl/policy \ - --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ - --data '{ - "Name": "dns-access", - "Description": "DNS Policy", - "Rules": "node_prefix \"\" {\n policy = \"read\"\n}\nservice_prefix \"\" {\n policy = \"read\"\n}\nquery_prefix \"\" {\n policy = \"read\"\n}\n" -}' -``` - - - - - -### Link the policy to a token - -After registering the policy into Consul, you can create and link tokens using the Consul command line or API endpoint. You can also enable Consul to dynamically create tokens from trusted external systems using an [auth method](/consul/docs/security/acl/auth-methods). - - - - - -Run the `consul acl token create` command and specify the policy name or ID to create a token linked to the policy. Refer to [Consul ACL Token Create](/consul/commands/acl/token/create) for details about the `consul acl token create` command. - -The following command creates the ACL token linked to the policy `dns-access`. +Run the `consul acl token create` CLI command and specify the `builtin/dns` templated policy to create a DNS token. ```shell-session -$ consul acl token create \ - -description "DNS token" \ - -policy-name "dns-access" +$ consul acl token create -name "dns-token" -templated-policy "builtin/dns" ``` - - - - -Send a PUT request to the `/acl/token` endpoint and specify the policy name or ID in the request to create an ACL token linked to the policy. Refer to [ACL Token HTTP API](/consul/api-docs/acl/tokens) for additional information about using the API endpoint. - -The following example creates the ACL token linked to the policy `dns-access`. - -```shell-session -$ curl --request PUT http://127.0.0.1:8500/v1/acl/token \ - --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ - --data '{ - "Policies": [ - { - "Name": "dns-access" - } - ] -}' -``` - - - - - -## DNS token in Consul Enterprise - -To create a token for DNS, you must define a policy, register the policy with Consul, and link the policy to a token. - -### Define a policy - -You can send policy definitions as command line or API arguments or define them in an external HCL or JSON file. Refer to [ACL Rules](/consul/docs/security/acl/acl-rules) for details about all of the rules you can use in your policies. - -The following example policy is defined in a file. The policy grants the appropriate permissions to enable a Consul agent to respond to DNS queries for resources in any namespace in any partition. - - - -```hcl -partition "default" { - namespace "default" { - query_prefix "" { - policy = "read" - } - } -} -partition_prefix "" { - namespace_prefix "" { - node_prefix "" { - policy = "read" - } - service_prefix "" { - policy = "read" - } - } -} -``` - -```json -{ - "partition": { - "default": [{ - "namespace": { - "default": [{ - "query_prefix": { - "": [{ - "policy": "read" - }] - } - }] - } - }] - }, - "partition_prefix": { - "": [{ - "namespace_prefix": { - "": [{ - "node_prefix": { - "": [{ - "policy": "read" - }] - }, - "service_prefix": { - "": [{ - "policy": "read" - }] - } - }] - } - }] - } -} -``` - - - -### Register the policy with Consul - -After defining the policy, you can register the policy with Consul using the command line or API endpoint. - -You can specify an admin partition when creating policies in Consul Enterprise. The policy is only valid in the specified admin partition. The example policy contains permissions for multiple namespaces in multiple partitions. You must create ACL policies that grant permissions for multiple namespaces in multiple partitions in the `default` namespace and the `default` partition. - - - - - - -Run the `consul acl policy create` command and specify the policy rules to create a policy. Refer to [Consul ACL Policy Create](/consul/commands/acl/policy/create) for details about the `consul acl policy create` command. - -```shell-session -consul acl policy create -partition "default" -namespace "default" \ - -name dns-access -rules @dns-access.hcl \ - -description "DNS Policy" -``` - - - - - -Send a PUT request to the `/acl/policy` endpoint and specify the policy rules in the request body to create a policy. Refer to [ACL Policy HTTP API](/consul/api-docs/acl/policies) for additional information about using the API endpoint. - -The following example registers the policy defined in `dns-access.hcl`. You must embed policy rules in the `Rules` field of the request body. - -```shell-session -$ curl --request PUT http://127.0.0.1:8500/v1/acl/policy \ - --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ - --data '{ - "Name": "dns-access", - "Description": "DNS Policy", - "Partition": "default", - "Namespace": "default", - "Rules": "partition_prefix \"\" {\n namespace_prefix \"\" {\n node_prefix \"\" {\n policy = \"read\"\n }\n service_prefix \"\" {\n policy = \"read\"\n }\n query_prefix \"\" {\n policy = \"read\"\n }\n }\n}\n" -}' -``` - - - - - -### Link the policy to a token - -After registering the policy into Consul, you can create and link tokens using the Consul command line or API endpoint. You can also enable Consul to dynamically create tokens from trusted external systems using an [auth method](/consul/docs/security/acl/auth-methods). - - - - - -Run the `consul acl token create` command and specify the policy name or ID to create a token linked to the policy. Refer to [Consul ACL Token Create](/consul/commands/acl/token/create) for details about the `consul acl token create` command. - -The following command creates the ACL token linked to the policy `dns-access`. - -```shell-session -$ consul acl token create -partition "default" -namespace "default" \ - -description "DNS token" \ - -policy-name "dns-access" -``` - - - - - -Send a PUT request to the `/acl/token` endpoint and specify the policy name or ID in the request to create an ACL token linked to the policy. Refer to [ACL Token HTTP API](/consul/api-docs/acl/tokens) for additional information about using the API endpoint. - -The following example creates the ACL token linked to the policy `dns-access`. - -```shell-session -$ curl --request PUT http://127.0.0.1:8500/v1/acl/token \ - --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" \ - --data '{ - "Policies": [ - { - "Name": "dns-access" - } - ], - "Partition": "default", - "Namespace": "default" -}' -``` - - - - - ## Apply the token Configure the Consul agent with the token by either specifying the token in the agent configuration file or by using the `consul set-agent-token` command. ### Apply the token in a file -Specify the token in the [`default`](/consul/docs/agent/config/config-files#acl_tokens_default) field of the agent configuration file so that the agent can present it and register into the catalog on startup. +Specify the token in the [`dns`](/consul/docs/agent/config/config-files#acl_tokens_dns) field of the agent configuration file so that the agent can present it and register into the catalog on startup. ```hcl acl = { enabled = true tokens = { - default = "" + dns = "" ... } ... @@ -335,9 +58,8 @@ acl = { ### Apply the token with a command -Set the `default` token using the [`acl.token.default`](/consul/docs/agent/config/config-files#acl_tokens_default) command. The following command configures a running Consul agent token with the specified token. +Set the `dns` token using the [`set-agent-token`](/consul/commands/acl/set-agent-token) command. The following command configures a running Consul agent token with the specified token. ```shell-session -$ consul set-agent-token default +$ consul set-agent-token dns ``` - diff --git a/website/content/docs/security/acl/tokens/index.mdx b/website/content/docs/security/acl/tokens/index.mdx index 0c57cbbe38f7..45df06d3900d 100644 --- a/website/content/docs/security/acl/tokens/index.mdx +++ b/website/content/docs/security/acl/tokens/index.mdx @@ -156,6 +156,9 @@ system or accessing Consul under specific conditions. The following table descri | [`acl.tokens.agent`](/consul/docs/agent/config/config-files#acl_tokens_agent) | `OPTIONAL` | `OPTIONAL` | Used for internal agent operations. See [ACL Agent Token](#acl-agent-token) for details. | | [`acl.tokens.initial_management`](/consul/docs/agent/config/config-files#acl_tokens_initial_management) | `OPTIONAL` | `N/A` | Used to bootstrap the ACL system. See [Initial Management Token](#initial-management-token). | | [`acl.tokens.default`](/consul/docs/agent/config/config-files#acl_tokens_default) | `OPTIONAL` | `OPTIONAL` | Specifies a default token to use for client requests if no token is supplied. This is commonly configured with read-only access to services to enable DNS service discovery on agents. | +| [`acl.tokens.replication`](/consul/docs/agent/config/config-files#acl_tokens_replication) | `OPTIONAL` | `N/A` | Authorizes secondary datacenters to replicate data from the primary datacenter. | +| [`acl.tokens.config_file_service_registration`](/consul/docs/agent/config/config-files#acl_tokens_config_file_service_registration) | `OPTIONAL` | `OPTIONAL` | Registers services and checks from service and check definitions specified in configuration files or fragments passed to the agent using the `-hcl` flag. | +| [`acl.tokens.dns`](/consul/docs/agent/config/config-files#acl_tokens_dns) | `OPTIONAL` | `OPTIONAL` | Enables the agent to answer DNS queries about services and nodes. | All reserved tokens except the `initial_management` token can be created or updated using the [/v1/agent/token API](/consul/api-docs/agent#update-acl-tokens). diff --git a/website/content/docs/security/encryption.mdx b/website/content/docs/security/encryption.mdx deleted file mode 100644 index 6cbbf6b3219c..000000000000 --- a/website/content/docs/security/encryption.mdx +++ /dev/null @@ -1,111 +0,0 @@ ---- -layout: docs -page_title: Encryption Systems -description: >- - Consul supports encrypting all of its network traffic. Remote Process Calls (RPCs) between client and server agents can be encrypted with TLS and authenticated with certificates. Gossip communication between all agents can also be encrypted. ---- - -# Encryption - -The Consul agent supports encrypting all of its network traffic. The exact -method of encryption is described on the [encryption internals page](/consul/docs/security). -There are two separate encryption systems, one for gossip traffic and one for RPC. - -To configure the encryption systems on a new cluster, review this following tutorials to -[enable gossip encryption](/consul/tutorials/security/gossip-encryption-secure?utm_source=consul.io&utm_medium=docs) and -[TLS encryption for agent communication](/consul/tutorials/security/tls-encryption-secure?utm_source=docs). - -## Gossip Encryption - -Enabling gossip encryption only requires that you set an encryption key when -starting the Consul agent. The key can be set via the `encrypt` parameter. - -~> **WAN Joined Datacenters Note:** If using multiple WAN joined datacenters, be sure to use _the same encryption key_ in all datacenters. - -The key must be 32-bytes, Base64 encoded. As a convenience, Consul provides the -[`consul keygen`](/consul/commands/keygen) command to generate a -cryptographically suitable key: - -```shell-session -$ consul keygen -pUqJrVyVRj5jsiYEkM/tFQYfWyJIv4s3XkvDwy7Cu5s= -``` - -With that key, you can enable encryption on the agent. If encryption is enabled, -the output of [`consul agent`](/consul/commands/agent) will include "Encrypt: true": - -```shell-session -$ cat encrypt.json -{"encrypt": "pUqJrVyVRj5jsiYEkM/tFQYfWyJIv4s3XkvDwy7Cu5s="} - -$ consul agent -data-dir=/tmp/consul -config-file=encrypt.json -==> WARNING: LAN keyring exists but -encrypt given, using keyring -==> WARNING: WAN keyring exists but -encrypt given, using keyring -==> Starting Consul agent... -==> Starting Consul agent RPC... -==> Consul agent running! - Node name: 'Armons-MacBook-Air.local' - Datacenter: 'dc1' - Server: false (bootstrap: false) - Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400) - Cluster Addr: 10.1.10.12 (LAN: 8301, WAN: 8302) - Gossip encrypt: true, RPC-TLS: false, TLS-Incoming: false -... -``` - -All nodes within a Consul cluster must share the same encryption key in -order to send and receive cluster information. - -## Configuring Gossip Encryption on an existing cluster - -As of version 0.8.4, Consul supports upshifting to encrypted gossip on a running cluster -through the following process. Review this [step-by-step tutorial](/consul/tutorials/security/gossip-encryption-secure?utm_source=consul.io&utm_medium=docs#enable-gossip-encryption-existing-cluster) -to encrypt gossip on an existing cluster. - -## RPC Encryption with TLS - -Consul supports using TLS to verify the authenticity of servers and clients. To enable this, -Consul requires that all clients and servers have key pairs that are generated by a single -Certificate Authority. This can be a private CA, used only internally. The -CA then signs keys for each of the agents, as in -[this tutorial on generating both a CA and signing keys](/consul/tutorials/security/tls-encryption-secure?utm_source=docs). - -~> Certificates need to be created with x509v3 extendedKeyUsage attributes for both clientAuth and serverAuth since Consul uses a single cert/key pair for both server and client communications. - -TLS can be used to verify the authenticity of the servers or verify the authenticity of clients. -These modes are controlled by the [`verify_outgoing`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_outgoing), -[`verify_server_hostname`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_server_hostname), -and [`verify_incoming`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_incoming) options, respectively. - -If [`verify_outgoing`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_outgoing) is set, agents verify the -authenticity of Consul for outgoing connections. Server nodes must present a certificate signed -by a common certificate authority present on all agents, set via the agent's -[`ca_file`](/consul/docs/agent/config/config-files#tls_internal_rpc_ca_file) and [`ca_path`](/consul/docs/agent/config/config-files#tls_internal_rpc_ca_path) -options. All server nodes must have an appropriate key pair set using [`cert_file`](/consul/docs/agent/config/config-files#tls_internal_rpc_cert_file) and [`key_file`](/consul/docs/agent/config/config-files#tls_internal_rpc_key_file). - -If [`verify_server_hostname`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_server_hostname) is set, then -outgoing connections perform hostname verification. All servers must have a certificate -valid for `server..` or the client will reject the handshake. This is -a new configuration as of 0.5.1, and it is used to prevent a compromised client from being -able to restart in server mode and perform a MITM (Man-In-The-Middle) attack. New deployments should set this -to true, and generate the proper certificates, but this is defaulted to false to avoid breaking -existing deployments. - -If [`verify_incoming`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_incoming) is set, the servers verify the -authenticity of all incoming connections. All clients must have a valid key pair set using -[`cert_file`](/consul/docs/agent/config/config-files#tls_internal_rpc_cert_file) and -[`key_file`](/consul/docs/agent/config/config-files#tls_internal_rpc_key_file). Servers will -also disallow any non-TLS connections. To force clients to use TLS, -[`verify_outgoing`](/consul/docs/agent/config/config-files#tls_internal_rpc_verify_outgoing) must also be set. - -TLS is used to secure the RPC calls between agents, but gossip between nodes is done over UDP -and is secured using a symmetric key. See above for enabling gossip encryption. - -## Configuring TLS on an existing cluster - -As of version 0.8.4, Consul supports migrating to TLS-encrypted traffic on a running cluster -without downtime. This process assumes a starting point with no TLS settings configured and involves -an intermediate step in order to get to full TLS encryption. Review the -[Securing RPC Communication with TLS Encryption tutorial](/consul/tutorials/security/tls-encryption-secure?utm_source=docs) -for the step-by-step process to configure TLS on a new or existing cluster. Note the call outs there -for existing cluster configuration. diff --git a/website/content/docs/security/encryption/gossip.mdx b/website/content/docs/security/encryption/gossip.mdx new file mode 100644 index 000000000000..4a04e16bd7c9 --- /dev/null +++ b/website/content/docs/security/encryption/gossip.mdx @@ -0,0 +1,302 @@ +--- +layout: docs +page_title: Manage gossip encryption +description: >- + Consul supports encrypting all of its network traffic. Learn how to secure gossip communication between all agents by creating and rotating a symmetric key. +--- + +# Manage gossip encryption + +This topic describes the steps to enable gossip encryption on a Consul datacenter and rotate the gossip encryption key to maintain secure communication between agents. + +## Workflows + +We recommend enabling gossip encryption to all new deployed Consul datacenters. You can also update the agents in an existing datacenter to use gossip encryption. + +The workflow to enable gossip encryption changes depending on whether your datacenter has client agents running. + +To [enable gossip encryption on a new datacenter](#enable-gossip-encryption-on-a-new-datacenter): + +1. Use `consul keygen` to generate a new gossip encryption key. +1. Create a configuration file that sets the `encrypt` parameter to the newly generated key. +1. Distribute the configuration file to all agent nodes that are part of the datacenter. Then start the Consul agent on all the nodes. + +To [enable gossip encryption on an existing datacenter](#enable-gossip-encryption-on-an-existing-datacenter): + +1. Use `consul keygen` to generate a new gossip encryption key. +1. Create a configuration file that sets the `encrypt` parameter to the newly generated key and sets `encrypt_verify_incoming` and `encrypt_verify_outgoing` to `false`. +1. Distribute the configuration file to all agent nodes that are part of the datacenter. Then perform a rolling restart of all Consul agents. +1. Update the `encrypt_verify_outgoing` setting to `true` and perform a rolling restart of all Consul agents. +1. Update the `encrypt_verify_incoming` setting to `true` and perform a rolling restart of all Consul agents. + +If you have multiple datacenters joined in WAN federation, be sure to use _the same encryption key_ in all datacenters. + +## Enable gossip encryption on a new datacenter + +We recommend enabling gossip encryption on all new Consul datacenters. + +### Generate a gossip encryption key + +First, generate an encryption key on a Consul server. The Consul CLI includes a `consul keygen` command to generate a key. + +```shell-session +$ consul keygen +YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA= +``` + +You can generate a new gossip key using any method that can create 32 random bytes encoded in base64. For example, you can use `openssl` or `dd` to create a key on Linux with one of the following commands: + +- `openssl rand -base64 32` +- `dd if=/dev/urandom bs=32 count=1 status=none | base64` + +### Add the key to the agent configuration + +Create a configuration that sets `encrypt` parameter to the newly generated key. You can edit the existing agent configuration, or you can add a file to the configuration directory. For more information, refer to [configuring Consul agents](/consul/docs/agent#configuring-consul-agents). + + + +```hcl +encrypt = "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=" +``` + +```json +{ + "encrypt": "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=" +} +``` + + + +### Add the key to all agent configurations + +Distribute the gossip key to all the agent nodes that need to be pert of the datacenter. Then start the Consul agent on all the nodes. + +When gossip encryption is properly configured, `Gossip Encryption: true` appears in the Consul logs at startup. + + + +```log +==> Starting Consul agent... + Version: '1.19.0' +Build Date: '2024-06-12 13:59:10 +0000 UTC' + Node ID: 'e74b1ade-e932-1707-cdf1-6579b8b2536c' + Node name: 'consul-server-0' +Datacenter: 'dc1' (Segment: '') +Server: true (Bootstrap: false) + Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: 8443, gRPC: -1, gRPC-TLS: 8503, DNS: 53) + Cluster Addr: 172.19.0.7 (LAN: 8301, WAN: 8302) + Gossip Encryption: true + Auto-Encrypt-TLS: true + ACL Enabled: true + Reporting Enabled: false +ACL Default Policy: deny + HTTPS TLS: Verify Incoming: false, Verify Outgoing: true, Min Version: TLSv1_2 + gRPC TLS: Verify Incoming: false, Min Version: TLSv1_2 + Internal RPC TLS: Verify Incoming: true, Verify Outgoing: true (Verify Hostname: true), Min Version: TLSv1_2 +## ... +``` + + + +## Enable gossip encryption on an existing datacenter + +You can also enable gossip encryption on existing Consul datacenters. + +### Generate a gossip encryption key + +First, generate an encryption key on a Consul server. The Consul CLI includes a `consul keygen` command to generate a key. + +```shell-session +$ consul keygen +YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA= +``` + +### Add the key to the agent configuration + +Create a configuration that sets the `encrypt` parameter to the newly generated key and sets the `encrypt_verify_incoming` and `encrypt_verify_outgoing` parameters to `false`. You can edit the existing agent configuration, or you can add a file to the configuration directory. For more information, refer to [configuring Consul agents](/consul/docs/agent#configuring-consul-agents). + + + + + +```hcl +encrypt = "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=" +encrypt_verify_incoming = false +encrypt_verify_outgoing = false +``` + + + + + +```json +{ +"encrypt": "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=", +"encrypt_verify_incoming" : false, +"encrypt_verify_outgoing" : false +} +``` + + + + + +### Add the configuration to all agents + +Distribute the configuration to all the agent nodes that need to be part of the datacenter, and then initiate a rolling update that restarts each agent. + +You must restart all of the agents. The `consul reload` and `kill -HUP ` commands are not sufficient when changing the gossip configuration. + +### Update outgoing encryption + +The agents can decrypt gossip communication with the `encrypt` parameter set, but they are not able to send encrypted traffic. + +Update the `encrypt_verify_outgoing` setting to `true` and then perform another rolling update of all Consul agents. Complete the process on all the nodes before you begin [updates to incoming encryption](#update-the-incoming-encryption). + + + + + +```hcl +encrypt = "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=" +encrypt_verify_incoming = false +encrypt_verify_outgoing = true + ``` + + + + + +```json +{ +"encrypt": "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=", +"encrypt_verify_incoming": false, +"encrypt_verify_outgoing": true +} +``` + + + + + +### Update incoming encryption + +The agents can send encrypted gossip but still allow unencrypted incoming traffic. Update the `encrypt_verify_incoming` setting to `true` and then perform a final rolling update on all the agents. + + + + + +```hcl +encrypt = "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=" +encrypt_verify_incoming = true +encrypt_verify_outgoing = true +``` + + + + + +```json +{ +"encrypt": "YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA=", +"encrypt_verify_incoming": true, +"encrypt_verify_outgoing": true +} +``` + + + + + +## Rotate the gossip encryption key + +It is important to periodically rotate the gossip encryption key your Consul datacenter uses. + +The process of rotating the gossip encryption key is centralized so that you can perform it on a single datacenter node. + +The process to rotate a gossip encryption key consists of the following steps: + +1. Generate a new encryption key using the `consul keygen` command. +1. Install the new encryption key using the `consul keyring -install` command. +1. Verify the new key is installed in your Consul datacenter with the `consul keyring -list` command. +1. Instruct Consul to use the new key with the `consul keyring -use` command. +1. Remove the old key using the `consul keyring -remove` command. + +### Generate a new encryption key + +Generate a new key using `consul keygen`: + +```shell-session +$ consul keygen +FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= +``` + +### Add new key to the keyring + +Add your newly generated key to the keyring. + +```shell-session +$ consul keyring -install FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= +==> Installing new gossip encryption key... +``` + +### Verify that the new key is installed + +After you add the key to one of the Consul agents, Consul propagates it across the entire datacenter. You do not need to repeat the command on other agents. + +To ensure that the key has been propagated to all agents, list the installed encryption keys and verify that the number of agents that recognize the key is equal to the total number of agents in the datacenter. + +```shell-session +$ consul keyring -list +==> Gathering installed encryption keys... + +WAN: + FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= [1/1] + YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA= [1/1] + +dc1 (LAN): + YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA= [7/7] + FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= [7/7] +``` + +Confirm that the two keys are installed in the datacenter and recognized by all agents, including server agents. The server agents are listed in the `WAN` section. Do not proceed to the next step unless all agents have the new key. + +### Promote the new key to primary + +After all agents recognize the key, it is possible to promote it to be the new primary encryption key. + +```shell-session +$ consul keyring -use FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= +==> Changing primary gossip encryption key... +``` + +### Remove the old key from the keyring + +Unused keys in the keyring are a potential security risk to your Consul cluster. We recommended that you remove the former primary key from the keyring after a new key is installed. + +```shell-session +$ consul keyring -remove YwgWlBvicJN17UOYcutXLpJSZsw5aWpLEEWqgK635zA= +==> Removing gossip encryption key... +``` + +Verify that the keyring contains only one key. + +```shell-session +$ consul keyring -list +==> Gathering installed encryption keys... + +WAN: + FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= [1/1] + +dc1 (LAN): + FfRV9j6NXU9LlCI4zLZjjpZdj4Nrqsdm7R8YgzSHzHw= [7/7] +``` + +## Next steps + +Documentation for the commands used in this topic is available at [Consul agent configuration - Encryption Parameters](/consul/docs/agent/config/config-files#encryption-parameters). You can find more information over the gossip protocol used by Consul at [Gossip Protocol](/consul/docs/architecture/gossip). + +After you enable gossip encryption, you can continue to process to secure your Consul datacenter by enabling mutual TLS encryption. For more information, refer to [Mutual TLS (mTLS) Encryption](/consul/docs/security/encryption/mtls). + +To learn how to automate gossip key rotation using HashiCorp Vault and consul-template, refer to the [Automatically Rotate Gossip Encryption Keys Secured in Vault tutorial](/consul/tutorials/operate-consul/vault-kv-consul-secure-gossip). \ No newline at end of file diff --git a/website/content/docs/security/encryption/index.mdx b/website/content/docs/security/encryption/index.mdx new file mode 100644 index 000000000000..60a5352b8a6f --- /dev/null +++ b/website/content/docs/security/encryption/index.mdx @@ -0,0 +1,55 @@ +--- +layout: docs +page_title: Encrypted communication between Consul agents +description: >- + Consul supports encrypting all of its network traffic. Remote Procedure Calls (RPCs) between client and server agents can be encrypted with TLS and authenticated with certificates. Gossip communication between all agents can also be encrypted. +--- + +# Encrypted communication between Consul agents + +This topic provides an overview of the two distinct encryption systems available in Consul. [Gossip encryption](/consul/docs/security/encryption#gossip-encryption) and [Mutual TLS encryption](/consul/docs/security/encryption#mutual-tls-mtls-encryption) are the foundations of a secure Consul datacenter. + +The guidelines in the [Consul security model](/consul/docs/security/security-models/core) for operating a secure Consul deployment recommends using both encryption systems. + +## Gossip Encryption + +Consul uses a [gossip protocol](/consul/docs/architecture/gossip) to perform the following cluster operations: + +- Identify datacenter members. +- Quickly detect failed members and notify the rest of the cluster. +- Broadcast events and queries that can trigger custom workflows. + +The gossip protocol, as well as its membership management and message broadcasting features, use the [Serf library](https://github.com/hashicorp/serf/). + +In a default Consul configuration, the gossip protocol uses [port `8301`](/consul/docs/install/ports#lan-serf) for LAN communications and [port `8302`](/consul/docs/install/ports#lan-serf) for WAN communications between federated datacenters. Enabling gossip encryption on a Consul datacenter is required to secure traffic on these two ports. + +Gossip encryption is symmetric and based on a single key that is shared across all members of the datacenter. You can configure gossip encryption in Consul using the following parameters: + +- [`encrypt`](/consul/docs/agent/config/config-files#encrypt). +- [`encrypt_verify_incoming`](/consul/docs/agent/config/config-files#encrypt_verify_incoming). Only used when upshifting from unencrypted to encrypted gossip on a running cluster. +- [`encrypt_verify_outgoing`](/consul/docs/agent/config/config-files#encrypt_verify_outgoing). Only used when upshifting from unencrypted to encrypted gossip on a running cluster. + +To learn more about enabling gossip encryption on your Consul datacenter and rotating gossip keys, refer to [manage gossip encryption](/consul/docs/security/encryption/gossip). + +## Mutual TLS (mTLS) Encryption + +Consul uses several communication protocols over different ports that you can secure using mTLS: + +- A [consensus protocol](/consul/docs/architecture/consensus) provides data consistency between Consul servers. It typically uses [port `8300`](/consul/docs/install/ports#server-rpc). +- Remote Procedure Calls (RPC) forward requests from client agents to server agents. They use the same port the consensus protocol uses. +- An HTTP or HTTPS interface permits client communication with the Consul API, CLI, and UI. It typically uses [port `8500`](/consul/docs/install/ports#http) and [port `8501`](/consul/docs/install/ports#https). +- A gRPC interface receives incoming traffic from the gateways and Envoy proxies registered to the agent node. It typically uses [port `8502`](/consul/docs/install/ports#client-grpc) and [port `8503`](/consul/docs/install/ports#client-grpc-tls). + +Consul uses mTLS to verify the authenticity of server and client agents. It requires that all clients and servers have key pairs that are generated by a single Certification Authority (CA). We recommend using a private CA that is not shared with other applications. + +You can configure mTLS in Consul using the [`tls` stanza in agent configuration files](/consul/docs/agent/config/config-files#tls-1). + +You can configure mTLS encryption for each protocol separately using the following parameters in the agent configuration file: + +- [`tls.defaults`](/consul/docs/agent/config/config-files#tls_defaults) provides default settings that Consul applies to every interface unless explicitly overridden by protocol-specific configurations. +- [`tls.internal_rpc`](/consul/docs/agent/config/config-files#tls_internal_rpc) provides settings for the internal server RPC interface. +- [`tls.https`](/consul/docs/agent/config/config-files#tls_https) provides settings for the HTTP/HTTPS interface. +- [`tls.grpc`](/consul/docs/agent/config/config-files#tls_grpc) provides settings for the gRPC/xDS interface. + +To learn more about enabling mTLS on your Consul datacenter, refer to [Manage mTLS encryption](/consul/docs/security/encryption/mTLS). + diff --git a/website/content/docs/security/encryption/mtls.mdx b/website/content/docs/security/encryption/mtls.mdx new file mode 100644 index 000000000000..5017c7b509f3 --- /dev/null +++ b/website/content/docs/security/encryption/mtls.mdx @@ -0,0 +1,553 @@ +--- +layout: docs +page_title: Manage agent mTLS encryption +description: >- + Consul supports encrypting all of its network traffic. Learn how to encrypt and authenticate Remote Process Calls (RPCs) between client and server agents with TLS certificates. +--- + +# Manage agent mTLS encryption + +This topic describes mutual TLS (mTLS) encryption between agents in a Consul datacenter. + +This mTLS encryption is distinct from Consul service mesh mTLS encryption. To learn about encrypted mTLS communication between services, refer to [service mesh certificate authority](/consul/docs/connect/ca). + +## Benefits of TLS encryption + +Consul supports TLS certificates that verify the authenticity of servers and clients to secure `RCP`, `gRPC`, and `HTTP` traffic. + +Implementing TLS encryption in Consul datacenters improves your deployment's security in the following ways: + +- **Encrypt data in transit:** TLS encrypts data transmitted between Consul datacenter nodes and user interfaces such as the UI or CLI to ensure that sensitive information is not exposed to unauthorized parties. + +- **Agent authentication:** TLS ensures that only verified parties can communicate with each other using certificates. This security measure prevents unauthorized nodes, services, and users from interacting with your Consul datacenter. + +- **Prevent man-in-the-middle (MITM) attacks:** Without TLS, attackers may intercept and change communications within your Consul deployments. TLS mitigates this risk by encrypting data and verifying the identity of the communication participants. + +- **Comply with security regulations and standards:** Compliance frameworks and regulations like PCI-DSS and HIPAA mandate the encryption of data in transit, which makes TLS a requirement for Consul deployments in regulated environments. + +Mutual TLS (mTLS) requires that all clients and servers have key pairs that are generated by a single Certification Authority (CA). We recommend using a private CA that is not shared with other applications. + +The following parameters in agent configuration files define the agent verification behavior: + +- [`tls.defaults.verify_incoming`](/consul/docs/agent/config/config-files#tls_defaults_verify_incoming) +- [`tls.defaults.verify_outgoing`](/consul/docs/agent/config/config-files#tls_defaults_verify_outgoing) +- [`tls.defaults.verify_server_hostname`](/consul/docs/agent/config/config-files#tls_default_verify_server_hostname) + +## Workflow + +The process to enable TLS encryption in Consul deployments consists of the following steps: + +1. [Initialize the built-in CA](/consul/docs/security/encryption/mtls#initialize-the-built-in-ca) used to sign all certificates. +1. [Create server certificates](/consul/docs/security/encryption/mtls#create-server-certificates) to secure Consul servers. +1. [Configure server agents](/consul/docs/security/encryption/mtls#configure-server-agents) for TLS encryption. +1. [Start server agents](/consul/docs/security/encryption/mtls#start-consul-servers). +1. [Configure Consul client agents](/consul/docs/security/encryption/mtls#configure-client-agents). +1. [Start client agents](/consul/docs/security/encryption/mtls#start-consul-clients). + +## Initialize the built-in CA + +The first step to configure mTLS for Consul is to initialize the certificate authority (CA) that signs the certificates. To prevent unauthorized datacenter access, Consul requires that all certificates are signed by the same CA. We recommend using a private CA because any certificate it signs will be allowed to communicate with the Consul datacenter. + +Consul supports a variety of tools for creating and managing your own CA, like the [PKI secrets engine in Vault](/vault/docs/secrets/pki) or the [Terraform TLS provider](https://registry.terraform.io/providers/hashicorp/tls/latest/docs). Consul also ships with built-in TLS tools to create and manage certificates. + +If you have the Consul binary installed on your path, you can create the CA and certificates, even before you start a Consul server agent. + +```shell-session +$ consul tls ca create -domain=consul +==> Saved consul-agent-ca.pem +==> Saved consul-agent-ca-key.pem +``` + +The command generates two files, `-agent-ca.pem` and `-agent-ca-key.pem`. In this example, the domain used to generate the certificates is the default one, `consul`. + +The CA certificate, `consul-agent-ca.pem`, contains the public key necessary to validate Consul certificates. You must distribute this certificate to every node where a Consul agent runs. + +The CA key, `consul-agent-ca-key.pem`, signs certificates for Consul nodes. You must keep this key private. Possession of this key allows anyone to run Consul as a trusted server or generate new valid certificates for the datacenter. Malicious actors may use this key to obtain access to all Consul data, including ACL tokens. + +## Create server certificates + +To authenticate Consul servers, servers are provided with a special certificate that lists `server..` in the `Common Name` and `Subject Alternative Name` fields. When you enable [`tls.defaults.verify_server_hostname`](/consul/docs/agent/config/config-files#tls_default_verify_server_hostname), only agents that provide this certificate are allowed to boot as a server. + +Without `tls.defaults.verify_server_hostname = true`, an attacker who compromises a Consul client agent can restart the agent as a server to get access to all the data in your datacenter. You must keep the server key private to protect your Consul data. + +The following example creates a server certificate for datacenter `dc1` in the `consul` domain. If your datacenter or domain is different, modify the command to use the appropriate flag values. + +```shell-session +$ consul tls cert create -server -dc=dc1 -domain=consul +==> WARNING: Server Certificates grants authority to become a + server and access all state in the cluster including root keys + and all ACL tokens. Do not distribute them to production hosts + that are not server nodes. Store them as securely as CA keys. +==> Using consul-agent-ca.pem and consul-agent-ca-key.pem +==> Saved dc1-server-consul-0.pem +==> Saved dc1-server-consul-0-key.pem +``` + +Repeat this process on the same node where you created the CA until the number of certificates is equal to the number of servers in the datacenter. You can run the command multiple times in a row, and it automatically increases the certificate and key numbers each time. + +### Federated Consul datacenter + +A federated Consul environment requires the server certificate to include the names of all Consul datacenters that are within the federated environment. + +Use the `-additional-dnsname` flag to provide an additional DNS names for Subject Alternative Names. `localhost` is always included. You can provide this flag multiple times in a single command. + +The following example creates a certificate for a federated environment containing two Consul datacenters named `dc1` and `dc2`. + +```shell-session +$ consul tls cert create -server -dc dc1 -domain=consul -additional-dnsname="server.dc2.consul" +==> WARNING: Server Certificates grants authority to become a + server and access all state in the cluster including root keys + and all ACL tokens. Do not distribute them to production hosts + that are not server nodes. Store them as securely as CA keys. +==> Using consul-agent-ca.pem and consul-agent-ca-key.pem +==> Saved dc1-server-consul-0.pem +==> Saved dc1-server-consul-0-key.pem +``` + +## Configure server agents + +After you generate the server certificates, distribute them to the Consul servers and modify the agent configuration file to include their local location. + +Copy the following files to each Consul server: + +- `consul-agent-ca.pem`: CA public certificate. +- `dc1-server-consul-0.pem`: Consul server node public certificate for first server node in the `dc1` datacenter in the `consul` domain. +- `dc1-server-consul-0-key.pem`: Consul server node private key for first server node in the `dc1` datacenter in the `consul` domain. + +There are two methods for configuring Consul server agents depending on the way you want to distribute certificates to the client agents: + +- The _auto encryption method_ uses the Consul Connect CA to generate client certificates and then automatically distributes them to all Consul clients. +- The _operator method_ requires you to manually generate client certificates and distribute them to each client agent individually. + +We recommend using the auto-encryption method with the built-in CA because Consul can then automatically rotate certificates without requiring operator intervention. + +Use the operator method if you need to use a third-party CA or need more fine-grained control over certificate management. + + + + + + +```hcl +addresses = { + https = "0.0.0.0" +} +ports { + https = 8501 +} +tls { + defaults { + ca_file = "consul-agent-ca.pem" + cert_file = "dc1-server-consul-0.pem" + key_file = "dc1-server-consul-0-key.pem" + verify_incoming = true + verify_outgoing = true + verify_server_hostname = true + } +} +auto_encrypt { + allow_tls = true +} +``` + +```json +{ + "addresses": { + "https" : "0.0.0.0" + }, + "ports": { + "https" : 8501 + }, + "tls" : { + "defaults": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "dc1-server-consul-0.pem", + "key_file": "dc1-server-consul-0-key.pem", + "verify_incoming": true, + "verify_outgoing": true, + "verify_server_hostname": true + } + }, + "auto_encrypt" : { + "allow_tls" : true + } +} +``` + + + + + + + + + +```hcl +addresses = { + https = "0.0.0.0" +} +ports { + https = 8501 +} +tls { + defaults { + ca_file = "consul-agent-ca.pem" + cert_file = "dc1-server-consul-0.pem" + key_file = "dc1-server-consul-0-key.pem" + verify_incoming = true + verify_outgoing = true + verify_server_hostname = true + } +} +``` + +```json +{ + "addresses": { + "https": "0.0.0.0" + }, + "ports": { + "https": 8501 + }, + "tls": { + "defaults": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "dc1-server-consul-0.pem", + "key_file": "dc1-server-consul-0-key.pem", + "verify_incoming": true, + "verify_outgoing": true, + "verify_server_hostname": true + } + } +} +``` + + + + + + + +Consul does not enable TLS for HTTP unless the `https` port is assigned a port number greater than `0`. We recommend using `8501`, the default number for the `https` port, because this default is designed to work automatically with other tools. + +## Start Consul servers + +After you configure your servers, start the Consul process. + +```shell-session +$ systemctl start consul +``` + +Your Consul servers can now communicate with TLS encryption for RPC and consensus. + +## Configure client agents + +Next, configure your client agents with the same method you used to [configure the server agent](#distribute-the-server-certificates) + + + + +The only file you need on the local disk to configure the Consul client agents using auto-encryption is the CA certificate `consul-agent-ca-.pem`. + + + +```hcl +addresses = { + https = "0.0.0.0" +} +ports { + https = 8501 +} +tls { + defaults { + ca_file = "consul-agent-ca.pem" + verify_incoming = true + verify_outgoing = true + verify_server_hostname = true + } +} +auto_encrypt = { + tls = true +} +``` + +```json +{ + "addresses": { + "https": "0.0.0.0" + }, + "ports": { + "https": 8501 + }, + "tls": { + "defaults": { + "ca_file": "consul-agent-ca.pem", + "verify_incoming": true, + "verify_outgoing": true, + "verify_server_hostname": true + } + }, + "auto_encrypt" : { + "tls" : true + } +} +``` + + + + + + + +On the node where you created the CA and server certificates, generate a client certificate with `consul tls cert create -client` command. + +```shell-session +$ consul tls cert create -client -dc=dc1 -domain=consul +==> Using consul-agent-ca.pem and consul-agent-ca-key.pem +==> Saved dc1-client-consul-0.pem +==> Saved dc1-client-consul-0-key.pem +``` + +The client certificate is also signed by the same CA used for the server certificates, but it does not contain `server..` in the `Common Name` and in the `Subject Alternative Name`. Because `verify_server_hostname` is enabled, a compromised client cannot use this certificate to start as a server and access datacenter data. + +Distribute the client certificates and the CA certificate `consul-agent-ca.pem` to every Consul client in the datacenter. Then add them to the client agent configuration. + + + +```hcl +addresses = { + https = "0.0.0.0" +} +ports { + https = 8501 +} +tls { + defaults { + ca_file = "consul-agent-ca.pem" + cert_file = "dc1-client-consul-0.pem" + key_file = "dc1-client-consul-0-key.pem" + verify_incoming = true + verify_outgoing = true + verify_server_hostname = true + } +} +``` + +```json +{ + "addresses": { + "https": "0.0.0.0" + }, + "ports": { + "https": 8501 + }, + "tls": { + "defaults": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "dc1-client-consul-0.pem", + "key_file": "dc1-client-consul-0-key.pem", + "verify_incoming": true, + "verify_outgoing": true, + "verify_server_hostname": true + } + } +} +``` + + + + + + + +## Start Consul clients + +After you configure each client, start the Consul process on the node. + +```shell-session +$ systemctl start consul +``` + +Your client agents now communicate using mutual TLS encryption. + +## Rotate TLS certificates + +To maintain the security offered by TLS encryption, we recommend that you rotate TLS certificates often. + +TLS certificates are part of [Consul's reloadable configuration](/consul/docs/agent/config#reloadable-configuration), so you do not need to restart the Consul agents when you renew certificates. As a result, there is no risk of downtime. + +To rotate certificates for Consul server agents complete the following steps: +1. [Generate new certificates for all server agents](/consul/docs/security/encryption/mtls#create-server-certificates) to replace the old ones. +1. Distribute the new certificates to the server nodes. +1. Reload Consul configuration on each server with the `consul reload` command. + +To rotate certificates for Consul client agents complete the following steps: + + + + +When using the auto-encryption method, Consul automatically rotates the client certificates without operator intervention. + + + + + +1. [Generate new certificates for all client agents](/consul/docs/security/encryption/mtls#configure-client-agents) to replace the old ones. +1. Distribute the new certificates to the client nodes. +1. Reload Consul configuration on all clients with `consul reload` command. + + + + + +## API, CLI, and UI interactions + +The configuration snippets provided in this page are valid to configure complete mTLS for your Consul datacenter. This means that all interfaces require the client to provide a valid certificate in order to communicate with the Consul agent. This is valid for all requests, API, CLI, and UI. + +Since Consul v1.12 it is possible to have different settings for: + + - the HTTP protocol, used for the Consul's REST API, the CLI integration, and the UI + - the RPC protocol, used for internal communications between the Consul agents. + +### Interact with Consul without a client certificate + +If you want to avoid the need to present a valid client certificate every time you interact with Consul using the HTTP API, CLI, or UI, configure Consul to trust all incoming HTTPS connections by setting `tls.https.verify_incoming` to `false`. RPC communications are still mTLS encrypted. + + + +```hcl +addresses = { + https = "0.0.0.0" +} +ports { + https = 8501 + http = -1 +} +tls { + https { + ca_file = "/etc/consul.d/consul-agent-ca.pem" + cert_file = "/etc/consul.d/consul-agent.pem" + key_file = "/etc/consul.d/consul-agent-key.pem" + verify_incoming = false + verify_outgoing = true + } + internal_rpc { + ca_file = "/etc/consul.d/consul-agent-ca.pem" + cert_file = "/etc/consul.d/consul-agent.pem" + key_file = "/etc/consul.d/consul-agent-key.pem" + verify_incoming = true + verify_outgoing = true + verify_server_hostname = true + } +} +``` + +```json +{ + "addresses": { + "https": "0.0.0.0", + "http": "127.0.0.1", + }, + "ports": { + "https": 8501, + "http": 8500 + }, + "tls": { + "https": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "consul-agent.pem", + "key_file": "consul-agent-key.pem", + "verify_incoming": false, + "verify_outgoing": true + }, + "internal_rpc": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "consul-agent.pem", + "key_file": "consul-agent-key.pem", + "verify_incoming": true, + "verify_outgoing": true, + "verify_server_hostname": true + } + } +} +``` + + + + +### Use HTTP for local client interaction + +If you want to avoid the need to present a valid client certificate or to use the CA certificate every time you interact with the local Consul agent, configure Consul to keep the HTTP listener active on the `localhost` interface only and set `tls.https.verify_incoming` to `false`. External requests to the API or UI are still protected by TLS encryption, but requests that originate locally do not need to present a client certificate. RPC communications are still mTLS encrypted. + + + +```hcl +addresses = { + https = "0.0.0.0" + http = "127.0.0.1" +} +ports { + https = 8501 + http = 8500 +} +tls { + https { + ca_file = "/etc/consul.d/consul-agent-ca.pem" + cert_file = "/etc/consul.d/consul-agent.pem" + key_file = "/etc/consul.d/consul-agent-key.pem" + verify_incoming = false + verify_outgoing = true + } + internal_rpc { + ca_file = "/etc/consul.d/consul-agent-ca.pem" + cert_file = "/etc/consul.d/consul-agent.pem" + key_file = "/etc/consul.d/consul-agent-key.pem" + verify_incoming = true + verify_outgoing = true + verify_server_hostname = true + } +} +``` + +```json +{ + "addresses": { + "https": "0.0.0.0", + "http": "127.0.0.1", + }, + "ports": { + "https": 8501, + "http": 8500 + }, + "tls": { + "https": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "consul-agent.pem", + "key_file": "consul-agent-key.pem", + "verify_incoming": false, + "verify_outgoing": true + }, + "internal_rpc": { + "ca_file": "consul-agent-ca.pem", + "cert_file": "consul-agent.pem", + "key_file": "consul-agent-key.pem", + "verify_incoming": true, + "verify_outgoing": true, + "verify_server_hostname": true + } + } +} +``` + + + +## Next steps + +Your agents are now configured with mTLS for encrypted communication. With the auto encryption method, your +client certificates are managed by the server. With the operator method, you distributed all the certificates manually, but have a more flexible configuration. + +Documentation for the commands used in this topic is available at [Consul agent configuration - TLS configuration reference](/consul/docs/agent/config/config-files#tls-configuration-reference) and the [`consul tls` CLI command reference](/consul/commands/tls). + +To learn how to automate TLS certificate generation and rotation, refer to the [Generate mTLS Certificates for Consul with Vault](/consul/tutorials/operate-consul/vault-pki-consul-secure-tls) tutorial. + +To continue securing your Consul deployment, add [gossip encryption](/consul/docs/security/encryption/gossip) and enable [Access Control Lists (ACLs)](/consul/docs/security/acl) with the default deny policy. diff --git a/website/content/docs/security/index.mdx b/website/content/docs/security/index.mdx index 0ec501aabf29..1f89ad104d23 100644 --- a/website/content/docs/security/index.mdx +++ b/website/content/docs/security/index.mdx @@ -5,11 +5,15 @@ description: >- Security requirements and recommendations for Consul vary depending on workloads and environments. Learn how ACLs and encryption can protect access to and communication within your datacenter. --- +# Consul security + +This topic describes the security requirements and recommendations for a Consul deployment. + ## Security Models Requirements and recommendations for operating a secure Consul deployment may vary drastically depending on your intended workloads, operating system, and environment. You can find detailed information about the various personas, -recommendations, requirements, and threats [here](/consul/docs/security/security-models). +recommendations, requirements, and threats in the [Security Models](/consul/docs/security/security-models) section. ## ACLs @@ -18,6 +22,9 @@ to data and APIs. ## Encryption -The Consul agent supports encrypting all of its network traffic. The exact method of encryption is described on the -[encryption security page](/consul/docs/security/encryption). There are two separate encryption systems, one for gossip -traffic and one for HTTP + RPC. +The Consul agent supports encryption for all of its network traffic. There are two separate encryption systems: + +- A gossip encryption system +- An mTLS encryption system for HTTP and RPC + +For more information about these two different encryption systems, as well as configuration guidance, refer to [Consul encryption](/consul/docs/security/encryption). diff --git a/website/content/docs/security/security-models/core.mdx b/website/content/docs/security/security-models/core.mdx index 1140cdab30e8..9b0da86089ca 100644 --- a/website/content/docs/security/security-models/core.mdx +++ b/website/content/docs/security/security-models/core.mdx @@ -5,7 +5,7 @@ description: >- The security model for Consul Core details requirements and recommendations for securing your deployment of Consul. Learn about potential threats and how to protect Consul from malicious actors. --- -## Overview +# Consul security model overview Consul enables automation of network configurations, service discovery, and secure network connectivity across any cloud or runtime. @@ -26,13 +26,17 @@ environment, but the general mechanisms for a secure Consul deployment revolve a [authentication methods](/consul/docs/security/acl/auth-methods) can be used to enable trusted external parties to authorize ACL token creation. +- **Intentions** - If in use, configure service intentions to use a default-deny policy. If L7 intentions are + in use, enable [Mesh request normalization](/consul/docs/connect/config-entries/mesh#request-normalization) + and review your [header match rules](/consul/docs/connect/config-entries/service-intentions#spec-sources-permissions-http-header) to prevent malformed requests from bypassing intentions. + - **Namespaces** - Read and write operations can be scoped to a logical namespace to restrict access to Consul components within a multi-tenant environment. - **Sentinel Policies** - Sentinel policies enable policy-as-code for granular control over the built-in key-value store. -### Personas +## Personas It helps to consider the following types of personas when managing the security requirements of a Consul deployment. The granularity may change depending on your team's requirements. @@ -60,14 +64,14 @@ The granularity may change depending on your team's requirements. be public facing on the internet such as a web server, typically through a load-balancer, or ingress gateway. This is someone who should not have any network access to the Consul agent APIs. -### Secure Configuration +## Secure Configuration Consul's security model is applicable only if all parts of the system are running with a secure configuration; **Consul is not secure-by-default.** Without the following mechanisms enabled in Consul's configuration, it may be possible to abuse access to a cluster. Like all security considerations, administrators must determine what is appropriate for their environment and adapt these configurations accordingly. -#### Requirements +## Requirements - **mTLS** - Mutual authentication of both the TLS server and client x509 certificates prevents internal abuse through unauthorized access to Consul agents within the cluster. @@ -178,6 +182,13 @@ environment and adapt these configurations accordingly. - **🏷 Namespace** - a named, logical scoping of Consul Enterprise resources, typically to enable multi-tenant environments. Consul CE clusters always operate within the "default" namespace. +- **Intentions** - Service intentions control traffic communication between services at the network layer (L4) and + application layer (L7). If in use, we strongly recommend configuring intentions to use a default-deny policy. + When L7 intentions are in use, review your configuration for [Mesh request normalization](/consul/docs/connect/config-entries/mesh#request-normalization) + and use the strictest set of options suitable to your environment. At minimum, we + recommend keeping path normalization enabled, because this default setting prevents requests that do not conform to [RFC 3986]( + https://tools.ietf.org/html/rfc3986#section-6) from bypassing path match rules. + - **Gossip Encryption** - A shared, base64-encoded 32-byte symmetric key is required to [encrypt Serf gossip communication](/consul/tutorials/security/gossip-encryption-secure?utm_source=consul.io&utm_medium=docs) within a cluster using AES GCM. The key size determines which AES encryption types to use; 16, 24, or 32 bytes to select AES-128, AES-192, @@ -212,7 +223,7 @@ environment and adapt these configurations accordingly. commands across the cluster. This is disabled by default since 0.8.0. We recommend leaving it disabled. If enabled, extreme care must be taken to ensure correct ACLs restrict access to execute arbitrary code on the cluster. -#### Recommendations +## Recommendations - **Rotate Credentials** - Using short-lived credentials and rotating them frequently is highly recommended for production environments to limit the blast radius from potentially compromised secrets, and enabling basic auditing. @@ -252,6 +263,10 @@ environment and adapt these configurations accordingly. } ``` +- **Customize Mesh HTTP Request Normalization** - If L7 intentions are in use, we recommend configuring request normalization to + avoid match rule circumvention. Other normalization options, such as dropping or rejecting headers with underscores, + may also be appropriate depending on your requirements. Review the options in the [Mesh configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization) to determine the appropriate settings for your use case. + - **Customize Default Limits** - Consul has a number of builtin features with default connection limits that should be tuned to fit your environment. @@ -307,7 +322,7 @@ environment and adapt these configurations accordingly. } ``` -### Threat Model +## Threat Model The following are parts of the core Consul threat model: @@ -381,7 +396,7 @@ The following are not part of the threat model for client agents: endpoint. If any of this isn't performed correctly, the proxy or service may allow unauthenticated or unauthorized connections. -#### Internal Threats +## Internal Threats - **Operator** - A malicious internal Consul operator with a valid mTLS certificate and ACL token may still be a threat to your cluster in certain situations, especially in multi-team deployments. They may accidentally or intentionally @@ -409,7 +424,7 @@ The following are not part of the threat model for client agents: information. When ACLs and HTTPS are enabled, the gRPC endpoint serving up the xDS service requires (m)TLS and a valid ACL token. -#### External Threats +## External Threats - **Agents** - External access to the Consul agent's various network endpoints should be considered including the gossip, HTTP, RPC, and gRPC ports. Furthermore, access through other services like SSH or `exec` functionality in diff --git a/website/content/docs/security/security-models/index.mdx b/website/content/docs/security/security-models/index.mdx index bcb8f639af0f..eea5cd6ab29f 100644 --- a/website/content/docs/security/security-models/index.mdx +++ b/website/content/docs/security/security-models/index.mdx @@ -5,20 +5,20 @@ description: >- Security models are the set of requirements and recommendations for securely operating a Consul deployment. Learn about security models and how they differ between environments. --- -## Overview +# Security models overview Requirements and recommendations for operating a secure Consul deployment may vary drastically depending on your intended workloads, operating system, and environment. Consul is not secure by default, but can be configured to satisfy the security requirements for a wide-range of use cases from local developer environments without any configuration to container orchestrators in-production with ACL authorization, and mTLS authentication. -### Core +## Core The core Consul product provides several options for enabling encryption, authentication, and authorization controls for a cluster. You can read more about the various personas, recommendations, requirements, and threats [here](/consul/docs/security/security-models/core). -### NIA +## NIA [Network Infrastructure Automation](/consul/docs/nia) (NIA) enables dynamic updates to network infrastructure devices triggered by service changes. Both the core Consul product's configuration and the configuration for the `consul-terraform-sync` diff --git a/website/content/docs/security/security-models/nia.mdx b/website/content/docs/security/security-models/nia.mdx index 0e6de4982b14..6770890654da 100644 --- a/website/content/docs/security/security-models/nia.mdx +++ b/website/content/docs/security/security-models/nia.mdx @@ -5,7 +5,7 @@ description: >- The NIA security model details requirements and recommendations for securing your Consul-Terraform-Sync (CTS) deployment. Learn about potential threats and how to protect CTS from malicious actors. --- -## Overview +# Network Infrastructure Automation (NIA) overview Network Infrastructure Automation (NIA) enables dynamic updates to network infrastructure devices triggered by service changes using the [Consul Terraform Sync](https://github.com/hashicorp/consul-terraform-sync) (`consul-terraform-sync`) daemon. This daemon uses Consul's catalog to monitor networking information about services along with [Terraform](https://www.terraform.io/)'s provider ecosystem to apply relevant changes to network infrastructure. @@ -13,7 +13,7 @@ The [Secure Consul-Terraform-Sync for Production](/consul/tutorials/network-infr tutorial contains a checklist of best practices to secure your Consul-Terraform-Sync installation for a production environment. -### Personas +## Personas When considering Consul NIA's security model, it helps to think of the following personas. @@ -32,7 +32,7 @@ When considering Consul NIA's security model, it helps to think of the following have no knowledge or access to the daemon's API endpoints, ACL tokens, certificates, or any other piece of the system. -### Secure Configuration +## Secure Configuration Consul NIA's security model is applicable only if all parts of the system are running with a secure configuration; `consul-terraform-sync` is not secure-by-default. Without the following mechanisms enabled in the @@ -40,7 +40,7 @@ daemon's configuration, it may be possible to abuse access to the daemon. Like a considerations, one must determine what concerns are appropriate for their environment, and adapt these security concerns accordingly. -#### Requirements +## Requirements - **Protect Configuration Files and Directories** - A dedicated NIA user and group with limited permissions should be created for production, along with directory, and file permissions appropriately @@ -68,7 +68,7 @@ security concerns accordingly. - **Read** permission for Consul Catalog for all of the selected services to be monitored, and their namespaces. - **Read + Write** permission to update health checks, when using NIA health monitoring. -#### Recommendations +## Recommendations - **Use Dedicated Host** - The NIA daemon will potentially have access to critical secrets for your environment's network infrastructure. Using a hardened, dedicated host, for supporting these sensitive operations is highly recommended. @@ -85,7 +85,7 @@ security concerns accordingly. are configured with the NIA daemon should be audited to ensure you're only using providers from sources that you trust. -### Threat Model +## Threat Model The following are the parts of the NIA threat model: @@ -131,7 +131,7 @@ a production deployment: - **Access to the Consul-Terraform-Sync Binary** - Direct access to the system binary used to start the NIA daemon can allow an attacker to extract sensitive information. -#### Internal Threats +## Internal Threats - **NIA Operator** - Someone with access to the NIA Host, and it's related binaries or configuration files may be a threat to your deployment, especially considering multi-team deployments. They may accidentally or intentionally use a @@ -150,7 +150,7 @@ a production deployment: means. Extra steps to configuring OS, cluster, service, user, directory, and file permissions are essential steps for implementing defense-in-depth within a production environment. -#### External Threats +## External Threats - **Terraform Providers and Modules** - Potentially malicious providers or modules, or any malicious dependencies part of the Terraform ecosystem could cause harm to the network, and may have access to secrets in order to make necessary diff --git a/website/content/docs/services/configuration/services-configuration-reference.mdx b/website/content/docs/services/configuration/services-configuration-reference.mdx index 2214bbabf566..59e93da6896f 100644 --- a/website/content/docs/services/configuration/services-configuration-reference.mdx +++ b/website/content/docs/services/configuration/services-configuration-reference.mdx @@ -360,22 +360,21 @@ The following table describes the parameters you can explicitly configure in the | `zone` | Specifies the availability zone where the Consul agent is running. Consul assigns this value to services registered to that agent. When service proxy regions match, Consul is able to prioritize routes between service instances in the same region and zone over instances in other regions and zones. When healthy service instances are available in multiple zones within the most-local region, Consul prioritizes instances that also match the downstream proxy's `zone`. You must specify values that are consistent with how zones are defined in your network, for example `us-west-1a` for networks in AWS. | String | None | ### weights -Object that configures how the service responds to DNS SRV requests based on the service's health status. Configuring allows service instances with more capacity to respond to DNS SRV requests. It also reduces the load on services with checks in `warning` status by giving passing instances a higher weight. +Object that configures how a service instance is weighted in a DNS SRV request based on the service's health status. Configuring tells DNS clients to direct more traffic to instances with a higher weight. A use case would be adjusting the weight higher for an instance with large capacity. It could also be used to reduce the load on services with checks in `warning` status by favoring passing instances with a higher weight. You can specify one or more of the following states and configure an integer value indicating its weight: - `passing` - `warning` -- `critical` Larger integer values increase the weight state. Services have the following default weights: - `"passing" : 1` - `"warning" : 1` -Services in a `critical` state are excluded from DNS responses by default. Services with `warning` checks are included in responses by default. Refer to [Perform Static DNS Queries](/consul/docs/services/discovery/dns-static-lookups) for additional information. +Services in a `critical` state are excluded from DNS responses. Services with `warning` checks are included in responses by default. Refer to [Perform Static DNS Queries](/consul/docs/services/discovery/dns-static-lookups) for additional information. -In the following example, service instances in a `passing` state respond to DNS SRV requests, while instances in a `critical` instance can still respond at a lower frequency: +In the following example, DNS SRV queries direct more traffic to service instances in a `passing` state, while instances in a `warning` instance are less favored: @@ -386,8 +385,7 @@ service { port = 6379 weights = { passing = 3 - warning = 2 - critical = 1 + warning = 1 } } ``` @@ -400,8 +398,7 @@ service { "port": 6379, "weights": { "passing": 3, - "warning": 2, - "critical": 1 + "warning": 1 } } } diff --git a/website/content/docs/services/discovery/dns-cache.mdx b/website/content/docs/services/discovery/dns-cache.mdx new file mode 100644 index 000000000000..68b531d1b699 --- /dev/null +++ b/website/content/docs/services/discovery/dns-cache.mdx @@ -0,0 +1,250 @@ +--- +layout: docs +page_title: Scale Consul DNS +description: -> + You tune Consul DNS query handling to balance between current information and reducing request response time. Learn how to enable caching by modifying TTL values, how to return stale results from the DNS cache, and how to configure Consul for negative response caching. +--- + +# Scale Consul DNS + +This page describes the process to return cached results in response to DNS lookups. Consul agents can use DNS caching to reduce response time, but might provide stale information in the process. + +## Scaling techniques + +By default, Consul serves all DNS results with a `0` TTL value so that it returns the most recent information. When operating at scale, this configuration may result in additional latency because servers must respond to every DNS query. There are several strategies for distributing this burden in your datacenter: + +- [Allow Stale Reads](#stale-reads). Allows other servers besides the leader to answer the query rather than forwarding it to the leader. +- [Configure DNS TTLs](#ttl-values). Configure DNS time-to-live (TTL) values for nodes or services so that the DNS subsystem on the container’s operating system can cache responses. Services then resolve DNS queries locally without any external requests. +- [Add Read Replicas](/consul/docs/enterprise/read-scale). Enterprise users can use read replicas, which are additional Consul servers that replicate cluster data without participating in the Raft quorum. +- [Use Cache to prevent server requests](/consul/docs/agent/config/config-files#dns_use_cache). Configure the Consul client to use its agent cache to subscribe to events about a service or node. After you establish the watch, the local Consul client agent can resolve DNS queries about the service or node without querying Consul servers. + +The following table describes the availability of each scaling technique depending on whether you configure Consul to offload DNS requests from the cluster leader to a client agent, dataplane, or DNS proxy. + +| Scaling technique | Supported by client agents | Supported by dataplanes | Supported by Consul DNS Proxy | +| :---------------------------------- | :---------------------------: | :---------------------------: | :---------------------------: | +| Configure DNS TTLs | ✅ | ✅ | ✅ | +| Allow Stale Reads | ✅ | ✅ | ✅ | +| Add Read Replicas | ✅ | ✅ | ✅ | +| Use Cache to prevent server request | ✅ | ❌ | ❌ | + +For more information about considerations for Consul deployments that operate at scale, refer to [Operating Consul at Scale](/consul/docs/architecture/scale). + +## TTL values ((#ttl)) + +You can configure TTL values in the [agent configuration file](/consul/docs/agent/config/config-files) to allow DNS results to be cached downstream of Consul. +Higher TTL values reduce the number of lookups on the Consul servers and speed +lookups for clients, at the cost of increasingly stale results. By default, all +TTLs are zero, preventing any caching. + + + +```hcl +dns_config { + service_ttl { + "*" = "0s" + } + node_ttl = "0s" +} +``` + +```json +{ + "dns_config": { + "service_ttl": { + "*": "0s" + }, + "node_ttl": "0s" + } +} +``` + + + +### Enable caching + +To enable caching of node lookups, set the +[`dns_config.node_ttl`](/consul/docs/agent/config/config-files#node_ttl) +value. This can be set to `10s` for example, and all node lookups will serve +results with a 10 second TTL. + +Service TTLs can be specified in a more granular fashion. You can set TTLs +per-service, with a wildcard TTL as the default. This is specified using the +[`dns_config.service_ttl`](/consul/docs/agent/config/config-files#service_ttl) +map. The `*` is supported at the end of any prefix and has a lower precedence +than strict match, so `my-service-x` has precedence over `my-service-*`. When +performing wildcard match, the longest path is taken into account, thus +`my-service-*` TTL will be used instead of `my-*` or `*`. With the same rule, +`*` is the default value when nothing else matches. If no match is found the TTL +defaults to 0. + +For example, a [`dns_config`](/consul/docs/agent/config/config-files#dns_config) +that provides a wildcard TTL and a specific TTL for a service might look like this: + + + +```hcl +dns_config { + service_ttl { + "*" = "5s" + "web" = "30s" + "db*" = "10s" + "db-master" = "3s" + } +} +``` + +```json +{ + "dns_config": { + "service_ttl": { + "*": "5s", + "web": "30s", + "db*": "10s", + "db-master": "3s" + } + } +} +``` + + + +This sets all lookups to "web.service.consul" to use a 30 second TTL +while lookups to "api.service.consul" will use the 5 second TTL from the wildcard. +All lookups matching "db\*" would get a 10 seconds TTL except "db-master" that +would have a 3 seconds TTL. + +### Prepared queries + +[Prepared Queries](/consul/api-docs/query) provide an additional +level of control over TTL. They allow for the TTL to be defined along with +the query, and they can be changed on the fly by updating the query definition. +If a TTL is not configured for a prepared query, then it will fall back to the +service-specific configuration defined in the Consul agent as described above, +and ultimately to 0 if no TTL is configured for the service in the Consul agent. + + + +## Stale reads + +Stale reads can be used to reduce latency and increase the throughput of DNS +queries. The [settings](/consul/docs/agent/config/config-files) used to +control stale reads of DNS queries are: + +- [`dns_config.allow_stale`](/consul/docs/agent/config/config-files#allow_stale) must be + set to true to enable stale reads. +- [`dns_config.max_stale`](/consul/docs/agent/config/config-files#max_stale) limits how stale results + are allowed to be when querying DNS. + +With these two settings you can allow or prevent stale reads. Below we will +discuss the advantages and disadvantages of both. + +### Allow stale reads + +Since Consul 0.7.1, `allow_stale` is enabled by default and uses a `max_stale` +value that defaults to a near-indefinite threshold (10 years). This allows DNS +queries to continue to be served in the event of a long outage with no leader. A +new telemetry counter has also been added at `consul.dns.stale_queries` to track +when agents serve DNS queries that are stale by more than 5 seconds. + + + +```hcl +dns_config { + allow_stale = true + max_stale = "87600h" +} +``` + +```json +{ + "dns_config": { + "allow_stale": true, + "max_stale": "87600h" + } +} +``` + + + + + + + The above example is the default setting. You do not need to set it explicitly. + + + +Doing a stale read allows any Consul server to service a query, but non-leader +nodes may return data that is out-of-date. By allowing data to be slightly +stale, you get horizontal read scalability. Now any Consul server can service +the request, so you increase throughput by the number of servers in a datacenter. + +### Prevent stale reads + +If you want to prevent stale reads or limit how stale they can be, you can set +`allow_stale` to false or use a lower value for `max_stale`. Doing the first +will ensure that all reads are serviced by a +[single leader node](/consul/docs/architecture/consensus). +The reads will then be strongly consistent but will be limited by the throughput +of a single node. + + + +```hcl +dns_config { + allow_stale = false +} +``` + +```json +{ + "dns_config": { + "allow_stale": false + } +} +``` + + + +## Negative response caching + +Although DNS clients cache negative responses, Consul returns a "not +found" style response when a service exists but there are no healthy +endpoints. When using DNS for service discovery, cached negative responses may +cause a service to appear down for longer than it is actually unavailable. + +### Configure SOA + +In Consul v1.3.0 and newer, it is now possible to tune SOA responses and modify +the negative TTL cache for some resolvers. It can be achieved using the +[`soa.min_ttl`](/consul/docs/agent/config/config-files#soa_min_ttl) +configuration within the [`soa`](/consul/docs/agent/config/config-files#soa) configuration. + + + +```hcl +dns_config { + soa { + min_ttl = 60 + } +} +``` + +```json +{ + "dns_config": { + "soa": { + "min_ttl": 60 + } + } +} +``` + + + +One common example is that Windows will default to caching negative responses +for 15 minutes. DNS forwarders may also cache negative responses, with the same +effect. To avoid this problem, check the negative response cache defaults for +your client operating system and any DNS forwarder on the path between the +client and Consul and set the cache values appropriately. In many cases +"appropriately" means turning negative response caching off to get the best +recovery time when a service becomes available again. diff --git a/website/content/docs/services/discovery/dns-configuration.mdx b/website/content/docs/services/discovery/dns-configuration.mdx index 5a0d890e79bf..5e78494ce728 100644 --- a/website/content/docs/services/discovery/dns-configuration.mdx +++ b/website/content/docs/services/discovery/dns-configuration.mdx @@ -33,6 +33,8 @@ You can specify a list of addresses in the agent's [`recursors`](/consul/docs/ag Nodes that query records outside the `consul.` domain resolve to an upstream DNS. You can specify IP addresses or use `go-sockaddr` templates. Consul resolves IP addresses in the specified order and ignores duplicates. +We recommend that you configure DNS resolvers to point the `consul.` domain towards your Consul DNS servers. Misconfigurations may cause other DNS infrastructure to route queries for the `consul.` domain outside of your network instead, leaking DNS queries to root DNS servers. Refer to [Forward DNS for Consul Service Discovery](/consul/tutorials/networking/dns-forwarding) for instructions. + ### Enable non-Consul queries You enable non-Consul queries to be resolved by setting Consul as the DNS server for a node and providing a [`recursors`](/consul/docs/agent/config/config-files#recursors) configuration. @@ -65,12 +67,5 @@ machine.node.dc1.test-domain. 0 IN TXT "consul-network-segment=" Responses to pointer record (PTR) queries, such as `.in-addr.arpa.`, always use the [primary domain](/consul/docs/agent/config/config-files#domain) and not the alternative domain. ### Caching -By default, DNS results served by Consul are not cached. Refer to the [DNS Caching tutorial](/consul/tutorials/networking/dns-caching) for instructions on how to enable caching. - - - - - - - +By default, DNS results served by Consul are not cached. Refer to [DNS caching](/consul/docs/services/discovery/dns-cache) for instructions on how to enable caching. diff --git a/website/content/docs/services/discovery/dns-forwarding/enable.mdx b/website/content/docs/services/discovery/dns-forwarding/enable.mdx new file mode 100644 index 000000000000..e7def0b4bc25 --- /dev/null +++ b/website/content/docs/services/discovery/dns-forwarding/enable.mdx @@ -0,0 +1,420 @@ +--- +layout: docs +page_title: Enable DNS forwarding +description: -> + Learn how to configure different DNS servers to perform DNS forwarding to Consul servers. +--- + +# Enable DNS forwarding + +This page describes the process to enable DNS forwarding to Consul servers. + +You can apply these operations on every node where a Consul agent is running. + +## Requirements + +To enable DNS forwarding, your deployment must have the following: + +- A running Consul server instance +- One or more Consul client nodes with registered services in the Consul catalog +- The `iptables` command available, or one of the following local DNS servers: + - [systemd-resolved](#systemd-resolved) + - [BIND](#bind) + - [Dnsmasq](#dnsmasq) + - [Unbound](#unbound) + - [macOS system resolver](#macos) + +### Network address configuration + +The example configurations on this page assumes Consul's DNS server is listening on the loopback interface on the same node of the local DNS server. + +If Consul is not listening on the loopback IP, replace the references to `localhost` and `120.0.0.1` in the configuration and commands with the appropriate IP address for your environment. + +## systemd-resolved + +[`systemd-resolved`](https://www.freedesktop.org/software/systemd/man/latest/systemd-resolved.service.html) is a system service that provides network name resolution to local applications. It is the default local DNS server for many Linux distributions. + +To configure the `systemd-resolved` service so that it sends `.consul` domain queries to Consul, create a `consul.conf` file located in the `/etc/systemd/resolved.conf.d/` directory. + + + + +Add a `[Resolve]` section to your resolved configuration. + + + +```ini +[Resolve] +DNS=127.0.0.1 +DNSSEC=false +Domains=~consul +``` + + + +### Define port for Consul DNS server + +When using systemd 245 and older, you cannot specify port numbers in the `DNS` configuration field. systemd-resolved only uses port `53`, which is a privileged port. + +When you cannot specify ports for the system's configuration, there are two workarounds: + - [Configure Consul DNS service to listen on port `53`](/consul/docs/agent/config/config-files#dns_port) instead of `8600`. + - Map port `53` to `8600` using `iptables`. + +Binding to port `53` usually requires running Consul as a privileged user or running Linux with the `CAP_NET_BIND_SERVICE` capability. +When using the Consul Docker image, add the following to the environment to allow Consul to use the port: `CONSUL_ALLOW_PRIVILEGED_PORTS=yes`. + +To avoid running Consul as a privileged user, the following `iptables` commands are sufficient to map port `53` to `8600` and redirect DNS queries to Consul. + +```shell-session +# iptables --table nat --append OUTPUT --destination localhost --protocol udp --match udp --dport 53 --jump REDIRECT --to-ports 8600 && \ + iptables --table nat --append OUTPUT --destination localhost --protocol tcp --match tcp --dport 53 --jump REDIRECT --to-ports 8600 +``` + + + + + +Systemd 246 and newer allow you to specify the DNS port directly in the `systemd-resolved` configuration file. +Previous versions of systemd required iptables rules to direct DNS traffic to Consul. + +Add a `[Resolve]` section to your resolved configuration. + + + +```ini +[Resolve] +DNS=127.0.0.1:8600 +DNSSEC=false +Domains=~consul +``` + + + + + + +PTR record queries are still sent to the other configured resolvers, in addition to Consul. + +After creating the resolved configuration, restart `systemd-resolved`. + +```shell-session +# systemctl restart systemd-resolved +``` + +The command produces no output. + +### Validate the systemd-resolved configuration + +Validate that `systemd-resolved` is active. + +```shell-session +# systemctl is-active systemd-resolved +active +``` + +Verify that `systemd-resolved` is configured to forward queries for the `consul` domain to Consul. + +```shell-session +# resolvectl domain +Global: ~consul +Link 2 (eth0): +``` + +Verify that `systemd-resolved` is able to resolve the Consul server address. + +```shell-session +# resolvectl query consul.service.consul +consul.service.consul: 127.0.0.1 + +-- Information acquired via protocol DNS in 6.6ms. +-- Data is authenticated: no +``` + +Confirm that `/etc/resolv.conf` points to the `stub-resolv.conf` file managed by `systemd-resolved`. + +```shell-session +$ ls -l /etc/resolv.conf +lrwxrwxrwx 1 root root 37 Jul 14 10:10 /etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf +``` + +Confirm that the IP address for `systemd-resolved`'s stub resolver is the configured `nameserver`. + + + +```shell-session +$ cat /etc/resolv.conf +## This file is managed by man:systemd-resolved(8). Do not edit. +## +## This is a dynamic resolv.conf file for connecting local clients to the +## internal DNS stub resolver of systemd-resolved. This file lists all +## configured search domains. +## +## Run "resolvectl status" to see details about the uplink DNS servers +## currently in use. +## +## Third party programs must not access this file directly, but only through the +## symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way, +## replace this symlink by a static file or a different symlink. +## +## See man:systemd-resolved.service(8) for details about the supported modes of +## operation for /etc/resolv.conf. + +nameserver 127.0.0.53 +options edns0 +``` + + + +Ensure that the operating system can resolve DNS queries to the `.consul` domain. + +```shell-session +$ host consul.service.consul +consul.service.consul has address 127.0.0.1 +``` + +### Using any local resolver with systemd + +By default, the local resolver stub in the `resolved.conf` file is configured to listen for UDP and TCP requests at `127.0.0.53:53`. However, you can set the `DNSStubListener` option to `false` so that your system can use any DNS configuration, as long as it loads earlier than `resolved`. + + + +```plaintext +DNSStubListener=false +``` + + + +## Dnsmasq + +Use [dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html) if you have a small network and need a lightweight DNS solution. + + + +If your distribution uses systemd, disable `systemd-resolved` before you follow these steps. + + + +Configure the `dnsmasq.conf` file or a series of files in the `/etc/dnsmasq.d` directory. Add server settings to your configuration file so that requests for the `consul` domain are forwarded to Consul DNS. + + + +```plaintext +# Enable forward lookup of the 'consul' domain: +server=/consul/127.0.0.1#8600 + +# Uncomment and modify as appropriate to enable reverse DNS lookups for +# common netblocks found in RFC 1918, 5735, and 6598: +#rev-server=0.0.0.0/8,127.0.0.1#8600 +#rev-server=10.0.0.0/8,127.0.0.1#8600 +#rev-server=100.64.0.0/10,127.0.0.1#8600 +#rev-server=127.0.0.1/8,127.0.0.1#8600 +#rev-server=169.254.0.0/16,127.0.0.1#8600 +#rev-server=172.16.0.0/12,127.0.0.1#8600 +#rev-server=192.168.0.0/16,127.0.0.1#8600 +#rev-server=224.0.0.0/4,127.0.0.1#8600 +#rev-server=240.0.0.0/4,127.0.0.1#8600 +# Accept DNS queries only from hosts whose address is on a local subnet. +#local-service +# Don't poll /etc/resolv.conf for changes. +#no-poll +# Don't read /etc/resolv.conf. Get upstream servers only from the command +# line or the dnsmasq configuration file (see the "server" directive below). +#no-resolv +# Specify IP address(es) of other DNS servers for queries not handled +# directly by consul. There is normally one 'server' entry set for every +# 'nameserver' parameter found in '/etc/resolv.conf'. See dnsmasq(8)'s +# 'server' configuration option for details. +#server=1.2.3.4 +#server=208.67.222.222 +#server=8.8.8.8 +# Set the size of dnsmasq's cache. The default is 150 names. Setting the +# cache size to zero disables caching. +#cache-size=65536 +``` + + + +Restart the `dnsmasq` service after creating the configuration. + +Refer to [`dnsmasq(8)`](http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html) for additional configuration settings such as specifying IP addresses for queries not handled directly by Consul. + + +## BIND + +[BIND](https://www.isc.org/bind/) is a robust DNS system. Its most prominent component, `named`, performs both of the main DNS server roles, acts as an authoritative name server for DNS zones, and is a recursive resolver in the network. + + + +If your distribution uses systemd, disable `systemd-resolved` before you follow these steps. + + + +To configure the BIND service to send `.consul` domain queries to Consul: + +1. Create a `named` configuration file with `DNSSEC` disabled. +1. Create a zone configuration file to manage the `.consul` domain. + +### Named configuration file + +Edit the `/etc/named.conf` to configure your BIND instance. Remember to disable `DNSSEC` so that Consul and BIND can communicate. Add an `include` section to include the zone file that you create in the next step. + +The following example shows a BIND configuration with `DNSSEC` disabled. + + + +```plaintext +options { + listen-on port 53 { 127.0.0.1; }; + listen-on-v6 port 53 { ::1; }; + directory "/var/named"; + dump-file "/var/named/data/cache_dump.db"; + statistics-file "/var/named/data/named_stats.txt"; + memstatistics-file "/var/named/data/named_mem_stats.txt"; + allow-query { localhost; }; + recursion yes; + + dnssec-enable no; + dnssec-validation no; + + /* Path to ISC DLV key */ + bindkeys-file "/etc/named.iscdlv.key"; + + managed-keys-directory "/var/named/dynamic"; +}; + +include "/etc/named/consul.conf"; +``` + + + +### Zone configuration file + +Set up a zone for your Consul-managed records in `consul.conf`. + + + +```dns-zone-file +zone "consul" IN { + type forward; + forward only; + forwarders { 127.0.0.1 port 8600; }; +}; +``` + + + +## Unbound + +Use [Unbound](https://www.unbound.net/) when you need a fast and lean DNS resolver for Linux and macOS. + + + +If your distribution uses systemd, disable `systemd-resolved` before you follow these steps. + + + + +The following example demonstrates a configuration for the `consul.conf` file in the `/etc/unbound/unbound.conf.d` directory. + +Add `server` and `stub-zone` settings to your Unbound configuration file. + + + +```plaintext +#Allow insecure queries to local resolvers +server: + do-not-query-localhost: no + domain-insecure: "consul" + +#Add consul as a stub-zone +stub-zone: + name: "consul" + stub-addr: 127.0.0.1@8600 +``` + + + +You may have to add the following line to the bottom of your `/etc/unbound/unbound.conf` file for the new configuration to be included. + + + +```plaintext +include: "/etc/unbound/unbound.conf.d/*.conf" +``` + + + +## iptables + +[iptables](https://www.netfilter.org/projects/iptables/index.html) is a generic firewalling software that allows you to define traffic rules for your system. + +If you do not have a local DNS server on the Consul agent node, use `iptables` to forward DNS requests on port `53` to the Consul agent running on the same machine without using a secondary service. + +This configuration realizes full DNS forwarding, which means that all DNS queries for the host are forwarded to Consul, not just the ones for the `.consul` top level domain. Consul's default configuration resolves only the `.consul` top level domain, so you must set the [`recursors`](/consul/docs/agent/config/config-files#recursors) flag if you want your node to be able to resolve other domains when using `iptables` configuration. + +If you use DNS relay hosts in your network, do not place them on the same host as Consul. The redirects may intercept the traffic. + +### Configure Consul recursors + +Add recursors to your Consul configuration. + + + +```hcl +# DNS recursors +recursors = [ "1.1.1.1" ] +``` + + + +Recursors should not include the `localhost` address because the `iptables` redirects would intercept the requests. + +You can replace the `1.1.1.1` address in the example with another DNS server address. This is suitable for situations where an external DNS +service is already running in your infrastructure and is used as the recursor. + +### Create iptables rules + +After you configure Consul to use a valid recursor, add rules to `iptables` to redirect traffic from port `53` to port `8600`. + +```shell-session +# iptables -t nat -A PREROUTING -p udp -m udp --dport 53 -j REDIRECT --to-ports 8600 \ + iptables -t nat -A PREROUTING -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 8600 \ + iptables -t nat -A OUTPUT -d localhost -p udp -m udp --dport 53 -j REDIRECT --to-ports 8600 \ + iptables -t nat -A OUTPUT -d localhost -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 8600 +``` + +## macOS + +On macOS systems, use the macOS system resolver to point all `.consul` requests to Consul. +The `man 5 resolver` command describes this feature in more detail. + +The following instructions require `sudo` or root access. + +To configure the macOS system resolver to forward DNS queries to Consul, add a resolver entry in the `/etc/resolver/` directory that points at the Consul agent. + +If you do not have this folder, create it. + +```shell-session +# mkdir -p /etc/resolver +``` + +Create a new file `/etc/resolver/consul` with `nameserver` and `port` entries. + + + +```plaintext +nameserver 127.0.0.1 +port 8600 +``` + + + +The configuration informs the macOS resolver daemon to forward all `.consul` TLD requests to `127.0.0.1` on port `8600`. + +## Next steps + +This instructions on this page helped you configure your node to forward DNS requests to Consul. + +To learn more on how to query Consul DNS once forwarding is enabled, refer to [DNS forwarding workflow](/consul/docs/services/discovery/dns-forwarding#workflow). + +For more information on other DNS features and configurations available in Consul, refer to [DNS usage overview](/consul/docs/services/discovery/dns-overview). diff --git a/website/content/docs/services/discovery/dns-forwarding/index.mdx b/website/content/docs/services/discovery/dns-forwarding/index.mdx new file mode 100644 index 000000000000..d47638bdfac7 --- /dev/null +++ b/website/content/docs/services/discovery/dns-forwarding/index.mdx @@ -0,0 +1,187 @@ +--- +layout: docs +page_title: DNS forwarding +description: -> + Learn how to configure your local DNS servers to perform DNS forwarding to Consul servers. +--- + +# DNS forwarding + +This topic describes the process to configure different DNS servers to enable DNS forwarding to Consul servers. + +You can apply these operations on every node where a Consul agent is running. + +## Introduction + +You deployed a Consul datacenter and want to use Consul DNS interface for name resolution. + +When configured with default values, Consul exposes the DNS interface on port `8600`. By default, DNS is served from port `53`. On most operating systems, this requires elevated privileges. It is also common, for most operating systems, to have a local DNS server already running on port `53`. + +Instead of running Consul with an administrative or root account, you can forward appropriate queries to Consul, running on an unprivileged port, from another DNS server or using port redirect. + +There are two configurations for a node's DNS forwarding behavior: + + - **Conditional DNS forwarding**: the local DNS servers are configured to forward to Consul only queries relative to the `.consul` zone. All other queries are still served via the default DNS server in the node. + - **Full DNS forwarding**: Consul serves all DNS queries and forwards to a remote DNS server the ones outside `.consul` domain. + +### Conditional DNS forwarding + +We recommend the conditional DNS forwarding approach. This configuration lowers the Consul agent's resource consumption by limiting the number of DNS requests it handles. + +![Consul DNS conditional forwarding - Only .consul requests are routed to Consul](/img/consul-dns-conditional-forwarding.png#light-theme-only) +![Consul DNS conditional forwarding - Only .consul requests are routed to Consul](/img/consul-dns-conditional-forwarding-dark.png#dark-theme-only) + +In this configuration, Consul only serves queries relative to the `.consul` domain. There is no unnecessary load on Consul servers to serve queries from different domains. + +This behavior is not enabled by default. + +### Full DNS forwarding + +This approach can be useful in scenarios where the Consul agent's node is allocated limited resources and you want to avoid the overhead of running a local DNS server. In this configuration, Consul serves all DNS queries for all domains and forwards the ones outside the `.consul` domain to one or more configured forwarder servers. + +![Consul DNS forwarding - All requests are routed to Consul](/img/consul-dns-forwarding.png#light-theme-only) +![Consul DNS forwarding - All requests are routed to Consul](/img/consul-dns-forwarding-dark.png#dark-theme-only) + +This behavior is not enabled by default. Consul standard configuration only resolves DNS records inside the `.consul` zone. To enable DNS forwarding, you need to set the [recursors](/consul/docs/agent/config/config-files#recursors) option in your Consul configuration. + +In this scenario, if a Consul DNS reply includes a `CNAME` record pointing outside the `.consul` top level domain, then the DNS reply only includes `CNAME` records by default. + +When `recursors` is set and the upstream resolver is functioning correctly, Consul tries to resolve CNAMEs and include any records (for example, A, AAAA, PTR) for them in its DNS reply. In these scenarios, Consul is used for full DNS forwarding and is able to serve queries for all domains. + +## Workflow + +To use DNS forwarding in Consul deployments, complete the following steps: + +1. Configure the local DNS service to enable DNS forwarding to Consul. Follow the instructions for one of the following services: + + - [systemd-resolved](/consul/docs/services/discovery/dns-forwarding/enable#systemd-resolved) + - [BIND](/consul/docs/services/discovery/dns-forwarding/enable#bind) + - [Dnsmasq](/consul/docs/services/discovery/dns-forwarding/enable#dnsmasq) + - [Unbound](/consul/docs/services/discovery/dns-forwarding/enable#unbound) + - [iptables](/consul/docs/services/discovery/dns-forwarding/enable#iptables) + - [macOS system resolver](/consul/docs/services/discovery/dns-forwarding/enable#macOS) + +1. Query the Consul DNS to confirm that DNS forwarding functions correctly. + + ```shell-session + $ dig consul.service.consul A + + ; <<>> DiG 9.16.48-Debian <<>> consul.service.consul A + ;; global options: +cmd + ;; Got answer: + ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 51736 + ;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1 + + ;; OPT PSEUDOSECTION: + ; EDNS: version: 0, flags:; udp: 65494 + ;; QUESTION SECTION: + ;consul.service.consul. IN A + + ;; ANSWER SECTION: + consul.service.consul. 0 IN A 10.0.4.140 + consul.service.consul. 0 IN A 10.0.4.121 + consul.service.consul. 0 IN A 10.0.4.9 + + ;; Query time: 4 msec + ;; SERVER: 127.0.0.53#53(127.0.0.53) + ;; WHEN: Wed Jun 26 20:47:05 UTC 2024 + ;; MSG SIZE rcvd: 98 + + ``` + +1. Optionally, verify reverse DNS. + + ```shell-session + $ dig 140.4.0.10.in-addr.arpa. PTR + + ; <<>> DiG 9.16.48-Debian <<>> 140.4.0.10.in-addr.arpa. PTR + ;; global options: +cmd + ;; Got answer: + ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35085 + ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 + + ;; OPT PSEUDOSECTION: + ; EDNS: version: 0, flags:; udp: 65494 + ;; QUESTION SECTION: + ;140.4.0.10.in-addr.arpa. IN PTR + + ;; ANSWER SECTION: + 140.4.0.10.in-addr.arpa. 0 IN PTR consul-server-0.node.dc1.consul. + + ;; Query time: 0 msec + ;; SERVER: 127.0.0.53#53(127.0.0.53) + ;; WHEN: Wed Jun 26 20:47:57 UTC 2024 + ;; MSG SIZE rcvd: 97 + + ``` + + You can use the `short` option for `dig` to only get the node name instead of the full output. + + ```shell-session + $ dig +short -x 10.0.4.140 + consul-server-0.node.dc1.consul. + ``` + +## Troubleshooting + +If your DNS server does not respond but you do get an answer from Consul, turn on your DNS server's query log to check for errors. + +### systemd-resolved + +Enable query logging for `systemd-resolved`: + +```shell-session +# resolvectl log-level debug +``` + +Check query log: + +```shell-session +# journalctl -r -u systemd-resolved +``` + +Disable query logging: + +```shell-session +# resolvectl log-level info +``` + +DNS forwarding may fail if you use the default `systemd-resolved` configuration and attempt to bind to `0.0.0.0`. The default configuration uses a DNS stub that listens for UDP and TCP requests at `127.0.0.53`. As a result, attempting to bind to `127.0.0.53` conflicts with the running stub. You can disable the stub as described in the [Using any local resolver with systemd](/consul/docs/services/discovery/dns-forwarding/enable#using-any-local-resolver-with-systemd) section to troubleshoot this problem. + +### Dnsmasq + +To enable query log refer to [Dnsmasq documentation](https://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html). + +In particular, look for the `log-queries` and `log-facility` configuration option. + +When query log is enabled, it is possible to force Dnsmasq to emit a full cache dump using the `SIGUSR1` signal. + +### BIND + +Enable query log: + +```shell-session +$ rndc querylog +``` + +Check logs: + +```shell-session +$ tail -f /var/log/messages +``` + +The log may show errors like this: + + + +```plaintext +error (no valid RRSIG) resolving +error (no valid DS) resolving +``` + + + +This error indicates that `DNSSEC` is not disabled properly. + +If you receive errors about network connections, verify that there are no firewall +or routing problems between the servers running BIND and Consul. diff --git a/website/content/docs/services/discovery/dns-overview.mdx b/website/content/docs/services/discovery/dns-overview.mdx index 34e92e5fe8a2..d961cc884d8f 100644 --- a/website/content/docs/services/discovery/dns-overview.mdx +++ b/website/content/docs/services/discovery/dns-overview.mdx @@ -10,6 +10,7 @@ description: >- This topic provides overview information about how to look up Consul nodes and services using the Consul DNS. ## Consul DNS + The Consul DNS is the primary interface for discovering services registered in the Consul catalog. The DNS enables you to look up services and nodes registered with Consul using terminal commands instead of making HTTP API requests to Consul. We recommend using the DNS for service discovery in virtual machine (VM) environments because it removes the need to modify native applications so that they can consume the Consul service discovery APIs. @@ -17,20 +18,37 @@ We recommend using the DNS for service discovery in virtual machine (VM) environ The DNS has several default configurations, but you can customize how the server processes lookups. Refer to [Configure DNS Behaviors](/consul/docs/services/discovery/dns-configuration) for additional information. ### DNS versus native app integration + You can use DNS to reach services registered with Consul or modify your application to natively consume the Consul service discovery HTTP APIs. We recommend using the DNS because it is less invasive. You do not have to modify your application with Consul to retrieve the service’s connection information. Instead, you can use a DNS fully qualified domain (FQDN) that conforms to Consul's lookup format to retrieve the relevant information. -Refer to [ Native App Integration](/consul/docs/connect/native) and its [Go package](/consul/docs/connect/native/go) for additional information. +Refer to [Native App Integration](/consul/docs/connect/native) and its [Go package](/consul/docs/connect/native/go) for additional information. ### DNS versus upstreams + If you are using Consul for service discovery and have not enabled service mesh features, then use the DNS to discover services and nodes in the Consul catalog. If you are using Consul for service mesh on VMs, you can use upstreams or DNS. We recommend using upstreams because you can query services and nodes without modifying the application code or environment variables. Refer to [Upstream Configuration Reference](/consul/docs/connect/proxies/proxy-config-reference#upstream-configuration-reference) for additional information. If you are using Consul on Kubernetes, refer to [the upstreams annotation documentation](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-connect-service-upstreams) for additional information. +## Consul DNS on Kubernetes + +Consul on Kubernetes supports approaches to using the Consul DNS in Kubernetes clusters. + +For service discovery operations, refer to [Consul DNS views on Kubernetes](/consul/docs/k8s/dns/views). + +For service mesh operations, refer to [Resolve Consul DNS requests in Kubernetes](/consul/docs/k8s/dns/enable). + +## DNS forwarding + +You can configure your local DNS servers to use Consul. + +Refer to [DNS Forwarding](/consul/docs/services/discovery/dns-forwarding) for additional information. + ## Static queries + Node lookups and service lookups are the fundamental types of static queries. Depending on your use case, you may need to use different query methods and syntaxes to query the DNS for services and nodes. Consul relies on a very specific format for queries to resolve names. Note that all queries are case-sensitive. @@ -38,4 +56,5 @@ Consul relies on a very specific format for queries to resolve names. Note that Refer to [Perform Static DNS Lookups](/consul/docs/services/discovery/dns-static-lookups) for details about how to perform node and service lookups. ## Prepared queries + Prepared queries are configurations that enable you to register complex DNS queries. They provide lookup features that extend Consul's service discovery capabilities, such as filtering by multiple tags and automatically querying remote datacenters for services if no healthy nodes are available in the local datacenter. You can also create prepared query templates that match names using a prefix match, allowing a single template to apply to potentially many services. Refer to [Enable Dynamic DNS Queries](/consul/docs/services/discovery/dns-dynamic-lookups) for additional information. diff --git a/website/content/docs/services/discovery/dns-static-lookups.mdx b/website/content/docs/services/discovery/dns-static-lookups.mdx index 56e9ccc02e64..74807c756adc 100644 --- a/website/content/docs/services/discovery/dns-static-lookups.mdx +++ b/website/content/docs/services/discovery/dns-static-lookups.mdx @@ -109,7 +109,9 @@ The `datacenter` subdomain is optional. By default, Consul interrogates the quer The `cluster-peer` name is optional, and specifies the [cluster peer](/consul/docs/connect/cluster-peering) whose [exported services](/consul/docs/connect/config-entries/exported-services) should be the target of the query. -The `sameness-group` name is optional, and specifies the [sameness group](/consul/docs/connect/cluster-peering/usage/create-sameness-groups) that should be the target of the query. When Consul receives a DNS request for a service that is tied to a sameness group, it returns service instances from the first healthy member of the sameness group. If the local partition is a member of a sameness group, its service instances take precedence over the members of its sameness group. Optionally, you can include a namespace or admin partition when performing a lookup on a sameness group. Refer to [Service lookups for Consul Enterprise](#service-lookups-for-consul-enterprise) for more information. +The `sameness-group` name is optional, and specifies the [sameness group](/consul/docs/connect/cluster-peering/usage/create-sameness-groups) that should be the target of the query. When Consul receives a DNS request for a service that is a member of a sameness group and the sameness groups is configured with `DefaultForFailover` set to `true`, it returns service instances from the first healthy member of the sameness group. If the local partition is a member of a sameness group, local service instances take precedence over the members of its sameness group. Optionally, you can include a namespace or admin partition when performing a lookup on a sameness group. + +Only sameness groups with `DefaultForFailover` set `true` can be queried through DNS. If `DefaultForFailover` is not true, then Consul DNS returns an error response. Refer to [Service lookups for Consul Enterprise](#service-lookups-for-consul-enterprise) for more information. By default, the lookups query in the `consul` domain. Refer to [Configure DNS Behaviors](/consul/docs/services/discovery/dns-configuration) for information about using alternate domains. diff --git a/website/content/docs/services/usage/register-services-checks.mdx b/website/content/docs/services/usage/register-services-checks.mdx index 07a3f20ad9c0..3cfe03c852eb 100644 --- a/website/content/docs/services/usage/register-services-checks.mdx +++ b/website/content/docs/services/usage/register-services-checks.mdx @@ -2,25 +2,25 @@ layout: docs page_title: Register services and health checks description: -> - Learn how to register services and health checks with Consul agents. + Learn how to register services and health checks with Consul agents. --- # Register services and health checks -This topic describes how to register services and health checks with Consul in networks running on virtual machines (VM). Refer to [Define Services](/consul/docs/services/usage/define-services) and [Define Health Checks](/consul/docs/services/usage/checks) for information about how to define services and health checks. +This topic describes how to register services and health checks with Consul in networks running on virtual machines (VM). Refer to [Define Services](/consul/docs/services/usage/define-services) and [Define Health Checks](/consul/docs/services/usage/checks) for information about how to define services and health checks. ## Overview Register services and health checks in VM environments by providing the service definition to a Consul agent. You can use several different methods to register services and health checks. - Start a Consul agent and pass the service definition in the [agent's configuration directory](/consul/docs/agent#configuring-consul-agents). - Reload the a running Consul agent and pass the service definition in the [agent's configuration directory](/consul/docs/agent#configuring-consul-agents). Use this method when implementing changes to an existing service or health check definition. -- Use the [`consul services register` command](/consul/commands/services/register) to register new service and health checks with a running Consul agent. -- Call the [`/agent/service/register`](/consul/api-docs/agent/service#register-service) HTTP API endpoint to to register new service and health checks with a running Consul agent. +- Use the [`consul services register` command](/consul/commands/services/register) to register new service and health checks with a running Consul agent. +- Call the [`/agent/service/register`](/consul/api-docs/agent/service#register-service) HTTP API endpoint to register new service and health checks with a running Consul agent. - Call the [`/agent/check/register`](/consul/api-docs/agent/check#register-check) HTTP API endpoint to register a health check independent from the service. -When a service is registered using the HTTP API endpoint or CLI command, the checks persist in the Consul data folder. If the agent restarts, Consul uses the service and check configurations in the configuration directory to start the services. +When a service is registered using the HTTP API endpoint or CLI command, the checks persist in the Consul data folder. If the agent restarts, Consul uses the service and check configurations in the configuration directory to start the services. -Note that health checks associated with a service are application-level checks. +Note that health checks associated with a service are application-level checks. ## Start an agent We recommend registering services on startup because the service persists if the agent fails. Specify the directory containing the service definition with the `-config-dir` option on startup. When the Consul agent starts, it processes all configurations in the directory and registers any services contained in the configurations. In the following example, the Consul agent starts and loads the configurations contained in the `configs` directory: @@ -48,7 +48,7 @@ Refer to [Consul Agent Service Registration](/consul/commands/services/register) Use the following methods to register services and health checks using the HTTP API. ### Register services -Send a `PUT` request to the `/agent/service/register` API endpoint to dynamically register a service and its associated health checks. To register health checks independently, [call the checks API endpoint](#call-the-checks-http-api-endpoint). +Send a `PUT` request to the `/agent/service/register` API endpoint to dynamically register a service and its associated health checks. To register health checks independently, [call the checks API endpoint](#call-the-checks-http-api-endpoint). The following example request registers the service defined in the `service.json` file. diff --git a/website/content/docs/troubleshoot/faq.mdx b/website/content/docs/troubleshoot/faq.mdx index c57ad30232ab..5e733f1cd1af 100644 --- a/website/content/docs/troubleshoot/faq.mdx +++ b/website/content/docs/troubleshoot/faq.mdx @@ -69,7 +69,7 @@ and [`disable_update_check`](/consul/docs/agent/config/config-files#disable_upda ### Q: Does Consul rely on UDP Broadcast or Multicast? -Consul uses the [Serf](https://www.serf.io) gossip protocol which relies on +Consul uses the [Serf](https://github.com/hashicorp/serf/) gossip protocol which relies on TCP and UDP unicast. Broadcast and Multicast are rarely available in a multi-tenant or cloud network environment. For that reason, Consul and Serf were both designed to avoid any dependence on those capabilities. diff --git a/website/content/docs/upgrading/index.mdx b/website/content/docs/upgrading/index.mdx index 4b3ecad8d848..50ef68deda58 100644 --- a/website/content/docs/upgrading/index.mdx +++ b/website/content/docs/upgrading/index.mdx @@ -56,15 +56,40 @@ Consul is A, and version B is released. by running `consul members` to make sure all members have the latest build and highest protocol version. +## Upgrade recommendation + +We encourage organizations to use a maintained version of Consul +so that they benefit from bug and security fixes in minor releases. + +### Consul community edition + +For Consul community edition users, +consistently operating a maintained version requires upgrading +every 4 months to the latest major release. + +### Consul Enterprise + +Standard major releases of Consul Enterprise are maintained for approximately 1 year. +[Consul Enterprise Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) +releases are maintained for approximately 2 years. + +For Consul Enterprise customers, +consistently operating a maintained version requires a major upgrade every 12 months +on average when using [LTS](/consul/docs/enterprise/long-term-support) releases. +LTS releases support an upgrade jump of at most 3 major versions. +For more details, refer to +[Long Term Support upgrade recommendation](/consul/docs/enterprise/long-term-support#annual-upgrade-to-next-lts-release). + ## Large Version Jumps -Operating a Consul datacenter that is multiple major versions behind the current major -version can increase the risk incurred during upgrades. We encourage our users to -remain no more than two major versions behind (i.e., if 1.8.x is the current release, -do not use versions older than 1.6.x). If you find yourself in a situation where you -are many major versions behind, and need to upgrade, please review our -[Upgrade Instructions page](/consul/docs/upgrading/instructions) for information on -how to perform those upgrades. +If your Consul deployment is many major versions behind the latest release +and you need to upgrade, review our +[upgrade instructions](/consul/docs/upgrading/instructions) +for more information about how to perform those upgrades. + +After upgrading to a maintained version of Consul, refer to our +[upgrade recommendation](#upgrade-recommendation) +to inform planning for future upgrades. ## Backward Incompatible Upgrades diff --git a/website/content/docs/upgrading/instructions/general-process.mdx b/website/content/docs/upgrading/instructions/general-process.mdx index 70fb45b42f53..6606c2d881d8 100644 --- a/website/content/docs/upgrading/instructions/general-process.mdx +++ b/website/content/docs/upgrading/instructions/general-process.mdx @@ -8,9 +8,7 @@ description: >- # General Upgrade Process -## Introduction - -This document describes some best practices that you should follow when +This pages describes the overall process and best practices that you should follow when upgrading Consul. Some versions also have steps that are specific to that version, so make sure you also review the [upgrade instructions](/consul/docs/upgrading/instructions) for the version you are on. @@ -46,117 +44,124 @@ If you are using Kubernetes, then please review our documentation for ## Prepare for the Upgrade -**1.** Take a snapshot: +1. Take a snapshot to ensure you have a safe fallback option in case something goes wrong. -``` -consul snapshot save backup.snap -``` + ```shell-session + $ consul snapshot save backup.snap + ``` -You can inspect the snapshot to ensure if was successful with: + You can inspect the snapshot to ensure your cluster's Raft index was successfully captured. -``` -consul snapshot inspect backup.snap -``` + ```shell-session + $ consul snapshot inspect backup.snap + ``` -Example output: + Example output: -``` -ID 2-1182-1542056499724 -Size 4115 -Index 1182 -Term 2 -Version 1 -``` + ```shell-session hideClipboard + ID 2-1182-1542056499724 + Size 4115 + Index 1182 + Term 2 + Version 1 + ``` -This will ensure you have a safe fallback option in case something goes wrong. Store -this snapshot somewhere safe. More documentation on snapshot usage is available here: + Store this snapshot somewhere safe. For more information on snapshots, refer to the following: -- [consul.io/commands/snapshot](/consul/commands/snapshot) -- [Backup Consul Data and State tutorial](/consul/tutorials/production-deploy/backup-and-restore) + - [`consul snapshot` CLI command](/consul/commands/snapshot) + - [Backup Consul Data and State tutorial](/consul/tutorials/production-deploy/backup-and-restore) -**2.** Temporarily modify your Consul configuration so that its [log_level](/consul/docs/agent/config/cli-flags#_log_level) -is set to `debug`. After doing this, issue the following command on your servers to +2. Temporarily modify your Consul configuration to set the agent's [`log_level`](/consul/docs/agent/config/cli-flags#_log_level) is set to `debug`. Then issue the following command on your servers to reload the configuration: -``` -consul reload +```shell-session +$ consul reload ``` -This change will give you more information to work with in the event something goes wrong. +When you change the cluster's log level, Consul gives you more information to work with in the event that something goes wrong. -## Perform the Upgrade +### Enterprise upgrades -**1.** Issue the following command to discover which server is currently the leader: + +To experience a smoother upgrade process on Consul Enterprise, we recommend that you disable the upgrade migration feature. + -``` -consul operator raft list-peers -``` +Consul Enterprise supports [automated upgrades](/consul/docs/enterprise/upgrades), but the autopilot feature may cause a node running an updated Consul version to elect a new leader before the version is updated on the existing cluster leader. -You should receive output similar to this (exact formatting and content may differ based on version): +If your datacenter runs Consul Enterprise, update your server agent configuration file to disable autopilot's upgrade migration or run the following CLI command: -``` -Node ID Address State Voter RaftProtocol -dc1-node1 ae15858f-7f5f-4dcb-b7d5-710fdcdd2745 10.11.0.2:8300 leader true 3 -dc1-node2 20e6be1b-f1cb-4aab-929f-f7d2d43d9a96 10.11.0.3:8300 follower true 3 -dc1-node3 658c343b-8769-431f-a71a-236f9dbb17b3 10.11.0.4:8300 follower true 3 +```shell-session +$ consul operator autopilot set-config -disable-upgrade-migration=true ``` -Take note of which agent is the leader. +## Perform the Upgrade -**2.** Copy the new `consul` binary onto your servers and replace the existing -binary with the new one. +1. Issue the following command to discover which server is currently the leader: -**3.** The following steps must be done in order on the server agents, leaving the leader -agent for last. First, use a service management system (e.g., systemd, upstart, etc.) to restart the Consul service. If -you are not using a service management system, you must restart the agent manually. + ```shell-session + $ consul operator raft list-peers + ``` -To validate that the agent has rejoined the cluster and is in sync with the leader, issue the -following command: + You should receive output similar to this (exact formatting and content may differ based on version): -``` -consul info -``` + ```shell-session hideClipboard + Node ID Address State Voter RaftProtocol + dc1-node1 ae15858f-7f5f-4dcb-b7d5-710fdcdd2745 10.11.0.2:8300 leader true 3 + dc1-node2 20e6be1b-f1cb-4aab-929f-f7d2d43d9a96 10.11.0.3:8300 follower true 3 + dc1-node3 658c343b-8769-431f-a71a-236f9dbb17b3 10.11.0.4:8300 follower true 3 + ``` -Check whether the `commit_index` and `last_log_index` fields have the same value. If done properly, -this should avoid an unexpected leadership election due to loss of quorum. + Take note of which agent is the leader. -**4.** Double-check that all servers are showing up in the cluster as expected and are on -the correct version by issuing: +2. Copy the new `consul` binary onto your servers and replace the existing binary with the new one. -``` -consul members -``` +3. Use a service management system such as systemd or upstart to restart the Consul service on each server. You must restart follower server agents first, leaving the leader agent for last. If you are not using a service management system, you must restart the agent manually. -You should receive output similar to this: + To validate that the agent has rejoined the cluster and is in sync with the leader after you restart it, issue the following command to the agent: -``` -Node Address Status Type Build Protocol DC -dc1-node1 10.11.0.2:8301 alive server 1.8.3 2 dc1 -dc1-node2 10.11.0.3:8301 alive server 1.8.3 2 dc1 -dc1-node3 10.11.0.4:8301 alive server 1.8.3 2 dc1 -``` + ```shell-session + $ consul info + ``` -Also double-check the raft state to make sure there is a leader and sufficient voters: + Check whether the `commit_index` and `last_log_index` fields have the same value. If done properly, + this should avoid an unexpected leadership election due to loss of quorum. -``` -consul operator raft list-peers -``` +4. Double-check that all servers joined the cluster as expected and run the correct version. Issue the following command: -You should receive output similar to this: + ```shell-session + $ consul members + ``` -``` -Node ID Address State Voter RaftProtocol -dc1-node1 ae15858f-7f5f-4dcb-b7d5-710fdcdd2745 10.11.0.2:8300 leader true 3 -dc1-node2 20e6be1b-f1cb-4aab-929f-f7d2d43d9a96 10.11.0.3:8300 follower true 3 -dc1-node3 658c343b-8769-431f-a71a-236f9dbb17b3 10.11.0.4:8300 follower true 3 -``` + You should receive output that lists the servers as `alive` and running the same updated Consul version. -**5.** Set your `log_level` back to its original value and issue the following command + ```shell-session hideClipboard + Node Address Status Type Build Protocol DC + dc1-node1 10.11.0.2:8301 alive server 1.8.3 2 dc1 + dc1-node2 10.11.0.3:8301 alive server 1.8.3 2 dc1 + dc1-node3 10.11.0.4:8301 alive server 1.8.3 2 dc1 + ``` + + Also double-check the Raft state to make sure there is a leader and sufficient voters: + + ```shell-session + $ consul operator raft list-peers + ``` + + You should receive output that lists one server as the `leader` and the rest as `follower`: + + ```shell-session hideClipboard + Node ID Address State Voter RaftProtocol + dc1-node1 ae15858f-7f5f-4dcb-b7d5-710fdcdd2745 10.11.0.2:8300 leader true 3 + dc1-node2 20e6be1b-f1cb-4aab-929f-f7d2d43d9a96 10.11.0.3:8300 follower true 3 + dc1-node3 658c343b-8769-431f-a71a-236f9dbb17b3 10.11.0.4:8300 follower true 3 + ``` + +5. Set your `log_level` back to its original value and issue the following command on your servers to reload the configuration: -``` -consul reload -``` + ```shell-session + $ consul reload + ``` ## Troubleshooting @@ -164,7 +169,7 @@ Most problems with upgrading occur due to either failing to upgrade the leader a or failing to wait for a follower agent to fully rejoin a cluster before moving on to another server. This can cause a loss of quorum and occasionally can result in all of your servers attempting to kick off leadership elections endlessly without ever -reaching a quorum and electing a leader. +reaching a quorum and electing a leader. Consul Enterprise users should [disable upgrade migration](#enterprise-upgrades) to prevent autopilot from prematurely electing a new cluster leader. Most of these problems can be solved by following the steps outlined in our [Disaster recovery for Consul clusters](/consul/tutorials/datacenter-operations/recovery-outage) document. diff --git a/website/content/docs/upgrading/instructions/index.mdx b/website/content/docs/upgrading/instructions/index.mdx index 1ea7effb7353..05a9ee761f80 100644 --- a/website/content/docs/upgrading/instructions/index.mdx +++ b/website/content/docs/upgrading/instructions/index.mdx @@ -6,13 +6,15 @@ description: >- process beyond the standard flow. --- -# Upgrade Instructions +# Upgrade instructions This document is intended to help users who find themselves many versions behind to upgrade safely. -## General Upgrade Path +## General upgrade path -Each upgrade should jump at most 2 major versions, except where +If you are not running a Consul Enterprise +[Long Term Support](/consul/docs/enterprise/long-term-support) +release, each upgrade should jump at most 2 major versions, except where [dedicated instructions](#dedicated-instructions-for-specific-upgrade-paths) are provided for a larger jump between specific versions. If your upgrade path has no applicable [dedicated instructions](#dedicated-instructions-for-specific-upgrade-paths), @@ -30,7 +32,14 @@ For example, to upgrade from Consul 1.12 to Consul 1.15: To plan, review the upgrade details for [1.15](/consul/docs/upgrading/upgrade-specific#consul-1-15-x). -## Dedicated Instructions for Specific Upgrade Paths +## Long Term Support releases + +Consul Enterprise [Long Term Support (LTS)](/consul/docs/enterprise/long-term-support) +releases allow jumping at most 3 major versions by upgrading from one LTS release to the next. +Review the [version-specific upgrade details](/consul/docs/upgrading/upgrade-specific) +to plan your upgrade, starting from the next major version and working upwards to your target version. + +## Dedicated instructions for specific upgrade paths The following table provides links to dedicated instructions for directly upgrading from a version in the starting range diff --git a/website/content/docs/upgrading/upgrade-specific.mdx b/website/content/docs/upgrading/upgrade-specific.mdx index 19b2e2ab1474..4ff5eb8c3036 100644 --- a/website/content/docs/upgrading/upgrade-specific.mdx +++ b/website/content/docs/upgrading/upgrade-specific.mdx @@ -14,7 +14,57 @@ provided for their upgrades as a result of new features or changed behavior. This page is used to document those details separately from the standard upgrade flow. +## Consul 1.20.x + +### Mesh traffic request path normalization enabled by default + +As of Consul v1.20.1, inbound traffic to mesh proxies will have Envoy request [path normalization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-normalize-path) applied by default. This should not interfere with the majority of service traffic, but can be disabled if needed by setting `http.incoming.request_normalization.insecure_disable_path_normalization` to `true` in the [global `mesh` configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization). This setting is generally safe to change if not using L7 intentions with path matching. + +## Consul v1.19.x + +### Health endpoint status filtering is now processed on the server side when using client agents +In previous versions of Consul, client agents responded to health queries by requesting all results from the Consul servers and then locally filtering out service nodes with a `critical` status. The client agent also processed the `?passing` parameter by filtering node results locally. This process was not resource efficient in large deployments because large numbers of services and health check results must propagate to many clients before Consul can return a healthy node. + +In this release, the Consul server is responsible for filtering services according to their health status before it sends the data to a client agent. When upgrading the version of Consul your deployment runs to this release, you must upgrade the Consul servers before you upgrade the client agents. We recommend this upgrade order to avoid a scenario where Consul returns results for an unhealthy service because the client agent no longer filters nodes but the servers do not yet understand the `?passing` query argument. + +### Metrics removal + +In previous versions, Consul emitted redundant state store usage metrics that contained two instances of `consul` in the metric name. As an example, config entry usage counts were emitted as both: + +- `consul.state.config_entries` +- `consul.consul.state.config_entries` + +As of Consul v1.19, Consul does not emit the redundant metric with the double `consul.consul` in its name. Any monitoring alerts and dashboards that you may have utilizing these metrics may require edits to update to the simplified metric name. + +### Legacy API Gateway Removal +The Consul Kubernetes Helm chart stanza +[`.apiGateway`](/consul/docs/v1.16.x/k8s/helm#apigateway-1) +is removed in Consul v1.19.0. If using that stanza, migrate to the +[`connectInject.apiGateway`](/consul/docs/k8s/helm#v-connectinject-apigateway) +stanza before upgrading to Consul v1.19 or later. + +The `.apiGateway` stanza is associated with the legacy API gateway that was +[deprecated in Consul v1.16.0](https://developer.hashicorp.com/consul/docs/release-notes/consul/v1_16_x#what-s-deprecated). +The Kubernetes-only legacy API gateway is superseded by the modern, multi-runtime +[API gateway](/consul/docs/connect/config-entries/api-gateway). +On Kubernetes, the modern API gateway is associated with the `connectInject.apiGateway` stanza. + +### Mesh traffic request path normalization enabled by default + +As of Consul v1.19.3, inbound traffic to mesh proxies will have Envoy request [path normalization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-normalize-path) applied by default. This should not interfere with the majority of service traffic, but can be disabled if needed by setting `http.incoming.request_normalization.insecure_disable_path_normalization` to `true` in the [global `mesh` configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization). This setting is generally safe to change if not using L7 intentions with path matching. + +## Consul 1.18.x + +### Mesh traffic request path normalization enabled by default + +As of Consul v1.18.5, inbound traffic to mesh proxies will have Envoy request [path normalization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-normalize-path) applied by default. This should not interfere with the majority of service traffic, but can be disabled if needed by setting `http.incoming.request_normalization.insecure_disable_path_normalization` to `true` in the [global `mesh` configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization). This setting is generally safe to change if not using L7 intentions with path matching. + ## Consul 1.17.x + +### Known issues + +Consul versions 1.17.2 and 1.16.5 perform excessively strict TLS SAN verification on terminating gateways, which prevents connections outside of the mesh to upstream services. Terminating gateway users are advised to avoid deploying these Consul versions. A fix will be present in a future release of Consul 1.17.3 and 1.16.6 [[GH-20360](https://github.com/hashicorp/consul/issues/20360)]. + #### Audit Log naming changes (Enterprise) Prior to Consul 1.17.0, audit logs contained timestamps on both the original log file names as well as rotated log file names. After Consul 1.17.0, only timestamps will be included in rotated log file names. @@ -34,6 +84,8 @@ service-defaults are configured in each partition and namespace before upgrading ### Known issues +Consul versions 1.17.2 and 1.16.5 perform excessively strict TLS SAN verification on terminating gateways, which prevents connections outside of the mesh to upstream services. Terminating gateway users are advised to avoid deploying these Consul versions. A fix will be present in a future release of Consul 1.17.3 and 1.16.6 [[GH-20360](https://github.com/hashicorp/consul/issues/20360)]. + Service mesh in Consul versions 1.16.0 and 1.16.1 may have issues when a snapshot restore is performed and the servers are hosting xDS streams. When this bug triggers, it causes Envoy to incorrectly populate upstream endpoints. To prevent this issue, service mesh users who run agent-less workloads should upgrade Consul to v1.16.2 or later. @@ -91,13 +143,13 @@ The `connect.enable_serverless_plugin` configuration option was removed. Lambda #### Deprecating authentication via token query parameter -Providing a Consul ACL token in API requests using the `token` query parameter is deprecated and will be removed in Consul 1.17. +Providing a Consul ACL token in API requests using the `token` query parameter is deprecated and will be removed in a future Consul version. Instead, you should provide the token through the `X-Consul-Token` header or with the Bearer scheme in the authorization header as described in the [API authentication documentation](/consul/api-docs/api-structure#authentication). Check whether you are using a `token` query parameter by searching your Consul agent logs for the message: ```shell-session hideClipboard -$ This request used the token query parameter which is deprecated and will be removed in Consul 1.17 +$ This request used the token query parameter which is deprecated and will be removed in a future Consul version ``` Deprecated authentication using the `token` query parameter: @@ -204,6 +256,10 @@ In Consul v1.15 and higher: +### Mesh traffic request path normalization enabled by default + +As of Consul v1.15.15, inbound traffic to mesh proxies will have Envoy request [path normalization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-field-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-normalize-path) applied by default. This should not interfere with the majority of service traffic, but can be disabled if needed by setting `http.incoming.request_normalization.insecure_disable_path_normalization` to `true` in the [global `mesh` configuration entry](/consul/docs/connect/config-entries/mesh#request-normalization). This setting is generally safe to change if not using L7 intentions with path matching. + ## Consul 1.14.x ### Service Mesh Compatibility diff --git a/website/content/partials/cli-http-api-partition-options.mdx b/website/content/partials/cli-http-api-partition-options.mdx new file mode 100644 index 000000000000..eb96310a37b9 --- /dev/null +++ b/website/content/partials/cli-http-api-partition-options.mdx @@ -0,0 +1 @@ +- `-partition=` - Specifies the admin partition to query. If not provided, the partition is inferred from the request's ACL token, or defaults to the `default` partition. diff --git a/website/content/partials/http-api-body-options-partition.mdx b/website/content/partials/http-api-body-options-partition.mdx new file mode 100644 index 000000000000..cf2acd813caf --- /dev/null +++ b/website/content/partials/http-api-body-options-partition.mdx @@ -0,0 +1,2 @@ + +- `Partition` `(string: "")` - The admin partition to use. If not provided, the partition is inferred from the request's ACL token, or defaults to the `default` partition. \ No newline at end of file diff --git a/website/content/partials/http-api-query-parms-partition.mdx b/website/content/partials/http-api-query-parms-partition.mdx new file mode 100644 index 000000000000..8d954d86c53c --- /dev/null +++ b/website/content/partials/http-api-query-parms-partition.mdx @@ -0,0 +1 @@ +- `partition` `(string: "")` - The admin partition to use. If not provided, the partition is inferred from the request's ACL token, or defaults to the `default` partition. \ No newline at end of file diff --git a/website/content/partials/http_api_partition_options.mdx b/website/content/partials/http_api_partition_options.mdx deleted file mode 100644 index a290c38201e5..000000000000 --- a/website/content/partials/http_api_partition_options.mdx +++ /dev/null @@ -1 +0,0 @@ -- `-partition=` - Specifies the partition to query. If not provided, the partition will be inferred from the request's ACL token, or will default to the `default` partition. Partitions are a Consul Enterprise feature added in v1.11.0. diff --git a/website/data/api-docs-nav-data.json b/website/data/api-docs-nav-data.json index 63109eb5e2c4..9f86aa6e9b07 100644 --- a/website/data/api-docs-nav-data.json +++ b/website/data/api-docs-nav-data.json @@ -131,6 +131,14 @@ "title": "Events", "path": "event" }, + { + "title": "Exported Services", + "path": "exported-services" + }, + { + "title": "HCP Consul Central Link", + "path": "hcp-link" + }, { "title": "Health", "path": "health" diff --git a/website/data/commands-nav-data.json b/website/data/commands-nav-data.json index bdeaebea3d00..2199c036dffc 100644 --- a/website/data/commands-nav-data.json +++ b/website/data/commands-nav-data.json @@ -472,6 +472,10 @@ "title": "establish", "path": "peering/establish" }, + { + "title": "exported-services", + "path": "peering/exported-services" + }, { "title": "generate-token", "path": "peering/generate-token" @@ -512,6 +516,10 @@ { "title": "export", "path": "services/export" + }, + { + "title": "exported-services", + "path": "services/exported-services" } ] }, @@ -526,6 +534,10 @@ "title": "agent", "path": "snapshot/agent" }, + { + "title": "decode", + "path": "snapshot/decode" + }, { "title": "inspect", "path": "snapshot/inspect" @@ -571,6 +583,10 @@ { "title": "proxy", "path": "troubleshoot/proxy" + }, + { + "title": "ports", + "path": "troubleshoot/ports" } ] }, diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 90b167036c68..25832322e897 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -49,7 +49,7 @@ "path": "install" }, { - "title": "Learn HCP Consul", + "title": "Learn HCP Consul Dedicated", "href": "https://developer.hashicorp.com/consul/tutorials/get-started-hcp" }, { @@ -102,6 +102,10 @@ "title": "Overview", "path": "architecture" }, + { + "title": "v1 Catalog", + "path": "architecture/catalog" + }, { "title": "Improving Consul Resilience", "path": "architecture/improving-consul-resilience" @@ -129,6 +133,10 @@ { "title": "Consul at Scale", "path": "architecture/scale" + }, + { + "title": "Consul Capacity Planning", + "path": "architecture/capacity-planning" } ] }, @@ -145,6 +153,18 @@ { "title": "Consul", "routes": [ + { + "title": "v1.20.x", + "path": "release-notes/consul/v1_20_x" + }, + { + "title": "v1.19.x", + "path": "release-notes/consul/v1_19_x" + }, + { + "title": "v1.18.x", + "path": "release-notes/consul/v1_18_x" + }, { "title": "v1.17.x", "path": "release-notes/consul/v1_17_x" @@ -186,6 +206,18 @@ { "title": "Consul K8s", "routes": [ + { + "title": "v1.6.x", + "path": "release-notes/consul-k8s/v1_6_x" + }, + { + "title": "v1.5.x", + "path": "release-notes/consul-k8s/v1_5_x" + }, + { + "title": "v1.4.x", + "path": "release-notes/consul-k8s/v1_4_x" + }, { "title": "v1.3.x", "path": "release-notes/consul-k8s/v1_3_x" @@ -365,10 +397,27 @@ "title": "Configure DNS behavior", "path": "services/discovery/dns-configuration" }, + { + "title": "DNS forwarding", + "routes": [ + { + "title": "Overview", + "path": "services/discovery/dns-forwarding" + }, + { + "title": "Enable DNS forwarding", + "path": "services/discovery/dns-forwarding/enable" + } + ] + }, { "title": "Perform static DNS lookups", "path": "services/discovery/dns-static-lookups" }, + { + "title": "Cache DNS lookups", + "path": "services/discovery/dns-cache" + }, { "title": "Enable dynamic DNS lookups", "path": "services/discovery/dns-dynamic-lookups" @@ -432,6 +481,10 @@ "title": "TCP route", "path": "connect/config-entries/tcp-route" }, + { + "title": "File system certificate", + "path": "connect/config-entries/file-system-certificate" + }, { "title": "Inline certificate", "path": "connect/config-entries/inline-certificate" @@ -456,6 +509,10 @@ "title": "Proxy defaults", "path": "connect/config-entries/proxy-defaults" }, + { + "title": "Registration", + "path": "connect/config-entries/registration" + }, { "title": "Sameness Group", "path": "connect/config-entries/sameness-group" @@ -626,6 +683,10 @@ "title": "Access Logs", "path": "connect/observability/access-logs" }, + { + "title": "Monitor service-to-service communication", + "path": "connect/observability/service" + }, { "title": "UI Visualization", "path": "connect/observability/ui-visualization" @@ -647,6 +708,10 @@ "title": "Limit request rates to services", "path": "connect/manage-traffic/limit-request-rates" }, + { + "title": "Fault Injection", + "path": "connect/manage-traffic/fault-injection" + }, { "title": "Failover", "routes": [ @@ -984,11 +1049,29 @@ "routes": [ { "title": "Consul KV", - "path": "dynamic-app-config/kv" + "routes": [ + { + "title": "Overview", + "path": "dynamic-app-config/kv" + }, + { + "title": "Store keys and values", + "path": "dynamic-app-config/kv/store" + } + ] }, { "title": "Sessions", - "path": "dynamic-app-config/sessions" + "routes": [ + { + "title": "Overview", + "path": "dynamic-app-config/sessions" + }, + { + "title": "Application leader election", + "path": "dynamic-app-config/sessions/application-leader-election" + } + ] }, { "title": "Watches", @@ -1003,6 +1086,23 @@ "title": "Overview", "path": "security" }, + { + "title": "Security Models", + "routes": [ + { + "title": "Overview", + "path": "security/security-models" + }, + { + "title": "Core", + "path": "security/security-models/core" + }, + { + "title": "Network Infrastructure Automation", + "path": "security/security-models/nia" + } + ] + }, { "title": "Access Control (ACLs)", "routes": [ @@ -1113,22 +1213,18 @@ }, { "title": "Encryption", - "path": "security/encryption" - }, - { - "title": "Security Models", "routes": [ { "title": "Overview", - "path": "security/security-models" + "path": "security/encryption" }, { - "title": "Core", - "path": "security/security-models/core" + "title": "Gossip encryption", + "path": "security/encryption/gossip" }, { - "title": "Network Infrastructure Automation", - "path": "security/security-models/nia" + "title": "mTLS", + "path": "security/encryption/mtls" } ] } @@ -1197,8 +1293,21 @@ "path": "agent/config-entries" }, { - "title": "Telemetry", - "path": "agent/telemetry" + "title": "Monitor Consul", + "routes": [ + { + "title": "Agent telemetry", + "path": "agent/monitor/telemetry" + }, + { + "title": "Monitor components", + "path": "agent/monitor/components" + }, + { + "title": "Recommendations", + "path": "agent/monitor/alerts" + } + ] }, { "title": "Sentinel", @@ -1315,6 +1424,10 @@ "title": "Consul Enterprise", "path": "k8s/deployment-configurations/consul-enterprise" }, + { + "title": "Argo Rollouts Progressive Delivery", + "path": "k8s/deployment-configurations/argo-rollouts-configuration" + }, { "title": "Multi-Cluster Federation", "routes": [ @@ -1393,6 +1506,14 @@ "path": "k8s/deployment-configurations/vault/wan-federation" } ] + }, + { + "title": "Datadog metrics", + "path": "k8s/deployment-configurations/datadog" + }, + { + "title": "Register external services", + "path": "k8s/deployment-configurations/external-service" } ] }, @@ -1522,25 +1643,12 @@ } ] }, - { - "title": "Multi-port services", - "routes": [ - { - "title": "Overview", - "path": "k8s/multiport" - }, - { - "title": "Configure multi-port services", - "path": "k8s/multiport/configure" - } - ] - }, { "title": "L7 traffic management", "routes": [ { "title": "Overview", - "href": "/docs/connect/l7-traffic" + "href": "/docs/connect/manage-traffic" }, { "title": "Configure failover services", @@ -1575,7 +1683,25 @@ }, { "title": "Consul DNS", - "path": "k8s/dns" + "routes": [ + { + "title": "DNS proxy for service discovery", + "routes": [ + { + "title": "Overview", + "path": "k8s/dns/views" + }, + { + "title": "Enable Consul DNS proxy", + "path": "k8s/dns/views/enable" + } + ] + }, + { + "title": "Enable on dataplanes", + "path": "k8s/dns/enable" + } + ] }, { "title": "Upgrade", @@ -1651,6 +1777,10 @@ } ] }, + { + "title": "Nomad", + "path": "nomad" + }, { "title": "AWS ECS", "routes": [ @@ -1761,7 +1891,7 @@ "divider": true }, { - "title": "HCP Consul", + "title": "HCP Consul Dedicated", "href": "https://cloud.hashicorp.com/docs/consul" }, { @@ -1771,6 +1901,10 @@ "title": "Overview", "path": "enterprise" }, + { + "title": "Long Term Support (LTS)", + "path": "enterprise/long-term-support" + }, { "title": "Admin Partitions", "path": "enterprise/admin-partitions" @@ -1791,6 +1925,10 @@ "title": "Enhanced Read Scalability", "path": "enterprise/read-scale" }, + { + "title": "Fault injection", + "href": "/docs/connect/manage-traffic/fault-injection" + }, { "title": "FIPS", "path": "enterprise/fips" @@ -1844,6 +1982,10 @@ "path": "enterprise/license/faq" } ] + }, + { + "title": "Enterprise to CE downgrade", + "path": "enterprise/ent-to-ce-downgrades" } ] }, @@ -1957,7 +2099,7 @@ "path": "nia/enterprise/license" }, { - "title": "Terraform Cloud Driver", + "title": "HCP Terraform Driver", "href": "/docs/nia/network-drivers/terraform-cloud" } ] @@ -1974,8 +2116,8 @@ "path": "nia/network-drivers/terraform" }, { - "title": "Terraform Cloud", - "path": "nia/network-drivers/terraform-cloud" + "title": "HCP Terraform", + "path": "nia/network-drivers/hcp-terraform" } ] }, diff --git a/website/package-lock.json b/website/package-lock.json index dceec6c8eddb..5ce68d61c763 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -8,15 +8,15 @@ "name": "consul-docs", "version": "0.0.1", "devDependencies": { - "@hashicorp/platform-cli": "^2.6.0", - "@hashicorp/platform-content-conformance": "^0.0.10", - "dart-linkcheck": "2.0.15", - "husky": "4.3.8", + "@hashicorp/platform-cli": "^2.7.3", + "@hashicorp/platform-content-conformance": "^0.0.12", + "dart-linkcheck": "^2.0.15", + "husky": "^9.0.7", "next": "^12.3.1", - "prettier": "2.2.1" + "prettier": "^3.2.4" }, "engines": { - "npm": ">=7.0.0" + "npm": ">=9.6.7" } }, "node_modules/@babel/code-frame": { @@ -629,18 +629,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "dev": true, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, "node_modules/@hashicorp/platform-cli": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@hashicorp/platform-cli/-/platform-cli-2.6.0.tgz", - "integrity": "sha512-nMO7Uiy/A5CT/BCE9RyQt6/Uci7bxwTesxCNWkXlciyqlIrz9WmBa9hr710IiMoDzrzQ1tL6AgFIeTbXs4RTqA==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@hashicorp/platform-cli/-/platform-cli-2.7.3.tgz", + "integrity": "sha512-8vmKiF67gxGQFj8GkNcm8udNYwm/Ao3mLpmUD0vDTN/SA6jdONyXt43/O3H7FvEkVfaUT5K0huljp4b5hY+LYQ==", "dev": true, "dependencies": { - "@hashicorp/platform-cms": "0.3.0", + "@hashicorp/platform-cms": "0.4.0", "@typescript-eslint/eslint-plugin": "^5.48.0", "@typescript-eslint/parser": "^5.48.0", "chalk": "4.1.0", "commander": "7.2.0", - "ejs": "3.1.5", + "ejs": "^3.1.9", "eslint": "^8.31.0", "eslint-config-next": "^13.1.1", "eslint-config-prettier": "^8.6.0", @@ -651,7 +660,7 @@ "inquirer": "7.3.3", "lint-staged": "11.1.2", "open": "7.3.0", - "prettier": "2.5.1", + "prettier": "^2.8.7", "readdirp": "3.5.0", "signale": "1.4.0", "slugify": "1.4.6", @@ -691,30 +700,33 @@ } }, "node_modules/@hashicorp/platform-cli/node_modules/prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/@hashicorp/platform-cms": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@hashicorp/platform-cms/-/platform-cms-0.3.0.tgz", - "integrity": "sha512-sRX9A+kDEZvfZy8PvGFbEaHjn5G1mEsHwTri1vDnrmKG8apE+ELlug83b0iEkD5wIJi9OqaewMIb0NrLxg9s5A==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@hashicorp/platform-cms/-/platform-cms-0.4.0.tgz", + "integrity": "sha512-Q8fixx7JnzzDvuMEC1+UK8xO4bqMh/QxNX7lPusfMixVhnnyJaTF7xRhDRFWMG1bhUwI9TJxQYElWC2aDj7CmA==", "dev": true, "dependencies": { - "rivet-graphql": "0.3.1" + "rivet-graphql": "^0.6.0-canary-20230309231927" } }, "node_modules/@hashicorp/platform-content-conformance": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@hashicorp/platform-content-conformance/-/platform-content-conformance-0.0.10.tgz", - "integrity": "sha512-vXLbd2w9phS4JfFyh17jCiyu+LXVonTfb7WEUK2eMlOL/wxe2umyJvEQaJNzD5bwyYC8LuXGA5JkbnPXnU5ZQg==", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@hashicorp/platform-content-conformance/-/platform-content-conformance-0.0.12.tgz", + "integrity": "sha512-Va6XTh7cH1M11yqgi4GsLPZZx1NgXQjKvCzadynJyJJhpXe++oQDS5ItDm8ABxeM/EuKU4dOfA7PMUkLzAtAWQ==", "dev": true, "dependencies": { "find-up": "^6.3.0", @@ -731,7 +743,7 @@ "vfile-reporter": "^7.0.4", "vfile-reporter-json": "^3.2.0", "vfile-statistics": "^2.0.0", - "yaml": "^2.1.3", + "yaml": "^2.2.2", "yargs": "^17.4.1", "zod": "^3.19.1" }, @@ -989,9 +1001,9 @@ } }, "node_modules/@hashicorp/platform-content-conformance/node_modules/yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "dev": true, "engines": { "node": ">= 14" @@ -2604,9 +2616,9 @@ } }, "node_modules/async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, "node_modules/asynckit": { @@ -3529,12 +3541,6 @@ "node": ">= 10" } }, - "node_modules/compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "dev": true - }, "node_modules/component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -3584,12 +3590,12 @@ } }, "node_modules/cross-fetch": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", - "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", "dev": true, "dependencies": { - "node-fetch": "2.6.1" + "node-fetch": "^2.6.12" } }, "node_modules/cross-spawn": { @@ -3998,12 +4004,12 @@ "dev": true }, "node_modules/ejs": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz", - "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", "dev": true, "dependencies": { - "jake": "^10.6.1" + "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" @@ -5360,12 +5366,33 @@ } }, "node_modules/filelist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", - "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dev": true, "dependencies": { - "minimatch": "^3.0.4" + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, "node_modules/fill-range": { @@ -5396,21 +5423,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-versions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", - "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", - "dev": true, - "dependencies": { - "semver-regex": "^3.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -5837,26 +5849,27 @@ "dev": true }, "node_modules/graphql": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.6.0.tgz", - "integrity": "sha512-WJR872Zlc9hckiEPhXgyUftXH48jp2EjO5tgBBOyNMRJZ9fviL2mJBD6CAysk6N5S0r9BTs09Qk39nnJBkvOXQ==", + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", "dev": true, "engines": { - "node": ">= 10.x" + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, "node_modules/graphql-request": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-3.5.0.tgz", - "integrity": "sha512-Io89QpfU4rqiMbqM/KwMBzKaDLOppi8FU8sEccCE4JqCgz95W9Q8bvxQ4NfPALLSMvg9nafgg8AkYRmgKSlukA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-5.1.0.tgz", + "integrity": "sha512-0OeRVYigVwIiXhNmqnPDt+JhMzsjinxHE7TVy3Lm6jUzav0guVcL0lfSbi6jVTRAxcbwgyr6yrZioSHxf9gHzw==", "dev": true, "dependencies": { - "cross-fetch": "^3.0.6", + "@graphql-typed-document-node/core": "^3.1.1", + "cross-fetch": "^3.1.5", "extract-files": "^9.0.0", "form-data": "^3.0.0" }, "peerDependencies": { - "graphql": "14.x || 15.x" + "graphql": "14 - 16" } }, "node_modules/growly": { @@ -6127,33 +6140,18 @@ } }, "node_modules/husky": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz", - "integrity": "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==", + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.7.tgz", + "integrity": "sha512-vWdusw+y12DUEeoZqW1kplOFqk3tedGV8qlga8/SF6a3lOiWLqGZZQvfWvY0fQYdfiRi/u1DFNpudTSV9l1aCg==", "dev": true, - "hasInstallScript": true, - "dependencies": { - "chalk": "^4.0.0", - "ci-info": "^2.0.0", - "compare-versions": "^3.6.0", - "cosmiconfig": "^7.0.0", - "find-versions": "^4.0.0", - "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^5.0.0", - "please-upgrade-node": "^3.2.0", - "slash": "^3.0.0", - "which-pm-runs": "^1.0.0" - }, "bin": { - "husky-run": "bin/run.js", - "husky-upgrade": "lib/upgrader/bin.js" + "husky": "bin.js" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/husky" + "url": "https://github.com/sponsors/typicode" } }, "node_modules/iconv-lite": { @@ -7127,83 +7125,21 @@ } }, "node_modules/jake": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", - "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", "dev": true, "dependencies": { - "async": "0.9.x", - "chalk": "^2.4.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" }, "bin": { "jake": "bin/cli.js" }, "engines": { - "node": "*" - } - }, - "node_modules/jake/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jake/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jake/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/jake/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/jake/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/jake/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" + "node": ">=10" } }, "node_modules/jest": { @@ -8885,12 +8821,23 @@ "peer": true }, "node_modules/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, "engines": { "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/node-int64": { @@ -9284,15 +9231,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/opencollective-postinstall": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", - "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", - "dev": true, - "bin": { - "opencollective-postinstall": "index.js" - } - }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -9611,18 +9549,6 @@ "node": ">=4" } }, - "node_modules/pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "dependencies": { - "find-up": "^5.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/please-upgrade-node": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", @@ -10409,15 +10335,18 @@ } }, "node_modules/prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", "dev": true, "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/prettier-linter-helpers": { @@ -11034,13 +10963,14 @@ } }, "node_modules/rivet-graphql": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/rivet-graphql/-/rivet-graphql-0.3.1.tgz", - "integrity": "sha512-HEov02XhZ6H1jOME+mO8CZwliu/UtgZSHixYUwvQ7HSx3gk8EOVaQY5c3zscOYjZECvP8cR4+1Ob3KHWJRWEMw==", + "version": "0.6.0-canary-20230309231927", + "resolved": "https://registry.npmjs.org/rivet-graphql/-/rivet-graphql-0.6.0-canary-20230309231927.tgz", + "integrity": "sha512-6+HlBIKGty0+XULdpQaXwFpXgItmNUOCSZ8a6Eit/kJzXPp7YVyBMvCN9ozaRVqHUK8PiToGB+jg+jo8/V+bgw==", "dev": true, "dependencies": { - "graphql": "^15.3.0", - "graphql-request": "^3.0.0" + "@graphql-typed-document-node/core": "^3.1.2", + "graphql": "^16.6.0", + "graphql-request": "~5.1.0" } }, "node_modules/rsvp": { @@ -11490,18 +11420,6 @@ "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", "dev": true }, - "node_modules/semver-regex": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.2.tgz", - "integrity": "sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -13242,6 +13160,12 @@ "node": ">= 4.0.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, "node_modules/trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", @@ -14320,6 +14244,12 @@ "makeerror": "1.0.12" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, "node_modules/whatwg-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", @@ -14337,6 +14267,16 @@ "dev": true, "peer": true }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -14390,12 +14330,6 @@ "dev": true, "peer": true }, - "node_modules/which-pm-runs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", - "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", - "dev": true - }, "node_modules/which-typed-array": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", @@ -15148,18 +15082,25 @@ } } }, + "@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "dev": true, + "requires": {} + }, "@hashicorp/platform-cli": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@hashicorp/platform-cli/-/platform-cli-2.6.0.tgz", - "integrity": "sha512-nMO7Uiy/A5CT/BCE9RyQt6/Uci7bxwTesxCNWkXlciyqlIrz9WmBa9hr710IiMoDzrzQ1tL6AgFIeTbXs4RTqA==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@hashicorp/platform-cli/-/platform-cli-2.7.3.tgz", + "integrity": "sha512-8vmKiF67gxGQFj8GkNcm8udNYwm/Ao3mLpmUD0vDTN/SA6jdONyXt43/O3H7FvEkVfaUT5K0huljp4b5hY+LYQ==", "dev": true, "requires": { - "@hashicorp/platform-cms": "0.3.0", + "@hashicorp/platform-cms": "0.4.0", "@typescript-eslint/eslint-plugin": "^5.48.0", "@typescript-eslint/parser": "^5.48.0", "chalk": "4.1.0", "commander": "7.2.0", - "ejs": "3.1.5", + "ejs": "^3.1.9", "eslint": "^8.31.0", "eslint-config-next": "^13.1.1", "eslint-config-prettier": "^8.6.0", @@ -15170,7 +15111,7 @@ "inquirer": "7.3.3", "lint-staged": "11.1.2", "open": "7.3.0", - "prettier": "2.5.1", + "prettier": "^2.8.7", "readdirp": "3.5.0", "signale": "1.4.0", "slugify": "1.4.6", @@ -15195,26 +15136,26 @@ } }, "prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true } } }, "@hashicorp/platform-cms": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@hashicorp/platform-cms/-/platform-cms-0.3.0.tgz", - "integrity": "sha512-sRX9A+kDEZvfZy8PvGFbEaHjn5G1mEsHwTri1vDnrmKG8apE+ELlug83b0iEkD5wIJi9OqaewMIb0NrLxg9s5A==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@hashicorp/platform-cms/-/platform-cms-0.4.0.tgz", + "integrity": "sha512-Q8fixx7JnzzDvuMEC1+UK8xO4bqMh/QxNX7lPusfMixVhnnyJaTF7xRhDRFWMG1bhUwI9TJxQYElWC2aDj7CmA==", "dev": true, "requires": { - "rivet-graphql": "0.3.1" + "rivet-graphql": "^0.6.0-canary-20230309231927" } }, "@hashicorp/platform-content-conformance": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@hashicorp/platform-content-conformance/-/platform-content-conformance-0.0.10.tgz", - "integrity": "sha512-vXLbd2w9phS4JfFyh17jCiyu+LXVonTfb7WEUK2eMlOL/wxe2umyJvEQaJNzD5bwyYC8LuXGA5JkbnPXnU5ZQg==", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@hashicorp/platform-content-conformance/-/platform-content-conformance-0.0.12.tgz", + "integrity": "sha512-Va6XTh7cH1M11yqgi4GsLPZZx1NgXQjKvCzadynJyJJhpXe++oQDS5ItDm8ABxeM/EuKU4dOfA7PMUkLzAtAWQ==", "dev": true, "requires": { "find-up": "^6.3.0", @@ -15231,7 +15172,7 @@ "vfile-reporter": "^7.0.4", "vfile-reporter-json": "^3.2.0", "vfile-statistics": "^2.0.0", - "yaml": "^2.1.3", + "yaml": "^2.2.2", "yargs": "^17.4.1", "zod": "^3.19.1" }, @@ -15413,9 +15354,9 @@ "dev": true }, "yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "dev": true }, "yargs": { @@ -16594,9 +16535,9 @@ "dev": true }, "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, "asynckit": { @@ -17306,12 +17247,6 @@ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true }, - "compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "dev": true - }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -17355,12 +17290,12 @@ } }, "cross-fetch": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", - "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", "dev": true, "requires": { - "node-fetch": "2.6.1" + "node-fetch": "^2.6.12" } }, "cross-spawn": { @@ -17687,12 +17622,12 @@ "dev": true }, "ejs": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz", - "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", "dev": true, "requires": { - "jake": "^10.6.1" + "jake": "^10.8.5" } }, "electron-to-chromium": { @@ -18751,12 +18686,32 @@ } }, "filelist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", - "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dev": true, "requires": { - "minimatch": "^3.0.4" + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "fill-range": { @@ -18778,15 +18733,6 @@ "path-exists": "^4.0.0" } }, - "find-versions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", - "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", - "dev": true, - "requires": { - "semver-regex": "^3.1.2" - } - }, "flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -19103,18 +19049,19 @@ "dev": true }, "graphql": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.6.0.tgz", - "integrity": "sha512-WJR872Zlc9hckiEPhXgyUftXH48jp2EjO5tgBBOyNMRJZ9fviL2mJBD6CAysk6N5S0r9BTs09Qk39nnJBkvOXQ==", + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", "dev": true }, "graphql-request": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-3.5.0.tgz", - "integrity": "sha512-Io89QpfU4rqiMbqM/KwMBzKaDLOppi8FU8sEccCE4JqCgz95W9Q8bvxQ4NfPALLSMvg9nafgg8AkYRmgKSlukA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-5.1.0.tgz", + "integrity": "sha512-0OeRVYigVwIiXhNmqnPDt+JhMzsjinxHE7TVy3Lm6jUzav0guVcL0lfSbi6jVTRAxcbwgyr6yrZioSHxf9gHzw==", "dev": true, "requires": { - "cross-fetch": "^3.0.6", + "@graphql-typed-document-node/core": "^3.1.1", + "cross-fetch": "^3.1.5", "extract-files": "^9.0.0", "form-data": "^3.0.0" } @@ -19325,22 +19272,10 @@ "peer": true }, "husky": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz", - "integrity": "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "ci-info": "^2.0.0", - "compare-versions": "^3.6.0", - "cosmiconfig": "^7.0.0", - "find-versions": "^4.0.0", - "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^5.0.0", - "please-upgrade-node": "^3.2.0", - "slash": "^3.0.0", - "which-pm-runs": "^1.0.0" - } + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.7.tgz", + "integrity": "sha512-vWdusw+y12DUEeoZqW1kplOFqk3tedGV8qlga8/SF6a3lOiWLqGZZQvfWvY0fQYdfiRi/u1DFNpudTSV9l1aCg==", + "dev": true }, "iconv-lite": { "version": "0.4.24", @@ -20025,67 +19960,15 @@ } }, "jake": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", - "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", "dev": true, "requires": { - "async": "0.9.x", - "chalk": "^2.4.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" } }, "jest": { @@ -21369,10 +21252,13 @@ "peer": true }, "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "dev": true + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } }, "node-int64": { "version": "0.4.0", @@ -21678,12 +21564,6 @@ "is-wsl": "^2.1.1" } }, - "opencollective-postinstall": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", - "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", - "dev": true - }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -21910,15 +21790,6 @@ } } }, - "pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "requires": { - "find-up": "^5.0.0" - } - }, "please-upgrade-node": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", @@ -22538,9 +22409,9 @@ "dev": true }, "prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", "dev": true }, "prettier-linter-helpers": { @@ -23014,13 +22885,14 @@ } }, "rivet-graphql": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/rivet-graphql/-/rivet-graphql-0.3.1.tgz", - "integrity": "sha512-HEov02XhZ6H1jOME+mO8CZwliu/UtgZSHixYUwvQ7HSx3gk8EOVaQY5c3zscOYjZECvP8cR4+1Ob3KHWJRWEMw==", + "version": "0.6.0-canary-20230309231927", + "resolved": "https://registry.npmjs.org/rivet-graphql/-/rivet-graphql-0.6.0-canary-20230309231927.tgz", + "integrity": "sha512-6+HlBIKGty0+XULdpQaXwFpXgItmNUOCSZ8a6Eit/kJzXPp7YVyBMvCN9ozaRVqHUK8PiToGB+jg+jo8/V+bgw==", "dev": true, "requires": { - "graphql": "^15.3.0", - "graphql-request": "^3.0.0" + "@graphql-typed-document-node/core": "^3.1.2", + "graphql": "^16.6.0", + "graphql-request": "~5.1.0" } }, "rsvp": { @@ -23379,12 +23251,6 @@ "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", "dev": true }, - "semver-regex": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.2.tgz", - "integrity": "sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA==", - "dev": true - }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -24771,6 +24637,12 @@ } } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", @@ -25585,6 +25457,12 @@ "makeerror": "1.0.12" } }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, "whatwg-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", @@ -25602,6 +25480,16 @@ "dev": true, "peer": true }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -25643,12 +25531,6 @@ "dev": true, "peer": true }, - "which-pm-runs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", - "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", - "dev": true - }, "which-typed-array": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", diff --git a/website/package.json b/website/package.json index caacb3c5976c..125e74228c14 100644 --- a/website/package.json +++ b/website/package.json @@ -4,22 +4,18 @@ "version": "0.0.1", "author": "HashiCorp", "devDependencies": { - "@hashicorp/platform-cli": "^2.6.0", - "@hashicorp/platform-content-conformance": "^0.0.10", - "dart-linkcheck": "2.0.15", - "husky": "4.3.8", + "@hashicorp/platform-cli": "^2.7.3", + "@hashicorp/platform-content-conformance": "^0.0.12", + "dart-linkcheck": "^2.0.15", + "husky": "^9.0.7", "next": "^12.3.1", - "prettier": "2.2.1" - }, - "husky": { - "hooks": { - "pre-commit": "next-hashicorp precommit" - } + "prettier": "^3.2.4" }, "main": "index.js", "scripts": { "build": "./scripts/website-build.sh", "format": "next-hashicorp format", + "prepare": "cd .. && husky website/.husky", "generate:component": "next-hashicorp generate component", "generate:readme": "next-hashicorp markdown-blocks README.md", "lint": "next-hashicorp lint", @@ -28,6 +24,6 @@ "content-check": "hc-content --config base-docs" }, "engines": { - "npm": ">=7.0.0" + "npm": ">=9.6.7" } } diff --git a/website/public/img/architecture/cluster-peering-diagram-dark.png b/website/public/img/architecture/cluster-peering-diagram-dark.png new file mode 100644 index 000000000000..2c414a7e3944 Binary files /dev/null and b/website/public/img/architecture/cluster-peering-diagram-dark.png differ diff --git a/website/public/img/architecture/cluster-peering-diagram-light.png b/website/public/img/architecture/cluster-peering-diagram-light.png new file mode 100644 index 000000000000..3d0a5959e8b0 Binary files /dev/null and b/website/public/img/architecture/cluster-peering-diagram-light.png differ diff --git a/website/public/img/architecture/cluster-peering-diagram.png b/website/public/img/architecture/cluster-peering-diagram.png new file mode 100644 index 000000000000..66a81dfc21bd Binary files /dev/null and b/website/public/img/architecture/cluster-peering-diagram.png differ diff --git a/website/public/img/architecture/consul-redundancy-zones-dark.png b/website/public/img/architecture/consul-redundancy-zones-dark.png new file mode 100644 index 000000000000..c7c5ba065b20 Binary files /dev/null and b/website/public/img/architecture/consul-redundancy-zones-dark.png differ diff --git a/website/public/img/architecture/consul-redundancy-zones-light.png b/website/public/img/architecture/consul-redundancy-zones-light.png new file mode 100644 index 000000000000..d374f1bb7d93 Binary files /dev/null and b/website/public/img/architecture/consul-redundancy-zones-light.png differ diff --git a/website/public/img/architecture/consul-singleDC-redundancyzones.png b/website/public/img/architecture/consul-singleDC-redundancyzones.png new file mode 100644 index 000000000000..e57955280f00 Binary files /dev/null and b/website/public/img/architecture/consul-singleDC-redundancyzones.png differ diff --git a/website/public/img/consul-dns-conditional-forwarding-dark.png b/website/public/img/consul-dns-conditional-forwarding-dark.png new file mode 100644 index 000000000000..b54ed817eb6c Binary files /dev/null and b/website/public/img/consul-dns-conditional-forwarding-dark.png differ diff --git a/website/public/img/consul-dns-conditional-forwarding.png b/website/public/img/consul-dns-conditional-forwarding.png new file mode 100644 index 000000000000..82ea08a11b2a Binary files /dev/null and b/website/public/img/consul-dns-conditional-forwarding.png differ diff --git a/website/public/img/consul-dns-forwarding-dark.png b/website/public/img/consul-dns-forwarding-dark.png new file mode 100644 index 000000000000..9ff518397b81 Binary files /dev/null and b/website/public/img/consul-dns-forwarding-dark.png differ diff --git a/website/public/img/consul-dns-forwarding.png b/website/public/img/consul-dns-forwarding.png new file mode 100644 index 000000000000..bffce6e333a9 Binary files /dev/null and b/website/public/img/consul-dns-forwarding.png differ diff --git a/website/public/img/ecs/consul-on-ecs-architecture-dataplanes-dark.jpg b/website/public/img/ecs/consul-on-ecs-architecture-dataplanes-dark.jpg deleted file mode 100644 index fc88e95145b5..000000000000 Binary files a/website/public/img/ecs/consul-on-ecs-architecture-dataplanes-dark.jpg and /dev/null differ diff --git a/website/public/img/ecs/consul-on-ecs-architecture-dataplanes-dark.png b/website/public/img/ecs/consul-on-ecs-architecture-dataplanes-dark.png new file mode 100644 index 000000000000..5c01933d16e9 Binary files /dev/null and b/website/public/img/ecs/consul-on-ecs-architecture-dataplanes-dark.png differ diff --git a/website/public/img/ecs/consul-on-ecs-architecture-dataplanes.jpg b/website/public/img/ecs/consul-on-ecs-architecture-dataplanes.jpg deleted file mode 100644 index 85b9eb7fb4fd..000000000000 Binary files a/website/public/img/ecs/consul-on-ecs-architecture-dataplanes.jpg and /dev/null differ diff --git a/website/public/img/ecs/consul-on-ecs-architecture-dataplanes.png b/website/public/img/ecs/consul-on-ecs-architecture-dataplanes.png new file mode 100644 index 000000000000..11c686015eb3 Binary files /dev/null and b/website/public/img/ecs/consul-on-ecs-architecture-dataplanes.png differ diff --git a/website/public/img/long-term-support/consul-enterprise-long-term-support-lifecycle-dark.png b/website/public/img/long-term-support/consul-enterprise-long-term-support-lifecycle-dark.png new file mode 100644 index 000000000000..e77b1e8a7ddf Binary files /dev/null and b/website/public/img/long-term-support/consul-enterprise-long-term-support-lifecycle-dark.png differ diff --git a/website/public/img/long-term-support/consul-enterprise-long-term-support-lifecycle-dark.svg b/website/public/img/long-term-support/consul-enterprise-long-term-support-lifecycle-dark.svg new file mode 100644 index 000000000000..d13b441bf798 --- /dev/null +++ b/website/public/img/long-term-support/consul-enterprise-long-term-support-lifecycle-dark.svg @@ -0,0 +1,735 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2023 + + + + MAR + JULY + NOV + + 2027 + + + + MAR + JULY + NOV + + 2024 + + + + MAR + JULY + NOV + + 2025 + + + + MAR + JULY + NOV + + 2026 + + + + MAR + JULY + NOV + + + + 1.15 + + + + 1.16 + + Enterprise Release Type + Standard + + Long TermSupport (LTS) + + + + 1.17 + + + + 1.18 + + + + 1.19 + + + + 1.20 + + + + 1.21 + + + + 1.22 + + + + 1.23 + + + + 1.24 + + + + + New Direct Upgrade Path + Current LTS + Next LTS + + to + + diff --git a/website/public/img/long-term-support/consul-enterprise-long-term-support-lifecycle.png b/website/public/img/long-term-support/consul-enterprise-long-term-support-lifecycle.png new file mode 100644 index 000000000000..fa383e21d21b Binary files /dev/null and b/website/public/img/long-term-support/consul-enterprise-long-term-support-lifecycle.png differ diff --git a/website/public/img/long-term-support/consul-enterprise-long-term-support-lifecycle.svg b/website/public/img/long-term-support/consul-enterprise-long-term-support-lifecycle.svg new file mode 100644 index 000000000000..0ab8b1884b44 --- /dev/null +++ b/website/public/img/long-term-support/consul-enterprise-long-term-support-lifecycle.svg @@ -0,0 +1,752 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2023 + + + + MAR + JULY + NOV + + 2027 + + + + MAR + JULY + NOV + + 2024 + + + + MAR + JULY + NOV + + 2025 + + + + MAR + JULY + NOV + + 2026 + + + + MAR + JULY + NOV + + + + 1.15 + + + + 1.16 + + + Enterprise Release Type + + Standard + + + + Long TermSupport (LTS) + + + + + + 1.17 + + + + 1.18 + + + + 1.19 + + + + 1.20 + + + + 1.21 + + + + 1.22 + + + + 1.23 + + + + 1.24 + + + + + + New Direct Upgrade Path + + Current LTS + Next LTS + + to + + + + diff --git a/website/redirects.js b/website/redirects.js index c75481acc130..826ef82fe3b2 100644 --- a/website/redirects.js +++ b/website/redirects.js @@ -212,4 +212,52 @@ module.exports = [ destination: '/consul/docs/v1.8.x/agent/config-entries/:slug', permanent: true, }, + { + source: '/consul/docs/architecture/catalog/v1/:slug', + destination: '/consul/docs/architecture/catalog/:slug', + permanent: true, + }, + { + source: + '/consul/docs/:version(v1.(?:8|9|10|11|12|13|14|15|16|17).x)/architecture/catalog/:slug*', + destination: '/consul/docs/:version/architecture/catalog/v1/:slug', + permanent: true, + }, + { + source: '/consul/docs/nia/network-drivers/terraform-cloud', + destination: '/consul/docs/nia/network-drivers/hcp-terraform', + permanent: true, + }, + { + source: + '/consul/docs/:version(v1.(?:8|9|10|11|12|13|14|15|16|17).x)/nia/network-drivers/hcp-terraform', + destination: '/consul/docs/:version/nia/network-drivers/terraform-cloud', + permanent: true, + }, + { + source: '/consul/docs/k8s/multiport/:slug', + destination: '/consul/docs/architecture/catalog#v2-catalog', + permanent: true, + }, + { + source: '/consul/docs/architecture/v2/:slug*', + destination: '/consul/docs/architecture/catalog#v2-catalog', + permanent: true, + }, + { + source: '/consul/commands/resource/:slug', + destination: '/consul/docs/architecture/catalog#v2-catalog', + permanent: true, + }, + { + source: '/consul/docs/k8s/dns', + destination: '/consul/docs/k8s/dns/enable', + permanent: true, + }, + { + source: + '/consul/docs/:version(v1.(?:11|12|13|14|15|16|17|18).x)/k8s/dns/enable', + destination: '/consul/docs/:version/k8s/dns', + permanent: true, + }, ]